- Finally get rid of ProbeAndConvertToBitmapV5Info
  - Rewrite renderBITMAPfromDIB, and a good bunch of DIB related functions accordingly.
  - Rewrite BITMAP_CopyBitmap into something simpler.
  - Use already existing DIB functions in IntGdiCreateDIBBrush
  - Use DIB sections in NtGdiStretchDIBitsInternal and NtGdiSetDIBits.
  - Use Bitmap hdc for NtGdiGetDIBitsInternal if there is one.

svn path=/branches/reactos-yarotows/; revision=48389
This commit is contained in:
Jérôme Gardou 2010-08-01 12:17:35 +00:00
parent 147e52c02c
commit 787cb5551f
7 changed files with 264 additions and 672 deletions

View file

@ -13,7 +13,6 @@ HBITMAP FASTCALL IntCreateBitmap(IN SIZEL Size, IN LONG Width, IN ULONG Format,
HBITMAP FASTCALL BITMAP_CopyBitmap (HBITMAP hBitmap); HBITMAP FASTCALL BITMAP_CopyBitmap (HBITMAP hBitmap);
UINT FASTCALL BITMAP_GetRealBitsPixel(UINT nBitsPixel); UINT FASTCALL BITMAP_GetRealBitsPixel(UINT nBitsPixel);
INT FASTCALL BITMAP_GetWidthBytes (INT bmWidth, INT bpp); INT FASTCALL BITMAP_GetWidthBytes (INT bmWidth, INT bpp);
NTSTATUS FASTCALL ProbeAndConvertToBitmapV5Info( OUT PBITMAPV5INFO pbmiDst, IN CONST BITMAPINFO* pbmiUnsafe, IN DWORD dwUse, UINT MaxSize);
HBITMAP HBITMAP
APIENTRY APIENTRY
@ -43,7 +42,7 @@ GreCreateDIBitmapInternal(
IN INT cy, IN INT cy,
IN DWORD fInit, IN DWORD fInit,
IN OPTIONAL LPBYTE pjInit, IN OPTIONAL LPBYTE pjInit,
IN OPTIONAL PBITMAPV5INFO pbmi, IN OPTIONAL PBITMAPINFO pbmi,
IN DWORD iUsage, IN DWORD iUsage,
IN FLONG fl, IN FLONG fl,
IN HANDLE hcmXform); IN HANDLE hcmXform);

View file

@ -13,11 +13,11 @@ INT APIENTRY
DIB_GetDIBImageBytes (INT width, INT height, INT depth); DIB_GetDIBImageBytes (INT width, INT height, INT depth);
INT FASTCALL INT FASTCALL
DIB_GetDIBWidthBytes (INT width, INT depth); DIB_GetDIBWidthBytes (INT width, INT depth);
RGBQUAD * FASTCALL HPALETTE FASTCALL
DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi); DIB_MapPaletteColors(PPALETTE ppal, CONST BITMAPINFO* lpbmi);
HPALETTE FASTCALL HPALETTE FASTCALL
BuildDIBPalette (CONST BITMAPINFO *bmi, PINT paletteType); BuildDIBPalette (CONST BITMAPINFO *bmi);
BITMAPINFO* FASTCALL DIB_ConvertBitmapInfo(CONST BITMAPINFO* bmi, DWORD Usage); BITMAPINFO* FASTCALL DIB_ConvertBitmapInfo(CONST BITMAPINFO* bmi, DWORD Usage);
VOID FASTCALL DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig); VOID FASTCALL DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig);

View file

