Bring mpegplayer backlight fix to the other plugins, this also fixes some wrongly...
[Rockbox.git] / apps / plugins / jpeg.c
blobb4f85f5a168db85caabd2db56f9503b634d2a9a3
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�g Hohensohn aka [IDC]Dragon
15 * Grayscale framework (C) 2004 Jens Arnold
16 * Heavily borrowed from the IJG implementation (C) Thomas G. Lane
17 * Small & fast downscaling IDCT (C) 2002 by Guido Vollbeding JPEGclub.org
19 * All files in this archive are subject to the GNU General Public License.
20 * See the file COPYING in the source tree root for full license agreement.
22 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
23 * KIND, either express or implied.
25 ****************************************************************************/
27 #include "plugin.h"
28 #include "playback_control.h"
29 #include "oldmenuapi.h"
30 #include "helper.h"
32 #ifdef HAVE_LCD_BITMAP
33 #include "gray.h"
34 #include "xlcd.h"
36 #ifdef HAVE_LCD_COLOR
37 #include "lib/configfile.h"
38 #endif
40 PLUGIN_HEADER
42 /* variable button definitions */
43 #if CONFIG_KEYPAD == RECORDER_PAD
44 #define JPEG_ZOOM_IN BUTTON_PLAY
45 #define JPEG_ZOOM_OUT BUTTON_ON
46 #define JPEG_UP BUTTON_UP
47 #define JPEG_DOWN BUTTON_DOWN
48 #define JPEG_LEFT BUTTON_LEFT
49 #define JPEG_RIGHT BUTTON_RIGHT
50 #define JPEG_NEXT BUTTON_F3
51 #define JPEG_PREVIOUS BUTTON_F2
52 #define JPEG_MENU BUTTON_OFF
54 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
55 #define JPEG_ZOOM_IN BUTTON_SELECT
56 #define JPEG_ZOOM_OUT BUTTON_ON
57 #define JPEG_UP BUTTON_UP
58 #define JPEG_DOWN BUTTON_DOWN
59 #define JPEG_LEFT BUTTON_LEFT
60 #define JPEG_RIGHT BUTTON_RIGHT
61 #define JPEG_NEXT BUTTON_F3
62 #define JPEG_PREVIOUS BUTTON_F2
63 #define JPEG_MENU BUTTON_OFF
65 #elif CONFIG_KEYPAD == ONDIO_PAD
66 #define JPEG_ZOOM_PRE BUTTON_MENU
67 #define JPEG_ZOOM_IN (BUTTON_MENU | BUTTON_REL)
68 #define JPEG_ZOOM_OUT (BUTTON_MENU | BUTTON_DOWN)
69 #define JPEG_UP BUTTON_UP
70 #define JPEG_DOWN BUTTON_DOWN
71 #define JPEG_LEFT BUTTON_LEFT
72 #define JPEG_RIGHT BUTTON_RIGHT
73 #define JPEG_NEXT (BUTTON_MENU | BUTTON_RIGHT)
74 #define JPEG_PREVIOUS (BUTTON_MENU | BUTTON_LEFT)
75 #define JPEG_MENU BUTTON_OFF
77 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
78 (CONFIG_KEYPAD == IRIVER_H300_PAD)
79 #define JPEG_ZOOM_IN BUTTON_SELECT
80 #define JPEG_ZOOM_OUT BUTTON_MODE
81 #define JPEG_UP BUTTON_UP
82 #define JPEG_DOWN BUTTON_DOWN
83 #define JPEG_LEFT BUTTON_LEFT
84 #define JPEG_RIGHT BUTTON_RIGHT
85 #if (CONFIG_KEYPAD == IRIVER_H100_PAD)
86 #define JPEG_NEXT BUTTON_ON
87 #define JPEG_PREVIOUS BUTTON_REC
88 #else
89 #define JPEG_NEXT BUTTON_REC
90 #define JPEG_PREVIOUS BUTTON_ON
91 #endif
92 #define JPEG_MENU BUTTON_OFF
93 #define JPEG_RC_MENU BUTTON_RC_STOP
95 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
96 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
97 #define JPEG_ZOOM_IN BUTTON_SCROLL_FWD
98 #define JPEG_ZOOM_OUT BUTTON_SCROLL_BACK
99 #define JPEG_UP BUTTON_MENU
100 #define JPEG_DOWN BUTTON_PLAY
101 #define JPEG_LEFT BUTTON_LEFT
102 #define JPEG_RIGHT BUTTON_RIGHT
103 #define JPEG_MENU (BUTTON_SELECT | BUTTON_MENU)
104 #define JPEG_NEXT (BUTTON_SELECT | BUTTON_RIGHT)
105 #define JPEG_PREVIOUS (BUTTON_SELECT | BUTTON_LEFT)
107 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
108 #define JPEG_ZOOM_PRE BUTTON_SELECT
109 #define JPEG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
110 #define JPEG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
111 #define JPEG_UP BUTTON_UP
112 #define JPEG_DOWN BUTTON_DOWN
113 #define JPEG_LEFT BUTTON_LEFT
114 #define JPEG_RIGHT BUTTON_RIGHT
115 #define JPEG_MENU BUTTON_POWER
116 #define JPEG_NEXT BUTTON_PLAY
117 #define JPEG_PREVIOUS BUTTON_REC
119 #elif CONFIG_KEYPAD == GIGABEAT_PAD
120 #define JPEG_ZOOM_IN BUTTON_VOL_UP
121 #define JPEG_ZOOM_OUT BUTTON_VOL_DOWN
122 #define JPEG_UP BUTTON_UP
123 #define JPEG_DOWN BUTTON_DOWN
124 #define JPEG_LEFT BUTTON_LEFT
125 #define JPEG_RIGHT BUTTON_RIGHT
126 #define JPEG_MENU BUTTON_MENU
127 #define JPEG_NEXT (BUTTON_A | BUTTON_RIGHT)
128 #define JPEG_PREVIOUS (BUTTON_A | BUTTON_LEFT)
130 #elif CONFIG_KEYPAD == SANSA_E200_PAD
131 #define JPEG_ZOOM_PRE BUTTON_SELECT
132 #define JPEG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
133 #define JPEG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
134 #define JPEG_UP BUTTON_UP
135 #define JPEG_DOWN BUTTON_DOWN
136 #define JPEG_LEFT BUTTON_LEFT
137 #define JPEG_RIGHT BUTTON_RIGHT
138 #define JPEG_MENU BUTTON_POWER
139 #define JPEG_SLIDE_SHOW BUTTON_REC
140 #define JPEG_NEXT BUTTON_SCROLL_DOWN
141 #define JPEG_NEXT_REPEAT (BUTTON_SCROLL_DOWN|BUTTON_REPEAT)
142 #define JPEG_PREVIOUS BUTTON_SCROLL_UP
143 #define JPEG_PREVIOUS_REPEAT (BUTTON_SCROLL_UP|BUTTON_REPEAT)
145 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
146 #define JPEG_ZOOM_PRE BUTTON_PLAY
147 #define JPEG_ZOOM_IN (BUTTON_PLAY | BUTTON_REL)
148 #define JPEG_ZOOM_OUT (BUTTON_PLAY | BUTTON_REPEAT)
149 #define JPEG_UP BUTTON_SCROLL_UP
150 #define JPEG_DOWN BUTTON_SCROLL_DOWN
151 #define JPEG_LEFT BUTTON_LEFT
152 #define JPEG_RIGHT BUTTON_RIGHT
153 #define JPEG_MENU BUTTON_POWER
154 #define JPEG_NEXT BUTTON_FF
155 #define JPEG_PREVIOUS BUTTON_REW
157 #endif
159 /* different graphics libraries */
160 #if LCD_DEPTH < 8
161 #define USEGSLIB
162 #define MYLCD(fn) gray_ub_ ## fn
163 #define MYLCD_UPDATE()
164 #define MYXLCD(fn) gray_ub_ ## fn
165 #else
166 #define MYLCD(fn) rb->lcd_ ## fn
167 #define MYLCD_UPDATE() rb->lcd_update();
168 #define MYXLCD(fn) xlcd_ ## fn
169 #endif
171 #define MAX_X_SIZE LCD_WIDTH*8
173 /* Min memory allowing us to use the plugin buffer
174 * and thus not stopping the music
175 * *Very* rough estimation:
176 * Max 10 000 dir entries * 4bytes/entry (char **) = 40000 bytes
177 * + 20k code size = 60 000
178 * + 50k min for jpeg = 120 000
180 #define MIN_MEM 120000
182 /* Headings */
183 #define DIR_PREV 1
184 #define DIR_NEXT -1
185 #define DIR_NONE 0
187 #define PLUGIN_OTHER 10 /* State code for output with return. */
189 /******************************* Globals ***********************************/
191 static struct plugin_api* rb;
192 MEM_FUNCTION_WRAPPERS(rb);
194 /* for portability of below JPEG code */
195 #define MEMSET(p,v,c) rb->memset(p,v,c)
196 #define MEMCPY(d,s,c) rb->memcpy(d,s,c)
197 #define INLINE static inline
198 #define ENDIAN_SWAP16(n) n /* only for poor little endian machines */
200 static int slideshow_enabled = false; /* run slideshow */
201 static int running_slideshow = false; /* loading image because of slideshw */
202 #ifndef SIMULATOR
203 static int immediate_ata_off = false; /* power down disk after loading */
204 #endif
205 static int button_timeout = HZ*5;
207 #ifdef HAVE_LCD_COLOR
209 /* Persistent configuration - only needed for color displays atm */
210 #define JPEG_CONFIGFILE "jpeg.cfg"
211 #define JPEG_SETTINGS_MINVERSION 1
212 #define JPEG_SETTINGS_VERSION 1
214 enum color_modes
216 COLOURMODE_COLOUR = 0,
217 COLOURMODE_GRAY,
218 COLOUR_NUM_MODES
221 enum dither_modes
223 DITHER_NONE = 0, /* No dithering */
224 DITHER_ORDERED, /* Bayer ordered */
225 DITHER_DIFFUSION, /* Floyd/Steinberg error diffusion */
226 DITHER_NUM_MODES
229 struct jpeg_settings
231 int colour_mode;
232 int dither_mode;
235 static struct jpeg_settings jpeg_settings =
236 { COLOURMODE_COLOUR, DITHER_NONE };
237 static struct jpeg_settings old_settings;
239 static struct configdata jpeg_config[] =
241 { TYPE_ENUM, 0, COLOUR_NUM_MODES, &jpeg_settings.colour_mode,
242 "Colour Mode", (char *[]){ "Colour", "Grayscale" }, NULL },
243 { TYPE_ENUM, 0, DITHER_NUM_MODES, &jpeg_settings.dither_mode,
244 "Dither Mode", (char *[]){ "None", "Ordered", "Diffusion" }, NULL },
247 #endif /* HAVE_LCD_COLOR */
248 #if LCD_DEPTH > 1
249 fb_data* old_backdrop;
250 #endif
252 /**************** begin JPEG code ********************/
254 INLINE unsigned range_limit(int value)
256 #if CONFIG_CPU == SH7034
257 unsigned tmp;
258 asm ( /* Note: Uses knowledge that only low byte of result is used */
259 "mov #-128,%[t] \n"
260 "sub %[t],%[v] \n" /* value -= -128; equals value += 128; */
261 "extu.b %[v],%[t] \n"
262 "cmp/eq %[v],%[t] \n" /* low byte == whole number ? */
263 "bt 1f \n" /* yes: no overflow */
264 "cmp/pz %[v] \n" /* overflow: positive? */
265 "subc %[v],%[v] \n" /* %[r] now either 0 or 0xffffffff */
266 "1: \n"
267 : /* outputs */
268 [v]"+r"(value),
269 [t]"=&r"(tmp)
271 return value;
272 #elif defined(CPU_COLDFIRE)
273 asm ( /* Note: Uses knowledge that only the low byte of the result is used */
274 "add.l #128,%[v] \n" /* value += 128; */
275 "cmp.l #255,%[v] \n" /* overflow? */
276 "bls.b 1f \n" /* no: return value */
277 "spl.b %[v] \n" /* yes: set low byte to appropriate boundary */
278 "1: \n"
279 : /* outputs */
280 [v]"+d"(value)
282 return value;
283 #elif defined(CPU_ARM)
284 asm ( /* Note: Uses knowledge that only the low byte of the result is used */
285 "add %[v], %[v], #128 \n" /* value += 128 */
286 "cmp %[v], #255 \n" /* out of range 0..255? */
287 "mvnhi %[v], %[v], asr #31 \n" /* yes: set all bits to ~(sign_bit) */
288 : /* outputs */
289 [v]"+r"(value)
291 return value;
292 #else
293 value += 128;
295 if ((unsigned)value <= 255)
296 return value;
298 if (value < 0)
299 return 0;
301 return 255;
302 #endif
305 /* IDCT implementation */
308 #define CONST_BITS 13
309 #define PASS1_BITS 2
312 /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
313 * causing a lot of useless floating-point operations at run time.
314 * To get around this we use the following pre-calculated constants.
315 * If you change CONST_BITS you may want to add appropriate values.
316 * (With a reasonable C compiler, you can just rely on the FIX() macro...)
318 #define FIX_0_298631336 2446 /* FIX(0.298631336) */
319 #define FIX_0_390180644 3196 /* FIX(0.390180644) */
320 #define FIX_0_541196100 4433 /* FIX(0.541196100) */
321 #define FIX_0_765366865 6270 /* FIX(0.765366865) */
322 #define FIX_0_899976223 7373 /* FIX(0.899976223) */
323 #define FIX_1_175875602 9633 /* FIX(1.175875602) */
324 #define FIX_1_501321110 12299 /* FIX(1.501321110) */
325 #define FIX_1_847759065 15137 /* FIX(1.847759065) */
326 #define FIX_1_961570560 16069 /* FIX(1.961570560) */
327 #define FIX_2_053119869 16819 /* FIX(2.053119869) */
328 #define FIX_2_562915447 20995 /* FIX(2.562915447) */
329 #define FIX_3_072711026 25172 /* FIX(3.072711026) */
333 /* Multiply an long variable by an long constant to yield an long result.
334 * For 8-bit samples with the recommended scaling, all the variable
335 * and constant values involved are no more than 16 bits wide, so a
336 * 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
337 * For 12-bit samples, a full 32-bit multiplication will be needed.
339 #define MULTIPLY16(var,const) (((short) (var)) * ((short) (const)))
342 /* Dequantize a coefficient by multiplying it by the multiplier-table
343 * entry; produce an int result. In this module, both inputs and result
344 * are 16 bits or less, so either int or short multiply will work.
346 /* #define DEQUANTIZE(coef,quantval) (((int) (coef)) * (quantval)) */
347 #define DEQUANTIZE MULTIPLY16
349 /* Descale and correctly round an int value that's scaled by N bits.
350 * We assume RIGHT_SHIFT rounds towards minus infinity, so adding
351 * the fudge factor is correct for either sign of X.
353 #define DESCALE(x,n) (((x) + (1l << ((n)-1))) >> (n))
358 * Perform dequantization and inverse DCT on one block of coefficients,
359 * producing a reduced-size 1x1 output block.
361 void idct1x1(unsigned char* p_byte, int* inptr, int* quantptr, int skip_line)
363 (void)skip_line; /* unused */
364 *p_byte = range_limit(inptr[0] * quantptr[0] >> 3);
370 * Perform dequantization and inverse DCT on one block of coefficients,
371 * producing a reduced-size 2x2 output block.
373 void idct2x2(unsigned char* p_byte, int* inptr, int* quantptr, int skip_line)
375 int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
376 unsigned char* outptr;
378 /* Pass 1: process columns from input, store into work array. */
380 /* Column 0 */
381 tmp4 = DEQUANTIZE(inptr[8*0], quantptr[8*0]);
382 tmp5 = DEQUANTIZE(inptr[8*1], quantptr[8*1]);
384 tmp0 = tmp4 + tmp5;
385 tmp2 = tmp4 - tmp5;
387 /* Column 1 */
388 tmp4 = DEQUANTIZE(inptr[8*0+1], quantptr[8*0+1]);
389 tmp5 = DEQUANTIZE(inptr[8*1+1], quantptr[8*1+1]);
391 tmp1 = tmp4 + tmp5;
392 tmp3 = tmp4 - tmp5;
394 /* Pass 2: process 2 rows, store into output array. */
396 /* Row 0 */
397 outptr = p_byte;
399 outptr[0] = range_limit((int) DESCALE(tmp0 + tmp1, 3));
400 outptr[1] = range_limit((int) DESCALE(tmp0 - tmp1, 3));
402 /* Row 1 */
403 outptr = p_byte + skip_line;
405 outptr[0] = range_limit((int) DESCALE(tmp2 + tmp3, 3));
406 outptr[1] = range_limit((int) DESCALE(tmp2 - tmp3, 3));
412 * Perform dequantization and inverse DCT on one block of coefficients,
413 * producing a reduced-size 4x4 output block.
415 void idct4x4(unsigned char* p_byte, int* inptr, int* quantptr, int skip_line)
417 int tmp0, tmp2, tmp10, tmp12;
418 int z1, z2, z3;
419 int * wsptr;
420 unsigned char* outptr;
421 int ctr;
422 int workspace[4*4]; /* buffers data between passes */
424 /* Pass 1: process columns from input, store into work array. */
426 wsptr = workspace;
427 for (ctr = 0; ctr < 4; ctr++, inptr++, quantptr++, wsptr++)
429 /* Even part */
431 tmp0 = DEQUANTIZE(inptr[8*0], quantptr[8*0]);
432 tmp2 = DEQUANTIZE(inptr[8*2], quantptr[8*2]);
434 tmp10 = (tmp0 + tmp2) << PASS1_BITS;
435 tmp12 = (tmp0 - tmp2) << PASS1_BITS;
437 /* Odd part */
438 /* Same rotation as in the even part of the 8x8 LL&M IDCT */
440 z2 = DEQUANTIZE(inptr[8*1], quantptr[8*1]);
441 z3 = DEQUANTIZE(inptr[8*3], quantptr[8*3]);
443 z1 = MULTIPLY16(z2 + z3, FIX_0_541196100);
444 tmp0 = DESCALE(z1 + MULTIPLY16(z3, - FIX_1_847759065), CONST_BITS-PASS1_BITS);
445 tmp2 = DESCALE(z1 + MULTIPLY16(z2, FIX_0_765366865), CONST_BITS-PASS1_BITS);
447 /* Final output stage */
449 wsptr[4*0] = (int) (tmp10 + tmp2);
450 wsptr[4*3] = (int) (tmp10 - tmp2);
451 wsptr[4*1] = (int) (tmp12 + tmp0);
452 wsptr[4*2] = (int) (tmp12 - tmp0);
455 /* Pass 2: process 4 rows from work array, store into output array. */
457 wsptr = workspace;
458 for (ctr = 0; ctr < 4; ctr++)
460 outptr = p_byte + (ctr*skip_line);
461 /* Even part */
463 tmp0 = (int) wsptr[0];
464 tmp2 = (int) wsptr[2];
466 tmp10 = (tmp0 + tmp2) << CONST_BITS;
467 tmp12 = (tmp0 - tmp2) << CONST_BITS;
469 /* Odd part */
470 /* Same rotation as in the even part of the 8x8 LL&M IDCT */
472 z2 = (int) wsptr[1];
473 z3 = (int) wsptr[3];
475 z1 = MULTIPLY16(z2 + z3, FIX_0_541196100);
476 tmp0 = z1 + MULTIPLY16(z3, - FIX_1_847759065);
477 tmp2 = z1 + MULTIPLY16(z2, FIX_0_765366865);
479 /* Final output stage */
481 outptr[0] = range_limit((int) DESCALE(tmp10 + tmp2,
482 CONST_BITS+PASS1_BITS+3));
483 outptr[3] = range_limit((int) DESCALE(tmp10 - tmp2,
484 CONST_BITS+PASS1_BITS+3));
485 outptr[1] = range_limit((int) DESCALE(tmp12 + tmp0,
486 CONST_BITS+PASS1_BITS+3));
487 outptr[2] = range_limit((int) DESCALE(tmp12 - tmp0,
488 CONST_BITS+PASS1_BITS+3));
490 wsptr += 4; /* advance pointer to next row */
497 * Perform dequantization and inverse DCT on one block of coefficients.
499 void idct8x8(unsigned char* p_byte, int* inptr, int* quantptr, int skip_line)
501 long tmp0, tmp1, tmp2, tmp3;
502 long tmp10, tmp11, tmp12, tmp13;
503 long z1, z2, z3, z4, z5;
504 int * wsptr;
505 unsigned char* outptr;
506 int ctr;
507 int workspace[64]; /* buffers data between passes */
509 /* Pass 1: process columns from input, store into work array. */
510 /* Note results are scaled up by sqrt(8) compared to a true IDCT; */
511 /* furthermore, we scale the results by 2**PASS1_BITS. */
513 wsptr = workspace;
514 for (ctr = 8; ctr > 0; ctr--)
516 /* Due to quantization, we will usually find that many of the input
517 * coefficients are zero, especially the AC terms. We can exploit this
518 * by short-circuiting the IDCT calculation for any column in which all
519 * the AC terms are zero. In that case each output is equal to the
520 * DC coefficient (with scale factor as needed).
521 * With typical images and quantization tables, half or more of the
522 * column DCT calculations can be simplified this way.
525 if ((inptr[8*1] | inptr[8*2] | inptr[8*3]
526 | inptr[8*4] | inptr[8*5] | inptr[8*6] | inptr[8*7]) == 0)
528 /* AC terms all zero */
529 int dcval = DEQUANTIZE(inptr[8*0], quantptr[8*0]) << PASS1_BITS;
531 wsptr[8*0] = wsptr[8*1] = wsptr[8*2] = wsptr[8*3] = wsptr[8*4]
532 = wsptr[8*5] = wsptr[8*6] = wsptr[8*7] = dcval;
533 inptr++; /* advance pointers to next column */
534 quantptr++;
535 wsptr++;
536 continue;
539 /* Even part: reverse the even part of the forward DCT. */
540 /* The rotator is sqrt(2)*c(-6). */
542 z2 = DEQUANTIZE(inptr[8*2], quantptr[8*2]);
543 z3 = DEQUANTIZE(inptr[8*6], quantptr[8*6]);
545 z1 = MULTIPLY16(z2 + z3, FIX_0_541196100);
546 tmp2 = z1 + MULTIPLY16(z3, - FIX_1_847759065);
547 tmp3 = z1 + MULTIPLY16(z2, FIX_0_765366865);
549 z2 = DEQUANTIZE(inptr[8*0], quantptr[8*0]);
550 z3 = DEQUANTIZE(inptr[8*4], quantptr[8*4]);
552 tmp0 = (z2 + z3) << CONST_BITS;
553 tmp1 = (z2 - z3) << CONST_BITS;
555 tmp10 = tmp0 + tmp3;
556 tmp13 = tmp0 - tmp3;
557 tmp11 = tmp1 + tmp2;
558 tmp12 = tmp1 - tmp2;
560 /* Odd part per figure 8; the matrix is unitary and hence its
561 transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */
563 tmp0 = DEQUANTIZE(inptr[8*7], quantptr[8*7]);
564 tmp1 = DEQUANTIZE(inptr[8*5], quantptr[8*5]);
565 tmp2 = DEQUANTIZE(inptr[8*3], quantptr[8*3]);
566 tmp3 = DEQUANTIZE(inptr[8*1], quantptr[8*1]);
568 z1 = tmp0 + tmp3;
569 z2 = tmp1 + tmp2;
570 z3 = tmp0 + tmp2;
571 z4 = tmp1 + tmp3;
572 z5 = MULTIPLY16(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
574 tmp0 = MULTIPLY16(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
575 tmp1 = MULTIPLY16(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
576 tmp2 = MULTIPLY16(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
577 tmp3 = MULTIPLY16(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
578 z1 = MULTIPLY16(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
579 z2 = MULTIPLY16(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
580 z3 = MULTIPLY16(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
581 z4 = MULTIPLY16(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
583 z3 += z5;
584 z4 += z5;
586 tmp0 += z1 + z3;
587 tmp1 += z2 + z4;
588 tmp2 += z2 + z3;
589 tmp3 += z1 + z4;
591 /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
593 wsptr[8*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
594 wsptr[8*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
595 wsptr[8*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
596 wsptr[8*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
597 wsptr[8*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
598 wsptr[8*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
599 wsptr[8*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
600 wsptr[8*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
602 inptr++; /* advance pointers to next column */
603 quantptr++;
604 wsptr++;
607 /* Pass 2: process rows from work array, store into output array. */
608 /* Note that we must descale the results by a factor of 8 == 2**3, */
609 /* and also undo the PASS1_BITS scaling. */
611 wsptr = workspace;
612 for (ctr = 0; ctr < 8; ctr++)
614 outptr = p_byte + (ctr*skip_line);
615 /* Rows of zeroes can be exploited in the same way as we did with columns.
616 * However, the column calculation has created many nonzero AC terms, so
617 * the simplification applies less often (typically 5% to 10% of the time).
618 * On machines with very fast multiplication, it's possible that the
619 * test takes more time than it's worth. In that case this section
620 * may be commented out.
623 #ifndef NO_ZERO_ROW_TEST
624 if ((wsptr[1] | wsptr[2] | wsptr[3]
625 | wsptr[4] | wsptr[5] | wsptr[6] | wsptr[7]) == 0)
627 /* AC terms all zero */
628 unsigned char dcval = range_limit((int) DESCALE((long) wsptr[0],
629 PASS1_BITS+3));
631 outptr[0] = dcval;
632 outptr[1] = dcval;
633 outptr[2] = dcval;
634 outptr[3] = dcval;
635 outptr[4] = dcval;
636 outptr[5] = dcval;
637 outptr[6] = dcval;
638 outptr[7] = dcval;
640 wsptr += 8; /* advance pointer to next row */
641 continue;
643 #endif
645 /* Even part: reverse the even part of the forward DCT. */
646 /* The rotator is sqrt(2)*c(-6). */
648 z2 = (long) wsptr[2];
649 z3 = (long) wsptr[6];
651 z1 = MULTIPLY16(z2 + z3, FIX_0_541196100);
652 tmp2 = z1 + MULTIPLY16(z3, - FIX_1_847759065);
653 tmp3 = z1 + MULTIPLY16(z2, FIX_0_765366865);
655 tmp0 = ((long) wsptr[0] + (long) wsptr[4]) << CONST_BITS;
656 tmp1 = ((long) wsptr[0] - (long) wsptr[4]) << CONST_BITS;
658 tmp10 = tmp0 + tmp3;
659 tmp13 = tmp0 - tmp3;
660 tmp11 = tmp1 + tmp2;
661 tmp12 = tmp1 - tmp2;
663 /* Odd part per figure 8; the matrix is unitary and hence its
664 * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */
666 tmp0 = (long) wsptr[7];
667 tmp1 = (long) wsptr[5];
668 tmp2 = (long) wsptr[3];
669 tmp3 = (long) wsptr[1];
671 z1 = tmp0 + tmp3;
672 z2 = tmp1 + tmp2;
673 z3 = tmp0 + tmp2;
674 z4 = tmp1 + tmp3;
675 z5 = MULTIPLY16(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
677 tmp0 = MULTIPLY16(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
678 tmp1 = MULTIPLY16(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
679 tmp2 = MULTIPLY16(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
680 tmp3 = MULTIPLY16(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
681 z1 = MULTIPLY16(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
682 z2 = MULTIPLY16(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
683 z3 = MULTIPLY16(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
684 z4 = MULTIPLY16(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
686 z3 += z5;
687 z4 += z5;
689 tmp0 += z1 + z3;
690 tmp1 += z2 + z4;
691 tmp2 += z2 + z3;
692 tmp3 += z1 + z4;
694 /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
696 outptr[0] = range_limit((int) DESCALE(tmp10 + tmp3,
697 CONST_BITS+PASS1_BITS+3));
698 outptr[7] = range_limit((int) DESCALE(tmp10 - tmp3,
699 CONST_BITS+PASS1_BITS+3));
700 outptr[1] = range_limit((int) DESCALE(tmp11 + tmp2,
701 CONST_BITS+PASS1_BITS+3));
702 outptr[6] = range_limit((int) DESCALE(tmp11 - tmp2,
703 CONST_BITS+PASS1_BITS+3));
704 outptr[2] = range_limit((int) DESCALE(tmp12 + tmp1,
705 CONST_BITS+PASS1_BITS+3));
706 outptr[5] = range_limit((int) DESCALE(tmp12 - tmp1,
707 CONST_BITS+PASS1_BITS+3));
708 outptr[3] = range_limit((int) DESCALE(tmp13 + tmp0,
709 CONST_BITS+PASS1_BITS+3));
710 outptr[4] = range_limit((int) DESCALE(tmp13 - tmp0,
711 CONST_BITS+PASS1_BITS+3));
713 wsptr += 8; /* advance pointer to next row */
719 /* JPEG decoder implementation */
722 #define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */
724 struct derived_tbl
726 /* Basic tables: (element [0] of each array is unused) */
727 long mincode[17]; /* smallest code of length k */
728 long maxcode[18]; /* largest code of length k (-1 if none) */
729 /* (maxcode[17] is a sentinel to ensure huff_DECODE terminates) */
730 int valptr[17]; /* huffval[] index of 1st symbol of length k */
732 /* Back link to public Huffman table (needed only in slow_DECODE) */
733 int* pub;
735 /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of
736 the input data stream. If the next Huffman code is no more
737 than HUFF_LOOKAHEAD bits long, we can obtain its length and
738 the corresponding symbol directly from these tables. */
739 int look_nbits[1<<HUFF_LOOKAHEAD]; /* # bits, or 0 if too long */
740 unsigned char look_sym[1<<HUFF_LOOKAHEAD]; /* symbol, or unused */
743 #define QUANT_TABLE_LENGTH 64
745 /* for type of Huffman table */
746 #define DC_LEN 28
747 #define AC_LEN 178
749 struct huffman_table
750 { /* length and code according to JFIF format */
751 int huffmancodes_dc[DC_LEN];
752 int huffmancodes_ac[AC_LEN];
755 struct frame_component
757 int ID;
758 int horizontal_sampling;
759 int vertical_sampling;
760 int quanttable_select;
763 struct scan_component
765 int ID;
766 int DC_select;
767 int AC_select;
770 struct bitstream
772 unsigned long get_buffer; /* current bit-extraction buffer */
773 int bits_left; /* # of unused bits in it */
774 unsigned char* next_input_byte;
775 unsigned char* input_end; /* upper limit +1 */
778 struct jpeg
780 int x_size, y_size; /* size of image (can be less than block boundary) */
781 int x_phys, y_phys; /* physical size, block aligned */
782 int x_mbl; /* x dimension of MBL */
783 int y_mbl; /* y dimension of MBL */
784 int blocks; /* blocks per MB */
785 int restart_interval; /* number of MCUs between RSTm markers */
786 int store_pos[4]; /* for Y block ordering */
788 unsigned char* p_entropy_data;
789 unsigned char* p_entropy_end;
791 int quanttable[4][QUANT_TABLE_LENGTH]; /* raw quantization tables 0-3 */
792 int qt_idct[2][QUANT_TABLE_LENGTH]; /* quantization tables for IDCT */
794 struct huffman_table hufftable[2]; /* Huffman tables */
795 struct derived_tbl dc_derived_tbls[2]; /* Huffman-LUTs */
796 struct derived_tbl ac_derived_tbls[2];
798 struct frame_component frameheader[3]; /* Component descriptor */
799 struct scan_component scanheader[3]; /* currently not used */
801 int mcu_membership[6]; /* info per block */
802 int tab_membership[6];
803 int subsample_x[3]; /* info per component */
804 int subsample_y[3];
808 /* possible return flags for process_markers() */
809 #define HUFFTAB 0x0001 /* with huffman table */
810 #define QUANTTAB 0x0002 /* with quantization table */
811 #define APP0_JFIF 0x0004 /* with APP0 segment following JFIF standard */
812 #define FILL_FF 0x0008 /* with 0xFF padding bytes at begin/end */
813 #define SOF0 0x0010 /* with SOF0-Segment */
814 #define DHT 0x0020 /* with Definition of huffman tables */
815 #define SOS 0x0040 /* with Start-of-Scan segment */
816 #define DQT 0x0080 /* with definition of quantization table */
818 /* Preprocess the JPEG JFIF file */
819 int process_markers(unsigned char* p_src, long size, struct jpeg* p_jpeg)
821 unsigned char* p_bytes = p_src;
822 int marker_size; /* variable length of marker segment */
823 int i, j, n;
824 int ret = 0; /* returned flags */
826 p_jpeg->p_entropy_end = p_src + size;
828 while (p_src < p_bytes + size)
830 if (*p_src++ != 0xFF) /* no marker? */
832 p_src--; /* it's image data, put it back */
833 p_jpeg->p_entropy_data = p_src;
834 break; /* exit marker processing */
837 switch (*p_src++)
839 case 0xFF: /* Fill byte */
840 ret |= FILL_FF;
841 case 0x00: /* Zero stuffed byte - entropy data */
842 p_src--; /* put it back */
843 continue;
845 case 0xC0: /* SOF Huff - Baseline DCT */
847 ret |= SOF0;
848 marker_size = *p_src++ << 8; /* Highbyte */
849 marker_size |= *p_src++; /* Lowbyte */
850 n = *p_src++; /* sample precision (= 8 or 12) */
851 if (n != 8)
853 return(-1); /* Unsupported sample precision */
855 p_jpeg->y_size = *p_src++ << 8; /* Highbyte */
856 p_jpeg->y_size |= *p_src++; /* Lowbyte */
857 p_jpeg->x_size = *p_src++ << 8; /* Highbyte */
858 p_jpeg->x_size |= *p_src++; /* Lowbyte */
860 n = (marker_size-2-6)/3;
861 if (*p_src++ != n || (n != 1 && n != 3))
863 return(-2); /* Unsupported SOF0 component specification */
865 for (i=0; i<n; i++)
867 p_jpeg->frameheader[i].ID = *p_src++; /* Component info */
868 p_jpeg->frameheader[i].horizontal_sampling = *p_src >> 4;
869 p_jpeg->frameheader[i].vertical_sampling = *p_src++ & 0x0F;
870 p_jpeg->frameheader[i].quanttable_select = *p_src++;
871 if (p_jpeg->frameheader[i].horizontal_sampling > 2
872 || p_jpeg->frameheader[i].vertical_sampling > 2)
873 return -3; /* Unsupported SOF0 subsampling */
875 p_jpeg->blocks = n;
877 break;
879 case 0xC1: /* SOF Huff - Extended sequential DCT*/
880 case 0xC2: /* SOF Huff - Progressive DCT*/
881 case 0xC3: /* SOF Huff - Spatial (sequential) lossless*/
882 case 0xC5: /* SOF Huff - Differential sequential DCT*/
883 case 0xC6: /* SOF Huff - Differential progressive DCT*/
884 case 0xC7: /* SOF Huff - Differential spatial*/
885 case 0xC8: /* SOF Arith - Reserved for JPEG extensions*/
886 case 0xC9: /* SOF Arith - Extended sequential DCT*/
887 case 0xCA: /* SOF Arith - Progressive DCT*/
888 case 0xCB: /* SOF Arith - Spatial (sequential) lossless*/
889 case 0xCD: /* SOF Arith - Differential sequential DCT*/
890 case 0xCE: /* SOF Arith - Differential progressive DCT*/
891 case 0xCF: /* SOF Arith - Differential spatial*/
893 return (-4); /* other DCT model than baseline not implemented */
896 case 0xC4: /* Define Huffman Table(s) */
898 unsigned char* p_temp;
900 ret |= DHT;
901 marker_size = *p_src++ << 8; /* Highbyte */
902 marker_size |= *p_src++; /* Lowbyte */
904 p_temp = p_src;
905 while (p_src < p_temp+marker_size-2-17) /* another table */
907 int sum = 0;
908 i = *p_src & 0x0F; /* table index */
909 if (i > 1)
911 return (-5); /* Huffman table index out of range */
913 else if (*p_src++ & 0xF0) /* AC table */
915 for (j=0; j<16; j++)
917 sum += *p_src;
918 p_jpeg->hufftable[i].huffmancodes_ac[j] = *p_src++;
920 if(16 + sum > AC_LEN)
921 return -10; /* longer than allowed */
923 for (; j < 16 + sum; j++)
924 p_jpeg->hufftable[i].huffmancodes_ac[j] = *p_src++;
926 else /* DC table */
928 for (j=0; j<16; j++)
930 sum += *p_src;
931 p_jpeg->hufftable[i].huffmancodes_dc[j] = *p_src++;
933 if(16 + sum > DC_LEN)
934 return -11; /* longer than allowed */
936 for (; j < 16 + sum; j++)
937 p_jpeg->hufftable[i].huffmancodes_dc[j] = *p_src++;
939 } /* while */
940 p_src = p_temp+marker_size - 2; /* skip possible residue */
942 break;
944 case 0xCC: /* Define Arithmetic coding conditioning(s) */
945 return(-6); /* Arithmetic coding not supported */
947 case 0xD8: /* Start of Image */
948 case 0xD9: /* End of Image */
949 case 0x01: /* for temp private use arith code */
950 break; /* skip parameterless marker */
953 case 0xDA: /* Start of Scan */
955 ret |= SOS;
956 marker_size = *p_src++ << 8; /* Highbyte */
957 marker_size |= *p_src++; /* Lowbyte */
959 n = (marker_size-2-1-3)/2;
960 if (*p_src++ != n || (n != 1 && n != 3))
962 return (-7); /* Unsupported SOS component specification */
964 for (i=0; i<n; i++)
966 p_jpeg->scanheader[i].ID = *p_src++;
967 p_jpeg->scanheader[i].DC_select = *p_src >> 4;
968 p_jpeg->scanheader[i].AC_select = *p_src++ & 0x0F;
970 p_src += 3; /* skip spectral information */
972 break;
974 case 0xDB: /* Define quantization Table(s) */
976 ret |= DQT;
977 marker_size = *p_src++ << 8; /* Highbyte */
978 marker_size |= *p_src++; /* Lowbyte */
979 n = (marker_size-2)/(QUANT_TABLE_LENGTH+1); /* # of tables */
980 for (i=0; i<n; i++)
982 int id = *p_src++; /* ID */
983 if (id >= 4)
985 return (-8); /* Unsupported quantization table */
987 /* Read Quantisation table: */
988 for (j=0; j<QUANT_TABLE_LENGTH; j++)
989 p_jpeg->quanttable[id][j] = *p_src++;
992 break;
994 case 0xDD: /* Define Restart Interval */
996 marker_size = *p_src++ << 8; /* Highbyte */
997 marker_size |= *p_src++; /* Lowbyte */
998 p_jpeg->restart_interval = *p_src++ << 8; /* Highbyte */
999 p_jpeg->restart_interval |= *p_src++; /* Lowbyte */
1000 p_src += marker_size-4; /* skip segment */
1002 break;
1004 case 0xDC: /* Define Number of Lines */
1005 case 0xDE: /* Define Hierarchical progression */
1006 case 0xDF: /* Expand Reference Component(s) */
1007 case 0xE0: /* Application Field 0*/
1008 case 0xE1: /* Application Field 1*/
1009 case 0xE2: /* Application Field 2*/
1010 case 0xE3: /* Application Field 3*/
1011 case 0xE4: /* Application Field 4*/
1012 case 0xE5: /* Application Field 5*/
1013 case 0xE6: /* Application Field 6*/
1014 case 0xE7: /* Application Field 7*/
1015 case 0xE8: /* Application Field 8*/
1016 case 0xE9: /* Application Field 9*/
1017 case 0xEA: /* Application Field 10*/
1018 case 0xEB: /* Application Field 11*/
1019 case 0xEC: /* Application Field 12*/
1020 case 0xED: /* Application Field 13*/
1021 case 0xEE: /* Application Field 14*/
1022 case 0xEF: /* Application Field 15*/
1023 case 0xFE: /* Comment */
1025 marker_size = *p_src++ << 8; /* Highbyte */
1026 marker_size |= *p_src++; /* Lowbyte */
1027 p_src += marker_size-2; /* skip segment */
1029 break;
1031 case 0xF0: /* Reserved for JPEG extensions */
1032 case 0xF1: /* Reserved for JPEG extensions */
1033 case 0xF2: /* Reserved for JPEG extensions */
1034 case 0xF3: /* Reserved for JPEG extensions */
1035 case 0xF4: /* Reserved for JPEG extensions */
1036 case 0xF5: /* Reserved for JPEG extensions */
1037 case 0xF6: /* Reserved for JPEG extensions */
1038 case 0xF7: /* Reserved for JPEG extensions */
1039 case 0xF8: /* Reserved for JPEG extensions */
1040 case 0xF9: /* Reserved for JPEG extensions */
1041 case 0xFA: /* Reserved for JPEG extensions */
1042 case 0xFB: /* Reserved for JPEG extensions */
1043 case 0xFC: /* Reserved for JPEG extensions */
1044 case 0xFD: /* Reserved for JPEG extensions */
1045 case 0x02: /* Reserved */
1046 default:
1047 return (-9); /* Unknown marker */
1048 } /* switch */
1049 } /* while */
1051 return (ret); /* return flags with seen markers */
1055 void default_huff_tbl(struct jpeg* p_jpeg)
1057 static const struct huffman_table luma_table =
1060 0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,
1061 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B
1064 0x00,0x02,0x01,0x03,0x03,0x02,0x04,0x03,0x05,0x05,0x04,0x04,0x00,0x00,0x01,0x7D,
1065 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,
1066 0x22,0x71,0x14,0x32,0x81,0x91,0xA1,0x08,0x23,0x42,0xB1,0xC1,0x15,0x52,0xD1,0xF0,
1067 0x24,0x33,0x62,0x72,0x82,0x09,0x0A,0x16,0x17,0x18,0x19,0x1A,0x25,0x26,0x27,0x28,
1068 0x29,0x2A,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,
1069 0x4A,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,
1070 0x6A,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
1071 0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,
1072 0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xC2,0xC3,0xC4,0xC5,
1073 0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xE1,0xE2,
1074 0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,
1075 0xF9,0xFA
1079 static const struct huffman_table chroma_table =
1082 0x00,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,
1083 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B
1086 0x00,0x02,0x01,0x02,0x04,0x04,0x03,0x04,0x07,0x05,0x04,0x04,0x00,0x01,0x02,0x77,
1087 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,
1088 0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xA1,0xB1,0xC1,0x09,0x23,0x33,0x52,0xF0,
1089 0x15,0x62,0x72,0xD1,0x0A,0x16,0x24,0x34,0xE1,0x25,0xF1,0x17,0x18,0x19,0x1A,0x26,
1090 0x27,0x28,0x29,0x2A,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,
1091 0x49,0x4A,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,
1092 0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x82,0x83,0x84,0x85,0x86,0x87,
1093 0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5,
1094 0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xC2,0xC3,
1095 0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,
1096 0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,
1097 0xF9,0xFA
1101 MEMCPY(&p_jpeg->hufftable[0], &luma_table, sizeof(luma_table));
1102 MEMCPY(&p_jpeg->hufftable[1], &chroma_table, sizeof(chroma_table));
1104 return;
1107 /* Compute the derived values for a Huffman table */
1108 void fix_huff_tbl(int* htbl, struct derived_tbl* dtbl)
1110 int p, i, l, si;
1111 int lookbits, ctr;
1112 char huffsize[257];
1113 unsigned int huffcode[257];
1114 unsigned int code;
1116 dtbl->pub = htbl; /* fill in back link */
1118 /* Figure C.1: make table of Huffman code length for each symbol */
1119 /* Note that this is in code-length order. */
1121 p = 0;
1122 for (l = 1; l <= 16; l++)
1123 { /* all possible code length */
1124 for (i = 1; i <= (int) htbl[l-1]; i++) /* all codes per length */
1125 huffsize[p++] = (char) l;
1127 huffsize[p] = 0;
1129 /* Figure C.2: generate the codes themselves */
1130 /* Note that this is in code-length order. */
1132 code = 0;
1133 si = huffsize[0];
1134 p = 0;
1135 while (huffsize[p])
1137 while (((int) huffsize[p]) == si)
1139 huffcode[p++] = code;
1140 code++;
1142 code <<= 1;
1143 si++;
1146 /* Figure F.15: generate decoding tables for bit-sequential decoding */
1148 p = 0;
1149 for (l = 1; l <= 16; l++)
1151 if (htbl[l-1])
1153 dtbl->valptr[l] = p; /* huffval[] index of 1st symbol of code length l */
1154 dtbl->mincode[l] = huffcode[p]; /* minimum code of length l */
1155 p += htbl[l-1];
1156 dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */
1158 else
1160 dtbl->maxcode[l] = -1; /* -1 if no codes of this length */
1163 dtbl->maxcode[17] = 0xFFFFFL; /* ensures huff_DECODE terminates */
1165 /* Compute lookahead tables to speed up decoding.
1166 * First we set all the table entries to 0, indicating "too long";
1167 * then we iterate through the Huffman codes that are short enough and
1168 * fill in all the entries that correspond to bit sequences starting
1169 * with that code.
1172 MEMSET(dtbl->look_nbits, 0, sizeof(dtbl->look_nbits));
1174 p = 0;
1175 for (l = 1; l <= HUFF_LOOKAHEAD; l++)
1177 for (i = 1; i <= (int) htbl[l-1]; i++, p++)
1179 /* l = current code's length, p = its index in huffcode[] & huffval[]. */
1180 /* Generate left-justified code followed by all possible bit sequences */
1181 lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l);
1182 for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--)
1184 dtbl->look_nbits[lookbits] = l;
1185 dtbl->look_sym[lookbits] = htbl[16+p];
1186 lookbits++;
1193 /* zag[i] is the natural-order position of the i'th element of zigzag order.
1194 * If the incoming data is corrupted, decode_mcu could attempt to
1195 * reference values beyond the end of the array. To avoid a wild store,
1196 * we put some extra zeroes after the real entries.
1198 static const int zag[] =
1200 0, 1, 8, 16, 9, 2, 3, 10,
1201 17, 24, 32, 25, 18, 11, 4, 5,
1202 12, 19, 26, 33, 40, 48, 41, 34,
1203 27, 20, 13, 6, 7, 14, 21, 28,
1204 35, 42, 49, 56, 57, 50, 43, 36,
1205 29, 22, 15, 23, 30, 37, 44, 51,
1206 58, 59, 52, 45, 38, 31, 39, 46,
1207 53, 60, 61, 54, 47, 55, 62, 63,
1208 0, 0, 0, 0, 0, 0, 0, 0, /* extra entries in case k>63 below */
1209 0, 0, 0, 0, 0, 0, 0, 0
1212 void build_lut(struct jpeg* p_jpeg)
1214 int i;
1215 fix_huff_tbl(p_jpeg->hufftable[0].huffmancodes_dc,
1216 &p_jpeg->dc_derived_tbls[0]);
1217 fix_huff_tbl(p_jpeg->hufftable[0].huffmancodes_ac,
1218 &p_jpeg->ac_derived_tbls[0]);
1219 fix_huff_tbl(p_jpeg->hufftable[1].huffmancodes_dc,
1220 &p_jpeg->dc_derived_tbls[1]);
1221 fix_huff_tbl(p_jpeg->hufftable[1].huffmancodes_ac,
1222 &p_jpeg->ac_derived_tbls[1]);
1224 /* build the dequantization tables for the IDCT (De-ZiZagged) */
1225 for (i=0; i<64; i++)
1227 p_jpeg->qt_idct[0][zag[i]] = p_jpeg->quanttable[0][i];
1228 p_jpeg->qt_idct[1][zag[i]] = p_jpeg->quanttable[1][i];
1231 for (i=0; i<4; i++)
1232 p_jpeg->store_pos[i] = i; /* default ordering */
1234 /* assignments for the decoding of blocks */
1235 if (p_jpeg->frameheader[0].horizontal_sampling == 2
1236 && p_jpeg->frameheader[0].vertical_sampling == 1)
1237 { /* 4:2:2 */
1238 p_jpeg->blocks = 4;
1239 p_jpeg->x_mbl = (p_jpeg->x_size+15) / 16;
1240 p_jpeg->x_phys = p_jpeg->x_mbl * 16;
1241 p_jpeg->y_mbl = (p_jpeg->y_size+7) / 8;
1242 p_jpeg->y_phys = p_jpeg->y_mbl * 8;
1243 p_jpeg->mcu_membership[0] = 0; /* Y1=Y2=0, U=1, V=2 */
1244 p_jpeg->mcu_membership[1] = 0;
1245 p_jpeg->mcu_membership[2] = 1;
1246 p_jpeg->mcu_membership[3] = 2;
1247 p_jpeg->tab_membership[0] = 0; /* DC, DC, AC, AC */
1248 p_jpeg->tab_membership[1] = 0;
1249 p_jpeg->tab_membership[2] = 1;
1250 p_jpeg->tab_membership[3] = 1;
1251 p_jpeg->subsample_x[0] = 1;
1252 p_jpeg->subsample_x[1] = 2;
1253 p_jpeg->subsample_x[2] = 2;
1254 p_jpeg->subsample_y[0] = 1;
1255 p_jpeg->subsample_y[1] = 1;
1256 p_jpeg->subsample_y[2] = 1;
1258 if (p_jpeg->frameheader[0].horizontal_sampling == 1
1259 && p_jpeg->frameheader[0].vertical_sampling == 2)
1260 { /* 4:2:2 vertically subsampled */
1261 p_jpeg->store_pos[1] = 2; /* block positions are mirrored */
1262 p_jpeg->store_pos[2] = 1;
1263 p_jpeg->blocks = 4;
1264 p_jpeg->x_mbl = (p_jpeg->x_size+7) / 8;
1265 p_jpeg->x_phys = p_jpeg->x_mbl * 8;
1266 p_jpeg->y_mbl = (p_jpeg->y_size+15) / 16;
1267 p_jpeg->y_phys = p_jpeg->y_mbl * 16;
1268 p_jpeg->mcu_membership[0] = 0; /* Y1=Y2=0, U=1, V=2 */
1269 p_jpeg->mcu_membership[1] = 0;
1270 p_jpeg->mcu_membership[2] = 1;
1271 p_jpeg->mcu_membership[3] = 2;
1272 p_jpeg->tab_membership[0] = 0; /* DC, DC, AC, AC */
1273 p_jpeg->tab_membership[1] = 0;
1274 p_jpeg->tab_membership[2] = 1;
1275 p_jpeg->tab_membership[3] = 1;
1276 p_jpeg->subsample_x[0] = 1;
1277 p_jpeg->subsample_x[1] = 1;
1278 p_jpeg->subsample_x[2] = 1;
1279 p_jpeg->subsample_y[0] = 1;
1280 p_jpeg->subsample_y[1] = 2;
1281 p_jpeg->subsample_y[2] = 2;
1283 else if (p_jpeg->frameheader[0].horizontal_sampling == 2
1284 && p_jpeg->frameheader[0].vertical_sampling == 2)
1285 { /* 4:2:0 */
1286 p_jpeg->blocks = 6;
1287 p_jpeg->x_mbl = (p_jpeg->x_size+15) / 16;
1288 p_jpeg->x_phys = p_jpeg->x_mbl * 16;
1289 p_jpeg->y_mbl = (p_jpeg->y_size+15) / 16;
1290 p_jpeg->y_phys = p_jpeg->y_mbl * 16;
1291 p_jpeg->mcu_membership[0] = 0;
1292 p_jpeg->mcu_membership[1] = 0;
1293 p_jpeg->mcu_membership[2] = 0;
1294 p_jpeg->mcu_membership[3] = 0;
1295 p_jpeg->mcu_membership[4] = 1;
1296 p_jpeg->mcu_membership[5] = 2;
1297 p_jpeg->tab_membership[0] = 0;
1298 p_jpeg->tab_membership[1] = 0;
1299 p_jpeg->tab_membership[2] = 0;
1300 p_jpeg->tab_membership[3] = 0;
1301 p_jpeg->tab_membership[4] = 1;
1302 p_jpeg->tab_membership[5] = 1;
1303 p_jpeg->subsample_x[0] = 1;
1304 p_jpeg->subsample_x[1] = 2;
1305 p_jpeg->subsample_x[2] = 2;
1306 p_jpeg->subsample_y[0] = 1;
1307 p_jpeg->subsample_y[1] = 2;
1308 p_jpeg->subsample_y[2] = 2;
1310 else if (p_jpeg->frameheader[0].horizontal_sampling == 1
1311 && p_jpeg->frameheader[0].vertical_sampling == 1)
1312 { /* 4:4:4 */
1313 /* don't overwrite p_jpeg->blocks */
1314 p_jpeg->x_mbl = (p_jpeg->x_size+7) / 8;
1315 p_jpeg->x_phys = p_jpeg->x_mbl * 8;
1316 p_jpeg->y_mbl = (p_jpeg->y_size+7) / 8;
1317 p_jpeg->y_phys = p_jpeg->y_mbl * 8;
1318 p_jpeg->mcu_membership[0] = 0;
1319 p_jpeg->mcu_membership[1] = 1;
1320 p_jpeg->mcu_membership[2] = 2;
1321 p_jpeg->tab_membership[0] = 0;
1322 p_jpeg->tab_membership[1] = 1;
1323 p_jpeg->tab_membership[2] = 1;
1324 p_jpeg->subsample_x[0] = 1;
1325 p_jpeg->subsample_x[1] = 1;
1326 p_jpeg->subsample_x[2] = 1;
1327 p_jpeg->subsample_y[0] = 1;
1328 p_jpeg->subsample_y[1] = 1;
1329 p_jpeg->subsample_y[2] = 1;
1331 else
1333 /* error */
1340 * These functions/macros provide the in-line portion of bit fetching.
1341 * Use check_bit_buffer to ensure there are N bits in get_buffer
1342 * before using get_bits, peek_bits, or drop_bits.
1343 * check_bit_buffer(state,n,action);
1344 * Ensure there are N bits in get_buffer; if suspend, take action.
1345 * val = get_bits(n);
1346 * Fetch next N bits.
1347 * val = peek_bits(n);
1348 * Fetch next N bits without removing them from the buffer.
1349 * drop_bits(n);
1350 * Discard next N bits.
1351 * The value N should be a simple variable, not an expression, because it
1352 * is evaluated multiple times.
1355 INLINE void check_bit_buffer(struct bitstream* pb, int nbits)
1357 if (pb->bits_left < nbits)
1358 { /* nbits is <= 16, so I can always refill 2 bytes in this case */
1359 unsigned char byte;
1361 byte = *pb->next_input_byte++;
1362 if (byte == 0xFF) /* legal marker can be byte stuffing or RSTm */
1363 { /* simplification: just skip the (one-byte) marker code */
1364 pb->next_input_byte++;
1366 pb->get_buffer = (pb->get_buffer << 8) | byte;
1368 byte = *pb->next_input_byte++;
1369 if (byte == 0xFF) /* legal marker can be byte stuffing or RSTm */
1370 { /* simplification: just skip the (one-byte) marker code */
1371 pb->next_input_byte++;
1373 pb->get_buffer = (pb->get_buffer << 8) | byte;
1375 pb->bits_left += 16;
1379 INLINE int get_bits(struct bitstream* pb, int nbits)
1381 return ((int) (pb->get_buffer >> (pb->bits_left -= nbits))) & ((1<<nbits)-1);
1384 INLINE int peek_bits(struct bitstream* pb, int nbits)
1386 return ((int) (pb->get_buffer >> (pb->bits_left - nbits))) & ((1<<nbits)-1);
1389 INLINE void drop_bits(struct bitstream* pb, int nbits)
1391 pb->bits_left -= nbits;
1394 /* re-synchronize to entropy data (skip restart marker) */
1395 void search_restart(struct bitstream* pb)
1397 pb->next_input_byte--; /* we may have overread it, taking 2 bytes */
1398 /* search for a non-byte-padding marker, has to be RSTm or EOS */
1399 while (pb->next_input_byte < pb->input_end &&
1400 (pb->next_input_byte[-2] != 0xFF || pb->next_input_byte[-1] == 0x00))
1402 pb->next_input_byte++;
1404 pb->bits_left = 0;
1407 /* Figure F.12: extend sign bit. */
1408 #define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
1410 static const int extend_test[16] = /* entry n is 2**(n-1) */
1412 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
1413 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000
1416 static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
1418 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
1419 ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
1420 ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
1421 ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1
1424 /* Decode a single value */
1425 INLINE int huff_decode_dc(struct bitstream* bs, struct derived_tbl* tbl)
1427 int nb, look, s, r;
1429 check_bit_buffer(bs, HUFF_LOOKAHEAD);
1430 look = peek_bits(bs, HUFF_LOOKAHEAD);
1431 if ((nb = tbl->look_nbits[look]) != 0)
1433 drop_bits(bs, nb);
1434 s = tbl->look_sym[look];
1435 check_bit_buffer(bs, s);
1436 r = get_bits(bs, s);
1437 s = HUFF_EXTEND(r, s);
1439 else
1440 { /* slow_DECODE(s, HUFF_LOOKAHEAD+1)) < 0); */
1441 long code;
1442 nb=HUFF_LOOKAHEAD+1;
1443 check_bit_buffer(bs, nb);
1444 code = get_bits(bs, nb);
1445 while (code > tbl->maxcode[nb])
1447 code <<= 1;
1448 check_bit_buffer(bs, 1);
1449 code |= get_bits(bs, 1);
1450 nb++;
1452 if (nb > 16) /* error in Huffman */
1454 s=0; /* fake a zero, this is most safe */
1456 else
1458 s = tbl->pub[16 + tbl->valptr[nb] + ((int) (code - tbl->mincode[nb])) ];
1459 check_bit_buffer(bs, s);
1460 r = get_bits(bs, s);
1461 s = HUFF_EXTEND(r, s);
1463 } /* end slow decode */
1464 return s;
1467 INLINE int huff_decode_ac(struct bitstream* bs, struct derived_tbl* tbl)
1469 int nb, look, s;
1471 check_bit_buffer(bs, HUFF_LOOKAHEAD);
1472 look = peek_bits(bs, HUFF_LOOKAHEAD);
1473 if ((nb = tbl->look_nbits[look]) != 0)
1475 drop_bits(bs, nb);
1476 s = tbl->look_sym[look];
1478 else
1479 { /* slow_DECODE(s, HUFF_LOOKAHEAD+1)) < 0); */
1480 long code;
1481 nb=HUFF_LOOKAHEAD+1;
1482 check_bit_buffer(bs, nb);
1483 code = get_bits(bs, nb);
1484 while (code > tbl->maxcode[nb])
1486 code <<= 1;
1487 check_bit_buffer(bs, 1);
1488 code |= get_bits(bs, 1);
1489 nb++;
1491 if (nb > 16) /* error in Huffman */
1493 s=0; /* fake a zero, this is most safe */
1495 else
1497 s = tbl->pub[16 + tbl->valptr[nb] + ((int) (code - tbl->mincode[nb])) ];
1499 } /* end slow decode */
1500 return s;
1504 #ifdef HAVE_LCD_COLOR
1506 /* JPEG decoder variant for YUV decoding, into 3 different planes */
1507 /* Note: it keeps the original color subsampling, even if resized. */
1508 int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel[3],
1509 int downscale, void (*pf_progress)(int current, int total))
1511 struct bitstream bs; /* bitstream "object" */
1512 int block[64]; /* decoded DCT coefficients */
1514 int width, height;
1515 int skip_line[3]; /* bytes from one line to the next (skip_line) */
1516 int skip_strip[3], skip_mcu[3]; /* bytes to next DCT row / column */
1518 int i, x, y; /* loop counter */
1520 unsigned char* p_line[3] = {p_pixel[0], p_pixel[1], p_pixel[2]};
1521 unsigned char* p_byte[3]; /* bitmap pointer */
1523 void (*pf_idct)(unsigned char*, int*, int*, int); /* selected IDCT */
1524 int k_need; /* AC coefficients needed up to here */
1525 int zero_need; /* init the block with this many zeros */
1527 int last_dc_val[3] = {0, 0, 0}; /* or 128 for chroma? */
1528 int store_offs[4]; /* memory offsets: order of Y11 Y12 Y21 Y22 U V */
1529 int restart = p_jpeg->restart_interval; /* MCUs until restart marker */
1531 /* pick the IDCT we want, determine how to work with coefs */
1532 if (downscale == 1)
1534 pf_idct = idct8x8;
1535 k_need = 64; /* all */
1536 zero_need = 63; /* all */
1538 else if (downscale == 2)
1540 pf_idct = idct4x4;
1541 k_need = 25; /* this far in zig-zag to cover 4*4 */
1542 zero_need = 27; /* clear this far in linear order */
1544 else if (downscale == 4)
1546 pf_idct = idct2x2;
1547 k_need = 5; /* this far in zig-zag to cover 2*2 */
1548 zero_need = 9; /* clear this far in linear order */
1550 else if (downscale == 8)
1552 pf_idct = idct1x1;
1553 k_need = 0; /* no AC, not needed */
1554 zero_need = 0; /* no AC, not needed */
1556 else return -1; /* not supported */
1558 /* init bitstream, fake a restart to make it start */
1559 bs.next_input_byte = p_jpeg->p_entropy_data;
1560 bs.bits_left = 0;
1561 bs.input_end = p_jpeg->p_entropy_end;
1563 width = p_jpeg->x_phys / downscale;
1564 height = p_jpeg->y_phys / downscale;
1565 for (i=0; i<3; i++) /* calculate some strides */
1567 skip_line[i] = width / p_jpeg->subsample_x[i];
1568 skip_strip[i] = skip_line[i]
1569 * (height / p_jpeg->y_mbl) / p_jpeg->subsample_y[i];
1570 skip_mcu[i] = width/p_jpeg->x_mbl / p_jpeg->subsample_x[i];
1573 /* prepare offsets about where to store the different blocks */
1574 store_offs[p_jpeg->store_pos[0]] = 0;
1575 store_offs[p_jpeg->store_pos[1]] = 8 / downscale; /* to the right */
1576 store_offs[p_jpeg->store_pos[2]] = width * 8 / downscale; /* below */
1577 store_offs[p_jpeg->store_pos[3]] = store_offs[1] + store_offs[2]; /* r+b */
1579 for(y=0; y<p_jpeg->y_mbl && bs.next_input_byte <= bs.input_end; y++)
1581 for (i=0; i<3; i++) /* scan line init */
1583 p_byte[i] = p_line[i];
1584 p_line[i] += skip_strip[i];
1586 for (x=0; x<p_jpeg->x_mbl; x++)
1588 int blkn;
1590 /* Outer loop handles each block in the MCU */
1591 for (blkn = 0; blkn < p_jpeg->blocks; blkn++)
1592 { /* Decode a single block's worth of coefficients */
1593 int k = 1; /* coefficient index */
1594 int s, r; /* huffman values */
1595 int ci = p_jpeg->mcu_membership[blkn]; /* component index */
1596 int ti = p_jpeg->tab_membership[blkn]; /* table index */
1597 struct derived_tbl* dctbl = &p_jpeg->dc_derived_tbls[ti];
1598 struct derived_tbl* actbl = &p_jpeg->ac_derived_tbls[ti];
1600 /* Section F.2.2.1: decode the DC coefficient difference */
1601 s = huff_decode_dc(&bs, dctbl);
1603 last_dc_val[ci] += s;
1604 block[0] = last_dc_val[ci]; /* output it (assumes zag[0] = 0) */
1606 /* coefficient buffer must be cleared */
1607 MEMSET(block+1, 0, zero_need*sizeof(block[0]));
1609 /* Section F.2.2.2: decode the AC coefficients */
1610 for (; k < k_need; k++)
1612 s = huff_decode_ac(&bs, actbl);
1613 r = s >> 4;
1614 s &= 15;
1616 if (s)
1618 k += r;
1619 check_bit_buffer(&bs, s);
1620 r = get_bits(&bs, s);
1621 block[zag[k]] = HUFF_EXTEND(r, s);
1623 else
1625 if (r != 15)
1627 k = 64;
1628 break;
1630 k += r;
1632 } /* for k */
1633 /* In this path we just discard the values */
1634 for (; k < 64; k++)
1636 s = huff_decode_ac(&bs, actbl);
1637 r = s >> 4;
1638 s &= 15;
1640 if (s)
1642 k += r;
1643 check_bit_buffer(&bs, s);
1644 drop_bits(&bs, s);
1646 else
1648 if (r != 15)
1649 break;
1650 k += r;
1652 } /* for k */
1654 if (ci == 0)
1655 { /* Y component needs to bother about block store */
1656 pf_idct(p_byte[0]+store_offs[blkn], block,
1657 p_jpeg->qt_idct[ti], skip_line[0]);
1659 else
1660 { /* chroma */
1661 pf_idct(p_byte[ci], block, p_jpeg->qt_idct[ti],
1662 skip_line[ci]);
1664 } /* for blkn */
1665 p_byte[0] += skip_mcu[0]; /* unrolled for (i=0; i<3; i++) loop */
1666 p_byte[1] += skip_mcu[1];
1667 p_byte[2] += skip_mcu[2];
1668 if (p_jpeg->restart_interval && --restart == 0)
1669 { /* if a restart marker is due: */
1670 restart = p_jpeg->restart_interval; /* count again */
1671 search_restart(&bs); /* align the bitstream */
1672 last_dc_val[0] = last_dc_val[1] =
1673 last_dc_val[2] = 0; /* reset decoder */
1675 } /* for x */
1676 if (pf_progress != NULL)
1677 pf_progress(y, p_jpeg->y_mbl-1); /* notify about decoding progress */
1678 } /* for y */
1680 return 0; /* success */
1682 #else /* !HAVE_LCD_COLOR */
1684 /* a JPEG decoder specialized in decoding only the luminance (b&w) */
1685 int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel[1], int downscale,
1686 void (*pf_progress)(int current, int total))
1688 struct bitstream bs; /* bitstream "object" */
1689 int block[64]; /* decoded DCT coefficients */
1691 int width, height;
1692 int skip_line; /* bytes from one line to the next (skip_line) */
1693 int skip_strip, skip_mcu; /* bytes to next DCT row / column */
1695 int x, y; /* loop counter */
1697 unsigned char* p_line = p_pixel[0];
1698 unsigned char* p_byte; /* bitmap pointer */
1700 void (*pf_idct)(unsigned char*, int*, int*, int); /* selected IDCT */
1701 int k_need; /* AC coefficients needed up to here */
1702 int zero_need; /* init the block with this many zeros */
1704 int last_dc_val = 0;
1705 int store_offs[4]; /* memory offsets: order of Y11 Y12 Y21 Y22 U V */
1706 int restart = p_jpeg->restart_interval; /* MCUs until restart marker */
1708 /* pick the IDCT we want, determine how to work with coefs */
1709 if (downscale == 1)
1711 pf_idct = idct8x8;
1712 k_need = 64; /* all */
1713 zero_need = 63; /* all */
1715 else if (downscale == 2)
1717 pf_idct = idct4x4;
1718 k_need = 25; /* this far in zig-zag to cover 4*4 */
1719 zero_need = 27; /* clear this far in linear order */
1721 else if (downscale == 4)
1723 pf_idct = idct2x2;
1724 k_need = 5; /* this far in zig-zag to cover 2*2 */
1725 zero_need = 9; /* clear this far in linear order */
1727 else if (downscale == 8)
1729 pf_idct = idct1x1;
1730 k_need = 0; /* no AC, not needed */
1731 zero_need = 0; /* no AC, not needed */
1733 else return -1; /* not supported */
1735 /* init bitstream, fake a restart to make it start */
1736 bs.next_input_byte = p_jpeg->p_entropy_data;
1737 bs.bits_left = 0;
1738 bs.input_end = p_jpeg->p_entropy_end;
1740 width = p_jpeg->x_phys / downscale;
1741 height = p_jpeg->y_phys / downscale;
1742 skip_line = width;
1743 skip_strip = skip_line * (height / p_jpeg->y_mbl);
1744 skip_mcu = (width/p_jpeg->x_mbl);
1746 /* prepare offsets about where to store the different blocks */
1747 store_offs[p_jpeg->store_pos[0]] = 0;
1748 store_offs[p_jpeg->store_pos[1]] = 8 / downscale; /* to the right */
1749 store_offs[p_jpeg->store_pos[2]] = width * 8 / downscale; /* below */
1750 store_offs[p_jpeg->store_pos[3]] = store_offs[1] + store_offs[2]; /* r+b */
1752 for(y=0; y<p_jpeg->y_mbl && bs.next_input_byte <= bs.input_end; y++)
1754 p_byte = p_line;
1755 p_line += skip_strip;
1756 for (x=0; x<p_jpeg->x_mbl; x++)
1758 int blkn;
1760 /* Outer loop handles each block in the MCU */
1761 for (blkn = 0; blkn < p_jpeg->blocks; blkn++)
1762 { /* Decode a single block's worth of coefficients */
1763 int k = 1; /* coefficient index */
1764 int s, r; /* huffman values */
1765 int ci = p_jpeg->mcu_membership[blkn]; /* component index */
1766 int ti = p_jpeg->tab_membership[blkn]; /* table index */
1767 struct derived_tbl* dctbl = &p_jpeg->dc_derived_tbls[ti];
1768 struct derived_tbl* actbl = &p_jpeg->ac_derived_tbls[ti];
1770 /* Section F.2.2.1: decode the DC coefficient difference */
1771 s = huff_decode_dc(&bs, dctbl);
1773 if (ci == 0) /* only for Y component */
1775 last_dc_val += s;
1776 block[0] = last_dc_val; /* output it (assumes zag[0] = 0) */
1778 /* coefficient buffer must be cleared */
1779 MEMSET(block+1, 0, zero_need*sizeof(block[0]));
1781 /* Section F.2.2.2: decode the AC coefficients */
1782 for (; k < k_need; k++)
1784 s = huff_decode_ac(&bs, actbl);
1785 r = s >> 4;
1786 s &= 15;
1788 if (s)
1790 k += r;
1791 check_bit_buffer(&bs, s);
1792 r = get_bits(&bs, s);
1793 block[zag[k]] = HUFF_EXTEND(r, s);
1795 else
1797 if (r != 15)
1799 k = 64;
1800 break;
1802 k += r;
1804 } /* for k */
1806 /* In this path we just discard the values */
1807 for (; k < 64; k++)
1809 s = huff_decode_ac(&bs, actbl);
1810 r = s >> 4;
1811 s &= 15;
1813 if (s)
1815 k += r;
1816 check_bit_buffer(&bs, s);
1817 drop_bits(&bs, s);
1819 else
1821 if (r != 15)
1822 break;
1823 k += r;
1825 } /* for k */
1827 if (ci == 0)
1828 { /* only for Y component */
1829 pf_idct(p_byte+store_offs[blkn], block, p_jpeg->qt_idct[ti],
1830 skip_line);
1832 } /* for blkn */
1833 p_byte += skip_mcu;
1834 if (p_jpeg->restart_interval && --restart == 0)
1835 { /* if a restart marker is due: */
1836 restart = p_jpeg->restart_interval; /* count again */
1837 search_restart(&bs); /* align the bitstream */
1838 last_dc_val = 0; /* reset decoder */
1840 } /* for x */
1841 if (pf_progress != NULL)
1842 pf_progress(y, p_jpeg->y_mbl-1); /* notify about decoding progress */
1843 } /* for y */
1845 return 0; /* success */
1847 #endif /* !HAVE_LCD_COLOR */
1849 /**************** end JPEG code ********************/
1853 /**************** begin Application ********************/
1856 /************************* Types ***************************/
1858 struct t_disp
1860 #ifdef HAVE_LCD_COLOR
1861 unsigned char* bitmap[3]; /* Y, Cr, Cb */
1862 int csub_x, csub_y;
1863 #else
1864 unsigned char* bitmap[1]; /* Y only */
1865 #endif
1866 int width;
1867 int height;
1868 int stride;
1869 int x, y;
1872 /************************* Globals ***************************/
1874 /* decompressed image in the possible sizes (1,2,4,8), wasting the other */
1875 struct t_disp disp[9];
1877 /* my memory pool (from the mp3 buffer) */
1878 char print[32]; /* use a common snprintf() buffer */
1879 unsigned char* buf; /* up to here currently used by image(s) */
1881 /* the remaining free part of the buffer for compressed+uncompressed images */
1882 unsigned char* buf_images;
1884 ssize_t buf_size, buf_images_size;
1885 /* the root of the images, hereafter are decompresed ones */
1886 unsigned char* buf_root;
1887 int root_size;
1889 int ds, ds_min, ds_max; /* downscaling and limits */
1890 static struct jpeg jpg; /* too large for stack */
1892 static struct tree_context *tree;
1894 /* the current full file name */
1895 static char np_file[MAX_PATH];
1896 int curfile = 0, direction = DIR_NONE, entries = 0;
1898 /* list of the jpeg files */
1899 char **file_pt;
1900 /* are we using the plugin buffer or the audio buffer? */
1901 bool plug_buf = false;
1904 /************************* Implementation ***************************/
1906 #ifdef HAVE_LCD_COLOR
1908 * Conversion of full 0-255 range YCrCb to RGB:
1909 * |R| |1.000000 -0.000001 1.402000| |Y'|
1910 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
1911 * |B| |1.000000 1.772000 0.000000| |Pr|
1912 * Scaled (yields s15-bit output):
1913 * |R| |128 0 179| |Y |
1914 * |G| = |128 -43 -91| |Cb - 128|
1915 * |B| |128 227 0| |Cr - 128|
1917 #define YFAC 128
1918 #define RVFAC 179
1919 #define GUFAC (-43)
1920 #define GVFAC (-91)
1921 #define BUFAC 227
1922 #define YUV_WHITE (255*YFAC)
1923 #define NODITHER_DELTA (127*YFAC)
1924 #define COMPONENT_SHIFT 15
1925 #define MATRIX_SHIFT 7
1927 static inline int clamp_component(int x)
1929 if ((unsigned)x > YUV_WHITE)
1930 x = x < 0 ? 0 : YUV_WHITE;
1931 return x;
1934 static inline int clamp_component_bits(int x, int bits)
1936 if ((unsigned)x > (1u << bits) - 1)
1937 x = x < 0 ? 0 : (1 << bits) - 1;
1938 return x;
1941 static inline int component_to_lcd(int x, int bits, int delta)
1943 /* Formula used in core bitmap loader. */
1944 return (((1 << bits) - 1)*x + (x >> (8 - bits)) + delta) >> COMPONENT_SHIFT;
1947 static inline int lcd_to_component(int x, int bits, int delta)
1949 /* Reasonable, approximate reversal to get a full range back from the
1950 quantized value. */
1951 return YUV_WHITE*x / ((1 << bits) - 1);
1952 (void)delta;
1955 #define RED 0
1956 #define GRN 1
1957 #define BLU 2
1959 struct rgb_err
1961 int16_t errbuf[LCD_WIDTH+2]; /* Error record for line below */
1962 } rgb_err_buffers[3];
1964 fb_data rgb_linebuf[LCD_WIDTH]; /* Line buffer for scrolling when
1965 DITHER_DIFFUSION is set */
1967 struct rgb_pixel
1969 int r, g, b; /* Current pixel components in s16.0 */
1970 int inc; /* Current line increment (-1 or 1) */
1971 int row; /* Current row in source image */
1972 int col; /* Current column in source image */
1973 int ce[3]; /* Errors to apply to current pixel */
1974 struct rgb_err *e; /* RED, GRN, BLU */
1975 int epos; /* Current position in error record */
1978 struct rgb_pixel *pixel;
1980 /** round and truncate to lcd depth **/
1981 static fb_data pixel_to_lcd_colour(void)
1983 struct rgb_pixel *p = pixel;
1984 int r, g, b;
1986 r = component_to_lcd(p->r, LCD_RED_BITS, NODITHER_DELTA);
1987 r = clamp_component_bits(r, LCD_RED_BITS);
1989 g = component_to_lcd(p->g, LCD_GREEN_BITS, NODITHER_DELTA);
1990 g = clamp_component_bits(g, LCD_GREEN_BITS);
1992 b = component_to_lcd(p->b, LCD_BLUE_BITS, NODITHER_DELTA);
1993 b = clamp_component_bits(b, LCD_BLUE_BITS);
1995 return LCD_RGBPACK_LCD(r, g, b);
1998 /** write a monochrome pixel to the colour LCD **/
1999 static fb_data pixel_to_lcd_gray(void)
2001 int r, g, b;
2003 g = clamp_component(pixel->g);
2004 r = component_to_lcd(g, LCD_RED_BITS, NODITHER_DELTA);
2005 b = component_to_lcd(g, LCD_BLUE_BITS, NODITHER_DELTA);
2006 g = component_to_lcd(g, LCD_GREEN_BITS, NODITHER_DELTA);
2008 return LCD_RGBPACK_LCD(r, g, b);
2012 * Bayer ordered dithering - swiped from the core bitmap loader.
2014 static fb_data pixel_odither_to_lcd(void)
2016 /* canonical ordered dither matrix */
2017 static const unsigned char dither_matrix[16][16] = {
2018 { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 },
2019 { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 },
2020 { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 },
2021 { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 },
2022 { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 },
2023 { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 },
2024 { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 },
2025 { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 },
2026 { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 },
2027 { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 },
2028 { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 },
2029 { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 },
2030 { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 },
2031 { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 },
2032 { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 },
2033 { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 }
2036 struct rgb_pixel *p = pixel;
2037 int r, g, b, delta;
2039 delta = dither_matrix[p->col & 15][p->row & 15] << MATRIX_SHIFT;
2041 r = component_to_lcd(p->r, LCD_RED_BITS, delta);
2042 r = clamp_component_bits(r, LCD_RED_BITS);
2044 g = component_to_lcd(p->g, LCD_GREEN_BITS, delta);
2045 g = clamp_component_bits(g, LCD_GREEN_BITS);
2047 b = component_to_lcd(p->b, LCD_BLUE_BITS, delta);
2048 b = clamp_component_bits(b, LCD_BLUE_BITS);
2050 p->col += p->inc;
2052 return LCD_RGBPACK_LCD(r, g, b);
2056 * Floyd/Steinberg dither to lcd depth.
2058 * Apply filter to each component in serpentine pattern. Kernel shown for
2059 * L->R scan. Kernel is reversed for R->L.
2060 * * 7
2061 * 3 5 1 (1/16)
2063 static inline void distribute_error(int *ce, struct rgb_err *e,
2064 int err, int epos, int inc)
2066 *ce = (7*err >> 4) + e->errbuf[epos+inc];
2067 e->errbuf[epos+inc] = err >> 4;
2068 e->errbuf[epos] += 5*err >> 4;
2069 e->errbuf[epos-inc] += 3*err >> 4;
2072 static fb_data pixel_fsdither_to_lcd(void)
2074 struct rgb_pixel *p = pixel;
2075 int rc, gc, bc, r, g, b;
2076 int inc, epos;
2078 /* Full components with error terms */
2079 rc = p->r + p->ce[RED];
2080 r = component_to_lcd(rc, LCD_RED_BITS, 0);
2081 r = clamp_component_bits(r, LCD_RED_BITS);
2083 gc = p->g + p->ce[GRN];
2084 g = component_to_lcd(gc, LCD_GREEN_BITS, 0);
2085 g = clamp_component_bits(g, LCD_GREEN_BITS);
2087 bc = p->b + p->ce[BLU];
2088 b = component_to_lcd(bc, LCD_BLUE_BITS, 0);
2089 b = clamp_component_bits(b, LCD_BLUE_BITS);
2091 /* Get pixel errors */
2092 rc -= lcd_to_component(r, LCD_RED_BITS, 0);
2093 gc -= lcd_to_component(g, LCD_GREEN_BITS, 0);
2094 bc -= lcd_to_component(b, LCD_BLUE_BITS, 0);
2096 /* Spead error to surrounding pixels. */
2097 inc = p->inc;
2098 epos = p->epos;
2099 p->epos += inc;
2101 distribute_error(&p->ce[RED], &p->e[RED], rc, epos, inc);
2102 distribute_error(&p->ce[GRN], &p->e[GRN], gc, epos, inc);
2103 distribute_error(&p->ce[BLU], &p->e[BLU], bc, epos, inc);
2105 /* Pack and return pixel */
2106 return LCD_RGBPACK_LCD(r, g, b);
2109 /* Functions for each output mode, colour then grayscale. */
2110 static fb_data (* const pixel_funcs[COLOUR_NUM_MODES][DITHER_NUM_MODES])(void) =
2112 [COLOURMODE_COLOUR] =
2114 [DITHER_NONE] = pixel_to_lcd_colour,
2115 [DITHER_ORDERED] = pixel_odither_to_lcd,
2116 [DITHER_DIFFUSION] = pixel_fsdither_to_lcd,
2118 [COLOURMODE_GRAY] =
2120 [DITHER_NONE] = pixel_to_lcd_gray,
2121 [DITHER_ORDERED] = pixel_odither_to_lcd,
2122 [DITHER_DIFFUSION] = pixel_fsdither_to_lcd,
2127 * Draw a partial YUV colour bitmap
2129 * Runs serpentine pattern when dithering is DITHER_DIFFUSION, else scan is
2130 * always L->R.
2132 void yuv_bitmap_part(unsigned char *src[3], int csub_x, int csub_y,
2133 int src_x, int src_y, int stride,
2134 int x, int y, int width, int height)
2136 fb_data *dst, *dst_end;
2137 fb_data (*pixel_func)(void);
2138 struct rgb_pixel px;
2140 if (x + width > LCD_WIDTH)
2141 width = LCD_WIDTH - x; /* Clip right */
2142 if (x < 0)
2143 width += x, x = 0; /* Clip left */
2144 if (width <= 0)
2145 return; /* nothing left to do */
2147 if (y + height > LCD_HEIGHT)
2148 height = LCD_HEIGHT - y; /* Clip bottom */
2149 if (y < 0)
2150 height += y, y = 0; /* Clip top */
2151 if (height <= 0)
2152 return; /* nothing left to do */
2154 pixel = &px;
2156 dst = rb->lcd_framebuffer + LCD_WIDTH * y + x;
2157 dst_end = dst + LCD_WIDTH * height;
2159 if (jpeg_settings.colour_mode == COLOURMODE_GRAY)
2160 csub_y = 0; /* Ignore Cb, Cr */
2162 pixel_func = pixel_funcs[jpeg_settings.colour_mode]
2163 [jpeg_settings.dither_mode];
2165 if (jpeg_settings.dither_mode == DITHER_DIFFUSION)
2167 /* Reset error terms. */
2168 px.e = rgb_err_buffers;
2169 px.ce[RED] = px.ce[GRN] = px.ce[BLU] = 0;
2170 rb->memset(px.e, 0, 3*sizeof (struct rgb_err));
2175 fb_data *dst_row, *row_end;
2176 const unsigned char *ysrc;
2177 px.inc = 1;
2179 if (jpeg_settings.dither_mode == DITHER_DIFFUSION)
2181 /* Use R->L scan on odd lines */
2182 px.inc -= (src_y & 1) << 1;
2183 px.epos = x + 1;
2185 if (px.inc < 0)
2186 px.epos += width - 1;
2189 if (px.inc == 1)
2191 /* Scan is L->R */
2192 dst_row = dst;
2193 row_end = dst_row + width;
2194 px.col = src_x;
2196 else
2198 /* Scan is R->L */
2199 row_end = dst - 1;
2200 dst_row = row_end + width;
2201 px.col = src_x + width - 1;
2204 ysrc = src[0] + stride * src_y + px.col;
2205 px.row = src_y;
2207 /* Do one row of pixels */
2208 if (csub_y) /* colour */
2210 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
2211 const unsigned char *usrc, *vsrc;
2213 usrc = src[1] + (stride/csub_x) * (src_y/csub_y)
2214 + (px.col/csub_x);
2215 vsrc = src[2] + (stride/csub_x) * (src_y/csub_y)
2216 + (px.col/csub_x);
2217 int xphase = px.col % csub_x;
2218 int xphase_reset = px.inc * csub_x;
2219 int y, v, u, rv, guv, bu;
2221 v = *vsrc - 128;
2222 vsrc += px.inc;
2223 u = *usrc - 128;
2224 usrc += px.inc;
2225 rv = RVFAC*v;
2226 guv = GUFAC*u + GVFAC*v;
2227 bu = BUFAC*u;
2229 while (1)
2231 y = YFAC*(*ysrc);
2232 ysrc += px.inc;
2233 px.r = y + rv;
2234 px.g = y + guv;
2235 px.b = y + bu;
2237 *dst_row = pixel_func();
2238 dst_row += px.inc;
2240 if (dst_row == row_end)
2241 break;
2243 xphase += px.inc;
2244 if ((unsigned)xphase < (unsigned)csub_x)
2245 continue;
2247 /* fetch new chromas */
2248 v = *vsrc - 128;
2249 vsrc += px.inc;
2250 u = *usrc - 128;
2251 usrc += px.inc;
2252 rv = RVFAC*v;
2253 guv = GUFAC*u + GVFAC*v;
2254 bu = BUFAC*u;
2256 xphase -= xphase_reset;
2259 else /* monochrome */
2263 /* Set all components the same for dithering purposes */
2264 px.g = px.r = px.b = YFAC*(*ysrc);
2265 *dst_row = pixel_func();
2266 ysrc += px.inc;
2267 dst_row += px.inc;
2269 while (dst_row != row_end);
2272 src_y++;
2273 dst += LCD_WIDTH;
2275 while (dst < dst_end);
2278 #endif /* HAVE_LCD_COLOR */
2281 /* support function for qsort() */
2282 static int compare(const void* p1, const void* p2)
2284 return rb->strcasecmp(*((char **)p1), *((char **)p2));
2287 bool jpg_ext(const char ext[])
2289 if(!ext)
2290 return false;
2291 if(!rb->strcasecmp(ext,".jpg") ||
2292 !rb->strcasecmp(ext,".jpe") ||
2293 !rb->strcasecmp(ext,".jpeg"))
2294 return true;
2295 else
2296 return false;
2299 /*Read directory contents for scrolling. */
2300 void get_pic_list(void)
2302 int i;
2303 long int str_len = 0;
2304 char *pname;
2305 tree = rb->tree_get_context();
2307 #if PLUGIN_BUFFER_SIZE >= MIN_MEM
2308 file_pt = rb->plugin_get_buffer((size_t *)&buf_size);
2309 #else
2310 file_pt = rb->plugin_get_audio_buffer((size_t *)&buf_size);
2311 #endif
2313 for(i = 0; i < tree->filesindir; i++)
2315 if(jpg_ext(rb->strrchr(&tree->name_buffer[str_len],'.')))
2316 file_pt[entries++] = &tree->name_buffer[str_len];
2318 str_len += rb->strlen(&tree->name_buffer[str_len]) + 1;
2321 rb->qsort(file_pt, entries, sizeof(char**), compare);
2323 /* Remove path and leave only the name.*/
2324 pname = rb->strrchr(np_file,'/');
2325 pname++;
2327 /* Find Selected File. */
2328 for(i = 0; i < entries; i++)
2329 if(!rb->strcmp(file_pt[i], pname))
2330 curfile = i;
2333 int change_filename(int direct)
2335 int count = 0;
2336 direction = direct;
2338 if(direct == DIR_PREV)
2342 count++;
2343 if(curfile == 0)
2344 curfile = entries - 1;
2345 else
2346 curfile--;
2347 }while(file_pt[curfile] == '\0' && count < entries);
2348 /* we "erase" the file name if we encounter
2349 * a non-supported file, so skip it now */
2351 else /* DIR_NEXT/DIR_NONE */
2355 count++;
2356 if(curfile == entries - 1)
2357 curfile = 0;
2358 else
2359 curfile++;
2360 }while(file_pt[curfile] == '\0' && count < entries);
2363 if(count == entries && file_pt[curfile] == '\0')
2365 rb->splash(HZ, "No supported files");
2366 return PLUGIN_ERROR;
2368 if(rb->strlen(tree->currdir) > 1)
2370 rb->strcpy(np_file, tree->currdir);
2371 rb->strcat(np_file, "/");
2373 else
2374 rb->strcpy(np_file, tree->currdir);
2376 rb->strcat(np_file, file_pt[curfile]);
2378 return PLUGIN_OTHER;
2381 /* switch off overlay, for handling SYS_ events */
2382 void cleanup(void *parameter)
2384 (void)parameter;
2385 #ifdef USEGSLIB
2386 gray_show(false);
2387 #endif
2390 #define VSCROLL (LCD_HEIGHT/8)
2391 #define HSCROLL (LCD_WIDTH/10)
2393 #define ZOOM_IN 100 /* return codes for below function */
2394 #define ZOOM_OUT 101
2396 #ifdef HAVE_LCD_COLOR
2397 bool set_option_grayscale(void)
2399 bool gray = jpeg_settings.colour_mode == COLOURMODE_GRAY;
2400 rb->set_bool("Grayscale", &gray);
2401 jpeg_settings.colour_mode = gray ? COLOURMODE_GRAY : COLOURMODE_COLOUR;
2402 return false;
2405 bool set_option_dithering(void)
2407 static const struct opt_items dithering[DITHER_NUM_MODES] = {
2408 [DITHER_NONE] = { "Off", -1 },
2409 [DITHER_ORDERED] = { "Ordered", -1 },
2410 [DITHER_DIFFUSION] = { "Diffusion", -1 },
2413 rb->set_option("Dithering", &jpeg_settings.dither_mode, INT,
2414 dithering, DITHER_NUM_MODES, NULL);
2415 return false;
2418 static void display_options(void)
2420 static const struct menu_item items[] = {
2421 { "Grayscale", set_option_grayscale },
2422 { "Dithering", set_option_dithering },
2425 int m = menu_init(rb, items, ARRAYLEN(items),
2426 NULL, NULL, NULL, NULL);
2427 menu_run(m);
2428 menu_exit(m);
2430 #endif /* HAVE_LCD_COLOR */
2432 int show_menu(void) /* return 1 to quit */
2434 #if LCD_DEPTH > 1
2435 rb->lcd_set_backdrop(old_backdrop);
2436 #ifdef HAVE_LCD_COLOR
2437 rb->lcd_set_foreground(rb->global_settings->fg_color);
2438 rb->lcd_set_background(rb->global_settings->bg_color);
2439 #else
2440 rb->lcd_set_foreground(LCD_BLACK);
2441 rb->lcd_set_background(LCD_WHITE);
2442 #endif
2443 #endif
2444 int m;
2445 int result;
2447 enum menu_id
2449 MIID_QUIT = 0,
2450 MIID_TOGGLE_SS_MODE,
2451 MIID_CHANGE_SS_MODE,
2452 #if PLUGIN_BUFFER_SIZE >= MIN_MEM
2453 MIID_SHOW_PLAYBACK_MENU,
2454 #endif
2455 #ifdef HAVE_LCD_COLOR
2456 MIID_DISPLAY_OPTIONS,
2457 #endif
2458 MIID_RETURN,
2461 static const struct menu_item items[] = {
2462 [MIID_QUIT] =
2463 { "Quit", NULL },
2464 [MIID_TOGGLE_SS_MODE] =
2465 { "Toggle Slideshow Mode", NULL },
2466 [MIID_CHANGE_SS_MODE] =
2467 { "Change Slideshow Time", NULL },
2468 #if PLUGIN_BUFFER_SIZE >= MIN_MEM
2469 [MIID_SHOW_PLAYBACK_MENU] =
2470 { "Show Playback Menu", NULL },
2471 #endif
2472 #ifdef HAVE_LCD_COLOR
2473 [MIID_DISPLAY_OPTIONS] =
2474 { "Display Options", NULL },
2475 #endif
2476 [MIID_RETURN] =
2477 { "Return", NULL },
2480 static const struct opt_items slideshow[2] = {
2481 { "Disable", -1 },
2482 { "Enable", -1 },
2485 static const struct opt_items timeout[12] = {
2486 { "1 second", -1 },
2487 { "2 seconds", -1 },
2488 { "3 seconds", -1 },
2489 { "4 seconds", -1 },
2490 { "5 seconds", -1 },
2491 { "6 seconds", -1 },
2492 { "7 seconds", -1 },
2493 { "8 seconds", -1 },
2494 { "9 seconds", -1 },
2495 { "10 seconds", -1 },
2496 { "15 seconds", -1 },
2497 { "20 seconds", -1 },
2500 m = menu_init(rb, items, sizeof(items) / sizeof(*items),
2501 NULL, NULL, NULL, NULL);
2502 result=menu_show(m);
2504 switch (result)
2506 case MIID_QUIT:
2507 menu_exit(m);
2508 return 1;
2509 break;
2510 case MIID_TOGGLE_SS_MODE:
2511 rb->set_option("Toggle Slideshow", &slideshow_enabled, INT,
2512 slideshow , 2, NULL);
2513 break;
2514 case MIID_CHANGE_SS_MODE:
2515 switch (button_timeout/HZ)
2517 case 10: result = 9; break;
2518 case 15: result = 10; break;
2519 case 20: result = 11; break;
2520 default: result = (button_timeout/HZ)-1; break;
2522 rb->set_option("Slideshow Time", &result, INT,
2523 timeout , 12, NULL);
2524 switch (result)
2526 case 9: button_timeout = 10*HZ; break;
2527 case 10: button_timeout = 15*HZ; break;
2528 case 11: button_timeout = 20*HZ; break;
2529 default: button_timeout = (result+1)*HZ; break;
2531 break;
2532 #if PLUGIN_BUFFER_SIZE >= MIN_MEM
2533 case MIID_SHOW_PLAYBACK_MENU:
2534 playback_control(rb);
2535 break;
2536 #endif
2537 #ifdef HAVE_LCD_COLOR
2538 case MIID_DISPLAY_OPTIONS:
2539 display_options();
2540 break;
2541 #endif
2542 case MIID_RETURN:
2543 break;
2546 #if !defined(SIMULATOR) && !defined(HAVE_FLASH_STORAGE)
2547 /* change ata spindown time based on slideshow time setting */
2548 immediate_ata_off = false;
2549 rb->ata_spindown(rb->global_settings->disk_spindown);
2551 if (slideshow_enabled)
2553 if(button_timeout/HZ < 10)
2555 /* slideshow times < 10s keep disk spinning */
2556 rb->ata_spindown(0);
2558 else if (!rb->mp3_is_playing())
2560 /* slideshow times > 10s and not playing: ata_off after load */
2561 immediate_ata_off = true;
2564 #endif
2565 #if LCD_DEPTH > 1
2566 rb->lcd_set_backdrop(NULL);
2567 rb->lcd_set_foreground(LCD_WHITE);
2568 rb->lcd_set_background(LCD_BLACK);
2569 #endif
2570 rb->lcd_clear_display();
2571 menu_exit(m);
2572 return 0;
2574 /* interactively scroll around the image */
2575 int scroll_bmp(struct t_disp* pdisp)
2577 int lastbutton = 0;
2579 while (true)
2581 int button;
2582 int move;
2584 if (slideshow_enabled)
2585 button = rb->button_get_w_tmo(button_timeout);
2586 else button = rb->button_get(true);
2588 running_slideshow = false;
2590 switch(button)
2592 case JPEG_LEFT:
2593 if (!(ds < ds_max) && entries > 0 && jpg.x_size <= MAX_X_SIZE)
2594 return change_filename(DIR_PREV);
2595 case JPEG_LEFT | BUTTON_REPEAT:
2596 move = MIN(HSCROLL, pdisp->x);
2597 if (move > 0)
2599 MYXLCD(scroll_right)(move); /* scroll right */
2600 pdisp->x -= move;
2601 #ifdef HAVE_LCD_COLOR
2602 yuv_bitmap_part(
2603 pdisp->bitmap, pdisp->csub_x, pdisp->csub_y,
2604 pdisp->x, pdisp->y, pdisp->stride,
2605 0, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */
2606 move, MIN(LCD_HEIGHT, pdisp->height)); /* w, h */
2607 #else
2608 MYXLCD(gray_bitmap_part)(
2609 pdisp->bitmap[0], pdisp->x, pdisp->y, pdisp->stride,
2610 0, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */
2611 move, MIN(LCD_HEIGHT, pdisp->height)); /* w, h */
2612 #endif
2613 MYLCD_UPDATE();
2615 break;
2617 case JPEG_RIGHT:
2618 if (!(ds < ds_max) && entries > 0 && jpg.x_size <= MAX_X_SIZE)
2619 return change_filename(DIR_NEXT);
2620 case JPEG_RIGHT | BUTTON_REPEAT:
2621 move = MIN(HSCROLL, pdisp->width - pdisp->x - LCD_WIDTH);
2622 if (move > 0)
2624 MYXLCD(scroll_left)(move); /* scroll left */
2625 pdisp->x += move;
2626 #ifdef HAVE_LCD_COLOR
2627 yuv_bitmap_part(
2628 pdisp->bitmap, pdisp->csub_x, pdisp->csub_y,
2629 pdisp->x + LCD_WIDTH - move, pdisp->y, pdisp->stride,
2630 LCD_WIDTH - move, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */
2631 move, MIN(LCD_HEIGHT, pdisp->height)); /* w, h */
2632 #else
2633 MYXLCD(gray_bitmap_part)(
2634 pdisp->bitmap[0], pdisp->x + LCD_WIDTH - move,
2635 pdisp->y, pdisp->stride,
2636 LCD_WIDTH - move, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */
2637 move, MIN(LCD_HEIGHT, pdisp->height)); /* w, h */
2638 #endif
2639 MYLCD_UPDATE();
2641 break;
2643 case JPEG_UP:
2644 case JPEG_UP | BUTTON_REPEAT:
2645 move = MIN(VSCROLL, pdisp->y);
2646 if (move > 0)
2648 MYXLCD(scroll_down)(move); /* scroll down */
2649 pdisp->y -= move;
2650 #ifdef HAVE_LCD_COLOR
2651 if (jpeg_settings.dither_mode == DITHER_DIFFUSION)
2653 /* Draw over the band at the top of the last update
2654 caused by lack of error history on line zero. */
2655 move = MIN(move + 1, pdisp->y + pdisp->height);
2658 yuv_bitmap_part(
2659 pdisp->bitmap, pdisp->csub_x, pdisp->csub_y,
2660 pdisp->x, pdisp->y, pdisp->stride,
2661 MAX(0, (LCD_WIDTH-pdisp->width)/2), 0, /* x, y */
2662 MIN(LCD_WIDTH, pdisp->width), move); /* w, h */
2663 #else
2664 MYXLCD(gray_bitmap_part)(
2665 pdisp->bitmap[0], pdisp->x, pdisp->y, pdisp->stride,
2666 MAX(0, (LCD_WIDTH-pdisp->width)/2), 0, /* x, y */
2667 MIN(LCD_WIDTH, pdisp->width), move); /* w, h */
2668 #endif
2669 MYLCD_UPDATE();
2671 break;
2673 case JPEG_DOWN:
2674 case JPEG_DOWN | BUTTON_REPEAT:
2675 move = MIN(VSCROLL, pdisp->height - pdisp->y - LCD_HEIGHT);
2676 if (move > 0)
2678 MYXLCD(scroll_up)(move); /* scroll up */
2679 pdisp->y += move;
2680 #ifdef HAVE_LCD_COLOR
2681 if (jpeg_settings.dither_mode == DITHER_DIFFUSION)
2683 /* Save the line that was on the last line of the display
2684 and draw one extra line above then recover the line with
2685 image data that had an error history when it was drawn.
2687 move++, pdisp->y--;
2688 MEMCPY(rgb_linebuf,
2689 rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH,
2690 LCD_WIDTH*sizeof (fb_data));
2693 yuv_bitmap_part(
2694 pdisp->bitmap, pdisp->csub_x, pdisp->csub_y, pdisp->x,
2695 pdisp->y + LCD_HEIGHT - move, pdisp->stride,
2696 MAX(0, (LCD_WIDTH-pdisp->width)/2), LCD_HEIGHT - move, /* x, y */
2697 MIN(LCD_WIDTH, pdisp->width), move); /* w, h */
2699 if (jpeg_settings.dither_mode == DITHER_DIFFUSION)
2701 /* Cover the first row drawn with previous image data. */
2702 MEMCPY(rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH,
2703 rgb_linebuf,
2704 LCD_WIDTH*sizeof (fb_data));
2705 pdisp->y++;
2707 #else
2708 MYXLCD(gray_bitmap_part)(
2709 pdisp->bitmap[0], pdisp->x,
2710 pdisp->y + LCD_HEIGHT - move, pdisp->stride,
2711 MAX(0, (LCD_WIDTH-pdisp->width)/2), LCD_HEIGHT - move, /* x, y */
2712 MIN(LCD_WIDTH, pdisp->width), move); /* w, h */
2713 #endif
2714 MYLCD_UPDATE();
2716 break;
2717 case BUTTON_NONE:
2718 if (!slideshow_enabled)
2719 break;
2720 running_slideshow = true;
2721 if (entries > 0)
2722 return change_filename(DIR_NEXT);
2723 break;
2725 #ifdef JPEG_SLIDE_SHOW
2726 case JPEG_SLIDE_SHOW:
2727 slideshow_enabled = !slideshow_enabled;
2728 running_slideshow = slideshow_enabled;
2729 break;
2730 #endif
2732 #ifdef JPEG_NEXT_REPEAT
2733 case JPEG_NEXT_REPEAT:
2734 #endif
2735 case JPEG_NEXT:
2736 if (entries > 0)
2737 return change_filename(DIR_NEXT);
2738 break;
2740 #ifdef JPEG_PREVIOUS_REPEAT
2741 case JPEG_PREVIOUS_REPEAT:
2742 #endif
2743 case JPEG_PREVIOUS:
2744 if (entries > 0)
2745 return change_filename(DIR_PREV);
2746 break;
2748 case JPEG_ZOOM_IN:
2749 #ifdef JPEG_ZOOM_PRE
2750 if (lastbutton != JPEG_ZOOM_PRE)
2751 break;
2752 #endif
2753 return ZOOM_IN;
2754 break;
2756 case JPEG_ZOOM_OUT:
2757 #ifdef JPEG_ZOOM_PRE
2758 if (lastbutton != JPEG_ZOOM_PRE)
2759 break;
2760 #endif
2761 return ZOOM_OUT;
2762 break;
2763 #ifdef JPEG_RC_MENU
2764 case JPEG_RC_MENU:
2765 #endif
2766 case JPEG_MENU:
2767 #ifdef USEGSLIB
2768 gray_show(false); /* switch off grayscale overlay */
2769 #endif
2770 if (show_menu() == 1)
2771 return PLUGIN_OK;
2773 #ifdef USEGSLIB
2774 gray_show(true); /* switch on grayscale overlay */
2775 #else
2776 yuv_bitmap_part(
2777 pdisp->bitmap, pdisp->csub_x, pdisp->csub_y,
2778 pdisp->x, pdisp->y, pdisp->stride,
2779 MAX(0, (LCD_WIDTH - pdisp->width) / 2),
2780 MAX(0, (LCD_HEIGHT - pdisp->height) / 2),
2781 MIN(LCD_WIDTH, pdisp->width),
2782 MIN(LCD_HEIGHT, pdisp->height));
2783 MYLCD_UPDATE();
2784 #endif
2785 break;
2786 default:
2787 if (rb->default_event_handler_ex(button, cleanup, NULL)
2788 == SYS_USB_CONNECTED)
2789 return PLUGIN_USB_CONNECTED;
2790 break;
2792 } /* switch */
2794 if (button != BUTTON_NONE)
2795 lastbutton = button;
2796 } /* while (true) */
2799 /********************* main function *************************/
2801 /* callback updating a progress meter while JPEG decoding */
2802 void cb_progess(int current, int total)
2804 rb->yield(); /* be nice to the other threads */
2805 if(!running_slideshow)
2807 rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN],0, LCD_HEIGHT-8, LCD_WIDTH, 8, total, 0,
2808 current, HORIZONTAL);
2809 rb->lcd_update_rect(0, LCD_HEIGHT-8, LCD_WIDTH, 8);
2811 #ifndef USEGSLIB
2812 else
2814 /* in slideshow mode, keep gui interference to a minimum */
2815 rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN],0, LCD_HEIGHT-4, LCD_WIDTH, 4, total, 0,
2816 current, HORIZONTAL);
2817 rb->lcd_update_rect(0, LCD_HEIGHT-4, LCD_WIDTH, 4);
2819 #endif
2822 int jpegmem(struct jpeg *p_jpg, int ds)
2824 int size;
2826 size = (p_jpg->x_phys/ds/p_jpg->subsample_x[0])
2827 * (p_jpg->y_phys/ds/p_jpg->subsample_y[0]);
2828 #ifdef HAVE_LCD_COLOR
2829 if (p_jpg->blocks > 1) /* colour, add requirements for chroma */
2831 size += (p_jpg->x_phys/ds/p_jpg->subsample_x[1])
2832 * (p_jpg->y_phys/ds/p_jpg->subsample_y[1]);
2833 size += (p_jpg->x_phys/ds/p_jpg->subsample_x[2])
2834 * (p_jpg->y_phys/ds/p_jpg->subsample_y[2]);
2836 #endif
2837 return size;
2840 /* how far can we zoom in without running out of memory */
2841 int min_downscale(struct jpeg *p_jpg, int bufsize)
2843 int downscale = 8;
2845 if (jpegmem(p_jpg, 8) > bufsize)
2846 return 0; /* error, too large, even 1:8 doesn't fit */
2848 while (downscale > 1 && jpegmem(p_jpg, downscale/2) <= bufsize)
2849 downscale /= 2;
2851 return downscale;
2855 /* how far can we zoom out, to fit image into the LCD */
2856 int max_downscale(struct jpeg *p_jpg)
2858 int downscale = 1;
2860 while (downscale < 8 && (p_jpg->x_size > LCD_WIDTH*downscale
2861 || p_jpg->y_size > LCD_HEIGHT*downscale))
2863 downscale *= 2;
2866 return downscale;
2870 /* return decoded or cached image */
2871 struct t_disp* get_image(struct jpeg* p_jpg, int ds)
2873 int w, h; /* used to center output */
2874 int size; /* decompressed image size */
2875 long time; /* measured ticks */
2876 int status;
2878 struct t_disp* p_disp = &disp[ds]; /* short cut */
2880 if (p_disp->bitmap[0] != NULL)
2882 return p_disp; /* we still have it */
2885 /* assign image buffer */
2887 /* physical size needed for decoding */
2888 size = jpegmem(p_jpg, ds);
2889 if (buf_size <= size)
2890 { /* have to discard the current */
2891 int i;
2892 for (i=1; i<=8; i++)
2893 disp[i].bitmap[0] = NULL; /* invalidate all bitmaps */
2894 buf = buf_root; /* start again from the beginning of the buffer */
2895 buf_size = root_size;
2898 #ifdef HAVE_LCD_COLOR
2899 if (p_jpg->blocks > 1) /* colour jpeg */
2901 int i;
2903 for (i = 1; i < 3; i++)
2905 size = (p_jpg->x_phys / ds / p_jpg->subsample_x[i])
2906 * (p_jpg->y_phys / ds / p_jpg->subsample_y[i]);
2907 p_disp->bitmap[i] = buf;
2908 buf += size;
2909 buf_size -= size;
2911 p_disp->csub_x = p_jpg->subsample_x[1];
2912 p_disp->csub_y = p_jpg->subsample_y[1];
2914 else
2916 p_disp->csub_x = p_disp->csub_y = 0;
2917 p_disp->bitmap[1] = p_disp->bitmap[2] = buf;
2919 #endif
2920 /* size may be less when decoded (if height is not block aligned) */
2921 size = (p_jpg->x_phys/ds) * (p_jpg->y_size / ds);
2922 p_disp->bitmap[0] = buf;
2923 buf += size;
2924 buf_size -= size;
2926 if(!running_slideshow)
2928 rb->snprintf(print, sizeof(print), "decoding %d*%d",
2929 p_jpg->x_size/ds, p_jpg->y_size/ds);
2930 rb->lcd_puts(0, 3, print);
2931 rb->lcd_update();
2934 /* update image properties */
2935 p_disp->width = p_jpg->x_size / ds;
2936 p_disp->stride = p_jpg->x_phys / ds; /* use physical size for stride */
2937 p_disp->height = p_jpg->y_size / ds;
2939 /* the actual decoding */
2940 time = *rb->current_tick;
2941 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
2942 rb->cpu_boost(true);
2943 status = jpeg_decode(p_jpg, p_disp->bitmap, ds, cb_progess);
2944 rb->cpu_boost(false);
2945 #else
2946 status = jpeg_decode(p_jpg, p_disp->bitmap, ds, cb_progess);
2947 #endif
2948 if (status)
2950 rb->splash(HZ, "decode error %d", status);
2951 file_pt[curfile] = '\0';
2952 return NULL;
2954 time = *rb->current_tick - time;
2956 if(!running_slideshow)
2958 rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ);
2959 rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */
2960 rb->lcd_putsxy((LCD_WIDTH - w)/2, LCD_HEIGHT - h, print);
2961 rb->lcd_update();
2964 return p_disp;
2968 /* set the view to the given center point, limit if necessary */
2969 void set_view (struct t_disp* p_disp, int cx, int cy)
2971 int x, y;
2973 /* plain center to available width/height */
2974 x = cx - MIN(LCD_WIDTH, p_disp->width) / 2;
2975 y = cy - MIN(LCD_HEIGHT, p_disp->height) / 2;
2977 /* limit against upper image size */
2978 x = MIN(p_disp->width - LCD_WIDTH, x);
2979 y = MIN(p_disp->height - LCD_HEIGHT, y);
2981 /* limit against negative side */
2982 x = MAX(0, x);
2983 y = MAX(0, y);
2985 p_disp->x = x; /* set the values */
2986 p_disp->y = y;
2990 /* calculate the view center based on the bitmap position */
2991 void get_view(struct t_disp* p_disp, int* p_cx, int* p_cy)
2993 *p_cx = p_disp->x + MIN(LCD_WIDTH, p_disp->width) / 2;
2994 *p_cy = p_disp->y + MIN(LCD_HEIGHT, p_disp->height) / 2;
2998 /* load, decode, display the image */
2999 int load_and_show(char* filename)
3001 int fd;
3002 int filesize;
3003 unsigned char* buf_jpeg; /* compressed JPEG image */
3004 int status;
3005 struct t_disp* p_disp; /* currenly displayed image */
3006 int cx, cy; /* view center */
3008 fd = rb->open(filename, O_RDONLY);
3009 if (fd < 0)
3011 rb->snprintf(print,sizeof(print),"err opening %s:%d",filename,fd);
3012 rb->splash(HZ, print);
3013 return PLUGIN_ERROR;
3015 filesize = rb->filesize(fd);
3016 rb->memset(&disp, 0, sizeof(disp));
3018 buf = buf_images + filesize;
3019 buf_size = buf_images_size - filesize;
3020 /* allocate JPEG buffer */
3021 buf_jpeg = buf_images;
3023 buf_root = buf; /* we can start the decompressed images behind it */
3024 root_size = buf_size;
3026 if (buf_size <= 0)
3028 #if PLUGIN_BUFFER_SIZE >= MIN_MEM
3029 if(plug_buf)
3031 rb->close(fd);
3032 rb->lcd_setfont(FONT_SYSFIXED);
3033 rb->lcd_clear_display();
3034 rb->snprintf(print,sizeof(print),"%s:",rb->strrchr(filename,'/')+1);
3035 rb->lcd_puts(0,0,print);
3036 rb->lcd_puts(0,1,"Not enough plugin memory!");
3037 rb->lcd_puts(0,2,"Zoom In: Stop playback.");
3038 if(entries>1)
3039 rb->lcd_puts(0,3,"Left/Right: Skip File.");
3040 rb->lcd_puts(0,4,"Off: Quit.");
3041 rb->lcd_update();
3042 rb->lcd_setfont(FONT_UI);
3044 rb->button_clear_queue();
3046 while (1)
3048 int button = rb->button_get(true);
3049 switch(button)
3051 case JPEG_ZOOM_IN:
3052 plug_buf = false;
3053 buf_images = rb->plugin_get_audio_buffer(
3054 (size_t *)&buf_images_size);
3055 /*try again this file, now using the audio buffer */
3056 return PLUGIN_OTHER;
3057 #ifdef JPEG_RC_MENU
3058 case JPEG_RC_MENU:
3059 #endif
3060 case JPEG_MENU:
3061 return PLUGIN_OK;
3063 case JPEG_LEFT:
3064 if(entries>1)
3066 rb->lcd_clear_display();
3067 return change_filename(DIR_PREV);
3069 break;
3071 case JPEG_RIGHT:
3072 if(entries>1)
3074 rb->lcd_clear_display();
3075 return change_filename(DIR_NEXT);
3077 break;
3078 default:
3079 if(rb->default_event_handler_ex(button, cleanup, NULL)
3080 == SYS_USB_CONNECTED)
3081 return PLUGIN_USB_CONNECTED;
3086 else
3087 #endif
3089 rb->splash(HZ, "Out of Memory");
3090 rb->close(fd);
3091 return PLUGIN_ERROR;
3095 if(!running_slideshow)
3097 #if LCD_DEPTH > 1
3098 rb->lcd_set_foreground(LCD_WHITE);
3099 rb->lcd_set_background(LCD_BLACK);
3100 rb->lcd_set_backdrop(NULL);
3101 #endif
3103 rb->lcd_clear_display();
3104 rb->snprintf(print, sizeof(print), "%s:", rb->strrchr(filename,'/')+1);
3105 rb->lcd_puts(0, 0, print);
3106 rb->lcd_update();
3108 rb->snprintf(print, sizeof(print), "loading %d bytes", filesize);
3109 rb->lcd_puts(0, 1, print);
3110 rb->lcd_update();
3113 rb->read(fd, buf_jpeg, filesize);
3114 rb->close(fd);
3116 if(!running_slideshow)
3118 rb->snprintf(print, sizeof(print), "decoding markers");
3119 rb->lcd_puts(0, 2, print);
3120 rb->lcd_update();
3122 #ifndef SIMULATOR
3123 else if(immediate_ata_off)
3125 /* running slideshow and time is long enough: power down disk */
3126 rb->ata_sleep();
3128 #endif
3130 rb->memset(&jpg, 0, sizeof(jpg)); /* clear info struct */
3131 /* process markers, unstuffing */
3132 status = process_markers(buf_jpeg, filesize, &jpg);
3134 if (status < 0 || (status & (DQT | SOF0)) != (DQT | SOF0))
3135 { /* bad format or minimum components not contained */
3136 rb->splash(HZ, "unsupported %d", status);
3137 file_pt[curfile] = '\0';
3138 return change_filename(direction);
3141 if (!(status & DHT)) /* if no Huffman table present: */
3142 default_huff_tbl(&jpg); /* use default */
3143 build_lut(&jpg); /* derive Huffman and other lookup-tables */
3145 if(!running_slideshow)
3147 rb->snprintf(print, sizeof(print), "image %dx%d", jpg.x_size, jpg.y_size);
3148 rb->lcd_puts(0, 2, print);
3149 rb->lcd_update();
3151 ds_max = max_downscale(&jpg); /* check display constraint */
3152 ds_min = min_downscale(&jpg, buf_size); /* check memory constraint */
3153 if (ds_min == 0)
3155 rb->splash(HZ, "too large");
3156 file_pt[curfile] = '\0';
3157 return change_filename(direction);
3160 ds = ds_max; /* initials setting */
3161 cx = jpg.x_size/ds/2; /* center the view */
3162 cy = jpg.y_size/ds/2;
3164 do /* loop the image prepare and decoding when zoomed */
3166 p_disp = get_image(&jpg, ds); /* decode or fetch from cache */
3167 if (p_disp == NULL)
3168 return change_filename(direction);
3170 set_view(p_disp, cx, cy);
3172 if(!running_slideshow)
3174 rb->snprintf(print, sizeof(print), "showing %dx%d",
3175 p_disp->width, p_disp->height);
3176 rb->lcd_puts(0, 3, print);
3177 rb->lcd_update();
3179 MYLCD(clear_display)();
3180 #ifdef HAVE_LCD_COLOR
3181 yuv_bitmap_part(
3182 p_disp->bitmap, p_disp->csub_x, p_disp->csub_y,
3183 p_disp->x, p_disp->y, p_disp->stride,
3184 MAX(0, (LCD_WIDTH - p_disp->width) / 2),
3185 MAX(0, (LCD_HEIGHT - p_disp->height) / 2),
3186 MIN(LCD_WIDTH, p_disp->width),
3187 MIN(LCD_HEIGHT, p_disp->height));
3188 #else
3189 MYXLCD(gray_bitmap_part)(
3190 p_disp->bitmap[0], p_disp->x, p_disp->y, p_disp->stride,
3191 MAX(0, (LCD_WIDTH - p_disp->width) / 2),
3192 MAX(0, (LCD_HEIGHT - p_disp->height) / 2),
3193 MIN(LCD_WIDTH, p_disp->width),
3194 MIN(LCD_HEIGHT, p_disp->height));
3195 #endif
3196 MYLCD_UPDATE();
3198 #ifdef USEGSLIB
3199 gray_show(true); /* switch on grayscale overlay */
3200 #endif
3202 /* drawing is now finished, play around with scrolling
3203 * until you press OFF or connect USB
3205 while (1)
3207 status = scroll_bmp(p_disp);
3208 if (status == ZOOM_IN)
3210 if (ds > ds_min)
3212 ds /= 2; /* reduce downscaling to zoom in */
3213 get_view(p_disp, &cx, &cy);
3214 cx *= 2; /* prepare the position in the new image */
3215 cy *= 2;
3217 else
3218 continue;
3221 if (status == ZOOM_OUT)
3223 if (ds < ds_max)
3225 ds *= 2; /* increase downscaling to zoom out */
3226 get_view(p_disp, &cx, &cy);
3227 cx /= 2; /* prepare the position in the new image */
3228 cy /= 2;
3230 else
3231 continue;
3233 break;
3236 #ifdef USEGSLIB
3237 gray_show(false); /* switch off overlay */
3238 #endif
3239 rb->lcd_clear_display();
3241 while (status != PLUGIN_OK && status != PLUGIN_USB_CONNECTED
3242 && status != PLUGIN_OTHER);
3243 #ifdef USEGSLIB
3244 rb->lcd_update();
3245 #endif
3246 return status;
3249 /******************** Plugin entry point *********************/
3251 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
3253 rb = api;
3255 int condition;
3256 #ifdef USEGSLIB
3257 int grayscales;
3258 long graysize; /* helper */
3259 #endif
3260 #if LCD_DEPTH > 1
3261 old_backdrop = rb->lcd_get_backdrop();
3262 #endif
3264 if(!parameter) return PLUGIN_ERROR;
3266 rb->strcpy(np_file, parameter);
3267 get_pic_list();
3269 if(!entries) return PLUGIN_ERROR;
3271 #if (PLUGIN_BUFFER_SIZE >= MIN_MEM) && !defined(SIMULATOR)
3272 if(rb->audio_status())
3274 buf = rb->plugin_get_buffer((size_t *)&buf_size) +
3275 (entries * sizeof(char**));
3276 buf_size -= (entries * sizeof(char**));
3277 plug_buf = true;
3279 else
3280 buf = rb->plugin_get_audio_buffer((size_t *)&buf_size);
3281 #else
3282 buf = rb->plugin_get_audio_buffer(&buf_size) +
3283 (entries * sizeof(char**));
3284 buf_size -= (entries * sizeof(char**));
3285 #endif
3287 #ifdef USEGSLIB
3288 /* initialize the grayscale buffer: 32 bitplanes for 33 shades of gray. */
3289 grayscales = gray_init(rb, buf, buf_size, false, LCD_WIDTH, LCD_HEIGHT,
3290 32, 2<<8, &graysize) + 1;
3291 buf += graysize;
3292 buf_size -= graysize;
3293 if (grayscales < 33 || buf_size <= 0)
3295 rb->splash(HZ, "gray buf error");
3296 return PLUGIN_ERROR;
3298 #else
3299 xlcd_init(rb);
3300 #endif
3302 #ifdef HAVE_LCD_COLOR
3303 /* should be ok to just load settings since a parameter is present
3304 here and the drive should be spinning */
3305 configfile_init(rb);
3306 configfile_load(JPEG_CONFIGFILE, jpeg_config,
3307 ARRAYLEN(jpeg_config), JPEG_SETTINGS_MINVERSION);
3308 old_settings = jpeg_settings;
3309 #endif
3311 buf_images = buf; buf_images_size = buf_size;
3313 /* Turn off backlight timeout */
3314 backlight_force_on(); /* backlight control in lib/helper.c */
3318 condition = load_and_show(np_file);
3319 }while (condition != PLUGIN_OK && condition != PLUGIN_USB_CONNECTED
3320 && condition != PLUGIN_ERROR);
3322 #ifdef HAVE_LCD_COLOR
3323 if (rb->memcmp(&jpeg_settings, &old_settings, sizeof (jpeg_settings)))
3325 /* Just in case drive has to spin, keep it from looking locked */
3326 rb->splash(0, "Saving Settings");
3327 configfile_save(JPEG_CONFIGFILE, jpeg_config,
3328 ARRAYLEN(jpeg_config), JPEG_SETTINGS_VERSION);
3330 #endif
3332 #if !defined(SIMULATOR) && !defined(HAVE_FLASH_STORAGE)
3333 /* set back ata spindown time in case we changed it */
3334 rb->ata_spindown(rb->global_settings->disk_spindown);
3335 #endif
3337 /* Turn on backlight timeout (revert to settings) */
3338 backlight_use_settings(); /* backlight control in lib/helper.c */
3340 #ifdef USEGSLIB
3341 gray_release(); /* deinitialize */
3342 #endif
3344 return condition;
3347 #endif /* HAVE_LCD_BITMAP */