1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
21 2005-04-16 Tomas Salfischberger:
22 - New BMP loader function, based on the old one (borrowed a lot of
23 calculations and checks there.)
24 - Conversion part needs some optimization, doing unneeded calulations now.
38 #define STRUCT_PACKED __attribute__((packed))
41 #pragma pack (push, 2)
44 /* Struct from original code. */
46 unsigned short Type
; /* signature - 'BM' */
47 unsigned long Size
; /* file size in bytes */
48 unsigned short Reserved1
; /* 0 */
49 unsigned short Reserved2
; /* 0 */
50 unsigned long OffBits
; /* offset to bitmap */
51 unsigned long StructSize
; /* size of this struct (40) */
52 unsigned long Width
; /* bmap width in pixels */
53 unsigned long Height
; /* bmap height in pixels */
54 unsigned short Planes
; /* num planes - always 1 */
55 unsigned short BitCount
; /* bits per pixel */
56 unsigned long Compression
; /* compression flag */
57 unsigned long SizeImage
; /* image size in bytes */
58 long XPelsPerMeter
; /* horz resolution */
59 long YPelsPerMeter
; /* vert resolution */
60 unsigned long ClrUsed
; /* 0 -> color table size */
61 unsigned long ClrImportant
; /* important color count */
64 struct rgb_quad
{ /* Little endian */
68 unsigned char reserved
;
71 /* big endian functions */
72 static short readshort(short *value
) {
73 unsigned char* bytes
= (unsigned char*) value
;
74 return bytes
[0] | (bytes
[1] << 8);
77 static long readlong(long *value
) {
78 unsigned char* bytes
= (unsigned char*) value
;
79 return (long)bytes
[0] | ((long)bytes
[1] << 8) |
80 ((long)bytes
[2] << 16) | ((long)bytes
[3] << 24);
83 unsigned char brightness(struct rgb_quad color
)
85 return (3 * (unsigned int)color
.red
+ 6 * (unsigned int)color
.green
86 + (unsigned int)color
.blue
) / 10;
89 /* Function to get a pixel from a line. (Tomas: maybe a better way?) */
90 inline int getpix(int px
, unsigned char *bmpbuf
) {
92 int b
= (7 - (px
% 8));
94 return (bmpbuf
[a
] & (1 << b
)) != 0;
98 /******************************************************************************
101 * Reads a monochrome BMP file and puts the data in rockbox format in *bitmap.
103 *****************************************************************************/
104 int read_bmp_file(char* filename
,
109 struct Fileheader fh
;
110 int width
, height
, PaddedWidth
, PaddedHeight
;
111 int fd
, row
, col
, ret
;
112 struct rgb_quad palette
[256];
113 int invert_pixel
= 0;
117 char *bitmap
= bm
->data
;
119 unsigned char bmpbuf
[LCD_WIDTH
*sizeof(struct rgb_quad
)]; /* Buffer for one line */
126 if(format
& FORMAT_TRANSPARENT
) {
128 format
&= ~FORMAT_TRANSPARENT
;
133 fd
= open(filename
, O_RDONLY
);
135 /* Exit if file opening failed */
137 DEBUGF("error - can't open '%s' open returned: %d\n", filename
, fd
);
138 return (fd
* 10) - 1;
141 /* read fileheader */
142 ret
= read(fd
, &fh
, sizeof(struct Fileheader
));
145 return (ret
* 10 - 2);
148 if(ret
!= sizeof(struct Fileheader
)) {
149 DEBUGF("error - can't read Fileheader structure.");
154 /* Exit if too wide */
155 if (readlong(&fh
.Width
) > LCD_WIDTH
) {
156 DEBUGF("error - Bitmap is too wide (%d pixels, max is %d)\n",
157 readlong(&fh
.Width
), LCD_WIDTH
);
162 /* Exit if too high */
163 if (readlong(&fh
.Height
) > LCD_HEIGHT
) {
164 DEBUGF("error - Bitmap is too high (%d pixels, max is %d)\n",
165 readlong(&fh
.Height
), LCD_HEIGHT
);
170 /* Calculate image size */
171 height
= readlong(&fh
.Height
);
172 width
= readlong(&fh
.Width
);
173 depth
= readshort(&fh
.BitCount
);
175 /* 4-byte boundary aligned */
176 PaddedWidth
= ((width
* depth
+ 31) / 8) & ~3;
179 if(format
== FORMAT_ANY
) {
181 format
= FORMAT_MONO
;
183 format
= FORMAT_NATIVE
;
187 /* PaddedHeight is for rockbox format. */
188 if(format
== FORMAT_MONO
) {
189 PaddedHeight
= (height
+ 7) / 8;
190 totalsize
= PaddedHeight
* width
;
193 PaddedHeight
= (height
+ 3) / 4;
195 PaddedHeight
= height
;
197 totalsize
= PaddedHeight
* width
* sizeof(fb_data
);
200 /* Check if this fits the buffer */
202 if (totalsize
> maxsize
) {
203 DEBUGF("error - Bitmap is too large to fit the supplied buffer: "
204 "%d bytes.\n", (PaddedHeight
* width
));
211 numcolors
= readlong(&fh
.ClrUsed
);
213 numcolors
= 1 << depth
;
215 if(read(fd
, palette
, numcolors
* sizeof(struct rgb_quad
))
216 != numcolors
* (int)sizeof(struct rgb_quad
))
218 DEBUGF("error - Can't read bitmap's color palette\n");
224 /* Use the darker palette color as foreground on mono bitmaps */
225 if(readshort(&fh
.BitCount
) == 1) {
226 if(brightness(palette
[0]) > brightness(palette
[1]))
230 /* Search to the beginning of the image data */
231 lseek(fd
, (off_t
)readlong(&fh
.OffBits
), SEEK_SET
);
234 if(format
== FORMAT_NATIVE
)
235 memset(bitmap
, 0, totalsize
);
239 fb_data
*dest
= (fb_data
*)bitmap
;
242 /* loop to read rows and put them to buffer */
243 for (row
= 0; row
< height
; row
++) {
247 ret
= read(fd
, bmpbuf
, PaddedWidth
);
248 if (ret
!= PaddedWidth
) {
249 DEBUGF("error reading image, read returned: %d expected was: "
250 "%d\n", ret
, PaddedWidth
);
258 if(format
== FORMAT_MONO
) {
261 for (col
= 0; col
< width
; col
++) {
262 ret
= getpix(col
, bmpbuf
) ^ invert_pixel
;
264 bitmap
[width
* ((height
- row
- 1) / 8) + col
]
265 &= ~ 1 << ((height
- row
- 1) % 8);
267 bitmap
[width
* ((height
- row
- 1) / 8) + col
]
268 |= 1 << ((height
- row
- 1) % 8);
273 /* Mono -> 2gray (iriver H1xx) */
274 for (col
= 0; col
< width
; col
++) {
275 ret
= brightness(palette
[getpix(col
, bmpbuf
)]);
278 bitmap
[width
* ((height
- row
- 1) / 8) + col
]
279 &= ~ 1 << ((height
- row
- 1) % 8);
281 bitmap
[width
* ((height
- row
- 1) / 8) + col
]
282 |= 1 << ((height
- row
- 1) % 8);
286 #elif LCD_DEPTH == 16
289 for (col
= 0; col
< width
; col
++) {
290 ret
= getpix(col
, bmpbuf
);
291 unsigned short rgb
= (((palette
[ret
].red
>> 3) << 11) |
292 ((palette
[ret
].green
>> 2) << 5) |
293 ((palette
[ret
].blue
>> 3)));
294 dest
[width
* (height
- row
- 1) + col
] = rgb
;
303 if(format
== FORMAT_MONO
) {
306 for (col
= 0; col
< width
; col
++) {
311 ret
= brightness(rgb
);
313 bitmap
[width
* ((height
- row
- 1) / 8) + col
]
314 &= ~ 1 << ((height
- row
- 1) % 8);
316 bitmap
[width
* ((height
- row
- 1) / 8) + col
]
317 |= 1 << ((height
- row
- 1) % 8);
323 /* RGB24 -> 2gray (iriver H1xx) */
324 for (col
= 0; col
< width
; col
++) {
329 ret
= brightness(rgb
);
331 dest
[((height
- row
- 1)/4) * width
+ col
] |=
332 (~ret
& 0xC0) >> (2 * (~(height
- row
- 1) & 3));
336 #elif LCD_DEPTH == 16
339 for (col
= 0; col
< width
; col
++) {
340 unsigned short rgb
= LCD_RGBPACK(p
[2],p
[1],p
[0]);
341 dest
[width
* (height
- row
- 1) + col
] = rgb
;
352 /* returning image size: */
359 DEBUGF("totalsize: %d\n", totalsize
);
360 return totalsize
; /* return the used buffer size. */