From 91efc162564cd9c04677e2e38550cde21995b06e Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Sat, 9 May 2009 07:31:27 +0000 Subject: Split 8-bit-to-native conversion in bmp.c into a function, add support for plugging unscaled output in BMP and JPEG loaders, use output_row_8_native in JPEG decoder when possible. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20884 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/bench_mem_jpeg.c | 5 +- apps/plugins/lib/grey_draw.c | 13 +- apps/plugins/lib/pluginlib_bmp.c | 7 -- apps/plugins/pictureflow/pictureflow.c | 35 +++++- apps/recorder/bmp.c | 218 +++++++++++++++++++-------------- apps/recorder/bmp.h | 4 + apps/recorder/jpeg_load.c | 57 ++++++++- apps/recorder/resize.c | 23 ++-- apps/recorder/resize.h | 8 +- 9 files changed, 242 insertions(+), 128 deletions(-) diff --git a/apps/plugins/bench_mem_jpeg.c b/apps/plugins/bench_mem_jpeg.c index 958e5208e8..cd7dea356e 100644 --- a/apps/plugins/bench_mem_jpeg.c +++ b/apps/plugins/bench_mem_jpeg.c @@ -42,13 +42,14 @@ static void output_row_null(uint32_t row, void * row_in, } const struct custom_format format_null = { + .output_row_8 = output_row_null, #ifdef HAVE_LCD_COLOR - .output_row = { + .output_row_32 = { output_row_null, output_row_null }, #else - .output_row = output_row_null, + .output_row_32 = output_row_null, #endif .get_size = get_size_null }; diff --git a/apps/plugins/lib/grey_draw.c b/apps/plugins/lib/grey_draw.c index 65f2211b7f..6315ad9b1a 100644 --- a/apps/plugins/lib/grey_draw.c +++ b/apps/plugins/lib/grey_draw.c @@ -719,7 +719,15 @@ void grey_ub_gray_bitmap(const unsigned char *src, int x, int y, int width, grey_ub_gray_bitmap_part(src, 0, 0, width, x, y, width, height); } -static void output_row_grey(uint32_t row, void * row_in, struct scaler_context *ctx) +static void output_row_grey_8(uint32_t row, void * row_in, + struct scaler_context *ctx) +{ + uint8_t *dest = (uint8_t*)ctx->bm->data + ctx->bm->width * row; + rb->memcpy(dest, row_in, ctx->bm->width); +} + +static void output_row_grey_32(uint32_t row, void * row_in, + struct scaler_context *ctx) { int col; uint32_t *qp = (uint32_t*)row_in; @@ -734,6 +742,7 @@ static unsigned int get_size_grey(struct bitmap *bm) } const struct custom_format format_grey = { - .output_row = output_row_grey, + .output_row_8 = output_row_grey_8, + .output_row_32 = output_row_grey_32, .get_size = get_size_grey }; diff --git a/apps/plugins/lib/pluginlib_bmp.c b/apps/plugins/lib/pluginlib_bmp.c index 110e534be0..6b1a54291c 100644 --- a/apps/plugins/lib/pluginlib_bmp.c +++ b/apps/plugins/lib/pluginlib_bmp.c @@ -124,14 +124,7 @@ void simple_resize_bitmap(struct bitmap *src, struct bitmap *dst) #endif /* LCD_DEPTH > 1 */ -#ifndef HAVE_BMP_SCALING #include "wrappers.h" /* import the core bmp loader */ #include "recorder/bmp.c" -#else -/* 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 diff --git a/apps/plugins/pictureflow/pictureflow.c b/apps/plugins/pictureflow/pictureflow.c index 82dc9748ec..6dd034c9a9 100644 --- a/apps/plugins/pictureflow/pictureflow.c +++ b/apps/plugins/pictureflow/pictureflow.c @@ -607,7 +607,29 @@ static inline uint32_t div255(uint32_t val) #define SCALE_VAL(val,out) div255((val) * (out) + 127) -static void output_row_transposed(uint32_t row, void * row_in, +static void output_row_8_transposed(uint32_t row, void * row_in, + struct scaler_context *ctx) +{ + pix_t *dest = (pix_t*)ctx->bm->data + row; + pix_t *end = dest + ctx->bm->height * ctx->bm->width; +#ifdef USEGSLIB + uint8_t *qp = (uint8_t*)row_in; + for (; dest < end; dest += ctx->bm->height) + *dest = *qp++; +#else + struct uint8_rgb *qp = (struct uint8_rgb*)row_in; + unsigned r, g, b; + for (; dest < end; dest += ctx->bm->height) + { + r = qp->red; + g = qp->green; + b = (qp++)->blue; + *dest = LCD_RGBPACK_LCD(r,g,b); + } +#endif +} + +static void output_row_32_transposed(uint32_t row, void * row_in, struct scaler_context *ctx) { pix_t *dest = (pix_t*)ctx->bm->data + row; @@ -635,7 +657,7 @@ static void output_row_transposed(uint32_t row, void * row_in, } #ifdef HAVE_LCD_COLOR -static void output_row_transposed_fromyuv(uint32_t row, void * row_in, +static void output_row_32_transposed_fromyuv(uint32_t row, void * row_in, struct scaler_context *ctx) { pix_t *dest = (pix_t*)ctx->bm->data + row; @@ -663,13 +685,14 @@ static unsigned int get_size(struct bitmap *bm) } const struct custom_format format_transposed = { + .output_row_8 = output_row_8_transposed, #ifdef HAVE_LCD_COLOR - .output_row = { - output_row_transposed, - output_row_transposed_fromyuv + .output_row_32 = { + output_row_32_transposed, + output_row_32_transposed_fromyuv }, #else - .output_row = output_row_transposed, + .output_row_32 = output_row_32_transposed, #endif .get_size = get_size }; diff --git a/apps/recorder/bmp.c b/apps/recorder/bmp.c index f1fc1f83b4..4897b2db18 100644 --- a/apps/recorder/bmp.c +++ b/apps/recorder/bmp.c @@ -351,6 +351,93 @@ static inline int rgbcmp(struct uint8_rgb rgb1, struct uint8_rgb rgb2) else return 1; } +#if LCD_DEPTH > 1 +void output_row_8_native(uint32_t row, void * row_in, + struct scaler_context *ctx) +{ + int col; + int fb_width = BM_WIDTH(ctx->bm->width,FORMAT_NATIVE,0); + uint8_t dy = DITHERY(row); +#ifdef HAVE_LCD_COLOR + struct uint8_rgb *qp = (struct uint8_rgb*)row_in; +#else + uint8_t *qp = (uint8_t*)row_in; +#endif + BDEBUGF("output_row: y: %lu in: %p\n",row, row_in); +#if LCD_DEPTH == 2 +#if LCD_PIXELFORMAT == HORIZONTAL_PACKING + /* greyscale iPods */ + fb_data *dest = (fb_data *)ctx->bm->data + fb_width * row; + int shift = 6; + int delta = 127; + unsigned bright; + unsigned data = 0; + + for (col = 0; col < ctx->bm->width; col++) { + if (ctx->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 *)ctx->bm->data + fb_width * + (row >> 2); + int shift = 2 * (row & 3); + int delta = 127; + unsigned bright; + + for (col = 0; col < ctx->bm->width; col++) { + if (ctx->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 *)ctx->bm->data + fb_width * + (row >> 3); + int shift = row & 7; + int delta = 127; + unsigned bright; + + for (col = 0; col < ctx->bm->width; col++) { + if (ctx->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 *)ctx->bm->data + fb_width * row; + int delta = 127; + unsigned r, g, b; + for (col = 0; col < ctx->bm->width; col++) { + if (ctx->dither) + delta = DITHERXDY(col,dy); + r = qp->red; + g = qp->green; + b = (qp++)->blue; + r = (31 * r + (r >> 3) + delta) >> 8; + g = (63 * g + (g >> 2) + delta) >> 8; + b = (31 * b + (b >> 3) + delta) >> 8; + *dest++ = LCD_RGBPACK_LCD(r, g, b); + } +#endif /* LCD_DEPTH */ +} +#endif /****************************************************************************** * read_bmp_fd() @@ -598,7 +685,7 @@ int read_bmp_fd(int fd, #if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \ defined(HAVE_BMP_SCALING) || defined(PLUGIN) #if LCD_DEPTH > 1 && defined(HAVE_BMP_SCALING) - if (resize || cformat) + if (resize) #endif { if (resize_on_load(bm, dither, &src_dim, &rset, @@ -610,31 +697,43 @@ int read_bmp_fd(int fd, } #endif /* LCD_DEPTH */ -#ifndef PLUGIN -#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) - int fb_width = BM_WIDTH(bm->width,bm->format,remote); +#if LCD_DEPTH > 1 || defined(PLUGIN) + struct scaler_context ctx = { + .bm = bm, + .dither = dither, + }; +#endif +#if LCD_DEPTH > 1 + void (*output_row_8)(uint32_t, void*, struct scaler_context*) = + output_row_8_native; +#elif defined(PLUGIN) + void (*output_row_8)(uint32_t, void*, struct scaler_context*) = NULL; +#endif +#if LCD_DEPTH > 1 || defined(PLUGIN) + if (cformat) + output_row_8 = cformat->output_row_8; #endif - int col, row; + int row; /* loop to read rows and put them to buffer */ for (row = rset.rowstart; row != rset.rowstop; row += rset.rowstep) { + if (!read_part_line(&ba)) + return -9; +#ifndef PLUGIN #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 (!read_part_line(&ba)) - return -9; - +#endif /* Convert to destination format */ -#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) - unsigned char dy = DITHERY(row); +#if ((LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) && \ + !defined(PLUGIN) if (format == FORMAT_NATIVE) { #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 if (remote) { + unsigned char dy = DITHERY(row); #if (LCD_REMOTE_DEPTH == 2) && (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED) /* iAudio X5/M5 remote */ fb_remote_data *dest = (fb_remote_data *)bitmap @@ -643,6 +742,7 @@ int read_bmp_fd(int fd, int delta = 127; unsigned bright; + int col; for (col = 0; col < bm->width; col++) { if (dither) delta = DITHERXDY(col,dy); @@ -658,85 +758,25 @@ int read_bmp_fd(int fd, #endif /* LCD_REMOTE_DEPTH / LCD_REMOTE_PIXELFORMAT */ } else #endif /* defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 */ +#endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && + (LCD_REMOTE_DEPTH > 1) */ +#if LCD_DEPTH > 1 || defined(PLUGIN) { -#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 < bm->width; col++) { - if (dither) - delta = DITHERXDY(col,dy); - q0 = *qp++; - 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 */ + output_row_8(row, ba.buf, &ctx); } - } else -#endif /* (LCD_DEPTH > 1) || - defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */ +#endif +#if ((LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) && \ + !defined(PLUGIN) + } +#ifndef PLUGIN + else +#endif +#endif +#ifndef PLUGIN { - p = bitmap + bm->width * (row >> 3); - mask = 1 << (row & 7); - + unsigned char *p = bitmap + bm->width * (row >> 3); + unsigned char mask = 1 << (row & 7); + int col; for (col = 0; col < bm->width; col++, p++) #if !defined(HAVE_LCD_COLOR) && \ (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) @@ -747,7 +787,7 @@ int read_bmp_fd(int fd, *p |= mask; #endif } +#endif } return totalsize; /* return the used buffer size. */ -#endif } diff --git a/apps/recorder/bmp.h b/apps/recorder/bmp.h index c570a3d6bd..6437e42d26 100644 --- a/apps/recorder/bmp.h +++ b/apps/recorder/bmp.h @@ -212,4 +212,8 @@ int read_bmp_fd(int fd, int format, const struct custom_format *cformat); +#if LCD_DEPTH > 1 +void output_row_8_native(uint32_t row, void * row_in, + struct scaler_context *ctx); +#endif #endif diff --git a/apps/recorder/jpeg_load.c b/apps/recorder/jpeg_load.c index 555f60d6bd..9393e60de8 100644 --- a/apps/recorder/jpeg_load.c +++ b/apps/recorder/jpeg_load.c @@ -109,6 +109,7 @@ struct jpeg int tab_membership[6]; int subsample_x[3]; /* info per component */ int subsample_y[3]; + bool resize; unsigned char buf[JPEG_READ_BUF_SIZE]; struct img_part part; }; @@ -2025,14 +2026,15 @@ int read_jpeg_fd(int fd, recalc_dimension(&resize_dim, &src_dim); bm->width = resize_dim.width; bm->height = resize_dim.height; - if (bm->width == src_dim.width && bm->height == src_dim.height) - resize = false; } else { bm->width = p_jpeg->x_size; bm->height = p_jpeg->y_size; } p_jpeg->h_scale[0] = calc_scale(p_jpeg->x_size, bm->width); p_jpeg->v_scale[0] = calc_scale(p_jpeg->y_size, bm->height); + if ((p_jpeg->x_size << p_jpeg->h_scale[0]) >> 3 && + (p_jpeg->y_size << p_jpeg->v_scale[0]) >> 3) + resize = false; #ifdef HAVE_LCD_COLOR p_jpeg->h_scale[1] = p_jpeg->h_scale[0] + p_jpeg->frameheader[0].horizontal_sampling - 1; @@ -2092,11 +2094,54 @@ int read_jpeg_fd(int fd, rset.rowstart = 0; rset.rowstop = bm->height; rset.rowstep = 1; - if (resize_on_load(bm, dither, &src_dim, &rset, buf_start, maxsize, cformat, - IF_PIX_FMT(p_jpeg->blocks == 1 ? 0 : 1,) store_row_jpeg, p_jpeg)) + p_jpeg->resize = resize; + if (resize) + { + if (resize_on_load(bm, dither, &src_dim, &rset, buf_start, maxsize, + cformat, IF_PIX_FMT(p_jpeg->blocks == 1 ? 0 : 1,) store_row_jpeg, + p_jpeg)) + return bm_size; + } else { + int row; + struct scaler_context ctx = { + .bm = bm, + .dither = dither, + }; +#if LCD_DEPTH > 1 + void (*output_row_8)(uint32_t, void*, struct scaler_context*) = + output_row_8_native; +#elif defined(PLUGIN) + void (*output_row_8)(uint32_t, void*, struct scaler_context*) = NULL; +#endif +#if LCD_DEPTH > 1 || defined(PLUGIN) + if (cformat) + output_row_8 = cformat->output_row_8; +#endif + struct img_part *part; + for (row = 0; row < bm->height; row++) + { + part = store_row_jpeg(p_jpeg); +#ifdef HAVE_LCD_COLOR + struct uint8_rgb *qp = part->buf; + struct uint8_rgb *end = qp + bm->width; + uint8_t y, u, v; + unsigned r, g, b; + for (; qp < end; qp++) + { + y = qp->blue; + u = qp->green; + v = qp->red; + yuv_to_rgb(y, u, v, &r, &g, &b); + qp->red = r; + qp->blue = b; + qp->green = g; + } +#endif + output_row_8(row, part->buf, &ctx); + } return bm_size; - else - return 0; + } + return 0; } /**************** end JPEG code ********************/ diff --git a/apps/recorder/resize.c b/apps/recorder/resize.c index 5ecb5c24cf..1e9210e819 100644 --- a/apps/recorder/resize.c +++ b/apps/recorder/resize.c @@ -518,7 +518,7 @@ static inline bool scale_v_linear(struct rowset *rset, #endif /* HAVE_UPSCALER */ #if defined(HAVE_LCD_COLOR) && (defined(HAVE_JPEG) || defined(PLUGIN)) -void output_row_native_fromyuv(uint32_t row, void * row_in, +static void output_row_32_native_fromyuv(uint32_t row, void * row_in, struct scaler_context *ctx) { int col; @@ -547,7 +547,7 @@ void output_row_native_fromyuv(uint32_t row, void * row_in, #endif #if !defined(PLUGIN) || LCD_DEPTH > 1 -void output_row_native(uint32_t row, void * row_in, +static void output_row_32_native(uint32_t row, void * row_in, struct scaler_context *ctx) { int col; @@ -644,13 +644,14 @@ unsigned int get_size_native(struct bitmap *bm) } const struct custom_format format_native = { + .output_row_8 = output_row_8_native, #if defined(HAVE_LCD_COLOR) && (defined(HAVE_JPEG) || defined(PLUGIN)) - .output_row = { - output_row_native, - output_row_native_fromyuv + .output_row_32 = { + output_row_32_native, + output_row_32_native_fromyuv }, #else - .output_row = output_row_native, + .output_row_32 = output_row_32_native, #endif .get_size = get_size_native }; @@ -722,17 +723,17 @@ int resize_on_load(struct bitmap *bm, bool dither, struct dim *src, ctx.dither = dither; #if !defined(PLUGIN) #if defined(HAVE_LCD_COLOR) && defined(HAVE_JPEG) - ctx.output_row = format_index ? output_row_native_fromyuv - : output_row_native; + ctx.output_row = format_index ? output_row_32_native_fromyuv + : output_row_32_native; #else - ctx.output_row = output_row_native; + ctx.output_row = output_row_32_native; #endif if (format) #endif #if defined(HAVE_LCD_COLOR) && (defined(HAVE_JPEG) || defined(PLUGIN)) - ctx.output_row = format->output_row[format_index]; + ctx.output_row = format->output_row_32[format_index]; #else - ctx.output_row = format->output_row; + ctx.output_row = format->output_row_32; #endif #ifdef HAVE_UPSCALER if (sw > dw) diff --git a/apps/recorder/resize.h b/apps/recorder/resize.h index f7cda15254..2964fcd2a9 100644 --- a/apps/recorder/resize.h +++ b/apps/recorder/resize.h @@ -150,19 +150,17 @@ struct scaler_context { #endif struct custom_format { + void (*output_row_8)(uint32_t,void*, struct scaler_context*); #if defined(HAVE_LCD_COLOR) - void (*output_row[2])(uint32_t,void*,struct scaler_context*); + void (*output_row_32[2])(uint32_t,void*, struct scaler_context*); #else - void (*output_row)(uint32_t,void*,struct scaler_context*); + void (*output_row_32)(uint32_t,void*, struct scaler_context*); #endif unsigned int (*get_size)(struct bitmap *bm); }; struct rowset; -void output_row_native(uint32_t row, void * row_in, - struct scaler_context *ctx); - extern const struct custom_format format_native; int recalc_dimension(struct dim *dst, struct dim *src); -- cgit v1.2.3