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 #ifdef ROCKBOX_LITTLE_ENDIAN
72 #define readshort(x) *(x)
73 #define readlong(x) *(x)
76 /* big endian functions */
77 static short readshort(short *value
) {
78 unsigned char* bytes
= (unsigned char*) value
;
79 return bytes
[0] | (bytes
[1] << 8);
82 static long readlong(long *value
) {
83 unsigned char* bytes
= (unsigned char*) value
;
84 return (long)bytes
[0] | ((long)bytes
[1] << 8) |
85 ((long)bytes
[2] << 16) | ((long)bytes
[3] << 24);
90 unsigned char brightness(struct rgb_quad color
)
92 return (3 * (unsigned int)color
.red
+ 6 * (unsigned int)color
.green
93 + (unsigned int)color
.blue
) / 10;
96 /* Function to get a pixel from a line. (Tomas: maybe a better way?) */
97 inline int getpix(int px
, unsigned char *bmpbuf
) {
99 int b
= (7 - (px
% 8));
101 return (bmpbuf
[a
] & (1 << b
)) != 0;
105 /******************************************************************************
108 * Reads a monochrome BMP file and puts the data in rockbox format in *bitmap.
110 *****************************************************************************/
111 int read_bmp_file(char* filename
,
116 struct Fileheader fh
;
117 int width
, height
, PaddedWidth
, PaddedHeight
;
118 int fd
, row
, col
, ret
;
119 struct rgb_quad palette
[256];
120 int invert_pixel
= 0;
124 char *bitmap
= bm
->data
;
126 unsigned char bmpbuf
[LCD_WIDTH
*sizeof(struct rgb_quad
)]; /* Buffer for one line */
133 if(format
& FORMAT_TRANSPARENT
) {
135 format
&= ~FORMAT_TRANSPARENT
;
140 fd
= open(filename
, O_RDONLY
);
142 /* Exit if file opening failed */
144 DEBUGF("error - can't open '%s' open returned: %d\n", filename
, fd
);
145 return (fd
* 10) - 1;
148 /* read fileheader */
149 ret
= read(fd
, &fh
, sizeof(struct Fileheader
));
152 return (ret
* 10 - 2);
155 if(ret
!= sizeof(struct Fileheader
)) {
156 DEBUGF("error - can't read Fileheader structure.");
161 /* Exit if too wide */
162 if (readlong(&fh
.Width
) > LCD_WIDTH
) {
163 DEBUGF("error - Bitmap is too wide (%d pixels, max is %d)\n",
164 readlong(&fh
.Width
), LCD_WIDTH
);
169 /* Exit if too high */
170 if (readlong(&fh
.Height
) > LCD_HEIGHT
) {
171 DEBUGF("error - Bitmap is too high (%d pixels, max is %d)\n",
172 readlong(&fh
.Height
), LCD_HEIGHT
);
177 /* Calculate image size */
178 height
= readlong(&fh
.Height
);
179 width
= readlong(&fh
.Width
);
180 depth
= readshort(&fh
.BitCount
);
182 /* 4-byte boundary aligned */
183 PaddedWidth
= (width
* depth
/ 8 + 3) & ~3;
186 if(format
== FORMAT_ANY
) {
188 format
= FORMAT_MONO
;
190 format
= FORMAT_NATIVE
;
194 /* PaddedHeight is for rockbox format. */
195 if(format
== FORMAT_MONO
) {
196 PaddedHeight
= (height
+ 7) / 8;
197 totalsize
= PaddedHeight
* width
;
200 PaddedHeight
= (height
+ 3) / 4;
202 PaddedHeight
= height
;
204 totalsize
= PaddedHeight
* width
* sizeof(fb_data
);
207 /* Check if this fits the buffer */
209 if (totalsize
> maxsize
) {
210 DEBUGF("error - Bitmap is too large to fit the supplied buffer: "
211 "%d bytes.\n", (PaddedHeight
* width
));
218 numcolors
= readlong(&fh
.ClrUsed
);
220 numcolors
= 1 << depth
;
222 if(read(fd
, palette
, numcolors
* sizeof(struct rgb_quad
))
223 != numcolors
* (int)sizeof(struct rgb_quad
))
225 DEBUGF("error - Can't read bitmap's color palette\n");
231 /* Use the darker palette color as foreground on mono bitmaps */
232 if(readshort(&fh
.BitCount
) == 1) {
233 if(brightness(palette
[0]) > brightness(palette
[1]))
237 /* Search to the beginning of the image data */
238 lseek(fd
, (off_t
)readlong(&fh
.OffBits
), SEEK_SET
);
241 if(format
== FORMAT_NATIVE
)
242 memset(bitmap
, 0, width
* height
/ 4);
246 fb_data
*dest
= (fb_data
*)bitmap
;
249 /* loop to read rows and put them to buffer */
250 for (row
= 0; row
< height
; row
++) {
254 ret
= read(fd
, bmpbuf
, PaddedWidth
);
255 if (ret
!= PaddedWidth
) {
256 DEBUGF("error reading image, read returned: %d expected was: "
257 "%d\n", ret
, PaddedWidth
);
265 if(format
== FORMAT_MONO
) {
268 for (col
= 0; col
< width
; col
++) {
269 ret
= getpix(col
, bmpbuf
) ^ invert_pixel
;
271 bitmap
[width
* ((height
- row
- 1) / 8) + col
]
272 &= ~ 1 << ((height
- row
- 1) % 8);
274 bitmap
[width
* ((height
- row
- 1) / 8) + col
]
275 |= 1 << ((height
- row
- 1) % 8);
280 /* Mono -> 2gray (iriver H1xx) */
281 for (col
= 0; col
< width
; col
++) {
282 ret
= brightness(palette
[getpix(col
, bmpbuf
)]);
285 bitmap
[width
* ((height
- row
- 1) / 8) + col
]
286 &= ~ 1 << ((height
- row
- 1) % 8);
288 bitmap
[width
* ((height
- row
- 1) / 8) + col
]
289 |= 1 << ((height
- row
- 1) % 8);
293 #elif LCD_DEPTH == 16
296 for (col
= 0; col
< width
; col
++) {
297 ret
= getpix(col
, bmpbuf
);
298 unsigned short rgb
= (((palette
[ret
].red
>> 3) << 11) |
299 ((palette
[ret
].green
>> 2) << 5) |
300 ((palette
[ret
].blue
>> 3)));
301 dest
[width
* (height
- row
- 1) + col
] = rgb
;
310 if(format
== FORMAT_MONO
) {
313 for (col
= 0; col
< width
; col
++) {
318 ret
= brightness(rgb
);
320 bitmap
[width
* ((height
- row
- 1) / 8) + col
]
321 &= ~ 1 << ((height
- row
- 1) % 8);
323 bitmap
[width
* ((height
- row
- 1) / 8) + col
]
324 |= 1 << ((height
- row
- 1) % 8);
330 /* RGB24 -> 2gray (iriver H1xx) */
331 for (col
= 0; col
< width
; col
++) {
336 ret
= brightness(rgb
);
338 dest
[((height
- row
- 1)/4) * width
+ col
] |=
339 (~ret
& 0xC0) >> (2 * (~(height
- row
- 1) & 3));
343 #elif LCD_DEPTH == 16
346 for (col
= 0; col
< width
; col
++) {
347 unsigned short rgb
= (((p
[2] >> 3) << 11) |
350 dest
[width
* (height
- row
- 1) + col
] = rgb
;
361 /* returning image size: */
368 DEBUGF("totalsize: %d\n", totalsize
);
369 return totalsize
; /* return the used buffer size. */