summaryrefslogtreecommitdiff
path: root/apps/plugins/imageviewer/jpegp/jpegp.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/imageviewer/jpegp/jpegp.c')
-rw-r--r--apps/plugins/imageviewer/jpegp/jpegp.c260
1 files changed, 260 insertions, 0 deletions
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