summaryrefslogtreecommitdiff
path: root/image
diff options
context:
space:
mode:
Diffstat (limited to 'image')
-rw-r--r--image/bmp.c127
-rw-r--r--image/bmp.h33
-rw-r--r--image/bmpread.c483
-rw-r--r--image/bmpread.h54
4 files changed, 697 insertions, 0 deletions
diff --git a/image/bmp.c b/image/bmp.c
new file mode 100644
index 000000000..b2fc59f86
--- /dev/null
+++ b/image/bmp.c
@@ -0,0 +1,127 @@
+/*
+ * This file is part of NetSurf, http://netsurf.sourceforge.net/
+ * Licensed under the GNU General Public License,
+ * http://www.opensource.org/licenses/gpl-license
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include "netsurf/utils/config.h"
+#include "netsurf/content/content.h"
+#include "netsurf/desktop/browser.h"
+#include "netsurf/desktop/options.h"
+#include "netsurf/desktop/plotters.h"
+#include "netsurf/image/bitmap.h"
+#include "netsurf/image/bmp.h"
+#include "netsurf/image/bmpread.h"
+#include "netsurf/utils/log.h"
+#include "netsurf/utils/messages.h"
+#include "netsurf/utils/utils.h"
+
+#ifdef WITH_BMP
+
+static void nsbmp_invalidate(struct bitmap *bitmap, void *private_word);
+
+bool nsbmp_create(struct content *c, const char *params[]) {
+ union content_msg_data msg_data;
+
+ c->data.bmp.bmp = calloc(sizeof(struct bmp_image), 1);
+ if (!c->data.bmp.bmp) {
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ warn_user("NoMemory", 0);
+ return false;
+ }
+ return true;
+}
+
+
+bool nsbmp_convert(struct content *c, int iwidth, int iheight) {
+ bmp_result res;
+ struct bmp_image *bmp;
+ union content_msg_data msg_data;
+
+ /* set our source data */
+ bmp = c->data.bmp.bmp;
+ bmp->bmp_data = c->source_data;
+ bmp->buffer_size = c->source_size;
+
+ /* analyse the BMP */
+ res = bmp_analyse(bmp);
+ switch (res) {
+ case BMP_OK:
+ break;
+ case BMP_INSUFFICIENT_MEMORY:
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ warn_user("NoMemory", 0);
+ return false;
+ case BMP_INSUFFICIENT_DATA:
+ case BMP_DATA_ERROR:
+ msg_data.error = messages_get("BadBMP");
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ /* Store our content width and description
+ */
+ c->width = bmp->width;
+ c->height = bmp->height;
+ c->title = malloc(100);
+ if (c->title)
+ snprintf(c->title, 100, messages_get("BMPTitle"), c->width,
+ c->height, c->source_size);
+ c->size += (bmp->width * bmp->height * 4) + 16 + 44 + 100;
+
+ /* make so that the bitmap code can free our image quickly */
+ bitmap_set_suspendable(bmp->bitmap, bmp, nsbmp_invalidate);
+
+ /* exit as a success */
+ c->bitmap = bmp->bitmap;
+ c->status = CONTENT_STATUS_DONE;
+ return true;
+}
+
+void nsbmp_invalidate(struct bitmap *bitmap, void *private_word) {
+ struct bmp_image *bmp = (struct bmp_image *)private_word;
+
+ bmp->decoded = false;
+}
+
+bool nsbmp_redraw(struct content *c, int x, int y,
+ int width, int height,
+ int clip_x0, int clip_y0, int clip_x1, int clip_y1,
+ float scale, unsigned long background_colour) {
+
+ if (!c->data.bmp.bmp->decoded)
+ bmp_decode(c->data.bmp.bmp);
+ c->bitmap = c->data.bmp.bmp->bitmap;
+ return plot.bitmap(x, y, width, height, c->bitmap, background_colour);
+}
+
+
+bool nsbmp_redraw_tiled(struct content *c, int x, int y,
+ int width, int height,
+ int clip_x0, int clip_y0, int clip_x1, int clip_y1,
+ float scale, unsigned long background_colour,
+ bool repeat_x, bool repeat_y) {
+
+ if (!c->data.bmp.bmp->decoded)
+ bmp_decode(c->data.bmp.bmp);
+ c->bitmap = c->data.bmp.bmp->bitmap;
+ return plot.bitmap_tile(x, y, width, height, c->bitmap,
+ background_colour, repeat_x, repeat_y);
+}
+
+
+void nsbmp_destroy(struct content *c)
+{
+ bmp_finalise(c->data.bmp.bmp);
+ free(c->data.bmp.bmp);
+ free(c->title);
+}
+
+#endif
diff --git a/image/bmp.h b/image/bmp.h
new file mode 100644
index 000000000..11f329b4d
--- /dev/null
+++ b/image/bmp.h
@@ -0,0 +1,33 @@
+/*
+ * This file is part of NetSurf, http://netsurf.sourceforge.net/
+ * Licensed under the GNU General Public License,
+ * http://www.opensource.org/licenses/gpl-license
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ */
+
+#ifndef _NETSURF_IMAGE_BMP_H_
+#define _NETSURF_IMAGE_BMP_H_
+
+#include <stdbool.h>
+#include "netsurf/image/bmpread.h"
+
+struct content;
+
+struct content_bmp_data {
+ struct bmp_image *bmp; /** BMP image data */
+};
+
+bool nsbmp_create(struct content *c, const char *params[]);
+bool nsbmp_convert(struct content *c, int width, int height);
+void nsbmp_destroy(struct content *c);
+bool nsbmp_redraw(struct content *c, int x, int y,
+ int width, int height,
+ int clip_x0, int clip_y0, int clip_x1, int clip_y1,
+ float scale, unsigned long background_colour);
+bool nsbmp_redraw_tiled(struct content *c, int x, int y,
+ int width, int height,
+ int clip_x0, int clip_y0, int clip_x1, int clip_y1,
+ float scale, unsigned long background_colour,
+ bool repeat_x, bool repeat_y);
+
+#endif
diff --git a/image/bmpread.c b/image/bmpread.c
new file mode 100644
index 000000000..15c103ae0
--- /dev/null
+++ b/image/bmpread.c
@@ -0,0 +1,483 @@
+/*
+ * This file is part of NetSurf, http://netsurf.sourceforge.net/
+ * Licensed under the GNU General Public License,
+ * http://www.opensource.org/licenses/gpl-license
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ */
+
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "netsurf/image/bmpread.h"
+#include "netsurf/image/bitmap.h"
+#include "netsurf/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))
+
+bmp_result bmp_decode_rgb24(struct bmp_image *bmp, char *data, int bytes);
+bmp_result bmp_decode_rgb(struct bmp_image *bmp, char *data, int bytes);
+bmp_result bmp_decode_rle(struct bmp_image *bmp, char *data, int bytes, int size);
+
+
+/**
+ * Analyse a BMP prior to decoding.
+ *
+ * This function will scan the data provided and perform simple checks to
+ * ensure the data is a valid BMP.
+ *
+ * This function must be called before bmp_decode() and sets up all the
+ * relevant values in the bmp structure.
+ *
+ * \param bmp the BMP image to analyse
+ * \return BMP_OK on success
+ */
+bmp_result bmp_analyse(struct bmp_image *bmp) {
+ char *data = bmp->bmp_data;
+ unsigned int header_size;
+ unsigned int i;
+ int width, height;
+ int palette_size;
+
+ /* ensure we aren't already initialised */
+ if (bmp->bitmap)
+ return BMP_OK;
+
+ /* standard 14-byte BMP file header is:
+ *
+ * +0 SHORT 'BM'
+ * +2 INT size of file (in bytes)
+ * +6 SHORT reserved field (1)
+ * +8 SHORT reserved field (2)
+ * +10 INT starting position of image data (in bytes)
+ */
+ if (bmp->buffer_size < 14)
+ return BMP_INSUFFICIENT_DATA;
+ if ((data[0] != 'B') || (data[1] != 'M'))
+ return BMP_DATA_ERROR;
+ bmp->bitmap_offset = READ_INT(data, 10);
+ data += 14;
+
+ /* a variety of different bitmap headers can now follow, depending
+ * 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);
+ if (bmp->buffer_size < (14 + header_size))
+ return BMP_INSUFFICIENT_DATA;
+ if (header_size == 12) {
+ /* the following header is for os/2 and windows 2.x and consists of:
+ *
+ * +0 INT size of this header (in bytes)
+ * +4 SHORT image width (in pixels)
+ * +6 SHORT image height (in pixels)
+ * +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);
+ if (width < 0)
+ return BMP_DATA_ERROR;
+ if (height < 0) {
+ bmp->reversed = true;
+ height = -height;
+ }
+ bmp->width = width;
+ bmp->height = height;
+ if (READ_SHORT(data, 8) != 1)
+ return BMP_DATA_ERROR;
+ bmp->bpp = READ_SHORT(data, 10);
+ bmp->colours = (1 << bmp->bpp);
+ palette_size = 3;
+ } else if (header_size < 40) {
+ return BMP_DATA_ERROR;
+ } else {
+ /* 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.
+ *
+ * +0 INT size of this header (in bytes)
+ * +4 INT image width (in pixels)
+ * +8 INT image height (in pixels)
+  * +12 SHORT number of color planes (always 1)
+ * +14 SHORT number of bits per pixel
+ * +16 INT compression methods used
+ * +20 INT size of bitmap (in bytes)
+ * +24 INT horizontal resolution (in pixels per meter)
+ * +28 INT vertical resolution (in pixels per meter)
+ * +32 INT number of colors in the image
+ * +36 INT number of important colors
+ * +40 INT mask identifying bits of red component
+ * +44 INT mask identifying bits of green component
+ * +48 INT mask identifying bits of blue component
+ * +52 INT mask identifying bits of alpha component
+ * +56 INT color space type
+ * +60 INT x coordinate of red endpoint
+ * +64 INT y coordinate of red endpoint
+ * +68 INT z coordinate of red endpoint
+ * +72 INT x coordinate of green endpoint
+ * +76 INT y coordinate of green endpoint
+ * +80 INT z coordinate of green endpoint
+ * +84 INT x coordinate of blue endpoint
+ * +88 INT y coordinate of blue endpoint
+ * +92 INT z coordinate of blue endpoint
+ * +96 INT gamma red coordinate scale value
+ * +100 INT gamma green coordinate scale value
+ * +104 INT gamma blue coordinate scale value
+ */
+ width = READ_INT(data, 4);
+ height = READ_INT(data, 8);
+ if (width < 0)
+ return BMP_DATA_ERROR;
+ if (height < 0) {
+ bmp->reversed = true;
+ height = -height;
+ }
+ bmp->width = width;
+ bmp->height = height;
+ if (READ_SHORT(data, 12) != 1)
+ return BMP_DATA_ERROR;
+ bmp->bpp = READ_SHORT(data, 14);
+ bmp->encoding = READ_INT(data, 16);
+ if (bmp->encoding >= BMP_ENCODING_BITFIELDS) /* unsupported so far */
+ return BMP_DATA_ERROR;
+ bmp->colours = READ_INT(data, 32);
+ if (bmp->colours == 0)
+ bmp->colours = (1 << bmp->bpp);
+ palette_size = 4;
+ /* we don't understand the rest of the data yet */
+ }
+ data += header_size;
+
+ /* we only have a palette for <16bpp */
+ if (bmp->bpp < 16) {
+ /* we now have a series of palette entries of the format:
+ *
+ * +0 BYTE blue
+ * +1 BYTE green
+ * +2 BYTE red
+ *
+ * if the palette is from an OS/2 or Win2.x file then the entries
+ * are padded with an extra byte.
+ */
+ if (bmp->buffer_size < (14 + header_size + (4 * bmp->colours)))
+ return BMP_INSUFFICIENT_DATA;
+ 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) | (0xff << 24));
+ data += palette_size;
+ }
+ }
+
+ /* create our bitmap */
+ bmp->bitmap = bitmap_create(bmp->width, bmp->height,
+ BITMAP_NEW | BITMAP_OPAQUE | BITMAP_CLEAR_MEMORY);
+ if (!bmp->bitmap) {
+ if (bmp->colour_table)
+ free(bmp->colour_table);
+ bmp->colour_table = NULL;
+ return BMP_INSUFFICIENT_MEMORY;
+ }
+ return BMP_OK;
+}
+
+
+/**
+ * Decode a BMP
+ *
+ * This function decodes the BMP data such that bmp->bitmap is a valid
+ * image. The state of bmp->decoded is set to TRUE on exit such that it
+ * can easily be identified which BMPs are in a fully decoded state.
+ *
+ * \param bmp the BMP image to decode
+ * \return BMP_OK on success
+ */
+bmp_result bmp_decode(struct bmp_image *bmp) {
+ char *data;
+ int bytes;
+
+ assert(bmp->bitmap);
+
+ data = bmp->bmp_data + bmp->bitmap_offset;
+ bytes = bmp->buffer_size - bmp->bitmap_offset;
+
+ switch (bmp->encoding) {
+ case BMP_ENCODING_RGB:
+ if (bmp->bpp >= 24)
+ return bmp_decode_rgb24(bmp, data, bytes);
+ else if (bmp->bpp > 8)
+ return BMP_DATA_ERROR;
+ else
+ return bmp_decode_rgb(bmp, data, bytes);
+ case BMP_ENCODING_RLE8:
+ return bmp_decode_rle(bmp, data, bytes, 8);
+ case BMP_ENCODING_RLE4:
+ return bmp_decode_rle(bmp, data, bytes, 4);
+ case BMP_ENCODING_BITFIELDS:
+ /* todo: implement me */
+ break;
+ }
+ return BMP_DATA_ERROR;
+}
+
+
+/**
+ * Decode BMP data stored in 24bpp colour.
+ *
+ * \param bmp the BMP image to decode
+ * \param data the data to decode
+ * \param bytes the number of bytes of data available
+ * \return BMP_OK on success
+ */
+bmp_result bmp_decode_rgb24(struct bmp_image *bmp, char *data, int bytes) {
+ char *top, *bottom, *end;
+ unsigned int *scanline;
+ unsigned int x, y, swidth, skip;
+ unsigned int addr;
+
+ 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;
+ skip = bmp->bpp >> 3;
+ bmp->decoded = true;
+
+ for (y = 0; y < bmp->height; y++) {
+ while (addr != (((unsigned int)data) & 3))
+ data++;
+ if ((data + (skip * bmp->width)) > end)
+ return BMP_INSUFFICIENT_DATA;
+ if (bmp->reversed)
+ scanline = (unsigned int *)(top + (y * swidth));
+ else
+ scanline = (unsigned int *)(bottom - (y * swidth));
+ for (x = 0; x < bmp->width; x++) {
+ scanline[x] = data[2] | (data[1] << 8) | (data[0] << 16);
+ data += skip;
+ }
+ }
+ return BMP_OK;
+}
+
+
+/**
+ * Decode BMP data stored with a palette and in 8bpp colour or less.
+ *
+ * \param bmp the BMP image to decode
+ * \param data the data to decode
+ * \param bytes the number of bytes of data available
+ * \return BMP_OK on success
+ */
+bmp_result bmp_decode_rgb(struct bmp_image *bmp, char *data, int bytes) {
+ char *top, *bottom, *end;
+ unsigned int *scanline;
+ unsigned int addr;
+ unsigned int x, y, swidth;
+ int i;
+ int bit_shifts[8];
+ int ppb = 8 / bmp->bpp;
+ int bit_mask = (1 << bmp->bpp) - 1;
+ int cur_byte = 0, bit;
+
+ for (i = 0; i < ppb; i++)
+ bit_shifts[i] = 8 - ((i + 1) * bmp->bpp);
+
+ 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++) {
+ while (addr != (((unsigned int)data) & 3))
+ data++;
+ bit = 32;
+ if ((data + (bmp->width / ppb)) > end)
+ return BMP_INSUFFICIENT_DATA;
+ if (bmp->reversed)
+ scanline = (unsigned int *)(top + (y * swidth));
+ else
+ scanline = (unsigned int *)(bottom - (y * swidth));
+ for (x = 0; x < bmp->width; x++) {
+ if (bit >= ppb) {
+ bit = 0;
+ cur_byte = *data++;
+ }
+ scanline[x] = bmp->colour_table[(cur_byte >>
+ bit_shifts[bit++]) & bit_mask];
+ }
+ }
+ return BMP_OK;
+}
+
+
+/**
+ * Decode BMP data stored encoded in either RLE4 or RLE8.
+ *
+ * \param bmp the BMP image to decode
+ * \param data the data to decode
+ * \param bytes the number of bytes of data available
+ * \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) {
+ char *top, *bottom, *end;
+ unsigned int *scanline;
+ unsigned int swidth;
+ int i, length, pixels_left;
+ unsigned int x = 0, y = 0, last_y = 0;
+ unsigned int pixel = 0, pixel2;
+
+ swidth = bitmap_get_rowstride(bmp->bitmap);
+ top = bitmap_get_buffer(bmp->bitmap);
+ bottom = top + swidth * (bmp->height - 1);
+ end = data + bytes;
+ bmp->decoded = true;
+
+ do {
+ if (data + 2 > end)
+ return BMP_INSUFFICIENT_DATA;
+ length = *data++;
+ if (length == 0) {
+ length = *data++;
+ if (length == 0) {
+ /* 00 - 00 means end of scanline */
+ x = 0;
+ if (last_y == y) {
+ if (++y > bmp->height)
+ return BMP_DATA_ERROR;
+ }
+ last_y = y;
+ } else if (length == 1) {
+ /* 00 - 01 means end of RLE data */
+ return BMP_OK;
+ } else if (length == 2) {
+ /* 00 - 02 - XX - YY means move cursor */
+ if (data + 2 > end)
+ return BMP_INSUFFICIENT_DATA;
+ x += *data++;
+ if (x >= bmp->width)
+ return BMP_DATA_ERROR;
+ y += *data++;
+ if (y >= bmp->height)
+ return BMP_DATA_ERROR;
+ } else {
+ /* 00 - NN means escape pixels */
+ if (bmp->reversed) {
+ pixels_left = (y + 1) * bmp->width - x;
+ scanline = (unsigned int *)(top + (y * swidth));
+ } else {
+ pixels_left = (bmp->height - y + 1) * bmp->width - x;
+ scanline = (unsigned int *)(bottom - (y * swidth));
+ }
+ if (length > pixels_left)
+ length = pixels_left;
+ if (data + length > end)
+ return BMP_INSUFFICIENT_DATA;
+
+ /* the following code could be easily optimised by simply
+ * checking the bounds on entry and using some simply copying
+ * routines if so */
+ if (size == 8) {
+ for (i = 0; i < length; i++) {
+ if (x >= bmp->width) {
+ x = 0;
+ if (++y > bmp->height)
+ return BMP_DATA_ERROR;
+ scanline -= bmp->width;
+ }
+ scanline[x++] = bmp->colour_table[(int)*data++];
+ }
+ } else {
+ for (i = 0; i < length; i++) {
+ if (x >= bmp->width) {
+ x = 0;
+ if (++y > bmp->height)
+ return BMP_DATA_ERROR;
+ scanline -= bmp->width;
+ }
+ if ((i & 1) == 0) {
+ pixel = *data++;
+ scanline[x++] = bmp->colour_table
+ [pixel >> 4];
+ } else {
+ scanline[x++] = bmp->colour_table
+ [pixel & 0xf];
+ }
+ }
+ length = (length + 1) >> 1;
+ }
+ if ((length & 1) && (*data++ != 0x00))
+ return BMP_DATA_ERROR;
+
+ }
+ } else {
+ /* NN means perform RLE for NN pixels */
+ if (bmp->reversed) {
+ pixels_left = (y + 1) * bmp->width - x;
+ scanline = (unsigned int *)(top + (y * swidth));
+ } else {
+ pixels_left = (bmp->height - y + 1) * bmp->width - x;
+ scanline = (unsigned int *)(bottom - (y * swidth));
+ }
+ if (length > pixels_left)
+ length = pixels_left;
+
+ /* the following code could be easily optimised by simply
+ * checking the bounds on entry and using some simply copying
+ * routines if so */
+ if (size == 8) {
+ pixel = bmp->colour_table[(int)*data++];
+ for (i = 0; i < length; i++) {
+ if (x >= bmp->width) {
+ x = 0;
+ if (++y > bmp->height)
+ return BMP_DATA_ERROR;
+ scanline -= bmp->width;
+ }
+ scanline[x++] = pixel;
+ }
+ } else {
+ pixel2 = *data++;
+ pixel = bmp->colour_table[pixel2 >> 4];
+ pixel2 = bmp->colour_table[pixel2 & 0xf];
+ for (i = 0; i < length; i++) {
+ if (x >= bmp->width) {
+ x = 0;
+ if (++y > bmp->height)
+ return BMP_DATA_ERROR;
+ scanline -= bmp->width;
+ }
+ if ((i & 1) == 0)
+ scanline[x++] = pixel;
+ else
+ scanline[x++] = pixel2;
+ }
+ }
+ }
+ } while (data < end);
+ return BMP_OK;
+}
+
+
+/**
+ * Finalise a BMP prior to destruction.
+ *
+ * \param bmp the BMP image to finalise
+ */
+void bmp_finalise(struct bmp_image *bmp) {
+ if (bmp->bitmap)
+ bitmap_destroy(bmp->bitmap);
+ bmp->bitmap = NULL;
+ if (bmp->colour_table)
+ free(bmp->colour_table);
+ bmp->colour_table = NULL;
+}
diff --git a/image/bmpread.h b/image/bmpread.h
new file mode 100644
index 000000000..45468a9ed
--- /dev/null
+++ b/image/bmpread.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of NetSurf, http://netsurf.sourceforge.net/
+ * Licensed under the GNU General Public License,
+ * http://www.opensource.org/licenses/gpl-license
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ */
+
+/** \file
+ * BMP file decoding (interface).
+ */
+
+#ifndef _NETSURF_IMAGE_BMPREAD_H_
+#define _NETSURF_IMAGE_BMPREAD_H_
+
+#include <stdbool.h>
+#include "netsurf/image/bitmap.h"
+
+/* error return values */
+typedef enum {
+ BMP_OK = 0,
+ BMP_INSUFFICIENT_MEMORY = 1,
+ BMP_INSUFFICIENT_DATA = 2,
+ BMP_DATA_ERROR = 3
+} bmp_result;
+
+/* encoding types */
+typedef enum {
+ BMP_ENCODING_RGB = 0,
+ BMP_ENCODING_RLE8 = 1,
+ BMP_ENCODING_RLE4 = 2,
+ BMP_ENCODING_BITFIELDS = 3
+} bmp_encoding;
+
+
+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) */
+ unsigned int height; /** heigth of BMP (valid after _analyse) */
+ bmp_encoding encoding; /** pixel encoding type */
+ unsigned int bitmap_offset; /** offset of bitmap data */
+ unsigned int bpp; /** bits per pixel */
+ unsigned int colours; /** number of colours */
+ unsigned int *colour_table; /** colour table */
+ bool reversed; /** scanlines are top to bottom */
+ bool decoded; /** whether the image has been decoded */
+ struct bitmap *bitmap; /** decoded image */
+};
+
+bmp_result bmp_analyse(struct bmp_image *bmp);
+bmp_result bmp_decode(struct bmp_image *bmp);
+void bmp_finalise(struct bmp_image *bmp);
+
+#endif