io-bmp.c 33.2 KB
Newer Older
1
/* -*- mode: C; c-file-style: "linux" -*- */
2
3
4
/* GdkPixbuf library - Windows Bitmap image loader
 *
 * Copyright (C) 1999 The Free Software Foundation
Mark Crichton's avatar
Mark Crichton committed
5
 *
6
7
8
9
 * Authors: Arjan van de Ven <arjan@fenrus.demon.nl>
 *          Federico Mena-Quintero <federico@gimp.org>
 *
 * Based on io-ras.c
Mark Crichton's avatar
Mark Crichton committed
10
11
 *
 * This library is free software; you can redistribute it and/or
12
 * modify it under the terms of the GNU Lesser General Public
Mark Crichton's avatar
Mark Crichton committed
13
14
15
16
17
18
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
19
 * Lesser General Public License for more details.
Mark Crichton's avatar
Mark Crichton committed
20
 *
21
 * You should have received a copy of the GNU Lesser General Public
22
23
24
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
Mark Crichton's avatar
Mark Crichton committed
25
26
27
28
 */

#include <config.h>
#include <stdio.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
29
#ifdef HAVE_UNISTD_H
30
#include <unistd.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
31
#endif
32
#include <string.h>
33
34
#include "gdk-pixbuf-private.h"
#include "gdk-pixbuf-io.h"
35

Matthias Clasen's avatar
Matthias Clasen committed
36
#define DUMPBIH 0
37

38

39

40
41
42
43
44
45
#if 0
/* If these structures were unpacked, they would define the two headers of the
 * BMP file.  After them comes the palette, and then the image data.
 *
 * We do not use these structures; we just keep them here for reference.
 */
46
struct BitmapFileHeader {
47
48
49
50
	guint16 magic;
	guint32 file_size;
	guint32 reserved;
	guint32 data_offset;
51
52
53
};

struct BitmapInfoHeader {
54
55
56
57
58
59
60
61
62
63
64
	guint32 header_size;
	guint32 width;
	guint32 height;
	guint16 planes;
	guint16 bpp;
	guint32 compression;
	guint32 data_size;
	guint32 x_ppm;
	guint32 y_ppm;
	guint32 n_colors;
	guint32 n_important_colors;
65
};
66
#endif
67

68
/* Compression values */
69
70
71
72
73
74

#define BI_RGB 0
#define BI_RLE8 1
#define BI_RLE4 2
#define BI_BITFIELDS 3

75
76
77
78
79
80
81
82
83
/* State machine */
typedef enum {
	READ_STATE_HEADERS,	/* Reading the bitmap file header and bitmap info header */
	READ_STATE_PALETTE,	/* Reading the palette */
	READ_STATE_BITMASKS,	/* Reading the bitmasks for BI_BITFIELDS */
	READ_STATE_DATA,	/* Reading the actual image data */
	READ_STATE_ERROR,	/* An error occurred; further data will be ignored */
	READ_STATE_DONE		/* Done reading the image; further data will be ignored */
} ReadState;
84

85
86
87
/*

DumpBIH printf's the values in a BitmapInfoHeader to the screen, for
88
89
90
91
debugging purposes.

*/
#if DUMPBIH
92
static void DumpBIH(unsigned char *BIH)
93
{
94
	printf("biSize      = %i \n",
95
96
	       (int) (BIH[3] << 24) + (BIH[2] << 16) + (BIH[1] << 8) +
	       (BIH[0]));
97
	printf("biWidth     = %i \n",
98
99
	       (int) (BIH[7] << 24) + (BIH[6] << 16) + (BIH[5] << 8) +
	       (BIH[4]));
100
	printf("biHeight    = %i \n",
101
	       (int) (BIH[11] << 24) + (BIH[10] << 16) + (BIH[9] << 8) +
102
	       (BIH[8]));
103
104
	printf("biPlanes    = %i \n", (int) (BIH[13] << 8) + (BIH[12]));
	printf("biBitCount  = %i \n", (int) (BIH[15] << 8) + (BIH[14]));
105
	printf("biCompress  = %i \n",
106
	       (int) (BIH[19] << 24) + (BIH[18] << 16) + (BIH[17] << 8) +
107
108
	       (BIH[16]));
	printf("biSizeImage = %i \n",
109
	       (int) (BIH[23] << 24) + (BIH[22] << 16) + (BIH[21] << 8) +
110
111
	       (BIH[20]));
	printf("biXPels     = %i \n",
112
	       (int) (BIH[27] << 24) + (BIH[26] << 16) + (BIH[25] << 8) +
113
114
	       (BIH[24]));
	printf("biYPels     = %i \n",
115
	       (int) (BIH[31] << 24) + (BIH[30] << 16) + (BIH[29] << 8) +
116
117
	       (BIH[28]));
	printf("biClrUsed   = %i \n",
118
	       (int) (BIH[35] << 24) + (BIH[34] << 16) + (BIH[33] << 8) +
119
120
	       (BIH[32]));
	printf("biClrImprtnt= %i \n",
121
	       (int) (BIH[39] << 24) + (BIH[38] << 16) + (BIH[37] << 8) +
122
123
	       (BIH[36]));
}
124
125
126
#endif
/* struct headerpair contains the decoded width/height/depth info for
   the current bitmap */
