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( CONST BITMAPINFO
* 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
,
77 if (header
->biSize
== sizeof(BITMAPCOREHEADER
))
79 BITMAPCOREHEADER
*core
= (BITMAPCOREHEADER
*)header
;
80 *width
= core
->bcWidth
;
81 *height
= core
->bcHeight
;
82 *planes
= core
->bcPlanes
;
83 *bpp
= core
->bcBitCount
;
89 if (header
->biSize
== sizeof(BITMAPINFOHEADER
))
91 *width
= header
->biWidth
;
92 *height
= header
->biHeight
;
93 *planes
= header
->biPlanes
;
94 *bpp
= header
->biBitCount
;
95 *compr
= header
->biCompression
;
96 *size
= header
->biSizeImage
;
100 if (header
->biSize
== sizeof(BITMAPV4HEADER
))
102 BITMAPV4HEADER
*v4hdr
= (BITMAPV4HEADER
*)header
;
103 *width
= v4hdr
->bV4Width
;
104 *height
= v4hdr
->bV4Height
;
105 *planes
= v4hdr
->bV4Planes
;
106 *bpp
= v4hdr
->bV4BitCount
;
107 *compr
= v4hdr
->bV4V4Compression
;
108 *size
= v4hdr
->bV4SizeImage
;
112 if (header
->biSize
== sizeof(BITMAPV5HEADER
))
114 BITMAPV5HEADER
*v5hdr
= (BITMAPV5HEADER
*)header
;
115 *width
= v5hdr
->bV5Width
;
116 *height
= v5hdr
->bV5Height
;
117 *planes
= v5hdr
->bV5Planes
;
118 *bpp
= v5hdr
->bV5BitCount
;
119 *compr
= v5hdr
->bV5Compression
;
120 *size
= v5hdr
->bV5SizeImage
;
123 DPRINT("(%ld): wrong size for header\n", header
->biSize
);
132 GdiGetBitmapBitsSize(BITMAPINFO
*lpbmi
)
136 if (lpbmi
->bmiHeader
.biSize
== FIELD_OFFSET(BITMAPINFOHEADER
, biPlanes
))
138 /* Calc the bits Size and align it*/
139 retSize
= HIWORD(lpbmi
->bmiHeader
.biWidth
) * ((LOWORD(lpbmi
->bmiHeader
.biWidth
) *
140 LOWORD(lpbmi
->bmiHeader
.biHeight
) * HIWORD(lpbmi
->bmiHeader
.biHeight
) + 31)
145 if ( (lpbmi
->bmiHeader
.biCompression
== BI_BITFIELDS
) ||
146 (lpbmi
->bmiHeader
.biCompression
== BI_RGB
))
148 if (lpbmi
->bmiHeader
.biHeight
>=0 )
150 /* Calc the bits Size and align it*/
151 retSize
= lpbmi
->bmiHeader
.biHeight
* ((lpbmi
->bmiHeader
.biWidth
*
152 lpbmi
->bmiHeader
.biPlanes
* lpbmi
->bmiHeader
.biBitCount
+ 31) & -32) / 8;
156 /* Make height postiive if it negitve then calc the bits Size and align it*/
157 retSize
= (-lpbmi
->bmiHeader
.biHeight
) * ((lpbmi
->bmiHeader
.biWidth
*
158 lpbmi
->bmiHeader
.biPlanes
* lpbmi
->bmiHeader
.biBitCount
+ 31) & -32) / 8;
163 retSize
= lpbmi
->bmiHeader
.biSizeImage
;
175 CONST BITMAPINFO
*BitmapInfo
,
181 PBITMAPINFO pConvertedInfo
;
182 UINT ConvertedInfoSize
;
183 HBITMAP hBitmap
= NULL
;
186 pConvertedInfo
= ConvertBitmapInfo(BitmapInfo
, Usage
,
187 &ConvertedInfoSize
, FALSE
);
189 { // Verify header due to converted may == info.
190 if ( pConvertedInfo
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
) )
192 if ( pConvertedInfo
->bmiHeader
.biCompression
== BI_JPEG
||
193 pConvertedInfo
->bmiHeader
.biCompression
== BI_PNG
)
195 SetLastError(ERROR_INVALID_PARAMETER
);
200 hBitmap
= NtGdiCreateDIBSection( hDC
,
209 if (BitmapInfo
!= pConvertedInfo
)
210 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);
218 if (Bits
) *Bits
= bmBits
;
229 BitBlt(HDC hdcDest
, /* handle to destination DC */
230 int nXOriginDest
, /* x-coord of destination upper-left corner */
231 int nYOriginDest
, /* y-coord of destination upper-left corner */
232 int nWidthDest
, /* width of destination rectangle */
233 int nHeightDest
, /* height of destination rectangle */
234 HDC hdcSrc
, /* handle to source DC */
235 int nXSrc
, /* x-coordinate of source upper-left corner */
236 int nYSrc
, /* y-coordinate of source upper-left corner */
237 DWORD dwRop
) /* raster operation code */
239 /* use patBlt for no source blt Like windows does */
240 if (!ROP_USES_SOURCE(dwRop
))
242 return PatBlt(hdcDest
, nXOriginDest
, nYOriginDest
, nWidthDest
, nHeightDest
, dwRop
);
245 return NtGdiBitBlt(hdcDest
,
263 HDC hdcDest
, /* handle to destination DC */
264 int nXOriginDest
, /* x-coord of destination upper-left corner */
265 int nYOriginDest
, /* y-coord of destination upper-left corner */
266 int nWidthDest
, /* width of destination rectangle */
267 int nHeightDest
, /* height of destination rectangle */
268 HDC hdcSrc
, /* handle to source DC */
269 int nXOriginSrc
, /* x-coord of source upper-left corner */
270 int nYOriginSrc
, /* y-coord of source upper-left corner */
271 int nWidthSrc
, /* width of source rectangle */
272 int nHeightSrc
, /* height of source rectangle */
273 DWORD dwRop
) /* raster operation code */
276 if ((nWidthDest
!= nWidthSrc
) || (nHeightDest
!= nHeightSrc
))
278 return NtGdiStretchBlt(hdcDest
, nXOriginDest
, nYOriginDest
, nWidthDest
,
279 nHeightDest
, hdcSrc
, nXOriginSrc
, nYOriginSrc
,
280 nWidthSrc
, nHeightSrc
, dwRop
, 0);
283 return NtGdiBitBlt(hdcDest
, nXOriginDest
, nYOriginDest
, nWidthDest
,
284 nHeightDest
, hdcSrc
, nXOriginSrc
, nYOriginSrc
, dwRop
, 0, 0);
291 CreateBitmap(INT Width
,
295 CONST VOID
* pUnsafeBits
)
297 /* FIXME some part should be done in user mode */
300 return NtGdiCreateBitmap(Width
, Height
, Planes
, BitsPixel
, (LPBYTE
) pUnsafeBits
);
304 /* Return 1x1 bitmap */
305 return GetStockObject(DEFAULT_BITMAP
);
313 CreateBitmapIndirect(const BITMAP
*pbm
)
315 HBITMAP bitmap
= NULL
;
317 /* Note windows xp/2003 does not check if pbm is NULL or not */
318 if ( (pbm
->bmWidthBytes
!= 0) &&
319 (!(pbm
->bmWidthBytes
& 1)) )
323 bitmap
= CreateBitmap(pbm
->bmWidth
,
331 SetLastError(ERROR_INVALID_PARAMETER
);
338 CreateDiscardableBitmap(
343 return CreateCompatibleBitmap(hDC
, Width
, Height
);
348 CreateCompatibleBitmap(
357 if (!GdiGetHandleUserData(hDC
, GDI_OBJECT_TYPE_DC
, (PVOID
)&pDc_Attr
))
360 if ( !Width
|| !Height
)
361 return GetStockObject(DEFAULT_BITMAP
);
363 if (!(pDc_Attr
->ulDirty_
& DC_DIBSECTION
))
365 return NtGdiCreateCompatibleBitmap(hDC
, Width
, Height
);
368 hBmp
= NtGdiGetDCObject(hDC
, GDI_OBJECT_TYPE_BITMAP
);
370 if ( GetObjectA(hBmp
, sizeof(DIBSECTION
), &dibs
) != sizeof(DIBSECTION
) )
373 if ( dibs
.dsBm
.bmBitsPixel
<= 8 )
374 GetDIBColorTable(hDC
, 0, 256, (RGBQUAD
*)&dibs
.dsBitfields
);
376 dibs
.dsBmih
.biWidth
= Width
;
377 dibs
.dsBmih
.biHeight
= Height
;
379 return CreateDIBSection(hDC
, (CONST BITMAPINFO
*)&dibs
.dsBmih
, 0, NULL
, NULL
, 0);
396 PVOID pvSafeBits
= lpvBits
;
398 if (!hDC
|| !GdiIsHandleValid((HGDIOBJ
)hDC
))
400 GdiSetLastError(ERROR_INVALID_PARAMETER
);
404 cjBmpScanSize
= DIB_BitmapMaxBitsSize(lpbmi
, cScanLines
);
410 if ( lpbmi
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
) )
412 if ( lpbmi
->bmiHeader
.biCompression
== BI_JPEG
||
413 lpbmi
->bmiHeader
.biCompression
== BI_PNG
)
415 SetLastError(ERROR_INVALID_PARAMETER
);
421 if ((ULONG
)lpvBits
& (sizeof(DWORD
) - 1))
423 pvSafeBits
= RtlAllocateHeap(RtlGetProcessHeap(), 0, cjBmpScanSize
);
429 Ret
= NtGdiGetDIBitsInternal(hDC
,
438 if (lpvBits
!= pvSafeBits
)
442 RtlCopyMemory(lpvBits
, pvSafeBits
, cjBmpScanSize
);
444 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits
);
454 CreateDIBitmap( HDC hDC
,
455 const BITMAPINFOHEADER
*Header
,
458 const BITMAPINFO
*Data
,
461 LONG width
, height
, compr
, dibsize
;
463 // PDC_ATTR pDc_Attr;
465 UINT cjBmpScanSize
= 0;
467 NTSTATUS Status
= STATUS_SUCCESS
;
469 if (!Header
) return 0;
471 if (DIB_GetBitmapInfo(Header
, &width
, &height
, &planes
, &bpp
, &compr
, &dibsize
) == -1)
473 GdiSetLastError(ERROR_INVALID_PARAMETER
);
478 // GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
484 cjBmpScanSize
= DIB_BitmapBitsSize(Data
);
485 CalculateColorTableSize(&Data
->bmiHeader
, &ColorUse
, &InfoSize
);
486 InfoSize
+= Data
->bmiHeader
.biSize
;
488 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
490 Status
= _SEH2_GetExceptionCode();
495 if(!NT_SUCCESS(Status
))
497 GdiSetLastError(ERROR_INVALID_PARAMETER
);
501 DPRINT("pBMI %x, Size bpp %d, dibsize %d, Conv %d, BSS %d\n", Data
,bpp
,dibsize
,InfoSize
,cjBmpScanSize
);
503 if ( !width
|| !height
)
504 hBmp
= GetStockObject(DEFAULT_BITMAP
);
507 hBmp
= NtGdiCreateDIBitmapInternal(hDC
,
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 pConvertedInfo
= ConvertBitmapInfo(lpBitsInfo
, iUsage
,
873 &ConvertedInfoSize
, FALSE
);
879 cjBmpScanSize
= DIB_BitmapBitsSize((LPBITMAPINFO
)pConvertedInfo
);
883 pvSafeBits
= RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize
);
888 RtlCopyMemory( pvSafeBits
, lpBits
, cjBmpScanSize
);
890 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
898 // We don't die, we continue on with a allocated safe pointer to kernel
900 DPRINT1("StretchDIBits fail to read BitMapInfo: %x or Bits: %x & Size: %d\n",pConvertedInfo
,lpBits
,cjBmpScanSize
);
902 DPRINT("StretchDIBits Allocate Bits %d!!!\n", cjBmpScanSize
);
906 if (!GdiGetHandleUserData(hdc
, GDI_OBJECT_TYPE_DC
, (PVOID
)&pDc_Attr
))
908 SetLastError(ERROR_INVALID_PARAMETER
);
913 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
914 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
915 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
917 LinesCopied
= NtGdiStretchDIBitsInternal( hdc
,
935 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits
);
936 if (lpBitsInfo
!= pConvertedInfo
)
937 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);