gifdec.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  1. #include "gifdec.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <stdbool.h>
  6. #define MIN(A, B) ((A) < (B) ? (A) : (B))
  7. #define MAX(A, B) ((A) > (B) ? (A) : (B))
  8. typedef struct Entry {
  9. uint16_t length;
  10. uint16_t prefix;
  11. uint8_t suffix;
  12. } Entry;
  13. typedef struct Table {
  14. int bulk;
  15. int nentries;
  16. Entry *entries;
  17. } Table;
  18. static gd_GIF * gif_open(gd_GIF * gif);
  19. static bool f_gif_open(gd_GIF * gif, const void * path, bool is_file);
  20. static void f_gif_read(gd_GIF * gif, void * buf, size_t len);
  21. static int f_gif_seek(gd_GIF * gif, size_t pos, int k);
  22. static void f_gif_close(gd_GIF * gif);
  23. static uint16_t
  24. read_num(gd_GIF * gif)
  25. {
  26. uint8_t bytes[2];
  27. f_gif_read(gif, bytes, 2);
  28. return bytes[0] + (((uint16_t) bytes[1]) << 8);
  29. }
  30. gd_GIF *
  31. gd_open_gif_file(const char *fname)
  32. {
  33. gd_GIF gif_base;
  34. memset(&gif_base, 0, sizeof(gif_base));
  35. bool res = f_gif_open(&gif_base, fname, true);
  36. if(!res) return NULL;
  37. return gif_open(&gif_base);
  38. }
  39. gd_GIF *
  40. gd_open_gif_data(const void *data)
  41. {
  42. gd_GIF gif_base;
  43. memset(&gif_base, 0, sizeof(gif_base));
  44. bool res = f_gif_open(&gif_base, data, false);
  45. if(!res) return NULL;
  46. return gif_open(&gif_base);
  47. }
  48. static gd_GIF * gif_open(gd_GIF * gif_base)
  49. {
  50. uint8_t sigver[3];
  51. uint16_t width, height, depth;
  52. uint8_t fdsz, bgidx, aspect;
  53. int i;
  54. uint8_t *bgcolor;
  55. int gct_sz;
  56. gd_GIF *gif = NULL;
  57. /* Header */
  58. f_gif_read(gif_base, sigver, 3);
  59. if (memcmp(sigver, "GIF", 3) != 0) {
  60. //fprintf(stderr, "invalid signature\n");
  61. goto fail;
  62. }
  63. /* Version */
  64. f_gif_read(gif_base, sigver, 3);
  65. if (memcmp(sigver, "89a", 3) != 0) {
  66. LV_LOG_WARN("invalid version\n");
  67. goto fail;
  68. }
  69. /* Width x Height */
  70. width = read_num(gif_base);
  71. height = read_num(gif_base);
  72. /* FDSZ */
  73. f_gif_read(gif_base, &fdsz, 1);
  74. /* Presence of GCT */
  75. if (!(fdsz & 0x80)) {
  76. LV_LOG_WARN("no global color table\n");
  77. goto fail;
  78. }
  79. /* Color Space's Depth */
  80. depth = ((fdsz >> 4) & 7) + 1;
  81. /* Ignore Sort Flag. */
  82. /* GCT Size */
  83. gct_sz = 1 << ((fdsz & 0x07) + 1);
  84. /* Background Color Index */
  85. f_gif_read(gif_base, &bgidx, 1);
  86. /* Aspect Ratio */
  87. f_gif_read(gif_base, &aspect, 1);
  88. /* Create gd_GIF Structure. */
  89. #if LV_COLOR_DEPTH == 32
  90. gif = lv_mem_alloc(sizeof(gd_GIF) + 5 * width * height);
  91. #elif LV_COLOR_DEPTH == 16
  92. gif = lv_mem_alloc(sizeof(gd_GIF) + 4 * width * height);
  93. #elif LV_COLOR_DEPTH == 8
  94. gif = lv_mem_alloc(sizeof(gd_GIF) + 3 * width * height);
  95. #endif
  96. if (!gif) goto fail;
  97. memcpy(gif, gif_base, sizeof(gd_GIF));
  98. gif->width = width;
  99. gif->height = height;
  100. gif->depth = depth;
  101. /* Read GCT */
  102. gif->gct.size = gct_sz;
  103. f_gif_read(gif, gif->gct.colors, 3 * gif->gct.size);
  104. gif->palette = &gif->gct;
  105. gif->bgindex = bgidx;
  106. gif->canvas = (uint8_t *) &gif[1];
  107. #if LV_COLOR_DEPTH == 32
  108. gif->frame = &gif->canvas[4 * width * height];
  109. #elif LV_COLOR_DEPTH == 16
  110. gif->frame = &gif->canvas[3 * width * height];
  111. #elif LV_COLOR_DEPTH == 8
  112. gif->frame = &gif->canvas[2 * width * height];
  113. #endif
  114. if (gif->bgindex)
  115. memset(gif->frame, gif->bgindex, gif->width * gif->height);
  116. bgcolor = &gif->palette->colors[gif->bgindex*3];
  117. if (bgcolor[0] || bgcolor[1] || bgcolor [2])
  118. for (i = 0; i < gif->width * gif->height; i++) {
  119. #if LV_COLOR_DEPTH == 32
  120. gif->canvas[i*4 + 0] = *(bgcolor + 2);
  121. gif->canvas[i*4 + 1] = *(bgcolor + 1);
  122. gif->canvas[i*4 + 2] = *(bgcolor + 0);
  123. gif->canvas[i*4 + 3] = 0xff;
  124. #elif LV_COLOR_DEPTH == 16
  125. lv_color_t c = lv_color_make(*(bgcolor + 0), *(bgcolor + 1), *(bgcolor + 2));
  126. gif->canvas[i*3 + 0] = c.full & 0xff;
  127. gif->canvas[i*3 + 1] = (c.full >> 8) & 0xff;
  128. gif->canvas[i*3 + 2] = 0xff;
  129. #elif LV_COLOR_DEPTH == 8
  130. lv_color_t c = lv_color_make(*(bgcolor + 0), *(bgcolor + 1), *(bgcolor + 2));
  131. gif->canvas[i*2 + 0] = c.full;
  132. gif->canvas[i*2 + 1] = 0xff;
  133. #endif
  134. }
  135. gif->anim_start = f_gif_seek(gif, 0, SEEK_CUR);
  136. goto ok;
  137. fail:
  138. f_gif_close(gif_base);
  139. ok:
  140. return gif;
  141. }
  142. static void
  143. discard_sub_blocks(gd_GIF *gif)
  144. {
  145. uint8_t size;
  146. do {
  147. f_gif_read(gif, &size, 1);
  148. f_gif_seek(gif, size, SEEK_CUR);
  149. } while (size);
  150. }
  151. static void
  152. read_plain_text_ext(gd_GIF *gif)
  153. {
  154. if (gif->plain_text) {
  155. uint16_t tx, ty, tw, th;
  156. uint8_t cw, ch, fg, bg;
  157. size_t sub_block;
  158. f_gif_seek(gif, 1, SEEK_CUR); /* block size = 12 */
  159. tx = read_num(gif);
  160. ty = read_num(gif);
  161. tw = read_num(gif);
  162. th = read_num(gif);
  163. f_gif_read(gif, &cw, 1);
  164. f_gif_read(gif, &ch, 1);
  165. f_gif_read(gif, &fg, 1);
  166. f_gif_read(gif, &bg, 1);
  167. sub_block = f_gif_seek(gif, 0, SEEK_CUR);
  168. gif->plain_text(gif, tx, ty, tw, th, cw, ch, fg, bg);
  169. f_gif_seek(gif, sub_block, SEEK_SET);
  170. } else {
  171. /* Discard plain text metadata. */
  172. f_gif_seek(gif, 13, SEEK_CUR);
  173. }
  174. /* Discard plain text sub-blocks. */
  175. discard_sub_blocks(gif);
  176. }
  177. static void
  178. read_graphic_control_ext(gd_GIF *gif)
  179. {
  180. uint8_t rdit;
  181. /* Discard block size (always 0x04). */
  182. f_gif_seek(gif, 1, SEEK_CUR);
  183. f_gif_read(gif, &rdit, 1);
  184. gif->gce.disposal = (rdit >> 2) & 3;
  185. gif->gce.input = rdit & 2;
  186. gif->gce.transparency = rdit & 1;
  187. gif->gce.delay = read_num(gif);
  188. f_gif_read(gif, &gif->gce.tindex, 1);
  189. /* Skip block terminator. */
  190. f_gif_seek(gif, 1, SEEK_CUR);
  191. }
  192. static void
  193. read_comment_ext(gd_GIF *gif)
  194. {
  195. if (gif->comment) {
  196. size_t sub_block = f_gif_seek(gif, 0, SEEK_CUR);
  197. gif->comment(gif);
  198. f_gif_seek(gif, sub_block, SEEK_SET);
  199. }
  200. /* Discard comment sub-blocks. */
  201. discard_sub_blocks(gif);
  202. }
  203. static void
  204. read_application_ext(gd_GIF *gif)
  205. {
  206. char app_id[8];
  207. char app_auth_code[3];
  208. /* Discard block size (always 0x0B). */
  209. f_gif_seek(gif, 1, SEEK_CUR);
  210. /* Application Identifier. */
  211. f_gif_read(gif, app_id, 8);
  212. /* Application Authentication Code. */
  213. f_gif_read(gif, app_auth_code, 3);
  214. if (!strncmp(app_id, "NETSCAPE", sizeof(app_id))) {
  215. /* Discard block size (0x03) and constant byte (0x01). */
  216. f_gif_seek(gif, 2, SEEK_CUR);
  217. gif->loop_count = read_num(gif);
  218. /* Skip block terminator. */
  219. f_gif_seek(gif, 1, SEEK_CUR);
  220. } else if (gif->application) {
  221. size_t sub_block = f_gif_seek(gif, 0, SEEK_CUR);
  222. gif->application(gif, app_id, app_auth_code);
  223. f_gif_seek(gif, sub_block, SEEK_SET);
  224. discard_sub_blocks(gif);
  225. } else {
  226. discard_sub_blocks(gif);
  227. }
  228. }
  229. static void
  230. read_ext(gd_GIF *gif)
  231. {
  232. uint8_t label;
  233. f_gif_read(gif, &label, 1);
  234. switch (label) {
  235. case 0x01:
  236. read_plain_text_ext(gif);
  237. break;
  238. case 0xF9:
  239. read_graphic_control_ext(gif);
  240. break;
  241. case 0xFE:
  242. read_comment_ext(gif);
  243. break;
  244. case 0xFF:
  245. read_application_ext(gif);
  246. break;
  247. default:
  248. LV_LOG_WARN("unknown extension: %02X\n", label);
  249. }
  250. }
  251. static Table *
  252. new_table(int key_size)
  253. {
  254. int key;
  255. int init_bulk = MAX(1 << (key_size + 1), 0x100);
  256. Table *table = lv_mem_alloc(sizeof(*table) + sizeof(Entry) * init_bulk);
  257. if (table) {
  258. table->bulk = init_bulk;
  259. table->nentries = (1 << key_size) + 2;
  260. table->entries = (Entry *) &table[1];
  261. for (key = 0; key < (1 << key_size); key++)
  262. table->entries[key] = (Entry) {1, 0xFFF, key};
  263. }
  264. return table;
  265. }
  266. /* Add table entry. Return value:
  267. * 0 on success
  268. * +1 if key size must be incremented after this addition
  269. * -1 if could not realloc table */
  270. static int
  271. add_entry(Table **tablep, uint16_t length, uint16_t prefix, uint8_t suffix)
  272. {
  273. Table *table = *tablep;
  274. if (table->nentries == table->bulk) {
  275. table->bulk *= 2;
  276. table = lv_mem_realloc(table, sizeof(*table) + sizeof(Entry) * table->bulk);
  277. if (!table) return -1;
  278. table->entries = (Entry *) &table[1];
  279. *tablep = table;
  280. }
  281. table->entries[table->nentries] = (Entry) {length, prefix, suffix};
  282. table->nentries++;
  283. if ((table->nentries & (table->nentries - 1)) == 0)
  284. return 1;
  285. return 0;
  286. }
  287. static uint16_t
  288. get_key(gd_GIF *gif, int key_size, uint8_t *sub_len, uint8_t *shift, uint8_t *byte)
  289. {
  290. int bits_read;
  291. int rpad;
  292. int frag_size;
  293. uint16_t key;
  294. key = 0;
  295. for (bits_read = 0; bits_read < key_size; bits_read += frag_size) {
  296. rpad = (*shift + bits_read) % 8;
  297. if (rpad == 0) {
  298. /* Update byte. */
  299. if (*sub_len == 0) {
  300. f_gif_read(gif, sub_len, 1); /* Must be nonzero! */
  301. if (*sub_len == 0) return 0x1000;
  302. }
  303. f_gif_read(gif, byte, 1);
  304. (*sub_len)--;
  305. }
  306. frag_size = MIN(key_size - bits_read, 8 - rpad);
  307. key |= ((uint16_t) ((*byte) >> rpad)) << bits_read;
  308. }
  309. /* Clear extra bits to the left. */
  310. key &= (1 << key_size) - 1;
  311. *shift = (*shift + key_size) % 8;
  312. return key;
  313. }
  314. /* Compute output index of y-th input line, in frame of height h. */
  315. static int
  316. interlaced_line_index(int h, int y)
  317. {
  318. int p; /* number of lines in current pass */
  319. p = (h - 1) / 8 + 1;
  320. if (y < p) /* pass 1 */
  321. return y * 8;
  322. y -= p;
  323. p = (h - 5) / 8 + 1;
  324. if (y < p) /* pass 2 */
  325. return y * 8 + 4;
  326. y -= p;
  327. p = (h - 3) / 4 + 1;
  328. if (y < p) /* pass 3 */
  329. return y * 4 + 2;
  330. y -= p;
  331. /* pass 4 */
  332. return y * 2 + 1;
  333. }
  334. /* Decompress image pixels.
  335. * Return 0 on success or -1 on out-of-memory (w.r.t. LZW code table). */
  336. static int
  337. read_image_data(gd_GIF *gif, int interlace)
  338. {
  339. uint8_t sub_len, shift, byte;
  340. int init_key_size, key_size, table_is_full = 0;
  341. int frm_off, frm_size, str_len = 0, i, p, x, y;
  342. uint16_t key, clear, stop;
  343. int ret;
  344. Table *table;
  345. Entry entry = {0};
  346. size_t start, end;
  347. f_gif_read(gif, &byte, 1);
  348. key_size = (int) byte;
  349. start = f_gif_seek(gif, 0, SEEK_CUR);
  350. discard_sub_blocks(gif);
  351. end = f_gif_seek(gif, 0, SEEK_CUR);
  352. f_gif_seek(gif, start, SEEK_SET);
  353. clear = 1 << key_size;
  354. stop = clear + 1;
  355. table = new_table(key_size);
  356. key_size++;
  357. init_key_size = key_size;
  358. sub_len = shift = 0;
  359. key = get_key(gif, key_size, &sub_len, &shift, &byte); /* clear code */
  360. frm_off = 0;
  361. ret = 0;
  362. frm_size = gif->fw*gif->fh;
  363. while (frm_off < frm_size) {
  364. if (key == clear) {
  365. key_size = init_key_size;
  366. table->nentries = (1 << (key_size - 1)) + 2;
  367. table_is_full = 0;
  368. } else if (!table_is_full) {
  369. ret = add_entry(&table, str_len + 1, key, entry.suffix);
  370. if (ret == -1) {
  371. lv_mem_free(table);
  372. return -1;
  373. }
  374. if (table->nentries == 0x1000) {
  375. ret = 0;
  376. table_is_full = 1;
  377. }
  378. }
  379. key = get_key(gif, key_size, &sub_len, &shift, &byte);
  380. if (key == clear) continue;
  381. if (key == stop || key == 0x1000) break;
  382. if (ret == 1) key_size++;
  383. entry = table->entries[key];
  384. str_len = entry.length;
  385. for (i = 0; i < str_len; i++) {
  386. p = frm_off + entry.length - 1;
  387. x = p % gif->fw;
  388. y = p / gif->fw;
  389. if (interlace)
  390. y = interlaced_line_index((int) gif->fh, y);
  391. gif->frame[(gif->fy + y) * gif->width + gif->fx + x] = entry.suffix;
  392. if (entry.prefix == 0xFFF)
  393. break;
  394. else
  395. entry = table->entries[entry.prefix];
  396. }
  397. frm_off += str_len;
  398. if (key < table->nentries - 1 && !table_is_full)
  399. table->entries[table->nentries - 1].suffix = entry.suffix;
  400. }
  401. lv_mem_free(table);
  402. if (key == stop) f_gif_read(gif, &sub_len, 1); /* Must be zero! */
  403. f_gif_seek(gif, end, SEEK_SET);
  404. return 0;
  405. }
  406. /* Read image.
  407. * Return 0 on success or -1 on out-of-memory (w.r.t. LZW code table). */
  408. static int
  409. read_image(gd_GIF *gif)
  410. {
  411. uint8_t fisrz;
  412. int interlace;
  413. /* Image Descriptor. */
  414. gif->fx = read_num(gif);
  415. gif->fy = read_num(gif);
  416. gif->fw = read_num(gif);
  417. gif->fh = read_num(gif);
  418. f_gif_read(gif, &fisrz, 1);
  419. interlace = fisrz & 0x40;
  420. /* Ignore Sort Flag. */
  421. /* Local Color Table? */
  422. if (fisrz & 0x80) {
  423. /* Read LCT */
  424. gif->lct.size = 1 << ((fisrz & 0x07) + 1);
  425. f_gif_read(gif, gif->lct.colors, 3 * gif->lct.size);
  426. gif->palette = &gif->lct;
  427. } else
  428. gif->palette = &gif->gct;
  429. /* Image Data. */
  430. return read_image_data(gif, interlace);
  431. }
  432. static void
  433. render_frame_rect(gd_GIF *gif, uint8_t *buffer)
  434. {
  435. int i, j, k;
  436. uint8_t index, *color;
  437. i = gif->fy * gif->width + gif->fx;
  438. for (j = 0; j < gif->fh; j++) {
  439. for (k = 0; k < gif->fw; k++) {
  440. index = gif->frame[(gif->fy + j) * gif->width + gif->fx + k];
  441. color = &gif->palette->colors[index*3];
  442. if (!gif->gce.transparency || index != gif->gce.tindex) {
  443. #if LV_COLOR_DEPTH == 32
  444. buffer[(i+k)*4 + 0] = *(color + 2);
  445. buffer[(i+k)*4 + 1] = *(color + 1);
  446. buffer[(i+k)*4 + 2] = *(color + 0);
  447. buffer[(i+k)*4 + 3] = 0xFF;
  448. #elif LV_COLOR_DEPTH == 16
  449. lv_color_t c = lv_color_make(*(color + 0), *(color + 1), *(color + 2));
  450. buffer[(i+k)*3 + 0] = c.full & 0xff;
  451. buffer[(i+k)*3 + 1] = (c.full >> 8) & 0xff;
  452. buffer[(i+k)*3 + 2] = 0xff;
  453. #elif LV_COLOR_DEPTH == 8
  454. lv_color_t c = lv_color_make(*(color + 0), *(color + 1), *(color + 2));
  455. buffer[(i+k)*2 + 0] = c.full;
  456. buffer[(i+k)*2 + 1] = 0xff;
  457. #endif
  458. }
  459. }
  460. i += gif->width;
  461. }
  462. }
  463. static void
  464. dispose(gd_GIF *gif)
  465. {
  466. int i, j, k;
  467. uint8_t *bgcolor;
  468. switch (gif->gce.disposal) {
  469. case 2: /* Restore to background color. */
  470. bgcolor = &gif->palette->colors[gif->bgindex*3];
  471. uint8_t opa = 0xff;
  472. if(gif->gce.transparency) opa = 0x00;
  473. i = gif->fy * gif->width + gif->fx;
  474. for (j = 0; j < gif->fh; j++) {
  475. for (k = 0; k < gif->fw; k++) {
  476. #if LV_COLOR_DEPTH == 32
  477. gif->canvas[(i+k)*4 + 0] = *(bgcolor + 2);
  478. gif->canvas[(i+k)*4 + 1] = *(bgcolor + 1);
  479. gif->canvas[(i+k)*4 + 2] = *(bgcolor + 0);
  480. gif->canvas[(i+k)*4 + 3] = opa;
  481. #elif LV_COLOR_DEPTH == 16
  482. lv_color_t c = lv_color_make(*(bgcolor + 0), *(bgcolor + 1), *(bgcolor + 2));
  483. gif->canvas[(i+k)*3 + 0] = c.full & 0xff;
  484. gif->canvas[(i+k)*3 + 1] = (c.full >> 8) & 0xff;
  485. gif->canvas[(i+k)*3 + 2] = opa;
  486. #elif LV_COLOR_DEPTH == 8
  487. lv_color_t c = lv_color_make(*(bgcolor + 0), *(bgcolor + 1), *(bgcolor + 2));
  488. gif->canvas[(i+k)*2 + 0] = c.full;
  489. gif->canvas[(i+k)*2 + 1] = opa;
  490. #endif
  491. }
  492. i += gif->width;
  493. }
  494. break;
  495. case 3: /* Restore to previous, i.e., don't update canvas.*/
  496. break;
  497. default:
  498. /* Add frame non-transparent pixels to canvas. */
  499. render_frame_rect(gif, gif->canvas);
  500. }
  501. }
  502. /* Return 1 if got a frame; 0 if got GIF trailer; -1 if error. */
  503. int
  504. gd_get_frame(gd_GIF *gif)
  505. {
  506. char sep;
  507. dispose(gif);
  508. f_gif_read(gif, &sep, 1);
  509. while (sep != ',') {
  510. if (sep == ';')
  511. return 0;
  512. if (sep == '!')
  513. read_ext(gif);
  514. else return -1;
  515. f_gif_read(gif, &sep, 1);
  516. }
  517. if (read_image(gif) == -1)
  518. return -1;
  519. return 1;
  520. }
  521. void
  522. gd_render_frame(gd_GIF *gif, uint8_t *buffer)
  523. {
  524. // uint32_t i;
  525. // uint32_t j;
  526. // for(i = 0, j = 0; i < gif->width * gif->height * 3; i+= 3, j+=4) {
  527. // buffer[j + 0] = gif->canvas[i + 2];
  528. // buffer[j + 1] = gif->canvas[i + 1];
  529. // buffer[j + 2] = gif->canvas[i + 0];
  530. // buffer[j + 3] = 0xFF;
  531. // }
  532. // memcpy(buffer, gif->canvas, gif->width * gif->height * 3);
  533. render_frame_rect(gif, buffer);
  534. }
  535. int
  536. gd_is_bgcolor(gd_GIF *gif, uint8_t color[3])
  537. {
  538. return !memcmp(&gif->palette->colors[gif->bgindex*3], color, 3);
  539. }
  540. void
  541. gd_rewind(gd_GIF *gif)
  542. {
  543. f_gif_seek(gif, gif->anim_start, SEEK_SET);
  544. }
  545. void
  546. gd_close_gif(gd_GIF *gif)
  547. {
  548. f_gif_close(gif);
  549. lv_mem_free(gif);
  550. }
  551. #if LV_USE_FILESYSTEM && LVGL_VERSION_MAJOR <= 7
  552. enum {
  553. LV_FS_SEEK_SET = 0x00,
  554. LV_FS_SEEK_CUR = 0x01,
  555. LV_FS_SEEK_END = 0x02,
  556. };
  557. typedef uint8_t lv_fs_whence_t;
  558. static void * lv_fs_open_to_old(const char * path, lv_fs_mode_t mode)
  559. {
  560. lv_fs_file_t * file_p = lv_mem_alloc(sizeof(lv_fs_file_t));
  561. lv_fs_open(file_p, path, mode);
  562. return file_p;
  563. }
  564. static lv_fs_res_t lv_fs_close_to_old(lv_fs_file_t * file_p)
  565. {
  566. lv_fs_close(file_p);
  567. lv_mem_free(file_p);
  568. return LV_FS_RES_OK;
  569. }
  570. static lv_fs_res_t lv_fs_seek_to_old(lv_fs_file_t * file_p, uint32_t pos, lv_fs_whence_t whence)
  571. {
  572. uint32_t read_pos = 0;
  573. uint32_t res_pos = 0;
  574. lv_fs_tell(file_p, &read_pos);
  575. if(whence == LV_FS_SEEK_SET){
  576. res_pos = pos;
  577. }
  578. else {
  579. res_pos = read_pos + pos;
  580. }
  581. lv_fs_seek(file_p, res_pos);
  582. return LV_FS_RES_OK;
  583. }
  584. #endif
  585. static bool f_gif_open(gd_GIF * gif, const void * path, bool is_file)
  586. {
  587. gif->f_rw_p = 0;
  588. gif->data = NULL;
  589. #if LV_USE_FILESYSTEM
  590. gif->fd = NULL;
  591. #endif
  592. if(is_file) {
  593. #if LV_USE_FILESYSTEM
  594. # if LVGL_VERSION_MAJOR > 7
  595. gif->fd = lv_fs_open(path, LV_FS_MODE_RD);
  596. # else
  597. gif->fd = lv_fs_open_to_old(path, LV_FS_MODE_RD);
  598. # endif
  599. if(gif->fd == NULL) return false;
  600. else return true;
  601. #else
  602. return false;
  603. #endif
  604. } else
  605. {
  606. gif->data = path;
  607. return true;
  608. }
  609. }
  610. static void f_gif_read(gd_GIF * gif, void * buf, size_t len)
  611. {
  612. #if LV_USE_FILESYSTEM
  613. if(gif->fd) {
  614. lv_fs_read(gif->fd, buf, len, NULL);
  615. } else
  616. #endif
  617. {
  618. memcpy(buf, &gif->data[gif->f_rw_p], len);
  619. gif->f_rw_p += len;
  620. }
  621. }
  622. static int f_gif_seek(gd_GIF * gif, size_t pos, int k)
  623. {
  624. #if LV_USE_FILESYSTEM
  625. if(k == SEEK_CUR) k = LV_FS_SEEK_CUR;
  626. else if(k == SEEK_SET) k = LV_FS_SEEK_SET;
  627. if(gif->fd) {
  628. # if LVGL_VERSION_MAJOR > 7
  629. lv_fs_seek(gif->fd, pos, k);
  630. # else
  631. lv_fs_seek_to_old(gif->fd, pos, k);
  632. # endif
  633. uint32_t x;
  634. lv_fs_tell(gif->fd, &x);
  635. return x;
  636. } else {
  637. if(k == LV_FS_SEEK_CUR) gif->f_rw_p += pos;
  638. else if(k == LV_FS_SEEK_SET) gif->f_rw_p = pos;
  639. return gif->f_rw_p;
  640. }
  641. #else
  642. if(k == SEEK_CUR) gif->f_rw_p += pos;
  643. else if(k == SEEK_SET) gif->f_rw_p = pos;
  644. return gif->f_rw_p;
  645. #endif
  646. }
  647. static void f_gif_close(gd_GIF * gif)
  648. {
  649. #if LV_USE_FILESYSTEM
  650. if(gif->fd) {
  651. # if LVGL_VERSION_MAJOR > 7
  652. lv_fs_close(gif->fd);
  653. # else
  654. lv_fs_close_to_old(gif->fd);
  655. # endif
  656. }
  657. #endif
  658. }