[project @ 2006-02-28 00:45:15 by rjw]
Implement bitfield encoding for BMPs. We now correctly decode every image in the BMP test suite at http://pobox.com/~jason1/bmpsuite/ svn path=/import/netsurf/; revision=2099
This commit is contained in:
parent
6929d90d41
commit
6f654c6f1e
221
image/bmpread.c
221
image/bmpread.c
|
@ -5,7 +5,6 @@
|
||||||
* Copyright 2006 Richard Wilson <info@tinct.net>
|
* Copyright 2006 Richard Wilson <info@tinct.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -20,6 +19,7 @@
|
||||||
|
|
||||||
bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data);
|
bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data);
|
||||||
bmp_result bmp_decode_rgb24(struct bmp_image *bmp, char **start, int bytes);
|
bmp_result bmp_decode_rgb24(struct bmp_image *bmp, char **start, int bytes);
|
||||||
|
bmp_result bmp_decode_rgb16(struct bmp_image *bmp, char **start, int bytes);
|
||||||
bmp_result bmp_decode_rgb(struct bmp_image *bmp, char **start, int bytes);
|
bmp_result bmp_decode_rgb(struct bmp_image *bmp, char **start, int bytes);
|
||||||
bmp_result bmp_decode_mask(struct bmp_image *bmp, char *data, int bytes);
|
bmp_result bmp_decode_mask(struct bmp_image *bmp, char *data, int bytes);
|
||||||
bmp_result bmp_decode_rle(struct bmp_image *bmp, char *data, int bytes, int size);
|
bmp_result bmp_decode_rle(struct bmp_image *bmp, char *data, int bytes, int size);
|
||||||
|
@ -58,11 +58,11 @@ bmp_result bmp_analyse(struct bmp_image *bmp) {
|
||||||
if ((data[0] != 'B') || (data[1] != 'M'))
|
if ((data[0] != 'B') || (data[1] != 'M'))
|
||||||
return BMP_DATA_ERROR;
|
return BMP_DATA_ERROR;
|
||||||
bmp->bitmap_offset = READ_INT(data, 10);
|
bmp->bitmap_offset = READ_INT(data, 10);
|
||||||
|
|
||||||
/* decode the BMP header */
|
/* decode the BMP header */
|
||||||
return bmp_analyse_header(bmp, data + 14);
|
return bmp_analyse_header(bmp, data + 14);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Analyse an ICO prior to decoding.
|
* Analyse an ICO prior to decoding.
|
||||||
|
@ -99,7 +99,7 @@ bmp_result ico_analyse(struct ico_collection *ico) {
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
return BMP_DATA_ERROR;
|
return BMP_DATA_ERROR;
|
||||||
data += 6;
|
data += 6;
|
||||||
|
|
||||||
/* decode the BMP files */
|
/* decode the BMP files */
|
||||||
if (ico->buffer_size < 6 + (16 * count))
|
if (ico->buffer_size < 6 + (16 * count))
|
||||||
return BMP_INSUFFICIENT_DATA;
|
return BMP_INSUFFICIENT_DATA;
|
||||||
|
@ -132,7 +132,7 @@ bmp_result ico_analyse(struct ico_collection *ico) {
|
||||||
bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data) {
|
bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data) {
|
||||||
unsigned int header_size;
|
unsigned int header_size;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int width, height;
|
int width, height, j;
|
||||||
int palette_size;
|
int palette_size;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
|
||||||
|
@ -157,8 +157,8 @@ bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data) {
|
||||||
if (width < 0)
|
if (width < 0)
|
||||||
return BMP_DATA_ERROR;
|
return BMP_DATA_ERROR;
|
||||||
if (height < 0) {
|
if (height < 0) {
|
||||||
bmp->reversed = true;
|
bmp->reversed = true;
|
||||||
height = -height;
|
height = -height;
|
||||||
}
|
}
|
||||||
bmp->width = width;
|
bmp->width = width;
|
||||||
bmp->height = height;
|
bmp->height = height;
|
||||||
|
@ -170,8 +170,8 @@ bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data) {
|
||||||
} else if (header_size < 40) {
|
} else if (header_size < 40) {
|
||||||
return BMP_DATA_ERROR;
|
return BMP_DATA_ERROR;
|
||||||
} else {
|
} else {
|
||||||
/* the following header is for windows 3.x and onwards. it is a
|
/* the following header is for windows 3.x and onwards. it is a
|
||||||
* minimum of 40 bytes and (as of Windows 95) a maximum of 108 bytes.
|
* minimum of 40 bytes and (as of Windows 95) a maximum of 108 bytes.
|
||||||
*
|
*
|
||||||
* +0 INT size of this header (in bytes)
|
* +0 INT size of this header (in bytes)
|
||||||
* +4 INT image width (in pixels)
|
* +4 INT image width (in pixels)
|
||||||
|
@ -208,8 +208,8 @@ bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data) {
|
||||||
if (width < 0)
|
if (width < 0)
|
||||||
return BMP_DATA_ERROR;
|
return BMP_DATA_ERROR;
|
||||||
if (height < 0) {
|
if (height < 0) {
|
||||||
bmp->reversed = true;
|
bmp->reversed = true;
|
||||||
height = -height;
|
height = -height;
|
||||||
}
|
}
|
||||||
bmp->width = width;
|
bmp->width = width;
|
||||||
bmp->height = height;
|
bmp->height = height;
|
||||||
|
@ -220,13 +220,39 @@ bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data) {
|
||||||
if (bmp->bpp == 0)
|
if (bmp->bpp == 0)
|
||||||
bmp->bpp = 8;
|
bmp->bpp = 8;
|
||||||
bmp->encoding = READ_INT(data, 16);
|
bmp->encoding = READ_INT(data, 16);
|
||||||
if (bmp->encoding >= BMP_ENCODING_BITFIELDS) /* unsupported so far */
|
if (bmp->encoding > BMP_ENCODING_BITFIELDS)
|
||||||
return BMP_DATA_ERROR;
|
return BMP_DATA_ERROR;
|
||||||
|
if (bmp->encoding == BMP_ENCODING_BITFIELDS) {
|
||||||
|
if ((bmp->bpp != 16) && (bmp->bpp != 32))
|
||||||
|
return BMP_DATA_ERROR;
|
||||||
|
if (header_size == 40) {
|
||||||
|
header_size += 12;
|
||||||
|
if (bmp->buffer_size < (14 + header_size))
|
||||||
|
return BMP_INSUFFICIENT_DATA;
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
bmp->mask[i] = READ_INT(data, 40 + (i << 2));
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
bmp->mask[i] = READ_INT(data, 40 + (i << 2));
|
||||||
|
}
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
if (bmp->mask[i] == 0)
|
||||||
|
break;
|
||||||
|
for (j = 31; j > 0; j--)
|
||||||
|
if (bmp->mask[i] & (1 << j)) {
|
||||||
|
if ((j - 7) > 0)
|
||||||
|
bmp->mask[i] &= 0xff << (j - 7);
|
||||||
|
else
|
||||||
|
bmp->mask[i] &= 0xff >> (-(j - 7));
|
||||||
|
bmp->shift[i] = (i << 3) - (j - 7);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
bmp->colours = READ_INT(data, 32);
|
bmp->colours = READ_INT(data, 32);
|
||||||
if (bmp->colours == 0)
|
if (bmp->colours == 0)
|
||||||
bmp->colours = (1 << bmp->bpp);
|
bmp->colours = (1 << bmp->bpp);
|
||||||
palette_size = 4;
|
palette_size = 4;
|
||||||
/* we don't understand the rest of the data yet */
|
|
||||||
}
|
}
|
||||||
data += header_size;
|
data += header_size;
|
||||||
|
|
||||||
|
@ -239,7 +265,7 @@ bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data) {
|
||||||
* +2 BYTE red
|
* +2 BYTE red
|
||||||
*
|
*
|
||||||
* if the palette is from an OS/2 or Win2.x file then the entries
|
* if the palette is from an OS/2 or Win2.x file then the entries
|
||||||
* are padded with an extra byte.
|
* are padded with an extra byte.
|
||||||
*/
|
*/
|
||||||
if (bmp->buffer_size < (14 + header_size + (4 * bmp->colours)))
|
if (bmp->buffer_size < (14 + header_size + (4 * bmp->colours)))
|
||||||
return BMP_INSUFFICIENT_DATA;
|
return BMP_INSUFFICIENT_DATA;
|
||||||
|
@ -256,7 +282,7 @@ bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data) {
|
||||||
|
|
||||||
/* create our bitmap */
|
/* create our bitmap */
|
||||||
flags = BITMAP_NEW | BITMAP_CLEAR_MEMORY;
|
flags = BITMAP_NEW | BITMAP_CLEAR_MEMORY;
|
||||||
if (!bmp->ico)
|
if ((!bmp->ico) || (bmp->mask[3] == 0))
|
||||||
flags |= BITMAP_OPAQUE;
|
flags |= BITMAP_OPAQUE;
|
||||||
bmp->bitmap = bitmap_create(bmp->width, bmp->height, flags);
|
bmp->bitmap = bitmap_create(bmp->width, bmp->height, flags);
|
||||||
if (!bmp->bitmap) {
|
if (!bmp->bitmap) {
|
||||||
|
@ -275,17 +301,17 @@ bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data) {
|
||||||
* Finds the closest BMP within an ICO collection
|
* Finds the closest BMP within an ICO collection
|
||||||
*
|
*
|
||||||
* This function finds the BMP with dimensions as close to a specified set
|
* This function finds the BMP with dimensions as close to a specified set
|
||||||
* as possible from the images in the collection.
|
* as possible from the images in the collection.
|
||||||
*
|
*
|
||||||
* \param ico the ICO collection to examine
|
* \param ico the ICO collection to examine
|
||||||
* \param width the preferred width
|
* \param width the preferred width
|
||||||
* \param height the preferred height
|
* \param height the preferred height
|
||||||
*/
|
*/
|
||||||
struct bmp_image *ico_find(struct ico_collection *ico, int width, int height) {
|
struct bmp_image *ico_find(struct ico_collection *ico, int width, int height) {
|
||||||
struct bmp_image *bmp = NULL;
|
struct bmp_image *bmp = NULL;
|
||||||
struct ico_image *image;
|
struct ico_image *image;
|
||||||
int x, y, cur, distance = (1 << 24);
|
int x, y, cur, distance = (1 << 24);
|
||||||
|
|
||||||
for (image = ico->first; image; image = image->next) {
|
for (image = ico->first; image; image = image->next) {
|
||||||
if (((int)image->bmp.width == width) && ((int)image->bmp.height == height))
|
if (((int)image->bmp.width == width) && ((int)image->bmp.height == height))
|
||||||
return &image->bmp;
|
return &image->bmp;
|
||||||
|
@ -305,13 +331,13 @@ struct bmp_image *ico_find(struct ico_collection *ico, int width, int height) {
|
||||||
* Invalidates a BMP
|
* Invalidates a BMP
|
||||||
*
|
*
|
||||||
* This function sets the BMP into a state such that the bitmap image data
|
* This function sets the BMP into a state such that the bitmap image data
|
||||||
* can be released from memory.
|
* can be released from memory.
|
||||||
*
|
*
|
||||||
* \param bmp the BMP image to invalidate
|
* \param bmp the BMP image to invalidate
|
||||||
*/
|
*/
|
||||||
void bmp_invalidate(struct bitmap *bitmap, void *private_word) {
|
void bmp_invalidate(struct bitmap *bitmap, void *private_word) {
|
||||||
struct bmp_image *bmp = (struct bmp_image *)private_word;
|
struct bmp_image *bmp = (struct bmp_image *)private_word;
|
||||||
|
|
||||||
bmp->decoded = false;
|
bmp->decoded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,7 +367,7 @@ bmp_result bmp_decode(struct bmp_image *bmp) {
|
||||||
if (bmp->bpp >= 24)
|
if (bmp->bpp >= 24)
|
||||||
result = bmp_decode_rgb24(bmp, &data, bytes);
|
result = bmp_decode_rgb24(bmp, &data, bytes);
|
||||||
else if (bmp->bpp > 8)
|
else if (bmp->bpp > 8)
|
||||||
return BMP_DATA_ERROR;
|
result = bmp_decode_rgb16(bmp, &data, bytes);
|
||||||
else
|
else
|
||||||
result = bmp_decode_rgb(bmp, &data, bytes);
|
result = bmp_decode_rgb(bmp, &data, bytes);
|
||||||
break;
|
break;
|
||||||
|
@ -352,12 +378,17 @@ bmp_result bmp_decode(struct bmp_image *bmp) {
|
||||||
result = bmp_decode_rle(bmp, data, bytes, 4);
|
result = bmp_decode_rle(bmp, data, bytes, 4);
|
||||||
break;
|
break;
|
||||||
case BMP_ENCODING_BITFIELDS:
|
case BMP_ENCODING_BITFIELDS:
|
||||||
return BMP_DATA_ERROR;
|
if (bmp->bpp == 32)
|
||||||
|
result = bmp_decode_rgb24(bmp, &data, bytes);
|
||||||
|
else if (bmp->bpp == 16)
|
||||||
|
result = bmp_decode_rgb16(bmp, &data, bytes);
|
||||||
|
else
|
||||||
|
return BMP_DATA_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!bmp->ico) || (result != BMP_OK))
|
if ((!bmp->ico) || (result != BMP_OK))
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
bytes = (int)bmp->bmp_data + bmp->buffer_size - (int)data;
|
bytes = (int)bmp->bmp_data + bmp->buffer_size - (int)data;
|
||||||
return bmp_decode_mask(bmp, data, bytes);
|
return bmp_decode_mask(bmp, data, bytes);
|
||||||
}
|
}
|
||||||
|
@ -376,6 +407,7 @@ bmp_result bmp_decode_rgb24(struct bmp_image *bmp, char **start, int bytes) {
|
||||||
unsigned int *scanline;
|
unsigned int *scanline;
|
||||||
unsigned int x, y, swidth, skip;
|
unsigned int x, y, swidth, skip;
|
||||||
unsigned int addr;
|
unsigned int addr;
|
||||||
|
unsigned int i, word;
|
||||||
|
|
||||||
data = *start;
|
data = *start;
|
||||||
swidth = bitmap_get_rowstride(bmp->bitmap);
|
swidth = bitmap_get_rowstride(bmp->bitmap);
|
||||||
|
@ -395,9 +427,86 @@ bmp_result bmp_decode_rgb24(struct bmp_image *bmp, char **start, int bytes) {
|
||||||
scanline = (unsigned int *)(top + (y * swidth));
|
scanline = (unsigned int *)(top + (y * swidth));
|
||||||
else
|
else
|
||||||
scanline = (unsigned int *)(bottom - (y * swidth));
|
scanline = (unsigned int *)(bottom - (y * swidth));
|
||||||
for (x = 0; x < bmp->width; x++) {
|
if (bmp->encoding == BMP_ENCODING_BITFIELDS) {
|
||||||
scanline[x] = data[2] | (data[1] << 8) | (data[0] << 16);
|
for (x = 0; x < bmp->width; x++) {
|
||||||
data += skip;
|
word = data[0] | (data[1] << 8) | (data[2] << 16) |
|
||||||
|
(data[3] << 24);
|
||||||
|
scanline[x] = 0;
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
if (bmp->shift[i] > 0)
|
||||||
|
scanline[x] |= ((word & bmp->mask[i]) <<
|
||||||
|
bmp->shift[i]);
|
||||||
|
else
|
||||||
|
scanline[x] |= ((word & bmp->mask[i]) >>
|
||||||
|
(-bmp->shift[i]));
|
||||||
|
data += 4;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (x = 0; x < bmp->width; x++) {
|
||||||
|
scanline[x] = data[2] | (data[1] << 8) | (data[0] << 16) |
|
||||||
|
(data[3] << 24);
|
||||||
|
data += skip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*start = data;
|
||||||
|
return BMP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode BMP data stored in 16bpp colour.
|
||||||
|
*
|
||||||
|
* \param bmp the BMP image to decode
|
||||||
|
* \param start the data to decode, updated to last byte read on success
|
||||||
|
* \param bytes the number of bytes of data available
|
||||||
|
* \return BMP_OK on success
|
||||||
|
*/
|
||||||
|
bmp_result bmp_decode_rgb16(struct bmp_image *bmp, char **start, int bytes) {
|
||||||
|
char *top, *bottom, *end, *data;
|
||||||
|
unsigned int *scanline;
|
||||||
|
unsigned int x, y, swidth;
|
||||||
|
unsigned int addr;
|
||||||
|
unsigned int word, i;
|
||||||
|
|
||||||
|
data = *start;
|
||||||
|
swidth = bitmap_get_rowstride(bmp->bitmap);
|
||||||
|
top = bitmap_get_buffer(bmp->bitmap);
|
||||||
|
bottom = top + swidth * (bmp->height - 1);
|
||||||
|
end = data + bytes;
|
||||||
|
addr = ((unsigned int)data) & 3;
|
||||||
|
bmp->decoded = true;
|
||||||
|
|
||||||
|
for (y = 0; y < bmp->height; y++) {
|
||||||
|
if (addr != (((unsigned int)data) & 3))
|
||||||
|
data += 2;
|
||||||
|
if ((data + (2 * bmp->width)) > end)
|
||||||
|
return BMP_INSUFFICIENT_DATA;
|
||||||
|
if (bmp->reversed)
|
||||||
|
scanline = (unsigned int *)(top + (y * swidth));
|
||||||
|
else
|
||||||
|
scanline = (unsigned int *)(bottom - (y * swidth));
|
||||||
|
if (bmp->encoding == BMP_ENCODING_BITFIELDS) {
|
||||||
|
for (x = 0; x < bmp->width; x++) {
|
||||||
|
word = data[0] | (data[1] << 8);
|
||||||
|
scanline[x] = 0;
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
if (bmp->shift[i] > 0)
|
||||||
|
scanline[x] |= ((word & bmp->mask[i]) <<
|
||||||
|
bmp->shift[i]);
|
||||||
|
else
|
||||||
|
scanline[x] |= ((word & bmp->mask[i]) >>
|
||||||
|
(-bmp->shift[i]));
|
||||||
|
data += 2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (x = 0; x < bmp->width; x++) {
|
||||||
|
word = data[0] | (data[1] << 8);
|
||||||
|
scanline[x] = ((word & (31 << 0)) << 19) |
|
||||||
|
((word & (31 << 5)) << 6) |
|
||||||
|
((word & (31 << 10)) >> 7);
|
||||||
|
data += 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*start = data;
|
*start = data;
|
||||||
|
@ -487,7 +596,7 @@ bmp_result bmp_decode_mask(struct bmp_image *bmp, char *data, int bytes) {
|
||||||
return BMP_INSUFFICIENT_DATA;
|
return BMP_INSUFFICIENT_DATA;
|
||||||
scanline = (unsigned int *)(bottom - (y * swidth));
|
scanline = (unsigned int *)(bottom - (y * swidth));
|
||||||
for (x = 0; x < bmp->width; x++) {
|
for (x = 0; x < bmp->width; x++) {
|
||||||
if ((x & 7) == 0)
|
if ((x & 7) == 0)
|
||||||
cur_byte = *data++;
|
cur_byte = *data++;
|
||||||
if ((cur_byte & 128) == 0)
|
if ((cur_byte & 128) == 0)
|
||||||
scanline[x] |= (0xff << 24);
|
scanline[x] |= (0xff << 24);
|
||||||
|
@ -523,15 +632,15 @@ bmp_result bmp_decode_rle(struct bmp_image *bmp, char *data, int bytes, int size
|
||||||
bottom = top + swidth * (bmp->height - 1);
|
bottom = top + swidth * (bmp->height - 1);
|
||||||
end = data + bytes;
|
end = data + bytes;
|
||||||
bmp->decoded = true;
|
bmp->decoded = true;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (data + 2 > end)
|
if (data + 2 > end)
|
||||||
return BMP_INSUFFICIENT_DATA;
|
return BMP_INSUFFICIENT_DATA;
|
||||||
length = *data++;
|
length = *data++;
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
length = *data++;
|
length = *data++;
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
/* 00 - 00 means end of scanline */
|
/* 00 - 00 means end of scanline */
|
||||||
x = 0;
|
x = 0;
|
||||||
if (last_y == y) {
|
if (last_y == y) {
|
||||||
if (++y > bmp->height)
|
if (++y > bmp->height)
|
||||||
|
@ -539,12 +648,12 @@ bmp_result bmp_decode_rle(struct bmp_image *bmp, char *data, int bytes, int size
|
||||||
}
|
}
|
||||||
last_y = y;
|
last_y = y;
|
||||||
} else if (length == 1) {
|
} else if (length == 1) {
|
||||||
/* 00 - 01 means end of RLE data */
|
/* 00 - 01 means end of RLE data */
|
||||||
return BMP_OK;
|
return BMP_OK;
|
||||||
} else if (length == 2) {
|
} else if (length == 2) {
|
||||||
/* 00 - 02 - XX - YY means move cursor */
|
/* 00 - 02 - XX - YY means move cursor */
|
||||||
if (data + 2 > end)
|
if (data + 2 > end)
|
||||||
return BMP_INSUFFICIENT_DATA;
|
return BMP_INSUFFICIENT_DATA;
|
||||||
x += *data++;
|
x += *data++;
|
||||||
if (x >= bmp->width)
|
if (x >= bmp->width)
|
||||||
return BMP_DATA_ERROR;
|
return BMP_DATA_ERROR;
|
||||||
|
@ -552,7 +661,7 @@ bmp_result bmp_decode_rle(struct bmp_image *bmp, char *data, int bytes, int size
|
||||||
if (y >= bmp->height)
|
if (y >= bmp->height)
|
||||||
return BMP_DATA_ERROR;
|
return BMP_DATA_ERROR;
|
||||||
} else {
|
} else {
|
||||||
/* 00 - NN means escape pixels */
|
/* 00 - NN means escape NN pixels */
|
||||||
if (bmp->reversed) {
|
if (bmp->reversed) {
|
||||||
pixels_left = (y + 1) * bmp->width - x;
|
pixels_left = (y + 1) * bmp->width - x;
|
||||||
scanline = (unsigned int *)(top + (y * swidth));
|
scanline = (unsigned int *)(top + (y * swidth));
|
||||||
|
@ -560,14 +669,14 @@ bmp_result bmp_decode_rle(struct bmp_image *bmp, char *data, int bytes, int size
|
||||||
pixels_left = (bmp->height - y + 1) * bmp->width - x;
|
pixels_left = (bmp->height - y + 1) * bmp->width - x;
|
||||||
scanline = (unsigned int *)(bottom - (y * swidth));
|
scanline = (unsigned int *)(bottom - (y * swidth));
|
||||||
}
|
}
|
||||||
if (length > pixels_left)
|
if (length > pixels_left)
|
||||||
length = pixels_left;
|
length = pixels_left;
|
||||||
if (data + length > end)
|
if (data + length > end)
|
||||||
return BMP_INSUFFICIENT_DATA;
|
return BMP_INSUFFICIENT_DATA;
|
||||||
|
|
||||||
/* the following code could be easily optimised by simply
|
/* the following code could be easily optimised by simply
|
||||||
* checking the bounds on entry and using some simply copying
|
* checking the bounds on entry and using some simply copying
|
||||||
* routines if so */
|
* routines if so */
|
||||||
if (size == 8) {
|
if (size == 8) {
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
if (x >= bmp->width) {
|
if (x >= bmp->width) {
|
||||||
|
@ -586,11 +695,11 @@ bmp_result bmp_decode_rle(struct bmp_image *bmp, char *data, int bytes, int size
|
||||||
return BMP_DATA_ERROR;
|
return BMP_DATA_ERROR;
|
||||||
scanline -= bmp->width;
|
scanline -= bmp->width;
|
||||||
}
|
}
|
||||||
if ((i & 1) == 0) {
|
if ((i & 1) == 0) {
|
||||||
pixel = *data++;
|
pixel = *data++;
|
||||||
scanline[x++] = bmp->colour_table
|
scanline[x++] = bmp->colour_table
|
||||||
[pixel >> 4];
|
[pixel >> 4];
|
||||||
} else {
|
} else {
|
||||||
scanline[x++] = bmp->colour_table
|
scanline[x++] = bmp->colour_table
|
||||||
[pixel & 0xf];
|
[pixel & 0xf];
|
||||||
}
|
}
|
||||||
|
@ -602,7 +711,7 @@ bmp_result bmp_decode_rle(struct bmp_image *bmp, char *data, int bytes, int size
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* NN means perform RLE for NN pixels */
|
/* NN means perform RLE for NN pixels */
|
||||||
if (bmp->reversed) {
|
if (bmp->reversed) {
|
||||||
pixels_left = (y + 1) * bmp->width - x;
|
pixels_left = (y + 1) * bmp->width - x;
|
||||||
scanline = (unsigned int *)(top + (y * swidth));
|
scanline = (unsigned int *)(top + (y * swidth));
|
||||||
|
@ -610,12 +719,12 @@ bmp_result bmp_decode_rle(struct bmp_image *bmp, char *data, int bytes, int size
|
||||||
pixels_left = (bmp->height - y + 1) * bmp->width - x;
|
pixels_left = (bmp->height - y + 1) * bmp->width - x;
|
||||||
scanline = (unsigned int *)(bottom - (y * swidth));
|
scanline = (unsigned int *)(bottom - (y * swidth));
|
||||||
}
|
}
|
||||||
if (length > pixels_left)
|
if (length > pixels_left)
|
||||||
length = pixels_left;
|
length = pixels_left;
|
||||||
|
|
||||||
/* the following code could be easily optimised by simply
|
/* the following code could be easily optimised by simply
|
||||||
* checking the bounds on entry and using some simply copying
|
* checking the bounds on entry and using some simply copying
|
||||||
* routines if so */
|
* routines if so */
|
||||||
if (size == 8) {
|
if (size == 8) {
|
||||||
pixel = bmp->colour_table[(int)*data++];
|
pixel = bmp->colour_table[(int)*data++];
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
|
@ -672,12 +781,12 @@ void bmp_finalise(struct bmp_image *bmp) {
|
||||||
*/
|
*/
|
||||||
void ico_finalise(struct ico_collection *ico) {
|
void ico_finalise(struct ico_collection *ico) {
|
||||||
struct ico_image *image;
|
struct ico_image *image;
|
||||||
|
|
||||||
for (image = ico->first; image; image = image->next)
|
for (image = ico->first; image; image = image->next)
|
||||||
bmp_finalise(&image->bmp);
|
bmp_finalise(&image->bmp);
|
||||||
while (ico->first) {
|
while (ico->first) {
|
||||||
image = ico->first;
|
image = ico->first;
|
||||||
ico->first = image->next;
|
ico->first = image->next;
|
||||||
free(image);
|
free(image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,6 @@ typedef enum {
|
||||||
BMP_ENCODING_BITFIELDS = 3
|
BMP_ENCODING_BITFIELDS = 3
|
||||||
} bmp_encoding;
|
} bmp_encoding;
|
||||||
|
|
||||||
|
|
||||||
struct bmp_image {
|
struct bmp_image {
|
||||||
unsigned char *bmp_data; /** pointer to BMP data */
|
unsigned char *bmp_data; /** pointer to BMP data */
|
||||||
unsigned int buffer_size; /** total number of bytes of BMP data available */
|
unsigned int buffer_size; /** total number of bytes of BMP data available */
|
||||||
|
@ -45,6 +44,8 @@ struct bmp_image {
|
||||||
bool reversed; /** scanlines are top to bottom */
|
bool reversed; /** scanlines are top to bottom */
|
||||||
bool decoded; /** whether the image has been decoded */
|
bool decoded; /** whether the image has been decoded */
|
||||||
bool ico; /** image is part of an ICO, mask follows */
|
bool ico; /** image is part of an ICO, mask follows */
|
||||||
|
unsigned int mask[4]; /** four bitwise mask */
|
||||||
|
int shift[4]; /** four bitwise shifts */
|
||||||
struct bitmap *bitmap; /** decoded image */
|
struct bitmap *bitmap; /** decoded image */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue