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
);
484 /* Use the header from the data */
485 Header
= &Data
->bmiHeader
;
488 /* Header is required */
491 GdiSetLastError(ERROR_INVALID_PARAMETER
);
495 /* Get the bitmap format and dimensions */
496 if (DIB_GetBitmapInfo(Header
, &width
, &height
, &planes
, &bpp
, &compr
, &dibsize
) == -1)
498 GdiSetLastError(ERROR_INVALID_PARAMETER
);
502 /* Check if the Compr is incompatible */
503 if ((compr
== BI_JPEG
) || (compr
== BI_PNG
) || (compr
== BI_BITFIELDS
))
506 /* Only DIB_RGB_COLORS (0), DIB_PAL_COLORS (1) and 2 are valid. */
507 if (ColorUse
> DIB_PAL_COLORS
+ 1)
509 GdiSetLastError(ERROR_INVALID_PARAMETER
);
513 /* If some Bits are given, only DIB_PAL_COLORS and DIB_RGB_COLORS are valid */
514 if (Bits
&& (ColorUse
> DIB_PAL_COLORS
))
516 GdiSetLastError(ERROR_INVALID_PARAMETER
);
520 /* Negative width is not allowed */
524 /* Top-down DIBs have a negative height. */
525 height
= abs(height
);
528 // GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
534 cjBmpScanSize
= GdiGetBitmapBitsSize((BITMAPINFO
*) Data
);
535 CalculateColorTableSize(&Data
->bmiHeader
, &ColorUse
, &InfoSize
);
536 InfoSize
+= Data
->bmiHeader
.biSize
;
538 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
540 Status
= _SEH2_GetExceptionCode();
545 if (!NT_SUCCESS(Status
))
547 GdiSetLastError(ERROR_INVALID_PARAMETER
);
551 DPRINT("pBMI %p, Size bpp %u, dibsize %d, Conv %u, BSS %u\n", Data
, bpp
, dibsize
, InfoSize
,
554 if (!width
|| !height
)
555 hBmp
= GetStockObject(DEFAULT_BITMAP
);
558 hBmp
= NtGdiCreateDIBitmapInternal(hDC
, width
, height
, Init
, (LPBYTE
) Bits
,
559 (LPBITMAPINFO
) Data
, ColorUse
, InfoSize
, cjBmpScanSize
, 0, 0);
575 CONST BITMAPINFO
*lpbmi
,
578 HDC hDCc
, SavehDC
, nhDC
;
579 DWORD dwWidth
, dwHeight
;
581 HPALETTE hPal
= NULL
;
585 if (!lpvBits
|| (GDI_HANDLE_GET_TYPE(hBitmap
) != GDI_OBJECT_TYPE_BITMAP
))
590 if (lpbmi
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
))
592 if (lpbmi
->bmiHeader
.biCompression
== BI_JPEG
593 || lpbmi
->bmiHeader
.biCompression
== BI_PNG
)
595 SetLastError(ERROR_INVALID_PARAMETER
);
601 hDCc
= NtGdiGetDCforBitmap(hBitmap
); // hDC can be NULL, so, get it from the bitmap.
603 if (!hDCc
) // No DC associated with bitmap, Clone or Create one.
605 nhDC
= CreateCompatibleDC(hDC
);
611 else if (!SaveDC(hDCc
))
614 hOldBitmap
= SelectObject(SavehDC
, hBitmap
);
619 hPal
= SelectPalette(SavehDC
, (HPALETTE
) GetCurrentObject(hDC
, OBJ_PAL
), FALSE
);
621 if (lpbmi
->bmiHeader
.biSize
< sizeof(BITMAPINFOHEADER
))
623 PBITMAPCOREINFO pbci
= (PBITMAPCOREINFO
) lpbmi
;
624 dwWidth
= pbci
->bmciHeader
.bcWidth
;
625 dwHeight
= pbci
->bmciHeader
.bcHeight
;
629 dwWidth
= lpbmi
->bmiHeader
.biWidth
;
630 dwHeight
= abs(lpbmi
->bmiHeader
.biHeight
);
633 LinesCopied
= SetDIBitsToDevice(SavehDC
, 0, 0, dwWidth
, dwHeight
, 0, 0, uStartScan
,
634 cScanLines
, (void *) lpvBits
, (LPBITMAPINFO
) lpbmi
, fuColorUse
);
637 SelectPalette(SavehDC
, hPal
, FALSE
);
639 SelectObject(SavehDC
, hOldBitmap
);
645 RestoreDC(SavehDC
, -1);
667 CONST BITMAPINFO
*lpbmi
,
671 PBITMAPINFO pConvertedInfo
;
672 UINT ConvertedInfoSize
;
674 UINT cjBmpScanSize
= 0;
676 PVOID pvSafeBits
= (PVOID
) Bits
;
678 if (!ScanLines
|| !lpbmi
|| !Bits
)
681 if (ColorUse
&& ColorUse
!= DIB_PAL_COLORS
&& ColorUse
!= DIB_PAL_COLORS
+ 1)
684 pConvertedInfo
= ConvertBitmapInfo(lpbmi
, ColorUse
, &ConvertedInfoSize
, FALSE
);
689 // Handle something other than a normal dc object.
690 if (GDI_HANDLE_GET_TYPE(hdc
) != GDI_OBJECT_TYPE_DC
)
692 if (GDI_HANDLE_GET_TYPE(hdc
) == GDI_OBJECT_TYPE_METADC
)
693 return MFDRV_SetDIBitsToDevice( hdc
,
707 PLDC pLDC
= GdiGetLDC(hdc
);
710 SetLastError(ERROR_INVALID_HANDLE
);
713 if (pLDC
->iType
== LDC_EMFLDC
)
715 return EMFDRV_SetDIBitsToDevice(hdc
,
733 if ((pConvertedInfo
->bmiHeader
.biCompression
== BI_RLE8
) ||
734 (pConvertedInfo
->bmiHeader
.biCompression
== BI_RLE4
))
736 /* For compressed data, we must set the whole thing */
738 ScanLines
= pConvertedInfo
->bmiHeader
.biHeight
;
741 cjBmpScanSize
= DIB_BitmapMaxBitsSize((LPBITMAPINFO
) lpbmi
, ScanLines
);
743 pvSafeBits
= RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize
);
748 RtlCopyMemory(pvSafeBits
, Bits
, cjBmpScanSize
);
750 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
758 // We don't die, we continue on with a allocated safe pointer to kernel
760 DPRINT1("SetDIBitsToDevice fail to read BitMapInfo: %p or Bits: %p & Size: %u\n",
761 pConvertedInfo
, Bits
, cjBmpScanSize
);
763 DPRINT("SetDIBitsToDevice Allocate Bits %u!!!\n", cjBmpScanSize
);
766 if (!GdiGetHandleUserData(hdc
, GDI_OBJECT_TYPE_DC
, (PVOID
) & pDc_Attr
))
768 SetLastError(ERROR_INVALID_PARAMETER
);
772 if ( !pDc_Attr || // DC is Public
773 ColorUse == DIB_PAL_COLORS ||
774 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
775 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
776 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
778 LinesCopied
= NtGdiSetDIBitsToDeviceInternal(hdc
, XDest
, YDest
, Width
, Height
, XSrc
, YSrc
,
779 StartScan
, ScanLines
, (LPBYTE
) pvSafeBits
, (LPBITMAPINFO
) pConvertedInfo
, ColorUse
,
780 cjBmpScanSize
, ConvertedInfoSize
,
784 if (Bits
!= pvSafeBits
)
785 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits
);
786 if (lpbmi
!= pConvertedInfo
)
787 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);
808 CONST BITMAPINFO
*lpBitsInfo
,
814 PBITMAPINFO pConvertedInfo
= NULL
;
815 UINT ConvertedInfoSize
= 0;
817 UINT cjBmpScanSize
= 0;
818 PVOID pvSafeBits
= NULL
;
821 DPRINT("StretchDIBits %p : %p : %u\n", lpBits
, lpBitsInfo
, iUsage
);
823 // Handle something other than a normal dc object.
824 if (GDI_HANDLE_GET_TYPE(hdc
) != GDI_OBJECT_TYPE_DC
)
826 if (GDI_HANDLE_GET_TYPE(hdc
) == GDI_OBJECT_TYPE_METADC
)
827 return MFDRV_StretchBlt( hdc
,
842 PLDC pLDC
= GdiGetLDC(hdc
);
845 SetLastError(ERROR_INVALID_HANDLE
);
848 if (pLDC
->iType
== LDC_EMFLDC
)
850 return EMFDRV_StretchBlt(hdc
,
868 pConvertedInfo
= ConvertBitmapInfo(lpBitsInfo
, iUsage
, &ConvertedInfoSize
,
875 cjBmpScanSize
= GdiGetBitmapBitsSize((BITMAPINFO
*) pConvertedInfo
);
879 pvSafeBits
= RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize
);
884 RtlCopyMemory(pvSafeBits
, lpBits
, cjBmpScanSize
);
886 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
894 // We don't die, we continue on with a allocated safe pointer to kernel
896 DPRINT1("StretchDIBits fail to read BitMapInfo: %p or Bits: %p & Size: %u\n",
897 pConvertedInfo
, lpBits
, cjBmpScanSize
);
899 DPRINT("StretchDIBits Allocate Bits %u!!!\n", cjBmpScanSize
);
903 if (!GdiGetHandleUserData(hdc
, GDI_OBJECT_TYPE_DC
, (PVOID
) & pDc_Attr
))
905 SetLastError(ERROR_INVALID_PARAMETER
);
910 iUsage == DIB_PAL_COLORS ||
911 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
912 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
913 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
915 LinesCopied
= NtGdiStretchDIBitsInternal(hdc
, XDest
, YDest
, nDestWidth
, nDestHeight
, XSrc
,
916 YSrc
, nSrcWidth
, nSrcHeight
, pvSafeBits
, pConvertedInfo
, (DWORD
) iUsage
, dwRop
,
917 ConvertedInfoSize
, cjBmpScanSize
,
921 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits
);
922 if (lpBitsInfo
!= pConvertedInfo
)
923 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);