7 * Return the full scan size for a bitmap.
9 * Based on Wine, Utils.c and Windows Graphics Prog pg 595, SDK amvideo.h.
13 DIB_BitmapMaxBitsSize( PBITMAPINFO Info
, UINT ScanLines
)
19 if (Info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
21 PBITMAPCOREHEADER Core
= (PBITMAPCOREHEADER
)Info
;
22 MaxBits
= Core
->bcBitCount
* Core
->bcPlanes
* Core
->bcWidth
;
24 else /* assume BITMAPINFOHEADER */
26 if ((Info
->bmiHeader
.biCompression
) && (Info
->bmiHeader
.biCompression
!= BI_BITFIELDS
))
27 return Info
->bmiHeader
.biSizeImage
;
28 // Planes are over looked by Yuan. I guess assumed always 1.
29 MaxBits
= Info
->bmiHeader
.biBitCount
* Info
->bmiHeader
.biPlanes
* Info
->bmiHeader
.biWidth
;
31 MaxBits
= ((MaxBits
+ 31) & ~31 ) / 8; // From Yuan, ScanLineSize = (Width * bitcount + 31)/32
32 return (MaxBits
* ScanLines
); // ret the full Size.
37 DIB_BitmapBitsSize( PBITMAPINFO Info
)
43 if ( Info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
45 PBITMAPCOREHEADER Core
= (PBITMAPCOREHEADER
)Info
;
46 Ret
= Core
->bcHeight
*
47 ((Core
->bcWidth
* Core
->bcPlanes
* Core
->bcBitCount
+ 31) & ~31 ) / 8;
49 else /* assume BITMAPINFOHEADER */
51 if ((Info
->bmiHeader
.biCompression
) &&
52 (Info
->bmiHeader
.biCompression
!= BI_BITFIELDS
))
53 return Info
->bmiHeader
.biSizeImage
;
54 // Make Height positive always....
55 Ret
= abs(Info
->bmiHeader
.biHeight
) *
56 ((Info
->bmiHeader
.biWidth
* Info
->bmiHeader
.biPlanes
* Info
->bmiHeader
.biBitCount
+ 31) & ~31 ) / 8;
63 * DIB_GetBitmapInfo is complete copy of wine cvs 2/9-2006
64 * from file dib.c from gdi32.dll or orginal version
65 * did not calc the info right for some headers.
69 DIB_GetBitmapInfo(const BITMAPINFOHEADER
*header
,
78 if (header
->biSize
== sizeof(BITMAPCOREHEADER
))
80 BITMAPCOREHEADER
*core
= (BITMAPCOREHEADER
*)header
;
81 *width
= core
->bcWidth
;
82 *height
= core
->bcHeight
;
83 *planes
= core
->bcPlanes
;
84 *bpp
= core
->bcBitCount
;
90 if (header
->biSize
== sizeof(BITMAPINFOHEADER
))
92 *width
= header
->biWidth
;
93 *height
= header
->biHeight
;
94 *planes
= header
->biPlanes
;
95 *bpp
= header
->biBitCount
;
96 *compr
= header
->biCompression
;
97 *size
= header
->biSizeImage
;
101 if (header
->biSize
== sizeof(BITMAPV4HEADER
))
103 BITMAPV4HEADER
*v4hdr
= (BITMAPV4HEADER
*)header
;
104 *width
= v4hdr
->bV4Width
;
105 *height
= v4hdr
->bV4Height
;
106 *planes
= v4hdr
->bV4Planes
;
107 *bpp
= v4hdr
->bV4BitCount
;
108 *compr
= v4hdr
->bV4V4Compression
;
109 *size
= v4hdr
->bV4SizeImage
;
113 if (header
->biSize
== sizeof(BITMAPV5HEADER
))
115 BITMAPV5HEADER
*v5hdr
= (BITMAPV5HEADER
*)header
;
116 *width
= v5hdr
->bV5Width
;
117 *height
= v5hdr
->bV5Height
;
118 *planes
= v5hdr
->bV5Planes
;
119 *bpp
= v5hdr
->bV5BitCount
;
120 *compr
= v5hdr
->bV5Compression
;
121 *size
= v5hdr
->bV5SizeImage
;
124 DPRINT("(%ld): wrong size for header\n", header
->biSize
);
133 GdiGetBitmapBitsSize(BITMAPINFO
*lpbmi
)
137 if (lpbmi
->bmiHeader
.biSize
== FIELD_OFFSET(BITMAPINFOHEADER
, biPlanes
))
139 /* Calc the bits Size and align it*/
140 retSize
= HIWORD(lpbmi
->bmiHeader
.biWidth
) * ((LOWORD(lpbmi
->bmiHeader
.biWidth
) *
141 LOWORD(lpbmi
->bmiHeader
.biHeight
) * HIWORD(lpbmi
->bmiHeader
.biHeight
) + 31)
146 if ( (lpbmi
->bmiHeader
.biCompression
== BI_BITFIELDS
) ||
147 (lpbmi
->bmiHeader
.biCompression
== BI_RGB
))
149 if (lpbmi
->bmiHeader
.biHeight
>=0 )
151 /* Calc the bits Size and align it*/
152 retSize
= lpbmi
->bmiHeader
.biHeight
* ((lpbmi
->bmiHeader
.biWidth
*
153 lpbmi
->bmiHeader
.biPlanes
* lpbmi
->bmiHeader
.biBitCount
+ 31) & -32) / 8;
157 /* Make height postiive if it negitve then calc the bits Size and align it*/
158 retSize
= (-lpbmi
->bmiHeader
.biHeight
) * ((lpbmi
->bmiHeader
.biWidth
*
159 lpbmi
->bmiHeader
.biPlanes
* lpbmi
->bmiHeader
.biBitCount
+ 31) & -32) / 8;
164 retSize
= lpbmi
->bmiHeader
.biSizeImage
;
176 CONST BITMAPINFO
*BitmapInfo
,
182 PBITMAPINFO pConvertedInfo
;
183 UINT ConvertedInfoSize
;
184 HBITMAP hBitmap
= NULL
;
187 pConvertedInfo
= ConvertBitmapInfo(BitmapInfo
, Usage
,
188 &ConvertedInfoSize
, FALSE
);
190 { // Verify header due to converted may == info.
191 if ( pConvertedInfo
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
) )
193 if ( pConvertedInfo
->bmiHeader
.biCompression
== BI_JPEG
||
194 pConvertedInfo
->bmiHeader
.biCompression
== BI_PNG
)
196 SetLastError(ERROR_INVALID_PARAMETER
);
201 hBitmap
= NtGdiCreateDIBSection( hDC
,
210 if (BitmapInfo
!= pConvertedInfo
)
211 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);
219 if (Bits
) *Bits
= bmBits
;
230 BitBlt(HDC hdcDest
, /* handle to destination DC */
231 int nXOriginDest
, /* x-coord of destination upper-left corner */
232 int nYOriginDest
, /* y-coord of destination upper-left corner */
233 int nWidthDest
, /* width of destination rectangle */
234 int nHeightDest
, /* height of destination rectangle */
235 HDC hdcSrc
, /* handle to source DC */
236 int nXSrc
, /* x-coordinate of source upper-left corner */
237 int nYSrc
, /* y-coordinate of source upper-left corner */
238 DWORD dwRop
) /* raster operation code */
240 /* use patBlt for no source blt Like windows does */
241 if (!ROP_USES_SOURCE(dwRop
))
243 return PatBlt(hdcDest
, nXOriginDest
, nYOriginDest
, nWidthDest
, nHeightDest
, dwRop
);
246 return NtGdiBitBlt(hdcDest
,
264 HDC hdcDest
, /* handle to destination DC */
265 int nXOriginDest
, /* x-coord of destination upper-left corner */
266 int nYOriginDest
, /* y-coord of destination upper-left corner */
267 int nWidthDest
, /* width of destination rectangle */
268 int nHeightDest
, /* height of destination rectangle */
269 HDC hdcSrc
, /* handle to source DC */
270 int nXOriginSrc
, /* x-coord of source upper-left corner */
271 int nYOriginSrc
, /* y-coord of source upper-left corner */
272 int nWidthSrc
, /* width of source rectangle */
273 int nHeightSrc
, /* height of source rectangle */
274 DWORD dwRop
) /* raster operation code */
277 if ((nWidthDest
!= nWidthSrc
) || (nHeightDest
!= nHeightSrc
))
279 return NtGdiStretchBlt(hdcDest
, nXOriginDest
, nYOriginDest
, nWidthDest
,
280 nHeightDest
, hdcSrc
, nXOriginSrc
, nYOriginSrc
,
281 nWidthSrc
, nHeightSrc
, dwRop
, 0);
284 return NtGdiBitBlt(hdcDest
, nXOriginDest
, nYOriginDest
, nWidthDest
,
285 nHeightDest
, hdcSrc
, nXOriginSrc
, nYOriginSrc
, dwRop
, 0, 0);
292 CreateBitmap(INT Width
,
298 /* FIXME some part should be done in user mode */
301 return NtGdiCreateBitmap(Width
, Height
, Planes
, BitsPixel
, (LPBYTE
) pUnsafeBits
);
305 /* Return 1x1 bitmap */
306 return GetStockObject(DEFAULT_BITMAP
);
314 CreateBitmapIndirect(const BITMAP
*pbm
)
316 HBITMAP bitmap
= NULL
;
318 /* Note windows xp/2003 does not check if pbm is NULL or not */
319 if ( (pbm
->bmWidthBytes
!= 0) &&
320 (!(pbm
->bmWidthBytes
& 1)) )
324 bitmap
= CreateBitmap(pbm
->bmWidth
,
332 SetLastError(ERROR_INVALID_PARAMETER
);
339 CreateDiscardableBitmap(
344 return CreateCompatibleBitmap(hDC
, Width
, Height
);
349 CreateCompatibleBitmap(
358 if (!GdiGetHandleUserData(hDC
, GDI_OBJECT_TYPE_DC
, (PVOID
)&pDc_Attr
))
361 if ( !Width
|| !Height
)
362 return GetStockObject(DEFAULT_BITMAP
);
364 if (!(pDc_Attr
->ulDirty_
& DC_DIBSECTION
))
366 return NtGdiCreateCompatibleBitmap(hDC
, Width
, Height
);
369 hBmp
= NtGdiGetDCObject(hDC
, GDI_OBJECT_TYPE_BITMAP
);
371 if ( GetObjectA(hBmp
, sizeof(DIBSECTION
), &dibs
) != sizeof(DIBSECTION
) )
374 if ( dibs
.dsBm
.bmBitsPixel
<= 8 )
375 GetDIBColorTable(hDC
, 0, 256, (RGBQUAD
*)&dibs
.dsBitfields
);
377 dibs
.dsBmih
.biWidth
= Width
;
378 dibs
.dsBmih
.biHeight
= Height
;
380 return CreateDIBSection(hDC
, (CONST BITMAPINFO
*)&dibs
.dsBmih
, 0, NULL
, NULL
, 0);
397 PVOID pvSafeBits
= lpvBits
;
399 if (!hDC
|| !GdiIsHandleValid((HGDIOBJ
)hDC
))
401 GdiSetLastError(ERROR_INVALID_PARAMETER
);
405 cjBmpScanSize
= DIB_BitmapMaxBitsSize(lpbmi
, cScanLines
);
411 if ( lpbmi
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
) )
413 if ( lpbmi
->bmiHeader
.biCompression
== BI_JPEG
||
414 lpbmi
->bmiHeader
.biCompression
== BI_PNG
)
416 SetLastError(ERROR_INVALID_PARAMETER
);
421 pvSafeBits
= RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize
);
424 Ret
= NtGdiGetDIBitsInternal(hDC
,
433 if ( lpvBits
!= pvSafeBits
)
435 RtlCopyMemory( lpvBits
, pvSafeBits
, cjBmpScanSize
);
436 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits
);
446 CreateDIBitmap( HDC hDC
,
447 const BITMAPINFOHEADER
*Header
,
450 const BITMAPINFO
*Data
,
453 LONG width
, height
, compr
, dibsize
;
455 // PDC_ATTR pDc_Attr;
456 PBITMAPINFO pConvertedInfo
;
457 UINT ConvertedInfoSize
;
459 PVOID pvSafeBits
= NULL
;
462 pConvertedInfo
= ConvertBitmapInfo(Data
, ColorUse
,
463 &ConvertedInfoSize
, FALSE
);
465 if (DIB_GetBitmapInfo(Header
, &width
, &height
, &planes
, &bpp
, &compr
, &dibsize
) == -1)
467 GdiSetLastError(ERROR_INVALID_PARAMETER
);
471 if ( pConvertedInfo
)
473 if ( pConvertedInfo
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
) )
475 if ( pConvertedInfo
->bmiHeader
.biCompression
== BI_JPEG
||
476 pConvertedInfo
->bmiHeader
.biCompression
== BI_PNG
)
485 // GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
487 cjBmpScanSize
= DIB_BitmapBitsSize((LPBITMAPINFO
)pConvertedInfo
);
488 DPRINT("pBMI %x, Size bpp %d, dibsize %d, Conv %d, BSS %d\n", pConvertedInfo
,bpp
,dibsize
,ConvertedInfoSize
,cjBmpScanSize
);
490 if ( !width
|| !height
)
491 hBmp
= GetStockObject(DEFAULT_BITMAP
);
496 pvSafeBits
= RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize
);
498 RtlCopyMemory( pvSafeBits
, Bits
, cjBmpScanSize
);
501 hBmp
= NtGdiCreateDIBitmapInternal(hDC
,
506 (PBITMAPINFO
)pConvertedInfo
,
514 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits
);
517 if (Data
!= pConvertedInfo
)
518 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);
522 #if 0 // FIXME!!! This is a victim of the Win32k Initialization BUG!!!!!
533 CONST BITMAPINFO
*lpbmi
,
536 HDC hDCc
, SavehDC
, nhDC
;
537 DWORD dwWidth
, dwHeight
;
539 HPALETTE hPal
= NULL
;
543 if ( !lpvBits
|| (GDI_HANDLE_GET_TYPE(hBitmap
) != GDI_OBJECT_TYPE_BITMAP
) )
548 if ( lpbmi
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
) )
550 if ( lpbmi
->bmiHeader
.biCompression
== BI_JPEG
|| lpbmi
->bmiHeader
.biCompression
== BI_PNG
)
552 SetLastError(ERROR_INVALID_PARAMETER
);
558 hDCc
= NtGdiGetDCforBitmap(hBitmap
);
562 nhDC
= CreateCompatibleDC(hDC
);
563 if ( !nhDC
) return 0;
567 else if ( !SaveDC(hDCc
) )
570 hOldBitmap
= SelectObject(SavehDC
, hBitmap
);
575 hPal
= SelectPalette(SavehDC
, (HPALETTE
)GetDCObject(hDC
, GDI_OBJECT_TYPE_PALETTE
), FALSE
);
577 if ( lpbmi
->bmiHeader
.biSize
< sizeof(BITMAPINFOHEADER
))
579 PBITMAPCOREINFO pbci
= (PBITMAPCOREINFO
) lpbmi
;
580 dwWidth
= pbci
->bmciHeader
.bcWidth
;
581 dwHeight
= pbci
->bmciHeader
.bcHeight
;
585 dwWidth
= lpbmi
->bmiHeader
.biWidth
;
586 dwHeight
= abs(lpbmi
->bmiHeader
.biHeight
);
589 LinesCopied
= SetDIBitsToDevice(SavehDC
,
602 if ( hDC
) SelectPalette(SavehDC
, hPal
, FALSE
);
604 SelectObject(SavehDC
, hOldBitmap
);
610 RestoreDC(SavehDC
, -1);
623 CONST BITMAPINFO
*lpbmi
,
626 PBITMAPINFO pConvertedInfo
;
627 UINT ConvertedInfoSize
;
629 UINT cjBmpScanSize
= 0;
630 PVOID pvSafeBits
= (PVOID
)lpvBits
;
632 // This needs to be almost the sames as SetDIBitsToDevice
634 if ( !cScanLines
|| !lpbmi
|| !lpvBits
|| (GDI_HANDLE_GET_TYPE(hbmp
) != GDI_OBJECT_TYPE_BITMAP
))
637 if ( fuColorUse
&& fuColorUse
!= DIB_PAL_COLORS
&& fuColorUse
!= DIB_PAL_COLORS
+1 )
640 pConvertedInfo
= ConvertBitmapInfo(lpbmi
, fuColorUse
,
641 &ConvertedInfoSize
, FALSE
);
645 cjBmpScanSize
= DIB_BitmapMaxBitsSize((LPBITMAPINFO
)lpbmi
, cScanLines
);
649 pvSafeBits
= RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize
);
651 RtlCopyMemory( pvSafeBits
, lpvBits
, cjBmpScanSize
);
654 LinesCopied
= NtGdiSetDIBits( hdc
,
662 if ( lpvBits
!= pvSafeBits
)
663 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits
);
664 if (lpbmi
!= pConvertedInfo
)
665 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);
686 CONST BITMAPINFO
*lpbmi
,
690 PBITMAPINFO pConvertedInfo
;
691 UINT ConvertedInfoSize
;
693 UINT cjBmpScanSize
= 0;
694 PVOID pvSafeBits
= (PVOID
)Bits
;
696 if ( !ScanLines
|| !lpbmi
|| !Bits
)
699 if ( ColorUse
&& ColorUse
!= DIB_PAL_COLORS
&& ColorUse
!= DIB_PAL_COLORS
+1 )
702 pConvertedInfo
= ConvertBitmapInfo(lpbmi
, ColorUse
,
703 &ConvertedInfoSize
, FALSE
);
708 // Handle something other than a normal dc object.
709 if (GDI_HANDLE_GET_TYPE(hdc
) != GDI_OBJECT_TYPE_DC
)
711 if (GDI_HANDLE_GET_TYPE(hdc
) == GDI_OBJECT_TYPE_METADC
)
712 return MFDRV_SetDIBitsToDevice( hdc
,
726 PLDC pLDC
= GdiGetLDC(hdc
);
729 SetLastError(ERROR_INVALID_HANDLE
);
732 if (pLDC
->iType
== LDC_EMFLDC
)
734 return EMFDRV_SetDIBitsToDevice(hdc
,
751 cjBmpScanSize
= DIB_BitmapMaxBitsSize((LPBITMAPINFO
)lpbmi
, ScanLines
);
755 pvSafeBits
= RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize
);
757 RtlCopyMemory( pvSafeBits
, Bits
, cjBmpScanSize
);
760 if (!GdiGetHandleUserData(hdc
, GDI_OBJECT_TYPE_DC
, (PVOID
)&pDc_Attr
))
762 SetLastError(ERROR_INVALID_PARAMETER
);
767 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
768 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
769 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
771 LinesCopied
= NtGdiSetDIBitsToDeviceInternal( hdc
,
781 (LPBITMAPINFO
)pConvertedInfo
,
788 if ( Bits
!= pvSafeBits
)
789 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits
);
790 if (lpbmi
!= pConvertedInfo
)
791 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);
802 StretchDIBits(HDC hdc
,
812 CONST BITMAPINFO
*lpBitsInfo
,
818 PBITMAPINFO pConvertedInfo
= NULL
;
819 UINT ConvertedInfoSize
= 0;
821 UINT cjBmpScanSize
= 0;
822 PVOID pvSafeBits
= NULL
;
825 DPRINT("StretchDIBits %x : %x : %d\n", lpBits
, lpBitsInfo
, iUsage
);
827 // Handle something other than a normal dc object.
828 if (GDI_HANDLE_GET_TYPE(hdc
) != GDI_OBJECT_TYPE_DC
)
830 if (GDI_HANDLE_GET_TYPE(hdc
) == GDI_OBJECT_TYPE_METADC
)
831 return MFDRV_StretchBlt( hdc
,
846 PLDC pLDC
= GdiGetLDC(hdc
);
849 SetLastError(ERROR_INVALID_HANDLE
);
852 if (pLDC
->iType
== LDC_EMFLDC
)
854 return EMFDRV_StretchBlt(hdc
,
872 if ( iUsage
) // Save time, we only look at non RGB.
874 pConvertedInfo
= ConvertBitmapInfo(lpBitsInfo
, iUsage
,
875 &ConvertedInfoSize
, FALSE
);
882 pConvertedInfo
= (PBITMAPINFO
)lpBitsInfo
;
884 cjBmpScanSize
= DIB_BitmapBitsSize((LPBITMAPINFO
)pConvertedInfo
);
888 pvSafeBits
= RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize
);
893 RtlCopyMemory( pvSafeBits
, lpBits
, cjBmpScanSize
);
895 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
903 // We don't die, we continue on with a allocated safe pointer to kernel
905 DPRINT1("StretchDIBits fail to read BitMapInfo: %x or Bits: %x & Size: %d\n",pConvertedInfo
,lpBits
,cjBmpScanSize
);
907 DPRINT("StretchDIBits Allocate Bits %d!!!\n", cjBmpScanSize
);
911 if (!GdiGetHandleUserData(hdc
, GDI_OBJECT_TYPE_DC
, (PVOID
)&pDc_Attr
))
913 SetLastError(ERROR_INVALID_PARAMETER
);
918 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
919 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
920 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
922 LinesCopied
= NtGdiStretchDIBitsInternal( hdc
,
940 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits
);
941 if (lpBitsInfo
!= pConvertedInfo
)
942 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);