io-bmp.c 27.8 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

36

37

38 39 40 41 42 43
#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.
 */
44
struct BitmapFileHeader {
45 46 47 48
	guint16 magic;
	guint32 file_size;
	guint32 reserved;
	guint32 data_offset;
49 50 51
};

struct BitmapInfoHeader {
52 53 54 55 56 57 58 59 60 61 62
	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;
63
};
64
#endif
65

66
/* Compression values */
67 68 69 70 71 72

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

73 74 75 76 77 78 79 80 81
/* 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;
82

83 84 85
/*

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

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

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

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

/* Progressive loading */

struct bmp_progressive_state {
147 148
	GdkPixbufModulePreparedFunc prepared_func;
	GdkPixbufModuleUpdatedFunc updated_func;
149 150
	gpointer user_data;

151 152
	ReadState read_state;

153 154
	guint LineWidth;
	guint Lines;		/* # of finished lines */
155

156 157 158 159 160
	guchar *buff;
	gint BufferSize;
	gint BufferDone;

	guchar (*Colormap)[3];
161

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


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

176 177 178 179
	/* 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;
180 181 182 183

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

184
static gpointer
185 186 187
gdk_pixbuf__bmp_image_begin_load(GdkPixbufModuleSizeFunc size_func,
                                 GdkPixbufModulePreparedFunc prepared_func,
				 GdkPixbufModuleUpdatedFunc updated_func,
Havoc Pennington's avatar
Havoc Pennington committed
188
                                 gpointer user_data,
Havoc Pennington's avatar
Havoc Pennington committed
189
                                 GError **error);
Federico Mena Quintero's avatar
Federico Mena Quintero committed
190

191 192 193 194 195
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);
196

Mark Crichton's avatar
Mark Crichton committed
197

198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
/* 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);
}

215 216 217
static gboolean grow_buffer (struct bmp_progressive_state *State,
                             GError **error)
{
218 219
  guchar *tmp = g_try_realloc (State->buff, State->BufferSize);
  if (!tmp) {
220 221 222 223 224 225 226
    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;
  }
227
  State->buff = tmp;
228 229 230
  return TRUE;
}

231 232 233
static gboolean DecodeHeader(unsigned char *BFH, unsigned char *BIH,
                             struct bmp_progressive_state *State,
                             GError **error)
234
{
235
        /* FIXME this is totally unrobust against bogus image data. */
236

237 238
	if (State->BufferSize < lsb_32 (&BIH[0]) + 14) {
		State->BufferSize = lsb_32 (&BIH[0]) + 14;
239
		if (!grow_buffer (State, error))
Matthias Clasen's avatar
Matthias Clasen committed
240
			return FALSE;
241 242 243
		return TRUE;
	}

244 245 246 247
#if DUMPBIH
	DumpBIH(BIH);
#endif

248
	State->Header.size = lsb_32 (&BIH[0]);
249
	if (State->Header.size == 40) {
250 251 252 253
		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]);
254
	} else if (State->Header.size == 12) {
255 256 257
		State->Header.width = lsb_16 (&BIH[4]);
		State->Header.height = lsb_16 (&BIH[6]);
		State->Header.depth = lsb_16 (&BIH[10]);
258
		State->Compressed = BI_RGB;
259 260 261 262 263
	} else {
		g_set_error (error,
			     GDK_PIXBUF_ERROR,
			     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
			     _("BMP image has unsupported header size"));
264
		State->read_state = READ_STATE_ERROR;
265 266
		return FALSE;
	}
267 268

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

270
	/* Negative heights indicates bottom-down pixelorder */
271 272 273 274 275 276 277 278
	if (State->Header.height < 0) {
		State->Header.height = -State->Header.height;
		State->Header.Negative = 1;
	}
	if (State->Header.width < 0) {
		State->Header.width = -State->Header.width;
		State->Header.Negative = 0;
	}
279

280 281 282
	if (State->Header.width == 0 || State->Header.height == 0 ||
	    (State->Compressed == BI_RLE4 && State->Type != 4)    ||
	    (State->Compressed == BI_RLE8 && State->Type != 8)	  ||
283 284
	    (State->Compressed == BI_BITFIELDS && !(State->Type == 16 || State->Type == 32)) ||
	    State->Compressed > BI_BITFIELDS) {
285 286 287 288
		g_set_error (error,
			     GDK_PIXBUF_ERROR,
			     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
			     _("BMP image has bogus header data"));
289
		State->read_state = READ_STATE_ERROR;
290 291 292
		return FALSE;
	}

293 294
	if (State->Type == 32)
		State->LineWidth = State->Header.width * 4;
