Pillow/Tests/test_imagewin_pointers.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

118 lines
3.7 KiB
Python
Raw Normal View History

from __future__ import annotations
2024-01-20 14:23:03 +03:00
2015-10-01 16:06:21 +03:00
from io import BytesIO
from pathlib import Path
2015-10-01 16:06:21 +03:00
from PIL import Image, ImageWin
2020-01-27 14:46:52 +03:00
from .helper import hopper, is_win32
2015-10-01 16:06:21 +03:00
# see https://github.com/python-pillow/Pillow/pull/1431#issuecomment-144692652
2019-09-25 12:46:54 +03:00
if is_win32():
import ctypes
import ctypes.wintypes
2015-12-10 01:35:35 +03:00
class BITMAPFILEHEADER(ctypes.Structure):
_pack_ = 2
_fields_ = [
2019-06-13 18:54:46 +03:00
("bfType", ctypes.wintypes.WORD),
("bfSize", ctypes.wintypes.DWORD),
("bfReserved1", ctypes.wintypes.WORD),
("bfReserved2", ctypes.wintypes.WORD),
("bfOffBits", ctypes.wintypes.DWORD),
]
class BITMAPINFOHEADER(ctypes.Structure):
_pack_ = 2
_fields_ = [
2019-06-13 18:54:46 +03:00
("biSize", ctypes.wintypes.DWORD),
("biWidth", ctypes.wintypes.LONG),
("biHeight", ctypes.wintypes.LONG),
("biPlanes", ctypes.wintypes.WORD),
("biBitCount", ctypes.wintypes.WORD),
("biCompression", ctypes.wintypes.DWORD),
("biSizeImage", ctypes.wintypes.DWORD),
("biXPelsPerMeter", ctypes.wintypes.LONG),
("biYPelsPerMeter", ctypes.wintypes.LONG),
("biClrUsed", ctypes.wintypes.DWORD),
("biClrImportant", ctypes.wintypes.DWORD),
]
BI_RGB = 0
DIB_RGB_COLORS = 0
memcpy = ctypes.cdll.msvcrt.memcpy
2015-12-10 01:35:35 +03:00
memcpy.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t]
CreateCompatibleDC = ctypes.windll.gdi32.CreateCompatibleDC
2015-12-10 01:35:35 +03:00
CreateCompatibleDC.argtypes = [ctypes.wintypes.HDC]
CreateCompatibleDC.restype = ctypes.wintypes.HDC
DeleteDC = ctypes.windll.gdi32.DeleteDC
2015-12-10 01:35:35 +03:00
DeleteDC.argtypes = [ctypes.wintypes.HDC]
SelectObject = ctypes.windll.gdi32.SelectObject
2015-12-10 01:35:35 +03:00
SelectObject.argtypes = [ctypes.wintypes.HDC, ctypes.wintypes.HGDIOBJ]
SelectObject.restype = ctypes.wintypes.HGDIOBJ
DeleteObject = ctypes.windll.gdi32.DeleteObject
2015-12-10 01:35:35 +03:00
DeleteObject.argtypes = [ctypes.wintypes.HGDIOBJ]
CreateDIBSection = ctypes.windll.gdi32.CreateDIBSection
2019-06-13 18:54:46 +03:00
CreateDIBSection.argtypes = [
ctypes.wintypes.HDC,
ctypes.c_void_p,
ctypes.c_uint,
ctypes.POINTER(ctypes.c_void_p),
ctypes.wintypes.HANDLE,
ctypes.wintypes.DWORD,
]
CreateDIBSection.restype = ctypes.wintypes.HBITMAP
def serialize_dib(bi, pixels):
bf = BITMAPFILEHEADER()
2019-06-13 18:54:46 +03:00
bf.bfType = 0x4D42
bf.bfOffBits = ctypes.sizeof(bf) + bi.biSize
bf.bfSize = bf.bfOffBits + bi.biSizeImage
bf.bfReserved1 = bf.bfReserved2 = 0
buf = (ctypes.c_byte * bf.bfSize)()
bp = ctypes.addressof(buf)
memcpy(bp, ctypes.byref(bf), ctypes.sizeof(bf))
memcpy(bp + ctypes.sizeof(bf), ctypes.byref(bi), bi.biSize)
memcpy(bp + bf.bfOffBits, pixels, bi.biSizeImage)
return bytearray(buf)
def test_pointer(tmp_path: Path) -> None:
2020-01-27 14:46:52 +03:00
im = hopper()
(width, height) = im.size
opath = str(tmp_path / "temp.png")
imdib = ImageWin.Dib(im)
hdr = BITMAPINFOHEADER()
hdr.biSize = ctypes.sizeof(hdr)
hdr.biWidth = width
hdr.biHeight = height
hdr.biPlanes = 1
hdr.biBitCount = 32
hdr.biCompression = BI_RGB
hdr.biSizeImage = width * height * 4
hdr.biClrUsed = 0
hdr.biClrImportant = 0
hdc = CreateCompatibleDC(None)
pixels = ctypes.c_void_p()
dib = CreateDIBSection(
hdc, ctypes.byref(hdr), DIB_RGB_COLORS, ctypes.byref(pixels), None, 0
)
SelectObject(hdc, dib)
imdib.expose(hdc)
bitmap = serialize_dib(hdr, pixels)
DeleteObject(dib)
DeleteDC(hdc)
2021-02-11 13:43:54 +03:00
with Image.open(BytesIO(bitmap)) as im:
im.save(opath)