PageRenderTime 65ms CodeModel.GetById 36ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/gifdec/gifdec.c

https://gitlab.com/lenivyyluitel/hitagi
C | 530 lines | 447 code | 42 blank | 41 comment | 87 complexity | 7a5c87fe9025088d0cc4131cf20097c8 MD5 | raw file
  1. #include "gifdec.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <sys/types.h>
  6. #include <sys/stat.h>
  7. #include <fcntl.h>
  8. #ifdef _WIN32
  9. #include <io.h>
  10. #else
  11. #include <unistd.h>
  12. #endif
  13. #define MIN(A, B) ((A) < (B) ? (A) : (B))
  14. #define MAX(A, B) ((A) > (B) ? (A) : (B))
  15. typedef struct Entry {
  16. uint16_t length;
  17. uint16_t prefix;
  18. uint8_t suffix;
  19. } Entry;
  20. typedef struct Table {
  21. int bulk;
  22. int nentries;
  23. Entry *entries;
  24. } Table;
  25. static uint16_t
  26. read_num(int fd)
  27. {
  28. uint8_t bytes[2];
  29. read(fd, bytes, 2);
  30. return bytes[0] + (((uint16_t) bytes[1]) << 8);
  31. }
  32. gd_GIF *
  33. gd_open_gif(const char *fname)
  34. {
  35. int fd;
  36. uint8_t sigver[3];
  37. uint16_t width, height, depth;
  38. uint8_t fdsz, bgidx, aspect;
  39. int i;
  40. uint8_t *bgcolor;
  41. int gct_sz;
  42. gd_GIF *gif;
  43. fd = open(fname, O_RDONLY);
  44. if (fd == -1) return NULL;
  45. #ifdef _WIN32
  46. setmode(fd, O_BINARY);
  47. #endif
  48. /* Header */
  49. read(fd, sigver, 3);
  50. if (memcmp(sigver, "GIF", 3) != 0) {
  51. fprintf(stderr, "invalid signature\n");
  52. goto fail;
  53. }
  54. /* Version */
  55. read(fd, sigver, 3);
  56. if (memcmp(sigver, "89a", 3) != 0) {
  57. fprintf(stderr, "invalid version\n");
  58. goto fail;
  59. }
  60. /* Width x Height */
  61. width = read_num(fd);
  62. height = read_num(fd);
  63. /* FDSZ */
  64. read(fd, &fdsz, 1);
  65. /* Presence of GCT */
  66. if (!(fdsz & 0x80)) {
  67. fprintf(stderr, "no global color table\n");
  68. goto fail;
  69. }
  70. /* Color Space's Depth */
  71. depth = ((fdsz >> 4) & 7) + 1;
  72. /* Ignore Sort Flag. */
  73. /* GCT Size */
  74. gct_sz = 1 << ((fdsz & 0x07) + 1);
  75. /* Background Color Index */
  76. read(fd, &bgidx, 1);
  77. /* Aspect Ratio */
  78. read(fd, &aspect, 1);
  79. /* Create gd_GIF Structure. */
  80. gif = calloc(1, sizeof(*gif));
  81. if (!gif) goto fail;
  82. gif->fd = fd;
  83. gif->width = width;
  84. gif->height = height;
  85. gif->depth = depth;
  86. /* Read GCT */
  87. gif->gct.size = gct_sz;
  88. read(fd, gif->gct.colors, 3 * gif->gct.size);
  89. gif->palette = &gif->gct;
  90. gif->bgindex = bgidx;
  91. gif->frame = calloc(4, width * height);
  92. if (!gif->frame) {
  93. free(gif);
  94. goto fail;
  95. }
  96. gif->canvas = &gif->frame[width * height];
  97. if (gif->bgindex)
  98. memset(gif->frame, gif->bgindex, gif->width * gif->height);
  99. bgcolor = &gif->palette->colors[gif->bgindex*3];
  100. if (bgcolor[0] || bgcolor[1] || bgcolor [2])
  101. for (i = 0; i < gif->width * gif->height; i++)
  102. memcpy(&gif->canvas[i*3], bgcolor, 3);
  103. gif->anim_start = lseek(fd, 0, SEEK_CUR);
  104. goto ok;
  105. fail:
  106. close(fd);
  107. return 0;
  108. ok:
  109. return gif;
  110. }
  111. static void
  112. discard_sub_blocks(gd_GIF *gif)
  113. {
  114. uint8_t size;
  115. do {
  116. read(gif->fd, &size, 1);
  117. lseek(gif->fd, size, SEEK_CUR);
  118. } while (size);
  119. }
  120. static void
  121. read_plain_text_ext(gd_GIF *gif)
  122. {
  123. if (gif->plain_text) {
  124. uint16_t tx, ty, tw, th;
  125. uint8_t cw, ch, fg, bg;
  126. off_t sub_block;
  127. lseek(gif->fd, 1, SEEK_CUR); /* block size = 12 */
  128. tx = read_num(gif->fd);
  129. ty = read_num(gif->fd);
  130. tw = read_num(gif->fd);
  131. th = read_num(gif->fd);
  132. read(gif->fd, &cw, 1);
  133. read(gif->fd, &ch, 1);
  134. read(gif->fd, &fg, 1);
  135. read(gif->fd, &bg, 1);
  136. sub_block = lseek(gif->fd, 0, SEEK_CUR);
  137. gif->plain_text(gif, tx, ty, tw, th, cw, ch, fg, bg);
  138. lseek(gif->fd, sub_block, SEEK_SET);
  139. } else {
  140. /* Discard plain text metadata. */
  141. lseek(gif->fd, 13, SEEK_CUR);
  142. }
  143. /* Discard plain text sub-blocks. */
  144. discard_sub_blocks(gif);
  145. }
  146. static void
  147. read_graphic_control_ext(gd_GIF *gif)
  148. {
  149. uint8_t rdit;
  150. /* Discard block size (always 0x04). */
  151. lseek(gif->fd, 1, SEEK_CUR);
  152. read(gif->fd, &rdit, 1);
  153. gif->gce.disposal = (rdit >> 2) & 3;
  154. gif->gce.input = rdit & 2;
  155. gif->gce.transparency = rdit & 1;
  156. gif->gce.delay = read_num(gif->fd);
  157. read(gif->fd, &gif->gce.tindex, 1);
  158. /* Skip block terminator. */
  159. lseek(gif->fd, 1, SEEK_CUR);
  160. }
  161. static void
  162. read_comment_ext(gd_GIF *gif)
  163. {
  164. if (gif->comment) {
  165. off_t sub_block = lseek(gif->fd, 0, SEEK_CUR);
  166. gif->comment(gif);
  167. lseek(gif->fd, sub_block, SEEK_SET);
  168. }
  169. /* Discard comment sub-blocks. */
  170. discard_sub_blocks(gif);
  171. }
  172. static void
  173. read_application_ext(gd_GIF *gif)
  174. {
  175. char app_id[8];
  176. char app_auth_code[3];
  177. /* Discard block size (always 0x0B). */
  178. lseek(gif->fd, 1, SEEK_CUR);
  179. /* Application Identifier. */
  180. read(gif->fd, app_id, 8);
  181. /* Application Authentication Code. */
  182. read(gif->fd, app_auth_code, 3);
  183. if (!strncmp(app_id, "NETSCAPE", sizeof(app_id))) {
  184. /* Discard block size (0x03) and constant byte (0x01). */
  185. lseek(gif->fd, 2, SEEK_CUR);
  186. gif->loop_count = read_num(gif->fd);
  187. /* Skip block terminator. */
  188. lseek(gif->fd, 1, SEEK_CUR);
  189. } else if (gif->application) {
  190. off_t sub_block = lseek(gif->fd, 0, SEEK_CUR);
  191. gif->application(gif, app_id, app_auth_code);
  192. lseek(gif->fd, sub_block, SEEK_SET);
  193. discard_sub_blocks(gif);
  194. } else {
  195. discard_sub_blocks(gif);
  196. }
  197. }
  198. static void
  199. read_ext(gd_GIF *gif)
  200. {
  201. uint8_t label;
  202. read(gif->fd, &label, 1);
  203. switch (label) {
  204. case 0x01:
  205. read_plain_text_ext(gif);
  206. break;
  207. case 0xF9:
  208. read_graphic_control_ext(gif);
  209. break;
  210. case 0xFE:
  211. read_comment_ext(gif);
  212. break;
  213. case 0xFF:
  214. read_application_ext(gif);
  215. break;
  216. default:
  217. fprintf(stderr, "unknown extension: %02X\n", label);
  218. }
  219. }
  220. static Table *
  221. new_table(int key_size)
  222. {
  223. int key;
  224. int init_bulk = MAX(1 << (key_size + 1), 0x100);
  225. Table *table = malloc(sizeof(*table) + sizeof(Entry) * init_bulk);
  226. if (table) {
  227. table->bulk = init_bulk;
  228. table->nentries = (1 << key_size) + 2;
  229. table->entries = (Entry *) &table[1];
  230. for (key = 0; key < (1 << key_size); key++)
  231. table->entries[key] = (Entry) {1, 0xFFF, key};
  232. }
  233. return table;
  234. }
  235. /* Add table entry. Return value:
  236. * 0 on success
  237. * +1 if key size must be incremented after this addition
  238. * -1 if could not realloc table */
  239. static int
  240. add_entry(Table **tablep, uint16_t length, uint16_t prefix, uint8_t suffix)
  241. {
  242. Table *table = *tablep;
  243. if (table->nentries == table->bulk) {
  244. table->bulk *= 2;
  245. table = realloc(table, sizeof(*table) + sizeof(Entry) * table->bulk);
  246. if (!table) return -1;
  247. table->entries = (Entry *) &table[1];
  248. *tablep = table;
  249. }
  250. table->entries[table->nentries] = (Entry) {length, prefix, suffix};
  251. table->nentries++;
  252. if ((table->nentries & (table->nentries - 1)) == 0)
  253. return 1;
  254. return 0;
  255. }
  256. static uint16_t
  257. get_key(gd_GIF *gif, int key_size, uint8_t *sub_len, uint8_t *shift, uint8_t *byte)
  258. {
  259. int bits_read;
  260. int rpad;
  261. int frag_size;
  262. uint16_t key;
  263. key = 0;
  264. for (bits_read = 0; bits_read < key_size; bits_read += frag_size) {
  265. rpad = (*shift + bits_read) % 8;
  266. if (rpad == 0) {
  267. /* Update byte. */
  268. if (*sub_len == 0) {
  269. read(gif->fd, sub_len, 1); /* Must be nonzero! */
  270. if (*sub_len == 0)
  271. return 0x1000;
  272. }
  273. read(gif->fd, byte, 1);
  274. (*sub_len)--;
  275. }
  276. frag_size = MIN(key_size - bits_read, 8 - rpad);
  277. key |= ((uint16_t) ((*byte) >> rpad)) << bits_read;
  278. }
  279. /* Clear extra bits to the left. */
  280. key &= (1 << key_size) - 1;
  281. *shift = (*shift + key_size) % 8;
  282. return key;
  283. }
  284. /* Compute output index of y-th input line, in frame of height h. */
  285. static int
  286. interlaced_line_index(int h, int y)
  287. {
  288. int p; /* number of lines in current pass */
  289. p = (h - 1) / 8 + 1;
  290. if (y < p) /* pass 1 */
  291. return y * 8;
  292. y -= p;
  293. p = (h - 5) / 8 + 1;
  294. if (y < p) /* pass 2 */
  295. return y * 8 + 4;
  296. y -= p;
  297. p = (h - 3) / 4 + 1;
  298. if (y < p) /* pass 3 */
  299. return y * 4 + 2;
  300. y -= p;
  301. /* pass 4 */
  302. return y * 2 + 1;
  303. }
  304. /* Decompress image pixels.
  305. * Return 0 on success or -1 on out-of-memory (w.r.t. LZW code table). */
  306. static int
  307. read_image_data(gd_GIF *gif, int interlace)
  308. {
  309. uint8_t sub_len, shift, byte;
  310. int init_key_size, key_size, table_is_full;
  311. int frm_off, frm_size, str_len, i, p, x, y;
  312. uint16_t key, clear, stop;
  313. int ret;
  314. Table *table;
  315. Entry entry;
  316. off_t start, end;
  317. read(gif->fd, &byte, 1);
  318. key_size = (int) byte;
  319. if (key_size < 2 || key_size > 8)
  320. return -1;
  321. start = lseek(gif->fd, 0, SEEK_CUR);
  322. discard_sub_blocks(gif);
  323. end = lseek(gif->fd, 0, SEEK_CUR);
  324. lseek(gif->fd, start, SEEK_SET);
  325. clear = 1 << key_size;
  326. stop = clear + 1;
  327. table = new_table(key_size);
  328. key_size++;
  329. init_key_size = key_size;
  330. sub_len = shift = 0;
  331. key = get_key(gif, key_size, &sub_len, &shift, &byte); /* clear code */
  332. frm_off = 0;
  333. ret = 0;
  334. frm_size = gif->fw*gif->fh;
  335. while (frm_off < frm_size) {
  336. if (key == clear) {
  337. key_size = init_key_size;
  338. table->nentries = (1 << (key_size - 1)) + 2;
  339. table_is_full = 0;
  340. } else if (!table_is_full) {
  341. ret = add_entry(&table, str_len + 1, key, entry.suffix);
  342. if (ret == -1) {
  343. free(table);
  344. return -1;
  345. }
  346. if (table->nentries == 0x1000) {
  347. ret = 0;
  348. table_is_full = 1;
  349. }
  350. }
  351. key = get_key(gif, key_size, &sub_len, &shift, &byte);
  352. if (key == clear) continue;
  353. if (key == stop || key == 0x1000) break;
  354. if (ret == 1) key_size++;
  355. entry = table->entries[key];
  356. str_len = entry.length;
  357. for (i = 0; i < str_len; i++) {
  358. p = frm_off + entry.length - 1;
  359. x = p % gif->fw;
  360. y = p / gif->fw;
  361. if (interlace)
  362. y = interlaced_line_index((int) gif->fh, y);
  363. gif->frame[(gif->fy + y) * gif->width + gif->fx + x] = entry.suffix;
  364. if (entry.prefix == 0xFFF)
  365. break;
  366. else
  367. entry = table->entries[entry.prefix];
  368. }
  369. frm_off += str_len;
  370. if (key < table->nentries - 1 && !table_is_full)
  371. table->entries[table->nentries - 1].suffix = entry.suffix;
  372. }
  373. free(table);
  374. if (key == stop)
  375. read(gif->fd, &sub_len, 1); /* Must be zero! */
  376. lseek(gif->fd, end, SEEK_SET);
  377. return 0;
  378. }
  379. /* Read image.
  380. * Return 0 on success or -1 on out-of-memory (w.r.t. LZW code table). */
  381. static int
  382. read_image(gd_GIF *gif)
  383. {
  384. uint8_t fisrz;
  385. int interlace;
  386. /* Image Descriptor. */
  387. gif->fx = read_num(gif->fd);
  388. gif->fy = read_num(gif->fd);
  389. if (gif->fx >= gif->width || gif->fy >= gif->height)
  390. return -1;
  391. gif->fw = read_num(gif->fd);
  392. gif->fh = read_num(gif->fd);
  393. gif->fw = MIN(gif->fw, gif->width - gif->fx);
  394. gif->fh = MIN(gif->fh, gif->height - gif->fy);
  395. read(gif->fd, &fisrz, 1);
  396. interlace = fisrz & 0x40;
  397. /* Ignore Sort Flag. */
  398. /* Local Color Table? */
  399. if (fisrz & 0x80) {
  400. /* Read LCT */
  401. gif->lct.size = 1 << ((fisrz & 0x07) + 1);
  402. read(gif->fd, gif->lct.colors, 3 * gif->lct.size);
  403. gif->palette = &gif->lct;
  404. } else
  405. gif->palette = &gif->gct;
  406. /* Image Data. */
  407. return read_image_data(gif, interlace);
  408. }
  409. static void
  410. render_frame_rect(gd_GIF *gif, uint8_t *buffer)
  411. {
  412. int i, j, k;
  413. uint8_t index, *color;
  414. i = gif->fy * gif->width + gif->fx;
  415. for (j = 0; j < gif->fh; j++) {
  416. for (k = 0; k < gif->fw; k++) {
  417. index = gif->frame[(gif->fy + j) * gif->width + gif->fx + k];
  418. color = &gif->palette->colors[index*3];
  419. if (!gif->gce.transparency || index != gif->gce.tindex)
  420. memcpy(&buffer[(i+k)*3], color, 3);
  421. }
  422. i += gif->width;
  423. }
  424. }
  425. static void
  426. dispose(gd_GIF *gif)
  427. {
  428. int i, j, k;
  429. uint8_t *bgcolor;
  430. switch (gif->gce.disposal) {
  431. case 2: /* Restore to background color. */
  432. bgcolor = &gif->palette->colors[gif->bgindex*3];
  433. i = gif->fy * gif->width + gif->fx;
  434. for (j = 0; j < gif->fh; j++) {
  435. for (k = 0; k < gif->fw; k++)
  436. memcpy(&gif->canvas[(i+k)*3], bgcolor, 3);
  437. i += gif->width;
  438. }
  439. break;
  440. case 3: /* Restore to previous, i.e., don't update canvas.*/
  441. break;
  442. default:
  443. /* Add frame non-transparent pixels to canvas. */
  444. render_frame_rect(gif, gif->canvas);
  445. }
  446. }
  447. /* Return 1 if got a frame; 0 if got GIF trailer; -1 if error. */
  448. int
  449. gd_get_frame(gd_GIF *gif)
  450. {
  451. char sep;
  452. dispose(gif);
  453. read(gif->fd, &sep, 1);
  454. while (sep != ',') {
  455. if (sep == ';')
  456. return 0;
  457. if (sep == '!')
  458. read_ext(gif);
  459. else return -1;
  460. read(gif->fd, &sep, 1);
  461. }
  462. if (read_image(gif) == -1)
  463. return -1;
  464. return 1;
  465. }
  466. void
  467. gd_render_frame(gd_GIF *gif, uint8_t *buffer)
  468. {
  469. memcpy(buffer, gif->canvas, gif->width * gif->height * 3);
  470. render_frame_rect(gif, buffer);
  471. }
  472. int
  473. gd_is_bgcolor(gd_GIF *gif, uint8_t color[3])
  474. {
  475. return !memcmp(&gif->palette->colors[gif->bgindex*3], color, 3);
  476. }
  477. void
  478. gd_rewind(gd_GIF *gif)
  479. {
  480. lseek(gif->fd, gif->anim_start, SEEK_SET);
  481. }
  482. void
  483. gd_close_gif(gd_GIF *gif)
  484. {
  485. close(gif->fd);
  486. free(gif->frame);
  487. free(gif);
  488. }