127

128
struct headerpair {
129
130
131
	guint32 size;
	gint32 width;
	gint32 height;
132
	guint depth;
133
	guint Negative;		/* Negative = 1 -> top down BMP,
134
				   Negative = 0 -> bottom up BMP */
135
	guint  n_colors;
136
};
137

138
139
/* Data needed for the "state" during decompression */
struct bmp_compression_state {
140
	gint phase;
141
142
143
144
	gint run;
	gint count;
	gint x, y;
	guchar *p;
145
};
146
147
148
149

/* Progressive loading */

struct bmp_progressive_state {
150
	GdkPixbufModuleSizeFunc size_func;
151
152
	GdkPixbufModulePreparedFunc prepared_func;
	GdkPixbufModuleUpdatedFunc updated_func;
153
154
	gpointer user_data;

155
156
	ReadState read_state;

157
158
	guint LineWidth;
	guint Lines;		/* # of finished lines */
159

160
	guchar *buff;
161
162
	guint BufferSize;
	guint BufferDone;
163
164

	guchar (*Colormap)[3];
165

166
	gint Type;		/*
167
				   32 = RGB + alpha
168
				   24 = RGB
169
				   16 = RGB
170
171
				   4  = 4 bpp colormapped
				   8  = 8 bpp colormapped
172
				   1  = 1 bit bitonal
173
				 */
174
	guint Compressed;
175
	struct bmp_compression_state compr;
176
177
178
179


	struct headerpair Header;	/* Decoded (BE->CPU) header */

180
181
182
183
	/* Bit masks, shift amounts, and significant bits for BI_BITFIELDS coding */
	int r_mask, r_shift, r_bits;
	int g_mask, g_shift, g_bits;
	int b_mask, b_shift, b_bits;
184
185
186
187

	GdkPixbuf *pixbuf;	/* Our "target" */
};

188
static gpointer
189
190
191
gdk_pixbuf__bmp_image_begin_load(GdkPixbufModuleSizeFunc size_func,
                                 GdkPixbufModulePreparedFunc prepared_func,
				 GdkPixbufModuleUpdatedFunc updated_func,
Havoc Pennington's avatar
Havoc Pennington committed
192
                                 gpointer user_data,
Havoc Pennington's avatar
Havoc Pennington committed
193
                                 GError **error);
Federico Mena Quintero's avatar
Federico Mena Quintero committed
194

195
196
197
198
199
static gboolean gdk_pixbuf__bmp_image_stop_load(gpointer data, GError **error);
static gboolean gdk_pixbuf__bmp_image_load_increment(gpointer data,
                                                     const guchar * buf,
                                                     guint size,
                                                     GError **error);
200

Mark Crichton's avatar
Mark Crichton committed
201

202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/* Picks up a 32-bit little-endian integer starting at the specified location.
 * Does it by hand instead of dereferencing a simple (gint *) cast due to
 * alignment constraints many platforms.
 */
static int
lsb_32 (guchar *src)
{
	return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
}

/* Same as above, but for 16-bit little-endian integers. */
static short
lsb_16 (guchar *src)
{
	return src[0] | (src[1] << 8);
}

219
220
221
static gboolean grow_buffer (struct bmp_progressive_state *State,
                             GError **error)
{
222
223
224
225
226
227
228
229
230
231
232
233
234
  guchar *tmp;

  if (State->BufferSize == 0) {
    g_set_error (error,
		 GDK_PIXBUF_ERROR,
		 GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
		 _("BMP image has bogus header data"));
    State->read_state = READ_STATE_ERROR;
    return FALSE;
  }

  tmp = g_try_realloc (State->buff, State->BufferSize);

235
  if (!tmp) {
236
237
238
239
240
241
242
    g_set_error (error,
		 GDK_PIXBUF_ERROR,
		 GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
		 _("Not enough memory to load bitmap image"));
    State->read_state = READ_STATE_ERROR;
    return FALSE;
  }
243

244
  State->buff = tmp;
245
246
247
  return TRUE;
}

248
249
250
static gboolean DecodeHeader(unsigned char *BFH, unsigned char *BIH,
                             struct bmp_progressive_state *State,
                             GError **error)
