1 /* -*- mode: C; c-file-style: "linux" -*- */
2 /* GdkPixbuf library - Windows Bitmap image loader
4 * Copyright (C) 1999 The Free Software Foundation
6 * Authors: Arjan van de Ven <arjan@fenrus.demon.nl>
7 * Federico Mena-Quintero <federico@gimp.org>
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.
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.
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.
33 #include "gdk-pixbuf-private.h"
34 #include "gdk-pixbuf-io.h"
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.
42 * We do not use these structures; we just keep them here for reference.
44 struct BitmapFileHeader {
51 struct BitmapInfoHeader {
62 guint32 n_important_colors;
66 /* Compression values */
71 #define BI_BITFIELDS 3
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 */
85 DumpBIH printf's the values in a BitmapInfoHeader to the screen, for
90 static void DumpBIH(unsigned char *BIH)
92 printf("biSize = %i \n",
93 (int) (BIH[3] << 24) + (BIH[2] << 16) + (BIH[1] << 8) +
95 printf("biWidth = %i \n",
96 (int) (BIH[7] << 24) + (BIH[6] << 16) + (BIH[5] << 8) +
98 printf("biHeight = %i \n",
99 (int) (BIH[11] << 24) + (BIH[10] << 16) + (BIH[9] << 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) +
106 printf("biSizeImage = %i \n",
107 (int) (BIH[23] << 24) + (BIH[22] << 16) + (BIH[21] << 8) +
109 printf("biXPels = %i \n",
110 (int) (BIH[27] << 24) + (BIH[26] << 16) + (BIH[25] << 8) +
112 printf("biYPels = %i \n",
113 (int) (BIH[31] << 24) + (BIH[30] << 16) + (BIH[29] << 8) +
115 printf("biClrUsed = %i \n",
116 (int) (BIH[35] << 24) + (BIH[34] << 16) + (BIH[33] << 8) +
118 printf("biClrImprtnt= %i \n",
119 (int) (BIH[39] << 24) + (BIH[38] << 16) + (BIH[37] << 8) +
123 /* struct headerpair contains the decoded width/height/depth info for
124 the current bitmap */
131 guint Negative; /* Negative = 1 -> top down BMP,
132 Negative = 0 -> bottom up BMP */
135 /* Data needed for the "state" during decompression */
136 struct bmp_compression_state {
144 /* Progressive loading */
146 struct bmp_progressive_state {
147 GdkPixbufModulePreparedFunc prepared_func;
148 GdkPixbufModuleUpdatedFunc updated_func;
151 ReadState read_state;
154 guint Lines; /* # of finished lines */
160 guchar (*Colormap)[3];
166 4 = 4 bpp colormapped
167 8 = 8 bpp colormapped
171 struct bmp_compression_state compr;
174 struct headerpair Header; /* Decoded (BE->CPU) header */
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;
181 GdkPixbuf *pixbuf; /* Our "target" */
185 gdk_pixbuf__bmp_image_begin_load(GdkPixbufModuleSizeFunc size_func,
186 GdkPixbufModulePreparedFunc prepared_func,
187 GdkPixbufModuleUpdatedFunc updated_func,
191 static gboolean gdk_pixbuf__bmp_image_stop_load(gpointer data, GError **error);
192 static gboolean gdk_pixbuf__bmp_image_load_increment(gpointer data,
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.
205 return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
208 /* Same as above, but for 16-bit little-endian integers. */
212 return src[0] | (src[1] << 8);
215 static gboolean grow_buffer (struct bmp_progressive_state *State,
218 guchar *tmp = g_try_realloc (State->buff, State->BufferSize);
222 GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
223 _("Not enough memory to load bitmap image"));
224 State->read_state = READ_STATE_ERROR;
231 static gboolean DecodeHeader(unsigned char *BFH, unsigned char *BIH,
232 struct bmp_progressive_state *State,
235 /* FIXME this is totally unrobust against bogus image data. */
237 if (State->BufferSize < lsb_32 (&BIH[0]) + 14) {
238 State->BufferSize = lsb_32 (&BIH[0]) + 14;
239 if (!grow_buffer (State, error))
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;
262 GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
263 _("BMP image has unsupported header size"));
264 State->read_state = READ_STATE_ERROR;
268 State->Type = State->Header.depth; /* This may be less trivial someday */
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;
275 if (State->Header.width < 0) {
276 State->Header.width = -State->Header.width;
277 State->Header.Negative = 0;
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) {
287 GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
288 _("BMP image has bogus header data"));
289 State->read_state = READ_STATE_ERROR;
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)
310 GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
311 _("BMP image has bogus header data"));
312 State->read_state = READ_STATE_ERROR;
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;
321 if (State->pixbuf == NULL) {
322 if (State->Type == 32 ||
323 State->Compressed == BI_RLE4 ||
324 State->Compressed == BI_RLE8)
326 gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8,
327 (gint) State->Header.width,
328 (gint) State->Header.height);
331 gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8,
332 (gint) State->Header.width,
333 (gint) State->Header.height);
335 if (State->pixbuf == NULL) {
338 GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
339 _("Not enough memory to load bitmap image"));
340 State->read_state = READ_STATE_ERROR;
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);
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);
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;
370 GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
371 _("BMP image has bogus header data"));
372 State->read_state = READ_STATE_ERROR;
376 if (!grow_buffer (State, error))
382 static gboolean DecodeColormap (guchar *buff,
383 struct bmp_progressive_state *State,
388 g_assert (State->read_state == READ_STATE_PALETTE);
390 State->Colormap = g_malloc ((1 << State->Header.depth) * sizeof (*State->Colormap));
392 for (i = 0; i < (1 << State->Header.depth); i++)
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];
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]);
405 State->read_state = READ_STATE_DATA;
407 State->BufferDone = 0;
408 if (!(State->Compressed == BI_RGB || State->Compressed == BI_BITFIELDS))
409 State->BufferSize = 2;
411 State->BufferSize = State->LineWidth;
413 if (!grow_buffer (State, error))
419 /* Finds the lowest set bit and the number of set bits */
421 find_bits (int n, int *lowest, int *n_set)
427 for (i = 31; i >= 0; i--)
434 /* Decodes the 3 shorts that follow for the bitmasks for BI_BITFIELDS coding */
436 decode_bitmasks (guchar *buf,
437 struct bmp_progressive_state *State,
440 State->r_mask = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
443 State->g_mask = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
446 State->b_mask = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
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);
452 if (State->r_bits == 0 || State->g_bits == 0 || State->b_bits == 0) {
453 State->r_mask = 0x7c00;
455 State->g_mask = 0x03e0;
457 State->b_mask = 0x001f;
460 State->r_bits = State->g_bits = State->b_bits = 5;
463 State->read_state = READ_STATE_DATA;
464 State->BufferDone = 0;
465 State->BufferSize = State->LineWidth;
466 if (!grow_buffer (State, error))
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)
479 gdk_pixbuf__bmp_image_begin_load(GdkPixbufModuleSizeFunc size_func,
480 GdkPixbufModulePreparedFunc prepared_func,
481 GdkPixbufModuleUpdatedFunc updated_func,
485 struct bmp_progressive_state *context;
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;
492 context->read_state = READ_STATE_HEADERS;
494 context->BufferSize = 26;
495 context->buff = g_malloc(26);
496 context->BufferDone = 0;
497 /* 14 for the BitmapFileHeader, 12 for the BitmapImageHeader */
499 context->Colormap = NULL;
505 memset(&context->Header, 0, sizeof(struct headerpair));
506 memset(&context->compr, 0, sizeof(struct bmp_compression_state));
509 context->pixbuf = NULL;
512 return (gpointer) context;
516 * context - returned from image_begin_load
518 * free context, unref gdk_pixbuf
520 static gboolean gdk_pixbuf__bmp_image_stop_load(gpointer data, GError **error)
522 struct bmp_progressive_state *context =
523 (struct bmp_progressive_state *) data;
525 /* FIXME this thing needs to report errors if
526 * we have unused image data
529 g_return_val_if_fail(context != NULL, TRUE);
531 if (context->Colormap != NULL)
532 g_free(context->Colormap);
535 g_object_unref(context->pixbuf);
537 g_free(context->buff);
545 The OneLineXX functions are called when 1 line worth of data is present.
546 OneLine24 is the 24 bpp-version.
548 static void OneLine32(struct bmp_progressive_state *context)
554 if (!context->Header.Negative)
555 pixels = (context->pixbuf->pixels +
556 context->pixbuf->rowstride * (context->Header.height - context->Lines - 1));
558 pixels = (context->pixbuf->pixels +
559 context->pixbuf->rowstride * context->Lines);
563 if (context->Compressed == BI_BITFIELDS) {
564 int r_lshift, r_rshift;
565 int g_lshift, g_rshift;
566 int b_lshift, b_rshift;
568 r_lshift = 8 - context->r_bits;
569 g_lshift = 8 - context->g_bits;
570 b_lshift = 8 - context->b_bits;
572 r_rshift = context->r_bits - r_lshift;
573 g_rshift = context->g_bits - g_lshift;
574 b_rshift = context->b_bits - b_lshift;
576 for (i = 0; i < context->Header.width; i++) {
579 v = src[0] | (src[1] << 8) | (src[2] << 16);
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;
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 */
593 for (i = 0; i < context->Header.width; i++) {
603 static void OneLine24(struct bmp_progressive_state *context)
609 if (context->Header.Negative == 0)
610 Pixels = (context->pixbuf->pixels +
611 context->pixbuf->rowstride *
612 (context->Header.height - context->Lines - 1));
614 Pixels = (context->pixbuf->pixels +
615 context->pixbuf->rowstride *
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];
626 static void OneLine16(struct bmp_progressive_state *context)
632 if (!context->Header.Negative)
633 pixels = (context->pixbuf->pixels +
634 context->pixbuf->rowstride * (context->Header.height - context->Lines - 1));
636 pixels = (context->pixbuf->pixels +
637 context->pixbuf->rowstride * context->Lines);
641 if (context->Compressed == BI_BITFIELDS) {
642 int r_lshift, r_rshift;
643 int g_lshift, g_rshift;
644 int b_lshift, b_rshift;
646 r_lshift = 8 - context->r_bits;
647 g_lshift = 8 - context->g_bits;
648 b_lshift = 8 - context->b_bits;
650 r_rshift = context->r_bits - r_lshift;
651 g_rshift = context->g_bits - g_lshift;
652 b_rshift = context->b_bits - b_lshift;
654 for (i = 0; i < context->Header.width; i++) {
657 v = (int) src[0] | ((int) src[1] << 8);
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;
663 *pixels++ = (r << r_lshift) | (r >> r_rshift);
664 *pixels++ = (g << g_lshift) | (g >> g_rshift);
665 *pixels++ = (b << b_lshift) | (b >> b_rshift);
670 for (i = 0; i < context->Header.width; i++) {
673 v = src[0] | (src[1] << 8);
675 r = (v >> 10) & 0x1f;
679 *pixels++ = (r << 3) | (r >> 2);
680 *pixels++ = (g << 3) | (g >> 2);
681 *pixels++ = (b << 3) | (b >> 2);
687 static void OneLine8(struct bmp_progressive_state *context)
693 if (context->Header.Negative == 0)
694 Pixels = (context->pixbuf->pixels +
695 context->pixbuf->rowstride *
696 (context->Header.height - context->Lines - 1));
698 Pixels = (context->pixbuf->pixels +
699 context->pixbuf->rowstride *
701 while (X < context->Header.width) {
703 context->Colormap[context->buff[X]][2];
705 context->Colormap[context->buff[X]][1];
707 context->Colormap[context->buff[X]][0];
712 static void OneLine4(struct bmp_progressive_state *context)
718 if (context->Header.Negative == 0)
719 Pixels = (context->pixbuf->pixels +
720 context->pixbuf->rowstride *
721 (context->Header.height - context->Lines - 1));
723 Pixels = (context->pixbuf->pixels +
724 context->pixbuf->rowstride *
727 while (X < context->Header.width) {
730 Pix = context->buff[X / 2];
733 context->Colormap[Pix >> 4][2];
735 context->Colormap[Pix >> 4][1];
737 context->Colormap[Pix >> 4][0];
739 if (X < context->Header.width) {
740 /* Handle the other 4 bit pixel only when there is one */
742 context->Colormap[Pix & 15][2];
744 context->Colormap[Pix & 15][1];
746 context->Colormap[Pix & 15][0];
753 static void OneLine1(struct bmp_progressive_state *context)
759 if (context->Header.Negative == 0)
760 Pixels = (context->pixbuf->pixels +
761 context->pixbuf->rowstride *
762 (context->Header.height - context->Lines - 1));
764 Pixels = (context->pixbuf->pixels +
765 context->pixbuf->rowstride *
767 while (X < context->Header.width) {
770 Bit = (context->buff[X / 8]) >> (7 - (X & 7));
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];
780 static void OneLine(struct bmp_progressive_state *context)
782 context->BufferDone = 0;
783 if (context->Lines >= context->Header.height)
786 if (context->Type == 32)
788 else if (context->Type == 24)
790 else if (context->Type == 16)
792 else if (context->Type == 8)
794 else if (context->Type == 4)
796 else if (context->Type == 1)
799 g_assert_not_reached ();
803 if (context->updated_func != NULL) {
804 (*context->updated_func) (context->pixbuf,
806 (context->Header.Negative ?
807 (context->Lines - 1) :
808 (context->Header.height - context->Lines)),
809 context->Header.width,
824 #define END_OF_LINE 0
825 #define END_OF_BITMAP 1
829 DoCompressed(struct bmp_progressive_state *context, GError **error)
836 if (context->compr.y >= context->Header.height)
839 y = context->compr.y;
841 for (i = 0; i < context->BufferSize; i++) {
842 c = context->buff[i];
843 switch (context->compr.phase) {
846 context->compr.run = c;
847 context->compr.phase = ENCODED;
850 context->compr.phase = ESCAPE;
853 for (j = 0; j < context->compr.run; j++) {
854 if (context->Compressed == BI_RLE8)
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;
868 context->compr.phase = NEUTRAL;
873 context->compr.x = 0;
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;
881 context->compr.x = 0;
882 context->compr.y = context->Header.height;
883 context->compr.phase = NEUTRAL;
886 context->compr.phase = DELTA_X;
889 context->compr.run = c;
890 context->compr.count = 0;
891 context->compr.phase = ABSOLUTE;
896 context->compr.x += c;
897 context->compr.phase = 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;
907 if (context->Compressed == BI_RLE8) {
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;
916 context->compr.count++;
918 if (context->compr.count == context->compr.run) {
919 if (context->compr.run & 1)
920 context->compr.phase = SKIP;
922 context->compr.phase = NEUTRAL;
926 for (j = 0; j < 2; j++) {
927 if (context->compr.count & 1)
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;
938 context->compr.count++;
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;
945 context->compr.phase = NEUTRAL;
952 context->compr.phase = NEUTRAL;
956 if (context->updated_func != NULL) {
957 if (context->compr.y > y)
958 (*context->updated_func) (context->pixbuf,
961 context->Header.width,
962 context->compr.y - y,
967 context->BufferDone = 0;
972 * context - from image_begin_load
973 * buf - new image data
974 * size - length of new image data
976 * append image data onto inrecrementally built output image
979 gdk_pixbuf__bmp_image_load_increment(gpointer data,
984 struct bmp_progressive_state *context =
985 (struct bmp_progressive_state *) data;
989 if (context->read_state == READ_STATE_DONE)
991 else if (context->read_state == READ_STATE_ERROR)
995 if (context->BufferDone < context->BufferSize) { /* We still
996 have headerbytes to do */
998 context->BufferSize - context->BufferDone;
999 if (BytesToCopy > size)
1002 memmove(context->buff + context->BufferDone,
1005 size -= BytesToCopy;
1007 context->BufferDone += BytesToCopy;
1009 if (context->BufferDone != context->BufferSize)
1013 switch (context->read_state) {
1014 case READ_STATE_HEADERS:
1015 if (!DecodeHeader (context->buff,
1016 context->buff + 14, context,
1022 case READ_STATE_PALETTE:
1023 if (!DecodeColormap (context->buff, context, error))
1027 case READ_STATE_BITMASKS:
1028 if (!decode_bitmasks (context->buff, context, error))
1032 case READ_STATE_DATA:
1033 if (context->Compressed == BI_RGB || context->Compressed == BI_BITFIELDS)
1035 else if (!DoCompressed (context, error))
1041 g_assert_not_reached ();
1049 MODULE_ENTRY (bmp, fill_vtable) (GdkPixbufModule *module)
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;
1057 MODULE_ENTRY (bmp, fill_info) (GdkPixbufFormat *info)
1059 static GdkPixbufModulePattern signature[] = {
1060 { "BM", NULL, 100 },
1063 static gchar * mime_types[] = {
1069 static gchar * extensions[] = {
1075 info->signature = signature;
1076 info->description = N_("The BMP image format");
1077 info->mime_types = mime_types;
1078 info->extensions = extensions;