rnd-19981118-1
[rocksndiamonds.git] / src / gfxloader.c
1 /***********************************************************
2 *  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
3 *----------------------------------------------------------*
4 *  ©1995 Artsoft Development                               *
5 *        Holger Schemel                                    *
6 *        33659 Bielefeld-Senne                             *
7 *        Telefon: (0521) 493245                            *
8 *        eMail: aeglos@valinor.owl.de                      *
9 *               aeglos@uni-paderborn.de                    *
10 *               q99492@pbhrzx.uni-paderborn.de             *
11 *----------------------------------------------------------*
12 *  gfxloader.c                                             *
13 ***********************************************************/
14
15 #include "gfxloader.h"
16
17
18
19
20
21
22 extern Window           window;
23 extern void Delay(long);
24
25
26
27
28
29
30 #ifdef DEBUG
31 /*
32 #define DEBUG_GIF
33 #define DEBUG_ILBM
34 */
35 #endif
36
37 struct IFF_ILBM_FORM_big_endian
38 {
39   char magic_FORM[4];
40   unsigned char chunk_size[4];
41   char magic_ILBM[4];
42 };
43
44 struct IFF_ILBM_BMHD_big_endian
45 {
46   char Width[2], Height[2];
47   char LeftEdge[2], TopEdge[2];
48   char Depth;
49   char Mask;
50   char Compression;
51   char pad1;
52   char transparentColor[2];
53   char xAspect, yAspect;
54   char pageWidth[2], pageHeight[2];
55 };
56
57 struct IFF_ILBM_BMHD
58 {
59   unsigned int Width, Height;
60   int LeftEdge, TopEdge;
61   unsigned int Depth;
62   unsigned int Mask;
63   unsigned int Compression;
64   unsigned char pad1;
65   unsigned int transparentColor;
66   unsigned int xAspect, yAspect;
67   int pageWidth, pageHeight;
68 };
69
70 static int ConvertXImageDepth(Display *, XImage **);
71 static int Read_GIF_to_Pixmap_or_Bitmap(Display *, char *, Pixmap *, int);
72
73 #define READ_GIF_TO_BITMAP      0
74 #define READ_GIF_TO_PIXMAP      1
75
76
77 int Read_GIF_to_Bitmap(Display *display, char *filename, Pixmap *pixmap)
78 {
79   printf("Read_GIF_to_Bitmap\n");
80
81
82
83
84   return(Read_GIF_to_Pixmap_or_Bitmap(display, filename,
85                                       pixmap, READ_GIF_TO_BITMAP));
86 }
87
88 int Read_GIF_to_Pixmap(Display *display, char *filename, Pixmap *pixmap)
89 {
90   printf("Read_GIF_to_Pixmap\n");
91
92
93
94
95   return(Read_GIF_to_Pixmap_or_Bitmap(display, filename,
96                                       pixmap, READ_GIF_TO_PIXMAP));
97 }
98
99 int Read_GIF_to_Pixmap_or_Bitmap(Display *display, char *filename,
100                                  Pixmap *pixmap, int mode)
101 {
102   XImage *image = NULL;
103   Pixmap new_pixmap = 0;
104   int return_code;
105
106   *pixmap = 0;
107   return_code = Read_GIF_to_XImage(display, filename, &image);
108   if (return_code != GIF_Success)
109     return(return_code);
110
111   if (image)
112   {
113     int screen = DefaultScreen(display);
114     Drawable root = RootWindow(display,screen);
115     int depth = DefaultDepth(display, screen);
116     int width = image->width;
117     int height = image->height;
118
119     if (mode == READ_GIF_TO_BITMAP)
120     {
121       int i,x,y;
122       unsigned long black_pixel = BlackPixel(display,screen);
123       int bytes_per_line = (width+7) / 8;
124       int size = bytes_per_line * height;
125       char *data, *ptr;
126
127       data = (char *)malloc(size);
128       if (!data)
129         return(GIF_NoMemory);
130
131       ptr = data;
132       for(i=0;i<size;i++)
133         *ptr++ = 0;
134
135       for(y=0;y<height;y++)
136       {
137         for(x=0;x<width;x++)
138         {
139           if (XGetPixel(image,x,y) == black_pixel)
140             data[y * bytes_per_line + x/8] |= (1 << (x%8));
141         }
142       }
143
144       new_pixmap = XCreateBitmapFromData(display,root,data,width,height);
145       free(data);
146
147       if (!new_pixmap)
148         return(GIF_NoMemory);
149     }
150     else
151     {
152       GC gc;
153       XGCValues gcv;
154
155       if (ConvertXImageDepth(display, &image) != GIF_Success)
156         return(GIF_ColorFailed);
157
158       new_pixmap = XCreatePixmap(display,root,width,height,depth);
159
160       if (!new_pixmap)
161         return(GIF_NoMemory);
162
163       gcv.foreground = BlackPixel(display,screen);
164       gcv.background = WhitePixel(display,screen);
165       gc = XCreateGC(display, root, GCForeground | GCBackground, &gcv);
166       XPutImage(display,new_pixmap,gc,image,0,0,0,0,width,height);
167
168
169
170
171
172
173       Delay(1000000);
174
175       XPutImage(display,window,gc,image,0,0,0,0,width,height);
176
177       Delay(3000000);
178
179
180
181
182
183       XFreeGC(display, gc);
184     }
185
186     XDestroyImage(image);
187   }
188
189   *pixmap = new_pixmap;
190   return(return_code);
191 }
192
193
194 /*
195  * Read_GIF_to_XImage()  -  based strongly on...
196  *
197  * xgifload.c  -  based strongly on...
198  *
199  * gif2ras.c - Converts from a Compuserve GIF (tm) image to a Sun Raster image.
200  *
201  * Copyright (c) 1988, 1989 by Patrick J. Naughton
202  *
203  * Author: Patrick J. Naughton
204  * naughton@wind.sun.com
205  *
206  * Permission to use, copy, modify, and distribute this software and its
207  * documentation for any purpose and without fee is hereby granted,
208  * provided that the above copyright notice appear in all copies and that
209  * both that copyright notice and this permission notice appear in
210  * supporting documentation.
211  *
212  * This file is provided AS IS with no warranties of any kind.  The author
213  * shall have no liability with respect to the infringement of copyrights,
214  * trade secrets or any patents by this file or any part thereof.  In no
215  * event will the author be liable for any lost revenue or profits or
216  * other special, indirect and consequential damages.
217  *
218  */
219
220 typedef int boolean;
221 typedef unsigned char byte;
222
223 static int ReadCode(void);
224 static void AddToPixel(byte);
225 static int ColorDicking(Display *);
226
227 #define NEXTBYTE        (*ptr++)
228 #define IMAGESEP        0x2c
229 #define INTERLACEMASK   0x40
230 #define COLORMAPMASK    0x80
231
232 static
233 int BitOffset,                  /* Bit Offset of next code */
234     XC, YC,                     /* Output X and Y coords of current pixel */
235     Pass,                       /* Used by output routine if interlaced pic */
236     OutCount,                   /* Decompressor output 'stack count' */
237     RWidth, RHeight,            /* screen dimensions */
238     Width, Height,              /* image dimensions */
239     LeftOfs, TopOfs,            /* image offset */
240     BitsPerPixel,               /* Bits per pixel, read from GIF header */
241     BytesPerScanline,           /* bytes per scanline in output raster */
242     ColorMapSize,               /* number of colors */
243     Background,                 /* background color */
244     CodeSize,                   /* Code size, read from GIF header */
245     InitCodeSize,               /* Starting code size, used during Clear */
246     Code,                       /* Value returned by ReadCode */
247     MaxCode,                    /* limiting value for current code size */
248     ClearCode,                  /* GIF clear code */
249     EOFCode,                    /* GIF end-of-information code */
250     CurCode, OldCode, InCode,   /* Decompressor variables */
251     FirstFree,                  /* First free code, generated per GIF spec */
252     FreeCode,                   /* Decompressor, next free slot in hash table*/
253     FinChar,                    /* Decompressor variable */
254     BitMask,                    /* AND mask for data size */
255     ReadMask;                   /* Code AND mask for current code size */
256
257 static boolean Interlace, HasColormap;
258
259 static byte *ImageData;         /* The result array */
260 static byte *RawGIF;            /* The heap array to hold it, raw */
261 static byte *Raster;            /* The raster data stream, unblocked */
262
263 /* The color map, read from the GIF header */
264 static byte Red[256], Green[256], Blue[256], used[256];
265 static int  numused;
266
267 extern char *progname;
268
269 static int numcols;
270 static unsigned long cols[256];
271 static XColor defs[256];
272
273 int Read_GIF_to_XImage(Display *display, char *filename, XImage **image)
274 {
275   int filesize;
276   register byte ch, ch1;
277   register byte *ptr, *ptr1;
278   register int i;
279   int screen = DefaultScreen(display);
280   Visual *visual = DefaultVisual(display,screen);
281   XImage *new_image = NULL;
282   char *id = "GIF87a";
283   FILE *file;
284   int Prefix[4096];     /* The hash table used by the decompressor */
285   int Suffix[4096];
286   int OutCode[1025];    /* An output array used by the decompressor */
287
288   BitOffset = XC = YC = Pass = OutCount = 0;
289   *image = NULL;
290
291   if (strcmp(filename,"-")==0)
292   {
293     file = stdin;
294     filename = "<stdin>";
295   }
296   else
297     file = fopen(filename,"r");
298
299   if (!file)
300     return(GIF_OpenFailed);
301
302   /* find the size of the file */
303   fseek(file, 0L, 2);
304   filesize = ftell(file);
305   fseek(file, 0L, 0);
306
307   if (!(ptr = RawGIF = (byte *) malloc(filesize)))
308     return(GIF_NoMemory);
309
310   if (!(Raster = (byte *) malloc(filesize)))
311     return(GIF_NoMemory);
312
313   if (fread(ptr, filesize, 1, file) != 1)
314     return(GIF_ReadFailed);
315
316   if (strncmp(ptr, id, 6))
317     return(GIF_FileInvalid);
318
319   ptr += 6;
320
321   /* Get variables from the GIF screen descriptor */
322
323   ch = NEXTBYTE;
324   RWidth = ch + 0x100 * NEXTBYTE;    /* screen dimensions... not used. */
325   ch = NEXTBYTE;
326   RHeight = ch + 0x100 * NEXTBYTE;
327
328   ch = NEXTBYTE;
329   HasColormap = ((ch & COLORMAPMASK) ? True : False);
330
331   BitsPerPixel = (ch & 7) + 1;
332   numcols = ColorMapSize = 1 << BitsPerPixel;
333   BitMask = ColorMapSize - 1;
334
335   Background = NEXTBYTE;             /* background color... not used. */
336
337   if (NEXTBYTE)              /* supposed to be NULL */
338     return(GIF_FileInvalid);
339
340   /* Read in global colormap. */
341
342   if (HasColormap)
343   {
344     for (i = 0; i < ColorMapSize; i++)
345     {
346       Red[i] = NEXTBYTE;
347       Green[i] = NEXTBYTE;
348       Blue[i] = NEXTBYTE;
349       used[i] = 0;
350     }
351     numused = 0;
352   }
353   else
354   {
355     /* no colormap in GIF file */
356     fprintf(stderr,"%s:  warning!  no colortable in this file.  Winging it.\n",
357             progname);
358     if (!numcols)
359       numcols=256;
360     for (i=0; i<numcols; i++)
361       cols[i] = (unsigned long) i;
362   }
363
364   /* Check for image seperator */
365
366   if (NEXTBYTE != IMAGESEP)
367     return(GIF_FileInvalid);
368
369   /* Now read in values from the image descriptor */
370
371   ch = NEXTBYTE;
372   LeftOfs = ch + 0x100 * NEXTBYTE;
373   ch = NEXTBYTE;
374   TopOfs = ch + 0x100 * NEXTBYTE;
375   ch = NEXTBYTE;
376   Width = ch + 0x100 * NEXTBYTE;
377   ch = NEXTBYTE;
378   Height = ch + 0x100 * NEXTBYTE;
379   Interlace = ((NEXTBYTE & INTERLACEMASK) ? True : False);
380
381 #ifdef DEBUG_GIF
382   fprintf(stderr, "%s:\n", filename);
383   fprintf(stderr, "   %dx%d, %d bpp / %d colors, %sinterlaced\n",
384           Width,Height, BitsPerPixel,ColorMapSize,(Interlace ? "" : "non-"));
385   fprintf(stderr, "   Reading file... ");
386 #endif
387
388   /* Note that I ignore the possible existence of a local color map.
389    * I'm told there aren't many files around that use them, and the spec
390    * says it's defined for future use.  This could lead to an error
391    * reading some files. 
392    */
393
394   /* Start reading the raster data. First we get the intial code size
395    * and compute decompressor constant values, based on this code size.
396    */
397
398   CodeSize = NEXTBYTE;
399   ClearCode = (1 << CodeSize);
400   EOFCode = ClearCode + 1;
401     FreeCode = FirstFree = ClearCode + 2;
402
403   /* The GIF spec has it that the code size is the code size used to
404    * compute the above values is the code size given in the file, but the
405    * code size used in compression/decompression is the code size given in
406    * the file plus one. (thus the ++).
407    */
408
409   CodeSize++;
410   InitCodeSize = CodeSize;
411   MaxCode = (1 << CodeSize);
412   ReadMask = MaxCode - 1;
413
414   /* Read the raster data.  Here we just transpose it from the GIF array
415    * to the Raster array, turning it from a series of blocks into one long
416    * data stream, which makes life much easier for ReadCode().
417    */
418
419   ptr1 = Raster;
420   do
421   {
422     ch = ch1 = NEXTBYTE;
423     while (ch--) *ptr1++ = NEXTBYTE;
424     if ((Raster - ptr1) > filesize)
425       return(GIF_FileInvalid);
426   }
427   while(ch1);
428
429   free(RawGIF);              /* We're done with the raw data now... */
430
431 #ifdef DEBUG_GIF
432   fprintf(stderr, "done\n");
433   fprintf(stderr, "   Decompressing... ");
434 #endif
435
436   /* Allocate the X Image */
437   ImageData = (byte *) malloc(Width*Height);
438   if (!ImageData)
439     return(GIF_NoMemory);
440
441   new_image = XCreateImage(display,visual,8,ZPixmap,0,ImageData,
442                            Width,Height,8,Width);
443   if (!new_image)
444     return(GIF_NoMemory);
445
446   BytesPerScanline = Width;
447
448
449   /* Decompress the file, continuing until you see the GIF EOF code.
450    * One obvious enhancement is to add checking for corrupt files here.
451    */
452
453   Code = ReadCode();
454   while (Code != EOFCode)
455   {
456     /* Clear code sets everything back to its initial value, then reads the
457      * immediately subsequent code as uncompressed data.
458      */
459
460     if (Code == ClearCode)
461     {
462       CodeSize = InitCodeSize;
463       MaxCode = (1 << CodeSize);
464       ReadMask = MaxCode - 1;
465       FreeCode = FirstFree;
466       CurCode = OldCode = Code = ReadCode();
467       FinChar = CurCode & BitMask;
468       AddToPixel(FinChar);
469     }
470     else
471     {
472       /* If not a clear code, then must be data:
473        * save same as CurCode and InCode
474        */
475
476       CurCode = InCode = Code;
477
478       /* If greater or equal to FreeCode, not in the hash table yet;
479        * repeat the last character decoded
480        */
481
482       if (CurCode >= FreeCode)
483       {
484         CurCode = OldCode;
485         OutCode[OutCount++] = FinChar;
486       }
487
488       /* Unless this code is raw data, pursue the chain pointed to by CurCode
489        * through the hash table to its end; each code in the chain puts its
490        * associated output code on the output queue.
491        */
492
493       while (CurCode > BitMask)
494       {
495         if (OutCount > 1024)
496           return(GIF_FileInvalid);
497
498         OutCode[OutCount++] = Suffix[CurCode];
499         CurCode = Prefix[CurCode];
500       }
501
502       /* The last code in the chain is treated as raw data. */
503
504       FinChar = CurCode & BitMask;
505       OutCode[OutCount++] = FinChar;
506
507       /* Now we put the data out to the Output routine.
508        * It's been stacked LIFO, so deal with it that way...
509        */
510
511       for (i = OutCount - 1; i >= 0; i--)
512         AddToPixel(OutCode[i]);
513       OutCount = 0;
514
515       /* Build the hash table on-the-fly. No table is stored in the file. */
516
517       Prefix[FreeCode] = OldCode;
518       Suffix[FreeCode] = FinChar;
519       OldCode = InCode;
520
521       /* Point to the next slot in the table.  If we exceed the current
522        * MaxCode value, increment the code size unless it's already 12.  If it
523        * is, do nothing: the next code decompressed better be CLEAR
524        */
525
526       FreeCode++;
527       if (FreeCode >= MaxCode)
528       {
529         if (CodeSize < 12)
530         {
531           CodeSize++;
532           MaxCode *= 2;
533           ReadMask = (1 << CodeSize) - 1;
534         }
535       }
536     }
537     Code = ReadCode();
538   }
539
540   free(Raster);
541
542 #ifdef DEBUG_GIF
543   fprintf(stderr, "done\n");
544   fprintf(stderr,"   %d colors used\n",numused);
545 #endif
546
547   if (file != stdin)
548     fclose(file);
549
550   if (ColorDicking(display) != GIF_Success)
551     return(GIF_ColorFailed);
552
553   *image = new_image;
554   return(GIF_Success);
555 }
556
557
558 /* Fetch the next code from the raster data stream.  The codes can be
559  * any length from 3 to 12 bits, packed into 8-bit bytes, so we have to
560  * maintain our location in the Raster array as a BIT Offset.  We compute
561  * the byte Offset into the raster array by dividing this by 8, pick up
562  * three bytes, compute the bit Offset into our 24-bit chunk, shift to
563  * bring the desired code to the bottom, then mask it off and return it. 
564  */
565
566 static int ReadCode()
567 {
568   int RawCode, ByteOffset;
569
570   ByteOffset = BitOffset / 8;
571   RawCode = Raster[ByteOffset] + (0x100 * Raster[ByteOffset + 1]);
572   if (CodeSize >= 8)
573     RawCode += (0x10000 * Raster[ByteOffset + 2]);
574   RawCode >>= (BitOffset % 8);
575   BitOffset += CodeSize;
576   return(RawCode & ReadMask);
577 }
578
579
580 static void AddToPixel(byte Index)
581 {
582   if (YC<Height)
583     *(ImageData + YC * BytesPerScanline + XC) = Index;
584
585   if (!used[Index])
586   {
587     used[Index]=1;
588     numused++;
589   }
590
591   /* Update the X-coordinate, and if it overflows, update the Y-coordinate */
592
593   if (++XC == Width)
594   {
595     /* If a non-interlaced picture, just increment YC to the next scan line. 
596      * If it's interlaced, deal with the interlace as described in the GIF
597      * spec.  Put the decoded scan line out to the screen if we haven't gone
598      * past the bottom of it
599      */
600
601     XC = 0;
602     if (!Interlace)
603       YC++;
604     else
605     {
606       switch (Pass)
607       {
608         case 0:
609           YC += 8;
610           if (YC >= Height)
611           {
612             Pass++;
613             YC = 4;
614           }
615           break;
616
617         case 1:
618           YC += 8;
619           if (YC >= Height)
620           {
621             Pass++;
622             YC = 2;
623           }
624           break;
625
626         case 2:
627           YC += 4;
628           if (YC >= Height)
629           {
630             Pass++;
631             YC = 1;
632           }
633           break;
634
635         case 3:
636           YC += 2;
637           break;
638
639         default:
640           break;
641         }
642     }
643   }
644 }
645
646
647 static int ColorDicking(Display *display)
648 {
649   /* we've got the picture loaded, we know what colors are needed. get 'em */
650
651   register int i,j;
652   static byte lmasks[8] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80};
653   byte lmask, *ptr;
654   int screen = DefaultScreen(display);
655   Colormap cmap = DefaultColormap(display,screen);
656   int dispcells = DisplayCells(display,screen);
657
658   int strip = 0;
659   int nostrip = 0; 
660
661   if (!HasColormap)
662     return(GIF_Success);
663   /* no need to allocate any colors if no colormap in GIF file */
664
665   /* Allocate the X colors for this picture */
666
667   if (nostrip)
668   {
669     /* nostrip was set.  try REAL hard to do it */
670     for (i=j=0; i<numcols; i++)
671     {
672       if (used[i])
673       {
674         defs[i].red   = Red[i]<<8;
675         defs[i].green = Green[i]<<8;
676         defs[i].blue  = Blue[i]<<8;
677         defs[i].flags = DoRed | DoGreen | DoBlue;
678         if (!XAllocColor(display,cmap,&defs[i]))
679         { 
680           j++;
681           defs[i].pixel = 0xffff;
682         }
683         cols[i] = defs[i].pixel;
684       }
685     }
686
687     if (j)
688     {
689       /* failed to pull it off */
690
691       XColor ctab[256];
692       int dc;
693
694       dc = (dispcells<256) ? dispcells : 256;
695
696       fprintf(stderr,
697               "failed to allocate %d out of %d colors.  Trying extra hard.\n",
698               j,numused);
699
700       /* read in the color table */
701       for (i=0; i<dc; i++)
702         ctab[i].pixel = i;
703       XQueryColors(display,cmap,ctab,dc);
704                 
705       /* run through the used colors.  any used color that has a pixel
706          value of 0xffff wasn't allocated.  for such colors, run through
707          the entire X colormap and pick the closest color */
708
709       for (i=0; i<numcols; i++)
710         if (used[i] && cols[i]==0xffff)
711         {
712           /* an unallocated pixel */
713
714           int d, mdist, close;
715           unsigned long r,g,b;
716
717           mdist = 100000;   close = -1;
718           r =  Red[i];
719           g =  Green[i];
720           b =  Blue[i];
721           for (j=0; j<dc; j++)
722           {
723             d = abs(r - (ctab[j].red>>8)) +
724               abs(g - (ctab[j].green>>8)) +
725                 abs(b - (ctab[j].blue>>8));
726             if (d<mdist)
727             {
728               mdist=d;
729               close=j;
730             }
731           }
732
733           if (close<0)
734             return(GIF_ColorFailed);
735
736           bcopy(&defs[close],&defs[i],sizeof(XColor));
737           cols[i] = ctab[close].pixel;
738         }
739     }  /* end 'failed to pull it off' */
740   }
741   else
742   {
743     /* strip wasn't set, do the best auto-strip */
744
745     j = 0;
746     while (strip<8)
747     {
748       lmask = lmasks[strip];
749       for (i=0; i<numcols; i++)
750       {
751         if (used[i])
752         {
753           defs[i].red   = (Red[i]  &lmask)<<8;
754           defs[i].green = (Green[i]&lmask)<<8;
755           defs[i].blue  = (Blue[i] &lmask)<<8;
756           defs[i].flags = DoRed | DoGreen | DoBlue;
757           if (!XAllocColor(display,cmap,&defs[i]))
758             break;
759           cols[i] = defs[i].pixel;
760         }
761       }
762
763       if (i<numcols)
764       {
765         /* failed */
766         strip++;
767         j++;
768         for (i--; i>=0; i--)
769           if (used[i])
770             XFreeColors(display,cmap,cols+i,1,0L);
771       }
772       else
773         break;
774     }
775
776 #ifdef DEBUG_GIF
777     if (j && strip<8)
778       fprintf(stderr,"%s: stripped %d bits\n",progname,strip);
779 #endif
780
781     if (strip==8)
782     {
783       fprintf(stderr,"UTTERLY failed to allocate the desired colors.\n");
784       for (i=0; i<numcols; i++) cols[i]=i;
785     }
786   }
787
788   ptr = ImageData;
789   for (i=0; i<Height; i++)
790     for (j=0; j<Width; j++,ptr++) 
791       *ptr = (byte) cols[*ptr];
792
793   return(GIF_Success);
794 }
795
796
797 /******************************************************************************
798  *  This makes sure the display's depth is the same as the
799  * depth of the default 8 bit image.  If not, we build a new image
800  * that has the correct depth.  This works on the fact that
801  * the color mapper has already changed every pixel value in the
802  * image into the proper number of bits (to fit into the pallet)
803  * so we can just chop down the number of bits.
804  *   This changes the global variable 'expImage' if necessary.
805  */
806
807 static int ConvertXImageDepth(Display *display, XImage **image)
808 {
809   int screen = DefaultScreen(display);
810   int depth = DefaultDepth(display, screen);
811
812
813
814
815
816
817   printf("ConvertXImageDepth:\n");
818   printf("(*image)->depth == %d\n",
819          (*image)->depth);
820   printf("DefaultDepth(display, screen) == %d\n",
821          DefaultDepth(display, screen));
822
823
824
825
826   if ((*image)->depth != depth)
827   {
828     XImage *old_image, *new_image;
829     /*
830     Visual *visual = DefaultVisual(display,screen);
831     */
832     int width = (*image)->width;
833     int height = (*image)->height;
834     register int dwx, dwy;
835     byte *data;
836
837
838
839
840
841     printf("ConvertXImageDepth: ---------> CONVERTING...\n");
842
843
844
845
846
847
848     data = (byte *)malloc(width * height * depth);
849     old_image = *image;
850
851     /*
852     new_image = XCreateImage(display,visual,depth,
853                              ZPixmap,0,data,width,height,8,0);
854                              */
855
856     new_image = XGetImage(display,RootWindow(display,screen),
857                           0,0,width,height,0xffffffff,ZPixmap);
858
859
860     if (!new_image)
861       return(GIF_NoMemory);
862
863     if (old_image->depth == 8 && new_image->depth == 4)
864     {
865       /* speedup for the most common format change */
866
867       register byte *sptr = (byte *)old_image->data;
868       register byte *dptr = (byte *)new_image->data;
869
870       for (dwy=1; dwy<=height; dwy++)
871       {
872         for (dwx=1; dwx<width; dwx+=2)
873         {
874           *dptr = (*sptr) | (*(sptr+1)<<4);
875           dptr++;
876           sptr+=2;
877         }
878         if (width & 1)
879         {
880           /* if extra pixal at end of line, just move it */
881           *dptr = *sptr;
882           sptr++; dptr++;
883         }
884       }
885     }
886     else        /* other format change than 8 bit -> 4 bit */
887     {
888       unsigned long pixel_value;
889
890       for (dwx=0; dwx<width; dwx++)
891       {
892         for (dwy=0; dwy<height; dwy++)
893         {
894           pixel_value = XGetPixel(old_image, dwx, dwy);
895
896           if (pixel_value > 0xff)
897             printf("pixel = %lx", pixel_value);
898
899           XPutPixel(new_image, dwx, dwy, pixel_value);
900         }
901       }
902     }
903
904     free(old_image->data);
905     old_image->data = NULL;
906     XDestroyImage(old_image);
907
908     *image = new_image;
909   }
910
911   return(GIF_Success);
912 }
913
914
915 static unsigned long be2long(unsigned char *be) /* big-endian -> long int */
916 {
917   return((be[0]<<24) | (be[1]<<16) | (be[2]<<8) | be[3]);
918 }
919
920 static unsigned short be2short(unsigned char *be) /* big-endian -> short int */
921 {
922   return((be[0]<<8) | be[1]);
923 }
924
925 static struct IFF_ILBM_BMHD *ConvertBMHD(unsigned char *header_data)
926 {
927   struct IFF_ILBM_BMHD_big_endian *bmhd_be;
928   struct IFF_ILBM_BMHD *bmhd;
929
930   bmhd_be = (struct IFF_ILBM_BMHD_big_endian *)header_data;
931   bmhd = (struct IFF_ILBM_BMHD *)malloc(sizeof(struct IFF_ILBM_BMHD));
932   if (!bmhd)
933     return(NULL);
934
935   bmhd->Width = be2short(bmhd_be->Width);
936   bmhd->Height = be2short(bmhd_be->Height);
937   bmhd->LeftEdge = be2short(bmhd_be->LeftEdge);
938   bmhd->TopEdge = be2short(bmhd_be->TopEdge);
939   bmhd->Depth = (int)bmhd_be->Depth;
940   bmhd->Mask = (int)bmhd_be->Mask;
941   bmhd->Compression = (int)bmhd_be->Compression;
942   bmhd->pad1 = bmhd_be->pad1;
943   bmhd->transparentColor = be2short(bmhd_be->transparentColor);
944   bmhd->xAspect = (int)bmhd_be->xAspect;
945   bmhd->yAspect = (int)bmhd_be->yAspect;
946   bmhd->pageWidth = be2short(bmhd_be->pageWidth);
947   bmhd->pageHeight = be2short(bmhd_be->pageHeight);
948
949   return(bmhd);
950 }
951
952 static unsigned char MSBitFirst2LSBitFirst(unsigned char msb_byte)
953 {
954   unsigned char lsb_byte = 0;
955   int i;
956
957   for(i=7;i>=0;i--)
958   {
959     lsb_byte |= (msb_byte & 1) << i;
960     msb_byte >>= 1;
961   }
962
963   return(lsb_byte);
964 }
965
966 int Read_ILBM_to_Bitmap(Display *display, char *filename, Pixmap *pixmap)
967 {
968   Pixmap new_pixmap = 0;
969   int screen = DefaultScreen(display);
970   Drawable root = RootWindow(display,screen);
971   struct IFF_ILBM_FORM_big_endian *form_header;
972   struct IFF_ILBM_BMHD *bitmap_header;
973   unsigned long file_len, body_len;
974   unsigned char *file_data, *bitmap_data;
975   unsigned char *file_ptr, *bitmap_ptr, *body_ptr;
976   unsigned char byte_count, byte_value;
977   int i,x,y,z;
978   int width, height, depth;
979   int bytes_per_line, bitmap_size;
980   FILE *file;
981
982
983
984
985
986   printf("Read_ILBM_to_Bitmap\n");
987
988
989
990
991   if (!(file = fopen(filename,"r")))
992     return(ILBM_OpenFailed);
993
994   if (fseek(file,0,SEEK_END) < 0)
995   {
996     fclose(file);
997     return(ILBM_ReadFailed);
998   }
999
1000   file_len = ftell(file);
1001   rewind(file);
1002
1003   if (!(file_data = (unsigned char *)malloc(file_len)))
1004   {
1005     fclose(file);
1006     return(ILBM_NoMemory);
1007   }
1008
1009   if (fread(file_data,1,file_len,file) != file_len)
1010   {
1011     free(file_data);
1012     fclose(file);
1013     return(ILBM_ReadFailed);
1014   }
1015
1016   fclose(file);
1017
1018   form_header = (struct IFF_ILBM_FORM_big_endian *)file_data;
1019
1020   if (strncmp(form_header->magic_FORM,"FORM",4) ||
1021       file_len != be2long(form_header->chunk_size)+8 ||
1022       strncmp(form_header->magic_ILBM,"ILBM",4))
1023   {
1024 #ifdef DEBUG_ILBM
1025       printf("%s: IFF chunk 'FORM' and/or 'ILBM' not found.\n",filename);
1026 #endif
1027     free(file_data);
1028     return(ILBM_FileInvalid);
1029   }
1030
1031   bitmap_header = NULL;
1032   body_ptr = NULL;
1033   file_ptr = file_data + 12;
1034
1035   while(file_ptr < (unsigned char *)(file_data + file_len))
1036   {
1037     if (!strncmp(file_ptr,"BMHD",4))
1038     {
1039 #ifdef DEBUG_ILBM
1040       printf("%s: IFF chunk 'BMHD' found.\n",filename);
1041 #endif
1042       bitmap_header = ConvertBMHD(file_ptr + 8);
1043       file_ptr += be2long(file_ptr + 4) + 8;
1044       continue;
1045     }
1046     else if (!strncmp(file_ptr,"BODY",4))
1047     {
1048 #ifdef DEBUG_ILBM
1049       printf("%s: IFF chunk 'BODY' found.\n",filename);
1050 #endif
1051       body_ptr = file_ptr + 8;
1052       body_len = be2long(file_ptr + 4);
1053       file_ptr += be2long(file_ptr + 4) + 8;
1054       continue;
1055     }
1056     else
1057     {
1058 #ifdef DEBUG_ILBM
1059       printf("%s: IFF chunk '%c%c%c%c' found (but not used).\n",filename,
1060              file_ptr[0],file_ptr[1],file_ptr[2],file_ptr[3]);
1061 #endif
1062       /* other chunk not recognized here */
1063       file_ptr += be2long(file_ptr + 4) + 8;
1064       continue;
1065     }
1066   }
1067
1068   if (!bitmap_header || !body_ptr)
1069   {
1070 #ifdef DEBUG_ILBM
1071       printf("%s: IFF chunk 'BMHD' and/or 'BODY' not found.\n",filename);
1072 #endif
1073     free(file_data);
1074     return(ILBM_FileInvalid);
1075   }
1076
1077   width = bitmap_header->Width;
1078   height = bitmap_header->Height;
1079   depth = bitmap_header->Depth;
1080
1081 #ifdef DEBUG_ILBM
1082   if (depth > 1)
1083     printf("%s: %d bitplanes found; using only the first plane.\n",
1084            filename,depth);
1085 #endif
1086
1087   bytes_per_line = ((width + 15) / 16) * 2;
1088   bitmap_size = bytes_per_line * height;
1089
1090   bitmap_data = (char *)malloc(bitmap_size);
1091   if (!bitmap_data)
1092   {
1093     free(file_data);
1094     free(bitmap_header);
1095     return(ILBM_NoMemory);
1096   }
1097
1098   bitmap_ptr = bitmap_data;
1099   for(i=0;i<bitmap_size;i++)
1100     *bitmap_ptr++ = 0;
1101
1102   for(y=0;y<height;y++)
1103   {
1104     /* we only read the first bitplane here to create a black/white bitmap */
1105
1106     for(z=0;z<depth;z++)
1107     {
1108       bitmap_ptr = bitmap_data + y * bytes_per_line;
1109       x = 0;
1110
1111       if (!bitmap_header->Compression)
1112       {
1113         while(x++ < bytes_per_line)
1114           *bitmap_ptr++ |= MSBitFirst2LSBitFirst(*body_ptr++);
1115       }
1116       else
1117       {
1118         while(x < bytes_per_line)
1119         {
1120           byte_count = *body_ptr++;
1121
1122           if (byte_count <= 128)
1123           {
1124             for(i=0;i<byte_count+1;i++)
1125               *bitmap_ptr++ |= MSBitFirst2LSBitFirst(*body_ptr++);
1126             x += byte_count + 1;
1127           }
1128           else
1129           {
1130             byte_value = *body_ptr++;
1131             for(i=0;i<257-byte_count;i++)
1132               *bitmap_ptr++ |= MSBitFirst2LSBitFirst(byte_value);
1133             x += 257 - byte_count;
1134           }
1135         }
1136       }
1137     }
1138   }
1139
1140   bitmap_ptr = bitmap_data;
1141   for(i=0;i<bitmap_size;i++)
1142     *bitmap_ptr++ ^= 0xff;
1143
1144   new_pixmap = XCreateBitmapFromData(display,root,bitmap_data,width,height);
1145
1146   free(file_data);
1147   free(bitmap_data);
1148   free(bitmap_header);
1149
1150   if (!new_pixmap)
1151     return(ILBM_NoMemory);
1152
1153   *pixmap = new_pixmap;
1154   return(ILBM_Success);
1155 }