6 // From Yuan, ScanLineSize = (Width * bitcount + 31)/32
7 #define WIDTH_BYTES_ALIGN32(cx, bpp) ((((cx) * (bpp) + 31) & ~31) >> 3)
12 * Return the size of the bitmap info structure including color table.
13 * 11/16/1999 (RJJ) lifted from wine
17 FASTCALL
DIB_BitmapInfoSize(
18 const BITMAPINFO
* info
,
22 unsigned int colors
, size
, masks
= 0;
24 if (info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
26 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*) info
;
27 size
= sizeof(BITMAPCOREHEADER
);
28 if (core
->bcBitCount
<= 8)
30 colors
= 1 << core
->bcBitCount
;
31 if (coloruse
== DIB_RGB_COLORS
)
32 size
+= colors
* sizeof(RGBTRIPLE
);
34 size
+= colors
* sizeof(WORD
);
38 else /* assume BITMAPINFOHEADER */
40 colors
= max
? (1 << info
->bmiHeader
.biBitCount
) : info
->bmiHeader
.biClrUsed
;
43 if (!colors
&& (info
->bmiHeader
.biBitCount
<= 8))
44 colors
= 1 << info
->bmiHeader
.biBitCount
;
45 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
47 size
= max(info
->bmiHeader
.biSize
, sizeof(BITMAPINFOHEADER
) + masks
* sizeof(DWORD
));
48 return size
+ colors
* ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBQUAD
) : sizeof(WORD
));
53 * Return the full scan size for a bitmap.
55 * Based on Wine, Utils.c and Windows Graphics Prog pg 595, SDK amvideo.h.
59 DIB_BitmapMaxBitsSize(
68 if (Info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
70 PBITMAPCOREHEADER Core
= (PBITMAPCOREHEADER
) Info
;
71 Ret
= WIDTH_BYTES_ALIGN32(Core
->bcWidth
* Core
->bcPlanes
,
72 Core
->bcBitCount
) * ScanLines
;
74 else /* assume BITMAPINFOHEADER */
76 if ((Info
->bmiHeader
.biCompression
== BI_RGB
) || (Info
->bmiHeader
.biCompression
== BI_BITFIELDS
))
78 Ret
= WIDTH_BYTES_ALIGN32(
79 Info
->bmiHeader
.biWidth
* Info
->bmiHeader
.biPlanes
,
80 Info
->bmiHeader
.biBitCount
) * ScanLines
;
84 Ret
= Info
->bmiHeader
.biSizeImage
;
91 * DIB_GetBitmapInfo is complete copy of wine cvs 2/9-2006
92 * from file dib.c from gdi32.dll or orginal version
93 * did not calc the info right for some headers.
98 const BITMAPINFOHEADER
*header
,
106 if (header
->biSize
== sizeof(BITMAPCOREHEADER
))
108 BITMAPCOREHEADER
*core
= (BITMAPCOREHEADER
*) header
;
109 *width
= core
->bcWidth
;
110 *height
= core
->bcHeight
;
111 *planes
= core
->bcPlanes
;
112 *bpp
= core
->bcBitCount
;
118 if (header
->biSize
== sizeof(BITMAPINFOHEADER
))
120 *width
= header
->biWidth
;
121 *height
= header
->biHeight
;
122 *planes
= header
->biPlanes
;
123 *bpp
= header
->biBitCount
;
124 *compr
= header
->biCompression
;
125 *size
= header
->biSizeImage
;
129 if (header
->biSize
== sizeof(BITMAPV4HEADER
))
131 BITMAPV4HEADER
*v4hdr
= (BITMAPV4HEADER
*) header
;
132 *width
= v4hdr
->bV4Width
;
133 *height
= v4hdr
->bV4Height
;
134 *planes
= v4hdr
->bV4Planes
;
135 *bpp
= v4hdr
->bV4BitCount
;
136 *compr
= v4hdr
->bV4V4Compression
;
137 *size
= v4hdr
->bV4SizeImage
;
141 if (header
->biSize
== sizeof(BITMAPV5HEADER
))
143 BITMAPV5HEADER
*v5hdr
= (BITMAPV5HEADER
*) header
;
144 *width
= v5hdr
->bV5Width
;
145 *height
= v5hdr
->bV5Height
;
146 *planes
= v5hdr
->bV5Planes
;
147 *bpp
= v5hdr
->bV5BitCount
;
148 *compr
= v5hdr
->bV5Compression
;
149 *size
= v5hdr
->bV5SizeImage
;
152 DPRINT("(%lu): wrong size for header\n", header
->biSize
);
161 GdiGetBitmapBitsSize(
169 if (lpbmi
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
171 PBITMAPCOREHEADER Core
= (PBITMAPCOREHEADER
) lpbmi
;
173 WIDTH_BYTES_ALIGN32(Core
->bcWidth
* Core
->bcPlanes
,
174 Core
->bcBitCount
) * Core
->bcHeight
;
176 else /* assume BITMAPINFOHEADER */
178 if (!(lpbmi
->bmiHeader
.biCompression
) || (lpbmi
->bmiHeader
.biCompression
== BI_BITFIELDS
))
180 Ret
= WIDTH_BYTES_ALIGN32(
181 lpbmi
->bmiHeader
.biWidth
* lpbmi
->bmiHeader
.biPlanes
,
182 lpbmi
->bmiHeader
.biBitCount
) * abs(lpbmi
->bmiHeader
.biHeight
);
186 Ret
= lpbmi
->bmiHeader
.biSizeImage
;
199 CONST BITMAPINFO
*BitmapInfo
,
205 PBITMAPINFO pConvertedInfo
;
206 UINT ConvertedInfoSize
;
207 HBITMAP hBitmap
= NULL
;
210 pConvertedInfo
= ConvertBitmapInfo(BitmapInfo
, Usage
, &ConvertedInfoSize
,
215 // Verify header due to converted may == info.
216 if (pConvertedInfo
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
))
218 if (pConvertedInfo
->bmiHeader
.biCompression
== BI_JPEG
219 || pConvertedInfo
->bmiHeader
.biCompression
== BI_PNG
)
221 SetLastError(ERROR_INVALID_PARAMETER
);
226 hBitmap
= NtGdiCreateDIBSection(hDC
, hSection
, dwOffset
, pConvertedInfo
, Usage
,
227 ConvertedInfoSize
, 0, // fl
231 if (BitmapInfo
!= pConvertedInfo
)
232 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);
257 CONST VOID
* pUnsafeBits
)
261 return NtGdiCreateBitmap(Width
, Height
, Planes
, BitsPixel
, (LPBYTE
) pUnsafeBits
);
265 /* Return 1x1 bitmap */
266 return GetStockObject(DEFAULT_BITMAP
);
275 CreateBitmapIndirect(
278 HBITMAP bitmap
= NULL
;
280 /* Note windows xp/2003 does not check if pbm is NULL or not */
281 if ((pbm
->bmWidthBytes
!= 0) && (!(pbm
->bmWidthBytes
& 1)))
284 bitmap
= CreateBitmap(pbm
->bmWidth
, pbm
->bmHeight
, pbm
->bmPlanes
, pbm
->bmBitsPixel
,
289 SetLastError(ERROR_INVALID_PARAMETER
);
297 CreateDiscardableBitmap(
302 return CreateCompatibleBitmap(hDC
, Width
, Height
);
307 CreateCompatibleBitmap(
314 if (!GdiGetHandleUserData(hDC
, GDI_OBJECT_TYPE_DC
, (PVOID
) & pDc_Attr
))
317 if (!Width
|| !Height
)
318 return GetStockObject(DEFAULT_BITMAP
);
320 if (!(pDc_Attr
->ulDirty_
& DC_DIBSECTION
))
322 return NtGdiCreateCompatibleBitmap(hDC
, Width
, Height
);
330 BITMAPINFOHEADER bmih
;
331 RGBQUAD rgbquad
[256];
333 DIBSECTION
* pDIBs
= (DIBSECTION
*) &buffer
;
334 BITMAPINFO
* pbmi
= (BITMAPINFO
*) &buffer
.bmih
;
336 hBmp
= NtGdiGetDCObject(hDC
, GDI_OBJECT_TYPE_BITMAP
);
338 if (GetObjectA(hBmp
, sizeof(DIBSECTION
), pDIBs
) != sizeof(DIBSECTION
))
341 if (pDIBs
->dsBm
.bmBitsPixel
<= 8)
342 GetDIBColorTable(hDC
, 0, 256, buffer
.rgbquad
);
344 pDIBs
->dsBmih
.biWidth
= Width
;
345 pDIBs
->dsBmih
.biHeight
= Height
;
347 return CreateDIBSection(hDC
, pbmi
, DIB_RGB_COLORS
, NULL
, NULL
, 0);
366 if (!hDC
|| !GdiIsHandleValid((HGDIOBJ
) hDC
) || !lpbmi
)
368 GdiSetLastError(ERROR_INVALID_PARAMETER
);
372 cjBmpScanSize
= DIB_BitmapMaxBitsSize(lpbmi
, cScanLines
);
373 /* Caller must provide maximum size possible */
374 cjInfoSize
= DIB_BitmapInfoSize(lpbmi
, uUsage
, TRUE
);
378 if (lpbmi
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
))
380 if (lpbmi
->bmiHeader
.biCompression
== BI_JPEG
381 || lpbmi
->bmiHeader
.biCompression
== BI_PNG
)
383 SetLastError(ERROR_INVALID_PARAMETER
);
389 return NtGdiGetDIBitsInternal(hDC
, hbmp
, uStartScan
, cScanLines
, lpvBits
, lpbmi
, uUsage
,
390 cjBmpScanSize
, cjInfoSize
);
400 const BITMAPINFOHEADER
*Header
,
403 const BITMAPINFO
*Data
,
406 LONG width
, height
, compr
, dibsize
;
408 // PDC_ATTR pDc_Attr;
410 UINT cjBmpScanSize
= 0;
412 NTSTATUS Status
= STATUS_SUCCESS
;
414 /* Check for CBM_CREATDIB */
415 if (Init
& CBM_CREATDIB
)
417 /* CBM_CREATDIB needs Data. */
423 /* It only works with PAL or RGB */
424 if (ColorUse
> DIB_PAL_COLORS
)
426 GdiSetLastError(ERROR_INVALID_PARAMETER
);
430 /* Use the header from the data */
431 Header
= &Data
->bmiHeader
;
434 /* Header is required */
437 GdiSetLastError(ERROR_INVALID_PARAMETER
);
441 /* Get the bitmap format and dimensions */
442 if (DIB_GetBitmapInfo(Header
, &width
, &height
, &planes
, &bpp
, &compr
, &dibsize
) == -1)
444 GdiSetLastError(ERROR_INVALID_PARAMETER
);
448 /* Check if the Compr is incompatible */
449 if ((compr
== BI_JPEG
) || (compr
== BI_PNG
) || (compr
== BI_BITFIELDS
))
452 /* Only DIB_RGB_COLORS (0), DIB_PAL_COLORS (1) and 2 are valid. */
453 if (ColorUse
> DIB_PAL_COLORS
+ 1)
455 GdiSetLastError(ERROR_INVALID_PARAMETER
);
459 /* If some Bits are given, only DIB_PAL_COLORS and DIB_RGB_COLORS are valid */
460 if (Bits
&& (ColorUse
> DIB_PAL_COLORS
))
462 GdiSetLastError(ERROR_INVALID_PARAMETER
);
466 /* Negative width is not allowed */
470 /* Top-down DIBs have a negative height. */
471 height
= abs(height
);
474 // GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
480 cjBmpScanSize
= GdiGetBitmapBitsSize((BITMAPINFO
*) Data
);
481 CalculateColorTableSize(&Data
->bmiHeader
, &ColorUse
, &InfoSize
);
482 InfoSize
+= Data
->bmiHeader
.biSize
;
484 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
486 Status
= _SEH2_GetExceptionCode();
491 if (!NT_SUCCESS(Status
))
493 GdiSetLastError(ERROR_INVALID_PARAMETER
);
497 DPRINT("pBMI %p, Size bpp %u, dibsize %d, Conv %u, BSS %u\n", Data
, bpp
, dibsize
, InfoSize
,
500 if (!width
|| !height
)
501 hBmp
= GetStockObject(DEFAULT_BITMAP
);
504 hBmp
= NtGdiCreateDIBitmapInternal(hDC
, width
, height
, Init
, (LPBYTE
) Bits
,
505 (LPBITMAPINFO
) Data
, ColorUse
, InfoSize
, cjBmpScanSize
, 0, 0);
521 CONST BITMAPINFO
*lpbmi
,
524 HDC hDCc
, SavehDC
, nhDC
;
525 DWORD dwWidth
, dwHeight
;
527 HPALETTE hPal
= NULL
;
531 if (!lpvBits
|| (GDI_HANDLE_GET_TYPE(hBitmap
) != GDI_OBJECT_TYPE_BITMAP
))
536 if (lpbmi
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
))
538 if (lpbmi
->bmiHeader
.biCompression
== BI_JPEG
539 || lpbmi
->bmiHeader
.biCompression
== BI_PNG
)
541 SetLastError(ERROR_INVALID_PARAMETER
);
547 hDCc
= NtGdiGetDCforBitmap(hBitmap
); // hDC can be NULL, so, get it from the bitmap.
549 if (!hDCc
) // No DC associated with bitmap, Clone or Create one.
551 nhDC
= CreateCompatibleDC(hDC
);
557 else if (!SaveDC(hDCc
))
560 hOldBitmap
= SelectObject(SavehDC
, hBitmap
);
565 hPal
= SelectPalette(SavehDC
, (HPALETTE
) GetCurrentObject(hDC
, OBJ_PAL
), FALSE
);
567 if (lpbmi
->bmiHeader
.biSize
< sizeof(BITMAPINFOHEADER
))
569 PBITMAPCOREINFO pbci
= (PBITMAPCOREINFO
) lpbmi
;
570 dwWidth
= pbci
->bmciHeader
.bcWidth
;
571 dwHeight
= pbci
->bmciHeader
.bcHeight
;
575 dwWidth
= lpbmi
->bmiHeader
.biWidth
;
576 dwHeight
= abs(lpbmi
->bmiHeader
.biHeight
);
579 LinesCopied
= SetDIBitsToDevice(SavehDC
, 0, 0, dwWidth
, dwHeight
, 0, 0, uStartScan
,
580 cScanLines
, (void *) lpvBits
, (LPBITMAPINFO
) lpbmi
, fuColorUse
);
583 SelectPalette(SavehDC
, hPal
, FALSE
);
585 SelectObject(SavehDC
, hOldBitmap
);
591 RestoreDC(SavehDC
, -1);
613 CONST BITMAPINFO
*lpbmi
,
617 PBITMAPINFO pConvertedInfo
;
618 UINT ConvertedInfoSize
;
620 UINT cjBmpScanSize
= 0;
622 PVOID pvSafeBits
= (PVOID
) Bits
;
624 if (!ScanLines
|| !lpbmi
|| !Bits
)
627 if (ColorUse
&& ColorUse
!= DIB_PAL_COLORS
&& ColorUse
!= DIB_PAL_COLORS
+ 1)
630 pConvertedInfo
= ConvertBitmapInfo(lpbmi
, ColorUse
, &ConvertedInfoSize
, FALSE
);
650 if ((pConvertedInfo
->bmiHeader
.biCompression
== BI_RLE8
) ||
651 (pConvertedInfo
->bmiHeader
.biCompression
== BI_RLE4
))
653 /* For compressed data, we must set the whole thing */
655 ScanLines
= pConvertedInfo
->bmiHeader
.biHeight
;
658 cjBmpScanSize
= DIB_BitmapMaxBitsSize((LPBITMAPINFO
) lpbmi
, ScanLines
);
660 pvSafeBits
= RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize
);
665 RtlCopyMemory(pvSafeBits
, Bits
, cjBmpScanSize
);
667 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
675 // We don't die, we continue on with a allocated safe pointer to kernel
677 DPRINT1("SetDIBitsToDevice fail to read BitMapInfo: %p or Bits: %p & Size: %u\n",
678 pConvertedInfo
, Bits
, cjBmpScanSize
);
680 DPRINT("SetDIBitsToDevice Allocate Bits %u!!!\n", cjBmpScanSize
);
683 if (!GdiGetHandleUserData(hdc
, GDI_OBJECT_TYPE_DC
, (PVOID
) & pDc_Attr
))
685 SetLastError(ERROR_INVALID_PARAMETER
);
689 if ( !pDc_Attr || // DC is Public
690 ColorUse == DIB_PAL_COLORS ||
691 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
692 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
693 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
695 LinesCopied
= NtGdiSetDIBitsToDeviceInternal(hdc
, XDest
, YDest
, Width
, Height
, XSrc
, YSrc
,
696 StartScan
, ScanLines
, (LPBYTE
) pvSafeBits
, (LPBITMAPINFO
) pConvertedInfo
, ColorUse
,
697 cjBmpScanSize
, ConvertedInfoSize
,
701 if (Bits
!= pvSafeBits
)
702 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits
);
703 if (lpbmi
!= pConvertedInfo
)
704 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);
725 CONST BITMAPINFO
*lpBitsInfo
,
731 PBITMAPINFO pConvertedInfo
= NULL
;
732 UINT ConvertedInfoSize
= 0;
734 UINT cjBmpScanSize
= 0;
735 PVOID pvSafeBits
= NULL
;
738 DPRINT("StretchDIBits %p : %p : %u\n", lpBits
, lpBitsInfo
, iUsage
);
740 // Handle something other than a normal dc object.
741 if (GDI_HANDLE_GET_TYPE(hdc
) != GDI_OBJECT_TYPE_DC
)
743 if (GDI_HANDLE_GET_TYPE(hdc
) == GDI_OBJECT_TYPE_METADC
)
744 return MFDRV_StretchBlt( hdc
,
759 PLDC pLDC
= GdiGetLDC(hdc
);
762 SetLastError(ERROR_INVALID_HANDLE
);
765 if (pLDC
->iType
== LDC_EMFLDC
)
767 return EMFDRV_StretchBlt(hdc
,
785 pConvertedInfo
= ConvertBitmapInfo(lpBitsInfo
, iUsage
, &ConvertedInfoSize
,
792 cjBmpScanSize
= GdiGetBitmapBitsSize((BITMAPINFO
*) pConvertedInfo
);
796 pvSafeBits
= RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize
);
801 RtlCopyMemory(pvSafeBits
, lpBits
, cjBmpScanSize
);
803 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
811 // We don't die, we continue on with a allocated safe pointer to kernel
813 DPRINT1("StretchDIBits fail to read BitMapInfo: %p or Bits: %p & Size: %u\n",
814 pConvertedInfo
, lpBits
, cjBmpScanSize
);
816 DPRINT("StretchDIBits Allocate Bits %u!!!\n", cjBmpScanSize
);
820 if (!GdiGetHandleUserData(hdc
, GDI_OBJECT_TYPE_DC
, (PVOID
) & pDc_Attr
))
822 SetLastError(ERROR_INVALID_PARAMETER
);
827 iUsage == DIB_PAL_COLORS ||
828 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
829 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
830 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
832 LinesCopied
= NtGdiStretchDIBitsInternal(hdc
, XDest
, YDest
, nDestWidth
, nDestHeight
, XSrc
,
833 YSrc
, nSrcWidth
, nSrcHeight
, pvSafeBits
, pConvertedInfo
, (DWORD
) iUsage
, dwRop
,
834 ConvertedInfoSize
, cjBmpScanSize
,
838 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits
);
839 if (lpBitsInfo
!= pConvertedInfo
)
840 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);
850 GetBitmapAttributes(HBITMAP hbm
)
853 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
862 SetBitmapAttributes(HBITMAP hbm
, DWORD dwFlags
)
865 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
874 ClearBitmapAttributes(HBITMAP hbm
, DWORD dwFlags
)
877 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
888 HBITMAP in_format_BitMap
,
893 /* FIXME guessing the prototypes */
896 * it have create a new bitmap with desired in format,
897 * then convert it src_bitmap to new format
898 * and return it as HBITMAP