12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238 |
- /*
- * CDE - Common Desktop Environment
- *
- * Copyright (c) 1993-2012, The Open Group. All rights reserved.
- *
- * These libraries and programs are free software; you can
- * redistribute them and/or modify them under the terms of the GNU
- * Lesser General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * These libraries and programs are distributed in the hope that
- * they will be useful, but WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with these libraries and programs; if not, write
- * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
- * Floor, Boston, MA 02110-1301 USA
- */
- /*
- * $XConsortium: GifUtils.c /main/5 1996/05/07 13:21:42 drk $
- * Copyright (c) 1993 HAL Computer Systems International, Ltd.
- * All rights reserved. Unpublished -- rights reserved under
- * the Copyright Laws of the United States. USE OF A COPYRIGHT
- * NOTICE IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION
- * OR DISCLOSURE.
- *
- * THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND TRADE
- * SECRETS OF HAL COMPUTER SYSTEMS INTERNATIONAL, LTD. USE,
- * DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE
- * PRIOR EXPRESS WRITTEN PERMISSION OF HAL COMPUTER SYSTEMS
- * INTERNATIONAL, LTD.
- *
- * RESTRICTED RIGHTS LEGEND
- * Use, duplication, or disclosure by the Government is subject
- * to the restrictions as set forth in subparagraph (c)(l)(ii)
- * of the Rights in Technical Data and Computer Software clause
- * at DFARS 252.227-7013.
- *
- * HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.
- * 1315 Dell Avenue
- * Campbell, CA 95008
- *
- */
- /* +-------------------------------------------------------------------+ */
- /* | Portions lifted from giftoppm.c (pbmplus version 10dec91) | */
- /* | | */
- /* | Copyright 1990, David Koblas. | */
- /* | Permission to use, copy, modify, and distribute this software | */
- /* | and its documentation for any purpose and without fee is hereby | */
- /* | granted, provided that the above copyright notice appear in all | */
- /* | copies and that both that copyright notice and this permission | */
- /* | notice appear in supporting documentation. This software is | */
- /* | provided "as is" without express or implied warranty. | */
- /* +-------------------------------------------------------------------+ */
- #define C_Gif
- #define L_Graphics
- #define C_MessageMgr
- #define L_Managers
- /* include files */
- #include <stdio.h>
- #include <stdarg.h>
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
- #include <assert.h>
- #include <Xm/XmPrivate.h>
- #include "GifUtilsI.h"
- #ifndef __STDC__
- #define debug1(s, x) s << "x" << " = " << (x) << "\n"
- #else
- #define debug1(s, x) s << #x << " = " << (x) << "\n"
- #endif
- #define MAX_GHANDS 16 /* maximum # of GRAF handles */
- #define PPM_ASSIGN(p,red,grn,blu) (p) = ((pixel) (red) << 20) | ((pixel) (grn) << 10) | (pixel) (blu)
- #define PPM_GETR(p) (((p) & 0x3ff00000) >> 20)
- #define PPM_GETG(p) (((p) & 0xffc00) >> 10)
- #define PPM_GETB(p) ((p) & 0x3ff)
- #define MAXCOLORMAPSIZE 256
- #define TRUE 1
- #define FALSE 0
- #define CM_RED 0
- #define CM_GREEN 1
- #define CM_BLUE 2
- #define MAX_LWZ_BITS 12
- #define INTERLACE 0x40
- #define LOCALCOLORMAP 0x80
- #define BitSet(byte, bit) (((byte) & (bit)) == (bit))
- #define LM_to_uint(a,b) (((b)<<8)|(a))
- typedef struct {
- unsigned int Width;
- unsigned int Height;
- unsigned char ColorMap[3][MAXCOLORMAPSIZE];
- unsigned int BitPixel;
- unsigned int ColorResolution;
- unsigned int Background;
- unsigned int AspectRatio;
- } GifScreenType;
- typedef struct {
- int transparent;
- int delayTime;
- int inputFlag;
- int disposal;
- } Gif89Type;
- /*
- * This structure holds variables that were formerly global or static
- * within a function in the original giftoppm code. They have been
- * moved into this object to ensure thread re-entrancy of the routines
- * that use them. A unique instance of this object is created for each
- * thread and passed to the appropriate routines.
- */
- typedef struct {
- /* Formerly global variables */
- GifScreenType GifScreen;
- Gif89Type Gif89;
- int ZeroDataBlock;
- /* Formerly static variables declared in DoExtension */
- char ext_buf[256];
- /* Formerly static variables declared in GetCode */
- unsigned char buf[280];
- int curbit, lastbit, done, last_byte;
- /* Formerly static variables declared in LWZReadByte*/
- int fresh;
- int code_size, set_code_size;
- int max_code, max_code_size;
- int firstcode, oldcode;
- int clear_code, end_code;
- int table[2][(1<< MAX_LWZ_BITS)];
- int stack[(1<<(MAX_LWZ_BITS))*2], *sp;
- } GifState;
- /*********************/
- static void
- _gif_error( char *format, ... )
- {
- va_list args;
- va_start( args, format );
- fprintf( stderr, "GifObject: " );
- (void) vfprintf( stderr, format, args );
- fputc( '\n', stderr );
- va_end( args );
- /* throw (Exception()); */
- #if 0
- abort();
- #endif
- }
- /*********************/
- static void
- _gif_message( char *format, ... )
- {
- va_list args;
- va_start( args, format );
- fprintf( stderr, "GifObject: " );
- (void) vfprintf( stderr, format, args );
- fputc( '\n', stderr );
- va_end( args );
- }
- /*********************/
- static pixel **
- _gif_allocarray( int cols, int rows, int size )
- {
- char** its;
- int i;
- its = (char**) malloc( rows * sizeof(char*) );
- if ( its == (char**) 0 )
- _gif_error( "out of memory allocating an array", 0 );
- its[0] = (char*) malloc( rows * cols * size );
- if ( its[0] == (char*) 0 )
- _gif_error( "out of memory allocating an array", 0 );
- for ( i = 1; i < rows; ++i )
- its[i] = &(its[0][i * cols * size]);
- return (pixel **)its;
- }
- /*********************/
- static int
- GetDataBlock(byte **inbuf, unsigned char *buf, GifState *g)
- {
- unsigned char count;
- count = (*inbuf)[0];
- (*inbuf)++;
- g->ZeroDataBlock = count == 0;
- if (count) {
- memcpy (buf, *inbuf, count);
- *inbuf += count;
- }
- return count;
- }
- /*********************/
- static int
- ReadColorMap(byte **inbuf, int number, unsigned char buffer[3][MAXCOLORMAPSIZE])
- {
- int i;
- unsigned char *rgb;
- for (i = 0; i < number; ++i) {
- rgb = (unsigned char *)*inbuf;
- *inbuf += 3;
- buffer[CM_RED][i] = rgb[0] ;
- buffer[CM_GREEN][i] = rgb[1] ;
- buffer[CM_BLUE][i] = rgb[2] ;
- }
- return FALSE;
- }
- /*********************/
- static int
- DoExtension(byte **inbuf, int label, GifState *g)
- {
- char *str;
- char *buf = g->ext_buf;
- switch (label) {
- case 0x01: /* Plain Text Extension */
- str = "Plain Text Extension";
- break;
- case 0xff: /* Application Extension */
- str = "Application Extension";
- break;
- case 0xfe: /* Comment Extension */
- str = "Comment Extension";
- while (GetDataBlock(inbuf, (unsigned char*) buf, g) != 0) {
- #ifdef DEBUG
- _gif_message("gif comment: %s", buf );
- #endif
- }
- return FALSE;
- case 0xf9: /* Graphic Control Extension */
- str = "Graphic Control Extension";
- (void) GetDataBlock(inbuf, (unsigned char*) buf, g);
- g->Gif89.disposal = (buf[0] >> 2) & 0x7;
- g->Gif89.inputFlag = (buf[0] >> 1) & 0x1;
- g->Gif89.delayTime = LM_to_uint(buf[1], buf[2]);
- if ((buf[0] & 0x1) != 0)
- g->Gif89.transparent = buf[3];
- while (GetDataBlock(inbuf, (unsigned char*) buf, g) != 0)
- ;
- return FALSE;
- default:
- str = buf;
- sprintf(buf, "UNKNOWN (0x%02x)", label);
- break;
- }
- #ifdef DEBUG
- _gif_message("got a '%s' extension", str );
- #endif
- while (GetDataBlock(inbuf, (unsigned char*) buf, g) != 0)
- ;
- return FALSE;
- }
- /*********************/
- static int
- GetCode(byte **inbuf, int code_size, int flag, GifState *g)
- {
- int i, j, ret;
- unsigned char count;
- unsigned char *buf = g->buf;
- if (flag) {
- for (i = 0; i < 280; i++)
- buf[i] = 0;
- g->last_byte = 0;
- g->curbit = 0;
- g->lastbit = 0;
- g->done = FALSE;
- return 0;
- }
- if ( (g->curbit+code_size) >= g->lastbit) {
- if (g->done) {
- if (g->curbit >= g->lastbit)
- _gif_error("ran off the end of my bits", 0 );
- return -1;
- }
- if (g->last_byte) {
- buf[0] = buf[g->last_byte-2];
- buf[1] = buf[g->last_byte-1];
- }
- if ((count = GetDataBlock(inbuf, &buf[2], g)) == 0)
- g->done = TRUE;
- g->last_byte = 2 + count;
- g->curbit = (g->curbit - g->lastbit) + 16;
- g->lastbit = (2+count)*8 ;
- }
- ret = 0;
- for (i = g->curbit, j = 0; j < code_size; ++i, ++j)
- ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j;
- g->curbit += code_size;
- return ret;
- }
- /*********************/
- static int
- LWZReadByte(byte **inbuf, int flag, int input_code_size, GifState *g)
- {
- int code, incode;
- int i;
- if (flag) {
- g->set_code_size = input_code_size;
- g->code_size = g->set_code_size+1;
- g->clear_code = 1 << g->set_code_size ;
- g->end_code = g->clear_code + 1;
- g->max_code_size = 2*g->clear_code;
- g->max_code = g->clear_code+2;
- GetCode(inbuf, 0, TRUE, g);
-
- g->fresh = TRUE;
- for (i = 0; i < g->clear_code; ++i) {
- g->table[0][i] = 0;
- g->table[1][i] = i;
- }
- for (; i < (1<<MAX_LWZ_BITS); ++i)
- g->table[0][i] = g->table[1][0] = 0;
- g->sp = g->stack;
- return 0;
- } else if (g->fresh) {
- g->fresh = FALSE;
- do {
- g->firstcode = g->oldcode =
- GetCode(inbuf, g->code_size, FALSE, g);
- } while (g->firstcode == g->clear_code);
- return g->firstcode;
- }
- if (g->sp > g->stack)
- return *--(g->sp);
- while ((code = GetCode(inbuf, g->code_size, FALSE, g)) >= 0) {
- if (code == g->clear_code) {
- for (i = 0; i < g->clear_code; ++i) {
- g->table[0][i] = 0;
- g->table[1][i] = i;
- }
- for (; i < (1<<MAX_LWZ_BITS); ++i)
- g->table[0][i] = g->table[1][i] = 0;
- g->code_size = g->set_code_size+1;
- g->max_code_size = 2*g->clear_code;
- g->max_code = g->clear_code+2;
- g->sp = g->stack;
- g->firstcode = g->oldcode =
- GetCode(inbuf, g->code_size, FALSE, g);
- return g->firstcode;
- } else if (code == g->end_code) {
- int count;
- unsigned char buf[260];
- if (g->ZeroDataBlock)
- return -2;
- while ((count = GetDataBlock(inbuf, buf, g)) > 0)
- ;
- #ifdef DEBUG
- if (count != 0)
- _gif_message("missing EOD in data stream (common occurence)");
- #endif
- return -2;
- }
- incode = code;
- if (code >= g->max_code) {
- *(g->sp)++ = g->firstcode;
- code = g->oldcode;
- }
- while (code >= g->clear_code) {
- *(g->sp++) = g->table[1][code];
- if (code == g->table[0][code])
- _gif_error("circular table entry BIG ERROR", 0);
- code = g->table[0][code];
- }
- *(g->sp)++ = g->firstcode = g->table[1][code];
- if ((code = g->max_code) <(1<<MAX_LWZ_BITS)) {
- g->table[0][code] = g->oldcode;
- g->table[1][code] = g->firstcode;
- ++(g->max_code);
- if ((g->max_code >= g->max_code_size) &&
- (g->max_code_size < (1<<MAX_LWZ_BITS))) {
- g->max_code_size *= 2;
- ++(g->code_size);
- }
- }
- g->oldcode = incode;
- if (g->sp > g->stack)
- return *--(g->sp);
- }
- return code;
- }
- /*********************/
- pixel **
- ReadImage(byte **inbuf, int len, int height, unsigned char cmap[3][MAXCOLORMAPSIZE], int interlace, int ignore, GifState *g)
- {
- unsigned char c;
- int v;
- int xpos = 0, ypos = 0, pass = 0;
- pixel **image;
- /*
- ** Initialize the Compression routines
- */
- c = (*inbuf)[0];
- (*inbuf)++;
- if (LWZReadByte(inbuf, TRUE, c, g) < 0)
- _gif_error("error reading image", 0 );
- /*
- ** If this is an "uninteresting picture" ignore it.
- */
- if (ignore) {
- #ifdef DEBUG
- _gif_message("skipping image..." );
- #endif
- while (LWZReadByte(inbuf, FALSE, c, g) >= 0)
- ;
- return NULL;
- }
- if ((image = _gif_allocarray(len, height, sizeof(pixel))) == NULL)
- _gif_error("couldn't alloc space for image", 0 );
- #ifdef DEBUG
- _gif_message("reading %d by %d%s GIF image",
- len, height, interlace ? " interlaced" : "" );
- #endif
- while ((v = LWZReadByte(inbuf,FALSE,c, g)) >= 0 ) {
- PPM_ASSIGN(image[ypos][xpos], cmap[CM_RED][v],
- cmap[CM_GREEN][v], cmap[CM_BLUE][v]);
- ++xpos;
- if (xpos == len) {
- xpos = 0;
- if (interlace) {
- switch (pass) {
- case 0:
- case 1:
- ypos += 8; break;
- case 2:
- ypos += 4; break;
- case 3:
- ypos += 2; break;
- }
- if (ypos >= height) {
- ++pass;
- switch (pass) {
- case 1:
- ypos = 4; break;
- case 2:
- ypos = 2; break;
- case 3:
- ypos = 1; break;
- default:
- goto fini;
- }
- }
- } else {
- ++ypos;
- }
- }
- if (ypos >= height)
- break;
- }
- fini:
- #ifdef DEBUG
- if (LWZReadByte(inbuf,FALSE,c, g)>=0)
- _gif_message("too much input data, ignoring extra...");
- #endif
- return image;
- }
- /* ////////////////////////////////////////////////////////////
- // class constructor
- // ////////////////////////////////////////////////////////// */
- enum _DtGrLoadStatus InitGifObject (
- GifObj *go,
- Display *dpy,
- Drawable drawable,
- Screen *screen,
- int depth,
- Colormap colormap,
- Visual *visual,
- GC gc,
- enum _DtGrColorModel colorModel,
- Boolean allowReducedColors)
- {
- int r, g, b, i, visualsMatched;
- XVisualInfo vTemplate, *visualList;
- /*
- ** Initialize structure values
- */
- go->bits_per_pixel = 2;
- go->colors_per_pixel = (int) pow (2, go->bits_per_pixel);
- go->total_colors = (int) pow (go->colors_per_pixel, 3);
- go->f_color_map_constructed = 0;
- go->f_total_greys = 2;
- go->f_ximage = NULL;
- go->f_dpy = dpy;
- go->f_drawable = drawable;
- go->f_screen = XScreenNumberOfScreen(screen);
- go->f_dft_depth = depth;
- go->f_cmap = colormap;
- go->f_gc = gc;
- go->f_visual = visual;
- go->f_ncells = DisplayCells(go->f_dpy, go->f_screen);
- go->f_nplanes = DisplayPlanes(go->f_dpy,go->f_screen);
- go->f_white = WhitePixel(go->f_dpy, go->f_screen);
- go->f_black = BlackPixel(go->f_dpy, go->f_screen);
- go->f_allow_reduced_colors = allowReducedColors;
- go->f_color_reduction_used = FALSE;
- /*
- ** Initialize color allocation fields according to the color model
- ** specified by the caller.
- */
- switch (colorModel)
- {
- case _DtGrCOLOR:
- go->f_do_visual = DO_COLOR;
- go->f_init_total_greys = 32;
- break;
- case _DtGrGRAY_SCALE:
- go->f_do_visual = DO_GREY;
- go->f_init_total_greys = 32;
- break;
- case _DtGrBITONAL:
- go->f_do_visual = DO_GREY;
- go->f_init_total_greys = 2;
- break;
- default:
- /* Should never get here */
- go->f_do_visual = DO_COLOR;
- go->f_init_total_greys = 32;
- }
- /* Return if the colormap is already allocated */
- if ( go->f_color_map_constructed )
- return (_DtGrSUCCESS);
- /* find the visual class code */
- vTemplate.screen = go->f_screen;
- vTemplate.depth = go->f_dft_depth;
- visualList = XGetVisualInfo( go->f_dpy,
- VisualScreenMask | VisualDepthMask,
- &vTemplate, &visualsMatched );
- /* Return failure if we can't find a matching visual */
- if ( visualsMatched == 0 )
- return (_DtGrCONVERT_FAILURE);
- go->f_visual_class = StaticGray;
- for ( i=0; i<visualsMatched; i++ )
- {
- if ( visualList[i].visual == go->f_visual )
- {
- go->f_visual_class = visualList[i].class;
- break;
- }
- }
- XFree(visualList);
- /* Construct a 4x4x4 color cube */
- i = 0;
- for (r = 0; r < go->colors_per_pixel; r++)
- for (g = 0; g < go->colors_per_pixel; g++)
- for (b = 0; b < go->colors_per_pixel; b++)
- {
- go->GifCMap[i].red = ((r * 65535)/(go->colors_per_pixel - 1));
- go->GifCMap[i].green = ((g * 65535)/(go->colors_per_pixel - 1));
- go->GifCMap[i].blue = ((b * 65535)/(go->colors_per_pixel - 1));
- i++;
- }
- /*
- ** Allocate X pixels, either color or greyscale values depending upon
- ** visual class and color model.
- */
- switch ( go->f_visual_class )
- {
- case StaticGray:
- case GrayScale:
- case StaticColor:
- {
- /*
- ** Return failure if caller is insisting on color and this
- ** visual can't provide it.
- */
- if ((colorModel == _DtGrCOLOR) && !allowReducedColors)
- return (_DtGrCOLOR_FAILED);
- if ( allocate_greys(go) != 0 )
- return (_DtGrCOLOR_FAILED);
- break;
- }
- case PseudoColor:
- case DirectColor:
- case TrueColor:
- {
- if (colorModel == _DtGrCOLOR)
- {
- if ( allocate_colors(go) != 0 )
- return (_DtGrCOLOR_FAILED);
- }
- else
- {
- if ( allocate_greys(go) != 0 )
- return (_DtGrCOLOR_FAILED);
- }
- break;
- }
- default:
- return (_DtGrCONVERT_FAILURE);
- }
- /*
- ** Colors successfully allocated, return status code indicating
- ** whether we had to fallback to a degraded color model.
- */
- if (go->f_color_reduction_used)
- return (_DtGrCOLOR_REDUCE);
- else
- return (_DtGrSUCCESS);
- }
- /* /////////////////////////////////////////////////////////////////
- // class destructor
- // /////////////////////////////////////////////////////////////// */
- void DeleteGifObjectResources(GifObj *g)
- {
- }
- int allocate_colors(GifObj *g)
- {
- int i, j;
- /*return allocate_greys(); // use this to test grey-scale */
- XColor color;
- unsigned long* colors;
- color.flags = DoRed | DoGreen | DoBlue;
- for (i = 0; i < g->total_colors; i++) {
- color.red = g->GifCMap[i].red;
- color.green = g->GifCMap[i].green;
- color.blue = g->GifCMap[i].blue;
-
- /*printf ("Allocating %3d: ", i); */
- if ( !XAllocColor (g->f_dpy, g->f_cmap, &color) ) {
- /*puts ("FAILED!!!"); */
- colors = (unsigned long *) malloc (sizeof(unsigned long) * i);
- for (j = 0; j < i; j++)
- colors[j] = g->GifCMap[j].pixel;
- /*cerr << "Xfree in allocate_colors(): " << i << "\n"; */
- XFreeColors (g->f_dpy, g->f_cmap, colors, i, 0);
- free(colors);
- /* fallback to greys */
- if (g->f_allow_reduced_colors)
- {
- g->f_color_reduction_used = TRUE;
- return allocate_greys(g);
- }
- else
- return (_DtGrCOLOR_FAILED);
- }
- /*fprintf(stderr, "i=%d pixel=%d\n", i, color.pixel);*/
- /*printf ("@ %d\n", color.pixel); */
- g->GifCMap[i].pixel = color.pixel;
- }
- g->f_do_visual = DO_COLOR;
- g->f_color_map_constructed = 1;
- return 0;
- }
- int allocate_greys(GifObj *g)
- {
- XColor color;
- int i, j;
- unsigned long* colors;
- color.flags = DoRed | DoGreen | DoBlue;
- for ( i=0; i<g->total_colors; i++ ) {
- /*
- debug1(cerr, i);
- debug1(cerr, GifCMap[i].red);
- debug1(cerr, GifCMap[i].green);
- debug1(cerr, GifCMap[i].blue);
- debug1(cerr, 0.299 * GifCMap[i].red + 0.587 * GifCMap[i].green +
- 0.114 * GifCMap[i].blue);
- debug1(cerr, GifCMap[i].grey);
- */
- g->GifCMap[i].grey = (unsigned short)(0.299 * g->GifCMap[i].red +
- 0.587 * g->GifCMap[i].green +
- 0.114 * g->GifCMap[i].blue);
- }
- /*
- if ( StaticColor == g->f_visual_class ||
- TrueColor == g->f_visual_class )
- */
- if ( StaticColor == g->f_visual_class)
- {
- g->f_do_visual = DO_GREY;
- g->f_total_greys = 2;
- return 0;
- }
- for ( g->f_total_greys=g->f_init_total_greys; g->f_total_greys>=2;
- g->f_total_greys/=2 )
- {
- /*fprintf(stderr, "f_total_greys = %d\n", g->f_total_greys); */
- /*
- ** Return failure if we're about to downgrade from greyscale
- ** to dithered monochrome and we don't allow reduced colors.
- */
- if ((g->f_total_greys == 2) && (g->f_init_total_greys > 2) &&
- (!g->f_allow_reduced_colors))
- return -1;
- for (i = 0; i<g->f_total_greys; i++) {
- color.red =
- color.green =
- color.blue = (i*65535)/(g->f_total_greys - 1);
-
- /*fprintf (stderr, "Allocating %3d: ", i);*/
- if ( !XAllocColor (g->f_dpy, g->f_cmap, &color) ) {
- /*fprintf(stderr, "alloc Grey FAILED!!!");*/
- colors = (unsigned long *) malloc (sizeof(unsigned long) * i);
- for (j = 0; j < i; j++)
- colors[j] = g->GifGMap[j];
- /*cerr << "Xfree in allocate_greys()\n"; */
- XFreeColors (g->f_dpy, g->f_cmap, colors, i, 0);
- free(colors);
-
- break;
- }
- /*printf ("@ %d\n", color.pixel); */
- g->GifGMap[i] = color.pixel;
- }
- if ( i == g->f_total_greys ) {
- /*
- for ( int l=0; l<i; l++ )
- cerr << "GifGMap[l]= " << GifGMap[l] << "\n";
- */
- g->f_color_map_constructed = 1;
- g->f_do_visual = DO_GREY;
- /* If greyscape was downgraded to bitonal, record the fact */
- if ((g->f_total_greys == 2) && (g->f_init_total_greys > 2))
- g->f_color_reduction_used = TRUE;
- return 0;
- }
- }
- return -1;
- }
- /* ////////////////////////////////////////////////////////////
- // Free allocated raw image data
- // ////////////////////////////////////////////////////////// */
- void
- free_raw_image( pixel **image )
- {
- free( (char *)image[0] );
- free( (char *)image );
- }
- /* ////////////////////////////////////////////////////////////
- // Decompress GIF data into raw bytes
- // ////////////////////////////////////////////////////////// */
- pixel **
- create_raw_image( byte *inbuf, unsigned int buflen, int *width, int *height, int imageNumber )
- {
- unsigned char *buf;
- unsigned char *start_of_buf = inbuf;
- unsigned char c;
- unsigned char localColorMap[3][MAXCOLORMAPSIZE];
- int useGlobalColormap;
- int bitPixel;
- int imageCount = 0;
- char version[4];
- pixel **image;
- GifState g;
- /* Initialize the GIF state object */
- g.Gif89.transparent = g.Gif89.delayTime = g.Gif89.inputFlag = -1;
- g.Gif89.disposal = 0;
- g.ZeroDataBlock = FALSE;
- g.fresh = FALSE;
- /* XXXSWM -- hack */
- if (buflen < 13) {
- fprintf (stderr, "Not GIF Data, buffer too small\n");
- return NULL;
- }
- buf = (unsigned char *)inbuf;
- inbuf += 6;
- if (strncmp((const char *)buf,"GIF",3) != 0) {
- fprintf( stderr, "GifObject: not GIF data\n" );
- return NULL;
- }
- strncpy(version, (const char *)(buf + 3), 3);
- version[3] = '\0';
- if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) {
- fprintf (stderr, "bad version number, not '87a' or '89a'\n" );
- return NULL;
- }
- buf = (unsigned char *)inbuf;
- inbuf += 7;
- g.GifScreen.Width = LM_to_uint(buf[0],buf[1]);
- g.GifScreen.Height = LM_to_uint(buf[2],buf[3]);
- g.GifScreen.BitPixel = 2<<(buf[4]&0x07);
- g.GifScreen.ColorResolution = (((buf[4]&0x70)>>3)+1);
- g.GifScreen.Background = buf[5];
- g.GifScreen.AspectRatio = buf[6];
- if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */
- if (ReadColorMap(&inbuf,g.GifScreen.BitPixel,g.GifScreen.ColorMap)) {
- fprintf (stderr, "error reading global colormap\n" );
- return NULL;
- }
- }
- if (g.GifScreen.AspectRatio != 0 && g.GifScreen.AspectRatio != 49) {
- float r;
- r = ( (float) g.GifScreen.AspectRatio + 15.0 ) / 64.0;
- #ifdef DEBUG
- _gif_message("warning - non-square pixels; to fix do a 'pnmscale -%cscale %g'",
- r < 1.0 ? 'x' : 'y',
- r < 1.0 ? 1.0 / r : r );
- #endif
- }
- image = NULL;
- for (;;) {
- if (inbuf - start_of_buf >= buflen) {
- fprintf (stderr, "Premature EOF in GIF data\n");
- return NULL;
- }
- c = inbuf[0];
- inbuf++;
- if (c == ';') { /* GIF terminator */
- if (imageCount < imageNumber)
- _gif_error("only %d image%s found in file",
- imageCount, imageCount>1?"s":"" );
- return image;
- }
- if (c == '!') { /* Extension */
- if (inbuf - start_of_buf >= buflen) {
- fprintf (stderr, "Premature EOF in GIF data\n");
- return NULL;
- }
- c = inbuf[0];
- inbuf++;
- DoExtension(&inbuf, c, &g);
- continue;
- }
- if (c != ',') { /* Not a valid start character */
- #ifdef DEBUG
- _gif_message("bogus character 0x%02x, ignoring", (int) c );
- #endif
- continue;
- }
- ++imageCount;
- buf = (unsigned char *)inbuf;
- inbuf += 9;
- useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP);
- bitPixel = 1<<((buf[8]&0x07)+1);
- *width = LM_to_uint(buf[4],buf[5]);
- *height = LM_to_uint(buf[6],buf[7]);
- if (! useGlobalColormap) {
- if (ReadColorMap(&inbuf, bitPixel, localColorMap))
- _gif_error("error reading local colormap", 0 );
- image = ReadImage(&inbuf, *width, *height, localColorMap,
- BitSet(buf[8], INTERLACE), imageCount != imageNumber,
- &g);
- } else {
- image = ReadImage(&inbuf, *width, *height, g.GifScreen.ColorMap,
- BitSet(buf[8], INTERLACE), imageCount != imageNumber,
- &g);
- }
- }
- }
- /* ////////////////////////////////////////////////////////////
- // Create X pixmap from raw image data
- // ////////////////////////////////////////////////////////// */
- /* from "Computer Graphics" by Foley, VanDam, Feiner, Hughes */
- /* 2nd edition */
- static int dither_8X8[8][8] =
- {
- { 0, 32, 8, 40, 2, 34, 10, 42 },
- { 48, 16, 56, 24, 50, 18, 58, 26 },
- { 42, 44, 4, 36, 14, 46, 6, 38 },
- { 60, 28, 52, 20, 62, 30, 54, 22 },
- { 3, 35, 11, 43, 1, 33, 9, 41 },
- { 51, 19, 59, 27, 49, 17, 57, 25 },
- { 15, 47, 7, 39, 13, 45, 5, 37 },
- { 63, 31, 55, 23, 61, 29, 53, 21 }
- };
- /*static int dither_6X6[6][6] =
- //{
- // { 24, 32, 16, 26, 34, 18},
- // { 4, 0, 12, 6, 2, 14},
- // { 20, 8, 28, 22, 10, 30},
- // { 27, 35, 19, 25, 33, 17},
- // { 7, 3, 15, 5, 1, 13},
- // { 23, 11, 31, 21, 9, 29}
- //};
- */
- /*
- static int dither_4X4[4][4] =
- {
- { 0, 8, 2, 10 },
- { 12, 4, 14, 6},
- { 3, 11, 1, 9},
- { 15, 7, 13, 5}
- };
- static int dither_3X3[3][3] =
- {
- { 6, 8, 4 },
- { 1, 0, 3},
- { 5, 2, 7}
- };
- static int dither_2X2[2][2] =
- {
- { 0, 2 },
- { 3, 1}
- };
- */
- /*static int dither_matrix_sz = 2; */
- /*static int dither_matrix_sz = 4; */
- /*static int dither_matrix_sz = 3; */
- static int dither_matrix_sz = 8;
- /* call XListPixFormat() to get bits/pix and pads ? */
- Pixmap
- create_pixmap( GifObj *g, pixel **image, int width, int height, Pixel fg, Pixel bg, float ratio)
- {
- int nullCount = (4 - (width % 4)) & 0x03;
- int ximWidth = width + nullCount;
- byte *ximData = 0;
- pixel *ipp = *image;
- int spacing;
- long pixval;
- int x, y;
- int index;
- Pixmap pm;
- int scaledWidth, scaledHeight;
- if ( g->f_nplanes > 8 )
- ximData = (byte *) malloc(ximWidth * height * 4 );
- else
- ximData = (byte *) malloc(ximWidth * height );
- if (!ximData) {
- fprintf(stderr, "Could not allocate ximage data\n");
- return None;
- }
- /* Monochrome */
- if (g->f_nplanes == 1)
- g->f_ximage = XCreateImage(g->f_dpy, g->f_visual, g->f_nplanes, XYPixmap,
- 0, (char *)ximData, width, height, 32, 0);
- /* 8 bit color */
- /*else if (g->f_nplanes == 8) */
- /* non-mono display */
- else
- g->f_ximage = XCreateImage(g->f_dpy, g->f_visual, g->f_nplanes, ZPixmap,
- 0, (char *)ximData, width, height, 32, 0);
- if (!g->f_ximage) {
- fprintf(stderr, "XCreateImage failed\n");
- return None;
- }
- /* RGB to Pixel Conversion */
- if ( g->f_total_greys == 2 )
- spacing = 65536 / (dither_matrix_sz * dither_matrix_sz);
- else
- spacing = 65536 / g->f_total_greys;
- /*cerr << "spacing" << spacing << "\n"; */
- for (y=0; y < height; y++) {
- for (x=0; x < width; x++) {
- pixval = (long)*ipp;
- /* XColor cellDef; */
- /* cellDef.red = (short)PPM_GETR(pixval); */
- /* cellDef.green = (short)PPM_GETG(pixval); */
- /* cellDef.blue = (short)PPM_GETB(pixval); */
- index = (((short)PPM_GETR(pixval))/64)*16 +
- (((short)PPM_GETG(pixval))/64)*4 +
- ((short)PPM_GETB(pixval))/64;
- /*fprintf(stderr, "grey= %d, grey/space=%d\n", g->GifCMap[index].grey, g->GifCMap[index].grey / spacing);*/
- switch (g->f_do_visual) {
- case DO_GREY:
- switch ( g->f_total_greys ) {
- case 2:
- /*cerr << "index=" << index << "\n"; */
- /*cerr << "GifCMap[index].grey" << GifCMap[index].grey << "\n"; */
- /*cerr << "GifCMap[index].grey/spacing" << GifCMap[index].grey / spacing << "\n"; */
- if ( dither_8X8[x%dither_matrix_sz][y%dither_matrix_sz] < g->GifCMap[index].grey / spacing ) {
- XPutPixel(g->f_ximage,x,y,g->f_white);
- } else {
- XPutPixel(g->f_ximage,x,y,g->f_black);
- }
- break;
- default:
- /*cerr << GifCMap[index].grey / spacing << " "; */
- XPutPixel(g->f_ximage,x,y, g->GifGMap[g->GifCMap[index].grey / spacing]);
- }
-
- break;
- case DO_COLOR:
- #ifdef FLOOD
- fprintf(stderr, "%03d %03d %03d -- %03d %03d %03d ",
- (short)PPM_GETR(pixval),(short)PPM_GETG(pixval),(short)PPM_GETB(pixval),
- g->GifCMap[index].red>>8, g->GifCMap[index].green>>8, g->GifCMap[index].blue>>8
- );
- if ((short)PPM_GETR(pixval) != (GifCMap[index].red>>8) ||
- (short)PPM_GETG(pixval) != (GifCMap[index].green>>8) ||
- (short)PPM_GETB(pixval) != (GifCMap[index].blue>>8))
- puts (" *");
- else
- puts (" -");
- #endif
- XPutPixel(g->f_ximage,x,y, g->GifCMap[index].pixel);
- /*
- switch ( g->f_visual_class ) {
- case StaticColor:
- case PseudoColor:
- XPutPixel(g->f_ximage,x,y, g->GifCMap[index].pixel);
- break;
- case TrueColor:
- case DirectColor:
- break;
- }
- */
- }
- ipp++;
- }
- for (x=width;x<ximWidth;x++)
- XPutPixel(g->f_ximage,x,y,bg); /* padding */
- }
- scaledWidth = width * ratio + 0.5;
- scaledHeight = height * ratio + 0.5;
- if (scaledWidth == 0)
- scaledWidth = 1;
- if (scaledHeight == 0)
- scaledHeight = 1;
- pm = XCreatePixmap(g->f_dpy,g->f_drawable,
- scaledWidth,scaledHeight,
- g->f_nplanes);
- if (!pm) {
- fprintf(stderr, "could not create pixmap\n");
- return None;
- }
- _XmPutScaledImage (g->f_dpy,pm,g->f_gc,g->f_ximage,
- 0,0,0,0,width,height,
- scaledWidth,scaledHeight);
- XDestroyImage(g->f_ximage);
- g->f_ximage = NULL;
-
- return(pm);
- }
- /* /////////////////////////////////////////////////////////////////
- // Load pixmap from GIF data
- // /////////////////////////////////////////////////////////////// */
- Pixmap
- gif_to_pixmap(GifObj *g, byte *inbuf, unsigned int buflen, Dimension *w, Dimension *h, Pixel fg, Pixel bg, float ratio)
- {
- Pixmap pixmap;
- pixel **raw_image;
- int width, height;
- /* Create raw image from compress GIF data */
- raw_image = create_raw_image (inbuf, buflen, &width, &height, 1);
- if (!raw_image) return None;
- /* Create X pixmap from raw image data */
- pixmap = create_pixmap(g, raw_image, width, height, fg, bg, ratio);
- /* Free raw image data */
- free_raw_image(raw_image);
- /* Set X pixmap dimensions */
- *w = (Dimension) width * ratio + 0.5;
- *h = (Dimension) height * ratio + 0.5;
- if (*w == 0)
- *w = 1;
- if (*h == 0)
- *h = 1;
- /* Return X pixmap */
- return pixmap;
- }
|