gifdec.c 19 KB

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