summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2006-01-28 12:12:42 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2006-01-28 12:12:42 +0000
commit745adad22a3803e7d7f3c14ba7ae2f8d3accb75a (patch)
tree644ae59e3b53daf9b534893763d2d0d7610f91fa /apps
parent9bd06032a37c60b17ae1643677ddc9a56a46d67f (diff)
downloadrockbox-745adad22a3803e7d7f3c14ba7ae2f8d3accb75a.tar.gz
rockbox-745adad22a3803e7d7f3c14ba7ae2f8d3accb75a.zip
Color BMP support
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8472 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/gui/gwps-common.c33
-rw-r--r--apps/gui/gwps.h6
-rw-r--r--apps/plugin.h8
-rw-r--r--apps/recorder/bmp.c240
-rw-r--r--apps/recorder/bmp.h14
-rw-r--r--apps/screen_access.c1
-rw-r--r--apps/screen_access.h2
7 files changed, 244 insertions, 60 deletions
diff --git a/apps/gui/gwps-common.c b/apps/gui/gwps-common.c
index d33bd8ccac..d15dbba888 100644
--- a/apps/gui/gwps-common.c
+++ b/apps/gui/gwps-common.c
@@ -216,12 +216,12 @@ bool wps_data_preload_tags(struct wps_data *data, char *buf,
216 } 216 }
217 217
218 /* load the image */ 218 /* load the image */
219 ret = read_bmp_file(imgname, &data->img[n].w, 219 data->img[n].bm.data = data->img_buf_ptr;
220 &data->img[n].h, data->img_buf_ptr, 220 ret = read_bmp_file(imgname, &data->img[n].bm,
221 data->img_buf_free); 221 data->img_buf_free,
222 FORMAT_ANY);
222 if (ret > 0) 223 if (ret > 0)
223 { 224 {
224 data->img[n].ptr = data->img_buf_ptr;
225 data->img_buf_ptr += ret; 225 data->img_buf_ptr += ret;
226 data->img_buf_free -= ret; 226 data->img_buf_free -= ret;
227 data->img[n].loaded = true; 227 data->img[n].loaded = true;
@@ -785,7 +785,7 @@ static void clear_image_pos(struct gui_wps *gwps, int n)
785 struct wps_data *data = gwps->data; 785 struct wps_data *data = gwps->data;
786 gwps->display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 786 gwps->display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
787 gwps->display->fillrect(data->img[n].x, data->img[n].y, 787 gwps->display->fillrect(data->img[n].x, data->img[n].y,
788 data->img[n].w, data->img[n].h); 788 data->img[n].bm.width, data->img[n].bm.height);
789 gwps->display->set_drawmode(DRMODE_SOLID); 789 gwps->display->set_drawmode(DRMODE_SOLID);
790} 790}
791#endif 791#endif
@@ -827,12 +827,13 @@ static const char* skip_conditional(struct gui_wps *gwps, const char* fmt,
827 if(n >= 'A' && n <= 'Z') 827 if(n >= 'A' && n <= 'Z')
828 n = n - 'A' + 26; 828 n = n - 'A' + 26;
829 if(last_x != data->img[n].x || last_y != data->img[n].y 829 if(last_x != data->img[n].x || last_y != data->img[n].y
830 || last_w != data->img[n].w || last_h != data->img[n].h) 830 || last_w != data->img[n].bm.width
831 || last_h != data->img[n].bm.height)
831 { 832 {
832 last_x = data->img[n].x; 833 last_x = data->img[n].x;
833 last_y = data->img[n].y; 834 last_y = data->img[n].y;
834 last_w = data->img[n].w; 835 last_w = data->img[n].bm.width;
835 last_h = data->img[n].h; 836 last_h = data->img[n].bm.height;
836 clear_image_pos(gwps,n); 837 clear_image_pos(gwps,n);
837 } 838 }
838 } 839 }
@@ -1243,9 +1244,19 @@ static void wps_draw_image(struct gui_wps *gwps, int n)
1243 else 1244 else
1244 display->set_drawmode(DRMODE_SOLID); 1245 display->set_drawmode(DRMODE_SOLID);
1245 1246
1246 display->mono_bitmap(data->img[n].ptr, data->img[n].x, 1247#if LCD_DEPTH > 1
1247 data->img[n].y, data->img[n].w, 1248 if(data->img[n].bm.format == FORMAT_MONO) {
1248 data->img[n].h); 1249#endif
1250 display->mono_bitmap(data->img[n].bm.data, data->img[n].x,
1251 data->img[n].y, data->img[n].bm.width,
1252 data->img[n].bm.height);
1253#if LCD_DEPTH > 1
1254 } else {
1255 display->bitmap((fb_data *)data->img[n].bm.data, data->img[n].x,
1256 data->img[n].y, data->img[n].bm.width,
1257 data->img[n].bm.height);
1258 }
1259#endif
1249} 1260}
1250static void wps_display_images(struct gui_wps *gwps, bool always) 1261static void wps_display_images(struct gui_wps *gwps, bool always)
1251{ 1262{
diff --git a/apps/gui/gwps.h b/apps/gui/gwps.h
index eb976c9220..8cd4c8f63e 100644
--- a/apps/gui/gwps.h
+++ b/apps/gui/gwps.h
@@ -255,11 +255,9 @@ extern bool keys_locked;
255 255
256#ifdef HAVE_LCD_BITMAP 256#ifdef HAVE_LCD_BITMAP
257struct gui_img{ 257struct gui_img{
258 unsigned char* ptr; /* pointer */ 258 struct bitmap bm;
259 int x; /* x-pos */ 259 int x; /* x-pos */
260 int y; /* y-pos */ 260 int y; /* y-pos */
261 int w; /* width */
262 int h; /* height */
263 bool loaded; /* load state */ 261 bool loaded; /* load state */
264 bool display; /* is to be displayed */ 262 bool display; /* is to be displayed */
265 bool always_display; /* not using the preload/display mechanism */ 263 bool always_display; /* not using the preload/display mechanism */
@@ -274,7 +272,7 @@ struct align_pos {
274 272
275#ifdef HAVE_LCD_BITMAP 273#ifdef HAVE_LCD_BITMAP
276#define MAX_IMAGES (26*2) /* a-z and A-Z */ 274#define MAX_IMAGES (26*2) /* a-z and A-Z */
277#define IMG_BUFSIZE (LCD_HEIGHT * LCD_WIDTH * MAX_IMAGES/10) / 8 275#define IMG_BUFSIZE (LCD_HEIGHT * LCD_WIDTH * MAX_IMAGES/10)
278#define WPS_MAX_LINES (LCD_HEIGHT/5+1) 276#define WPS_MAX_LINES (LCD_HEIGHT/5+1)
279#define FORMAT_BUFFER_SIZE 3072 277#define FORMAT_BUFFER_SIZE 3072
280#else 278#else
diff --git a/apps/plugin.h b/apps/plugin.h
index 747c9e099a..10ae180df7 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -97,12 +97,12 @@
97#define PLUGIN_MAGIC 0x526F634B /* RocK */ 97#define PLUGIN_MAGIC 0x526F634B /* RocK */
98 98
99/* increase this every time the api struct changes */ 99/* increase this every time the api struct changes */
100#define PLUGIN_API_VERSION 3 100#define PLUGIN_API_VERSION 4
101 101
102/* update this to latest version if a change to the api struct breaks 102/* update this to latest version if a change to the api struct breaks
103 backwards compatibility (and please take the opportunity to sort in any 103 backwards compatibility (and please take the opportunity to sort in any
104 new function which are "waiting" at the end of the function table) */ 104 new function which are "waiting" at the end of the function table) */
105#define PLUGIN_MIN_API_VERSION 1 105#define PLUGIN_MIN_API_VERSION 2
106 106
107/* plugin return codes */ 107/* plugin return codes */
108enum plugin_status { 108enum plugin_status {
@@ -420,8 +420,8 @@ struct plugin_api {
420 bool (*peak_meter_get_use_dbfs)(void); 420 bool (*peak_meter_get_use_dbfs)(void);
421#endif 421#endif
422#ifdef HAVE_LCD_BITMAP 422#ifdef HAVE_LCD_BITMAP
423 int (*read_bmp_file)(char* filename, int *get_width, int *get_height, 423 int (*read_bmp_file)(char* filename, struct bitmap *bm, int maxsize,
424 char *bitmap, int maxsize); 424 int format);
425 void (*screen_dump_set_hook)(void (*hook)(int fh)); 425 void (*screen_dump_set_hook)(void (*hook)(int fh));
426#endif 426#endif
427 int (*show_logo)(void); 427 int (*show_logo)(void);
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}
diff --git a/apps/recorder/bmp.h b/apps/recorder/bmp.h
index 5414ad893a..3bd8da74b7 100644
--- a/apps/recorder/bmp.h
+++ b/apps/recorder/bmp.h
@@ -16,6 +16,12 @@
16 * KIND, either express or implied. 16 * KIND, either express or implied.
17 * 17 *
18 ****************************************************************************/ 18 ****************************************************************************/
19#ifndef _BMP_H_
20#define _BMP_H_
21
22#include "config.h"
23#include "lcd.h"
24
19/********************************************************************* 25/*********************************************************************
20 * read_bmp_file() 26 * read_bmp_file()
21 * 27 *
@@ -24,7 +30,7 @@
24 * 30 *
25 **********************************************/ 31 **********************************************/
26int read_bmp_file(char* filename, 32int read_bmp_file(char* filename,
27 int *get_width, /* in pixels */ 33 struct bitmap *bm,
28 int *get_height, /* in pixels */ 34 int maxsize,
29 char *bitmap, 35 int format);
30 int maxsize);/* Maximum amount of bytes to write to bitmap */ 36#endif
diff --git a/apps/screen_access.c b/apps/screen_access.c
index dfe2b13a46..8f7f5c5aae 100644
--- a/apps/screen_access.c
+++ b/apps/screen_access.c
@@ -120,6 +120,7 @@ void screen_init(struct screen * screen, enum screen_type screen_type)
120 screen->mono_bitmap=&lcd_mono_bitmap; 120 screen->mono_bitmap=&lcd_mono_bitmap;
121 screen->set_drawmode=&lcd_set_drawmode; 121 screen->set_drawmode=&lcd_set_drawmode;
122#if LCD_DEPTH > 1 122#if LCD_DEPTH > 1
123 screen->bitmap=&lcd_bitmap;
123 screen->set_background=&lcd_set_background; 124 screen->set_background=&lcd_set_background;
124#endif 125#endif
125 screen->update_rect=&lcd_update_rect; 126 screen->update_rect=&lcd_update_rect;
diff --git a/apps/screen_access.h b/apps/screen_access.h
index 1c694e8d31..af52527fc0 100644
--- a/apps/screen_access.h
+++ b/apps/screen_access.h
@@ -82,6 +82,8 @@ struct screen
82 int style, int offset); 82 int style, int offset);
83 void (*mono_bitmap)(const unsigned char *src, 83 void (*mono_bitmap)(const unsigned char *src,
84 int x, int y, int width, int height); 84 int x, int y, int width, int height);
85 void (*bitmap)(const fb_data *src,
86 int x, int y, int width, int height);
85 void (*set_drawmode)(int mode); 87 void (*set_drawmode)(int mode);
86#if (LCD_DEPTH > 1) || (LCD_REMOTE_DEPTH > 1) 88#if (LCD_DEPTH > 1) || (LCD_REMOTE_DEPTH > 1)
87 void (*set_background)(unsigned background); 89 void (*set_background)(unsigned background);