113a58dca6
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6422 a1c6a512-1295-4272-9138-f99709370657
205 lines
6.5 KiB
C
205 lines
6.5 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2002 by Linus Nielsen Feltzing
|
|
*
|
|
* All files in this archive are subject to the GNU General Public License.
|
|
* See the file COPYING in the source tree root for full license agreement.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/*
|
|
2005-04-16 Tomas Salfischberger:
|
|
- New BMP loader function, based on the old one (borrowed a lot of
|
|
calculations and checks there.)
|
|
- Conversion part needs some optimization, doing unneeded calulations now.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "debug.h"
|
|
#include "lcd.h"
|
|
#include "file.h"
|
|
#include "autoconf.h"
|
|
|
|
#ifdef __GNUC__
|
|
#define STRUCT_PACKED __attribute__((packed))
|
|
#else
|
|
#define STRUCT_PACKED
|
|
#pragma pack (push, 2)
|
|
#endif
|
|
|
|
/* 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 */
|
|
} STRUCT_PACKED;
|
|
|
|
|
|
#ifdef ROCKBOX_LITTLE_ENDIAN
|
|
#define readshort(x) x
|
|
#define readlong(x) x
|
|
#else
|
|
|
|
/* Endian functions */
|
|
short readshort(void* value) {
|
|
unsigned char* bytes = (unsigned char*) value;
|
|
return bytes[0] | (bytes[1] << 8);
|
|
}
|
|
|
|
long readlong(void* value) {
|
|
unsigned char* bytes = (unsigned char*) value;
|
|
return (long)bytes[0] | ((long)bytes[1] << 8) |
|
|
((long)bytes[2] << 16) | ((long)bytes[3] << 24);
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/* Function to get a pixel from a line. (Tomas: maybe a better way?) */
|
|
int getpix(int px, unsigned char *bmpbuf) {
|
|
int a = (px / 8);
|
|
int b = (7 - (px % 8));
|
|
|
|
return (bmpbuf[a] & (1 << b)) != 0;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
* read_bmp_file()
|
|
*
|
|
* Reads a monochrome BMP file and puts the data in rockbox format in *bitmap.
|
|
*
|
|
*****************************************************************************/
|
|
int read_bmp_file(char* filename,
|
|
int *get_width, /* in pixels */
|
|
int *get_height, /* in pixels */
|
|
char *bitmap,
|
|
int maxsize) /* Maximum amount of bytes to write to bitmap */
|
|
{
|
|
struct Fileheader fh;
|
|
int bitmap_width, bitmap_height, PaddedWidth, PaddedHeight;
|
|
int fd, row, col, ret;
|
|
char bmpbuf[(LCD_WIDTH / 8 + 3) & ~3]; /* Buffer for one line */
|
|
|
|
fd = open(filename, O_RDONLY);
|
|
|
|
/* Exit if file opening failed */
|
|
if (fd < 0) {
|
|
DEBUGF("error - can't open '%s' open returned: %d\n", filename, fd);
|
|
return (fd * 10) - 1;
|
|
}
|
|
|
|
/* read fileheader */
|
|
ret = read(fd, &fh, sizeof(struct Fileheader));
|
|
if(ret < 0) {
|
|
close(fd);
|
|
return (ret * 10 - 2);
|
|
}
|
|
|
|
if(ret != sizeof(struct Fileheader)) {
|
|
DEBUGF("error - can't read Fileheader structure.");
|
|
close(fd);
|
|
return -3;
|
|
}
|
|
|
|
/* Exit if not monochrome */
|
|
if (readshort(&fh.BitCount) != 1) {
|
|
DEBUGF("error - Bitmap must be in 1 bit per pixel format. "
|
|
"This one is: %d\n", readshort(&fh.BitCount));
|
|
close(fd);
|
|
return -4;
|
|
}
|
|
|
|
/* 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);
|
|
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);
|
|
close(fd);
|
|
return -6;
|
|
}
|
|
|
|
/* Calculate image size */
|
|
bitmap_height = readlong(&fh.Height);
|
|
bitmap_width = readlong(&fh.Width);
|
|
/* Paddedwidth is for BMP files. */
|
|
PaddedWidth = ((bitmap_width + 31) & (~0x1f)) / 8;
|
|
/* PaddedHeight is for rockbox format. */
|
|
PaddedHeight = (bitmap_height + 7) / 8;
|
|
|
|
/* Check if this fits the buffer */
|
|
if ((PaddedHeight * bitmap_width) > maxsize) {
|
|
DEBUGF("error - Bitmap is too large to fit the supplied buffer: "
|
|
"%d bytes.\n", (PaddedHeight * bitmap_width));
|
|
close(fd);
|
|
return -7;
|
|
}
|
|
|
|
/* Search to the beginning of the image data */
|
|
lseek(fd, (off_t)readlong(&fh.OffBits), SEEK_SET);
|
|
|
|
/* loop to read rows and put them to buffer */
|
|
for (row = 0; row < bitmap_height; row++) {
|
|
/* 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 -8;
|
|
}
|
|
|
|
/* loop though the pixels in this line. */
|
|
for (col = 0; col < bitmap_width; col++) {
|
|
ret = getpix(col, bmpbuf);
|
|
if (ret == 1) {
|
|
bitmap[bitmap_width * ((bitmap_height - row - 1) / 8) + col]
|
|
&= ~ 1 << ((bitmap_height - row - 1) % 8);
|
|
} else {
|
|
bitmap[bitmap_width * ((bitmap_height - row - 1) / 8) + col]
|
|
|= 1 << ((bitmap_height - row - 1) % 8);
|
|
}
|
|
}
|
|
}
|
|
|
|
close(fd);
|
|
|
|
/* returning image size: */
|
|
*get_width = bitmap_width;
|
|
*get_height = bitmap_height;
|
|
|
|
return (PaddedHeight * bitmap_width); /* return the used buffer size. */
|
|
|
|
}
|