fixing red:
[Rockbox.git] / apps / plugins / jpeg.c
blobf128558c5a9823bcf715e95cdaf00879c97a904b
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * JPEG image viewer
11 * (This is a real mess if it has to be coded in one single C file)
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
18 * All files in this archive are subject to the GNU General Public License.
19 * See the file COPYING in the source tree root for full license agreement.
21 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
22 * KIND, either express or implied.
24 ****************************************************************************/
26 #include "plugin.h"
27 #include "playback_control.h"
28 #include "oldmenuapi.h"
29 #include "helper.h"
30 #include "lib/configfile.h"
32 #ifdef HAVE_LCD_BITMAP
33 #include "grey.h"
34 #include "xlcd.h"
36 PLUGIN_HEADER
38 /* variable button definitions */
39 #if CONFIG_KEYPAD == RECORDER_PAD
40 #define JPEG_ZOOM_IN BUTTON_PLAY
41 #define JPEG_ZOOM_OUT BUTTON_ON
42 #define JPEG_UP BUTTON_UP
43 #define JPEG_DOWN BUTTON_DOWN
44 #define JPEG_LEFT BUTTON_LEFT
45 #define JPEG_RIGHT BUTTON_RIGHT
46 #define JPEG_NEXT BUTTON_F3
47 #define JPEG_PREVIOUS BUTTON_F2
48 #define JPEG_MENU BUTTON_OFF
50 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
51 #define JPEG_ZOOM_IN BUTTON_SELECT
52 #define JPEG_ZOOM_OUT BUTTON_ON
53 #define JPEG_UP BUTTON_UP
54 #define JPEG_DOWN BUTTON_DOWN
55 #define JPEG_LEFT BUTTON_LEFT
56 #define JPEG_RIGHT BUTTON_RIGHT
57 #define JPEG_NEXT BUTTON_F3
58 #define JPEG_PREVIOUS BUTTON_F2
59 #define JPEG_MENU BUTTON_OFF
61 #elif CONFIG_KEYPAD == ONDIO_PAD
62 #define JPEG_ZOOM_PRE BUTTON_MENU
63 #define JPEG_ZOOM_IN (BUTTON_MENU | BUTTON_REL)
64 #define JPEG_ZOOM_OUT (BUTTON_MENU | BUTTON_DOWN)
65 #define JPEG_UP BUTTON_UP
66 #define JPEG_DOWN BUTTON_DOWN
67 #define JPEG_LEFT BUTTON_LEFT
68 #define JPEG_RIGHT BUTTON_RIGHT
69 #define JPEG_NEXT (BUTTON_MENU | BUTTON_RIGHT)
70 #define JPEG_PREVIOUS (BUTTON_MENU | BUTTON_LEFT)
71 #define JPEG_MENU BUTTON_OFF
73 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
74 (CONFIG_KEYPAD == IRIVER_H300_PAD)
75 #define JPEG_ZOOM_IN BUTTON_SELECT
76 #define JPEG_ZOOM_OUT BUTTON_MODE
77 #define JPEG_UP BUTTON_UP
78 #define JPEG_DOWN BUTTON_DOWN
79 #define JPEG_LEFT BUTTON_LEFT
80 #define JPEG_RIGHT BUTTON_RIGHT
81 #if (CONFIG_KEYPAD == IRIVER_H100_PAD)
82 #define JPEG_NEXT BUTTON_ON
83 #define JPEG_PREVIOUS BUTTON_REC
84 #else
85 #define JPEG_NEXT BUTTON_REC
86 #define JPEG_PREVIOUS BUTTON_ON
87 #endif
88 #define JPEG_MENU BUTTON_OFF
89 #define JPEG_RC_MENU BUTTON_RC_STOP
91 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
92 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
93 #define JPEG_ZOOM_IN BUTTON_SCROLL_FWD
94 #define JPEG_ZOOM_OUT BUTTON_SCROLL_BACK
95 #define JPEG_UP BUTTON_MENU
96 #define JPEG_DOWN BUTTON_PLAY
97 #define JPEG_LEFT BUTTON_LEFT
98 #define JPEG_RIGHT BUTTON_RIGHT
99 #define JPEG_MENU (BUTTON_SELECT | BUTTON_MENU)
100 #define JPEG_NEXT (BUTTON_SELECT | BUTTON_RIGHT)
101 #define JPEG_PREVIOUS (BUTTON_SELECT | BUTTON_LEFT)
103 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
104 #define JPEG_ZOOM_PRE BUTTON_SELECT
105 #define JPEG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
106 #define JPEG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
107 #define JPEG_UP BUTTON_UP
108 #define JPEG_DOWN BUTTON_DOWN
109 #define JPEG_LEFT BUTTON_LEFT
110 #define JPEG_RIGHT BUTTON_RIGHT
111 #define JPEG_MENU BUTTON_POWER
112 #define JPEG_NEXT BUTTON_PLAY
113 #define JPEG_PREVIOUS BUTTON_REC
115 #elif CONFIG_KEYPAD == GIGABEAT_PAD
116 #define JPEG_ZOOM_IN BUTTON_VOL_UP
117 #define JPEG_ZOOM_OUT BUTTON_VOL_DOWN
118 #define JPEG_UP BUTTON_UP
119 #define JPEG_DOWN BUTTON_DOWN
120 #define JPEG_LEFT BUTTON_LEFT
121 #define JPEG_RIGHT BUTTON_RIGHT
122 #define JPEG_MENU BUTTON_MENU
123 #define JPEG_NEXT (BUTTON_A | BUTTON_RIGHT)
124 #define JPEG_PREVIOUS (BUTTON_A | BUTTON_LEFT)
126 #elif CONFIG_KEYPAD == SANSA_E200_PAD
127 #define JPEG_ZOOM_PRE BUTTON_SELECT
128 #define JPEG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
129 #define JPEG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
130 #define JPEG_UP BUTTON_UP
131 #define JPEG_DOWN BUTTON_DOWN
132 #define JPEG_LEFT BUTTON_LEFT
133 #define JPEG_RIGHT BUTTON_RIGHT
134 #define JPEG_MENU BUTTON_POWER
135 #define JPEG_SLIDE_SHOW BUTTON_REC
136 #define JPEG_NEXT BUTTON_SCROLL_FWD
137 #define JPEG_NEXT_REPEAT (BUTTON_SCROLL_FWD|BUTTON_REPEAT)
138 #define JPEG_PREVIOUS BUTTON_SCROLL_BACK
139 #define JPEG_PREVIOUS_REPEAT (BUTTON_SCROLL_BACK|BUTTON_REPEAT)
141 #elif CONFIG_KEYPAD == SANSA_C200_PAD
142 #define JPEG_ZOOM_PRE BUTTON_SELECT
143 #define JPEG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
144 #define JPEG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
145 #define JPEG_UP BUTTON_UP
146 #define JPEG_DOWN BUTTON_DOWN
147 #define JPEG_LEFT BUTTON_LEFT
148 #define JPEG_RIGHT BUTTON_RIGHT
149 #define JPEG_MENU BUTTON_POWER
150 #define JPEG_SLIDE_SHOW BUTTON_REC
151 #define JPEG_NEXT BUTTON_VOL_UP
152 #define JPEG_NEXT_REPEAT (BUTTON_VOL_UP|BUTTON_REPEAT)
153 #define JPEG_PREVIOUS BUTTON_VOL_DOWN
154 #define JPEG_PREVIOUS_REPEAT (BUTTON_VOL_DOWN|BUTTON_REPEAT)
156 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
157 #define JPEG_ZOOM_PRE BUTTON_PLAY
158 #define JPEG_ZOOM_IN (BUTTON_PLAY | BUTTON_REL)
159 #define JPEG_ZOOM_OUT (BUTTON_PLAY | BUTTON_REPEAT)
160 #define JPEG_UP BUTTON_SCROLL_UP
161 #define JPEG_DOWN BUTTON_SCROLL_DOWN
162 #define JPEG_LEFT BUTTON_LEFT
163 #define JPEG_RIGHT BUTTON_RIGHT
164 #define JPEG_MENU BUTTON_POWER
165 #define JPEG_NEXT BUTTON_FF
166 #define JPEG_PREVIOUS BUTTON_REW
168 #elif CONFIG_KEYPAD == MROBE500_PAD
169 #define JPEG_ZOOM_IN BUTTON_RC_VOL_UP
170 #define JPEG_ZOOM_OUT BUTTON_RC_VOL_DOWN
171 #define JPEG_UP BUTTON_RC_PLAY
172 #define JPEG_DOWN BUTTON_RC_DOWN
173 #define JPEG_LEFT BUTTON_LEFT
174 #define JPEG_RIGHT BUTTON_RIGHT
175 #define JPEG_MENU BUTTON_POWER
176 #define JPEG_NEXT BUTTON_RC_HEART
177 #define JPEG_PREVIOUS BUTTON_RC_MODE
179 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
180 #define JPEG_ZOOM_IN BUTTON_VOL_UP
181 #define JPEG_ZOOM_OUT BUTTON_VOL_DOWN
182 #define JPEG_UP BUTTON_UP
183 #define JPEG_DOWN BUTTON_DOWN
184 #define JPEG_LEFT BUTTON_LEFT
185 #define JPEG_RIGHT BUTTON_RIGHT
186 #define JPEG_MENU BUTTON_MENU
187 #define JPEG_NEXT BUTTON_NEXT
188 #define JPEG_PREVIOUS BUTTON_PREV
190 #elif CONFIG_KEYPAD == MROBE100_PAD
191 #define JPEG_ZOOM_IN BUTTON_SELECT
192 #define JPEG_ZOOM_OUT BUTTON_PLAY
193 #define JPEG_UP BUTTON_UP
194 #define JPEG_DOWN BUTTON_DOWN
195 #define JPEG_LEFT BUTTON_LEFT
196 #define JPEG_RIGHT BUTTON_RIGHT
197 #define JPEG_MENU BUTTON_MENU
198 #define JPEG_NEXT (BUTTON_DISPLAY | BUTTON_RIGHT)
199 #define JPEG_PREVIOUS (BUTTON_DISPLAY | BUTTON_LEFT)
201 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
202 #define JPEG_ZOOM_PRE BUTTON_RC_PLAY
203 #define JPEG_ZOOM_IN (BUTTON_RC_PLAY|BUTTON_REL)
204 #define JPEG_ZOOM_OUT (BUTTON_RC_PLAY|BUTTON_REPEAT)
205 #define JPEG_UP BUTTON_RC_VOL_UP
206 #define JPEG_DOWN BUTTON_RC_VOL_DOWN
207 #define JPEG_LEFT BUTTON_RC_REW
208 #define JPEG_RIGHT BUTTON_RC_FF
209 #define JPEG_MENU BUTTON_RC_REC
210 #define JPEG_NEXT BUTTON_RC_MODE
211 #define JPEG_PREVIOUS BUTTON_RC_MENU
213 #elif CONFIG_KEYPAD == COWOND2_PAD
214 #define JPEG_ZOOM_IN BUTTON_PLUS
215 #define JPEG_ZOOM_OUT BUTTON_MINUS
216 #define JPEG_UP BUTTON_UP
217 #define JPEG_DOWN BUTTON_DOWN
218 #define JPEG_LEFT BUTTON_LEFT
219 #define JPEG_RIGHT BUTTON_RIGHT
220 #define JPEG_MENU BUTTON_MENU
221 #define JPEG_NEXT (BUTTON_SELECT|BUTTON_PLUS)
222 #define JPEG_PREVIOUS (BUTTON_SELECT|BUTTON_MINUS)
224 #else
225 #error No keymap defined!
226 #endif
228 /* different graphics libraries */
229 #if LCD_DEPTH < 8
230 #define USEGSLIB
231 GREY_INFO_STRUCT
232 #define MYLCD(fn) grey_ub_ ## fn
233 #define MYLCD_UPDATE()
234 #define MYXLCD(fn) grey_ub_ ## fn
235 #else
236 #define MYLCD(fn) rb->lcd_ ## fn
237 #define MYLCD_UPDATE() rb->lcd_update();
238 #define MYXLCD(fn) xlcd_ ## fn
239 #endif
241 #define MAX_X_SIZE LCD_WIDTH*8
243 /* Min memory allowing us to use the plugin buffer
244 * and thus not stopping the music
245 * *Very* rough estimation:
246 * Max 10 000 dir entries * 4bytes/entry (char **) = 40000 bytes
247 * + 20k code size = 60 000
248 * + 50k min for jpeg = 120 000
250 #define MIN_MEM 120000
252 /* Headings */
253 #define DIR_PREV 1
254 #define DIR_NEXT -1
255 #define DIR_NONE 0
257 #define PLUGIN_OTHER 10 /* State code for output with return. */
259 /******************************* Globals ***********************************/
261 static struct plugin_api* rb;
262 MEM_FUNCTION_WRAPPERS(rb);
264 /* for portability of below JPEG code */
265 #define MEMSET(p,v,c) rb->memset(p,v,c)
266 #define MEMCPY(d,s,c) rb->memcpy(d,s,c)
267 #define INLINE static inline
268 #define ENDIAN_SWAP16(n) n /* only for poor little endian machines */
270 static int slideshow_enabled = false; /* run slideshow */
271 static int running_slideshow = false; /* loading image because of slideshw */
272 #ifndef SIMULATOR
273 static int immediate_ata_off = false; /* power down disk after loading */
274 #endif
276 /* Persistent configuration */
277 #define JPEG_CONFIGFILE "jpeg.cfg"
278 #define JPEG_SETTINGS_MINVERSION 1
279 #define JPEG_SETTINGS_VERSION 2
281 /* Slideshow times */
282 #define SS_MIN_TIMEOUT 1
283 #define SS_MAX_TIMEOUT 20
284 #define SS_DEFAULT_TIMEOUT 5
286 enum color_modes
288 COLOURMODE_COLOUR = 0,
289 COLOURMODE_GRAY,
290 COLOUR_NUM_MODES
293 enum dither_modes
295 DITHER_NONE = 0, /* No dithering */
296 DITHER_ORDERED, /* Bayer ordered */
297 DITHER_DIFFUSION, /* Floyd/Steinberg error diffusion */
298 DITHER_NUM_MODES
301 struct jpeg_settings
303 int colour_mode;
304 int dither_mode;
305 int ss_timeout;
308 static struct jpeg_settings jpeg_settings =
309 { COLOURMODE_COLOUR, DITHER_NONE, SS_DEFAULT_TIMEOUT };
310 static struct jpeg_settings old_settings;
312 static struct configdata jpeg_config[] =
314 #ifdef HAVE_LCD_COLOR
315 { TYPE_ENUM, 0, COLOUR_NUM_MODES, &jpeg_settings.colour_mode,
316 "Colour Mode", (char *[]){ "Colour", "Grayscale" }, NULL },
317 { TYPE_ENUM, 0, DITHER_NUM_MODES, &jpeg_settings.dither_mode,
318 "Dither Mode", (char *[]){ "None", "Ordered", "Diffusion" }, NULL },
319 #endif
320 { TYPE_INT, SS_MIN_TIMEOUT, SS_MAX_TIMEOUT, &jpeg_settings.ss_timeout,
321 "Slideshow Time", NULL, NULL},
324 #if LCD_DEPTH > 1
325 fb_data* old_backdrop;
326 #endif
328 /**************** begin JPEG code ********************/
330 INLINE unsigned range_limit(int value)
332 #if CONFIG_CPU == SH7034
333 unsigned tmp;
334 asm ( /* Note: Uses knowledge that only low byte of result is used */
335 "mov #-128,%[t] \n"
336 "sub %[t],%[v] \n" /* value -= -128; equals value += 128; */
337 "extu.b %[v],%[t] \n"
338 "cmp/eq %[v],%[t] \n" /* low byte == whole number ? */
339 "bt 1f \n" /* yes: no overflow */
340 "cmp/pz %[v] \n" /* overflow: positive? */
341 "subc %[v],%[v] \n" /* %[r] now either 0 or 0xffffffff */
342 "1: \n"
343 : /* outputs */
344 [v]"+r"(value),
345 [t]"=&r"(tmp)
347 return value;
348 #elif defined(CPU_COLDFIRE)
349 asm ( /* Note: Uses knowledge that only the low byte of the result is used */
350 "add.l #128,%[v] \n" /* value += 128; */
351 "cmp.l #255,%[v] \n" /* overflow? */
352 "bls.b 1f \n" /* no: return value */
353 "spl.b %[v] \n" /* yes: set low byte to appropriate boundary */
354 "1: \n"
355 : /* outputs */
356 [v]"+d"(value)
358 return value;
359 #elif defined(CPU_ARM)
360 asm ( /* Note: Uses knowledge that only the low byte of the result is used */
361 "add %[v], %[v], #128 \n" /* value += 128 */
362 "cmp %[v], #255 \n" /* out of range 0..255? */
363 "mvnhi %[v], %[v], asr #31 \n" /* yes: set all bits to ~(sign_bit) */
364 : /* outputs */
365 [v]"+r"(value)
367 return value;
368 #else
369 value += 128;
371 if ((unsigned)value <= 255)
372 return value;
374 if (value < 0)
375 return 0;
377 return 255;
378 #endif
381 /* IDCT implementation */
384 #define CONST_BITS 13
385 #define PASS1_BITS 2
388 /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
389 * causing a lot of useless floating-point operations at run time.
390 * To get around this we use the following pre-calculated constants.
391 * If you change CONST_BITS you may want to add appropriate values.
392 * (With a reasonable C compiler, you can just rely on the FIX() macro...)
394 #define FIX_0_298631336 2446 /* FIX(0.298631336) */
395 #define FIX_0_390180644 3196 /* FIX(0.390180644) */
396 #define FIX_0_541196100 4433 /* FIX(0.541196100) */
397 #define FIX_0_765366865 6270 /* FIX(0.765366865) */
398 #define FIX_0_899976223 7373 /* FIX(0.899976223) */
399 #define FIX_1_175875602 9633 /* FIX(1.175875602) */
400 #define FIX_1_501321110 12299 /* FIX(1.501321110) */
401 #define FIX_1_847759065 15137 /* FIX(1.847759065) */
402 #define FIX_1_961570560 16069 /* FIX(1.961570560) */
403 #define FIX_2_053119869 16819 /* FIX(2.053119869) */
404 #define FIX_2_562915447 20995 /* FIX(2.562915447) */
405 #define FIX_3_072711026 25172 /* FIX(3.072711026) */
409 /* Multiply an long variable by an long constant to yield an long result.
410 * For 8-bit samples with the recommended scaling, all the variable
411 * and constant values involved are no more than 16 bits wide, so a
412 * 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
413 * For 12-bit samples, a full 32-bit multiplication will be needed.
415 #define MULTIPLY16(var,const) (((short) (var)) * ((short) (const)))
418 /* Dequantize a coefficient by multiplying it by the multiplier-table
419 * entry; produce an int result. In this module, both inputs and result
420 * are 16 bits or less, so either int or short multiply will work.
422 /* #define DEQUANTIZE(coef,quantval) (((int) (coef)) * (quantval)) */
423 #define DEQUANTIZE MULTIPLY16
425 /* Descale and correctly round an int value that's scaled by N bits.
426 * We assume RIGHT_SHIFT rounds towards minus infinity, so adding
427 * the fudge factor is correct for either sign of X.
429 #define DESCALE(x,n) (((x) + (1l << ((n)-1))) >> (n))
434 * Perform dequantization and inverse DCT on one block of coefficients,
435 * producing a reduced-size 1x1 output block.
437 void idct1x1(unsigned char* p_byte, int* inptr, int* quantptr, int skip_line)
439 (void)skip_line; /* unused */
440 *p_byte = range_limit(inptr[0] * quantptr[0] >> 3);
446 * Perform dequantization and inverse DCT on one block of coefficients,
447 * producing a reduced-size 2x2 output block.
449 void idct2x2(unsigned char* p_byte, int* inptr, int* quantptr, int skip_line)
451 int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
452 unsigned char* outptr;
454 /* Pass 1: process columns from input, store into work array. */
456 /* Column 0 */
457 tmp4 = DEQUANTIZE(inptr[8*0], quantptr[8*0]);
458 tmp5 = DEQUANTIZE(inptr[8*1], quantptr[8*1]);
460 tmp0 = tmp4 + tmp5;
461 tmp2 = tmp4 - tmp5;
463 /* Column 1 */
464 tmp4 = DEQUANTIZE(inptr[8*0+1], quantptr[8*0+1]);
465 tmp5 = DEQUANTIZE(inptr[8*1+1], quantptr[8*1+1]);
467 tmp1 = tmp4 + tmp5;
468 tmp3 = tmp4 - tmp5;
470 /* Pass 2: process 2 rows, store into output array. */
472 /* Row 0 */
473 outptr = p_byte;
475 outptr[0] = range_limit((int) DESCALE(tmp0 + tmp1, 3));
476 outptr[1] = range_limit((int) DESCALE(tmp0 - tmp1, 3));
478 /* Row 1 */
479 outptr = p_byte + skip_line;
481 outptr[0] = range_limit((int) DESCALE(tmp2 + tmp3, 3));
482 outptr[1] = range_limit((int) DESCALE(tmp2 - tmp3, 3));
488 * Perform dequantization and inverse DCT on one block of coefficients,
489 * producing a reduced-size 4x4 output block.
491 void idct4x4(unsigned char* p_byte, int* inptr, int* quantptr, int skip_line)
493 int tmp0, tmp2, tmp10, tmp12;
494 int z1, z2, z3;
495 int * wsptr;
496 unsigned char* outptr;
497 int ctr;
498 int workspace[4*4]; /* buffers data between passes */
500 /* Pass 1: process columns from input, store into work array. */
502 wsptr = workspace;
503 for (ctr = 0; ctr < 4; ctr++, inptr++, quantptr++, wsptr++)
505 /* Even part */
507 tmp0 = DEQUANTIZE(inptr[8*0], quantptr[8*0]);
508 tmp2 = DEQUANTIZE(inptr[8*2], quantptr[8*2]);
510 tmp10 = (tmp0 + tmp2) << PASS1_BITS;
511 tmp12 = (tmp0 - tmp2) << PASS1_BITS;
513 /* Odd part */
514 /* Same rotation as in the even part of the 8x8 LL&M IDCT */
516 z2 = DEQUANTIZE(inptr[8*1], quantptr[8*1]);
517 z3 = DEQUANTIZE(inptr[8*3], quantptr[8*3]);
519 z1 = MULTIPLY16(z2 + z3, FIX_0_541196100);
520 tmp0 = DESCALE(z1 + MULTIPLY16(z3, - FIX_1_847759065), CONST_BITS-PASS1_BITS);
521 tmp2 = DESCALE(z1 + MULTIPLY16(z2, FIX_0_765366865), CONST_BITS-PASS1_BITS);
523 /* Final output stage */
525 wsptr[4*0] = (int) (tmp10 + tmp2);
526 wsptr[4*3] = (int) (tmp10 - tmp2);
527 wsptr[4*1] = (int) (tmp12 + tmp0);
528 wsptr[4*2] = (int) (tmp12 - tmp0);
531 /* Pass 2: process 4 rows from work array, store into output array. */
533 wsptr = workspace;
534 for (ctr = 0; ctr < 4; ctr++)
536 outptr = p_byte + (ctr*skip_line);
537 /* Even part */
539 tmp0 = (int) wsptr[0];
540 tmp2 = (int) wsptr[2];
542 tmp10 = (tmp0 + tmp2) << CONST_BITS;
543 tmp12 = (tmp0 - tmp2) << CONST_BITS;
545 /* Odd part */
546 /* Same rotation as in the even part of the 8x8 LL&M IDCT */
548 z2 = (int) wsptr[1];
549 z3 = (int) wsptr[3];
551 z1 = MULTIPLY16(z2 + z3, FIX_0_541196100);
552 tmp0 = z1 + MULTIPLY16(z3, - FIX_1_847759065);
553 tmp2 = z1 + MULTIPLY16(z2, FIX_0_765366865);
555 /* Final output stage */
557 outptr[0] = range_limit((int) DESCALE(tmp10 + tmp2,
558 CONST_BITS+PASS1_BITS+3));
559 outptr[3] = range_limit((int) DESCALE(tmp10 - tmp2,
560 CONST_BITS+PASS1_BITS+3));
561 outptr[1] = range_limit((int) DESCALE(tmp12 + tmp0,
562 CONST_BITS+PASS1_BITS+3));
563 outptr[2] = range_limit((int) DESCALE(tmp12 - tmp0,
564 CONST_BITS+PASS1_BITS+3));
566 wsptr += 4; /* advance pointer to next row */
573 * Perform dequantization and inverse DCT on one block of coefficients.
575 void idct8x8(unsigned char* p_byte, int* inptr, int* quantptr, int skip_line)
577 long tmp0, tmp1, tmp2, tmp3;
578 long tmp10, tmp11, tmp12, tmp13;
579 long z1, z2, z3, z4, z5;
580 int * wsptr;
581 unsigned char* outptr;
582 int ctr;
583 int workspace[64]; /* buffers data between passes */
585 /* Pass 1: process columns from input, store into work array. */
586 /* Note results are scaled up by sqrt(8) compared to a true IDCT; */
587 /* furthermore, we scale the results by 2**PASS1_BITS. */
589 wsptr = workspace;
590 for (ctr = 8; ctr > 0; ctr--)
592 /* Due to quantization, we will usually find that many of the input
593 * coefficients are zero, especially the AC terms. We can exploit this
594 * by short-circuiting the IDCT calculation for any column in which all
595 * the AC terms are zero. In that case each output is equal to the
596 * DC coefficient (with scale factor as needed).
597 * With typical images and quantization tables, half or more of the
598 * column DCT calculations can be simplified this way.
601 if ((inptr[8*1] | inptr[8*2] | inptr[8*3]
602 | inptr[8*4] | inptr[8*5] | inptr[8*6] | inptr[8*7]) == 0)
604 /* AC terms all zero */
605 int dcval = DEQUANTIZE(inptr[8*0], quantptr[8*0]) << PASS1_BITS;
607 wsptr[8*0] = wsptr[8*1] = wsptr[8*2] = wsptr[8*3] = wsptr[8*4]
608 = wsptr[8*5] = wsptr[8*6] = wsptr[8*7] = dcval;
609 inptr++; /* advance pointers to next column */
610 quantptr++;
611 wsptr++;
612 continue;
615 /* Even part: reverse the even part of the forward DCT. */
616 /* The rotator is sqrt(2)*c(-6). */
618 z2 = DEQUANTIZE(inptr[8*2], quantptr[8*2]);
619 z3 = DEQUANTIZE(inptr[8*6], quantptr[8*6]);
621 z1 = MULTIPLY16(z2 + z3, FIX_0_541196100);
622 tmp2 = z1 + MULTIPLY16(z3, - FIX_1_847759065);
623 tmp3 = z1 + MULTIPLY16(z2, FIX_0_765366865);
625 z2 = DEQUANTIZE(inptr[8*0], quantptr[8*0]);
626 z3 = DEQUANTIZE(inptr[8*4], quantptr[8*4]);
628 tmp0 = (z2 + z3) << CONST_BITS;
629 tmp1 = (z2 - z3) << CONST_BITS;
631 tmp10 = tmp0 + tmp3;
632 tmp13 = tmp0 - tmp3;
633 tmp11 = tmp1 + tmp2;
634 tmp12 = tmp1 - tmp2;
636 /* Odd part per figure 8; the matrix is unitary and hence its
637 transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */
639 tmp0 = DEQUANTIZE(inptr[8*7], quantptr[8*7]);
640 tmp1 = DEQUANTIZE(inptr[8*5], quantptr[8*5]);
641 tmp2 = DEQUANTIZE(inptr[8*3], quantptr[8*3]);
642 tmp3 = DEQUANTIZE(inptr[8*1], quantptr[8*1]);
644 z1 = tmp0 + tmp3;
645 z2 = tmp1 + tmp2;
646 z3 = tmp0 + tmp2;
647 z4 = tmp1 + tmp3;
648 z5 = MULTIPLY16(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
650 tmp0 = MULTIPLY16(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
651 tmp1 = MULTIPLY16(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
652 tmp2 = MULTIPLY16(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
653 tmp3 = MULTIPLY16(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
654 z1 = MULTIPLY16(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
655 z2 = MULTIPLY16(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
656 z3 = MULTIPLY16(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
657 z4 = MULTIPLY16(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
659 z3 += z5;
660 z4 += z5;
662 tmp0 += z1 + z3;
663 tmp1 += z2 + z4;
664 tmp2 += z2 + z3;
665 tmp3 += z1 + z4;
667 /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
669 wsptr[8*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
670 wsptr[8*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
671 wsptr[8*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
672 wsptr[8*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
673 wsptr[8*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
674 wsptr[8*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
675 wsptr[8*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
676 wsptr[8*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
678 inptr++; /* advance pointers to next column */
679 quantptr++;
680 wsptr++;
683 /* Pass 2: process rows from work array, store into output array. */
684 /* Note that we must descale the results by a factor of 8 == 2**3, */
685 /* and also undo the PASS1_BITS scaling. */
687 wsptr = workspace;
688 for (ctr = 0; ctr < 8; ctr++)
690 outptr = p_byte + (ctr*skip_line);
691 /* Rows of zeroes can be exploited in the same way as we did with columns.
692 * However, the column calculation has created many nonzero AC terms, so
693 * the simplification applies less often (typically 5% to 10% of the time).
694 * On machines with very fast multiplication, it's possible that the
695 * test takes more time than it's worth. In that case this section
696 * may be commented out.
699 #ifndef NO_ZERO_ROW_TEST
700 if ((wsptr[1] | wsptr[2] | wsptr[3]
701 | wsptr[4] | wsptr[5] | wsptr[6] | wsptr[7]) == 0)
703 /* AC terms all zero */
704 unsigned char dcval = range_limit((int) DESCALE((long) wsptr[0],
705 PASS1_BITS+3));
707 outptr[0] = dcval;
708 outptr[1] = dcval;
709 outptr[2] = dcval;
710 outptr[3] = dcval;
711 outptr[4] = dcval;
712 outptr[5] = dcval;
713 outptr[6] = dcval;
714 outptr[7] = dcval;
716 wsptr += 8; /* advance pointer to next row */
717 continue;
719 #endif
721 /* Even part: reverse the even part of the forward DCT. */
722 /* The rotator is sqrt(2)*c(-6). */
724 z2 = (long) wsptr[2];
725 z3 = (long) wsptr[6];
727 z1 = MULTIPLY16(z2 + z3, FIX_0_541196100);
728 tmp2 = z1 + MULTIPLY16(z3, - FIX_1_847759065);
729 tmp3 = z1 + MULTIPLY16(z2, FIX_0_765366865);
731 tmp0 = ((long) wsptr[0] + (long) wsptr[4]) << CONST_BITS;
732 tmp1 = ((long) wsptr[0] - (long) wsptr[4]) << CONST_BITS;
734 tmp10 = tmp0 + tmp3;
735 tmp13 = tmp0 - tmp3;
736 tmp11 = tmp1 + tmp2;
737 tmp12 = tmp1 - tmp2;
739 /* Odd part per figure 8; the matrix is unitary and hence its
740 * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */
742 tmp0 = (long) wsptr[7];
743 tmp1 = (long) wsptr[5];
744 tmp2 = (long) wsptr[3];
745 tmp3 = (long) wsptr[1];
747 z1 = tmp0 + tmp3;
748 z2 = tmp1 + tmp2;
749 z3 = tmp0 + tmp2;
750 z4 = tmp1 + tmp3;
751 z5 = MULTIPLY16(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
753 tmp0 = MULTIPLY16(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
754 tmp1 = MULTIPLY16(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
755 tmp2 = MULTIPLY16(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
756 tmp3 = MULTIPLY16(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
757 z1 = MULTIPLY16(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
758 z2 = MULTIPLY16(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
759 z3 = MULTIPLY16(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
760 z4 = MULTIPLY16(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
762 z3 += z5;
763 z4 += z5;
765 tmp0 += z1 + z3;
766 tmp1 += z2 + z4;
767 tmp2 += z2 + z3;
768 tmp3 += z1 + z4;
770 /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
772 outptr[0] = range_limit((int) DESCALE(tmp10 + tmp3,
773 CONST_BITS+PASS1_BITS+3));
774 outptr[7] = range_limit((int) DESCALE(tmp10 - tmp3,
775 CONST_BITS+PASS1_BITS+3));
776 outptr[1] = range_limit((int) DESCALE(tmp11 + tmp2,
777 CONST_BITS+PASS1_BITS+3));
778 outptr[6] = range_limit((int) DESCALE(tmp11 - tmp2,
779 CONST_BITS+PASS1_BITS+3));
780 outptr[2] = range_limit((int) DESCALE(tmp12 + tmp1,
781 CONST_BITS+PASS1_BITS+3));
782 outptr[5] = range_limit((int) DESCALE(tmp12 - tmp1,
783 CONST_BITS+PASS1_BITS+3));
784 outptr[3] = range_limit((int) DESCALE(tmp13 + tmp0,
785 CONST_BITS+PASS1_BITS+3));
786 outptr[4] = range_limit((int) DESCALE(tmp13 - tmp0,
787 CONST_BITS+PASS1_BITS+3));
789 wsptr += 8; /* advance pointer to next row */
795 /* JPEG decoder implementation */
798 #define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */
800 struct derived_tbl
802 /* Basic tables: (element [0] of each array is unused) */
803 long mincode[17]; /* smallest code of length k */
804 long maxcode[18]; /* largest code of length k (-1 if none) */
805 /* (maxcode[17] is a sentinel to ensure huff_DECODE terminates) */
806 int valptr[17]; /* huffval[] index of 1st symbol of length k */
808 /* Back link to public Huffman table (needed only in slow_DECODE) */
809 int* pub;
811 /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of
812 the input data stream. If the next Huffman code is no more
813 than HUFF_LOOKAHEAD bits long, we can obtain its length and
814 the corresponding symbol directly from these tables. */
815 int look_nbits[1<<HUFF_LOOKAHEAD]; /* # bits, or 0 if too long */
816 unsigned char look_sym[1<<HUFF_LOOKAHEAD]; /* symbol, or unused */
819 #define QUANT_TABLE_LENGTH 64
821 /* for type of Huffman table */
822 #define DC_LEN 28
823 #define AC_LEN 178
825 struct huffman_table
826 { /* length and code according to JFIF format */
827 int huffmancodes_dc[DC_LEN];
828 int huffmancodes_ac[AC_LEN];
831 struct frame_component
833 int ID;
834 int horizontal_sampling;
835 int vertical_sampling;
836 int quanttable_select;
839 struct scan_component
841 int ID;
842 int DC_select;
843 int AC_select;
846 struct bitstream
848 unsigned long get_buffer; /* current bit-extraction buffer */
849 int bits_left; /* # of unused bits in it */
850 unsigned char* next_input_byte;
851 unsigned char* input_end; /* upper limit +1 */
854 struct jpeg
856 int x_size, y_size; /* size of image (can be less than block boundary) */
857 int x_phys, y_phys; /* physical size, block aligned */
858 int x_mbl; /* x dimension of MBL */
859 int y_mbl; /* y dimension of MBL */
860 int blocks; /* blocks per MB */
861 int restart_interval; /* number of MCUs between RSTm markers */
862 int store_pos[4]; /* for Y block ordering */
864 unsigned char* p_entropy_data;
865 unsigned char* p_entropy_end;
867 int quanttable[4][QUANT_TABLE_LENGTH]; /* raw quantization tables 0-3 */
868 int qt_idct[2][QUANT_TABLE_LENGTH]; /* quantization tables for IDCT */
870 struct huffman_table hufftable[2]; /* Huffman tables */
871 struct derived_tbl dc_derived_tbls[2]; /* Huffman-LUTs */
872 struct derived_tbl ac_derived_tbls[2];
874 struct frame_component frameheader[3]; /* Component descriptor */
875 struct scan_component scanheader[3]; /* currently not used */
877 int mcu_membership[6]; /* info per block */
878 int tab_membership[6];
879 int subsample_x[3]; /* info per component */
880 int subsample_y[3];
884 /* possible return flags for process_markers() */
885 #define HUFFTAB 0x0001 /* with huffman table */
886 #define QUANTTAB 0x0002 /* with quantization table */
887 #define APP0_JFIF 0x0004 /* with APP0 segment following JFIF standard */
888 #define FILL_FF 0x0008 /* with 0xFF padding bytes at begin/end */
889 #define SOF0 0x0010 /* with SOF0-Segment */
890 #define DHT 0x0020 /* with Definition of huffman tables */
891 #define SOS 0x0040 /* with Start-of-Scan segment */
892 #define DQT 0x0080 /* with definition of quantization table */
894 /* Preprocess the JPEG JFIF file */
895 int process_markers(unsigned char* p_src, long size, struct jpeg* p_jpeg)
897 unsigned char* p_bytes = p_src;
898 int marker_size; /* variable length of marker segment */
899 int i, j, n;
900 int ret = 0; /* returned flags */
902 p_jpeg->p_entropy_end = p_src + size;
904 while (p_src < p_bytes + size)
906 if (*p_src++ != 0xFF) /* no marker? */
908 p_src--; /* it's image data, put it back */
909 p_jpeg->p_entropy_data = p_src;
910 break; /* exit marker processing */
913 switch (*p_src++)
915 case 0xFF: /* Fill byte */
916 ret |= FILL_FF;
917 case 0x00: /* Zero stuffed byte - entropy data */
918 p_src--; /* put it back */
919 continue;
921 case 0xC0: /* SOF Huff - Baseline DCT */
923 ret |= SOF0;
924 marker_size = *p_src++ << 8; /* Highbyte */
925 marker_size |= *p_src++; /* Lowbyte */
926 n = *p_src++; /* sample precision (= 8 or 12) */
927 if (n != 8)
929 return(-1); /* Unsupported sample precision */
931 p_jpeg->y_size = *p_src++ << 8; /* Highbyte */
932 p_jpeg->y_size |= *p_src++; /* Lowbyte */
933 p_jpeg->x_size = *p_src++ << 8; /* Highbyte */
934 p_jpeg->x_size |= *p_src++; /* Lowbyte */
936 n = (marker_size-2-6)/3;
937 if (*p_src++ != n || (n != 1 && n != 3))
939 return(-2); /* Unsupported SOF0 component specification */
941 for (i=0; i<n; i++)
943 p_jpeg->frameheader[i].ID = *p_src++; /* Component info */
944 p_jpeg->frameheader[i].horizontal_sampling = *p_src >> 4;
945 p_jpeg->frameheader[i].vertical_sampling = *p_src++ & 0x0F;
946 p_jpeg->frameheader[i].quanttable_select = *p_src++;
947 if (p_jpeg->frameheader[i].horizontal_sampling > 2
948 || p_jpeg->frameheader[i].vertical_sampling > 2)
949 return -3; /* Unsupported SOF0 subsampling */
951 p_jpeg->blocks = n;
953 break;
955 case 0xC1: /* SOF Huff - Extended sequential DCT*/
956 case 0xC2: /* SOF Huff - Progressive DCT*/
957 case 0xC3: /* SOF Huff - Spatial (sequential) lossless*/
958 case 0xC5: /* SOF Huff - Differential sequential DCT*/
959 case 0xC6: /* SOF Huff - Differential progressive DCT*/
960 case 0xC7: /* SOF Huff - Differential spatial*/
961 case 0xC8: /* SOF Arith - Reserved for JPEG extensions*/
962 case 0xC9: /* SOF Arith - Extended sequential DCT*/
963 case 0xCA: /* SOF Arith - Progressive DCT*/
964 case 0xCB: /* SOF Arith - Spatial (sequential) lossless*/
965 case 0xCD: /* SOF Arith - Differential sequential DCT*/
966 case 0xCE: /* SOF Arith - Differential progressive DCT*/
967 case 0xCF: /* SOF Arith - Differential spatial*/
969 return (-4); /* other DCT model than baseline not implemented */
972 case 0xC4: /* Define Huffman Table(s) */
974 unsigned char* p_temp;
976 ret |= DHT;
977 marker_size = *p_src++ << 8; /* Highbyte */
978 marker_size |= *p_src++; /* Lowbyte */
980 p_temp = p_src;
981 while (p_src < p_temp+marker_size-2-17) /* another table */
983 int sum = 0;
984 i = *p_src & 0x0F; /* table index */
985 if (i > 1)
987 return (-5); /* Huffman table index out of range */
989 else if (*p_src++ & 0xF0) /* AC table */
991 for (j=0; j<16; j++)
993 sum += *p_src;
994 p_jpeg->hufftable[i].huffmancodes_ac[j] = *p_src++;
996 if(16 + sum > AC_LEN)
997 return -10; /* longer than allowed */
999 for (; j < 16 + sum; j++)
1000 p_jpeg->hufftable[i].huffmancodes_ac[j] = *p_src++;
1002 else /* DC table */
1004 for (j=0; j<16; j++)
1006 sum += *p_src;
1007 p_jpeg->hufftable[i].huffmancodes_dc[j] = *p_src++;
1009 if(16 + sum > DC_LEN)
1010 return -11; /* longer than allowed */
1012 for (; j < 16 + sum; j++)
1013 p_jpeg->hufftable[i].huffmancodes_dc[j] = *p_src++;
1015 } /* while */
1016 p_src = p_temp+marker_size - 2; /* skip possible residue */
1018 break;
1020 case 0xCC: /* Define Arithmetic coding conditioning(s) */
1021 return(-6); /* Arithmetic coding not supported */
1023 case 0xD8: /* Start of Image */
1024 case 0xD9: /* End of Image */
1025 case 0x01: /* for temp private use arith code */
1026 break; /* skip parameterless marker */
1029 case 0xDA: /* Start of Scan */
1031 ret |= SOS;
1032 marker_size = *p_src++ << 8; /* Highbyte */
1033 marker_size |= *p_src++; /* Lowbyte */
1035 n = (marker_size-2-1-3)/2;
1036 if (*p_src++ != n || (n != 1 && n != 3))
1038 return (-7); /* Unsupported SOS component specification */
1040 for (i=0; i<n; i++)
1042 p_jpeg->scanheader[i].ID = *p_src++;
1043 p_jpeg->scanheader[i].DC_select = *p_src >> 4;
1044 p_jpeg->scanheader[i].AC_select = *p_src++ & 0x0F;
1046 p_src += 3; /* skip spectral information */
1048 break;
1050 case 0xDB: /* Define quantization Table(s) */
1052 ret |= DQT;
1053 marker_size = *p_src++ << 8; /* Highbyte */
1054 marker_size |= *p_src++; /* Lowbyte */
1055 n = (marker_size-2)/(QUANT_TABLE_LENGTH+1); /* # of tables */
1056 for (i=0; i<n; i++)
1058 int id = *p_src++; /* ID */
1059 if (id >= 4)
1061 return (-8); /* Unsupported quantization table */
1063 /* Read Quantisation table: */
1064 for (j=0; j<QUANT_TABLE_LENGTH; j++)
1065 p_jpeg->quanttable[id][j] = *p_src++;
1068 break;
1070 case 0xDD: /* Define Restart Interval */
1072 marker_size = *p_src++ << 8; /* Highbyte */
1073 marker_size |= *p_src++; /* Lowbyte */
1074 p_jpeg->restart_interval = *p_src++ << 8; /* Highbyte */
1075 p_jpeg->restart_interval |= *p_src++; /* Lowbyte */
1076 p_src += marker_size-4; /* skip segment */
1078 break;
1080 case 0xDC: /* Define Number of Lines */
1081 case 0xDE: /* Define Hierarchical progression */
1082 case 0xDF: /* Expand Reference Component(s) */
1083 case 0xE0: /* Application Field 0*/
1084 case 0xE1: /* Application Field 1*/
1085 case 0xE2: /* Application Field 2*/
1086 case 0xE3: /* Application Field 3*/
1087 case 0xE4: /* Application Field 4*/
1088 case 0xE5: /* Application Field 5*/
1089 case 0xE6: /* Application Field 6*/
1090 case 0xE7: /* Application Field 7*/
1091 case 0xE8: /* Application Field 8*/
1092 case 0xE9: /* Application Field 9*/
1093 case 0xEA: /* Application Field 10*/
1094 case 0xEB: /* Application Field 11*/
1095 case 0xEC: /* Application Field 12*/
1096 case 0xED: /* Application Field 13*/
1097 case 0xEE: /* Application Field 14*/
1098 case 0xEF: /* Application Field 15*/
1099 case 0xFE: /* Comment */
1101 marker_size = *p_src++ << 8; /* Highbyte */
1102 marker_size |= *p_src++; /* Lowbyte */
1103 p_src += marker_size-2; /* skip segment */
1105 break;
1107 case 0xF0: /* Reserved for JPEG extensions */
1108 case 0xF1: /* Reserved for JPEG extensions */
1109 case 0xF2: /* Reserved for JPEG extensions */
1110 case 0xF3: /* Reserved for JPEG extensions */
1111 case 0xF4: /* Reserved for JPEG extensions */
1112 case 0xF5: /* Reserved for JPEG extensions */
1113 case 0xF6: /* Reserved for JPEG extensions */
1114 case 0xF7: /* Reserved for JPEG extensions */
1115 case 0xF8: /* Reserved for JPEG extensions */
1116 case 0xF9: /* Reserved for JPEG extensions */
1117 case 0xFA: /* Reserved for JPEG extensions */
1118 case 0xFB: /* Reserved for JPEG extensions */
1119 case 0xFC: /* Reserved for JPEG extensions */
1120 case 0xFD: /* Reserved for JPEG extensions */
1121 case 0x02: /* Reserved */
1122 default:
1123 return (-9); /* Unknown marker */
1124 } /* switch */
1125 } /* while */
1127 return (ret); /* return flags with seen markers */
1131 void default_huff_tbl(struct jpeg* p_jpeg)
1133 static const struct huffman_table luma_table =
1136 0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,
1137 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B
1140 0x00,0x02,0x01,0x03,0x03,0x02,0x04,0x03,0x05,0x05,0x04,0x04,0x00,0x00,0x01,0x7D,
1141 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,
1142 0x22,0x71,0x14,0x32,0x81,0x91,0xA1,0x08,0x23,0x42,0xB1,0xC1,0x15,0x52,0xD1,0xF0,
1143 0x24,0x33,0x62,0x72,0x82,0x09,0x0A,0x16,0x17,0x18,0x19,0x1A,0x25,0x26,0x27,0x28,
1144 0x29,0x2A,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,
1145 0x4A,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,
1146 0x6A,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
1147 0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,
1148 0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xC2,0xC3,0xC4,0xC5,
1149 0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xE1,0xE2,
1150 0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,
1151 0xF9,0xFA
1155 static const struct huffman_table chroma_table =
1158 0x00,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,
1159 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B
1162 0x00,0x02,0x01,0x02,0x04,0x04,0x03,0x04,0x07,0x05,0x04,0x04,0x00,0x01,0x02,0x77,
1163 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,
1164 0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xA1,0xB1,0xC1,0x09,0x23,0x33,0x52,0xF0,
1165 0x15,0x62,0x72,0xD1,0x0A,0x16,0x24,0x34,0xE1,0x25,0xF1,0x17,0x18,0x19,0x1A,0x26,
1166 0x27,0x28,0x29,0x2A,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,
1167 0x49,0x4A,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,
1168 0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x82,0x83,0x84,0x85,0x86,0x87,
1169 0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5,
1170 0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xC2,0xC3,
1171 0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,
1172 0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,
1173 0xF9,0xFA
1177 MEMCPY(&p_jpeg->hufftable[0], &luma_table, sizeof(luma_table));
1178 MEMCPY(&p_jpeg->hufftable[1], &chroma_table, sizeof(chroma_table));
1180 return;
1183 /* Compute the derived values for a Huffman table */
1184 void fix_huff_tbl(int* htbl, struct derived_tbl* dtbl)
1186 int p, i, l, si;
1187 int lookbits, ctr;
1188 char huffsize[257];
1189 unsigned int huffcode[257];
1190 unsigned int code;
1192 dtbl->pub = htbl; /* fill in back link */
1194 /* Figure C.1: make table of Huffman code length for each symbol */
1195 /* Note that this is in code-length order. */
1197 p = 0;
1198 for (l = 1; l <= 16; l++)
1199 { /* all possible code length */
1200 for (i = 1; i <= (int) htbl[l-1]; i++) /* all codes per length */
1201 huffsize[p++] = (char) l;
1203 huffsize[p] = 0;
1205 /* Figure C.2: generate the codes themselves */
1206 /* Note that this is in code-length order. */
1208 code = 0;
1209 si = huffsize[0];
1210 p = 0;
1211 while (huffsize[p])
1213 while (((int) huffsize[p]) == si)
1215 huffcode[p++] = code;
1216 code++;
1218 code <<= 1;
1219 si++;
1222 /* Figure F.15: generate decoding tables for bit-sequential decoding */
1224 p = 0;
1225 for (l = 1; l <= 16; l++)
1227 if (htbl[l-1])
1229 dtbl->valptr[l] = p; /* huffval[] index of 1st symbol of code length l */
1230 dtbl->mincode[l] = huffcode[p]; /* minimum code of length l */
1231 p += htbl[l-1];
1232 dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */
1234 else
1236 dtbl->maxcode[l] = -1; /* -1 if no codes of this length */
1239 dtbl->maxcode[17] = 0xFFFFFL; /* ensures huff_DECODE terminates */
1241 /* Compute lookahead tables to speed up decoding.
1242 * First we set all the table entries to 0, indicating "too long";
1243 * then we iterate through the Huffman codes that are short enough and
1244 * fill in all the entries that correspond to bit sequences starting
1245 * with that code.
1248 MEMSET(dtbl->look_nbits, 0, sizeof(dtbl->look_nbits));
1250 p = 0;
1251 for (l = 1; l <= HUFF_LOOKAHEAD; l++)
1253 for (i = 1; i <= (int) htbl[l-1]; i++, p++)
1255 /* l = current code's length, p = its index in huffcode[] & huffval[]. */
1256 /* Generate left-justified code followed by all possible bit sequences */
1257 lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l);
1258 for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--)
1260 dtbl->look_nbits[lookbits] = l;
1261 dtbl->look_sym[lookbits] = htbl[16+p];
1262 lookbits++;
1269 /* zag[i] is the natural-order position of the i'th element of zigzag order.
1270 * If the incoming data is corrupted, decode_mcu could attempt to
1271 * reference values beyond the end of the array. To avoid a wild store,
1272 * we put some extra zeroes after the real entries.
1274 static const int zag[] =
1276 0, 1, 8, 16, 9, 2, 3, 10,
1277 17, 24, 32, 25, 18, 11, 4, 5,
1278 12, 19, 26, 33, 40, 48, 41, 34,
1279 27, 20, 13, 6, 7, 14, 21, 28,
1280 35, 42, 49, 56, 57, 50, 43, 36,
1281 29, 22, 15, 23, 30, 37, 44, 51,
1282 58, 59, 52, 45, 38, 31, 39, 46,
1283 53, 60, 61, 54, 47, 55, 62, 63,
1284 0, 0, 0, 0, 0, 0, 0, 0, /* extra entries in case k>63 below */
1285 0, 0, 0, 0, 0, 0, 0, 0
1288 void build_lut(struct jpeg* p_jpeg)
1290 int i;
1291 fix_huff_tbl(p_jpeg->hufftable[0].huffmancodes_dc,
1292 &p_jpeg->dc_derived_tbls[0]);
1293 fix_huff_tbl(p_jpeg->hufftable[0].huffmancodes_ac,
1294 &p_jpeg->ac_derived_tbls[0]);
1295 fix_huff_tbl(p_jpeg->hufftable[1].huffmancodes_dc,
1296 &p_jpeg->dc_derived_tbls[1]);
1297 fix_huff_tbl(p_jpeg->hufftable[1].huffmancodes_ac,
1298 &p_jpeg->ac_derived_tbls[1]);
1300 /* build the dequantization tables for the IDCT (De-ZiZagged) */
1301 for (i=0; i<64; i++)
1303 p_jpeg->qt_idct[0][zag[i]] = p_jpeg->quanttable[0][i];
1304 p_jpeg->qt_idct[1][zag[i]] = p_jpeg->quanttable[1][i];
1307 for (i=0; i<4; i++)
1308 p_jpeg->store_pos[i] = i; /* default ordering */
1310 /* assignments for the decoding of blocks */
1311 if (p_jpeg->frameheader[0].horizontal_sampling == 2
1312 && p_jpeg->frameheader[0].vertical_sampling == 1)
1313 { /* 4:2:2 */
1314 p_jpeg->blocks = 4;
1315 p_jpeg->x_mbl = (p_jpeg->x_size+15) / 16;
1316 p_jpeg->x_phys = p_jpeg->x_mbl * 16;
1317 p_jpeg->y_mbl = (p_jpeg->y_size+7) / 8;
1318 p_jpeg->y_phys = p_jpeg->y_mbl * 8;
1319 p_jpeg->mcu_membership[0] = 0; /* Y1=Y2=0, U=1, V=2 */
1320 p_jpeg->mcu_membership[1] = 0;
1321 p_jpeg->mcu_membership[2] = 1;
1322 p_jpeg->mcu_membership[3] = 2;
1323 p_jpeg->tab_membership[0] = 0; /* DC, DC, AC, AC */
1324 p_jpeg->tab_membership[1] = 0;
1325 p_jpeg->tab_membership[2] = 1;
1326 p_jpeg->tab_membership[3] = 1;
1327 p_jpeg->subsample_x[0] = 1;
1328 p_jpeg->subsample_x[1] = 2;
1329 p_jpeg->subsample_x[2] = 2;
1330 p_jpeg->subsample_y[0] = 1;
1331 p_jpeg->subsample_y[1] = 1;
1332 p_jpeg->subsample_y[2] = 1;
1334 if (p_jpeg->frameheader[0].horizontal_sampling == 1
1335 && p_jpeg->frameheader[0].vertical_sampling == 2)
1336 { /* 4:2:2 vertically subsampled */
1337 p_jpeg->store_pos[1] = 2; /* block positions are mirrored */
1338 p_jpeg->store_pos[2] = 1;
1339 p_jpeg->blocks = 4;
1340 p_jpeg->x_mbl = (p_jpeg->x_size+7) / 8;
1341 p_jpeg->x_phys = p_jpeg->x_mbl * 8;
1342 p_jpeg->y_mbl = (p_jpeg->y_size+15) / 16;
1343 p_jpeg->y_phys = p_jpeg->y_mbl * 16;
1344 p_jpeg->mcu_membership[0] = 0; /* Y1=Y2=0, U=1, V=2 */
1345 p_jpeg->mcu_membership[1] = 0;
1346 p_jpeg->mcu_membership[2] = 1;
1347 p_jpeg->mcu_membership[3] = 2;
1348 p_jpeg->tab_membership[0] = 0; /* DC, DC, AC, AC */
1349 p_jpeg->tab_membership[1] = 0;
1350 p_jpeg->tab_membership[2] = 1;
1351 p_jpeg->tab_membership[3] = 1;
1352 p_jpeg->subsample_x[0] = 1;
1353 p_jpeg->subsample_x[1] = 1;
1354 p_jpeg->subsample_x[2] = 1;
1355 p_jpeg->subsample_y[0] = 1;
1356 p_jpeg->subsample_y[1] = 2;
1357 p_jpeg->subsample_y[2] = 2;
1359 else if (p_jpeg->frameheader[0].horizontal_sampling == 2
1360 && p_jpeg->frameheader[0].vertical_sampling == 2)
1361 { /* 4:2:0 */
1362 p_jpeg->blocks = 6;
1363 p_jpeg->x_mbl = (p_jpeg->x_size+15) / 16;
1364 p_jpeg->x_phys = p_jpeg->x_mbl * 16;
1365 p_jpeg->y_mbl = (p_jpeg->y_size+15) / 16;
1366 p_jpeg->y_phys = p_jpeg->y_mbl * 16;
1367 p_jpeg->mcu_membership[0] = 0;
1368 p_jpeg->mcu_membership[1] = 0;
1369 p_jpeg->mcu_membership[2] = 0;
1370 p_jpeg->mcu_membership[3] = 0;
1371 p_jpeg->mcu_membership[4] = 1;
1372 p_jpeg->mcu_membership[5] = 2;
1373 p_jpeg->tab_membership[0] = 0;
1374 p_jpeg->tab_membership[1] = 0;
1375 p_jpeg->tab_membership[2] = 0;
1376 p_jpeg->tab_membership[3] = 0;
1377 p_jpeg->tab_membership[4] = 1;
1378 p_jpeg->tab_membership[5] = 1;
1379 p_jpeg->subsample_x[0] = 1;
1380 p_jpeg->subsample_x[1] = 2;
1381 p_jpeg->subsample_x[2] = 2;
1382 p_jpeg->subsample_y[0] = 1;
1383 p_jpeg->subsample_y[1] = 2;
1384 p_jpeg->subsample_y[2] = 2;
1386 else if (p_jpeg->frameheader[0].horizontal_sampling == 1
1387 && p_jpeg->frameheader[0].vertical_sampling == 1)
1388 { /* 4:4:4 */
1389 /* don't overwrite p_jpeg->blocks */
1390 p_jpeg->x_mbl = (p_jpeg->x_size+7) / 8;
1391 p_jpeg->x_phys = p_jpeg->x_mbl * 8;
1392 p_jpeg->y_mbl = (p_jpeg->y_size+7) / 8;
1393 p_jpeg->y_phys = p_jpeg->y_mbl * 8;
1394 p_jpeg->mcu_membership[0] = 0;
1395 p_jpeg->mcu_membership[1] = 1;
1396 p_jpeg->mcu_membership[2] = 2;
1397 p_jpeg->tab_membership[0] = 0;
1398 p_jpeg->tab_membership[1] = 1;
1399 p_jpeg->tab_membership[2] = 1;
1400 p_jpeg->subsample_x[0] = 1;
1401 p_jpeg->subsample_x[1] = 1;
1402 p_jpeg->subsample_x[2] = 1;
1403 p_jpeg->subsample_y[0] = 1;
1404 p_jpeg->subsample_y[1] = 1;
1405 p_jpeg->subsample_y[2] = 1;
1407 else
1409 /* error */
1416 * These functions/macros provide the in-line portion of bit fetching.
1417 * Use check_bit_buffer to ensure there are N bits in get_buffer
1418 * before using get_bits, peek_bits, or drop_bits.
1419 * check_bit_buffer(state,n,action);
1420 * Ensure there are N bits in get_buffer; if suspend, take action.
1421 * val = get_bits(n);
1422 * Fetch next N bits.
1423 * val = peek_bits(n);
1424 * Fetch next N bits without removing them from the buffer.
1425 * drop_bits(n);
1426 * Discard next N bits.
1427 * The value N should be a simple variable, not an expression, because it
1428 * is evaluated multiple times.
1431 INLINE void check_bit_buffer(struct bitstream* pb, int nbits)
1433 if (pb->bits_left < nbits)
1434 { /* nbits is <= 16, so I can always refill 2 bytes in this case */
1435 unsigned char byte;
1437 byte = *pb->next_input_byte++;
1438 if (byte == 0xFF) /* legal marker can be byte stuffing or RSTm */
1439 { /* simplification: just skip the (one-byte) marker code */
1440 pb->next_input_byte++;
1442 pb->get_buffer = (pb->get_buffer << 8) | byte;
1444 byte = *pb->next_input_byte++;
1445 if (byte == 0xFF) /* legal marker can be byte stuffing or RSTm */
1446 { /* simplification: just skip the (one-byte) marker code */
1447 pb->next_input_byte++;
1449 pb->get_buffer = (pb->get_buffer << 8) | byte;
1451 pb->bits_left += 16;
1455 INLINE int get_bits(struct bitstream* pb, int nbits)
1457 return ((int) (pb->get_buffer >> (pb->bits_left -= nbits))) & ((1<<nbits)-1);
1460 INLINE int peek_bits(struct bitstream* pb, int nbits)
1462 return ((int) (pb->get_buffer >> (pb->bits_left - nbits))) & ((1<<nbits)-1);
1465 INLINE void drop_bits(struct bitstream* pb, int nbits)
1467 pb->bits_left -= nbits;
1470 /* re-synchronize to entropy data (skip restart marker) */
1471 void search_restart(struct bitstream* pb)
1473 pb->next_input_byte--; /* we may have overread it, taking 2 bytes */
1474 /* search for a non-byte-padding marker, has to be RSTm or EOS */
1475 while (pb->next_input_byte < pb->input_end &&
1476 (pb->next_input_byte[-2] != 0xFF || pb->next_input_byte[-1] == 0x00))
1478 pb->next_input_byte++;
1480 pb->bits_left = 0;
1483 /* Figure F.12: extend sign bit. */
1484 #define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
1486 static const int extend_test[16] = /* entry n is 2**(n-1) */
1488 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
1489 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000
1492 static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
1494 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
1495 ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
1496 ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
1497 ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1
1500 /* Decode a single value */
1501 INLINE int huff_decode_dc(struct bitstream* bs, struct derived_tbl* tbl)
1503 int nb, look, s, r;
1505 check_bit_buffer(bs, HUFF_LOOKAHEAD);
1506 look = peek_bits(bs, HUFF_LOOKAHEAD);
1507 if ((nb = tbl->look_nbits[look]) != 0)
1509 drop_bits(bs, nb);
1510 s = tbl->look_sym[look];
1511 check_bit_buffer(bs, s);
1512 r = get_bits(bs, s);
1513 s = HUFF_EXTEND(r, s);
1515 else
1516 { /* slow_DECODE(s, HUFF_LOOKAHEAD+1)) < 0); */
1517 long code;
1518 nb=HUFF_LOOKAHEAD+1;
1519 check_bit_buffer(bs, nb);
1520 code = get_bits(bs, nb);
1521 while (code > tbl->maxcode[nb])
1523 code <<= 1;
1524 check_bit_buffer(bs, 1);
1525 code |= get_bits(bs, 1);
1526 nb++;
1528 if (nb > 16) /* error in Huffman */
1530 s=0; /* fake a zero, this is most safe */
1532 else
1534 s = tbl->pub[16 + tbl->valptr[nb] + ((int) (code - tbl->mincode[nb])) ];
1535 check_bit_buffer(bs, s);
1536 r = get_bits(bs, s);
1537 s = HUFF_EXTEND(r, s);
1539 } /* end slow decode */
1540 return s;
1543 INLINE int huff_decode_ac(struct bitstream* bs, struct derived_tbl* tbl)
1545 int nb, look, s;
1547 check_bit_buffer(bs, HUFF_LOOKAHEAD);
1548 look = peek_bits(bs, HUFF_LOOKAHEAD);
1549 if ((nb = tbl->look_nbits[look]) != 0)
1551 drop_bits(bs, nb);
1552 s = tbl->look_sym[look];
1554 else
1555 { /* slow_DECODE(s, HUFF_LOOKAHEAD+1)) < 0); */
1556 long code;
1557 nb=HUFF_LOOKAHEAD+1;
1558 check_bit_buffer(bs, nb);
1559 code = get_bits(bs, nb);
1560 while (code > tbl->maxcode[nb])
1562 code <<= 1;
1563 check_bit_buffer(bs, 1);
1564 code |= get_bits(bs, 1);
1565 nb++;
1567 if (nb > 16) /* error in Huffman */
1569 s=0; /* fake a zero, this is most safe */
1571 else
1573 s = tbl->pub[16 + tbl->valptr[nb] + ((int) (code - tbl->mincode[nb])) ];
1575 } /* end slow decode */
1576 return s;
1580 #ifdef HAVE_LCD_COLOR
1582 /* JPEG decoder variant for YUV decoding, into 3 different planes */
1583 /* Note: it keeps the original color subsampling, even if resized. */
1584 int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel[3],
1585 int downscale, void (*pf_progress)(int current, int total))
1587 struct bitstream bs; /* bitstream "object" */
1588 int block[64]; /* decoded DCT coefficients */
1590 int width, height;
1591 int skip_line[3]; /* bytes from one line to the next (skip_line) */
1592 int skip_strip[3], skip_mcu[3]; /* bytes to next DCT row / column */
1594 int i, x, y; /* loop counter */
1596 unsigned char* p_line[3] = {p_pixel[0], p_pixel[1], p_pixel[2]};
1597 unsigned char* p_byte[3]; /* bitmap pointer */
1599 void (*pf_idct)(unsigned char*, int*, int*, int); /* selected IDCT */
1600 int k_need; /* AC coefficients needed up to here */
1601 int zero_need; /* init the block with this many zeros */
1603 int last_dc_val[3] = {0, 0, 0}; /* or 128 for chroma? */
1604 int store_offs[4]; /* memory offsets: order of Y11 Y12 Y21 Y22 U V */
1605 int restart = p_jpeg->restart_interval; /* MCUs until restart marker */
1607 /* pick the IDCT we want, determine how to work with coefs */
1608 if (downscale == 1)
1610 pf_idct = idct8x8;
1611 k_need = 64; /* all */
1612 zero_need = 63; /* all */
1614 else if (downscale == 2)
1616 pf_idct = idct4x4;
1617 k_need = 25; /* this far in zig-zag to cover 4*4 */
1618 zero_need = 27; /* clear this far in linear order */
1620 else if (downscale == 4)
1622 pf_idct = idct2x2;
1623 k_need = 5; /* this far in zig-zag to cover 2*2 */
1624 zero_need = 9; /* clear this far in linear order */
1626 else if (downscale == 8)
1628 pf_idct = idct1x1;
1629 k_need = 0; /* no AC, not needed */
1630 zero_need = 0; /* no AC, not needed */
1632 else return -1; /* not supported */
1634 /* init bitstream, fake a restart to make it start */
1635 bs.next_input_byte = p_jpeg->p_entropy_data;
1636 bs.bits_left = 0;
1637 bs.input_end = p_jpeg->p_entropy_end;
1639 width = p_jpeg->x_phys / downscale;
1640 height = p_jpeg->y_phys / downscale;
1641 for (i=0; i<3; i++) /* calculate some strides */
1643 skip_line[i] = width / p_jpeg->subsample_x[i];
1644 skip_strip[i] = skip_line[i]
1645 * (height / p_jpeg->y_mbl) / p_jpeg->subsample_y[i];
1646 skip_mcu[i] = width/p_jpeg->x_mbl / p_jpeg->subsample_x[i];
1649 /* prepare offsets about where to store the different blocks */
1650 store_offs[p_jpeg->store_pos[0]] = 0;
1651 store_offs[p_jpeg->store_pos[1]] = 8 / downscale; /* to the right */
1652 store_offs[p_jpeg->store_pos[2]] = width * 8 / downscale; /* below */
1653 store_offs[p_jpeg->store_pos[3]] = store_offs[1] + store_offs[2]; /* r+b */
1655 for(y=0; y<p_jpeg->y_mbl && bs.next_input_byte <= bs.input_end; y++)
1657 for (i=0; i<3; i++) /* scan line init */
1659 p_byte[i] = p_line[i];
1660 p_line[i] += skip_strip[i];
1662 for (x=0; x<p_jpeg->x_mbl; x++)
1664 int blkn;
1666 /* Outer loop handles each block in the MCU */
1667 for (blkn = 0; blkn < p_jpeg->blocks; blkn++)
1668 { /* Decode a single block's worth of coefficients */
1669 int k = 1; /* coefficient index */
1670 int s, r; /* huffman values */
1671 int ci = p_jpeg->mcu_membership[blkn]; /* component index */
1672 int ti = p_jpeg->tab_membership[blkn]; /* table index */
1673 struct derived_tbl* dctbl = &p_jpeg->dc_derived_tbls[ti];
1674 struct derived_tbl* actbl = &p_jpeg->ac_derived_tbls[ti];
1676 /* Section F.2.2.1: decode the DC coefficient difference */
1677 s = huff_decode_dc(&bs, dctbl);
1679 last_dc_val[ci] += s;
1680 block[0] = last_dc_val[ci]; /* output it (assumes zag[0] = 0) */
1682 /* coefficient buffer must be cleared */
1683 MEMSET(block+1, 0, zero_need*sizeof(block[0]));
1685 /* Section F.2.2.2: decode the AC coefficients */
1686 for (; k < k_need; k++)
1688 s = huff_decode_ac(&bs, actbl);
1689 r = s >> 4;
1690 s &= 15;
1692 if (s)
1694 k += r;
1695 check_bit_buffer(&bs, s);
1696 r = get_bits(&bs, s);
1697 block[zag[k]] = HUFF_EXTEND(r, s);
1699 else
1701 if (r != 15)
1703 k = 64;
1704 break;
1706 k += r;
1708 } /* for k */
1709 /* In this path we just discard the values */
1710 for (; k < 64; k++)
1712 s = huff_decode_ac(&bs, actbl);
1713 r = s >> 4;
1714 s &= 15;
1716 if (s)
1718 k += r;
1719 check_bit_buffer(&bs, s);
1720 drop_bits(&bs, s);
1722 else
1724 if (r != 15)
1725 break;
1726 k += r;
1728 } /* for k */
1730 if (ci == 0)
1731 { /* Y component needs to bother about block store */
1732 pf_idct(p_byte[0]+store_offs[blkn], block,
1733 p_jpeg->qt_idct[ti], skip_line[0]);
1735 else
1736 { /* chroma */
1737 pf_idct(p_byte[ci], block, p_jpeg->qt_idct[ti],
1738 skip_line[ci]);
1740 } /* for blkn */
1741 p_byte[0] += skip_mcu[0]; /* unrolled for (i=0; i<3; i++) loop */
1742 p_byte[1] += skip_mcu[1];
1743 p_byte[2] += skip_mcu[2];
1744 if (p_jpeg->restart_interval && --restart == 0)
1745 { /* if a restart marker is due: */
1746 restart = p_jpeg->restart_interval; /* count again */
1747 search_restart(&bs); /* align the bitstream */
1748 last_dc_val[0] = last_dc_val[1] =
1749 last_dc_val[2] = 0; /* reset decoder */
1751 } /* for x */
1752 if (pf_progress != NULL)
1753 pf_progress(y, p_jpeg->y_mbl-1); /* notify about decoding progress */
1754 } /* for y */
1756 return 0; /* success */
1758 #else /* !HAVE_LCD_COLOR */
1760 /* a JPEG decoder specialized in decoding only the luminance (b&w) */
1761 int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel[1], int downscale,
1762 void (*pf_progress)(int current, int total))
1764 struct bitstream bs; /* bitstream "object" */
1765 int block[64]; /* decoded DCT coefficients */
1767 int width, height;
1768 int skip_line; /* bytes from one line to the next (skip_line) */
1769 int skip_strip, skip_mcu; /* bytes to next DCT row / column */
1771 int x, y; /* loop counter */
1773 unsigned char* p_line = p_pixel[0];
1774 unsigned char* p_byte; /* bitmap pointer */
1776 void (*pf_idct)(unsigned char*, int*, int*, int); /* selected IDCT */
1777 int k_need; /* AC coefficients needed up to here */
1778 int zero_need; /* init the block with this many zeros */
1780 int last_dc_val = 0;
1781 int store_offs[4]; /* memory offsets: order of Y11 Y12 Y21 Y22 U V */
1782 int restart = p_jpeg->restart_interval; /* MCUs until restart marker */
1784 /* pick the IDCT we want, determine how to work with coefs */
1785 if (downscale == 1)
1787 pf_idct = idct8x8;
1788 k_need = 64; /* all */
1789 zero_need = 63; /* all */
1791 else if (downscale == 2)
1793 pf_idct = idct4x4;
1794 k_need = 25; /* this far in zig-zag to cover 4*4 */
1795 zero_need = 27; /* clear this far in linear order */
1797 else if (downscale == 4)
1799 pf_idct = idct2x2;
1800 k_need = 5; /* this far in zig-zag to cover 2*2 */
1801 zero_need = 9; /* clear this far in linear order */
1803 else if (downscale == 8)
1805 pf_idct = idct1x1;
1806 k_need = 0; /* no AC, not needed */
1807 zero_need = 0; /* no AC, not needed */
1809 else return -1; /* not supported */
1811 /* init bitstream, fake a restart to make it start */
1812 bs.next_input_byte = p_jpeg->p_entropy_data;
1813 bs.bits_left = 0;
1814 bs.input_end = p_jpeg->p_entropy_end;
1816 width = p_jpeg->x_phys / downscale;
1817 height = p_jpeg->y_phys / downscale;
1818 skip_line = width;
1819 skip_strip = skip_line * (height / p_jpeg->y_mbl);
1820 skip_mcu = (width/p_jpeg->x_mbl);
1822 /* prepare offsets about where to store the different blocks */
1823 store_offs[p_jpeg->store_pos[0]] = 0;
1824 store_offs[p_jpeg->store_pos[1]] = 8 / downscale; /* to the right */
1825 store_offs[p_jpeg->store_pos[2]] = width * 8 / downscale; /* below */
1826 store_offs[p_jpeg->store_pos[3]] = store_offs[1] + store_offs[2]; /* r+b */
1828 for(y=0; y<p_jpeg->y_mbl && bs.next_input_byte <= bs.input_end; y++)
1830 p_byte = p_line;
1831 p_line += skip_strip;
1832 for (x=0; x<p_jpeg->x_mbl; x++)
1834 int blkn;
1836 /* Outer loop handles each block in the MCU */
1837 for (blkn = 0; blkn < p_jpeg->blocks; blkn++)
1838 { /* Decode a single block's worth of coefficients */
1839 int k = 1; /* coefficient index */
1840 int s, r; /* huffman values */
1841 int ci = p_jpeg->mcu_membership[blkn]; /* component index */
1842 int ti = p_jpeg->tab_membership[blkn]; /* table index */
1843 struct derived_tbl* dctbl = &p_jpeg->dc_derived_tbls[ti];
1844 struct derived_tbl* actbl = &p_jpeg->ac_derived_tbls[ti];
1846 /* Section F.2.2.1: decode the DC coefficient difference */
1847 s = huff_decode_dc(&bs, dctbl);
1849 if (ci == 0) /* only for Y component */
1851 last_dc_val += s;
1852 block[0] = last_dc_val; /* output it (assumes zag[0] = 0) */
1854 /* coefficient buffer must be cleared */
1855 MEMSET(block+1, 0, zero_need*sizeof(block[0]));
1857 /* Section F.2.2.2: decode the AC coefficients */
1858 for (; k < k_need; k++)
1860 s = huff_decode_ac(&bs, actbl);
1861 r = s >> 4;
1862 s &= 15;
1864 if (s)
1866 k += r;
1867 check_bit_buffer(&bs, s);
1868 r = get_bits(&bs, s);
1869 block[zag[k]] = HUFF_EXTEND(r, s);
1871 else
1873 if (r != 15)
1875 k = 64;
1876 break;
1878 k += r;
1880 } /* for k */
1882 /* In this path we just discard the values */
1883 for (; k < 64; k++)
1885 s = huff_decode_ac(&bs, actbl);
1886 r = s >> 4;
1887 s &= 15;
1889 if (s)
1891 k += r;
1892 check_bit_buffer(&bs, s);
1893 drop_bits(&bs, s);
1895 else
1897 if (r != 15)
1898 break;
1899 k += r;
1901 } /* for k */
1903 if (ci == 0)
1904 { /* only for Y component */
1905 pf_idct(p_byte+store_offs[blkn], block, p_jpeg->qt_idct[ti],
1906 skip_line);
1908 } /* for blkn */
1909 p_byte += skip_mcu;
1910 if (p_jpeg->restart_interval && --restart == 0)
1911 { /* if a restart marker is due: */
1912 restart = p_jpeg->restart_interval; /* count again */
1913 search_restart(&bs); /* align the bitstream */
1914 last_dc_val = 0; /* reset decoder */
1916 } /* for x */
1917 if (pf_progress != NULL)
1918 pf_progress(y, p_jpeg->y_mbl-1); /* notify about decoding progress */
1919 } /* for y */
1921 return 0; /* success */
1923 #endif /* !HAVE_LCD_COLOR */
1925 /**************** end JPEG code ********************/
1929 /**************** begin Application ********************/
1932 /************************* Types ***************************/
1934 struct t_disp
1936 #ifdef HAVE_LCD_COLOR
1937 unsigned char* bitmap[3]; /* Y, Cr, Cb */
1938 int csub_x, csub_y;
1939 #else
1940 unsigned char* bitmap[1]; /* Y only */
1941 #endif
1942 int width;
1943 int height;
1944 int stride;
1945 int x, y;
1948 /************************* Globals ***************************/
1950 /* decompressed image in the possible sizes (1,2,4,8), wasting the other */
1951 struct t_disp disp[9];
1953 /* my memory pool (from the mp3 buffer) */
1954 char print[32]; /* use a common snprintf() buffer */
1955 unsigned char* buf; /* up to here currently used by image(s) */
1957 /* the remaining free part of the buffer for compressed+uncompressed images */
1958 unsigned char* buf_images;
1960 ssize_t buf_size, buf_images_size;
1961 /* the root of the images, hereafter are decompresed ones */
1962 unsigned char* buf_root;
1963 int root_size;
1965 int ds, ds_min, ds_max; /* downscaling and limits */
1966 static struct jpeg jpg; /* too large for stack */
1968 static struct tree_context *tree;
1970 /* the current full file name */
1971 static char np_file[MAX_PATH];
1972 int curfile = 0, direction = DIR_NONE, entries = 0;
1974 /* list of the jpeg files */
1975 char **file_pt;
1976 /* are we using the plugin buffer or the audio buffer? */
1977 bool plug_buf = false;
1980 /************************* Implementation ***************************/
1982 #ifdef HAVE_LCD_COLOR
1984 * Conversion of full 0-255 range YCrCb to RGB:
1985 * |R| |1.000000 -0.000001 1.402000| |Y'|
1986 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
1987 * |B| |1.000000 1.772000 0.000000| |Pr|
1988 * Scaled (yields s15-bit output):
1989 * |R| |128 0 179| |Y |
1990 * |G| = |128 -43 -91| |Cb - 128|
1991 * |B| |128 227 0| |Cr - 128|
1993 #define YFAC 128
1994 #define RVFAC 179
1995 #define GUFAC (-43)
1996 #define GVFAC (-91)
1997 #define BUFAC 227
1998 #define YUV_WHITE (255*YFAC)
1999 #define NODITHER_DELTA (127*YFAC)
2000 #define COMPONENT_SHIFT 15
2001 #define MATRIX_SHIFT 7
2003 static inline int clamp_component(int x)
2005 if ((unsigned)x > YUV_WHITE)
2006 x = x < 0 ? 0 : YUV_WHITE;
2007 return x;
2010 static inline int clamp_component_bits(int x, int bits)
2012 if ((unsigned)x > (1u << bits) - 1)
2013 x = x < 0 ? 0 : (1 << bits) - 1;
2014 return x;
2017 static inline int component_to_lcd(int x, int bits, int delta)
2019 /* Formula used in core bitmap loader. */
2020 return (((1 << bits) - 1)*x + (x >> (8 - bits)) + delta) >> COMPONENT_SHIFT;
2023 static inline int lcd_to_component(int x, int bits, int delta)
2025 /* Reasonable, approximate reversal to get a full range back from the
2026 quantized value. */
2027 return YUV_WHITE*x / ((1 << bits) - 1);
2028 (void)delta;
2031 #define RED 0
2032 #define GRN 1
2033 #define BLU 2
2035 struct rgb_err
2037 int16_t errbuf[LCD_WIDTH+2]; /* Error record for line below */
2038 } rgb_err_buffers[3];
2040 fb_data rgb_linebuf[LCD_WIDTH]; /* Line buffer for scrolling when
2041 DITHER_DIFFUSION is set */
2043 struct rgb_pixel
2045 int r, g, b; /* Current pixel components in s16.0 */
2046 int inc; /* Current line increment (-1 or 1) */
2047 int row; /* Current row in source image */
2048 int col; /* Current column in source image */
2049 int ce[3]; /* Errors to apply to current pixel */
2050 struct rgb_err *e; /* RED, GRN, BLU */
2051 int epos; /* Current position in error record */
2054 struct rgb_pixel *pixel;
2056 /** round and truncate to lcd depth **/
2057 static fb_data pixel_to_lcd_colour(void)
2059 struct rgb_pixel *p = pixel;
2060 int r, g, b;
2062 r = component_to_lcd(p->r, LCD_RED_BITS, NODITHER_DELTA);
2063 r = clamp_component_bits(r, LCD_RED_BITS);
2065 g = component_to_lcd(p->g, LCD_GREEN_BITS, NODITHER_DELTA);
2066 g = clamp_component_bits(g, LCD_GREEN_BITS);
2068 b = component_to_lcd(p->b, LCD_BLUE_BITS, NODITHER_DELTA);
2069 b = clamp_component_bits(b, LCD_BLUE_BITS);
2071 return LCD_RGBPACK_LCD(r, g, b);
2074 /** write a monochrome pixel to the colour LCD **/
2075 static fb_data pixel_to_lcd_gray(void)
2077 int r, g, b;
2079 g = clamp_component(pixel->g);
2080 r = component_to_lcd(g, LCD_RED_BITS, NODITHER_DELTA);
2081 b = component_to_lcd(g, LCD_BLUE_BITS, NODITHER_DELTA);
2082 g = component_to_lcd(g, LCD_GREEN_BITS, NODITHER_DELTA);
2084 return LCD_RGBPACK_LCD(r, g, b);
2088 * Bayer ordered dithering - swiped from the core bitmap loader.
2090 static fb_data pixel_odither_to_lcd(void)
2092 /* canonical ordered dither matrix */
2093 static const unsigned char dither_matrix[16][16] = {
2094 { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 },
2095 { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 },
2096 { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 },
2097 { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 },
2098 { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 },
2099 { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 },
2100 { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 },
2101 { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 },
2102 { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 },
2103 { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 },
2104 { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 },
2105 { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 },
2106 { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 },
2107 { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 },
2108 { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 },
2109 { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 }
2112 struct rgb_pixel *p = pixel;
2113 int r, g, b, delta;
2115 delta = dither_matrix[p->col & 15][p->row & 15] << MATRIX_SHIFT;
2117 r = component_to_lcd(p->r, LCD_RED_BITS, delta);
2118 r = clamp_component_bits(r, LCD_RED_BITS);
2120 g = component_to_lcd(p->g, LCD_GREEN_BITS, delta);
2121 g = clamp_component_bits(g, LCD_GREEN_BITS);
2123 b = component_to_lcd(p->b, LCD_BLUE_BITS, delta);
2124 b = clamp_component_bits(b, LCD_BLUE_BITS);
2126 p->col += p->inc;
2128 return LCD_RGBPACK_LCD(r, g, b);
2132 * Floyd/Steinberg dither to lcd depth.
2134 * Apply filter to each component in serpentine pattern. Kernel shown for
2135 * L->R scan. Kernel is reversed for R->L.
2136 * * 7
2137 * 3 5 1 (1/16)
2139 static inline void distribute_error(int *ce, struct rgb_err *e,
2140 int err, int epos, int inc)
2142 *ce = (7*err >> 4) + e->errbuf[epos+inc];
2143 e->errbuf[epos+inc] = err >> 4;
2144 e->errbuf[epos] += 5*err >> 4;
2145 e->errbuf[epos-inc] += 3*err >> 4;
2148 static fb_data pixel_fsdither_to_lcd(void)
2150 struct rgb_pixel *p = pixel;
2151 int rc, gc, bc, r, g, b;
2152 int inc, epos;
2154 /* Full components with error terms */
2155 rc = p->r + p->ce[RED];
2156 r = component_to_lcd(rc, LCD_RED_BITS, 0);
2157 r = clamp_component_bits(r, LCD_RED_BITS);
2159 gc = p->g + p->ce[GRN];
2160 g = component_to_lcd(gc, LCD_GREEN_BITS, 0);
2161 g = clamp_component_bits(g, LCD_GREEN_BITS);
2163 bc = p->b + p->ce[BLU];
2164 b = component_to_lcd(bc, LCD_BLUE_BITS, 0);
2165 b = clamp_component_bits(b, LCD_BLUE_BITS);
2167 /* Get pixel errors */
2168 rc -= lcd_to_component(r, LCD_RED_BITS, 0);
2169 gc -= lcd_to_component(g, LCD_GREEN_BITS, 0);
2170 bc -= lcd_to_component(b, LCD_BLUE_BITS, 0);
2172 /* Spead error to surrounding pixels. */
2173 inc = p->inc;
2174 epos = p->epos;
2175 p->epos += inc;
2177 distribute_error(&p->ce[RED], &p->e[RED], rc, epos, inc);
2178 distribute_error(&p->ce[GRN], &p->e[GRN], gc, epos, inc);
2179 distribute_error(&p->ce[BLU], &p->e[BLU], bc, epos, inc);
2181 /* Pack and return pixel */
2182 return LCD_RGBPACK_LCD(r, g, b);
2185 /* Functions for each output mode, colour then grayscale. */
2186 static fb_data (* const pixel_funcs[COLOUR_NUM_MODES][DITHER_NUM_MODES])(void) =
2188 [COLOURMODE_COLOUR] =
2190 [DITHER_NONE] = pixel_to_lcd_colour,
2191 [DITHER_ORDERED] = pixel_odither_to_lcd,
2192 [DITHER_DIFFUSION] = pixel_fsdither_to_lcd,
2194 [COLOURMODE_GRAY] =
2196 [DITHER_NONE] = pixel_to_lcd_gray,
2197 [DITHER_ORDERED] = pixel_odither_to_lcd,
2198 [DITHER_DIFFUSION] = pixel_fsdither_to_lcd,
2203 * Draw a partial YUV colour bitmap
2205 * Runs serpentine pattern when dithering is DITHER_DIFFUSION, else scan is
2206 * always L->R.
2208 void yuv_bitmap_part(unsigned char *src[3], int csub_x, int csub_y,
2209 int src_x, int src_y, int stride,
2210 int x, int y, int width, int height)
2212 fb_data *dst, *dst_end;
2213 fb_data (*pixel_func)(void);
2214 struct rgb_pixel px;
2216 if (x + width > LCD_WIDTH)
2217 width = LCD_WIDTH - x; /* Clip right */
2218 if (x < 0)
2219 width += x, x = 0; /* Clip left */
2220 if (width <= 0)
2221 return; /* nothing left to do */
2223 if (y + height > LCD_HEIGHT)
2224 height = LCD_HEIGHT - y; /* Clip bottom */
2225 if (y < 0)
2226 height += y, y = 0; /* Clip top */
2227 if (height <= 0)
2228 return; /* nothing left to do */
2230 pixel = &px;
2232 dst = rb->lcd_framebuffer + LCD_WIDTH * y + x;
2233 dst_end = dst + LCD_WIDTH * height;
2235 if (jpeg_settings.colour_mode == COLOURMODE_GRAY)
2236 csub_y = 0; /* Ignore Cb, Cr */
2238 pixel_func = pixel_funcs[jpeg_settings.colour_mode]
2239 [jpeg_settings.dither_mode];
2241 if (jpeg_settings.dither_mode == DITHER_DIFFUSION)
2243 /* Reset error terms. */
2244 px.e = rgb_err_buffers;
2245 px.ce[RED] = px.ce[GRN] = px.ce[BLU] = 0;
2246 rb->memset(px.e, 0, 3*sizeof (struct rgb_err));
2251 fb_data *dst_row, *row_end;
2252 const unsigned char *ysrc;
2253 px.inc = 1;
2255 if (jpeg_settings.dither_mode == DITHER_DIFFUSION)
2257 /* Use R->L scan on odd lines */
2258 px.inc -= (src_y & 1) << 1;
2259 px.epos = x + 1;
2261 if (px.inc < 0)
2262 px.epos += width - 1;
2265 if (px.inc == 1)
2267 /* Scan is L->R */
2268 dst_row = dst;
2269 row_end = dst_row + width;
2270 px.col = src_x;
2272 else
2274 /* Scan is R->L */
2275 row_end = dst - 1;
2276 dst_row = row_end + width;
2277 px.col = src_x + width - 1;
2280 ysrc = src[0] + stride * src_y + px.col;
2281 px.row = src_y;
2283 /* Do one row of pixels */
2284 if (csub_y) /* colour */
2286 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
2287 const unsigned char *usrc, *vsrc;
2289 usrc = src[1] + (stride/csub_x) * (src_y/csub_y)
2290 + (px.col/csub_x);
2291 vsrc = src[2] + (stride/csub_x) * (src_y/csub_y)
2292 + (px.col/csub_x);
2293 int xphase = px.col % csub_x;
2294 int xphase_reset = px.inc * csub_x;
2295 int y, v, u, rv, guv, bu;
2297 v = *vsrc - 128;
2298 vsrc += px.inc;
2299 u = *usrc - 128;
2300 usrc += px.inc;
2301 rv = RVFAC*v;
2302 guv = GUFAC*u + GVFAC*v;
2303 bu = BUFAC*u;
2305 while (1)
2307 y = YFAC*(*ysrc);
2308 ysrc += px.inc;
2309 px.r = y + rv;
2310 px.g = y + guv;
2311 px.b = y + bu;
2313 *dst_row = pixel_func();
2314 dst_row += px.inc;
2316 if (dst_row == row_end)
2317 break;
2319 xphase += px.inc;
2320 if ((unsigned)xphase < (unsigned)csub_x)
2321 continue;
2323 /* fetch new chromas */
2324 v = *vsrc - 128;
2325 vsrc += px.inc;
2326 u = *usrc - 128;
2327 usrc += px.inc;
2328 rv = RVFAC*v;
2329 guv = GUFAC*u + GVFAC*v;
2330 bu = BUFAC*u;
2332 xphase -= xphase_reset;
2335 else /* monochrome */
2339 /* Set all components the same for dithering purposes */
2340 px.g = px.r = px.b = YFAC*(*ysrc);
2341 *dst_row = pixel_func();
2342 ysrc += px.inc;
2343 dst_row += px.inc;
2345 while (dst_row != row_end);
2348 src_y++;
2349 dst += LCD_WIDTH;
2351 while (dst < dst_end);
2354 #endif /* HAVE_LCD_COLOR */
2357 /* support function for qsort() */
2358 static int compare(const void* p1, const void* p2)
2360 return rb->strcasecmp(*((char **)p1), *((char **)p2));
2363 bool jpg_ext(const char ext[])
2365 if(!ext)
2366 return false;
2367 if(!rb->strcasecmp(ext,".jpg") ||
2368 !rb->strcasecmp(ext,".jpe") ||
2369 !rb->strcasecmp(ext,".jpeg"))
2370 return true;
2371 else
2372 return false;
2375 /*Read directory contents for scrolling. */
2376 void get_pic_list(void)
2378 int i;
2379 long int str_len = 0;
2380 char *pname;
2381 tree = rb->tree_get_context();
2383 #if PLUGIN_BUFFER_SIZE >= MIN_MEM
2384 file_pt = rb->plugin_get_buffer((size_t *)&buf_size);
2385 #else
2386 file_pt = rb->plugin_get_audio_buffer((size_t *)&buf_size);
2387 #endif
2389 for(i = 0; i < tree->filesindir; i++)
2391 if(jpg_ext(rb->strrchr(&tree->name_buffer[str_len],'.')))
2392 file_pt[entries++] = &tree->name_buffer[str_len];
2394 str_len += rb->strlen(&tree->name_buffer[str_len]) + 1;
2397 rb->qsort(file_pt, entries, sizeof(char**), compare);
2399 /* Remove path and leave only the name.*/
2400 pname = rb->strrchr(np_file,'/');
2401 pname++;
2403 /* Find Selected File. */
2404 for(i = 0; i < entries; i++)
2405 if(!rb->strcmp(file_pt[i], pname))
2406 curfile = i;
2409 int change_filename(int direct)
2411 int count = 0;
2412 direction = direct;
2414 if(direct == DIR_PREV)
2418 count++;
2419 if(curfile == 0)
2420 curfile = entries - 1;
2421 else
2422 curfile--;
2423 }while(file_pt[curfile] == '\0' && count < entries);
2424 /* we "erase" the file name if we encounter
2425 * a non-supported file, so skip it now */
2427 else /* DIR_NEXT/DIR_NONE */
2431 count++;
2432 if(curfile == entries - 1)
2433 curfile = 0;
2434 else
2435 curfile++;
2436 }while(file_pt[curfile] == '\0' && count < entries);
2439 if(count == entries && file_pt[curfile] == '\0')
2441 rb->splash(HZ, "No supported files");
2442 return PLUGIN_ERROR;
2444 if(rb->strlen(tree->currdir) > 1)
2446 rb->strcpy(np_file, tree->currdir);
2447 rb->strcat(np_file, "/");
2449 else
2450 rb->strcpy(np_file, tree->currdir);
2452 rb->strcat(np_file, file_pt[curfile]);
2454 return PLUGIN_OTHER;
2457 /* switch off overlay, for handling SYS_ events */
2458 void cleanup(void *parameter)
2460 (void)parameter;
2461 #ifdef USEGSLIB
2462 grey_show(false);
2463 #endif
2466 #define VSCROLL (LCD_HEIGHT/8)
2467 #define HSCROLL (LCD_WIDTH/10)
2469 #define ZOOM_IN 100 /* return codes for below function */
2470 #define ZOOM_OUT 101
2472 #ifdef HAVE_LCD_COLOR
2473 bool set_option_grayscale(void)
2475 bool gray = jpeg_settings.colour_mode == COLOURMODE_GRAY;
2476 rb->set_bool("Grayscale", &gray);
2477 jpeg_settings.colour_mode = gray ? COLOURMODE_GRAY : COLOURMODE_COLOUR;
2478 return false;
2481 bool set_option_dithering(void)
2483 static const struct opt_items dithering[DITHER_NUM_MODES] = {
2484 [DITHER_NONE] = { "Off", -1 },
2485 [DITHER_ORDERED] = { "Ordered", -1 },
2486 [DITHER_DIFFUSION] = { "Diffusion", -1 },
2489 rb->set_option("Dithering", &jpeg_settings.dither_mode, INT,
2490 dithering, DITHER_NUM_MODES, NULL);
2491 return false;
2494 static void display_options(void)
2496 static const struct menu_item items[] = {
2497 { "Grayscale", set_option_grayscale },
2498 { "Dithering", set_option_dithering },
2501 int m = menu_init(rb, items, ARRAYLEN(items),
2502 NULL, NULL, NULL, NULL);
2503 menu_run(m);
2504 menu_exit(m);
2506 #endif /* HAVE_LCD_COLOR */
2508 int show_menu(void) /* return 1 to quit */
2510 #if LCD_DEPTH > 1
2511 rb->lcd_set_backdrop(old_backdrop);
2512 #ifdef HAVE_LCD_COLOR
2513 rb->lcd_set_foreground(rb->global_settings->fg_color);
2514 rb->lcd_set_background(rb->global_settings->bg_color);
2515 #else
2516 rb->lcd_set_foreground(LCD_BLACK);
2517 rb->lcd_set_background(LCD_WHITE);
2518 #endif
2519 #endif
2520 int m;
2521 int result;
2523 enum menu_id
2525 MIID_QUIT = 0,
2526 MIID_TOGGLE_SS_MODE,
2527 MIID_CHANGE_SS_MODE,
2528 #if PLUGIN_BUFFER_SIZE >= MIN_MEM
2529 MIID_SHOW_PLAYBACK_MENU,
2530 #endif
2531 #ifdef HAVE_LCD_COLOR
2532 MIID_DISPLAY_OPTIONS,
2533 #endif
2534 MIID_RETURN,
2537 static const struct menu_item items[] = {
2538 [MIID_QUIT] =
2539 { "Quit", NULL },
2540 [MIID_TOGGLE_SS_MODE] =
2541 { "Toggle Slideshow Mode", NULL },
2542 [MIID_CHANGE_SS_MODE] =
2543 { "Change Slideshow Time", NULL },
2544 #if PLUGIN_BUFFER_SIZE >= MIN_MEM
2545 [MIID_SHOW_PLAYBACK_MENU] =
2546 { "Show Playback Menu", NULL },
2547 #endif
2548 #ifdef HAVE_LCD_COLOR
2549 [MIID_DISPLAY_OPTIONS] =
2550 { "Display Options", NULL },
2551 #endif
2552 [MIID_RETURN] =
2553 { "Return", NULL },
2556 static const struct opt_items slideshow[2] = {
2557 { "Disable", -1 },
2558 { "Enable", -1 },
2561 m = menu_init(rb, items, sizeof(items) / sizeof(*items),
2562 NULL, NULL, NULL, NULL);
2563 result=menu_show(m);
2565 switch (result)
2567 case MIID_QUIT:
2568 menu_exit(m);
2569 return 1;
2570 break;
2571 case MIID_TOGGLE_SS_MODE:
2572 rb->set_option("Toggle Slideshow", &slideshow_enabled, INT,
2573 slideshow , 2, NULL);
2574 break;
2575 case MIID_CHANGE_SS_MODE:
2576 rb->set_int("Slideshow Time", "s", UNIT_SEC,
2577 &jpeg_settings.ss_timeout, NULL, 1,
2578 SS_MIN_TIMEOUT, SS_MAX_TIMEOUT, NULL);
2579 break;
2581 #if PLUGIN_BUFFER_SIZE >= MIN_MEM
2582 case MIID_SHOW_PLAYBACK_MENU:
2583 playback_control(rb);
2584 break;
2585 #endif
2586 #ifdef HAVE_LCD_COLOR
2587 case MIID_DISPLAY_OPTIONS:
2588 display_options();
2589 break;
2590 #endif
2591 case MIID_RETURN:
2592 break;
2595 #if !defined(SIMULATOR) && !defined(HAVE_FLASH_STORAGE)
2596 /* change ata spindown time based on slideshow time setting */
2597 immediate_ata_off = false;
2598 rb->ata_spindown(rb->global_settings->disk_spindown);
2600 if (slideshow_enabled)
2602 if(jpeg_settings.ss_timeout < 10)
2604 /* slideshow times < 10s keep disk spinning */
2605 rb->ata_spindown(0);
2607 else if (!rb->mp3_is_playing())
2609 /* slideshow times > 10s and not playing: ata_off after load */
2610 immediate_ata_off = true;
2613 #endif
2614 #if LCD_DEPTH > 1
2615 rb->lcd_set_backdrop(NULL);
2616 rb->lcd_set_foreground(LCD_WHITE);
2617 rb->lcd_set_background(LCD_BLACK);
2618 #endif
2619 rb->lcd_clear_display();
2620 menu_exit(m);
2621 return 0;
2623 /* interactively scroll around the image */
2624 int scroll_bmp(struct t_disp* pdisp)
2626 int lastbutton = 0;
2628 while (true)
2630 int button;
2631 int move;
2633 if (slideshow_enabled)
2634 button = rb->button_get_w_tmo(jpeg_settings.ss_timeout * HZ);
2635 else button = rb->button_get(true);
2637 running_slideshow = false;
2639 switch(button)
2641 case JPEG_LEFT:
2642 if (!(ds < ds_max) && entries > 0 && jpg.x_size <= MAX_X_SIZE)
2643 return change_filename(DIR_PREV);
2644 case JPEG_LEFT | BUTTON_REPEAT:
2645 move = MIN(HSCROLL, pdisp->x);
2646 if (move > 0)
2648 MYXLCD(scroll_right)(move); /* scroll right */
2649 pdisp->x -= move;
2650 #ifdef HAVE_LCD_COLOR
2651 yuv_bitmap_part(
2652 pdisp->bitmap, pdisp->csub_x, pdisp->csub_y,
2653 pdisp->x, pdisp->y, pdisp->stride,
2654 0, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */
2655 move, MIN(LCD_HEIGHT, pdisp->height)); /* w, h */
2656 #else
2657 MYXLCD(gray_bitmap_part)(
2658 pdisp->bitmap[0], pdisp->x, pdisp->y, pdisp->stride,
2659 0, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */
2660 move, MIN(LCD_HEIGHT, pdisp->height)); /* w, h */
2661 #endif
2662 MYLCD_UPDATE();
2664 break;
2666 case JPEG_RIGHT:
2667 if (!(ds < ds_max) && entries > 0 && jpg.x_size <= MAX_X_SIZE)
2668 return change_filename(DIR_NEXT);
2669 case JPEG_RIGHT | BUTTON_REPEAT:
2670 move = MIN(HSCROLL, pdisp->width - pdisp->x - LCD_WIDTH);
2671 if (move > 0)
2673 MYXLCD(scroll_left)(move); /* scroll left */
2674 pdisp->x += move;
2675 #ifdef HAVE_LCD_COLOR
2676 yuv_bitmap_part(
2677 pdisp->bitmap, pdisp->csub_x, pdisp->csub_y,
2678 pdisp->x + LCD_WIDTH - move, pdisp->y, pdisp->stride,
2679 LCD_WIDTH - move, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */
2680 move, MIN(LCD_HEIGHT, pdisp->height)); /* w, h */
2681 #else
2682 MYXLCD(gray_bitmap_part)(
2683 pdisp->bitmap[0], pdisp->x + LCD_WIDTH - move,
2684 pdisp->y, pdisp->stride,
2685 LCD_WIDTH - move, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */
2686 move, MIN(LCD_HEIGHT, pdisp->height)); /* w, h */
2687 #endif
2688 MYLCD_UPDATE();
2690 break;
2692 case JPEG_UP:
2693 case JPEG_UP | BUTTON_REPEAT:
2694 move = MIN(VSCROLL, pdisp->y);
2695 if (move > 0)
2697 MYXLCD(scroll_down)(move); /* scroll down */
2698 pdisp->y -= move;
2699 #ifdef HAVE_LCD_COLOR
2700 if (jpeg_settings.dither_mode == DITHER_DIFFUSION)
2702 /* Draw over the band at the top of the last update
2703 caused by lack of error history on line zero. */
2704 move = MIN(move + 1, pdisp->y + pdisp->height);
2707 yuv_bitmap_part(
2708 pdisp->bitmap, pdisp->csub_x, pdisp->csub_y,
2709 pdisp->x, pdisp->y, pdisp->stride,
2710 MAX(0, (LCD_WIDTH-pdisp->width)/2), 0, /* x, y */
2711 MIN(LCD_WIDTH, pdisp->width), move); /* w, h */
2712 #else
2713 MYXLCD(gray_bitmap_part)(
2714 pdisp->bitmap[0], pdisp->x, pdisp->y, pdisp->stride,
2715 MAX(0, (LCD_WIDTH-pdisp->width)/2), 0, /* x, y */
2716 MIN(LCD_WIDTH, pdisp->width), move); /* w, h */
2717 #endif
2718 MYLCD_UPDATE();
2720 break;
2722 case JPEG_DOWN:
2723 case JPEG_DOWN | BUTTON_REPEAT:
2724 move = MIN(VSCROLL, pdisp->height - pdisp->y - LCD_HEIGHT);
2725 if (move > 0)
2727 MYXLCD(scroll_up)(move); /* scroll up */
2728 pdisp->y += move;
2729 #ifdef HAVE_LCD_COLOR
2730 if (jpeg_settings.dither_mode == DITHER_DIFFUSION)
2732 /* Save the line that was on the last line of the display
2733 and draw one extra line above then recover the line with
2734 image data that had an error history when it was drawn.
2736 move++, pdisp->y--;
2737 MEMCPY(rgb_linebuf,
2738 rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH,
2739 LCD_WIDTH*sizeof (fb_data));
2742 yuv_bitmap_part(
2743 pdisp->bitmap, pdisp->csub_x, pdisp->csub_y, pdisp->x,
2744 pdisp->y + LCD_HEIGHT - move, pdisp->stride,
2745 MAX(0, (LCD_WIDTH-pdisp->width)/2), LCD_HEIGHT - move, /* x, y */
2746 MIN(LCD_WIDTH, pdisp->width), move); /* w, h */
2748 if (jpeg_settings.dither_mode == DITHER_DIFFUSION)
2750 /* Cover the first row drawn with previous image data. */
2751 MEMCPY(rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH,
2752 rgb_linebuf,
2753 LCD_WIDTH*sizeof (fb_data));
2754 pdisp->y++;
2756 #else
2757 MYXLCD(gray_bitmap_part)(
2758 pdisp->bitmap[0], pdisp->x,
2759 pdisp->y + LCD_HEIGHT - move, pdisp->stride,
2760 MAX(0, (LCD_WIDTH-pdisp->width)/2), LCD_HEIGHT - move, /* x, y */
2761 MIN(LCD_WIDTH, pdisp->width), move); /* w, h */
2762 #endif
2763 MYLCD_UPDATE();
2765 break;
2766 case BUTTON_NONE:
2767 if (!slideshow_enabled)
2768 break;
2769 running_slideshow = true;
2770 if (entries > 0)
2771 return change_filename(DIR_NEXT);
2772 break;
2774 #ifdef JPEG_SLIDE_SHOW
2775 case JPEG_SLIDE_SHOW:
2776 slideshow_enabled = !slideshow_enabled;
2777 running_slideshow = slideshow_enabled;
2778 break;
2779 #endif
2781 #ifdef JPEG_NEXT_REPEAT
2782 case JPEG_NEXT_REPEAT:
2783 #endif
2784 case JPEG_NEXT:
2785 if (entries > 0)
2786 return change_filename(DIR_NEXT);
2787 break;
2789 #ifdef JPEG_PREVIOUS_REPEAT
2790 case JPEG_PREVIOUS_REPEAT:
2791 #endif
2792 case JPEG_PREVIOUS:
2793 if (entries > 0)
2794 return change_filename(DIR_PREV);
2795 break;
2797 case JPEG_ZOOM_IN:
2798 #ifdef JPEG_ZOOM_PRE
2799 if (lastbutton != JPEG_ZOOM_PRE)
2800 break;
2801 #endif
2802 return ZOOM_IN;
2803 break;
2805 case JPEG_ZOOM_OUT:
2806 #ifdef JPEG_ZOOM_PRE
2807 if (lastbutton != JPEG_ZOOM_PRE)
2808 break;
2809 #endif
2810 return ZOOM_OUT;
2811 break;
2812 #ifdef JPEG_RC_MENU
2813 case JPEG_RC_MENU:
2814 #endif
2815 case JPEG_MENU:
2816 #ifdef USEGSLIB
2817 grey_show(false); /* switch off greyscale overlay */
2818 #endif
2819 if (show_menu() == 1)
2820 return PLUGIN_OK;
2822 #ifdef USEGSLIB
2823 grey_show(true); /* switch on greyscale overlay */
2824 #else
2825 yuv_bitmap_part(
2826 pdisp->bitmap, pdisp->csub_x, pdisp->csub_y,
2827 pdisp->x, pdisp->y, pdisp->stride,
2828 MAX(0, (LCD_WIDTH - pdisp->width) / 2),
2829 MAX(0, (LCD_HEIGHT - pdisp->height) / 2),
2830 MIN(LCD_WIDTH, pdisp->width),
2831 MIN(LCD_HEIGHT, pdisp->height));
2832 MYLCD_UPDATE();
2833 #endif
2834 break;
2835 default:
2836 if (rb->default_event_handler_ex(button, cleanup, NULL)
2837 == SYS_USB_CONNECTED)
2838 return PLUGIN_USB_CONNECTED;
2839 break;
2841 } /* switch */
2843 if (button != BUTTON_NONE)
2844 lastbutton = button;
2845 } /* while (true) */
2848 /********************* main function *************************/
2850 /* callback updating a progress meter while JPEG decoding */
2851 void cb_progess(int current, int total)
2853 rb->yield(); /* be nice to the other threads */
2854 if(!running_slideshow)
2856 rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN],0, LCD_HEIGHT-8, LCD_WIDTH, 8, total, 0,
2857 current, HORIZONTAL);
2858 rb->lcd_update_rect(0, LCD_HEIGHT-8, LCD_WIDTH, 8);
2860 #ifndef USEGSLIB
2861 else
2863 /* in slideshow mode, keep gui interference to a minimum */
2864 rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN],0, LCD_HEIGHT-4, LCD_WIDTH, 4, total, 0,
2865 current, HORIZONTAL);
2866 rb->lcd_update_rect(0, LCD_HEIGHT-4, LCD_WIDTH, 4);
2868 #endif
2871 int jpegmem(struct jpeg *p_jpg, int ds)
2873 int size;
2875 size = (p_jpg->x_phys/ds/p_jpg->subsample_x[0])
2876 * (p_jpg->y_phys/ds/p_jpg->subsample_y[0]);
2877 #ifdef HAVE_LCD_COLOR
2878 if (p_jpg->blocks > 1) /* colour, add requirements for chroma */
2880 size += (p_jpg->x_phys/ds/p_jpg->subsample_x[1])
2881 * (p_jpg->y_phys/ds/p_jpg->subsample_y[1]);
2882 size += (p_jpg->x_phys/ds/p_jpg->subsample_x[2])
2883 * (p_jpg->y_phys/ds/p_jpg->subsample_y[2]);
2885 #endif
2886 return size;
2889 /* how far can we zoom in without running out of memory */
2890 int min_downscale(struct jpeg *p_jpg, int bufsize)
2892 int downscale = 8;
2894 if (jpegmem(p_jpg, 8) > bufsize)
2895 return 0; /* error, too large, even 1:8 doesn't fit */
2897 while (downscale > 1 && jpegmem(p_jpg, downscale/2) <= bufsize)
2898 downscale /= 2;
2900 return downscale;
2904 /* how far can we zoom out, to fit image into the LCD */
2905 int max_downscale(struct jpeg *p_jpg)
2907 int downscale = 1;
2909 while (downscale < 8 && (p_jpg->x_size > LCD_WIDTH*downscale
2910 || p_jpg->y_size > LCD_HEIGHT*downscale))
2912 downscale *= 2;
2915 return downscale;
2919 /* return decoded or cached image */
2920 struct t_disp* get_image(struct jpeg* p_jpg, int ds)
2922 int w, h; /* used to center output */
2923 int size; /* decompressed image size */
2924 long time; /* measured ticks */
2925 int status;
2927 struct t_disp* p_disp = &disp[ds]; /* short cut */
2929 if (p_disp->bitmap[0] != NULL)
2931 return p_disp; /* we still have it */
2934 /* assign image buffer */
2936 /* physical size needed for decoding */
2937 size = jpegmem(p_jpg, ds);
2938 if (buf_size <= size)
2939 { /* have to discard the current */
2940 int i;
2941 for (i=1; i<=8; i++)
2942 disp[i].bitmap[0] = NULL; /* invalidate all bitmaps */
2943 buf = buf_root; /* start again from the beginning of the buffer */
2944 buf_size = root_size;
2947 #ifdef HAVE_LCD_COLOR
2948 if (p_jpg->blocks > 1) /* colour jpeg */
2950 int i;
2952 for (i = 1; i < 3; i++)
2954 size = (p_jpg->x_phys / ds / p_jpg->subsample_x[i])
2955 * (p_jpg->y_phys / ds / p_jpg->subsample_y[i]);
2956 p_disp->bitmap[i] = buf;
2957 buf += size;
2958 buf_size -= size;
2960 p_disp->csub_x = p_jpg->subsample_x[1];
2961 p_disp->csub_y = p_jpg->subsample_y[1];
2963 else
2965 p_disp->csub_x = p_disp->csub_y = 0;
2966 p_disp->bitmap[1] = p_disp->bitmap[2] = buf;
2968 #endif
2969 /* size may be less when decoded (if height is not block aligned) */
2970 size = (p_jpg->x_phys/ds) * (p_jpg->y_size / ds);
2971 p_disp->bitmap[0] = buf;
2972 buf += size;
2973 buf_size -= size;
2975 if(!running_slideshow)
2977 rb->snprintf(print, sizeof(print), "decoding %d*%d",
2978 p_jpg->x_size/ds, p_jpg->y_size/ds);
2979 rb->lcd_puts(0, 3, print);
2980 rb->lcd_update();
2983 /* update image properties */
2984 p_disp->width = p_jpg->x_size / ds;
2985 p_disp->stride = p_jpg->x_phys / ds; /* use physical size for stride */
2986 p_disp->height = p_jpg->y_size / ds;
2988 /* the actual decoding */
2989 time = *rb->current_tick;
2990 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
2991 rb->cpu_boost(true);
2992 status = jpeg_decode(p_jpg, p_disp->bitmap, ds, cb_progess);
2993 rb->cpu_boost(false);
2994 #else
2995 status = jpeg_decode(p_jpg, p_disp->bitmap, ds, cb_progess);
2996 #endif
2997 if (status)
2999 rb->splash(HZ, "decode error %d", status);
3000 file_pt[curfile] = '\0';
3001 return NULL;
3003 time = *rb->current_tick - time;
3005 if(!running_slideshow)
3007 rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ);
3008 rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */
3009 rb->lcd_putsxy((LCD_WIDTH - w)/2, LCD_HEIGHT - h, print);
3010 rb->lcd_update();
3013 return p_disp;
3017 /* set the view to the given center point, limit if necessary */
3018 void set_view (struct t_disp* p_disp, int cx, int cy)
3020 int x, y;
3022 /* plain center to available width/height */
3023 x = cx - MIN(LCD_WIDTH, p_disp->width) / 2;
3024 y = cy - MIN(LCD_HEIGHT, p_disp->height) / 2;
3026 /* limit against upper image size */
3027 x = MIN(p_disp->width - LCD_WIDTH, x);
3028 y = MIN(p_disp->height - LCD_HEIGHT, y);
3030 /* limit against negative side */
3031 x = MAX(0, x);
3032 y = MAX(0, y);
3034 p_disp->x = x; /* set the values */
3035 p_disp->y = y;
3039 /* calculate the view center based on the bitmap position */
3040 void get_view(struct t_disp* p_disp, int* p_cx, int* p_cy)
3042 *p_cx = p_disp->x + MIN(LCD_WIDTH, p_disp->width) / 2;
3043 *p_cy = p_disp->y + MIN(LCD_HEIGHT, p_disp->height) / 2;
3047 /* load, decode, display the image */
3048 int load_and_show(char* filename)
3050 int fd;
3051 int filesize;
3052 unsigned char* buf_jpeg; /* compressed JPEG image */
3053 int status;
3054 struct t_disp* p_disp; /* currenly displayed image */
3055 int cx, cy; /* view center */
3057 fd = rb->open(filename, O_RDONLY);
3058 if (fd < 0)
3060 rb->snprintf(print,sizeof(print),"err opening %s:%d",filename,fd);
3061 rb->splash(HZ, print);
3062 return PLUGIN_ERROR;
3064 filesize = rb->filesize(fd);
3065 rb->memset(&disp, 0, sizeof(disp));
3067 buf = buf_images + filesize;
3068 buf_size = buf_images_size - filesize;
3069 /* allocate JPEG buffer */
3070 buf_jpeg = buf_images;
3072 buf_root = buf; /* we can start the decompressed images behind it */
3073 root_size = buf_size;
3075 if (buf_size <= 0)
3077 #if PLUGIN_BUFFER_SIZE >= MIN_MEM
3078 if(plug_buf)
3080 rb->close(fd);
3081 rb->lcd_setfont(FONT_SYSFIXED);
3082 rb->lcd_clear_display();
3083 rb->snprintf(print,sizeof(print),"%s:",rb->strrchr(filename,'/')+1);
3084 rb->lcd_puts(0,0,print);
3085 rb->lcd_puts(0,1,"Not enough plugin memory!");
3086 rb->lcd_puts(0,2,"Zoom In: Stop playback.");
3087 if(entries>1)
3088 rb->lcd_puts(0,3,"Left/Right: Skip File.");
3089 rb->lcd_puts(0,4,"Off: Quit.");
3090 rb->lcd_update();
3091 rb->lcd_setfont(FONT_UI);
3093 rb->button_clear_queue();
3095 while (1)
3097 int button = rb->button_get(true);
3098 switch(button)
3100 case JPEG_ZOOM_IN:
3101 plug_buf = false;
3102 buf_images = rb->plugin_get_audio_buffer(
3103 (size_t *)&buf_images_size);
3104 /*try again this file, now using the audio buffer */
3105 return PLUGIN_OTHER;
3106 #ifdef JPEG_RC_MENU
3107 case JPEG_RC_MENU:
3108 #endif
3109 case JPEG_MENU:
3110 return PLUGIN_OK;
3112 case JPEG_LEFT:
3113 if(entries>1)
3115 rb->lcd_clear_display();
3116 return change_filename(DIR_PREV);
3118 break;
3120 case JPEG_RIGHT:
3121 if(entries>1)
3123 rb->lcd_clear_display();
3124 return change_filename(DIR_NEXT);
3126 break;
3127 default:
3128 if(rb->default_event_handler_ex(button, cleanup, NULL)
3129 == SYS_USB_CONNECTED)
3130 return PLUGIN_USB_CONNECTED;
3135 else
3136 #endif
3138 rb->splash(HZ, "Out of Memory");
3139 rb->close(fd);
3140 return PLUGIN_ERROR;
3144 if(!running_slideshow)
3146 #if LCD_DEPTH > 1
3147 rb->lcd_set_foreground(LCD_WHITE);
3148 rb->lcd_set_background(LCD_BLACK);
3149 rb->lcd_set_backdrop(NULL);
3150 #endif
3152 rb->lcd_clear_display();
3153 rb->snprintf(print, sizeof(print), "%s:", rb->strrchr(filename,'/')+1);
3154 rb->lcd_puts(0, 0, print);
3155 rb->lcd_update();
3157 rb->snprintf(print, sizeof(print), "loading %d bytes", filesize);
3158 rb->lcd_puts(0, 1, print);
3159 rb->lcd_update();
3162 rb->read(fd, buf_jpeg, filesize);
3163 rb->close(fd);
3165 if(!running_slideshow)
3167 rb->snprintf(print, sizeof(print), "decoding markers");
3168 rb->lcd_puts(0, 2, print);
3169 rb->lcd_update();
3171 #ifndef SIMULATOR
3172 else if(immediate_ata_off)
3174 /* running slideshow and time is long enough: power down disk */
3175 rb->ata_sleep();
3177 #endif
3179 rb->memset(&jpg, 0, sizeof(jpg)); /* clear info struct */
3180 /* process markers, unstuffing */
3181 status = process_markers(buf_jpeg, filesize, &jpg);
3183 if (status < 0 || (status & (DQT | SOF0)) != (DQT | SOF0))
3184 { /* bad format or minimum components not contained */
3185 rb->splash(HZ, "unsupported %d", status);
3186 file_pt[curfile] = '\0';
3187 return change_filename(direction);
3190 if (!(status & DHT)) /* if no Huffman table present: */
3191 default_huff_tbl(&jpg); /* use default */
3192 build_lut(&jpg); /* derive Huffman and other lookup-tables */
3194 if(!running_slideshow)
3196 rb->snprintf(print, sizeof(print), "image %dx%d", jpg.x_size, jpg.y_size);
3197 rb->lcd_puts(0, 2, print);
3198 rb->lcd_update();
3200 ds_max = max_downscale(&jpg); /* check display constraint */
3201 ds_min = min_downscale(&jpg, buf_size); /* check memory constraint */
3202 if (ds_min == 0)
3204 rb->splash(HZ, "too large");
3205 file_pt[curfile] = '\0';
3206 return change_filename(direction);
3209 ds = ds_max; /* initials setting */
3210 cx = jpg.x_size/ds/2; /* center the view */
3211 cy = jpg.y_size/ds/2;
3213 do /* loop the image prepare and decoding when zoomed */
3215 p_disp = get_image(&jpg, ds); /* decode or fetch from cache */
3216 if (p_disp == NULL)
3217 return change_filename(direction);
3219 set_view(p_disp, cx, cy);
3221 if(!running_slideshow)
3223 rb->snprintf(print, sizeof(print), "showing %dx%d",
3224 p_disp->width, p_disp->height);
3225 rb->lcd_puts(0, 3, print);
3226 rb->lcd_update();
3228 MYLCD(clear_display)();
3229 #ifdef HAVE_LCD_COLOR
3230 yuv_bitmap_part(
3231 p_disp->bitmap, p_disp->csub_x, p_disp->csub_y,
3232 p_disp->x, p_disp->y, p_disp->stride,
3233 MAX(0, (LCD_WIDTH - p_disp->width) / 2),
3234 MAX(0, (LCD_HEIGHT - p_disp->height) / 2),
3235 MIN(LCD_WIDTH, p_disp->width),
3236 MIN(LCD_HEIGHT, p_disp->height));
3237 #else
3238 MYXLCD(gray_bitmap_part)(
3239 p_disp->bitmap[0], p_disp->x, p_disp->y, p_disp->stride,
3240 MAX(0, (LCD_WIDTH - p_disp->width) / 2),
3241 MAX(0, (LCD_HEIGHT - p_disp->height) / 2),
3242 MIN(LCD_WIDTH, p_disp->width),
3243 MIN(LCD_HEIGHT, p_disp->height));
3244 #endif
3245 MYLCD_UPDATE();
3247 #ifdef USEGSLIB
3248 grey_show(true); /* switch on greyscale overlay */
3249 #endif
3251 /* drawing is now finished, play around with scrolling
3252 * until you press OFF or connect USB
3254 while (1)
3256 status = scroll_bmp(p_disp);
3257 if (status == ZOOM_IN)
3259 if (ds > ds_min)
3261 ds /= 2; /* reduce downscaling to zoom in */
3262 get_view(p_disp, &cx, &cy);
3263 cx *= 2; /* prepare the position in the new image */
3264 cy *= 2;
3266 else
3267 continue;
3270 if (status == ZOOM_OUT)
3272 if (ds < ds_max)
3274 ds *= 2; /* increase downscaling to zoom out */
3275 get_view(p_disp, &cx, &cy);
3276 cx /= 2; /* prepare the position in the new image */
3277 cy /= 2;
3279 else
3280 continue;
3282 break;
3285 #ifdef USEGSLIB
3286 grey_show(false); /* switch off overlay */
3287 #endif
3288 rb->lcd_clear_display();
3290 while (status != PLUGIN_OK && status != PLUGIN_USB_CONNECTED
3291 && status != PLUGIN_OTHER);
3292 #ifdef USEGSLIB
3293 rb->lcd_update();
3294 #endif
3295 return status;
3298 /******************** Plugin entry point *********************/
3300 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
3302 rb = api;
3304 int condition;
3305 #ifdef USEGSLIB
3306 long greysize; /* helper */
3307 #endif
3308 #if LCD_DEPTH > 1
3309 old_backdrop = rb->lcd_get_backdrop();
3310 #endif
3312 if(!parameter) return PLUGIN_ERROR;
3314 rb->strcpy(np_file, parameter);
3315 get_pic_list();
3317 if(!entries) return PLUGIN_ERROR;
3319 #if (PLUGIN_BUFFER_SIZE >= MIN_MEM) && !defined(SIMULATOR)
3320 if(rb->audio_status())
3322 buf = rb->plugin_get_buffer((size_t *)&buf_size) +
3323 (entries * sizeof(char**));
3324 buf_size -= (entries * sizeof(char**));
3325 plug_buf = true;
3327 else
3328 buf = rb->plugin_get_audio_buffer((size_t *)&buf_size);
3329 #else
3330 buf = rb->plugin_get_audio_buffer(&buf_size) +
3331 (entries * sizeof(char**));
3332 buf_size -= (entries * sizeof(char**));
3333 #endif
3335 #ifdef USEGSLIB
3336 if (!grey_init(rb, buf, buf_size, 0, LCD_WIDTH, LCD_HEIGHT, &greysize))
3338 rb->splash(HZ, "grey buf error");
3339 return PLUGIN_ERROR;
3341 buf += greysize;
3342 buf_size -= greysize;
3343 #else
3344 xlcd_init(rb);
3345 #endif
3347 /* should be ok to just load settings since a parameter is present
3348 here and the drive should be spinning */
3349 configfile_init(rb);
3350 configfile_load(JPEG_CONFIGFILE, jpeg_config,
3351 ARRAYLEN(jpeg_config), JPEG_SETTINGS_MINVERSION);
3352 old_settings = jpeg_settings;
3354 buf_images = buf; buf_images_size = buf_size;
3356 /* Turn off backlight timeout */
3357 backlight_force_on(rb); /* backlight control in lib/helper.c */
3361 condition = load_and_show(np_file);
3362 }while (condition != PLUGIN_OK && condition != PLUGIN_USB_CONNECTED
3363 && condition != PLUGIN_ERROR);
3365 if (rb->memcmp(&jpeg_settings, &old_settings, sizeof (jpeg_settings)))
3367 /* Just in case drive has to spin, keep it from looking locked */
3368 rb->splash(0, "Saving Settings");
3369 configfile_save(JPEG_CONFIGFILE, jpeg_config,
3370 ARRAYLEN(jpeg_config), JPEG_SETTINGS_VERSION);
3373 #if !defined(SIMULATOR) && !defined(HAVE_FLASH_STORAGE)
3374 /* set back ata spindown time in case we changed it */
3375 rb->ata_spindown(rb->global_settings->disk_spindown);
3376 #endif
3378 /* Turn on backlight timeout (revert to settings) */
3379 backlight_use_settings(rb); /* backlight control in lib/helper.c */
3381 #ifdef USEGSLIB
3382 grey_release(); /* deinitialize */
3383 #endif
3385 return condition;
3388 #endif /* HAVE_LCD_BITMAP */