295
	else if (State->Type == 24)
296
		State->LineWidth = State->Header.width * 3;
297 298 299
	else if (State->Type == 16)
		State->LineWidth = State->Header.width * 2;
	else if (State->Type == 8)
300
		State->LineWidth = State->Header.width * 1;
301
	else if (State->Type == 4)
302
		State->LineWidth = (State->Header.width + 1) / 2;
303
	else if (State->Type == 1) {
304 305 306
		State->LineWidth = State->Header.width / 8;
		if ((State->Header.width & 7) != 0)
			State->LineWidth++;
307 308 309 310 311
	} else {
		g_set_error (error,
			     GDK_PIXBUF_ERROR,
			     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
			     _("BMP image has bogus header data"));
312
		State->read_state = READ_STATE_ERROR;
313
		return FALSE;
314
	}
315

316
	/* Pad to a 32 bit boundary */
317 318
	if (((State->LineWidth % 4) > 0)
	    && (State->Compressed == BI_RGB || State->Compressed == BI_BITFIELDS))
319 320
		State->LineWidth = (State->LineWidth / 4) * 4 + 4;

321
	if (State->pixbuf == NULL) {
322 323 324
		if (State->Type == 32 || 
		    State->Compressed == BI_RLE4 || 
		    State->Compressed == BI_RLE8)
325
			State->pixbuf =
326
			    gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8,
327 328 329 330
					   (gint) State->Header.width,
					   (gint) State->Header.height);
		else
			State->pixbuf =
331
			    gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8,
332 333
					   (gint) State->Header.width,
					   (gint) State->Header.height);
334

335 336 337 338 339
                if (State->pixbuf == NULL) {
                        g_set_error (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
                                     _("Not enough memory to load bitmap image"));
340
			State->read_state = READ_STATE_ERROR;
341
                        return FALSE;
342
                }
343

344 345
		if (State->prepared_func != NULL)
			/* Notify the client that we are ready to go */
Havoc Pennington's avatar
Havoc Pennington committed
346
			(*State->prepared_func) (State->pixbuf, NULL, State->user_data);
347 348

	}
349 350 351 352 353 354
	
	/* 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);
355 356 357
	}

	State->BufferDone = 0;
358 359
	if (State->Type <= 8) {
		State->read_state = READ_STATE_PALETTE;
360
		State->BufferSize = lsb_32 (&BFH[10]) - 14 - State->Header.size; 
361 362
	} else if (State->Compressed == BI_RGB) {
		State->read_state = READ_STATE_DATA;
363
		State->BufferSize = State->LineWidth;
364 365 366
	} else if (State->Compressed == BI_BITFIELDS) {
		State->read_state = READ_STATE_BITMASKS;
		State->BufferSize = 12;
367 368 369 370 371 372 373 374
	} 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;
	}
375

376 377
	if (!grow_buffer (State, error)) 
		return FALSE;
378 379 380 381

        return TRUE;
}

382 383 384
static gboolean DecodeColormap (guchar *buff,
				struct bmp_progressive_state *State,
				GError **error)
385 386 387
{
	gint i;

388 389
	g_assert (State->read_state == READ_STATE_PALETTE);

390 391 392 393 394 395 396
	State->Colormap = g_malloc ((1 << State->Header.depth) * sizeof (*State->Colormap));

	for (i = 0; i < (1 << State->Header.depth); i++)
	{
		State->Colormap[i][0] = buff[i * (State->Header.size == 12 ? 3 : 4)];
		State->Colormap[i][1] = buff[i * (State->Header.size == 12 ? 3 : 4) + 1];
		State->Colormap[i][2] = buff[i * (State->Header.size == 12 ? 3 : 4) + 2];
397 398 399 400 401 402
#ifdef DUMPCMAP
		g_print ("color %d %x %x %x\n", i,
			 State->Colormap[i][0],
			 State->Colormap[i][1],
			 State->Colormap[i][2]);
#endif
403 404
	}

405 406
	State->read_state = READ_STATE_DATA;

407
	State->BufferDone = 0;
408
	if (!(State->Compressed == BI_RGB || State->Compressed == BI_BITFIELDS))
409 410 411
		State->BufferSize = 2;
	else
		State->BufferSize = State->LineWidth;
412 413 414
	
	if (!grow_buffer (State, error))
		return FALSE;
415

416
	return TRUE;
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
}

/* 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 */
435 436 437 438
static gboolean
decode_bitmasks (guchar *buf,
		 struct bmp_progressive_state *State, 
		 GError **error)
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
{
	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;
466 467 468 469
	if (!grow_buffer (State, error)) 
		return FALSE;

	return TRUE;
470 471
}

