]> Pileus Git - ~andy/gtk/blob - gdk-pixbuf/io-bmp.c
Include x11/gdkx.h only when building for X11.
[~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 /*
27
28 Known bugs:
29         * 4bpp compressed files don't work
30         * bi-tonal files aren't tested with palettes
31
32 */
33
34 #include <config.h>
35 #include <stdio.h>
36 #ifdef HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39 #include <string.h>
40 #include "gdk-pixbuf-private.h"
41 #include "gdk-pixbuf-io.h"
42
43 \f
44
45 /* 
46
47 These structures are actually dummies. These are according to
48 the "Windows API reference guide volume II" as written by 
49 Borland International, but GCC fiddles with the alignment of 
50 the internal members, so these aren't actually usable.
51
52 */
53
54 struct BitmapFileHeader {
55         gushort bfType;
56         guint bfSize;
57         guint reserverd;
58         guint bfOffbits;
59 };
60
61 struct BitmapInfoHeader {
62         guint biSize;
63         guint biWidth;
64         guint biHeight;
65         gushort biPlanes;
66         gushort biBitCount;
67         guint biCompression;
68         guint biSizeImage;
69         guint biXPelsPerMeter;
70         guint biYPelsPerMeter;
71         guint biClrUsed;
72         guint biClrImportant;
73 };
74
75 /* 
76
77 DumpBIH printf's the values in a BitmapInfoHeader to the screen, for 
78 debugging purposes.
79
80 */
81 #if DUMPBIH
82 static void DumpBIH(unsigned char *BIH)
83 {
84         printf("biSize      = %i \n",
85                (int) (BIH[3] << 24) + (BIH[2] << 16) + (BIH[1] << 8) +
86                (BIH[0]));
87         printf("biWidth     = %i \n",
88                (int) (BIH[7] << 24) + (BIH[6] << 16) + (BIH[5] << 8) +
89                (BIH[4]));
90         printf("biHeight    = %i \n",
91                (int) (BIH[11] << 24) + (BIH[10] << 16) + (BIH[9] << 8) +
92                (BIH[8]));
93         printf("biPlanes    = %i \n", (int) (BIH[13] << 8) + (BIH[12]));
94         printf("biBitCount  = %i \n", (int) (BIH[15] << 8) + (BIH[14]));
95         printf("biCompress  = %i \n",
96                (int) (BIH[19] << 24) + (BIH[18] << 16) + (BIH[17] << 8) +
97                (BIH[16]));
98         printf("biSizeImage = %i \n",
99                (int) (BIH[23] << 24) + (BIH[22] << 16) + (BIH[21] << 8) +
100                (BIH[20]));
101         printf("biXPels     = %i \n",
102                (int) (BIH[27] << 24) + (BIH[26] << 16) + (BIH[25] << 8) +
103                (BIH[24]));
104         printf("biYPels     = %i \n",
105                (int) (BIH[31] << 24) + (BIH[30] << 16) + (BIH[29] << 8) +
106                (BIH[28]));
107         printf("biClrUsed   = %i \n",
108                (int) (BIH[35] << 24) + (BIH[34] << 16) + (BIH[33] << 8) +
109                (BIH[32]));
110         printf("biClrImprtnt= %i \n",
111                (int) (BIH[39] << 24) + (BIH[38] << 16) + (BIH[37] << 8) +
112                (BIH[36]));
113 }
114 #endif
115 /* struct headerpair contains the decoded width/height/depth info for
116    the current bitmap */
117
118 struct headerpair {
119         guint width;
120         guint height;
121         guint depth;
122         guint Negative;         /* Negative = 1 -> top down BMP,  
123                                    Negative = 0 -> bottom up BMP */
124 };
125
126 /* Data needed for the "state" during decompression */
127 struct bmp_compression_state {
128         gint phase;             /* 0 = clean, 
129                                    1 = count received
130                                    2 = escape received
131                                    3 = in "raw" run
132                                    4 = Relative part 1 is next
133                                    5 = Relative part 2 is next
134                                    6 = end of image -> No more input allowed
135                                  */
136         gint RunCount;
137         gint XDelta;
138         gint YDelta;
139 };
140
141 /* Progressive loading */
142
143 struct bmp_progressive_state {
144         ModulePreparedNotifyFunc prepared_func;
145         ModuleUpdatedNotifyFunc updated_func;
146         gpointer user_data;
147
148         gint HeaderSize;        /* The size of the header-part (incl colormap) */
149         guchar *HeaderBuf;      /* The buffer for the header (incl colormap) */
150         gint HeaderDone;        /* The nr of bytes actually in HeaderBuf */
151
152         gint LineWidth;         /* The width of a line in bytes */
153         guchar *LineBuf;        /* Buffer for 1 line */
154         gint LineDone;          /* # of bytes in LineBuf */
155         gint Lines;             /* # of finished lines */
156
157         gint Type;              /*  
158                                    32 = RGB + alpha
159                                    24 = RGB
160                                    4  = 4 bpp colormapped
161                                    8  = 8 bpp colormapped
162                                    1  = 1 bit bitonal 
163                                  */
164         gint Compressed;
165         struct bmp_compression_state compr;
166
167
168         struct headerpair Header;       /* Decoded (BE->CPU) header */
169
170
171         GdkPixbuf *pixbuf;      /* Our "target" */
172 };
173
174 gpointer
175 gdk_pixbuf__bmp_image_begin_load(ModulePreparedNotifyFunc prepared_func,
176                                  ModuleUpdatedNotifyFunc updated_func,
177                                  ModuleFrameDoneNotifyFunc frame_done_func,
178                                  ModuleAnimationDoneNotifyFunc
179                                  anim_done_func, gpointer user_data,
180                                  GError **error);
181
182 void gdk_pixbuf__bmp_image_stop_load(gpointer data);
183 gboolean gdk_pixbuf__bmp_image_load_increment(gpointer data, guchar * buf,
184                                               guint size,
185                                               GError **error);
186
187
188
189 /* Shared library entry point --> This should be removed when
190    generic_image_load enters gdk-pixbuf-io. */
191 GdkPixbuf *gdk_pixbuf__bmp_image_load(FILE * f, GError **error)
192 {
193         guchar membuf[4096];
194         size_t length;
195         struct bmp_progressive_state *State;
196
197         GdkPixbuf *pb;
198
199         State =
200             gdk_pixbuf__bmp_image_begin_load(NULL, NULL, NULL, NULL, NULL,
201                                              error);
202
203         if (State == NULL)
204           return NULL;
205         
206         while (feof(f) == 0) {
207                 length = fread(membuf, 1, 4096, f);
208                 if (length > 0)
209                   if (!gdk_pixbuf__bmp_image_load_increment(State,
210                                                             membuf,
211                                                             length,
212                                                             error)) {
213                           gdk_pixbuf__bmp_image_stop_load (State);
214                           return NULL;
215                   }
216
217         }
218         if (State->pixbuf != NULL)
219                 gdk_pixbuf_ref(State->pixbuf);
220
221         pb = State->pixbuf;
222
223         gdk_pixbuf__bmp_image_stop_load(State);
224         return pb;
225 }
226
227 static void DecodeHeader(unsigned char *BFH, unsigned char *BIH,
228                          struct bmp_progressive_state *State)
229 {
230 #if DUMPBIH
231         DumpBIH(BIH);
232 #endif
233
234         State->Header.width =
235             (int) (BIH[7] << 24) + (BIH[6] << 16) + (BIH[5] << 8) +
236             (BIH[4]);
237         State->Header.height =
238             (int) (BIH[11] << 24) + (BIH[10] << 16) + (BIH[9] << 8) +
239             (BIH[8]);
240         State->Header.depth = (int) (BIH[15] << 8) + (BIH[14]);;
241
242         State->Type = State->Header.depth;      /* This may be less trivial someday */
243         State->HeaderSize =
244             (int) ((BFH[13] << 24) + (BFH[12] << 16) + (BFH[11] << 8) +
245                    (BFH[10]));
246         if (State->HeaderSize >= 14 + 40 + 1024)
247                 State->HeaderBuf =
248                     g_realloc(State->HeaderBuf, State->HeaderSize);
249
250         if ((BIH[16] != 0) || (BIH[17] != 0) || (BIH[18] != 0)
251             || (BIH[19] != 0)) {
252                 State->Compressed = 1;
253         }
254
255         /* Negative heights indicates bottom-down pixelorder */
256         if (State->Header.height < 0) {
257                 State->Header.height = -State->Header.height;
258                 State->Header.Negative = 1;
259         }
260         if (State->Header.width < 0) {
261                 State->Header.width = -State->Header.width;
262                 State->Header.Negative = 0;
263         }
264
265         if (State->Type == 32)
266                 State->LineWidth = State->Header.width * 4;
267         if (State->Type == 24)
268                 State->LineWidth = State->Header.width * 3;
269         if (State->Type == 8)
270                 State->LineWidth = State->Header.width * 1;
271         if (State->Type == 4)
272                 State->LineWidth = (State->Header.width + 1) / 2;
273         if (State->Type == 1) {
274                 State->LineWidth = State->Header.width / 8;
275                 if ((State->Header.width & 7) != 0)
276                         State->LineWidth++;
277         }
278
279         /* Pad to a 32 bit boundary */
280         if (((State->LineWidth % 4) > 0) && (State->Compressed == 0))
281                 State->LineWidth = (State->LineWidth / 4) * 4 + 4;
282
283
284         if (State->LineBuf == NULL)
285                 State->LineBuf = g_malloc(State->LineWidth);
286
287         g_assert(State->LineBuf != NULL);
288
289
290         if (State->pixbuf == NULL) {
291                 if (State->Type == 32)
292                         State->pixbuf =
293                             gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8,
294                                            (gint) State->Header.width,
295                                            (gint) State->Header.height);
296                 else
297                         State->pixbuf =
298                             gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8,
299                                            (gint) State->Header.width,
300                                            (gint) State->Header.height);
301
302                 if (State->prepared_func != NULL)
303                         /* Notify the client that we are ready to go */
304                         (*State->prepared_func) (State->pixbuf, State->user_data);
305
306         }
307
308 }
309
310 /* 
311  * func - called when we have pixmap created (but no image data)
312  * user_data - passed as arg 1 to func
313  * return context (opaque to user)
314  */
315
316 gpointer
317 gdk_pixbuf__bmp_image_begin_load(ModulePreparedNotifyFunc prepared_func,
318                                  ModuleUpdatedNotifyFunc updated_func,
319                                  ModuleFrameDoneNotifyFunc frame_done_func,
320                                  ModuleAnimationDoneNotifyFunc
321                                  anim_done_func, gpointer user_data,
322                                  GError **error)
323 {
324         struct bmp_progressive_state *context;
325
326         context = g_new0(struct bmp_progressive_state, 1);
327         context->prepared_func = prepared_func;
328         context->updated_func = updated_func;
329         context->user_data = user_data;
330
331         context->HeaderSize = 54;
332         context->HeaderBuf = g_malloc(14 + 40 + 1024);
333         /* 14 for the BitmapFileHeader, 40 for the BitmapImageHeader and 
334            1024 for the colormap */
335
336         context->HeaderDone = 0;
337
338         context->LineWidth = 0;
339         context->LineBuf = NULL;
340         context->LineDone = 0;
341         context->Lines = 0;
342
343         context->Type = 0;
344
345         memset(&context->Header, 0, sizeof(struct headerpair));
346         memset(&context->compr, 0, sizeof(struct bmp_compression_state));
347
348
349         context->pixbuf = NULL;
350
351
352         return (gpointer) context;
353 }
354
355 /*
356  * context - returned from image_begin_load
357  *
358  * free context, unref gdk_pixbuf
359  */
360 void gdk_pixbuf__bmp_image_stop_load(gpointer data)
361 {
362         struct bmp_progressive_state *context =
363             (struct bmp_progressive_state *) data;
364
365
366         g_return_if_fail(context != NULL);
367
368         if (context->LineBuf != NULL)
369                 g_free(context->LineBuf);
370         context->LineBuf = NULL;
371
372         if (context->HeaderBuf != NULL)
373                 g_free(context->HeaderBuf);
374         context->LineBuf = NULL;
375
376         if (context->pixbuf)
377                 gdk_pixbuf_unref(context->pixbuf);
378
379         g_free(context);
380 }
381
382
383 /*
384 The OneLineXX functions are called when 1 line worth of data is present.
385 OneLine24 is the 24 bpp-version.
386 */
387 static void OneLine32(struct bmp_progressive_state *context)
388 {
389         gint X;
390         guchar *Pixels;
391
392         X = 0;
393         if (context->Header.Negative == 0)
394                 Pixels = (context->pixbuf->pixels +
395                           context->pixbuf->rowstride *
396                           (context->Header.height - context->Lines - 1));
397         else
398                 Pixels = (context->pixbuf->pixels +
399                           context->pixbuf->rowstride *
400                           context->Lines);
401         while (X < context->Header.width) {
402                 Pixels[X * 4 + 0] = context->LineBuf[X * 4 + 2];
403                 Pixels[X * 4 + 1] = context->LineBuf[X * 4 + 1];
404                 Pixels[X * 4 + 2] = context->LineBuf[X * 4 + 0];
405                 Pixels[X * 4 + 3] = context->LineBuf[X * 4 + 3];
406                 X++;
407         }
408
409 }
410
411 static void OneLine24(struct bmp_progressive_state *context)
412 {
413         gint X;
414         guchar *Pixels;
415
416         X = 0;
417         if (context->Header.Negative == 0)
418                 Pixels = (context->pixbuf->pixels +
419                           context->pixbuf->rowstride *
420                           (context->Header.height - context->Lines - 1));
421         else
422                 Pixels = (context->pixbuf->pixels +
423                           context->pixbuf->rowstride *
424                           context->Lines);
425         while (X < context->Header.width) {
426                 Pixels[X * 3 + 0] = context->LineBuf[X * 3 + 2];
427                 Pixels[X * 3 + 1] = context->LineBuf[X * 3 + 1];
428                 Pixels[X * 3 + 2] = context->LineBuf[X * 3 + 0];
429                 X++;
430         }
431
432 }
433
434 static void OneLine8(struct bmp_progressive_state *context)
435 {
436         gint X;
437         guchar *Pixels;
438
439         X = 0;
440         if (context->Header.Negative == 0)
441                 Pixels = (context->pixbuf->pixels +
442                           context->pixbuf->rowstride *
443                           (context->Header.height - context->Lines - 1));
444         else
445                 Pixels = (context->pixbuf->pixels +
446                           context->pixbuf->rowstride *
447                           context->Lines);
448         while (X < context->Header.width) {
449                 Pixels[X * 3 + 0] =
450                     context->HeaderBuf[4 * context->LineBuf[X] + 56];
451                 Pixels[X * 3 + 1] =
452                     context->HeaderBuf[4 * context->LineBuf[X] + 55];
453                 Pixels[X * 3 + 2] =
454                     context->HeaderBuf[4 * context->LineBuf[X] + 54];
455                 X++;
456         }
457 }
458
459 static void OneLine4(struct bmp_progressive_state *context)
460 {
461         gint X;
462         guchar *Pixels;
463
464         X = 0;
465         if (context->Header.Negative == 0)
466                 Pixels = (context->pixbuf->pixels +
467                           context->pixbuf->rowstride *
468                           (context->Header.height - context->Lines - 1));
469         else
470                 Pixels = (context->pixbuf->pixels +
471                           context->pixbuf->rowstride *
472                           context->Lines);
473
474         while (X < context->Header.width) {
475                 guchar Pix;
476
477                 Pix = context->LineBuf[X / 2];
478
479                 Pixels[X * 3 + 0] =
480                     context->HeaderBuf[4 * (Pix >> 4) + 56];
481                 Pixels[X * 3 + 1] =
482                     context->HeaderBuf[4 * (Pix >> 4) + 55];
483                 Pixels[X * 3 + 2] =
484                     context->HeaderBuf[4 * (Pix >> 4) + 54];
485                 X++;
486                 if (X < context->Header.width) {
487                         /* Handle the other 4 bit pixel only when there is one */
488                         Pixels[X * 3 + 0] =
489                             context->HeaderBuf[4 * (Pix & 15) + 56];
490                         Pixels[X * 3 + 1] =
491                             context->HeaderBuf[4 * (Pix & 15) + 55];
492                         Pixels[X * 3 + 2] =
493                             context->HeaderBuf[4 * (Pix & 15) + 54];
494                         X++;
495                 }
496         }
497
498 }
499
500 static void OneLine1(struct bmp_progressive_state *context)
501 {
502         gint X;
503         guchar *Pixels;
504
505         X = 0;
506         if (context->Header.Negative == 0)
507                 Pixels = (context->pixbuf->pixels +
508                           context->pixbuf->rowstride *
509                           (context->Header.height - context->Lines - 1));
510         else
511                 Pixels = (context->pixbuf->pixels +
512                           context->pixbuf->rowstride *
513                           context->Lines);
514         while (X < context->Header.width) {
515                 gint Bit;
516
517                 Bit = (context->LineBuf[X / 8]) >> (7 - (X & 7));
518                 Bit = Bit & 1;
519                 Pixels[X * 3 + 0] = Bit * 255;
520                 Pixels[X * 3 + 1] = Bit * 255;
521                 Pixels[X * 3 + 2] = Bit * 255;
522                 X++;
523         }
524 }
525
526
527 static void OneLine(struct bmp_progressive_state *context)
528 {
529         context->LineDone = 0;
530         if (context->Lines >= context->Header.height)
531                 return;
532
533         if (context->Type == 32)
534                 OneLine32(context);
535         if (context->Type == 24)
536                 OneLine24(context);
537         if (context->Type == 8)
538                 OneLine8(context);
539         if (context->Type == 4)
540                 OneLine4(context);
541         if (context->Type == 1)
542                 OneLine1(context);
543
544         context->Lines++;
545
546         if (context->updated_func != NULL) {
547                 (*context->updated_func) (context->pixbuf,
548                                           0,
549                                           context->Lines,
550                                           context->Header.width,
551                                           context->Header.height,
552                                           context->user_data);
553
554         }
555 }
556
557 /* DoCompressedByte handles 1 byte of incomming compressed data */
558 void DoCompressedByte(struct bmp_progressive_state *context, guchar ** buf,
559                       gint * size)
560 {
561         gint BytesToCopy;
562         switch (context->compr.phase) {
563         case 0:         /* Neutral state */
564                 if ((*buf)[0] != 0) {   /* run count */
565                         context->compr.phase = 1;
566                         context->compr.RunCount = (*buf)[0];
567
568                 } else {        /* Escape */
569                         context->compr.phase = 2;
570                 }
571                 (*buf)++;
572                 (*size)--;
573                 break;
574         case 1:         /* Run count received.... */
575                 while (context->compr.RunCount > 0) {
576                         BytesToCopy =
577                             context->LineWidth - context->LineDone;
578                         if (BytesToCopy > context->compr.RunCount)
579                                 BytesToCopy = context->compr.RunCount;
580                         if (BytesToCopy > 0) {
581                                 memset(context->LineBuf +
582                                        context->LineDone, (*buf)[0],
583                                        BytesToCopy);
584
585                                 context->compr.RunCount -= BytesToCopy;
586                                 context->LineDone += BytesToCopy;
587                         }
588                         if ((context->LineDone >= context->LineWidth)
589                             && (context->LineWidth > 0)) {
590                                 OneLine(context);
591                         }
592                 }
593                 context->compr.phase = 0;
594                 (*buf)++;
595                 (*size)--;
596                 break;
597         case 2:         /* Escape received */
598                 if ((*buf)[0] == 0) {   /* End of line */
599                         context->compr.phase = 0;
600                         if (context->LineDone > 0)
601                                 OneLine(context);
602                 } else if ((*buf)[0] == 1) {    /* End of image */
603                         OneLine(context);
604                         context->compr.phase = 6;
605                         (*size) = 0;
606                         break;
607                 } else if ((*buf)[0] == 2) {    /* Cursor displacement */
608                         context->compr.phase = 4;
609                 } else {
610                         context->compr.phase = 3;
611                         context->compr.RunCount = (*buf)[0];
612                         if (context->compr.RunCount & 1)
613                                 context->compr.phase = 7;
614
615                 }
616                 (*buf)++;
617                 (*size)--;
618
619                 break;
620         case 3:
621                 while ((context->compr.RunCount > 0)
622                        && (*size > 0)) {
623                         BytesToCopy =
624                             context->LineWidth - context->LineDone;
625                         if (BytesToCopy > context->compr.RunCount)
626                                 BytesToCopy = context->compr.RunCount;
627                         if (BytesToCopy > *size)
628                                 BytesToCopy = *size;
629
630                         if (BytesToCopy > 0) {
631                                 memcpy(context->LineBuf +
632                                        context->LineDone, *buf,
633                                        BytesToCopy);
634
635                                 context->compr.RunCount -= BytesToCopy;
636                                 (*buf) += BytesToCopy;
637                                 (*size) -= BytesToCopy;
638                                 context->LineDone += BytesToCopy;
639                         }
640                         if ((context->LineDone >= context->LineWidth)
641                             && (context->LineWidth > 0))
642                                 OneLine(context);
643                 }
644                 if (context->compr.RunCount <= 0)
645                         context->compr.phase = 0;
646
647                 break;
648         case 4:
649                 context->compr.phase = 5;
650                 context->compr.XDelta = (*buf)[0];
651                 (*buf)++;
652                 (*size)--;
653                 break;
654         case 5:
655                 context->compr.phase = 0;
656                 context->compr.YDelta = (*buf)[0];
657                 g_assert(0);    /* No implementatio of this yet */
658                 /* If this happens, please email me (arjan@fenrus.demon.nl)
659                    the image concerned. */
660                 (*buf)++;
661                 (*size)--;
662                 break;
663         case 6:
664                 (*size) = 0;
665                 break;
666         case 7:         /* Odd raw run */
667                 while ((context->compr.RunCount > 0) && (*size > 0)) {
668                         BytesToCopy =
669                             context->LineWidth - context->LineDone;
670                         if (BytesToCopy > context->compr.RunCount)
671                                 BytesToCopy = context->compr.RunCount;
672                         if (BytesToCopy > *size)
673                                 BytesToCopy = *size;
674
675                         if (BytesToCopy > 0) {
676                                 memcpy(context->LineBuf +
677                                        context->LineDone, *buf,
678                                        BytesToCopy);
679
680                                 context->compr.RunCount -= BytesToCopy;
681                                 (*buf) += BytesToCopy;
682                                 (*size) -= BytesToCopy;
683                                 context->LineDone += BytesToCopy;
684                         }
685                         if ((context->LineDone >= context->LineWidth)
686                             && (context->LineWidth > 0))
687                                 OneLine(context);
688                 }
689                 if (context->compr.RunCount <= 0)
690                         context->compr.phase = 8;
691
692                 break;
693         case 8:         /* Eat dummy byte; */
694                 (*buf)++;
695                 (*size)--;
696                 context->compr.phase = 0;
697                 break;
698         }
699 }
700
701 /*
702  * context - from image_begin_load
703  * buf - new image data
704  * size - length of new image data
705  *
706  * append image data onto inrecrementally built output image
707  */
708 gboolean gdk_pixbuf__bmp_image_load_increment(gpointer data,
709                                               guchar * buf,
710                                               guint size,
711                                               GError **error)
712 {
713         struct bmp_progressive_state *context =
714             (struct bmp_progressive_state *) data;
715
716         gint BytesToCopy;
717
718         while (size > 0) {
719                 g_assert(context->LineDone >= 0);
720                 if (context->HeaderDone < context->HeaderSize) {        /* We still 
721                                                                            have headerbytes to do */
722                         BytesToCopy =
723                             context->HeaderSize - context->HeaderDone;
724                         if (BytesToCopy > size)
725                                 BytesToCopy = size;
726
727                         memmove(context->HeaderBuf + context->HeaderDone,
728                                 buf, BytesToCopy);
729
730                         size -= BytesToCopy;
731                         buf += BytesToCopy;
732                         context->HeaderDone += BytesToCopy;
733
734                 } else if (context->Compressed) {
735                         /* Compression is done 1 byte at a time for now */
736                         DoCompressedByte(context, &buf, &size);
737
738                 } else {
739                         /* Uncompressed pixeldata */
740                         BytesToCopy =
741                             context->LineWidth - context->LineDone;
742                         if (BytesToCopy > size)
743                                 BytesToCopy = size;
744
745                         if (BytesToCopy > 0) {
746                                 memmove(context->LineBuf +
747                                         context->LineDone, buf,
748                                         BytesToCopy);
749
750                                 size -= BytesToCopy;
751                                 buf += BytesToCopy;
752                                 context->LineDone += BytesToCopy;
753                         }
754                         if ((context->LineDone >= context->LineWidth)
755                             && (context->LineWidth > 0))
756                                 OneLine(context);
757
758
759                 }
760
761                 if (context->HeaderDone >= 14 + 40)
762                         DecodeHeader(context->HeaderBuf,
763                                      context->HeaderBuf + 14, context);
764
765
766         }
767
768         return TRUE;
769 }