diff -u -r apps/buffering.c apps/buffering.c --- apps/buffering.c 2007-11-11 21:29:23.577500000 -0600 +++ apps/buffering.c 2007-11-12 00:05:03.374375000 -0600 @@ -49,6 +49,7 @@ #include "pcmbuf.h" #include "buffer.h" #include "bmp.h" +#include "gwps.h" #ifdef SIMULATOR #define ata_disk_is_active() 1 @@ -840,7 +841,10 @@ #endif int free = (int)MIN(buffer_len - BUF_USED, buffer_len - buf_widx); - rc = read_bmp_fd(fd, bmp, free, FORMAT_ANY|FORMAT_DITHER); + rc = read_bmp_fd(fd, bmp, free, FORMAT_ANY|FORMAT_DITHER, + gui_wps->data->albumart_max_width, + gui_wps->data->albumart_max_height, + BMP_RESIZE_INCREASE | BMP_RESIZE_DECREASE); return rc + (rc > 0 ? sizeof(struct bitmap) : 0); } #endif diff -u -r apps/gui/backdrop.c apps/gui/backdrop.c --- apps/gui/backdrop.c 2007-10-28 17:01:38.671875000 -0500 +++ apps/gui/backdrop.c 2007-11-12 00:04:08.530625000 -0600 @@ -50,7 +50,9 @@ /* load the image */ bm.data=(char*)backdrop_buffer; ret = read_bmp_file(filename, &bm, sizeof(main_backdrop), - FORMAT_NATIVE | FORMAT_DITHER); + FORMAT_NATIVE | FORMAT_DITHER, + LCD_WIDTH, LCD_HEIGHT, + BMP_RESIZE_INCREASE | BMP_RESIZE_DECREASE); if ((ret > 0) && (bm.width == LCD_WIDTH) && (bm.height == LCD_HEIGHT)) { @@ -112,7 +114,9 @@ /* load the image */ bm.data=(char*)backdrop_buffer; ret = read_bmp_file(filename, &bm, sizeof(main_backdrop), - FORMAT_NATIVE | FORMAT_DITHER | FORMAT_REMOTE); + FORMAT_NATIVE | FORMAT_DITHER | FORMAT_REMOTE, + LCD_WIDTH, LCD_HEIGHT, + BMP_RESIZE_INCREASE | BMP_RESIZE_DECREASE); if ((ret > 0) && (bm.width == LCD_REMOTE_WIDTH) && (bm.height == LCD_REMOTE_HEIGHT)) { diff -u -r apps/gui/icon.c apps/gui/icon.c --- apps/gui/icon.c 2007-10-28 17:01:38.718750000 -0500 +++ apps/gui/icon.c 2007-11-12 00:04:08.546250000 -0600 @@ -220,7 +220,9 @@ char path[MAX_PATH]; snprintf(path, sizeof(path), "%s/%s.bmp", ICON_DIR, filename); - size_read = read_bmp_file(path, bmp, IMG_BUFSIZE, bmpformat); + size_read = read_bmp_file(path, bmp, IMG_BUFSIZE, bmpformat, + 0, 0, + BMP_RESIZE_NONE); if (size_read > 0) { *loaded_ok = true; diff -u -r apps/gui/wps_parser.c apps/gui/wps_parser.c --- apps/gui/wps_parser.c 2007-11-12 00:06:17.358750000 -0600 +++ apps/gui/wps_parser.c 2007-11-12 00:04:08.577500000 -0600 @@ -372,7 +372,9 @@ int ret = read_bmp_file(filename, bm, wps_data->img_buf_free, - format); + format, + 0,0, + BMP_RESIZE_NONE); if (ret > 0) { diff -u -r apps/plugin.h apps/plugin.h --- apps/plugin.h 2007-11-12 00:06:17.452500000 -0600 +++ apps/plugin.h 2007-11-12 00:04:08.593125000 -0600 @@ -604,7 +604,10 @@ #endif #ifdef HAVE_LCD_BITMAP int (*read_bmp_file)(const char* filename, struct bitmap *bm, int maxsize, - int format); + int format, + int dst_maxwidth, /* =0 */ + int dst_maxheight,/* =0 */ + int flags); /* =BMP_RESIZE_NONE */ void (*screen_dump_set_hook)(void (*hook)(int fh)); #endif int (*show_logo)(void); diff -u -r apps/plugins/lib/bmp.h apps/plugins/lib/bmp.h --- apps/plugins/lib/bmp.h 2007-10-28 17:01:08.265625000 -0500 +++ apps/plugins/lib/bmp.h 2007-11-12 00:04:08.608750000 -0600 @@ -21,6 +21,7 @@ #include "lcd.h" #include "plugin.h" +#include "recorder/bmp.h" /** * Save bitmap to file diff -u -r apps/plugins/rockpaint.c apps/plugins/rockpaint.c --- apps/plugins/rockpaint.c 2007-10-28 17:01:33.078125000 -0500 +++ apps/plugins/rockpaint.c 2007-11-12 00:04:08.624375000 -0600 @@ -2916,7 +2916,9 @@ bm.data = (char*)save_buffer; ret = rb->read_bmp_file( file, &bm, ROWS*COLS*sizeof( fb_data ), - FORMAT_NATIVE ); + FORMAT_NATIVE, + COLS, ROWS, + BMP_RESIZE_INCREASE | BMP_RESIZE_DECREASE); if((bm.width > COLS ) || ( bm.height > ROWS )) return -1; diff -u -r apps/recorder/bmp.c apps/recorder/bmp.c --- apps/recorder/bmp.c 2007-11-10 18:54:43.390000000 -0600 +++ apps/recorder/bmp.c 2007-11-12 00:04:08.640000000 -0600 @@ -51,6 +51,7 @@ #pragma pack (push, 2) #endif +#define FACT_SCALE 1000 /* BMP header structure */ struct bmp_header { uint16_t type; /* signature - 'BM' */ @@ -81,6 +82,12 @@ uint32_t raw; }; +/* maximum bitmap width which can be read: */ +#define MAX_WIDTH 1280 +/* Buffer for one line */ +//static uint32_t bmpbuf[MAX_WIDTH]; +static union rgb_union bmpbuf[MAX_WIDTH]; + /* masks for supported BI_BITFIELDS encodings (16/32 bit), little endian */ static const unsigned char bitfields[3][12] = { { 0x00,0x7c,0x00,0, 0xe0,0x03,0x00,0, 0x1f,0x00,0x00,0 }, /* 15 bit */ @@ -137,59 +144,104 @@ + (unsigned)color.blue) / 10; } -/****************************************************************************** - * read_bmp_file() - * - * Reads a BMP file and puts the data in rockbox format in *bitmap. - * - *****************************************************************************/ -int read_bmp_file(const char* filename, - struct bitmap *bm, - int maxsize, - int format) + +static void set_pixel(int format, + unsigned char *bitmap, + bool dither, + union rgb_union color, + int dst_padded_width, + int dst_x, + int dst_y) { - int fd, ret; - fd = open(filename, O_RDONLY); +#if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 + bool remote = format & FORMAT_REMOTE; + format &= ~FORMAT_REMOTE; +#endif - /* Exit if file opening failed */ - if (fd < 0) { - DEBUGF("read_bmp_file: can't open '%s', rc: %d\n", filename, fd); - return fd * 10 - 1; +#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) + int delta = (dither)?dither_matrix[dst_y & 0xf][dst_x & 0xf]:127; + unsigned bright = brightness(color); + bright = (3 * bright + (bright >> 6) + delta) >> 8; + ((fb_remote_data *)bitmap)[dst_padded_width*(dst_y >> 3)+dst_x] |= + remote_pattern[bright] << (dst_y & 7); +# endif /* LCD_REMOTE_DEPTH / LCD_REMOTE_PIXELFORMAT */ + } + else +# endif /* defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 */ + { + int delta = (dither)?dither_matrix[dst_y & 0xf][dst_x & 0xf]:127; +# if LCD_DEPTH == 2 + unsigned bright = brightness(color); + bright = (3 * bright + (bright >> 6) + delta) >> 8; +# if LCD_PIXELFORMAT == VERTICAL_PACKING + /* iriver H1x0 */ + ((fb_data *)bitmap)[dst_padded_width * (dst_y >> 2)+dst_x] |= + (~bright & 3) << (2 * (dst_y & 3)); +# else /* LCD_PIXELFORMAT == HORIZONTAL_PACKING */ + /* greyscale iPods */ + ((fb_data *)bitmap)[dst_padded_width * dst_y + (dst_x >> 2)] |= + (~bright & 3) << (6 - 2 * (dst_x & 3)); +# endif /* LCD_PIXELFORMAT */ +# elif LCD_DEPTH == 16 + /* iriver h300, colour iPods, X5 */ + unsigned r = (31 * color.red + (color.red >> 3) + delta) >> 8; + unsigned g = (63 * color.green + (color.green >> 2) + delta) >> 8; + unsigned b = (31 * color.blue + (color.blue >> 3) + delta) >> 8; + ((fb_data *)bitmap)[dst_padded_width * dst_y + dst_x] = + LCD_RGBPACK_LCD(r, g, b); +# endif /* LCD_DEPTH */ + } + } + else +#else /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */ + (void) format; + (void) dither; +#endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */ + { + if (brightness(color) < 128) + bitmap[dst_padded_width * (dst_y >> 3)+dst_x] |= 1 << (dst_y & 7); } - - ret = read_bmp_fd(fd, bm, maxsize, format); - close(fd); - return ret; } /****************************************************************************** - * read_bmp_fd() + * read_bmp_file() * - * Reads a BMP file in an open file descriptor and puts the data in rockbox - * format in *bitmap. + * Reads a BMP file and puts the data in rockbox format in *bitmap. * *****************************************************************************/ -int read_bmp_fd(int fd, - struct bitmap *bm, - int maxsize, - int format) +int read_bmp_fd( int fd, + struct bitmap *bm, + int maxsize, + int format, + int dst_maxwidth, + int dst_maxheight, + int flags) { struct bmp_header bmph; - int width, height, padded_width; - int dst_height, dst_width; + int src_w, src_h, src_padded_width; + int dst_w, dst_h, dst_padded_width, dst_padded_height; + int row, ret; + int fact_w = FACT_SCALE; + int fact_h = FACT_SCALE; + int top = 0,decrement_y = 0; + int left = 0,decrement_x = 0; int depth, numcolors, compression, totalsize; - int row, col, ret; int rowstart, rowstop, rowstep; unsigned char *bitmap = bm->data; - uint32_t bmpbuf[LCD_WIDTH]; /* Buffer for one line */ - uint32_t palette[256]; + union rgb_union palette[256]; + bool dither = false; #if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) bool transparent = false; - bool dither = false; #ifdef HAVE_REMOTE_LCD bool remote = false; - + if (format & FORMAT_REMOTE) { remote = true; #if LCD_REMOTE_DEPTH == 1 @@ -209,7 +261,7 @@ } #else - (void)format; + format = FORMAT_MONO; #endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */ /* read fileheader */ @@ -223,27 +275,131 @@ return -3; } - width = readlong(&bmph.width); - if (width > LCD_WIDTH) { - DEBUGF("read_bmp_fd: Bitmap too wide (%d pixels, max is %d)\n", - width, LCD_WIDTH); + /* check bitmap file signature */ + if (readshort(&bmph.type)!=0x4d42) { + DEBUGF("read_bmp_fd: wring signature."); + return -3; + } + /* read the source dimensions */ + src_w = readlong(&bmph.width); + src_h = readlong(&bmph.height); + + /* Exit if too wide */ + if (((flags & BMP_RESIZE_NONE)==0 && (src_w > MAX_WIDTH)) || + ((flags & BMP_RESIZE_NONE) && (src_w > LCD_WIDTH))) + { + DEBUGF("read_bmp_fd: Bitmap is too wide (%d pixels, max is %d)\n", + src_w, MAX_WIDTH); return -4; } - height = readlong(&bmph.height); - if (height < 0) { /* Top-down BMP file */ - height = -height; - rowstart = 0; - rowstop = height; - rowstep = 1; - } else { /* normal BMP */ - rowstart = height - 1; - rowstop = -1; - rowstep = -1; - } + /* Calculate resize factors and image size */ + if (dst_maxwidth<=0 || dst_maxheight<=0) + { + dst_w = src_w; + dst_h = src_h; + } + else + { + dst_w = dst_maxwidth; + dst_h = dst_maxheight; + if (flags & BMP_RESIZE_FILL) + { + int aspect_src = src_w*FACT_SCALE/src_h; + int aspect_dst = dst_maxwidth*FACT_SCALE/dst_maxheight; + if (aspect_dst >= aspect_src) /* adjust height */ + decrement_y = (dst_maxheight * aspect_dst / aspect_src) + - dst_maxheight; + else /* adjust width */ + decrement_x = (dst_maxwidth * aspect_src / aspect_dst) + - dst_maxwidth; + + if ((flags & BMP_RESIZE_INCREASE) == 0 && + (src_w < dst_w || src_h < dst_h)) + { + if ((decrement_x = (src_w-dst_w)) < 0) + decrement_x = 0; + if ((decrement_y = (src_h-dst_h)) < 0) + decrement_y = 0; + } + left = decrement_x / 2; + top = decrement_y / 2; + flags |= BMP_RESIZE_DECREASE; + } + if (flags & (BMP_RESIZE_DECREASE | BMP_RESIZE_INCREASE)) + { + int fact; + if (dst_w > 0) + { + fact = (src_w * FACT_SCALE) / (dst_w + decrement_x); + /* decrease allowed and increase allowed */ + if ((fact < FACT_SCALE && (flags & BMP_RESIZE_DECREASE)) || + (fact > FACT_SCALE && (flags & BMP_RESIZE_INCREASE))) + fact_w = fact; + } + + if (dst_h > 0) + { + fact = (src_h * FACT_SCALE) / (dst_h + decrement_y); + /* decrease allowed and increase allowed */ + if ((fact < FACT_SCALE && (flags & BMP_RESIZE_DECREASE)) || + (fact > FACT_SCALE && (flags & BMP_RESIZE_INCREASE))) + fact_h = fact; + } + + if ((flags & BMP_RESIZE_IGNORE_ASPECT)==0) + { + /* keep aspect ratio of source */ + if (fact_w < fact_h) + fact_w = fact_h; + else + fact_h = fact_w; + /* don't resize */ + if (fact_w <= 0 || fact_h <= 0) + fact_h = fact_w = FACT_SCALE; + } + while (true) + { + dst_w = ((src_w * FACT_SCALE) / fact_w) - decrement_x; + if (dst_w <= dst_maxwidth) + break; + fact_w++; + } + while (true) + { + dst_h = ((src_h * FACT_SCALE) / fact_h) - decrement_y; + if (dst_h <= dst_maxheight) + break; + fact_h++; + } + } + } + + /* returning image size */ + bm->width = dst_w; + bm->height = dst_h; + + DEBUGF("read_bmp_fd: src=%d/%d, dst=%d/%d max=%d/%d (fact=%d/%d)" + " dec=%d/%d\n", + src_w, src_h, + dst_w, dst_h, + dst_maxwidth, dst_maxheight, + fact_w, fact_h, + decrement_x,decrement_y); + + /* Exit if too big for screen */ + if ((flags & BMP_RESIZE_NONE)==0 && + (dst_w > LCD_WIDTH || dst_h > LCD_HEIGHT)) + { + DEBUGF("read_bmp_fd: error - Bitmap is too big" + " (%d x %d pixels, screen is %d x %d)\n", + dst_w, dst_h, LCD_WIDTH, LCD_HEIGHT); + return -5; + } + depth = readshort(&bmph.bit_count); - padded_width = ((width * depth + 31) >> 3) & ~3; /* 4-byte boundary aligned */ + src_padded_width = ((src_w * depth + 31) >> 3) & ~3; /* 4-byte boundary aligned */ #if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) if (format == FORMAT_ANY) { @@ -253,49 +409,44 @@ format = FORMAT_NATIVE; } bm->format = format; -#endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */ - /* returning image size */ - bm->width = width; - bm->height = height; - -#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 defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 if (remote) { -#if (LCD_REMOTE_DEPTH == 2) && (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED) - dst_width = width; - dst_height = (height + 7) >> 3; -#endif /* LCD_REMOTE_DEPTH / LCD_REMOTE_PIXELFORMAT */ - totalsize = dst_width * dst_height * sizeof(fb_remote_data); +# if (LCD_REMOTE_DEPTH == 2) && (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED) + dst_padded_width = dst_w; + dst_padded_height = (dst_h + 7) >> 3; +# endif /* LCD_REMOTE_DEPTH / LCD_REMOTE_PIXELFORMAT */ + totalsize = dst_padded_width * dst_padded_height * sizeof(fb_remote_data); } else -#endif /* defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 */ +# endif /* defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 */ { -#if LCD_DEPTH == 2 -#if LCD_PIXELFORMAT == VERTICAL_PACKING - dst_width = width; - dst_height = (height + 3) >> 2; -#else /* LCD_PIXELFORMAT == HORIZONTAL_PACKING */ - dst_width = (width + 3) >> 2; - dst_height = height; -#endif /* LCD_PIXELFORMAT */ -#elif LCD_DEPTH == 16 - dst_width = width; - dst_height = height; -#endif /* LCD_DEPTH */ - totalsize = dst_width * dst_height * sizeof(fb_data); +# if LCD_DEPTH == 2 +# if LCD_PIXELFORMAT == VERTICAL_PACKING + dst_padded_width = dst_w; + dst_padded_height = (dst_h + 3) >> 2; +# else /* LCD_PIXELFORMAT == HORIZONTAL_PACKING */ + dst_padded_width = (dst_w + 3) >> 2; + dst_padded_height = dst_h; +# endif /* LCD_PIXELFORMAT */ +# elif LCD_DEPTH == 16 + dst_padded_width = dst_w; + dst_padded_height = dst_h; +# endif /* LCD_DEPTH */ + totalsize = dst_padded_width * dst_padded_height * sizeof(fb_data); } } else #endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */ { - dst_width = width; - dst_height = (height + 7) >> 3; - totalsize = dst_width * dst_height; + dst_padded_width = dst_w; + dst_padded_height = (dst_h + 7) >> 3; + totalsize = dst_padded_width * dst_padded_height; } /* Check if this fits the buffer */ if (totalsize > maxsize) { - DEBUGF("read_bmp_fd: Bitmap too large for buffer: " - "%d bytes.\n", totalsize); + DEBUGF("read_bmp_fd: error - Bitmap is too large to fit the supplied buffer: " + "%d bytes.%d:%d\n", (dst_padded_height * dst_padded_width), + totalsize, maxsize); return -6; } @@ -306,7 +457,7 @@ numcolors = 1 << depth; } else numcolors = (compression == 3) ? 3 : 0; - + if (numcolors > 0 && numcolors <= 256) { if (read(fd, palette, numcolors * sizeof(uint32_t)) != numcolors * (int)sizeof(uint32_t)) @@ -357,31 +508,64 @@ memset(bitmap, 0, totalsize); - /* loop to read rows and put them to buffer */ - for (row = rowstart; row != rowstop; row += rowstep) { - unsigned data, mask; - unsigned char *p; - uint16_t *p2; - uint32_t *rp; - union rgb_union *qp; - union rgb_union q0, q1; +#if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 + if (remote) + format |= FORMAT_REMOTE; // set remote flag if it is necessary +#endif + /* loop to read rows and put them to buffer */ + for (row = src_h - 1; row >= 0; row--) + { /* read one row */ - ret = read(fd, bmpbuf, padded_width); - if (ret != padded_width) { + int dst_y, num_rows = 0; + if (fact_h >= FACT_SCALE) + { + /* + * decrease vertically or just transport the pixels + * -> put only every "fact" row to the dest buffer + */ + if ((row % (fact_h / FACT_SCALE)) == 0) + { + dst_y = (row * FACT_SCALE) / fact_h - top; + if (dst_y >= 0 && dst_y < dst_h) + num_rows = 1; + } + } + else + { + /* + * increase + * -> duplicate src-pixel for not existing dst_rows/cols + */ + dst_y = MAX(row * FACT_SCALE / fact_h - top,0); + num_rows = MIN((row + 1) * FACT_SCALE / fact_h - top, dst_h)-dst_y; + } + if (num_rows<=0) + { + /* if we are not going to process data - just skip reading */ + ret = lseek(fd, src_padded_width, SEEK_CUR ); + continue; + } + ret = read(fd, bmpbuf, src_padded_width); + if (ret != src_padded_width) { DEBUGF("read_bmp_fd: error reading image, read returned: %d " - "expected: %d\n", ret, padded_width); + "expected: %d\n", ret, src_padded_width); return -9; } + unsigned data, mask; + unsigned char *p; + uint16_t *p2; + uint32_t *rp; + union rgb_union q0, q1; /* convert whole line in-place to XRGB8888 (little endian) */ - rp = bmpbuf + width; + rp = (uint32_t *)(bmpbuf + src_w); switch (depth) { case 1: - q0.raw = palette[0]; - q1.raw = palette[1]; - p = (unsigned char*)bmpbuf + ((width + 7) >> 3); - mask = 0x80 >> ((width + 7) & 7); + q0.raw = palette[0].raw; + q1.raw = palette[1].raw; + p = (unsigned char*)bmpbuf + ((src_w + 7) >> 3); + mask = 0x80 >> ((src_w + 7) & 7); while (p > (unsigned char*)bmpbuf) { data = *(--p); for (; mask <= 0x80; mask <<= 1) @@ -391,25 +575,25 @@ break; case 4: - if (width & 1) + if (src_w & 1) rp++; - p = (unsigned char*)bmpbuf + ((width + 1) >> 1); + p = (unsigned char*)bmpbuf + ((src_w + 1) >> 1); while (p > (unsigned char*)bmpbuf) { data = *(--p); - *(--rp) = palette[data & 0x0f]; - *(--rp) = palette[data >> 4]; + *(--rp) = palette[data & 0x0f].raw; + *(--rp) = palette[data >> 4].raw; } break; case 8: - p = (unsigned char*)bmpbuf + width; + p = (unsigned char*)bmpbuf + src_w; while (p > (unsigned char*)bmpbuf) - *(--rp) = palette[*(--p)]; + *(--rp) = palette[*(--p)].raw; break; - + case 15: case 16: - p2 = (uint16_t *)bmpbuf + width; + p2 = (uint16_t *)bmpbuf + src_w; while (p2 > (uint16_t *)bmpbuf) { unsigned component, rgb; @@ -455,7 +639,7 @@ break; case 24: - p = (unsigned char*)bmpbuf + 3 * width; + p = (unsigned char*)bmpbuf + 3 * src_w; while (p > (unsigned char*)bmpbuf) { data = *(--p); data = (data << 8) | *(--p); @@ -467,99 +651,63 @@ case 32: /* already in desired format */ break; } - + /* Convert to destination format */ - qp = (union rgb_union *)bmpbuf; -#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) - fb_remote_data *dest = (fb_remote_data *)bitmap - + dst_width * (row >> 3); - int shift = row & 7; - int delta = 127; - unsigned bright; - - for (col = 0; col < width; col++) { - if (dither) - delta = dither_matrix[row & 0xf][col & 0xf]; - bright = brightness(*qp++); - bright = (3 * bright + (bright >> 6) + delta) >> 8; - *dest++ |= remote_pattern[bright] << shift; - } -#endif /* LCD_REMOTE_DEPTH / LCD_REMOTE_PIXELFORMAT */ - } else -#endif /* defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 */ + while (--num_rows>=0) { + int src_col, dst_x; + if (fact_w >= FACT_SCALE) { -#if LCD_DEPTH == 2 -#if LCD_PIXELFORMAT == VERTICAL_PACKING - /* iriver H1x0 */ - fb_data *dest = (fb_data *)bitmap + dst_width * (row >> 2); - int shift = 2 * (row & 3); - int delta = 127; - unsigned bright; - - for (col = 0; col < width; col++) { - if (dither) - delta = dither_matrix[row & 0xf][col & 0xf]; - bright = brightness(*qp++); - bright = (3 * bright + (bright >> 6) + delta) >> 8; - *dest++ |= (~bright & 3) << shift; + /* decrease horizontally or just transport the pixels */ + for (dst_x = 0; dst_x < dst_w; dst_x++) { + src_col = ((dst_x + left) * fact_w) / FACT_SCALE; + set_pixel(format,bitmap,dither,bmpbuf[src_col], + dst_padded_width,dst_x,dst_y); } -#else /* LCD_PIXELFORMAT == HORIZONTAL_PACKING */ - /* greyscale iPods */ - fb_data *dest = (fb_data *)bitmap + dst_width * row; - int shift = 6; - int delta = 127; - unsigned bright; - unsigned data = 0; - - for (col = 0; col < width; col++) { - if (dither) - delta = dither_matrix[row & 0xf][col & 0xf]; - bright = brightness(*qp++); - bright = (3 * bright + (bright >> 6) + delta) >> 8; - data |= (~bright & 3) << shift; - shift -= 2; - if (shift < 0) { - *dest++ = data; - data = 0; - shift = 6; + } + else /*if (fact_w < FACT_SCALE)*/ + { + /* increase horizontally */ + for (src_col = 0; src_col < src_w; src_col++) { + int num_col; + dst_x = MAX(src_col * FACT_SCALE / fact_w - left,0); + num_col = MIN((src_col + 1) * FACT_SCALE / fact_w + - left,dst_w) - dst_x; + q0 = bmpbuf[src_col]; + while (--num_col>=0) { + set_pixel(format,bitmap,dither,q0,dst_padded_width, + dst_x,dst_y); + dst_x++; } } - if (shift < 6) - *dest++ = data; -#endif /* LCD_PIXELFORMAT */ -#elif LCD_DEPTH == 16 - /* iriver h300, colour iPods, X5 */ - fb_data *dest = (fb_data *)bitmap + dst_width * row; - int delta = 127; - unsigned r, g, b; - - for (col = 0; col < width; col++) { - if (dither) - delta = dither_matrix[row & 0xf][col & 0xf]; - 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 */ } - } else -#endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */ - { - p = bitmap + dst_width * (row >> 3); - mask = 1 << (row & 7); - - for (col = 0; col < width; col++, p++) - if (brightness(*qp++) < 128) - *p |= mask; + dst_y++; } } - DEBUGF("totalsize: %d\n", totalsize); + DEBUGF("read_bmp_fd: totalsize=%d, width=%d, height=%d depth=%d" + " compression=%d numcolors=%d\n", + totalsize, dst_w, dst_h, depth, compression, numcolors); + return totalsize; /* return the used buffer size. */ } + +int read_bmp_file(const char* filename, + struct bitmap *bm, + int maxsize, + int format, + int dst_maxwidth, + int dst_maxheight, + int flags) +{ + int fd = open(filename, O_RDONLY); + int ret; + /* Exit if file opening failed */ + if (fd < 0) { + DEBUGF("read_bmp_fd: can't open '%s', rc: %d\n", filename, fd); + return fd * 10 - 1; + } + ret = read_bmp_fd(fd, bm, maxsize, format, dst_maxwidth, dst_maxheight, + flags); + close(fd); + return ret; +} diff -u -r apps/recorder/bmp.h apps/recorder/bmp.h --- apps/recorder/bmp.h 2007-11-10 18:54:43.405625000 -0600 +++ apps/recorder/bmp.h 2007-11-12 00:04:08.671250000 -0600 @@ -22,21 +22,34 @@ #include "config.h" #include "lcd.h" +#define BMP_RESIZE_NONE 1 +#define BMP_RESIZE_INCREASE 2 +#define BMP_RESIZE_DECREASE 4 +#define BMP_RESIZE_IGNORE_ASPECT 8 +#define BMP_RESIZE_FILL 16 + /********************************************************************* * read_bmp_file() * * Reads a 8bit BMP file and puts the data in a 1-pixel-per-byte - * array. + * array. * Returns < 0 for error, or number of bytes used from the bitmap buffer * **********************************************/ +int read_bmp_fd (int fd, + struct bitmap *bm, + int maxsize, + int format, + int dst_maxwidth, /* = 0 */ + int dst_maxheight,/* = 0 */ + int flags); /* BMP_RESIZE_NONE */ + int read_bmp_file(const char* filename, struct bitmap *bm, int maxsize, - int format); + int format, + int dst_maxwidth, /* = 0 */ + int dst_maxheight,/* = 0 */ + int flags); /* BMP_RESIZE_NONE */ -int read_bmp_fd(int fd, - struct bitmap *bm, - int maxsize, - int format); #endif