get algorithm right (use HSV/RGB conversion) at cost of making it a lot

2002-02-07  Havoc Pennington  <hp@pobox.com>

	* src/theme.c (colorize_pixbuf): get algorithm right (use HSV/RGB
	conversion) at cost of making it a lot slower. It doesn't matter
	anyhow with the cache, though.
This commit is contained in:
Havoc Pennington 2002-02-07 05:13:26 +00:00 committed by Havoc Pennington
parent e6984e727c
commit e605dff37f
2 changed files with 173 additions and 9 deletions

View File

@ -1,3 +1,9 @@
2002-02-07 Havoc Pennington <hp@pobox.com>
* src/theme.c (colorize_pixbuf): get algorithm right (use HSV/RGB
conversion) at cost of making it a lot slower. It doesn't matter
anyhow with the cache, though.
2002-02-06 Havoc Pennington <hp@pobox.com> 2002-02-06 Havoc Pennington <hp@pobox.com>
* src/theme.c (colorize_pixbuf): handle out-of-memory creating * src/theme.c (colorize_pixbuf): handle out-of-memory creating

View File

@ -45,6 +45,156 @@
#define INTENSITY(r, g, b) (r * 0.30 + g * 0.59 + b * 0.11) #define INTENSITY(r, g, b) (r * 0.30 + g * 0.59 + b * 0.11)
#define CLAMP_UCHAR(v) ((guchar) (CLAMP (((int)v), (int)0, (int)255))) #define CLAMP_UCHAR(v) ((guchar) (CLAMP (((int)v), (int)0, (int)255)))
#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
/* Converts from HSV to RGB */
static void
hsv_to_rgb (gdouble *h,
gdouble *s,
gdouble *v)
{
gdouble hue, saturation, value;
gdouble f, p, q, t;
if (*s == 0.0)
{
*h = *v;
*s = *v;
*v = *v; /* heh */
}
else
{
hue = *h * 6.0;
saturation = *s;
value = *v;
if (hue == 6.0)
hue = 0.0;
f = hue - (int) hue;
p = value * (1.0 - saturation);
q = value * (1.0 - saturation * f);
t = value * (1.0 - saturation * (1.0 - f));
switch ((int) hue)
{
case 0:
*h = value;
*s = t;
*v = p;
break;
case 1:
*h = q;
*s = value;
*v = p;
break;
case 2:
*h = p;
*s = value;
*v = t;
break;
case 3:
*h = p;
*s = q;
*v = value;
break;
case 4:
*h = t;
*s = p;
*v = value;
break;
case 5:
*h = value;
*s = p;
*v = q;
break;
default:
g_assert_not_reached ();
}
}
}
/* Converts from RGB to HSV */
static void
rgb_to_hsv (gdouble *r,
gdouble *g,
gdouble *b)
{
gdouble red, green, blue;
gdouble h, s, v;
gdouble min, max;
gdouble delta;
red = *r;
green = *g;
blue = *b;
h = 0.0;
if (red > green)
{
if (red > blue)
max = red;
else
max = blue;
if (green < blue)
min = green;
else
min = blue;
}
else
{
if (green > blue)
max = green;
else
max = blue;
if (red < blue)
min = red;
else
min = blue;
}
v = max;
if (max != 0.0)
s = (max - min) / max;
else
s = 0.0;
if (s == 0.0)
h = 0.0;
else
{
delta = max - min;
if (red == max)
h = (green - blue) / delta;
else if (green == max)
h = 2 + (blue - red) / delta;
else if (blue == max)
h = 4 + (red - green) / delta;
h /= 6.0;
if (h < 0.0)
h += 1.0;
else if (h > 1.0)
h -= 1.0;
}
*r = h;
*g = s;
*b = v;
}
static GdkPixbuf * static GdkPixbuf *
colorize_pixbuf (GdkPixbuf *orig, colorize_pixbuf (GdkPixbuf *orig,
GdkColor *new_color) GdkColor *new_color)
@ -52,7 +202,6 @@ colorize_pixbuf (GdkPixbuf *orig,
GdkPixbuf *pixbuf; GdkPixbuf *pixbuf;
double intensity; double intensity;
int x, y; int x, y;
guchar r, g, b;
const guchar *src; const guchar *src;
guchar *dest; guchar *dest;
int orig_rowstride; int orig_rowstride;
@ -61,10 +210,12 @@ colorize_pixbuf (GdkPixbuf *orig,
gboolean has_alpha; gboolean has_alpha;
const guchar *src_pixels; const guchar *src_pixels;
guchar *dest_pixels; guchar *dest_pixels;
double dh, ds, dv;
r = new_color->red / 256;
g = new_color->green / 256; dh = new_color->red / 65535.0;
b = new_color->blue / 256; ds = new_color->green / 65535.0;
dv = new_color->blue / 65535.0;
rgb_to_hsv (&dh, &ds, &dv);
pixbuf = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (orig), gdk_pixbuf_get_has_alpha (orig), 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_bits_per_sample (orig),
@ -88,11 +239,18 @@ colorize_pixbuf (GdkPixbuf *orig,
for (x = 0; x < width; x++) for (x = 0; x < width; x++)
{ {
intensity = INTENSITY (src[0], src[1], src[2]) / 255.0; double dr, dg, db;
dest[0] = CLAMP_UCHAR (r * intensity); intensity = INTENSITY (src[0], src[1], src[2]) / 255.0;
dest[1] = CLAMP_UCHAR (g * intensity);
dest[2] = CLAMP_UCHAR (b * intensity); dr = dh;
dg = ds;
db = intensity;
hsv_to_rgb (&dr, &dg, &db);
dest[0] = CLAMP_UCHAR (255 * dr);
dest[1] = CLAMP_UCHAR (255 * dg);
dest[2] = CLAMP_UCHAR (255 * db);
if (has_alpha) if (has_alpha)
{ {