The other answers already covered the "What are dictionaries?" part of your question. Now let's turn to "How can Ghostscript access them?"
Maybe the question should rather be: "How can I (a power user, a developer, a geek...) access them?"
You can print out the contents of any accessible dictionary that's known to your PostScript interpreter (which may be Ghostscript) by writing a simple PostScript program one-liner -- or by simply calling the interpreter (Ghostscript) with the program code handed over on the commandline (-c ...
).
You only need to know the name of the respective dictionary for this.
Let's look at one interesting such internal Ghostscript dictionary, called .distillersettings
:
gs \
-dNODISPLAY \
-c ".distillersettings {exch ==only ( ) print ==} forall quit"
Result:
/default -dict-
/prepress -dict-
/PSL2Printer -dict-
/ebook -dict-
/screen -dict-
/printer -dict-
This may not tell you much at the first glance. But you may recognize some of the key names in that dictionary: /prepress
, /printer
, /screen
, /ebook
...
All of these you can use on a Ghostscript commandline to ask for a pre-defined set of settings when you want output made by -sDEVICE=pdfwrite
(the Ghostscript 'Distiller'-alike functionality). To ask for such a set of settings, simply add -dPDFSETTINGS=/printer
to the commandline.
At the second glance now you'll see that the content of the .distillersettings
dictionary essentially is a set of 6 more dictionaries. It is a 'dictionary of dictionaries'.
Dictionary contents are not printed out by default (not with the PostScript code above). But if you want them, you can use a Ghostscript-specific procedure called ===
instead of the standard PostScript language operator ==
in the above command. This procedure behaves the same as ==
execpt that it also expands the dictionaries and prints all key:value pairs contained in them.
Be carefull with that ===
procedure: the -dict-
you're trying to expand may be veeeeeery long and could cause you to loose your eyesight. :-)
In our current case however it is still manageable:
gs \
-dNODISPLAY \
-c ".distillersettings {exch ==only ( ) print ===} forall quit"
Output now is:
/default << /Optimize false /DoThumbnails false /PreserveEPSInfo true /ColorConversionStrategy /LeaveColorUnchanged /DownsampleMonoImages false /EmbedAllFonts true /CannotEmbedFontPolicy /Warning /PreserveOPIComments true /GrayACSImageDict << /HSamples [2 1 1 2] /VSamples [2 1 1 2] /QFactor 0.9 /Blend 1 >> /DownsampleColorImages false /PreserveOverprintSettings true /CreateJobTicket false /AutoRotatePages /PageByPage /NeverEmbed [/Courier /Courier-Bold /Courier-Oblique /Courier-BoldOblique /Helvetica /Helvetica-Bold /Helvetica-Oblique /Helvetica-BoldOblique /Times-Roman /Times-Bold /Times-Italic /Times-BoldItalic /Symbol /ZapfDingbats] /ColorACSImageDict << /HSamples [2 1 1 2] /VSamples [2 1 1 2] /QFactor 0.9 /Blend 1 >> /DownsampleGrayImages false /UCRandBGInfo /Preserve >>
/prepress << /DoThumbnails true /MonoImageResolution 1200 /ColorImageDownsampleType /Bicubic /PreserveEPSInfo true /ColorConversionStrategy /LeaveColorUnchanged /GrayImageDownsampleType /Bicubic /EmbedAllFonts true /CannotEmbedFontPolicy /Error /PreserveOPIComments true /GrayImageResolution 300 /GrayACSImageDict << /ColorTransform 1 /QFactor 0.15 /Blend 1 /HSamples [1 1 1 1] /VSamples [1 1 1 1] >> /ColorImageResolution 300 /PreserveOverprintSettings true /CreateJobTicket true /AutoRotatePages /None /MonoImageDownsampleType /Bicubic /NeverEmbed [] /ColorACSImageDict << /ColorTransform 1 /QFactor 0.15 /Blend 1 /HSamples [1 1 1 1] /VSamples [1 1 1 1] >> /CompatibilityLevel 1.4 /UCRandBGInfo /Preserve >>
/PSL2Printer << /DoThumbnails false /CompatibilityLevel 1.2 /TransferFunctionInfo /Preserve /MonoImageResolution 1200 /PreserveEPSInfo true /CompressFonts true /ColorImageDownsampleType /Bicubic /GrayImageDownsampleType /Bicubic /ColorConversionStrategy /LeaveColorUnchanged /EmbedAllFonts true /ColorACSImageDict << /ColorTransform 1 /QFactor 0.15 /Blend 1 /HSamples [1 1 1 1] /VSamples [1 1 1 1] >> /CannotEmbedFontPolicy /Error /PreserveOPIComments true /CompressPages true /GrayImageResolution 600 /GrayACSImageDict << /ColorTransform 1 /QFactor 0.15 /Blend 1 /HSamples [1 1 1 1] /VSamples [1 1 1 1] >> /ColorImageResolution 600 /PreserveOverprintSettings true /AutoRotatePages /None /MonoImageDownsampleType /Bicubic /ASCII85EncodePages true /MaxViewerMemorySize 8000000 /NeverEmbed [] /PreserveHalftoneInfo true /UCRandBGInfo /Preserve >>
/ebook << /DoThumbnails false /MonoImageResolution 300 /ColorImageDownsampleType /Bicubic /PreserveEPSInfo false /ColorConversionStrategy /sRGB /GrayImageDownsampleType /Bicubic /EmbedAllFonts true /CannotEmbedFontPolicy /Warning /PreserveOPIComments false /GrayImageResolution 150 /GrayACSImageDict << /ColorTransform 1 /QFactor 0.76 /Blend 1 /HSamples [2 1 1 2] /VSamples [2 1 1 2] >> /ColorImageResolution 150 /PreserveOverprintSettings false /CreateJobTicket false /AutoRotatePages /All /MonoImageDownsampleType /Bicubic /NeverEmbed [/Courier /Courier-Bold /Courier-Oblique /Courier-BoldOblique /Helvetica /Helvetica-Bold /Helvetica-Oblique /Helvetica-BoldOblique /Times-Roman /Times-Bold /Times-Italic /Times-BoldItalic /Symbol /ZapfDingbats] /ColorACSImageDict << /ColorTransform 1 /QFactor 0.76 /Blend 1 /HSamples [2 1 1 2] /VSamples [2 1 1 2] >> /CompatibilityLevel 1.4 /UCRandBGInfo /Remove >>
/screen << /DoThumbnails false /MonoImageResolution 300 /ColorImageDownsampleType /Average /PreserveEPSInfo false /ColorConversionStrategy /sRGB /GrayImageDownsampleType /Average /EmbedAllFonts true /CannotEmbedFontPolicy /Warning /PreserveOPIComments false /GrayImageResolution 72 /GrayACSImageDict << /ColorTransform 1 /QFactor 0.76 /Blend 1 /HSamples [2 1 1 2] /VSamples [2 1 1 2] >> /ColorImageResolution 72 /PreserveOverprintSettings false /CreateJobTicket false /AutoRotatePages /PageByPage /MonoImageDownsampleType /Average /NeverEmbed [/Courier /Courier-Bold /Courier-Oblique /Courier-BoldOblique /Helvetica /Helvetica-Bold /Helvetica-Oblique /Helvetica-BoldOblique /Times-Roman /Times-Bold /Times-Italic /Times-BoldItalic /Symbol /ZapfDingbats] /ColorACSImageDict << /ColorTransform 1 /QFactor 0.76 /Blend 1 /HSamples [2 1 1 2] /VSamples [2 1 1 2] >> /CompatibilityLevel 1.3 /UCRandBGInfo /Remove >>
/printer << /DoThumbnails false /MonoImageResolution 1200 /ColorImageDownsampleType /Bicubic /PreserveEPSInfo true /ColorConversionStrategy /UseDeviceIndependentColor /GrayImageDownsampleType /Bicubic /EmbedAllFonts true /CannotEmbedFontPolicy /Warning /PreserveOPIComments true /GrayImageResolution 300 /GrayACSImageDict << /ColorTransform 1 /QFactor 0.4 /Blend 1 /HSamples [1 1 1 1] /VSamples [1 1 1 1] >> /ColorImageResolution 300 /PreserveOverprintSettings true /CreateJobTicket true /AutoRotatePages /None /MonoImageDownsampleType /Bicubic /NeverEmbed [] /ColorACSImageDict << /ColorTransform 1 /QFactor 0.4 /Blend 1 /HSamples [1 1 1 1] /VSamples [1 1 1 1] >> /CompatibilityLevel 1.4 /UCRandBGInfo /Preserve >>
Still not so nice. So let's try to get it better. The way we can do it is to modify our PostScript code: we tell it now to access the .distillersettings
dictionary and get the value of one of the keys from it (let's use /screen
). Since we know that the value is another dictionary, we know we'll get another set of key:value pairs which we will be able to format the same way we did before:
gs \
-q \
-dNODISPLAY \
-c ".distillersettings /screen get {exch ==only ( ) print ===} forall quit"
Now this looks nicer, doesn't it? See yourself:
/DoThumbnails false
/MonoImageResolution 300
/ColorImageDownsampleType /Average
/PreserveEPSInfo false
/ColorConversionStrategy /sRGB
/GrayImageDownsampleType /Average
/EmbedAllFonts true
/CannotEmbedFontPolicy /Warning
/PreserveOPIComments false
/GrayImageResolution 72
/GrayACSImageDict -dict-
/ColorImageResolution 72
/PreserveOverprintSettings false
/CreateJobTicket false
/AutoRotatePages /PageByPage
/MonoImageDownsampleType /Average
/NeverEmbed [/Courier /Courier-Bold /Courier-Oblique /Courier-BoldOblique /Helvetica /Helvetica-Bold /Helvetica-Oblique /Helvetica-BoldOblique /Times-Roman /Times-Bold /Times-Italic /Times-BoldItalic /Symbol /ZapfDingbats]
/ColorACSImageDict -dict-
/CompatibilityLevel 1.3
/UCRandBGInfo /Remove
As your sharp eye may have spotted already: some of the key values are again dictionaries. You are free to use the above command again, this time with a ===
in place of the second ==
to resolve the mysteries that /GrayACSImageDict -dict-
and the like may keep hiding...
In any case, now you know what you save on typing by simply using -dPDFSETTINGS=/screen
instead of enumerating all the single parameters embedded in this /screen
dictionary...
And you also know what single value you need to override should you want the general 'screen' quality output, but with the difference that all fonts get embedded:
gs \
-o out.pdf \
-sDEVICE=pdfwrite \
-dPDFSETTINGS=/screen \
-c "<</NeverEmbed [ ] /AlwaysEmbed [/Courier /Courier-Bold /Courier-Oblique /Courier-BoldOblique /Helvetica /Helvetica-Bold /Helvetica-Oblique /Helvetica-BoldOblique /Times-Roman /Times-Bold /Times-Italic /Times-BoldItalic /Symbol /ZapfDingbats]>> setdistillerparams" \
-f input.pdf
You can explore a lot of interesting things this way about Ghostscript internals, if only you know the name of the dictionaries it uses. :-)
ghostscript
terminal example, of "the interpreter [] looking up a name" (which can also show "userdict
is searched beforesystemdict
", and possibly overwriting an operator)? Many thanks again - cheers! – Levigate