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