summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/plugins/imageviewer/png/png.c45
-rw-r--r--apps/plugins/imageviewer/png/png.h25
-rw-r--r--apps/plugins/imageviewer/png/png_decoder.c1082
-rw-r--r--apps/plugins/imageviewer/png/tinflate.c4
4 files changed, 561 insertions, 595 deletions
diff --git a/apps/plugins/imageviewer/png/png.c b/apps/plugins/imageviewer/png/png.c
index 4bd988d939..956cad37d8 100644
--- a/apps/plugins/imageviewer/png/png.c
+++ b/apps/plugins/imageviewer/png/png.c
@@ -31,19 +31,18 @@
31#include "lcd.h" 31#include "lcd.h"
32#include <lib/pluginlib_bmp.h> 32#include <lib/pluginlib_bmp.h>
33#include "tinf.h" 33#include "tinf.h"
34#include "png.h" 34#include "../imageviewer.h"
35#include "png_decoder.h" 35#include "png_decoder.h"
36#include "bmp.h" 36#include "bmp.h"
37 37
38/* decoder context struct */ 38/* decoder context struct */
39static LodePNG_Decoder decoder; 39static LodePNG_Decoder decoder;
40 40
41/* my memory pool (from the mp3 buffer) */ 41static char print[32]; /* use a common snprintf() buffer */
42static char print[128]; /* use a common snprintf() buffer */
43 42
44/* decompressed image in the possible sizes (1,2,4,8), wasting the other */ 43/* decompressed image in the possible sizes (1,2,4,8), wasting the other */
45static fb_data *disp[9]; 44static unsigned char *disp[9];
46static fb_data *disp_buf; 45static unsigned char *disp_buf;
47 46
48#if defined(HAVE_LCD_COLOR) 47#if defined(HAVE_LCD_COLOR)
49#define resize_bitmap smooth_resize_bitmap 48#define resize_bitmap smooth_resize_bitmap
@@ -64,16 +63,16 @@ bool img_ext(const char *ext)
64void draw_image_rect(struct image_info *info, 63void draw_image_rect(struct image_info *info,
65 int x, int y, int width, int height) 64 int x, int y, int width, int height)
66{ 65{
67 fb_data **pdisp = (fb_data**)info->data; 66 unsigned char **pdisp = (unsigned char **)info->data;
68 67
69#ifdef HAVE_LCD_COLOR 68#ifdef HAVE_LCD_COLOR
70 rb->lcd_bitmap_part(*pdisp, info->x + x, info->y + y, 69 rb->lcd_bitmap_part((fb_data *)*pdisp, info->x + x, info->y + y,
71 STRIDE(SCREEN_MAIN, info->width, info->height), 70 STRIDE(SCREEN_MAIN, info->width, info->height),
72 x + MAX(0, (LCD_WIDTH-info->width)/2), 71 x + MAX(0, (LCD_WIDTH-info->width)/2),
73 y + MAX(0, (LCD_HEIGHT-info->height)/2), 72 y + MAX(0, (LCD_HEIGHT-info->height)/2),
74 width, height); 73 width, height);
75#else 74#else
76 mylcd_ub_gray_bitmap_part((const unsigned char*)*pdisp, 75 mylcd_ub_gray_bitmap_part(*pdisp,
77 info->x + x, info->y + y, info->width, 76 info->x + x, info->y + y, info->width,
78 x + MAX(0, (LCD_WIDTH-info->width)/2), 77 x + MAX(0, (LCD_WIDTH-info->width)/2),
79 y + MAX(0, (LCD_HEIGHT-info->height)/2), 78 y + MAX(0, (LCD_HEIGHT-info->height)/2),
@@ -102,9 +101,8 @@ int load_image(char *filename, struct image_info *info,
102 int w, h; /* used to center output */ 101 int w, h; /* used to center output */
103 LodePNG_Decoder *p_decoder = &decoder; 102 LodePNG_Decoder *p_decoder = &decoder;
104 103
105 unsigned char *memory, *memory_max; 104 unsigned char *memory, *memory_max, *image;
106 static size_t memory_size, file_size; 105 size_t memory_size, file_size;
107 static unsigned char *image;
108 106
109 /* cleanup */ 107 /* cleanup */
110 memset(&disp, 0, sizeof(disp)); 108 memset(&disp, 0, sizeof(disp));
@@ -239,16 +237,16 @@ int load_image(char *filename, struct image_info *info,
239 info->x_size = p_decoder->infoPng.width; 237 info->x_size = p_decoder->infoPng.width;
240 info->y_size = p_decoder->infoPng.height; 238 info->y_size = p_decoder->infoPng.height;
241 239
242 disp_buf = (fb_data *)(p_decoder->buf + p_decoder->native_img_size); 240 p_decoder->native_img_size = (p_decoder->native_img_size + 3) & ~3;
243 disp_buf = (fb_data *)ALIGN_UP((uintptr_t)disp_buf,4); 241 disp_buf = p_decoder->buf + p_decoder->native_img_size;
244 *buf_size = memory_max - (unsigned char*)disp_buf; 242 *buf_size = memory_max - disp_buf;
245 243
246 return PLUGIN_OK; 244 return PLUGIN_OK;
247} 245}
248 246
249int get_image(struct image_info *info, int ds) 247int get_image(struct image_info *info, int ds)
250{ 248{
251 fb_data **p_disp = &disp[ds]; /* short cut */ 249 unsigned char **p_disp = &disp[ds]; /* short cut */
252 LodePNG_Decoder *p_decoder = &decoder; 250 LodePNG_Decoder *p_decoder = &decoder;
253 251
254 info->width = p_decoder->infoPng.width / ds; 252 info->width = p_decoder->infoPng.width / ds;
@@ -270,33 +268,28 @@ int get_image(struct image_info *info, int ds)
270 } 268 }
271 struct bitmap bmp_src, bmp_dst; 269 struct bitmap bmp_src, bmp_dst;
272 270
273 int size = info->width * info->height; 271 int size = img_mem(ds);
274 272
275 if ((unsigned char *)(disp_buf + size) >= p_decoder->buf + p_decoder->buf_size) { 273 if (disp_buf + size >= p_decoder->buf + p_decoder->buf_size) {
276 /* have to discard the current */ 274 /* have to discard the current */
277 int i; 275 int i;
278 for (i=1; i<=8; i++) 276 for (i=1; i<=8; i++)
279 disp[i] = NULL; /* invalidate all bitmaps */ 277 disp[i] = NULL; /* invalidate all bitmaps */
280 278
281 /* start again from the beginning of the buffer */ 279 /* start again from the beginning of the buffer */
282 disp_buf = (fb_data *)(p_decoder->buf + p_decoder->native_img_size); 280 disp_buf = p_decoder->buf + p_decoder->native_img_size;
283 disp_buf = (fb_data *)ALIGN_UP((uintptr_t)disp_buf,4);
284 } 281 }
285 282
286 *p_disp = disp_buf; 283 *p_disp = disp_buf;
287#ifdef USEGSLIB
288 disp_buf = (fb_data *)((unsigned char *)disp_buf + size);
289#else
290 disp_buf += size; 284 disp_buf += size;
291#endif
292 285
293 bmp_src.width = p_decoder->infoPng.width; 286 bmp_src.width = p_decoder->infoPng.width;
294 bmp_src.height = p_decoder->infoPng.height; 287 bmp_src.height = p_decoder->infoPng.height;
295 bmp_src.data = (unsigned char *)p_decoder->buf; 288 bmp_src.data = p_decoder->buf;
296 289
297 bmp_dst.width = info->width; 290 bmp_dst.width = info->width;
298 bmp_dst.height = info->height; 291 bmp_dst.height = info->height;
299 bmp_dst.data = (unsigned char *)*p_disp; 292 bmp_dst.data = *p_disp;
300#ifdef HAVE_ADJUSTABLE_CPU_FREQ 293#ifdef HAVE_ADJUSTABLE_CPU_FREQ
301 rb->cpu_boost(true); 294 rb->cpu_boost(true);
302 resize_bitmap(&bmp_src, &bmp_dst); 295 resize_bitmap(&bmp_src, &bmp_dst);
@@ -305,7 +298,7 @@ int get_image(struct image_info *info, int ds)
305 resize_bitmap(&bmp_src, &bmp_dst); 298 resize_bitmap(&bmp_src, &bmp_dst);
306#endif /*HAVE_ADJUSTABLE_CPU_FREQ*/ 299#endif /*HAVE_ADJUSTABLE_CPU_FREQ*/
307 } else { 300 } else {
308 *p_disp = (fb_data *)p_decoder->buf; 301 *p_disp = p_decoder->buf;
309 } 302 }
310 303
311 return PLUGIN_OK; 304 return PLUGIN_OK;
diff --git a/apps/plugins/imageviewer/png/png.h b/apps/plugins/imageviewer/png/png.h
deleted file mode 100644
index f5c76f1f44..0000000000
--- a/apps/plugins/imageviewer/png/png.h
+++ /dev/null
@@ -1,25 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$id $
9 *
10 * Copyright (C) 2009 by Christophe Gouiran <bechris13250 -at- gmail -dot- com>
11 *
12 * Based on lodepng, a lightweight png decoder/encoder
13 * (c) 2005-2008 Lode Vandevenne
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
22 *
23 ****************************************************************************/
24
25#include "../imageviewer.h"
diff --git a/apps/plugins/imageviewer/png/png_decoder.c b/apps/plugins/imageviewer/png/png_decoder.c
index b09d2e2ece..a0ce0519de 100644
--- a/apps/plugins/imageviewer/png/png_decoder.c
+++ b/apps/plugins/imageviewer/png/png_decoder.c
@@ -199,7 +199,7 @@ static void setBitOfReversedStream0(size_t* bitpointer,
199 */ 199 */
200 if (bit) 200 if (bit)
201 bitstream[(*bitpointer) >> 3] |= (bit << (7 - ((*bitpointer) & 0x7))); 201 bitstream[(*bitpointer) >> 3] |= (bit << (7 - ((*bitpointer) & 0x7)));
202 202
203 (*bitpointer)++; 203 (*bitpointer)++;
204} 204}
205 205
@@ -408,7 +408,7 @@ static void LodePNG_convert(LodePNG_Decoder *decoder)
408#ifdef HAVE_LCD_COLOR 408#ifdef HAVE_LCD_COLOR
409 struct uint8_rgb *line_buf = (struct uint8_rgb *)(out + w * h * FB_DATA_SZ); 409 struct uint8_rgb *line_buf = (struct uint8_rgb *)(out + w * h * FB_DATA_SZ);
410#else 410#else
411 uint8_t *line_buf = (unsigned char *)(out + w * h * FB_DATA_SZ); 411 uint8_t *line_buf = (unsigned char *)(out + w * h);
412#endif 412#endif
413 413
414 struct bitmap bm = { 414 struct bitmap bm = {
@@ -428,585 +428,585 @@ static void LodePNG_convert(LodePNG_Decoder *decoder)
428 const struct custom_format *cformat = &format_native; 428 const struct custom_format *cformat = &format_native;
429#endif 429#endif
430 430
431void (*output_row_8)(uint32_t, void*, struct scaler_context*) = cformat->output_row_8; 431 void (*output_row_8)(uint32_t, void*, struct scaler_context*) = cformat->output_row_8;
432 432
433#ifdef HAVE_LCD_COLOR 433#ifdef HAVE_LCD_COLOR
434struct uint8_rgb *pixel; 434 struct uint8_rgb *pixel;
435#else 435#else
436unsigned char *pixel; 436 unsigned char *pixel;
437#endif 437#endif
438 438
439#ifdef HAVE_LCD_COLOR 439#ifdef HAVE_LCD_COLOR
440 if (infoIn->color.bitDepth == 8) 440 if (infoIn->color.bitDepth == 8)
441 {
442 switch (infoIn->color.colorType)
441 { 443 {
442 switch (infoIn->color.colorType) 444 case PNG_COLORTYPE_GREY: /*greyscale color*/
443 { 445 i = 0;
444 case PNG_COLORTYPE_GREY: /*greyscale color*/ 446 for (y = 0 ; y < h ; y++) {
445 i = 0; 447 /* reset line buf */
446 for (y = 0 ; y < h ; y++) { 448 pixel = line_buf;
447 /* reset line buf */ 449
448 pixel = line_buf; 450 for (x = 0; x < w ; x++) {
449 451 value = in[i++];
450 for (x = 0; x < w ; x++) { 452 if (infoIn->color.key_defined)
451 value = in[i++]; 453 if ( (uint8_t)value == (uint8_t)infoIn->color.key_r )
452 if (infoIn->color.key_defined) 454 value = infoIn->background_r; /* full transparent */
453 if ( (uint8_t)value == (uint8_t)infoIn->color.key_r ) 455
454 value = infoIn->background_r; /* full transparent */ 456 pixel->red = (uint8_t)value;
455 457 pixel->green = (uint8_t)value;
456 pixel->red = (uint8_t)value; 458 pixel->blue = (uint8_t)value;
457 pixel->green = (uint8_t)value; 459 pixel++;
458 pixel->blue = (uint8_t)value;
459 pixel++;
460 }
461 output_row_8(y,(void *)line_buf,&ctx);
462 } 460 }
463 break; 461 output_row_8(y,(void *)line_buf,&ctx);
464 case PNG_COLORTYPE_RGB: /*RGB color*/ 462 }
465 i = 0; 463 break;
466 for (y = 0 ; y < h ; y++) { 464 case PNG_COLORTYPE_RGB: /*RGB color*/
467 pixel = line_buf; 465 i = 0;
468 for (x = 0 ; x < w ; x++) { 466 for (y = 0 ; y < h ; y++) {
469 j = 3*i++; 467 pixel = line_buf;
470 468 for (x = 0 ; x < w ; x++) {
471 /* tRNs & bKGD */ 469 j = 3*i++;
472 if (infoIn->color.key_defined && 470
473 in[j] == (uint8_t)infoIn->color.key_r && 471 /* tRNs & bKGD */
474 in[j + 1] == (uint8_t)infoIn->color.key_g && 472 if (infoIn->color.key_defined &&
475 in[j + 2] == (uint8_t)infoIn->color.key_b) 473 in[j] == (uint8_t)infoIn->color.key_r &&
476 { 474 in[j + 1] == (uint8_t)infoIn->color.key_g &&
477 pixel->red = (uint8_t)infoIn->background_r; 475 in[j + 2] == (uint8_t)infoIn->color.key_b)
478 pixel->green = (uint8_t)infoIn->background_g; 476 {
479 pixel->blue = (uint8_t)infoIn->background_b; 477 pixel->red = (uint8_t)infoIn->background_r;
480 } 478 pixel->green = (uint8_t)infoIn->background_g;
481 else 479 pixel->blue = (uint8_t)infoIn->background_b;
482 {
483 pixel->red = in[j];
484 pixel->green = in[j + 1];
485 pixel->blue = in[j + 2];
486 }
487 pixel++;
488 } 480 }
489 output_row_8(y,(void *)line_buf,&ctx); 481 else
490 } 482 {
491 break; 483 pixel->red = in[j];
492 case PNG_COLORTYPE_PALETTE: /*indexed color (palette)*/ 484 pixel->green = in[j + 1];
493 i = 0; 485 pixel->blue = in[j + 2];
494 for (y = 0 ; y < h ; y++) {
495 /* reset line buf */
496 pixel = line_buf;
497 for (x = 0 ; x < w ; x++) {
498 if (in[i] >= infoIn->color.palettesize)
499 {
500 decoder->error = 46;
501 return;
502 }
503
504 j = in[i++]<<2;
505 alpha = infoIn->color.palette[j + 3];
506 alpha_complement = (256 - alpha);
507
508 /* tRNS and bKGD */
509 pixel->red = (infoIn->color.palette[j] * alpha +
510 alpha_complement*infoIn->background_r)>>8;
511 pixel->green = (infoIn->color.palette[j + 1] * alpha +
512 alpha_complement*infoIn->background_g)>>8;
513 pixel->blue = (infoIn->color.palette[j + 2] * alpha +
514 alpha_complement*infoIn->background_b)>>8;
515 pixel++;
516 } 486 }
517 output_row_8(y,(void *)(line_buf),&ctx); 487 pixel++;
518 } 488 }
519 break; 489 output_row_8(y,(void *)line_buf,&ctx);
520 case PNG_COLORTYPE_GREYA: /*greyscale with alpha*/ 490 }
521 i = 0; 491 break;
522 for (y = 0 ; y < h ; y++) { 492 case PNG_COLORTYPE_PALETTE: /*indexed color (palette)*/
523 pixel = line_buf; 493 i = 0;
524 for (x = 0 ; x < w ; x++) { 494 for (y = 0 ; y < h ; y++) {
525 alpha = in[(i << 1) + 1]; 495 /* reset line buf */
526 alpha_complement = (256 - alpha)*infoIn->background_r; 496 pixel = line_buf;
527 value = (alpha * in[i++ << 1] + alpha_complement)>>8; 497 for (x = 0 ; x < w ; x++) {
528 pixel->red = (uint8_t)(value); 498 if (in[i] >= infoIn->color.palettesize)
529 pixel->green = (uint8_t)value; 499 {
530 pixel->blue = (uint8_t)value; 500 decoder->error = 46;
531 pixel++; 501 return;
532 } 502 }
533 output_row_8(y,(void *)line_buf,&ctx); 503
504 j = in[i++]<<2;
505 alpha = infoIn->color.palette[j + 3];
506 alpha_complement = (256 - alpha);
507
508 /* tRNS and bKGD */
509 pixel->red = (infoIn->color.palette[j] * alpha +
510 alpha_complement*infoIn->background_r)>>8;
511 pixel->green = (infoIn->color.palette[j + 1] * alpha +
512 alpha_complement*infoIn->background_g)>>8;
513 pixel->blue = (infoIn->color.palette[j + 2] * alpha +
514 alpha_complement*infoIn->background_b)>>8;
515 pixel++;
534 } 516 }
535 break; 517 output_row_8(y,(void *)(line_buf),&ctx);
536 case PNG_COLORTYPE_RGBA: /*RGB with alpha*/ 518 }
537 i = 0; 519 break;
538 for (y = 0 ; y < h ; y++) { 520 case PNG_COLORTYPE_GREYA: /*greyscale with alpha*/
539 pixel = line_buf; 521 i = 0;
540 for (x = 0 ; x < w ; x++) { 522 for (y = 0 ; y < h ; y++) {
541 j = i++ << 2; 523 pixel = line_buf;
542 alpha = in[j + 3]; 524 for (x = 0 ; x < w ; x++) {
543 alpha_complement = (256 - alpha); 525 alpha = in[(i << 1) + 1];
544 pixel->red = (in[j] * alpha + 526 alpha_complement = (256 - alpha)*infoIn->background_r;
545 alpha_complement*infoIn->background_r)>>8; 527 value = (alpha * in[i++ << 1] + alpha_complement)>>8;
546 pixel->green = (in[j + 1] * alpha + 528 pixel->red = (uint8_t)(value);
547 alpha_complement*infoIn->background_g)>>8; 529 pixel->green = (uint8_t)value;
548 pixel->blue = (in[j + 2] * alpha + 530 pixel->blue = (uint8_t)value;
549 alpha_complement*infoIn->background_b)>>8; 531 pixel++;
550 pixel++;
551 }
552 output_row_8(y,(void *)line_buf,&ctx);
553 } 532 }
554 break; 533 output_row_8(y,(void *)line_buf,&ctx);
555 default: 534 }
556 break; 535 break;
536 case PNG_COLORTYPE_RGBA: /*RGB with alpha*/
537 i = 0;
538 for (y = 0 ; y < h ; y++) {
539 pixel = line_buf;
540 for (x = 0 ; x < w ; x++) {
541 j = i++ << 2;
542 alpha = in[j + 3];
543 alpha_complement = (256 - alpha);
544 pixel->red = (in[j] * alpha +
545 alpha_complement*infoIn->background_r)>>8;
546 pixel->green = (in[j + 1] * alpha +
547 alpha_complement*infoIn->background_g)>>8;
548 pixel->blue = (in[j + 2] * alpha +
549 alpha_complement*infoIn->background_b)>>8;
550 pixel++;
551 }
552 output_row_8(y,(void *)line_buf,&ctx);
557 } 553 }
554 break;
555 default:
556 break;
558 } 557 }
559 else if (infoIn->color.bitDepth == 16) 558 }
559 else if (infoIn->color.bitDepth == 16)
560 {
561 switch (infoIn->color.colorType)
560 { 562 {
561 switch (infoIn->color.colorType) 563 case PNG_COLORTYPE_GREY: /*greyscale color*/
562 { 564 i = 0;
563 case PNG_COLORTYPE_GREY: /*greyscale color*/ 565 for (y = 0 ; y < h ; y++) {
564 i = 0; 566 pixel = line_buf;
565 for (y = 0 ; y < h ; y++) { 567 for (x = 0 ; x < w ; x++) {
566 pixel = line_buf; 568 value = (in[i<<1]<<8)|in[(i << 1) + 1];
567 for (x = 0 ; x < w ; x++) { 569 i++;
568 value = (in[i<<1]<<8)|in[(i << 1) + 1]; 570
569 i++; 571 /* tRNS and bKGD */
570 572 if (infoIn->color.key_defined &&
571 /* tRNS and bKGD */ 573 value == infoIn->color.key_r)
572 if (infoIn->color.key_defined && 574 value = infoIn->background_r<<8;
573 value == infoIn->color.key_r) 575
574 value = infoIn->background_r<<8; 576 pixel->red =
575 577 pixel->green =
576 pixel->red = 578 pixel->blue = (uint8_t)(value>>8);
577 pixel->green = 579 pixel++;
578 pixel->blue = (uint8_t)(value>>8);
579 pixel++;
580 }
581 output_row_8(y,(void *)line_buf,&ctx);
582 } 580 }
583 break; 581 output_row_8(y,(void *)line_buf,&ctx);
584 case PNG_COLORTYPE_RGB: /*RGB color*/ 582 }
585 i = 0; 583 break;
586 for (y = 0 ; y < h ; y++) { 584 case PNG_COLORTYPE_RGB: /*RGB color*/
587 pixel = line_buf; 585 i = 0;
588 for (x = 0 ; x < w ; x++) { 586 for (y = 0 ; y < h ; y++) {
589 j = 6 * i++; 587 pixel = line_buf;
590 588 for (x = 0 ; x < w ; x++) {
591 /* tRNS and bKGD */ 589 j = 6 * i++;
592 if (infoIn->color.key_defined && 590
593 ((uint16_t)(in[j]<<8|in[j + 1]) == 591 /* tRNS and bKGD */
594 infoIn->color.key_r) && 592 if (infoIn->color.key_defined &&
595 ((uint16_t)(in[j + 2]<<8|in[j + 3]) == 593 ((uint16_t)(in[j]<<8|in[j + 1]) ==
596 infoIn->color.key_g) && 594 infoIn->color.key_r) &&
597 ((uint16_t)(in[j + 4]<<8|in[j + 5]) == 595 ((uint16_t)(in[j + 2]<<8|in[j + 3]) ==
598 infoIn->color.key_b)) 596 infoIn->color.key_g) &&
599 { 597 ((uint16_t)(in[j + 4]<<8|in[j + 5]) ==
600 pixel->red = (uint8_t)infoIn->background_r; 598 infoIn->color.key_b))
601 pixel->green = (uint8_t)infoIn->background_g; 599 {
602 pixel->blue = (uint8_t)infoIn->background_b; 600 pixel->red = (uint8_t)infoIn->background_r;
603 } 601 pixel->green = (uint8_t)infoIn->background_g;
604 else 602 pixel->blue = (uint8_t)infoIn->background_b;
605 {
606 pixel->red = in[j];
607 pixel->green = in[j + 2];
608 pixel->blue = in[j + 4];
609 }
610 pixel++;
611 } 603 }
612 output_row_8(y,(void *)line_buf,&ctx); 604 else
613 } 605 {
614 break; 606 pixel->red = in[j];
615 case PNG_COLORTYPE_GREYA: /*greyscale with alpha*/ 607 pixel->green = in[j + 2];
616 i = 0; 608 pixel->blue = in[j + 4];
617 for (y = 0 ; y < h ; y++) {
618 pixel = line_buf;
619 for (x = 0 ; x < w ; x++) {
620 alpha = in[(i << 2) + 2];
621 alpha_complement = (256-alpha)*infoIn->background_r;
622 value = (in[i++ << 2] * alpha + alpha_complement)>>8;
623 pixel->red = (uint8_t)value;
624 pixel->green = (uint8_t)value;
625 pixel->blue = (uint8_t)value;
626 pixel++;
627 } 609 }
628 output_row_8(y,(void *)line_buf,&ctx); 610 pixel++;
629 } 611 }
630 break; 612 output_row_8(y,(void *)line_buf,&ctx);
631 case PNG_COLORTYPE_RGBA: /*RGB with alpha*/ 613 }
632 i = 0; 614 break;
633 for (y = 0 ; y < h ; y++) { 615 case PNG_COLORTYPE_GREYA: /*greyscale with alpha*/
634 pixel = line_buf; 616 i = 0;
635 for (x = 0 ; x < w ; x++) { 617 for (y = 0 ; y < h ; y++) {
636 j = i++ << 3; 618 pixel = line_buf;
637 alpha = in[j + 6]; 619 for (x = 0 ; x < w ; x++) {
638 alpha_complement = (256-alpha); 620 alpha = in[(i << 2) + 2];
639 pixel->red = (in[j] * alpha + 621 alpha_complement = (256-alpha)*infoIn->background_r;
640 alpha_complement*infoIn->background_r)>>8; 622 value = (in[i++ << 2] * alpha + alpha_complement)>>8;
641 pixel->green = (in[j + 2] * alpha + 623 pixel->red = (uint8_t)value;
642 alpha_complement*infoIn->background_g)>>8; 624 pixel->green = (uint8_t)value;
643 pixel->blue = (in[j + 4] * alpha + 625 pixel->blue = (uint8_t)value;
644 alpha_complement*infoIn->background_b)>>8; 626 pixel++;
645 pixel++;
646 }
647 output_row_8(y,(void *)line_buf,&ctx);
648 } 627 }
649 break; 628 output_row_8(y,(void *)line_buf,&ctx);
650 default:
651 break;
652 } 629 }
630 break;
631 case PNG_COLORTYPE_RGBA: /*RGB with alpha*/
632 i = 0;
633 for (y = 0 ; y < h ; y++) {
634 pixel = line_buf;
635 for (x = 0 ; x < w ; x++) {
636 j = i++ << 3;
637 alpha = in[j + 6];
638 alpha_complement = (256-alpha);
639 pixel->red = (in[j] * alpha +
640 alpha_complement*infoIn->background_r)>>8;
641 pixel->green = (in[j + 2] * alpha +
642 alpha_complement*infoIn->background_g)>>8;
643 pixel->blue = (in[j + 4] * alpha +
644 alpha_complement*infoIn->background_b)>>8;
645 pixel++;
646 }
647 output_row_8(y,(void *)line_buf,&ctx);
648 }
649 break;
650 default:
651 break;
653 } 652 }
654 else /*infoIn->bitDepth is less than 8 bit per channel*/ 653 }
654 else /*infoIn->bitDepth is less than 8 bit per channel*/
655 {
656 switch (infoIn->color.colorType)
655 { 657 {
656 switch (infoIn->color.colorType) 658 case PNG_COLORTYPE_GREY: /*greyscale color*/
657 { 659 i = 0;
658 case PNG_COLORTYPE_GREY: /*greyscale color*/ 660 for (y = 0 ; y < h ; y++) {
659 i = 0; 661 pixel = line_buf;
660 for (y = 0 ; y < h ; y++) { 662 for (x = 0 ; x < w ; x++) {
661 pixel = line_buf; 663 value = readBitsFromReversedStream(&bp, in, infoIn->color.bitDepth);
662 for (x = 0 ; x < w ; x++) { 664
663 value = readBitsFromReversedStream(&bp, in, infoIn->color.bitDepth); 665 /* tRNS and bKGD */
664 666 if (infoIn->color.key_defined)
665 /* tRNS and bKGD */ 667 if ( value == infoIn->color.key_r )
666 if (infoIn->color.key_defined) 668 value = infoIn->background_r; /* full transparent */
667 if ( value == infoIn->color.key_r ) 669
668 value = infoIn->background_r; /* full transparent */ 670 /* scale value from 0 to 255 */
669 671 value = (value * 255) / ((1 << infoIn->color.bitDepth) - 1);
670 /* scale value from 0 to 255 */ 672
671 value = (value * 255) / ((1 << infoIn->color.bitDepth) - 1); 673 pixel->red = (uint8_t)value;
672 674 pixel->green = (uint8_t)value;
673 pixel->red = (uint8_t)value; 675 pixel->blue = (uint8_t)value;
674 pixel->green = (uint8_t)value; 676 pixel++;
675 pixel->blue = (uint8_t)value;
676 pixel++;
677 }
678 output_row_8(y,(void *)line_buf,&ctx);
679 } 677 }
680 break; 678 output_row_8(y,(void *)line_buf,&ctx);
681 case PNG_COLORTYPE_PALETTE: /*indexed color (palette)*/ 679 }
682 i = 0; 680 break;
683 for (y = 0 ; y < h ; y++) { 681 case PNG_COLORTYPE_PALETTE: /*indexed color (palette)*/
684 pixel = line_buf; 682 i = 0;
685 for (x = 0 ; x < w ; x++) { 683 for (y = 0 ; y < h ; y++) {
686 value = readBitsFromReversedStream(&bp, in, infoIn->color.bitDepth); 684 pixel = line_buf;
687 if (value >= infoIn->color.palettesize) 685 for (x = 0 ; x < w ; x++) {
688 { 686 value = readBitsFromReversedStream(&bp, in, infoIn->color.bitDepth);
689 decoder->error = 47; 687 if (value >= infoIn->color.palettesize)
690 return; 688 {
691 } 689 decoder->error = 47;
692 690 return;
693 j = value << 2;
694
695 /* tRNS and bKGD */
696 alpha = infoIn->color.palette[j + 3];
697 alpha_complement = (256 - alpha);
698 pixel->red = (alpha * infoIn->color.palette[j] +
699 alpha_complement*infoIn->background_r)>>8;
700 pixel->green = (alpha * infoIn->color.palette[j + 1] +
701 alpha_complement*infoIn->background_g)>>8;
702 pixel->blue = (alpha * infoIn->color.palette[j + 2] +
703 alpha_complement*infoIn->background_b)>>8;
704 pixel++;
705 } 691 }
706 output_row_8(y,(void *)line_buf,&ctx); 692
693 j = value << 2;
694
695 /* tRNS and bKGD */
696 alpha = infoIn->color.palette[j + 3];
697 alpha_complement = (256 - alpha);
698 pixel->red = (alpha * infoIn->color.palette[j] +
699 alpha_complement*infoIn->background_r)>>8;
700 pixel->green = (alpha * infoIn->color.palette[j + 1] +
701 alpha_complement*infoIn->background_g)>>8;
702 pixel->blue = (alpha * infoIn->color.palette[j + 2] +
703 alpha_complement*infoIn->background_b)>>8;
704 pixel++;
707 } 705 }
708 break; 706 output_row_8(y,(void *)line_buf,&ctx);
709 default:
710 break;
711 } 707 }
708 break;
709 default:
710 break;
712 } 711 }
712 }
713#else /* greyscale targets */ 713#else /* greyscale targets */
714struct uint8_rgb px_rgb; /* for rgb(a) -> greyscale conversion */ 714 struct uint8_rgb px_rgb; /* for rgb(a) -> greyscale conversion */
715uint8_t background_grey; /* for rgb background -> greyscale background */ 715 uint8_t background_grey; /* for rgb background -> greyscale background */
716 716
717 if (infoIn->color.bitDepth == 8) 717 if (infoIn->color.bitDepth == 8)
718 {
719 switch (infoIn->color.colorType)
718 { 720 {
719 switch (infoIn->color.colorType) 721 case PNG_COLORTYPE_GREY: /*greyscale color*/
720 { 722 i = 0;
721 case PNG_COLORTYPE_GREY: /*greyscale color*/ 723 for (y = 0 ; y < h ; y++) {
722 i = 0; 724 pixel = line_buf;
723 for (y = 0 ; y < h ; y++) { 725 for (x = 0 ; x < w ; x++ ) {
724 pixel = line_buf; 726 value = in[i++];
725 for (x = 0 ; x < w ; x++ ) { 727
726 value = in[i++]; 728 /* transparent color defined in tRNS chunk */
727 729 if (infoIn->color.key_defined)
728 /* transparent color defined in tRNS chunk */ 730 if ( (uint8_t)value == (uint8_t)infoIn->color.key_r )
729 if (infoIn->color.key_defined) 731 value = infoIn->background_r;
730 if ( (uint8_t)value == (uint8_t)infoIn->color.key_r ) 732
731 value = infoIn->background_r; 733 *pixel++ = (uint8_t)value;
732
733 *pixel++ = (uint8_t)value;
734 }
735 output_row_8(y,(void *)line_buf,&ctx);
736 } 734 }
737 break; 735 output_row_8(y,(void *)line_buf,&ctx);
738 case PNG_COLORTYPE_RGB: /*RGB color*/ 736 }
739 /* convert background rgb color to greyscale */ 737 break;
740 px_rgb.red = infoIn->background_r; 738 case PNG_COLORTYPE_RGB: /*RGB color*/
741 px_rgb.green = infoIn->background_g; 739 /* convert background rgb color to greyscale */
742 px_rgb.blue = infoIn->background_b; 740 px_rgb.red = infoIn->background_r;
743 background_grey = brightness(px_rgb); 741 px_rgb.green = infoIn->background_g;
744 742 px_rgb.blue = infoIn->background_b;
745 i = 0; 743 background_grey = brightness(px_rgb);
746 for (y = 0 ; y < h ; y++) { 744
747 pixel = line_buf; 745 i = 0;
748 for (x = 0 ; x < w ; x++) { 746 for (y = 0 ; y < h ; y++) {
749 j = 3*i++; 747 pixel = line_buf;
750 748 for (x = 0 ; x < w ; x++) {
751 /* tRNs & bKGD */ 749 j = 3*i++;
752 if (infoIn->color.key_defined && 750
753 in[j] == (uint8_t)infoIn->color.key_r && 751 /* tRNs & bKGD */
754 in[j + 1] == (uint8_t)infoIn->color.key_g && 752 if (infoIn->color.key_defined &&
755 in[j + 2] == (uint8_t)infoIn->color.key_b) 753 in[j] == (uint8_t)infoIn->color.key_r &&
756 { 754 in[j + 1] == (uint8_t)infoIn->color.key_g &&
757 *pixel = background_grey; 755 in[j + 2] == (uint8_t)infoIn->color.key_b)
758 } 756 {
759 else 757 *pixel = background_grey;
760 {
761 /* rgb -> greyscale */
762 px_rgb.red = in[j];
763 px_rgb.green = in[j + 1];
764 px_rgb.blue = in[j + 2];
765 *pixel = brightness(px_rgb);
766 }
767 pixel++;
768
769 }
770 output_row_8(y,(void *)line_buf,&ctx);
771 }
772 break;
773 case PNG_COLORTYPE_PALETTE: /*indexed color (palette)*/
774 i = 0;
775 /* calculate grey value of rgb background */
776 px_rgb.red = infoIn->background_r;
777 px_rgb.green = infoIn->background_g;
778 px_rgb.blue = infoIn->background_b;
779 background_grey = brightness(px_rgb);
780
781 for (y = 0 ; y < h ; y++) {
782 /* reset line buf */
783 pixel = line_buf;
784 for (x = 0 ; x < w ; x++) {
785 if (in[i] >= infoIn->color.palettesize)
786 {
787 decoder->error = 46;
788 return;
789 }
790
791 j = in[i++] << 2;
792 alpha = infoIn->color.palette[j + 3];
793 alpha_complement = (256 - alpha);
794
795 /* tRNS and bKGD */
796 px_rgb.red = (alpha * infoIn->color.palette[j] +
797 alpha_complement*background_grey)>>8;
798 px_rgb.green = (alpha * infoIn->color.palette[j + 1] +
799 alpha_complement*background_grey)>>8;
800 px_rgb.blue = (alpha * infoIn->color.palette[j + 2] +
801 alpha_complement*background_grey)>>8;
802
803 *pixel++ = brightness(px_rgb);
804 }
805 output_row_8(y,(void *)(line_buf),&ctx);
806 }
807 break;
808 case PNG_COLORTYPE_GREYA: /*greyscale with alpha*/
809 i = 0;
810 for (y = 0 ; y < h ; y++) {
811 pixel = line_buf;
812 for (x = 0 ; x < w ; x++) {
813 alpha = in[(i << 1) + 1];
814 alpha_complement = ((256 - alpha)*infoIn->background_r);
815 *pixel++ = (alpha * in[i++ << 1] + alpha_complement)>>8;
816 } 758 }
817 output_row_8(y,(void *)line_buf,&ctx); 759 else
818 } 760 {
819 break; 761 /* rgb -> greyscale */
820 case PNG_COLORTYPE_RGBA: /*RGB with alpha*/
821 px_rgb.red = infoIn->background_r;
822 px_rgb.green = infoIn->background_g;
823 px_rgb.blue = infoIn->background_b;
824 background_grey = brightness(px_rgb);
825
826 i = 0;
827 for (y = 0 ; y < h ; y++) {
828 pixel = line_buf;
829 for (x = 0 ; x < w ; x++) {
830 j = i++ << 2;
831 alpha = in[j + 3];
832 alpha_complement = ((256 - alpha)*background_grey);
833
834 px_rgb.red = in[j]; 762 px_rgb.red = in[j];
835 px_rgb.green = in[j + 1]; 763 px_rgb.green = in[j + 1];
836 px_rgb.blue = in[j + 2]; 764 px_rgb.blue = in[j + 2];
837 *pixel++ = (alpha * brightness(px_rgb) + 765 *pixel = brightness(px_rgb);
838 alpha_complement)>>8;
839 } 766 }
840 output_row_8(y,(void *)line_buf,&ctx); 767 pixel++;
768
841 } 769 }
842 break; 770 output_row_8(y,(void *)line_buf,&ctx);
843 default:
844 break;
845 } 771 }
846 } 772 break;
847 else if (infoIn->color.bitDepth == 16) 773 case PNG_COLORTYPE_PALETTE: /*indexed color (palette)*/
848 { 774 i = 0;
849 switch (infoIn->color.colorType) 775 /* calculate grey value of rgb background */
850 { 776 px_rgb.red = infoIn->background_r;
851 case PNG_COLORTYPE_GREY: /*greyscale color*/ 777 px_rgb.green = infoIn->background_g;
852 i = 0; 778 px_rgb.blue = infoIn->background_b;
853 for (y = 0 ; y < h ; y++) { 779 background_grey = brightness(px_rgb);
854 pixel = line_buf; 780
855 for (x = 0 ; x < w ; x++) { 781 for (y = 0 ; y < h ; y++) {
856 /* specification states that we have to compare 782 /* reset line buf */
857 * colors for simple transparency in 16bits 783 pixel = line_buf;
858 * even if we scale down to 8bits later 784 for (x = 0 ; x < w ; x++) {
859 */ 785 if (in[i] >= infoIn->color.palettesize)
860 value = in[i<<1]<<8|in[(i << 1) + 1]; 786 {
861 i++; 787 decoder->error = 46;
862 788 return;
863 /* tRNS and bKGD */
864 if (infoIn->color.key_defined &&
865 value == infoIn->color.key_r)
866 value = infoIn->background_r<<8;
867
868 /* we take upper 8bits */
869 *pixel++ = (uint8_t)(value>>8);
870 } 789 }
871 790
872 output_row_8(y,(void *)line_buf,&ctx); 791 j = in[i++] << 2;
792 alpha = infoIn->color.palette[j + 3];
793 alpha_complement = (256 - alpha);
794
795 /* tRNS and bKGD */
796 px_rgb.red = (alpha * infoIn->color.palette[j] +
797 alpha_complement*background_grey)>>8;
798 px_rgb.green = (alpha * infoIn->color.palette[j + 1] +
799 alpha_complement*background_grey)>>8;
800 px_rgb.blue = (alpha * infoIn->color.palette[j + 2] +
801 alpha_complement*background_grey)>>8;
802
803 *pixel++ = brightness(px_rgb);
873 } 804 }
874 break; 805 output_row_8(y,(void *)(line_buf),&ctx);
875 case PNG_COLORTYPE_RGB: /*RGB color*/ 806 }
876 i = 0; 807 break;
877 px_rgb.red = infoIn->background_r; 808 case PNG_COLORTYPE_GREYA: /*greyscale with alpha*/
878 px_rgb.green = infoIn->background_g; 809 i = 0;
879 px_rgb.blue = infoIn->background_b; 810 for (y = 0 ; y < h ; y++) {
880 background_grey = brightness(px_rgb); 811 pixel = line_buf;
881 812 for (x = 0 ; x < w ; x++) {
882 for (y = 0 ; y < h ; y++) { 813 alpha = in[(i << 1) + 1];
883 pixel = line_buf; 814 alpha_complement = ((256 - alpha)*infoIn->background_r);
884 for (x = 0 ; x < w ; x++) { 815 *pixel++ = (alpha * in[i++ << 1] + alpha_complement)>>8;
885 j = 6 * i++;
886
887 /* tRNS and bKGD */
888 if (infoIn->color.key_defined &&
889 (uint16_t)(in[j]<<8|in[j + 1]) ==
890 infoIn->color.key_r &&
891 (uint16_t)(in[j + 2]<<8|in[j + 3]) ==
892 infoIn->color.key_g &&
893 (uint16_t)(in[j + 4]<<8|in[j + 5]) ==
894 infoIn->color.key_b)
895 {
896 *pixel = background_grey;
897 }
898 else
899 {
900 /* we take only upper byte of 16bit value */
901 px_rgb.red = in[j];
902 px_rgb.green = in[j + 2];
903 px_rgb.blue = in[j + 4];
904 *pixel = brightness(px_rgb);
905 }
906 pixel++;
907 }
908 output_row_8(y,(void *)line_buf,&ctx);
909 } 816 }
910 break; 817 output_row_8(y,(void *)line_buf,&ctx);
911 case PNG_COLORTYPE_GREYA: /*greyscale with alpha*/ 818 }
912 i = 0; 819 break;
913 for (y = 0 ; y < h ; y++) { 820 case PNG_COLORTYPE_RGBA: /*RGB with alpha*/
914 pixel = line_buf; 821 px_rgb.red = infoIn->background_r;
915 for (x = 0 ; x < w ; x++) { 822 px_rgb.green = infoIn->background_g;
916 alpha = in[(i << 2) + 2]; 823 px_rgb.blue = infoIn->background_b;
917 alpha_complement = (256 - alpha)*infoIn->background_r; 824 background_grey = brightness(px_rgb);
918 *pixel++ = (alpha * in[i++ << 2] + alpha_complement)>>8; 825
919 } 826 i = 0;
920 output_row_8(y,(void *)line_buf,&ctx); 827 for (y = 0 ; y < h ; y++) {
828 pixel = line_buf;
829 for (x = 0 ; x < w ; x++) {
830 j = i++ << 2;
831 alpha = in[j + 3];
832 alpha_complement = ((256 - alpha)*background_grey);
833
834 px_rgb.red = in[j];
835 px_rgb.green = in[j + 1];
836 px_rgb.blue = in[j + 2];
837 *pixel++ = (alpha * brightness(px_rgb) +
838 alpha_complement)>>8;
921 } 839 }
922 break; 840 output_row_8(y,(void *)line_buf,&ctx);
923 case PNG_COLORTYPE_RGBA: /*RGB with alpha*/ 841 }
924 px_rgb.red = infoIn->background_r; 842 break;
925 px_rgb.green = infoIn->background_g; 843 default:
926 px_rgb.blue = infoIn->background_b; 844 break;
927 background_grey = brightness(px_rgb); 845 }
928 846 }
929 i = 0; 847 else if (infoIn->color.bitDepth == 16)
930 for (y = 0 ; y < h ; y++) { 848 {
931 pixel = line_buf; 849 switch (infoIn->color.colorType)
932 for (x = 0 ; x < w ; x++) { 850 {
933 j = i++ << 3; 851 case PNG_COLORTYPE_GREY: /*greyscale color*/
934 alpha = in[j + 6]; 852 i = 0;
935 alpha_complement = (256 - alpha)*background_grey; 853 for (y = 0 ; y < h ; y++) {
854 pixel = line_buf;
855 for (x = 0 ; x < w ; x++) {
856 /* specification states that we have to compare
857 * colors for simple transparency in 16bits
858 * even if we scale down to 8bits later
859 */
860 value = in[i<<1]<<8|in[(i << 1) + 1];
861 i++;
862
863 /* tRNS and bKGD */
864 if (infoIn->color.key_defined &&
865 value == infoIn->color.key_r)
866 value = infoIn->background_r<<8;
867
868 /* we take upper 8bits */
869 *pixel++ = (uint8_t)(value>>8);
870 }
871
872 output_row_8(y,(void *)line_buf,&ctx);
873 }
874 break;
875 case PNG_COLORTYPE_RGB: /*RGB color*/
876 i = 0;
877 px_rgb.red = infoIn->background_r;
878 px_rgb.green = infoIn->background_g;
879 px_rgb.blue = infoIn->background_b;
880 background_grey = brightness(px_rgb);
881
882 for (y = 0 ; y < h ; y++) {
883 pixel = line_buf;
884 for (x = 0 ; x < w ; x++) {
885 j = 6 * i++;
886
887 /* tRNS and bKGD */
888 if (infoIn->color.key_defined &&
889 (uint16_t)(in[j]<<8|in[j + 1]) ==
890 infoIn->color.key_r &&
891 (uint16_t)(in[j + 2]<<8|in[j + 3]) ==
892 infoIn->color.key_g &&
893 (uint16_t)(in[j + 4]<<8|in[j + 5]) ==
894 infoIn->color.key_b)
895 {
896 *pixel = background_grey;
897 }
898 else
899 {
900 /* we take only upper byte of 16bit value */
936 px_rgb.red = in[j]; 901 px_rgb.red = in[j];
937 px_rgb.green = in[j + 2]; 902 px_rgb.green = in[j + 2];
938 px_rgb.blue = in[j + 4]; 903 px_rgb.blue = in[j + 4];
939 *pixel++ = (alpha * brightness(px_rgb) + alpha_complement)>>8; 904 *pixel = brightness(px_rgb);
940 } 905 }
941 output_row_8(y,(void *)line_buf,&ctx); 906 pixel++;
942 } 907 }
943 break; 908 output_row_8(y,(void *)line_buf,&ctx);
944 default:
945 break;
946 } 909 }
910 break;
911 case PNG_COLORTYPE_GREYA: /*greyscale with alpha*/
912 i = 0;
913 for (y = 0 ; y < h ; y++) {
914 pixel = line_buf;
915 for (x = 0 ; x < w ; x++) {
916 alpha = in[(i << 2) + 2];
917 alpha_complement = (256 - alpha)*infoIn->background_r;
918 *pixel++ = (alpha * in[i++ << 2] + alpha_complement)>>8;
919 }
920 output_row_8(y,(void *)line_buf,&ctx);
921 }
922 break;
923 case PNG_COLORTYPE_RGBA: /*RGB with alpha*/
924 px_rgb.red = infoIn->background_r;
925 px_rgb.green = infoIn->background_g;
926 px_rgb.blue = infoIn->background_b;
927 background_grey = brightness(px_rgb);
928
929 i = 0;
930 for (y = 0 ; y < h ; y++) {
931 pixel = line_buf;
932 for (x = 0 ; x < w ; x++) {
933 j = i++ << 3;
934 alpha = in[j + 6];
935 alpha_complement = (256 - alpha)*background_grey;
936 px_rgb.red = in[j];
937 px_rgb.green = in[j + 2];
938 px_rgb.blue = in[j + 4];
939 *pixel++ = (alpha * brightness(px_rgb) + alpha_complement)>>8;
940 }
941 output_row_8(y,(void *)line_buf,&ctx);
942 }
943 break;
944 default:
945 break;
947 } 946 }
948 else /*infoIn->bitDepth is less than 8 bit per channel*/ 947 }
948 else /*infoIn->bitDepth is less than 8 bit per channel*/
949 {
950 switch (infoIn->color.colorType)
949 { 951 {
950 switch (infoIn->color.colorType) 952 case PNG_COLORTYPE_GREY: /*greyscale color*/
951 { 953 i = 0;
952 case PNG_COLORTYPE_GREY: /*greyscale color*/ 954 for (y = 0 ; y < h ; y++) {
953 i = 0; 955 pixel = line_buf;
954 for (y = 0 ; y < h ; y++) { 956 for (x = 0 ; x < w ; x++) {
955 pixel = line_buf; 957 value = readBitsFromReversedStream(&bp, in, infoIn->color.bitDepth);
956 for (x = 0 ; x < w ; x++) { 958
957 value = readBitsFromReversedStream(&bp, in, infoIn->color.bitDepth); 959 /* tRNS and bKGD */
958 960 if (infoIn->color.key_defined)
959 /* tRNS and bKGD */ 961 if ( value == infoIn->color.key_r )
960 if (infoIn->color.key_defined) 962 value = infoIn->background_r; /* full transparent */
961 if ( value == infoIn->color.key_r ) 963
962 value = infoIn->background_r; /* full transparent */ 964 /*scale value from 0 to 255*/
963 965 value = (value * 255) / ((1 << infoIn->color.bitDepth) - 1);
964 /*scale value from 0 to 255*/ 966
965 value = (value * 255) / ((1 << infoIn->color.bitDepth) - 1); 967 *pixel++ = (unsigned char)value;
966
967 *pixel++ = (unsigned char)value;
968 }
969 output_row_8(y,(void *)line_buf,&ctx);
970 } 968 }
971 break; 969 output_row_8(y,(void *)line_buf,&ctx);
972 case PNG_COLORTYPE_PALETTE: /*indexed color (palette)*/ 970 }
973 i = 0; 971 break;
974 px_rgb.red = infoIn->background_r; 972 case PNG_COLORTYPE_PALETTE: /*indexed color (palette)*/
975 px_rgb.green = infoIn->background_g; 973 i = 0;
976 px_rgb.blue = infoIn->background_b; 974 px_rgb.red = infoIn->background_r;
977 uint8_t background_grey = brightness(px_rgb); 975 px_rgb.green = infoIn->background_g;
978 976 px_rgb.blue = infoIn->background_b;
979 for (y = 0 ; y < h ; y++) { 977 uint8_t background_grey = brightness(px_rgb);
980 pixel = line_buf; 978
981 for (x = 0 ; x < w ; x++) { 979 for (y = 0 ; y < h ; y++) {
982 value = readBitsFromReversedStream(&bp, in, infoIn->color.bitDepth); 980 pixel = line_buf;
983 if (value >= infoIn->color.palettesize) 981 for (x = 0 ; x < w ; x++) {
984 { 982 value = readBitsFromReversedStream(&bp, in, infoIn->color.bitDepth);
985 decoder->error = 47; 983 if (value >= infoIn->color.palettesize)
986 return; 984 {
987 } 985 decoder->error = 47;
988 986 return;
989 j = value << 2;
990
991 /* tRNS and bKGD */
992 alpha = infoIn->color.palette[j + 3];
993 alpha_complement = (256 - alpha) * background_grey;
994
995 px_rgb.red = (alpha * infoIn->color.palette[j] +
996 alpha_complement)>>8;
997 px_rgb.green = (alpha * infoIn->color.palette[j + 1] +
998 alpha_complement)>>8;
999 px_rgb.blue = (alpha * infoIn->color.palette[j + 2] +
1000 alpha_complement)>>8;
1001 *pixel++ = brightness(px_rgb);
1002 } 987 }
1003 output_row_8(y,(void *)line_buf,&ctx); 988
989 j = value << 2;
990
991 /* tRNS and bKGD */
992 alpha = infoIn->color.palette[j + 3];
993 alpha_complement = (256 - alpha) * background_grey;
994
995 px_rgb.red = (alpha * infoIn->color.palette[j] +
996 alpha_complement)>>8;
997 px_rgb.green = (alpha * infoIn->color.palette[j + 1] +
998 alpha_complement)>>8;
999 px_rgb.blue = (alpha * infoIn->color.palette[j + 2] +
1000 alpha_complement)>>8;
1001 *pixel++ = brightness(px_rgb);
1004 } 1002 }
1005 break; 1003 output_row_8(y,(void *)line_buf,&ctx);
1006 default:
1007 break;
1008 } 1004 }
1005 break;
1006 default:
1007 break;
1009 } 1008 }
1009 }
1010#endif 1010#endif
1011} 1011}
1012 1012
@@ -1097,13 +1097,13 @@ static uint8_t unfilterScanline(uint8_t* recon,
1097 * disjoint. 1097 * disjoint.
1098 */ 1098 */
1099 1099
1100/* storage space for cached portion of scanline */ 1100 /* storage space for cached portion of scanline */
1101unsigned char cache[512+16]; 1101 unsigned char cache[512+16];
1102 1102
1103/* ptr to second element of the cache */ 1103 /* ptr to second element of the cache */
1104unsigned char *cache_1 = cache + bytewidth; 1104 unsigned char *cache_1 = cache + bytewidth;
1105unsigned char *p_cache = cache + 256 + 8; /* half way */ 1105 unsigned char *p_cache = cache + 256 + 8; /* half way */
1106unsigned char *p_cache_1 = p_cache + bytewidth; 1106 unsigned char *p_cache_1 = p_cache + bytewidth;
1107 1107
1108 size_t i; 1108 size_t i;
1109 switch (filterType) 1109 switch (filterType)
@@ -1192,7 +1192,7 @@ unsigned char *p_cache_1 = p_cache + bytewidth;
1192 memcpy(recon, cache, length); 1192 memcpy(recon, cache, length);
1193 } 1193 }
1194 } 1194 }
1195 else 1195 else
1196 /* for(i = 0; i < length; i++) recon[i] = scanline[i]; */ 1196 /* for(i = 0; i < length; i++) recon[i] = scanline[i]; */
1197 memcpy(recon, scanline, length * sizeof(uint8_t)); 1197 memcpy(recon, scanline, length * sizeof(uint8_t));
1198 break; 1198 break;
@@ -1519,7 +1519,7 @@ static void Adam7_deinterlace(uint8_t* out,
1519 /* note that this function assumes the out buffer 1519 /* note that this function assumes the out buffer
1520 * is completely 0, use setBitOfReversedStream 1520 * is completely 0, use setBitOfReversedStream
1521 * otherwise*/ 1521 * otherwise*/
1522 setBitOfReversedStream0(&obp, out, bit); 1522 setBitOfReversedStream0(&obp, out, bit);
1523 } 1523 }
1524 } 1524 }
1525 } 1525 }
@@ -1832,7 +1832,7 @@ static void decodeGeneric(LodePNG_Decoder* decoder)
1832 } 1832 }
1833 decoder->infoPng.background_r = 1833 decoder->infoPng.background_r =
1834 decoder->infoPng.color.palette[(data[0]<<2)]; 1834 decoder->infoPng.color.palette[(data[0]<<2)];
1835 1835
1836 decoder->infoPng.background_g = 1836 decoder->infoPng.background_g =
1837 decoder->infoPng.color.palette[(data[0]<<2) | 1]; 1837 decoder->infoPng.color.palette[(data[0]<<2) | 1];
1838 1838
@@ -1880,7 +1880,7 @@ static void decodeGeneric(LodePNG_Decoder* decoder)
1880 */ 1880 */
1881 decoder->error = 69; 1881 decoder->error = 69;
1882 break; 1882 break;
1883 } 1883 }
1884 unknown = true; 1884 unknown = true;
1885 } 1885 }
1886 1886
@@ -2007,7 +2007,7 @@ void LodePNG_inspect(LodePNG_Decoder* decoder, uint8_t *in, size_t inlength)
2007 decoder->error = 29; 2007 decoder->error = 29;
2008 return; 2008 return;
2009 } 2009 }
2010 2010
2011 /* read the values given in the header */ 2011 /* read the values given in the header */
2012 decoder->infoPng.width = in[16]<<24|in[17]<<16|in[18]<<8|in[19]; 2012 decoder->infoPng.width = in[16]<<24|in[17]<<16|in[18]<<8|in[19];
2013 decoder->infoPng.height = in[20]<<24|in[21]<<16|in[22]<<8|in[23]; 2013 decoder->infoPng.height = in[20]<<24|in[21]<<16|in[22]<<8|in[23];
@@ -2080,7 +2080,7 @@ void LodePNG_decode(LodePNG_Decoder* decoder,
2080 /* one line more as temp buffer for conversion */ 2080 /* one line more as temp buffer for conversion */
2081#ifdef HAVE_LCD_COLOR 2081#ifdef HAVE_LCD_COLOR
2082 decoder->native_img_size = decoder->infoPng.width * 2082 decoder->native_img_size = decoder->infoPng.width *
2083 (decoder->infoPng.height)*FB_DATA_SZ; 2083 decoder->infoPng.height * FB_DATA_SZ;
2084 line_buf_size = decoder->infoPng.width * sizeof(struct uint8_rgb); 2084 line_buf_size = decoder->infoPng.width * sizeof(struct uint8_rgb);
2085#else 2085#else
2086 decoder->native_img_size = decoder->infoPng.width * 2086 decoder->native_img_size = decoder->infoPng.width *
@@ -2134,11 +2134,9 @@ void LodePNG_decode(LodePNG_Decoder* decoder,
2134 { 2134 {
2135 /* calculate 'corrected' image size */ 2135 /* calculate 'corrected' image size */
2136#ifdef HAVE_LCD_COLOR 2136#ifdef HAVE_LCD_COLOR
2137 c_native_img_size = dim_dst.width * 2137 c_native_img_size = dim_dst.width * dim_dst.height * FB_DATA_SZ;
2138 (dim_dst.height)*FB_DATA_SZ;
2139#else 2138#else
2140 c_native_img_size = dim_dst.width * 2139 c_native_img_size = dim_dst.width * dim_dst.height;
2141 dim_dst.height;
2142#endif 2140#endif
2143 /* check memory constraints 2141 /* check memory constraints
2144 * do the correction only if there is enough 2142 * do the correction only if there is enough
@@ -2165,15 +2163,15 @@ void LodePNG_decode(LodePNG_Decoder* decoder,
2165 decoder->infoPng.width = img_dst.width; 2163 decoder->infoPng.width = img_dst.width;
2166 decoder->infoPng.height = img_dst.height; 2164 decoder->infoPng.height = img_dst.height;
2167 decoder->native_img_size = c_native_img_size; 2165 decoder->native_img_size = c_native_img_size;
2168 2166
2169 /* copy back corrected image to the begining of the buffer */ 2167 /* copy back corrected image to the begining of the buffer */
2170 memcpy(img_src.data, img_dst.data, decoder->native_img_size); 2168 memcpy(img_src.data, img_dst.data, decoder->native_img_size);
2171 } 2169 }
2172 } 2170 }
2173
2174#endif /* (LCD_PIXEL_ASPECT_HEIGHT != 1 || LCD_PIXEL_ASPECT_WIDTH != 1) */ 2171#endif /* (LCD_PIXEL_ASPECT_HEIGHT != 1 || LCD_PIXEL_ASPECT_WIDTH != 1) */
2175time = *rb->current_tick - time; 2172
2176if (pf_progress) pf_progress(100, 100); 2173 time = *rb->current_tick - time;
2174 if (pf_progress) pf_progress(100, 100);
2177} 2175}
2178 2176
2179void LodePNG_Decoder_init(LodePNG_Decoder* decoder, 2177void LodePNG_Decoder_init(LodePNG_Decoder* decoder,
diff --git a/apps/plugins/imageviewer/png/tinflate.c b/apps/plugins/imageviewer/png/tinflate.c
index b142f7afe7..95d8e2b483 100644
--- a/apps/plugins/imageviewer/png/tinflate.c
+++ b/apps/plugins/imageviewer/png/tinflate.c
@@ -148,7 +148,7 @@ TINF_TABLES tbl = {
148 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 148 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
149 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f}, 149 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f},
150 }, 150 },
151 151
152 .length_bits = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 152 .length_bits = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
153 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 153 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
154 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 154 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04,
@@ -494,7 +494,7 @@ int tinf_uncompress(void *dest, unsigned int *destLen,
494 } 494 }
495 495
496 if (res != TINF_OK) return TINF_DATA_ERROR; 496 if (res != TINF_OK) return TINF_DATA_ERROR;
497 497
498 if (d.source > (unsigned char *)source + sourceLen) 498 if (d.source > (unsigned char *)source + sourceLen)
499 return TINF_DATA_ERROR; 499 return TINF_DATA_ERROR;
500 } while (!bfinal); 500 } while (!bfinal);