diff options
author | Dave Chapman <dave@dchapman.com> | 2008-10-21 16:05:46 +0000 |
---|---|---|
committer | Dave Chapman <dave@dchapman.com> | 2008-10-21 16:05:46 +0000 |
commit | 76596deaf1c90f107d43542bf60c9bad1a7ffd68 (patch) | |
tree | ba3a919baa3a3ddd3064f86d98bc220b4daee654 | |
parent | b0b3f0339ab928530ceac34a0d2714b266f8d831 (diff) | |
download | rockbox-76596deaf1c90f107d43542bf60c9bad1a7ffd68.tar.gz rockbox-76596deaf1c90f107d43542bf60c9bad1a7ffd68.zip |
Move the monolithic jpeg viewer into its own subdirectory and split it into three (for now - maybe it should be split further) files - jpeg.c (the main plugin/viewer parts), jpeg_decoder.c (the actual decoder) and. for colour targets only, yuv2rgb.c. The intention of this commit is as a first step towards abstracting this viewer into a reusable jpeg decoder and a multi-format image viewer.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18853 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/plugins/SOURCES | 6 | ||||
-rw-r--r-- | apps/plugins/SUBDIRS | 1 | ||||
-rw-r--r-- | apps/plugins/jpeg.c | 3430 | ||||
-rw-r--r-- | apps/plugins/jpeg/Makefile | 75 | ||||
-rw-r--r-- | apps/plugins/jpeg/SOURCES | 5 | ||||
-rw-r--r-- | apps/plugins/jpeg/jpeg.c | 1235 | ||||
-rw-r--r-- | apps/plugins/jpeg/jpeg.h | 256 | ||||
-rw-r--r-- | apps/plugins/jpeg/jpeg_decoder.c | 1540 | ||||
-rw-r--r-- | apps/plugins/jpeg/jpeg_decoder.h | 142 | ||||
-rw-r--r-- | apps/plugins/jpeg/yuv2rgb.c | 401 | ||||
-rw-r--r-- | apps/plugins/jpeg/yuv2rgb.h | 51 |
11 files changed, 3706 insertions, 3436 deletions
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES index 4bcc144ed8..b1b397d062 100644 --- a/apps/plugins/SOURCES +++ b/apps/plugins/SOURCES | |||
@@ -24,11 +24,6 @@ viewer.c | |||
24 | lamp.c | 24 | lamp.c |
25 | #endif /* HAVE_BACKLIGHT */ | 25 | #endif /* HAVE_BACKLIGHT */ |
26 | 26 | ||
27 | #ifdef OLYMPUS_MROBE_500 | ||
28 | /* remove these once the plugins before it are compileable */ | ||
29 | jpeg.c | ||
30 | #endif | ||
31 | |||
32 | #ifndef OLYMPUS_MROBE_500 | 27 | #ifndef OLYMPUS_MROBE_500 |
33 | 28 | ||
34 | #if (CONFIG_CODEC == SWCODEC) || !defined(SIMULATOR) | 29 | #if (CONFIG_CODEC == SWCODEC) || !defined(SIMULATOR) |
@@ -62,7 +57,6 @@ ppmviewer.c | |||
62 | 57 | ||
63 | /* Plugins needing the grayscale lib on low-depth LCDs */ | 58 | /* Plugins needing the grayscale lib on low-depth LCDs */ |
64 | fire.c | 59 | fire.c |
65 | jpeg.c | ||
66 | mandelbrot.c | 60 | mandelbrot.c |
67 | plasma.c | 61 | plasma.c |
68 | 62 | ||
diff --git a/apps/plugins/SUBDIRS b/apps/plugins/SUBDIRS index 1b3e2af252..22ddcef4cb 100644 --- a/apps/plugins/SUBDIRS +++ b/apps/plugins/SUBDIRS | |||
@@ -17,6 +17,7 @@ rockboy | |||
17 | /* For all targets with a bitmap display */ | 17 | /* For all targets with a bitmap display */ |
18 | #ifdef HAVE_LCD_BITMAP | 18 | #ifdef HAVE_LCD_BITMAP |
19 | chessbox | 19 | chessbox |
20 | jpeg | ||
20 | sudoku | 21 | sudoku |
21 | reversi | 22 | reversi |
22 | #ifndef OLYMPUS_MROBE_500 | 23 | #ifndef OLYMPUS_MROBE_500 |
diff --git a/apps/plugins/jpeg.c b/apps/plugins/jpeg.c deleted file mode 100644 index 397fab7bd6..0000000000 --- a/apps/plugins/jpeg.c +++ /dev/null | |||
@@ -1,3430 +0,0 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * JPEG image viewer | ||
11 | * (This is a real mess if it has to be coded in one single C file) | ||
12 | * | ||
13 | * File scrolling addition (C) 2005 Alexander Spyridakis | ||
14 | * Copyright (C) 2004 Jörg Hohensohn aka [IDC]Dragon | ||
15 | * Heavily borrowed from the IJG implementation (C) Thomas G. Lane | ||
16 | * Small & fast downscaling IDCT (C) 2002 by Guido Vollbeding JPEGclub.org | ||
17 | * | ||
18 | * This program is free software; you can redistribute it and/or | ||
19 | * modify it under the terms of the GNU General Public License | ||
20 | * as published by the Free Software Foundation; either version 2 | ||
21 | * of the License, or (at your option) any later version. | ||
22 | * | ||
23 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
24 | * KIND, either express or implied. | ||
25 | * | ||
26 | ****************************************************************************/ | ||
27 | |||
28 | #include "plugin.h" | ||
29 | #include "playback_control.h" | ||
30 | #include "oldmenuapi.h" | ||
31 | #include "helper.h" | ||
32 | #include "lib/configfile.h" | ||
33 | |||
34 | #ifdef HAVE_LCD_BITMAP | ||
35 | #include "grey.h" | ||
36 | #include "xlcd.h" | ||
37 | |||
38 | PLUGIN_HEADER | ||
39 | |||
40 | /* variable button definitions */ | ||
41 | #if CONFIG_KEYPAD == RECORDER_PAD | ||
42 | #define JPEG_ZOOM_IN BUTTON_PLAY | ||
43 | #define JPEG_ZOOM_OUT BUTTON_ON | ||
44 | #define JPEG_UP BUTTON_UP | ||
45 | #define JPEG_DOWN BUTTON_DOWN | ||
46 | #define JPEG_LEFT BUTTON_LEFT | ||
47 | #define JPEG_RIGHT BUTTON_RIGHT | ||
48 | #define JPEG_NEXT BUTTON_F3 | ||
49 | #define JPEG_PREVIOUS BUTTON_F2 | ||
50 | #define JPEG_MENU BUTTON_OFF | ||
51 | |||
52 | #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD | ||
53 | #define JPEG_ZOOM_IN BUTTON_SELECT | ||
54 | #define JPEG_ZOOM_OUT BUTTON_ON | ||
55 | #define JPEG_UP BUTTON_UP | ||
56 | #define JPEG_DOWN BUTTON_DOWN | ||
57 | #define JPEG_LEFT BUTTON_LEFT | ||
58 | #define JPEG_RIGHT BUTTON_RIGHT | ||
59 | #define JPEG_NEXT BUTTON_F3 | ||
60 | #define JPEG_PREVIOUS BUTTON_F2 | ||
61 | #define JPEG_MENU BUTTON_OFF | ||
62 | |||
63 | #elif CONFIG_KEYPAD == ONDIO_PAD | ||
64 | #define JPEG_ZOOM_PRE BUTTON_MENU | ||
65 | #define JPEG_ZOOM_IN (BUTTON_MENU | BUTTON_REL) | ||
66 | #define JPEG_ZOOM_OUT (BUTTON_MENU | BUTTON_DOWN) | ||
67 | #define JPEG_UP BUTTON_UP | ||
68 | #define JPEG_DOWN BUTTON_DOWN | ||
69 | #define JPEG_LEFT BUTTON_LEFT | ||
70 | #define JPEG_RIGHT BUTTON_RIGHT | ||
71 | #define JPEG_NEXT (BUTTON_MENU | BUTTON_RIGHT) | ||
72 | #define JPEG_PREVIOUS (BUTTON_MENU | BUTTON_LEFT) | ||
73 | #define JPEG_MENU BUTTON_OFF | ||
74 | |||
75 | #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ | ||
76 | (CONFIG_KEYPAD == IRIVER_H300_PAD) | ||
77 | #define JPEG_ZOOM_IN BUTTON_SELECT | ||
78 | #define JPEG_ZOOM_OUT BUTTON_MODE | ||
79 | #define JPEG_UP BUTTON_UP | ||
80 | #define JPEG_DOWN BUTTON_DOWN | ||
81 | #define JPEG_LEFT BUTTON_LEFT | ||
82 | #define JPEG_RIGHT BUTTON_RIGHT | ||
83 | #if (CONFIG_KEYPAD == IRIVER_H100_PAD) | ||
84 | #define JPEG_NEXT BUTTON_ON | ||
85 | #define JPEG_PREVIOUS BUTTON_REC | ||
86 | #else | ||
87 | #define JPEG_NEXT BUTTON_REC | ||
88 | #define JPEG_PREVIOUS BUTTON_ON | ||
89 | #endif | ||
90 | #define JPEG_MENU BUTTON_OFF | ||
91 | #define JPEG_RC_MENU BUTTON_RC_STOP | ||
92 | |||
93 | #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \ | ||
94 | (CONFIG_KEYPAD == IPOD_1G2G_PAD) | ||
95 | #define JPEG_ZOOM_IN BUTTON_SCROLL_FWD | ||
96 | #define JPEG_ZOOM_OUT BUTTON_SCROLL_BACK | ||
97 | #define JPEG_UP BUTTON_MENU | ||
98 | #define JPEG_DOWN BUTTON_PLAY | ||
99 | #define JPEG_LEFT BUTTON_LEFT | ||
100 | #define JPEG_RIGHT BUTTON_RIGHT | ||
101 | #define JPEG_MENU (BUTTON_SELECT | BUTTON_MENU) | ||
102 | #define JPEG_NEXT (BUTTON_SELECT | BUTTON_RIGHT) | ||
103 | #define JPEG_PREVIOUS (BUTTON_SELECT | BUTTON_LEFT) | ||
104 | |||
105 | #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD | ||
106 | #define JPEG_ZOOM_PRE BUTTON_SELECT | ||
107 | #define JPEG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) | ||
108 | #define JPEG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) | ||
109 | #define JPEG_UP BUTTON_UP | ||
110 | #define JPEG_DOWN BUTTON_DOWN | ||
111 | #define JPEG_LEFT BUTTON_LEFT | ||
112 | #define JPEG_RIGHT BUTTON_RIGHT | ||
113 | #define JPEG_MENU BUTTON_POWER | ||
114 | #define JPEG_NEXT BUTTON_PLAY | ||
115 | #define JPEG_PREVIOUS BUTTON_REC | ||
116 | |||
117 | #elif CONFIG_KEYPAD == GIGABEAT_PAD | ||
118 | #define JPEG_ZOOM_IN BUTTON_VOL_UP | ||
119 | #define JPEG_ZOOM_OUT BUTTON_VOL_DOWN | ||
120 | #define JPEG_UP BUTTON_UP | ||
121 | #define JPEG_DOWN BUTTON_DOWN | ||
122 | #define JPEG_LEFT BUTTON_LEFT | ||
123 | #define JPEG_RIGHT BUTTON_RIGHT | ||
124 | #define JPEG_MENU BUTTON_MENU | ||
125 | #define JPEG_NEXT (BUTTON_A | BUTTON_RIGHT) | ||
126 | #define JPEG_PREVIOUS (BUTTON_A | BUTTON_LEFT) | ||
127 | |||
128 | #elif CONFIG_KEYPAD == SANSA_E200_PAD | ||
129 | #define JPEG_ZOOM_PRE BUTTON_SELECT | ||
130 | #define JPEG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) | ||
131 | #define JPEG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) | ||
132 | #define JPEG_UP BUTTON_UP | ||
133 | #define JPEG_DOWN BUTTON_DOWN | ||
134 | #define JPEG_LEFT BUTTON_LEFT | ||
135 | #define JPEG_RIGHT BUTTON_RIGHT | ||
136 | #define JPEG_MENU BUTTON_POWER | ||
137 | #define JPEG_SLIDE_SHOW BUTTON_REC | ||
138 | #define JPEG_NEXT BUTTON_SCROLL_FWD | ||
139 | #define JPEG_NEXT_REPEAT (BUTTON_SCROLL_FWD|BUTTON_REPEAT) | ||
140 | #define JPEG_PREVIOUS BUTTON_SCROLL_BACK | ||
141 | #define JPEG_PREVIOUS_REPEAT (BUTTON_SCROLL_BACK|BUTTON_REPEAT) | ||
142 | |||
143 | #elif CONFIG_KEYPAD == SANSA_C200_PAD | ||
144 | #define JPEG_ZOOM_PRE BUTTON_SELECT | ||
145 | #define JPEG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) | ||
146 | #define JPEG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) | ||
147 | #define JPEG_UP BUTTON_UP | ||
148 | #define JPEG_DOWN BUTTON_DOWN | ||
149 | #define JPEG_LEFT BUTTON_LEFT | ||
150 | #define JPEG_RIGHT BUTTON_RIGHT | ||
151 | #define JPEG_MENU BUTTON_POWER | ||
152 | #define JPEG_SLIDE_SHOW BUTTON_REC | ||
153 | #define JPEG_NEXT BUTTON_VOL_UP | ||
154 | #define JPEG_NEXT_REPEAT (BUTTON_VOL_UP|BUTTON_REPEAT) | ||
155 | #define JPEG_PREVIOUS BUTTON_VOL_DOWN | ||
156 | #define JPEG_PREVIOUS_REPEAT (BUTTON_VOL_DOWN|BUTTON_REPEAT) | ||
157 | |||
158 | #elif CONFIG_KEYPAD == IRIVER_H10_PAD | ||
159 | #define JPEG_ZOOM_PRE BUTTON_PLAY | ||
160 | #define JPEG_ZOOM_IN (BUTTON_PLAY | BUTTON_REL) | ||
161 | #define JPEG_ZOOM_OUT (BUTTON_PLAY | BUTTON_REPEAT) | ||
162 | #define JPEG_UP BUTTON_SCROLL_UP | ||
163 | #define JPEG_DOWN BUTTON_SCROLL_DOWN | ||
164 | #define JPEG_LEFT BUTTON_LEFT | ||
165 | #define JPEG_RIGHT BUTTON_RIGHT | ||
166 | #define JPEG_MENU BUTTON_POWER | ||
167 | #define JPEG_NEXT BUTTON_FF | ||
168 | #define JPEG_PREVIOUS BUTTON_REW | ||
169 | |||
170 | #elif CONFIG_KEYPAD == MROBE500_PAD | ||
171 | #define JPEG_ZOOM_IN BUTTON_RC_VOL_UP | ||
172 | #define JPEG_ZOOM_OUT BUTTON_RC_VOL_DOWN | ||
173 | #define JPEG_UP BUTTON_RC_PLAY | ||
174 | #define JPEG_DOWN BUTTON_RC_DOWN | ||
175 | #define JPEG_LEFT BUTTON_LEFT | ||
176 | #define JPEG_RIGHT BUTTON_RIGHT | ||
177 | #define JPEG_MENU BUTTON_POWER | ||
178 | #define JPEG_NEXT BUTTON_RC_HEART | ||
179 | #define JPEG_PREVIOUS BUTTON_RC_MODE | ||
180 | |||
181 | #elif CONFIG_KEYPAD == GIGABEAT_S_PAD | ||
182 | #define JPEG_ZOOM_IN BUTTON_VOL_UP | ||
183 | #define JPEG_ZOOM_OUT BUTTON_VOL_DOWN | ||
184 | #define JPEG_UP BUTTON_UP | ||
185 | #define JPEG_DOWN BUTTON_DOWN | ||
186 | #define JPEG_LEFT BUTTON_LEFT | ||
187 | #define JPEG_RIGHT BUTTON_RIGHT | ||
188 | #define JPEG_MENU BUTTON_MENU | ||
189 | #define JPEG_NEXT BUTTON_NEXT | ||
190 | #define JPEG_PREVIOUS BUTTON_PREV | ||
191 | |||
192 | #elif CONFIG_KEYPAD == MROBE100_PAD | ||
193 | #define JPEG_ZOOM_IN BUTTON_SELECT | ||
194 | #define JPEG_ZOOM_OUT BUTTON_PLAY | ||
195 | #define JPEG_UP BUTTON_UP | ||
196 | #define JPEG_DOWN BUTTON_DOWN | ||
197 | #define JPEG_LEFT BUTTON_LEFT | ||
198 | #define JPEG_RIGHT BUTTON_RIGHT | ||
199 | #define JPEG_MENU BUTTON_MENU | ||
200 | #define JPEG_NEXT (BUTTON_DISPLAY | BUTTON_RIGHT) | ||
201 | #define JPEG_PREVIOUS (BUTTON_DISPLAY | BUTTON_LEFT) | ||
202 | |||
203 | #elif CONFIG_KEYPAD == IAUDIO_M3_PAD | ||
204 | #define JPEG_ZOOM_PRE BUTTON_RC_PLAY | ||
205 | #define JPEG_ZOOM_IN (BUTTON_RC_PLAY|BUTTON_REL) | ||
206 | #define JPEG_ZOOM_OUT (BUTTON_RC_PLAY|BUTTON_REPEAT) | ||
207 | #define JPEG_UP BUTTON_RC_VOL_UP | ||
208 | #define JPEG_DOWN BUTTON_RC_VOL_DOWN | ||
209 | #define JPEG_LEFT BUTTON_RC_REW | ||
210 | #define JPEG_RIGHT BUTTON_RC_FF | ||
211 | #define JPEG_MENU BUTTON_RC_REC | ||
212 | #define JPEG_NEXT BUTTON_RC_MODE | ||
213 | #define JPEG_PREVIOUS BUTTON_RC_MENU | ||
214 | |||
215 | #elif CONFIG_KEYPAD == COWOND2_PAD | ||
216 | |||
217 | #elif CONFIG_KEYPAD == IAUDIO67_PAD | ||
218 | #define JPEG_ZOOM_IN BUTTON_VOLUP | ||
219 | #define JPEG_ZOOM_OUT BUTTON_VOLDOWN | ||
220 | #define JPEG_UP BUTTON_STOP | ||
221 | #define JPEG_DOWN BUTTON_PLAY | ||
222 | #define JPEG_LEFT BUTTON_LEFT | ||
223 | #define JPEG_RIGHT BUTTON_RIGHT | ||
224 | #define JPEG_MENU BUTTON_MENU | ||
225 | #define JPEG_NEXT (BUTTON_PLAY|BUTTON_VOLUP) | ||
226 | #define JPEG_PREVIOUS (BUTTON_PLAY|BUTTON_VOLDOWN) | ||
227 | |||
228 | #else | ||
229 | #error No keymap defined! | ||
230 | #endif | ||
231 | |||
232 | #ifdef HAVE_TOUCHSCREEN | ||
233 | #ifndef JPEG_UP | ||
234 | #define JPEG_UP BUTTON_TOPMIDDLE | ||
235 | #endif | ||
236 | #ifndef JPEG_DOWN | ||
237 | #define JPEG_DOWN BUTTON_BOTTOMMIDDLE | ||
238 | #endif | ||
239 | #ifndef JPEG_LEFT | ||
240 | #define JPEG_LEFT BUTTON_MIDLEFT | ||
241 | #endif | ||
242 | #ifndef JPEG_RIGHT | ||
243 | #define JPEG_RIGHT BUTTON_MIDRIGHT | ||
244 | #endif | ||
245 | #ifndef JPEG_ZOOM_IN | ||
246 | #define JPEG_ZOOM_IN BUTTON_TOPRIGHT | ||
247 | #endif | ||
248 | #ifndef JPEG_ZOOM_OUT | ||
249 | #define JPEG_ZOOM_OUT BUTTON_TOPLEFT | ||
250 | #endif | ||
251 | #ifndef JPEG_MENU | ||
252 | #define JPEG_MENU (BUTTON_CENTER|BUTTON_REL) | ||
253 | #endif | ||
254 | #ifndef JPEG_NEXT | ||
255 | #define JPEG_NEXT BUTTON_BOTTOMRIGHT | ||
256 | #endif | ||
257 | #ifndef JPEG_PREVIOUS | ||
258 | #define JPEG_PREVIOUS BUTTON_BOTTOMLEFT | ||
259 | #endif | ||
260 | #endif | ||
261 | |||
262 | /* different graphics libraries */ | ||
263 | #if LCD_DEPTH < 8 | ||
264 | #define USEGSLIB | ||
265 | GREY_INFO_STRUCT | ||
266 | #define MYLCD(fn) grey_ub_ ## fn | ||
267 | #define MYLCD_UPDATE() | ||
268 | #define MYXLCD(fn) grey_ub_ ## fn | ||
269 | #else | ||
270 | #define MYLCD(fn) rb->lcd_ ## fn | ||
271 | #define MYLCD_UPDATE() rb->lcd_update(); | ||
272 | #define MYXLCD(fn) xlcd_ ## fn | ||
273 | #endif | ||
274 | |||
275 | #define MAX_X_SIZE LCD_WIDTH*8 | ||
276 | |||
277 | /* Min memory allowing us to use the plugin buffer | ||
278 | * and thus not stopping the music | ||
279 | * *Very* rough estimation: | ||
280 | * Max 10 000 dir entries * 4bytes/entry (char **) = 40000 bytes | ||
281 | * + 20k code size = 60 000 | ||
282 | * + 50k min for jpeg = 120 000 | ||
283 | */ | ||
284 | #define MIN_MEM 120000 | ||
285 | |||
286 | /* Headings */ | ||
287 | #define DIR_PREV 1 | ||
288 | #define DIR_NEXT -1 | ||
289 | #define DIR_NONE 0 | ||
290 | |||
291 | #define PLUGIN_OTHER 10 /* State code for output with return. */ | ||
292 | |||
293 | /******************************* Globals ***********************************/ | ||
294 | |||
295 | static const struct plugin_api* rb; | ||
296 | MEM_FUNCTION_WRAPPERS(rb); | ||
297 | |||
298 | /* for portability of below JPEG code */ | ||
299 | #define MEMSET(p,v,c) rb->memset(p,v,c) | ||
300 | #define MEMCPY(d,s,c) rb->memcpy(d,s,c) | ||
301 | #define INLINE static inline | ||
302 | #define ENDIAN_SWAP16(n) n /* only for poor little endian machines */ | ||
303 | |||
304 | static int slideshow_enabled = false; /* run slideshow */ | ||
305 | static int running_slideshow = false; /* loading image because of slideshw */ | ||
306 | #ifndef SIMULATOR | ||
307 | static int immediate_ata_off = false; /* power down disk after loading */ | ||
308 | #endif | ||
309 | |||
310 | /* Persistent configuration */ | ||
311 | #define JPEG_CONFIGFILE "jpeg.cfg" | ||
312 | #define JPEG_SETTINGS_MINVERSION 1 | ||
313 | #define JPEG_SETTINGS_VERSION 2 | ||
314 | |||
315 | /* Slideshow times */ | ||
316 | #define SS_MIN_TIMEOUT 1 | ||
317 | #define SS_MAX_TIMEOUT 20 | ||
318 | #define SS_DEFAULT_TIMEOUT 5 | ||
319 | |||
320 | enum color_modes | ||
321 | { | ||
322 | COLOURMODE_COLOUR = 0, | ||
323 | COLOURMODE_GRAY, | ||
324 | COLOUR_NUM_MODES | ||
325 | }; | ||
326 | |||
327 | enum dither_modes | ||
328 | { | ||
329 | DITHER_NONE = 0, /* No dithering */ | ||
330 | DITHER_ORDERED, /* Bayer ordered */ | ||
331 | DITHER_DIFFUSION, /* Floyd/Steinberg error diffusion */ | ||
332 | DITHER_NUM_MODES | ||
333 | }; | ||
334 | |||
335 | struct jpeg_settings | ||
336 | { | ||
337 | int colour_mode; | ||
338 | int dither_mode; | ||
339 | int ss_timeout; | ||
340 | }; | ||
341 | |||
342 | static struct jpeg_settings jpeg_settings = | ||
343 | { COLOURMODE_COLOUR, DITHER_NONE, SS_DEFAULT_TIMEOUT }; | ||
344 | static struct jpeg_settings old_settings; | ||
345 | |||
346 | static struct configdata jpeg_config[] = | ||
347 | { | ||
348 | #ifdef HAVE_LCD_COLOR | ||
349 | { TYPE_ENUM, 0, COLOUR_NUM_MODES, &jpeg_settings.colour_mode, | ||
350 | "Colour Mode", (char *[]){ "Colour", "Grayscale" }, NULL }, | ||
351 | { TYPE_ENUM, 0, DITHER_NUM_MODES, &jpeg_settings.dither_mode, | ||
352 | "Dither Mode", (char *[]){ "None", "Ordered", "Diffusion" }, NULL }, | ||
353 | #endif | ||
354 | { TYPE_INT, SS_MIN_TIMEOUT, SS_MAX_TIMEOUT, &jpeg_settings.ss_timeout, | ||
355 | "Slideshow Time", NULL, NULL}, | ||
356 | }; | ||
357 | |||
358 | #if LCD_DEPTH > 1 | ||
359 | fb_data* old_backdrop; | ||
360 | #endif | ||
361 | |||
362 | /**************** begin JPEG code ********************/ | ||
363 | |||
364 | INLINE unsigned range_limit(int value) | ||
365 | { | ||
366 | #if CONFIG_CPU == SH7034 | ||
367 | unsigned tmp; | ||
368 | asm ( /* Note: Uses knowledge that only low byte of result is used */ | ||
369 | "mov #-128,%[t] \n" | ||
370 | "sub %[t],%[v] \n" /* value -= -128; equals value += 128; */ | ||
371 | "extu.b %[v],%[t] \n" | ||
372 | "cmp/eq %[v],%[t] \n" /* low byte == whole number ? */ | ||
373 | "bt 1f \n" /* yes: no overflow */ | ||
374 | "cmp/pz %[v] \n" /* overflow: positive? */ | ||
375 | "subc %[v],%[v] \n" /* %[r] now either 0 or 0xffffffff */ | ||
376 | "1: \n" | ||
377 | : /* outputs */ | ||
378 | [v]"+r"(value), | ||
379 | [t]"=&r"(tmp) | ||
380 | ); | ||
381 | return value; | ||
382 | #elif defined(CPU_COLDFIRE) | ||
383 | asm ( /* Note: Uses knowledge that only the low byte of the result is used */ | ||
384 | "add.l #128,%[v] \n" /* value += 128; */ | ||
385 | "cmp.l #255,%[v] \n" /* overflow? */ | ||
386 | "bls.b 1f \n" /* no: return value */ | ||
387 | "spl.b %[v] \n" /* yes: set low byte to appropriate boundary */ | ||
388 | "1: \n" | ||
389 | : /* outputs */ | ||
390 | [v]"+d"(value) | ||
391 | ); | ||
392 | return value; | ||
393 | #elif defined(CPU_ARM) | ||
394 | asm ( /* Note: Uses knowledge that only the low byte of the result is used */ | ||
395 | "add %[v], %[v], #128 \n" /* value += 128 */ | ||
396 | "cmp %[v], #255 \n" /* out of range 0..255? */ | ||
397 | "mvnhi %[v], %[v], asr #31 \n" /* yes: set all bits to ~(sign_bit) */ | ||
398 | : /* outputs */ | ||
399 | [v]"+r"(value) | ||
400 | ); | ||
401 | return value; | ||
402 | #else | ||
403 | value += 128; | ||
404 | |||
405 | if ((unsigned)value <= 255) | ||
406 | return value; | ||
407 | |||
408 | if (value < 0) | ||
409 | return 0; | ||
410 | |||
411 | return 255; | ||
412 | #endif | ||
413 | } | ||
414 | |||
415 | /* IDCT implementation */ | ||
416 | |||
417 | |||
418 | #define CONST_BITS 13 | ||
419 | #define PASS1_BITS 2 | ||
420 | |||
421 | |||
422 | /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus | ||
423 | * causing a lot of useless floating-point operations at run time. | ||
424 | * To get around this we use the following pre-calculated constants. | ||
425 | * If you change CONST_BITS you may want to add appropriate values. | ||
426 | * (With a reasonable C compiler, you can just rely on the FIX() macro...) | ||
427 | */ | ||
428 | #define FIX_0_298631336 2446 /* FIX(0.298631336) */ | ||
429 | #define FIX_0_390180644 3196 /* FIX(0.390180644) */ | ||
430 | #define FIX_0_541196100 4433 /* FIX(0.541196100) */ | ||
431 | #define FIX_0_765366865 6270 /* FIX(0.765366865) */ | ||
432 | #define FIX_0_899976223 7373 /* FIX(0.899976223) */ | ||
433 | #define FIX_1_175875602 9633 /* FIX(1.175875602) */ | ||
434 | #define FIX_1_501321110 12299 /* FIX(1.501321110) */ | ||
435 | #define FIX_1_847759065 15137 /* FIX(1.847759065) */ | ||
436 | #define FIX_1_961570560 16069 /* FIX(1.961570560) */ | ||
437 | #define FIX_2_053119869 16819 /* FIX(2.053119869) */ | ||
438 | #define FIX_2_562915447 20995 /* FIX(2.562915447) */ | ||
439 | #define FIX_3_072711026 25172 /* FIX(3.072711026) */ | ||
440 | |||
441 | |||
442 | |||
443 | /* Multiply an long variable by an long constant to yield an long result. | ||
444 | * For 8-bit samples with the recommended scaling, all the variable | ||
445 | * and constant values involved are no more than 16 bits wide, so a | ||
446 | * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. | ||
447 | * For 12-bit samples, a full 32-bit multiplication will be needed. | ||
448 | */ | ||
449 | #define MULTIPLY16(var,const) (((short) (var)) * ((short) (const))) | ||
450 | |||
451 | |||
452 | /* Dequantize a coefficient by multiplying it by the multiplier-table | ||
453 | * entry; produce an int result. In this module, both inputs and result | ||
454 | * are 16 bits or less, so either int or short multiply will work. | ||
455 | */ | ||
456 | /* #define DEQUANTIZE(coef,quantval) (((int) (coef)) * (quantval)) */ | ||
457 | #define DEQUANTIZE MULTIPLY16 | ||
458 | |||
459 | /* Descale and correctly round an int value that's scaled by N bits. | ||
460 | * We assume RIGHT_SHIFT rounds towards minus infinity, so adding | ||
461 | * the fudge factor is correct for either sign of X. | ||
462 | */ | ||
463 | #define DESCALE(x,n) (((x) + (1l << ((n)-1))) >> (n)) | ||
464 | |||
465 | |||
466 | |||
467 | /* | ||
468 | * Perform dequantization and inverse DCT on one block of coefficients, | ||
469 | * producing a reduced-size 1x1 output block. | ||
470 | */ | ||
471 | void idct1x1(unsigned char* p_byte, int* inptr, int* quantptr, int skip_line) | ||
472 | { | ||
473 | (void)skip_line; /* unused */ | ||
474 | *p_byte = range_limit(inptr[0] * quantptr[0] >> 3); | ||
475 | } | ||
476 | |||
477 | |||
478 | |||
479 | /* | ||
480 | * Perform dequantization and inverse DCT on one block of coefficients, | ||
481 | * producing a reduced-size 2x2 output block. | ||
482 | */ | ||
483 | void idct2x2(unsigned char* p_byte, int* inptr, int* quantptr, int skip_line) | ||
484 | { | ||
485 | int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; | ||
486 | unsigned char* outptr; | ||
487 | |||
488 | /* Pass 1: process columns from input, store into work array. */ | ||
489 | |||
490 | /* Column 0 */ | ||
491 | tmp4 = DEQUANTIZE(inptr[8*0], quantptr[8*0]); | ||
492 | tmp5 = DEQUANTIZE(inptr[8*1], quantptr[8*1]); | ||
493 | |||
494 | tmp0 = tmp4 + tmp5; | ||
495 | tmp2 = tmp4 - tmp5; | ||
496 | |||
497 | /* Column 1 */ | ||
498 | tmp4 = DEQUANTIZE(inptr[8*0+1], quantptr[8*0+1]); | ||
499 | tmp5 = DEQUANTIZE(inptr[8*1+1], quantptr[8*1+1]); | ||
500 | |||
501 | tmp1 = tmp4 + tmp5; | ||
502 | tmp3 = tmp4 - tmp5; | ||
503 | |||
504 | /* Pass 2: process 2 rows, store into output array. */ | ||
505 | |||
506 | /* Row 0 */ | ||
507 | outptr = p_byte; | ||
508 | |||
509 | outptr[0] = range_limit((int) DESCALE(tmp0 + tmp1, 3)); | ||
510 | outptr[1] = range_limit((int) DESCALE(tmp0 - tmp1, 3)); | ||
511 | |||
512 | /* Row 1 */ | ||
513 | outptr = p_byte + skip_line; | ||
514 | |||
515 | outptr[0] = range_limit((int) DESCALE(tmp2 + tmp3, 3)); | ||
516 | outptr[1] = range_limit((int) DESCALE(tmp2 - tmp3, 3)); | ||
517 | } | ||
518 | |||
519 | |||
520 | |||
521 | /* | ||
522 | * Perform dequantization and inverse DCT on one block of coefficients, | ||
523 | * producing a reduced-size 4x4 output block. | ||
524 | */ | ||
525 | void idct4x4(unsigned char* p_byte, int* inptr, int* quantptr, int skip_line) | ||
526 | { | ||
527 | int tmp0, tmp2, tmp10, tmp12; | ||
528 | int z1, z2, z3; | ||
529 | int * wsptr; | ||
530 | unsigned char* outptr; | ||
531 | int ctr; | ||
532 | int workspace[4*4]; /* buffers data between passes */ | ||
533 | |||
534 | /* Pass 1: process columns from input, store into work array. */ | ||
535 | |||
536 | wsptr = workspace; | ||
537 | for (ctr = 0; ctr < 4; ctr++, inptr++, quantptr++, wsptr++) | ||
538 | { | ||
539 | /* Even part */ | ||
540 | |||
541 | tmp0 = DEQUANTIZE(inptr[8*0], quantptr[8*0]); | ||
542 | tmp2 = DEQUANTIZE(inptr[8*2], quantptr[8*2]); | ||
543 | |||
544 | tmp10 = (tmp0 + tmp2) << PASS1_BITS; | ||
545 | tmp12 = (tmp0 - tmp2) << PASS1_BITS; | ||
546 | |||
547 | /* Odd part */ | ||
548 | /* Same rotation as in the even part of the 8x8 LL&M IDCT */ | ||
549 | |||
550 | z2 = DEQUANTIZE(inptr[8*1], quantptr[8*1]); | ||
551 | z3 = DEQUANTIZE(inptr[8*3], quantptr[8*3]); | ||
552 | |||
553 | z1 = MULTIPLY16(z2 + z3, FIX_0_541196100); | ||
554 | tmp0 = DESCALE(z1 + MULTIPLY16(z3, - FIX_1_847759065), CONST_BITS-PASS1_BITS); | ||
555 | tmp2 = DESCALE(z1 + MULTIPLY16(z2, FIX_0_765366865), CONST_BITS-PASS1_BITS); | ||
556 | |||
557 | /* Final output stage */ | ||
558 | |||
559 | wsptr[4*0] = (int) (tmp10 + tmp2); | ||
560 | wsptr[4*3] = (int) (tmp10 - tmp2); | ||
561 | wsptr[4*1] = (int) (tmp12 + tmp0); | ||
562 | wsptr[4*2] = (int) (tmp12 - tmp0); | ||
563 | } | ||
564 | |||
565 | /* Pass 2: process 4 rows from work array, store into output array. */ | ||
566 | |||
567 | wsptr = workspace; | ||
568 | for (ctr = 0; ctr < 4; ctr++) | ||
569 | { | ||
570 | outptr = p_byte + (ctr*skip_line); | ||
571 | /* Even part */ | ||
572 | |||
573 | tmp0 = (int) wsptr[0]; | ||
574 | tmp2 = (int) wsptr[2]; | ||
575 | |||
576 | tmp10 = (tmp0 + tmp2) << CONST_BITS; | ||
577 | tmp12 = (tmp0 - tmp2) << CONST_BITS; | ||
578 | |||
579 | /* Odd part */ | ||
580 | /* Same rotation as in the even part of the 8x8 LL&M IDCT */ | ||
581 | |||
582 | z2 = (int) wsptr[1]; | ||
583 | z3 = (int) wsptr[3]; | ||
584 | |||
585 | z1 = MULTIPLY16(z2 + z3, FIX_0_541196100); | ||
586 | tmp0 = z1 + MULTIPLY16(z3, - FIX_1_847759065); | ||
587 | tmp2 = z1 + MULTIPLY16(z2, FIX_0_765366865); | ||
588 | |||
589 | /* Final output stage */ | ||
590 | |||
591 | outptr[0] = range_limit((int) DESCALE(tmp10 + tmp2, | ||
592 | CONST_BITS+PASS1_BITS+3)); | ||
593 | outptr[3] = range_limit((int) DESCALE(tmp10 - tmp2, | ||
594 | CONST_BITS+PASS1_BITS+3)); | ||
595 | outptr[1] = range_limit((int) DESCALE(tmp12 + tmp0, | ||
596 | CONST_BITS+PASS1_BITS+3)); | ||
597 | outptr[2] = range_limit((int) DESCALE(tmp12 - tmp0, | ||
598 | CONST_BITS+PASS1_BITS+3)); | ||
599 | |||
600 | wsptr += 4; /* advance pointer to next row */ | ||
601 | } | ||
602 | } | ||
603 | |||
604 | |||
605 | |||
606 | /* | ||
607 | * Perform dequantization and inverse DCT on one block of coefficients. | ||
608 | */ | ||
609 | void idct8x8(unsigned char* p_byte, int* inptr, int* quantptr, int skip_line) | ||
610 | { | ||
611 | long tmp0, tmp1, tmp2, tmp3; | ||
612 | long tmp10, tmp11, tmp12, tmp13; | ||
613 | long z1, z2, z3, z4, z5; | ||
614 | int * wsptr; | ||
615 | unsigned char* outptr; | ||
616 | int ctr; | ||
617 | int workspace[64]; /* buffers data between passes */ | ||
618 | |||
619 | /* Pass 1: process columns from input, store into work array. */ | ||
620 | /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ | ||
621 | /* furthermore, we scale the results by 2**PASS1_BITS. */ | ||
622 | |||
623 | wsptr = workspace; | ||
624 | for (ctr = 8; ctr > 0; ctr--) | ||
625 | { | ||
626 | /* Due to quantization, we will usually find that many of the input | ||
627 | * coefficients are zero, especially the AC terms. We can exploit this | ||
628 | * by short-circuiting the IDCT calculation for any column in which all | ||
629 | * the AC terms are zero. In that case each output is equal to the | ||
630 | * DC coefficient (with scale factor as needed). | ||
631 | * With typical images and quantization tables, half or more of the | ||
632 | * column DCT calculations can be simplified this way. | ||
633 | */ | ||
634 | |||
635 | if ((inptr[8*1] | inptr[8*2] | inptr[8*3] | ||
636 | | inptr[8*4] | inptr[8*5] | inptr[8*6] | inptr[8*7]) == 0) | ||
637 | { | ||
638 | /* AC terms all zero */ | ||
639 | int dcval = DEQUANTIZE(inptr[8*0], quantptr[8*0]) << PASS1_BITS; | ||
640 | |||
641 | wsptr[8*0] = wsptr[8*1] = wsptr[8*2] = wsptr[8*3] = wsptr[8*4] | ||
642 | = wsptr[8*5] = wsptr[8*6] = wsptr[8*7] = dcval; | ||
643 | inptr++; /* advance pointers to next column */ | ||
644 | quantptr++; | ||
645 | wsptr++; | ||
646 | continue; | ||
647 | } | ||
648 | |||
649 | /* Even part: reverse the even part of the forward DCT. */ | ||
650 | /* The rotator is sqrt(2)*c(-6). */ | ||
651 | |||
652 | z2 = DEQUANTIZE(inptr[8*2], quantptr[8*2]); | ||
653 | z3 = DEQUANTIZE(inptr[8*6], quantptr[8*6]); | ||
654 | |||
655 | z1 = MULTIPLY16(z2 + z3, FIX_0_541196100); | ||
656 | tmp2 = z1 + MULTIPLY16(z3, - FIX_1_847759065); | ||
657 | tmp3 = z1 + MULTIPLY16(z2, FIX_0_765366865); | ||
658 | |||
659 | z2 = DEQUANTIZE(inptr[8*0], quantptr[8*0]); | ||
660 | z3 = DEQUANTIZE(inptr[8*4], quantptr[8*4]); | ||
661 | |||
662 | tmp0 = (z2 + z3) << CONST_BITS; | ||
663 | tmp1 = (z2 - z3) << CONST_BITS; | ||
664 | |||
665 | tmp10 = tmp0 + tmp3; | ||
666 | tmp13 = tmp0 - tmp3; | ||
667 | tmp11 = tmp1 + tmp2; | ||
668 | tmp12 = tmp1 - tmp2; | ||
669 | |||
670 | /* Odd part per figure 8; the matrix is unitary and hence its | ||
671 | transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */ | ||
672 | |||
673 | tmp0 = DEQUANTIZE(inptr[8*7], quantptr[8*7]); | ||
674 | tmp1 = DEQUANTIZE(inptr[8*5], quantptr[8*5]); | ||
675 | tmp2 = DEQUANTIZE(inptr[8*3], quantptr[8*3]); | ||
676 | tmp3 = DEQUANTIZE(inptr[8*1], quantptr[8*1]); | ||
677 | |||
678 | z1 = tmp0 + tmp3; | ||
679 | z2 = tmp1 + tmp2; | ||
680 | z3 = tmp0 + tmp2; | ||
681 | z4 = tmp1 + tmp3; | ||
682 | z5 = MULTIPLY16(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ | ||
683 | |||
684 | tmp0 = MULTIPLY16(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ | ||
685 | tmp1 = MULTIPLY16(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ | ||
686 | tmp2 = MULTIPLY16(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ | ||
687 | tmp3 = MULTIPLY16(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ | ||
688 | z1 = MULTIPLY16(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ | ||
689 | z2 = MULTIPLY16(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ | ||
690 | z3 = MULTIPLY16(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ | ||
691 | z4 = MULTIPLY16(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ | ||
692 | |||
693 | z3 += z5; | ||
694 | z4 += z5; | ||
695 | |||
696 | tmp0 += z1 + z3; | ||
697 | tmp1 += z2 + z4; | ||
698 | tmp2 += z2 + z3; | ||
699 | tmp3 += z1 + z4; | ||
700 | |||
701 | /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ | ||
702 | |||
703 | wsptr[8*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS); | ||
704 | wsptr[8*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS); | ||
705 | wsptr[8*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS); | ||
706 | wsptr[8*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS); | ||
707 | wsptr[8*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS); | ||
708 | wsptr[8*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS); | ||
709 | wsptr[8*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS); | ||
710 | wsptr[8*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS); | ||
711 | |||
712 | inptr++; /* advance pointers to next column */ | ||
713 | quantptr++; | ||
714 | wsptr++; | ||
715 | } | ||
716 | |||
717 | /* Pass 2: process rows from work array, store into output array. */ | ||
718 | /* Note that we must descale the results by a factor of 8 == 2**3, */ | ||
719 | /* and also undo the PASS1_BITS scaling. */ | ||
720 | |||
721 | wsptr = workspace; | ||
722 | for (ctr = 0; ctr < 8; ctr++) | ||
723 | { | ||
724 | outptr = p_byte + (ctr*skip_line); | ||
725 | /* Rows of zeroes can be exploited in the same way as we did with columns. | ||
726 | * However, the column calculation has created many nonzero AC terms, so | ||
727 | * the simplification applies less often (typically 5% to 10% of the time). | ||
728 | * On machines with very fast multiplication, it's possible that the | ||
729 | * test takes more time than it's worth. In that case this section | ||
730 | * may be commented out. | ||
731 | */ | ||
732 | |||
733 | #ifndef NO_ZERO_ROW_TEST | ||
734 | if ((wsptr[1] | wsptr[2] | wsptr[3] | ||
735 | | wsptr[4] | wsptr[5] | wsptr[6] | wsptr[7]) == 0) | ||
736 | { | ||
737 | /* AC terms all zero */ | ||
738 | unsigned char dcval = range_limit((int) DESCALE((long) wsptr[0], | ||
739 | PASS1_BITS+3)); | ||
740 | |||
741 | outptr[0] = dcval; | ||
742 | outptr[1] = dcval; | ||
743 | outptr[2] = dcval; | ||
744 | outptr[3] = dcval; | ||
745 | outptr[4] = dcval; | ||
746 | outptr[5] = dcval; | ||
747 | outptr[6] = dcval; | ||
748 | outptr[7] = dcval; | ||
749 | |||
750 | wsptr += 8; /* advance pointer to next row */ | ||
751 | continue; | ||
752 | } | ||
753 | #endif | ||
754 | |||
755 | /* Even part: reverse the even part of the forward DCT. */ | ||
756 | /* The rotator is sqrt(2)*c(-6). */ | ||
757 | |||
758 | z2 = (long) wsptr[2]; | ||
759 | z3 = (long) wsptr[6]; | ||
760 | |||
761 | z1 = MULTIPLY16(z2 + z3, FIX_0_541196100); | ||
762 | tmp2 = z1 + MULTIPLY16(z3, - FIX_1_847759065); | ||
763 | tmp3 = z1 + MULTIPLY16(z2, FIX_0_765366865); | ||
764 | |||
765 | tmp0 = ((long) wsptr[0] + (long) wsptr[4]) << CONST_BITS; | ||
766 | tmp1 = ((long) wsptr[0] - (long) wsptr[4]) << CONST_BITS; | ||
767 | |||
768 | tmp10 = tmp0 + tmp3; | ||
769 | tmp13 = tmp0 - tmp3; | ||
770 | tmp11 = tmp1 + tmp2; | ||
771 | tmp12 = tmp1 - tmp2; | ||
772 | |||
773 | /* Odd part per figure 8; the matrix is unitary and hence its | ||
774 | * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */ | ||
775 | |||
776 | tmp0 = (long) wsptr[7]; | ||
777 | tmp1 = (long) wsptr[5]; | ||
778 | tmp2 = (long) wsptr[3]; | ||
779 | tmp3 = (long) wsptr[1]; | ||
780 | |||
781 | z1 = tmp0 + tmp3; | ||
782 | z2 = tmp1 + tmp2; | ||
783 | z3 = tmp0 + tmp2; | ||
784 | z4 = tmp1 + tmp3; | ||
785 | z5 = MULTIPLY16(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ | ||
786 | |||
787 | tmp0 = MULTIPLY16(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ | ||
788 | tmp1 = MULTIPLY16(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ | ||
789 | tmp2 = MULTIPLY16(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ | ||
790 | tmp3 = MULTIPLY16(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ | ||
791 | z1 = MULTIPLY16(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ | ||
792 | z2 = MULTIPLY16(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ | ||
793 | z3 = MULTIPLY16(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ | ||
794 | z4 = MULTIPLY16(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ | ||
795 | |||
796 | z3 += z5; | ||
797 | z4 += z5; | ||
798 | |||
799 | tmp0 += z1 + z3; | ||
800 | tmp1 += z2 + z4; | ||
801 | tmp2 += z2 + z3; | ||
802 | tmp3 += z1 + z4; | ||
803 | |||
804 | /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ | ||
805 | |||
806 | outptr[0] = range_limit((int) DESCALE(tmp10 + tmp3, | ||
807 | CONST_BITS+PASS1_BITS+3)); | ||
808 | outptr[7] = range_limit((int) DESCALE(tmp10 - tmp3, | ||
809 | CONST_BITS+PASS1_BITS+3)); | ||
810 | outptr[1] = range_limit((int) DESCALE(tmp11 + tmp2, | ||
811 | CONST_BITS+PASS1_BITS+3)); | ||
812 | outptr[6] = range_limit((int) DESCALE(tmp11 - tmp2, | ||
813 | CONST_BITS+PASS1_BITS+3)); | ||
814 | outptr[2] = range_limit((int) DESCALE(tmp12 + tmp1, | ||
815 | CONST_BITS+PASS1_BITS+3)); | ||
816 | outptr[5] = range_limit((int) DESCALE(tmp12 - tmp1, | ||
817 | CONST_BITS+PASS1_BITS+3)); | ||
818 | outptr[3] = range_limit((int) DESCALE(tmp13 + tmp0, | ||
819 | CONST_BITS+PASS1_BITS+3)); | ||
820 | outptr[4] = range_limit((int) DESCALE(tmp13 - tmp0, | ||
821 | CONST_BITS+PASS1_BITS+3)); | ||
822 | |||
823 | wsptr += 8; /* advance pointer to next row */ | ||
824 | } | ||
825 | } | ||
826 | |||
827 | |||
828 | |||
829 | /* JPEG decoder implementation */ | ||
830 | |||
831 | |||
832 | #define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ | ||
833 | |||
834 | struct derived_tbl | ||
835 | { | ||
836 | /* Basic tables: (element [0] of each array is unused) */ | ||
837 | long mincode[17]; /* smallest code of length k */ | ||
838 | long maxcode[18]; /* largest code of length k (-1 if none) */ | ||
839 | /* (maxcode[17] is a sentinel to ensure huff_DECODE terminates) */ | ||
840 | int valptr[17]; /* huffval[] index of 1st symbol of length k */ | ||
841 | |||
842 | /* Back link to public Huffman table (needed only in slow_DECODE) */ | ||
843 | int* pub; | ||
844 | |||
845 | /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of | ||
846 | the input data stream. If the next Huffman code is no more | ||
847 | than HUFF_LOOKAHEAD bits long, we can obtain its length and | ||
848 | the corresponding symbol directly from these tables. */ | ||
849 | int look_nbits[1<<HUFF_LOOKAHEAD]; /* # bits, or 0 if too long */ | ||
850 | unsigned char look_sym[1<<HUFF_LOOKAHEAD]; /* symbol, or unused */ | ||
851 | }; | ||
852 | |||
853 | #define QUANT_TABLE_LENGTH 64 | ||
854 | |||
855 | /* for type of Huffman table */ | ||
856 | #define DC_LEN 28 | ||
857 | #define AC_LEN 178 | ||
858 | |||
859 | struct huffman_table | ||
860 | { /* length and code according to JFIF format */ | ||
861 | int huffmancodes_dc[DC_LEN]; | ||
862 | int huffmancodes_ac[AC_LEN]; | ||
863 | }; | ||
864 | |||
865 | struct frame_component | ||
866 | { | ||
867 | int ID; | ||
868 | int horizontal_sampling; | ||
869 | int vertical_sampling; | ||
870 | int quanttable_select; | ||
871 | }; | ||
872 | |||
873 | struct scan_component | ||
874 | { | ||
875 | int ID; | ||
876 | int DC_select; | ||
877 | int AC_select; | ||
878 | }; | ||
879 | |||
880 | struct bitstream | ||
881 | { | ||
882 | unsigned long get_buffer; /* current bit-extraction buffer */ | ||
883 | int bits_left; /* # of unused bits in it */ | ||
884 | unsigned char* next_input_byte; | ||
885 | unsigned char* input_end; /* upper limit +1 */ | ||
886 | }; | ||
887 | |||
888 | struct jpeg | ||
889 | { | ||
890 | int x_size, y_size; /* size of image (can be less than block boundary) */ | ||
891 | int x_phys, y_phys; /* physical size, block aligned */ | ||
892 | int x_mbl; /* x dimension of MBL */ | ||
893 | int y_mbl; /* y dimension of MBL */ | ||
894 | int blocks; /* blocks per MB */ | ||
895 | int restart_interval; /* number of MCUs between RSTm markers */ | ||
896 | int store_pos[4]; /* for Y block ordering */ | ||
897 | |||
898 | unsigned char* p_entropy_data; | ||
899 | unsigned char* p_entropy_end; | ||
900 | |||
901 | int quanttable[4][QUANT_TABLE_LENGTH]; /* raw quantization tables 0-3 */ | ||
902 | int qt_idct[2][QUANT_TABLE_LENGTH]; /* quantization tables for IDCT */ | ||
903 | |||
904 | struct huffman_table hufftable[2]; /* Huffman tables */ | ||
905 | struct derived_tbl dc_derived_tbls[2]; /* Huffman-LUTs */ | ||
906 | struct derived_tbl ac_derived_tbls[2]; | ||
907 | |||
908 | struct frame_component frameheader[3]; /* Component descriptor */ | ||
909 | struct scan_component scanheader[3]; /* currently not used */ | ||
910 | |||
911 | int mcu_membership[6]; /* info per block */ | ||
912 | int tab_membership[6]; | ||
913 | int subsample_x[3]; /* info per component */ | ||
914 | int subsample_y[3]; | ||
915 | }; | ||
916 | |||
917 | |||
918 | /* possible return flags for process_markers() */ | ||
919 | #define HUFFTAB 0x0001 /* with huffman table */ | ||
920 | #define QUANTTAB 0x0002 /* with quantization table */ | ||
921 | #define APP0_JFIF 0x0004 /* with APP0 segment following JFIF standard */ | ||
922 | #define FILL_FF 0x0008 /* with 0xFF padding bytes at begin/end */ | ||
923 | #define SOF0 0x0010 /* with SOF0-Segment */ | ||
924 | #define DHT 0x0020 /* with Definition of huffman tables */ | ||
925 | #define SOS 0x0040 /* with Start-of-Scan segment */ | ||
926 | #define DQT 0x0080 /* with definition of quantization table */ | ||
927 | |||
928 | /* Preprocess the JPEG JFIF file */ | ||
929 | int process_markers(unsigned char* p_src, long size, struct jpeg* p_jpeg) | ||
930 | { | ||
931 | unsigned char* p_bytes = p_src; | ||
932 | int marker_size; /* variable length of marker segment */ | ||
933 | int i, j, n; | ||
934 | int ret = 0; /* returned flags */ | ||
935 | |||
936 | p_jpeg->p_entropy_end = p_src + size; | ||
937 | |||
938 | while (p_src < p_bytes + size) | ||
939 | { | ||
940 | if (*p_src++ != 0xFF) /* no marker? */ | ||
941 | { | ||
942 | p_src--; /* it's image data, put it back */ | ||
943 | p_jpeg->p_entropy_data = p_src; | ||
944 | break; /* exit marker processing */ | ||
945 | } | ||
946 | |||
947 | switch (*p_src++) | ||
948 | { | ||
949 | case 0xFF: /* Fill byte */ | ||
950 | ret |= FILL_FF; | ||
951 | case 0x00: /* Zero stuffed byte - entropy data */ | ||
952 | p_src--; /* put it back */ | ||
953 | continue; | ||
954 | |||
955 | case 0xC0: /* SOF Huff - Baseline DCT */ | ||
956 | { | ||
957 | ret |= SOF0; | ||
958 | marker_size = *p_src++ << 8; /* Highbyte */ | ||
959 | marker_size |= *p_src++; /* Lowbyte */ | ||
960 | n = *p_src++; /* sample precision (= 8 or 12) */ | ||
961 | if (n != 8) | ||
962 | { | ||
963 | return(-1); /* Unsupported sample precision */ | ||
964 | } | ||
965 | p_jpeg->y_size = *p_src++ << 8; /* Highbyte */ | ||
966 | p_jpeg->y_size |= *p_src++; /* Lowbyte */ | ||
967 | p_jpeg->x_size = *p_src++ << 8; /* Highbyte */ | ||
968 | p_jpeg->x_size |= *p_src++; /* Lowbyte */ | ||
969 | |||
970 | n = (marker_size-2-6)/3; | ||
971 | if (*p_src++ != n || (n != 1 && n != 3)) | ||
972 | { | ||
973 | return(-2); /* Unsupported SOF0 component specification */ | ||
974 | } | ||
975 | for (i=0; i<n; i++) | ||
976 | { | ||
977 | p_jpeg->frameheader[i].ID = *p_src++; /* Component info */ | ||
978 | p_jpeg->frameheader[i].horizontal_sampling = *p_src >> 4; | ||
979 | p_jpeg->frameheader[i].vertical_sampling = *p_src++ & 0x0F; | ||
980 | p_jpeg->frameheader[i].quanttable_select = *p_src++; | ||
981 | if (p_jpeg->frameheader[i].horizontal_sampling > 2 | ||
982 | || p_jpeg->frameheader[i].vertical_sampling > 2) | ||
983 | return -3; /* Unsupported SOF0 subsampling */ | ||
984 | } | ||
985 | p_jpeg->blocks = n; | ||
986 | } | ||
987 | break; | ||
988 | |||
989 | case 0xC1: /* SOF Huff - Extended sequential DCT*/ | ||
990 | case 0xC2: /* SOF Huff - Progressive DCT*/ | ||
991 | case 0xC3: /* SOF Huff - Spatial (sequential) lossless*/ | ||
992 | case 0xC5: /* SOF Huff - Differential sequential DCT*/ | ||
993 | case 0xC6: /* SOF Huff - Differential progressive DCT*/ | ||
994 | case 0xC7: /* SOF Huff - Differential spatial*/ | ||
995 | case 0xC8: /* SOF Arith - Reserved for JPEG extensions*/ | ||
996 | case 0xC9: /* SOF Arith - Extended sequential DCT*/ | ||
997 | case 0xCA: /* SOF Arith - Progressive DCT*/ | ||
998 | case 0xCB: /* SOF Arith - Spatial (sequential) lossless*/ | ||
999 | case 0xCD: /* SOF Arith - Differential sequential DCT*/ | ||
1000 | case 0xCE: /* SOF Arith - Differential progressive DCT*/ | ||
1001 | case 0xCF: /* SOF Arith - Differential spatial*/ | ||
1002 | { | ||
1003 | return (-4); /* other DCT model than baseline not implemented */ | ||
1004 | } | ||
1005 | |||
1006 | case 0xC4: /* Define Huffman Table(s) */ | ||
1007 | { | ||
1008 | unsigned char* p_temp; | ||
1009 | |||
1010 | ret |= DHT; | ||
1011 | marker_size = *p_src++ << 8; /* Highbyte */ | ||
1012 | marker_size |= *p_src++; /* Lowbyte */ | ||
1013 | |||
1014 | p_temp = p_src; | ||
1015 | while (p_src < p_temp+marker_size-2-17) /* another table */ | ||
1016 | { | ||
1017 | int sum = 0; | ||
1018 | i = *p_src & 0x0F; /* table index */ | ||
1019 | if (i > 1) | ||
1020 | { | ||
1021 | return (-5); /* Huffman table index out of range */ | ||
1022 | } | ||
1023 | else if (*p_src++ & 0xF0) /* AC table */ | ||
1024 | { | ||
1025 | for (j=0; j<16; j++) | ||
1026 | { | ||
1027 | sum += *p_src; | ||
1028 | p_jpeg->hufftable[i].huffmancodes_ac[j] = *p_src++; | ||
1029 | } | ||
1030 | if(16 + sum > AC_LEN) | ||
1031 | return -10; /* longer than allowed */ | ||
1032 | |||
1033 | for (; j < 16 + sum; j++) | ||
1034 | p_jpeg->hufftable[i].huffmancodes_ac[j] = *p_src++; | ||
1035 | } | ||
1036 | else /* DC table */ | ||
1037 | { | ||
1038 | for (j=0; j<16; j++) | ||
1039 | { | ||
1040 | sum += *p_src; | ||
1041 | p_jpeg->hufftable[i].huffmancodes_dc[j] = *p_src++; | ||
1042 | } | ||
1043 | if(16 + sum > DC_LEN) | ||
1044 | return -11; /* longer than allowed */ | ||
1045 | |||
1046 | for (; j < 16 + sum; j++) | ||
1047 | p_jpeg->hufftable[i].huffmancodes_dc[j] = *p_src++; | ||
1048 | } | ||
1049 | } /* while */ | ||
1050 | p_src = p_temp+marker_size - 2; /* skip possible residue */ | ||
1051 | } | ||
1052 | break; | ||
1053 | |||
1054 | case 0xCC: /* Define Arithmetic coding conditioning(s) */ | ||
1055 | return(-6); /* Arithmetic coding not supported */ | ||
1056 | |||
1057 | case 0xD8: /* Start of Image */ | ||
1058 | case 0xD9: /* End of Image */ | ||
1059 | case 0x01: /* for temp private use arith code */ | ||
1060 | break; /* skip parameterless marker */ | ||
1061 | |||
1062 | |||
1063 | case 0xDA: /* Start of Scan */ | ||
1064 | { | ||
1065 | ret |= SOS; | ||
1066 | marker_size = *p_src++ << 8; /* Highbyte */ | ||
1067 | marker_size |= *p_src++; /* Lowbyte */ | ||
1068 | |||
1069 | n = (marker_size-2-1-3)/2; | ||
1070 | if (*p_src++ != n || (n != 1 && n != 3)) | ||
1071 | { | ||
1072 | return (-7); /* Unsupported SOS component specification */ | ||
1073 | } | ||
1074 | for (i=0; i<n; i++) | ||
1075 | { | ||
1076 | p_jpeg->scanheader[i].ID = *p_src++; | ||
1077 | p_jpeg->scanheader[i].DC_select = *p_src >> 4; | ||
1078 | p_jpeg->scanheader[i].AC_select = *p_src++ & 0x0F; | ||
1079 | } | ||
1080 | p_src += 3; /* skip spectral information */ | ||
1081 | } | ||
1082 | break; | ||
1083 | |||
1084 | case 0xDB: /* Define quantization Table(s) */ | ||
1085 | { | ||
1086 | ret |= DQT; | ||
1087 | marker_size = *p_src++ << 8; /* Highbyte */ | ||
1088 | marker_size |= *p_src++; /* Lowbyte */ | ||
1089 | n = (marker_size-2)/(QUANT_TABLE_LENGTH+1); /* # of tables */ | ||
1090 | for (i=0; i<n; i++) | ||
1091 | { | ||
1092 | int id = *p_src++; /* ID */ | ||
1093 | if (id >= 4) | ||
1094 | { | ||
1095 | return (-8); /* Unsupported quantization table */ | ||
1096 | } | ||
1097 | /* Read Quantisation table: */ | ||
1098 | for (j=0; j<QUANT_TABLE_LENGTH; j++) | ||
1099 | p_jpeg->quanttable[id][j] = *p_src++; | ||
1100 | } | ||
1101 | } | ||
1102 | break; | ||
1103 | |||
1104 | case 0xDD: /* Define Restart Interval */ | ||
1105 | { | ||
1106 | marker_size = *p_src++ << 8; /* Highbyte */ | ||
1107 | marker_size |= *p_src++; /* Lowbyte */ | ||
1108 | p_jpeg->restart_interval = *p_src++ << 8; /* Highbyte */ | ||
1109 | p_jpeg->restart_interval |= *p_src++; /* Lowbyte */ | ||
1110 | p_src += marker_size-4; /* skip segment */ | ||
1111 | } | ||
1112 | break; | ||
1113 | |||
1114 | case 0xDC: /* Define Number of Lines */ | ||
1115 | case 0xDE: /* Define Hierarchical progression */ | ||
1116 | case 0xDF: /* Expand Reference Component(s) */ | ||
1117 | case 0xE0: /* Application Field 0*/ | ||
1118 | case 0xE1: /* Application Field 1*/ | ||
1119 | case 0xE2: /* Application Field 2*/ | ||
1120 | case 0xE3: /* Application Field 3*/ | ||
1121 | case 0xE4: /* Application Field 4*/ | ||
1122 | case 0xE5: /* Application Field 5*/ | ||
1123 | case 0xE6: /* Application Field 6*/ | ||
1124 | case 0xE7: /* Application Field 7*/ | ||
1125 | case 0xE8: /* Application Field 8*/ | ||
1126 | case 0xE9: /* Application Field 9*/ | ||
1127 | case 0xEA: /* Application Field 10*/ | ||
1128 | case 0xEB: /* Application Field 11*/ | ||
1129 | case 0xEC: /* Application Field 12*/ | ||
1130 | case 0xED: /* Application Field 13*/ | ||
1131 | case 0xEE: /* Application Field 14*/ | ||
1132 | case 0xEF: /* Application Field 15*/ | ||
1133 | case 0xFE: /* Comment */ | ||
1134 | { | ||
1135 | marker_size = *p_src++ << 8; /* Highbyte */ | ||
1136 | marker_size |= *p_src++; /* Lowbyte */ | ||
1137 | p_src += marker_size-2; /* skip segment */ | ||
1138 | } | ||
1139 | break; | ||
1140 | |||
1141 | case 0xF0: /* Reserved for JPEG extensions */ | ||
1142 | case 0xF1: /* Reserved for JPEG extensions */ | ||
1143 | case 0xF2: /* Reserved for JPEG extensions */ | ||
1144 | case 0xF3: /* Reserved for JPEG extensions */ | ||
1145 | case 0xF4: /* Reserved for JPEG extensions */ | ||
1146 | case 0xF5: /* Reserved for JPEG extensions */ | ||
1147 | case 0xF6: /* Reserved for JPEG extensions */ | ||
1148 | case 0xF7: /* Reserved for JPEG extensions */ | ||
1149 | case 0xF8: /* Reserved for JPEG extensions */ | ||
1150 | case 0xF9: /* Reserved for JPEG extensions */ | ||
1151 | case 0xFA: /* Reserved for JPEG extensions */ | ||
1152 | case 0xFB: /* Reserved for JPEG extensions */ | ||
1153 | case 0xFC: /* Reserved for JPEG extensions */ | ||
1154 | case 0xFD: /* Reserved for JPEG extensions */ | ||
1155 | case 0x02: /* Reserved */ | ||
1156 | default: | ||
1157 | return (-9); /* Unknown marker */ | ||
1158 | } /* switch */ | ||
1159 | } /* while */ | ||
1160 | |||
1161 | return (ret); /* return flags with seen markers */ | ||
1162 | } | ||
1163 | |||
1164 | |||
1165 | void default_huff_tbl(struct jpeg* p_jpeg) | ||
1166 | { | ||
1167 | static const struct huffman_table luma_table = | ||
1168 | { | ||
1169 | { | ||
1170 | 0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00, | ||
1171 | 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B | ||
1172 | }, | ||
1173 | { | ||
1174 | 0x00,0x02,0x01,0x03,0x03,0x02,0x04,0x03,0x05,0x05,0x04,0x04,0x00,0x00,0x01,0x7D, | ||
1175 | 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07, | ||
1176 | 0x22,0x71,0x14,0x32,0x81,0x91,0xA1,0x08,0x23,0x42,0xB1,0xC1,0x15,0x52,0xD1,0xF0, | ||
1177 | 0x24,0x33,0x62,0x72,0x82,0x09,0x0A,0x16,0x17,0x18,0x19,0x1A,0x25,0x26,0x27,0x28, | ||
1178 | 0x29,0x2A,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49, | ||
1179 | 0x4A,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69, | ||
1180 | 0x6A,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x83,0x84,0x85,0x86,0x87,0x88,0x89, | ||
1181 | 0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7, | ||
1182 | 0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xC2,0xC3,0xC4,0xC5, | ||
1183 | 0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xE1,0xE2, | ||
1184 | 0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8, | ||
1185 | 0xF9,0xFA | ||
1186 | } | ||
1187 | }; | ||
1188 | |||
1189 | static const struct huffman_table chroma_table = | ||
1190 | { | ||
1191 | { | ||
1192 | 0x00,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00, | ||
1193 | 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B | ||
1194 | }, | ||
1195 | { | ||
1196 | 0x00,0x02,0x01,0x02,0x04,0x04,0x03,0x04,0x07,0x05,0x04,0x04,0x00,0x01,0x02,0x77, | ||
1197 | 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71, | ||
1198 | 0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xA1,0xB1,0xC1,0x09,0x23,0x33,0x52,0xF0, | ||
1199 | 0x15,0x62,0x72,0xD1,0x0A,0x16,0x24,0x34,0xE1,0x25,0xF1,0x17,0x18,0x19,0x1A,0x26, | ||
1200 | 0x27,0x28,0x29,0x2A,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48, | ||
1201 | 0x49,0x4A,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68, | ||
1202 | 0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x82,0x83,0x84,0x85,0x86,0x87, | ||
1203 | 0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5, | ||
1204 | 0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xC2,0xC3, | ||
1205 | 0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA, | ||
1206 | 0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8, | ||
1207 | 0xF9,0xFA | ||
1208 | } | ||
1209 | }; | ||
1210 | |||
1211 | MEMCPY(&p_jpeg->hufftable[0], &luma_table, sizeof(luma_table)); | ||
1212 | MEMCPY(&p_jpeg->hufftable[1], &chroma_table, sizeof(chroma_table)); | ||
1213 | |||
1214 | return; | ||
1215 | } | ||
1216 | |||
1217 | /* Compute the derived values for a Huffman table */ | ||
1218 | void fix_huff_tbl(int* htbl, struct derived_tbl* dtbl) | ||
1219 | { | ||
1220 | int p, i, l, si; | ||
1221 | int lookbits, ctr; | ||
1222 | char huffsize[257]; | ||
1223 | unsigned int huffcode[257]; | ||
1224 | unsigned int code; | ||
1225 | |||
1226 | dtbl->pub = htbl; /* fill in back link */ | ||
1227 | |||
1228 | /* Figure C.1: make table of Huffman code length for each symbol */ | ||
1229 | /* Note that this is in code-length order. */ | ||
1230 | |||
1231 | p = 0; | ||
1232 | for (l = 1; l <= 16; l++) | ||
1233 | { /* all possible code length */ | ||
1234 | for (i = 1; i <= (int) htbl[l-1]; i++) /* all codes per length */ | ||
1235 | huffsize[p++] = (char) l; | ||
1236 | } | ||
1237 | huffsize[p] = 0; | ||
1238 | |||
1239 | /* Figure C.2: generate the codes themselves */ | ||
1240 | /* Note that this is in code-length order. */ | ||
1241 | |||
1242 | code = 0; | ||
1243 | si = huffsize[0]; | ||
1244 | p = 0; | ||
1245 | while (huffsize[p]) | ||
1246 | { | ||
1247 | while (((int) huffsize[p]) == si) | ||
1248 | { | ||
1249 | huffcode[p++] = code; | ||
1250 | code++; | ||
1251 | } | ||
1252 | code <<= 1; | ||
1253 | si++; | ||
1254 | } | ||
1255 | |||
1256 | /* Figure F.15: generate decoding tables for bit-sequential decoding */ | ||
1257 | |||
1258 | p = 0; | ||
1259 | for (l = 1; l <= 16; l++) | ||
1260 | { | ||
1261 | if (htbl[l-1]) | ||
1262 | { | ||
1263 | dtbl->valptr[l] = p; /* huffval[] index of 1st symbol of code length l */ | ||
1264 | dtbl->mincode[l] = huffcode[p]; /* minimum code of length l */ | ||
1265 | p += htbl[l-1]; | ||
1266 | dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */ | ||
1267 | } | ||
1268 | else | ||
1269 | { | ||
1270 | dtbl->maxcode[l] = -1; /* -1 if no codes of this length */ | ||
1271 | } | ||
1272 | } | ||
1273 | dtbl->maxcode[17] = 0xFFFFFL; /* ensures huff_DECODE terminates */ | ||
1274 | |||
1275 | /* Compute lookahead tables to speed up decoding. | ||
1276 | * First we set all the table entries to 0, indicating "too long"; | ||
1277 | * then we iterate through the Huffman codes that are short enough and | ||
1278 | * fill in all the entries that correspond to bit sequences starting | ||
1279 | * with that code. | ||
1280 | */ | ||
1281 | |||
1282 | MEMSET(dtbl->look_nbits, 0, sizeof(dtbl->look_nbits)); | ||
1283 | |||
1284 | p = 0; | ||
1285 | for (l = 1; l <= HUFF_LOOKAHEAD; l++) | ||
1286 | { | ||
1287 | for (i = 1; i <= (int) htbl[l-1]; i++, p++) | ||
1288 | { | ||
1289 | /* l = current code's length, p = its index in huffcode[] & huffval[]. */ | ||
1290 | /* Generate left-justified code followed by all possible bit sequences */ | ||
1291 | lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l); | ||
1292 | for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) | ||
1293 | { | ||
1294 | dtbl->look_nbits[lookbits] = l; | ||
1295 | dtbl->look_sym[lookbits] = htbl[16+p]; | ||
1296 | lookbits++; | ||
1297 | } | ||
1298 | } | ||
1299 | } | ||
1300 | } | ||
1301 | |||
1302 | |||
1303 | /* zag[i] is the natural-order position of the i'th element of zigzag order. | ||
1304 | * If the incoming data is corrupted, decode_mcu could attempt to | ||
1305 | * reference values beyond the end of the array. To avoid a wild store, | ||
1306 | * we put some extra zeroes after the real entries. | ||
1307 | */ | ||
1308 | static const int zag[] = | ||
1309 | { | ||
1310 | 0, 1, 8, 16, 9, 2, 3, 10, | ||
1311 | 17, 24, 32, 25, 18, 11, 4, 5, | ||
1312 | 12, 19, 26, 33, 40, 48, 41, 34, | ||
1313 | 27, 20, 13, 6, 7, 14, 21, 28, | ||
1314 | 35, 42, 49, 56, 57, 50, 43, 36, | ||
1315 | 29, 22, 15, 23, 30, 37, 44, 51, | ||
1316 | 58, 59, 52, 45, 38, 31, 39, 46, | ||
1317 | 53, 60, 61, 54, 47, 55, 62, 63, | ||
1318 | 0, 0, 0, 0, 0, 0, 0, 0, /* extra entries in case k>63 below */ | ||
1319 | 0, 0, 0, 0, 0, 0, 0, 0 | ||
1320 | }; | ||
1321 | |||
1322 | void build_lut(struct jpeg* p_jpeg) | ||
1323 | { | ||
1324 | int i; | ||
1325 | fix_huff_tbl(p_jpeg->hufftable[0].huffmancodes_dc, | ||
1326 | &p_jpeg->dc_derived_tbls[0]); | ||
1327 | fix_huff_tbl(p_jpeg->hufftable[0].huffmancodes_ac, | ||
1328 | &p_jpeg->ac_derived_tbls[0]); | ||
1329 | fix_huff_tbl(p_jpeg->hufftable[1].huffmancodes_dc, | ||
1330 | &p_jpeg->dc_derived_tbls[1]); | ||
1331 | fix_huff_tbl(p_jpeg->hufftable[1].huffmancodes_ac, | ||
1332 | &p_jpeg->ac_derived_tbls[1]); | ||
1333 | |||
1334 | /* build the dequantization tables for the IDCT (De-ZiZagged) */ | ||
1335 | for (i=0; i<64; i++) | ||
1336 | { | ||
1337 | p_jpeg->qt_idct[0][zag[i]] = p_jpeg->quanttable[0][i]; | ||
1338 | p_jpeg->qt_idct[1][zag[i]] = p_jpeg->quanttable[1][i]; | ||
1339 | } | ||
1340 | |||
1341 | for (i=0; i<4; i++) | ||
1342 | p_jpeg->store_pos[i] = i; /* default ordering */ | ||
1343 | |||
1344 | /* assignments for the decoding of blocks */ | ||
1345 | if (p_jpeg->frameheader[0].horizontal_sampling == 2 | ||
1346 | && p_jpeg->frameheader[0].vertical_sampling == 1) | ||
1347 | { /* 4:2:2 */ | ||
1348 | p_jpeg->blocks = 4; | ||
1349 | p_jpeg->x_mbl = (p_jpeg->x_size+15) / 16; | ||
1350 | p_jpeg->x_phys = p_jpeg->x_mbl * 16; | ||
1351 | p_jpeg->y_mbl = (p_jpeg->y_size+7) / 8; | ||
1352 | p_jpeg->y_phys = p_jpeg->y_mbl * 8; | ||
1353 | p_jpeg->mcu_membership[0] = 0; /* Y1=Y2=0, U=1, V=2 */ | ||
1354 | p_jpeg->mcu_membership[1] = 0; | ||
1355 | p_jpeg->mcu_membership[2] = 1; | ||
1356 | p_jpeg->mcu_membership[3] = 2; | ||
1357 | p_jpeg->tab_membership[0] = 0; /* DC, DC, AC, AC */ | ||
1358 | p_jpeg->tab_membership[1] = 0; | ||
1359 | p_jpeg->tab_membership[2] = 1; | ||
1360 | p_jpeg->tab_membership[3] = 1; | ||
1361 | p_jpeg->subsample_x[0] = 1; | ||
1362 | p_jpeg->subsample_x[1] = 2; | ||
1363 | p_jpeg->subsample_x[2] = 2; | ||
1364 | p_jpeg->subsample_y[0] = 1; | ||
1365 | p_jpeg->subsample_y[1] = 1; | ||
1366 | p_jpeg->subsample_y[2] = 1; | ||
1367 | } | ||
1368 | if (p_jpeg->frameheader[0].horizontal_sampling == 1 | ||
1369 | && p_jpeg->frameheader[0].vertical_sampling == 2) | ||
1370 | { /* 4:2:2 vertically subsampled */ | ||
1371 | p_jpeg->store_pos[1] = 2; /* block positions are mirrored */ | ||
1372 | p_jpeg->store_pos[2] = 1; | ||
1373 | p_jpeg->blocks = 4; | ||
1374 | p_jpeg->x_mbl = (p_jpeg->x_size+7) / 8; | ||
1375 | p_jpeg->x_phys = p_jpeg->x_mbl * 8; | ||
1376 | p_jpeg->y_mbl = (p_jpeg->y_size+15) / 16; | ||
1377 | p_jpeg->y_phys = p_jpeg->y_mbl * 16; | ||
1378 | p_jpeg->mcu_membership[0] = 0; /* Y1=Y2=0, U=1, V=2 */ | ||
1379 | p_jpeg->mcu_membership[1] = 0; | ||
1380 | p_jpeg->mcu_membership[2] = 1; | ||
1381 | p_jpeg->mcu_membership[3] = 2; | ||
1382 | p_jpeg->tab_membership[0] = 0; /* DC, DC, AC, AC */ | ||
1383 | p_jpeg->tab_membership[1] = 0; | ||
1384 | p_jpeg->tab_membership[2] = 1; | ||
1385 | p_jpeg->tab_membership[3] = 1; | ||
1386 | p_jpeg->subsample_x[0] = 1; | ||
1387 | p_jpeg->subsample_x[1] = 1; | ||
1388 | p_jpeg->subsample_x[2] = 1; | ||
1389 | p_jpeg->subsample_y[0] = 1; | ||
1390 | p_jpeg->subsample_y[1] = 2; | ||
1391 | p_jpeg->subsample_y[2] = 2; | ||
1392 | } | ||
1393 | else if (p_jpeg->frameheader[0].horizontal_sampling == 2 | ||
1394 | && p_jpeg->frameheader[0].vertical_sampling == 2) | ||
1395 | { /* 4:2:0 */ | ||
1396 | p_jpeg->blocks = 6; | ||
1397 | p_jpeg->x_mbl = (p_jpeg->x_size+15) / 16; | ||
1398 | p_jpeg->x_phys = p_jpeg->x_mbl * 16; | ||
1399 | p_jpeg->y_mbl = (p_jpeg->y_size+15) / 16; | ||
1400 | p_jpeg->y_phys = p_jpeg->y_mbl * 16; | ||
1401 | p_jpeg->mcu_membership[0] = 0; | ||
1402 | p_jpeg->mcu_membership[1] = 0; | ||
1403 | p_jpeg->mcu_membership[2] = 0; | ||
1404 | p_jpeg->mcu_membership[3] = 0; | ||
1405 | p_jpeg->mcu_membership[4] = 1; | ||
1406 | p_jpeg->mcu_membership[5] = 2; | ||
1407 | p_jpeg->tab_membership[0] = 0; | ||
1408 | p_jpeg->tab_membership[1] = 0; | ||
1409 | p_jpeg->tab_membership[2] = 0; | ||
1410 | p_jpeg->tab_membership[3] = 0; | ||
1411 | p_jpeg->tab_membership[4] = 1; | ||
1412 | p_jpeg->tab_membership[5] = 1; | ||
1413 | p_jpeg->subsample_x[0] = 1; | ||
1414 | p_jpeg->subsample_x[1] = 2; | ||
1415 | p_jpeg->subsample_x[2] = 2; | ||
1416 | p_jpeg->subsample_y[0] = 1; | ||
1417 | p_jpeg->subsample_y[1] = 2; | ||
1418 | p_jpeg->subsample_y[2] = 2; | ||
1419 | } | ||
1420 | else if (p_jpeg->frameheader[0].horizontal_sampling == 1 | ||
1421 | && p_jpeg->frameheader[0].vertical_sampling == 1) | ||
1422 | { /* 4:4:4 */ | ||
1423 | /* don't overwrite p_jpeg->blocks */ | ||
1424 | p_jpeg->x_mbl = (p_jpeg->x_size+7) / 8; | ||
1425 | p_jpeg->x_phys = p_jpeg->x_mbl * 8; | ||
1426 | p_jpeg->y_mbl = (p_jpeg->y_size+7) / 8; | ||
1427 | p_jpeg->y_phys = p_jpeg->y_mbl * 8; | ||
1428 | p_jpeg->mcu_membership[0] = 0; | ||
1429 | p_jpeg->mcu_membership[1] = 1; | ||
1430 | p_jpeg->mcu_membership[2] = 2; | ||
1431 | p_jpeg->tab_membership[0] = 0; | ||
1432 | p_jpeg->tab_membership[1] = 1; | ||
1433 | p_jpeg->tab_membership[2] = 1; | ||
1434 | p_jpeg->subsample_x[0] = 1; | ||
1435 | p_jpeg->subsample_x[1] = 1; | ||
1436 | p_jpeg->subsample_x[2] = 1; | ||
1437 | p_jpeg->subsample_y[0] = 1; | ||
1438 | p_jpeg->subsample_y[1] = 1; | ||
1439 | p_jpeg->subsample_y[2] = 1; | ||
1440 | } | ||
1441 | else | ||
1442 | { | ||
1443 | /* error */ | ||
1444 | } | ||
1445 | |||
1446 | } | ||
1447 | |||
1448 | |||
1449 | /* | ||
1450 | * These functions/macros provide the in-line portion of bit fetching. | ||
1451 | * Use check_bit_buffer to ensure there are N bits in get_buffer | ||
1452 | * before using get_bits, peek_bits, or drop_bits. | ||
1453 | * check_bit_buffer(state,n,action); | ||
1454 | * Ensure there are N bits in get_buffer; if suspend, take action. | ||
1455 | * val = get_bits(n); | ||
1456 | * Fetch next N bits. | ||
1457 | * val = peek_bits(n); | ||
1458 | * Fetch next N bits without removing them from the buffer. | ||
1459 | * drop_bits(n); | ||
1460 | * Discard next N bits. | ||
1461 | * The value N should be a simple variable, not an expression, because it | ||
1462 | * is evaluated multiple times. | ||
1463 | */ | ||
1464 | |||
1465 | INLINE void check_bit_buffer(struct bitstream* pb, int nbits) | ||
1466 | { | ||
1467 | if (pb->bits_left < nbits) | ||
1468 | { /* nbits is <= 16, so I can always refill 2 bytes in this case */ | ||
1469 | unsigned char byte; | ||
1470 | |||
1471 | byte = *pb->next_input_byte++; | ||
1472 | if (byte == 0xFF) /* legal marker can be byte stuffing or RSTm */ | ||
1473 | { /* simplification: just skip the (one-byte) marker code */ | ||
1474 | pb->next_input_byte++; | ||
1475 | } | ||
1476 | pb->get_buffer = (pb->get_buffer << 8) | byte; | ||
1477 | |||
1478 | byte = *pb->next_input_byte++; | ||
1479 | if (byte == 0xFF) /* legal marker can be byte stuffing or RSTm */ | ||
1480 | { /* simplification: just skip the (one-byte) marker code */ | ||
1481 | pb->next_input_byte++; | ||
1482 | } | ||
1483 | pb->get_buffer = (pb->get_buffer << 8) | byte; | ||
1484 | |||
1485 | pb->bits_left += 16; | ||
1486 | } | ||
1487 | } | ||
1488 | |||
1489 | INLINE int get_bits(struct bitstream* pb, int nbits) | ||
1490 | { | ||
1491 | return ((int) (pb->get_buffer >> (pb->bits_left -= nbits))) & ((1<<nbits)-1); | ||
1492 | } | ||
1493 | |||
1494 | INLINE int peek_bits(struct bitstream* pb, int nbits) | ||
1495 | { | ||
1496 | return ((int) (pb->get_buffer >> (pb->bits_left - nbits))) & ((1<<nbits)-1); | ||
1497 | } | ||
1498 | |||
1499 | INLINE void drop_bits(struct bitstream* pb, int nbits) | ||
1500 | { | ||
1501 | pb->bits_left -= nbits; | ||
1502 | } | ||
1503 | |||
1504 | /* re-synchronize to entropy data (skip restart marker) */ | ||
1505 | void search_restart(struct bitstream* pb) | ||
1506 | { | ||
1507 | pb->next_input_byte--; /* we may have overread it, taking 2 bytes */ | ||
1508 | /* search for a non-byte-padding marker, has to be RSTm or EOS */ | ||
1509 | while (pb->next_input_byte < pb->input_end && | ||
1510 | (pb->next_input_byte[-2] != 0xFF || pb->next_input_byte[-1] == 0x00)) | ||
1511 | { | ||
1512 | pb->next_input_byte++; | ||
1513 | } | ||
1514 | pb->bits_left = 0; | ||
1515 | } | ||
1516 | |||
1517 | /* Figure F.12: extend sign bit. */ | ||
1518 | #define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) | ||
1519 | |||
1520 | static const int extend_test[16] = /* entry n is 2**(n-1) */ | ||
1521 | { | ||
1522 | 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, | ||
1523 | 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 | ||
1524 | }; | ||
1525 | |||
1526 | static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ | ||
1527 | { | ||
1528 | 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, | ||
1529 | ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, | ||
1530 | ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, | ||
1531 | ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 | ||
1532 | }; | ||
1533 | |||
1534 | /* Decode a single value */ | ||
1535 | INLINE int huff_decode_dc(struct bitstream* bs, struct derived_tbl* tbl) | ||
1536 | { | ||
1537 | int nb, look, s, r; | ||
1538 | |||
1539 | check_bit_buffer(bs, HUFF_LOOKAHEAD); | ||
1540 | look = peek_bits(bs, HUFF_LOOKAHEAD); | ||
1541 | if ((nb = tbl->look_nbits[look]) != 0) | ||
1542 | { | ||
1543 | drop_bits(bs, nb); | ||
1544 | s = tbl->look_sym[look]; | ||
1545 | check_bit_buffer(bs, s); | ||
1546 | r = get_bits(bs, s); | ||
1547 | s = HUFF_EXTEND(r, s); | ||
1548 | } | ||
1549 | else | ||
1550 | { /* slow_DECODE(s, HUFF_LOOKAHEAD+1)) < 0); */ | ||
1551 | long code; | ||
1552 | nb=HUFF_LOOKAHEAD+1; | ||
1553 | check_bit_buffer(bs, nb); | ||
1554 | code = get_bits(bs, nb); | ||
1555 | while (code > tbl->maxcode[nb]) | ||
1556 | { | ||
1557 | code <<= 1; | ||
1558 | check_bit_buffer(bs, 1); | ||
1559 | code |= get_bits(bs, 1); | ||
1560 | nb++; | ||
1561 | } | ||
1562 | if (nb > 16) /* error in Huffman */ | ||
1563 | { | ||
1564 | s=0; /* fake a zero, this is most safe */ | ||
1565 | } | ||
1566 | else | ||
1567 | { | ||
1568 | s = tbl->pub[16 + tbl->valptr[nb] + ((int) (code - tbl->mincode[nb])) ]; | ||
1569 | check_bit_buffer(bs, s); | ||
1570 | r = get_bits(bs, s); | ||
1571 | s = HUFF_EXTEND(r, s); | ||
1572 | } | ||
1573 | } /* end slow decode */ | ||
1574 | return s; | ||
1575 | } | ||
1576 | |||
1577 | INLINE int huff_decode_ac(struct bitstream* bs, struct derived_tbl* tbl) | ||
1578 | { | ||
1579 | int nb, look, s; | ||
1580 | |||
1581 | check_bit_buffer(bs, HUFF_LOOKAHEAD); | ||
1582 | look = peek_bits(bs, HUFF_LOOKAHEAD); | ||
1583 | if ((nb = tbl->look_nbits[look]) != 0) | ||
1584 | { | ||
1585 | drop_bits(bs, nb); | ||
1586 | s = tbl->look_sym[look]; | ||
1587 | } | ||
1588 | else | ||
1589 | { /* slow_DECODE(s, HUFF_LOOKAHEAD+1)) < 0); */ | ||
1590 | long code; | ||
1591 | nb=HUFF_LOOKAHEAD+1; | ||
1592 | check_bit_buffer(bs, nb); | ||
1593 | code = get_bits(bs, nb); | ||
1594 | while (code > tbl->maxcode[nb]) | ||
1595 | { | ||
1596 | code <<= 1; | ||
1597 | check_bit_buffer(bs, 1); | ||
1598 | code |= get_bits(bs, 1); | ||
1599 | nb++; | ||
1600 | } | ||
1601 | if (nb > 16) /* error in Huffman */ | ||
1602 | { | ||
1603 | s=0; /* fake a zero, this is most safe */ | ||
1604 | } | ||
1605 | else | ||
1606 | { | ||
1607 | s = tbl->pub[16 + tbl->valptr[nb] + ((int) (code - tbl->mincode[nb])) ]; | ||
1608 | } | ||
1609 | } /* end slow decode */ | ||
1610 | return s; | ||
1611 | } | ||
1612 | |||
1613 | |||
1614 | #ifdef HAVE_LCD_COLOR | ||
1615 | |||
1616 | /* JPEG decoder variant for YUV decoding, into 3 different planes */ | ||
1617 | /* Note: it keeps the original color subsampling, even if resized. */ | ||
1618 | int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel[3], | ||
1619 | int downscale, void (*pf_progress)(int current, int total)) | ||
1620 | { | ||
1621 | struct bitstream bs; /* bitstream "object" */ | ||
1622 | int block[64]; /* decoded DCT coefficients */ | ||
1623 | |||
1624 | int width, height; | ||
1625 | int skip_line[3]; /* bytes from one line to the next (skip_line) */ | ||
1626 | int skip_strip[3], skip_mcu[3]; /* bytes to next DCT row / column */ | ||
1627 | |||
1628 | int i, x, y; /* loop counter */ | ||
1629 | |||
1630 | unsigned char* p_line[3] = {p_pixel[0], p_pixel[1], p_pixel[2]}; | ||
1631 | unsigned char* p_byte[3]; /* bitmap pointer */ | ||
1632 | |||
1633 | void (*pf_idct)(unsigned char*, int*, int*, int); /* selected IDCT */ | ||
1634 | int k_need; /* AC coefficients needed up to here */ | ||
1635 | int zero_need; /* init the block with this many zeros */ | ||
1636 | |||
1637 | int last_dc_val[3] = {0, 0, 0}; /* or 128 for chroma? */ | ||
1638 | int store_offs[4]; /* memory offsets: order of Y11 Y12 Y21 Y22 U V */ | ||
1639 | int restart = p_jpeg->restart_interval; /* MCUs until restart marker */ | ||
1640 | |||
1641 | /* pick the IDCT we want, determine how to work with coefs */ | ||
1642 | if (downscale == 1) | ||
1643 | { | ||
1644 | pf_idct = idct8x8; | ||
1645 | k_need = 64; /* all */ | ||
1646 | zero_need = 63; /* all */ | ||
1647 | } | ||
1648 | else if (downscale == 2) | ||
1649 | { | ||
1650 | pf_idct = idct4x4; | ||
1651 | k_need = 25; /* this far in zig-zag to cover 4*4 */ | ||
1652 | zero_need = 27; /* clear this far in linear order */ | ||
1653 | } | ||
1654 | else if (downscale == 4) | ||
1655 | { | ||
1656 | pf_idct = idct2x2; | ||
1657 | k_need = 5; /* this far in zig-zag to cover 2*2 */ | ||
1658 | zero_need = 9; /* clear this far in linear order */ | ||
1659 | } | ||
1660 | else if (downscale == 8) | ||
1661 | { | ||
1662 | pf_idct = idct1x1; | ||
1663 | k_need = 0; /* no AC, not needed */ | ||
1664 | zero_need = 0; /* no AC, not needed */ | ||
1665 | } | ||
1666 | else return -1; /* not supported */ | ||
1667 | |||
1668 | /* init bitstream, fake a restart to make it start */ | ||
1669 | bs.next_input_byte = p_jpeg->p_entropy_data; | ||
1670 | bs.bits_left = 0; | ||
1671 | bs.input_end = p_jpeg->p_entropy_end; | ||
1672 | |||
1673 | width = p_jpeg->x_phys / downscale; | ||
1674 | height = p_jpeg->y_phys / downscale; | ||
1675 | for (i=0; i<3; i++) /* calculate some strides */ | ||
1676 | { | ||
1677 | skip_line[i] = width / p_jpeg->subsample_x[i]; | ||
1678 | skip_strip[i] = skip_line[i] | ||
1679 | * (height / p_jpeg->y_mbl) / p_jpeg->subsample_y[i]; | ||
1680 | skip_mcu[i] = width/p_jpeg->x_mbl / p_jpeg->subsample_x[i]; | ||
1681 | } | ||
1682 | |||
1683 | /* prepare offsets about where to store the different blocks */ | ||
1684 | store_offs[p_jpeg->store_pos[0]] = 0; | ||
1685 | store_offs[p_jpeg->store_pos[1]] = 8 / downscale; /* to the right */ | ||
1686 | store_offs[p_jpeg->store_pos[2]] = width * 8 / downscale; /* below */ | ||
1687 | store_offs[p_jpeg->store_pos[3]] = store_offs[1] + store_offs[2]; /* r+b */ | ||
1688 | |||
1689 | for(y=0; y<p_jpeg->y_mbl && bs.next_input_byte <= bs.input_end; y++) | ||
1690 | { | ||
1691 | for (i=0; i<3; i++) /* scan line init */ | ||
1692 | { | ||
1693 | p_byte[i] = p_line[i]; | ||
1694 | p_line[i] += skip_strip[i]; | ||
1695 | } | ||
1696 | for (x=0; x<p_jpeg->x_mbl; x++) | ||
1697 | { | ||
1698 | int blkn; | ||
1699 | |||
1700 | /* Outer loop handles each block in the MCU */ | ||
1701 | for (blkn = 0; blkn < p_jpeg->blocks; blkn++) | ||
1702 | { /* Decode a single block's worth of coefficients */ | ||
1703 | int k = 1; /* coefficient index */ | ||
1704 | int s, r; /* huffman values */ | ||
1705 | int ci = p_jpeg->mcu_membership[blkn]; /* component index */ | ||
1706 | int ti = p_jpeg->tab_membership[blkn]; /* table index */ | ||
1707 | struct derived_tbl* dctbl = &p_jpeg->dc_derived_tbls[ti]; | ||
1708 | struct derived_tbl* actbl = &p_jpeg->ac_derived_tbls[ti]; | ||
1709 | |||
1710 | /* Section F.2.2.1: decode the DC coefficient difference */ | ||
1711 | s = huff_decode_dc(&bs, dctbl); | ||
1712 | |||
1713 | last_dc_val[ci] += s; | ||
1714 | block[0] = last_dc_val[ci]; /* output it (assumes zag[0] = 0) */ | ||
1715 | |||
1716 | /* coefficient buffer must be cleared */ | ||
1717 | MEMSET(block+1, 0, zero_need*sizeof(block[0])); | ||
1718 | |||
1719 | /* Section F.2.2.2: decode the AC coefficients */ | ||
1720 | for (; k < k_need; k++) | ||
1721 | { | ||
1722 | s = huff_decode_ac(&bs, actbl); | ||
1723 | r = s >> 4; | ||
1724 | s &= 15; | ||
1725 | |||
1726 | if (s) | ||
1727 | { | ||
1728 | k += r; | ||
1729 | check_bit_buffer(&bs, s); | ||
1730 | r = get_bits(&bs, s); | ||
1731 | block[zag[k]] = HUFF_EXTEND(r, s); | ||
1732 | } | ||
1733 | else | ||
1734 | { | ||
1735 | if (r != 15) | ||
1736 | { | ||
1737 | k = 64; | ||
1738 | break; | ||
1739 | } | ||
1740 | k += r; | ||
1741 | } | ||
1742 | } /* for k */ | ||
1743 | /* In this path we just discard the values */ | ||
1744 | for (; k < 64; k++) | ||
1745 | { | ||
1746 | s = huff_decode_ac(&bs, actbl); | ||
1747 | r = s >> 4; | ||
1748 | s &= 15; | ||
1749 | |||
1750 | if (s) | ||
1751 | { | ||
1752 | k += r; | ||
1753 | check_bit_buffer(&bs, s); | ||
1754 | drop_bits(&bs, s); | ||
1755 | } | ||
1756 | else | ||
1757 | { | ||
1758 | if (r != 15) | ||
1759 | break; | ||
1760 | k += r; | ||
1761 | } | ||
1762 | } /* for k */ | ||
1763 | |||
1764 | if (ci == 0) | ||
1765 | { /* Y component needs to bother about block store */ | ||
1766 | pf_idct(p_byte[0]+store_offs[blkn], block, | ||
1767 | p_jpeg->qt_idct[ti], skip_line[0]); | ||
1768 | } | ||
1769 | else | ||
1770 | { /* chroma */ | ||
1771 | pf_idct(p_byte[ci], block, p_jpeg->qt_idct[ti], | ||
1772 | skip_line[ci]); | ||
1773 | } | ||
1774 | } /* for blkn */ | ||
1775 | p_byte[0] += skip_mcu[0]; /* unrolled for (i=0; i<3; i++) loop */ | ||
1776 | p_byte[1] += skip_mcu[1]; | ||
1777 | p_byte[2] += skip_mcu[2]; | ||
1778 | if (p_jpeg->restart_interval && --restart == 0) | ||
1779 | { /* if a restart marker is due: */ | ||
1780 | restart = p_jpeg->restart_interval; /* count again */ | ||
1781 | search_restart(&bs); /* align the bitstream */ | ||
1782 | last_dc_val[0] = last_dc_val[1] = | ||
1783 | last_dc_val[2] = 0; /* reset decoder */ | ||
1784 | } | ||
1785 | } /* for x */ | ||
1786 | if (pf_progress != NULL) | ||
1787 | pf_progress(y, p_jpeg->y_mbl-1); /* notify about decoding progress */ | ||
1788 | } /* for y */ | ||
1789 | |||
1790 | return 0; /* success */ | ||
1791 | } | ||
1792 | #else /* !HAVE_LCD_COLOR */ | ||
1793 | |||
1794 | /* a JPEG decoder specialized in decoding only the luminance (b&w) */ | ||
1795 | int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel[1], int downscale, | ||
1796 | void (*pf_progress)(int current, int total)) | ||
1797 | { | ||
1798 | struct bitstream bs; /* bitstream "object" */ | ||
1799 | int block[64]; /* decoded DCT coefficients */ | ||
1800 | |||
1801 | int width, height; | ||
1802 | int skip_line; /* bytes from one line to the next (skip_line) */ | ||
1803 | int skip_strip, skip_mcu; /* bytes to next DCT row / column */ | ||
1804 | |||
1805 | int x, y; /* loop counter */ | ||
1806 | |||
1807 | unsigned char* p_line = p_pixel[0]; | ||
1808 | unsigned char* p_byte; /* bitmap pointer */ | ||
1809 | |||
1810 | void (*pf_idct)(unsigned char*, int*, int*, int); /* selected IDCT */ | ||
1811 | int k_need; /* AC coefficients needed up to here */ | ||
1812 | int zero_need; /* init the block with this many zeros */ | ||
1813 | |||
1814 | int last_dc_val = 0; | ||
1815 | int store_offs[4]; /* memory offsets: order of Y11 Y12 Y21 Y22 U V */ | ||
1816 | int restart = p_jpeg->restart_interval; /* MCUs until restart marker */ | ||
1817 | |||
1818 | /* pick the IDCT we want, determine how to work with coefs */ | ||
1819 | if (downscale == 1) | ||
1820 | { | ||
1821 | pf_idct = idct8x8; | ||
1822 | k_need = 64; /* all */ | ||
1823 | zero_need = 63; /* all */ | ||
1824 | } | ||
1825 | else if (downscale == 2) | ||
1826 | { | ||
1827 | pf_idct = idct4x4; | ||
1828 | k_need = 25; /* this far in zig-zag to cover 4*4 */ | ||
1829 | zero_need = 27; /* clear this far in linear order */ | ||
1830 | } | ||
1831 | else if (downscale == 4) | ||
1832 | { | ||
1833 | pf_idct = idct2x2; | ||
1834 | k_need = 5; /* this far in zig-zag to cover 2*2 */ | ||
1835 | zero_need = 9; /* clear this far in linear order */ | ||
1836 | } | ||
1837 | else if (downscale == 8) | ||
1838 | { | ||
1839 | pf_idct = idct1x1; | ||
1840 | k_need = 0; /* no AC, not needed */ | ||
1841 | zero_need = 0; /* no AC, not needed */ | ||
1842 | } | ||
1843 | else return -1; /* not supported */ | ||
1844 | |||
1845 | /* init bitstream, fake a restart to make it start */ | ||
1846 | bs.next_input_byte = p_jpeg->p_entropy_data; | ||
1847 | bs.bits_left = 0; | ||
1848 | bs.input_end = p_jpeg->p_entropy_end; | ||
1849 | |||
1850 | width = p_jpeg->x_phys / downscale; | ||
1851 | height = p_jpeg->y_phys / downscale; | ||
1852 | skip_line = width; | ||
1853 | skip_strip = skip_line * (height / p_jpeg->y_mbl); | ||
1854 | skip_mcu = (width/p_jpeg->x_mbl); | ||
1855 | |||
1856 | /* prepare offsets about where to store the different blocks */ | ||
1857 | store_offs[p_jpeg->store_pos[0]] = 0; | ||
1858 | store_offs[p_jpeg->store_pos[1]] = 8 / downscale; /* to the right */ | ||
1859 | store_offs[p_jpeg->store_pos[2]] = width * 8 / downscale; /* below */ | ||
1860 | store_offs[p_jpeg->store_pos[3]] = store_offs[1] + store_offs[2]; /* r+b */ | ||
1861 | |||
1862 | for(y=0; y<p_jpeg->y_mbl && bs.next_input_byte <= bs.input_end; y++) | ||
1863 | { | ||
1864 | p_byte = p_line; | ||
1865 | p_line += skip_strip; | ||
1866 | for (x=0; x<p_jpeg->x_mbl; x++) | ||
1867 | { | ||
1868 | int blkn; | ||
1869 | |||
1870 | /* Outer loop handles each block in the MCU */ | ||
1871 | for (blkn = 0; blkn < p_jpeg->blocks; blkn++) | ||
1872 | { /* Decode a single block's worth of coefficients */ | ||
1873 | int k = 1; /* coefficient index */ | ||
1874 | int s, r; /* huffman values */ | ||
1875 | int ci = p_jpeg->mcu_membership[blkn]; /* component index */ | ||
1876 | int ti = p_jpeg->tab_membership[blkn]; /* table index */ | ||
1877 | struct derived_tbl* dctbl = &p_jpeg->dc_derived_tbls[ti]; | ||
1878 | struct derived_tbl* actbl = &p_jpeg->ac_derived_tbls[ti]; | ||
1879 | |||
1880 | /* Section F.2.2.1: decode the DC coefficient difference */ | ||
1881 | s = huff_decode_dc(&bs, dctbl); | ||
1882 | |||
1883 | if (ci == 0) /* only for Y component */ | ||
1884 | { | ||
1885 | last_dc_val += s; | ||
1886 | block[0] = last_dc_val; /* output it (assumes zag[0] = 0) */ | ||
1887 | |||
1888 | /* coefficient buffer must be cleared */ | ||
1889 | MEMSET(block+1, 0, zero_need*sizeof(block[0])); | ||
1890 | |||
1891 | /* Section F.2.2.2: decode the AC coefficients */ | ||
1892 | for (; k < k_need; k++) | ||
1893 | { | ||
1894 | s = huff_decode_ac(&bs, actbl); | ||
1895 | r = s >> 4; | ||
1896 | s &= 15; | ||
1897 | |||
1898 | if (s) | ||
1899 | { | ||
1900 | k += r; | ||
1901 | check_bit_buffer(&bs, s); | ||
1902 | r = get_bits(&bs, s); | ||
1903 | block[zag[k]] = HUFF_EXTEND(r, s); | ||
1904 | } | ||
1905 | else | ||
1906 | { | ||
1907 | if (r != 15) | ||
1908 | { | ||
1909 | k = 64; | ||
1910 | break; | ||
1911 | } | ||
1912 | k += r; | ||
1913 | } | ||
1914 | } /* for k */ | ||
1915 | } | ||
1916 | /* In this path we just discard the values */ | ||
1917 | for (; k < 64; k++) | ||
1918 | { | ||
1919 | s = huff_decode_ac(&bs, actbl); | ||
1920 | r = s >> 4; | ||
1921 | s &= 15; | ||
1922 | |||
1923 | if (s) | ||
1924 | { | ||
1925 | k += r; | ||
1926 | check_bit_buffer(&bs, s); | ||
1927 | drop_bits(&bs, s); | ||
1928 | } | ||
1929 | else | ||
1930 | { | ||
1931 | if (r != 15) | ||
1932 | break; | ||
1933 | k += r; | ||
1934 | } | ||
1935 | } /* for k */ | ||
1936 | |||
1937 | if (ci == 0) | ||
1938 | { /* only for Y component */ | ||
1939 | pf_idct(p_byte+store_offs[blkn], block, p_jpeg->qt_idct[ti], | ||
1940 | skip_line); | ||
1941 | } | ||
1942 | } /* for blkn */ | ||
1943 | p_byte += skip_mcu; | ||
1944 | if (p_jpeg->restart_interval && --restart == 0) | ||
1945 | { /* if a restart marker is due: */ | ||
1946 | restart = p_jpeg->restart_interval; /* count again */ | ||
1947 | search_restart(&bs); /* align the bitstream */ | ||
1948 | last_dc_val = 0; /* reset decoder */ | ||
1949 | } | ||
1950 | } /* for x */ | ||
1951 | if (pf_progress != NULL) | ||
1952 | pf_progress(y, p_jpeg->y_mbl-1); /* notify about decoding progress */ | ||
1953 | } /* for y */ | ||
1954 | |||
1955 | return 0; /* success */ | ||
1956 | } | ||
1957 | #endif /* !HAVE_LCD_COLOR */ | ||
1958 | |||
1959 | /**************** end JPEG code ********************/ | ||
1960 | |||
1961 | |||
1962 | |||
1963 | /**************** begin Application ********************/ | ||
1964 | |||
1965 | |||
1966 | /************************* Types ***************************/ | ||
1967 | |||
1968 | struct t_disp | ||
1969 | { | ||
1970 | #ifdef HAVE_LCD_COLOR | ||
1971 | unsigned char* bitmap[3]; /* Y, Cr, Cb */ | ||
1972 | int csub_x, csub_y; | ||
1973 | #else | ||
1974 | unsigned char* bitmap[1]; /* Y only */ | ||
1975 | #endif | ||
1976 | int width; | ||
1977 | int height; | ||
1978 | int stride; | ||
1979 | int x, y; | ||
1980 | }; | ||
1981 | |||
1982 | /************************* Globals ***************************/ | ||
1983 | |||
1984 | /* decompressed image in the possible sizes (1,2,4,8), wasting the other */ | ||
1985 | struct t_disp disp[9]; | ||
1986 | |||
1987 | /* my memory pool (from the mp3 buffer) */ | ||
1988 | char print[32]; /* use a common snprintf() buffer */ | ||
1989 | unsigned char* buf; /* up to here currently used by image(s) */ | ||
1990 | |||
1991 | /* the remaining free part of the buffer for compressed+uncompressed images */ | ||
1992 | unsigned char* buf_images; | ||
1993 | |||
1994 | ssize_t buf_size, buf_images_size; | ||
1995 | /* the root of the images, hereafter are decompresed ones */ | ||
1996 | unsigned char* buf_root; | ||
1997 | int root_size; | ||
1998 | |||
1999 | int ds, ds_min, ds_max; /* downscaling and limits */ | ||
2000 | static struct jpeg jpg; /* too large for stack */ | ||
2001 | |||
2002 | static struct tree_context *tree; | ||
2003 | |||
2004 | /* the current full file name */ | ||
2005 | static char np_file[MAX_PATH]; | ||
2006 | int curfile = 0, direction = DIR_NONE, entries = 0; | ||
2007 | |||
2008 | /* list of the jpeg files */ | ||
2009 | char **file_pt; | ||
2010 | /* are we using the plugin buffer or the audio buffer? */ | ||
2011 | bool plug_buf = false; | ||
2012 | |||
2013 | |||
2014 | /************************* Implementation ***************************/ | ||
2015 | |||
2016 | #ifdef HAVE_LCD_COLOR | ||
2017 | /* | ||
2018 | * Conversion of full 0-255 range YCrCb to RGB: | ||
2019 | * |R| |1.000000 -0.000001 1.402000| |Y'| | ||
2020 | * |G| = |1.000000 -0.334136 -0.714136| |Pb| | ||
2021 | * |B| |1.000000 1.772000 0.000000| |Pr| | ||
2022 | * Scaled (yields s15-bit output): | ||
2023 | * |R| |128 0 179| |Y | | ||
2024 | * |G| = |128 -43 -91| |Cb - 128| | ||
2025 | * |B| |128 227 0| |Cr - 128| | ||
2026 | */ | ||
2027 | #define YFAC 128 | ||
2028 | #define RVFAC 179 | ||
2029 | #define GUFAC (-43) | ||
2030 | #define GVFAC (-91) | ||
2031 | #define BUFAC 227 | ||
2032 | #define YUV_WHITE (255*YFAC) | ||
2033 | #define NODITHER_DELTA (127*YFAC) | ||
2034 | #define COMPONENT_SHIFT 15 | ||
2035 | #define MATRIX_SHIFT 7 | ||
2036 | |||
2037 | static inline int clamp_component(int x) | ||
2038 | { | ||
2039 | if ((unsigned)x > YUV_WHITE) | ||
2040 | x = x < 0 ? 0 : YUV_WHITE; | ||
2041 | return x; | ||
2042 | } | ||
2043 | |||
2044 | static inline int clamp_component_bits(int x, int bits) | ||
2045 | { | ||
2046 | if ((unsigned)x > (1u << bits) - 1) | ||
2047 | x = x < 0 ? 0 : (1 << bits) - 1; | ||
2048 | return x; | ||
2049 | } | ||
2050 | |||
2051 | static inline int component_to_lcd(int x, int bits, int delta) | ||
2052 | { | ||
2053 | /* Formula used in core bitmap loader. */ | ||
2054 | return (((1 << bits) - 1)*x + (x >> (8 - bits)) + delta) >> COMPONENT_SHIFT; | ||
2055 | } | ||
2056 | |||
2057 | static inline int lcd_to_component(int x, int bits, int delta) | ||
2058 | { | ||
2059 | /* Reasonable, approximate reversal to get a full range back from the | ||
2060 | quantized value. */ | ||
2061 | return YUV_WHITE*x / ((1 << bits) - 1); | ||
2062 | (void)delta; | ||
2063 | } | ||
2064 | |||
2065 | #define RED 0 | ||
2066 | #define GRN 1 | ||
2067 | #define BLU 2 | ||
2068 | |||
2069 | struct rgb_err | ||
2070 | { | ||
2071 | int16_t errbuf[LCD_WIDTH+2]; /* Error record for line below */ | ||
2072 | } rgb_err_buffers[3]; | ||
2073 | |||
2074 | fb_data rgb_linebuf[LCD_WIDTH]; /* Line buffer for scrolling when | ||
2075 | DITHER_DIFFUSION is set */ | ||
2076 | |||
2077 | struct rgb_pixel | ||
2078 | { | ||
2079 | int r, g, b; /* Current pixel components in s16.0 */ | ||
2080 | int inc; /* Current line increment (-1 or 1) */ | ||
2081 | int row; /* Current row in source image */ | ||
2082 | int col; /* Current column in source image */ | ||
2083 | int ce[3]; /* Errors to apply to current pixel */ | ||
2084 | struct rgb_err *e; /* RED, GRN, BLU */ | ||
2085 | int epos; /* Current position in error record */ | ||
2086 | }; | ||
2087 | |||
2088 | struct rgb_pixel *pixel; | ||
2089 | |||
2090 | /** round and truncate to lcd depth **/ | ||
2091 | static fb_data pixel_to_lcd_colour(void) | ||
2092 | { | ||
2093 | struct rgb_pixel *p = pixel; | ||
2094 | int r, g, b; | ||
2095 | |||
2096 | r = component_to_lcd(p->r, LCD_RED_BITS, NODITHER_DELTA); | ||
2097 | r = clamp_component_bits(r, LCD_RED_BITS); | ||
2098 | |||
2099 | g = component_to_lcd(p->g, LCD_GREEN_BITS, NODITHER_DELTA); | ||
2100 | g = clamp_component_bits(g, LCD_GREEN_BITS); | ||
2101 | |||
2102 | b = component_to_lcd(p->b, LCD_BLUE_BITS, NODITHER_DELTA); | ||
2103 | b = clamp_component_bits(b, LCD_BLUE_BITS); | ||
2104 | |||
2105 | return LCD_RGBPACK_LCD(r, g, b); | ||
2106 | } | ||
2107 | |||
2108 | /** write a monochrome pixel to the colour LCD **/ | ||
2109 | static fb_data pixel_to_lcd_gray(void) | ||
2110 | { | ||
2111 | int r, g, b; | ||
2112 | |||
2113 | g = clamp_component(pixel->g); | ||
2114 | r = component_to_lcd(g, LCD_RED_BITS, NODITHER_DELTA); | ||
2115 | b = component_to_lcd(g, LCD_BLUE_BITS, NODITHER_DELTA); | ||
2116 | g = component_to_lcd(g, LCD_GREEN_BITS, NODITHER_DELTA); | ||
2117 | |||
2118 | return LCD_RGBPACK_LCD(r, g, b); | ||
2119 | } | ||
2120 | |||
2121 | /** | ||
2122 | * Bayer ordered dithering - swiped from the core bitmap loader. | ||
2123 | */ | ||
2124 | static fb_data pixel_odither_to_lcd(void) | ||
2125 | { | ||
2126 | /* canonical ordered dither matrix */ | ||
2127 | static const unsigned char dither_matrix[16][16] = { | ||
2128 | { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 }, | ||
2129 | { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 }, | ||
2130 | { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 }, | ||
2131 | { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 }, | ||
2132 | { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 }, | ||
2133 | { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 }, | ||
2134 | { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 }, | ||
2135 | { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 }, | ||
2136 | { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 }, | ||
2137 | { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 }, | ||
2138 | { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 }, | ||
2139 | { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 }, | ||
2140 | { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 }, | ||
2141 | { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 }, | ||
2142 | { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 }, | ||
2143 | { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 } | ||
2144 | }; | ||
2145 | |||
2146 | struct rgb_pixel *p = pixel; | ||
2147 | int r, g, b, delta; | ||
2148 | |||
2149 | delta = dither_matrix[p->col & 15][p->row & 15] << MATRIX_SHIFT; | ||
2150 | |||
2151 | r = component_to_lcd(p->r, LCD_RED_BITS, delta); | ||
2152 | r = clamp_component_bits(r, LCD_RED_BITS); | ||
2153 | |||
2154 | g = component_to_lcd(p->g, LCD_GREEN_BITS, delta); | ||
2155 | g = clamp_component_bits(g, LCD_GREEN_BITS); | ||
2156 | |||
2157 | b = component_to_lcd(p->b, LCD_BLUE_BITS, delta); | ||
2158 | b = clamp_component_bits(b, LCD_BLUE_BITS); | ||
2159 | |||
2160 | p->col += p->inc; | ||
2161 | |||
2162 | return LCD_RGBPACK_LCD(r, g, b); | ||
2163 | } | ||
2164 | |||
2165 | /** | ||
2166 | * Floyd/Steinberg dither to lcd depth. | ||
2167 | * | ||
2168 | * Apply filter to each component in serpentine pattern. Kernel shown for | ||
2169 | * L->R scan. Kernel is reversed for R->L. | ||
2170 | * * 7 | ||
2171 | * 3 5 1 (1/16) | ||
2172 | */ | ||
2173 | static inline void distribute_error(int *ce, struct rgb_err *e, | ||
2174 | int err, int epos, int inc) | ||
2175 | { | ||
2176 | *ce = (7*err >> 4) + e->errbuf[epos+inc]; | ||
2177 | e->errbuf[epos+inc] = err >> 4; | ||
2178 | e->errbuf[epos] += 5*err >> 4; | ||
2179 | e->errbuf[epos-inc] += 3*err >> 4; | ||
2180 | } | ||
2181 | |||
2182 | static fb_data pixel_fsdither_to_lcd(void) | ||
2183 | { | ||
2184 | struct rgb_pixel *p = pixel; | ||
2185 | int rc, gc, bc, r, g, b; | ||
2186 | int inc, epos; | ||
2187 | |||
2188 | /* Full components with error terms */ | ||
2189 | rc = p->r + p->ce[RED]; | ||
2190 | r = component_to_lcd(rc, LCD_RED_BITS, 0); | ||
2191 | r = clamp_component_bits(r, LCD_RED_BITS); | ||
2192 | |||
2193 | gc = p->g + p->ce[GRN]; | ||
2194 | g = component_to_lcd(gc, LCD_GREEN_BITS, 0); | ||
2195 | g = clamp_component_bits(g, LCD_GREEN_BITS); | ||
2196 | |||
2197 | bc = p->b + p->ce[BLU]; | ||
2198 | b = component_to_lcd(bc, LCD_BLUE_BITS, 0); | ||
2199 | b = clamp_component_bits(b, LCD_BLUE_BITS); | ||
2200 | |||
2201 | /* Get pixel errors */ | ||
2202 | rc -= lcd_to_component(r, LCD_RED_BITS, 0); | ||
2203 | gc -= lcd_to_component(g, LCD_GREEN_BITS, 0); | ||
2204 | bc -= lcd_to_component(b, LCD_BLUE_BITS, 0); | ||
2205 | |||
2206 | /* Spead error to surrounding pixels. */ | ||
2207 | inc = p->inc; | ||
2208 | epos = p->epos; | ||
2209 | p->epos += inc; | ||
2210 | |||
2211 | distribute_error(&p->ce[RED], &p->e[RED], rc, epos, inc); | ||
2212 | distribute_error(&p->ce[GRN], &p->e[GRN], gc, epos, inc); | ||
2213 | distribute_error(&p->ce[BLU], &p->e[BLU], bc, epos, inc); | ||
2214 | |||
2215 | /* Pack and return pixel */ | ||
2216 | return LCD_RGBPACK_LCD(r, g, b); | ||
2217 | } | ||
2218 | |||
2219 | /* Functions for each output mode, colour then grayscale. */ | ||
2220 | static fb_data (* const pixel_funcs[COLOUR_NUM_MODES][DITHER_NUM_MODES])(void) = | ||
2221 | { | ||
2222 | [COLOURMODE_COLOUR] = | ||
2223 | { | ||
2224 | [DITHER_NONE] = pixel_to_lcd_colour, | ||
2225 | [DITHER_ORDERED] = pixel_odither_to_lcd, | ||
2226 | [DITHER_DIFFUSION] = pixel_fsdither_to_lcd, | ||
2227 | }, | ||
2228 | [COLOURMODE_GRAY] = | ||
2229 | { | ||
2230 | [DITHER_NONE] = pixel_to_lcd_gray, | ||
2231 | [DITHER_ORDERED] = pixel_odither_to_lcd, | ||
2232 | [DITHER_DIFFUSION] = pixel_fsdither_to_lcd, | ||
2233 | }, | ||
2234 | }; | ||
2235 | |||
2236 | /** | ||
2237 | * Draw a partial YUV colour bitmap | ||
2238 | * | ||
2239 | * Runs serpentine pattern when dithering is DITHER_DIFFUSION, else scan is | ||
2240 | * always L->R. | ||
2241 | */ | ||
2242 | void yuv_bitmap_part(unsigned char *src[3], int csub_x, int csub_y, | ||
2243 | int src_x, int src_y, int stride, | ||
2244 | int x, int y, int width, int height) | ||
2245 | { | ||
2246 | fb_data *dst, *dst_end; | ||
2247 | fb_data (*pixel_func)(void); | ||
2248 | struct rgb_pixel px; | ||
2249 | |||
2250 | if (x + width > LCD_WIDTH) | ||
2251 | width = LCD_WIDTH - x; /* Clip right */ | ||
2252 | if (x < 0) | ||
2253 | width += x, x = 0; /* Clip left */ | ||
2254 | if (width <= 0) | ||
2255 | return; /* nothing left to do */ | ||
2256 | |||
2257 | if (y + height > LCD_HEIGHT) | ||
2258 | height = LCD_HEIGHT - y; /* Clip bottom */ | ||
2259 | if (y < 0) | ||
2260 | height += y, y = 0; /* Clip top */ | ||
2261 | if (height <= 0) | ||
2262 | return; /* nothing left to do */ | ||
2263 | |||
2264 | pixel = &px; | ||
2265 | |||
2266 | dst = rb->lcd_framebuffer + LCD_WIDTH * y + x; | ||
2267 | dst_end = dst + LCD_WIDTH * height; | ||
2268 | |||
2269 | if (jpeg_settings.colour_mode == COLOURMODE_GRAY) | ||
2270 | csub_y = 0; /* Ignore Cb, Cr */ | ||
2271 | |||
2272 | pixel_func = pixel_funcs[jpeg_settings.colour_mode] | ||
2273 | [jpeg_settings.dither_mode]; | ||
2274 | |||
2275 | if (jpeg_settings.dither_mode == DITHER_DIFFUSION) | ||
2276 | { | ||
2277 | /* Reset error terms. */ | ||
2278 | px.e = rgb_err_buffers; | ||
2279 | px.ce[RED] = px.ce[GRN] = px.ce[BLU] = 0; | ||
2280 | rb->memset(px.e, 0, 3*sizeof (struct rgb_err)); | ||
2281 | } | ||
2282 | |||
2283 | do | ||
2284 | { | ||
2285 | fb_data *dst_row, *row_end; | ||
2286 | const unsigned char *ysrc; | ||
2287 | px.inc = 1; | ||
2288 | |||
2289 | if (jpeg_settings.dither_mode == DITHER_DIFFUSION) | ||
2290 | { | ||
2291 | /* Use R->L scan on odd lines */ | ||
2292 | px.inc -= (src_y & 1) << 1; | ||
2293 | px.epos = x + 1; | ||
2294 | |||
2295 | if (px.inc < 0) | ||
2296 | px.epos += width - 1; | ||
2297 | } | ||
2298 | |||
2299 | if (px.inc == 1) | ||
2300 | { | ||
2301 | /* Scan is L->R */ | ||
2302 | dst_row = dst; | ||
2303 | row_end = dst_row + width; | ||
2304 | px.col = src_x; | ||
2305 | } | ||
2306 | else | ||
2307 | { | ||
2308 | /* Scan is R->L */ | ||
2309 | row_end = dst - 1; | ||
2310 | dst_row = row_end + width; | ||
2311 | px.col = src_x + width - 1; | ||
2312 | } | ||
2313 | |||
2314 | ysrc = src[0] + stride * src_y + px.col; | ||
2315 | px.row = src_y; | ||
2316 | |||
2317 | /* Do one row of pixels */ | ||
2318 | if (csub_y) /* colour */ | ||
2319 | { | ||
2320 | /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ | ||
2321 | const unsigned char *usrc, *vsrc; | ||
2322 | |||
2323 | usrc = src[1] + (stride/csub_x) * (src_y/csub_y) | ||
2324 | + (px.col/csub_x); | ||
2325 | vsrc = src[2] + (stride/csub_x) * (src_y/csub_y) | ||
2326 | + (px.col/csub_x); | ||
2327 | int xphase = px.col % csub_x; | ||
2328 | int xphase_reset = px.inc * csub_x; | ||
2329 | int y, v, u, rv, guv, bu; | ||
2330 | |||
2331 | v = *vsrc - 128; | ||
2332 | vsrc += px.inc; | ||
2333 | u = *usrc - 128; | ||
2334 | usrc += px.inc; | ||
2335 | rv = RVFAC*v; | ||
2336 | guv = GUFAC*u + GVFAC*v; | ||
2337 | bu = BUFAC*u; | ||
2338 | |||
2339 | while (1) | ||
2340 | { | ||
2341 | y = YFAC*(*ysrc); | ||
2342 | ysrc += px.inc; | ||
2343 | px.r = y + rv; | ||
2344 | px.g = y + guv; | ||
2345 | px.b = y + bu; | ||
2346 | |||
2347 | *dst_row = pixel_func(); | ||
2348 | dst_row += px.inc; | ||
2349 | |||
2350 | if (dst_row == row_end) | ||
2351 | break; | ||
2352 | |||
2353 | xphase += px.inc; | ||
2354 | if ((unsigned)xphase < (unsigned)csub_x) | ||
2355 | continue; | ||
2356 | |||
2357 | /* fetch new chromas */ | ||
2358 | v = *vsrc - 128; | ||
2359 | vsrc += px.inc; | ||
2360 | u = *usrc - 128; | ||
2361 | usrc += px.inc; | ||
2362 | rv = RVFAC*v; | ||
2363 | guv = GUFAC*u + GVFAC*v; | ||
2364 | bu = BUFAC*u; | ||
2365 | |||
2366 | xphase -= xphase_reset; | ||
2367 | } | ||
2368 | } | ||
2369 | else /* monochrome */ | ||
2370 | { | ||
2371 | do | ||
2372 | { | ||
2373 | /* Set all components the same for dithering purposes */ | ||
2374 | px.g = px.r = px.b = YFAC*(*ysrc); | ||
2375 | *dst_row = pixel_func(); | ||
2376 | ysrc += px.inc; | ||
2377 | dst_row += px.inc; | ||
2378 | } | ||
2379 | while (dst_row != row_end); | ||
2380 | } | ||
2381 | |||
2382 | src_y++; | ||
2383 | dst += LCD_WIDTH; | ||
2384 | } | ||
2385 | while (dst < dst_end); | ||
2386 | } | ||
2387 | |||
2388 | #endif /* HAVE_LCD_COLOR */ | ||
2389 | |||
2390 | |||
2391 | /* support function for qsort() */ | ||
2392 | static int compare(const void* p1, const void* p2) | ||
2393 | { | ||
2394 | return rb->strcasecmp(*((char **)p1), *((char **)p2)); | ||
2395 | } | ||
2396 | |||
2397 | bool jpg_ext(const char ext[]) | ||
2398 | { | ||
2399 | if(!ext) | ||
2400 | return false; | ||
2401 | if(!rb->strcasecmp(ext,".jpg") || | ||
2402 | !rb->strcasecmp(ext,".jpe") || | ||
2403 | !rb->strcasecmp(ext,".jpeg")) | ||
2404 | return true; | ||
2405 | else | ||
2406 | return false; | ||
2407 | } | ||
2408 | |||
2409 | /*Read directory contents for scrolling. */ | ||
2410 | void get_pic_list(void) | ||
2411 | { | ||
2412 | int i; | ||
2413 | long int str_len = 0; | ||
2414 | char *pname; | ||
2415 | tree = rb->tree_get_context(); | ||
2416 | |||
2417 | #if PLUGIN_BUFFER_SIZE >= MIN_MEM | ||
2418 | file_pt = rb->plugin_get_buffer((size_t *)&buf_size); | ||
2419 | #else | ||
2420 | file_pt = rb->plugin_get_audio_buffer((size_t *)&buf_size); | ||
2421 | #endif | ||
2422 | |||
2423 | for(i = 0; i < tree->filesindir; i++) | ||
2424 | { | ||
2425 | if(jpg_ext(rb->strrchr(&tree->name_buffer[str_len],'.'))) | ||
2426 | file_pt[entries++] = &tree->name_buffer[str_len]; | ||
2427 | |||
2428 | str_len += rb->strlen(&tree->name_buffer[str_len]) + 1; | ||
2429 | } | ||
2430 | |||
2431 | rb->qsort(file_pt, entries, sizeof(char**), compare); | ||
2432 | |||
2433 | /* Remove path and leave only the name.*/ | ||
2434 | pname = rb->strrchr(np_file,'/'); | ||
2435 | pname++; | ||
2436 | |||
2437 | /* Find Selected File. */ | ||
2438 | for(i = 0; i < entries; i++) | ||
2439 | if(!rb->strcmp(file_pt[i], pname)) | ||
2440 | curfile = i; | ||
2441 | } | ||
2442 | |||
2443 | int change_filename(int direct) | ||
2444 | { | ||
2445 | int count = 0; | ||
2446 | direction = direct; | ||
2447 | |||
2448 | if(direct == DIR_PREV) | ||
2449 | { | ||
2450 | do | ||
2451 | { | ||
2452 | count++; | ||
2453 | if(curfile == 0) | ||
2454 | curfile = entries - 1; | ||
2455 | else | ||
2456 | curfile--; | ||
2457 | }while(file_pt[curfile] == '\0' && count < entries); | ||
2458 | /* we "erase" the file name if we encounter | ||
2459 | * a non-supported file, so skip it now */ | ||
2460 | } | ||
2461 | else /* DIR_NEXT/DIR_NONE */ | ||
2462 | { | ||
2463 | do | ||
2464 | { | ||
2465 | count++; | ||
2466 | if(curfile == entries - 1) | ||
2467 | curfile = 0; | ||
2468 | else | ||
2469 | curfile++; | ||
2470 | }while(file_pt[curfile] == '\0' && count < entries); | ||
2471 | } | ||
2472 | |||
2473 | if(count == entries && file_pt[curfile] == '\0') | ||
2474 | { | ||
2475 | rb->splash(HZ, "No supported files"); | ||
2476 | return PLUGIN_ERROR; | ||
2477 | } | ||
2478 | if(rb->strlen(tree->currdir) > 1) | ||
2479 | { | ||
2480 | rb->strcpy(np_file, tree->currdir); | ||
2481 | rb->strcat(np_file, "/"); | ||
2482 | } | ||
2483 | else | ||
2484 | rb->strcpy(np_file, tree->currdir); | ||
2485 | |||
2486 | rb->strcat(np_file, file_pt[curfile]); | ||
2487 | |||
2488 | return PLUGIN_OTHER; | ||
2489 | } | ||
2490 | |||
2491 | /* switch off overlay, for handling SYS_ events */ | ||
2492 | void cleanup(void *parameter) | ||
2493 | { | ||
2494 | (void)parameter; | ||
2495 | #ifdef USEGSLIB | ||
2496 | grey_show(false); | ||
2497 | #endif | ||
2498 | } | ||
2499 | |||
2500 | #define VSCROLL (LCD_HEIGHT/8) | ||
2501 | #define HSCROLL (LCD_WIDTH/10) | ||
2502 | |||
2503 | #define ZOOM_IN 100 /* return codes for below function */ | ||
2504 | #define ZOOM_OUT 101 | ||
2505 | |||
2506 | #ifdef HAVE_LCD_COLOR | ||
2507 | bool set_option_grayscale(void) | ||
2508 | { | ||
2509 | bool gray = jpeg_settings.colour_mode == COLOURMODE_GRAY; | ||
2510 | rb->set_bool("Grayscale", &gray); | ||
2511 | jpeg_settings.colour_mode = gray ? COLOURMODE_GRAY : COLOURMODE_COLOUR; | ||
2512 | return false; | ||
2513 | } | ||
2514 | |||
2515 | bool set_option_dithering(void) | ||
2516 | { | ||
2517 | static const struct opt_items dithering[DITHER_NUM_MODES] = { | ||
2518 | [DITHER_NONE] = { "Off", -1 }, | ||
2519 | [DITHER_ORDERED] = { "Ordered", -1 }, | ||
2520 | [DITHER_DIFFUSION] = { "Diffusion", -1 }, | ||
2521 | }; | ||
2522 | |||
2523 | rb->set_option("Dithering", &jpeg_settings.dither_mode, INT, | ||
2524 | dithering, DITHER_NUM_MODES, NULL); | ||
2525 | return false; | ||
2526 | } | ||
2527 | |||
2528 | static void display_options(void) | ||
2529 | { | ||
2530 | static const struct menu_item items[] = { | ||
2531 | { "Grayscale", set_option_grayscale }, | ||
2532 | { "Dithering", set_option_dithering }, | ||
2533 | }; | ||
2534 | |||
2535 | int m = menu_init(rb, items, ARRAYLEN(items), | ||
2536 | NULL, NULL, NULL, NULL); | ||
2537 | menu_run(m); | ||
2538 | menu_exit(m); | ||
2539 | } | ||
2540 | #endif /* HAVE_LCD_COLOR */ | ||
2541 | |||
2542 | int show_menu(void) /* return 1 to quit */ | ||
2543 | { | ||
2544 | #if LCD_DEPTH > 1 | ||
2545 | rb->lcd_set_backdrop(old_backdrop); | ||
2546 | #ifdef HAVE_LCD_COLOR | ||
2547 | rb->lcd_set_foreground(rb->global_settings->fg_color); | ||
2548 | rb->lcd_set_background(rb->global_settings->bg_color); | ||
2549 | #else | ||
2550 | rb->lcd_set_foreground(LCD_BLACK); | ||
2551 | rb->lcd_set_background(LCD_WHITE); | ||
2552 | #endif | ||
2553 | #endif | ||
2554 | int m; | ||
2555 | int result; | ||
2556 | |||
2557 | enum menu_id | ||
2558 | { | ||
2559 | MIID_QUIT = 0, | ||
2560 | MIID_TOGGLE_SS_MODE, | ||
2561 | MIID_CHANGE_SS_MODE, | ||
2562 | #if PLUGIN_BUFFER_SIZE >= MIN_MEM | ||
2563 | MIID_SHOW_PLAYBACK_MENU, | ||
2564 | #endif | ||
2565 | #ifdef HAVE_LCD_COLOR | ||
2566 | MIID_DISPLAY_OPTIONS, | ||
2567 | #endif | ||
2568 | MIID_RETURN, | ||
2569 | }; | ||
2570 | |||
2571 | static const struct menu_item items[] = { | ||
2572 | [MIID_QUIT] = | ||
2573 | { "Quit", NULL }, | ||
2574 | [MIID_TOGGLE_SS_MODE] = | ||
2575 | { "Toggle Slideshow Mode", NULL }, | ||
2576 | [MIID_CHANGE_SS_MODE] = | ||
2577 | { "Change Slideshow Time", NULL }, | ||
2578 | #if PLUGIN_BUFFER_SIZE >= MIN_MEM | ||
2579 | [MIID_SHOW_PLAYBACK_MENU] = | ||
2580 | { "Show Playback Menu", NULL }, | ||
2581 | #endif | ||
2582 | #ifdef HAVE_LCD_COLOR | ||
2583 | [MIID_DISPLAY_OPTIONS] = | ||
2584 | { "Display Options", NULL }, | ||
2585 | #endif | ||
2586 | [MIID_RETURN] = | ||
2587 | { "Return", NULL }, | ||
2588 | }; | ||
2589 | |||
2590 | static const struct opt_items slideshow[2] = { | ||
2591 | { "Disable", -1 }, | ||
2592 | { "Enable", -1 }, | ||
2593 | }; | ||
2594 | |||
2595 | m = menu_init(rb, items, sizeof(items) / sizeof(*items), | ||
2596 | NULL, NULL, NULL, NULL); | ||
2597 | result=menu_show(m); | ||
2598 | |||
2599 | switch (result) | ||
2600 | { | ||
2601 | case MIID_QUIT: | ||
2602 | menu_exit(m); | ||
2603 | return 1; | ||
2604 | break; | ||
2605 | case MIID_TOGGLE_SS_MODE: | ||
2606 | rb->set_option("Toggle Slideshow", &slideshow_enabled, INT, | ||
2607 | slideshow , 2, NULL); | ||
2608 | break; | ||
2609 | case MIID_CHANGE_SS_MODE: | ||
2610 | rb->set_int("Slideshow Time", "s", UNIT_SEC, | ||
2611 | &jpeg_settings.ss_timeout, NULL, 1, | ||
2612 | SS_MIN_TIMEOUT, SS_MAX_TIMEOUT, NULL); | ||
2613 | break; | ||
2614 | |||
2615 | #if PLUGIN_BUFFER_SIZE >= MIN_MEM | ||
2616 | case MIID_SHOW_PLAYBACK_MENU: | ||
2617 | if (plug_buf) | ||
2618 | { | ||
2619 | playback_control(rb, NULL); | ||
2620 | } | ||
2621 | else | ||
2622 | { | ||
2623 | rb->splash(HZ, "Cannot restart playback"); | ||
2624 | } | ||
2625 | break; | ||
2626 | #endif | ||
2627 | #ifdef HAVE_LCD_COLOR | ||
2628 | case MIID_DISPLAY_OPTIONS: | ||
2629 | display_options(); | ||
2630 | break; | ||
2631 | #endif | ||
2632 | case MIID_RETURN: | ||
2633 | break; | ||
2634 | } | ||
2635 | |||
2636 | #if !defined(SIMULATOR) && defined(HAVE_DISK_STORAGE) | ||
2637 | /* change ata spindown time based on slideshow time setting */ | ||
2638 | immediate_ata_off = false; | ||
2639 | rb->ata_spindown(rb->global_settings->disk_spindown); | ||
2640 | |||
2641 | if (slideshow_enabled) | ||
2642 | { | ||
2643 | if(jpeg_settings.ss_timeout < 10) | ||
2644 | { | ||
2645 | /* slideshow times < 10s keep disk spinning */ | ||
2646 | rb->ata_spindown(0); | ||
2647 | } | ||
2648 | else if (!rb->mp3_is_playing()) | ||
2649 | { | ||
2650 | /* slideshow times > 10s and not playing: ata_off after load */ | ||
2651 | immediate_ata_off = true; | ||
2652 | } | ||
2653 | } | ||
2654 | #endif | ||
2655 | #if LCD_DEPTH > 1 | ||
2656 | rb->lcd_set_backdrop(NULL); | ||
2657 | rb->lcd_set_foreground(LCD_WHITE); | ||
2658 | rb->lcd_set_background(LCD_BLACK); | ||
2659 | #endif | ||
2660 | rb->lcd_clear_display(); | ||
2661 | menu_exit(m); | ||
2662 | return 0; | ||
2663 | } | ||
2664 | /* interactively scroll around the image */ | ||
2665 | int scroll_bmp(struct t_disp* pdisp) | ||
2666 | { | ||
2667 | int lastbutton = 0; | ||
2668 | |||
2669 | while (true) | ||
2670 | { | ||
2671 | int button; | ||
2672 | int move; | ||
2673 | |||
2674 | if (slideshow_enabled) | ||
2675 | button = rb->button_get_w_tmo(jpeg_settings.ss_timeout * HZ); | ||
2676 | else button = rb->button_get(true); | ||
2677 | |||
2678 | running_slideshow = false; | ||
2679 | |||
2680 | switch(button) | ||
2681 | { | ||
2682 | case JPEG_LEFT: | ||
2683 | if (!(ds < ds_max) && entries > 0 && jpg.x_size <= MAX_X_SIZE) | ||
2684 | return change_filename(DIR_PREV); | ||
2685 | case JPEG_LEFT | BUTTON_REPEAT: | ||
2686 | move = MIN(HSCROLL, pdisp->x); | ||
2687 | if (move > 0) | ||
2688 | { | ||
2689 | MYXLCD(scroll_right)(move); /* scroll right */ | ||
2690 | pdisp->x -= move; | ||
2691 | #ifdef HAVE_LCD_COLOR | ||
2692 | yuv_bitmap_part( | ||
2693 | pdisp->bitmap, pdisp->csub_x, pdisp->csub_y, | ||
2694 | pdisp->x, pdisp->y, pdisp->stride, | ||
2695 | 0, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */ | ||
2696 | move, MIN(LCD_HEIGHT, pdisp->height)); /* w, h */ | ||
2697 | #else | ||
2698 | MYXLCD(gray_bitmap_part)( | ||
2699 | pdisp->bitmap[0], pdisp->x, pdisp->y, pdisp->stride, | ||
2700 | 0, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */ | ||
2701 | move, MIN(LCD_HEIGHT, pdisp->height)); /* w, h */ | ||
2702 | #endif | ||
2703 | MYLCD_UPDATE(); | ||
2704 | } | ||
2705 | break; | ||
2706 | |||
2707 | case JPEG_RIGHT: | ||
2708 | if (!(ds < ds_max) && entries > 0 && jpg.x_size <= MAX_X_SIZE) | ||
2709 | return change_filename(DIR_NEXT); | ||
2710 | case JPEG_RIGHT | BUTTON_REPEAT: | ||
2711 | move = MIN(HSCROLL, pdisp->width - pdisp->x - LCD_WIDTH); | ||
2712 | if (move > 0) | ||
2713 | { | ||
2714 | MYXLCD(scroll_left)(move); /* scroll left */ | ||
2715 | pdisp->x += move; | ||
2716 | #ifdef HAVE_LCD_COLOR | ||
2717 | yuv_bitmap_part( | ||
2718 | pdisp->bitmap, pdisp->csub_x, pdisp->csub_y, | ||
2719 | pdisp->x + LCD_WIDTH - move, pdisp->y, pdisp->stride, | ||
2720 | LCD_WIDTH - move, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */ | ||
2721 | move, MIN(LCD_HEIGHT, pdisp->height)); /* w, h */ | ||
2722 | #else | ||
2723 | MYXLCD(gray_bitmap_part)( | ||
2724 | pdisp->bitmap[0], pdisp->x + LCD_WIDTH - move, | ||
2725 | pdisp->y, pdisp->stride, | ||
2726 | LCD_WIDTH - move, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */ | ||
2727 | move, MIN(LCD_HEIGHT, pdisp->height)); /* w, h */ | ||
2728 | #endif | ||
2729 | MYLCD_UPDATE(); | ||
2730 | } | ||
2731 | break; | ||
2732 | |||
2733 | case JPEG_UP: | ||
2734 | case JPEG_UP | BUTTON_REPEAT: | ||
2735 | move = MIN(VSCROLL, pdisp->y); | ||
2736 | if (move > 0) | ||
2737 | { | ||
2738 | MYXLCD(scroll_down)(move); /* scroll down */ | ||
2739 | pdisp->y -= move; | ||
2740 | #ifdef HAVE_LCD_COLOR | ||
2741 | if (jpeg_settings.dither_mode == DITHER_DIFFUSION) | ||
2742 | { | ||
2743 | /* Draw over the band at the top of the last update | ||
2744 | caused by lack of error history on line zero. */ | ||
2745 | move = MIN(move + 1, pdisp->y + pdisp->height); | ||
2746 | } | ||
2747 | |||
2748 | yuv_bitmap_part( | ||
2749 | pdisp->bitmap, pdisp->csub_x, pdisp->csub_y, | ||
2750 | pdisp->x, pdisp->y, pdisp->stride, | ||
2751 | MAX(0, (LCD_WIDTH-pdisp->width)/2), 0, /* x, y */ | ||
2752 | MIN(LCD_WIDTH, pdisp->width), move); /* w, h */ | ||
2753 | #else | ||
2754 | MYXLCD(gray_bitmap_part)( | ||
2755 | pdisp->bitmap[0], pdisp->x, pdisp->y, pdisp->stride, | ||
2756 | MAX(0, (LCD_WIDTH-pdisp->width)/2), 0, /* x, y */ | ||
2757 | MIN(LCD_WIDTH, pdisp->width), move); /* w, h */ | ||
2758 | #endif | ||
2759 | MYLCD_UPDATE(); | ||
2760 | } | ||
2761 | break; | ||
2762 | |||
2763 | case JPEG_DOWN: | ||
2764 | case JPEG_DOWN | BUTTON_REPEAT: | ||
2765 | move = MIN(VSCROLL, pdisp->height - pdisp->y - LCD_HEIGHT); | ||
2766 | if (move > 0) | ||
2767 | { | ||
2768 | MYXLCD(scroll_up)(move); /* scroll up */ | ||
2769 | pdisp->y += move; | ||
2770 | #ifdef HAVE_LCD_COLOR | ||
2771 | if (jpeg_settings.dither_mode == DITHER_DIFFUSION) | ||
2772 | { | ||
2773 | /* Save the line that was on the last line of the display | ||
2774 | and draw one extra line above then recover the line with | ||
2775 | image data that had an error history when it was drawn. | ||
2776 | */ | ||
2777 | move++, pdisp->y--; | ||
2778 | MEMCPY(rgb_linebuf, | ||
2779 | rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH, | ||
2780 | LCD_WIDTH*sizeof (fb_data)); | ||
2781 | } | ||
2782 | |||
2783 | yuv_bitmap_part( | ||
2784 | pdisp->bitmap, pdisp->csub_x, pdisp->csub_y, pdisp->x, | ||
2785 | pdisp->y + LCD_HEIGHT - move, pdisp->stride, | ||
2786 | MAX(0, (LCD_WIDTH-pdisp->width)/2), LCD_HEIGHT - move, /* x, y */ | ||
2787 | MIN(LCD_WIDTH, pdisp->width), move); /* w, h */ | ||
2788 | |||
2789 | if (jpeg_settings.dither_mode == DITHER_DIFFUSION) | ||
2790 | { | ||
2791 | /* Cover the first row drawn with previous image data. */ | ||
2792 | MEMCPY(rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH, | ||
2793 | rgb_linebuf, | ||
2794 | LCD_WIDTH*sizeof (fb_data)); | ||
2795 | pdisp->y++; | ||
2796 | } | ||
2797 | #else | ||
2798 | MYXLCD(gray_bitmap_part)( | ||
2799 | pdisp->bitmap[0], pdisp->x, | ||
2800 | pdisp->y + LCD_HEIGHT - move, pdisp->stride, | ||
2801 | MAX(0, (LCD_WIDTH-pdisp->width)/2), LCD_HEIGHT - move, /* x, y */ | ||
2802 | MIN(LCD_WIDTH, pdisp->width), move); /* w, h */ | ||
2803 | #endif | ||
2804 | MYLCD_UPDATE(); | ||
2805 | } | ||
2806 | break; | ||
2807 | case BUTTON_NONE: | ||
2808 | if (!slideshow_enabled) | ||
2809 | break; | ||
2810 | running_slideshow = true; | ||
2811 | if (entries > 0) | ||
2812 | return change_filename(DIR_NEXT); | ||
2813 | break; | ||
2814 | |||
2815 | #ifdef JPEG_SLIDE_SHOW | ||
2816 | case JPEG_SLIDE_SHOW: | ||
2817 | slideshow_enabled = !slideshow_enabled; | ||
2818 | running_slideshow = slideshow_enabled; | ||
2819 | break; | ||
2820 | #endif | ||
2821 | |||
2822 | #ifdef JPEG_NEXT_REPEAT | ||
2823 | case JPEG_NEXT_REPEAT: | ||
2824 | #endif | ||
2825 | case JPEG_NEXT: | ||
2826 | if (entries > 0) | ||
2827 | return change_filename(DIR_NEXT); | ||
2828 | break; | ||
2829 | |||
2830 | #ifdef JPEG_PREVIOUS_REPEAT | ||
2831 | case JPEG_PREVIOUS_REPEAT: | ||
2832 | #endif | ||
2833 | case JPEG_PREVIOUS: | ||
2834 | if (entries > 0) | ||
2835 | return change_filename(DIR_PREV); | ||
2836 | break; | ||
2837 | |||
2838 | case JPEG_ZOOM_IN: | ||
2839 | #ifdef JPEG_ZOOM_PRE | ||
2840 | if (lastbutton != JPEG_ZOOM_PRE) | ||
2841 | break; | ||
2842 | #endif | ||
2843 | return ZOOM_IN; | ||
2844 | break; | ||
2845 | |||
2846 | case JPEG_ZOOM_OUT: | ||
2847 | #ifdef JPEG_ZOOM_PRE | ||
2848 | if (lastbutton != JPEG_ZOOM_PRE) | ||
2849 | break; | ||
2850 | #endif | ||
2851 | return ZOOM_OUT; | ||
2852 | break; | ||
2853 | #ifdef JPEG_RC_MENU | ||
2854 | case JPEG_RC_MENU: | ||
2855 | #endif | ||
2856 | case JPEG_MENU: | ||
2857 | #ifdef USEGSLIB | ||
2858 | grey_show(false); /* switch off greyscale overlay */ | ||
2859 | #endif | ||
2860 | if (show_menu() == 1) | ||
2861 | return PLUGIN_OK; | ||
2862 | |||
2863 | #ifdef USEGSLIB | ||
2864 | grey_show(true); /* switch on greyscale overlay */ | ||
2865 | #else | ||
2866 | yuv_bitmap_part( | ||
2867 | pdisp->bitmap, pdisp->csub_x, pdisp->csub_y, | ||
2868 | pdisp->x, pdisp->y, pdisp->stride, | ||
2869 | MAX(0, (LCD_WIDTH - pdisp->width) / 2), | ||
2870 | MAX(0, (LCD_HEIGHT - pdisp->height) / 2), | ||
2871 | MIN(LCD_WIDTH, pdisp->width), | ||
2872 | MIN(LCD_HEIGHT, pdisp->height)); | ||
2873 | MYLCD_UPDATE(); | ||
2874 | #endif | ||
2875 | break; | ||
2876 | default: | ||
2877 | if (rb->default_event_handler_ex(button, cleanup, NULL) | ||
2878 | == SYS_USB_CONNECTED) | ||
2879 | return PLUGIN_USB_CONNECTED; | ||
2880 | break; | ||
2881 | |||
2882 | } /* switch */ | ||
2883 | |||
2884 | if (button != BUTTON_NONE) | ||
2885 | lastbutton = button; | ||
2886 | } /* while (true) */ | ||
2887 | } | ||
2888 | |||
2889 | /********************* main function *************************/ | ||
2890 | |||
2891 | /* callback updating a progress meter while JPEG decoding */ | ||
2892 | void cb_progess(int current, int total) | ||
2893 | { | ||
2894 | rb->yield(); /* be nice to the other threads */ | ||
2895 | if(!running_slideshow) | ||
2896 | { | ||
2897 | rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN],0, LCD_HEIGHT-8, LCD_WIDTH, 8, total, 0, | ||
2898 | current, HORIZONTAL); | ||
2899 | rb->lcd_update_rect(0, LCD_HEIGHT-8, LCD_WIDTH, 8); | ||
2900 | } | ||
2901 | #ifndef USEGSLIB | ||
2902 | else | ||
2903 | { | ||
2904 | /* in slideshow mode, keep gui interference to a minimum */ | ||
2905 | rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN],0, LCD_HEIGHT-4, LCD_WIDTH, 4, total, 0, | ||
2906 | current, HORIZONTAL); | ||
2907 | rb->lcd_update_rect(0, LCD_HEIGHT-4, LCD_WIDTH, 4); | ||
2908 | } | ||
2909 | #endif | ||
2910 | } | ||
2911 | |||
2912 | int jpegmem(struct jpeg *p_jpg, int ds) | ||
2913 | { | ||
2914 | int size; | ||
2915 | |||
2916 | size = (p_jpg->x_phys/ds/p_jpg->subsample_x[0]) | ||
2917 | * (p_jpg->y_phys/ds/p_jpg->subsample_y[0]); | ||
2918 | #ifdef HAVE_LCD_COLOR | ||
2919 | if (p_jpg->blocks > 1) /* colour, add requirements for chroma */ | ||
2920 | { | ||
2921 | size += (p_jpg->x_phys/ds/p_jpg->subsample_x[1]) | ||
2922 | * (p_jpg->y_phys/ds/p_jpg->subsample_y[1]); | ||
2923 | size += (p_jpg->x_phys/ds/p_jpg->subsample_x[2]) | ||
2924 | * (p_jpg->y_phys/ds/p_jpg->subsample_y[2]); | ||
2925 | } | ||
2926 | #endif | ||
2927 | return size; | ||
2928 | } | ||
2929 | |||
2930 | /* how far can we zoom in without running out of memory */ | ||
2931 | int min_downscale(struct jpeg *p_jpg, int bufsize) | ||
2932 | { | ||
2933 | int downscale = 8; | ||
2934 | |||
2935 | if (jpegmem(p_jpg, 8) > bufsize) | ||
2936 | return 0; /* error, too large, even 1:8 doesn't fit */ | ||
2937 | |||
2938 | while (downscale > 1 && jpegmem(p_jpg, downscale/2) <= bufsize) | ||
2939 | downscale /= 2; | ||
2940 | |||
2941 | return downscale; | ||
2942 | } | ||
2943 | |||
2944 | |||
2945 | /* how far can we zoom out, to fit image into the LCD */ | ||
2946 | int max_downscale(struct jpeg *p_jpg) | ||
2947 | { | ||
2948 | int downscale = 1; | ||
2949 | |||
2950 | while (downscale < 8 && (p_jpg->x_size > LCD_WIDTH*downscale | ||
2951 | || p_jpg->y_size > LCD_HEIGHT*downscale)) | ||
2952 | { | ||
2953 | downscale *= 2; | ||
2954 | } | ||
2955 | |||
2956 | return downscale; | ||
2957 | } | ||
2958 | |||
2959 | |||
2960 | /* return decoded or cached image */ | ||
2961 | struct t_disp* get_image(struct jpeg* p_jpg, int ds) | ||
2962 | { | ||
2963 | int w, h; /* used to center output */ | ||
2964 | int size; /* decompressed image size */ | ||
2965 | long time; /* measured ticks */ | ||
2966 | int status; | ||
2967 | |||
2968 | struct t_disp* p_disp = &disp[ds]; /* short cut */ | ||
2969 | |||
2970 | if (p_disp->bitmap[0] != NULL) | ||
2971 | { | ||
2972 | return p_disp; /* we still have it */ | ||
2973 | } | ||
2974 | |||
2975 | /* assign image buffer */ | ||
2976 | |||
2977 | /* physical size needed for decoding */ | ||
2978 | size = jpegmem(p_jpg, ds); | ||
2979 | if (buf_size <= size) | ||
2980 | { /* have to discard the current */ | ||
2981 | int i; | ||
2982 | for (i=1; i<=8; i++) | ||
2983 | disp[i].bitmap[0] = NULL; /* invalidate all bitmaps */ | ||
2984 | buf = buf_root; /* start again from the beginning of the buffer */ | ||
2985 | buf_size = root_size; | ||
2986 | } | ||
2987 | |||
2988 | #ifdef HAVE_LCD_COLOR | ||
2989 | if (p_jpg->blocks > 1) /* colour jpeg */ | ||
2990 | { | ||
2991 | int i; | ||
2992 | |||
2993 | for (i = 1; i < 3; i++) | ||
2994 | { | ||
2995 | size = (p_jpg->x_phys / ds / p_jpg->subsample_x[i]) | ||
2996 | * (p_jpg->y_phys / ds / p_jpg->subsample_y[i]); | ||
2997 | p_disp->bitmap[i] = buf; | ||
2998 | buf += size; | ||
2999 | buf_size -= size; | ||
3000 | } | ||
3001 | p_disp->csub_x = p_jpg->subsample_x[1]; | ||
3002 | p_disp->csub_y = p_jpg->subsample_y[1]; | ||
3003 | } | ||
3004 | else | ||
3005 | { | ||
3006 | p_disp->csub_x = p_disp->csub_y = 0; | ||
3007 | p_disp->bitmap[1] = p_disp->bitmap[2] = buf; | ||
3008 | } | ||
3009 | #endif | ||
3010 | /* size may be less when decoded (if height is not block aligned) */ | ||
3011 | size = (p_jpg->x_phys/ds) * (p_jpg->y_size / ds); | ||
3012 | p_disp->bitmap[0] = buf; | ||
3013 | buf += size; | ||
3014 | buf_size -= size; | ||
3015 | |||
3016 | if(!running_slideshow) | ||
3017 | { | ||
3018 | rb->snprintf(print, sizeof(print), "decoding %d*%d", | ||
3019 | p_jpg->x_size/ds, p_jpg->y_size/ds); | ||
3020 | rb->lcd_puts(0, 3, print); | ||
3021 | rb->lcd_update(); | ||
3022 | } | ||
3023 | |||
3024 | /* update image properties */ | ||
3025 | p_disp->width = p_jpg->x_size / ds; | ||
3026 | p_disp->stride = p_jpg->x_phys / ds; /* use physical size for stride */ | ||
3027 | p_disp->height = p_jpg->y_size / ds; | ||
3028 | |||
3029 | /* the actual decoding */ | ||
3030 | time = *rb->current_tick; | ||
3031 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | ||
3032 | rb->cpu_boost(true); | ||
3033 | status = jpeg_decode(p_jpg, p_disp->bitmap, ds, cb_progess); | ||
3034 | rb->cpu_boost(false); | ||
3035 | #else | ||
3036 | status = jpeg_decode(p_jpg, p_disp->bitmap, ds, cb_progess); | ||
3037 | #endif | ||
3038 | if (status) | ||
3039 | { | ||
3040 | rb->splashf(HZ, "decode error %d", status); | ||
3041 | file_pt[curfile] = '\0'; | ||
3042 | return NULL; | ||
3043 | } | ||
3044 | time = *rb->current_tick - time; | ||
3045 | |||
3046 | if(!running_slideshow) | ||
3047 | { | ||
3048 | rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ); | ||
3049 | rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */ | ||
3050 | rb->lcd_putsxy((LCD_WIDTH - w)/2, LCD_HEIGHT - h, print); | ||
3051 | rb->lcd_update(); | ||
3052 | } | ||
3053 | |||
3054 | return p_disp; | ||
3055 | } | ||
3056 | |||
3057 | |||
3058 | /* set the view to the given center point, limit if necessary */ | ||
3059 | void set_view (struct t_disp* p_disp, int cx, int cy) | ||
3060 | { | ||
3061 | int x, y; | ||
3062 | |||
3063 | /* plain center to available width/height */ | ||
3064 | x = cx - MIN(LCD_WIDTH, p_disp->width) / 2; | ||
3065 | y = cy - MIN(LCD_HEIGHT, p_disp->height) / 2; | ||
3066 | |||
3067 | /* limit against upper image size */ | ||
3068 | x = MIN(p_disp->width - LCD_WIDTH, x); | ||
3069 | y = MIN(p_disp->height - LCD_HEIGHT, y); | ||
3070 | |||
3071 | /* limit against negative side */ | ||
3072 | x = MAX(0, x); | ||
3073 | y = MAX(0, y); | ||
3074 | |||
3075 | p_disp->x = x; /* set the values */ | ||
3076 | p_disp->y = y; | ||
3077 | } | ||
3078 | |||
3079 | |||
3080 | /* calculate the view center based on the bitmap position */ | ||
3081 | void get_view(struct t_disp* p_disp, int* p_cx, int* p_cy) | ||
3082 | { | ||
3083 | *p_cx = p_disp->x + MIN(LCD_WIDTH, p_disp->width) / 2; | ||
3084 | *p_cy = p_disp->y + MIN(LCD_HEIGHT, p_disp->height) / 2; | ||
3085 | } | ||
3086 | |||
3087 | |||
3088 | /* load, decode, display the image */ | ||
3089 | int load_and_show(char* filename) | ||
3090 | { | ||
3091 | int fd; | ||
3092 | int filesize; | ||
3093 | unsigned char* buf_jpeg; /* compressed JPEG image */ | ||
3094 | int status; | ||
3095 | struct t_disp* p_disp; /* currenly displayed image */ | ||
3096 | int cx, cy; /* view center */ | ||
3097 | |||
3098 | fd = rb->open(filename, O_RDONLY); | ||
3099 | if (fd < 0) | ||
3100 | { | ||
3101 | rb->snprintf(print,sizeof(print),"err opening %s:%d",filename,fd); | ||
3102 | rb->splash(HZ, print); | ||
3103 | return PLUGIN_ERROR; | ||
3104 | } | ||
3105 | filesize = rb->filesize(fd); | ||
3106 | rb->memset(&disp, 0, sizeof(disp)); | ||
3107 | |||
3108 | buf = buf_images + filesize; | ||
3109 | buf_size = buf_images_size - filesize; | ||
3110 | /* allocate JPEG buffer */ | ||
3111 | buf_jpeg = buf_images; | ||
3112 | |||
3113 | buf_root = buf; /* we can start the decompressed images behind it */ | ||
3114 | root_size = buf_size; | ||
3115 | |||
3116 | if (buf_size <= 0) | ||
3117 | { | ||
3118 | #if PLUGIN_BUFFER_SIZE >= MIN_MEM | ||
3119 | if(plug_buf) | ||
3120 | { | ||
3121 | rb->close(fd); | ||
3122 | rb->lcd_setfont(FONT_SYSFIXED); | ||
3123 | rb->lcd_clear_display(); | ||
3124 | rb->snprintf(print,sizeof(print),"%s:",rb->strrchr(filename,'/')+1); | ||
3125 | rb->lcd_puts(0,0,print); | ||
3126 | rb->lcd_puts(0,1,"Not enough plugin memory!"); | ||
3127 | rb->lcd_puts(0,2,"Zoom In: Stop playback."); | ||
3128 | if(entries>1) | ||
3129 | rb->lcd_puts(0,3,"Left/Right: Skip File."); | ||
3130 | rb->lcd_puts(0,4,"Off: Quit."); | ||
3131 | rb->lcd_update(); | ||
3132 | rb->lcd_setfont(FONT_UI); | ||
3133 | |||
3134 | rb->button_clear_queue(); | ||
3135 | |||
3136 | while (1) | ||
3137 | { | ||
3138 | int button = rb->button_get(true); | ||
3139 | switch(button) | ||
3140 | { | ||
3141 | case JPEG_ZOOM_IN: | ||
3142 | plug_buf = false; | ||
3143 | buf_images = rb->plugin_get_audio_buffer( | ||
3144 | (size_t *)&buf_images_size); | ||
3145 | /*try again this file, now using the audio buffer */ | ||
3146 | return PLUGIN_OTHER; | ||
3147 | #ifdef JPEG_RC_MENU | ||
3148 | case JPEG_RC_MENU: | ||
3149 | #endif | ||
3150 | case JPEG_MENU: | ||
3151 | return PLUGIN_OK; | ||
3152 | |||
3153 | case JPEG_LEFT: | ||
3154 | if(entries>1) | ||
3155 | { | ||
3156 | rb->lcd_clear_display(); | ||
3157 | return change_filename(DIR_PREV); | ||
3158 | } | ||
3159 | break; | ||
3160 | |||
3161 | case JPEG_RIGHT: | ||
3162 | if(entries>1) | ||
3163 | { | ||
3164 | rb->lcd_clear_display(); | ||
3165 | return change_filename(DIR_NEXT); | ||
3166 | } | ||
3167 | break; | ||
3168 | default: | ||
3169 | if(rb->default_event_handler_ex(button, cleanup, NULL) | ||
3170 | == SYS_USB_CONNECTED) | ||
3171 | return PLUGIN_USB_CONNECTED; | ||
3172 | |||
3173 | } | ||
3174 | } | ||
3175 | } | ||
3176 | else | ||
3177 | #endif | ||
3178 | { | ||
3179 | rb->splash(HZ, "Out of Memory"); | ||
3180 | rb->close(fd); | ||
3181 | return PLUGIN_ERROR; | ||
3182 | } | ||
3183 | } | ||
3184 | |||
3185 | if(!running_slideshow) | ||
3186 | { | ||
3187 | #if LCD_DEPTH > 1 | ||
3188 | rb->lcd_set_foreground(LCD_WHITE); | ||
3189 | rb->lcd_set_background(LCD_BLACK); | ||
3190 | rb->lcd_set_backdrop(NULL); | ||
3191 | #endif | ||
3192 | |||
3193 | rb->lcd_clear_display(); | ||
3194 | rb->snprintf(print, sizeof(print), "%s:", rb->strrchr(filename,'/')+1); | ||
3195 | rb->lcd_puts(0, 0, print); | ||
3196 | rb->lcd_update(); | ||
3197 | |||
3198 | rb->snprintf(print, sizeof(print), "loading %d bytes", filesize); | ||
3199 | rb->lcd_puts(0, 1, print); | ||
3200 | rb->lcd_update(); | ||
3201 | } | ||
3202 | |||
3203 | rb->read(fd, buf_jpeg, filesize); | ||
3204 | rb->close(fd); | ||
3205 | |||
3206 | if(!running_slideshow) | ||
3207 | { | ||
3208 | rb->snprintf(print, sizeof(print), "decoding markers"); | ||
3209 | rb->lcd_puts(0, 2, print); | ||
3210 | rb->lcd_update(); | ||
3211 | } | ||
3212 | #ifndef SIMULATOR | ||
3213 | else if(immediate_ata_off) | ||
3214 | { | ||
3215 | /* running slideshow and time is long enough: power down disk */ | ||
3216 | rb->ata_sleep(); | ||
3217 | } | ||
3218 | #endif | ||
3219 | |||
3220 | rb->memset(&jpg, 0, sizeof(jpg)); /* clear info struct */ | ||
3221 | /* process markers, unstuffing */ | ||
3222 | status = process_markers(buf_jpeg, filesize, &jpg); | ||
3223 | |||
3224 | if (status < 0 || (status & (DQT | SOF0)) != (DQT | SOF0)) | ||
3225 | { /* bad format or minimum components not contained */ | ||
3226 | rb->splashf(HZ, "unsupported %d", status); | ||
3227 | file_pt[curfile] = '\0'; | ||
3228 | return change_filename(direction); | ||
3229 | } | ||
3230 | |||
3231 | if (!(status & DHT)) /* if no Huffman table present: */ | ||
3232 | default_huff_tbl(&jpg); /* use default */ | ||
3233 | build_lut(&jpg); /* derive Huffman and other lookup-tables */ | ||
3234 | |||
3235 | if(!running_slideshow) | ||
3236 | { | ||
3237 | rb->snprintf(print, sizeof(print), "image %dx%d", jpg.x_size, jpg.y_size); | ||
3238 | rb->lcd_puts(0, 2, print); | ||
3239 | rb->lcd_update(); | ||
3240 | } | ||
3241 | ds_max = max_downscale(&jpg); /* check display constraint */ | ||
3242 | ds_min = min_downscale(&jpg, buf_size); /* check memory constraint */ | ||
3243 | if (ds_min == 0) | ||
3244 | { | ||
3245 | rb->splash(HZ, "too large"); | ||
3246 | file_pt[curfile] = '\0'; | ||
3247 | return change_filename(direction); | ||
3248 | } | ||
3249 | |||
3250 | ds = ds_max; /* initials setting */ | ||
3251 | cx = jpg.x_size/ds/2; /* center the view */ | ||
3252 | cy = jpg.y_size/ds/2; | ||
3253 | |||
3254 | do /* loop the image prepare and decoding when zoomed */ | ||
3255 | { | ||
3256 | p_disp = get_image(&jpg, ds); /* decode or fetch from cache */ | ||
3257 | if (p_disp == NULL) | ||
3258 | return change_filename(direction); | ||
3259 | |||
3260 | set_view(p_disp, cx, cy); | ||
3261 | |||
3262 | if(!running_slideshow) | ||
3263 | { | ||
3264 | rb->snprintf(print, sizeof(print), "showing %dx%d", | ||
3265 | p_disp->width, p_disp->height); | ||
3266 | rb->lcd_puts(0, 3, print); | ||
3267 | rb->lcd_update(); | ||
3268 | } | ||
3269 | MYLCD(clear_display)(); | ||
3270 | #ifdef HAVE_LCD_COLOR | ||
3271 | yuv_bitmap_part( | ||
3272 | p_disp->bitmap, p_disp->csub_x, p_disp->csub_y, | ||
3273 | p_disp->x, p_disp->y, p_disp->stride, | ||
3274 | MAX(0, (LCD_WIDTH - p_disp->width) / 2), | ||
3275 | MAX(0, (LCD_HEIGHT - p_disp->height) / 2), | ||
3276 | MIN(LCD_WIDTH, p_disp->width), | ||
3277 | MIN(LCD_HEIGHT, p_disp->height)); | ||
3278 | #else | ||
3279 | MYXLCD(gray_bitmap_part)( | ||
3280 | p_disp->bitmap[0], p_disp->x, p_disp->y, p_disp->stride, | ||
3281 | MAX(0, (LCD_WIDTH - p_disp->width) / 2), | ||
3282 | MAX(0, (LCD_HEIGHT - p_disp->height) / 2), | ||
3283 | MIN(LCD_WIDTH, p_disp->width), | ||
3284 | MIN(LCD_HEIGHT, p_disp->height)); | ||
3285 | #endif | ||
3286 | MYLCD_UPDATE(); | ||
3287 | |||
3288 | #ifdef USEGSLIB | ||
3289 | grey_show(true); /* switch on greyscale overlay */ | ||
3290 | #endif | ||
3291 | |||
3292 | /* drawing is now finished, play around with scrolling | ||
3293 | * until you press OFF or connect USB | ||
3294 | */ | ||
3295 | while (1) | ||
3296 | { | ||
3297 | status = scroll_bmp(p_disp); | ||
3298 | if (status == ZOOM_IN) | ||
3299 | { | ||
3300 | if (ds > ds_min) | ||
3301 | { | ||
3302 | ds /= 2; /* reduce downscaling to zoom in */ | ||
3303 | get_view(p_disp, &cx, &cy); | ||
3304 | cx *= 2; /* prepare the position in the new image */ | ||
3305 | cy *= 2; | ||
3306 | } | ||
3307 | else | ||
3308 | continue; | ||
3309 | } | ||
3310 | |||
3311 | if (status == ZOOM_OUT) | ||
3312 | { | ||
3313 | if (ds < ds_max) | ||
3314 | { | ||
3315 | ds *= 2; /* increase downscaling to zoom out */ | ||
3316 | get_view(p_disp, &cx, &cy); | ||
3317 | cx /= 2; /* prepare the position in the new image */ | ||
3318 | cy /= 2; | ||
3319 | } | ||
3320 | else | ||
3321 | continue; | ||
3322 | } | ||
3323 | break; | ||
3324 | } | ||
3325 | |||
3326 | #ifdef USEGSLIB | ||
3327 | grey_show(false); /* switch off overlay */ | ||
3328 | #endif | ||
3329 | rb->lcd_clear_display(); | ||
3330 | } | ||
3331 | while (status != PLUGIN_OK && status != PLUGIN_USB_CONNECTED | ||
3332 | && status != PLUGIN_OTHER); | ||
3333 | #ifdef USEGSLIB | ||
3334 | rb->lcd_update(); | ||
3335 | #endif | ||
3336 | return status; | ||
3337 | } | ||
3338 | |||
3339 | /******************** Plugin entry point *********************/ | ||
3340 | |||
3341 | enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter) | ||
3342 | { | ||
3343 | rb = api; | ||
3344 | |||
3345 | int condition; | ||
3346 | #ifdef USEGSLIB | ||
3347 | long greysize; /* helper */ | ||
3348 | #endif | ||
3349 | #if LCD_DEPTH > 1 | ||
3350 | old_backdrop = rb->lcd_get_backdrop(); | ||
3351 | #endif | ||
3352 | |||
3353 | if(!parameter) return PLUGIN_ERROR; | ||
3354 | |||
3355 | rb->strcpy(np_file, parameter); | ||
3356 | get_pic_list(); | ||
3357 | |||
3358 | if(!entries) return PLUGIN_ERROR; | ||
3359 | |||
3360 | #if (PLUGIN_BUFFER_SIZE >= MIN_MEM) && !defined(SIMULATOR) | ||
3361 | if(rb->audio_status()) | ||
3362 | { | ||
3363 | buf = rb->plugin_get_buffer((size_t *)&buf_size) + | ||
3364 | (entries * sizeof(char**)); | ||
3365 | buf_size -= (entries * sizeof(char**)); | ||
3366 | plug_buf = true; | ||
3367 | } | ||
3368 | else | ||
3369 | buf = rb->plugin_get_audio_buffer((size_t *)&buf_size); | ||
3370 | #else | ||
3371 | buf = rb->plugin_get_audio_buffer(&buf_size) + | ||
3372 | (entries * sizeof(char**)); | ||
3373 | buf_size -= (entries * sizeof(char**)); | ||
3374 | #endif | ||
3375 | |||
3376 | #ifdef USEGSLIB | ||
3377 | if (!grey_init(rb, buf, buf_size, GREY_ON_COP, | ||
3378 | LCD_WIDTH, LCD_HEIGHT, &greysize)) | ||
3379 | { | ||
3380 | rb->splash(HZ, "grey buf error"); | ||
3381 | return PLUGIN_ERROR; | ||
3382 | } | ||
3383 | buf += greysize; | ||
3384 | buf_size -= greysize; | ||
3385 | #else | ||
3386 | xlcd_init(rb); | ||
3387 | #endif | ||
3388 | |||
3389 | /* should be ok to just load settings since a parameter is present | ||
3390 | here and the drive should be spinning */ | ||
3391 | configfile_init(rb); | ||
3392 | configfile_load(JPEG_CONFIGFILE, jpeg_config, | ||
3393 | ARRAYLEN(jpeg_config), JPEG_SETTINGS_MINVERSION); | ||
3394 | old_settings = jpeg_settings; | ||
3395 | |||
3396 | buf_images = buf; buf_images_size = buf_size; | ||
3397 | |||
3398 | /* Turn off backlight timeout */ | ||
3399 | backlight_force_on(rb); /* backlight control in lib/helper.c */ | ||
3400 | |||
3401 | do | ||
3402 | { | ||
3403 | condition = load_and_show(np_file); | ||
3404 | }while (condition != PLUGIN_OK && condition != PLUGIN_USB_CONNECTED | ||
3405 | && condition != PLUGIN_ERROR); | ||
3406 | |||
3407 | if (rb->memcmp(&jpeg_settings, &old_settings, sizeof (jpeg_settings))) | ||
3408 | { | ||
3409 | /* Just in case drive has to spin, keep it from looking locked */ | ||
3410 | rb->splash(0, "Saving Settings"); | ||
3411 | configfile_save(JPEG_CONFIGFILE, jpeg_config, | ||
3412 | ARRAYLEN(jpeg_config), JPEG_SETTINGS_VERSION); | ||
3413 | } | ||
3414 | |||
3415 | #if !defined(SIMULATOR) && defined(HAVE_DISK_STORAGE) | ||
3416 | /* set back ata spindown time in case we changed it */ | ||
3417 | rb->ata_spindown(rb->global_settings->disk_spindown); | ||
3418 | #endif | ||
3419 | |||
3420 | /* Turn on backlight timeout (revert to settings) */ | ||
3421 | backlight_use_settings(rb); /* backlight control in lib/helper.c */ | ||
3422 | |||
3423 | #ifdef USEGSLIB | ||
3424 | grey_release(); /* deinitialize */ | ||
3425 | #endif | ||
3426 | |||
3427 | return condition; | ||
3428 | } | ||
3429 | |||
3430 | #endif /* HAVE_LCD_BITMAP */ | ||
diff --git a/apps/plugins/jpeg/Makefile b/apps/plugins/jpeg/Makefile new file mode 100644 index 0000000000..83207258b5 --- /dev/null +++ b/apps/plugins/jpeg/Makefile | |||
@@ -0,0 +1,75 @@ | |||
1 | # __________ __ ___. | ||
2 | # Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
3 | # Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
4 | # Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
5 | # Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
6 | # \/ \/ \/ \/ \/ | ||
7 | # $Id$ | ||
8 | # | ||
9 | |||
10 | INCLUDES = -I$(APPSDIR) -I.. -I. $(TARGET_INC) -I$(FIRMDIR)/include -I$(FIRMDIR)/export \ | ||
11 | -I$(FIRMDIR)/common -I$(FIRMDIR)/drivers -I$(OUTDIR) -I$(BUILDDIR) \ | ||
12 | -I$(BUILDDIR)/pluginbitmaps -I$(APPSDIR)/plugins/lib | ||
13 | CFLAGS = $(INCLUDES) $(GCCOPTS) $(TARGET) $(EXTRA_DEFINES) \ | ||
14 | -DTARGET_ID=$(TARGET_ID) -DMEM=${MEMORYSIZE} -DPLUGIN | ||
15 | |||
16 | ifdef APPEXTRA | ||
17 | INCLUDES += $(patsubst %,-I$(APPSDIR)/%,$(subst :, ,$(APPEXTRA))) | ||
18 | endif | ||
19 | |||
20 | LINKFILE := $(OBJDIR)/link.lds | ||
21 | DEPFILE = $(OBJDIR)/dep-jpeg | ||
22 | |||
23 | # This sets up 'SRC' based on the files mentioned in SOURCES | ||
24 | include $(TOOLSDIR)/makesrc.inc | ||
25 | |||
26 | SOURCES = $(SRC) | ||
27 | OBJS := $(SRC:%.c=$(OBJDIR)/%.o) | ||
28 | DIRS = . | ||
29 | |||
30 | ifndef SIMVER | ||
31 | LDS := ../plugin.lds | ||
32 | OUTPUT = $(OUTDIR)/jpeg.rock | ||
33 | else ## simulators | ||
34 | OUTPUT = $(OUTDIR)/jpeg.rock | ||
35 | endif | ||
36 | |||
37 | all: $(OUTPUT) | ||
38 | |||
39 | ifndef SIMVER | ||
40 | $(OBJDIR)/jpeg.elf: $(OBJS) $(LINKFILE) $(BITMAPLIBS) | ||
41 | $(call PRINTS,LD $(@F))$(CC) $(CFLAGS) -o $@ $(OBJS) -L$(BUILDDIR) -lplugin -lgcc \ | ||
42 | $(LINKBITMAPS) -T$(LINKFILE) -Wl,--gc-sections -Wl,-Map,$(OBJDIR)/jpeg.map | ||
43 | |||
44 | $(OUTPUT): $(OBJDIR)/jpeg.elf | ||
45 | $(call PRINTS,OBJCOPY $(@F))$(OC) -O binary $< $@ | ||
46 | else | ||
47 | ################################################### | ||
48 | # This is the SDL simulator version | ||
49 | |||
50 | $(OUTPUT): $(OBJS) | ||
51 | $(call PRINTS,LD $(@F))$(CC) $(CFLAGS) $(SHARED_FLAG) $(OBJS) -L$(BUILDDIR) -lplugin $(LINKBITMAPS) -o $@ | ||
52 | ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN) | ||
53 | # 'x' must be kept or you'll have "Win32 error 5" | ||
54 | # $ fgrep 5 /usr/include/w32api/winerror.h | head -1 | ||
55 | # #define ERROR_ACCESS_DENIED 5L | ||
56 | else | ||
57 | @chmod -x $@ | ||
58 | endif | ||
59 | |||
60 | endif # end of simulator section | ||
61 | |||
62 | |||
63 | include $(TOOLSDIR)/make.inc | ||
64 | |||
65 | # MEMORYSIZE should be passed on to this makefile with the chosen memory size | ||
66 | # given in number of MB | ||
67 | $(LINKFILE): $(LDS) | ||
68 | $(call PRINTS,build $(@F))cat $< | $(CC) -DMEMORYSIZE=$(MEMORYSIZE) $(INCLUDES) $(TARGET) \ | ||
69 | $(DEFINES) -E -P - >$@ | ||
70 | |||
71 | clean: | ||
72 | $(call PRINTS,cleaning jpeg)rm -rf $(OBJDIR)/jpeg | ||
73 | $(SILENT)rm -f $(OBJDIR)/jpeg.* $(DEPFILE) | ||
74 | |||
75 | -include $(DEPFILE) | ||
diff --git a/apps/plugins/jpeg/SOURCES b/apps/plugins/jpeg/SOURCES new file mode 100644 index 0000000000..c3524001e2 --- /dev/null +++ b/apps/plugins/jpeg/SOURCES | |||
@@ -0,0 +1,5 @@ | |||
1 | jpeg.c | ||
2 | jpeg_decoder.c | ||
3 | #ifdef HAVE_LCD_COLOR | ||
4 | yuv2rgb.c | ||
5 | #endif | ||
diff --git a/apps/plugins/jpeg/jpeg.c b/apps/plugins/jpeg/jpeg.c new file mode 100644 index 0000000000..d70fca809f --- /dev/null +++ b/apps/plugins/jpeg/jpeg.c | |||
@@ -0,0 +1,1235 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * JPEG image viewer | ||
11 | * (This is a real mess if it has to be coded in one single C file) | ||
12 | * | ||
13 | * File scrolling addition (C) 2005 Alexander Spyridakis | ||
14 | * Copyright (C) 2004 Jörg Hohensohn aka [IDC]Dragon | ||
15 | * Heavily borrowed from the IJG implementation (C) Thomas G. Lane | ||
16 | * Small & fast downscaling IDCT (C) 2002 by Guido Vollbeding JPEGclub.org | ||
17 | * | ||
18 | * This program is free software; you can redistribute it and/or | ||
19 | * modify it under the terms of the GNU General Public License | ||
20 | * as published by the Free Software Foundation; either version 2 | ||
21 | * of the License, or (at your option) any later version. | ||
22 | * | ||
23 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
24 | * KIND, either express or implied. | ||
25 | * | ||
26 | ****************************************************************************/ | ||
27 | |||
28 | #include "plugin.h" | ||
29 | #include <lib/playback_control.h> | ||
30 | #include <lib/oldmenuapi.h> | ||
31 | #include <lib/helper.h> | ||
32 | #include <lib/configfile.h> | ||
33 | |||
34 | #include <lib/grey.h> | ||
35 | #include <lib/xlcd.h> | ||
36 | |||
37 | #include "jpeg.h" | ||
38 | #include "jpeg_decoder.h" | ||
39 | |||
40 | PLUGIN_HEADER | ||
41 | |||
42 | #ifdef HAVE_LCD_COLOR | ||
43 | #include "yuv2rgb.h" | ||
44 | #endif | ||
45 | |||
46 | /* different graphics libraries */ | ||
47 | #if LCD_DEPTH < 8 | ||
48 | #define USEGSLIB | ||
49 | GREY_INFO_STRUCT | ||
50 | #define MYLCD(fn) grey_ub_ ## fn | ||
51 | #define MYLCD_UPDATE() | ||
52 | #define MYXLCD(fn) grey_ub_ ## fn | ||
53 | #else | ||
54 | #define MYLCD(fn) rb->lcd_ ## fn | ||
55 | #define MYLCD_UPDATE() rb->lcd_update(); | ||
56 | #define MYXLCD(fn) xlcd_ ## fn | ||
57 | #endif | ||
58 | |||
59 | #define MAX_X_SIZE LCD_WIDTH*8 | ||
60 | |||
61 | /* Min memory allowing us to use the plugin buffer | ||
62 | * and thus not stopping the music | ||
63 | * *Very* rough estimation: | ||
64 | * Max 10 000 dir entries * 4bytes/entry (char **) = 40000 bytes | ||
65 | * + 20k code size = 60 000 | ||
66 | * + 50k min for jpeg = 120 000 | ||
67 | */ | ||
68 | #define MIN_MEM 120000 | ||
69 | |||
70 | /* Headings */ | ||
71 | #define DIR_PREV 1 | ||
72 | #define DIR_NEXT -1 | ||
73 | #define DIR_NONE 0 | ||
74 | |||
75 | #define PLUGIN_OTHER 10 /* State code for output with return. */ | ||
76 | |||
77 | /******************************* Globals ***********************************/ | ||
78 | |||
79 | const struct plugin_api* rb; | ||
80 | MEM_FUNCTION_WRAPPERS(rb); | ||
81 | |||
82 | static int slideshow_enabled = false; /* run slideshow */ | ||
83 | static int running_slideshow = false; /* loading image because of slideshw */ | ||
84 | #ifndef SIMULATOR | ||
85 | static int immediate_ata_off = false; /* power down disk after loading */ | ||
86 | #endif | ||
87 | |||
88 | #ifdef HAVE_LCD_COLOR | ||
89 | fb_data rgb_linebuf[LCD_WIDTH]; /* Line buffer for scrolling when | ||
90 | DITHER_DIFFUSION is set */ | ||
91 | #endif | ||
92 | |||
93 | |||
94 | /* Persistent configuration */ | ||
95 | #define JPEG_CONFIGFILE "jpeg.cfg" | ||
96 | #define JPEG_SETTINGS_MINVERSION 1 | ||
97 | #define JPEG_SETTINGS_VERSION 2 | ||
98 | |||
99 | /* Slideshow times */ | ||
100 | #define SS_MIN_TIMEOUT 1 | ||
101 | #define SS_MAX_TIMEOUT 20 | ||
102 | #define SS_DEFAULT_TIMEOUT 5 | ||
103 | |||
104 | struct jpeg_settings | ||
105 | { | ||
106 | #ifdef HAVE_LCD_COLOR | ||
107 | int colour_mode; | ||
108 | int dither_mode; | ||
109 | #endif | ||
110 | int ss_timeout; | ||
111 | }; | ||
112 | |||
113 | static struct jpeg_settings jpeg_settings = | ||
114 | { | ||
115 | #ifdef HAVE_LCD_COLOR | ||
116 | COLOURMODE_COLOUR, | ||
117 | DITHER_NONE, | ||
118 | #endif | ||
119 | SS_DEFAULT_TIMEOUT | ||
120 | }; | ||
121 | static struct jpeg_settings old_settings; | ||
122 | |||
123 | static struct configdata jpeg_config[] = | ||
124 | { | ||
125 | #ifdef HAVE_LCD_COLOR | ||
126 | { TYPE_ENUM, 0, COLOUR_NUM_MODES, &jpeg_settings.colour_mode, | ||
127 | "Colour Mode", (char *[]){ "Colour", "Grayscale" }, NULL }, | ||
128 | { TYPE_ENUM, 0, DITHER_NUM_MODES, &jpeg_settings.dither_mode, | ||
129 | "Dither Mode", (char *[]){ "None", "Ordered", "Diffusion" }, NULL }, | ||
130 | #endif | ||
131 | { TYPE_INT, SS_MIN_TIMEOUT, SS_MAX_TIMEOUT, &jpeg_settings.ss_timeout, | ||
132 | "Slideshow Time", NULL, NULL}, | ||
133 | }; | ||
134 | |||
135 | #if LCD_DEPTH > 1 | ||
136 | fb_data* old_backdrop; | ||
137 | #endif | ||
138 | |||
139 | /**************** begin Application ********************/ | ||
140 | |||
141 | |||
142 | /************************* Types ***************************/ | ||
143 | |||
144 | struct t_disp | ||
145 | { | ||
146 | #ifdef HAVE_LCD_COLOR | ||
147 | unsigned char* bitmap[3]; /* Y, Cr, Cb */ | ||
148 | int csub_x, csub_y; | ||
149 | #else | ||
150 | unsigned char* bitmap[1]; /* Y only */ | ||
151 | #endif | ||
152 | int width; | ||
153 | int height; | ||
154 | int stride; | ||
155 | int x, y; | ||
156 | }; | ||
157 | |||
158 | /************************* Globals ***************************/ | ||
159 | |||
160 | /* decompressed image in the possible sizes (1,2,4,8), wasting the other */ | ||
161 | struct t_disp disp[9]; | ||
162 | |||
163 | /* my memory pool (from the mp3 buffer) */ | ||
164 | char print[32]; /* use a common snprintf() buffer */ | ||
165 | unsigned char* buf; /* up to here currently used by image(s) */ | ||
166 | |||
167 | /* the remaining free part of the buffer for compressed+uncompressed images */ | ||
168 | unsigned char* buf_images; | ||
169 | |||
170 | ssize_t buf_size, buf_images_size; | ||
171 | /* the root of the images, hereafter are decompresed ones */ | ||
172 | unsigned char* buf_root; | ||
173 | int root_size; | ||
174 | |||
175 | int ds, ds_min, ds_max; /* downscaling and limits */ | ||
176 | static struct jpeg jpg; /* too large for stack */ | ||
177 | |||
178 | static struct tree_context *tree; | ||
179 | |||
180 | /* the current full file name */ | ||
181 | static char np_file[MAX_PATH]; | ||
182 | int curfile = 0, direction = DIR_NONE, entries = 0; | ||
183 | |||
184 | /* list of the jpeg files */ | ||
185 | char **file_pt; | ||
186 | /* are we using the plugin buffer or the audio buffer? */ | ||
187 | bool plug_buf = false; | ||
188 | |||
189 | |||
190 | /************************* Implementation ***************************/ | ||
191 | |||
192 | /* support function for qsort() */ | ||
193 | static int compare(const void* p1, const void* p2) | ||
194 | { | ||
195 | return rb->strcasecmp(*((char **)p1), *((char **)p2)); | ||
196 | } | ||
197 | |||
198 | bool jpg_ext(const char ext[]) | ||
199 | { | ||
200 | if(!ext) | ||
201 | return false; | ||
202 | if(!rb->strcasecmp(ext,".jpg") || | ||
203 | !rb->strcasecmp(ext,".jpe") || | ||
204 | !rb->strcasecmp(ext,".jpeg")) | ||
205 | return true; | ||
206 | else | ||
207 | return false; | ||
208 | } | ||
209 | |||
210 | /*Read directory contents for scrolling. */ | ||
211 | void get_pic_list(void) | ||
212 | { | ||
213 | int i; | ||
214 | long int str_len = 0; | ||
215 | char *pname; | ||
216 | tree = rb->tree_get_context(); | ||
217 | |||
218 | #if PLUGIN_BUFFER_SIZE >= MIN_MEM | ||
219 | file_pt = rb->plugin_get_buffer((size_t *)&buf_size); | ||
220 | #else | ||
221 | file_pt = rb->plugin_get_audio_buffer((size_t *)&buf_size); | ||
222 | #endif | ||
223 | |||
224 | for(i = 0; i < tree->filesindir; i++) | ||
225 | { | ||
226 | if(jpg_ext(rb->strrchr(&tree->name_buffer[str_len],'.'))) | ||
227 | file_pt[entries++] = &tree->name_buffer[str_len]; | ||
228 | |||
229 | str_len += rb->strlen(&tree->name_buffer[str_len]) + 1; | ||
230 | } | ||
231 | |||
232 | rb->qsort(file_pt, entries, sizeof(char**), compare); | ||
233 | |||
234 | /* Remove path and leave only the name.*/ | ||
235 | pname = rb->strrchr(np_file,'/'); | ||
236 | pname++; | ||
237 | |||
238 | /* Find Selected File. */ | ||
239 | for(i = 0; i < entries; i++) | ||
240 | if(!rb->strcmp(file_pt[i], pname)) | ||
241 | curfile = i; | ||
242 | } | ||
243 | |||
244 | int change_filename(int direct) | ||
245 | { | ||
246 | int count = 0; | ||
247 | direction = direct; | ||
248 | |||
249 | if(direct == DIR_PREV) | ||
250 | { | ||
251 | do | ||
252 | { | ||
253 | count++; | ||
254 | if(curfile == 0) | ||
255 | curfile = entries - 1; | ||
256 | else | ||
257 | curfile--; | ||
258 | }while(file_pt[curfile] == '\0' && count < entries); | ||
259 | /* we "erase" the file name if we encounter | ||
260 | * a non-supported file, so skip it now */ | ||
261 | } | ||
262 | else /* DIR_NEXT/DIR_NONE */ | ||
263 | { | ||
264 | do | ||
265 | { | ||
266 | count++; | ||
267 | if(curfile == entries - 1) | ||
268 | curfile = 0; | ||
269 | else | ||
270 | curfile++; | ||
271 | }while(file_pt[curfile] == '\0' && count < entries); | ||
272 | } | ||
273 | |||
274 | if(count == entries && file_pt[curfile] == '\0') | ||
275 | { | ||
276 | rb->splash(HZ, "No supported files"); | ||
277 | return PLUGIN_ERROR; | ||
278 | } | ||
279 | if(rb->strlen(tree->currdir) > 1) | ||
280 | { | ||
281 | rb->strcpy(np_file, tree->currdir); | ||
282 | rb->strcat(np_file, "/"); | ||
283 | } | ||
284 | else | ||
285 | rb->strcpy(np_file, tree->currdir); | ||
286 | |||
287 | rb->strcat(np_file, file_pt[curfile]); | ||
288 | |||
289 | return PLUGIN_OTHER; | ||
290 | } | ||
291 | |||
292 | /* switch off overlay, for handling SYS_ events */ | ||
293 | void cleanup(void *parameter) | ||
294 | { | ||
295 | (void)parameter; | ||
296 | #ifdef USEGSLIB | ||
297 | grey_show(false); | ||
298 | #endif | ||
299 | } | ||
300 | |||
301 | #define VSCROLL (LCD_HEIGHT/8) | ||
302 | #define HSCROLL (LCD_WIDTH/10) | ||
303 | |||
304 | #define ZOOM_IN 100 /* return codes for below function */ | ||
305 | #define ZOOM_OUT 101 | ||
306 | |||
307 | #ifdef HAVE_LCD_COLOR | ||
308 | bool set_option_grayscale(void) | ||
309 | { | ||
310 | bool gray = jpeg_settings.colour_mode == COLOURMODE_GRAY; | ||
311 | rb->set_bool("Grayscale", &gray); | ||
312 | jpeg_settings.colour_mode = gray ? COLOURMODE_GRAY : COLOURMODE_COLOUR; | ||
313 | return false; | ||
314 | } | ||
315 | |||
316 | bool set_option_dithering(void) | ||
317 | { | ||
318 | static const struct opt_items dithering[DITHER_NUM_MODES] = { | ||
319 | [DITHER_NONE] = { "Off", -1 }, | ||
320 | [DITHER_ORDERED] = { "Ordered", -1 }, | ||
321 | [DITHER_DIFFUSION] = { "Diffusion", -1 }, | ||
322 | }; | ||
323 | |||
324 | rb->set_option("Dithering", &jpeg_settings.dither_mode, INT, | ||
325 | dithering, DITHER_NUM_MODES, NULL); | ||
326 | return false; | ||
327 | } | ||
328 | |||
329 | static void display_options(void) | ||
330 | { | ||
331 | static const struct menu_item items[] = { | ||
332 | { "Grayscale", set_option_grayscale }, | ||
333 | { "Dithering", set_option_dithering }, | ||
334 | }; | ||
335 | |||
336 | int m = menu_init(rb, items, ARRAYLEN(items), | ||
337 | NULL, NULL, NULL, NULL); | ||
338 | menu_run(m); | ||
339 | menu_exit(m); | ||
340 | } | ||
341 | #endif /* HAVE_LCD_COLOR */ | ||
342 | |||
343 | int show_menu(void) /* return 1 to quit */ | ||
344 | { | ||
345 | #if LCD_DEPTH > 1 | ||
346 | rb->lcd_set_backdrop(old_backdrop); | ||
347 | #ifdef HAVE_LCD_COLOR | ||
348 | rb->lcd_set_foreground(rb->global_settings->fg_color); | ||
349 | rb->lcd_set_background(rb->global_settings->bg_color); | ||
350 | #else | ||
351 | rb->lcd_set_foreground(LCD_BLACK); | ||
352 | rb->lcd_set_background(LCD_WHITE); | ||
353 | #endif | ||
354 | #endif | ||
355 | int m; | ||
356 | int result; | ||
357 | |||
358 | enum menu_id | ||
359 | { | ||
360 | MIID_QUIT = 0, | ||
361 | MIID_TOGGLE_SS_MODE, | ||
362 | MIID_CHANGE_SS_MODE, | ||
363 | #if PLUGIN_BUFFER_SIZE >= MIN_MEM | ||
364 | MIID_SHOW_PLAYBACK_MENU, | ||
365 | #endif | ||
366 | #ifdef HAVE_LCD_COLOR | ||
367 | MIID_DISPLAY_OPTIONS, | ||
368 | #endif | ||
369 | MIID_RETURN, | ||
370 | }; | ||
371 | |||
372 | static const struct menu_item items[] = { | ||
373 | [MIID_QUIT] = | ||
374 | { "Quit", NULL }, | ||
375 | [MIID_TOGGLE_SS_MODE] = | ||
376 | { "Toggle Slideshow Mode", NULL }, | ||
377 | [MIID_CHANGE_SS_MODE] = | ||
378 | { "Change Slideshow Time", NULL }, | ||
379 | #if PLUGIN_BUFFER_SIZE >= MIN_MEM | ||
380 | [MIID_SHOW_PLAYBACK_MENU] = | ||
381 | { "Show Playback Menu", NULL }, | ||
382 | #endif | ||
383 | #ifdef HAVE_LCD_COLOR | ||
384 | [MIID_DISPLAY_OPTIONS] = | ||
385 | { "Display Options", NULL }, | ||
386 | #endif | ||
387 | [MIID_RETURN] = | ||
388 | { "Return", NULL }, | ||
389 | }; | ||
390 | |||
391 | static const struct opt_items slideshow[2] = { | ||
392 | { "Disable", -1 }, | ||
393 | { "Enable", -1 }, | ||
394 | }; | ||
395 | |||
396 | m = menu_init(rb, items, sizeof(items) / sizeof(*items), | ||
397 | NULL, NULL, NULL, NULL); | ||
398 | result=menu_show(m); | ||
399 | |||
400 | switch (result) | ||
401 | { | ||
402 | case MIID_QUIT: | ||
403 | menu_exit(m); | ||
404 | return 1; | ||
405 | break; | ||
406 | case MIID_TOGGLE_SS_MODE: | ||
407 | rb->set_option("Toggle Slideshow", &slideshow_enabled, INT, | ||
408 | slideshow , 2, NULL); | ||
409 | break; | ||
410 | case MIID_CHANGE_SS_MODE: | ||
411 | rb->set_int("Slideshow Time", "s", UNIT_SEC, | ||
412 | &jpeg_settings.ss_timeout, NULL, 1, | ||
413 | SS_MIN_TIMEOUT, SS_MAX_TIMEOUT, NULL); | ||
414 | break; | ||
415 | |||
416 | #if PLUGIN_BUFFER_SIZE >= MIN_MEM | ||
417 | case MIID_SHOW_PLAYBACK_MENU: | ||
418 | if (plug_buf) | ||
419 | { | ||
420 | playback_control(rb, NULL); | ||
421 | } | ||
422 | else | ||
423 | { | ||
424 | rb->splash(HZ, "Cannot restart playback"); | ||
425 | } | ||
426 | break; | ||
427 | #endif | ||
428 | #ifdef HAVE_LCD_COLOR | ||
429 | case MIID_DISPLAY_OPTIONS: | ||
430 | display_options(); | ||
431 | break; | ||
432 | #endif | ||
433 | case MIID_RETURN: | ||
434 | break; | ||
435 | } | ||
436 | |||
437 | #if !defined(SIMULATOR) && defined(HAVE_DISK_STORAGE) | ||
438 | /* change ata spindown time based on slideshow time setting */ | ||
439 | immediate_ata_off = false; | ||
440 | rb->ata_spindown(rb->global_settings->disk_spindown); | ||
441 | |||
442 | if (slideshow_enabled) | ||
443 | { | ||
444 | if(jpeg_settings.ss_timeout < 10) | ||
445 | { | ||
446 | /* slideshow times < 10s keep disk spinning */ | ||
447 | rb->ata_spindown(0); | ||
448 | } | ||
449 | else if (!rb->mp3_is_playing()) | ||
450 | { | ||
451 | /* slideshow times > 10s and not playing: ata_off after load */ | ||
452 | immediate_ata_off = true; | ||
453 | } | ||
454 | } | ||
455 | #endif | ||
456 | #if LCD_DEPTH > 1 | ||
457 | rb->lcd_set_backdrop(NULL); | ||
458 | rb->lcd_set_foreground(LCD_WHITE); | ||
459 | rb->lcd_set_background(LCD_BLACK); | ||
460 | #endif | ||
461 | rb->lcd_clear_display(); | ||
462 | menu_exit(m); | ||
463 | return 0; | ||
464 | } | ||
465 | /* interactively scroll around the image */ | ||
466 | int scroll_bmp(struct t_disp* pdisp) | ||
467 | { | ||
468 | int lastbutton = 0; | ||
469 | |||
470 | while (true) | ||
471 | { | ||
472 | int button; | ||
473 | int move; | ||
474 | |||
475 | if (slideshow_enabled) | ||
476 | button = rb->button_get_w_tmo(jpeg_settings.ss_timeout * HZ); | ||
477 | else button = rb->button_get(true); | ||
478 | |||
479 | running_slideshow = false; | ||
480 | |||
481 | switch(button) | ||
482 | { | ||
483 | case JPEG_LEFT: | ||
484 | if (!(ds < ds_max) && entries > 0 && jpg.x_size <= MAX_X_SIZE) | ||
485 | return change_filename(DIR_PREV); | ||
486 | case JPEG_LEFT | BUTTON_REPEAT: | ||
487 | move = MIN(HSCROLL, pdisp->x); | ||
488 | if (move > 0) | ||
489 | { | ||
490 | MYXLCD(scroll_right)(move); /* scroll right */ | ||
491 | pdisp->x -= move; | ||
492 | #ifdef HAVE_LCD_COLOR | ||
493 | yuv_bitmap_part( | ||
494 | pdisp->bitmap, pdisp->csub_x, pdisp->csub_y, | ||
495 | pdisp->x, pdisp->y, pdisp->stride, | ||
496 | 0, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */ | ||
497 | move, MIN(LCD_HEIGHT, pdisp->height), /* w, h */ | ||
498 | jpeg_settings.colour_mode, jpeg_settings.dither_mode); | ||
499 | #else | ||
500 | MYXLCD(gray_bitmap_part)( | ||
501 | pdisp->bitmap[0], pdisp->x, pdisp->y, pdisp->stride, | ||
502 | 0, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */ | ||
503 | move, MIN(LCD_HEIGHT, pdisp->height)); /* w, h */ | ||
504 | #endif | ||
505 | MYLCD_UPDATE(); | ||
506 | } | ||
507 | break; | ||
508 | |||
509 | case JPEG_RIGHT: | ||
510 | if (!(ds < ds_max) && entries > 0 && jpg.x_size <= MAX_X_SIZE) | ||
511 | return change_filename(DIR_NEXT); | ||
512 | case JPEG_RIGHT | BUTTON_REPEAT: | ||
513 | move = MIN(HSCROLL, pdisp->width - pdisp->x - LCD_WIDTH); | ||
514 | if (move > 0) | ||
515 | { | ||
516 | MYXLCD(scroll_left)(move); /* scroll left */ | ||
517 | pdisp->x += move; | ||
518 | #ifdef HAVE_LCD_COLOR | ||
519 | yuv_bitmap_part( | ||
520 | pdisp->bitmap, pdisp->csub_x, pdisp->csub_y, | ||
521 | pdisp->x + LCD_WIDTH - move, pdisp->y, pdisp->stride, | ||
522 | LCD_WIDTH - move, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */ | ||
523 | move, MIN(LCD_HEIGHT, pdisp->height), /* w, h */ | ||
524 | jpeg_settings.colour_mode, jpeg_settings.dither_mode); | ||
525 | #else | ||
526 | MYXLCD(gray_bitmap_part)( | ||
527 | pdisp->bitmap[0], pdisp->x + LCD_WIDTH - move, | ||
528 | pdisp->y, pdisp->stride, | ||
529 | LCD_WIDTH - move, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */ | ||
530 | move, MIN(LCD_HEIGHT, pdisp->height)); /* w, h */ | ||
531 | #endif | ||
532 | MYLCD_UPDATE(); | ||
533 | } | ||
534 | break; | ||
535 | |||
536 | case JPEG_UP: | ||
537 | case JPEG_UP | BUTTON_REPEAT: | ||
538 | move = MIN(VSCROLL, pdisp->y); | ||
539 | if (move > 0) | ||
540 | { | ||
541 | MYXLCD(scroll_down)(move); /* scroll down */ | ||
542 | pdisp->y -= move; | ||
543 | #ifdef HAVE_LCD_COLOR | ||
544 | if (jpeg_settings.dither_mode == DITHER_DIFFUSION) | ||
545 | { | ||
546 | /* Draw over the band at the top of the last update | ||
547 | caused by lack of error history on line zero. */ | ||
548 | move = MIN(move + 1, pdisp->y + pdisp->height); | ||
549 | } | ||
550 | |||
551 | yuv_bitmap_part( | ||
552 | pdisp->bitmap, pdisp->csub_x, pdisp->csub_y, | ||
553 | pdisp->x, pdisp->y, pdisp->stride, | ||
554 | MAX(0, (LCD_WIDTH-pdisp->width)/2), 0, /* x, y */ | ||
555 | MIN(LCD_WIDTH, pdisp->width), move, /* w, h */ | ||
556 | jpeg_settings.colour_mode, jpeg_settings.dither_mode); | ||
557 | #else | ||
558 | MYXLCD(gray_bitmap_part)( | ||
559 | pdisp->bitmap[0], pdisp->x, pdisp->y, pdisp->stride, | ||
560 | MAX(0, (LCD_WIDTH-pdisp->width)/2), 0, /* x, y */ | ||
561 | MIN(LCD_WIDTH, pdisp->width), move); /* w, h */ | ||
562 | #endif | ||
563 | MYLCD_UPDATE(); | ||
564 | } | ||
565 | break; | ||
566 | |||
567 | case JPEG_DOWN: | ||
568 | case JPEG_DOWN | BUTTON_REPEAT: | ||
569 | move = MIN(VSCROLL, pdisp->height - pdisp->y - LCD_HEIGHT); | ||
570 | if (move > 0) | ||
571 | { | ||
572 | MYXLCD(scroll_up)(move); /* scroll up */ | ||
573 | pdisp->y += move; | ||
574 | #ifdef HAVE_LCD_COLOR | ||
575 | if (jpeg_settings.dither_mode == DITHER_DIFFUSION) | ||
576 | { | ||
577 | /* Save the line that was on the last line of the display | ||
578 | and draw one extra line above then recover the line with | ||
579 | image data that had an error history when it was drawn. | ||
580 | */ | ||
581 | move++, pdisp->y--; | ||
582 | rb->memcpy(rgb_linebuf, | ||
583 | rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH, | ||
584 | LCD_WIDTH*sizeof (fb_data)); | ||
585 | } | ||
586 | |||
587 | yuv_bitmap_part( | ||
588 | pdisp->bitmap, pdisp->csub_x, pdisp->csub_y, pdisp->x, | ||
589 | pdisp->y + LCD_HEIGHT - move, pdisp->stride, | ||
590 | MAX(0, (LCD_WIDTH-pdisp->width)/2), LCD_HEIGHT - move, /* x, y */ | ||
591 | MIN(LCD_WIDTH, pdisp->width), move, /* w, h */ | ||
592 | jpeg_settings.colour_mode, jpeg_settings.dither_mode); | ||
593 | |||
594 | if (jpeg_settings.dither_mode == DITHER_DIFFUSION) | ||
595 | { | ||
596 | /* Cover the first row drawn with previous image data. */ | ||
597 | rb->memcpy(rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH, | ||
598 | rgb_linebuf, | ||
599 | LCD_WIDTH*sizeof (fb_data)); | ||
600 | pdisp->y++; | ||
601 | } | ||
602 | #else | ||
603 | MYXLCD(gray_bitmap_part)( | ||
604 | pdisp->bitmap[0], pdisp->x, | ||
605 | pdisp->y + LCD_HEIGHT - move, pdisp->stride, | ||
606 | MAX(0, (LCD_WIDTH-pdisp->width)/2), LCD_HEIGHT - move, /* x, y */ | ||
607 | MIN(LCD_WIDTH, pdisp->width), move); /* w, h */ | ||
608 | #endif | ||
609 | MYLCD_UPDATE(); | ||
610 | } | ||
611 | break; | ||
612 | case BUTTON_NONE: | ||
613 | if (!slideshow_enabled) | ||
614 | break; | ||
615 | running_slideshow = true; | ||
616 | if (entries > 0) | ||
617 | return change_filename(DIR_NEXT); | ||
618 | break; | ||
619 | |||
620 | #ifdef JPEG_SLIDE_SHOW | ||
621 | case JPEG_SLIDE_SHOW: | ||
622 | slideshow_enabled = !slideshow_enabled; | ||
623 | running_slideshow = slideshow_enabled; | ||
624 | break; | ||
625 | #endif | ||
626 | |||
627 | #ifdef JPEG_NEXT_REPEAT | ||
628 | case JPEG_NEXT_REPEAT: | ||
629 | #endif | ||
630 | case JPEG_NEXT: | ||
631 | if (entries > 0) | ||
632 | return change_filename(DIR_NEXT); | ||
633 | break; | ||
634 | |||
635 | #ifdef JPEG_PREVIOUS_REPEAT | ||
636 | case JPEG_PREVIOUS_REPEAT: | ||
637 | #endif | ||
638 | case JPEG_PREVIOUS: | ||
639 | if (entries > 0) | ||
640 | return change_filename(DIR_PREV); | ||
641 | break; | ||
642 | |||
643 | case JPEG_ZOOM_IN: | ||
644 | #ifdef JPEG_ZOOM_PRE | ||
645 | if (lastbutton != JPEG_ZOOM_PRE) | ||
646 | break; | ||
647 | #endif | ||
648 | return ZOOM_IN; | ||
649 | break; | ||
650 | |||
651 | case JPEG_ZOOM_OUT: | ||
652 | #ifdef JPEG_ZOOM_PRE | ||
653 | if (lastbutton != JPEG_ZOOM_PRE) | ||
654 | break; | ||
655 | #endif | ||
656 | return ZOOM_OUT; | ||
657 | break; | ||
658 | #ifdef JPEG_RC_MENU | ||
659 | case JPEG_RC_MENU: | ||
660 | #endif | ||
661 | case JPEG_MENU: | ||
662 | #ifdef USEGSLIB | ||
663 | grey_show(false); /* switch off greyscale overlay */ | ||
664 | #endif | ||
665 | if (show_menu() == 1) | ||
666 | return PLUGIN_OK; | ||
667 | |||
668 | #ifdef USEGSLIB | ||
669 | grey_show(true); /* switch on greyscale overlay */ | ||
670 | #else | ||
671 | yuv_bitmap_part( | ||
672 | pdisp->bitmap, pdisp->csub_x, pdisp->csub_y, | ||
673 | pdisp->x, pdisp->y, pdisp->stride, | ||
674 | MAX(0, (LCD_WIDTH - pdisp->width) / 2), | ||
675 | MAX(0, (LCD_HEIGHT - pdisp->height) / 2), | ||
676 | MIN(LCD_WIDTH, pdisp->width), | ||
677 | MIN(LCD_HEIGHT, pdisp->height), | ||
678 | jpeg_settings.colour_mode, jpeg_settings.dither_mode); | ||
679 | MYLCD_UPDATE(); | ||
680 | #endif | ||
681 | break; | ||
682 | default: | ||
683 | if (rb->default_event_handler_ex(button, cleanup, NULL) | ||
684 | == SYS_USB_CONNECTED) | ||
685 | return PLUGIN_USB_CONNECTED; | ||
686 | break; | ||
687 | |||
688 | } /* switch */ | ||
689 | |||
690 | if (button != BUTTON_NONE) | ||
691 | lastbutton = button; | ||
692 | } /* while (true) */ | ||
693 | } | ||
694 | |||
695 | /********************* main function *************************/ | ||
696 | |||
697 | /* callback updating a progress meter while JPEG decoding */ | ||
698 | void cb_progess(int current, int total) | ||
699 | { | ||
700 | rb->yield(); /* be nice to the other threads */ | ||
701 | if(!running_slideshow) | ||
702 | { | ||
703 | rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN],0, LCD_HEIGHT-8, LCD_WIDTH, 8, total, 0, | ||
704 | current, HORIZONTAL); | ||
705 | rb->lcd_update_rect(0, LCD_HEIGHT-8, LCD_WIDTH, 8); | ||
706 | } | ||
707 | #ifndef USEGSLIB | ||
708 | else | ||
709 | { | ||
710 | /* in slideshow mode, keep gui interference to a minimum */ | ||
711 | rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN],0, LCD_HEIGHT-4, LCD_WIDTH, 4, total, 0, | ||
712 | current, HORIZONTAL); | ||
713 | rb->lcd_update_rect(0, LCD_HEIGHT-4, LCD_WIDTH, 4); | ||
714 | } | ||
715 | #endif | ||
716 | } | ||
717 | |||
718 | int jpegmem(struct jpeg *p_jpg, int ds) | ||
719 | { | ||
720 | int size; | ||
721 | |||
722 | size = (p_jpg->x_phys/ds/p_jpg->subsample_x[0]) | ||
723 | * (p_jpg->y_phys/ds/p_jpg->subsample_y[0]); | ||
724 | #ifdef HAVE_LCD_COLOR | ||
725 | if (p_jpg->blocks > 1) /* colour, add requirements for chroma */ | ||
726 | { | ||
727 | size += (p_jpg->x_phys/ds/p_jpg->subsample_x[1]) | ||
728 | * (p_jpg->y_phys/ds/p_jpg->subsample_y[1]); | ||
729 | size += (p_jpg->x_phys/ds/p_jpg->subsample_x[2]) | ||
730 | * (p_jpg->y_phys/ds/p_jpg->subsample_y[2]); | ||
731 | } | ||
732 | #endif | ||
733 | return size; | ||
734 | } | ||
735 | |||
736 | /* how far can we zoom in without running out of memory */ | ||
737 | int min_downscale(struct jpeg *p_jpg, int bufsize) | ||
738 | { | ||
739 | int downscale = 8; | ||
740 | |||
741 | if (jpegmem(p_jpg, 8) > bufsize) | ||
742 | return 0; /* error, too large, even 1:8 doesn't fit */ | ||
743 | |||
744 | while (downscale > 1 && jpegmem(p_jpg, downscale/2) <= bufsize) | ||
745 | downscale /= 2; | ||
746 | |||
747 | return downscale; | ||
748 | } | ||
749 | |||
750 | |||
751 | /* how far can we zoom out, to fit image into the LCD */ | ||
752 | int max_downscale(struct jpeg *p_jpg) | ||
753 | { | ||
754 | int downscale = 1; | ||
755 | |||
756 | while (downscale < 8 && (p_jpg->x_size > LCD_WIDTH*downscale | ||
757 | || p_jpg->y_size > LCD_HEIGHT*downscale)) | ||
758 | { | ||
759 | downscale *= 2; | ||
760 | } | ||
761 | |||
762 | return downscale; | ||
763 | } | ||
764 | |||
765 | |||
766 | /* return decoded or cached image */ | ||
767 | struct t_disp* get_image(struct jpeg* p_jpg, int ds) | ||
768 | { | ||
769 | int w, h; /* used to center output */ | ||
770 | int size; /* decompressed image size */ | ||
771 | long time; /* measured ticks */ | ||
772 | int status; | ||
773 | |||
774 | struct t_disp* p_disp = &disp[ds]; /* short cut */ | ||
775 | |||
776 | if (p_disp->bitmap[0] != NULL) | ||
777 | { | ||
778 | return p_disp; /* we still have it */ | ||
779 | } | ||
780 | |||
781 | /* assign image buffer */ | ||
782 | |||
783 | /* physical size needed for decoding */ | ||
784 | size = jpegmem(p_jpg, ds); | ||
785 | if (buf_size <= size) | ||
786 | { /* have to discard the current */ | ||
787 | int i; | ||
788 | for (i=1; i<=8; i++) | ||
789 | disp[i].bitmap[0] = NULL; /* invalidate all bitmaps */ | ||
790 | buf = buf_root; /* start again from the beginning of the buffer */ | ||
791 | buf_size = root_size; | ||
792 | } | ||
793 | |||
794 | #ifdef HAVE_LCD_COLOR | ||
795 | if (p_jpg->blocks > 1) /* colour jpeg */ | ||
796 | { | ||
797 | int i; | ||
798 | |||
799 | for (i = 1; i < 3; i++) | ||
800 | { | ||
801 | size = (p_jpg->x_phys / ds / p_jpg->subsample_x[i]) | ||
802 | * (p_jpg->y_phys / ds / p_jpg->subsample_y[i]); | ||
803 | p_disp->bitmap[i] = buf; | ||
804 | buf += size; | ||
805 | buf_size -= size; | ||
806 | } | ||
807 | p_disp->csub_x = p_jpg->subsample_x[1]; | ||
808 | p_disp->csub_y = p_jpg->subsample_y[1]; | ||
809 | } | ||
810 | else | ||
811 | { | ||
812 | p_disp->csub_x = p_disp->csub_y = 0; | ||
813 | p_disp->bitmap[1] = p_disp->bitmap[2] = buf; | ||
814 | } | ||
815 | #endif | ||
816 | /* size may be less when decoded (if height is not block aligned) */ | ||
817 | size = (p_jpg->x_phys/ds) * (p_jpg->y_size / ds); | ||
818 | p_disp->bitmap[0] = buf; | ||
819 | buf += size; | ||
820 | buf_size -= size; | ||
821 | |||
822 | if(!running_slideshow) | ||
823 | { | ||
824 | rb->snprintf(print, sizeof(print), "decoding %d*%d", | ||
825 | p_jpg->x_size/ds, p_jpg->y_size/ds); | ||
826 | rb->lcd_puts(0, 3, print); | ||
827 | rb->lcd_update(); | ||
828 | } | ||
829 | |||
830 | /* update image properties */ | ||
831 | p_disp->width = p_jpg->x_size / ds; | ||
832 | p_disp->stride = p_jpg->x_phys / ds; /* use physical size for stride */ | ||
833 | p_disp->height = p_jpg->y_size / ds; | ||
834 | |||
835 | /* the actual decoding */ | ||
836 | time = *rb->current_tick; | ||
837 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | ||
838 | rb->cpu_boost(true); | ||
839 | status = jpeg_decode(p_jpg, p_disp->bitmap, ds, cb_progess); | ||
840 | rb->cpu_boost(false); | ||
841 | #else | ||
842 | status = jpeg_decode(p_jpg, p_disp->bitmap, ds, cb_progess); | ||
843 | #endif | ||
844 | if (status) | ||
845 | { | ||
846 | rb->splashf(HZ, "decode error %d", status); | ||
847 | file_pt[curfile] = '\0'; | ||
848 | return NULL; | ||
849 | } | ||
850 | time = *rb->current_tick - time; | ||
851 | |||
852 | if(!running_slideshow) | ||
853 | { | ||
854 | rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ); | ||
855 | rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */ | ||
856 | rb->lcd_putsxy((LCD_WIDTH - w)/2, LCD_HEIGHT - h, print); | ||
857 | rb->lcd_update(); | ||
858 | } | ||
859 | |||
860 | return p_disp; | ||
861 | } | ||
862 | |||
863 | |||
864 | /* set the view to the given center point, limit if necessary */ | ||
865 | void set_view (struct t_disp* p_disp, int cx, int cy) | ||
866 | { | ||
867 | int x, y; | ||
868 | |||
869 | /* plain center to available width/height */ | ||
870 | x = cx - MIN(LCD_WIDTH, p_disp->width) / 2; | ||
871 | y = cy - MIN(LCD_HEIGHT, p_disp->height) / 2; | ||
872 | |||
873 | /* limit against upper image size */ | ||
874 | x = MIN(p_disp->width - LCD_WIDTH, x); | ||
875 | y = MIN(p_disp->height - LCD_HEIGHT, y); | ||
876 | |||
877 | /* limit against negative side */ | ||
878 | x = MAX(0, x); | ||
879 | y = MAX(0, y); | ||
880 | |||
881 | p_disp->x = x; /* set the values */ | ||
882 | p_disp->y = y; | ||
883 | } | ||
884 | |||
885 | |||
886 | /* calculate the view center based on the bitmap position */ | ||
887 | void get_view(struct t_disp* p_disp, int* p_cx, int* p_cy) | ||
888 | { | ||
889 | *p_cx = p_disp->x + MIN(LCD_WIDTH, p_disp->width) / 2; | ||
890 | *p_cy = p_disp->y + MIN(LCD_HEIGHT, p_disp->height) / 2; | ||
891 | } | ||
892 | |||
893 | |||
894 | /* load, decode, display the image */ | ||
895 | int load_and_show(char* filename) | ||
896 | { | ||
897 | int fd; | ||
898 | int filesize; | ||
899 | unsigned char* buf_jpeg; /* compressed JPEG image */ | ||
900 | int status; | ||
901 | struct t_disp* p_disp; /* currenly displayed image */ | ||
902 | int cx, cy; /* view center */ | ||
903 | |||
904 | fd = rb->open(filename, O_RDONLY); | ||
905 | if (fd < 0) | ||
906 | { | ||
907 | rb->snprintf(print,sizeof(print),"err opening %s:%d",filename,fd); | ||
908 | rb->splash(HZ, print); | ||
909 | return PLUGIN_ERROR; | ||
910 | } | ||
911 | filesize = rb->filesize(fd); | ||
912 | rb->memset(&disp, 0, sizeof(disp)); | ||
913 | |||
914 | buf = buf_images + filesize; | ||
915 | buf_size = buf_images_size - filesize; | ||
916 | /* allocate JPEG buffer */ | ||
917 | buf_jpeg = buf_images; | ||
918 | |||
919 | buf_root = buf; /* we can start the decompressed images behind it */ | ||
920 | root_size = buf_size; | ||
921 | |||
922 | if (buf_size <= 0) | ||
923 | { | ||
924 | #if PLUGIN_BUFFER_SIZE >= MIN_MEM | ||
925 | if(plug_buf) | ||
926 | { | ||
927 | rb->close(fd); | ||
928 | rb->lcd_setfont(FONT_SYSFIXED); | ||
929 | rb->lcd_clear_display(); | ||
930 | rb->snprintf(print,sizeof(print),"%s:",rb->strrchr(filename,'/')+1); | ||
931 | rb->lcd_puts(0,0,print); | ||
932 | rb->lcd_puts(0,1,"Not enough plugin memory!"); | ||
933 | rb->lcd_puts(0,2,"Zoom In: Stop playback."); | ||
934 | if(entries>1) | ||
935 | rb->lcd_puts(0,3,"Left/Right: Skip File."); | ||
936 | rb->lcd_puts(0,4,"Off: Quit."); | ||
937 | rb->lcd_update(); | ||
938 | rb->lcd_setfont(FONT_UI); | ||
939 | |||
940 | rb->button_clear_queue(); | ||
941 | |||
942 | while (1) | ||
943 | { | ||
944 | int button = rb->button_get(true); | ||
945 | switch(button) | ||
946 | { | ||
947 | case JPEG_ZOOM_IN: | ||
948 | plug_buf = false; | ||
949 | buf_images = rb->plugin_get_audio_buffer( | ||
950 | (size_t *)&buf_images_size); | ||
951 | /*try again this file, now using the audio buffer */ | ||
952 | return PLUGIN_OTHER; | ||
953 | #ifdef JPEG_RC_MENU | ||
954 | case JPEG_RC_MENU: | ||
955 | #endif | ||
956 | case JPEG_MENU: | ||
957 | return PLUGIN_OK; | ||
958 | |||
959 | case JPEG_LEFT: | ||
960 | if(entries>1) | ||
961 | { | ||
962 | rb->lcd_clear_display(); | ||
963 | return change_filename(DIR_PREV); | ||
964 | } | ||
965 | break; | ||
966 | |||
967 | case JPEG_RIGHT: | ||
968 | if(entries>1) | ||
969 | { | ||
970 | rb->lcd_clear_display(); | ||
971 | return change_filename(DIR_NEXT); | ||
972 | } | ||
973 | break; | ||
974 | default: | ||
975 | if(rb->default_event_handler_ex(button, cleanup, NULL) | ||
976 | == SYS_USB_CONNECTED) | ||
977 | return PLUGIN_USB_CONNECTED; | ||
978 | |||
979 | } | ||
980 | } | ||
981 | } | ||
982 | else | ||
983 | #endif | ||
984 | { | ||
985 | rb->splash(HZ, "Out of Memory"); | ||
986 | rb->close(fd); | ||
987 | return PLUGIN_ERROR; | ||
988 | } | ||
989 | } | ||
990 | |||
991 | if(!running_slideshow) | ||
992 | { | ||
993 | #if LCD_DEPTH > 1 | ||
994 | rb->lcd_set_foreground(LCD_WHITE); | ||
995 | rb->lcd_set_background(LCD_BLACK); | ||
996 | rb->lcd_set_backdrop(NULL); | ||
997 | #endif | ||
998 | |||
999 | rb->lcd_clear_display(); | ||
1000 | rb->snprintf(print, sizeof(print), "%s:", rb->strrchr(filename,'/')+1); | ||
1001 | rb->lcd_puts(0, 0, print); | ||
1002 | rb->lcd_update(); | ||
1003 | |||
1004 | rb->snprintf(print, sizeof(print), "loading %d bytes", filesize); | ||
1005 | rb->lcd_puts(0, 1, print); | ||
1006 | rb->lcd_update(); | ||
1007 | } | ||
1008 | |||
1009 | rb->read(fd, buf_jpeg, filesize); | ||
1010 | rb->close(fd); | ||
1011 | |||
1012 | if(!running_slideshow) | ||
1013 | { | ||
1014 | rb->snprintf(print, sizeof(print), "decoding markers"); | ||
1015 | rb->lcd_puts(0, 2, print); | ||
1016 | rb->lcd_update(); | ||
1017 | } | ||
1018 | #ifndef SIMULATOR | ||
1019 | else if(immediate_ata_off) | ||
1020 | { | ||
1021 | /* running slideshow and time is long enough: power down disk */ | ||
1022 | rb->ata_sleep(); | ||
1023 | } | ||
1024 | #endif | ||
1025 | |||
1026 | rb->memset(&jpg, 0, sizeof(jpg)); /* clear info struct */ | ||
1027 | /* process markers, unstuffing */ | ||
1028 | status = process_markers(buf_jpeg, filesize, &jpg); | ||
1029 | |||
1030 | if (status < 0 || (status & (DQT | SOF0)) != (DQT | SOF0)) | ||
1031 | { /* bad format or minimum components not contained */ | ||
1032 | rb->splashf(HZ, "unsupported %d", status); | ||
1033 | file_pt[curfile] = '\0'; | ||
1034 | return change_filename(direction); | ||
1035 | } | ||
1036 | |||
1037 | if (!(status & DHT)) /* if no Huffman table present: */ | ||
1038 | default_huff_tbl(&jpg); /* use default */ | ||
1039 | build_lut(&jpg); /* derive Huffman and other lookup-tables */ | ||
1040 | |||
1041 | if(!running_slideshow) | ||
1042 | { | ||
1043 | rb->snprintf(print, sizeof(print), "image %dx%d", jpg.x_size, jpg.y_size); | ||
1044 | rb->lcd_puts(0, 2, print); | ||
1045 | rb->lcd_update(); | ||
1046 | } | ||
1047 | ds_max = max_downscale(&jpg); /* check display constraint */ | ||
1048 | ds_min = min_downscale(&jpg, buf_size); /* check memory constraint */ | ||
1049 | if (ds_min == 0) | ||
1050 | { | ||
1051 | rb->splash(HZ, "too large"); | ||
1052 | file_pt[curfile] = '\0'; | ||
1053 | return change_filename(direction); | ||
1054 | } | ||
1055 | |||
1056 | ds = ds_max; /* initials setting */ | ||
1057 | cx = jpg.x_size/ds/2; /* center the view */ | ||
1058 | cy = jpg.y_size/ds/2; | ||
1059 | |||
1060 | do /* loop the image prepare and decoding when zoomed */ | ||
1061 | { | ||
1062 | p_disp = get_image(&jpg, ds); /* decode or fetch from cache */ | ||
1063 | if (p_disp == NULL) | ||
1064 | return change_filename(direction); | ||
1065 | |||
1066 | set_view(p_disp, cx, cy); | ||
1067 | |||
1068 | if(!running_slideshow) | ||
1069 | { | ||
1070 | rb->snprintf(print, sizeof(print), "showing %dx%d", | ||
1071 | p_disp->width, p_disp->height); | ||
1072 | rb->lcd_puts(0, 3, print); | ||
1073 | rb->lcd_update(); | ||
1074 | } | ||
1075 | MYLCD(clear_display)(); | ||
1076 | #ifdef HAVE_LCD_COLOR | ||
1077 | yuv_bitmap_part( | ||
1078 | p_disp->bitmap, p_disp->csub_x, p_disp->csub_y, | ||
1079 | p_disp->x, p_disp->y, p_disp->stride, | ||
1080 | MAX(0, (LCD_WIDTH - p_disp->width) / 2), | ||
1081 | MAX(0, (LCD_HEIGHT - p_disp->height) / 2), | ||
1082 | MIN(LCD_WIDTH, p_disp->width), | ||
1083 | MIN(LCD_HEIGHT, p_disp->height), | ||
1084 | jpeg_settings.colour_mode, jpeg_settings.dither_mode); | ||
1085 | #else | ||
1086 | MYXLCD(gray_bitmap_part)( | ||
1087 | p_disp->bitmap[0], p_disp->x, p_disp->y, p_disp->stride, | ||
1088 | MAX(0, (LCD_WIDTH - p_disp->width) / 2), | ||
1089 | MAX(0, (LCD_HEIGHT - p_disp->height) / 2), | ||
1090 | MIN(LCD_WIDTH, p_disp->width), | ||
1091 | MIN(LCD_HEIGHT, p_disp->height)); | ||
1092 | #endif | ||
1093 | MYLCD_UPDATE(); | ||
1094 | |||
1095 | #ifdef USEGSLIB | ||
1096 | grey_show(true); /* switch on greyscale overlay */ | ||
1097 | #endif | ||
1098 | |||
1099 | /* drawing is now finished, play around with scrolling | ||
1100 | * until you press OFF or connect USB | ||
1101 | */ | ||
1102 | while (1) | ||
1103 | { | ||
1104 | status = scroll_bmp(p_disp); | ||
1105 | if (status == ZOOM_IN) | ||
1106 | { | ||
1107 | if (ds > ds_min) | ||
1108 | { | ||
1109 | ds /= 2; /* reduce downscaling to zoom in */ | ||
1110 | get_view(p_disp, &cx, &cy); | ||
1111 | cx *= 2; /* prepare the position in the new image */ | ||
1112 | cy *= 2; | ||
1113 | } | ||
1114 | else | ||
1115 | continue; | ||
1116 | } | ||
1117 | |||
1118 | if (status == ZOOM_OUT) | ||
1119 | { | ||
1120 | if (ds < ds_max) | ||
1121 | { | ||
1122 | ds *= 2; /* increase downscaling to zoom out */ | ||
1123 | get_view(p_disp, &cx, &cy); | ||
1124 | cx /= 2; /* prepare the position in the new image */ | ||
1125 | cy /= 2; | ||
1126 | } | ||
1127 | else | ||
1128 | continue; | ||
1129 | } | ||
1130 | break; | ||
1131 | } | ||
1132 | |||
1133 | #ifdef USEGSLIB | ||
1134 | grey_show(false); /* switch off overlay */ | ||
1135 | #endif | ||
1136 | rb->lcd_clear_display(); | ||
1137 | } | ||
1138 | while (status != PLUGIN_OK && status != PLUGIN_USB_CONNECTED | ||
1139 | && status != PLUGIN_OTHER); | ||
1140 | #ifdef USEGSLIB | ||
1141 | rb->lcd_update(); | ||
1142 | #endif | ||
1143 | return status; | ||
1144 | } | ||
1145 | |||
1146 | /******************** Plugin entry point *********************/ | ||
1147 | |||
1148 | enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter) | ||
1149 | { | ||
1150 | rb = api; | ||
1151 | |||
1152 | int condition; | ||
1153 | #ifdef USEGSLIB | ||
1154 | long greysize; /* helper */ | ||
1155 | #endif | ||
1156 | #if LCD_DEPTH > 1 | ||
1157 | old_backdrop = rb->lcd_get_backdrop(); | ||
1158 | #endif | ||
1159 | |||
1160 | if(!parameter) return PLUGIN_ERROR; | ||
1161 | |||
1162 | rb->strcpy(np_file, parameter); | ||
1163 | get_pic_list(); | ||
1164 | |||
1165 | if(!entries) return PLUGIN_ERROR; | ||
1166 | |||
1167 | #if (PLUGIN_BUFFER_SIZE >= MIN_MEM) && !defined(SIMULATOR) | ||
1168 | if(rb->audio_status()) | ||
1169 | { | ||
1170 | buf = rb->plugin_get_buffer((size_t *)&buf_size) + | ||
1171 | (entries * sizeof(char**)); | ||
1172 | buf_size -= (entries * sizeof(char**)); | ||
1173 | plug_buf = true; | ||
1174 | } | ||
1175 | else | ||
1176 | buf = rb->plugin_get_audio_buffer((size_t *)&buf_size); | ||
1177 | #else | ||
1178 | buf = rb->plugin_get_audio_buffer(&buf_size) + | ||
1179 | (entries * sizeof(char**)); | ||
1180 | buf_size -= (entries * sizeof(char**)); | ||
1181 | #endif | ||
1182 | |||
1183 | #ifdef USEGSLIB | ||
1184 | if (!grey_init(rb, buf, buf_size, GREY_ON_COP, | ||
1185 | LCD_WIDTH, LCD_HEIGHT, &greysize)) | ||
1186 | { | ||
1187 | rb->splash(HZ, "grey buf error"); | ||
1188 | return PLUGIN_ERROR; | ||
1189 | } | ||
1190 | buf += greysize; | ||
1191 | buf_size -= greysize; | ||
1192 | #else | ||
1193 | xlcd_init(rb); | ||
1194 | #endif | ||
1195 | |||
1196 | /* should be ok to just load settings since a parameter is present | ||
1197 | here and the drive should be spinning */ | ||
1198 | configfile_init(rb); | ||
1199 | configfile_load(JPEG_CONFIGFILE, jpeg_config, | ||
1200 | ARRAYLEN(jpeg_config), JPEG_SETTINGS_MINVERSION); | ||
1201 | old_settings = jpeg_settings; | ||
1202 | |||
1203 | buf_images = buf; buf_images_size = buf_size; | ||
1204 | |||
1205 | /* Turn off backlight timeout */ | ||
1206 | backlight_force_on(rb); /* backlight control in lib/helper.c */ | ||
1207 | |||
1208 | do | ||
1209 | { | ||
1210 | condition = load_and_show(np_file); | ||
1211 | }while (condition != PLUGIN_OK && condition != PLUGIN_USB_CONNECTED | ||
1212 | && condition != PLUGIN_ERROR); | ||
1213 | |||
1214 | if (rb->memcmp(&jpeg_settings, &old_settings, sizeof (jpeg_settings))) | ||
1215 | { | ||
1216 | /* Just in case drive has to spin, keep it from looking locked */ | ||
1217 | rb->splash(0, "Saving Settings"); | ||
1218 | configfile_save(JPEG_CONFIGFILE, jpeg_config, | ||
1219 | ARRAYLEN(jpeg_config), JPEG_SETTINGS_VERSION); | ||
1220 | } | ||
1221 | |||
1222 | #if !defined(SIMULATOR) && defined(HAVE_DISK_STORAGE) | ||
1223 | /* set back ata spindown time in case we changed it */ | ||
1224 | rb->ata_spindown(rb->global_settings->disk_spindown); | ||
1225 | #endif | ||
1226 | |||
1227 | /* Turn on backlight timeout (revert to settings) */ | ||
1228 | backlight_use_settings(rb); /* backlight control in lib/helper.c */ | ||
1229 | |||
1230 | #ifdef USEGSLIB | ||
1231 | grey_release(); /* deinitialize */ | ||
1232 | #endif | ||
1233 | |||
1234 | return condition; | ||
1235 | } | ||
diff --git a/apps/plugins/jpeg/jpeg.h b/apps/plugins/jpeg/jpeg.h new file mode 100644 index 0000000000..1a24948a19 --- /dev/null +++ b/apps/plugins/jpeg/jpeg.h | |||
@@ -0,0 +1,256 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * JPEG image viewer | ||
11 | * (This is a real mess if it has to be coded in one single C file) | ||
12 | * | ||
13 | * File scrolling addition (C) 2005 Alexander Spyridakis | ||
14 | * Copyright (C) 2004 Jörg Hohensohn aka [IDC]Dragon | ||
15 | * Heavily borrowed from the IJG implementation (C) Thomas G. Lane | ||
16 | * Small & fast downscaling IDCT (C) 2002 by Guido Vollbeding JPEGclub.org | ||
17 | * | ||
18 | * This program is free software; you can redistribute it and/or | ||
19 | * modify it under the terms of the GNU General Public License | ||
20 | * as published by the Free Software Foundation; either version 2 | ||
21 | * of the License, or (at your option) any later version. | ||
22 | * | ||
23 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
24 | * KIND, either express or implied. | ||
25 | * | ||
26 | ****************************************************************************/ | ||
27 | |||
28 | #ifndef _JPEG_JPEG_H | ||
29 | #define _JPEG_JPEG_H | ||
30 | |||
31 | #include "plugin.h" | ||
32 | |||
33 | /* variable button definitions */ | ||
34 | #if CONFIG_KEYPAD == RECORDER_PAD | ||
35 | #define JPEG_ZOOM_IN BUTTON_PLAY | ||
36 | #define JPEG_ZOOM_OUT BUTTON_ON | ||
37 | #define JPEG_UP BUTTON_UP | ||
38 | #define JPEG_DOWN BUTTON_DOWN | ||
39 | #define JPEG_LEFT BUTTON_LEFT | ||
40 | #define JPEG_RIGHT BUTTON_RIGHT | ||
41 | #define JPEG_NEXT BUTTON_F3 | ||
42 | #define JPEG_PREVIOUS BUTTON_F2 | ||
43 | #define JPEG_MENU BUTTON_OFF | ||
44 | |||
45 | #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD | ||
46 | #define JPEG_ZOOM_IN BUTTON_SELECT | ||
47 | #define JPEG_ZOOM_OUT BUTTON_ON | ||
48 | #define JPEG_UP BUTTON_UP | ||
49 | #define JPEG_DOWN BUTTON_DOWN | ||
50 | #define JPEG_LEFT BUTTON_LEFT | ||
51 | #define JPEG_RIGHT BUTTON_RIGHT | ||
52 | #define JPEG_NEXT BUTTON_F3 | ||
53 | #define JPEG_PREVIOUS BUTTON_F2 | ||
54 | #define JPEG_MENU BUTTON_OFF | ||
55 | |||
56 | #elif CONFIG_KEYPAD == ONDIO_PAD | ||
57 | #define JPEG_ZOOM_PRE BUTTON_MENU | ||
58 | #define JPEG_ZOOM_IN (BUTTON_MENU | BUTTON_REL) | ||
59 | #define JPEG_ZOOM_OUT (BUTTON_MENU | BUTTON_DOWN) | ||
60 | #define JPEG_UP BUTTON_UP | ||
61 | #define JPEG_DOWN BUTTON_DOWN | ||
62 | #define JPEG_LEFT BUTTON_LEFT | ||
63 | #define JPEG_RIGHT BUTTON_RIGHT | ||
64 | #define JPEG_NEXT (BUTTON_MENU | BUTTON_RIGHT) | ||
65 | #define JPEG_PREVIOUS (BUTTON_MENU | BUTTON_LEFT) | ||
66 | #define JPEG_MENU BUTTON_OFF | ||
67 | |||
68 | #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ | ||
69 | (CONFIG_KEYPAD == IRIVER_H300_PAD) | ||
70 | #define JPEG_ZOOM_IN BUTTON_SELECT | ||
71 | #define JPEG_ZOOM_OUT BUTTON_MODE | ||
72 | #define JPEG_UP BUTTON_UP | ||
73 | #define JPEG_DOWN BUTTON_DOWN | ||
74 | #define JPEG_LEFT BUTTON_LEFT | ||
75 | #define JPEG_RIGHT BUTTON_RIGHT | ||
76 | #if (CONFIG_KEYPAD == IRIVER_H100_PAD) | ||
77 | #define JPEG_NEXT BUTTON_ON | ||
78 | #define JPEG_PREVIOUS BUTTON_REC | ||
79 | #else | ||
80 | #define JPEG_NEXT BUTTON_REC | ||
81 | #define JPEG_PREVIOUS BUTTON_ON | ||
82 | #endif | ||
83 | #define JPEG_MENU BUTTON_OFF | ||
84 | #define JPEG_RC_MENU BUTTON_RC_STOP | ||
85 | |||
86 | #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \ | ||
87 | (CONFIG_KEYPAD == IPOD_1G2G_PAD) | ||
88 | #define JPEG_ZOOM_IN BUTTON_SCROLL_FWD | ||
89 | #define JPEG_ZOOM_OUT BUTTON_SCROLL_BACK | ||
90 | #define JPEG_UP BUTTON_MENU | ||
91 | #define JPEG_DOWN BUTTON_PLAY | ||
92 | #define JPEG_LEFT BUTTON_LEFT | ||
93 | #define JPEG_RIGHT BUTTON_RIGHT | ||
94 | #define JPEG_MENU (BUTTON_SELECT | BUTTON_MENU) | ||
95 | #define JPEG_NEXT (BUTTON_SELECT | BUTTON_RIGHT) | ||
96 | #define JPEG_PREVIOUS (BUTTON_SELECT | BUTTON_LEFT) | ||
97 | |||
98 | #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD | ||
99 | #define JPEG_ZOOM_PRE BUTTON_SELECT | ||
100 | #define JPEG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) | ||
101 | #define JPEG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) | ||
102 | #define JPEG_UP BUTTON_UP | ||
103 | #define JPEG_DOWN BUTTON_DOWN | ||
104 | #define JPEG_LEFT BUTTON_LEFT | ||
105 | #define JPEG_RIGHT BUTTON_RIGHT | ||
106 | #define JPEG_MENU BUTTON_POWER | ||
107 | #define JPEG_NEXT BUTTON_PLAY | ||
108 | #define JPEG_PREVIOUS BUTTON_REC | ||
109 | |||
110 | #elif CONFIG_KEYPAD == GIGABEAT_PAD | ||
111 | #define JPEG_ZOOM_IN BUTTON_VOL_UP | ||
112 | #define JPEG_ZOOM_OUT BUTTON_VOL_DOWN | ||
113 | #define JPEG_UP BUTTON_UP | ||
114 | #define JPEG_DOWN BUTTON_DOWN | ||
115 | #define JPEG_LEFT BUTTON_LEFT | ||
116 | #define JPEG_RIGHT BUTTON_RIGHT | ||
117 | #define JPEG_MENU BUTTON_MENU | ||
118 | #define JPEG_NEXT (BUTTON_A | BUTTON_RIGHT) | ||
119 | #define JPEG_PREVIOUS (BUTTON_A | BUTTON_LEFT) | ||
120 | |||
121 | #elif CONFIG_KEYPAD == SANSA_E200_PAD | ||
122 | #define JPEG_ZOOM_PRE BUTTON_SELECT | ||
123 | #define JPEG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) | ||
124 | #define JPEG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) | ||
125 | #define JPEG_UP BUTTON_UP | ||
126 | #define JPEG_DOWN BUTTON_DOWN | ||
127 | #define JPEG_LEFT BUTTON_LEFT | ||
128 | #define JPEG_RIGHT BUTTON_RIGHT | ||
129 | #define JPEG_MENU BUTTON_POWER | ||
130 | #define JPEG_SLIDE_SHOW BUTTON_REC | ||
131 | #define JPEG_NEXT BUTTON_SCROLL_FWD | ||
132 | #define JPEG_NEXT_REPEAT (BUTTON_SCROLL_FWD|BUTTON_REPEAT) | ||
133 | #define JPEG_PREVIOUS BUTTON_SCROLL_BACK | ||
134 | #define JPEG_PREVIOUS_REPEAT (BUTTON_SCROLL_BACK|BUTTON_REPEAT) | ||
135 | |||
136 | #elif CONFIG_KEYPAD == SANSA_C200_PAD | ||
137 | #define JPEG_ZOOM_PRE BUTTON_SELECT | ||
138 | #define JPEG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) | ||
139 | #define JPEG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) | ||
140 | #define JPEG_UP BUTTON_UP | ||
141 | #define JPEG_DOWN BUTTON_DOWN | ||
142 | #define JPEG_LEFT BUTTON_LEFT | ||
143 | #define JPEG_RIGHT BUTTON_RIGHT | ||
144 | #define JPEG_MENU BUTTON_POWER | ||
145 | #define JPEG_SLIDE_SHOW BUTTON_REC | ||
146 | #define JPEG_NEXT BUTTON_VOL_UP | ||
147 | #define JPEG_NEXT_REPEAT (BUTTON_VOL_UP|BUTTON_REPEAT) | ||
148 | #define JPEG_PREVIOUS BUTTON_VOL_DOWN | ||
149 | #define JPEG_PREVIOUS_REPEAT (BUTTON_VOL_DOWN|BUTTON_REPEAT) | ||
150 | |||
151 | #elif CONFIG_KEYPAD == IRIVER_H10_PAD | ||
152 | #define JPEG_ZOOM_PRE BUTTON_PLAY | ||
153 | #define JPEG_ZOOM_IN (BUTTON_PLAY | BUTTON_REL) | ||
154 | #define JPEG_ZOOM_OUT (BUTTON_PLAY | BUTTON_REPEAT) | ||
155 | #define JPEG_UP BUTTON_SCROLL_UP | ||
156 | #define JPEG_DOWN BUTTON_SCROLL_DOWN | ||
157 | #define JPEG_LEFT BUTTON_LEFT | ||
158 | #define JPEG_RIGHT BUTTON_RIGHT | ||
159 | #define JPEG_MENU BUTTON_POWER | ||
160 | #define JPEG_NEXT BUTTON_FF | ||
161 | #define JPEG_PREVIOUS BUTTON_REW | ||
162 | |||
163 | #elif CONFIG_KEYPAD == MROBE500_PAD | ||
164 | #define JPEG_ZOOM_IN BUTTON_RC_VOL_UP | ||
165 | #define JPEG_ZOOM_OUT BUTTON_RC_VOL_DOWN | ||
166 | #define JPEG_UP BUTTON_RC_PLAY | ||
167 | #define JPEG_DOWN BUTTON_RC_DOWN | ||
168 | #define JPEG_LEFT BUTTON_LEFT | ||
169 | #define JPEG_RIGHT BUTTON_RIGHT | ||
170 | #define JPEG_MENU BUTTON_POWER | ||
171 | #define JPEG_NEXT BUTTON_RC_HEART | ||
172 | #define JPEG_PREVIOUS BUTTON_RC_MODE | ||
173 | |||
174 | #elif CONFIG_KEYPAD == GIGABEAT_S_PAD | ||
175 | #define JPEG_ZOOM_IN BUTTON_VOL_UP | ||
176 | #define JPEG_ZOOM_OUT BUTTON_VOL_DOWN | ||
177 | #define JPEG_UP BUTTON_UP | ||
178 | #define JPEG_DOWN BUTTON_DOWN | ||
179 | #define JPEG_LEFT BUTTON_LEFT | ||
180 | #define JPEG_RIGHT BUTTON_RIGHT | ||
181 | #define JPEG_MENU BUTTON_MENU | ||
182 | #define JPEG_NEXT BUTTON_NEXT | ||
183 | #define JPEG_PREVIOUS BUTTON_PREV | ||
184 | |||
185 | #elif CONFIG_KEYPAD == MROBE100_PAD | ||
186 | #define JPEG_ZOOM_IN BUTTON_SELECT | ||
187 | #define JPEG_ZOOM_OUT BUTTON_PLAY | ||
188 | #define JPEG_UP BUTTON_UP | ||
189 | #define JPEG_DOWN BUTTON_DOWN | ||
190 | #define JPEG_LEFT BUTTON_LEFT | ||
191 | #define JPEG_RIGHT BUTTON_RIGHT | ||
192 | #define JPEG_MENU BUTTON_MENU | ||
193 | #define JPEG_NEXT (BUTTON_DISPLAY | BUTTON_RIGHT) | ||
194 | #define JPEG_PREVIOUS (BUTTON_DISPLAY | BUTTON_LEFT) | ||
195 | |||
196 | #elif CONFIG_KEYPAD == IAUDIO_M3_PAD | ||
197 | #define JPEG_ZOOM_PRE BUTTON_RC_PLAY | ||
198 | #define JPEG_ZOOM_IN (BUTTON_RC_PLAY|BUTTON_REL) | ||
199 | #define JPEG_ZOOM_OUT (BUTTON_RC_PLAY|BUTTON_REPEAT) | ||
200 | #define JPEG_UP BUTTON_RC_VOL_UP | ||
201 | #define JPEG_DOWN BUTTON_RC_VOL_DOWN | ||
202 | #define JPEG_LEFT BUTTON_RC_REW | ||
203 | #define JPEG_RIGHT BUTTON_RC_FF | ||
204 | #define JPEG_MENU BUTTON_RC_REC | ||
205 | #define JPEG_NEXT BUTTON_RC_MODE | ||
206 | #define JPEG_PREVIOUS BUTTON_RC_MENU | ||
207 | |||
208 | #elif CONFIG_KEYPAD == COWOND2_PAD | ||
209 | |||
210 | #elif CONFIG_KEYPAD == IAUDIO67_PAD | ||
211 | #define JPEG_ZOOM_IN BUTTON_VOLUP | ||
212 | #define JPEG_ZOOM_OUT BUTTON_VOLDOWN | ||
213 | #define JPEG_UP BUTTON_STOP | ||
214 | #define JPEG_DOWN BUTTON_PLAY | ||
215 | #define JPEG_LEFT BUTTON_LEFT | ||
216 | #define JPEG_RIGHT BUTTON_RIGHT | ||
217 | #define JPEG_MENU BUTTON_MENU | ||
218 | #define JPEG_NEXT (BUTTON_PLAY|BUTTON_VOLUP) | ||
219 | #define JPEG_PREVIOUS (BUTTON_PLAY|BUTTON_VOLDOWN) | ||
220 | |||
221 | #else | ||
222 | #error No keymap defined! | ||
223 | #endif | ||
224 | |||
225 | #ifdef HAVE_TOUCHSCREEN | ||
226 | #ifndef JPEG_UP | ||
227 | #define JPEG_UP BUTTON_TOPMIDDLE | ||
228 | #endif | ||
229 | #ifndef JPEG_DOWN | ||
230 | #define JPEG_DOWN BUTTON_BOTTOMMIDDLE | ||
231 | #endif | ||
232 | #ifndef JPEG_LEFT | ||
233 | #define JPEG_LEFT BUTTON_MIDLEFT | ||
234 | #endif | ||
235 | #ifndef JPEG_RIGHT | ||
236 | #define JPEG_RIGHT BUTTON_MIDRIGHT | ||
237 | #endif | ||
238 | #ifndef JPEG_ZOOM_IN | ||
239 | #define JPEG_ZOOM_IN BUTTON_TOPRIGHT | ||
240 | #endif | ||
241 | #ifndef JPEG_ZOOM_OUT | ||
242 | #define JPEG_ZOOM_OUT BUTTON_TOPLEFT | ||
243 | #endif | ||
244 | #ifndef JPEG_MENU | ||
245 | #define JPEG_MENU (BUTTON_CENTER|BUTTON_REL) | ||
246 | #endif | ||
247 | #ifndef JPEG_NEXT | ||
248 | #define JPEG_NEXT BUTTON_BOTTOMRIGHT | ||
249 | #endif | ||
250 | #ifndef JPEG_PREVIOUS | ||
251 | #define JPEG_PREVIOUS BUTTON_BOTTOMLEFT | ||
252 | #endif | ||
253 | #endif | ||
254 | |||
255 | |||
256 | #endif /* _JPEG_JPEG_H */ | ||
diff --git a/apps/plugins/jpeg/jpeg_decoder.c b/apps/plugins/jpeg/jpeg_decoder.c new file mode 100644 index 0000000000..ffd71a1320 --- /dev/null +++ b/apps/plugins/jpeg/jpeg_decoder.c | |||
@@ -0,0 +1,1540 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * JPEG image viewer | ||
11 | * (This is a real mess if it has to be coded in one single C file) | ||
12 | * | ||
13 | * File scrolling addition (C) 2005 Alexander Spyridakis | ||
14 | * Copyright (C) 2004 Jörg Hohensohn aka [IDC]Dragon | ||
15 | * Heavily borrowed from the IJG implementation (C) Thomas G. Lane | ||
16 | * Small & fast downscaling IDCT (C) 2002 by Guido Vollbeding JPEGclub.org | ||
17 | * | ||
18 | * This program is free software; you can redistribute it and/or | ||
19 | * modify it under the terms of the GNU General Public License | ||
20 | * as published by the Free Software Foundation; either version 2 | ||
21 | * of the License, or (at your option) any later version. | ||
22 | * | ||
23 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
24 | * KIND, either express or implied. | ||
25 | * | ||
26 | ****************************************************************************/ | ||
27 | |||
28 | #include "plugin.h" | ||
29 | |||
30 | #include "jpeg_decoder.h" | ||
31 | |||
32 | extern const struct plugin_api* rb; | ||
33 | |||
34 | /* for portability of below JPEG code */ | ||
35 | #define MEMSET(p,v,c) rb->memset(p,v,c) | ||
36 | #define MEMCPY(d,s,c) rb->memcpy(d,s,c) | ||
37 | #define INLINE static inline | ||
38 | #define ENDIAN_SWAP16(n) n /* only for poor little endian machines */ | ||
39 | |||
40 | /**************** begin JPEG code ********************/ | ||
41 | |||
42 | INLINE unsigned range_limit(int value) | ||
43 | { | ||
44 | #if CONFIG_CPU == SH7034 | ||
45 | unsigned tmp; | ||
46 | asm ( /* Note: Uses knowledge that only low byte of result is used */ | ||
47 | "mov #-128,%[t] \n" | ||
48 | "sub %[t],%[v] \n" /* value -= -128; equals value += 128; */ | ||
49 | "extu.b %[v],%[t] \n" | ||
50 | "cmp/eq %[v],%[t] \n" /* low byte == whole number ? */ | ||
51 | "bt 1f \n" /* yes: no overflow */ | ||
52 | "cmp/pz %[v] \n" /* overflow: positive? */ | ||
53 | "subc %[v],%[v] \n" /* %[r] now either 0 or 0xffffffff */ | ||
54 | "1: \n" | ||
55 | : /* outputs */ | ||
56 | [v]"+r"(value), | ||
57 | [t]"=&r"(tmp) | ||
58 | ); | ||
59 | return value; | ||
60 | #elif defined(CPU_COLDFIRE) | ||
61 | asm ( /* Note: Uses knowledge that only the low byte of the result is used */ | ||
62 | "add.l #128,%[v] \n" /* value += 128; */ | ||
63 | "cmp.l #255,%[v] \n" /* overflow? */ | ||
64 | "bls.b 1f \n" /* no: return value */ | ||
65 | "spl.b %[v] \n" /* yes: set low byte to appropriate boundary */ | ||
66 | "1: \n" | ||
67 | : /* outputs */ | ||
68 | [v]"+d"(value) | ||
69 | ); | ||
70 | return value; | ||
71 | #elif defined(CPU_ARM) | ||
72 | asm ( /* Note: Uses knowledge that only the low byte of the result is used */ | ||
73 | "add %[v], %[v], #128 \n" /* value += 128 */ | ||
74 | "cmp %[v], #255 \n" /* out of range 0..255? */ | ||
75 | "mvnhi %[v], %[v], asr #31 \n" /* yes: set all bits to ~(sign_bit) */ | ||
76 | : /* outputs */ | ||
77 | [v]"+r"(value) | ||
78 | ); | ||
79 | return value; | ||
80 | #else | ||
81 | value += 128; | ||
82 | |||
83 | if ((unsigned)value <= 255) | ||
84 | return value; | ||
85 | |||
86 | if (value < 0) | ||
87 | return 0; | ||
88 | |||
89 | return 255; | ||
90 | #endif | ||
91 | } | ||
92 | |||
93 | /* IDCT implementation */ | ||
94 | |||
95 | |||
96 | #define CONST_BITS 13 | ||
97 | #define PASS1_BITS 2 | ||
98 | |||
99 | |||
100 | /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus | ||
101 | * causing a lot of useless floating-point operations at run time. | ||
102 | * To get around this we use the following pre-calculated constants. | ||
103 | * If you change CONST_BITS you may want to add appropriate values. | ||
104 | * (With a reasonable C compiler, you can just rely on the FIX() macro...) | ||
105 | */ | ||
106 | #define FIX_0_298631336 2446 /* FIX(0.298631336) */ | ||
107 | #define FIX_0_390180644 3196 /* FIX(0.390180644) */ | ||
108 | #define FIX_0_541196100 4433 /* FIX(0.541196100) */ | ||
109 | #define FIX_0_765366865 6270 /* FIX(0.765366865) */ | ||
110 | #define FIX_0_899976223 7373 /* FIX(0.899976223) */ | ||
111 | #define FIX_1_175875602 9633 /* FIX(1.175875602) */ | ||
112 | #define FIX_1_501321110 12299 /* FIX(1.501321110) */ | ||
113 | #define FIX_1_847759065 15137 /* FIX(1.847759065) */ | ||
114 | #define FIX_1_961570560 16069 /* FIX(1.961570560) */ | ||
115 | #define FIX_2_053119869 16819 /* FIX(2.053119869) */ | ||
116 | #define FIX_2_562915447 20995 /* FIX(2.562915447) */ | ||
117 | #define FIX_3_072711026 25172 /* FIX(3.072711026) */ | ||
118 | |||
119 | |||
120 | |||
121 | /* Multiply an long variable by an long constant to yield an long result. | ||
122 | * For 8-bit samples with the recommended scaling, all the variable | ||
123 | * and constant values involved are no more than 16 bits wide, so a | ||
124 | * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. | ||
125 | * For 12-bit samples, a full 32-bit multiplication will be needed. | ||
126 | */ | ||
127 | #define MULTIPLY16(var,const) (((short) (var)) * ((short) (const))) | ||
128 | |||
129 | |||
130 | /* Dequantize a coefficient by multiplying it by the multiplier-table | ||
131 | * entry; produce an int result. In this module, both inputs and result | ||
132 | * are 16 bits or less, so either int or short multiply will work. | ||
133 | */ | ||
134 | /* #define DEQUANTIZE(coef,quantval) (((int) (coef)) * (quantval)) */ | ||
135 | #define DEQUANTIZE MULTIPLY16 | ||
136 | |||
137 | /* Descale and correctly round an int value that's scaled by N bits. | ||
138 | * We assume RIGHT_SHIFT rounds towards minus infinity, so adding | ||
139 | * the fudge factor is correct for either sign of X. | ||
140 | */ | ||
141 | #define DESCALE(x,n) (((x) + (1l << ((n)-1))) >> (n)) | ||
142 | |||
143 | |||
144 | |||
145 | /* | ||
146 | * Perform dequantization and inverse DCT on one block of coefficients, | ||
147 | * producing a reduced-size 1x1 output block. | ||
148 | */ | ||
149 | void idct1x1(unsigned char* p_byte, int* inptr, int* quantptr, int skip_line) | ||
150 | { | ||
151 | (void)skip_line; /* unused */ | ||
152 | *p_byte = range_limit(inptr[0] * quantptr[0] >> 3); | ||
153 | } | ||
154 | |||
155 | |||
156 | |||
157 | /* | ||
158 | * Perform dequantization and inverse DCT on one block of coefficients, | ||
159 | * producing a reduced-size 2x2 output block. | ||
160 | */ | ||
161 | void idct2x2(unsigned char* p_byte, int* inptr, int* quantptr, int skip_line) | ||
162 | { | ||
163 | int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; | ||
164 | unsigned char* outptr; | ||
165 | |||
166 | /* Pass 1: process columns from input, store into work array. */ | ||
167 | |||
168 | /* Column 0 */ | ||
169 | tmp4 = DEQUANTIZE(inptr[8*0], quantptr[8*0]); | ||
170 | tmp5 = DEQUANTIZE(inptr[8*1], quantptr[8*1]); | ||
171 | |||
172 | tmp0 = tmp4 + tmp5; | ||
173 | tmp2 = tmp4 - tmp5; | ||
174 | |||
175 | /* Column 1 */ | ||
176 | tmp4 = DEQUANTIZE(inptr[8*0+1], quantptr[8*0+1]); | ||
177 | tmp5 = DEQUANTIZE(inptr[8*1+1], quantptr[8*1+1]); | ||
178 | |||
179 | tmp1 = tmp4 + tmp5; | ||
180 | tmp3 = tmp4 - tmp5; | ||
181 | |||
182 | /* Pass 2: process 2 rows, store into output array. */ | ||
183 | |||
184 | /* Row 0 */ | ||
185 | outptr = p_byte; | ||
186 | |||
187 | outptr[0] = range_limit((int) DESCALE(tmp0 + tmp1, 3)); | ||
188 | outptr[1] = range_limit((int) DESCALE(tmp0 - tmp1, 3)); | ||
189 | |||
190 | /* Row 1 */ | ||
191 | outptr = p_byte + skip_line; | ||
192 | |||
193 | outptr[0] = range_limit((int) DESCALE(tmp2 + tmp3, 3)); | ||
194 | outptr[1] = range_limit((int) DESCALE(tmp2 - tmp3, 3)); | ||
195 | } | ||
196 | |||
197 | |||
198 | |||
199 | /* | ||
200 | * Perform dequantization and inverse DCT on one block of coefficients, | ||
201 | * producing a reduced-size 4x4 output block. | ||
202 | */ | ||
203 | void idct4x4(unsigned char* p_byte, int* inptr, int* quantptr, int skip_line) | ||
204 | { | ||
205 | int tmp0, tmp2, tmp10, tmp12; | ||
206 | int z1, z2, z3; | ||
207 | int * wsptr; | ||
208 | unsigned char* outptr; | ||
209 | int ctr; | ||
210 | int workspace[4*4]; /* buffers data between passes */ | ||
211 | |||
212 | /* Pass 1: process columns from input, store into work array. */ | ||
213 | |||
214 | wsptr = workspace; | ||
215 | for (ctr = 0; ctr < 4; ctr++, inptr++, quantptr++, wsptr++) | ||
216 | { | ||
217 | /* Even part */ | ||
218 | |||
219 | tmp0 = DEQUANTIZE(inptr[8*0], quantptr[8*0]); | ||
220 | tmp2 = DEQUANTIZE(inptr[8*2], quantptr[8*2]); | ||
221 | |||
222 | tmp10 = (tmp0 + tmp2) << PASS1_BITS; | ||
223 | tmp12 = (tmp0 - tmp2) << PASS1_BITS; | ||
224 | |||
225 | /* Odd part */ | ||
226 | /* Same rotation as in the even part of the 8x8 LL&M IDCT */ | ||
227 | |||
228 | z2 = DEQUANTIZE(inptr[8*1], quantptr[8*1]); | ||
229 | z3 = DEQUANTIZE(inptr[8*3], quantptr[8*3]); | ||
230 | |||
231 | z1 = MULTIPLY16(z2 + z3, FIX_0_541196100); | ||
232 | tmp0 = DESCALE(z1 + MULTIPLY16(z3, - FIX_1_847759065), CONST_BITS-PASS1_BITS); | ||
233 | tmp2 = DESCALE(z1 + MULTIPLY16(z2, FIX_0_765366865), CONST_BITS-PASS1_BITS); | ||
234 | |||
235 | /* Final output stage */ | ||
236 | |||
237 | wsptr[4*0] = (int) (tmp10 + tmp2); | ||
238 | wsptr[4*3] = (int) (tmp10 - tmp2); | ||
239 | wsptr[4*1] = (int) (tmp12 + tmp0); | ||
240 | wsptr[4*2] = (int) (tmp12 - tmp0); | ||
241 | } | ||
242 | |||
243 | /* Pass 2: process 4 rows from work array, store into output array. */ | ||
244 | |||
245 | wsptr = workspace; | ||
246 | for (ctr = 0; ctr < 4; ctr++) | ||
247 | { | ||
248 | outptr = p_byte + (ctr*skip_line); | ||
249 | /* Even part */ | ||
250 | |||
251 | tmp0 = (int) wsptr[0]; | ||
252 | tmp2 = (int) wsptr[2]; | ||
253 | |||
254 | tmp10 = (tmp0 + tmp2) << CONST_BITS; | ||
255 | tmp12 = (tmp0 - tmp2) << CONST_BITS; | ||
256 | |||
257 | /* Odd part */ | ||
258 | /* Same rotation as in the even part of the 8x8 LL&M IDCT */ | ||
259 | |||
260 | z2 = (int) wsptr[1]; | ||
261 | z3 = (int) wsptr[3]; | ||
262 | |||
263 | z1 = MULTIPLY16(z2 + z3, FIX_0_541196100); | ||
264 | tmp0 = z1 + MULTIPLY16(z3, - FIX_1_847759065); | ||
265 | tmp2 = z1 + MULTIPLY16(z2, FIX_0_765366865); | ||
266 | |||
267 | /* Final output stage */ | ||
268 | |||
269 | outptr[0] = range_limit((int) DESCALE(tmp10 + tmp2, | ||
270 | CONST_BITS+PASS1_BITS+3)); | ||
271 | outptr[3] = range_limit((int) DESCALE(tmp10 - tmp2, | ||
272 | CONST_BITS+PASS1_BITS+3)); | ||
273 | outptr[1] = range_limit((int) DESCALE(tmp12 + tmp0, | ||
274 | CONST_BITS+PASS1_BITS+3)); | ||
275 | outptr[2] = range_limit((int) DESCALE(tmp12 - tmp0, | ||
276 | CONST_BITS+PASS1_BITS+3)); | ||
277 | |||
278 | wsptr += 4; /* advance pointer to next row */ | ||
279 | } | ||
280 | } | ||
281 | |||
282 | |||
283 | |||
284 | /* | ||
285 | * Perform dequantization and inverse DCT on one block of coefficients. | ||
286 | */ | ||
287 | void idct8x8(unsigned char* p_byte, int* inptr, int* quantptr, int skip_line) | ||
288 | { | ||
289 | long tmp0, tmp1, tmp2, tmp3; | ||
290 | long tmp10, tmp11, tmp12, tmp13; | ||
291 | long z1, z2, z3, z4, z5; | ||
292 | int * wsptr; | ||
293 | unsigned char* outptr; | ||
294 | int ctr; | ||
295 | int workspace[64]; /* buffers data between passes */ | ||
296 | |||
297 | /* Pass 1: process columns from input, store into work array. */ | ||
298 | /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ | ||
299 | /* furthermore, we scale the results by 2**PASS1_BITS. */ | ||
300 | |||
301 | wsptr = workspace; | ||
302 | for (ctr = 8; ctr > 0; ctr--) | ||
303 | { | ||
304 | /* Due to quantization, we will usually find that many of the input | ||
305 | * coefficients are zero, especially the AC terms. We can exploit this | ||
306 | * by short-circuiting the IDCT calculation for any column in which all | ||
307 | * the AC terms are zero. In that case each output is equal to the | ||
308 | * DC coefficient (with scale factor as needed). | ||
309 | * With typical images and quantization tables, half or more of the | ||
310 | * column DCT calculations can be simplified this way. | ||
311 | */ | ||
312 | |||
313 | if ((inptr[8*1] | inptr[8*2] | inptr[8*3] | ||
314 | | inptr[8*4] | inptr[8*5] | inptr[8*6] | inptr[8*7]) == 0) | ||
315 | { | ||
316 | /* AC terms all zero */ | ||
317 | int dcval = DEQUANTIZE(inptr[8*0], quantptr[8*0]) << PASS1_BITS; | ||
318 | |||
319 | wsptr[8*0] = wsptr[8*1] = wsptr[8*2] = wsptr[8*3] = wsptr[8*4] | ||
320 | = wsptr[8*5] = wsptr[8*6] = wsptr[8*7] = dcval; | ||
321 | inptr++; /* advance pointers to next column */ | ||
322 | quantptr++; | ||
323 | wsptr++; | ||
324 | continue; | ||
325 | } | ||
326 | |||
327 | /* Even part: reverse the even part of the forward DCT. */ | ||
328 | /* The rotator is sqrt(2)*c(-6). */ | ||
329 | |||
330 | z2 = DEQUANTIZE(inptr[8*2], quantptr[8*2]); | ||
331 | z3 = DEQUANTIZE(inptr[8*6], quantptr[8*6]); | ||
332 | |||
333 | z1 = MULTIPLY16(z2 + z3, FIX_0_541196100); | ||
334 | tmp2 = z1 + MULTIPLY16(z3, - FIX_1_847759065); | ||
335 | tmp3 = z1 + MULTIPLY16(z2, FIX_0_765366865); | ||
336 | |||
337 | z2 = DEQUANTIZE(inptr[8*0], quantptr[8*0]); | ||
338 | z3 = DEQUANTIZE(inptr[8*4], quantptr[8*4]); | ||
339 | |||
340 | tmp0 = (z2 + z3) << CONST_BITS; | ||
341 | tmp1 = (z2 - z3) << CONST_BITS; | ||
342 | |||
343 | tmp10 = tmp0 + tmp3; | ||
344 | tmp13 = tmp0 - tmp3; | ||
345 | tmp11 = tmp1 + tmp2; | ||
346 | tmp12 = tmp1 - tmp2; | ||
347 | |||
348 | /* Odd part per figure 8; the matrix is unitary and hence its | ||
349 | transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */ | ||
350 | |||
351 | tmp0 = DEQUANTIZE(inptr[8*7], quantptr[8*7]); | ||
352 | tmp1 = DEQUANTIZE(inptr[8*5], quantptr[8*5]); | ||
353 | tmp2 = DEQUANTIZE(inptr[8*3], quantptr[8*3]); | ||
354 | tmp3 = DEQUANTIZE(inptr[8*1], quantptr[8*1]); | ||
355 | |||
356 | z1 = tmp0 + tmp3; | ||
357 | z2 = tmp1 + tmp2; | ||
358 | z3 = tmp0 + tmp2; | ||
359 | z4 = tmp1 + tmp3; | ||
360 | z5 = MULTIPLY16(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ | ||
361 | |||
362 | tmp0 = MULTIPLY16(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ | ||
363 | tmp1 = MULTIPLY16(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ | ||
364 | tmp2 = MULTIPLY16(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ | ||
365 | tmp3 = MULTIPLY16(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ | ||
366 | z1 = MULTIPLY16(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ | ||
367 | z2 = MULTIPLY16(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ | ||
368 | z3 = MULTIPLY16(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ | ||
369 | z4 = MULTIPLY16(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ | ||
370 | |||
371 | z3 += z5; | ||
372 | z4 += z5; | ||
373 | |||
374 | tmp0 += z1 + z3; | ||
375 | tmp1 += z2 + z4; | ||
376 | tmp2 += z2 + z3; | ||
377 | tmp3 += z1 + z4; | ||
378 | |||
379 | /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ | ||
380 | |||
381 | wsptr[8*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS); | ||
382 | wsptr[8*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS); | ||
383 | wsptr[8*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS); | ||
384 | wsptr[8*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS); | ||
385 | wsptr[8*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS); | ||
386 | wsptr[8*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS); | ||
387 | wsptr[8*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS); | ||
388 | wsptr[8*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS); | ||
389 | |||
390 | inptr++; /* advance pointers to next column */ | ||
391 | quantptr++; | ||
392 | wsptr++; | ||
393 | } | ||
394 | |||
395 | /* Pass 2: process rows from work array, store into output array. */ | ||
396 | /* Note that we must descale the results by a factor of 8 == 2**3, */ | ||
397 | /* and also undo the PASS1_BITS scaling. */ | ||
398 | |||
399 | wsptr = workspace; | ||
400 | for (ctr = 0; ctr < 8; ctr++) | ||
401 | { | ||
402 | outptr = p_byte + (ctr*skip_line); | ||
403 | /* Rows of zeroes can be exploited in the same way as we did with columns. | ||
404 | * However, the column calculation has created many nonzero AC terms, so | ||
405 | * the simplification applies less often (typically 5% to 10% of the time). | ||
406 | * On machines with very fast multiplication, it's possible that the | ||
407 | * test takes more time than it's worth. In that case this section | ||
408 | * may be commented out. | ||
409 | */ | ||
410 | |||
411 | #ifndef NO_ZERO_ROW_TEST | ||
412 | if ((wsptr[1] | wsptr[2] | wsptr[3] | ||
413 | | wsptr[4] | wsptr[5] | wsptr[6] | wsptr[7]) == 0) | ||
414 | { | ||
415 | /* AC terms all zero */ | ||
416 | unsigned char dcval = range_limit((int) DESCALE((long) wsptr[0], | ||
417 | PASS1_BITS+3)); | ||
418 | |||
419 | outptr[0] = dcval; | ||
420 | outptr[1] = dcval; | ||
421 | outptr[2] = dcval; | ||
422 | outptr[3] = dcval; | ||
423 | outptr[4] = dcval; | ||
424 | outptr[5] = dcval; | ||
425 | outptr[6] = dcval; | ||
426 | outptr[7] = dcval; | ||
427 | |||
428 | wsptr += 8; /* advance pointer to next row */ | ||
429 | continue; | ||
430 | } | ||
431 | #endif | ||
432 | |||
433 | /* Even part: reverse the even part of the forward DCT. */ | ||
434 | /* The rotator is sqrt(2)*c(-6). */ | ||
435 | |||
436 | z2 = (long) wsptr[2]; | ||
437 | z3 = (long) wsptr[6]; | ||
438 | |||
439 | z1 = MULTIPLY16(z2 + z3, FIX_0_541196100); | ||
440 | tmp2 = z1 + MULTIPLY16(z3, - FIX_1_847759065); | ||
441 | tmp3 = z1 + MULTIPLY16(z2, FIX_0_765366865); | ||
442 | |||
443 | tmp0 = ((long) wsptr[0] + (long) wsptr[4]) << CONST_BITS; | ||
444 | tmp1 = ((long) wsptr[0] - (long) wsptr[4]) << CONST_BITS; | ||
445 | |||
446 | tmp10 = tmp0 + tmp3; | ||
447 | tmp13 = tmp0 - tmp3; | ||
448 | tmp11 = tmp1 + tmp2; | ||
449 | tmp12 = tmp1 - tmp2; | ||
450 | |||
451 | /* Odd part per figure 8; the matrix is unitary and hence its | ||
452 | * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */ | ||
453 | |||
454 | tmp0 = (long) wsptr[7]; | ||
455 | tmp1 = (long) wsptr[5]; | ||
456 | tmp2 = (long) wsptr[3]; | ||
457 | tmp3 = (long) wsptr[1]; | ||
458 | |||
459 | z1 = tmp0 + tmp3; | ||
460 | z2 = tmp1 + tmp2; | ||
461 | z3 = tmp0 + tmp2; | ||
462 | z4 = tmp1 + tmp3; | ||
463 | z5 = MULTIPLY16(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ | ||
464 | |||
465 | tmp0 = MULTIPLY16(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ | ||
466 | tmp1 = MULTIPLY16(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ | ||
467 | tmp2 = MULTIPLY16(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ | ||
468 | tmp3 = MULTIPLY16(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ | ||
469 | z1 = MULTIPLY16(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ | ||
470 | z2 = MULTIPLY16(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ | ||
471 | z3 = MULTIPLY16(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ | ||
472 | z4 = MULTIPLY16(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ | ||
473 | |||
474 | z3 += z5; | ||
475 | z4 += z5; | ||
476 | |||
477 | tmp0 += z1 + z3; | ||
478 | tmp1 += z2 + z4; | ||
479 | tmp2 += z2 + z3; | ||
480 | tmp3 += z1 + z4; | ||
481 | |||
482 | /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ | ||
483 | |||
484 | outptr[0] = range_limit((int) DESCALE(tmp10 + tmp3, | ||
485 | CONST_BITS+PASS1_BITS+3)); | ||
486 | outptr[7] = range_limit((int) DESCALE(tmp10 - tmp3, | ||
487 | CONST_BITS+PASS1_BITS+3)); | ||
488 | outptr[1] = range_limit((int) DESCALE(tmp11 + tmp2, | ||
489 | CONST_BITS+PASS1_BITS+3)); | ||
490 | outptr[6] = range_limit((int) DESCALE(tmp11 - tmp2, | ||
491 | CONST_BITS+PASS1_BITS+3)); | ||
492 | outptr[2] = range_limit((int) DESCALE(tmp12 + tmp1, | ||
493 | CONST_BITS+PASS1_BITS+3)); | ||
494 | outptr[5] = range_limit((int) DESCALE(tmp12 - tmp1, | ||
495 | CONST_BITS+PASS1_BITS+3)); | ||
496 | outptr[3] = range_limit((int) DESCALE(tmp13 + tmp0, | ||
497 | CONST_BITS+PASS1_BITS+3)); | ||
498 | outptr[4] = range_limit((int) DESCALE(tmp13 - tmp0, | ||
499 | CONST_BITS+PASS1_BITS+3)); | ||
500 | |||
501 | wsptr += 8; /* advance pointer to next row */ | ||
502 | } | ||
503 | } | ||
504 | |||
505 | |||
506 | |||
507 | /* JPEG decoder implementation */ | ||
508 | |||
509 | /* Preprocess the JPEG JFIF file */ | ||
510 | int process_markers(unsigned char* p_src, long size, struct jpeg* p_jpeg) | ||
511 | { | ||
512 | unsigned char* p_bytes = p_src; | ||
513 | int marker_size; /* variable length of marker segment */ | ||
514 | int i, j, n; | ||
515 | int ret = 0; /* returned flags */ | ||
516 | |||
517 | p_jpeg->p_entropy_end = p_src + size; | ||
518 | |||
519 | while (p_src < p_bytes + size) | ||
520 | { | ||
521 | if (*p_src++ != 0xFF) /* no marker? */ | ||
522 | { | ||
523 | p_src--; /* it's image data, put it back */ | ||
524 | p_jpeg->p_entropy_data = p_src; | ||
525 | break; /* exit marker processing */ | ||
526 | } | ||
527 | |||
528 | switch (*p_src++) | ||
529 | { | ||
530 | case 0xFF: /* Fill byte */ | ||
531 | ret |= FILL_FF; | ||
532 | case 0x00: /* Zero stuffed byte - entropy data */ | ||
533 | p_src--; /* put it back */ | ||
534 | continue; | ||
535 | |||
536 | case 0xC0: /* SOF Huff - Baseline DCT */ | ||
537 | { | ||
538 | ret |= SOF0; | ||
539 | marker_size = *p_src++ << 8; /* Highbyte */ | ||
540 | marker_size |= *p_src++; /* Lowbyte */ | ||
541 | n = *p_src++; /* sample precision (= 8 or 12) */ | ||
542 | if (n != 8) | ||
543 | { | ||
544 | return(-1); /* Unsupported sample precision */ | ||
545 | } | ||
546 | p_jpeg->y_size = *p_src++ << 8; /* Highbyte */ | ||
547 | p_jpeg->y_size |= *p_src++; /* Lowbyte */ | ||
548 | p_jpeg->x_size = *p_src++ << 8; /* Highbyte */ | ||
549 | p_jpeg->x_size |= *p_src++; /* Lowbyte */ | ||
550 | |||
551 | n = (marker_size-2-6)/3; | ||
552 | if (*p_src++ != n || (n != 1 && n != 3)) | ||
553 | { | ||
554 | return(-2); /* Unsupported SOF0 component specification */ | ||
555 | } | ||
556 | for (i=0; i<n; i++) | ||
557 | { | ||
558 | p_jpeg->frameheader[i].ID = *p_src++; /* Component info */ | ||
559 | p_jpeg->frameheader[i].horizontal_sampling = *p_src >> 4; | ||
560 | p_jpeg->frameheader[i].vertical_sampling = *p_src++ & 0x0F; | ||
561 | p_jpeg->frameheader[i].quanttable_select = *p_src++; | ||
562 | if (p_jpeg->frameheader[i].horizontal_sampling > 2 | ||
563 | || p_jpeg->frameheader[i].vertical_sampling > 2) | ||
564 | return -3; /* Unsupported SOF0 subsampling */ | ||
565 | } | ||
566 | p_jpeg->blocks = n; | ||
567 | } | ||
568 | break; | ||
569 | |||
570 | case 0xC1: /* SOF Huff - Extended sequential DCT*/ | ||
571 | case 0xC2: /* SOF Huff - Progressive DCT*/ | ||
572 | case 0xC3: /* SOF Huff - Spatial (sequential) lossless*/ | ||
573 | case 0xC5: /* SOF Huff - Differential sequential DCT*/ | ||
574 | case 0xC6: /* SOF Huff - Differential progressive DCT*/ | ||
575 | case 0xC7: /* SOF Huff - Differential spatial*/ | ||
576 | case 0xC8: /* SOF Arith - Reserved for JPEG extensions*/ | ||
577 | case 0xC9: /* SOF Arith - Extended sequential DCT*/ | ||
578 | case 0xCA: /* SOF Arith - Progressive DCT*/ | ||
579 | case 0xCB: /* SOF Arith - Spatial (sequential) lossless*/ | ||
580 | case 0xCD: /* SOF Arith - Differential sequential DCT*/ | ||
581 | case 0xCE: /* SOF Arith - Differential progressive DCT*/ | ||
582 | case 0xCF: /* SOF Arith - Differential spatial*/ | ||
583 | { | ||
584 | return (-4); /* other DCT model than baseline not implemented */ | ||
585 | } | ||
586 | |||
587 | case 0xC4: /* Define Huffman Table(s) */ | ||
588 | { | ||
589 | unsigned char* p_temp; | ||
590 | |||
591 | ret |= DHT; | ||
592 | marker_size = *p_src++ << 8; /* Highbyte */ | ||
593 | marker_size |= *p_src++; /* Lowbyte */ | ||
594 | |||
595 | p_temp = p_src; | ||
596 | while (p_src < p_temp+marker_size-2-17) /* another table */ | ||
597 | { | ||
598 | int sum = 0; | ||
599 | i = *p_src & 0x0F; /* table index */ | ||
600 | if (i > 1) | ||
601 | { | ||
602 | return (-5); /* Huffman table index out of range */ | ||
603 | } | ||
604 | else if (*p_src++ & 0xF0) /* AC table */ | ||
605 | { | ||
606 | for (j=0; j<16; j++) | ||
607 | { | ||
608 | sum += *p_src; | ||
609 | p_jpeg->hufftable[i].huffmancodes_ac[j] = *p_src++; | ||
610 | } | ||
611 | if(16 + sum > AC_LEN) | ||
612 | return -10; /* longer than allowed */ | ||
613 | |||
614 | for (; j < 16 + sum; j++) | ||
615 | p_jpeg->hufftable[i].huffmancodes_ac[j] = *p_src++; | ||
616 | } | ||
617 | else /* DC table */ | ||
618 | { | ||
619 | for (j=0; j<16; j++) | ||
620 | { | ||
621 | sum += *p_src; | ||
622 | p_jpeg->hufftable[i].huffmancodes_dc[j] = *p_src++; | ||
623 | } | ||
624 | if(16 + sum > DC_LEN) | ||
625 | return -11; /* longer than allowed */ | ||
626 | |||
627 | for (; j < 16 + sum; j++) | ||
628 | p_jpeg->hufftable[i].huffmancodes_dc[j] = *p_src++; | ||
629 | } | ||
630 | } /* while */ | ||
631 | p_src = p_temp+marker_size - 2; /* skip possible residue */ | ||
632 | } | ||
633 | break; | ||
634 | |||
635 | case 0xCC: /* Define Arithmetic coding conditioning(s) */ | ||
636 | return(-6); /* Arithmetic coding not supported */ | ||
637 | |||
638 | case 0xD8: /* Start of Image */ | ||
639 | case 0xD9: /* End of Image */ | ||
640 | case 0x01: /* for temp private use arith code */ | ||
641 | break; /* skip parameterless marker */ | ||
642 | |||
643 | |||
644 | case 0xDA: /* Start of Scan */ | ||
645 | { | ||
646 | ret |= SOS; | ||
647 | marker_size = *p_src++ << 8; /* Highbyte */ | ||
648 | marker_size |= *p_src++; /* Lowbyte */ | ||
649 | |||
650 | n = (marker_size-2-1-3)/2; | ||
651 | if (*p_src++ != n || (n != 1 && n != 3)) | ||
652 | { | ||
653 | return (-7); /* Unsupported SOS component specification */ | ||
654 | } | ||
655 | for (i=0; i<n; i++) | ||
656 | { | ||
657 | p_jpeg->scanheader[i].ID = *p_src++; | ||
658 | p_jpeg->scanheader[i].DC_select = *p_src >> 4; | ||
659 | p_jpeg->scanheader[i].AC_select = *p_src++ & 0x0F; | ||
660 | } | ||
661 | p_src += 3; /* skip spectral information */ | ||
662 | } | ||
663 | break; | ||
664 | |||
665 | case 0xDB: /* Define quantization Table(s) */ | ||
666 | { | ||
667 | ret |= DQT; | ||
668 | marker_size = *p_src++ << 8; /* Highbyte */ | ||
669 | marker_size |= *p_src++; /* Lowbyte */ | ||
670 | n = (marker_size-2)/(QUANT_TABLE_LENGTH+1); /* # of tables */ | ||
671 | for (i=0; i<n; i++) | ||
672 | { | ||
673 | int id = *p_src++; /* ID */ | ||
674 | if (id >= 4) | ||
675 | { | ||
676 | return (-8); /* Unsupported quantization table */ | ||
677 | } | ||
678 | /* Read Quantisation table: */ | ||
679 | for (j=0; j<QUANT_TABLE_LENGTH; j++) | ||
680 | p_jpeg->quanttable[id][j] = *p_src++; | ||
681 | } | ||
682 | } | ||
683 | break; | ||
684 | |||
685 | case 0xDD: /* Define Restart Interval */ | ||
686 | { | ||
687 | marker_size = *p_src++ << 8; /* Highbyte */ | ||
688 | marker_size |= *p_src++; /* Lowbyte */ | ||
689 | p_jpeg->restart_interval = *p_src++ << 8; /* Highbyte */ | ||
690 | p_jpeg->restart_interval |= *p_src++; /* Lowbyte */ | ||
691 | p_src += marker_size-4; /* skip segment */ | ||
692 | } | ||
693 | break; | ||
694 | |||
695 | case 0xDC: /* Define Number of Lines */ | ||
696 | case 0xDE: /* Define Hierarchical progression */ | ||
697 | case 0xDF: /* Expand Reference Component(s) */ | ||
698 | case 0xE0: /* Application Field 0*/ | ||
699 | case 0xE1: /* Application Field 1*/ | ||
700 | case 0xE2: /* Application Field 2*/ | ||
701 | case 0xE3: /* Application Field 3*/ | ||
702 | case 0xE4: /* Application Field 4*/ | ||
703 | case 0xE5: /* Application Field 5*/ | ||
704 | case 0xE6: /* Application Field 6*/ | ||
705 | case 0xE7: /* Application Field 7*/ | ||
706 | case 0xE8: /* Application Field 8*/ | ||
707 | case 0xE9: /* Application Field 9*/ | ||
708 | case 0xEA: /* Application Field 10*/ | ||
709 | case 0xEB: /* Application Field 11*/ | ||
710 | case 0xEC: /* Application Field 12*/ | ||
711 | case 0xED: /* Application Field 13*/ | ||
712 | case 0xEE: /* Application Field 14*/ | ||
713 | case 0xEF: /* Application Field 15*/ | ||
714 | case 0xFE: /* Comment */ | ||
715 | { | ||
716 | marker_size = *p_src++ << 8; /* Highbyte */ | ||
717 | marker_size |= *p_src++; /* Lowbyte */ | ||
718 | p_src += marker_size-2; /* skip segment */ | ||
719 | } | ||
720 | break; | ||
721 | |||
722 | case 0xF0: /* Reserved for JPEG extensions */ | ||
723 | case 0xF1: /* Reserved for JPEG extensions */ | ||
724 | case 0xF2: /* Reserved for JPEG extensions */ | ||
725 | case 0xF3: /* Reserved for JPEG extensions */ | ||
726 | case 0xF4: /* Reserved for JPEG extensions */ | ||
727 | case 0xF5: /* Reserved for JPEG extensions */ | ||
728 | case 0xF6: /* Reserved for JPEG extensions */ | ||
729 | case 0xF7: /* Reserved for JPEG extensions */ | ||
730 | case 0xF8: /* Reserved for JPEG extensions */ | ||
731 | case 0xF9: /* Reserved for JPEG extensions */ | ||
732 | case 0xFA: /* Reserved for JPEG extensions */ | ||
733 | case 0xFB: /* Reserved for JPEG extensions */ | ||
734 | case 0xFC: /* Reserved for JPEG extensions */ | ||
735 | case 0xFD: /* Reserved for JPEG extensions */ | ||
736 | case 0x02: /* Reserved */ | ||
737 | default: | ||
738 | return (-9); /* Unknown marker */ | ||
739 | } /* switch */ | ||
740 | } /* while */ | ||
741 | |||
742 | return (ret); /* return flags with seen markers */ | ||
743 | } | ||
744 | |||
745 | |||
746 | void default_huff_tbl(struct jpeg* p_jpeg) | ||
747 | { | ||
748 | static const struct huffman_table luma_table = | ||
749 | { | ||
750 | { | ||
751 | 0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00, | ||
752 | 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B | ||
753 | }, | ||
754 | { | ||
755 | 0x00,0x02,0x01,0x03,0x03,0x02,0x04,0x03,0x05,0x05,0x04,0x04,0x00,0x00,0x01,0x7D, | ||
756 | 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07, | ||
757 | 0x22,0x71,0x14,0x32,0x81,0x91,0xA1,0x08,0x23,0x42,0xB1,0xC1,0x15,0x52,0xD1,0xF0, | ||
758 | 0x24,0x33,0x62,0x72,0x82,0x09,0x0A,0x16,0x17,0x18,0x19,0x1A,0x25,0x26,0x27,0x28, | ||
759 | 0x29,0x2A,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49, | ||
760 | 0x4A,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69, | ||
761 | 0x6A,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x83,0x84,0x85,0x86,0x87,0x88,0x89, | ||
762 | 0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7, | ||
763 | 0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xC2,0xC3,0xC4,0xC5, | ||
764 | 0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xE1,0xE2, | ||
765 | 0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8, | ||
766 | 0xF9,0xFA | ||
767 | } | ||
768 | }; | ||
769 | |||
770 | static const struct huffman_table chroma_table = | ||
771 | { | ||
772 | { | ||
773 | 0x00,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00, | ||
774 | 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B | ||
775 | }, | ||
776 | { | ||
777 | 0x00,0x02,0x01,0x02,0x04,0x04,0x03,0x04,0x07,0x05,0x04,0x04,0x00,0x01,0x02,0x77, | ||
778 | 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71, | ||
779 | 0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xA1,0xB1,0xC1,0x09,0x23,0x33,0x52,0xF0, | ||
780 | 0x15,0x62,0x72,0xD1,0x0A,0x16,0x24,0x34,0xE1,0x25,0xF1,0x17,0x18,0x19,0x1A,0x26, | ||
781 | 0x27,0x28,0x29,0x2A,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48, | ||
782 | 0x49,0x4A,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68, | ||
783 | 0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x82,0x83,0x84,0x85,0x86,0x87, | ||
784 | 0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5, | ||
785 | 0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xC2,0xC3, | ||
786 | 0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA, | ||
787 | 0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8, | ||
788 | 0xF9,0xFA | ||
789 | } | ||
790 | }; | ||
791 | |||
792 | MEMCPY(&p_jpeg->hufftable[0], &luma_table, sizeof(luma_table)); | ||
793 | MEMCPY(&p_jpeg->hufftable[1], &chroma_table, sizeof(chroma_table)); | ||
794 | |||
795 | return; | ||
796 | } | ||
797 | |||
798 | /* Compute the derived values for a Huffman table */ | ||
799 | void fix_huff_tbl(int* htbl, struct derived_tbl* dtbl) | ||
800 | { | ||
801 | int p, i, l, si; | ||
802 | int lookbits, ctr; | ||
803 | char huffsize[257]; | ||
804 | unsigned int huffcode[257]; | ||
805 | unsigned int code; | ||
806 | |||
807 | dtbl->pub = htbl; /* fill in back link */ | ||
808 | |||
809 | /* Figure C.1: make table of Huffman code length for each symbol */ | ||
810 | /* Note that this is in code-length order. */ | ||
811 | |||
812 | p = 0; | ||
813 | for (l = 1; l <= 16; l++) | ||
814 | { /* all possible code length */ | ||
815 | for (i = 1; i <= (int) htbl[l-1]; i++) /* all codes per length */ | ||
816 | huffsize[p++] = (char) l; | ||
817 | } | ||
818 | huffsize[p] = 0; | ||
819 | |||
820 | /* Figure C.2: generate the codes themselves */ | ||
821 | /* Note that this is in code-length order. */ | ||
822 | |||
823 | code = 0; | ||
824 | si = huffsize[0]; | ||
825 | p = 0; | ||
826 | while (huffsize[p]) | ||
827 | { | ||
828 | while (((int) huffsize[p]) == si) | ||
829 | { | ||
830 | huffcode[p++] = code; | ||
831 | code++; | ||
832 | } | ||
833 | code <<= 1; | ||
834 | si++; | ||
835 | } | ||
836 | |||
837 | /* Figure F.15: generate decoding tables for bit-sequential decoding */ | ||
838 | |||
839 | p = 0; | ||
840 | for (l = 1; l <= 16; l++) | ||
841 | { | ||
842 | if (htbl[l-1]) | ||
843 | { | ||
844 | dtbl->valptr[l] = p; /* huffval[] index of 1st symbol of code length l */ | ||
845 | dtbl->mincode[l] = huffcode[p]; /* minimum code of length l */ | ||
846 | p += htbl[l-1]; | ||
847 | dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */ | ||
848 | } | ||
849 | else | ||
850 | { | ||
851 | dtbl->maxcode[l] = -1; /* -1 if no codes of this length */ | ||
852 | } | ||
853 | } | ||
854 | dtbl->maxcode[17] = 0xFFFFFL; /* ensures huff_DECODE terminates */ | ||
855 | |||
856 | /* Compute lookahead tables to speed up decoding. | ||
857 | * First we set all the table entries to 0, indicating "too long"; | ||
858 | * then we iterate through the Huffman codes that are short enough and | ||
859 | * fill in all the entries that correspond to bit sequences starting | ||
860 | * with that code. | ||
861 | */ | ||
862 | |||
863 | MEMSET(dtbl->look_nbits, 0, sizeof(dtbl->look_nbits)); | ||
864 | |||
865 | p = 0; | ||
866 | for (l = 1; l <= HUFF_LOOKAHEAD; l++) | ||
867 | { | ||
868 | for (i = 1; i <= (int) htbl[l-1]; i++, p++) | ||
869 | { | ||
870 | /* l = current code's length, p = its index in huffcode[] & huffval[]. */ | ||
871 | /* Generate left-justified code followed by all possible bit sequences */ | ||
872 | lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l); | ||
873 | for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) | ||
874 | { | ||
875 | dtbl->look_nbits[lookbits] = l; | ||
876 | dtbl->look_sym[lookbits] = htbl[16+p]; | ||
877 | lookbits++; | ||
878 | } | ||
879 | } | ||
880 | } | ||
881 | } | ||
882 | |||
883 | |||
884 | /* zag[i] is the natural-order position of the i'th element of zigzag order. | ||
885 | * If the incoming data is corrupted, decode_mcu could attempt to | ||
886 | * reference values beyond the end of the array. To avoid a wild store, | ||
887 | * we put some extra zeroes after the real entries. | ||
888 | */ | ||
889 | static const int zag[] = | ||
890 | { | ||
891 | 0, 1, 8, 16, 9, 2, 3, 10, | ||
892 | 17, 24, 32, 25, 18, 11, 4, 5, | ||
893 | 12, 19, 26, 33, 40, 48, 41, 34, | ||
894 | 27, 20, 13, 6, 7, 14, 21, 28, | ||
895 | 35, 42, 49, 56, 57, 50, 43, 36, | ||
896 | 29, 22, 15, 23, 30, 37, 44, 51, | ||
897 | 58, 59, 52, 45, 38, 31, 39, 46, | ||
898 | 53, 60, 61, 54, 47, 55, 62, 63, | ||
899 | 0, 0, 0, 0, 0, 0, 0, 0, /* extra entries in case k>63 below */ | ||
900 | 0, 0, 0, 0, 0, 0, 0, 0 | ||
901 | }; | ||
902 | |||
903 | void build_lut(struct jpeg* p_jpeg) | ||
904 | { | ||
905 | int i; | ||
906 | fix_huff_tbl(p_jpeg->hufftable[0].huffmancodes_dc, | ||
907 | &p_jpeg->dc_derived_tbls[0]); | ||
908 | fix_huff_tbl(p_jpeg->hufftable[0].huffmancodes_ac, | ||
909 | &p_jpeg->ac_derived_tbls[0]); | ||
910 | fix_huff_tbl(p_jpeg->hufftable[1].huffmancodes_dc, | ||
911 | &p_jpeg->dc_derived_tbls[1]); | ||
912 | fix_huff_tbl(p_jpeg->hufftable[1].huffmancodes_ac, | ||
913 | &p_jpeg->ac_derived_tbls[1]); | ||
914 | |||
915 | /* build the dequantization tables for the IDCT (De-ZiZagged) */ | ||
916 | for (i=0; i<64; i++) | ||
917 | { | ||
918 | p_jpeg->qt_idct[0][zag[i]] = p_jpeg->quanttable[0][i]; | ||
919 | p_jpeg->qt_idct[1][zag[i]] = p_jpeg->quanttable[1][i]; | ||
920 | } | ||
921 | |||
922 | for (i=0; i<4; i++) | ||
923 | p_jpeg->store_pos[i] = i; /* default ordering */ | ||
924 | |||
925 | /* assignments for the decoding of blocks */ | ||
926 | if (p_jpeg->frameheader[0].horizontal_sampling == 2 | ||
927 | && p_jpeg->frameheader[0].vertical_sampling == 1) | ||
928 | { /* 4:2:2 */ | ||
929 | p_jpeg->blocks = 4; | ||
930 | p_jpeg->x_mbl = (p_jpeg->x_size+15) / 16; | ||
931 | p_jpeg->x_phys = p_jpeg->x_mbl * 16; | ||
932 | p_jpeg->y_mbl = (p_jpeg->y_size+7) / 8; | ||
933 | p_jpeg->y_phys = p_jpeg->y_mbl * 8; | ||
934 | p_jpeg->mcu_membership[0] = 0; /* Y1=Y2=0, U=1, V=2 */ | ||
935 | p_jpeg->mcu_membership[1] = 0; | ||
936 | p_jpeg->mcu_membership[2] = 1; | ||
937 | p_jpeg->mcu_membership[3] = 2; | ||
938 | p_jpeg->tab_membership[0] = 0; /* DC, DC, AC, AC */ | ||
939 | p_jpeg->tab_membership[1] = 0; | ||
940 | p_jpeg->tab_membership[2] = 1; | ||
941 | p_jpeg->tab_membership[3] = 1; | ||
942 | p_jpeg->subsample_x[0] = 1; | ||
943 | p_jpeg->subsample_x[1] = 2; | ||
944 | p_jpeg->subsample_x[2] = 2; | ||
945 | p_jpeg->subsample_y[0] = 1; | ||
946 | p_jpeg->subsample_y[1] = 1; | ||
947 | p_jpeg->subsample_y[2] = 1; | ||
948 | } | ||
949 | if (p_jpeg->frameheader[0].horizontal_sampling == 1 | ||
950 | && p_jpeg->frameheader[0].vertical_sampling == 2) | ||
951 | { /* 4:2:2 vertically subsampled */ | ||
952 | p_jpeg->store_pos[1] = 2; /* block positions are mirrored */ | ||
953 | p_jpeg->store_pos[2] = 1; | ||
954 | p_jpeg->blocks = 4; | ||
955 | p_jpeg->x_mbl = (p_jpeg->x_size+7) / 8; | ||
956 | p_jpeg->x_phys = p_jpeg->x_mbl * 8; | ||
957 | p_jpeg->y_mbl = (p_jpeg->y_size+15) / 16; | ||
958 | p_jpeg->y_phys = p_jpeg->y_mbl * 16; | ||
959 | p_jpeg->mcu_membership[0] = 0; /* Y1=Y2=0, U=1, V=2 */ | ||
960 | p_jpeg->mcu_membership[1] = 0; | ||
961 | p_jpeg->mcu_membership[2] = 1; | ||
962 | p_jpeg->mcu_membership[3] = 2; | ||
963 | p_jpeg->tab_membership[0] = 0; /* DC, DC, AC, AC */ | ||
964 | p_jpeg->tab_membership[1] = 0; | ||
965 | p_jpeg->tab_membership[2] = 1; | ||
966 | p_jpeg->tab_membership[3] = 1; | ||
967 | p_jpeg->subsample_x[0] = 1; | ||
968 | p_jpeg->subsample_x[1] = 1; | ||
969 | p_jpeg->subsample_x[2] = 1; | ||
970 | p_jpeg->subsample_y[0] = 1; | ||
971 | p_jpeg->subsample_y[1] = 2; | ||
972 | p_jpeg->subsample_y[2] = 2; | ||
973 | } | ||
974 | else if (p_jpeg->frameheader[0].horizontal_sampling == 2 | ||
975 | && p_jpeg->frameheader[0].vertical_sampling == 2) | ||
976 | { /* 4:2:0 */ | ||
977 | p_jpeg->blocks = 6; | ||
978 | p_jpeg->x_mbl = (p_jpeg->x_size+15) / 16; | ||
979 | p_jpeg->x_phys = p_jpeg->x_mbl * 16; | ||
980 | p_jpeg->y_mbl = (p_jpeg->y_size+15) / 16; | ||
981 | p_jpeg->y_phys = p_jpeg->y_mbl * 16; | ||
982 | p_jpeg->mcu_membership[0] = 0; | ||
983 | p_jpeg->mcu_membership[1] = 0; | ||
984 | p_jpeg->mcu_membership[2] = 0; | ||
985 | p_jpeg->mcu_membership[3] = 0; | ||
986 | p_jpeg->mcu_membership[4] = 1; | ||
987 | p_jpeg->mcu_membership[5] = 2; | ||
988 | p_jpeg->tab_membership[0] = 0; | ||
989 | p_jpeg->tab_membership[1] = 0; | ||
990 | p_jpeg->tab_membership[2] = 0; | ||
991 | p_jpeg->tab_membership[3] = 0; | ||
992 | p_jpeg->tab_membership[4] = 1; | ||
993 | p_jpeg->tab_membership[5] = 1; | ||
994 | p_jpeg->subsample_x[0] = 1; | ||
995 | p_jpeg->subsample_x[1] = 2; | ||
996 | p_jpeg->subsample_x[2] = 2; | ||
997 | p_jpeg->subsample_y[0] = 1; | ||
998 | p_jpeg->subsample_y[1] = 2; | ||
999 | p_jpeg->subsample_y[2] = 2; | ||
1000 | } | ||
1001 | else if (p_jpeg->frameheader[0].horizontal_sampling == 1 | ||
1002 | && p_jpeg->frameheader[0].vertical_sampling == 1) | ||
1003 | { /* 4:4:4 */ | ||
1004 | /* don't overwrite p_jpeg->blocks */ | ||
1005 | p_jpeg->x_mbl = (p_jpeg->x_size+7) / 8; | ||
1006 | p_jpeg->x_phys = p_jpeg->x_mbl * 8; | ||
1007 | p_jpeg->y_mbl = (p_jpeg->y_size+7) / 8; | ||
1008 | p_jpeg->y_phys = p_jpeg->y_mbl * 8; | ||
1009 | p_jpeg->mcu_membership[0] = 0; | ||
1010 | p_jpeg->mcu_membership[1] = 1; | ||
1011 | p_jpeg->mcu_membership[2] = 2; | ||
1012 | p_jpeg->tab_membership[0] = 0; | ||
1013 | p_jpeg->tab_membership[1] = 1; | ||
1014 | p_jpeg->tab_membership[2] = 1; | ||
1015 | p_jpeg->subsample_x[0] = 1; | ||
1016 | p_jpeg->subsample_x[1] = 1; | ||
1017 | p_jpeg->subsample_x[2] = 1; | ||
1018 | p_jpeg->subsample_y[0] = 1; | ||
1019 | p_jpeg->subsample_y[1] = 1; | ||
1020 | p_jpeg->subsample_y[2] = 1; | ||
1021 | } | ||
1022 | else | ||
1023 | { | ||
1024 | /* error */ | ||
1025 | } | ||
1026 | |||
1027 | } | ||
1028 | |||
1029 | |||
1030 | /* | ||
1031 | * These functions/macros provide the in-line portion of bit fetching. | ||
1032 | * Use check_bit_buffer to ensure there are N bits in get_buffer | ||
1033 | * before using get_bits, peek_bits, or drop_bits. | ||
1034 | * check_bit_buffer(state,n,action); | ||
1035 | * Ensure there are N bits in get_buffer; if suspend, take action. | ||
1036 | * val = get_bits(n); | ||
1037 | * Fetch next N bits. | ||
1038 | * val = peek_bits(n); | ||
1039 | * Fetch next N bits without removing them from the buffer. | ||
1040 | * drop_bits(n); | ||
1041 | * Discard next N bits. | ||
1042 | * The value N should be a simple variable, not an expression, because it | ||
1043 | * is evaluated multiple times. | ||
1044 | */ | ||
1045 | |||
1046 | INLINE void check_bit_buffer(struct bitstream* pb, int nbits) | ||
1047 | { | ||
1048 | if (pb->bits_left < nbits) | ||
1049 | { /* nbits is <= 16, so I can always refill 2 bytes in this case */ | ||
1050 | unsigned char byte; | ||
1051 | |||
1052 | byte = *pb->next_input_byte++; | ||
1053 | if (byte == 0xFF) /* legal marker can be byte stuffing or RSTm */ | ||
1054 | { /* simplification: just skip the (one-byte) marker code */ | ||
1055 | pb->next_input_byte++; | ||
1056 | } | ||
1057 | pb->get_buffer = (pb->get_buffer << 8) | byte; | ||
1058 | |||
1059 | byte = *pb->next_input_byte++; | ||
1060 | if (byte == 0xFF) /* legal marker can be byte stuffing or RSTm */ | ||
1061 | { /* simplification: just skip the (one-byte) marker code */ | ||
1062 | pb->next_input_byte++; | ||
1063 | } | ||
1064 | pb->get_buffer = (pb->get_buffer << 8) | byte; | ||
1065 | |||
1066 | pb->bits_left += 16; | ||
1067 | } | ||
1068 | } | ||
1069 | |||
1070 | INLINE int get_bits(struct bitstream* pb, int nbits) | ||
1071 | { | ||
1072 | return ((int) (pb->get_buffer >> (pb->bits_left -= nbits))) & ((1<<nbits)-1); | ||
1073 | } | ||
1074 | |||
1075 | INLINE int peek_bits(struct bitstream* pb, int nbits) | ||
1076 | { | ||
1077 | return ((int) (pb->get_buffer >> (pb->bits_left - nbits))) & ((1<<nbits)-1); | ||
1078 | } | ||
1079 | |||
1080 | INLINE void drop_bits(struct bitstream* pb, int nbits) | ||
1081 | { | ||
1082 | pb->bits_left -= nbits; | ||
1083 | } | ||
1084 | |||
1085 | /* re-synchronize to entropy data (skip restart marker) */ | ||
1086 | void search_restart(struct bitstream* pb) | ||
1087 | { | ||
1088 | pb->next_input_byte--; /* we may have overread it, taking 2 bytes */ | ||
1089 | /* search for a non-byte-padding marker, has to be RSTm or EOS */ | ||
1090 | while (pb->next_input_byte < pb->input_end && | ||
1091 | (pb->next_input_byte[-2] != 0xFF || pb->next_input_byte[-1] == 0x00)) | ||
1092 | { | ||
1093 | pb->next_input_byte++; | ||
1094 | } | ||
1095 | pb->bits_left = 0; | ||
1096 | } | ||
1097 | |||
1098 | /* Figure F.12: extend sign bit. */ | ||
1099 | #define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) | ||
1100 | |||
1101 | static const int extend_test[16] = /* entry n is 2**(n-1) */ | ||
1102 | { | ||
1103 | 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, | ||
1104 | 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 | ||
1105 | }; | ||
1106 | |||
1107 | static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ | ||
1108 | { | ||
1109 | 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, | ||
1110 | ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, | ||
1111 | ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, | ||
1112 | ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 | ||
1113 | }; | ||
1114 | |||
1115 | /* Decode a single value */ | ||
1116 | INLINE int huff_decode_dc(struct bitstream* bs, struct derived_tbl* tbl) | ||
1117 | { | ||
1118 | int nb, look, s, r; | ||
1119 | |||
1120 | check_bit_buffer(bs, HUFF_LOOKAHEAD); | ||
1121 | look = peek_bits(bs, HUFF_LOOKAHEAD); | ||
1122 | if ((nb = tbl->look_nbits[look]) != 0) | ||
1123 | { | ||
1124 | drop_bits(bs, nb); | ||
1125 | s = tbl->look_sym[look]; | ||
1126 | check_bit_buffer(bs, s); | ||
1127 | r = get_bits(bs, s); | ||
1128 | s = HUFF_EXTEND(r, s); | ||
1129 | } | ||
1130 | else | ||
1131 | { /* slow_DECODE(s, HUFF_LOOKAHEAD+1)) < 0); */ | ||
1132 | long code; | ||
1133 | nb=HUFF_LOOKAHEAD+1; | ||
1134 | check_bit_buffer(bs, nb); | ||
1135 | code = get_bits(bs, nb); | ||
1136 | while (code > tbl->maxcode[nb]) | ||
1137 | { | ||
1138 | code <<= 1; | ||
1139 | check_bit_buffer(bs, 1); | ||
1140 | code |= get_bits(bs, 1); | ||
1141 | nb++; | ||
1142 | } | ||
1143 | if (nb > 16) /* error in Huffman */ | ||
1144 | { | ||
1145 | s=0; /* fake a zero, this is most safe */ | ||
1146 | } | ||
1147 | else | ||
1148 | { | ||
1149 | s = tbl->pub[16 + tbl->valptr[nb] + ((int) (code - tbl->mincode[nb])) ]; | ||
1150 | check_bit_buffer(bs, s); | ||
1151 | r = get_bits(bs, s); | ||
1152 | s = HUFF_EXTEND(r, s); | ||
1153 | } | ||
1154 | } /* end slow decode */ | ||
1155 | return s; | ||
1156 | } | ||
1157 | |||
1158 | INLINE int huff_decode_ac(struct bitstream* bs, struct derived_tbl* tbl) | ||
1159 | { | ||
1160 | int nb, look, s; | ||
1161 | |||
1162 | check_bit_buffer(bs, HUFF_LOOKAHEAD); | ||
1163 | look = peek_bits(bs, HUFF_LOOKAHEAD); | ||
1164 | if ((nb = tbl->look_nbits[look]) != 0) | ||
1165 | { | ||
1166 | drop_bits(bs, nb); | ||
1167 | s = tbl->look_sym[look]; | ||
1168 | } | ||
1169 | else | ||
1170 | { /* slow_DECODE(s, HUFF_LOOKAHEAD+1)) < 0); */ | ||
1171 | long code; | ||
1172 | nb=HUFF_LOOKAHEAD+1; | ||
1173 | check_bit_buffer(bs, nb); | ||
1174 | code = get_bits(bs, nb); | ||
1175 | while (code > tbl->maxcode[nb]) | ||
1176 | { | ||
1177 | code <<= 1; | ||
1178 | check_bit_buffer(bs, 1); | ||
1179 | code |= get_bits(bs, 1); | ||
1180 | nb++; | ||
1181 | } | ||
1182 | if (nb > 16) /* error in Huffman */ | ||
1183 | { | ||
1184 | s=0; /* fake a zero, this is most safe */ | ||
1185 | } | ||
1186 | else | ||
1187 | { | ||
1188 | s = tbl->pub[16 + tbl->valptr[nb] + ((int) (code - tbl->mincode[nb])) ]; | ||
1189 | } | ||
1190 | } /* end slow decode */ | ||
1191 | return s; | ||
1192 | } | ||
1193 | |||
1194 | |||
1195 | #ifdef HAVE_LCD_COLOR | ||
1196 | |||
1197 | /* JPEG decoder variant for YUV decoding, into 3 different planes */ | ||
1198 | /* Note: it keeps the original color subsampling, even if resized. */ | ||
1199 | int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel[3], | ||
1200 | int downscale, void (*pf_progress)(int current, int total)) | ||
1201 | { | ||
1202 | struct bitstream bs; /* bitstream "object" */ | ||
1203 | int block[64]; /* decoded DCT coefficients */ | ||
1204 | |||
1205 | int width, height; | ||
1206 | int skip_line[3]; /* bytes from one line to the next (skip_line) */ | ||
1207 | int skip_strip[3], skip_mcu[3]; /* bytes to next DCT row / column */ | ||
1208 | |||
1209 | int i, x, y; /* loop counter */ | ||
1210 | |||
1211 | unsigned char* p_line[3] = {p_pixel[0], p_pixel[1], p_pixel[2]}; | ||
1212 | unsigned char* p_byte[3]; /* bitmap pointer */ | ||
1213 | |||
1214 | void (*pf_idct)(unsigned char*, int*, int*, int); /* selected IDCT */ | ||
1215 | int k_need; /* AC coefficients needed up to here */ | ||
1216 | int zero_need; /* init the block with this many zeros */ | ||
1217 | |||
1218 | int last_dc_val[3] = {0, 0, 0}; /* or 128 for chroma? */ | ||
1219 | int store_offs[4]; /* memory offsets: order of Y11 Y12 Y21 Y22 U V */ | ||
1220 | int restart = p_jpeg->restart_interval; /* MCUs until restart marker */ | ||
1221 | |||
1222 | /* pick the IDCT we want, determine how to work with coefs */ | ||
1223 | if (downscale == 1) | ||
1224 | { | ||
1225 | pf_idct = idct8x8; | ||
1226 | k_need = 64; /* all */ | ||
1227 | zero_need = 63; /* all */ | ||
1228 | } | ||
1229 | else if (downscale == 2) | ||
1230 | { | ||
1231 | pf_idct = idct4x4; | ||
1232 | k_need = 25; /* this far in zig-zag to cover 4*4 */ | ||
1233 | zero_need = 27; /* clear this far in linear order */ | ||
1234 | } | ||
1235 | else if (downscale == 4) | ||
1236 | { | ||
1237 | pf_idct = idct2x2; | ||
1238 | k_need = 5; /* this far in zig-zag to cover 2*2 */ | ||
1239 | zero_need = 9; /* clear this far in linear order */ | ||
1240 | } | ||
1241 | else if (downscale == 8) | ||
1242 | { | ||
1243 | pf_idct = idct1x1; | ||
1244 | k_need = 0; /* no AC, not needed */ | ||
1245 | zero_need = 0; /* no AC, not needed */ | ||
1246 | } | ||
1247 | else return -1; /* not supported */ | ||
1248 | |||
1249 | /* init bitstream, fake a restart to make it start */ | ||
1250 | bs.next_input_byte = p_jpeg->p_entropy_data; | ||
1251 | bs.bits_left = 0; | ||
1252 | bs.input_end = p_jpeg->p_entropy_end; | ||
1253 | |||
1254 | width = p_jpeg->x_phys / downscale; | ||
1255 | height = p_jpeg->y_phys / downscale; | ||
1256 | for (i=0; i<3; i++) /* calculate some strides */ | ||
1257 | { | ||
1258 | skip_line[i] = width / p_jpeg->subsample_x[i]; | ||
1259 | skip_strip[i] = skip_line[i] | ||
1260 | * (height / p_jpeg->y_mbl) / p_jpeg->subsample_y[i]; | ||
1261 | skip_mcu[i] = width/p_jpeg->x_mbl / p_jpeg->subsample_x[i]; | ||
1262 | } | ||
1263 | |||
1264 | /* prepare offsets about where to store the different blocks */ | ||
1265 | store_offs[p_jpeg->store_pos[0]] = 0; | ||
1266 | store_offs[p_jpeg->store_pos[1]] = 8 / downscale; /* to the right */ | ||
1267 | store_offs[p_jpeg->store_pos[2]] = width * 8 / downscale; /* below */ | ||
1268 | store_offs[p_jpeg->store_pos[3]] = store_offs[1] + store_offs[2]; /* r+b */ | ||
1269 | |||
1270 | for(y=0; y<p_jpeg->y_mbl && bs.next_input_byte <= bs.input_end; y++) | ||
1271 | { | ||
1272 | for (i=0; i<3; i++) /* scan line init */ | ||
1273 | { | ||
1274 | p_byte[i] = p_line[i]; | ||
1275 | p_line[i] += skip_strip[i]; | ||
1276 | } | ||
1277 | for (x=0; x<p_jpeg->x_mbl; x++) | ||
1278 | { | ||
1279 | int blkn; | ||
1280 | |||
1281 | /* Outer loop handles each block in the MCU */ | ||
1282 | for (blkn = 0; blkn < p_jpeg->blocks; blkn++) | ||
1283 | { /* Decode a single block's worth of coefficients */ | ||
1284 | int k = 1; /* coefficient index */ | ||
1285 | int s, r; /* huffman values */ | ||
1286 | int ci = p_jpeg->mcu_membership[blkn]; /* component index */ | ||
1287 | int ti = p_jpeg->tab_membership[blkn]; /* table index */ | ||
1288 | struct derived_tbl* dctbl = &p_jpeg->dc_derived_tbls[ti]; | ||
1289 | struct derived_tbl* actbl = &p_jpeg->ac_derived_tbls[ti]; | ||
1290 | |||
1291 | /* Section F.2.2.1: decode the DC coefficient difference */ | ||
1292 | s = huff_decode_dc(&bs, dctbl); | ||
1293 | |||
1294 | last_dc_val[ci] += s; | ||
1295 | block[0] = last_dc_val[ci]; /* output it (assumes zag[0] = 0) */ | ||
1296 | |||
1297 | /* coefficient buffer must be cleared */ | ||
1298 | MEMSET(block+1, 0, zero_need*sizeof(block[0])); | ||
1299 | |||
1300 | /* Section F.2.2.2: decode the AC coefficients */ | ||
1301 | for (; k < k_need; k++) | ||
1302 | { | ||
1303 | s = huff_decode_ac(&bs, actbl); | ||
1304 | r = s >> 4; | ||
1305 | s &= 15; | ||
1306 | |||
1307 | if (s) | ||
1308 | { | ||
1309 | k += r; | ||
1310 | check_bit_buffer(&bs, s); | ||
1311 | r = get_bits(&bs, s); | ||
1312 | block[zag[k]] = HUFF_EXTEND(r, s); | ||
1313 | } | ||
1314 | else | ||
1315 | { | ||
1316 | if (r != 15) | ||
1317 | { | ||
1318 | k = 64; | ||
1319 | break; | ||
1320 | } | ||
1321 | k += r; | ||
1322 | } | ||
1323 | } /* for k */ | ||
1324 | /* In this path we just discard the values */ | ||
1325 | for (; k < 64; k++) | ||
1326 | { | ||
1327 | s = huff_decode_ac(&bs, actbl); | ||
1328 | r = s >> 4; | ||
1329 | s &= 15; | ||
1330 | |||
1331 | if (s) | ||
1332 | { | ||
1333 | k += r; | ||
1334 | check_bit_buffer(&bs, s); | ||
1335 | drop_bits(&bs, s); | ||
1336 | } | ||
1337 | else | ||
1338 | { | ||
1339 | if (r != 15) | ||
1340 | break; | ||
1341 | k += r; | ||
1342 | } | ||
1343 | } /* for k */ | ||
1344 | |||
1345 | if (ci == 0) | ||
1346 | { /* Y component needs to bother about block store */ | ||
1347 | pf_idct(p_byte[0]+store_offs[blkn], block, | ||
1348 | p_jpeg->qt_idct[ti], skip_line[0]); | ||
1349 | } | ||
1350 | else | ||
1351 | { /* chroma */ | ||
1352 | pf_idct(p_byte[ci], block, p_jpeg->qt_idct[ti], | ||
1353 | skip_line[ci]); | ||
1354 | } | ||
1355 | } /* for blkn */ | ||
1356 | p_byte[0] += skip_mcu[0]; /* unrolled for (i=0; i<3; i++) loop */ | ||
1357 | p_byte[1] += skip_mcu[1]; | ||
1358 | p_byte[2] += skip_mcu[2]; | ||
1359 | if (p_jpeg->restart_interval && --restart == 0) | ||
1360 | { /* if a restart marker is due: */ | ||
1361 | restart = p_jpeg->restart_interval; /* count again */ | ||
1362 | search_restart(&bs); /* align the bitstream */ | ||
1363 | last_dc_val[0] = last_dc_val[1] = | ||
1364 | last_dc_val[2] = 0; /* reset decoder */ | ||
1365 | } | ||
1366 | } /* for x */ | ||
1367 | if (pf_progress != NULL) | ||
1368 | pf_progress(y, p_jpeg->y_mbl-1); /* notify about decoding progress */ | ||
1369 | } /* for y */ | ||
1370 | |||
1371 | return 0; /* success */ | ||
1372 | } | ||
1373 | #else /* !HAVE_LCD_COLOR */ | ||
1374 | |||
1375 | /* a JPEG decoder specialized in decoding only the luminance (b&w) */ | ||
1376 | int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel[1], int downscale, | ||
1377 | void (*pf_progress)(int current, int total)) | ||
1378 | { | ||
1379 | struct bitstream bs; /* bitstream "object" */ | ||
1380 | int block[64]; /* decoded DCT coefficients */ | ||
1381 | |||
1382 | int width, height; | ||
1383 | int skip_line; /* bytes from one line to the next (skip_line) */ | ||
1384 | int skip_strip, skip_mcu; /* bytes to next DCT row / column */ | ||
1385 | |||
1386 | int x, y; /* loop counter */ | ||
1387 | |||
1388 | unsigned char* p_line = p_pixel[0]; | ||
1389 | unsigned char* p_byte; /* bitmap pointer */ | ||
1390 | |||
1391 | void (*pf_idct)(unsigned char*, int*, int*, int); /* selected IDCT */ | ||
1392 | int k_need; /* AC coefficients needed up to here */ | ||
1393 | int zero_need; /* init the block with this many zeros */ | ||
1394 | |||
1395 | int last_dc_val = 0; | ||
1396 | int store_offs[4]; /* memory offsets: order of Y11 Y12 Y21 Y22 U V */ | ||
1397 | int restart = p_jpeg->restart_interval; /* MCUs until restart marker */ | ||
1398 | |||
1399 | /* pick the IDCT we want, determine how to work with coefs */ | ||
1400 | if (downscale == 1) | ||
1401 | { | ||
1402 | pf_idct = idct8x8; | ||
1403 | k_need = 64; /* all */ | ||
1404 | zero_need = 63; /* all */ | ||
1405 | } | ||
1406 | else if (downscale == 2) | ||
1407 | { | ||
1408 | pf_idct = idct4x4; | ||
1409 | k_need = 25; /* this far in zig-zag to cover 4*4 */ | ||
1410 | zero_need = 27; /* clear this far in linear order */ | ||
1411 | } | ||
1412 | else if (downscale == 4) | ||
1413 | { | ||
1414 | pf_idct = idct2x2; | ||
1415 | k_need = 5; /* this far in zig-zag to cover 2*2 */ | ||
1416 | zero_need = 9; /* clear this far in linear order */ | ||
1417 | } | ||
1418 | else if (downscale == 8) | ||
1419 | { | ||
1420 | pf_idct = idct1x1; | ||
1421 | k_need = 0; /* no AC, not needed */ | ||
1422 | zero_need = 0; /* no AC, not needed */ | ||
1423 | } | ||
1424 | else return -1; /* not supported */ | ||
1425 | |||
1426 | /* init bitstream, fake a restart to make it start */ | ||
1427 | bs.next_input_byte = p_jpeg->p_entropy_data; | ||
1428 | bs.bits_left = 0; | ||
1429 | bs.input_end = p_jpeg->p_entropy_end; | ||
1430 | |||
1431 | width = p_jpeg->x_phys / downscale; | ||
1432 | height = p_jpeg->y_phys / downscale; | ||
1433 | skip_line = width; | ||
1434 | skip_strip = skip_line * (height / p_jpeg->y_mbl); | ||
1435 | skip_mcu = (width/p_jpeg->x_mbl); | ||
1436 | |||
1437 | /* prepare offsets about where to store the different blocks */ | ||
1438 | store_offs[p_jpeg->store_pos[0]] = 0; | ||
1439 | store_offs[p_jpeg->store_pos[1]] = 8 / downscale; /* to the right */ | ||
1440 | store_offs[p_jpeg->store_pos[2]] = width * 8 / downscale; /* below */ | ||
1441 | store_offs[p_jpeg->store_pos[3]] = store_offs[1] + store_offs[2]; /* r+b */ | ||
1442 | |||
1443 | for(y=0; y<p_jpeg->y_mbl && bs.next_input_byte <= bs.input_end; y++) | ||
1444 | { | ||
1445 | p_byte = p_line; | ||
1446 | p_line += skip_strip; | ||
1447 | for (x=0; x<p_jpeg->x_mbl; x++) | ||
1448 | { | ||
1449 | int blkn; | ||
1450 | |||
1451 | /* Outer loop handles each block in the MCU */ | ||
1452 | for (blkn = 0; blkn < p_jpeg->blocks; blkn++) | ||
1453 | { /* Decode a single block's worth of coefficients */ | ||
1454 | int k = 1; /* coefficient index */ | ||
1455 | int s, r; /* huffman values */ | ||
1456 | int ci = p_jpeg->mcu_membership[blkn]; /* component index */ | ||
1457 | int ti = p_jpeg->tab_membership[blkn]; /* table index */ | ||
1458 | struct derived_tbl* dctbl = &p_jpeg->dc_derived_tbls[ti]; | ||
1459 | struct derived_tbl* actbl = &p_jpeg->ac_derived_tbls[ti]; | ||
1460 | |||
1461 | /* Section F.2.2.1: decode the DC coefficient difference */ | ||
1462 | s = huff_decode_dc(&bs, dctbl); | ||
1463 | |||
1464 | if (ci == 0) /* only for Y component */ | ||
1465 | { | ||
1466 | last_dc_val += s; | ||
1467 | block[0] = last_dc_val; /* output it (assumes zag[0] = 0) */ | ||
1468 | |||
1469 | /* coefficient buffer must be cleared */ | ||
1470 | MEMSET(block+1, 0, zero_need*sizeof(block[0])); | ||
1471 | |||
1472 | /* Section F.2.2.2: decode the AC coefficients */ | ||
1473 | for (; k < k_need; k++) | ||
1474 | { | ||
1475 | s = huff_decode_ac(&bs, actbl); | ||
1476 | r = s >> 4; | ||
1477 | s &= 15; | ||
1478 | |||
1479 | if (s) | ||
1480 | { | ||
1481 | k += r; | ||
1482 | check_bit_buffer(&bs, s); | ||
1483 | r = get_bits(&bs, s); | ||
1484 | block[zag[k]] = HUFF_EXTEND(r, s); | ||
1485 | } | ||
1486 | else | ||
1487 | { | ||
1488 | if (r != 15) | ||
1489 | { | ||
1490 | k = 64; | ||
1491 | break; | ||
1492 | } | ||
1493 | k += r; | ||
1494 | } | ||
1495 | } /* for k */ | ||
1496 | } | ||
1497 | /* In this path we just discard the values */ | ||
1498 | for (; k < 64; k++) | ||
1499 | { | ||
1500 | s = huff_decode_ac(&bs, actbl); | ||
1501 | r = s >> 4; | ||
1502 | s &= 15; | ||
1503 | |||
1504 | if (s) | ||
1505 | { | ||
1506 | k += r; | ||
1507 | check_bit_buffer(&bs, s); | ||
1508 | drop_bits(&bs, s); | ||
1509 | } | ||
1510 | else | ||
1511 | { | ||
1512 | if (r != 15) | ||
1513 | break; | ||
1514 | k += r; | ||
1515 | } | ||
1516 | } /* for k */ | ||
1517 | |||
1518 | if (ci == 0) | ||
1519 | { /* only for Y component */ | ||
1520 | pf_idct(p_byte+store_offs[blkn], block, p_jpeg->qt_idct[ti], | ||
1521 | skip_line); | ||
1522 | } | ||
1523 | } /* for blkn */ | ||
1524 | p_byte += skip_mcu; | ||
1525 | if (p_jpeg->restart_interval && --restart == 0) | ||
1526 | { /* if a restart marker is due: */ | ||
1527 | restart = p_jpeg->restart_interval; /* count again */ | ||
1528 | search_restart(&bs); /* align the bitstream */ | ||
1529 | last_dc_val = 0; /* reset decoder */ | ||
1530 | } | ||
1531 | } /* for x */ | ||
1532 | if (pf_progress != NULL) | ||
1533 | pf_progress(y, p_jpeg->y_mbl-1); /* notify about decoding progress */ | ||
1534 | } /* for y */ | ||
1535 | |||
1536 | return 0; /* success */ | ||
1537 | } | ||
1538 | #endif /* !HAVE_LCD_COLOR */ | ||
1539 | |||
1540 | /**************** end JPEG code ********************/ | ||
diff --git a/apps/plugins/jpeg/jpeg_decoder.h b/apps/plugins/jpeg/jpeg_decoder.h new file mode 100644 index 0000000000..f4dbeaa147 --- /dev/null +++ b/apps/plugins/jpeg/jpeg_decoder.h | |||
@@ -0,0 +1,142 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * JPEG image viewer | ||
11 | * (This is a real mess if it has to be coded in one single C file) | ||
12 | * | ||
13 | * File scrolling addition (C) 2005 Alexander Spyridakis | ||
14 | * Copyright (C) 2004 Jörg Hohensohn aka [IDC]Dragon | ||
15 | * Heavily borrowed from the IJG implementation (C) Thomas G. Lane | ||
16 | * Small & fast downscaling IDCT (C) 2002 by Guido Vollbeding JPEGclub.org | ||
17 | * | ||
18 | * This program is free software; you can redistribute it and/or | ||
19 | * modify it under the terms of the GNU General Public License | ||
20 | * as published by the Free Software Foundation; either version 2 | ||
21 | * of the License, or (at your option) any later version. | ||
22 | * | ||
23 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
24 | * KIND, either express or implied. | ||
25 | * | ||
26 | ****************************************************************************/ | ||
27 | |||
28 | #ifndef _JPEG_JPEG_DECODER_H | ||
29 | #define _JPEG_JPEG_DECODER_H | ||
30 | |||
31 | #define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ | ||
32 | |||
33 | struct derived_tbl | ||
34 | { | ||
35 | /* Basic tables: (element [0] of each array is unused) */ | ||
36 | long mincode[17]; /* smallest code of length k */ | ||
37 | long maxcode[18]; /* largest code of length k (-1 if none) */ | ||
38 | /* (maxcode[17] is a sentinel to ensure huff_DECODE terminates) */ | ||
39 | int valptr[17]; /* huffval[] index of 1st symbol of length k */ | ||
40 | |||
41 | /* Back link to public Huffman table (needed only in slow_DECODE) */ | ||
42 | int* pub; | ||
43 | |||
44 | /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of | ||
45 | the input data stream. If the next Huffman code is no more | ||
46 | than HUFF_LOOKAHEAD bits long, we can obtain its length and | ||
47 | the corresponding symbol directly from these tables. */ | ||
48 | int look_nbits[1<<HUFF_LOOKAHEAD]; /* # bits, or 0 if too long */ | ||
49 | unsigned char look_sym[1<<HUFF_LOOKAHEAD]; /* symbol, or unused */ | ||
50 | }; | ||
51 | |||
52 | #define QUANT_TABLE_LENGTH 64 | ||
53 | |||
54 | /* for type of Huffman table */ | ||
55 | #define DC_LEN 28 | ||
56 | #define AC_LEN 178 | ||
57 | |||
58 | struct huffman_table | ||
59 | { /* length and code according to JFIF format */ | ||
60 | int huffmancodes_dc[DC_LEN]; | ||
61 | int huffmancodes_ac[AC_LEN]; | ||
62 | }; | ||
63 | |||
64 | struct frame_component | ||
65 | { | ||
66 | int ID; | ||
67 | int horizontal_sampling; | ||
68 | int vertical_sampling; | ||
69 | int quanttable_select; | ||
70 | }; | ||
71 | |||
72 | struct scan_component | ||
73 | { | ||
74 | int ID; | ||
75 | int DC_select; | ||
76 | int AC_select; | ||
77 | }; | ||
78 | |||
79 | struct bitstream | ||
80 | { | ||
81 | unsigned long get_buffer; /* current bit-extraction buffer */ | ||
82 | int bits_left; /* # of unused bits in it */ | ||
83 | unsigned char* next_input_byte; | ||
84 | unsigned char* input_end; /* upper limit +1 */ | ||
85 | }; | ||
86 | |||
87 | struct jpeg | ||
88 | { | ||
89 | int x_size, y_size; /* size of image (can be less than block boundary) */ | ||
90 | int x_phys, y_phys; /* physical size, block aligned */ | ||
91 | int x_mbl; /* x dimension of MBL */ | ||
92 | int y_mbl; /* y dimension of MBL */ | ||
93 | int blocks; /* blocks per MB */ | ||
94 | int restart_interval; /* number of MCUs between RSTm markers */ | ||
95 | int store_pos[4]; /* for Y block ordering */ | ||
96 | |||
97 | unsigned char* p_entropy_data; | ||
98 | unsigned char* p_entropy_end; | ||
99 | |||
100 | int quanttable[4][QUANT_TABLE_LENGTH]; /* raw quantization tables 0-3 */ | ||
101 | int qt_idct[2][QUANT_TABLE_LENGTH]; /* quantization tables for IDCT */ | ||
102 | |||
103 | struct huffman_table hufftable[2]; /* Huffman tables */ | ||
104 | struct derived_tbl dc_derived_tbls[2]; /* Huffman-LUTs */ | ||
105 | struct derived_tbl ac_derived_tbls[2]; | ||
106 | |||
107 | struct frame_component frameheader[3]; /* Component descriptor */ | ||
108 | struct scan_component scanheader[3]; /* currently not used */ | ||
109 | |||
110 | int mcu_membership[6]; /* info per block */ | ||
111 | int tab_membership[6]; | ||
112 | int subsample_x[3]; /* info per component */ | ||
113 | int subsample_y[3]; | ||
114 | }; | ||
115 | |||
116 | |||
117 | /* possible return flags for process_markers() */ | ||
118 | #define HUFFTAB 0x0001 /* with huffman table */ | ||
119 | #define QUANTTAB 0x0002 /* with quantization table */ | ||
120 | #define APP0_JFIF 0x0004 /* with APP0 segment following JFIF standard */ | ||
121 | #define FILL_FF 0x0008 /* with 0xFF padding bytes at begin/end */ | ||
122 | #define SOF0 0x0010 /* with SOF0-Segment */ | ||
123 | #define DHT 0x0020 /* with Definition of huffman tables */ | ||
124 | #define SOS 0x0040 /* with Start-of-Scan segment */ | ||
125 | #define DQT 0x0080 /* with definition of quantization table */ | ||
126 | |||
127 | /* various helper functions */ | ||
128 | void default_huff_tbl(struct jpeg* p_jpeg); | ||
129 | void build_lut(struct jpeg* p_jpeg); | ||
130 | int process_markers(unsigned char* p_src, long size, struct jpeg* p_jpeg); | ||
131 | |||
132 | /* the main decode function */ | ||
133 | #ifdef HAVE_LCD_COLOR | ||
134 | int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel[3], | ||
135 | int downscale, void (*pf_progress)(int current, int total)); | ||
136 | #else | ||
137 | int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel[1], int downscale, | ||
138 | void (*pf_progress)(int current, int total)); | ||
139 | #endif | ||
140 | |||
141 | |||
142 | #endif /* _JPEG_JPEG_DECODER_H */ | ||
diff --git a/apps/plugins/jpeg/yuv2rgb.c b/apps/plugins/jpeg/yuv2rgb.c new file mode 100644 index 0000000000..1130f038af --- /dev/null +++ b/apps/plugins/jpeg/yuv2rgb.c | |||
@@ -0,0 +1,401 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * JPEG image viewer | ||
11 | * (This is a real mess if it has to be coded in one single C file) | ||
12 | * | ||
13 | * File scrolling addition (C) 2005 Alexander Spyridakis | ||
14 | * Copyright (C) 2004 Jörg Hohensohn aka [IDC]Dragon | ||
15 | * Heavily borrowed from the IJG implementation (C) Thomas G. Lane | ||
16 | * Small & fast downscaling IDCT (C) 2002 by Guido Vollbeding JPEGclub.org | ||
17 | * | ||
18 | * This program is free software; you can redistribute it and/or | ||
19 | * modify it under the terms of the GNU General Public License | ||
20 | * as published by the Free Software Foundation; either version 2 | ||
21 | * of the License, or (at your option) any later version. | ||
22 | * | ||
23 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
24 | * KIND, either express or implied. | ||
25 | * | ||
26 | ****************************************************************************/ | ||
27 | |||
28 | #include "plugin.h" | ||
29 | #include "yuv2rgb.h" | ||
30 | |||
31 | /* Needed for memset and rb->lcd_framebuffer */ | ||
32 | extern const struct plugin_api* rb; | ||
33 | |||
34 | /* | ||
35 | * Conversion of full 0-255 range YCrCb to RGB: | ||
36 | * |R| |1.000000 -0.000001 1.402000| |Y'| | ||
37 | * |G| = |1.000000 -0.334136 -0.714136| |Pb| | ||
38 | * |B| |1.000000 1.772000 0.000000| |Pr| | ||
39 | * Scaled (yields s15-bit output): | ||
40 | * |R| |128 0 179| |Y | | ||
41 | * |G| = |128 -43 -91| |Cb - 128| | ||
42 | * |B| |128 227 0| |Cr - 128| | ||
43 | */ | ||
44 | #define YFAC 128 | ||
45 | #define RVFAC 179 | ||
46 | #define GUFAC (-43) | ||
47 | #define GVFAC (-91) | ||
48 | #define BUFAC 227 | ||
49 | #define YUV_WHITE (255*YFAC) | ||
50 | #define NODITHER_DELTA (127*YFAC) | ||
51 | #define COMPONENT_SHIFT 15 | ||
52 | #define MATRIX_SHIFT 7 | ||
53 | |||
54 | static inline int clamp_component(int x) | ||
55 | { | ||
56 | if ((unsigned)x > YUV_WHITE) | ||
57 | x = x < 0 ? 0 : YUV_WHITE; | ||
58 | return x; | ||
59 | } | ||
60 | |||
61 | static inline int clamp_component_bits(int x, int bits) | ||
62 | { | ||
63 | if ((unsigned)x > (1u << bits) - 1) | ||
64 | x = x < 0 ? 0 : (1 << bits) - 1; | ||
65 | return x; | ||
66 | } | ||
67 | |||
68 | static inline int component_to_lcd(int x, int bits, int delta) | ||
69 | { | ||
70 | /* Formula used in core bitmap loader. */ | ||
71 | return (((1 << bits) - 1)*x + (x >> (8 - bits)) + delta) >> COMPONENT_SHIFT; | ||
72 | } | ||
73 | |||
74 | static inline int lcd_to_component(int x, int bits, int delta) | ||
75 | { | ||
76 | /* Reasonable, approximate reversal to get a full range back from the | ||
77 | quantized value. */ | ||
78 | return YUV_WHITE*x / ((1 << bits) - 1); | ||
79 | (void)delta; | ||
80 | } | ||
81 | |||
82 | #define RED 0 | ||
83 | #define GRN 1 | ||
84 | #define BLU 2 | ||
85 | |||
86 | struct rgb_err | ||
87 | { | ||
88 | int16_t errbuf[LCD_WIDTH+2]; /* Error record for line below */ | ||
89 | } rgb_err_buffers[3]; | ||
90 | |||
91 | struct rgb_pixel | ||
92 | { | ||
93 | int r, g, b; /* Current pixel components in s16.0 */ | ||
94 | int inc; /* Current line increment (-1 or 1) */ | ||
95 | int row; /* Current row in source image */ | ||
96 | int col; /* Current column in source image */ | ||
97 | int ce[3]; /* Errors to apply to current pixel */ | ||
98 | struct rgb_err *e; /* RED, GRN, BLU */ | ||
99 | int epos; /* Current position in error record */ | ||
100 | }; | ||
101 | |||
102 | struct rgb_pixel *pixel; | ||
103 | |||
104 | /** round and truncate to lcd depth **/ | ||
105 | static fb_data pixel_to_lcd_colour(void) | ||
106 | { | ||
107 | struct rgb_pixel *p = pixel; | ||
108 | int r, g, b; | ||
109 | |||
110 | r = component_to_lcd(p->r, LCD_RED_BITS, NODITHER_DELTA); | ||
111 | r = clamp_component_bits(r, LCD_RED_BITS); | ||
112 | |||
113 | g = component_to_lcd(p->g, LCD_GREEN_BITS, NODITHER_DELTA); | ||
114 | g = clamp_component_bits(g, LCD_GREEN_BITS); | ||
115 | |||
116 | b = component_to_lcd(p->b, LCD_BLUE_BITS, NODITHER_DELTA); | ||
117 | b = clamp_component_bits(b, LCD_BLUE_BITS); | ||
118 | |||
119 | return LCD_RGBPACK_LCD(r, g, b); | ||
120 | } | ||
121 | |||
122 | /** write a monochrome pixel to the colour LCD **/ | ||
123 | static fb_data pixel_to_lcd_gray(void) | ||
124 | { | ||
125 | int r, g, b; | ||
126 | |||
127 | g = clamp_component(pixel->g); | ||
128 | r = component_to_lcd(g, LCD_RED_BITS, NODITHER_DELTA); | ||
129 | b = component_to_lcd(g, LCD_BLUE_BITS, NODITHER_DELTA); | ||
130 | g = component_to_lcd(g, LCD_GREEN_BITS, NODITHER_DELTA); | ||
131 | |||
132 | return LCD_RGBPACK_LCD(r, g, b); | ||
133 | } | ||
134 | |||
135 | /** | ||
136 | * Bayer ordered dithering - swiped from the core bitmap loader. | ||
137 | */ | ||
138 | static fb_data pixel_odither_to_lcd(void) | ||
139 | { | ||
140 | /* canonical ordered dither matrix */ | ||
141 | static const unsigned char dither_matrix[16][16] = { | ||
142 | { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 }, | ||
143 | { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 }, | ||
144 | { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 }, | ||
145 | { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 }, | ||
146 | { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 }, | ||
147 | { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 }, | ||
148 | { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 }, | ||
149 | { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 }, | ||
150 | { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 }, | ||
151 | { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 }, | ||
152 | { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 }, | ||
153 | { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 }, | ||
154 | { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 }, | ||
155 | { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 }, | ||
156 | { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 }, | ||
157 | { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 } | ||
158 | }; | ||
159 | |||
160 | struct rgb_pixel *p = pixel; | ||
161 | int r, g, b, delta; | ||
162 | |||
163 | delta = dither_matrix[p->col & 15][p->row & 15] << MATRIX_SHIFT; | ||
164 | |||
165 | r = component_to_lcd(p->r, LCD_RED_BITS, delta); | ||
166 | r = clamp_component_bits(r, LCD_RED_BITS); | ||
167 | |||
168 | g = component_to_lcd(p->g, LCD_GREEN_BITS, delta); | ||
169 | g = clamp_component_bits(g, LCD_GREEN_BITS); | ||
170 | |||
171 | b = component_to_lcd(p->b, LCD_BLUE_BITS, delta); | ||
172 | b = clamp_component_bits(b, LCD_BLUE_BITS); | ||
173 | |||
174 | p->col += p->inc; | ||
175 | |||
176 | return LCD_RGBPACK_LCD(r, g, b); | ||
177 | } | ||
178 | |||
179 | /** | ||
180 | * Floyd/Steinberg dither to lcd depth. | ||
181 | * | ||
182 | * Apply filter to each component in serpentine pattern. Kernel shown for | ||
183 | * L->R scan. Kernel is reversed for R->L. | ||
184 | * * 7 | ||
185 | * 3 5 1 (1/16) | ||
186 | */ | ||
187 | static inline void distribute_error(int *ce, struct rgb_err *e, | ||
188 | int err, int epos, int inc) | ||
189 | { | ||
190 | *ce = (7*err >> 4) + e->errbuf[epos+inc]; | ||
191 | e->errbuf[epos+inc] = err >> 4; | ||
192 | e->errbuf[epos] += 5*err >> 4; | ||
193 | e->errbuf[epos-inc] += 3*err >> 4; | ||
194 | } | ||
195 | |||
196 | static fb_data pixel_fsdither_to_lcd(void) | ||
197 | { | ||
198 | struct rgb_pixel *p = pixel; | ||
199 | int rc, gc, bc, r, g, b; | ||
200 | int inc, epos; | ||
201 | |||
202 | /* Full components with error terms */ | ||
203 | rc = p->r + p->ce[RED]; | ||
204 | r = component_to_lcd(rc, LCD_RED_BITS, 0); | ||
205 | r = clamp_component_bits(r, LCD_RED_BITS); | ||
206 | |||
207 | gc = p->g + p->ce[GRN]; | ||
208 | g = component_to_lcd(gc, LCD_GREEN_BITS, 0); | ||
209 | g = clamp_component_bits(g, LCD_GREEN_BITS); | ||
210 | |||
211 | bc = p->b + p->ce[BLU]; | ||
212 | b = component_to_lcd(bc, LCD_BLUE_BITS, 0); | ||
213 | b = clamp_component_bits(b, LCD_BLUE_BITS); | ||
214 | |||
215 | /* Get pixel errors */ | ||
216 | rc -= lcd_to_component(r, LCD_RED_BITS, 0); | ||
217 | gc -= lcd_to_component(g, LCD_GREEN_BITS, 0); | ||
218 | bc -= lcd_to_component(b, LCD_BLUE_BITS, 0); | ||
219 | |||
220 | /* Spead error to surrounding pixels. */ | ||
221 | inc = p->inc; | ||
222 | epos = p->epos; | ||
223 | p->epos += inc; | ||
224 | |||
225 | distribute_error(&p->ce[RED], &p->e[RED], rc, epos, inc); | ||
226 | distribute_error(&p->ce[GRN], &p->e[GRN], gc, epos, inc); | ||
227 | distribute_error(&p->ce[BLU], &p->e[BLU], bc, epos, inc); | ||
228 | |||
229 | /* Pack and return pixel */ | ||
230 | return LCD_RGBPACK_LCD(r, g, b); | ||
231 | } | ||
232 | |||
233 | /* Functions for each output mode, colour then grayscale. */ | ||
234 | static fb_data (* const pixel_funcs[COLOUR_NUM_MODES][DITHER_NUM_MODES])(void) = | ||
235 | { | ||
236 | [COLOURMODE_COLOUR] = | ||
237 | { | ||
238 | [DITHER_NONE] = pixel_to_lcd_colour, | ||
239 | [DITHER_ORDERED] = pixel_odither_to_lcd, | ||
240 | [DITHER_DIFFUSION] = pixel_fsdither_to_lcd, | ||
241 | }, | ||
242 | [COLOURMODE_GRAY] = | ||
243 | { | ||
244 | [DITHER_NONE] = pixel_to_lcd_gray, | ||
245 | [DITHER_ORDERED] = pixel_odither_to_lcd, | ||
246 | [DITHER_DIFFUSION] = pixel_fsdither_to_lcd, | ||
247 | }, | ||
248 | }; | ||
249 | |||
250 | /** | ||
251 | * Draw a partial YUV colour bitmap | ||
252 | * | ||
253 | * Runs serpentine pattern when dithering is DITHER_DIFFUSION, else scan is | ||
254 | * always L->R. | ||
255 | */ | ||
256 | void yuv_bitmap_part(unsigned char *src[3], int csub_x, int csub_y, | ||
257 | int src_x, int src_y, int stride, | ||
258 | int x, int y, int width, int height, | ||
259 | int colour_mode, int dither_mode) | ||
260 | { | ||
261 | fb_data *dst, *dst_end; | ||
262 | fb_data (*pixel_func)(void); | ||
263 | struct rgb_pixel px; | ||
264 | |||
265 | if (x + width > LCD_WIDTH) | ||
266 | width = LCD_WIDTH - x; /* Clip right */ | ||
267 | if (x < 0) | ||
268 | width += x, x = 0; /* Clip left */ | ||
269 | if (width <= 0) | ||
270 | return; /* nothing left to do */ | ||
271 | |||
272 | if (y + height > LCD_HEIGHT) | ||
273 | height = LCD_HEIGHT - y; /* Clip bottom */ | ||
274 | if (y < 0) | ||
275 | height += y, y = 0; /* Clip top */ | ||
276 | if (height <= 0) | ||
277 | return; /* nothing left to do */ | ||
278 | |||
279 | pixel = &px; | ||
280 | |||
281 | dst = rb->lcd_framebuffer + LCD_WIDTH * y + x; | ||
282 | dst_end = dst + LCD_WIDTH * height; | ||
283 | |||
284 | if (colour_mode == COLOURMODE_GRAY) | ||
285 | csub_y = 0; /* Ignore Cb, Cr */ | ||
286 | |||
287 | pixel_func = pixel_funcs[colour_mode] | ||
288 | [dither_mode]; | ||
289 | |||
290 | if (dither_mode == DITHER_DIFFUSION) | ||
291 | { | ||
292 | /* Reset error terms. */ | ||
293 | px.e = rgb_err_buffers; | ||
294 | px.ce[RED] = px.ce[GRN] = px.ce[BLU] = 0; | ||
295 | rb->memset(px.e, 0, 3*sizeof (struct rgb_err)); | ||
296 | } | ||
297 | |||
298 | do | ||
299 | { | ||
300 | fb_data *dst_row, *row_end; | ||
301 | const unsigned char *ysrc; | ||
302 | px.inc = 1; | ||
303 | |||
304 | if (dither_mode == DITHER_DIFFUSION) | ||
305 | { | ||
306 | /* Use R->L scan on odd lines */ | ||
307 | px.inc -= (src_y & 1) << 1; | ||
308 | px.epos = x + 1; | ||
309 | |||
310 | if (px.inc < 0) | ||
311 | px.epos += width - 1; | ||
312 | } | ||
313 | |||
314 | if (px.inc == 1) | ||
315 | { | ||
316 | /* Scan is L->R */ | ||
317 | dst_row = dst; | ||
318 | row_end = dst_row + width; | ||
319 | px.col = src_x; | ||
320 | } | ||
321 | else | ||
322 | { | ||
323 | /* Scan is R->L */ | ||
324 | row_end = dst - 1; | ||
325 | dst_row = row_end + width; | ||
326 | px.col = src_x + width - 1; | ||
327 | } | ||
328 | |||
329 | ysrc = src[0] + stride * src_y + px.col; | ||
330 | px.row = src_y; | ||
331 | |||
332 | /* Do one row of pixels */ | ||
333 | if (csub_y) /* colour */ | ||
334 | { | ||
335 | /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ | ||
336 | const unsigned char *usrc, *vsrc; | ||
337 | |||
338 | usrc = src[1] + (stride/csub_x) * (src_y/csub_y) | ||
339 | + (px.col/csub_x); | ||
340 | vsrc = src[2] + (stride/csub_x) * (src_y/csub_y) | ||
341 | + (px.col/csub_x); | ||
342 | int xphase = px.col % csub_x; | ||
343 | int xphase_reset = px.inc * csub_x; | ||
344 | int y, v, u, rv, guv, bu; | ||
345 | |||
346 | v = *vsrc - 128; | ||
347 | vsrc += px.inc; | ||
348 | u = *usrc - 128; | ||
349 | usrc += px.inc; | ||
350 | rv = RVFAC*v; | ||
351 | guv = GUFAC*u + GVFAC*v; | ||
352 | bu = BUFAC*u; | ||
353 | |||
354 | while (1) | ||
355 | { | ||
356 | y = YFAC*(*ysrc); | ||
357 | ysrc += px.inc; | ||
358 | px.r = y + rv; | ||
359 | px.g = y + guv; | ||
360 | px.b = y + bu; | ||
361 | |||
362 | *dst_row = pixel_func(); | ||
363 | dst_row += px.inc; | ||
364 | |||
365 | if (dst_row == row_end) | ||
366 | break; | ||
367 | |||
368 | xphase += px.inc; | ||
369 | if ((unsigned)xphase < (unsigned)csub_x) | ||
370 | continue; | ||
371 | |||
372 | /* fetch new chromas */ | ||
373 | v = *vsrc - 128; | ||
374 | vsrc += px.inc; | ||
375 | u = *usrc - 128; | ||
376 | usrc += px.inc; | ||
377 | rv = RVFAC*v; | ||
378 | guv = GUFAC*u + GVFAC*v; | ||
379 | bu = BUFAC*u; | ||
380 | |||
381 | xphase -= xphase_reset; | ||
382 | } | ||
383 | } | ||
384 | else /* monochrome */ | ||
385 | { | ||
386 | do | ||
387 | { | ||
388 | /* Set all components the same for dithering purposes */ | ||
389 | px.g = px.r = px.b = YFAC*(*ysrc); | ||
390 | *dst_row = pixel_func(); | ||
391 | ysrc += px.inc; | ||
392 | dst_row += px.inc; | ||
393 | } | ||
394 | while (dst_row != row_end); | ||
395 | } | ||
396 | |||
397 | src_y++; | ||
398 | dst += LCD_WIDTH; | ||
399 | } | ||
400 | while (dst < dst_end); | ||
401 | } | ||
diff --git a/apps/plugins/jpeg/yuv2rgb.h b/apps/plugins/jpeg/yuv2rgb.h new file mode 100644 index 0000000000..d10a944f38 --- /dev/null +++ b/apps/plugins/jpeg/yuv2rgb.h | |||
@@ -0,0 +1,51 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * JPEG image viewer | ||
11 | * (This is a real mess if it has to be coded in one single C file) | ||
12 | * | ||
13 | * File scrolling addition (C) 2005 Alexander Spyridakis | ||
14 | * Copyright (C) 2004 Jörg Hohensohn aka [IDC]Dragon | ||
15 | * Heavily borrowed from the IJG implementation (C) Thomas G. Lane | ||
16 | * Small & fast downscaling IDCT (C) 2002 by Guido Vollbeding JPEGclub.org | ||
17 | * | ||
18 | * This program is free software; you can redistribute it and/or | ||
19 | * modify it under the terms of the GNU General Public License | ||
20 | * as published by the Free Software Foundation; either version 2 | ||
21 | * of the License, or (at your option) any later version. | ||
22 | * | ||
23 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
24 | * KIND, either express or implied. | ||
25 | * | ||
26 | ****************************************************************************/ | ||
27 | |||
28 | #ifndef _JPEG_YUV2RGB_H | ||
29 | #define _JPEG_YUV2RGB_H | ||
30 | |||
31 | enum color_modes | ||
32 | { | ||
33 | COLOURMODE_COLOUR = 0, | ||
34 | COLOURMODE_GRAY, | ||
35 | COLOUR_NUM_MODES | ||
36 | }; | ||
37 | |||
38 | enum dither_modes | ||
39 | { | ||
40 | DITHER_NONE = 0, /* No dithering */ | ||
41 | DITHER_ORDERED, /* Bayer ordered */ | ||
42 | DITHER_DIFFUSION, /* Floyd/Steinberg error diffusion */ | ||
43 | DITHER_NUM_MODES | ||
44 | }; | ||
45 | |||
46 | void yuv_bitmap_part(unsigned char *src[3], int csub_x, int csub_y, | ||
47 | int src_x, int src_y, int stride, | ||
48 | int x, int y, int width, int height, | ||
49 | int colour_mode, int dither_mode); | ||
50 | |||
51 | #endif | ||