1
from __future__ import annotations
4
from pathlib import Path
6
from PIL import Image, ImageWin
8
from .helper import hopper, is_win32
14
import ctypes.wintypes
16
class BITMAPFILEHEADER(ctypes.Structure):
19
("bfType", ctypes.wintypes.WORD),
20
("bfSize", ctypes.wintypes.DWORD),
21
("bfReserved1", ctypes.wintypes.WORD),
22
("bfReserved2", ctypes.wintypes.WORD),
23
("bfOffBits", ctypes.wintypes.DWORD),
26
class BITMAPINFOHEADER(ctypes.Structure):
29
("biSize", ctypes.wintypes.DWORD),
30
("biWidth", ctypes.wintypes.LONG),
31
("biHeight", ctypes.wintypes.LONG),
32
("biPlanes", ctypes.wintypes.WORD),
33
("biBitCount", ctypes.wintypes.WORD),
34
("biCompression", ctypes.wintypes.DWORD),
35
("biSizeImage", ctypes.wintypes.DWORD),
36
("biXPelsPerMeter", ctypes.wintypes.LONG),
37
("biYPelsPerMeter", ctypes.wintypes.LONG),
38
("biClrUsed", ctypes.wintypes.DWORD),
39
("biClrImportant", ctypes.wintypes.DWORD),
45
memcpy = ctypes.cdll.msvcrt.memcpy
46
memcpy.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t]
48
windll = getattr(ctypes, "windll")
49
CreateCompatibleDC = windll.gdi32.CreateCompatibleDC
50
CreateCompatibleDC.argtypes = [ctypes.wintypes.HDC]
51
CreateCompatibleDC.restype = ctypes.wintypes.HDC
53
DeleteDC = windll.gdi32.DeleteDC
54
DeleteDC.argtypes = [ctypes.wintypes.HDC]
56
SelectObject = windll.gdi32.SelectObject
57
SelectObject.argtypes = [ctypes.wintypes.HDC, ctypes.wintypes.HGDIOBJ]
58
SelectObject.restype = ctypes.wintypes.HGDIOBJ
60
DeleteObject = windll.gdi32.DeleteObject
61
DeleteObject.argtypes = [ctypes.wintypes.HGDIOBJ]
63
CreateDIBSection = windll.gdi32.CreateDIBSection
64
CreateDIBSection.argtypes = [
68
ctypes.POINTER(ctypes.c_void_p),
69
ctypes.wintypes.HANDLE,
70
ctypes.wintypes.DWORD,
72
CreateDIBSection.restype = ctypes.wintypes.HBITMAP
74
def serialize_dib(bi: BITMAPINFOHEADER, pixels: ctypes.c_void_p) -> bytearray:
75
bf = BITMAPFILEHEADER()
77
bf.bfOffBits = ctypes.sizeof(bf) + bi.biSize
78
bf.bfSize = bf.bfOffBits + bi.biSizeImage
79
bf.bfReserved1 = bf.bfReserved2 = 0
81
buf = (ctypes.c_byte * bf.bfSize)()
82
bp = ctypes.addressof(buf)
83
memcpy(bp, ctypes.byref(bf), ctypes.sizeof(bf))
84
memcpy(bp + ctypes.sizeof(bf), ctypes.byref(bi), bi.biSize)
85
memcpy(bp + bf.bfOffBits, pixels, bi.biSizeImage)
88
def test_pointer(tmp_path: Path) -> None:
90
(width, height) = im.size
91
opath = str(tmp_path / "temp.png")
92
imdib = ImageWin.Dib(im)
94
hdr = BITMAPINFOHEADER()
95
hdr.biSize = ctypes.sizeof(hdr)
100
hdr.biCompression = BI_RGB
101
hdr.biSizeImage = width * height * 4
103
hdr.biClrImportant = 0
105
hdc = CreateCompatibleDC(None)
106
pixels = ctypes.c_void_p()
107
dib = CreateDIBSection(
108
hdc, ctypes.byref(hdr), DIB_RGB_COLORS, ctypes.byref(pixels), None, 0
110
SelectObject(hdc, dib)
113
bitmap = serialize_dib(hdr, pixels)
117
with Image.open(BytesIO(bitmap)) as im: