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
,
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;
464 PBITMAPINFO pConvertedInfo
;
465 UINT ConvertedInfoSize
;
467 PVOID pvSafeBits
= NULL
;
470 if (!Header
) return 0;
472 pConvertedInfo
= ConvertBitmapInfo(Data
, ColorUse
,
473 &ConvertedInfoSize
, FALSE
);
475 if (DIB_GetBitmapInfo(Header
, &width
, &height
, &planes
, &bpp
, &compr
, &dibsize
) == -1)
477 GdiSetLastError(ERROR_INVALID_PARAMETER
);
481 if ( pConvertedInfo
)
483 if ( pConvertedInfo
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
) )
485 if ( pConvertedInfo
->bmiHeader
.biCompression
== BI_JPEG
||
486 pConvertedInfo
->bmiHeader
.biCompression
== BI_PNG
)
495 // GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
497 cjBmpScanSize
= DIB_BitmapBitsSize((LPBITMAPINFO
)pConvertedInfo
);
498 DPRINT("pBMI %x, Size bpp %d, dibsize %d, Conv %d, BSS %d\n", pConvertedInfo
,bpp
,dibsize
,ConvertedInfoSize
,cjBmpScanSize
);
500 if ( !width
|| !height
)
501 hBmp
= GetStockObject(DEFAULT_BITMAP
);
504 if ( Bits
&& Init
== CBM_INIT
)
506 pvSafeBits
= RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize
);
507 if (pvSafeBits
== NULL
)
514 RtlCopyMemory( pvSafeBits
, Bits
, cjBmpScanSize
);
518 hBmp
= NtGdiCreateDIBitmapInternal(hDC
,
523 (PBITMAPINFO
)pConvertedInfo
,
530 if ( Bits
&& Init
== CBM_INIT
)
531 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits
);
534 if (Data
!= pConvertedInfo
)
535 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);
539 #if 0 // FIXME!!! This is a victim of the Win32k Initialization BUG!!!!!
550 CONST BITMAPINFO
*lpbmi
,
553 HDC hDCc
, SavehDC
, nhDC
;
554 DWORD dwWidth
, dwHeight
;
556 HPALETTE hPal
= NULL
;
560 if ( !lpvBits
|| (GDI_HANDLE_GET_TYPE(hBitmap
) != GDI_OBJECT_TYPE_BITMAP
) )
565 if ( lpbmi
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
) )
567 if ( lpbmi
->bmiHeader
.biCompression
== BI_JPEG
|| lpbmi
->bmiHeader
.biCompression
== BI_PNG
)
569 SetLastError(ERROR_INVALID_PARAMETER
);
575 hDCc
= NtGdiGetDCforBitmap(hBitmap
);
579 nhDC
= CreateCompatibleDC(hDC
);
580 if ( !nhDC
) return 0;
584 else if ( !SaveDC(hDCc
) )
587 hOldBitmap
= SelectObject(SavehDC
, hBitmap
);
592 hPal
= SelectPalette(SavehDC
, (HPALETTE
)GetDCObject(hDC
, GDI_OBJECT_TYPE_PALETTE
), FALSE
);
594 if ( lpbmi
->bmiHeader
.biSize
< sizeof(BITMAPINFOHEADER
))
596 PBITMAPCOREINFO pbci
= (PBITMAPCOREINFO
) lpbmi
;
597 dwWidth
= pbci
->bmciHeader
.bcWidth
;
598 dwHeight
= pbci
->bmciHeader
.bcHeight
;
602 dwWidth
= lpbmi
->bmiHeader
.biWidth
;
603 dwHeight
= abs(lpbmi
->bmiHeader
.biHeight
);
606 LinesCopied
= SetDIBitsToDevice(SavehDC
,
619 if ( hDC
) SelectPalette(SavehDC
, hPal
, FALSE
);
621 SelectObject(SavehDC
, hOldBitmap
);
627 RestoreDC(SavehDC
, -1);
640 CONST BITMAPINFO
*lpbmi
,
643 PBITMAPINFO pConvertedInfo
;
644 UINT ConvertedInfoSize
;
646 UINT cjBmpScanSize
= 0;
647 PVOID pvSafeBits
= (PVOID
)lpvBits
;
649 // This needs to be almost the sames as SetDIBitsToDevice
651 if ( !cScanLines
|| !lpbmi
|| !lpvBits
|| (GDI_HANDLE_GET_TYPE(hbmp
) != GDI_OBJECT_TYPE_BITMAP
))
654 if ( fuColorUse
&& fuColorUse
!= DIB_PAL_COLORS
&& fuColorUse
!= DIB_PAL_COLORS
+1 )
657 pConvertedInfo
= ConvertBitmapInfo(lpbmi
, fuColorUse
,
658 &ConvertedInfoSize
, FALSE
);
662 cjBmpScanSize
= DIB_BitmapMaxBitsSize((LPBITMAPINFO
)lpbmi
, cScanLines
);
666 pvSafeBits
= RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize
);
668 RtlCopyMemory( pvSafeBits
, lpvBits
, cjBmpScanSize
);
671 LinesCopied
= NtGdiSetDIBits( hdc
,
679 if ( lpvBits
!= pvSafeBits
)
680 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits
);
681 if (lpbmi
!= pConvertedInfo
)
682 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);
703 CONST BITMAPINFO
*lpbmi
,
707 PBITMAPINFO pConvertedInfo
;
708 UINT ConvertedInfoSize
;
710 UINT cjBmpScanSize
= 0;
711 PVOID pvSafeBits
= (PVOID
)Bits
;
713 if ( !ScanLines
|| !lpbmi
|| !Bits
)
716 if ( ColorUse
&& ColorUse
!= DIB_PAL_COLORS
&& ColorUse
!= DIB_PAL_COLORS
+1 )
719 pConvertedInfo
= ConvertBitmapInfo(lpbmi
, ColorUse
,
720 &ConvertedInfoSize
, FALSE
);
725 // Handle something other than a normal dc object.
726 if (GDI_HANDLE_GET_TYPE(hdc
) != GDI_OBJECT_TYPE_DC
)
728 if (GDI_HANDLE_GET_TYPE(hdc
) == GDI_OBJECT_TYPE_METADC
)
729 return MFDRV_SetDIBitsToDevice( hdc
,
743 PLDC pLDC
= GdiGetLDC(hdc
);
746 SetLastError(ERROR_INVALID_HANDLE
);
749 if (pLDC
->iType
== LDC_EMFLDC
)
751 return EMFDRV_SetDIBitsToDevice(hdc
,
768 cjBmpScanSize
= DIB_BitmapMaxBitsSize((LPBITMAPINFO
)lpbmi
, ScanLines
);
772 pvSafeBits
= RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize
);
774 RtlCopyMemory( pvSafeBits
, Bits
, cjBmpScanSize
);
777 if (!GdiGetHandleUserData(hdc
, GDI_OBJECT_TYPE_DC
, (PVOID
)&pDc_Attr
))
779 SetLastError(ERROR_INVALID_PARAMETER
);
784 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
785 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
786 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
788 LinesCopied
= NtGdiSetDIBitsToDeviceInternal( hdc
,
798 (LPBITMAPINFO
)pConvertedInfo
,
805 if ( Bits
!= pvSafeBits
)
806 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits
);
807 if (lpbmi
!= pConvertedInfo
)
808 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);
819 StretchDIBits(HDC hdc
,
829 CONST BITMAPINFO
*lpBitsInfo
,
835 PBITMAPINFO pConvertedInfo
= NULL
;
836 UINT ConvertedInfoSize
= 0;
838 UINT cjBmpScanSize
= 0;
839 PVOID pvSafeBits
= NULL
;
842 DPRINT("StretchDIBits %x : %x : %d\n", lpBits
, lpBitsInfo
, iUsage
);
844 // Handle something other than a normal dc object.
845 if (GDI_HANDLE_GET_TYPE(hdc
) != GDI_OBJECT_TYPE_DC
)
847 if (GDI_HANDLE_GET_TYPE(hdc
) == GDI_OBJECT_TYPE_METADC
)
848 return MFDRV_StretchBlt( hdc
,
863 PLDC pLDC
= GdiGetLDC(hdc
);
866 SetLastError(ERROR_INVALID_HANDLE
);
869 if (pLDC
->iType
== LDC_EMFLDC
)
871 return EMFDRV_StretchBlt(hdc
,
889 if ( iUsage
) // Save time, we only look at non RGB.
891 pConvertedInfo
= ConvertBitmapInfo(lpBitsInfo
, iUsage
,
892 &ConvertedInfoSize
, FALSE
);
899 pConvertedInfo
= (PBITMAPINFO
)lpBitsInfo
;
901 cjBmpScanSize
= DIB_BitmapBitsSize((LPBITMAPINFO
)pConvertedInfo
);
905 pvSafeBits
= RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize
);
910 RtlCopyMemory( pvSafeBits
, lpBits
, cjBmpScanSize
);
912 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
920 // We don't die, we continue on with a allocated safe pointer to kernel
922 DPRINT1("StretchDIBits fail to read BitMapInfo: %x or Bits: %x & Size: %d\n",pConvertedInfo
,lpBits
,cjBmpScanSize
);
924 DPRINT("StretchDIBits Allocate Bits %d!!!\n", cjBmpScanSize
);
928 if (!GdiGetHandleUserData(hdc
, GDI_OBJECT_TYPE_DC
, (PVOID
)&pDc_Attr
))
930 SetLastError(ERROR_INVALID_PARAMETER
);
935 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
936 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
937 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
939 LinesCopied
= NtGdiStretchDIBitsInternal( hdc
,
957 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits
);
958 if (lpBitsInfo
!= pConvertedInfo
)
959 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo
);