GifUtils.c 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  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)
  10. * any later version.
  11. *
  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
  16. * details.
  17. *
  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
  22. */
  23. /*
  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
  29. * OR DISCLOSURE.
  30. *
  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
  35. * INTERNATIONAL, LTD.
  36. *
  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.
  42. *
  43. * HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.
  44. * 1315 Dell Avenue
  45. * Campbell, CA 95008
  46. *
  47. */
  48. /* +-------------------------------------------------------------------+ */
  49. /* | Portions lifted from giftoppm.c (pbmplus version 10dec91) | */
  50. /* | | */
  51. /* | Copyright 1990, David Koblas. | */
  52. /* | Permission to use, copy, modify, and distribute this software | */
  53. /* | and its documentation for any purpose and without fee is hereby | */
  54. /* | granted, provided that the above copyright notice appear in all | */
  55. /* | copies and that both that copyright notice and this permission | */
  56. /* | notice appear in supporting documentation. This software is | */
  57. /* | provided "as is" without express or implied warranty. | */
  58. /* +-------------------------------------------------------------------+ */
  59. #define C_Gif
  60. #define L_Graphics
  61. #define C_MessageMgr
  62. #define L_Managers
  63. /* include files */
  64. #include <stdio.h>
  65. #include <stdarg.h>
  66. #include <stdlib.h>
  67. #include <string.h>
  68. #include <math.h>
  69. #include <assert.h>
  70. #include <Xm/XmPrivate.h>
  71. #include "GifUtilsI.h"
  72. #ifndef __STDC__
  73. #define debug1(s, x) s << "x" << " = " << (x) << "\n"
  74. #else
  75. #define debug1(s, x) s << #x << " = " << (x) << "\n"
  76. #endif
  77. #define MAX_GHANDS 16 /* maximum # of GRAF handles */
  78. #define PPM_ASSIGN(p,red,grn,blu) (p) = ((pixel) (red) << 20) | ((pixel) (grn) << 10) | (pixel) (blu)
  79. #define PPM_GETR(p) (((p) & 0x3ff00000) >> 20)
  80. #define PPM_GETG(p) (((p) & 0xffc00) >> 10)
  81. #define PPM_GETB(p) ((p) & 0x3ff)
  82. #define MAXCOLORMAPSIZE 256
  83. #define TRUE 1
  84. #define FALSE 0
  85. #define CM_RED 0
  86. #define CM_GREEN 1
  87. #define CM_BLUE 2
  88. #define MAX_LWZ_BITS 12
  89. #define INTERLACE 0x40
  90. #define LOCALCOLORMAP 0x80
  91. #define BitSet(byte, bit) (((byte) & (bit)) == (bit))
  92. #define LM_to_uint(a,b) (((b)<<8)|(a))
  93. typedef struct {
  94. unsigned int Width;
  95. unsigned int Height;
  96. unsigned char ColorMap[3][MAXCOLORMAPSIZE];
  97. unsigned int BitPixel;
  98. unsigned int ColorResolution;
  99. unsigned int Background;
  100. unsigned int AspectRatio;
  101. } GifScreenType;
  102. typedef struct {
  103. int transparent;
  104. int delayTime;
  105. int inputFlag;
  106. int disposal;
  107. } Gif89Type;
  108. /*
  109. * This structure holds variables that were formerly global or static
  110. * within a function in the original giftoppm code. They have been
  111. * moved into this object to ensure thread re-entrancy of the routines
  112. * that use them. A unique instance of this object is created for each
  113. * thread and passed to the appropriate routines.
  114. */
  115. typedef struct {
  116. /* Formerly global variables */
  117. GifScreenType GifScreen;
  118. Gif89Type Gif89;
  119. int ZeroDataBlock;
  120. /* Formerly static variables declared in DoExtension */
  121. char ext_buf[256];
  122. /* Formerly static variables declared in GetCode */
  123. unsigned char buf[280];
  124. int curbit, lastbit, done, last_byte;
  125. /* Formerly static variables declared in LWZReadByte*/
  126. int fresh;
  127. int code_size, set_code_size;
  128. int max_code, max_code_size;
  129. int firstcode, oldcode;
  130. int clear_code, end_code;
  131. int table[2][(1<< MAX_LWZ_BITS)];
  132. int stack[(1<<(MAX_LWZ_BITS))*2], *sp;
  133. } GifState;
  134. /*********************/
  135. static void
  136. _gif_error( char *format, ... )
  137. {
  138. va_list args;
  139. va_start( args, format );
  140. fprintf( stderr, "GifObject: " );
  141. (void) vfprintf( stderr, format, args );
  142. fputc( '\n', stderr );
  143. va_end( args );
  144. /* throw (Exception()); */
  145. #if 0
  146. abort();
  147. #endif
  148. }
  149. /*********************/
  150. static void
  151. _gif_message( char *format, ... )
  152. {
  153. va_list args;
  154. va_start( args, format );
  155. fprintf( stderr, "GifObject: " );
  156. (void) vfprintf( stderr, format, args );
  157. fputc( '\n', stderr );
  158. va_end( args );
  159. }
  160. /*********************/
  161. static pixel **
  162. _gif_allocarray( int cols, int rows, int size )
  163. {
  164. char** its;
  165. int i;
  166. its = (char**) malloc( rows * sizeof(char*) );
  167. if ( its == (char**) 0 )
  168. _gif_error( "out of memory allocating an array", 0 );
  169. its[0] = (char*) malloc( rows * cols * size );
  170. if ( its[0] == (char*) 0 )
  171. _gif_error( "out of memory allocating an array", 0 );
  172. for ( i = 1; i < rows; ++i )
  173. its[i] = &(its[0][i * cols * size]);
  174. return (pixel **)its;
  175. }
  176. /*********************/
  177. static int
  178. GetDataBlock(byte **inbuf, unsigned char *buf, GifState *g)
  179. {
  180. unsigned char count;
  181. count = (*inbuf)[0];
  182. (*inbuf)++;
  183. g->ZeroDataBlock = count == 0;
  184. if (count) {
  185. memcpy (buf, *inbuf, count);
  186. *inbuf += count;
  187. }
  188. return count;
  189. }
  190. /*********************/
  191. static int
  192. ReadColorMap(byte **inbuf, int number, unsigned char buffer[3][MAXCOLORMAPSIZE])
  193. {
  194. int i;
  195. unsigned char *rgb;
  196. for (i = 0; i < number; ++i) {
  197. rgb = (unsigned char *)*inbuf;
  198. *inbuf += 3;
  199. buffer[CM_RED][i] = rgb[0] ;
  200. buffer[CM_GREEN][i] = rgb[1] ;
  201. buffer[CM_BLUE][i] = rgb[2] ;
  202. }
  203. return FALSE;
  204. }
  205. /*********************/
  206. static int
  207. DoExtension(byte **inbuf, int label, GifState *g)
  208. {
  209. char *str;
  210. char *buf = g->ext_buf;
  211. switch (label) {
  212. case 0x01: /* Plain Text Extension */
  213. str = "Plain Text Extension";
  214. break;
  215. case 0xff: /* Application Extension */
  216. str = "Application Extension";
  217. break;
  218. case 0xfe: /* Comment Extension */
  219. str = "Comment Extension";
  220. while (GetDataBlock(inbuf, (unsigned char*) buf, g) != 0) {
  221. #ifdef DEBUG
  222. _gif_message("gif comment: %s", buf );
  223. #endif
  224. }
  225. return FALSE;
  226. case 0xf9: /* Graphic Control Extension */
  227. str = "Graphic Control Extension";
  228. (void) GetDataBlock(inbuf, (unsigned char*) buf, g);
  229. g->Gif89.disposal = (buf[0] >> 2) & 0x7;
  230. g->Gif89.inputFlag = (buf[0] >> 1) & 0x1;
  231. g->Gif89.delayTime = LM_to_uint(buf[1], buf[2]);
  232. if ((buf[0] & 0x1) != 0)
  233. g->Gif89.transparent = buf[3];
  234. while (GetDataBlock(inbuf, (unsigned char*) buf, g) != 0)
  235. ;
  236. return FALSE;
  237. default:
  238. str = buf;
  239. sprintf(buf, "UNKNOWN (0x%02x)", label);
  240. break;
  241. }
  242. #ifdef DEBUG
  243. _gif_message("got a '%s' extension", str );
  244. #endif
  245. while (GetDataBlock(inbuf, (unsigned char*) buf, g) != 0)
  246. ;
  247. return FALSE;
  248. }
  249. /*********************/
  250. static int
  251. GetCode(byte **inbuf, int code_size, int flag, GifState *g)
  252. {
  253. int i, j, ret;
  254. unsigned char count;
  255. unsigned char *buf = g->buf;
  256. if (flag) {
  257. for (i = 0; i < 280; i++)
  258. buf[i] = 0;
  259. g->last_byte = 0;
  260. g->curbit = 0;
  261. g->lastbit = 0;
  262. g->done = FALSE;
  263. return 0;
  264. }
  265. if ( (g->curbit+code_size) >= g->lastbit) {
  266. if (g->done) {
  267. if (g->curbit >= g->lastbit)
  268. _gif_error("ran off the end of my bits", 0 );
  269. return -1;
  270. }
  271. if (g->last_byte) {
  272. buf[0] = buf[g->last_byte-2];
  273. buf[1] = buf[g->last_byte-1];
  274. }
  275. if ((count = GetDataBlock(inbuf, &buf[2], g)) == 0)
  276. g->done = TRUE;
  277. g->last_byte = 2 + count;
  278. g->curbit = (g->curbit - g->lastbit) + 16;
  279. g->lastbit = (2+count)*8 ;
  280. }
  281. ret = 0;
  282. for (i = g->curbit, j = 0; j < code_size; ++i, ++j)
  283. ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j;
  284. g->curbit += code_size;
  285. return ret;
  286. }
  287. /*********************/
  288. static int
  289. LWZReadByte(byte **inbuf, int flag, int input_code_size, GifState *g)
  290. {
  291. int code, incode;
  292. int i;
  293. if (flag) {
  294. g->set_code_size = input_code_size;
  295. g->code_size = g->set_code_size+1;
  296. g->clear_code = 1 << g->set_code_size ;
  297. g->end_code = g->clear_code + 1;
  298. g->max_code_size = 2*g->clear_code;
  299. g->max_code = g->clear_code+2;
  300. GetCode(inbuf, 0, TRUE, g);
  301. g->fresh = TRUE;
  302. for (i = 0; i < g->clear_code; ++i) {
  303. g->table[0][i] = 0;
  304. g->table[1][i] = i;
  305. }
  306. for (; i < (1<<MAX_LWZ_BITS); ++i)
  307. g->table[0][i] = g->table[1][0] = 0;
  308. g->sp = g->stack;
  309. return 0;
  310. } else if (g->fresh) {
  311. g->fresh = FALSE;
  312. do {
  313. g->firstcode = g->oldcode =
  314. GetCode(inbuf, g->code_size, FALSE, g);
  315. } while (g->firstcode == g->clear_code);
  316. return g->firstcode;
  317. }
  318. if (g->sp > g->stack)
  319. return *--(g->sp);
  320. while ((code = GetCode(inbuf, g->code_size, FALSE, g)) >= 0) {
  321. if (code == g->clear_code) {
  322. for (i = 0; i < g->clear_code; ++i) {
  323. g->table[0][i] = 0;
  324. g->table[1][i] = i;
  325. }
  326. for (; i < (1<<MAX_LWZ_BITS); ++i)
  327. g->table[0][i] = g->table[1][i] = 0;
  328. g->code_size = g->set_code_size+1;
  329. g->max_code_size = 2*g->clear_code;
  330. g->max_code = g->clear_code+2;
  331. g->sp = g->stack;
  332. g->firstcode = g->oldcode =
  333. GetCode(inbuf, g->code_size, FALSE, g);
  334. return g->firstcode;
  335. } else if (code == g->end_code) {
  336. int count;
  337. unsigned char buf[260];
  338. if (g->ZeroDataBlock)
  339. return -2;
  340. while ((count = GetDataBlock(inbuf, buf, g)) > 0)
  341. ;
  342. #ifdef DEBUG
  343. if (count != 0)
  344. _gif_message("missing EOD in data stream (common occurence)");
  345. #endif
  346. return -2;
  347. }
  348. incode = code;
  349. if (code >= g->max_code) {
  350. *(g->sp)++ = g->firstcode;
  351. code = g->oldcode;
  352. }
  353. while (code >= g->clear_code) {
  354. *(g->sp++) = g->table[1][code];
  355. if (code == g->table[0][code])
  356. _gif_error("circular table entry BIG ERROR", 0);
  357. code = g->table[0][code];
  358. }
  359. *(g->sp)++ = g->firstcode = g->table[1][code];
  360. if ((code = g->max_code) <(1<<MAX_LWZ_BITS)) {
  361. g->table[0][code] = g->oldcode;
  362. g->table[1][code] = g->firstcode;
  363. ++(g->max_code);
  364. if ((g->max_code >= g->max_code_size) &&
  365. (g->max_code_size < (1<<MAX_LWZ_BITS))) {
  366. g->max_code_size *= 2;
  367. ++(g->code_size);
  368. }
  369. }
  370. g->oldcode = incode;
  371. if (g->sp > g->stack)
  372. return *--(g->sp);
  373. }
  374. return code;
  375. }
  376. /*********************/
  377. pixel **
  378. ReadImage(byte **inbuf, int len, int height, unsigned char cmap[3][MAXCOLORMAPSIZE], int interlace, int ignore, GifState *g)
  379. {
  380. unsigned char c;
  381. int v;
  382. int xpos = 0, ypos = 0, pass = 0;
  383. pixel **image;
  384. /*
  385. ** Initialize the Compression routines
  386. */
  387. c = (*inbuf)[0];
  388. (*inbuf)++;
  389. if (LWZReadByte(inbuf, TRUE, c, g) < 0)
  390. _gif_error("error reading image", 0 );
  391. /*
  392. ** If this is an "uninteresting picture" ignore it.
  393. */
  394. if (ignore) {
  395. #ifdef DEBUG
  396. _gif_message("skipping image..." );
  397. #endif
  398. while (LWZReadByte(inbuf, FALSE, c, g) >= 0)
  399. ;
  400. return NULL;
  401. }
  402. if ((image = _gif_allocarray(len, height, sizeof(pixel))) == NULL)
  403. _gif_error("couldn't alloc space for image", 0 );
  404. #ifdef DEBUG
  405. _gif_message("reading %d by %d%s GIF image",
  406. len, height, interlace ? " interlaced" : "" );
  407. #endif
  408. while ((v = LWZReadByte(inbuf,FALSE,c, g)) >= 0 ) {
  409. PPM_ASSIGN(image[ypos][xpos], cmap[CM_RED][v],
  410. cmap[CM_GREEN][v], cmap[CM_BLUE][v]);
  411. ++xpos;
  412. if (xpos == len) {
  413. xpos = 0;
  414. if (interlace) {
  415. switch (pass) {
  416. case 0:
  417. case 1:
  418. ypos += 8; break;
  419. case 2:
  420. ypos += 4; break;
  421. case 3:
  422. ypos += 2; break;
  423. }
  424. if (ypos >= height) {
  425. ++pass;
  426. switch (pass) {
  427. case 1:
  428. ypos = 4; break;
  429. case 2:
  430. ypos = 2; break;
  431. case 3:
  432. ypos = 1; break;
  433. default:
  434. goto fini;
  435. }
  436. }
  437. } else {
  438. ++ypos;
  439. }
  440. }
  441. if (ypos >= height)
  442. break;
  443. }
  444. fini:
  445. #ifdef DEBUG
  446. if (LWZReadByte(inbuf,FALSE,c, g)>=0)
  447. _gif_message("too much input data, ignoring extra...");
  448. #endif
  449. return image;
  450. }
  451. /* ////////////////////////////////////////////////////////////
  452. // class constructor
  453. // ////////////////////////////////////////////////////////// */
  454. enum _DtGrLoadStatus InitGifObject (
  455. GifObj *go,
  456. Display *dpy,
  457. Drawable drawable,
  458. Screen *screen,
  459. int depth,
  460. Colormap colormap,
  461. Visual *visual,
  462. GC gc,
  463. enum _DtGrColorModel colorModel,
  464. Boolean allowReducedColors)
  465. {
  466. int r, g, b, i, visualsMatched;
  467. XVisualInfo vTemplate, *visualList;
  468. /*
  469. ** Initialize structure values
  470. */
  471. go->bits_per_pixel = 2;
  472. go->colors_per_pixel = (int) pow (2, go->bits_per_pixel);
  473. go->total_colors = (int) pow (go->colors_per_pixel, 3);
  474. go->f_color_map_constructed = 0;
  475. go->f_total_greys = 2;
  476. go->f_ximage = NULL;
  477. go->f_dpy = dpy;
  478. go->f_drawable = drawable;
  479. go->f_screen = XScreenNumberOfScreen(screen);
  480. go->f_dft_depth = depth;
  481. go->f_cmap = colormap;
  482. go->f_gc = gc;
  483. go->f_visual = visual;
  484. go->f_ncells = DisplayCells(go->f_dpy, go->f_screen);
  485. go->f_nplanes = DisplayPlanes(go->f_dpy,go->f_screen);
  486. go->f_white = WhitePixel(go->f_dpy, go->f_screen);
  487. go->f_black = BlackPixel(go->f_dpy, go->f_screen);
  488. go->f_allow_reduced_colors = allowReducedColors;
  489. go->f_color_reduction_used = FALSE;
  490. /*
  491. ** Initialize color allocation fields according to the color model
  492. ** specified by the caller.
  493. */
  494. switch (colorModel)
  495. {
  496. case _DtGrCOLOR:
  497. go->f_do_visual = DO_COLOR;
  498. go->f_init_total_greys = 32;
  499. break;
  500. case _DtGrGRAY_SCALE:
  501. go->f_do_visual = DO_GREY;
  502. go->f_init_total_greys = 32;
  503. break;
  504. case _DtGrBITONAL:
  505. go->f_do_visual = DO_GREY;
  506. go->f_init_total_greys = 2;
  507. break;
  508. default:
  509. /* Should never get here */
  510. go->f_do_visual = DO_COLOR;
  511. go->f_init_total_greys = 32;
  512. }
  513. /* Return if the colormap is already allocated */
  514. if ( go->f_color_map_constructed )
  515. return (_DtGrSUCCESS);
  516. /* find the visual class code */
  517. vTemplate.screen = go->f_screen;
  518. vTemplate.depth = go->f_dft_depth;
  519. visualList = XGetVisualInfo( go->f_dpy,
  520. VisualScreenMask | VisualDepthMask,
  521. &vTemplate, &visualsMatched );
  522. /* Return failure if we can't find a matching visual */
  523. if ( visualsMatched == 0 )
  524. return (_DtGrCONVERT_FAILURE);
  525. go->f_visual_class = StaticGray;
  526. for ( i=0; i<visualsMatched; i++ )
  527. {
  528. if ( visualList[i].visual == go->f_visual )
  529. {
  530. go->f_visual_class = visualList[i].class;
  531. break;
  532. }
  533. }
  534. XFree(visualList);
  535. /* Construct a 4x4x4 color cube */
  536. i = 0;
  537. for (r = 0; r < go->colors_per_pixel; r++)
  538. for (g = 0; g < go->colors_per_pixel; g++)
  539. for (b = 0; b < go->colors_per_pixel; b++)
  540. {
  541. go->GifCMap[i].red = ((r * 65535)/(go->colors_per_pixel - 1));
  542. go->GifCMap[i].green = ((g * 65535)/(go->colors_per_pixel - 1));
  543. go->GifCMap[i].blue = ((b * 65535)/(go->colors_per_pixel - 1));
  544. i++;
  545. }
  546. /*
  547. ** Allocate X pixels, either color or greyscale values depending upon
  548. ** visual class and color model.
  549. */
  550. switch ( go->f_visual_class )
  551. {
  552. case StaticGray:
  553. case GrayScale:
  554. case StaticColor:
  555. {
  556. /*
  557. ** Return failure if caller is insisting on color and this
  558. ** visual can't provide it.
  559. */
  560. if ((colorModel == _DtGrCOLOR) && !allowReducedColors)
  561. return (_DtGrCOLOR_FAILED);
  562. if ( allocate_greys(go) != 0 )
  563. return (_DtGrCOLOR_FAILED);
  564. break;
  565. }
  566. case PseudoColor:
  567. case DirectColor:
  568. case TrueColor:
  569. {
  570. if (colorModel == _DtGrCOLOR)
  571. {
  572. if ( allocate_colors(go) != 0 )
  573. return (_DtGrCOLOR_FAILED);
  574. }
  575. else
  576. {
  577. if ( allocate_greys(go) != 0 )
  578. return (_DtGrCOLOR_FAILED);
  579. }
  580. break;
  581. }
  582. default:
  583. return (_DtGrCONVERT_FAILURE);
  584. }
  585. /*
  586. ** Colors successfully allocated, return status code indicating
  587. ** whether we had to fallback to a degraded color model.
  588. */
  589. if (go->f_color_reduction_used)
  590. return (_DtGrCOLOR_REDUCE);
  591. else
  592. return (_DtGrSUCCESS);
  593. }
  594. /* /////////////////////////////////////////////////////////////////
  595. // class destructor
  596. // /////////////////////////////////////////////////////////////// */
  597. void DeleteGifObjectResources(GifObj *g)
  598. {
  599. }
  600. int allocate_colors(GifObj *g)
  601. {
  602. int i, j;
  603. /*return allocate_greys(); // use this to test grey-scale */
  604. XColor color;
  605. unsigned long* colors;
  606. color.flags = DoRed | DoGreen | DoBlue;
  607. for (i = 0; i < g->total_colors; i++) {
  608. color.red = g->GifCMap[i].red;
  609. color.green = g->GifCMap[i].green;
  610. color.blue = g->GifCMap[i].blue;
  611. /*printf ("Allocating %3d: ", i); */
  612. if ( !XAllocColor (g->f_dpy, g->f_cmap, &color) ) {
  613. /*puts ("FAILED!!!"); */
  614. colors = (unsigned long *) malloc (sizeof(unsigned long) * i);
  615. for (j = 0; j < i; j++)
  616. colors[j] = g->GifCMap[j].pixel;
  617. /*cerr << "Xfree in allocate_colors(): " << i << "\n"; */
  618. XFreeColors (g->f_dpy, g->f_cmap, colors, i, 0);
  619. free(colors);
  620. /* fallback to greys */
  621. if (g->f_allow_reduced_colors)
  622. {
  623. g->f_color_reduction_used = TRUE;
  624. return allocate_greys(g);
  625. }
  626. else
  627. return (_DtGrCOLOR_FAILED);
  628. }
  629. /*fprintf(stderr, "i=%d pixel=%d\n", i, color.pixel);*/
  630. /*printf ("@ %d\n", color.pixel); */
  631. g->GifCMap[i].pixel = color.pixel;
  632. }
  633. g->f_do_visual = DO_COLOR;
  634. g->f_color_map_constructed = 1;
  635. return 0;
  636. }
  637. int allocate_greys(GifObj *g)
  638. {
  639. XColor color;
  640. int i, j;
  641. unsigned long* colors;
  642. color.flags = DoRed | DoGreen | DoBlue;
  643. for ( i=0; i<g->total_colors; i++ ) {
  644. /*
  645. debug1(cerr, i);
  646. debug1(cerr, GifCMap[i].red);
  647. debug1(cerr, GifCMap[i].green);
  648. debug1(cerr, GifCMap[i].blue);
  649. debug1(cerr, 0.299 * GifCMap[i].red + 0.587 * GifCMap[i].green +
  650. 0.114 * GifCMap[i].blue);
  651. debug1(cerr, GifCMap[i].grey);
  652. */
  653. g->GifCMap[i].grey = (unsigned short)(0.299 * g->GifCMap[i].red +
  654. 0.587 * g->GifCMap[i].green +
  655. 0.114 * g->GifCMap[i].blue);
  656. }
  657. /*
  658. if ( StaticColor == g->f_visual_class ||
  659. TrueColor == g->f_visual_class )
  660. */
  661. if ( StaticColor == g->f_visual_class)
  662. {
  663. g->f_do_visual = DO_GREY;
  664. g->f_total_greys = 2;
  665. return 0;
  666. }
  667. for ( g->f_total_greys=g->f_init_total_greys; g->f_total_greys>=2;
  668. g->f_total_greys/=2 )
  669. {
  670. /*fprintf(stderr, "f_total_greys = %d\n", g->f_total_greys); */
  671. /*
  672. ** Return failure if we're about to downgrade from greyscale
  673. ** to dithered monochrome and we don't allow reduced colors.
  674. */
  675. if ((g->f_total_greys == 2) && (g->f_init_total_greys > 2) &&
  676. (!g->f_allow_reduced_colors))
  677. return -1;
  678. for (i = 0; i<g->f_total_greys; i++) {
  679. color.red =
  680. color.green =
  681. color.blue = (i*65535)/(g->f_total_greys - 1);
  682. /*fprintf (stderr, "Allocating %3d: ", i);*/
  683. if ( !XAllocColor (g->f_dpy, g->f_cmap, &color) ) {
  684. /*fprintf(stderr, "alloc Grey FAILED!!!");*/
  685. colors = (unsigned long *) malloc (sizeof(unsigned long) * i);
  686. for (j = 0; j < i; j++)
  687. colors[j] = g->GifGMap[j];
  688. /*cerr << "Xfree in allocate_greys()\n"; */
  689. XFreeColors (g->f_dpy, g->f_cmap, colors, i, 0);
  690. free(colors);
  691. break;
  692. }
  693. /*printf ("@ %d\n", color.pixel); */
  694. g->GifGMap[i] = color.pixel;
  695. }
  696. if ( i == g->f_total_greys ) {
  697. /*
  698. for ( int l=0; l<i; l++ )
  699. cerr << "GifGMap[l]= " << GifGMap[l] << "\n";
  700. */
  701. g->f_color_map_constructed = 1;
  702. g->f_do_visual = DO_GREY;
  703. /* If greyscape was downgraded to bitonal, record the fact */
  704. if ((g->f_total_greys == 2) && (g->f_init_total_greys > 2))
  705. g->f_color_reduction_used = TRUE;
  706. return 0;
  707. }
  708. }
  709. return -1;
  710. }
  711. /* ////////////////////////////////////////////////////////////
  712. // Free allocated raw image data
  713. // ////////////////////////////////////////////////////////// */
  714. void
  715. free_raw_image( pixel **image )
  716. {
  717. free( (char *)image[0] );
  718. free( (char *)image );
  719. }
  720. /* ////////////////////////////////////////////////////////////
  721. // Decompress GIF data into raw bytes
  722. // ////////////////////////////////////////////////////////// */
  723. pixel **
  724. create_raw_image( byte *inbuf, unsigned int buflen, int *width, int *height, int imageNumber )
  725. {
  726. unsigned char *buf;
  727. unsigned char *start_of_buf = inbuf;
  728. unsigned char c;
  729. unsigned char localColorMap[3][MAXCOLORMAPSIZE];
  730. int useGlobalColormap;
  731. int bitPixel;
  732. int imageCount = 0;
  733. char version[4];
  734. pixel **image;
  735. GifState g;
  736. /* Initialize the GIF state object */
  737. g.Gif89.transparent = g.Gif89.delayTime = g.Gif89.inputFlag = -1;
  738. g.Gif89.disposal = 0;
  739. g.ZeroDataBlock = FALSE;
  740. g.fresh = FALSE;
  741. /* XXXSWM -- hack */
  742. if (buflen < 13) {
  743. fprintf (stderr, "Not GIF Data, buffer too small\n");
  744. return NULL;
  745. }
  746. buf = (unsigned char *)inbuf;
  747. inbuf += 6;
  748. if (strncmp((const char *)buf,"GIF",3) != 0) {
  749. fprintf( stderr, "GifObject: not GIF data\n" );
  750. return NULL;
  751. }
  752. strncpy(version, (const char *)(buf + 3), 3);
  753. version[3] = '\0';
  754. if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) {
  755. fprintf (stderr, "bad version number, not '87a' or '89a'\n" );
  756. return NULL;
  757. }
  758. buf = (unsigned char *)inbuf;
  759. inbuf += 7;
  760. g.GifScreen.Width = LM_to_uint(buf[0],buf[1]);
  761. g.GifScreen.Height = LM_to_uint(buf[2],buf[3]);
  762. g.GifScreen.BitPixel = 2<<(buf[4]&0x07);
  763. g.GifScreen.ColorResolution = (((buf[4]&0x70)>>3)+1);
  764. g.GifScreen.Background = buf[5];
  765. g.GifScreen.AspectRatio = buf[6];
  766. if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */
  767. if (ReadColorMap(&inbuf,g.GifScreen.BitPixel,g.GifScreen.ColorMap)) {
  768. fprintf (stderr, "error reading global colormap\n" );
  769. return NULL;
  770. }
  771. }
  772. if (g.GifScreen.AspectRatio != 0 && g.GifScreen.AspectRatio != 49) {
  773. float r;
  774. r = ( (float) g.GifScreen.AspectRatio + 15.0 ) / 64.0;
  775. #ifdef DEBUG
  776. _gif_message("warning - non-square pixels; to fix do a 'pnmscale -%cscale %g'",
  777. r < 1.0 ? 'x' : 'y',
  778. r < 1.0 ? 1.0 / r : r );
  779. #endif
  780. }
  781. image = NULL;
  782. for (;;) {
  783. if (inbuf - start_of_buf >= buflen) {
  784. fprintf (stderr, "Premature EOF in GIF data\n");
  785. return NULL;
  786. }
  787. c = inbuf[0];
  788. inbuf++;
  789. if (c == ';') { /* GIF terminator */
  790. if (imageCount < imageNumber)
  791. _gif_error("only %d image%s found in file",
  792. imageCount, imageCount>1?"s":"" );
  793. return image;
  794. }
  795. if (c == '!') { /* Extension */
  796. if (inbuf - start_of_buf >= buflen) {
  797. fprintf (stderr, "Premature EOF in GIF data\n");
  798. return NULL;
  799. }
  800. c = inbuf[0];
  801. inbuf++;
  802. DoExtension(&inbuf, c, &g);
  803. continue;
  804. }
  805. if (c != ',') { /* Not a valid start character */
  806. #ifdef DEBUG
  807. _gif_message("bogus character 0x%02x, ignoring", (int) c );
  808. #endif
  809. continue;
  810. }
  811. ++imageCount;
  812. buf = (unsigned char *)inbuf;
  813. inbuf += 9;
  814. useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP);
  815. bitPixel = 1<<((buf[8]&0x07)+1);
  816. *width = LM_to_uint(buf[4],buf[5]);
  817. *height = LM_to_uint(buf[6],buf[7]);
  818. if (! useGlobalColormap) {
  819. if (ReadColorMap(&inbuf, bitPixel, localColorMap))
  820. _gif_error("error reading local colormap", 0 );
  821. image = ReadImage(&inbuf, *width, *height, localColorMap,
  822. BitSet(buf[8], INTERLACE), imageCount != imageNumber,
  823. &g);
  824. } else {
  825. image = ReadImage(&inbuf, *width, *height, g.GifScreen.ColorMap,
  826. BitSet(buf[8], INTERLACE), imageCount != imageNumber,
  827. &g);
  828. }
  829. }
  830. }
  831. /* ////////////////////////////////////////////////////////////
  832. // Create X pixmap from raw image data
  833. // ////////////////////////////////////////////////////////// */
  834. /* from "Computer Graphics" by Foley, VanDam, Feiner, Hughes */
  835. /* 2nd edition */
  836. static int dither_8X8[8][8] =
  837. {
  838. { 0, 32, 8, 40, 2, 34, 10, 42 },
  839. { 48, 16, 56, 24, 50, 18, 58, 26 },
  840. { 42, 44, 4, 36, 14, 46, 6, 38 },
  841. { 60, 28, 52, 20, 62, 30, 54, 22 },
  842. { 3, 35, 11, 43, 1, 33, 9, 41 },
  843. { 51, 19, 59, 27, 49, 17, 57, 25 },
  844. { 15, 47, 7, 39, 13, 45, 5, 37 },
  845. { 63, 31, 55, 23, 61, 29, 53, 21 }
  846. };
  847. /*static int dither_6X6[6][6] =
  848. //{
  849. // { 24, 32, 16, 26, 34, 18},
  850. // { 4, 0, 12, 6, 2, 14},
  851. // { 20, 8, 28, 22, 10, 30},
  852. // { 27, 35, 19, 25, 33, 17},
  853. // { 7, 3, 15, 5, 1, 13},
  854. // { 23, 11, 31, 21, 9, 29}
  855. //};
  856. */
  857. /*
  858. static int dither_4X4[4][4] =
  859. {
  860. { 0, 8, 2, 10 },
  861. { 12, 4, 14, 6},
  862. { 3, 11, 1, 9},
  863. { 15, 7, 13, 5}
  864. };
  865. static int dither_3X3[3][3] =
  866. {
  867. { 6, 8, 4 },
  868. { 1, 0, 3},
  869. { 5, 2, 7}
  870. };
  871. static int dither_2X2[2][2] =
  872. {
  873. { 0, 2 },
  874. { 3, 1}
  875. };
  876. */
  877. /*static int dither_matrix_sz = 2; */
  878. /*static int dither_matrix_sz = 4; */
  879. /*static int dither_matrix_sz = 3; */
  880. static int dither_matrix_sz = 8;
  881. /* call XListPixFormat() to get bits/pix and pads ? */
  882. Pixmap
  883. create_pixmap( GifObj *g, pixel **image, int width, int height, Pixel fg, Pixel bg, float ratio)
  884. {
  885. int nullCount = (4 - (width % 4)) & 0x03;
  886. int ximWidth = width + nullCount;
  887. byte *ximData = 0;
  888. pixel *ipp = *image;
  889. int spacing;
  890. long pixval;
  891. int x, y;
  892. int index;
  893. Pixmap pm;
  894. int scaledWidth, scaledHeight;
  895. if ( g->f_nplanes > 8 )
  896. ximData = (byte *) malloc(ximWidth * height * 4 );
  897. else
  898. ximData = (byte *) malloc(ximWidth * height );
  899. if (!ximData) {
  900. fprintf(stderr, "Could not allocate ximage data\n");
  901. return None;
  902. }
  903. /* Monochrome */
  904. if (g->f_nplanes == 1)
  905. g->f_ximage = XCreateImage(g->f_dpy, g->f_visual, g->f_nplanes, XYPixmap,
  906. 0, (char *)ximData, width, height, 32, 0);
  907. /* 8 bit color */
  908. /*else if (g->f_nplanes == 8) */
  909. /* non-mono display */
  910. else
  911. g->f_ximage = XCreateImage(g->f_dpy, g->f_visual, g->f_nplanes, ZPixmap,
  912. 0, (char *)ximData, width, height, 32, 0);
  913. if (!g->f_ximage) {
  914. fprintf(stderr, "XCreateImage failed\n");
  915. return None;
  916. }
  917. /* RGB to Pixel Conversion */
  918. if ( g->f_total_greys == 2 )
  919. spacing = 65536 / (dither_matrix_sz * dither_matrix_sz);
  920. else
  921. spacing = 65536 / g->f_total_greys;
  922. /*cerr << "spacing" << spacing << "\n"; */
  923. for (y=0; y < height; y++) {
  924. for (x=0; x < width; x++) {
  925. pixval = (long)*ipp;
  926. /* XColor cellDef; */
  927. /* cellDef.red = (short)PPM_GETR(pixval); */
  928. /* cellDef.green = (short)PPM_GETG(pixval); */
  929. /* cellDef.blue = (short)PPM_GETB(pixval); */
  930. index = (((short)PPM_GETR(pixval))/64)*16 +
  931. (((short)PPM_GETG(pixval))/64)*4 +
  932. ((short)PPM_GETB(pixval))/64;
  933. /*fprintf(stderr, "grey= %d, grey/space=%d\n", g->GifCMap[index].grey, g->GifCMap[index].grey / spacing);*/
  934. switch (g->f_do_visual) {
  935. case DO_GREY:
  936. switch ( g->f_total_greys ) {
  937. case 2:
  938. /*cerr << "index=" << index << "\n"; */
  939. /*cerr << "GifCMap[index].grey" << GifCMap[index].grey << "\n"; */
  940. /*cerr << "GifCMap[index].grey/spacing" << GifCMap[index].grey / spacing << "\n"; */
  941. if ( dither_8X8[x%dither_matrix_sz][y%dither_matrix_sz] < g->GifCMap[index].grey / spacing ) {
  942. XPutPixel(g->f_ximage,x,y,g->f_white);
  943. } else {
  944. XPutPixel(g->f_ximage,x,y,g->f_black);
  945. }
  946. break;
  947. default:
  948. /*cerr << GifCMap[index].grey / spacing << " "; */
  949. XPutPixel(g->f_ximage,x,y, g->GifGMap[g->GifCMap[index].grey / spacing]);
  950. }
  951. break;
  952. case DO_COLOR:
  953. #ifdef FLOOD
  954. fprintf(stderr, "%03d %03d %03d -- %03d %03d %03d ",
  955. (short)PPM_GETR(pixval),(short)PPM_GETG(pixval),(short)PPM_GETB(pixval),
  956. g->GifCMap[index].red>>8, g->GifCMap[index].green>>8, g->GifCMap[index].blue>>8
  957. );
  958. if ((short)PPM_GETR(pixval) != (GifCMap[index].red>>8) ||
  959. (short)PPM_GETG(pixval) != (GifCMap[index].green>>8) ||
  960. (short)PPM_GETB(pixval) != (GifCMap[index].blue>>8))
  961. puts (" *");
  962. else
  963. puts (" -");
  964. #endif
  965. XPutPixel(g->f_ximage,x,y, g->GifCMap[index].pixel);
  966. /*
  967. switch ( g->f_visual_class ) {
  968. case StaticColor:
  969. case PseudoColor:
  970. XPutPixel(g->f_ximage,x,y, g->GifCMap[index].pixel);
  971. break;
  972. case TrueColor:
  973. case DirectColor:
  974. break;
  975. }
  976. */
  977. }
  978. ipp++;
  979. }
  980. for (x=width;x<ximWidth;x++)
  981. XPutPixel(g->f_ximage,x,y,bg); /* padding */
  982. }
  983. scaledWidth = width * ratio + 0.5;
  984. scaledHeight = height * ratio + 0.5;
  985. if (scaledWidth == 0)
  986. scaledWidth = 1;
  987. if (scaledHeight == 0)
  988. scaledHeight = 1;
  989. pm = XCreatePixmap(g->f_dpy,g->f_drawable,
  990. scaledWidth,scaledHeight,
  991. g->f_nplanes);
  992. if (!pm) {
  993. fprintf(stderr, "could not create pixmap\n");
  994. return None;
  995. }
  996. _XmPutScaledImage (g->f_dpy,pm,g->f_gc,g->f_ximage,
  997. 0,0,0,0,width,height,
  998. scaledWidth,scaledHeight);
  999. XDestroyImage(g->f_ximage);
  1000. g->f_ximage = NULL;
  1001. return(pm);
  1002. }
  1003. /* /////////////////////////////////////////////////////////////////
  1004. // Load pixmap from GIF data
  1005. // /////////////////////////////////////////////////////////////// */
  1006. Pixmap
  1007. gif_to_pixmap(GifObj *g, byte *inbuf, unsigned int buflen, Dimension *w, Dimension *h, Pixel fg, Pixel bg, float ratio)
  1008. {
  1009. Pixmap pixmap;
  1010. pixel **raw_image;
  1011. int width, height;
  1012. /* Create raw image from compress GIF data */
  1013. raw_image = create_raw_image (inbuf, buflen, &width, &height, 1);
  1014. if (!raw_image) return None;
  1015. /* Create X pixmap from raw image data */
  1016. pixmap = create_pixmap(g, raw_image, width, height, fg, bg, ratio);
  1017. /* Free raw image data */
  1018. free_raw_image(raw_image);
  1019. /* Set X pixmap dimensions */
  1020. *w = (Dimension) width * ratio + 0.5;
  1021. *h = (Dimension) height * ratio + 0.5;
  1022. if (*w == 0)
  1023. *w = 1;
  1024. if (*h == 0)
  1025. *h = 1;
  1026. /* Return X pixmap */
  1027. return pixmap;
  1028. }