Index: apps/recorder/albumart.c =================================================================== --- apps/recorder/albumart.c (revision 18858) +++ apps/recorder/albumart.c (working copy) @@ -98,6 +98,7 @@ * ../.bmp * ../cover.bmp * ROCKBOX_DIR/albumart/-.bmp + * ROCKBOX_DIR/albumart/.bmp * is the value of the size_string parameter, and * are read from the ID3 metadata. * If a matching bitmap is found, its filename is stored in buf. @@ -163,6 +164,17 @@ found = file_exists(path); } + if (!found && id3->album) + { + /* look in the albumart subdir of .rockbox */ + snprintf(path, sizeof(path), + ROCKBOX_DIR "/albumart/%s%s.bmp", + id3->album, + size_string); + fix_path_part(path, strlen(ROCKBOX_DIR "/albumart/"), MAX_PATH); + found = file_exists(path); + } + if (!found) { /* if it still doesn't exist, @@ -297,3 +309,12 @@ gwps->display->set_drawmode(DRMODE_SOLID); } } + +void get_albumart_size(struct bitmap *bmp) +{ + /* FIXME: What should we do with albumart on remote? */ + struct wps_data *data = gui_wps[0].data; + + bmp->width = data->albumart_max_width; + bmp->height = data->albumart_max_height; +} Index: apps/recorder/albumart.h =================================================================== --- apps/recorder/albumart.h (revision 18858) +++ apps/recorder/albumart.h (working copy) @@ -40,6 +40,8 @@ bool search_albumart_files(const struct mp3entry *id3, const char *size_string, char *buf, int buflen); +void get_albumart_size(struct bitmap *bmp); + #endif /* HAVE_ALBUMART */ #endif /* _ALBUMART_H_ */ Index: apps/recorder/bmp.c =================================================================== --- apps/recorder/bmp.c (revision 18858) +++ apps/recorder/bmp.c (working copy) @@ -170,6 +170,839 @@ return ret; } +static int read_one_line(int fd, uint32_t *bmpb, int padded_width, + short width, short depth, uint32_t *palette) +{ + unsigned data, mask; + unsigned char *p; + uint16_t *p2; + uint32_t *rp; + int ret; + union rgb_union q0, q1; + + ret = read(fd, bmpb, padded_width); + if (ret != padded_width) { + DEBUGF("read_one_line: error reading image, read returned: %d " + "expected: %d\n", ret, padded_width); + return -9; + } + + /* convert whole line in-place to XRGB8888 (little endian) */ + rp = bmpb + width; + switch (depth) { + case 1: + q0.raw = palette[0]; + q1.raw = palette[1]; + p = (unsigned char*)bmpb + ((width + 7) >> 3); + mask = 0x80 >> ((width + 7) & 7); + while (p > (unsigned char*)bmpb) { + data = *(--p); + for (; mask <= 0x80; mask <<= 1) + *(--rp) = (data & mask) ? q1.raw : q0.raw; + mask = 0x01; + } + break; + + case 4: + if (width & 1) + rp++; + p = (unsigned char*)bmpb + ((width + 1) >> 1); + while (p > (unsigned char*)bmpb) { + data = *(--p); + *(--rp) = palette[data & 0x0f]; + *(--rp) = palette[data >> 4]; + } + break; + + case 8: + p = (unsigned char*)bmpb + width; + while (p > (unsigned char*)bmpb) + *(--rp) = palette[*(--p)]; + break; + + case 15: + case 16: + p2 = (uint16_t *)bmpb + width; + while (p2 > (uint16_t *)bmpb) { + unsigned component, rgb; + + data = letoh16(*(--p2)); + /* blue */ + component = (data << 3) & 0xf8; +#ifdef ROCKBOX_BIG_ENDIAN + rgb = (component | (component >> 5)) << 8; + /* green */ + data >>= 2; + if (depth == 15) { + component = data & 0xf8; + rgb |= component | (component >> 5); + } else { + data >>= 1; + component = data & 0xfc; + rgb |= component | (component >> 6); + } + /* red */ + data >>= 5; + component = data & 0xf8; + rgb = (rgb << 8) | component | (component >> 5); + *(--rp) = rgb << 8; +#else /* little endian */ + rgb = component | (component >> 5); + /* green */ + data >>= 2; + if (depth == 15) { + component = data & 0xf8; + rgb |= (component | (component >> 5)) << 8; + } else { + data >>= 1; + component = data & 0xfc; + rgb |= (component | (component >> 6)) << 8; + } + /* red */ + data >>= 5; + component = data & 0xf8; + rgb |= (component | (component >> 5)) << 16; + *(--rp) = rgb; +#endif + } + break; + + case 24: + p = (unsigned char*)bmpb + 3 * width; + while (p > (unsigned char*)bmpb) { + data = *(--p); + data = (data << 8) | *(--p); + data = (data << 8) | *(--p); + *(--rp) = htole32(data); + } + break; + + case 32: /* already in desired format */ + break; + } + return 0; +} + +#if (LCD_DEPTH > 1) +#define LIMIT_WIDTH (500) +#else +#define LIMIT_WIDTH LCD_WIDTH +#endif + +#if (LCD_WIDTH < LIMIT_WIDTH) +#define MAX_WIDTH LIMIT_WIDTH +#else +#define MAX_WIDTH LCD_WIDTH +#endif + +#define BMP_NORESIZE 0 +#define BMP_RESIZE 1 +#define BMP_BILINEAR 2 +#define BMP_RESIZE_BILINEAR (BMP_RESIZE | BMP_BILINEAR) + +struct cache_line_t { + uint32_t bmpbuf[MAX_WIDTH]; + short y; +}; + +struct dim_t { + short width; + short height; +}; + +#if (LCD_DEPTH == 16) +/* needs more than 2 lines for bilinear */ +#define CACHE_SZ 5 +#else +/* only 1 line for nearest neighbour */ +#define CACHE_SZ 1 +#endif + +#define ARRAY_SIZE(array) (int)(sizeof(array)/(sizeof(array[0]))) + +static struct cache_line_t cache_line[CACHE_SZ]; +static short cache_line_index = 0; +static short cache_line_srcy = -1; + +static union rgb_union *read_cache_line(int fd, short y, short padded_width, + short width, int depth, + uint32_t *palette) +{ + union rgb_union *qp = NULL; + int i = 0; + + for (i = 0; i < ARRAY_SIZE(cache_line); i++) { + if (y == cache_line[i].y) { + qp = (union rgb_union *)cache_line[i].bmpbuf; + cache_line_index = i + 1; + + if (cache_line_index == ARRAY_SIZE(cache_line)) + cache_line_index = 0; + + return qp; /* cache found */ + } + } + + /* cache missed, so read some lines from disk.. */ + int loop; + if (cache_line_srcy == -1) { + loop = 1; + cache_line_srcy = y; + } else + loop = (y - cache_line_srcy) + 1; + + int dummy_loop = loop - CACHE_SZ; + uint32_t *cline_dum = NULL; + if (dummy_loop > 0) { + loop -= dummy_loop; + cline_dum = cache_line[cache_line_index].bmpbuf; + } + + /* skip some needless lines */ + for (i = 0; i < dummy_loop; i++) { + short ret = read(fd, cline_dum, padded_width); + if (ret != padded_width) { + DEBUGF("read_cache_line: error reading image, read returned: %d " + "expected: %d\n", ret, padded_width); + return NULL; + } + cache_line_srcy++; + } + + + for (i = 0; i < loop; i++) { + uint32_t *cline = cache_line[cache_line_index].bmpbuf; + if (0 != read_one_line(fd, cline, padded_width, width, depth, palette)) + return NULL; + + cache_line[cache_line_index].y = cache_line_srcy; + cache_line_srcy++; + qp = (union rgb_union *)cache_line[cache_line_index].bmpbuf; + cache_line_index++; + if (cache_line_index == ARRAY_SIZE(cache_line)) + cache_line_index = 0; + } + + return qp; +} + +static void init_cache_line(void) +{ + int i; + cache_line_index = 0; + cache_line_srcy = -1; + for (i = 0; i < ARRAY_SIZE(cache_line); i++) + cache_line[i].y = -1; +} + +#if (LCD_DEPTH == 16) +#define PACKRED(r, delata) (31 * r + (r >> 3) + delta) >> 8; +#define PACKGREEN(g, delta) (63 * g + (g >> 2) + delta) >> 8; +#define PACKBLUE(b, delta) (31 * b + (b >> 3) + delta) >> 8; + +struct rgb_t { + int r; + int g; + int b; +}; + +static void downscale_help(union rgb_union *pix, int xap, int Cx, int Cy, + struct rgb_t *rgb) +{ + int i; + int rx = (pix->red * xap) >> 9; + int gx = (pix->green * xap) >> 9; + int bx = (pix->blue * xap) >> 9; + pix++; + for (i = (1 << 14) - xap; i > Cx; i -= Cx) { + rx += (pix->red * Cx) >> 9; + gx += (pix->green * Cx) >> 9; + bx += (pix->blue * Cx) >> 9; + pix++; + } + if (i > 0) { + rx += (pix->red * i) >> 9; + gx += (pix->green * i) >> 9; + bx += (pix->blue * i) >> 9; + } + + rgb->r = (rx * Cy) >> 14; + rgb->g = (gx * Cy) >> 14; + rgb->b = (bx * Cy) >> 14; +} + +/* + * This algorithm is taken from app/plugins/lib/bmp_smooth_scale.c + * smooth_resize_bitmap(). + * And that is take from Imlib2 + */ +static bool resize_on_load(int fd, short padded_width, int depth, bool dither, + uint32_t *palette, struct bitmap *bm, + struct dim_t *src, struct dim_t *dst, + short rowstep, bool remote, unsigned char resize) +{ + const short sw = src->width; + const short sh = src->height; + const short dw = bm->width; + const short dh = bm->height; + const int inc_x = (sw << 16) / dw; + const int inc_y = (sh << 16) / dh; + const int Cp_x = ((dw << 14) / sw) + 1; + const int Cp_y = ((dh << 14) / sh) + 1; + unsigned char xup_yup; + unsigned char *bitmap = bm->data; + int XAP, YAP, INV_YAP, INV_XAP; + int val_y = 0, val_x; + short x, y, xpoint, ypoint; + short rowstart, rowstop; + int format = bm->format; +#if defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH == 2) && \ + (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED) + const short dst_width = dst->width; +#else + (void) dst; +#endif + +#if !defined(HAVE_REMOTE_LCD) || \ + (defined(HAVE_REMOTE_LCD) &&(LCD_REMOTE_DEPTH == 1)) + (void) remote; +#endif + if (resize & BMP_BILINEAR) + xup_yup = 3; /* always use bilinear */ + else + xup_yup = (dw >= sw) + ((dh >= sh) << 1); + + if (rowstep == -1) { + rowstart = dh - 1; + rowstop = -1; + } else { + rowstart = 0; + rowstop = dh; + } + + init_cache_line(); + + for (y = rowstart; y != rowstop; y += rowstep) { + 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 + + dst_width * (y >> 3); + int shift = y & 7; + int delta = 127; + unsigned bright; + union rgb_union *qp; + + ypoint = (val_y >> 8); + if ((qp = read_cache_line(fd, ypoint, padded_width, sw, + depth, palette)) == NULL) + goto out; + + for (val_x = 0, x = 0; x < dw; x++) { + union rgb_union *pix; + if (dither) + delta = dither_matrix[y & 0xf][x & 0xf]; + xpoint = (val_x >> 8); + pix = qp + xpoint; + bright = brightness(*pix); + bright = (3 * bright + (bright >> 6) + delta) >> 8; + *dest++ |= vi_pattern[bright] << shift; + val_x += inc_x; + } + val_y += inc_y; + +#endif /* LCD_REMOTE_DEPTH / LCD_REMOTE_PIXELFORMAT */ + } else +#endif /* defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 */ + { + union rgb_union *qp, *qp2; + int delta = 127; + + if (xup_yup == 3) { + /* upscaling both way */ + /* algorithm: bilinear */ + ypoint = (val_y >> 16); + fb_data *dest = (fb_data *)bitmap + y * dw; + + if ((qp = read_cache_line(fd, ypoint, padded_width, sw, + depth, palette)) == NULL) + goto out; + + YAP = ((val_y >> 16) >= (sh - 1)) ? 0 : + (val_y >> 8) - ((val_y >> 8) & 0xffffff00); + INV_YAP = 256 - YAP; + val_y += inc_y; + val_x = 0; + if (YAP > 0) { + for (x = 0; x < dw; x++) { + int r = 0, g = 0, b = 0; + int rr = 0, gg = 0, bb = 0; + union rgb_union *pix; + if (dither) + delta = dither_matrix[y & 0xf][x & 0xf]; + xpoint = (val_x >> 16); + XAP = ((val_x >> 16) >= (sw - 1)) ? 0 : + (val_x >> 8) - ((val_x >> 8) & 0xffffff00); + INV_XAP = 256 - XAP; + val_x += inc_x; + + if (XAP > 0) { + pix = qp + xpoint; + r = pix->red * INV_XAP; + g = pix->green * INV_XAP; + b = pix->blue * INV_XAP; + pix++; + r += pix->red * XAP; + g += pix->green * XAP; + b += pix->blue * XAP; + + if ((qp2 = read_cache_line(fd, ypoint + 1, + padded_width, sw, + depth, palette)) == NULL) + goto out; + + + pix = qp2 + xpoint; + rr = pix->red * INV_XAP; + gg = pix->green * INV_XAP; + bb = pix->blue * INV_XAP; + pix++; + rr += pix->red * XAP; + gg += pix->green * XAP; + bb += pix->blue * XAP; + r = ((rr * YAP) + (r * INV_YAP)) >> 16; + g = ((gg * YAP) + (g * INV_YAP)) >> 16; + b = ((bb * YAP) + (b * INV_YAP)) >> 16; + r = PACKRED(r, delta); + g = PACKGREEN(g, delta); + b = PACKBLUE(b, delta); + *dest++ = LCD_RGBPACK_LCD(r, g, b); + } else { + pix = qp + xpoint; + r = pix->red * INV_YAP; + g = pix->green * INV_YAP; + b = pix->blue * INV_YAP; + + if ((qp2 = read_cache_line(fd, ypoint + 1, + padded_width, sw, depth, + palette)) == NULL) + goto out; + + pix = qp2 + xpoint; + r += pix->red * YAP; + g += pix->green * YAP; + b += pix->blue * YAP; + r >>= 8; + g >>= 8; + b >>= 8; + r = PACKRED(r, delta); + g = PACKGREEN(g, delta); + b = PACKBLUE(b, delta); + *dest++ = LCD_RGBPACK_LCD(r, g, b); + } + } + } else { + for (x = 0; x < dw; x++) { + int r = 0, g = 0, b = 0; + union rgb_union *pix; + if (dither) + delta = dither_matrix[y & 0xf][x & 0xf]; + xpoint = (val_x >> 16); + XAP = ((val_x >> 16) >= (sw - 1)) ? 0 : + (val_x >> 8) - ((val_x >> 8) & 0xffffff00); + INV_XAP = 256 - XAP; + val_x += inc_x; + + if (XAP > 0) { + pix = qp + xpoint; + r = pix->red * INV_XAP; + g = pix->green * INV_XAP; + b = pix->blue * INV_XAP; + pix++; + r += pix->red * XAP; + g += pix->green * XAP; + b += pix->blue * XAP; + r >>= 8; + g >>= 8; + b >>= 8; + r = PACKRED(r, delta); + g = PACKGREEN(g, delta); + b = PACKBLUE(b, delta); + *dest++ = LCD_RGBPACK_LCD(r, g, b); + } else { + pix = qp + xpoint; + r = pix->red; + g = pix->green; + b = pix->blue; + r = PACKRED(r, delta); + g = PACKGREEN(g, delta); + b = PACKBLUE(b, delta); + *dest++ = LCD_RGBPACK_LCD(r, g, b); + } + } + } + } else if (xup_yup == 0) { + /* downscaling both way */ + /* algorithm: area sampling */ + int Cx, Cy, j; + union rgb_union *pix; + int r, g, b; + int xap, yap; + fb_data *dest = (fb_data *)bitmap + y * dw; + + if ((qp = read_cache_line(fd, val_y >> 16, padded_width, + sw, depth, + palette)) == NULL) + goto out; + + YAP = (((0x100 - ((val_y >> 8) & 0xff)) * Cp_y) >> 8) | + (Cp_y << 16); + INV_YAP = 256 - YAP; + val_y += inc_y; + val_x = 0; + + Cy = YAP >> 16; + yap = YAP & 0xffff; + + for (x = 0; x < dw; x++) { + struct rgb_t tmp_rgb; + ypoint = ((val_y - inc_y) >> 16); + if (dither) + delta = dither_matrix[y & 0xf][x & 0xf]; + xpoint = (val_x >> 16); + XAP = (((0x100 - ((val_x >> 8) & 0xff)) * Cp_x) >> 8) | + (Cp_x << 16); + INV_XAP = 256 - XAP; + val_x += inc_x; + + Cx = XAP >> 16; + xap = XAP & 0xffff; + + pix = qp + xpoint; + ypoint++; + + downscale_help(pix, xap, Cx, yap, &tmp_rgb); + r = tmp_rgb.r; + g = tmp_rgb.g; + b = tmp_rgb.b; + + for (j = (1 << 14) - yap; j > Cy; j -= Cy) { + if ((qp = read_cache_line(fd, ypoint, padded_width, + sw, depth, + palette)) == NULL) + goto out; + + pix = qp + xpoint; + ypoint++; + + downscale_help(pix, xap, Cx, Cy, &tmp_rgb); + r += tmp_rgb.r; + g += tmp_rgb.g; + b += tmp_rgb.b; + } + if (j > 0) { + + if ((qp = read_cache_line(fd, ypoint, padded_width, + sw, depth, + palette)) == NULL) + goto out; + + pix = qp + xpoint; + ypoint++; + + downscale_help(pix, xap, Cx, j, &tmp_rgb); + r += tmp_rgb.r; + g += tmp_rgb.g; + b += tmp_rgb.b; + } + + r = PACKRED(r, delta); + g = PACKGREEN(g, delta); + b = PACKBLUE(b, delta); + *dest = LCD_RGBPACK_LCD(r >> 5, g >> 5, b >> 5); + dest++; + } + } else { + /* We always keep aspect ratio, so this does not occur. */ + DEBUGF("error: xup_yup = %d is not implemented\n", xup_yup); + goto out; + } + } + } else + { + unsigned char *p = bitmap + dw * (y >> 3); + unsigned mask = 1 << (y & 7); + union rgb_union *qp; + + ypoint = (val_y >> 8); + if ((qp = read_cache_line(fd, ypoint, padded_width, sw, + depth, palette)) == NULL) + goto out; + + for (val_x = 0, x = 0; x < dw; x++, p++) { + union rgb_union *pix; + xpoint = (val_x >> 8); + pix = qp + xpoint; + if (brightness(*pix) < 128) + *p |= mask; + val_x += inc_x; + } + val_y += inc_y; + } + } + return true; + +out: + return false; +} +#else /* LCD_DEPTH == 16 */ +/* + * This algorithm is taken from apps/plugins/lib/bmp.c simple_resize_bitmap(). + * And that algorithm is "nearest neighbour". + */ +static bool resize_on_load(int fd, short padded_width, int depth, bool dither, + uint32_t *palette, struct bitmap *bm, + struct dim_t *src, struct dim_t *dst, + short rowstep, bool remote, unsigned char resize) +{ + const short sw = src->width; + const short sh = src->height; + const short dw = bm->width; + const short dh = bm->height; + int val_y = 0, val_x; + const int inc_x = ((sw - 1) << 8) / (dw - 1); + const int inc_y = ((sh - 1) << 8) / (dh - 1); + unsigned char *bitmap = bm->data; + int ypoint, xpoint; + short rowstart, rowstop; + const short dst_width = dst->width; +#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) + int format = bm->format; +#endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */ + (void) resize; + +#if !defined(HAVE_REMOTE_LCD) || \ + (defined(HAVE_REMOTE_LCD) &&(LCD_REMOTE_DEPTH == 1)) + (void) remote; +#endif + +#if (LCD_DEPTH == 1) + (void) dither; +#endif + short x, y; + + if (rowstep == -1) { + rowstart = dh - 1; + rowstop = -1; + } else { + rowstart = 0; + rowstop = dh; + } + + init_cache_line(); + + for (y = rowstart; y != rowstop; y += rowstep) { +#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) + /* iAudio X5/M5 remote */ + fb_remote_data *dest = (fb_remote_data *)bitmap + + dst_width * (y >> 3); + int shift = y & 7; + int delta = 127; + unsigned bright; + union rgb_union *qp; + + ypoint = (val_y >> 8); + if ((qp = read_cache_line(fd, ypoint, padded_width, sw, + depth, palette)) == NULL) + goto out; + + for (val_x = 0, x = 0; x < dw; x++) { + union rgb_union *pix; + if (dither) + delta = dither_matrix[y & 0xf][x & 0xf]; + xpoint = (val_x >> 8); + pix = qp + xpoint; + bright = brightness(*pix); + bright = (3 * bright + (bright >> 6) + delta) >> 8; + *dest++ |= vi_pattern[bright] << shift; + val_x += inc_x; + } + val_y += inc_y; + +#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 + dst_width * y; + int shift = 6; + int delta = 127; + unsigned bright; + unsigned data = 0; + union rgb_union *qp; + + ypoint = (val_y >> 8); + if ((qp = read_cache_line(fd, ypoint, padded_width, sw, + depth, palette)) == NULL) + goto out; + + for (val_x = 0, x = 0; x < dw; x++) { + union rgb_union *pix; + if (dither) + delta = dither_matrix[y & 0xf][x & 0xf]; + xpoint = (val_x >> 8); + pix = qp + xpoint; + bright = brightness(*pix); + bright = (3 * bright + (bright >> 6) + delta) >> 8; + data |= (~bright & 3) << shift; + shift -= 2; + if (shift < 0) { + *dest++ = data; + data = 0; + shift = 6; + } + val_x += inc_x; + } + val_y += inc_y; + if (shift < 6) + *dest++ = data; +#elif LCD_PIXELFORMAT == VERTICAL_PACKING + /* iriver H1x0 */ + fb_data *dest = (fb_data *)bitmap + dst_width * (y >> 2); + int shift = 2 * (y & 3); + int delta = 127; + unsigned bright; + union rgb_union *qp; + + ypoint = (val_y >> 8); + if ((qp = read_cache_line(fd, ypoint, padded_width, sw, + depth, palette)) == NULL) + goto out; + + for (val_x = 0, x = 0; x < dw; x++) { + union rgb_union *pix; + if (dither) + delta = dither_matrix[y & 0xf][x & 0xf]; + xpoint = (val_x >> 8); + pix = qp + xpoint; + bright = brightness(*pix); + bright = (3 * bright + (bright >> 6) + delta) >> 8; + *dest++ |= (~bright & 3) << shift; + val_x += inc_x; + } + val_y += inc_y; +#elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED + /* iAudio M3 */ + fb_data *dest = (fb_data *)bitmap + dst_width * (y >> 3); + int shift = y & 7; + int delta = 127; + unsigned bright; + union rgb_union *qp; + + ypoint = (val_y >> 8); + if ((qp = read_cache_line(fd, ypoint, padded_width, sw, + depth, palette)) == NULL) + goto out; + + for (val_x = 0, x = 0; x < dw; x++) { + union rgb_union *pix; + if (dither) + delta = dither_matrix[y & 0xf][x & 0xf]; + xpoint = (val_x >> 8); + pix = qp + xpoint; + bright = brightness(*pix); + bright = (3 * bright + (bright >> 6) + delta) >> 8; + *dest++ |= vi_pattern[bright] << shift; + val_x += inc_x; + } + val_y += inc_y; +#endif /* LCD_PIXELFORMAT */ +#endif /* LCD_DEPTH == 2 */ + } + } else +#endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */ + { + unsigned char *p = bitmap + dst_width * (y >> 3); + unsigned mask = 1 << (y & 7); + union rgb_union *qp; + + ypoint = (val_y >> 8); + if ((qp = read_cache_line(fd, ypoint, padded_width, sw, + depth, palette)) == NULL) + goto out; + + for (val_x = 0, x = 0; x < dw; x++, p++) { + union rgb_union *pix; + xpoint = (val_x >> 8); + pix = qp + xpoint; + if (brightness(*pix) < 128) + *p |= mask; + val_x += inc_x; + } + val_y += inc_y; + } + } + return true; + +out: + return false; +} +#endif /* (LCD_DEPTH == 16) */ + +#define SCALE 10 + +static inline bool recalc_dimension(struct dim_t *dst, struct dim_t *src) +{ + short dst_width = dst->width; + short dst_height = dst->height; + const short src_width = src->width; + const short src_height = src->height; + bool ret = false; + + if (dst_width < 0 || dst_height < 0 || src_width <= 0 || src_height <= 0) { + dst->width = src_width; + dst->height = src_height; + ret = false; + goto out; + } + + if (dst_width == 0) + dst_width = src_width; + if (dst_height == 0) + dst_height = src_height; + + if ((dst_width == src_width) && (dst_height == src_height)) { + dst->width = src_width; + dst->height = src_height; + ret = false; + } else { + /* recalc bmpsize to keep aspect ratio */ + const unsigned short fact_w = (dst_width << SCALE) / src_width; + const unsigned short fact_h = (dst_height << SCALE) / src_height; + const unsigned short fact = MIN(fact_w, fact_h); + + /* "1 << (SCALE -1)" is "round off" */ + dst->width = (src_width * fact + (1 << (SCALE - 1))) >> SCALE; + dst->height = (src_height * fact + (1 << (SCALE -1))) >> SCALE; + + if ((dst->width == src_width) && (dst->height == src_height)) + ret = false; + else + ret = true; + } + +out: + return ret; +} + /****************************************************************************** * read_bmp_fd() * @@ -183,20 +1016,21 @@ int format) { struct bmp_header bmph; - int width, height, padded_width; - int dst_height, dst_width; - int depth, numcolors, compression, totalsize; - int row, col, ret; - int rowstart, rowstop, rowstep; + short width, height, padded_width; + short dst_height, dst_width; + short depth; + int numcolors, compression, totalsize; + short row, col, ret; + short rowstart, rowstop, rowstep; unsigned char *bitmap = bm->data; - uint32_t bmpbuf[LCD_WIDTH]; /* Buffer for one line */ + unsigned char resize = BMP_NORESIZE; uint32_t palette[256]; + bool remote = 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; @@ -207,6 +1041,10 @@ #endif } #endif /* HAVE_REMOTE_LCD */ + + if ((bm->height > 0) || (bm->width > 0)) + resize = BMP_RESIZE; + if (format & FORMAT_TRANSPARENT) { transparent = true; format &= ~FORMAT_TRANSPARENT; @@ -216,7 +1054,7 @@ format &= ~FORMAT_DITHER; } #else - + bool dither = false; (void)format; #endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */ @@ -232,9 +1070,9 @@ } width = readlong(&bmph.width); - if (width > LCD_WIDTH) { + if (width > MAX_WIDTH) { DEBUGF("read_bmp_fd: Bitmap too wide (%d pixels, max is %d)\n", - width, LCD_WIDTH); + width, MAX_WIDTH); return -4; } @@ -262,10 +1100,38 @@ } 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 == 16) + if (resize & BMP_RESIZE) { + if ((bm->width * CACHE_SZ < width) || + (bm->height * CACHE_SZ < height)) { + DEBUGF("Warning: This bitmap is too large to downscale!\n"); + resize = BMP_RESIZE_BILINEAR; + } + } +#endif + struct dim_t orig_dim = { + .width = width, + .height = height, + }; + if (resize & BMP_RESIZE) { + struct dim_t resize_dim = { + .width = bm->width, + .height = bm->height, + }; + /* We always keep aspect ratio.. */ + if (!recalc_dimension(&resize_dim, &orig_dim)) + resize = BMP_NORESIZE; + width = resize_dim.width; + height = resize_dim.height; + bm->width = width; + bm->height = height; + } else { + /* returning image size */ + bm->width = orig_dim.width; + bm->height = orig_dim.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 @@ -368,119 +1234,31 @@ memset(bitmap, 0, totalsize); + if (resize & BMP_RESIZE) { + struct dim_t dst_dim = { + .width = dst_width, + .height = dst_height, + }; + if (resize_on_load(fd, padded_width, depth, dither, palette, bm, + &orig_dim, &dst_dim, rowstep, remote, resize)) { + return totalsize; + } else { + return -1; + } + } + + uint32_t *bmpb = cache_line[0].bmpbuf; /* loop to read rows and put them to buffer */ for (row = rowstart; row != rowstop; row += rowstep) { - unsigned data, mask; + unsigned mask; unsigned char *p; - uint16_t *p2; - uint32_t *rp; union rgb_union *qp; - union rgb_union q0, q1; - /* read one row */ - ret = read(fd, bmpbuf, padded_width); - if (ret != padded_width) { - DEBUGF("read_bmp_fd: error reading image, read returned: %d " - "expected: %d\n", ret, padded_width); + if (0 != read_one_line(fd, bmpb, padded_width, width, depth, palette)) return -9; - } - - /* convert whole line in-place to XRGB8888 (little endian) */ - rp = bmpbuf + width; - switch (depth) { - case 1: - q0.raw = palette[0]; - q1.raw = palette[1]; - p = (unsigned char*)bmpbuf + ((width + 7) >> 3); - mask = 0x80 >> ((width + 7) & 7); - while (p > (unsigned char*)bmpbuf) { - data = *(--p); - for (; mask <= 0x80; mask <<= 1) - *(--rp) = (data & mask) ? q1.raw : q0.raw; - mask = 0x01; - } - break; - - case 4: - if (width & 1) - rp++; - p = (unsigned char*)bmpbuf + ((width + 1) >> 1); - while (p > (unsigned char*)bmpbuf) { - data = *(--p); - *(--rp) = palette[data & 0x0f]; - *(--rp) = palette[data >> 4]; - } - break; - - case 8: - p = (unsigned char*)bmpbuf + width; - while (p > (unsigned char*)bmpbuf) - *(--rp) = palette[*(--p)]; - break; - - case 15: - case 16: - p2 = (uint16_t *)bmpbuf + width; - while (p2 > (uint16_t *)bmpbuf) { - unsigned component, rgb; - - data = letoh16(*(--p2)); - /* blue */ - component = (data << 3) & 0xf8; -#ifdef ROCKBOX_BIG_ENDIAN - rgb = (component | (component >> 5)) << 8; - /* green */ - data >>= 2; - if (depth == 15) { - component = data & 0xf8; - rgb |= component | (component >> 5); - } else { - data >>= 1; - component = data & 0xfc; - rgb |= component | (component >> 6); - } - /* red */ - data >>= 5; - component = data & 0xf8; - rgb = (rgb << 8) | component | (component >> 5); - *(--rp) = rgb << 8; -#else /* little endian */ - rgb = component | (component >> 5); - /* green */ - data >>= 2; - if (depth == 15) { - component = data & 0xf8; - rgb |= (component | (component >> 5)) << 8; - } else { - data >>= 1; - component = data & 0xfc; - rgb |= (component | (component >> 6)) << 8; - } - /* red */ - data >>= 5; - component = data & 0xf8; - rgb |= (component | (component >> 5)) << 16; - *(--rp) = rgb; -#endif - } - break; - - case 24: - p = (unsigned char*)bmpbuf + 3 * width; - while (p > (unsigned char*)bmpbuf) { - data = *(--p); - data = (data << 8) | *(--p); - data = (data << 8) | *(--p); - *(--rp) = htole32(data); - } - break; - - case 32: /* already in desired format */ - break; - } /* Convert to destination format */ - qp = (union rgb_union *)bmpbuf; + qp = (union rgb_union *)bmpb; #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 @@ -562,6 +1340,7 @@ fb_data *dest = (fb_data *)bitmap + dst_width * row; int delta = 127; unsigned r, g, b; + union rgb_union q0; for (col = 0; col < width; col++) { if (dither) Index: apps/plugins/test_resize.c =================================================================== --- apps/plugins/test_resize.c (revision 18858) +++ apps/plugins/test_resize.c (working copy) @@ -77,8 +77,8 @@ input_bmp.data = (char*)input_bmp_data; output_bmp.data = (char*)output_bmp_data; - int ret = rb->read_bmp_file("/test.bmp", &input_bmp, sizeof(input_bmp_data), - FORMAT_NATIVE); + int ret = rb->read_bmp_file("/test.bmp", noresize(&input_bmp), + sizeof(input_bmp_data), FORMAT_NATIVE); if (ret < 0) { rb->splash(HZ, "Could not load /test.bmp"); Index: apps/plugins/sliding_puzzle.c =================================================================== --- apps/plugins/sliding_puzzle.c (revision 18858) +++ apps/plugins/sliding_puzzle.c (working copy) @@ -233,10 +233,6 @@ static unsigned char img_buf[IMAGE_WIDTH*IMAGE_HEIGHT*sizeof(fb_data)] __attribute__ ((aligned(16))); -#if LCD_DEPTH>1 -static unsigned char temp_img_buf[LCD_WIDTH*LCD_HEIGHT*sizeof(fb_data)] -__attribute__ ((aligned(16))); -#endif #ifdef HAVE_ALBUMART static char albumart_path[MAX_PATH+1]; #endif @@ -312,28 +308,9 @@ rb->memset(&main_bitmap,0,sizeof(struct bitmap)); main_bitmap.data = img_buf; -#if LCD_DEPTH>1 - struct bitmap temp_bitmap; - rb->memset(&temp_bitmap,0,sizeof(struct bitmap)); - temp_bitmap.data = temp_img_buf; - main_bitmap.width = IMAGE_WIDTH; main_bitmap.height = IMAGE_HEIGHT; - rc = rb->read_bmp_file( filename, &temp_bitmap, sizeof(temp_img_buf), - FORMAT_NATIVE ); - if( rc > 0 ) - { -#ifdef HAVE_LCD_COLOR - smooth_resize_bitmap( &temp_bitmap, &main_bitmap ); -#else - simple_resize_bitmap( &temp_bitmap, &main_bitmap ); -#endif - puzzle_bmp_ptr = (const fb_data *)img_buf; - rb->strcpy( img_buf_path, filename ); - return true; - } -#else rc = rb->read_bmp_file( filename, &main_bitmap, sizeof(img_buf), FORMAT_NATIVE ); if( rc > 0 ) @@ -342,7 +319,6 @@ rb->strcpy( img_buf_path, filename ); return true; } -#endif } /* something must have failed. get_albumart_bmp_path could return Index: apps/plugins/jpeg/yuv2rgb.c =================================================================== --- apps/plugins/jpeg/yuv2rgb.c (revision 18858) +++ apps/plugins/jpeg/yuv2rgb.c (working copy) @@ -7,9 +7,10 @@ * \/ \/ \/ \/ \/ * $Id$ * -* JPEG image viewer -* (This is a real mess if it has to be coded in one single C file) -* +* Colour Conversion and Rotation +* +* Landscape rotation addition by Rene Peinthor and Adam Geshlin +* with modifications made by GRaTT * File scrolling addition (C) 2005 Alexander Spyridakis * Copyright (C) 2004 Jörg Hohensohn aka [IDC]Dragon * Heavily borrowed from the IJG implementation (C) Thomas G. Lane @@ -246,7 +247,175 @@ [DITHER_DIFFUSION] = pixel_fsdither_to_lcd, }, }; - + +/* Rotate Function */ + +#define RYFAC (31*257) +#define GYFAC (63*257) +#define BYFAC (31*257) +#define R_RVFAC 11170 /* 31 * 257 * 1.402 */ +#define R_GVFAC (-11563) /* 63 * 257 * -0.714136 */ +#define R_GUFAC (-5572) /* 63 * 257 * -0.344136 */ +#define R_BUFAC 14118 /* 31 * 257 * 1.772 */ + +#define ROUNDOFFS (127*257) + +/* Performance function to blit a YUV bitmap directly to the LCD + Actually this code is from gigabeat, because this target is also + writing direct to a buffer. */ +void rotate(unsigned char *src[3], int csub_x, int csub_y, + int src_x, int src_y, int stride, + int _x, int _y, /* x, y */ + int width, int height, /* w, h */ + int colour_mode) +{ + fb_data *dst, *dst_end; + const unsigned char *usrc; + const unsigned char *vsrc; + const unsigned char *ysrc; + int xphase; + int rc, gc, bc; + int y, u, v; + int red, green, blue; + unsigned rbits, gbits, bbits; + int count; + fb_data *dst_row; + +/******************* Center rotated image in screen *************************/ + if (width > LCD_HEIGHT) + width = LCD_HEIGHT; + if (width < LCD_HEIGHT) + _x = (LCD_HEIGHT - width)/2; + + if (height > LCD_WIDTH) + height = LCD_WIDTH; + if (height < LCD_WIDTH) + _y = (LCD_WIDTH - height)/2; +/************** end of Center rotated image in screen ***********************/ + + width = (width + 1) & ~1; + + dst = rb->lcd_framebuffer + _x * LCD_WIDTH + (LCD_WIDTH - _y) - 1; + dst_end = dst - (height - 1); + +/** black and white pict will crash the sim *****************************/ +#ifdef SIMULATOR + if (!csub_y) /* if not colour */ + { + rb->splash(HZ, "File not supported"); + }else{ +#endif + if (colour_mode == COLOURMODE_GRAY){ +#ifdef SIMULATOR + //rb->splash(HZ, "Grayscale not fully supported in simulator"); +#endif + csub_y = 0; + } + do + { + dst_row = dst; + count = width; + ysrc = src[0] + stride * src_y + src_x; + + /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ +/** Grayscale work around on simulator *****************/ +#ifdef SIMULATOR + if (csub_y == 0){ + usrc = src[1] + (stride/csub_x) * (csub_y) + + (src_x/csub_x); + vsrc = src[2] + (stride/csub_x) * (csub_y) + + (src_x/csub_x); + } + else + { +#endif + usrc = src[1] + (stride/csub_x) * (src_y/csub_y) + + (src_x/csub_x); + vsrc = src[2] + (stride/csub_x) * (src_y/csub_y) + + (src_x/csub_x); +#ifdef SIMULATOR + } +#endif + + xphase = src_x % csub_x; + + u = *usrc++ - 128; + v = *vsrc++ - 128; + rc = R_RVFAC * v + ROUNDOFFS; + gc = R_GVFAC * v + R_GUFAC * u + ROUNDOFFS; + bc = R_BUFAC * u + ROUNDOFFS; + + do + { + y = *ysrc++; + red = RYFAC * y + rc; + green = GYFAC * y + gc; + blue = BYFAC * y + bc; + + if ((unsigned)red > (RYFAC*255+ROUNDOFFS)) + { + if (red < 0) + { + red = 0; + } + else + { + red = (RYFAC*255+ROUNDOFFS); + } + } + if ((unsigned)green > (GYFAC*255+ROUNDOFFS)) + { + if (green < 0) + { + green = 0; + } + else + { + green = (GYFAC*255+ROUNDOFFS); + } + } + if ((unsigned)blue > (BYFAC*255+ROUNDOFFS)) + { + if (blue < 0) + { + blue = 0; + } + else + { + blue = (BYFAC*255+ROUNDOFFS); + } + } + rbits = ((unsigned)red) >> 16 ; + gbits = ((unsigned)green) >> 16 ; + bbits = ((unsigned)blue) >> 16 ; + + *dst_row = (rbits << 11) | (gbits << 5) | bbits; + + /* next pixel - since rotated, add WIDTH */ + dst_row += LCD_WIDTH; + + if (++xphase >= csub_x) + { + u = *usrc++ - 128; + v = *vsrc++ - 128; + rc = R_RVFAC * v + ROUNDOFFS; + gc = R_GVFAC * v + R_GUFAC * u + ROUNDOFFS; + bc = R_BUFAC * u + ROUNDOFFS; + xphase = 0; + } + } + while (--count); + + if (dst == dst_end) break; + dst--; + src_y++; + } + while(1); +#ifdef SIMULATOR + }/* if not colour */ +#endif +} + /** * Draw a partial YUV colour bitmap * @@ -256,120 +425,102 @@ void yuv_bitmap_part(unsigned char *src[3], int csub_x, int csub_y, int src_x, int src_y, int stride, int x, int y, int width, int height, - int colour_mode, int dither_mode) + int colour_mode, int dither_mode, int rotate_screen) { - fb_data *dst, *dst_end; - fb_data (*pixel_func)(void); - struct rgb_pixel px; + + if(rotate_screen) + { + rotate(src, csub_x, csub_y, + src_x, src_y, stride, + x, y, width, height, colour_mode); + } + else + { + fb_data *dst, *dst_end; + fb_data (*pixel_func)(void); + struct rgb_pixel px; - if (x + width > LCD_WIDTH) - width = LCD_WIDTH - x; /* Clip right */ - if (x < 0) - width += x, x = 0; /* Clip left */ - if (width <= 0) - return; /* nothing left to do */ + if (x + width > LCD_WIDTH) + width = LCD_WIDTH - x; /* Clip right */ + if (x < 0) + width += x, x = 0; /* Clip left */ + if (width <= 0) + return; /* nothing left to do */ - if (y + height > LCD_HEIGHT) - height = LCD_HEIGHT - y; /* Clip bottom */ - if (y < 0) - height += y, y = 0; /* Clip top */ - if (height <= 0) - return; /* nothing left to do */ + if (y + height > LCD_HEIGHT) + height = LCD_HEIGHT - y; /* Clip bottom */ + if (y < 0) + height += y, y = 0; /* Clip top */ + if (height <= 0) + return; /* nothing left to do */ - pixel = &px; + pixel = &px; - dst = rb->lcd_framebuffer + LCD_WIDTH * y + x; - dst_end = dst + LCD_WIDTH * height; + dst = rb->lcd_framebuffer + LCD_WIDTH * y + x; + dst_end = dst + LCD_WIDTH * height; - if (colour_mode == COLOURMODE_GRAY) - csub_y = 0; /* Ignore Cb, Cr */ + if (colour_mode == COLOURMODE_GRAY) + csub_y = 0; /* Ignore Cb, Cr */ - pixel_func = pixel_funcs[colour_mode] + pixel_func = pixel_funcs[colour_mode] [dither_mode]; - if (dither_mode == DITHER_DIFFUSION) - { - /* Reset error terms. */ - px.e = rgb_err_buffers; - px.ce[RED] = px.ce[GRN] = px.ce[BLU] = 0; - rb->memset(px.e, 0, 3*sizeof (struct rgb_err)); - } - - do - { - fb_data *dst_row, *row_end; - const unsigned char *ysrc; - px.inc = 1; - if (dither_mode == DITHER_DIFFUSION) { - /* Use R->L scan on odd lines */ - px.inc -= (src_y & 1) << 1; - px.epos = x + 1; - - if (px.inc < 0) - px.epos += width - 1; + /* Reset error terms. */ + px.e = rgb_err_buffers; + px.ce[RED] = px.ce[GRN] = px.ce[BLU] = 0; + rb->memset(px.e, 0, 3*sizeof (struct rgb_err)); } - if (px.inc == 1) + do { - /* Scan is L->R */ - dst_row = dst; - row_end = dst_row + width; - px.col = src_x; - } - else - { - /* Scan is R->L */ - row_end = dst - 1; - dst_row = row_end + width; - px.col = src_x + width - 1; - } + fb_data *dst_row, *row_end; + const unsigned char *ysrc; + px.inc = 1; - ysrc = src[0] + stride * src_y + px.col; - px.row = src_y; + if (dither_mode == DITHER_DIFFUSION) + { + /* Use R->L scan on odd lines */ + px.inc -= (src_y & 1) << 1; + px.epos = x + 1; - /* Do one row of pixels */ - if (csub_y) /* colour */ - { - /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ - const unsigned char *usrc, *vsrc; + if (px.inc < 0) + px.epos += width - 1; + } - usrc = src[1] + (stride/csub_x) * (src_y/csub_y) - + (px.col/csub_x); - vsrc = src[2] + (stride/csub_x) * (src_y/csub_y) - + (px.col/csub_x); - int xphase = px.col % csub_x; - int xphase_reset = px.inc * csub_x; - int y, v, u, rv, guv, bu; + if (px.inc == 1) + { + /* Scan is L->R */ + dst_row = dst; + row_end = dst_row + width; + px.col = src_x; + } + else + { + /* Scan is R->L */ + row_end = dst - 1; + dst_row = row_end + width; + px.col = src_x + width - 1; + } - v = *vsrc - 128; - vsrc += px.inc; - u = *usrc - 128; - usrc += px.inc; - rv = RVFAC*v; - guv = GUFAC*u + GVFAC*v; - bu = BUFAC*u; + ysrc = src[0] + stride * src_y + px.col; + px.row = src_y; - while (1) + /* Do one row of pixels */ + if (csub_y) /* colour */ { - y = YFAC*(*ysrc); - ysrc += px.inc; - px.r = y + rv; - px.g = y + guv; - px.b = y + bu; + /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ + const unsigned char *usrc, *vsrc; - *dst_row = pixel_func(); - dst_row += px.inc; + usrc = src[1] + (stride/csub_x) * (src_y/csub_y) + + (px.col/csub_x); + vsrc = src[2] + (stride/csub_x) * (src_y/csub_y) + + (px.col/csub_x); + int xphase = px.col % csub_x; + int xphase_reset = px.inc * csub_x; + int y, v, u, rv, guv, bu; - if (dst_row == row_end) - break; - - xphase += px.inc; - if ((unsigned)xphase < (unsigned)csub_x) - continue; - - /* fetch new chromas */ v = *vsrc - 128; vsrc += px.inc; u = *usrc - 128; @@ -378,24 +529,52 @@ guv = GUFAC*u + GVFAC*v; bu = BUFAC*u; - xphase -= xphase_reset; + while (1) + { + y = YFAC*(*ysrc); + ysrc += px.inc; + px.r = y + rv; + px.g = y + guv; + px.b = y + bu; + + *dst_row = pixel_func(); + dst_row += px.inc; + + if (dst_row == row_end) + break; + + xphase += px.inc; + if ((unsigned)xphase < (unsigned)csub_x) + continue; + + /* fetch new chromas */ + v = *vsrc - 128; + vsrc += px.inc; + u = *usrc - 128; + usrc += px.inc; + rv = RVFAC*v; + guv = GUFAC*u + GVFAC*v; + bu = BUFAC*u; + + xphase -= xphase_reset; + } } - } - else /* monochrome */ - { - do + else /* monochrome */ { - /* Set all components the same for dithering purposes */ - px.g = px.r = px.b = YFAC*(*ysrc); - *dst_row = pixel_func(); - ysrc += px.inc; - dst_row += px.inc; + do + { + /* Set all components the same for dithering purposes */ + px.g = px.r = px.b = YFAC*(*ysrc); + *dst_row = pixel_func(); + ysrc += px.inc; + dst_row += px.inc; + } + while (dst_row != row_end); } - while (dst_row != row_end); + + src_y++; + dst += LCD_WIDTH; } - - src_y++; - dst += LCD_WIDTH; + while (dst < dst_end); } - while (dst < dst_end); } Index: apps/plugins/jpeg/jpeg.c =================================================================== --- apps/plugins/jpeg/jpeg.c (revision 18858) +++ apps/plugins/jpeg/jpeg.c (working copy) @@ -79,8 +79,13 @@ const struct plugin_api* rb; MEM_FUNCTION_WRAPPERS(rb); +/* screenwidth/height for zoom in landscape mode */ +static int screenwidth = LCD_WIDTH; +static int screenheight = LCD_HEIGHT; +static int rotate_screen = false; /* rotate screen */ +static int auto_rotate_enabled = false; /* auto rotate screen */ static int slideshow_enabled = false; /* run slideshow */ -static int running_slideshow = false; /* loading image because of slideshw */ +static int running_slideshow = false; /* loading image because of slideshow */ #ifndef SIMULATOR static int immediate_ata_off = false; /* power down disk after loading */ #endif @@ -259,7 +264,7 @@ /* we "erase" the file name if we encounter * a non-supported file, so skip it now */ } - else /* DIR_NEXT/DIR_NONE */ + else if(direct == DIR_NEXT)/* DIR_NEXT */ { do { @@ -270,6 +275,11 @@ curfile++; }while(file_pt[curfile] == '\0' && count < entries); } + /* not required now maybe required later */ + /* else */ /* DIR_NONE */ + /* { */ + + /* } */ if(count == entries && file_pt[curfile] == '\0') { @@ -360,6 +370,8 @@ MIID_QUIT = 0, MIID_TOGGLE_SS_MODE, MIID_CHANGE_SS_MODE, + MIID_ROTATE, + MIID_AUTO_ROTATE_MODE, #if PLUGIN_BUFFER_SIZE >= MIN_MEM MIID_SHOW_PLAYBACK_MENU, #endif @@ -376,6 +388,10 @@ { "Toggle Slideshow Mode", NULL }, [MIID_CHANGE_SS_MODE] = { "Change Slideshow Time", NULL }, + [MIID_ROTATE] = + { "Toggle Portrait/Landscape view", NULL }, + [MIID_AUTO_ROTATE_MODE] = + { "Toggle Auto Rotate Mode", NULL }, #if PLUGIN_BUFFER_SIZE >= MIN_MEM [MIID_SHOW_PLAYBACK_MENU] = { "Show Playback Menu", NULL }, @@ -393,6 +409,12 @@ { "Enable", -1 }, }; + static const struct opt_items auto_rotate[2] = { + { "Disable", -1 }, + { "Enable", -1 }, + }; + + m = menu_init(rb, items, sizeof(items) / sizeof(*items), NULL, NULL, NULL, NULL); result=menu_show(m); @@ -403,6 +425,13 @@ menu_exit(m); return 1; break; + case MIID_ROTATE: + return 3; + break; + case MIID_AUTO_ROTATE_MODE: + rb->set_option("Toggle Auto Rotate", &auto_rotate_enabled, INT, + auto_rotate , 2, NULL); + break; case MIID_TOGGLE_SS_MODE: rb->set_option("Toggle Slideshow", &slideshow_enabled, INT, slideshow , 2, NULL); @@ -466,6 +495,7 @@ int scroll_bmp(struct t_disp* pdisp) { int lastbutton = 0; + int menu_return = 0; while (true) { @@ -495,7 +525,8 @@ pdisp->x, pdisp->y, pdisp->stride, 0, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */ move, MIN(LCD_HEIGHT, pdisp->height), /* w, h */ - jpeg_settings.colour_mode, jpeg_settings.dither_mode); + jpeg_settings.colour_mode, jpeg_settings.dither_mode, + rotate_screen); #else MYXLCD(gray_bitmap_part)( pdisp->bitmap[0], pdisp->x, pdisp->y, pdisp->stride, @@ -521,7 +552,8 @@ pdisp->x + LCD_WIDTH - move, pdisp->y, pdisp->stride, LCD_WIDTH - move, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */ move, MIN(LCD_HEIGHT, pdisp->height), /* w, h */ - jpeg_settings.colour_mode, jpeg_settings.dither_mode); + jpeg_settings.colour_mode, jpeg_settings.dither_mode, + rotate_screen); #else MYXLCD(gray_bitmap_part)( pdisp->bitmap[0], pdisp->x + LCD_WIDTH - move, @@ -553,7 +585,8 @@ pdisp->x, pdisp->y, pdisp->stride, MAX(0, (LCD_WIDTH-pdisp->width)/2), 0, /* x, y */ MIN(LCD_WIDTH, pdisp->width), move, /* w, h */ - jpeg_settings.colour_mode, jpeg_settings.dither_mode); + jpeg_settings.colour_mode, jpeg_settings.dither_mode, + rotate_screen); #else MYXLCD(gray_bitmap_part)( pdisp->bitmap[0], pdisp->x, pdisp->y, pdisp->stride, @@ -589,7 +622,8 @@ pdisp->y + LCD_HEIGHT - move, pdisp->stride, MAX(0, (LCD_WIDTH-pdisp->width)/2), LCD_HEIGHT - move, /* x, y */ MIN(LCD_WIDTH, pdisp->width), move, /* w, h */ - jpeg_settings.colour_mode, jpeg_settings.dither_mode); + jpeg_settings.colour_mode, jpeg_settings.dither_mode, + rotate_screen); if (jpeg_settings.dither_mode == DITHER_DIFFUSION) { @@ -655,6 +689,24 @@ #endif return ZOOM_OUT; break; + +#ifdef JPEG_ROTATE + case JPEG_ROTATE: + if (!rotate_screen) + { + rotate_screen = true; + screenwidth = LCD_HEIGHT; + screenheight = LCD_WIDTH; + } + else + { + rotate_screen = false; + screenwidth = LCD_WIDTH; + screenheight = LCD_HEIGHT; + } + return change_filename(DIR_NONE); + break; +#endif #ifdef JPEG_RC_MENU case JPEG_RC_MENU: #endif @@ -662,8 +714,45 @@ #ifdef USEGSLIB grey_show(false); /* switch off greyscale overlay */ #endif - if (show_menu() == 1) + menu_return = show_menu(); + if (menu_return == 1) + { return PLUGIN_OK; + } + if (menu_return == 3) + { + rb->lcd_clear_display(); + rb->lcd_puts(0,1,"Toggle Portrait/landscape"); + rb->lcd_puts(0,4,">> = Yes"); + rb->lcd_puts(0,5,"Any other = No"); + rb->lcd_update(); + button = rb->button_get(true); + switch(button) + { + case JPEG_RIGHT: + rb->lcd_clear_display(); + if (!rotate_screen) + { + rotate_screen = true; + screenwidth = LCD_HEIGHT; + screenheight = LCD_WIDTH; + } + else + { + rotate_screen = false; + screenwidth = LCD_WIDTH; + screenheight = LCD_HEIGHT; + } + rb->button_clear_queue(); + return change_filename(DIR_NONE); + break; + default: + rb->button_clear_queue(); + return change_filename(DIR_NONE); + break; + } + break; + } #ifdef USEGSLIB grey_show(true); /* switch on greyscale overlay */ @@ -675,7 +764,8 @@ MAX(0, (LCD_HEIGHT - pdisp->height) / 2), MIN(LCD_WIDTH, pdisp->width), MIN(LCD_HEIGHT, pdisp->height), - jpeg_settings.colour_mode, jpeg_settings.dither_mode); + jpeg_settings.colour_mode, jpeg_settings.dither_mode, + rotate_screen); MYLCD_UPDATE(); #endif break; @@ -700,17 +790,35 @@ rb->yield(); /* be nice to the other threads */ if(!running_slideshow) { - rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN],0, LCD_HEIGHT-8, LCD_WIDTH, 8, total, 0, + /* flip scroll bar when in landscape mode */ + if(rotate_screen){ + rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN], 0, 2, 4, LCD_HEIGHT-4, total, 0, + current, VERTICAL); + rb->lcd_update_rect(0, 2, 4, LCD_HEIGHT-4); + } + else + { + rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN],0, LCD_HEIGHT-4, LCD_WIDTH, 4, total, 0, current, HORIZONTAL); - rb->lcd_update_rect(0, LCD_HEIGHT-8, LCD_WIDTH, 8); + rb->lcd_update_rect(0, LCD_HEIGHT-4, LCD_WIDTH, 4); + } } #ifndef USEGSLIB else { /* in slideshow mode, keep gui interference to a minimum */ - rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN],0, LCD_HEIGHT-4, LCD_WIDTH, 4, total, 0, - current, HORIZONTAL); - rb->lcd_update_rect(0, LCD_HEIGHT-4, LCD_WIDTH, 4); + /* flip scroll bar when in landscape mode */ + if(rotate_screen){ + rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN], 0, 2, 2, LCD_HEIGHT-4, total, 0, + current, VERTICAL); + rb->lcd_update_rect(0, 2, 2, LCD_HEIGHT-4); + } + else + { + rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN],0, LCD_HEIGHT-4, LCD_WIDTH, 4, total, 0, + current, HORIZONTAL); + rb->lcd_update_rect(0, LCD_HEIGHT-4, LCD_WIDTH, 4); + } } #endif } @@ -753,8 +861,8 @@ { int downscale = 1; - while (downscale < 8 && (p_jpg->x_size > LCD_WIDTH*downscale - || p_jpg->y_size > LCD_HEIGHT*downscale)) + while (downscale < 8 && (p_jpg->x_size > screenwidth*downscale + || p_jpg->y_size > screenheight*downscale)) { downscale *= 2; } @@ -823,7 +931,7 @@ { rb->snprintf(print, sizeof(print), "decoding %d*%d", p_jpg->x_size/ds, p_jpg->y_size/ds); - rb->lcd_puts(0, 3, print); + rb->lcd_puts(2, 3, print); rb->lcd_update(); } @@ -867,12 +975,12 @@ int x, y; /* plain center to available width/height */ - x = cx - MIN(LCD_WIDTH, p_disp->width) / 2; - y = cy - MIN(LCD_HEIGHT, p_disp->height) / 2; + x = cx - MIN(screenwidth, p_disp->width) / 2; + y = cy - MIN(screenheight, p_disp->height) / 2; /* limit against upper image size */ - x = MIN(p_disp->width - LCD_WIDTH, x); - y = MIN(p_disp->height - LCD_HEIGHT, y); + x = MIN(p_disp->width - screenwidth, x); + y = MIN(p_disp->height - screenheight, y); /* limit against negative side */ x = MAX(0, x); @@ -886,8 +994,8 @@ /* calculate the view center based on the bitmap position */ void get_view(struct t_disp* p_disp, int* p_cx, int* p_cy) { - *p_cx = p_disp->x + MIN(LCD_WIDTH, p_disp->width) / 2; - *p_cy = p_disp->y + MIN(LCD_HEIGHT, p_disp->height) / 2; + *p_cx = p_disp->x + MIN(screenwidth, p_disp->width) / 2; + *p_cy = p_disp->y + MIN(screenheight, p_disp->height) / 2; } @@ -998,11 +1106,11 @@ rb->lcd_clear_display(); rb->snprintf(print, sizeof(print), "%s:", rb->strrchr(filename,'/')+1); - rb->lcd_puts(0, 0, print); + rb->lcd_puts(2, 0, print); rb->lcd_update(); rb->snprintf(print, sizeof(print), "loading %d bytes", filesize); - rb->lcd_puts(0, 1, print); + rb->lcd_puts(2, 1, print); rb->lcd_update(); } @@ -1012,7 +1120,7 @@ if(!running_slideshow) { rb->snprintf(print, sizeof(print), "decoding markers"); - rb->lcd_puts(0, 2, print); + rb->lcd_puts(2, 2, print); rb->lcd_update(); } #ifndef SIMULATOR @@ -1038,10 +1146,33 @@ default_huff_tbl(&jpg); /* use default */ build_lut(&jpg); /* derive Huffman and other lookup-tables */ + if(auto_rotate_enabled) + { + int lcd_diff, jpeg_diff; + + lcd_diff = LCD_HEIGHT - LCD_WIDTH; + jpeg_diff = jpg.y_size - jpg.x_size; + + if((jpeg_diff < 0 && lcd_diff > 0) || + (jpeg_diff > 0 && lcd_diff < 0)) + { + rotate_screen = true; + screenwidth = LCD_HEIGHT; + screenheight = LCD_WIDTH; + } + else + { + rotate_screen = false; + screenwidth = LCD_WIDTH; + screenheight = LCD_HEIGHT; + } + } + + if(!running_slideshow) { rb->snprintf(print, sizeof(print), "image %dx%d", jpg.x_size, jpg.y_size); - rb->lcd_puts(0, 2, print); + rb->lcd_puts(2, 2, print); rb->lcd_update(); } ds_max = max_downscale(&jpg); /* check display constraint */ @@ -1069,7 +1200,7 @@ { rb->snprintf(print, sizeof(print), "showing %dx%d", p_disp->width, p_disp->height); - rb->lcd_puts(0, 3, print); + rb->lcd_puts(2, 3, print); rb->lcd_update(); } MYLCD(clear_display)(); @@ -1077,18 +1208,19 @@ yuv_bitmap_part( p_disp->bitmap, p_disp->csub_x, p_disp->csub_y, p_disp->x, p_disp->y, p_disp->stride, - MAX(0, (LCD_WIDTH - p_disp->width) / 2), - MAX(0, (LCD_HEIGHT - p_disp->height) / 2), - MIN(LCD_WIDTH, p_disp->width), - MIN(LCD_HEIGHT, p_disp->height), - jpeg_settings.colour_mode, jpeg_settings.dither_mode); + MAX(0, (screenwidth - p_disp->width) / 2), + MAX(0, (screenheight - p_disp->height) / 2), + MIN(screenwidth, p_disp->width), + MIN(screenheight, p_disp->height), + jpeg_settings.colour_mode, jpeg_settings.dither_mode, + rotate_screen); #else MYXLCD(gray_bitmap_part)( p_disp->bitmap[0], p_disp->x, p_disp->y, p_disp->stride, - MAX(0, (LCD_WIDTH - p_disp->width) / 2), - MAX(0, (LCD_HEIGHT - p_disp->height) / 2), - MIN(LCD_WIDTH, p_disp->width), - MIN(LCD_HEIGHT, p_disp->height)); + MAX(0, (screenwidth - p_disp->width) / 2), + MAX(0, (screenheight - p_disp->height) / 2), + MIN(screenwidth, p_disp->width), + MIN(screenheight, p_disp->height)); #endif MYLCD_UPDATE(); @@ -1182,7 +1314,7 @@ #ifdef USEGSLIB if (!grey_init(rb, buf, buf_size, GREY_ON_COP, - LCD_WIDTH, LCD_HEIGHT, &greysize)) + screenwidth, screenheight, &greysize)) { rb->splash(HZ, "grey buf error"); return PLUGIN_ERROR; Index: apps/plugins/jpeg/yuv2rgb.h =================================================================== --- apps/plugins/jpeg/yuv2rgb.h (revision 18858) +++ apps/plugins/jpeg/yuv2rgb.h (working copy) @@ -46,6 +46,6 @@ void yuv_bitmap_part(unsigned char *src[3], int csub_x, int csub_y, int src_x, int src_y, int stride, int x, int y, int width, int height, - int colour_mode, int dither_mode); - + int colour_mode, int dither_mode, + int rotate_screen); #endif Index: apps/plugins/jpeg/jpeg.h =================================================================== --- apps/plugins/jpeg/jpeg.h (revision 18858) +++ apps/plugins/jpeg/jpeg.h (working copy) @@ -115,6 +115,7 @@ #define JPEG_LEFT BUTTON_LEFT #define JPEG_RIGHT BUTTON_RIGHT #define JPEG_MENU BUTTON_MENU +#define JPEG_ROTATE BUTTON_POWER #define JPEG_NEXT (BUTTON_A | BUTTON_RIGHT) #define JPEG_PREVIOUS (BUTTON_A | BUTTON_LEFT) Index: apps/plugins/jpeg/jpeg_decoder.c =================================================================== --- apps/plugins/jpeg/jpeg_decoder.c (revision 18858) +++ apps/plugins/jpeg/jpeg_decoder.c (working copy) @@ -7,8 +7,7 @@ * \/ \/ \/ \/ \/ * $Id$ * -* JPEG image viewer -* (This is a real mess if it has to be coded in one single C file) +* JPEG Decoder * * File scrolling addition (C) 2005 Alexander Spyridakis * Copyright (C) 2004 Jörg Hohensohn aka [IDC]Dragon Index: apps/plugins/pictureflow.c =================================================================== --- apps/plugins/pictureflow.c (revision 18858) +++ apps/plugins/pictureflow.c (working copy) @@ -634,7 +634,7 @@ continue; input_bmp.data = (char *)input_bmp_buffer; - ret = rb->read_bmp_file(tmp_path_name, &input_bmp, + ret = rb->read_bmp_file(tmp_path_name, noresize(&input_bmp), sizeof(fb_data)*MAX_IMG_WIDTH*MAX_IMG_HEIGHT, FORMAT_NATIVE); if (ret <= 0) { Index: apps/plugins/rockpaint.c =================================================================== --- apps/plugins/rockpaint.c (revision 18858) +++ apps/plugins/rockpaint.c (working copy) @@ -2956,7 +2956,7 @@ int l; bm.data = (char*)save_buffer; - ret = rb->read_bmp_file( file, &bm, ROWS*COLS*sizeof( fb_data ), + ret = rb->read_bmp_file( file, noresize(&bm), ROWS*COLS*sizeof( fb_data ), FORMAT_NATIVE ); if((bm.width > COLS ) || ( bm.height > ROWS )) Index: apps/gui/backdrop.c =================================================================== --- apps/gui/backdrop.c (revision 18858) +++ apps/gui/backdrop.c (working copy) @@ -51,7 +51,7 @@ /* load the image */ bm.data=(char*)backdrop_buffer; - ret = read_bmp_file(filename, &bm, sizeof(main_backdrop), + ret = read_bmp_file(filename, noresize(&bm), sizeof(main_backdrop), FORMAT_NATIVE | FORMAT_DITHER); if ((ret > 0) && (bm.width == LCD_WIDTH) && (bm.height == LCD_HEIGHT)) @@ -113,7 +113,7 @@ /* load the image */ bm.data=(char*)backdrop_buffer; - ret = read_bmp_file(filename, &bm, sizeof(main_backdrop), + ret = read_bmp_file(filename, noresize(&bm), sizeof(main_backdrop), FORMAT_NATIVE | FORMAT_DITHER | FORMAT_REMOTE); if ((ret > 0) && (bm.width == LCD_REMOTE_WIDTH) && (bm.height == LCD_REMOTE_HEIGHT)) Index: apps/gui/gwps.h =================================================================== --- apps/gui/gwps.h (revision 18858) +++ apps/gui/gwps.h (working copy) @@ -47,13 +47,11 @@ #define WPS_ALBUMART_CHECK 1 /* WPS contains AA conditional tag */ #define WPS_ALBUMART_LOAD 2 /* WPS contains AA tag */ -#define WPS_ALBUMART_ALIGN_RIGHT WPS_ALIGN_RIGHT /* x align: right */ -#define WPS_ALBUMART_ALIGN_CENTER WPS_ALIGN_CENTER /* x/y align: center */ -#define WPS_ALBUMART_ALIGN_LEFT WPS_ALIGN_LEFT /* x align: left */ -#define WPS_ALBUMART_ALIGN_TOP WPS_ALIGN_RIGHT /* y align: top */ -#define WPS_ALBUMART_ALIGN_BOTTOM WPS_ALIGN_LEFT /* y align: bottom */ -#define WPS_ALBUMART_INCREASE 8 /* increase if smaller */ -#define WPS_ALBUMART_DECREASE 16 /* decrease if larger */ +#define WPS_ALBUMART_ALIGN_RIGHT 1 /* x align: right */ +#define WPS_ALBUMART_ALIGN_CENTER 2 /* x/y align: center */ +#define WPS_ALBUMART_ALIGN_LEFT 4 /* x align: left */ +#define WPS_ALBUMART_ALIGN_TOP 1 /* y align: top */ +#define WPS_ALBUMART_ALIGN_BOTTOM 4 /* y align: bottom */ #endif /* HAVE_ALBUMART */ @@ -382,10 +380,8 @@ unsigned char wps_uses_albumart; /* WPS_ALBUMART_NONE, _CHECK, _LOAD */ short albumart_x; short albumart_y; - unsigned short albumart_xalign; /* WPS_ALBUMART_ALIGN_LEFT, _CENTER, _RIGHT, - + .._INCREASE, + .._DECREASE */ - unsigned short albumart_yalign; /* WPS_ALBUMART_ALIGN_TOP, _CENTER, _BOTTOM, - + .._INCREASE, + .._DECREASE */ + unsigned char albumart_xalign; /* WPS_ALBUMART_ALIGN_LEFT, _CENTER, _RIGHT */ + unsigned char albumart_yalign; /* WPS_ALBUMART_ALIGN_TOP, _CENTER, _BOTTOM */ short albumart_max_width; short albumart_max_height; Index: apps/gui/wps_parser.c =================================================================== --- apps/gui/wps_parser.c (revision 18858) +++ apps/gui/wps_parser.c (working copy) @@ -409,7 +409,7 @@ #endif format = FORMAT_ANY|FORMAT_TRANSPARENT; - int ret = read_bmp_file(filename, bm, + int ret = read_bmp_file(filename, noresize(bm), wps_data->img_buf_free, format); @@ -911,13 +911,6 @@ { const char *_pos, *newline; bool parsing; - const short xalign_mask = WPS_ALBUMART_ALIGN_LEFT | - WPS_ALBUMART_ALIGN_CENTER | - WPS_ALBUMART_ALIGN_RIGHT; - const short yalign_mask = WPS_ALBUMART_ALIGN_TOP | - WPS_ALBUMART_ALIGN_CENTER | - WPS_ALBUMART_ALIGN_BOTTOM; - (void)token; /* silence warning */ /* reset albumart info in wps */ @@ -927,7 +920,7 @@ wps_data->albumart_xalign = WPS_ALBUMART_ALIGN_CENTER; /* default */ wps_data->albumart_yalign = WPS_ALBUMART_ALIGN_CENTER; /* default */ - /* format: %Cl|x|y|[[l|c|r][d|i|s]mwidth]|[[t|c|b][d|i|s]mheight]| */ + /* format: %Cl|x|y|[[l|c|r]mwidth]|[[t|c|b]mheight]| */ newline = strchr(wps_bufptr, '\n'); @@ -962,35 +955,24 @@ case 'l': case 'L': case '+': - wps_data->albumart_xalign = - (wps_data->albumart_xalign & xalign_mask) | - WPS_ALBUMART_ALIGN_LEFT; + wps_data->albumart_xalign = WPS_ALBUMART_ALIGN_LEFT; break; case 'c': case 'C': - wps_data->albumart_xalign = - (wps_data->albumart_xalign & xalign_mask) | - WPS_ALBUMART_ALIGN_CENTER; + wps_data->albumart_xalign = WPS_ALBUMART_ALIGN_CENTER; break; case 'r': case 'R': case '-': - wps_data->albumart_xalign = - (wps_data->albumart_xalign & xalign_mask) | - WPS_ALBUMART_ALIGN_RIGHT; + wps_data->albumart_xalign = WPS_ALBUMART_ALIGN_RIGHT; break; case 'd': case 'D': - wps_data->albumart_xalign |= WPS_ALBUMART_DECREASE; - break; case 'i': case 'I': - wps_data->albumart_xalign |= WPS_ALBUMART_INCREASE; - break; case 's': case 'S': - wps_data->albumart_xalign |= - (WPS_ALBUMART_DECREASE | WPS_ALBUMART_INCREASE); + /* simply ignored */ break; default: parsing = false; @@ -1022,35 +1004,24 @@ case 't': case 'T': case '-': - wps_data->albumart_yalign = - (wps_data->albumart_yalign & yalign_mask) | - WPS_ALBUMART_ALIGN_TOP; + wps_data->albumart_yalign = WPS_ALBUMART_ALIGN_TOP; break; case 'c': case 'C': - wps_data->albumart_yalign = - (wps_data->albumart_yalign & yalign_mask) | - WPS_ALBUMART_ALIGN_CENTER; + wps_data->albumart_yalign = WPS_ALBUMART_ALIGN_CENTER; break; case 'b': case 'B': case '+': - wps_data->albumart_yalign = - (wps_data->albumart_yalign & yalign_mask) | - WPS_ALBUMART_ALIGN_BOTTOM; + wps_data->albumart_yalign = WPS_ALBUMART_ALIGN_BOTTOM; break; case 'd': case 'D': - wps_data->albumart_yalign |= WPS_ALBUMART_DECREASE; - break; case 'i': case 'I': - wps_data->albumart_yalign |= WPS_ALBUMART_INCREASE; - break; case 's': case 'S': - wps_data->albumart_yalign |= - (WPS_ALBUMART_DECREASE | WPS_ALBUMART_INCREASE); + /* simply ignored */ break; default: parsing = false; Index: apps/gui/icon.c =================================================================== --- apps/gui/icon.c (revision 18858) +++ apps/gui/icon.c (working copy) @@ -222,7 +222,7 @@ 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, noresize(bmp), IMG_BUFSIZE, bmpformat); if (size_read > 0) { *loaded_ok = true; Index: apps/buffering.c =================================================================== --- apps/buffering.c (revision 18858) +++ apps/buffering.c (working copy) @@ -52,6 +52,9 @@ #include "bmp.h" #include "appevents.h" #include "metadata.h" +#ifdef HAVE_ALBUMART +#include "albumart.h" +#endif #if MEM > 1 #define GUARD_BUFSIZE (32*1024) @@ -852,7 +855,11 @@ bmp->maskdata = NULL; #endif - int free = (int)MIN(buffer_len - BUF_USED, buffer_len - buf_widx); + int free = (int)MIN(buffer_len - BUF_USED, buffer_len - buf_widx) + - sizeof(struct bitmap); + + get_albumart_size(bmp); + rc = read_bmp_fd(fd, bmp, free, FORMAT_ANY|FORMAT_DITHER); return rc + (rc > 0 ? sizeof(struct bitmap) : 0); } Index: firmware/export/config-ipodmini.h =================================================================== --- firmware/export/config-ipodmini.h (revision 18858) +++ firmware/export/config-ipodmini.h (working copy) @@ -158,6 +158,8 @@ #define CONFIG_USBOTG USBOTG_ARC /* enable these for the experimental usb stack */ +#define USE_ROCKBOX_USB +#define USE_HIGH_SPEED #define HAVE_USBSTACK #define USB_VENDOR_ID 0x05ac #define USB_PRODUCT_ID 0x1205 Index: firmware/export/lcd.h =================================================================== --- firmware/export/lcd.h (revision 18858) +++ firmware/export/lcd.h (working copy) @@ -378,6 +378,15 @@ unsigned char *data; }; +static inline struct bitmap* noresize(struct bitmap *bm) +{ + /* no resize */ + bm->width = 0; + bm->height = 0; + + return bm; +} + extern void lcd_set_invert_display(bool yesno); #ifdef HAVE_BACKLIGHT_INVERSION extern void lcd_set_backlight_inversion(bool yesno); Index: firmware/target/arm/s3c2440/gigabeat-fx/button-meg-fx.c =================================================================== --- firmware/target/arm/s3c2440/gigabeat-fx/button-meg-fx.c (revision 18858) +++ firmware/target/arm/s3c2440/gigabeat-fx/button-meg-fx.c (working copy) @@ -156,6 +156,18 @@ buttonlight_on(); } + /* the cradle buttons */ + buttons = ~GPFDAT & 0xc0; + if (buttons) + { + if (buttons & (1 << 6)) + btn |= BUTTON_A; + + if (buttons & (1 << 7)) + btn |= BUTTON_POWER; + buttonlight_on(); + } + return btn; }