diff --git a/apps/plugin.h b/apps/plugin.h index e91c866..ce738b0 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -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" diff --git a/apps/plugins/sliding_puzzle.c b/apps/plugins/sliding_puzzle.c index 85f4d32..941290f 100644 --- a/apps/plugins/sliding_puzzle.c +++ b/apps/plugins/sliding_puzzle.c @@ -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)] -__attribute__ ((aligned(16))); -#endif +static unsigned char img_buf + [BM_SCALED_SIZE(IMAGE_WIDTH,IMAGE_HEIGHT,FORMAT_NATIVE,0)] + __attribute__ ((aligned(16))); #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; @@ -627,13 +618,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 */ diff --git a/apps/recorder/bmp.c b/apps/recorder/bmp.c index cdff8cc..282aafc 100644 --- a/apps/recorder/bmp.c +++ b/apps/recorder/bmp.c @@ -194,7 +194,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 +222,13 @@ 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); 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 +239,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]; - data <<= 1; + data = *ibuf++; + 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 +280,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,9 +290,9 @@ static unsigned int read_part_line(struct bmp_args *ba) buf->red = *ibuf++; if (depth == 32) ibuf++; + buf++; break; } - buf++; } #if LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1) @@ -406,10 +407,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 +420,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 +467,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 +490,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 +501,8 @@ int read_bmp_fd(int fd, } } + format &= 1; + if (!(resize & IMG_RESIZE)) { #endif /* returning image size */ @@ -524,7 +521,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) { @@ -626,13 +623,11 @@ int read_bmp_fd(int fd, if (format == FORMAT_NATIVE) #endif return resize_on_load(bm, dither, &src_dim, &rset, remote, -#ifdef HAVE_LCD_COLOR bitmap + totalsize, maxsize - totalsize, -#endif store_part_bmp, skip_lines_bmp, &ba); #endif /* LCD_DEPTH */ - int fb_width = get_fb_width(bm, remote); + int fb_width = BM_WIDTH(bm->width,bm->format,remote); int col, row; /* loop to read rows and put them to buffer */ @@ -663,7 +658,7 @@ int read_bmp_fd(int fd, for (col = 0; col < src_dim.width; col++) { if (dither) - delta = dither_mat(row & 0xf, col & 0xf); + delta = dither_matrix[row & 0xf][col & 0xf]; if (!len) { if(!(len = read_part_line(&ba))) diff --git a/apps/recorder/bmp.h b/apps/recorder/bmp.h index d1b1d7f..cab1f6b 100644 --- a/apps/recorder/bmp.h +++ b/apps/recorder/bmp.h @@ -33,9 +33,9 @@ #define IMG_NORESIZE 0 #define IMG_RESIZE 1 #if LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1) -#define MAX_WIDTH 8 +#define BM_MAX_WIDTH 8 #else -#define MAX_WIDTH LCD_WIDTH +#define BM_MAX_WIDTH (((LCD_WIDTH) + 7) >> 3) #endif struct uint8_rgb { @@ -57,128 +57,114 @@ 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]; -} #endif 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 +#ifdef ROCKBOX_HQ_GREY + return (77 * (unsigned)color.red + 150 * (unsigned)color.green + + 29 * (unsigned)color.blue) / 256; +#else + return (5 * (unsigned)color.red + 9 * (unsigned)color.green + + 2 * (unsigned)color.blue) / 16; +#endif +#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; +#define MONO_BM_HEIGHT(height) (((height) + 7) >> 3) + +#if LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1) +#if LCD_DEPTH == 1 || \ + (LCD_DEPTH == 2 && LCD_PIXELFORMAT == VERTICAL_INTERLEAVED) +#define 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 - int dst_height; -#if !defined(HAVE_REMOTE_LCD) || \ - (defined(HAVE_REMOTE_LCD) &&(LCD_REMOTE_DEPTH == 1)) - (void) remote; +#ifdef HAVE_REMOTE_LCD +#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 +#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 -#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; -} +#define MONO_BM_WIDTH(width) (width) -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; +#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 - int dst_width; -#if !defined(HAVE_REMOTE_LCD) || \ - (defined(HAVE_REMOTE_LCD) &&(LCD_REMOTE_DEPTH == 1)) - (void) remote; +#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 -#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; -} +#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 -static inline int get_totalsize(struct bitmap *bm, bool remote) -{ - int sz; -#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); +#define MONO_BM_SIZE(width,height) (MONO_BM_WIDTH(width) * \ + MONO_BM_HEIGHT(height) * FB_DATA_SZ) +#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 +#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 - return get_fb_width(bm, remote) * get_fb_height(bm, remote) * sz; -} +#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) * 24 + 3)) +#else +#define BM_SCALED_SIZE BM_SIZE +#endif /********************************************************************* * read_bmp_file() diff --git a/apps/recorder/resize.c b/apps/recorder/resize.c index e415010..762b3cb 100644 --- a/apps/recorder/resize.c +++ b/apps/recorder/resize.c @@ -91,8 +91,7 @@ struct uint32_rgb { }; struct scaler_context { - uint32_t divmul; - uint32_t round; + uint32_t divisor; struct img_part* (*store_part)(void *); long last_tick; unsigned char *buf; @@ -106,8 +105,7 @@ static void scale_h_area_setup(struct bitmap *bm, struct dim *src, { (void) bm; /* sum is output value * src->width */ - ctx->divmul = ((src->width - 1 + 0x80000000U) / src->width) << 1; - ctx->round = (src->width + 1) >> 1; + ctx->divisor = src->width; } /* horizontal area average scaler */ @@ -157,15 +155,15 @@ static bool scale_h_area(struct bitmap *bm, struct dim *src, rgbvalacc.g += rgbvaltmp.g * mul; rgbvalacc.b += rgbvaltmp.b * mul; /* round, divide, and either store or accumulate to output row */ - out_line[ox].r = (accum ? out_line[ox].r : 0) + - ((rgbvalacc.r + ctx->round) * - (uint64_t)ctx->divmul >> 32); - out_line[ox].g = (accum ? out_line[ox].g : 0) + - ((rgbvalacc.g + ctx->round) * - (uint64_t)ctx->divmul >> 32); - out_line[ox].b = (accum ? out_line[ox].b : 0) + - ((rgbvalacc.b + ctx->round) * - (uint64_t)ctx->divmul >> 32); + if (accum) + { + rgbvalacc.r += out_line[ox].r; + rgbvalacc.g += out_line[ox].g; + rgbvalacc.b += out_line[ox].b; + } + out_line[ox].r = rgbvalacc.r; + out_line[ox].g = rgbvalacc.g; + out_line[ox].b = rgbvalacc.b; /* reset accumulator */ rgbvalacc.r = 0; rgbvalacc.g = 0; @@ -195,13 +193,14 @@ static bool scale_v_area(struct bitmap *bm, bool dither, struct dim *src, struct scaler_context*, bool), struct scaler_context *ctx) { - uint32_t mul, divmul, x, oy, iy, oye, round; + uint32_t mul, recip, divisor, x, oy, iy, oye, round; int delta = 127, r, g, b; fb_data *row, *pix; /* Set up rounding and scale factors */ - divmul = ((src->height - 1 + 0x80000000U) / src->height) << 1; - round = (src->height + 1) >> 1; + divisor = ctx->divisor * src->height; + recip = ((divisor - 1 + 0x80000000U) / divisor) << 1; + round = divisor >> 1; mul = 0; oy = 0; oye = 0; @@ -239,14 +238,14 @@ static bool scale_v_area(struct bitmap *bm, bool dither, struct dim *src, ((uint32_t*)rowacc)[x] += mul * ((uint32_t*)rowtmp)[x]; ((uint32_t*)rowacc)[x] = (round + ((uint32_t*)rowacc)[x]) * - (uint64_t)divmul >> 32; + (uint64_t)recip >> 32; } /* convert to RGB565 in output bitmap */ pix = row; for (x = 0; x < (unsigned int)bm->width; x++) { if (dither) - delta = dither_mat(x & 0xf, oy & 0xf); + delta = dither_matrix[x & 0xf][oy & 0xf]; r = PACKRB(rowacc[x].r,delta); g = PACKG(rowacc[x].g,delta); b = PACKRB(rowacc[x].b,delta); @@ -276,8 +275,7 @@ static void scale_h_linear_setup(struct bitmap *bm, struct dim *src, struct scaler_context *ctx) { (void) src; - ctx->divmul = ((bm->width - 2 + 0x80000000U) / (bm->width - 1)) << 1; - ctx->round = bm->width >> 1; + ctx->divisor = bm->width - 1; } /* horizontal linear scaler */ @@ -339,15 +337,16 @@ static bool scale_h_linear(struct bitmap *bm, struct dim *src, rgbinc.b *= src->width - 1; } /* round and scale values, and accumulate or store to output */ - out_line[ox].r = (accum ? out_line[ox].r : 0) + - ((rgbval.r + ctx->round) * - (uint64_t)ctx->divmul >> 32); - out_line[ox].g = (accum ? out_line[ox].g : 0) + - ((rgbval.g + ctx->round) * - (uint64_t)ctx->divmul >> 32); - out_line[ox].b = (accum ? out_line[ox].b : 0) + - ((rgbval.b + ctx->round) * - (uint64_t)ctx->divmul >> 32); + if (accum) + { + out_line[ox].r += rgbval.r; + out_line[ox].g += rgbval.g; + out_line[ox].b += rgbval.b; + } else { + out_line[ox].r = rgbval.r; + out_line[ox].g = rgbval.g; + out_line[ox].b = rgbval.b; + } rgbval.r += rgbinc.r; rgbval.g += rgbinc.g; rgbval.b += rgbinc.b; @@ -364,13 +363,14 @@ static bool scale_v_linear(struct bitmap *bm, bool dither, struct dim *src, struct scaler_context*, bool), struct scaler_context *ctx) { - uint32_t mul, divmul, x, oy, iy, iye, round; + uint32_t mul, recip, divisor, x, oy, iy, iye, round; int delta = 127; struct uint32_rgb p; fb_data *row, *pix; /* Set up scale and rounding factors, the divisor is bm->height - 1 */ - divmul = ((bm->height - 2 + 0x80000000U) / (bm->height - 1)) << 1; - round = bm->height >> 1; + divisor = ctx->divisor * (bm->height - 1); + recip = ((divisor - 1 + 0x80000000U) / divisor) << 1; + round = divisor >> 1; mul = 0; iy = 0; iye = bm->height - 1; @@ -410,14 +410,14 @@ static bool scale_v_linear(struct bitmap *bm, bool dither, struct dim *src, scale it. */ p.r = (crow1[x].r * (bm->height - 1 - iye) + - crow2[x].r * iye + round) * (uint64_t)divmul >> 32; + crow2[x].r * iye + round) * (uint64_t)recip >> 32; p.g = (crow1[x].g * (bm->height - 1 - iye) + - crow2[x].g * iye + round) * (uint64_t)divmul >> 32; + crow2[x].g * iye + round) * (uint64_t)recip >> 32; p.b = (crow1[x].b * (bm->height - 1 - iye) + - crow2[x].b * iye + round) * (uint64_t)divmul >> 32; + crow2[x].b * iye + round) * (uint64_t)recip >> 32; /* dither and pack pixels to output */ if (dither) - delta = dither_mat(x & 0xf, oy & 0xf); + delta = dither_matrix[x & 0xf][oy & 0xf]; p.r = PACKRB(p.r,delta); p.g = PACKG(p.g,delta); p.b = PACKRB(p.b,delta); @@ -431,10 +431,12 @@ static bool scale_v_linear(struct bitmap *bm, bool dither, struct dim *src, #endif /* HAVE_UPSCALER */ #endif /* HAVE_LCD_COLOR */ -/* docs for this are still TODO, but it's Bresenham's again, used to skip or - repeat input pixels, and with the *ls values being used for "long steps" - that skip all the way, or nearly all the way, to the next transition of - the associated value. +/* This is a slightly different Bresenham's than used above. The error + and the index are stepped in the output space, until one bound for the + error is reached, and then in the input space until the other bound is + reached. "Long step" values are precalculated that allow either of these + values to be stepped enough times to reach the error bound, or one step + short of it. */ #if LCD_DEPTH < 8 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH < 8) /* nearest-neighbor up/down/non-scaler */ @@ -454,7 +456,7 @@ static inline bool scale_nearest(struct bitmap *bm, const int rowstep = rset->rowstep; const int rowstart = rset->rowstart; const int rowstop = rset->rowstop; - const int fb_width = get_fb_width(bm, false); + const int fb_width = BM_WIDTH(dw,bm->format,false); long last_tick = current_tick; /* yet/oyt will always be initialized before use, since they are set in the inside loop, and not used elsewhere until the end of the outside loop. @@ -474,6 +476,12 @@ static inline bool scale_nearest(struct bitmap *bm, ly = 0; iy = 0; ye = 0; + /* Set up long step values. X can't long step on output, since it has to + iterate over each output pixel anyway. Y is a little bit different, + to avoid caching an entire line of data an extra inner loop iterates + each line in the output image until a new input line is reached, + and then the outer loop uses long steps for input rows and output rows. + */ xelim = sw == dw - 1 ? dw : dw - 1; ixls = xelim ? sw / xelim : 1; xels = sw - ixls * (xelim ? xelim : 1); @@ -483,6 +491,9 @@ static inline bool scale_nearest(struct bitmap *bm, int delta = 127; #if LCD_PIXELFORMAT == HORIZONTAL_PACKING || \ (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_PIXELFORMAT == HORIZONTAL_PACKING) + /* Four pixels of output data are collected before stepping through the + next set of lines, so that each byte of output can be written just once. + */ uint8_t buf[4]; int data, oxt; #endif @@ -491,6 +502,9 @@ static inline bool scale_nearest(struct bitmap *bm, (defined(HAVE_REMOTE_LCD) && \ (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED || \ LCD_REMOTE_PIXELFORMAT == VERTICAL_PACKING)) + /* The other cases are packed differently, and the collect-then-store + method won't work for them. + */ int bright, shift; #endif for (oy = rowstart; oy != rowstop;) { @@ -500,6 +514,7 @@ static inline bool scale_nearest(struct bitmap *bm, yield(); last_tick = current_tick; } + /* skip rows until row iy is reached */ if (iy > ly && !skip_lines(args, iy - ly - 1)) return false; ly = iy; @@ -517,9 +532,12 @@ static inline bool scale_nearest(struct bitmap *bm, (void)remote; #endif #if LCD_PIXELFORMAT == HORIZONTAL_PACKING + /* one row of image for each row of data */ dest = (fb_data *)bitmap + fb_width * oy; #elif LCD_PIXELFORMAT == VERTICAL_PACKING + /* four rows of image for each row of data */ dest = (fb_data *)bitmap + fb_width * (oy >> 2); + /* eight rows of image for each row of data */ #elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED dest = (fb_data *)bitmap + fb_width * (oy >> 3); #endif @@ -527,9 +545,13 @@ static inline bool scale_nearest(struct bitmap *bm, #ifndef HAVE_LCD_COLOR else #endif + /* All remotes currently supported use store eight rows of + image per row of data. + */ rdest = (fb_remote_data *)bitmap + fb_width * (oy >> 3); #endif for (ox = 0; ox < dw; ox++) { + /* get new image parts until the ix is reached */ while (cur_part->len <= ix - lx) { lx += cur_part->len; @@ -559,7 +581,7 @@ static inline bool scale_nearest(struct bitmap *bm, for (oxt = 0; oxt < (ox & 3) + 1; oxt++) { if (dither) - delta = dither_mat(oyt & 0xf, (xo + oxt) & 0xf); + delta = dither_matrix[oyt & 0xf][(xo + oxt) & 0xf]; p = (3 * buf[oxt] + (buf[oxt] >> 6) + delta) >> 8; data |= (~p & 3) << ((3 - oxt) << 1); } @@ -579,7 +601,7 @@ static inline bool scale_nearest(struct bitmap *bm, { shift = (oyt & 3) << 1; if (dither) - delta = dither_mat(oyt & 0xf, ox & 0xf); + delta = dither_matrix[oyt & 0xf][ox & 0xf]; p = (3 * bright + (bright >> 6) + delta) >> 8; *dest_t |= (~p & 3) << shift; @@ -597,10 +619,10 @@ static inline bool scale_nearest(struct bitmap *bm, { shift = oyt & 7; if (dither) - delta = dither_mat(oyt & 0xf, ox & 0xf); + delta = dither_matrix[oyt & 0xf][ox & 0xf]; p = (3 * bright + (bright >> 6) + delta) >> 8; - *dest_t |= vi_pat(p) << shift; + *dest_t |= vi_pattern[p] << shift; if ((rowstep > 0 && shift == 7) || shift == 0) dest_t += rowstep * fb_width; yet += sh; @@ -621,10 +643,10 @@ static inline bool scale_nearest(struct bitmap *bm, { shift = oyt & 7; if (dither) - delta = dither_mat(oyt & 0xf, ox & 0xf); + delta = dither_matrix[oyt & 0xf][ox & 0xf]; p = (3 * bright + (bright >> 6) + delta) >> 8; - *rdest_t |= vi_pat(p) << shift; + *rdest_t |= vi_pattern[p] << shift; if ((rowstep > 0 && shift == 7) || shift == 0) rdest_t += rowstep * fb_width; yet += sh; @@ -639,7 +661,7 @@ static inline bool scale_nearest(struct bitmap *bm, { shift = oyt & 7; if (dither) - delta = dither_mat(oyt & 0xf, ox & 0xf); + delta = dither_matrix[oyt & 0xf][ox & 0xf]; p = (bright + delta) >> 8; *rdest_t |= (~p & 1) << shift; if ((rowstep > 0 && shift == 7) || shift == 0) @@ -650,8 +672,10 @@ static inline bool scale_nearest(struct bitmap *bm, #endif } #endif + /* long-step ix */ xe += xels; ix += ixls; + /* single-step until boundary is reached */ while (xe > xelim) { xe -= xelim; @@ -661,6 +685,7 @@ static inline bool scale_nearest(struct bitmap *bm, oy = oyt; ye = yet - yels; iy += iyls; + /* single-step until boundary is reached */ while (ye > yelim) { ye -= yelim; @@ -673,17 +698,22 @@ static inline bool scale_nearest(struct bitmap *bm, int resize_on_load(struct bitmap *bm, bool dither, struct dim *src, struct rowset *rset, bool remote, -#ifdef HAVE_LCD_COLOR unsigned char *buf, unsigned int len, -#endif struct img_part* (*store_part)(void *args), bool (*skip_lines)(void *args, unsigned int lines), void *args) { +#ifndef HAVE_LCD_COLOR + (void) buf; + (void)len; +#endif #if defined(HAVE_LCD_COLOR) && !defined(HAVE_REMOTE_LCD) (void)skip_lines; #endif +#ifndef HAVE_REMOTE_LCD + (void)remote; +#endif #ifdef HAVE_LCD_COLOR #ifdef HAVE_REMOTE_LCD if (!remote) @@ -777,5 +807,5 @@ int resize_on_load(struct bitmap *bm, bool dither, struct dim *src, return 0; } #endif /* !HAVE_LCD_COLOR || HAVE_REMOTE_LCD*/ - return get_totalsize(bm, remote); + return BM_SIZE(bm->width,bm->height,bm->format,remote); } diff --git a/apps/recorder/resize.h b/apps/recorder/resize.h index 8a39db5..cd7f1d3 100644 --- a/apps/recorder/resize.h +++ b/apps/recorder/resize.h @@ -51,9 +51,7 @@ struct img_part { 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, -#endif struct img_part* (*store_part)(void *args), bool (*skip_lines)(void *args, unsigned int lines), void *args); diff --git a/firmware/export/lcd-remote.h b/firmware/export/lcd-remote.h index 3c013d6..01df5a7 100644 --- a/firmware/export/lcd-remote.h +++ b/firmware/export/lcd-remote.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 */ diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h index ea5851e..e435d17 100644 --- a/firmware/export/lcd.h +++ b/firmware/export/lcd.h @@ -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 */