summaryrefslogtreecommitdiff
path: root/apps/plugins/jpeg
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/jpeg')
-rw-r--r--apps/plugins/jpeg/SOURCES5
-rw-r--r--apps/plugins/jpeg/jpeg.c1218
-rw-r--r--apps/plugins/jpeg/jpeg.h340
-rw-r--r--apps/plugins/jpeg/jpeg.make21
-rw-r--r--apps/plugins/jpeg/jpeg_decoder.c1538
-rw-r--r--apps/plugins/jpeg/jpeg_decoder.h76
-rw-r--r--apps/plugins/jpeg/yuv2rgb.c407
-rw-r--r--apps/plugins/jpeg/yuv2rgb.h51
8 files changed, 0 insertions, 3656 deletions
diff --git a/apps/plugins/jpeg/SOURCES b/apps/plugins/jpeg/SOURCES
deleted file mode 100644
index c3524001e2..0000000000
--- a/apps/plugins/jpeg/SOURCES
+++ /dev/null
@@ -1,5 +0,0 @@
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
deleted file mode 100644
index 4a61f13e51..0000000000
--- a/apps/plugins/jpeg/jpeg.c
+++ /dev/null
@@ -1,1218 +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 <lib/playback_control.h>
30#include <lib/helper.h>
31#include <lib/configfile.h>
32
33#include <lib/grey.h>
34#include <lib/xlcd.h>
35
36#include "jpeg.h"
37#include "jpeg_decoder.h"
38
39PLUGIN_HEADER
40
41#ifdef HAVE_LCD_COLOR
42#include "yuv2rgb.h"
43#endif
44
45/* different graphics libraries */
46#if LCD_DEPTH < 8
47#define USEGSLIB
48GREY_INFO_STRUCT
49#define MYLCD(fn) grey_ub_ ## fn
50#define MYLCD_UPDATE()
51#define MYXLCD(fn) grey_ub_ ## fn
52#else
53#define MYLCD(fn) rb->lcd_ ## fn
54#define MYLCD_UPDATE() rb->lcd_update();
55#define MYXLCD(fn) xlcd_ ## fn
56#endif
57
58/* Min memory allowing us to use the plugin buffer
59 * and thus not stopping the music
60 * *Very* rough estimation:
61 * Max 10 000 dir entries * 4bytes/entry (char **) = 40000 bytes
62 * + 20k code size = 60 000
63 * + 50k min for jpeg = 120 000
64 */
65#define MIN_MEM 120000
66
67/* Headings */
68#define DIR_PREV 1
69#define DIR_NEXT -1
70#define DIR_NONE 0
71
72#define PLUGIN_OTHER 10 /* State code for output with return. */
73#define PLUGIN_ABORT 11
74#define PLUGIN_OUTOFMEM 12
75
76/******************************* Globals ***********************************/
77
78static int slideshow_enabled = false; /* run slideshow */
79static int running_slideshow = false; /* loading image because of slideshw */
80#ifndef SIMULATOR
81static int immediate_ata_off = false; /* power down disk after loading */
82#endif
83
84#ifdef HAVE_LCD_COLOR
85fb_data rgb_linebuf[LCD_WIDTH]; /* Line buffer for scrolling when
86 DITHER_DIFFUSION is set */
87#endif
88
89
90/* Persistent configuration */
91#define JPEG_CONFIGFILE "jpeg.cfg"
92#define JPEG_SETTINGS_MINVERSION 1
93#define JPEG_SETTINGS_VERSION 2
94
95/* Slideshow times */
96#define SS_MIN_TIMEOUT 1
97#define SS_MAX_TIMEOUT 20
98#define SS_DEFAULT_TIMEOUT 5
99
100struct jpeg_settings
101{
102#ifdef HAVE_LCD_COLOR
103 int colour_mode;
104 int dither_mode;
105#endif
106 int ss_timeout;
107};
108
109static struct jpeg_settings jpeg_settings =
110{
111#ifdef HAVE_LCD_COLOR
112 COLOURMODE_COLOUR,
113 DITHER_NONE,
114#endif
115 SS_DEFAULT_TIMEOUT
116};
117static struct jpeg_settings old_settings;
118
119static struct configdata jpeg_config[] =
120{
121#ifdef HAVE_LCD_COLOR
122 { TYPE_ENUM, 0, COLOUR_NUM_MODES, { .int_p = &jpeg_settings.colour_mode },
123 "Colour Mode", (char *[]){ "Colour", "Grayscale" } },
124 { TYPE_ENUM, 0, DITHER_NUM_MODES, { .int_p = &jpeg_settings.dither_mode },
125 "Dither Mode", (char *[]){ "None", "Ordered", "Diffusion" } },
126#endif
127 { TYPE_INT, SS_MIN_TIMEOUT, SS_MAX_TIMEOUT,
128 { .int_p = &jpeg_settings.ss_timeout }, "Slideshow Time", NULL },
129};
130
131#if LCD_DEPTH > 1
132static fb_data* old_backdrop;
133#endif
134
135/**************** begin Application ********************/
136
137
138/************************* Types ***************************/
139
140struct t_disp
141{
142#ifdef HAVE_LCD_COLOR
143 unsigned char* bitmap[3]; /* Y, Cr, Cb */
144 int csub_x, csub_y;
145#else
146 unsigned char* bitmap[1]; /* Y only */
147#endif
148 int width;
149 int height;
150 int stride;
151 int x, y;
152};
153
154/************************* Globals ***************************/
155
156/* decompressed image in the possible sizes (1,2,4,8), wasting the other */
157static struct t_disp disp[9];
158
159/* my memory pool (from the mp3 buffer) */
160static char print[32]; /* use a common snprintf() buffer */
161/* the remaining free part of the buffer for compressed+uncompressed images */
162static unsigned char* buf;
163static ssize_t buf_size;
164
165/* the root of the images, hereafter are decompresed ones */
166static unsigned char* buf_root;
167static int root_size;
168
169/* up to here currently used by image(s) */
170static unsigned char* buf_images;
171static ssize_t buf_images_size;
172
173static int ds, ds_min, ds_max; /* downscaling and limits */
174static struct jpeg jpg; /* too large for stack */
175
176static struct tree_context *tree;
177
178/* the current full file name */
179static char np_file[MAX_PATH];
180static int curfile = 0, direction = DIR_NONE, entries = 0;
181
182/* list of the jpeg files */
183static char **file_pt;
184#if PLUGIN_BUFFER_SIZE >= MIN_MEM
185/* are we using the plugin buffer or the audio buffer? */
186static bool plug_buf = true;
187#endif
188
189
190/************************* Implementation ***************************/
191
192bool jpg_ext(const char ext[])
193{
194 if(!ext)
195 return false;
196 if(!rb->strcasecmp(ext,".jpg") ||
197 !rb->strcasecmp(ext,".jpe") ||
198 !rb->strcasecmp(ext,".jpeg"))
199 return true;
200 else
201 return false;
202}
203
204/*Read directory contents for scrolling. */
205void get_pic_list(void)
206{
207 int i;
208 struct entry *dircache;
209 char *pname;
210 tree = rb->tree_get_context();
211 dircache = tree->dircache;
212
213 file_pt = (char **) buf;
214
215 /* Remove path and leave only the name.*/
216 pname = rb->strrchr(np_file,'/');
217 pname++;
218
219 for (i = 0; i < tree->filesindir; i++)
220 {
221 if (!(dircache[i].attr & ATTR_DIRECTORY)
222 && jpg_ext(rb->strrchr(dircache[i].name,'.')))
223 {
224 file_pt[entries] = dircache[i].name;
225 /* Set Selected File. */
226 if (!rb->strcmp(file_pt[entries], pname))
227 curfile = entries;
228 entries++;
229 }
230 }
231
232 buf += (entries * sizeof(char**));
233 buf_size -= (entries * sizeof(char**));
234}
235
236int change_filename(int direct)
237{
238 bool file_erased = (file_pt[curfile] == NULL);
239 direction = direct;
240
241 curfile += (direct == DIR_PREV? entries - 1: 1);
242 if (curfile >= entries)
243 curfile -= entries;
244
245 if (file_erased)
246 {
247 /* remove 'erased' file names from list. */
248 int count, i;
249 for (count = i = 0; i < entries; i++)
250 {
251 if (curfile == i)
252 curfile = count;
253 if (file_pt[i] != NULL)
254 file_pt[count++] = file_pt[i];
255 }
256 entries = count;
257 }
258
259 if (entries == 0)
260 {
261 rb->splash(HZ, "No supported files");
262 return PLUGIN_ERROR;
263 }
264
265 if (rb->strlen(tree->currdir) > 1)
266 {
267 rb->strcpy(np_file, tree->currdir);
268 rb->strcat(np_file, "/");
269 }
270 else
271 rb->strcpy(np_file, tree->currdir);
272
273 rb->strcat(np_file, file_pt[curfile]);
274
275 return PLUGIN_OTHER;
276}
277
278/* switch off overlay, for handling SYS_ events */
279void cleanup(void *parameter)
280{
281 (void)parameter;
282#ifdef USEGSLIB
283 grey_show(false);
284#endif
285}
286
287#define VSCROLL (LCD_HEIGHT/8)
288#define HSCROLL (LCD_WIDTH/10)
289
290#define ZOOM_IN 100 /* return codes for below function */
291#define ZOOM_OUT 101
292
293#ifdef HAVE_LCD_COLOR
294bool set_option_grayscale(void)
295{
296 bool gray = jpeg_settings.colour_mode == COLOURMODE_GRAY;
297 rb->set_bool("Grayscale", &gray);
298 jpeg_settings.colour_mode = gray ? COLOURMODE_GRAY : COLOURMODE_COLOUR;
299 return false;
300}
301
302bool set_option_dithering(void)
303{
304 static const struct opt_items dithering[DITHER_NUM_MODES] = {
305 [DITHER_NONE] = { "Off", -1 },
306 [DITHER_ORDERED] = { "Ordered", -1 },
307 [DITHER_DIFFUSION] = { "Diffusion", -1 },
308 };
309
310 rb->set_option("Dithering", &jpeg_settings.dither_mode, INT,
311 dithering, DITHER_NUM_MODES, NULL);
312 return false;
313}
314
315MENUITEM_FUNCTION(grayscale_item, 0, "Greyscale",
316 set_option_grayscale, NULL, NULL, Icon_NOICON);
317MENUITEM_FUNCTION(dithering_item, 0, "Dithering",
318 set_option_dithering, NULL, NULL, Icon_NOICON);
319MAKE_MENU(display_menu, "Display Options", NULL, Icon_NOICON,
320 &grayscale_item, &dithering_item);
321
322static void display_options(void)
323{
324 rb->do_menu(&display_menu, NULL, NULL, false);
325}
326#endif /* HAVE_LCD_COLOR */
327
328int show_menu(void) /* return 1 to quit */
329{
330#if LCD_DEPTH > 1
331 rb->lcd_set_backdrop(old_backdrop);
332#ifdef HAVE_LCD_COLOR
333 rb->lcd_set_foreground(rb->global_settings->fg_color);
334 rb->lcd_set_background(rb->global_settings->bg_color);
335#else
336 rb->lcd_set_foreground(LCD_BLACK);
337 rb->lcd_set_background(LCD_WHITE);
338#endif
339#endif
340 int result;
341
342 enum menu_id
343 {
344 MIID_RETURN = 0,
345 MIID_TOGGLE_SS_MODE,
346 MIID_CHANGE_SS_MODE,
347#if PLUGIN_BUFFER_SIZE >= MIN_MEM
348 MIID_SHOW_PLAYBACK_MENU,
349#endif
350#ifdef HAVE_LCD_COLOR
351 MIID_DISPLAY_OPTIONS,
352#endif
353 MIID_QUIT,
354 };
355
356 MENUITEM_STRINGLIST(menu, "Jpeg Menu", NULL,
357 "Return", "Toggle Slideshow Mode",
358 "Change Slideshow Time",
359#if PLUGIN_BUFFER_SIZE >= MIN_MEM
360 "Show Playback Menu",
361#endif
362#ifdef HAVE_LCD_COLOR
363 "Display Options",
364#endif
365 "Quit");
366
367 static const struct opt_items slideshow[2] = {
368 { "Disable", -1 },
369 { "Enable", -1 },
370 };
371
372 result=rb->do_menu(&menu, NULL, NULL, false);
373
374 switch (result)
375 {
376 case MIID_RETURN:
377 break;
378 case MIID_TOGGLE_SS_MODE:
379 rb->set_option("Toggle Slideshow", &slideshow_enabled, INT,
380 slideshow , 2, NULL);
381 break;
382 case MIID_CHANGE_SS_MODE:
383 rb->set_int("Slideshow Time", "s", UNIT_SEC,
384 &jpeg_settings.ss_timeout, NULL, 1,
385 SS_MIN_TIMEOUT, SS_MAX_TIMEOUT, NULL);
386 break;
387
388#if PLUGIN_BUFFER_SIZE >= MIN_MEM
389 case MIID_SHOW_PLAYBACK_MENU:
390 if (plug_buf)
391 {
392 playback_control(NULL);
393 }
394 else
395 {
396 rb->splash(HZ, "Cannot restart playback");
397 }
398 break;
399#endif
400#ifdef HAVE_LCD_COLOR
401 case MIID_DISPLAY_OPTIONS:
402 display_options();
403 break;
404#endif
405 case MIID_QUIT:
406 return 1;
407 break;
408 }
409
410#if !defined(SIMULATOR) && defined(HAVE_DISK_STORAGE)
411 /* change ata spindown time based on slideshow time setting */
412 immediate_ata_off = false;
413 rb->storage_spindown(rb->global_settings->disk_spindown);
414
415 if (slideshow_enabled)
416 {
417 if(jpeg_settings.ss_timeout < 10)
418 {
419 /* slideshow times < 10s keep disk spinning */
420 rb->storage_spindown(0);
421 }
422 else if (!rb->mp3_is_playing())
423 {
424 /* slideshow times > 10s and not playing: ata_off after load */
425 immediate_ata_off = true;
426 }
427 }
428#endif
429#if LCD_DEPTH > 1
430 rb->lcd_set_backdrop(NULL);
431 rb->lcd_set_foreground(LCD_WHITE);
432 rb->lcd_set_background(LCD_BLACK);
433#endif
434 rb->lcd_clear_display();
435 return 0;
436}
437
438void draw_image_rect(struct t_disp* pdisp, int x, int y, int width, int height)
439{
440#ifdef HAVE_LCD_COLOR
441 yuv_bitmap_part(
442 pdisp->bitmap, pdisp->csub_x, pdisp->csub_y,
443 pdisp->x + x, pdisp->y + y, pdisp->stride,
444 x + MAX(0, (LCD_WIDTH - pdisp->width) / 2),
445 y + MAX(0, (LCD_HEIGHT - pdisp->height) / 2),
446 width, height,
447 jpeg_settings.colour_mode, jpeg_settings.dither_mode);
448#else
449 MYXLCD(gray_bitmap_part)(
450 pdisp->bitmap[0], pdisp->x + x, pdisp->y + y, pdisp->stride,
451 x + MAX(0, (LCD_WIDTH-pdisp->width)/2),
452 y + MAX(0, (LCD_HEIGHT-pdisp->height)/2),
453 width, height);
454#endif
455}
456
457/* Pan the viewing window right - move image to the left and fill in
458 the right-hand side */
459static void pan_view_right(struct t_disp* pdisp)
460{
461 int move;
462
463 move = MIN(HSCROLL, pdisp->width - pdisp->x - LCD_WIDTH);
464 if (move > 0)
465 {
466 MYXLCD(scroll_left)(move); /* scroll left */
467 pdisp->x += move;
468 draw_image_rect(pdisp, LCD_WIDTH - move, 0, move, pdisp->height-pdisp->y);
469 MYLCD_UPDATE();
470 }
471}
472
473/* Pan the viewing window left - move image to the right and fill in
474 the left-hand side */
475static void pan_view_left(struct t_disp* pdisp)
476{
477 int move;
478
479 move = MIN(HSCROLL, pdisp->x);
480 if (move > 0)
481 {
482 MYXLCD(scroll_right)(move); /* scroll right */
483 pdisp->x -= move;
484 draw_image_rect(pdisp, 0, 0, move, pdisp->height-pdisp->y);
485 MYLCD_UPDATE();
486 }
487}
488
489/* Pan the viewing window up - move image down and fill in
490 the top */
491static void pan_view_up(struct t_disp* pdisp)
492{
493 int move;
494
495 move = MIN(VSCROLL, pdisp->y);
496 if (move > 0)
497 {
498 MYXLCD(scroll_down)(move); /* scroll down */
499 pdisp->y -= move;
500#ifdef HAVE_LCD_COLOR
501 if (jpeg_settings.dither_mode == DITHER_DIFFUSION)
502 {
503 /* Draw over the band at the top of the last update
504 caused by lack of error history on line zero. */
505 move = MIN(move + 1, pdisp->y + pdisp->height);
506 }
507#endif
508 draw_image_rect(pdisp, 0, 0, pdisp->width-pdisp->x, move);
509 MYLCD_UPDATE();
510 }
511}
512
513/* Pan the viewing window down - move image up and fill in
514 the bottom */
515static void pan_view_down(struct t_disp* pdisp)
516{
517 int move;
518
519 move = MIN(VSCROLL, pdisp->height - pdisp->y - LCD_HEIGHT);
520 if (move > 0)
521 {
522 MYXLCD(scroll_up)(move); /* scroll up */
523 pdisp->y += move;
524#ifdef HAVE_LCD_COLOR
525 if (jpeg_settings.dither_mode == DITHER_DIFFUSION)
526 {
527 /* Save the line that was on the last line of the display
528 and draw one extra line above then recover the line with
529 image data that had an error history when it was drawn.
530 */
531 move++, pdisp->y--;
532 rb->memcpy(rgb_linebuf,
533 rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH,
534 LCD_WIDTH*sizeof (fb_data));
535 }
536#endif
537
538 draw_image_rect(pdisp, 0, LCD_HEIGHT - move, pdisp->width-pdisp->x, move);
539
540#ifdef HAVE_LCD_COLOR
541 if (jpeg_settings.dither_mode == DITHER_DIFFUSION)
542 {
543 /* Cover the first row drawn with previous image data. */
544 rb->memcpy(rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH,
545 rgb_linebuf, LCD_WIDTH*sizeof (fb_data));
546 pdisp->y++;
547 }
548#endif
549 MYLCD_UPDATE();
550 }
551}
552
553/* interactively scroll around the image */
554int scroll_bmp(struct t_disp* pdisp)
555{
556 int button;
557 int lastbutton = 0;
558
559 while (true)
560 {
561 if (slideshow_enabled)
562 button = rb->button_get_w_tmo(jpeg_settings.ss_timeout * HZ);
563 else
564 button = rb->button_get(true);
565
566 running_slideshow = false;
567
568 switch(button)
569 {
570 case JPEG_LEFT:
571 if (entries > 1 && pdisp->width <= LCD_WIDTH
572 && pdisp->height <= LCD_HEIGHT)
573 return change_filename(DIR_PREV);
574 case JPEG_LEFT | BUTTON_REPEAT:
575 pan_view_left(pdisp);
576 break;
577
578 case JPEG_RIGHT:
579 if (entries > 1 && pdisp->width <= LCD_WIDTH
580 && pdisp->height <= LCD_HEIGHT)
581 return change_filename(DIR_NEXT);
582 case JPEG_RIGHT | BUTTON_REPEAT:
583 pan_view_right(pdisp);
584 break;
585
586 case JPEG_UP:
587 case JPEG_UP | BUTTON_REPEAT:
588 pan_view_up(pdisp);
589 break;
590
591 case JPEG_DOWN:
592 case JPEG_DOWN | BUTTON_REPEAT:
593 pan_view_down(pdisp);
594 break;
595
596 case BUTTON_NONE:
597 if (!slideshow_enabled)
598 break;
599 running_slideshow = true;
600 if (entries > 1)
601 return change_filename(DIR_NEXT);
602 break;
603
604#ifdef JPEG_SLIDE_SHOW
605 case JPEG_SLIDE_SHOW:
606 slideshow_enabled = !slideshow_enabled;
607 running_slideshow = slideshow_enabled;
608 break;
609#endif
610
611#ifdef JPEG_NEXT_REPEAT
612 case JPEG_NEXT_REPEAT:
613#endif
614 case JPEG_NEXT:
615 if (entries > 1)
616 return change_filename(DIR_NEXT);
617 break;
618
619#ifdef JPEG_PREVIOUS_REPEAT
620 case JPEG_PREVIOUS_REPEAT:
621#endif
622 case JPEG_PREVIOUS:
623 if (entries > 1)
624 return change_filename(DIR_PREV);
625 break;
626
627 case JPEG_ZOOM_IN:
628#ifdef JPEG_ZOOM_PRE
629 if (lastbutton != JPEG_ZOOM_PRE)
630 break;
631#endif
632 return ZOOM_IN;
633 break;
634
635 case JPEG_ZOOM_OUT:
636#ifdef JPEG_ZOOM_PRE
637 if (lastbutton != JPEG_ZOOM_PRE)
638 break;
639#endif
640 return ZOOM_OUT;
641 break;
642#ifdef JPEG_RC_MENU
643 case JPEG_RC_MENU:
644#endif
645 case JPEG_MENU:
646#ifdef USEGSLIB
647 grey_show(false); /* switch off greyscale overlay */
648#endif
649 if (show_menu() == 1)
650 return PLUGIN_OK;
651
652#ifdef USEGSLIB
653 grey_show(true); /* switch on greyscale overlay */
654#else
655 draw_image_rect(pdisp, 0, 0,
656 pdisp->width-pdisp->x, pdisp->height-pdisp->y);
657 MYLCD_UPDATE();
658#endif
659 break;
660 default:
661 if (rb->default_event_handler_ex(button, cleanup, NULL)
662 == SYS_USB_CONNECTED)
663 return PLUGIN_USB_CONNECTED;
664 break;
665
666 } /* switch */
667
668 if (button != BUTTON_NONE)
669 lastbutton = button;
670 } /* while (true) */
671}
672
673/********************* main function *************************/
674
675/* callback updating a progress meter while JPEG decoding */
676void cb_progress(int current, int total)
677{
678 rb->yield(); /* be nice to the other threads */
679 if(!running_slideshow)
680 {
681 rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN],
682 0, LCD_HEIGHT-8, LCD_WIDTH, 8,
683 total, 0, current, HORIZONTAL);
684 rb->lcd_update_rect(0, LCD_HEIGHT-8, LCD_WIDTH, 8);
685 }
686#ifndef USEGSLIB
687 else
688 {
689 /* in slideshow mode, keep gui interference to a minimum */
690 rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN],
691 0, LCD_HEIGHT-4, LCD_WIDTH, 4,
692 total, 0, current, HORIZONTAL);
693 rb->lcd_update_rect(0, LCD_HEIGHT-4, LCD_WIDTH, 4);
694 }
695#endif
696}
697
698int jpegmem(struct jpeg *p_jpg, int ds)
699{
700 int size;
701
702 size = (p_jpg->x_phys/ds/p_jpg->subsample_x[0])
703 * (p_jpg->y_phys/ds/p_jpg->subsample_y[0]);
704#ifdef HAVE_LCD_COLOR
705 if (p_jpg->blocks > 1) /* colour, add requirements for chroma */
706 {
707 size += (p_jpg->x_phys/ds/p_jpg->subsample_x[1])
708 * (p_jpg->y_phys/ds/p_jpg->subsample_y[1]);
709 size += (p_jpg->x_phys/ds/p_jpg->subsample_x[2])
710 * (p_jpg->y_phys/ds/p_jpg->subsample_y[2]);
711 }
712#endif
713 return size;
714}
715
716/* how far can we zoom in without running out of memory */
717int min_downscale(struct jpeg *p_jpg, int bufsize)
718{
719 int downscale = 8;
720
721 if (jpegmem(p_jpg, 8) > bufsize)
722 return 0; /* error, too large, even 1:8 doesn't fit */
723
724 while (downscale > 1 && jpegmem(p_jpg, downscale/2) <= bufsize)
725 downscale /= 2;
726
727 return downscale;
728}
729
730/* how far can we zoom out, to fit image into the LCD */
731int max_downscale(struct jpeg *p_jpg)
732{
733 int downscale = 1;
734
735 while (downscale < 8 && (p_jpg->x_size/downscale > LCD_WIDTH
736 || p_jpg->y_size/downscale > LCD_HEIGHT))
737 {
738 downscale *= 2;
739 }
740
741 return downscale;
742}
743
744/* load image from filename. */
745int load_image(char* filename, struct jpeg *p_jpg)
746{
747 int fd;
748 int filesize;
749 unsigned char* buf_jpeg; /* compressed JPEG image */
750 int status;
751
752 fd = rb->open(filename, O_RDONLY);
753 if (fd < 0)
754 {
755 rb->splashf(HZ, "err opening %s:%d", filename, fd);
756 return PLUGIN_ERROR;
757 }
758 filesize = rb->filesize(fd);
759
760 /* allocate JPEG buffer */
761 buf_jpeg = buf;
762
763 /* we can start the decompressed images behind it */
764 buf_images = buf_root = buf + filesize;
765 buf_images_size = root_size = buf_size - filesize;
766
767 if (buf_images_size <= 0)
768 {
769 rb->close(fd);
770 return PLUGIN_OUTOFMEM;
771 }
772
773 if(!running_slideshow)
774 {
775 rb->snprintf(print, sizeof(print), "%s:", rb->strrchr(filename,'/')+1);
776 rb->lcd_puts(0, 0, print);
777 rb->lcd_update();
778
779 rb->snprintf(print, sizeof(print), "loading %d bytes", filesize);
780 rb->lcd_puts(0, 1, print);
781 rb->lcd_update();
782 }
783
784 rb->read(fd, buf_jpeg, filesize);
785 rb->close(fd);
786
787 if(!running_slideshow)
788 {
789 rb->snprintf(print, sizeof(print), "decoding markers");
790 rb->lcd_puts(0, 2, print);
791 rb->lcd_update();
792 }
793#ifndef SIMULATOR
794 else if(immediate_ata_off)
795 {
796 /* running slideshow and time is long enough: power down disk */
797 rb->storage_sleep();
798 }
799#endif
800
801 /* process markers, unstuffing */
802 status = process_markers(buf_jpeg, filesize, p_jpg);
803
804 if (status < 0 || (status & (DQT | SOF0)) != (DQT | SOF0))
805 { /* bad format or minimum components not contained */
806 rb->splashf(HZ, "unsupported %d", status);
807 return PLUGIN_ERROR;
808 }
809
810 if (!(status & DHT)) /* if no Huffman table present: */
811 default_huff_tbl(p_jpg); /* use default */
812 build_lut(p_jpg); /* derive Huffman and other lookup-tables */
813
814 if(!running_slideshow)
815 {
816 rb->snprintf(print, sizeof(print), "image %dx%d",
817 p_jpg->x_size, p_jpg->y_size);
818 rb->lcd_puts(0, 2, print);
819 rb->lcd_update();
820 }
821
822 return PLUGIN_OK;
823}
824
825/* return decoded or cached image */
826struct t_disp* get_image(struct jpeg* p_jpg, int ds)
827{
828 int w, h; /* used to center output */
829 int size; /* decompressed image size */
830 long time; /* measured ticks */
831 int status;
832
833 struct t_disp* p_disp = &disp[ds]; /* short cut */
834
835 if (p_disp->bitmap[0] != NULL)
836 {
837 return p_disp; /* we still have it */
838 }
839
840 /* assign image buffer */
841
842 /* physical size needed for decoding */
843 size = jpegmem(p_jpg, ds);
844 if (buf_images_size <= size)
845 { /* have to discard the current */
846 int i;
847 for (i=1; i<=8; i++)
848 disp[i].bitmap[0] = NULL; /* invalidate all bitmaps */
849 buf_images = buf_root; /* start again from the beginning of the buffer */
850 buf_images_size = root_size;
851 }
852
853#ifdef HAVE_LCD_COLOR
854 if (p_jpg->blocks > 1) /* colour jpeg */
855 {
856 int i;
857
858 for (i = 1; i < 3; i++)
859 {
860 size = (p_jpg->x_phys / ds / p_jpg->subsample_x[i])
861 * (p_jpg->y_phys / ds / p_jpg->subsample_y[i]);
862 p_disp->bitmap[i] = buf_images;
863 buf_images += size;
864 buf_images_size -= size;
865 }
866 p_disp->csub_x = p_jpg->subsample_x[1];
867 p_disp->csub_y = p_jpg->subsample_y[1];
868 }
869 else
870 {
871 p_disp->csub_x = p_disp->csub_y = 0;
872 p_disp->bitmap[1] = p_disp->bitmap[2] = buf_images;
873 }
874#endif
875 /* size may be less when decoded (if height is not block aligned) */
876 size = (p_jpg->x_phys/ds) * (p_jpg->y_size / ds);
877 p_disp->bitmap[0] = buf_images;
878 buf_images += size;
879 buf_images_size -= size;
880
881 if(!running_slideshow)
882 {
883 rb->snprintf(print, sizeof(print), "decoding %d*%d",
884 p_jpg->x_size/ds, p_jpg->y_size/ds);
885 rb->lcd_puts(0, 3, print);
886 rb->lcd_update();
887 }
888
889 /* update image properties */
890 p_disp->width = p_jpg->x_size / ds;
891 p_disp->stride = p_jpg->x_phys / ds; /* use physical size for stride */
892 p_disp->height = p_jpg->y_size / ds;
893
894 /* the actual decoding */
895 time = *rb->current_tick;
896#ifdef HAVE_ADJUSTABLE_CPU_FREQ
897 rb->cpu_boost(true);
898 status = jpeg_decode(p_jpg, p_disp->bitmap, ds, cb_progress);
899 rb->cpu_boost(false);
900#else
901 status = jpeg_decode(p_jpg, p_disp->bitmap, ds, cb_progress);
902#endif
903 if (status)
904 {
905 rb->splashf(HZ, "decode error %d", status);
906 return NULL;
907 }
908 time = *rb->current_tick - time;
909
910 if(!running_slideshow)
911 {
912 rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ);
913 rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */
914 rb->lcd_putsxy((LCD_WIDTH - w)/2, LCD_HEIGHT - h, print);
915 rb->lcd_update();
916 }
917
918 return p_disp;
919}
920
921
922/* set the view to the given center point, limit if necessary */
923void set_view (struct t_disp* p_disp, int cx, int cy)
924{
925 int x, y;
926
927 /* plain center to available width/height */
928 x = cx - MIN(LCD_WIDTH, p_disp->width) / 2;
929 y = cy - MIN(LCD_HEIGHT, p_disp->height) / 2;
930
931 /* limit against upper image size */
932 x = MIN(p_disp->width - LCD_WIDTH, x);
933 y = MIN(p_disp->height - LCD_HEIGHT, y);
934
935 /* limit against negative side */
936 x = MAX(0, x);
937 y = MAX(0, y);
938
939 p_disp->x = x; /* set the values */
940 p_disp->y = y;
941}
942
943/* calculate the view center based on the bitmap position */
944void get_view(struct t_disp* p_disp, int* p_cx, int* p_cy)
945{
946 *p_cx = p_disp->x + MIN(LCD_WIDTH, p_disp->width) / 2;
947 *p_cy = p_disp->y + MIN(LCD_HEIGHT, p_disp->height) / 2;
948}
949
950/* load, decode, display the image */
951int load_and_show(char* filename)
952{
953 int status;
954 struct t_disp* p_disp; /* currenly displayed image */
955 int cx, cy; /* view center */
956
957#if LCD_DEPTH > 1
958 rb->lcd_set_foreground(LCD_WHITE);
959 rb->lcd_set_background(LCD_BLACK);
960 rb->lcd_set_backdrop(NULL);
961#endif
962 rb->lcd_clear_display();
963
964 rb->memset(&disp, 0, sizeof(disp));
965 rb->memset(&jpg, 0, sizeof(jpg)); /* clear info struct */
966
967 if (rb->button_get(false) == JPEG_MENU)
968 status = PLUGIN_ABORT;
969 else
970 status = load_image(filename, &jpg);
971
972 if (status == PLUGIN_OUTOFMEM)
973 {
974#if PLUGIN_BUFFER_SIZE >= MIN_MEM
975 if(plug_buf)
976 {
977 rb->lcd_setfont(FONT_SYSFIXED);
978 rb->lcd_clear_display();
979 rb->snprintf(print,sizeof(print),"%s:",rb->strrchr(filename,'/')+1);
980 rb->lcd_puts(0,0,print);
981 rb->lcd_puts(0,1,"Not enough plugin memory!");
982 rb->lcd_puts(0,2,"Zoom In: Stop playback.");
983 if(entries>1)
984 rb->lcd_puts(0,3,"Left/Right: Skip File.");
985 rb->lcd_puts(0,4,"Show Menu: Quit.");
986 rb->lcd_update();
987 rb->lcd_setfont(FONT_UI);
988
989 rb->button_clear_queue();
990
991 while (1)
992 {
993 int button = rb->button_get(true);
994 switch(button)
995 {
996 case JPEG_ZOOM_IN:
997 plug_buf = false;
998 buf = rb->plugin_get_audio_buffer((size_t *)&buf_size);
999 /*try again this file, now using the audio buffer */
1000 return PLUGIN_OTHER;
1001#ifdef JPEG_RC_MENU
1002 case JPEG_RC_MENU:
1003#endif
1004 case JPEG_MENU:
1005 return PLUGIN_OK;
1006
1007 case JPEG_LEFT:
1008 if(entries>1)
1009 {
1010 rb->lcd_clear_display();
1011 return change_filename(DIR_PREV);
1012 }
1013 break;
1014
1015 case JPEG_RIGHT:
1016 if(entries>1)
1017 {
1018 rb->lcd_clear_display();
1019 return change_filename(DIR_NEXT);
1020 }
1021 break;
1022 default:
1023 if(rb->default_event_handler_ex(button, cleanup, NULL)
1024 == SYS_USB_CONNECTED)
1025 return PLUGIN_USB_CONNECTED;
1026
1027 }
1028 }
1029 }
1030 else
1031#endif
1032 {
1033 rb->splash(HZ, "Out of Memory");
1034 file_pt[curfile] = NULL;
1035 return change_filename(direction);
1036 }
1037 }
1038 else if (status == PLUGIN_ERROR)
1039 {
1040 file_pt[curfile] = NULL;
1041 return change_filename(direction);
1042 }
1043 else if (status == PLUGIN_ABORT) {
1044 rb->splash(HZ, "aborted");
1045 return PLUGIN_OK;
1046 }
1047
1048 ds_max = max_downscale(&jpg); /* check display constraint */
1049 ds_min = min_downscale(&jpg, buf_images_size); /* check memory constraint */
1050 if (ds_min == 0)
1051 {
1052 rb->splash(HZ, "too large");
1053 file_pt[curfile] = NULL;
1054 return change_filename(direction);
1055 }
1056 else if (ds_max < ds_min)
1057 ds_max = ds_min;
1058
1059 ds = ds_max; /* initialize setting */
1060 cx = jpg.x_size/ds/2; /* center the view */
1061 cy = jpg.y_size/ds/2;
1062
1063 do /* loop the image prepare and decoding when zoomed */
1064 {
1065 p_disp = get_image(&jpg, ds); /* decode or fetch from cache */
1066 if (p_disp == NULL)
1067 {
1068 file_pt[curfile] = NULL;
1069 return change_filename(direction);
1070 }
1071
1072 set_view(p_disp, cx, cy);
1073
1074 if(!running_slideshow)
1075 {
1076 rb->snprintf(print, sizeof(print), "showing %dx%d",
1077 p_disp->width, p_disp->height);
1078 rb->lcd_puts(0, 3, print);
1079 rb->lcd_update();
1080 }
1081
1082 MYLCD(clear_display)();
1083 draw_image_rect(p_disp, 0, 0,
1084 p_disp->width-p_disp->x, p_disp->height-p_disp->y);
1085 MYLCD_UPDATE();
1086
1087#ifdef USEGSLIB
1088 grey_show(true); /* switch on greyscale overlay */
1089#endif
1090
1091 /* drawing is now finished, play around with scrolling
1092 * until you press OFF or connect USB
1093 */
1094 while (1)
1095 {
1096 status = scroll_bmp(p_disp);
1097 if (status == ZOOM_IN)
1098 {
1099 if (ds > ds_min)
1100 {
1101 ds /= 2; /* reduce downscaling to zoom in */
1102 get_view(p_disp, &cx, &cy);
1103 cx *= 2; /* prepare the position in the new image */
1104 cy *= 2;
1105 }
1106 else
1107 continue;
1108 }
1109
1110 if (status == ZOOM_OUT)
1111 {
1112 if (ds < ds_max)
1113 {
1114 ds *= 2; /* increase downscaling to zoom out */
1115 get_view(p_disp, &cx, &cy);
1116 cx /= 2; /* prepare the position in the new image */
1117 cy /= 2;
1118 }
1119 else
1120 continue;
1121 }
1122 break;
1123 }
1124
1125#ifdef USEGSLIB
1126 grey_show(false); /* switch off overlay */
1127#endif
1128 rb->lcd_clear_display();
1129 }
1130 while (status != PLUGIN_OK && status != PLUGIN_USB_CONNECTED
1131 && status != PLUGIN_OTHER);
1132#ifdef USEGSLIB
1133 rb->lcd_update();
1134#endif
1135 return status;
1136}
1137
1138/******************** Plugin entry point *********************/
1139
1140enum plugin_status plugin_start(const void* parameter)
1141{
1142 int condition;
1143#ifdef USEGSLIB
1144 long greysize; /* helper */
1145#endif
1146#if LCD_DEPTH > 1
1147 old_backdrop = rb->lcd_get_backdrop();
1148#endif
1149
1150 if(!parameter) return PLUGIN_ERROR;
1151
1152#if PLUGIN_BUFFER_SIZE >= MIN_MEM
1153 buf = rb->plugin_get_buffer((size_t *)&buf_size);
1154#else
1155 buf = rb->plugin_get_audio_buffer((size_t *)&buf_size);
1156#endif
1157
1158 rb->strcpy(np_file, parameter);
1159 get_pic_list();
1160
1161 if(!entries) return PLUGIN_ERROR;
1162
1163#if (PLUGIN_BUFFER_SIZE >= MIN_MEM) && !defined(SIMULATOR)
1164 if(!rb->audio_status())
1165 {
1166 plug_buf = false;
1167 buf = rb->plugin_get_audio_buffer((size_t *)&buf_size);
1168 }
1169#endif
1170
1171#ifdef USEGSLIB
1172 if (!grey_init(buf, buf_size, GREY_ON_COP,
1173 LCD_WIDTH, LCD_HEIGHT, &greysize))
1174 {
1175 rb->splash(HZ, "grey buf error");
1176 return PLUGIN_ERROR;
1177 }
1178 buf += greysize;
1179 buf_size -= greysize;
1180#endif
1181
1182 /* should be ok to just load settings since the plugin itself has
1183 just been loaded from disk and the drive should be spinning */
1184 configfile_load(JPEG_CONFIGFILE, jpeg_config,
1185 ARRAYLEN(jpeg_config), JPEG_SETTINGS_MINVERSION);
1186 old_settings = jpeg_settings;
1187
1188 /* Turn off backlight timeout */
1189 backlight_force_on(); /* backlight control in lib/helper.c */
1190
1191 do
1192 {
1193 condition = load_and_show(np_file);
1194 } while (condition != PLUGIN_OK && condition != PLUGIN_USB_CONNECTED
1195 && condition != PLUGIN_ERROR);
1196
1197 if (rb->memcmp(&jpeg_settings, &old_settings, sizeof (jpeg_settings)))
1198 {
1199 /* Just in case drive has to spin, keep it from looking locked */
1200 rb->splash(0, "Saving Settings");
1201 configfile_save(JPEG_CONFIGFILE, jpeg_config,
1202 ARRAYLEN(jpeg_config), JPEG_SETTINGS_VERSION);
1203 }
1204
1205#if !defined(SIMULATOR) && defined(HAVE_DISK_STORAGE)
1206 /* set back ata spindown time in case we changed it */
1207 rb->storage_spindown(rb->global_settings->disk_spindown);
1208#endif
1209
1210 /* Turn on backlight timeout (revert to settings) */
1211 backlight_use_settings(); /* backlight control in lib/helper.c */
1212
1213#ifdef USEGSLIB
1214 grey_release(); /* deinitialize */
1215#endif
1216
1217 return condition;
1218}
diff --git a/apps/plugins/jpeg/jpeg.h b/apps/plugins/jpeg/jpeg.h
deleted file mode 100644
index 552d26ed1a..0000000000
--- a/apps/plugins/jpeg/jpeg.h
+++ /dev/null
@@ -1,340 +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#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_FUZE_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_HOME|BUTTON_REPEAT)
145#define JPEG_NEXT BUTTON_SCROLL_FWD
146#define JPEG_NEXT_REPEAT (BUTTON_SCROLL_FWD|BUTTON_REPEAT)
147#define JPEG_PREVIOUS BUTTON_SCROLL_BACK
148#define JPEG_PREVIOUS_REPEAT (BUTTON_SCROLL_BACK|BUTTON_REPEAT)
149
150#elif CONFIG_KEYPAD == SANSA_C200_PAD
151#define JPEG_ZOOM_PRE BUTTON_SELECT
152#define JPEG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
153#define JPEG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
154#define JPEG_UP BUTTON_UP
155#define JPEG_DOWN BUTTON_DOWN
156#define JPEG_LEFT BUTTON_LEFT
157#define JPEG_RIGHT BUTTON_RIGHT
158#define JPEG_MENU BUTTON_POWER
159#define JPEG_SLIDE_SHOW BUTTON_REC
160#define JPEG_NEXT BUTTON_VOL_UP
161#define JPEG_NEXT_REPEAT (BUTTON_VOL_UP|BUTTON_REPEAT)
162#define JPEG_PREVIOUS BUTTON_VOL_DOWN
163#define JPEG_PREVIOUS_REPEAT (BUTTON_VOL_DOWN|BUTTON_REPEAT)
164
165#elif CONFIG_KEYPAD == SANSA_CLIP_PAD
166#define JPEG_ZOOM_PRE BUTTON_SELECT
167#define JPEG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
168#define JPEG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
169#define JPEG_UP BUTTON_UP
170#define JPEG_DOWN BUTTON_DOWN
171#define JPEG_LEFT BUTTON_LEFT
172#define JPEG_RIGHT BUTTON_RIGHT
173#define JPEG_MENU BUTTON_POWER
174#define JPEG_SLIDE_SHOW BUTTON_HOME
175#define JPEG_NEXT BUTTON_VOL_UP
176#define JPEG_NEXT_REPEAT (BUTTON_VOL_UP|BUTTON_REPEAT)
177#define JPEG_PREVIOUS BUTTON_VOL_DOWN
178#define JPEG_PREVIOUS_REPEAT (BUTTON_VOL_DOWN|BUTTON_REPEAT)
179
180#elif CONFIG_KEYPAD == SANSA_M200_PAD
181#define JPEG_ZOOM_PRE BUTTON_SELECT
182#define JPEG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
183#define JPEG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
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_POWER
189#define JPEG_SLIDE_SHOW (BUTTON_SELECT | BUTTON_UP)
190#define JPEG_NEXT BUTTON_VOL_UP
191#define JPEG_NEXT_REPEAT (BUTTON_VOL_UP|BUTTON_REPEAT)
192#define JPEG_PREVIOUS BUTTON_VOL_DOWN
193#define JPEG_PREVIOUS_REPEAT (BUTTON_VOL_DOWN|BUTTON_REPEAT)
194
195#elif CONFIG_KEYPAD == IRIVER_H10_PAD
196#define JPEG_ZOOM_PRE BUTTON_PLAY
197#define JPEG_ZOOM_IN (BUTTON_PLAY | BUTTON_REL)
198#define JPEG_ZOOM_OUT (BUTTON_PLAY | BUTTON_REPEAT)
199#define JPEG_UP BUTTON_SCROLL_UP
200#define JPEG_DOWN BUTTON_SCROLL_DOWN
201#define JPEG_LEFT BUTTON_LEFT
202#define JPEG_RIGHT BUTTON_RIGHT
203#define JPEG_MENU BUTTON_POWER
204#define JPEG_NEXT BUTTON_FF
205#define JPEG_PREVIOUS BUTTON_REW
206
207#elif CONFIG_KEYPAD == MROBE500_PAD
208#define JPEG_MENU BUTTON_POWER
209
210#elif CONFIG_KEYPAD == GIGABEAT_S_PAD
211#define JPEG_ZOOM_IN BUTTON_VOL_UP
212#define JPEG_ZOOM_OUT BUTTON_VOL_DOWN
213#define JPEG_UP BUTTON_UP
214#define JPEG_DOWN BUTTON_DOWN
215#define JPEG_LEFT BUTTON_LEFT
216#define JPEG_RIGHT BUTTON_RIGHT
217#define JPEG_MENU BUTTON_MENU
218#define JPEG_NEXT BUTTON_NEXT
219#define JPEG_PREVIOUS BUTTON_PREV
220
221#elif CONFIG_KEYPAD == MROBE100_PAD
222#define JPEG_ZOOM_IN BUTTON_SELECT
223#define JPEG_ZOOM_OUT BUTTON_PLAY
224#define JPEG_UP BUTTON_UP
225#define JPEG_DOWN BUTTON_DOWN
226#define JPEG_LEFT BUTTON_LEFT
227#define JPEG_RIGHT BUTTON_RIGHT
228#define JPEG_MENU BUTTON_MENU
229#define JPEG_NEXT (BUTTON_DISPLAY | BUTTON_RIGHT)
230#define JPEG_PREVIOUS (BUTTON_DISPLAY | BUTTON_LEFT)
231
232#elif CONFIG_KEYPAD == IAUDIO_M3_PAD
233#define JPEG_ZOOM_PRE BUTTON_RC_PLAY
234#define JPEG_ZOOM_IN (BUTTON_RC_PLAY|BUTTON_REL)
235#define JPEG_ZOOM_OUT (BUTTON_RC_PLAY|BUTTON_REPEAT)
236#define JPEG_UP BUTTON_RC_VOL_UP
237#define JPEG_DOWN BUTTON_RC_VOL_DOWN
238#define JPEG_LEFT BUTTON_RC_REW
239#define JPEG_RIGHT BUTTON_RC_FF
240#define JPEG_MENU BUTTON_RC_REC
241#define JPEG_NEXT BUTTON_RC_MODE
242#define JPEG_PREVIOUS BUTTON_RC_MENU
243
244#elif CONFIG_KEYPAD == COWON_D2_PAD
245
246#elif CONFIG_KEYPAD == IAUDIO67_PAD
247#define JPEG_ZOOM_IN BUTTON_VOLUP
248#define JPEG_ZOOM_OUT BUTTON_VOLDOWN
249#define JPEG_UP BUTTON_STOP
250#define JPEG_DOWN BUTTON_PLAY
251#define JPEG_LEFT BUTTON_LEFT
252#define JPEG_RIGHT BUTTON_RIGHT
253#define JPEG_MENU BUTTON_MENU
254#define JPEG_NEXT (BUTTON_PLAY|BUTTON_VOLUP)
255#define JPEG_PREVIOUS (BUTTON_PLAY|BUTTON_VOLDOWN)
256
257#elif CONFIG_KEYPAD == CREATIVEZVM_PAD
258
259#define JPEG_ZOOM_IN BUTTON_PLAY
260#define JPEG_ZOOM_OUT BUTTON_CUSTOM
261#define JPEG_UP BUTTON_UP
262#define JPEG_DOWN BUTTON_DOWN
263#define JPEG_LEFT BUTTON_LEFT
264#define JPEG_RIGHT BUTTON_RIGHT
265#define JPEG_MENU BUTTON_MENU
266#define JPEG_NEXT BUTTON_SELECT
267#define JPEG_PREVIOUS BUTTON_BACK
268
269#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
270#define JPEG_ZOOM_IN BUTTON_VOL_UP
271#define JPEG_ZOOM_OUT BUTTON_VOL_DOWN
272#define JPEG_UP BUTTON_UP
273#define JPEG_DOWN BUTTON_DOWN
274#define JPEG_LEFT BUTTON_LEFT
275#define JPEG_RIGHT BUTTON_RIGHT
276#define JPEG_MENU BUTTON_MENU
277#define JPEG_NEXT BUTTON_VIEW
278#define JPEG_PREVIOUS BUTTON_PLAYLIST
279
280#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
281#define JPEG_ZOOM_IN BUTTON_VOL_UP
282#define JPEG_ZOOM_OUT BUTTON_VOL_DOWN
283#define JPEG_UP BUTTON_UP
284#define JPEG_DOWN BUTTON_DOWN
285#define JPEG_LEFT BUTTON_PREV
286#define JPEG_RIGHT BUTTON_NEXT
287#define JPEG_MENU BUTTON_MENU
288#define JPEG_NEXT BUTTON_RIGHT
289#define JPEG_PREVIOUS BUTTON_LEFT
290
291#elif CONFIG_KEYPAD == ONDAVX747_PAD
292#elif CONFIG_KEYPAD == ONDAVX777_PAD
293
294#elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
295#define JPEG_ZOOM_IN (BUTTON_PLAY|BUTTON_UP)
296#define JPEG_ZOOM_OUT (BUTTON_PLAY|BUTTON_DOWN)
297#define JPEG_UP BUTTON_UP
298#define JPEG_DOWN BUTTON_DOWN
299#define JPEG_LEFT BUTTON_LEFT
300#define JPEG_RIGHT BUTTON_RIGHT
301#define JPEG_MENU BUTTON_PLAY
302#define JPEG_NEXT BUTTON_FFWD
303#define JPEG_PREVIOUS BUTTON_REW
304
305#else
306#error No keymap defined!
307#endif
308
309#ifdef HAVE_TOUCHSCREEN
310#ifndef JPEG_UP
311#define JPEG_UP BUTTON_TOPMIDDLE
312#endif
313#ifndef JPEG_DOWN
314#define JPEG_DOWN BUTTON_BOTTOMMIDDLE
315#endif
316#ifndef JPEG_LEFT
317#define JPEG_LEFT BUTTON_MIDLEFT
318#endif
319#ifndef JPEG_RIGHT
320#define JPEG_RIGHT BUTTON_MIDRIGHT
321#endif
322#ifndef JPEG_ZOOM_IN
323#define JPEG_ZOOM_IN BUTTON_TOPRIGHT
324#endif
325#ifndef JPEG_ZOOM_OUT
326#define JPEG_ZOOM_OUT BUTTON_TOPLEFT
327#endif
328#ifndef JPEG_MENU
329#define JPEG_MENU (BUTTON_CENTER|BUTTON_REL)
330#endif
331#ifndef JPEG_NEXT
332#define JPEG_NEXT BUTTON_BOTTOMRIGHT
333#endif
334#ifndef JPEG_PREVIOUS
335#define JPEG_PREVIOUS BUTTON_BOTTOMLEFT
336#endif
337#endif
338
339
340#endif /* _JPEG_JPEG_H */
diff --git a/apps/plugins/jpeg/jpeg.make b/apps/plugins/jpeg/jpeg.make
deleted file mode 100644
index 15168dc4fb..0000000000
--- a/apps/plugins/jpeg/jpeg.make
+++ /dev/null
@@ -1,21 +0,0 @@
1# __________ __ ___.
2# Open \______ \ ____ ____ | | _\_ |__ _______ ___
3# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
4# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
5# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
6# \/ \/ \/ \/ \/
7# $Id$
8#
9
10JPEGSRCDIR := $(APPSDIR)/plugins/jpeg
11JPEGBUILDDIR := $(BUILDDIR)/apps/plugins/jpeg
12
13ROCKS += $(JPEGBUILDDIR)/jpeg.rock
14
15JPEG_SRC := $(call preprocess, $(JPEGSRCDIR)/SOURCES)
16JPEG_OBJ := $(call c2obj, $(JPEG_SRC))
17
18# add source files to OTHER_SRC to get automatic dependencies
19OTHER_SRC += $(JPEG_SRC)
20
21$(JPEGBUILDDIR)/jpeg.rock: $(JPEG_OBJ)
diff --git a/apps/plugins/jpeg/jpeg_decoder.c b/apps/plugins/jpeg/jpeg_decoder.c
deleted file mode 100644
index c90bff87a4..0000000000
--- a/apps/plugins/jpeg/jpeg_decoder.c
+++ /dev/null
@@ -1,1538 +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
30#include "jpeg_decoder.h"
31
32/* for portability of below JPEG code */
33#define MEMSET(p,v,c) rb->memset(p,v,c)
34#define MEMCPY(d,s,c) rb->memcpy(d,s,c)
35#define INLINE static inline
36#define ENDIAN_SWAP16(n) n /* only for poor little endian machines */
37
38/**************** begin JPEG code ********************/
39
40INLINE unsigned range_limit(int value)
41{
42#if CONFIG_CPU == SH7034
43 unsigned tmp;
44 asm ( /* Note: Uses knowledge that only low byte of result is used */
45 "mov #-128,%[t] \n"
46 "sub %[t],%[v] \n" /* value -= -128; equals value += 128; */
47 "extu.b %[v],%[t] \n"
48 "cmp/eq %[v],%[t] \n" /* low byte == whole number ? */
49 "bt 1f \n" /* yes: no overflow */
50 "cmp/pz %[v] \n" /* overflow: positive? */
51 "subc %[v],%[v] \n" /* %[r] now either 0 or 0xffffffff */
52 "1: \n"
53 : /* outputs */
54 [v]"+r"(value),
55 [t]"=&r"(tmp)
56 );
57 return value;
58#elif defined(CPU_COLDFIRE)
59 asm ( /* Note: Uses knowledge that only the low byte of the result is used */
60 "add.l #128,%[v] \n" /* value += 128; */
61 "cmp.l #255,%[v] \n" /* overflow? */
62 "bls.b 1f \n" /* no: return value */
63 "spl.b %[v] \n" /* yes: set low byte to appropriate boundary */
64 "1: \n"
65 : /* outputs */
66 [v]"+d"(value)
67 );
68 return value;
69#elif defined(CPU_ARM)
70 asm ( /* Note: Uses knowledge that only the low byte of the result is used */
71 "add %[v], %[v], #128 \n" /* value += 128 */
72 "cmp %[v], #255 \n" /* out of range 0..255? */
73 "mvnhi %[v], %[v], asr #31 \n" /* yes: set all bits to ~(sign_bit) */
74 : /* outputs */
75 [v]"+r"(value)
76 );
77 return value;
78#else
79 value += 128;
80
81 if ((unsigned)value <= 255)
82 return value;
83
84 if (value < 0)
85 return 0;
86
87 return 255;
88#endif
89}
90
91/* IDCT implementation */
92
93
94#define CONST_BITS 13
95#define PASS1_BITS 2
96
97
98/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
99* causing a lot of useless floating-point operations at run time.
100* To get around this we use the following pre-calculated constants.
101* If you change CONST_BITS you may want to add appropriate values.
102* (With a reasonable C compiler, you can just rely on the FIX() macro...)
103*/
104#define FIX_0_298631336 2446 /* FIX(0.298631336) */
105#define FIX_0_390180644 3196 /* FIX(0.390180644) */
106#define FIX_0_541196100 4433 /* FIX(0.541196100) */
107#define FIX_0_765366865 6270 /* FIX(0.765366865) */
108#define FIX_0_899976223 7373 /* FIX(0.899976223) */
109#define FIX_1_175875602 9633 /* FIX(1.175875602) */
110#define FIX_1_501321110 12299 /* FIX(1.501321110) */
111#define FIX_1_847759065 15137 /* FIX(1.847759065) */
112#define FIX_1_961570560 16069 /* FIX(1.961570560) */
113#define FIX_2_053119869 16819 /* FIX(2.053119869) */
114#define FIX_2_562915447 20995 /* FIX(2.562915447) */
115#define FIX_3_072711026 25172 /* FIX(3.072711026) */
116
117
118
119/* Multiply an long variable by an long constant to yield an long result.
120* For 8-bit samples with the recommended scaling, all the variable
121* and constant values involved are no more than 16 bits wide, so a
122* 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
123* For 12-bit samples, a full 32-bit multiplication will be needed.
124*/
125#define MULTIPLY16(var,const) (((short) (var)) * ((short) (const)))
126
127
128/* Dequantize a coefficient by multiplying it by the multiplier-table
129* entry; produce an int result. In this module, both inputs and result
130* are 16 bits or less, so either int or short multiply will work.
131*/
132/* #define DEQUANTIZE(coef,quantval) (((int) (coef)) * (quantval)) */
133#define DEQUANTIZE MULTIPLY16
134
135/* Descale and correctly round an int value that's scaled by N bits.
136* We assume RIGHT_SHIFT rounds towards minus infinity, so adding
137* the fudge factor is correct for either sign of X.
138*/
139#define DESCALE(x,n) (((x) + (1l << ((n)-1))) >> (n))
140
141
142
143/*
144* Perform dequantization and inverse DCT on one block of coefficients,
145* producing a reduced-size 1x1 output block.
146*/
147void idct1x1(unsigned char* p_byte, int* inptr, int* quantptr, int skip_line)
148{
149 (void)skip_line; /* unused */
150 *p_byte = range_limit(inptr[0] * quantptr[0] >> 3);
151}
152
153
154
155/*
156* Perform dequantization and inverse DCT on one block of coefficients,
157* producing a reduced-size 2x2 output block.
158*/
159void idct2x2(unsigned char* p_byte, int* inptr, int* quantptr, int skip_line)
160{
161 int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
162 unsigned char* outptr;
163
164 /* Pass 1: process columns from input, store into work array. */
165
166 /* Column 0 */
167 tmp4 = DEQUANTIZE(inptr[8*0], quantptr[8*0]);
168 tmp5 = DEQUANTIZE(inptr[8*1], quantptr[8*1]);
169
170 tmp0 = tmp4 + tmp5;
171 tmp2 = tmp4 - tmp5;
172
173 /* Column 1 */
174 tmp4 = DEQUANTIZE(inptr[8*0+1], quantptr[8*0+1]);
175 tmp5 = DEQUANTIZE(inptr[8*1+1], quantptr[8*1+1]);
176
177 tmp1 = tmp4 + tmp5;
178 tmp3 = tmp4 - tmp5;
179
180 /* Pass 2: process 2 rows, store into output array. */
181
182 /* Row 0 */
183 outptr = p_byte;
184
185 outptr[0] = range_limit((int) DESCALE(tmp0 + tmp1, 3));
186 outptr[1] = range_limit((int) DESCALE(tmp0 - tmp1, 3));
187
188 /* Row 1 */
189 outptr = p_byte + skip_line;
190
191 outptr[0] = range_limit((int) DESCALE(tmp2 + tmp3, 3));
192 outptr[1] = range_limit((int) DESCALE(tmp2 - tmp3, 3));
193}
194
195
196
197/*
198* Perform dequantization and inverse DCT on one block of coefficients,
199* producing a reduced-size 4x4 output block.
200*/
201void idct4x4(unsigned char* p_byte, int* inptr, int* quantptr, int skip_line)
202{
203 int tmp0, tmp2, tmp10, tmp12;
204 int z1, z2, z3;
205 int * wsptr;
206 unsigned char* outptr;
207 int ctr;
208 int workspace[4*4]; /* buffers data between passes */
209
210 /* Pass 1: process columns from input, store into work array. */
211
212 wsptr = workspace;
213 for (ctr = 0; ctr < 4; ctr++, inptr++, quantptr++, wsptr++)
214 {
215 /* Even part */
216
217 tmp0 = DEQUANTIZE(inptr[8*0], quantptr[8*0]);
218 tmp2 = DEQUANTIZE(inptr[8*2], quantptr[8*2]);
219
220 tmp10 = (tmp0 + tmp2) << PASS1_BITS;
221 tmp12 = (tmp0 - tmp2) << PASS1_BITS;
222
223 /* Odd part */
224 /* Same rotation as in the even part of the 8x8 LL&M IDCT */
225
226 z2 = DEQUANTIZE(inptr[8*1], quantptr[8*1]);
227 z3 = DEQUANTIZE(inptr[8*3], quantptr[8*3]);
228
229 z1 = MULTIPLY16(z2 + z3, FIX_0_541196100);
230 tmp0 = DESCALE(z1 + MULTIPLY16(z3, - FIX_1_847759065), CONST_BITS-PASS1_BITS);
231 tmp2 = DESCALE(z1 + MULTIPLY16(z2, FIX_0_765366865), CONST_BITS-PASS1_BITS);
232
233 /* Final output stage */
234
235 wsptr[4*0] = (int) (tmp10 + tmp2);
236 wsptr[4*3] = (int) (tmp10 - tmp2);
237 wsptr[4*1] = (int) (tmp12 + tmp0);
238 wsptr[4*2] = (int) (tmp12 - tmp0);
239 }
240
241 /* Pass 2: process 4 rows from work array, store into output array. */
242
243 wsptr = workspace;
244 for (ctr = 0; ctr < 4; ctr++)
245 {
246 outptr = p_byte + (ctr*skip_line);
247 /* Even part */
248
249 tmp0 = (int) wsptr[0];
250 tmp2 = (int) wsptr[2];
251
252 tmp10 = (tmp0 + tmp2) << CONST_BITS;
253 tmp12 = (tmp0 - tmp2) << CONST_BITS;
254
255 /* Odd part */
256 /* Same rotation as in the even part of the 8x8 LL&M IDCT */
257
258 z2 = (int) wsptr[1];
259 z3 = (int) wsptr[3];
260
261 z1 = MULTIPLY16(z2 + z3, FIX_0_541196100);
262 tmp0 = z1 + MULTIPLY16(z3, - FIX_1_847759065);
263 tmp2 = z1 + MULTIPLY16(z2, FIX_0_765366865);
264
265 /* Final output stage */
266
267 outptr[0] = range_limit((int) DESCALE(tmp10 + tmp2,
268 CONST_BITS+PASS1_BITS+3));
269 outptr[3] = range_limit((int) DESCALE(tmp10 - tmp2,
270 CONST_BITS+PASS1_BITS+3));
271 outptr[1] = range_limit((int) DESCALE(tmp12 + tmp0,
272 CONST_BITS+PASS1_BITS+3));
273 outptr[2] = range_limit((int) DESCALE(tmp12 - tmp0,
274 CONST_BITS+PASS1_BITS+3));
275
276 wsptr += 4; /* advance pointer to next row */
277 }
278}
279
280
281
282/*
283* Perform dequantization and inverse DCT on one block of coefficients.
284*/
285void idct8x8(unsigned char* p_byte, int* inptr, int* quantptr, int skip_line)
286{
287 long tmp0, tmp1, tmp2, tmp3;
288 long tmp10, tmp11, tmp12, tmp13;
289 long z1, z2, z3, z4, z5;
290 int * wsptr;
291 unsigned char* outptr;
292 int ctr;
293 int workspace[64]; /* buffers data between passes */
294
295 /* Pass 1: process columns from input, store into work array. */
296 /* Note results are scaled up by sqrt(8) compared to a true IDCT; */
297 /* furthermore, we scale the results by 2**PASS1_BITS. */
298
299 wsptr = workspace;
300 for (ctr = 8; ctr > 0; ctr--)
301 {
302 /* Due to quantization, we will usually find that many of the input
303 * coefficients are zero, especially the AC terms. We can exploit this
304 * by short-circuiting the IDCT calculation for any column in which all
305 * the AC terms are zero. In that case each output is equal to the
306 * DC coefficient (with scale factor as needed).
307 * With typical images and quantization tables, half or more of the
308 * column DCT calculations can be simplified this way.
309 */
310
311 if ((inptr[8*1] | inptr[8*2] | inptr[8*3]
312 | inptr[8*4] | inptr[8*5] | inptr[8*6] | inptr[8*7]) == 0)
313 {
314 /* AC terms all zero */
315 int dcval = DEQUANTIZE(inptr[8*0], quantptr[8*0]) << PASS1_BITS;
316
317 wsptr[8*0] = wsptr[8*1] = wsptr[8*2] = wsptr[8*3] = wsptr[8*4]
318 = wsptr[8*5] = wsptr[8*6] = wsptr[8*7] = dcval;
319 inptr++; /* advance pointers to next column */
320 quantptr++;
321 wsptr++;
322 continue;
323 }
324
325 /* Even part: reverse the even part of the forward DCT. */
326 /* The rotator is sqrt(2)*c(-6). */
327
328 z2 = DEQUANTIZE(inptr[8*2], quantptr[8*2]);
329 z3 = DEQUANTIZE(inptr[8*6], quantptr[8*6]);
330
331 z1 = MULTIPLY16(z2 + z3, FIX_0_541196100);
332 tmp2 = z1 + MULTIPLY16(z3, - FIX_1_847759065);
333 tmp3 = z1 + MULTIPLY16(z2, FIX_0_765366865);
334
335 z2 = DEQUANTIZE(inptr[8*0], quantptr[8*0]);
336 z3 = DEQUANTIZE(inptr[8*4], quantptr[8*4]);
337
338 tmp0 = (z2 + z3) << CONST_BITS;
339 tmp1 = (z2 - z3) << CONST_BITS;
340
341 tmp10 = tmp0 + tmp3;
342 tmp13 = tmp0 - tmp3;
343 tmp11 = tmp1 + tmp2;
344 tmp12 = tmp1 - tmp2;
345
346 /* Odd part per figure 8; the matrix is unitary and hence its
347 transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */
348
349 tmp0 = DEQUANTIZE(inptr[8*7], quantptr[8*7]);
350 tmp1 = DEQUANTIZE(inptr[8*5], quantptr[8*5]);
351 tmp2 = DEQUANTIZE(inptr[8*3], quantptr[8*3]);
352 tmp3 = DEQUANTIZE(inptr[8*1], quantptr[8*1]);
353
354 z1 = tmp0 + tmp3;
355 z2 = tmp1 + tmp2;
356 z3 = tmp0 + tmp2;
357 z4 = tmp1 + tmp3;
358 z5 = MULTIPLY16(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
359
360 tmp0 = MULTIPLY16(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
361 tmp1 = MULTIPLY16(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
362 tmp2 = MULTIPLY16(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
363 tmp3 = MULTIPLY16(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
364 z1 = MULTIPLY16(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
365 z2 = MULTIPLY16(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
366 z3 = MULTIPLY16(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
367 z4 = MULTIPLY16(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
368
369 z3 += z5;
370 z4 += z5;
371
372 tmp0 += z1 + z3;
373 tmp1 += z2 + z4;
374 tmp2 += z2 + z3;
375 tmp3 += z1 + z4;
376
377 /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
378
379 wsptr[8*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
380 wsptr[8*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
381 wsptr[8*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
382 wsptr[8*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
383 wsptr[8*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
384 wsptr[8*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
385 wsptr[8*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
386 wsptr[8*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
387
388 inptr++; /* advance pointers to next column */
389 quantptr++;
390 wsptr++;
391 }
392
393 /* Pass 2: process rows from work array, store into output array. */
394 /* Note that we must descale the results by a factor of 8 == 2**3, */
395 /* and also undo the PASS1_BITS scaling. */
396
397 wsptr = workspace;
398 for (ctr = 0; ctr < 8; ctr++)
399 {
400 outptr = p_byte + (ctr*skip_line);
401 /* Rows of zeroes can be exploited in the same way as we did with columns.
402 * However, the column calculation has created many nonzero AC terms, so
403 * the simplification applies less often (typically 5% to 10% of the time).
404 * On machines with very fast multiplication, it's possible that the
405 * test takes more time than it's worth. In that case this section
406 * may be commented out.
407 */
408
409#ifndef NO_ZERO_ROW_TEST
410 if ((wsptr[1] | wsptr[2] | wsptr[3]
411 | wsptr[4] | wsptr[5] | wsptr[6] | wsptr[7]) == 0)
412 {
413 /* AC terms all zero */
414 unsigned char dcval = range_limit((int) DESCALE((long) wsptr[0],
415 PASS1_BITS+3));
416
417 outptr[0] = dcval;
418 outptr[1] = dcval;
419 outptr[2] = dcval;
420 outptr[3] = dcval;
421 outptr[4] = dcval;
422 outptr[5] = dcval;
423 outptr[6] = dcval;
424 outptr[7] = dcval;
425
426 wsptr += 8; /* advance pointer to next row */
427 continue;
428 }
429#endif
430
431 /* Even part: reverse the even part of the forward DCT. */
432 /* The rotator is sqrt(2)*c(-6). */
433
434 z2 = (long) wsptr[2];
435 z3 = (long) wsptr[6];
436
437 z1 = MULTIPLY16(z2 + z3, FIX_0_541196100);
438 tmp2 = z1 + MULTIPLY16(z3, - FIX_1_847759065);
439 tmp3 = z1 + MULTIPLY16(z2, FIX_0_765366865);
440
441 tmp0 = ((long) wsptr[0] + (long) wsptr[4]) << CONST_BITS;
442 tmp1 = ((long) wsptr[0] - (long) wsptr[4]) << CONST_BITS;
443
444 tmp10 = tmp0 + tmp3;
445 tmp13 = tmp0 - tmp3;
446 tmp11 = tmp1 + tmp2;
447 tmp12 = tmp1 - tmp2;
448
449 /* Odd part per figure 8; the matrix is unitary and hence its
450 * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */
451
452 tmp0 = (long) wsptr[7];
453 tmp1 = (long) wsptr[5];
454 tmp2 = (long) wsptr[3];
455 tmp3 = (long) wsptr[1];
456
457 z1 = tmp0 + tmp3;
458 z2 = tmp1 + tmp2;
459 z3 = tmp0 + tmp2;
460 z4 = tmp1 + tmp3;
461 z5 = MULTIPLY16(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
462
463 tmp0 = MULTIPLY16(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
464 tmp1 = MULTIPLY16(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
465 tmp2 = MULTIPLY16(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
466 tmp3 = MULTIPLY16(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
467 z1 = MULTIPLY16(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
468 z2 = MULTIPLY16(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
469 z3 = MULTIPLY16(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
470 z4 = MULTIPLY16(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
471
472 z3 += z5;
473 z4 += z5;
474
475 tmp0 += z1 + z3;
476 tmp1 += z2 + z4;
477 tmp2 += z2 + z3;
478 tmp3 += z1 + z4;
479
480 /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
481
482 outptr[0] = range_limit((int) DESCALE(tmp10 + tmp3,
483 CONST_BITS+PASS1_BITS+3));
484 outptr[7] = range_limit((int) DESCALE(tmp10 - tmp3,
485 CONST_BITS+PASS1_BITS+3));
486 outptr[1] = range_limit((int) DESCALE(tmp11 + tmp2,
487 CONST_BITS+PASS1_BITS+3));
488 outptr[6] = range_limit((int) DESCALE(tmp11 - tmp2,
489 CONST_BITS+PASS1_BITS+3));
490 outptr[2] = range_limit((int) DESCALE(tmp12 + tmp1,
491 CONST_BITS+PASS1_BITS+3));
492 outptr[5] = range_limit((int) DESCALE(tmp12 - tmp1,
493 CONST_BITS+PASS1_BITS+3));
494 outptr[3] = range_limit((int) DESCALE(tmp13 + tmp0,
495 CONST_BITS+PASS1_BITS+3));
496 outptr[4] = range_limit((int) DESCALE(tmp13 - tmp0,
497 CONST_BITS+PASS1_BITS+3));
498
499 wsptr += 8; /* advance pointer to next row */
500 }
501}
502
503
504
505/* JPEG decoder implementation */
506
507/* Preprocess the JPEG JFIF file */
508int process_markers(unsigned char* p_src, long size, struct jpeg* p_jpeg)
509{
510 unsigned char* p_bytes = p_src;
511 int marker_size; /* variable length of marker segment */
512 int i, j, n;
513 int ret = 0; /* returned flags */
514
515 p_jpeg->p_entropy_end = p_src + size;
516
517 while (p_src < p_bytes + size)
518 {
519 if (*p_src++ != 0xFF) /* no marker? */
520 {
521 p_src--; /* it's image data, put it back */
522 p_jpeg->p_entropy_data = p_src;
523 break; /* exit marker processing */
524 }
525
526 switch (*p_src++)
527 {
528 case 0xFF: /* Fill byte */
529 ret |= FILL_FF;
530 case 0x00: /* Zero stuffed byte - entropy data */
531 p_src--; /* put it back */
532 continue;
533
534 case 0xC0: /* SOF Huff - Baseline DCT */
535 {
536 ret |= SOF0;
537 marker_size = *p_src++ << 8; /* Highbyte */
538 marker_size |= *p_src++; /* Lowbyte */
539 n = *p_src++; /* sample precision (= 8 or 12) */
540 if (n != 8)
541 {
542 return(-1); /* Unsupported sample precision */
543 }
544 p_jpeg->y_size = *p_src++ << 8; /* Highbyte */
545 p_jpeg->y_size |= *p_src++; /* Lowbyte */
546 p_jpeg->x_size = *p_src++ << 8; /* Highbyte */
547 p_jpeg->x_size |= *p_src++; /* Lowbyte */
548
549 n = (marker_size-2-6)/3;
550 if (*p_src++ != n || (n != 1 && n != 3))
551 {
552 return(-2); /* Unsupported SOF0 component specification */
553 }
554 for (i=0; i<n; i++)
555 {
556 p_jpeg->frameheader[i].ID = *p_src++; /* Component info */
557 p_jpeg->frameheader[i].horizontal_sampling = *p_src >> 4;
558 p_jpeg->frameheader[i].vertical_sampling = *p_src++ & 0x0F;
559 p_jpeg->frameheader[i].quanttable_select = *p_src++;
560 if (p_jpeg->frameheader[i].horizontal_sampling > 2
561 || p_jpeg->frameheader[i].vertical_sampling > 2)
562 return -3; /* Unsupported SOF0 subsampling */
563 }
564 p_jpeg->blocks = n;
565 }
566 break;
567
568 case 0xC1: /* SOF Huff - Extended sequential DCT*/
569 case 0xC2: /* SOF Huff - Progressive DCT*/
570 case 0xC3: /* SOF Huff - Spatial (sequential) lossless*/
571 case 0xC5: /* SOF Huff - Differential sequential DCT*/
572 case 0xC6: /* SOF Huff - Differential progressive DCT*/
573 case 0xC7: /* SOF Huff - Differential spatial*/
574 case 0xC8: /* SOF Arith - Reserved for JPEG extensions*/
575 case 0xC9: /* SOF Arith - Extended sequential DCT*/
576 case 0xCA: /* SOF Arith - Progressive DCT*/
577 case 0xCB: /* SOF Arith - Spatial (sequential) lossless*/
578 case 0xCD: /* SOF Arith - Differential sequential DCT*/
579 case 0xCE: /* SOF Arith - Differential progressive DCT*/
580 case 0xCF: /* SOF Arith - Differential spatial*/
581 {
582 return (-4); /* other DCT model than baseline not implemented */
583 }
584
585 case 0xC4: /* Define Huffman Table(s) */
586 {
587 unsigned char* p_temp;
588
589 ret |= DHT;
590 marker_size = *p_src++ << 8; /* Highbyte */
591 marker_size |= *p_src++; /* Lowbyte */
592
593 p_temp = p_src;
594 while (p_src < p_temp+marker_size-2-17) /* another table */
595 {
596 int sum = 0;
597 i = *p_src & 0x0F; /* table index */
598 if (i > 1)
599 {
600 return (-5); /* Huffman table index out of range */
601 }
602 else if (*p_src++ & 0xF0) /* AC table */
603 {
604 for (j=0; j<16; j++)
605 {
606 sum += *p_src;
607 p_jpeg->hufftable[i].huffmancodes_ac[j] = *p_src++;
608 }
609 if(16 + sum > AC_LEN)
610 return -10; /* longer than allowed */
611
612 for (; j < 16 + sum; j++)
613 p_jpeg->hufftable[i].huffmancodes_ac[j] = *p_src++;
614 }
615 else /* DC table */
616 {
617 for (j=0; j<16; j++)
618 {
619 sum += *p_src;
620 p_jpeg->hufftable[i].huffmancodes_dc[j] = *p_src++;
621 }
622 if(16 + sum > DC_LEN)
623 return -11; /* longer than allowed */
624
625 for (; j < 16 + sum; j++)
626 p_jpeg->hufftable[i].huffmancodes_dc[j] = *p_src++;
627 }
628 } /* while */
629 p_src = p_temp+marker_size - 2; /* skip possible residue */
630 }
631 break;
632
633 case 0xCC: /* Define Arithmetic coding conditioning(s) */
634 return(-6); /* Arithmetic coding not supported */
635
636 case 0xD8: /* Start of Image */
637 case 0xD9: /* End of Image */
638 case 0x01: /* for temp private use arith code */
639 break; /* skip parameterless marker */
640
641
642 case 0xDA: /* Start of Scan */
643 {
644 ret |= SOS;
645 marker_size = *p_src++ << 8; /* Highbyte */
646 marker_size |= *p_src++; /* Lowbyte */
647
648 n = (marker_size-2-1-3)/2;
649 if (*p_src++ != n || (n != 1 && n != 3))
650 {
651 return (-7); /* Unsupported SOS component specification */
652 }
653 for (i=0; i<n; i++)
654 {
655 p_jpeg->scanheader[i].ID = *p_src++;
656 p_jpeg->scanheader[i].DC_select = *p_src >> 4;
657 p_jpeg->scanheader[i].AC_select = *p_src++ & 0x0F;
658 }
659 p_src += 3; /* skip spectral information */
660 }
661 break;
662
663 case 0xDB: /* Define quantization Table(s) */
664 {
665 ret |= DQT;
666 marker_size = *p_src++ << 8; /* Highbyte */
667 marker_size |= *p_src++; /* Lowbyte */
668 n = (marker_size-2)/(QUANT_TABLE_LENGTH+1); /* # of tables */
669 for (i=0; i<n; i++)
670 {
671 int id = *p_src++; /* ID */
672 if (id >= 4)
673 {
674 return (-8); /* Unsupported quantization table */
675 }
676 /* Read Quantisation table: */
677 for (j=0; j<QUANT_TABLE_LENGTH; j++)
678 p_jpeg->quanttable[id][j] = *p_src++;
679 }
680 }
681 break;
682
683 case 0xDD: /* Define Restart Interval */
684 {
685 marker_size = *p_src++ << 8; /* Highbyte */
686 marker_size |= *p_src++; /* Lowbyte */
687 p_jpeg->restart_interval = *p_src++ << 8; /* Highbyte */
688 p_jpeg->restart_interval |= *p_src++; /* Lowbyte */
689 p_src += marker_size-4; /* skip segment */
690 }
691 break;
692
693 case 0xDC: /* Define Number of Lines */
694 case 0xDE: /* Define Hierarchical progression */
695 case 0xDF: /* Expand Reference Component(s) */
696 case 0xE0: /* Application Field 0*/
697 case 0xE1: /* Application Field 1*/
698 case 0xE2: /* Application Field 2*/
699 case 0xE3: /* Application Field 3*/
700 case 0xE4: /* Application Field 4*/
701 case 0xE5: /* Application Field 5*/
702 case 0xE6: /* Application Field 6*/
703 case 0xE7: /* Application Field 7*/
704 case 0xE8: /* Application Field 8*/
705 case 0xE9: /* Application Field 9*/
706 case 0xEA: /* Application Field 10*/
707 case 0xEB: /* Application Field 11*/
708 case 0xEC: /* Application Field 12*/
709 case 0xED: /* Application Field 13*/
710 case 0xEE: /* Application Field 14*/
711 case 0xEF: /* Application Field 15*/
712 case 0xFE: /* Comment */
713 {
714 marker_size = *p_src++ << 8; /* Highbyte */
715 marker_size |= *p_src++; /* Lowbyte */
716 p_src += marker_size-2; /* skip segment */
717 }
718 break;
719
720 case 0xF0: /* Reserved for JPEG extensions */
721 case 0xF1: /* Reserved for JPEG extensions */
722 case 0xF2: /* Reserved for JPEG extensions */
723 case 0xF3: /* Reserved for JPEG extensions */
724 case 0xF4: /* Reserved for JPEG extensions */
725 case 0xF5: /* Reserved for JPEG extensions */
726 case 0xF6: /* Reserved for JPEG extensions */
727 case 0xF7: /* Reserved for JPEG extensions */
728 case 0xF8: /* Reserved for JPEG extensions */
729 case 0xF9: /* Reserved for JPEG extensions */
730 case 0xFA: /* Reserved for JPEG extensions */
731 case 0xFB: /* Reserved for JPEG extensions */
732 case 0xFC: /* Reserved for JPEG extensions */
733 case 0xFD: /* Reserved for JPEG extensions */
734 case 0x02: /* Reserved */
735 default:
736 return (-9); /* Unknown marker */
737 } /* switch */
738 } /* while */
739
740 return (ret); /* return flags with seen markers */
741}
742
743
744void default_huff_tbl(struct jpeg* p_jpeg)
745{
746 static const struct huffman_table luma_table =
747 {
748 {
749 0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,
750 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B
751 },
752 {
753 0x00,0x02,0x01,0x03,0x03,0x02,0x04,0x03,0x05,0x05,0x04,0x04,0x00,0x00,0x01,0x7D,
754 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,
755 0x22,0x71,0x14,0x32,0x81,0x91,0xA1,0x08,0x23,0x42,0xB1,0xC1,0x15,0x52,0xD1,0xF0,
756 0x24,0x33,0x62,0x72,0x82,0x09,0x0A,0x16,0x17,0x18,0x19,0x1A,0x25,0x26,0x27,0x28,
757 0x29,0x2A,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,
758 0x4A,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,
759 0x6A,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
760 0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,
761 0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xC2,0xC3,0xC4,0xC5,
762 0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xE1,0xE2,
763 0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,
764 0xF9,0xFA
765 }
766 };
767
768 static const struct huffman_table chroma_table =
769 {
770 {
771 0x00,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,
772 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B
773 },
774 {
775 0x00,0x02,0x01,0x02,0x04,0x04,0x03,0x04,0x07,0x05,0x04,0x04,0x00,0x01,0x02,0x77,
776 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,
777 0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xA1,0xB1,0xC1,0x09,0x23,0x33,0x52,0xF0,
778 0x15,0x62,0x72,0xD1,0x0A,0x16,0x24,0x34,0xE1,0x25,0xF1,0x17,0x18,0x19,0x1A,0x26,
779 0x27,0x28,0x29,0x2A,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,
780 0x49,0x4A,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,
781 0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x82,0x83,0x84,0x85,0x86,0x87,
782 0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5,
783 0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xC2,0xC3,
784 0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,
785 0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,
786 0xF9,0xFA
787 }
788 };
789
790 MEMCPY(&p_jpeg->hufftable[0], &luma_table, sizeof(luma_table));
791 MEMCPY(&p_jpeg->hufftable[1], &chroma_table, sizeof(chroma_table));
792
793 return;
794}
795
796/* Compute the derived values for a Huffman table */
797void fix_huff_tbl(int* htbl, struct derived_tbl* dtbl)
798{
799 int p, i, l, si;
800 int lookbits, ctr;
801 char huffsize[257];
802 unsigned int huffcode[257];
803 unsigned int code;
804
805 dtbl->pub = htbl; /* fill in back link */
806
807 /* Figure C.1: make table of Huffman code length for each symbol */
808 /* Note that this is in code-length order. */
809
810 p = 0;
811 for (l = 1; l <= 16; l++)
812 { /* all possible code length */
813 for (i = 1; i <= (int) htbl[l-1]; i++) /* all codes per length */
814 huffsize[p++] = (char) l;
815 }
816 huffsize[p] = 0;
817
818 /* Figure C.2: generate the codes themselves */
819 /* Note that this is in code-length order. */
820
821 code = 0;
822 si = huffsize[0];
823 p = 0;
824 while (huffsize[p])
825 {
826 while (((int) huffsize[p]) == si)
827 {
828 huffcode[p++] = code;
829 code++;
830 }
831 code <<= 1;
832 si++;
833 }
834
835 /* Figure F.15: generate decoding tables for bit-sequential decoding */
836
837 p = 0;
838 for (l = 1; l <= 16; l++)
839 {
840 if (htbl[l-1])
841 {
842 dtbl->valptr[l] = p; /* huffval[] index of 1st symbol of code length l */
843 dtbl->mincode[l] = huffcode[p]; /* minimum code of length l */
844 p += htbl[l-1];
845 dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */
846 }
847 else
848 {
849 dtbl->maxcode[l] = -1; /* -1 if no codes of this length */
850 }
851 }
852 dtbl->maxcode[17] = 0xFFFFFL; /* ensures huff_DECODE terminates */
853
854 /* Compute lookahead tables to speed up decoding.
855 * First we set all the table entries to 0, indicating "too long";
856 * then we iterate through the Huffman codes that are short enough and
857 * fill in all the entries that correspond to bit sequences starting
858 * with that code.
859 */
860
861 MEMSET(dtbl->look_nbits, 0, sizeof(dtbl->look_nbits));
862
863 p = 0;
864 for (l = 1; l <= HUFF_LOOKAHEAD; l++)
865 {
866 for (i = 1; i <= (int) htbl[l-1]; i++, p++)
867 {
868 /* l = current code's length, p = its index in huffcode[] & huffval[]. */
869 /* Generate left-justified code followed by all possible bit sequences */
870 lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l);
871 for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--)
872 {
873 dtbl->look_nbits[lookbits] = l;
874 dtbl->look_sym[lookbits] = htbl[16+p];
875 lookbits++;
876 }
877 }
878 }
879}
880
881
882/* zag[i] is the natural-order position of the i'th element of zigzag order.
883 * If the incoming data is corrupted, decode_mcu could attempt to
884 * reference values beyond the end of the array. To avoid a wild store,
885 * we put some extra zeroes after the real entries.
886 */
887static const int zag[] =
888{
889 0, 1, 8, 16, 9, 2, 3, 10,
890 17, 24, 32, 25, 18, 11, 4, 5,
891 12, 19, 26, 33, 40, 48, 41, 34,
892 27, 20, 13, 6, 7, 14, 21, 28,
893 35, 42, 49, 56, 57, 50, 43, 36,
894 29, 22, 15, 23, 30, 37, 44, 51,
895 58, 59, 52, 45, 38, 31, 39, 46,
896 53, 60, 61, 54, 47, 55, 62, 63,
897 0, 0, 0, 0, 0, 0, 0, 0, /* extra entries in case k>63 below */
898 0, 0, 0, 0, 0, 0, 0, 0
899};
900
901void build_lut(struct jpeg* p_jpeg)
902{
903 int i;
904 fix_huff_tbl(p_jpeg->hufftable[0].huffmancodes_dc,
905 &p_jpeg->dc_derived_tbls[0]);
906 fix_huff_tbl(p_jpeg->hufftable[0].huffmancodes_ac,
907 &p_jpeg->ac_derived_tbls[0]);
908 fix_huff_tbl(p_jpeg->hufftable[1].huffmancodes_dc,
909 &p_jpeg->dc_derived_tbls[1]);
910 fix_huff_tbl(p_jpeg->hufftable[1].huffmancodes_ac,
911 &p_jpeg->ac_derived_tbls[1]);
912
913 /* build the dequantization tables for the IDCT (De-ZiZagged) */
914 for (i=0; i<64; i++)
915 {
916 p_jpeg->qt_idct[0][zag[i]] = p_jpeg->quanttable[0][i];
917 p_jpeg->qt_idct[1][zag[i]] = p_jpeg->quanttable[1][i];
918 }
919
920 for (i=0; i<4; i++)
921 p_jpeg->store_pos[i] = i; /* default ordering */
922
923 /* assignments for the decoding of blocks */
924 if (p_jpeg->frameheader[0].horizontal_sampling == 2
925 && p_jpeg->frameheader[0].vertical_sampling == 1)
926 { /* 4:2:2 */
927 p_jpeg->blocks = 4;
928 p_jpeg->x_mbl = (p_jpeg->x_size+15) / 16;
929 p_jpeg->x_phys = p_jpeg->x_mbl * 16;
930 p_jpeg->y_mbl = (p_jpeg->y_size+7) / 8;
931 p_jpeg->y_phys = p_jpeg->y_mbl * 8;
932 p_jpeg->mcu_membership[0] = 0; /* Y1=Y2=0, U=1, V=2 */
933 p_jpeg->mcu_membership[1] = 0;
934 p_jpeg->mcu_membership[2] = 1;
935 p_jpeg->mcu_membership[3] = 2;
936 p_jpeg->tab_membership[0] = 0; /* DC, DC, AC, AC */
937 p_jpeg->tab_membership[1] = 0;
938 p_jpeg->tab_membership[2] = 1;
939 p_jpeg->tab_membership[3] = 1;
940 p_jpeg->subsample_x[0] = 1;
941 p_jpeg->subsample_x[1] = 2;
942 p_jpeg->subsample_x[2] = 2;
943 p_jpeg->subsample_y[0] = 1;
944 p_jpeg->subsample_y[1] = 1;
945 p_jpeg->subsample_y[2] = 1;
946 }
947 if (p_jpeg->frameheader[0].horizontal_sampling == 1
948 && p_jpeg->frameheader[0].vertical_sampling == 2)
949 { /* 4:2:2 vertically subsampled */
950 p_jpeg->store_pos[1] = 2; /* block positions are mirrored */
951 p_jpeg->store_pos[2] = 1;
952 p_jpeg->blocks = 4;
953 p_jpeg->x_mbl = (p_jpeg->x_size+7) / 8;
954 p_jpeg->x_phys = p_jpeg->x_mbl * 8;
955 p_jpeg->y_mbl = (p_jpeg->y_size+15) / 16;
956 p_jpeg->y_phys = p_jpeg->y_mbl * 16;
957 p_jpeg->mcu_membership[0] = 0; /* Y1=Y2=0, U=1, V=2 */
958 p_jpeg->mcu_membership[1] = 0;
959 p_jpeg->mcu_membership[2] = 1;
960 p_jpeg->mcu_membership[3] = 2;
961 p_jpeg->tab_membership[0] = 0; /* DC, DC, AC, AC */
962 p_jpeg->tab_membership[1] = 0;
963 p_jpeg->tab_membership[2] = 1;
964 p_jpeg->tab_membership[3] = 1;
965 p_jpeg->subsample_x[0] = 1;
966 p_jpeg->subsample_x[1] = 1;
967 p_jpeg->subsample_x[2] = 1;
968 p_jpeg->subsample_y[0] = 1;
969 p_jpeg->subsample_y[1] = 2;
970 p_jpeg->subsample_y[2] = 2;
971 }
972 else if (p_jpeg->frameheader[0].horizontal_sampling == 2
973 && p_jpeg->frameheader[0].vertical_sampling == 2)
974 { /* 4:2:0 */
975 p_jpeg->blocks = 6;
976 p_jpeg->x_mbl = (p_jpeg->x_size+15) / 16;
977 p_jpeg->x_phys = p_jpeg->x_mbl * 16;
978 p_jpeg->y_mbl = (p_jpeg->y_size+15) / 16;
979 p_jpeg->y_phys = p_jpeg->y_mbl * 16;
980 p_jpeg->mcu_membership[0] = 0;
981 p_jpeg->mcu_membership[1] = 0;
982 p_jpeg->mcu_membership[2] = 0;
983 p_jpeg->mcu_membership[3] = 0;
984 p_jpeg->mcu_membership[4] = 1;
985 p_jpeg->mcu_membership[5] = 2;
986 p_jpeg->tab_membership[0] = 0;
987 p_jpeg->tab_membership[1] = 0;
988 p_jpeg->tab_membership[2] = 0;
989 p_jpeg->tab_membership[3] = 0;
990 p_jpeg->tab_membership[4] = 1;
991 p_jpeg->tab_membership[5] = 1;
992 p_jpeg->subsample_x[0] = 1;
993 p_jpeg->subsample_x[1] = 2;
994 p_jpeg->subsample_x[2] = 2;
995 p_jpeg->subsample_y[0] = 1;
996 p_jpeg->subsample_y[1] = 2;
997 p_jpeg->subsample_y[2] = 2;
998 }
999 else if (p_jpeg->frameheader[0].horizontal_sampling == 1
1000 && p_jpeg->frameheader[0].vertical_sampling == 1)
1001 { /* 4:4:4 */
1002 /* don't overwrite p_jpeg->blocks */
1003 p_jpeg->x_mbl = (p_jpeg->x_size+7) / 8;
1004 p_jpeg->x_phys = p_jpeg->x_mbl * 8;
1005 p_jpeg->y_mbl = (p_jpeg->y_size+7) / 8;
1006 p_jpeg->y_phys = p_jpeg->y_mbl * 8;
1007 p_jpeg->mcu_membership[0] = 0;
1008 p_jpeg->mcu_membership[1] = 1;
1009 p_jpeg->mcu_membership[2] = 2;
1010 p_jpeg->tab_membership[0] = 0;
1011 p_jpeg->tab_membership[1] = 1;
1012 p_jpeg->tab_membership[2] = 1;
1013 p_jpeg->subsample_x[0] = 1;
1014 p_jpeg->subsample_x[1] = 1;
1015 p_jpeg->subsample_x[2] = 1;
1016 p_jpeg->subsample_y[0] = 1;
1017 p_jpeg->subsample_y[1] = 1;
1018 p_jpeg->subsample_y[2] = 1;
1019 }
1020 else
1021 {
1022 /* error */
1023 }
1024
1025}
1026
1027
1028/*
1029* These functions/macros provide the in-line portion of bit fetching.
1030* Use check_bit_buffer to ensure there are N bits in get_buffer
1031* before using get_bits, peek_bits, or drop_bits.
1032* check_bit_buffer(state,n,action);
1033* Ensure there are N bits in get_buffer; if suspend, take action.
1034* val = get_bits(n);
1035* Fetch next N bits.
1036* val = peek_bits(n);
1037* Fetch next N bits without removing them from the buffer.
1038* drop_bits(n);
1039* Discard next N bits.
1040* The value N should be a simple variable, not an expression, because it
1041* is evaluated multiple times.
1042*/
1043
1044INLINE void check_bit_buffer(struct bitstream* pb, int nbits)
1045{
1046 if (pb->bits_left < nbits)
1047 { /* nbits is <= 16, so I can always refill 2 bytes in this case */
1048 unsigned char byte;
1049
1050 byte = *pb->next_input_byte++;
1051 if (byte == 0xFF) /* legal marker can be byte stuffing or RSTm */
1052 { /* simplification: just skip the (one-byte) marker code */
1053 pb->next_input_byte++;
1054 }
1055 pb->get_buffer = (pb->get_buffer << 8) | byte;
1056
1057 byte = *pb->next_input_byte++;
1058 if (byte == 0xFF) /* legal marker can be byte stuffing or RSTm */
1059 { /* simplification: just skip the (one-byte) marker code */
1060 pb->next_input_byte++;
1061 }
1062 pb->get_buffer = (pb->get_buffer << 8) | byte;
1063
1064 pb->bits_left += 16;
1065 }
1066}
1067
1068INLINE int get_bits(struct bitstream* pb, int nbits)
1069{
1070 return ((int) (pb->get_buffer >> (pb->bits_left -= nbits))) & (BIT_N(nbits)-1);
1071}
1072
1073INLINE int peek_bits(struct bitstream* pb, int nbits)
1074{
1075 return ((int) (pb->get_buffer >> (pb->bits_left - nbits))) & (BIT_N(nbits)-1);
1076}
1077
1078INLINE void drop_bits(struct bitstream* pb, int nbits)
1079{
1080 pb->bits_left -= nbits;
1081}
1082
1083/* re-synchronize to entropy data (skip restart marker) */
1084void search_restart(struct bitstream* pb)
1085{
1086 pb->next_input_byte--; /* we may have overread it, taking 2 bytes */
1087 /* search for a non-byte-padding marker, has to be RSTm or EOS */
1088 while (pb->next_input_byte < pb->input_end &&
1089 (pb->next_input_byte[-2] != 0xFF || pb->next_input_byte[-1] == 0x00))
1090 {
1091 pb->next_input_byte++;
1092 }
1093 pb->bits_left = 0;
1094}
1095
1096/* Figure F.12: extend sign bit. */
1097#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
1098
1099static const int extend_test[16] = /* entry n is 2**(n-1) */
1100{
1101 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
1102 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000
1103};
1104
1105static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
1106{
1107 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
1108 ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
1109 ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
1110 ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1
1111};
1112
1113/* Decode a single value */
1114INLINE int huff_decode_dc(struct bitstream* bs, struct derived_tbl* tbl)
1115{
1116 int nb, look, s, r;
1117
1118 check_bit_buffer(bs, HUFF_LOOKAHEAD);
1119 look = peek_bits(bs, HUFF_LOOKAHEAD);
1120 if ((nb = tbl->look_nbits[look]) != 0)
1121 {
1122 drop_bits(bs, nb);
1123 s = tbl->look_sym[look];
1124 check_bit_buffer(bs, s);
1125 r = get_bits(bs, s);
1126 s = HUFF_EXTEND(r, s);
1127 }
1128 else
1129 { /* slow_DECODE(s, HUFF_LOOKAHEAD+1)) < 0); */
1130 long code;
1131 nb=HUFF_LOOKAHEAD+1;
1132 check_bit_buffer(bs, nb);
1133 code = get_bits(bs, nb);
1134 while (code > tbl->maxcode[nb])
1135 {
1136 code <<= 1;
1137 check_bit_buffer(bs, 1);
1138 code |= get_bits(bs, 1);
1139 nb++;
1140 }
1141 if (nb > 16) /* error in Huffman */
1142 {
1143 s=0; /* fake a zero, this is most safe */
1144 }
1145 else
1146 {
1147 s = tbl->pub[16 + tbl->valptr[nb] + ((int) (code - tbl->mincode[nb])) ];
1148 check_bit_buffer(bs, s);
1149 r = get_bits(bs, s);
1150 s = HUFF_EXTEND(r, s);
1151 }
1152 } /* end slow decode */
1153 return s;
1154}
1155
1156INLINE int huff_decode_ac(struct bitstream* bs, struct derived_tbl* tbl)
1157{
1158 int nb, look, s;
1159
1160 check_bit_buffer(bs, HUFF_LOOKAHEAD);
1161 look = peek_bits(bs, HUFF_LOOKAHEAD);
1162 if ((nb = tbl->look_nbits[look]) != 0)
1163 {
1164 drop_bits(bs, nb);
1165 s = tbl->look_sym[look];
1166 }
1167 else
1168 { /* slow_DECODE(s, HUFF_LOOKAHEAD+1)) < 0); */
1169 long code;
1170 nb=HUFF_LOOKAHEAD+1;
1171 check_bit_buffer(bs, nb);
1172 code = get_bits(bs, nb);
1173 while (code > tbl->maxcode[nb])
1174 {
1175 code <<= 1;
1176 check_bit_buffer(bs, 1);
1177 code |= get_bits(bs, 1);
1178 nb++;
1179 }
1180 if (nb > 16) /* error in Huffman */
1181 {
1182 s=0; /* fake a zero, this is most safe */
1183 }
1184 else
1185 {
1186 s = tbl->pub[16 + tbl->valptr[nb] + ((int) (code - tbl->mincode[nb])) ];
1187 }
1188 } /* end slow decode */
1189 return s;
1190}
1191
1192
1193#ifdef HAVE_LCD_COLOR
1194
1195/* JPEG decoder variant for YUV decoding, into 3 different planes */
1196/* Note: it keeps the original color subsampling, even if resized. */
1197int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel[3],
1198 int downscale, void (*pf_progress)(int current, int total))
1199{
1200 struct bitstream bs; /* bitstream "object" */
1201 int block[64]; /* decoded DCT coefficients */
1202
1203 int width, height;
1204 int skip_line[3]; /* bytes from one line to the next (skip_line) */
1205 int skip_strip[3], skip_mcu[3]; /* bytes to next DCT row / column */
1206
1207 int i, x, y; /* loop counter */
1208
1209 unsigned char* p_line[3] = {p_pixel[0], p_pixel[1], p_pixel[2]};
1210 unsigned char* p_byte[3]; /* bitmap pointer */
1211
1212 void (*pf_idct)(unsigned char*, int*, int*, int); /* selected IDCT */
1213 int k_need; /* AC coefficients needed up to here */
1214 int zero_need; /* init the block with this many zeros */
1215
1216 int last_dc_val[3] = {0, 0, 0}; /* or 128 for chroma? */
1217 int store_offs[4]; /* memory offsets: order of Y11 Y12 Y21 Y22 U V */
1218 int restart = p_jpeg->restart_interval; /* MCUs until restart marker */
1219
1220 /* pick the IDCT we want, determine how to work with coefs */
1221 if (downscale == 1)
1222 {
1223 pf_idct = idct8x8;
1224 k_need = 64; /* all */
1225 zero_need = 63; /* all */
1226 }
1227 else if (downscale == 2)
1228 {
1229 pf_idct = idct4x4;
1230 k_need = 25; /* this far in zig-zag to cover 4*4 */
1231 zero_need = 27; /* clear this far in linear order */
1232 }
1233 else if (downscale == 4)
1234 {
1235 pf_idct = idct2x2;
1236 k_need = 5; /* this far in zig-zag to cover 2*2 */
1237 zero_need = 9; /* clear this far in linear order */
1238 }
1239 else if (downscale == 8)
1240 {
1241 pf_idct = idct1x1;
1242 k_need = 0; /* no AC, not needed */
1243 zero_need = 0; /* no AC, not needed */
1244 }
1245 else return -1; /* not supported */
1246
1247 /* init bitstream, fake a restart to make it start */
1248 bs.next_input_byte = p_jpeg->p_entropy_data;
1249 bs.bits_left = 0;
1250 bs.input_end = p_jpeg->p_entropy_end;
1251
1252 width = p_jpeg->x_phys / downscale;
1253 height = p_jpeg->y_phys / downscale;
1254 for (i=0; i<3; i++) /* calculate some strides */
1255 {
1256 skip_line[i] = width / p_jpeg->subsample_x[i];
1257 skip_strip[i] = skip_line[i]
1258 * (height / p_jpeg->y_mbl) / p_jpeg->subsample_y[i];
1259 skip_mcu[i] = width/p_jpeg->x_mbl / p_jpeg->subsample_x[i];
1260 }
1261
1262 /* prepare offsets about where to store the different blocks */
1263 store_offs[p_jpeg->store_pos[0]] = 0;
1264 store_offs[p_jpeg->store_pos[1]] = 8 / downscale; /* to the right */
1265 store_offs[p_jpeg->store_pos[2]] = width * 8 / downscale; /* below */
1266 store_offs[p_jpeg->store_pos[3]] = store_offs[1] + store_offs[2]; /* r+b */
1267
1268 for(y=0; y<p_jpeg->y_mbl && bs.next_input_byte <= bs.input_end; y++)
1269 {
1270 for (i=0; i<3; i++) /* scan line init */
1271 {
1272 p_byte[i] = p_line[i];
1273 p_line[i] += skip_strip[i];
1274 }
1275 for (x=0; x<p_jpeg->x_mbl; x++)
1276 {
1277 int blkn;
1278
1279 /* Outer loop handles each block in the MCU */
1280 for (blkn = 0; blkn < p_jpeg->blocks; blkn++)
1281 { /* Decode a single block's worth of coefficients */
1282 int k = 1; /* coefficient index */
1283 int s, r; /* huffman values */
1284 int ci = p_jpeg->mcu_membership[blkn]; /* component index */
1285 int ti = p_jpeg->tab_membership[blkn]; /* table index */
1286 struct derived_tbl* dctbl = &p_jpeg->dc_derived_tbls[ti];
1287 struct derived_tbl* actbl = &p_jpeg->ac_derived_tbls[ti];
1288
1289 /* Section F.2.2.1: decode the DC coefficient difference */
1290 s = huff_decode_dc(&bs, dctbl);
1291
1292 last_dc_val[ci] += s;
1293 block[0] = last_dc_val[ci]; /* output it (assumes zag[0] = 0) */
1294
1295 /* coefficient buffer must be cleared */
1296 MEMSET(block+1, 0, zero_need*sizeof(block[0]));
1297
1298 /* Section F.2.2.2: decode the AC coefficients */
1299 for (; k < k_need; k++)
1300 {
1301 s = huff_decode_ac(&bs, actbl);
1302 r = s >> 4;
1303 s &= 15;
1304
1305 if (s)
1306 {
1307 k += r;
1308 check_bit_buffer(&bs, s);
1309 r = get_bits(&bs, s);
1310 block[zag[k]] = HUFF_EXTEND(r, s);
1311 }
1312 else
1313 {
1314 if (r != 15)
1315 {
1316 k = 64;
1317 break;
1318 }
1319 k += r;
1320 }
1321 } /* for k */
1322 /* In this path we just discard the values */
1323 for (; k < 64; k++)
1324 {
1325 s = huff_decode_ac(&bs, actbl);
1326 r = s >> 4;
1327 s &= 15;
1328
1329 if (s)
1330 {
1331 k += r;
1332 check_bit_buffer(&bs, s);
1333 drop_bits(&bs, s);
1334 }
1335 else
1336 {
1337 if (r != 15)
1338 break;
1339 k += r;
1340 }
1341 } /* for k */
1342
1343 if (ci == 0)
1344 { /* Y component needs to bother about block store */
1345 pf_idct(p_byte[0]+store_offs[blkn], block,
1346 p_jpeg->qt_idct[ti], skip_line[0]);
1347 }
1348 else
1349 { /* chroma */
1350 pf_idct(p_byte[ci], block, p_jpeg->qt_idct[ti],
1351 skip_line[ci]);
1352 }
1353 } /* for blkn */
1354 p_byte[0] += skip_mcu[0]; /* unrolled for (i=0; i<3; i++) loop */
1355 p_byte[1] += skip_mcu[1];
1356 p_byte[2] += skip_mcu[2];
1357 if (p_jpeg->restart_interval && --restart == 0)
1358 { /* if a restart marker is due: */
1359 restart = p_jpeg->restart_interval; /* count again */
1360 search_restart(&bs); /* align the bitstream */
1361 last_dc_val[0] = last_dc_val[1] =
1362 last_dc_val[2] = 0; /* reset decoder */
1363 }
1364 } /* for x */
1365 if (pf_progress != NULL)
1366 pf_progress(y, p_jpeg->y_mbl-1); /* notify about decoding progress */
1367 } /* for y */
1368
1369 return 0; /* success */
1370}
1371#else /* !HAVE_LCD_COLOR */
1372
1373/* a JPEG decoder specialized in decoding only the luminance (b&w) */
1374int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel[1], int downscale,
1375 void (*pf_progress)(int current, int total))
1376{
1377 struct bitstream bs; /* bitstream "object" */
1378 int block[64]; /* decoded DCT coefficients */
1379
1380 int width, height;
1381 int skip_line; /* bytes from one line to the next (skip_line) */
1382 int skip_strip, skip_mcu; /* bytes to next DCT row / column */
1383
1384 int x, y; /* loop counter */
1385
1386 unsigned char* p_line = p_pixel[0];
1387 unsigned char* p_byte; /* bitmap pointer */
1388
1389 void (*pf_idct)(unsigned char*, int*, int*, int); /* selected IDCT */
1390 int k_need; /* AC coefficients needed up to here */
1391 int zero_need; /* init the block with this many zeros */
1392
1393 int last_dc_val = 0;
1394 int store_offs[4]; /* memory offsets: order of Y11 Y12 Y21 Y22 U V */
1395 int restart = p_jpeg->restart_interval; /* MCUs until restart marker */
1396
1397 /* pick the IDCT we want, determine how to work with coefs */
1398 if (downscale == 1)
1399 {
1400 pf_idct = idct8x8;
1401 k_need = 64; /* all */
1402 zero_need = 63; /* all */
1403 }
1404 else if (downscale == 2)
1405 {
1406 pf_idct = idct4x4;
1407 k_need = 25; /* this far in zig-zag to cover 4*4 */
1408 zero_need = 27; /* clear this far in linear order */
1409 }
1410 else if (downscale == 4)
1411 {
1412 pf_idct = idct2x2;
1413 k_need = 5; /* this far in zig-zag to cover 2*2 */
1414 zero_need = 9; /* clear this far in linear order */
1415 }
1416 else if (downscale == 8)
1417 {
1418 pf_idct = idct1x1;
1419 k_need = 0; /* no AC, not needed */
1420 zero_need = 0; /* no AC, not needed */
1421 }
1422 else return -1; /* not supported */
1423
1424 /* init bitstream, fake a restart to make it start */
1425 bs.next_input_byte = p_jpeg->p_entropy_data;
1426 bs.bits_left = 0;
1427 bs.input_end = p_jpeg->p_entropy_end;
1428
1429 width = p_jpeg->x_phys / downscale;
1430 height = p_jpeg->y_phys / downscale;
1431 skip_line = width;
1432 skip_strip = skip_line * (height / p_jpeg->y_mbl);
1433 skip_mcu = (width/p_jpeg->x_mbl);
1434
1435 /* prepare offsets about where to store the different blocks */
1436 store_offs[p_jpeg->store_pos[0]] = 0;
1437 store_offs[p_jpeg->store_pos[1]] = 8 / downscale; /* to the right */
1438 store_offs[p_jpeg->store_pos[2]] = width * 8 / downscale; /* below */
1439 store_offs[p_jpeg->store_pos[3]] = store_offs[1] + store_offs[2]; /* r+b */
1440
1441 for(y=0; y<p_jpeg->y_mbl && bs.next_input_byte <= bs.input_end; y++)
1442 {
1443 p_byte = p_line;
1444 p_line += skip_strip;
1445 for (x=0; x<p_jpeg->x_mbl; x++)
1446 {
1447 int blkn;
1448
1449 /* Outer loop handles each block in the MCU */
1450 for (blkn = 0; blkn < p_jpeg->blocks; blkn++)
1451 { /* Decode a single block's worth of coefficients */
1452 int k = 1; /* coefficient index */
1453 int s, r; /* huffman values */
1454 int ci = p_jpeg->mcu_membership[blkn]; /* component index */
1455 int ti = p_jpeg->tab_membership[blkn]; /* table index */
1456 struct derived_tbl* dctbl = &p_jpeg->dc_derived_tbls[ti];
1457 struct derived_tbl* actbl = &p_jpeg->ac_derived_tbls[ti];
1458
1459 /* Section F.2.2.1: decode the DC coefficient difference */
1460 s = huff_decode_dc(&bs, dctbl);
1461
1462 if (ci == 0) /* only for Y component */
1463 {
1464 last_dc_val += s;
1465 block[0] = last_dc_val; /* output it (assumes zag[0] = 0) */
1466
1467 /* coefficient buffer must be cleared */
1468 MEMSET(block+1, 0, zero_need*sizeof(block[0]));
1469
1470 /* Section F.2.2.2: decode the AC coefficients */
1471 for (; k < k_need; k++)
1472 {
1473 s = huff_decode_ac(&bs, actbl);
1474 r = s >> 4;
1475 s &= 15;
1476
1477 if (s)
1478 {
1479 k += r;
1480 check_bit_buffer(&bs, s);
1481 r = get_bits(&bs, s);
1482 block[zag[k]] = HUFF_EXTEND(r, s);
1483 }
1484 else
1485 {
1486 if (r != 15)
1487 {
1488 k = 64;
1489 break;
1490 }
1491 k += r;
1492 }
1493 } /* for k */
1494 }
1495 /* In this path we just discard the values */
1496 for (; k < 64; k++)
1497 {
1498 s = huff_decode_ac(&bs, actbl);
1499 r = s >> 4;
1500 s &= 15;
1501
1502 if (s)
1503 {
1504 k += r;
1505 check_bit_buffer(&bs, s);
1506 drop_bits(&bs, s);
1507 }
1508 else
1509 {
1510 if (r != 15)
1511 break;
1512 k += r;
1513 }
1514 } /* for k */
1515
1516 if (ci == 0)
1517 { /* only for Y component */
1518 pf_idct(p_byte+store_offs[blkn], block, p_jpeg->qt_idct[ti],
1519 skip_line);
1520 }
1521 } /* for blkn */
1522 p_byte += skip_mcu;
1523 if (p_jpeg->restart_interval && --restart == 0)
1524 { /* if a restart marker is due: */
1525 restart = p_jpeg->restart_interval; /* count again */
1526 search_restart(&bs); /* align the bitstream */
1527 last_dc_val = 0; /* reset decoder */
1528 }
1529 } /* for x */
1530 if (pf_progress != NULL)
1531 pf_progress(y, p_jpeg->y_mbl-1); /* notify about decoding progress */
1532 } /* for y */
1533
1534 return 0; /* success */
1535}
1536#endif /* !HAVE_LCD_COLOR */
1537
1538/**************** end JPEG code ********************/
diff --git a/apps/plugins/jpeg/jpeg_decoder.h b/apps/plugins/jpeg/jpeg_decoder.h
deleted file mode 100644
index b86bdaf001..0000000000
--- a/apps/plugins/jpeg/jpeg_decoder.h
+++ /dev/null
@@ -1,76 +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#ifndef _JPEG_JPEG_DECODER_H
29#define _JPEG_JPEG_DECODER_H
30#include "jpeg_common.h"
31
32struct jpeg
33{
34 int x_size, y_size; /* size of image (can be less than block boundary) */
35 int x_phys, y_phys; /* physical size, block aligned */
36 int x_mbl; /* x dimension of MBL */
37 int y_mbl; /* y dimension of MBL */
38 int blocks; /* blocks per MB */
39 int restart_interval; /* number of MCUs between RSTm markers */
40 int store_pos[4]; /* for Y block ordering */
41
42 unsigned char* p_entropy_data;
43 unsigned char* p_entropy_end;
44
45 int quanttable[4][QUANT_TABLE_LENGTH]; /* raw quantization tables 0-3 */
46 int qt_idct[2][QUANT_TABLE_LENGTH]; /* quantization tables for IDCT */
47
48 struct huffman_table hufftable[2]; /* Huffman tables */
49 struct derived_tbl dc_derived_tbls[2]; /* Huffman-LUTs */
50 struct derived_tbl ac_derived_tbls[2];
51
52 struct frame_component frameheader[3]; /* Component descriptor */
53 struct scan_component scanheader[3]; /* currently not used */
54
55 int mcu_membership[6]; /* info per block */
56 int tab_membership[6];
57 int subsample_x[3]; /* info per component */
58 int subsample_y[3];
59};
60
61/* various helper functions */
62void default_huff_tbl(struct jpeg* p_jpeg);
63void build_lut(struct jpeg* p_jpeg);
64int process_markers(unsigned char* p_src, long size, struct jpeg* p_jpeg);
65
66/* the main decode function */
67#ifdef HAVE_LCD_COLOR
68int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel[3],
69 int downscale, void (*pf_progress)(int current, int total));
70#else
71int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel[1], int downscale,
72 void (*pf_progress)(int current, int total));
73#endif
74
75
76#endif /* _JPEG_JPEG_DECODER_H */
diff --git a/apps/plugins/jpeg/yuv2rgb.c b/apps/plugins/jpeg/yuv2rgb.c
deleted file mode 100644
index 2395f232b2..0000000000
--- a/apps/plugins/jpeg/yuv2rgb.c
+++ /dev/null
@@ -1,407 +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 "yuv2rgb.h"
30
31/*
32 * Conversion of full 0-255 range YCrCb to RGB:
33 * |R| |1.000000 -0.000001 1.402000| |Y'|
34 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
35 * |B| |1.000000 1.772000 0.000000| |Pr|
36 * Scaled (yields s15-bit output):
37 * |R| |128 0 179| |Y |
38 * |G| = |128 -43 -91| |Cb - 128|
39 * |B| |128 227 0| |Cr - 128|
40 */
41#define YFAC 128
42#define RVFAC 179
43#define GUFAC (-43)
44#define GVFAC (-91)
45#define BUFAC 227
46#define YUV_WHITE (255*YFAC)
47#define NODITHER_DELTA (127*YFAC)
48#define COMPONENT_SHIFT 15
49#define MATRIX_SHIFT 7
50
51static inline int clamp_component_bits(int x, int bits)
52{
53 if ((unsigned)x > (1u << bits) - 1)
54 x = x < 0 ? 0 : (1 << bits) - 1;
55 return x;
56}
57
58static inline int component_to_lcd(int x, int bits, int delta)
59{
60 /* Formula used in core bitmap loader. */
61 return (((1 << bits) - 1)*x + (x >> (8 - bits)) + delta) >> COMPONENT_SHIFT;
62}
63
64static inline int lcd_to_component(int x, int bits, int delta)
65{
66 /* Reasonable, approximate reversal to get a full range back from the
67 quantized value. */
68 return YUV_WHITE*x / ((1 << bits) - 1);
69 (void)delta;
70}
71
72#define RED 0
73#define GRN 1
74#define BLU 2
75
76struct rgb_err
77{
78 int16_t errbuf[LCD_WIDTH+2]; /* Error record for line below */
79} rgb_err_buffers[3];
80
81struct rgb_pixel
82{
83 int r, g, b; /* Current pixel components in s16.0 */
84 int inc; /* Current line increment (-1 or 1) */
85 int row; /* Current row in source image */
86 int col; /* Current column in source image */
87 int ce[3]; /* Errors to apply to current pixel */
88 struct rgb_err *e; /* RED, GRN, BLU */
89 int epos; /* Current position in error record */
90};
91
92struct rgb_pixel *pixel;
93
94/** round and truncate to lcd depth **/
95static fb_data pixel_to_lcd_colour(void)
96{
97 struct rgb_pixel *p = pixel;
98 int r, g, b;
99
100 r = component_to_lcd(p->r, LCD_RED_BITS, NODITHER_DELTA);
101 r = clamp_component_bits(r, LCD_RED_BITS);
102
103 g = component_to_lcd(p->g, LCD_GREEN_BITS, NODITHER_DELTA);
104 g = clamp_component_bits(g, LCD_GREEN_BITS);
105
106 b = component_to_lcd(p->b, LCD_BLUE_BITS, NODITHER_DELTA);
107 b = clamp_component_bits(b, LCD_BLUE_BITS);
108
109 return LCD_RGBPACK_LCD(r, g, b);
110}
111
112/** write a monochrome pixel to the colour LCD **/
113static fb_data pixel_to_lcd_gray(void)
114{
115 int r, g, b;
116
117 g = clamp_component(pixel->g);
118 r = component_to_lcd(g, LCD_RED_BITS, NODITHER_DELTA);
119 b = component_to_lcd(g, LCD_BLUE_BITS, NODITHER_DELTA);
120 g = component_to_lcd(g, LCD_GREEN_BITS, NODITHER_DELTA);
121
122 return LCD_RGBPACK_LCD(r, g, b);
123}
124
125/**
126 * Bayer ordered dithering - swiped from the core bitmap loader.
127 */
128static fb_data pixel_odither_to_lcd(void)
129{
130 /* canonical ordered dither matrix */
131 static const unsigned char dither_matrix[16][16] = {
132 { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 },
133 { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 },
134 { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 },
135 { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 },
136 { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 },
137 { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 },
138 { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 },
139 { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 },
140 { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 },
141 { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 },
142 { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 },
143 { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 },
144 { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 },
145 { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 },
146 { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 },
147 { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 }
148 };
149
150 struct rgb_pixel *p = pixel;
151 int r, g, b, delta;
152
153 delta = dither_matrix[p->col & 15][p->row & 15] << MATRIX_SHIFT;
154
155 r = component_to_lcd(p->r, LCD_RED_BITS, delta);
156 r = clamp_component_bits(r, LCD_RED_BITS);
157
158 g = component_to_lcd(p->g, LCD_GREEN_BITS, delta);
159 g = clamp_component_bits(g, LCD_GREEN_BITS);
160
161 b = component_to_lcd(p->b, LCD_BLUE_BITS, delta);
162 b = clamp_component_bits(b, LCD_BLUE_BITS);
163
164 p->col += p->inc;
165
166 return LCD_RGBPACK_LCD(r, g, b);
167}
168
169/**
170 * Floyd/Steinberg dither to lcd depth.
171 *
172 * Apply filter to each component in serpentine pattern. Kernel shown for
173 * L->R scan. Kernel is reversed for R->L.
174 * * 7
175 * 3 5 1 (1/16)
176 */
177static inline void distribute_error(int *ce, struct rgb_err *e,
178 int err, int epos, int inc)
179{
180 *ce = (7*err >> 4) + e->errbuf[epos+inc];
181 e->errbuf[epos+inc] = err >> 4;
182 e->errbuf[epos] += 5*err >> 4;
183 e->errbuf[epos-inc] += 3*err >> 4;
184}
185
186static fb_data pixel_fsdither_to_lcd(void)
187{
188 struct rgb_pixel *p = pixel;
189 int rc, gc, bc, r, g, b;
190 int inc, epos;
191
192 /* Full components with error terms */
193 rc = p->r + p->ce[RED];
194 r = component_to_lcd(rc, LCD_RED_BITS, 0);
195 r = clamp_component_bits(r, LCD_RED_BITS);
196
197 gc = p->g + p->ce[GRN];
198 g = component_to_lcd(gc, LCD_GREEN_BITS, 0);
199 g = clamp_component_bits(g, LCD_GREEN_BITS);
200
201 bc = p->b + p->ce[BLU];
202 b = component_to_lcd(bc, LCD_BLUE_BITS, 0);
203 b = clamp_component_bits(b, LCD_BLUE_BITS);
204
205 /* Get pixel errors */
206 rc -= lcd_to_component(r, LCD_RED_BITS, 0);
207 gc -= lcd_to_component(g, LCD_GREEN_BITS, 0);
208 bc -= lcd_to_component(b, LCD_BLUE_BITS, 0);
209
210 /* Spead error to surrounding pixels. */
211 inc = p->inc;
212 epos = p->epos;
213 p->epos += inc;
214
215 distribute_error(&p->ce[RED], &p->e[RED], rc, epos, inc);
216 distribute_error(&p->ce[GRN], &p->e[GRN], gc, epos, inc);
217 distribute_error(&p->ce[BLU], &p->e[BLU], bc, epos, inc);
218
219 /* Pack and return pixel */
220 return LCD_RGBPACK_LCD(r, g, b);
221}
222
223/* Functions for each output mode, colour then grayscale. */
224static fb_data (* const pixel_funcs[COLOUR_NUM_MODES][DITHER_NUM_MODES])(void) =
225{
226 [COLOURMODE_COLOUR] =
227 {
228 [DITHER_NONE] = pixel_to_lcd_colour,
229 [DITHER_ORDERED] = pixel_odither_to_lcd,
230 [DITHER_DIFFUSION] = pixel_fsdither_to_lcd,
231 },
232 [COLOURMODE_GRAY] =
233 {
234 [DITHER_NONE] = pixel_to_lcd_gray,
235 [DITHER_ORDERED] = pixel_odither_to_lcd,
236 [DITHER_DIFFUSION] = pixel_fsdither_to_lcd,
237 },
238};
239
240/* These defines are used fornormal horizontal strides and vertical strides. */
241#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
242#define LCDADDR(x, y) (rb->lcd_framebuffer + LCD_HEIGHT*(x) + (y))
243#define ROWENDOFFSET (width*LCD_HEIGHT)
244#define ROWOFFSET (1)
245#define COLOFFSET (LCD_HEIGHT)
246#else
247#define LCDADDR(x, y) (rb->lcd_framebuffer + LCD_WIDTH*(y) + (x))
248#define ROWENDOFFSET (width)
249#define ROWOFFSET (LCD_WIDTH)
250#define COLOFFSET (1)
251#endif
252
253/**
254 * Draw a partial YUV colour bitmap
255 *
256 * Runs serpentine pattern when dithering is DITHER_DIFFUSION, else scan is
257 * always L->R.
258 */
259void yuv_bitmap_part(unsigned char *src[3], int csub_x, int csub_y,
260 int src_x, int src_y, int stride,
261 int x, int y, int width, int height,
262 int colour_mode, int dither_mode)
263{
264 fb_data *dst, *dst_end;
265 fb_data (*pixel_func)(void);
266 struct rgb_pixel px;
267 int dst_inc;
268
269 if (x + width > LCD_WIDTH)
270 width = LCD_WIDTH - x; /* Clip right */
271 if (x < 0)
272 width += x, x = 0; /* Clip left */
273 if (width <= 0)
274 return; /* nothing left to do */
275
276 if (y + height > LCD_HEIGHT)
277 height = LCD_HEIGHT - y; /* Clip bottom */
278 if (y < 0)
279 height += y, y = 0; /* Clip top */
280 if (height <= 0)
281 return; /* nothing left to do */
282
283 pixel = &px;
284
285 dst = LCDADDR(x, y);
286 dst_end = LCDADDR(x, y+height);
287
288 if (colour_mode == COLOURMODE_GRAY)
289 csub_y = 0; /* Ignore Cb, Cr */
290
291 pixel_func = pixel_funcs[colour_mode]
292 [dither_mode];
293
294 if (dither_mode == DITHER_DIFFUSION)
295 {
296 /* Reset error terms. */
297 px.e = rgb_err_buffers;
298 px.ce[RED] = px.ce[GRN] = px.ce[BLU] = 0;
299 rb->memset(px.e, 0, 3*sizeof (struct rgb_err));
300 }
301
302 do
303 {
304 fb_data *dst_row, *row_end;
305 const unsigned char *ysrc;
306 px.inc = 1;
307
308 if (dither_mode == DITHER_DIFFUSION)
309 {
310 /* Use R->L scan on odd lines */
311 px.inc -= (src_y & 1) << 1;
312 px.epos = x + 1;
313
314 if (px.inc < 0)
315 px.epos += width - 1;
316 }
317
318 if (px.inc == 1)
319 {
320 /* Scan is L->R */
321 dst_inc = COLOFFSET;
322 dst_row = dst;
323 row_end = dst_row + ROWENDOFFSET;
324 px.col = src_x;
325 }
326 else
327 {
328 /* Scan is R->L */
329 dst_inc = -COLOFFSET;
330 row_end = dst + dst_inc;
331 dst_row = row_end + ROWENDOFFSET;
332 px.col = src_x + width - 1;
333 }
334
335 ysrc = src[0] + stride * src_y + px.col;
336 px.row = src_y;
337
338 /* Do one row of pixels */
339 if (csub_y) /* colour */
340 {
341 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
342 const unsigned char *usrc, *vsrc;
343
344 usrc = src[1] + (stride/csub_x) * (src_y/csub_y)
345 + (px.col/csub_x);
346 vsrc = src[2] + (stride/csub_x) * (src_y/csub_y)
347 + (px.col/csub_x);
348 int xphase = px.col % csub_x;
349 int xphase_reset = px.inc * csub_x;
350 int y, v, u, rv, guv, bu;
351
352 v = *vsrc - 128;
353 vsrc += px.inc;
354 u = *usrc - 128;
355 usrc += px.inc;
356 rv = RVFAC*v;
357 guv = GUFAC*u + GVFAC*v;
358 bu = BUFAC*u;
359
360 while (1)
361 {
362 y = YFAC*(*ysrc);
363 ysrc += px.inc;
364 px.r = y + rv;
365 px.g = y + guv;
366 px.b = y + bu;
367
368 *dst_row = pixel_func();
369 dst_row += dst_inc;
370
371 if (dst_row == row_end)
372 break;
373
374 xphase += px.inc;
375 if ((unsigned)xphase < (unsigned)csub_x)
376 continue;
377
378 /* fetch new chromas */
379 v = *vsrc - 128;
380 vsrc += px.inc;
381 u = *usrc - 128;
382 usrc += px.inc;
383 rv = RVFAC*v;
384 guv = GUFAC*u + GVFAC*v;
385 bu = BUFAC*u;
386
387 xphase -= xphase_reset;
388 }
389 }
390 else /* monochrome */
391 {
392 do
393 {
394 /* Set all components the same for dithering purposes */
395 px.g = px.r = px.b = YFAC*(*ysrc);
396 *dst_row = pixel_func();
397 ysrc += px.inc;
398 dst_row += dst_inc;
399 }
400 while (dst_row != row_end);
401 }
402
403 src_y++;
404 dst += ROWOFFSET;
405 }
406 while (dst < dst_end);
407}
diff --git a/apps/plugins/jpeg/yuv2rgb.h b/apps/plugins/jpeg/yuv2rgb.h
deleted file mode 100644
index d10a944f38..0000000000
--- a/apps/plugins/jpeg/yuv2rgb.h
+++ /dev/null
@@ -1,51 +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#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