From eef7945a970e4da69b95c638a44a8ee1a9205430 Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Wed, 6 May 2009 04:53:56 +0000 Subject: [PATCH] Move YUV->RGB in JPEG load from before scaler to after scaler. Required change to struct custom_format, so sorted the plugin API as well. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20856 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugin.c | 30 +++++++++------------- apps/plugin.h | 45 ++++++++++++++------------------ apps/plugins/jpeg/yuv2rgb.c | 7 ----- apps/plugins/pictureflow.c | 30 ++++++++++++++++++++++ apps/recorder/bmp.c | 2 +- apps/recorder/jpeg_common.h | 51 +++++++++++++++++++++++++++++++++++++ apps/recorder/jpeg_load.c | 32 +++-------------------- apps/recorder/resize.c | 47 ++++++++++++++++++++++++++++++++++ apps/recorder/resize.h | 11 ++++++++ 9 files changed, 174 insertions(+), 81 deletions(-) diff --git a/apps/plugin.c b/apps/plugin.c index 2d996a404e..f079e849bd 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -135,11 +135,18 @@ static const struct plugin_api rockbox_api = { lcd_blit_mono, lcd_blit_grey_phase, #endif /* LCD_DEPTH */ +#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256) + lcd_blit_pal256, + lcd_pal256_update_pal, +#endif lcd_puts_style, lcd_puts_scroll_style, #ifdef HAVE_LCD_INVERT lcd_set_invert_display, #endif /* HAVE_LCD_INVERT */ +#if defined(HAVE_LCD_MODES) + lcd_set_mode, +#endif #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) lcd_activation_set_hook, &button_queue, @@ -571,6 +578,11 @@ static const struct plugin_api rockbox_api = { #endif #ifdef HAVE_LCD_BITMAP read_bmp_file, + read_bmp_fd, +#ifdef HAVE_JPEG + read_jpeg_file, + read_jpeg_fd, +#endif screen_dump_set_hook, #endif show_logo, @@ -632,24 +644,6 @@ static const struct plugin_api rockbox_api = { appsversion, /* new stuff at the end, sort into place next time the API gets incompatible */ - -#if defined(HAVE_LCD_MODES) - lcd_set_mode, -#endif - -#if defined(HAVE_LCD_MODES) -#if HAVE_LCD_MODES & LCD_MODE_PAL256 - lcd_blit_pal256, - lcd_pal256_update_pal, -#endif -#endif -#ifdef HAVE_LCD_BITMAP -#ifdef HAVE_JPEG - read_jpeg_file, - read_jpeg_fd, -#endif - read_bmp_fd, -#endif }; int plugin_load(const char* plugin, const void* parameter) diff --git a/apps/plugin.h b/apps/plugin.h index 72d71b6e93..d017d6394d 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -129,12 +129,12 @@ void* plugin_get_buffer(size_t *buffer_size); #define PLUGIN_MAGIC 0x526F634B /* RocK */ /* increase this every time the api struct changes */ -#define PLUGIN_API_VERSION 149 +#define PLUGIN_API_VERSION 150 /* update this to latest version if a change to the api struct breaks backwards compatibility (and please take the opportunity to sort in any new function which are "waiting" at the end of the function table) */ -#define PLUGIN_MIN_API_VERSION 147 +#define PLUGIN_MIN_API_VERSION 150 /* plugin return codes */ enum plugin_status { @@ -220,12 +220,20 @@ struct plugin_api { int bx, int by, int bwidth, int bheight, int stride); #endif /* LCD_DEPTH */ +#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256) + void (*lcd_blit_pal256)(unsigned char *src, int src_x, int src_y, int x, int y, + int width, int height); + void (*lcd_pal256_update_pal)(fb_data *palette); +#endif void (*lcd_puts_style)(int x, int y, const unsigned char *str, int style); void (*lcd_puts_scroll_style)(int x, int y, const unsigned char* string, int style); #ifdef HAVE_LCD_INVERT void (*lcd_set_invert_display)(bool yesno); #endif /* HAVE_LCD_INVERT */ +#if defined(HAVE_LCD_MODES) + void (*lcd_set_mode)(int mode); +#endif #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) void (*lcd_activation_set_hook)(void (*enable_hook)(void)); @@ -723,6 +731,14 @@ struct plugin_api { #ifdef HAVE_LCD_BITMAP int (*read_bmp_file)(const char* filename, struct bitmap *bm, int maxsize, int format, const struct custom_format *cformat); + int (*read_bmp_fd)(int fd, struct bitmap *bm, int maxsize, + int format, const struct custom_format *cformat); +#ifdef HAVE_JPEG + int (*read_jpeg_file)(const char* filename, struct bitmap *bm, int maxsize, + int format, const struct custom_format *cformat); + int (*read_jpeg_fd)(int fd, struct bitmap *bm, int maxsize, + int format, const struct custom_format *cformat); +#endif void (*screen_dump_set_hook)(void (*hook)(int fh)); #endif int (*show_logo)(void); @@ -788,32 +804,9 @@ struct plugin_api { void (*semaphore_release)(struct semaphore *s); #endif - const char *appsversion; + const char *appsversion; /* new stuff at the end, sort into place next time the API gets incompatible */ - -#if defined(HAVE_LCD_MODES) - void (*lcd_set_mode)(int mode); -#endif - -#if defined(HAVE_LCD_MODES) -#if HAVE_LCD_MODES & LCD_MODE_PAL256 - void (*lcd_blit_pal256)(unsigned char *src, int src_x, int src_y, int x, int y, - int width, int height); - void (*lcd_pal256_update_pal)(fb_data *palette); -#endif -#endif - -#ifdef HAVE_LCD_BITMAP -#ifdef HAVE_JPEG - int (*read_jpeg_file)(const char* filename, struct bitmap *bm, int maxsize, - int format, const struct custom_format *cformat); - int (*read_jpeg_fd)(int fd, struct bitmap *bm, int maxsize, - int format, const struct custom_format *cformat); -#endif - int (*read_bmp_fd)(int fd, struct bitmap *bm, int maxsize, - int format, const struct custom_format *cformat); -#endif }; /* plugin header */ diff --git a/apps/plugins/jpeg/yuv2rgb.c b/apps/plugins/jpeg/yuv2rgb.c index c2464924fe..ed88d5416a 100644 --- a/apps/plugins/jpeg/yuv2rgb.c +++ b/apps/plugins/jpeg/yuv2rgb.c @@ -48,13 +48,6 @@ #define COMPONENT_SHIFT 15 #define MATRIX_SHIFT 7 -static inline int clamp_component(int x) -{ - if ((unsigned)x > YUV_WHITE) - x = x < 0 ? 0 : YUV_WHITE; - return x; -} - static inline int clamp_component_bits(int x, int bits) { if ((unsigned)x > (1u << bits) - 1) diff --git a/apps/plugins/pictureflow.c b/apps/plugins/pictureflow.c index b78b953f13..7261d7a402 100644 --- a/apps/plugins/pictureflow.c +++ b/apps/plugins/pictureflow.c @@ -634,13 +634,43 @@ static void output_row_transposed(uint32_t row, void * row_in, #endif } +#ifdef HAVE_LCD_COLOR +static void output_row_transposed_fromyuv(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; + struct uint32_rgb *qp = (struct uint32_rgb*)row_in; + for (; dest < end; dest += ctx->bm->height) + { + unsigned r, g, b, y, u, v; + y = SC_MUL(qp->b + ctx->round, ctx->divisor); + u = SC_MUL(qp->g + ctx->round, ctx->divisor); + v = SC_MUL(qp->r + ctx->round, ctx->divisor); + qp++; + yuv_to_rgb(y, u, v, &r, &g, &b); + r = (31 * r + (r >> 3) + 127) >> 8; + g = (63 * g + (g >> 2) + 127) >> 8; + b = (31 * b + (b >> 3) + 127) >> 8; + *dest = LCD_RGBPACK_LCD(r, g, b); + } +} +#endif + static unsigned int get_size(struct bitmap *bm) { return bm->width * bm->height * sizeof(pix_t); } const struct custom_format format_transposed = { +#ifdef HAVE_LCD_COLOR + .output_row = { + output_row_transposed, + output_row_transposed_fromyuv + }, +#else .output_row = output_row_transposed, +#endif .get_size = get_size }; diff --git a/apps/recorder/bmp.c b/apps/recorder/bmp.c index 403c34d951..f1fc1f83b4 100644 --- a/apps/recorder/bmp.c +++ b/apps/recorder/bmp.c @@ -603,7 +603,7 @@ int read_bmp_fd(int fd, { if (resize_on_load(bm, dither, &src_dim, &rset, bitmap + totalsize, maxsize - totalsize, - cformat, store_part_bmp, &ba)) + cformat, IF_PIX_FMT(0,) store_part_bmp, &ba)) return totalsize; else return 0; diff --git a/apps/recorder/jpeg_common.h b/apps/recorder/jpeg_common.h index 44bf81e435..061cfc8e64 100644 --- a/apps/recorder/jpeg_common.h +++ b/apps/recorder/jpeg_common.h @@ -28,6 +28,8 @@ #ifndef _JPEG_COMMON_H #define _JPEG_COMMON_H +#include "bmp.h" + #define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ #define JPEG_READ_BUF_SIZE 16 struct derived_tbl @@ -51,6 +53,55 @@ struct derived_tbl #define QUANT_TABLE_LENGTH 64 +/* + * Conversion of full 0-255 range YCrCb to RGB: + * |R| |1.000000 -0.000001 1.402000| |Y'| + * |G| = |1.000000 -0.334136 -0.714136| |Pb| + * |B| |1.000000 1.772000 0.000000| |Pr| + * Scaled (yields s15-bit output): + * |R| |128 0 179| |Y | + * |G| = |128 -43 -91| |Cb - 128| + * |B| |128 227 0| |Cr - 128| + */ +#define YFAC 128 +#define RVFAC 179 +#define GUFAC (-43) +#define GVFAC (-91) +#define BUFAC 227 +#define COMPONENT_SHIFT 15 + +struct uint8_yuv { + uint8_t y; + uint8_t u; + uint8_t v; +}; + +union uint8_rgbyuv { + struct uint8_yuv yuv; + struct uint8_rgb rgb; +}; + +static inline int clamp_component(int x) +{ + if ((unsigned)x > 255) + x = x < 0 ? 0 : 255; + return x; +} +#include +static inline void yuv_to_rgb(int y, int u, int v, unsigned *r, unsigned *g, unsigned *b) +{ + int rv, guv, bu; + y = y * YFAC + (YFAC >> 1); + u = u - 128; + v = v - 128; + rv = RVFAC * v; + guv = GUFAC * u + GVFAC * v; + bu = BUFAC * u; + *r = clamp_component((y + rv) / YFAC); + *g = clamp_component((y + guv) / YFAC); + *b = clamp_component((y + bu) / YFAC); +} + /* for type of Huffman table */ #define DC_LEN 28 #define AC_LEN 178 diff --git a/apps/recorder/jpeg_load.c b/apps/recorder/jpeg_load.c index 8b2c3f2fef..14aa024fcf 100644 --- a/apps/recorder/jpeg_load.c +++ b/apps/recorder/jpeg_load.c @@ -153,13 +153,6 @@ INLINE unsigned range_limit(int value) #endif } -static inline int clamp_component(int x) -{ - if ((unsigned)x > 255) - x = x < 0 ? 0 : 255; - return x; -} - /* IDCT implementation */ @@ -1810,27 +1803,8 @@ static struct img_part *store_row_jpeg(void *jpeg_args) unsigned int xp; int yp; unsigned char *row = out; - if (p_jpeg->blocks > 1) { - for (yp = 0; yp < height; yp++, row += b_width) - { - unsigned char *px = row; - for (xp = 0; xp < 1U << p_jpeg->h_scale[1]; - xp++, px += JPEG_PIX_SZ) - { - int y, u, v, rv, guv, bu; - y = px[0] * YFAC + (YFAC >> 1); - u = px[1] - 128; - v = px[2] - 128; - rv = RVFAC * v; - guv = GUFAC * u + GVFAC * v; - bu = BUFAC * u; - struct uint8_rgb *rgb = (struct uint8_rgb *)px; - rgb->red = clamp_component((y + rv) / YFAC); - rgb->green = clamp_component((y + guv) / YFAC); - rgb->blue = clamp_component((y + bu) / YFAC); - } - } - } else { + if (p_jpeg->blocks == 1) + { for (yp = 0; yp < height; yp++, row += b_width) { unsigned char *px = row; @@ -2003,7 +1977,7 @@ int read_jpeg_fd(int fd, rset.rowstop = bm->height; rset.rowstep = 1; if (resize_on_load(bm, dither, &src_dim, &rset, buf_start, maxsize, cformat, - store_row_jpeg, p_jpeg)) + IF_PIX_FMT(p_jpeg->blocks == 1 ? 0 : 1,) store_row_jpeg, p_jpeg)) return bm_size; else return 0; diff --git a/apps/recorder/resize.c b/apps/recorder/resize.c index 7000c448e6..1852519958 100644 --- a/apps/recorder/resize.c +++ b/apps/recorder/resize.c @@ -59,6 +59,7 @@ #undef DEBUGF #define DEBUGF(...) #endif +#include #if CONFIG_CPU == SH7034 /* 16*16->32 bit multiplication is a single instrcution on the SH1 */ @@ -516,6 +517,35 @@ 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, + struct scaler_context *ctx) +{ + int col; + int fb_width = BM_WIDTH(ctx->bm->width,FORMAT_NATIVE,0); + uint8_t dy = DITHERY(row); + struct uint32_rgb *qp = (struct uint32_rgb *)row_in; + SDEBUGF("output_row: y: %lu in: %p\n",row, row_in); + fb_data *dest = (fb_data *)ctx->bm->data + fb_width * row; + int delta = 127; + unsigned r, g, b, y, u, v; + + for (col = 0; col < ctx->bm->width; col++) { + if (ctx->dither) + delta = DITHERXDY(col,dy); + y = SC_MUL(qp->b + ctx->round, ctx->divisor); + u = SC_MUL(qp->g + ctx->round, ctx->divisor); + v = SC_MUL(qp->r + ctx->round, ctx->divisor); + qp++; + yuv_to_rgb(y, u, v, &r, &g, &b); + 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 + #if !defined(PLUGIN) || LCD_DEPTH > 1 void output_row_native(uint32_t row, void * row_in, struct scaler_context *ctx) @@ -614,7 +644,14 @@ unsigned int get_size_native(struct bitmap *bm) } const struct custom_format format_native = { +#if defined(HAVE_LCD_COLOR) && (defined(HAVE_JPEG) || defined(PLUGIN)) + .output_row = { + output_row_native, + output_row_native_fromyuv + }, +#else .output_row = output_row_native, +#endif .get_size = get_size_native }; #endif @@ -622,6 +659,7 @@ const struct custom_format format_native = { int resize_on_load(struct bitmap *bm, bool dither, struct dim *src, struct rowset *rset, unsigned char *buf, unsigned int len, const struct custom_format *format, + IF_PIX_FMT(int format_index,) struct img_part* (*store_part)(void *args), void *args) { @@ -683,10 +721,19 @@ int resize_on_load(struct bitmap *bm, bool dither, struct dim *src, ctx.src = 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; +#else ctx.output_row = output_row_native; +#endif if (format) #endif +#if defined(HAVE_LCD_COLOR) && (defined(HAVE_JPEG) || defined(PLUGIN)) + ctx.output_row = format->output_row[format_index]; +#else ctx.output_row = format->output_row; +#endif #ifdef HAVE_UPSCALER if (sw > dw) { diff --git a/apps/recorder/resize.h b/apps/recorder/resize.h index de9e8a9ab0..f7cda15254 100644 --- a/apps/recorder/resize.h +++ b/apps/recorder/resize.h @@ -143,8 +143,18 @@ struct scaler_context { bool (*h_scaler)(void*,struct scaler_context*, bool); }; +#if defined(HAVE_LCD_COLOR) && (defined(HAVE_JPEG) || defined(PLUGIN)) +#define IF_PIX_FMT(...) __VA_ARGS__ +#else +#define IF_PIX_FMT(...) +#endif + struct custom_format { +#if defined(HAVE_LCD_COLOR) + void (*output_row[2])(uint32_t,void*,struct scaler_context*); +#else void (*output_row)(uint32_t,void*,struct scaler_context*); +#endif unsigned int (*get_size)(struct bitmap *bm); }; @@ -161,6 +171,7 @@ int resize_on_load(struct bitmap *bm, bool dither, struct dim *src, struct rowset *tmp_row, unsigned char *buf, unsigned int len, const struct custom_format *cformat, + IF_PIX_FMT(int format_index,) struct img_part* (*store_part)(void *args), void *args);