summaryrefslogtreecommitdiff
path: root/apps/plugins/jpeg/jpeg.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/jpeg/jpeg.c')
-rw-r--r--apps/plugins/jpeg/jpeg.c224
1 files changed, 127 insertions, 97 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 {