1 /*
2 * Copyright 2006 Richard Wilson <richard.wilson@netsurf-browser.org>
3 * Copyright 2008 Sean Fox <dyntryx@gmail.com>
4 *
5 * This file is part of NetSurf's libnsbmp, http://www.netsurf-browser.org/
6 * Licenced under the MIT License,
7 * http://www.opensource.org/licenses/mit-license.php
8 */
9
10 /**
11 * \file
12 * BMP decoding implementation
13 *
14 * This library decode windows bitmaps and icons from their disc images.
15 *
16 * The image format is described in several documents:
17 * https://msdn.microsoft.com/en-us/library/dd183391(v=vs.85).aspx
18 * http://www.fileformat.info/format/bmp/egff.htm
19 * https://en.wikipedia.org/wiki/BMP_file_format
20 *
21 * Despite the format being clearly defined many bitmaps found on the web are
22 * not compliant and this implementation attempts to cope with as many issues
23 * as possible rather than simply failing.
24 */
25
26 #include "libnsbmp.h"
27
28 /* squashes unused variable compiler warnings */
29 #define UNUSED(x) ((x)=(x))
30
31 /* BMP entry sizes */
32 #define BMP_FILE_HEADER_SIZE 14
33 #define ICO_FILE_HEADER_SIZE 6
34 #define ICO_DIR_ENTRY_SIZE 16
35
36 /* the bitmap information header types (encoded as lengths) */
37 #define BITMAPCOREHEADER 12
38
39 #ifdef WE_NEED_INT8_READING_NOW
read_int8(uint8_t * data,unsigned int o)40 static inline int8_t read_int8(uint8_t *data, unsigned int o) {
41 return (int8_t) data[o];
42 }
43 #endif
44
read_uint8(uint8_t * data,unsigned int o)45 static inline uint8_t read_uint8(uint8_t *data, unsigned int o) {
46 return (uint8_t) data[o];
47 }
48
read_int16(uint8_t * data,unsigned int o)49 static inline int16_t read_int16(uint8_t *data, unsigned int o) {
50 return (int16_t) (data[o] | (data[o+1] << 8));
51 }
52
read_uint16(uint8_t * data,unsigned int o)53 static inline uint16_t read_uint16(uint8_t *data, unsigned int o) {
54 return (uint16_t) (data[o] | (data[o+1] << 8));
55 }
56
read_int32(uint8_t * data,unsigned int o)57 static inline int32_t read_int32(uint8_t *data, unsigned int o) {
58 return (int32_t) ((unsigned)data[o] |
59 ((unsigned)data[o+1] << 8) |
60 ((unsigned)data[o+2] << 16) |
61 ((unsigned)data[o+3] << 24));
62 }
63
read_uint32(uint8_t * data,unsigned int o)64 static inline uint32_t read_uint32(uint8_t *data, unsigned int o) {
65 return (uint32_t) ((unsigned)data[o] |
66 ((unsigned)data[o+1] << 8) |
67 ((unsigned)data[o+2] << 16) |
68 ((unsigned)data[o+3] << 24));
69 }
70
71
72 /**
73 * Parse the bitmap info header
74 */
bmp_info_header_parse(bmp_image * bmp,uint8_t * data)75 static bmp_result bmp_info_header_parse(bmp_image *bmp, uint8_t *data)
76 {
77 uint32_t header_size;
78 uint32_t i;
79 uint8_t j;
80 int32_t width, height;
81 uint8_t palette_size;
82 unsigned int flags = 0;
83
84 /* must be at least enough data for a core header */
85 if (bmp->buffer_size < (BMP_FILE_HEADER_SIZE + BITMAPCOREHEADER)) {
86 return BMP_INSUFFICIENT_DATA;
87 }
88
89 header_size = read_uint32(data, 0);
90
91 /* ensure there is enough data for the declared header size*/
92 if ((bmp->buffer_size - BMP_FILE_HEADER_SIZE) < header_size) {
93 return BMP_INSUFFICIENT_DATA;
94 }
95
96 /* a variety of different bitmap headers can follow, depending
97 * on the BMP variant. The header length field determines the type.
98 */
99 if (header_size == BITMAPCOREHEADER) {
100 /* the following header is for os/2 and windows 2.x and consists of:
101 *
102 * +0 UINT32 size of this header (in bytes)
103 * +4 INT16 image width (in pixels)
104 * +6 INT16 image height (in pixels)
105 * +8 UINT16 number of colour planes (always 1)
106 * +10 UINT16 number of bits per pixel
107 */
108 width = read_int16(data, 4);
109 height = read_int16(data, 6);
110 if ((width <= 0) || (height == 0))
111 return BMP_DATA_ERROR;
112 if (height < 0) {
113 bmp->reversed = true;
114 height = -height;
115 }
116 /* ICOs only support 256*256 resolutions
117 * In the case of the ICO header, the height is actually the added
118 * height of XOR-Bitmap and AND-Bitmap (double the visible height)
119 * Technically we could remove this check and ICOs with bitmaps
120 * of any size could be processed; this is to conform to the spec.
121 */
122 if (bmp->ico) {
123 if ((width > 256) || (height > 512)) {
124 return BMP_DATA_ERROR;
125 } else {
126 bmp->width = width;
127 bmp->height = height / 2;
128 }
129 } else {
130 bmp->width = width;
131 bmp->height = height;
132 }
133 if (read_uint16(data, 8) != 1)
134 return BMP_DATA_ERROR;
135 bmp->bpp = read_uint16(data, 10);
136 /**
137 * The bpp value should be in the range 1-32, but the only
138 * values considered legal are:
139 * RGB ENCODING: 1, 4, 8, 16, 24 and 32
140 */
141 if ((bmp->bpp != 1) && (bmp->bpp != 4) &&
142 (bmp->bpp != 8) &&
143 (bmp->bpp != 16) &&
144 (bmp->bpp != 24) &&
145 (bmp->bpp != 32))
146 return BMP_DATA_ERROR;
147 if (bmp->bpp < 16)
148 bmp->colours = (1 << bmp->bpp);
149 palette_size = 3;
150 } else if (header_size < 40) {
151 return BMP_DATA_ERROR;
152 } else {
153 /* the following header is for windows 3.x and onwards. it is a
154 * minimum of 40 bytes and (as of Windows 95) a maximum of 108 bytes.
155 *
156 * +0 UINT32 size of this header (in bytes)
157 * +4 INT32 image width (in pixels)
158 * +8 INT32 image height (in pixels)
159 * +12 UINT16 number of colour planes (always 1)
160 * +14 UINT16 number of bits per pixel
161 * +16 UINT32 compression methods used
162 * +20 UINT32 size of bitmap (in bytes)
163 * +24 UINT32 horizontal resolution (in pixels per meter)
164 * +28 UINT32 vertical resolution (in pixels per meter)
165 * +32 UINT32 number of colours in the image
166 * +36 UINT32 number of important colours
167 * +40 UINT32 mask identifying bits of red component
168 * +44 UINT32 mask identifying bits of green component
169 * +48 UINT32 mask identifying bits of blue component
170 * +52 UINT32 mask identifying bits of alpha component
171 * +56 UINT32 color space type
172 * +60 UINT32 x coordinate of red endpoint
173 * +64 UINT32 y coordinate of red endpoint
174 * +68 UINT32 z coordinate of red endpoint
175 * +72 UINT32 x coordinate of green endpoint
176 * +76 UINT32 y coordinate of green endpoint
177 * +80 UINT32 z coordinate of green endpoint
178 * +84 UINT32 x coordinate of blue endpoint
179 * +88 UINT32 y coordinate of blue endpoint
180 * +92 UINT32 z coordinate of blue endpoint
181 * +96 UINT32 gamma red coordinate scale value
182 * +100 UINT32 gamma green coordinate scale value
183 * +104 UINT32 gamma blue coordinate scale value
184 */
185 width = read_int32(data, 4);
186 height = read_int32(data, 8);
187 if ((width <= 0) || (height == 0))
188 return BMP_DATA_ERROR;
189 if (height < 0) {
190 bmp->reversed = true;
191 if (height <= -INT32_MAX) {
192 height = INT32_MAX;
193 } else {
194 height = -height;
195 }
196 }
197 /* ICOs only support 256*256 resolutions
198 * In the case of the ICO header, the height is actually the added
199 * height of XOR-Bitmap and AND-Bitmap (double the visible height)
200 * Technically we could remove this check and ICOs with bitmaps
201 * of any size could be processed; this is to conform to the spec.
202 */
203 if (bmp->ico) {
204 if ((width > 256) || (height > 512)) {
205 return BMP_DATA_ERROR;
206 } else {
207 bmp->width = width;
208 bmp->height = height / 2;
209 }
210 } else {
211 bmp->width = width;
212 bmp->height = height;
213 }
214 if (read_uint16(data, 12) != 1)
215 return BMP_DATA_ERROR;
216 bmp->bpp = read_uint16(data, 14);
217 if (bmp->bpp == 0)
218 bmp->bpp = 8;
219 bmp->encoding = read_uint32(data, 16);
220 /**
221 * The bpp value should be in the range 1-32, but the only
222 * values considered legal are:
223 * RGB ENCODING: 1, 4, 8, 16, 24 and 32
224 * RLE4 ENCODING: 4
225 * RLE8 ENCODING: 8
226 * BITFIELD ENCODING: 16 and 32
227 */
228 switch (bmp->encoding) {
229 case BMP_ENCODING_RGB:
230 if ((bmp->bpp != 1) && (bmp->bpp != 4) &&
231 (bmp->bpp != 8) &&
232 (bmp->bpp != 16) &&
233 (bmp->bpp != 24) &&
234 (bmp->bpp != 32))
235 return BMP_DATA_ERROR;
236 break;
237 case BMP_ENCODING_RLE8:
238 if (bmp->bpp != 8)
239 return BMP_DATA_ERROR;
240 break;
241 case BMP_ENCODING_RLE4:
242 if (bmp->bpp != 4)
243 return BMP_DATA_ERROR;
244 break;
245 case BMP_ENCODING_BITFIELDS:
246 if ((bmp->bpp != 16) && (bmp->bpp != 32))
247 return BMP_DATA_ERROR;
248 break;
249 /* invalid encoding */
250 default:
251 return BMP_DATA_ERROR;
252 break;
253 }
254 /* Bitfield encoding means we have red, green, blue, and alpha masks.
255 * Here we acquire the masks and determine the required bit shift to
256 * align them in our 24-bit color 8-bit alpha format.
257 */
258 if (bmp->encoding == BMP_ENCODING_BITFIELDS) {
259 if (header_size == 40) {
260 header_size += 12;
261 if (bmp->buffer_size < (14 + header_size))
262 return BMP_INSUFFICIENT_DATA;
263 for (i = 0; i < 3; i++)
264 bmp->mask[i] = read_uint32(data, 40 + (i << 2));
265 } else {
266 if (header_size < 56)
267 return BMP_INSUFFICIENT_DATA;
268 for (i = 0; i < 4; i++)
269 bmp->mask[i] = read_uint32(data, 40 + (i << 2));
270 }
271 for (i = 0; i < 4; i++) {
272 if (bmp->mask[i] == 0)
273 break;
274 for (j = 31; j > 0; j--)
275 if (bmp->mask[i] & ((unsigned)1 << j)) {
276 if ((j - 7) > 0)
277 bmp->mask[i] &= (unsigned)0xff << (j - 7);
278 else
279 bmp->mask[i] &= 0xff >> (-(j - 7));
280 bmp->shift[i] = (i << 3) - (j - 7);
281 break;
282 }
283 }
284 }
285 bmp->colours = read_uint32(data, 32);
286 if (bmp->colours == 0 && bmp->bpp < 16)
287 bmp->colours = (1 << bmp->bpp);
288 palette_size = 4;
289 }
290 data += header_size;
291
292 /* if there's no alpha mask, flag the bmp opaque */
293 if ((!bmp->ico) && (bmp->mask[3] == 0)) {
294 flags |= BMP_OPAQUE;
295 bmp->opaque = true;
296 }
297
298 /* we only have a palette for <16bpp */
299 if (bmp->bpp < 16) {
300 /* we now have a series of palette entries of the format:
301 *
302 * +0 BYTE blue
303 * +1 BYTE green
304 * +2 BYTE red
305 *
306 * if the palette is from an OS/2 or Win2.x file then the entries
307 * are padded with an extra byte.
308 */
309
310 /* boundary checking */
311 if (bmp->buffer_size < (14 + header_size + ((uint64_t)4 * bmp->colours)))
312 return BMP_INSUFFICIENT_DATA;
313
314 /* create the colour table */
315 bmp->colour_table = (uint32_t *)malloc(bmp->colours * 4);
316 if (!bmp->colour_table)
317 return BMP_INSUFFICIENT_MEMORY;
318 for (i = 0; i < bmp->colours; i++) {
319 uint32_t colour = data[2] | (data[1] << 8) | (data[0] << 16);
320 if (bmp->opaque)
321 colour |= ((uint32_t)0xff << 24);
322 data += palette_size;
323 bmp->colour_table[i] = read_uint32((uint8_t *)&colour,0);
324 }
325
326 /* some bitmaps have a bad offset if there is a pallete, work
327 * round this by fixing up the data offset to after the palette
328 * but only if there is data following the palette as some
329 * bitmaps encode data in the palette!
330 */
331 if ((bmp->bitmap_offset < (uint32_t)(data - bmp->bmp_data)) &&
332 ((bmp->buffer_size - (data - bmp->bmp_data)) > 0)) {
333 bmp->bitmap_offset = data - bmp->bmp_data;
334 }
335 }
336
337 /* create our bitmap */
338 flags |= BMP_NEW | BMP_CLEAR_MEMORY;
339 bmp->bitmap = bmp->bitmap_callbacks.bitmap_create(bmp->width, bmp->height, flags);
340 if (!bmp->bitmap) {
341 if (bmp->colour_table)
342 free(bmp->colour_table);
343 bmp->colour_table = NULL;
344 return BMP_INSUFFICIENT_MEMORY;
345 }
346 /* BMPs within ICOs don't have BMP file headers, so the image data should
347 * always be right after the colour table.
348 */
349 if (bmp->ico)
350 bmp->bitmap_offset = (uintptr_t)data - (uintptr_t)bmp->bmp_data;
351 return BMP_OK;
352 }
353
354
355 /**
356 * Parse the bitmap file header
357 *
358 * \param bmp The bitmap.
359 * \param data The data for the file header
360 * \return BMP_OK on success or error code on faliure
361 */
bmp_file_header_parse(bmp_image * bmp,uint8_t * data)362 static bmp_result bmp_file_header_parse(bmp_image *bmp, uint8_t *data)
363 {
364 /* standard 14-byte BMP file header is:
365 *
366 * +0 UINT16 File Type ('BM')
367 * +2 UINT32 Size of File (in bytes)
368 * +6 INT16 Reserved Field (1)
369 * +8 INT16 Reserved Field (2)
370 * +10 UINT32 Starting Position of Image Data (offset in bytes)
371 */
372 if (bmp->buffer_size < BMP_FILE_HEADER_SIZE)
373 return BMP_INSUFFICIENT_DATA;
374
375 if ((data[0] != (uint8_t)'B') || (data[1] != (uint8_t)'M'))
376 return BMP_DATA_ERROR;
377
378 bmp->bitmap_offset = read_uint32(data, 10);
379
380 /* check the offset to data lies within the file */
381 if (bmp->bitmap_offset >= bmp->buffer_size) {
382 return BMP_INSUFFICIENT_DATA;
383 }
384
385 return BMP_OK;
386 }
387
388
389 /**
390 * Allocates memory for the next BMP in an ICO collection
391 *
392 * Sets proper structure values
393 *
394 * \param ico the ICO collection to add the image to
395 * \param image a pointer to the ICO image to be initialised
396 */
next_ico_image(ico_collection * ico,ico_image * image)397 static bmp_result next_ico_image(ico_collection *ico, ico_image *image) {
398 bmp_create(&image->bmp, &ico->bitmap_callbacks);
399 image->next = ico->first;
400 ico->first = image;
401 return BMP_OK;
402 }
403
404
405 /**
406 * Parse the icon file header
407 *
408 * \param ico The icon collection.
409 * \param data The header data to parse.
410 * \return BMP_OK on successful parse else error code
411 */
ico_header_parse(ico_collection * ico,uint8_t * data)412 static bmp_result ico_header_parse(ico_collection *ico, uint8_t *data)
413 {
414 uint16_t count, i;
415 bmp_result result;
416 int area, max_area = 0;
417
418 /* 6-byte ICO file header is:
419 *
420 * +0 INT16 Reserved (should be 0)
421 * +2 UINT16 Type (1 for ICO, 2 for CUR)
422 * +4 UINT16 Number of BMPs to follow
423 */
424 if (ico->buffer_size < ICO_FILE_HEADER_SIZE)
425 return BMP_INSUFFICIENT_DATA;
426 // if (read_int16(data, 2) != 0x0000)
427 // return BMP_DATA_ERROR;
428 if (read_uint16(data, 2) != 0x0001)
429 return BMP_DATA_ERROR;
430 count = read_uint16(data, 4);
431 if (count == 0)
432 return BMP_DATA_ERROR;
433 data += ICO_FILE_HEADER_SIZE;
434
435 /* check if we have enough data for the directory */
436 if (ico->buffer_size < (uint32_t)(ICO_FILE_HEADER_SIZE + (ICO_DIR_ENTRY_SIZE * count)))
437 return BMP_INSUFFICIENT_DATA;
438
439 /* Decode the BMP files.
440 *
441 * 16-byte ICO directory entry is:
442 *
443 * +0 UINT8 Width (0 for 256 pixels)
444 * +1 UINT8 Height (0 for 256 pixels)
445 * +2 UINT8 Colour count (0 if more than 256 colours)
446 * +3 INT8 Reserved (should be 0, but may not be)
447 * +4 UINT16 Colour Planes (should be 0 or 1)
448 * +6 UINT16 Bits Per Pixel
449 * +8 UINT32 Size of BMP info header + bitmap data in bytes
450 * +12 UINT32 Offset (points to the BMP info header, not the bitmap data)
451 */
452 for (i = 0; i < count; i++) {
453 ico_image *image;
454 image = calloc(1, sizeof(ico_image));
455 if (!image)
456 return BMP_INSUFFICIENT_MEMORY;
457 result = next_ico_image(ico, image);
458 if (result != BMP_OK)
459 return result;
460 image->bmp.width = read_uint8(data, 0);
461 if (image->bmp.width == 0)
462 image->bmp.width = 256;
463 image->bmp.height = read_uint8(data, 1);
464 if (image->bmp.height == 0)
465 image->bmp.height = 256;
466 image->bmp.buffer_size = read_uint32(data, 8);
467 image->bmp.bmp_data = ico->ico_data + read_uint32(data, 12);
468 if (image->bmp.bmp_data + image->bmp.buffer_size >
469 ico->ico_data + ico->buffer_size)
470 return BMP_INSUFFICIENT_DATA;
471 image->bmp.ico = true;
472 data += ICO_DIR_ENTRY_SIZE;
473
474 /* Ensure that the bitmap data resides in the buffer */
475 if (image->bmp.bmp_data - ico->ico_data >= 0 &&
476 (uint32_t)(image->bmp.bmp_data -
477 ico->ico_data) >= ico->buffer_size)
478 return BMP_DATA_ERROR;
479
480 /* Ensure that we have sufficient data to read the bitmap */
481 if (image->bmp.buffer_size - ICO_DIR_ENTRY_SIZE >=
482 ico->buffer_size - (ico->ico_data - data))
483 return BMP_INSUFFICIENT_DATA;
484
485 result = bmp_info_header_parse(&image->bmp,
486 image->bmp.bmp_data);
487 if (result != BMP_OK)
488 return result;
489
490 /* adjust the size based on the images available */
491 area = image->bmp.width * image->bmp.height;
492 if (area > max_area) {
493 ico->width = image->bmp.width;
494 ico->height = image->bmp.height;
495 max_area = area;
496 }
497 }
498 return BMP_OK;
499 }
500
501
502 /**
503 * Decode BMP data stored in 32bpp colour.
504 *
505 * \param bmp the BMP image to decode
506 * \param start the data to decode, updated to last byte read on success
507 * \param bytes the number of bytes of data available
508 * \return BMP_OK on success
509 * BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly;
510 * in this case, the image may be partially viewable
511 */
bmp_decode_rgb32(bmp_image * bmp,uint8_t ** start,int bytes)512 static bmp_result bmp_decode_rgb32(bmp_image *bmp, uint8_t **start, int bytes)
513 {
514 uint8_t *top, *bottom, *end, *data;
515 uint32_t *scanline;
516 uint32_t x, y;
517 uint32_t swidth;
518 uint8_t i;
519 uint32_t word;
520
521 data = *start;
522 swidth = sizeof(uint32_t) * bmp->width;
523 top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap);
524 if (!top)
525 return BMP_INSUFFICIENT_MEMORY;
526 bottom = top + (uint64_t)swidth * (bmp->height - 1);
527 end = data + bytes;
528 bmp->decoded = true;
529
530 /* Determine transparent index */
531 if (bmp->limited_trans) {
532 if ((data + 4) > end)
533 return BMP_INSUFFICIENT_DATA;
534 if (bmp->encoding == BMP_ENCODING_BITFIELDS)
535 bmp->transparent_index = read_uint32(data, 0);
536 else
537 bmp->transparent_index = data[2] | (data[1] << 8) | (data[0] << 16);
538 }
539
540 for (y = 0; y < bmp->height; y++) {
541 if ((data + (4 * bmp->width)) > end)
542 return BMP_INSUFFICIENT_DATA;
543 if (bmp->reversed)
544 scanline = (void *)(top + (y * swidth));
545 else
546 scanline = (void *)(bottom - (y * swidth));
547 if (bmp->encoding == BMP_ENCODING_BITFIELDS) {
548 for (x = 0; x < bmp->width; x++) {
549 word = read_uint32(data, 0);
550 for (i = 0; i < 4; i++)
551 if (bmp->shift[i] > 0)
552 scanline[x] |= ((word & bmp->mask[i]) << bmp->shift[i]);
553 else
554 scanline[x] |= ((word & bmp->mask[i]) >> (-bmp->shift[i]));
555 /* 32-bit BMPs have alpha masks, but sometimes they're not utilized */
556 if (bmp->opaque)
557 scanline[x] |= ((unsigned)0xff << 24);
558 data += 4;
559 scanline[x] = read_uint32((uint8_t *)&scanline[x],0);
560 }
561 } else {
562 for (x = 0; x < bmp->width; x++) {
563 scanline[x] = data[2] | (data[1] << 8) | (data[0] << 16);
564 if ((bmp->limited_trans) && (scanline[x] == bmp->transparent_index)) {
565 scanline[x] = bmp->trans_colour;
566 }
567 if (bmp->opaque) {
568 scanline[x] |= ((unsigned)0xff << 24);
569 } else {
570 scanline[x] |= (unsigned)data[3] << 24;
571 }
572 data += 4;
573 scanline[x] = read_uint32((uint8_t *)&scanline[x],0);
574 }
575 }
576 }
577 *start = data;
578 return BMP_OK;
579 }
580
581
582 /**
583 * Decode BMP data stored in 24bpp colour.
584 *
585 * \param bmp the BMP image to decode
586 * \param start the data to decode, updated to last byte read on success
587 * \param bytes the number of bytes of data available
588 * \return BMP_OK on success
589 * BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly;
590 * in this case, the image may be partially viewable
591 */
bmp_decode_rgb24(bmp_image * bmp,uint8_t ** start,int bytes)592 static bmp_result bmp_decode_rgb24(bmp_image *bmp, uint8_t **start, int bytes)
593 {
594 uint8_t *top, *bottom, *end, *data;
595 uint32_t *scanline;
596 uint32_t x, y;
597 uint32_t swidth;
598 uintptr_t addr;
599
600 data = *start;
601 swidth = sizeof(uint32_t) * bmp->width;
602 top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap);
603 if (!top) {
604 return BMP_INSUFFICIENT_MEMORY;
605 }
606
607 bottom = top + (uint64_t)swidth * (bmp->height - 1);
608 end = data + bytes;
609 addr = ((uintptr_t)data) & 3;
610 bmp->decoded = true;
611
612 /* Determine transparent index */
613 if (bmp->limited_trans) {
614 if ((data + 3) > end) {
615 return BMP_INSUFFICIENT_DATA;
616 }
617
618 bmp->transparent_index = data[2] | (data[1] << 8) | (data[0] << 16);
619 }
620
621 for (y = 0; y < bmp->height; y++) {
622 if ((data + (3 * bmp->width)) > end) {
623 return BMP_INSUFFICIENT_DATA;
624 }
625
626 if (bmp->reversed) {
627 scanline = (void *)(top + (y * swidth));
628 } else {
629 scanline = (void *)(bottom - (y * swidth));
630 }
631
632 for (x = 0; x < bmp->width; x++) {
633 scanline[x] = data[2] | (data[1] << 8) | (data[0] << 16);
634 if ((bmp->limited_trans) && (scanline[x] == bmp->transparent_index)) {
635 scanline[x] = bmp->trans_colour;
636 } else {
637 scanline[x] |= ((uint32_t)0xff << 24);
638 }
639 data += 3;
640 scanline[x] = read_uint32((uint8_t *)&scanline[x],0);
641 }
642
643 while (addr != (((uintptr_t)data) & 3)) {
644 data++;
645 }
646 }
647 *start = data;
648 return BMP_OK;
649 }
650
651
652 /**
653 * Decode BMP data stored in 16bpp colour.
654 *
655 * \param bmp the BMP image to decode
656 * \param start the data to decode, updated to last byte read on success
657 * \param bytes the number of bytes of data available
658 * \return BMP_OK on success
659 * BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly;
660 * in this case, the image may be partially viewable
661 */
bmp_decode_rgb16(bmp_image * bmp,uint8_t ** start,int bytes)662 static bmp_result bmp_decode_rgb16(bmp_image *bmp, uint8_t **start, int bytes)
663 {
664 uint8_t *top, *bottom, *end, *data;
665 uint32_t *scanline;
666 uint32_t x, y, swidth;
667 uintptr_t addr;
668 uint8_t i;
669 uint16_t word;
670
671 data = *start;
672 swidth = sizeof(uint32_t) * bmp->width;
673 top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap);
674 if (!top)
675 return BMP_INSUFFICIENT_MEMORY;
676 bottom = top + (uint64_t)swidth * (bmp->height - 1);
677 end = data + bytes;
678 addr = ((uintptr_t)data) & 3;
679 bmp->decoded = true;
680
681 /* Determine transparent index */
682 if (bmp->limited_trans) {
683 if ((data + 2) > end)
684 return BMP_INSUFFICIENT_DATA;
685 bmp->transparent_index = read_uint16(data, 0);
686 }
687
688 for (y = 0; y < bmp->height; y++) {
689 if ((data + (2 * bmp->width)) > end)
690 return BMP_INSUFFICIENT_DATA;
691 if (bmp->reversed)
692 scanline = (void *)(top + (y * swidth));
693 else
694 scanline = (void *)(bottom - (y * swidth));
695 if (bmp->encoding == BMP_ENCODING_BITFIELDS) {
696 for (x = 0; x < bmp->width; x++) {
697 word = read_uint16(data, 0);
698 if ((bmp->limited_trans) && (word == bmp->transparent_index))
699 scanline[x] = bmp->trans_colour;
700 else {
701 scanline[x] = 0;
702 for (i = 0; i < 4; i++)
703 if (bmp->shift[i] > 0)
704 scanline[x] |= ((word & bmp->mask[i]) << bmp->shift[i]);
705 else
706 scanline[x] |= ((word & bmp->mask[i]) >> (-bmp->shift[i]));
707 if (bmp->opaque)
708 scanline[x] |= ((unsigned)0xff << 24);
709 }
710 data += 2;
711 scanline[x] = read_uint32((uint8_t *)&scanline[x],0);
712 }
713 } else {
714 for (x = 0; x < bmp->width; x++) {
715 word = read_uint16(data, 0);
716 if ((bmp->limited_trans) && (word == bmp->transparent_index))
717 scanline[x] = bmp->trans_colour;
718 else {
719 /* 16-bit RGB defaults to RGB555 */
720 scanline[x] = ((word & (31 << 0)) << 19) |
721 ((word & (31 << 5)) << 6) |
722 ((word & (31 << 10)) >> 7);
723 }
724 if (bmp->opaque)
725 scanline[x] |= ((unsigned)0xff << 24);
726 data += 2;
727 scanline[x] = read_uint32((uint8_t *)&scanline[x],0);
728 }
729 }
730 while (addr != (((uintptr_t)data) & 3))
731 data += 2;
732 }
733 *start = data;
734 return BMP_OK;
735 }
736
737
738 /**
739 * Decode BMP data stored with a palette and in 8bpp colour or less.
740 *
741 * \param bmp the BMP image to decode
742 * \param start the data to decode, updated to last byte read on success
743 * \param bytes the number of bytes of data available
744 * \return BMP_OK on success
745 * BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly;
746 * in this case, the image may be partially viewable
747 */
bmp_decode_rgb(bmp_image * bmp,uint8_t ** start,int bytes)748 static bmp_result bmp_decode_rgb(bmp_image *bmp, uint8_t **start, int bytes)
749 {
750 uint8_t *top, *bottom, *end, *data;
751 uint32_t *scanline;
752 uintptr_t addr;
753 uint32_t x, y, swidth;
754 uint8_t bit_shifts[8];
755 uint8_t ppb = 8 / bmp->bpp;
756 uint8_t bit_mask = (1 << bmp->bpp) - 1;
757 uint8_t cur_byte = 0, bit, i;
758
759 for (i = 0; i < ppb; i++)
760 bit_shifts[i] = 8 - ((i + 1) * bmp->bpp);
761
762 data = *start;
763 swidth = sizeof(uint32_t) * bmp->width;
764 top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap);
765 if (!top)
766 return BMP_INSUFFICIENT_MEMORY;
767 bottom = top + (uint64_t)swidth * (bmp->height - 1);
768 end = data + bytes;
769 addr = ((uintptr_t)data) & 3;
770 bmp->decoded = true;
771
772 /* Determine transparent index */
773 if (bmp->limited_trans) {
774 uint32_t idx = (*data >> bit_shifts[0]) & bit_mask;
775 if (idx >= bmp->colours)
776 return BMP_DATA_ERROR;
777 bmp->transparent_index = bmp->colour_table[idx];
778 }
779
780 for (y = 0; y < bmp->height; y++) {
781 bit = 8;
782 if ((data + ((bmp->width + ppb - 1) / ppb)) > end)
783 return BMP_INSUFFICIENT_DATA;
784 if (bmp->reversed)
785 scanline = (void *)(top + (y * swidth));
786 else
787 scanline = (void *)(bottom - (y * swidth));
788 for (x = 0; x < bmp->width; x++) {
789 uint32_t idx;
790 if (bit >= ppb) {
791 bit = 0;
792 cur_byte = *data++;
793 }
794 idx = (cur_byte >> bit_shifts[bit++]) & bit_mask;
795 if (idx < bmp->colours) {
796 /* ensure colour table index is in bounds */
797 scanline[x] = bmp->colour_table[idx];
798 if ((bmp->limited_trans) &&
799 (scanline[x] == bmp->transparent_index)) {
800 scanline[x] = bmp->trans_colour;
801 }
802 }
803 }
804 while (addr != (((uintptr_t)data) & 3))
805 data++;
806 }
807 *start = data;
808 return BMP_OK;
809 }
810
811
812 /**
813 * Decode a 1bpp mask for an ICO
814 *
815 * \param bmp the BMP image to decode
816 * \param data the data to decode
817 * \param bytes the number of bytes of data available
818 * \return BMP_OK on success
819 */
bmp_decode_mask(bmp_image * bmp,uint8_t * data,int bytes)820 static bmp_result bmp_decode_mask(bmp_image *bmp, uint8_t *data, int bytes)
821 {
822 uint8_t *top, *bottom, *end;
823 uint32_t *scanline;
824 uintptr_t addr;
825 uint32_t x, y, swidth;
826 uint32_t cur_byte = 0;
827
828 swidth = sizeof(uint32_t) * bmp->width;
829 top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap);
830 if (!top)
831 return BMP_INSUFFICIENT_MEMORY;
832 bottom = top + (uint64_t)swidth * (bmp->height - 1);
833 end = data + bytes;
834
835 addr = ((uintptr_t)data) & 3;
836
837 for (y = 0; y < bmp->height; y++) {
838 if ((data + (bmp->width >> 3)) > end)
839 return BMP_INSUFFICIENT_DATA;
840 scanline = (void *)(bottom - (y * swidth));
841 for (x = 0; x < bmp->width; x++) {
842 if ((x & 7) == 0)
843 cur_byte = *data++;
844 scanline[x] = read_uint32((uint8_t *)&scanline[x], 0);
845 if ((cur_byte & 128) == 0) {
846 scanline[x] |= ((unsigned)0xff << 24);
847 } else {
848 scanline[x] &= 0xffffff;
849 }
850 scanline[x] = read_uint32((uint8_t *)&scanline[x], 0);
851 cur_byte = cur_byte << 1;
852 }
853 while (addr != (((uintptr_t)data) & 3))
854 data++;
855 }
856 return BMP_OK;
857 }
858
859
860 /**
861 * Decode BMP data stored encoded in RLE8.
862 *
863 * \param bmp the BMP image to decode
864 * \param data the data to decode
865 * \param bytes the number of bytes of data available
866 * \return BMP_OK on success
867 * BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly;
868 * in this case, the image may be partially viewable
869 */
870 static bmp_result
bmp_decode_rle8(bmp_image * bmp,uint8_t * data,int bytes)871 bmp_decode_rle8(bmp_image *bmp, uint8_t *data, int bytes)
872 {
873 uint8_t *top, *bottom, *end;
874 uint32_t *scanline;
875 uint32_t swidth;
876 uint32_t i, length, pixels_left;
877 uint32_t x = 0, y = 0, last_y = 0;
878 uint32_t pixel = 0;
879
880 if (bmp->ico)
881 return BMP_DATA_ERROR;
882
883 swidth = sizeof(uint32_t) * bmp->width;
884 top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap);
885 if (!top)
886 return BMP_INSUFFICIENT_MEMORY;
887 bottom = top + (uint64_t)swidth * (bmp->height - 1);
888 end = data + bytes;
889 bmp->decoded = true;
890
891 do {
892 if (data + 2 > end)
893 return BMP_INSUFFICIENT_DATA;
894 length = *data++;
895 if (length == 0) {
896 length = *data++;
897 switch (length) {
898 case 0:
899 /* 00 - 00 means end of scanline */
900 x = 0;
901 if (last_y == y) {
902 y++;
903 if (y >= bmp->height)
904 return BMP_DATA_ERROR;
905 }
906 last_y = y;
907 break;
908
909 case 1:
910 /* 00 - 01 means end of RLE data */
911 return BMP_OK;
912
913 case 2:
914 /* 00 - 02 - XX - YY means move cursor */
915 if (data + 2 > end)
916 return BMP_INSUFFICIENT_DATA;
917 x += *data++;
918 if (x >= bmp->width)
919 return BMP_DATA_ERROR;
920 y += *data++;
921 if (y >= bmp->height)
922 return BMP_DATA_ERROR;
923 break;
924
925 default:
926 /* 00 - NN means escape NN pixels */
927 if (bmp->reversed) {
928 pixels_left = (bmp->height - y) * bmp->width - x;
929 scanline = (void *)(top + (y * swidth));
930 } else {
931 pixels_left = (y + 1) * bmp->width - x;
932 scanline = (void *)(bottom - (y * swidth));
933 }
934 if (length > pixels_left)
935 length = pixels_left;
936 if (data + length > end)
937 return BMP_INSUFFICIENT_DATA;
938
939 /* the following code could be easily optimised
940 * by simply checking the bounds on entry and
941 * using some simple copying routines if so
942 */
943 for (i = 0; i < length; i++) {
944 uint32_t idx = (uint32_t) *data++;
945 if (x >= bmp->width) {
946 x = 0;
947 y++;
948 if (y >= bmp->height)
949 return BMP_DATA_ERROR;
950 if (bmp->reversed) {
951 scanline += bmp->width;
952 } else {
953 scanline -= bmp->width;
954 }
955 }
956 if (idx >= bmp->colours)
957 return BMP_DATA_ERROR;
958 scanline[x++] = bmp->colour_table[idx];
959 }
960
961 if ((length & 1) && (*data++ != 0x00))
962 return BMP_DATA_ERROR;
963
964 break;
965 }
966 } else {
967 uint32_t idx;
968
969 /* NN means perform RLE for NN pixels */
970 if (bmp->reversed) {
971 pixels_left = (bmp->height - y) * bmp->width - x;
972 scanline = (void *)(top + (y * swidth));
973 } else {
974 pixels_left = (y + 1) * bmp->width - x;
975 scanline = (void *)(bottom - (y * swidth));
976 }
977 if (length > pixels_left)
978 length = pixels_left;
979
980 /* boundary checking */
981 if (data + 1 > end)
982 return BMP_INSUFFICIENT_DATA;
983
984 /* the following code could be easily optimised by
985 * simply checking the bounds on entry and using some
986 * simply copying routines if so
987 */
988 idx = (uint32_t) *data++;
989 if (idx >= bmp->colours)
990 return BMP_DATA_ERROR;
991
992 pixel = bmp->colour_table[idx];
993 for (i = 0; i < length; i++) {
994 if (x >= bmp->width) {
995 x = 0;
996 y++;
997 if (y >= bmp->height)
998 return BMP_DATA_ERROR;
999 if (bmp->reversed) {
1000 scanline += bmp->width;
1001 } else {
1002 scanline -= bmp->width;
1003 }
1004 }
1005 scanline[x++] = pixel;
1006 }
1007 }
1008 } while (data < end);
1009
1010 return BMP_OK;
1011 }
1012
1013
1014 /**
1015 * Decode BMP data stored encoded in RLE4.
1016 *
1017 * \param bmp the BMP image to decode
1018 * \param data the data to decode
1019 * \param bytes the number of bytes of data available
1020 * \return BMP_OK on success
1021 * BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly;
1022 * in this case, the image may be partially viewable
1023 */
1024 static bmp_result
bmp_decode_rle4(bmp_image * bmp,uint8_t * data,int bytes)1025 bmp_decode_rle4(bmp_image *bmp, uint8_t *data, int bytes)
1026 {
1027 uint8_t *top, *bottom, *end;
1028 uint32_t *scanline;
1029 uint32_t swidth;
1030 uint32_t i, length, pixels_left;
1031 uint32_t x = 0, y = 0, last_y = 0;
1032 uint32_t pixel = 0, pixel2;
1033
1034 if (bmp->ico)
1035 return BMP_DATA_ERROR;
1036
1037 swidth = sizeof(uint32_t) * bmp->width;
1038 top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap);
1039 if (!top)
1040 return BMP_INSUFFICIENT_MEMORY;
1041 bottom = top + (uint64_t)swidth * (bmp->height - 1);
1042 end = data + bytes;
1043 bmp->decoded = true;
1044
1045 do {
1046 if (data + 2 > end)
1047 return BMP_INSUFFICIENT_DATA;
1048 length = *data++;
1049 if (length == 0) {
1050 length = *data++;
1051 switch (length) {
1052 case 0:
1053 /* 00 - 00 means end of scanline */
1054 x = 0;
1055 if (last_y == y) {
1056 y++;
1057 if (y >= bmp->height)
1058 return BMP_DATA_ERROR;
1059 }
1060 last_y = y;
1061 break;
1062
1063 case 1:
1064 /* 00 - 01 means end of RLE data */
1065 return BMP_OK;
1066
1067 case 2:
1068 /* 00 - 02 - XX - YY means move cursor */
1069 if (data + 2 > end)
1070 return BMP_INSUFFICIENT_DATA;
1071 x += *data++;
1072 if (x >= bmp->width)
1073 return BMP_DATA_ERROR;
1074 y += *data++;
1075 if (y >= bmp->height)
1076 return BMP_DATA_ERROR;
1077 break;
1078
1079 default:
1080 /* 00 - NN means escape NN pixels */
1081 if (bmp->reversed) {
1082 pixels_left = (bmp->height - y) * bmp->width - x;
1083 scanline = (void *)(top + (y * swidth));
1084 } else {
1085 pixels_left = (y + 1) * bmp->width - x;
1086 scanline = (void *)(bottom - (y * swidth));
1087 }
1088 if (length > pixels_left)
1089 length = pixels_left;
1090 if (data + ((length + 1) / 2) > end)
1091 return BMP_INSUFFICIENT_DATA;
1092
1093 /* the following code could be easily optimised
1094 * by simply checking the bounds on entry and
1095 * using some simple copying routines
1096 */
1097
1098 for (i = 0; i < length; i++) {
1099 if (x >= bmp->width) {
1100 x = 0;
1101 y++;
1102 if (y >= bmp->height)
1103 return BMP_DATA_ERROR;
1104 if (bmp->reversed) {
1105 scanline += bmp->width;
1106 } else {
1107 scanline -= bmp->width;
1108 }
1109
1110 }
1111 if ((i & 1) == 0) {
1112 pixel = *data++;
1113 if ((pixel >> 4) >= bmp->colours)
1114 return BMP_DATA_ERROR;
1115 scanline[x++] = bmp->colour_table
1116 [pixel >> 4];
1117 } else {
1118 if ((pixel & 0xf) >= bmp->colours)
1119 return BMP_DATA_ERROR;
1120 scanline[x++] = bmp->colour_table
1121 [pixel & 0xf];
1122 }
1123 }
1124 length = (length + 1) >> 1;
1125
1126 if ((length & 1) && (*data++ != 0x00))
1127 return BMP_DATA_ERROR;
1128
1129 break;
1130 }
1131 } else {
1132 /* NN means perform RLE for NN pixels */
1133 if (bmp->reversed) {
1134 pixels_left = (bmp->height - y) * bmp->width - x;
1135 scanline = (void *)(top + (y * swidth));
1136 } else {
1137 pixels_left = (y + 1) * bmp->width - x;
1138 scanline = (void *)(bottom - (y * swidth));
1139 }
1140 if (length > pixels_left)
1141 length = pixels_left;
1142
1143 /* boundary checking */
1144 if (data + 1 > end)
1145 return BMP_INSUFFICIENT_DATA;
1146
1147 /* the following code could be easily optimised by
1148 * simply checking the bounds on entry and using some
1149 * simple copying routines
1150 */
1151
1152 pixel2 = *data++;
1153 if ((pixel2 >> 4) >= bmp->colours ||
1154 (pixel2 & 0xf) >= bmp->colours)
1155 return BMP_DATA_ERROR;
1156 pixel = bmp->colour_table[pixel2 >> 4];
1157 pixel2 = bmp->colour_table[pixel2 & 0xf];
1158 for (i = 0; i < length; i++) {
1159 if (x >= bmp->width) {
1160 x = 0;
1161 y++;
1162 if (y >= bmp->height)
1163 return BMP_DATA_ERROR;
1164 if (bmp->reversed) {
1165 scanline += bmp->width;
1166 } else {
1167 scanline -= bmp->width;
1168 }
1169 }
1170 if ((i & 1) == 0)
1171 scanline[x++] = pixel;
1172 else
1173 scanline[x++] = pixel2;
1174 }
1175
1176 }
1177 } while (data < end);
1178
1179 return BMP_OK;
1180 }
1181
1182
1183 /* exported interface documented in libnsbmp.h */
1184 bmp_result
bmp_create(bmp_image * bmp,bmp_bitmap_callback_vt * bitmap_callbacks)1185 bmp_create(bmp_image *bmp,
1186 bmp_bitmap_callback_vt *bitmap_callbacks)
1187 {
1188 memset(bmp, 0, sizeof(bmp_image));
1189 bmp->bitmap_callbacks = *bitmap_callbacks;
1190
1191 return BMP_OK;
1192 }
1193
1194
1195 /* exported interface documented in libnsbmp.h */
1196 bmp_result
ico_collection_create(ico_collection * ico,bmp_bitmap_callback_vt * bitmap_callbacks)1197 ico_collection_create(ico_collection *ico,
1198 bmp_bitmap_callback_vt *bitmap_callbacks)
1199 {
1200
1201 memset(ico, 0, sizeof(ico_collection));
1202 ico->bitmap_callbacks = *bitmap_callbacks;
1203
1204 return BMP_OK;
1205 }
1206
1207
1208 /* exported interface documented in libnsbmp.h */
bmp_analyse(bmp_image * bmp,size_t size,uint8_t * data)1209 bmp_result bmp_analyse(bmp_image *bmp, size_t size, uint8_t *data)
1210 {
1211 bmp_result res;
1212
1213 /* ensure we aren't already initialised */
1214 if (bmp->bitmap) {
1215 return BMP_OK;
1216 }
1217
1218 /* initialize source data values */
1219 bmp->buffer_size = size;
1220 bmp->bmp_data = data;
1221
1222 res = bmp_file_header_parse(bmp, data);
1223 if (res == BMP_OK) {
1224 res = bmp_info_header_parse(bmp, data + BMP_FILE_HEADER_SIZE);
1225 }
1226 return res;
1227 }
1228
1229
1230 /* exported interface documented in libnsbmp.h */
ico_analyse(ico_collection * ico,size_t size,uint8_t * data)1231 bmp_result ico_analyse(ico_collection *ico, size_t size, uint8_t *data)
1232 {
1233 /* ensure we aren't already initialised */
1234 if (ico->first)
1235 return BMP_OK;
1236
1237 /* initialize values */
1238 ico->buffer_size = size;
1239 ico->ico_data = data;
1240
1241 return ico_header_parse(ico, data);
1242 }
1243
1244
1245 /* exported interface documented in libnsbmp.h */
bmp_decode(bmp_image * bmp)1246 bmp_result bmp_decode(bmp_image *bmp)
1247 {
1248 uint8_t *data;
1249 uint32_t bytes;
1250 bmp_result result = BMP_OK;
1251
1252 data = bmp->bmp_data + bmp->bitmap_offset;
1253 bytes = bmp->buffer_size - bmp->bitmap_offset;
1254
1255 switch (bmp->encoding) {
1256 case BMP_ENCODING_RGB:
1257 switch (bmp->bpp) {
1258 case 32:
1259 result = bmp_decode_rgb32(bmp, &data, bytes);
1260 break;
1261
1262 case 24:
1263 result = bmp_decode_rgb24(bmp, &data, bytes);
1264 break;
1265
1266 case 16:
1267 result = bmp_decode_rgb16(bmp, &data, bytes);
1268 break;
1269
1270 default:
1271 result = bmp_decode_rgb(bmp, &data, bytes);
1272 break;
1273 }
1274 break;
1275
1276 case BMP_ENCODING_RLE8:
1277 result = bmp_decode_rle8(bmp, data, bytes);
1278 break;
1279
1280 case BMP_ENCODING_RLE4:
1281 result = bmp_decode_rle4(bmp, data, bytes);
1282 break;
1283
1284 case BMP_ENCODING_BITFIELDS:
1285 switch (bmp->bpp) {
1286 case 32:
1287 result = bmp_decode_rgb32(bmp, &data, bytes);
1288 break;
1289
1290 case 16:
1291 result = bmp_decode_rgb16(bmp, &data, bytes);
1292 break;
1293
1294 default:
1295 result = BMP_DATA_ERROR;
1296 break;
1297 }
1298 break;
1299 }
1300
1301 /* icons with less than 32bpp have a 1bpp alpha mask */
1302 if ((result == BMP_OK) && (bmp->ico) && (bmp->bpp != 32)) {
1303 bytes = (uintptr_t)bmp->bmp_data + bmp->buffer_size - (uintptr_t)data;
1304 result = bmp_decode_mask(bmp, data, bytes);
1305 }
1306 return result;
1307 }
1308
1309
1310 /* exported interface documented in libnsbmp.h */
bmp_decode_trans(bmp_image * bmp,uint32_t colour)1311 bmp_result bmp_decode_trans(bmp_image *bmp, uint32_t colour)
1312 {
1313 bmp->limited_trans = true;
1314 bmp->trans_colour = colour;
1315 return bmp_decode(bmp);
1316 }
1317
1318
1319 /* exported interface documented in libnsbmp.h */
ico_find(ico_collection * ico,uint16_t width,uint16_t height)1320 bmp_image *ico_find(ico_collection *ico, uint16_t width, uint16_t height)
1321 {
1322 bmp_image *bmp = NULL;
1323 ico_image *image;
1324 int x, y, cur, distance = (1 << 24);
1325
1326 if (width == 0)
1327 width = ico->width;
1328 if (height == 0)
1329 height = ico->height;
1330 for (image = ico->first; image; image = image->next) {
1331 if ((image->bmp.width == width) && (image->bmp.height == height))
1332 return &image->bmp;
1333 x = image->bmp.width - width;
1334 y = image->bmp.height - height;
1335 cur = (x * x) + (y * y);
1336 if (cur < distance) {
1337 distance = cur;
1338 bmp = &image->bmp;
1339 }
1340 }
1341 return bmp;
1342 }
1343
1344
1345 /* exported interface documented in libnsbmp.h */
bmp_finalise(bmp_image * bmp)1346 void bmp_finalise(bmp_image *bmp)
1347 {
1348 if (bmp->bitmap)
1349 bmp->bitmap_callbacks.bitmap_destroy(bmp->bitmap);
1350 bmp->bitmap = NULL;
1351 if (bmp->colour_table)
1352 free(bmp->colour_table);
1353 bmp->colour_table = NULL;
1354 }
1355
1356
1357 /* exported interface documented in libnsbmp.h */
ico_finalise(ico_collection * ico)1358 void ico_finalise(ico_collection *ico)
1359 {
1360 ico_image *image;
1361
1362 for (image = ico->first; image; image = image->next)
1363 bmp_finalise(&image->bmp);
1364 while (ico->first) {
1365 image = ico->first;
1366 ico->first = image->next;
1367 free(image);
1368 }
1369 }
1370