1
0
Fork 0
forked from len0rd/rockbox

Colour JPEG display on colour targets.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8715 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Jens Arnold 2006-02-17 16:55:23 +00:00
parent 9131c4a326
commit 41f1ab2710

View file

@ -1389,176 +1389,12 @@ INLINE int huff_decode_ac(struct bitstream* bs, struct derived_tbl* tbl)
}
/* a JPEG decoder specialized in decoding only the luminance (b&w) */
int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel, int downscale,
void (*pf_progress)(int current, int total))
{
struct bitstream bs; /* bitstream "object" */
static int block[64]; /* decoded DCT coefficients */
int width, height;
int skip_line; /* bytes from one line to the next (skip_line) */
int skip_strip, skip_mcu; /* bytes to next DCT row / column */
int x, y; /* loop counter */
unsigned char* p_byte; /* bitmap pointer */
void (*pf_idct)(unsigned char*, int*, int*, int); /* selected IDCT */
int k_need; /* AC coefficients needed up to here */
int zero_need; /* init the block with this many zeros */
int last_dc_val = 0;
int store_offs[4]; /* memory offsets: order of Y11 Y12 Y21 Y22 U V */
int restart = p_jpeg->restart_interval; /* MCUs until restart marker */
/* pick the IDCT we want, determine how to work with coefs */
if (downscale == 1)
{
pf_idct = idct8x8;
k_need = 64; /* all */
zero_need = 63; /* all */
}
else if (downscale == 2)
{
pf_idct = idct4x4;
k_need = 25; /* this far in zig-zag to cover 4*4 */
zero_need = 27; /* clear this far in linear order */
}
else if (downscale == 4)
{
pf_idct = idct2x2;
k_need = 5; /* this far in zig-zag to cover 2*2 */
zero_need = 9; /* clear this far in linear order */
}
else if (downscale == 8)
{
pf_idct = idct1x1;
k_need = 0; /* no AC, not needed */
zero_need = 0; /* no AC, not needed */
}
else return -1; /* not supported */
/* init bitstream, fake a restart to make it start */
bs.next_input_byte = p_jpeg->p_entropy_data;
bs.bits_left = 0;
bs.input_end = p_jpeg->p_entropy_end;
width = p_jpeg->x_phys / downscale;
height = p_jpeg->y_phys / downscale;
skip_line = width;
skip_strip = skip_line * (height / p_jpeg->y_mbl);
skip_mcu = (width/p_jpeg->x_mbl);
/* prepare offsets about where to store the different blocks */
store_offs[p_jpeg->store_pos[0]] = 0;
store_offs[p_jpeg->store_pos[1]] = 8 / downscale; /* to the right */
store_offs[p_jpeg->store_pos[2]] = width * 8 / downscale; /* below */
store_offs[p_jpeg->store_pos[3]] = store_offs[1] + store_offs[2]; /* r+b */
for(y=0; y<p_jpeg->y_mbl && bs.next_input_byte <= bs.input_end; y++)
{
p_byte = p_pixel;
p_pixel += skip_strip;
for (x=0; x<p_jpeg->x_mbl; x++)
{
int blkn;
/* Outer loop handles each block in the MCU */
for (blkn = 0; blkn < p_jpeg->blocks; blkn++)
{ /* Decode a single block's worth of coefficients */
int k = 1; /* coefficient index */
int s, r; /* huffman values */
int ci = p_jpeg->mcu_membership[blkn]; /* component index */
int ti = p_jpeg->tab_membership[blkn]; /* table index */
struct derived_tbl* dctbl = &p_jpeg->dc_derived_tbls[ti];
struct derived_tbl* actbl = &p_jpeg->ac_derived_tbls[ti];
/* Section F.2.2.1: decode the DC coefficient difference */
s = huff_decode_dc(&bs, dctbl);
if (ci == 0) /* only for Y component */
{
last_dc_val += s;
block[0] = last_dc_val; /* output it (assumes zag[0] = 0) */
/* coefficient buffer must be cleared */
MEMSET(block+1, 0, zero_need*sizeof(block[0]));
/* Section F.2.2.2: decode the AC coefficients */
for (; k < k_need; k++)
{
s = huff_decode_ac(&bs, actbl);
r = s >> 4;
s &= 15;
if (s)
{
k += r;
check_bit_buffer(&bs, s);
r = get_bits(&bs, s);
block[zag[k]] = HUFF_EXTEND(r, s);
}
else
{
if (r != 15)
{
k = 64;
break;
}
k += r;
}
} /* for k */
}
/* In this path we just discard the values */
for (; k < 64; k++)
{
s = huff_decode_ac(&bs, actbl);
r = s >> 4;
s &= 15;
if (s)
{
k += r;
check_bit_buffer(&bs, s);
drop_bits(&bs, s);
}
else
{
if (r != 15)
break;
k += r;
}
} /* for k */
if (ci == 0)
{ /* only for Y component */
pf_idct(p_byte+store_offs[blkn], block, p_jpeg->qt_idct[ti],
skip_line);
}
} /* for blkn */
p_byte += skip_mcu;
if (p_jpeg->restart_interval && --restart == 0)
{ /* if a restart marker is due: */
restart = p_jpeg->restart_interval; /* count again */
search_restart(&bs); /* align the bitstream */
last_dc_val = 0; /* reset decoder */
}
} /* for x */
if (pf_progress != NULL)
pf_progress(y, p_jpeg->y_mbl-1); /* notify about decoding progress */
} /* for y */
return 0; /* success */
}
#ifdef HAVE_LCD_COLOR
/* JPEG decoder variant for YUV decoding, into 3 different planes */
/* Note: it keeps the original color subsampling, even if resized. */
int jpeg_decode_color(struct jpeg* p_jpeg, unsigned char* p_pixel[3],
int downscale, void (*pf_progress)(int current, int total))
int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel[3],
int downscale, void (*pf_progress)(int current, int total))
{
struct bitstream bs; /* bitstream "object" */
static int block[64]; /* decoded DCT coefficients */
@ -1710,7 +1546,7 @@ int jpeg_decode_color(struct jpeg* p_jpeg, unsigned char* p_pixel[3],
}
else
{ /* chroma */
pf_idct(p_byte[ci], block, p_jpeg->qt_idct[ti],
pf_idct(p_byte[ci], block, p_jpeg->qt_idct[ti],
skip_line[ci]);
}
} /* for blkn */
@ -1731,8 +1567,172 @@ int jpeg_decode_color(struct jpeg* p_jpeg, unsigned char* p_pixel[3],
return 0; /* success */
}
#else /* !HAVE_LCD_COLOR */
#endif /* #ifdef HAVE_LCD_COLOR */
/* a JPEG decoder specialized in decoding only the luminance (b&w) */
int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel[1], int downscale,
void (*pf_progress)(int current, int total))
{
struct bitstream bs; /* bitstream "object" */
static int block[64]; /* decoded DCT coefficients */
int width, height;
int skip_line; /* bytes from one line to the next (skip_line) */
int skip_strip, skip_mcu; /* bytes to next DCT row / column */
int x, y; /* loop counter */
unsigned char* p_line = p_pixel[0];
unsigned char* p_byte; /* bitmap pointer */
void (*pf_idct)(unsigned char*, int*, int*, int); /* selected IDCT */
int k_need; /* AC coefficients needed up to here */
int zero_need; /* init the block with this many zeros */
int last_dc_val = 0;
int store_offs[4]; /* memory offsets: order of Y11 Y12 Y21 Y22 U V */
int restart = p_jpeg->restart_interval; /* MCUs until restart marker */
/* pick the IDCT we want, determine how to work with coefs */
if (downscale == 1)
{
pf_idct = idct8x8;
k_need = 64; /* all */
zero_need = 63; /* all */
}
else if (downscale == 2)
{
pf_idct = idct4x4;
k_need = 25; /* this far in zig-zag to cover 4*4 */
zero_need = 27; /* clear this far in linear order */
}
else if (downscale == 4)
{
pf_idct = idct2x2;
k_need = 5; /* this far in zig-zag to cover 2*2 */
zero_need = 9; /* clear this far in linear order */
}
else if (downscale == 8)
{
pf_idct = idct1x1;
k_need = 0; /* no AC, not needed */
zero_need = 0; /* no AC, not needed */
}
else return -1; /* not supported */
/* init bitstream, fake a restart to make it start */
bs.next_input_byte = p_jpeg->p_entropy_data;
bs.bits_left = 0;
bs.input_end = p_jpeg->p_entropy_end;
width = p_jpeg->x_phys / downscale;
height = p_jpeg->y_phys / downscale;
skip_line = width;
skip_strip = skip_line * (height / p_jpeg->y_mbl);
skip_mcu = (width/p_jpeg->x_mbl);
/* prepare offsets about where to store the different blocks */
store_offs[p_jpeg->store_pos[0]] = 0;
store_offs[p_jpeg->store_pos[1]] = 8 / downscale; /* to the right */
store_offs[p_jpeg->store_pos[2]] = width * 8 / downscale; /* below */
store_offs[p_jpeg->store_pos[3]] = store_offs[1] + store_offs[2]; /* r+b */
for(y=0; y<p_jpeg->y_mbl && bs.next_input_byte <= bs.input_end; y++)
{
p_byte = p_line;
p_line += skip_strip;
for (x=0; x<p_jpeg->x_mbl; x++)
{
int blkn;
/* Outer loop handles each block in the MCU */
for (blkn = 0; blkn < p_jpeg->blocks; blkn++)
{ /* Decode a single block's worth of coefficients */
int k = 1; /* coefficient index */
int s, r; /* huffman values */
int ci = p_jpeg->mcu_membership[blkn]; /* component index */
int ti = p_jpeg->tab_membership[blkn]; /* table index */
struct derived_tbl* dctbl = &p_jpeg->dc_derived_tbls[ti];
struct derived_tbl* actbl = &p_jpeg->ac_derived_tbls[ti];
/* Section F.2.2.1: decode the DC coefficient difference */
s = huff_decode_dc(&bs, dctbl);
if (ci == 0) /* only for Y component */
{
last_dc_val += s;
block[0] = last_dc_val; /* output it (assumes zag[0] = 0) */
/* coefficient buffer must be cleared */
MEMSET(block+1, 0, zero_need*sizeof(block[0]));
/* Section F.2.2.2: decode the AC coefficients */
for (; k < k_need; k++)
{
s = huff_decode_ac(&bs, actbl);
r = s >> 4;
s &= 15;
if (s)
{
k += r;
check_bit_buffer(&bs, s);
r = get_bits(&bs, s);
block[zag[k]] = HUFF_EXTEND(r, s);
}
else
{
if (r != 15)
{
k = 64;
break;
}
k += r;
}
} /* for k */
}
/* In this path we just discard the values */
for (; k < 64; k++)
{
s = huff_decode_ac(&bs, actbl);
r = s >> 4;
s &= 15;
if (s)
{
k += r;
check_bit_buffer(&bs, s);
drop_bits(&bs, s);
}
else
{
if (r != 15)
break;
k += r;
}
} /* for k */
if (ci == 0)
{ /* only for Y component */
pf_idct(p_byte+store_offs[blkn], block, p_jpeg->qt_idct[ti],
skip_line);
}
} /* for blkn */
p_byte += skip_mcu;
if (p_jpeg->restart_interval && --restart == 0)
{ /* if a restart marker is due: */
restart = p_jpeg->restart_interval; /* count again */
search_restart(&bs); /* align the bitstream */
last_dc_val = 0; /* reset decoder */
}
} /* for x */
if (pf_progress != NULL)
pf_progress(y, p_jpeg->y_mbl-1); /* notify about decoding progress */
} /* for y */
return 0; /* success */
}
#endif /* !HAVE_LCD_COLOR */
/**************** end JPEG code ********************/
@ -1745,7 +1745,12 @@ int jpeg_decode_color(struct jpeg* p_jpeg, unsigned char* p_pixel[3],
struct t_disp
{
unsigned char* bitmap;
#ifdef HAVE_LCD_COLOR
unsigned char* bitmap[3]; /* Y, Cr, Cb */
int csub_x, csub_y;
#else
unsigned char* bitmap[1]; /* Y only */
#endif
int width;
int height;
int stride;
@ -1767,6 +1772,151 @@ int root_size;
/************************* Implementation ***************************/
#ifdef HAVE_LCD_COLOR
#if (LCD_DEPTH == 16) && \
((LCD_PIXELFORMAT == RGB565) || (LCD_PIXELFORMAT == RGB565SWAPPED))
#define RYFAC (31*257)
#define GYFAC (63*257)
#define BYFAC (31*257)
#define RVFAC 11170 /* 31 * 257 * 1.402 */
#define GVFAC (-11563) /* 63 * 257 * -0.714136 */
#define GUFAC (-5572) /* 63 * 257 * -0.344136 */
#define BUFAC 14118 /* 31 * 257 * 1.772 */
#endif
/* Draw a partial YUV colour bitmap */
void yuv_bitmap_part(unsigned char *src[3], int csub_x, int csub_y,
int src_x, int src_y, int stride,
int x, int y, int width, int height)
{
fb_data *dst, *dst_end;
/* nothing to draw? */
if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
|| (x + width <= 0) || (y + height <= 0))
return;
/* clipping */
if (x < 0)
{
width += x;
src_x -= x;
x = 0;
}
if (y < 0)
{
height += y;
src_y -= y;
y = 0;
}
if (x + width > LCD_WIDTH)
width = LCD_WIDTH - x;
if (y + height > LCD_HEIGHT)
height = LCD_HEIGHT - y;
dst = rb->lcd_framebuffer + LCD_WIDTH * y + x;
dst_end = dst + LCD_WIDTH * height;
do
{
fb_data *dst_row = dst;
fb_data *row_end = dst_row + width;
const unsigned char *ysrc = src[0] + stride * src_y + src_x;
int y, u, v;
int red, green, blue;
unsigned rbits, gbits, bbits;
if (csub_y) /* colour */
{
/* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
const unsigned char *usrc = src[1] + (stride/csub_x) * (src_y/csub_y)
+ (src_x/csub_x);
const unsigned char *vsrc = src[2] + (stride/csub_x) * (src_y/csub_y)
+ (src_x/csub_x);
int xphase = src_x % csub_x;
int rc, gc, bc;
u = *usrc++ - 128;
v = *vsrc++ - 128;
rc = RVFAC * v + 32639;
gc = GVFAC * v + GUFAC * u + 32639;
bc = BUFAC * u + 32639;
do
{
y = *ysrc++;
red = RYFAC * y + rc;
green = GYFAC * y + gc;
blue = BYFAC * y + bc;
if ((unsigned)red > (RYFAC*255+32639))
{
if (red < 0)
red = 0;
else
red = (RYFAC*255+32639);
}
if ((unsigned)green > (GYFAC*255+32639))
{
if (green < 0)
green = 0;
else
green = (GYFAC*255+32639);
}
if ((unsigned)blue > (BYFAC*255+32639))
{
if (blue < 0)
blue = 0;
else
blue = (BYFAC*255+32639);
}
rbits = ((unsigned)red) >> 16 ;
gbits = ((unsigned)green) >> 16 ;
bbits = ((unsigned)blue) >> 16 ;
#if LCD_PIXELFORMAT == RGB565
*dst_row++ = (rbits << 11) | (gbits << 5) | bbits;
#elif LCD_PIXELFORMAT == RGB565SWAPPED
*dst_row++ = swap16((rbits << 11) | (gbits << 5) | bbits);
#endif
if (++xphase >= csub_x)
{
u = *usrc++ - 128;
v = *vsrc++ - 128;
rc = RVFAC * v + 32639;
gc = GVFAC * v + GUFAC * u + 32639;
bc = BUFAC * u + 32639;
xphase = 0;
}
}
while (dst_row < row_end);
}
else /* monochrome */
{
do
{
y = *ysrc++;
red = RYFAC * y + 32639; /* blue == red */
green = GYFAC * y + 32639;
rbits = ((unsigned)red) >> 16;
gbits = ((unsigned)green) >> 16;
#if LCD_PIXELFORMAT == RGB565
*dst_row++ = (rbits << 11) | (gbits << 5) | rbits;
#elif LCD_PIXELFORMAT == RGB565SWAPPED
*dst_row++ = swap16((rbits << 11) | (gbits << 5) | rbits);
#endif
}
while (dst_row < row_end);
}
src_y++;
dst += LCD_WIDTH;
}
while (dst < dst_end);
}
#endif
/* switch off overlay, for handling SYS_ events */
void cleanup(void *parameter)
{
@ -1806,10 +1956,18 @@ int scroll_bmp(struct t_disp* pdisp)
{
MYXLCD(scroll_right)(move); /* scroll right */
pdisp->x -= move;
MYXLCD(gray_bitmap_part)(
pdisp->bitmap, pdisp->x, pdisp->y, pdisp->stride,
#ifdef HAVE_LCD_COLOR
yuv_bitmap_part(
pdisp->bitmap, pdisp->csub_x, pdisp->csub_y,
pdisp->x, pdisp->y, pdisp->stride,
0, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */
move, MIN(LCD_HEIGHT, pdisp->height)); /* w, h */
#else
MYXLCD(gray_bitmap_part)(
pdisp->bitmap[0], pdisp->x, pdisp->y, pdisp->stride,
0, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */
move, MIN(LCD_HEIGHT, pdisp->height)); /* w, h */
#endif
MYLCD_UPDATE();
}
break;
@ -1821,11 +1979,19 @@ int scroll_bmp(struct t_disp* pdisp)
{
MYXLCD(scroll_left)(move); /* scroll left */
pdisp->x += move;
#ifdef HAVE_LCD_COLOR
yuv_bitmap_part(
pdisp->bitmap, pdisp->csub_x, pdisp->csub_y,
pdisp->x + LCD_WIDTH - move, pdisp->y, pdisp->stride,
LCD_WIDTH - move, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */
move, MIN(LCD_HEIGHT, pdisp->height)); /* w, h */
#else
MYXLCD(gray_bitmap_part)(
pdisp->bitmap, pdisp->x + LCD_WIDTH - move,
pdisp->bitmap[0], pdisp->x + LCD_WIDTH - move,
pdisp->y, pdisp->stride,
LCD_WIDTH - move, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */
move, MIN(LCD_HEIGHT, pdisp->height)); /* w, h */
#endif
MYLCD_UPDATE();
}
break;
@ -1837,10 +2003,18 @@ int scroll_bmp(struct t_disp* pdisp)
{
MYXLCD(scroll_down)(move); /* scroll down */
pdisp->y -= move;
MYXLCD(gray_bitmap_part)(
pdisp->bitmap, pdisp->x, pdisp->y, pdisp->stride,
#ifdef HAVE_LCD_COLOR
yuv_bitmap_part(
pdisp->bitmap, pdisp->csub_x, pdisp->csub_y,
pdisp->x, pdisp->y, pdisp->stride,
MAX(0, (LCD_WIDTH-pdisp->width)/2), 0, /* x, y */
MIN(LCD_WIDTH, pdisp->width), move); /* w, h */
#else
MYXLCD(gray_bitmap_part)(
pdisp->bitmap[0], pdisp->x, pdisp->y, pdisp->stride,
MAX(0, (LCD_WIDTH-pdisp->width)/2), 0, /* x, y */
MIN(LCD_WIDTH, pdisp->width), move); /* w, h */
#endif
MYLCD_UPDATE();
}
break;
@ -1852,11 +2026,19 @@ int scroll_bmp(struct t_disp* pdisp)
{
MYXLCD(scroll_up)(move); /* scroll up */
pdisp->y += move;
MYXLCD(gray_bitmap_part)(
pdisp->bitmap, pdisp->x,
#ifdef HAVE_LCD_COLOR
yuv_bitmap_part(
pdisp->bitmap, pdisp->csub_x, pdisp->csub_y, pdisp->x,
pdisp->y + LCD_HEIGHT - move, pdisp->stride,
MAX(0, (LCD_WIDTH-pdisp->width)/2), LCD_HEIGHT - move, /* x, y */
MIN(LCD_WIDTH, pdisp->width), move); /* w, h */
#else
MYXLCD(gray_bitmap_part)(
pdisp->bitmap[0], pdisp->x,
pdisp->y + LCD_HEIGHT - move, pdisp->stride,
MAX(0, (LCD_WIDTH-pdisp->width)/2), LCD_HEIGHT - move, /* x, y */
MIN(LCD_WIDTH, pdisp->width), move); /* w, h */
#endif
MYLCD_UPDATE();
}
break;
@ -1927,35 +2109,50 @@ void align(unsigned char** ppbuf, int* plen, int align)
*ppbuf = (unsigned char*)aligned;
}
int jpegmem(struct jpeg *p_jpg, int ds)
{
int size;
size = (p_jpg->x_phys/ds/p_jpg->subsample_x[0])
* (p_jpg->y_phys/ds/p_jpg->subsample_y[0]);
#ifdef HAVE_LCD_COLOR
if (p_jpg->blocks > 1) /* colour, add requirements for chroma */
{
size += (p_jpg->x_phys/ds/p_jpg->subsample_x[1])
* (p_jpg->y_phys/ds/p_jpg->subsample_y[1]);
size += (p_jpg->x_phys/ds/p_jpg->subsample_x[2])
* (p_jpg->y_phys/ds/p_jpg->subsample_y[2]);
}
#endif
return size;
}
/* how far can we zoom in without running out of memory */
int min_downscale(int x, int y, int bufsize)
int min_downscale(struct jpeg *p_jpg, int bufsize)
{
int downscale = 8;
if ((x/8) * (y/8) > bufsize)
if (jpegmem(p_jpg, 8) > bufsize)
return 0; /* error, too large, even 1:8 doesn't fit */
while ((x*2/downscale) * (y*2/downscale) < bufsize
&& downscale > 1)
{
while (downscale > 1 && jpegmem(p_jpg, downscale/2) <= bufsize)
downscale /= 2;
}
return downscale;
}
/* how far can we zoom out, to fit image into the LCD */
int max_downscale(int x, int y)
int max_downscale(struct jpeg *p_jpg)
{
int downscale = 1;
while ((x/downscale > LCD_WIDTH || y/downscale > LCD_HEIGHT)
&& downscale < 8)
while (downscale < 8 && (p_jpg->x_size > LCD_WIDTH*downscale
|| p_jpg->y_size > LCD_HEIGHT*downscale))
{
downscale *= 2;
}
return downscale;
}
@ -1970,7 +2167,7 @@ struct t_disp* get_image(struct jpeg* p_jpg, int ds)
struct t_disp* p_disp = &disp[ds]; /* short cut */
if (p_disp->bitmap != NULL)
if (p_disp->bitmap[0] != NULL)
{
return p_disp; /* we still have it */
}
@ -1978,19 +2175,41 @@ struct t_disp* get_image(struct jpeg* p_jpg, int ds)
/* assign image buffer */
/* physical size needed for decoding */
size = (p_jpg->x_phys/ds) * (p_jpg->y_phys / ds);
size = jpegmem(p_jpg, ds);
if (buf_size <= size)
{ /* have to discard the current */
int i;
for (i=1; i<=8; i++)
disp[i].bitmap = NULL; /* invalidate all bitmaps */
disp[i].bitmap[0] = NULL; /* invalidate all bitmaps */
buf = buf_root; /* start again from the beginning of the buffer */
buf_size = root_size;
}
#ifdef HAVE_LCD_COLOR
if (p_jpg->blocks > 1) /* colour jpeg */
{
int i;
for (i = 1; i < 3; i++)
{
size = (p_jpg->x_phys / ds / p_jpg->subsample_x[i])
* (p_jpg->y_phys / ds / p_jpg->subsample_y[i]);
p_disp->bitmap[i] = buf;
buf += size;
buf_size -= size;
}
p_disp->csub_x = p_jpg->subsample_x[1];
p_disp->csub_y = p_jpg->subsample_y[1];
}
else
{
p_disp->csub_x = p_disp->csub_y = 0;
p_disp->bitmap[1] = p_disp->bitmap[2] = buf;
}
#endif
/* size may be less when decoded (if height is not block aligned) */
size = (p_jpg->x_phys/ds) * (p_jpg->y_size / ds);
p_disp->bitmap = buf;
p_disp->bitmap[0] = buf;
buf += size;
buf_size -= size;
@ -2000,9 +2219,9 @@ struct t_disp* get_image(struct jpeg* p_jpg, int ds)
rb->lcd_update();
/* update image properties */
p_disp->width = p_jpg->x_size/ds;
p_disp->width = p_jpg->x_size / ds;
p_disp->stride = p_jpg->x_phys / ds; /* use physical size for stride */
p_disp->height = p_jpg->y_size/ds;
p_disp->height = p_jpg->y_size / ds;
/* the actual decoding */
time = *rb->current_tick;
@ -2106,7 +2325,7 @@ int plugin_main(char* filename)
/* allocate JPEG buffer */
align(&buf, &buf_size, 2); /* 16 bit align */
buf_jpeg = (unsigned char*)(((int)buf + 1) & ~1);
buf_jpeg = buf;
buf += filesize;
buf_size -= filesize;
buf_root = buf; /* we can start the decompressed images behind it */
@ -2117,6 +2336,12 @@ int plugin_main(char* filename)
rb->close(fd);
return PLUGIN_ERROR;
}
#ifdef HAVE_LCD_COLOR
rb->lcd_set_foreground(LCD_WHITE);
rb->lcd_set_background(LCD_BLACK);
rb->lcd_clear_display();
#endif
rb->snprintf(print, sizeof(print), "loading %d bytes", filesize);
rb->lcd_puts(0, 0, print);
@ -2145,10 +2370,8 @@ int plugin_main(char* filename)
rb->lcd_puts(0, 2, print);
rb->lcd_update();
/* check display constraint */
ds_max = max_downscale(jpg.x_size, jpg.y_size);
/* check memory constraint */
ds_min = min_downscale(jpg.x_phys, jpg.y_phys, buf_size);
ds_max = max_downscale(&jpg); /* check display constraint */
ds_min = min_downscale(&jpg, buf_size); /* check memory constraint */
if (ds_min == 0)
{
rb->splash(HZ*2, true, "too large");
@ -2172,12 +2395,22 @@ int plugin_main(char* filename)
rb->lcd_update();
MYLCD(clear_display)();
MYXLCD(gray_bitmap_part)(
p_disp->bitmap, p_disp->x, p_disp->y, p_disp->stride,
#ifdef HAVE_LCD_COLOR
yuv_bitmap_part(
p_disp->bitmap, p_disp->csub_x, p_disp->csub_y,
p_disp->x, p_disp->y, p_disp->stride,
MAX(0, (LCD_WIDTH - p_disp->width) / 2),
MAX(0, (LCD_HEIGHT - p_disp->height) / 2),
MIN(LCD_WIDTH, p_disp->width),
MIN(LCD_HEIGHT, p_disp->height));
#else
MYXLCD(gray_bitmap_part)(
p_disp->bitmap[0], p_disp->x, p_disp->y, p_disp->stride,
MAX(0, (LCD_WIDTH - p_disp->width) / 2),
MAX(0, (LCD_HEIGHT - p_disp->height) / 2),
MIN(LCD_WIDTH, p_disp->width),
MIN(LCD_HEIGHT, p_disp->height));
#endif
MYLCD_UPDATE();
#ifdef USEGSLIB