Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3584 sourcerer 1
/*
2
 * Copyright 2006 Richard Wilson 
3
 * Copyright 2008 Sean Fox 
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
#include 
11
#include 
12
#include 
13
#include 
14
#include 
15
#include 
16
 
17
#include 
18
 
19
#include "utils/log.h"
20
 
21
/*	The functions provided by this file allow for the decoding of
22
	Microsoft's BMP and ICO image file formats.
23
 
24
	READING BMP FILES
25
	=================
26
 
27
	To begin decoding a BMP, the caller should initialise a
28
	'bmp_bitmap_callback_vt' structure with the appropriate values necessary
29
	to handle bitmap images.  Next, a 'bmp_image' structure should be
30
	initialised by calling bmp_create().  This structure should then be
31
	passed to bmp_analyse() along with the BMP data to process and the size
32
	of this data.
33
 
34
	Once the analysis has begun, the decoder completes the width and height
35
	variables.
36
 
37
	To decode the image, the caller must use bmp_decode() which selects the
38
	proper decoding method based on the BMP info header and assigns the
39
	decoded bitmap image to the 'bitmap' member of the 'bmp_image'
40
	structure.  The bitmap image is stored with 4 bytes-per-pixel in RGBA
41
	format.
42
 
43
	It should be noted that bmp_finalise() should always be called, even if
44
	the image was never decoded.  It is also the responsibility of the
45
	caller to free 'bmp_data'.
46
 
47
	READING ICO FILES
48
	=================
49
 
50
	To begin decoding an ICO, the caller should initialise a
51
	'bmp_bitmap_callback_vt' structure with the appropriate values necessary
52
	to handle bitmap images.  Next, an 'ico_collection' structure should be
53
	initialised by calling ico_create().  This structure should then be
54
	passed to ico_analyse() along with the ICO data to process and the size
55
	of this data.
56
 
57
	Once the analysis has begun, the decoder completes the width and height
58
	variables.  Because ICO collections contain multiple bitmap images, the
59
	width and height will contain the values of the largest available image.
60
 
61
	The caller then obtains a BMP from the ICO collection by calling
62
	ico_find() with the requested width and height.
63
 
64
	To decode the image, the caller must use bmp_decode() which selects the
65
	proper decoding method based on the BMP info header and assigns the
66
	decoded bitmap image to the 'bitmap' member of the 'bmp_image'
67
	structure.  The bitmap image is stored with 4 bytes-per-pixel in RGBA
68
	format.
69
 
70
	It should be noted that ico_finalise() should always be called, even if
71
	no images were decoded.  Because ico_finalise() calls bmp_finalise() for
72
	each bitmap within the collection, the caller is not required to perform
73
	this function.  However, it is the responsibility of the caller to free
74
	'ico_data'.
75
 
76
	[dynis] - Tue 1st July 2008
77
*/
78
 
79
/* squashes unused variable compiler warnings */
80
#define UNUSED(x) ((x)=(x))
81
 
82
/* BMP flags */
83
#define BMP_FILE_HEADER_SIZE 14
84
#define ICO_FILE_HEADER_SIZE 6
85
#define ICO_DIR_ENTRY_SIZE 16
86
 
87
static inline int8_t read_int8(uint8_t *data, unsigned int o) {
88
	return (int8_t) data[o];
89
}
90
 
91
static inline uint8_t read_uint8(uint8_t *data, unsigned int o) {
92
	return (uint8_t) data[o];
93
}
94
 
95
static inline int16_t read_int16(uint8_t *data, unsigned int o) {
96
	return (int16_t) (data[o] | (data[o+1] << 8));
97
}
98
 
99
static inline uint16_t read_uint16(uint8_t *data, unsigned int o) {
100
	return (uint16_t) (data[o] | (data[o+1] << 8));
101
}
102
 
103
static inline int32_t read_int32(uint8_t *data, unsigned int o) {
104
	return (int32_t) (data[o] | (data[o+1] << 8) | (data[o+2] << 16) | (data[o+3] << 24));
105
}
106
 
107
static inline uint32_t read_uint32(uint8_t *data, unsigned int o) {
108
	return (uint32_t) (data[o] | (data[o+1] << 8) | (data[o+2] << 16) | (data[o+3] << 24));
109
}
110
 
111
static bmp_result next_ico_image(ico_collection *ico, ico_image *image);
112
static bmp_result bmp_analyse_header(bmp_image *bmp, unsigned char *data);
113
static bmp_result bmp_decode_rgb24(bmp_image *bmp, uint8_t **start, int bytes);
114
static bmp_result bmp_decode_rgb16(bmp_image *bmp, uint8_t **start, int bytes);
115
static bmp_result bmp_decode_rgb(bmp_image *bmp, uint8_t **start, int bytes);
116
static bmp_result bmp_decode_mask(bmp_image *bmp, uint8_t *data, int bytes);
117
static bmp_result bmp_decode_rle(bmp_image *bmp, uint8_t *data, int bytes, int size);
118
 
119
 
120
 
121
/**	Initialises necessary bmp_image members.
122
*/
123
void bmp_create(bmp_image *bmp, bmp_bitmap_callback_vt *bitmap_callbacks) {
124
	memset(bmp, 0, sizeof(bmp_image));
125
	bmp->bitmap_callbacks = *bitmap_callbacks;
126
}
127
 
128
 
129
/**	Initialises necessary ico_collection members.
130
*/
131
void ico_collection_create(ico_collection *ico, bmp_bitmap_callback_vt *bitmap_callbacks) {
132
	memset(ico, 0, sizeof(ico_collection));
133
	ico->bitmap_callbacks = *bitmap_callbacks;
134
}
135
 
136
 
