µGFX library fork

gdisp_image_png.c 45KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632
  1. /*
  2. * This file is subject to the terms of the GFX License. If a copy of
  3. * the license was not distributed with this file, you can obtain one at:
  4. *
  5. * http://ugfx.org/license.html
  6. */
  7. #include "../../gfx.h"
  8. #if GFX_USE_GDISP && GDISP_NEED_IMAGE && GDISP_NEED_IMAGE_PNG
  9. #include "gdisp_image_support.h"
  10. /*-----------------------------------------------------------------
  11. * Structure definitions
  12. *---------------------------------------------------------------*/
  13. struct PNG_decode;
  14. // PNG info (comes from the PNG header)
  15. typedef struct PNG_info {
  16. uint8_t flags; // Flags (global)
  17. #define PNG_FLG_HEADERDONE 0x01 // The header has been processed
  18. #define PNG_FLG_TRANSPARENT 0x02 // Has transparency
  19. #define PNG_FLG_INTERLACE 0x04 // Is Interlaced
  20. #define PNG_FLG_BACKGROUND 0x08 // Has a specified background color
  21. uint8_t bitdepth; // 1, 2, 4, 8, 16
  22. uint8_t mode; // The PNG color-mode
  23. #define PNG_COLORMODE_GRAY 0x00 // Grayscale
  24. #define PNG_COLORMODE_RGB 0x02 // RGB
  25. #define PNG_COLORMODE_PALETTE 0x03 // Pallete
  26. #define PNG_COLORMODE_GRAYALPHA 0x04 // Grayscale with Alpha
  27. #define PNG_COLORMODE_RGBA 0x06 // RGBA
  28. uint8_t bpp; // Bits per pixel
  29. uint8_t *cache; // The image cache
  30. unsigned cachesz; // The image cache size
  31. void (*out)(struct PNG_decode *); // The scan line output function
  32. #if GDISP_NEED_IMAGE_PNG_BACKGROUND
  33. color_t bg; // The background color
  34. #endif
  35. #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY
  36. uint16_t trans_r; // Red/grayscale component of the transparent color (PNG_COLORMODE_GRAY and PNG_COLORMODE_RGB only)
  37. uint16_t trans_g; // Green component of the transparent color (PNG_COLORMODE_RGB only)
  38. uint16_t trans_b; // Blue component of the transparent color (PNG_COLORMODE_RGB only)
  39. #endif
  40. #if GDISP_NEED_IMAGE_PNG_PALETTE_124 || GDISP_NEED_IMAGE_PNG_PALETTE_8
  41. uint16_t palsize; // palette size in number of colors
  42. uint8_t *palette; // palette in RGBA RGBA... order (4 bytes per entry - PNG_COLORMODE_PALETTE only)
  43. #endif
  44. } PNG_info;
  45. // Handle the PNG file stream
  46. typedef struct PNG_input {
  47. GFILE * f; // The gfile to retrieve data from
  48. unsigned buflen; // The number of bytes left in the buffer
  49. uint8_t *pbuf; // The pointer to the next byte
  50. uint32_t chunklen; // The number of bytes left in the current PNG chunk
  51. uint32_t chunknext; // The file position of the next PNG chunk
  52. uint8_t buf[GDISP_IMAGE_PNG_FILE_BUFFER_SIZE]; // Must be a minimum of 8 bytes to hold a chunk header
  53. } PNG_input;
  54. // Handle the display output and windowing
  55. typedef struct PNG_output {
  56. GDisplay *g;
  57. coord_t x, y;
  58. coord_t cx, cy;
  59. coord_t sx, sy;
  60. coord_t ix, iy;
  61. unsigned cnt;
  62. pixel_t buf[GDISP_IMAGE_PNG_BLIT_BUFFER_SIZE];
  63. } PNG_output;
  64. // Handle the PNG scan line filter
  65. typedef struct PNG_filter {
  66. unsigned scanbytes;
  67. unsigned bytewidth;
  68. uint8_t *line;
  69. uint8_t *prev;
  70. } PNG_filter;
  71. // Handle the PNG inflate decompression
  72. typedef struct PNG_zTree {
  73. uint16_t table[16]; // Table of code length counts
  74. uint16_t trans[288]; // Code to symbol translation table
  75. } PNG_zTree;
  76. typedef struct PNG_zinflate {
  77. uint8_t data; // The current input stream data byte
  78. uint8_t bits; // The number of bits left in the data byte
  79. uint8_t flags; // Decompression flags
  80. #define PNG_ZFLG_EOF 0x01 // No more input data
  81. #define PNG_ZFLG_FINAL 0x02 // This is the final block
  82. #define PNG_ZFLG_RESUME_MASK 0x0C // The mask of bits for the resume state
  83. #define PNG_ZFLG_RESUME_NEW 0x00 // Process a new block
  84. #define PNG_ZFLG_RESUME_COPY 0x04 // Resume a byte copy from the input stream (length in tmp)
  85. #define PNG_ZFLG_RESUME_INFLATE 0x08 // Resume using the specified symbol (symbol in tmp[0])
  86. #define PNG_ZFLG_RESUME_OFFSET 0x0C // Resume a byte offset copy from the buffer (length and offset in tmp)
  87. unsigned bufpos; // The current buffer output position
  88. unsigned bufend; // The current buffer end position (wraps)
  89. PNG_zTree ltree; // The dynamic length tree
  90. PNG_zTree dtree; // The dynamic distance tree
  91. uint8_t tmp[288+32]; // Temporary space for decoding dynamic trees and other temporary uses
  92. uint8_t buf[GDISP_IMAGE_PNG_Z_BUFFER_SIZE]; // The decoding buffer and sliding window
  93. } PNG_zinflate;
  94. // Put all the decoding structures together.
  95. // Note this is immediately followed by 2 scan lines of uncompressed image data for filtering (dynamic size).
  96. typedef struct PNG_decode {
  97. gdispImage *img;
  98. PNG_info *pinfo;
  99. PNG_input i;
  100. PNG_output o;
  101. PNG_filter f;
  102. PNG_zinflate z;
  103. } PNG_decode;
  104. /*-----------------------------------------------------------------
  105. * PNG input data stream functions
  106. *---------------------------------------------------------------*/
  107. // Input initialization
  108. static void PNG_iInit(PNG_decode *d) {
  109. if (d->pinfo->cache) {
  110. d->i.pbuf = d->pinfo->cache;
  111. d->i.buflen = d->pinfo->cachesz;
  112. d->i.f = 0;
  113. } else {
  114. d->i.buflen = 0;
  115. d->i.chunklen = 0;
  116. d->i.chunknext = 8;
  117. d->i.f = d->img->f;
  118. }
  119. }
  120. // Load the next byte of image data from the PNG file
  121. static bool_t PNG_iLoadData(PNG_decode *d) {
  122. uint32_t sz;
  123. // Is there data still left in the buffer?
  124. if (d->i.buflen)
  125. return TRUE;
  126. // If we are cached then we have no more data
  127. if (!d->i.f)
  128. return FALSE;
  129. // Have we finished the current chunk?
  130. if (!d->i.chunklen) {
  131. while(1) {
  132. // Find a new chunk
  133. gfileSetPos(d->i.f, d->i.chunknext);
  134. if (gfileRead(d->i.f, d->i.buf, 8) != 8)
  135. return FALSE;
  136. // Calculate the chunk length and next chunk
  137. d->i.chunklen = gdispImageGetAlignedBE32(d->i.buf, 0);
  138. d->i.chunknext += d->i.chunklen + 12;
  139. // Process only image data chunks
  140. switch (gdispImageGetAlignedBE32(d->i.buf, 4)) {
  141. case 0x49444154: // "IDAT" - Image Data
  142. if (!d->i.chunklen)
  143. break;
  144. goto gotchunk;
  145. case 0x49454E44: // "IEND" - All done
  146. return FALSE;
  147. }
  148. }
  149. }
  150. gotchunk:
  151. // Try to read data some from the chunk
  152. sz = d->i.chunklen;
  153. if (sz > GDISP_IMAGE_PNG_FILE_BUFFER_SIZE)
  154. sz = GDISP_IMAGE_PNG_FILE_BUFFER_SIZE;
  155. if (gfileRead(d->i.f, d->i.buf, sz) != sz)
  156. return FALSE;
  157. d->i.chunklen -= sz;
  158. d->i.buflen = sz;
  159. d->i.pbuf = d->i.buf;
  160. return TRUE;
  161. }
  162. // Get the last loaded byte of image data from the PNG file
  163. static uint8_t PNG_iGetByte(PNG_decode *d) {
  164. d->i.buflen--;
  165. return *d->i.pbuf++;
  166. }
  167. /*-----------------------------------------------------------------
  168. * Display output and windowing functions
  169. *---------------------------------------------------------------*/
  170. // Initialize the display output window
  171. static void PNG_oInit(PNG_output *o, GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) {
  172. o->g = g;
  173. o->x = x;
  174. o->y = y;
  175. o->cx = cx;
  176. o->cy = cy;
  177. o->sx = sx;
  178. o->sy = sy;
  179. o->ix = o->iy = 0;
  180. o->cnt = 0;
  181. }
  182. // Flush the output buffer to the display
  183. static void PNG_oFlush(PNG_output *o) {
  184. switch(o->cnt) {
  185. case 0: return;
  186. case 1: gdispGDrawPixel(o->g, o->x+o->ix-o->sx, o->y+o->iy-o->sy, o->buf[0]); break;
  187. default: gdispGBlitArea(o->g, o->x+o->ix-o->sx, o->y+o->iy-o->sy, o->cnt, 1, 0, 0, o->cnt, o->buf); break;
  188. }
  189. o->ix += o->cnt;
  190. o->cnt = 0;
  191. }
  192. // Start a new image line
  193. static bool_t PNG_oStartY(PNG_output *o, coord_t y) {
  194. if (y < o->sy || y >= o->sy+o->cy)
  195. return FALSE;
  196. o->ix = 0;
  197. o->iy = y;
  198. return TRUE;
  199. }
  200. // Feed a pixel color to the display buffer
  201. static void PNG_oColor(PNG_output *o, color_t c) {
  202. // Is it in the window
  203. if (o->ix+(coord_t)o->cnt < o->sx || o->ix+(coord_t)o->cnt >= o->sx+o->cx) {
  204. // No - just skip the pixel
  205. PNG_oFlush(o);
  206. o->ix++;
  207. return;
  208. }
  209. // Is the buffer full
  210. if (o->cnt >= sizeof(o->buf)/sizeof(o->buf[0]))
  211. PNG_oFlush(o);
  212. // Save the pixel
  213. o->buf[o->cnt++] = c;
  214. }
  215. #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY || GDISP_NEED_IMAGE_PNG_ALPHACLIFF > 0
  216. // Feed a transparent pixel to the display buffer
  217. static void PNG_oTransparent(PNG_output *o) {
  218. // Flush any existing pixels
  219. PNG_oFlush(o);
  220. // Just skip the pixel
  221. o->ix++;
  222. }
  223. #endif
  224. /*-----------------------------------------------------------------
  225. * Inflate uncompress functions
  226. *---------------------------------------------------------------*/
  227. // Wrap the zInflate buffer position (after increment)
  228. #if (GDISP_IMAGE_PNG_Z_BUFFER_SIZE & ~(GDISP_IMAGE_PNG_Z_BUFFER_SIZE-1)) == GDISP_IMAGE_PNG_Z_BUFFER_SIZE
  229. #define WRAP_ZBUF(x) { x &= GDISP_IMAGE_PNG_Z_BUFFER_SIZE-1; }
  230. #else
  231. #if GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_DIRECT
  232. #warning "PNG: GDISP_IMAGE_PNG_Z_BUFFER_SIZE is more efficient as a power of 2"
  233. #elif GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_MACRO
  234. COMPILER_WARNING("PNG: GDISP_IMAGE_PNG_Z_BUFFER_SIZE is more efficient as a power of 2")
  235. #endif
  236. #define WRAP_ZBUF(x) { if (x >= GDISP_IMAGE_PNG_Z_BUFFER_SIZE) x = 0; }
  237. #endif
  238. // Initialize the inflate decompressor
  239. static void PNG_zInit(PNG_zinflate *z) {
  240. z->bits = 0;
  241. z->flags = 0;
  242. z->bufpos = z->bufend = 0;
  243. }
  244. // Get the inflate header (slightly customized for PNG validity testing)
  245. static bool_t PNG_zGetHeader(PNG_decode *d) {
  246. if (!PNG_iLoadData(d))
  247. return FALSE;
  248. d->z.tmp[0] = PNG_iGetByte(d);
  249. if (!PNG_iLoadData(d))
  250. return FALSE;
  251. d->z.tmp[1] = PNG_iGetByte(d);
  252. if (gdispImageGetAlignedBE16(d->z.tmp, 0) % 31 != 0 // Must be modulo 31, the FCHECK value is made that way
  253. || (d->z.tmp[0] & 0x0F) != 8 || (d->z.tmp[0] & 0x80) // only method 8: inflate 32k sliding window
  254. || (d->z.tmp[1] & 0x20)) // no preset dictionary
  255. return FALSE;
  256. return TRUE;
  257. }
  258. // Get a bit from the input (treated as a LSB first stream)
  259. static unsigned PNG_zGetBit(PNG_decode *d) {
  260. unsigned bit;
  261. // Check for EOF
  262. if ((d->z.flags & PNG_ZFLG_EOF))
  263. return 1;
  264. // Check if data is empty
  265. if (!d->z.bits) {
  266. if (!PNG_iLoadData(d)) {
  267. d->z.flags |= PNG_ZFLG_EOF;
  268. return 1;
  269. }
  270. d->z.data = PNG_iGetByte(d);
  271. d->z.bits = 8;
  272. }
  273. // Get the next bit
  274. d->z.bits--;
  275. bit = d->z.data & 0x01;
  276. d->z.data >>= 1;
  277. return bit;
  278. }
  279. // Get multiple bits from the input (treated as a LSB first stream with bit order retained)
  280. static unsigned PNG_zGetBits(PNG_decode *d, unsigned num) {
  281. unsigned val;
  282. unsigned limit;
  283. unsigned mask;
  284. val = 0;
  285. limit = 1 << num;
  286. for (mask = 1; mask < limit; mask <<= 1)
  287. if (PNG_zGetBit(d))
  288. val += mask;
  289. return val;
  290. }
  291. // Build an inflate dynamic tree using a string of byte lengths
  292. static void PNG_zBuildTree(PNG_zTree *t, const uint8_t *lengths, unsigned num) {
  293. unsigned i, sum;
  294. uint16_t offs[16];
  295. for (i = 0; i < 16; ++i)
  296. t->table[i] = 0;
  297. for (i = 0; i < num; ++i)
  298. t->table[lengths[i]]++;
  299. t->table[0] = 0;
  300. for (sum = 0, i = 0; i < 16; ++i) {
  301. offs[i] = sum;
  302. sum += t->table[i];
  303. }
  304. for (i = 0; i < num; ++i) {
  305. if (lengths[i])
  306. t->trans[offs[lengths[i]]++] = i;
  307. }
  308. }
  309. // Get an inflate decode symbol
  310. static uint16_t PNG_zGetSymbol(PNG_decode *d, PNG_zTree *t) {
  311. int sum, cur;
  312. unsigned len;
  313. sum = cur = 0;
  314. len = 0;
  315. do {
  316. cur <<= 1;
  317. cur += PNG_zGetBit(d);
  318. if ((d->z.flags & PNG_ZFLG_EOF))
  319. return 0;
  320. len++;
  321. sum += t->table[len];
  322. cur -= t->table[len];
  323. } while (cur >= 0);
  324. return t->trans[sum + cur];
  325. }
  326. // Build inflate fixed length and distance trees
  327. static void PNG_zBuildFixedTrees(PNG_decode *d) {
  328. unsigned i;
  329. for (i = 0; i < 16; ++i) d->z.ltree.table[i] = 0;
  330. d->z.ltree.table[7] = 24;
  331. d->z.ltree.table[8] = 152;
  332. d->z.ltree.table[9] = 112;
  333. for (i = 0; i < 24; ++i) d->z.ltree.trans[i] = 256 + i;
  334. for (i = 0; i < 144; ++i) d->z.ltree.trans[24 + i] = i;
  335. for (i = 0; i < 8; ++i) d->z.ltree.trans[24 + 144 + i] = 280 + i;
  336. for (i = 0; i < 112; ++i) d->z.ltree.trans[24 + 144 + 8 + i] = 144 + i;
  337. for (i = 0; i < 16; ++i) d->z.dtree.table[i] = 0;
  338. d->z.dtree.table[5] = 32;
  339. for (i = 0; i < 32; ++i) d->z.dtree.trans[i] = i;
  340. for ( ; i < 288; ++i) d->z.dtree.trans[i] = 0;
  341. }
  342. // Build inflate dynamic length and distance trees
  343. static bool_t PNG_zDecodeTrees(PNG_decode *d) {
  344. static const uint8_t IndexLookup[19] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
  345. unsigned hlit, hdist, hclen;
  346. unsigned i, num;
  347. uint16_t symbol;
  348. uint8_t val;
  349. hlit = PNG_zGetBits(d, 5) + 257; // 257 - 286
  350. hdist = PNG_zGetBits(d, 5) + 1; // 1 - 32
  351. hclen = PNG_zGetBits(d, 4) + 4; // 4 - 19
  352. if ((d->z.flags & PNG_ZFLG_EOF))
  353. return FALSE;
  354. for (i = 0; i < 19; ++i)
  355. d->z.tmp[i] = 0;
  356. // Get code lengths for the code length alphabet
  357. for (i = 0; i < hclen; ++i)
  358. d->z.tmp[IndexLookup[i]] = PNG_zGetBits(d, 3);
  359. if ((d->z.flags & PNG_ZFLG_EOF))
  360. return FALSE;
  361. // Build the code length tree
  362. PNG_zBuildTree(&d->z.ltree, d->z.tmp, 19);
  363. // Decode code lengths
  364. for (num = 0; num < hlit + hdist; ) {
  365. symbol = PNG_zGetSymbol(d, &d->z.ltree);
  366. if ((d->z.flags & PNG_ZFLG_EOF))
  367. return FALSE;
  368. switch(symbol) {
  369. case 16: // Copy the previous code length 3-6 times
  370. val = d->z.tmp[num - 1];
  371. for (i = PNG_zGetBits(d, 2) + 3; i; i--)
  372. d->z.tmp[num++] = val;
  373. break;
  374. case 17: // Repeat code length 0 for 3-10 times
  375. for (i = PNG_zGetBits(d, 3) + 3; i; i--)
  376. d->z.tmp[num++] = 0;
  377. break;
  378. case 18: // Repeat code length 0 for 11-138 times
  379. for (i = PNG_zGetBits(d, 7) + 11; i; i--)
  380. d->z.tmp[num++] = 0;
  381. break;
  382. default: // symbols 0-15 are the actual code lengths
  383. d->z.tmp[num++] = symbol;
  384. break;
  385. }
  386. }
  387. // Build the trees
  388. PNG_zBuildTree(&d->z.ltree, d->z.tmp, hlit);
  389. PNG_zBuildTree(&d->z.dtree, d->z.tmp + hlit, hdist);
  390. return TRUE;
  391. }
  392. // Copy bytes from the input stream. Completing the copy completes the block.
  393. static bool_t PNG_zCopyInput(PNG_decode *d, unsigned length) {
  394. // Copy the block
  395. while(length--) {
  396. if (!PNG_iLoadData(d)) { // EOF?
  397. d->z.flags |= PNG_ZFLG_EOF;
  398. return FALSE;
  399. }
  400. d->z.buf[d->z.bufend++] = PNG_iGetByte(d);
  401. WRAP_ZBUF(d->z.bufend);
  402. if (d->z.bufend == d->z.bufpos) { // Buffer full?
  403. d->z.flags = (d->z.flags & ~PNG_ZFLG_RESUME_MASK) | PNG_ZFLG_RESUME_COPY;
  404. ((unsigned *)d->z.tmp)[0] = length;
  405. return TRUE;
  406. }
  407. }
  408. // The block is done
  409. d->z.flags = (d->z.flags & ~PNG_ZFLG_RESUME_MASK) | PNG_ZFLG_RESUME_NEW;
  410. return TRUE;
  411. }
  412. // Copy an uncompressed inflate block into the output
  413. static bool_t PNG_zUncompressedBlock(PNG_decode *d) {
  414. unsigned length;
  415. // This block works on byte boundaries
  416. d->z.bits = 0;
  417. // Get 4 byte header
  418. for (length = 0; length < 4; length++) {
  419. if (!PNG_iLoadData(d)) { // EOF?
  420. d->z.flags |= PNG_ZFLG_EOF;
  421. return FALSE;
  422. }
  423. d->z.tmp[length] = PNG_iGetByte(d);
  424. }
  425. // Get length
  426. length = gdispImageGetAlignedLE16(d->z.tmp, 0);
  427. // Check length
  428. if ((uint16_t)length != (uint16_t)~gdispImageGetAlignedLE16(d->z.tmp, 2)) {
  429. d->z.flags |= PNG_ZFLG_EOF;
  430. return FALSE;
  431. }
  432. // Copy the block
  433. return PNG_zCopyInput(d, length);
  434. }
  435. // Inflate a compressed inflate block into the output
  436. static bool_t PNG_zInflateBlock(PNG_decode *d) {
  437. static const uint8_t lbits[30] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 6 };
  438. static const uint16_t lbase[30] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 323 };
  439. static const uint8_t dbits[30] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 };
  440. static const uint16_t dbase[30] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 };
  441. unsigned length, dist, offset;
  442. uint16_t symbol;
  443. while(1) {
  444. symbol = PNG_zGetSymbol(d, &d->z.ltree); // EOF?
  445. if ((d->z.flags & PNG_ZFLG_EOF))
  446. goto iserror;
  447. // Is the block done?
  448. if (symbol == 256) {
  449. d->z.flags = (d->z.flags & ~PNG_ZFLG_RESUME_MASK) | PNG_ZFLG_RESUME_NEW;
  450. return TRUE;
  451. }
  452. if (symbol < 256) {
  453. // The symbol is the data
  454. d->z.buf[d->z.bufend++] = (uint8_t)symbol;
  455. WRAP_ZBUF(d->z.bufend);
  456. if (d->z.bufend == d->z.bufpos) { // Buffer full?
  457. d->z.flags = (d->z.flags & ~PNG_ZFLG_RESUME_MASK) | PNG_ZFLG_RESUME_INFLATE;
  458. return TRUE;
  459. }
  460. continue;
  461. }
  462. // Shift the symbol down into an index
  463. symbol -= 257;
  464. if (symbol >= sizeof(lbits)) // Bad index?
  465. goto iserror;
  466. // Get more bits from length code
  467. length = PNG_zGetBits(d, lbits[symbol]) + lbase[symbol];
  468. if ((d->z.flags & PNG_ZFLG_EOF) || length >= GDISP_IMAGE_PNG_Z_BUFFER_SIZE) // Bad length?
  469. goto iserror;
  470. // Get the distance code
  471. dist = PNG_zGetSymbol(d, &d->z.dtree); // Bad distance?
  472. if ((d->z.flags & PNG_ZFLG_EOF) || dist >= sizeof(dbits))
  473. goto iserror;
  474. // Get more bits from distance code
  475. offset = PNG_zGetBits(d, dbits[dist]) + dbase[dist];
  476. if ((d->z.flags & PNG_ZFLG_EOF) || offset >= GDISP_IMAGE_PNG_Z_BUFFER_SIZE) // Bad offset?
  477. goto iserror;
  478. // Work out the source buffer position allowing for wrapping
  479. if (offset > d->z.bufend)
  480. offset -= GDISP_IMAGE_PNG_Z_BUFFER_SIZE;
  481. offset = d->z.bufend - offset;
  482. // Copy the matching string
  483. while (length--) {
  484. d->z.buf[d->z.bufend++] = d->z.buf[offset++];
  485. WRAP_ZBUF(d->z.bufend);
  486. WRAP_ZBUF(offset);
  487. if (d->z.bufend == d->z.bufpos) { // Buffer full?
  488. d->z.flags = (d->z.flags & ~PNG_ZFLG_RESUME_MASK) | PNG_ZFLG_RESUME_OFFSET;
  489. ((unsigned *)d->z.tmp)[0] = length;
  490. ((unsigned *)d->z.tmp)[1] = offset;
  491. return TRUE;
  492. }
  493. }
  494. }
  495. iserror:
  496. d->z.flags |= PNG_ZFLG_EOF;
  497. return FALSE;
  498. }
  499. // Start a new uncompressed/inflate block
  500. static bool_t PNG_zStartBlock(PNG_decode *d) {
  501. // Check for previous error, EOF or no more blocks
  502. if ((d->z.flags & (PNG_ZFLG_EOF|PNG_ZFLG_FINAL)))
  503. return FALSE;
  504. // Is this the final inflate block?
  505. if (PNG_zGetBit(d))
  506. d->z.flags |= PNG_ZFLG_FINAL;
  507. // Get the block type
  508. switch (PNG_zGetBits(d, 2)) {
  509. case 0: // Decompress uncompressed block
  510. if (!PNG_zUncompressedBlock(d))
  511. return FALSE;
  512. break;
  513. case 1: // Decompress block with fixed huffman trees
  514. PNG_zBuildFixedTrees(d);
  515. if (!PNG_zInflateBlock(d))
  516. return FALSE;
  517. break;
  518. case 2: // Decompress block with dynamic huffman trees
  519. if (!PNG_zDecodeTrees(d))
  520. return FALSE;
  521. if (!PNG_zInflateBlock(d))
  522. return FALSE;
  523. break;
  524. default: // Bad block type
  525. // Mark it as an error
  526. d->z.flags |= PNG_ZFLG_EOF;
  527. return FALSE;
  528. }
  529. return TRUE;
  530. }
  531. // Resume an offset copy
  532. static bool_t PNG_zResumeOffset(PNG_decode *d, unsigned length, unsigned offset) {
  533. // Copy the matching string
  534. while (length--) {
  535. d->z.buf[d->z.bufend++] = d->z.buf[offset++];
  536. WRAP_ZBUF(d->z.bufend);
  537. WRAP_ZBUF(offset);
  538. if (d->z.bufend == d->z.bufpos) { // Buffer full?
  539. d->z.flags = (d->z.flags & ~PNG_ZFLG_RESUME_MASK) | PNG_ZFLG_RESUME_OFFSET;
  540. ((unsigned *)d->z.tmp)[0] = length;
  541. ((unsigned *)d->z.tmp)[1] = offset;
  542. return TRUE;
  543. }
  544. }
  545. return PNG_zInflateBlock(d);
  546. }
  547. // Get a fully decompressed byte from the inflate data stream
  548. static uint8_t PNG_zGetByte(PNG_decode *d) {
  549. uint8_t data;
  550. // Do we have any data in the buffers
  551. while (d->z.bufpos == d->z.bufend) {
  552. // No, get some more data
  553. switch((d->z.flags & PNG_ZFLG_RESUME_MASK)) {
  554. case PNG_ZFLG_RESUME_NEW: // Start a new inflate block
  555. if (!PNG_zStartBlock(d))
  556. return 0xFF;
  557. break;
  558. case PNG_ZFLG_RESUME_COPY: // Resume uncompressed block copy for length bytes
  559. if (!PNG_zCopyInput(d, ((unsigned *)d->z.tmp)[0]))
  560. return 0xFF;
  561. break;
  562. case PNG_ZFLG_RESUME_INFLATE: // Resume compressed block
  563. if (!PNG_zInflateBlock(d))
  564. return 0xFF;
  565. break;
  566. case PNG_ZFLG_RESUME_OFFSET: // Resume compressed block using offset copy for length bytes
  567. if (!PNG_zResumeOffset(d, ((unsigned *)d->z.tmp)[0], ((unsigned *)d->z.tmp)[1]))
  568. return 0xFF;
  569. break;
  570. }
  571. // Check for no data being provided
  572. // A resume code means the buffer is completely full so the test must be skipped
  573. if ((d->z.flags & PNG_ZFLG_RESUME_MASK) != PNG_ZFLG_RESUME_NEW)
  574. break;
  575. }
  576. // Get the next data byte
  577. data = d->z.buf[d->z.bufpos++];
  578. WRAP_ZBUF(d->z.bufpos);
  579. return data;
  580. }
  581. /*-----------------------------------------------------------------
  582. * Scan-line filter functions
  583. *---------------------------------------------------------------*/
  584. // Initialise the scan-line engine
  585. static void PNG_fInit(PNG_filter *f, uint8_t *buf, unsigned bytewidth, unsigned scanbytes) {
  586. f->scanbytes = scanbytes;
  587. f->bytewidth = bytewidth;
  588. f->line = buf;
  589. f->prev = 0;
  590. }
  591. // Get ready for the next scan-line
  592. static void PNG_fNext(PNG_filter *f) {
  593. if (f->prev && f->line > f->prev) {
  594. f->line = f->prev;
  595. f->prev += f->scanbytes;
  596. } else {
  597. f->prev = f->line;
  598. f->line += f->scanbytes;
  599. }
  600. }
  601. // Predictor function for filter0 mode 4
  602. static uint8_t PNG_fCalcPath(uint16_t a, uint16_t b, uint16_t c) {
  603. uint16_t pa = b > c ? (b - c) : (c - b);
  604. uint16_t pb = a > c ? (a - c) : (c - a);
  605. uint16_t pc = a + b > c + c ? (a + b - c - c) : (c + c - a - b);
  606. if (pc < pa && pc < pb)
  607. return (uint8_t)c;
  608. if (pb < pa)
  609. return (uint8_t)b;
  610. return (uint8_t)a;
  611. }
  612. // Scan-line filter type 0
  613. static bool_t PNG_unfilter_type0(PNG_decode *d) { // PNG filter method 0
  614. uint8_t ft;
  615. unsigned i;
  616. // Get the filter type and check for validity (eg not EOF)
  617. ft = PNG_zGetByte(d);
  618. if (ft > 0x04)
  619. return FALSE;
  620. // Uncompress the scan line
  621. for(i = 0; i < d->f.scanbytes; i++)
  622. d->f.line[i] = PNG_zGetByte(d);
  623. // Adjust the scan line based on the filter type
  624. // 0 = no adjustment
  625. switch(ft) {
  626. case 1:
  627. for(i = d->f.bytewidth; i < d->f.scanbytes; i++)
  628. d->f.line[i] += d->f.line[i - d->f.bytewidth];
  629. break;
  630. case 2:
  631. if (d->f.prev) {
  632. for(i = 0; i < d->f.scanbytes; i++)
  633. d->f.line[i] += d->f.prev[i];
  634. }
  635. break;
  636. case 3:
  637. if (d->f.prev) {
  638. for(i = 0; i < d->f.bytewidth; i++)
  639. d->f.line[i] += d->f.prev[i] / 2;
  640. for( ; i < d->f.scanbytes; i++)
  641. d->f.line[i] += (d->f.line[i - d->f.bytewidth] + d->f.prev[i]) / 2;
  642. } else {
  643. for(i = d->f.bytewidth; i < d->f.scanbytes; i++)
  644. d->f.line[i] += d->f.line[i - d->f.bytewidth] / 2;
  645. }
  646. break;
  647. case 4:
  648. if (d->f.prev) {
  649. for(i = 0; i < d->f.bytewidth; i++)
  650. d->f.line[i] += d->f.prev[i]; // PNG_fCalcPath(0, val, 0) is always val
  651. for( ; i < d->f.scanbytes; i++)
  652. d->f.line[i] += PNG_fCalcPath(d->f.line[i - d->f.bytewidth], d->f.prev[i], d->f.prev[i - d->f.bytewidth]);
  653. } else {
  654. for(i = d->f.bytewidth; i < d->f.scanbytes; i++)
  655. d->f.line[i] += d->f.line[i - d->f.bytewidth]; // PNG_fCalcPath(val, 0, 0) is always val
  656. }
  657. break;
  658. }
  659. return TRUE;
  660. }
  661. /*-----------------------------------------------------------------
  662. * Scan-line output and color conversion functions
  663. *---------------------------------------------------------------*/
  664. #if GDISP_NEED_IMAGE_PNG_GRAYSCALE_124
  665. static void PNG_OutGRAY124(PNG_decode *d) {
  666. unsigned i;
  667. PNG_info *pinfo;
  668. uint8_t px;
  669. uint8_t bits;
  670. pinfo = d->pinfo;
  671. for(i = 0; i < d->f.scanbytes; i++) {
  672. for(bits = 8; bits; bits -= pinfo->bitdepth) {
  673. px = (d->f.line[i] >> (bits - pinfo->bitdepth)) & ((1U << pinfo->bitdepth)-1);
  674. #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY
  675. if ((pinfo->flags & PNG_FLG_TRANSPARENT) && (uint16_t)px == pinfo->trans_r) {
  676. #if GDISP_NEED_IMAGE_PNG_BACKGROUND
  677. if ((pinfo->flags & PNG_FLG_BACKGROUND)) {
  678. PNG_oColor(&d->o, pinfo->bg);
  679. continue;
  680. }
  681. #endif
  682. PNG_oTransparent(&d->o);
  683. continue;
  684. }
  685. #endif
  686. px = px << (8-pinfo->bitdepth);
  687. if (px >= 0x80) px += ((1U << (8-pinfo->bitdepth))-1);
  688. PNG_oColor(&d->o, LUMA2COLOR(px));
  689. }
  690. }
  691. }
  692. #endif
  693. #if GDISP_NEED_IMAGE_PNG_GRAYSCALE_8
  694. static void PNG_OutGRAY8(PNG_decode *d) {
  695. unsigned i;
  696. uint8_t px;
  697. #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY
  698. PNG_info *pinfo = d->pinfo;
  699. #endif
  700. for(i = 0; i < d->f.scanbytes; i++) {
  701. px = d->f.line[i];
  702. #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY
  703. if ((pinfo->flags & PNG_FLG_TRANSPARENT) && (uint16_t)px == pinfo->trans_r) {
  704. #if GDISP_NEED_IMAGE_PNG_BACKGROUND
  705. if ((pinfo->flags & PNG_FLG_BACKGROUND)) {
  706. PNG_oColor(&d->o, pinfo->bg);
  707. continue;
  708. }
  709. #endif
  710. PNG_oTransparent(&d->o);
  711. continue;
  712. }
  713. #endif
  714. PNG_oColor(&d->o, LUMA2COLOR(px));
  715. }
  716. }
  717. #endif
  718. #if GDISP_NEED_IMAGE_PNG_GRAYSCALE_16
  719. static void PNG_OutGRAY16(PNG_decode *d) {
  720. unsigned i;
  721. uint8_t px;
  722. #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY
  723. PNG_info *pinfo = d->pinfo;
  724. #endif
  725. for(i = 0; i < d->f.scanbytes; i+=2) {
  726. px = d->f.line[i];
  727. #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY
  728. if ((pinfo->flags & PNG_FLG_TRANSPARENT) && gdispImageGetBE16(d->f.line, i) == pinfo->trans_r) {
  729. #if GDISP_NEED_IMAGE_PNG_BACKGROUND
  730. if ((pinfo->flags & PNG_FLG_BACKGROUND)) {
  731. PNG_oColor(&d->o, pinfo->bg);
  732. continue;
  733. }
  734. #endif
  735. PNG_oTransparent(&d->o);
  736. continue;
  737. }
  738. #endif
  739. PNG_oColor(&d->o, LUMA2COLOR(px));
  740. }
  741. }
  742. #endif
  743. #if GDISP_NEED_IMAGE_PNG_RGB_8
  744. static void PNG_OutRGB8(PNG_decode *d) {
  745. unsigned i;
  746. #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY
  747. PNG_info *pinfo = d->pinfo;
  748. #endif
  749. for(i = 0; i < d->f.scanbytes; i+=3) {
  750. #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY
  751. if ((pinfo->flags & PNG_FLG_TRANSPARENT)
  752. && (uint16_t)d->f.line[i+0] == pinfo->trans_r
  753. && (uint16_t)d->f.line[i+1] == pinfo->trans_g
  754. && (uint16_t)d->f.line[i+2] == pinfo->trans_b) {
  755. #if GDISP_NEED_IMAGE_PNG_BACKGROUND
  756. if ((pinfo->flags & PNG_FLG_BACKGROUND)) {
  757. PNG_oColor(&d->o, pinfo->bg);
  758. continue;
  759. }
  760. #endif
  761. PNG_oTransparent(&d->o);
  762. continue;
  763. }
  764. #endif
  765. PNG_oColor(&d->o, RGB2COLOR(d->f.line[i+0], d->f.line[i+1], d->f.line[i+2]));
  766. }
  767. }
  768. #endif
  769. #if GDISP_NEED_IMAGE_PNG_RGB_16
  770. static void PNG_OutRGB16(PNG_decode *d) {
  771. unsigned i;
  772. #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY
  773. PNG_info *pinfo = d->pinfo;
  774. #endif
  775. for(i = 0; i < d->f.scanbytes; i+=6) {
  776. #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY
  777. if ((pinfo->flags & PNG_FLG_TRANSPARENT)
  778. && gdispImageGetBE16(d->f.line, i+0) == pinfo->trans_r
  779. && gdispImageGetBE16(d->f.line, i+2) == pinfo->trans_g
  780. && gdispImageGetBE16(d->f.line, i+4) == pinfo->trans_b) {
  781. #if GDISP_NEED_IMAGE_PNG_BACKGROUND
  782. if ((pinfo->flags & PNG_FLG_BACKGROUND)) {
  783. PNG_oColor(&d->o, pinfo->bg);
  784. continue;
  785. }
  786. #endif
  787. PNG_oTransparent(&d->o);
  788. continue;
  789. }
  790. #endif
  791. PNG_oColor(&d->o, RGB2COLOR(d->f.line[i+0], d->f.line[i+2], d->f.line[i+4]));
  792. }
  793. }
  794. #endif
  795. #if GDISP_NEED_IMAGE_PNG_PALETTE_124
  796. static void PNG_OutPAL124(PNG_decode *d) {
  797. unsigned i;
  798. PNG_info *pinfo;
  799. unsigned idx;
  800. uint8_t bits;
  801. pinfo = d->pinfo;
  802. for(i = 0; i < d->f.scanbytes; i++) {
  803. for(bits = 8; bits; bits -= pinfo->bitdepth) {
  804. idx = (d->f.line[i] >> (bits - pinfo->bitdepth)) & ((1U << pinfo->bitdepth)-1);
  805. if ((uint16_t)idx >= pinfo->palsize) {
  806. PNG_oColor(&d->o, RGB2COLOR(0, 0, 0));
  807. continue;
  808. }
  809. idx *= 4;
  810. #define pix_color RGB2COLOR(pinfo->palette[idx], pinfo->palette[idx+1], pinfo->palette[idx+2])
  811. #define pix_alpha pinfo->palette[idx+3]
  812. #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY
  813. #if GDISP_NEED_IMAGE_PNG_BACKGROUND
  814. if (pix_alpha != 255 && (pinfo->flags & PNG_FLG_BACKGROUND)) {
  815. PNG_oColor(&d->o, gdispBlendColor(pix_color, pinfo->bg, pix_alpha));
  816. continue;
  817. }
  818. #endif
  819. #if GDISP_NEED_IMAGE_PNG_ALPHACLIFF > 0
  820. if (pix_alpha < GDISP_NEED_IMAGE_PNG_ALPHACLIFF) {
  821. PNG_oTransparent(&d->o);
  822. continue;
  823. }
  824. #endif
  825. #endif
  826. PNG_oColor(&d->o, pix_color);
  827. #undef pix_color
  828. #undef pix_alpha
  829. }
  830. }
  831. }
  832. #endif
  833. #if GDISP_NEED_IMAGE_PNG_PALETTE_8
  834. static void PNG_OutPAL8(PNG_decode *d) {
  835. unsigned i;
  836. PNG_info *pinfo;
  837. unsigned idx;
  838. pinfo = d->pinfo;
  839. for(i = 0; i < d->f.scanbytes; i++) {
  840. idx = (unsigned)d->f.line[i];
  841. if ((uint16_t)idx >= pinfo->palsize) {
  842. PNG_oColor(&d->o, RGB2COLOR(0, 0, 0));
  843. continue;
  844. }
  845. idx *= 4;
  846. #define pix_color RGB2COLOR(pinfo->palette[idx], pinfo->palette[idx+1], pinfo->palette[idx+2])
  847. #define pix_alpha pinfo->palette[idx+3]
  848. #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY
  849. #if GDISP_NEED_IMAGE_PNG_BACKGROUND
  850. if (pix_alpha != 255 && (pinfo->flags & PNG_FLG_BACKGROUND)) {
  851. PNG_oColor(&d->o, gdispBlendColor(pix_color, pinfo->bg, pix_alpha));
  852. continue;
  853. }
  854. #endif
  855. #if GDISP_NEED_IMAGE_PNG_ALPHACLIFF > 0
  856. if (pix_alpha < GDISP_NEED_IMAGE_PNG_ALPHACLIFF) {
  857. PNG_oTransparent(&d->o);
  858. continue;
  859. }
  860. #endif
  861. #endif
  862. PNG_oColor(&d->o, pix_color);
  863. #undef pix_color
  864. #undef pix_alpha
  865. }
  866. }
  867. #endif
  868. #if GDISP_NEED_IMAGE_PNG_GRAYALPHA_8
  869. static void PNG_OutGRAYA8(PNG_decode *d) {
  870. unsigned i;
  871. #if GDISP_NEED_IMAGE_PNG_BACKGROUND
  872. PNG_info *pinfo = d->pinfo;
  873. #endif
  874. for(i = 0; i < d->f.scanbytes; i+=2) {
  875. #define pix_color LUMA2COLOR(d->f.line[i])
  876. #define pix_alpha d->f.line[i+1]
  877. #if GDISP_NEED_IMAGE_PNG_BACKGROUND
  878. if (pix_alpha != 255 && (pinfo->flags & PNG_FLG_BACKGROUND)) {
  879. PNG_oColor(&d->o, gdispBlendColor(pix_color, pinfo->bg, pix_alpha));
  880. continue;
  881. }
  882. #endif
  883. #if GDISP_NEED_IMAGE_PNG_ALPHACLIFF > 0
  884. if (pix_alpha < GDISP_NEED_IMAGE_PNG_ALPHACLIFF) {
  885. PNG_oTransparent(&d->o);
  886. continue;
  887. }
  888. #endif
  889. PNG_oColor(&d->o, pix_color);
  890. #undef pix_color
  891. #undef pix_alpha
  892. }
  893. }
  894. #endif
  895. #if GDISP_NEED_IMAGE_PNG_GRAYALPHA_16
  896. static void PNG_OutGRAYA16(PNG_decode *d) {
  897. unsigned i;
  898. #if GDISP_NEED_IMAGE_PNG_BACKGROUND
  899. PNG_info *pinfo = d->pinfo;
  900. #endif
  901. for(i = 0; i < d->f.scanbytes; i+=4) {
  902. #define pix_color LUMA2COLOR(d->f.line[i])
  903. #define pix_alpha d->f.line[i+2]
  904. #if GDISP_NEED_IMAGE_PNG_BACKGROUND
  905. if (pix_alpha != 255 && (pinfo->flags & PNG_FLG_BACKGROUND)) {
  906. PNG_oColor(&d->o, gdispBlendColor(pix_color, pinfo->bg, pix_alpha));
  907. continue;
  908. }
  909. #endif
  910. #if GDISP_NEED_IMAGE_PNG_ALPHACLIFF > 0
  911. if (pix_alpha < GDISP_NEED_IMAGE_PNG_ALPHACLIFF) {
  912. PNG_oTransparent(&d->o);
  913. continue;
  914. }
  915. #endif
  916. PNG_oColor(&d->o, pix_color);
  917. #undef pix_color
  918. #undef pix_alpha
  919. }
  920. }
  921. #endif
  922. #if GDISP_NEED_IMAGE_PNG_RGBALPHA_8
  923. static void PNG_OutRGBA8(PNG_decode *d) {
  924. unsigned i;
  925. #if GDISP_NEED_IMAGE_PNG_BACKGROUND
  926. PNG_info *pinfo = d->pinfo;
  927. #endif
  928. for(i = 0; i < d->f.scanbytes; i+=4) {
  929. #define pix_color RGB2COLOR(d->f.line[i+0], d->f.line[i+1], d->f.line[i+2])
  930. #define pix_alpha d->f.line[i+3]
  931. #if GDISP_NEED_IMAGE_PNG_BACKGROUND
  932. if (pix_alpha != 255 && (pinfo->flags & PNG_FLG_BACKGROUND)) {
  933. PNG_oColor(&d->o, gdispBlendColor(pix_color, pinfo->bg, pix_alpha));
  934. continue;
  935. }
  936. #endif
  937. #if GDISP_NEED_IMAGE_PNG_ALPHACLIFF > 0
  938. if (pix_alpha < GDISP_NEED_IMAGE_PNG_ALPHACLIFF) {
  939. PNG_oTransparent(&d->o);
  940. continue;
  941. }
  942. #endif
  943. PNG_oColor(&d->o, pix_color);
  944. #undef pix_color
  945. #undef pix_alpha
  946. }
  947. }
  948. #endif
  949. #if GDISP_NEED_IMAGE_PNG_RGBALPHA_16
  950. static void PNG_OutRGBA16(PNG_decode *d) {
  951. unsigned i;
  952. #if GDISP_NEED_IMAGE_PNG_BACKGROUND
  953. PNG_info *pinfo = d->pinfo;
  954. #endif
  955. for(i = 0; i < d->f.scanbytes; i+=8) {
  956. #define pix_color RGB2COLOR(d->f.line[i+0], d->f.line[i+2], d->f.line[i+4])
  957. #define pix_alpha d->f.line[i+6]
  958. #if GDISP_NEED_IMAGE_PNG_BACKGROUND
  959. if (pix_alpha != 255 && (pinfo->flags & PNG_FLG_BACKGROUND)) {
  960. PNG_oColor(&d->o, gdispBlendColor(pix_color, pinfo->bg, pix_alpha));
  961. continue;
  962. }
  963. #endif
  964. #if GDISP_NEED_IMAGE_PNG_ALPHACLIFF > 0
  965. if (pix_alpha < GDISP_NEED_IMAGE_PNG_ALPHACLIFF) {
  966. PNG_oTransparent(&d->o);
  967. continue;
  968. }
  969. #endif
  970. PNG_oColor(&d->o, pix_color);
  971. #undef pix_color
  972. #undef pix_alpha
  973. }
  974. }
  975. #endif
  976. /*-----------------------------------------------------------------
  977. * Public PNG functions
  978. *---------------------------------------------------------------*/
  979. void gdispImageClose_PNG(gdispImage *img) {
  980. PNG_info *pinfo;
  981. pinfo = (PNG_info *)img->priv;
  982. if (pinfo) {
  983. if (pinfo->palette)
  984. gdispImageFree(img, (void *)pinfo->palette, pinfo->palsize*4);
  985. if (pinfo->cache)
  986. gdispImageFree(img, (void *)pinfo->cache, pinfo->cachesz);
  987. gdispImageFree(img, (void *)pinfo, sizeof(PNG_info));
  988. img->priv = 0;
  989. }
  990. }
  991. gdispImageError gdispImageOpen_PNG(gdispImage *img) {
  992. PNG_info *pinfo;
  993. uint32_t pos;
  994. uint32_t len;
  995. uint8_t buf[13];
  996. /* Read the file identifier */
  997. if (gfileRead(img->f, buf, 8) != 8)
  998. return GDISP_IMAGE_ERR_BADFORMAT; // It can't be us
  999. // Check the PNG signature
  1000. if(buf[0] != 137 || buf[1] != 80 || buf[2] != 78 || buf[3] != 71 || buf[4] != 13 || buf[5] != 10 || buf[6] != 26 || buf[7] != 10)
  1001. return GDISP_IMAGE_ERR_BADFORMAT; // It can't be us
  1002. /* We know we are a PNG format image */
  1003. img->flags = 0;
  1004. img->priv = 0;
  1005. img->type = GDISP_IMAGE_TYPE_PNG;
  1006. /* Allocate our private area */
  1007. if (!(img->priv = gdispImageAlloc(img, sizeof(PNG_info))))
  1008. return GDISP_IMAGE_ERR_NOMEMORY;
  1009. /* Initialise the essential bits in the private area */
  1010. pinfo = (PNG_info *)img->priv;
  1011. pinfo->flags = 0;
  1012. pinfo->cache = 0;
  1013. pinfo->trans_r = 0;
  1014. pinfo->trans_g = 0;
  1015. pinfo->trans_b = 0;
  1016. #if GDISP_NEED_IMAGE_PNG_PALETTE_124 || GDISP_NEED_IMAGE_PNG_PALETTE_8
  1017. pinfo->palsize = 0;
  1018. pinfo->palette = 0;
  1019. #endif
  1020. // Cycle the chunks to get other information
  1021. for(pos = 8; ; pos += len+12, gfileSetPos(img->f, pos)) {
  1022. // Get a chunk header
  1023. if (gfileRead(img->f, buf, 8) != 8)
  1024. goto exit_baddata;
  1025. // Calculate the chunk length
  1026. len = gdispImageGetAlignedBE32(buf, 0);
  1027. // Process the interesting information chunks
  1028. switch (gdispImageGetAlignedBE32(buf, 4)) {
  1029. case 0x49484452: // "IHDR" - Header block
  1030. // Check if the header is already done
  1031. if ((pinfo->flags & PNG_FLG_HEADERDONE))
  1032. goto exit_baddata;
  1033. // Read the image parameters
  1034. if (len < 13 || gfileRead(img->f, buf, 13) != 13)
  1035. goto exit_baddata;
  1036. img->width = gdispImageGetAlignedBE16(buf, 2);
  1037. img->height = gdispImageGetAlignedBE16(buf, 6);
  1038. pinfo->bitdepth = gdispImageGetVar(uint8_t, buf, 8);
  1039. pinfo->mode = gdispImageGetVar(uint8_t, buf, 9);
  1040. if (gdispImageGetVar(uint8_t, buf, 12)) {
  1041. pinfo->flags |= PNG_FLG_INTERLACE;
  1042. #if !GDISP_NEED_IMAGE_PNG_INTERLACED
  1043. goto exit_unsupported;
  1044. #endif
  1045. }
  1046. // Check width and height, filter, compression and interlacing
  1047. if (gdispImageGetVar(uint16_t, buf, 0) != 0 || img->width <= 0 // width
  1048. || gdispImageGetVar(uint16_t, buf, 4) != 0 || img->height <= 0 // height
  1049. || gdispImageGetVar(uint8_t, buf, 10) != 0 // compression
  1050. || gdispImageGetVar(uint8_t, buf, 11) != 0 // filter
  1051. || gdispImageGetVar(uint8_t, buf, 12) > 1 // interlace
  1052. )
  1053. goto exit_unsupported;
  1054. // Check mode, bitdepth and calculate bits per pixel
  1055. switch(pinfo->mode) {
  1056. #if GDISP_NEED_IMAGE_PNG_GRAYSCALE_124 || GDISP_NEED_IMAGE_PNG_GRAYSCALE_8 || GDISP_NEED_IMAGE_PNG_GRAYSCALE_16
  1057. case PNG_COLORMODE_GRAY:
  1058. switch(pinfo->bitdepth) {
  1059. #if GDISP_NEED_IMAGE_PNG_GRAYSCALE_124
  1060. case 1:
  1061. case 2:
  1062. case 4: pinfo->out = PNG_OutGRAY124; break;
  1063. #endif
  1064. #if GDISP_NEED_IMAGE_PNG_GRAYSCALE_8
  1065. case 8: pinfo->out = PNG_OutGRAY8; break;
  1066. #endif
  1067. #if GDISP_NEED_IMAGE_PNG_GRAYSCALE_16
  1068. case 16: pinfo->out = PNG_OutGRAY16; break;
  1069. #endif
  1070. default: goto exit_unsupported;
  1071. }
  1072. pinfo->bpp = pinfo->bitdepth;
  1073. break;
  1074. #endif
  1075. #if GDISP_NEED_IMAGE_PNG_RGB_8 || GDISP_NEED_IMAGE_PNG_RGB_16
  1076. case PNG_COLORMODE_RGB:
  1077. switch(pinfo->bitdepth) {
  1078. #if GDISP_NEED_IMAGE_PNG_RGB_8
  1079. case 8: pinfo->out = PNG_OutRGB8; break;
  1080. #endif
  1081. #if GDISP_NEED_IMAGE_PNG_RGB_16
  1082. case 16: pinfo->out = PNG_OutRGB16; break;
  1083. #endif
  1084. default: goto exit_unsupported;
  1085. }
  1086. pinfo->bpp = pinfo->bitdepth * 3;
  1087. break;
  1088. #endif
  1089. #if GDISP_NEED_IMAGE_PNG_PALETTE_124 || GDISP_NEED_IMAGE_PNG_PALETTE_8
  1090. case PNG_COLORMODE_PALETTE:
  1091. switch(pinfo->bitdepth) {
  1092. #if GDISP_NEED_IMAGE_PNG_PALETTE_124
  1093. case 1:
  1094. case 2:
  1095. case 4: pinfo->out = PNG_OutPAL124; break;
  1096. #endif
  1097. #if GDISP_NEED_IMAGE_PNG_PALETTE_8
  1098. case 8: pinfo->out = PNG_OutPAL8; break;
  1099. #endif
  1100. default: goto exit_unsupported;
  1101. }
  1102. pinfo->bpp = pinfo->bitdepth;
  1103. break;
  1104. #endif
  1105. #if GDISP_NEED_IMAGE_PNG_GRAYALPHA_8 || GDISP_NEED_IMAGE_PNG_GRAYALPHA_16
  1106. case PNG_COLORMODE_GRAYALPHA:
  1107. switch(pinfo->bitdepth) {
  1108. #if GDISP_NEED_IMAGE_PNG_GRAYALPHA_8
  1109. case 8: pinfo->out = PNG_OutGRAYA8; break;
  1110. #endif
  1111. #if GDISP_NEED_IMAGE_PNG_GRAYALPHA_16
  1112. case 16: pinfo->out = PNG_OutGRAYA16; break;
  1113. #endif
  1114. default: goto exit_unsupported;
  1115. }
  1116. pinfo->bpp = pinfo->bitdepth * 2;
  1117. break;
  1118. #endif
  1119. #if GDISP_NEED_IMAGE_PNG_RGBALPHA_8 || GDISP_NEED_IMAGE_PNG_RGBALPHA_16
  1120. case PNG_COLORMODE_RGBA:
  1121. switch(pinfo->bitdepth) {
  1122. #if GDISP_NEED_IMAGE_PNG_RGBALPHA_8
  1123. case 8: pinfo->out = PNG_OutRGBA8; break;
  1124. #endif
  1125. #if GDISP_NEED_IMAGE_PNG_RGBALPHA_16
  1126. case 16: pinfo->out = PNG_OutRGBA16; break;
  1127. #endif
  1128. default: goto exit_unsupported;
  1129. }
  1130. pinfo->bpp = pinfo->bitdepth * 4;
  1131. break;
  1132. #endif
  1133. default:
  1134. goto exit_unsupported;
  1135. }
  1136. pinfo->flags |= PNG_FLG_HEADERDONE;
  1137. break;
  1138. case 0x49454E44: // "IEND" - All done
  1139. goto exit_baddata; // Oops we didn't get any data.
  1140. case 0x49444154: // "IDAT" - Image Data
  1141. // Check if the header is already done
  1142. if (!(pinfo->flags & PNG_FLG_HEADERDONE))
  1143. goto exit_baddata;
  1144. #if GDISP_NEED_IMAGE_PNG_PALETTE_124 || GDISP_NEED_IMAGE_PNG_PALETTE_8
  1145. // Make sure a palette image actually has a palette
  1146. if (pinfo->mode == PNG_COLORMODE_PALETTE && !pinfo->palette)
  1147. goto exit_baddata;
  1148. #endif
  1149. // All good
  1150. return GDISP_IMAGE_ERR_OK;
  1151. #if GDISP_NEED_IMAGE_PNG_PALETTE_124 || GDISP_NEED_IMAGE_PNG_PALETTE_8
  1152. case 0x504C5445: // "PLTE" - Palette
  1153. // Check if the header is already done
  1154. if (!(pinfo->flags & PNG_FLG_HEADERDONE))
  1155. goto exit_baddata;
  1156. // Skip a palette if we don't need it.
  1157. if (pinfo->mode != PNG_COLORMODE_PALETTE)
  1158. break;
  1159. // Check the size and that we don't have one already
  1160. if (len > 3 * 256 || pinfo->palette)
  1161. goto exit_baddata;
  1162. // Allocate the palette
  1163. pinfo->palsize = len / 3;
  1164. if (!(pinfo->palette = gfxAlloc(pinfo->palsize * 4)))
  1165. goto exit_nonmem;
  1166. // Read the palette
  1167. {
  1168. uint16_t idx;
  1169. uint8_t *p;
  1170. for(idx=pinfo->palsize, p=pinfo->palette; idx; p += 4, idx--) {
  1171. if (gfileRead(img->f, p, 3) != 3)
  1172. goto exit_baddata;
  1173. p[3] = 255;
  1174. }
  1175. }
  1176. break;
  1177. #endif
  1178. #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY
  1179. case 0x74524E53: // "tRNS" - Transparency
  1180. // Check if the header is already done
  1181. if (!(pinfo->flags & PNG_FLG_HEADERDONE))
  1182. goto exit_baddata;
  1183. // Transparency is handled differently depending on the mode
  1184. switch(pinfo->mode) {
  1185. #if GDISP_NEED_IMAGE_PNG_PALETTE_124 || GDISP_NEED_IMAGE_PNG_PALETTE_8
  1186. case PNG_COLORMODE_PALETTE:
  1187. if (len > pinfo->palsize)
  1188. goto exit_baddata;
  1189. // Adjust the palette
  1190. {
  1191. uint16_t idx;
  1192. uint8_t *p;
  1193. for(idx=len, p=pinfo->palette+3; idx; p += 4, idx--) {
  1194. if (gfileRead(img->f, p, 1) != 1)
  1195. goto exit_baddata;
  1196. }
  1197. }
  1198. break;
  1199. #endif
  1200. #if GDISP_NEED_IMAGE_PNG_GRAYSCALE_124 || GDISP_NEED_IMAGE_PNG_GRAYSCALE_8 || GDISP_NEED_IMAGE_PNG_GRAYSCALE_16
  1201. case PNG_COLORMODE_GRAY:
  1202. // Read the transparency color
  1203. if (len != 2 || gfileRead(img->f, buf, 2) != 2)
  1204. goto exit_baddata;
  1205. pinfo->flags |= PNG_FLG_TRANSPARENT;
  1206. pinfo->trans_r = gdispImageGetAlignedBE16(buf, 0);
  1207. break;
  1208. #endif
  1209. #if GDISP_NEED_IMAGE_PNG_RGB_8 || GDISP_NEED_IMAGE_PNG_RGB_16
  1210. case PNG_COLORMODE_RGB:
  1211. // Read the transparency color
  1212. if (len != 6 || gfileRead(img->f, buf, 6) != 6)
  1213. goto exit_baddata;
  1214. pinfo->flags |= PNG_FLG_TRANSPARENT;
  1215. pinfo->trans_r = gdispImageGetAlignedBE16(buf, 0);
  1216. pinfo->trans_g = gdispImageGetAlignedBE16(buf, 2);
  1217. pinfo->trans_b = gdispImageGetAlignedBE16(buf, 4);
  1218. break;
  1219. #endif
  1220. default:
  1221. goto exit_unsupported;
  1222. }
  1223. break;
  1224. #endif
  1225. #if GDISP_NEED_IMAGE_PNG_BACKGROUND
  1226. case 0x624B4744: // "bKGD" - Background
  1227. // Check if the header is already done
  1228. if (!(pinfo->flags & PNG_FLG_HEADERDONE))
  1229. goto exit_baddata;
  1230. pinfo->flags |= PNG_FLG_BACKGROUND;
  1231. // Background data is handled differently depending on the mode
  1232. switch(pinfo->mode) {
  1233. #if GDISP_NEED_IMAGE_PNG_PALETTE_124 || GDISP_NEED_IMAGE_PNG_PALETTE_8
  1234. case PNG_COLORMODE_PALETTE:
  1235. if (!pinfo->palette || len < 1 || gfileRead(img->f, buf, 1) != 1 || (uint16_t)buf[0] >= pinfo->palsize)
  1236. goto exit_baddata;
  1237. pinfo->bg = RGB2COLOR(pinfo->palette[((unsigned)buf[0])*4+0],
  1238. pinfo->palette[((unsigned)buf[0])*4+1],
  1239. pinfo->palette[((unsigned)buf[0])*4+2]);
  1240. break;
  1241. #endif
  1242. #if GDISP_NEED_IMAGE_PNG_GRAYSCALE_124 || GDISP_NEED_IMAGE_PNG_GRAYSCALE_8 || GDISP_NEED_IMAGE_PNG_GRAYSCALE_16 || GDISP_NEED_IMAGE_PNG_GRAYALPHA_8 || GDISP_NEED_IMAGE_PNG_GRAYALPHA_16
  1243. case PNG_COLORMODE_GRAY:
  1244. case PNG_COLORMODE_GRAYALPHA:
  1245. if (len < 2 || gfileRead(img->f, buf, 2) != 2)
  1246. goto exit_baddata;
  1247. switch(pinfo->bitdepth) {
  1248. #if GDISP_NEED_IMAGE_PNG_GRAYSCALE_124
  1249. case 1:
  1250. case 2:
  1251. case 4:
  1252. buf[1] <<= 8-pinfo->bitdepth;
  1253. if (buf[1] >= 0x80)
  1254. buf[1] += ((1U << (8-pinfo->bitdepth))-1);
  1255. pinfo->bg = LUMA2COLOR(buf[1]);
  1256. break;
  1257. #endif
  1258. #if GDISP_NEED_IMAGE_PNG_GRAYSCALE_8 || GDISP_NEED_IMAGE_PNG_GRAYALPHA_8
  1259. case 8:
  1260. pinfo->bg = LUMA2COLOR(buf[1]);
  1261. break;
  1262. #endif
  1263. #if GDISP_NEED_IMAGE_PNG_GRAYSCALE_16 || GDISP_NEED_IMAGE_PNG_GRAYALPHA_16
  1264. case 16:
  1265. pinfo->bg = LUMA2COLOR(buf[0]);
  1266. break;
  1267. #endif
  1268. }
  1269. break;
  1270. #endif
  1271. #if GDISP_NEED_IMAGE_PNG_RGB_8 || GDISP_NEED_IMAGE_PNG_RGB_16 || GDISP_NEED_IMAGE_PNG_RGBALPHA_8 || GDISP_NEED_IMAGE_PNG_RGBALPHA_16
  1272. case PNG_COLORMODE_RGB:
  1273. case PNG_COLORMODE_RGBA:
  1274. if (len < 6 || gfileRead(img->f, buf, 6) != 6)
  1275. goto exit_baddata;
  1276. #if GDISP_NEED_IMAGE_PNG_RGB_16 || GDISP_NEED_IMAGE_PNG_RGBALPHA_16
  1277. if (pinfo->bitdepth == 16) {
  1278. pinfo->bg = RGB2COLOR(buf[0], buf[2], buf[4]);
  1279. } else
  1280. #endif
  1281. pinfo->bg = RGB2COLOR(buf[1], buf[3], buf[5]);
  1282. break;
  1283. #endif
  1284. default:
  1285. goto exit_unsupported;
  1286. }
  1287. break;
  1288. #endif
  1289. }
  1290. }
  1291. exit_baddata:
  1292. gdispImageClose_PNG(img);
  1293. return GDISP_IMAGE_ERR_BADDATA;
  1294. exit_unsupported:
  1295. gdispImageClose_PNG(img);
  1296. return GDISP_IMAGE_ERR_UNSUPPORTED;
  1297. exit_nonmem:
  1298. gdispImageClose_PNG(img);
  1299. return GDISP_IMAGE_ERR_NOMEMORY;
  1300. }
  1301. gdispImageError gdispGImageDraw_PNG(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) {
  1302. PNG_info *pinfo;
  1303. PNG_decode *d;
  1304. // Allocate the space to decode with including space for 2 full scan lines for filtering.
  1305. pinfo = (PNG_info *)img->priv;
  1306. if (!(d = gdispImageAlloc(img, sizeof(PNG_decode) + (img->width * pinfo->bpp + 7) / 4)))
  1307. return GDISP_IMAGE_ERR_NOMEMORY;
  1308. // Initialise the decoder
  1309. d->img = img;
  1310. d->pinfo = pinfo;
  1311. PNG_iInit(d);
  1312. PNG_oInit(&d->o, g, x, y, cx, cy, sx, sy);
  1313. PNG_zInit(&d->z);
  1314. // Process the zlib inflate header
  1315. if (!PNG_zGetHeader(d))
  1316. goto exit_baddata;
  1317. #if GDISP_NEED_IMAGE_PNG_INTERLACED
  1318. if ((pinfo->flags & PNG_FLG_INTERLACE)) {
  1319. // Interlaced decoding
  1320. #error "PNG Decoder: Interlaced PNG's are not supported yet!"
  1321. } else
  1322. #endif
  1323. {
  1324. // Non-interlaced decoding
  1325. PNG_fInit(&d->f, (uint8_t *)(d+1), (pinfo->bpp + 7) / 8, (img->width * pinfo->bpp + 7) / 8);
  1326. for(y = 0; y < sy+cy; PNG_fNext(&d->f), y++) {
  1327. if (!PNG_unfilter_type0(d))
  1328. goto exit_baddata;
  1329. if (PNG_oStartY(&d->o, y)) {
  1330. pinfo->out(d);
  1331. PNG_oFlush(&d->o);
  1332. }
  1333. }
  1334. }
  1335. // Clean up
  1336. gdispImageFree(img, d, sizeof(PNG_decode) + (img->width * pinfo->bpp + 7) / 4);
  1337. return GDISP_IMAGE_ERR_OK;
  1338. exit_baddata:
  1339. gdispImageFree(img, d, sizeof(PNG_decode) + (img->width * pinfo->bpp + 7) / 4);
  1340. return GDISP_IMAGE_ERR_BADDATA;
  1341. }
  1342. gdispImageError gdispImageCache_PNG(gdispImage *img) {
  1343. PNG_info *pinfo;
  1344. unsigned chunknext;
  1345. unsigned chunklen;
  1346. uint8_t *pcache;
  1347. uint8_t buf[8];
  1348. // If we are already cached - just return OK
  1349. pinfo = (PNG_info *)img->priv;
  1350. if (pinfo->cache)
  1351. return GDISP_IMAGE_ERR_OK;
  1352. // Calculate the size of all the image data blocks in the image
  1353. pinfo->cachesz = 0;
  1354. chunknext = 8;
  1355. while(1) {
  1356. // Find a new chunk
  1357. gfileSetPos(img->f, chunknext);
  1358. if (gfileRead(img->f, buf, 8) != 8)
  1359. return GDISP_IMAGE_ERR_BADDATA;
  1360. // Calculate the chunk length and next chunk
  1361. chunklen = gdispImageGetAlignedBE32(buf, 0);
  1362. chunknext += chunklen + 12;
  1363. // Process only image data chunks
  1364. switch (gdispImageGetAlignedBE32(buf, 4)) {
  1365. case 0x49444154: // "IDAT" - Image Data
  1366. pinfo->cachesz += chunklen;
  1367. break;
  1368. case 0x49454E44: // "IEND" - All done
  1369. if (!pinfo->cachesz)
  1370. return GDISP_IMAGE_ERR_BADDATA;
  1371. goto gotsize;
  1372. }
  1373. }
  1374. gotsize:
  1375. // Allocate the cache
  1376. if (!(pcache = gdispImageAlloc(img, pinfo->cachesz)))
  1377. return GDISP_IMAGE_ERR_NOMEMORY;
  1378. pinfo->cache = pcache;
  1379. // Read the image data into the cache
  1380. chunknext = 8;
  1381. while(1) {
  1382. // Find a new chunk
  1383. gfileSetPos(img->f, chunknext);
  1384. if (gfileRead(img->f, buf, 8) != 8)
  1385. goto baddata;
  1386. // Calculate the chunk length and next chunk
  1387. chunklen = gdispImageGetAlignedBE32(buf, 0);
  1388. chunknext += chunklen + 12;
  1389. // Process only image data chunks
  1390. switch (gdispImageGetAlignedBE32(buf, 4)) {
  1391. case 0x49444154: // "IDAT" - Image Data
  1392. if (gfileRead(img->f, pcache, chunklen) != chunklen)
  1393. goto baddata;
  1394. pcache += chunklen;
  1395. break;
  1396. case 0x49454E44: // "IEND" - All done
  1397. return GDISP_IMAGE_ERR_OK;
  1398. }
  1399. }
  1400. baddata:
  1401. // Oops - can't read the data. Throw away the cache.
  1402. gdispImageFree(img, pinfo->cache, pinfo->cachesz);
  1403. pinfo->cache = 0;
  1404. return GDISP_IMAGE_ERR_BADDATA;
  1405. }
  1406. delaytime_t gdispImageNext_PNG(gdispImage *img) {
  1407. (void) img;
  1408. /* No more frames/pages */
  1409. return TIME_INFINITE;
  1410. }
  1411. #endif /* GFX_USE_GDISP && GDISP_NEED_IMAGE && GDISP_NEED_IMAGE_PNG */