gdi32: Use a local copy of the bitmap info structure to further simplify GetDIBits.
This commit is contained in:
parent
74707e956e
commit
dd39da49e5
190
dlls/gdi32/dib.c
190
dlls/gdi32/dib.c
|
@ -63,6 +63,7 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
|
@ -443,6 +444,59 @@ static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
|
||||||
static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
|
static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
|
||||||
static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
|
static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* copy_color_info
|
||||||
|
*
|
||||||
|
* Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
|
||||||
|
*/
|
||||||
|
static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
|
||||||
|
{
|
||||||
|
unsigned int colors = src->bmiHeader.biBitCount > 8 ? 0 : 1 << src->bmiHeader.biBitCount;
|
||||||
|
RGBQUAD *src_colors = (RGBQUAD *)((char *)src + src->bmiHeader.biSize);
|
||||||
|
|
||||||
|
assert( src->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) );
|
||||||
|
|
||||||
|
if (src->bmiHeader.biClrUsed) colors = src->bmiHeader.biClrUsed;
|
||||||
|
|
||||||
|
if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
|
||||||
|
{
|
||||||
|
BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
|
||||||
|
if (coloruse == DIB_PAL_COLORS)
|
||||||
|
memcpy( core->bmciColors, src_colors, colors * sizeof(WORD) );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
for (i = 0; i < colors; i++)
|
||||||
|
{
|
||||||
|
core->bmciColors[i].rgbtRed = src_colors[i].rgbRed;
|
||||||
|
core->bmciColors[i].rgbtGreen = src_colors[i].rgbGreen;
|
||||||
|
core->bmciColors[i].rgbtBlue = src_colors[i].rgbBlue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed;
|
||||||
|
dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
|
||||||
|
|
||||||
|
if (src->bmiHeader.biCompression == BI_BITFIELDS)
|
||||||
|
/* bitfields are always at bmiColors even in larger structures */
|
||||||
|
memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
|
||||||
|
else if (colors)
|
||||||
|
{
|
||||||
|
void *colorptr = (char *)dst + dst->bmiHeader.biSize;
|
||||||
|
unsigned int size;
|
||||||
|
|
||||||
|
if (coloruse == DIB_PAL_COLORS)
|
||||||
|
size = colors * sizeof(WORD);
|
||||||
|
else
|
||||||
|
size = colors * sizeof(RGBQUAD);
|
||||||
|
memcpy( colorptr, src_colors, size );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* GetDIBits [GDI32.@]
|
* GetDIBits [GDI32.@]
|
||||||
*
|
*
|
||||||
|
@ -470,9 +524,8 @@ INT WINAPI GetDIBits(
|
||||||
LONG height;
|
LONG height;
|
||||||
WORD planes, bpp;
|
WORD planes, bpp;
|
||||||
DWORD compr, size;
|
DWORD compr, size;
|
||||||
void* colorPtr;
|
char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
|
||||||
RGBQUAD quad_buf[256];
|
BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
|
||||||
RGBQUAD* rgbQuads = quad_buf;
|
|
||||||
|
|
||||||
if (!info) return 0;
|
if (!info) return 0;
|
||||||
|
|
||||||
|
@ -495,14 +548,9 @@ INT WINAPI GetDIBits(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
|
|
||||||
if(!core_header) rgbQuads = colorPtr;
|
|
||||||
|
|
||||||
/* Transfer color info */
|
if (bpp == 0) /* query bitmap info only */
|
||||||
|
|
||||||
switch (bpp)
|
|
||||||
{
|
{
|
||||||
case 0: /* query bitmap info only */
|
|
||||||
if (core_header)
|
if (core_header)
|
||||||
{
|
{
|
||||||
BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
|
BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
|
||||||
|
@ -549,34 +597,46 @@ INT WINAPI GetDIBits(
|
||||||
}
|
}
|
||||||
lines = abs(bmp->bitmap.bmHeight);
|
lines = abs(bmp->bitmap.bmHeight);
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
|
||||||
|
own copy and transfer the colour info back at the end */
|
||||||
|
|
||||||
|
dst_info->bmiHeader.biSize = sizeof(dst_info->bmiHeader);
|
||||||
|
dst_info->bmiHeader.biWidth = width;
|
||||||
|
dst_info->bmiHeader.biHeight = height;
|
||||||
|
dst_info->bmiHeader.biPlanes = planes;
|
||||||
|
dst_info->bmiHeader.biBitCount = bpp;
|
||||||
|
dst_info->bmiHeader.biCompression = compr;
|
||||||
|
dst_info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
|
||||||
|
dst_info->bmiHeader.biXPelsPerMeter = 0;
|
||||||
|
dst_info->bmiHeader.biYPelsPerMeter = 0;
|
||||||
|
dst_info->bmiHeader.biClrUsed = 0;
|
||||||
|
dst_info->bmiHeader.biClrImportant = 0;
|
||||||
|
|
||||||
|
switch (bpp)
|
||||||
|
{
|
||||||
case 1:
|
case 1:
|
||||||
case 4:
|
case 4:
|
||||||
case 8:
|
case 8:
|
||||||
{
|
{
|
||||||
unsigned int colors = 1 << bpp;
|
unsigned int colors = 1 << bpp;
|
||||||
|
|
||||||
if (!core_header) info->bmiHeader.biClrUsed = 0;
|
|
||||||
|
|
||||||
if (coloruse == DIB_PAL_COLORS)
|
if (coloruse == DIB_PAL_COLORS)
|
||||||
{
|
{
|
||||||
WORD *index = colorPtr;
|
WORD *index = (WORD*)dst_info->bmiColors;
|
||||||
for (i = 0; i < colors; i++, index++)
|
for (i = 0; i < colors; i++, index++)
|
||||||
*index = i;
|
*index = i;
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the bitmap object already has a dib section at the
|
/* If the bitmap object is a dib section at the
|
||||||
same color depth then get the color map from it */
|
same color depth then get the color map from it */
|
||||||
|
else if (bmp->dib && bpp == bmp->dib->dsBm.bmBitsPixel)
|
||||||
if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp)
|
|
||||||
{
|
{
|
||||||
colors = min( colors, bmp->nb_colors );
|
colors = min( colors, bmp->nb_colors );
|
||||||
|
if (colors != 1 << bpp) dst_info->bmiHeader.biClrUsed = colors;
|
||||||
if (!core_header && colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
|
memcpy( dst_info->bmiColors, bmp->color_table, colors * sizeof(RGBQUAD) );
|
||||||
|
|
||||||
memcpy(rgbQuads, bmp->color_table, colors * sizeof(RGBQUAD));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For color DDBs in native depth (mono DDBs always have a black/white palette):
|
/* For color DDBs in native depth (mono DDBs always have a black/white palette):
|
||||||
|
@ -589,16 +649,16 @@ INT WINAPI GetDIBits(
|
||||||
memset( palEntry, 0, sizeof(palEntry) );
|
memset( palEntry, 0, sizeof(palEntry) );
|
||||||
if (!GetPaletteEntries( dc->hPalette, 0, colors, palEntry ))
|
if (!GetPaletteEntries( dc->hPalette, 0, colors, palEntry ))
|
||||||
{
|
{
|
||||||
release_dc_ptr( dc );
|
lines = 0;
|
||||||
GDI_ReleaseObj( hbitmap );
|
goto done;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < colors; i++)
|
for (i = 0; i < colors; i++)
|
||||||
{
|
{
|
||||||
rgbQuads[i].rgbRed = palEntry[i].peRed;
|
dst_info->bmiColors[i].rgbRed = palEntry[i].peRed;
|
||||||
rgbQuads[i].rgbGreen = palEntry[i].peGreen;
|
dst_info->bmiColors[i].rgbGreen = palEntry[i].peGreen;
|
||||||
rgbQuads[i].rgbBlue = palEntry[i].peBlue;
|
dst_info->bmiColors[i].rgbBlue = palEntry[i].peBlue;
|
||||||
rgbQuads[i].rgbReserved = 0;
|
dst_info->bmiColors[i].rgbReserved = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -606,76 +666,64 @@ INT WINAPI GetDIBits(
|
||||||
switch (bpp)
|
switch (bpp)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen = rgbQuads[0].rgbBlue = 0;
|
dst_info->bmiColors[0].rgbRed = dst_info->bmiColors[0].rgbGreen = dst_info->bmiColors[0].rgbBlue = 0;
|
||||||
rgbQuads[0].rgbReserved = 0;
|
dst_info->bmiColors[0].rgbReserved = 0;
|
||||||
rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen = rgbQuads[1].rgbBlue = 0xff;
|
dst_info->bmiColors[1].rgbRed = dst_info->bmiColors[1].rgbGreen = dst_info->bmiColors[1].rgbBlue = 0xff;
|
||||||
rgbQuads[1].rgbReserved = 0;
|
dst_info->bmiColors[1].rgbReserved = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
/* The EGA palette is the first and last 8 colours of the default palette
|
/* The EGA palette is the first and last 8 colours of the default palette
|
||||||
with the innermost pair swapped */
|
with the innermost pair swapped */
|
||||||
memcpy(rgbQuads, DefLogPaletteQuads, 7 * sizeof(RGBQUAD));
|
memcpy(dst_info->bmiColors, DefLogPaletteQuads, 7 * sizeof(RGBQUAD));
|
||||||
memcpy(rgbQuads + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
|
memcpy(dst_info->bmiColors + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
|
||||||
memcpy(rgbQuads + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD));
|
memcpy(dst_info->bmiColors + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD));
|
||||||
memcpy(rgbQuads + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
|
memcpy(dst_info->bmiColors + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 8:
|
case 8:
|
||||||
memcpy(rgbQuads, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
|
memcpy(dst_info->bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
|
||||||
memcpy(rgbQuads + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
|
memcpy(dst_info->bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
|
||||||
for (i = 10; i < 246; i++)
|
for (i = 10; i < 246; i++)
|
||||||
{
|
{
|
||||||
rgbQuads[i].rgbRed = (i & 0x07) << 5;
|
dst_info->bmiColors[i].rgbRed = (i & 0x07) << 5;
|
||||||
rgbQuads[i].rgbGreen = (i & 0x38) << 2;
|
dst_info->bmiColors[i].rgbGreen = (i & 0x38) << 2;
|
||||||
rgbQuads[i].rgbBlue = i & 0xc0;
|
dst_info->bmiColors[i].rgbBlue = i & 0xc0;
|
||||||
rgbQuads[i].rgbReserved = 0;
|
dst_info->bmiColors[i].rgbReserved = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(core_header)
|
|
||||||
{
|
|
||||||
RGBTRIPLE *triple = (RGBTRIPLE *)colorPtr;
|
|
||||||
for (i = 0; i < colors; i++)
|
|
||||||
{
|
|
||||||
triple[i].rgbtRed = rgbQuads[i].rgbRed;
|
|
||||||
triple[i].rgbtGreen = rgbQuads[i].rgbGreen;
|
|
||||||
triple[i].rgbtBlue = rgbQuads[i].rgbBlue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 15:
|
case 15:
|
||||||
if (info->bmiHeader.biCompression == BI_BITFIELDS)
|
if (dst_info->bmiHeader.biCompression == BI_BITFIELDS)
|
||||||
memcpy( info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
|
memcpy( dst_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 16:
|
case 16:
|
||||||
if (info->bmiHeader.biCompression == BI_BITFIELDS)
|
if (dst_info->bmiHeader.biCompression == BI_BITFIELDS)
|
||||||
{
|
{
|
||||||
if (bmp->dib)
|
if (bmp->dib)
|
||||||
{
|
{
|
||||||
if (bmp->dib->dsBmih.biCompression == BI_BITFIELDS && bmp->dib->dsBmih.biBitCount == bpp)
|
if (bmp->dib->dsBmih.biCompression == BI_BITFIELDS && bmp->dib->dsBmih.biBitCount == bpp)
|
||||||
memcpy( info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
|
memcpy( dst_info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
|
||||||
else
|
else
|
||||||
memcpy( info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
|
memcpy( dst_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
memcpy( info->bmiColors, bit_fields_565, sizeof(bit_fields_565) );
|
memcpy( dst_info->bmiColors, bit_fields_565, sizeof(bit_fields_565) );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 24:
|
case 24:
|
||||||
case 32:
|
case 32:
|
||||||
if (info->bmiHeader.biCompression == BI_BITFIELDS)
|
if (dst_info->bmiHeader.biCompression == BI_BITFIELDS)
|
||||||
{
|
{
|
||||||
if (bmp->dib && bmp->dib->dsBmih.biCompression == BI_BITFIELDS && bmp->dib->dsBmih.biBitCount == bpp)
|
if (bmp->dib && bmp->dib->dsBmih.biCompression == BI_BITFIELDS && bmp->dib->dsBmih.biBitCount == bpp)
|
||||||
memcpy( info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
|
memcpy( dst_info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
|
||||||
else
|
else
|
||||||
memcpy( info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
|
memcpy( dst_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -894,7 +942,7 @@ INT WINAPI GetDIBits(
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: /* ? bit DIB */
|
default: /* ? bit DIB */
|
||||||
FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
|
FIXME("Unsupported DIB depth %d\n", dst_info->bmiHeader.biBitCount);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -904,22 +952,12 @@ INT WINAPI GetDIBits(
|
||||||
PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetDIBits );
|
PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetDIBits );
|
||||||
if (!BITMAP_SetOwnerDC( hbitmap, physdev )) lines = 0;
|
if (!BITMAP_SetOwnerDC( hbitmap, physdev )) lines = 0;
|
||||||
else lines = physdev->funcs->pGetDIBits( physdev, hbitmap, startscan,
|
else lines = physdev->funcs->pGetDIBits( physdev, hbitmap, startscan,
|
||||||
lines, bits, info, coloruse );
|
lines, bits, dst_info, coloruse );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else lines = abs(height);
|
else lines = abs(height);
|
||||||
|
|
||||||
/* The knowledge base article Q81498 ("DIBs and Their Uses") states that
|
copy_color_info( info, dst_info, coloruse );
|
||||||
if bits == NULL and bpp != 0, only biSizeImage and the color table are
|
|
||||||
filled in. */
|
|
||||||
if (!core_header)
|
|
||||||
{
|
|
||||||
/* FIXME: biSizeImage should be calculated according to the selected
|
|
||||||
compression algorithm if biCompression != BI_RGB */
|
|
||||||
info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
|
|
||||||
TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
|
|
||||||
}
|
|
||||||
TRACE("biWidth = %d, biHeight = %d\n", width, height);
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
release_dc_ptr( dc );
|
release_dc_ptr( dc );
|
||||||
|
|
Loading…
Reference in New Issue