137
/**
138
 * Analyse a BMP prior to decoding.
139
 *
140
 * This function will scan the data provided and perform simple checks to
141
 * ensure the data is a valid BMP.
142
 *
143
 * This function must be called before bmp_decode() and sets up all the
144
 * relevant values in the bmp structure.
145
 *
146
 * \param bmp	the BMP image to analyse
147
 * \return BMP_OK on success
148
 */
149
bmp_result bmp_analyse(bmp_image *bmp, size_t size, unsigned char *cdata) {
150
	uint8_t *data = (uint8_t *)cdata;
151
 
152
	/* ensure we aren't already initialised */
153
	if (bmp->bitmap)
154
		return BMP_OK;
155
 
156
	/* initialize values */
157
	bmp->buffer_size = size;
158
	bmp->bmp_data = data;
159
 
160
	/* standard 14-byte BMP file header is:
161
	 *
162
	 *	+0	UINT16	File Type ('BM')
163
	 *	+2	UINT32	Size of File (in bytes)
164
	 *	+6	INT16	Reserved Field (1)
165
	 *	+8	INT16	Reserved Field (2)
166
	 *	+10	UINT32	Starting Position of Image Data (offset in bytes)
167
	 */
168
	if (bmp->buffer_size < BMP_FILE_HEADER_SIZE)
169
		return BMP_INSUFFICIENT_DATA;
170
	if ((data[0] != (uint8_t)'B') || (data[1] != (uint8_t)'M'))
171
		return BMP_DATA_ERROR;
172
	bmp->bitmap_offset = read_uint32(data, 10);
173
	data += BMP_FILE_HEADER_SIZE;
174
 
175
	/* boundary checking */
176
	if (bmp->bitmap_offset >= size)
177
		return BMP_INSUFFICIENT_DATA;
178
 
179
	/* decode the BMP header */
180
	return bmp_analyse_header(bmp, data);
181
}
182
 
183
 
184
/**
185
 * Analyse an ICO prior to decoding.
186
 *
187
 * This function will scan the data provided and perform simple checks to
188
 * ensure the data is a valid ICO.
189
 *
190
 * This function must be called before ico_find().
191
 *
192
 * \param ico	the ICO image to analyse
193
 * \return BMP_OK on success
194
 */
195
bmp_result ico_analyse(ico_collection *ico, size_t size, uint8_t *data) {
196
	uint16_t count, i;
197
	bmp_result result;
198
	int area, max_area = 0;
199
 
200
	/* ensure we aren't already initialised */
201
	if (ico->first)
202
		return BMP_OK;
203
 
204
	/* initialize values */
205
	ico->buffer_size = size;
206
	ico->ico_data = data;
207
 
208
	/* 6-byte ICO file header is:
209
	 *
210
	 *	+0	INT16	Reserved (should be 0)
211
	 *	+2	UINT16	Type (1 for ICO, 2 for CUR)
212
	 *	+4	UINT16	Number of BMPs to follow
213
	 */
214
	if (ico->buffer_size < ICO_FILE_HEADER_SIZE)
215
		return BMP_INSUFFICIENT_DATA;
216
// 	if (read_int16(data, 2) != 0x0000)
217
// 		return BMP_DATA_ERROR;
218
	if (read_uint16(data, 2) != 0x0001)
219
		return BMP_DATA_ERROR;
220
	count = read_uint16(data, 4);
221
	if (count == 0)
222
		return BMP_DATA_ERROR;
223
	data += ICO_FILE_HEADER_SIZE;
224
 
225
	/* check if we have enough data for the directory */
226
	if (ico->buffer_size < (uint32_t)(ICO_FILE_HEADER_SIZE + (ICO_DIR_ENTRY_SIZE * count)))
227
		return BMP_INSUFFICIENT_DATA;
228
 
229
	/* Decode the BMP files.
230
	 *
231
	 * 16-byte ICO directory entry is:
232
	 *
233
	 *	+0	UINT8	Width (0 for 256 pixels)
234
	 *	+1	UINT8	Height (0 for 256 pixels)
235
	 *	+2	UINT8	Colour count (0 if more than 256 colours)
236
	 *	+3	INT8	Reserved (should be 0, but may not be)
237
	 *	+4	UINT16	Colour Planes (should be 0 or 1)
238
	 *	+6	UINT16	Bits Per Pixel
239
	 *	+8	UINT32	Size of BMP info header + bitmap data in bytes
240
	 *	+12	UINT32	Offset (points to the BMP info header, not the bitmap data)
241
	 */
242
	for (i = 0; i < count; i++) {
243
		ico_image *image;
244
		image = calloc(1, sizeof(ico_image));
245
		if (!image)
246
			return BMP_INSUFFICIENT_MEMORY;
247
		result = next_ico_image(ico, image);
248
		if (result != BMP_OK)
249
			return result;
250
		image->bmp.width = read_uint8(data, 0);
251
		if (image->bmp.width == 0)
252
			image->bmp.width = 256;
253
		image->bmp.height = read_uint8(data, 1);
254
		if (image->bmp.height == 0)
255
			image->bmp.height = 256;
256
		image->bmp.buffer_size = read_uint32(data, 8);
257
		image->bmp.bmp_data = ico->ico_data + read_uint32(data, 12);
258
		image->bmp.ico = true;
259
		data += ICO_DIR_ENTRY_SIZE;
260
 
261
		/* Ensure that the bitmap data resides in the buffer */
262
		if (image->bmp.bmp_data - ico->ico_data >= 0 &&
263
				(uint32_t)(image->bmp.bmp_data -
264
				ico->ico_data) >= ico->buffer_size)
265
			return BMP_DATA_ERROR;
266
 
267
		/* Ensure that we have sufficient data to read the bitmap */
268
		if (image->bmp.buffer_size - ICO_DIR_ENTRY_SIZE >=
269
		    ico->buffer_size - (ico->ico_data - data))
270
			return BMP_INSUFFICIENT_DATA;
271
 
272
		result = bmp_analyse_header(&image->bmp, image->bmp.bmp_data);
273
		if (result != BMP_OK)
274
			return result;
275
 
276
		/* adjust the size based on the images available */
277
		area = image->bmp.width * image->bmp.height;
278
		if (area > max_area) {
279
			ico->width = image->bmp.width;
280
			ico->height = image->bmp.height;
281
			max_area = area;
282
		}
283
	}
284
	return BMP_OK;
285
}
286
 
