diff -upNr -X dontdiff ../../tmp/rockbox/apps/gui/gwps-common.c ./apps/gui/gwps-common.c
--- ../../tmp/rockbox/apps/gui/gwps-common.c	2007-04-17 16:08:34.000000000 +0900
+++ ./apps/gui/gwps-common.c	2007-04-17 16:09:07.000000000 +0900
@@ -596,7 +596,12 @@ static bool wps_data_albumart_load(struc
     int rc;
     struct bitmap temp_bitmap;
     temp_bitmap.data = data->img_buf_ptr;
-    rc = read_bmp_file(gwps->state->id3->albumart_path, &temp_bitmap, data->img_buf_free, FORMAT_ANY|FORMAT_TRANSPARENT);
+    rc = read_bmp_file(gwps->state->id3->albumart_path, 
+			&temp_bitmap, data->img_buf_free, 
+			FORMAT_ANY|FORMAT_TRANSPARENT,
+			gui_wps->data->albumart_max_width, gui_wps->data->albumart_max_height,
+			BMP_RESIZE_INCREASE | BMP_RESIZE_DECREASE);
+
     if(rc <= 0)
     {
         /* load failed */
diff -upNr -X dontdiff ../../tmp/rockbox/apps/gui/icon.c ./apps/gui/icon.c
--- ../../tmp/rockbox/apps/gui/icon.c	2007-04-17 16:08:21.000000000 +0900
+++ ./apps/gui/icon.c	2007-04-17 16:10:09.000000000 +0900
@@ -230,7 +230,9 @@ static void load_icons(const char* filen
         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 -upNr -X dontdiff ../../tmp/rockbox/apps/gui/wps_parser.c ./apps/gui/wps_parser.c
--- ../../tmp/rockbox/apps/gui/wps_parser.c	2007-04-17 16:08:34.000000000 +0900
+++ ./apps/gui/wps_parser.c	2007-04-17 16:09:07.000000000 +0900
@@ -328,7 +328,9 @@ static bool load_bitmap(struct wps_data 
 {
     int ret = read_bmp_file(filename, bm,
                             wps_data->img_buf_free,
-                            format);
+                            format,
+			    0,0,
+			    BMP_RESIZE_NONE);
 
     if (ret > 0)
     {
diff -upNr -X dontdiff ../../tmp/rockbox/apps/plugin.h ./apps/plugin.h
--- ../../tmp/rockbox/apps/plugin.h	2007-04-17 01:54:46.000000000 +0900
+++ ./apps/plugin.h	2007-04-17 16:09:07.000000000 +0900
@@ -578,7 +578,10 @@ struct plugin_api {
 #endif
 #ifdef HAVE_LCD_BITMAP
     int (*read_bmp_file)(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 -upNr -X dontdiff ../../tmp/rockbox/apps/plugins/lib/bmp.h ./apps/plugins/lib/bmp.h
--- ../../tmp/rockbox/apps/plugins/lib/bmp.h	2007-04-05 21:50:35.000000000 +0900
+++ ./apps/plugins/lib/bmp.h	2007-04-17 16:09:07.000000000 +0900
@@ -21,6 +21,7 @@
 
 #include "lcd.h"
 #include "plugin.h"
+#include "recorder/bmp.h"
 
 /**
  * Save bitmap to file
diff -upNr -X dontdiff ../../tmp/rockbox/apps/plugins/rockpaint.c ./apps/plugins/rockpaint.c
--- ../../tmp/rockbox/apps/plugins/rockpaint.c	2007-04-05 21:50:35.000000000 +0900
+++ ./apps/plugins/rockpaint.c	2007-04-17 16:09:07.000000000 +0900
@@ -2905,7 +2905,9 @@ static int load_bitmap( char *file )
 
     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 -upNr -X dontdiff ../../tmp/rockbox/apps/gui/backdrop.c ./apps/gui/backdrop.c
--- ../../tmp/rockbox/apps/gui/backdrop.c	2007-04-05 21:50:34.000000000 +0900
+++ ./apps/gui/backdrop.c	2007-04-17 16:09:07.000000000 +0900
@@ -47,7 +47,9 @@ static bool load_backdrop(char* filename
     /* 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))
     {
diff -upNr -X dontdiff ../../tmp/rockbox/apps/recorder/bmp.c ./apps/recorder/bmp.c
--- ../../tmp/rockbox/apps/recorder/bmp.c	2007-04-17 01:54:40.000000000 +0900
+++ ./apps/recorder/bmp.c	2007-04-17 16:09:07.000000000 +0900
@@ -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 @@ union rgb_union {
     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 */
@@ -130,39 +137,100 @@ static inline uint32_t readlong(uint32_t
     return (uint32_t)bytes[0] | ((uint32_t)bytes[1] << 8) |
            ((uint32_t)bytes[2] << 16) | ((uint32_t)bytes[3] << 24);
 }
-                            
+
 static inline unsigned brightness(union rgb_union color)
 {
     return (3 * (unsigned)color.red + 6 * (unsigned)color.green
               + (unsigned)color.blue) / 10;
 }
 
+
+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)
+{
+#if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
+	bool remote = format & FORMAT_REMOTE;
+	format &= ~FORMAT_REMOTE;
+#endif
+	
+#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
+	if (format == FORMAT_NATIVE) {
+# if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
+		if (remote) {
+#  if (LCD_REMOTE_DEPTH == 2) && (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED)
+			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
+#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);
+	}
+}
+
 /******************************************************************************
  * read_bmp_file()
  *
  * Reads a BMP file and puts the data in rockbox format in *bitmap.
  *
  *****************************************************************************/
-int read_bmp_file(char* filename,
+int read_bmp_fd(  int fd,
                   struct bitmap *bm,
                   int maxsize,
-                  int format)
+                  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 fd, row, col, ret;
+    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;
 
     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
@@ -182,41 +250,133 @@ int read_bmp_file(char* filename,
     }
 #else
 
-    (void)format;
+    format = FORMAT_MONO;
 #endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */
 
-    fd = open(filename, O_RDONLY);
-
-    /* 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;
-    }
-
     /* read fileheader */
     ret = read(fd, &bmph, sizeof(struct bmp_header));
     if (ret < 0) {
-        close(fd);
         return ret * 10 - 2;
     }
 
     if (ret != sizeof(struct bmp_header)) {
         DEBUGF("read_bmp_file: can't read BMP header.");
-        close(fd);
         return -3;
     }
 
-    width = readlong(&bmph.width);
-    if (width > LCD_WIDTH) {
-        DEBUGF("read_bmp_file: Bitmap too wide (%d pixels, max is %d)\n",
-                        width, LCD_WIDTH);
-        close(fd);
+    /* check bitmap file signature */
+    if (readshort(&bmph.type)!=0x4d42) {
+        DEBUGF("read_bmp_file: 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_file: Bitmap is too wide (%d pixels, max is %d)\n",
+               src_w, MAX_WIDTH);
         return -4;
     }
 
-    height = readlong(&bmph.height);
+    /* 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);
+                              if ((fact < FACT_SCALE && (flags & BMP_RESIZE_DECREASE)) || /* decrease allowed */
+                                      (fact > FACT_SCALE && (flags & BMP_RESIZE_INCREASE)))   /* increase allowed */
+                                      fact_w = fact;
+                      }
+
+                      if (dst_h > 0) {
+                              fact = (src_h * FACT_SCALE) / (dst_h + decrement_y);
+                              if ((fact < FACT_SCALE && (flags & BMP_RESIZE_DECREASE)) || /* decrease allowed */
+                                      (fact > FACT_SCALE && (flags & BMP_RESIZE_INCREASE)))   /* increase allowed */
+                                      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;
+                              if (fact_w <= 0 || fact_h <= 0) {
+                                      /* don't resize */
+                                      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_file: 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_file: 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) {
@@ -226,50 +386,44 @@ int read_bmp_file(char* filename,
             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_file: Bitmap too large for buffer: "
-               "%d bytes.\n", totalsize);
-        close(fd);
+        DEBUGF("read_bmp_file: 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;
     }
 
@@ -280,13 +434,12 @@ int read_bmp_file(char* filename,
             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))
         {
             DEBUGF("read_bmp_file: Can't read color palette\n");
-            close(fd);
             return -7;
         }
     }
@@ -322,7 +475,6 @@ int read_bmp_file(char* filename,
         if (compression != 0) { /* not BI_RGB */
             DEBUGF("read_bmp_file: Unsupported compression (type %d)\n",
                    compression);
-            close(fd);
             return -8;
         }
         break;
@@ -333,32 +485,54 @@ int read_bmp_file(char* filename,
 
     memset(bitmap, 0, totalsize);
 
-    /* loop to read rows and put them to buffer */
-    for (row = height - 1; row >= 0; row--) {
-        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_file: error reading image, read returned: %d "
-                   "expected: %d\n", ret, padded_width);
-            close(fd);
+                   "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)
@@ -368,25 +542,25 @@ int read_bmp_file(char* filename,
             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;
 
@@ -432,7 +606,7 @@ int read_bmp_file(char* filename,
             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);
@@ -444,101 +618,56 @@ int read_bmp_file(char* filename,
           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 */
-            {
-#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;
-                }
-#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;
-                    }
-                }
-                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;
-        }
+        /* Convert to destination format */
+		while (--num_rows>=0) {
+			 int src_col, dst_x;
+			 if (fact_w >= FACT_SCALE)
+			 {	/* 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 /*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++;
+					 }
+				 }
+			 }
+			 dst_y++;
+		}
     }
 
-    close(fd);
+    DEBUGF("read_bmp_file: totalsize=%d, width=%d, height=%d depth=%d compression=%d numcolors=%d\n", 
+				totalsize, dst_w, dst_h, depth, compression, numcolors);
 
-    DEBUGF("totalsize: %d\n", totalsize);
     return totalsize; /* return the used buffer size. */
 }
+
+int read_bmp_file(char* filename,
+                  struct bitmap *bm,
+                  int maxsize,
+                  int format,
+                  int dst_maxwidth,
+                  int dst_maxheight,
+                  int flags)
+{
+    int fd = open(filename, O_RDONLY);
+	int res;
+    /* 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;
+    }
+	res = read_bmp_fd(fd, bm, maxsize, format, dst_maxwidth, dst_maxheight, flags);
+	close(fd);
+	return res;
+}
diff -upNr -X dontdiff ../../tmp/rockbox/apps/recorder/bmp.h ./apps/recorder/bmp.h
--- ../../tmp/rockbox/apps/recorder/bmp.h	2007-04-17 01:54:40.000000000 +0900
+++ ./apps/recorder/bmp.h	2007-04-17 16:09:07.000000000 +0900
@@ -22,6 +22,12 @@
 #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()
  *
@@ -30,8 +36,20 @@
  * 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(char* filename,
                   struct bitmap *bm,
                   int maxsize,
-                  int format);
+                  int format,
+                  int dst_maxwidth,	/* = 0 */
+                  int dst_maxheight,/* = 0 */
+                  int flags);		/* BMP_RESIZE_NONE */
+
 #endif
