Hi,
The BMP provider has a couple of bugs. The first is a faulty for
condition for 1bit BMPs. The second is an incorrect palette lookup for 1
and 4bit BMPs. Both of them are fixed by the attached patch, which is
unfortunately generated against DirectFB 1.0.
Sorin
Index: interfaces/IDirectFBImageProvider/idirectfbimageprovider_bmp.c
===================================================================
RCS file: /bigbig/dungeon/dcchd_project/directfb/install/dfb-smp86xx/interfaces/IDirectFBImageProvider/Attic/idirectfbimageprovider_bmp.c,v
retrieving revision 1.3
diff -u -r1.3 idirectfbimageprovider_bmp.c
--- interfaces/IDirectFBImageProvider/idirectfbimageprovider_bmp.c 2 Dec 2008 15:49:44 -0000 1.3
+++ interfaces/IDirectFBImageProvider/idirectfbimageprovider_bmp.c 3 Feb 2010 11:51:09 -0000
@@ -63,9 +63,9 @@
typedef struct {
int ref;
-
+
IDirectFBDataBuffer *buffer;
-
+
int width;
int height;
int depth;
@@ -73,11 +73,11 @@
BMPImageCompression compression;
unsigned int img_offset;
unsigned int num_colors;
-
+
DFBColor *palette;
-
+
CoreSurface *image;
-
+
DIRenderCallback render_callback;
void *render_callback_ctx;
} IDirectFBImageProvider_BMP_data;
@@ -96,7 +96,7 @@
ret = buffer->WaitForData( buffer, len );
if (ret == DFB_OK)
ret = buffer->GetData( buffer, len, ptr, &read );
-
+
if (ret)
return ret;
@@ -114,24 +114,24 @@
__u8 buf[54];
__u32 tmp;
__u32 bihsize;
-
+
memset( buf, 0, sizeof(buf) );
-
+
ret = fetch_data( data->buffer, buf, sizeof(buf) );
if (ret)
return ret;
-
- /* 2 bytes: Magic */
+
+ /* 2 bytes: Magic */
if (buf[0] != 'B' && buf[1] != 'M') {
D_ERROR( "IDirectFBImageProvider_BMP: "
"Invalid magic (%c%c)!\n", buf[0], buf[1] );
return DFB_UNSUPPORTED;
}
-
+
/* 4 bytes: FileSize */
-
+
/* 4 bytes: Reserved */
-
+
/* 4 bytes: DataOffset */
data->img_offset = buf[10] | (buf[11]<<8) | (buf[12]<<16) | (buf[13]<<24);
if (data->img_offset < 54) {
@@ -139,7 +139,7 @@
"Invalid offset %08x!\n", data->img_offset );
return DFB_UNSUPPORTED;
}
-
+
/* 4 bytes: HeaderSize */
bihsize = buf[14] | (buf[15]<<8) | (buf[16]<<16) | (buf[17]<<24);
if (bihsize < 40) {
@@ -147,7 +147,7 @@
"Invalid image header size %d!\n", bihsize );
return DFB_UNSUPPORTED;
}
-
+
/* 4 bytes: Width */
data->width = buf[18] | (buf[19]<<8) | (buf[20]<<16) | (buf[21]<<24);
if (data->width < 1 || data->width > 0xffff) {
@@ -155,7 +155,7 @@
"Invalid width %d!\n", data->width );
return DFB_UNSUPPORTED;
}
-
+
/* 4 bytes: Height */
data->height = buf[22] | (buf[23]<<8) | (buf[24]<<16) | (buf[25]<<24);
if (data->height < 1 || data->height > 0xffff) {
@@ -163,7 +163,7 @@
"Invalid height %d!\n", data->height );
return DFB_UNSUPPORTED;
}
-
+
/* 2 bytes: Planes */
tmp = buf[26] | (buf[27]<<8);
if (tmp != 1) {
@@ -171,7 +171,7 @@
"Unsupported number of planes %d!\n", tmp );
return DFB_UNSUPPORTED;
}
-
+
/* 2 bytes: Depth */
data->depth = buf[28] | (buf[29]<<8);
switch (data->depth) {
@@ -187,7 +187,7 @@
"Unsupported depth %d!\n", data->depth );
return DFB_UNSUPPORTED;
}
-
+
/* 4 bytes: Compression */
data->compression = buf[30] | (buf[31]<<8) | (buf[32]<<16) | (buf[33]<<24);
switch (data->compression) {
@@ -201,56 +201,70 @@
"Unsupported compression %d!\n", data->compression );
return DFB_UNSUPPORTED;
}
-
+
/* 4 bytes: CompressedSize */
-
+
/* 4 bytes: HorizontalResolution */
-
+
/* 4 bytes: VerticalResolution */
-
+
/* 4 bytes: UsedColors */
data->num_colors = buf[46] | (buf[47]<<8) | (buf[48]<<16) | (buf[49]<<24);
if (!data->num_colors)
data->num_colors = 1 << data->depth;
-
+
/* 4 bytes: ImportantColors */
-
+
/* Skip remaining bytes */
if (bihsize > 40) {
bihsize -= 40;
while (bihsize--) {
- __u8 b;
+ __u8 b;
ret = fetch_data( data->buffer, &b, 1 );
if (ret)
return ret;
}
}
-
+
/* Palette */
if (data->indexed) {
void *src;
- int i;
-
- data->palette = src = D_MALLOC( data->num_colors*4 );
+ int i, j;
+
+ data->palette = src = D_MALLOC( 256*4 );
if (!data->palette)
return D_OOM();
-
+
ret = fetch_data( data->buffer, src, data->num_colors*4 );
if (ret)
return ret;
-
+
for (i = 0; i < data->num_colors; i++) {
DFBColor c;
-
+
c.a = 0xff;
c.r = ((__u8*)src)[i*4+2];
c.g = ((__u8*)src)[i*4+1];
c.b = ((__u8*)src)[i*4+0];
-
- data->palette[i] = c;
+
+ /* For faster lookup, fill all 256 entries with duplicate data
+ for every bit position */
+ switch (data->num_colors) {
+ case 2:
+ if (i == 0)
+ data->palette[0] = c;
+ else
+ for (j = 1; j < 256; j++)
+ data->palette[j] = c;
+ break;
+ case 4:
+ data->palette[i] = c;
+ data->palette[i << 4] = c;
+ break;
+ }
}
}
-
+
return DFB_OK;
}
@@ -262,16 +276,16 @@
__u8 buf[pitch];
__u32 *dst;
int i;
-
+
ret = fetch_data( data->buffer, buf, pitch );
if (ret)
return ret;
-
+
dst = image + row * data->width;
-
+
switch (data->depth) {
case 1:
- for (i = 0; data->width; i++) {
+ for (i = 0; i < data->width; i++) {
unsigned idx = buf[i>>3] & (0x80 >> (i&7));
DFBColor c = data->palette[idx];
dst[i] = c.b | (c.g << 8) | (c.r << 16) | (c.a << 24);
@@ -279,7 +293,7 @@
break;
case 4:
for (i = 0; i < data->width; i++) {
- unsigned idx = buf[i>>1] & (0xf0 >> (i&1));
+ unsigned idx = buf[i>>1] & (0xf0 >> ((i&1) << 2));
DFBColor c = data->palette[idx];
dst[i] = c.b | (c.g << 8) | (c.r << 16) | (c.a << 24);
}
@@ -294,7 +308,7 @@
for (i = 0; i < data->width; i++) {
__u32 r, g, b;
__u16 c;
-
+
c = buf[i*2+0] | (buf[i*2+1]<<8);
r = (c >> 10) & 0x1f;
g = (c >> 5) & 0x1f;
@@ -302,13 +316,13 @@
r = (r << 3) | (r >> 2);
g = (g << 3) | (g >> 2);
b = (b << 3) | (b >> 2);
-
+
dst[i] = b | (g<<8) | (r<<16) | 0xff000000;
}
break;
case 24:
for (i = 0; i < data->width; i++) {
- dst[i] = (buf[i*3+0] ) |
+ dst[i] = (buf[i*3+0] ) |
(buf[i*3+1]<< 8) |
(buf[i*3+2]<<16) |
0xff000000;
@@ -316,19 +330,19 @@
break;
case 32:
for (i = 0; i < data->width; i++) {
- dst[i] = (buf[i*4+2] ) |
+ dst[i] = (buf[i*4+2] ) |
(buf[i*4+1]<< 8) |
(buf[i*4+0]<<16) |
(buf[i*4+3]<<24);
}
- break;
+ break;
default:
break;
}
-
+
return DFB_OK;
-}
-
+}
+
/*****************************************************************************/
static void
@@ -338,10 +352,10 @@
if (data->buffer)
data->buffer->Release( data->buffer );
-
+
if (data->image)
dfb_surface_unref(data->image);
-
+
if (data->palette)
D_FREE( data->palette );
@@ -380,18 +394,18 @@
DFBRectangle src_rect;
DFBRegion clip;
DFBResult ret = DFB_OK;
-
+
DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_BMP )
-
+
if (!destination)
return DFB_INVARG;
-
+
dst_data = destination->priv;
if (!dst_data || !dst_data->surface)
return DFB_DESTROYED;
-
+
dst_surface = dst_data->surface;
-
+
if (dest_rect) {
if (dest_rect->w < 1 || dest_rect->h < 1)
return DFB_INVARG;
@@ -402,7 +416,7 @@
else {
rect = dst_data->area.wanted;
}
-
+
dfb_region_from_rectangle( &clip, &dst_data->area.current );
if (!dfb_rectangle_intersect_by_region( &rect, &clip ))
return DFB_OK;
@@ -418,16 +432,16 @@
palette->Release( palette );
}
- if (!data->image)
+ if (!data->image)
{
int y;
__u32 *image_data;
int image_pitch;
- ret = dfb_surface_create(dst_data->core, data->width, data->height, DSPF_RGB32,
+ ret = dfb_surface_create(dst_data->core, data->width, data->height, DSPF_RGB32,
CSP_VIDEOONLY, DSCAPS_VIDEOONLY, NULL, &data->image);
- if (ret)
+ if (ret)
return D_OOM();
ret = dfb_surface_soft_lock(dst_data->core, data->image, DSLF_WRITE, (void**)&image_data, &image_pitch, true);
@@ -436,15 +450,15 @@
data->image = NULL;
return D_OOM();
}
-
+
data->buffer->SeekTo( data->buffer, data->img_offset );
-
+
for (y = data->height-1; y >= 0; y--) {
ret = bmp_decode_rgb_row( data, image_data, y );
if (ret)
break;
}
-
+
dfb_surface_unlock(data->image, true);
data->buffer->Release( data->buffer );
@@ -459,8 +473,8 @@
dfb_state_set_blitting_flags( &dst_data->state, DSBLIT_NOFX );
dfb_gfxcard_stretchblit( &src_rect, &rect, &dst_data->state );
dfb_state_set_source( &dst_data->state, NULL );
-
- if (data->render_callback)
+
+ if (data->render_callback)
data->render_callback( &src_rect, data->render_callback_ctx );
return ret;
_______________________________________________
directfb-dev mailing list
directfb-dev@directfb.org
http://mail.directfb.org/cgi-bin/mailman/listinfo/directfb-dev