287
 
288
/**
289
 * Allocates memory for the next BMP in an ICO collection
290
 *
291
 * Sets proper structure values
292
 *
293
 * \param ico		the ICO collection to add the image to
294
 * \param image		a pointer to the ICO image to be initialised
295
 */
296
static bmp_result next_ico_image(ico_collection *ico, ico_image *image) {
297
	bmp_create(&image->bmp, &ico->bitmap_callbacks);
298
	image->next = ico->first;
299
	ico->first = image;
300
	return BMP_OK;
301
}
302
 
303
 
304
static bmp_result bmp_analyse_header(bmp_image *bmp, uint8_t *data) {
305
	uint32_t header_size;
306
	uint32_t i;
307
	uint8_t j;
308
	int32_t width, height;
309
	uint8_t palette_size;
310
	unsigned int flags = 0;
311
 
312
	/* a variety of different bitmap headers can follow, depending
313
	 * on the BMP variant. A full description of the various headers
314
	 * can be found at
315
	 * http://msdn.microsoft.com/en-us/library/ms532301(VS.85).aspx
316
	 */
317
	header_size = read_uint32(data, 0);
318
	if (bmp->buffer_size < (14 + header_size))
319
		return BMP_INSUFFICIENT_DATA;
320
	if (header_size == 12) {
321
		/* the following header is for os/2 and windows 2.x and consists of:
322
		 *
323
		 *	+0	UINT32	size of this header (in bytes)
324
		 *	+4	INT16	image width (in pixels)
325
		 *	+6	INT16	image height (in pixels)
326
		 *	+8	UINT16	number of colour planes (always 1)
327
		 *	+10	UINT16	number of bits per pixel
328
		 */
329
		width = read_int16(data, 4);
330
		height = read_int16(data, 6);
331
		if ((width <= 0) || (height == 0))
332
			return BMP_DATA_ERROR;
333
		if (height < 0) {
334
			bmp->reversed = true;
335
			height = -height;
336
		}
337
		/* ICOs only support 256*256 resolutions
338
		 * In the case of the ICO header, the height is actually the added
339
		 * height of XOR-Bitmap and AND-Bitmap (double the visible height)
340
		 * Technically we could remove this check and ICOs with bitmaps
341
		 * of any size could be processed; this is to conform to the spec.
342
		 */
343
		if (bmp->ico) {
344
			if ((width > 256) || (height > 512)) {
345
				return BMP_DATA_ERROR;
346
			} else {
347
				bmp->width = width;
348
				bmp->height = height / 2;
349
			}
350
		} else {
351
			bmp->width = width;
352
			bmp->height = height;
353
		}
354
		if (read_uint16(data, 8) != 1)
355
			return BMP_DATA_ERROR;
356
		bmp->bpp = read_uint16(data, 10);
357
		/**
358
		 * The bpp value should be in the range 1-32, but the only
359
		 * values considered legal are:
360
		 * RGB ENCODING: 1, 4, 8, 16, 24 and 32
361
		 */
362
		if ((bmp->bpp != 1) && (bmp->bpp != 4) &&
363
				(bmp->bpp != 8) &&
364
				(bmp->bpp != 16) &&
365
				(bmp->bpp != 24) &&
366
				(bmp->bpp != 32))
367
			return BMP_DATA_ERROR;
368
		bmp->colours = (1 << bmp->bpp);
369
		palette_size = 3;
370
	} else if (header_size < 40) {
371
		return BMP_DATA_ERROR;
372
	} else {
373
		/* the following header is for windows 3.x and onwards. it is a
374
		 * minimum of 40 bytes and (as of Windows 95) a maximum of 108 bytes.
375
		 *
376
		 *	+0	UINT32	size of this header (in bytes)
377
		 *	+4	INT32	image width (in pixels)
378
		 *	+8	INT32	image height (in pixels)
379
 		 *	+12	UINT16	number of colour planes (always 1)
380
		 *	+14	UINT16	number of bits per pixel
381
		 *	+16	UINT32	compression methods used
382
		 *	+20	UINT32	size of bitmap (in bytes)
383
		 *	+24	UINT32	horizontal resolution (in pixels per meter)
384
		 *	+28	UINT32	vertical resolution (in pixels per meter)
385
		 *	+32	UINT32	number of colours in the image
386
		 *	+36	UINT32	number of important colours
387
		 *	+40	UINT32	mask identifying bits of red component
388
		 *	+44	UINT32	mask identifying bits of green component
389
		 *	+48	UINT32	mask identifying bits of blue component
390
		 *	+52	UINT32	mask identifying bits of alpha component
391
		 *	+56	UINT32	color space type
392
		 *	+60	UINT32	x coordinate of red endpoint
393
		 *	+64	UINT32	y coordinate of red endpoint
394
		 *	+68	UINT32	z coordinate of red endpoint
395
		 *	+72	UINT32	x coordinate of green endpoint
396
		 *	+76	UINT32	y coordinate of green endpoint
397
		 *	+80	UINT32	z coordinate of green endpoint
398
		 *	+84	UINT32	x coordinate of blue endpoint
399
		 *	+88	UINT32	y coordinate of blue endpoint
400
		 *	+92	UINT32	z coordinate of blue endpoint
401
		 *	+96	UINT32	gamma red coordinate scale value
402
		 *	+100	UINT32	gamma green coordinate scale value
403
		 *	+104	UINT32	gamma blue coordinate scale value
404
		 */
405
		width = read_int32(data, 4);
406
		height = read_int32(data, 8);
407
		if ((width <= 0) || (height == 0))
408
			return BMP_DATA_ERROR;
409
		if (height < 0) {
410
			bmp->reversed = true;
411
			height = -height;
412
		}
413
		/* ICOs only support 256*256 resolutions
414
		 * In the case of the ICO header, the height is actually the added
415
		 * height of XOR-Bitmap and AND-Bitmap (double the visible height)
416
		 * Technically we could remove this check and ICOs with bitmaps
417
		 * of any size could be processed; this is to conform to the spec.
418
		 */
419
		if (bmp->ico) {
420
			if ((width > 256) || (height > 512)) {
421
				return BMP_DATA_ERROR;
422
			} else {
423
				bmp->width = width;
424
				bmp->height = height / 2;
425
			}
426
		} else {
427
			bmp->width = width;
428
			bmp->height = height;
429
		}
430
		if (read_uint16(data, 12) != 1)
431
			return BMP_DATA_ERROR;
432
		bmp->bpp = read_uint16(data, 14);
433
		if (bmp->bpp == 0)
434
			bmp->bpp = 8;
435
		bmp->encoding = read_uint32(data, 16);
436
		/**
437
		 * The bpp value should be in the range 1-32, but the only
438
		 * values considered legal are:
439
		 * RGB ENCODING: 1, 4, 8, 16, 24 and 32
440
		 * RLE4 ENCODING: 4
441
		 * RLE8 ENCODING: 8
442
		 * BITFIELD ENCODING: 16 and 32
443
		 */
444
		switch (bmp->encoding) {
445
			case BMP_ENCODING_RGB:
446
				if ((bmp->bpp != 1) && (bmp->bpp != 4) &&
447
						(bmp->bpp != 8) &&
448
						(bmp->bpp != 16) &&
449
						(bmp->bpp != 24) &&
450
						(bmp->bpp != 32))
451
					return BMP_DATA_ERROR;
452
				break;
453
			case BMP_ENCODING_RLE8:
454
				if (bmp->bpp != 8)
455
					return BMP_DATA_ERROR;
456
				break;
457
			case BMP_ENCODING_RLE4:
458
				if (bmp->bpp != 4)
459
					return BMP_DATA_ERROR;
460
				break;
461
			case BMP_ENCODING_BITFIELDS:
462
				if ((bmp->bpp != 16) && (bmp->bpp != 32))
463
					return BMP_DATA_ERROR;
464
				break;
465
			/* invalid encoding */
466
			default:
467
				return BMP_DATA_ERROR;
468
				break;
469
		}
470
		/* Bitfield encoding means we have red, green, blue, and alpha masks.
471
		 * Here we aquire the masks and determine the required bit shift to
472
		 * align them in our 24-bit color 8-bit alpha format.
473
		 */
474
		if (bmp->encoding == BMP_ENCODING_BITFIELDS) {
475
			if (header_size == 40) {
476
				header_size += 12;
477
				if (bmp->buffer_size < (14 + header_size))
478
					return BMP_INSUFFICIENT_DATA;
479
				for (i = 0; i < 3; i++)
480
					bmp->mask[i] = read_uint32(data, 40 + (i << 2));
481
			} else {
482
				for (i = 0; i < 4; i++)
483
					bmp->mask[i] = read_uint32(data, 40 + (i << 2));
484
			}
485
			for (i = 0; i < 4; i++) {
486
				if (bmp->mask[i] == 0)
487
					break;
488
				for (j = 31; j > 0; j--)
489
					if (bmp->mask[i] & (1 << j)) {
490
					  	if ((j - 7) > 0)
491
					  		bmp->mask[i] &= 0xff << (j - 7);
492
					  	else
493
					  		bmp->mask[i] &= 0xff >> (-(j - 7));
494
					  	bmp->shift[i] = (i << 3) - (j - 7);
495
						break;
496
					}
497
			}
498
		}
499
		bmp->colours = read_uint32(data, 32);
500
		if (bmp->colours == 0)
501
			bmp->colours = (1 << bmp->bpp);
502
		palette_size = 4;
503
	}
504
	data += header_size;
505
 
506
	/* if there's no alpha mask, flag the bmp opaque */
507
	if ((!bmp->ico) && (bmp->mask[3] == 0)) {
508
		flags |= BMP_OPAQUE;
509
		bmp->opaque = true;
510
	}
511
 
512
	/* we only have a palette for <16bpp */
513
	if (bmp->bpp < 16) {
514
		/* we now have a series of palette entries of the format:
515
		 *
516
		 *	+0	BYTE	blue
517
		 *	+1	BYTE	green
518
		 *	+2	BYTE	red
519
		 *
520
		 * if the palette is from an OS/2 or Win2.x file then the entries
521
		 * are padded with an extra byte.
522
		 */
523
 
524
		/* boundary checking */
525
		if (bmp->buffer_size < (14 + header_size + ((uint64_t)4 * bmp->colours)))
526
			return BMP_INSUFFICIENT_DATA;
527
 
528
		/* create the colour table */
529
		bmp->colour_table = (uint32_t *)malloc(bmp->colours * 4);
530
		if (!bmp->colour_table)
531
			return BMP_INSUFFICIENT_MEMORY;
532
		for (i = 0; i < bmp->colours; i++) {
533
			bmp->colour_table[i] = data[2] | (data[1] << 8) | (data[0] << 16);
534
			if (bmp->opaque)
535
				bmp->colour_table[i] |= (0xff << 24);
536
			data += palette_size;
537
			bmp->colour_table[i] = read_uint32((uint8_t *)&bmp->colour_table[i],0);
538
		}
539
	}
540
 
541
	/* create our bitmap */
542
	flags |= BMP_NEW | BMP_CLEAR_MEMORY;
543
	bmp->bitmap = bmp->bitmap_callbacks.bitmap_create(bmp->width, bmp->height, flags);
544
	if (!bmp->bitmap) {
545
		if (bmp->colour_table)
546
			free(bmp->colour_table);
547
		bmp->colour_table = NULL;
548
		return BMP_INSUFFICIENT_MEMORY;
549
	}
550
	/* BMPs within ICOs don't have BMP file headers, so the image data should
551
	 * always be right after the colour table.
552
	 */
553
	if (bmp->ico)
554
		bmp->bitmap_offset = (intptr_t)data - (intptr_t)bmp->bmp_data;
555
	return BMP_OK;
556
}
557
 
