gdi32: Add support for arbitrary DIB bitfields for 32-bpp conversions.

This commit is contained in:
Alexandre Julliard 2011-10-12 23:25:32 +02:00
parent b2ef9218ec
commit b084e52bf6
2 changed files with 176 additions and 29 deletions

View File

@ -1030,11 +1030,31 @@ static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) ); return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
} }
static const DWORD field_masks[33] =
{
0x00, /* should never happen */
0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
static inline DWORD get_field(DWORD field, int shift, int len)
{
shift = shift - (8 - len);
if (shift < 0)
field <<= -shift;
else
field >>= shift;
field &= field_masks[len];
field |= field >> len;
return field;
}
static inline DWORD put_field(DWORD field, int shift, int len) static inline DWORD put_field(DWORD field, int shift, int len)
{ {
shift = shift - (8 - len); shift = shift - (8 - len);
if (len <= 8) field &= field_masks[len];
field &= (((1 << len) - 1) << (8 - len));
if (shift < 0) if (shift < 0)
field >>= -shift; field >>= -shift;
else else
@ -1166,8 +1186,21 @@ static BOOL convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_
} }
else else
{ {
FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 8888\n", src->red_mask, src->green_mask, src->blue_mask); for(y = src_rect->top; y < src_rect->bottom; y++)
return FALSE; {
dst_pixel = dst_start;
src_pixel = src_start;
for(x = src_rect->left; x < src_rect->right; x++)
{
src_val = *src_pixel++;
*dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
get_field( src_val, src->green_shift, src->green_len ) << 8 |
get_field( src_val, src->blue_shift, src->blue_len ));
}
if(pad_size) memset(dst_pixel, 0, pad_size);
dst_start += dst->stride / 4;
src_start += src->stride / 4;
}
} }
break; break;
} }
@ -1359,9 +1392,9 @@ static BOOL convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_re
for(x = src_rect->left; x < src_rect->right; x++) for(x = src_rect->left; x < src_rect->right; x++)
{ {
src_val = *src_pixel++; src_val = *src_pixel++;
*dst_pixel++ = put_field((src_val >> 16) & 0xff, dst->red_shift, dst->red_len) | *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
put_field((src_val >> 8) & 0xff, dst->green_shift, dst->green_len) | put_field(src_val >> 8, dst->green_shift, dst->green_len) |
put_field( src_val & 0xff, dst->blue_shift, dst->blue_len); put_field(src_val, dst->blue_shift, dst->blue_len);
} }
if(pad_size) memset(dst_pixel, 0, pad_size); if(pad_size) memset(dst_pixel, 0, pad_size);
dst_start += dst->stride / 4; dst_start += dst->stride / 4;
@ -1404,9 +1437,21 @@ static BOOL convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_re
} }
else else
{ {
FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 32 (%08x, %08x, %08x)\n", for(y = src_rect->top; y < src_rect->bottom; y++)
src->red_mask, src->green_mask, src->blue_mask, dst->red_mask, dst->green_mask, dst->blue_mask); {
return FALSE; dst_pixel = dst_start;
src_pixel = src_start;
for(x = src_rect->left; x < src_rect->right; x++)
{
src_val = *src_pixel++;
*dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
}
if(pad_size) memset(dst_pixel, 0, pad_size);
dst_start += dst->stride / 4;
src_start += src->stride / 4;
}
} }
break; break;
} }
@ -1635,8 +1680,21 @@ static BOOL convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_re
} }
else else
{ {
FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 24\n", src->red_mask, src->green_mask, src->blue_mask); for(y = src_rect->top; y < src_rect->bottom; y++)
return FALSE; {
dst_pixel = dst_start;
src_pixel = src_start;
for(x = src_rect->left; x < src_rect->right; x++)
{
src_val = *src_pixel++;
*dst_pixel++ = get_field( src_val, src->blue_shift, src->blue_len );
*dst_pixel++ = get_field( src_val, src->green_shift, src->green_len );
*dst_pixel++ = get_field( src_val, src->red_shift, src->red_len );
}
if(pad_size) memset(dst_pixel, 0, pad_size);
dst_start += dst->stride;
src_start += src->stride / 4;
}
} }
break; break;
} }
@ -1859,8 +1917,21 @@ static BOOL convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_r
} }
else else
{ {
FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 555\n", src->red_mask, src->green_mask, src->blue_mask); for(y = src_rect->top; y < src_rect->bottom; y++)
return FALSE; {
dst_pixel = dst_start;
src_pixel = src_start;
for(x = src_rect->left; x < src_rect->right; x++)
{
src_val = *src_pixel++;
*dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len ) << 7) & 0x7c00) |
((get_field(src_val, src->green_shift, src->green_len ) << 2) & 0x03e0) |
( get_field(src_val, src->blue_shift, src->blue_len ) >> 3));
}
if(pad_size) memset(dst_pixel, 0, pad_size);
dst_start += dst->stride / 2;
src_start += src->stride / 4;
}
} }
break; break;
} }
@ -2052,9 +2123,9 @@ static BOOL convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_re
for(x = src_rect->left; x < src_rect->right; x++) for(x = src_rect->left; x < src_rect->right; x++)
{ {
src_val = *src_pixel++; src_val = *src_pixel++;
*dst_pixel++ = put_field((src_val >> 16) & 0xff, dst->red_shift, dst->red_len) | *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) |
put_field((src_val >> 8) & 0xff, dst->green_shift, dst->green_len) | put_field(src_val >> 8, dst->green_shift, dst->green_len) |
put_field( src_val & 0xff, dst->blue_shift, dst->blue_len); put_field(src_val, dst->blue_shift, dst->blue_len);
} }
if(pad_size) memset(dst_pixel, 0, pad_size); if(pad_size) memset(dst_pixel, 0, pad_size);
dst_start += dst->stride / 2; dst_start += dst->stride / 2;
@ -2070,9 +2141,9 @@ static BOOL convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_re
for(x = src_rect->left; x < src_rect->right; x++) for(x = src_rect->left; x < src_rect->right; x++)
{ {
src_val = *src_pixel++; src_val = *src_pixel++;
*dst_pixel++ = put_field((src_val >> src->red_shift) & 0xff, dst->red_shift, dst->red_len) | *dst_pixel++ = put_field(src_val >> src->red_shift, dst->red_shift, dst->red_len) |
put_field((src_val >> src->green_shift) & 0xff, dst->green_shift, dst->green_len) | put_field(src_val >> src->green_shift, dst->green_shift, dst->green_len) |
put_field((src_val >> src->blue_shift) & 0xff, dst->blue_shift, dst->blue_len); put_field(src_val >> src->blue_shift, dst->blue_shift, dst->blue_len);
} }
if(pad_size) memset(dst_pixel, 0, pad_size); if(pad_size) memset(dst_pixel, 0, pad_size);
dst_start += dst->stride / 2; dst_start += dst->stride / 2;
@ -2081,8 +2152,21 @@ static BOOL convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_re
} }
else else
{ {
FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 16\n", src->red_mask, src->green_mask, src->blue_mask); for(y = src_rect->top; y < src_rect->bottom; y++)
return FALSE; {
dst_pixel = dst_start;
src_pixel = src_start;
for(x = src_rect->left; x < src_rect->right; x++)
{
src_val = *src_pixel++;
*dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
}
if(pad_size) memset(dst_pixel, 0, pad_size);
dst_start += dst->stride / 2;
src_start += src->stride / 4;
}
} }
break; break;
} }
@ -2336,8 +2420,21 @@ static BOOL convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rec
} }
else else
{ {
FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 8\n", src->red_mask, src->green_mask, src->blue_mask); for(y = src_rect->top; y < src_rect->bottom; y++)
return FALSE; {
dst_pixel = dst_start;
src_pixel = src_start;
for(x = src_rect->left; x < src_rect->right; x++)
{
src_val = *src_pixel++;
*dst_pixel++ = colorref_to_pixel_colortable(dst, (get_field(src_val, src->red_shift, src->red_len) |
get_field(src_val, src->green_shift, src->green_len) << 8 |
get_field(src_val, src->blue_shift, src->blue_len) << 16));
}
if(pad_size) memset(dst_pixel, 0, pad_size);
dst_start += dst->stride;
src_start += src->stride / 4;
}
} }
break; break;
} }
@ -2602,8 +2699,32 @@ static BOOL convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rec
} }
else else
{ {
FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 4\n", src->red_mask, src->green_mask, src->blue_mask); for(y = src_rect->top; y < src_rect->bottom; y++)
return FALSE; {
dst_pixel = dst_start;
src_pixel = src_start;
for(x = src_rect->left; x < src_rect->right; x++)
{
src_val = *src_pixel++;
dst_val = colorref_to_pixel_colortable(dst, (get_field(src_val, src->red_shift, src->red_len) |
get_field(src_val, src->green_shift, src->green_len) << 8 |
get_field(src_val, src->blue_shift, src->blue_len) << 16));
if((x - src_rect->left) & 1)
{
*dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
dst_pixel++;
}
else
*dst_pixel = (dst_val << 4) & 0xf0;
}
if(pad_size)
{
if((x - src_rect->left) & 1) dst_pixel++;
memset(dst_pixel, 0, pad_size);
}
dst_start += dst->stride;
src_start += src->stride / 4;
}
} }
break; break;
} }
@ -2955,8 +3076,34 @@ static BOOL convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rec
} }
else else
{ {
FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 1\n", src->red_mask, src->green_mask, src->blue_mask); for(y = src_rect->top; y < src_rect->bottom; y++)
return FALSE; {
dst_pixel = dst_start;
src_pixel = src_start;
for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
{
src_val = *src_pixel++;
dst_val = colorref_to_pixel_colortable(dst, (get_field(src_val, src->red_shift, src->red_len) |
get_field(src_val, src->green_shift, src->green_len) << 8 |
get_field(src_val, src->blue_shift, src->blue_len) << 16)) ? 0xff : 0;
if(bit_pos == 0) *dst_pixel = 0;
*dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
if(++bit_pos == 8)
{
dst_pixel++;
bit_pos = 0;
}
}
if(pad_size)
{
if(bit_pos != 0) dst_pixel++;
memset(dst_pixel, 0, pad_size);
}
dst_start += dst->stride;
src_start += src->stride / 4;
}
} }
break; break;
} }

View File

@ -846,7 +846,7 @@ static void test_dib_formats(void)
case 32: expect_ok = (compr == BI_RGB || compr == BI_BITFIELDS); break; case 32: expect_ok = (compr == BI_RGB || compr == BI_BITFIELDS); break;
default: expect_ok = FALSE; break; default: expect_ok = FALSE; break;
} }
todo = (compr == BI_BITFIELDS); /* wine doesn't like strange bitfields */ todo = (compr == BI_BITFIELDS) && bpp == 16; /* wine doesn't like strange bitfields */
memset( bi, 0, sizeof(bi->bmiHeader) ); memset( bi, 0, sizeof(bi->bmiHeader) );
bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);