Latest work on the bmp on-load scaler:
Macros for calculating size needed for bitmap load and scaling, so that these can be compile-time constant when their inputs are. Reduce size of bayer dither by chopping all but first row of dither matrix, and replacing 2D lookup with 1D lookup and small calculation. Move some functions not related to actual bmp file loading out of bmp.c. A smaller brightness() for mono targets, and a higher-quality one for greyscale targets, both replacing the division by 10 with a shift. Port of the linear and area scalers to greyscale targets, this costs some binsize but produces better output even when dithered to 2bpp. Move duplicated row output code from inside vertical scalers to a separate row output function. Move some multiplies out of the line scaler, for a small speedup and code size reduction, as well as a small improvement in accuracy for the upscaling case. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19592 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
7428c7cc5b
commit
f7fa7e5ad5
8 changed files with 761 additions and 819 deletions
|
@ -78,6 +78,7 @@ void* plugin_get_buffer(size_t *buffer_size);
|
|||
#include "playlist.h"
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
#include "scrollbar.h"
|
||||
#include "../recorder/bmp.h"
|
||||
#endif
|
||||
#include "statusbar.h"
|
||||
#include "menu.h"
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
#include "plugin.h"
|
||||
#include "lib/bmp.h"
|
||||
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
PLUGIN_HEADER
|
||||
|
@ -258,13 +257,9 @@ static int num_font = FONT_UI;
|
|||
static int moves_font = FONT_UI;
|
||||
static int moves_y = 0;
|
||||
|
||||
#ifdef HAVE_LCD_COLOR
|
||||
static unsigned char *img_buf;
|
||||
static size_t buf_len;
|
||||
#else
|
||||
static unsigned char img_buf[IMAGE_WIDTH*IMAGE_HEIGHT*sizeof(fb_data)]
|
||||
static unsigned char img_buf
|
||||
[BM_SCALED_SIZE(IMAGE_WIDTH,IMAGE_HEIGHT,FORMAT_NATIVE,0)]
|
||||
__attribute__ ((aligned(16)));
|
||||
#endif
|
||||
#ifdef HAVE_ALBUMART
|
||||
static char albumart_path[MAX_PATH+1];
|
||||
#endif
|
||||
|
@ -343,13 +338,9 @@ static bool load_resize_bitmap(void)
|
|||
main_bitmap.width = IMAGE_WIDTH;
|
||||
main_bitmap.height = IMAGE_HEIGHT;
|
||||
|
||||
#ifndef HAVE_LCD_COLOR
|
||||
size_t buf_len = sizeof(img_buf);
|
||||
#endif
|
||||
|
||||
rc = rb->read_bmp_file( filename, &main_bitmap,
|
||||
buf_len,
|
||||
FORMAT_NATIVE|FORMAT_RESIZE );
|
||||
sizeof(img_buf),
|
||||
FORMAT_NATIVE|FORMAT_RESIZE|FORMAT_DITHER);
|
||||
if( rc > 0 )
|
||||
{
|
||||
puzzle_bmp_ptr = (const fb_data *)img_buf;
|
||||
|
@ -574,7 +565,8 @@ static int puzzle_loop(void)
|
|||
/* change picture */
|
||||
picmode = (picmode+1)%PICMODE_LAST_XXX;
|
||||
|
||||
/* if load_resize_bitmap fails to load bitmap, try next picmode */
|
||||
/* if load_resize_bitmap fails to load bitmap, try next picmode
|
||||
*/
|
||||
do
|
||||
{
|
||||
load_success = load_resize_bitmap();
|
||||
|
@ -618,7 +610,8 @@ static int puzzle_loop(void)
|
|||
}
|
||||
}
|
||||
|
||||
enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter)
|
||||
enum plugin_status plugin_start(const struct plugin_api* api,
|
||||
const void* parameter)
|
||||
{
|
||||
int i, w, h;
|
||||
|
||||
|
@ -627,13 +620,6 @@ enum plugin_status plugin_start(const struct plugin_api* api, const void* parame
|
|||
initial_bmp_path=(const char *)parameter;
|
||||
picmode = PICMODE_INITIAL_PICTURE;
|
||||
img_buf_path[0] = '\0';
|
||||
#ifdef HAVE_LCD_COLOR
|
||||
unsigned char *img_buf_end;
|
||||
img_buf = (unsigned char *)(rb->plugin_get_buffer(&buf_len));
|
||||
img_buf_end = img_buf + buf_len;
|
||||
rb->align_buffer(PUN_PTR(void **,&img_buf), buf_len, 16);
|
||||
buf_len = img_buf_end - img_buf;
|
||||
#endif
|
||||
|
||||
/* If launched as a viewer, just go straight to the game without
|
||||
bothering with the splash or instructions page */
|
||||
|
|
|
@ -124,25 +124,10 @@ static const struct uint8_rgb bitfields[3][3] = {
|
|||
};
|
||||
|
||||
#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
|
||||
/* canonical ordered dither matrix */
|
||||
const unsigned char dither_matrix[16][16] = {
|
||||
{ 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 },
|
||||
{ 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 },
|
||||
{ 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 },
|
||||
{ 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 },
|
||||
{ 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 },
|
||||
{ 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 },
|
||||
{ 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 },
|
||||
{ 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 },
|
||||
{ 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 },
|
||||
{ 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 },
|
||||
{ 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 },
|
||||
{ 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 },
|
||||
{ 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 },
|
||||
{ 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 },
|
||||
{ 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 },
|
||||
{ 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 }
|
||||
};
|
||||
/* the full 16x16 Bayer dither matrix may be calculated quickly with this table
|
||||
*/
|
||||
const unsigned char dither_table[16] =
|
||||
{ 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 };
|
||||
#endif
|
||||
|
||||
#if ((LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)) \
|
||||
|
@ -194,7 +179,7 @@ struct bmp_args {
|
|||
short read_width;
|
||||
short width;
|
||||
short depth;
|
||||
unsigned char buf[MAX_WIDTH * 4];
|
||||
unsigned char buf[BM_MAX_WIDTH * 4];
|
||||
struct uint8_rgb *palette;
|
||||
#if LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
|
||||
int cur_row;
|
||||
|
@ -222,13 +207,14 @@ static unsigned int read_part_line(struct bmp_args *ba)
|
|||
int i, cols, len;
|
||||
|
||||
#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
|
||||
cols = MIN(width - cur_col,(int)MAX_WIDTH);
|
||||
cols = MIN(width - cur_col,(int)BM_MAX_WIDTH);
|
||||
BDEBUGF("reading %d cols (width: %d, max: %d)\n",cols,width,BM_MAX_WIDTH);
|
||||
len = (cols * (depth == 15 ? 16 : depth) + 7) >> 3;
|
||||
#else
|
||||
cols = width;
|
||||
len = read_width;
|
||||
#endif
|
||||
ibuf = ((unsigned char *)buf) + (MAX_WIDTH << 2) - len;
|
||||
ibuf = ((unsigned char *)buf) + (BM_MAX_WIDTH << 2) - len;
|
||||
BDEBUGF("read_part_line: cols=%d len=%d\n",cols,len);
|
||||
ret = read(fd, ibuf, len);
|
||||
if (ret != len)
|
||||
|
@ -239,25 +225,25 @@ static unsigned int read_part_line(struct bmp_args *ba)
|
|||
cols, len);
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < cols; i++)
|
||||
while (ibuf < ba->buf + (BM_MAX_WIDTH << 2))
|
||||
{
|
||||
switch (depth)
|
||||
{
|
||||
case 1:
|
||||
if ((i & 7) == 0)
|
||||
data = *ibuf++;
|
||||
*buf = palette[(data >> 7) & 1];
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
*buf++ = palette[data & 0x80 ? 1 : 0];
|
||||
data <<= 1;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
*buf = palette[*ibuf >> 4];
|
||||
if (i & 1)
|
||||
ibuf++;
|
||||
else
|
||||
*ibuf <<= 4;
|
||||
data = *ibuf++;
|
||||
*buf++ = palette[data >> 4];
|
||||
*buf++ = palette[data & 0xf];
|
||||
break;
|
||||
case 8:
|
||||
*buf = palette[*ibuf++];
|
||||
*buf++ = palette[*ibuf++];
|
||||
break;
|
||||
case 15:
|
||||
case 16:
|
||||
|
@ -280,6 +266,7 @@ static unsigned int read_part_line(struct bmp_args *ba)
|
|||
component = data & 0xf8;
|
||||
component |= component >> 5;
|
||||
buf->red = component;
|
||||
buf++;
|
||||
ibuf += 2;
|
||||
break;
|
||||
case 32:
|
||||
|
@ -289,11 +276,19 @@ static unsigned int read_part_line(struct bmp_args *ba)
|
|||
buf->red = *ibuf++;
|
||||
if (depth == 32)
|
||||
ibuf++;
|
||||
buf++;
|
||||
break;
|
||||
}
|
||||
buf++;
|
||||
}
|
||||
|
||||
#if !defined(HAVE_LCD_COLOR) && \
|
||||
(LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1))
|
||||
ibuf = ba->buf;
|
||||
buf = (struct uint8_rgb*)ba->buf;
|
||||
while (ibuf < ba->buf + cols)
|
||||
*ibuf++ = brightness(*buf++);
|
||||
#endif
|
||||
|
||||
#if LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
|
||||
cur_col += cols;
|
||||
if (cur_col == width)
|
||||
|
@ -323,58 +318,16 @@ static struct img_part *store_part_bmp(void *args)
|
|||
struct bmp_args *ba = (struct bmp_args *)args;
|
||||
|
||||
ba->part.len = read_part_line(ba);
|
||||
#ifdef HAVE_LCD_COLOR
|
||||
ba->part.buf = (struct uint8_rgb *)ba->buf;
|
||||
#else
|
||||
ba->part.buf = (uint8_t *)ba->buf;
|
||||
#endif
|
||||
if (ba->part.len)
|
||||
return &(ba->part);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool skip_lines_bmp(void *args, unsigned int lines)
|
||||
{
|
||||
struct bmp_args * ba = (struct bmp_args *)args;
|
||||
|
||||
int pad = lines * ba->padded_width +
|
||||
(ba->cur_col
|
||||
? ((ba->cur_col * ba->depth + 7) >> 3) - ba->padded_width
|
||||
: 0);
|
||||
if (pad)
|
||||
{
|
||||
if(lseek(ba->fd, pad, SEEK_CUR) < 0)
|
||||
|
||||
return false;
|
||||
}
|
||||
ba->cur_row += lines + (ba->cur_col ? 1 : 0);
|
||||
ba->cur_col = 0;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
|
||||
static inline int recalc_dimension(struct dim *dst, struct dim *src)
|
||||
{
|
||||
int tmp;
|
||||
if (dst->width <= 0)
|
||||
dst->width = LCD_WIDTH;
|
||||
if (dst->height <= 0)
|
||||
dst->height = LCD_HEIGHT;
|
||||
#ifndef HAVE_UPSCALER
|
||||
if (dst->width > src->width || dst->height > src->height)
|
||||
{
|
||||
dst->width = src->width;
|
||||
dst->height = src->height;
|
||||
}
|
||||
if (src->width == dst->width && src->height == dst->height)
|
||||
return 1;
|
||||
#endif
|
||||
tmp = (src->width * dst->height + (src->height >> 1)) / src->height;
|
||||
if (tmp > dst->width)
|
||||
dst->height = (src->height * dst->width + (src->width >> 1))
|
||||
/ src->width;
|
||||
else
|
||||
dst->width = tmp;
|
||||
return src->width == dst->width && src->height == dst->height;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int rgbcmp(struct uint8_rgb rgb1, struct uint8_rgb rgb2)
|
||||
|
@ -406,10 +359,10 @@ int read_bmp_fd(int fd,
|
|||
|
||||
unsigned char *bitmap = bm->data;
|
||||
struct uint8_rgb palette[256];
|
||||
bool remote = false;
|
||||
struct rowset rset;
|
||||
struct dim src_dim;
|
||||
#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
|
||||
bool remote = false;
|
||||
unsigned int resize = IMG_NORESIZE;
|
||||
bool dither = false;
|
||||
bool transparent = false;
|
||||
|
@ -419,24 +372,19 @@ int read_bmp_fd(int fd,
|
|||
remote = true;
|
||||
#if LCD_REMOTE_DEPTH == 1
|
||||
format = FORMAT_MONO;
|
||||
#else
|
||||
format &= ~FORMAT_REMOTE;
|
||||
#endif
|
||||
}
|
||||
#endif /* HAVE_REMOTE_LCD */
|
||||
|
||||
if (format & FORMAT_RESIZE) {
|
||||
resize = IMG_RESIZE;
|
||||
format &= ~FORMAT_RESIZE;
|
||||
}
|
||||
|
||||
if (format & FORMAT_TRANSPARENT) {
|
||||
transparent = true;
|
||||
format &= ~FORMAT_TRANSPARENT;
|
||||
}
|
||||
if (format & FORMAT_DITHER) {
|
||||
dither = true;
|
||||
format &= ~FORMAT_DITHER;
|
||||
}
|
||||
#else
|
||||
|
||||
|
@ -471,22 +419,22 @@ int read_bmp_fd(int fd,
|
|||
BDEBUGF("width: %d height: %d depth: %d padded_width: %d\n", src_dim.width,
|
||||
src_dim.height, depth, padded_width);
|
||||
|
||||
#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
|
||||
#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
|
||||
if ((format & 3) == FORMAT_ANY) {
|
||||
if (depth == 1)
|
||||
format = (format & ~3);
|
||||
else
|
||||
format = (format & ~3) | FORMAT_NATIVE;
|
||||
}
|
||||
bm->format = format & 3;
|
||||
if ((format & 3) == FORMAT_MONO)
|
||||
bm->format = format & 1;
|
||||
if ((format & 1) == FORMAT_MONO)
|
||||
{
|
||||
resize &= ~IMG_RESIZE;
|
||||
resize |= IMG_NORESIZE;
|
||||
remote = 0;
|
||||
}
|
||||
#else
|
||||
if (src_dim.width > MAX_WIDTH)
|
||||
if (src_dim.width > BM_MAX_WIDTH)
|
||||
return -6;
|
||||
#endif /*(LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)*/
|
||||
|
||||
|
@ -494,7 +442,6 @@ int read_bmp_fd(int fd,
|
|||
if (resize & IMG_RESIZE) {
|
||||
if(format & FORMAT_KEEP_ASPECT) {
|
||||
/* keep aspect ratio.. */
|
||||
format &= ~FORMAT_KEEP_ASPECT;
|
||||
struct dim resize_dim = {
|
||||
.width = bm->width,
|
||||
.height = bm->height,
|
||||
|
@ -506,6 +453,8 @@ int read_bmp_fd(int fd,
|
|||
}
|
||||
}
|
||||
|
||||
format &= 1;
|
||||
|
||||
if (!(resize & IMG_RESIZE)) {
|
||||
#endif
|
||||
/* returning image size */
|
||||
|
@ -524,7 +473,7 @@ int read_bmp_fd(int fd,
|
|||
rset.rowstop = -1;
|
||||
}
|
||||
|
||||
totalsize = get_totalsize(bm, remote);
|
||||
totalsize = BM_SIZE(bm->width,bm->height,format,remote);
|
||||
|
||||
/* Check if this fits the buffer */
|
||||
if (totalsize > maxsize) {
|
||||
|
@ -616,90 +565,146 @@ int read_bmp_fd(int fd,
|
|||
};
|
||||
|
||||
#if LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
|
||||
#if LCD_DEPTH == 16
|
||||
#ifdef HAVE_REMOTE_LCD
|
||||
if (resize & IMG_RESIZE || remote)
|
||||
#else
|
||||
if (resize & IMG_RESIZE)
|
||||
#endif
|
||||
#else
|
||||
if (format == FORMAT_NATIVE)
|
||||
#endif
|
||||
return resize_on_load(bm, dither, &src_dim, &rset, remote,
|
||||
#ifdef HAVE_LCD_COLOR
|
||||
if (resize)
|
||||
return resize_on_load(bm, dither, &src_dim, &rset,
|
||||
bitmap + totalsize, maxsize - totalsize,
|
||||
#endif
|
||||
store_part_bmp, skip_lines_bmp, &ba);
|
||||
store_part_bmp, &ba);
|
||||
|
||||
int fb_width = BM_WIDTH(bm->width,bm->format,remote);
|
||||
#endif /* LCD_DEPTH */
|
||||
|
||||
int fb_width = get_fb_width(bm, remote);
|
||||
int col, row;
|
||||
|
||||
/* loop to read rows and put them to buffer */
|
||||
for (row = rset.rowstart; row != rset.rowstop; row += rset.rowstep) {
|
||||
struct uint8_rgb *qp;
|
||||
#if !defined(HAVE_LCD_COLOR) && \
|
||||
(LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1))
|
||||
uint8_t* qp = ba.buf;
|
||||
#else
|
||||
struct uint8_rgb *qp = (struct uint8_rgb *)ba.buf;
|
||||
#endif
|
||||
unsigned mask;
|
||||
unsigned char *p;
|
||||
#if LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
|
||||
unsigned int len;
|
||||
|
||||
if (!(len = read_part_line(&ba)))
|
||||
return -9;
|
||||
#else
|
||||
if (!read_part_line(&ba))
|
||||
return -9;
|
||||
#endif
|
||||
|
||||
/* Convert to destination format */
|
||||
qp = (struct uint8_rgb *) ba.buf;
|
||||
#if LCD_DEPTH == 16
|
||||
if (format == FORMAT_NATIVE)
|
||||
#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
|
||||
unsigned char dy = DITHERY(row);
|
||||
if (format == FORMAT_NATIVE) {
|
||||
#if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
|
||||
if (remote) {
|
||||
#if (LCD_REMOTE_DEPTH == 2) && (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED)
|
||||
/* iAudio X5/M5 remote */
|
||||
fb_remote_data *dest = (fb_remote_data *)bitmap
|
||||
+ bm->width * (row >> 3);
|
||||
int shift = row & 7;
|
||||
int delta = 127;
|
||||
unsigned bright;
|
||||
|
||||
for (col = 0; col < bm->width; col++) {
|
||||
if (dither)
|
||||
delta = DITHERXDY(col,dy);
|
||||
#if !defined(HAVE_LCD_COLOR) && \
|
||||
(LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1))
|
||||
bright = *qp++;
|
||||
#else
|
||||
bright = brightness(*qp++);
|
||||
#endif
|
||||
bright = (3 * bright + (bright >> 6) + delta) >> 8;
|
||||
*dest++ |= vi_pattern[bright] << shift;
|
||||
}
|
||||
#endif /* LCD_REMOTE_DEPTH / LCD_REMOTE_PIXELFORMAT */
|
||||
} else
|
||||
#endif /* defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 */
|
||||
{
|
||||
#if LCD_DEPTH == 2
|
||||
#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
|
||||
/* greyscale iPods */
|
||||
fb_data *dest = (fb_data *)bitmap + fb_width * row;
|
||||
int shift = 6;
|
||||
int delta = 127;
|
||||
unsigned bright;
|
||||
unsigned data = 0;
|
||||
|
||||
for (col = 0; col < bm->width; col++) {
|
||||
if (dither)
|
||||
delta = DITHERXDY(col,dy);
|
||||
bright = *qp++;
|
||||
bright = (3 * bright + (bright >> 6) + delta) >> 8;
|
||||
data |= (~bright & 3) << shift;
|
||||
shift -= 2;
|
||||
if (shift < 0) {
|
||||
*dest++ = data;
|
||||
data = 0;
|
||||
shift = 6;
|
||||
}
|
||||
}
|
||||
if (shift < 6)
|
||||
*dest++ = data;
|
||||
#elif LCD_PIXELFORMAT == VERTICAL_PACKING
|
||||
/* iriver H1x0 */
|
||||
fb_data *dest = (fb_data *)bitmap + fb_width * (row >> 2);
|
||||
int shift = 2 * (row & 3);
|
||||
int delta = 127;
|
||||
unsigned bright;
|
||||
|
||||
for (col = 0; col < bm->width; col++) {
|
||||
if (dither)
|
||||
delta = DITHERXDY(col,dy);
|
||||
bright = *qp++;
|
||||
bright = (3 * bright + (bright >> 6) + delta) >> 8;
|
||||
*dest++ |= (~bright & 3) << shift;
|
||||
}
|
||||
#elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
|
||||
/* iAudio M3 */
|
||||
fb_data *dest = (fb_data *)bitmap + fb_width * (row >> 3);
|
||||
int shift = row & 7;
|
||||
int delta = 127;
|
||||
unsigned bright;
|
||||
|
||||
for (col = 0; col < bm->width; col++) {
|
||||
if (dither)
|
||||
delta = DITHERXDY(col,dy);
|
||||
bright = *qp++;
|
||||
bright = (3 * bright + (bright >> 6) + delta) >> 8;
|
||||
*dest++ |= vi_pattern[bright] << shift;
|
||||
}
|
||||
#endif /* LCD_PIXELFORMAT */
|
||||
#elif LCD_DEPTH == 16
|
||||
/* iriver h300, colour iPods, X5 */
|
||||
fb_data *dest = (fb_data *)bitmap + fb_width * row;
|
||||
int delta = 127;
|
||||
unsigned r, g, b;
|
||||
struct uint8_rgb q0;
|
||||
|
||||
for (col = 0; col < src_dim.width; col++) {
|
||||
for (col = 0; col < bm->width; col++) {
|
||||
if (dither)
|
||||
delta = dither_mat(row & 0xf, col & 0xf);
|
||||
if (!len)
|
||||
{
|
||||
if(!(len = read_part_line(&ba)))
|
||||
return -9;
|
||||
else
|
||||
qp = (struct uint8_rgb *)ba.buf;
|
||||
}
|
||||
delta = DITHERXDY(col,dy);
|
||||
q0 = *qp++;
|
||||
len--;
|
||||
r = (31 * q0.red + (q0.red >> 3) + delta) >> 8;
|
||||
g = (63 * q0.green + (q0.green >> 2) + delta) >> 8;
|
||||
b = (31 * q0.blue + (q0.blue >> 3) + delta) >> 8;
|
||||
*dest++ = LCD_RGBPACK_LCD(r, g, b);
|
||||
}
|
||||
#endif /* LCD_DEPTH */
|
||||
}
|
||||
else
|
||||
#endif
|
||||
} else
|
||||
#endif /* (LCD_DEPTH > 1) ||
|
||||
defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */
|
||||
{
|
||||
p = bitmap + fb_width * (row >> 3);
|
||||
p = bitmap + bm->width * (row >> 3);
|
||||
mask = 1 << (row & 7);
|
||||
for (col = 0; col < src_dim.width; col++)
|
||||
{
|
||||
#if LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
|
||||
if (!len)
|
||||
{
|
||||
if(!(len = read_part_line(&ba)))
|
||||
return -9;
|
||||
else
|
||||
qp = (struct uint8_rgb *)ba.buf;
|
||||
}
|
||||
len--;
|
||||
#endif
|
||||
|
||||
for (col = 0; col < bm->width; col++, p++)
|
||||
#if !defined(HAVE_LCD_COLOR) && \
|
||||
(LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1))
|
||||
if (*qp++ < 128)
|
||||
*p |= mask;
|
||||
#else
|
||||
if (brightness(*qp++) < 128)
|
||||
*p |= mask;
|
||||
p++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return totalsize; /* return the used buffer size. */
|
||||
|
|
|
@ -32,11 +32,7 @@
|
|||
|
||||
#define IMG_NORESIZE 0
|
||||
#define IMG_RESIZE 1
|
||||
#if LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
|
||||
#define MAX_WIDTH 8
|
||||
#else
|
||||
#define MAX_WIDTH LCD_WIDTH
|
||||
#endif
|
||||
#define BM_MAX_WIDTH (((LCD_WIDTH) + 7) & ~7)
|
||||
|
||||
struct uint8_rgb {
|
||||
uint8_t blue;
|
||||
|
@ -56,129 +52,144 @@ struct rowset {
|
|||
};
|
||||
|
||||
#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
|
||||
extern const unsigned char dither_matrix[16][16];
|
||||
static inline unsigned char dither_mat(unsigned int x, unsigned int y)
|
||||
{
|
||||
return dither_matrix[y][x];
|
||||
}
|
||||
extern const unsigned char dither_table[16];
|
||||
#define DITHERY(y) (dither_table[(y) & 15] & 0xAA)
|
||||
#define DITHERX(x) (dither_table[(x) & 15])
|
||||
#define DITHERXDY(x,dy) (DITHERX(x) ^ dy)
|
||||
#define DITHERDXY(dx,y) (dx ^ DITHERY(y))
|
||||
#define DITHERXY(x,y) (DITHERX(x) ^ DITHERY(y))
|
||||
#endif
|
||||
|
||||
/* The /256 version has a mean squared variance from YUV luma of <1 grey level.
|
||||
The /8 version is a good deal less accurate, but sufficient on mono as we
|
||||
don't support HQ output or dithering there, yet.
|
||||
*/
|
||||
static inline unsigned brightness(struct uint8_rgb color)
|
||||
{
|
||||
return (3 * (unsigned)color.red + 6 * (unsigned)color.green
|
||||
+ (unsigned)color.blue) / 10;
|
||||
#if LCD_DEPTH > 1
|
||||
return (77 * (unsigned)color.red + 150 * (unsigned)color.green
|
||||
+ 29 * (unsigned)color.blue) / 256;
|
||||
#else
|
||||
return (2 * (unsigned)color.red + 5 * (unsigned)color.green
|
||||
+ (unsigned)color.blue) / 8;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ((LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)) \
|
||||
|| (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH == 2) \
|
||||
&& (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED))
|
||||
extern const unsigned short vi_pattern[4];
|
||||
static inline unsigned short vi_pat(unsigned int bright)
|
||||
{
|
||||
return vi_pattern[bright];
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int get_fb_height(struct bitmap *bm, bool remote)
|
||||
{
|
||||
const int height = bm->height;
|
||||
#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
|
||||
const int format = bm->format;
|
||||
#endif
|
||||
int dst_height;
|
||||
/* Number of rows of data in a mono bitmap height pixels tall */
|
||||
#define MONO_BM_HEIGHT(height) (((height) + 7) >> 3)
|
||||
|
||||
#if !defined(HAVE_REMOTE_LCD) || \
|
||||
(defined(HAVE_REMOTE_LCD) &&(LCD_REMOTE_DEPTH == 1))
|
||||
(void) remote;
|
||||
/* Number of rows of datain a LCD native bitmap height pixels tall */
|
||||
#if LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
|
||||
#if LCD_DEPTH == 1 || \
|
||||
(LCD_DEPTH == 2 && LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
|
||||
#define LCD_BM_HEIGHT(height) (((height) + 7) >> 3)
|
||||
#elif LCD_DEPTH == 2 && LCD_PIXELFORMAT == VERTICAL_PACKING
|
||||
#define LCD_BM_HEIGHT(height) (((height) + 3) >> 2)
|
||||
#else
|
||||
#define LCD_BM_HEIGHT(height) (height)
|
||||
#endif
|
||||
|
||||
#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
|
||||
if (format == FORMAT_NATIVE) {
|
||||
#if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
|
||||
if (remote) {
|
||||
#if (LCD_REMOTE_DEPTH == 2) && (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED)
|
||||
dst_height = (height + 7) >> 3;
|
||||
#endif /* LCD_REMOTE_DEPTH / LCD_REMOTE_PIXELFORMAT */
|
||||
} else
|
||||
#endif /* defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 */
|
||||
{
|
||||
#if LCD_DEPTH == 2
|
||||
#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
|
||||
dst_height = height;
|
||||
#elif LCD_PIXELFORMAT == VERTICAL_PACKING
|
||||
dst_height = (height + 3) >> 2;
|
||||
#elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
|
||||
dst_height = (height + 7) >> 3;
|
||||
#endif /* LCD_PIXELFORMAT */
|
||||
#elif LCD_DEPTH == 16
|
||||
dst_height = height;
|
||||
#endif /* LCD_DEPTH */
|
||||
}
|
||||
} else
|
||||
#endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */
|
||||
{
|
||||
dst_height = (height + 7) >> 3;
|
||||
}
|
||||
|
||||
return dst_height;
|
||||
}
|
||||
|
||||
static inline int get_fb_width(struct bitmap *bm, bool remote)
|
||||
{
|
||||
const int width = bm->width;
|
||||
#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
|
||||
const int format = bm->format;
|
||||
#endif
|
||||
int dst_width;
|
||||
|
||||
#if !defined(HAVE_REMOTE_LCD) || \
|
||||
(defined(HAVE_REMOTE_LCD) &&(LCD_REMOTE_DEPTH == 1))
|
||||
(void) remote;
|
||||
#endif
|
||||
|
||||
#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
|
||||
if (format == FORMAT_NATIVE) {
|
||||
#if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
|
||||
if (remote) {
|
||||
#if (LCD_REMOTE_DEPTH == 2) && (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED)
|
||||
dst_width = width;
|
||||
#endif /* LCD_REMOTE_DEPTH / LCD_REMOTE_PIXELFORMAT */
|
||||
} else
|
||||
#endif /* defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 */
|
||||
{
|
||||
#if LCD_DEPTH == 2
|
||||
#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
|
||||
dst_width = (width + 3) >> 2;
|
||||
#elif LCD_PIXELFORMAT == VERTICAL_PACKING
|
||||
dst_width = width;
|
||||
#elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
|
||||
dst_width = width;
|
||||
#endif /* LCD_PIXELFORMAT */
|
||||
#elif LCD_DEPTH == 16
|
||||
dst_width = width;
|
||||
#endif /* LCD_DEPTH */
|
||||
}
|
||||
} else
|
||||
#endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */
|
||||
{
|
||||
dst_width = width;
|
||||
}
|
||||
|
||||
return dst_width;
|
||||
}
|
||||
|
||||
static inline int get_totalsize(struct bitmap *bm, bool remote)
|
||||
{
|
||||
int sz;
|
||||
/* Number of rows of data in a remote native bitmap height pixels tall. */
|
||||
#ifdef HAVE_REMOTE_LCD
|
||||
if (remote && sizeof(fb_data) != sizeof(fb_remote_data))
|
||||
sz = sizeof(fb_remote_data);
|
||||
else
|
||||
#endif /* LCD_REMOTE_DEPTH / LCD_REMOTE_PIXELFORMAT */
|
||||
sz = sizeof(fb_data);
|
||||
#if LCD_REMOTE_DEPTH == 1 || \
|
||||
(LCD_REMOTE_DEPTH == 2 && LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED)
|
||||
#define LCD_REMOTE_BM_HEIGHT(height) (((height) + 7) >> 3)
|
||||
#elif LCD_REMOTE_DEPTH == 2 && LCD_REMOTE_PIXELFORMAT == VERTICAL_PACKING
|
||||
#define LCD_REMOTE_BM_HEIGHT(height) (((height) + 3) >> 2)
|
||||
#else
|
||||
#define LCD_REMOTE_BM_HEIGHT(height) (height)
|
||||
#endif
|
||||
#define NATIVE_BM_HEIGHT(height,remote) ((remote) ? \
|
||||
LCD_REMOTE_BM_HEIGHT(height) : LCD_BM_HEIGHT(height))
|
||||
#else
|
||||
#define NATIVE_BM_HEIGHT(height,remote) LCD_BM_HEIGHT(height)
|
||||
#endif
|
||||
|
||||
return get_fb_width(bm, remote) * get_fb_height(bm, remote) * sz;
|
||||
}
|
||||
/* Convenience macro to calculate rows based on height, remote vs main LCD,
|
||||
and format
|
||||
*/
|
||||
#define BM_HEIGHT(height,format,remote) ((format) == FORMAT_MONO ? \
|
||||
MONO_BM_HEIGHT(height) : NATIVE_BM_HEIGHT(height,remote))
|
||||
#else
|
||||
#define BM_HEIGHT(height,format,remote) MONO_BM_HEIGHT(height)
|
||||
#endif
|
||||
|
||||
/* Number of data elements in a mono bitmap width pixels wide */
|
||||
#define MONO_BM_WIDTH(width) (width)
|
||||
|
||||
/* Number of data elements in a LCD native bitmap width pixels wide */
|
||||
#if LCD_DEPTH > 1
|
||||
#if LCD_DEPTH == 2 && LCD_PIXELFORMAT == HORIZONTAL_PACKING
|
||||
#define LCD_BM_WIDTH(width) (((width) + 3) >> 2)
|
||||
#else
|
||||
#define LCD_BM_WIDTH(width) (width)
|
||||
#endif
|
||||
|
||||
/* Number of data elements in a remote native bitmap width pixels wide */
|
||||
#ifdef HAVE_LCD_REMOTE
|
||||
#if LCD_REMOTE_DEPTH == 2 && LCD_REMOTE_PIXELFORMAT == HORIZONTAL_PACKING
|
||||
#define LCD_REMOTE_BM_WIDTH(width) (((width) + 3) >> 2)
|
||||
#else
|
||||
#define LCD_REMOTE_BM_WIDTH(width) (width)
|
||||
#endif
|
||||
#define NATIVE_BM_WIDTH(width,remote) ((remote) ? \
|
||||
LCD_REMOTE_BM_WIDTH(width) : LCD_BM_WIDTH(width))
|
||||
#else
|
||||
#define NATIVE_BM_WIDTH(width,remote) LCD_BM_WIDTH(width)
|
||||
#endif
|
||||
|
||||
/* Convenience macro to calculate elements based on height, remote vs native
|
||||
main LCD, and format
|
||||
*/
|
||||
#define BM_WIDTH(width,format,remote) ((format) == FORMAT_MONO ? \
|
||||
MONO_BM_WIDTH(width) : NATIVE_BM_WIDTH(width,remote))
|
||||
#else
|
||||
#define BM_WIDTH(width,format,remote) MONO_BM_WIDTH(width)
|
||||
#endif
|
||||
|
||||
/* Size in bytes of a mono bitmap of dimensions width*height */
|
||||
#define MONO_BM_SIZE(width,height) (MONO_BM_WIDTH(width) * \
|
||||
MONO_BM_HEIGHT(height) * FB_DATA_SZ)
|
||||
|
||||
/* Size in bytes of a native bitmap of dimensions width*height */
|
||||
#if LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
|
||||
#if defined(HAVE_REMOTE_LCD) && FB_DATA_SZ != FB_RDATA_SZ
|
||||
#define NATIVE_BM_SIZE(width,height,format,remote) \
|
||||
(((remote) ? FB_RDATA_SZ : FB_DATA_SZ) * BM_WIDTH(width,format,remote) \
|
||||
* BM_HEIGHT(height,format,remote))
|
||||
#else
|
||||
#define NATIVE_BM_SIZE(width,height,format,remote) \
|
||||
(FB_DATA_SZ * BM_WIDTH(width,format,remote) * \
|
||||
BM_HEIGHT(height,format,remote))
|
||||
#endif
|
||||
|
||||
/* Convenience macro to calculate size in bytes based on height, remote vs
|
||||
main LCD, and format
|
||||
*/
|
||||
#define BM_SIZE(width,height,format,remote) (((format) == FORMAT_MONO) ? \
|
||||
MONO_BM_SIZE(width,height) : NATIVE_BM_SIZE(width,height,format,remote))
|
||||
#else
|
||||
#define BM_SIZE(width,height,format,remote) MONO_BM_SIZE(width,height)
|
||||
#endif
|
||||
|
||||
/* Size in bytes needed to load and scale a bitmap with target size up to
|
||||
width*height, including overhead to allow for buffer alignment.
|
||||
*/
|
||||
#ifdef HAVE_LCD_COLOR
|
||||
#define BM_SCALED_SIZE(width,height,format,remote) \
|
||||
(BM_SIZE(width,height,format,remote) + \
|
||||
(remote ? 0 : BM_WIDTH(width,format,remote) * sizeof(uint32_t) * 9 + 3))
|
||||
#else
|
||||
#define BM_SCALED_SIZE(width,height,format,remote) \
|
||||
(BM_SIZE(width,height,format,remote) + \
|
||||
(width * sizeof(uint32_t) * 3 + 3))
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
* read_bmp_file()
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "config.h"
|
||||
#include "lcd.h"
|
||||
#include "inttypes.h"
|
||||
|
||||
/****************************************************************
|
||||
* resize_on_load()
|
||||
|
@ -45,16 +46,30 @@
|
|||
|
||||
struct img_part {
|
||||
int len;
|
||||
#if !defined(HAVE_LCD_COLOR) && \
|
||||
(LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1))
|
||||
uint8_t *buf;
|
||||
#else
|
||||
struct uint8_rgb* buf;
|
||||
#endif
|
||||
};
|
||||
|
||||
int resize_on_load(struct bitmap *bm, bool dither,
|
||||
struct dim *src,
|
||||
struct rowset *tmp_row, bool remote,
|
||||
#ifdef HAVE_LCD_COLOR
|
||||
unsigned char *buf, unsigned int len,
|
||||
/* intermediate type used by the scaler for color output. greyscale version
|
||||
uses uint32_t
|
||||
*/
|
||||
struct uint32_rgb {
|
||||
uint32_t r;
|
||||
uint32_t g;
|
||||
uint32_t b;
|
||||
};
|
||||
#endif
|
||||
|
||||
int recalc_dimension(struct dim *dst, struct dim *src);
|
||||
|
||||
int resize_on_load(struct bitmap *bm, bool dither,
|
||||
struct dim *src, struct rowset *tmp_row,
|
||||
unsigned char *buf, unsigned int len,
|
||||
struct img_part* (*store_part)(void *args),
|
||||
bool (*skip_lines)(void *args, unsigned int lines),
|
||||
void *args);
|
||||
#endif /* _RESIZE_H_ */
|
||||
|
|
|
@ -48,13 +48,17 @@ int remote_type(void);
|
|||
#if (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED) \
|
||||
|| (LCD_REMOTE_PIXELFORMAT == HORIZONTAL_INTERLEAVED)
|
||||
typedef unsigned short fb_remote_data;
|
||||
#define FB_RDATA_SZ 2
|
||||
#else
|
||||
typedef unsigned char fb_remote_data;
|
||||
#define FB_RDATA_SZ 1
|
||||
#endif
|
||||
#elif LCD_DEPTH <= 16
|
||||
typedef unsigned short fb_remote_data;
|
||||
#define FB_RDATA_SZ 2
|
||||
#else
|
||||
typedef unsigned long fb_remote_data;
|
||||
#define FB_RDATA_SZ 4
|
||||
#endif
|
||||
|
||||
/* common functions */
|
||||
|
|
|
@ -75,13 +75,17 @@ struct viewport {
|
|||
#if (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED) \
|
||||
|| (LCD_PIXELFORMAT == HORIZONTAL_INTERLEAVED)
|
||||
typedef unsigned short fb_data;
|
||||
#define FB_DATA_SZ 2
|
||||
#else
|
||||
typedef unsigned char fb_data;
|
||||
#define FB_DATA_SZ 1
|
||||
#endif
|
||||
#elif LCD_DEPTH <= 16
|
||||
typedef unsigned short fb_data;
|
||||
#define FB_DATA_SZ 2
|
||||
#else /* LCD_DEPTH > 16 */
|
||||
typedef unsigned long fb_data;
|
||||
#define FB_DATA_SZ 4
|
||||
#endif /* LCD_DEPTH */
|
||||
|
||||
#else /* LCD_CHARCELLS */
|
||||
|
|
Loading…
Reference in a new issue