558
 
559
/**
560
 * Finds the closest BMP within an ICO collection
561
 *
562
 * This function finds the BMP with dimensions as close to a specified set
563
 * as possible from the images in the collection.
564
 *
565
 * \param ico		the ICO collection to examine
566
 * \param width		the preferred width (0 to use ICO header width)
567
 * \param height	the preferred height (0 to use ICO header height)
568
 */
569
bmp_image *ico_find(ico_collection *ico, uint16_t width, uint16_t height) {
570
	bmp_image *bmp = NULL;
571
	ico_image *image;
572
	int x, y, cur, distance = (1 << 24);
573
 
574
	if (width == 0)
575
		width = ico->width;
576
	if (height == 0)
577
		height = ico->height;
578
	for (image = ico->first; image; image = image->next) {
579
		if ((image->bmp.width == width) && (image->bmp.height == height))
580
			return &image->bmp;
581
		x = image->bmp.width - width;
582
		y = image->bmp.height - height;
583
		cur = (x * x) + (y * y);
584
		if (cur < distance) {
585
			distance = cur;
586
			bmp = &image->bmp;
587
		}
588
	}
589
	return bmp;
590
}
591
 
592
 
593
/**
594
 * Decode a BMP
595
 *
596
 * This function decodes the BMP data such that bmp->bitmap is a valid
597
 * image. The state of bmp->decoded is set to TRUE on exit such that it
598
 * can easily be identified which BMPs are in a fully decoded state.
599
 *
600
 * \param bmp	the BMP image to decode
601
 * \return BMP_OK on success
602
 */
