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
;
413 PBITMAPINFO pbmiConverted
;
416 /* Convert the BITMAPINFO if it is a COREINFO */
417 pbmiConverted
= ConvertBitmapInfo(Data
, ColorUse
, &cjInfoSize
, FALSE
);
419 /* Check for CBM_CREATDIB */
420 if (Init
& CBM_CREATDIB
)
422 /* CBM_CREATDIB needs Data. */
423 if (pbmiConverted
== NULL
)
425 DPRINT1("CBM_CREATDIB needs a BITMAINFO!\n");
429 /* It only works with PAL or RGB */
430 if (ColorUse
> DIB_PAL_COLORS
)
432 DPRINT1("Invalid ColorUse: %lu\n", ColorUse
);
433 GdiSetLastError(ERROR_INVALID_PARAMETER
);
437 /* Use the header from the data */
438 Header
= &Data
->bmiHeader
;
441 /* Header is required */
444 DPRINT1("Header is NULL\n");
445 GdiSetLastError(ERROR_INVALID_PARAMETER
);
449 /* Get the bitmap format and dimensions */
450 if (DIB_GetBitmapInfo(Header
, &width
, &height
, &planes
, &bpp
, &compr
, &dibsize
) == -1)
452 DPRINT1("DIB_GetBitmapInfo failed!\n");
453 GdiSetLastError(ERROR_INVALID_PARAMETER
);
457 /* Check if the Compr is incompatible */
458 if ((compr
== BI_JPEG
) || (compr
== BI_PNG
) || (compr
== BI_BITFIELDS
))
460 DPRINT1("invalid compr: %lu!\n", compr
);
464 /* Only DIB_RGB_COLORS (0), DIB_PAL_COLORS (1) and 2 are valid. */
465 if (ColorUse
> DIB_PAL_COLORS
+ 1)
467 DPRINT1("invalid compr: %lu!\n", compr
);
468 GdiSetLastError(ERROR_INVALID_PARAMETER
);
472 /* If some Bits are given, only DIB_PAL_COLORS and DIB_RGB_COLORS are valid */
473 if (Bits
&& (ColorUse
> DIB_PAL_COLORS
))
475 DPRINT1("Invalid ColorUse: %lu\n", ColorUse
);
476 GdiSetLastError(ERROR_INVALID_PARAMETER
);
480 /* Negative width is not allowed */
483 DPRINT1("Negative width: %li\n", width
);
487 /* Top-down DIBs have a negative height. */
488 height
= abs(height
);
491 // GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
497 cjBmpScanSize
= GdiGetBitmapBitsSize(pbmiConverted
);
498 CalculateColorTableSize(&pbmiConverted
->bmiHeader
, &ColorUse
, &InfoSize
);
499 InfoSize
+= pbmiConverted
->bmiHeader
.biSize
;
501 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
503 Status
= _SEH2_GetExceptionCode();
508 if (!NT_SUCCESS(Status
))
510 DPRINT1("Got an exception!\n");
511 GdiSetLastError(ERROR_INVALID_PARAMETER
);
515 DPRINT("pBMI %p, Size bpp %u, dibsize %d, Conv %u, BSS %u\n", Data
, bpp
, dibsize
, InfoSize
,
518 if (!width
|| !height
)
519 hBmp
= GetStockObject(DEFAULT_BITMAP
);
522 hBmp
= NtGdiCreateDIBitmapInternal(hDC
, width
, height
, Init
, (LPBYTE
)Bits
,
523 (LPBITMAPINFO
)pbmiConverted
, ColorUse
, InfoSize
, cjBmpScanSize
, 0, 0);
528 /* Cleanup converted BITMAPINFO */
529 if ((pbmiConverted
!= NULL
) && (pbmiConverted
!= Data
))
531 RtlFreeHeap(RtlGetProcessHeap(), 0, pbmiConverted
);
548 CONST BITMAPINFO
*lpbmi
,
551 HDC hDCc
, SavehDC
, nhDC
;
552 DWORD dwWidth
, dwHeight
;
554 HPALETTE hPal
= NULL
;
558 if (!lpvBits
|| (GDI_HANDLE_GET_TYPE(hBitmap
) != GDI_OBJECT_TYPE_BITMAP
))
563 if (lpbmi
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
))
565 if (lpbmi
->bmiHeader
.biCompression
== BI_JPEG
566 || lpbmi
->bmiHeader
.biCompression
== BI_PNG
)
568 SetLastError(ERROR_INVALID_PARAMETER
);
574 hDCc
= NtGdiGetDCforBitmap(hBitmap
); // hDC can be NULL, so, get it from the bitmap.
576 if (!hDCc
) // No DC associated with bitmap, Clone or Create one.
578 nhDC
= CreateCompatibleDC(hDC
);
584 else if (!SaveDC(hDCc
))
587 hOldBitmap
= SelectObject(SavehDC
, hBitmap
);
592 hPal
= SelectPalette(SavehDC
, (HPALETTE
) GetCurrentObject(hDC
, OBJ_PAL
), FALSE
);
594 if (lpbmi
->bmiHeader
.biSize
< sizeof(BITMAPINFOHEADER
))
596 PBITMAPCOREINFO pbci
= (PBITMAPCOREINFO
) lpbmi
;
597 dwWidth
= pbci
->bmciHeader
.bcWidth
;
598 dwHeight
= pbci
->bmciHeader
.bcHeight
;
602 dwWidth
= lpbmi
->bmiHeader
.biWidth
;
603 dwHeight
= abs(lpbmi
->bmiHeader
.biHeight
);
606 LinesCopied
= SetDIBitsToDevice(SavehDC
, 0, 0, dwWidth
, dwHeight
, 0, 0, uStartScan
,
607 cScanLines
, (void *) lpvBits
, (LPBITMAPINFO
) lpbmi
, fuColorUse
);
610 SelectPalette(SavehDC
, hPal
, FALSE
);
612 SelectObject(SavehDC
, hOldBitmap
);
618 RestoreDC(SavehDC
, -1);
640 CONST BITMAPINFO
*lpbmi
,
644 PBITMAPINFO pConvertedInfo
;
645 UINT ConvertedInfoSize
;
647 UINT cjBmpScanSize
= 0;
649 PVOID pvSafeBits
= (PVOID
) Bits
;
651 if (!ScanLines
|| !lpbmi
|| !Bits
)
654 if (ColorUse
&& ColorUse
!= DIB_PAL_COLORS
&& ColorUse
!= DIB_PAL_COLORS
+ 1)
657 pConvertedInfo
= ConvertBitmapInfo(lpbmi
, ColorUse
, &ConvertedInfoSize
, FALSE
);
677 if ((pConvertedInfo
->bmiHeader
.biCompression
== BI_RLE8
) ||
678 (pConvertedInfo
->bmiHeader
.biCompression
== BI_RLE4
))
680 /* For compressed data, we must set the whole thing */
682 ScanLines
= pConvertedInfo
->bmiHeader
.biHeight
;
685 cjBmpScanSize
= DIB_BitmapMaxBitsSize((LPBITMAPINFO
) lpbmi
, ScanLines
);
687 pvSafeBits
= RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize
);
692 RtlCopyMemory(pvSafeBits
, Bits
, cjBmpScanSize
);
694 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
702 // We don't die, we continue on with a allocated safe pointer to kernel
704 DPRINT1("SetDIBitsToDevice fail to read BitMapInfo: %p or Bits: %p & Size: %u\n",
705 pConvertedInfo
, Bits
, cjBmpScanSize
);
707 DPRINT("SetDIBitsToDevice Allocate Bits %u!!!\n", cjBmpScanSize
);
710 if (!GdiGetHandleUserData(hdc
, GDI_OBJECT_TYPE_DC
, (PVOID
) & pDc_Attr
))
712 SetLastError(ERROR_INVALID_PARAMETER
);
716 if ( !pDc_Attr || // DC is Public
717 ColorUse == DIB_PAL_COLORS ||
718 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
719 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
720 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
722 LinesCopied
= NtGdiSetDIBitsToDeviceInternal(hdc
, XDest
, YDest
, Width
, Height
, XSrc
, YSrc
,
723 StartScan
, ScanLines
, (LPBYTE
) pvSafeBits
, (LPBITMAPINFO
) pConvertedInfo
, ColorUse
,
724 cjBmpScanSize
, ConvertedInfoSize
,
728 if (Bits
!= pvSafeBits
)
729 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits
);
730 if (lpbmi
!= pConvertedInfo
)
731 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);
752 CONST BITMAPINFO
*lpBitsInfo
,
758 PBITMAPINFO pConvertedInfo
= NULL
;
759 UINT ConvertedInfoSize
= 0;
761 UINT cjBmpScanSize
= 0;
762 PVOID pvSafeBits
= NULL
;
765 DPRINT("StretchDIBits %p : %p : %u\n", lpBits
, lpBitsInfo
, iUsage
);
767 // Handle something other than a normal dc object.
768 if (GDI_HANDLE_GET_TYPE(hdc
) != GDI_OBJECT_TYPE_DC
)
770 if (GDI_HANDLE_GET_TYPE(hdc
) == GDI_OBJECT_TYPE_METADC
)
771 return MFDRV_StretchBlt( hdc
,
786 PLDC pLDC
= GdiGetLDC(hdc
);
789 SetLastError(ERROR_INVALID_HANDLE
);
792 if (pLDC
->iType
== LDC_EMFLDC
)
794 return EMFDRV_StretchBlt(hdc
,
812 pConvertedInfo
= ConvertBitmapInfo(lpBitsInfo
, iUsage
, &ConvertedInfoSize
,
819 cjBmpScanSize
= GdiGetBitmapBitsSize((BITMAPINFO
*) pConvertedInfo
);
823 pvSafeBits
= RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize
);
828 RtlCopyMemory(pvSafeBits
, lpBits
, cjBmpScanSize
);
830 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
838 // We don't die, we continue on with a allocated safe pointer to kernel
840 DPRINT1("StretchDIBits fail to read BitMapInfo: %p or Bits: %p & Size: %u\n",
841 pConvertedInfo
, lpBits
, cjBmpScanSize
);
843 DPRINT("StretchDIBits Allocate Bits %u!!!\n", cjBmpScanSize
);
847 if (!GdiGetHandleUserData(hdc
, GDI_OBJECT_TYPE_DC
, (PVOID
) & pDc_Attr
))
849 SetLastError(ERROR_INVALID_PARAMETER
);
854 iUsage == DIB_PAL_COLORS ||
855 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
856 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
857 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
859 LinesCopied
= NtGdiStretchDIBitsInternal(hdc
, XDest
, YDest
, nDestWidth
, nDestHeight
, XSrc
,
860 YSrc
, nSrcWidth
, nSrcHeight
, pvSafeBits
, pConvertedInfo
, (DWORD
) iUsage
, dwRop
,
861 ConvertedInfoSize
, cjBmpScanSize
,
865 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits
);
866 if (lpBitsInfo
!= pConvertedInfo
)
867 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);
877 GetBitmapAttributes(HBITMAP hbm
)
880 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
889 SetBitmapAttributes(HBITMAP hbm
, DWORD dwFlags
)
892 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
901 ClearBitmapAttributes(HBITMAP hbm
, DWORD dwFlags
)
904 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
915 HBITMAP in_format_BitMap
,
920 /* FIXME guessing the prototypes */
923 * it have create a new bitmap with desired in format,
924 * then convert it src_bitmap to new format
925 * and return it as HBITMAP