summaryrefslogtreecommitdiff
path: root/apps/recorder/bmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/recorder/bmp.c')
-rw-r--r--apps/recorder/bmp.c240
1 files changed, 203 insertions, 37 deletions
diff --git a/apps/recorder/bmp.c b/apps/recorder/bmp.c
index d2be8c9172..61d7430bb6 100644
--- a/apps/recorder/bmp.c
+++ b/apps/recorder/bmp.c
@@ -26,11 +26,13 @@
26 26
27#include <stdio.h> 27#include <stdio.h>
28#include <stdlib.h> 28#include <stdlib.h>
29 29#include <string.h>
30#include "debug.h" 30#include "debug.h"
31#include "lcd.h" 31#include "lcd.h"
32#include "file.h" 32#include "file.h"
33#include "autoconf.h" 33#include "config.h"
34#include "bmp.h"
35#include "lcd.h"
34 36
35#ifdef __GNUC__ 37#ifdef __GNUC__
36#define STRUCT_PACKED __attribute__((packed)) 38#define STRUCT_PACKED __attribute__((packed))
@@ -59,6 +61,12 @@ struct Fileheader {
59 unsigned long ClrImportant; /* important color count */ 61 unsigned long ClrImportant; /* important color count */
60} STRUCT_PACKED; 62} STRUCT_PACKED;
61 63
64struct rgb_quad { /* Little endian */
65 unsigned char blue;
66 unsigned char green;
67 unsigned char red;
68 unsigned char reserved;
69} STRUCT_PACKED;
62 70
63#ifdef ROCKBOX_LITTLE_ENDIAN 71#ifdef ROCKBOX_LITTLE_ENDIAN
64#define readshort(x) *(x) 72#define readshort(x) *(x)
@@ -79,6 +87,19 @@ static long readlong(long *value) {
79 87
80#endif 88#endif
81 89
90unsigned char brightness(struct rgb_quad color)
91{
92 return (3 * (unsigned int)color.red + 6 * (unsigned int)color.green
93 + (unsigned int)color.blue) / 10;
94}
95
96/* Function to get a pixel from a line. (Tomas: maybe a better way?) */
97inline int getpix(int px, unsigned char *bmpbuf) {
98 int a = (px / 8);
99 int b = (7 - (px % 8));
100
101 return (bmpbuf[a] & (1 << b)) != 0;
102}
82 103
83 104
84/****************************************************************************** 105/******************************************************************************
@@ -88,16 +109,26 @@ static long readlong(long *value) {
88 * 109 *
89 *****************************************************************************/ 110 *****************************************************************************/
90int read_bmp_file(char* filename, 111int read_bmp_file(char* filename,
91 int *get_width, /* in pixels */ 112 struct bitmap *bm,
92 int *get_height, /* in pixels */ 113 int maxsize,
93 char *bitmap, 114 int format)
94 int maxsize) /* Maximum amount of bytes to write to bitmap */
95{ 115{
96 struct Fileheader fh; 116 struct Fileheader fh;
97 int bitmap_width, bitmap_height, PaddedWidth, PaddedHeight; 117 int width, height, PaddedWidth, PaddedHeight;
98 int fd, row, col, ret; 118 int fd, row, col, ret;
99 char bmpbuf[(LCD_WIDTH / 8 + 3) & ~3]; /* Buffer for one line */ 119 struct rgb_quad palette[256];
120 int invert_pixel = 0;
121 int numcolors;
122 int depth;
123 int totalsize;
124 char *bitmap = bm->data;
125
126 unsigned char bmpbuf[LCD_WIDTH*sizeof(struct rgb_quad)]; /* Buffer for one line */
100 127
128#if LCD_DEPTH == 1
129 (void)format;
130#endif
131
101 fd = open(filename, O_RDONLY); 132 fd = open(filename, O_RDONLY);
102 133
103 /* Exit if file opening failed */ 134 /* Exit if file opening failed */
@@ -119,14 +150,6 @@ int read_bmp_file(char* filename,
119 return -3; 150 return -3;
120 } 151 }
121 152
122 /* Exit if not monochrome */
123 if (readshort(&fh.BitCount) != 1) {
124 DEBUGF("error - Bitmap must be in 1 bit per pixel format. "
125 "This one is: %d\n", readshort(&fh.BitCount));
126 close(fd);
127 return -4;
128 }
129
130 /* Exit if too wide */ 153 /* Exit if too wide */
131 if (readlong(&fh.Width) > LCD_WIDTH) { 154 if (readlong(&fh.Width) > LCD_WIDTH) {
132 DEBUGF("error - Bitmap is too wide (%d pixels, max is %d)\n", 155 DEBUGF("error - Bitmap is too wide (%d pixels, max is %d)\n",
@@ -144,28 +167,80 @@ int read_bmp_file(char* filename,
144 } 167 }
145 168
146 /* Calculate image size */ 169 /* Calculate image size */
147 bitmap_height = readlong(&fh.Height); 170 height = readlong(&fh.Height);
148 bitmap_width = readlong(&fh.Width); 171 width = readlong(&fh.Width);
149 /* Paddedwidth is for BMP files. */ 172 depth = readshort(&fh.BitCount);
150 PaddedWidth = ((bitmap_width + 31) & (~0x1f)) / 8; 173
174 /* 4-byte boundary aligned */
175 PaddedWidth = (width * depth / 8 + 3) & ~3;
176
177#if LCD_DEPTH > 1
178 if(format == FORMAT_ANY) {
179 if(depth == 1)
180 format = FORMAT_MONO;
181 else
182 format = FORMAT_NATIVE;
183 }
184#endif
185
151 /* PaddedHeight is for rockbox format. */ 186 /* PaddedHeight is for rockbox format. */
152 PaddedHeight = (bitmap_height + 7) / 8; 187 if(format == FORMAT_MONO) {
188 PaddedHeight = (height + 7) / 8;
189 totalsize = PaddedHeight * width;
190 } else {
191#if LCD_DEPTH == 2
192 PaddedHeight = height/4;
193#else
194 PaddedHeight = height;
195#endif
196 totalsize = PaddedHeight * width * sizeof(fb_data);
197 }
153 198
154 /* Check if this fits the buffer */ 199 /* Check if this fits the buffer */
155 if ((PaddedHeight * bitmap_width) > maxsize) { 200
201 if (totalsize > maxsize) {
156 DEBUGF("error - Bitmap is too large to fit the supplied buffer: " 202 DEBUGF("error - Bitmap is too large to fit the supplied buffer: "
157 "%d bytes.\n", (PaddedHeight * bitmap_width)); 203 "%d bytes.\n", (PaddedHeight * width));
158 close(fd); 204 close(fd);
159 return -7; 205 return -7;
160 } 206 }
161 207
208 if (depth <= 8)
209 {
210 numcolors = readlong(&fh.ClrUsed);
211 if (numcolors == 0)
212 numcolors = 1 << depth;
213
214 if(read(fd, palette, numcolors * sizeof(struct rgb_quad))
215 != numcolors * (int)sizeof(struct rgb_quad))
216 {
217 DEBUGF("error - Can't read bitmap's color palette\n");
218 close(fd);
219 return -8;
220 }
221 }
222
223 /* Use the darker palette color as foreground on mono bitmaps */
224 if(readshort(&fh.BitCount) == 1) {
225 if(brightness(palette[0]) > brightness(palette[1]))
226 invert_pixel = 1;
227 }
228
162 /* Search to the beginning of the image data */ 229 /* Search to the beginning of the image data */
163 lseek(fd, (off_t)readlong(&fh.OffBits), SEEK_SET); 230 lseek(fd, (off_t)readlong(&fh.OffBits), SEEK_SET);
164 231
232#if LCD_DEPTH == 2
233 if(format == FORMAT_NATIVE)
234 memset(bitmap, 0, width * height / 4);
235#endif
236
237#if LCD_DEPTH > 1
238 fb_data *dest = (fb_data *)bitmap;
239#endif
240
165 /* loop to read rows and put them to buffer */ 241 /* loop to read rows and put them to buffer */
166 for (row = 0; row < bitmap_height; row++) { 242 for (row = 0; row < height; row++) {
167 int bitsel = 1 << ((bitmap_height - row - 1) % 8); 243 unsigned char *p;
168 int bytesel = bitmap_width * ((bitmap_height - row - 1) / 8);
169 244
170 /* read one row */ 245 /* read one row */
171 ret = read(fd, bmpbuf, PaddedWidth); 246 ret = read(fd, bmpbuf, PaddedWidth);
@@ -173,24 +248,115 @@ int read_bmp_file(char* filename,
173 DEBUGF("error reading image, read returned: %d expected was: " 248 DEBUGF("error reading image, read returned: %d expected was: "
174 "%d\n", ret, PaddedWidth); 249 "%d\n", ret, PaddedWidth);
175 close(fd); 250 close(fd);
176 return -8; 251 return -9;
177 } 252 }
178 253
179 /* loop though the pixels in this line. */ 254 switch(depth) {
180 for (col = 0; col < bitmap_width; col++) { 255 case 1:
181 ret = (bmpbuf[col/8] & (1 << (7 - (col % 8)))) != 0; 256#if LCD_DEPTH > 1
182 if (ret == 1) 257 if(format == FORMAT_MONO) {
183 bitmap[bytesel + col] &= ~bitsel; 258#endif
184 else 259 /* Mono -> Mono */
185 bitmap[bytesel + col] |= bitsel; 260 for (col = 0; col < width; col++) {
261 ret = getpix(col, bmpbuf) ^ invert_pixel;
262 if (ret == 1) {
263 bitmap[width * ((height - row - 1) / 8) + col]
264 &= ~ 1 << ((height - row - 1) % 8);
265 } else {
266 bitmap[width * ((height - row - 1) / 8) + col]
267 |= 1 << ((height - row - 1) % 8);
268 }
269 }
270#if LCD_DEPTH == 2
271 } else {
272 /* Mono -> 2gray (iriver H1xx) */
273 for (col = 0; col < width; col++) {
274 ret = brightness(palette[getpix(col, bmpbuf)]);
275
276 if (ret > 96) {
277 bitmap[width * ((height - row - 1) / 8) + col]
278 &= ~ 1 << ((height - row - 1) % 8);
279 } else {
280 bitmap[width * ((height - row - 1) / 8) + col]
281 |= 1 << ((height - row - 1) % 8);
282 }
283 }
284 }
285#elif LCD_DEPTH == 16
286 } else {
287 /* Mono -> RGB16 */
288 for (col = 0; col < width; col++) {
289 ret = getpix(col, bmpbuf);
290 unsigned short rgb = (((palette[ret].red >> 3) << 11) |
291 ((palette[ret].green >> 2) << 5) |
292 ((palette[ret].blue >> 3)));
293 dest[width * (height - row - 1) + col] = rgb;
294 }
295 }
296#endif
297 break;
298
299 case 24:
300 p = bmpbuf;
301#if LCD_DEPTH > 1
302 if(format == FORMAT_MONO) {
303#endif
304 /* RGB24 -> mono */
305 for (col = 0; col < width; col++) {
306 struct rgb_quad rgb;
307 rgb.red = p[2];
308 rgb.green = p[1];
309 rgb.blue = p[0];
310 ret = brightness(rgb);
311 if (ret > 96) {
312 bitmap[width * ((height - row - 1) / 8) + col]
313 &= ~ 1 << ((height - row - 1) % 8);
314 } else {
315 bitmap[width * ((height - row - 1) / 8) + col]
316 |= 1 << ((height - row - 1) % 8);
317 }
318 p += 3;
319 }
320#if LCD_DEPTH == 2
321 } else {
322 /* RGB24 -> 2gray (iriver H1xx) */
323 for (col = 0; col < width; col++) {
324 struct rgb_quad rgb;
325 rgb.red = p[2];
326 rgb.green = p[1];
327 rgb.blue = p[0];
328 ret = brightness(rgb);
329
330 dest[((height - row - 1)/4) * width + col] |=
331 (~ret & 0xC0) >> (2 * (~(height - row - 1) & 3));
332 p += 3;
333 }
334 }
335#elif LCD_DEPTH == 16
336 } else {
337 /* RGB24 -> RGB16 */
338 for (col = 0; col < width; col++) {
339 unsigned short rgb = (((p[2] >> 3) << 11) |
340 ((p[1] >> 2) << 5) |
341 ((p[0] >> 3)));
342 dest[width * (height - row - 1) + col] = rgb;
343 p += 3;
344 }
345 }
346#endif
347 break;
186 } 348 }
187 } 349 }
188 350
189 close(fd); 351 close(fd);
190 352
191 /* returning image size: */ 353 /* returning image size: */
192 *get_width = bitmap_width; 354 bm->width = width;
193 *get_height = bitmap_height; 355 bm->height = height;
356#if LCD_DEPTH > 1
357 bm->format = format;
358#endif
194 359
195 return (PaddedHeight * bitmap_width); /* return the used buffer size. */ 360DEBUGF("totalsize: %d\n", totalsize);
361 return totalsize; /* return the used buffer size. */
196} 362}