603
bmp_result bmp_decode(bmp_image *bmp) {
604
	uint8_t *data;
605
	uint32_t bytes;
606
	bmp_result result = BMP_OK;
607
 
608
	assert(bmp->bitmap);
609
 
610
	data = bmp->bmp_data + bmp->bitmap_offset;
611
	bytes = bmp->buffer_size - bmp->bitmap_offset;
612
 
613
	switch (bmp->encoding) {
614
		case BMP_ENCODING_RGB:
615
			if ((bmp->bpp == 24) || (bmp->bpp == 32))
616
				result = bmp_decode_rgb24(bmp, &data, bytes);
617
			else if (bmp->bpp == 16)
618
				result = bmp_decode_rgb16(bmp, &data, bytes);
619
			else
620
				result = bmp_decode_rgb(bmp, &data, bytes);
621
			break;
622
		case BMP_ENCODING_RLE8:
623
			result = bmp_decode_rle(bmp, data, bytes, 8);
624
			break;
625
		case BMP_ENCODING_RLE4:
626
			result = bmp_decode_rle(bmp, data, bytes, 4);
627
			break;
628
		case BMP_ENCODING_BITFIELDS:
629
			if (bmp->bpp == 32)
630
				result = bmp_decode_rgb24(bmp, &data, bytes);
631
			else if (bmp->bpp == 16)
632
				result = bmp_decode_rgb16(bmp, &data, bytes);
633
			else
634
				return BMP_DATA_ERROR;
635
	}
636
 
637
	if ((!bmp->ico) || (result != BMP_OK))
638
		return result;
639
 
640
	bytes = (uintptr_t)bmp->bmp_data + bmp->buffer_size - (uintptr_t)data;
641
	return bmp_decode_mask(bmp, data, bytes);
642
}
643
 
644
/**
645
 * Decode a BMP using "limited transparency"
646
 *
647
 * Bitmaps do not have native transparency support.  However, there is a
648
 * "trick" that is used in some instances in which the first pixel of the
649
 * bitmap becomes the "transparency index".  The decoding application can
650
 * replace this index with whatever background colour it chooses to
651
 * create the illusion of transparency.
652
 *
653
 * When to use transparency is at the discretion of the decoding
654
 * application.
655
 *
656
 * \param bmp		the BMP image to decode
657
 * \param colour	the colour to use as "transparent"
658
 * \return BMP_OK on success
659
 */
660
bmp_result bmp_decode_trans(bmp_image *bmp, uint32_t colour) {
661
	bmp->limited_trans = true;
662
	bmp->trans_colour = colour;
663
	return bmp_decode(bmp);
664
}
665
 
666
 
667
/**
668
 * Decode BMP data stored in 24bpp colour.
669
 *
670
 * \param bmp	the BMP image to decode
671
 * \param start	the data to decode, updated to last byte read on success
672
 * \param bytes	the number of bytes of data available
673
 * \return	BMP_OK on success
674
 *		BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly;
675
 *			in this case, the image may be partially viewable
676
 */
677
static bmp_result bmp_decode_rgb24(bmp_image *bmp, uint8_t **start, int bytes) {
678
	uint8_t *top, *bottom, *end, *data;
679
	uint32_t *scanline;
680
	uint32_t x, y;
681
	uint32_t swidth, skip;
682
	intptr_t addr;
683
	uint8_t i;
684
	uint32_t word;
685
 
686
	data = *start;
687
	swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width;
688
	top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap);
