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