251
{
252
253
	gint clrUsed;

254
        /* FIXME this is totally unrobust against bogus image data. */
255

256
257
	if (State->BufferSize < lsb_32 (&BIH[0]) + 14) {
		State->BufferSize = lsb_32 (&BIH[0]) + 14;
258
		if (!grow_buffer (State, error))
Matthias Clasen's avatar
Matthias Clasen committed
259
			return FALSE;
260
261
262
		return TRUE;
	}

263
264
#if DUMPBIH
	DumpBIH(BIH);
265
#endif    
266

267
	State->Header.size = lsb_32 (&BIH[0]);
268
	if (State->Header.size == 40) {
269
270
271
272
		State->Header.width = lsb_32 (&BIH[4]);
		State->Header.height = lsb_32 (&BIH[8]);
		State->Header.depth = lsb_16 (&BIH[14]);
		State->Compressed = lsb_32 (&BIH[16]);
273
	} else if (State->Header.size == 12) {
274
275
276
		State->Header.width = lsb_16 (&BIH[4]);
		State->Header.height = lsb_16 (&BIH[6]);
		State->Header.depth = lsb_16 (&BIH[10]);
277
		State->Compressed = BI_RGB;
278
279
280
281
282
	} else {
		g_set_error (error,
			     GDK_PIXBUF_ERROR,
			     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
			     _("BMP image has unsupported header size"));
283
		State->read_state = READ_STATE_ERROR;
284
285
		return FALSE;
	}
286

287
288
289
290
291
	if (State->Header.size == 12)
		clrUsed = 1 << State->Header.depth;
	else
		clrUsed = (int) (BIH[35] << 24) + (BIH[34] << 16) + (BIH[33] << 8) + (BIH[32]);

292
293
294
295
296
297
298
299
300
301
302
303
304
305
	if (clrUsed != 0)
		State->Header.n_colors = clrUsed;
	else
            State->Header.n_colors = 1 << State->Header.depth;
	
	if (State->Header.n_colors > 1 << State->Header.depth) {
		g_set_error (error,
			     GDK_PIXBUF_ERROR,
			     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
			     _("BMP image has bogus header data"));
		State->read_state = READ_STATE_ERROR;
		return FALSE;
	}

306
	State->Type = State->Header.depth;	/* This may be less trivial someday */
307

308
	/* Negative heights indicates bottom-down pixelorder */
309
310
311
312
	if (State->Header.height < 0) {
		State->Header.height = -State->Header.height;
		State->Header.Negative = 1;
	}
313
314
315
316
317
318
319
320
321
322

	if (State->Header.Negative && 
	    (State->Compressed != BI_RGB && State->Compressed != BI_BITFIELDS))
	{
		g_set_error (error,
			     GDK_PIXBUF_ERROR,
			     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
			     _("Topdown BMP images cannot be compressed"));
		State->read_state = READ_STATE_ERROR;
		return FALSE;
323
	}
324

325
	if (State->Header.width <= 0 || State->Header.height == 0 ||
326
327
	    (State->Compressed == BI_RLE4 && State->Type != 4)    ||
	    (State->Compressed == BI_RLE8 && State->Type != 8)	  ||
328
	    (State->Compressed == BI_BITFIELDS && !(State->Type == 16 || State->Type == 32)) ||
329
	    (State->Compressed > BI_BITFIELDS)) {
330
331
332
333
		g_set_error (error,
			     GDK_PIXBUF_ERROR,
			     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
			     _("BMP image has bogus header data"));
334
		State->read_state = READ_STATE_ERROR;
335
336
337
		return FALSE;
	}

338
339
	if (State->Type == 32)
		State->LineWidth = State->Header.width * 4;
340
	else if (State->Type == 24)
341
		State->LineWidth = State->Header.width * 3;
342
343
344
	else if (State->Type == 16)
		State->LineWidth = State->Header.width * 2;
	else if (State->Type == 8)
345
		State->LineWidth = State->Header.width * 1;
346
	else if (State->Type == 4)
347
		State->LineWidth = (State->Header.width + 1) / 2;
348
	else if (State->Type == 1) {
349
350
351
		State->LineWidth = State->Header.width / 8;
		if ((State->Header.width & 7) != 0)
			State->LineWidth++;
352
353
354
355
356
	} else {
		g_set_error (error,
			     GDK_PIXBUF_ERROR,
			     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
			     _("BMP image has bogus header data"));
357
		State->read_state = READ_STATE_ERROR;
358
		return FALSE;
359
	}
360

361
	/* Pad to a 32 bit boundary */
362
363
	if (((State->LineWidth % 4) > 0)
	    && (State->Compressed == BI_RGB || State->Compressed == BI_BITFIELDS))
364
365
		State->LineWidth = (State->LineWidth / 4) * 4 + 4;

366
	if (State->pixbuf == NULL) {
367
368
369
370
371
372
373
374
375
376
377
378
		if (State->size_func) {
			gint width = State->Header.width;
			gint height = State->Header.height;

			(*State->size_func) (&width, &height, State->user_data);
			if (width == 0 || height == 0) {
				State->read_state = READ_STATE_DONE;
				State->BufferSize = 0;
				return TRUE;
			}
		}

379
380
381
		if (State->Type == 32 || 
		    State->Compressed == BI_RLE4 || 
		    State->Compressed == BI_RLE8)
382
			State->pixbuf =
383
384
385
				gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8,
					       (gint) State->Header.width,
					       (gint) State->Header.height);
386
387
		else
			State->pixbuf =
388
389
390
391
392
393
394
395
396
				gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8,
					       (gint) State->Header.width,
					       (gint) State->Header.height);
		
		if (State->pixbuf == NULL) {
			g_set_error (error,
				     GDK_PIXBUF_ERROR,
				     GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
				     _("Not enough memory to load bitmap image"));
397
			State->read_state = READ_STATE_ERROR;
398
399
400
			return FALSE;
			}
		
