]> Pileus Git - ~andy/gtk/blob - gdk-pixbuf/io-bmp.c
4285b5ac58dd61095d93b9d186fa7730915f354d
[~andy/gtk] / gdk-pixbuf / io-bmp.c
1 /* GdkPixbuf library - Windows Bitmap image loader
2  *
3  * Copyright (C) 1999 The Free Software Foundation
4  *
5  * Authors: Arjan van de Ven <arjan@fenrus.demon.nl>
6  *          Federico Mena-Quintero <federico@gimp.org>
7  *
8  * Based on io-ras.c
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the
22  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23  * Boston, MA 02111-1307, USA.
24  */
25
26 #include <config.h>
27 #include <stdio.h>
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
31 #include <string.h>
32 #include "gdk-pixbuf-private.h"
33 #include "gdk-pixbuf-io.h"
34
35 \f
36
37 #if 0
38 /* If these structures were unpacked, they would define the two headers of the
39  * BMP file.  After them comes the palette, and then the image data.
40  *
41  * We do not use these structures; we just keep them here for reference.
42  */
43 struct BitmapFileHeader {
44         guint16 magic;
45         guint32 file_size;
46         guint32 reserved;
47         guint32 data_offset;
48 };
49
50 struct BitmapInfoHeader {
51         guint32 header_size;
52         guint32 width;
53         guint32 height;
54         guint16 planes;
55         guint16 bpp;
56         guint32 compression;
57         guint32 data_size;
58         guint32 x_ppm;
59         guint32 y_ppm;
60         guint32 n_colors;
61         guint32 n_important_colors;
62 };
63 #endif
64
65 /* Compression values */
66
67 #define BI_RGB 0
68 #define BI_RLE8 1
69 #define BI_RLE4 2
70 #define BI_BITFIELDS 3
71
72 /* State machine */
73 typedef enum {
74         READ_STATE_HEADERS,     /* Reading the bitmap file header and bitmap info header */
75         READ_STATE_PALETTE,     /* Reading the palette */
76         READ_STATE_BITMASKS,    /* Reading the bitmasks for BI_BITFIELDS */
77         READ_STATE_DATA,        /* Reading the actual image data */
78         READ_STATE_ERROR,       /* An error occurred; further data will be ignored */
79         READ_STATE_DONE         /* Done reading the image; further data will be ignored */
80 } ReadState;
81
82 /*
83
84 DumpBIH printf's the values in a BitmapInfoHeader to the screen, for
85 debugging purposes.
86
87 */
88 #if DUMPBIH
89 static void DumpBIH(unsigned char *BIH)
90 {
91         printf("biSize      = %i \n",
92                (int) (BIH[3] << 24) + (BIH[2] << 16) + (BIH[1] << 8) +
93                (BIH[0]));
94         printf("biWidth     = %i \n",
95                (int) (BIH[7] << 24) + (BIH[6] << 16) + (BIH[5] << 8) +
96                (BIH[4]));
97         printf("biHeight    = %i \n",
98                (int) (BIH[11] << 24) + (BIH[10] << 16) + (BIH[9] << 8) +
99                (BIH[8]));
100         printf("biPlanes    = %i \n", (int) (BIH[13] << 8) + (BIH[12]));
101         printf("biBitCount  = %i \n", (int) (BIH[15] << 8) + (BIH[14]));
102         printf("biCompress  = %i \n",
103                (int) (BIH[19] << 24) + (BIH[18] << 16) + (BIH[17] << 8) +
104                (BIH[16]));
105         printf("biSizeImage = %i \n",
106                (int) (BIH[23] << 24) + (BIH[22] << 16) + (BIH[21] << 8) +
107                (BIH[20]));
108         printf("biXPels     = %i \n",
109                (int) (BIH[27] << 24) + (BIH[26] << 16) + (BIH[25] << 8) +
110                (BIH[24]));
111         printf("biYPels     = %i \n",
112                (int) (BIH[31] << 24) + (BIH[30] << 16) + (BIH[29] << 8) +
113                (BIH[28]));
114         printf("biClrUsed   = %i \n",
115                (int) (BIH[35] << 24) + (BIH[34] << 16) + (BIH[33] << 8) +
116                (BIH[32]));
117         printf("biClrImprtnt= %i \n",
118                (int) (BIH[39] << 24) + (BIH[38] << 16) + (BIH[37] << 8) +
119                (BIH[36]));
120 }
121 #endif
122 /* struct headerpair contains the decoded width/height/depth info for
123    the current bitmap */
124
125 struct headerpair {
126         guint32 size;
127         gint32 width;
128         gint32 height;
129         guint depth;
130         guint Negative;         /* Negative = 1 -> top down BMP,
131                                    Negative = 0 -> bottom up BMP */
132 };
133
134 /* Data needed for the "state" during decompression */
135 struct bmp_compression_state {
136         gint phase;
137         gint RunCount;
138
139         guchar *linebuff;
140         gint linebuffsize;      /* these two counts in nibbles */
141         gint linebuffdone;
142 };
143
144 /* Progressive loading */
145
146 struct bmp_progressive_state {
147         ModulePreparedNotifyFunc prepared_func;
148         ModuleUpdatedNotifyFunc updated_func;
149         gpointer user_data;
150
151         ReadState read_state;
152
153         guint LineWidth;
154         guint Lines;            /* # of finished lines */
155
156         guchar *buff;
157         gint BufferSize;
158         gint BufferDone;
159
160         guchar (*Colormap)[3];
161
162         gint Type;              /*
163                                    32 = RGB + alpha
164                                    24 = RGB
165                                    16 = RGB
166                                    4  = 4 bpp colormapped
167                                    8  = 8 bpp colormapped
168                                    1  = 1 bit bitonal
169                                  */
170         gint Compressed;
171         struct bmp_compression_state compr;
172
173
174         struct headerpair Header;       /* Decoded (BE->CPU) header */
175
176         /* Bit masks, shift amounts, and significant bits for BI_BITFIELDS coding */
177         int r_mask, r_shift, r_bits;
178         int g_mask, g_shift, g_bits;
179         int b_mask, b_shift, b_bits;
180
181         GdkPixbuf *pixbuf;      /* Our "target" */
182 };
183
184 static gpointer
185 gdk_pixbuf__bmp_image_begin_load(ModulePreparedNotifyFunc prepared_func,
186                                  ModuleUpdatedNotifyFunc updated_func,
187                                  gpointer user_data,
188                                  GError **error);
189
190 static gboolean gdk_pixbuf__bmp_image_stop_load(gpointer data, GError **error);
191 static gboolean gdk_pixbuf__bmp_image_load_increment(gpointer data,
192                                                      const guchar * buf,
193                                                      guint size,
194                                                      GError **error);
195
196
197
198 /* Shared library entry point --> This should be removed when
199    generic_image_load enters gdk-pixbuf-io. */
200 static GdkPixbuf *gdk_pixbuf__bmp_image_load(FILE * f, GError **error)
201 {
202         guchar membuf[4096];
203         size_t length;
204         struct bmp_progressive_state *State;
205
206         GdkPixbuf *pb;
207
208         State =
209             gdk_pixbuf__bmp_image_begin_load(NULL, NULL, NULL,
210                                              error);
211
212         if (State == NULL)
213           return NULL;
214
215         while (feof(f) == 0) {
216                 length = fread(membuf, 1, sizeof (membuf), f);
217                 if (length > 0)
218                   if (!gdk_pixbuf__bmp_image_load_increment(State,
219                                                             membuf,
220                                                             length,
221                                                             error)) {
222                           gdk_pixbuf__bmp_image_stop_load (State, NULL);
223                           return NULL;
224                   }
225
226         }
227         if (State->pixbuf != NULL)
228                 g_object_ref(State->pixbuf);
229
230         pb = State->pixbuf;
231
232         gdk_pixbuf__bmp_image_stop_load(State, NULL);
233         return pb;
234 }
235
236 static gboolean DecodeHeader(unsigned char *BFH, unsigned char *BIH,
237                              struct bmp_progressive_state *State,
238                              GError **error)
239 {
240         /* FIXME this is totally unrobust against bogus image data. */
241
242         if (State->BufferSize < GUINT32_FROM_LE (* (guint32 *) &BIH[0]) + 14) {
243                 State->BufferSize = GUINT32_FROM_LE (* (guint32 *) &BIH[0]) + 14;
244                 State->buff = g_realloc (State->buff, State->BufferSize);
245                 return TRUE;
246         }
247
248 #if DUMPBIH
249         DumpBIH(BIH);
250 #endif
251
252         State->Header.size = GUINT32_FROM_LE (* (guint32 *) &BIH[0]);
253         if (State->Header.size == 40) {
254                 State->Header.width = GINT32_FROM_LE (* (gint32 *) &BIH[4]);
255                 State->Header.height = GINT32_FROM_LE (* (gint32 *) &BIH[8]);
256                 State->Header.depth = GUINT16_FROM_LE (* (guint16 *) &BIH[14]);
257                 State->Compressed = GUINT32_FROM_LE (* (guint32 *) &BIH[16]);
258         } else if (State->Header.size == 12) {
259                 State->Header.width = GUINT16_FROM_LE (* (guint16 *) &BIH[4]);
260                 State->Header.height = GUINT16_FROM_LE (* (guint16 *) &BIH[6]);
261                 State->Header.depth = GUINT16_FROM_LE (* (guint16 *) &BIH[10]);
262                 State->Compressed = BI_RGB;
263         } else {
264                 g_set_error (error,
265                              GDK_PIXBUF_ERROR,
266                              GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
267                              _("BMP image has unsupported header size"));
268                 State->read_state = READ_STATE_ERROR;
269                 return FALSE;
270         }
271
272         State->Type = State->Header.depth;      /* This may be less trivial someday */
273
274         /* Negative heights indicates bottom-down pixelorder */
275         if (State->Header.height < 0) {
276                 State->Header.height = -State->Header.height;
277                 State->Header.Negative = 1;
278         }
279         if (State->Header.width < 0) {
280                 State->Header.width = -State->Header.width;
281                 State->Header.Negative = 0;
282         }
283
284         if (State->Header.width == 0 || State->Header.height == 0 ||
285             (State->Compressed == BI_RLE4 && State->Type != 4)    ||
286             (State->Compressed == BI_RLE8 && State->Type != 8)    ||
287             (State->Compressed == BI_BITFIELDS && !(State->Type == 16 || State->Type == 32)) ||
288             State->Compressed > BI_BITFIELDS) {
289                 g_set_error (error,
290                              GDK_PIXBUF_ERROR,
291                              GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
292                              _("BMP image has bogus header data"));
293                 State->read_state = READ_STATE_ERROR;
294                 return FALSE;
295         }
296
297         if (State->Type == 32)
298                 State->LineWidth = State->Header.width * 4;
299         else if (State->Type == 24)
300                 State->LineWidth = State->Header.width * 3;
301         else if (State->Type == 16)
302                 State->LineWidth = State->Header.width * 2;
303         else if (State->Type == 8)
304                 State->LineWidth = State->Header.width * 1;
305         else if (State->Type == 4)
306                 State->LineWidth = (State->Header.width + 1) / 2;
307         else if (State->Type == 1) {
308                 State->LineWidth = State->Header.width / 8;
309                 if ((State->Header.width & 7) != 0)
310                         State->LineWidth++;
311         } else {
312                 g_set_error (error,
313                              GDK_PIXBUF_ERROR,
314                              GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
315                              _("BMP image has bogus header data"));
316                 State->read_state = READ_STATE_ERROR;
317                 return FALSE;
318         }
319
320         /* Pad to a 32 bit boundary */
321         if (((State->LineWidth % 4) > 0)
322             && (State->Compressed == BI_RGB || State->Compressed == BI_BITFIELDS))
323                 State->LineWidth = (State->LineWidth / 4) * 4 + 4;
324
325         if (State->pixbuf == NULL) {
326                 if (State->Type == 32)
327                         State->pixbuf =
328                             gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8,
329                                            (gint) State->Header.width,
330                                            (gint) State->Header.height);
331                 else
332                         State->pixbuf =
333                             gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8,
334                                            (gint) State->Header.width,
335                                            (gint) State->Header.height);
336
337                 if (State->pixbuf == NULL) {
338                         g_set_error (error,
339                                      GDK_PIXBUF_ERROR,
340                                      GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
341                                      _("Not enough memory to load bitmap image"));
342                         State->read_state = READ_STATE_ERROR;
343                         return FALSE;
344                 }
345
346                 if (State->prepared_func != NULL)
347                         /* Notify the client that we are ready to go */
348                         (*State->prepared_func) (State->pixbuf, NULL, State->user_data);
349
350         }
351
352         if (!(State->Compressed == BI_RGB || State->Compressed == BI_BITFIELDS)) {
353                 State->compr.linebuffdone = 0;
354                 State->compr.linebuffsize = State->Header.width;
355                 if (State->Type == 8)
356                         State->compr.linebuffsize *= 2;
357                 State->compr.linebuff = g_malloc ((State->compr.linebuffsize + 1) / 2);
358         }
359
360         State->BufferDone = 0;
361         if (State->Type <= 8) {
362                 State->read_state = READ_STATE_PALETTE;
363                 State->BufferSize = GUINT32_FROM_LE (* (guint32 *) &BFH[10]) - 14 - State->Header.size;
364         } else if (State->Compressed == BI_RGB) {
365                 State->read_state = READ_STATE_DATA;
366                 State->BufferSize = State->LineWidth;
367         } else if (State->Compressed == BI_BITFIELDS) {
368                 State->read_state = READ_STATE_BITMASKS;
369                 State->BufferSize = 12;
370         } else
371                 g_assert_not_reached ();
372
373         State->buff = g_realloc (State->buff, State->BufferSize);
374
375         return TRUE;
376 }
377
378 static void DecodeColormap (guchar *buff,
379                             struct bmp_progressive_state *State,
380                             GError **error)
381 {
382         gint i;
383
384         g_assert (State->read_state == READ_STATE_PALETTE);
385
386         State->Colormap = g_malloc ((1 << State->Header.depth) * sizeof (*State->Colormap));
387
388         for (i = 0; i < (1 << State->Header.depth); i++)
389         {
390                 State->Colormap[i][0] = buff[i * (State->Header.size == 12 ? 3 : 4)];
391                 State->Colormap[i][1] = buff[i * (State->Header.size == 12 ? 3 : 4) + 1];
392                 State->Colormap[i][2] = buff[i * (State->Header.size == 12 ? 3 : 4) + 2];
393         }
394
395         State->read_state = READ_STATE_DATA;
396
397         State->BufferDone = 0;
398         if (!(State->Compressed == BI_RGB || State->Compressed == BI_BITFIELDS))
399                 State->BufferSize = 2;
400         else
401                 State->BufferSize = State->LineWidth;
402
403         State->buff = g_realloc (State->buff, State->BufferSize);
404 }
405
406 /* Finds the lowest set bit and the number of set bits */
407 static void
408 find_bits (int n, int *lowest, int *n_set)
409 {
410         int i;
411
412         *n_set = 0;
413
414         for (i = 31; i >= 0; i--)
415                 if (n & (1 << i)) {
416                         *lowest = i;
417                         (*n_set)++;
418                 }
419 }
420
421 /* Decodes the 3 shorts that follow for the bitmasks for BI_BITFIELDS coding */
422 static void
423 decode_bitmasks (struct bmp_progressive_state *State, guchar *buf)
424 {
425         State->r_mask = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
426         buf += 4;
427
428         State->g_mask = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
429         buf += 4;
430
431         State->b_mask = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
432
433         find_bits (State->r_mask, &State->r_shift, &State->r_bits);
434         find_bits (State->g_mask, &State->g_shift, &State->g_bits);
435         find_bits (State->b_mask, &State->b_shift, &State->b_bits);
436
437         if (State->r_bits == 0 || State->g_bits == 0 || State->b_bits == 0) {
438                 State->r_mask = 0x7c00;
439                 State->r_shift = 10;
440                 State->g_mask = 0x03e0;
441                 State->g_shift = 5;
442                 State->b_mask = 0x001f;
443                 State->b_shift = 0;
444
445                 State->r_bits = State->g_bits = State->b_bits = 5;
446         }
447
448         State->read_state = READ_STATE_DATA;
449         State->BufferDone = 0;
450         State->BufferSize = State->LineWidth;
451         State->buff = g_realloc (State->buff, State->BufferSize);
452 }
453
454 /*
455  * func - called when we have pixmap created (but no image data)
456  * user_data - passed as arg 1 to func
457  * return context (opaque to user)
458  */
459
460 static gpointer
461 gdk_pixbuf__bmp_image_begin_load(ModulePreparedNotifyFunc prepared_func,
462                                  ModuleUpdatedNotifyFunc updated_func,
463                                  gpointer user_data,
464                                  GError **error)
465 {
466         struct bmp_progressive_state *context;
467
468         context = g_new0(struct bmp_progressive_state, 1);
469         context->prepared_func = prepared_func;
470         context->updated_func = updated_func;
471         context->user_data = user_data;
472
473         context->read_state = READ_STATE_HEADERS;
474
475         context->BufferSize = 26;
476         context->buff = g_malloc(26);
477         context->BufferDone = 0;
478         /* 14 for the BitmapFileHeader, 12 for the BitmapImageHeader */
479
480         context->Colormap = NULL;
481
482         context->Lines = 0;
483
484         context->Type = 0;
485
486         memset(&context->Header, 0, sizeof(struct headerpair));
487         memset(&context->compr, 0, sizeof(struct bmp_compression_state));
488
489
490         context->pixbuf = NULL;
491
492
493         return (gpointer) context;
494 }
495
496 /*
497  * context - returned from image_begin_load
498  *
499  * free context, unref gdk_pixbuf
500  */
501 static gboolean gdk_pixbuf__bmp_image_stop_load(gpointer data, GError **error)
502 {
503         struct bmp_progressive_state *context =
504             (struct bmp_progressive_state *) data;
505
506         /* FIXME this thing needs to report errors if
507          * we have unused image data
508          */
509
510         g_return_val_if_fail(context != NULL, TRUE);
511
512         if (context->compr.linebuff != NULL)
513                 g_free(context->compr.linebuff);
514
515         if (context->Colormap != NULL)
516                 g_free(context->Colormap);
517
518         if (context->pixbuf)
519                 g_object_unref(context->pixbuf);
520
521         g_free(context->buff);
522         g_free(context);
523
524         return TRUE;
525 }
526
527
528 /*
529 The OneLineXX functions are called when 1 line worth of data is present.
530 OneLine24 is the 24 bpp-version.
531 */
532 static void OneLine32(struct bmp_progressive_state *context)
533 {
534         int i;
535         guchar *pixels;
536         guchar *src;
537
538         if (!context->Header.Negative)
539                 pixels = (context->pixbuf->pixels +
540                           context->pixbuf->rowstride * (context->Header.height - context->Lines - 1));
541         else
542                 pixels = (context->pixbuf->pixels +
543                           context->pixbuf->rowstride * context->Lines);
544
545         src = context->buff;
546
547         if (context->Compressed == BI_BITFIELDS) {
548                 int r_lshift, r_rshift;
549                 int g_lshift, g_rshift;
550                 int b_lshift, b_rshift;
551
552                 r_lshift = 8 - context->r_bits;
553                 g_lshift = 8 - context->g_bits;
554                 b_lshift = 8 - context->b_bits;
555
556                 r_rshift = context->r_bits - r_lshift;
557                 g_rshift = context->g_bits - g_lshift;
558                 b_rshift = context->b_bits - b_lshift;
559
560                 for (i = 0; i < context->Header.width; i++) {
561                         int v, r, g, b;
562
563                         v = src[0] | (src[1] << 8) | (src[2] << 16);
564
565                         r = (v & context->r_mask) >> context->r_shift;
566                         g = (v & context->g_mask) >> context->g_shift;
567                         b = (v & context->b_mask) >> context->b_shift;
568
569                         *pixels++ = (r << r_lshift) | (r >> r_rshift);
570                         *pixels++ = (g << g_lshift) | (g >> g_rshift);
571                         *pixels++ = (b << b_lshift) | (b >> b_rshift);
572                         *pixels++ = src[3]; /* alpha */
573
574                         src += 4;
575                 }
576         } else
577                 for (i = 0; i < context->Header.width; i++) {
578                         *pixels++ = src[2];
579                         *pixels++ = src[1];
580                         *pixels++ = src[0];
581                         *pixels++ = src[3];
582
583                         src += 4;
584                 }
585 }
586
587 static void OneLine24(struct bmp_progressive_state *context)
588 {
589         gint X;
590         guchar *Pixels;
591
592         X = 0;
593         if (context->Header.Negative == 0)
594                 Pixels = (context->pixbuf->pixels +
595                           context->pixbuf->rowstride *
596                           (context->Header.height - context->Lines - 1));
597         else
598                 Pixels = (context->pixbuf->pixels +
599                           context->pixbuf->rowstride *
600                           context->Lines);
601         while (X < context->Header.width) {
602                 Pixels[X * 3 + 0] = context->buff[X * 3 + 2];
603                 Pixels[X * 3 + 1] = context->buff[X * 3 + 1];
604                 Pixels[X * 3 + 2] = context->buff[X * 3 + 0];
605                 X++;
606         }
607
608 }
609
610 static void OneLine16(struct bmp_progressive_state *context)
611 {
612         int i;
613         guchar *pixels;
614         guchar *src;
615
616         if (!context->Header.Negative)
617                 pixels = (context->pixbuf->pixels +
618                           context->pixbuf->rowstride * (context->Header.height - context->Lines - 1));
619         else
620                 pixels = (context->pixbuf->pixels +
621                           context->pixbuf->rowstride * context->Lines);
622
623         src = context->buff;
624
625         if (context->Compressed == BI_BITFIELDS) {
626                 int r_lshift, r_rshift;
627                 int g_lshift, g_rshift;
628                 int b_lshift, b_rshift;
629
630                 r_lshift = 8 - context->r_bits;
631                 g_lshift = 8 - context->g_bits;
632                 b_lshift = 8 - context->b_bits;
633
634                 r_rshift = context->r_bits - r_lshift;
635                 g_rshift = context->g_bits - g_lshift;
636                 b_rshift = context->b_bits - b_lshift;
637
638                 for (i = 0; i < context->Header.width; i++) {
639                         int v, r, g, b;
640
641                         v = (int) src[0] | ((int) src[1] << 8);
642
643                         r = (v & context->r_mask) >> context->r_shift;
644                         g = (v & context->g_mask) >> context->g_shift;
645                         b = (v & context->b_mask) >> context->b_shift;
646
647                         *pixels++ = (r << r_lshift) | (r >> r_rshift);
648                         *pixels++ = (g << g_lshift) | (g >> g_rshift);
649                         *pixels++ = (b << b_lshift) | (b >> b_rshift);
650
651                         src += 2;
652                 }
653         } else
654                 for (i = 0; i < context->Header.width; i++) {
655                         int v, r, g, b;
656
657                         v = src[0] | (src[1] << 8);
658
659                         r = (v >> 10) & 0x1f;
660                         g = (v >> 5) & 0x1f;
661                         b = v & 0x1f;
662
663                         *pixels++ = (r << 3) | (r >> 2);
664                         *pixels++ = (g << 3) | (g >> 2);
665                         *pixels++ = (b << 3) | (b >> 2);
666                 }
667 }
668
669 static void OneLine8(struct bmp_progressive_state *context)
670 {
671         gint X;
672         guchar *Pixels;
673
674         X = 0;
675         if (context->Header.Negative == 0)
676                 Pixels = (context->pixbuf->pixels +
677                           context->pixbuf->rowstride *
678                           (context->Header.height - context->Lines - 1));
679         else
680                 Pixels = (context->pixbuf->pixels +
681                           context->pixbuf->rowstride *
682                           context->Lines);
683         while (X < context->Header.width) {
684                 Pixels[X * 3 + 0] =
685                     context->Colormap[context->buff[X]][2];
686                 Pixels[X * 3 + 1] =
687                     context->Colormap[context->buff[X]][1];
688                 Pixels[X * 3 + 2] =
689                     context->Colormap[context->buff[X]][0];
690                 X++;
691         }
692 }
693
694 static void OneLine4(struct bmp_progressive_state *context)
695 {
696         gint X;
697         guchar *Pixels;
698
699         X = 0;
700         if (context->Header.Negative == 0)
701                 Pixels = (context->pixbuf->pixels +
702                           context->pixbuf->rowstride *
703                           (context->Header.height - context->Lines - 1));
704         else
705                 Pixels = (context->pixbuf->pixels +
706                           context->pixbuf->rowstride *
707                           context->Lines);
708
709         while (X < context->Header.width) {
710                 guchar Pix;
711
712                 Pix = context->buff[X / 2];
713
714                 Pixels[X * 3 + 0] =
715                     context->Colormap[Pix >> 4][2];
716                 Pixels[X * 3 + 1] =
717                     context->Colormap[Pix >> 4][1];
718                 Pixels[X * 3 + 2] =
719                     context->Colormap[Pix >> 4][0];
720                 X++;
721                 if (X < context->Header.width) {
722                         /* Handle the other 4 bit pixel only when there is one */
723                         Pixels[X * 3 + 0] =
724                             context->Colormap[Pix & 15][2];
725                         Pixels[X * 3 + 1] =
726                             context->Colormap[Pix & 15][1];
727                         Pixels[X * 3 + 2] =
728                             context->Colormap[Pix & 15][0];
729                         X++;
730                 }
731         }
732
733 }
734
735 static void OneLine1(struct bmp_progressive_state *context)
736 {
737         gint X;
738         guchar *Pixels;
739
740         X = 0;
741         if (context->Header.Negative == 0)
742                 Pixels = (context->pixbuf->pixels +
743                           context->pixbuf->rowstride *
744                           (context->Header.height - context->Lines - 1));
745         else
746                 Pixels = (context->pixbuf->pixels +
747                           context->pixbuf->rowstride *
748                           context->Lines);
749         while (X < context->Header.width) {
750                 gint Bit;
751
752                 Bit = (context->buff[X / 8]) >> (7 - (X & 7));
753                 Bit = Bit & 1;
754                 Pixels[X * 3 + 0] = context->Colormap[Bit][2];
755                 Pixels[X * 3 + 1] = context->Colormap[Bit][1];
756                 Pixels[X * 3 + 2] = context->Colormap[Bit][0];
757                 X++;
758         }
759 }
760
761
762 static void OneLine(struct bmp_progressive_state *context)
763 {
764         context->BufferDone = 0;
765         if (context->Lines >= context->Header.height)
766                 return;
767
768         if (context->Type == 32)
769                 OneLine32(context);
770         else if (context->Type == 24)
771                 OneLine24(context);
772         else if (context->Type == 16)
773                 OneLine16(context);
774         else if (context->Type == 8)
775                 OneLine8(context);
776         else if (context->Type == 4)
777                 OneLine4(context);
778         else if (context->Type == 1)
779                 OneLine1(context);
780         else
781                 g_assert_not_reached ();
782
783         context->Lines++;
784
785         if (context->updated_func != NULL) {
786                 (*context->updated_func) (context->pixbuf,
787                                           0,
788                                           context->Lines,
789                                           context->Header.width,
790                                           1,
791                                           context->user_data);
792
793         }
794 }
795
796 static void
797 DoCompressed(struct bmp_progressive_state *context)
798 {
799         gint count, pos;
800         switch (context->compr.phase) {
801         case 0:         /* Neutral state */
802                 if (context->buff[0] != 0) {    /* run count */
803                         context->compr.RunCount = context->buff[0];
804                         if (context->Type == 8)
805                                 context->compr.RunCount *= 2;
806                         while (context->compr.RunCount > 0) {
807                                 if (context->compr.linebuffdone & 1) {
808                                         guchar *ptr = context->compr.linebuff +
809                                             context->compr.linebuffdone / 2;
810
811                                         *ptr = (*ptr & 0xF0) | (context->buff[1] >> 4);
812                                         context->buff[1] = (context->buff[1] << 4) |
813                                                            (context->buff[1] >> 4);
814                                         context->compr.linebuffdone++;
815                                         context->compr.RunCount--;
816                                 }
817
818                                 if (context->compr.RunCount) {
819                                         count = context->compr.linebuffsize -
820                                             context->compr.linebuffdone;
821                                         if (count > context->compr.RunCount)
822                                                 count = context->compr.RunCount;
823
824                                         memset (context->compr.linebuff +
825                                                 context->compr.linebuffdone / 2,
826                                                 context->buff[1],
827                                                 (count + 1) / 2);
828                                         context->compr.RunCount -= count;
829                                         context->compr.linebuffdone += count;
830                                 }
831                                 if (context->compr.linebuffdone == context->compr.linebuffsize) {
832                                         guchar *tmp = context->buff;
833                                         context->buff = context->compr.linebuff;
834                                         OneLine (context);
835                                         context->buff = tmp;
836
837                                         if (context->compr.linebuffdone & 1)
838                                                 context->buff[1] = (context->buff[1] << 4) |
839                                                                    (context->buff[1] >> 4);
840                                         context->compr.linebuffdone = 0;
841                                 }
842                         }
843                 } else {        /* Escape */
844                         if (context->buff[1] == 0) {    /* End of line */
845                                 if (context->compr.linebuffdone) {
846                                         guchar *tmp = context->buff;
847                                         context->buff = context->compr.linebuff;
848                                         OneLine (context);
849                                         context->buff = tmp;
850
851                                         context->compr.linebuffdone = 0;
852                                 }
853                         } else if (context->buff[1] == 1) {     /* End of image */
854                                 if (context->compr.linebuffdone) {
855                                         guchar *tmp = context->buff;
856                                         context->buff = context->compr.linebuff;
857                                         OneLine (context);
858                                         context->buff = tmp;
859                                 }
860
861                                 context->compr.phase = 2;
862                         } else if (context->buff[1] == 2)       /* Cursor displacement */
863                                 ;       /* not implemented */
864                         else {
865                                 context->compr.phase = 1;
866                                 context->compr.RunCount = context->buff[1];
867                                 if (context->Type == 8)
868                                         context->compr.RunCount *= 2;
869                                 context->BufferSize = (context->compr.RunCount + 3) / 4 * 2;
870                                 context->buff = g_realloc (context->buff, context->BufferSize);
871                         }
872                 }
873                 context->BufferDone = 0;
874                 break;
875         case 1:
876                 pos = 0;
877                 while (pos < context->compr.RunCount) {
878                         count = context->compr.linebuffsize - context->compr.linebuffdone;
879                         if (count > context->compr.RunCount)
880                                 count = context->compr.RunCount;
881
882                         if ((context->compr.linebuffdone & 1) || (pos & 1)) {
883                                 gint i, newval;
884                                 guchar *ptr;
885                                 for (i = 0; i < count; i++) {
886                                         ptr = context->compr.linebuff + (i +
887                                               context->compr.linebuffdone) / 2;
888                                         newval = *(context->buff + (pos + i) / 2) & (0xf0 >> (((pos + i) % 2) * 4));
889                                         if (((pos + i) % 2) ^ ((context->compr.linebuffdone + i) % 2)) {
890                                                 if ((pos + i) % 2)
891                                                         newval <<= 4;
892                                                 else
893                                                         newval >>= 4;
894                                         }
895                                         *ptr = (*ptr & (0xf << (((i + context->compr.linebuffdone) % 2) * 4))) | newval;
896                                 }
897                         } else {
898                                 memmove (context->compr.linebuff +
899                                          context->compr.linebuffdone / 2,
900                                          context->buff + pos / 2,
901                                          (count + 1) / 2);
902                         }
903                         pos += count;
904                         context->compr.linebuffdone += count;
905                         if (context->compr.linebuffdone == context->compr.linebuffsize) {
906                                 guchar *tmp = context->buff;
907                                 context->buff = context->compr.linebuff;
908                                 OneLine (context);
909                                 context->buff = tmp;
910
911                                 context->compr.linebuffdone = 0;
912                         }
913                 }
914                 context->compr.phase = 0;
915                 context->BufferSize = 2;
916                 context->buff = g_realloc (context->buff, context->BufferSize);
917                 context->BufferDone = 0;
918                 break;
919         case 2:
920                 context->BufferDone = 0;
921                 break;
922         }
923 }
924
925 /*
926  * context - from image_begin_load
927  * buf - new image data
928  * size - length of new image data
929  *
930  * append image data onto inrecrementally built output image
931  */
932 static gboolean
933 gdk_pixbuf__bmp_image_load_increment(gpointer data,
934                                      const guchar * buf,
935                                      guint size,
936                                      GError **error)
937 {
938         struct bmp_progressive_state *context =
939             (struct bmp_progressive_state *) data;
940
941         gint BytesToCopy;
942
943         if (context->read_state == READ_STATE_DONE)
944                 return TRUE;
945         else if (context->read_state == READ_STATE_ERROR)
946                 return FALSE;
947
948         while (size > 0) {
949                 if (context->BufferDone < context->BufferSize) {        /* We still
950                                                                            have headerbytes to do */
951                         BytesToCopy =
952                             context->BufferSize - context->BufferDone;
953                         if (BytesToCopy > size)
954                                 BytesToCopy = size;
955
956                         memmove(context->buff + context->BufferDone,
957                                 buf, BytesToCopy);
958
959                         size -= BytesToCopy;
960                         buf += BytesToCopy;
961                         context->BufferDone += BytesToCopy;
962
963                         if (context->BufferDone != context->BufferSize)
964                                 break;
965                 }
966
967                 switch (context->read_state) {
968                 case READ_STATE_HEADERS:
969                         if (!DecodeHeader (context->buff,
970                                            context->buff + 14, context,
971                                            error))
972                                 return FALSE;
973
974                         break;
975
976                 case READ_STATE_PALETTE:
977                         DecodeColormap (context->buff, context, error);
978                         break;
979
980                 case READ_STATE_BITMASKS:
981                         decode_bitmasks (context, context->buff);
982                         break;
983
984                 case READ_STATE_DATA:
985                         if (context->Compressed == BI_RGB || context->Compressed == BI_BITFIELDS)
986                                 OneLine (context);
987                         else
988                                 DoCompressed (context);
989
990                         break;
991
992                 default:
993                         g_assert_not_reached ();
994                 }
995         }
996
997         return TRUE;
998 }
999
1000 void
1001 gdk_pixbuf__bmp_fill_vtable (GdkPixbufModule *module)
1002 {
1003   module->load = gdk_pixbuf__bmp_image_load;
1004   module->begin_load = gdk_pixbuf__bmp_image_begin_load;
1005   module->stop_load = gdk_pixbuf__bmp_image_stop_load;
1006   module->load_increment = gdk_pixbuf__bmp_image_load_increment;
1007 }