689
	if (!top)
690
		return BMP_INSUFFICIENT_MEMORY;
691
	bottom = top + (uint64_t)swidth * (bmp->height - 1);
692
	end = data + bytes;
693
	addr = ((intptr_t)data) & 3;
694
	skip = bmp->bpp >> 3;
695
	bmp->decoded = true;
696
 
697
	/* Determine transparent index */
698
	if (bmp->limited_trans) {
699
		if ((data + skip) > end)
700
			return BMP_INSUFFICIENT_DATA;
701
		if (bmp->encoding == BMP_ENCODING_BITFIELDS)
702
			bmp->transparent_index = read_uint32(data, 0);
703
		else
704
			bmp->transparent_index = data[2] | (data[1] << 8) | (data[0] << 16);
705
	}
706
 
707
	for (y = 0; y < bmp->height; y++) {
708
		while (addr != (((intptr_t)data) & 3))
709
			data++;
710
		if ((data + (skip * bmp->width)) > end)
711
			return BMP_INSUFFICIENT_DATA;
712
		if (bmp->reversed)
713
			scanline = (void *)(top + (y * swidth));
714
		else
715
			scanline = (void *)(bottom - (y * swidth));
716
		if (bmp->encoding == BMP_ENCODING_BITFIELDS) {
717
			for (x = 0; x < bmp->width; x++) {
718
				word = read_uint32(data, 0);
719
				for (i = 0; i < 4; i++)
720
					if (bmp->shift[i] > 0)
721
						scanline[x] |= ((word & bmp->mask[i]) << bmp->shift[i]);
722
					else
723
						scanline[x] |= ((word & bmp->mask[i]) >> (-bmp->shift[i]));
724
				/* 32-bit BMPs have alpha masks, but sometimes they're not utilized */
725
				if (bmp->opaque)
726
					scanline[x] |= (0xff << 24);
727
				data += skip;
728
				scanline[x] = read_uint32((uint8_t *)&scanline[x],0);
729
			}
730
		} else {
731
			for (x = 0; x < bmp->width; x++) {
732
				scanline[x] = data[2] | (data[1] << 8) | (data[0] << 16);
733
				if ((bmp->limited_trans) && (scanline[x] == bmp->transparent_index))
734
					scanline[x] = bmp->trans_colour;
735
				if (bmp->opaque)
736
					scanline[x] |= (0xff << 24);
737
				data += skip;
738
				scanline[x] = read_uint32((uint8_t *)&scanline[x],0);
739
			}
740
		}
741
	}
742
	*start = data;
743
	return BMP_OK;
744
}
745
 
746
 
747
/**
748
 * Decode BMP data stored in 16bpp colour.
749
 *
750
 * \param bmp	the BMP image to decode
751
 * \param start	the data to decode, updated to last byte read on success
752
 * \param bytes	the number of bytes of data available
753
 * \return	BMP_OK on success
754
 *		BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly;
755
 *			in this case, the image may be partially viewable
756
 */
757
static bmp_result bmp_decode_rgb16(bmp_image *bmp, uint8_t **start, int bytes) {
758
	uint8_t *top, *bottom, *end, *data;
759
	uint32_t *scanline;
760
	uint32_t x, y, swidth;
761
	intptr_t addr;
762
	uint8_t i;
763
	uint16_t word;
764
 
765
	data = *start;
766
	swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width;
767
	top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap);
768
	if (!top)
769
		return BMP_INSUFFICIENT_MEMORY;
770
	bottom = top + (uint64_t)swidth * (bmp->height - 1);
771
	end = data + bytes;
772
	addr = ((intptr_t)data) & 3;
773
	bmp->decoded = true;
774
 
775
	/* Determine transparent index */
776
	if (bmp->limited_trans) {
777
		if ((data + 2) > end)
778
			return BMP_INSUFFICIENT_DATA;
779
		bmp->transparent_index = read_uint16(data, 0);
780
	}
781
 
782
	for (y = 0; y < bmp->height; y++) {
783
		while (addr != (((intptr_t)data) & 3))
784
			data += 2;
785
		if ((data + (2 * bmp->width)) > end)
786
			return BMP_INSUFFICIENT_DATA;
787
		if (bmp->reversed)
788
			scanline = (void *)(top + (y * swidth));
789
		else
790
			scanline = (void *)(bottom - (y * swidth));
791
		if (bmp->encoding == BMP_ENCODING_BITFIELDS) {
792
			for (x = 0; x < bmp->width; x++) {
793
				word = read_uint16(data, 0);
794
				if ((bmp->limited_trans) && (word == bmp->transparent_index))
795
					scanline[x] = bmp->trans_colour;
796
				else {
797
					scanline[x] = 0;
798
					for (i = 0; i < 4; i++)
799
						if (bmp->shift[i] > 0)
800
							scanline[x] |= ((word & bmp->mask[i]) << bmp->shift[i]);
801
						else
802
							scanline[x] |= ((word & bmp->mask[i]) >> (-bmp->shift[i]));
803
					if (bmp->opaque)
804
						scanline[x] |= (0xff << 24);
805
				}
806
				data += 2;
807
				scanline[x] = read_uint32((uint8_t *)&scanline[x],0);
808
			}
809
		} else {
810
			for (x = 0; x < bmp->width; x++) {
811
				word = read_uint16(data, 0);
812
				if ((bmp->limited_trans) && (word == bmp->transparent_index))
813
					scanline[x] = bmp->trans_colour;
814
				else {
815
					/* 16-bit RGB defaults to RGB555 */
816
					scanline[x] = ((word & (31 << 0)) << 19) |
817
							((word & (31 << 5)) << 6) |
818
							((word & (31 << 10)) >> 7);
819
				}
820
				if (bmp->opaque)
821
					scanline[x] |= (0xff << 24);
822
				data += 2;
823
				scanline[x] = read_uint32((uint8_t *)&scanline[x],0);
824
			}
825
		}
826
	}
