summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2011-11-08 21:36:49 +0000
committerThomas Martitz <kugel@rockbox.org>2011-11-08 21:36:49 +0000
commitf443e7bbf7771ce3a79b1c2116b9cf216f15938f (patch)
treeeeaf47216f88c811529ade5a7c27bd76203bb02b
parent13209604c1512658e729d0bd9f1c54cf3e53568d (diff)
downloadrockbox-f443e7bbf7771ce3a79b1c2116b9cf216f15938f.tar.gz
rockbox-f443e7bbf7771ce3a79b1c2116b9cf216f15938f.zip
Support for transparency in 32bit bitmaps on color targets.
This uses the alpha blending capabilities introduced with anti-aliased fonts to draw bitmaps with transparency information. The bmp loader is extended to read this information (pass FORMAT_TRANSPARENT in format). The alpha information will be used when drawing the bitmap. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30937 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/recorder/bmp.c87
-rw-r--r--apps/recorder/bmp.h1
-rw-r--r--firmware/drivers/lcd-16bit-common.c58
-rw-r--r--firmware/export/lcd.h3
4 files changed, 109 insertions, 40 deletions
diff --git a/apps/recorder/bmp.c b/apps/recorder/bmp.c
index d6f61d1c87..819d2e6976 100644
--- a/apps/recorder/bmp.c
+++ b/apps/recorder/bmp.c
@@ -173,6 +173,7 @@ static inline void set_rgb_union(struct uint8_rgb *dst, union rgb_union src)
173 dst->red = src.red; 173 dst->red = src.red;
174 dst->green = src.green; 174 dst->green = src.green;
175 dst->blue = src.blue; 175 dst->blue = src.blue;
176 dst->alpha = 0xff;
176} 177}
177 178
178struct bmp_args { 179struct bmp_args {
@@ -189,6 +190,9 @@ struct bmp_args {
189 int cur_col; 190 int cur_col;
190 struct img_part part; 191 struct img_part part;
191#endif 192#endif
193 /* as read_part_line() goes through the rows it'll set this to true
194 * if it finds transparency. Initialize to false before calling */
195 bool alpha_detected;
192}; 196};
193 197
194static unsigned int read_part_line(struct bmp_args *ba) 198static unsigned int read_part_line(struct bmp_args *ba)
@@ -233,6 +237,7 @@ static unsigned int read_part_line(struct bmp_args *ba)
233#endif 237#endif
234 return 0; 238 return 0;
235 } 239 }
240
236 while (ibuf < ba->buf + (BM_MAX_WIDTH << 2)) 241 while (ibuf < ba->buf + (BM_MAX_WIDTH << 2))
237 { 242 {
238 switch (depth) 243 switch (depth)
@@ -274,6 +279,7 @@ static unsigned int read_part_line(struct bmp_args *ba)
274 component = data & 0xf8; 279 component = data & 0xf8;
275 component |= component >> 5; 280 component |= component >> 5;
276 buf->red = component; 281 buf->red = component;
282 buf->alpha = 0xff;
277 buf++; 283 buf++;
278 ibuf += 2; 284 ibuf += 2;
279 break; 285 break;
@@ -282,13 +288,12 @@ static unsigned int read_part_line(struct bmp_args *ba)
282 buf->blue = *ibuf++; 288 buf->blue = *ibuf++;
283 buf->green = *ibuf++; 289 buf->green = *ibuf++;
284 buf->red = *ibuf++; 290 buf->red = *ibuf++;
285 if (depth == 32) 291 buf->alpha = (depth == 32) ? *ibuf++ : 0xff;
286 ibuf++; 292 if (buf->alpha != 0xff) ba->alpha_detected = true;
287 buf++; 293 buf++;
288 break; 294 break;
289 } 295 }
290 } 296 }
291
292#if !defined(HAVE_LCD_COLOR) && \ 297#if !defined(HAVE_LCD_COLOR) && \
293 ((LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) || \ 298 ((LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) || \
294 defined(PLUGIN)) 299 defined(PLUGIN))
@@ -422,41 +427,40 @@ void output_row_8_native(uint32_t row, void * row_in,
422 } 427 }
423#endif /* LCD_PIXELFORMAT */ 428#endif /* LCD_PIXELFORMAT */
424#elif LCD_DEPTH == 16 429#elif LCD_DEPTH == 16
425#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
426 /* M:Robe 500 */
427 (void) fb_width;
428 fb_data *dest = (fb_data *)ctx->bm->data + row;
429 int delta = 127;
430 unsigned r, g, b;
431 for (col = 0; col < ctx->bm->width; col++) {
432 if (ctx->dither)
433 delta = DITHERXDY(col,dy);
434 r = qp->red;
435 g = qp->green;
436 b = (qp++)->blue;
437 r = (31 * r + (r >> 3) + delta) >> 8;
438 g = (63 * g + (g >> 2) + delta) >> 8;
439 b = (31 * b + (b >> 3) + delta) >> 8;
440 *dest = LCD_RGBPACK_LCD(r, g, b);
441 dest += ctx->bm->height;
442 }
443#else
444 /* iriver h300, colour iPods, X5 */ 430 /* iriver h300, colour iPods, X5 */
445 fb_data *dest = (fb_data *)ctx->bm->data + fb_width * row; 431 (void)fb_width;
432 fb_data *dest = STRIDE_MAIN((fb_data *)ctx->bm->data + fb_width * row,
433 (fb_data *)ctx->bm->data + row);
446 int delta = 127; 434 int delta = 127;
447 unsigned r, g, b; 435 unsigned r, g, b;
436 /* setup alpha channel buffer */
437 unsigned char *bm_alpha = NULL;
438 if (ctx->bm->alpha_offset > 0)
439 bm_alpha = ctx->bm->data + ctx->bm->alpha_offset;
440 if (bm_alpha)
441 bm_alpha += ctx->bm->width*row/2;
442
448 for (col = 0; col < ctx->bm->width; col++) { 443 for (col = 0; col < ctx->bm->width; col++) {
449 if (ctx->dither) 444 if (ctx->dither)
450 delta = DITHERXDY(col,dy); 445 delta = DITHERXDY(col,dy);
451 r = qp->red; 446 r = qp->red;
452 g = qp->green; 447 g = qp->green;
453 b = (qp++)->blue; 448 b = qp->blue;
454 r = (31 * r + (r >> 3) + delta) >> 8; 449 r = (31 * r + (r >> 3) + delta) >> 8;
455 g = (63 * g + (g >> 2) + delta) >> 8; 450 g = (63 * g + (g >> 2) + delta) >> 8;
456 b = (31 * b + (b >> 3) + delta) >> 8; 451 b = (31 * b + (b >> 3) + delta) >> 8;
457 *dest++ = LCD_RGBPACK_LCD(r, g, b); 452 *dest = LCD_RGBPACK_LCD(r, g, b);
453 dest += STRIDE_MAIN(1, ctx->bm->height);
454 if (bm_alpha) {
455 /* pack alpha channel for 2 pixels into 1 byte */
456 unsigned alpha = 255-qp->alpha;
457 if (col%2)
458 *bm_alpha++ |= alpha&0xf0;
459 else
460 *bm_alpha = alpha>>4;
461 }
462 qp++;
458 } 463 }
459#endif
460#endif /* LCD_DEPTH */ 464#endif /* LCD_DEPTH */
461} 465}
462#endif 466#endif
@@ -480,6 +484,7 @@ int read_bmp_fd(int fd,
480 int depth, numcolors, compression, totalsize; 484 int depth, numcolors, compression, totalsize;
481 int ret; 485 int ret;
482 bool return_size = format & FORMAT_RETURN_SIZE; 486 bool return_size = format & FORMAT_RETURN_SIZE;
487 bool read_alpha = format & FORMAT_TRANSPARENT;
483 488
484 unsigned char *bitmap = bm->data; 489 unsigned char *bitmap = bm->data;
485 struct uint8_rgb palette[256]; 490 struct uint8_rgb palette[256];
@@ -608,8 +613,14 @@ int read_bmp_fd(int fd,
608 613
609 if (cformat) 614 if (cformat)
610 totalsize = cformat->get_size(bm); 615 totalsize = cformat->get_size(bm);
611 else 616 else {
612 totalsize = BM_SIZE(bm->width,bm->height,format,remote); 617 totalsize = BM_SIZE(bm->width,bm->height,format,remote);
618#ifdef HAVE_REMOTE_LCD
619 if (!remote)
620#endif
621 if (depth == 32 && read_alpha) /* account for possible 4bit alpha per pixel */
622 totalsize += bm->width * bm->height / 2;
623 }
613 624
614 if(return_size) 625 if(return_size)
615 { 626 {
@@ -704,13 +715,21 @@ int read_bmp_fd(int fd,
704 715
705 memset(bitmap, 0, totalsize); 716 memset(bitmap, 0, totalsize);
706 717
718#ifdef HAVE_LCD_COLOR
719 if (read_alpha && depth == 32)
720 bm->alpha_offset = totalsize - (bm->width * bm->height / 2);
721 else
722 bm->alpha_offset = 0;
723#endif
724
707 struct bmp_args ba = { 725 struct bmp_args ba = {
708 .fd = fd, .padded_width = padded_width, .read_width = read_width, 726 .fd = fd, .padded_width = padded_width, .read_width = read_width,
709 .width = src_dim.width, .depth = depth, .palette = palette, 727 .width = src_dim.width, .depth = depth, .palette = palette,
710#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \ 728#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \
711 defined(HAVE_BMP_SCALING) || defined(PLUGIN) 729 defined(HAVE_BMP_SCALING) || defined(PLUGIN)
712 .cur_row = 0, .cur_col = 0, .part = {0,0} 730 .cur_row = 0, .cur_col = 0, .part = {0,0},
713#endif 731#endif
732 .alpha_detected = false,
714 }; 733 };
715 734
716#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \ 735#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \
@@ -759,7 +778,6 @@ int read_bmp_fd(int fd,
759 return -6; 778 return -6;
760 } 779 }
761#endif 780#endif
762
763 int row; 781 int row;
764 /* loop to read rows and put them to buffer */ 782 /* loop to read rows and put them to buffer */
765 for (row = rset.rowstart; row != rset.rowstop; row += rset.rowstep) { 783 for (row = rset.rowstart; row != rset.rowstop; row += rset.rowstep) {
@@ -858,5 +876,14 @@ int read_bmp_fd(int fd,
858 } 876 }
859#endif 877#endif
860 } 878 }
879#ifdef HAVE_LCD_COLOR
880 if (!ba.alpha_detected)
881 { /* if this has an alpha channel, totalsize accounts for it as well
882 * subtract if no actual alpha information was found */
883 if (bm->alpha_offset > 0)
884 totalsize -= bm->width*bm->height/2;
885 bm->alpha_offset = 0;
886 }
887#endif
861 return totalsize; /* return the used buffer size. */ 888 return totalsize; /* return the used buffer size. */
862} 889}
diff --git a/apps/recorder/bmp.h b/apps/recorder/bmp.h
index 31bd0730bd..3ddc3b66df 100644
--- a/apps/recorder/bmp.h
+++ b/apps/recorder/bmp.h
@@ -39,6 +39,7 @@ struct uint8_rgb {
39 uint8_t blue; 39 uint8_t blue;
40 uint8_t green; 40 uint8_t green;
41 uint8_t red; 41 uint8_t red;
42 uint8_t alpha;
42}; 43};
43 44
44struct dim { 45struct dim {
diff --git a/firmware/drivers/lcd-16bit-common.c b/firmware/drivers/lcd-16bit-common.c
index bbac2b295a..7b37bf7c30 100644
--- a/firmware/drivers/lcd-16bit-common.c
+++ b/firmware/drivers/lcd-16bit-common.c
@@ -229,7 +229,6 @@ void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width, int heig
229 lcd_mono_bitmap_part(src, 0, 0, width, x, y, width, height); 229 lcd_mono_bitmap_part(src, 0, 0, width, x, y, width, height);
230} 230}
231 231
232/* draw alpha bitmap for anti-alias font */
233#define ALPHA_COLOR_FONT_DEPTH 2 232#define ALPHA_COLOR_FONT_DEPTH 2
234#define ALPHA_COLOR_LOOKUP_SHIFT (1 << ALPHA_COLOR_FONT_DEPTH) 233#define ALPHA_COLOR_LOOKUP_SHIFT (1 << ALPHA_COLOR_FONT_DEPTH)
235#define ALPHA_COLOR_LOOKUP_SIZE ((1 << ALPHA_COLOR_LOOKUP_SHIFT) - 1) 234#define ALPHA_COLOR_LOOKUP_SIZE ((1 << ALPHA_COLOR_LOOKUP_SHIFT) - 1)
@@ -285,11 +284,17 @@ static inline unsigned blend_color(unsigned c, unsigned a)
285 return blend_two_colors(c, current_vp->fg_pattern, a); 284 return blend_two_colors(c, current_vp->fg_pattern, a);
286} 285}
287 286
288void ICODE_ATTR lcd_alpha_bitmap_part(const unsigned char *src, int src_x, 287/* Blend an image with an alpha channel
289 int src_y, int stride, int x, int y, 288 * if image is NULL, drawing will happen according to the drawmode
290 int width, int height) 289 * src is the alpha channel (4bit per pixel) */
290static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image,
291 const unsigned char *src, int src_x,
292 int src_y, int x, int y,
293 int width, int height,
294 int stride_image, int stride_src)
291{ 295{
292 fb_data *dst, *dst_row; 296 fb_data *dst, *dst_row;
297 const fb_data *image_row;
293 unsigned dmask = 0x00000000; 298 unsigned dmask = 0x00000000;
294 int drmode = current_vp->drawmode; 299 int drmode = current_vp->drawmode;
295 /* nothing to draw? */ 300 /* nothing to draw? */
@@ -356,13 +361,22 @@ void ICODE_ATTR lcd_alpha_bitmap_part(const unsigned char *src, int src_x,
356 { 361 {
357 dmask = ~dmask; 362 dmask = ~dmask;
358 } 363 }
364 /* sourcing from an image ignore drawmode.
365 * Set to DRMODE_BG as we use its code path in the switch below */
366 if (image != NULL)
367 {
368 dmask = 0;
369 drmode = DRMODE_BG;
370 }
359 371
360 dst_row = LCDADDR(x, y); 372 dst_row = LCDADDR(x, y);
361 373
362 int col, row = height; 374 int col, row = height;
363 unsigned data, pixels; 375 unsigned data, pixels;
364 unsigned skip_end = (stride - width); 376 unsigned skip_end = (stride_src - width);
365 unsigned skip_start = src_y * stride + src_x; 377 unsigned skip_start = src_y * stride_src + src_x;
378 unsigned skip_start_image = STRIDE_MAIN(src_y * stride_image + src_x,
379 src_x * stride_image + src_y);
366 380
367#ifdef ALPHA_BITMAP_READ_WORDS 381#ifdef ALPHA_BITMAP_READ_WORDS
368 uint32_t *src_w = (uint32_t *)((uintptr_t)src & ~3); 382 uint32_t *src_w = (uint32_t *)((uintptr_t)src & ~3);
@@ -379,6 +393,9 @@ void ICODE_ATTR lcd_alpha_bitmap_part(const unsigned char *src, int src_x,
379#ifdef ALPHA_BITMAP_READ_WORDS 393#ifdef ALPHA_BITMAP_READ_WORDS
380 pixels = 8 - pixels; 394 pixels = 8 - pixels;
381#endif 395#endif
396 if (image)
397 image += skip_start_image;
398 image_row = image;
382 399
383 /* go through the rows and update each pixel */ 400 /* go through the rows and update each pixel */
384 do 401 do
@@ -386,6 +403,12 @@ void ICODE_ATTR lcd_alpha_bitmap_part(const unsigned char *src, int src_x,
386 col = width; 403 col = width;
387 dst = dst_row; 404 dst = dst_row;
388 dst_row += ROW_INC; 405 dst_row += ROW_INC;
406 if (image_row) {
407 image = image_row;
408 image_row += STRIDE_MAIN(stride_image,1);
409 }
410 else
411 image = dst;
389#ifdef ALPHA_BITMAP_READ_WORDS 412#ifdef ALPHA_BITMAP_READ_WORDS
390#define UPDATE_SRC_ALPHA do { \ 413#define UPDATE_SRC_ALPHA do { \
391 if (--pixels) \ 414 if (--pixels) \
@@ -431,10 +454,11 @@ void ICODE_ATTR lcd_alpha_bitmap_part(const unsigned char *src, int src_x,
431 uintptr_t bo = lcd_backdrop_offset; 454 uintptr_t bo = lcd_backdrop_offset;
432 do 455 do
433 { 456 {
434 *dst = blend_two_colors(*dst, *(fb_data *)((uintptr_t)dst + bo), 457 *dst = blend_two_colors(*(fb_data *)((uintptr_t)dst + bo),
435 data & ALPHA_COLOR_LOOKUP_SIZE ); 458 *image, data & ALPHA_COLOR_LOOKUP_SIZE );
436 459
437 dst += COL_INC; 460 dst += COL_INC;
461 image += STRIDE_MAIN(1, stride_image);
438 UPDATE_SRC_ALPHA; 462 UPDATE_SRC_ALPHA;
439 } 463 }
440 while (--col); 464 while (--col);
@@ -443,9 +467,10 @@ void ICODE_ATTR lcd_alpha_bitmap_part(const unsigned char *src, int src_x,
443 { 467 {
444 do 468 do
445 { 469 {
446 *dst = blend_two_colors(*dst, current_vp->bg_pattern, 470 *dst = blend_two_colors(current_vp->bg_pattern,
447 data & ALPHA_COLOR_LOOKUP_SIZE ); 471 *image, data & ALPHA_COLOR_LOOKUP_SIZE );
448 dst += COL_INC; 472 dst += COL_INC;
473 image += STRIDE_MAIN(1, stride_image);
449 UPDATE_SRC_ALPHA; 474 UPDATE_SRC_ALPHA;
450 } 475 }
451 while (--col); 476 while (--col);
@@ -516,6 +541,15 @@ void ICODE_ATTR lcd_alpha_bitmap_part(const unsigned char *src, int src_x,
516 } while (--row); 541 } while (--row);
517} 542}
518 543
544
545/* draw alpha bitmap for anti-alias font */
546void ICODE_ATTR lcd_alpha_bitmap_part(const unsigned char *src, int src_x,
547 int src_y, int stride, int x, int y,
548 int width, int height)
549{
550 lcd_alpha_bitmap_part_mix(NULL, src, src_x, src_y, x, y, width, height, 0, stride);
551}
552
519/* Draw a partial bitmap (mono or native) including alpha channel */ 553/* Draw a partial bitmap (mono or native) including alpha channel */
520void ICODE_ATTR lcd_bmp_part(const struct bitmap* bm, int src_x, int src_y, 554void ICODE_ATTR lcd_bmp_part(const struct bitmap* bm, int src_x, int src_y,
521 int x, int y, int width, int height) 555 int x, int y, int width, int height)
@@ -523,6 +557,10 @@ void ICODE_ATTR lcd_bmp_part(const struct bitmap* bm, int src_x, int src_y,
523 int bitmap_stride = STRIDE_MAIN(bm->width, bm->height); 557 int bitmap_stride = STRIDE_MAIN(bm->width, bm->height);
524 if (bm->format == FORMAT_MONO) 558 if (bm->format == FORMAT_MONO)
525 lcd_mono_bitmap_part(bm->data, src_x, src_y, bitmap_stride, x, y, width, height); 559 lcd_mono_bitmap_part(bm->data, src_x, src_y, bitmap_stride, x, y, width, height);
560 else if (bm->alpha_offset > 0)
561 lcd_alpha_bitmap_part_mix((fb_data*)bm->data, bm->data+bm->alpha_offset,
562 src_x, src_y, x, y, width, height,
563 bitmap_stride, bm->width);
526 else 564 else
527 lcd_bitmap_transparent_part((fb_data*)bm->data, 565 lcd_bitmap_transparent_part((fb_data*)bm->data,
528 src_x, src_y, bitmap_stride, x, y, width, height); 566 src_x, src_y, bitmap_stride, x, y, width, height);
diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h
index 47ea94bca9..ad579820ad 100644
--- a/firmware/export/lcd.h
+++ b/firmware/export/lcd.h
@@ -468,6 +468,9 @@ struct bitmap {
468 int format; 468 int format;
469 unsigned char *maskdata; 469 unsigned char *maskdata;
470#endif 470#endif
471#ifdef HAVE_LCD_COLOR
472 int alpha_offset; /* byte-offset of alpha channel in data */
473#endif
471 unsigned char *data; 474 unsigned char *data;
472}; 475};
473 476