diff options
Diffstat (limited to 'image/bmpread.c')
-rw-r--r-- | image/bmpread.c | 816 |
1 files changed, 0 insertions, 816 deletions
diff --git a/image/bmpread.c b/image/bmpread.c deleted file mode 100644 index bff31167b..000000000 --- a/image/bmpread.c +++ /dev/null @@ -1,816 +0,0 @@ -/* - * Copyright 2006 Richard Wilson <info@tinct.net> - * - * This file is part of NetSurf, http://www.netsurf-browser.org/ - * - * NetSurf is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * NetSurf is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <assert.h> -#include <stdbool.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <stdint.h> -#include "image/bmpread.h" -#include "image/bitmap.h" -#include "utils/log.h" -#include "utils/config.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_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_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_mask(struct bmp_image *bmp, char *data, int bytes); -bmp_result bmp_decode_rle(struct bmp_image *bmp, char *data, int bytes, int size); -void bmp_invalidate(struct bitmap *bitmap, void *private_word); - - -/** - * 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 = (char *) bmp->bmp_data; - - /* 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); - - /* decode the BMP header */ - return bmp_analyse_header(bmp, data + 14); -} - - -/** - * Analyse an ICO prior to decoding. - * - * This function will scan the data provided and perform simple checks to - * ensure the data is a valid ICO. - * - * This function must be called before ico_find(). - * - * \param ico the ICO image to analyse - * \return BMP_OK on success - */ -bmp_result ico_analyse(struct ico_collection *ico) { - char *data = (char *) ico->ico_data; - unsigned int count, i; - bmp_result result; - struct ico_image *image; - int area, max_area = 0; - - /* ensure we aren't already initialised */ - if (ico->first) - return BMP_OK; - - /* standard 6-byte ICO file header is: - * - * +0 INT 0x00010000 - * +4 SHORT number of BMPs to follow - */ - if (ico->buffer_size < 6) - return BMP_INSUFFICIENT_DATA; - if (READ_INT(data, 0) != 0x00010000) - return BMP_DATA_ERROR; - count = READ_SHORT(data, 4); - if (count == 0) - return BMP_DATA_ERROR; - data += 6; - - /* decode the BMP files */ - if (ico->buffer_size < 6 + (16 * count)) - return BMP_INSUFFICIENT_DATA; - for (i = 0; i < count; i++) { - image = calloc(1, sizeof(struct ico_image)); - if (!image) - return BMP_INSUFFICIENT_MEMORY; - image->next = ico->first; - 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.ico = true; - data += 16; - result = bmp_analyse_header(&image->bmp, - (char *) image->bmp.bmp_data); - if (result != BMP_OK) - return result; - area = image->bmp.width * image->bmp.height; - if (area > max_area) { - ico->width = image->bmp.width; - ico->height = image->bmp.height; - max_area = area; - } - } - return BMP_OK; -} - - -bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data) { - unsigned int header_size; - unsigned int i; - int width, height, j; - int palette_size; - unsigned int flags; - - /* a variety of different bitmap headers can 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 - */ - if (!bmp->ico) { - 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); - if (bmp->bpp == 0) - bmp->bpp = 8; - bmp->encoding = READ_INT(data, 16); - if (bmp->encoding > BMP_ENCODING_BITFIELDS) - 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); - if (bmp->colours == 0) - bmp->colours = (1 << bmp->bpp); - palette_size = 4; - } - 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); - data += palette_size; - } - } - - /* create our bitmap */ - flags = BITMAP_NEW | BITMAP_CLEAR_MEMORY; - if ((!bmp->ico) && (bmp->mask[3] == 0)) - flags |= BITMAP_OPAQUE; - bmp->bitmap = bitmap_create(bmp->width, bmp->height, flags); - if (!bmp->bitmap) { - if (bmp->colour_table) - free(bmp->colour_table); - bmp->colour_table = NULL; - return BMP_INSUFFICIENT_MEMORY; - } - bmp->bitmap_offset = (intptr_t)data - (intptr_t)bmp->bmp_data; - bitmap_set_suspendable(bmp->bitmap, bmp, bmp_invalidate); - return BMP_OK; -} - - -/* - * Finds the closest BMP within an ICO collection - * - * This function finds the BMP with dimensions as close to a specified set - * as possible from the images in the collection. - * - * \param ico the ICO collection to examine - * \param width the preferred width - * \param height the preferred height - */ -struct bmp_image *ico_find(struct ico_collection *ico, int width, int height) { - struct bmp_image *bmp = NULL; - struct ico_image *image; - int x, y, cur, distance = (1 << 24); - - for (image = ico->first; image; image = image->next) { - if (((int)image->bmp.width == width) && ((int)image->bmp.height == height)) - return &image->bmp; - x = image->bmp.width - width; - y = image->bmp.height - height; - cur = (x * x) + (y * y); - if (cur < distance) { - distance = cur; - bmp = &image->bmp; - } - } - return bmp; -} - - -/** - * Invalidates a BMP - * - * This function sets the BMP into a state such that the bitmap image data - * can be released from memory. - * - * \param bmp the BMP image to invalidate - */ -void bmp_invalidate(struct bitmap *bitmap, void *private_word) { - struct bmp_image *bmp = (struct bmp_image *)private_word; - - bmp->decoded = false; -} - - -/** - * 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; - bmp_result result = BMP_OK; - - assert(bmp->bitmap); - - data = (char *) bmp->bmp_data + bmp->bitmap_offset; - bytes = bmp->buffer_size - bmp->bitmap_offset; - - switch (bmp->encoding) { - case BMP_ENCODING_RGB: - if (bmp->bpp >= 24) - result = bmp_decode_rgb24(bmp, &data, bytes); - else if (bmp->bpp > 8) - result = bmp_decode_rgb16(bmp, &data, bytes); - else - result = bmp_decode_rgb(bmp, &data, bytes); - break; - case BMP_ENCODING_RLE8: - result = bmp_decode_rle(bmp, data, bytes, 8); - break; - case BMP_ENCODING_RLE4: - result = bmp_decode_rle(bmp, data, bytes, 4); - break; - case BMP_ENCODING_BITFIELDS: - 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)) - return result; - - bytes = (intptr_t)bmp->bmp_data + bmp->buffer_size - (intptr_t)data; - return bmp_decode_mask(bmp, data, bytes); -} - - -/** - * Decode BMP data stored in 24bpp 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_rgb24(struct bmp_image *bmp, char **start, int bytes) { - 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_get_rowstride(bmp->bitmap); - top = bitmap_get_buffer(bmp->bitmap); - if (!top) - return BMP_INSUFFICIENT_MEMORY; - bottom = top + swidth * (bmp->height - 1); - end = data + bytes; - addr = ((intptr_t)data) & 3; - skip = bmp->bpp >> 3; - bmp->decoded = true; - - for (y = 0; y < bmp->height; y++) { - while (addr != (((intptr_t)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)); - if (bmp->encoding == BMP_ENCODING_BITFIELDS) { - for (x = 0; x < bmp->width; x++) { - word = data[0] | (data[1] << 8) | (data[2] << 16) | - (data[3] << 24); - scanline[x] = (0xff << 24); - 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; - intptr_t addr; - unsigned int word, i; - - data = *start; - swidth = bitmap_get_rowstride(bmp->bitmap); - top = bitmap_get_buffer(bmp->bitmap); - if (!top) - return BMP_INSUFFICIENT_MEMORY; - bottom = top + swidth * (bmp->height - 1); - end = data + bytes; - addr = ((intptr_t)data) & 3; - bmp->decoded = true; - - for (y = 0; y < bmp->height; y++) { - if (addr != (((intptr_t)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] = (0xff << 24); - 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; - return BMP_OK; -} - - -/** - * Decode BMP data stored with a palette and in 8bpp colour or less. - * - * \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_rgb(struct bmp_image *bmp, char **start, int bytes) { - char *top, *bottom, *end, *data; - unsigned int *scanline; - intptr_t 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); - - data = *start; - swidth = bitmap_get_rowstride(bmp->bitmap); - top = bitmap_get_buffer(bmp->bitmap); - if (!top) - return BMP_INSUFFICIENT_MEMORY; - bottom = top + swidth * (bmp->height - 1); - end = data + bytes; - addr = ((intptr_t)data) & 3; - bmp->decoded = true; - - for (y = 0; y < bmp->height; y++) { - while (addr != (((intptr_t)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]; - } - } - *start = data; - return BMP_OK; -} - - -/** - * Decode a 1bpp mask for an ICO - * - * \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_mask(struct bmp_image *bmp, char *data, int bytes) { - char *top, *bottom, *end; - unsigned int *scanline; - intptr_t addr; - unsigned int x, y, swidth; - int cur_byte = 0; - - swidth = bitmap_get_rowstride(bmp->bitmap); - top = bitmap_get_buffer(bmp->bitmap); - if (!top) - return BMP_INSUFFICIENT_MEMORY; - bottom = top + swidth * (bmp->height - 1); - end = data + bytes; - addr = ((intptr_t)data) & 3; - - for (y = 0; y < bmp->height; y++) { - while (addr != (((intptr_t)data) & 3)) - data++; - if ((data + (bmp->width >> 3)) > end) - return BMP_INSUFFICIENT_DATA; - scanline = (unsigned int *)(bottom - (y * swidth)); - for (x = 0; x < bmp->width; x++) { - if ((x & 7) == 0) - cur_byte = *data++; - if ((cur_byte & 128) == 0) - scanline[x] |= (0xff << 24); - cur_byte = cur_byte << 1; - } - } - 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; - - if (bmp->ico) - return BMP_DATA_ERROR; - - swidth = bitmap_get_rowstride(bmp->bitmap); - top = bitmap_get_buffer(bmp->bitmap); - if (!top) - return BMP_INSUFFICIENT_MEMORY; - 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 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; - 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; -} - - -/** - * Finalise an ICO prior to destruction. - * - * \param ico the ICO image to finalise - */ -void ico_finalise(struct ico_collection *ico) { - struct ico_image *image; - - for (image = ico->first; image; image = image->next) - bmp_finalise(&image->bmp); - while (ico->first) { - image = ico->first; - ico->first = image->next; - free(image); - } -} |