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
|| !GdiValidateHandle((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
, Compression
, DibSize
;
407 WORD Planes
, BitsPerPixel
;
408 // PDC_ATTR pDc_Attr;
409 UINT cjBmpScanSize
= 0;
410 HBITMAP hBitmap
= NULL
;
411 PBITMAPINFO pbmiConverted
;
414 /* Convert the BITMAPINFO if it is a COREINFO */
415 pbmiConverted
= ConvertBitmapInfo(Data
, ColorUse
, &cjInfoSize
, FALSE
);
417 /* Check for CBM_CREATDIB */
418 if (Init
& CBM_CREATDIB
)
424 else if (Init
& CBM_INIT
)
436 /* CBM_CREATDIB needs Data. */
437 if (pbmiConverted
== NULL
)
439 DPRINT1("CBM_CREATDIB needs a BITMAPINFO!\n");
443 /* It only works with PAL or RGB */
444 if (ColorUse
> DIB_PAL_COLORS
)
446 DPRINT1("Invalid ColorUse: %lu\n", ColorUse
);
447 GdiSetLastError(ERROR_INVALID_PARAMETER
);
451 /* Use the header from the data */
452 Header
= &Data
->bmiHeader
;
472 /* Header is required */
475 DPRINT1("Header is NULL\n");
476 GdiSetLastError(ERROR_INVALID_PARAMETER
);
480 /* Get the bitmap format and dimensions */
481 if (DIB_GetBitmapInfo(Header
, &Width
, &Height
, &Planes
, &BitsPerPixel
, &Compression
, &DibSize
) == -1)
483 DPRINT1("DIB_GetBitmapInfo failed!\n");
484 GdiSetLastError(ERROR_INVALID_PARAMETER
);
488 /* Check if the Compr is incompatible */
489 if ((Compression
== BI_JPEG
) || (Compression
== BI_PNG
) || (Compression
== BI_BITFIELDS
))
491 DPRINT1("Invalid compression: %lu!\n", Compression
);
495 /* Only DIB_RGB_COLORS (0), DIB_PAL_COLORS (1) and 2 are valid. */
496 if (ColorUse
> DIB_PAL_COLORS
+ 1)
498 DPRINT1("Invalid compression: %lu!\n", Compression
);
499 GdiSetLastError(ERROR_INVALID_PARAMETER
);
503 /* If some Bits are given, only DIB_PAL_COLORS and DIB_RGB_COLORS are valid */
504 if (Bits
&& (ColorUse
> DIB_PAL_COLORS
))
506 DPRINT1("Invalid ColorUse: %lu\n", ColorUse
);
507 GdiSetLastError(ERROR_INVALID_PARAMETER
);
511 /* Negative width is not allowed */
514 DPRINT1("Negative width: %li\n", Width
);
518 /* Top-down DIBs have a negative height. */
519 Height
= abs(Height
);
522 // GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
524 cjBmpScanSize
= GdiGetBitmapBitsSize(pbmiConverted
);
526 DPRINT("pBMI %p, Size bpp %u, dibsize %d, Conv %u, BSS %u\n",
527 Data
, BitsPerPixel
, DibSize
, cjInfoSize
, cjBmpScanSize
);
529 if (!Width
|| !Height
)
531 hBitmap
= GetStockObject(DEFAULT_BITMAP
);
535 hBitmap
= NtGdiCreateDIBitmapInternal(hDC
,
540 (LPBITMAPINFO
)pbmiConverted
,
548 /* Cleanup converted BITMAPINFO */
549 if ((pbmiConverted
!= NULL
) && (pbmiConverted
!= Data
))
551 RtlFreeHeap(RtlGetProcessHeap(), 0, pbmiConverted
);
568 CONST BITMAPINFO
*lpbmi
,
571 HDC hDCc
, SavehDC
, nhDC
;
572 DWORD dwWidth
, dwHeight
;
574 HPALETTE hPal
= NULL
;
578 if (!lpvBits
|| (GDI_HANDLE_GET_TYPE(hBitmap
) != GDI_OBJECT_TYPE_BITMAP
))
581 if (lpbmi
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
))
583 if (lpbmi
->bmiHeader
.biCompression
== BI_JPEG
584 || lpbmi
->bmiHeader
.biCompression
== BI_PNG
)
586 SetLastError(ERROR_INVALID_PARAMETER
);
591 hDCc
= NtGdiGetDCforBitmap(hBitmap
); // hDC can be NULL, so, get it from the bitmap.
593 if (!hDCc
) // No DC associated with bitmap, Clone or Create one.
595 nhDC
= CreateCompatibleDC(hDC
);
601 else if (!SaveDC(hDCc
))
604 hOldBitmap
= SelectObject(SavehDC
, hBitmap
);
609 hPal
= SelectPalette(SavehDC
, (HPALETTE
) GetCurrentObject(hDC
, OBJ_PAL
), FALSE
);
611 if (lpbmi
->bmiHeader
.biSize
< sizeof(BITMAPINFOHEADER
))
613 PBITMAPCOREINFO pbci
= (PBITMAPCOREINFO
) lpbmi
;
614 dwWidth
= pbci
->bmciHeader
.bcWidth
;
615 dwHeight
= pbci
->bmciHeader
.bcHeight
;
619 dwWidth
= lpbmi
->bmiHeader
.biWidth
;
620 dwHeight
= abs(lpbmi
->bmiHeader
.biHeight
);
623 LinesCopied
= SetDIBitsToDevice(SavehDC
, 0, 0, dwWidth
, dwHeight
, 0, 0, uStartScan
,
624 cScanLines
, (void *) lpvBits
, (LPBITMAPINFO
) lpbmi
, fuColorUse
);
627 SelectPalette(SavehDC
, hPal
, FALSE
);
629 SelectObject(SavehDC
, hOldBitmap
);
635 RestoreDC(SavehDC
, -1);
657 CONST BITMAPINFO
*lpbmi
,
661 PBITMAPINFO pConvertedInfo
;
662 UINT ConvertedInfoSize
;
664 UINT cjBmpScanSize
= 0;
666 PVOID pvSafeBits
= (PVOID
) Bits
;
668 if (!ScanLines
|| !lpbmi
|| !Bits
)
671 if (ColorUse
&& ColorUse
!= DIB_PAL_COLORS
&& ColorUse
!= DIB_PAL_COLORS
+ 1)
674 pConvertedInfo
= ConvertBitmapInfo(lpbmi
, ColorUse
, &ConvertedInfoSize
, FALSE
);
694 if ((pConvertedInfo
->bmiHeader
.biCompression
== BI_RLE8
) ||
695 (pConvertedInfo
->bmiHeader
.biCompression
== BI_RLE4
))
697 /* For compressed data, we must set the whole thing */
699 ScanLines
= pConvertedInfo
->bmiHeader
.biHeight
;
702 cjBmpScanSize
= DIB_BitmapMaxBitsSize((LPBITMAPINFO
) lpbmi
, ScanLines
);
704 pvSafeBits
= RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize
);
709 RtlCopyMemory(pvSafeBits
, Bits
, cjBmpScanSize
);
711 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
719 // We don't die, we continue on with a allocated safe pointer to kernel
721 DPRINT1("SetDIBitsToDevice fail to read BitMapInfo: %p or Bits: %p & Size: %u\n",
722 pConvertedInfo
, Bits
, cjBmpScanSize
);
724 DPRINT("SetDIBitsToDevice Allocate Bits %u!!!\n", cjBmpScanSize
);
727 if (!GdiGetHandleUserData(hdc
, GDI_OBJECT_TYPE_DC
, (PVOID
) & pDc_Attr
))
729 SetLastError(ERROR_INVALID_PARAMETER
);
733 if ( !pDc_Attr || // DC is Public
734 ColorUse == DIB_PAL_COLORS ||
735 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
736 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
737 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
739 LinesCopied
= NtGdiSetDIBitsToDeviceInternal(hdc
, XDest
, YDest
, Width
, Height
, XSrc
, YSrc
,
740 StartScan
, ScanLines
, (LPBYTE
) pvSafeBits
, (LPBITMAPINFO
) pConvertedInfo
, ColorUse
,
741 cjBmpScanSize
, ConvertedInfoSize
,
745 if (Bits
!= pvSafeBits
)
746 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits
);
747 if (lpbmi
!= pConvertedInfo
)
748 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);
769 CONST BITMAPINFO
*lpBitsInfo
,
775 PBITMAPINFO pConvertedInfo
= NULL
;
776 UINT ConvertedInfoSize
= 0;
778 UINT cjBmpScanSize
= 0;
779 PVOID pvSafeBits
= NULL
;
782 DPRINT("StretchDIBits %p : %p : %u\n", lpBits
, lpBitsInfo
, iUsage
);
784 // Handle something other than a normal dc object.
785 if (GDI_HANDLE_GET_TYPE(hdc
) != GDI_OBJECT_TYPE_DC
)
787 if (GDI_HANDLE_GET_TYPE(hdc
) == GDI_OBJECT_TYPE_METADC
)
788 return MFDRV_StretchBlt( hdc
,
803 PLDC pLDC
= GdiGetLDC(hdc
);
806 SetLastError(ERROR_INVALID_HANDLE
);
809 if (pLDC
->iType
== LDC_EMFLDC
)
811 return EMFDRV_StretchBlt(hdc
,
829 pConvertedInfo
= ConvertBitmapInfo(lpBitsInfo
, iUsage
, &ConvertedInfoSize
,
836 cjBmpScanSize
= GdiGetBitmapBitsSize((BITMAPINFO
*) pConvertedInfo
);
840 pvSafeBits
= RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize
);
845 RtlCopyMemory(pvSafeBits
, lpBits
, cjBmpScanSize
);
847 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
855 // We don't die, we continue on with a allocated safe pointer to kernel
857 DPRINT1("StretchDIBits fail to read BitMapInfo: %p or Bits: %p & Size: %u\n",
858 pConvertedInfo
, lpBits
, cjBmpScanSize
);
860 DPRINT("StretchDIBits Allocate Bits %u!!!\n", cjBmpScanSize
);
864 if (!GdiGetHandleUserData(hdc
, GDI_OBJECT_TYPE_DC
, (PVOID
) & pDc_Attr
))
866 SetLastError(ERROR_INVALID_PARAMETER
);
871 iUsage == DIB_PAL_COLORS ||
872 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
873 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
874 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
876 LinesCopied
= NtGdiStretchDIBitsInternal(hdc
, XDest
, YDest
, nDestWidth
, nDestHeight
, XSrc
,
877 YSrc
, nSrcWidth
, nSrcHeight
, pvSafeBits
, pConvertedInfo
, (DWORD
) iUsage
, dwRop
,
878 ConvertedInfoSize
, cjBmpScanSize
,
882 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits
);
883 if (lpBitsInfo
!= pConvertedInfo
)
884 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);
894 GetBitmapAttributes(HBITMAP hbm
)
897 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
906 SetBitmapAttributes(HBITMAP hbm
, DWORD dwFlags
)
909 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
918 ClearBitmapAttributes(HBITMAP hbm
, DWORD dwFlags
)
921 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
932 HBITMAP in_format_BitMap
,
937 /* FIXME guessing the prototypes */
940 * it have create a new bitmap with desired in format,
941 * then convert it src_bitmap to new format
942 * and return it as HBITMAP