[project @ 2006-02-25 18:50:34 by rjw]

Support for BMP files

svn path=/import/netsurf/; revision=2095
This commit is contained in:
Richard Wilson 2006-02-25 18:51:51 +00:00
parent 44d192c762
commit da4a9313f1
18 changed files with 776 additions and 7 deletions

View File

@ -325,6 +325,7 @@ SelectMenu:Select
#
DrawTitle:Draw Bild (%lux%lu, %lu bytes)
GIFTitle:GIF Bild (%lux%lu, %lu bytes)
BMPTitle:BMP Bild (%lux%lu, %lu bytes)
JPEGTitle:JPEG Bild (%ux%u, %lu bytes)
PNGTitle:PNG Bild (%lux%lu, %lu bytes)
JNGTitle:JNG Bild (%lux%lu, %lu bytes)
@ -436,6 +437,7 @@ BadObject:Warning: bad object type
ObjError:Error loading object: %s
ParsingFail:Parsing the document failed.
BadGIF:Reading GIF failed.
BadBMP:Reading BMP failed.
PNGError:PNG library error.
MNGError:MNG library error.
BadSprite:Invalid or corrupt Sprite data.

View File

@ -325,6 +325,7 @@ SelectMenu:Select
#
DrawTitle:Draw image (%lux%lu, %lu bytes)
GIFTitle:GIF image (%lux%lu, %lu bytes)
BMPTitle:BMP image (%lux%lu, %lu bytes)
JPEGTitle:JPEG image (%ux%u, %lu bytes)
PNGTitle:PNG image (%lux%lu, %lu bytes)
JNGTitle:JNG image (%lux%lu, %lu bytes)
@ -435,6 +436,7 @@ BadObject:Warning: bad object type
ObjError:Error loading object: %s
ParsingFail:Parsing the document failed.
BadGIF:Reading GIF failed.
BadBMP:Reading BMP failed.
PNGError:PNG library error.
MNGError:MNG library error.
BadSprite:Invalid or corrupt Sprite data.

View File

@ -325,6 +325,7 @@ SelectMenu:Sélection
#
DrawTitle:Image Draw (%lux%lu, %lu octets)
GIFTitle:Image GIF (%lux%lu, %lu octets)
BMPTitle:Image BMP (%lux%lu, %lu octets)
JPEGTitle:Image JPEG (%ux%u, %lu octets)
PNGTitle:Image PNG (%lux%lu, %lu octets)
JNGTitle:Image JNG (%lux%lu, %lu octets)
@ -436,6 +437,7 @@ BadObject:Attention: mauvais type d'objet
ObjError:Erreur lors du chargement de: %s
ParsingFail:L'analyse syntaxique du document a échoué.
BadGIF:Erreur de lecture de GIF.
BadBMP:Erreur de lecture de BMP.
PNGError:Erreur dans la bibliothèque PNG.
MNGError:Erreur dans la bibliothèque MNG.
BadSprite:Les données du sprite sont invalides ou corrompues.

View File

@ -326,6 +326,7 @@ SelectMenu:Select
#
DrawTitle:Draw image (%lux%lu, %lu bytes)
GIFTitle:GIF image (%lux%lu, %lu bytes)
BMPTitle:BMP image (%lux%lu, %lu bytes)
JPEGTitle:JPEG image (%ux%u, %lu bytes)
PNGTitle:PNG image (%lux%lu, %lu bytes)
JNGTitle:JNG image (%lux%lu, %lu bytes)
@ -438,6 +439,7 @@ BadObject:melding: fout object type
ObjError:fout bij laden object: %s
ParsingFail:fout bij ontleden van dit document.
BadGIF:fout bij lezen GIF.
BadBMP:fout bij lezen BMP.
PNGError:PNG library fout.
MNGError:MNG library fout.
BadSprite:foutief sprite bestand.

View File