401
402
		if (State->prepared_func != NULL)
			/* Notify the client that we are ready to go */
Havoc Pennington's avatar
Havoc Pennington committed
403
			(*State->prepared_func) (State->pixbuf, NULL, State->user_data);
404
405
406
407
408
409
410
		
		/* make all pixels initially transparent */
		if (State->Compressed == BI_RLE4 || State->Compressed == BI_RLE8) {
			memset (State->pixbuf->pixels, 0, State->pixbuf->rowstride * State->Header.height);
			State->compr.p = State->pixbuf->pixels 
				+ State->pixbuf->rowstride * (State->Header.height- 1);
		}
411
	}
412
	
413
	State->BufferDone = 0;
414
415
	if (State->Type <= 8) {
		State->read_state = READ_STATE_PALETTE;
416
		State->BufferSize = lsb_32 (&BFH[10]) - 14 - State->Header.size; 
417
	} else if (State->Compressed == BI_RGB) {
418
419
420
421
422
423
424
425
426
427
428
429
		if (State->BufferSize < lsb_32 (&BFH[10]))
		{
			/* skip over padding between headers and image data */
			State->read_state = READ_STATE_HEADERS;
			State->BufferDone = State->BufferSize;
			State->BufferSize = lsb_32 (&BFH[10]);
		}
		else
		{
			State->read_state = READ_STATE_DATA;
			State->BufferSize = State->LineWidth;
		}
430
431
432
	} else if (State->Compressed == BI_BITFIELDS) {
		State->read_state = READ_STATE_BITMASKS;
		State->BufferSize = 12;
433
434
435
436
437
438
439
440
	} else {
		g_set_error (error,
			     GDK_PIXBUF_ERROR,
			     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
			     _("BMP image has bogus header data"));
		State->read_state = READ_STATE_ERROR;
		return FALSE;
	}
441

442
443
	if (!grow_buffer (State, error)) 
		return FALSE;
444
445
446
447

        return TRUE;
}

448
449
450
static gboolean DecodeColormap (guchar *buff,
				struct bmp_progressive_state *State,
				GError **error)
451
452
{
	gint i;
453
	gint samples;
454

455
456
	g_assert (State->read_state == READ_STATE_PALETTE);

457
458
459
460
461
462
463
464
	samples = (State->Header.size == 12 ? 3 : 4);
	if (State->BufferSize < State->Header.n_colors * samples) {
		State->BufferSize = State->Header.n_colors * samples;
		if (!grow_buffer (State, error))
			return FALSE;
		return TRUE;
	}

465
	State->Colormap = g_malloc ((1 << State->Header.depth) * sizeof (*State->Colormap));
466
	for (i = 0; i < State->Header.n_colors; i++)
467
468

	{
469
470
471
		State->Colormap[i][0] = buff[i * samples];
		State->Colormap[i][1] = buff[i * samples + 1];
		State->Colormap[i][2] = buff[i * samples + 2];
472
473
474
475
476
477
#ifdef DUMPCMAP
		g_print ("color %d %x %x %x\n", i,
			 State->Colormap[i][0],
			 State->Colormap[i][1],
			 State->Colormap[i][2]);
#endif
478
479
	}

480
481
	State->read_state = READ_STATE_DATA;

482
	State->BufferDone = 0;
483
	if (!(State->Compressed == BI_RGB || State->Compressed == BI_BITFIELDS))
484
485
486
		State->BufferSize = 2;
	else
		State->BufferSize = State->LineWidth;
487
488
489
	
	if (!grow_buffer (State, error))
		return FALSE;
490

491
	return TRUE;
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
}

/* Finds the lowest set bit and the number of set bits */
static void
find_bits (int n, int *lowest, int *n_set)
{
	int i;

	*n_set = 0;

	for (i = 31; i >= 0; i--)
		if (n & (1 << i)) {
			*lowest = i;
			(*n_set)++;
		}
}

/* Decodes the 3 shorts that follow for the bitmasks for BI_BITFIELDS coding */
510
511
512
513
static gboolean
decode_bitmasks (guchar *buf,
		 struct bmp_progressive_state *State, 
		 GError **error)
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
{
	State->r_mask = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
	buf += 4;

	State->g_mask = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
	buf += 4;

	State->b_mask = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);

	find_bits (State->r_mask, &State->r_shift, &State->r_bits);
	find_bits (State->g_mask, &State->g_shift, &State->g_bits);
	find_bits (State->b_mask, &State->b_shift, &State->b_bits);

	if (State->r_bits == 0 || State->g_bits == 0 || State->b_bits == 0) {
		State->r_mask = 0x7c00;
		State->r_shift = 10;
		State->g_mask = 0x03e0;
		State->g_shift = 5;
		State->b_mask = 0x001f;
		State->b_shift = 0;

		State->r_bits = State->g_bits = State->b_bits = 5;
	}

	State->read_state = READ_STATE_DATA;
	State->BufferDone = 0;
	State->BufferSize = State->LineWidth;
