Index: apps/recorder/bmp.c =================================================================== --- apps/recorder/bmp.c (revision 16267) +++ apps/recorder/bmp.c (working copy) @@ -162,6 +162,32 @@ int read_bmp_file(const char* filename, return ret; } +int get_bmp_size(int fd, struct bitmap *bmp) +{ + struct bmp_header bmph; + + int ret = read(fd, &bmph, sizeof(struct bmp_header)); + if (ret < 0) { + return ret * 10 - 2; + } + + if (ret != sizeof(struct bmp_header)) { + DEBUGF("get_bmp_size: can't read BMP header."); + return -3; + } + + bmp->width = readlong(&bmph.width); + bmp->height = readlong(&bmph.height); + + /* Top-down BMP file */ + if (bmp->height < 0) + bmp->height = -bmp->height; + + lseek(fd, -ret, SEEK_CUR); + + return bmp->width * bmp->height * sizeof(fb_data); +} + /****************************************************************************** * read_bmp_fd() * Index: apps/recorder/bmp.h =================================================================== --- apps/recorder/bmp.h (revision 16267) +++ apps/recorder/bmp.h (working copy) @@ -39,4 +39,8 @@ int read_bmp_fd(int fd, struct bitmap *bm, int maxsize, int format); + +int get_bmp_size(int fd, + struct bitmap *bmp); + #endif Index: apps/recorder/albumart.c =================================================================== --- apps/recorder/albumart.c (revision 16267) +++ apps/recorder/albumart.c (working copy) @@ -29,6 +29,7 @@ #include "misc.h" #include "settings.h" +#define SCALE 1000 /* Strip filename from a full path * @@ -292,3 +293,50 @@ void draw_album_art(struct gui_wps *gwps gwps->display->set_drawmode(DRMODE_SOLID); } } + +int get_albumart_size(struct bitmap *dst_bmp, struct bitmap *src_bmp) +{ + struct wps_data *data = gui_wps[0].data; + short aa_max_width = data->albumart_max_width; + short aa_max_height = data->albumart_max_height; + const unsigned short aa_xalign = data->albumart_xalign; + const unsigned short aa_yalign = data->albumart_yalign; + const short width = src_bmp->width; + const short height = src_bmp->height; + + dst_bmp->width = width; + dst_bmp->height = height; + + if (aa_max_width == 0) + aa_max_width = width; + if (aa_max_height == 0) + aa_max_height = height; + + if (((aa_xalign & WPS_ALBUMART_DECREASE) && (aa_max_width < width)) || + ((aa_xalign & WPS_ALBUMART_INCREASE) && (aa_max_width > width)) || + ((aa_yalign & WPS_ALBUMART_DECREASE) && (aa_max_height < height)) || + ((aa_yalign & WPS_ALBUMART_INCREASE) && (aa_max_height > height))) + { + const unsigned long factx = aa_max_width * SCALE / width; + const unsigned long facty = aa_max_height * SCALE / height; + + /* resize image */ + if (factx == facty) + { + dst_bmp->width = aa_max_width; + dst_bmp->height = aa_max_height; + } + else if (factx < facty) + { + dst_bmp->width = aa_max_width; + dst_bmp->height = (height * factx + SCALE/2) / SCALE; + } + else + { + dst_bmp->width = (width * facty + SCALE/2) / SCALE; + dst_bmp->height = aa_max_height; + } + } + + return dst_bmp->width * dst_bmp->height * sizeof(fb_data); +} Index: apps/recorder/albumart.h =================================================================== --- apps/recorder/albumart.h (revision 16267) +++ apps/recorder/albumart.h (working copy) @@ -38,6 +38,8 @@ void draw_album_art(struct gui_wps *gwps bool search_albumart_files(const struct mp3entry *id3, const char *size_string, char *buf, int buflen); +int get_albumart_size(struct bitmap *dst_bmp, struct bitmap *src_bmp); + #endif /* HAVE_ALBUMART */ #endif /* _ALBUMART_H_ */ Index: apps/gui/gwps.c =================================================================== --- apps/gui/gwps.c (revision 16267) +++ apps/gui/gwps.c (working copy) @@ -779,6 +779,7 @@ void gui_sync_wps_screen_init(void) void gui_sync_wps_init(void) { int i; + aa_mutex_init(&img_buf_mutex); FOR_NB_SCREENS(i) { wps_data_init(&wps_datas[i]); Index: apps/gui/gwps.h =================================================================== --- apps/gui/gwps.h (revision 16267) +++ apps/gui/gwps.h (working copy) @@ -462,6 +462,14 @@ void gui_sync_wps_screen_init(void); #ifdef HAVE_ALBUMART /* gives back if WPS contains an albumart tag */ bool gui_sync_wps_uses_albumart(void); +extern struct mutex img_buf_mutex; +#define aa_mutex_lock(mutex) mutex_lock(mutex) +#define aa_mutex_unlock(mutex) mutex_unlock(mutex) +#define aa_mutex_init(mutex) mutex_init(mutex) +#else +#define aa_mutex_lock(mutex) do { } while (0) +#define aa_mutex_unlock(mutex) do { } while (0) +#define aa_mutex_init(mutex) do { } while (0) #endif #endif Index: apps/gui/wps_parser.c =================================================================== --- apps/gui/wps_parser.c (revision 16267) +++ apps/gui/wps_parser.c (working copy) @@ -66,6 +66,10 @@ static int numoptions[WPS_MAX_COND_LEVEL /* the current line in the file */ static int line; +#ifdef HAVE_ALBUMART +struct mutex img_buf_mutex; +#endif + #ifdef HAVE_LCD_BITMAP #if LCD_DEPTH > 1 @@ -1198,8 +1202,10 @@ void wps_data_init(struct wps_data *wps_ wps_images_clear(wps_data); wps_data->wps_sb_tag = false; wps_data->show_sb_on_wps = false; + aa_mutex_lock(&img_buf_mutex); wps_data->img_buf_ptr = wps_data->img_buf; /* where in image buffer */ wps_data->img_buf_free = IMG_BUFSIZE; /* free space in image buffer */ + aa_mutex_unlock(&img_buf_mutex); wps_data->peak_meter_enabled = false; #else /* HAVE_LCD_CHARCELLS */ int i; @@ -1263,12 +1269,14 @@ static void load_wps_bitmaps(struct wps_ loaded = &wps_data->img[n].loaded; } + aa_mutex_lock(&img_buf_mutex); /* load the image */ bitmap->data = wps_data->img_buf_ptr; if (load_bitmap(wps_data, img_path, bitmap)) { *loaded = true; } + aa_mutex_unlock(&img_buf_mutex); } } Index: apps/SOURCES =================================================================== --- apps/SOURCES (revision 16267) +++ apps/SOURCES (working copy) @@ -78,6 +78,7 @@ recorder/keyboard.c recorder/peakmeter.c #ifdef HAVE_ALBUMART recorder/albumart.c +plugins/lib/bmp_smooth_scale.c #endif #ifdef HAVE_LCD_COLOR gui/color_picker.c Index: apps/buffering.c =================================================================== --- apps/buffering.c (revision 16267) +++ apps/buffering.c (working copy) @@ -49,6 +49,8 @@ #include "pcmbuf.h" #include "buffer.h" #include "bmp.h" +#include "albumart.h" +#include "plugins/lib/bmp.h" #ifdef SIMULATOR #define ata_disk_is_active() 1 @@ -831,16 +833,66 @@ static bool fill_buffer(void) static int load_bitmap(const int fd) { int rc; - struct bitmap *bmp = (struct bitmap *)&buffer[buf_widx]; + struct bitmap *bmp, orig_bmp; + int free, tmp; + + tmp = get_bmp_size(fd, &orig_bmp); + + if (tmp < 0) + return tmp; + + bmp = (struct bitmap *)&buffer[buf_widx]; + free = (int)MIN(buffer_len - BUF_USED, buffer_len - buf_widx) + - sizeof(struct bitmap); + + rc = get_albumart_size(bmp, &orig_bmp); + + if (rc > free) + return 0; + /* FIXME: alignment may be needed for the data buffer. */ bmp->data = &buffer[buf_widx + sizeof(struct bitmap)]; + if (bmp->width == orig_bmp.width && bmp->height == orig_bmp.height) + { +#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) + bmp->maskdata = NULL; +#endif + rc = read_bmp_fd(fd, bmp, free, FORMAT_ANY|FORMAT_DITHER); + } + else + { + struct wps_data *data = gui_wps[0].data; #if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) - bmp->maskdata = NULL; + orig_bmp.maskdata = NULL; #endif + aa_mutex_lock(&img_buf_mutex); + int wps_free = data->img_buf_free; + orig_bmp.data = data->img_buf_ptr; + + tmp = read_bmp_fd(fd, &orig_bmp, wps_free, FORMAT_ANY|FORMAT_DITHER); + + if (tmp <= 0) + { + aa_mutex_unlock(&img_buf_mutex); + return tmp; + } + + data->img_buf_free -= tmp; + data->img_buf_ptr += tmp; + +#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) + bmp->format = orig_bmp.format; + bmp->maskdata = orig_bmp.maskdata; +#endif + + smooth_resize_bitmap(&orig_bmp, bmp); + + data->img_buf_ptr -= tmp; + data->img_buf_free += tmp; + aa_mutex_unlock(&img_buf_mutex); + } - int free = (int)MIN(buffer_len - BUF_USED, buffer_len - buf_widx); - rc = read_bmp_fd(fd, bmp, free, FORMAT_ANY|FORMAT_DITHER); return rc + (rc > 0 ? sizeof(struct bitmap) : 0); } #endif