Search code examples
pdfimagemagickghostscriptpostscript

Ghostscript and ImageMagick to convert 16 bit per channel (48 bit) TIFF image to PDF or PDF/A


I am creating a PDF file from a TIFF image using ImageMagick and Ghostscript.

My source tiff is 16 bits per channel with no alpha (48 bit image) with an attached ICC Profile (AdobeRGB) and I want to maintaing this in the final PDF.

convert input.tif[0] -density 600 -alpha Off -size 5809x9408 -depth 16 intermediate.ps

This takes my input tiff image (just the main image, and not the thumbnail via using [0]) and creates a .ps file from the bitmap.

When I look at the size of the PostScript file, it's roughly the same size (3-4 MB larger than the 328MB tiff) as the source TIFF, but I can't tell if the image data in the .ps is 8 or 16 bit per channel.

Then, when I use GhostScript to convert this to a PDF, I'm getting 8 bits per channel in the PDF.

gs -dPDFA=1 -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sDefaultRGBProfile=AdobeRGB1998.icc -dOverrideICC -sOutputFile=output.pdf -r600 -P PDFA_def.ps -f custom.joboptions intermediate.ps

If I use pdfimages to inspect the PDF, it shows me 8 bit per channel.

pdfimages -list output.pdf

page   num  type   width height color comp bpc  enc interp  object ID x-ppi y-ppi size ratio
--------------------------------------------------------------------------------------------
   1     0 image    5809  9408  rgb     3   8  image  no        10  0   600   600 74.1M  47%

The contents of my PDFA_def.ps has been modified from the default Ghostscript install to specify AdobeRGB (1998) as the colour profile:

%!
% This is a sample prefix file for creating a PDF/A document.
% Feel free to modify entries marked with "Customize".
% This assumes an ICC profile to reside in the file (ISO Coated sb.icc),
% unless the user modifies the corresponding line below.

% Define entries in the document Info dictionary :
/ICCProfile (AdobeRGB1998.icc) % Customise
def

