Bug 694842 - PDF document renders Grey shadow fill on embedded graphics object
Summary: PDF document renders Grey shadow fill on embedded graphics object
Status: RESOLVED FIXED
Alias: None
Product: Ghostscript
Classification: Unclassified
Component: Images (show other bugs)
Version: master
Hardware: PC Windows 7
: P4 normal
Assignee: Robin Watts
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-12-13 13:32 UTC by Marvin Steakley
Modified: 2016-02-02 05:06 UTC (History)
1 user (show)

See Also:
Customer:
Word Size: ---


Attachments
Example PDF document with rendering issue (32.33 KB, application/pdf)
2013-12-13 13:32 UTC, Marvin Steakley
Details
E1150xx.tif (81.41 KB, image/tiff)
2013-12-14 11:00 UTC, Marcos H. Woehrmann
Details
E1150xx.pdf (41.57 KB, application/pdf)
2013-12-14 11:13 UTC, Marcos H. Woehrmann
Details
E1150xx3.pdf (46.81 KB, application/pdf)
2013-12-16 06:36 UTC, Robin Watts
Details
e1150-with-stocht.tif (74.51 KB, application/octet-stream)
2013-12-16 15:42 UTC, Ray Johnston
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Marvin Steakley 2013-12-13 13:32:19 UTC
Created attachment 10453 [details]
Example PDF document with rendering issue

PDF documents with an embedded graphic (the signature of our company president) render with a grey shadow boundary box.  The same PDF rendered with Adobe Acrobat Reader (all reasonable versions) does not have this shadow.  I can say for sure that Ghostscript 8.70 does not have this issue either.  I tried both 9.07 & 9.10 and they do have this issue.  I have unfortunately not tried any of the older 9.xx versions.  Also, unfortunately, we have literally 1,000s of individual PDF documents with this same embedded graphic, so fixing the PDFs to work around this problem is not practical at this time.
Comment 1 Marcos H. Woehrmann 2013-12-14 10:57:49 UTC
Sample command line that demonstrates the problem:

  bin/gs -sDEVICE=tiffg4 -o test.tif -r300 ./E1150xx.pdf
Comment 2 Marcos H. Woehrmann 2013-12-14 11:00:15 UTC
Created attachment 10460 [details]
E1150xx.tif

Original file saved as 300 dpi G4 TIFF from Acrobat.
Comment 3 Marcos H. Woehrmann 2013-12-14 11:13:01 UTC
Created attachment 10461 [details]
E1150xx.pdf

Simplified version of original file.
Comment 4 Marcos H. Woehrmann 2013-12-14 13:48:54 UTC
As was mentioned in the description this is a regression.  There are actually two commits which changed the output, the first caused a few halftoning dots to appear in the background of the signature, the second caused more to appear:


commit e03db2c2530cbd41a16513824d5aadcc5c611a26
Author: Michael Vrhel <michael.vrhel@artifex.com>
Date:   Thu Mar 3 17:51:48 2011 +0000

    Enabling of thresholding code as default image rendering of monochrome/indexed images for monochrome devices.  This will result in about 2432 difference
    
    git-svn-id: http://svn.ghostscript.com/ghostscript/trunk@12232 a1074d23-0009-0410-80fe-cf8c14f379e6



commit 1da2a46ed9f6ae0b0afc5fd4417943a36e532171
Author: Robin Watts <Robin.Watts@artifex.com>
Date:   Wed Aug 31 18:39:24 2011 +0100

    More work on bug 690538: introduce macros for color rounding.
    
    Introduce new macros to gxcvalue.h header file that defines helpful macros
    for colour depth changing.
    
    COLROUND macros do rounding (16->n bits), COLDUP macros do bit duplication
    (n->16 bits). Use these macros in various places throughout the code.
    
    Also tweak the gx_color_value_to_byte macro to round in the same way.
    
    Colors for devices that use these functions are now rounded in the same way
    that lcms does.
    
    Change as many encode_color routines as I can find to use this new code
    rather than simply truncating.
Comment 5 Robin Watts 2013-12-16 06:36:21 UTC
Created attachment 10462 [details]
E1150xx3.pdf

Further simplified version.

The original version had various watermarks/fonts in that didn't actually do anything. I've removed them. For the image it used an indexed colorspace with an ICC base for sRGB with a deviceRGB alternate. I've removed the ICC space, and resolved the indexed colorspace so we just have a direct 8bpp DeviceGray image. The same problem exhibits.
Comment 6 Robin Watts 2013-12-16 06:52:45 UTC
So we have an 8bpp device gray image that gs renders with some of it's background pixels non white, where acrobat renders the background entirely white.

