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