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
);
252 HDC hdcDest
, /* handle to destination DC */
253 int nXOriginDest
, /* x-coord of destination upper-left corner */
254 int nYOriginDest
, /* y-coord of destination upper-left corner */
255 int nWidthDest
, /* width of destination rectangle */
256 int nHeightDest
, /* height of destination rectangle */
257 HDC hdcSrc
, /* handle to source DC */
258 int nXSrc
, /* x-coordinate of source upper-left corner */
259 int nYSrc
, /* y-coordinate of source upper-left corner */
260 DWORD dwRop
) /* raster operation code */
262 /* use patBlt for no source blt Like windows does */
263 if (!ROP_USES_SOURCE(dwRop
))
265 return PatBlt(hdcDest
, nXOriginDest
, nYOriginDest
, nWidthDest
, nHeightDest
, dwRop
);
268 return NtGdiBitBlt(hdcDest
, nXOriginDest
, nYOriginDest
, nWidthDest
, nHeightDest
, hdcSrc
, nXSrc
,
278 HDC hdcDest
, /* handle to destination DC */
279 int nXOriginDest
, /* x-coord of destination upper-left corner */
280 int nYOriginDest
, /* y-coord of destination upper-left corner */
281 int nWidthDest
, /* width of destination rectangle */
282 int nHeightDest
, /* height of destination rectangle */
283 HDC hdcSrc
, /* handle to source DC */
284 int nXOriginSrc
, /* x-coord of source upper-left corner */
285 int nYOriginSrc
, /* y-coord of source upper-left corner */
286 int nWidthSrc
, /* width of source rectangle */
287 int nHeightSrc
, /* height of source rectangle */
288 DWORD dwRop
) /* raster operation code */
291 if ((nWidthDest
!= nWidthSrc
) || (nHeightDest
!= nHeightSrc
))
293 return NtGdiStretchBlt(hdcDest
, nXOriginDest
, nYOriginDest
, nWidthDest
, nHeightDest
, hdcSrc
,
294 nXOriginSrc
, nYOriginSrc
, nWidthSrc
, nHeightSrc
, dwRop
, 0);
297 return NtGdiBitBlt(hdcDest
, nXOriginDest
, nYOriginDest
, nWidthDest
, nHeightDest
, hdcSrc
,
298 nXOriginSrc
, nYOriginSrc
, dwRop
, 0, 0);
311 CONST VOID
* pUnsafeBits
)
315 return NtGdiCreateBitmap(Width
, Height
, Planes
, BitsPixel
, (LPBYTE
) pUnsafeBits
);
319 /* Return 1x1 bitmap */
320 return GetStockObject(DEFAULT_BITMAP
);
329 CreateBitmapIndirect(
332 HBITMAP bitmap
= NULL
;
334 /* Note windows xp/2003 does not check if pbm is NULL or not */
335 if ((pbm
->bmWidthBytes
!= 0) && (!(pbm
->bmWidthBytes
& 1)))
338 bitmap
= CreateBitmap(pbm
->bmWidth
, pbm
->bmHeight
, pbm
->bmPlanes
, pbm
->bmBitsPixel
,
343 SetLastError(ERROR_INVALID_PARAMETER
);
351 CreateDiscardableBitmap(
356 return CreateCompatibleBitmap(hDC
, Width
, Height
);
361 CreateCompatibleBitmap(
368 if (!GdiGetHandleUserData(hDC
, GDI_OBJECT_TYPE_DC
, (PVOID
) & pDc_Attr
))
371 if (!Width
|| !Height
)
372 return GetStockObject(DEFAULT_BITMAP
);
374 if (!(pDc_Attr
->ulDirty_
& DC_DIBSECTION
))
376 return NtGdiCreateCompatibleBitmap(hDC
, Width
, Height
);
384 BITMAPINFOHEADER bmih
;
385 RGBQUAD rgbquad
[256];
387 DIBSECTION
* pDIBs
= (DIBSECTION
*) &buffer
;
388 BITMAPINFO
* pbmi
= (BITMAPINFO
*) &buffer
.bmih
;
390 hBmp
= NtGdiGetDCObject(hDC
, GDI_OBJECT_TYPE_BITMAP
);
392 if (GetObjectA(hBmp
, sizeof(DIBSECTION
), pDIBs
) != sizeof(DIBSECTION
))
395 if (pDIBs
->dsBm
.bmBitsPixel
<= 8)
396 GetDIBColorTable(hDC
, 0, 256, buffer
.rgbquad
);
398 pDIBs
->dsBmih
.biWidth
= Width
;
399 pDIBs
->dsBmih
.biHeight
= Height
;
401 return CreateDIBSection(hDC
, pbmi
, DIB_RGB_COLORS
, NULL
, NULL
, 0);
420 if (!hDC
|| !GdiIsHandleValid((HGDIOBJ
) hDC
) || !lpbmi
)
422 GdiSetLastError(ERROR_INVALID_PARAMETER
);
426 cjBmpScanSize
= DIB_BitmapMaxBitsSize(lpbmi
, cScanLines
);
427 /* Caller must provide maximum size possible */
428 cjInfoSize
= DIB_BitmapInfoSize(lpbmi
, uUsage
, TRUE
);
432 if (lpbmi
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
))
434 if (lpbmi
->bmiHeader
.biCompression
== BI_JPEG
435 || lpbmi
->bmiHeader
.biCompression
== BI_PNG
)
437 SetLastError(ERROR_INVALID_PARAMETER
);
443 return NtGdiGetDIBitsInternal(hDC
, hbmp
, uStartScan
, cScanLines
, lpvBits
, lpbmi
, uUsage
,
444 cjBmpScanSize
, cjInfoSize
);
454 const BITMAPINFOHEADER
*Header
,
457 const BITMAPINFO
*Data
,
460 LONG width
, height
, compr
, dibsize
;
462 // PDC_ATTR pDc_Attr;
464 UINT cjBmpScanSize
= 0;
466 NTSTATUS Status
= STATUS_SUCCESS
;
468 /* Check for CBM_CREATDIB */
469 if (Init
& CBM_CREATDIB
)
471 /* CBM_CREATDIB needs Data. */
477 /* It only works with PAL or RGB */
478 if (ColorUse
> DIB_PAL_COLORS
)
480 GdiSetLastError(ERROR_INVALID_PARAMETER
);
485 /* Header is required */
488 GdiSetLastError(ERROR_INVALID_PARAMETER
);
492 /* Get the bitmap format and dimensions */
493 if (DIB_GetBitmapInfo(Header
, &width
, &height
, &planes
, &bpp
, &compr
, &dibsize
) == -1)
495 GdiSetLastError(ERROR_INVALID_PARAMETER
);
499 /* Check if the Compr is incompatible */
500 if ((compr
== BI_JPEG
) || (compr
== BI_PNG
) || (compr
== BI_BITFIELDS
))
503 /* Only DIB_RGB_COLORS (0), DIB_PAL_COLORS (1) and 2 are valid. */
504 if (ColorUse
> DIB_PAL_COLORS
+ 1)
506 GdiSetLastError(ERROR_INVALID_PARAMETER
);
510 /* Negative width is not allowed */
514 /* Top-down DIBs have a negative height. */
515 height
= abs(height
);
518 // GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
524 cjBmpScanSize
= GdiGetBitmapBitsSize((BITMAPINFO
*) Data
);
525 CalculateColorTableSize(&Data
->bmiHeader
, &ColorUse
, &InfoSize
);
526 InfoSize
+= Data
->bmiHeader
.biSize
;
528 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
530 Status
= _SEH2_GetExceptionCode();
535 if (!NT_SUCCESS(Status
))
537 GdiSetLastError(ERROR_INVALID_PARAMETER
);
541 DPRINT("pBMI %p, Size bpp %u, dibsize %d, Conv %u, BSS %u\n", Data
, bpp
, dibsize
, InfoSize
,
544 if (!width
|| !height
)
545 hBmp
= GetStockObject(DEFAULT_BITMAP
);
548 hBmp
= NtGdiCreateDIBitmapInternal(hDC
, width
, height
, Init
, (LPBYTE
) Bits
,
549 (LPBITMAPINFO
) Data
, ColorUse
, InfoSize
, cjBmpScanSize
, 0, 0);
565 CONST BITMAPINFO
*lpbmi
,
568 HDC hDCc
, SavehDC
, nhDC
;
569 DWORD dwWidth
, dwHeight
;
571 HPALETTE hPal
= NULL
;
575 if (!lpvBits
|| (GDI_HANDLE_GET_TYPE(hBitmap
) != GDI_OBJECT_TYPE_BITMAP
))
580 if (lpbmi
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
))
582 if (lpbmi
->bmiHeader
.biCompression
== BI_JPEG
583 || lpbmi
->bmiHeader
.biCompression
== BI_PNG
)
585 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
,
680 // Handle something other than a normal dc object.
681 if (GDI_HANDLE_GET_TYPE(hdc
) != GDI_OBJECT_TYPE_DC
)
683 if (GDI_HANDLE_GET_TYPE(hdc
) == GDI_OBJECT_TYPE_METADC
)
684 return MFDRV_SetDIBitsToDevice( hdc
,
698 PLDC pLDC
= GdiGetLDC(hdc
);
701 SetLastError(ERROR_INVALID_HANDLE
);
704 if (pLDC
->iType
== LDC_EMFLDC
)
706 return EMFDRV_SetDIBitsToDevice(hdc
,
723 cjBmpScanSize
= DIB_BitmapMaxBitsSize((LPBITMAPINFO
) lpbmi
, ScanLines
);
725 pvSafeBits
= RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize
);
730 RtlCopyMemory(pvSafeBits
, Bits
, cjBmpScanSize
);
732 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
740 // We don't die, we continue on with a allocated safe pointer to kernel
742 DPRINT1("SetDIBitsToDevice fail to read BitMapInfo: %p or Bits: %p & Size: %u\n",
743 pConvertedInfo
, Bits
, cjBmpScanSize
);
745 DPRINT("SetDIBitsToDevice Allocate Bits %u!!!\n", cjBmpScanSize
);
748 if (!GdiGetHandleUserData(hdc
, GDI_OBJECT_TYPE_DC
, (PVOID
) & pDc_Attr
))
750 SetLastError(ERROR_INVALID_PARAMETER
);
754 if ( !pDc_Attr || // DC is Public
755 ColorUse == DIB_PAL_COLORS ||
756 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
757 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
758 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
760 LinesCopied
= NtGdiSetDIBitsToDeviceInternal(hdc
, XDest
, YDest
, Width
, Height
, XSrc
, YSrc
,
761 StartScan
, ScanLines
, (LPBYTE
) pvSafeBits
, (LPBITMAPINFO
) pConvertedInfo
, ColorUse
,
762 cjBmpScanSize
, ConvertedInfoSize
,
766 if (Bits
!= pvSafeBits
)
767 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits
);
768 if (lpbmi
!= pConvertedInfo
)
769 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);
790 CONST BITMAPINFO
*lpBitsInfo
,
796 PBITMAPINFO pConvertedInfo
= NULL
;
797 UINT ConvertedInfoSize
= 0;
799 UINT cjBmpScanSize
= 0;
800 PVOID pvSafeBits
= NULL
;
803 DPRINT("StretchDIBits %p : %p : %u\n", lpBits
, lpBitsInfo
, iUsage
);
805 // Handle something other than a normal dc object.
806 if (GDI_HANDLE_GET_TYPE(hdc
) != GDI_OBJECT_TYPE_DC
)
808 if (GDI_HANDLE_GET_TYPE(hdc
) == GDI_OBJECT_TYPE_METADC
)
809 return MFDRV_StretchBlt( hdc
,
824 PLDC pLDC
= GdiGetLDC(hdc
);
827 SetLastError(ERROR_INVALID_HANDLE
);
830 if (pLDC
->iType
== LDC_EMFLDC
)
832 return EMFDRV_StretchBlt(hdc
,
850 pConvertedInfo
= ConvertBitmapInfo(lpBitsInfo
, iUsage
, &ConvertedInfoSize
,
857 cjBmpScanSize
= GdiGetBitmapBitsSize((BITMAPINFO
*) pConvertedInfo
);
861 pvSafeBits
= RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize
);
866 RtlCopyMemory(pvSafeBits
, lpBits
, cjBmpScanSize
);
868 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
876 // We don't die, we continue on with a allocated safe pointer to kernel
878 DPRINT1("StretchDIBits fail to read BitMapInfo: %p or Bits: %p & Size: %u\n",
879 pConvertedInfo
, lpBits
, cjBmpScanSize
);
881 DPRINT("StretchDIBits Allocate Bits %u!!!\n", cjBmpScanSize
);
885 if (!GdiGetHandleUserData(hdc
, GDI_OBJECT_TYPE_DC
, (PVOID
) & pDc_Attr
))
887 SetLastError(ERROR_INVALID_PARAMETER
);
892 iUsage == DIB_PAL_COLORS ||
893 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
894 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
895 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
897 LinesCopied
= NtGdiStretchDIBitsInternal(hdc
, XDest
, YDest
, nDestWidth
, nDestHeight
, XSrc
,
898 YSrc
, nSrcWidth
, nSrcHeight
, pvSafeBits
, pConvertedInfo
, (DWORD
) iUsage
, dwRop
,
899 ConvertedInfoSize
, cjBmpScanSize
,
903 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits
);
904 if (lpBitsInfo
!= pConvertedInfo
)
905 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);