summaryrefslogtreecommitdiff
path: root/gdk-pixbuf/pixops
diff options
context:
space:
mode:
authorDarin Adler <darin@src.gnome.org>2000-05-05 02:50:24 +0000
committerDarin Adler <darin@src.gnome.org>2000-05-05 02:50:24 +0000
commit0f038c9e320c4ef3306e17b136c39909cd7baa57 (patch)
treee10f49d7c4d6b09a872989c28f0da091d207a104 /gdk-pixbuf/pixops
parent24fa8a64bcd200b1c2f15ffb9d8d5c34e279601f (diff)
downloadgdk-pixbuf-0f038c9e320c4ef3306e17b136c39909cd7baa57.tar.gz
Now that Owen explained the algorithm, I think I implemented it right for
* gdk-pixbuf/pixops/pixops.c: (pixops_composite_nearest), (composite_pixel), (composite_line): * gdk-pixbuf/test-gdk-pixbuf.c: (simple_composite_test_one_type): Now that Owen explained the algorithm, I think I implemented it right for the cases where the destination pixbuf is not opaque. The test does seem to confirm it.
Diffstat (limited to 'gdk-pixbuf/pixops')
-rw-r--r--gdk-pixbuf/pixops/pixops.c66
1 files changed, 52 insertions, 14 deletions
diff --git a/gdk-pixbuf/pixops/pixops.c b/gdk-pixbuf/pixops/pixops.c
index 00652d5c6..ae0ff5ee7 100644
--- a/gdk-pixbuf/pixops/pixops.c
+++ b/gdk-pixbuf/pixops/pixops.c
@@ -177,10 +177,24 @@ pixops_composite_nearest (guchar *dest_buf,
if (dest_has_alpha)
{
- dest[0] = (a0 * src[0] + (0xff - a0) * dest[0]) / 0xff;
- dest[1] = (a0 * src[1] + (0xff - a0) * dest[1]) / 0xff;
- dest[2] = (a0 * src[2] + (0xff - a0) * dest[2]) / 0xff;
- dest[3] = (0xff * a0 + (0xff - a0) * dest[3]) / 0xff;
+ unsigned int w0 = 0xff * a0;
+ unsigned int w1 = (0xff - a0) * dest[3];
+ unsigned int w = w0 + w1;
+
+ if (w != 0)
+ {
+ dest[0] = (w0 * src[0] + w1 * dest[0]) / w;
+ dest[1] = (w0 * src[1] + w1 * dest[1]) / w;
+ dest[2] = (w0 * src[2] + w1 * dest[2]) / w;
+ dest[3] = w / 0xff;
+ }
+ else
+ {
+ dest[0] = 0;
+ dest[1] = 0;
+ dest[2] = 0;
+ dest[3] = 0;
+ }
}
else
{
@@ -296,12 +310,24 @@ composite_pixel (guchar *dest, int dest_x, int dest_channels, int dest_has_alpha
{
if (dest_has_alpha)
{
- unsigned int w = (0xff0000 - a) * dest[3];
+ unsigned int w0 = a - (a >> 8);
+ unsigned int w1 = ((0xff0000 - a) >> 8) * dest[3];
+ unsigned int w = w0 + w1;
- dest[0] = (r + (0xff0000 - a) * dest[0]) / 0xff0000;
- dest[1] = (g + (0xff0000 - a) * dest[1]) / 0xff0000;
- dest[2] = (b + (0xff0000 - a) * dest[2]) / 0xff0000;
- dest[3] = (0xff * a + (0xff0000 - a) * dest[3]) / 0xff0000;
+ if (w != 0)
+ {
+ dest[0] = (r - (r >> 8) + w1 * dest[0]) / w;
+ dest[1] = (g - (g >> 8) + w1 * dest[1]) / w;
+ dest[2] = (b - (b >> 8) + w1 * dest[2]) / w;
+ dest[3] = w / 0xff00;
+ }
+ else
+ {
+ dest[0] = 0;
+ dest[1] = 0;
+ dest[2] = 0;
+ dest[3] = 0;
+ }
}
else
{
@@ -354,12 +380,24 @@ composite_line (int *weights, int n_x, int n_y,
if (dest_has_alpha)
{
- unsigned int w = (0xff0000 - a) * dest[3];
+ unsigned int w0 = a - (a >> 8);
+ unsigned int w1 = ((0xff0000 - a) >> 8) * dest[3];
+ unsigned int w = w0 + w1;
- dest[0] = (r + (0xff0000 - a) * dest[0]) / 0xff0000;
- dest[1] = (g + (0xff0000 - a) * dest[1]) / 0xff0000;
- dest[2] = (b + (0xff0000 - a) * dest[2]) / 0xff0000;
- dest[3] = (0xff * a + (0xff0000 - a) * dest[3]) / 0xff0000;
+ if (w != 0)
+ {
+ dest[0] = (r - (r >> 8) + w1 * dest[0]) / w;
+ dest[1] = (g - (g >> 8) + w1 * dest[1]) / w;
+ dest[2] = (b - (b >> 8) + w1 * dest[2]) / w;
+ dest[3] = w / 0xff00;
+ }
+ else
+ {
+ dest[0] = 0;
+ dest[1] = 0;
+ dest[2] = 0;
+ dest[3] = 0;
+ }
}
else
{