--- apps/recorder/bmpBB.c	2006-10-14 16:18:50.000000000 +0200
+++ apps/recorder/bmp.c	2006-10-12 15:54:06.000000000 +0200
@@ -5,7 +5,11 @@
  *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
  *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
  *                     \/            \/     \/    \/            \/
- * $Id: bmp.c,v 1.33 2006/10/12 00:25:21 jethead71 Exp $
+<<<<<<< bmp.c
+ * $Id: bmp.c,v 1.31 2006/10/11 18:12:36 jethead71 Exp $
+=======
+ * $Id: bmp.c,v 1.33 2006-10-12 00:25:21 jethead71 Exp $
+>>>>>>> 1.33
  *
  * Copyright (C) 2002 by Linus Nielsen Feltzing
  *
@@ -27,6 +31,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include "inttypes.h"
 #include "debug.h"
 #include "lcd.h"
 #include "file.h"
@@ -44,22 +49,22 @@
 
 /* Struct from original code. */
 struct Fileheader {
-    unsigned short Type;        /* signature - 'BM' */
-    unsigned long Size;         /* file size in bytes */
-    unsigned short Reserved1;   /* 0 */
-    unsigned short Reserved2;   /* 0 */
-    unsigned long OffBits;      /* offset to bitmap */
-    unsigned long StructSize;   /* size of this struct (40) */
-    unsigned long Width;        /* bmap width in pixels */
-    unsigned long Height;       /* bmap height in pixels */
-    unsigned short Planes;      /* num planes - always 1 */
-    unsigned short BitCount;    /* bits per pixel */
-    unsigned long Compression;  /* compression flag */
-    unsigned long SizeImage;    /* image size in bytes */
-    long XPelsPerMeter;         /* horz resolution */
-    long YPelsPerMeter;         /* vert resolution */
-    unsigned long ClrUsed;      /* 0 -> color table size */
-    unsigned long ClrImportant; /* important color count */
+    uint16_t Type;        /* signature - 'BM' */
+    uint32_t Size;         /* file size in bytes */
+    uint16_t Reserved1;   /* 0 */
+    uint16_t Reserved2;   /* 0 */
+    uint32_t OffBits;      /* offset to bitmap */
+    uint32_t StructSize;   /* size of this struct (40) */
+    uint32_t Width;        /* bmap width in pixels */
+    uint32_t Height;       /* bmap height in pixels */
+    uint16_t Planes;      /* num planes - always 1 */
+    uint16_t BitCount;    /* bits per pixel */
+    uint32_t Compression;  /* compression flag */
+    uint32_t SizeImage;    /* image size in bytes */
+    int32_t XPelsPerMeter;         /* horz resolution */
+    int32_t YPelsPerMeter;         /* vert resolution */
+    uint32_t ClrUsed;      /* 0 -> color table size */
+    uint32_t ClrImportant; /* important color count */
 } STRUCT_PACKED;
 
 struct rgb_quad { /* Little endian */
@@ -70,12 +75,12 @@
 } STRUCT_PACKED; 
 
 /* big endian functions */
