summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/plugins/CATEGORIES1
-rw-r--r--apps/plugins/imageviewer/SUBDIRS1
-rw-r--r--apps/plugins/imageviewer/image_decoder.c5
-rw-r--r--apps/plugins/imageviewer/image_decoder.h2
-rw-r--r--apps/plugins/imageviewer/imageviewer.c9
-rw-r--r--apps/plugins/imageviewer/imageviewer.h1
-rw-r--r--apps/plugins/imageviewer/jpeg/jpeg.c4
-rw-r--r--apps/plugins/imageviewer/jpegp/BUFFILEGETC.c94
-rw-r--r--apps/plugins/imageviewer/jpegp/FILEGETC.c71
-rw-r--r--apps/plugins/imageviewer/jpegp/GETC.h14
-rw-r--r--apps/plugins/imageviewer/jpegp/SOURCES6
-rw-r--r--apps/plugins/imageviewer/jpegp/jpeg81.c24
-rw-r--r--apps/plugins/imageviewer/jpegp/jpeg81.h2
-rw-r--r--apps/plugins/imageviewer/jpegp/jpegp.c260
-rw-r--r--apps/plugins/imageviewer/jpegp/jpegp.make32
-rw-r--r--apps/plugins/imageviewer/jpegp/mempool.c50
-rw-r--r--apps/plugins/imageviewer/jpegp/mempool.h7
-rw-r--r--apps/plugins/imageviewer/jpegp/rb_glue.h35
-rw-r--r--manual/plugins/imageviewer.tex3
19 files changed, 599 insertions, 22 deletions
diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIES
index 79186b7aed..aa7dbf38e5 100644
--- a/apps/plugins/CATEGORIES
+++ b/apps/plugins/CATEGORIES
@@ -51,6 +51,7 @@ iriverify,viewers
51jackpot,games 51jackpot,games
52jewels,games 52jewels,games
53jpeg,viewers 53jpeg,viewers
54jpegp,viewers
54keybox,apps 55keybox,apps
55keyremap,apps 56keyremap,apps
56lamp,apps 57lamp,apps
diff --git a/apps/plugins/imageviewer/SUBDIRS b/apps/plugins/imageviewer/SUBDIRS
index 1f7b4d8b52..ea7c304218 100644
--- a/apps/plugins/imageviewer/SUBDIRS
+++ b/apps/plugins/imageviewer/SUBDIRS
@@ -3,5 +3,6 @@ jpeg
3png 3png
4#ifdef HAVE_LCD_COLOR 4#ifdef HAVE_LCD_COLOR
5ppm 5ppm
6jpegp
6#endif 7#endif
7gif 8gif
diff --git a/apps/plugins/imageviewer/image_decoder.c b/apps/plugins/imageviewer/image_decoder.c
index 0c1776daaa..c481899bae 100644
--- a/apps/plugins/imageviewer/image_decoder.c
+++ b/apps/plugins/imageviewer/image_decoder.c
@@ -25,12 +25,13 @@
25 25
26static const char *decoder_names[MAX_IMAGE_TYPES] = { 26static const char *decoder_names[MAX_IMAGE_TYPES] = {
27 "bmp", 27 "bmp",
28 "jpeg", 28 "jpeg", // Default decoder for jpeg: Use jpeg for old decoder, jpegp for new
29 "png", 29 "png",
30#ifdef HAVE_LCD_COLOR 30#ifdef HAVE_LCD_COLOR
31 "ppm", 31 "ppm",
32#endif 32#endif
33 "gif" 33 "gif",
34 "jpegp",
34}; 35};
35 36
36/* Check file type by magic number or file extension 37/* Check file type by magic number or file extension
diff --git a/apps/plugins/imageviewer/image_decoder.h b/apps/plugins/imageviewer/image_decoder.h
index c27ed33e8e..7a9cd5d06c 100644
--- a/apps/plugins/imageviewer/image_decoder.h
+++ b/apps/plugins/imageviewer/image_decoder.h
@@ -33,6 +33,8 @@ enum image_type {
33 IMAGE_PPM, 33 IMAGE_PPM,
34#endif 34#endif
35 IMAGE_GIF, 35 IMAGE_GIF,
36 IMAGE_JPEG_PROGRESSIVE,
37
36 MAX_IMAGE_TYPES 38 MAX_IMAGE_TYPES
37}; 39};
38 40
diff --git a/apps/plugins/imageviewer/imageviewer.c b/apps/plugins/imageviewer/imageviewer.c
index b849812508..ba5f8fec16 100644
--- a/apps/plugins/imageviewer/imageviewer.c
+++ b/apps/plugins/imageviewer/imageviewer.c
@@ -853,6 +853,8 @@ static int load_and_show(char* filename, struct image_info *info)
853 file_pt[curfile] = NULL; 853 file_pt[curfile] = NULL;
854 return change_filename(direction); 854 return change_filename(direction);
855 } 855 }
856
857reload_decoder:
856 if (image_type != status) /* type of image is changed, load decoder. */ 858 if (image_type != status) /* type of image is changed, load decoder. */
857 { 859 {
858 struct loader_info loader_info = { 860 struct loader_info loader_info = {
@@ -881,6 +883,13 @@ static int load_and_show(char* filename, struct image_info *info)
881 else 883 else
882 status = imgdec->load_image(filename, info, buf, &remaining); 884 status = imgdec->load_image(filename, info, buf, &remaining);
883 885
886 if (status == PLUGIN_JPEG_PROGRESSIVE)
887 {
888 rb->lcd_clear_display();
889 status = IMAGE_JPEG_PROGRESSIVE;
890 goto reload_decoder;
891 }
892
884 if (status == PLUGIN_OUTOFMEM) 893 if (status == PLUGIN_OUTOFMEM)
885 { 894 {
886#ifdef USE_PLUG_BUF 895#ifdef USE_PLUG_BUF
diff --git a/apps/plugins/imageviewer/imageviewer.h b/apps/plugins/imageviewer/imageviewer.h
index ac15df5960..44e56c0696 100644
--- a/apps/plugins/imageviewer/imageviewer.h
+++ b/apps/plugins/imageviewer/imageviewer.h
@@ -55,6 +55,7 @@ enum {
55 PLUGIN_OTHER = 0x200, 55 PLUGIN_OTHER = 0x200,
56 PLUGIN_ABORT, 56 PLUGIN_ABORT,
57 PLUGIN_OUTOFMEM, 57 PLUGIN_OUTOFMEM,
58 PLUGIN_JPEG_PROGRESSIVE,
58 59
59 ZOOM_IN, 60 ZOOM_IN,
60 ZOOM_OUT, 61 ZOOM_OUT,
diff --git a/apps/plugins/imageviewer/jpeg/jpeg.c b/apps/plugins/imageviewer/jpeg/jpeg.c
index 3d8c9c3ac8..c231209beb 100644
--- a/apps/plugins/imageviewer/jpeg/jpeg.c
+++ b/apps/plugins/imageviewer/jpeg/jpeg.c
@@ -170,8 +170,12 @@ static int load_image(char *filename, struct image_info *info,
170 170
171 if (status < 0 || (status & (DQT | SOF0)) != (DQT | SOF0)) 171 if (status < 0 || (status & (DQT | SOF0)) != (DQT | SOF0))
172 { /* bad format or minimum components not contained */ 172 { /* bad format or minimum components not contained */
173#ifndef HAVE_LCD_COLOR
173 rb->splashf(HZ, "unsupported %d", status); 174 rb->splashf(HZ, "unsupported %d", status);
174 return PLUGIN_ERROR; 175 return PLUGIN_ERROR;
176#else
177 return PLUGIN_JPEG_PROGRESSIVE;
178#endif
175 } 179 }
176 180
177 if (!(status & DHT)) /* if no Huffman table present: */ 181 if (!(status & DHT)) /* if no Huffman table present: */
diff --git a/apps/plugins/imageviewer/jpegp/BUFFILEGETC.c b/apps/plugins/imageviewer/jpegp/BUFFILEGETC.c
new file mode 100644
index 0000000000..5124636731
--- /dev/null
+++ b/apps/plugins/imageviewer/jpegp/BUFFILEGETC.c
@@ -0,0 +1,94 @@
1/* Simple buffered version of file reader.
2 * JPEG decoding seems to work faster with it.
3 * Not fully tested. In case of any issues try FILEGETC (see SOURCES)
4 * */
5#include "rb_glue.h"
6
7static int fd;
8static unsigned char buff[256]; //TODO: Adjust it...
9static int length = 0;
10static int cur_buff_pos = 0;
11static int file_pos = 0;
12
13extern int GETC(void)
14{
15 if (cur_buff_pos >= length)
16 {
17 length = rb->read(fd, buff, sizeof(buff));
18 file_pos += length;
19 cur_buff_pos = 0;
20 }
21
22 return buff[cur_buff_pos++];
23}
24
25// multibyte readers: host-endian independent - if evaluated in right order (ie. don't optimize)
26
27extern int GETWbi(void) // 16-bit big-endian
28{
29 return ( GETC()<<8 ) | GETC();
30}
31
32extern int GETDbi(void) // 32-bit big-endian
33{
34 return ( GETC()<<24 ) | ( GETC()<<16 ) | ( GETC()<<8 ) | GETC();
35}
36
37extern int GETWli(void) // 16-bit little-endian
38{
39 return GETC() | ( GETC()<<8 );
40}
41
42extern int GETDli(void) // 32-bit little-endian
43{
44 return GETC() | ( GETC()<<8 ) | ( GETC()<<16 ) | ( GETC()<<24 );
45}
46
47// seek
48
49extern void SEEK(int d)
50{
51 int newPos = cur_buff_pos + d;
52 if (newPos < length && newPos >= 0)
53 {
54 cur_buff_pos = newPos;
55 return;
56 }
57 file_pos = rb->lseek(fd, (cur_buff_pos - length) + d, SEEK_CUR);
58 cur_buff_pos = length = 0;
59}
60
61extern void POS(int d)
62{
63 cur_buff_pos = length = 0;
64 file_pos = d;
65 rb->lseek(fd, d, SEEK_SET);
66}
67
68extern int TELL(void)
69{
70 return file_pos + cur_buff_pos - length;
71}
72
73// OPEN/CLOSE file
74
75extern void *OPEN(char *f)
76{
77 printf("Opening %s\n", f);
78 cur_buff_pos = length = file_pos = 0;
79 fd = rb->open(f,O_RDONLY);
80
81 if ( fd < 0 )
82 {
83 printf("Error opening %s\n", f);
84 return NULL;
85 }
86
87 return &fd;
88}
89
90extern int CLOSE(void)
91{
92 cur_buff_pos = length = file_pos = 0;
93 return rb->close(fd);
94}
diff --git a/apps/plugins/imageviewer/jpegp/FILEGETC.c b/apps/plugins/imageviewer/jpegp/FILEGETC.c
new file mode 100644
index 0000000000..bb7f0c485f
--- /dev/null
+++ b/apps/plugins/imageviewer/jpegp/FILEGETC.c
@@ -0,0 +1,71 @@
1#include "rb_glue.h"
2
3static int fd;
4
5extern int GETC(void)
6{
7 unsigned char x;
8 rb->read(fd, &x, 1);
9 return x;
10}
11
12// multibyte readers: host-endian independent - if evaluated in right order (ie. don't optimize)
13
14extern int GETWbi(void) // 16-bit big-endian
15{
16 return ( GETC()<<8 ) | GETC();
17}
18
19extern int GETDbi(void) // 32-bit big-endian
20{
21 return ( GETC()<<24 ) | ( GETC()<<16 ) | ( GETC()<<8 ) | GETC();
22}
23
24extern int GETWli(void) // 16-bit little-endian
25{
26 return GETC() | ( GETC()<<8 );
27}
28
29extern int GETDli(void) // 32-bit little-endian
30{
31 return GETC() | ( GETC()<<8 ) | ( GETC()<<16 ) | ( GETC()<<24 );
32}
33
34// seek
35
36extern void SEEK(int d)
37{
38 rb->lseek(fd, d, SEEK_CUR);
39}
40
41extern void POS(int d)
42{
43 rb->lseek(fd, d, SEEK_SET);
44}
45
46extern int TELL(void)
47{
48 return rb->lseek(fd, 0, SEEK_CUR);
49}
50
51// OPEN/CLOSE file
52
53extern void *OPEN(char *f)
54{
55 printf("Opening %s\n", f);
56
57 fd = rb->open(f,O_RDONLY);
58
59 if ( fd < 0 )
60 {
61 printf("Error opening %s\n", f);
62 return NULL;
63 }
64
65 return &fd;
66}
67
68extern int CLOSE(void)
69{
70 return rb->close(fd);
71}
diff --git a/apps/plugins/imageviewer/jpegp/GETC.h b/apps/plugins/imageviewer/jpegp/GETC.h
index d17cdb9857..5e8a3c6a9d 100644
--- a/apps/plugins/imageviewer/jpegp/GETC.h
+++ b/apps/plugins/imageviewer/jpegp/GETC.h
@@ -37,20 +37,20 @@
37 37
38// For decoders 38// For decoders
39 39
40extern int GETC(); 40extern int GETC(void);
41 41
42// Multibyte helpers 42// Multibyte helpers
43extern int GETWbi(); // read word (16-bit) big-endian 43extern int GETWbi(void); // read word (16-bit) big-endian
44extern int GETWli(); // little-endian 44extern int GETWli(void); // little-endian
45extern int GETDbi(); // read double word (32-bit) big-endian 45extern int GETDbi(void); // read double word (32-bit) big-endian
46extern int GETDli(); // little-endian 46extern int GETDli(void); // little-endian
47 47
48// positioning 48// positioning
49extern void SEEK(int); // move relative to current 49extern void SEEK(int); // move relative to current
50extern void POS(int); // move absolute position (TIFF) 50extern void POS(int); // move absolute position (TIFF)
51extern int TELL(); // read actual position 51extern int TELL(void); // read actual position
52 52
53 53
54// For RAINBOW clients to implement outside of Rainbow Library 54// For RAINBOW clients to implement outside of Rainbow Library
55extern void *OPEN(char*); 55extern void *OPEN(char*);
56extern void CLOSE(); 56extern void CLOSE(void);
diff --git a/apps/plugins/imageviewer/jpegp/SOURCES b/apps/plugins/imageviewer/jpegp/SOURCES
new file mode 100644
index 0000000000..dfaf63a42f
--- /dev/null
+++ b/apps/plugins/imageviewer/jpegp/SOURCES
@@ -0,0 +1,6 @@
1jpegp.c
2//FILEGETC.c
3BUFFILEGETC.c
4jpeg81.c
5idct.c
6mempool.c \ No newline at end of file
diff --git a/apps/plugins/imageviewer/jpegp/jpeg81.c b/apps/plugins/imageviewer/jpegp/jpeg81.c
index 95e46dbd17..76b36ca950 100644
--- a/apps/plugins/imageviewer/jpegp/jpeg81.c
+++ b/apps/plugins/imageviewer/jpegp/jpeg81.c
@@ -40,12 +40,12 @@ jpeg81.c
40* SOFTWARE. 40* SOFTWARE.
41*/ 41*/
42 42
43#include "GETC.h" 43#include "GETC.h"
44#include "rb_glue.h"
44#include "jpeg81.h" 45#include "jpeg81.h"
45#include <malloc.h> // calloc() called once
46#include <stdio.h> // debug only
47
48 46
47#pragma GCC diagnostic push
48#pragma GCC diagnostic ignored "-Wunused-parameter"
49///////////////////////////////////////// LOSSLESS ///////////////////////////////////////// 49///////////////////////////////////////// LOSSLESS /////////////////////////////////////////
50 50
51static int P1(struct COMP *C, TSAMP *samp) // Px = Ra 51static int P1(struct COMP *C, TSAMP *samp) // Px = Ra
@@ -63,17 +63,17 @@ static int P3(struct COMP *C, TSAMP *samp) // Px = Rc
63 return samp[-C->du_width-1]; 63 return samp[-C->du_width-1];
64} 64}
65 65
66static int P4(struct COMP *C, TSAMP *samp) // Px = Ra + Rb Rc 66static int P4(struct COMP *C, TSAMP *samp) // Px = Ra + Rb - Rc
67{ 67{
68 return samp[-1] + samp[-C->du_width] - samp[-C->du_width-1]; 68 return samp[-1] + samp[-C->du_width] - samp[-C->du_width-1];
69} 69}
70 70
71static int P5(struct COMP *C, TSAMP *samp) // Px = Ra + ((Rb Rc)/2) 71static int P5(struct COMP *C, TSAMP *samp) // Px = Ra + ((Rb - Rc)/2)
72{ 72{
73 return samp[-1] + ( (samp[-C->du_width] - samp[-C->du_width-1]) >> 1 ); 73 return samp[-1] + ( (samp[-C->du_width] - samp[-C->du_width-1]) >> 1 );
74} 74}
75 75
76static int P6(struct COMP *C, TSAMP *samp) // Px = Rb + ((Ra Rc)/2) 76static int P6(struct COMP *C, TSAMP *samp) // Px = Rb + ((Ra - Rc)/2)
77{ 77{
78 return samp[-C->du_width] + ( (samp[-1] - samp[-C->du_width-1]) >> 1 ); 78 return samp[-C->du_width] + ( (samp[-1] - samp[-C->du_width-1]) >> 1 );
79} 79}
@@ -215,7 +215,7 @@ static void du_sequential_huff(struct JPEGD *j, struct COMP *sc, TCOEF *coef)
215{ 215{
216 int s, k; 216 int s, k;
217 dc_decode_huff(j, sc, coef); 217 dc_decode_huff(j, sc, coef);
218 for (k=1; s=sc->ACS[ReadHuffmanCode(j, sc->ACB)]; k++) { // EOB? 218 for (k=1; (s=sc->ACS[ReadHuffmanCode(j, sc->ACB)]); k++) { // EOB?
219 k+= s>>4; 219 k+= s>>4;
220 if (s==0xf0) continue; // ZRL 220 if (s==0xf0) continue; // ZRL
221 coef[k]= ReadDiff(j, s&15); 221 coef[k]= ReadDiff(j, s&15);
@@ -496,7 +496,7 @@ static void Ri(struct JPEGD *j, int n)
496 printf("RST%d\n", Marker&7); 496 printf("RST%d\n", Marker&7);
497 printf("%08X: ECS\n", TELL()); 497 printf("%08X: ECS\n", TELL());
498 } 498 }
499 else printf("STREAM ERROR: expected RSTn missing from ECS\n"); 499 else { printf("STREAM ERROR: expected RSTn missing from ECS\n"); }
500 j->Reset_decoder(j); 500 j->Reset_decoder(j);
501 } 501 }
502 } 502 }
@@ -832,7 +832,7 @@ extern enum JPEGENUM JPEGDecode(struct JPEGD *j)
832 } 832 }
833 } 833 }
834 834
835 printf(" Malloc for %d Data Units (%d bytes)\n\n", TotalDU, sizeof(DU)*TotalDU); 835 printf(" Malloc for %d Data Units (%lu bytes)\n\n", TotalDU, sizeof(DU)*TotalDU);
836 836
837 if (j->SOF > 0xC8) { // DCT Arithmetic 837 if (j->SOF > 0xC8) { // DCT Arithmetic
838 j->Reset_decoder= Reset_decoder_arith; 838 j->Reset_decoder= Reset_decoder_arith;
@@ -953,7 +953,7 @@ extern enum JPEGENUM JPEGDecode(struct JPEGD *j)
953 953
954 for (Lq-=2; Lq; Lq -= 65 + 64*Pq) 954 for (Lq-=2; Lq; Lq -= 65 + 64*Pq)
955 { 955 {
956 int (*get)(); 956 int (*get)(void);
957 int T= GETC(); 957 int T= GETC();
958 int Tq= T&3; 958 int Tq= T&3;
959 int *qt= j->QT[Tq]; 959 int *qt= j->QT[Tq];
@@ -993,3 +993,5 @@ extern enum JPEGENUM JPEGDecode(struct JPEGD *j)
993 } 993 }
994 } 994 }
995} 995}
996
997#pragma GCC diagnostic pop \ No newline at end of file
diff --git a/apps/plugins/imageviewer/jpegp/jpeg81.h b/apps/plugins/imageviewer/jpegp/jpeg81.h
index fa71b10113..e265d84926 100644
--- a/apps/plugins/imageviewer/jpegp/jpeg81.h
+++ b/apps/plugins/imageviewer/jpegp/jpeg81.h
@@ -144,4 +144,4 @@ struct JPEGD { // The JPEG DECODER OBJECT
144 144
145}; 145};
146 146
147extern int JPEGDecode(struct JPEGD *j); 147extern enum JPEGENUM JPEGDecode(struct JPEGD *j);
diff --git a/apps/plugins/imageviewer/jpegp/jpegp.c b/apps/plugins/imageviewer/jpegp/jpegp.c
new file mode 100644
index 0000000000..bb7be314f1
--- /dev/null
+++ b/apps/plugins/imageviewer/jpegp/jpegp.c
@@ -0,0 +1,260 @@
1#include "jpeg81.h"
2#include "idct.h"
3#include "GETC.h"
4#include "rb_glue.h"
5
6#include "../imageviewer.h"
7
8
9/**************** begin Application ********************/
10
11/************************* Types ***************************/
12
13struct t_disp
14{
15 unsigned char* bitmap;
16};
17
18/************************* Globals ***************************/
19
20/* decompressed image in the possible sizes (1,2,4,8), wasting the other */
21static struct t_disp disp[9];
22
23static struct JPEGD jpg; /* too large for stack */
24
25/************************* Implementation ***************************/
26
27static void draw_image_rect(struct image_info *info,
28 int x, int y, int width, int height)
29{
30 struct t_disp* pdisp = (struct t_disp*)info->data;
31#ifdef HAVE_LCD_COLOR
32 rb->lcd_bitmap_part(
33 (fb_data*)pdisp->bitmap, info->x + x, info->y + y,
34 STRIDE(SCREEN_MAIN, info->width, info->height),
35 x + MAX(0, (LCD_WIDTH-info->width)/2),
36 y + MAX(0, (LCD_HEIGHT-info->height)/2),
37 width, height);
38#else
39 mylcd_ub_gray_bitmap_part(
40 pdisp->bitmap, info->x + x, info->y + y, info->width,
41 x + MAX(0, (LCD_WIDTH-info->width)/2),
42 y + MAX(0, (LCD_HEIGHT-info->height)/2),
43 width, height);
44#endif
45}
46
47static int img_mem(int ds)
48{
49 struct JPEGD* j = &jpg;
50 return j->Y/ds * j->X/ds*sizeof(fb_data);
51}
52
53/* my memory pool (from the mp3 buffer) */
54static char print[32]; /* use a common snprintf() buffer */
55
56static void scaled_dequantization_and_idct(void)
57{
58 struct JPEGD* j = &jpg;
59 // The following code is based on RAINBOW lib jpeg2bmp example:
60 // https://github.com/Halicery/vc_rainbow/blob/605c045a564dad8e2df84e48914eac3d2d8d4a9b/jpeg2bmp.c
61
62 printf("Scaled de-quantization and IDCT.. ");
63 int c, i, n;
64
65 // Pre-scale quant-tables
66 int SQ[4][64];
67 for (c=0; c<4 && j->QT[c][0]; c++)
68 {
69 int *q= j->QT[c], *sq= SQ[c];
70 for (i=0; i<64; i++) sq[i]= q[i] * SCALEM[zigzag[i]];
71 }
72
73 // DEQUANT + IDCT
74 for (c=0; c<j->Nf; c++)
75 {
76 struct COMP *C= j->Components+c;
77 //int *q= j->QT[C->Qi];
78 int *sq= SQ[C->Qi];
79
80 for (n=0; n < C->du_size; n++)
81 {
82 /*
83 // <--- scaled idct
84 int k, t[64];
85 TCOEF *coef= du[x];
86 t[0]= coef[0] * q[0] + 1024; // dequant DC and level-shift (8-bit)
87 for (k=1; k<64; k++) t[zigzag[k]] = coef[k] * q[k]; // dequant AC (+zigzag)
88 idct_s(t, coef);
89 */
90
91 // <--- scaled idct with dequant
92 idct_sq( C->du[ (n / C->du_w) * C->du_width + n % C->du_w ], sq );
93 }
94 }
95 printf("done\n");
96}
97
98static int load_image(char *filename, struct image_info *info,
99 unsigned char *buf, ssize_t *buf_size)
100{
101 int status;
102 struct JPEGD *p_jpg = &jpg;
103
104 memset(&disp, 0, sizeof(disp));
105 memset(&jpg, 0, sizeof(jpg));
106
107 init_mem_pool(buf, *buf_size);
108
109 if (!OPEN(filename))
110 {
111 return PLUGIN_ERROR;
112 }
113
114 if (!iv->running_slideshow)
115 {
116 rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1);
117 rb->lcd_puts(0, 2, "decoding...");
118 rb->lcd_update();
119 }
120 long time; /* measured ticks */
121
122 /* the actual decoding */
123 time = *rb->current_tick;
124 status = JPEGDecode(p_jpg);
125 time = *rb->current_tick - time;
126
127 CLOSE();
128
129 if (status < 0)
130 { /* bad format or minimum components not contained */
131 if (status == JPEGENUMERR_MALLOC)
132 {
133 return PLUGIN_OUTOFMEM;
134 }
135 rb->splashf(HZ, "unsupported %d", status);
136 return PLUGIN_ERROR;
137 }
138
139 if (!iv->running_slideshow)
140 {
141 rb->lcd_putsf(0, 2, "image %dx%d", p_jpg->X, p_jpg->Y);
142 int w, h; /* used to center output */
143 rb->snprintf(print, sizeof(print), "jpegp %ld.%02ld sec ", time/HZ, time%HZ);
144 rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */
145 rb->lcd_putsxy((LCD_WIDTH - w)/2, LCD_HEIGHT - h, print);
146 rb->lcd_update();
147 //rb->sleep(100);
148 }
149
150 info->x_size = p_jpg->X;
151 info->y_size = p_jpg->Y;
152
153#ifdef DISK_SPINDOWN
154 if (iv->running_slideshow && iv->immediate_ata_off)
155 {
156 /* running slideshow and time is long enough: power down disk */
157 rb->storage_sleep();
158 }
159#endif
160
161 if ( 3 != p_jpg->Nf )
162 return PLUGIN_ERROR;
163
164 scaled_dequantization_and_idct();
165
166 *buf_size = freeze_mem_pool();
167 return PLUGIN_OK;
168}
169
170static int get_image(struct image_info *info, int frame, int ds)
171{
172 (void)frame;
173 struct JPEGD* p_jpg = &jpg;
174 struct t_disp* p_disp = &disp[ds]; /* short cut */
175
176 info->width = p_jpg->X / ds;
177 info->height = p_jpg->Y / ds;
178 info->data = p_disp;
179
180 if (p_disp->bitmap != NULL)
181 {
182 /* we still have it */
183 return PLUGIN_OK;
184 }
185
186 struct JPEGD* j = p_jpg;
187 int mem = img_mem(ds);
188
189 p_disp->bitmap = malloc(mem);
190
191 if (!p_disp->bitmap)
192 {
193 clear_mem_pool();
194 memset(&disp, 0, sizeof(disp));
195 p_disp->bitmap = malloc(mem);
196 if (!p_disp->bitmap)
197 return PLUGIN_ERROR;
198 }
199
200 fb_data *bmp = (fb_data *)p_disp->bitmap;
201
202 // The following code is based on RAINBOW lib jpeg2bmp example:
203 // https://github.com/Halicery/vc_rainbow/blob/605c045a564dad8e2df84e48914eac3d2d8d4a9b/jpeg2bmp.c
204 // Primitive yuv-rgb converter for all sub-sampling types, 24-bit BMP only
205 printf("YUV-to-RGB conversion.. ");
206 int h0 = j->Hmax / j->Components[0].Hi;
207 int v0 = j->Vmax / j->Components[0].Vi;
208 int h1 = j->Hmax / j->Components[1].Hi;
209 int v1 = j->Vmax / j->Components[1].Vi;
210 int h2 = j->Hmax / j->Components[2].Hi;
211 int v2 = j->Vmax / j->Components[2].Vi;
212
213 int x, y;
214 for (y = 0; y < j->Y; y++)
215 {
216 if (y%ds != 0)
217 continue;
218
219 TCOEF *C0 =
220 j->Components[0].du[j->Components[0].du_width * ((y / v0) / 8)] + 8 * ((y / v0) & 7);
221 TCOEF *C1 =
222 j->Components[1].du[j->Components[1].du_width * ((y / v1) / 8)] + 8 * ((y / v1) & 7);
223 TCOEF *C2 =
224 j->Components[2].du[j->Components[2].du_width * ((y / v2) / 8)] + 8 * ((y / v2) & 7);
225
226 for (x = 0; x < j->X; x++)
227 {
228 if (x%ds != 0)
229 continue;
230
231 TCOEF c0 = C0[(x / h0 / 8) * 64 + ((x / h0) & 7)];
232 TCOEF c1 = C1[(x / h1 / 8) * 64 + ((x / h1) & 7)];
233 TCOEF c2 = C2[(x / h2 / 8) * 64 + ((x / h2) & 7)];
234
235 // ITU BT.601 full-range YUV-to-RGB integer approximation
236 {
237 int y = (c0 << 5) + 16;
238 int u = c1 - 128;
239 int v = c2 - 128;
240
241 int b = CLIP[(y + 57 * u)>>5]; // B;
242 int g = CLIP[(y - 11 * u - 23 * v)>>5]; // G
243 int r = CLIP[(y + 45 * v)>>5]; // R;
244 *bmp++= FB_RGBPACK(r,g,b);
245 }
246 }
247 }
248 printf("done\n");
249 return 0;
250}
251
252const struct image_decoder image_decoder = {
253 false,
254 img_mem,
255 load_image,
256 get_image,
257 draw_image_rect,
258};
259
260IMGDEC_HEADER
diff --git a/apps/plugins/imageviewer/jpegp/jpegp.make b/apps/plugins/imageviewer/jpegp/jpegp.make
new file mode 100644
index 0000000000..8d15af3a68
--- /dev/null
+++ b/apps/plugins/imageviewer/jpegp/jpegp.make
@@ -0,0 +1,32 @@
1# __________ __ ___.
2# Open \______ \ ____ ____ | | _\_ |__ _______ ___
3# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
4# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
5# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
6# \/ \/ \/ \/ \/
7# $Id$
8#
9
10JPEGPSRCDIR := $(IMGVSRCDIR)/jpegp
11JPEGPBUILDDIR := $(IMGVBUILDDIR)/jpegp
12
13JPEGP_SRC := $(call preprocess, $(JPEGPSRCDIR)/SOURCES)
14JPEGP_OBJ := $(call c2obj, $(JPEGP_SRC))
15
16OTHER_SRC += $(JPEGP_SRC)
17
18ROCKS += $(JPEGPBUILDDIR)/jpegp.ovl
19
20$(JPEGPBUILDDIR)/jpegp.refmap: $(JPEGP_OBJ) $(TLSFLIB)
21$(JPEGPBUILDDIR)/jpegp.link: $(PLUGIN_LDS) $(JPEGPBUILDDIR)/jpegp.refmap
22$(JPEGPBUILDDIR)/jpegp.ovl: $(JPEGP_OBJ) $(TLSFLIB)
23
24JPEGPFLAGS = $(IMGDECFLAGS)
25ifndef DEBUG
26JPEGPFLAGS += -Os
27endif
28
29# Compile plugin with extra flags (adapted from ZXBox)
30$(JPEGPBUILDDIR)/%.o: $(JPEGPSRCDIR)/%.c $(JPEGPSRCDIR)/jpegp.make
31 $(SILENT)mkdir -p $(dir $@)
32 $(call PRINTS,CC $(subst $(ROOTDIR)/,,$<))$(CC) -I$(dir $<) $(JPEGPFLAGS) -c $< -o $@
diff --git a/apps/plugins/imageviewer/jpegp/mempool.c b/apps/plugins/imageviewer/jpegp/mempool.c
new file mode 100644
index 0000000000..f777ff230a
--- /dev/null
+++ b/apps/plugins/imageviewer/jpegp/mempool.c
@@ -0,0 +1,50 @@
1#include <inttypes.h>
2#include "plugin.h"
3
4static unsigned char *mem_pool;
5static unsigned char *mem_pool_start;
6static size_t memory_size;
7
8extern void *malloc(size_t size)
9{
10 if (size > memory_size)
11 return NULL;
12
13 memory_size -= size;
14 unsigned char* ptr = mem_pool;
15
16 mem_pool+= size;
17 return ptr;
18}
19
20extern void *calloc(size_t nelem, size_t elem_size)
21{
22 unsigned char* ptr = malloc(nelem*elem_size);
23 if (!ptr)
24 return NULL;
25 rb->memset(ptr, 0, nelem*elem_size);
26 return ptr;
27}
28
29extern void init_mem_pool(const unsigned char *buf, const ssize_t buf_size)
30{
31 //TODO: do we need this alignment? (copied from gif lib)
32 unsigned char *memory_max;
33
34 /* align buffer */
35 mem_pool_start = mem_pool = (unsigned char *)((intptr_t)(buf + 3) & ~3);
36 memory_max = (unsigned char *)((intptr_t)(mem_pool + buf_size) & ~3);
37 memory_size = memory_max - mem_pool;
38}
39
40extern ssize_t freeze_mem_pool(void)
41{
42 mem_pool_start = mem_pool;
43 return memory_size;
44}
45
46extern void clear_mem_pool(void)
47{
48 memory_size += mem_pool - mem_pool_start;
49 mem_pool = mem_pool_start;
50} \ No newline at end of file
diff --git a/apps/plugins/imageviewer/jpegp/mempool.h b/apps/plugins/imageviewer/jpegp/mempool.h
new file mode 100644
index 0000000000..55bbdaf363
--- /dev/null
+++ b/apps/plugins/imageviewer/jpegp/mempool.h
@@ -0,0 +1,7 @@
1#include <inttypes.h>
2
3extern void init_mem_pool(const unsigned char *buf, const ssize_t buf_size);
4extern void *malloc(size_t size);
5extern void *calloc(size_t nelem, size_t elem_size);
6extern ssize_t freeze_mem_pool(void);
7extern void clear_mem_pool(void);
diff --git a/apps/plugins/imageviewer/jpegp/rb_glue.h b/apps/plugins/imageviewer/jpegp/rb_glue.h
new file mode 100644
index 0000000000..ce08483deb
--- /dev/null
+++ b/apps/plugins/imageviewer/jpegp/rb_glue.h
@@ -0,0 +1,35 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * $Id$
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20
21#include "plugin.h"
22#include "mempool.h"
23
24//define from rbunicode.h clashes with jpeg81.h struct
25#undef COMP
26
27#undef memset
28#define memset(a,b,c) rb->memset((a),(b),(c))
29
30#if defined(DEBUG) || defined(SIMULATOR)
31#define printf rb->debugf
32#else
33#undef printf
34#define printf(...)
35#endif \ No newline at end of file
diff --git a/manual/plugins/imageviewer.tex b/manual/plugins/imageviewer.tex
index cc5b27eee4..0676f21a9f 100644
--- a/manual/plugins/imageviewer.tex
+++ b/manual/plugins/imageviewer.tex
@@ -161,7 +161,8 @@ for JPEG images.
161\end{description} 161\end{description}
162 162
163\note{ 163\note{
164Progressive scan and other unusual JPEG files are not supported, and will 164\opt{lcd_color}{Progressive scan is supported. Unsupported JPEG files}
165\nopt{lcd_color}{Progressive scan and other unusual JPEG files are not supported, and} will
165result in various ``unsupported xx'' messages. Processing could also fail if the 166result in various ``unsupported xx'' messages. Processing could also fail if the
166image is too big to decode which will be explained by a respective message. 167image is too big to decode which will be explained by a respective message.
167 168