472
/*
473 474 475 476 477
 * func - called when we have pixmap created (but no image data)
 * user_data - passed as arg 1 to func
 * return context (opaque to user)
 */

478
static gpointer
479 480 481
gdk_pixbuf__bmp_image_begin_load(GdkPixbufModuleSizeFunc size_func,
                                 GdkPixbufModulePreparedFunc prepared_func,
				 GdkPixbufModuleUpdatedFunc updated_func,
Havoc Pennington's avatar
Havoc Pennington committed
482
                                 gpointer user_data,
Havoc Pennington's avatar
Havoc Pennington committed
483
                                 GError **error)
484 485 486 487 488 489 490 491
{
	struct bmp_progressive_state *context;

	context = g_new0(struct bmp_progressive_state, 1);
	context->prepared_func = prepared_func;
	context->updated_func = updated_func;
	context->user_data = user_data;

492 493
	context->read_state = READ_STATE_HEADERS;

494 495 496
	context->BufferSize = 26;
	context->buff = g_malloc(26);
	context->BufferDone = 0;
497
	/* 14 for the BitmapFileHeader, 12 for the BitmapImageHeader */
498

499
	context->Colormap = NULL;
500 501 502 503 504 505

	context->Lines = 0;

	context->Type = 0;

	memset(&context->Header, 0, sizeof(struct headerpair));
506
	memset(&context->compr, 0, sizeof(struct bmp_compression_state));
507 508 509 510 511 512 513 514 515 516 517 518 519


	context->pixbuf = NULL;


	return (gpointer) context;
}

/*
 * context - returned from image_begin_load
 *
 * free context, unref gdk_pixbuf
 */
520
static gboolean gdk_pixbuf__bmp_image_stop_load(gpointer data, GError **error)
521 522 523 524
{
	struct bmp_progressive_state *context =
	    (struct bmp_progressive_state *) data;

525 526
        /* FIXME this thing needs to report errors if
         * we have unused image data
527
         */
528

529
	g_return_val_if_fail(context != NULL, TRUE);
530

531 532
	if (context->Colormap != NULL)
		g_free(context->Colormap);
533 534

	if (context->pixbuf)
535
		g_object_unref(context->pixbuf);
536

537
	g_free(context->buff);
538
	g_free(context);
539 540

        return TRUE;
541 542 543
}


544 545 546 547 548 549
/*
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)
{
550
	int i;
551 552
	guchar *pixels;
	guchar *src;
553

554 555 556
	if (!context->Header.Negative)
		pixels = (context->pixbuf->pixels +
			  context->pixbuf->rowstride * (context->Header.height - context->Lines - 1));
557
	else
558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574
		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;
575

576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600
		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);
			*pixels++ = src[3]; /* alpha */

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

			src += 4;
		}
601 602
}

603 604 605 606 607 608
static void OneLine24(struct bmp_progressive_state *context)
{
	gint X;
	guchar *Pixels;

	X = 0;
609
	if (context->Header.Negative == 0)
610 611 612
		Pixels = (context->pixbuf->pixels +
			  context->pixbuf->rowstride *
			  (context->Header.height - context->Lines - 1));
613
	else
614 615 616
		Pixels = (context->pixbuf->pixels +
			  context->pixbuf->rowstride *
			  context->Lines);
617
	while (X < context->Header.width) {
618 619 620
		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];
621 622 623 624 625
		X++;
	}

}

626 627
static void OneLine16(struct bmp_progressive_state *context)
{
628 629 630
	int i;
	guchar *pixels;
	guchar *src;
631

632 633 634
	if (!context->Header.Negative)
		pixels = (context->pixbuf->pixels +
			  context->pixbuf->rowstride * (context->Header.height - context->Lines - 1));
635
	else
636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681
		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);
682 683

			src += 2;
684
		}
685 686
}

687 688 689 690 691 692
static void OneLine8(struct bmp_progressive_state *context)
{
	gint X;
	guchar *Pixels;

	X = 0;
693
	if (context->Header.Negative == 0)
694 695 696
		Pixels = (context->pixbuf->pixels +
			  context->pixbuf->rowstride *
			  (context->Header.height - context->Lines - 1));
697
	else
698 699 700
		Pixels = (context->pixbuf->pixels +
			  context->pixbuf->rowstride *
			  context->Lines);
701 702
	while (X < context->Header.width) {
		Pixels[X * 3 + 0] =
703
		    context->Colormap[context->buff[X]][2];
704
		Pixels[X * 3 + 1] =
705
		    context->Colormap[context->buff[X]][1];
706
		Pixels[X * 3 + 2] =
707
		    context->Colormap[context->buff[X]][0];
708 709 710 711
		X++;
	}
}

