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�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 ****************************************************************************/
28 #include "playback_control.h"
29 #include "oldmenuapi.h"
32 #ifdef HAVE_LCD_BITMAP
37 #include "lib/configfile.h"
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
89 #define JPEG_NEXT BUTTON_REC
90 #define JPEG_PREVIOUS BUTTON_ON
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 == SANSA_C200_PAD
146 #define JPEG_ZOOM_PRE BUTTON_SELECT
147 #define JPEG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
148 #define JPEG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
149 #define JPEG_UP BUTTON_UP
150 #define JPEG_DOWN BUTTON_DOWN
151 #define JPEG_LEFT BUTTON_LEFT
152 #define JPEG_RIGHT BUTTON_RIGHT
153 #define JPEG_MENU BUTTON_POWER
154 #define JPEG_SLIDE_SHOW BUTTON_REC
155 #define JPEG_NEXT BUTTON_VOL_UP
156 #define JPEG_NEXT_REPEAT (BUTTON_VOL_UP|BUTTON_REPEAT)
157 #define JPEG_PREVIOUS BUTTON_VOL_DOWN
158 #define JPEG_PREVIOUS_REPEAT (BUTTON_VOL_DOWN|BUTTON_REPEAT)
160 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
161 #define JPEG_ZOOM_PRE BUTTON_PLAY
162 #define JPEG_ZOOM_IN (BUTTON_PLAY | BUTTON_REL)
163 #define JPEG_ZOOM_OUT (BUTTON_PLAY | BUTTON_REPEAT)
164 #define JPEG_UP BUTTON_SCROLL_UP
165 #define JPEG_DOWN BUTTON_SCROLL_DOWN
166 #define JPEG_LEFT BUTTON_LEFT
167 #define JPEG_RIGHT BUTTON_RIGHT
168 #define JPEG_MENU BUTTON_POWER
169 #define JPEG_NEXT BUTTON_FF
170 #define JPEG_PREVIOUS BUTTON_REW
174 /* different graphics libraries */
177 #define MYLCD(fn) gray_ub_ ## fn
178 #define MYLCD_UPDATE()
179 #define MYXLCD(fn) gray_ub_ ## fn
181 #define MYLCD(fn) rb->lcd_ ## fn
182 #define MYLCD_UPDATE() rb->lcd_update();
183 #define MYXLCD(fn) xlcd_ ## fn
186 #define MAX_X_SIZE LCD_WIDTH*8
188 /* Min memory allowing us to use the plugin buffer
189 * and thus not stopping the music
190 * *Very* rough estimation:
191 * Max 10 000 dir entries * 4bytes/entry (char **) = 40000 bytes
192 * + 20k code size = 60 000
193 * + 50k min for jpeg = 120 000
195 #define MIN_MEM 120000
202 #define PLUGIN_OTHER 10 /* State code for output with return. */
204 /******************************* Globals ***********************************/
206 static struct plugin_api
* rb
;
207 MEM_FUNCTION_WRAPPERS(rb
);
209 /* for portability of below JPEG code */
210 #define MEMSET(p,v,c) rb->memset(p,v,c)
211 #define MEMCPY(d,s,c) rb->memcpy(d,s,c)
212 #define INLINE static inline
213 #define ENDIAN_SWAP16(n) n /* only for poor little endian machines */
215 static int slideshow_enabled
= false; /* run slideshow */
216 static int running_slideshow
= false; /* loading image because of slideshw */
218 static int immediate_ata_off
= false; /* power down disk after loading */
220 static int button_timeout
= HZ
*5;
222 #ifdef HAVE_LCD_COLOR
224 /* Persistent configuration - only needed for color displays atm */
225 #define JPEG_CONFIGFILE "jpeg.cfg"
226 #define JPEG_SETTINGS_MINVERSION 1
227 #define JPEG_SETTINGS_VERSION 1
231 COLOURMODE_COLOUR
= 0,
238 DITHER_NONE
= 0, /* No dithering */
239 DITHER_ORDERED
, /* Bayer ordered */
240 DITHER_DIFFUSION
, /* Floyd/Steinberg error diffusion */
250 static struct jpeg_settings jpeg_settings
=
251 { COLOURMODE_COLOUR
, DITHER_NONE
};
252 static struct jpeg_settings old_settings
;
254 static struct configdata jpeg_config
[] =
256 { TYPE_ENUM
, 0, COLOUR_NUM_MODES
, &jpeg_settings
.colour_mode
,
257 "Colour Mode", (char *[]){ "Colour", "Grayscale" }, NULL
},
258 { TYPE_ENUM
, 0, DITHER_NUM_MODES
, &jpeg_settings
.dither_mode
,
259 "Dither Mode", (char *[]){ "None", "Ordered", "Diffusion" }, NULL
},
262 #endif /* HAVE_LCD_COLOR */
264 fb_data
* old_backdrop
;
267 /**************** begin JPEG code ********************/
269 INLINE
unsigned range_limit(int value
)
271 #if CONFIG_CPU == SH7034
273 asm ( /* Note: Uses knowledge that only low byte of result is used */
275 "sub %[t],%[v] \n" /* value -= -128; equals value += 128; */
276 "extu.b %[v],%[t] \n"
277 "cmp/eq %[v],%[t] \n" /* low byte == whole number ? */
278 "bt 1f \n" /* yes: no overflow */
279 "cmp/pz %[v] \n" /* overflow: positive? */
280 "subc %[v],%[v] \n" /* %[r] now either 0 or 0xffffffff */
287 #elif defined(CPU_COLDFIRE)
288 asm ( /* Note: Uses knowledge that only the low byte of the result is used */
289 "add.l #128,%[v] \n" /* value += 128; */
290 "cmp.l #255,%[v] \n" /* overflow? */
291 "bls.b 1f \n" /* no: return value */
292 "spl.b %[v] \n" /* yes: set low byte to appropriate boundary */
298 #elif defined(CPU_ARM)
299 asm ( /* Note: Uses knowledge that only the low byte of the result is used */
300 "add %[v], %[v], #128 \n" /* value += 128 */
301 "cmp %[v], #255 \n" /* out of range 0..255? */
302 "mvnhi %[v], %[v], asr #31 \n" /* yes: set all bits to ~(sign_bit) */
310 if ((unsigned)value
<= 255)
320 /* IDCT implementation */
323 #define CONST_BITS 13
327 /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
328 * causing a lot of useless floating-point operations at run time.
329 * To get around this we use the following pre-calculated constants.
330 * If you change CONST_BITS you may want to add appropriate values.
331 * (With a reasonable C compiler, you can just rely on the FIX() macro...)
333 #define FIX_0_298631336 2446 /* FIX(0.298631336) */
334 #define FIX_0_390180644 3196 /* FIX(0.390180644) */
335 #define FIX_0_541196100 4433 /* FIX(0.541196100) */
336 #define FIX_0_765366865 6270 /* FIX(0.765366865) */
337 #define FIX_0_899976223 7373 /* FIX(0.899976223) */
338 #define FIX_1_175875602 9633 /* FIX(1.175875602) */
339 #define FIX_1_501321110 12299 /* FIX(1.501321110) */
340 #define FIX_1_847759065 15137 /* FIX(1.847759065) */
341 #define FIX_1_961570560 16069 /* FIX(1.961570560) */
342 #define FIX_2_053119869 16819 /* FIX(2.053119869) */
343 #define FIX_2_562915447 20995 /* FIX(2.562915447) */
344 #define FIX_3_072711026 25172 /* FIX(3.072711026) */
348 /* Multiply an long variable by an long constant to yield an long result.
349 * For 8-bit samples with the recommended scaling, all the variable
350 * and constant values involved are no more than 16 bits wide, so a
351 * 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
352 * For 12-bit samples, a full 32-bit multiplication will be needed.
354 #define MULTIPLY16(var,const) (((short) (var)) * ((short) (const)))
357 /* Dequantize a coefficient by multiplying it by the multiplier-table
358 * entry; produce an int result. In this module, both inputs and result
359 * are 16 bits or less, so either int or short multiply will work.
361 /* #define DEQUANTIZE(coef,quantval) (((int) (coef)) * (quantval)) */
362 #define DEQUANTIZE MULTIPLY16
364 /* Descale and correctly round an int value that's scaled by N bits.
365 * We assume RIGHT_SHIFT rounds towards minus infinity, so adding
366 * the fudge factor is correct for either sign of X.
368 #define DESCALE(x,n) (((x) + (1l << ((n)-1))) >> (n))
373 * Perform dequantization and inverse DCT on one block of coefficients,
374 * producing a reduced-size 1x1 output block.
376 void idct1x1(unsigned char* p_byte
, int* inptr
, int* quantptr
, int skip_line
)
378 (void)skip_line
; /* unused */
379 *p_byte
= range_limit(inptr
[0] * quantptr
[0] >> 3);
385 * Perform dequantization and inverse DCT on one block of coefficients,
386 * producing a reduced-size 2x2 output block.
388 void idct2x2(unsigned char* p_byte
, int* inptr
, int* quantptr
, int skip_line
)
390 int tmp0
, tmp1
, tmp2
, tmp3
, tmp4
, tmp5
;
391 unsigned char* outptr
;
393 /* Pass 1: process columns from input, store into work array. */
396 tmp4
= DEQUANTIZE(inptr
[8*0], quantptr
[8*0]);
397 tmp5
= DEQUANTIZE(inptr
[8*1], quantptr
[8*1]);
403 tmp4
= DEQUANTIZE(inptr
[8*0+1], quantptr
[8*0+1]);
404 tmp5
= DEQUANTIZE(inptr
[8*1+1], quantptr
[8*1+1]);
409 /* Pass 2: process 2 rows, store into output array. */
414 outptr
[0] = range_limit((int) DESCALE(tmp0
+ tmp1
, 3));
415 outptr
[1] = range_limit((int) DESCALE(tmp0
- tmp1
, 3));
418 outptr
= p_byte
+ skip_line
;
420 outptr
[0] = range_limit((int) DESCALE(tmp2
+ tmp3
, 3));
421 outptr
[1] = range_limit((int) DESCALE(tmp2
- tmp3
, 3));
427 * Perform dequantization and inverse DCT on one block of coefficients,
428 * producing a reduced-size 4x4 output block.
430 void idct4x4(unsigned char* p_byte
, int* inptr
, int* quantptr
, int skip_line
)
432 int tmp0
, tmp2
, tmp10
, tmp12
;
435 unsigned char* outptr
;
437 int workspace
[4*4]; /* buffers data between passes */
439 /* Pass 1: process columns from input, store into work array. */
442 for (ctr
= 0; ctr
< 4; ctr
++, inptr
++, quantptr
++, wsptr
++)
446 tmp0
= DEQUANTIZE(inptr
[8*0], quantptr
[8*0]);
447 tmp2
= DEQUANTIZE(inptr
[8*2], quantptr
[8*2]);
449 tmp10
= (tmp0
+ tmp2
) << PASS1_BITS
;
450 tmp12
= (tmp0
- tmp2
) << PASS1_BITS
;
453 /* Same rotation as in the even part of the 8x8 LL&M IDCT */
455 z2
= DEQUANTIZE(inptr
[8*1], quantptr
[8*1]);
456 z3
= DEQUANTIZE(inptr
[8*3], quantptr
[8*3]);
458 z1
= MULTIPLY16(z2
+ z3
, FIX_0_541196100
);
459 tmp0
= DESCALE(z1
+ MULTIPLY16(z3
, - FIX_1_847759065
), CONST_BITS
-PASS1_BITS
);
460 tmp2
= DESCALE(z1
+ MULTIPLY16(z2
, FIX_0_765366865
), CONST_BITS
-PASS1_BITS
);
462 /* Final output stage */
464 wsptr
[4*0] = (int) (tmp10
+ tmp2
);
465 wsptr
[4*3] = (int) (tmp10
- tmp2
);
466 wsptr
[4*1] = (int) (tmp12
+ tmp0
);
467 wsptr
[4*2] = (int) (tmp12
- tmp0
);
470 /* Pass 2: process 4 rows from work array, store into output array. */
473 for (ctr
= 0; ctr
< 4; ctr
++)
475 outptr
= p_byte
+ (ctr
*skip_line
);
478 tmp0
= (int) wsptr
[0];
479 tmp2
= (int) wsptr
[2];
481 tmp10
= (tmp0
+ tmp2
) << CONST_BITS
;
482 tmp12
= (tmp0
- tmp2
) << CONST_BITS
;
485 /* Same rotation as in the even part of the 8x8 LL&M IDCT */
490 z1
= MULTIPLY16(z2
+ z3
, FIX_0_541196100
);
491 tmp0
= z1
+ MULTIPLY16(z3
, - FIX_1_847759065
);
492 tmp2
= z1
+ MULTIPLY16(z2
, FIX_0_765366865
);
494 /* Final output stage */
496 outptr
[0] = range_limit((int) DESCALE(tmp10
+ tmp2
,
497 CONST_BITS
+PASS1_BITS
+3));
498 outptr
[3] = range_limit((int) DESCALE(tmp10
- tmp2
,
499 CONST_BITS
+PASS1_BITS
+3));
500 outptr
[1] = range_limit((int) DESCALE(tmp12
+ tmp0
,
501 CONST_BITS
+PASS1_BITS
+3));
502 outptr
[2] = range_limit((int) DESCALE(tmp12
- tmp0
,
503 CONST_BITS
+PASS1_BITS
+3));
505 wsptr
+= 4; /* advance pointer to next row */
512 * Perform dequantization and inverse DCT on one block of coefficients.
514 void idct8x8(unsigned char* p_byte
, int* inptr
, int* quantptr
, int skip_line
)
516 long tmp0
, tmp1
, tmp2
, tmp3
;
517 long tmp10
, tmp11
, tmp12
, tmp13
;
518 long z1
, z2
, z3
, z4
, z5
;
520 unsigned char* outptr
;
522 int workspace
[64]; /* buffers data between passes */
524 /* Pass 1: process columns from input, store into work array. */
525 /* Note results are scaled up by sqrt(8) compared to a true IDCT; */
526 /* furthermore, we scale the results by 2**PASS1_BITS. */
529 for (ctr
= 8; ctr
> 0; ctr
--)
531 /* Due to quantization, we will usually find that many of the input
532 * coefficients are zero, especially the AC terms. We can exploit this
533 * by short-circuiting the IDCT calculation for any column in which all
534 * the AC terms are zero. In that case each output is equal to the
535 * DC coefficient (with scale factor as needed).
536 * With typical images and quantization tables, half or more of the
537 * column DCT calculations can be simplified this way.
540 if ((inptr
[8*1] | inptr
[8*2] | inptr
[8*3]
541 | inptr
[8*4] | inptr
[8*5] | inptr
[8*6] | inptr
[8*7]) == 0)
543 /* AC terms all zero */
544 int dcval
= DEQUANTIZE(inptr
[8*0], quantptr
[8*0]) << PASS1_BITS
;
546 wsptr
[8*0] = wsptr
[8*1] = wsptr
[8*2] = wsptr
[8*3] = wsptr
[8*4]
547 = wsptr
[8*5] = wsptr
[8*6] = wsptr
[8*7] = dcval
;
548 inptr
++; /* advance pointers to next column */
554 /* Even part: reverse the even part of the forward DCT. */
555 /* The rotator is sqrt(2)*c(-6). */
557 z2
= DEQUANTIZE(inptr
[8*2], quantptr
[8*2]);
558 z3
= DEQUANTIZE(inptr
[8*6], quantptr
[8*6]);
560 z1
= MULTIPLY16(z2
+ z3
, FIX_0_541196100
);
561 tmp2
= z1
+ MULTIPLY16(z3
, - FIX_1_847759065
);
562 tmp3
= z1
+ MULTIPLY16(z2
, FIX_0_765366865
);
564 z2
= DEQUANTIZE(inptr
[8*0], quantptr
[8*0]);
565 z3
= DEQUANTIZE(inptr
[8*4], quantptr
[8*4]);
567 tmp0
= (z2
+ z3
) << CONST_BITS
;
568 tmp1
= (z2
- z3
) << CONST_BITS
;
575 /* Odd part per figure 8; the matrix is unitary and hence its
576 transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */
578 tmp0
= DEQUANTIZE(inptr
[8*7], quantptr
[8*7]);
579 tmp1
= DEQUANTIZE(inptr
[8*5], quantptr
[8*5]);
580 tmp2
= DEQUANTIZE(inptr
[8*3], quantptr
[8*3]);
581 tmp3
= DEQUANTIZE(inptr
[8*1], quantptr
[8*1]);
587 z5
= MULTIPLY16(z3
+ z4
, FIX_1_175875602
); /* sqrt(2) * c3 */
589 tmp0
= MULTIPLY16(tmp0
, FIX_0_298631336
); /* sqrt(2) * (-c1+c3+c5-c7) */
590 tmp1
= MULTIPLY16(tmp1
, FIX_2_053119869
); /* sqrt(2) * ( c1+c3-c5+c7) */
591 tmp2
= MULTIPLY16(tmp2
, FIX_3_072711026
); /* sqrt(2) * ( c1+c3+c5-c7) */
592 tmp3
= MULTIPLY16(tmp3
, FIX_1_501321110
); /* sqrt(2) * ( c1+c3-c5-c7) */
593 z1
= MULTIPLY16(z1
, - FIX_0_899976223
); /* sqrt(2) * (c7-c3) */
594 z2
= MULTIPLY16(z2
, - FIX_2_562915447
); /* sqrt(2) * (-c1-c3) */
595 z3
= MULTIPLY16(z3
, - FIX_1_961570560
); /* sqrt(2) * (-c3-c5) */
596 z4
= MULTIPLY16(z4
, - FIX_0_390180644
); /* sqrt(2) * (c5-c3) */
606 /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
608 wsptr
[8*0] = (int) DESCALE(tmp10
+ tmp3
, CONST_BITS
-PASS1_BITS
);
609 wsptr
[8*7] = (int) DESCALE(tmp10
- tmp3
, CONST_BITS
-PASS1_BITS
);
610 wsptr
[8*1] = (int) DESCALE(tmp11
+ tmp2
, CONST_BITS
-PASS1_BITS
);
611 wsptr
[8*6] = (int) DESCALE(tmp11
- tmp2
, CONST_BITS
-PASS1_BITS
);
612 wsptr
[8*2] = (int) DESCALE(tmp12
+ tmp1
, CONST_BITS
-PASS1_BITS
);
613 wsptr
[8*5] = (int) DESCALE(tmp12
- tmp1
, CONST_BITS
-PASS1_BITS
);
614 wsptr
[8*3] = (int) DESCALE(tmp13
+ tmp0
, CONST_BITS
-PASS1_BITS
);
615 wsptr
[8*4] = (int) DESCALE(tmp13
- tmp0
, CONST_BITS
-PASS1_BITS
);
617 inptr
++; /* advance pointers to next column */
622 /* Pass 2: process rows from work array, store into output array. */
623 /* Note that we must descale the results by a factor of 8 == 2**3, */
624 /* and also undo the PASS1_BITS scaling. */
627 for (ctr
= 0; ctr
< 8; ctr
++)
629 outptr
= p_byte
+ (ctr
*skip_line
);
630 /* Rows of zeroes can be exploited in the same way as we did with columns.
631 * However, the column calculation has created many nonzero AC terms, so
632 * the simplification applies less often (typically 5% to 10% of the time).
633 * On machines with very fast multiplication, it's possible that the
634 * test takes more time than it's worth. In that case this section
635 * may be commented out.
638 #ifndef NO_ZERO_ROW_TEST
639 if ((wsptr
[1] | wsptr
[2] | wsptr
[3]
640 | wsptr
[4] | wsptr
[5] | wsptr
[6] | wsptr
[7]) == 0)
642 /* AC terms all zero */
643 unsigned char dcval
= range_limit((int) DESCALE((long) wsptr
[0],
655 wsptr
+= 8; /* advance pointer to next row */
660 /* Even part: reverse the even part of the forward DCT. */
661 /* The rotator is sqrt(2)*c(-6). */
663 z2
= (long) wsptr
[2];
664 z3
= (long) wsptr
[6];
666 z1
= MULTIPLY16(z2
+ z3
, FIX_0_541196100
);
667 tmp2
= z1
+ MULTIPLY16(z3
, - FIX_1_847759065
);
668 tmp3
= z1
+ MULTIPLY16(z2
, FIX_0_765366865
);
670 tmp0
= ((long) wsptr
[0] + (long) wsptr
[4]) << CONST_BITS
;
671 tmp1
= ((long) wsptr
[0] - (long) wsptr
[4]) << CONST_BITS
;
678 /* Odd part per figure 8; the matrix is unitary and hence its
679 * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */
681 tmp0
= (long) wsptr
[7];
682 tmp1
= (long) wsptr
[5];
683 tmp2
= (long) wsptr
[3];
684 tmp3
= (long) wsptr
[1];
690 z5
= MULTIPLY16(z3
+ z4
, FIX_1_175875602
); /* sqrt(2) * c3 */
692 tmp0
= MULTIPLY16(tmp0
, FIX_0_298631336
); /* sqrt(2) * (-c1+c3+c5-c7) */
693 tmp1
= MULTIPLY16(tmp1
, FIX_2_053119869
); /* sqrt(2) * ( c1+c3-c5+c7) */
694 tmp2
= MULTIPLY16(tmp2
, FIX_3_072711026
); /* sqrt(2) * ( c1+c3+c5-c7) */
695 tmp3
= MULTIPLY16(tmp3
, FIX_1_501321110
); /* sqrt(2) * ( c1+c3-c5-c7) */
696 z1
= MULTIPLY16(z1
, - FIX_0_899976223
); /* sqrt(2) * (c7-c3) */
697 z2
= MULTIPLY16(z2
, - FIX_2_562915447
); /* sqrt(2) * (-c1-c3) */
698 z3
= MULTIPLY16(z3
, - FIX_1_961570560
); /* sqrt(2) * (-c3-c5) */
699 z4
= MULTIPLY16(z4
, - FIX_0_390180644
); /* sqrt(2) * (c5-c3) */
709 /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
711 outptr
[0] = range_limit((int) DESCALE(tmp10
+ tmp3
,
712 CONST_BITS
+PASS1_BITS
+3));
713 outptr
[7] = range_limit((int) DESCALE(tmp10
- tmp3
,
714 CONST_BITS
+PASS1_BITS
+3));
715 outptr
[1] = range_limit((int) DESCALE(tmp11
+ tmp2
,
716 CONST_BITS
+PASS1_BITS
+3));
717 outptr
[6] = range_limit((int) DESCALE(tmp11
- tmp2
,
718 CONST_BITS
+PASS1_BITS
+3));
719 outptr
[2] = range_limit((int) DESCALE(tmp12
+ tmp1
,
720 CONST_BITS
+PASS1_BITS
+3));
721 outptr
[5] = range_limit((int) DESCALE(tmp12
- tmp1
,
722 CONST_BITS
+PASS1_BITS
+3));
723 outptr
[3] = range_limit((int) DESCALE(tmp13
+ tmp0
,
724 CONST_BITS
+PASS1_BITS
+3));
725 outptr
[4] = range_limit((int) DESCALE(tmp13
- tmp0
,
726 CONST_BITS
+PASS1_BITS
+3));
728 wsptr
+= 8; /* advance pointer to next row */
734 /* JPEG decoder implementation */
737 #define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */
741 /* Basic tables: (element [0] of each array is unused) */
742 long mincode
[17]; /* smallest code of length k */
743 long maxcode
[18]; /* largest code of length k (-1 if none) */
744 /* (maxcode[17] is a sentinel to ensure huff_DECODE terminates) */
745 int valptr
[17]; /* huffval[] index of 1st symbol of length k */
747 /* Back link to public Huffman table (needed only in slow_DECODE) */
750 /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of
751 the input data stream. If the next Huffman code is no more
752 than HUFF_LOOKAHEAD bits long, we can obtain its length and
753 the corresponding symbol directly from these tables. */
754 int look_nbits
[1<<HUFF_LOOKAHEAD
]; /* # bits, or 0 if too long */
755 unsigned char look_sym
[1<<HUFF_LOOKAHEAD
]; /* symbol, or unused */
758 #define QUANT_TABLE_LENGTH 64
760 /* for type of Huffman table */
765 { /* length and code according to JFIF format */
766 int huffmancodes_dc
[DC_LEN
];
767 int huffmancodes_ac
[AC_LEN
];
770 struct frame_component
773 int horizontal_sampling
;
774 int vertical_sampling
;
775 int quanttable_select
;
778 struct scan_component
787 unsigned long get_buffer
; /* current bit-extraction buffer */
788 int bits_left
; /* # of unused bits in it */
789 unsigned char* next_input_byte
;
790 unsigned char* input_end
; /* upper limit +1 */
795 int x_size
, y_size
; /* size of image (can be less than block boundary) */
796 int x_phys
, y_phys
; /* physical size, block aligned */
797 int x_mbl
; /* x dimension of MBL */
798 int y_mbl
; /* y dimension of MBL */
799 int blocks
; /* blocks per MB */
800 int restart_interval
; /* number of MCUs between RSTm markers */
801 int store_pos
[4]; /* for Y block ordering */
803 unsigned char* p_entropy_data
;
804 unsigned char* p_entropy_end
;
806 int quanttable
[4][QUANT_TABLE_LENGTH
]; /* raw quantization tables 0-3 */
807 int qt_idct
[2][QUANT_TABLE_LENGTH
]; /* quantization tables for IDCT */
809 struct huffman_table hufftable
[2]; /* Huffman tables */
810 struct derived_tbl dc_derived_tbls
[2]; /* Huffman-LUTs */
811 struct derived_tbl ac_derived_tbls
[2];
813 struct frame_component frameheader
[3]; /* Component descriptor */
814 struct scan_component scanheader
[3]; /* currently not used */
816 int mcu_membership
[6]; /* info per block */
817 int tab_membership
[6];
818 int subsample_x
[3]; /* info per component */
823 /* possible return flags for process_markers() */
824 #define HUFFTAB 0x0001 /* with huffman table */
825 #define QUANTTAB 0x0002 /* with quantization table */
826 #define APP0_JFIF 0x0004 /* with APP0 segment following JFIF standard */
827 #define FILL_FF 0x0008 /* with 0xFF padding bytes at begin/end */
828 #define SOF0 0x0010 /* with SOF0-Segment */
829 #define DHT 0x0020 /* with Definition of huffman tables */
830 #define SOS 0x0040 /* with Start-of-Scan segment */
831 #define DQT 0x0080 /* with definition of quantization table */
833 /* Preprocess the JPEG JFIF file */
834 int process_markers(unsigned char* p_src
, long size
, struct jpeg
* p_jpeg
)
836 unsigned char* p_bytes
= p_src
;
837 int marker_size
; /* variable length of marker segment */
839 int ret
= 0; /* returned flags */
841 p_jpeg
->p_entropy_end
= p_src
+ size
;
843 while (p_src
< p_bytes
+ size
)
845 if (*p_src
++ != 0xFF) /* no marker? */
847 p_src
--; /* it's image data, put it back */
848 p_jpeg
->p_entropy_data
= p_src
;
849 break; /* exit marker processing */
854 case 0xFF: /* Fill byte */
856 case 0x00: /* Zero stuffed byte - entropy data */
857 p_src
--; /* put it back */
860 case 0xC0: /* SOF Huff - Baseline DCT */
863 marker_size
= *p_src
++ << 8; /* Highbyte */
864 marker_size
|= *p_src
++; /* Lowbyte */
865 n
= *p_src
++; /* sample precision (= 8 or 12) */
868 return(-1); /* Unsupported sample precision */
870 p_jpeg
->y_size
= *p_src
++ << 8; /* Highbyte */
871 p_jpeg
->y_size
|= *p_src
++; /* Lowbyte */
872 p_jpeg
->x_size
= *p_src
++ << 8; /* Highbyte */
873 p_jpeg
->x_size
|= *p_src
++; /* Lowbyte */
875 n
= (marker_size
-2-6)/3;
876 if (*p_src
++ != n
|| (n
!= 1 && n
!= 3))
878 return(-2); /* Unsupported SOF0 component specification */
882 p_jpeg
->frameheader
[i
].ID
= *p_src
++; /* Component info */
883 p_jpeg
->frameheader
[i
].horizontal_sampling
= *p_src
>> 4;
884 p_jpeg
->frameheader
[i
].vertical_sampling
= *p_src
++ & 0x0F;
885 p_jpeg
->frameheader
[i
].quanttable_select
= *p_src
++;
886 if (p_jpeg
->frameheader
[i
].horizontal_sampling
> 2
887 || p_jpeg
->frameheader
[i
].vertical_sampling
> 2)
888 return -3; /* Unsupported SOF0 subsampling */
894 case 0xC1: /* SOF Huff - Extended sequential DCT*/
895 case 0xC2: /* SOF Huff - Progressive DCT*/
896 case 0xC3: /* SOF Huff - Spatial (sequential) lossless*/
897 case 0xC5: /* SOF Huff - Differential sequential DCT*/
898 case 0xC6: /* SOF Huff - Differential progressive DCT*/
899 case 0xC7: /* SOF Huff - Differential spatial*/
900 case 0xC8: /* SOF Arith - Reserved for JPEG extensions*/
901 case 0xC9: /* SOF Arith - Extended sequential DCT*/
902 case 0xCA: /* SOF Arith - Progressive DCT*/
903 case 0xCB: /* SOF Arith - Spatial (sequential) lossless*/
904 case 0xCD: /* SOF Arith - Differential sequential DCT*/
905 case 0xCE: /* SOF Arith - Differential progressive DCT*/
906 case 0xCF: /* SOF Arith - Differential spatial*/
908 return (-4); /* other DCT model than baseline not implemented */
911 case 0xC4: /* Define Huffman Table(s) */
913 unsigned char* p_temp
;
916 marker_size
= *p_src
++ << 8; /* Highbyte */
917 marker_size
|= *p_src
++; /* Lowbyte */
920 while (p_src
< p_temp
+marker_size
-2-17) /* another table */
923 i
= *p_src
& 0x0F; /* table index */
926 return (-5); /* Huffman table index out of range */
928 else if (*p_src
++ & 0xF0) /* AC table */
933 p_jpeg
->hufftable
[i
].huffmancodes_ac
[j
] = *p_src
++;
935 if(16 + sum
> AC_LEN
)
936 return -10; /* longer than allowed */
938 for (; j
< 16 + sum
; j
++)
939 p_jpeg
->hufftable
[i
].huffmancodes_ac
[j
] = *p_src
++;
946 p_jpeg
->hufftable
[i
].huffmancodes_dc
[j
] = *p_src
++;
948 if(16 + sum
> DC_LEN
)
949 return -11; /* longer than allowed */
951 for (; j
< 16 + sum
; j
++)
952 p_jpeg
->hufftable
[i
].huffmancodes_dc
[j
] = *p_src
++;
955 p_src
= p_temp
+marker_size
- 2; /* skip possible residue */
959 case 0xCC: /* Define Arithmetic coding conditioning(s) */
960 return(-6); /* Arithmetic coding not supported */
962 case 0xD8: /* Start of Image */
963 case 0xD9: /* End of Image */
964 case 0x01: /* for temp private use arith code */
965 break; /* skip parameterless marker */
968 case 0xDA: /* Start of Scan */
971 marker_size
= *p_src
++ << 8; /* Highbyte */
972 marker_size
|= *p_src
++; /* Lowbyte */
974 n
= (marker_size
-2-1-3)/2;
975 if (*p_src
++ != n
|| (n
!= 1 && n
!= 3))
977 return (-7); /* Unsupported SOS component specification */
981 p_jpeg
->scanheader
[i
].ID
= *p_src
++;
982 p_jpeg
->scanheader
[i
].DC_select
= *p_src
>> 4;
983 p_jpeg
->scanheader
[i
].AC_select
= *p_src
++ & 0x0F;
985 p_src
+= 3; /* skip spectral information */
989 case 0xDB: /* Define quantization Table(s) */
992 marker_size
= *p_src
++ << 8; /* Highbyte */
993 marker_size
|= *p_src
++; /* Lowbyte */
994 n
= (marker_size
-2)/(QUANT_TABLE_LENGTH
+1); /* # of tables */
997 int id
= *p_src
++; /* ID */
1000 return (-8); /* Unsupported quantization table */
1002 /* Read Quantisation table: */
1003 for (j
=0; j
<QUANT_TABLE_LENGTH
; j
++)
1004 p_jpeg
->quanttable
[id
][j
] = *p_src
++;
1009 case 0xDD: /* Define Restart Interval */
1011 marker_size
= *p_src
++ << 8; /* Highbyte */
1012 marker_size
|= *p_src
++; /* Lowbyte */
1013 p_jpeg
->restart_interval
= *p_src
++ << 8; /* Highbyte */
1014 p_jpeg
->restart_interval
|= *p_src
++; /* Lowbyte */
1015 p_src
+= marker_size
-4; /* skip segment */
1019 case 0xDC: /* Define Number of Lines */
1020 case 0xDE: /* Define Hierarchical progression */
1021 case 0xDF: /* Expand Reference Component(s) */
1022 case 0xE0: /* Application Field 0*/
1023 case 0xE1: /* Application Field 1*/
1024 case 0xE2: /* Application Field 2*/
1025 case 0xE3: /* Application Field 3*/
1026 case 0xE4: /* Application Field 4*/
1027 case 0xE5: /* Application Field 5*/
1028 case 0xE6: /* Application Field 6*/
1029 case 0xE7: /* Application Field 7*/
1030 case 0xE8: /* Application Field 8*/
1031 case 0xE9: /* Application Field 9*/
1032 case 0xEA: /* Application Field 10*/
1033 case 0xEB: /* Application Field 11*/
1034 case 0xEC: /* Application Field 12*/
1035 case 0xED: /* Application Field 13*/
1036 case 0xEE: /* Application Field 14*/
1037 case 0xEF: /* Application Field 15*/
1038 case 0xFE: /* Comment */
1040 marker_size
= *p_src
++ << 8; /* Highbyte */
1041 marker_size
|= *p_src
++; /* Lowbyte */
1042 p_src
+= marker_size
-2; /* skip segment */
1046 case 0xF0: /* Reserved for JPEG extensions */
1047 case 0xF1: /* Reserved for JPEG extensions */
1048 case 0xF2: /* Reserved for JPEG extensions */
1049 case 0xF3: /* Reserved for JPEG extensions */
1050 case 0xF4: /* Reserved for JPEG extensions */
1051 case 0xF5: /* Reserved for JPEG extensions */
1052 case 0xF6: /* Reserved for JPEG extensions */
1053 case 0xF7: /* Reserved for JPEG extensions */
1054 case 0xF8: /* Reserved for JPEG extensions */
1055 case 0xF9: /* Reserved for JPEG extensions */
1056 case 0xFA: /* Reserved for JPEG extensions */
1057 case 0xFB: /* Reserved for JPEG extensions */
1058 case 0xFC: /* Reserved for JPEG extensions */
1059 case 0xFD: /* Reserved for JPEG extensions */
1060 case 0x02: /* Reserved */
1062 return (-9); /* Unknown marker */
1066 return (ret
); /* return flags with seen markers */
1070 void default_huff_tbl(struct jpeg
* p_jpeg
)
1072 static const struct huffman_table luma_table
=
1075 0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,
1076 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B
1079 0x00,0x02,0x01,0x03,0x03,0x02,0x04,0x03,0x05,0x05,0x04,0x04,0x00,0x00,0x01,0x7D,
1080 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,
1081 0x22,0x71,0x14,0x32,0x81,0x91,0xA1,0x08,0x23,0x42,0xB1,0xC1,0x15,0x52,0xD1,0xF0,
1082 0x24,0x33,0x62,0x72,0x82,0x09,0x0A,0x16,0x17,0x18,0x19,0x1A,0x25,0x26,0x27,0x28,
1083 0x29,0x2A,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,
1084 0x4A,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,
1085 0x6A,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
1086 0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,
1087 0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xC2,0xC3,0xC4,0xC5,
1088 0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xE1,0xE2,
1089 0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,
1094 static const struct huffman_table chroma_table
=
1097 0x00,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,
1098 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B
1101 0x00,0x02,0x01,0x02,0x04,0x04,0x03,0x04,0x07,0x05,0x04,0x04,0x00,0x01,0x02,0x77,
1102 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,
1103 0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xA1,0xB1,0xC1,0x09,0x23,0x33,0x52,0xF0,
1104 0x15,0x62,0x72,0xD1,0x0A,0x16,0x24,0x34,0xE1,0x25,0xF1,0x17,0x18,0x19,0x1A,0x26,
1105 0x27,0x28,0x29,0x2A,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,
1106 0x49,0x4A,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,
1107 0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x82,0x83,0x84,0x85,0x86,0x87,
1108 0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5,
1109 0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xC2,0xC3,
1110 0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,
1111 0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,
1116 MEMCPY(&p_jpeg
->hufftable
[0], &luma_table
, sizeof(luma_table
));
1117 MEMCPY(&p_jpeg
->hufftable
[1], &chroma_table
, sizeof(chroma_table
));
1122 /* Compute the derived values for a Huffman table */
1123 void fix_huff_tbl(int* htbl
, struct derived_tbl
* dtbl
)
1128 unsigned int huffcode
[257];
1131 dtbl
->pub
= htbl
; /* fill in back link */
1133 /* Figure C.1: make table of Huffman code length for each symbol */
1134 /* Note that this is in code-length order. */
1137 for (l
= 1; l
<= 16; l
++)
1138 { /* all possible code length */
1139 for (i
= 1; i
<= (int) htbl
[l
-1]; i
++) /* all codes per length */
1140 huffsize
[p
++] = (char) l
;
1144 /* Figure C.2: generate the codes themselves */
1145 /* Note that this is in code-length order. */
1152 while (((int) huffsize
[p
]) == si
)
1154 huffcode
[p
++] = code
;
1161 /* Figure F.15: generate decoding tables for bit-sequential decoding */
1164 for (l
= 1; l
<= 16; l
++)
1168 dtbl
->valptr
[l
] = p
; /* huffval[] index of 1st symbol of code length l */
1169 dtbl
->mincode
[l
] = huffcode
[p
]; /* minimum code of length l */
1171 dtbl
->maxcode
[l
] = huffcode
[p
-1]; /* maximum code of length l */
1175 dtbl
->maxcode
[l
] = -1; /* -1 if no codes of this length */
1178 dtbl
->maxcode
[17] = 0xFFFFFL
; /* ensures huff_DECODE terminates */
1180 /* Compute lookahead tables to speed up decoding.
1181 * First we set all the table entries to 0, indicating "too long";
1182 * then we iterate through the Huffman codes that are short enough and
1183 * fill in all the entries that correspond to bit sequences starting
1187 MEMSET(dtbl
->look_nbits
, 0, sizeof(dtbl
->look_nbits
));
1190 for (l
= 1; l
<= HUFF_LOOKAHEAD
; l
++)
1192 for (i
= 1; i
<= (int) htbl
[l
-1]; i
++, p
++)
1194 /* l = current code's length, p = its index in huffcode[] & huffval[]. */
1195 /* Generate left-justified code followed by all possible bit sequences */
1196 lookbits
= huffcode
[p
] << (HUFF_LOOKAHEAD
-l
);
1197 for (ctr
= 1 << (HUFF_LOOKAHEAD
-l
); ctr
> 0; ctr
--)
1199 dtbl
->look_nbits
[lookbits
] = l
;
1200 dtbl
->look_sym
[lookbits
] = htbl
[16+p
];
1208 /* zag[i] is the natural-order position of the i'th element of zigzag order.
1209 * If the incoming data is corrupted, decode_mcu could attempt to
1210 * reference values beyond the end of the array. To avoid a wild store,
1211 * we put some extra zeroes after the real entries.
1213 static const int zag
[] =
1215 0, 1, 8, 16, 9, 2, 3, 10,
1216 17, 24, 32, 25, 18, 11, 4, 5,
1217 12, 19, 26, 33, 40, 48, 41, 34,
1218 27, 20, 13, 6, 7, 14, 21, 28,
1219 35, 42, 49, 56, 57, 50, 43, 36,
1220 29, 22, 15, 23, 30, 37, 44, 51,
1221 58, 59, 52, 45, 38, 31, 39, 46,
1222 53, 60, 61, 54, 47, 55, 62, 63,
1223 0, 0, 0, 0, 0, 0, 0, 0, /* extra entries in case k>63 below */
1224 0, 0, 0, 0, 0, 0, 0, 0
1227 void build_lut(struct jpeg
* p_jpeg
)
1230 fix_huff_tbl(p_jpeg
->hufftable
[0].huffmancodes_dc
,
1231 &p_jpeg
->dc_derived_tbls
[0]);
1232 fix_huff_tbl(p_jpeg
->hufftable
[0].huffmancodes_ac
,
1233 &p_jpeg
->ac_derived_tbls
[0]);
1234 fix_huff_tbl(p_jpeg
->hufftable
[1].huffmancodes_dc
,
1235 &p_jpeg
->dc_derived_tbls
[1]);
1236 fix_huff_tbl(p_jpeg
->hufftable
[1].huffmancodes_ac
,
1237 &p_jpeg
->ac_derived_tbls
[1]);
1239 /* build the dequantization tables for the IDCT (De-ZiZagged) */
1240 for (i
=0; i
<64; i
++)
1242 p_jpeg
->qt_idct
[0][zag
[i
]] = p_jpeg
->quanttable
[0][i
];
1243 p_jpeg
->qt_idct
[1][zag
[i
]] = p_jpeg
->quanttable
[1][i
];
1247 p_jpeg
->store_pos
[i
] = i
; /* default ordering */
1249 /* assignments for the decoding of blocks */
1250 if (p_jpeg
->frameheader
[0].horizontal_sampling
== 2
1251 && p_jpeg
->frameheader
[0].vertical_sampling
== 1)
1254 p_jpeg
->x_mbl
= (p_jpeg
->x_size
+15) / 16;
1255 p_jpeg
->x_phys
= p_jpeg
->x_mbl
* 16;
1256 p_jpeg
->y_mbl
= (p_jpeg
->y_size
+7) / 8;
1257 p_jpeg
->y_phys
= p_jpeg
->y_mbl
* 8;
1258 p_jpeg
->mcu_membership
[0] = 0; /* Y1=Y2=0, U=1, V=2 */
1259 p_jpeg
->mcu_membership
[1] = 0;
1260 p_jpeg
->mcu_membership
[2] = 1;
1261 p_jpeg
->mcu_membership
[3] = 2;
1262 p_jpeg
->tab_membership
[0] = 0; /* DC, DC, AC, AC */
1263 p_jpeg
->tab_membership
[1] = 0;
1264 p_jpeg
->tab_membership
[2] = 1;
1265 p_jpeg
->tab_membership
[3] = 1;
1266 p_jpeg
->subsample_x
[0] = 1;
1267 p_jpeg
->subsample_x
[1] = 2;
1268 p_jpeg
->subsample_x
[2] = 2;
1269 p_jpeg
->subsample_y
[0] = 1;
1270 p_jpeg
->subsample_y
[1] = 1;
1271 p_jpeg
->subsample_y
[2] = 1;
1273 if (p_jpeg
->frameheader
[0].horizontal_sampling
== 1
1274 && p_jpeg
->frameheader
[0].vertical_sampling
== 2)
1275 { /* 4:2:2 vertically subsampled */
1276 p_jpeg
->store_pos
[1] = 2; /* block positions are mirrored */
1277 p_jpeg
->store_pos
[2] = 1;
1279 p_jpeg
->x_mbl
= (p_jpeg
->x_size
+7) / 8;
1280 p_jpeg
->x_phys
= p_jpeg
->x_mbl
* 8;
1281 p_jpeg
->y_mbl
= (p_jpeg
->y_size
+15) / 16;
1282 p_jpeg
->y_phys
= p_jpeg
->y_mbl
* 16;
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] = 1;
1293 p_jpeg
->subsample_x
[2] = 1;
1294 p_jpeg
->subsample_y
[0] = 1;
1295 p_jpeg
->subsample_y
[1] = 2;
1296 p_jpeg
->subsample_y
[2] = 2;
1298 else if (p_jpeg
->frameheader
[0].horizontal_sampling
== 2
1299 && p_jpeg
->frameheader
[0].vertical_sampling
== 2)
1302 p_jpeg
->x_mbl
= (p_jpeg
->x_size
+15) / 16;
1303 p_jpeg
->x_phys
= p_jpeg
->x_mbl
* 16;
1304 p_jpeg
->y_mbl
= (p_jpeg
->y_size
+15) / 16;
1305 p_jpeg
->y_phys
= p_jpeg
->y_mbl
* 16;
1306 p_jpeg
->mcu_membership
[0] = 0;
1307 p_jpeg
->mcu_membership
[1] = 0;
1308 p_jpeg
->mcu_membership
[2] = 0;
1309 p_jpeg
->mcu_membership
[3] = 0;
1310 p_jpeg
->mcu_membership
[4] = 1;
1311 p_jpeg
->mcu_membership
[5] = 2;
1312 p_jpeg
->tab_membership
[0] = 0;
1313 p_jpeg
->tab_membership
[1] = 0;
1314 p_jpeg
->tab_membership
[2] = 0;
1315 p_jpeg
->tab_membership
[3] = 0;
1316 p_jpeg
->tab_membership
[4] = 1;
1317 p_jpeg
->tab_membership
[5] = 1;
1318 p_jpeg
->subsample_x
[0] = 1;
1319 p_jpeg
->subsample_x
[1] = 2;
1320 p_jpeg
->subsample_x
[2] = 2;
1321 p_jpeg
->subsample_y
[0] = 1;
1322 p_jpeg
->subsample_y
[1] = 2;
1323 p_jpeg
->subsample_y
[2] = 2;
1325 else if (p_jpeg
->frameheader
[0].horizontal_sampling
== 1
1326 && p_jpeg
->frameheader
[0].vertical_sampling
== 1)
1328 /* don't overwrite p_jpeg->blocks */
1329 p_jpeg
->x_mbl
= (p_jpeg
->x_size
+7) / 8;
1330 p_jpeg
->x_phys
= p_jpeg
->x_mbl
* 8;
1331 p_jpeg
->y_mbl
= (p_jpeg
->y_size
+7) / 8;
1332 p_jpeg
->y_phys
= p_jpeg
->y_mbl
* 8;
1333 p_jpeg
->mcu_membership
[0] = 0;
1334 p_jpeg
->mcu_membership
[1] = 1;
1335 p_jpeg
->mcu_membership
[2] = 2;
1336 p_jpeg
->tab_membership
[0] = 0;
1337 p_jpeg
->tab_membership
[1] = 1;
1338 p_jpeg
->tab_membership
[2] = 1;
1339 p_jpeg
->subsample_x
[0] = 1;
1340 p_jpeg
->subsample_x
[1] = 1;
1341 p_jpeg
->subsample_x
[2] = 1;
1342 p_jpeg
->subsample_y
[0] = 1;
1343 p_jpeg
->subsample_y
[1] = 1;
1344 p_jpeg
->subsample_y
[2] = 1;
1355 * These functions/macros provide the in-line portion of bit fetching.
1356 * Use check_bit_buffer to ensure there are N bits in get_buffer
1357 * before using get_bits, peek_bits, or drop_bits.
1358 * check_bit_buffer(state,n,action);
1359 * Ensure there are N bits in get_buffer; if suspend, take action.
1360 * val = get_bits(n);
1361 * Fetch next N bits.
1362 * val = peek_bits(n);
1363 * Fetch next N bits without removing them from the buffer.
1365 * Discard next N bits.
1366 * The value N should be a simple variable, not an expression, because it
1367 * is evaluated multiple times.
1370 INLINE
void check_bit_buffer(struct bitstream
* pb
, int nbits
)
1372 if (pb
->bits_left
< nbits
)
1373 { /* nbits is <= 16, so I can always refill 2 bytes in this case */
1376 byte
= *pb
->next_input_byte
++;
1377 if (byte
== 0xFF) /* legal marker can be byte stuffing or RSTm */
1378 { /* simplification: just skip the (one-byte) marker code */
1379 pb
->next_input_byte
++;
1381 pb
->get_buffer
= (pb
->get_buffer
<< 8) | byte
;
1383 byte
= *pb
->next_input_byte
++;
1384 if (byte
== 0xFF) /* legal marker can be byte stuffing or RSTm */
1385 { /* simplification: just skip the (one-byte) marker code */
1386 pb
->next_input_byte
++;
1388 pb
->get_buffer
= (pb
->get_buffer
<< 8) | byte
;
1390 pb
->bits_left
+= 16;
1394 INLINE
int get_bits(struct bitstream
* pb
, int nbits
)
1396 return ((int) (pb
->get_buffer
>> (pb
->bits_left
-= nbits
))) & ((1<<nbits
)-1);
1399 INLINE
int peek_bits(struct bitstream
* pb
, int nbits
)
1401 return ((int) (pb
->get_buffer
>> (pb
->bits_left
- nbits
))) & ((1<<nbits
)-1);
1404 INLINE
void drop_bits(struct bitstream
* pb
, int nbits
)
1406 pb
->bits_left
-= nbits
;
1409 /* re-synchronize to entropy data (skip restart marker) */
1410 void search_restart(struct bitstream
* pb
)
1412 pb
->next_input_byte
--; /* we may have overread it, taking 2 bytes */
1413 /* search for a non-byte-padding marker, has to be RSTm or EOS */
1414 while (pb
->next_input_byte
< pb
->input_end
&&
1415 (pb
->next_input_byte
[-2] != 0xFF || pb
->next_input_byte
[-1] == 0x00))
1417 pb
->next_input_byte
++;
1422 /* Figure F.12: extend sign bit. */
1423 #define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
1425 static const int extend_test
[16] = /* entry n is 2**(n-1) */
1427 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
1428 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000
1431 static const int extend_offset
[16] = /* entry n is (-1 << n) + 1 */
1433 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
1434 ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
1435 ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
1436 ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1
1439 /* Decode a single value */
1440 INLINE
int huff_decode_dc(struct bitstream
* bs
, struct derived_tbl
* tbl
)
1444 check_bit_buffer(bs
, HUFF_LOOKAHEAD
);
1445 look
= peek_bits(bs
, HUFF_LOOKAHEAD
);
1446 if ((nb
= tbl
->look_nbits
[look
]) != 0)
1449 s
= tbl
->look_sym
[look
];
1450 check_bit_buffer(bs
, s
);
1451 r
= get_bits(bs
, s
);
1452 s
= HUFF_EXTEND(r
, s
);
1455 { /* slow_DECODE(s, HUFF_LOOKAHEAD+1)) < 0); */
1457 nb
=HUFF_LOOKAHEAD
+1;
1458 check_bit_buffer(bs
, nb
);
1459 code
= get_bits(bs
, nb
);
1460 while (code
> tbl
->maxcode
[nb
])
1463 check_bit_buffer(bs
, 1);
1464 code
|= get_bits(bs
, 1);
1467 if (nb
> 16) /* error in Huffman */
1469 s
=0; /* fake a zero, this is most safe */
1473 s
= tbl
->pub
[16 + tbl
->valptr
[nb
] + ((int) (code
- tbl
->mincode
[nb
])) ];
1474 check_bit_buffer(bs
, s
);
1475 r
= get_bits(bs
, s
);
1476 s
= HUFF_EXTEND(r
, s
);
1478 } /* end slow decode */
1482 INLINE
int huff_decode_ac(struct bitstream
* bs
, struct derived_tbl
* tbl
)
1486 check_bit_buffer(bs
, HUFF_LOOKAHEAD
);
1487 look
= peek_bits(bs
, HUFF_LOOKAHEAD
);
1488 if ((nb
= tbl
->look_nbits
[look
]) != 0)
1491 s
= tbl
->look_sym
[look
];
1494 { /* slow_DECODE(s, HUFF_LOOKAHEAD+1)) < 0); */
1496 nb
=HUFF_LOOKAHEAD
+1;
1497 check_bit_buffer(bs
, nb
);
1498 code
= get_bits(bs
, nb
);
1499 while (code
> tbl
->maxcode
[nb
])
1502 check_bit_buffer(bs
, 1);
1503 code
|= get_bits(bs
, 1);
1506 if (nb
> 16) /* error in Huffman */
1508 s
=0; /* fake a zero, this is most safe */
1512 s
= tbl
->pub
[16 + tbl
->valptr
[nb
] + ((int) (code
- tbl
->mincode
[nb
])) ];
1514 } /* end slow decode */
1519 #ifdef HAVE_LCD_COLOR
1521 /* JPEG decoder variant for YUV decoding, into 3 different planes */
1522 /* Note: it keeps the original color subsampling, even if resized. */
1523 int jpeg_decode(struct jpeg
* p_jpeg
, unsigned char* p_pixel
[3],
1524 int downscale
, void (*pf_progress
)(int current
, int total
))
1526 struct bitstream bs
; /* bitstream "object" */
1527 int block
[64]; /* decoded DCT coefficients */
1530 int skip_line
[3]; /* bytes from one line to the next (skip_line) */
1531 int skip_strip
[3], skip_mcu
[3]; /* bytes to next DCT row / column */
1533 int i
, x
, y
; /* loop counter */
1535 unsigned char* p_line
[3] = {p_pixel
[0], p_pixel
[1], p_pixel
[2]};
1536 unsigned char* p_byte
[3]; /* bitmap pointer */
1538 void (*pf_idct
)(unsigned char*, int*, int*, int); /* selected IDCT */
1539 int k_need
; /* AC coefficients needed up to here */
1540 int zero_need
; /* init the block with this many zeros */
1542 int last_dc_val
[3] = {0, 0, 0}; /* or 128 for chroma? */
1543 int store_offs
[4]; /* memory offsets: order of Y11 Y12 Y21 Y22 U V */
1544 int restart
= p_jpeg
->restart_interval
; /* MCUs until restart marker */
1546 /* pick the IDCT we want, determine how to work with coefs */
1550 k_need
= 64; /* all */
1551 zero_need
= 63; /* all */
1553 else if (downscale
== 2)
1556 k_need
= 25; /* this far in zig-zag to cover 4*4 */
1557 zero_need
= 27; /* clear this far in linear order */
1559 else if (downscale
== 4)
1562 k_need
= 5; /* this far in zig-zag to cover 2*2 */
1563 zero_need
= 9; /* clear this far in linear order */
1565 else if (downscale
== 8)
1568 k_need
= 0; /* no AC, not needed */
1569 zero_need
= 0; /* no AC, not needed */
1571 else return -1; /* not supported */
1573 /* init bitstream, fake a restart to make it start */
1574 bs
.next_input_byte
= p_jpeg
->p_entropy_data
;
1576 bs
.input_end
= p_jpeg
->p_entropy_end
;
1578 width
= p_jpeg
->x_phys
/ downscale
;
1579 height
= p_jpeg
->y_phys
/ downscale
;
1580 for (i
=0; i
<3; i
++) /* calculate some strides */
1582 skip_line
[i
] = width
/ p_jpeg
->subsample_x
[i
];
1583 skip_strip
[i
] = skip_line
[i
]
1584 * (height
/ p_jpeg
->y_mbl
) / p_jpeg
->subsample_y
[i
];
1585 skip_mcu
[i
] = width
/p_jpeg
->x_mbl
/ p_jpeg
->subsample_x
[i
];
1588 /* prepare offsets about where to store the different blocks */
1589 store_offs
[p_jpeg
->store_pos
[0]] = 0;
1590 store_offs
[p_jpeg
->store_pos
[1]] = 8 / downscale
; /* to the right */
1591 store_offs
[p_jpeg
->store_pos
[2]] = width
* 8 / downscale
; /* below */
1592 store_offs
[p_jpeg
->store_pos
[3]] = store_offs
[1] + store_offs
[2]; /* r+b */
1594 for(y
=0; y
<p_jpeg
->y_mbl
&& bs
.next_input_byte
<= bs
.input_end
; y
++)
1596 for (i
=0; i
<3; i
++) /* scan line init */
1598 p_byte
[i
] = p_line
[i
];
1599 p_line
[i
] += skip_strip
[i
];
1601 for (x
=0; x
<p_jpeg
->x_mbl
; x
++)
1605 /* Outer loop handles each block in the MCU */
1606 for (blkn
= 0; blkn
< p_jpeg
->blocks
; blkn
++)
1607 { /* Decode a single block's worth of coefficients */
1608 int k
= 1; /* coefficient index */
1609 int s
, r
; /* huffman values */
1610 int ci
= p_jpeg
->mcu_membership
[blkn
]; /* component index */
1611 int ti
= p_jpeg
->tab_membership
[blkn
]; /* table index */
1612 struct derived_tbl
* dctbl
= &p_jpeg
->dc_derived_tbls
[ti
];
1613 struct derived_tbl
* actbl
= &p_jpeg
->ac_derived_tbls
[ti
];
1615 /* Section F.2.2.1: decode the DC coefficient difference */
1616 s
= huff_decode_dc(&bs
, dctbl
);
1618 last_dc_val
[ci
] += s
;
1619 block
[0] = last_dc_val
[ci
]; /* output it (assumes zag[0] = 0) */
1621 /* coefficient buffer must be cleared */
1622 MEMSET(block
+1, 0, zero_need
*sizeof(block
[0]));
1624 /* Section F.2.2.2: decode the AC coefficients */
1625 for (; k
< k_need
; k
++)
1627 s
= huff_decode_ac(&bs
, actbl
);
1634 check_bit_buffer(&bs
, s
);
1635 r
= get_bits(&bs
, s
);
1636 block
[zag
[k
]] = HUFF_EXTEND(r
, s
);
1648 /* In this path we just discard the values */
1651 s
= huff_decode_ac(&bs
, actbl
);
1658 check_bit_buffer(&bs
, s
);
1670 { /* Y component needs to bother about block store */
1671 pf_idct(p_byte
[0]+store_offs
[blkn
], block
,
1672 p_jpeg
->qt_idct
[ti
], skip_line
[0]);
1676 pf_idct(p_byte
[ci
], block
, p_jpeg
->qt_idct
[ti
],
1680 p_byte
[0] += skip_mcu
[0]; /* unrolled for (i=0; i<3; i++) loop */
1681 p_byte
[1] += skip_mcu
[1];
1682 p_byte
[2] += skip_mcu
[2];
1683 if (p_jpeg
->restart_interval
&& --restart
== 0)
1684 { /* if a restart marker is due: */
1685 restart
= p_jpeg
->restart_interval
; /* count again */
1686 search_restart(&bs
); /* align the bitstream */
1687 last_dc_val
[0] = last_dc_val
[1] =
1688 last_dc_val
[2] = 0; /* reset decoder */
1691 if (pf_progress
!= NULL
)
1692 pf_progress(y
, p_jpeg
->y_mbl
-1); /* notify about decoding progress */
1695 return 0; /* success */
1697 #else /* !HAVE_LCD_COLOR */
1699 /* a JPEG decoder specialized in decoding only the luminance (b&w) */
1700 int jpeg_decode(struct jpeg
* p_jpeg
, unsigned char* p_pixel
[1], int downscale
,
1701 void (*pf_progress
)(int current
, int total
))
1703 struct bitstream bs
; /* bitstream "object" */
1704 int block
[64]; /* decoded DCT coefficients */
1707 int skip_line
; /* bytes from one line to the next (skip_line) */
1708 int skip_strip
, skip_mcu
; /* bytes to next DCT row / column */
1710 int x
, y
; /* loop counter */
1712 unsigned char* p_line
= p_pixel
[0];
1713 unsigned char* p_byte
; /* bitmap pointer */
1715 void (*pf_idct
)(unsigned char*, int*, int*, int); /* selected IDCT */
1716 int k_need
; /* AC coefficients needed up to here */
1717 int zero_need
; /* init the block with this many zeros */
1719 int last_dc_val
= 0;
1720 int store_offs
[4]; /* memory offsets: order of Y11 Y12 Y21 Y22 U V */
1721 int restart
= p_jpeg
->restart_interval
; /* MCUs until restart marker */
1723 /* pick the IDCT we want, determine how to work with coefs */
1727 k_need
= 64; /* all */
1728 zero_need
= 63; /* all */
1730 else if (downscale
== 2)
1733 k_need
= 25; /* this far in zig-zag to cover 4*4 */
1734 zero_need
= 27; /* clear this far in linear order */
1736 else if (downscale
== 4)
1739 k_need
= 5; /* this far in zig-zag to cover 2*2 */
1740 zero_need
= 9; /* clear this far in linear order */
1742 else if (downscale
== 8)
1745 k_need
= 0; /* no AC, not needed */
1746 zero_need
= 0; /* no AC, not needed */
1748 else return -1; /* not supported */
1750 /* init bitstream, fake a restart to make it start */
1751 bs
.next_input_byte
= p_jpeg
->p_entropy_data
;
1753 bs
.input_end
= p_jpeg
->p_entropy_end
;
1755 width
= p_jpeg
->x_phys
/ downscale
;
1756 height
= p_jpeg
->y_phys
/ downscale
;
1758 skip_strip
= skip_line
* (height
/ p_jpeg
->y_mbl
);
1759 skip_mcu
= (width
/p_jpeg
->x_mbl
);
1761 /* prepare offsets about where to store the different blocks */
1762 store_offs
[p_jpeg
->store_pos
[0]] = 0;
1763 store_offs
[p_jpeg
->store_pos
[1]] = 8 / downscale
; /* to the right */
1764 store_offs
[p_jpeg
->store_pos
[2]] = width
* 8 / downscale
; /* below */
1765 store_offs
[p_jpeg
->store_pos
[3]] = store_offs
[1] + store_offs
[2]; /* r+b */
1767 for(y
=0; y
<p_jpeg
->y_mbl
&& bs
.next_input_byte
<= bs
.input_end
; y
++)
1770 p_line
+= skip_strip
;
1771 for (x
=0; x
<p_jpeg
->x_mbl
; x
++)
1775 /* Outer loop handles each block in the MCU */
1776 for (blkn
= 0; blkn
< p_jpeg
->blocks
; blkn
++)
1777 { /* Decode a single block's worth of coefficients */
1778 int k
= 1; /* coefficient index */
1779 int s
, r
; /* huffman values */
1780 int ci
= p_jpeg
->mcu_membership
[blkn
]; /* component index */
1781 int ti
= p_jpeg
->tab_membership
[blkn
]; /* table index */
1782 struct derived_tbl
* dctbl
= &p_jpeg
->dc_derived_tbls
[ti
];
1783 struct derived_tbl
* actbl
= &p_jpeg
->ac_derived_tbls
[ti
];
1785 /* Section F.2.2.1: decode the DC coefficient difference */
1786 s
= huff_decode_dc(&bs
, dctbl
);
1788 if (ci
== 0) /* only for Y component */
1791 block
[0] = last_dc_val
; /* output it (assumes zag[0] = 0) */
1793 /* coefficient buffer must be cleared */
1794 MEMSET(block
+1, 0, zero_need
*sizeof(block
[0]));
1796 /* Section F.2.2.2: decode the AC coefficients */
1797 for (; k
< k_need
; k
++)
1799 s
= huff_decode_ac(&bs
, actbl
);
1806 check_bit_buffer(&bs
, s
);
1807 r
= get_bits(&bs
, s
);
1808 block
[zag
[k
]] = HUFF_EXTEND(r
, s
);
1821 /* In this path we just discard the values */
1824 s
= huff_decode_ac(&bs
, actbl
);
1831 check_bit_buffer(&bs
, s
);
1843 { /* only for Y component */
1844 pf_idct(p_byte
+store_offs
[blkn
], block
, p_jpeg
->qt_idct
[ti
],
1849 if (p_jpeg
->restart_interval
&& --restart
== 0)
1850 { /* if a restart marker is due: */
1851 restart
= p_jpeg
->restart_interval
; /* count again */
1852 search_restart(&bs
); /* align the bitstream */
1853 last_dc_val
= 0; /* reset decoder */
1856 if (pf_progress
!= NULL
)
1857 pf_progress(y
, p_jpeg
->y_mbl
-1); /* notify about decoding progress */
1860 return 0; /* success */
1862 #endif /* !HAVE_LCD_COLOR */
1864 /**************** end JPEG code ********************/
1868 /**************** begin Application ********************/
1871 /************************* Types ***************************/
1875 #ifdef HAVE_LCD_COLOR
1876 unsigned char* bitmap
[3]; /* Y, Cr, Cb */
1879 unsigned char* bitmap
[1]; /* Y only */
1887 /************************* Globals ***************************/
1889 /* decompressed image in the possible sizes (1,2,4,8), wasting the other */
1890 struct t_disp disp
[9];
1892 /* my memory pool (from the mp3 buffer) */
1893 char print
[32]; /* use a common snprintf() buffer */
1894 unsigned char* buf
; /* up to here currently used by image(s) */
1896 /* the remaining free part of the buffer for compressed+uncompressed images */
1897 unsigned char* buf_images
;
1899 ssize_t buf_size
, buf_images_size
;
1900 /* the root of the images, hereafter are decompresed ones */
1901 unsigned char* buf_root
;
1904 int ds
, ds_min
, ds_max
; /* downscaling and limits */
1905 static struct jpeg jpg
; /* too large for stack */
1907 static struct tree_context
*tree
;
1909 /* the current full file name */
1910 static char np_file
[MAX_PATH
];
1911 int curfile
= 0, direction
= DIR_NONE
, entries
= 0;
1913 /* list of the jpeg files */
1915 /* are we using the plugin buffer or the audio buffer? */
1916 bool plug_buf
= false;
1919 /************************* Implementation ***************************/
1921 #ifdef HAVE_LCD_COLOR
1923 * Conversion of full 0-255 range YCrCb to RGB:
1924 * |R| |1.000000 -0.000001 1.402000| |Y'|
1925 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
1926 * |B| |1.000000 1.772000 0.000000| |Pr|
1927 * Scaled (yields s15-bit output):
1928 * |R| |128 0 179| |Y |
1929 * |G| = |128 -43 -91| |Cb - 128|
1930 * |B| |128 227 0| |Cr - 128|
1937 #define YUV_WHITE (255*YFAC)
1938 #define NODITHER_DELTA (127*YFAC)
1939 #define COMPONENT_SHIFT 15
1940 #define MATRIX_SHIFT 7
1942 static inline int clamp_component(int x
)
1944 if ((unsigned)x
> YUV_WHITE
)
1945 x
= x
< 0 ? 0 : YUV_WHITE
;
1949 static inline int clamp_component_bits(int x
, int bits
)
1951 if ((unsigned)x
> (1u << bits
) - 1)
1952 x
= x
< 0 ? 0 : (1 << bits
) - 1;
1956 static inline int component_to_lcd(int x
, int bits
, int delta
)
1958 /* Formula used in core bitmap loader. */
1959 return (((1 << bits
) - 1)*x
+ (x
>> (8 - bits
)) + delta
) >> COMPONENT_SHIFT
;
1962 static inline int lcd_to_component(int x
, int bits
, int delta
)
1964 /* Reasonable, approximate reversal to get a full range back from the
1966 return YUV_WHITE
*x
/ ((1 << bits
) - 1);
1976 int16_t errbuf
[LCD_WIDTH
+2]; /* Error record for line below */
1977 } rgb_err_buffers
[3];
1979 fb_data rgb_linebuf
[LCD_WIDTH
]; /* Line buffer for scrolling when
1980 DITHER_DIFFUSION is set */
1984 int r
, g
, b
; /* Current pixel components in s16.0 */
1985 int inc
; /* Current line increment (-1 or 1) */
1986 int row
; /* Current row in source image */
1987 int col
; /* Current column in source image */
1988 int ce
[3]; /* Errors to apply to current pixel */
1989 struct rgb_err
*e
; /* RED, GRN, BLU */
1990 int epos
; /* Current position in error record */
1993 struct rgb_pixel
*pixel
;
1995 /** round and truncate to lcd depth **/
1996 static fb_data
pixel_to_lcd_colour(void)
1998 struct rgb_pixel
*p
= pixel
;
2001 r
= component_to_lcd(p
->r
, LCD_RED_BITS
, NODITHER_DELTA
);
2002 r
= clamp_component_bits(r
, LCD_RED_BITS
);
2004 g
= component_to_lcd(p
->g
, LCD_GREEN_BITS
, NODITHER_DELTA
);
2005 g
= clamp_component_bits(g
, LCD_GREEN_BITS
);
2007 b
= component_to_lcd(p
->b
, LCD_BLUE_BITS
, NODITHER_DELTA
);
2008 b
= clamp_component_bits(b
, LCD_BLUE_BITS
);
2010 return LCD_RGBPACK_LCD(r
, g
, b
);
2013 /** write a monochrome pixel to the colour LCD **/
2014 static fb_data
pixel_to_lcd_gray(void)
2018 g
= clamp_component(pixel
->g
);
2019 r
= component_to_lcd(g
, LCD_RED_BITS
, NODITHER_DELTA
);
2020 b
= component_to_lcd(g
, LCD_BLUE_BITS
, NODITHER_DELTA
);
2021 g
= component_to_lcd(g
, LCD_GREEN_BITS
, NODITHER_DELTA
);
2023 return LCD_RGBPACK_LCD(r
, g
, b
);
2027 * Bayer ordered dithering - swiped from the core bitmap loader.
2029 static fb_data
pixel_odither_to_lcd(void)
2031 /* canonical ordered dither matrix */
2032 static const unsigned char dither_matrix
[16][16] = {
2033 { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 },
2034 { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 },
2035 { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 },
2036 { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 },
2037 { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 },
2038 { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 },
2039 { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 },
2040 { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 },
2041 { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 },
2042 { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 },
2043 { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 },
2044 { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 },
2045 { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 },
2046 { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 },
2047 { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 },
2048 { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 }
2051 struct rgb_pixel
*p
= pixel
;
2054 delta
= dither_matrix
[p
->col
& 15][p
->row
& 15] << MATRIX_SHIFT
;
2056 r
= component_to_lcd(p
->r
, LCD_RED_BITS
, delta
);
2057 r
= clamp_component_bits(r
, LCD_RED_BITS
);
2059 g
= component_to_lcd(p
->g
, LCD_GREEN_BITS
, delta
);
2060 g
= clamp_component_bits(g
, LCD_GREEN_BITS
);
2062 b
= component_to_lcd(p
->b
, LCD_BLUE_BITS
, delta
);
2063 b
= clamp_component_bits(b
, LCD_BLUE_BITS
);
2067 return LCD_RGBPACK_LCD(r
, g
, b
);
2071 * Floyd/Steinberg dither to lcd depth.
2073 * Apply filter to each component in serpentine pattern. Kernel shown for
2074 * L->R scan. Kernel is reversed for R->L.
2078 static inline void distribute_error(int *ce
, struct rgb_err
*e
,
2079 int err
, int epos
, int inc
)
2081 *ce
= (7*err
>> 4) + e
->errbuf
[epos
+inc
];
2082 e
->errbuf
[epos
+inc
] = err
>> 4;
2083 e
->errbuf
[epos
] += 5*err
>> 4;
2084 e
->errbuf
[epos
-inc
] += 3*err
>> 4;
2087 static fb_data
pixel_fsdither_to_lcd(void)
2089 struct rgb_pixel
*p
= pixel
;
2090 int rc
, gc
, bc
, r
, g
, b
;
2093 /* Full components with error terms */
2094 rc
= p
->r
+ p
->ce
[RED
];
2095 r
= component_to_lcd(rc
, LCD_RED_BITS
, 0);
2096 r
= clamp_component_bits(r
, LCD_RED_BITS
);
2098 gc
= p
->g
+ p
->ce
[GRN
];
2099 g
= component_to_lcd(gc
, LCD_GREEN_BITS
, 0);
2100 g
= clamp_component_bits(g
, LCD_GREEN_BITS
);
2102 bc
= p
->b
+ p
->ce
[BLU
];
2103 b
= component_to_lcd(bc
, LCD_BLUE_BITS
, 0);
2104 b
= clamp_component_bits(b
, LCD_BLUE_BITS
);
2106 /* Get pixel errors */
2107 rc
-= lcd_to_component(r
, LCD_RED_BITS
, 0);
2108 gc
-= lcd_to_component(g
, LCD_GREEN_BITS
, 0);
2109 bc
-= lcd_to_component(b
, LCD_BLUE_BITS
, 0);
2111 /* Spead error to surrounding pixels. */
2116 distribute_error(&p
->ce
[RED
], &p
->e
[RED
], rc
, epos
, inc
);
2117 distribute_error(&p
->ce
[GRN
], &p
->e
[GRN
], gc
, epos
, inc
);
2118 distribute_error(&p
->ce
[BLU
], &p
->e
[BLU
], bc
, epos
, inc
);
2120 /* Pack and return pixel */
2121 return LCD_RGBPACK_LCD(r
, g
, b
);
2124 /* Functions for each output mode, colour then grayscale. */
2125 static fb_data (* const pixel_funcs
[COLOUR_NUM_MODES
][DITHER_NUM_MODES
])(void) =
2127 [COLOURMODE_COLOUR
] =
2129 [DITHER_NONE
] = pixel_to_lcd_colour
,
2130 [DITHER_ORDERED
] = pixel_odither_to_lcd
,
2131 [DITHER_DIFFUSION
] = pixel_fsdither_to_lcd
,
2135 [DITHER_NONE
] = pixel_to_lcd_gray
,
2136 [DITHER_ORDERED
] = pixel_odither_to_lcd
,
2137 [DITHER_DIFFUSION
] = pixel_fsdither_to_lcd
,
2142 * Draw a partial YUV colour bitmap
2144 * Runs serpentine pattern when dithering is DITHER_DIFFUSION, else scan is
2147 void yuv_bitmap_part(unsigned char *src
[3], int csub_x
, int csub_y
,
2148 int src_x
, int src_y
, int stride
,
2149 int x
, int y
, int width
, int height
)
2151 fb_data
*dst
, *dst_end
;
2152 fb_data (*pixel_func
)(void);
2153 struct rgb_pixel px
;
2155 if (x
+ width
> LCD_WIDTH
)
2156 width
= LCD_WIDTH
- x
; /* Clip right */
2158 width
+= x
, x
= 0; /* Clip left */
2160 return; /* nothing left to do */
2162 if (y
+ height
> LCD_HEIGHT
)
2163 height
= LCD_HEIGHT
- y
; /* Clip bottom */
2165 height
+= y
, y
= 0; /* Clip top */
2167 return; /* nothing left to do */
2171 dst
= rb
->lcd_framebuffer
+ LCD_WIDTH
* y
+ x
;
2172 dst_end
= dst
+ LCD_WIDTH
* height
;
2174 if (jpeg_settings
.colour_mode
== COLOURMODE_GRAY
)
2175 csub_y
= 0; /* Ignore Cb, Cr */
2177 pixel_func
= pixel_funcs
[jpeg_settings
.colour_mode
]
2178 [jpeg_settings
.dither_mode
];
2180 if (jpeg_settings
.dither_mode
== DITHER_DIFFUSION
)
2182 /* Reset error terms. */
2183 px
.e
= rgb_err_buffers
;
2184 px
.ce
[RED
] = px
.ce
[GRN
] = px
.ce
[BLU
] = 0;
2185 rb
->memset(px
.e
, 0, 3*sizeof (struct rgb_err
));
2190 fb_data
*dst_row
, *row_end
;
2191 const unsigned char *ysrc
;
2194 if (jpeg_settings
.dither_mode
== DITHER_DIFFUSION
)
2196 /* Use R->L scan on odd lines */
2197 px
.inc
-= (src_y
& 1) << 1;
2201 px
.epos
+= width
- 1;
2208 row_end
= dst_row
+ width
;
2215 dst_row
= row_end
+ width
;
2216 px
.col
= src_x
+ width
- 1;
2219 ysrc
= src
[0] + stride
* src_y
+ px
.col
;
2222 /* Do one row of pixels */
2223 if (csub_y
) /* colour */
2225 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
2226 const unsigned char *usrc
, *vsrc
;
2228 usrc
= src
[1] + (stride
/csub_x
) * (src_y
/csub_y
)
2230 vsrc
= src
[2] + (stride
/csub_x
) * (src_y
/csub_y
)
2232 int xphase
= px
.col
% csub_x
;
2233 int xphase_reset
= px
.inc
* csub_x
;
2234 int y
, v
, u
, rv
, guv
, bu
;
2241 guv
= GUFAC
*u
+ GVFAC
*v
;
2252 *dst_row
= pixel_func();
2255 if (dst_row
== row_end
)
2259 if ((unsigned)xphase
< (unsigned)csub_x
)
2262 /* fetch new chromas */
2268 guv
= GUFAC
*u
+ GVFAC
*v
;
2271 xphase
-= xphase_reset
;
2274 else /* monochrome */
2278 /* Set all components the same for dithering purposes */
2279 px
.g
= px
.r
= px
.b
= YFAC
*(*ysrc
);
2280 *dst_row
= pixel_func();
2284 while (dst_row
!= row_end
);
2290 while (dst
< dst_end
);
2293 #endif /* HAVE_LCD_COLOR */
2296 /* support function for qsort() */
2297 static int compare(const void* p1
, const void* p2
)
2299 return rb
->strcasecmp(*((char **)p1
), *((char **)p2
));
2302 bool jpg_ext(const char ext
[])
2306 if(!rb
->strcasecmp(ext
,".jpg") ||
2307 !rb
->strcasecmp(ext
,".jpe") ||
2308 !rb
->strcasecmp(ext
,".jpeg"))
2314 /*Read directory contents for scrolling. */
2315 void get_pic_list(void)
2318 long int str_len
= 0;
2320 tree
= rb
->tree_get_context();
2322 #if PLUGIN_BUFFER_SIZE >= MIN_MEM
2323 file_pt
= rb
->plugin_get_buffer((size_t *)&buf_size
);
2325 file_pt
= rb
->plugin_get_audio_buffer((size_t *)&buf_size
);
2328 for(i
= 0; i
< tree
->filesindir
; i
++)
2330 if(jpg_ext(rb
->strrchr(&tree
->name_buffer
[str_len
],'.')))
2331 file_pt
[entries
++] = &tree
->name_buffer
[str_len
];
2333 str_len
+= rb
->strlen(&tree
->name_buffer
[str_len
]) + 1;
2336 rb
->qsort(file_pt
, entries
, sizeof(char**), compare
);
2338 /* Remove path and leave only the name.*/
2339 pname
= rb
->strrchr(np_file
,'/');
2342 /* Find Selected File. */
2343 for(i
= 0; i
< entries
; i
++)
2344 if(!rb
->strcmp(file_pt
[i
], pname
))
2348 int change_filename(int direct
)
2353 if(direct
== DIR_PREV
)
2359 curfile
= entries
- 1;
2362 }while(file_pt
[curfile
] == '\0' && count
< entries
);
2363 /* we "erase" the file name if we encounter
2364 * a non-supported file, so skip it now */
2366 else /* DIR_NEXT/DIR_NONE */
2371 if(curfile
== entries
- 1)
2375 }while(file_pt
[curfile
] == '\0' && count
< entries
);
2378 if(count
== entries
&& file_pt
[curfile
] == '\0')
2380 rb
->splash(HZ
, "No supported files");
2381 return PLUGIN_ERROR
;
2383 if(rb
->strlen(tree
->currdir
) > 1)
2385 rb
->strcpy(np_file
, tree
->currdir
);
2386 rb
->strcat(np_file
, "/");
2389 rb
->strcpy(np_file
, tree
->currdir
);
2391 rb
->strcat(np_file
, file_pt
[curfile
]);
2393 return PLUGIN_OTHER
;
2396 /* switch off overlay, for handling SYS_ events */
2397 void cleanup(void *parameter
)
2405 #define VSCROLL (LCD_HEIGHT/8)
2406 #define HSCROLL (LCD_WIDTH/10)
2408 #define ZOOM_IN 100 /* return codes for below function */
2409 #define ZOOM_OUT 101
2411 #ifdef HAVE_LCD_COLOR
2412 bool set_option_grayscale(void)
2414 bool gray
= jpeg_settings
.colour_mode
== COLOURMODE_GRAY
;
2415 rb
->set_bool("Grayscale", &gray
);
2416 jpeg_settings
.colour_mode
= gray
? COLOURMODE_GRAY
: COLOURMODE_COLOUR
;
2420 bool set_option_dithering(void)
2422 static const struct opt_items dithering
[DITHER_NUM_MODES
] = {
2423 [DITHER_NONE
] = { "Off", -1 },
2424 [DITHER_ORDERED
] = { "Ordered", -1 },
2425 [DITHER_DIFFUSION
] = { "Diffusion", -1 },
2428 rb
->set_option("Dithering", &jpeg_settings
.dither_mode
, INT
,
2429 dithering
, DITHER_NUM_MODES
, NULL
);
2433 static void display_options(void)
2435 static const struct menu_item items
[] = {
2436 { "Grayscale", set_option_grayscale
},
2437 { "Dithering", set_option_dithering
},
2440 int m
= menu_init(rb
, items
, ARRAYLEN(items
),
2441 NULL
, NULL
, NULL
, NULL
);
2445 #endif /* HAVE_LCD_COLOR */
2447 int show_menu(void) /* return 1 to quit */
2450 rb
->lcd_set_backdrop(old_backdrop
);
2451 #ifdef HAVE_LCD_COLOR
2452 rb
->lcd_set_foreground(rb
->global_settings
->fg_color
);
2453 rb
->lcd_set_background(rb
->global_settings
->bg_color
);
2455 rb
->lcd_set_foreground(LCD_BLACK
);
2456 rb
->lcd_set_background(LCD_WHITE
);
2465 MIID_TOGGLE_SS_MODE
,
2466 MIID_CHANGE_SS_MODE
,
2467 #if PLUGIN_BUFFER_SIZE >= MIN_MEM
2468 MIID_SHOW_PLAYBACK_MENU
,
2470 #ifdef HAVE_LCD_COLOR
2471 MIID_DISPLAY_OPTIONS
,
2476 static const struct menu_item items
[] = {
2479 [MIID_TOGGLE_SS_MODE
] =
2480 { "Toggle Slideshow Mode", NULL
},
2481 [MIID_CHANGE_SS_MODE
] =
2482 { "Change Slideshow Time", NULL
},
2483 #if PLUGIN_BUFFER_SIZE >= MIN_MEM
2484 [MIID_SHOW_PLAYBACK_MENU
] =
2485 { "Show Playback Menu", NULL
},
2487 #ifdef HAVE_LCD_COLOR
2488 [MIID_DISPLAY_OPTIONS
] =
2489 { "Display Options", NULL
},
2495 static const struct opt_items slideshow
[2] = {
2500 static const struct opt_items timeout
[12] = {
2502 { "2 seconds", -1 },
2503 { "3 seconds", -1 },
2504 { "4 seconds", -1 },
2505 { "5 seconds", -1 },
2506 { "6 seconds", -1 },
2507 { "7 seconds", -1 },
2508 { "8 seconds", -1 },
2509 { "9 seconds", -1 },
2510 { "10 seconds", -1 },
2511 { "15 seconds", -1 },
2512 { "20 seconds", -1 },
2515 m
= menu_init(rb
, items
, sizeof(items
) / sizeof(*items
),
2516 NULL
, NULL
, NULL
, NULL
);
2517 result
=menu_show(m
);
2525 case MIID_TOGGLE_SS_MODE
:
2526 rb
->set_option("Toggle Slideshow", &slideshow_enabled
, INT
,
2527 slideshow
, 2, NULL
);
2529 case MIID_CHANGE_SS_MODE
:
2530 switch (button_timeout
/HZ
)
2532 case 10: result
= 9; break;
2533 case 15: result
= 10; break;
2534 case 20: result
= 11; break;
2535 default: result
= (button_timeout
/HZ
)-1; break;
2537 rb
->set_option("Slideshow Time", &result
, INT
,
2538 timeout
, 12, NULL
);
2541 case 9: button_timeout
= 10*HZ
; break;
2542 case 10: button_timeout
= 15*HZ
; break;
2543 case 11: button_timeout
= 20*HZ
; break;
2544 default: button_timeout
= (result
+1)*HZ
; break;
2547 #if PLUGIN_BUFFER_SIZE >= MIN_MEM
2548 case MIID_SHOW_PLAYBACK_MENU
:
2549 playback_control(rb
);
2552 #ifdef HAVE_LCD_COLOR
2553 case MIID_DISPLAY_OPTIONS
:
2561 #if !defined(SIMULATOR) && !defined(HAVE_FLASH_STORAGE)
2562 /* change ata spindown time based on slideshow time setting */
2563 immediate_ata_off
= false;
2564 rb
->ata_spindown(rb
->global_settings
->disk_spindown
);
2566 if (slideshow_enabled
)
2568 if(button_timeout
/HZ
< 10)
2570 /* slideshow times < 10s keep disk spinning */
2571 rb
->ata_spindown(0);
2573 else if (!rb
->mp3_is_playing())
2575 /* slideshow times > 10s and not playing: ata_off after load */
2576 immediate_ata_off
= true;
2581 rb
->lcd_set_backdrop(NULL
);
2582 rb
->lcd_set_foreground(LCD_WHITE
);
2583 rb
->lcd_set_background(LCD_BLACK
);
2585 rb
->lcd_clear_display();
2589 /* interactively scroll around the image */
2590 int scroll_bmp(struct t_disp
* pdisp
)
2599 if (slideshow_enabled
)
2600 button
= rb
->button_get_w_tmo(button_timeout
);
2601 else button
= rb
->button_get(true);
2603 running_slideshow
= false;
2608 if (!(ds
< ds_max
) && entries
> 0 && jpg
.x_size
<= MAX_X_SIZE
)
2609 return change_filename(DIR_PREV
);
2610 case JPEG_LEFT
| BUTTON_REPEAT
:
2611 move
= MIN(HSCROLL
, pdisp
->x
);
2614 MYXLCD(scroll_right
)(move
); /* scroll right */
2616 #ifdef HAVE_LCD_COLOR
2618 pdisp
->bitmap
, pdisp
->csub_x
, pdisp
->csub_y
,
2619 pdisp
->x
, pdisp
->y
, pdisp
->stride
,
2620 0, MAX(0, (LCD_HEIGHT
-pdisp
->height
)/2), /* x, y */
2621 move
, MIN(LCD_HEIGHT
, pdisp
->height
)); /* w, h */
2623 MYXLCD(gray_bitmap_part
)(
2624 pdisp
->bitmap
[0], pdisp
->x
, pdisp
->y
, pdisp
->stride
,
2625 0, MAX(0, (LCD_HEIGHT
-pdisp
->height
)/2), /* x, y */
2626 move
, MIN(LCD_HEIGHT
, pdisp
->height
)); /* w, h */
2633 if (!(ds
< ds_max
) && entries
> 0 && jpg
.x_size
<= MAX_X_SIZE
)
2634 return change_filename(DIR_NEXT
);
2635 case JPEG_RIGHT
| BUTTON_REPEAT
:
2636 move
= MIN(HSCROLL
, pdisp
->width
- pdisp
->x
- LCD_WIDTH
);
2639 MYXLCD(scroll_left
)(move
); /* scroll left */
2641 #ifdef HAVE_LCD_COLOR
2643 pdisp
->bitmap
, pdisp
->csub_x
, pdisp
->csub_y
,
2644 pdisp
->x
+ LCD_WIDTH
- move
, pdisp
->y
, pdisp
->stride
,
2645 LCD_WIDTH
- move
, MAX(0, (LCD_HEIGHT
-pdisp
->height
)/2), /* x, y */
2646 move
, MIN(LCD_HEIGHT
, pdisp
->height
)); /* w, h */
2648 MYXLCD(gray_bitmap_part
)(
2649 pdisp
->bitmap
[0], pdisp
->x
+ LCD_WIDTH
- move
,
2650 pdisp
->y
, pdisp
->stride
,
2651 LCD_WIDTH
- move
, MAX(0, (LCD_HEIGHT
-pdisp
->height
)/2), /* x, y */
2652 move
, MIN(LCD_HEIGHT
, pdisp
->height
)); /* w, h */
2659 case JPEG_UP
| BUTTON_REPEAT
:
2660 move
= MIN(VSCROLL
, pdisp
->y
);
2663 MYXLCD(scroll_down
)(move
); /* scroll down */
2665 #ifdef HAVE_LCD_COLOR
2666 if (jpeg_settings
.dither_mode
== DITHER_DIFFUSION
)
2668 /* Draw over the band at the top of the last update
2669 caused by lack of error history on line zero. */
2670 move
= MIN(move
+ 1, pdisp
->y
+ pdisp
->height
);
2674 pdisp
->bitmap
, pdisp
->csub_x
, pdisp
->csub_y
,
2675 pdisp
->x
, pdisp
->y
, pdisp
->stride
,
2676 MAX(0, (LCD_WIDTH
-pdisp
->width
)/2), 0, /* x, y */
2677 MIN(LCD_WIDTH
, pdisp
->width
), move
); /* w, h */
2679 MYXLCD(gray_bitmap_part
)(
2680 pdisp
->bitmap
[0], pdisp
->x
, pdisp
->y
, pdisp
->stride
,
2681 MAX(0, (LCD_WIDTH
-pdisp
->width
)/2), 0, /* x, y */
2682 MIN(LCD_WIDTH
, pdisp
->width
), move
); /* w, h */
2689 case JPEG_DOWN
| BUTTON_REPEAT
:
2690 move
= MIN(VSCROLL
, pdisp
->height
- pdisp
->y
- LCD_HEIGHT
);
2693 MYXLCD(scroll_up
)(move
); /* scroll up */
2695 #ifdef HAVE_LCD_COLOR
2696 if (jpeg_settings
.dither_mode
== DITHER_DIFFUSION
)
2698 /* Save the line that was on the last line of the display
2699 and draw one extra line above then recover the line with
2700 image data that had an error history when it was drawn.
2704 rb
->lcd_framebuffer
+ (LCD_HEIGHT
- move
)*LCD_WIDTH
,
2705 LCD_WIDTH
*sizeof (fb_data
));
2709 pdisp
->bitmap
, pdisp
->csub_x
, pdisp
->csub_y
, 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 */
2714 if (jpeg_settings
.dither_mode
== DITHER_DIFFUSION
)
2716 /* Cover the first row drawn with previous image data. */
2717 MEMCPY(rb
->lcd_framebuffer
+ (LCD_HEIGHT
- move
)*LCD_WIDTH
,
2719 LCD_WIDTH
*sizeof (fb_data
));
2723 MYXLCD(gray_bitmap_part
)(
2724 pdisp
->bitmap
[0], pdisp
->x
,
2725 pdisp
->y
+ LCD_HEIGHT
- move
, pdisp
->stride
,
2726 MAX(0, (LCD_WIDTH
-pdisp
->width
)/2), LCD_HEIGHT
- move
, /* x, y */
2727 MIN(LCD_WIDTH
, pdisp
->width
), move
); /* w, h */
2733 if (!slideshow_enabled
)
2735 running_slideshow
= true;
2737 return change_filename(DIR_NEXT
);
2740 #ifdef JPEG_SLIDE_SHOW
2741 case JPEG_SLIDE_SHOW
:
2742 slideshow_enabled
= !slideshow_enabled
;
2743 running_slideshow
= slideshow_enabled
;
2747 #ifdef JPEG_NEXT_REPEAT
2748 case JPEG_NEXT_REPEAT
:
2752 return change_filename(DIR_NEXT
);
2755 #ifdef JPEG_PREVIOUS_REPEAT
2756 case JPEG_PREVIOUS_REPEAT
:
2760 return change_filename(DIR_PREV
);
2764 #ifdef JPEG_ZOOM_PRE
2765 if (lastbutton
!= JPEG_ZOOM_PRE
)
2772 #ifdef JPEG_ZOOM_PRE
2773 if (lastbutton
!= JPEG_ZOOM_PRE
)
2783 gray_show(false); /* switch off grayscale overlay */
2785 if (show_menu() == 1)
2789 gray_show(true); /* switch on grayscale overlay */
2792 pdisp
->bitmap
, pdisp
->csub_x
, pdisp
->csub_y
,
2793 pdisp
->x
, pdisp
->y
, pdisp
->stride
,
2794 MAX(0, (LCD_WIDTH
- pdisp
->width
) / 2),
2795 MAX(0, (LCD_HEIGHT
- pdisp
->height
) / 2),
2796 MIN(LCD_WIDTH
, pdisp
->width
),
2797 MIN(LCD_HEIGHT
, pdisp
->height
));
2802 if (rb
->default_event_handler_ex(button
, cleanup
, NULL
)
2803 == SYS_USB_CONNECTED
)
2804 return PLUGIN_USB_CONNECTED
;
2809 if (button
!= BUTTON_NONE
)
2810 lastbutton
= button
;
2811 } /* while (true) */
2814 /********************* main function *************************/
2816 /* callback updating a progress meter while JPEG decoding */
2817 void cb_progess(int current
, int total
)
2819 rb
->yield(); /* be nice to the other threads */
2820 if(!running_slideshow
)
2822 rb
->gui_scrollbar_draw(rb
->screens
[SCREEN_MAIN
],0, LCD_HEIGHT
-8, LCD_WIDTH
, 8, total
, 0,
2823 current
, HORIZONTAL
);
2824 rb
->lcd_update_rect(0, LCD_HEIGHT
-8, LCD_WIDTH
, 8);
2829 /* in slideshow mode, keep gui interference to a minimum */
2830 rb
->gui_scrollbar_draw(rb
->screens
[SCREEN_MAIN
],0, LCD_HEIGHT
-4, LCD_WIDTH
, 4, total
, 0,
2831 current
, HORIZONTAL
);
2832 rb
->lcd_update_rect(0, LCD_HEIGHT
-4, LCD_WIDTH
, 4);
2837 int jpegmem(struct jpeg
*p_jpg
, int ds
)
2841 size
= (p_jpg
->x_phys
/ds
/p_jpg
->subsample_x
[0])
2842 * (p_jpg
->y_phys
/ds
/p_jpg
->subsample_y
[0]);
2843 #ifdef HAVE_LCD_COLOR
2844 if (p_jpg
->blocks
> 1) /* colour, add requirements for chroma */
2846 size
+= (p_jpg
->x_phys
/ds
/p_jpg
->subsample_x
[1])
2847 * (p_jpg
->y_phys
/ds
/p_jpg
->subsample_y
[1]);
2848 size
+= (p_jpg
->x_phys
/ds
/p_jpg
->subsample_x
[2])
2849 * (p_jpg
->y_phys
/ds
/p_jpg
->subsample_y
[2]);
2855 /* how far can we zoom in without running out of memory */
2856 int min_downscale(struct jpeg
*p_jpg
, int bufsize
)
2860 if (jpegmem(p_jpg
, 8) > bufsize
)
2861 return 0; /* error, too large, even 1:8 doesn't fit */
2863 while (downscale
> 1 && jpegmem(p_jpg
, downscale
/2) <= bufsize
)
2870 /* how far can we zoom out, to fit image into the LCD */
2871 int max_downscale(struct jpeg
*p_jpg
)
2875 while (downscale
< 8 && (p_jpg
->x_size
> LCD_WIDTH
*downscale
2876 || p_jpg
->y_size
> LCD_HEIGHT
*downscale
))
2885 /* return decoded or cached image */
2886 struct t_disp
* get_image(struct jpeg
* p_jpg
, int ds
)
2888 int w
, h
; /* used to center output */
2889 int size
; /* decompressed image size */
2890 long time
; /* measured ticks */
2893 struct t_disp
* p_disp
= &disp
[ds
]; /* short cut */
2895 if (p_disp
->bitmap
[0] != NULL
)
2897 return p_disp
; /* we still have it */
2900 /* assign image buffer */
2902 /* physical size needed for decoding */
2903 size
= jpegmem(p_jpg
, ds
);
2904 if (buf_size
<= size
)
2905 { /* have to discard the current */
2907 for (i
=1; i
<=8; i
++)
2908 disp
[i
].bitmap
[0] = NULL
; /* invalidate all bitmaps */
2909 buf
= buf_root
; /* start again from the beginning of the buffer */
2910 buf_size
= root_size
;
2913 #ifdef HAVE_LCD_COLOR
2914 if (p_jpg
->blocks
> 1) /* colour jpeg */
2918 for (i
= 1; i
< 3; i
++)
2920 size
= (p_jpg
->x_phys
/ ds
/ p_jpg
->subsample_x
[i
])
2921 * (p_jpg
->y_phys
/ ds
/ p_jpg
->subsample_y
[i
]);
2922 p_disp
->bitmap
[i
] = buf
;
2926 p_disp
->csub_x
= p_jpg
->subsample_x
[1];
2927 p_disp
->csub_y
= p_jpg
->subsample_y
[1];
2931 p_disp
->csub_x
= p_disp
->csub_y
= 0;
2932 p_disp
->bitmap
[1] = p_disp
->bitmap
[2] = buf
;
2935 /* size may be less when decoded (if height is not block aligned) */
2936 size
= (p_jpg
->x_phys
/ds
) * (p_jpg
->y_size
/ ds
);
2937 p_disp
->bitmap
[0] = buf
;
2941 if(!running_slideshow
)
2943 rb
->snprintf(print
, sizeof(print
), "decoding %d*%d",
2944 p_jpg
->x_size
/ds
, p_jpg
->y_size
/ds
);
2945 rb
->lcd_puts(0, 3, print
);
2949 /* update image properties */
2950 p_disp
->width
= p_jpg
->x_size
/ ds
;
2951 p_disp
->stride
= p_jpg
->x_phys
/ ds
; /* use physical size for stride */
2952 p_disp
->height
= p_jpg
->y_size
/ ds
;
2954 /* the actual decoding */
2955 time
= *rb
->current_tick
;
2956 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
2957 rb
->cpu_boost(true);
2958 status
= jpeg_decode(p_jpg
, p_disp
->bitmap
, ds
, cb_progess
);
2959 rb
->cpu_boost(false);
2961 status
= jpeg_decode(p_jpg
, p_disp
->bitmap
, ds
, cb_progess
);
2965 rb
->splash(HZ
, "decode error %d", status
);
2966 file_pt
[curfile
] = '\0';
2969 time
= *rb
->current_tick
- time
;
2971 if(!running_slideshow
)
2973 rb
->snprintf(print
, sizeof(print
), " %ld.%02ld sec ", time
/HZ
, time
%HZ
);
2974 rb
->lcd_getstringsize(print
, &w
, &h
); /* centered in progress bar */
2975 rb
->lcd_putsxy((LCD_WIDTH
- w
)/2, LCD_HEIGHT
- h
, print
);
2983 /* set the view to the given center point, limit if necessary */
2984 void set_view (struct t_disp
* p_disp
, int cx
, int cy
)
2988 /* plain center to available width/height */
2989 x
= cx
- MIN(LCD_WIDTH
, p_disp
->width
) / 2;
2990 y
= cy
- MIN(LCD_HEIGHT
, p_disp
->height
) / 2;
2992 /* limit against upper image size */
2993 x
= MIN(p_disp
->width
- LCD_WIDTH
, x
);
2994 y
= MIN(p_disp
->height
- LCD_HEIGHT
, y
);
2996 /* limit against negative side */
3000 p_disp
->x
= x
; /* set the values */
3005 /* calculate the view center based on the bitmap position */
3006 void get_view(struct t_disp
* p_disp
, int* p_cx
, int* p_cy
)
3008 *p_cx
= p_disp
->x
+ MIN(LCD_WIDTH
, p_disp
->width
) / 2;
3009 *p_cy
= p_disp
->y
+ MIN(LCD_HEIGHT
, p_disp
->height
) / 2;
3013 /* load, decode, display the image */
3014 int load_and_show(char* filename
)
3018 unsigned char* buf_jpeg
; /* compressed JPEG image */
3020 struct t_disp
* p_disp
; /* currenly displayed image */
3021 int cx
, cy
; /* view center */
3023 fd
= rb
->open(filename
, O_RDONLY
);
3026 rb
->snprintf(print
,sizeof(print
),"err opening %s:%d",filename
,fd
);
3027 rb
->splash(HZ
, print
);
3028 return PLUGIN_ERROR
;
3030 filesize
= rb
->filesize(fd
);
3031 rb
->memset(&disp
, 0, sizeof(disp
));
3033 buf
= buf_images
+ filesize
;
3034 buf_size
= buf_images_size
- filesize
;
3035 /* allocate JPEG buffer */
3036 buf_jpeg
= buf_images
;
3038 buf_root
= buf
; /* we can start the decompressed images behind it */
3039 root_size
= buf_size
;
3043 #if PLUGIN_BUFFER_SIZE >= MIN_MEM
3047 rb
->lcd_setfont(FONT_SYSFIXED
);
3048 rb
->lcd_clear_display();
3049 rb
->snprintf(print
,sizeof(print
),"%s:",rb
->strrchr(filename
,'/')+1);
3050 rb
->lcd_puts(0,0,print
);
3051 rb
->lcd_puts(0,1,"Not enough plugin memory!");
3052 rb
->lcd_puts(0,2,"Zoom In: Stop playback.");
3054 rb
->lcd_puts(0,3,"Left/Right: Skip File.");
3055 rb
->lcd_puts(0,4,"Off: Quit.");
3057 rb
->lcd_setfont(FONT_UI
);
3059 rb
->button_clear_queue();
3063 int button
= rb
->button_get(true);
3068 buf_images
= rb
->plugin_get_audio_buffer(
3069 (size_t *)&buf_images_size
);
3070 /*try again this file, now using the audio buffer */
3071 return PLUGIN_OTHER
;
3081 rb
->lcd_clear_display();
3082 return change_filename(DIR_PREV
);
3089 rb
->lcd_clear_display();
3090 return change_filename(DIR_NEXT
);
3094 if(rb
->default_event_handler_ex(button
, cleanup
, NULL
)
3095 == SYS_USB_CONNECTED
)
3096 return PLUGIN_USB_CONNECTED
;
3104 rb
->splash(HZ
, "Out of Memory");
3106 return PLUGIN_ERROR
;
3110 if(!running_slideshow
)
3113 rb
->lcd_set_foreground(LCD_WHITE
);
3114 rb
->lcd_set_background(LCD_BLACK
);
3115 rb
->lcd_set_backdrop(NULL
);
3118 rb
->lcd_clear_display();
3119 rb
->snprintf(print
, sizeof(print
), "%s:", rb
->strrchr(filename
,'/')+1);
3120 rb
->lcd_puts(0, 0, print
);
3123 rb
->snprintf(print
, sizeof(print
), "loading %d bytes", filesize
);
3124 rb
->lcd_puts(0, 1, print
);
3128 rb
->read(fd
, buf_jpeg
, filesize
);
3131 if(!running_slideshow
)
3133 rb
->snprintf(print
, sizeof(print
), "decoding markers");
3134 rb
->lcd_puts(0, 2, print
);
3138 else if(immediate_ata_off
)
3140 /* running slideshow and time is long enough: power down disk */
3145 rb
->memset(&jpg
, 0, sizeof(jpg
)); /* clear info struct */
3146 /* process markers, unstuffing */
3147 status
= process_markers(buf_jpeg
, filesize
, &jpg
);
3149 if (status
< 0 || (status
& (DQT
| SOF0
)) != (DQT
| SOF0
))
3150 { /* bad format or minimum components not contained */
3151 rb
->splash(HZ
, "unsupported %d", status
);
3152 file_pt
[curfile
] = '\0';
3153 return change_filename(direction
);
3156 if (!(status
& DHT
)) /* if no Huffman table present: */
3157 default_huff_tbl(&jpg
); /* use default */
3158 build_lut(&jpg
); /* derive Huffman and other lookup-tables */
3160 if(!running_slideshow
)
3162 rb
->snprintf(print
, sizeof(print
), "image %dx%d", jpg
.x_size
, jpg
.y_size
);
3163 rb
->lcd_puts(0, 2, print
);
3166 ds_max
= max_downscale(&jpg
); /* check display constraint */
3167 ds_min
= min_downscale(&jpg
, buf_size
); /* check memory constraint */
3170 rb
->splash(HZ
, "too large");
3171 file_pt
[curfile
] = '\0';
3172 return change_filename(direction
);
3175 ds
= ds_max
; /* initials setting */
3176 cx
= jpg
.x_size
/ds
/2; /* center the view */
3177 cy
= jpg
.y_size
/ds
/2;
3179 do /* loop the image prepare and decoding when zoomed */
3181 p_disp
= get_image(&jpg
, ds
); /* decode or fetch from cache */
3183 return change_filename(direction
);
3185 set_view(p_disp
, cx
, cy
);
3187 if(!running_slideshow
)
3189 rb
->snprintf(print
, sizeof(print
), "showing %dx%d",
3190 p_disp
->width
, p_disp
->height
);
3191 rb
->lcd_puts(0, 3, print
);
3194 MYLCD(clear_display
)();
3195 #ifdef HAVE_LCD_COLOR
3197 p_disp
->bitmap
, p_disp
->csub_x
, p_disp
->csub_y
,
3198 p_disp
->x
, p_disp
->y
, p_disp
->stride
,
3199 MAX(0, (LCD_WIDTH
- p_disp
->width
) / 2),
3200 MAX(0, (LCD_HEIGHT
- p_disp
->height
) / 2),
3201 MIN(LCD_WIDTH
, p_disp
->width
),
3202 MIN(LCD_HEIGHT
, p_disp
->height
));
3204 MYXLCD(gray_bitmap_part
)(
3205 p_disp
->bitmap
[0], p_disp
->x
, p_disp
->y
, p_disp
->stride
,
3206 MAX(0, (LCD_WIDTH
- p_disp
->width
) / 2),
3207 MAX(0, (LCD_HEIGHT
- p_disp
->height
) / 2),
3208 MIN(LCD_WIDTH
, p_disp
->width
),
3209 MIN(LCD_HEIGHT
, p_disp
->height
));
3214 gray_show(true); /* switch on grayscale overlay */
3217 /* drawing is now finished, play around with scrolling
3218 * until you press OFF or connect USB
3222 status
= scroll_bmp(p_disp
);
3223 if (status
== ZOOM_IN
)
3227 ds
/= 2; /* reduce downscaling to zoom in */
3228 get_view(p_disp
, &cx
, &cy
);
3229 cx
*= 2; /* prepare the position in the new image */
3236 if (status
== ZOOM_OUT
)
3240 ds
*= 2; /* increase downscaling to zoom out */
3241 get_view(p_disp
, &cx
, &cy
);
3242 cx
/= 2; /* prepare the position in the new image */
3252 gray_show(false); /* switch off overlay */
3254 rb
->lcd_clear_display();
3256 while (status
!= PLUGIN_OK
&& status
!= PLUGIN_USB_CONNECTED
3257 && status
!= PLUGIN_OTHER
);
3264 /******************** Plugin entry point *********************/
3266 enum plugin_status
plugin_start(struct plugin_api
* api
, void* parameter
)
3273 long graysize
; /* helper */
3276 old_backdrop
= rb
->lcd_get_backdrop();
3279 if(!parameter
) return PLUGIN_ERROR
;
3281 rb
->strcpy(np_file
, parameter
);
3284 if(!entries
) return PLUGIN_ERROR
;
3286 #if (PLUGIN_BUFFER_SIZE >= MIN_MEM) && !defined(SIMULATOR)
3287 if(rb
->audio_status())
3289 buf
= rb
->plugin_get_buffer((size_t *)&buf_size
) +
3290 (entries
* sizeof(char**));
3291 buf_size
-= (entries
* sizeof(char**));
3295 buf
= rb
->plugin_get_audio_buffer((size_t *)&buf_size
);
3297 buf
= rb
->plugin_get_audio_buffer(&buf_size
) +
3298 (entries
* sizeof(char**));
3299 buf_size
-= (entries
* sizeof(char**));
3303 /* initialize the grayscale buffer: 32 bitplanes for 33 shades of gray. */
3304 grayscales
= gray_init(rb
, buf
, buf_size
, false, LCD_WIDTH
, LCD_HEIGHT
,
3305 32, 2<<8, &graysize
) + 1;
3307 buf_size
-= graysize
;
3308 if (grayscales
< 33 || buf_size
<= 0)
3310 rb
->splash(HZ
, "gray buf error");
3311 return PLUGIN_ERROR
;
3317 #ifdef HAVE_LCD_COLOR
3318 /* should be ok to just load settings since a parameter is present
3319 here and the drive should be spinning */
3320 configfile_init(rb
);
3321 configfile_load(JPEG_CONFIGFILE
, jpeg_config
,
3322 ARRAYLEN(jpeg_config
), JPEG_SETTINGS_MINVERSION
);
3323 old_settings
= jpeg_settings
;
3326 buf_images
= buf
; buf_images_size
= buf_size
;
3328 /* Turn off backlight timeout */
3329 backlight_force_on(rb
); /* backlight control in lib/helper.c */
3333 condition
= load_and_show(np_file
);
3334 }while (condition
!= PLUGIN_OK
&& condition
!= PLUGIN_USB_CONNECTED
3335 && condition
!= PLUGIN_ERROR
);
3337 #ifdef HAVE_LCD_COLOR
3338 if (rb
->memcmp(&jpeg_settings
, &old_settings
, sizeof (jpeg_settings
)))
3340 /* Just in case drive has to spin, keep it from looking locked */
3341 rb
->splash(0, "Saving Settings");
3342 configfile_save(JPEG_CONFIGFILE
, jpeg_config
,
3343 ARRAYLEN(jpeg_config
), JPEG_SETTINGS_VERSION
);
3347 #if !defined(SIMULATOR) && !defined(HAVE_FLASH_STORAGE)
3348 /* set back ata spindown time in case we changed it */
3349 rb
->ata_spindown(rb
->global_settings
->disk_spindown
);
3352 /* Turn on backlight timeout (revert to settings) */
3353 backlight_use_settings(rb
); /* backlight control in lib/helper.c */
3356 gray_release(); /* deinitialize */
3362 #endif /* HAVE_LCD_BITMAP */