2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * $XConsortium: GifUtils.c /main/5 1996/05/07 13:21:42 drk $
25 * Copyright (c) 1993 HAL Computer Systems International, Ltd.
26 * All rights reserved. Unpublished -- rights reserved under
27 * the Copyright Laws of the United States. USE OF A COPYRIGHT
28 * NOTICE IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION
31 * THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND TRADE
32 * SECRETS OF HAL COMPUTER SYSTEMS INTERNATIONAL, LTD. USE,
33 * DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE
34 * PRIOR EXPRESS WRITTEN PERMISSION OF HAL COMPUTER SYSTEMS
37 * RESTRICTED RIGHTS LEGEND
38 * Use, duplication, or disclosure by the Government is subject
39 * to the restrictions as set forth in subparagraph (c)(l)(ii)
40 * of the Rights in Technical Data and Computer Software clause
41 * at DFARS 252.227-7013.
43 * HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.
50 /* +-------------------------------------------------------------------+ */
51 /* | Portions lifted from giftoppm.c (pbmplus version 10dec91) | */
53 /* | Copyright 1990, David Koblas. | */
54 /* | Permission to use, copy, modify, and distribute this software | */
55 /* | and its documentation for any purpose and without fee is hereby | */
56 /* | granted, provided that the above copyright notice appear in all | */
57 /* | copies and that both that copyright notice and this permission | */
58 /* | notice appear in supporting documentation. This software is | */
59 /* | provided "as is" without express or implied warranty. | */
60 /* +-------------------------------------------------------------------+ */
74 #include <Xm/XmPrivate.h>
75 #include "GifUtilsI.h"
78 #define debug1(s, x) s << "x" << " = " << (x) << "\n"
80 #define debug1(s, x) s << #x << " = " << (x) << "\n"
83 #define MAX_GHANDS 16 /* maximum # of GRAF handles */
85 #define PPM_ASSIGN(p,red,grn,blu) (p) = ((pixel) (red) << 20) | ((pixel) (grn) << 10) | (pixel) (blu)
86 #define PPM_GETR(p) (((p) & 0x3ff00000) >> 20)
87 #define PPM_GETG(p) (((p) & 0xffc00) >> 10)
88 #define PPM_GETB(p) ((p) & 0x3ff)
90 #define MAXCOLORMAPSIZE 256
99 #define MAX_LWZ_BITS 12
101 #define INTERLACE 0x40
102 #define LOCALCOLORMAP 0x80
103 #define BitSet(byte, bit) (((byte) & (bit)) == (bit))
105 #define LM_to_uint(a,b) (((b)<<8)|(a))
110 unsigned char ColorMap[3][MAXCOLORMAPSIZE];
111 unsigned int BitPixel;
112 unsigned int ColorResolution;
113 unsigned int Background;
114 unsigned int AspectRatio;
125 * This structure holds variables that were formerly global or static
126 * within a function in the original giftoppm code. They have been
127 * moved into this object to ensure thread re-entrancy of the routines
128 * that use them. A unique instance of this object is created for each
129 * thread and passed to the appropriate routines.
132 /* Formerly global variables */
133 GifScreenType GifScreen;
136 /* Formerly static variables declared in DoExtension */
138 /* Formerly static variables declared in GetCode */
139 unsigned char buf[280];
140 int curbit, lastbit, done, last_byte;
141 /* Formerly static variables declared in LWZReadByte*/
143 int code_size, set_code_size;
144 int max_code, max_code_size;
145 int firstcode, oldcode;
146 int clear_code, end_code;
147 int table[2][(1<< MAX_LWZ_BITS)];
148 int stack[(1<<(MAX_LWZ_BITS))*2], *sp;
151 /*********************/
153 _gif_error( char *format, ... )
157 va_start( args, format );
159 fprintf( stderr, "GifObject: " );
160 (void) vfprintf( stderr, format, args );
161 fputc( '\n', stderr );
163 /* throw (Exception()); */
169 /*********************/
171 _gif_message( char *format, ... )
175 va_start( args, format );
177 fprintf( stderr, "GifObject: " );
178 (void) vfprintf( stderr, format, args );
179 fputc( '\n', stderr );
183 /*********************/
185 _gif_allocarray( int cols, int rows, int size )
190 its = (char**) malloc( rows * sizeof(char*) );
191 if ( its == (char**) 0 )
192 _gif_error( "out of memory allocating an array", 0 );
193 its[0] = (char*) malloc( rows * cols * size );
194 if ( its[0] == (char*) 0 )
195 _gif_error( "out of memory allocating an array", 0 );
196 for ( i = 1; i < rows; ++i )
197 its[i] = &(its[0][i * cols * size]);
198 return (pixel **)its;
201 /*********************/
203 GetDataBlock(byte **inbuf, unsigned char *buf, GifState *g)
210 g->ZeroDataBlock = count == 0;
213 memcpy (buf, *inbuf, count);
220 /*********************/
222 ReadColorMap(byte **inbuf, int number, unsigned char buffer[3][MAXCOLORMAPSIZE])
227 for (i = 0; i < number; ++i) {
228 rgb = (unsigned char *)*inbuf;
231 buffer[CM_RED][i] = rgb[0] ;
232 buffer[CM_GREEN][i] = rgb[1] ;
233 buffer[CM_BLUE][i] = rgb[2] ;
238 /*********************/
240 DoExtension(byte **inbuf, int label, GifState *g)
243 char *buf = g->ext_buf;
246 case 0x01: /* Plain Text Extension */
247 str = "Plain Text Extension";
249 case 0xff: /* Application Extension */
250 str = "Application Extension";
252 case 0xfe: /* Comment Extension */
253 str = "Comment Extension";
254 while (GetDataBlock(inbuf, (unsigned char*) buf, g) != 0) {
256 _gif_message("gif comment: %s", buf );
260 case 0xf9: /* Graphic Control Extension */
261 str = "Graphic Control Extension";
262 (void) GetDataBlock(inbuf, (unsigned char*) buf, g);
263 g->Gif89.disposal = (buf[0] >> 2) & 0x7;
264 g->Gif89.inputFlag = (buf[0] >> 1) & 0x1;
265 g->Gif89.delayTime = LM_to_uint(buf[1], buf[2]);
266 if ((buf[0] & 0x1) != 0)
267 g->Gif89.transparent = buf[3];
269 while (GetDataBlock(inbuf, (unsigned char*) buf, g) != 0)
274 sprintf(buf, "UNKNOWN (0x%02x)", label);
279 _gif_message("got a '%s' extension", str );
282 while (GetDataBlock(inbuf, (unsigned char*) buf, g) != 0)
288 /*********************/
290 GetCode(byte **inbuf, int code_size, int flag, GifState *g)
294 unsigned char *buf = g->buf;
297 for (i = 0; i < 280; i++)
306 if ( (g->curbit+code_size) >= g->lastbit) {
308 if (g->curbit >= g->lastbit)
309 _gif_error("ran off the end of my bits", 0 );
313 buf[0] = buf[g->last_byte-2];
314 buf[1] = buf[g->last_byte-1];
317 if ((count = GetDataBlock(inbuf, &buf[2], g)) == 0)
320 g->last_byte = 2 + count;
321 g->curbit = (g->curbit - g->lastbit) + 16;
322 g->lastbit = (2+count)*8 ;
326 for (i = g->curbit, j = 0; j < code_size; ++i, ++j)
327 ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j;
329 g->curbit += code_size;
334 /*********************/
336 LWZReadByte(byte **inbuf, int flag, int input_code_size, GifState *g)
342 g->set_code_size = input_code_size;
343 g->code_size = g->set_code_size+1;
344 g->clear_code = 1 << g->set_code_size ;
345 g->end_code = g->clear_code + 1;
346 g->max_code_size = 2*g->clear_code;
347 g->max_code = g->clear_code+2;
349 GetCode(inbuf, 0, TRUE, g);
353 for (i = 0; i < g->clear_code; ++i) {
357 for (; i < (1<<MAX_LWZ_BITS); ++i)
358 g->table[0][i] = g->table[1][0] = 0;
363 } else if (g->fresh) {
366 g->firstcode = g->oldcode =
367 GetCode(inbuf, g->code_size, FALSE, g);
368 } while (g->firstcode == g->clear_code);
372 if (g->sp > g->stack)
375 while ((code = GetCode(inbuf, g->code_size, FALSE, g)) >= 0) {
376 if (code == g->clear_code) {
377 for (i = 0; i < g->clear_code; ++i) {
381 for (; i < (1<<MAX_LWZ_BITS); ++i)
382 g->table[0][i] = g->table[1][i] = 0;
383 g->code_size = g->set_code_size+1;
384 g->max_code_size = 2*g->clear_code;
385 g->max_code = g->clear_code+2;
387 g->firstcode = g->oldcode =
388 GetCode(inbuf, g->code_size, FALSE, g);
390 } else if (code == g->end_code) {
392 unsigned char buf[260];
394 if (g->ZeroDataBlock)
397 while ((count = GetDataBlock(inbuf, buf, g)) > 0)
402 _gif_message("missing EOD in data stream (common occurence)");
409 if (code >= g->max_code) {
410 *(g->sp)++ = g->firstcode;
414 while (code >= g->clear_code) {
415 *(g->sp++) = g->table[1][code];
416 if (code == g->table[0][code])
417 _gif_error("circular table entry BIG ERROR", 0);
418 code = g->table[0][code];
421 *(g->sp)++ = g->firstcode = g->table[1][code];
423 if ((code = g->max_code) <(1<<MAX_LWZ_BITS)) {
424 g->table[0][code] = g->oldcode;
425 g->table[1][code] = g->firstcode;
427 if ((g->max_code >= g->max_code_size) &&
428 (g->max_code_size < (1<<MAX_LWZ_BITS))) {
429 g->max_code_size *= 2;
436 if (g->sp > g->stack)
442 /*********************/
444 ReadImage(byte **inbuf, int len, int height, unsigned char cmap[3][MAXCOLORMAPSIZE], int interlace, int ignore, GifState *g)
448 int xpos = 0, ypos = 0, pass = 0;
452 ** Initialize the Compression routines
457 if (LWZReadByte(inbuf, TRUE, c, g) < 0)
458 _gif_error("error reading image", 0 );
461 ** If this is an "uninteresting picture" ignore it.
465 _gif_message("skipping image..." );
467 while (LWZReadByte(inbuf, FALSE, c, g) >= 0)
472 if ((image = _gif_allocarray(len, height, sizeof(pixel))) == NULL)
473 _gif_error("couldn't alloc space for image", 0 );
476 _gif_message("reading %d by %d%s GIF image",
477 len, height, interlace ? " interlaced" : "" );
480 while ((v = LWZReadByte(inbuf,FALSE,c, g)) >= 0 ) {
481 PPM_ASSIGN(image[ypos][xpos], cmap[CM_RED][v],
482 cmap[CM_GREEN][v], cmap[CM_BLUE][v]);
498 if (ypos >= height) {
521 if (LWZReadByte(inbuf,FALSE,c, g)>=0)
522 _gif_message("too much input data, ignoring extra...");
529 /* ////////////////////////////////////////////////////////////
531 // ////////////////////////////////////////////////////////// */
533 enum _DtGrLoadStatus InitGifObject (
542 enum _DtGrColorModel colorModel,
543 Boolean allowReducedColors)
545 int r, g, b, i, visualsMatched;
546 XVisualInfo vTemplate, *visualList;
549 ** Initialize structure values
551 go->bits_per_pixel = 2;
552 go->colors_per_pixel = (int) pow (2, go->bits_per_pixel);
553 go->total_colors = (int) pow (go->colors_per_pixel, 3);
554 go->f_color_map_constructed = 0;
555 go->f_total_greys = 2;
558 go->f_drawable = drawable;
559 go->f_screen = XScreenNumberOfScreen(screen);
560 go->f_dft_depth = depth;
561 go->f_cmap = colormap;
563 go->f_visual = visual;
564 go->f_ncells = DisplayCells(go->f_dpy, go->f_screen);
565 go->f_nplanes = DisplayPlanes(go->f_dpy,go->f_screen);
566 go->f_white = WhitePixel(go->f_dpy, go->f_screen);
567 go->f_black = BlackPixel(go->f_dpy, go->f_screen);
568 go->f_allow_reduced_colors = allowReducedColors;
569 go->f_color_reduction_used = FALSE;
572 ** Initialize color allocation fields according to the color model
573 ** specified by the caller.
578 go->f_do_visual = DO_COLOR;
579 go->f_init_total_greys = 32;
581 case _DtGrGRAY_SCALE:
582 go->f_do_visual = DO_GREY;
583 go->f_init_total_greys = 32;
586 go->f_do_visual = DO_GREY;
587 go->f_init_total_greys = 2;
590 /* Should never get here */
591 go->f_do_visual = DO_COLOR;
592 go->f_init_total_greys = 32;
595 /* Return if the colormap is already allocated */
596 if ( go->f_color_map_constructed )
597 return (_DtGrSUCCESS);
599 /* find the visual class code */
601 vTemplate.screen = go->f_screen;
602 vTemplate.depth = go->f_dft_depth;
604 visualList = XGetVisualInfo( go->f_dpy,
605 VisualScreenMask | VisualDepthMask,
606 &vTemplate, &visualsMatched );
608 /* Return failure if we can't find a matching visual */
609 if ( visualsMatched == 0 )
610 return (_DtGrCONVERT_FAILURE);
612 go->f_visual_class = StaticGray;
614 for ( i=0; i<visualsMatched; i++ )
616 if ( visualList[i].visual == go->f_visual )
618 go->f_visual_class = visualList[i].class;
625 /* Construct a 4x4x4 color cube */
627 for (r = 0; r < go->colors_per_pixel; r++)
628 for (g = 0; g < go->colors_per_pixel; g++)
629 for (b = 0; b < go->colors_per_pixel; b++)
631 go->GifCMap[i].red = ((r * 65535)/(go->colors_per_pixel - 1));
632 go->GifCMap[i].green = ((g * 65535)/(go->colors_per_pixel - 1));
633 go->GifCMap[i].blue = ((b * 65535)/(go->colors_per_pixel - 1));
638 ** Allocate X pixels, either color or greyscale values depending upon
639 ** visual class and color model.
641 switch ( go->f_visual_class )
648 ** Return failure if caller is insisting on color and this
649 ** visual can't provide it.
651 if ((colorModel == _DtGrCOLOR) && !allowReducedColors)
652 return (_DtGrCOLOR_FAILED);
654 if ( allocate_greys(go) != 0 )
655 return (_DtGrCOLOR_FAILED);
664 if (colorModel == _DtGrCOLOR)
666 if ( allocate_colors(go) != 0 )
667 return (_DtGrCOLOR_FAILED);
671 if ( allocate_greys(go) != 0 )
672 return (_DtGrCOLOR_FAILED);
678 return (_DtGrCONVERT_FAILURE);
682 ** Colors successfully allocated, return status code indicating
683 ** whether we had to fallback to a degraded color model.
685 if (go->f_color_reduction_used)
686 return (_DtGrCOLOR_REDUCE);
688 return (_DtGrSUCCESS);
691 /* /////////////////////////////////////////////////////////////////
693 // /////////////////////////////////////////////////////////////// */
695 void DeleteGifObjectResources(GifObj *g)
699 int allocate_colors(GifObj *g)
702 /*return allocate_greys(); // use this to test grey-scale */
705 unsigned long* colors;
707 color.flags = DoRed | DoGreen | DoBlue;
709 for (i = 0; i < g->total_colors; i++) {
711 color.red = g->GifCMap[i].red;
712 color.green = g->GifCMap[i].green;
713 color.blue = g->GifCMap[i].blue;
715 /*printf ("Allocating %3d: ", i); */
716 if ( !XAllocColor (g->f_dpy, g->f_cmap, &color) ) {
718 /*puts ("FAILED!!!"); */
719 colors = (unsigned long *) malloc (sizeof(unsigned long) * i);
720 for (j = 0; j < i; j++)
721 colors[j] = g->GifCMap[j].pixel;
723 /*cerr << "Xfree in allocate_colors(): " << i << "\n"; */
724 XFreeColors (g->f_dpy, g->f_cmap, colors, i, 0);
728 /* fallback to greys */
729 if (g->f_allow_reduced_colors)
731 g->f_color_reduction_used = TRUE;
732 return allocate_greys(g);
735 return (_DtGrCOLOR_FAILED);
738 /*fprintf(stderr, "i=%d pixel=%d\n", i, color.pixel);*/
740 /*printf ("@ %d\n", color.pixel); */
741 g->GifCMap[i].pixel = color.pixel;
744 g->f_do_visual = DO_COLOR;
745 g->f_color_map_constructed = 1;
750 int allocate_greys(GifObj *g)
754 unsigned long* colors;
756 color.flags = DoRed | DoGreen | DoBlue;
758 for ( i=0; i<g->total_colors; i++ ) {
762 debug1(cerr, GifCMap[i].red);
763 debug1(cerr, GifCMap[i].green);
764 debug1(cerr, GifCMap[i].blue);
765 debug1(cerr, 0.299 * GifCMap[i].red + 0.587 * GifCMap[i].green +
766 0.114 * GifCMap[i].blue);
767 debug1(cerr, GifCMap[i].grey);
770 g->GifCMap[i].grey = (unsigned short)(0.299 * g->GifCMap[i].red +
771 0.587 * g->GifCMap[i].green +
772 0.114 * g->GifCMap[i].blue);
776 if ( StaticColor == g->f_visual_class ||
777 TrueColor == g->f_visual_class )
779 if ( StaticColor == g->f_visual_class)
781 g->f_do_visual = DO_GREY;
782 g->f_total_greys = 2;
787 for ( g->f_total_greys=g->f_init_total_greys; g->f_total_greys>=2;
788 g->f_total_greys/=2 )
790 /*fprintf(stderr, "f_total_greys = %d\n", g->f_total_greys); */
793 ** Return failure if we're about to downgrade from greyscale
794 ** to dithered monochrome and we don't allow reduced colors.
796 if ((g->f_total_greys == 2) && (g->f_init_total_greys > 2) &&
797 (!g->f_allow_reduced_colors))
800 for (i = 0; i<g->f_total_greys; i++) {
804 color.blue = (i*65535)/(g->f_total_greys - 1);
806 /*fprintf (stderr, "Allocating %3d: ", i);*/
807 if ( !XAllocColor (g->f_dpy, g->f_cmap, &color) ) {
809 /*fprintf(stderr, "alloc Grey FAILED!!!");*/
810 colors = (unsigned long *) malloc (sizeof(unsigned long) * i);
811 for (j = 0; j < i; j++)
812 colors[j] = g->GifGMap[j];
814 /*cerr << "Xfree in allocate_greys()\n"; */
815 XFreeColors (g->f_dpy, g->f_cmap, colors, i, 0);
822 /*printf ("@ %d\n", color.pixel); */
823 g->GifGMap[i] = color.pixel;
826 if ( i == g->f_total_greys ) {
829 for ( int l=0; l<i; l++ )
830 cerr << "GifGMap[l]= " << GifGMap[l] << "\n";
833 g->f_color_map_constructed = 1;
834 g->f_do_visual = DO_GREY;
835 /* If greyscape was downgraded to bitonal, record the fact */
836 if ((g->f_total_greys == 2) && (g->f_init_total_greys > 2))
837 g->f_color_reduction_used = TRUE;
845 /* ////////////////////////////////////////////////////////////
846 // Free allocated raw image data
847 // ////////////////////////////////////////////////////////// */
850 free_raw_image( pixel **image )
852 free( (char *)image[0] );
853 free( (char *)image );
856 /* ////////////////////////////////////////////////////////////
857 // Decompress GIF data into raw bytes
858 // ////////////////////////////////////////////////////////// */
861 create_raw_image( byte *inbuf, unsigned int buflen, int *width, int *height, int imageNumber )
864 unsigned char *start_of_buf = inbuf;
866 unsigned char localColorMap[3][MAXCOLORMAPSIZE];
867 int useGlobalColormap;
874 /* Initialize the GIF state object */
875 g.Gif89.transparent = g.Gif89.delayTime = g.Gif89.inputFlag = -1;
876 g.Gif89.disposal = 0;
877 g.ZeroDataBlock = FALSE;
882 fprintf (stderr, "Not GIF Data, buffer too small\n");
886 buf = (unsigned char *)inbuf;
889 if (strncmp((const char *)buf,"GIF",3) != 0) {
890 fprintf( stderr, "GifObject: not GIF data\n" );
894 strncpy(version, (const char *)(buf + 3), 3);
897 if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) {
898 fprintf (stderr, "bad version number, not '87a' or '89a'\n" );
902 buf = (unsigned char *)inbuf;
905 g.GifScreen.Width = LM_to_uint(buf[0],buf[1]);
906 g.GifScreen.Height = LM_to_uint(buf[2],buf[3]);
907 g.GifScreen.BitPixel = 2<<(buf[4]&0x07);
908 g.GifScreen.ColorResolution = (((buf[4]&0x70)>>3)+1);
909 g.GifScreen.Background = buf[5];
910 g.GifScreen.AspectRatio = buf[6];
912 if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */
913 if (ReadColorMap(&inbuf,g.GifScreen.BitPixel,g.GifScreen.ColorMap)) {
914 fprintf (stderr, "error reading global colormap\n" );
919 if (g.GifScreen.AspectRatio != 0 && g.GifScreen.AspectRatio != 49) {
921 r = ( (float) g.GifScreen.AspectRatio + 15.0 ) / 64.0;
923 _gif_message("warning - non-square pixels; to fix do a 'pnmscale -%cscale %g'",
925 r < 1.0 ? 1.0 / r : r );
932 if (inbuf - start_of_buf >= buflen) {
933 fprintf (stderr, "Premature EOF in GIF data\n");
939 if (c == ';') { /* GIF terminator */
940 if (imageCount < imageNumber)
941 _gif_error("only %d image%s found in file",
942 imageCount, imageCount>1?"s":"" );
946 if (c == '!') { /* Extension */
947 if (inbuf - start_of_buf >= buflen) {
948 fprintf (stderr, "Premature EOF in GIF data\n");
953 DoExtension(&inbuf, c, &g);
957 if (c != ',') { /* Not a valid start character */
959 _gif_message("bogus character 0x%02x, ignoring", (int) c );
966 buf = (unsigned char *)inbuf;
969 useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP);
971 bitPixel = 1<<((buf[8]&0x07)+1);
973 *width = LM_to_uint(buf[4],buf[5]);
974 *height = LM_to_uint(buf[6],buf[7]);
976 if (! useGlobalColormap) {
977 if (ReadColorMap(&inbuf, bitPixel, localColorMap))
978 _gif_error("error reading local colormap", 0 );
979 image = ReadImage(&inbuf, *width, *height, localColorMap,
980 BitSet(buf[8], INTERLACE), imageCount != imageNumber,
983 image = ReadImage(&inbuf, *width, *height, g.GifScreen.ColorMap,
984 BitSet(buf[8], INTERLACE), imageCount != imageNumber,
991 /* ////////////////////////////////////////////////////////////
992 // Create X pixmap from raw image data
993 // ////////////////////////////////////////////////////////// */
995 /* from "Computer Graphics" by Foley, VanDam, Feiner, Hughes */
997 static int dither_8X8[8][8] =
999 { 0, 32, 8, 40, 2, 34, 10, 42 },
1000 { 48, 16, 56, 24, 50, 18, 58, 26 },
1001 { 42, 44, 4, 36, 14, 46, 6, 38 },
1002 { 60, 28, 52, 20, 62, 30, 54, 22 },
1003 { 3, 35, 11, 43, 1, 33, 9, 41 },
1004 { 51, 19, 59, 27, 49, 17, 57, 25 },
1005 { 15, 47, 7, 39, 13, 45, 5, 37 },
1006 { 63, 31, 55, 23, 61, 29, 53, 21 }
1009 /*static int dither_6X6[6][6] =
1011 // { 24, 32, 16, 26, 34, 18},
1012 // { 4, 0, 12, 6, 2, 14},
1013 // { 20, 8, 28, 22, 10, 30},
1014 // { 27, 35, 19, 25, 33, 17},
1015 // { 7, 3, 15, 5, 1, 13},
1016 // { 23, 11, 31, 21, 9, 29}
1021 static int dither_4X4[4][4] =
1030 static int dither_3X3[3][3] =
1038 static int dither_2X2[2][2] =
1045 /*static int dither_matrix_sz = 2; */
1046 /*static int dither_matrix_sz = 4; */
1047 /*static int dither_matrix_sz = 3; */
1048 static int dither_matrix_sz = 8;
1050 /* call XListPixFormat() to get bits/pix and pads ? */
1052 create_pixmap( GifObj *g, pixel **image, int width, int height, Pixel fg, Pixel bg, float ratio)
1054 int nullCount = (4 - (width % 4)) & 0x03;
1055 int ximWidth = width + nullCount;
1057 pixel *ipp = *image;
1063 int scaledWidth, scaledHeight;
1065 if ( g->f_nplanes > 8 )
1066 ximData = (byte *) malloc(ximWidth * height * 4 );
1068 ximData = (byte *) malloc(ximWidth * height );
1071 fprintf(stderr, "Could not allocate ximage data\n");
1076 if (g->f_nplanes == 1)
1077 g->f_ximage = XCreateImage(g->f_dpy, g->f_visual, g->f_nplanes, XYPixmap,
1078 0, (char *)ximData, width, height, 32, 0);
1080 /*else if (g->f_nplanes == 8) */
1082 /* non-mono display */
1084 g->f_ximage = XCreateImage(g->f_dpy, g->f_visual, g->f_nplanes, ZPixmap,
1085 0, (char *)ximData, width, height, 32, 0);
1088 fprintf(stderr, "XCreateImage failed\n");
1093 /* RGB to Pixel Conversion */
1095 if ( g->f_total_greys == 2 )
1096 spacing = 65536 / (dither_matrix_sz * dither_matrix_sz);
1098 spacing = 65536 / g->f_total_greys;
1100 /*cerr << "spacing" << spacing << "\n"; */
1102 for (y=0; y < height; y++) {
1103 for (x=0; x < width; x++) {
1104 pixval = (long)*ipp;
1106 /* XColor cellDef; */
1107 /* cellDef.red = (short)PPM_GETR(pixval); */
1108 /* cellDef.green = (short)PPM_GETG(pixval); */
1109 /* cellDef.blue = (short)PPM_GETB(pixval); */
1111 index = (((short)PPM_GETR(pixval))/64)*16 +
1112 (((short)PPM_GETG(pixval))/64)*4 +
1113 ((short)PPM_GETB(pixval))/64;
1115 /*fprintf(stderr, "grey= %d, grey/space=%d\n", g->GifCMap[index].grey, g->GifCMap[index].grey / spacing);*/
1116 switch (g->f_do_visual) {
1119 switch ( g->f_total_greys ) {
1122 /*cerr << "index=" << index << "\n"; */
1123 /*cerr << "GifCMap[index].grey" << GifCMap[index].grey << "\n"; */
1124 /*cerr << "GifCMap[index].grey/spacing" << GifCMap[index].grey / spacing << "\n"; */
1126 if ( dither_8X8[x%dither_matrix_sz][y%dither_matrix_sz] < g->GifCMap[index].grey / spacing ) {
1127 XPutPixel(g->f_ximage,x,y,g->f_white);
1129 XPutPixel(g->f_ximage,x,y,g->f_black);
1136 /*cerr << GifCMap[index].grey / spacing << " "; */
1138 XPutPixel(g->f_ximage,x,y, g->GifGMap[g->GifCMap[index].grey / spacing]);
1146 fprintf(stderr, "%03d %03d %03d -- %03d %03d %03d ",
1147 (short)PPM_GETR(pixval),(short)PPM_GETG(pixval),(short)PPM_GETB(pixval),
1148 g->GifCMap[index].red>>8, g->GifCMap[index].green>>8, g->GifCMap[index].blue>>8
1150 if ((short)PPM_GETR(pixval) != (GifCMap[index].red>>8) ||
1151 (short)PPM_GETG(pixval) != (GifCMap[index].green>>8) ||
1152 (short)PPM_GETB(pixval) != (GifCMap[index].blue>>8))
1159 XPutPixel(g->f_ximage,x,y, g->GifCMap[index].pixel);
1161 switch ( g->f_visual_class ) {
1164 XPutPixel(g->f_ximage,x,y, g->GifCMap[index].pixel);
1178 for (x=width;x<ximWidth;x++)
1179 XPutPixel(g->f_ximage,x,y,bg); /* padding */
1182 scaledWidth = width * ratio + 0.5;
1183 scaledHeight = height * ratio + 0.5;
1184 if (scaledWidth == 0)
1186 if (scaledHeight == 0)
1188 pm = XCreatePixmap(g->f_dpy,g->f_drawable,
1189 scaledWidth,scaledHeight,
1193 fprintf(stderr, "could not create pixmap\n");
1197 _XmPutScaledImage (g->f_dpy,pm,g->f_gc,g->f_ximage,
1198 0,0,0,0,width,height,
1199 scaledWidth,scaledHeight);
1201 XDestroyImage(g->f_ximage);
1208 /* /////////////////////////////////////////////////////////////////
1209 // Load pixmap from GIF data
1210 // /////////////////////////////////////////////////////////////// */
1213 gif_to_pixmap(GifObj *g, byte *inbuf, unsigned int buflen, Dimension *w, Dimension *h, Pixel fg, Pixel bg, float ratio)
1219 /* Create raw image from compress GIF data */
1220 raw_image = create_raw_image (inbuf, buflen, &width, &height, 1);
1221 if (!raw_image) return None;
1223 /* Create X pixmap from raw image data */
1224 pixmap = create_pixmap(g, raw_image, width, height, fg, bg, ratio);
1226 /* Free raw image data */
1227 free_raw_image(raw_image);
1229 /* Set X pixmap dimensions */
1230 *w = (Dimension) width * ratio + 0.5;
1231 *h = (Dimension) height * ratio + 0.5;
1236 /* Return X pixmap */