541
542
543
544
	if (!grow_buffer (State, error)) 
		return FALSE;

	return TRUE;
545
546
}

547
/*
548
549
550
551
552
 * func - called when we have pixmap created (but no image data)
 * user_data - passed as arg 1 to func
 * return context (opaque to user)
 */

553
static gpointer
554
555
556
gdk_pixbuf__bmp_image_begin_load(GdkPixbufModuleSizeFunc size_func,
                                 GdkPixbufModulePreparedFunc prepared_func,
				 GdkPixbufModuleUpdatedFunc updated_func,
Havoc Pennington's avatar
Havoc Pennington committed
557
                                 gpointer user_data,
Havoc Pennington's avatar
Havoc Pennington committed
558
                                 GError **error)
559
560
{
	struct bmp_progressive_state *context;
561
	
562
	context = g_new0(struct bmp_progressive_state, 1);
563
	context->size_func = size_func;
564
565
566
567
	context->prepared_func = prepared_func;
	context->updated_func = updated_func;
	context->user_data = user_data;

568
569
	context->read_state = READ_STATE_HEADERS;

570
571
572
	context->BufferSize = 26;
	context->buff = g_malloc(26);
	context->BufferDone = 0;
573
	/* 14 for the BitmapFileHeader, 12 for the BitmapImageHeader */
574

575
	context->Colormap = NULL;
576
577
578
579
580
581

	context->Lines = 0;

	context->Type = 0;

	memset(&context->Header, 0, sizeof(struct headerpair));
582
	memset(&context->compr, 0, sizeof(struct bmp_compression_state));
583
584
585


	context->pixbuf = NULL;
586
	
587
588
589
590
591
592
593
594
	return (gpointer) context;
}

/*
 * context - returned from image_begin_load
 *
 * free context, unref gdk_pixbuf
 */
595
static gboolean gdk_pixbuf__bmp_image_stop_load(gpointer data, GError **error)
596
597
598
599
{
	struct bmp_progressive_state *context =
	    (struct bmp_progressive_state *) data;

600
601
        /* FIXME this thing needs to report errors if
         * we have unused image data
602
         */
603
	
604
	g_return_val_if_fail(context != NULL, TRUE);
605

606
607
	if (context->Colormap != NULL)
		g_free(context->Colormap);
608
609

	if (context->pixbuf)
610
		g_object_unref(context->pixbuf);
611

612
	g_free(context->buff);
613
	g_free(context);
614
615

        return TRUE;
616
617
618
}


619
620
621
622
623
624
/*
The OneLineXX functions are called when 1 line worth of data is present.
OneLine24 is the 24 bpp-version.
*/
static void OneLine32(struct bmp_progressive_state *context)
{
625
	int i;
626
627
	guchar *pixels;
	guchar *src;
628

629
630
631
	if (!context->Header.Negative)
		pixels = (context->pixbuf->pixels +
			  context->pixbuf->rowstride * (context->Header.height - context->Lines - 1));
632
	else
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
		pixels = (context->pixbuf->pixels +
			  context->pixbuf->rowstride * context->Lines);

	src = context->buff;

	if (context->Compressed == BI_BITFIELDS) {
		int r_lshift, r_rshift;
		int g_lshift, g_rshift;
		int b_lshift, b_rshift;

		r_lshift = 8 - context->r_bits;
		g_lshift = 8 - context->g_bits;
		b_lshift = 8 - context->b_bits;

		r_rshift = context->r_bits - r_lshift;
		g_rshift = context->g_bits - g_lshift;
		b_rshift = context->b_bits - b_lshift;
650

651
652
653
654
655
656
657
658
659
660
661
662
		for (i = 0; i < context->Header.width; i++) {
			int v, r, g, b;

			v = src[0] | (src[1] << 8) | (src[2] << 16);

			r = (v & context->r_mask) >> context->r_shift;
			g = (v & context->g_mask) >> context->g_shift;
			b = (v & context->b_mask) >> context->b_shift;

			*pixels++ = (r << r_lshift) | (r >> r_rshift);
			*pixels++ = (g << g_lshift) | (g >> g_rshift);
			*pixels++ = (b << b_lshift) | (b >> b_rshift);
663
			*pixels++ = 0xff;
664
665
666
667
668
669
670
671

			src += 4;
		}
	} else
		for (i = 0; i < context->Header.width; i++) {
			*pixels++ = src[2];
			*pixels++ = src[1];
			*pixels++ = src[0];
672
			*pixels++ = 0xff;
673
674
675

			src += 4;
		}
676
677
}