@ -36,6 +36,9 @@
#ifdef WITH_GIF
#include "netsurf/image/gif.h"
#endif
#ifdef WITH_BMP
#include "netsurf/image/bmp.h"
#endif
#ifdef WITH_SPRITE
#include "netsurf/riscos/sprite.h"
#endif
@ -68,17 +71,32 @@ static const struct mime_entry mime_map[] = {
#ifdef WITH_ARTWORKS
{"application/artworks", CONTENT_ARTWORKS},
#endif
#ifdef WITH_BMP
{"application/bmp", CONTENT_BMP},
#endif
#ifdef WITH_DRAW
{"application/drawfile", CONTENT_DRAW},
#endif
#ifdef WITH_BMP
{"application/preview", CONTENT_BMP},
{"application/x-bmp", CONTENT_BMP},
#endif
#ifdef WITH_DRAW
{"application/x-drawfile", CONTENT_DRAW},
#endif
#ifdef WITH_THEME_INSTALL
{"application/x-netsurf-theme", CONTENT_THEME},
#endif
#ifdef WITH_BMP
{"application/x-win-bitmap", CONTENT_BMP},
#endif
{"application/xhtml+xml", CONTENT_HTML},
#ifdef WITH_ARTWORKS
{"image/artworks", CONTENT_ARTWORKS},
#endif
#ifdef WITH_BMP
{"image/bmp", CONTENT_BMP},
#endif
#ifdef WITH_DRAW
{"image/drawfile", CONTENT_DRAW},
#endif
@ -94,12 +112,19 @@ static const struct mime_entry mime_map[] = {
#ifdef WITH_MNG
{"image/mng", CONTENT_MNG},
#endif
#ifdef WITH_BMP
{"image/ms-bmp", CONTENT_BMP},
#endif
#ifdef WITH_JPEG
{"image/pjpeg", CONTENT_JPEG},
#endif
#ifdef WITH_MNG
{"image/png", CONTENT_PNG},
#endif
#ifdef WITH_BMP
{"image/x-bitmap", CONTENT_BMP},
{"image/x-bmp", CONTENT_BMP},
#endif
#ifdef WITH_DRAW
{"image/x-drawfile", CONTENT_DRAW},
#endif
@ -107,8 +132,16 @@ static const struct mime_entry mime_map[] = {
{"image/x-jng", CONTENT_JNG},
{"image/x-mng", CONTENT_MNG},
#endif
#ifdef WITH_BMP
{"image/x-ms-bmp", CONTENT_BMP},
#endif
#ifdef WITH_SPRITE
{"image/x-riscos-sprite", CONTENT_SPRITE},
#endif
#ifdef WITH_BMP
{"image/x-win-bitmap", CONTENT_BMP},
{"image/x-windows-bmp", CONTENT_BMP},
{"image/x-xbitmap", CONTENT_BMP},
#endif
{"text/css", CONTENT_CSS},
{"text/html", CONTENT_HTML},
@ -130,6 +163,9 @@ const char *content_type_name[] = {
#ifdef WITH_GIF
"GIF",
#endif
#ifdef WITH_BMP
"BMP",
#endif
#ifdef WITH_MNG
"PNG",
"JNG",
@ -206,6 +242,10 @@ static const struct handler_entry handler_map[] = {
{nsgif_create, 0, nsgif_convert, 0, nsgif_destroy, 0,
nsgif_redraw, nsgif_redraw_tiled, 0, 0, false},
#endif
#ifdef WITH_BMP
{nsbmp_create, 0, nsbmp_convert, 0, nsbmp_destroy, 0,
nsbmp_redraw, nsbmp_redraw_tiled, 0, 0, false},
#endif
#ifdef WITH_MNG
{nsmng_create, nsmng_process_data, nsmng_convert,
0, nsmng_destroy, 0, nsmng_redraw, nsmng_redraw_tiled,

View File

@ -115,6 +115,9 @@
#ifdef WITH_GIF
#include "netsurf/image/gif.h"
#endif
#ifdef WITH_BMP
#include "netsurf/image/bmp.h"
#endif
#ifdef WITH_PLUGIN
#include "netsurf/riscos/plugin.h"
#endif
@ -230,6 +233,9 @@ struct content {
#ifdef WITH_GIF
struct content_gif_data gif;
#endif
#ifdef WITH_BMP
struct content_bmp_data bmp;
#endif
#ifdef WITH_MNG
struct content_mng_data mng;
#endif

View File

@ -28,6 +28,9 @@ typedef enum {
#ifdef WITH_GIF
CONTENT_GIF,
#endif
#ifdef WITH_BMP
CONTENT_BMP,
#endif
#ifdef WITH_MNG
CONTENT_PNG,
CONTENT_JNG,

127
image/bmp.c Normal file
View File

@ -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

33
image/bmp.h Normal file
View File

@ -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

483
image/bmpread.c Normal file
View File

@ -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;
}

54
image/bmpread.h Normal file
View File

@ -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

View File

@ -27,7 +27,7 @@ OBJECTS_COMMON += messages.o talloc.o url.o utf8.o \
utils.o # utils/
OBJECTS_COMMON += options.o tree.o # desktop/
OBJECTS_IMAGE = gif.o gifread.o jpeg.o mng.o # image/
OBJECTS_IMAGE = bmp.o bmpread.o gif.o gifread.o jpeg.o mng.o # image/
OBJECTS_RISCOS = $(OBJECTS_COMMON) $(OBJECTS_IMAGE)
OBJECTS_RISCOS += browser.o netsurf.o selection.o textinput.o \

View File

@ -51,10 +51,11 @@ static const content_type image_types[] = {
#ifdef WITH_GIF
CONTENT_GIF,
#endif
#ifdef WITH_PNG
CONTENT_PNG,
#ifdef WITH_BMP
CONTENT_BMP,
#endif
#ifdef WITH_MNG
CONTENT_PNG,
CONTENT_JNG,
CONTENT_MNG,
#endif

View File

@ -237,16 +237,17 @@ int ro_content_filetype_from_type(content_type type) {
#ifdef WITH_MNG
case CONTENT_JNG: return 0xf78;
case CONTENT_MNG: return 0xf84;
case CONTENT_PNG: return 0xb60;
#endif
#ifdef WITH_JPEG
case CONTENT_JPEG: return 0xc85;
#endif
#ifdef WITH_PNG
case CONTENT_PNG: return 0xb60;
#endif
#ifdef WITH_GIF
case CONTENT_GIF: return 0x695;
#endif
#ifdef WITH_BMP
case CONTENT_BMP: return 0x69c;
#endif
#ifdef WITH_SPRITE
case CONTENT_SPRITE: return 0xff9;
#endif

View File

@ -109,6 +109,9 @@
#ifndef FILETYPE_GIF
#define FILETYPE_GIF 0x695
#endif
#ifndef FILETYPE_BMP
#define FILETYPE_BMP 0x69c
#endif
#ifndef FILETYPE_PNG
#define FILETYPE_PNG 0xb60
#endif
@ -1492,6 +1495,7 @@ void ro_msg_dataload(wimp_message *message)
case FILETYPE_CSS:
case FILETYPE_MNG:
case FILETYPE_GIF:
case FILETYPE_BMP:
case osfile_TYPE_DRAW:
case FILETYPE_PNG:
case FILETYPE_JPEG:
@ -1779,6 +1783,7 @@ void ro_msg_datasave(wimp_message *message)
case FILETYPE_CSS:
case FILETYPE_MNG:
case FILETYPE_GIF:
case FILETYPE_BMP:
case osfile_TYPE_DRAW:
case FILETYPE_PNG:
case FILETYPE_JPEG:

View File

@ -812,6 +812,11 @@ void ro_gui_save_object_native(struct content *c, char *path)
case CONTENT_GIF:
bitmap_save(c->bitmap, path);
break;
#endif
#ifdef WITH_BMP
case CONTENT_BMP:
bitmap_save(c->bitmap, path);
break;
#endif
default:
break;

View File

@ -496,6 +496,9 @@ void ro_gui_window_redraw(struct gui_window *g, wimp_draw *redraw)
#ifdef WITH_GIF
case CONTENT_GIF:
#endif
#ifdef WITH_BMP
case CONTENT_BMP:
#endif
#ifdef WITH_MNG
case CONTENT_JNG:
case CONTENT_MNG:

View File

@ -28,9 +28,9 @@
#endif
/* Image renderering modules */
#define WITH_BMP
#define WITH_JPEG
#define WITH_MNG
#define WITH_PNG
#define WITH_GIF
#if defined(riscos) || defined(ncos)
#define WITH_DRAW