summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Fox <dyntryx@gmail.com>2008-06-27 03:42:33 +0000
committerSean Fox <dyntryx@gmail.com>2008-06-27 03:42:33 +0000
commitef3d085158e9d56c38b186942abc6cf5dd81f3c3 (patch)
tree637394ad939330044e2508fbf0ca5bbc6f0b5af6
parent701b5113963324efe386807130201dd4a4c72145 (diff)
downloadlibnsbmp-ef3d085158e9d56c38b186942abc6cf5dd81f3c3.tar.gz
libnsbmp-ef3d085158e9d56c38b186942abc6cf5dd81f3c3.tar.bz2
Correct coloring issue under linux caused by signedness; added bmp_create() function
svn path=/branches/dynis/libnsbmp/; revision=4461
-rw-r--r--libnsbmp.c120
-rw-r--r--libnsbmp.h13
2 files changed, 72 insertions, 61 deletions
diff --git a/libnsbmp.c b/libnsbmp.c
index b3d79c2..1b56143 100644
--- a/libnsbmp.c
+++ b/libnsbmp.c
@@ -26,21 +26,34 @@
#include "libnsbmp.h"
#include "utils/log.h"
-#define READ_SHORT(a, o) (a[o]|(a[o+1]<<8))
-#define READ_INT(a, o) (a[o]|(a[o+1]<<8)|(a[o+2]<<16)|(a[o+3]<<24))
-
/* squashes unused variable compiler warnings */
#define UNUSED(x) ((x)=(x))
-bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data, bmp_bitmap_callback_vt *bitmap_callbacks);
-bmp_result bmp_decode_rgb24(struct bmp_image *bmp, char **start, int bytes, bmp_bitmap_callback_vt *bitmap_callbacks);
-bmp_result bmp_decode_rgb16(struct bmp_image *bmp, char **start, int bytes, bmp_bitmap_callback_vt *bitmap_callbacks);
-bmp_result bmp_decode_rgb(struct bmp_image *bmp, char **start, int bytes, bmp_bitmap_callback_vt *bitmap_callbacks);
-bmp_result bmp_decode_mask(struct bmp_image *bmp, char *data, int bytes, bmp_bitmap_callback_vt *bitmap_callbacks);
-bmp_result bmp_decode_rle(struct bmp_image *bmp, char *data, int bytes, int size, bmp_bitmap_callback_vt *bitmap_callbacks);
+static inline int read_short(unsigned char *data, unsigned int o) {
+ return (data[o] | ((unsigned char)data[o+1] << 8));
+}
+
+static inline int read_int(unsigned char *data, unsigned int o) {
+ return ((unsigned char)data[o] | ((unsigned char)data[o+1] << 8) | ((unsigned char)data[o+2] << 16) | ((unsigned char)data[o+3] << 24));
+}
+
+bmp_result bmp_analyse_header(struct bmp_image *bmp, unsigned char *data, bmp_bitmap_callback_vt *bitmap_callbacks);
+bmp_result bmp_decode_rgb24(struct bmp_image *bmp, unsigned char **start, int bytes, bmp_bitmap_callback_vt *bitmap_callbacks);
+bmp_result bmp_decode_rgb16(struct bmp_image *bmp, unsigned char **start, int bytes, bmp_bitmap_callback_vt *bitmap_callbacks);
+bmp_result bmp_decode_rgb(struct bmp_image *bmp, unsigned char **start, int bytes, bmp_bitmap_callback_vt *bitmap_callbacks);
+bmp_result bmp_decode_mask(struct bmp_image *bmp, unsigned char *data, int bytes, bmp_bitmap_callback_vt *bitmap_callbacks);
+bmp_result bmp_decode_rle(struct bmp_image *bmp, unsigned char *data, int bytes, int size, bmp_bitmap_callback_vt *bitmap_callbacks);
void bmp_invalidate(void *bitmap, void *private_word);
+
+/** Initialises necessary bmp_image members.
+*/
+void bmp_create(bmp_image *bmp) {
+ memset(bmp, 0, sizeof(bmp_image));
+}
+
+
/**
* Analyse a BMP prior to decoding.
*
@@ -54,7 +67,7 @@ void bmp_invalidate(void *bitmap, void *private_word);
* \return BMP_OK on success
*/
bmp_result bmp_analyse(struct bmp_image *bmp, bmp_bitmap_callback_vt *bitmap_callbacks) {
- char *data = (char *) bmp->bmp_data;
+ unsigned char *data = bmp->bmp_data;
/* ensure we aren't already initialised */
if (bmp->bitmap)
@@ -72,7 +85,7 @@ bmp_result bmp_analyse(struct bmp_image *bmp, bmp_bitmap_callback_vt *bitmap_cal
return BMP_INSUFFICIENT_DATA;
if ((data[0] != 'B') || (data[1] != 'M'))
return BMP_DATA_ERROR;
- bmp->bitmap_offset = READ_INT(data, 10);
+ bmp->bitmap_offset = read_int(data, 10);
/* decode the BMP header */
return bmp_analyse_header(bmp, data + 14, bitmap_callbacks);
@@ -91,7 +104,7 @@ bmp_result bmp_analyse(struct bmp_image *bmp, bmp_bitmap_callback_vt *bitmap_cal
* \return BMP_OK on success
*/
bmp_result ico_analyse(struct ico_collection *ico, bmp_bitmap_callback_vt *bitmap_callbacks) {
- char *data = (char *) ico->ico_data;
+ unsigned char *data = ico->ico_data;
unsigned int count, i;
bmp_result result;
struct ico_image *image;
@@ -108,9 +121,9 @@ bmp_result ico_analyse(struct ico_collection *ico, bmp_bitmap_callback_vt *bitma
*/
if (ico->buffer_size < 6)
return BMP_INSUFFICIENT_DATA;
- if (READ_INT(data, 0) != 0x00010000)
+ if (read_int(data, 0) != 0x00010000)
return BMP_DATA_ERROR;
- count = READ_SHORT(data, 4);
+ count = read_short(data, 4);
if (count == 0)
return BMP_DATA_ERROR;
data += 6;
@@ -126,12 +139,12 @@ bmp_result ico_analyse(struct ico_collection *ico, bmp_bitmap_callback_vt *bitma
ico->first = image;
image->bmp.width = data[0];
image->bmp.height = data[1];
- image->bmp.buffer_size = READ_INT(data, 8) + 40;
- image->bmp.bmp_data = ico->ico_data + READ_INT(data, 12);
+ image->bmp.buffer_size = read_int(data, 8) + 40;
+ image->bmp.bmp_data = ico->ico_data + read_int(data, 12);
image->bmp.ico = true;
data += 16;
result = bmp_analyse_header(&image->bmp,
- (char *) image->bmp.bmp_data, bitmap_callbacks);
+ image->bmp.bmp_data, bitmap_callbacks);
if (result != BMP_OK)
return result;
area = image->bmp.width * image->bmp.height;
@@ -145,7 +158,7 @@ bmp_result ico_analyse(struct ico_collection *ico, bmp_bitmap_callback_vt *bitma
}
-bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data, bmp_bitmap_callback_vt *bitmap_callbacks) {
+bmp_result bmp_analyse_header(struct bmp_image *bmp, unsigned char *data, bmp_bitmap_callback_vt *bitmap_callbacks) {
unsigned int header_size;
unsigned int i;
int width, height, j;
@@ -156,7 +169,7 @@ bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data, bmp_bitmap_call
* on the BMP variant. A full description of the various headers
* can be found at http://www.fileformat.info/format/bmp/
*/
- header_size = READ_INT(data, 0);
+ header_size = read_int(data, 0);
if (bmp->buffer_size < (14 + header_size))
return BMP_INSUFFICIENT_DATA;
if (header_size == 12) {
@@ -168,8 +181,8 @@ bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data, bmp_bitmap_call
* +8 SHORT number of color planes (always 1)
* +10 SHORT number of bits per pixel
*/
- width = READ_SHORT(data, 4);
- height = READ_SHORT(data, 6);
+ width = read_short(data, 4);
+ height = read_short(data, 6);
if (width < 0)
return BMP_DATA_ERROR;
if (height < 0) {
@@ -178,9 +191,9 @@ bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data, bmp_bitmap_call
}
bmp->width = width;
bmp->height = height;
- if (READ_SHORT(data, 8) != 1)
+ if (read_short(data, 8) != 1)
return BMP_DATA_ERROR;
- bmp->bpp = READ_SHORT(data, 10);
+ bmp->bpp = read_short(data, 10);
bmp->colours = (1 << bmp->bpp);
palette_size = 3;
} else if (header_size < 40) {
@@ -219,8 +232,8 @@ bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data, bmp_bitmap_call
* +104 INT gamma blue coordinate scale value
*/
if (!bmp->ico) {
- width = READ_INT(data, 4);
- height = READ_INT(data, 8);
+ width = read_int(data, 4);
+ height = read_int(data, 8);
if (width < 0)
return BMP_DATA_ERROR;
if (height < 0) {
@@ -230,12 +243,12 @@ bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data, bmp_bitmap_call
bmp->width = width;
bmp->height = height;
}
- if (READ_SHORT(data, 12) != 1)
+ if (read_short(data, 12) != 1)
return BMP_DATA_ERROR;
- bmp->bpp = READ_SHORT(data, 14);
+ bmp->bpp = read_short(data, 14);
if (bmp->bpp == 0)
bmp->bpp = 8;
- bmp->encoding = READ_INT(data, 16);
+ bmp->encoding = read_int(data, 16);
if (bmp->encoding > BMP_ENCODING_BITFIELDS)
return BMP_DATA_ERROR;
if (bmp->encoding == BMP_ENCODING_BITFIELDS) {
@@ -246,10 +259,10 @@ bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data, bmp_bitmap_call
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));
+ 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));
+ bmp->mask[i] = read_int(data, 40 + (i << 2));
}
for (i = 0; i < 4; i++) {
if (bmp->mask[i] == 0)
@@ -265,7 +278,7 @@ bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data, bmp_bitmap_call
}
}
}
- bmp->colours = READ_INT(data, 32);
+ bmp->colours = read_int(data, 32);
if (bmp->colours == 0)
bmp->colours = (1 << bmp->bpp);
palette_size = 4;
@@ -285,13 +298,11 @@ bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data, bmp_bitmap_call
*/
if (bmp->buffer_size < (14 + header_size + (4 * bmp->colours)))
return BMP_INSUFFICIENT_DATA;
- bmp->colour_table = (unsigned int *)
- malloc(bmp->colours * sizeof(int));
+ bmp->colour_table = (unsigned int *)malloc(bmp->colours * sizeof(int));
if (!bmp->colour_table)
return BMP_INSUFFICIENT_MEMORY;
for (i = 0; i < bmp->colours; i++) {
- bmp->colour_table[i] = data[2] | (data[1] << 8) |
- (data[0] << 16);
+ bmp->colour_table[i] = data[2] | (data[1] << 8) | (data[0] << 16);
data += palette_size;
}
}
@@ -313,7 +324,7 @@ bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data, bmp_bitmap_call
}
-/*
+/**
* Finds the closest BMP within an ICO collection
*
* This function finds the BMP with dimensions as close to a specified set
@@ -370,13 +381,13 @@ void bmp_invalidate(void *bitmap, void *private_word) {
* \return BMP_OK on success
*/
bmp_result bmp_decode(struct bmp_image *bmp, bmp_bitmap_callback_vt *bitmap_callbacks) {
- char *data;
+ unsigned char *data;
int bytes;
bmp_result result = BMP_OK;
assert(bmp->bitmap);
- data = (char *) bmp->bmp_data + bmp->bitmap_offset;
+ data = bmp->bmp_data + bmp->bitmap_offset;
bytes = bmp->buffer_size - bmp->bitmap_offset;
switch (bmp->encoding) {
@@ -419,15 +430,15 @@ bmp_result bmp_decode(struct bmp_image *bmp, bmp_bitmap_callback_vt *bitmap_call
* \param bytes the number of bytes of data available
* \return BMP_OK on success
*/
-bmp_result bmp_decode_rgb24(struct bmp_image *bmp, char **start, int bytes, bmp_bitmap_callback_vt *bitmap_callbacks) {
- char *top, *bottom, *end, *data;
+bmp_result bmp_decode_rgb24(struct bmp_image *bmp, unsigned char **start, int bytes, bmp_bitmap_callback_vt *bitmap_callbacks) {
+ unsigned char *top, *bottom, *end, *data;
unsigned int *scanline;
unsigned int x, y, swidth, skip;
intptr_t addr;
unsigned int i, word;
data = *start;
- swidth = bitmap_callbacks->bitmap_get_rowstride(bmp->bitmap);
+ swidth = bitmap_callbacks->bitmap_get_bpp(bmp->bitmap) * bmp->width;
top = bitmap_callbacks->bitmap_get_buffer(bmp->bitmap);
if (!top)
return BMP_INSUFFICIENT_MEMORY;
@@ -462,8 +473,7 @@ bmp_result bmp_decode_rgb24(struct bmp_image *bmp, char **start, int bytes, bmp_
}
} else {
for (x = 0; x < bmp->width; x++) {
- scanline[x] = data[2] | (data[1] << 8) | (data[0] << 16) |
- (data[3] << 24);
+ scanline[x] = data[2] | (data[1] << 8) | (data[0] << 16) | (0xff << 24);
data += skip;
}
}
@@ -481,15 +491,15 @@ bmp_result bmp_decode_rgb24(struct bmp_image *bmp, char **start, int bytes, bmp_
* \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, bmp_bitmap_callback_vt *bitmap_callbacks) {
- char *top, *bottom, *end, *data;
+bmp_result bmp_decode_rgb16(struct bmp_image *bmp, unsigned char **start, int bytes, bmp_bitmap_callback_vt *bitmap_callbacks) {
+ unsigned char *top, *bottom, *end, *data;
unsigned int *scanline;
unsigned int x, y, swidth;
intptr_t addr;
unsigned int word, i;
data = *start;
- swidth = bitmap_callbacks->bitmap_get_rowstride(bmp->bitmap);
+ swidth = bitmap_callbacks->bitmap_get_bpp(bmp->bitmap) * bmp->width;
top = bitmap_callbacks->bitmap_get_buffer(bmp->bitmap);
if (!top)
return BMP_INSUFFICIENT_MEMORY;
@@ -543,8 +553,8 @@ bmp_result bmp_decode_rgb16(struct bmp_image *bmp, char **start, int bytes, bmp_
* \param bytes the number of bytes of data available
* \return BMP_OK on success
*/
-bmp_result bmp_decode_rgb(struct bmp_image *bmp, char **start, int bytes, bmp_bitmap_callback_vt *bitmap_callbacks) {
- char *top, *bottom, *end, *data;
+bmp_result bmp_decode_rgb(struct bmp_image *bmp, unsigned char **start, int bytes, bmp_bitmap_callback_vt *bitmap_callbacks) {
+ unsigned char *top, *bottom, *end, *data;
unsigned int *scanline;
intptr_t addr;
unsigned int x, y, swidth;
@@ -558,7 +568,7 @@ bmp_result bmp_decode_rgb(struct bmp_image *bmp, char **start, int bytes, bmp_bi
bit_shifts[i] = 8 - ((i + 1) * bmp->bpp);
data = *start;
- swidth = bitmap_callbacks->bitmap_get_rowstride(bmp->bitmap);
+ swidth = bitmap_callbacks->bitmap_get_bpp(bmp->bitmap) * bmp->width;
top = bitmap_callbacks->bitmap_get_buffer(bmp->bitmap);
if (!top)
return BMP_INSUFFICIENT_MEMORY;
@@ -599,14 +609,14 @@ bmp_result bmp_decode_rgb(struct bmp_image *bmp, char **start, int bytes, bmp_bi
* \param bytes the number of bytes of data available
* \return BMP_OK on success
*/
-bmp_result bmp_decode_mask(struct bmp_image *bmp, char *data, int bytes, bmp_bitmap_callback_vt *bitmap_callbacks) {
- char *top, *bottom, *end;
+bmp_result bmp_decode_mask(struct bmp_image *bmp, unsigned char *data, int bytes, bmp_bitmap_callback_vt *bitmap_callbacks) {
+ unsigned char *top, *bottom, *end;
unsigned int *scanline;
intptr_t addr;
unsigned int x, y, swidth;
int cur_byte = 0;
- swidth = bitmap_callbacks->bitmap_get_rowstride(bmp->bitmap);
+ swidth = bitmap_callbacks->bitmap_get_bpp(bmp->bitmap) * bmp->width;
top = bitmap_callbacks->bitmap_get_buffer(bmp->bitmap);
if (!top)
return BMP_INSUFFICIENT_MEMORY;
@@ -641,8 +651,8 @@ bmp_result bmp_decode_mask(struct bmp_image *bmp, char *data, int bytes, bmp_bit
* \param size the size of the RLE tokens (4 or 8)
* \return BMP_OK on success
*/
-bmp_result bmp_decode_rle(struct bmp_image *bmp, char *data, int bytes, int size, bmp_bitmap_callback_vt *bitmap_callbacks) {
- char *top, *bottom, *end;
+bmp_result bmp_decode_rle(struct bmp_image *bmp, unsigned char *data, int bytes, int size, bmp_bitmap_callback_vt *bitmap_callbacks) {
+ unsigned char *top, *bottom, *end;
unsigned int *scanline;
unsigned int swidth;
int i, length, pixels_left;
@@ -652,7 +662,7 @@ bmp_result bmp_decode_rle(struct bmp_image *bmp, char *data, int bytes, int size
if (bmp->ico)
return BMP_DATA_ERROR;
- swidth = bitmap_callbacks->bitmap_get_rowstride(bmp->bitmap);
+ swidth = bitmap_callbacks->bitmap_get_bpp(bmp->bitmap) * bmp->width;
top = bitmap_callbacks->bitmap_get_buffer(bmp->bitmap);
if (!top)
return BMP_INSUFFICIENT_MEMORY;
diff --git a/libnsbmp.h b/libnsbmp.h
index 610be0d..61e9ef8 100644
--- a/libnsbmp.h
+++ b/libnsbmp.h
@@ -53,8 +53,8 @@ typedef void* (*bmp_bitmap_cb_create)(int width, int height, unsigned int state)
typedef void (*bmp_bitmap_cb_destroy)(void *bitmap);
typedef void (*bmp_bitmap_cb_set_suspendable)(void *bitmap, void *private_word,
void (*invalidate)(void *bitmap, void *private_word));
-typedef char* (*bmp_bitmap_cb_get_buffer)(void *bitmap);
-typedef size_t (*bmp_bitmap_cb_get_rowstride)(void *bitmap);
+typedef unsigned char* (*bmp_bitmap_cb_get_buffer)(void *bitmap);
+typedef size_t (*bmp_bitmap_cb_get_bpp)(void *bitmap);
/* The Bitmap callbacks function table
*/
@@ -63,10 +63,10 @@ typedef struct bmp_bitmap_callback_vt_s {
bmp_bitmap_cb_destroy bitmap_destroy; /**< Free a bitmap. */
bmp_bitmap_cb_set_suspendable bitmap_set_suspendable; /**< The bitmap image can be suspended. */
bmp_bitmap_cb_get_buffer bitmap_get_buffer; /**< Return a pointer to the pixel data in a bitmap. */
- bmp_bitmap_cb_get_rowstride bitmap_get_rowstride; /**< Find the width of a pixel row in bytes. */
+ bmp_bitmap_cb_get_bpp bitmap_get_bpp; /**< Find the width of a pixel row in bytes. */
} bmp_bitmap_callback_vt;
-struct bmp_image {
+typedef struct bmp_image {
unsigned char *bmp_data; /** pointer to BMP data */
unsigned int buffer_size; /** total number of bytes of BMP data available */
unsigned int width; /** width of BMP (valid after _analyse) */
@@ -81,8 +81,8 @@ struct bmp_image {
bool ico; /** image is part of an ICO, mask follows */
unsigned int mask[4]; /** four bitwise mask */
int shift[4]; /** four bitwise shifts */
- void *bitmap; /** decoded image */
-};
+ void *bitmap; /** decoded image */
+} bmp_image;
struct ico_image {
struct bmp_image bmp;
@@ -97,6 +97,7 @@ struct ico_collection {
struct ico_image *first;
};
+void bmp_create(bmp_image *gif);
bmp_result bmp_analyse(struct bmp_image *bmp, bmp_bitmap_callback_vt *bitmap_callbacks);
bmp_result bmp_decode(struct bmp_image *bmp, bmp_bitmap_callback_vt *bitmap_callbacks);
void bmp_finalise(struct bmp_image *bmp, bmp_bitmap_callback_vt *bitmap_callbacks);