gd_gif_in.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. #include <stdio.h>
  2. #include <math.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. #include "gd.h"
  6. #include "php.h"
  7. /* Used only when debugging GIF compression code */
  8. /* #define DEBUGGING_ENVARS */
  9. #ifdef DEBUGGING_ENVARS
  10. static int verbose_set = 0;
  11. static int verbose;
  12. #define VERBOSE (verbose_set?verbose:set_verbose())
  13. static int set_verbose(void)
  14. {
  15. verbose = !!getenv("GIF_VERBOSE");
  16. verbose_set = 1;
  17. return(verbose);
  18. }
  19. #else
  20. #define VERBOSE 0
  21. #endif
  22. #define MAXCOLORMAPSIZE 256
  23. #define TRUE 1
  24. #define FALSE 0
  25. #define CM_RED 0
  26. #define CM_GREEN 1
  27. #define CM_BLUE 2
  28. #define MAX_LWZ_BITS 12
  29. #define INTERLACE 0x40
  30. #define LOCALCOLORMAP 0x80
  31. #define BitSet(byte, bit) (((byte) & (bit)) == (bit))
  32. #define ReadOK(file,buffer,len) (gdGetBuf(buffer, len, file) > 0)
  33. #define LM_to_uint(a,b) (((b)<<8)|(a))
  34. /* We may eventually want to use this information, but def it out for now */
  35. #if 0
  36. static struct {
  37. unsigned int Width;
  38. unsigned int Height;
  39. unsigned char ColorMap[3][MAXCOLORMAPSIZE];
  40. unsigned int BitPixel;
  41. unsigned int ColorResolution;
  42. unsigned int Background;
  43. unsigned int AspectRatio;
  44. } GifScreen;
  45. #endif
  46. #if 0
  47. static struct {
  48. int transparent;
  49. int delayTime;
  50. int inputFlag;
  51. int disposal;
  52. } Gif89 = { -1, -1, -1, 0 };
  53. #endif
  54. #define STACK_SIZE ((1<<(MAX_LWZ_BITS))*2)
  55. #define CSD_BUF_SIZE 280
  56. typedef struct {
  57. unsigned char buf[CSD_BUF_SIZE];
  58. int curbit, lastbit, done, last_byte;
  59. } CODE_STATIC_DATA;
  60. typedef struct {
  61. int fresh;
  62. int code_size, set_code_size;
  63. int max_code, max_code_size;
  64. int firstcode, oldcode;
  65. int clear_code, end_code;
  66. int table[2][(1<< MAX_LWZ_BITS)];
  67. int stack[STACK_SIZE], *sp;
  68. CODE_STATIC_DATA scd;
  69. } LZW_STATIC_DATA;
  70. static int ReadColorMap (gdIOCtx *fd, int number, unsigned char (*buffer)[256]);
  71. static int DoExtension (gdIOCtx *fd, int label, int *Transparent, int *ZeroDataBlockP);
  72. static int GetDataBlock (gdIOCtx *fd, unsigned char *buf, int *ZeroDataBlockP);
  73. static int GetCode (gdIOCtx *fd, CODE_STATIC_DATA *scd, int code_size, int flag, int *ZeroDataBlockP);
  74. static int LWZReadByte (gdIOCtx *fd, LZW_STATIC_DATA *sd, char flag, int input_code_size, int *ZeroDataBlockP);
  75. static void ReadImage (gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap)[256], int interlace, int *ZeroDataBlockP); /*1.4//, int ignore); */
  76. gdImagePtr gdImageCreateFromGifSource(gdSourcePtr inSource) /* {{{ */
  77. {
  78. gdIOCtx *in = gdNewSSCtx(inSource, NULL);
  79. gdImagePtr im;
  80. im = gdImageCreateFromGifCtx(in);
  81. in->gd_free(in);
  82. return im;
  83. }
  84. /* }}} */
  85. gdImagePtr gdImageCreateFromGif(FILE *fdFile) /* {{{ */
  86. {
  87. gdIOCtx *fd = gdNewFileCtx(fdFile);
  88. gdImagePtr im = 0;
  89. im = gdImageCreateFromGifCtx(fd);
  90. fd->gd_free(fd);
  91. return im;
  92. }
  93. /* }}} */
  94. gdImagePtr gdImageCreateFromGifCtx(gdIOCtxPtr fd) /* {{{ */
  95. {
  96. int BitPixel;
  97. #if 0
  98. int ColorResolution;
  99. int Background;
  100. int AspectRatio;
  101. #endif
  102. int Transparent = (-1);
  103. unsigned char buf[16];
  104. unsigned char c;
  105. unsigned char ColorMap[3][MAXCOLORMAPSIZE];
  106. unsigned char localColorMap[3][MAXCOLORMAPSIZE];
  107. int imw, imh, screen_width, screen_height;
  108. int gif87a, useGlobalColormap;
  109. int bitPixel;
  110. int i;
  111. /*1.4//int imageCount = 0; */
  112. int ZeroDataBlock = FALSE;
  113. int haveGlobalColormap;
  114. gdImagePtr im = 0;
  115. memset(ColorMap, 0, 3 * MAXCOLORMAPSIZE);
  116. memset(localColorMap, 0, 3 * MAXCOLORMAPSIZE);
  117. /*1.4//imageNumber = 1; */
  118. if (! ReadOK(fd,buf,6)) {
  119. return 0;
  120. }
  121. if (strncmp((char *)buf,"GIF",3) != 0) {
  122. return 0;
  123. }
  124. if (memcmp((char *)buf+3, "87a", 3) == 0) {
  125. gif87a = 1;
  126. } else if (memcmp((char *)buf+3, "89a", 3) == 0) {
  127. gif87a = 0;
  128. } else {
  129. return 0;
  130. }
  131. if (! ReadOK(fd,buf,7)) {
  132. return 0;
  133. }
  134. BitPixel = 2<<(buf[4]&0x07);
  135. #if 0
  136. ColorResolution = (int) (((buf[4]&0x70)>>3)+1);
  137. Background = buf[5];
  138. AspectRatio = buf[6];
  139. #endif
  140. screen_width = imw = LM_to_uint(buf[0],buf[1]);
  141. screen_height = imh = LM_to_uint(buf[2],buf[3]);
  142. haveGlobalColormap = BitSet(buf[4], LOCALCOLORMAP); /* Global Colormap */
  143. if (haveGlobalColormap) {
  144. if (ReadColorMap(fd, BitPixel, ColorMap)) {
  145. return 0;
  146. }
  147. }
  148. for (;;) {
  149. int top, left;
  150. int width, height;
  151. if (! ReadOK(fd,&c,1)) {
  152. return 0;
  153. }
  154. if (c == ';') { /* GIF terminator */
  155. goto terminated;
  156. }
  157. if (c == '!') { /* Extension */
  158. if (! ReadOK(fd,&c,1)) {
  159. return 0;
  160. }
  161. DoExtension(fd, c, &Transparent, &ZeroDataBlock);
  162. continue;
  163. }
  164. if (c != ',') { /* Not a valid start character */
  165. continue;
  166. }
  167. /*1.4//++imageCount; */
  168. if (! ReadOK(fd,buf,9)) {
  169. return 0;
  170. }
  171. useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP);
  172. bitPixel = 1<<((buf[8]&0x07)+1);
  173. left = LM_to_uint(buf[0], buf[1]);
  174. top = LM_to_uint(buf[2], buf[3]);
  175. width = LM_to_uint(buf[4], buf[5]);
  176. height = LM_to_uint(buf[6], buf[7]);
  177. if (left + width > screen_width || top + height > screen_height) {
  178. if (VERBOSE) {
  179. printf("Frame is not confined to screen dimension.\n");
  180. }
  181. return 0;
  182. }
  183. if (!(im = gdImageCreate(width, height))) {
  184. return 0;
  185. }
  186. im->interlace = BitSet(buf[8], INTERLACE);
  187. if (!useGlobalColormap) {
  188. if (ReadColorMap(fd, bitPixel, localColorMap)) {
  189. gdImageDestroy(im);
  190. return 0;
  191. }
  192. ReadImage(im, fd, width, height, localColorMap,
  193. BitSet(buf[8], INTERLACE), &ZeroDataBlock);
  194. } else {
  195. if (!haveGlobalColormap) {
  196. gdImageDestroy(im);
  197. return 0;
  198. }
  199. ReadImage(im, fd, width, height,
  200. ColorMap,
  201. BitSet(buf[8], INTERLACE), &ZeroDataBlock);
  202. }
  203. if (Transparent != (-1)) {
  204. gdImageColorTransparent(im, Transparent);
  205. }
  206. goto terminated;
  207. }
  208. terminated:
  209. /* Terminator before any image was declared! */
  210. if (!im) {
  211. return 0;
  212. }
  213. /* Check for open colors at the end, so
  214. we can reduce colorsTotal and ultimately
  215. BitsPerPixel */
  216. for (i=((im->colorsTotal-1)); (i>=0); i--) {
  217. if (im->open[i]) {
  218. im->colorsTotal--;
  219. } else {
  220. break;
  221. }
  222. }
  223. if (!im->colorsTotal) {
  224. gdImageDestroy(im);
  225. return 0;
  226. }
  227. return im;
  228. }
  229. /* }}} */
  230. static int ReadColorMap(gdIOCtx *fd, int number, unsigned char (*buffer)[256]) /* {{{ */
  231. {
  232. int i;
  233. unsigned char rgb[3];
  234. for (i = 0; i < number; ++i) {
  235. if (! ReadOK(fd, rgb, sizeof(rgb))) {
  236. return TRUE;
  237. }
  238. buffer[CM_RED][i] = rgb[0] ;
  239. buffer[CM_GREEN][i] = rgb[1] ;
  240. buffer[CM_BLUE][i] = rgb[2] ;
  241. }
  242. return FALSE;
  243. }
  244. /* }}} */
  245. static int
  246. DoExtension(gdIOCtx *fd, int label, int *Transparent, int *ZeroDataBlockP)
  247. {
  248. unsigned char buf[256];
  249. switch (label) {
  250. case 0xf9: /* Graphic Control Extension */
  251. memset(buf, 0, 4); /* initialize a few bytes in the case the next function fails */
  252. (void) GetDataBlock(fd, (unsigned char*) buf, ZeroDataBlockP);
  253. #if 0
  254. Gif89.disposal = (buf[0] >> 2) & 0x7;
  255. Gif89.inputFlag = (buf[0] >> 1) & 0x1;
  256. Gif89.delayTime = LM_to_uint(buf[1],buf[2]);
  257. #endif
  258. if ((buf[0] & 0x1) != 0)
  259. *Transparent = buf[3];
  260. while (GetDataBlock(fd, (unsigned char*) buf, ZeroDataBlockP) > 0);
  261. return FALSE;
  262. default:
  263. break;
  264. }
  265. while (GetDataBlock(fd, (unsigned char*) buf, ZeroDataBlockP) > 0)
  266. ;
  267. return FALSE;
  268. }
  269. /* }}} */
  270. static int
  271. GetDataBlock_(gdIOCtx *fd, unsigned char *buf, int *ZeroDataBlockP)
  272. {
  273. unsigned char count;
  274. if (! ReadOK(fd,&count,1)) {
  275. return -1;
  276. }
  277. *ZeroDataBlockP = count == 0;
  278. if ((count != 0) && (! ReadOK(fd, buf, count))) {
  279. return -1;
  280. }
  281. return count;
  282. }
  283. /* }}} */
  284. static int
  285. GetDataBlock(gdIOCtx *fd, unsigned char *buf, int *ZeroDataBlockP)
  286. {
  287. int rv;
  288. int i;
  289. rv = GetDataBlock_(fd,buf, ZeroDataBlockP);
  290. if (VERBOSE) {
  291. char *tmp = NULL;
  292. if (rv > 0) {
  293. tmp = safe_emalloc(3 * rv, sizeof(char), 1);
  294. for (i=0;i<rv;i++) {
  295. sprintf(&tmp[3*sizeof(char)*i], " %02x", buf[i]);
  296. }
  297. } else {
  298. tmp = estrdup("");
  299. }
  300. php_gd_error_ex(E_NOTICE, "[GetDataBlock returning %d: %s]", rv, tmp);
  301. efree(tmp);
  302. }
  303. return(rv);
  304. }
  305. /* }}} */
  306. static int
  307. GetCode_(gdIOCtx *fd, CODE_STATIC_DATA *scd, int code_size, int flag, int *ZeroDataBlockP)
  308. {
  309. int i, j, ret;
  310. int count;
  311. if (flag) {
  312. scd->curbit = 0;
  313. scd->lastbit = 0;
  314. scd->last_byte = 0;
  315. scd->done = FALSE;
  316. return 0;
  317. }
  318. if ( (scd->curbit + code_size) >= scd->lastbit) {
  319. if (scd->done) {
  320. if (scd->curbit >= scd->lastbit) {
  321. /* Oh well */
  322. }
  323. return -1;
  324. }
  325. scd->buf[0] = scd->buf[scd->last_byte-2];
  326. scd->buf[1] = scd->buf[scd->last_byte-1];
  327. if ((count = GetDataBlock(fd, &scd->buf[2], ZeroDataBlockP)) <= 0)
  328. scd->done = TRUE;
  329. scd->last_byte = 2 + count;
  330. scd->curbit = (scd->curbit - scd->lastbit) + 16;
  331. scd->lastbit = (2+count)*8 ;
  332. }
  333. if ((scd->curbit + code_size - 1) >= (CSD_BUF_SIZE * 8)) {
  334. ret = -1;
  335. } else {
  336. ret = 0;
  337. for (i = scd->curbit, j = 0; j < code_size; ++i, ++j) {
  338. ret |= ((scd->buf[i / 8] & (1 << (i % 8))) != 0) << j;
  339. }
  340. }
  341. scd->curbit += code_size;
  342. return ret;
  343. }
  344. static int
  345. GetCode(gdIOCtx *fd, CODE_STATIC_DATA *scd, int code_size, int flag, int *ZeroDataBlockP)
  346. {
  347. int rv;
  348. rv = GetCode_(fd, scd, code_size,flag, ZeroDataBlockP);
  349. if (VERBOSE) printf("[GetCode(,%d,%d) returning %d]\n",code_size,flag,rv);
  350. return(rv);
  351. }
  352. /* }}} */
  353. static int
  354. LWZReadByte_(gdIOCtx *fd, LZW_STATIC_DATA *sd, char flag, int input_code_size, int *ZeroDataBlockP)
  355. {
  356. int code, incode, i;
  357. if (flag) {
  358. sd->set_code_size = input_code_size;
  359. sd->code_size = sd->set_code_size+1;
  360. sd->clear_code = 1 << sd->set_code_size ;
  361. sd->end_code = sd->clear_code + 1;
  362. sd->max_code_size = 2*sd->clear_code;
  363. sd->max_code = sd->clear_code+2;
  364. GetCode(fd, &sd->scd, 0, TRUE, ZeroDataBlockP);
  365. sd->fresh = TRUE;
  366. for (i = 0; i < sd->clear_code; ++i) {
  367. sd->table[0][i] = 0;
  368. sd->table[1][i] = i;
  369. }
  370. for (; i < (1<<MAX_LWZ_BITS); ++i)
  371. sd->table[0][i] = sd->table[1][0] = 0;
  372. sd->sp = sd->stack;
  373. return 0;
  374. } else if (sd->fresh) {
  375. sd->fresh = FALSE;
  376. do {
  377. sd->firstcode = sd->oldcode =
  378. GetCode(fd, &sd->scd, sd->code_size, FALSE, ZeroDataBlockP);
  379. } while (sd->firstcode == sd->clear_code);
  380. return sd->firstcode;
  381. }
  382. if (sd->sp > sd->stack)
  383. return *--sd->sp;
  384. while ((code = GetCode(fd, &sd->scd, sd->code_size, FALSE, ZeroDataBlockP)) >= 0) {
  385. if (code == sd->clear_code) {
  386. for (i = 0; i < sd->clear_code; ++i) {
  387. sd->table[0][i] = 0;
  388. sd->table[1][i] = i;
  389. }
  390. for (; i < (1<<MAX_LWZ_BITS); ++i)
  391. sd->table[0][i] = sd->table[1][i] = 0;
  392. sd->code_size = sd->set_code_size+1;
  393. sd->max_code_size = 2*sd->clear_code;
  394. sd->max_code = sd->clear_code+2;
  395. sd->sp = sd->stack;
  396. sd->firstcode = sd->oldcode =
  397. GetCode(fd, &sd->scd, sd->code_size, FALSE, ZeroDataBlockP);
  398. return sd->firstcode;
  399. } else if (code == sd->end_code) {
  400. int count;
  401. unsigned char buf[260];
  402. if (*ZeroDataBlockP)
  403. return -2;
  404. while ((count = GetDataBlock(fd, buf, ZeroDataBlockP)) > 0)
  405. ;
  406. if (count != 0)
  407. return -2;
  408. }
  409. incode = code;
  410. if (sd->sp == (sd->stack + STACK_SIZE)) {
  411. /* Bad compressed data stream */
  412. return -1;
  413. }
  414. if (code >= sd->max_code) {
  415. *sd->sp++ = sd->firstcode;
  416. code = sd->oldcode;
  417. }
  418. while (code >= sd->clear_code) {
  419. if (sd->sp == (sd->stack + STACK_SIZE)) {
  420. /* Bad compressed data stream */
  421. return -1;
  422. }
  423. *sd->sp++ = sd->table[1][code];
  424. if (code == sd->table[0][code]) {
  425. /* Oh well */
  426. }
  427. code = sd->table[0][code];
  428. }
  429. *sd->sp++ = sd->firstcode = sd->table[1][code];
  430. if ((code = sd->max_code) <(1<<MAX_LWZ_BITS)) {
  431. sd->table[0][code] = sd->oldcode;
  432. sd->table[1][code] = sd->firstcode;
  433. ++sd->max_code;
  434. if ((sd->max_code >= sd->max_code_size) &&
  435. (sd->max_code_size < (1<<MAX_LWZ_BITS))) {
  436. sd->max_code_size *= 2;
  437. ++sd->code_size;
  438. }
  439. }
  440. sd->oldcode = incode;
  441. if (sd->sp > sd->stack)
  442. return *--sd->sp;
  443. }
  444. return code;
  445. }
  446. /* }}} */
  447. static int
  448. LWZReadByte(gdIOCtx *fd, LZW_STATIC_DATA *sd, char flag, int input_code_size, int *ZeroDataBlockP)
  449. {
  450. int rv;
  451. rv = LWZReadByte_(fd, sd, flag, input_code_size, ZeroDataBlockP);
  452. if (VERBOSE) printf("[LWZReadByte(,%d,%d) returning %d]\n",flag,input_code_size,rv);
  453. return(rv);
  454. }
  455. /* }}} */
  456. static void
  457. ReadImage(gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap)[256], int interlace, int *ZeroDataBlockP) /*1.4//, int ignore) */
  458. {
  459. unsigned char c;
  460. int v;
  461. int xpos = 0, ypos = 0, pass = 0;
  462. int i;
  463. LZW_STATIC_DATA sd;
  464. /*
  465. ** Initialize the Compression routines
  466. */
  467. if (! ReadOK(fd,&c,1)) {
  468. return;
  469. }
  470. if (c > MAX_LWZ_BITS) {
  471. return;
  472. }
  473. /* Stash the color map into the image */
  474. for (i=0; (i<gdMaxColors); i++) {
  475. im->red[i] = cmap[CM_RED][i];
  476. im->green[i] = cmap[CM_GREEN][i];
  477. im->blue[i] = cmap[CM_BLUE][i];
  478. im->open[i] = 1;
  479. }
  480. /* Many (perhaps most) of these colors will remain marked open. */
  481. im->colorsTotal = gdMaxColors;
  482. if (LWZReadByte(fd, &sd, TRUE, c, ZeroDataBlockP) < 0) {
  483. return;
  484. }
  485. /*
  486. ** If this is an "uninteresting picture" ignore it.
  487. ** REMOVED For 1.4
  488. */
  489. /*if (ignore) { */
  490. /* while (LWZReadByte(fd, &sd, FALSE, c) >= 0) */
  491. /* ; */
  492. /* return; */
  493. /*} */
  494. while ((v = LWZReadByte(fd, &sd, FALSE, c, ZeroDataBlockP)) >= 0) {
  495. if (v >= gdMaxColors) {
  496. v = 0;
  497. }
  498. /* This how we recognize which colors are actually used. */
  499. if (im->open[v]) {
  500. im->open[v] = 0;
  501. }
  502. gdImageSetPixel(im, xpos, ypos, v);
  503. ++xpos;
  504. if (xpos == len) {
  505. xpos = 0;
  506. if (interlace) {
  507. switch (pass) {
  508. case 0:
  509. case 1:
  510. ypos += 8; break;
  511. case 2:
  512. ypos += 4; break;
  513. case 3:
  514. ypos += 2; break;
  515. }
  516. if (ypos >= height) {
  517. ++pass;
  518. switch (pass) {
  519. case 1:
  520. ypos = 4; break;
  521. case 2:
  522. ypos = 2; break;
  523. case 3:
  524. ypos = 1; break;
  525. default:
  526. goto fini;
  527. }
  528. }
  529. } else {
  530. ++ypos;
  531. }
  532. }
  533. if (ypos >= height)
  534. break;
  535. }
  536. fini:
  537. if (LWZReadByte(fd, &sd, FALSE, c, ZeroDataBlockP) >=0) {
  538. /* Ignore extra */
  539. }
  540. }
  541. /* }}} */