827
	*start = data;
828
	return BMP_OK;
829
}
830
 
831
 
832
/**
833
 * Decode BMP data stored with a palette and in 8bpp colour or less.
834
 *
835
 * \param bmp	the BMP image to decode
836
 * \param start	the data to decode, updated to last byte read on success
837
 * \param bytes	the number of bytes of data available
838
 * \return	BMP_OK on success
839
 *		BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly;
840
 *			in this case, the image may be partially viewable
841
 */
842
static bmp_result bmp_decode_rgb(bmp_image *bmp, uint8_t **start, int bytes) {
843
	uint8_t *top, *bottom, *end, *data;
844
	uint32_t *scanline;
845
	intptr_t addr;
846
	uint32_t x, y, swidth;
847
	uint8_t bit_shifts[8];
848
	uint8_t ppb = 8 / bmp->bpp;
849
	uint8_t bit_mask = (1 << bmp->bpp) - 1;
850
	uint8_t cur_byte = 0, bit, i;
851
 
852
	for (i = 0; i < ppb; i++)
853
	    bit_shifts[i] = 8 - ((i + 1) * bmp->bpp);
854
 
855
	data = *start;
856
	swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width;
857
	top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap);
858
	if (!top)
859
		return BMP_INSUFFICIENT_MEMORY;
860
	bottom = top + (uint64_t)swidth * (bmp->height - 1);
861
	end = data + bytes;
862
	addr = ((intptr_t)data) & 3;
863
	bmp->decoded = true;
864
 
865
	/* Determine transparent index */
866
	if (bmp->limited_trans)
867
		bmp->transparent_index = bmp->colour_table[(*data >> bit_shifts[0]) & bit_mask];
868
 
869
	for (y = 0; y < bmp->height; y++) {
870
		while (addr != (((intptr_t)data) & 3))
871
			data++;
872
		bit = 8;
873
		if ((data + (bmp->width / ppb)) > end)
874
			return BMP_INSUFFICIENT_DATA;
875
		if (bmp->reversed)
876
			scanline = (void *)(top + (y * swidth));
877
		else
878
			scanline = (void *)(bottom - (y * swidth));
879
		for (x = 0; x < bmp->width; x++) {
880
			if (bit >= ppb) {
881
				bit = 0;
882
				cur_byte = *data++;
883
			}
884
			scanline[x] = bmp->colour_table[(cur_byte >> bit_shifts[bit++]) & bit_mask];
885
			if ((bmp->limited_trans) && (scanline[x] == bmp->transparent_index))
886
				scanline[x] = bmp->trans_colour;
887
		}
888
	}
889
	*start = data;
890
	return BMP_OK;
891
}
892
 
893
 
894
/**
895
 * Decode a 1bpp mask for an ICO
896
 *
897
 * \param bmp	the BMP image to decode
898
 * \param data	the data to decode
899
 * \param bytes	the number of bytes of data available
900
 * \return BMP_OK on success
901
 */
902
static bmp_result bmp_decode_mask(bmp_image *bmp, uint8_t *data, int bytes) {
903
	uint8_t *top, *bottom, *end;
904
	uint32_t *scanline;
905
	intptr_t addr;
906
	uint32_t x, y, swidth;
907
	uint32_t cur_byte = 0;
908
 
909
	swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width;
910
	top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap);
911
	if (!top)
912
		return BMP_INSUFFICIENT_MEMORY;
913
	bottom = top + (uint64_t)swidth * (bmp->height - 1);
914
	end = data + bytes;
915
	addr = ((intptr_t)data) & 3;
916
 
917
	for (y = 0; y < bmp->height; y++) {
918
		while (addr != (((intptr_t)data) & 3))
919
			data++;
920
		if ((data + (bmp->width >> 3)) > end)
921
			return BMP_INSUFFICIENT_DATA;
922
		scanline = (void *)(bottom - (y * swidth));
923
		for (x = 0; x < bmp->width; x++) {
924
			if ((x & 7) == 0)
925
				cur_byte = *data++;
926
			if ((cur_byte & 128) == 0) {
927
				scanline[x] = read_uint32((uint8_t *)&scanline[x], 0);
928
				scanline[x] |= (0xff << 24);
929
				scanline[x] = read_uint32((uint8_t *)&scanline[x], 0);
930
			}
931
			cur_byte = cur_byte << 1;
932
		}
933
	}
934
	return BMP_OK;
935
}
936
 
937
 
938
/**
939
 * Decode BMP data stored encoded in either RLE4 or RLE8.
940
 *
941
 * \param bmp	the BMP image to decode
942
 * \param data	the data to decode
943
 * \param bytes	the number of bytes of data available
944
 * \param size	the size of the RLE tokens (4 or 8)
945
 * \return	BMP_OK on success
946
 *		BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly;
947
 *			in this case, the image may be partially viewable
948
 */
949
static bmp_result bmp_decode_rle(bmp_image *bmp, uint8_t *data, int bytes, int size) {
950
	uint8_t *top, *bottom, *end;
951
	uint32_t *scanline;
952
	uint32_t swidth;
953
	uint32_t i, length, pixels_left;
954
	uint32_t x = 0, y = 0, last_y = 0;
955
	uint32_t pixel = 0, pixel2;
956
 
957
	if (bmp->ico)
958
		return BMP_DATA_ERROR;
959
 
960
	swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width;
961
	top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap);
962
	if (!top)
963
		return BMP_INSUFFICIENT_MEMORY;
964
	bottom = top + (uint64_t)swidth * (bmp->height - 1);
965
	end = data + bytes;
966
	bmp->decoded = true;
967
 