678
679
680
681
682
683
static void OneLine24(struct bmp_progressive_state *context)
{
	gint X;
	guchar *Pixels;

	X = 0;
684
	if (context->Header.Negative == 0)
685
686
687
		Pixels = (context->pixbuf->pixels +
			  context->pixbuf->rowstride *
			  (context->Header.height - context->Lines - 1));
688
	else
689
690
691
		Pixels = (context->pixbuf->pixels +
			  context->pixbuf->rowstride *
			  context->Lines);
692
	while (X < context->Header.width) {
693
694
695
		Pixels[X * 3 + 0] = context->buff[X * 3 + 2];
		Pixels[X * 3 + 1] = context->buff[X * 3 + 1];
		Pixels[X * 3 + 2] = context->buff[X * 3 + 0];
696
697
698
699
700
		X++;
	}

}

701
702
static void OneLine16(struct bmp_progressive_state *context)
{
703
704
705
	int i;
	guchar *pixels;
	guchar *src;
706

707
708
709
	if (!context->Header.Negative)
		pixels = (context->pixbuf->pixels +
			  context->pixbuf->rowstride * (context->Header.height - context->Lines - 1));
710
	else
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
		pixels = (context->pixbuf->pixels +
			  context->pixbuf->rowstride * context->Lines);

	src = context->buff;

	if (context->Compressed == BI_BITFIELDS) {
		int r_lshift, r_rshift;
		int g_lshift, g_rshift;
		int b_lshift, b_rshift;

		r_lshift = 8 - context->r_bits;
		g_lshift = 8 - context->g_bits;
		b_lshift = 8 - context->b_bits;

		r_rshift = context->r_bits - r_lshift;
		g_rshift = context->g_bits - g_lshift;
		b_rshift = context->b_bits - b_lshift;

		for (i = 0; i < context->Header.width; i++) {
			int v, r, g, b;

			v = (int) src[0] | ((int) src[1] << 8);

			r = (v & context->r_mask) >> context->r_shift;
			g = (v & context->g_mask) >> context->g_shift;
			b = (v & context->b_mask) >> context->b_shift;

			*pixels++ = (r << r_lshift) | (r >> r_rshift);
			*pixels++ = (g << g_lshift) | (g >> g_rshift);
			*pixels++ = (b << b_lshift) | (b >> b_rshift);

			src += 2;
		}
	} else
		for (i = 0; i < context->Header.width; i++) {
			int v, r, g, b;

			v = src[0] | (src[1] << 8);

			r = (v >> 10) & 0x1f;
			g = (v >> 5) & 0x1f;
			b = v & 0x1f;

			*pixels++ = (r << 3) | (r >> 2);
			*pixels++ = (g << 3) | (g >> 2);
			*pixels++ = (b << 3) | (b >> 2);
757
758

			src += 2;
759
		}
760
761
}

762
763
764
765
766
767
static void OneLine8(struct bmp_progressive_state *context)
{
	gint X;
	guchar *Pixels;

	X = 0;
768
	if (context->Header.Negative == 0)
769
770
771
		Pixels = (context->pixbuf->pixels +
			  context->pixbuf->rowstride *
			  (context->Header.height - context->Lines - 1));
772
	else
773
774
775
		Pixels = (context->pixbuf->pixels +
			  context->pixbuf->rowstride *
			  context->Lines);
776
777
	while (X < context->Header.width) {
		Pixels[X * 3 + 0] =
778
		    context->Colormap[context->buff[X]][2];
779
		Pixels[X * 3 + 1] =
780
		    context->Colormap[context->buff[X]][1];
781
		Pixels[X * 3 + 2] =
782
		    context->Colormap[context->buff[X]][0];
783
784
785
786
		X++;
	}
}

787
788
789
790
791
792
793
static void OneLine4(struct bmp_progressive_state *context)
{
	gint X;
	guchar *Pixels;

	X = 0;
	if (context->Header.Negative == 0)
794
795
796
		Pixels = (context->pixbuf->pixels +
			  context->pixbuf->rowstride *
			  (context->Header.height - context->Lines - 1));
797
	else
798
799
800
		Pixels = (context->pixbuf->pixels +
			  context->pixbuf->rowstride *
			  context->Lines);
801
802
803
804

	while (X < context->Header.width) {
		guchar Pix;

805
		Pix = context->buff[X / 2];
806
807

		Pixels[X * 3 + 0] =
808
		    context->Colormap[Pix >> 4][2];
809
		Pixels[X * 3 + 1] =
810
		    context->Colormap[Pix >> 4][1];
811
		Pixels[X * 3 + 2] =
812
		    context->Colormap[Pix >> 4][0];
813
814
815
816
		X++;
		if (X < context->Header.width) {
			/* Handle the other 4 bit pixel only when there is one */
			Pixels[X * 3 + 0] =
817
			    context->Colormap[Pix & 15][2];
818
			Pixels[X * 3 + 1] =
819
			    context->Colormap[Pix & 15][1];
820
			Pixels[X * 3 + 2] =
821
			    context->Colormap[Pix & 15][0];
822
823
824
825
826
827
			X++;
		}
	}

}

