diff options
-rw-r--r-- | apps/plugins/imageviewer/png/png.c | 45 | ||||
-rw-r--r-- | apps/plugins/imageviewer/png/png.h | 25 | ||||
-rw-r--r-- | apps/plugins/imageviewer/png/png_decoder.c | 1082 | ||||
-rw-r--r-- | apps/plugins/imageviewer/png/tinflate.c | 4 |
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 */ |
39 | static LodePNG_Decoder decoder; | 39 | static LodePNG_Decoder decoder; |
40 | 40 | ||
41 | /* my memory pool (from the mp3 buffer) */ | 41 | static char print[32]; /* use a common snprintf() buffer */ |
42 | static 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 */ |
45 | static fb_data *disp[9]; | 44 | static unsigned char *disp[9]; |
46 | static fb_data *disp_buf; | 45 | static 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) | |||
64 | void draw_image_rect(struct image_info *info, | 63 | void 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 | ||
249 | int get_image(struct image_info *info, int ds) | 247 | int 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 | ||
431 | void (*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 |
434 | struct uint8_rgb *pixel; | 434 | struct uint8_rgb *pixel; |
435 | #else | 435 | #else |
436 | unsigned 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 */ |
714 | struct uint8_rgb px_rgb; /* for rgb(a) -> greyscale conversion */ | 714 | struct uint8_rgb px_rgb; /* for rgb(a) -> greyscale conversion */ |
715 | uint8_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 */ |
1101 | unsigned 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 */ |
1104 | unsigned char *cache_1 = cache + bytewidth; | 1104 | unsigned char *cache_1 = cache + bytewidth; |
1105 | unsigned char *p_cache = cache + 256 + 8; /* half way */ | 1105 | unsigned char *p_cache = cache + 256 + 8; /* half way */ |
1106 | unsigned 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) */ |
2175 | time = *rb->current_tick - time; | 2172 | |
2176 | if (pf_progress) pf_progress(100, 100); | 2173 | time = *rb->current_tick - time; |
2174 | if (pf_progress) pf_progress(100, 100); | ||
2177 | } | 2175 | } |
2178 | 2176 | ||
2179 | void LodePNG_Decoder_init(LodePNG_Decoder* decoder, | 2177 | void 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); |