mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-10-25 05:01:26 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			115 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			115 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from io import BytesIO
 | |
| 
 | |
| from PIL import Image, ImageWin
 | |
| 
 | |
| from .helper import hopper, is_win32
 | |
| 
 | |
| # see https://github.com/python-pillow/Pillow/pull/1431#issuecomment-144692652
 | |
| 
 | |
| if is_win32():
 | |
|     import ctypes
 | |
|     import ctypes.wintypes
 | |
| 
 | |
|     class BITMAPFILEHEADER(ctypes.Structure):
 | |
|         _pack_ = 2
 | |
|         _fields_ = [
 | |
|             ("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_ = [
 | |
|             ("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
 | |
|     memcpy.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t]
 | |
| 
 | |
|     CreateCompatibleDC = ctypes.windll.gdi32.CreateCompatibleDC
 | |
|     CreateCompatibleDC.argtypes = [ctypes.wintypes.HDC]
 | |
|     CreateCompatibleDC.restype = ctypes.wintypes.HDC
 | |
| 
 | |
|     DeleteDC = ctypes.windll.gdi32.DeleteDC
 | |
|     DeleteDC.argtypes = [ctypes.wintypes.HDC]
 | |
| 
 | |
|     SelectObject = ctypes.windll.gdi32.SelectObject
 | |
|     SelectObject.argtypes = [ctypes.wintypes.HDC, ctypes.wintypes.HGDIOBJ]
 | |
|     SelectObject.restype = ctypes.wintypes.HGDIOBJ
 | |
| 
 | |
|     DeleteObject = ctypes.windll.gdi32.DeleteObject
 | |
|     DeleteObject.argtypes = [ctypes.wintypes.HGDIOBJ]
 | |
| 
 | |
|     CreateDIBSection = ctypes.windll.gdi32.CreateDIBSection
 | |
|     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()
 | |
|         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):
 | |
|         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)
 | |
| 
 | |
|         with Image.open(BytesIO(bitmap)) as im:
 | |
|             im.save(opath)
 |