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
16 INT FASTCALL
DIB_BitmapInfoSize(const BITMAPINFO
* info
, WORD coloruse
, BOOL max
)
18 unsigned int colors
, size
, masks
= 0;
20 if (info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
22 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
23 colors
= (core
->bcBitCount
<= 8) ? 1 << core
->bcBitCount
: 0;
24 return sizeof(BITMAPCOREHEADER
) + colors
*
25 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBTRIPLE
) : sizeof(WORD
));
27 else /* assume BITMAPINFOHEADER */
29 colors
= max
? 1 << info
->bmiHeader
.biBitCount
: info
->bmiHeader
.biClrUsed
;
30 if (colors
> 256) colors
= 256;
31 if (!colors
&& (info
->bmiHeader
.biBitCount
<= 8))
32 colors
= 1 << info
->bmiHeader
.biBitCount
;
33 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
) masks
= 3;
34 size
= max( info
->bmiHeader
.biSize
, sizeof(BITMAPINFOHEADER
) + masks
* sizeof(DWORD
) );
35 return size
+ colors
* ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBQUAD
) : sizeof(WORD
));
40 * Return the full scan size for a bitmap.
42 * Based on Wine, Utils.c and Windows Graphics Prog pg 595, SDK amvideo.h.
46 DIB_BitmapMaxBitsSize( PBITMAPINFO Info
, UINT ScanLines
)
52 if ( Info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
54 PBITMAPCOREHEADER Core
= (PBITMAPCOREHEADER
)Info
;
55 Ret
= WIDTH_BYTES_ALIGN32(Core
->bcWidth
* Core
->bcPlanes
, Core
->bcBitCount
) * ScanLines
;
57 else /* assume BITMAPINFOHEADER */
59 if (!(Info
->bmiHeader
.biCompression
) || (Info
->bmiHeader
.biCompression
== BI_BITFIELDS
))
61 Ret
= WIDTH_BYTES_ALIGN32(Info
->bmiHeader
.biWidth
* Info
->bmiHeader
.biPlanes
, Info
->bmiHeader
.biBitCount
) * ScanLines
;
65 Ret
= Info
->bmiHeader
.biSizeImage
;
72 * DIB_GetBitmapInfo is complete copy of wine cvs 2/9-2006
73 * from file dib.c from gdi32.dll or orginal version
74 * did not calc the info right for some headers.
78 DIB_GetBitmapInfo(const BITMAPINFOHEADER
*header
,
86 if (header
->biSize
== sizeof(BITMAPCOREHEADER
))
88 BITMAPCOREHEADER
*core
= (BITMAPCOREHEADER
*)header
;
89 *width
= core
->bcWidth
;
90 *height
= core
->bcHeight
;
91 *planes
= core
->bcPlanes
;
92 *bpp
= core
->bcBitCount
;
98 if (header
->biSize
== sizeof(BITMAPINFOHEADER
))
100 *width
= header
->biWidth
;
101 *height
= header
->biHeight
;
102 *planes
= header
->biPlanes
;
103 *bpp
= header
->biBitCount
;
104 *compr
= header
->biCompression
;
105 *size
= header
->biSizeImage
;
109 if (header
->biSize
== sizeof(BITMAPV4HEADER
))
111 BITMAPV4HEADER
*v4hdr
= (BITMAPV4HEADER
*)header
;
112 *width
= v4hdr
->bV4Width
;
113 *height
= v4hdr
->bV4Height
;
114 *planes
= v4hdr
->bV4Planes
;
115 *bpp
= v4hdr
->bV4BitCount
;
116 *compr
= v4hdr
->bV4V4Compression
;
117 *size
= v4hdr
->bV4SizeImage
;
121 if (header
->biSize
== sizeof(BITMAPV5HEADER
))
123 BITMAPV5HEADER
*v5hdr
= (BITMAPV5HEADER
*)header
;
124 *width
= v5hdr
->bV5Width
;
125 *height
= v5hdr
->bV5Height
;
126 *planes
= v5hdr
->bV5Planes
;
127 *bpp
= v5hdr
->bV5BitCount
;
128 *compr
= v5hdr
->bV5Compression
;
129 *size
= v5hdr
->bV5SizeImage
;
132 DPRINT("(%ld): wrong size for header\n", header
->biSize
);
141 GdiGetBitmapBitsSize(BITMAPINFO
*lpbmi
)
145 if (!lpbmi
) return 0;
147 if ( lpbmi
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
149 PBITMAPCOREHEADER Core
= (PBITMAPCOREHEADER
)lpbmi
;
150 Ret
= WIDTH_BYTES_ALIGN32(Core
->bcWidth
* Core
->bcPlanes
, Core
->bcBitCount
) * Core
->bcHeight
;
152 else /* assume BITMAPINFOHEADER */
154 if (!(lpbmi
->bmiHeader
.biCompression
) || (lpbmi
->bmiHeader
.biCompression
== BI_BITFIELDS
))
156 Ret
= WIDTH_BYTES_ALIGN32(lpbmi
->bmiHeader
.biWidth
* lpbmi
->bmiHeader
.biPlanes
, lpbmi
->bmiHeader
.biBitCount
) * abs(lpbmi
->bmiHeader
.biHeight
);
160 Ret
= lpbmi
->bmiHeader
.biSizeImage
;
172 CONST BITMAPINFO
*BitmapInfo
,
178 PBITMAPINFO pConvertedInfo
;
179 UINT ConvertedInfoSize
;
180 HBITMAP hBitmap
= NULL
;
183 pConvertedInfo
= ConvertBitmapInfo(BitmapInfo
, Usage
,
184 &ConvertedInfoSize
, FALSE
);
187 // Verify header due to converted may == info.
188 if ( pConvertedInfo
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
) )
190 if ( pConvertedInfo
->bmiHeader
.biCompression
== BI_JPEG
||
191 pConvertedInfo
->bmiHeader
.biCompression
== BI_PNG
)
193 SetLastError(ERROR_INVALID_PARAMETER
);
198 hBitmap
= NtGdiCreateDIBSection( hDC
,
207 if (BitmapInfo
!= pConvertedInfo
)
208 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);
216 if (Bits
) *Bits
= bmBits
;
227 BitBlt(HDC hdcDest
, /* handle to destination DC */
228 int nXOriginDest
, /* x-coord of destination upper-left corner */
229 int nYOriginDest
, /* y-coord of destination upper-left corner */
230 int nWidthDest
, /* width of destination rectangle */
231 int nHeightDest
, /* height of destination rectangle */
232 HDC hdcSrc
, /* handle to source DC */
233 int nXSrc
, /* x-coordinate of source upper-left corner */
234 int nYSrc
, /* y-coordinate of source upper-left corner */
235 DWORD dwRop
) /* raster operation code */
237 /* use patBlt for no source blt Like windows does */
238 if (!ROP_USES_SOURCE(dwRop
))
240 return PatBlt(hdcDest
, nXOriginDest
, nYOriginDest
, nWidthDest
, nHeightDest
, dwRop
);
243 return NtGdiBitBlt(hdcDest
,
261 HDC hdcDest
, /* handle to destination DC */
262 int nXOriginDest
, /* x-coord of destination upper-left corner */
263 int nYOriginDest
, /* y-coord of destination upper-left corner */
264 int nWidthDest
, /* width of destination rectangle */
265 int nHeightDest
, /* height of destination rectangle */
266 HDC hdcSrc
, /* handle to source DC */
267 int nXOriginSrc
, /* x-coord of source upper-left corner */
268 int nYOriginSrc
, /* y-coord of source upper-left corner */
269 int nWidthSrc
, /* width of source rectangle */
270 int nHeightSrc
, /* height of source rectangle */
271 DWORD dwRop
) /* raster operation code */
274 if ((nWidthDest
!= nWidthSrc
) || (nHeightDest
!= nHeightSrc
))
276 return NtGdiStretchBlt(hdcDest
, nXOriginDest
, nYOriginDest
, nWidthDest
,
277 nHeightDest
, hdcSrc
, nXOriginSrc
, nYOriginSrc
,
278 nWidthSrc
, nHeightSrc
, dwRop
, 0);
281 return NtGdiBitBlt(hdcDest
, nXOriginDest
, nYOriginDest
, nWidthDest
,
282 nHeightDest
, hdcSrc
, nXOriginSrc
, nYOriginSrc
, dwRop
, 0, 0);
289 CreateBitmap(INT Width
,
293 CONST VOID
* pUnsafeBits
)
297 return NtGdiCreateBitmap(Width
, Height
, Planes
, BitsPixel
, (LPBYTE
) pUnsafeBits
);
301 /* Return 1x1 bitmap */
302 return GetStockObject(DEFAULT_BITMAP
);
310 CreateBitmapIndirect(const BITMAP
*pbm
)
312 HBITMAP bitmap
= NULL
;
314 /* Note windows xp/2003 does not check if pbm is NULL or not */
315 if ( (pbm
->bmWidthBytes
!= 0) &&
316 (!(pbm
->bmWidthBytes
& 1)) )
320 bitmap
= CreateBitmap(pbm
->bmWidth
,
328 SetLastError(ERROR_INVALID_PARAMETER
);
335 CreateDiscardableBitmap(
340 return CreateCompatibleBitmap(hDC
, Width
, Height
);
345 CreateCompatibleBitmap(
352 if (!GdiGetHandleUserData(hDC
, GDI_OBJECT_TYPE_DC
, (PVOID
)&pDc_Attr
))
355 if ( !Width
|| !Height
)
356 return GetStockObject(DEFAULT_BITMAP
);
358 if (!(pDc_Attr
->ulDirty_
& DC_DIBSECTION
))
360 return NtGdiCreateCompatibleBitmap(hDC
, Width
, Height
);
368 BITMAPINFOHEADER bmih
;
369 RGBQUAD rgbquad
[256];
371 DIBSECTION
* pDIBs
= (DIBSECTION
*)&buffer
;
372 BITMAPINFO
* pbmi
= (BITMAPINFO
*)&buffer
.bmih
;
374 hBmp
= NtGdiGetDCObject(hDC
, GDI_OBJECT_TYPE_BITMAP
);
376 if ( GetObjectA(hBmp
, sizeof(DIBSECTION
), pDIBs
) != sizeof(DIBSECTION
) )
379 if ( pDIBs
->dsBm
.bmBitsPixel
<= 8 )
380 GetDIBColorTable(hDC
, 0, 256, buffer
.rgbquad
);
382 pDIBs
->dsBmih
.biWidth
= Width
;
383 pDIBs
->dsBmih
.biHeight
= Height
;
385 return CreateDIBSection(hDC
, pbmi
, DIB_RGB_COLORS
, NULL
, NULL
, 0);
405 if (!hDC
|| !GdiIsHandleValid((HGDIOBJ
)hDC
) || !lpbmi
)
407 GdiSetLastError(ERROR_INVALID_PARAMETER
);
411 cjBmpScanSize
= DIB_BitmapMaxBitsSize(lpbmi
, cScanLines
);
412 /* Caller must provide maximum size possible */
413 cjInfoSize
= DIB_BitmapInfoSize(lpbmi
, uUsage
, TRUE
);
417 if ( lpbmi
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
) )
419 if ( lpbmi
->bmiHeader
.biCompression
== BI_JPEG
||
420 lpbmi
->bmiHeader
.biCompression
== BI_PNG
)
422 SetLastError(ERROR_INVALID_PARAMETER
);
428 return NtGdiGetDIBitsInternal(hDC
,
444 CreateDIBitmap( HDC hDC
,
445 const BITMAPINFOHEADER
*Header
,
448 const BITMAPINFO
*Data
,
451 LONG width
, height
, compr
, dibsize
;
453 // PDC_ATTR pDc_Attr;
455 UINT cjBmpScanSize
= 0;
457 NTSTATUS Status
= STATUS_SUCCESS
;
459 /* Check for CBM_CREATDIB */
460 if (Init
& CBM_CREATDIB
)
462 /* CBM_CREATDIB needs Data. */
468 /* It only works with PAL or RGB */
469 if (ColorUse
> DIB_PAL_COLORS
)
471 GdiSetLastError(ERROR_INVALID_PARAMETER
);
476 /* Header is required */
479 GdiSetLastError(ERROR_INVALID_PARAMETER
);
483 /* Get the bitmap format and dimensions */
484 if (DIB_GetBitmapInfo(Header
, &width
, &height
, &planes
, &bpp
, &compr
, &dibsize
) == -1)
486 GdiSetLastError(ERROR_INVALID_PARAMETER
);
490 /* Check if the Compr is incompatible */
491 if ((compr
== BI_JPEG
) || (compr
== BI_PNG
) || (compr
== BI_BITFIELDS
)) return 0;
493 /* Only DIB_RGB_COLORS (0), DIB_PAL_COLORS (1) and 2 are valid. */
494 if (ColorUse
> DIB_PAL_COLORS
+ 1)
496 GdiSetLastError(ERROR_INVALID_PARAMETER
);
500 /* Negative width is not allowed */
501 if (width
< 0) return 0;
503 /* Top-down DIBs have a negative height. */
504 height
= abs(height
);
507 // GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
513 cjBmpScanSize
= GdiGetBitmapBitsSize((BITMAPINFO
*)Data
);
514 CalculateColorTableSize(&Data
->bmiHeader
, &ColorUse
, &InfoSize
);
515 InfoSize
+= Data
->bmiHeader
.biSize
;
517 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
519 Status
= _SEH2_GetExceptionCode();
524 if(!NT_SUCCESS(Status
))
526 GdiSetLastError(ERROR_INVALID_PARAMETER
);
530 DPRINT("pBMI %x, Size bpp %d, dibsize %d, Conv %d, BSS %d\n", Data
,bpp
,dibsize
,InfoSize
,cjBmpScanSize
);
532 if ( !width
|| !height
)
533 hBmp
= GetStockObject(DEFAULT_BITMAP
);
536 hBmp
= NtGdiCreateDIBitmapInternal(hDC
,
561 CONST BITMAPINFO
*lpbmi
,
564 HDC hDCc
, SavehDC
, nhDC
;
565 DWORD dwWidth
, dwHeight
;
567 HPALETTE hPal
= NULL
;
571 if ( !lpvBits
|| (GDI_HANDLE_GET_TYPE(hBitmap
) != GDI_OBJECT_TYPE_BITMAP
) )
576 if ( lpbmi
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
) )
578 if ( lpbmi
->bmiHeader
.biCompression
== BI_JPEG
|| lpbmi
->bmiHeader
.biCompression
== BI_PNG
)
580 SetLastError(ERROR_INVALID_PARAMETER
);
586 hDCc
= NtGdiGetDCforBitmap(hBitmap
); // hDC can be NULL, so, get it from the bitmap.
588 if ( !hDCc
) // No DC associated with bitmap, Clone or Create one.
590 nhDC
= CreateCompatibleDC(hDC
);
591 if ( !nhDC
) return 0;
595 else if ( !SaveDC(hDCc
) )
598 hOldBitmap
= SelectObject(SavehDC
, hBitmap
);
603 hPal
= SelectPalette(SavehDC
, (HPALETTE
)GetCurrentObject(hDC
, OBJ_PAL
), FALSE
);
605 if ( lpbmi
->bmiHeader
.biSize
< sizeof(BITMAPINFOHEADER
))
607 PBITMAPCOREINFO pbci
= (PBITMAPCOREINFO
) lpbmi
;
608 dwWidth
= pbci
->bmciHeader
.bcWidth
;
609 dwHeight
= pbci
->bmciHeader
.bcHeight
;
613 dwWidth
= lpbmi
->bmiHeader
.biWidth
;
614 dwHeight
= abs(lpbmi
->bmiHeader
.biHeight
);
617 LinesCopied
= SetDIBitsToDevice(SavehDC
,
630 if ( hDC
) SelectPalette(SavehDC
, hPal
, FALSE
);
632 SelectObject(SavehDC
, hOldBitmap
);
638 RestoreDC(SavehDC
, -1);
660 CONST BITMAPINFO
*lpbmi
,
664 PBITMAPINFO pConvertedInfo
;
665 UINT ConvertedInfoSize
;
667 UINT cjBmpScanSize
= 0;
669 PVOID pvSafeBits
= (PVOID
)Bits
;
671 if ( !ScanLines
|| !lpbmi
|| !Bits
)
674 if ( ColorUse
&& ColorUse
!= DIB_PAL_COLORS
&& ColorUse
!= DIB_PAL_COLORS
+1 )
677 pConvertedInfo
= ConvertBitmapInfo(lpbmi
, ColorUse
,
678 &ConvertedInfoSize
, FALSE
);
683 // Handle something other than a normal dc object.
684 if (GDI_HANDLE_GET_TYPE(hdc
) != GDI_OBJECT_TYPE_DC
)
686 if (GDI_HANDLE_GET_TYPE(hdc
) == GDI_OBJECT_TYPE_METADC
)
687 return MFDRV_SetDIBitsToDevice( hdc
,
701 PLDC pLDC
= GdiGetLDC(hdc
);
704 SetLastError(ERROR_INVALID_HANDLE
);
707 if (pLDC
->iType
== LDC_EMFLDC
)
709 return EMFDRV_SetDIBitsToDevice(hdc
,
726 cjBmpScanSize
= DIB_BitmapMaxBitsSize((LPBITMAPINFO
)lpbmi
, ScanLines
);
728 pvSafeBits
= RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize
);
733 RtlCopyMemory( pvSafeBits
, Bits
, cjBmpScanSize
);
735 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
743 // We don't die, we continue on with a allocated safe pointer to kernel
745 DPRINT1("SetDIBitsToDevice fail to read BitMapInfo: %x or Bits: %x & Size: %d\n",pConvertedInfo
,Bits
,cjBmpScanSize
);
747 DPRINT("SetDIBitsToDevice Allocate Bits %d!!!\n", cjBmpScanSize
);
750 if (!GdiGetHandleUserData(hdc
, GDI_OBJECT_TYPE_DC
, (PVOID
)&pDc_Attr
))
752 SetLastError(ERROR_INVALID_PARAMETER
);
756 if ( !pDc_Attr || // DC is Public
757 ColorUse == DIB_PAL_COLORS ||
758 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
759 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
760 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
762 LinesCopied
= NtGdiSetDIBitsToDeviceInternal( hdc
,
772 (LPBITMAPINFO
)pConvertedInfo
,
779 if ( Bits
!= pvSafeBits
)
780 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits
);
781 if (lpbmi
!= pConvertedInfo
)
782 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);
793 StretchDIBits(HDC hdc
,
803 CONST BITMAPINFO
*lpBitsInfo
,
809 PBITMAPINFO pConvertedInfo
= NULL
;
810 UINT ConvertedInfoSize
= 0;
812 UINT cjBmpScanSize
= 0;
813 PVOID pvSafeBits
= NULL
;
816 DPRINT("StretchDIBits %x : %x : %d\n", lpBits
, lpBitsInfo
, iUsage
);
818 // Handle something other than a normal dc object.
819 if (GDI_HANDLE_GET_TYPE(hdc
) != GDI_OBJECT_TYPE_DC
)
821 if (GDI_HANDLE_GET_TYPE(hdc
) == GDI_OBJECT_TYPE_METADC
)
822 return MFDRV_StretchBlt( hdc
,
837 PLDC pLDC
= GdiGetLDC(hdc
);
840 SetLastError(ERROR_INVALID_HANDLE
);
843 if (pLDC
->iType
== LDC_EMFLDC
)
845 return EMFDRV_StretchBlt(hdc
,
863 pConvertedInfo
= ConvertBitmapInfo(lpBitsInfo
, iUsage
,
864 &ConvertedInfoSize
, FALSE
);
870 cjBmpScanSize
= GdiGetBitmapBitsSize((BITMAPINFO
*)pConvertedInfo
);
874 pvSafeBits
= RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize
);
879 RtlCopyMemory( pvSafeBits
, lpBits
, cjBmpScanSize
);
881 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
889 // We don't die, we continue on with a allocated safe pointer to kernel
891 DPRINT1("StretchDIBits fail to read BitMapInfo: %x or Bits: %x & Size: %d\n",pConvertedInfo
,lpBits
,cjBmpScanSize
);
893 DPRINT("StretchDIBits Allocate Bits %d!!!\n", cjBmpScanSize
);
897 if (!GdiGetHandleUserData(hdc
, GDI_OBJECT_TYPE_DC
, (PVOID
)&pDc_Attr
))
899 SetLastError(ERROR_INVALID_PARAMETER
);
904 iUsage == DIB_PAL_COLORS ||
905 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
906 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
907 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
909 LinesCopied
= NtGdiStretchDIBitsInternal( hdc
,
927 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits
);
928 if (lpBitsInfo
!= pConvertedInfo
)
929 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);