828
829
830
831
832
833
static void OneLine1(struct bmp_progressive_state *context)
{
	gint X;
	guchar *Pixels;

	X = 0;
834
	if (context->Header.Negative == 0)
835
836
837
		Pixels = (context->pixbuf->pixels +
			  context->pixbuf->rowstride *
			  (context->Header.height - context->Lines - 1));
838
	else
839
840
841
		Pixels = (context->pixbuf->pixels +
			  context->pixbuf->rowstride *
			  context->Lines);
842
	while (X < context->Header.width) {
843
		gint Bit;
844

845
		Bit = (context->buff[X / 8]) >> (7 - (X & 7));
846
		Bit = Bit & 1;
847
848
849
		Pixels[X * 3 + 0] = context->Colormap[Bit][2];
		Pixels[X * 3 + 1] = context->Colormap[Bit][1];
		Pixels[X * 3 + 2] = context->Colormap[Bit][0];
850
851
852
853
854
855
856
		X++;
	}
}


static void OneLine(struct bmp_progressive_state *context)
{
857
	context->BufferDone = 0;
858
859
860
	if (context->Lines >= context->Header.height)
		return;

861
862
	if (context->Type == 32)
		OneLine32(context);
863
	else if (context->Type == 24)
864
		OneLine24(context);
865
	else if (context->Type == 16)
866
		OneLine16(context);
867
	else if (context->Type == 8)
868
		OneLine8(context);
869
	else if (context->Type == 4)
870
		OneLine4(context);
871
	else if (context->Type == 1)
872
		OneLine1(context);
873
874
	else
		g_assert_not_reached ();
875
876
877
878
879
880

	context->Lines++;

	if (context->updated_func != NULL) {
		(*context->updated_func) (context->pixbuf,
					  0,
881
882
883
					  (context->Header.Negative ?
					   (context->Lines - 1) :
					   (context->Header.height - context->Lines)),
884
					  context->Header.width,
885
					  1,
886
					  context->user_data);
887
888
889
890

	}
}

891
892
893
894
895
896
897
898
899
900
901
902
903
904
#define NEUTRAL       0
#define ENCODED       1
#define ESCAPE        2   
#define DELTA_X       3
#define DELTA_Y       4
#define ABSOLUTE      5
#define SKIP          6

#define END_OF_LINE   0
#define END_OF_BITMAP 1
#define DELTA         2

static gboolean 
DoCompressed(struct bmp_progressive_state *context, GError **error)
905
{
906
907
908
909
910
	gint i, j;
	gint y;
	guchar c;
	gint idx;

911
912
913
914
915
916
917
918
919
920
	/* context->compr.y might be past the last line because we are
	 * on padding past the end of a valid data, or we might have hit
	 * out-of-bounds data. Either way we just eat-and-ignore the
	 * rest of the file. Doing the check only here and not when
	 * we change y below is fine since BufferSize is always 2 here
	 * and the BMP file format always starts new data on 16-bit
	 * boundaries.
	 */
	if (context->compr.y >= context->Header.height) {
		context->BufferDone = 0;
921
		return TRUE;
922
	}
923

924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
	y = context->compr.y;

 	for (i = 0; i < context->BufferSize; i++) {
		c = context->buff[i];
		switch (context->compr.phase) {
		    case NEUTRAL:
			    if (c) {
				    context->compr.run = c;
				    context->compr.phase = ENCODED;
			    }
			    else
				    context->compr.phase = ESCAPE;
			    break;
		    case ENCODED:
			    for (j = 0; j < context->compr.run; j++) {
				    if (context->Compressed == BI_RLE8)
					    idx = c;
				    else if (j & 1) 
					    idx = c & 0x0f;
				    else 
					    idx = (c >> 4) & 0x0f;
				    if (context->compr.x < context->Header.width) {
					    *context->compr.p++ = context->Colormap[idx][2];
					    *context->compr.p++ = context->Colormap[idx][1];
					    *context->compr.p++ = context->Colormap[idx][0];
					    *context->compr.p++ = 0xff;
					    context->compr.x++;    
				    }
			    }
			    context->compr.phase = NEUTRAL;
			    break;
		    case ESCAPE:
			    switch (c) {
				case END_OF_LINE:
					context->compr.x = 0;
					context->compr.y++;
					context->compr.p = context->pixbuf->pixels 
						+ (context->pixbuf->rowstride * (context->Header.height - context->compr.y - 1))
						+ (4 * context->compr.x);
					context->compr.phase = NEUTRAL;
					break;
				case END_OF_BITMAP:
					context->compr.x = 0;
					context->compr.y = context->Header.height;
					context->compr.phase = NEUTRAL;
					break;
				case DELTA:
					context->compr.phase = DELTA_X;
					break;
				default:
					context->compr.run = c;
					context->compr.count = 0;
					context->compr.phase = ABSOLUTE;
					break;
			    }
			    break;
		    case DELTA_X:
			    context->compr.x += c;
			    context->compr.phase = DELTA_Y;
			    break;
		    case DELTA_Y:
			    context->compr.y += c;
			    context->compr.p = context->pixbuf->pixels 
				    + (context->pixbuf->rowstride * (context->Header.height - context->compr.y - 1))
				    + (4 * context->compr.x);
			    context->compr.phase = NEUTRAL;
			    break;
		    case ABSOLUTE:
			    if (context->Compressed == BI_RLE8) {
				    idx = c;
				    if (context->compr.x < context->Header.width) {
					    *context->compr.p++ = context->Colormap[idx][2];
					    *context->compr.p++ = context->Colormap[idx][1];
					    *context->compr.p++ = context->Colormap[idx][0];
					    *context->compr.p++ = 0xff;
					    context->compr.x++;    
				    }
				    context->compr.count++;

				    if (context->compr.count == context->compr.run) {
					    if (context->compr.run & 1)
						    context->compr.phase = SKIP;
					    else
						    context->compr.phase = NEUTRAL;
				    }
			    }
			    else {
				    for (j = 0; j < 2; j++) {
					    if (context->compr.count & 1)
						    idx = c & 0x0f;
					    else 
						    idx = (c >> 4) & 0x0f;
					    if (context->compr.x < context->Header.width) {
						    *context->compr.p++ = context->Colormap[idx][2];
						    *context->compr.p++ = context->Colormap[idx][1];
						    *context->compr.p++ = context->Colormap[idx][0];
						    *context->compr.p++ = 0xff;
						    context->compr.x++;    
					    }
					    context->compr.count++;

					    if (context->compr.count == context->compr.run) {
						    if ((context->compr.run & 3) == 1
							|| (context->compr.run & 3) == 2) 
							    context->compr.phase = SKIP;
						    else
							    context->compr.phase = NEUTRAL;
						    break;
					    }
				    }
			    }
			    break;
		    case SKIP:
			    context->compr.phase = NEUTRAL;
			    break;
1039
		}
1040
	}
1041
1042
	if (context->updated_func != NULL) {
		if (context->compr.y > y)
1043
1044
		{
			gint new_y = MIN (context->compr.y, context->Header.height);
1045
1046
			(*context->updated_func) (context->pixbuf,
						  0,
1047
						  context->Header.height - new_y,
1048
						  context->Header.width,
1049
						  new_y - y,
1050
						  context->user_data);
1051
		}
1052
1053
1054
1055
1056

	}

	context->BufferDone = 0;
	return TRUE;
1057
1058
}

