summaryrefslogtreecommitdiff
path: root/apps/plugins/imageviewer/png/png.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/imageviewer/png/png.c')
-rw-r--r--apps/plugins/imageviewer/png/png.c1413
1 files changed, 104 insertions, 1309 deletions
diff --git a/apps/plugins/imageviewer/png/png.c b/apps/plugins/imageviewer/png/png.c
index 46430607ea..4bd988d939 100644
--- a/apps/plugins/imageviewer/png/png.c
+++ b/apps/plugins/imageviewer/png/png.c
@@ -12,6 +12,11 @@
12 * Based on lodepng, a lightweight png decoder/encoder 12 * Based on lodepng, a lightweight png decoder/encoder
13 * (c) 2005-2008 Lode Vandevenne 13 * (c) 2005-2008 Lode Vandevenne
14 * 14 *
15 * Copyright (c) 2010 Marcin Bukat
16 * - pixel format conversion & transparency handling
17 * - adaptation of tinf (tiny inflate library)
18 * - code refactoring & cleanups
19 *
15 * This program is free software; you can redistribute it and/or 20 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License 21 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2 22 * as published by the Free Software Foundation; either version 2
@@ -22,1279 +27,29 @@
22 * 27 *
23 ****************************************************************************/ 28 ****************************************************************************/
24 29
25/*
26LodePNG version 20080927
27
28Copyright (c) 2005-2008 Lode Vandevenne
29
30This software is provided 'as-is', without any express or implied
31warranty. In no event will the authors be held liable for any damages
32arising from the use of this software.
33
34Permission is granted to anyone to use this software for any purpose,
35including commercial applications, and to alter it and redistribute it
36freely, subject to the following restrictions:
37
38 1. The origin of this software must not be misrepresented; you must not
39 claim that you wrote the original software. If you use this software
40 in a product, an acknowledgment in the product documentation would be
41 appreciated but is not required.
42
43 2. Altered source versions must be plainly marked as such, and must not be
44 misrepresented as being the original software.
45
46 3. This notice may not be removed or altered from any source
47 distribution.
48*/
49
50/*
51The manual and changelog can be found in the header file "lodepng.h"
52You are free to name this file lodepng.cpp or lodepng.c depending on your usage.
53*/
54
55#include "plugin.h" 30#include "plugin.h"
56#include "lcd.h" 31#include "lcd.h"
57#include <lib/pluginlib_bmp.h> 32#include <lib/pluginlib_bmp.h>
58#include "zlib.h" 33#include "tinf.h"
59#include "png.h" 34#include "png.h"
35#include "png_decoder.h"
36#include "bmp.h"
60 37
61/* ////////////////////////////////////////////////////////////////////////// */ 38/* decoder context struct */
62/* LodeFlate & LodeZlib Setting structs */ 39static LodePNG_Decoder decoder;
63/* ////////////////////////////////////////////////////////////////////////// */
64
65typedef struct LodePNG_InfoColor /*info about the color type of an image*/
66{
67 /*header (IHDR)*/
68 unsigned colorType; /*color type*/
69 unsigned bitDepth; /*bits per sample*/
70
71 /*palette (PLTE)*/
72 unsigned char palette[256 * 4]; /*palette in RGBARGBA... order*/
73 size_t palettesize; /*palette size in number of colors (amount of bytes is 4 * palettesize)*/
74 40
75 /*transparent color key (tRNS)*/ 41/* my memory pool (from the mp3 buffer) */
76 unsigned key_defined; /*is a transparent color key given?*/ 42static char print[128]; /* use a common snprintf() buffer */
77 unsigned key_r; /*red component of color key*/
78 unsigned key_g; /*green component of color key*/
79 unsigned key_b; /*blue component of color key*/
80} LodePNG_InfoColor;
81
82typedef struct LodePNG_Time /*LodePNG's encoder does not generate the current time. To make it add a time chunk the correct time has to be provided*/
83{
84 unsigned year; /*2 bytes*/
85 unsigned char month; /*1-12*/
86 unsigned char day; /*1-31*/
87 unsigned char hour; /*0-23*/
88 unsigned char minute; /*0-59*/
89 unsigned char second; /*0-60 (to allow for leap seconds)*/
90} LodePNG_Time;
91
92typedef struct LodePNG_InfoPng /*information about the PNG image, except pixels and sometimes except width and height*/
93{
94 /*header (IHDR), palette (PLTE) and transparency (tRNS)*/
95 unsigned width; /*width of the image in pixels (ignored by encoder, but filled in by decoder)*/
96 unsigned height; /*height of the image in pixels (ignored by encoder, but filled in by decoder)*/
97 unsigned compressionMethod; /*compression method of the original file*/
98 unsigned filterMethod; /*filter method of the original file*/
99 unsigned interlaceMethod; /*interlace method of the original file*/
100 LodePNG_InfoColor color; /*color type and bits, palette, transparency*/
101
102 /*suggested background color (bKGD)*/
103 unsigned background_defined; /*is a suggested background color given?*/
104 unsigned background_r; /*red component of suggested background color*/
105 unsigned background_g; /*green component of suggested background color*/
106 unsigned background_b; /*blue component of suggested background color*/
107
108 /*time chunk (tIME)*/
109 unsigned char time_defined; /*if 0, no tIME chunk was or will be generated in the PNG image*/
110 LodePNG_Time time;
111
112 /*phys chunk (pHYs)*/
113 unsigned phys_defined; /*is pHYs chunk defined?*/
114 unsigned phys_x;
115 unsigned phys_y;
116 unsigned char phys_unit; /*may be 0 (unknown unit) or 1 (metre)*/
117
118} LodePNG_InfoPng;
119
120typedef struct LodePNG_InfoRaw /*contains user-chosen information about the raw image data, which is independent of the PNG image*/
121{
122 LodePNG_InfoColor color;
123} LodePNG_InfoRaw;
124
125typedef struct LodePNG_DecodeSettings
126{
127 unsigned color_convert; /*whether to convert the PNG to the color type you want. Default: yes*/
128} LodePNG_DecodeSettings;
129
130typedef struct LodePNG_Decoder
131{
132 LodePNG_DecodeSettings settings;
133 LodePNG_InfoRaw infoRaw;
134 LodePNG_InfoPng infoPng; /*info of the PNG image obtained after decoding*/
135 long error;
136 char error_msg[128];
137} LodePNG_Decoder;
138
139#define VERSION_STRING "20080927"
140 43
141/* decompressed image in the possible sizes (1,2,4,8), wasting the other */ 44/* decompressed image in the possible sizes (1,2,4,8), wasting the other */
142static fb_data *disp[9]; 45static fb_data *disp[9];
143/* up to here currently used by image(s) */
144static fb_data *disp_buf; 46static fb_data *disp_buf;
145 47
146/* my memory pool (from the mp3 buffer) */ 48#if defined(HAVE_LCD_COLOR)
147static char print[32]; /* use a common snprintf() buffer */ 49#define resize_bitmap smooth_resize_bitmap
148 50#else
149unsigned char *memory, *memory_max; /* inffast.c needs memory_max */ 51#define resize_bitmap grey_resize_bitmap
150static size_t memory_size; 52#endif
151
152static unsigned char *image; /* where we put the content of the file */
153static size_t image_size;
154
155static fb_data *converted_image; /* the (color) converted image */
156static size_t converted_image_size;
157
158static unsigned char *decoded_image; /* the decoded image */
159static size_t decoded_image_size;
160
161static LodePNG_Decoder _decoder;
162
163/*
164The two functions below (LodePNG_decompress and LodePNG_compress) directly call the
165LodeZlib_decompress and LodeZlib_compress functions. The only purpose of the functions
166below, is to provide the ability to let LodePNG use a different Zlib encoder by only
167changing the two functions below, instead of changing it inside the vareous places
168in the other LodePNG functions.
169
170*out must be NULL and *outsize must be 0 initially, and after the function is done,
171*out must point to the decompressed data, *outsize must be the size of it, and must
172be the size of the useful data in bytes, not the alloc size.
173*/
174
175static unsigned LodePNG_decompress(unsigned char* out, size_t* outsize, const unsigned char* in, size_t insize, char *error_msg)
176{
177 z_stream stream;
178 int err;
179
180 rb->strcpy(error_msg, "");
181
182 stream.next_in = (Bytef*)in;
183 stream.avail_in = (uInt)insize;
184
185 stream.next_out = out;
186 stream.avail_out = (uInt)*outsize;
187
188 stream.zalloc = (alloc_func)0;
189 stream.zfree = (free_func)0;
190
191 err = inflateInit(&stream);
192 if (err != Z_OK) return err;
193
194 err = inflate(&stream, Z_FINISH);
195 if (err != Z_STREAM_END) {
196 inflateEnd(&stream);
197 if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
198 return Z_DATA_ERROR;
199 return err;
200 }
201 *outsize = stream.total_out;
202
203 err = inflateEnd(&stream);
204 if (stream.msg != Z_NULL)
205 rb->strcpy(error_msg, stream.msg);
206 return err;
207}
208
209/* ////////////////////////////////////////////////////////////////////////// */
210/* / Reading and writing single bits and bytes from/to stream for LodePNG / */
211/* ////////////////////////////////////////////////////////////////////////// */
212
213static unsigned char readBitFromReversedStream(size_t* bitpointer, const unsigned char* bitstream)
214{
215 unsigned char result = (unsigned char)((bitstream[(*bitpointer) >> 3] >> (7 - ((*bitpointer) & 0x7))) & 1);
216 (*bitpointer)++;
217 return result;
218}
219
220static unsigned readBitsFromReversedStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits)
221{
222 unsigned result = 0;
223 size_t i;
224 for (i = nbits - 1; i < nbits; i--) result += (unsigned)readBitFromReversedStream(bitpointer, bitstream) << i;
225 return result;
226}
227
228static void setBitOfReversedStream0(size_t* bitpointer, unsigned char* bitstream, unsigned char bit)
229{
230 /*the current bit in bitstream must be 0 for this to work*/
231 if (bit) bitstream[(*bitpointer) >> 3] |= (bit << (7 - ((*bitpointer) & 0x7))); /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/
232 (*bitpointer)++;
233}
234
235static void setBitOfReversedStream(size_t* bitpointer, unsigned char* bitstream, unsigned char bit)
236{
237 /*the current bit in bitstream may be 0 or 1 for this to work*/
238 if (bit == 0) bitstream[(*bitpointer) >> 3] &= (unsigned char)(~(1 << (7 - ((*bitpointer) & 0x7))));
239 else bitstream[(*bitpointer) >> 3] |= (1 << (7 - ((*bitpointer) & 0x7)));
240 (*bitpointer)++;
241}
242
243static unsigned LodePNG_read32bitInt(const unsigned char* buffer)
244{
245 return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
246}
247
248/* ////////////////////////////////////////////////////////////////////////// */
249/* / PNG chunks / */
250/* ////////////////////////////////////////////////////////////////////////// */
251
252unsigned LodePNG_chunk_length(const unsigned char* chunk) /*get the length of the data of the chunk. Total chunk length has 12 bytes more.*/
253{
254 return LodePNG_read32bitInt(&chunk[0]);
255}
256
257void LodePNG_chunk_type(char type[5], const unsigned char* chunk) /*puts the 4-byte type in null terminated string*/
258{
259 unsigned i;
260 for (i = 0; i < 4; i++) type[i] = chunk[4 + i];
261 type[4] = 0; /*null termination char*/
262}
263
264unsigned char LodePNG_chunk_type_equals(const unsigned char* chunk, const char* type) /*check if the type is the given type*/
265{
266 if (type[4] != 0) return 0;
267 return (chunk[4] == type[0] && chunk[5] == type[1] && chunk[6] == type[2] && chunk[7] == type[3]);
268}
269
270/*properties of PNG chunks gotten from capitalization of chunk type name, as defined by the standard*/
271unsigned char LodePNG_chunk_critical(const unsigned char* chunk) /*0: ancillary chunk, 1: it's one of the critical chunk types*/
272{
273 return((chunk[4] & 32) == 0);
274}
275
276unsigned char LodePNG_chunk_private(const unsigned char* chunk) /*0: public, 1: private*/
277{
278 return((chunk[6] & 32) != 0);
279}
280
281unsigned char LodePNG_chunk_safetocopy(const unsigned char* chunk) /*0: the chunk is unsafe to copy, 1: the chunk is safe to copy*/
282{
283 return((chunk[7] & 32) != 0);
284}
285
286unsigned char* LodePNG_chunk_data(unsigned char* chunk) /*get pointer to the data of the chunk*/
287{
288 return &chunk[8];
289}
290
291const unsigned char* LodePNG_chunk_data_const(const unsigned char* chunk) /*get pointer to the data of the chunk*/
292{
293 return &chunk[8];
294}
295
296unsigned LodePNG_chunk_check_crc(const unsigned char* chunk) /*returns 0 if the crc is correct, error code if it's incorrect*/
297{
298 unsigned length = LodePNG_chunk_length(chunk);
299 unsigned CRC = LodePNG_read32bitInt(&chunk[length + 8]);
300 unsigned checksum = crc32(0L, &chunk[4], length + 4); /*the CRC is taken of the data and the 4 chunk type letters, not the length*/
301 if (CRC != checksum) return 1;
302 else return 0;
303}
304
305unsigned char* LodePNG_chunk_next(unsigned char* chunk) /*don't use on IEND chunk, as there is no next chunk then*/
306{
307 unsigned total_chunk_length = LodePNG_chunk_length(chunk) + 12;
308 return &chunk[total_chunk_length];
309}
310
311const unsigned char* LodePNG_chunk_next_const(const unsigned char* chunk) /*don't use on IEND chunk, as there is no next chunk then*/
312{
313 unsigned total_chunk_length = LodePNG_chunk_length(chunk) + 12;
314 return &chunk[total_chunk_length];
315}
316
317/* ////////////////////////////////////////////////////////////////////////// */
318/* / Color types and such / */
319/* ////////////////////////////////////////////////////////////////////////// */
320
321/*return type is a LodePNG error code*/
322static unsigned checkColorValidity(unsigned colorType, unsigned bd) /*bd = bitDepth*/
323{
324 switch (colorType)
325 {
326 case 0:
327 if (!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; break; /*grey*/
328 case 2:
329 if (!( bd == 8 || bd == 16)) return 37; break; /*RGB*/
330 case 3:
331 if (!(bd == 1 || bd == 2 || bd == 4 || bd == 8 )) return 37; break; /*palette*/
332 case 4:
333 if (!( bd == 8 || bd == 16)) return 37; break; /*grey + alpha*/
334 case 6:
335 if (!( bd == 8 || bd == 16)) return 37; break; /*RGBA*/
336 default:
337 return 31;
338 }
339 return 0; /*allowed color type / bits combination*/
340}
341
342static unsigned getNumColorChannels(unsigned colorType)
343{
344 switch (colorType)
345 {
346 case 0:
347 return 1; /*grey*/
348 case 2:
349 return 3; /*RGB*/
350 case 3:
351 return 1; /*palette*/
352 case 4:
353 return 2; /*grey + alpha*/
354 case 6:
355 return 4; /*RGBA*/
356 }
357 return 0; /*unexisting color type*/
358}
359
360static unsigned getBpp(unsigned colorType, unsigned bitDepth)
361{
362 return getNumColorChannels(colorType) * bitDepth; /*bits per pixel is amount of channels * bits per channel*/
363}
364
365/* ////////////////////////////////////////////////////////////////////////// */
366
367void LodePNG_InfoColor_init(LodePNG_InfoColor* info)
368{
369 info->key_defined = 0;
370 info->key_r = info->key_g = info->key_b = 0;
371 info->colorType = 6;
372 info->bitDepth = 8;
373 memset(info->palette, 0, 256 * 4 * sizeof(unsigned char));
374 info->palettesize = 0;
375}
376
377void LodePNG_InfoColor_cleanup(LodePNG_InfoColor* info)
378{
379 info->palettesize = 0;
380}
381
382unsigned LodePNG_InfoColor_getBpp(const LodePNG_InfoColor* info) { return getBpp(info->colorType, info->bitDepth); } /*calculate bits per pixel out of colorType and bitDepth*/
383unsigned LodePNG_InfoColor_isGreyscaleType(const LodePNG_InfoColor* info) { return info->colorType == 0 || info->colorType == 4; }
384
385unsigned LodePNG_InfoColor_equal(const LodePNG_InfoColor* info1, const LodePNG_InfoColor* info2)
386{
387 return info1->colorType == info2->colorType
388 && info1->bitDepth == info2->bitDepth; /*palette and color key not compared*/
389}
390
391void LodePNG_InfoPng_init(LodePNG_InfoPng* info)
392{
393 info->width = info->height = 0;
394 LodePNG_InfoColor_init(&info->color);
395 info->interlaceMethod = 0;
396 info->compressionMethod = 0;
397 info->filterMethod = 0;
398 info->background_defined = 0;
399 info->background_r = info->background_g = info->background_b = 0;
400
401 info->time_defined = 0;
402 info->phys_defined = 0;
403}
404
405void LodePNG_InfoPng_cleanup(LodePNG_InfoPng* info)
406{
407 LodePNG_InfoColor_cleanup(&info->color);
408}
409
410unsigned LodePNG_InfoColor_copy(LodePNG_InfoColor* dest, const LodePNG_InfoColor* source)
411{
412 size_t i;
413 LodePNG_InfoColor_cleanup(dest);
414 *dest = *source;
415 for (i = 0; i < source->palettesize * 4; i++) dest->palette[i] = source->palette[i];
416 return 0;
417}
418
419unsigned LodePNG_InfoPng_copy(LodePNG_InfoPng* dest, const LodePNG_InfoPng* source)
420{
421 unsigned error = 0;
422 LodePNG_InfoPng_cleanup(dest);
423 *dest = *source;
424 LodePNG_InfoColor_init(&dest->color);
425 error = LodePNG_InfoColor_copy(&dest->color, &source->color); if (error) return error;
426 return error;
427}
428
429void LodePNG_InfoPng_swap(LodePNG_InfoPng* a, LodePNG_InfoPng* b)
430{
431 LodePNG_InfoPng temp = *a;
432 *a = *b;
433 *b = temp;
434}
435
436void LodePNG_InfoRaw_init(LodePNG_InfoRaw* info)
437{
438 LodePNG_InfoColor_init(&info->color);
439}
440
441void LodePNG_InfoRaw_cleanup(LodePNG_InfoRaw* info)
442{
443 LodePNG_InfoColor_cleanup(&info->color);
444}
445
446unsigned LodePNG_InfoRaw_copy(LodePNG_InfoRaw* dest, const LodePNG_InfoRaw* source)
447{
448 unsigned error = 0;
449 LodePNG_InfoRaw_cleanup(dest);
450 *dest = *source;
451 LodePNG_InfoColor_init(&dest->color);
452 error = LodePNG_InfoColor_copy(&dest->color, &source->color); if (error) return error;
453 return error;
454}
455
456/* ////////////////////////////////////////////////////////////////////////// */
457
458/*
459converts from any color type to 24-bit or 32-bit (later maybe more supported). return value = LodePNG error code
460the out buffer must have (w * h * bpp + 7) / 8 bytes, where bpp is the bits per pixel of the output color type (LodePNG_InfoColor_getBpp)
461for < 8 bpp images, there may _not_ be padding bits at the end of scanlines.
462*/
463unsigned LodePNG_convert(fb_data* out, const unsigned char* in, LodePNG_InfoColor* infoOut, LodePNG_InfoColor* infoIn, unsigned w, unsigned h)
464{
465 size_t i, j, bp = 0; /*bitpointer, used by less-than-8-bit color types*/
466 size_t x, y;
467 unsigned char c;
468
469 if (!running_slideshow)
470 {
471 rb->lcd_puts(0, 3, "color conversion in progress");
472 rb->lcd_update();
473 }
474
475 /*cases where in and out already have the same format*/
476 if (LodePNG_InfoColor_equal(infoIn, infoOut))
477 {
478
479 i = 0;
480 j = 0;
481 for (y = 0 ; y < h ; y++) {
482 for (x = 0 ; x < w ; x++) {
483 unsigned char r = in[i++];
484 unsigned char g = in[i++];
485 unsigned char b = in[i++];
486 out[j++] = LCD_RGBPACK(r,g,b);
487 }
488 }
489 return 0;
490 }
491
492 if ((infoOut->colorType == 2 || infoOut->colorType == 6) && infoOut->bitDepth == 8)
493 {
494 if (infoIn->bitDepth == 8)
495 {
496 switch (infoIn->colorType)
497 {
498 case 0: /*greyscale color*/
499 i = 0;
500 for (y = 0 ; y < h ; y++) {
501 for (x = 0 ; x < w ; x++) {
502 c=in[i];
503 //unsigned char r = in[i];
504 //unsigned char g = in[i];
505 //unsigned char b = in[i];
506 out[i++] = LCD_RGBPACK(c,c,c);
507 }
508 }
509 break;
510 case 2: /*RGB color*/
511 i = 0;
512 for (y = 0 ; y < h ; y++) {
513 for (x = 0 ; x < w ; x++) {
514 j = 3 * i;
515 unsigned char r = in[j];
516 unsigned char g = in[j + 1];
517 unsigned char b = in[j + 2];
518 out[i++] = LCD_RGBPACK(r,g,b);
519 }
520 }
521 break;
522 case 3: /*indexed color (palette)*/
523 i = 0;
524 for (y = 0 ; y < h ; y++) {
525 for (x = 0 ; x < w ; x++) {
526 if (in[i] >= infoIn->palettesize) return 46;
527 j = in[i] << 2;
528 unsigned char r = infoIn->palette[j];
529 unsigned char g = infoIn->palette[j + 1];
530 unsigned char b = infoIn->palette[j + 2];
531 out[i++] = LCD_RGBPACK(r,g,b);
532 }
533 }
534 break;
535 case 4: /*greyscale with alpha*/
536 i = 0;
537 for (y = 0 ; y < h ; y++) {
538 for (x = 0 ; x < w ; x++) {
539 c = in[i << 1];
540 //unsigned char r = in[i<<1];
541 //unsigned char g = in[i<<1];
542 //unsigned char b = in[i<<1];
543 out[i++] = LCD_RGBPACK(c,c,c);
544 }
545 }
546 break;
547 case 6: /*RGB with alpha*/
548 i = 0;
549 for (y = 0 ; y < h ; y++) {
550 for (x = 0 ; x < w ; x++) {
551 j = i << 2;
552 unsigned char r = in[j];
553 unsigned char g = in[j + 1];
554 unsigned char b = in[j + 2];
555 out[i++] = LCD_RGBPACK(r,g,b);
556 }
557 }
558 break;
559 default:
560 break;
561 }
562 }
563 else if (infoIn->bitDepth == 16)
564 {
565 switch (infoIn->colorType)
566 {
567 case 0: /*greyscale color*/
568 i = 0;
569 for (y = 0 ; y < h ; y++) {
570 for (x = 0 ; x < w ; x++) {
571 c = in[i << 1];
572 //unsigned char r = in[2 * i];
573 //unsigned char g = in[2 * i];
574 //unsigned char b = in[2 * i];
575 out[i++] = LCD_RGBPACK(c,c,c);
576 }
577 }
578 break;
579 case 2: /*RGB color*/
580 i = 0;
581 for (y = 0 ; y < h ; y++) {
582 for (x = 0 ; x < w ; x++) {
583 j = 6 * i;
584 unsigned char r = in[j];
585 unsigned char g = in[j + 2];
586 unsigned char b = in[j + 4];
587 out[i++] = LCD_RGBPACK(r,g,b);
588 }
589 }
590 break;
591 case 4: /*greyscale with alpha*/
592 i = 0;
593 for (y = 0 ; y < h ; y++) {
594 for (x = 0 ; x < w ; x++) {
595 c = in[i << 2];
596 //unsigned char r = in[4 * i];
597 //unsigned char g = in[4 * i];
598 //unsigned char b = in[4 * i];
599 out[i++] = LCD_RGBPACK(c,c,c);
600 }
601 }
602 break;
603 case 6: /*RGB with alpha*/
604 i = 0;
605 for (y = 0 ; y < h ; y++) {
606 for (x = 0 ; x < w ; x++) {
607 j = i << 3;
608 unsigned char r = in[j];
609 unsigned char g = in[j + 2];
610 unsigned char b = in[j + 4];
611 out[i++] = LCD_RGBPACK(r,g,b);
612 }
613 }
614 break;
615 default:
616 break;
617 }
618 }
619 else /*infoIn->bitDepth is less than 8 bit per channel*/
620 {
621 switch (infoIn->colorType)
622 {
623 case 0: /*greyscale color*/
624 i = 0;
625 for (y = 0 ; y < h ; y++) {
626 for (x = 0 ; x < w ; x++) {
627 unsigned value = readBitsFromReversedStream(&bp, in, infoIn->bitDepth);
628 value = (value * 255) / ((1 << infoIn->bitDepth) - 1); /*scale value from 0 to 255*/
629 unsigned char r = (unsigned char)value;
630 unsigned char g = (unsigned char)value;
631 unsigned char b = (unsigned char)value;
632 out[i++] = LCD_RGBPACK(r,g,b);
633 }
634 }
635 break;
636 case 3: /*indexed color (palette)*/
637 i = 0;
638 for (y = 0 ; y < h ; y++) {
639 for (x = 0 ; x < w ; x++) {
640 unsigned value = readBitsFromReversedStream(&bp, in, infoIn->bitDepth);
641 if (value >= infoIn->palettesize) return 47;
642 j = value << 2;
643 unsigned char r = infoIn->palette[j];
644 unsigned char g = infoIn->palette[j + 1];
645 unsigned char b = infoIn->palette[j + 2];
646 out[i++] = LCD_RGBPACK(r,g,b);
647 }
648 }
649 break;
650 default:
651 break;
652 }
653 }
654 }
655 else if (LodePNG_InfoColor_isGreyscaleType(infoOut) && infoOut->bitDepth == 8) /*conversion from greyscale to greyscale*/
656 {
657 if (!LodePNG_InfoColor_isGreyscaleType(infoIn)) return 62;
658 if (infoIn->bitDepth == 8)
659 {
660 switch (infoIn->colorType)
661 {
662 case 0: /*greyscale color*/
663 i = 0;
664 for (y = 0 ; y < h ; y++) {
665 for (x = 0 ; x < w ; x++) {
666 c = in[i];
667 //unsigned char r = in[i];
668 //unsigned char g = in[i];
669 //unsigned char b = in[i];
670 out[i++] = LCD_RGBPACK(c,c,c);
671 }
672 }
673 break;
674 case 4: /*greyscale with alpha*/
675 i = 0;
676 for (y = 0 ; y < h ; y++) {
677 for (x = 0 ; x < w ; x++) {
678 c = in[(i << 1) + 1];
679 //unsigned char r = in[2 * i + 1];
680 //unsigned char g = in[2 * i + 1];
681 //unsigned char b = in[2 * i + 1];
682 out[i++] = LCD_RGBPACK(c,c,c);
683 }
684 }
685 break;
686 default:
687 return 31;
688 }
689 }
690 else if (infoIn->bitDepth == 16)
691 {
692 switch (infoIn->colorType)
693 {
694 case 0: /*greyscale color*/
695 i = 0;
696 for (y = 0 ; y < h ; y++) {
697 for (x = 0 ; x < w ; x++) {
698 c = in[i << 1];
699 //unsigned char r = in[2 * i];
700 //unsigned char g = in[2 * i];
701 //unsigned char b = in[2 * i];
702 out[i++] = LCD_RGBPACK(c,c,c);
703 }
704 }
705 break;
706 case 4: /*greyscale with alpha*/
707 i = 0;
708 for (y = 0 ; y < h ; y++) {
709 for (x = 0 ; x < w ; x++) {
710 c = in[i << 2];
711 //unsigned char r = in[4 * i];
712 //unsigned char g = in[4 * i];
713 //unsigned char b = in[4 * i];
714 out[i++] = LCD_RGBPACK(c,c,c);
715 }
716 }
717 break;
718 default:
719 return 31;
720 }
721 }
722 else /*infoIn->bitDepth is less than 8 bit per channel*/
723 {
724 if (infoIn->colorType != 0) return 31; /*colorType 0 is the only greyscale type with < 8 bits per channel*/
725 i = 0;
726 for (y = 0 ; y < h ; y++) {
727 for (x = 0 ; x < w ; x++) {
728 unsigned value = readBitsFromReversedStream(&bp, in, infoIn->bitDepth);
729 value = (value * 255) / ((1 << infoIn->bitDepth) - 1); /*scale value from 0 to 255*/
730 unsigned char r = (unsigned char)value;
731 unsigned char g = (unsigned char)value;
732 unsigned char b = (unsigned char)value;
733 out[i++] = LCD_RGBPACK(r,g,b);
734 }
735 }
736 }
737 }
738 else return 59;
739
740 return 0;
741}
742
743/*Paeth predicter, used by PNG filter type 4*/
744static int paethPredictor(int a, int b, int c)
745{
746 int p = a + b - c;
747 int pa = p > a ? p - a : a - p;
748 int pb = p > b ? p - b : b - p;
749 int pc = p > c ? p - c : c - p;
750
751 if (pa <= pb && pa <= pc) return a;
752 else if (pb <= pc) return b;
753 else return c;
754}
755
756/*shared values used by multiple Adam7 related functions*/
757
758static const unsigned ADAM7_IX[7] = { 0, 4, 0, 2, 0, 1, 0 }; /*x start values*/
759static const unsigned ADAM7_IY[7] = { 0, 0, 4, 0, 2, 0, 1 }; /*y start values*/
760static const unsigned ADAM7_DX[7] = { 8, 8, 4, 4, 2, 2, 1 }; /*x delta values*/
761static const unsigned ADAM7_DY[7] = { 8, 8, 8, 4, 4, 2, 2 }; /*y delta values*/
762
763static void Adam7_getpassvalues(unsigned passw[7], unsigned passh[7], size_t filter_passstart[8], size_t padded_passstart[8], size_t passstart[8], unsigned w, unsigned h, unsigned bpp)
764{
765 /*the passstart values have 8 values: the 8th one actually indicates the byte after the end of the 7th (= last) pass*/
766 unsigned i;
767
768 /*calculate width and height in pixels of each pass*/
769 for (i = 0; i < 7; i++)
770 {
771 passw[i] = (w + ADAM7_DX[i] - ADAM7_IX[i] - 1) / ADAM7_DX[i];
772 passh[i] = (h + ADAM7_DY[i] - ADAM7_IY[i] - 1) / ADAM7_DY[i];
773 if (passw[i] == 0) passh[i] = 0;
774 if (passh[i] == 0) passw[i] = 0;
775 }
776
777 filter_passstart[0] = padded_passstart[0] = passstart[0] = 0;
778 for (i = 0; i < 7; i++)
779 {
780 filter_passstart[i + 1] = filter_passstart[i] + ((passw[i] && passh[i]) ? passh[i] * (1 + (passw[i] * bpp + 7) / 8) : 0); /*if passw[i] is 0, it's 0 bytes, not 1 (no filtertype-byte)*/
781 padded_passstart[i + 1] = padded_passstart[i] + passh[i] * ((passw[i] * bpp + 7) / 8); /*bits padded if needed to fill full byte at end of each scanline*/
782 passstart[i + 1] = passstart[i] + (passh[i] * passw[i] * bpp + 7) / 8; /*only padded at end of reduced image*/
783 }
784}
785
786/* ////////////////////////////////////////////////////////////////////////// */
787/* / PNG Decoder / */
788/* ////////////////////////////////////////////////////////////////////////// */
789
790/*read the information from the header and store it in the LodePNG_Info. return value is error*/
791void LodePNG_inspect(LodePNG_Decoder* decoder, const unsigned char* in, size_t inlength)
792{
793 if (inlength == 0 || in == 0) { decoder->error = 48; return; } /*the given data is empty*/
794 if (inlength < 29) { decoder->error = 27; return; } /*error: the data length is smaller than the length of the header*/
795
796 /*when decoding a new PNG image, make sure all parameters created after previous decoding are reset*/
797 LodePNG_InfoPng_cleanup(&decoder->infoPng);
798 LodePNG_InfoPng_init(&decoder->infoPng);
799 decoder->error = 0;
800
801 if (in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71 || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10) { decoder->error = 28; return; } /*error: the first 8 bytes are not the correct PNG signature*/
802 if (in[12] != 'I' || in[13] != 'H' || in[14] != 'D' || in[15] != 'R') { decoder->error = 29; return; } /*error: it doesn't start with a IHDR chunk!*/
803
804 /*read the values given in the header*/
805 decoder->infoPng.width = LodePNG_read32bitInt(&in[16]);
806 decoder->infoPng.height = LodePNG_read32bitInt(&in[20]);
807 decoder->infoPng.color.bitDepth = in[24];
808 decoder->infoPng.color.colorType = in[25];
809 decoder->infoPng.compressionMethod = in[26];
810 decoder->infoPng.filterMethod = in[27];
811 decoder->infoPng.interlaceMethod = in[28];
812
813 unsigned CRC = LodePNG_read32bitInt(&in[29]);
814 unsigned checksum = crc32(0L, &in[12], 17);
815 if (CRC != checksum) { decoder->error = 57; return; }
816
817 if (decoder->infoPng.compressionMethod != 0) { decoder->error = 32; return; } /*error: only compression method 0 is allowed in the specification*/
818 if (decoder->infoPng.filterMethod != 0) { decoder->error = 33; return; } /*error: only filter method 0 is allowed in the specification*/
819 if (decoder->infoPng.interlaceMethod > 1) { decoder->error = 34; return; } /*error: only interlace methods 0 and 1 exist in the specification*/
820
821 decoder->error = checkColorValidity(decoder->infoPng.color.colorType, decoder->infoPng.color.bitDepth);
822}
823
824static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon, size_t bytewidth, unsigned char filterType, size_t length)
825{
826 /*
827 For PNG filter method 0
828 unfilter a PNG image scanline by scanline. when the pixels are smaller than 1 byte, the filter works byte per byte (bytewidth = 1)
829 precon is the previous unfiltered scanline, recon the result, scanline the current one
830 the incoming scanlines do NOT include the filtertype byte, that one is given in the parameter filterType instead
831 recon and scanline MAY be the same memory address! precon must be disjoint.
832 */
833
834 size_t i;
835 switch (filterType)
836 {
837 case 0:
838 //for(i = 0; i < length; i++) recon[i] = scanline[i];
839 memcpy(recon, scanline, length * sizeof(unsigned char));
840 break;
841 case 1:
842 //for(i = 0; i < bytewidth; i++) recon[i] = scanline[i];
843 memcpy(recon, scanline, bytewidth * sizeof(unsigned char));
844 for (i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth];
845 break;
846 case 2:
847 if (precon) for (i = 0; i < length; i++) recon[i] = scanline[i] + precon[i];
848 else //for(i = 0; i < length; i++) recon[i] = scanline[i];
849 memcpy(recon, scanline, length * sizeof(unsigned char));
850 break;
851 case 3:
852 if (precon)
853 {
854 for (i = 0; i < bytewidth; i++) recon[i] = scanline[i] + precon[i] / 2;
855 for (i = bytewidth; i < length; i++) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) / 2);
856 }
857 else
858 {
859 //for(i = 0; i < bytewidth; i++) recon[i] = scanline[i];
860 memcpy(recon, scanline, bytewidth * sizeof(unsigned char));
861 for (i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth] / 2;
862 }
863 break;
864 case 4:
865 if (precon)
866 {
867 for (i = 0; i < bytewidth; i++) recon[i] = (unsigned char)(scanline[i] + paethPredictor(0, precon[i], 0));
868 for (i = bytewidth; i < length; i++) recon[i] = (unsigned char)(scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth]));
869 }
870 else
871 {
872 //for(i = 0; i < bytewidth; i++) recon[i] = scanline[i];
873 memcpy(recon, scanline, bytewidth * sizeof(unsigned char));
874 for (i = bytewidth; i < length; i++) recon[i] = (unsigned char)(scanline[i] + paethPredictor(recon[i - bytewidth], 0, 0));
875 }
876 break;
877 default:
878 return 36; /*error: unexisting filter type given*/
879 }
880 return 0;
881}
882
883static unsigned unfilter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp)
884{
885 /*
886 For PNG filter method 0
887 this function unfilters a single image (e.g. without interlacing this is called once, with Adam7 it's called 7 times)
888 out must have enough bytes allocated already, in must have the scanlines + 1 filtertype byte per scanline
889 w and h are image dimensions or dimensions of reduced image, bpp is bits per pixel
890 in and out are allowed to be the same memory address!
891 */
892
893 unsigned y;
894 unsigned char* prevline = 0;
895
896 size_t bytewidth = (bpp + 7) / 8; /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/
897 size_t linebytes = (w * bpp + 7) / 8;
898
899 for (y = 0; y < h; y++)
900 {
901 size_t outindex = linebytes * y;
902 size_t inindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/
903 unsigned char filterType = in[inindex];
904
905 unsigned error = unfilterScanline(&out[outindex], &in[inindex + 1], prevline, bytewidth, filterType, linebytes);
906 if (error) return error;
907
908 prevline = &out[outindex];
909 }
910
911 return 0;
912}
913
914static void Adam7_deinterlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp)
915{
916 /*Note: this function works on image buffers WITHOUT padding bits at end of scanlines with non-multiple-of-8 bit amounts, only between reduced images is padding
917 out must be big enough AND must be 0 everywhere if bpp < 8 in the current implementation (because that's likely a little bit faster)*/
918 unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8];
919 unsigned i;
920
921 Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);
922
923 if (bpp >= 8)
924 {
925 for (i = 0; i < 7; i++)
926 {
927 unsigned x, y, b;
928 size_t bytewidth = bpp / 8;
929 for (y = 0; y < passh[i]; y++)
930 for (x = 0; x < passw[i]; x++)
931 {
932 size_t pixelinstart = passstart[i] + (y * passw[i] + x) * bytewidth;
933 size_t pixeloutstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth;
934 for (b = 0; b < bytewidth; b++)
935 {
936 out[pixeloutstart + b] = in[pixelinstart + b];
937 }
938 }
939 }
940 }
941 else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/
942 {
943 for (i = 0; i < 7; i++)
944 {
945 unsigned x, y, b;
946 unsigned ilinebits = bpp * passw[i];
947 unsigned olinebits = bpp * w;
948 size_t obp, ibp; /*bit pointers (for out and in buffer)*/
949 for (y = 0; y < passh[i]; y++)
950 for (x = 0; x < passw[i]; x++)
951 {
952 ibp = (8 * passstart[i]) + (y * ilinebits + x * bpp);
953 obp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp;
954 for (b = 0; b < bpp; b++)
955 {
956 unsigned char bit = readBitFromReversedStream(&ibp, in);
957 setBitOfReversedStream0(&obp, out, bit); /*note that this function assumes the out buffer is completely 0, use setBitOfReversedStream otherwise*/
958 }
959 }
960 }
961 }
962}
963
964static void removePaddingBits(unsigned char* out, const unsigned char* in, size_t olinebits, size_t ilinebits, unsigned h)
965{
966 /*
967 After filtering there are still padding bits if scanlines have non multiple of 8 bit amounts. They need to be removed (except at last scanline of (Adam7-reduced) image) before working with pure image buffers for the Adam7 code, the color convert code and the output to the user.
968 in and out are allowed to be the same buffer, in may also be higher but still overlapping; in must have >= ilinebits*h bits, out must have >= olinebits*h bits, olinebits must be <= ilinebits
969 also used to move bits after earlier such operations happened, e.g. in a sequence of reduced images from Adam7
970 only useful if (ilinebits - olinebits) is a value in the range 1..7
971 */
972 unsigned y;
973 size_t diff = ilinebits - olinebits;
974 size_t obp = 0, ibp = 0; /*bit pointers*/
975 for (y = 0; y < h; y++)
976 {
977 size_t x;
978 for (x = 0; x < olinebits; x++)
979 {
980 unsigned char bit = readBitFromReversedStream(&ibp, in);
981 setBitOfReversedStream(&obp, out, bit);
982 }
983 ibp += diff;
984 }
985}
986
987/*out must be buffer big enough to contain full image, and in must contain the full decompressed data from the IDAT chunks*/
988static unsigned postProcessScanlines(unsigned char* out, unsigned char* in, const LodePNG_Decoder* decoder) /*return value is error*/
989{
990 /*
991 This function converts the filtered-padded-interlaced data into pure 2D image buffer with the PNG's colortype. Steps:
992 *) if no Adam7: 1) unfilter 2) remove padding bits (= posible extra bits per scanline if bpp < 8)
993 *) if adam7: 1) 7x unfilter 2) 7x remove padding bits 3) Adam7_deinterlace
994 NOTE: the in buffer will be overwritten with intermediate data!
995 */
996 unsigned bpp = LodePNG_InfoColor_getBpp(&decoder->infoPng.color);
997 unsigned w = decoder->infoPng.width;
998 unsigned h = decoder->infoPng.height;
999 unsigned error = 0;
1000 if (bpp == 0) return 31; /*error: invalid colortype*/
1001
1002 if (decoder->infoPng.interlaceMethod == 0)
1003 {
1004 if (bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8)
1005 {
1006 error = unfilter(in, in, w, h, bpp);
1007 if (error) return error;
1008 removePaddingBits(out, in, w * bpp, ((w * bpp + 7) / 8) * 8, h);
1009 }
1010 else error = unfilter(out, in, w, h, bpp); /*we can immediatly filter into the out buffer, no other steps needed*/
1011 }
1012 else /*interlaceMethod is 1 (Adam7)*/
1013 {
1014 unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8];
1015 unsigned i;
1016
1017 Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);
1018
1019 for (i = 0; i < 7; i++)
1020 {
1021 error = unfilter(&in[padded_passstart[i]], &in[filter_passstart[i]], passw[i], passh[i], bpp);
1022 if (error) return error;
1023 if (bpp < 8) /*TODO: possible efficiency improvement: if in this reduced image the bits fit nicely in 1 scanline, move bytes instead of bits or move not at all*/
1024 {
1025 /*remove padding bits in scanlines; after this there still may be padding bits between the different reduced images: each reduced image still starts nicely at a byte*/
1026 removePaddingBits(&in[passstart[i]], &in[padded_passstart[i]], passw[i] * bpp, ((passw[i] * bpp + 7) / 8) * 8, passh[i]);
1027 }
1028 }
1029
1030 Adam7_deinterlace(out, in, w, h, bpp);
1031 }
1032
1033 return error;
1034}
1035
1036/*read a PNG, the result will be in the same color type as the PNG (hence "generic")*/
1037static void decodeGeneric(LodePNG_Decoder* decoder, unsigned char* in, size_t size, void (*pf_progress)(int current, int total))
1038{
1039 if (pf_progress != NULL)
1040 pf_progress(0, 100);
1041 unsigned char IEND = 0;
1042 const unsigned char* chunk;
1043 size_t i;
1044 unsigned char *idat = memory;
1045 size_t idat_size = 0;
1046
1047 /*for unknown chunk order*/
1048 unsigned unknown = 0;
1049 unsigned critical_pos = 1; /*1 = after IHDR, 2 = after PLTE, 3 = after IDAT*/
1050
1051 /*provide some proper output values if error will happen*/
1052 decoded_image_size = 0;
1053
1054 if (size == 0 || in == 0) { decoder->error = 48; return; } /*the given data is empty*/
1055
1056 LodePNG_inspect(decoder, in, size); /*reads header and resets other parameters in decoder->infoPng*/
1057 if (decoder->error) return;
1058
1059 chunk = &in[33]; /*first byte of the first chunk after the header*/
1060
1061 while (!IEND) /*loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. IDAT data is put at the start of the in buffer*/
1062 {
1063 unsigned chunkLength;
1064 const unsigned char* data; /*the data in the chunk*/
1065
1066 if ((size_t)((chunk - in) + 12) > size || chunk < in) { decoder->error = 30; break; } /*error: size of the in buffer too small to contain next chunk*/
1067 chunkLength = LodePNG_chunk_length(chunk); /*length of the data of the chunk, excluding the length bytes, chunk type and CRC bytes*/
1068 if (chunkLength > 2147483647) { decoder->error = 63; break; }
1069 if ((size_t)((chunk - in) + chunkLength + 12) > size || (chunk + chunkLength + 12) < in) { decoder->error = 35; break; } /*error: size of the in buffer too small to contain next chunk*/
1070 data = LodePNG_chunk_data_const(chunk);
1071
1072 /*IDAT chunk, containing compressed image data*/
1073 if (LodePNG_chunk_type_equals(chunk, "IDAT"))
1074 {
1075 size_t oldsize = idat_size;
1076 idat_size += chunkLength;
1077 if (idat + idat_size >= image) { decoder->error = OUT_OF_MEMORY; break; }
1078 memcpy(idat+oldsize, data, chunkLength * sizeof(unsigned char));
1079 critical_pos = 3;
1080 }
1081 /*IEND chunk*/
1082 else if (LodePNG_chunk_type_equals(chunk, "IEND"))
1083 {
1084 IEND = 1;
1085 }
1086 /*palette chunk (PLTE)*/
1087 else if (LodePNG_chunk_type_equals(chunk, "PLTE"))
1088 {
1089 unsigned pos = 0;
1090 decoder->infoPng.color.palettesize = chunkLength / 3;
1091 if (decoder->infoPng.color.palettesize > 256) { decoder->error = 38; break; } /*error: palette too big*/
1092 for (i = 0; i < decoder->infoPng.color.palettesize; i++)
1093 {
1094 decoder->infoPng.color.palette[4 * i + 0] = data[pos++]; /*R*/
1095 decoder->infoPng.color.palette[4 * i + 1] = data[pos++]; /*G*/
1096 decoder->infoPng.color.palette[4 * i + 2] = data[pos++]; /*B*/
1097 decoder->infoPng.color.palette[4 * i + 3] = 255; /*alpha*/
1098 }
1099 critical_pos = 2;
1100 }
1101 /*palette transparency chunk (tRNS)*/
1102 else if (LodePNG_chunk_type_equals(chunk, "tRNS"))
1103 {
1104 if (decoder->infoPng.color.colorType == 3)
1105 {
1106 if (chunkLength > decoder->infoPng.color.palettesize) { decoder->error = 39; break; } /*error: more alpha values given than there are palette entries*/
1107 for (i = 0; i < chunkLength; i++) decoder->infoPng.color.palette[4 * i + 3] = data[i];
1108 }
1109 else if (decoder->infoPng.color.colorType == 0)
1110 {
1111 if (chunkLength != 2) { decoder->error = 40; break; } /*error: this chunk must be 2 bytes for greyscale image*/
1112 decoder->infoPng.color.key_defined = 1;
1113 decoder->infoPng.color.key_r = decoder->infoPng.color.key_g = decoder->infoPng.color.key_b = 256 * data[0] + data[1];
1114 }
1115 else if (decoder->infoPng.color.colorType == 2)
1116 {
1117 if (chunkLength != 6) { decoder->error = 41; break; } /*error: this chunk must be 6 bytes for RGB image*/
1118 decoder->infoPng.color.key_defined = 1;
1119 decoder->infoPng.color.key_r = 256 * data[0] + data[1];
1120 decoder->infoPng.color.key_g = 256 * data[2] + data[3];
1121 decoder->infoPng.color.key_b = 256 * data[4] + data[5];
1122 }
1123 else { decoder->error = 42; break; } /*error: tRNS chunk not allowed for other color models*/
1124 }
1125 /*background color chunk (bKGD)*/
1126 else if (LodePNG_chunk_type_equals(chunk, "bKGD"))
1127 {
1128 if (decoder->infoPng.color.colorType == 3)
1129 {
1130 if (chunkLength != 1) { decoder->error = 43; break; } /*error: this chunk must be 1 byte for indexed color image*/
1131 decoder->infoPng.background_defined = 1;
1132 decoder->infoPng.background_r = decoder->infoPng.color.palette[4 * data[0] + 0];
1133 decoder->infoPng.background_g = decoder->infoPng.color.palette[4 * data[0] + 1];
1134 decoder->infoPng.background_b = decoder->infoPng.color.palette[4 * data[0] + 2];
1135
1136 }
1137 else if (decoder->infoPng.color.colorType == 0 || decoder->infoPng.color.colorType == 4)
1138 {
1139 if (chunkLength != 2) { decoder->error = 44; break; } /*error: this chunk must be 2 bytes for greyscale image*/
1140 decoder->infoPng.background_defined = 1;
1141 decoder->infoPng.background_r = decoder->infoPng.background_g = decoder->infoPng.background_b = 256 * data[0] + data[1];
1142 }
1143 else if (decoder->infoPng.color.colorType == 2 || decoder->infoPng.color.colorType == 6)
1144 {
1145 if (chunkLength != 6) { decoder->error = 45; break; } /*error: this chunk must be 6 bytes for greyscale image*/
1146 decoder->infoPng.background_defined = 1;
1147 decoder->infoPng.background_r = 256 * data[0] + data[1];
1148 decoder->infoPng.background_g = 256 * data[2] + data[3];
1149 decoder->infoPng.background_b = 256 * data[4] + data[5];
1150 }
1151 }
1152 else if (LodePNG_chunk_type_equals(chunk, "tIME"))
1153 {
1154 if (chunkLength != 7) { decoder->error = 73; break; }
1155 decoder->infoPng.time_defined = 1;
1156 decoder->infoPng.time.year = 256 * data[0] + data[+ 1];
1157 decoder->infoPng.time.month = data[2];
1158 decoder->infoPng.time.day = data[3];
1159 decoder->infoPng.time.hour = data[4];
1160 decoder->infoPng.time.minute = data[5];
1161 decoder->infoPng.time.second = data[6];
1162 }
1163 else if (LodePNG_chunk_type_equals(chunk, "pHYs"))
1164 {
1165 if (chunkLength != 9) { decoder->error = 74; break; }
1166 decoder->infoPng.phys_defined = 1;
1167 decoder->infoPng.phys_x = 16777216 * data[0] + 65536 * data[1] + 256 * data[2] + data[3];
1168 decoder->infoPng.phys_y = 16777216 * data[4] + 65536 * data[5] + 256 * data[6] + data[7];
1169 decoder->infoPng.phys_unit = data[8];
1170 }
1171 else /*it's not an implemented chunk type, so ignore it: skip over the data*/
1172 {
1173 if (LodePNG_chunk_critical(chunk)) { decoder->error = 69; break; } /*error: unknown critical chunk (5th bit of first byte of chunk type is 0)*/
1174 unknown = 1;
1175 }
1176
1177 if (!unknown) /*check CRC if wanted, only on known chunk types*/
1178 {
1179 long time = *rb->current_tick;
1180 if (LodePNG_chunk_check_crc(chunk)) { decoder->error = 57; break; }
1181 time = *rb->current_tick-time;
1182 }
1183
1184 if (!IEND) chunk = LodePNG_chunk_next_const(chunk);
1185 }
1186
1187 if (!decoder->error)
1188 {
1189 unsigned char *scanlines = idat + idat_size;
1190 size_t scanlines_size = (size_t)memory_max - idat_size;
1191 long time = *rb->current_tick;
1192 decoder->error = LodePNG_decompress(scanlines, &scanlines_size, idat, idat_size, decoder->error_msg); /*decompress with the Zlib decompressor*/
1193 if (pf_progress) pf_progress(100, 100);
1194 time = *rb->current_tick-time;
1195
1196 if (!decoder->error)
1197 {
1198 decoded_image_size = (decoder->infoPng.height * decoder->infoPng.width * LodePNG_InfoColor_getBpp(&decoder->infoPng.color) + 7) / 8;
1199 if (decoded_image_size > memory_size) { decoder->error = OUT_OF_MEMORY; return; }
1200 decoded_image = memory_max - decoded_image_size;
1201 if (scanlines + scanlines_size >= decoded_image) { decoder->error = OUT_OF_MEMORY; return; }
1202 memset(decoded_image, 0, decoded_image_size * sizeof(unsigned char));
1203 if (!running_slideshow)
1204 {
1205 rb->lcd_puts(0, 3, "unfiltering scanlines");
1206 rb->lcd_update();
1207 }
1208 decoder->error = postProcessScanlines(decoded_image, scanlines, decoder);
1209 }
1210 }
1211}
1212
1213void LodePNG_decode(LodePNG_Decoder* decoder, unsigned char* in, size_t insize, void (*pf_progress)(int current, int total))
1214{
1215 decodeGeneric(decoder, in, insize, pf_progress);
1216 if (decoder->error) return;
1217
1218 /*TODO: check if this works according to the statement in the documentation: "The converter can convert from greyscale input color type, to 8-bit greyscale or greyscale with alpha"*/
1219 if (!(decoder->infoRaw.color.colorType == 2 || decoder->infoRaw.color.colorType == 6) && !(decoder->infoRaw.color.bitDepth == 8)) { decoder->error = 56; return; }
1220 converted_image = (fb_data *)memory;
1221 converted_image_size = decoder->infoPng.width*decoder->infoPng.height;
1222 if ((unsigned char *)(converted_image + converted_image_size) >= decoded_image) { decoder->error = OUT_OF_MEMORY; }
1223 if (!decoder->error) decoder->error = LodePNG_convert(converted_image, decoded_image, &decoder->infoRaw.color, &decoder->infoPng.color, decoder->infoPng.width, decoder->infoPng.height);
1224}
1225
1226void LodePNG_DecodeSettings_init(LodePNG_DecodeSettings* settings)
1227{
1228 settings->color_convert = 1;
1229}
1230
1231void LodePNG_Decoder_init(LodePNG_Decoder* decoder)
1232{
1233 LodePNG_DecodeSettings_init(&decoder->settings);
1234 LodePNG_InfoRaw_init(&decoder->infoRaw);
1235 LodePNG_InfoPng_init(&decoder->infoPng);
1236 decoder->error = 1;
1237}
1238
1239void LodePNG_Decoder_cleanup(LodePNG_Decoder* decoder)
1240{
1241 LodePNG_InfoRaw_cleanup(&decoder->infoRaw);
1242 LodePNG_InfoPng_cleanup(&decoder->infoPng);
1243}
1244
1245#define PNG_ERROR_MIN 27
1246#define PNG_ERROR_MAX 74
1247static const unsigned char *png_error_messages[PNG_ERROR_MAX-PNG_ERROR_MIN+1] =
1248{
1249 "png file smaller than a png header", /*27*/
1250 "incorrect png signature", /*28*/
1251 "first chunk is not IHDR", /*29*/
1252 "chunk length too large", /*30*/
1253 "illegal PNG color type or bpp", /*31*/
1254 "illegal PNG compression method", /*32*/
1255 "illegal PNG filter method", /*33*/
1256 "illegal PNG interlace method", /*34*/
1257 "chunk length of a chunk is too large or the chunk too small", /*35*/
1258 "illegal PNG filter type encountered", /*36*/
1259 "illegal bit depth for this color type given", /*37*/
1260 "the palette is too big (more than 256 colors)", /*38*/
1261 "more palette alpha values given in tRNS, than there are colors in the palette", /*39*/
1262 "tRNS chunk has wrong size for greyscale image", /*40*/
1263 "tRNS chunk has wrong size for RGB image", /*41*/
1264 "tRNS chunk appeared while it was not allowed for this color type", /*42*/
1265 "bKGD chunk has wrong size for palette image", /*43*/
1266 "bKGD chunk has wrong size for greyscale image", /*44*/
1267 "bKGD chunk has wrong size for RGB image", /*45*/
1268 "value encountered in indexed image is larger than the palette size", /*46*/
1269 "value encountered in indexed image is larger than the palette size", /*47*/
1270 "input file is empty", /*48*/
1271 NULL, /*49*/
1272 NULL, /*50*/
1273 NULL, /*51*/
1274 NULL, /*52*/
1275 NULL, /*53*/
1276 NULL, /*54*/
1277 NULL, /*55*/
1278 NULL, /*56*/
1279 "invalid CRC", /*57*/
1280 NULL, /*58*/
1281 "conversion to unexisting or unsupported color type or bit depth", /*59*/
1282 NULL, /*60*/
1283 NULL, /*61*/
1284 NULL, /*62*/
1285 "png chunk too long", /*63*/
1286 NULL, /*64*/
1287 NULL, /*65*/
1288 NULL, /*66*/
1289 NULL, /*67*/
1290 NULL, /*68*/
1291 "unknown critical chunk", /*69*/
1292 NULL, /*70*/
1293 NULL, /*71*/
1294 NULL, /*72*/
1295 "invalid tIME chunk size", /*73*/
1296 "invalid pHYs chunk size", /*74*/
1297};
1298 53
1299bool img_ext(const char *ext) 54bool img_ext(const char *ext)
1300{ 55{
@@ -1310,16 +65,33 @@ void draw_image_rect(struct image_info *info,
1310 int x, int y, int width, int height) 65 int x, int y, int width, int height)
1311{ 66{
1312 fb_data **pdisp = (fb_data**)info->data; 67 fb_data **pdisp = (fb_data**)info->data;
1313 rb->lcd_bitmap_part(*pdisp, info->x + x, info->y + y, info->width, 68
69#ifdef HAVE_LCD_COLOR
70 rb->lcd_bitmap_part(*pdisp, info->x + x, info->y + y,
71 STRIDE(SCREEN_MAIN, info->width, info->height),
1314 x + MAX(0, (LCD_WIDTH-info->width)/2), 72 x + MAX(0, (LCD_WIDTH-info->width)/2),
1315 y + MAX(0, (LCD_HEIGHT-info->height)/2), 73 y + MAX(0, (LCD_HEIGHT-info->height)/2),
1316 width, height); 74 width, height);
75#else
76 mylcd_ub_gray_bitmap_part((const unsigned char*)*pdisp,
77 info->x + x, info->y + y, info->width,
78 x + MAX(0, (LCD_WIDTH-info->width)/2),
79 y + MAX(0, (LCD_HEIGHT-info->height)/2),
80 width, height);
81#endif
1317} 82}
1318 83
1319int img_mem(int ds) 84int img_mem(int ds)
1320{ 85{
1321 LodePNG_Decoder *decoder = &_decoder; 86 LodePNG_Decoder *p_decoder = &decoder;
1322 return (decoder->infoPng.width/ds) * (decoder->infoPng.height/ds) * FB_DATA_SZ; 87
88#ifdef USEGSLIB
89 return (p_decoder->infoPng.width/ds) * (p_decoder->infoPng.height/ds);
90#else
91 return (p_decoder->infoPng.width/ds) *
92 (p_decoder->infoPng.height/ds) *
93 FB_DATA_SZ;
94#endif
1323} 95}
1324 96
1325int load_image(char *filename, struct image_info *info, 97int load_image(char *filename, struct image_info *info,
@@ -1328,10 +100,14 @@ int load_image(char *filename, struct image_info *info,
1328 int fd; 100 int fd;
1329 long time = 0; /* measured ticks */ 101 long time = 0; /* measured ticks */
1330 int w, h; /* used to center output */ 102 int w, h; /* used to center output */
1331 LodePNG_Decoder *decoder = &_decoder; 103 LodePNG_Decoder *p_decoder = &decoder;
104
105 unsigned char *memory, *memory_max;
106 static size_t memory_size, file_size;
107 static unsigned char *image;
1332 108
109 /* cleanup */
1333 memset(&disp, 0, sizeof(disp)); 110 memset(&disp, 0, sizeof(disp));
1334 LodePNG_Decoder_init(decoder);
1335 111
1336 /* align buffer */ 112 /* align buffer */
1337 memory = (unsigned char *)((intptr_t)(buf + 3) & ~3); 113 memory = (unsigned char *)((intptr_t)(buf + 3) & ~3);
@@ -1344,7 +120,7 @@ int load_image(char *filename, struct image_info *info,
1344 rb->splashf(HZ, "err opening %s: %d", filename, fd); 120 rb->splashf(HZ, "err opening %s: %d", filename, fd);
1345 return PLUGIN_ERROR; 121 return PLUGIN_ERROR;
1346 } 122 }
1347 image_size = rb->filesize(fd); 123 file_size = rb->filesize(fd);
1348 124
1349 DEBUGF("reading file '%s'\n", filename); 125 DEBUGF("reading file '%s'\n", filename);
1350 126
@@ -1353,18 +129,19 @@ int load_image(char *filename, struct image_info *info,
1353 rb->lcd_update(); 129 rb->lcd_update();
1354 } 130 }
1355 131
1356 if (image_size > memory_size) { 132 if (file_size > memory_size) {
1357 decoder->error = FILE_TOO_LARGE; 133 p_decoder->error = FILE_TOO_LARGE;
1358 rb->close(fd); 134 rb->close(fd);
1359 135
1360 } else { 136 } else {
1361 if (!running_slideshow) { 137 if (!running_slideshow) {
1362 rb->lcd_putsf(0, 1, "loading %zu bytes", image_size); 138 rb->lcd_putsf(0, 1, "loading %zu bytes", file_size);
1363 rb->lcd_update(); 139 rb->lcd_update();
1364 } 140 }
1365 141
1366 image = memory_max - image_size; 142 /* load file to the end of the buffer */
1367 rb->read(fd, image, image_size); 143 image = memory_max - file_size;
144 rb->read(fd, image, file_size);
1368 rb->close(fd); 145 rb->close(fd);
1369 146
1370 if (!running_slideshow) { 147 if (!running_slideshow) {
@@ -1378,19 +155,27 @@ int load_image(char *filename, struct image_info *info,
1378 } 155 }
1379#endif 156#endif
1380 157
1381 decoder->settings.color_convert = 1; 158 /* Initialize decoder context struct, set buffer decoder is free
1382 decoder->infoRaw.color.colorType = 2; 159 * to use.
1383 decoder->infoRaw.color.bitDepth = 8; 160 * Decoder assumes that raw image file is loaded at the very
161 * end of the allocated buffer
162 */
163 LodePNG_Decoder_init(p_decoder, memory, memory_size);
1384 164
1385 LodePNG_inspect(decoder, image, image_size); 165 /* read file header; file is loaded at the end
166 * of the allocated buffer
167 */
168 LodePNG_inspect(p_decoder, image, file_size);
1386 169
1387 if (!decoder->error) { 170 if (!p_decoder->error) {
1388 171
1389 if (!running_slideshow) { 172 if (!running_slideshow) {
1390 rb->lcd_putsf(0, 2, "image %dx%d", 173 rb->lcd_putsf(0, 2, "image %dx%d",
1391 decoder->infoPng.width, decoder->infoPng.height); 174 p_decoder->infoPng.width,
175 p_decoder->infoPng.height);
1392 rb->lcd_putsf(0, 3, "decoding %d*%d", 176 rb->lcd_putsf(0, 3, "decoding %d*%d",
1393 decoder->infoPng.width, decoder->infoPng.height); 177 p_decoder->infoPng.width,
178 p_decoder->infoPng.height);
1394 rb->lcd_update(); 179 rb->lcd_update();
1395 } 180 }
1396 181
@@ -1398,16 +183,16 @@ int load_image(char *filename, struct image_info *info,
1398 time = *rb->current_tick; 183 time = *rb->current_tick;
1399#ifdef HAVE_ADJUSTABLE_CPU_FREQ 184#ifdef HAVE_ADJUSTABLE_CPU_FREQ
1400 rb->cpu_boost(true); 185 rb->cpu_boost(true);
1401 LodePNG_decode(decoder, image, image_size, cb_progress); 186 LodePNG_decode(p_decoder, image, file_size, cb_progress);
1402 rb->cpu_boost(false); 187 rb->cpu_boost(false);
1403#else 188#else
1404 LodePNG_decode(decoder, image, image_size, cb_progress); 189 LodePNG_decode(p_decoder, image, file_size, cb_progress);
1405#endif /*HAVE_ADJUSTABLE_CPU_FREQ*/ 190#endif /*HAVE_ADJUSTABLE_CPU_FREQ*/
1406 time = *rb->current_tick - time; 191 time = *rb->current_tick - time;
1407 } 192 }
1408 } 193 }
1409 194
1410 if (!running_slideshow && !decoder->error) 195 if (!running_slideshow && !p_decoder->error)
1411 { 196 {
1412 rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ); 197 rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ);
1413 rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */ 198 rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */
@@ -1415,55 +200,59 @@ int load_image(char *filename, struct image_info *info,
1415 rb->lcd_update(); 200 rb->lcd_update();
1416 } 201 }
1417 202
1418 if (decoder->error) { 203 if (p_decoder->error) {
1419#ifdef USE_PLUG_BUF 204#ifdef USE_PLUG_BUF
1420 if (plug_buf && (decoder->error == FILE_TOO_LARGE 205 if (plug_buf && (p_decoder->error == FILE_TOO_LARGE ||
1421 || decoder->error == OUT_OF_MEMORY || decoder->error == Z_MEM_ERROR)) 206 p_decoder->error == OUT_OF_MEMORY ||
207 p_decoder->error == TINF_DATA_ERROR))
1422 return PLUGIN_OUTOFMEM; 208 return PLUGIN_OUTOFMEM;
1423#endif 209#endif
1424 210
1425 if (decoder->error >= PNG_ERROR_MIN && decoder->error <= PNG_ERROR_MAX 211 if (p_decoder->error >= PNG_ERROR_MIN &&
1426 && png_error_messages[decoder->error-PNG_ERROR_MIN] != NULL) 212 p_decoder->error <= PNG_ERROR_MAX &&
213 LodePNG_perror(p_decoder) != NULL)
1427 { 214 {
1428 rb->splash(HZ, png_error_messages[decoder->error-PNG_ERROR_MIN]); 215 rb->splash(HZ, LodePNG_perror(p_decoder));
1429 } 216 }
1430 else 217 else
1431 { 218 {
1432 switch (decoder->error) { 219 switch (p_decoder->error) {
1433 case PLUGIN_ABORT: 220 case PLUGIN_ABORT:
1434 break; 221 break;
1435 case OUT_OF_MEMORY: 222 case OUT_OF_MEMORY:
1436 case Z_MEM_ERROR:
1437 rb->splash(HZ, "Out of Memory");break; 223 rb->splash(HZ, "Out of Memory");break;
1438 case FILE_TOO_LARGE: 224 case FILE_TOO_LARGE:
1439 rb->splash(HZ, "File too large");break; 225 rb->splash(HZ, "File too large");break;
1440 case Z_DATA_ERROR: 226 case TINF_DATA_ERROR:
1441 rb->splash(HZ, decoder->error_msg);break; 227 rb->splash(HZ, "Zlib decompressor error");break;
1442 default: 228 default:
1443 rb->splashf(HZ, "other error : %ld", decoder->error);break; 229 rb->splashf(HZ, "other error : %ld", p_decoder->error);break;
1444 } 230 }
1445 } 231 }
1446 232
1447 if (decoder->error == PLUGIN_ABORT) 233 if (p_decoder->error == PLUGIN_ABORT)
1448 return PLUGIN_ABORT; 234 return PLUGIN_ABORT;
1449 else 235 else
1450 return PLUGIN_ERROR; 236 return PLUGIN_ERROR;
1451 } 237 }
1452 238
1453 disp_buf = converted_image + converted_image_size; 239 info->x_size = p_decoder->infoPng.width;
1454 info->x_size = decoder->infoPng.width; 240 info->y_size = p_decoder->infoPng.height;
1455 info->y_size = decoder->infoPng.height; 241
242 disp_buf = (fb_data *)(p_decoder->buf + p_decoder->native_img_size);
243 disp_buf = (fb_data *)ALIGN_UP((uintptr_t)disp_buf,4);
1456 *buf_size = memory_max - (unsigned char*)disp_buf; 244 *buf_size = memory_max - (unsigned char*)disp_buf;
245
1457 return PLUGIN_OK; 246 return PLUGIN_OK;
1458} 247}
1459 248
1460int get_image(struct image_info *info, int ds) 249int get_image(struct image_info *info, int ds)
1461{ 250{
1462 fb_data **p_disp = &disp[ds]; /* short cut */ 251 fb_data **p_disp = &disp[ds]; /* short cut */
1463 LodePNG_Decoder *decoder = &_decoder; 252 LodePNG_Decoder *p_decoder = &decoder;
1464 253
1465 info->width = decoder->infoPng.width / ds; 254 info->width = p_decoder->infoPng.width / ds;
1466 info->height = decoder->infoPng.height / ds; 255 info->height = p_decoder->infoPng.height / ds;
1467 info->data = p_disp; 256 info->data = p_disp;
1468 257
1469 if (*p_disp != NULL) 258 if (*p_disp != NULL)
@@ -1483,34 +272,40 @@ int get_image(struct image_info *info, int ds)
1483 272
1484 int size = info->width * info->height; 273 int size = info->width * info->height;
1485 274
1486 if ((unsigned char *)(disp_buf + size) >= memory_max) { 275 if ((unsigned char *)(disp_buf + size) >= p_decoder->buf + p_decoder->buf_size) {
1487 /* have to discard the current */ 276 /* have to discard the current */
1488 int i; 277 int i;
1489 for (i=1; i<=8; i++) 278 for (i=1; i<=8; i++)
1490 disp[i] = NULL; /* invalidate all bitmaps */ 279 disp[i] = NULL; /* invalidate all bitmaps */
280
1491 /* start again from the beginning of the buffer */ 281 /* start again from the beginning of the buffer */
1492 disp_buf = converted_image + converted_image_size; 282 disp_buf = (fb_data *)(p_decoder->buf + p_decoder->native_img_size);
283 disp_buf = (fb_data *)ALIGN_UP((uintptr_t)disp_buf,4);
1493 } 284 }
1494 285
1495 *p_disp = disp_buf; 286 *p_disp = disp_buf;
287#ifdef USEGSLIB
288 disp_buf = (fb_data *)((unsigned char *)disp_buf + size);
289#else
1496 disp_buf += size; 290 disp_buf += size;
291#endif
1497 292
1498 bmp_src.width = decoder->infoPng.width; 293 bmp_src.width = p_decoder->infoPng.width;
1499 bmp_src.height = decoder->infoPng.height; 294 bmp_src.height = p_decoder->infoPng.height;
1500 bmp_src.data = (unsigned char *)converted_image; 295 bmp_src.data = (unsigned char *)p_decoder->buf;
1501 296
1502 bmp_dst.width = info->width; 297 bmp_dst.width = info->width;
1503 bmp_dst.height = info->height; 298 bmp_dst.height = info->height;
1504 bmp_dst.data = (unsigned char *)*p_disp; 299 bmp_dst.data = (unsigned char *)*p_disp;
1505#ifdef HAVE_ADJUSTABLE_CPU_FREQ 300#ifdef HAVE_ADJUSTABLE_CPU_FREQ
1506 rb->cpu_boost(true); 301 rb->cpu_boost(true);
1507 smooth_resize_bitmap(&bmp_src, &bmp_dst); 302 resize_bitmap(&bmp_src, &bmp_dst);
1508 rb->cpu_boost(false); 303 rb->cpu_boost(false);
1509#else 304#else
1510 smooth_resize_bitmap(&bmp_src, &bmp_dst); 305 resize_bitmap(&bmp_src, &bmp_dst);
1511#endif /*HAVE_ADJUSTABLE_CPU_FREQ*/ 306#endif /*HAVE_ADJUSTABLE_CPU_FREQ*/
1512 } else { 307 } else {
1513 *p_disp = converted_image; 308 *p_disp = (fb_data *)p_decoder->buf;
1514 } 309 }
1515 310
1516 return PLUGIN_OK; 311 return PLUGIN_OK;