summaryrefslogtreecommitdiffstats
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.tar.bz2
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,
}
/* load the image */
- ret = read_bmp_file(imgname, &data->img[n].w,
- &data->img[n].h, data->img_buf_ptr,
- data->img_buf_free);
+ data->img[n].bm.data = data->img_buf_ptr;
+ ret = read_bmp_file(imgname, &data->img[n].bm,
+ data->img_buf_free,
+ FORMAT_ANY);
if (ret > 0)
{
- data->img[n].ptr = data->img_buf_ptr;
data->img_buf_ptr += ret;
data->img_buf_free -= ret;
data->img[n].loaded = true;
@@ -785,7 +785,7 @@ static void clear_image_pos(struct gui_wps *gwps, int n)
struct wps_data *data = gwps->data;
gwps->display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
gwps->display->fillrect(data->img[n].x, data->img[n].y,
- data->img[n].w, data->img[n].h);
+ data->img[n].bm.width, data->img[n].bm.height);
gwps->display->set_drawmode(DRMODE_SOLID);
}
#endif
@@ -827,12 +827,13 @@ static const char* skip_conditional(struct gui_wps *gwps, const char* fmt,
if(n >= 'A' && n <= 'Z')
n = n - 'A' + 26;
if(last_x != data->img[n].x || last_y != data->img[n].y
- || last_w != data->img[n].w || last_h != data->img[n].h)
+ || last_w != data->img[n].bm.width
+ || last_h != data->img[n].bm.height)
{
last_x = data->img[n].x;
last_y = data->img[n].y;
- last_w = data->img[n].w;
- last_h = data->img[n].h;
+ last_w = data->img[n].bm.width;
+ last_h = data->img[n].bm.height;
clear_image_pos(gwps,n);
}
}
@@ -1243,9 +1244,19 @@ static void wps_draw_image(struct gui_wps *gwps, int n)
else
display->set_drawmode(DRMODE_SOLID);
- display->mono_bitmap(data->img[n].ptr, data->img[n].x,
- data->img[n].y, data->img[n].w,
- data->img[n].h);
+#if LCD_DEPTH > 1
+ if(data->img[n].bm.format == FORMAT_MONO) {
+#endif
+ display->mono_bitmap(data->img[n].bm.data, data->img[n].x,
+ data->img[n].y, data->img[n].bm.width,
+ data->img[n].bm.height);
+#if LCD_DEPTH > 1
+ } else {
+ display->bitmap((fb_data *)data->img[n].bm.data, data->img[n].x,
+ data->img[n].y, data->img[n].bm.width,
+ data->img[n].bm.height);
+ }
+#endif
}
static void wps_display_images(struct gui_wps *gwps, bool always)
{
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;
#ifdef HAVE_LCD_BITMAP
struct gui_img{
- unsigned char* ptr; /* pointer */
+ struct bitmap bm;
int x; /* x-pos */
int y; /* y-pos */
- int w; /* width */
- int h; /* height */
bool loaded; /* load state */
bool display; /* is to be displayed */
bool always_display; /* not using the preload/display mechanism */
@@ -274,7 +272,7 @@ struct align_pos {
#ifdef HAVE_LCD_BITMAP
#define MAX_IMAGES (26*2) /* a-z and A-Z */
-#define IMG_BUFSIZE (LCD_HEIGHT * LCD_WIDTH * MAX_IMAGES/10) / 8
+#define IMG_BUFSIZE (LCD_HEIGHT * LCD_WIDTH * MAX_IMAGES/10)
#define WPS_MAX_LINES (LCD_HEIGHT/5+1)
#define FORMAT_BUFFER_SIZE 3072
#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 @@
#define PLUGIN_MAGIC 0x526F634B /* RocK */
/* increase this every time the api struct changes */
-#define PLUGIN_API_VERSION 3
+#define PLUGIN_API_VERSION 4
/* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any
new function which are "waiting" at the end of the function table) */
-#define PLUGIN_MIN_API_VERSION 1
+#define PLUGIN_MIN_API_VERSION 2
/* plugin return codes */
enum plugin_status {
@@ -420,8 +420,8 @@ struct plugin_api {
bool (*peak_meter_get_use_dbfs)(void);
#endif
#ifdef HAVE_LCD_BITMAP
- int (*read_bmp_file)(char* filename, int *get_width, int *get_height,
- char *bitmap, int maxsize);
+ int (*read_bmp_file)(char* filename, struct bitmap *bm, int maxsize,
+ int format);
void (*screen_dump_set_hook)(void (*hook)(int fh));
#endif
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 @@
#include <stdio.h>
#include <stdlib.h>
-
+#include <string.h>
#include "debug.h"
#include "lcd.h"
#include "file.h"
-#include "autoconf.h"
+#include "config.h"
+#include "bmp.h"
+#include "lcd.h"
#ifdef __GNUC__
#define STRUCT_PACKED __attribute__((packed))
@@ -59,6 +61,12 @@ struct Fileheader {
unsigned long ClrImportant; /* important color count */
} STRUCT_PACKED;
+struct rgb_quad { /* Little endian */
+ unsigned char blue;
+ unsigned char green;
+ unsigned char red;
+ unsigned char reserved;
+} STRUCT_PACKED;
#ifdef ROCKBOX_LITTLE_ENDIAN
#define readshort(x) *(x)
@@ -79,6 +87,19 @@ static long readlong(long *value) {
#endif
+unsigned char brightness(struct rgb_quad color)
+{
+ return (3 * (unsigned int)color.red + 6 * (unsigned int)color.green
+ + (unsigned int)color.blue) / 10;
+}
+
+/* Function to get a pixel from a line. (Tomas: maybe a better way?) */
+inline int getpix(int px, unsigned char *bmpbuf) {
+ int a = (px / 8);
+ int b = (7 - (px % 8));
+
+ return (bmpbuf[a] & (1 << b)) != 0;
+}
/******************************************************************************
@@ -88,16 +109,26 @@ static long readlong(long *value) {
*
*****************************************************************************/
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 bitmap *bm,
+ int maxsize,
+ int format)
{
struct Fileheader fh;
- int bitmap_width, bitmap_height, PaddedWidth, PaddedHeight;
+ int width, height, PaddedWidth, PaddedHeight;
int fd, row, col, ret;
- char bmpbuf[(LCD_WIDTH / 8 + 3) & ~3]; /* Buffer for one line */
+ struct rgb_quad palette[256];
+ int invert_pixel = 0;
+ int numcolors;
+ int depth;
+ int totalsize;
+ char *bitmap = bm->data;
+
+ unsigned char bmpbuf[LCD_WIDTH*sizeof(struct rgb_quad)]; /* Buffer for one line */
+#if LCD_DEPTH == 1
+ (void)format;
+#endif
+
fd = open(filename, O_RDONLY);
/* Exit if file opening failed */
@@ -119,14 +150,6 @@ int read_bmp_file(char* filename,
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",
@@ -144,28 +167,80 @@ int read_bmp_file(char* filename,
}
/* Calculate image size */
- bitmap_height = readlong(&fh.Height);
- bitmap_width = readlong(&fh.Width);
- /* Paddedwidth is for BMP files. */
- PaddedWidth = ((bitmap_width + 31) & (~0x1f)) / 8;
+ height = readlong(&fh.Height);
+ width = readlong(&fh.Width);
+ depth = readshort(&fh.BitCount);
+
+ /* 4-byte boundary aligned */
+ PaddedWidth = (width * depth / 8 + 3) & ~3;
+
+#if LCD_DEPTH > 1
+ if(format == FORMAT_ANY) {
+ if(depth == 1)
+ format = FORMAT_MONO;
+ else
+ format = FORMAT_NATIVE;
+ }
+#endif
+
/* PaddedHeight is for rockbox format. */
- PaddedHeight = (bitmap_height + 7) / 8;
+ if(format == FORMAT_MONO) {
+ PaddedHeight = (height + 7) / 8;
+ totalsize = PaddedHeight * width;
+ } else {
+#if LCD_DEPTH == 2
+ PaddedHeight = height/4;
+#else
+ PaddedHeight = height;
+#endif
+ totalsize = PaddedHeight * width * sizeof(fb_data);
+ }
/* Check if this fits the buffer */
- if ((PaddedHeight * bitmap_width) > maxsize) {
+
+ if (totalsize > maxsize) {
DEBUGF("error - Bitmap is too large to fit the supplied buffer: "
- "%d bytes.\n", (PaddedHeight * bitmap_width));
+ "%d bytes.\n", (PaddedHeight * width));
close(fd);
return -7;
}
+ if (depth <= 8)
+ {
+ numcolors = readlong(&fh.ClrUsed);
+ if (numcolors == 0)
+ numcolors = 1 << depth;
+
+ if(read(fd, palette, numcolors * sizeof(struct rgb_quad))
+ != numcolors * (int)sizeof(struct rgb_quad))
+ {
+ DEBUGF("error - Can't read bitmap's color palette\n");
+ close(fd);
+ return -8;
+ }
+ }
+
+ /* Use the darker palette color as foreground on mono bitmaps */
+ if(readshort(&fh.BitCount) == 1) {
+ if(brightness(palette[0]) > brightness(palette[1]))
+ invert_pixel = 1;
+ }
+
/* Search to the beginning of the image data */
lseek(fd, (off_t)readlong(&fh.OffBits), SEEK_SET);
+#if LCD_DEPTH == 2
+ if(format == FORMAT_NATIVE)
+ memset(bitmap, 0, width * height / 4);
+#endif
+
+#if LCD_DEPTH > 1
+ fb_data *dest = (fb_data *)bitmap;
+#endif
+
/* loop to read rows and put them to buffer */
- for (row = 0; row < bitmap_height; row++) {
- int bitsel = 1 << ((bitmap_height - row - 1) % 8);
- int bytesel = bitmap_width * ((bitmap_height - row - 1) / 8);
+ for (row = 0; row < height; row++) {
+ unsigned char *p;
/* read one row */
ret = read(fd, bmpbuf, PaddedWidth);
@@ -173,24 +248,115 @@ int read_bmp_file(char* filename,
DEBUGF("error reading image, read returned: %d expected was: "
"%d\n", ret, PaddedWidth);
close(fd);
- return -8;
+ return -9;
}
- /* loop though the pixels in this line. */
- for (col = 0; col < bitmap_width; col++) {
- ret = (bmpbuf[col/8] & (1 << (7 - (col % 8)))) != 0;
- if (ret == 1)
- bitmap[bytesel + col] &= ~bitsel;
- else
- bitmap[bytesel + col] |= bitsel;
+ switch(depth) {
+ case 1:
+#if LCD_DEPTH > 1
+ if(format == FORMAT_MONO) {
+#endif
+ /* Mono -> Mono */
+ for (col = 0; col < width; col++) {
+ ret = getpix(col, bmpbuf) ^ invert_pixel;
+ if (ret == 1) {
+ bitmap[width * ((height - row - 1) / 8) + col]
+ &= ~ 1 << ((height - row - 1) % 8);
+ } else {
+ bitmap[width * ((height - row - 1) / 8) + col]
+ |= 1 << ((height - row - 1) % 8);
+ }
+ }
+#if LCD_DEPTH == 2
+ } else {
+ /* Mono -> 2gray (iriver H1xx) */
+ for (col = 0; col < width; col++) {
+ ret = brightness(palette[getpix(col, bmpbuf)]);
+
+ if (ret > 96) {
+ bitmap[width * ((height - row - 1) / 8) + col]
+ &= ~ 1 << ((height - row - 1) % 8);
+ } else {
+ bitmap[width * ((height - row - 1) / 8) + col]
+ |= 1 << ((height - row - 1) % 8);
+ }
+ }
+ }
+#elif LCD_DEPTH == 16
+ } else {
+ /* Mono -> RGB16 */
+ for (col = 0; col < width; col++) {
+ ret = getpix(col, bmpbuf);
+ unsigned short rgb = (((palette[ret].red >> 3) << 11) |
+ ((palette[ret].green >> 2) << 5) |
+ ((palette[ret].blue >> 3)));
+ dest[width * (height - row - 1) + col] = rgb;
+ }
+ }
+#endif
+ break;
+
+ case 24:
+ p = bmpbuf;
+#if LCD_DEPTH > 1
+ if(format == FORMAT_MONO) {
+#endif
+ /* RGB24 -> mono */
+ for (col = 0; col < width; col++) {
+ struct rgb_quad rgb;
+ rgb.red = p[2];
+ rgb.green = p[1];
+ rgb.blue = p[0];
+ ret = brightness(rgb);
+ if (ret > 96) {
+ bitmap[width * ((height - row - 1) / 8) + col]
+ &= ~ 1 << ((height - row - 1) % 8);
+ } else {
+ bitmap[width * ((height - row - 1) / 8) + col]
+ |= 1 << ((height - row - 1) % 8);
+ }
+ p += 3;
+ }
+#if LCD_DEPTH == 2
+ } else {
+ /* RGB24 -> 2gray (iriver H1xx) */
+ for (col = 0; col < width; col++) {
+ struct rgb_quad rgb;
+ rgb.red = p[2];
+ rgb.green = p[1];
+ rgb.blue = p[0];
+ ret = brightness(rgb);
+
+ dest[((height - row - 1)/4) * width + col] |=
+ (~ret & 0xC0) >> (2 * (~(height - row - 1) & 3));
+ p += 3;
+ }
+ }
+#elif LCD_DEPTH == 16
+ } else {
+ /* RGB24 -> RGB16 */
+ for (col = 0; col < width; col++) {
+ unsigned short rgb = (((p[2] >> 3) << 11) |
+ ((p[1] >> 2) << 5) |
+ ((p[0] >> 3)));
+ dest[width * (height - row - 1) + col] = rgb;
+ p += 3;
+ }
+ }
+#endif
+ break;
}
}
close(fd);
/* returning image size: */
- *get_width = bitmap_width;
- *get_height = bitmap_height;
+ bm->width = width;
+ bm->height = height;
+#if LCD_DEPTH > 1
+ bm->format = format;
+#endif
- return (PaddedHeight * bitmap_width); /* return the used buffer size. */
+DEBUGF("totalsize: %d\n", totalsize);
+ return totalsize; /* return the used buffer size. */
}
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 @@
* KIND, either express or implied.
*
****************************************************************************/
+#ifndef _BMP_H_
+#define _BMP_H_
+
+#include "config.h"
+#include "lcd.h"
+
/*********************************************************************
* read_bmp_file()
*
@@ -24,7 +30,7 @@
*
**********************************************/
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 bitmap *bm,
+ int maxsize,
+ int format);
+#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)
screen->mono_bitmap=&lcd_mono_bitmap;
screen->set_drawmode=&lcd_set_drawmode;
#if LCD_DEPTH > 1
+ screen->bitmap=&lcd_bitmap;
screen->set_background=&lcd_set_background;
#endif
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
int style, int offset);
void (*mono_bitmap)(const unsigned char *src,
int x, int y, int width, int height);
+ void (*bitmap)(const fb_data *src,
+ int x, int y, int width, int height);
void (*set_drawmode)(int mode);
#if (LCD_DEPTH > 1) || (LCD_REMOTE_DEPTH > 1)
void (*set_background)(unsigned background);