summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
authorJörg Hohensohn <hohensoh@rockbox.org>2004-05-12 22:56:32 +0000
committerJörg Hohensohn <hohensoh@rockbox.org>2004-05-12 22:56:32 +0000
commitefea9e6b2de7a2127bc281a8851627b579731afb (patch)
tree20b8c21d9c08ddb03f3bb30671d8df812517cea5 /apps/plugins
parent1f55909081b86e560e43234a1e49e9ffe1ada4af (diff)
downloadrockbox-efea9e6b2de7a2127bc281a8851627b579731afb.tar.gz
rockbox-efea9e6b2de7a2127bc281a8851627b579731afb.zip
jpeg viewer: use Play to zoom in, On to zoom out, arrows to scroll
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4613 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/jpeg.c3026
1 files changed, 3026 insertions, 0 deletions
diff --git a/apps/plugins/jpeg.c b/apps/plugins/jpeg.c
new file mode 100644
index 0000000000..ee6fb83f66
--- /dev/null
+++ b/apps/plugins/jpeg.c
@@ -0,0 +1,3026 @@
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* Copyright (C) 2004 Jörg Hohensohn aka [IDC]Dragon
14* Grayscale framework (c) 2004 Jens Arnold
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* All files in this archive are subject to the GNU General Public License.
19* See the file COPYING in the source tree root for full license agreement.
20*
21* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
22* KIND, either express or implied.
23*
24****************************************************************************/
25
26#ifndef SIMULATOR /* not for simulator by now */
27#include "plugin.h"
28
29#ifdef HAVE_LCD_BITMAP /* and also not for the Player */
30
31/******************************* Globals ***********************************/
32
33static struct plugin_api* rb;
34
35/*********************** Begin grayscale framework *************************/
36
37/* This is a generic framework to use grayscale display within rockbox
38 * plugins. It obviously does not work for the player.
39 *
40 * If you want to use grayscale display within a plugin, copy this section
41 * (up to "End grayscale framework") into your source and you are able to use
42 * it. For detailed documentation look at the head of each public function.
43 *
44 * It requires a global Rockbox api pointer in "rb" and uses the rockbox
45 * timer api so you cannot use that timer for other purposes while
46 * displaying grayscale.
47 *
48 * The framework consists of 3 sections:
49 *
50 * - internal core functions and definitions
51 * - public core functions
52 * - public optional functions
53 *
54 * Usually you will use functions from the latter two sections in your code.
55 * You can cut out functions from the third section that you do not need in
56 * order to not waste space. Don't forget to cut the prototype as well.
57 */
58
59/**** internal core functions and definitions ****/
60
61/* You do not want to touch these if you don't know exactly what you're
62 * doing. */
63
64#define GRAY_RUNNING 0x0001 /* grayscale overlay is running */
65#define GRAY_DEFERRED_UPDATE 0x0002 /* lcd_update() requested */
66
67typedef struct
68{
69 int x;
70 int by; /* 8-pixel units */
71 int width;
72 int height;
73 int bheight; /* 8-pixel units */
74 int plane_size;
75 int depth; /* number_of_bitplanes = (number_of_grayscales - 1) */
76 int cur_plane; /* for the timer isr */
77 unsigned long randmask; /* mask for random value in graypixel() */
78 unsigned long flags; /* various flags, see #defines */
79 unsigned char *data; /* pointer to start of bitplane data */
80 unsigned long *bitpattern; /* pointer to start of pattern table */
81} tGraybuf;
82
83static tGraybuf *graybuf = NULL;
84
85/** prototypes **/
86
87void timer_isr(void);
88void graypixel(int x, int y, unsigned long pattern);
89void grayinvertmasked(int x, int yb, unsigned char mask);
90
91/** implementation **/
92
93/* timer interrupt handler: display next bitplane */
94void timer_isr(void)
95{
96 rb->lcd_blit(graybuf->data + (graybuf->plane_size * graybuf->cur_plane),
97 graybuf->x, graybuf->by, graybuf->width, graybuf->bheight,
98 graybuf->width);
99
100 if (++graybuf->cur_plane >= graybuf->depth)
101 graybuf->cur_plane = 0;
102
103 if (graybuf->flags & GRAY_DEFERRED_UPDATE) /* lcd_update() requested? */
104 {
105 int x1 = MAX(graybuf->x, 0);
106 int x2 = MIN(graybuf->x + graybuf->width, LCD_WIDTH);
107 int y1 = MAX(graybuf->by << 3, 0);
108 int y2 = MIN((graybuf->by + graybuf->bheight) << 3, LCD_HEIGHT);
109
110 if (y1 > 0) /* refresh part above overlay, full width */
111 rb->lcd_update_rect(0, 0, LCD_WIDTH, y1);
112
113 if (y2 < LCD_HEIGHT) /* refresh part below overlay, full width */
114 rb->lcd_update_rect(0, y2, LCD_WIDTH, LCD_HEIGHT - y2);
115
116 if (x1 > 0) /* refresh part to the left of overlay */
117 rb->lcd_update_rect(0, y1, x1, y2 - y1);
118
119 if (x2 < LCD_WIDTH) /* refresh part to the right of overlay */
120 rb->lcd_update_rect(x2, y1, LCD_WIDTH - x2, y2 - y1);
121
122 graybuf->flags &= ~GRAY_DEFERRED_UPDATE; /* clear request */
123 }
124}
125
126/* Set a pixel to a specific bit pattern
127 * This is the fundamental graphics primitive, asm optimized */
128void graypixel(int x, int y, unsigned long pattern)
129{
130 static short random_buffer;
131 register long address, mask, random;
132
133 /* Some (pseudo-)random function must be used here to shift the bit
134 * pattern randomly, otherwise you would get flicker and/or moire.
135 * Since rand() is relatively slow, I've implemented a simple, but very
136 * fast pseudo-random generator based on linear congruency in assembler.
137 * It delivers 16 pseudo-random bits in each iteration. */
138
139 /* simple but fast pseudo-random generator */
140 asm(
141 "mov.w @%1,%0 \n" /* load last value */
142 "mov #75,r1 \n"
143 "mulu %0,r1 \n" /* multiply by 75 */
144 "sts macl,%0 \n" /* get result */
145 "add #74,%0 \n" /* add another 74 */
146 "mov.w %0,@%1 \n" /* store new value */
147 /* Since the lower bits are not very random: */
148 "shlr8 %0 \n" /* get bits 8..15 (need max. 5) */
149 "and %2,%0 \n" /* mask out unneeded bits */
150 : /* outputs */
151 /* %0 */ "=&r"(random)
152 : /* inputs */
153 /* %1 */ "r"(&random_buffer),
154 /* %2 */ "r"(graybuf->randmask)
155 : /* clobbers */
156 "r1","macl"
157 );
158
159 /* precalculate mask and byte address in first bitplane */
160 asm(
161 "mov %3,%0 \n" /* take y as base for address offset */
162 "shlr2 %0 \n" /* shift right by 3 (= divide by 8) */
163 "shlr %0 \n"
164 "mulu %0,%2 \n" /* multiply with width */
165 "and #7,%3 \n" /* get lower 3 bits of y */
166 "sts macl,%0 \n" /* get mulu result */
167 "add %4,%0 \n" /* add base + x to get final address */
168
169 "mov %3,%1 \n" /* move lower 3 bits of y out of r0 */
170 "mova .pp_table,%3 \n" /* get address of mask table in r0 */
171 "bra .pp_end \n" /* skip the table */
172 "mov.b @(%3,%1),%1 \n" /* get entry from mask table */
173
174 ".align 2 \n"
175 ".pp_table: \n" /* mask table */
176 ".byte 0x01 \n"
177 ".byte 0x02 \n"
178 ".byte 0x04 \n"
179 ".byte 0x08 \n"
180 ".byte 0x10 \n"
181 ".byte 0x20 \n"
182 ".byte 0x40 \n"
183 ".byte 0x80 \n"
184
185 ".pp_end: \n"
186 : /* outputs */
187 /* %0 */ "=&r"(address),
188 /* %1 */ "=&r"(mask)
189 : /* inputs */
190 /* %2 */ "r"(graybuf->width),
191 /* %3 = r0 */ "z"(y),
192 /* %4 */ "r"(graybuf->data + x)
193 : /* clobbers */
194 "macl"
195 );
196
197 /* the hard part: set bits in all bitplanes according to pattern */
198 asm(
199 "cmp/hs %1,%5 \n" /* random >= depth ? */
200 "bf .p_ntrim \n"
201 "sub %1,%5 \n" /* yes: random -= depth */
202 /* it's sufficient to do this once, since the mask guarantees
203 * random < 2 * depth */
204 ".p_ntrim: \n"
205
206 /* calculate some addresses */
207 "mulu %4,%1 \n" /* end address offset */
208 "not %3,r1 \n" /* get inverse mask (for "and") */
209 "sts macl,%1 \n" /* result of mulu */
210 "mulu %4,%5 \n" /* address offset of <random>'th plane */
211 "add %2,%1 \n" /* end offset -> end address */
212 "sts macl,%5 \n" /* result of mulu */
213 "add %2,%5 \n" /* address of <random>'th plane */
214 "bra .p_start1 \n"
215 "mov %5,r2 \n" /* copy address */
216
217 /* first loop: set bits from <random>'th bitplane to last */
218 ".p_loop1: \n"
219 "mov.b @r2,r3 \n" /* get data byte */
220 "shlr %0 \n" /* shift bit mask, sets t bit */
221 "and r1,r3 \n" /* reset bit (-> "white") */
222 "bf .p_white1 \n" /* t=0? -> "white" bit */
223 "or %3,r3 \n" /* set bit ("black" bit) */
224 ".p_white1: \n"
225 "mov.b r3,@r2 \n" /* store data byte */
226 "add %4,r2 \n" /* advance address to next bitplane */
227 ".p_start1: \n"
228 "cmp/hi r2,%1 \n" /* address < end address ? */
229 "bt .p_loop1 \n"
230
231 "bra .p_start2 \n"
232 "nop \n"
233
234 /* second loop: set bits from first to <random-1>'th bitplane
235 * Bit setting works the other way round here to equalize average
236 * execution times for bright and dark pixels */
237 ".p_loop2: \n"
238 "mov.b @%2,r3 \n" /* get data byte */
239 "shlr %0 \n" /* shift bit mask, sets t bit */
240 "or %3,r3 \n" /* set bit (-> "black") */
241 "bt .p_black2 \n" /* t=1? -> "black" bit */
242 "and r1,r3 \n" /* reset bit ("white" bit) */
243 ".p_black2: \n"
244 "mov.b r3,@%2 \n" /* store data byte */
245 "add %4,%2 \n" /* advance address to next bitplane */
246 ".p_start2: \n"
247 "cmp/hi %2,%5 \n" /* address < <random>'th address ? */
248 "bt .p_loop2 \n"
249 : /* outputs */
250 : /* inputs */
251 /* %0 */ "r"(pattern),
252 /* %1 */ "r"(graybuf->depth),
253 /* %2 */ "r"(address),
254 /* %3 */ "r"(mask),
255 /* %4 */ "r"(graybuf->plane_size),
256 /* %5 */ "r"(random)
257 : /* clobbers */
258 "r1", "r2", "r3", "macl"
259 );
260}
261
262/* Invert the bits for 1-8 pixels within the buffer */
263void grayinvertmasked(int x, int by, unsigned char mask)
264{
265 asm(
266 "mulu %4,%5 \n" /* width * by (offset of row) */
267 "mov #0,r1 \n" /* current_plane = 0 */
268 "sts macl,r2 \n" /* get mulu result */
269 "add r2,%1 \n" /* -> address in 1st bitplane */
270
271 ".i_loop: \n"
272 "mov.b @%1,r2 \n" /* get data byte */
273 "add #1,r1 \n" /* current_plane++; */
274 "xor %2,r2 \n" /* invert bits */
275 "mov.b r2,@%1 \n" /* store data byte */
276 "add %3,%1 \n" /* advance address to next bitplane */
277 "cmp/hi r1,%0 \n" /* current_plane < depth ? */
278 "bt .i_loop \n"
279 : /* outputs */
280 : /* inputs */
281 /* %0 */ "r"(graybuf->depth),
282 /* %1 */ "r"(graybuf->data + x),
283 /* %2 */ "r"(mask),
284 /* %3 */ "r"(graybuf->plane_size),
285 /* %4 */ "r"(graybuf->width),
286 /* %5 */ "r"(by)
287 : /* clobbers */
288 "r1", "r2", "macl"
289 );
290}
291
292/*** public core functions ***/
293
294/** prototypes **/
295
296int gray_init_buffer(unsigned char *gbuf, int gbuf_size, int width,
297 int bheight, int depth);
298void gray_release_buffer(void);
299void gray_position_display(int x, int by);
300void gray_show_display(bool enable);
301
302/** implementation **/
303
304/* Prepare the grayscale display buffer
305 *
306 * arguments:
307 * gbuf = pointer to the memory area to use (e.g. plugin buffer)
308 * gbuf_size = max usable size of the buffer
309 * width = width in pixels (1..112)
310 * bheight = height in 8-pixel units (1..8)
311 * depth = desired number of shades - 1 (1..32)
312 *
313 * result:
314 * = depth if there was enough memory
315 * < depth if there wasn't enough memory. The number of displayable
316 * shades is smaller than desired, but it still works
317 * = 0 if there wasn't even enough memory for 1 bitplane (black & white)
318 *
319 * You can request any depth from 1 to 32, not just powers of 2. The routine
320 * performs "graceful degradation" if the memory is not sufficient for the
321 * desired depth. As long as there is at least enough memory for 1 bitplane,
322 * it creates as many bitplanes as fit into memory, although 1 bitplane will
323 * only deliver black & white display.
324 *
325 * The total memory needed can be calculated as follows:
326 * total_mem =
327 * sizeof(tGraymap) (= 48 bytes currently)
328 * + sizeof(long) (= 4 bytes)
329 * + (width * bheight + sizeof(long)) * depth
330 * + 0..3 (longword alignment of grayscale display buffer)
331 */
332int gray_init_buffer(unsigned char *gbuf, int gbuf_size, int width,
333 int bheight, int depth)
334{
335 int possible_depth, plane_size;
336 int i, j;
337
338 if (width > LCD_WIDTH || bheight > (LCD_HEIGHT >> 3) || depth < 1)
339 return 0;
340
341 while ((unsigned long)gbuf & 3) /* the buffer has to be long aligned */
342 {
343 gbuf++;
344 gbuf_size--;
345 }
346
347 plane_size = width * bheight;
348 possible_depth = (gbuf_size - sizeof(tGraybuf) - sizeof(unsigned long))
349 / (plane_size + sizeof(unsigned long));
350
351 if (possible_depth < 1)
352 return 0;
353
354 depth = MIN(depth, 32);
355 depth = MIN(depth, possible_depth);
356
357 graybuf = (tGraybuf *) gbuf; /* global pointer to buffer structure */
358
359 graybuf->x = 0;
360 graybuf->by = 0;
361 graybuf->width = width;
362 graybuf->height = bheight << 3;
363 graybuf->bheight = bheight;
364 graybuf->plane_size = plane_size;
365 graybuf->depth = depth;
366 graybuf->cur_plane = 0;
367 graybuf->flags = 0;
368 graybuf->data = gbuf + sizeof(tGraybuf);
369 graybuf->bitpattern = (unsigned long *) (graybuf->data
370 + depth * plane_size);
371
372 i = depth;
373 j = 8;
374 while (i != 0)
375 {
376 i >>= 1;
377 j--;
378 }
379 graybuf->randmask = 0xFF >> j;
380
381 /* initial state is all white */
382 rb->memset(graybuf->data, 0, depth * plane_size);
383
384 /* Precalculate the bit patterns for all possible pixel values */
385 for (i = 0; i <= depth; i++)
386 {
387 unsigned long pattern = 0;
388 int value = 0;
389
390 for (j = 0; j < depth; j++)
391 {
392 pattern <<= 1;
393 value += i;
394
395 if (value >= depth)
396 value -= depth; /* "white" bit */
397 else
398 pattern |= 1; /* "black" bit */
399 }
400 /* now the lower <depth> bits contain the pattern */
401
402 graybuf->bitpattern[i] = pattern;
403 }
404
405 return depth;
406}
407
408/* Release the grayscale display buffer
409 *
410 * Switches the grayscale overlay off at first if it is still running,
411 * then sets the pointer to NULL.
412 * DO CALL either this function or at least gray_show_display(false)
413 * before you exit, otherwise nasty things may happen.
414 */
415void gray_release_buffer(void)
416{
417 gray_show_display(false);
418 graybuf = NULL;
419}
420
421/* Set position of the top left corner of the grayscale overlay
422 *
423 * arguments:
424 * x = left margin in pixels
425 * by = top margin in 8-pixel units
426 *
427 * You may set this in a way that the overlay spills across the right or
428 * bottom display border. In this case it will simply be clipped by the
429 * LCD controller. You can even set negative values, this will clip at the
430 * left or top border. I did not test it, but the limits may be +127 / -128
431 *
432 * If you use this while the grayscale overlay is running, the now-freed area
433 * will be restored.
434 */
435void gray_position_display(int x, int by)
436{
437 if (graybuf == NULL)
438 return;
439
440 graybuf->x = x;
441 graybuf->by = by;
442
443 if (graybuf->flags & GRAY_RUNNING)
444 graybuf->flags |= GRAY_DEFERRED_UPDATE;
445}
446
447/* Switch the grayscale overlay on or off
448 *
449 * arguments:
450 * enable = true: the grayscale overlay is switched on if initialized
451 * = false: the grayscale overlay is switched off and the regular lcd
452 * content is restored
453 *
454 * DO NOT call lcd_update() or any other api function that directly accesses
455 * the lcd while the grayscale overlay is running! If you need to do
456 * lcd_update() to update something outside the grayscale overlay area, use
457 * gray_deferred_update() instead.
458 *
459 * Other functions to avoid are:
460 * lcd_blit() (obviously), lcd_update_rect(), lcd_set_contrast(),
461 * lcd_set_invert_display(), lcd_set_flip(), lcd_roll()
462 *
463 * The grayscale display consumes ~50 % CPU power (for a full screen overlay,
464 * less if the overlay is smaller) when switched on. You can switch the overlay
465 * on and off as many times as you want.
466 */
467void gray_show_display(bool enable)
468{
469 if (graybuf == NULL)
470 return;
471
472 if (enable)
473 {
474 graybuf->flags |= GRAY_RUNNING;
475 rb->plugin_register_timer(FREQ / 67, 1, timer_isr);
476 }
477 else
478 {
479 rb->plugin_unregister_timer();
480 graybuf->flags &= ~GRAY_RUNNING;
481 rb->lcd_update(); /* restore whatever there was before */
482 }
483}
484
485/*** public optional functions ***/
486
487/* Here are the various graphics primitives. Cut out functions you do not
488 * need in order to keep plugin code size down.
489 */
490
491/** prototypes **/
492
493/* functions affecting the whole display */
494void gray_clear_display(void);
495void gray_black_display(void);
496void gray_deferred_update(void);
497
498/* scrolling functions */
499void gray_scroll_left(int count, bool black_border);
500void gray_scroll_right(int count, bool black_border);
501void gray_scroll_up8(bool black_border);
502void gray_scroll_down8(bool black_border);
503void gray_scroll_up1(bool black_border);
504void gray_scroll_down1(bool black_border);
505
506/* pixel functions */
507void gray_drawpixel(int x, int y, int brightness);
508void gray_invertpixel(int x, int y);
509
510/* line functions */
511void gray_drawline(int x1, int y1, int x2, int y2, int brightness);
512void gray_invertline(int x1, int y1, int x2, int y2);
513
514/* rectangle functions */
515void gray_drawrect(int x1, int y1, int x2, int y2, int brightness);
516void gray_fillrect(int x1, int y1, int x2, int y2, int brightness);
517void gray_invertrect(int x1, int y1, int x2, int y2);
518
519/* bitmap functions */
520void gray_drawgraymap(unsigned char *src, int x, int y, int nx, int ny,
521 int stride);
522void gray_drawbitmap(unsigned char *src, int x, int y, int nx, int ny,
523 int stride, bool draw_bg, int fg_brightness,
524 int bg_brightness);
525
526/** implementation **/
527
528/* Clear the grayscale display (sets all pixels to white)
529 */
530void gray_clear_display(void)
531{
532 if (graybuf == NULL)
533 return;
534
535 rb->memset(graybuf->data, 0, graybuf->depth * graybuf->plane_size);
536}
537
538/* Set the grayscale display to all black
539 */
540void gray_black_display(void)
541{
542 if (graybuf == NULL)
543 return;
544
545 rb->memset(graybuf->data, 0xFF, graybuf->depth * graybuf->plane_size);
546}
547
548/* Do a lcd_update() to show changes done by rb->lcd_xxx() functions (in areas
549 * of the screen not covered by the grayscale overlay). If the grayscale
550 * overlay is running, the update will be done in the next call of the
551 * interrupt routine, otherwise it will be performed right away. See also
552 * comment for the gray_show_display() function.
553 */
554void gray_deferred_update(void)
555{
556 if (graybuf != NULL && (graybuf->flags & GRAY_RUNNING))
557 graybuf->flags |= GRAY_DEFERRED_UPDATE;
558 else
559 rb->lcd_update();
560}
561
562/* Scroll the whole grayscale buffer left by <count> pixels
563 *
564 * black_border determines if the pixels scrolled in at the right are black
565 * or white
566 */
567void gray_scroll_left(int count, bool black_border)
568{
569 int x, by, d;
570 unsigned char *src, *dest;
571 unsigned char filler;
572
573 if (graybuf == NULL || count >= graybuf->width)
574 return;
575
576 if (black_border)
577 filler = 0xFF;
578 else
579 filler = 0;
580
581 /* Scroll row by row to minimize flicker (byte rows = 8 pixels each) */
582 for (by = 0; by < graybuf->bheight; by++)
583 {
584 for (d = 0; d < graybuf->depth; d++)
585 {
586 dest = graybuf->data + graybuf->plane_size * d
587 + graybuf->width * by;
588 src = dest + count;
589
590 for (x = count; x < graybuf->width; x++)
591 *dest++ = *src++;
592
593 for (x = 0; x < count; x++)
594 *dest++ = filler;
595 }
596 }
597}
598
599/* Scroll the whole grayscale buffer right by <count> pixels
600 *
601 * black_border determines if the pixels scrolled in at the left are black
602 * or white
603 */
604void gray_scroll_right(int count, bool black_border)
605{
606 int x, by, d;
607 unsigned char *src, *dest;
608 unsigned char filler;
609
610 if (graybuf == NULL || count >= graybuf->width)
611 return;
612
613 if (black_border)
614 filler = 0xFF;
615 else
616 filler = 0;
617
618 /* Scroll row by row to minimize flicker (byte rows = 8 pixels each) */
619 for (by = 0; by < graybuf->bheight; by++)
620 {
621 for (d = 0; d < graybuf->depth; d++)
622 {
623 dest = graybuf->data + graybuf->plane_size * d
624 + graybuf->width * (by + 1) - 1;
625 src = dest - count;
626
627 for (x = count; x < graybuf->width; x++)
628 *dest-- = *src--;
629
630 for (x = 0; x < count; x++)
631 *dest-- = filler;
632 }
633 }
634}
635
636/* Scroll the whole grayscale buffer up by 8 pixels
637 *
638 * black_border determines if the pixels scrolled in at the bottom are black
639 * or white
640 */
641void gray_scroll_up8(bool black_border)
642{
643 int by, d;
644 unsigned char *src;
645 unsigned char filler;
646
647 if (graybuf == NULL)
648 return;
649
650 if (black_border)
651 filler = 0xFF;
652 else
653 filler = 0;
654
655 /* Scroll row by row to minimize flicker (byte rows = 8 pixels each) */
656 for (by = 1; by < graybuf->bheight; by++)
657 {
658 for (d = 0; d < graybuf->depth; d++)
659 {
660 src = graybuf->data + graybuf->plane_size * d
661 + graybuf->width * by;
662
663 rb->memcpy(src - graybuf->width, src, graybuf->width);
664 }
665 }
666 for (d = 0; d < graybuf->depth; d++) /* fill last row */
667 {
668 rb->memset(graybuf->data + graybuf->plane_size * (d + 1)
669 - graybuf->width, filler, graybuf->width);
670 }
671}
672
673/* Scroll the whole grayscale buffer down by 8 pixels
674 *
675 * black_border determines if the pixels scrolled in at the top are black
676 * or white
677 */
678void gray_scroll_down8(bool black_border)
679{
680 int by, d;
681 unsigned char *dest;
682 unsigned char filler;
683
684 if (graybuf == NULL)
685 return;
686
687 if (black_border)
688 filler = 0xFF;
689 else
690 filler = 0;
691
692 /* Scroll row by row to minimize flicker (byte rows = 8 pixels each) */
693 for (by = graybuf->bheight - 1; by > 0; by--)
694 {
695 for (d = 0; d < graybuf->depth; d++)
696 {
697 dest = graybuf->data + graybuf->plane_size * d
698 + graybuf->width * by;
699
700 rb->memcpy(dest, dest - graybuf->width, graybuf->width);
701 }
702 }
703 for (d = 0; d < graybuf->depth; d++) /* fill first row */
704 {
705 rb->memset(graybuf->data + graybuf->plane_size * d, filler,
706 graybuf->width);
707 }
708}
709
710/* Scroll the whole grayscale buffer up by 1 pixel
711 *
712 * black_border determines if the pixels scrolled in at the bottom are black
713 * or white
714 *
715 * Scrolling up/down pixel-wise is significantly slower than scrolling
716 * left/right or scrolling up/down byte-wise because it involves bit
717 * shifting. That's why it is asm optimized.
718 */
719void gray_scroll_up1(bool black_border)
720{
721 int filler;
722
723 if (graybuf == NULL)
724 return;
725
726 if (black_border)
727 filler = 1;
728 else
729 filler = 0;
730
731 /* scroll column by column to minimize flicker */
732 asm(
733 "mov #0,r6 \n" /* x = 0; */
734
735 ".su_cloop: \n" /* repeat for every column */
736 "mov %1,r7 \n" /* get start address */
737 "mov #0,r1 \n" /* current_plane = 0 */
738
739 ".su_oloop: \n" /* repeat for every bitplane */
740 "mov r7,r2 \n" /* get start address */
741 "mov #0,r3 \n" /* current_row = 0 */
742 "mov %5,r5 \n" /* get filler bit (bit 0) */
743
744 ".su_iloop: \n" /* repeat for all rows */
745 "sub %2,r2 \n" /* address -= width; */
746 "mov.b @r2,r4 \n" /* get new byte */
747 "shll8 r5 \n" /* shift old lsb to bit 8 */
748 "extu.b r4,r4 \n" /* extend byte unsigned */
749 "or r5,r4 \n" /* merge old lsb */
750 "shlr r4 \n" /* shift right */
751 "movt r5 \n" /* save new lsb */
752 "mov.b r4,@r2 \n" /* store byte */
753 "add #1,r3 \n" /* current_row++; */
754 "cmp/hi r3,%3 \n" /* cuurent_row < bheight ? */
755 "bt .su_iloop \n"
756
757 "add %4,r7 \n" /* start_address += plane_size; */
758 "add #1,r1 \n" /* current_plane++; */
759 "cmp/hi r1,%0 \n" /* current_plane < depth ? */
760 "bt .su_oloop \n"
761
762 "add #1,%1 \n" /* start_address++; */
763 "add #1,r6 \n" /* x++; */
764 "cmp/hi r6,%2 \n" /* x < width ? */
765 "bt .su_cloop \n"
766 : /* outputs */
767 : /* inputs */
768 /* %0 */ "r"(graybuf->depth),
769 /* %1 */ "r"(graybuf->data + graybuf->plane_size),
770 /* %2 */ "r"(graybuf->width),
771 /* %3 */ "r"(graybuf->bheight),
772 /* %4 */ "r"(graybuf->plane_size),
773 /* %5 */ "r"(filler)
774 : /* clobbers */
775 "r1", "r2", "r3", "r4", "r5", "r6", "r7"
776 );
777}
778
779/* Scroll the whole grayscale buffer down by 1 pixel
780 *
781 * black_border determines if the pixels scrolled in at the top are black
782 * or white
783 *
784 * Scrolling up/down pixel-wise is significantly slower than scrolling
785 * left/right or scrolling up/down byte-wise because it involves bit
786 * shifting. That's why it is asm optimized. Scrolling down is a bit
787 * faster than scrolling up, though.
788 */
789void gray_scroll_down1(bool black_border)
790{
791 int filler;
792
793 if (graybuf == NULL)
794 return;
795
796 if (black_border)
797 filler = -1; /* sets bit 31 */
798 else
799 filler = 0;
800
801 /* scroll column by column to minimize flicker */
802 asm(
803 "mov #0,r5 \n" /* x = 0; */
804
805 ".sd_cloop: \n" /* repeat for every column */
806 "mov %1,r6 \n" /* get start address */
807 "mov #0,r1 \n" /* current_plane = 0 */
808
809 ".sd_oloop: \n" /* repeat for every bitplane */
810 "mov r6,r2 \n" /* get start address */
811 "mov #0,r3 \n" /* current_row = 0 */
812 "mov %5,r4 \n" /* get filler bit (bit 31) */
813
814 ".sd_iloop: \n" /* repeat for all rows */
815 "shll r4 \n" /* get old msb (again) */
816 /* This is possible because the sh1 loads byte data sign-extended,
817 * so the upper 25 bits of the register are all identical */
818 "mov.b @r2,r4 \n" /* get new byte */
819 "add #1,r3 \n" /* current_row++; */
820 "rotcl r4 \n" /* rotate left, merges previous msb */
821 "mov.b r4,@r2 \n" /* store byte */
822 "add %2,r2 \n" /* address += width; */
823 "cmp/hi r3,%3 \n" /* cuurent_row < bheight ? */
824 "bt .sd_iloop \n"
825
826 "add %4,r6 \n" /* start_address += plane_size; */
827 "add #1,r1 \n" /* current_plane++; */
828 "cmp/hi r1,%0 \n" /* current_plane < depth ? */
829 "bt .sd_oloop \n"
830
831 "add #1,%1 \n" /* start_address++; */
832 "add #1,r5 \n" /* x++ */
833 "cmp/hi r5,%2 \n" /* x < width ? */
834 "bt .sd_cloop \n"
835 : /* outputs */
836 : /* inputs */
837 /* %0 */ "r"(graybuf->depth),
838 /* %1 */ "r"(graybuf->data),
839 /* %2 */ "r"(graybuf->width),
840 /* %3 */ "r"(graybuf->bheight),
841 /* %4 */ "r"(graybuf->plane_size),
842 /* %5 */ "r"(filler)
843 : /* clobbers */
844 "r1", "r2", "r3", "r4", "r5", "r6"
845 );
846}
847
848/* Set a pixel to a specific gray value
849 *
850 * brightness is 0..255 (black to white) regardless of real bit depth
851 */
852void gray_drawpixel(int x, int y, int brightness)
853{
854 if (graybuf == NULL || x >= graybuf->width || y >= graybuf->height
855 || brightness > 255)
856 return;
857
858 graypixel(x, y, graybuf->bitpattern[(brightness
859 * (graybuf->depth + 1)) >> 8]);
860}
861
862/* Invert a pixel
863 *
864 * The bit pattern for that pixel in the buffer is inverted, so white becomes
865 * black, light gray becomes dark gray etc.
866 */
867void gray_invertpixel(int x, int y)
868{
869 if (graybuf == NULL || x >= graybuf->width || y >= graybuf->height)
870 return;
871
872 grayinvertmasked(x, (y >> 3), 1 << (y & 7));
873}
874
875/* Draw a line from (x1, y1) to (x2, y2) with a specific gray value
876 *
877 * brightness is 0..255 (black to white) regardless of real bit depth
878 */
879void gray_drawline(int x1, int y1, int x2, int y2, int brightness)
880{
881 int numpixels;
882 int i;
883 int deltax, deltay;
884 int d, dinc1, dinc2;
885 int x, xinc1, xinc2;
886 int y, yinc1, yinc2;
887 unsigned long pattern;
888
889 if (graybuf == NULL || x1 >= graybuf->width || y1 >= graybuf->height
890 || x2 >= graybuf->width || y2 >= graybuf->height|| brightness > 255)
891 return;
892
893 pattern = graybuf->bitpattern[(brightness * (graybuf->depth + 1)) >> 8];
894
895 deltax = abs(x2 - x1);
896 deltay = abs(y2 - y1);
897
898 if (deltax >= deltay)
899 {
900 numpixels = deltax;
901 d = 2 * deltay - deltax;
902 dinc1 = deltay * 2;
903 dinc2 = (deltay - deltax) * 2;
904 xinc1 = 1;
905 xinc2 = 1;
906 yinc1 = 0;
907 yinc2 = 1;
908 }
909 else
910 {
911 numpixels = deltay;
912 d = 2 * deltax - deltay;
913 dinc1 = deltax * 2;
914 dinc2 = (deltax - deltay) * 2;
915 xinc1 = 0;
916 xinc2 = 1;
917 yinc1 = 1;
918 yinc2 = 1;
919 }
920 numpixels++; /* include endpoints */
921
922 if (x1 > x2)
923 {
924 xinc1 = -xinc1;
925 xinc2 = -xinc2;
926 }
927
928 if (y1 > y2)
929 {
930 yinc1 = -yinc1;
931 yinc2 = -yinc2;
932 }
933
934 x = x1;
935 y = y1;
936
937 for (i=0; i<numpixels; i++)
938 {
939 graypixel(x, y, pattern);
940
941 if (d < 0)
942 {
943 d += dinc1;
944 x += xinc1;
945 y += yinc1;
946 }
947 else
948 {
949 d += dinc2;
950 x += xinc2;
951 y += yinc2;
952 }
953 }
954}
955
956/* Invert a line from (x1, y1) to (x2, y2)
957 *
958 * The bit patterns for the pixels of the line are inverted, so white becomes
959 * black, light gray becomes dark gray etc.
960 */
961void gray_invertline(int x1, int y1, int x2, int y2)
962{
963 int numpixels;
964 int i;
965 int deltax, deltay;
966 int d, dinc1, dinc2;
967 int x, xinc1, xinc2;
968 int y, yinc1, yinc2;
969
970 if (graybuf == NULL || x1 >= graybuf->width || y1 >= graybuf->height
971 || x2 >= graybuf->width || y2 >= graybuf->height)
972 return;
973
974 deltax = abs(x2 - x1);
975 deltay = abs(y2 - y1);
976
977 if (deltax >= deltay)
978 {
979 numpixels = deltax;
980 d = 2 * deltay - deltax;
981 dinc1 = deltay * 2;
982 dinc2 = (deltay - deltax) * 2;
983 xinc1 = 1;
984 xinc2 = 1;
985 yinc1 = 0;
986 yinc2 = 1;
987 }
988 else
989 {
990 numpixels = deltay;
991 d = 2 * deltax - deltay;
992 dinc1 = deltax * 2;
993 dinc2 = (deltax - deltay) * 2;
994 xinc1 = 0;
995 xinc2 = 1;
996 yinc1 = 1;
997 yinc2 = 1;
998 }
999 numpixels++; /* include endpoints */
1000
1001 if (x1 > x2)
1002 {
1003 xinc1 = -xinc1;
1004 xinc2 = -xinc2;
1005 }
1006
1007 if (y1 > y2)
1008 {
1009 yinc1 = -yinc1;
1010 yinc2 = -yinc2;
1011 }
1012
1013 x = x1;
1014 y = y1;
1015
1016 for (i=0; i<numpixels; i++)
1017 {
1018 grayinvertmasked(x, (y >> 3), 1 << (y & 7));
1019
1020 if (d < 0)
1021 {
1022 d += dinc1;
1023 x += xinc1;
1024 y += yinc1;
1025 }
1026 else
1027 {
1028 d += dinc2;
1029 x += xinc2;
1030 y += yinc2;
1031 }
1032 }
1033}
1034
1035/* Draw a (hollow) rectangle with a specific gray value,
1036 * corners are (x1, y1) and (x2, y2)
1037 *
1038 * brightness is 0..255 (black to white) regardless of real bit depth
1039 */
1040void gray_drawrect(int x1, int y1, int x2, int y2, int brightness)
1041{
1042 int x, y;
1043 unsigned long pattern;
1044
1045 if (graybuf == NULL || x1 >= graybuf->width || y1 >= graybuf->height
1046 || x2 >= graybuf->width || y2 >= graybuf->height|| brightness > 255)
1047 return;
1048
1049 pattern = graybuf->bitpattern[(brightness * (graybuf->depth + 1)) >> 8];
1050
1051 if (y1 > y2)
1052 {
1053 y = y1;
1054 y1 = y2;
1055 y2 = y;
1056 }
1057 if (x1 > x2)
1058 {
1059 x = x1;
1060 x1 = x2;
1061 x2 = x;
1062 }
1063
1064 for (x = x1; x <= x2; x++)
1065 {
1066 graypixel(x, y1, pattern);
1067 graypixel(x, y2, pattern);
1068 }
1069 for (y = y1; y <= y2; y++)
1070 {
1071 graypixel(x1, y, pattern);
1072 graypixel(x2, y, pattern);
1073 }
1074}
1075
1076/* Fill a rectangle with a specific gray value
1077 * corners are (x1, y1) and (x2, y2)
1078 *
1079 * brightness is 0..255 (black to white) regardless of real bit depth
1080 */
1081void gray_fillrect(int x1, int y1, int x2, int y2, int brightness)
1082{
1083 int x, y;
1084 unsigned long pattern;
1085
1086 if (graybuf == NULL || x1 >= graybuf->width || y1 >= graybuf->height
1087 || x2 >= graybuf->width || y2 >= graybuf->height || brightness > 255)
1088 return;
1089
1090 if (y1 > y2)
1091 {
1092 y = y1;
1093 y1 = y2;
1094 y2 = y;
1095 }
1096 if (x1 > x2)
1097 {
1098 x = x1;
1099 x1 = x2;
1100 x2 = x;
1101 }
1102
1103 pattern = graybuf->bitpattern[(brightness * (graybuf->depth + 1)) >> 8];
1104
1105 for (y = y1; y <= y2; y++)
1106 {
1107 for (x = x1; x <= x2; x++)
1108 {
1109 graypixel(x, y, pattern);
1110 }
1111 }
1112}
1113
1114/* Invert a (solid) rectangle, corners are (x1, y1) and (x2, y2)
1115 *
1116 * The bit patterns for all pixels of the rectangle are inverted, so white
1117 * becomes black, light gray becomes dark gray etc. This is the fastest of
1118 * all gray_xxxrect() functions! Perfectly suited for cursors.
1119 */
1120void gray_invertrect(int x1, int y1, int x2, int y2)
1121{
1122 int x, yb, yb1, yb2;
1123 unsigned char mask;
1124
1125 if (graybuf == NULL || x1 >= graybuf->width || y1 >= graybuf->height
1126 || x2 >= graybuf->width || y2 >= graybuf->height)
1127 return;
1128
1129 if (y1 > y2)
1130 {
1131 yb = y1;
1132 y1 = y2;
1133 y2 = yb;
1134 }
1135 if (x1 > x2)
1136 {
1137 x = x1;
1138 x1 = x2;
1139 x2 = x;
1140 }
1141
1142 yb1 = y1 >> 3;
1143 yb2 = y2 >> 3;
1144
1145 if (yb1 == yb2)
1146 {
1147 mask = 0xFF << (y1 & 7);
1148 mask &= 0xFF >> (7 - (y2 & 7));
1149
1150 for (x = x1; x <= x2; x++)
1151 grayinvertmasked(x, yb1, mask);
1152 }
1153 else
1154 {
1155 mask = 0xFF << (y1 & 7);
1156
1157 for (x = x1; x <= x2; x++)
1158 grayinvertmasked(x, yb1, mask);
1159
1160 for (yb = yb1 + 1; yb < yb2; yb++)
1161 {
1162 for (x = x1; x <= x2; x++)
1163 grayinvertmasked(x, yb, 0xFF);
1164 }
1165
1166 mask = 0xFF >> (7 - (y2 & 7));
1167
1168 for (x = x1; x <= x2; x++)
1169 grayinvertmasked(x, yb2, mask);
1170 }
1171}
1172
1173/* Copy a grayscale bitmap into the display
1174 *
1175 * A grayscale bitmap contains one byte for every pixel that defines the
1176 * brightness of the pixel (0..255). Bytes are read in row-major order.
1177 * The <stride> parameter is useful if you want to show only a part of a
1178 * bitmap. It should always be set to the "line length" of the bitmap, so
1179 * for displaying the whole bitmap, nx == stride.
1180 */
1181void gray_drawgraymap(unsigned char *src, int x, int y, int nx, int ny,
1182 int stride)
1183{
1184 int xi, yi;
1185 unsigned char *row;
1186
1187 if (graybuf == NULL || x >= graybuf->width || y >= graybuf->height)
1188 return;
1189
1190 if ((y + ny) >= graybuf->height) /* clip bottom */
1191 ny = graybuf->height - y;
1192
1193 if ((x + nx) >= graybuf->width) /* clip right */
1194 nx = graybuf->width - x;
1195
1196 for (yi = y; yi < y + ny; yi++)
1197 {
1198 row = src;
1199 src += stride;
1200 for (xi = x; xi < x + nx; xi++)
1201 {
1202 graypixel(xi, yi, graybuf->bitpattern[((int)(*row++)
1203 * (graybuf->depth + 1)) >> 8]);
1204 }
1205 }
1206}
1207
1208/* Display a bitmap with specific foreground and background gray values
1209 *
1210 * A bitmap contains one bit for every pixel that defines if that pixel is
1211 * foreground (1) or background (0). Bytes are read in row-major order, MSB
1212 * first. A row consists of an integer number of bytes, extra bits past the
1213 * right margin are ignored.
1214 * The <stride> parameter is useful if you want to show only a part of a
1215 * bitmap. It should always be set to the "line length" of the bitmap.
1216 * Beware that this is counted in bytes, so nx == 8 * stride for the whole
1217 * bitmap.
1218 *
1219 * If draw_bg is false, only foreground pixels are drawn, so the background
1220 * is transparent. In this case bg_brightness is ignored.
1221 */
1222void gray_drawbitmap(unsigned char *src, int x, int y, int nx, int ny,
1223 int stride, bool draw_bg, int fg_brightness,
1224 int bg_brightness)
1225{
1226 int xi, yi, i;
1227 unsigned long fg_pattern, bg_pattern;
1228 unsigned long bits = 0; /* Have to initialize to prevent warning */
1229 unsigned char *row;
1230
1231 if (graybuf == NULL || x >= graybuf->width || y >= graybuf->height
1232 || fg_brightness > 255 || bg_brightness > 255)
1233 return;
1234
1235 if ((y + ny) >= graybuf->height) /* clip bottom */
1236 ny = graybuf->height - y;
1237
1238 if ((x + nx) >= graybuf->width) /* clip right */
1239 nx = graybuf->width - x;
1240
1241 fg_pattern = graybuf->bitpattern[(fg_brightness
1242 * (graybuf->depth + 1)) >> 8];
1243
1244 bg_pattern = graybuf->bitpattern[(bg_brightness
1245 * (graybuf->depth + 1)) >> 8];
1246
1247 for (yi = y; yi < y + ny; yi++)
1248 {
1249 i = 0;
1250 row = src;
1251 src += stride;
1252 for (xi = x; xi < x + nx; xi++)
1253 {
1254 if (i == 0) /* get next 8 bits */
1255 bits = (unsigned long)(*row++);
1256
1257 if (bits & 0x80)
1258 graypixel(xi, yi, fg_pattern);
1259 else
1260 if (draw_bg)
1261 graypixel(xi, yi, bg_pattern);
1262
1263 bits <<= 1;
1264 i++;
1265 i &= 7;
1266 }
1267 }
1268}
1269
1270/**************** end grayscale framework ********************/
1271
1272#define MEMSET(p,v,c) rb->memset(p,v,c) // for portability of below
1273#define INLINE static inline
1274
1275/**************** begin JPEG code ********************/
1276
1277/* LUT for IDCT, this could also be used for gamma correction */
1278const unsigned char range_limit[1024] = {
1279 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
1280 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
1281 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
1282 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
1283 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
1284 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
1285 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
1286 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
1287
1288 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1289 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1290 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1291 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1292 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1293 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1294 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1295 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1296 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1297 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1298 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1299 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1300 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1301 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1302 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1303 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1304 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1305 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1306 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1307 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1308 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1309 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1310 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1311 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1312
1313 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1314 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1315 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1316 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1317 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1318 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1319 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1320 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1321 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1322 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1323 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1324 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1325 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1326 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1327 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1328 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1329 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1330 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1331 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1332 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1333 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1334 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1335 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1336 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1337
1338 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
1339 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
1340 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
1341 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
1342 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
1343 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
1344 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
1345 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127
1346};
1347
1348
1349/* IDCT implementation */
1350
1351
1352#define CONST_BITS 13
1353#define PASS1_BITS 2
1354
1355
1356/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
1357* causing a lot of useless floating-point operations at run time.
1358* To get around this we use the following pre-calculated constants.
1359* If you change CONST_BITS you may want to add appropriate values.
1360* (With a reasonable C compiler, you can just rely on the FIX() macro...)
1361*/
1362#define FIX_0_298631336 2446 /* FIX(0.298631336) */
1363#define FIX_0_390180644 3196 /* FIX(0.390180644) */
1364#define FIX_0_541196100 4433 /* FIX(0.541196100) */
1365#define FIX_0_765366865 6270 /* FIX(0.765366865) */
1366#define FIX_0_899976223 7373 /* FIX(0.899976223) */
1367#define FIX_1_175875602 9633 /* FIX(1.175875602) */
1368#define FIX_1_501321110 12299 /* FIX(1.501321110) */
1369#define FIX_1_847759065 15137 /* FIX(1.847759065) */
1370#define FIX_1_961570560 16069 /* FIX(1.961570560) */
1371#define FIX_2_053119869 16819 /* FIX(2.053119869) */
1372#define FIX_2_562915447 20995 /* FIX(2.562915447) */
1373#define FIX_3_072711026 25172 /* FIX(3.072711026) */
1374
1375
1376
1377/* Multiply an long variable by an long constant to yield an long result.
1378* For 8-bit samples with the recommended scaling, all the variable
1379* and constant values involved are no more than 16 bits wide, so a
1380* 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
1381* For 12-bit samples, a full 32-bit multiplication will be needed.
1382*/
1383#define MULTIPLY16(var,const) (((short) (var)) * ((short) (const)))
1384
1385
1386/* Dequantize a coefficient by multiplying it by the multiplier-table
1387* entry; produce an int result. In this module, both inputs and result
1388* are 16 bits or less, so either int or short multiply will work.
1389*/
1390/* #define DEQUANTIZE(coef,quantval) (((int) (coef)) * (quantval)) */
1391#define DEQUANTIZE MULTIPLY16
1392
1393/* Descale and correctly round an int value that's scaled by N bits.
1394* We assume RIGHT_SHIFT rounds towards minus infinity, so adding
1395* the fudge factor is correct for either sign of X.
1396*/
1397#define DESCALE(x,n) (((x) + (1l << ((n)-1))) >> (n))
1398
1399#define RANGE_MASK (255 * 4 + 3) /* 2 bits wider than legal samples */
1400
1401
1402
1403/*
1404* Perform dequantization and inverse DCT on one block of coefficients,
1405* producing a reduced-size 1x1 output block.
1406*/
1407void idct1x1(unsigned char* p_byte, int* inptr, int* quantptr, int skip_line)
1408{
1409 (void)skip_line; /* unused */
1410 *p_byte = range_limit[(inptr[0] * quantptr[0] >> 3) & RANGE_MASK];
1411}
1412
1413
1414
1415/*
1416* Perform dequantization and inverse DCT on one block of coefficients,
1417* producing a reduced-size 2x2 output block.
1418*/
1419void idct2x2(unsigned char* p_byte, int* inptr, int* quantptr, int skip_line)
1420{
1421 int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
1422 unsigned char* outptr;
1423
1424 /* Pass 1: process columns from input, store into work array. */
1425
1426 /* Column 0 */
1427 tmp4 = DEQUANTIZE(inptr[8*0], quantptr[8*0]);
1428 tmp5 = DEQUANTIZE(inptr[8*1], quantptr[8*1]);
1429
1430 tmp0 = tmp4 + tmp5;
1431 tmp2 = tmp4 - tmp5;
1432
1433 /* Column 1 */
1434 tmp4 = DEQUANTIZE(inptr[8*0+1], quantptr[8*0+1]);
1435 tmp5 = DEQUANTIZE(inptr[8*1+1], quantptr[8*1+1]);
1436
1437 tmp1 = tmp4 + tmp5;
1438 tmp3 = tmp4 - tmp5;
1439
1440 /* Pass 2: process 2 rows, store into output array. */
1441
1442 /* Row 0 */
1443 outptr = p_byte;
1444
1445 outptr[0] = range_limit[(int) DESCALE(tmp0 + tmp1, 3)
1446 & RANGE_MASK];
1447 outptr[1] = range_limit[(int) DESCALE(tmp0 - tmp1, 3)
1448 & RANGE_MASK];
1449
1450 /* Row 1 */
1451 outptr = p_byte + skip_line;
1452
1453 outptr[0] = range_limit[(int) DESCALE(tmp2 + tmp3, 3)
1454 & RANGE_MASK];
1455 outptr[1] = range_limit[(int) DESCALE(tmp2 - tmp3, 3)
1456 & RANGE_MASK];
1457}
1458
1459
1460
1461/*
1462* Perform dequantization and inverse DCT on one block of coefficients,
1463* producing a reduced-size 4x4 output block.
1464*/
1465void idct4x4(unsigned char* p_byte, int* inptr, int* quantptr, int skip_line)
1466{
1467 int tmp0, tmp2, tmp10, tmp12;
1468 int z1, z2, z3;
1469 int * wsptr;
1470 unsigned char* outptr;
1471 int ctr;
1472 int workspace[4*4]; /* buffers data between passes */
1473
1474 /* Pass 1: process columns from input, store into work array. */
1475
1476 wsptr = workspace;
1477 for (ctr = 0; ctr < 4; ctr++, inptr++, quantptr++, wsptr++)
1478 {
1479 /* Even part */
1480
1481 tmp0 = DEQUANTIZE(inptr[8*0], quantptr[8*0]);
1482 tmp2 = DEQUANTIZE(inptr[8*2], quantptr[8*2]);
1483
1484 tmp10 = (tmp0 + tmp2) << PASS1_BITS;
1485 tmp12 = (tmp0 - tmp2) << PASS1_BITS;
1486
1487 /* Odd part */
1488 /* Same rotation as in the even part of the 8x8 LL&M IDCT */
1489
1490 z2 = DEQUANTIZE(inptr[8*1], quantptr[8*1]);
1491 z3 = DEQUANTIZE(inptr[8*3], quantptr[8*3]);
1492
1493 z1 = MULTIPLY16(z2 + z3, FIX_0_541196100);
1494 tmp0 = DESCALE(z1 + MULTIPLY16(z3, - FIX_1_847759065), CONST_BITS-PASS1_BITS);
1495 tmp2 = DESCALE(z1 + MULTIPLY16(z2, FIX_0_765366865), CONST_BITS-PASS1_BITS);
1496
1497 /* Final output stage */
1498
1499 wsptr[4*0] = (int) (tmp10 + tmp2);
1500 wsptr[4*3] = (int) (tmp10 - tmp2);
1501 wsptr[4*1] = (int) (tmp12 + tmp0);
1502 wsptr[4*2] = (int) (tmp12 - tmp0);
1503 }
1504
1505 /* Pass 2: process 4 rows from work array, store into output array. */
1506
1507 wsptr = workspace;
1508 for (ctr = 0; ctr < 4; ctr++)
1509 {
1510 outptr = p_byte + (ctr*skip_line);
1511 /* Even part */
1512
1513 tmp0 = (int) wsptr[0];
1514 tmp2 = (int) wsptr[2];
1515
1516 tmp10 = (tmp0 + tmp2) << CONST_BITS;
1517 tmp12 = (tmp0 - tmp2) << CONST_BITS;
1518
1519 /* Odd part */
1520 /* Same rotation as in the even part of the 8x8 LL&M IDCT */
1521
1522 z2 = (int) wsptr[1];
1523 z3 = (int) wsptr[3];
1524
1525 z1 = MULTIPLY16(z2 + z3, FIX_0_541196100);
1526 tmp0 = z1 + MULTIPLY16(z3, - FIX_1_847759065);
1527 tmp2 = z1 + MULTIPLY16(z2, FIX_0_765366865);
1528
1529 /* Final output stage */
1530
1531 outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp2,
1532 CONST_BITS+PASS1_BITS+3)
1533 & RANGE_MASK];
1534 outptr[3] = range_limit[(int) DESCALE(tmp10 - tmp2,
1535 CONST_BITS+PASS1_BITS+3)
1536 & RANGE_MASK];
1537 outptr[1] = range_limit[(int) DESCALE(tmp12 + tmp0,
1538 CONST_BITS+PASS1_BITS+3)
1539 & RANGE_MASK];
1540 outptr[2] = range_limit[(int) DESCALE(tmp12 - tmp0,
1541 CONST_BITS+PASS1_BITS+3)
1542 & RANGE_MASK];
1543
1544 wsptr += 4; /* advance pointer to next row */
1545 }
1546}
1547
1548
1549
1550/*
1551* Perform dequantization and inverse DCT on one block of coefficients.
1552*/
1553void idct8x8(unsigned char* p_byte, int* inptr, int* quantptr, int skip_line)
1554{
1555 long tmp0, tmp1, tmp2, tmp3;
1556 long tmp10, tmp11, tmp12, tmp13;
1557 long z1, z2, z3, z4, z5;
1558 int * wsptr;
1559 unsigned char* outptr;
1560 int ctr;
1561 static int workspace[64]; /* buffers data between passes */
1562
1563 /* Pass 1: process columns from input, store into work array. */
1564 /* Note results are scaled up by sqrt(8) compared to a true IDCT; */
1565 /* furthermore, we scale the results by 2**PASS1_BITS. */
1566
1567 wsptr = workspace;
1568 for (ctr = 8; ctr > 0; ctr--)
1569 {
1570 /* Due to quantization, we will usually find that many of the input
1571 * coefficients are zero, especially the AC terms. We can exploit this
1572 * by short-circuiting the IDCT calculation for any column in which all
1573 * the AC terms are zero. In that case each output is equal to the
1574 * DC coefficient (with scale factor as needed).
1575 * With typical images and quantization tables, half or more of the
1576 * column DCT calculations can be simplified this way.
1577 */
1578
1579 if ((inptr[8*1] | inptr[8*2] | inptr[8*3]
1580 | inptr[8*4] | inptr[8*5] | inptr[8*6] | inptr[8*7]) == 0)
1581 {
1582 /* AC terms all zero */
1583 int dcval = DEQUANTIZE(inptr[8*0], quantptr[8*0]) << PASS1_BITS;
1584
1585 wsptr[8*0] = wsptr[8*1] = wsptr[8*2] = wsptr[8*3] = wsptr[8*4]
1586 = wsptr[8*5] = wsptr[8*6] = wsptr[8*7] = dcval;
1587 inptr++; /* advance pointers to next column */
1588 quantptr++;
1589 wsptr++;
1590 continue;
1591 }
1592
1593 /* Even part: reverse the even part of the forward DCT. */
1594 /* The rotator is sqrt(2)*c(-6). */
1595
1596 z2 = DEQUANTIZE(inptr[8*2], quantptr[8*2]);
1597 z3 = DEQUANTIZE(inptr[8*6], quantptr[8*6]);
1598
1599 z1 = MULTIPLY16(z2 + z3, FIX_0_541196100);
1600 tmp2 = z1 + MULTIPLY16(z3, - FIX_1_847759065);
1601 tmp3 = z1 + MULTIPLY16(z2, FIX_0_765366865);
1602
1603 z2 = DEQUANTIZE(inptr[8*0], quantptr[8*0]);
1604 z3 = DEQUANTIZE(inptr[8*4], quantptr[8*4]);
1605
1606 tmp0 = (z2 + z3) << CONST_BITS;
1607 tmp1 = (z2 - z3) << CONST_BITS;
1608
1609 tmp10 = tmp0 + tmp3;
1610 tmp13 = tmp0 - tmp3;
1611 tmp11 = tmp1 + tmp2;
1612 tmp12 = tmp1 - tmp2;
1613
1614 /* Odd part per figure 8; the matrix is unitary and hence its
1615 transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */
1616
1617 tmp0 = DEQUANTIZE(inptr[8*7], quantptr[8*7]);
1618 tmp1 = DEQUANTIZE(inptr[8*5], quantptr[8*5]);
1619 tmp2 = DEQUANTIZE(inptr[8*3], quantptr[8*3]);
1620 tmp3 = DEQUANTIZE(inptr[8*1], quantptr[8*1]);
1621
1622 z1 = tmp0 + tmp3;
1623 z2 = tmp1 + tmp2;
1624 z3 = tmp0 + tmp2;
1625 z4 = tmp1 + tmp3;
1626 z5 = MULTIPLY16(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
1627
1628 tmp0 = MULTIPLY16(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
1629 tmp1 = MULTIPLY16(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
1630 tmp2 = MULTIPLY16(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
1631 tmp3 = MULTIPLY16(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
1632 z1 = MULTIPLY16(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
1633 z2 = MULTIPLY16(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
1634 z3 = MULTIPLY16(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
1635 z4 = MULTIPLY16(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
1636
1637 z3 += z5;
1638 z4 += z5;
1639
1640 tmp0 += z1 + z3;
1641 tmp1 += z2 + z4;
1642 tmp2 += z2 + z3;
1643 tmp3 += z1 + z4;
1644
1645 /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
1646
1647 wsptr[8*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
1648 wsptr[8*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
1649 wsptr[8*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
1650 wsptr[8*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
1651 wsptr[8*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
1652 wsptr[8*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
1653 wsptr[8*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
1654 wsptr[8*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
1655
1656 inptr++; /* advance pointers to next column */
1657 quantptr++;
1658 wsptr++;
1659 }
1660
1661 /* Pass 2: process rows from work array, store into output array. */
1662 /* Note that we must descale the results by a factor of 8 == 2**3, */
1663 /* and also undo the PASS1_BITS scaling. */
1664
1665 wsptr = workspace;
1666 for (ctr = 0; ctr < 8; ctr++) {
1667 outptr = p_byte + (ctr*skip_line);
1668 /* Rows of zeroes can be exploited in the same way as we did with columns.
1669 * However, the column calculation has created many nonzero AC terms, so
1670 * the simplification applies less often (typically 5% to 10% of the time).
1671 * On machines with very fast multiplication, it's possible that the
1672 * test takes more time than it's worth. In that case this section
1673 * may be commented out.
1674 */
1675
1676#ifndef NO_ZERO_ROW_TEST
1677 if ((wsptr[1] | wsptr[2] | wsptr[3]
1678 | wsptr[4] | wsptr[5] | wsptr[6] | wsptr[7]) == 0)
1679 {
1680 /* AC terms all zero */
1681 unsigned char dcval = range_limit[(int) DESCALE((long) wsptr[0],
1682 PASS1_BITS+3) & RANGE_MASK];
1683
1684 outptr[0] = dcval;
1685 outptr[1] = dcval;
1686 outptr[2] = dcval;
1687 outptr[3] = dcval;
1688 outptr[4] = dcval;
1689 outptr[5] = dcval;
1690 outptr[6] = dcval;
1691 outptr[7] = dcval;
1692
1693 wsptr += 8; /* advance pointer to next row */
1694 continue;
1695 }
1696#endif
1697
1698 /* Even part: reverse the even part of the forward DCT. */
1699 /* The rotator is sqrt(2)*c(-6). */
1700
1701 z2 = (long) wsptr[2];
1702 z3 = (long) wsptr[6];
1703
1704 z1 = MULTIPLY16(z2 + z3, FIX_0_541196100);
1705 tmp2 = z1 + MULTIPLY16(z3, - FIX_1_847759065);
1706 tmp3 = z1 + MULTIPLY16(z2, FIX_0_765366865);
1707
1708 tmp0 = ((long) wsptr[0] + (long) wsptr[4]) << CONST_BITS;
1709 tmp1 = ((long) wsptr[0] - (long) wsptr[4]) << CONST_BITS;
1710
1711 tmp10 = tmp0 + tmp3;
1712 tmp13 = tmp0 - tmp3;
1713 tmp11 = tmp1 + tmp2;
1714 tmp12 = tmp1 - tmp2;
1715
1716 /* Odd part per figure 8; the matrix is unitary and hence its
1717 * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */
1718
1719 tmp0 = (long) wsptr[7];
1720 tmp1 = (long) wsptr[5];
1721 tmp2 = (long) wsptr[3];
1722 tmp3 = (long) wsptr[1];
1723
1724 z1 = tmp0 + tmp3;
1725 z2 = tmp1 + tmp2;
1726 z3 = tmp0 + tmp2;
1727 z4 = tmp1 + tmp3;
1728 z5 = MULTIPLY16(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
1729
1730 tmp0 = MULTIPLY16(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
1731 tmp1 = MULTIPLY16(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
1732 tmp2 = MULTIPLY16(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
1733 tmp3 = MULTIPLY16(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
1734 z1 = MULTIPLY16(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
1735 z2 = MULTIPLY16(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
1736 z3 = MULTIPLY16(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
1737 z4 = MULTIPLY16(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
1738
1739 z3 += z5;
1740 z4 += z5;
1741
1742 tmp0 += z1 + z3;
1743 tmp1 += z2 + z4;
1744 tmp2 += z2 + z3;
1745 tmp3 += z1 + z4;
1746
1747 /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
1748
1749 outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3,
1750 CONST_BITS+PASS1_BITS+3) & RANGE_MASK];
1751 outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3,
1752 CONST_BITS+PASS1_BITS+3) & RANGE_MASK];
1753 outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2,
1754 CONST_BITS+PASS1_BITS+3) & RANGE_MASK];
1755 outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2,
1756 CONST_BITS+PASS1_BITS+3) & RANGE_MASK];
1757 outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1,
1758 CONST_BITS+PASS1_BITS+3) & RANGE_MASK];
1759 outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1,
1760 CONST_BITS+PASS1_BITS+3) & RANGE_MASK];
1761 outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0,
1762 CONST_BITS+PASS1_BITS+3) & RANGE_MASK];
1763 outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0,
1764 CONST_BITS+PASS1_BITS+3) & RANGE_MASK];
1765
1766 wsptr += 8; /* advance pointer to next row */
1767 }
1768}
1769
1770
1771
1772/* JPEG decoder implementation */
1773
1774
1775#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */
1776
1777struct derived_tbl
1778{
1779 /* Basic tables: (element [0] of each array is unused) */
1780 long mincode[17]; /* smallest code of length k */
1781 long maxcode[18]; /* largest code of length k (-1 if none) */
1782 /* (maxcode[17] is a sentinel to ensure huff_DECODE terminates) */
1783 int valptr[17]; /* huffval[] index of 1st symbol of length k */
1784
1785 /* Back link to public Huffman table (needed only in slow_DECODE) */
1786 int* pub;
1787
1788 /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of
1789 the input data stream. If the next Huffman code is no more
1790 than HUFF_LOOKAHEAD bits long, we can obtain its length and
1791 the corresponding symbol directly from these tables. */
1792 int look_nbits[1<<HUFF_LOOKAHEAD]; /* # bits, or 0 if too long */
1793 unsigned char look_sym[1<<HUFF_LOOKAHEAD]; /* symbol, or unused */
1794};
1795
1796#define QUANT_TABLE_LENGTH 64
1797
1798/* for type of Huffman table */
1799#define DC_LEN 28
1800#define AC_LEN 178
1801
1802struct huffman_table
1803{ /* length and code according to JFIF format */
1804 int huffmancodes_dc[DC_LEN];
1805 int huffmancodes_ac[AC_LEN];
1806};
1807
1808struct frame_component
1809{
1810 int ID;
1811 int horizontal_sampling;
1812 int vertical_sampling;
1813 int quanttable_select;
1814};
1815
1816struct scan_component
1817{
1818 int ID;
1819 int DC_select;
1820 int AC_select;
1821};
1822
1823struct bitstream
1824{
1825 unsigned long get_buffer; /* current bit-extraction buffer */
1826 int bits_left; /* # of unused bits in it */
1827 unsigned short* next_input_word;
1828 long words_left; /* # of words remaining in source buffer */
1829};
1830
1831struct jpeg
1832{
1833 int x_size, y_size; /* size of image (can be less than block boundary) */
1834 int x_phys, y_phys; /* physical size, block aligned */
1835 int x_mbl; /* x dimension of MBL */
1836 int y_mbl; /* y dimension of MBL */
1837 int blocks; /* blocks per MBL */
1838
1839 unsigned short* p_entropy_data;
1840 long words_in_buffer; /* # of valid words in source buffer */
1841
1842 int quanttable[4][QUANT_TABLE_LENGTH]; /* raw quantization tables 0-3 */
1843 int qt_idct[2][QUANT_TABLE_LENGTH]; /* quantization tables for IDCT */
1844
1845 struct huffman_table hufftable[2]; /* Huffman tables */
1846 struct derived_tbl dc_derived_tbls[2]; /* Huffman-LUTs */
1847 struct derived_tbl ac_derived_tbls[2];
1848
1849 struct frame_component frameheader[3]; /* Component descriptor */
1850 struct scan_component scanheader[3]; /* currently not used */
1851
1852 int mcu_membership[6]; /* info per block */
1853 int tab_membership[6];
1854};
1855
1856
1857/* possible return flags for process_markers() */
1858#define HUFFTAB 0x0001 /* with huffman table */
1859#define QUANTTAB 0x0002 /* with quantization table */
1860#define APP0_JFIF 0x0004 /* with APP0 segment following JFIF standard */
1861#define FILL_FF 0x0008 /* with 0xFF padding bytes at begin/end */
1862#define SOF0 0x0010 /* with SOF0-Segment */
1863#define DHT 0x0020 /* with Definition of huffman tables */
1864#define SOS 0x0040 /* with Start-of-Scan segment */
1865#define DQT 0x0080 /* with definition of quantization table */
1866
1867/* Preprocess the JPEG JFIF file */
1868int process_markers(unsigned char* p_bytes, long size, struct jpeg* p_jpeg)
1869{
1870 unsigned char* p_src = p_bytes;
1871 unsigned char* p_temp;
1872
1873 /* write without markers nor stuffing in same buffer */
1874 unsigned short* p_dest = (unsigned short*) p_bytes;
1875 int marker_size; /* variable length of marker segment */
1876 int i, j, n;
1877 unsigned char highbyte, lowbyte;
1878 int ret = 0; /* returned flags */
1879
1880 /* memory location for later decompress */
1881 p_jpeg->p_entropy_data = (unsigned short*)p_bytes;
1882
1883 while (p_src < p_bytes + size)
1884 {
1885 if (*p_src++ != 0xFF) /* no marker? */
1886 {
1887 p_src--; /* it's image data, put it back */
1888 break; /* exit marker processing */
1889 }
1890
1891 switch (*p_src++)
1892 {
1893 case 0xFF: /* Fill byte */
1894 ret |= FILL_FF;
1895 case 0x00: /* Zero stuffed byte - entropy data */
1896 p_src--; /* put it back */
1897 continue;
1898
1899 case 0xC0: /* SOF Huff - Baseline DCT */
1900 {
1901 ret |= SOF0;
1902 marker_size = *p_src++ << 8; /* Highbyte */
1903 marker_size |= *p_src++; /* Lowbyte */
1904 n = *p_src++; /* sample precision (= 8 or 12) */
1905 if (n != 8)
1906 {
1907 return(-1); /* Unsupported sample precision */
1908 }
1909 p_jpeg->y_size = *p_src++ << 8; /* Highbyte */
1910 p_jpeg->y_size |= *p_src++; /* Lowbyte */
1911 p_jpeg->x_size = *p_src++ << 8; /* Highbyte */
1912 p_jpeg->x_size |= *p_src++; /* Lowbyte */
1913
1914 n = (marker_size-2-6)/3;
1915 if (*p_src++ != n || (n != 1 && n != 3))
1916 {
1917 return(-2); /* Unsupported SOF0 component specification */
1918 }
1919 for (i=0; i<n; i++)
1920 {
1921 p_jpeg->frameheader[i].ID = *p_src++; /* Component info */
1922 p_jpeg->frameheader[i].horizontal_sampling = *p_src >> 4;
1923 p_jpeg->frameheader[i].vertical_sampling = *p_src++ & 0x0F;
1924 p_jpeg->frameheader[i].quanttable_select = *p_src++;
1925 }
1926
1927 /* assignments for the decoding of blocks */
1928 if (p_jpeg->frameheader[0].horizontal_sampling == 2
1929 && p_jpeg->frameheader[0].vertical_sampling == 1)
1930 { /* 4:2:2 */
1931 p_jpeg->blocks = 4;
1932 p_jpeg->x_mbl = (p_jpeg->x_size+15) / 16;
1933 p_jpeg->x_phys = p_jpeg->x_mbl * 16;
1934 p_jpeg->y_mbl = (p_jpeg->y_size+7) / 8;
1935 p_jpeg->y_phys = p_jpeg->y_mbl * 8;
1936 p_jpeg->mcu_membership[0] = 0; /* Y1=Y2=0, U=2, V=3 */
1937 p_jpeg->mcu_membership[1] = 0;
1938 p_jpeg->mcu_membership[2] = 2;
1939 p_jpeg->mcu_membership[3] = 3;
1940 p_jpeg->tab_membership[0] = 0; /* DC, DC, AC, AC */
1941 p_jpeg->tab_membership[1] = 0;
1942 p_jpeg->tab_membership[2] = 1;
1943 p_jpeg->tab_membership[3] = 1;
1944 }
1945 else if (p_jpeg->frameheader[0].horizontal_sampling == 2
1946 && p_jpeg->frameheader[0].vertical_sampling == 2)
1947 { /* 4:2:0 */
1948 p_jpeg->blocks = 6;
1949 p_jpeg->x_mbl = (p_jpeg->x_size+15) / 16;
1950 p_jpeg->x_phys = p_jpeg->x_mbl * 16;
1951 p_jpeg->y_mbl = (p_jpeg->y_size+15) / 16;
1952 p_jpeg->y_phys = p_jpeg->y_mbl * 16;
1953 p_jpeg->mcu_membership[0] = 0;
1954 p_jpeg->mcu_membership[1] = 0;
1955 p_jpeg->mcu_membership[2] = 0;
1956 p_jpeg->mcu_membership[3] = 0;
1957 p_jpeg->mcu_membership[4] = 2;
1958 p_jpeg->mcu_membership[5] = 3;
1959 p_jpeg->tab_membership[0] = 0;
1960 p_jpeg->tab_membership[1] = 0;
1961 p_jpeg->tab_membership[2] = 0;
1962 p_jpeg->tab_membership[3] = 0;
1963 p_jpeg->tab_membership[4] = 1;
1964 p_jpeg->tab_membership[5] = 1;
1965 }
1966 else if (p_jpeg->frameheader[0].horizontal_sampling == 1
1967 && p_jpeg->frameheader[0].vertical_sampling == 1)
1968 { /* 4:4:4 */
1969 p_jpeg->blocks = n;
1970 p_jpeg->x_mbl = (p_jpeg->x_size+7) / 8;
1971 p_jpeg->x_phys = p_jpeg->x_mbl * 8;
1972 p_jpeg->y_mbl = (p_jpeg->y_size+7) / 8;
1973 p_jpeg->y_phys = p_jpeg->y_mbl * 8;
1974 p_jpeg->mcu_membership[0] = 0;
1975 p_jpeg->mcu_membership[1] = 2;
1976 p_jpeg->mcu_membership[2] = 3;
1977 p_jpeg->tab_membership[0] = 0;
1978 p_jpeg->tab_membership[1] = 1;
1979 p_jpeg->tab_membership[2] = 1;
1980 }
1981 else
1982 {
1983 return(-3); /* Unsupported SOF0 subsampling */
1984 }
1985
1986 }
1987 break;
1988
1989 case 0xC1: /* SOF Huff - Extended sequential DCT*/
1990 case 0xC2: /* SOF Huff - Progressive DCT*/
1991 case 0xC3: /* SOF Huff - Spatial (sequential) lossless*/
1992 case 0xC5: /* SOF Huff - Differential sequential DCT*/
1993 case 0xC6: /* SOF Huff - Differential progressive DCT*/
1994 case 0xC7: /* SOF Huff - Differential spatial*/
1995 case 0xC8: /* SOF Arith - Reserved for JPEG extensions*/
1996 case 0xC9: /* SOF Arith - Extended sequential DCT*/
1997 case 0xCA: /* SOF Arith - Progressive DCT*/
1998 case 0xCB: /* SOF Arith - Spatial (sequential) lossless*/
1999 case 0xCD: /* SOF Arith - Differential sequential DCT*/
2000 case 0xCE: /* SOF Arith - Differential progressive DCT*/
2001 case 0xCF: /* SOF Arith - Differential spatial*/
2002 {
2003 return (-4); /* other DCT model than baseline not implemented */
2004 }
2005
2006 case 0xC4: /* Define Huffman Table(s) */
2007 {
2008 ret |= DHT;
2009 marker_size = *p_src++ << 8; /* Highbyte */
2010 marker_size |= *p_src++; /* Lowbyte */
2011
2012 p_temp = p_src;
2013 while (p_src < p_temp+marker_size-2) /* another table */
2014 {
2015 i = *p_src & 0x0F; /* table index */
2016 if (i > 1)
2017 {
2018 return (-5); /* Huffman table index out of range */
2019 }
2020 if (*p_src++ & 0xF0) /* AC table */
2021 {
2022 for (j=0; j<AC_LEN; j++)
2023 p_jpeg->hufftable[i].huffmancodes_ac[j] = *p_src++;
2024 }
2025 else /* DC table */
2026 {
2027 for (j=0; j<DC_LEN; j++)
2028 p_jpeg->hufftable[i].huffmancodes_dc[j] = *p_src++;
2029 }
2030 } /* while */
2031 }
2032 break;
2033
2034 case 0xCC: /* Define Arithmetic coding conditioning(s) */
2035 return(-6); /* Arithmetic coding not supported */
2036
2037 case 0xD0: /* Restart with modulo 8 count 0 */
2038 case 0xD1: /* Restart with modulo 8 count 1 */
2039 case 0xD2: /* Restart with modulo 8 count 2 */
2040 case 0xD3: /* Restart with modulo 8 count 3 */
2041 case 0xD4: /* Restart with modulo 8 count 4 */
2042 case 0xD5: /* Restart with modulo 8 count 5 */
2043 case 0xD6: /* Restart with modulo 8 count 6 */
2044 case 0xD7: /* Restart with modulo 8 count 7 */
2045 case 0xD8: /* Start of Image */
2046 case 0xD9: /* End of Image */
2047 case 0x01: /* for temp private use arith code */
2048 break; /* skip parameterless marker */
2049
2050
2051 case 0xDA: /* Start of Scan */
2052 {
2053 ret |= SOS;
2054 marker_size = *p_src++ << 8; /* Highbyte */
2055 marker_size |= *p_src++; /* Lowbyte */
2056
2057 n = (marker_size-2-1-3)/2;
2058 if (*p_src++ != n || (n != 1 && n != 3))
2059 {
2060 return (-7); /* Unsupported SOS component specification */
2061 }
2062 for (i=0; i<n; i++)
2063 {
2064 p_jpeg->scanheader[i].ID = *p_src++;
2065 p_jpeg->scanheader[i].DC_select = *p_src >> 4;
2066 p_jpeg->scanheader[i].AC_select = *p_src++ & 0x0F;
2067 }
2068 p_src += 3; /* skip spectral information */
2069 }
2070 break;
2071
2072 case 0xDB: /* Define quantization Table(s) */
2073 {
2074 ret |= DQT;
2075 marker_size = *p_src++ << 8; /* Highbyte */
2076 marker_size |= *p_src++; /* Lowbyte */
2077 n = (marker_size-2)/(QUANT_TABLE_LENGTH+1); /* # of tables */
2078 for (i=0; i<n; i++)
2079 {
2080 int id = *p_src++; /* ID */
2081 if (id >= 4)
2082 {
2083 return (-8); /* Unsupported quantization table */
2084 }
2085 /* Read Quantisation table: */
2086 for (j=0; j<QUANT_TABLE_LENGTH; j++)
2087 p_jpeg->quanttable[id][j] = *p_src++;
2088 }
2089 }
2090 break;
2091
2092 case 0xDC: /* Define Number of Lines */
2093 case 0xDD: /* Define Restart Interval */
2094 case 0xDE: /* Define Hierarchical progression */
2095 case 0xDF: /* Expand Reference Component(s) */
2096 case 0xE0: /* Application Field 0*/
2097 case 0xE1: /* Application Field 1*/
2098 case 0xE2: /* Application Field 2*/
2099 case 0xE3: /* Application Field 3*/
2100 case 0xE4: /* Application Field 4*/
2101 case 0xE5: /* Application Field 5*/
2102 case 0xE6: /* Application Field 6*/
2103 case 0xE7: /* Application Field 7*/
2104 case 0xFE: /* Comment */
2105 {
2106 marker_size = *p_src++ << 8; /* Highbyte */
2107 marker_size |= *p_src++; /* Lowbyte */
2108 p_src += marker_size-2; /* skip segment */
2109 }
2110 break;
2111
2112 case 0xF0: /* Reserved for JPEG extensions */
2113 case 0xF1: /* Reserved for JPEG extensions */
2114 case 0xF2: /* Reserved for JPEG extensions */
2115 case 0xF3: /* Reserved for JPEG extensions */
2116 case 0xF4: /* Reserved for JPEG extensions */
2117 case 0xF5: /* Reserved for JPEG extensions */
2118 case 0xF6: /* Reserved for JPEG extensions */
2119 case 0xF7: /* Reserved for JPEG extensions */
2120 case 0xF8: /* Reserved for JPEG extensions */
2121 case 0xF9: /* Reserved for JPEG extensions */
2122 case 0xFA: /* Reserved for JPEG extensions */
2123 case 0xFB: /* Reserved for JPEG extensions */
2124 case 0xFC: /* Reserved for JPEG extensions */
2125 case 0xFD: /* Reserved for JPEG extensions */
2126 case 0x02: /* Reserved */
2127 default:
2128 return (-9); /* Unknown marker */
2129 } /* switch */
2130 } /* while */
2131
2132 /* undo byte stuffing, endian conversion */
2133 /* ToDo: remove restart markers, if present */
2134 while (p_src < p_bytes + size)
2135 {
2136 highbyte = *p_src++;
2137 if (highbyte==0xFF && *p_src++) break; /* end on marker */
2138 lowbyte = *p_src++;
2139 if (lowbyte==0xFF && *p_src++)
2140 {
2141 *p_dest++ = highbyte<<8; /* write remaining */
2142 break; /* end on marker */
2143 }
2144 *p_dest++ = highbyte<<8 | lowbyte;
2145 }
2146 MEMSET(p_dest, 0, size-((unsigned char*)p_dest-p_bytes)); /* fill tail with zeros */
2147 p_jpeg->words_in_buffer = p_dest-(unsigned short*)p_bytes;
2148 return (ret); /* return flags with seen markers */
2149}
2150
2151
2152void default_huff_tbl(struct jpeg* p_jpeg)
2153{
2154 static const struct huffman_table luma_table =
2155 {
2156 {
2157 0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,
2158 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B
2159 },
2160 {
2161 0x00,0x02,0x01,0x03,0x03,0x02,0x04,0x03,0x05,0x05,0x04,0x04,0x00,0x00,0x01,0x7D,
2162 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,
2163 0x22,0x71,0x14,0x32,0x81,0x91,0xA1,0x08,0x23,0x42,0xB1,0xC1,0x15,0x52,0xD1,0xF0,
2164 0x24,0x33,0x62,0x72,0x82,0x09,0x0A,0x16,0x17,0x18,0x19,0x1A,0x25,0x26,0x27,0x28,
2165 0x29,0x2A,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,
2166 0x4A,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,
2167 0x6A,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
2168 0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,
2169 0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xC2,0xC3,0xC4,0xC5,
2170 0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xE1,0xE2,
2171 0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,
2172 0xF9,0xFA
2173 }
2174 };
2175
2176 static const struct huffman_table chroma_table =
2177 {
2178 {
2179 0x00,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,
2180 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B
2181 },
2182 {
2183 0x00,0x02,0x01,0x02,0x04,0x04,0x03,0x04,0x07,0x05,0x04,0x04,0x00,0x01,0x02,0x77,
2184 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,
2185 0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xA1,0xB1,0xC1,0x09,0x23,0x33,0x52,0xF0,
2186 0x15,0x62,0x72,0xD1,0x0A,0x16,0x24,0x34,0xE1,0x25,0xF1,0x17,0x18,0x19,0x1A,0x26,
2187 0x27,0x28,0x29,0x2A,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,
2188 0x49,0x4A,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,
2189 0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x82,0x83,0x84,0x85,0x86,0x87,
2190 0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5,
2191 0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xC2,0xC3,
2192 0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,
2193 0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,
2194 0xF9,0xFA
2195 }
2196 };
2197
2198 p_jpeg->hufftable[0] = luma_table;
2199 p_jpeg->hufftable[1] = chroma_table;
2200
2201 return;
2202}
2203
2204/* Compute the derived values for a Huffman table */
2205void fix_huff_tbl(int* htbl, struct derived_tbl* dtbl)
2206{
2207 int p, i, l, si;
2208 int lookbits, ctr;
2209 char huffsize[257];
2210 unsigned int huffcode[257];
2211 unsigned int code;
2212
2213 dtbl->pub = htbl; /* fill in back link */
2214
2215 /* Figure C.1: make table of Huffman code length for each symbol */
2216 /* Note that this is in code-length order. */
2217
2218 p = 0;
2219 for (l = 1; l <= 16; l++)
2220 { /* all possible code length */
2221 for (i = 1; i <= (int) htbl[l-1]; i++) /* all codes per length */
2222 huffsize[p++] = (char) l;
2223 }
2224 huffsize[p] = 0;
2225
2226 /* Figure C.2: generate the codes themselves */
2227 /* Note that this is in code-length order. */
2228
2229 code = 0;
2230 si = huffsize[0];
2231 p = 0;
2232 while (huffsize[p])
2233 {
2234 while (((int) huffsize[p]) == si)
2235 {
2236 huffcode[p++] = code;
2237 code++;
2238 }
2239 code <<= 1;
2240 si++;
2241 }
2242
2243 /* Figure F.15: generate decoding tables for bit-sequential decoding */
2244
2245 p = 0;
2246 for (l = 1; l <= 16; l++)
2247 {
2248 if (htbl[l-1])
2249 {
2250 dtbl->valptr[l] = p; /* huffval[] index of 1st symbol of code length l */
2251 dtbl->mincode[l] = huffcode[p]; /* minimum code of length l */
2252 p += htbl[l-1];
2253 dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */
2254 }
2255 else
2256 {
2257 dtbl->maxcode[l] = -1; /* -1 if no codes of this length */
2258 }
2259 }
2260 dtbl->maxcode[17] = 0xFFFFFL; /* ensures huff_DECODE terminates */
2261
2262 /* Compute lookahead tables to speed up decoding.
2263 * First we set all the table entries to 0, indicating "too long";
2264 * then we iterate through the Huffman codes that are short enough and
2265 * fill in all the entries that correspond to bit sequences starting
2266 * with that code.
2267 */
2268
2269 MEMSET(dtbl->look_nbits, 0, sizeof(dtbl->look_nbits));
2270
2271 p = 0;
2272 for (l = 1; l <= HUFF_LOOKAHEAD; l++)
2273 {
2274 for (i = 1; i <= (int) htbl[l-1]; i++, p++)
2275 {
2276 /* l = current code's length, p = its index in huffcode[] & huffval[]. */
2277 /* Generate left-justified code followed by all possible bit sequences */
2278 lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l);
2279 for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--)
2280 {
2281 dtbl->look_nbits[lookbits] = l;
2282 dtbl->look_sym[lookbits] = htbl[16+p];
2283 lookbits++;
2284 }
2285 }
2286 }
2287}
2288
2289
2290/* zag[i] is the natural-order position of the i'th element of zigzag order.
2291 * If the incoming data is corrupted, decode_mcu could attempt to
2292 * reference values beyond the end of the array. To avoid a wild store,
2293 * we put some extra zeroes after the real entries.
2294 */
2295static const int zag[] = {
2296 0, 1, 8, 16, 9, 2, 3, 10,
2297 17, 24, 32, 25, 18, 11, 4, 5,
2298 12, 19, 26, 33, 40, 48, 41, 34,
2299 27, 20, 13, 6, 7, 14, 21, 28,
2300 35, 42, 49, 56, 57, 50, 43, 36,
2301 29, 22, 15, 23, 30, 37, 44, 51,
2302 58, 59, 52, 45, 38, 31, 39, 46,
2303 53, 60, 61, 54, 47, 55, 62, 63,
2304 0, 0, 0, 0, 0, 0, 0, 0, /* extra entries in case k>63 below */
2305 0, 0, 0, 0, 0, 0, 0, 0
2306};
2307
2308void build_lut(struct jpeg* p_jpeg)
2309{
2310 int i;
2311 fix_huff_tbl(p_jpeg->hufftable[0].huffmancodes_dc,
2312 &p_jpeg->dc_derived_tbls[0]);
2313 fix_huff_tbl(p_jpeg->hufftable[0].huffmancodes_ac,
2314 &p_jpeg->ac_derived_tbls[0]);
2315 fix_huff_tbl(p_jpeg->hufftable[1].huffmancodes_dc,
2316 &p_jpeg->dc_derived_tbls[1]);
2317 fix_huff_tbl(p_jpeg->hufftable[1].huffmancodes_ac,
2318 &p_jpeg->ac_derived_tbls[1]);
2319
2320 /* build the dequantization tables for the IDCT (De-ZiZagged) */
2321 for (i=0; i<64; i++)
2322 {
2323 p_jpeg->qt_idct[0][zag[i]] = p_jpeg->quanttable[0][i];
2324 p_jpeg->qt_idct[1][zag[i]] = p_jpeg->quanttable[1][i];
2325 }
2326}
2327
2328
2329/*
2330* These functions/macros provide the in-line portion of bit fetching.
2331* Use check_bit_buffer to ensure there are N bits in get_buffer
2332* before using get_bits, peek_bits, or drop_bits.
2333* check_bit_buffer(state,n,action);
2334* Ensure there are N bits in get_buffer; if suspend, take action.
2335* val = get_bits(n);
2336* Fetch next N bits.
2337* val = peek_bits(n);
2338* Fetch next N bits without removing them from the buffer.
2339* drop_bits(n);
2340* Discard next N bits.
2341* The value N should be a simple variable, not an expression, because it
2342* is evaluated multiple times.
2343*/
2344
2345INLINE void check_bit_buffer(struct bitstream* pb, int nbits)
2346{
2347 if (pb->bits_left < nbits)
2348 {
2349 pb->words_left--;
2350 pb->get_buffer = (pb->get_buffer << 16) | *pb->next_input_word++;
2351 pb->bits_left += 16;
2352 }
2353}
2354
2355INLINE int get_bits(struct bitstream* pb, int nbits)
2356{
2357 return ((int) (pb->get_buffer >> (pb->bits_left -= nbits))) & ((1<<nbits)-1);
2358}
2359
2360INLINE int peek_bits(struct bitstream* pb, int nbits)
2361{
2362 return ((int) (pb->get_buffer >> (pb->bits_left - nbits))) & ((1<<nbits)-1);
2363}
2364
2365INLINE void drop_bits(struct bitstream* pb, int nbits)
2366{
2367 pb->bits_left -= nbits;
2368}
2369
2370/* Figure F.12: extend sign bit. */
2371#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
2372
2373static const int extend_test[16] = /* entry n is 2**(n-1) */
2374{
2375 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
2376 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000
2377};
2378
2379static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
2380{
2381 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
2382 ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
2383 ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
2384 ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1
2385};
2386
2387/* Decode a single value */
2388INLINE int huff_decode_dc(struct bitstream* bs, struct derived_tbl* tbl)
2389{
2390 int nb, look, s, r;
2391
2392 check_bit_buffer(bs, HUFF_LOOKAHEAD);
2393 look = peek_bits(bs, HUFF_LOOKAHEAD);
2394 if ((nb = tbl->look_nbits[look]) != 0)
2395 {
2396 drop_bits(bs, nb);
2397 s = tbl->look_sym[look];
2398 check_bit_buffer(bs, s);
2399 r = get_bits(bs, s);
2400 s = HUFF_EXTEND(r, s);
2401 }
2402 else
2403 { /* slow_DECODE(s, HUFF_LOOKAHEAD+1)) < 0); */
2404 long code;
2405 nb=HUFF_LOOKAHEAD+1;
2406 check_bit_buffer(bs, nb);
2407 code = get_bits(bs, nb);
2408 while (code > tbl->maxcode[nb])
2409 {
2410 code <<= 1;
2411 check_bit_buffer(bs, 1);
2412 code |= get_bits(bs, 1);
2413 nb++;
2414 }
2415 if (nb > 16) /* error in Huffman */
2416 {
2417 s=0; /* fake a zero, this is most safe */
2418 }
2419 else
2420 {
2421 s = tbl->pub[16 + tbl->valptr[nb] + ((int) (code - tbl->mincode[nb])) ];
2422 check_bit_buffer(bs, s);
2423 r = get_bits(bs, s);
2424 s = HUFF_EXTEND(r, s);
2425 }
2426 } /* end slow decode */
2427 return s;
2428}
2429
2430INLINE int huff_decode_ac(struct bitstream* bs, struct derived_tbl* tbl)
2431{
2432 int nb, look, s;
2433
2434 check_bit_buffer(bs, HUFF_LOOKAHEAD);
2435 look = peek_bits(bs, HUFF_LOOKAHEAD);
2436 if ((nb = tbl->look_nbits[look]) != 0)
2437 {
2438 drop_bits(bs, nb);
2439 s = tbl->look_sym[look];
2440 }
2441 else
2442 { /* slow_DECODE(s, HUFF_LOOKAHEAD+1)) < 0); */
2443 long code;
2444 nb=HUFF_LOOKAHEAD+1;
2445 check_bit_buffer(bs, nb);
2446 code = get_bits(bs, nb);
2447 while (code > tbl->maxcode[nb])
2448 {
2449 code <<= 1;
2450 check_bit_buffer(bs, 1);
2451 code |= get_bits(bs, 1);
2452 nb++;
2453 }
2454 if (nb > 16) /* error in Huffman */
2455 {
2456 s=0; /* fake a zero, this is most safe */
2457 }
2458 else
2459 {
2460 s = tbl->pub[16 + tbl->valptr[nb] + ((int) (code - tbl->mincode[nb])) ];
2461 }
2462 } /* end slow decode */
2463 return s;
2464}
2465
2466
2467/* a JPEG decoder specialized in decoding only the luminance (b&w) */
2468int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel, int downscale,
2469 void (*pf_progress)(int current, int total))
2470{
2471 struct bitstream bs; /* bitstream "object" */
2472 static int block[64]; /* decoded DCT coefficients */
2473
2474 int width, height;
2475 int skip_line; /* bytes from one line to the next (skip_line) */
2476 int skip_strip, skip_mcu; /* bytes to next DCT row / column */
2477
2478 int x, y; /* loop counter */
2479
2480 unsigned char* p_byte; /* bitmap pointer */
2481
2482 void (*pf_idct)(unsigned char*, int*, int*, int); /* selected IDCT */
2483 int k_need; /* AC coefficients needed up to here */
2484 int zero_need; /* init the block with this many zeros */
2485
2486 int last_dc_val[4];
2487 int store_offs[4]; /* memory offsets: order of Y11 Y12 Y21 Y22 U V */
2488 MEMSET(&last_dc_val, 0, sizeof(last_dc_val));
2489
2490 /* pick the IDCT we want, determine how to work with coefs */
2491 if (downscale == 1)
2492 {
2493 pf_idct = idct8x8;
2494 k_need = 63; /* all */
2495 zero_need = 63; /* all */
2496 }
2497 else if (downscale == 2)
2498 {
2499 pf_idct = idct4x4;
2500 k_need = 25; /* this far in zig-zag to cover 4*4 */
2501 zero_need = 27; /* clear this far in linear order */
2502 }
2503 else if (downscale == 4)
2504 {
2505 pf_idct = idct2x2;
2506 k_need = 5; /* this far in zig-zag to cover 2*2 */
2507 zero_need = 9; /* clear this far in linear order */
2508 }
2509 else if (downscale == 8)
2510 {
2511 pf_idct = idct1x1;
2512 k_need = 0; /* no AC, not needed */
2513 zero_need = 0; /* no AC, not needed */
2514 }
2515 else return -1; /* not supported */
2516
2517 /* init bitstream */
2518 bs.bits_left = 0;
2519 bs.next_input_word = p_jpeg->p_entropy_data;
2520 bs.words_left = p_jpeg->words_in_buffer;
2521
2522 width = p_jpeg->x_phys / downscale;
2523 height = p_jpeg->y_phys / downscale;
2524 skip_line = width;
2525 skip_strip = skip_line * (height / p_jpeg->y_mbl);
2526 skip_mcu = (width/p_jpeg->x_mbl);
2527
2528 /* prepare offsets about where to store the different blocks */
2529 store_offs[0] = 0;
2530 store_offs[1] = 8 / downscale; /* to the right */
2531 store_offs[2] = width * 8 / downscale; /* below */
2532 store_offs[3] = store_offs[1] + store_offs[2]; /* right+below */
2533
2534 for(y=0; y<p_jpeg->y_mbl; y++)
2535 {
2536 p_byte = p_pixel;
2537 p_pixel += skip_strip;
2538 for (x=0; x<p_jpeg->x_mbl; x++)
2539 {
2540 int blkn;
2541
2542 /* Outer loop handles each block in the MCU */
2543
2544 for (blkn = 0; blkn < p_jpeg->blocks && bs.words_left>=0; blkn++)
2545 { /* Decode a single block's worth of coefficients */
2546 int k = 1; /* coefficient index */
2547 int s, r; /* huffman values */
2548 int ci = p_jpeg->mcu_membership[blkn]; /* component index */
2549 int ti = p_jpeg->tab_membership[blkn]; /* table index */
2550 struct derived_tbl* dctbl = &p_jpeg->dc_derived_tbls[ti];
2551 struct derived_tbl* actbl = &p_jpeg->ac_derived_tbls[ti];
2552
2553 /* Section F.2.2.1: decode the DC coefficient difference */
2554 last_dc_val[ci] += huff_decode_dc(&bs, dctbl);
2555 block[0] = last_dc_val[ci]; /* output it (assumes zag[0] = 0) */
2556
2557 /* Section F.2.2.2: decode the AC coefficients */
2558 if (ci == 0) /* only for Y component */
2559 {
2560 /* coefficient buffer must be cleared */
2561 MEMSET(block+1, 0, zero_need*sizeof(int));
2562 for (; k < k_need; k++)
2563 {
2564 s = huff_decode_ac(&bs, actbl);
2565 r = s >> 4;
2566 s &= 15;
2567
2568 if (s)
2569 {
2570 k += r;
2571 check_bit_buffer(&bs, s);
2572 r = get_bits(&bs, s);
2573 block[zag[k]] = HUFF_EXTEND(r, s);
2574 }
2575 else
2576 {
2577 if (r != 15)
2578 {
2579 k = 64;
2580 break;
2581 }
2582 k += r;
2583 }
2584 } /* for k */
2585 }
2586 /* In this path we just discard the values */
2587 for (; k < 64; k++)
2588 {
2589 s = huff_decode_ac(&bs, actbl);
2590 r = s >> 4;
2591 s &= 15;
2592
2593 if (s)
2594 {
2595 k += r;
2596 check_bit_buffer(&bs, s);
2597 drop_bits(&bs, s);
2598 }
2599 else
2600 {
2601 if (r != 15)
2602 break;
2603 k += r;
2604 }
2605 } /* for k */
2606
2607 if (ci == 0)
2608 { /* only for Y component */
2609 pf_idct(p_byte+store_offs[blkn], block, p_jpeg->qt_idct[ti],
2610 skip_line);
2611 }
2612 } /* for blkn */
2613 p_byte += skip_mcu;
2614 } /* for x */
2615 if (pf_progress != NULL)
2616 pf_progress(y, p_jpeg->y_mbl-1); /* notify about decoding progress */
2617 } /* for y */
2618
2619 return 0; /* success */
2620}
2621
2622
2623/**************** end JPEG code ********************/
2624
2625
2626/**************** begin Application ********************/
2627
2628
2629/************************* Types ***************************/
2630
2631struct t_disp
2632{
2633 unsigned char* bitmap;
2634 int width;
2635 int height;
2636 int stride;
2637 int x, y;
2638};
2639
2640
2641/************************* Implementation ***************************/
2642
2643#define ZOOM_IN 100 // return codes for below function
2644#define ZOOM_OUT 101
2645
2646/* interactively scroll around the image */
2647int scroll_bmp(struct t_disp* pdisp)
2648{
2649 while (true)
2650 {
2651 int button;
2652 int move;
2653 int i;
2654
2655 /* we're unfortunately slower than key repeat,
2656 so empty the button queue, to avoid post-scroll */
2657 while(rb->button_get(false) != BUTTON_NONE);
2658
2659 button = rb->button_get(true);
2660
2661 if (button == SYS_USB_CONNECTED)
2662 {
2663 gray_release_buffer(); /* switch off overlay and deinitialize */
2664 return PLUGIN_USB_CONNECTED;
2665 }
2666
2667 switch(button & ~(BUTTON_REPEAT))
2668 {
2669 case BUTTON_LEFT:
2670 move = MIN(10, pdisp->x);
2671 if (move > 0)
2672 {
2673 gray_scroll_right(move, false); /* scroll right */
2674 pdisp->x -= move;
2675 gray_drawgraymap(
2676 pdisp->bitmap + pdisp->y * pdisp->stride + pdisp->x,
2677 0, MAX(0, (LCD_HEIGHT-pdisp->height)/2), // x, y
2678 move, MIN(LCD_HEIGHT, pdisp->height), // w, h
2679 pdisp->stride);
2680 }
2681 break;
2682
2683 case BUTTON_RIGHT:
2684 move = MIN(10, pdisp->width - pdisp->x - LCD_WIDTH);
2685 if (move > 0)
2686 {
2687 gray_scroll_left(move, false); /* scroll left */
2688 pdisp->x += move;
2689 gray_drawgraymap(
2690 pdisp->bitmap + pdisp->y * pdisp->stride + pdisp->x + LCD_WIDTH - move,
2691 LCD_WIDTH - move, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */
2692 move, MIN(LCD_HEIGHT, pdisp->height), /* w, h */
2693 pdisp->stride);
2694 }
2695 break;
2696
2697 case BUTTON_UP:
2698 move = MIN(8, pdisp->y);
2699 if (move > 0)
2700 {
2701 if (move == 8)
2702 gray_scroll_down8(false); /* scroll down by 8 pixel */
2703 else
2704 for (i=0; i<move; i++)
2705 gray_scroll_down1(false); /* n times one pixel */
2706 pdisp->y -= move;
2707 gray_drawgraymap(
2708 pdisp->bitmap + pdisp->y * pdisp->stride + pdisp->x,
2709 MAX(0, (LCD_WIDTH-pdisp->width)/2), 0, /* x, y */
2710 MIN(LCD_WIDTH, pdisp->width), move, /* w, h */
2711 pdisp->stride);
2712 }
2713 break;
2714
2715 case BUTTON_DOWN:
2716 move = MIN(8, pdisp->height - pdisp->y - LCD_HEIGHT);
2717 if (move > 0)
2718 {
2719 if (move == 8)
2720 gray_scroll_up8(false); /* scroll up by 8 pixel */
2721 else
2722 for (i=0; i<move; i++)
2723 gray_scroll_up1(false); /* n times one pixel */
2724 pdisp->y += move;
2725 gray_drawgraymap(
2726 pdisp->bitmap + (pdisp->y + LCD_HEIGHT - move) * pdisp->stride + pdisp->x,
2727 MAX(0, (LCD_WIDTH-pdisp->width)/2), LCD_HEIGHT - move, /* x, y */
2728 MIN(LCD_WIDTH, pdisp->width), move, /* w, h */
2729 pdisp->stride);
2730 }
2731 break;
2732
2733 case BUTTON_PLAY:
2734 return ZOOM_IN;
2735 break;
2736
2737 case BUTTON_ON:
2738 return ZOOM_OUT;
2739 break;
2740
2741 case BUTTON_OFF:
2742 return PLUGIN_OK;
2743 } /* switch */
2744 } /* while (true) */
2745}
2746
2747/********************* main function *************************/
2748
2749/* debug function */
2750int wait_for_button(void)
2751{
2752 int button;
2753
2754 do
2755 {
2756 button = rb->button_get(true);
2757 } while ((button & BUTTON_REL) && button != SYS_USB_CONNECTED);
2758
2759 return button;
2760}
2761
2762/* callback updating a progress meter while JPEG decoding */
2763void cb_progess(int current, int total)
2764{
2765 rb->progressbar(0, LCD_HEIGHT-8, LCD_WIDTH, 8,
2766 current*100/total, 0 /*Grow_Right*/);
2767 rb->lcd_update_rect(0, LCD_HEIGHT-8, LCD_WIDTH, 8);
2768}
2769
2770/* helper to align a buffer to a given power of two */
2771void align(unsigned char** ppbuf, int* plen, int align)
2772{
2773 unsigned int orig = (unsigned int)*ppbuf;
2774 unsigned int aligned = (orig + (align-1)) & ~(align-1);
2775
2776 *plen -= aligned - orig;
2777 *ppbuf = (unsigned char*)aligned;
2778}
2779
2780
2781/* how far can we zoom in without running out of memory */
2782int min_downscale(int x, int y, int bufsize)
2783{
2784 int downscale = 8;
2785
2786 if ((x/8) * (y/8) > bufsize)
2787 return 0; /* error, too large even 1:8, doesn't fit */
2788
2789 while ((x*2/downscale) * (y*2/downscale) < bufsize
2790 && downscale > 1)
2791 {
2792 downscale /= 2;
2793 }
2794 return downscale;
2795}
2796
2797/* how far can we zoom out, to fit image into the LCD */
2798int max_downscale(int x, int y)
2799{
2800 int downscale = 1;
2801
2802 while ((x/downscale > LCD_WIDTH || y/downscale > LCD_HEIGHT)
2803 && downscale < 8)
2804 {
2805 downscale *= 2;
2806 }
2807
2808 return downscale;
2809}
2810
2811
2812/* load, decode, display the image */
2813int main(char* filename)
2814{
2815 int fd;
2816 int filesize;
2817 int grayscales;
2818 int graysize; // helper
2819 char print[32];
2820 unsigned char* buf;
2821 int buf_size;
2822 unsigned char* buf_jpeg; /* compressed JPEG image */
2823 struct t_disp disp; /* decompressed image */
2824 long time; /* measured ticks */
2825
2826 static struct jpeg jpg; /* too large for stack */
2827 int status;
2828 int ds, ds_min, ds_max; /* scaling and limits */
2829
2830 buf = rb->plugin_get_mp3_buffer(&buf_size);
2831
2832 fd = rb->open(filename, O_RDONLY);
2833 if (fd < 0)
2834 {
2835 rb->splash(HZ*2, true, "fopen err");
2836 return PLUGIN_ERROR;
2837 }
2838 filesize = rb->filesize(fd);
2839
2840
2841 /* initialize the grayscale buffer:
2842 * 112 pixels wide, 8 rows (64 pixels) high, (try to) reserve
2843 * 32 bitplanes for 33 shades of gray. (uses 28856 bytes)*/
2844 align(&buf, &buf_size, 4); // 32 bit align
2845 graysize = sizeof(tGraybuf) + sizeof(long) + (112 * 8 + sizeof(long)) * 32;
2846 grayscales = gray_init_buffer(buf, graysize, 112, 8, 32) + 1;
2847 buf += graysize;
2848 buf_size -= graysize;
2849 if (grayscales < 33 || buf_size <= 0)
2850 {
2851 rb->splash(HZ*2, true, "gray buf error");
2852 return PLUGIN_ERROR;
2853 }
2854
2855
2856 /* allocate JPEG buffer */
2857 align(&buf, &buf_size, 2); /* 16 bit align */
2858 buf_jpeg = (unsigned char*)(((int)buf + 1) & ~1);
2859 buf += filesize;
2860 buf_size -= filesize;
2861 if (buf_size <= 0)
2862 {
2863 rb->splash(HZ*2, true, "out of memory");
2864 rb->close(fd);
2865 return PLUGIN_ERROR;
2866 }
2867
2868 rb->snprintf(print, sizeof(print), "loading %d bytes", filesize);
2869 rb->lcd_puts(0, 0, print);
2870 rb->lcd_update();
2871
2872 rb->read(fd, buf_jpeg, filesize);
2873 rb->close(fd);
2874
2875 rb->snprintf(print, sizeof(print), "decoding markers");
2876 rb->lcd_puts(0, 1, print);
2877 rb->lcd_update();
2878
2879 rb->memset(&jpg, 0, sizeof(jpg)); /* clear info struct */
2880 /* process markers, unstuffing */
2881 status = process_markers(buf_jpeg, filesize, &jpg);
2882 if (status < 0 || (status & (DQT | SOF0)) != (DQT | SOF0))
2883 { /* bad format or minimum components not contained */
2884 rb->splash(HZ*2, true, "unsupported format %d", status);
2885 return PLUGIN_ERROR;
2886 }
2887 if (!(status & DHT)) /* if no Huffman table present: */
2888 default_huff_tbl(&jpg); /* use default */
2889 build_lut(&jpg); /* derive Huffman and other lookup-tables */
2890
2891 /* I can correct the buffer now, re-gain what the removed markers took */
2892 buf -= filesize; /* back to before */
2893 buf_size += filesize;
2894 buf += jpg.words_in_buffer * sizeof(short); /* real space */
2895 buf_size -= jpg.words_in_buffer * sizeof(short);
2896
2897 rb->snprintf(print, sizeof(print), "image %d*%d", jpg.x_size, jpg.y_size);
2898 rb->lcd_puts(0, 2, print);
2899 rb->lcd_update();
2900
2901 /* check display constraint */
2902 ds_max = max_downscale(jpg.x_size, jpg.y_size);
2903 /* check memory constraint */
2904 ds_min = min_downscale(jpg.x_phys, jpg.y_phys, buf_size);
2905 if (ds_min == 0)
2906 {
2907 rb->splash(HZ*2, true, "too large");
2908 return PLUGIN_ERROR;
2909 }
2910 ds = ds_max; /* initials setting */
2911
2912 /* assign image buffer */
2913 rb->memset(&disp, 0, sizeof(disp));
2914 disp.bitmap = buf;
2915
2916 do /* loop the image prepare and decoding when zoomed */
2917 {
2918 int w, h; /* used to center output */
2919 rb->snprintf(print, sizeof(print), "decoding %d*%d",
2920 jpg.x_size/ds, jpg.y_size/ds);
2921 rb->lcd_puts(0, 3, print);
2922 rb->lcd_update();
2923
2924 /* update image properties */
2925 disp.width = jpg.x_size/ds;
2926 disp.stride = jpg.x_phys / ds; /* use physical size for stride */
2927 disp.height = jpg.y_size/ds;
2928 disp.x = MAX(0, (disp.width - LCD_WIDTH) / 2); /* center view */
2929 disp.y = MAX(0, (disp.height - LCD_HEIGHT) / 2);
2930
2931 /* the actual decoding */
2932 time = *rb->current_tick;
2933 status = jpeg_decode(&jpg, disp.bitmap, ds, cb_progess);
2934 if (status)
2935 {
2936 rb->splash(HZ*2, true, "decode error %d", status);
2937 return PLUGIN_ERROR;
2938 }
2939 time = *rb->current_tick - time;
2940 rb->snprintf(print, sizeof(print), " %d.%02d sec ", time/HZ, time%HZ);
2941 rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */
2942 rb->lcd_putsxy((LCD_WIDTH - w)/2, LCD_HEIGHT - h, print);
2943 rb->lcd_update();
2944
2945 gray_clear_display();
2946 gray_drawgraymap(
2947 disp.bitmap + disp.y * disp.stride + disp.x,
2948 MAX(0, (LCD_WIDTH - disp.width) / 2),
2949 MAX(0, (LCD_HEIGHT - disp.height) / 2),
2950 MIN(LCD_WIDTH, disp.width), MIN(LCD_HEIGHT, disp.height),
2951 disp.stride);
2952
2953 gray_show_display(true); /* switch on grayscale overlay */
2954
2955 /* drawing is now finished, play around with scrolling
2956 * until you press OFF or connect USB
2957 */
2958 while (1)
2959 {
2960 status = scroll_bmp(&disp);
2961 if (status == ZOOM_IN)
2962 {
2963 if (ds > ds_min)
2964 {
2965 ds /= 2; /* reduce downscaling to zoom in */
2966 /* FixMe: maintain center
2967 disp.x = disp.x * 2 + LCD_WIDTH/2;
2968 disp.y = disp.y * 2 + LCD_HEIGHT/2;
2969 */
2970 }
2971 else
2972 continue;
2973 }
2974
2975 if (status == ZOOM_OUT)
2976 {
2977 if (ds < ds_max)
2978 {
2979 ds *= 2; /* increase downscaling to zoom out */
2980 /* FixMe: maintain center, if possible
2981 disp.x = (disp.x - LCD_WIDTH/2) / 2;
2982 disp.x = MIN(0, disp.x);
2983 disp.x = MAX(disp.width/2 - LCD_WIDTH, disp.x);
2984 disp.y = (disp.y - LCD_HEIGHT/2) / 2;
2985 disp.y = MIN(0, disp.y);
2986 disp.y = MAX(disp.height/2 - LCD_HEIGHT, disp.y);
2987 */
2988 }
2989 else
2990 continue;
2991 }
2992 break;
2993 }
2994
2995 gray_show_display(false); /* switch off overlay */
2996
2997 }
2998 while (status > 0 && status != SYS_USB_CONNECTED);
2999
3000 gray_release_buffer(); /* deinitialize */
3001
3002 return status;
3003}
3004
3005/******************** Plugin entry point *********************/
3006
3007enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
3008{
3009 int ret;
3010 /* this macro should be called as the first thing you do in the plugin.
3011 it test that the api version and model the plugin was compiled for
3012 matches the machine it is running on */
3013 TEST_PLUGIN_API(api);
3014
3015 rb = api; /* copy to global api pointer */
3016
3017 ret = main((char*)parameter);
3018
3019 if (ret == PLUGIN_USB_CONNECTED)
3020 rb->usb_screen();
3021 return ret;
3022}
3023
3024#endif /* #ifdef HAVE_LCD_BITMAP */
3025#endif /* #ifndef SIMULATOR */
3026