Index: bmp.c =================================================================== --- bmp.c (revision 18474) +++ bmp.c (working copy) @@ -58,6 +58,8 @@ #pragma pack (push, 2) #endif +#define BLOCK_SIZE (((LCD_WIDTH+7)>>3)<<3) + /* BMP header structure */ struct bmp_header { uint16_t type; /* signature - 'BM' */ @@ -185,12 +187,13 @@ struct bmp_header bmph; int width, height, padded_width; int dst_height, dst_width; - int depth, numcolors, compression, totalsize; - int row, col, ret; + int bit_count, depth, numcolors, compression, totalsize; + int row, col; + off_t ret,fstart; int rowstart, rowstop, rowstep; unsigned char *bitmap = bm->data; - uint32_t bmpbuf[LCD_WIDTH]; /* Buffer for one line */ + uint32_t bmpbuf[BLOCK_SIZE]; /* Buffer for one line */ uint32_t palette[256]; #if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) bool transparent = false; @@ -220,6 +223,7 @@ (void)format; #endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */ + fstart=lseek(fd,0,SEEK_CUR); /* read fileheader */ ret = read(fd, &bmph, sizeof(struct bmp_header)); if (ret < 0) { @@ -232,12 +236,13 @@ } width = readlong(&bmph.width); - if (width > LCD_WIDTH) { +/* + if (width > LINEBUFFER) { DEBUGF("read_bmp_fd: Bitmap too wide (%d pixels, max is %d)\n", - width, LCD_WIDTH); + width, LINEBUFFER); return -4; } - +*/ height = readlong(&bmph.height); if (height < 0) { /* Top-down BMP file */ height = -height; @@ -251,6 +256,7 @@ } depth = readshort(&bmph.bit_count); + bit_count = depth; padded_width = ((width * depth + 31) >> 3) & ~3; /* 4-byte boundary aligned */ #if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) @@ -364,35 +370,52 @@ } /* Search to the beginning of the image data */ - lseek(fd, (off_t)readlong(&bmph.off_bits), SEEK_SET); + lseek(fd, (off_t)readlong(&bmph.off_bits)+fstart,SEEK_SET); memset(bitmap, 0, totalsize); /* loop to read rows and put them to buffer */ for (row = rowstart; row != rowstop; row += rowstep) { - unsigned data, mask; - unsigned char *p; - uint16_t *p2; - uint32_t *rp; - union rgb_union *qp; - union rgb_union q0, q1; + unsigned data, mask; + unsigned char *p; + uint16_t *p2; + uint32_t *rp; + union rgb_union *qp; + union rgb_union q0, q1; + int byteread,doffset,rwidth,dwidth; + + byteread = doffset = 0; + while (byteread < padded_width) + { - /* read one row */ - ret = read(fd, bmpbuf, padded_width); - if (ret != padded_width) { + /* determine read block size & extent of data*/ + dwidth = BLOCK_SIZE; + rwidth = (BLOCK_SIZE*bit_count) >> 3; + if (doffset + dwidth > width) + { + dwidth = width - doffset; + rwidth = padded_width - byteread; + } + + /* read one block */ + ret = read(fd, bmpbuf, rwidth); + if (ret != rwidth) { DEBUGF("read_bmp_fd: error reading image, read returned: %d " - "expected: %d\n", ret, padded_width); + "expected: %d\n", ret, rwidth); return -9; } + byteread += rwidth; + + if (dwidth <= 0) break; - /* convert whole line in-place to XRGB8888 (little endian) */ - rp = bmpbuf + width; + /* convert whole block in-place to XRGB8888 (little endian) */ + rp = bmpbuf + dwidth; switch (depth) { case 1: q0.raw = palette[0]; q1.raw = palette[1]; - p = (unsigned char*)bmpbuf + ((width + 7) >> 3); - mask = 0x80 >> ((width + 7) & 7); + p = (unsigned char*)bmpbuf + ((dwidth + 7) >> 3); + mask = 0x80 >> ((dwidth + 7) & 7); while (p > (unsigned char*)bmpbuf) { data = *(--p); for (; mask <= 0x80; mask <<= 1) @@ -402,9 +425,9 @@ break; case 4: - if (width & 1) + if (dwidth & 1) rp++; - p = (unsigned char*)bmpbuf + ((width + 1) >> 1); + p = (unsigned char*)bmpbuf + ((dwidth + 1) >> 1); while (p > (unsigned char*)bmpbuf) { data = *(--p); *(--rp) = palette[data & 0x0f]; @@ -413,14 +436,14 @@ break; case 8: - p = (unsigned char*)bmpbuf + width; + p = (unsigned char*)bmpbuf + dwidth; while (p > (unsigned char*)bmpbuf) *(--rp) = palette[*(--p)]; break; case 15: case 16: - p2 = (uint16_t *)bmpbuf + width; + p2 = (uint16_t *)bmpbuf + dwidth; while (p2 > (uint16_t *)bmpbuf) { unsigned component, rgb; @@ -466,7 +489,7 @@ break; case 24: - p = (unsigned char*)bmpbuf + 3 * width; + p = (unsigned char*)bmpbuf + 3 * dwidth; while (p > (unsigned char*)bmpbuf) { data = *(--p); data = (data << 8) | *(--p); @@ -488,12 +511,12 @@ #if (LCD_REMOTE_DEPTH == 2) && (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED) /* iAudio X5/M5 remote */ fb_remote_data *dest = (fb_remote_data *)bitmap - + dst_width * (row >> 3); + + dst_width * (row >> 3) + doffset; int shift = row & 7; int delta = 127; unsigned bright; - for (col = 0; col < width; col++) { + for (col = doffset; col < doffset + dwidth; col++) { if (dither) delta = dither_matrix[row & 0xf][col & 0xf]; bright = brightness(*qp++); @@ -507,13 +530,13 @@ #if LCD_DEPTH == 2 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING /* greyscale iPods */ - fb_data *dest = (fb_data *)bitmap + dst_width * row; + fb_data *dest = (fb_data *)bitmap + dst_width * row + (doffset>>2); int shift = 6; int delta = 127; unsigned bright; unsigned data = 0; - for (col = 0; col < width; col++) { + for (col = doffset; col < doffset + dwidth; col++) { if (dither) delta = dither_matrix[row & 0xf][col & 0xf]; bright = brightness(*qp++); @@ -530,12 +553,12 @@ *dest++ = data; #elif LCD_PIXELFORMAT == VERTICAL_PACKING /* iriver H1x0 */ - fb_data *dest = (fb_data *)bitmap + dst_width * (row >> 2); + fb_data *dest = (fb_data *)bitmap + dst_width * (row >> 2) + doffset; int shift = 2 * (row & 3); int delta = 127; unsigned bright; - for (col = 0; col < width; col++) { + for (col = doffset; col < doffset + dwidth; col++) { if (dither) delta = dither_matrix[row & 0xf][col & 0xf]; bright = brightness(*qp++); @@ -544,12 +567,12 @@ } #elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED /* iAudio M3 */ - fb_data *dest = (fb_data *)bitmap + dst_width * (row >> 3); + fb_data *dest = (fb_data *)bitmap + dst_width * (row >> 3) + doffset; int shift = row & 7; int delta = 127; unsigned bright; - for (col = 0; col < width; col++) { + for (col = doffset; col < doffset+dwidth; col++) { if (dither) delta = dither_matrix[row & 0xf][col & 0xf]; bright = brightness(*qp++); @@ -559,11 +582,11 @@ #endif /* LCD_PIXELFORMAT */ #elif LCD_DEPTH == 16 /* iriver h300, colour iPods, X5 */ - fb_data *dest = (fb_data *)bitmap + dst_width * row; + fb_data *dest = (fb_data *)bitmap + dst_width * row + doffset; int delta = 127; unsigned r, g, b; - for (col = 0; col < width; col++) { + for (col = doffset; col < doffset + dwidth; col++) { if (dither) delta = dither_matrix[row & 0xf][col & 0xf]; q0 = *qp++; @@ -577,13 +600,15 @@ } else #endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */ { - p = bitmap + dst_width * (row >> 3); + p = bitmap + dst_width * (row >> 3) + doffset; mask = 1 << (row & 7); - for (col = 0; col < width; col++, p++) + for (col = doffset; col < doffset + dwidth; col++,p++) if (brightness(*qp++) < 128) *p |= mask; } + doffset+=dwidth; + } } return totalsize; /* return the used buffer size. */