GNU bug report logs - #36315
27.0.50; SVG transparency handling is inaccurate

Previous Next

Package: emacs;

Reported by: Pip Cet <pipcet <at> gmail.com>

Date: Thu, 20 Jun 2019 20:28:02 UTC

Severity: normal

Found in version 27.0.50

Done: Alan Third <alan <at> idiocy.org>

Bug is archived. No further changes may be made.

Full log


View this message in rfc822 format

From: Pip Cet <pipcet <at> gmail.com>
To: 36315 <at> debbugs.gnu.org
Subject: bug#36315: 27.0.50; SVG transparency handling is inaccurate
Date: Thu, 20 Jun 2019 20:46:20 +0000
[Message part 1 (text/plain, inline)]
Oops, typo in the patch. Better patch attached.

Subject: [PATCH] SVG: scale color values properly

* src/image.c (svg_load_image): scale color channel values to proper
range.
---
 src/image.c | 25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/src/image.c b/src/image.c
index 866323ba6e..8e25f1f590 100644
--- a/src/image.c
+++ b/src/image.c
@@ -9658,17 +9658,20 @@ svg_load_image (struct frame *f, struct image
*img, char *contents,
       {
     for (int x = 0; x < width; ++x)
       {
-        int red     = *pixels++;
-        int green   = *pixels++;
-        int blue    = *pixels++;
-        int opacity = *pixels++;
-
-        red   = ((red * opacity)
-             + (background.red * ((1 << 8) - opacity)));
-        green = ((green * opacity)
-             + (background.green * ((1 << 8) - opacity)));
-        blue  = ((blue * opacity)
-             + (background.blue * ((1 << 8) - opacity)));
+        unsigned int red     = *pixels++;
+        unsigned int green   = *pixels++;
+        unsigned int blue    = *pixels++;
+        unsigned int opacity = *pixels++;
+
+        /* opacity and the color channel values are in the range {0..255},
+         * but expected output values are in the range {0..65535}, so scale
+         * by (256/255)^2. */
+#define MIX(a, b, opacity)                        \
+        (((((a) * opacity) + ((b) * (255 - opacity))) * 65535 + 32512) / 65025)
+        red   = MIX (red, background.red, opacity);
+        green = MIX (green, background.green, opacity);
+        blue  = MIX (blue, background.blue, opacity);
+#undef MIX

         PUT_PIXEL (ximg, x, y, lookup_rgb_color (f, red, green, blue));
       }
-- 
2.20.1


On Thu, Jun 20, 2019 at 8:43 PM Pip Cet <pipcet <at> gmail.com> wrote:
>
> Evaluate the following in emacs -Q:
>
> (require 'svg)
>
> (defun make-image (color)
>   (let ((svg (svg-create 100 100)))
>     (svg-rectangle svg 0 0 100 100 :fill color)
>     (svg-image svg)))
>
> (set-frame-parameter (window-frame) 'background-color "black")
>
> (insert (propertize " " 'display (make-image "#f00000")))
>
> The expected result is a rectangle (on black background) of color
> #f00000. The actual result is a rectangle of color #ef0000. For black
> backgrounds, white is no longer representable.
>
> This is related to bug #36304, but much easier to fix.
>
> Patch attached.
[0001-SVG-scale-color-values-properly.patch (application/x-patch, attachment)]

This bug report was last modified 3 years and 219 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.