-static short readshort(short *value) {
+static uint16_t readshort(uint16_t *value) {
     unsigned char* bytes = (unsigned char*) value;
     return bytes[0] | (bytes[1] << 8);
 }
 
-static long readlong(long *value) {
+static uint32_t readlong(uint32_t *value) {
     unsigned char* bytes = (unsigned char*) value;
     return (long)bytes[0] | ((long)bytes[1] << 8) |
         ((long)bytes[2] << 16) | ((long)bytes[3] << 24);
@@ -94,7 +99,6 @@
 
     return (bmpbuf[a] & (1 << b)) != 0;
 }
-
 #if LCD_DEPTH == 16
 /* Cheapo 24 -> 16 bit dither */
 static unsigned short dither_24_to_16(struct rgb_quad rgb, int row, int col)
@@ -135,27 +139,212 @@
 #endif /* LCD_DEPTH == 16 */
 
 
+/* maximum bitmap width which can be read: */
+#define MAX_WIDTH 1024
+static unsigned char bmpbuf[MAX_WIDTH*sizeof(struct rgb_quad)]; /* Buffer for one line */
+
+
+/******************************************************************************
++ * set_bmp_pixel()
+ *
+ * puts a pixel from BMP source (bmpbuf) to destination (bitmap).
+ *
+ *****************************************************************************/
+static void set_bmp_pixel(int depth,
+                          int format,
+                          int invert_pixel,
+                          struct rgb_quad *palette,
+                          unsigned char *bmpbuf,
+                          int src_col,
+                          unsigned char *bitmap,
+                          int dst_row,
+                          int dst_col,
+                          int dst_w,
+                          int dst_h,
+                          bool dither)
+{
+#if LCD_DEPTH > 1
+    fb_data *dest = (fb_data *)bitmap;
+#endif
+    unsigned char *p;
+    int ret;
+
+    switch (depth) {
+        case 1:
+#if LCD_DEPTH > 1
+            if (format == FORMAT_MONO) {
+#endif
+                /* Mono -> Mono */
+                ret = getpix(src_col, bmpbuf) ^ invert_pixel;
+                if (ret) {
+                    bitmap[dst_w * ((dst_h - dst_row - 1) / 8) + dst_col]
+                        |= 1 << ((dst_h - dst_row - 1) % 8);
+                } else {
+                    bitmap[dst_w * ((dst_h - dst_row - 1) / 8) + dst_col]
+                        &= ~ 1 << ((dst_h - dst_row - 1) % 8);
+                }
+#if LCD_DEPTH > 1
+            } else {
+#endif
+#if LCD_DEPTH == 2
+#if LCD_PIXELFORMAT == VERTICAL_PACKING
+                /* Mono -> 2gray (iriver H1xx) */
+                ret = getpix(src_col, bmpbuf) ^ invert_pixel;
+                if (ret) {
+                    dest[((dst_h - dst_row - 1) / 4) * dst_w + dst_col] |=
+                        0xC0 >> (2 * (~(dst_h - dst_row - 1) & 3));
+                }
+#else
+                /* Mono -> 2gray (ipod) */
+                ret = getpix(src_col, bmpbuf) ^ invert_pixel;
+                if (ret) {
+                    dest[(dst_h - dst_row - 1) * dst_w + dst_col/4] |=
+                        0xC0 >> (2 * (dst_col & 3));
+                }
+#endif
+#elif LCD_DEPTH == 16
+                /* Mono -> RGB16 */
+                ret = getpix(src_col, bmpbuf);
+                unsigned short rgb16 = LCD_RGBPACK(palette[ret].red,
+                                                   palette[ret].green,
+                                                   palette[ret].blue);
+                dest[dst_w * (dst_h - dst_row - 1) + dst_col] = rgb16;
+#endif
+#if LCD_DEPTH > 1
+            }
+#endif
+        break; /* case 1 */
+
+        case 8:
+            p = bmpbuf + src_col;
+#if LCD_DEPTH > 1
+            if (format == FORMAT_MONO) {
+#endif
+                /* 8-bit RGB24 palette -> mono */
+                struct rgb_quad rgb = palette[*p];
+                ret = brightness(rgb);
+                if (ret > 96) {
+                    bitmap[dst_w * ((dst_h - dst_row - 1) / 8) + dst_col]
+                        &= ~ 1 << ((dst_h - dst_row - 1) % 8);
+                } else {
+                    bitmap[dst_w * ((dst_h - dst_row - 1) / 8) + dst_col]
+                        |= 1 << ((dst_h - dst_row - 1) % 8);
+                }
+#if LCD_DEPTH > 1
+            } else {
+#endif
+#if LCD_DEPTH == 2
+#if LCD_PIXELFORMAT == VERTICAL_PACKING
+                /* 8-bit RGB24 palette -> 2gray (iriver H1xx) */
+                struct rgb_quad rgb = palette[*p];
+                ret = brightness(rgb);
+                dest[((dst_h - dst_row - 1)/4) * dst_w + dst_col] |=
+                    (~ret & 0xC0) >> (2 * (~(dst_h - dst_row - 1) & 3));
+#else
+                /* 8-bit RGB24 palette -> 2gray (ipod) */
+                struct rgb_quad rgb = palette[*p];
+                ret = brightness(rgb);
+
+                dest[(dst_h - dst_row - 1) * dst_w + dst_col/4] |=
+                    (~ret & 0xC0) >> (2 * (dst_col & 3));
+#endif
+#elif LCD_DEPTH == 16
+                /* 8-bit RGB24 palette -> RGB16 */
+                struct rgb_quad rgb = palette[*p];
+                dest[dst_w * (dst_h - dst_row - 1) + dst_col] = dither ?
+                dither_24_to_16(rgb, dst_row, dst_col) : LCD_RGBPACK(rgb.red, rgb.green, rgb.blue);
+#endif
+#if LCD_DEPTH > 1
+            }
+#endif
+        break; /* case 8 */
+
+        case 24:
+            p = bmpbuf + 3 * src_col;
+#if LCD_DEPTH > 1
+            if (format == FORMAT_MONO) {
+#endif
+            /* RGB24 -> mono */
+                struct rgb_quad rgb;
+                rgb.red = p[2];
+                rgb.green = p[1];
+                rgb.blue = p[0];
+                ret = brightness(rgb);
+                if (ret > 96) {
+                    bitmap[dst_w * ((dst_h - dst_row - 1) / 8) + dst_col]
+                        &= ~ 1 << ((dst_h - dst_row - 1) % 8);
+                } else {
+                    bitmap[dst_w * ((dst_h - dst_row - 1) / 8) + dst_col]
+                        |= 1 << ((dst_h - dst_row - 1) % 8);
+                }
+#if LCD_DEPTH > 1
+            } else {
+#endif
+#if LCD_DEPTH == 2
+#if LCD_PIXELFORMAT == VERTICAL_PACKING
+                /* RGB24 -> 2gray (iriver H1xx) */
+                struct rgb_quad rgb;
+                rgb.red = p[2];
+                rgb.green = p[1];
+                rgb.blue = p[0];
+                ret = brightness(rgb);
+
+                dest[((dst_h - dst_row - 1)/4) * dst_w + dst_col] |=
+                    (~ret & 0xC0) >> (2 * (~(dst_h - dst_row - 1) & 3));
+#else
+                /* RGB24 -> 2gray (ipod) */
+                struct rgb_quad rgb;
+                rgb.red = p[2];
+                rgb.green = p[1];
+                rgb.blue = p[0];
+                ret = brightness(rgb);
+
+                dest[(dst_h - dst_row - 1) * dst_w + dst_col/4] |=
+                    (~ret & 0xC0) >> (2 * (dst_col & 3));
+#endif
+#elif LCD_DEPTH == 16
+                /* RGB24 -> RGB16 */
+                dest[dst_w * (dst_h - dst_row - 1) + dst_col] = dither?
+                  dither_24_to_16(*(struct rgb_quad *)p, dst_row, dst_col) :
+                  LCD_RGBPACK(p[2],p[1],p[0]);
+#endif
+#if LCD_DEPTH > 1
+            }
+#endif
+        break; /* case 24 */
+    } /* END switch(depth) */
+}
+
+
+
 /******************************************************************************
  * read_bmp_file()
  *
- * Reads a monochrome BMP file and puts the data in rockbox format in *bitmap.
+ * Reads a BMP file and puts the data in rockbox format in *bitmap.
  *
  *****************************************************************************/
 int read_bmp_file(char* filename,
                   struct bitmap *bm,
                   int maxsize,
-                  int format)
+                  int format,
+                  int dst_maxwidth,
+                  int dst_width_resize,
+                  int dst_maxheight,
+                  int dst_height_resize)
 {
     struct Fileheader fh;
-    int width, height, PaddedWidth, PaddedHeight, dst_width;
-    int fd, row, col, ret;
+    int src_w, src_h, SrcPaddedWidth;
+    int dst_w, dst_h, DstPaddedHeight, DstPaddedWidth;
+    int fact;
+    int fd, row, ret;
+
     struct rgb_quad palette[256];
     int invert_pixel = 0;
     int numcolors;
     int depth;
     int totalsize;
     char *bitmap = bm->data;
-    unsigned char bmpbuf[LCD_WIDTH*sizeof(struct rgb_quad)]; /* Buffer for one line */
+//    unsigned char bmpbuf[LCD_WIDTH*sizeof(struct rgb_quad)]; /* Buffer for one line */
 #if LCD_DEPTH != 1
     bool transparent = false;
 #if LCD_DEPTH == 16
@@ -178,8 +367,8 @@
 
     /* Exit if file opening failed */
     if (fd < 0) {
-        DEBUGF("error - can't open '%s' open returned: %d\n", filename, fd);
-        return (fd * 10) - 1; 
+      DEBUGF("read_bmp_file: error - can't open '%s' open returned: %d\n", filename, fd);
+      return (fd * 10) - 1; 
     }
 
     /* read fileheader */
@@ -190,34 +379,82 @@
     }
     
     if(ret != sizeof(struct Fileheader)) {
-        DEBUGF("error - can't read Fileheader structure.");
+        DEBUGF("read_bmp_file: error - can't read Fileheader structure.");
         close(fd);
         return -3;
     }
 
+    /* read the source dimensions */
+    src_w = readlong(&fh.Width);
+    src_h = readlong(&fh.Height);
+
+    if (src_w > MAX_WIDTH) {
+        DEBUGF("read_bmp_file: error - Bitmap is too wide (%d pixels, max is %d)\n",
+               src_w, MAX_WIDTH);
+        close(fd);
+        return -5;
+    }
+
+    depth = readshort(&fh.BitCount);
+
+    /* Calculate resize factors and image size */
+    {
+        int fact_w = -1;
+        int fact_h = -1;
+        if (dst_maxwidth > 0)
+            fact_w = (src_w * 1000) / dst_maxwidth;
+        if (fact_w > 1000 && !(dst_width_resize & BMP_RESIZE_DECREASE)) {
+            /* no decrease allowed */
+            fact_w = -1;
+        }
+        if (fact_w < 1000 && !(dst_width_resize & BMP_RESIZE_INCREASE)) {
+            /* no increase allowed */
+            fact_w = -1;
+        }
+
+        if (dst_maxheight > 0)
+            fact_h = (src_h * 1000) / dst_maxheight;
+        if (fact_h > 1000 && !(dst_height_resize & BMP_RESIZE_DECREASE)) {
+            /* no decrease allowed */
+            fact_h = -1;
+        }
+        if (fact_h < 1000 && !(dst_height_resize & BMP_RESIZE_INCREASE)) {
+            /* no increase allowed */
+            fact_h = -1;
+        }
+
+        fact = MAX(fact_h, fact_w);
+        if (fact > 0) {
+            dst_w = (src_w * 1000) / fact;
+            dst_h = (src_h * 1000) / fact;
+        } else {
+            /* don't resize */
+            fact = 1000;
+            dst_w = src_w;
+            dst_h = src_h;
+        }
+    }
+
+    DEBUGF("read_bmp_file: src_w/h=%d/%d, dst_w/h=%d/%d (fact=%d)\n",
+           src_w, src_h, dst_w, dst_h, fact);
+
     /* Exit if too wide */
-    if (readlong(&fh.Width) > LCD_WIDTH) {
-        DEBUGF("error - Bitmap is too wide (%d pixels, max is %d)\n",
-                        readlong(&fh.Width), LCD_WIDTH);
+    if (dst_w > LCD_WIDTH) {
+        DEBUGF("read_bmp_file: error - Bitmap is too wide (%d pixels, max is %d)\n",
+               dst_w, LCD_WIDTH);
         close(fd);
         return -5;
     }
 
-    /* Exit if too high */
-    if (readlong(&fh.Height) > LCD_HEIGHT) {
-        DEBUGF("error - Bitmap is too high (%d pixels, max is %d)\n",
-                        readlong(&fh.Height), LCD_HEIGHT);
+    if (dst_h > LCD_HEIGHT) {
+        DEBUGF("read_bmp_file: error - Bitmap is too high (%d pixels, max is %d)\n",
+               dst_h, LCD_HEIGHT);
         close(fd);
         return -6;
     }
 
-    /* Calculate image size */
-    height = readlong(&fh.Height);
-    width = readlong(&fh.Width);
-    depth = readshort(&fh.BitCount);
-
     /* 4-byte boundary aligned */
-    PaddedWidth = ((width * depth + 31) / 8) & ~3;
+    SrcPaddedWidth = ((src_w * depth + 31) / 8) & ~3;
 
 #if LCD_DEPTH > 1
         if(format == FORMAT_ANY) {
@@ -228,32 +465,33 @@
         }
 #endif
 
-    /* PaddedHeight is for rockbox format. */
-    if(format == FORMAT_MONO) {
-        PaddedHeight = (height + 7) / 8;
-        dst_width = width;
-        totalsize = PaddedHeight * dst_width;
+    /* DstPaddedHeight/Width is for rockbox format. */
+    if (format == FORMAT_MONO) {
+        DstPaddedHeight = (dst_h + 7) / 8;
+        DstPaddedWidth = dst_w;
+        totalsize = DstPaddedHeight * DstPaddedWidth;
     } else {
 #if LCD_DEPTH == 2
 #if LCD_PIXELFORMAT == VERTICAL_PACKING
-        PaddedHeight = (height + 3) / 4;
-        dst_width = width;
+        DstPaddedHeight = (dst_h + 3) / 4;
+        DstPaddedWidth = dst_w;
 #else
-        PaddedHeight = height;
-        dst_width = (width + 3) / 4;
+        DstPaddedHeight = dst_h;
+        DstPaddedWidth = (dst_w + 3) / 4;
 #endif
 #else
-        PaddedHeight = height;
-        dst_width = width;
+        DstPaddedHeight = dst_h;
+        DstPaddedWidth = dst_w;
 #endif
-        totalsize = PaddedHeight * dst_width * sizeof(fb_data);
+        totalsize = DstPaddedHeight * DstPaddedWidth * sizeof(fb_data);
     }
 
     /* Check if this fits the buffer */
     
     if (totalsize > maxsize) {
-        DEBUGF("error - Bitmap is too large to fit the supplied buffer: "
-               "%d bytes.\n", (PaddedHeight * dst_width));
+        DEBUGF("read_bmp_file: error - Bitmap is too large to fit the supplied buffer: "
+               "%d bytes.%d:%d\n", (DstPaddedHeight * DstPaddedWidth),
+               totalsize, maxsize);
         close(fd);
         return -7;
     }
@@ -267,7 +505,7 @@
         if(read(fd, palette, numcolors * sizeof(struct rgb_quad))
            != numcolors * (int)sizeof(struct rgb_quad))
         {
-            DEBUGF("error - Can't read bitmap's color palette\n");
+            DEBUGF("read_bmp_file: error - Can't read bitmap's color palette\n");
             close(fd);
             return -8;
         }
@@ -287,211 +525,72 @@
         memset(bitmap, 0, totalsize);
 #endif
     
-#if LCD_DEPTH > 1
-    fb_data *dest = (fb_data *)bitmap;
-#endif
-    
-    /* loop to read rows and put them to buffer */
-    for (row = 0; row < height; row++) {
-        unsigned char *p;
-        
-        /* read one row */
-        ret = read(fd, bmpbuf, PaddedWidth);
-        if (ret != PaddedWidth) {
-            DEBUGF("error reading image, read returned: %d expected was: "
-                   "%d\n", ret, PaddedWidth);
-            close(fd);
-            return -9;
-        }
-
-        switch(depth) {
-        case 1:
-#if LCD_DEPTH > 1
-            if(format == FORMAT_MONO) {
-#endif
-                /* Mono -> Mono */
-                for (col = 0; col < width; col++) {
-                    ret = getpix(col, bmpbuf) ^ invert_pixel;
-                    if (ret) {
-                        bitmap[width * ((height - row - 1) / 8) + col]
-                            |= 1 << ((height - row - 1) % 8);
-                    } else {
-                        bitmap[width * ((height - row - 1) / 8) + col]
-                            &= ~ 1 << ((height - row - 1) % 8);
-                    }
-                }
-#if LCD_DEPTH == 2
-#if LCD_PIXELFORMAT == VERTICAL_PACKING
-            } else {
-                /* Mono -> 2gray (iriver H1xx) */
-                for (col = 0; col < width; col++) {
-                    ret = getpix(col, bmpbuf) ^ invert_pixel;
-                    
-                    if (ret)
-                        dest[((height - row - 1)/4) * width + col] |=
-                            0xC0 >> (2 * (~(height - row - 1) & 3));
-                }
-            }
-#else
-            } else {
-                /* Mono -> 2gray (ipod) */
-                for (col = 0; col < width; col++) {
-                    ret = getpix(col, bmpbuf) ^ invert_pixel;
-                    
-                    if (ret)
-                        dest[(height - row - 1) * dst_width + col/4] |=
-                            0xC0 >> (2 * (col & 3));
-                }
-            }
-#endif
-#elif LCD_DEPTH == 16
-            } else {
-                /* Mono -> RGB16 */
-                for (col = 0; col < width; col++) {
-                    ret = getpix(col, bmpbuf);
-                    unsigned short rgb16 = LCD_RGBPACK(palette[ret].red,
-                                                       palette[ret].green,
-                                                       palette[ret].blue);
-                    dest[width * (height - row - 1) + col] = rgb16;
-                }
-            }
-#endif
-            break;
-
-
-        case 8:
-            p = bmpbuf;
-#if LCD_DEPTH > 1
-            if(format == FORMAT_MONO) {
-#endif
-                /* 8-bit RGB24 palette -> mono */
-                for (col = 0; col < width; col++) {
-                    struct rgb_quad rgb = palette[*p];
-                    ret = brightness(rgb);
-                    if (ret > 96) {
-                        bitmap[width * ((height - row - 1) / 8) + col]
-                            &= ~ 1 << ((height - row - 1) % 8);
-                    } else {
-                        bitmap[width * ((height - row - 1) / 8) + col]
-                            |= 1 << ((height - row - 1) % 8);
-                    }
-                    p++;
-                }
-#if LCD_DEPTH == 2
-#if LCD_PIXELFORMAT == VERTICAL_PACKING
-            } else {
-                /* 8-bit RGB24 palette -> 2gray (iriver H1xx) */
-                for (col = 0; col < width; col++) {
-                    struct rgb_quad rgb = palette[*p];
-                    ret = brightness(rgb);
-
-                    dest[((height - row - 1)/4) * width + col] |=
-                        (~ret & 0xC0) >> (2 * (~(height - row - 1) & 3));
-                    p++;
-                }
-            }
-#else
-            } else {
-                /* 8-bit RGB24 palette -> 2gray (ipod) */
-                for (col = 0; col < width; col++) {
-                    struct rgb_quad rgb = palette[*p];
-                    ret = brightness(rgb);
-
-                    dest[(height - row - 1) * dst_width + col/4] |=
-                        (~ret & 0xC0) >> (2 * (col & 3));
-                    p++;
-                }
-            }
-#endif
-#elif LCD_DEPTH == 16
-            } else {
-                /* 8-bit RGB24 palette -> RGB16 */
-                for (col = 0; col < width; col++, p++) {
-                    struct rgb_quad rgb = palette[*p];
-                    dest[width * (height - row - 1) + col] = dither ?
-                        dither_24_to_16(rgb, row, col) :
-                        LCD_RGBPACK(rgb.red, rgb.green, rgb.blue);
-                }
-            }
-#endif
-            break;
-
-        case 24:
-            p = bmpbuf;
-#if LCD_DEPTH > 1
-            if(format == FORMAT_MONO) {
-#endif
-                /* RGB24 -> mono */
-                for (col = 0; col < width; col++) {
-                    struct rgb_quad rgb;
-                    rgb.red = p[2];
-                    rgb.green = p[1];
-                    rgb.blue = p[0];
-                    ret = brightness(rgb);
-                    if (ret > 96) {
-                        bitmap[width * ((height - row - 1) / 8) + col]
-                            &= ~ 1 << ((height - row - 1) % 8);
-                    } else {
-                        bitmap[width * ((height - row - 1) / 8) + col]
-                            |= 1 << ((height - row - 1) % 8);
-                    }
-                    p += 3;
-                }
-#if LCD_DEPTH == 2
-#if LCD_PIXELFORMAT == VERTICAL_PACKING
-            } else {
-                /* RGB24 -> 2gray (iriver H1xx) */
-                for (col = 0; col < width; col++) {
-                    struct rgb_quad rgb;
-                    rgb.red = p[2];
-                    rgb.green = p[1];
-                    rgb.blue = p[0];
-                    ret = brightness(rgb);
-
-                    dest[((height - row - 1)/4) * width + col] |=
-                        (~ret & 0xC0) >> (2 * (~(height - row - 1) & 3));
-                    p += 3;
-                }
-            }
-#else
-            } else {
-                /* RGB24 -> 2gray (ipod) */
-                for (col = 0; col < width; col++) {
-                    struct rgb_quad rgb;
-                    rgb.red = p[2];
-                    rgb.green = p[1];
-                    rgb.blue = p[0];
-                    ret = brightness(rgb);
-
-                    dest[(height - row - 1) * dst_width + col/4] |=
-                        (~ret & 0xC0) >> (2 * (col & 3));
-                    p += 3;
-                }
-            }
-#endif
-#elif LCD_DEPTH == 16
-            } else {
-                /* RGB24 -> RGB16 */
-                for (col = 0; col < width; col++, p += 3) {
-                    dest[width * (height - row - 1) + col] = dither ?
-                        dither_24_to_16(*(struct rgb_quad *)p, row, col) :
-                        LCD_RGBPACK(p[2], p[1], p[0]);
-                }
-            }
-#endif
-            break;
-        }
-    }
+ 
+      /* loop to read rows and put them to buffer */
+     for (row = 0; row < src_h; row++) {
+          /* read one row */
+         ret = read(fd, bmpbuf, SrcPaddedWidth);
+         if (ret != SrcPaddedWidth) {
+             DEBUGF("read_bmp_file: error reading image, read returned: %d expected was: "
+                    "%d\n", ret, SrcPaddedWidth);
+              close(fd);
+              return -9;
+          }
+  
+         if (fact > 1000) {
+             /* decrease
+              * -> put only every "fact" row to the dest buffer */
+             if ((row % (fact / 1000)) == 0) {
+                 int dst_row = (row * 1000) / fact;
+                 int dst_col;
+ 
+                 for (dst_col = 0; dst_col < dst_w; dst_col++) {
+                     int src_col = (dst_col * fact) / 1000;
+ 
+                     set_bmp_pixel(depth, format, invert_pixel, palette,
+                                   bmpbuf, src_col,
+                                   bitmap, dst_row, dst_col, dst_w, dst_h,dither);
+                  }
+              }
+         } else
+         if (fact < 1000) {
+             /* increase
+              * -> duplicate src-pixel for not existing dst-rows/cols */
+             int dst_row, dst_col;
+             int src_col;
+ 
+             for (dst_row = row * 1000 / fact;
+                  dst_row < (row + 1) * 1000 / fact; dst_row++) {
+                 for (src_col = 0; src_col < src_w; src_col++) {
+                     for (dst_col = src_col * 1000 / fact;
+                          dst_col < (src_col + 1) * 1000 / fact; dst_col++) {
+                         set_bmp_pixel(depth, format, invert_pixel, palette,
+                                       bmpbuf, src_col,
+                                       bitmap, dst_row, dst_col, dst_w, dst_h,dither);
+                     }
+                  }
+              }
+         } else {
+             /* same size -> just transport the pixels */
+             int dst_col;
+             for (dst_col = 0; dst_col < dst_w; dst_col++) {
+                 set_bmp_pixel(depth, format, invert_pixel, palette,
+                               bmpbuf, dst_col,
+                               bitmap, row, dst_col, dst_w, dst_h,dither);
+              }
+          }
+     } /* END for (row = 0; row < src_h; row++) */
 
     close(fd);
 
     /* returning image size: */
-    bm->width = width;
-    bm->height = height;
-#if LCD_DEPTH > 1
+    bm->width = dst_w;
+    bm->height = dst_h;
+    #if LCD_DEPTH > 1
     bm->format = format;
 #endif
 
-DEBUGF("totalsize: %d\n", totalsize);
+    DEBUGF("read_bmp_file: totalsize=%d, width=%d, height=%d\n",
+           totalsize, dst_w, dst_h);
     return totalsize; /* return the used buffer size. */
 }