712 713 714 715 716 717 718
static void OneLine4(struct bmp_progressive_state *context)
{
	gint X;
	guchar *Pixels;

	X = 0;
	if (context->Header.Negative == 0)
719 720 721
		Pixels = (context->pixbuf->pixels +
			  context->pixbuf->rowstride *
			  (context->Header.height - context->Lines - 1));
722
	else
723 724 725
		Pixels = (context->pixbuf->pixels +
			  context->pixbuf->rowstride *
			  context->Lines);
726 727 728 729

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

730
		Pix = context->buff[X / 2];
731 732

		Pixels[X * 3 + 0] =
733
		    context->Colormap[Pix >> 4][2];
734
		Pixels[X * 3 + 1] =
735
		    context->Colormap[Pix >> 4][1];
736
		Pixels[X * 3 + 2] =
737
		    context->Colormap[Pix >> 4][0];
738 739 740 741
		X++;
		if (X < context->Header.width) {
			/* Handle the other 4 bit pixel only when there is one */
			Pixels[X * 3 + 0] =
742
			    context->Colormap[Pix & 15][2];
743
			Pixels[X * 3 + 1] =
744
			    context->Colormap[Pix & 15][1];
745
			Pixels[X * 3 + 2] =
746
			    context->Colormap[Pix & 15][0];
747 748 749 750 751 752
			X++;
		}
	}

}

753 754 755 756 757 758
static void OneLine1(struct bmp_progressive_state *context)
{
	gint X;
	guchar *Pixels;

	X = 0;
759
	if (context->Header.Negative == 0)
760 761 762
		Pixels = (context->pixbuf->pixels +
			  context->pixbuf->rowstride *
			  (context->Header.height - context->Lines - 1));
763
	else
764 765 766
		Pixels = (context->pixbuf->pixels +
			  context->pixbuf->rowstride *
			  context->Lines);
767
	while (X < context->Header.width) {
768
		gint Bit;
769

770
		Bit = (context->buff[X / 8]) >> (7 - (X & 7));
771
		Bit = Bit & 1;
772 773 774
		Pixels[X * 3 + 0] = context->Colormap[Bit][2];
		Pixels[X * 3 + 1] = context->Colormap[Bit][1];
		Pixels[X * 3 + 2] = context->Colormap[Bit][0];
775 776 777 778 779 780 781
		X++;
	}
}


static void OneLine(struct bmp_progressive_state *context)
{
782
	context->BufferDone = 0;
783 784 785
	if (context->Lines >= context->Header.height)
		return;

786 787
	if (context->Type == 32)
		OneLine32(context);
788
	else if (context->Type == 24)
789
		OneLine24(context);
790
	else if (context->Type == 16)
791
		OneLine16(context);
792
	else if (context->Type == 8)
793
		OneLine8(context);
794
	else if (context->Type == 4)
795
		OneLine4(context);
796
	else if (context->Type == 1)
797
		OneLine1(context);
798 799
	else
		g_assert_not_reached ();
800 801 802 803 804 805

	context->Lines++;

	if (context->updated_func != NULL) {
		(*context->updated_func) (context->pixbuf,
					  0,
806 807 808
					  (context->Header.Negative ?
					   (context->Lines - 1) :
					   (context->Header.height - context->Lines)),
809
					  context->Header.width,
810
					  1,
811
					  context->user_data);
812 813 814 815

	}
}

816 817 818 819 820 821 822 823 824 825 826 827 828 829
#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)
830
{
831 832 833 834 835 836 837
	gint i, j;
	gint y;
	guchar c;
	gint idx;

	if (context->compr.y >= context->Header.height)
		return TRUE;
838

839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 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
	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;
954
		}
955
	}
956 957 958 959 960 961 962 963 964 965 966 967 968
	if (context->updated_func != NULL) {
		if (context->compr.y > y)
			(*context->updated_func) (context->pixbuf,
						  0,
						  y,
						  context->Header.width,
						  context->compr.y - y,
						  context->user_data);

	}

	context->BufferDone = 0;
	return TRUE;
969 970
}

971 972 973 974 975 976 977
/*
 * context - from image_begin_load
 * buf - new image data
 * size - length of new image data
 *
 * append image data onto inrecrementally built output image
 */
978 979 980 981 982
static gboolean
gdk_pixbuf__bmp_image_load_increment(gpointer data,
                                     const guchar * buf,
                                     guint size,
                                     GError **error)
983 984 985 986 987 988