Uploaded image for project: 'FOP'
  1. FOP
  2. FOP-2847

[PATCH] Support palette-based transparency via tRNS chunk of PNG images in PDF export

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Major
    • Resolution: Fixed
    • 2.3
    • None
    • renderer/pdf
    • None

    Description

      TL;NR

      When using palette-based transparency via tRNS chunk in PNG images, the generated PDFs are broken.

      palette-based with transparency.

      8.5.2. Palette-Based with Transparency

      "The PNG spec forbids the use of a full alpha channel with palette-based images, but it does allow `cheap alpha` via the transparency chunk, tRNS [...] In effect, it transforms the palette from an RGB lookup table to an RGBA table [...] a single PNG transparency entry should come first"

      http://www.libpng.org/pub/png/book/chapter08.html#png.ch08.div.5.2

      general PDF encoding strategy

      Option 1:

      most libraries just undo the palettization and use a full color image + mask.

      https://forums.adobe.com/message/6148131#6148131

      Option 2:

      SMask would be simpler since you could leave the palette in place

      https://forums.adobe.com/message/6148557#6148557

      what does FOP do

      It creates a chroma-key mask:

       /Type /XObject
        /ColorSpace [/Indexed /DeviceRGB 255 <D9DB ...>]
        /Mask [182 182 151 151 158 158]
      

      Acrobat Reader even fails to read those files while PDF viewers embedded into Chrome/Firefox read the file, but show visual glitches:

      https://github.com/apache/fop/pull/49 fixes the Acrobat Reader error.

      FOP doesn't implement Option 1 yet. None of the ImageLoaders is prepared to do that:
      https://wiki.apache.org/xmlgraphics-fop/HowTo/ImageLoaderRawPNG
      In fact the following results in missing Option 2:

      public void setup(PDFDocument doc) {
        RenderedImage ri = getImage().getRenderedImage();
        // code deleted
        Raster raster = GraphicsUtil.getAlphaRaster(ri);
        if (raster != null) {
          AlphaRasterImage alphaImage = new AlphaRasterImage("Mask:" + getKey(), raster);
          this.softMask = doc.addImage(null, alphaImage).makeReference();
        }
      

      https://github.com/apache/fop/blob/ff452f3685a02715aee791d651b58dd1797ddfd4/fop-core/src/main/java/org/apache/fop/render/pdf/ImageRenderedAdapter.java

      In the above code raster will be null and therefore FOP fails to initialize a softMask. GraphicsUtil.getAlphaRaster() calls internally ColorModel.getAlphaRaster(), which returns null:

      If this is an IndexColorModel which has alpha in the lookup table, this method will return null since there is no spatially discrete alpha channel.

      https://docs.oracle.com/javase/8/docs/api/index.html?java/awt/image/ColorModel.html

      The softMask Issue is fixed by:
      https://github.com/apache/fop/pull/50
      As a result an image such as is rendered with a transparency gradient instead of

      This code will then add the chroma key mask to the image:

      protected void populateXObjectDictionaryForIndexColorModel(PDFDictionary dict, IndexColorModel icm) {
        // code deleted
        Integer index = getIndexOfFirstTransparentColorInPalette(icm);
        if (index != null) {
          PDFArray mask = new PDFArray(dict);
          mask.add(index);
          mask.add(index);
          dict.put("Mask", mask);
        }
      }
      

      https://github.com/apache/fop/blob/ff452f3685a02715aee791d651b58dd1797ddfd4/fop-core/src/main/java/org/apache/fop/render/pdf/AbstractImageAdapter.java

      why care to support?

      Libraries such as pngquant optimize images for web usage and low footprint and can not be used directly with Apache FOP as source images:

      "pngquant: Lossy PNG optimizer, reducing a PNG image down to an 8 bit color palette with dithering. It will build indexed-color PNG's with alpha transparency colors conveyed in the tRNS chunk."

      https://imagemagick.org/Usage/formats/#png_non-im

      sample data

      $ identify -verbose sample_image_palette_tRNS.png
      
        Format: PNG (Portable Network Graphics)
        Type: PaletteAlpha
        png:IHDR.color_type      : 3 (Indexed)
        png:tRNS                 : chunk was found
      

      Attachments

        1. acrobat_reader_error_message.PNG
          12 kB
          Tobias Hain
        2. broken_generated_pdf.pdf
          110 kB
          Tobias Hain
        3. pal_bk.png
          1 kB
          Tobias Hain
        4. pdf_trans_broken.png
          0.3 kB
          Tobias Hain
        5. sample_image_palette_tRNS.png
          102 kB
          Tobias Hain

        Issue Links

          Activity

            People

              ssteiner Simon Steiner
              7oby Tobias Hain
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: