diff options
author | Teruaki Kawashima <teru@rockbox.org> | 2009-12-18 13:06:21 +0000 |
---|---|---|
committer | Teruaki Kawashima <teru@rockbox.org> | 2009-12-18 13:06:21 +0000 |
commit | 3e2aba0c3eded353ba119e5df23968d70b1263c5 (patch) | |
tree | 56ff071a728f451afd7a1f7e091bd201db85f11a /apps/plugins/jpeg/jpeg.c | |
parent | d42cdfd91c581d20a4e895a73e5fdc8830693ba2 (diff) | |
download | rockbox-3e2aba0c3eded353ba119e5df23968d70b1263c5.tar.gz rockbox-3e2aba0c3eded353ba119e5df23968d70b1263c5.zip |
jpeg,png: Separate code to load file from load_and_show().
Add a way to abort loading to jpeg inspired by png.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24075 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/jpeg/jpeg.c')
-rw-r--r-- | apps/plugins/jpeg/jpeg.c | 224 |
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 | ||
107 | static struct jpeg_settings jpeg_settings = | 109 | static 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 | }; |
115 | static struct jpeg_settings old_settings; | 117 | static struct jpeg_settings old_settings; |
116 | 118 | ||
117 | static struct configdata jpeg_config[] = | 119 | static 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. */ | ||
743 | int 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 */ |
742 | struct t_disp* get_image(struct jpeg* p_jpg, int ds) | 824 | struct 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 */ |
861 | void get_view(struct t_disp* p_disp, int* p_cx, int* p_cy) | 942 | void 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 */ |
869 | int load_and_show(char* filename) | 949 | int 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 | { |