1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
11 * (This is a real mess if it has to be coded in one single C file)
13 * File scrolling addition (C) 2005 Alexander Spyridakis
14 * Copyright (C) 2004 Jörg Hohensohn aka [IDC]Dragon
15 * Heavily borrowed from the IJG implementation (C) Thomas G. Lane
16 * Small & fast downscaling IDCT (C) 2002 by Guido Vollbeding JPEGclub.org
18 * All files in this archive are subject to the GNU General Public License.
19 * See the file COPYING in the source tree root for full license agreement.
21 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
22 * KIND, either express or implied.
24 ****************************************************************************/
27 #include "playback_control.h"
28 #include "oldmenuapi.h"
30 #include "lib/configfile.h"
32 #ifdef HAVE_LCD_BITMAP
38 /* variable button definitions */
39 #if CONFIG_KEYPAD == RECORDER_PAD
40 #define JPEG_ZOOM_IN BUTTON_PLAY
41 #define JPEG_ZOOM_OUT BUTTON_ON
42 #define JPEG_UP BUTTON_UP
43 #define JPEG_DOWN BUTTON_DOWN
44 #define JPEG_LEFT BUTTON_LEFT
45 #define JPEG_RIGHT BUTTON_RIGHT
46 #define JPEG_NEXT BUTTON_F3
47 #define JPEG_PREVIOUS BUTTON_F2
48 #define JPEG_MENU BUTTON_OFF
50 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
51 #define JPEG_ZOOM_IN BUTTON_SELECT
52 #define JPEG_ZOOM_OUT BUTTON_ON
53 #define JPEG_UP BUTTON_UP
54 #define JPEG_DOWN BUTTON_DOWN
55 #define JPEG_LEFT BUTTON_LEFT
56 #define JPEG_RIGHT BUTTON_RIGHT
57 #define JPEG_NEXT BUTTON_F3
58 #define JPEG_PREVIOUS BUTTON_F2
59 #define JPEG_MENU BUTTON_OFF
61 #elif CONFIG_KEYPAD == ONDIO_PAD
62 #define JPEG_ZOOM_PRE BUTTON_MENU
63 #define JPEG_ZOOM_IN (BUTTON_MENU | BUTTON_REL)
64 #define JPEG_ZOOM_OUT (BUTTON_MENU | BUTTON_DOWN)
65 #define JPEG_UP BUTTON_UP
66 #define JPEG_DOWN BUTTON_DOWN
67 #define JPEG_LEFT BUTTON_LEFT
68 #define JPEG_RIGHT BUTTON_RIGHT
69 #define JPEG_NEXT (BUTTON_MENU | BUTTON_RIGHT)
70 #define JPEG_PREVIOUS (BUTTON_MENU | BUTTON_LEFT)
71 #define JPEG_MENU BUTTON_OFF
73 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
74 (CONFIG_KEYPAD == IRIVER_H300_PAD)
75 #define JPEG_ZOOM_IN BUTTON_SELECT
76 #define JPEG_ZOOM_OUT BUTTON_MODE
77 #define JPEG_UP BUTTON_UP
78 #define JPEG_DOWN BUTTON_DOWN
79 #define JPEG_LEFT BUTTON_LEFT
80 #define JPEG_RIGHT BUTTON_RIGHT
81 #if (CONFIG_KEYPAD == IRIVER_H100_PAD)
82 #define JPEG_NEXT BUTTON_ON
83 #define JPEG_PREVIOUS BUTTON_REC
85 #define JPEG_NEXT BUTTON_REC
86 #define JPEG_PREVIOUS BUTTON_ON
88 #define JPEG_MENU BUTTON_OFF
89 #define JPEG_RC_MENU BUTTON_RC_STOP
91 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
92 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
93 #define JPEG_ZOOM_IN BUTTON_SCROLL_FWD
94 #define JPEG_ZOOM_OUT BUTTON_SCROLL_BACK
95 #define JPEG_UP BUTTON_MENU
96 #define JPEG_DOWN BUTTON_PLAY
97 #define JPEG_LEFT BUTTON_LEFT
98 #define JPEG_RIGHT BUTTON_RIGHT
99 #define JPEG_MENU (BUTTON_SELECT | BUTTON_MENU)
100 #define JPEG_NEXT (BUTTON_SELECT | BUTTON_RIGHT)
101 #define JPEG_PREVIOUS (BUTTON_SELECT | BUTTON_LEFT)
103 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
104 #define JPEG_ZOOM_PRE BUTTON_SELECT
105 #define JPEG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
106 #define JPEG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
107 #define JPEG_UP BUTTON_UP
108 #define JPEG_DOWN BUTTON_DOWN
109 #define JPEG_LEFT BUTTON_LEFT
110 #define JPEG_RIGHT BUTTON_RIGHT
111 #define JPEG_MENU BUTTON_POWER
112 #define JPEG_NEXT BUTTON_PLAY
113 #define JPEG_PREVIOUS BUTTON_REC
115 #elif CONFIG_KEYPAD == GIGABEAT_PAD
116 #define JPEG_ZOOM_IN BUTTON_VOL_UP
117 #define JPEG_ZOOM_OUT BUTTON_VOL_DOWN
118 #define JPEG_UP BUTTON_UP
119 #define JPEG_DOWN BUTTON_DOWN
120 #define JPEG_LEFT BUTTON_LEFT
121 #define JPEG_RIGHT BUTTON_RIGHT
122 #define JPEG_MENU BUTTON_MENU
123 #define JPEG_NEXT (BUTTON_A | BUTTON_RIGHT)
124 #define JPEG_PREVIOUS (BUTTON_A | BUTTON_LEFT)
126 #elif CONFIG_KEYPAD == SANSA_E200_PAD
127 #define JPEG_ZOOM_PRE BUTTON_SELECT
128 #define JPEG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
129 #define JPEG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
130 #define JPEG_UP BUTTON_UP
131 #define JPEG_DOWN BUTTON_DOWN
132 #define JPEG_LEFT BUTTON_LEFT
133 #define JPEG_RIGHT BUTTON_RIGHT
134 #define JPEG_MENU BUTTON_POWER
135 #define JPEG_SLIDE_SHOW BUTTON_REC
136 #define JPEG_NEXT BUTTON_SCROLL_FWD
137 #define JPEG_NEXT_REPEAT (BUTTON_SCROLL_FWD|BUTTON_REPEAT)
138 #define JPEG_PREVIOUS BUTTON_SCROLL_BACK
139 #define JPEG_PREVIOUS_REPEAT (BUTTON_SCROLL_BACK|BUTTON_REPEAT)
141 #elif CONFIG_KEYPAD == SANSA_C200_PAD
142 #define JPEG_ZOOM_PRE BUTTON_SELECT
143 #define JPEG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
144 #define JPEG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
145 #define JPEG_UP BUTTON_UP
146 #define JPEG_DOWN BUTTON_DOWN
147 #define JPEG_LEFT BUTTON_LEFT
148 #define JPEG_RIGHT BUTTON_RIGHT
149 #define JPEG_MENU BUTTON_POWER
150 #define JPEG_SLIDE_SHOW BUTTON_REC
151 #define JPEG_NEXT BUTTON_VOL_UP
152 #define JPEG_NEXT_REPEAT (BUTTON_VOL_UP|BUTTON_REPEAT)
153 #define JPEG_PREVIOUS BUTTON_VOL_DOWN
154 #define JPEG_PREVIOUS_REPEAT (BUTTON_VOL_DOWN|BUTTON_REPEAT)
156 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
157 #define JPEG_ZOOM_PRE BUTTON_PLAY
158 #define JPEG_ZOOM_IN (BUTTON_PLAY | BUTTON_REL)
159 #define JPEG_ZOOM_OUT (BUTTON_PLAY | BUTTON_REPEAT)
160 #define JPEG_UP BUTTON_SCROLL_UP
161 #define JPEG_DOWN BUTTON_SCROLL_DOWN
162 #define JPEG_LEFT BUTTON_LEFT
163 #define JPEG_RIGHT BUTTON_RIGHT
164 #define JPEG_MENU BUTTON_POWER
165 #define JPEG_NEXT BUTTON_FF
166 #define JPEG_PREVIOUS BUTTON_REW
168 #elif CONFIG_KEYPAD == MROBE500_PAD
169 #define JPEG_ZOOM_IN BUTTON_RC_VOL_UP
170 #define JPEG_ZOOM_OUT BUTTON_RC_VOL_DOWN
171 #define JPEG_UP BUTTON_RC_PLAY
172 #define JPEG_DOWN BUTTON_RC_DOWN
173 #define JPEG_LEFT BUTTON_LEFT
174 #define JPEG_RIGHT BUTTON_RIGHT
175 #define JPEG_MENU BUTTON_POWER
176 #define JPEG_NEXT BUTTON_RC_HEART
177 #define JPEG_PREVIOUS BUTTON_RC_MODE
179 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
180 #define JPEG_ZOOM_IN BUTTON_VOL_UP
181 #define JPEG_ZOOM_OUT BUTTON_VOL_DOWN
182 #define JPEG_UP BUTTON_UP
183 #define JPEG_DOWN BUTTON_DOWN
184 #define JPEG_LEFT BUTTON_LEFT
185 #define JPEG_RIGHT BUTTON_RIGHT
186 #define JPEG_MENU BUTTON_MENU
187 #define JPEG_NEXT BUTTON_NEXT
188 #define JPEG_PREVIOUS BUTTON_PREV
192 /* different graphics libraries */
196 #define MYLCD(fn) grey_ub_ ## fn
197 #define MYLCD_UPDATE()
198 #define MYXLCD(fn) grey_ub_ ## fn
200 #define MYLCD(fn) rb->lcd_ ## fn
201 #define MYLCD_UPDATE() rb->lcd_update();
202 #define MYXLCD(fn) xlcd_ ## fn
205 #define MAX_X_SIZE LCD_WIDTH*8
207 /* Min memory allowing us to use the plugin buffer
208 * and thus not stopping the music
209 * *Very* rough estimation:
210 * Max 10 000 dir entries * 4bytes/entry (char **) = 40000 bytes
211 * + 20k code size = 60 000
212 * + 50k min for jpeg = 120 000
214 #define MIN_MEM 120000
221 #define PLUGIN_OTHER 10 /* State code for output with return. */
223 /******************************* Globals ***********************************/
225 static struct plugin_api
* rb
;
226 MEM_FUNCTION_WRAPPERS(rb
);
228 /* for portability of below JPEG code */
229 #define MEMSET(p,v,c) rb->memset(p,v,c)
230 #define MEMCPY(d,s,c) rb->memcpy(d,s,c)
231 #define INLINE static inline
232 #define ENDIAN_SWAP16(n) n /* only for poor little endian machines */
234 static int slideshow_enabled
= false; /* run slideshow */
235 static int running_slideshow
= false; /* loading image because of slideshw */
237 static int immediate_ata_off
= false; /* power down disk after loading */
240 /* Persistent configuration */
241 #define JPEG_CONFIGFILE "jpeg.cfg"
242 #define JPEG_SETTINGS_MINVERSION 1
243 #define JPEG_SETTINGS_VERSION 2
245 /* Slideshow times */
246 #define SS_MIN_TIMEOUT 1
247 #define SS_MAX_TIMEOUT 20
248 #define SS_DEFAULT_TIMEOUT 5
252 COLOURMODE_COLOUR
= 0,
259 DITHER_NONE
= 0, /* No dithering */
260 DITHER_ORDERED
, /* Bayer ordered */
261 DITHER_DIFFUSION
, /* Floyd/Steinberg error diffusion */
272 static struct jpeg_settings jpeg_settings
=
273 { COLOURMODE_COLOUR
, DITHER_NONE
, SS_DEFAULT_TIMEOUT
};
274 static struct jpeg_settings old_settings
;
276 static struct configdata jpeg_config
[] =
278 #ifdef HAVE_LCD_COLOR
279 { TYPE_ENUM
, 0, COLOUR_NUM_MODES
, &jpeg_settings
.colour_mode
,
280 "Colour Mode", (char *[]){ "Colour", "Grayscale" }, NULL
},
281 { TYPE_ENUM
, 0, DITHER_NUM_MODES
, &jpeg_settings
.dither_mode
,
282 "Dither Mode", (char *[]){ "None", "Ordered", "Diffusion" }, NULL
},
284 { TYPE_INT
, SS_MIN_TIMEOUT
, SS_MAX_TIMEOUT
, &jpeg_settings
.ss_timeout
,
285 "Slideshow Time", NULL
, NULL
},
289 fb_data
* old_backdrop
;
292 /**************** begin JPEG code ********************/
294 INLINE
unsigned range_limit(int value
)
296 #if CONFIG_CPU == SH7034
298 asm ( /* Note: Uses knowledge that only low byte of result is used */
300 "sub %[t],%[v] \n" /* value -= -128; equals value += 128; */
301 "extu.b %[v],%[t] \n"
302 "cmp/eq %[v],%[t] \n" /* low byte == whole number ? */
303 "bt 1f \n" /* yes: no overflow */
304 "cmp/pz %[v] \n" /* overflow: positive? */
305 "subc %[v],%[v] \n" /* %[r] now either 0 or 0xffffffff */
312 #elif defined(CPU_COLDFIRE)
313 asm ( /* Note: Uses knowledge that only the low byte of the result is used */
314 "add.l #128,%[v] \n" /* value += 128; */
315 "cmp.l #255,%[v] \n" /* overflow? */
316 "bls.b 1f \n" /* no: return value */
317 "spl.b %[v] \n" /* yes: set low byte to appropriate boundary */
323 #elif defined(CPU_ARM)
324 asm ( /* Note: Uses knowledge that only the low byte of the result is used */
325 "add %[v], %[v], #128 \n" /* value += 128 */
326 "cmp %[v], #255 \n" /* out of range 0..255? */
327 "mvnhi %[v], %[v], asr #31 \n" /* yes: set all bits to ~(sign_bit) */
335 if ((unsigned)value
<= 255)
345 /* IDCT implementation */
348 #define CONST_BITS 13
352 /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
353 * causing a lot of useless floating-point operations at run time.
354 * To get around this we use the following pre-calculated constants.
355 * If you change CONST_BITS you may want to add appropriate values.
356 * (With a reasonable C compiler, you can just rely on the FIX() macro...)
358 #define FIX_0_298631336 2446 /* FIX(0.298631336) */
359 #define FIX_0_390180644 3196 /* FIX(0.390180644) */
360 #define FIX_0_541196100 4433 /* FIX(0.541196100) */
361 #define FIX_0_765366865 6270 /* FIX(0.765366865) */
362 #define FIX_0_899976223 7373 /* FIX(0.899976223) */
363 #define FIX_1_175875602 9633 /* FIX(1.175875602) */
364 #define FIX_1_501321110 12299 /* FIX(1.501321110) */
365 #define FIX_1_847759065 15137 /* FIX(1.847759065) */
366 #define FIX_1_961570560 16069 /* FIX(1.961570560) */
367 #define FIX_2_053119869 16819 /* FIX(2.053119869) */
368 #define FIX_2_562915447 20995 /* FIX(2.562915447) */
369 #define FIX_3_072711026 25172 /* FIX(3.072711026) */
373 /* Multiply an long variable by an long constant to yield an long result.
374 * For 8-bit samples with the recommended scaling, all the variable
375 * and constant values involved are no more than 16 bits wide, so a
376 * 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
377 * For 12-bit samples, a full 32-bit multiplication will be needed.
379 #define MULTIPLY16(var,const) (((short) (var)) * ((short) (const)))
382 /* Dequantize a coefficient by multiplying it by the multiplier-table
383 * entry; produce an int result. In this module, both inputs and result
384 * are 16 bits or less, so either int or short multiply will work.
386 /* #define DEQUANTIZE(coef,quantval) (((int) (coef)) * (quantval)) */
387 #define DEQUANTIZE MULTIPLY16
389 /* Descale and correctly round an int value that's scaled by N bits.
390 * We assume RIGHT_SHIFT rounds towards minus infinity, so adding
391 * the fudge factor is correct for either sign of X.
393 #define DESCALE(x,n) (((x) + (1l << ((n)-1))) >> (n))
398 * Perform dequantization and inverse DCT on one block of coefficients,
399 * producing a reduced-size 1x1 output block.
401 void idct1x1(unsigned char* p_byte
, int* inptr
, int* quantptr
, int skip_line
)
403 (void)skip_line
; /* unused */
404 *p_byte
= range_limit(inptr
[0] * quantptr
[0] >> 3);
410 * Perform dequantization and inverse DCT on one block of coefficients,
411 * producing a reduced-size 2x2 output block.
413 void idct2x2(unsigned char* p_byte
, int* inptr
, int* quantptr
, int skip_line
)
415 int tmp0
, tmp1
, tmp2
, tmp3
, tmp4
, tmp5
;
416 unsigned char* outptr
;
418 /* Pass 1: process columns from input, store into work array. */
421 tmp4
= DEQUANTIZE(inptr
[8*0], quantptr
[8*0]);
422 tmp5
= DEQUANTIZE(inptr
[8*1], quantptr
[8*1]);
428 tmp4
= DEQUANTIZE(inptr
[8*0+1], quantptr
[8*0+1]);
429 tmp5
= DEQUANTIZE(inptr
[8*1+1], quantptr
[8*1+1]);
434 /* Pass 2: process 2 rows, store into output array. */
439 outptr
[0] = range_limit((int) DESCALE(tmp0
+ tmp1
, 3));
440 outptr
[1] = range_limit((int) DESCALE(tmp0
- tmp1
, 3));
443 outptr
= p_byte
+ skip_line
;
445 outptr
[0] = range_limit((int) DESCALE(tmp2
+ tmp3
, 3));
446 outptr
[1] = range_limit((int) DESCALE(tmp2
- tmp3
, 3));
452 * Perform dequantization and inverse DCT on one block of coefficients,
453 * producing a reduced-size 4x4 output block.
455 void idct4x4(unsigned char* p_byte
, int* inptr
, int* quantptr
, int skip_line
)
457 int tmp0
, tmp2
, tmp10
, tmp12
;
460 unsigned char* outptr
;
462 int workspace
[4*4]; /* buffers data between passes */
464 /* Pass 1: process columns from input, store into work array. */
467 for (ctr
= 0; ctr
< 4; ctr
++, inptr
++, quantptr
++, wsptr
++)
471 tmp0
= DEQUANTIZE(inptr
[8*0], quantptr
[8*0]);
472 tmp2
= DEQUANTIZE(inptr
[8*2], quantptr
[8*2]);
474 tmp10
= (tmp0
+ tmp2
) << PASS1_BITS
;
475 tmp12
= (tmp0
- tmp2
) << PASS1_BITS
;
478 /* Same rotation as in the even part of the 8x8 LL&M IDCT */
480 z2
= DEQUANTIZE(inptr
[8*1], quantptr
[8*1]);
481 z3
= DEQUANTIZE(inptr
[8*3], quantptr
[8*3]);
483 z1
= MULTIPLY16(z2
+ z3
, FIX_0_541196100
);
484 tmp0
= DESCALE(z1
+ MULTIPLY16(z3
, - FIX_1_847759065
), CONST_BITS
-PASS1_BITS
);
485 tmp2
= DESCALE(z1
+ MULTIPLY16(z2
, FIX_0_765366865
), CONST_BITS
-PASS1_BITS
);
487 /* Final output stage */
489 wsptr
[4*0] = (int) (tmp10
+ tmp2
);
490 wsptr
[4*3] = (int) (tmp10
- tmp2
);
491 wsptr
[4*1] = (int) (tmp12
+ tmp0
);
492 wsptr
[4*2] = (int) (tmp12
- tmp0
);
495 /* Pass 2: process 4 rows from work array, store into output array. */
498 for (ctr
= 0; ctr
< 4; ctr
++)
500 outptr
= p_byte
+ (ctr
*skip_line
);
503 tmp0
= (int) wsptr
[0];
504 tmp2
= (int) wsptr
[2];
506 tmp10
= (tmp0
+ tmp2
) << CONST_BITS
;
507 tmp12
= (tmp0
- tmp2
) << CONST_BITS
;
510 /* Same rotation as in the even part of the 8x8 LL&M IDCT */
515 z1
= MULTIPLY16(z2
+ z3
, FIX_0_541196100
);
516 tmp0
= z1
+ MULTIPLY16(z3
, - FIX_1_847759065
);
517 tmp2
= z1
+ MULTIPLY16(z2
, FIX_0_765366865
);
519 /* Final output stage */
521 outptr
[0] = range_limit((int) DESCALE(tmp10
+ tmp2
,
522 CONST_BITS
+PASS1_BITS
+3));
523 outptr
[3] = range_limit((int) DESCALE(tmp10
- tmp2
,
524 CONST_BITS
+PASS1_BITS
+3));
525 outptr
[1] = range_limit((int) DESCALE(tmp12
+ tmp0
,
526 CONST_BITS
+PASS1_BITS
+3));
527 outptr
[2] = range_limit((int) DESCALE(tmp12
- tmp0
,
528 CONST_BITS
+PASS1_BITS
+3));
530 wsptr
+= 4; /* advance pointer to next row */
537 * Perform dequantization and inverse DCT on one block of coefficients.
539 void idct8x8(unsigned char* p_byte
, int* inptr
, int* quantptr
, int skip_line
)
541 long tmp0
, tmp1
, tmp2
, tmp3
;
542 long tmp10
, tmp11
, tmp12
, tmp13
;
543 long z1
, z2
, z3
, z4
, z5
;
545 unsigned char* outptr
;
547 int workspace
[64]; /* buffers data between passes */
549 /* Pass 1: process columns from input, store into work array. */
550 /* Note results are scaled up by sqrt(8) compared to a true IDCT; */
551 /* furthermore, we scale the results by 2**PASS1_BITS. */
554 for (ctr
= 8; ctr
> 0; ctr
--)
556 /* Due to quantization, we will usually find that many of the input
557 * coefficients are zero, especially the AC terms. We can exploit this
558 * by short-circuiting the IDCT calculation for any column in which all
559 * the AC terms are zero. In that case each output is equal to the
560 * DC coefficient (with scale factor as needed).
561 * With typical images and quantization tables, half or more of the
562 * column DCT calculations can be simplified this way.
565 if ((inptr
[8*1] | inptr
[8*2] | inptr
[8*3]
566 | inptr
[8*4] | inptr
[8*5] | inptr
[8*6] | inptr
[8*7]) == 0)
568 /* AC terms all zero */
569 int dcval
= DEQUANTIZE(inptr
[8*0], quantptr
[8*0]) << PASS1_BITS
;
571 wsptr
[8*0] = wsptr
[8*1] = wsptr
[8*2] = wsptr
[8*3] = wsptr
[8*4]
572 = wsptr
[8*5] = wsptr
[8*6] = wsptr
[8*7] = dcval
;
573 inptr
++; /* advance pointers to next column */
579 /* Even part: reverse the even part of the forward DCT. */
580 /* The rotator is sqrt(2)*c(-6). */
582 z2
= DEQUANTIZE(inptr
[8*2], quantptr
[8*2]);
583 z3
= DEQUANTIZE(inptr
[8*6], quantptr
[8*6]);
585 z1
= MULTIPLY16(z2
+ z3
, FIX_0_541196100
);
586 tmp2
= z1
+ MULTIPLY16(z3
, - FIX_1_847759065
);
587 tmp3
= z1
+ MULTIPLY16(z2
, FIX_0_765366865
);
589 z2
= DEQUANTIZE(inptr
[8*0], quantptr
[8*0]);
590 z3
= DEQUANTIZE(inptr
[8*4], quantptr
[8*4]);
592 tmp0
= (z2
+ z3
) << CONST_BITS
;
593 tmp1
= (z2
- z3
) << CONST_BITS
;
600 /* Odd part per figure 8; the matrix is unitary and hence its
601 transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */
603 tmp0
= DEQUANTIZE(inptr
[8*7], quantptr
[8*7]);
604 tmp1
= DEQUANTIZE(inptr
[8*5], quantptr
[8*5]);
605 tmp2
= DEQUANTIZE(inptr
[8*3], quantptr
[8*3]);
606 tmp3
= DEQUANTIZE(inptr
[8*1], quantptr
[8*1]);
612 z5
= MULTIPLY16(z3
+ z4
, FIX_1_175875602
); /* sqrt(2) * c3 */
614 tmp0
= MULTIPLY16(tmp0
, FIX_0_298631336
); /* sqrt(2) * (-c1+c3+c5-c7) */
615 tmp1
= MULTIPLY16(tmp1
, FIX_2_053119869
); /* sqrt(2) * ( c1+c3-c5+c7) */
616 tmp2
= MULTIPLY16(tmp2
, FIX_3_072711026
); /* sqrt(2) * ( c1+c3+c5-c7) */
617 tmp3
= MULTIPLY16(tmp3
, FIX_1_501321110
); /* sqrt(2) * ( c1+c3-c5-c7) */
618 z1
= MULTIPLY16(z1
, - FIX_0_899976223
); /* sqrt(2) * (c7-c3) */
619 z2
= MULTIPLY16(z2
, - FIX_2_562915447
); /* sqrt(2) * (-c1-c3) */
620 z3
= MULTIPLY16(z3
, - FIX_1_961570560
); /* sqrt(2) * (-c3-c5) */
621 z4
= MULTIPLY16(z4
, - FIX_0_390180644
); /* sqrt(2) * (c5-c3) */
631 /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
633 wsptr
[8*0] = (int) DESCALE(tmp10
+ tmp3
, CONST_BITS
-PASS1_BITS
);
634 wsptr
[8*7] = (int) DESCALE(tmp10
- tmp3
, CONST_BITS
-PASS1_BITS
);
635 wsptr
[8*1] = (int) DESCALE(tmp11
+ tmp2
, CONST_BITS
-PASS1_BITS
);
636 wsptr
[8*6] = (int) DESCALE(tmp11
- tmp2
, CONST_BITS
-PASS1_BITS
);
637 wsptr
[8*2] = (int) DESCALE(tmp12
+ tmp1
, CONST_BITS
-PASS1_BITS
);
638 wsptr
[8*5] = (int) DESCALE(tmp12
- tmp1
, CONST_BITS
-PASS1_BITS
);
639 wsptr
[8*3] = (int) DESCALE(tmp13
+ tmp0
, CONST_BITS
-PASS1_BITS
);
640 wsptr
[8*4] = (int) DESCALE(tmp13
- tmp0
, CONST_BITS
-PASS1_BITS
);
642 inptr
++; /* advance pointers to next column */
647 /* Pass 2: process rows from work array, store into output array. */
648 /* Note that we must descale the results by a factor of 8 == 2**3, */
649 /* and also undo the PASS1_BITS scaling. */
652 for (ctr
= 0; ctr
< 8; ctr
++)
654 outptr
= p_byte
+ (ctr
*skip_line
);
655 /* Rows of zeroes can be exploited in the same way as we did with columns.
656 * However, the column calculation has created many nonzero AC terms, so
657 * the simplification applies less often (typically 5% to 10% of the time).
658 * On machines with very fast multiplication, it's possible that the
659 * test takes more time than it's worth. In that case this section
660 * may be commented out.
663 #ifndef NO_ZERO_ROW_TEST
664 if ((wsptr
[1] | wsptr
[2] | wsptr
[3]
665 | wsptr
[4] | wsptr
[5] | wsptr
[6] | wsptr
[7]) == 0)
667 /* AC terms all zero */
668 unsigned char dcval
= range_limit((int) DESCALE((long) wsptr
[0],
680 wsptr
+= 8; /* advance pointer to next row */
685 /* Even part: reverse the even part of the forward DCT. */
686 /* The rotator is sqrt(2)*c(-6). */
688 z2
= (long) wsptr
[2];
689 z3
= (long) wsptr
[6];
691 z1
= MULTIPLY16(z2
+ z3
, FIX_0_541196100
);
692 tmp2
= z1
+ MULTIPLY16(z3
, - FIX_1_847759065
);
693 tmp3
= z1
+ MULTIPLY16(z2
, FIX_0_765366865
);
695 tmp0
= ((long) wsptr
[0] + (long) wsptr
[4]) << CONST_BITS
;
696 tmp1
= ((long) wsptr
[0] - (long) wsptr
[4]) << CONST_BITS
;
703 /* Odd part per figure 8; the matrix is unitary and hence its
704 * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */
706 tmp0
= (long) wsptr
[7];
707 tmp1
= (long) wsptr
[5];
708 tmp2
= (long) wsptr
[3];
709 tmp3
= (long) wsptr
[1];
715 z5
= MULTIPLY16(z3
+ z4
, FIX_1_175875602
); /* sqrt(2) * c3 */
717 tmp0
= MULTIPLY16(tmp0
, FIX_0_298631336
); /* sqrt(2) * (-c1+c3+c5-c7) */
718 tmp1
= MULTIPLY16(tmp1
, FIX_2_053119869
); /* sqrt(2) * ( c1+c3-c5+c7) */
719 tmp2
= MULTIPLY16(tmp2
, FIX_3_072711026
); /* sqrt(2) * ( c1+c3+c5-c7) */
720 tmp3
= MULTIPLY16(tmp3
, FIX_1_501321110
); /* sqrt(2) * ( c1+c3-c5-c7) */
721 z1
= MULTIPLY16(z1
, - FIX_0_899976223
); /* sqrt(2) * (c7-c3) */
722 z2
= MULTIPLY16(z2
, - FIX_2_562915447
); /* sqrt(2) * (-c1-c3) */
723 z3
= MULTIPLY16(z3
, - FIX_1_961570560
); /* sqrt(2) * (-c3-c5) */
724 z4
= MULTIPLY16(z4
, - FIX_0_390180644
); /* sqrt(2) * (c5-c3) */
734 /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
736 outptr
[0] = range_limit((int) DESCALE(tmp10
+ tmp3
,
737 CONST_BITS
+PASS1_BITS
+3));
738 outptr
[7] = range_limit((int) DESCALE(tmp10
- tmp3
,
739 CONST_BITS
+PASS1_BITS
+3));
740 outptr
[1] = range_limit((int) DESCALE(tmp11
+ tmp2
,
741 CONST_BITS
+PASS1_BITS
+3));
742 outptr
[6] = range_limit((int) DESCALE(tmp11
- tmp2
,
743 CONST_BITS
+PASS1_BITS
+3));
744 outptr
[2] = range_limit((int) DESCALE(tmp12
+ tmp1
,
745 CONST_BITS
+PASS1_BITS
+3));
746 outptr
[5] = range_limit((int) DESCALE(tmp12
- tmp1
,
747 CONST_BITS
+PASS1_BITS
+3));
748 outptr
[3] = range_limit((int) DESCALE(tmp13
+ tmp0
,
749 CONST_BITS
+PASS1_BITS
+3));
750 outptr
[4] = range_limit((int) DESCALE(tmp13
- tmp0
,
751 CONST_BITS
+PASS1_BITS
+3));
753 wsptr
+= 8; /* advance pointer to next row */
759 /* JPEG decoder implementation */
762 #define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */
766 /* Basic tables: (element [0] of each array is unused) */
767 long mincode
[17]; /* smallest code of length k */
768 long maxcode
[18]; /* largest code of length k (-1 if none) */
769 /* (maxcode[17] is a sentinel to ensure huff_DECODE terminates) */
770 int valptr
[17]; /* huffval[] index of 1st symbol of length k */
772 /* Back link to public Huffman table (needed only in slow_DECODE) */
775 /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of
776 the input data stream. If the next Huffman code is no more
777 than HUFF_LOOKAHEAD bits long, we can obtain its length and
778 the corresponding symbol directly from these tables. */
779 int look_nbits
[1<<HUFF_LOOKAHEAD
]; /* # bits, or 0 if too long */
780 unsigned char look_sym
[1<<HUFF_LOOKAHEAD
]; /* symbol, or unused */
783 #define QUANT_TABLE_LENGTH 64
785 /* for type of Huffman table */
790 { /* length and code according to JFIF format */
791 int huffmancodes_dc
[DC_LEN
];
792 int huffmancodes_ac
[AC_LEN
];
795 struct frame_component
798 int horizontal_sampling
;
799 int vertical_sampling
;
800 int quanttable_select
;
803 struct scan_component
812 unsigned long get_buffer
; /* current bit-extraction buffer */
813 int bits_left
; /* # of unused bits in it */
814 unsigned char* next_input_byte
;
815 unsigned char* input_end
; /* upper limit +1 */
820 int x_size
, y_size
; /* size of image (can be less than block boundary) */
821 int x_phys
, y_phys
; /* physical size, block aligned */
822 int x_mbl
; /* x dimension of MBL */
823 int y_mbl
; /* y dimension of MBL */
824 int blocks
; /* blocks per MB */
825 int restart_interval
; /* number of MCUs between RSTm markers */
826 int store_pos
[4]; /* for Y block ordering */
828 unsigned char* p_entropy_data
;
829 unsigned char* p_entropy_end
;
831 int quanttable
[4][QUANT_TABLE_LENGTH
]; /* raw quantization tables 0-3 */
832 int qt_idct
[2][QUANT_TABLE_LENGTH
]; /* quantization tables for IDCT */
834 struct huffman_table hufftable
[2]; /* Huffman tables */
835 struct derived_tbl dc_derived_tbls
[2]; /* Huffman-LUTs */
836 struct derived_tbl ac_derived_tbls
[2];
838 struct frame_component frameheader
[3]; /* Component descriptor */
839 struct scan_component scanheader
[3]; /* currently not used */
841 int mcu_membership
[6]; /* info per block */
842 int tab_membership
[6];
843 int subsample_x
[3]; /* info per component */
848 /* possible return flags for process_markers() */
849 #define HUFFTAB 0x0001 /* with huffman table */
850 #define QUANTTAB 0x0002 /* with quantization table */
851 #define APP0_JFIF 0x0004 /* with APP0 segment following JFIF standard */
852 #define FILL_FF 0x0008 /* with 0xFF padding bytes at begin/end */
853 #define SOF0 0x0010 /* with SOF0-Segment */
854 #define DHT 0x0020 /* with Definition of huffman tables */
855 #define SOS 0x0040 /* with Start-of-Scan segment */
856 #define DQT 0x0080 /* with definition of quantization table */
858 /* Preprocess the JPEG JFIF file */
859 int process_markers(unsigned char* p_src
, long size
, struct jpeg
* p_jpeg
)
861 unsigned char* p_bytes
= p_src
;
862 int marker_size
; /* variable length of marker segment */
864 int ret
= 0; /* returned flags */
866 p_jpeg
->p_entropy_end
= p_src
+ size
;
868 while (p_src
< p_bytes
+ size
)
870 if (*p_src
++ != 0xFF) /* no marker? */
872 p_src
--; /* it's image data, put it back */
873 p_jpeg
->p_entropy_data
= p_src
;
874 break; /* exit marker processing */
879 case 0xFF: /* Fill byte */
881 case 0x00: /* Zero stuffed byte - entropy data */
882 p_src
--; /* put it back */
885 case 0xC0: /* SOF Huff - Baseline DCT */
888 marker_size
= *p_src
++ << 8; /* Highbyte */
889 marker_size
|= *p_src
++; /* Lowbyte */
890 n
= *p_src
++; /* sample precision (= 8 or 12) */
893 return(-1); /* Unsupported sample precision */
895 p_jpeg
->y_size
= *p_src
++ << 8; /* Highbyte */
896 p_jpeg
->y_size
|= *p_src
++; /* Lowbyte */
897 p_jpeg
->x_size
= *p_src
++ << 8; /* Highbyte */
898 p_jpeg
->x_size
|= *p_src
++; /* Lowbyte */
900 n
= (marker_size
-2-6)/3;
901 if (*p_src
++ != n
|| (n
!= 1 && n
!= 3))
903 return(-2); /* Unsupported SOF0 component specification */
907 p_jpeg
->frameheader
[i
].ID
= *p_src
++; /* Component info */
908 p_jpeg
->frameheader
[i
].horizontal_sampling
= *p_src
>> 4;
909 p_jpeg
->frameheader
[i
].vertical_sampling
= *p_src
++ & 0x0F;
910 p_jpeg
->frameheader
[i
].quanttable_select
= *p_src
++;
911 if (p_jpeg
->frameheader
[i
].horizontal_sampling
> 2
912 || p_jpeg
->frameheader
[i
].vertical_sampling
> 2)
913 return -3; /* Unsupported SOF0 subsampling */
919 case 0xC1: /* SOF Huff - Extended sequential DCT*/
920 case 0xC2: /* SOF Huff - Progressive DCT*/
921 case 0xC3: /* SOF Huff - Spatial (sequential) lossless*/
922 case 0xC5: /* SOF Huff - Differential sequential DCT*/
923 case 0xC6: /* SOF Huff - Differential progressive DCT*/
924 case 0xC7: /* SOF Huff - Differential spatial*/
925 case 0xC8: /* SOF Arith - Reserved for JPEG extensions*/
926 case 0xC9: /* SOF Arith - Extended sequential DCT*/
927 case 0xCA: /* SOF Arith - Progressive DCT*/
928 case 0xCB: /* SOF Arith - Spatial (sequential) lossless*/
929 case 0xCD: /* SOF Arith - Differential sequential DCT*/
930 case 0xCE: /* SOF Arith - Differential progressive DCT*/
931 case 0xCF: /* SOF Arith - Differential spatial*/
933 return (-4); /* other DCT model than baseline not implemented */
936 case 0xC4: /* Define Huffman Table(s) */
938 unsigned char* p_temp
;
941 marker_size
= *p_src
++ << 8; /* Highbyte */
942 marker_size
|= *p_src
++; /* Lowbyte */
945 while (p_src
< p_temp
+marker_size
-2-17) /* another table */
948 i
= *p_src
& 0x0F; /* table index */
951 return (-5); /* Huffman table index out of range */
953 else if (*p_src
++ & 0xF0) /* AC table */
958 p_jpeg
->hufftable
[i
].huffmancodes_ac
[j
] = *p_src
++;
960 if(16 + sum
> AC_LEN
)
961 return -10; /* longer than allowed */
963 for (; j
< 16 + sum
; j
++)
964 p_jpeg
->hufftable
[i
].huffmancodes_ac
[j
] = *p_src
++;
971 p_jpeg
->hufftable
[i
].huffmancodes_dc
[j
] = *p_src
++;
973 if(16 + sum
> DC_LEN
)
974 return -11; /* longer than allowed */
976 for (; j
< 16 + sum
; j
++)
977 p_jpeg
->hufftable
[i
].huffmancodes_dc
[j
] = *p_src
++;
980 p_src
= p_temp
+marker_size
- 2; /* skip possible residue */
984 case 0xCC: /* Define Arithmetic coding conditioning(s) */
985 return(-6); /* Arithmetic coding not supported */
987 case 0xD8: /* Start of Image */
988 case 0xD9: /* End of Image */
989 case 0x01: /* for temp private use arith code */
990 break; /* skip parameterless marker */
993 case 0xDA: /* Start of Scan */
996 marker_size
= *p_src
++ << 8; /* Highbyte */
997 marker_size
|= *p_src
++; /* Lowbyte */
999 n
= (marker_size
-2-1-3)/2;
1000 if (*p_src
++ != n
|| (n
!= 1 && n
!= 3))
1002 return (-7); /* Unsupported SOS component specification */
1006 p_jpeg
->scanheader
[i
].ID
= *p_src
++;
1007 p_jpeg
->scanheader
[i
].DC_select
= *p_src
>> 4;
1008 p_jpeg
->scanheader
[i
].AC_select
= *p_src
++ & 0x0F;
1010 p_src
+= 3; /* skip spectral information */
1014 case 0xDB: /* Define quantization Table(s) */
1017 marker_size
= *p_src
++ << 8; /* Highbyte */
1018 marker_size
|= *p_src
++; /* Lowbyte */
1019 n
= (marker_size
-2)/(QUANT_TABLE_LENGTH
+1); /* # of tables */
1022 int id
= *p_src
++; /* ID */
1025 return (-8); /* Unsupported quantization table */
1027 /* Read Quantisation table: */
1028 for (j
=0; j
<QUANT_TABLE_LENGTH
; j
++)
1029 p_jpeg
->quanttable
[id
][j
] = *p_src
++;
1034 case 0xDD: /* Define Restart Interval */
1036 marker_size
= *p_src
++ << 8; /* Highbyte */
1037 marker_size
|= *p_src
++; /* Lowbyte */
1038 p_jpeg
->restart_interval
= *p_src
++ << 8; /* Highbyte */
1039 p_jpeg
->restart_interval
|= *p_src
++; /* Lowbyte */
1040 p_src
+= marker_size
-4; /* skip segment */
1044 case 0xDC: /* Define Number of Lines */
1045 case 0xDE: /* Define Hierarchical progression */
1046 case 0xDF: /* Expand Reference Component(s) */
1047 case 0xE0: /* Application Field 0*/
1048 case 0xE1: /* Application Field 1*/
1049 case 0xE2: /* Application Field 2*/
1050 case 0xE3: /* Application Field 3*/
1051 case 0xE4: /* Application Field 4*/
1052 case 0xE5: /* Application Field 5*/
1053 case 0xE6: /* Application Field 6*/
1054 case 0xE7: /* Application Field 7*/
1055 case 0xE8: /* Application Field 8*/
1056 case 0xE9: /* Application Field 9*/
1057 case 0xEA: /* Application Field 10*/
1058 case 0xEB: /* Application Field 11*/
1059 case 0xEC: /* Application Field 12*/
1060 case 0xED: /* Application Field 13*/
1061 case 0xEE: /* Application Field 14*/
1062 case 0xEF: /* Application Field 15*/
1063 case 0xFE: /* Comment */
1065 marker_size
= *p_src
++ << 8; /* Highbyte */
1066 marker_size
|= *p_src
++; /* Lowbyte */
1067 p_src
+= marker_size
-2; /* skip segment */
1071 case 0xF0: /* Reserved for JPEG extensions */
1072 case 0xF1: /* Reserved for JPEG extensions */
1073 case 0xF2: /* Reserved for JPEG extensions */
1074 case 0xF3: /* Reserved for JPEG extensions */
1075 case 0xF4: /* Reserved for JPEG extensions */
1076 case 0xF5: /* Reserved for JPEG extensions */
1077 case 0xF6: /* Reserved for JPEG extensions */
1078 case 0xF7: /* Reserved for JPEG extensions */
1079 case 0xF8: /* Reserved for JPEG extensions */
1080 case 0xF9: /* Reserved for JPEG extensions */
1081 case 0xFA: /* Reserved for JPEG extensions */
1082 case 0xFB: /* Reserved for JPEG extensions */
1083 case 0xFC: /* Reserved for JPEG extensions */
1084 case 0xFD: /* Reserved for JPEG extensions */
1085 case 0x02: /* Reserved */
1087 return (-9); /* Unknown marker */
1091 return (ret
); /* return flags with seen markers */
1095 void default_huff_tbl(struct jpeg
* p_jpeg
)
1097 static const struct huffman_table luma_table
=
1100 0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,
1101 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B
1104 0x00,0x02,0x01,0x03,0x03,0x02,0x04,0x03,0x05,0x05,0x04,0x04,0x00,0x00,0x01,0x7D,
1105 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,
1106 0x22,0x71,0x14,0x32,0x81,0x91,0xA1,0x08,0x23,0x42,0xB1,0xC1,0x15,0x52,0xD1,0xF0,
1107 0x24,0x33,0x62,0x72,0x82,0x09,0x0A,0x16,0x17,0x18,0x19,0x1A,0x25,0x26,0x27,0x28,
1108 0x29,0x2A,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,
1109 0x4A,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,
1110 0x6A,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
1111 0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,
1112 0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xC2,0xC3,0xC4,0xC5,
1113 0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xE1,0xE2,
1114 0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,
1119 static const struct huffman_table chroma_table
=
1122 0x00,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,
1123 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B
1126 0x00,0x02,0x01,0x02,0x04,0x04,0x03,0x04,0x07,0x05,0x04,0x04,0x00,0x01,0x02,0x77,
1127 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,
1128 0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xA1,0xB1,0xC1,0x09,0x23,0x33,0x52,0xF0,
1129 0x15,0x62,0x72,0xD1,0x0A,0x16,0x24,0x34,0xE1,0x25,0xF1,0x17,0x18,0x19,0x1A,0x26,
1130 0x27,0x28,0x29,0x2A,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,
1131 0x49,0x4A,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,
1132 0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x82,0x83,0x84,0x85,0x86,0x87,
1133 0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5,
1134 0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xC2,0xC3,
1135 0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,
1136 0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,
1141 MEMCPY(&p_jpeg
->hufftable
[0], &luma_table
, sizeof(luma_table
));
1142 MEMCPY(&p_jpeg
->hufftable
[1], &chroma_table
, sizeof(chroma_table
));
1147 /* Compute the derived values for a Huffman table */
1148 void fix_huff_tbl(int* htbl
, struct derived_tbl
* dtbl
)
1153 unsigned int huffcode
[257];
1156 dtbl
->pub
= htbl
; /* fill in back link */
1158 /* Figure C.1: make table of Huffman code length for each symbol */
1159 /* Note that this is in code-length order. */
1162 for (l
= 1; l
<= 16; l
++)
1163 { /* all possible code length */
1164 for (i
= 1; i
<= (int) htbl
[l
-1]; i
++) /* all codes per length */
1165 huffsize
[p
++] = (char) l
;
1169 /* Figure C.2: generate the codes themselves */
1170 /* Note that this is in code-length order. */
1177 while (((int) huffsize
[p
]) == si
)
1179 huffcode
[p
++] = code
;
1186 /* Figure F.15: generate decoding tables for bit-sequential decoding */
1189 for (l
= 1; l
<= 16; l
++)
1193 dtbl
->valptr
[l
] = p
; /* huffval[] index of 1st symbol of code length l */
1194 dtbl
->mincode
[l
] = huffcode
[p
]; /* minimum code of length l */
1196 dtbl
->maxcode
[l
] = huffcode
[p
-1]; /* maximum code of length l */
1200 dtbl
->maxcode
[l
] = -1; /* -1 if no codes of this length */
1203 dtbl
->maxcode
[17] = 0xFFFFFL
; /* ensures huff_DECODE terminates */
1205 /* Compute lookahead tables to speed up decoding.
1206 * First we set all the table entries to 0, indicating "too long";
1207 * then we iterate through the Huffman codes that are short enough and
1208 * fill in all the entries that correspond to bit sequences starting
1212 MEMSET(dtbl
->look_nbits
, 0, sizeof(dtbl
->look_nbits
));
1215 for (l
= 1; l
<= HUFF_LOOKAHEAD
; l
++)
1217 for (i
= 1; i
<= (int) htbl
[l
-1]; i
++, p
++)
1219 /* l = current code's length, p = its index in huffcode[] & huffval[]. */
1220 /* Generate left-justified code followed by all possible bit sequences */
1221 lookbits
= huffcode
[p
] << (HUFF_LOOKAHEAD
-l
);
1222 for (ctr
= 1 << (HUFF_LOOKAHEAD
-l
); ctr
> 0; ctr
--)
1224 dtbl
->look_nbits
[lookbits
] = l
;
1225 dtbl
->look_sym
[lookbits
] = htbl
[16+p
];
1233 /* zag[i] is the natural-order position of the i'th element of zigzag order.
1234 * If the incoming data is corrupted, decode_mcu could attempt to
1235 * reference values beyond the end of the array. To avoid a wild store,
1236 * we put some extra zeroes after the real entries.
1238 static const int zag
[] =
1240 0, 1, 8, 16, 9, 2, 3, 10,
1241 17, 24, 32, 25, 18, 11, 4, 5,
1242 12, 19, 26, 33, 40, 48, 41, 34,
1243 27, 20, 13, 6, 7, 14, 21, 28,
1244 35, 42, 49, 56, 57, 50, 43, 36,
1245 29, 22, 15, 23, 30, 37, 44, 51,
1246 58, 59, 52, 45, 38, 31, 39, 46,
1247 53, 60, 61, 54, 47, 55, 62, 63,
1248 0, 0, 0, 0, 0, 0, 0, 0, /* extra entries in case k>63 below */
1249 0, 0, 0, 0, 0, 0, 0, 0
1252 void build_lut(struct jpeg
* p_jpeg
)
1255 fix_huff_tbl(p_jpeg
->hufftable
[0].huffmancodes_dc
,
1256 &p_jpeg
->dc_derived_tbls
[0]);
1257 fix_huff_tbl(p_jpeg
->hufftable
[0].huffmancodes_ac
,
1258 &p_jpeg
->ac_derived_tbls
[0]);
1259 fix_huff_tbl(p_jpeg
->hufftable
[1].huffmancodes_dc
,
1260 &p_jpeg
->dc_derived_tbls
[1]);
1261 fix_huff_tbl(p_jpeg
->hufftable
[1].huffmancodes_ac
,
1262 &p_jpeg
->ac_derived_tbls
[1]);
1264 /* build the dequantization tables for the IDCT (De-ZiZagged) */
1265 for (i
=0; i
<64; i
++)
1267 p_jpeg
->qt_idct
[0][zag
[i
]] = p_jpeg
->quanttable
[0][i
];
1268 p_jpeg
->qt_idct
[1][zag
[i
]] = p_jpeg
->quanttable
[1][i
];
1272 p_jpeg
->store_pos
[i
] = i
; /* default ordering */
1274 /* assignments for the decoding of blocks */
1275 if (p_jpeg
->frameheader
[0].horizontal_sampling
== 2
1276 && p_jpeg
->frameheader
[0].vertical_sampling
== 1)
1279 p_jpeg
->x_mbl
= (p_jpeg
->x_size
+15) / 16;
1280 p_jpeg
->x_phys
= p_jpeg
->x_mbl
* 16;
1281 p_jpeg
->y_mbl
= (p_jpeg
->y_size
+7) / 8;
1282 p_jpeg
->y_phys
= p_jpeg
->y_mbl
* 8;
1283 p_jpeg
->mcu_membership
[0] = 0; /* Y1=Y2=0, U=1, V=2 */
1284 p_jpeg
->mcu_membership
[1] = 0;
1285 p_jpeg
->mcu_membership
[2] = 1;
1286 p_jpeg
->mcu_membership
[3] = 2;
1287 p_jpeg
->tab_membership
[0] = 0; /* DC, DC, AC, AC */
1288 p_jpeg
->tab_membership
[1] = 0;
1289 p_jpeg
->tab_membership
[2] = 1;
1290 p_jpeg
->tab_membership
[3] = 1;
1291 p_jpeg
->subsample_x
[0] = 1;
1292 p_jpeg
->subsample_x
[1] = 2;
1293 p_jpeg
->subsample_x
[2] = 2;
1294 p_jpeg
->subsample_y
[0] = 1;
1295 p_jpeg
->subsample_y
[1] = 1;
1296 p_jpeg
->subsample_y
[2] = 1;
1298 if (p_jpeg
->frameheader
[0].horizontal_sampling
== 1
1299 && p_jpeg
->frameheader
[0].vertical_sampling
== 2)
1300 { /* 4:2:2 vertically subsampled */
1301 p_jpeg
->store_pos
[1] = 2; /* block positions are mirrored */
1302 p_jpeg
->store_pos
[2] = 1;
1304 p_jpeg
->x_mbl
= (p_jpeg
->x_size
+7) / 8;
1305 p_jpeg
->x_phys
= p_jpeg
->x_mbl
* 8;
1306 p_jpeg
->y_mbl
= (p_jpeg
->y_size
+15) / 16;
1307 p_jpeg
->y_phys
= p_jpeg
->y_mbl
* 16;
1308 p_jpeg
->mcu_membership
[0] = 0; /* Y1=Y2=0, U=1, V=2 */
1309 p_jpeg
->mcu_membership
[1] = 0;
1310 p_jpeg
->mcu_membership
[2] = 1;
1311 p_jpeg
->mcu_membership
[3] = 2;
1312 p_jpeg
->tab_membership
[0] = 0; /* DC, DC, AC, AC */
1313 p_jpeg
->tab_membership
[1] = 0;
1314 p_jpeg
->tab_membership
[2] = 1;
1315 p_jpeg
->tab_membership
[3] = 1;
1316 p_jpeg
->subsample_x
[0] = 1;
1317 p_jpeg
->subsample_x
[1] = 1;
1318 p_jpeg
->subsample_x
[2] = 1;
1319 p_jpeg
->subsample_y
[0] = 1;
1320 p_jpeg
->subsample_y
[1] = 2;
1321 p_jpeg
->subsample_y
[2] = 2;
1323 else if (p_jpeg
->frameheader
[0].horizontal_sampling
== 2
1324 && p_jpeg
->frameheader
[0].vertical_sampling
== 2)
1327 p_jpeg
->x_mbl
= (p_jpeg
->x_size
+15) / 16;
1328 p_jpeg
->x_phys
= p_jpeg
->x_mbl
* 16;
1329 p_jpeg
->y_mbl
= (p_jpeg
->y_size
+15) / 16;
1330 p_jpeg
->y_phys
= p_jpeg
->y_mbl
* 16;
1331 p_jpeg
->mcu_membership
[0] = 0;
1332 p_jpeg
->mcu_membership
[1] = 0;
1333 p_jpeg
->mcu_membership
[2] = 0;
1334 p_jpeg
->mcu_membership
[3] = 0;
1335 p_jpeg
->mcu_membership
[4] = 1;
1336 p_jpeg
->mcu_membership
[5] = 2;
1337 p_jpeg
->tab_membership
[0] = 0;
1338 p_jpeg
->tab_membership
[1] = 0;
1339 p_jpeg
->tab_membership
[2] = 0;
1340 p_jpeg
->tab_membership
[3] = 0;
1341 p_jpeg
->tab_membership
[4] = 1;
1342 p_jpeg
->tab_membership
[5] = 1;
1343 p_jpeg
->subsample_x
[0] = 1;
1344 p_jpeg
->subsample_x
[1] = 2;
1345 p_jpeg
->subsample_x
[2] = 2;
1346 p_jpeg
->subsample_y
[0] = 1;
1347 p_jpeg
->subsample_y
[1] = 2;
1348 p_jpeg
->subsample_y
[2] = 2;
1350 else if (p_jpeg
->frameheader
[0].horizontal_sampling
== 1
1351 && p_jpeg
->frameheader
[0].vertical_sampling
== 1)
1353 /* don't overwrite p_jpeg->blocks */
1354 p_jpeg
->x_mbl
= (p_jpeg
->x_size
+7) / 8;
1355 p_jpeg
->x_phys
= p_jpeg
->x_mbl
* 8;
1356 p_jpeg
->y_mbl
= (p_jpeg
->y_size
+7) / 8;
1357 p_jpeg
->y_phys
= p_jpeg
->y_mbl
* 8;
1358 p_jpeg
->mcu_membership
[0] = 0;
1359 p_jpeg
->mcu_membership
[1] = 1;
1360 p_jpeg
->mcu_membership
[2] = 2;
1361 p_jpeg
->tab_membership
[0] = 0;
1362 p_jpeg
->tab_membership
[1] = 1;
1363 p_jpeg
->tab_membership
[2] = 1;
1364 p_jpeg
->subsample_x
[0] = 1;
1365 p_jpeg
->subsample_x
[1] = 1;
1366 p_jpeg
->subsample_x
[2] = 1;
1367 p_jpeg
->subsample_y
[0] = 1;
1368 p_jpeg
->subsample_y
[1] = 1;
1369 p_jpeg
->subsample_y
[2] = 1;
1380 * These functions/macros provide the in-line portion of bit fetching.
1381 * Use check_bit_buffer to ensure there are N bits in get_buffer
1382 * before using get_bits, peek_bits, or drop_bits.
1383 * check_bit_buffer(state,n,action);
1384 * Ensure there are N bits in get_buffer; if suspend, take action.
1385 * val = get_bits(n);
1386 * Fetch next N bits.
1387 * val = peek_bits(n);
1388 * Fetch next N bits without removing them from the buffer.
1390 * Discard next N bits.
1391 * The value N should be a simple variable, not an expression, because it
1392 * is evaluated multiple times.
1395 INLINE
void check_bit_buffer(struct bitstream
* pb
, int nbits
)
1397 if (pb
->bits_left
< nbits
)
1398 { /* nbits is <= 16, so I can always refill 2 bytes in this case */
1401 byte
= *pb
->next_input_byte
++;
1402 if (byte
== 0xFF) /* legal marker can be byte stuffing or RSTm */
1403 { /* simplification: just skip the (one-byte) marker code */
1404 pb
->next_input_byte
++;
1406 pb
->get_buffer
= (pb
->get_buffer
<< 8) | byte
;
1408 byte
= *pb
->next_input_byte
++;
1409 if (byte
== 0xFF) /* legal marker can be byte stuffing or RSTm */
1410 { /* simplification: just skip the (one-byte) marker code */
1411 pb
->next_input_byte
++;
1413 pb
->get_buffer
= (pb
->get_buffer
<< 8) | byte
;
1415 pb
->bits_left
+= 16;
1419 INLINE
int get_bits(struct bitstream
* pb
, int nbits
)
1421 return ((int) (pb
->get_buffer
>> (pb
->bits_left
-= nbits
))) & ((1<<nbits
)-1);
1424 INLINE
int peek_bits(struct bitstream
* pb
, int nbits
)
1426 return ((int) (pb
->get_buffer
>> (pb
->bits_left
- nbits
))) & ((1<<nbits
)-1);
1429 INLINE
void drop_bits(struct bitstream
* pb
, int nbits
)
1431 pb
->bits_left
-= nbits
;
1434 /* re-synchronize to entropy data (skip restart marker) */
1435 void search_restart(struct bitstream
* pb
)
1437 pb
->next_input_byte
--; /* we may have overread it, taking 2 bytes */
1438 /* search for a non-byte-padding marker, has to be RSTm or EOS */
1439 while (pb
->next_input_byte
< pb
->input_end
&&
1440 (pb
->next_input_byte
[-2] != 0xFF || pb
->next_input_byte
[-1] == 0x00))
1442 pb
->next_input_byte
++;
1447 /* Figure F.12: extend sign bit. */
1448 #define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
1450 static const int extend_test
[16] = /* entry n is 2**(n-1) */
1452 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
1453 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000
1456 static const int extend_offset
[16] = /* entry n is (-1 << n) + 1 */
1458 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
1459 ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
1460 ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
1461 ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1
1464 /* Decode a single value */
1465 INLINE
int huff_decode_dc(struct bitstream
* bs
, struct derived_tbl
* tbl
)
1469 check_bit_buffer(bs
, HUFF_LOOKAHEAD
);
1470 look
= peek_bits(bs
, HUFF_LOOKAHEAD
);
1471 if ((nb
= tbl
->look_nbits
[look
]) != 0)
1474 s
= tbl
->look_sym
[look
];
1475 check_bit_buffer(bs
, s
);
1476 r
= get_bits(bs
, s
);
1477 s
= HUFF_EXTEND(r
, s
);
1480 { /* slow_DECODE(s, HUFF_LOOKAHEAD+1)) < 0); */
1482 nb
=HUFF_LOOKAHEAD
+1;
1483 check_bit_buffer(bs
, nb
);
1484 code
= get_bits(bs
, nb
);
1485 while (code
> tbl
->maxcode
[nb
])
1488 check_bit_buffer(bs
, 1);
1489 code
|= get_bits(bs
, 1);
1492 if (nb
> 16) /* error in Huffman */
1494 s
=0; /* fake a zero, this is most safe */
1498 s
= tbl
->pub
[16 + tbl
->valptr
[nb
] + ((int) (code
- tbl
->mincode
[nb
])) ];
1499 check_bit_buffer(bs
, s
);
1500 r
= get_bits(bs
, s
);
1501 s
= HUFF_EXTEND(r
, s
);
1503 } /* end slow decode */
1507 INLINE
int huff_decode_ac(struct bitstream
* bs
, struct derived_tbl
* tbl
)
1511 check_bit_buffer(bs
, HUFF_LOOKAHEAD
);
1512 look
= peek_bits(bs
, HUFF_LOOKAHEAD
);
1513 if ((nb
= tbl
->look_nbits
[look
]) != 0)
1516 s
= tbl
->look_sym
[look
];
1519 { /* slow_DECODE(s, HUFF_LOOKAHEAD+1)) < 0); */
1521 nb
=HUFF_LOOKAHEAD
+1;
1522 check_bit_buffer(bs
, nb
);
1523 code
= get_bits(bs
, nb
);
1524 while (code
> tbl
->maxcode
[nb
])
1527 check_bit_buffer(bs
, 1);
1528 code
|= get_bits(bs
, 1);
1531 if (nb
> 16) /* error in Huffman */
1533 s
=0; /* fake a zero, this is most safe */
1537 s
= tbl
->pub
[16 + tbl
->valptr
[nb
] + ((int) (code
- tbl
->mincode
[nb
])) ];
1539 } /* end slow decode */
1544 #ifdef HAVE_LCD_COLOR
1546 /* JPEG decoder variant for YUV decoding, into 3 different planes */
1547 /* Note: it keeps the original color subsampling, even if resized. */
1548 int jpeg_decode(struct jpeg
* p_jpeg
, unsigned char* p_pixel
[3],
1549 int downscale
, void (*pf_progress
)(int current
, int total
))
1551 struct bitstream bs
; /* bitstream "object" */
1552 int block
[64]; /* decoded DCT coefficients */
1555 int skip_line
[3]; /* bytes from one line to the next (skip_line) */
1556 int skip_strip
[3], skip_mcu
[3]; /* bytes to next DCT row / column */
1558 int i
, x
, y
; /* loop counter */
1560 unsigned char* p_line
[3] = {p_pixel
[0], p_pixel
[1], p_pixel
[2]};
1561 unsigned char* p_byte
[3]; /* bitmap pointer */
1563 void (*pf_idct
)(unsigned char*, int*, int*, int); /* selected IDCT */
1564 int k_need
; /* AC coefficients needed up to here */
1565 int zero_need
; /* init the block with this many zeros */
1567 int last_dc_val
[3] = {0, 0, 0}; /* or 128 for chroma? */
1568 int store_offs
[4]; /* memory offsets: order of Y11 Y12 Y21 Y22 U V */
1569 int restart
= p_jpeg
->restart_interval
; /* MCUs until restart marker */
1571 /* pick the IDCT we want, determine how to work with coefs */
1575 k_need
= 64; /* all */
1576 zero_need
= 63; /* all */
1578 else if (downscale
== 2)
1581 k_need
= 25; /* this far in zig-zag to cover 4*4 */
1582 zero_need
= 27; /* clear this far in linear order */
1584 else if (downscale
== 4)
1587 k_need
= 5; /* this far in zig-zag to cover 2*2 */
1588 zero_need
= 9; /* clear this far in linear order */
1590 else if (downscale
== 8)
1593 k_need
= 0; /* no AC, not needed */
1594 zero_need
= 0; /* no AC, not needed */
1596 else return -1; /* not supported */
1598 /* init bitstream, fake a restart to make it start */
1599 bs
.next_input_byte
= p_jpeg
->p_entropy_data
;
1601 bs
.input_end
= p_jpeg
->p_entropy_end
;
1603 width
= p_jpeg
->x_phys
/ downscale
;
1604 height
= p_jpeg
->y_phys
/ downscale
;
1605 for (i
=0; i
<3; i
++) /* calculate some strides */
1607 skip_line
[i
] = width
/ p_jpeg
->subsample_x
[i
];
1608 skip_strip
[i
] = skip_line
[i
]
1609 * (height
/ p_jpeg
->y_mbl
) / p_jpeg
->subsample_y
[i
];
1610 skip_mcu
[i
] = width
/p_jpeg
->x_mbl
/ p_jpeg
->subsample_x
[i
];
1613 /* prepare offsets about where to store the different blocks */
1614 store_offs
[p_jpeg
->store_pos
[0]] = 0;
1615 store_offs
[p_jpeg
->store_pos
[1]] = 8 / downscale
; /* to the right */
1616 store_offs
[p_jpeg
->store_pos
[2]] = width
* 8 / downscale
; /* below */
1617 store_offs
[p_jpeg
->store_pos
[3]] = store_offs
[1] + store_offs
[2]; /* r+b */
1619 for(y
=0; y
<p_jpeg
->y_mbl
&& bs
.next_input_byte
<= bs
.input_end
; y
++)
1621 for (i
=0; i
<3; i
++) /* scan line init */
1623 p_byte
[i
] = p_line
[i
];
1624 p_line
[i
] += skip_strip
[i
];
1626 for (x
=0; x
<p_jpeg
->x_mbl
; x
++)
1630 /* Outer loop handles each block in the MCU */
1631 for (blkn
= 0; blkn
< p_jpeg
->blocks
; blkn
++)
1632 { /* Decode a single block's worth of coefficients */
1633 int k
= 1; /* coefficient index */
1634 int s
, r
; /* huffman values */
1635 int ci
= p_jpeg
->mcu_membership
[blkn
]; /* component index */
1636 int ti
= p_jpeg
->tab_membership
[blkn
]; /* table index */
1637 struct derived_tbl
* dctbl
= &p_jpeg
->dc_derived_tbls
[ti
];
1638 struct derived_tbl
* actbl
= &p_jpeg
->ac_derived_tbls
[ti
];
1640 /* Section F.2.2.1: decode the DC coefficient difference */
1641 s
= huff_decode_dc(&bs
, dctbl
);
1643 last_dc_val
[ci
] += s
;
1644 block
[0] = last_dc_val
[ci
]; /* output it (assumes zag[0] = 0) */
1646 /* coefficient buffer must be cleared */
1647 MEMSET(block
+1, 0, zero_need
*sizeof(block
[0]));
1649 /* Section F.2.2.2: decode the AC coefficients */
1650 for (; k
< k_need
; k
++)
1652 s
= huff_decode_ac(&bs
, actbl
);
1659 check_bit_buffer(&bs
, s
);
1660 r
= get_bits(&bs
, s
);
1661 block
[zag
[k
]] = HUFF_EXTEND(r
, s
);
1673 /* In this path we just discard the values */
1676 s
= huff_decode_ac(&bs
, actbl
);
1683 check_bit_buffer(&bs
, s
);
1695 { /* Y component needs to bother about block store */
1696 pf_idct(p_byte
[0]+store_offs
[blkn
], block
,
1697 p_jpeg
->qt_idct
[ti
], skip_line
[0]);
1701 pf_idct(p_byte
[ci
], block
, p_jpeg
->qt_idct
[ti
],
1705 p_byte
[0] += skip_mcu
[0]; /* unrolled for (i=0; i<3; i++) loop */
1706 p_byte
[1] += skip_mcu
[1];
1707 p_byte
[2] += skip_mcu
[2];
1708 if (p_jpeg
->restart_interval
&& --restart
== 0)
1709 { /* if a restart marker is due: */
1710 restart
= p_jpeg
->restart_interval
; /* count again */
1711 search_restart(&bs
); /* align the bitstream */
1712 last_dc_val
[0] = last_dc_val
[1] =
1713 last_dc_val
[2] = 0; /* reset decoder */
1716 if (pf_progress
!= NULL
)
1717 pf_progress(y
, p_jpeg
->y_mbl
-1); /* notify about decoding progress */
1720 return 0; /* success */
1722 #else /* !HAVE_LCD_COLOR */
1724 /* a JPEG decoder specialized in decoding only the luminance (b&w) */
1725 int jpeg_decode(struct jpeg
* p_jpeg
, unsigned char* p_pixel
[1], int downscale
,
1726 void (*pf_progress
)(int current
, int total
))
1728 struct bitstream bs
; /* bitstream "object" */
1729 int block
[64]; /* decoded DCT coefficients */
1732 int skip_line
; /* bytes from one line to the next (skip_line) */
1733 int skip_strip
, skip_mcu
; /* bytes to next DCT row / column */
1735 int x
, y
; /* loop counter */
1737 unsigned char* p_line
= p_pixel
[0];
1738 unsigned char* p_byte
; /* bitmap pointer */
1740 void (*pf_idct
)(unsigned char*, int*, int*, int); /* selected IDCT */
1741 int k_need
; /* AC coefficients needed up to here */
1742 int zero_need
; /* init the block with this many zeros */
1744 int last_dc_val
= 0;
1745 int store_offs
[4]; /* memory offsets: order of Y11 Y12 Y21 Y22 U V */
1746 int restart
= p_jpeg
->restart_interval
; /* MCUs until restart marker */
1748 /* pick the IDCT we want, determine how to work with coefs */
1752 k_need
= 64; /* all */
1753 zero_need
= 63; /* all */
1755 else if (downscale
== 2)
1758 k_need
= 25; /* this far in zig-zag to cover 4*4 */
1759 zero_need
= 27; /* clear this far in linear order */
1761 else if (downscale
== 4)
1764 k_need
= 5; /* this far in zig-zag to cover 2*2 */
1765 zero_need
= 9; /* clear this far in linear order */
1767 else if (downscale
== 8)
1770 k_need
= 0; /* no AC, not needed */
1771 zero_need
= 0; /* no AC, not needed */
1773 else return -1; /* not supported */
1775 /* init bitstream, fake a restart to make it start */
1776 bs
.next_input_byte
= p_jpeg
->p_entropy_data
;
1778 bs
.input_end
= p_jpeg
->p_entropy_end
;
1780 width
= p_jpeg
->x_phys
/ downscale
;
1781 height
= p_jpeg
->y_phys
/ downscale
;
1783 skip_strip
= skip_line
* (height
/ p_jpeg
->y_mbl
);
1784 skip_mcu
= (width
/p_jpeg
->x_mbl
);
1786 /* prepare offsets about where to store the different blocks */
1787 store_offs
[p_jpeg
->store_pos
[0]] = 0;
1788 store_offs
[p_jpeg
->store_pos
[1]] = 8 / downscale
; /* to the right */
1789 store_offs
[p_jpeg
->store_pos
[2]] = width
* 8 / downscale
; /* below */
1790 store_offs
[p_jpeg
->store_pos
[3]] = store_offs
[1] + store_offs
[2]; /* r+b */
1792 for(y
=0; y
<p_jpeg
->y_mbl
&& bs
.next_input_byte
<= bs
.input_end
; y
++)
1795 p_line
+= skip_strip
;
1796 for (x
=0; x
<p_jpeg
->x_mbl
; x
++)
1800 /* Outer loop handles each block in the MCU */
1801 for (blkn
= 0; blkn
< p_jpeg
->blocks
; blkn
++)
1802 { /* Decode a single block's worth of coefficients */
1803 int k
= 1; /* coefficient index */
1804 int s
, r
; /* huffman values */
1805 int ci
= p_jpeg
->mcu_membership
[blkn
]; /* component index */
1806 int ti
= p_jpeg
->tab_membership
[blkn
]; /* table index */
1807 struct derived_tbl
* dctbl
= &p_jpeg
->dc_derived_tbls
[ti
];
1808 struct derived_tbl
* actbl
= &p_jpeg
->ac_derived_tbls
[ti
];
1810 /* Section F.2.2.1: decode the DC coefficient difference */
1811 s
= huff_decode_dc(&bs
, dctbl
);
1813 if (ci
== 0) /* only for Y component */
1816 block
[0] = last_dc_val
; /* output it (assumes zag[0] = 0) */
1818 /* coefficient buffer must be cleared */
1819 MEMSET(block
+1, 0, zero_need
*sizeof(block
[0]));
1821 /* Section F.2.2.2: decode the AC coefficients */
1822 for (; k
< k_need
; k
++)
1824 s
= huff_decode_ac(&bs
, actbl
);
1831 check_bit_buffer(&bs
, s
);
1832 r
= get_bits(&bs
, s
);
1833 block
[zag
[k
]] = HUFF_EXTEND(r
, s
);
1846 /* In this path we just discard the values */
1849 s
= huff_decode_ac(&bs
, actbl
);
1856 check_bit_buffer(&bs
, s
);
1868 { /* only for Y component */
1869 pf_idct(p_byte
+store_offs
[blkn
], block
, p_jpeg
->qt_idct
[ti
],
1874 if (p_jpeg
->restart_interval
&& --restart
== 0)
1875 { /* if a restart marker is due: */
1876 restart
= p_jpeg
->restart_interval
; /* count again */
1877 search_restart(&bs
); /* align the bitstream */
1878 last_dc_val
= 0; /* reset decoder */
1881 if (pf_progress
!= NULL
)
1882 pf_progress(y
, p_jpeg
->y_mbl
-1); /* notify about decoding progress */
1885 return 0; /* success */
1887 #endif /* !HAVE_LCD_COLOR */
1889 /**************** end JPEG code ********************/
1893 /**************** begin Application ********************/
1896 /************************* Types ***************************/
1900 #ifdef HAVE_LCD_COLOR
1901 unsigned char* bitmap
[3]; /* Y, Cr, Cb */
1904 unsigned char* bitmap
[1]; /* Y only */
1912 /************************* Globals ***************************/
1914 /* decompressed image in the possible sizes (1,2,4,8), wasting the other */
1915 struct t_disp disp
[9];
1917 /* my memory pool (from the mp3 buffer) */
1918 char print
[32]; /* use a common snprintf() buffer */
1919 unsigned char* buf
; /* up to here currently used by image(s) */
1921 /* the remaining free part of the buffer for compressed+uncompressed images */
1922 unsigned char* buf_images
;
1924 ssize_t buf_size
, buf_images_size
;
1925 /* the root of the images, hereafter are decompresed ones */
1926 unsigned char* buf_root
;
1929 int ds
, ds_min
, ds_max
; /* downscaling and limits */
1930 static struct jpeg jpg
; /* too large for stack */
1932 static struct tree_context
*tree
;
1934 /* the current full file name */
1935 static char np_file
[MAX_PATH
];
1936 int curfile
= 0, direction
= DIR_NONE
, entries
= 0;
1938 /* list of the jpeg files */
1940 /* are we using the plugin buffer or the audio buffer? */
1941 bool plug_buf
= false;
1944 /************************* Implementation ***************************/
1946 #ifdef HAVE_LCD_COLOR
1948 * Conversion of full 0-255 range YCrCb to RGB:
1949 * |R| |1.000000 -0.000001 1.402000| |Y'|
1950 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
1951 * |B| |1.000000 1.772000 0.000000| |Pr|
1952 * Scaled (yields s15-bit output):
1953 * |R| |128 0 179| |Y |
1954 * |G| = |128 -43 -91| |Cb - 128|
1955 * |B| |128 227 0| |Cr - 128|
1962 #define YUV_WHITE (255*YFAC)
1963 #define NODITHER_DELTA (127*YFAC)
1964 #define COMPONENT_SHIFT 15
1965 #define MATRIX_SHIFT 7
1967 static inline int clamp_component(int x
)
1969 if ((unsigned)x
> YUV_WHITE
)
1970 x
= x
< 0 ? 0 : YUV_WHITE
;
1974 static inline int clamp_component_bits(int x
, int bits
)
1976 if ((unsigned)x
> (1u << bits
) - 1)
1977 x
= x
< 0 ? 0 : (1 << bits
) - 1;
1981 static inline int component_to_lcd(int x
, int bits
, int delta
)
1983 /* Formula used in core bitmap loader. */
1984 return (((1 << bits
) - 1)*x
+ (x
>> (8 - bits
)) + delta
) >> COMPONENT_SHIFT
;
1987 static inline int lcd_to_component(int x
, int bits
, int delta
)
1989 /* Reasonable, approximate reversal to get a full range back from the
1991 return YUV_WHITE
*x
/ ((1 << bits
) - 1);
2001 int16_t errbuf
[LCD_WIDTH
+2]; /* Error record for line below */
2002 } rgb_err_buffers
[3];
2004 fb_data rgb_linebuf
[LCD_WIDTH
]; /* Line buffer for scrolling when
2005 DITHER_DIFFUSION is set */
2009 int r
, g
, b
; /* Current pixel components in s16.0 */
2010 int inc
; /* Current line increment (-1 or 1) */
2011 int row
; /* Current row in source image */
2012 int col
; /* Current column in source image */
2013 int ce
[3]; /* Errors to apply to current pixel */
2014 struct rgb_err
*e
; /* RED, GRN, BLU */
2015 int epos
; /* Current position in error record */
2018 struct rgb_pixel
*pixel
;
2020 /** round and truncate to lcd depth **/
2021 static fb_data
pixel_to_lcd_colour(void)
2023 struct rgb_pixel
*p
= pixel
;
2026 r
= component_to_lcd(p
->r
, LCD_RED_BITS
, NODITHER_DELTA
);
2027 r
= clamp_component_bits(r
, LCD_RED_BITS
);
2029 g
= component_to_lcd(p
->g
, LCD_GREEN_BITS
, NODITHER_DELTA
);
2030 g
= clamp_component_bits(g
, LCD_GREEN_BITS
);
2032 b
= component_to_lcd(p
->b
, LCD_BLUE_BITS
, NODITHER_DELTA
);
2033 b
= clamp_component_bits(b
, LCD_BLUE_BITS
);
2035 return LCD_RGBPACK_LCD(r
, g
, b
);
2038 /** write a monochrome pixel to the colour LCD **/
2039 static fb_data
pixel_to_lcd_gray(void)
2043 g
= clamp_component(pixel
->g
);
2044 r
= component_to_lcd(g
, LCD_RED_BITS
, NODITHER_DELTA
);
2045 b
= component_to_lcd(g
, LCD_BLUE_BITS
, NODITHER_DELTA
);
2046 g
= component_to_lcd(g
, LCD_GREEN_BITS
, NODITHER_DELTA
);
2048 return LCD_RGBPACK_LCD(r
, g
, b
);
2052 * Bayer ordered dithering - swiped from the core bitmap loader.
2054 static fb_data
pixel_odither_to_lcd(void)
2056 /* canonical ordered dither matrix */
2057 static const unsigned char dither_matrix
[16][16] = {
2058 { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 },
2059 { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 },
2060 { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 },
2061 { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 },
2062 { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 },
2063 { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 },
2064 { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 },
2065 { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 },
2066 { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 },
2067 { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 },
2068 { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 },
2069 { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 },
2070 { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 },
2071 { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 },
2072 { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 },
2073 { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 }
2076 struct rgb_pixel
*p
= pixel
;
2079 delta
= dither_matrix
[p
->col
& 15][p
->row
& 15] << MATRIX_SHIFT
;
2081 r
= component_to_lcd(p
->r
, LCD_RED_BITS
, delta
);
2082 r
= clamp_component_bits(r
, LCD_RED_BITS
);
2084 g
= component_to_lcd(p
->g
, LCD_GREEN_BITS
, delta
);
2085 g
= clamp_component_bits(g
, LCD_GREEN_BITS
);
2087 b
= component_to_lcd(p
->b
, LCD_BLUE_BITS
, delta
);
2088 b
= clamp_component_bits(b
, LCD_BLUE_BITS
);
2092 return LCD_RGBPACK_LCD(r
, g
, b
);
2096 * Floyd/Steinberg dither to lcd depth.
2098 * Apply filter to each component in serpentine pattern. Kernel shown for
2099 * L->R scan. Kernel is reversed for R->L.
2103 static inline void distribute_error(int *ce
, struct rgb_err
*e
,
2104 int err
, int epos
, int inc
)
2106 *ce
= (7*err
>> 4) + e
->errbuf
[epos
+inc
];
2107 e
->errbuf
[epos
+inc
] = err
>> 4;
2108 e
->errbuf
[epos
] += 5*err
>> 4;
2109 e
->errbuf
[epos
-inc
] += 3*err
>> 4;
2112 static fb_data
pixel_fsdither_to_lcd(void)
2114 struct rgb_pixel
*p
= pixel
;
2115 int rc
, gc
, bc
, r
, g
, b
;
2118 /* Full components with error terms */
2119 rc
= p
->r
+ p
->ce
[RED
];
2120 r
= component_to_lcd(rc
, LCD_RED_BITS
, 0);
2121 r
= clamp_component_bits(r
, LCD_RED_BITS
);
2123 gc
= p
->g
+ p
->ce
[GRN
];
2124 g
= component_to_lcd(gc
, LCD_GREEN_BITS
, 0);
2125 g
= clamp_component_bits(g
, LCD_GREEN_BITS
);
2127 bc
= p
->b
+ p
->ce
[BLU
];
2128 b
= component_to_lcd(bc
, LCD_BLUE_BITS
, 0);
2129 b
= clamp_component_bits(b
, LCD_BLUE_BITS
);
2131 /* Get pixel errors */
2132 rc
-= lcd_to_component(r
, LCD_RED_BITS
, 0);
2133 gc
-= lcd_to_component(g
, LCD_GREEN_BITS
, 0);
2134 bc
-= lcd_to_component(b
, LCD_BLUE_BITS
, 0);
2136 /* Spead error to surrounding pixels. */
2141 distribute_error(&p
->ce
[RED
], &p
->e
[RED
], rc
, epos
, inc
);
2142 distribute_error(&p
->ce
[GRN
], &p
->e
[GRN
], gc
, epos
, inc
);
2143 distribute_error(&p
->ce
[BLU
], &p
->e
[BLU
], bc
, epos
, inc
);
2145 /* Pack and return pixel */
2146 return LCD_RGBPACK_LCD(r
, g
, b
);
2149 /* Functions for each output mode, colour then grayscale. */
2150 static fb_data (* const pixel_funcs
[COLOUR_NUM_MODES
][DITHER_NUM_MODES
])(void) =
2152 [COLOURMODE_COLOUR
] =
2154 [DITHER_NONE
] = pixel_to_lcd_colour
,
2155 [DITHER_ORDERED
] = pixel_odither_to_lcd
,
2156 [DITHER_DIFFUSION
] = pixel_fsdither_to_lcd
,
2160 [DITHER_NONE
] = pixel_to_lcd_gray
,
2161 [DITHER_ORDERED
] = pixel_odither_to_lcd
,
2162 [DITHER_DIFFUSION
] = pixel_fsdither_to_lcd
,
2167 * Draw a partial YUV colour bitmap
2169 * Runs serpentine pattern when dithering is DITHER_DIFFUSION, else scan is
2172 void yuv_bitmap_part(unsigned char *src
[3], int csub_x
, int csub_y
,
2173 int src_x
, int src_y
, int stride
,
2174 int x
, int y
, int width
, int height
)
2176 fb_data
*dst
, *dst_end
;
2177 fb_data (*pixel_func
)(void);
2178 struct rgb_pixel px
;
2180 if (x
+ width
> LCD_WIDTH
)
2181 width
= LCD_WIDTH
- x
; /* Clip right */
2183 width
+= x
, x
= 0; /* Clip left */
2185 return; /* nothing left to do */
2187 if (y
+ height
> LCD_HEIGHT
)
2188 height
= LCD_HEIGHT
- y
; /* Clip bottom */
2190 height
+= y
, y
= 0; /* Clip top */
2192 return; /* nothing left to do */
2196 dst
= rb
->lcd_framebuffer
+ LCD_WIDTH
* y
+ x
;
2197 dst_end
= dst
+ LCD_WIDTH
* height
;
2199 if (jpeg_settings
.colour_mode
== COLOURMODE_GRAY
)
2200 csub_y
= 0; /* Ignore Cb, Cr */
2202 pixel_func
= pixel_funcs
[jpeg_settings
.colour_mode
]
2203 [jpeg_settings
.dither_mode
];
2205 if (jpeg_settings
.dither_mode
== DITHER_DIFFUSION
)
2207 /* Reset error terms. */
2208 px
.e
= rgb_err_buffers
;
2209 px
.ce
[RED
] = px
.ce
[GRN
] = px
.ce
[BLU
] = 0;
2210 rb
->memset(px
.e
, 0, 3*sizeof (struct rgb_err
));
2215 fb_data
*dst_row
, *row_end
;
2216 const unsigned char *ysrc
;
2219 if (jpeg_settings
.dither_mode
== DITHER_DIFFUSION
)
2221 /* Use R->L scan on odd lines */
2222 px
.inc
-= (src_y
& 1) << 1;
2226 px
.epos
+= width
- 1;
2233 row_end
= dst_row
+ width
;
2240 dst_row
= row_end
+ width
;
2241 px
.col
= src_x
+ width
- 1;
2244 ysrc
= src
[0] + stride
* src_y
+ px
.col
;
2247 /* Do one row of pixels */
2248 if (csub_y
) /* colour */
2250 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
2251 const unsigned char *usrc
, *vsrc
;
2253 usrc
= src
[1] + (stride
/csub_x
) * (src_y
/csub_y
)
2255 vsrc
= src
[2] + (stride
/csub_x
) * (src_y
/csub_y
)
2257 int xphase
= px
.col
% csub_x
;
2258 int xphase_reset
= px
.inc
* csub_x
;
2259 int y
, v
, u
, rv
, guv
, bu
;
2266 guv
= GUFAC
*u
+ GVFAC
*v
;
2277 *dst_row
= pixel_func();
2280 if (dst_row
== row_end
)
2284 if ((unsigned)xphase
< (unsigned)csub_x
)
2287 /* fetch new chromas */
2293 guv
= GUFAC
*u
+ GVFAC
*v
;
2296 xphase
-= xphase_reset
;
2299 else /* monochrome */
2303 /* Set all components the same for dithering purposes */
2304 px
.g
= px
.r
= px
.b
= YFAC
*(*ysrc
);
2305 *dst_row
= pixel_func();
2309 while (dst_row
!= row_end
);
2315 while (dst
< dst_end
);
2318 #endif /* HAVE_LCD_COLOR */
2321 /* support function for qsort() */
2322 static int compare(const void* p1
, const void* p2
)
2324 return rb
->strcasecmp(*((char **)p1
), *((char **)p2
));
2327 bool jpg_ext(const char ext
[])
2331 if(!rb
->strcasecmp(ext
,".jpg") ||
2332 !rb
->strcasecmp(ext
,".jpe") ||
2333 !rb
->strcasecmp(ext
,".jpeg"))
2339 /*Read directory contents for scrolling. */
2340 void get_pic_list(void)
2343 long int str_len
= 0;
2345 tree
= rb
->tree_get_context();
2347 #if PLUGIN_BUFFER_SIZE >= MIN_MEM
2348 file_pt
= rb
->plugin_get_buffer((size_t *)&buf_size
);
2350 file_pt
= rb
->plugin_get_audio_buffer((size_t *)&buf_size
);
2353 for(i
= 0; i
< tree
->filesindir
; i
++)
2355 if(jpg_ext(rb
->strrchr(&tree
->name_buffer
[str_len
],'.')))
2356 file_pt
[entries
++] = &tree
->name_buffer
[str_len
];
2358 str_len
+= rb
->strlen(&tree
->name_buffer
[str_len
]) + 1;
2361 rb
->qsort(file_pt
, entries
, sizeof(char**), compare
);
2363 /* Remove path and leave only the name.*/
2364 pname
= rb
->strrchr(np_file
,'/');
2367 /* Find Selected File. */
2368 for(i
= 0; i
< entries
; i
++)
2369 if(!rb
->strcmp(file_pt
[i
], pname
))
2373 int change_filename(int direct
)
2378 if(direct
== DIR_PREV
)
2384 curfile
= entries
- 1;
2387 }while(file_pt
[curfile
] == '\0' && count
< entries
);
2388 /* we "erase" the file name if we encounter
2389 * a non-supported file, so skip it now */
2391 else /* DIR_NEXT/DIR_NONE */
2396 if(curfile
== entries
- 1)
2400 }while(file_pt
[curfile
] == '\0' && count
< entries
);
2403 if(count
== entries
&& file_pt
[curfile
] == '\0')
2405 rb
->splash(HZ
, "No supported files");
2406 return PLUGIN_ERROR
;
2408 if(rb
->strlen(tree
->currdir
) > 1)
2410 rb
->strcpy(np_file
, tree
->currdir
);
2411 rb
->strcat(np_file
, "/");
2414 rb
->strcpy(np_file
, tree
->currdir
);
2416 rb
->strcat(np_file
, file_pt
[curfile
]);
2418 return PLUGIN_OTHER
;
2421 /* switch off overlay, for handling SYS_ events */
2422 void cleanup(void *parameter
)
2430 #define VSCROLL (LCD_HEIGHT/8)
2431 #define HSCROLL (LCD_WIDTH/10)
2433 #define ZOOM_IN 100 /* return codes for below function */
2434 #define ZOOM_OUT 101
2436 #ifdef HAVE_LCD_COLOR
2437 bool set_option_grayscale(void)
2439 bool gray
= jpeg_settings
.colour_mode
== COLOURMODE_GRAY
;
2440 rb
->set_bool("Grayscale", &gray
);
2441 jpeg_settings
.colour_mode
= gray
? COLOURMODE_GRAY
: COLOURMODE_COLOUR
;
2445 bool set_option_dithering(void)
2447 static const struct opt_items dithering
[DITHER_NUM_MODES
] = {
2448 [DITHER_NONE
] = { "Off", -1 },
2449 [DITHER_ORDERED
] = { "Ordered", -1 },
2450 [DITHER_DIFFUSION
] = { "Diffusion", -1 },
2453 rb
->set_option("Dithering", &jpeg_settings
.dither_mode
, INT
,
2454 dithering
, DITHER_NUM_MODES
, NULL
);
2458 static void display_options(void)
2460 static const struct menu_item items
[] = {
2461 { "Grayscale", set_option_grayscale
},
2462 { "Dithering", set_option_dithering
},
2465 int m
= menu_init(rb
, items
, ARRAYLEN(items
),
2466 NULL
, NULL
, NULL
, NULL
);
2470 #endif /* HAVE_LCD_COLOR */
2472 int show_menu(void) /* return 1 to quit */
2475 rb
->lcd_set_backdrop(old_backdrop
);
2476 #ifdef HAVE_LCD_COLOR
2477 rb
->lcd_set_foreground(rb
->global_settings
->fg_color
);
2478 rb
->lcd_set_background(rb
->global_settings
->bg_color
);
2480 rb
->lcd_set_foreground(LCD_BLACK
);
2481 rb
->lcd_set_background(LCD_WHITE
);
2490 MIID_TOGGLE_SS_MODE
,
2491 MIID_CHANGE_SS_MODE
,
2492 #if PLUGIN_BUFFER_SIZE >= MIN_MEM
2493 MIID_SHOW_PLAYBACK_MENU
,
2495 #ifdef HAVE_LCD_COLOR
2496 MIID_DISPLAY_OPTIONS
,
2501 static const struct menu_item items
[] = {
2504 [MIID_TOGGLE_SS_MODE
] =
2505 { "Toggle Slideshow Mode", NULL
},
2506 [MIID_CHANGE_SS_MODE
] =
2507 { "Change Slideshow Time", NULL
},
2508 #if PLUGIN_BUFFER_SIZE >= MIN_MEM
2509 [MIID_SHOW_PLAYBACK_MENU
] =
2510 { "Show Playback Menu", NULL
},
2512 #ifdef HAVE_LCD_COLOR
2513 [MIID_DISPLAY_OPTIONS
] =
2514 { "Display Options", NULL
},
2520 static const struct opt_items slideshow
[2] = {
2525 m
= menu_init(rb
, items
, sizeof(items
) / sizeof(*items
),
2526 NULL
, NULL
, NULL
, NULL
);
2527 result
=menu_show(m
);
2535 case MIID_TOGGLE_SS_MODE
:
2536 rb
->set_option("Toggle Slideshow", &slideshow_enabled
, INT
,
2537 slideshow
, 2, NULL
);
2539 case MIID_CHANGE_SS_MODE
:
2540 rb
->set_int("Slideshow Time", "s", UNIT_SEC
,
2541 &jpeg_settings
.ss_timeout
, NULL
, 1,
2542 SS_MIN_TIMEOUT
, SS_MAX_TIMEOUT
, NULL
);
2545 #if PLUGIN_BUFFER_SIZE >= MIN_MEM
2546 case MIID_SHOW_PLAYBACK_MENU
:
2547 playback_control(rb
);
2550 #ifdef HAVE_LCD_COLOR
2551 case MIID_DISPLAY_OPTIONS
:
2559 #if !defined(SIMULATOR) && !defined(HAVE_FLASH_STORAGE)
2560 /* change ata spindown time based on slideshow time setting */
2561 immediate_ata_off
= false;
2562 rb
->ata_spindown(rb
->global_settings
->disk_spindown
);
2564 if (slideshow_enabled
)
2566 if(jpeg_settings
.ss_timeout
< 10)
2568 /* slideshow times < 10s keep disk spinning */
2569 rb
->ata_spindown(0);
2571 else if (!rb
->mp3_is_playing())
2573 /* slideshow times > 10s and not playing: ata_off after load */
2574 immediate_ata_off
= true;
2579 rb
->lcd_set_backdrop(NULL
);
2580 rb
->lcd_set_foreground(LCD_WHITE
);
2581 rb
->lcd_set_background(LCD_BLACK
);
2583 rb
->lcd_clear_display();
2587 /* interactively scroll around the image */
2588 int scroll_bmp(struct t_disp
* pdisp
)
2597 if (slideshow_enabled
)
2598 button
= rb
->button_get_w_tmo(jpeg_settings
.ss_timeout
* HZ
);
2599 else button
= rb
->button_get(true);
2601 running_slideshow
= false;
2606 if (!(ds
< ds_max
) && entries
> 0 && jpg
.x_size
<= MAX_X_SIZE
)
2607 return change_filename(DIR_PREV
);
2608 case JPEG_LEFT
| BUTTON_REPEAT
:
2609 move
= MIN(HSCROLL
, pdisp
->x
);
2612 MYXLCD(scroll_right
)(move
); /* scroll right */
2614 #ifdef HAVE_LCD_COLOR
2616 pdisp
->bitmap
, pdisp
->csub_x
, pdisp
->csub_y
,
2617 pdisp
->x
, pdisp
->y
, pdisp
->stride
,
2618 0, MAX(0, (LCD_HEIGHT
-pdisp
->height
)/2), /* x, y */
2619 move
, MIN(LCD_HEIGHT
, pdisp
->height
)); /* w, h */
2621 MYXLCD(gray_bitmap_part
)(
2622 pdisp
->bitmap
[0], pdisp
->x
, pdisp
->y
, pdisp
->stride
,
2623 0, MAX(0, (LCD_HEIGHT
-pdisp
->height
)/2), /* x, y */
2624 move
, MIN(LCD_HEIGHT
, pdisp
->height
)); /* w, h */
2631 if (!(ds
< ds_max
) && entries
> 0 && jpg
.x_size
<= MAX_X_SIZE
)
2632 return change_filename(DIR_NEXT
);
2633 case JPEG_RIGHT
| BUTTON_REPEAT
:
2634 move
= MIN(HSCROLL
, pdisp
->width
- pdisp
->x
- LCD_WIDTH
);
2637 MYXLCD(scroll_left
)(move
); /* scroll left */
2639 #ifdef HAVE_LCD_COLOR
2641 pdisp
->bitmap
, pdisp
->csub_x
, pdisp
->csub_y
,
2642 pdisp
->x
+ LCD_WIDTH
- move
, pdisp
->y
, pdisp
->stride
,
2643 LCD_WIDTH
- move
, MAX(0, (LCD_HEIGHT
-pdisp
->height
)/2), /* x, y */
2644 move
, MIN(LCD_HEIGHT
, pdisp
->height
)); /* w, h */
2646 MYXLCD(gray_bitmap_part
)(
2647 pdisp
->bitmap
[0], pdisp
->x
+ LCD_WIDTH
- move
,
2648 pdisp
->y
, pdisp
->stride
,
2649 LCD_WIDTH
- move
, MAX(0, (LCD_HEIGHT
-pdisp
->height
)/2), /* x, y */
2650 move
, MIN(LCD_HEIGHT
, pdisp
->height
)); /* w, h */
2657 case JPEG_UP
| BUTTON_REPEAT
:
2658 move
= MIN(VSCROLL
, pdisp
->y
);
2661 MYXLCD(scroll_down
)(move
); /* scroll down */
2663 #ifdef HAVE_LCD_COLOR
2664 if (jpeg_settings
.dither_mode
== DITHER_DIFFUSION
)
2666 /* Draw over the band at the top of the last update
2667 caused by lack of error history on line zero. */
2668 move
= MIN(move
+ 1, pdisp
->y
+ pdisp
->height
);
2672 pdisp
->bitmap
, pdisp
->csub_x
, pdisp
->csub_y
,
2673 pdisp
->x
, pdisp
->y
, pdisp
->stride
,
2674 MAX(0, (LCD_WIDTH
-pdisp
->width
)/2), 0, /* x, y */
2675 MIN(LCD_WIDTH
, pdisp
->width
), move
); /* w, h */
2677 MYXLCD(gray_bitmap_part
)(
2678 pdisp
->bitmap
[0], pdisp
->x
, pdisp
->y
, pdisp
->stride
,
2679 MAX(0, (LCD_WIDTH
-pdisp
->width
)/2), 0, /* x, y */
2680 MIN(LCD_WIDTH
, pdisp
->width
), move
); /* w, h */
2687 case JPEG_DOWN
| BUTTON_REPEAT
:
2688 move
= MIN(VSCROLL
, pdisp
->height
- pdisp
->y
- LCD_HEIGHT
);
2691 MYXLCD(scroll_up
)(move
); /* scroll up */
2693 #ifdef HAVE_LCD_COLOR
2694 if (jpeg_settings
.dither_mode
== DITHER_DIFFUSION
)
2696 /* Save the line that was on the last line of the display
2697 and draw one extra line above then recover the line with
2698 image data that had an error history when it was drawn.
2702 rb
->lcd_framebuffer
+ (LCD_HEIGHT
- move
)*LCD_WIDTH
,
2703 LCD_WIDTH
*sizeof (fb_data
));
2707 pdisp
->bitmap
, pdisp
->csub_x
, pdisp
->csub_y
, pdisp
->x
,
2708 pdisp
->y
+ LCD_HEIGHT
- move
, pdisp
->stride
,
2709 MAX(0, (LCD_WIDTH
-pdisp
->width
)/2), LCD_HEIGHT
- move
, /* x, y */
2710 MIN(LCD_WIDTH
, pdisp
->width
), move
); /* w, h */
2712 if (jpeg_settings
.dither_mode
== DITHER_DIFFUSION
)
2714 /* Cover the first row drawn with previous image data. */
2715 MEMCPY(rb
->lcd_framebuffer
+ (LCD_HEIGHT
- move
)*LCD_WIDTH
,
2717 LCD_WIDTH
*sizeof (fb_data
));
2721 MYXLCD(gray_bitmap_part
)(
2722 pdisp
->bitmap
[0], pdisp
->x
,
2723 pdisp
->y
+ LCD_HEIGHT
- move
, pdisp
->stride
,
2724 MAX(0, (LCD_WIDTH
-pdisp
->width
)/2), LCD_HEIGHT
- move
, /* x, y */
2725 MIN(LCD_WIDTH
, pdisp
->width
), move
); /* w, h */
2731 if (!slideshow_enabled
)
2733 running_slideshow
= true;
2735 return change_filename(DIR_NEXT
);
2738 #ifdef JPEG_SLIDE_SHOW
2739 case JPEG_SLIDE_SHOW
:
2740 slideshow_enabled
= !slideshow_enabled
;
2741 running_slideshow
= slideshow_enabled
;
2745 #ifdef JPEG_NEXT_REPEAT
2746 case JPEG_NEXT_REPEAT
:
2750 return change_filename(DIR_NEXT
);
2753 #ifdef JPEG_PREVIOUS_REPEAT
2754 case JPEG_PREVIOUS_REPEAT
:
2758 return change_filename(DIR_PREV
);
2762 #ifdef JPEG_ZOOM_PRE
2763 if (lastbutton
!= JPEG_ZOOM_PRE
)
2770 #ifdef JPEG_ZOOM_PRE
2771 if (lastbutton
!= JPEG_ZOOM_PRE
)
2781 grey_show(false); /* switch off greyscale overlay */
2783 if (show_menu() == 1)
2787 grey_show(true); /* switch on greyscale overlay */
2790 pdisp
->bitmap
, pdisp
->csub_x
, pdisp
->csub_y
,
2791 pdisp
->x
, pdisp
->y
, pdisp
->stride
,
2792 MAX(0, (LCD_WIDTH
- pdisp
->width
) / 2),
2793 MAX(0, (LCD_HEIGHT
- pdisp
->height
) / 2),
2794 MIN(LCD_WIDTH
, pdisp
->width
),
2795 MIN(LCD_HEIGHT
, pdisp
->height
));
2800 if (rb
->default_event_handler_ex(button
, cleanup
, NULL
)
2801 == SYS_USB_CONNECTED
)
2802 return PLUGIN_USB_CONNECTED
;
2807 if (button
!= BUTTON_NONE
)
2808 lastbutton
= button
;
2809 } /* while (true) */
2812 /********************* main function *************************/
2814 /* callback updating a progress meter while JPEG decoding */
2815 void cb_progess(int current
, int total
)
2817 rb
->yield(); /* be nice to the other threads */
2818 if(!running_slideshow
)
2820 rb
->gui_scrollbar_draw(rb
->screens
[SCREEN_MAIN
],0, LCD_HEIGHT
-8, LCD_WIDTH
, 8, total
, 0,
2821 current
, HORIZONTAL
);
2822 rb
->lcd_update_rect(0, LCD_HEIGHT
-8, LCD_WIDTH
, 8);
2827 /* in slideshow mode, keep gui interference to a minimum */
2828 rb
->gui_scrollbar_draw(rb
->screens
[SCREEN_MAIN
],0, LCD_HEIGHT
-4, LCD_WIDTH
, 4, total
, 0,
2829 current
, HORIZONTAL
);
2830 rb
->lcd_update_rect(0, LCD_HEIGHT
-4, LCD_WIDTH
, 4);
2835 int jpegmem(struct jpeg
*p_jpg
, int ds
)
2839 size
= (p_jpg
->x_phys
/ds
/p_jpg
->subsample_x
[0])
2840 * (p_jpg
->y_phys
/ds
/p_jpg
->subsample_y
[0]);
2841 #ifdef HAVE_LCD_COLOR
2842 if (p_jpg
->blocks
> 1) /* colour, add requirements for chroma */
2844 size
+= (p_jpg
->x_phys
/ds
/p_jpg
->subsample_x
[1])
2845 * (p_jpg
->y_phys
/ds
/p_jpg
->subsample_y
[1]);
2846 size
+= (p_jpg
->x_phys
/ds
/p_jpg
->subsample_x
[2])
2847 * (p_jpg
->y_phys
/ds
/p_jpg
->subsample_y
[2]);
2853 /* how far can we zoom in without running out of memory */
2854 int min_downscale(struct jpeg
*p_jpg
, int bufsize
)
2858 if (jpegmem(p_jpg
, 8) > bufsize
)
2859 return 0; /* error, too large, even 1:8 doesn't fit */
2861 while (downscale
> 1 && jpegmem(p_jpg
, downscale
/2) <= bufsize
)
2868 /* how far can we zoom out, to fit image into the LCD */
2869 int max_downscale(struct jpeg
*p_jpg
)
2873 while (downscale
< 8 && (p_jpg
->x_size
> LCD_WIDTH
*downscale
2874 || p_jpg
->y_size
> LCD_HEIGHT
*downscale
))
2883 /* return decoded or cached image */
2884 struct t_disp
* get_image(struct jpeg
* p_jpg
, int ds
)
2886 int w
, h
; /* used to center output */
2887 int size
; /* decompressed image size */
2888 long time
; /* measured ticks */
2891 struct t_disp
* p_disp
= &disp
[ds
]; /* short cut */
2893 if (p_disp
->bitmap
[0] != NULL
)
2895 return p_disp
; /* we still have it */
2898 /* assign image buffer */
2900 /* physical size needed for decoding */
2901 size
= jpegmem(p_jpg
, ds
);
2902 if (buf_size
<= size
)
2903 { /* have to discard the current */
2905 for (i
=1; i
<=8; i
++)
2906 disp
[i
].bitmap
[0] = NULL
; /* invalidate all bitmaps */
2907 buf
= buf_root
; /* start again from the beginning of the buffer */
2908 buf_size
= root_size
;
2911 #ifdef HAVE_LCD_COLOR
2912 if (p_jpg
->blocks
> 1) /* colour jpeg */
2916 for (i
= 1; i
< 3; i
++)
2918 size
= (p_jpg
->x_phys
/ ds
/ p_jpg
->subsample_x
[i
])
2919 * (p_jpg
->y_phys
/ ds
/ p_jpg
->subsample_y
[i
]);
2920 p_disp
->bitmap
[i
] = buf
;
2924 p_disp
->csub_x
= p_jpg
->subsample_x
[1];
2925 p_disp
->csub_y
= p_jpg
->subsample_y
[1];
2929 p_disp
->csub_x
= p_disp
->csub_y
= 0;
2930 p_disp
->bitmap
[1] = p_disp
->bitmap
[2] = buf
;
2933 /* size may be less when decoded (if height is not block aligned) */
2934 size
= (p_jpg
->x_phys
/ds
) * (p_jpg
->y_size
/ ds
);
2935 p_disp
->bitmap
[0] = buf
;
2939 if(!running_slideshow
)
2941 rb
->snprintf(print
, sizeof(print
), "decoding %d*%d",
2942 p_jpg
->x_size
/ds
, p_jpg
->y_size
/ds
);
2943 rb
->lcd_puts(0, 3, print
);
2947 /* update image properties */
2948 p_disp
->width
= p_jpg
->x_size
/ ds
;
2949 p_disp
->stride
= p_jpg
->x_phys
/ ds
; /* use physical size for stride */
2950 p_disp
->height
= p_jpg
->y_size
/ ds
;
2952 /* the actual decoding */
2953 time
= *rb
->current_tick
;
2954 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
2955 rb
->cpu_boost(true);
2956 status
= jpeg_decode(p_jpg
, p_disp
->bitmap
, ds
, cb_progess
);
2957 rb
->cpu_boost(false);
2959 status
= jpeg_decode(p_jpg
, p_disp
->bitmap
, ds
, cb_progess
);
2963 rb
->splash(HZ
, "decode error %d", status
);
2964 file_pt
[curfile
] = '\0';
2967 time
= *rb
->current_tick
- time
;
2969 if(!running_slideshow
)
2971 rb
->snprintf(print
, sizeof(print
), " %ld.%02ld sec ", time
/HZ
, time
%HZ
);
2972 rb
->lcd_getstringsize(print
, &w
, &h
); /* centered in progress bar */
2973 rb
->lcd_putsxy((LCD_WIDTH
- w
)/2, LCD_HEIGHT
- h
, print
);
2981 /* set the view to the given center point, limit if necessary */
2982 void set_view (struct t_disp
* p_disp
, int cx
, int cy
)
2986 /* plain center to available width/height */
2987 x
= cx
- MIN(LCD_WIDTH
, p_disp
->width
) / 2;
2988 y
= cy
- MIN(LCD_HEIGHT
, p_disp
->height
) / 2;
2990 /* limit against upper image size */
2991 x
= MIN(p_disp
->width
- LCD_WIDTH
, x
);
2992 y
= MIN(p_disp
->height
- LCD_HEIGHT
, y
);
2994 /* limit against negative side */
2998 p_disp
->x
= x
; /* set the values */
3003 /* calculate the view center based on the bitmap position */
3004 void get_view(struct t_disp
* p_disp
, int* p_cx
, int* p_cy
)
3006 *p_cx
= p_disp
->x
+ MIN(LCD_WIDTH
, p_disp
->width
) / 2;
3007 *p_cy
= p_disp
->y
+ MIN(LCD_HEIGHT
, p_disp
->height
) / 2;
3011 /* load, decode, display the image */
3012 int load_and_show(char* filename
)
3016 unsigned char* buf_jpeg
; /* compressed JPEG image */
3018 struct t_disp
* p_disp
; /* currenly displayed image */
3019 int cx
, cy
; /* view center */
3021 fd
= rb
->open(filename
, O_RDONLY
);
3024 rb
->snprintf(print
,sizeof(print
),"err opening %s:%d",filename
,fd
);
3025 rb
->splash(HZ
, print
);
3026 return PLUGIN_ERROR
;
3028 filesize
= rb
->filesize(fd
);
3029 rb
->memset(&disp
, 0, sizeof(disp
));
3031 buf
= buf_images
+ filesize
;
3032 buf_size
= buf_images_size
- filesize
;
3033 /* allocate JPEG buffer */
3034 buf_jpeg
= buf_images
;
3036 buf_root
= buf
; /* we can start the decompressed images behind it */
3037 root_size
= buf_size
;
3041 #if PLUGIN_BUFFER_SIZE >= MIN_MEM
3045 rb
->lcd_setfont(FONT_SYSFIXED
);
3046 rb
->lcd_clear_display();
3047 rb
->snprintf(print
,sizeof(print
),"%s:",rb
->strrchr(filename
,'/')+1);
3048 rb
->lcd_puts(0,0,print
);
3049 rb
->lcd_puts(0,1,"Not enough plugin memory!");
3050 rb
->lcd_puts(0,2,"Zoom In: Stop playback.");
3052 rb
->lcd_puts(0,3,"Left/Right: Skip File.");
3053 rb
->lcd_puts(0,4,"Off: Quit.");
3055 rb
->lcd_setfont(FONT_UI
);
3057 rb
->button_clear_queue();
3061 int button
= rb
->button_get(true);
3066 buf_images
= rb
->plugin_get_audio_buffer(
3067 (size_t *)&buf_images_size
);
3068 /*try again this file, now using the audio buffer */
3069 return PLUGIN_OTHER
;
3079 rb
->lcd_clear_display();
3080 return change_filename(DIR_PREV
);
3087 rb
->lcd_clear_display();
3088 return change_filename(DIR_NEXT
);
3092 if(rb
->default_event_handler_ex(button
, cleanup
, NULL
)
3093 == SYS_USB_CONNECTED
)
3094 return PLUGIN_USB_CONNECTED
;
3102 rb
->splash(HZ
, "Out of Memory");
3104 return PLUGIN_ERROR
;
3108 if(!running_slideshow
)
3111 rb
->lcd_set_foreground(LCD_WHITE
);
3112 rb
->lcd_set_background(LCD_BLACK
);
3113 rb
->lcd_set_backdrop(NULL
);
3116 rb
->lcd_clear_display();
3117 rb
->snprintf(print
, sizeof(print
), "%s:", rb
->strrchr(filename
,'/')+1);
3118 rb
->lcd_puts(0, 0, print
);
3121 rb
->snprintf(print
, sizeof(print
), "loading %d bytes", filesize
);
3122 rb
->lcd_puts(0, 1, print
);
3126 rb
->read(fd
, buf_jpeg
, filesize
);
3129 if(!running_slideshow
)
3131 rb
->snprintf(print
, sizeof(print
), "decoding markers");
3132 rb
->lcd_puts(0, 2, print
);
3136 else if(immediate_ata_off
)
3138 /* running slideshow and time is long enough: power down disk */
3143 rb
->memset(&jpg
, 0, sizeof(jpg
)); /* clear info struct */
3144 /* process markers, unstuffing */
3145 status
= process_markers(buf_jpeg
, filesize
, &jpg
);
3147 if (status
< 0 || (status
& (DQT
| SOF0
)) != (DQT
| SOF0
))
3148 { /* bad format or minimum components not contained */
3149 rb
->splash(HZ
, "unsupported %d", status
);
3150 file_pt
[curfile
] = '\0';
3151 return change_filename(direction
);
3154 if (!(status
& DHT
)) /* if no Huffman table present: */
3155 default_huff_tbl(&jpg
); /* use default */
3156 build_lut(&jpg
); /* derive Huffman and other lookup-tables */
3158 if(!running_slideshow
)
3160 rb
->snprintf(print
, sizeof(print
), "image %dx%d", jpg
.x_size
, jpg
.y_size
);
3161 rb
->lcd_puts(0, 2, print
);
3164 ds_max
= max_downscale(&jpg
); /* check display constraint */
3165 ds_min
= min_downscale(&jpg
, buf_size
); /* check memory constraint */
3168 rb
->splash(HZ
, "too large");
3169 file_pt
[curfile
] = '\0';
3170 return change_filename(direction
);
3173 ds
= ds_max
; /* initials setting */
3174 cx
= jpg
.x_size
/ds
/2; /* center the view */
3175 cy
= jpg
.y_size
/ds
/2;
3177 do /* loop the image prepare and decoding when zoomed */
3179 p_disp
= get_image(&jpg
, ds
); /* decode or fetch from cache */
3181 return change_filename(direction
);
3183 set_view(p_disp
, cx
, cy
);
3185 if(!running_slideshow
)
3187 rb
->snprintf(print
, sizeof(print
), "showing %dx%d",
3188 p_disp
->width
, p_disp
->height
);
3189 rb
->lcd_puts(0, 3, print
);
3192 MYLCD(clear_display
)();
3193 #ifdef HAVE_LCD_COLOR
3195 p_disp
->bitmap
, p_disp
->csub_x
, p_disp
->csub_y
,
3196 p_disp
->x
, p_disp
->y
, p_disp
->stride
,
3197 MAX(0, (LCD_WIDTH
- p_disp
->width
) / 2),
3198 MAX(0, (LCD_HEIGHT
- p_disp
->height
) / 2),
3199 MIN(LCD_WIDTH
, p_disp
->width
),
3200 MIN(LCD_HEIGHT
, p_disp
->height
));
3202 MYXLCD(gray_bitmap_part
)(
3203 p_disp
->bitmap
[0], p_disp
->x
, p_disp
->y
, p_disp
->stride
,
3204 MAX(0, (LCD_WIDTH
- p_disp
->width
) / 2),
3205 MAX(0, (LCD_HEIGHT
- p_disp
->height
) / 2),
3206 MIN(LCD_WIDTH
, p_disp
->width
),
3207 MIN(LCD_HEIGHT
, p_disp
->height
));
3212 grey_show(true); /* switch on greyscale overlay */
3215 /* drawing is now finished, play around with scrolling
3216 * until you press OFF or connect USB
3220 status
= scroll_bmp(p_disp
);
3221 if (status
== ZOOM_IN
)
3225 ds
/= 2; /* reduce downscaling to zoom in */
3226 get_view(p_disp
, &cx
, &cy
);
3227 cx
*= 2; /* prepare the position in the new image */
3234 if (status
== ZOOM_OUT
)
3238 ds
*= 2; /* increase downscaling to zoom out */
3239 get_view(p_disp
, &cx
, &cy
);
3240 cx
/= 2; /* prepare the position in the new image */
3250 grey_show(false); /* switch off overlay */
3252 rb
->lcd_clear_display();
3254 while (status
!= PLUGIN_OK
&& status
!= PLUGIN_USB_CONNECTED
3255 && status
!= PLUGIN_OTHER
);
3262 /******************** Plugin entry point *********************/
3264 enum plugin_status
plugin_start(struct plugin_api
* api
, void* parameter
)
3270 long greysize
; /* helper */
3273 old_backdrop
= rb
->lcd_get_backdrop();
3276 if(!parameter
) return PLUGIN_ERROR
;
3278 rb
->strcpy(np_file
, parameter
);
3281 if(!entries
) return PLUGIN_ERROR
;
3283 #if (PLUGIN_BUFFER_SIZE >= MIN_MEM) && !defined(SIMULATOR)
3284 if(rb
->audio_status())
3286 buf
= rb
->plugin_get_buffer((size_t *)&buf_size
) +
3287 (entries
* sizeof(char**));
3288 buf_size
-= (entries
* sizeof(char**));
3292 buf
= rb
->plugin_get_audio_buffer((size_t *)&buf_size
);
3294 buf
= rb
->plugin_get_audio_buffer(&buf_size
) +
3295 (entries
* sizeof(char**));
3296 buf_size
-= (entries
* sizeof(char**));
3300 if (!grey_init(rb
, buf
, buf_size
, false, LCD_WIDTH
, LCD_HEIGHT
, &greysize
))
3302 rb
->splash(HZ
, "grey buf error");
3303 return PLUGIN_ERROR
;
3306 buf_size
-= greysize
;
3311 /* should be ok to just load settings since a parameter is present
3312 here and the drive should be spinning */
3313 configfile_init(rb
);
3314 configfile_load(JPEG_CONFIGFILE
, jpeg_config
,
3315 ARRAYLEN(jpeg_config
), JPEG_SETTINGS_MINVERSION
);
3316 old_settings
= jpeg_settings
;
3318 buf_images
= buf
; buf_images_size
= buf_size
;
3320 /* Turn off backlight timeout */
3321 backlight_force_on(rb
); /* backlight control in lib/helper.c */
3325 condition
= load_and_show(np_file
);
3326 }while (condition
!= PLUGIN_OK
&& condition
!= PLUGIN_USB_CONNECTED
3327 && condition
!= PLUGIN_ERROR
);
3329 if (rb
->memcmp(&jpeg_settings
, &old_settings
, sizeof (jpeg_settings
)))
3331 /* Just in case drive has to spin, keep it from looking locked */
3332 rb
->splash(0, "Saving Settings");
3333 configfile_save(JPEG_CONFIGFILE
, jpeg_config
,
3334 ARRAYLEN(jpeg_config
), JPEG_SETTINGS_VERSION
);
3337 #if !defined(SIMULATOR) && !defined(HAVE_FLASH_STORAGE)
3338 /* set back ata spindown time in case we changed it */
3339 rb
->ata_spindown(rb
->global_settings
->disk_spindown
);
3342 /* Turn on backlight timeout (revert to settings) */
3343 backlight_use_settings(rb
); /* backlight control in lib/helper.c */
3346 grey_release(); /* deinitialize */
3352 #endif /* HAVE_LCD_BITMAP */