Pillow

Форк
0
/
test_imagewin_pointers.py 
118 строк · 3.8 Кб
1
from __future__ import annotations
2

3
from io import BytesIO
4
from pathlib import Path
5

6
from PIL import Image, ImageWin
7

8
from .helper import hopper, is_win32
9

10
# see https://github.com/python-pillow/Pillow/pull/1431#issuecomment-144692652
11

12
if is_win32():
13
    import ctypes
14
    import ctypes.wintypes
15

16
    class BITMAPFILEHEADER(ctypes.Structure):
17
        _pack_ = 2
18
        _fields_ = [
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),
24
        ]
25

26
    class BITMAPINFOHEADER(ctypes.Structure):
27
        _pack_ = 2
28
        _fields_ = [
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),
40
        ]
41

42
    BI_RGB = 0
43
    DIB_RGB_COLORS = 0
44

45
    memcpy = ctypes.cdll.msvcrt.memcpy
46
    memcpy.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t]
47

48
    windll = getattr(ctypes, "windll")
49
    CreateCompatibleDC = windll.gdi32.CreateCompatibleDC
50
    CreateCompatibleDC.argtypes = [ctypes.wintypes.HDC]
51
    CreateCompatibleDC.restype = ctypes.wintypes.HDC
52

53
    DeleteDC = windll.gdi32.DeleteDC
54
    DeleteDC.argtypes = [ctypes.wintypes.HDC]
55

56
    SelectObject = windll.gdi32.SelectObject
57
    SelectObject.argtypes = [ctypes.wintypes.HDC, ctypes.wintypes.HGDIOBJ]
58
    SelectObject.restype = ctypes.wintypes.HGDIOBJ
59

60
    DeleteObject = windll.gdi32.DeleteObject
61
    DeleteObject.argtypes = [ctypes.wintypes.HGDIOBJ]
62

63
    CreateDIBSection = windll.gdi32.CreateDIBSection
64
    CreateDIBSection.argtypes = [
65
        ctypes.wintypes.HDC,
66
        ctypes.c_void_p,
67
        ctypes.c_uint,
68
        ctypes.POINTER(ctypes.c_void_p),
69
        ctypes.wintypes.HANDLE,
70
        ctypes.wintypes.DWORD,
71
    ]
72
    CreateDIBSection.restype = ctypes.wintypes.HBITMAP
73

74
    def serialize_dib(bi: BITMAPINFOHEADER, pixels: ctypes.c_void_p) -> bytearray:
75
        bf = BITMAPFILEHEADER()
76
        bf.bfType = 0x4D42
77
        bf.bfOffBits = ctypes.sizeof(bf) + bi.biSize
78
        bf.bfSize = bf.bfOffBits + bi.biSizeImage
79
        bf.bfReserved1 = bf.bfReserved2 = 0
80

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)
86
        return bytearray(buf)
87

88
    def test_pointer(tmp_path: Path) -> None:
89
        im = hopper()
90
        (width, height) = im.size
91
        opath = str(tmp_path / "temp.png")
92
        imdib = ImageWin.Dib(im)
93

94
        hdr = BITMAPINFOHEADER()
95
        hdr.biSize = ctypes.sizeof(hdr)
96
        hdr.biWidth = width
97
        hdr.biHeight = height
98
        hdr.biPlanes = 1
99
        hdr.biBitCount = 32
100
        hdr.biCompression = BI_RGB
101
        hdr.biSizeImage = width * height * 4
102
        hdr.biClrUsed = 0
103
        hdr.biClrImportant = 0
104

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
109
        )
110
        SelectObject(hdc, dib)
111

112
        imdib.expose(hdc)
113
        bitmap = serialize_dib(hdr, pixels)
114
        DeleteObject(dib)
115
        DeleteDC(hdc)
116

117
        with Image.open(BytesIO(bitmap)) as im:
118
            im.save(opath)
119

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.