968
	do {
969
		if (data + 2 > end)
970
			return BMP_INSUFFICIENT_DATA;
971
		length = *data++;
972
		if (length == 0) {
973
			length = *data++;
974
			if (length == 0) {
975
				/* 00 - 00 means end of scanline */
976
				x = 0;
977
				if (last_y == y) {
978
					if (++y > bmp->height)
979
						return BMP_DATA_ERROR;
980
				}
981
				last_y = y;
982
			} else if (length == 1) {
983
				/* 00 - 01 means end of RLE data */
984
				return BMP_OK;
985
			} else if (length == 2) {
986
				/* 00 - 02 - XX - YY means move cursor */
987
				if (data + 2 > end)
988
					return BMP_INSUFFICIENT_DATA;
989
				x += *data++;
990
				if (x >= bmp->width)
991
					return BMP_DATA_ERROR;
992
				y += *data++;
993
				if (y >= bmp->height)
994
					return BMP_DATA_ERROR;
995
			} else {
996
				/* 00 - NN means escape NN pixels */
997
				if (bmp->reversed) {
998
					pixels_left = (y + 1) * bmp->width - x;
999
					scanline = (void *)(top + (y * swidth));
1000
				} else {
1001
					pixels_left = (bmp->height - y + 1) * bmp->width - x;
1002
					scanline = (void *)(bottom - (y * swidth));
1003
				}
1004
				if (length > pixels_left)
1005
					length = pixels_left;
1006
				if (data + length > end)
1007
					return BMP_INSUFFICIENT_DATA;
1008
 
1009
				/* the following code could be easily optimised by simply
1010
				 * checking the bounds on entry and using some simply copying
1011
				 * routines if so */
1012
				if (size == 8) {
1013
					for (i = 0; i < length; i++) {
1014
						if (x >= bmp->width) {
1015
							x = 0;
1016
							if (++y > bmp->height)
1017
								return BMP_DATA_ERROR;
1018
							scanline -= bmp->width;
1019
						}
1020
						scanline[x++] = bmp->colour_table[(int)*data++];
1021
					}
1022
				} else {
1023
					for (i = 0; i < length; i++) {
1024
						if (x >= bmp->width) {
1025
							x = 0;
1026
							if (++y > bmp->height)
1027
								return BMP_DATA_ERROR;
1028
							scanline -= bmp->width;
1029
						}
1030
						if ((i & 1) == 0) {
1031
							pixel = *data++;
1032
							scanline[x++] = bmp->colour_table
1033
									[pixel >> 4];
1034
						} else {
1035
							scanline[x++] = bmp->colour_table
1036
									[pixel & 0xf];
1037
						}
1038
					}
1039
					length = (length + 1) >> 1;
1040
				}
1041
				if ((length & 1) && (*data++ != 0x00))
1042
					return BMP_DATA_ERROR;
1043
 
1044
			}
1045
		} else {
1046
			/* NN means perform RLE for NN pixels */
1047
			if (bmp->reversed) {
1048
				pixels_left = (y + 1) * bmp->width - x;
1049
				scanline = (void *)(top + (y * swidth));
1050
			} else {
1051
				pixels_left = (bmp->height - y + 1) * bmp->width - x;
1052
				scanline = (void *)(bottom - (y * swidth));
1053
			}
1054
			if (length > pixels_left)
1055
				length = pixels_left;
1056
 
1057
			/* boundary checking */
1058
			if (data + 1 > end)
1059
				return BMP_INSUFFICIENT_DATA;
1060
 
1061
			/* the following code could be easily optimised by simply
1062
			 * checking the bounds on entry and using some simply copying
1063
			 * routines if so */
1064
			if (size == 8) {
1065
				pixel = bmp->colour_table[(int)*data++];
1066
				for (i = 0; i < length; i++) {
1067
					if (x >= bmp->width) {
1068
						x = 0;
1069
						if (++y > bmp->height)
1070
							return BMP_DATA_ERROR;
1071
						scanline -= bmp->width;
1072
					}
1073
					scanline[x++] = pixel;
1074
				}
1075
			} else {
1076
				pixel2 = *data++;
1077
				pixel = bmp->colour_table[pixel2 >> 4];
1078
				pixel2 = bmp->colour_table[pixel2 & 0xf];
1079
				for (i = 0; i < length; i++) {
1080
					if (x >= bmp->width) {
1081
						x = 0;
1082
						if (++y > bmp->height)
1083
							return BMP_DATA_ERROR;
1084
						scanline -= bmp->width;
1085
					}
1086
					if ((i & 1) == 0)
1087
						scanline[x++] = pixel;
1088
					else
1089
						scanline[x++] = pixel2;
1090
				}
1091
			}
1092
		}
1093
	} while (data < end);
1094
	return BMP_OK;
1095
}
1096
 
1097
 
1098
/**
1099
 * Finalise a BMP prior to destruction.
1100
 *
1101
 * \param bmp	the BMP image to finalise
1102
 */
1103
void bmp_finalise(bmp_image *bmp) {
1104
	if (bmp->bitmap)
1105
		bmp->bitmap_callbacks.bitmap_destroy(bmp->bitmap);
1106
	bmp->bitmap = NULL;
1107
	if (bmp->colour_table)
1108
		free(bmp->colour_table);
1109
	bmp->colour_table = NULL;
1110
}
1111
 
1112
 
1113
/**
1114
 * Finalise an ICO prior to destruction.
1115
 *
1116
 * \param ico	the ICO image to finalise
1117
 */
1118
void ico_finalise(ico_collection *ico) {
1119
	ico_image *image;
1120
 
1121
	for (image = ico->first; image; image = image->next)
1122
		bmp_finalise(&image->bmp);
1123
	while (ico->first) {
1124
		image = ico->first;
1125
		ico->first = image->next;
1126
		free(image);
1127
	}
1128
}