[ /Title (Title)       % Customise
  /DOCINFO pdfmark

% Define an ICC profile :

[/_objdef {icc_PDFA} /type /stream /OBJ pdfmark
[{icc_PDFA}
<<
  /N currentpagedevice /ProcessColorModel known {
    currentpagedevice /ProcessColorModel get dup /DeviceGray eq
    {pop 1} {
      /DeviceRGB eq
      {3}{4} ifelse
    } ifelse
  } {
    (ERROR, unable to determine ProcessColorModel) == flush
  } ifelse
>> /PUT pdfmark
[{icc_PDFA} ICCProfile (r) file /PUT pdfmark

% Define the output intent dictionary :

[/_objdef {OutputIntent_PDFA} /type /dict /OBJ pdfmark
[{OutputIntent_PDFA} <<
  /Type /OutputIntent             % Must be so (the standard requires).
  /S /GTS_PDFA1                   % Must be so (the standard requires).
  /DestOutputProfile {icc_PDFA}            % Must be so (see above).
  /OutputConditionIdentifier (sRGB)      % Customize
>> /PUT pdfmark
[{Catalog} <</OutputIntents [ {OutputIntent_PDFA} ]>> /PUT pdfmark

I've also got a custom.joboptions file that I created in Acrobat Distiller and then have modified for PDF/A compliance - I have tried to force 16-bit images in this file too, but I'm still getting 8-bit images in the PDF.

I don't know how many of these options Ghostscript respects and how many it ignores however. If I don't use this custom.joboptions file when making the PDF, the images are downsampled to a very low resolution.

<<
  /ASCII85EncodePages false
  /AllowTransparency false
  /AutoPositionEPSFiles true
  /AutoRotatePages /All
  /Binding /Left
  /CalGrayProfile (Dot Gain 20%)
  /CalRGBProfile (sRGB IEC61966-2.1)
  /CalCMYKProfile (U.S. Web Coated \050SWOP\051 v2)
  /sRGBProfile (sRGB IEC61966-2.1)
  /CannotEmbedFontPolicy /Error
  /CompatibilityLevel 1.4
  /CompressObjects /Off
  /CompressPages true
  /ConvertImagesToIndexed true
  /PassThroughJPEGImages true
  /CreateJobTicket false
  /DefaultRenderingIntent /Default
  /DetectBlends true
  /DetectCurves 0.0000
  /ColorConversionStrategy /LeaveColorUnchanged
  /DoThumbnails false
  /EmbedAllFonts true
  /EmbedOpenType false
  /ParseICCProfilesInComments true
  /EmbedJobOptions false
  /DSCReportingLevel 0
  /EmitDSCWarnings false
  /EndPage -1
  /ImageMemory 1048576
  /LockDistillerParams true
  /MaxSubsetPct 100
  /Optimize false
  /OPM 1
  /ParseDSCComments true
  /ParseDSCCommentsForDocInfo true
  /PreserveCopyPage true
  /PreserveDICMYKValues true
  /PreserveEPSInfo true
  /PreserveFlatness true
  /PreserveHalftoneInfo false
  /PreserveOPIComments false
  /PreserveOverprintSettings false
  /StartPage 1
  /SubsetFonts false
  /TransferFunctionInfo /Apply
  /UCRandBGInfo /Remove
  /UsePrologue false
  /ColorSettingsFile (None)
  /AlwaysEmbed [ true
  ]
  /NeverEmbed [ true
  ]
  /AntiAliasColorImages false
  /CropColorImages true
  /ColorImageMinResolution 600
  /ColorImageMinResolutionPolicy /OK
  /DownsampleColorImages false
  /ColorImageDownsampleType /Average
  /ColorImageResolution 600
  /ColorImageDepth -1
  /ColorImageMinDownsampleDepth 16
  /ColorImageDownsampleThreshold 1.50000
  /EncodeColorImages true
  /ColorImageFilter /FlateEncode
  /AutoFilterColorImages false
  /ColorImageAutoFilterStrategy /JPEG
  /ColorACSImageDict <<
    /QFactor 0.15
    /HSamples [1 1 1 1] /VSamples [1 1 1 1]
  >>
  /ColorImageDict <<
    /QFactor 0.15
    /HSamples [1 1 1 1] /VSamples [1 1 1 1]
  >>
  /JPEG2000ColorACSImageDict <<
    /TileWidth 256
    /TileHeight 256
    /Quality 30
  >>
  /JPEG2000ColorImageDict <<
    /TileWidth 256
    /TileHeight 256
    /Quality 30
  >>
  /AntiAliasGrayImages false
  /CropGrayImages true
  /GrayImageMinResolution 300
  /GrayImageMinResolutionPolicy /OK
  /DownsampleGrayImages false
  /GrayImageDownsampleType /Average
  /GrayImageResolution 600
  /GrayImageDepth -1
  /GrayImageMinDownsampleDepth 2
  /GrayImageDownsampleThreshold 1.50000
  /EncodeGrayImages true
  /GrayImageFilter /FlateEncode
  /AutoFilterGrayImages false
  /GrayImageAutoFilterStrategy /JPEG
  /GrayACSImageDict <<
    /QFactor 0.15
    /HSamples [1 1 1 1] /VSamples [1 1 1 1]
  >>
  /GrayImageDict <<
    /QFactor 0.15
    /HSamples [1 1 1 1] /VSamples [1 1 1 1]
  >>
  /JPEG2000GrayACSImageDict <<
    /TileWidth 256
    /TileHeight 256
    /Quality 30
  >>
  /JPEG2000GrayImageDict <<
    /TileWidth 256
    /TileHeight 256
    /Quality 30
  >>
  /AntiAliasMonoImages false
  /CropMonoImages true
  /MonoImageMinResolution 1200
  /MonoImageMinResolutionPolicy /OK
  /DownsampleMonoImages false
  /MonoImageDownsampleType /Average
  /MonoImageResolution 2400
  /MonoImageDepth -1
  /MonoImageDownsampleThreshold 1.50000
  /EncodeMonoImages true
  /MonoImageFilter /CCITTFaxEncode
  /MonoImageDict <<
    /K -1
  >>
  /AllowPSXObjects false
  /CheckCompliance [
    /PDFA1B:2005
  ]
  /PDFX1aCheck false
  /PDFX3Check false
  /PDFXCompliantPDFOnly true
  /PDFXNoTrimBoxError false
  /PDFXTrimBoxToMediaBoxOffset [
    0.00000
    0.00000
    0.00000
    0.00000
  ]
  /PDFXSetBleedBoxToMediaBox true
  /PDFXBleedBoxToTrimBoxOffset [
    0.00000
    0.00000
    0.00000
    0.00000
  ]
  /PDFXOutputIntentProfile (Adobe RGB \0501998\051)
  /PDFXOutputConditionIdentifier ()
  /PDFXOutputCondition ()
  /PDFXRegistryName ()
  /PDFXTrapped /False

  /CreateJDFFile false
>> setdistillerparams
<<
  /HWResolution [600 600]
  /PageSize [697.080 1128.960]
>> setpagedevice

Solution

  • PostScript can't handle 16 bits per component, it only handles 1, 2, 4, 8 and 12.

    PDF doesn't support 12 BPC, only 1, 2, 4, 8 and 16.

    So there isn't any way to get a PDF file with more than 12 BPC if you use PostScript as an intermediate format. Even if the PDF file says its 16 BPC the actual data will be limited to 12 (16BPC original -> 12 BPC PostScript -> 16 BPC PDF)

    Now further to that, you say that you are creating a PDF/A file, and its PDF/A-1. If you read the PDF/A-1 specification you will see that its limited to PDF 1.4, checking the PDF Reference Manual, we find that 16 BPC images were introduced in PDF 1.5

    So even if pdfwrite were able to upscale the 12 BPC image to a 16 BPC image (with padding), its not allowed to do so if you want to create a PDF/A-1 file, because that's not allowed by the specification. So I'm afraid you can't do what you want, you can't create a legal PDF/A-1 file with 16 BPC images using any tool.

    Regarding downsampling, the default for colour image downsampling is 'false', so if you don't enable it (DownsampleColorImages=true) then the pdfwrite device won't downsample the images.