📄 dibobj.c
字号:
RGBQUAD *lpRGB;
DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
bm.bmType = 0;
bm.bmWidth = bi->biWidth;
bm.bmHeight = effHeight;
bm.bmWidthBytes = ovr_pitch ? ovr_pitch : (ULONG) DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
bm.bmPlanes = bi->biPlanes;
bm.bmBitsPixel = bi->biBitCount;
bm.bmBits = NULL;
// Get storage location for DIB bits. Only use biSizeImage if it's valid and
// we're dealing with a compressed bitmap. Otherwise, use width * height.
totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
? bi->biSizeImage : (ULONG) (bm.bmWidthBytes * effHeight);
if (section)
{
/* bm.bmBits = MapViewOfFile(section, FILE_MAP_ALL_ACCESS,
0L, offset, totalSize); */
DbgPrint("DIB_CreateDIBSection: Cannot yet handle section DIBs\n");
SetLastWin32Error(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
else if (ovr_pitch && offset)
bm.bmBits = (LPVOID) offset;
else {
offset = 0;
bm.bmBits = EngAllocUserMem(totalSize, 0);
}
if(usage == DIB_PAL_COLORS)
lpRGB = DIB_MapPaletteColors(dc, bmi);
else
lpRGB = bmi->bmiColors;
// Allocate Memory for DIB and fill structure
if (bm.bmBits)
{
dib = ExAllocatePoolWithTag(PagedPool, sizeof(DIBSECTION), TAG_DIB);
if (dib != NULL) RtlZeroMemory(dib, sizeof(DIBSECTION));
}
if (dib)
{
dib->dsBm = bm;
dib->dsBmih = *bi;
dib->dsBmih.biSizeImage = totalSize;
/* Set dsBitfields values */
if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
{
dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
}
else switch(bi->biBitCount)
{
case 16:
dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)lpRGB : 0x7c00;
dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 1) : 0x03e0;
dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 2) : 0x001f; break;
case 24:
dib->dsBitfields[0] = 0xff0000;
dib->dsBitfields[1] = 0x00ff00;
dib->dsBitfields[2] = 0x0000ff;
break;
case 32:
dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)lpRGB : 0xff0000;
dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 1) : 0x00ff00;
dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 2) : 0x0000ff;
break;
}
dib->dshSection = section;
dib->dsOffset = offset;
}
// Create Device Dependent Bitmap and add DIB pointer
if (dib)
{
Size.cx = bm.bmWidth;
Size.cy = abs(bm.bmHeight);
res = IntCreateBitmap(Size, bm.bmWidthBytes,
BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
(bi->biHeight < 0 ? BMF_TOPDOWN : 0),
bm.bmBits);
if (! res)
{
if (lpRGB != bmi->bmiColors)
{
ExFreePool(lpRGB);
}
SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
return NULL;
}
bmp = BITMAPOBJ_LockBitmap(res);
if (NULL == bmp)
{
if (lpRGB != bmi->bmiColors)
{
ExFreePool(lpRGB);
}
SetLastWin32Error(ERROR_INVALID_HANDLE);
NtGdiDeleteObject(bmp);
return NULL;
}
bmp->dib = (DIBSECTION *) dib;
bmp->flFlags = BITMAPOBJ_IS_APIBITMAP;
/* WINE NOTE: WINE makes use of a colormap, which is a color translation table between the DIB and the X physical
device. Obviously, this is left out of the ReactOS implementation. Instead, we call
NtGdiSetDIBColorTable. */
if(bi->biBitCount == 1) { Entries = 2; } else
if(bi->biBitCount == 4) { Entries = 16; } else
if(bi->biBitCount == 8) { Entries = 256; }
if (Entries)
bmp->hDIBPalette = PALETTE_AllocPaletteIndexedRGB(Entries, lpRGB);
else
bmp->hDIBPalette = PALETTE_AllocPalette(PAL_BITFIELDS, 0, NULL,
dib->dsBitfields[0],
dib->dsBitfields[1],
dib->dsBitfields[2]);
}
// Clean up in case of errors
if (!res || !bmp || !dib || !bm.bmBits)
{
DPRINT("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n", res, bmp, dib, bm.bmBits);
/* if (bm.bmBits)
{
if (section)
UnmapViewOfFile(bm.bmBits), bm.bmBits = NULL;
else if (!offset)
VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
} */
if (dib) { ExFreePool(dib); dib = NULL; }
if (bmp) { bmp = NULL; }
if (res) { BITMAPOBJ_FreeBitmap(res); res = 0; }
}
if (lpRGB != bmi->bmiColors)
{
ExFreePool(lpRGB);
}
if (bmp)
{
BITMAPOBJ_UnlockBitmap(bmp);
}
// Return BITMAP handle and storage location
if (NULL != bm.bmBits && NULL != bits)
{
*bits = bm.bmBits;
}
return res;
}
/***********************************************************************
* DIB_GetDIBWidthBytes
*
* Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
* http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
* 11/16/1999 (RJJ) lifted from wine
*/
INT FASTCALL DIB_GetDIBWidthBytes (INT width, INT depth)
{
return ((width * depth + 31) & ~31) >> 3;
}
/***********************************************************************
* DIB_GetDIBImageBytes
*
* Return the number of bytes used to hold the image in a DIB bitmap.
* 11/16/1999 (RJJ) lifted from wine
*/
INT STDCALL DIB_GetDIBImageBytes (INT width, INT height, INT depth)
{
return DIB_GetDIBWidthBytes( width, depth ) * (height < 0 ? -height : height);
}
/***********************************************************************
* DIB_BitmapInfoSize
*
* Return the size of the bitmap info structure including color table.
* 11/16/1999 (RJJ) lifted from wine
*/
INT FASTCALL DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse)
{
int colors;
if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{
BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
return sizeof(BITMAPCOREHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
}
else /* assume BITMAPINFOHEADER */
{
colors = info->bmiHeader.biClrUsed;
if (!colors && (info->bmiHeader.biBitCount <= 8)) colors = 1 << info->bmiHeader.biBitCount;
return sizeof(BITMAPINFOHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
}
}
/*
* DIB_GetBitmapInfo is complete copy of wine cvs 2/9-2006
* from file dib.c from gdi32.dll or orginal version
* did not calc the info right for some headers.
*/
INT STDCALL
DIB_GetBitmapInfo( const BITMAPINFOHEADER *header,
PLONG width,
PLONG height,
PWORD planes,
PWORD bpp,
PLONG compr,
PLONG size )
{
if (header->biSize == sizeof(BITMAPCOREHEADER))
{
BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
*width = core->bcWidth;
*height = core->bcHeight;
*planes = core->bcPlanes;
*bpp = core->bcBitCount;
*compr = 0;
*size = 0;
return 0;
}
if (header->biSize == sizeof(BITMAPINFOHEADER))
{
*width = header->biWidth;
*height = header->biHeight;
*planes = header->biPlanes;
*bpp = header->biBitCount;
*compr = header->biCompression;
*size = header->biSizeImage;
return 1;
}
if (header->biSize == sizeof(BITMAPV4HEADER))
{
BITMAPV4HEADER *v4hdr = (BITMAPV4HEADER *)header;
*width = v4hdr->bV4Width;
*height = v4hdr->bV4Height;
*planes = v4hdr->bV4Planes;
*bpp = v4hdr->bV4BitCount;
*compr = v4hdr->bV4V4Compression;
*size = v4hdr->bV4SizeImage;
return 4;
}
if (header->biSize == sizeof(BITMAPV5HEADER))
{
BITMAPV5HEADER *v5hdr = (BITMAPV5HEADER *)header;
*width = v5hdr->bV5Width;
*height = v5hdr->bV5Height;
*planes = v5hdr->bV5Planes;
*bpp = v5hdr->bV5BitCount;
*compr = v5hdr->bV5Compression;
*size = v5hdr->bV5SizeImage;
return 5;
}
DPRINT("(%ld): wrong size for header\n", header->biSize );
return -1;
}
// Converts a Device Independent Bitmap (DIB) to a Device Dependant Bitmap (DDB)
// The specified Device Context (DC) defines what the DIB should be converted to
PBITMAPOBJ FASTCALL DIBtoDDB(HGLOBAL hPackedDIB, HDC hdc) // FIXME: This should be removed. All references to this function should
// change to NtGdiSetDIBits
{
HBITMAP hBmp = 0;
PBITMAPOBJ pBmp = NULL;
DIBSECTION *dib;
LPBYTE pbits = NULL;
// Get a pointer to the packed DIB's data
// pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
dib = hPackedDIB;
pbits = (LPBYTE)(dib + DIB_BitmapInfoSize((BITMAPINFO*)&dib->dsBmih, DIB_RGB_COLORS));
// Create a DDB from the DIB
hBmp = NtGdiCreateDIBitmap ( hdc, &dib->dsBmih, CBM_INIT,
(LPVOID)pbits, (BITMAPINFO*)&dib->dsBmih, DIB_RGB_COLORS);
// GlobalUnlock(hPackedDIB);
// Retrieve the internal Pixmap from the DDB
pBmp = BITMAPOBJ_LockBitmap(hBmp);
return pBmp;
}
RGBQUAD * FASTCALL
DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi)
{
RGBQUAD *lpRGB;
ULONG nNumColors,i;
USHORT *lpIndex;
PPALGDI palGDI;
palGDI = PALETTE_LockPalette(dc->w.hPalette);
if (NULL == palGDI)
{
// RELEASEDCINFO(hDC);
return NULL;
}
if (palGDI->Mode != PAL_INDEXED)
{
PALETTE_UnlockPalette(palGDI);
palGDI = PALETTE_LockPalette(dc->PalIndexed);
if (palGDI->Mode != PAL_INDEXED)
{
return NULL;
}
}
nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
if (lpbmi->bmiHeader.biClrUsed)
{
nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
}
lpRGB = (RGBQUAD *)ExAllocatePoolWithTag(PagedPool, sizeof(RGBQUAD) * nNumColors, TAG_COLORMAP);
if (lpRGB == NULL)
{
PALETTE_UnlockPalette(palGDI);
return NULL;
}
lpIndex = (USHORT *)&lpbmi->bmiColors[0];
for (i = 0; i < nNumColors; i++)
{
lpRGB[i].rgbRed = palGDI->IndexedColors[*lpIndex].peRed;
lpRGB[i].rgbGreen = palGDI->IndexedColors[*lpIndex].peGreen;
lpRGB[i].rgbBlue = palGDI->IndexedColors[*lpIndex].peBlue;
lpIndex++;
}
// RELEASEDCINFO(hDC);
PALETTE_UnlockPalette(palGDI);
return lpRGB;
}
HPALETTE FASTCALL
BuildDIBPalette (CONST BITMAPINFO *bmi, PINT paletteType)
{
BYTE bits;
ULONG ColorCount;
PALETTEENTRY *palEntries = NULL;
HPALETTE hPal;
ULONG RedMask, GreenMask, BlueMask;
// Determine Bits Per Pixel
bits = bmi->bmiHeader.biBitCount;
// Determine paletteType from Bits Per Pixel
if (bits <= 8)
{
*paletteType = PAL_INDEXED;
RedMask = GreenMask = BlueMask = 0;
}
else if(bits < 24)
{
*paletteType = PAL_BITFIELDS;
RedMask = 0xf800;
GreenMask = 0x07e0;
BlueMask = 0x001f;
}
else
{
*paletteType = PAL_BGR;
RedMask = 0xff0000;
GreenMask = 0x00ff00;
BlueMask = 0x0000ff;
}
if (bmi->bmiHeader.biClrUsed == 0)
{
ColorCount = 1 << bmi->bmiHeader.biBitCount;
}
else
{
ColorCount = bmi->bmiHeader.biClrUsed;
}
if (PAL_INDEXED == *paletteType)
{
hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)bmi->bmiColors);
}
else
{
hPal = PALETTE_AllocPalette(*paletteType, ColorCount,
(ULONG*) palEntries,
RedMask, GreenMask, BlueMask );
}
return hPal;
}
/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -