static GdkPixbuf * colorize_pixbuf (GdkPixbuf *orig, GdkRGBA *new_color) { GdkPixbuf *pixbuf; double intensity; int x, y; const guchar *src; guchar *dest; int orig_rowstride; int dest_rowstride; int width, height; gboolean has_alpha; const guchar *src_pixels; guchar *dest_pixels; pixbuf = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (orig), gdk_pixbuf_get_has_alpha (orig), gdk_pixbuf_get_bits_per_sample (orig), gdk_pixbuf_get_width (orig), gdk_pixbuf_get_height (orig)); if (pixbuf == NULL) return NULL; orig_rowstride = gdk_pixbuf_get_rowstride (orig); dest_rowstride = gdk_pixbuf_get_rowstride (pixbuf); width = gdk_pixbuf_get_width (pixbuf); height = gdk_pixbuf_get_height (pixbuf); has_alpha = gdk_pixbuf_get_has_alpha (orig); src_pixels = gdk_pixbuf_get_pixels (orig); dest_pixels = gdk_pixbuf_get_pixels (pixbuf); for (y = 0; y < height; y++) { src = src_pixels + y * orig_rowstride; dest = dest_pixels + y * dest_rowstride; for (x = 0; x < width; x++) { double dr, dg, db; intensity = INTENSITY (src[0], src[1], src[2]) / 255.0; if (intensity <= 0.5) { /* Go from black at intensity = 0.0 to new_color at intensity = 0.5 */ dr = new_color->red * intensity * 2.0; dg = new_color->green * intensity * 2.0; db = new_color->blue * intensity * 2.0; } else { /* Go from new_color at intensity = 0.5 to white at intensity = 1.0 */ dr = new_color->red + (1.0 - new_color->red) * (intensity - 0.5) * 2.0; dg = new_color->green + (1.0 - new_color->green) * (intensity - 0.5) * 2.0; db = new_color->blue + (1.0 - new_color->blue) * (intensity - 0.5) * 2.0; } dest[0] = CLAMP_UCHAR (255 * dr); dest[1] = CLAMP_UCHAR (255 * dg); dest[2] = CLAMP_UCHAR (255 * db); if (has_alpha) { dest[3] = src[3]; src += 4; dest += 4; } else { src += 3; dest += 3; } } } return pixbuf; }
/** * gdk_pixbuf_saturate_and_pixelate: * @src: source image * @dest: place to write modified version of @src * @saturation: saturation factor * @pixelate: whether to pixelate * * Modifies saturation and optionally pixelates @src, placing the result in * @dest. @src and @dest may be the same pixbuf with no ill effects. If * @saturation is 1.0 then saturation is not changed. If it's less than 1.0, * saturation is reduced (the image turns toward grayscale); if greater than * 1.0, saturation is increased (the image gets more vivid colors). If @pixelate * is %TRUE, then pixels are faded in a checkerboard pattern to create a * pixelated image. @src and @dest must have the same image format, size, and * rowstride. * **/ void gdk_pixbuf_saturate_and_pixelate(const GdkPixbuf *src, GdkPixbuf *dest, gfloat saturation, gboolean pixelate) { /* NOTE that src and dest MAY be the same pixbuf! */ g_return_if_fail (GDK_IS_PIXBUF (src)); g_return_if_fail (GDK_IS_PIXBUF (dest)); g_return_if_fail (gdk_pixbuf_get_height (src) == gdk_pixbuf_get_height (dest)); g_return_if_fail (gdk_pixbuf_get_width (src) == gdk_pixbuf_get_width (dest)); g_return_if_fail (gdk_pixbuf_get_has_alpha (src) == gdk_pixbuf_get_has_alpha (dest)); g_return_if_fail (gdk_pixbuf_get_colorspace (src) == gdk_pixbuf_get_colorspace (dest)); if (saturation == 1.0 && !pixelate) { if (dest != src) gdk_pixbuf_copy_area (src, 0, 0, gdk_pixbuf_get_width (src), gdk_pixbuf_get_height (src), dest, 0, 0); } else { int i, j, t; int width, height, has_alpha, src_rowstride, dest_rowstride, bytes_per_pixel; const guchar *src_line; guchar *dest_line; const guchar *src_pixel; guchar *dest_pixel; guchar intensity; has_alpha = gdk_pixbuf_get_has_alpha (src); bytes_per_pixel = has_alpha ? 4 : 3; width = gdk_pixbuf_get_width (src); height = gdk_pixbuf_get_height (src); src_rowstride = gdk_pixbuf_get_rowstride (src); dest_rowstride = gdk_pixbuf_get_rowstride (dest); dest_line = gdk_pixbuf_get_pixels (dest); src_line = gdk_pixbuf_read_pixels (src); #define DARK_FACTOR 0.7 #define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11) #define CLAMP_UCHAR(v) (t = (v), CLAMP (t, 0, 255)) #define SATURATE(v) ((1.0 - saturation) * intensity + saturation * (v)) for (i = 0 ; i < height ; i++) { src_pixel = src_line; src_line += src_rowstride; dest_pixel = dest_line; dest_line += dest_rowstride; for (j = 0 ; j < width ; j++) { intensity = INTENSITY (src_pixel[0], src_pixel[1], src_pixel[2]); if (pixelate && (i + j) % 2 == 0) { dest_pixel[0] = intensity / 2 + 127; dest_pixel[1] = intensity / 2 + 127; dest_pixel[2] = intensity / 2 + 127; } else if (pixelate) { dest_pixel[0] = CLAMP_UCHAR ((SATURATE (src_pixel[0])) * DARK_FACTOR); dest_pixel[1] = CLAMP_UCHAR ((SATURATE (src_pixel[1])) * DARK_FACTOR); dest_pixel[2] = CLAMP_UCHAR ((SATURATE (src_pixel[2])) * DARK_FACTOR); } else { dest_pixel[0] = CLAMP_UCHAR (SATURATE (src_pixel[0])); dest_pixel[1] = CLAMP_UCHAR (SATURATE (src_pixel[1])); dest_pixel[2] = CLAMP_UCHAR (SATURATE (src_pixel[2])); } if (has_alpha) dest_pixel[3] = src_pixel[3]; src_pixel += bytes_per_pixel; dest_pixel += bytes_per_pixel; } } } }