1
0
Fork 0
forked from len0rd/rockbox

Plugin JPEG decoder for data in memory, along with test_mem_jpeg.c and bench_mem_jpeg.c plugins to test and benchmark it, and a line-length clean up in jpeg_load.c.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20871 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Andrew Mahone 2009-05-08 03:46:48 +00:00
parent c91e73e922
commit a75c72c169
7 changed files with 435 additions and 14 deletions

View file

@ -0,0 +1,150 @@
/*****************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// __ \_/ ___\| |/ /| __ \ / __ \ \/ /
* Jukebox | | ( (__) ) \___| ( | \_\ ( (__) ) (
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2009 Andrew Mahone
*
* In-memory JPEG decode benchmark.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "plugin.h"
#include "lib/jpeg_mem.h"
PLUGIN_HEADER
/* a null output plugin to save memory and better isolate decode cost */
static unsigned int get_size_null(struct bitmap *bm)
{
(void) bm;
return 1;
}
static void output_row_null(uint32_t row, void * row_in,
struct scaler_context *ctx)
{
(void) row;
(void) row_in;
(void) ctx;
return;
}
const struct custom_format format_null = {
#ifdef HAVE_LCD_COLOR
.output_row = {
output_row_null,
output_row_null
},
#else
.output_row = output_row_null,
#endif
.get_size = get_size_null
};
static char output_buf[256];
static int output_y = 0;
static int font_h;
#define lcd_printf(...) \
do { \
rb->snprintf(output_buf, sizeof(output_buf), __VA_ARGS__); \
rb->lcd_putsxy(0, output_y, output_buf); \
rb->lcd_update_rect(0, output_y, LCD_WIDTH, font_h); \
output_y += font_h; \
} while (0)
/* this is the plugin entry point */
enum plugin_status plugin_start(const void* parameter)
{
size_t plugin_buf_len;
unsigned char * plugin_buf =
(unsigned char *)rb->plugin_get_buffer(&plugin_buf_len);
static char filename[MAX_PATH];
struct bitmap bm = {
.width = LCD_WIDTH,
.height = LCD_HEIGHT,
};
int ret;
if(!parameter) return PLUGIN_ERROR;
rb->strcpy(filename, parameter);
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
rb->lcd_fillrect(0, 0, LCD_WIDTH, LCD_HEIGHT);
rb->lcd_set_drawmode(DRMODE_SOLID);
rb->lcd_getstringsize("A", NULL, &font_h);
int fd = rb->open(filename, O_RDONLY);
if (fd < 0)
{
lcd_printf("file open failed: %d", fd);
goto wait;
}
unsigned long filesize = rb->filesize(fd);
if (filesize > plugin_buf_len)
{
lcd_printf("file too large");
goto wait;
}
plugin_buf_len -= filesize;
unsigned char *jpeg_buf = plugin_buf;
plugin_buf += filesize;
rb->read(fd, jpeg_buf, filesize);
rb->close(fd);
bm.data = plugin_buf;
struct dim jpeg_size;
get_jpeg_dim_mem(jpeg_buf, filesize, &jpeg_size);
lcd_printf("jpeg file size: %dx%d",jpeg_size.width, jpeg_size.height);
bm.width = jpeg_size.width;
bm.height = jpeg_size.height;
char *size_str[] = { "1/1", "1/2", "1/4", "1/8" };
int i;
for (i = 0; i < 4; i++)
{
lcd_printf("timing %s decode", size_str[i]);
ret = decode_jpeg_mem(jpeg_buf, filesize, &bm, plugin_buf_len,
FORMAT_NATIVE|FORMAT_RESIZE|FORMAT_KEEP_ASPECT,
&format_null);
if (ret == 1)
{
long t1, t2;
int count = 0;
t2 = *(rb->current_tick);
while (t2 != (t1 = *(rb->current_tick)));
do {
decode_jpeg_mem(jpeg_buf, filesize, &bm, plugin_buf_len,
FORMAT_NATIVE|FORMAT_RESIZE|FORMAT_KEEP_ASPECT,
&format_null);
count++;
t2 = *(rb->current_tick);
} while (t2 - t1 < HZ || count < 10);
t2 -= t1;
t2 *= 10;
t2 += count >> 1;
t2 /= count;
t1 = t2 / 1000;
t2 -= t1 * 1000;
lcd_printf("%01d.%03d secs/decode", (int)t1, (int)t2);
bm.width >>= 1;
bm.height >>= 1;
if (!(bm.width && bm.height))
break;
} else
lcd_printf("insufficient memory");
}
wait:
while (rb->get_action(CONTEXT_STD,1) != ACTION_STD_OK) rb->yield();
return PLUGIN_OK;
}

