diff --git a/gtk/bitmap.c b/gtk/bitmap.c index 96e9edaee..4474b074f 100644 --- a/gtk/bitmap.c +++ b/gtk/bitmap.c @@ -187,48 +187,54 @@ unsigned char *bitmap_get_buffer(void *vbitmap) struct bitmap *gbitmap = (struct bitmap *)vbitmap; int pixel_loop; int pixel_count; - uint32_t *pixels; - uint32_t pixel; + uint8_t *pixels; + uint32_t t, r, g, b; cairo_format_t fmt; assert(gbitmap); cairo_surface_flush(gbitmap->surface); - pixels = (uint32_t *)cairo_image_surface_get_data(gbitmap->surface); + pixels = cairo_image_surface_get_data(gbitmap->surface); if (!gbitmap->converted) - return (unsigned char *) pixels; + return pixels; fmt = cairo_image_surface_get_format(gbitmap->surface); pixel_count = cairo_image_surface_get_width(gbitmap->surface) * cairo_image_surface_get_height(gbitmap->surface); if (fmt == CAIRO_FORMAT_RGB24) { + /* Opaque image: simply swap R & B channels */ for (pixel_loop=0; pixel_loop < pixel_count; pixel_loop++) { - pixel = pixels[pixel_loop]; - pixels[pixel_loop] = (pixel & 0xff00ff00) | - ((pixel & 0xff) << 16) | - ((pixel & 0xff0000) >> 16); + b = pixels[4 * pixel_loop + 0]; + r = pixels[4 * pixel_loop + 2]; + pixels[4 * pixel_loop + 0] = r; + pixels[4 * pixel_loop + 2] = b; } } else { - uint32_t t, r, g, b; + /* Alpha image: swap R & B channels, and de-multiply alpha */ for (pixel_loop=0; pixel_loop < pixel_count; pixel_loop++) { - pixel = pixels[pixel_loop]; - t = (pixel & 0xff000000) >> 24; - if (t == 0) { - pixels[pixel_loop] = 0; - } else { - r = ((pixel & 0xff0000) >> 8) / t; - g = ((pixel & 0xff00)) / t; - b = ((pixel & 0xff) << 8) / t; + b = pixels[4 * pixel_loop + 0]; + g = pixels[4 * pixel_loop + 1]; + r = pixels[4 * pixel_loop + 2]; + t = pixels[4 * pixel_loop + 3]; + + if (t != 0) { + r = (r << 8) / t; + g = (g << 8) / t; + b = (b << 8) / t; r = (r > 255) ? 255 : r; g = (g > 255) ? 255 : g; b = (b > 255) ? 255 : b; - - pixels[pixel_loop] = (t << 24) | - (r) | (g << 8) | (b << 16); + } else { + r = g = b = 0; } + + pixels[4 * pixel_loop + 0] = r; + pixels[4 * pixel_loop + 1] = g; + pixels[4 * pixel_loop + 2] = b; + pixels[4 * pixel_loop + 3] = t; } } @@ -319,8 +325,8 @@ void bitmap_modified(void *vbitmap) { struct bitmap *gbitmap = (struct bitmap *)vbitmap; int pixel_loop; int pixel_count; - uint32_t *pixels; - uint32_t pixel; + uint8_t *pixels; + uint32_t t, r, g, b; cairo_format_t fmt; assert(gbitmap); @@ -329,7 +335,7 @@ void bitmap_modified(void *vbitmap) { pixel_count = cairo_image_surface_get_width(gbitmap->surface) * cairo_image_surface_get_height(gbitmap->surface); - pixels = (uint32_t *)cairo_image_surface_get_data(gbitmap->surface); + pixels = cairo_image_surface_get_data(gbitmap->surface); if (gbitmap->converted) { cairo_surface_mark_dirty(gbitmap->surface); @@ -337,30 +343,33 @@ void bitmap_modified(void *vbitmap) { } if (fmt == CAIRO_FORMAT_RGB24) { + /* Opaque image: simply swap R & B channels */ for (pixel_loop=0; pixel_loop < pixel_count; pixel_loop++) { - pixel = pixels[pixel_loop]; - pixels[pixel_loop] = (pixel & 0xff00ff00) | - ((pixel & 0xff) << 16) | - ((pixel & 0xff0000) >> 16); + r = pixels[4 * pixel_loop + 0]; + b = pixels[4 * pixel_loop + 2]; + pixels[4 * pixel_loop + 0] = b; + pixels[4 * pixel_loop + 2] = r; } } else { - uint8_t t, r, g, b; + /* Alpha image: swap R & B channels, and pre-multiply alpha */ for (pixel_loop=0; pixel_loop < pixel_count; pixel_loop++) { - pixel = pixels[pixel_loop]; - t = (pixel & 0xff000000) >> 24; - if (t == 0) { - pixels[pixel_loop] = 0; - } else { - r = (pixel & 0xff0000) >> 16; - g = (pixel & 0xff00) >> 8; - b = pixel & 0xff; - - pixels[pixel_loop] = (t << 24) | - ((r * t) >> 8) | - ((g * t) >> 8) << 8 | - ((b * t) >> 8) << 16; + r = pixels[4 * pixel_loop + 0]; + g = pixels[4 * pixel_loop + 1]; + b = pixels[4 * pixel_loop + 2]; + t = pixels[4 * pixel_loop + 3]; + if (t != 0) { + r = ((r * t) >> 8) & 0xff; + g = ((g * t) >> 8) & 0xff; + b = ((b * t) >> 8) & 0xff; + } else { + r = g = b = 0; } + + pixels[4 * pixel_loop + 0] = b; + pixels[4 * pixel_loop + 1] = g; + pixels[4 * pixel_loop + 2] = r; + pixels[4 * pixel_loop + 3] = t; } }