PageRenderTime 1355ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/release/src/router/php/ext/gd/libgd/gd_gif_in.c

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