View file

@ -27,9 +27,8 @@ playergfx.c
profile_plugin.c profile_plugin.c
#endif #endif
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
#if !defined(HAVE_BMP_SCALING) || !defined(HAVE_JPEG) pluginlib_jpeg_mem.c
pluginlib_resize.c pluginlib_resize.c
#endif
#ifndef HAVE_JPEG #ifndef HAVE_JPEG
pluginlib_jpeg_load.c pluginlib_jpeg_load.c
#endif #endif

View file

@ -0,0 +1,41 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2009 by Andrew Mahone
*
* Header for the in-memory JPEG decoder.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "plugin.h"
#include "resize.h"
#include "bmp.h"
#include "jpeg_common.h"
#ifndef _JPEG_MEM_H
#define _JPEG_MEM_H
int get_jpeg_dim_mem(unsigned char *data, unsigned long len,
struct dim *size);
int decode_jpeg_mem(unsigned char *data, unsigned long len,
struct bitmap *bm,
int maxsize,
int format,
const struct custom_format *cformat);
#endif /* _JPEG_MEM_H */

View file

@ -0,0 +1,29 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2009 by Andrew Mahone
*
* This is a wrapper for the core jpeg_load.c, to provide the from-memory
* version of the decoder.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include <plugin.h>
#include "wrappers.h"
#define JPEG_FROM_MEM
#include "../../recorder/jpeg_load.c"

View file

@ -0,0 +1,103 @@
/*****************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// __ \_/ ___\| |/ /| __ \ / __ \ \/ /
* Jukebox | | ( (__) ) \___| ( | \_\ ( (__) ) (
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2009 Andrew Mahone
*
* In-memory JPEG decode test.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "plugin.h"
#include "lib/grey.h"
#include "lib/jpeg_mem.h"
PLUGIN_HEADER
/* different graphics libraries */
#if LCD_DEPTH < 8
#define USEGSLIB
GREY_INFO_STRUCT
#define MYLCD(fn) grey_ub_ ## fn
#define MYLCD_UPDATE()
#define MYXLCD(fn) grey_ub_ ## fn
#define CFORMAT &format_grey
#else
#define MYLCD(fn) rb->lcd_ ## fn
#define MYLCD_UPDATE() rb->lcd_update();
#define MYXLCD(fn) xlcd_ ## fn
#define CFORMAT &format_native
#endif
/* this is the plugin entry point */
enum plugin_status plugin_start(const void* parameter)
{
size_t plugin_buf_len;
unsigned char * plugin_buf =
(unsigned char *)rb->plugin_get_buffer(&plugin_buf_len);
static char filename[MAX_PATH];
struct bitmap bm = {
.width = LCD_WIDTH,
.height = LCD_HEIGHT,
};
int ret;
if(!parameter) return PLUGIN_ERROR;
rb->strcpy(filename, parameter);
#ifdef USEGSLIB
long greysize;
if (!grey_init(plugin_buf, plugin_buf_len, GREY_ON_COP,
LCD_WIDTH, LCD_HEIGHT, &greysize))
{
rb->splash(HZ, "grey buf error");
return PLUGIN_ERROR;
}
plugin_buf += greysize;
plugin_buf_len -= greysize;
#endif
int fd = rb->open(filename, O_RDONLY);
if (fd < 0)
return PLUGIN_ERROR;
unsigned long filesize = rb->filesize(fd);
if (filesize > plugin_buf_len)
return PLUGIN_ERROR;
plugin_buf_len -= filesize;
unsigned char *jpeg_buf = plugin_buf;
plugin_buf += filesize;
rb->read(fd, jpeg_buf, filesize);
rb->close(fd);
bm.data = plugin_buf;
ret = decode_jpeg_mem(jpeg_buf, filesize, &bm, plugin_buf_len,
FORMAT_NATIVE|FORMAT_RESIZE|FORMAT_KEEP_ASPECT,
CFORMAT);
if (ret < 1)
return PLUGIN_ERROR;
#ifdef USEGSLIB
grey_show(true);
grey_ub_gray_bitmap((fb_data *)bm.data, (LCD_WIDTH - bm.width) >> 1,
(LCD_HEIGHT - bm.height) >> 1, bm.width, bm.height);
#else
rb->lcd_bitmap((fb_data *)bm.data, (LCD_WIDTH - bm.width) >> 1,
(LCD_HEIGHT - bm.height) >> 1, bm.width, bm.height);
#endif
MYLCD_UPDATE();
while (rb->get_action(CONTEXT_STD,1) != ACTION_STD_OK) rb->yield();
#ifdef USEGSLIB
grey_release();
#endif
return PLUGIN_OK;
}