The image in question has a background color of 253 rather than the 255 you would expect to see for a full white image. This can be confirmed by exporting the image as a contone and examining the background. Thus having some pixels set in the background of a monochrome rendering of the image is correct.

So, why do gs and acrobat render this differently?

Well, gs is using an 8x8 dither pattern. This can represents 65 possible levels, ranging from 0 pixels set in the dither to 64 pixels set in the dither.

We need to distribute these 65 levels as evenly as possible across the 0..255 range, and so we pick:

0     0,1
1     2,3,4,5
...
63    250,251,252,253
64    254,255

Accordingly, the '253' value in there is sent as 63 white pixels, and 1 black pixel - hence the 'shadow' seen in the background.

If we used a 4x4 dither instead, we'd have 17 possible levels, which would be distributed as:

0     0-7
1     8-23
...
15    232-247
16    248-255

This would leave us with a white background. I suspect Acrobat is using a 4x4 or  smaller dither.
Comment 7 Robin Watts 2013-12-16 10:16:21 UTC
Actually, we are using an 8x4 dither, which results in 33 possible values. We should still be showing that as white. A patch is forthcoming.
Comment 8 Robin Watts 2013-12-16 12:52:46 UTC
(In reply to comment #0)
> PDF documents with an embedded graphic (the signature of our company
> president) render with a grey shadow boundary box.  The same PDF rendered
> with Adobe Acrobat Reader (all reasonable versions) does not have this
> shadow.  I can say for sure that Ghostscript 8.70 does not have this issue
> either.  I tried both 9.07 & 9.10 and they do have this issue.  I have
> unfortunately not tried any of the older 9.xx versions.  Also,
> unfortunately, we have literally 1,000s of individual PDF documents with
> this same embedded graphic, so fixing the PDFs to work around this problem
> is not practical at this time.

Are Pacific Life a supported customer? If you're relying on Ghostscript as part of your business workflow, it probably makes sense for you to be. Not to mention that warm fuzzy feeling of supporting the software you use! >8*)
Comment 9 Ray Johnston 2013-12-16 15:42:54 UTC
Created attachment 10465 [details]
e1150-with-stocht.tif

While there may be a problem with the definition of the low quality default
halftone used by Ghostscript, we have a much higher quality stochastic dither
halftone screen that does not exhibit the problem.

The attached output from the original file looks OK, and the "SPECIMEN"
watermark is much smoother without the 45 degree angle grid effect.

This was produced with:

   gs -sDEVICE=tiffg4 -o e1150.tif -r300 -Ilib stocht.ps e1150.pdf

We may continue to look into the default halftone settings, but this seems
to be an acceptable (or even preferable) workaround.
Comment 10 Robin Watts 2013-12-17 06:40:31 UTC
The default halftone generation code is fixed in:

commit 300c3ea8f2c82471c5e57655bd13549f1172c38a
Author: Robin Watts <robin.watts@artifex.com>
Date:   Mon Dec 16 18:13:03 2013 +0000

    Bug 694842: Fix threshold table generation.

    When we generate threshold tables for dithering, we should expect them
    to be 'evenly distributed'. This is not the case currently. In the
    example given in this bug, we generate an 8x4 dither table. This
    contains 32 pixels, all of which can be on or off, hence we have 33
    levels, ranging from 0 on to 32 on.

    We would further expect our input range to be evenly divided into these
    levels - i.e. roughly 256/33 in each band.

    This is not the case. The threshold table generated is:

    threshold array row   0=  88 120 152 184 176 144 112  80
    threshold array row   1= 192 224 208 168  72  40  56  96
    threshold array row   2= 232 255 240 136  32   8  24 128
    threshold array row   3= 216 248 200 104  48  16  64 160

    The operation of our thresholding code is to set a pixel if
    contone(x,y) < threshold(x,y), hence our inputs divide into:
    0-7,8-15,...240-254,255

    Not only does this not have the required 256/33 per region, the top
    and bottom regions are far from being even (8 vs 1 entries).

    Ideally we should fix this code so generate the correct distribution -
    an enhancement bug will be opened for this. For now we will satisfy
    ourselves by offsetting the thresholds slightly so that the top and
    bottom ranges are at least even. The new code gives:

    threshold array row   0=  84 116 148 180 172 140 108  76
    threshold array row   1= 188 220 204 164  68  36  52  92
    threshold array row   2= 228 252 236 132  28   4  20 124
    threshold array row   3= 212 244 196 100  44  12  60 156

This threshold array is still not perfect, but it's better. I will open an enhancement bug to look at making it perfect. Also, we should double check the behaviour of this code with multi-level dithering.
Comment 11 Robin Watts 2013-12-17 07:00:04 UTC
Enhancement has been opened as bug 694850.