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 "GifUtilsI.h"
77 #define debug1(s, x) s << "x" << " = " << (x) << "\n"
79 #define debug1(s, x) s << #x << " = " << (x) << "\n"
82 #define MAX_GHANDS 16 /* maximum # of GRAF handles */
84 #define PPM_ASSIGN(p,red,grn,blu) (p) = ((pixel) (red) << 20) | ((pixel) (grn) << 10) | (pixel) (blu)
85 #define PPM_GETR(p) (((p) & 0x3ff00000) >> 20)
86 #define PPM_GETG(p) (((p) & 0xffc00) >> 10)
87 #define PPM_GETB(p) ((p) & 0x3ff)
89 #define MAXCOLORMAPSIZE 256
98 #define MAX_LWZ_BITS 12
100 #define INTERLACE 0x40
101 #define LOCALCOLORMAP 0x80
102 #define BitSet(byte, bit) (((byte) & (bit)) == (bit))
104 #define LM_to_uint(a,b) (((b)<<8)|(a))
109 unsigned char ColorMap[3][MAXCOLORMAPSIZE];
110 unsigned int BitPixel;
111 unsigned int ColorResolution;
112 unsigned int Background;
113 unsigned int AspectRatio;
124 * This structure holds variables that were formerly global or static
125 * within a function in the original giftoppm code. They have been
126 * moved into this object to ensure thread re-entrancy of the routines
127 * that use them. A unique instance of this object is created for each
128 * thread and passed to the appropriate routines.
131 /* Formerly global variables */
132 GifScreenType GifScreen;
135 /* Formerly static variables declared in DoExtension */
137 /* Formerly static variables declared in GetCode */
138 unsigned char buf[280];
139 int curbit, lastbit, done, last_byte;
140 /* Formerly static variables declared in LWZReadByte*/
142 int code_size, set_code_size;
143 int max_code, max_code_size;
144 int firstcode, oldcode;
145 int clear_code, end_code;
146 int table[2][(1<< MAX_LWZ_BITS)];
147 int stack[(1<<(MAX_LWZ_BITS))*2], *sp;
150 /*********************/
152 _gif_error( char *format, ... )
156 va_start( args, format );
158 fprintf( stderr, "GifObject: " );
159 (void) vfprintf( stderr, format, args );
160 fputc( '\n', stderr );
162 /* throw (Exception()); */
168 /*********************/
170 _gif_message( char *format, ... )
174 va_start( args, format );
176 fprintf( stderr, "GifObject: " );
177 (void) vfprintf( stderr, format, args );
178 fputc( '\n', stderr );
182 /*********************/
184 _gif_allocarray( int cols, int rows, int size )
189 its = (char**) malloc( rows * sizeof(char*) );
190 if ( its == (char**) 0 )
191 _gif_error( "out of memory allocating an array", 0 );
192 its[0] = (char*) malloc( rows * cols * size );
193 if ( its[0] == (char*) 0 )
194 _gif_error( "out of memory allocating an array", 0 );
195 for ( i = 1; i < rows; ++i )
196 its[i] = &(its[0][i * cols * size]);
197 return (pixel **)its;
200 /*********************/
202 GetDataBlock(byte **inbuf, unsigned char *buf, GifState *g)
209 g->ZeroDataBlock = count == 0;
212 memcpy (buf, *inbuf, count);
219 /*********************/
221 ReadColorMap(byte **inbuf, int number, unsigned char buffer[3][MAXCOLORMAPSIZE])
226 for (i = 0; i < number; ++i) {
227 rgb = (unsigned char *)*inbuf;
230 buffer[CM_RED][i] = rgb[0] ;
231 buffer[CM_GREEN][i] = rgb[1] ;
232 buffer[CM_BLUE][i] = rgb[2] ;
237 /*********************/
239 DoExtension(byte **inbuf, int label, GifState *g)
242 char *buf = g->ext_buf;
245 case 0x01: /* Plain Text Extension */
246 str = "Plain Text Extension";
248 if (GetDataBlock(inbuf, (unsigned char*) buf, g) == 0)
251 lpos = LM_to_uint(buf[0], buf[1]);
252 tpos = LM_to_uint(buf[2], buf[3]);
253 width = LM_to_uint(buf[4], buf[5]);
254 height = LM_to_uint(buf[6], buf[7]);
257 foreground = buf[10];
258 background = buf[11];
260 while (GetDataBlock(inbuf, (unsigned char*) buf, g) != 0) {
261 PPM_ASSIGN(image[ypos][xpos],
272 case 0xff: /* Application Extension */
273 str = "Application Extension";
275 case 0xfe: /* Comment Extension */
276 str = "Comment Extension";
277 while (GetDataBlock(inbuf, (unsigned char*) buf, g) != 0) {
279 _gif_message("gif comment: %s", buf );
283 case 0xf9: /* Graphic Control Extension */
284 str = "Graphic Control Extension";
285 (void) GetDataBlock(inbuf, (unsigned char*) buf, g);
286 g->Gif89.disposal = (buf[0] >> 2) & 0x7;
287 g->Gif89.inputFlag = (buf[0] >> 1) & 0x1;
288 g->Gif89.delayTime = LM_to_uint(buf[1], buf[2]);
289 if ((buf[0] & 0x1) != 0)
290 g->Gif89.transparent = buf[3];
292 while (GetDataBlock(inbuf, (unsigned char*) buf, g) != 0)
297 sprintf(buf, "UNKNOWN (0x%02x)", label);
302 _gif_message("got a '%s' extension", str );
305 while (GetDataBlock(inbuf, (unsigned char*) buf, g) != 0)
311 /*********************/
313 GetCode(byte **inbuf, int code_size, int flag, GifState *g)
317 unsigned char *buf = g->buf;
320 for (i = 0; i < 280; i++)
329 if ( (g->curbit+code_size) >= g->lastbit) {
331 if (g->curbit >= g->lastbit)
332 _gif_error("ran off the end of my bits", 0 );
336 buf[0] = buf[g->last_byte-2];
337 buf[1] = buf[g->last_byte-1];
340 if ((count = GetDataBlock(inbuf, &buf[2], g)) == 0)
343 g->last_byte = 2 + count;
344 g->curbit = (g->curbit - g->lastbit) + 16;
345 g->lastbit = (2+count)*8 ;
349 for (i = g->curbit, j = 0; j < code_size; ++i, ++j)
350 ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j;
352 g->curbit += code_size;
357 /*********************/
359 LWZReadByte(byte **inbuf, int flag, int input_code_size, GifState *g)
365 g->set_code_size = input_code_size;
366 g->code_size = g->set_code_size+1;
367 g->clear_code = 1 << g->set_code_size ;
368 g->end_code = g->clear_code + 1;
369 g->max_code_size = 2*g->clear_code;
370 g->max_code = g->clear_code+2;
372 GetCode(inbuf, 0, TRUE, g);
376 for (i = 0; i < g->clear_code; ++i) {
380 for (; i < (1<<MAX_LWZ_BITS); ++i)
381 g->table[0][i] = g->table[1][0] = 0;
386 } else if (g->fresh) {
389 g->firstcode = g->oldcode =
390 GetCode(inbuf, g->code_size, FALSE, g);
391 } while (g->firstcode == g->clear_code);
395 if (g->sp > g->stack)
398 while ((code = GetCode(inbuf, g->code_size, FALSE, g)) >= 0) {
399 if (code == g->clear_code) {
400 for (i = 0; i < g->clear_code; ++i) {
404 for (; i < (1<<MAX_LWZ_BITS); ++i)
405 g->table[0][i] = g->table[1][i] = 0;
406 g->code_size = g->set_code_size+1;
407 g->max_code_size = 2*g->clear_code;
408 g->max_code = g->clear_code+2;
410 g->firstcode = g->oldcode =
411 GetCode(inbuf, g->code_size, FALSE, g);
413 } else if (code == g->end_code) {
415 unsigned char buf[260];
417 if (g->ZeroDataBlock)
420 while ((count = GetDataBlock(inbuf, buf, g)) > 0)
425 _gif_message("missing EOD in data stream (common occurence)");
432 if (code >= g->max_code) {
433 *(g->sp)++ = g->firstcode;
437 while (code >= g->clear_code) {
438 *(g->sp++) = g->table[1][code];
439 if (code == g->table[0][code])
440 _gif_error("circular table entry BIG ERROR", 0);
441 code = g->table[0][code];
444 *(g->sp)++ = g->firstcode = g->table[1][code];
446 if ((code = g->max_code) <(1<<MAX_LWZ_BITS)) {
447 g->table[0][code] = g->oldcode;
448 g->table[1][code] = g->firstcode;
450 if ((g->max_code >= g->max_code_size) &&
451 (g->max_code_size < (1<<MAX_LWZ_BITS))) {
452 g->max_code_size *= 2;
459 if (g->sp > g->stack)
465 /*********************/
467 ReadImage(byte **inbuf, int len, int height, unsigned char cmap[3][MAXCOLORMAPSIZE], int interlace, int ignore, GifState *g)
471 int xpos = 0, ypos = 0, pass = 0;
475 ** Initialize the Compression routines
480 if (LWZReadByte(inbuf, TRUE, c, g) < 0)
481 _gif_error("error reading image", 0 );
484 ** If this is an "uninteresting picture" ignore it.
488 _gif_message("skipping image..." );
490 while (LWZReadByte(inbuf, FALSE, c, g) >= 0)
495 if ((image = _gif_allocarray(len, height, sizeof(pixel))) == NULL)
496 _gif_error("couldn't alloc space for image", 0 );
499 _gif_message("reading %d by %d%s GIF image",
500 len, height, interlace ? " interlaced" : "" );
503 while ((v = LWZReadByte(inbuf,FALSE,c, g)) >= 0 ) {
504 PPM_ASSIGN(image[ypos][xpos], cmap[CM_RED][v],
505 cmap[CM_GREEN][v], cmap[CM_BLUE][v]);
521 if (ypos >= height) {
544 if (LWZReadByte(inbuf,FALSE,c, g)>=0)
545 _gif_message("too much input data, ignoring extra...");
552 /* ////////////////////////////////////////////////////////////
554 // ////////////////////////////////////////////////////////// */
556 enum _DtGrLoadStatus InitGifObject (
565 enum _DtGrColorModel colorModel,
566 Boolean allowReducedColors)
568 int r, g, b, i, visualsMatched;
569 XVisualInfo vTemplate, *visualList;
572 ** Initialize structure values
574 go->bits_per_pixel = 2;
575 go->colors_per_pixel = (int) pow (2, go->bits_per_pixel);
576 go->total_colors = (int) pow (go->colors_per_pixel, 3);
577 go->f_color_map_constructed = 0;
578 go->f_total_greys = 2;
581 go->f_drawable = drawable;
582 go->f_screen = XScreenNumberOfScreen(screen);
583 go->f_dft_depth = depth;
584 go->f_cmap = colormap;
586 go->f_visual = visual;
587 go->f_ncells = DisplayCells(go->f_dpy, go->f_screen);
588 go->f_nplanes = DisplayPlanes(go->f_dpy,go->f_screen);
589 go->f_white = WhitePixel(go->f_dpy, go->f_screen);
590 go->f_black = BlackPixel(go->f_dpy, go->f_screen);
591 go->f_allow_reduced_colors = allowReducedColors;
592 go->f_color_reduction_used = FALSE;
595 ** Initialize color allocation fields according to the color model
596 ** specified by the caller.
601 go->f_do_visual = DO_COLOR;
602 go->f_init_total_greys = 32;
604 case _DtGrGRAY_SCALE:
605 go->f_do_visual = DO_GREY;
606 go->f_init_total_greys = 32;
609 go->f_do_visual = DO_GREY;
610 go->f_init_total_greys = 2;
613 /* Should never get here */
614 go->f_do_visual = DO_COLOR;
615 go->f_init_total_greys = 32;
618 /* Return if the colormap is already allocated */
619 if ( go->f_color_map_constructed )
620 return (_DtGrSUCCESS);
622 /* find the visual class code */
624 vTemplate.screen = go->f_screen;
625 vTemplate.depth = go->f_dft_depth;
627 visualList = XGetVisualInfo( go->f_dpy,
628 VisualScreenMask | VisualDepthMask,
629 &vTemplate, &visualsMatched );
631 /* Return failure if we can't find a matching visual */
632 if ( visualsMatched == 0 )
633 return (_DtGrCONVERT_FAILURE);
635 go->f_visual_class = StaticGray;
637 for ( i=0; i<visualsMatched; i++ )
639 if ( visualList[i].visual == go->f_visual )
641 go->f_visual_class = visualList[i].class;
648 /* Construct a 4x4x4 color cube */
650 for (r = 0; r < go->colors_per_pixel; r++)
651 for (g = 0; g < go->colors_per_pixel; g++)
652 for (b = 0; b < go->colors_per_pixel; b++)
654 go->GifCMap[i].red = ((r * 65535)/(go->colors_per_pixel - 1));
655 go->GifCMap[i].green = ((g * 65535)/(go->colors_per_pixel - 1));
656 go->GifCMap[i].blue = ((b * 65535)/(go->colors_per_pixel - 1));
661 ** Allocate X pixels, either color or greyscale values depending upon
662 ** visual class and color model.
664 switch ( go->f_visual_class )
671 ** Return failure if caller is insisting on color and this
672 ** visual can't provide it.
674 if ((colorModel == _DtGrCOLOR) && !allowReducedColors)
675 return (_DtGrCOLOR_FAILED);
677 if ( allocate_greys(go) != 0 )
678 return (_DtGrCOLOR_FAILED);
687 if (colorModel == _DtGrCOLOR)
689 if ( allocate_colors(go) != 0 )
690 return (_DtGrCOLOR_FAILED);
694 if ( allocate_greys(go) != 0 )
695 return (_DtGrCOLOR_FAILED);
701 return (_DtGrCONVERT_FAILURE);
705 ** Colors successfully allocated, return status code indicating
706 ** whether we had to fallback to a degraded color model.
708 if (go->f_color_reduction_used)
709 return (_DtGrCOLOR_REDUCE);
711 return (_DtGrSUCCESS);
714 /* /////////////////////////////////////////////////////////////////
716 // /////////////////////////////////////////////////////////////// */
718 void DeleteGifObjectResources(GifObj *g)
722 int allocate_colors(GifObj *g)
725 /*return allocate_greys(); // use this to test grey-scale */
728 unsigned long* colors;
730 color.flags = DoRed | DoGreen | DoBlue;
732 for (i = 0; i < g->total_colors; i++) {
734 color.red = g->GifCMap[i].red;
735 color.green = g->GifCMap[i].green;
736 color.blue = g->GifCMap[i].blue;
738 /*printf ("Allocating %3d: ", i); */
739 if ( !XAllocColor (g->f_dpy, g->f_cmap, &color) ) {
741 /*puts ("FAILED!!!"); */
742 colors = (unsigned long *) malloc (sizeof(unsigned long) * i);
743 for (j = 0; j < i; j++)
744 colors[j] = g->GifCMap[j].pixel;
746 /*cerr << "Xfree in allocate_colors(): " << i << "\n"; */
747 XFreeColors (g->f_dpy, g->f_cmap, colors, i, 0);
751 /* fallback to greys */
752 if (g->f_allow_reduced_colors)
754 g->f_color_reduction_used = TRUE;
755 return allocate_greys(g);
758 return (_DtGrCOLOR_FAILED);
761 /*fprintf(stderr, "i=%d pixel=%d\n", i, color.pixel);*/
763 /*printf ("@ %d\n", color.pixel); */
764 g->GifCMap[i].pixel = color.pixel;
767 g->f_do_visual = DO_COLOR;
768 g->f_color_map_constructed = 1;
773 int allocate_greys(GifObj *g)
777 unsigned long* colors;
779 color.flags = DoRed | DoGreen | DoBlue;
781 for ( i=0; i<g->total_colors; i++ ) {
785 debug1(cerr, GifCMap[i].red);
786 debug1(cerr, GifCMap[i].green);
787 debug1(cerr, GifCMap[i].blue);
788 debug1(cerr, 0.299 * GifCMap[i].red + 0.587 * GifCMap[i].green +
789 0.114 * GifCMap[i].blue);
790 debug1(cerr, GifCMap[i].grey);
793 g->GifCMap[i].grey = (unsigned short)(0.299 * g->GifCMap[i].red +
794 0.587 * g->GifCMap[i].green +
795 0.114 * g->GifCMap[i].blue);
799 if ( StaticColor == g->f_visual_class ||
800 TrueColor == g->f_visual_class )
802 if ( StaticColor == g->f_visual_class)
804 g->f_do_visual = DO_GREY;
805 g->f_total_greys = 2;
810 for ( g->f_total_greys=g->f_init_total_greys; g->f_total_greys>=2;
811 g->f_total_greys/=2 )
813 /*fprintf(stderr, "f_total_greys = %d\n", g->f_total_greys); */
816 ** Return failure if we're about to downgrade from greyscale
817 ** to dithered monochrome and we don't allow reduced colors.
819 if ((g->f_total_greys == 2) && (g->f_init_total_greys > 2) &&
820 (!g->f_allow_reduced_colors))
823 for (i = 0; i<g->f_total_greys; i++) {
827 color.blue = (i*65535)/(g->f_total_greys - 1);
829 /*fprintf (stderr, "Allocating %3d: ", i);*/
830 if ( !XAllocColor (g->f_dpy, g->f_cmap, &color) ) {
832 /*fprintf(stderr, "alloc Grey FAILED!!!");*/
833 colors = (unsigned long *) malloc (sizeof(unsigned long) * i);
834 for (j = 0; j < i; j++)
835 colors[j] = g->GifGMap[j];
837 /*cerr << "Xfree in allocate_greys()\n"; */
838 XFreeColors (g->f_dpy, g->f_cmap, colors, i, 0);
845 /*printf ("@ %d\n", color.pixel); */
846 g->GifGMap[i] = color.pixel;
849 if ( i == g->f_total_greys ) {
852 for ( int l=0; l<i; l++ )
853 cerr << "GifGMap[l]= " << GifGMap[l] << "\n";
856 g->f_color_map_constructed = 1;
857 g->f_do_visual = DO_GREY;
858 /* If greyscape was downgraded to bitonal, record the fact */
859 if ((g->f_total_greys == 2) && (g->f_init_total_greys > 2))
860 g->f_color_reduction_used = TRUE;
868 /* ////////////////////////////////////////////////////////////
869 // Free allocated raw image data
870 // ////////////////////////////////////////////////////////// */
873 free_raw_image( pixel **image )
875 free( (char *)image[0] );
876 free( (char *)image );
879 /* ////////////////////////////////////////////////////////////
880 // Decompress GIF data into raw bytes
881 // ////////////////////////////////////////////////////////// */
884 create_raw_image( byte *inbuf, unsigned int buflen, int *width, int *height, int imageNumber )
887 unsigned char *start_of_buf = inbuf;
889 unsigned char localColorMap[3][MAXCOLORMAPSIZE];
890 int useGlobalColormap;
897 /* Initialize the GIF state object */
898 g.Gif89.transparent = g.Gif89.delayTime = g.Gif89.inputFlag = -1;
899 g.Gif89.disposal = 0;
900 g.ZeroDataBlock = FALSE;
905 fprintf (stderr, "Not GIF Data, buffer too small\n");
909 buf = (unsigned char *)inbuf;
912 if (strncmp((const char *)buf,"GIF",3) != 0) {
913 fprintf( stderr, "GifObject: not GIF data\n" );
917 strncpy(version, (const char *)(buf + 3), 3);
920 if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) {
921 fprintf (stderr, "bad version number, not '87a' or '89a'\n" );
925 buf = (unsigned char *)inbuf;
928 g.GifScreen.Width = LM_to_uint(buf[0],buf[1]);
929 g.GifScreen.Height = LM_to_uint(buf[2],buf[3]);
930 g.GifScreen.BitPixel = 2<<(buf[4]&0x07);
931 g.GifScreen.ColorResolution = (((buf[4]&0x70)>>3)+1);
932 g.GifScreen.Background = buf[5];
933 g.GifScreen.AspectRatio = buf[6];
935 if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */
936 if (ReadColorMap(&inbuf,g.GifScreen.BitPixel,g.GifScreen.ColorMap)) {
937 fprintf (stderr, "error reading global colormap\n" );
942 if (g.GifScreen.AspectRatio != 0 && g.GifScreen.AspectRatio != 49) {
944 r = ( (float) g.GifScreen.AspectRatio + 15.0 ) / 64.0;
946 _gif_message("warning - non-square pixels; to fix do a 'pnmscale -%cscale %g'",
948 r < 1.0 ? 1.0 / r : r );
955 if (inbuf - start_of_buf >= buflen) {
956 fprintf (stderr, "Premature EOF in GIF data\n");
962 if (c == ';') { /* GIF terminator */
963 if (imageCount < imageNumber)
964 _gif_error("only %d image%s found in file",
965 imageCount, imageCount>1?"s":"" );
969 if (c == '!') { /* Extension */
970 if (inbuf - start_of_buf >= buflen) {
971 fprintf (stderr, "Premature EOF in GIF data\n");
976 DoExtension(&inbuf, c, &g);
980 if (c != ',') { /* Not a valid start character */
982 _gif_message("bogus character 0x%02x, ignoring", (int) c );
989 buf = (unsigned char *)inbuf;
992 useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP);
994 bitPixel = 1<<((buf[8]&0x07)+1);
996 *width = LM_to_uint(buf[4],buf[5]);
997 *height = LM_to_uint(buf[6],buf[7]);
999 if (! useGlobalColormap) {
1000 if (ReadColorMap(&inbuf, bitPixel, localColorMap))
1001 _gif_error("error reading local colormap", 0 );
1002 image = ReadImage(&inbuf, *width, *height, localColorMap,
1003 BitSet(buf[8], INTERLACE), imageCount != imageNumber,
1006 image = ReadImage(&inbuf, *width, *height, g.GifScreen.ColorMap,
1007 BitSet(buf[8], INTERLACE), imageCount != imageNumber,
1014 /* ////////////////////////////////////////////////////////////
1015 // Create X pixmap from raw image data
1016 // ////////////////////////////////////////////////////////// */
1018 /* from "Computer Graphics" by Foley, VanDam, Feiner, Hughes */
1020 static int dither_8X8[8][8] =
1022 { 0, 32, 8, 40, 2, 34, 10, 42 },
1023 { 48, 16, 56, 24, 50, 18, 58, 26 },
1024 { 42, 44, 4, 36, 14, 46, 6, 38 },
1025 { 60, 28, 52, 20, 62, 30, 54, 22 },
1026 { 3, 35, 11, 43, 1, 33, 9, 41 },
1027 { 51, 19, 59, 27, 49, 17, 57, 25 },
1028 { 15, 47, 7, 39, 13, 45, 5, 37 },
1029 { 63, 31, 55, 23, 61, 29, 53, 21 }
1032 /*static int dither_6X6[6][6] =
1034 // { 24, 32, 16, 26, 34, 18},
1035 // { 4, 0, 12, 6, 2, 14},
1036 // { 20, 8, 28, 22, 10, 30},
1037 // { 27, 35, 19, 25, 33, 17},
1038 // { 7, 3, 15, 5, 1, 13},
1039 // { 23, 11, 31, 21, 9, 29}
1043 static int dither_4X4[4][4] =
1052 static int dither_3X3[3][3] =
1060 static int dither_2X2[2][2] =
1066 /*static int dither_matrix_sz = 2; */
1067 /*static int dither_matrix_sz = 4; */
1068 /*static int dither_matrix_sz = 3; */
1069 static int dither_matrix_sz = 8;
1071 /* call XListPixFormat() to get bits/pix and pads ? */
1073 create_pixmap( GifObj *g, pixel **image, int width, int height, Pixel fg, Pixel bg, float ratio)
1075 int nullCount = (4 - (width % 4)) & 0x03;
1076 int ximWidth = width + nullCount;
1078 pixel *ipp = *image;
1084 int scaledWidth, scaledHeight;
1086 if ( g->f_nplanes > 8 )
1087 ximData = (byte *) malloc(ximWidth * height * 4 );
1089 ximData = (byte *) malloc(ximWidth * height );
1092 fprintf(stderr, "Could not allocate ximage data\n");
1097 if (g->f_nplanes == 1)
1098 g->f_ximage = XCreateImage(g->f_dpy, g->f_visual, g->f_nplanes, XYPixmap,
1099 0, (char *)ximData, width, height, 32, 0);
1101 /*else if (g->f_nplanes == 8) */
1103 /* non-mono display */
1105 g->f_ximage = XCreateImage(g->f_dpy, g->f_visual, g->f_nplanes, ZPixmap,
1106 0, (char *)ximData, width, height, 32, 0);
1109 fprintf(stderr, "XCreateImage failed\n");
1114 /* RGB to Pixel Conversion */
1116 if ( g->f_total_greys == 2 )
1117 spacing = 65536 / (dither_matrix_sz * dither_matrix_sz);
1119 spacing = 65536 / g->f_total_greys;
1121 /*cerr << "spacing" << spacing << "\n"; */
1123 for (y=0; y < height; y++) {
1124 for (x=0; x < width; x++) {
1125 pixval = (long)*ipp;
1127 /* XColor cellDef; */
1128 /* cellDef.red = (short)PPM_GETR(pixval); */
1129 /* cellDef.green = (short)PPM_GETG(pixval); */
1130 /* cellDef.blue = (short)PPM_GETB(pixval); */
1132 index = (((short)PPM_GETR(pixval))/64)*16 +
1133 (((short)PPM_GETG(pixval))/64)*4 +
1134 ((short)PPM_GETB(pixval))/64;
1136 /*fprintf(stderr, "grey= %d, grey/space=%d\n", g->GifCMap[index].grey, g->GifCMap[index].grey / spacing);*/
1137 switch (g->f_do_visual) {
1140 switch ( g->f_total_greys ) {
1143 /*cerr << "index=" << index << "\n"; */
1144 /*cerr << "GifCMap[index].grey" << GifCMap[index].grey << "\n"; */
1145 /*cerr << "GifCMap[index].grey/spacing" << GifCMap[index].grey / spacing << "\n"; */
1147 if ( dither_8X8[x%dither_matrix_sz][y%dither_matrix_sz] < g->GifCMap[index].grey / spacing ) {
1148 XPutPixel(g->f_ximage,x,y,g->f_white);
1150 XPutPixel(g->f_ximage,x,y,g->f_black);
1157 /*cerr << GifCMap[index].grey / spacing << " "; */
1159 XPutPixel(g->f_ximage,x,y, g->GifGMap[g->GifCMap[index].grey / spacing]);
1167 fprintf(stderr, "%03d %03d %03d -- %03d %03d %03d ",
1168 (short)PPM_GETR(pixval),(short)PPM_GETG(pixval),(short)PPM_GETB(pixval),
1169 g->GifCMap[index].red>>8, g->GifCMap[index].green>>8, g->GifCMap[index].blue>>8
1171 if ((short)PPM_GETR(pixval) != (GifCMap[index].red>>8) ||
1172 (short)PPM_GETG(pixval) != (GifCMap[index].green>>8) ||
1173 (short)PPM_GETB(pixval) != (GifCMap[index].blue>>8))
1180 XPutPixel(g->f_ximage,x,y, g->GifCMap[index].pixel);
1182 switch ( g->f_visual_class ) {
1185 XPutPixel(g->f_ximage,x,y, g->GifCMap[index].pixel);
1199 for (x=width;x<ximWidth;x++)
1200 XPutPixel(g->f_ximage,x,y,bg); /* padding */
1203 scaledWidth = width * ratio + 0.5;
1204 scaledHeight = height * ratio + 0.5;
1205 if (scaledWidth == 0)
1207 if (scaledHeight == 0)
1209 pm = XCreatePixmap(g->f_dpy,g->f_drawable,
1210 scaledWidth,scaledHeight,
1214 fprintf(stderr, "could not create pixmap\n");
1218 _XmPutScaledImage (g->f_dpy,pm,g->f_gc,g->f_ximage,
1219 0,0,0,0,width,height,
1220 scaledWidth,scaledHeight);
1222 XDestroyImage(g->f_ximage);
1229 /* /////////////////////////////////////////////////////////////////
1230 // Load pixmap from GIF data
1231 // /////////////////////////////////////////////////////////////// */
1234 gif_to_pixmap(GifObj *g, byte *inbuf, unsigned int buflen, Dimension *w, Dimension *h, Pixel fg, Pixel bg, float ratio)
1240 /* Create raw image from compress GIF data */
1241 raw_image = create_raw_image (inbuf, buflen, &width, &height, 1);
1242 if (!raw_image) return NULL;
1244 /* Create X pixmap from raw image data */
1245 pixmap = create_pixmap(g, raw_image, width, height, fg, bg, ratio);
1247 /* Free raw image data */
1248 free_raw_image(raw_image);
1250 /* Set X pixmap dimensions */
1251 *w = (Dimension) width * ratio + 0.5;
1252 *h = (Dimension) height * ratio + 0.5;
1257 /* Return X pixmap */