View file

@ -30,6 +30,12 @@ bmp,viewers/test_greylib_bitmap_scale,-
jpeg,viewers/test_core_jpeg,- jpeg,viewers/test_core_jpeg,-
jpe,viewers/test_core_jpeg,- jpe,viewers/test_core_jpeg,-
jpg,viewers/test_core_jpeg,- jpg,viewers/test_core_jpeg,-
jpeg,viewers/test_mem_jpeg,-
jpe,viewers/test_mem_jpeg,-
jpg,viewers/test_mem_jpeg,-
jpeg,viewers/bench_mem_jpeg,-
jpe,viewers/bench_mem_jpeg,-
jpg,viewers/bench_mem_jpeg,-
bmp,apps/rockpaint,11 bmp,apps/rockpaint,11
bmp,games/sliding_puzzle,11 bmp,games/sliding_puzzle,11
mpg,viewers/mpegplayer,4 mpg,viewers/mpegplayer,4

View file

@ -36,6 +36,11 @@
#define MEMCPY(d,s,c) memcpy(d,s,c) #define MEMCPY(d,s,c) memcpy(d,s,c)
#define INLINE static inline #define INLINE static inline
#define ENDIAN_SWAP16(n) n /* only for poor little endian machines */ #define ENDIAN_SWAP16(n) n /* only for poor little endian machines */
#ifdef ROCKBOX_DEBUG_JPEG
#define JDEBUGF DEBUGF
#else
#define JDEBUGF(...)
#endif
/**************** begin JPEG code ********************/ /**************** begin JPEG code ********************/
@ -51,9 +56,14 @@ typedef uint8_t jpeg_pix_t;
*/ */
struct jpeg struct jpeg
{ {
#ifdef JPEG_FROM_MEM
unsigned char *data;
unsigned long len;
#else
int fd; int fd;
int buf_left; int buf_left;
unsigned char *buf_index; unsigned char *buf_index;
#endif
unsigned long int bitbuf; unsigned long int bitbuf;
int bitbuf_bits; int bitbuf_bits;
int marker_ind; int marker_ind;
@ -103,6 +113,10 @@ struct jpeg
struct img_part part; struct img_part part;
}; };
#ifdef JPEG_FROM_MEM
static struct jpeg jpeg;
#endif
INLINE unsigned range_limit(int value) INLINE unsigned range_limit(int value)
{ {
#if CONFIG_CPU == SH7034 #if CONFIG_CPU == SH7034
@ -811,6 +825,37 @@ struct idct_entry idct_tbl[] = {
/* JPEG decoder implementation */ /* JPEG decoder implementation */
#ifdef JPEG_FROM_MEM
INLINE unsigned char *getc(struct jpeg* p_jpeg)
{
if (p_jpeg->len)
{
p_jpeg->len--;
return p_jpeg->data++;
} else
return NULL;
}
INLINE bool skip_bytes(struct jpeg* p_jpeg, int count)
{
if (p_jpeg->len >= (unsigned)count)
{
p_jpeg->len -= count;
p_jpeg->data += count;
return true;
} else {
p_jpeg->data += p_jpeg->len;
p_jpeg->len = 0;
return false;
}
}
INLINE void putc(struct jpeg* p_jpeg)
{
p_jpeg->len++;
p_jpeg->data--;
}
#else
INLINE void fill_buf(struct jpeg* p_jpeg) INLINE void fill_buf(struct jpeg* p_jpeg)
{ {
p_jpeg->buf_left = read(p_jpeg->fd, p_jpeg->buf, JPEG_READ_BUF_SIZE); p_jpeg->buf_left = read(p_jpeg->fd, p_jpeg->buf, JPEG_READ_BUF_SIZE);
@ -842,6 +887,13 @@ static bool skip_bytes(struct jpeg* p_jpeg, int count)
return p_jpeg->buf_left >= 0 || skip_bytes_seek(p_jpeg); return p_jpeg->buf_left >= 0 || skip_bytes_seek(p_jpeg);
} }
static void putc(struct jpeg* p_jpeg)
{
p_jpeg->buf_left++;
p_jpeg->buf_index--;
}
#endif
#define e_skip_bytes(jpeg, count) \ #define e_skip_bytes(jpeg, count) \
do {\ do {\
if (!skip_bytes((jpeg),(count))) \ if (!skip_bytes((jpeg),(count))) \
@ -863,12 +915,6 @@ do {\
c; \ c; \
}) })
static void putc(struct jpeg* p_jpeg)
{
p_jpeg->buf_left++;
p_jpeg->buf_index--;
}
/* Preprocess the JPEG JFIF file */ /* Preprocess the JPEG JFIF file */
static int process_markers(struct jpeg* p_jpeg) static int process_markers(struct jpeg* p_jpeg)
{ {
@ -881,11 +927,13 @@ static int process_markers(struct jpeg* p_jpeg)
{ {
if (c != 0xFF) /* no marker? */ if (c != 0xFF) /* no marker? */
{ {
JDEBUGF("Non-marker data\n");
putc(p_jpeg); putc(p_jpeg);
break; /* exit marker processing */ break; /* exit marker processing */
} }
c = e_getc(p_jpeg, -1); c = e_getc(p_jpeg, -1);
JDEBUGF("marker value %X\n",c);
switch (c) switch (c)
{ {
case 0xFF: /* Fill byte */ case 0xFF: /* Fill byte */
@ -896,9 +944,11 @@ static int process_markers(struct jpeg* p_jpeg)
case 0xC0: /* SOF Huff - Baseline DCT */ case 0xC0: /* SOF Huff - Baseline DCT */
{ {
JDEBUGF("SOF marker ");
ret |= SOF0; ret |= SOF0;
marker_size = e_getc(p_jpeg, -1) << 8; /* Highbyte */ marker_size = e_getc(p_jpeg, -1) << 8; /* Highbyte */
marker_size |= e_getc(p_jpeg, -1); /* Lowbyte */ marker_size |= e_getc(p_jpeg, -1); /* Lowbyte */
JDEBUGF("len: %d\n", marker_size);
n = e_getc(p_jpeg, -1); /* sample precision (= 8 or 12) */ n = e_getc(p_jpeg, -1); /* sample precision (= 8 or 12) */
if (n != 8) if (n != 8)
{ {
@ -908,6 +958,8 @@ static int process_markers(struct jpeg* p_jpeg)
p_jpeg->y_size |= e_getc(p_jpeg, -1); /* Lowbyte */ p_jpeg->y_size |= e_getc(p_jpeg, -1); /* Lowbyte */
p_jpeg->x_size = e_getc(p_jpeg, -1) << 8; /* Highbyte */ p_jpeg->x_size = e_getc(p_jpeg, -1) << 8; /* Highbyte */
p_jpeg->x_size |= e_getc(p_jpeg, -1); /* Lowbyte */ p_jpeg->x_size |= e_getc(p_jpeg, -1); /* Lowbyte */
JDEBUGF(" dimensions: %dx%d\n", p_jpeg->x_size,
p_jpeg->y_size);
n = (marker_size-2-6)/3; n = (marker_size-2-6)/3;
if (e_getc(p_jpeg, -1) != n || (n != 1 && n != 3)) if (e_getc(p_jpeg, -1) != n || (n != 1 && n != 3))
@ -1013,8 +1065,13 @@ static int process_markers(struct jpeg* p_jpeg)
return(-6); /* Arithmetic coding not supported */ return(-6); /* Arithmetic coding not supported */
case 0xD8: /* Start of Image */ case 0xD8: /* Start of Image */
JDEBUGF("SOI\n");
break;
case 0xD9: /* End of Image */ case 0xD9: /* End of Image */
JDEBUGF("EOI\n");
break;
case 0x01: /* for temp private use arith code */ case 0x01: /* for temp private use arith code */
JDEBUGF("private\n");
break; /* skip parameterless marker */ break; /* skip parameterless marker */
@ -1107,6 +1164,7 @@ static int process_markers(struct jpeg* p_jpeg)
marker_size = e_getc(p_jpeg, -1) << 8; /* Highbyte */ marker_size = e_getc(p_jpeg, -1) << 8; /* Highbyte */
marker_size |= e_getc(p_jpeg, -1); /* Lowbyte */ marker_size |= e_getc(p_jpeg, -1); /* Lowbyte */
marker_size -= 2; marker_size -= 2;
JDEBUGF("unhandled marker len %d\n", marker_size);
e_skip_bytes(p_jpeg, marker_size); /* skip segment */ e_skip_bytes(p_jpeg, marker_size); /* skip segment */
} }
break; break;
@ -1693,8 +1751,10 @@ static struct img_part *store_row_jpeg(void *jpeg_args)
int mcu_hscale = p_jpeg->h_scale[1]; int mcu_hscale = p_jpeg->h_scale[1];
int mcu_vscale = p_jpeg->v_scale[1]; int mcu_vscale = p_jpeg->v_scale[1];
#else #else
int mcu_hscale = (p_jpeg->h_scale[0] + p_jpeg->frameheader[0].horizontal_sampling - 1); int mcu_hscale = (p_jpeg->h_scale[0] +
int mcu_vscale = (p_jpeg->v_scale[0] + p_jpeg->frameheader[0].vertical_sampling - 1); p_jpeg->frameheader[0].horizontal_sampling - 1);
int mcu_vscale = (p_jpeg->v_scale[0] +
p_jpeg->frameheader[0].vertical_sampling - 1);
#endif #endif
unsigned int width = p_jpeg->x_mbl << mcu_hscale; unsigned int width = p_jpeg->x_mbl << mcu_hscale;
unsigned int b_width = width * JPEG_PIX_SZ; unsigned int b_width = width * JPEG_PIX_SZ;
@ -1855,6 +1915,7 @@ static struct img_part *store_row_jpeg(void *jpeg_args)
* Reads a JPEG file and puts the data in rockbox format in *bitmap. * Reads a JPEG file and puts the data in rockbox format in *bitmap.
* *
*****************************************************************************/ *****************************************************************************/
#ifndef JPEG_FROM_MEM
int read_jpeg_file(const char* filename, int read_jpeg_file(const char* filename,
struct bitmap *bm, struct bitmap *bm,
int maxsize, int maxsize,
@ -1874,6 +1935,7 @@ int read_jpeg_file(const char* filename,
close(fd); close(fd);
return ret; return ret;
} }
#endif
static int calc_scale(int in_size, int out_size) static int calc_scale(int in_size, int out_size)
{ {
@ -1889,7 +1951,28 @@ static int calc_scale(int in_size, int out_size)
return scale; return scale;
} }
#ifdef JPEG_FROM_MEM
int get_jpeg_dim_mem(unsigned char *data, unsigned long len,
struct dim *size)
{
struct jpeg *p_jpeg = &jpeg;
memset(p_jpeg, 0, sizeof(struct jpeg));
p_jpeg->data = data;
p_jpeg->len = len;
int status = process_markers(p_jpeg);
if (status < 0)
return status;
if ((status & (DQT | SOF0)) != (DQT | SOF0))
return -(status * 16);
size->width = p_jpeg->x_size;
size->height = p_jpeg->y_size;
return 0;
}
int decode_jpeg_mem(unsigned char *data, unsigned long len,
#else
int read_jpeg_fd(int fd, int read_jpeg_fd(int fd,
#endif
struct bitmap *bm, struct bitmap *bm,
int maxsize, int maxsize,
int format, int format,
@ -1898,17 +1981,25 @@ int read_jpeg_fd(int fd,
bool resize = false, dither = false; bool resize = false, dither = false;
struct rowset rset; struct rowset rset;
struct dim src_dim; struct dim src_dim;
struct jpeg *p_jpeg = (struct jpeg*)bm->data;
int tmp_size = maxsize;
int status; int status;
int bm_size; int bm_size;
#ifdef JPEG_FROM_MEM
struct jpeg *p_jpeg = &jpeg;
#else
struct jpeg *p_jpeg = (struct jpeg*)bm->data;
int tmp_size = maxsize;
ALIGN_BUFFER(p_jpeg, tmp_size, sizeof(int)); ALIGN_BUFFER(p_jpeg, tmp_size, sizeof(int));
/* not enough memory for our struct jpeg */ /* not enough memory for our struct jpeg */
if ((size_t)tmp_size < sizeof(struct jpeg)) if ((size_t)tmp_size < sizeof(struct jpeg))
return -1; return -1;
#endif
memset(p_jpeg, 0, sizeof(struct jpeg)); memset(p_jpeg, 0, sizeof(struct jpeg));
#ifdef JPEG_FROM_MEM
p_jpeg->data = data;
p_jpeg->len = len;
#else
p_jpeg->fd = fd; p_jpeg->fd = fd;
#endif
status = process_markers(p_jpeg); status = process_markers(p_jpeg);
if (status < 0) if (status < 0)
return status; return status;
@ -1968,14 +2059,16 @@ int read_jpeg_fd(int fd,
char *buf_start = (char *)bm->data + bm_size; char *buf_start = (char *)bm->data + bm_size;
char *buf_end = (char *)bm->data + maxsize; char *buf_end = (char *)bm->data + maxsize;
maxsize = buf_end - buf_start; maxsize = buf_end - buf_start;
#ifndef JPEG_FROM_MEM
ALIGN_BUFFER(buf_start, maxsize, sizeof(uint32_t)); ALIGN_BUFFER(buf_start, maxsize, sizeof(uint32_t));
if (maxsize < (int)sizeof(struct jpeg)) if (maxsize < (int)sizeof(struct jpeg))
return -1; return -1;
memmove(buf_start, p_jpeg, sizeof(struct jpeg)); memmove(buf_start, p_jpeg, sizeof(struct jpeg));
p_jpeg = (struct jpeg *)buf_start; p_jpeg = (struct jpeg *)buf_start;
fix_huff_tables(p_jpeg);
buf_start += sizeof(struct jpeg); buf_start += sizeof(struct jpeg);
maxsize = buf_end - buf_start; maxsize = buf_end - buf_start;
#endif
fix_huff_tables(p_jpeg);
#ifdef HAVE_LCD_COLOR #ifdef HAVE_LCD_COLOR
int decode_buf_size = (p_jpeg->x_mbl << p_jpeg->h_scale[1]) int decode_buf_size = (p_jpeg->x_mbl << p_jpeg->h_scale[1])
<< p_jpeg->v_scale[1]; << p_jpeg->v_scale[1];