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 librararies 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 if (GetDataBlock(inbuf, (unsigned char*) buf, g) == 0)
252 lpos = LM_to_uint(buf[0], buf[1]);
253 tpos = LM_to_uint(buf[2], buf[3]);
254 width = LM_to_uint(buf[4], buf[5]);
255 height = LM_to_uint(buf[6], buf[7]);
258 foreground = buf[10];
259 background = buf[11];
261 while (GetDataBlock(inbuf, (unsigned char*) buf, g) != 0) {
262 PPM_ASSIGN(image[ypos][xpos],
273 case 0xff: /* Application Extension */
274 str = "Application Extension";
276 case 0xfe: /* Comment Extension */
277 str = "Comment Extension";
278 while (GetDataBlock(inbuf, (unsigned char*) buf, g) != 0) {
280 _gif_message("gif comment: %s", buf );
284 case 0xf9: /* Graphic Control Extension */
285 str = "Graphic Control Extension";
286 (void) GetDataBlock(inbuf, (unsigned char*) buf, g);
287 g->Gif89.disposal = (buf[0] >> 2) & 0x7;
288 g->Gif89.inputFlag = (buf[0] >> 1) & 0x1;
289 g->Gif89.delayTime = LM_to_uint(buf[1], buf[2]);
290 if ((buf[0] & 0x1) != 0)
291 g->Gif89.transparent = buf[3];
293 while (GetDataBlock(inbuf, (unsigned char*) buf, g) != 0)
298 sprintf(buf, "UNKNOWN (0x%02x)", label);
303 _gif_message("got a '%s' extension", str );
306 while (GetDataBlock(inbuf, (unsigned char*) buf, g) != 0)
312 /*********************/
314 GetCode(byte **inbuf, int code_size, int flag, GifState *g)
318 unsigned char *buf = g->buf;
321 for (i = 0; i < 280; i++)
330 if ( (g->curbit+code_size) >= g->lastbit) {
332 if (g->curbit >= g->lastbit)
333 _gif_error("ran off the end of my bits", 0 );
337 buf[0] = buf[g->last_byte-2];
338 buf[1] = buf[g->last_byte-1];
341 if ((count = GetDataBlock(inbuf, &buf[2], g)) == 0)
344 g->last_byte = 2 + count;
345 g->curbit = (g->curbit - g->lastbit) + 16;
346 g->lastbit = (2+count)*8 ;
350 for (i = g->curbit, j = 0; j < code_size; ++i, ++j)
351 ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j;
353 g->curbit += code_size;
358 /*********************/
360 LWZReadByte(byte **inbuf, int flag, int input_code_size, GifState *g)
366 g->set_code_size = input_code_size;
367 g->code_size = g->set_code_size+1;
368 g->clear_code = 1 << g->set_code_size ;
369 g->end_code = g->clear_code + 1;
370 g->max_code_size = 2*g->clear_code;
371 g->max_code = g->clear_code+2;
373 GetCode(inbuf, 0, TRUE, g);
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][0] = 0;
387 } else if (g->fresh) {
390 g->firstcode = g->oldcode =
391 GetCode(inbuf, g->code_size, FALSE, g);
392 } while (g->firstcode == g->clear_code);
396 if (g->sp > g->stack)
399 while ((code = GetCode(inbuf, g->code_size, FALSE, g)) >= 0) {
400 if (code == g->clear_code) {
401 for (i = 0; i < g->clear_code; ++i) {
405 for (; i < (1<<MAX_LWZ_BITS); ++i)
406 g->table[0][i] = g->table[1][i] = 0;
407 g->code_size = g->set_code_size+1;
408 g->max_code_size = 2*g->clear_code;
409 g->max_code = g->clear_code+2;
411 g->firstcode = g->oldcode =
412 GetCode(inbuf, g->code_size, FALSE, g);
414 } else if (code == g->end_code) {
416 unsigned char buf[260];
418 if (g->ZeroDataBlock)
421 while ((count = GetDataBlock(inbuf, buf, g)) > 0)
426 _gif_message("missing EOD in data stream (common occurence)");
433 if (code >= g->max_code) {
434 *(g->sp)++ = g->firstcode;
438 while (code >= g->clear_code) {
439 *(g->sp++) = g->table[1][code];
440 if (code == g->table[0][code])
441 _gif_error("circular table entry BIG ERROR", 0);
442 code = g->table[0][code];
445 *(g->sp)++ = g->firstcode = g->table[1][code];
447 if ((code = g->max_code) <(1<<MAX_LWZ_BITS)) {
448 g->table[0][code] = g->oldcode;
449 g->table[1][code] = g->firstcode;
451 if ((g->max_code >= g->max_code_size) &&
452 (g->max_code_size < (1<<MAX_LWZ_BITS))) {
453 g->max_code_size *= 2;
460 if (g->sp > g->stack)
466 /*********************/
468 ReadImage(byte **inbuf, int len, int height, unsigned char cmap[3][MAXCOLORMAPSIZE], int interlace, int ignore, GifState *g)
472 int xpos = 0, ypos = 0, pass = 0;
476 ** Initialize the Compression routines
481 if (LWZReadByte(inbuf, TRUE, c, g) < 0)
482 _gif_error("error reading image", 0 );
485 ** If this is an "uninteresting picture" ignore it.
489 _gif_message("skipping image..." );
491 while (LWZReadByte(inbuf, FALSE, c, g) >= 0)
496 if ((image = _gif_allocarray(len, height, sizeof(pixel))) == NULL)
497 _gif_error("couldn't alloc space for image", 0 );
500 _gif_message("reading %d by %d%s GIF image",
501 len, height, interlace ? " interlaced" : "" );
504 while ((v = LWZReadByte(inbuf,FALSE,c, g)) >= 0 ) {
505 PPM_ASSIGN(image[ypos][xpos], cmap[CM_RED][v],
506 cmap[CM_GREEN][v], cmap[CM_BLUE][v]);
522 if (ypos >= height) {
545 if (LWZReadByte(inbuf,FALSE,c, g)>=0)
546 _gif_message("too much input data, ignoring extra...");
553 /* ////////////////////////////////////////////////////////////
555 // ////////////////////////////////////////////////////////// */
557 enum _DtGrLoadStatus InitGifObject (
566 enum _DtGrColorModel colorModel,
567 Boolean allowReducedColors)
569 int r, g, b, i, visualsMatched;
570 XVisualInfo vTemplate, *visualList;
573 ** Initialize structure values
575 go->bits_per_pixel = 2;
576 go->colors_per_pixel = (int) pow (2, go->bits_per_pixel);
577 go->total_colors = (int) pow (go->colors_per_pixel, 3);
578 go->f_color_map_constructed = 0;
579 go->f_total_greys = 2;
582 go->f_drawable = drawable;
583 go->f_screen = XScreenNumberOfScreen(screen);
584 go->f_dft_depth = depth;
585 go->f_cmap = colormap;
587 go->f_visual = visual;
588 go->f_ncells = DisplayCells(go->f_dpy, go->f_screen);
589 go->f_nplanes = DisplayPlanes(go->f_dpy,go->f_screen);
590 go->f_white = WhitePixel(go->f_dpy, go->f_screen);
591 go->f_black = BlackPixel(go->f_dpy, go->f_screen);
592 go->f_allow_reduced_colors = allowReducedColors;
593 go->f_color_reduction_used = FALSE;
596 ** Initialize color allocation fields according to the color model
597 ** specified by the caller.
602 go->f_do_visual = DO_COLOR;
603 go->f_init_total_greys = 32;
605 case _DtGrGRAY_SCALE:
606 go->f_do_visual = DO_GREY;
607 go->f_init_total_greys = 32;
610 go->f_do_visual = DO_GREY;
611 go->f_init_total_greys = 2;
614 /* Should never get here */
615 go->f_do_visual = DO_COLOR;
616 go->f_init_total_greys = 32;
619 /* Return if the colormap is already allocated */
620 if ( go->f_color_map_constructed )
621 return (_DtGrSUCCESS);
623 /* find the visual class code */
625 vTemplate.screen = go->f_screen;
626 vTemplate.depth = go->f_dft_depth;
628 visualList = XGetVisualInfo( go->f_dpy,
629 VisualScreenMask | VisualDepthMask,
630 &vTemplate, &visualsMatched );
632 /* Return failure if we can't find a matching visual */
633 if ( visualsMatched == 0 )
634 return (_DtGrCONVERT_FAILURE);
636 go->f_visual_class = StaticGray;
638 for ( i=0; i<visualsMatched; i++ )
640 if ( visualList[i].visual == go->f_visual )
642 go->f_visual_class = visualList[i].class;
649 /* Construct a 4x4x4 color cube */
651 for (r = 0; r < go->colors_per_pixel; r++)
652 for (g = 0; g < go->colors_per_pixel; g++)
653 for (b = 0; b < go->colors_per_pixel; b++)
655 go->GifCMap[i].red = ((r * 65535)/(go->colors_per_pixel - 1));
656 go->GifCMap[i].green = ((g * 65535)/(go->colors_per_pixel - 1));
657 go->GifCMap[i].blue = ((b * 65535)/(go->colors_per_pixel - 1));
662 ** Allocate X pixels, either color or greyscale values depending upon
663 ** visual class and color model.
665 switch ( go->f_visual_class )
672 ** Return failure if caller is insisting on color and this
673 ** visual can't provide it.
675 if ((colorModel == _DtGrCOLOR) && !allowReducedColors)
676 return (_DtGrCOLOR_FAILED);
678 if ( allocate_greys(go) != 0 )
679 return (_DtGrCOLOR_FAILED);
688 if (colorModel == _DtGrCOLOR)
690 if ( allocate_colors(go) != 0 )
691 return (_DtGrCOLOR_FAILED);
695 if ( allocate_greys(go) != 0 )
696 return (_DtGrCOLOR_FAILED);
702 return (_DtGrCONVERT_FAILURE);
706 ** Colors successfully allocated, return status code indicating
707 ** whether we had to fallback to a degraded color model.
709 if (go->f_color_reduction_used)
710 return (_DtGrCOLOR_REDUCE);
712 return (_DtGrSUCCESS);
715 /* /////////////////////////////////////////////////////////////////
717 // /////////////////////////////////////////////////////////////// */
719 void DeleteGifObjectResources(GifObj *g)
723 int allocate_colors(GifObj *g)
726 /*return allocate_greys(); // use this to test grey-scale */
729 unsigned long* colors;
731 color.flags = DoRed | DoGreen | DoBlue;
733 for (i = 0; i < g->total_colors; i++) {
735 color.red = g->GifCMap[i].red;
736 color.green = g->GifCMap[i].green;
737 color.blue = g->GifCMap[i].blue;
739 /*printf ("Allocating %3d: ", i); */
740 if ( !XAllocColor (g->f_dpy, g->f_cmap, &color) ) {
742 /*puts ("FAILED!!!"); */
743 colors = (unsigned long *) malloc (sizeof(unsigned long) * i);
744 for (j = 0; j < i; j++)
745 colors[j] = g->GifCMap[j].pixel;
747 /*cerr << "Xfree in allocate_colors(): " << i << "\n"; */
748 XFreeColors (g->f_dpy, g->f_cmap, colors, i, 0);
752 /* fallback to greys */
753 if (g->f_allow_reduced_colors)
755 g->f_color_reduction_used = TRUE;
756 return allocate_greys(g);
759 return (_DtGrCOLOR_FAILED);
762 /*fprintf(stderr, "i=%d pixel=%d\n", i, color.pixel);*/
764 /*printf ("@ %d\n", color.pixel); */
765 g->GifCMap[i].pixel = color.pixel;
768 g->f_do_visual = DO_COLOR;
769 g->f_color_map_constructed = 1;
774 int allocate_greys(GifObj *g)
778 unsigned long* colors;
780 color.flags = DoRed | DoGreen | DoBlue;
782 for ( i=0; i<g->total_colors; i++ ) {
786 debug1(cerr, GifCMap[i].red);
787 debug1(cerr, GifCMap[i].green);
788 debug1(cerr, GifCMap[i].blue);
789 debug1(cerr, 0.299 * GifCMap[i].red + 0.587 * GifCMap[i].green +
790 0.114 * GifCMap[i].blue);
791 debug1(cerr, GifCMap[i].grey);
794 g->GifCMap[i].grey = (unsigned short)(0.299 * g->GifCMap[i].red +
795 0.587 * g->GifCMap[i].green +
796 0.114 * g->GifCMap[i].blue);
800 if ( StaticColor == g->f_visual_class ||
801 TrueColor == g->f_visual_class )
803 if ( StaticColor == g->f_visual_class)
805 g->f_do_visual = DO_GREY;
806 g->f_total_greys = 2;
811 for ( g->f_total_greys=g->f_init_total_greys; g->f_total_greys>=2;
812 g->f_total_greys/=2 )
814 /*fprintf(stderr, "f_total_greys = %d\n", g->f_total_greys); */
817 ** Return failure if we're about to downgrade from greyscale
818 ** to dithered monochrome and we don't allow reduced colors.
820 if ((g->f_total_greys == 2) && (g->f_init_total_greys > 2) &&
821 (!g->f_allow_reduced_colors))
824 for (i = 0; i<g->f_total_greys; i++) {
828 color.blue = (i*65535)/(g->f_total_greys - 1);
830 /*fprintf (stderr, "Allocating %3d: ", i);*/
831 if ( !XAllocColor (g->f_dpy, g->f_cmap, &color) ) {
833 /*fprintf(stderr, "alloc Grey FAILED!!!");*/
834 colors = (unsigned long *) malloc (sizeof(unsigned long) * i);
835 for (j = 0; j < i; j++)
836 colors[j] = g->GifGMap[j];
838 /*cerr << "Xfree in allocate_greys()\n"; */
839 XFreeColors (g->f_dpy, g->f_cmap, colors, i, 0);
846 /*printf ("@ %d\n", color.pixel); */
847 g->GifGMap[i] = color.pixel;
850 if ( i == g->f_total_greys ) {
853 for ( int l=0; l<i; l++ )
854 cerr << "GifGMap[l]= " << GifGMap[l] << "\n";
857 g->f_color_map_constructed = 1;
858 g->f_do_visual = DO_GREY;
859 /* If greyscape was downgraded to bitonal, record the fact */
860 if ((g->f_total_greys == 2) && (g->f_init_total_greys > 2))
861 g->f_color_reduction_used = TRUE;
869 /* ////////////////////////////////////////////////////////////
870 // Free allocated raw image data
871 // ////////////////////////////////////////////////////////// */
874 free_raw_image( pixel **image )
876 free( (char *)image[0] );
877 free( (char *)image );
880 /* ////////////////////////////////////////////////////////////
881 // Decompress GIF data into raw bytes
882 // ////////////////////////////////////////////////////////// */
885 create_raw_image( byte *inbuf, unsigned int buflen, int *width, int *height, int imageNumber )
888 unsigned char *start_of_buf = inbuf;
890 unsigned char localColorMap[3][MAXCOLORMAPSIZE];
891 int useGlobalColormap;
898 /* Initialize the GIF state object */
899 g.Gif89.transparent = g.Gif89.delayTime = g.Gif89.inputFlag = -1;
900 g.Gif89.disposal = 0;
901 g.ZeroDataBlock = FALSE;
906 fprintf (stderr, "Not GIF Data, buffer too small\n");
910 buf = (unsigned char *)inbuf;
913 if (strncmp((const char *)buf,"GIF",3) != 0) {
914 fprintf( stderr, "GifObject: not GIF data\n" );
918 strncpy(version, (const char *)(buf + 3), 3);
921 if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) {
922 fprintf (stderr, "bad version number, not '87a' or '89a'\n" );
926 buf = (unsigned char *)inbuf;
929 g.GifScreen.Width = LM_to_uint(buf[0],buf[1]);
930 g.GifScreen.Height = LM_to_uint(buf[2],buf[3]);
931 g.GifScreen.BitPixel = 2<<(buf[4]&0x07);
932 g.GifScreen.ColorResolution = (((buf[4]&0x70)>>3)+1);
933 g.GifScreen.Background = buf[5];
934 g.GifScreen.AspectRatio = buf[6];
936 if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */
937 if (ReadColorMap(&inbuf,g.GifScreen.BitPixel,g.GifScreen.ColorMap)) {
938 fprintf (stderr, "error reading global colormap\n" );
943 if (g.GifScreen.AspectRatio != 0 && g.GifScreen.AspectRatio != 49) {
945 r = ( (float) g.GifScreen.AspectRatio + 15.0 ) / 64.0;
947 _gif_message("warning - non-square pixels; to fix do a 'pnmscale -%cscale %g'",
949 r < 1.0 ? 1.0 / r : r );
956 if (inbuf - start_of_buf >= buflen) {
957 fprintf (stderr, "Premature EOF in GIF data\n");
963 if (c == ';') { /* GIF terminator */
964 if (imageCount < imageNumber)
965 _gif_error("only %d image%s found in file",
966 imageCount, imageCount>1?"s":"" );
970 if (c == '!') { /* Extension */
971 if (inbuf - start_of_buf >= buflen) {
972 fprintf (stderr, "Premature EOF in GIF data\n");
977 DoExtension(&inbuf, c, &g);
981 if (c != ',') { /* Not a valid start character */
983 _gif_message("bogus character 0x%02x, ignoring", (int) c );
990 buf = (unsigned char *)inbuf;
993 useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP);
995 bitPixel = 1<<((buf[8]&0x07)+1);
997 *width = LM_to_uint(buf[4],buf[5]);
998 *height = LM_to_uint(buf[6],buf[7]);
1000 if (! useGlobalColormap) {
1001 if (ReadColorMap(&inbuf, bitPixel, localColorMap))
1002 _gif_error("error reading local colormap", 0 );
1003 image = ReadImage(&inbuf, *width, *height, localColorMap,
1004 BitSet(buf[8], INTERLACE), imageCount != imageNumber,
1007 image = ReadImage(&inbuf, *width, *height, g.GifScreen.ColorMap,
1008 BitSet(buf[8], INTERLACE), imageCount != imageNumber,
1015 /* ////////////////////////////////////////////////////////////
1016 // Create X pixmap from raw image data
1017 // ////////////////////////////////////////////////////////// */
1019 /* from "Computer Graphics" by Foley, VanDam, Feiner, Hughes */
1021 static int dither_8X8[8][8] =
1023 { 0, 32, 8, 40, 2, 34, 10, 42 },
1024 { 48, 16, 56, 24, 50, 18, 58, 26 },
1025 { 42, 44, 4, 36, 14, 46, 6, 38 },
1026 { 60, 28, 52, 20, 62, 30, 54, 22 },
1027 { 3, 35, 11, 43, 1, 33, 9, 41 },
1028 { 51, 19, 59, 27, 49, 17, 57, 25 },
1029 { 15, 47, 7, 39, 13, 45, 5, 37 },
1030 { 63, 31, 55, 23, 61, 29, 53, 21 }
1033 /*static int dither_6X6[6][6] =
1035 // { 24, 32, 16, 26, 34, 18},
1036 // { 4, 0, 12, 6, 2, 14},
1037 // { 20, 8, 28, 22, 10, 30},
1038 // { 27, 35, 19, 25, 33, 17},
1039 // { 7, 3, 15, 5, 1, 13},
1040 // { 23, 11, 31, 21, 9, 29}
1045 static int dither_4X4[4][4] =
1054 static int dither_3X3[3][3] =
1062 static int dither_2X2[2][2] =
1069 /*static int dither_matrix_sz = 2; */
1070 /*static int dither_matrix_sz = 4; */
1071 /*static int dither_matrix_sz = 3; */
1072 static int dither_matrix_sz = 8;
1074 /* call XListPixFormat() to get bits/pix and pads ? */
1076 create_pixmap( GifObj *g, pixel **image, int width, int height, Pixel fg, Pixel bg, float ratio)
1078 int nullCount = (4 - (width % 4)) & 0x03;
1079 int ximWidth = width + nullCount;
1081 pixel *ipp = *image;
1087 int scaledWidth, scaledHeight;
1089 if ( g->f_nplanes > 8 )
1090 ximData = (byte *) malloc(ximWidth * height * 4 );
1092 ximData = (byte *) malloc(ximWidth * height );
1095 fprintf(stderr, "Could not allocate ximage data\n");
1100 if (g->f_nplanes == 1)
1101 g->f_ximage = XCreateImage(g->f_dpy, g->f_visual, g->f_nplanes, XYPixmap,
1102 0, (char *)ximData, width, height, 32, 0);
1104 /*else if (g->f_nplanes == 8) */
1106 /* non-mono display */
1108 g->f_ximage = XCreateImage(g->f_dpy, g->f_visual, g->f_nplanes, ZPixmap,
1109 0, (char *)ximData, width, height, 32, 0);
1112 fprintf(stderr, "XCreateImage failed\n");
1117 /* RGB to Pixel Conversion */
1119 if ( g->f_total_greys == 2 )
1120 spacing = 65536 / (dither_matrix_sz * dither_matrix_sz);
1122 spacing = 65536 / g->f_total_greys;
1124 /*cerr << "spacing" << spacing << "\n"; */
1126 for (y=0; y < height; y++) {
1127 for (x=0; x < width; x++) {
1128 pixval = (long)*ipp;
1130 /* XColor cellDef; */
1131 /* cellDef.red = (short)PPM_GETR(pixval); */
1132 /* cellDef.green = (short)PPM_GETG(pixval); */
1133 /* cellDef.blue = (short)PPM_GETB(pixval); */
1135 index = (((short)PPM_GETR(pixval))/64)*16 +
1136 (((short)PPM_GETG(pixval))/64)*4 +
1137 ((short)PPM_GETB(pixval))/64;
1139 /*fprintf(stderr, "grey= %d, grey/space=%d\n", g->GifCMap[index].grey, g->GifCMap[index].grey / spacing);*/
1140 switch (g->f_do_visual) {
1143 switch ( g->f_total_greys ) {
1146 /*cerr << "index=" << index << "\n"; */
1147 /*cerr << "GifCMap[index].grey" << GifCMap[index].grey << "\n"; */
1148 /*cerr << "GifCMap[index].grey/spacing" << GifCMap[index].grey / spacing << "\n"; */
1150 if ( dither_8X8[x%dither_matrix_sz][y%dither_matrix_sz] < g->GifCMap[index].grey / spacing ) {
1151 XPutPixel(g->f_ximage,x,y,g->f_white);
1153 XPutPixel(g->f_ximage,x,y,g->f_black);
1160 /*cerr << GifCMap[index].grey / spacing << " "; */
1162 XPutPixel(g->f_ximage,x,y, g->GifGMap[g->GifCMap[index].grey / spacing]);
1170 fprintf(stderr, "%03d %03d %03d -- %03d %03d %03d ",
1171 (short)PPM_GETR(pixval),(short)PPM_GETG(pixval),(short)PPM_GETB(pixval),
1172 g->GifCMap[index].red>>8, g->GifCMap[index].green>>8, g->GifCMap[index].blue>>8
1174 if ((short)PPM_GETR(pixval) != (GifCMap[index].red>>8) ||
1175 (short)PPM_GETG(pixval) != (GifCMap[index].green>>8) ||
1176 (short)PPM_GETB(pixval) != (GifCMap[index].blue>>8))
1183 XPutPixel(g->f_ximage,x,y, g->GifCMap[index].pixel);
1185 switch ( g->f_visual_class ) {
1188 XPutPixel(g->f_ximage,x,y, g->GifCMap[index].pixel);
1202 for (x=width;x<ximWidth;x++)
1203 XPutPixel(g->f_ximage,x,y,bg); /* padding */
1206 scaledWidth = width * ratio + 0.5;
1207 scaledHeight = height * ratio + 0.5;
1208 if (scaledWidth == 0)
1210 if (scaledHeight == 0)
1212 pm = XCreatePixmap(g->f_dpy,g->f_drawable,
1213 scaledWidth,scaledHeight,
1217 fprintf(stderr, "could not create pixmap\n");
1221 _XmPutScaledImage (g->f_dpy,pm,g->f_gc,g->f_ximage,
1222 0,0,0,0,width,height,
1223 scaledWidth,scaledHeight);
1225 XDestroyImage(g->f_ximage);
1232 /* /////////////////////////////////////////////////////////////////
1233 // Load pixmap from GIF data
1234 // /////////////////////////////////////////////////////////////// */
1237 gif_to_pixmap(GifObj *g, byte *inbuf, unsigned int buflen, Dimension *w, Dimension *h, Pixel fg, Pixel bg, float ratio)
1243 /* Create raw image from compress GIF data */
1244 raw_image = create_raw_image (inbuf, buflen, &width, &height, 1);
1245 if (!raw_image) return None;
1247 /* Create X pixmap from raw image data */
1248 pixmap = create_pixmap(g, raw_image, width, height, fg, bg, ratio);
1250 /* Free raw image data */
1251 free_raw_image(raw_image);
1253 /* Set X pixmap dimensions */
1254 *w = (Dimension) width * ratio + 0.5;
1255 *h = (Dimension) height * ratio + 0.5;
1260 /* Return X pixmap */