summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/plugins/jpeg/jpeg.c224
-rw-r--r--apps/plugins/png/png.c438
-rw-r--r--apps/plugins/png/png.h10
3 files changed, 362 insertions, 310 deletions
diff --git a/apps/plugins/jpeg/jpeg.c b/apps/plugins/jpeg/jpeg.c
index 1049e4827e..e524b0cffd 100644
--- a/apps/plugins/jpeg/jpeg.c
+++ b/apps/plugins/jpeg/jpeg.c
@@ -69,7 +69,9 @@ GREY_INFO_STRUCT
69#define DIR_NEXT -1 69#define DIR_NEXT -1
70#define DIR_NONE 0 70#define DIR_NONE 0
71 71
72#define PLUGIN_OTHER 10 /* State code for output with return. */ 72#define PLUGIN_OTHER 10 /* State code for output with return. */
73#define PLUGIN_ABORT 11
74#define PLUGIN_OUTOFMEM 12
73 75
74/******************************* Globals ***********************************/ 76/******************************* Globals ***********************************/
75 77
@@ -105,25 +107,25 @@ struct jpeg_settings
105}; 107};
106 108
107static struct jpeg_settings jpeg_settings = 109static struct jpeg_settings jpeg_settings =
108 { 110{
109#ifdef HAVE_LCD_COLOR 111#ifdef HAVE_LCD_COLOR
110 COLOURMODE_COLOUR, 112 COLOURMODE_COLOUR,
111 DITHER_NONE, 113 DITHER_NONE,
112#endif 114#endif
113 SS_DEFAULT_TIMEOUT 115 SS_DEFAULT_TIMEOUT
114 }; 116};
115static struct jpeg_settings old_settings; 117static struct jpeg_settings old_settings;
116 118
117static struct configdata jpeg_config[] = 119static struct configdata jpeg_config[] =
118{ 120{
119#ifdef HAVE_LCD_COLOR 121#ifdef HAVE_LCD_COLOR
120 { TYPE_ENUM, 0, COLOUR_NUM_MODES, { .int_p = &jpeg_settings.colour_mode }, 122 { TYPE_ENUM, 0, COLOUR_NUM_MODES, { .int_p = &jpeg_settings.colour_mode },
121 "Colour Mode", (char *[]){ "Colour", "Grayscale" } }, 123 "Colour Mode", (char *[]){ "Colour", "Grayscale" } },
122 { TYPE_ENUM, 0, DITHER_NUM_MODES, { .int_p = &jpeg_settings.dither_mode }, 124 { TYPE_ENUM, 0, DITHER_NUM_MODES, { .int_p = &jpeg_settings.dither_mode },
123 "Dither Mode", (char *[]){ "None", "Ordered", "Diffusion" } }, 125 "Dither Mode", (char *[]){ "None", "Ordered", "Diffusion" } },
124#endif 126#endif
125 { TYPE_INT, SS_MIN_TIMEOUT, SS_MAX_TIMEOUT, 127 { TYPE_INT, SS_MIN_TIMEOUT, SS_MAX_TIMEOUT,
126 { .int_p = &jpeg_settings.ss_timeout }, "Slideshow Time", NULL }, 128 { .int_p = &jpeg_settings.ss_timeout }, "Slideshow Time", NULL },
127}; 129};
128 130
129#if LCD_DEPTH > 1 131#if LCD_DEPTH > 1
@@ -526,8 +528,8 @@ static void pan_view_down(struct t_disp* pdisp)
526 */ 528 */
527 move++, pdisp->y--; 529 move++, pdisp->y--;
528 rb->memcpy(rgb_linebuf, 530 rb->memcpy(rgb_linebuf,
529 rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH, 531 rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH,
530 LCD_WIDTH*sizeof (fb_data)); 532 LCD_WIDTH*sizeof (fb_data));
531 } 533 }
532#endif 534#endif
533 535
@@ -538,8 +540,7 @@ static void pan_view_down(struct t_disp* pdisp)
538 { 540 {
539 /* Cover the first row drawn with previous image data. */ 541 /* Cover the first row drawn with previous image data. */
540 rb->memcpy(rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH, 542 rb->memcpy(rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH,
541 rgb_linebuf, 543 rgb_linebuf, LCD_WIDTH*sizeof (fb_data));
542 LCD_WIDTH*sizeof (fb_data));
543 pdisp->y++; 544 pdisp->y++;
544 } 545 }
545#endif 546#endif
@@ -557,7 +558,8 @@ int scroll_bmp(struct t_disp* pdisp)
557 { 558 {
558 if (slideshow_enabled) 559 if (slideshow_enabled)
559 button = rb->button_get_w_tmo(jpeg_settings.ss_timeout * HZ); 560 button = rb->button_get_w_tmo(jpeg_settings.ss_timeout * HZ);
560 else button = rb->button_get(true); 561 else
562 button = rb->button_get(true);
561 563
562 running_slideshow = false; 564 running_slideshow = false;
563 565
@@ -737,6 +739,86 @@ int max_downscale(struct jpeg *p_jpg)
737 return downscale; 739 return downscale;
738} 740}
739 741
742/* load image from filename. */
743int load_image(char* filename, struct jpeg *p_jpg)
744{
745 int fd;
746 int filesize;
747 unsigned char* buf_jpeg; /* compressed JPEG image */
748 int status;
749
750 fd = rb->open(filename, O_RDONLY);
751 if (fd < 0)
752 {
753 rb->splashf(HZ, "err opening %s:%d", filename, fd);
754 return PLUGIN_ERROR;
755 }
756 filesize = rb->filesize(fd);
757
758 /* allocate JPEG buffer */
759 buf_jpeg = buf;
760
761 /* we can start the decompressed images behind it */
762 buf_images = buf_root = buf + filesize;
763 buf_images_size = root_size = buf_size - filesize;
764
765 if (buf_images_size <= 0)
766 {
767 rb->close(fd);
768 return PLUGIN_OUTOFMEM;
769 }
770
771 if(!running_slideshow)
772 {
773 rb->snprintf(print, sizeof(print), "%s:", rb->strrchr(filename,'/')+1);
774 rb->lcd_puts(0, 0, print);
775 rb->lcd_update();
776
777 rb->snprintf(print, sizeof(print), "loading %d bytes", filesize);
778 rb->lcd_puts(0, 1, print);
779 rb->lcd_update();
780 }
781
782 rb->read(fd, buf_jpeg, filesize);
783 rb->close(fd);
784
785 if(!running_slideshow)
786 {
787 rb->snprintf(print, sizeof(print), "decoding markers");
788 rb->lcd_puts(0, 2, print);
789 rb->lcd_update();
790 }
791#ifndef SIMULATOR
792 else if(immediate_ata_off)
793 {
794 /* running slideshow and time is long enough: power down disk */
795 rb->storage_sleep();
796 }
797#endif
798
799 /* process markers, unstuffing */
800 status = process_markers(buf_jpeg, filesize, p_jpg);
801
802 if (status < 0 || (status & (DQT | SOF0)) != (DQT | SOF0))
803 { /* bad format or minimum components not contained */
804 rb->splashf(HZ, "unsupported %d", status);
805 return PLUGIN_ERROR;
806 }
807
808 if (!(status & DHT)) /* if no Huffman table present: */
809 default_huff_tbl(p_jpg); /* use default */
810 build_lut(p_jpg); /* derive Huffman and other lookup-tables */
811
812 if(!running_slideshow)
813 {
814 rb->snprintf(print, sizeof(print), "image %dx%d",
815 p_jpg->x_size, p_jpg->y_size);
816 rb->lcd_puts(0, 2, print);
817 rb->lcd_update();
818 }
819
820 return PLUGIN_OK;
821}
740 822
741/* return decoded or cached image */ 823/* return decoded or cached image */
742struct t_disp* get_image(struct jpeg* p_jpg, int ds) 824struct t_disp* get_image(struct jpeg* p_jpg, int ds)
@@ -755,7 +837,7 @@ struct t_disp* get_image(struct jpeg* p_jpg, int ds)
755 837
756 /* assign image buffer */ 838 /* assign image buffer */
757 839
758 /* physical size needed for decoding */ 840 /* physical size needed for decoding */
759 size = jpegmem(p_jpg, ds); 841 size = jpegmem(p_jpg, ds);
760 if (buf_images_size <= size) 842 if (buf_images_size <= size)
761 { /* have to discard the current */ 843 { /* have to discard the current */
@@ -856,7 +938,6 @@ void set_view (struct t_disp* p_disp, int cx, int cy)
856 p_disp->y = y; 938 p_disp->y = y;
857} 939}
858 940
859
860/* calculate the view center based on the bitmap position */ 941/* calculate the view center based on the bitmap position */
861void get_view(struct t_disp* p_disp, int* p_cx, int* p_cy) 942void get_view(struct t_disp* p_disp, int* p_cx, int* p_cy)
862{ 943{
@@ -864,37 +945,30 @@ void get_view(struct t_disp* p_disp, int* p_cx, int* p_cy)
864 *p_cy = p_disp->y + MIN(LCD_HEIGHT, p_disp->height) / 2; 945 *p_cy = p_disp->y + MIN(LCD_HEIGHT, p_disp->height) / 2;
865} 946}
866 947
867
868/* load, decode, display the image */ 948/* load, decode, display the image */
869int load_and_show(char* filename) 949int load_and_show(char* filename)
870{ 950{
871 int fd;
872 int filesize;
873 unsigned char* buf_jpeg; /* compressed JPEG image */
874 int status; 951 int status;
875 struct t_disp* p_disp; /* currenly displayed image */ 952 struct t_disp* p_disp; /* currenly displayed image */
876 int cx, cy; /* view center */ 953 int cx, cy; /* view center */
877 954
878 fd = rb->open(filename, O_RDONLY); 955#if LCD_DEPTH > 1
879 if (fd < 0) 956 rb->lcd_set_foreground(LCD_WHITE);
880 { 957 rb->lcd_set_background(LCD_BLACK);
881 rb->snprintf(print,sizeof(print),"err opening %s:%d",filename,fd); 958 rb->lcd_set_backdrop(NULL);
882 rb->splash(HZ, print); 959#endif
883 return PLUGIN_ERROR; 960 rb->lcd_clear_display();
884 }
885 filesize = rb->filesize(fd);
886 rb->memset(&disp, 0, sizeof(disp));
887 961
888 /* allocate JPEG buffer */ 962 rb->memset(&disp, 0, sizeof(disp));
889 buf_jpeg = buf; 963 rb->memset(&jpg, 0, sizeof(jpg)); /* clear info struct */
890 964
891 /* we can start the decompressed images behind it */ 965 if (rb->button_get(false) == JPEG_MENU)
892 buf_images = buf_root = buf + filesize; 966 status = PLUGIN_ABORT;
893 buf_images_size = root_size = buf_size - filesize; 967 else
968 status = load_image(filename, &jpg);
894 969
895 if (buf_images_size <= 0) 970 if (status == PLUGIN_OUTOFMEM)
896 { 971 {
897 rb->close(fd);
898#if PLUGIN_BUFFER_SIZE >= MIN_MEM 972#if PLUGIN_BUFFER_SIZE >= MIN_MEM
899 if(plug_buf) 973 if(plug_buf)
900 { 974 {
@@ -944,9 +1018,9 @@ int load_and_show(char* filename)
944 } 1018 }
945 break; 1019 break;
946 default: 1020 default:
947 if(rb->default_event_handler_ex(button, cleanup, NULL) 1021 if(rb->default_event_handler_ex(button, cleanup, NULL)
948 == SYS_USB_CONNECTED) 1022 == SYS_USB_CONNECTED)
949 return PLUGIN_USB_CONNECTED; 1023 return PLUGIN_USB_CONNECTED;
950 1024
951 } 1025 }
952 } 1026 }
@@ -955,66 +1029,20 @@ int load_and_show(char* filename)
955#endif 1029#endif
956 { 1030 {
957 rb->splash(HZ, "Out of Memory"); 1031 rb->splash(HZ, "Out of Memory");
958 return PLUGIN_ERROR; 1032 file_pt[curfile] = NULL;
1033 return change_filename(direction);
959 } 1034 }
960 } 1035 }
961 1036 else if (status == PLUGIN_ERROR)
962 if(!running_slideshow)
963 { 1037 {
964#if LCD_DEPTH > 1
965 rb->lcd_set_foreground(LCD_WHITE);
966 rb->lcd_set_background(LCD_BLACK);
967 rb->lcd_set_backdrop(NULL);
968#endif
969
970 rb->lcd_clear_display();
971 rb->snprintf(print, sizeof(print), "%s:", rb->strrchr(filename,'/')+1);
972 rb->lcd_puts(0, 0, print);
973 rb->lcd_update();
974
975 rb->snprintf(print, sizeof(print), "loading %d bytes", filesize);
976 rb->lcd_puts(0, 1, print);
977 rb->lcd_update();
978 }
979
980 rb->read(fd, buf_jpeg, filesize);
981 rb->close(fd);
982
983 if(!running_slideshow)
984 {
985 rb->snprintf(print, sizeof(print), "decoding markers");
986 rb->lcd_puts(0, 2, print);
987 rb->lcd_update();
988 }
989#ifndef SIMULATOR
990 else if(immediate_ata_off)
991 {
992 /* running slideshow and time is long enough: power down disk */
993 rb->storage_sleep();
994 }
995#endif
996
997 rb->memset(&jpg, 0, sizeof(jpg)); /* clear info struct */
998 /* process markers, unstuffing */
999 status = process_markers(buf_jpeg, filesize, &jpg);
1000
1001 if (status < 0 || (status & (DQT | SOF0)) != (DQT | SOF0))
1002 { /* bad format or minimum components not contained */
1003 rb->splashf(HZ, "unsupported %d", status);
1004 file_pt[curfile] = NULL; 1038 file_pt[curfile] = NULL;
1005 return change_filename(direction); 1039 return change_filename(direction);
1006 } 1040 }
1007 1041 else if (status == PLUGIN_ABORT) {
1008 if (!(status & DHT)) /* if no Huffman table present: */ 1042 rb->splash(HZ, "aborted");
1009 default_huff_tbl(&jpg); /* use default */ 1043 return PLUGIN_OK;
1010 build_lut(&jpg); /* derive Huffman and other lookup-tables */
1011
1012 if(!running_slideshow)
1013 {
1014 rb->snprintf(print, sizeof(print), "image %dx%d", jpg.x_size, jpg.y_size);
1015 rb->lcd_puts(0, 2, print);
1016 rb->lcd_update();
1017 } 1044 }
1045
1018 ds_max = max_downscale(&jpg); /* check display constraint */ 1046 ds_max = max_downscale(&jpg); /* check display constraint */
1019 ds_min = min_downscale(&jpg, buf_images_size); /* check memory constraint */ 1047 ds_min = min_downscale(&jpg, buf_images_size); /* check memory constraint */
1020 if (ds_min == 0) 1048 if (ds_min == 0)
@@ -1023,6 +1051,8 @@ int load_and_show(char* filename)
1023 file_pt[curfile] = NULL; 1051 file_pt[curfile] = NULL;
1024 return change_filename(direction); 1052 return change_filename(direction);
1025 } 1053 }
1054 else if (ds_max < ds_min)
1055 ds_max = ds_min;
1026 1056
1027 ds = ds_max; /* initialize setting */ 1057 ds = ds_max; /* initialize setting */
1028 cx = jpg.x_size/ds/2; /* center the view */ 1058 cx = jpg.x_size/ds/2; /* center the view */
@@ -1096,7 +1126,7 @@ int load_and_show(char* filename)
1096 rb->lcd_clear_display(); 1126 rb->lcd_clear_display();
1097 } 1127 }
1098 while (status != PLUGIN_OK && status != PLUGIN_USB_CONNECTED 1128 while (status != PLUGIN_OK && status != PLUGIN_USB_CONNECTED
1099 && status != PLUGIN_OTHER); 1129 && status != PLUGIN_OTHER);
1100#ifdef USEGSLIB 1130#ifdef USEGSLIB
1101 rb->lcd_update(); 1131 rb->lcd_update();
1102#endif 1132#endif
@@ -1158,8 +1188,8 @@ enum plugin_status plugin_start(const void* parameter)
1158 do 1188 do
1159 { 1189 {
1160 condition = load_and_show(np_file); 1190 condition = load_and_show(np_file);
1161 }while (condition != PLUGIN_OK && condition != PLUGIN_USB_CONNECTED 1191 } while (condition != PLUGIN_OK && condition != PLUGIN_USB_CONNECTED
1162 && condition != PLUGIN_ERROR); 1192 && condition != PLUGIN_ERROR);
1163 1193
1164 if (rb->memcmp(&jpeg_settings, &old_settings, sizeof (jpeg_settings))) 1194 if (rb->memcmp(&jpeg_settings, &old_settings, sizeof (jpeg_settings)))
1165 { 1195 {
diff --git a/apps/plugins/png/png.c b/apps/plugins/png/png.c
index e24434fc72..9e3b780907 100644
--- a/apps/plugins/png/png.c
+++ b/apps/plugins/png/png.c
@@ -260,7 +260,7 @@ static unsigned LodePNG_decompress(unsigned char* out, size_t* outsize, const un
260 z_stream stream; 260 z_stream stream;
261 int err; 261 int err;
262 262
263 error_msg = ""; 263 rb->strcpy(error_msg, "");
264 264
265 stream.next_in = (Bytef*)in; 265 stream.next_in = (Bytef*)in;
266 stream.avail_in = (uInt)insize; 266 stream.avail_in = (uInt)insize;
@@ -284,7 +284,8 @@ static unsigned LodePNG_decompress(unsigned char* out, size_t* outsize, const un
284 *outsize = stream.total_out; 284 *outsize = stream.total_out;
285 285
286 err = inflateEnd(&stream); 286 err = inflateEnd(&stream);
287 error_msg = stream.msg; 287 if (stream.msg != Z_NULL)
288 rb->strcpy(error_msg, stream.msg);
288 return err; 289 return err;
289 290
290} 291}
@@ -1324,6 +1325,60 @@ void LodePNG_Decoder_cleanup(LodePNG_Decoder* decoder)
1324 LodePNG_InfoPng_cleanup(&decoder->infoPng); 1325 LodePNG_InfoPng_cleanup(&decoder->infoPng);
1325} 1326}
1326 1327
1328#define PNG_ERROR_MIN 27
1329#define PNG_ERROR_MAX 74
1330static const unsigned char *png_error_messages[PNG_ERROR_MAX-PNG_ERROR_MIN+1] =
1331{
1332 "png file smaller than a png header", /*27*/
1333 "incorrect png signature", /*28*/
1334 "first chunk is not IHDR", /*29*/
1335 "chunk length too large", /*30*/
1336 "illegal PNG color type or bpp", /*31*/
1337 "illegal PNG compression method", /*32*/
1338 "illegal PNG filter method", /*33*/
1339 "illegal PNG interlace method", /*34*/
1340 "chunk length of a chunk is too large or the chunk too small", /*35*/
1341 "illegal PNG filter type encountered", /*36*/
1342 "illegal bit depth for this color type given", /*37*/
1343 "the palette is too big (more than 256 colors)", /*38*/
1344 "more palette alpha values given in tRNS, than there are colors in the palette", /*39*/
1345 "tRNS chunk has wrong size for greyscale image", /*40*/
1346 "tRNS chunk has wrong size for RGB image", /*41*/
1347 "tRNS chunk appeared while it was not allowed for this color type", /*42*/
1348 "bKGD chunk has wrong size for palette image", /*43*/
1349 "bKGD chunk has wrong size for greyscale image", /*44*/
1350 "bKGD chunk has wrong size for RGB image", /*45*/
1351 "value encountered in indexed image is larger than the palette size", /*46*/
1352 "value encountered in indexed image is larger than the palette size", /*47*/
1353 "input file is empty", /*48*/
1354 NULL, /*49*/
1355 NULL, /*50*/
1356 NULL, /*51*/
1357 NULL, /*52*/
1358 NULL, /*53*/
1359 NULL, /*54*/
1360 NULL, /*55*/
1361 NULL, /*56*/
1362 "invalid CRC", /*57*/
1363 NULL, /*58*/
1364 "conversion to unexisting or unsupported color type or bit depth", /*59*/
1365 NULL, /*60*/
1366 NULL, /*61*/
1367 NULL, /*62*/
1368 "png chunk too long", /*63*/
1369 NULL, /*64*/
1370 NULL, /*65*/
1371 NULL, /*66*/
1372 NULL, /*67*/
1373 NULL, /*68*/
1374 "unknown critical chunk", /*69*/
1375 NULL, /*70*/
1376 NULL, /*71*/
1377 NULL, /*72*/
1378 "invalid tIME chunk size", /*73*/
1379 "invalid pHYs chunk size", /*74*/
1380};
1381
1327bool png_ext(const char ext[]) 1382bool png_ext(const char ext[])
1328{ 1383{
1329 if (!ext) 1384 if (!ext)
@@ -1454,9 +1509,9 @@ int show_menu(void) /* return 1 to quit */
1454 "Quit"); 1509 "Quit");
1455 1510
1456 static const struct opt_items slideshow[2] = { 1511 static const struct opt_items slideshow[2] = {
1457 { "Disable", -1 }, 1512 { "Disable", -1 },
1458 { "Enable", -1 }, 1513 { "Enable", -1 },
1459 }; 1514 };
1460 1515
1461 result=rb->do_menu(&menu, NULL, NULL, false); 1516 result=rb->do_menu(&menu, NULL, NULL, false);
1462 1517
@@ -1598,7 +1653,8 @@ int scroll_bmp(struct LodePNG_Decoder* decoder)
1598 { 1653 {
1599 if (slideshow_enabled) 1654 if (slideshow_enabled)
1600 button = rb->button_get_w_tmo(png_settings.ss_timeout * HZ); 1655 button = rb->button_get_w_tmo(png_settings.ss_timeout * HZ);
1601 else button = rb->button_get(true); 1656 else
1657 button = rb->button_get(true);
1602 1658
1603 running_slideshow = false; 1659 running_slideshow = false;
1604 1660
@@ -1681,10 +1737,12 @@ int scroll_bmp(struct LodePNG_Decoder* decoder)
1681 case PNG_RC_MENU: 1737 case PNG_RC_MENU:
1682#endif 1738#endif
1683 case PNG_MENU: 1739 case PNG_MENU:
1740
1684 if (show_menu() == 1) 1741 if (show_menu() == 1)
1685 return PLUGIN_OK; 1742 return PLUGIN_OK;
1686 else 1743
1687 return PLUGIN_REFRESH; 1744 draw_image(decoder);
1745 rb->lcd_update();
1688 1746
1689 break; 1747 break;
1690 default: 1748 default:
@@ -1755,6 +1813,140 @@ unsigned max_downscale(struct LodePNG_Decoder* decoder)
1755 return downscale; 1813 return downscale;
1756} 1814}
1757 1815
1816/* load image from filename. */
1817int load_image(char* filename, struct LodePNG_Decoder* decoder)
1818{
1819 int fd;
1820 long time = 0; /* measured ticks */
1821 int w, h; /* used to center output */
1822
1823 fd = rb->open(filename, O_RDONLY);
1824 if (fd < 0)
1825 {
1826 rb->snprintf(print,sizeof(print),"err opening %s:%d",filename,fd);
1827 rb->splash(HZ, print);
1828 return PLUGIN_ERROR;
1829 }
1830 image_size = rb->filesize(fd);
1831
1832 DEBUGF("reading file '%s'\n", filename);
1833
1834 if (!running_slideshow) {
1835 rb->snprintf(print, sizeof(print), "%s:", rb->strrchr(filename,'/')+1);
1836 rb->lcd_puts(0, 0, print);
1837 rb->lcd_update();
1838 }
1839
1840 if (image_size > memory_size) {
1841 decoder->error = FILE_TOO_LARGE;
1842 rb->close(fd);
1843#ifndef SIMULATOR
1844 if (running_slideshow && immediate_ata_off) {
1845 /* running slideshow and time is long enough: power down disk */
1846 rb->storage_sleep();
1847 }
1848#endif
1849
1850 } else {
1851 if (!running_slideshow) {
1852 rb->snprintf(print, sizeof(print), "loading %lu bytes", image_size);
1853 rb->lcd_puts(0, 1, print);
1854 rb->lcd_update();
1855 }
1856
1857 image = memory_max - image_size + 1;
1858 rb->read(fd, image, image_size);
1859 rb->close(fd);
1860
1861 if (!running_slideshow) {
1862 rb->snprintf(print, sizeof(print), "decoding image");
1863 rb->lcd_puts(0, 2, print);
1864 rb->lcd_update();
1865 }
1866#ifndef SIMULATOR
1867 else if (immediate_ata_off) {
1868 /* running slideshow and time is long enough: power down disk */
1869 rb->storage_sleep();
1870 }
1871#endif
1872
1873 decoder->settings.color_convert = 1;
1874 decoder->infoRaw.color.colorType = 2;
1875 decoder->infoRaw.color.bitDepth = 8;
1876
1877 LodePNG_inspect(decoder, image, image_size);
1878
1879 if (!decoder->error) {
1880
1881 if (!running_slideshow) {
1882 rb->snprintf(print, sizeof(print), "image %dx%d",
1883 decoder->infoPng.width, decoder->infoPng.height);
1884 rb->lcd_puts(0, 2, print);
1885 rb->lcd_update();
1886
1887 rb->snprintf(print, sizeof(print), "decoding %d*%d",
1888 decoder->infoPng.width, decoder->infoPng.height);
1889 rb->lcd_puts(0, 3, print);
1890 rb->lcd_update();
1891 }
1892
1893 /* the actual decoding */
1894 time = *rb->current_tick;
1895#ifdef HAVE_ADJUSTABLE_CPU_FREQ
1896 rb->cpu_boost(true);
1897 LodePNG_decode(decoder, image, image_size, cb_progress);
1898 rb->cpu_boost(false);
1899#else
1900 LodePNG_decode(decoder, image, image_size, cb_progress);
1901#endif /*HAVE_ADJUSTABLE_CPU_FREQ*/
1902 }
1903 }
1904
1905 time = *rb->current_tick - time;
1906
1907 if (!running_slideshow && !decoder->error)
1908 {
1909 rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ);
1910 rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */
1911 rb->lcd_putsxy((LCD_WIDTH - w)/2, LCD_HEIGHT - h, print);
1912 rb->lcd_update();
1913 }
1914
1915 if (decoder->error) {
1916 if (decoder->error == FILE_TOO_LARGE || decoder->error == OUT_OF_MEMORY
1917 || decoder->error == Z_MEM_ERROR)
1918 return PLUGIN_OUTOFMEM;
1919
1920 if (decoder->error >= PNG_ERROR_MIN && decoder->error <= PNG_ERROR_MAX
1921 && png_error_messages[decoder->error-PNG_ERROR_MIN] != NULL)
1922 {
1923 rb->splash(HZ, png_error_messages[decoder->error-PNG_ERROR_MIN]);
1924 }
1925 else
1926 {
1927 switch (decoder->error) {
1928 case PLUGIN_ABORT:
1929 break;
1930 case OUT_OF_MEMORY:
1931 case Z_MEM_ERROR:
1932 rb->splash(HZ, "Out of Memory");break;
1933 case FILE_TOO_LARGE:
1934 rb->splash(HZ, "File too large");break;
1935 case Z_DATA_ERROR:
1936 rb->splash(HZ, decoder->error_msg);break;
1937 default:
1938 rb->splashf(HZ, "other error : %ld", decoder->error);break;
1939 }
1940 }
1941
1942 if (decoder->error == PLUGIN_ABORT)
1943 return PLUGIN_ABORT;
1944 else
1945 return PLUGIN_ERROR;
1946 }
1947 return PLUGIN_OK;
1948}
1949
1758/* return decoded or cached image */ 1950/* return decoded or cached image */
1759fb_data *get_image(struct LodePNG_Decoder* decoder, int ds) 1951fb_data *get_image(struct LodePNG_Decoder* decoder, int ds)
1760{ 1952{
@@ -1778,7 +1970,7 @@ fb_data *get_image(struct LodePNG_Decoder* decoder, int ds)
1778 rb->lcd_puts(0, 3, print); 1970 rb->lcd_puts(0, 3, print);
1779 rb->lcd_update(); 1971 rb->lcd_update();
1780 } 1972 }
1781 static struct bitmap bmp_src, bmp_dst; 1973 struct bitmap bmp_src, bmp_dst;
1782 1974
1783 int size = decoder->width * decoder->height; 1975 int size = decoder->width * decoder->height;
1784 1976
@@ -1792,6 +1984,7 @@ fb_data *get_image(struct LodePNG_Decoder* decoder, int ds)
1792 } 1984 }
1793 1985
1794 disp[ds] = disp_buf; 1986 disp[ds] = disp_buf;
1987 disp_buf = (fb_data *)((intptr_t)(disp[ds] + size + 3) & ~3);
1795 1988
1796 bmp_src.width = decoder->infoPng.width; 1989 bmp_src.width = decoder->infoPng.width;
1797 bmp_src.height = decoder->infoPng.height; 1990 bmp_src.height = decoder->infoPng.height;
@@ -1807,8 +2000,6 @@ fb_data *get_image(struct LodePNG_Decoder* decoder, int ds)
1807#else 2000#else
1808 smooth_resize_bitmap(&bmp_src, &bmp_dst); 2001 smooth_resize_bitmap(&bmp_src, &bmp_dst);
1809#endif /*HAVE_ADJUSTABLE_CPU_FREQ*/ 2002#endif /*HAVE_ADJUSTABLE_CPU_FREQ*/
1810
1811 disp_buf = (fb_data *)((intptr_t)(disp[ds] + size + 3) & ~3);
1812 } else { 2003 } else {
1813 disp[ds] = converted_image; 2004 disp[ds] = converted_image;
1814 return converted_image; 2005 return converted_image;
@@ -1848,132 +2039,28 @@ void get_view(struct LodePNG_Decoder* decoder, int* p_cx, int* p_cy)
1848/* load, decode, display the image */ 2039/* load, decode, display the image */
1849int load_and_show(char* filename) 2040int load_and_show(char* filename)
1850{ 2041{
1851 int fd;
1852 int status; 2042 int status;
1853 long time=0; /* measured ticks */
1854 int cx=0, cy=0; /* view center */ 2043 int cx=0, cy=0; /* view center */
1855 int w, h; /* used to center output */
1856
1857 LodePNG_Decoder_init(&decoder);
1858 2044
1859 rb->lcd_clear_display();
1860
1861 fd = rb->open(filename, O_RDONLY);
1862 if (fd < 0)
1863 {
1864 rb->snprintf(print,sizeof(print),"err opening %s:%d",filename,fd);
1865 rb->splash(HZ, print);
1866 return PLUGIN_ERROR;
1867 }
1868 image_size = rb->filesize(fd);
1869 memset(&disp, 0, sizeof(disp));
1870
1871 DEBUGF("reading file '%s'\n", filename);
1872
1873 if (!running_slideshow) {
1874#if LCD_DEPTH > 1 2045#if LCD_DEPTH > 1
1875 rb->lcd_set_foreground(LCD_WHITE); 2046 rb->lcd_set_foreground(LCD_WHITE);
1876 rb->lcd_set_background(LCD_BLACK); 2047 rb->lcd_set_background(LCD_BLACK);
1877 rb->lcd_set_backdrop(NULL); 2048 rb->lcd_set_backdrop(NULL);
1878#endif
1879
1880 rb->lcd_clear_display();
1881 rb->snprintf(print, sizeof(print), "%s:", rb->strrchr(filename,'/')+1);
1882 rb->lcd_puts(0, 0, print);
1883 rb->lcd_update();
1884 }
1885
1886 if (rb->button_get(false) == PNG_MENU) {
1887 decoder.error = PLUGIN_ABORT;
1888 rb->close(fd);
1889
1890 } else if (image_size > memory_size) {
1891 decoder.error = FILE_TOO_LARGE;
1892 rb->close(fd);
1893
1894 } else {
1895 if (!running_slideshow) {
1896 rb->snprintf(print, sizeof(print), "loading %lu bytes", image_size);
1897 rb->lcd_puts(0, 1, print);
1898 rb->lcd_update();
1899 }
1900
1901 image = memory_max - image_size + 1;
1902 rb->read(fd, image, image_size);
1903 rb->close(fd);
1904
1905 if (!running_slideshow) {
1906 rb->snprintf(print, sizeof(print), "decoding image");
1907 rb->lcd_puts(0, 2, print);
1908 rb->lcd_update();
1909 }
1910#ifndef SIMULATOR
1911 else if (immediate_ata_off) {
1912 /* running slideshow and time is long enough: power down disk */
1913 rb->storage_sleep();
1914 }
1915#endif 2049#endif
2050 rb->lcd_clear_display();
1916 2051
1917 decoder.settings.color_convert = 1; 2052 memset(&disp, 0, sizeof(disp));
1918 decoder.infoRaw.color.colorType = 2; 2053 LodePNG_Decoder_init(&decoder);
1919 decoder.infoRaw.color.bitDepth = 8;
1920
1921 if (rb->button_get(false) == PNG_MENU) {
1922 decoder.error = PLUGIN_ABORT;
1923 } else {
1924 LodePNG_inspect(&decoder, image, image_size);
1925 }
1926
1927 if (!decoder.error) {
1928
1929 if (!running_slideshow) {
1930 rb->snprintf(print, sizeof(print), "image %dx%d",
1931 decoder.infoPng.width, decoder.infoPng.height);
1932 rb->lcd_puts(0, 2, print);
1933 rb->lcd_update();
1934 }
1935
1936 if (!running_slideshow)
1937 {
1938 rb->snprintf(print, sizeof(print), "decoding %d*%d",
1939 decoder.infoPng.width, decoder.infoPng.height);
1940 rb->lcd_puts(0, 3, print);
1941 rb->lcd_update();
1942 }
1943
1944 /* the actual decoding */
1945 time = *rb->current_tick;
1946#ifdef HAVE_ADJUSTABLE_CPU_FREQ
1947 rb->cpu_boost(true);
1948 LodePNG_decode(&decoder, image, image_size, cb_progress);
1949 rb->cpu_boost(false);
1950#else
1951 LodePNG_decode(&decoder, image, image_size, cb_progress);
1952#endif /*HAVE_ADJUSTABLE_CPU_FREQ*/
1953 }
1954 }
1955
1956 if (decoder.error == PLUGIN_ABORT || decoder.error == FILE_TOO_LARGE) {
1957#ifndef SIMULATOR
1958 if (immediate_ata_off) {
1959 /* running slideshow and time is long enough: power down disk */
1960 rb->storage_sleep();
1961 }
1962#endif
1963 }
1964 2054
1965 time = *rb->current_tick - time; 2055 if (rb->button_get(false) == PNG_MENU)
2056 status = PLUGIN_ABORT;
2057 else
2058 status = load_image(filename, &decoder);
1966 2059
1967 if (!running_slideshow && !decoder.error) 2060 if (status == PLUGIN_OUTOFMEM)
1968 { 2061 {
1969 rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ);
1970 rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */
1971 rb->lcd_putsxy((LCD_WIDTH - w)/2, LCD_HEIGHT - h, print);
1972 rb->lcd_update();
1973 }
1974
1975#if PLUGIN_BUFFER_SIZE >= MIN_MEM 2062#if PLUGIN_BUFFER_SIZE >= MIN_MEM
1976 if (plug_buf && (decoder.error == FILE_TOO_LARGE || decoder.error == OUT_OF_MEMORY || decoder.error == Z_MEM_ERROR)) 2063 if (plug_buf)
1977 { 2064 {
1978 rb->lcd_setfont(FONT_SYSFIXED); 2065 rb->lcd_setfont(FONT_SYSFIXED);
1979 rb->lcd_clear_display(); 2066 rb->lcd_clear_display();
@@ -2029,87 +2116,23 @@ int load_and_show(char* filename)
2029 } 2116 }
2030 } 2117 }
2031 } 2118 }
2032 //else 2119 else
2033#endif 2120#endif
2034 2121 {
2035 if (decoder.error) { 2122 rb->splash(HZ, "Out of Memory");
2036 2123 file_pt[curfile] = NULL;
2037 switch (decoder.error) { 2124 return change_filename(direction);
2038 case PLUGIN_ABORT:
2039 rb->splash(HZ, "aborted");break;
2040 case 27:
2041 rb->splash(HZ, "png file smaller than a png header");break;
2042 case 28:
2043 rb->splash(HZ, "incorrect png signature");break;
2044 case 29:
2045 rb->splash(HZ, "first chunk is not IHDR");break;
2046 case 30:
2047 rb->splash(HZ, "chunk length too large");break;
2048 case 31:
2049 rb->splash(HZ, "illegal PNG color type or bpp");break;
2050 case 32:
2051 rb->splash(HZ, "illegal PNG compression method");break;
2052 case 33:
2053 rb->splash(HZ, "illegal PNG filter method");break;
2054 case 34:
2055 rb->splash(HZ, "illegal PNG interlace method");break;
2056 case 35:
2057 rb->splash(HZ, "chunk length of a chunk is too large or the chunk too small");break;
2058 case 36:
2059 rb->splash(HZ, "illegal PNG filter type encountered");break;
2060 case 37:
2061 rb->splash(HZ, "illegal bit depth for this color type given");break;
2062 case 38:
2063 rb->splash(HZ, "the palette is too big (more than 256 colors)");break;
2064 case 39:
2065 rb->splash(HZ, "more palette alpha values given in tRNS, than there are colors in the palette");break;
2066 case 40:
2067 rb->splash(HZ, "tRNS chunk has wrong size for greyscale image");break;
2068 case 41:
2069 rb->splash(HZ, "tRNS chunk has wrong size for RGB image");break;
2070 case 42:
2071 rb->splash(HZ, "tRNS chunk appeared while it was not allowed for this color type");break;
2072 case 43:
2073 rb->splash(HZ, "bKGD chunk has wrong size for palette image");break;
2074 case 44:
2075 rb->splash(HZ, "bKGD chunk has wrong size for greyscale image");break;
2076 case 45:
2077 rb->splash(HZ, "bKGD chunk has wrong size for RGB image");break;
2078 case 46:
2079 case 47:
2080 rb->splash(HZ, "value encountered in indexed image is larger than the palette size");break;
2081 case 48:
2082 rb->splash(HZ, "input file is empty");break;
2083 case OUT_OF_MEMORY:
2084 case Z_MEM_ERROR:
2085 rb->splash(HZ, "Out of Memory");break;
2086 case 57:
2087 rb->splash(HZ, "invalid CRC");break;
2088 case 59:
2089 rb->splash(HZ, "conversion to unexisting or unsupported color type or bit depth");break;
2090 case 63:
2091 rb->splash(HZ, "png chunk too long");break;
2092 case 69:
2093 rb->splash(HZ, "unknown critical chunk");break;
2094 case 73:
2095 rb->splash(HZ, "invalid tIME chunk size");break;
2096 case 74:
2097 rb->splash(HZ, "invalid pHYs chunk size");break;
2098 case FILE_TOO_LARGE:
2099 rb->splash(HZ, "File too large");break;
2100 case Z_DATA_ERROR:
2101 rb->splash(HZ, decoder.error_msg);break;
2102 default:
2103 rb->splashf(HZ, "other error : %ld", decoder.error);break;
2104 }
2105
2106 if (decoder.error == PLUGIN_ABORT) {
2107 return PLUGIN_OK;
2108 } else {
2109 file_pt[curfile] = NULL;
2110 return change_filename(direction);
2111 }
2112 } 2125 }
2126 }
2127 else if (status == PLUGIN_ERROR)
2128 {
2129 file_pt[curfile] = NULL;
2130 return change_filename(direction);
2131 }
2132 else if (status == PLUGIN_ABORT) {
2133 rb->splash(HZ, "aborted");
2134 return PLUGIN_OK;
2135 }
2113 2136
2114 disp_buf = (fb_data *)((intptr_t)(converted_image + converted_image_size + 3) & ~3); 2137 disp_buf = (fb_data *)((intptr_t)(converted_image + converted_image_size + 3) & ~3);
2115 ds_max = max_downscale(&decoder); /* check display constraint */ 2138 ds_max = max_downscale(&decoder); /* check display constraint */
@@ -2231,7 +2254,7 @@ enum plugin_status plugin_start(const void* parameter)
2231 do 2254 do
2232 { 2255 {
2233 condition = load_and_show(np_file); 2256 condition = load_and_show(np_file);
2234 }while (condition != PLUGIN_OK && condition != PLUGIN_USB_CONNECTED 2257 } while (condition != PLUGIN_OK && condition != PLUGIN_USB_CONNECTED
2235 && condition != PLUGIN_ERROR); 2258 && condition != PLUGIN_ERROR);
2236 2259
2237 if (rb->memcmp(&png_settings, &old_settings, sizeof (png_settings))) 2260 if (rb->memcmp(&png_settings, &old_settings, sizeof (png_settings)))
@@ -2252,4 +2275,3 @@ enum plugin_status plugin_start(const void* parameter)
2252 2275
2253 return condition; 2276 return condition;
2254} 2277}
2255
diff --git a/apps/plugins/png/png.h b/apps/plugins/png/png.h
index 50ae334ad0..4699e24e70 100644
--- a/apps/plugins/png/png.h
+++ b/apps/plugins/png/png.h
@@ -359,8 +359,8 @@ You are free to name this file lodepng.cpp or lodepng.c depending on your usage.
359#endif 359#endif
360#endif 360#endif
361 361
362#define PLUGIN_OTHER 10 /* State code for output with return. */ 362#define PLUGIN_OTHER 10 /* State code for output with return. */
363#define PLUGIN_REFRESH 11 /* State code for output with return. */ 363#define PLUGIN_ABORT 11
364#define PLUGIN_ABORT 12 364#define PLUGIN_OUTOFMEM 12
365#define OUT_OF_MEMORY 9900 365#define OUT_OF_MEMORY 9900
366#define FILE_TOO_LARGE 9910 366#define FILE_TOO_LARGE 9910