Package: libimlib2
Version: 1.2.1-2
Severity: normal
Tags: patch

*** Please type your report below this line ***

Viewing TIFF images with an alpha channel shows semitransparent
pixels as too dark.  imlib2 uses unpremultiplied-by-alpha colour
components (cf. src/lib/blend.h), but in
src/modules/loaders/loader_tiff.c, the raster() function neglects
to divide by alpha the RGB colour components of premultiplied
pixels fed to it by TIFFRGBAImageGet().

To reproduce:  Make a TIFF image with a white background and a
50% semitransparent white box in it.  View the image with feh.
Note how the box is darker than when the image is viewed in gimp,
for example.

-- System Information:
Debian Release: testing/unstable
  APT prefers testing
  APT policy: (500, 'testing')
Architecture: amd64 (x86_64)
Shell:  /bin/sh linked to /bin/bash
Kernel: Linux 2.6.16-2-amd64-k8-smp
Locale: LANG=en_US, LC_CTYPE=en_US (charmap=ISO-8859-1) (ignored: LC_ALL set to 
en_US)

Versions of packages libimlib2 depends on:
ii  libbz2-1.0                  1.0.3-3      high-quality block-sorting file co
ii  libc6                       2.3.6-15     GNU C Library: Shared libraries
ii  libfreetype6                2.2.1-2      FreeType 2 font engine, shared lib
ii  libjpeg62                   6b-13        The Independent JPEG Group's JPEG
ii  libpng12-0                  1.2.8rel-5.1 PNG library - runtime
ii  libtiff4                    3.8.2-5      Tag Image File Format (TIFF) libra
ii  libungif4g                  4.1.4-2      shared library for GIF images (run
ii  libx11-6                    2:1.0.0-7    X11 client-side library
ii  libxext6                    1:1.0.0-4    X11 miscellaneous extension librar
ii  zlib1g                      1:1.2.3-13   compression library - runtime

libimlib2 recommends no packages.

-- no debconf information
--- imlib2-1.2.1/src/modules/loaders/loader_tiff.c      2004-12-14 
05:50:46.000000000 +0200
+++ imlib2-1.2.1-tiffalpha/src/modules/loaders/loader_tiff.c    2006-08-02 
23:45:17.787205647 +0300
@@ -97,13 +97,57 @@
 
         for (j = 0; j < w; j++)
           {
-             pixel_value = (*(pixel++));
-             (*(buffer_pixel++)) =
-                 (TIFFGetA(pixel_value) << 24) |
-                 (TIFFGetR(pixel_value) << 16) | (TIFFGetG(pixel_value) << 8) |
-                 TIFFGetB(pixel_value);
+            unsigned a;
+            pixel_value = (*(pixel++));
+            a = TIFFGetA(pixel_value);
+            /* Convert premultiplied alpha to unpremultiplied alpha used by
+             * imlib2.  Note: TIFFRGBAImageGet() always gives us premultiplied
+             * alpha, regardless of the type of alpha in the image, and we
+             * can't rely on the .alpha field of TIFFRGBAImage.  The behaviour
+             * seems to be (cf. tiff-3.7.2/libtiff/tif_getimage.c):
+             *
+             * a) If the image has no EXTRASAMPLES information at all, assume
+             * it's really associated alpha, perform no transformation on the
+             * pixels, and override the .alpha field of TIFFRGBAImage to be
+             * EXTRASAMPLE_ASSOCALPHA.
+             * 
+             * b) If the image has one EXTRASAMPLE_UNASSALPHA, premultiply all
+             * pixels' RGB values by alpha.  Sets the .alpha field of
+             * TIFFRGBAImage to EXTRASAMPLE_UNASSALPHA.
+             *
+             * c) If the image has one EXTRASAMPLE_ASSOCALPHA, perform no
+             * transformation on the pixels.  Set the .alpha field of
+             * TIFFRGBAImage to EXTRASAMPLE_ASSOCALPHA.  */
+            if (a == 255)
+              {
+                (*(buffer_pixel++)) =
+                  (a << 24) |
+                  (TIFFGetR(pixel_value) << 16) |
+                  (TIFFGetG(pixel_value) << 8) |
+                  TIFFGetB(pixel_value);
+              }
+            else if (!a)
+              {
+                (*(buffer_pixel++)) = 0;
+              }
+            else
+              {
+                /* need to divide by alpha; watch out for overflow. */
+                unsigned b = TIFFGetB(pixel_value);
+                unsigned g = TIFFGetG(pixel_value);
+                unsigned r = TIFFGetR(pixel_value);
+                if (b < a) b = b*255/a; else b = 255;
+                if (g < a) g = g*255/a; else g = 255;
+                if (r < a) r = r*255/a; else r = 255;
+                (*(buffer_pixel++)) =
+                  (a << 24) |
+                  (r << 16) |
+                  (g <<  8) |
+                  (b <<  0);
+              }
           }
      }
+   
 
    if (img->progress)
      {

Reply via email to