togif.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817
  1. /**********************************************************************
  2. * togif -
  3. * Convert an IRIS image to GIF format. Converts b/w and
  4. * color images to 8 bit per pixel GIF format. Color images
  5. * are dithered with a 4 by 4 dither matrix. GIF image files
  6. * may be uuencoded, and sent over the network.
  7. *
  8. * Paul Haeberli @ Silicon Graphics - 1989
  9. *
  10. * * Modified Jan 1995 - Made parallelizable via elimination of
  11. * * global variables.
  12. **********************************************************************
  13. */
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <math.h>
  17. #include <stdlib.h>
  18. #include <grass/gis.h>
  19. #include "togif.h"
  20. #define GIFGAMMA (1.5) /* smaller makes output image darker */
  21. #define MAXCOLORS 256
  22. #define CBITS 12
  23. typedef int (*ifunptr) (int x, int y, vgl_GIFWriter * dataPtr);
  24. /***************************************************************************
  25. * These routines interface the non-GIF data to the GIF black box (GIFENCOD)
  26. ***************************************************************************
  27. */
  28. static int getgifpix2(int x, int y, vgl_GIFWriter * dataPtr);
  29. static void getrow2(unsigned long *buffer, short *row, unsigned short width,
  30. unsigned short rownum, unsigned short comp);
  31. static void gammawarp(short *sbuf, float gam, int n, vgl_GIFWriter * dataPtr);
  32. static short **makedittab(int levels, int mult, int add);
  33. static int ditherrow(unsigned short *r, unsigned short *g, unsigned short *b,
  34. short *wp, int n, int y, vgl_GIFWriter * dataPtr);
  35. /******************************************************************************
  36. * GIF black box routines
  37. ******************************************************************************
  38. */
  39. static void BumpPixel(vgl_GIFWriter * dataPtr);
  40. static int GIFNextPixel(ifunptr getpixel, vgl_GIFWriter * dataPtr);
  41. static int GIFEncode(FILE * fp, int GWidth, int GHeight, int GInterlace,
  42. int Background, int BitsPerPixel, int Red[], int Green[],
  43. int Blue[], ifunptr GetPixel, vgl_GIFWriter * dataPtr);
  44. static void Putword(int w, FILE * fp);
  45. /******************************************************************************
  46. * GIF compression black box routines
  47. ******************************************************************************
  48. */
  49. static void compress(int init_bits, FILE * outfile, ifunptr ReadValue,
  50. vgl_GIFWriter * dataPtr);
  51. static void output(code_int code, vgl_GIFWriter * dataPtr);
  52. static void cl_block(vgl_GIFWriter * dataPtr);
  53. static void cl_hash(register count_int hsize, vgl_GIFWriter * dataPtr);
  54. static void writeerr();
  55. static void flush_char(vgl_GIFWriter * dataPtr);
  56. static void char_out(int c, vgl_GIFWriter * dataPtr);
  57. static void char_init(vgl_GIFWriter * dataPtr);
  58. /************************ vgl_GIFWriterBegin() ******************************/
  59. vgl_GIFWriter *vgl_GIFWriterBegin(void)
  60. {
  61. vgl_GIFWriter *gifwriter;
  62. gifwriter = (vgl_GIFWriter *) G_malloc(sizeof(vgl_GIFWriter));
  63. return gifwriter;
  64. }
  65. /************************** vgl_GIFWriterEnd() ********************************/
  66. void vgl_GIFWriterEnd(vgl_GIFWriter * gifwriter)
  67. {
  68. G_free(gifwriter);
  69. }
  70. /********************** vgl_GIFWriterWriteGIFFile() ****************************/
  71. void vgl_GIFWriterWriteGIFFile(vgl_GIFWriter * gifwriter,
  72. unsigned long *buffer, int xsize, int ysize,
  73. int bwflag, FILE * outf)
  74. {
  75. short r, g, b;
  76. int i;
  77. int bpp;
  78. int gifcolors;
  79. int rmap[MAXCOLORS];
  80. int gmap[MAXCOLORS];
  81. int bmap[MAXCOLORS];
  82. memset(gifwriter, '\0', sizeof(vgl_GIFWriter));
  83. gifwriter->maxbits = CBITS; /* user settable max # bits/code */
  84. gifwriter->maxmaxcode = (code_int) 1 << CBITS; /* should NEVER generate this code */
  85. gifwriter->hsize = HSIZE;
  86. gifwriter->in_count = 1;
  87. gifwriter->xsize = xsize;
  88. gifwriter->ysize = ysize;
  89. gifwriter->iscolor = !bwflag;
  90. gifwriter->buffer = buffer;
  91. if (gifwriter->iscolor) {
  92. gifcolors = 256;
  93. bpp = 8;
  94. for (i = 0; i < gifcolors; i++) {
  95. r = (i >> 0) & 0x7;
  96. g = (i >> 3) & 0x7;
  97. b = (i >> 6) & 0x3;
  98. rmap[i] = (255 * r) / 7;
  99. gmap[i] = (255 * g) / 7;
  100. bmap[i] = (255 * b) / 3;
  101. }
  102. }
  103. else {
  104. gifcolors = 16;
  105. bpp = 4;
  106. for (i = 0; i < gifcolors; i++) {
  107. rmap[i] = (255 * i) / (gifcolors - 1);
  108. gmap[i] = (255 * i) / (gifcolors - 1);
  109. bmap[i] = (255 * i) / (gifcolors - 1);
  110. }
  111. }
  112. gifwriter->currow = -1;
  113. GIFEncode(outf, xsize, ysize, 1, 0, bpp, rmap, gmap, bmap, getgifpix2,
  114. gifwriter);
  115. }
  116. /************************** getgifpix2() ********************************/
  117. static int getgifpix2(int x, int y, vgl_GIFWriter * dataPtr)
  118. {
  119. int pix;
  120. if (dataPtr->iscolor) {
  121. if (dataPtr->currow != y) {
  122. getrow2(dataPtr->buffer, dataPtr->rbuf, dataPtr->xsize,
  123. dataPtr->ysize - 1 - y, 0);
  124. gammawarp(dataPtr->rbuf, 1.0 / GIFGAMMA, dataPtr->xsize, dataPtr);
  125. getrow2(dataPtr->buffer, dataPtr->gbuf, dataPtr->xsize,
  126. dataPtr->ysize - 1 - y, 1);
  127. gammawarp(dataPtr->gbuf, 1.0 / GIFGAMMA, dataPtr->xsize, dataPtr);
  128. getrow2(dataPtr->buffer, dataPtr->bbuf, dataPtr->xsize,
  129. dataPtr->ysize - 1 - y, 2);
  130. gammawarp(dataPtr->bbuf, 1.0 / GIFGAMMA, dataPtr->xsize, dataPtr);
  131. ditherrow((unsigned short *)(dataPtr->rbuf),
  132. (unsigned short *)(dataPtr->gbuf),
  133. (unsigned short *)(dataPtr->bbuf), dataPtr->obuf,
  134. dataPtr->xsize, y, dataPtr);
  135. dataPtr->currow = y;
  136. }
  137. pix = dataPtr->obuf[x];
  138. }
  139. else {
  140. if (dataPtr->currow != y) {
  141. getrow2(dataPtr->buffer, dataPtr->rbuf, dataPtr->xsize,
  142. dataPtr->ysize - 1 - y, 0);
  143. gammawarp(dataPtr->rbuf, 1.0 / GIFGAMMA, dataPtr->xsize, dataPtr);
  144. ditherrow((unsigned short *)(dataPtr->rbuf),
  145. (unsigned short *)(dataPtr->rbuf),
  146. (unsigned short *)(dataPtr->rbuf), dataPtr->obuf,
  147. dataPtr->xsize, y, dataPtr);
  148. dataPtr->currow = y;
  149. }
  150. pix = dataPtr->obuf[x] & 0xf;
  151. }
  152. return pix;
  153. }
  154. /************************** getrow2() ********************************/
  155. static void getrow2(unsigned long *buffer, short *row, unsigned short width,
  156. unsigned short rownum, unsigned short comp)
  157. {
  158. unsigned short i;
  159. unsigned long *ptr = buffer + width * rownum;
  160. switch (comp) {
  161. case 0:
  162. for (i = 0; i < width; i++) {
  163. row[i] = *ptr & 0xff;
  164. ptr++;
  165. }
  166. break;
  167. case 1:
  168. for (i = 0; i < width; i++) {
  169. row[i] = (*ptr >> 8) & 0xff;
  170. ptr++;
  171. }
  172. break;
  173. case 2:
  174. for (i = 0; i < width; i++) {
  175. row[i] = (*ptr >> 16) & 0xff;
  176. ptr++;
  177. }
  178. break;
  179. }
  180. }
  181. /********************** gammawarp() ***************************/
  182. static void gammawarp(short *sbuf, float gam, int n, vgl_GIFWriter * dataPtr)
  183. {
  184. int i;
  185. float f;
  186. if (gam != dataPtr->curgamma) {
  187. for (i = 0; i < 256; i++)
  188. dataPtr->gamtab[i] = 255 * pow(i / 255.0, gam) + 0.5;
  189. dataPtr->curgamma = gam;
  190. }
  191. while (n--) {
  192. *sbuf = dataPtr->gamtab[*sbuf];
  193. sbuf++;
  194. }
  195. }
  196. /***************************************************************************
  197. * dithering code follows
  198. */
  199. #define XSIZE 4
  200. #define YSIZE 4
  201. #define TOTAL (XSIZE*YSIZE)
  202. #define WRAPY(y) ((y)%YSIZE)
  203. #define WRAPX(x) ((x)%XSIZE)
  204. static short dithmat[YSIZE][XSIZE] = {
  205. 0, 8, 2, 10,
  206. 12, 4, 14, 6,
  207. 3, 11, 1, 9,
  208. 15, 7, 13, 5,
  209. };
  210. /************************** makedittab() ********************************/
  211. static short **makedittab(int levels, int mult, int add)
  212. {
  213. register int val;
  214. register int nshades;
  215. register int i, j, k;
  216. register int matval, tabval;
  217. short **tab;
  218. nshades = XSIZE * YSIZE * (levels - 1) + 1;
  219. tab = (short **)G_malloc(YSIZE * sizeof(short *));
  220. for (j = 0; j < YSIZE; j++) {
  221. tab[j] = (short *)G_malloc(XSIZE * 256 * sizeof(short));
  222. for (i = 0; i < XSIZE; i++) {
  223. matval = dithmat[i][j];
  224. for (k = 0; k < 256; k++) {
  225. val = (nshades * k) / 255;
  226. if (val == nshades)
  227. val = nshades - 1;
  228. if ((val % TOTAL) > matval)
  229. tabval = (val / TOTAL) + 1;
  230. else
  231. tabval = (val / TOTAL);
  232. tabval *= mult;
  233. tabval += add;
  234. tab[j][256 * i + k] = tabval;
  235. }
  236. }
  237. }
  238. return tab;
  239. }
  240. /************************** ditherrow() ********************************/
  241. static int ditherrow(unsigned short *r, unsigned short *g, unsigned short *b,
  242. short *wp, int n, int y, vgl_GIFWriter * dataPtr)
  243. {
  244. short *rbase;
  245. short *gbase;
  246. short *bbase;
  247. if (!dataPtr->rtab) {
  248. if (dataPtr->iscolor) {
  249. dataPtr->rtab = makedittab(8, 1, 0);
  250. dataPtr->gtab = makedittab(8, 8, 0);
  251. dataPtr->btab = makedittab(4, 64, 0);
  252. }
  253. else {
  254. dataPtr->rtab = makedittab(16, 1, 0);
  255. dataPtr->gtab = makedittab(2, 16, 0);
  256. dataPtr->btab = makedittab(2, 32, 0);
  257. }
  258. }
  259. rbase = dataPtr->rtab[WRAPY(y)];
  260. gbase = dataPtr->gtab[WRAPY(y)];
  261. bbase = dataPtr->btab[WRAPY(y)];
  262. while (n) {
  263. if (n >= XSIZE) {
  264. *wp++ = rbase[*r++ + 0] + gbase[*g++ + 0] + bbase[*b++ + 0];
  265. *wp++ = rbase[*r++ + 256] + gbase[*g++ + 256] + bbase[*b++ + 256];
  266. *wp++ = rbase[*r++ + 512] + gbase[*g++ + 512] + bbase[*b++ + 512];
  267. *wp++ = rbase[*r++ + 768] + gbase[*g++ + 768] + bbase[*b++ + 768];
  268. n -= XSIZE;
  269. }
  270. else {
  271. *wp++ = rbase[*r++] + gbase[*g++] + bbase[*b++];
  272. rbase += 256;
  273. gbase += 256;
  274. bbase += 256;
  275. n--;
  276. }
  277. }
  278. return 1;
  279. }
  280. /*****************************************************************************
  281. * SCARY GIF code follows . . . . sorry.
  282. *
  283. * Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>.A
  284. * Lempel-Zim compression based on "compress".
  285. *
  286. *****************************************************************************
  287. */
  288. /*****************************************************************************
  289. *
  290. * GIFENCODE.C - GIF Image compression interface
  291. *
  292. * GIFEncode( FName, GHeight, GWidth, GInterlace, Background,
  293. * BitsPerPixel, Red, Green, Blue, GetPixel )
  294. *
  295. *****************************************************************************/
  296. #define TRUE 1
  297. #define FALSE 0
  298. /************************** BumpPixel() ********************************/
  299. /*
  300. * Bump the 'curx' and 'cury' to point to the next pixel
  301. */
  302. static void BumpPixel(vgl_GIFWriter * dataPtr)
  303. {
  304. dataPtr->curx++;
  305. if (dataPtr->curx == dataPtr->xsize) {
  306. dataPtr->curx = 0;
  307. if (!dataPtr->interlace) {
  308. dataPtr->cury++;
  309. }
  310. else {
  311. switch (dataPtr->pass) {
  312. case 0:
  313. dataPtr->cury += 8;
  314. if (dataPtr->cury >= dataPtr->ysize) {
  315. dataPtr->pass++;
  316. dataPtr->cury = 4;
  317. }
  318. break;
  319. case 1:
  320. dataPtr->cury += 8;
  321. if (dataPtr->cury >= dataPtr->ysize) {
  322. dataPtr->pass++;
  323. dataPtr->cury = 2;
  324. }
  325. break;
  326. case 2:
  327. dataPtr->cury += 4;
  328. if (dataPtr->cury >= dataPtr->ysize) {
  329. dataPtr->pass++;
  330. dataPtr->cury = 1;
  331. }
  332. break;
  333. case 3:
  334. dataPtr->cury += 2;
  335. break;
  336. }
  337. }
  338. }
  339. }
  340. /************************** GIFNextPixel() ********************************/
  341. /*
  342. * Return the next pixel from the image
  343. */
  344. static int GIFNextPixel(ifunptr getpixel, vgl_GIFWriter * dataPtr)
  345. {
  346. int r;
  347. if (dataPtr->countDown == 0)
  348. return EOF;
  349. dataPtr->countDown--;
  350. r = (*getpixel) (dataPtr->curx, dataPtr->cury, dataPtr);
  351. BumpPixel(dataPtr);
  352. return r;
  353. }
  354. /************************** GIFEncode () ********************************/
  355. /*
  356. * public GIFEncode
  357. */
  358. static int GIFEncode(FILE * fp, int GWidth, int GHeight, int GInterlace,
  359. int Background, int BitsPerPixel, int Red[], int Green[],
  360. int Blue[], ifunptr GetPixel, vgl_GIFWriter * dataPtr)
  361. {
  362. int B;
  363. int RWidth, RHeight;
  364. int LeftOfs, TopOfs;
  365. int Resolution;
  366. int ColorMapSize;
  367. int InitCodeSize;
  368. int i;
  369. dataPtr->cur_bits = 0;
  370. dataPtr->interlace = GInterlace;
  371. ColorMapSize = 1 << BitsPerPixel;
  372. RWidth = dataPtr->xsize;
  373. RHeight = dataPtr->ysize;
  374. LeftOfs = TopOfs = 0;
  375. Resolution = BitsPerPixel;
  376. dataPtr->countDown = (long)(dataPtr->xsize) * (long)(dataPtr->ysize);
  377. dataPtr->pass = 0;
  378. if (BitsPerPixel <= 1)
  379. InitCodeSize = 2;
  380. else
  381. InitCodeSize = BitsPerPixel;
  382. dataPtr->curx = dataPtr->cury = 0;
  383. fwrite("GIF87a", 1, 6, fp);
  384. Putword(RWidth, fp);
  385. Putword(RHeight, fp);
  386. B = 0x80; /* Yes, there is a color map */
  387. B |= (Resolution - 1) << 5;
  388. B |= (BitsPerPixel - 1);
  389. fputc(B, fp);
  390. fputc(Background, fp);
  391. fputc(0, fp);
  392. for (i = 0; i < ColorMapSize; i++) {
  393. fputc(Red[i], fp);
  394. fputc(Green[i], fp);
  395. fputc(Blue[i], fp);
  396. }
  397. fputc(',', fp);
  398. Putword(LeftOfs, fp);
  399. Putword(TopOfs, fp);
  400. Putword(dataPtr->xsize, fp);
  401. Putword(dataPtr->ysize, fp);
  402. if (dataPtr->interlace)
  403. fputc(0x40, fp);
  404. else
  405. fputc(0x00, fp);
  406. fputc(InitCodeSize, fp);
  407. compress(InitCodeSize + 1, fp, GetPixel, dataPtr);
  408. fputc(0, fp);
  409. fputc(';', fp);
  410. fclose(fp);
  411. return 1;
  412. }
  413. /************************** Putword () ********************************/
  414. /*
  415. * Write out a word to the GIF file
  416. */
  417. static void Putword(int w, FILE * fp)
  418. {
  419. fputc(w & 0xff, fp);
  420. fputc((w / 256) & 0xff, fp);
  421. }
  422. /***************************************************************************
  423. *
  424. * GIFCOMPR.C - GIF Image compression routines
  425. *
  426. * Lempel-Ziv compression based on 'compress'. GIF modifications by
  427. * David Rowley (mgardi@watdcsu.waterloo.edu)
  428. *
  429. ***************************************************************************/
  430. /*
  431. *
  432. * GIF Image compression - modified 'compress'
  433. *
  434. * Based on: compress.c - File compression ala IEEE Computer, June 1984.
  435. *
  436. * By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
  437. * Jim McKie (decvax!mcvax!jim)
  438. * Steve Davies (decvax!vax135!petsd!peora!srd)
  439. * Ken Turkowski (decvax!decwrl!turtlevax!ken)
  440. * James A. Woods (decvax!ihnp4!ames!jaw)
  441. * Joe Orost (decvax!vax135!petsd!joe)
  442. *
  443. */
  444. #include <ctype.h>
  445. #include <grass/gis.h>
  446. #define ARGVAL() (*++(*argv) || (--argc && *++argv))
  447. # define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1)
  448. #define HashTabOf(i) dataPtr->htab[i]
  449. #define CodeTabOf(i) dataPtr->codetab[i]
  450. /*
  451. * To save much memory, we overlay the table used by compress() with those
  452. * used by decompress(). The tab_prefix table is the same size and type
  453. * as the codetab. The tab_suffix table needs 2**CBITS characters. We
  454. * get this from the beginning of htab. The output stack uses the rest
  455. * of htab, and contains characters. There is plenty of room for any
  456. * possible stack (stack used to be 8000 characters).
  457. */
  458. #define tab_prefixof(i) CodeTabOf(i)
  459. #define tab_suffixof(i) ((char_type *)(dataPtr->htab))[i]
  460. #define de_stack ((char_type *)&tab_suffixof((code_int)1<<CBITS))
  461. /************************** compress () ********************************
  462. * compress stdin to stdout
  463. *
  464. * Algorithm: use open addressing double hashing (no chaining) on the
  465. * prefix code / next character combination. We do a variant of Knuth's
  466. * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
  467. * secondary probe. Here, the modular division first probe is gives way
  468. * to a faster exclusive-or manipulation. Also do block compression with
  469. * an adaptive reset, whereby the code table is cleared when the compression
  470. * ratio decreases, but after the table fills. The variable-length output
  471. * codes are re-sized at this point, and a special CLEAR code is generated
  472. * for the decompressor. Late addition: construct the table according to
  473. * file size for noticeable speed improvement on small files. Please direct
  474. * questions about this implementation to ames!jaw.
  475. */
  476. static void compress(int init_bits, FILE * outfile, ifunptr ReadValue,
  477. vgl_GIFWriter * dataPtr)
  478. {
  479. register long fcode;
  480. register code_int i = 0;
  481. register int c;
  482. register code_int ent;
  483. register code_int disp;
  484. register code_int hsize_reg;
  485. register int hshift;
  486. /*
  487. * Set up the globals: g_init_bits - initial number of bits
  488. * g_outfile - pointer to output file
  489. */
  490. dataPtr->g_init_bits = init_bits;
  491. dataPtr->g_outfile = outfile;
  492. /*
  493. * Set up the necessary values
  494. */
  495. dataPtr->offset = 0;
  496. dataPtr->out_count = 0;
  497. dataPtr->clear_flg = 0;
  498. dataPtr->in_count = 1;
  499. dataPtr->maxcode = MAXCODE(dataPtr->n_bits = dataPtr->g_init_bits);
  500. dataPtr->clearCode = (1 << (init_bits - 1));
  501. dataPtr->EOFCode = dataPtr->clearCode + 1;
  502. dataPtr->free_ent = dataPtr->clearCode + 2;
  503. char_init(dataPtr);
  504. ent = GIFNextPixel(ReadValue, dataPtr);
  505. hshift = 0;
  506. for (fcode = (long)(dataPtr->hsize); fcode < 65536L; fcode *= 2L)
  507. hshift++;
  508. hshift = 8 - hshift; /* set hash code range bound */
  509. hsize_reg = dataPtr->hsize;
  510. cl_hash((count_int) hsize_reg, dataPtr); /* clear hash table */
  511. output((code_int) (dataPtr->clearCode), dataPtr);
  512. while ((c = GIFNextPixel(ReadValue, dataPtr)) != EOF) {
  513. dataPtr->in_count++;
  514. fcode = (long)(((long)c << dataPtr->maxbits) + ent);
  515. /* i = (((code_int)c << hshift) ~ ent); */
  516. i = (((code_int) c << hshift) ^ ent); /* xor hashing */
  517. if (HashTabOf(i) == fcode) {
  518. ent = CodeTabOf(i);
  519. continue;
  520. }
  521. else if ((long)HashTabOf(i) < 0) /* empty slot */
  522. goto nomatch;
  523. disp = hsize_reg - i; /* secondary hash (after G. Knott) */
  524. if (i == 0)
  525. disp = 1;
  526. probe:
  527. if ((i -= disp) < 0)
  528. i += hsize_reg;
  529. if (HashTabOf(i) == fcode) {
  530. ent = CodeTabOf(i);
  531. continue;
  532. }
  533. if ((long)HashTabOf(i) > 0)
  534. goto probe;
  535. nomatch:
  536. output((code_int) ent, dataPtr);
  537. dataPtr->out_count++;
  538. ent = c;
  539. if (dataPtr->free_ent < dataPtr->maxmaxcode) {
  540. CodeTabOf(i) = dataPtr->free_ent++; /* code -> hashtable */
  541. HashTabOf(i) = fcode;
  542. }
  543. else
  544. cl_block(dataPtr);
  545. }
  546. /*
  547. * Put out the final code.
  548. */
  549. output((code_int) ent, dataPtr);
  550. dataPtr->out_count++;
  551. output((code_int) (dataPtr->EOFCode), dataPtr);
  552. return;
  553. }
  554. /*****************************************************************
  555. * TAG( output )
  556. *
  557. * Output the given code.
  558. * Inputs:
  559. * code: A n_bits-bit integer. If == -1, then EOF. This assumes
  560. * that n_bits =< (long)wordsize - 1.
  561. * Outputs:
  562. * Outputs code to the file.
  563. * Assumptions:
  564. * Chars are 8 bits long.
  565. * Algorithm:
  566. * Maintain a CBITS character long buffer (so that 8 codes will
  567. * fit in it exactly). Use the VAX insv instruction to insert each
  568. * code in turn. When the buffer fills up empty it and start over.
  569. */
  570. static unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
  571. 0x001F, 0x003F, 0x007F, 0x00FF,
  572. 0x01FF, 0x03FF, 0x07FF, 0x0FFF,
  573. 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF
  574. };
  575. static void output(code_int code, vgl_GIFWriter * dataPtr)
  576. {
  577. dataPtr->cur_accum &= masks[dataPtr->cur_bits];
  578. if (dataPtr->cur_bits > 0)
  579. dataPtr->cur_accum |= ((long)code << dataPtr->cur_bits);
  580. else
  581. dataPtr->cur_accum = code;
  582. dataPtr->cur_bits += dataPtr->n_bits;
  583. while (dataPtr->cur_bits >= 8) {
  584. char_out((unsigned int)(dataPtr->cur_accum & 0xff), dataPtr);
  585. dataPtr->cur_accum >>= 8;
  586. dataPtr->cur_bits -= 8;
  587. }
  588. /*
  589. * If the next entry is going to be too big for the code size,
  590. * then increase it, if possible.
  591. */
  592. if (dataPtr->free_ent > dataPtr->maxcode || dataPtr->clear_flg) {
  593. if (dataPtr->clear_flg) {
  594. dataPtr->maxcode = MAXCODE(dataPtr->n_bits =
  595. dataPtr->g_init_bits);
  596. dataPtr->clear_flg = 0;
  597. }
  598. else {
  599. dataPtr->n_bits++;
  600. if (dataPtr->n_bits == dataPtr->maxbits)
  601. dataPtr->maxcode = dataPtr->maxmaxcode;
  602. else
  603. dataPtr->maxcode = MAXCODE(dataPtr->n_bits);
  604. }
  605. }
  606. if (code == dataPtr->EOFCode) {
  607. /*
  608. * At EOF, write the rest of the buffer.
  609. */
  610. while (dataPtr->cur_bits > 0) {
  611. char_out((unsigned int)(dataPtr->cur_accum & 0xff), dataPtr);
  612. dataPtr->cur_accum >>= 8;
  613. dataPtr->cur_bits -= 8;
  614. }
  615. flush_char(dataPtr);
  616. fflush(dataPtr->g_outfile);
  617. if (ferror(dataPtr->g_outfile))
  618. writeerr();
  619. }
  620. }
  621. /********************** cl_block() ***************************/
  622. /*
  623. * table clear for block compress
  624. */
  625. static void cl_block(vgl_GIFWriter * dataPtr)
  626. {
  627. cl_hash((count_int) (dataPtr->hsize), dataPtr);
  628. dataPtr->free_ent = dataPtr->clearCode + 2;
  629. dataPtr->clear_flg = 1;
  630. output((code_int) (dataPtr->clearCode), dataPtr);
  631. }
  632. /********************** cl_hash() ***************************/
  633. /* reset code table */
  634. static void cl_hash(register count_int hsize, vgl_GIFWriter * dataPtr)
  635. {
  636. register count_int *htab_p;
  637. register long i;
  638. register long m1 = -1;
  639. htab_p = dataPtr->htab + hsize;
  640. i = hsize - 16;
  641. do { /* might use Sys V memset(3) here */
  642. *(htab_p - 16) = m1;
  643. *(htab_p - 15) = m1;
  644. *(htab_p - 14) = m1;
  645. *(htab_p - 13) = m1;
  646. *(htab_p - 12) = m1;
  647. *(htab_p - 11) = m1;
  648. *(htab_p - 10) = m1;
  649. *(htab_p - 9) = m1;
  650. *(htab_p - 8) = m1;
  651. *(htab_p - 7) = m1;
  652. *(htab_p - 6) = m1;
  653. *(htab_p - 5) = m1;
  654. *(htab_p - 4) = m1;
  655. *(htab_p - 3) = m1;
  656. *(htab_p - 2) = m1;
  657. *(htab_p - 1) = m1;
  658. htab_p -= 16;
  659. } while ((i -= 16) >= 0);
  660. for (i += 16; i > 0; i--)
  661. *--htab_p = m1;
  662. }
  663. /********************** writeerr() ***************************/
  664. static void writeerr()
  665. {
  666. }
  667. /******************************************************************************
  668. *
  669. * GIF Specific routines used by compression stuff
  670. *
  671. ******************************************************************************/
  672. /********************** char_init() ***************************/
  673. /*
  674. * Set up the 'byte output' routine
  675. */
  676. static void char_init(vgl_GIFWriter * dataPtr)
  677. {
  678. dataPtr->a_count = 0;
  679. }
  680. /*
  681. * Define the storage for the packet accumulator
  682. */
  683. /********************** char_out() ***************************/
  684. /*
  685. * Add a character to the end of the current packet, and if it is 254
  686. * characters, flush the packet to disk.
  687. */
  688. static void char_out(int c, vgl_GIFWriter * dataPtr)
  689. {
  690. dataPtr->accum[dataPtr->a_count++] = c;
  691. if (dataPtr->a_count >= 254)
  692. flush_char(dataPtr);
  693. }
  694. /********************** flush_char() ***************************/
  695. /*
  696. * Flush the packet to disk, and reset the accumulator
  697. */
  698. static void flush_char(vgl_GIFWriter * dataPtr)
  699. {
  700. if (dataPtr->a_count > 0) {
  701. fputc(dataPtr->a_count, dataPtr->g_outfile);
  702. fwrite(dataPtr->accum, 1, dataPtr->a_count, dataPtr->g_outfile);
  703. dataPtr->a_count = 0;
  704. }
  705. }
  706. /*
  707. main(int argc,char *argv[] )
  708. {
  709. FILE *of;
  710. int xsize, ysize,bwflag;
  711. unsigned long *buffer;
  712. int i;
  713. int j;
  714. vgl_GIFWriter *gifwriter;
  715. if(argc<3) {
  716. fprintf(stderr,"usage: togif image.rgb image.gif\n");
  717. exit(1);
  718. }
  719. gifwriter = vgl_GIFWriterBegin();
  720. xsize = ysize = 200;
  721. buffer = (unsigned long *)G_malloc ((xsize)*(ysize) * sizeof(unsigned long));
  722. for(i = 0; i < ysize; i++)
  723. {
  724. for(j = 0; j < xsize; j++)
  725. {
  726. buffer[j + i * xsize] =
  727. i | j << 8 | (0xff<<24);
  728. }
  729. }
  730. bwflag = 0;
  731. of = fopen(argv[2],"w");
  732. if(!of) {
  733. fprintf(stderr,"togif: can't open output image [%s]\n",argv[2]);
  734. exit(1);
  735. }
  736. vgl_GIFWriterWriteGIFFile(gifwriter,buffer,xsize,ysize,bwflag,of);
  737. vgl_GIFWriterEnd(gifwriter);
  738. fclose(of);
  739. exit(0);
  740. }
  741. */