1059
1060
1061
1062
1063
/*
 * context - from image_begin_load
 * buf - new image data
 * size - length of new image data
 *
1064
 * append image data onto incrementally built output image
1065
 */
1066
1067
1068
1069
1070
static gboolean
gdk_pixbuf__bmp_image_load_increment(gpointer data,
                                     const guchar * buf,
                                     guint size,
                                     GError **error)
1071
1072
1073
1074
1075
1076
{
	struct bmp_progressive_state *context =
	    (struct bmp_progressive_state *) data;

	gint BytesToCopy;

1077
1078
1079
1080
1081
	if (context->read_state == READ_STATE_DONE)
		return TRUE;
	else if (context->read_state == READ_STATE_ERROR)
		return FALSE;

1082
	while (size > 0) {
1083
		if (context->BufferDone < context->BufferSize) {	/* We still
1084
1085
									   have headerbytes to do */
			BytesToCopy =
1086
			    context->BufferSize - context->BufferDone;
1087
1088
1089
			if (BytesToCopy > size)
				BytesToCopy = size;

1090
			memmove(context->buff + context->BufferDone,
1091
				buf, BytesToCopy);
1092
1093
1094

			size -= BytesToCopy;
			buf += BytesToCopy;
1095
			context->BufferDone += BytesToCopy;
1096

1097
1098
			if (context->BufferDone != context->BufferSize)
				break;
1099
1100
		}

1101
1102
		switch (context->read_state) {
		case READ_STATE_HEADERS:
1103
1104
1105
			if (!DecodeHeader (context->buff,
					   context->buff + 14, context,
					   error))
1106
				return FALSE;
1107
1108
1109
1110

			break;

		case READ_STATE_PALETTE:
1111
1112
			if (!DecodeColormap (context->buff, context, error))
				return FALSE;
1113
1114
1115
			break;

		case READ_STATE_BITMASKS:
1116
1117
			if (!decode_bitmasks (context->buff, context, error))
				return FALSE;
1118
1119
1120
1121
1122
			break;

		case READ_STATE_DATA:
			if (context->Compressed == BI_RGB || context->Compressed == BI_BITFIELDS)
				OneLine (context);
1123
1124
			else if (!DoCompressed (context, error))
				return FALSE;
1125
1126

			break;
1127
1128
1129
		case READ_STATE_DONE:
			return TRUE;
			break;
1130
1131
1132

		default:
			g_assert_not_reached ();
1133
		}
1134
	}