From 53991e791a53697aca742c4567121374724bf293 Mon Sep 17 00:00:00 2001 From: Matthew Hague Date: Sat, 2 May 2015 12:43:11 +0100 Subject: [PATCH] keep alpha channel on mapnik rendering, scale alpha to alpha of mapnik layer Signed-off-by: Rob Norris --- src/mapnik_interface.cpp | 34 +++------------------------------- src/ui_util.c | 34 ++++++++++++++++++++++++++++++++++ src/ui_util.h | 1 + src/vikmapniklayer.c | 2 +- 4 files changed, 39 insertions(+), 32 deletions(-) diff --git a/src/mapnik_interface.cpp b/src/mapnik_interface.cpp index 6253523f..087e0138 100644 --- a/src/mapnik_interface.cpp +++ b/src/mapnik_interface.cpp @@ -189,34 +189,6 @@ gchar* mapnik_interface_load_map_file ( MapnikInterface* mi, return msg; } -// These two functions copied from gpsdrive 2.11 -/** - * convert the color channel - */ -inline unsigned char -convert_color_channel (unsigned char Source, unsigned char Alpha) -{ - return Alpha ? ((Source << 8) - Source) / Alpha : 0; -} - -/** - * converting argb32 to gdkpixbuf - */ -static void -convert_argb32_to_gdkpixbuf_data (unsigned char const *Source, unsigned int width, unsigned int height, unsigned char *Dest) -{ - unsigned char const *SourcePixel = Source; - unsigned char *DestPixel = Dest; - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - DestPixel[0] = convert_color_channel(SourcePixel[0], SourcePixel[3]); - DestPixel[1] = convert_color_channel(SourcePixel[1], SourcePixel[3]); - DestPixel[2] = convert_color_channel(SourcePixel[2], SourcePixel[3]); - DestPixel += 3; - SourcePixel += 4; - } - } -} /** * mapnik_interface_render: @@ -253,11 +225,11 @@ GdkPixbuf* mapnik_interface_render ( MapnikInterface* mi, double lat_tl, double render.apply(); if ( image.painted() ) { - unsigned char *ImageRawDataPtr = (unsigned char *) g_malloc(width * 3 * height); + unsigned char *ImageRawDataPtr = (unsigned char *) g_malloc(width * 4 * height); if (!ImageRawDataPtr) return NULL; - convert_argb32_to_gdkpixbuf_data(image.raw_data(), width, height, ImageRawDataPtr); - pixbuf = gdk_pixbuf_new_from_data(ImageRawDataPtr, GDK_COLORSPACE_RGB, FALSE, 8, width, height, width * 3, NULL, NULL); + memcpy(ImageRawDataPtr, image.raw_data(), width * height * 4); + pixbuf = gdk_pixbuf_new_from_data(ImageRawDataPtr, GDK_COLORSPACE_RGB, TRUE, 8, width, height, width * 4, NULL, NULL); } else g_warning ("%s not rendered", __FUNCTION__ ); diff --git a/src/ui_util.c b/src/ui_util.c index ec0976b4..bc061ea5 100644 --- a/src/ui_util.c +++ b/src/ui_util.c @@ -211,6 +211,40 @@ GdkPixbuf *ui_pixbuf_set_alpha ( GdkPixbuf *pixbuf, guint8 alpha ) return pixbuf; } + +/** + * Reduce the alpha value of the specified pixbuf by alpha / 255 + */ +GdkPixbuf *ui_pixbuf_scale_alpha ( GdkPixbuf *pixbuf, guint8 alpha ) +{ + guchar *pixels; + gint width, height, iii, jjj; + + if ( ! gdk_pixbuf_get_has_alpha ( pixbuf ) ) + { + GdkPixbuf *tmp = gdk_pixbuf_add_alpha(pixbuf,FALSE,0,0,0); + g_object_unref(G_OBJECT(pixbuf)); + pixbuf = tmp; + if ( !pixbuf ) + return NULL; + } + + pixels = gdk_pixbuf_get_pixels(pixbuf); + width = gdk_pixbuf_get_width(pixbuf); + height = gdk_pixbuf_get_height(pixbuf); + + /* r,g,b,a,r,g,b,a.... */ + for (iii = 0; iii < width; iii++) for (jjj = 0; jjj < height; jjj++) + { + pixels += 3; + *pixels = (guint8)(((guint16)*pixels * (guint16)alpha) / 255); + pixels++; + } + return pixbuf; +} + + + /** * */ diff --git a/src/ui_util.h b/src/ui_util.h index 2fff065a..42370188 100644 --- a/src/ui_util.h +++ b/src/ui_util.h @@ -38,6 +38,7 @@ GtkWidget *ui_lookup_widget(GtkWidget *widget, const gchar *widget_name); GtkWidget* ui_label_new_selectable ( const gchar* text ); GdkPixbuf *ui_pixbuf_set_alpha ( GdkPixbuf *pixbuf, guint8 alpha ); +GdkPixbuf *ui_pixbuf_scale_alpha ( GdkPixbuf *pixbuf, guint8 alpha ); void ui_add_recent_file ( const gchar *filename ); G_END_DECLS diff --git a/src/vikmapniklayer.c b/src/vikmapniklayer.c index dc64985d..486125ee 100644 --- a/src/vikmapniklayer.c +++ b/src/vikmapniklayer.c @@ -671,7 +671,7 @@ static void render ( VikMapnikLayer *vml, VikCoord *ul, VikCoord *br, MapCoord * // NB Mapnik can apply alpha, but use our own function for now if ( vml->alpha < 255 ) - pixbuf = ui_pixbuf_set_alpha ( pixbuf, vml->alpha ); + pixbuf = ui_pixbuf_scale_alpha ( pixbuf, vml->alpha ); a_mapcache_add ( pixbuf, (mapcache_extra_t){ tt }, ulm->x, ulm->y, ulm->z, MAP_ID_MAPNIK_RENDER, ulm->scale, vml->alpha, 0.0, 0.0, vml->filename_xml ); } -- 2.39.5