@ -247,9 +247,11 @@ renderBITMAPfromDIB(LPBYTE pDIB)
{ {
HDC hdc; HDC hdc;
HBITMAP hbitmap; HBITMAP hbitmap;
unsigned int offset = 0; /* Stupid compiler */ PBITMAPINFO pBmi, pConvertedBmi = NULL;
BITMAPV5INFO bmi;
NTSTATUS Status ; NTSTATUS Status ;
UINT offset = 0; /* Stupid compiler */
pBmi = (BITMAPINFO*)pDIB;
//hdc = UserGetDCEx(NULL, NULL, DCX_USESTYLE); //hdc = UserGetDCEx(NULL, NULL, DCX_USESTYLE);
hdc = UserGetDCEx(ClipboardWindow, NULL, DCX_USESTYLE); hdc = UserGetDCEx(ClipboardWindow, NULL, DCX_USESTYLE);
@ -257,9 +259,19 @@ renderBITMAPfromDIB(LPBYTE pDIB)
/* Probe it */ /* Probe it */
_SEH2_TRY _SEH2_TRY
{ {
Status = ProbeAndConvertToBitmapV5Info(&bmi, (BITMAPINFO*)pDIB, DIB_RGB_COLORS, 0); ProbeForRead(&pBmi->bmiHeader.biSize, sizeof(DWORD), 1);
offset = DIB_BitmapInfoSize((BITMAPINFO*)pDIB, DIB_RGB_COLORS); ProbeForRead(pBmi, pBmi->bmiHeader.biSize, 1);
ProbeForRead(pDIB + offset, bmi.bmiHeader.bV5SizeImage, 1); ProbeForRead(pBmi, DIB_BitmapInfoSize(pBmi, DIB_RGB_COLORS), 1);
pConvertedBmi = DIB_ConvertBitmapInfo(pBmi, DIB_RGB_COLORS);
if(!pConvertedBmi)
{
Status = STATUS_INVALID_PARAMETER;
}
else
{
offset = DIB_BitmapInfoSize((BITMAPINFO*)pBmi, DIB_RGB_COLORS);
ProbeForRead(pDIB + offset, pConvertedBmi->bmiHeader.biSizeImage, 1);
}
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {
@ -274,17 +286,19 @@ renderBITMAPfromDIB(LPBYTE pDIB)
} }
hbitmap = GreCreateDIBitmapInternal(hdc, hbitmap = GreCreateDIBitmapInternal(hdc,
bmi.bmiHeader.bV5Width, pConvertedBmi->bmiHeader.biWidth,
bmi.bmiHeader.bV5Height, pConvertedBmi->bmiHeader.biHeight,
CBM_INIT, CBM_INIT,
pDIB+offset, pDIB+offset,
&bmi, pConvertedBmi,
DIB_RGB_COLORS, DIB_RGB_COLORS,
0, 0,
0); 0);
//UserReleaseDC(NULL, hdc, FALSE); //UserReleaseDC(NULL, hdc, FALSE);
UserReleaseDC(ClipboardWindow, hdc, FALSE); UserReleaseDC(ClipboardWindow, hdc, FALSE);
DIB_FreeConvertedBitmapInfo(pConvertedBmi, pBmi);
return hbitmap; return hbitmap;
} }

View file

@ -1325,12 +1325,10 @@ UserDrawIconEx(
if(bAlpha && (diFlags & DI_IMAGE)) if(bAlpha && (diFlags & DI_IMAGE))
{ {
BLENDFUNCTION pixelblend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; BLENDFUNCTION pixelblend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
DWORD Pixel; BYTE Alpha;
BYTE Red, Green, Blue, Alpha;
DWORD Count = 0;
INT i, j; INT i, j;
PSURFACE psurf; PSURFACE psurf;
PBYTE pBits ; PBYTE pBits, ptr ;
HBITMAP hMemBmp = NULL; HBITMAP hMemBmp = NULL;
pBits = ExAllocatePoolWithTag(PagedPool, pBits = ExAllocatePoolWithTag(PagedPool,
@ -1363,20 +1361,15 @@ UserDrawIconEx(
/* premultiply with the alpha channel value */ /* premultiply with the alpha channel value */
for (i = 0; i < abs(bmpColor.bmHeight); i++) for (i = 0; i < abs(bmpColor.bmHeight); i++)
{ {
Count = i*bmpColor.bmWidthBytes; ptr = pBits + i*bmpColor.bmWidthBytes;
for (j = 0; j < bmpColor.bmWidth; j++) for (j = 0; j < bmpColor.bmWidth; j++)
{ {
Pixel = *(DWORD *)(pBits + Count); Alpha = ptr[3];
ptr[0] *= Alpha / 0xff;
ptr[1] *= Alpha / 0xff;
ptr[2] *= Alpha / 0xff;
Alpha = ((BYTE)(Pixel >> 24) & 0xff); ptr += 4;
Red = (((BYTE)(Pixel >> 0)) * Alpha) / 0xff;
Green = (((BYTE)(Pixel >> 8)) * Alpha) / 0xff;
Blue = (((BYTE)(Pixel >> 16)) * Alpha) / 0xff;
*(DWORD *)(pBits + Count) = (DWORD)(Red | (Green << 8) | (Blue << 16) | (Alpha << 24));
Count += sizeof(DWORD);
} }
} }

View file

@ -912,7 +912,7 @@ BITMAP_CopyBitmap(HBITMAP hBitmap)
return 0; return 0;
} }
Bitmap = GDIOBJ_LockObj(hBitmap, GDI_OBJECT_TYPE_BITMAP); Bitmap = SURFACE_LockSurface(hBitmap);
if (Bitmap == NULL) if (Bitmap == NULL)
{ {
return 0; return 0;
@ -925,40 +925,22 @@ BITMAP_CopyBitmap(HBITMAP hBitmap)
Size.cx = abs(bm.bmWidth); Size.cx = abs(bm.bmWidth);
Size.cy = abs(bm.bmHeight); Size.cy = abs(bm.bmHeight);
res = GreCreateBitmap(abs(bm.bmWidth), res = GreCreateBitmapEx(Size.cx,
abs(bm.bmHeight), Size.cy,
1, bm.bmWidthBytes,
bm.bmBitsPixel, Bitmap->SurfObj.iBitmapFormat,
NULL); Bitmap->SurfObj.fjBitmap,
Bitmap->SurfObj.cjBits,
NULL);
if (res) if (res)
{ {
PBYTE buf; resBitmap = SURFACE_LockSurface(res);
resBitmap = GDIOBJ_LockObj(res, GDI_OBJECT_TYPE_BITMAP);
if (resBitmap) if (resBitmap)
{ {
buf = ExAllocatePoolWithTag(PagedPool, IntSetBitmapBits(resBitmap, Bitmap->SurfObj.cjBits, Bitmap->SurfObj.pvBits);
bm.bmWidthBytes * abs(bm.bmHeight), SURFACE_UnlockSurface(resBitmap);
TAG_BITMAP);
if (buf == NULL)
{
GDIOBJ_UnlockObjByPtr((POBJ)resBitmap);
GDIOBJ_UnlockObjByPtr((POBJ)Bitmap);
GreDeleteObject(res);
return 0;
}
IntGetBitmapBits(Bitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
IntSetBitmapBits(resBitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
ExFreePoolWithTag(buf,TAG_BITMAP);
resBitmap->flags = Bitmap->flags;
/* Copy palette */
if (Bitmap->ppal)
{
resBitmap->ppal = Bitmap->ppal ;
GDIOBJ_IncrementShareCount(&Bitmap->ppal->BaseObject);
}
GDIOBJ_UnlockObjByPtr((POBJ)resBitmap);
} }
else else
{ {
@ -967,7 +949,7 @@ BITMAP_CopyBitmap(HBITMAP hBitmap)
} }
} }
GDIOBJ_UnlockObjByPtr((POBJ)Bitmap); SURFACE_UnlockSurface(Bitmap);
return res; return res;
} }

View file

@ -244,129 +244,6 @@ BRUSH_GetObject(PBRUSH pbrush, INT Count, LPLOGBRUSH Buffer)
return sizeof(LOGBRUSH); return sizeof(LOGBRUSH);
} }
/**
* @name CalculateColorTableSize
*
* Internal routine to calculate the number of color table entries.
*
* @param BitmapInfoHeader
* Input bitmap information header, can be any version of
* BITMAPINFOHEADER or BITMAPCOREHEADER.
*
* @param ColorSpec
* Pointer to variable which specifiing the color mode (DIB_RGB_COLORS
* or DIB_RGB_COLORS). On successful return this value is normalized
* according to the bitmap info.
*
* @param ColorTableSize
* On successful return this variable is filled with number of
* entries in color table for the image with specified parameters.
*
* @return
* TRUE if the input values together form a valid image, FALSE otherwise.
*/
BOOL
APIENTRY
CalculateColorTableSize(
CONST BITMAPINFOHEADER *BitmapInfoHeader,
UINT *ColorSpec,
UINT *ColorTableSize)
{
WORD BitCount;
DWORD ClrUsed;
DWORD Compression;
/*
* At first get some basic parameters from the passed BitmapInfoHeader
* structure. It can have one of the following formats:
* - BITMAPCOREHEADER (the oldest one with totally different layout
* from the others)
* - BITMAPINFOHEADER (the standard and most common header)
* - BITMAPV4HEADER (extension of BITMAPINFOHEADER)
* - BITMAPV5HEADER (extension of BITMAPV4HEADER)
*/
if (BitmapInfoHeader->biSize == sizeof(BITMAPCOREHEADER))
{
BitCount = ((LPBITMAPCOREHEADER)BitmapInfoHeader)->bcBitCount;
ClrUsed = 0;
Compression = BI_RGB;
}
else
{
BitCount = BitmapInfoHeader->biBitCount;
ClrUsed = BitmapInfoHeader->biClrUsed;
Compression = BitmapInfoHeader->biCompression;
}
switch (Compression)
{
case BI_BITFIELDS:
if (*ColorSpec == DIB_PAL_COLORS)
*ColorSpec = DIB_RGB_COLORS;
if (BitCount != 16 && BitCount != 32)
return FALSE;
/* For BITMAPV4HEADER/BITMAPV5HEADER the masks are included in
* the structure itself (bV4RedMask, bV4GreenMask, and bV4BlueMask).
* For BITMAPINFOHEADER the color masks are stored in the palette. */
if (BitmapInfoHeader->biSize > sizeof(BITMAPINFOHEADER))
*ColorTableSize = 0;
else
*ColorTableSize = 3;
return TRUE;
case BI_RGB:
switch (BitCount)
{
case 1:
*ColorTableSize = ClrUsed ? min(ClrUsed, 2) : 2;
return TRUE;
case 4:
*ColorTableSize = ClrUsed ? min(ClrUsed, 16) : 16;
return TRUE;
case 8:
*ColorTableSize = ClrUsed ? min(ClrUsed, 256) : 256;
return TRUE;
default:
if (*ColorSpec == DIB_PAL_COLORS)
*ColorSpec = DIB_RGB_COLORS;
if (BitCount != 16 && BitCount != 24 && BitCount != 32)
return FALSE;
*ColorTableSize = ClrUsed;
return TRUE;
}
case BI_RLE4:
if (BitCount == 4)
{
*ColorTableSize = ClrUsed ? min(ClrUsed, 16) : 16;
return TRUE;
}
return FALSE;
case BI_RLE8:
if (BitCount == 8)
{
*ColorTableSize = ClrUsed ? min(ClrUsed, 256) : 256;
return TRUE;
}
return FALSE;
case BI_JPEG:
case BI_PNG:
*ColorTableSize = ClrUsed;
return TRUE;
default:
return FALSE;
}
}
HBRUSH HBRUSH
APIENTRY APIENTRY
IntGdiCreateDIBBrush( IntGdiCreateDIBBrush(
@ -379,9 +256,7 @@ IntGdiCreateDIBBrush(
PBRUSH pbrush; PBRUSH pbrush;
HBITMAP hPattern; HBITMAP hPattern;
ULONG_PTR DataPtr; ULONG_PTR DataPtr;
UINT PaletteEntryCount;
PSURFACE psurfPattern; PSURFACE psurfPattern;
INT PaletteType;
HPALETTE hpal ; HPALETTE hpal ;
if (BitmapInfo->bmiHeader.biSize < sizeof(BITMAPINFOHEADER)) if (BitmapInfo->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
@ -390,20 +265,7 @@ IntGdiCreateDIBBrush(
return NULL; return NULL;
} }
if (!CalculateColorTableSize(&BitmapInfo->bmiHeader, DataPtr = (ULONG_PTR)BitmapInfo + DIB_BitmapInfoSize(BitmapInfo, ColorSpec);
&ColorSpec,
&PaletteEntryCount))
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return NULL;
}
// FIXME: What about BI_BITFIELDS
DataPtr = (ULONG_PTR)BitmapInfo + BitmapInfo->bmiHeader.biSize;
if (ColorSpec == DIB_RGB_COLORS)
DataPtr += PaletteEntryCount * sizeof(RGBQUAD);
else
DataPtr += PaletteEntryCount * sizeof(USHORT);
hPattern = GreCreateBitmap(BitmapInfo->bmiHeader.biWidth, hPattern = GreCreateBitmap(BitmapInfo->bmiHeader.biWidth,
BitmapInfo->bmiHeader.biHeight, BitmapInfo->bmiHeader.biHeight,
@ -418,7 +280,8 @@ IntGdiCreateDIBBrush(
psurfPattern = SURFACE_LockSurface(hPattern); psurfPattern = SURFACE_LockSurface(hPattern);
ASSERT(psurfPattern != NULL); ASSERT(psurfPattern != NULL);
hpal = BuildDIBPalette(BitmapInfo, &PaletteType); if(ColorSpec == DIB_PAL_COLORS) DPRINT1("FIXME, unsupported color spec!\n");
hpal = BuildDIBPalette(BitmapInfo);
psurfPattern->ppal = PALETTE_ShareLockPalette(hpal); psurfPattern->ppal = PALETTE_ShareLockPalette(hpal);
/* Lazy delete palette, it will be freed when its shared reference is zeroed */ /* Lazy delete palette, it will be freed when its shared reference is zeroed */
GreDeleteObject(hpal); GreDeleteObject(hpal);

View file

@ -262,115 +262,62 @@ IntSetDIBits(
UINT StartScan, UINT StartScan,
UINT ScanLines, UINT ScanLines,
CONST VOID *Bits, CONST VOID *Bits,
CONST BITMAPV5INFO *bmi, CONST BITMAPINFO *bmi,
UINT ColorUse) UINT ColorUse)
{ {
SURFACE *bitmap; HBITMAP SourceBitmap, hOldSrcBmp = NULL, hOldDstBmp = NULL;
HBITMAP SourceBitmap; HDC hdcSrc, hdcDst;
INT result = 0; INT result = 0;
BOOL copyBitsResult; PVOID pvBits;
SURFOBJ *DestSurf, *SourceSurf;
SIZEL SourceSize;
POINTL ZeroPoint;
RECTL DestRect;
EXLATEOBJ exlo;
PPALETTE ppalDIB;
//RGBQUAD *lpRGB;
HPALETTE DIB_Palette;
ULONG DIB_Palette_Type;
INT DIBWidth;
// Check parameters SourceBitmap = DIB_CreateDIBSection(DC, bmi, ColorUse, &pvBits, NULL, 0, 0);
if (!(bitmap = SURFACE_LockSurface(hBitmap))) if (0 == SourceBitmap)
{ {
return 0; DPRINT1("Error : Could not create a DIBSection.\n");
}
// Get RGB values
//if (ColorUse == DIB_PAL_COLORS)
// lpRGB = DIB_MapPaletteColors(hDC, bmi);
//else
// lpRGB = &bmi->bmiColors;
DestSurf = &bitmap->SurfObj;
// Create source surface
SourceSize.cx = bmi->bmiHeader.bV5Width;
SourceSize.cy = ScanLines;
// Determine width of DIB
DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.bV5BitCount);
SourceBitmap = EngCreateBitmap(SourceSize,
DIBWidth,
BitmapFormat(bmi->bmiHeader.bV5BitCount, bmi->bmiHeader.bV5Compression),
bmi->bmiHeader.bV5Height < 0 ? BMF_TOPDOWN : 0,
(PVOID) Bits);
if (0 == SourceBitmap)
{
SURFACE_UnlockSurface(bitmap);
SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES); SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
return 0; return 0;
} }
SourceSurf = EngLockSurface((HSURF)SourceBitmap); RtlCopyMemory(pvBits, Bits, DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
if (NULL == SourceSurf) bmi->bmiHeader.biHeight,
{ bmi->bmiHeader.biBitCount));
EngDeleteSurface((HSURF)SourceBitmap);
SURFACE_UnlockSurface(bitmap);
SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
return 0;
}
ASSERT(bitmap->ppal); hdcSrc = NtGdiCreateCompatibleDC(0);
hdcDst = NtGdiCreateCompatibleDC(0);
// Source palette obtained from the BITMAPINFO if(!(hdcSrc && hdcDst))
DIB_Palette = BuildDIBPalette((BITMAPINFO*)bmi, (PINT)&DIB_Palette_Type); {
if (NULL == DIB_Palette) DPRINT1("Error, could not create memory DCs.\n");
{ goto cleanup;
EngUnlockSurface(SourceSurf); }
EngDeleteSurface((HSURF)SourceBitmap);
SURFACE_UnlockSurface(bitmap);
SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
return 0;
}
ppalDIB = PALETTE_LockPalette(DIB_Palette); hOldSrcBmp = NtGdiSelectBitmap(hdcSrc, SourceBitmap);
hOldDstBmp = NtGdiSelectBitmap(hdcDst, hBitmap);
/* Initialize XLATEOBJ for color translation */ if(!(hOldSrcBmp && hOldDstBmp))
EXLATEOBJ_vInitialize(&exlo, ppalDIB, bitmap->ppal, 0, 0, 0); {
DPRINT1("Error : Could not select bitmaps into DCs\n");
goto cleanup;
}
// Zero point result = NtGdiBitBlt(hdcDst, 0, 0, bmi->bmiHeader.biWidth, ScanLines, hdcSrc, 0, StartScan,
ZeroPoint.x = 0; SRCCOPY, 0, 0);
ZeroPoint.y = 0;
// Determine destination rectangle if(result)
DestRect.left = 0; result = ScanLines;
DestRect.top = abs(bmi->bmiHeader.bV5Height) - StartScan - ScanLines;
DestRect.right = SourceSize.cx;
DestRect.bottom = DestRect.top + ScanLines;
copyBitsResult = IntEngCopyBits(DestSurf, SourceSurf, NULL, &exlo.xlo, &DestRect, &ZeroPoint); cleanup:
if(hdcSrc)
// If it succeeded, return number of scanlines copies {
if (copyBitsResult == TRUE) if(hOldSrcBmp) NtGdiSelectBitmap(hdcSrc, hOldSrcBmp);
{ NtGdiDeleteObjectApp(hdcSrc);
result = SourceSize.cy; }
// or if(hdcDst)
// result = abs(bmi->bmiHeader.biHeight) - StartScan; {
} if(hOldDstBmp) NtGdiSelectBitmap(hdcDst, hOldDstBmp);
NtGdiDeleteObjectApp(hdcDst);
// Clean up }
EXLATEOBJ_vCleanup(&exlo); GreDeleteObject(SourceBitmap);
PALETTE_UnlockPalette(ppalDIB);
PALETTE_FreePaletteByHandle(DIB_Palette);
EngUnlockSurface(SourceSurf);
EngDeleteSurface((HSURF)SourceBitmap);
// if (ColorUse == DIB_PAL_COLORS)
// WinFree((LPSTR)lpRGB);
SURFACE_UnlockSurface(bitmap);
return result; return result;
} }
@ -392,14 +339,19 @@ NtGdiSetDIBits(
PDC Dc; PDC Dc;
INT Ret; INT Ret;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
BITMAPV5INFO bmiLocal;
if (!Bits) return 0; if (!Bits) return 0;
_SEH2_TRY _SEH2_TRY
{ {
Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, bmi, ColorUse, 0); ProbeForRead(&bmi->bmiHeader.biSize, sizeof(DWORD), 1);
ProbeForRead(Bits, bmiLocal.bmiHeader.bV5SizeImage, 1); ProbeForRead(bmi, bmi->bmiHeader.biSize, 1);
ProbeForRead(bmi, DIB_BitmapInfoSize(bmi, ColorUse), 1);
ProbeForRead(Bits,
DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
ScanLines,
bmi->bmiHeader.biBitCount),
1);
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {
@ -424,7 +376,7 @@ NtGdiSetDIBits(
return 0; return 0;
} }
Ret = IntSetDIBits(Dc, hBitmap, StartScan, ScanLines, Bits, &bmiLocal, ColorUse); Ret = IntSetDIBits(Dc, hBitmap, StartScan, ScanLines, Bits, bmi, ColorUse);
DC_UnlockDc(Dc); DC_UnlockDc(Dc);
@ -465,14 +417,12 @@ NtGdiSetDIBitsToDeviceInternal(
EXLATEOBJ exlo; EXLATEOBJ exlo;
PPALETTE ppalDIB = NULL; PPALETTE ppalDIB = NULL;
HPALETTE hpalDIB = NULL; HPALETTE hpalDIB = NULL;
ULONG DIBPaletteType;
BITMAPV5INFO bmiLocal ;
if (!Bits) return 0; if (!Bits) return 0;
_SEH2_TRY _SEH2_TRY
{ {
Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, bmi, ColorUse, cjMaxInfo); ProbeForRead(bmi, cjMaxInfo, 1);
ProbeForRead(Bits, cjMaxBits, 1); ProbeForRead(Bits, cjMaxBits, 1);
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
@ -502,7 +452,7 @@ NtGdiSetDIBitsToDeviceInternal(
pDestSurf = pSurf ? &pSurf->SurfObj : NULL; pDestSurf = pSurf ? &pSurf->SurfObj : NULL;
ScanLines = min(ScanLines, abs(bmiLocal.bmiHeader.bV5Height) - StartScan); ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan);
rcDest.left = XDest; rcDest.left = XDest;
rcDest.top = YDest; rcDest.top = YDest;
@ -519,16 +469,16 @@ NtGdiSetDIBitsToDeviceInternal(
ptSource.x = XSrc; ptSource.x = XSrc;
ptSource.y = YSrc; ptSource.y = YSrc;
SourceSize.cx = bmiLocal.bmiHeader.bV5Width; SourceSize.cx = bmi->bmiHeader.biWidth;
SourceSize.cy = ScanLines; SourceSize.cy = ScanLines;
DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmiLocal.bmiHeader.bV5BitCount); DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount);
hSourceBitmap = EngCreateBitmap(SourceSize, hSourceBitmap = EngCreateBitmap(SourceSize,
DIBWidth, DIBWidth,
BitmapFormat(bmiLocal.bmiHeader.bV5BitCount, BitmapFormat(bmi->bmiHeader.biBitCount,
bmiLocal.bmiHeader.bV5Compression), bmi->bmiHeader.biCompression),
bmiLocal.bmiHeader.bV5Height < 0 ? BMF_TOPDOWN : 0, bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
(PVOID) Bits); (PVOID) Bits);
if (!hSourceBitmap) if (!hSourceBitmap)
{ {
@ -547,7 +497,7 @@ NtGdiSetDIBitsToDeviceInternal(
ASSERT(pSurf->ppal); ASSERT(pSurf->ppal);
/* Create a palette for the DIB */ /* Create a palette for the DIB */
hpalDIB = BuildDIBPalette((PBITMAPINFO)&bmiLocal, (PINT)&DIBPaletteType); hpalDIB = BuildDIBPalette(bmi);
if (!hpalDIB) if (!hpalDIB)
{ {
SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES); SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
@ -697,13 +647,6 @@ NtGdiGetDIBitsInternal(
ScanLines = 0; ScanLines = 0;
goto done; goto done;
} }
/* Must not be selected */
if(psurf->hdc != NULL)
{
ScanLines = 0;
SetLastWin32Error(ERROR_INVALID_PARAMETER);
goto done;
}
/* Fill in the structure */ /* Fill in the structure */
switch(bpp) switch(bpp)
@ -948,13 +891,14 @@ NtGdiGetDIBitsInternal(
} }
break; break;
} }
Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(width, height, bpp);
if(Bits && ScanLines) if(Bits && ScanLines)
{ {
/* Create a DIBSECTION, blt it, profit */ /* Create a DIBSECTION, blt it, profit */
PVOID pDIBits ; PVOID pDIBits ;
HBITMAP hBmpDest, hOldDest = NULL, hOldSrc = NULL; HBITMAP hBmpDest, hOldDest = NULL, hOldSrc = NULL;
HDC hdcDest, hdcSrc; HDC hdcDest = NULL, hdcSrc;
BOOL ret ; BOOL ret ;
if (StartScan > psurf->SurfObj.sizlBitmap.cy) if (StartScan > psurf->SurfObj.sizlBitmap.cy)
@ -977,22 +921,38 @@ NtGdiGetDIBitsInternal(
goto done ; goto done ;
} }
hdcDest = NtGdiCreateCompatibleDC(0); if(psurf->hdc)
hdcSrc = NtGdiCreateCompatibleDC(0); hdcSrc = psurf->hdc;
else
if(!(hdcSrc && hdcDest))
{ {
DPRINT1("Error: could not create HDCs!\n"); hdcSrc = NtGdiCreateCompatibleDC(0);
if(!hdcSrc)
{
DPRINT1("Error: could not create HDC!\n");
ScanLines = 0;
goto cleanup_blt;
}
hOldSrc = NtGdiSelectBitmap(hdcSrc, hBitmap);
if(!hOldSrc)
{
DPRINT1("Error : Could not Select bitmap\n");
ScanLines = 0;
goto cleanup_blt;
}
}
hdcDest = NtGdiCreateCompatibleDC(0);
if(!hdcDest)
{
DPRINT1("Error: could not create HDC!\n");
ScanLines = 0; ScanLines = 0;
goto cleanup_blt; goto cleanup_blt;
} }
hOldDest = NtGdiSelectBitmap(hdcDest, hBmpDest); hOldDest = NtGdiSelectBitmap(hdcDest, hBmpDest);
hOldSrc = NtGdiSelectBitmap(hdcSrc, hBitmap); if(!hOldDest)
if(!(hOldDest && hOldSrc))
{ {
DPRINT1("Error : Could not Select bitmaps\n"); DPRINT1("Error : Could not Select bitmap\n");
ScanLines = 0;
goto cleanup_blt; goto cleanup_blt;
} }
@ -1035,7 +995,7 @@ NtGdiGetDIBitsInternal(
} }
cleanup_blt: cleanup_blt:
if(hdcSrc) if(hdcSrc && (hdcSrc != psurf->hdc))
{ {
if(hOldSrc) NtGdiSelectBitmap(hdcSrc, hOldSrc); if(hOldSrc) NtGdiSelectBitmap(hdcSrc, hOldSrc);
NtGdiDeleteObjectApp(hdcSrc); NtGdiDeleteObjectApp(hdcSrc);
@ -1079,11 +1039,10 @@ NtGdiStretchDIBitsInternal(
HANDLE hcmXform) HANDLE hcmXform)
{ {
HBITMAP hBitmap, hOldBitmap = NULL; HBITMAP hBitmap, hOldBitmap = NULL;
HDC hdcMem; HDC hdcMem = NULL;
HPALETTE hPal = NULL; NTSTATUS Status = STATUS_SUCCESS;
PDC pDC; PVOID pvDIBits;
NTSTATUS Status; INT Ret = 0;
BITMAPV5INFO bmiLocal ;
if (!Bits || !BitsInfo) if (!Bits || !BitsInfo)
{ {
@ -1091,101 +1050,82 @@ NtGdiStretchDIBitsInternal(
return 0; return 0;
} }
_SEH2_TRY /* Create a DIB Section, data will be probed there */
{ hBitmap = NtGdiCreateDIBSection(hDC,
Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, BitsInfo, Usage, cjMaxInfo); NULL,
ProbeForRead(Bits, cjMaxBits, 1); 0,
} BitsInfo,
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) Usage,
{ 0,
Status = _SEH2_GetExceptionCode(); 0,
} 0,
_SEH2_END &pvDIBits);
if (!NT_SUCCESS(Status)) if(!hBitmap)
{ {
DPRINT1("NtGdiStretchDIBitsInternal fail to read BitMapInfo: %x or Bits: %x\n",BitsInfo,Bits); DPRINT1("Failed to create a DIB.\n");
return 0; return 0;
} }
hdcMem = NtGdiCreateCompatibleDC(hDC); _SEH2_TRY
if (hdcMem == NULL) {
{ ProbeForRead(Bits, cjMaxBits, 1);
DPRINT1("NtGdiCreateCompatibleDC fail create hdc\n"); RtlCopyMemory(pvDIBits, Bits, DIB_GetDIBImageBytes(BitsInfo->bmiHeader.biWidth,
return 0; BitsInfo->bmiHeader.biHeight,
} BitsInfo->bmiHeader.biBitCount));
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END
hBitmap = NtGdiCreateCompatibleBitmap(hDC, if(!NT_SUCCESS(Status))
abs(bmiLocal.bmiHeader.bV5Width), {
abs(bmiLocal.bmiHeader.bV5Height)); DPRINT1("Error : Could not read DIB bits\n");
if (hBitmap == NULL) SetLastNtError(Status);
{ goto cleanup;
DPRINT1("NtGdiCreateCompatibleBitmap fail create bitmap\n"); }
DPRINT1("hDC : 0x%08x \n", hDC);
DPRINT1("BitsInfo->bmiHeader.biWidth : 0x%08x \n", BitsInfo->bmiHeader.biWidth);
DPRINT1("BitsInfo->bmiHeader.biHeight : 0x%08x \n", BitsInfo->bmiHeader.biHeight);
return 0;
}
/* Select the bitmap into hdcMem, and save a handle to the old bitmap */ hdcMem = NtGdiCreateCompatibleDC(0);
hOldBitmap = NtGdiSelectBitmap(hdcMem, hBitmap); if(!hdcMem)
{
DPRINT1("Failed to create a memory DC!");
goto cleanup;
}
if (Usage == DIB_PAL_COLORS) hOldBitmap = NtGdiSelectBitmap(hdcMem, hBitmap);
{ if(!hOldBitmap)
hPal = NtGdiGetDCObject(hDC, GDI_OBJECT_TYPE_PALETTE); {
hPal = GdiSelectPalette(hdcMem, hPal, FALSE); DPRINT1("Could not select the DIB into the memory DC\n");
} goto cleanup;
}
if (bmiLocal.bmiHeader.bV5Compression == BI_RLE4 || /* Do we want to stretch ? */
bmiLocal.bmiHeader.bV5Compression == BI_RLE8) if((SrcWidth == DestWidth) && (SrcHeight == DestHeight))
{ {
/* copy existing bitmap from destination dc */ Ret = NtGdiBitBlt(hDC, XDest, YDest, XDest + DestWidth, YDest + DestHeight,
if (SrcWidth == DestWidth && SrcHeight == DestHeight) hdcMem, XSrc, YSrc, ROP, 0, 0);
NtGdiBitBlt(hdcMem, XSrc, abs(bmiLocal.bmiHeader.bV5Height) - SrcHeight - YSrc, }
SrcWidth, SrcHeight, hDC, XDest, YDest, ROP, 0, 0); else
else {
NtGdiStretchBlt(hdcMem, XSrc, abs(bmiLocal.bmiHeader.bV5Height) - SrcHeight - YSrc, Ret = NtGdiStretchBlt(hDC, XDest, YDest, XDest + DestWidth, YDest + DestHeight,
SrcWidth, SrcHeight, hDC, XDest, YDest, DestWidth, DestHeight, hdcMem, XSrc, YSrc, XSrc + SrcWidth, YSrc + SrcHeight,
ROP, 0); ROP, 0);
} }
pDC = DC_LockDc(hdcMem); if(Ret)
if (pDC != NULL) Ret = SrcHeight ;
{
/* Note BitsInfo->bmiHeader.biHeight is the number of scanline,
* if it negitve we getting to many scanline for scanline is UINT not
* a INT, so we need make the negtive value to positve and that make the
* count correct for negtive bitmap, TODO : we need testcase for this api */
IntSetDIBits(pDC, hBitmap, 0, abs(bmiLocal.bmiHeader.bV5Height), Bits,
&bmiLocal, Usage);
DC_UnlockDc(pDC); cleanup:
} if(hdcMem)
{
if(hOldBitmap) NtGdiSelectBitmap(hdcMem, hOldBitmap);
NtGdiDeleteObjectApp(hdcMem);
}
GreDeleteObject(hBitmap);
return Ret;
/* Origin for DIBitmap may be bottom left (positive biHeight) or top
left (negative biHeight) */
if (SrcWidth == DestWidth && SrcHeight == DestHeight)
NtGdiBitBlt(hDC, XDest, YDest, DestWidth, DestHeight,
hdcMem, XSrc, abs(bmiLocal.bmiHeader.bV5Height) - SrcHeight - YSrc,
ROP, 0, 0);
else
NtGdiStretchBlt(hDC, XDest, YDest, DestWidth, DestHeight,
hdcMem, XSrc, abs(bmiLocal.bmiHeader.bV5Height) - SrcHeight - YSrc,
SrcWidth, SrcHeight, ROP, 0);
/* cleanup */
if (hPal)
GdiSelectPalette(hdcMem, hPal, FALSE);
if (hOldBitmap)
NtGdiSelectBitmap(hdcMem, hOldBitmap);
NtGdiDeleteObjectApp(hdcMem);
GreDeleteObject(hBitmap);
return SrcHeight;
} }
@ -1198,7 +1138,7 @@ IntCreateDIBitmap(
UINT bpp, UINT bpp,
DWORD init, DWORD init,
LPBYTE bits, LPBYTE bits,
PBITMAPV5INFO data, PBITMAPINFO data,
DWORD coloruse) DWORD coloruse)
{ {
HBITMAP handle; HBITMAP handle;
@ -1211,7 +1151,7 @@ IntCreateDIBitmap(
else if ((coloruse != DIB_RGB_COLORS) || (init != CBM_INIT) || !data) fColor = FALSE; else if ((coloruse != DIB_RGB_COLORS) || (init != CBM_INIT) || !data) fColor = FALSE;
else else
{ {
const RGBQUAD *rgb = data->bmiColors; const RGBQUAD *rgb = (RGBQUAD*)((PBYTE)data + data->bmiHeader.biSize);
DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue); DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
// Check if the first color of the colormap is black // Check if the first color of the colormap is black
@ -1268,12 +1208,11 @@ NtGdiCreateDIBitmapInternal(
IN FLONG fl, IN FLONG fl,
IN HANDLE hcmXform) IN HANDLE hcmXform)
{ {
BITMAPV5INFO bmiLocal ;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
_SEH2_TRY _SEH2_TRY
{ {
if(pbmi) Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, pbmi, iUsage, cjMaxInitInfo); if(pbmi) ProbeForRead(pbmi, cjMaxInitInfo, 1);
if(pjInit && (fInit == CBM_INIT)) ProbeForRead(pjInit, cjMaxBits, 1); if(pjInit && (fInit == CBM_INIT)) ProbeForRead(pjInit, cjMaxBits, 1);
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
@ -1293,7 +1232,7 @@ NtGdiCreateDIBitmapInternal(
cy, cy,
fInit, fInit,
pjInit, pjInit,
pbmi ? &bmiLocal : NULL, pbmi,
iUsage, iUsage,
fl, fl,
hcmXform); hcmXform);
@ -1307,7 +1246,7 @@ GreCreateDIBitmapInternal(
IN INT cy, IN INT cy,
IN DWORD fInit, IN DWORD fInit,
IN OPTIONAL LPBYTE pjInit, IN OPTIONAL LPBYTE pjInit,
IN OPTIONAL PBITMAPV5INFO pbmi, IN OPTIONAL PBITMAPINFO pbmi,
IN DWORD iUsage, IN DWORD iUsage,
IN FLONG fl, IN FLONG fl,
IN HANDLE hcmXform) IN HANDLE hcmXform)
@ -1339,7 +1278,7 @@ GreCreateDIBitmapInternal(
/* It's OK to set bpp=0 here, as IntCreateDIBitmap will create a compatible Bitmap /* It's OK to set bpp=0 here, as IntCreateDIBitmap will create a compatible Bitmap
* if bpp != 1 and ignore the real value that was passed */ * if bpp != 1 and ignore the real value that was passed */
if (pbmi) if (pbmi)
bpp = pbmi->bmiHeader.bV5BitCount; bpp = pbmi->bmiHeader.biBitCount;
else else
bpp = 0; bpp = 0;
Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage); Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
@ -1435,7 +1374,6 @@ DIB_CreateDIBSection(
SURFACE *bmp = NULL; SURFACE *bmp = NULL;
void *mapBits = NULL; void *mapBits = NULL;
HPALETTE hpal ; HPALETTE hpal ;
INT palMode = PAL_INDEXED;
// Fill BITMAP32 structure with DIB data // Fill BITMAP32 structure with DIB data
CONST BITMAPINFOHEADER *bi = &bmi->bmiHeader; CONST BITMAPINFOHEADER *bi = &bmi->bmiHeader;
@ -1527,24 +1465,18 @@ DIB_CreateDIBSection(
{ {
PPALETTE pdcPal ; PPALETTE pdcPal ;
pdcPal = PALETTE_LockPalette(dc->dclevel.hpal); pdcPal = PALETTE_LockPalette(dc->dclevel.hpal);
if(!pdcPal) hpal = DIB_MapPaletteColors(pdcPal, bmi);
{
DPRINT1("Unable to lock DC palette?!\n");
goto cleanup;
}
if(pdcPal->Mode != PAL_INDEXED)
{
DPRINT1("Not indexed palette selected in the DC?!\n");
PALETTE_UnlockPalette(pdcPal);
}
hpal = PALETTE_AllocPalette(PAL_INDEXED,
pdcPal->NumColors,
(ULONG*)pdcPal->IndexedColors, 0, 0, 0);
PALETTE_UnlockPalette(pdcPal); PALETTE_UnlockPalette(pdcPal);
} }
else else
{ {
hpal = BuildDIBPalette(bmi, &palMode); hpal = BuildDIBPalette(bmi);
}
if(!hpal)
{
DPRINT1("Error : Could not create a aplette for the DIB.\n");
goto cleanup;
} }
// Create Device Dependent Bitmap and add DIB pointer // Create Device Dependent Bitmap and add DIB pointer
@ -1716,74 +1648,72 @@ INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
} }
} }
RGBQUAD * HPALETTE
FASTCALL FASTCALL
DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi) DIB_MapPaletteColors(PPALETTE ppal, CONST BITMAPINFO* lpbmi)
{ {
RGBQUAD *lpRGB; PALETTEENTRY* ppalEntries;
ULONG nNumColors,i; ULONG nNumColors,i;
USHORT *lpIndex; USHORT *lpIndex;
PPALETTE palGDI; HPALETTE hpal;
palGDI = PALETTE_LockPalette(dc->dclevel.hpal); if (ppal->Mode != PAL_INDEXED)
if (NULL == palGDI)
{ {
return NULL; return NULL;
} }
if (palGDI->Mode != PAL_INDEXED)
{
PALETTE_UnlockPalette(palGDI);
return NULL;
}
nNumColors = 1 << lpbmi->bmiHeader.biBitCount; nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
if (lpbmi->bmiHeader.biClrUsed) if (lpbmi->bmiHeader.biClrUsed)
{ {
nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed); nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
} }
lpRGB = (RGBQUAD *)ExAllocatePoolWithTag(PagedPool, sizeof(RGBQUAD) * nNumColors, TAG_COLORMAP); /* Don't have more colors than we need */
if (lpRGB == NULL) nNumColors = min(ppal->NumColors, nNumColors);
ppalEntries = ExAllocatePoolWithTag(PagedPool, sizeof(PALETTEENTRY) * nNumColors, TAG_COLORMAP);
if (ppalEntries == NULL)
{ {
PALETTE_UnlockPalette(palGDI); DPRINT1("Could not allocate palette entries\n");
return NULL; return NULL;
} }
lpIndex = (USHORT *)&lpbmi->bmiColors[0]; lpIndex = (USHORT *)((PBYTE)lpbmi + lpbmi->bmiHeader.biSize);
for (i = 0; i < nNumColors; i++) for (i = 0; i < nNumColors; i++)
{ {
if (*lpIndex < palGDI->NumColors) if (*lpIndex < ppal->NumColors)
{ {
lpRGB[i].rgbRed = palGDI->IndexedColors[*lpIndex].peRed; ppalEntries[i] = ppal->IndexedColors[*lpIndex];
lpRGB[i].rgbGreen = palGDI->IndexedColors[*lpIndex].peGreen;
lpRGB[i].rgbBlue = palGDI->IndexedColors[*lpIndex].peBlue;
} }
else else
{ {
lpRGB[i].rgbRed = 0; ppalEntries[i].peRed = 0;
lpRGB[i].rgbGreen = 0; ppalEntries[i].peGreen = 0;
lpRGB[i].rgbBlue = 0; ppalEntries[i].peBlue = 0;
ppalEntries[i].peFlags = 0;
} }
lpRGB[i].rgbReserved = 0;
lpIndex++; lpIndex++;
} }
PALETTE_UnlockPalette(palGDI);
hpal = PALETTE_AllocPalette(PAL_INDEXED, nNumColors, (ULONG*)ppalEntries, 0, 0, 0);
return lpRGB; ExFreePoolWithTag(ppalEntries, TAG_COLORMAP);
return hpal;
} }
HPALETTE HPALETTE
FASTCALL FASTCALL
BuildDIBPalette(CONST BITMAPINFO *bmi, PINT paletteType) BuildDIBPalette(CONST BITMAPINFO *bmi)
{ {
BYTE bits; BYTE bits;
ULONG ColorCount; ULONG ColorCount;
HPALETTE hPal; HPALETTE hPal;
ULONG RedMask, GreenMask, BlueMask; ULONG RedMask = 0, GreenMask = 0, BlueMask = 0;
PDWORD pdwColors = (PDWORD)((PBYTE)bmi + bmi->bmiHeader.biSize); PDWORD pdwColors = (PDWORD)((PBYTE)bmi + bmi->bmiHeader.biSize);
INT paletteType;
// Determine Bits Per Pixel // Determine Bits Per Pixel
bits = bmi->bmiHeader.biBitCount; bits = bmi->bmiHeader.biBitCount;
@ -1791,36 +1721,36 @@ BuildDIBPalette(CONST BITMAPINFO *bmi, PINT paletteType)
// Determine paletteType from Bits Per Pixel // Determine paletteType from Bits Per Pixel
if (bits <= 8) if (bits <= 8)
{ {
*paletteType = PAL_INDEXED; paletteType = PAL_INDEXED;
RedMask = GreenMask = BlueMask = 0; RedMask = GreenMask = BlueMask = 0;
} }
else if (bmi->bmiHeader.biCompression == BI_BITFIELDS) else if (bmi->bmiHeader.biCompression == BI_BITFIELDS)
{ {
*paletteType = PAL_BITFIELDS; paletteType = PAL_BITFIELDS;
RedMask = pdwColors[0]; RedMask = pdwColors[0];
GreenMask = pdwColors[1]; GreenMask = pdwColors[1];
BlueMask = pdwColors[2]; BlueMask = pdwColors[2];
} }
else if (bits == 15) else if (bits == 15)
{ {
*paletteType = PAL_BITFIELDS; paletteType = PAL_RGB16_555;
RedMask = 0x7c00;
GreenMask = 0x03e0;
BlueMask = 0x001f;
} }
else if (bits == 16) else if (bits == 16)
{ {
*paletteType = PAL_BITFIELDS; paletteType = PAL_RGB16_565;
RedMask = 0xF800;
GreenMask = 0x07e0;
BlueMask = 0x001f;
} }
else else
{ {
*paletteType = PAL_RGB; if((pdwColors[0] == 0x0000FF) /* R */
RedMask = 0xff0000; && (pdwColors[1] == 0x00FF00) /* G */
GreenMask = 0x00ff00; && (pdwColors[2] == 0xFF0000))/* B */
BlueMask = 0x0000ff; {
paletteType = PAL_BGR;
}
else
{
paletteType == PAL_RGB;
}
} }
if (bmi->bmiHeader.biClrUsed == 0) if (bmi->bmiHeader.biClrUsed == 0)
@ -1832,13 +1762,13 @@ BuildDIBPalette(CONST BITMAPINFO *bmi, PINT paletteType)
ColorCount = bmi->bmiHeader.biClrUsed; ColorCount = bmi->bmiHeader.biClrUsed;
} }
if (PAL_INDEXED == *paletteType) if (PAL_INDEXED == paletteType)
{ {
hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)pdwColors); hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)pdwColors);
} }
else else
{ {
hPal = PALETTE_AllocPalette(*paletteType, 0, hPal = PALETTE_AllocPalette(paletteType, 0,
NULL, NULL,
RedMask, GreenMask, BlueMask); RedMask, GreenMask, BlueMask);
} }
@ -1846,195 +1776,6 @@ BuildDIBPalette(CONST BITMAPINFO *bmi, PINT paletteType)
return hPal; return hPal;
} }
FORCEINLINE
DWORD
GetBMIColor(CONST BITMAPINFO* pbmi, INT i)
{
DWORD dwRet = 0;
INT size;
if(pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{
/* BITMAPCOREINFO holds RGBTRIPLE values */
size = sizeof(RGBTRIPLE);
}
else
{
size = sizeof(RGBQUAD);
}
memcpy(&dwRet, (PBYTE)pbmi + pbmi->bmiHeader.biSize + i*size, size);
return dwRet;
}
NTSTATUS
FASTCALL
ProbeAndConvertToBitmapV5Info(
OUT PBITMAPV5INFO pbmiDst,
IN CONST BITMAPINFO* pbmiUnsafe,
IN DWORD dwColorUse,
IN UINT MaxSize)
{
DWORD dwSize;
ULONG ulWidthBytes;
PBITMAPV5HEADER pbmhDst = &pbmiDst->bmiHeader;
/* Get the size and probe */
ProbeForRead(&pbmiUnsafe->bmiHeader.biSize, sizeof(DWORD), 1);
dwSize = pbmiUnsafe->bmiHeader.biSize;
/* At least dwSize bytes must be valids */
ProbeForRead(pbmiUnsafe, max(dwSize, MaxSize), 1);
if(!MaxSize)
ProbeForRead(pbmiUnsafe, DIB_BitmapInfoSize(pbmiUnsafe, dwColorUse), 1);
/* Check the size */
// FIXME: are intermediate sizes allowed? As what are they interpreted?
// make sure we don't use a too big dwSize later
if (dwSize != sizeof(BITMAPCOREHEADER) &&
dwSize != sizeof(BITMAPINFOHEADER) &&
dwSize != sizeof(BITMAPV4HEADER) &&
dwSize != sizeof(BITMAPV5HEADER))
{
return STATUS_INVALID_PARAMETER;
}
if (dwSize == sizeof(BITMAPCOREHEADER))
{
PBITMAPCOREHEADER pbch = (PBITMAPCOREHEADER)pbmiUnsafe;
/* Manually copy the fields that are present */
pbmhDst->bV5Width = pbch->bcWidth;
pbmhDst->bV5Height = pbch->bcHeight;
pbmhDst->bV5Planes = pbch->bcPlanes;
pbmhDst->bV5BitCount = pbch->bcBitCount;
/* Set some default values */
pbmhDst->bV5Compression = BI_RGB;
pbmhDst->bV5SizeImage = DIB_GetDIBImageBytes(pbch->bcWidth,
pbch->bcHeight,
pbch->bcPlanes*pbch->bcBitCount) ;
pbmhDst->bV5XPelsPerMeter = 72;
pbmhDst->bV5YPelsPerMeter = 72;
pbmhDst->bV5ClrUsed = 0;
pbmhDst->bV5ClrImportant = 0;
}
else
{
/* Copy valid fields */
memcpy(pbmiDst, pbmiUnsafe, dwSize);
if(!pbmhDst->bV5SizeImage)
pbmhDst->bV5SizeImage = DIB_GetDIBImageBytes(pbmhDst->bV5Width,
pbmhDst->bV5Height,
pbmhDst->bV5Planes*pbmhDst->bV5BitCount) ;
if(dwSize < sizeof(BITMAPV5HEADER))
{
/* Zero out the rest of the V5 header */
memset((char*)pbmiDst + dwSize, 0, sizeof(BITMAPV5HEADER) - dwSize);
}
}
pbmhDst->bV5Size = sizeof(BITMAPV5HEADER);
if (dwSize < sizeof(BITMAPV4HEADER))
{
if (pbmhDst->bV5Compression == BI_BITFIELDS)
{
pbmhDst->bV5RedMask = GetBMIColor(pbmiUnsafe, 0);
pbmhDst->bV5GreenMask = GetBMIColor(pbmiUnsafe, 1);
pbmhDst->bV5BlueMask = GetBMIColor(pbmiUnsafe, 2);
pbmhDst->bV5AlphaMask = 0;
pbmhDst->bV5ClrUsed = 0;
}
// pbmhDst->bV5CSType;
// pbmhDst->bV5Endpoints;
// pbmhDst->bV5GammaRed;
// pbmhDst->bV5GammaGreen;
// pbmhDst->bV5GammaBlue;
}
if (dwSize < sizeof(BITMAPV5HEADER))
{
// pbmhDst->bV5Intent;
// pbmhDst->bV5ProfileData;
// pbmhDst->bV5ProfileSize;
// pbmhDst->bV5Reserved;
}
ulWidthBytes = ((pbmhDst->bV5Width * pbmhDst->bV5Planes *
pbmhDst->bV5BitCount + 31) & ~31) / 8;
if (pbmhDst->bV5SizeImage == 0)
pbmhDst->bV5SizeImage = abs(ulWidthBytes * pbmhDst->bV5Height);
if (pbmhDst->bV5ClrUsed == 0)
{
switch(pbmhDst->bV5BitCount)
{
case 1:
pbmhDst->bV5ClrUsed = 2;
break;
case 4:
pbmhDst->bV5ClrUsed = 16;
break;
case 8:
pbmhDst->bV5ClrUsed = 256;
break;
default:
pbmhDst->bV5ClrUsed = 0;
break;
}
}
if (pbmhDst->bV5Planes != 1)
{
return STATUS_INVALID_PARAMETER;
}
if (pbmhDst->bV5BitCount != 0 && pbmhDst->bV5BitCount != 1 &&
pbmhDst->bV5BitCount != 4 && pbmhDst->bV5BitCount != 8 &&
pbmhDst->bV5BitCount != 16 && pbmhDst->bV5BitCount != 24 &&
pbmhDst->bV5BitCount != 32)
{
DPRINT("Invalid bit count: %d\n", pbmhDst->bV5BitCount);
return STATUS_INVALID_PARAMETER;
}
if ((pbmhDst->bV5BitCount == 0 &&
pbmhDst->bV5Compression != BI_JPEG && pbmhDst->bV5Compression != BI_PNG))
{
DPRINT("Bit count 0 is invalid for compression %d.\n", pbmhDst->bV5Compression);
return STATUS_INVALID_PARAMETER;
}
if (pbmhDst->bV5Compression == BI_BITFIELDS &&
pbmhDst->bV5BitCount != 16 && pbmhDst->bV5BitCount != 32)
{
DPRINT("Bit count %d is invalid for compression BI_BITFIELDS.\n", pbmhDst->bV5BitCount);
return STATUS_INVALID_PARAMETER;
}
/* Copy Colors */
if(pbmhDst->bV5ClrUsed)
{
INT i;
if(dwColorUse == DIB_PAL_COLORS)
{
RtlCopyMemory(pbmiDst->bmiColors,
pbmiUnsafe->bmiColors,
pbmhDst->bV5ClrUsed * sizeof(WORD));
}
else
{
for(i = 0; i < pbmhDst->bV5ClrUsed; i++)
{
((DWORD*)pbmiDst->bmiColors)[i] = GetBMIColor(pbmiUnsafe, i);
}
}
}
return STATUS_SUCCESS;
}
/* Converts a BITMAPCOREINFO to a BITMAPINFO structure, /* Converts a BITMAPCOREINFO to a BITMAPINFO structure,
* or does nothing if it's already a BITMAPINFO (or V4 or V5) */ * or does nothing if it's already a BITMAPINFO (or V4 or V5) */
BITMAPINFO* BITMAPINFO*