summaryrefslogtreecommitdiff
blob: 36760cc52055c893dc5df4209379e8401d7230f2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
% Copyright (C) 2001-2019 Artifex Software, Inc.
% All Rights Reserved.
%
% This software is provided AS-IS with no warranty, either express or
% implied.
%
% This software is distributed under license and may not be copied,
% modified or distributed except as expressly authorized under the terms
% of the license contained in the file LICENSE in this distribution.
%
% Refer to licensing information at http://www.artifex.com or contact
% Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
% CA 94945, U.S.A., +1(415)492-9861, for further information.
%
%
% $Id:$
%
% Extract Input and Output ICC profiles from a PDF file
%
%	Input ICC profiles are created with the prefix concatenated with
%	the Resource ColorSpace name from the PDF file.
%
%	Output ICC profiles are created with the prefix concatenated with
%	an incrementing number (the text info is usually too bulky to make
%	a reasonable file name).
%
% example usage:
%
%	gs -q -dNODISPLAY extractICCprofiles.ps -c "(ICC_) (somefile.pdf) extractICCprofiles quit"
%
% to show only input (ICCBased) colorspace profiles, use -dICCin prior to the '-c'.
% to show only output (OutputIntent) device profiles, use -dICCout prior to the '-c'.
%
% default is -dICCin -dICCout (including one but not both selects only that type)

% Copy one file to another.
% Close the files when finished
/copyfile		% <infile> <outfile> copyfile <outfile> <length>
 { 0 mark 32000 string
    { 4 index 1 index readstring
      exch 5 index 1 index writestring
      length 5 -1 roll add 4 1 roll
      not { exit } if
    } loop
   cleartomark 3 -1 roll closefile
   pop closefile
 } bind def

/extractICCprofiles {	%	(prefix) (filename) extractICCprofiles
  /DoICCin /ICCin where { pop true } { /ICCout where { pop false } { true } ifelse } ifelse def
  /DoICCout /ICCout where { pop true } { /ICCin where { pop false } { true } ifelse } ifelse def
  currentglobal true setglobal /CSNameDict 100 dict def setglobal
  exch /fnprefix exch def	% filename prefix

  (r) file runpdfbegin
  1 pdfpagecount % stack: first_page# last_page#
  DoICCin {
    1 exch {
      pdfgetpage			% get pagedict
      /Resources pget {
          /ColorSpace knownoget {
            {
              CSNameDict 2 index known not {
                oforce
                    % stack: CSname CSobject
                dup type /arraytype eq {
                  dup 0 oget /Indexed eq {
                    1 oget
                    dup type /arraytype ne { pop { 0 } } if
                  } if
                  dup 0 oget /ICCBased eq {
                    dup PDFfile fileposition exch
                    1 oget
                    mark exch { oforce } forall .dicttomark
                    true resolvestream
                    % construct a destination file name
                    fnprefix 4 index 100 string cvs concatstrings
                    (Found ICC input profile, extracting to: ) print dup = flush
                    (w) file copyfile
                    PDFfile exch setfileposition
                    currentglobal true setglobal CSNameDict 3 index //null put setglobal
                  } if	      % CS must be ICCBased
                } if	    % ICCBased must be array
              } if	% CS Resource Name already known ?
              pop pop	% done with CSname and object
            } forall    % enumerate the ColorSpace Resource dict
          } if
      } if
    } for		% for each Page
  } {
    pop pop
  } ifelse	% DoICCin

  % OutputIntent ICC output profiles are at the Catalog level
  DoICCout {
    /ICCoutcount 1 def
    Trailer /Root oget /OutputIntents knownoget {
      {	% process all output profiles present
        dup /DestOutputProfile knownoget {
          PDFfile fileposition exch
          mark exch { oforce } forall .dicttomark
          true resolvestream
          (ICC output profile, extracted to: ) print
          fnprefix ICCoutcount 10 string cvs concatstrings
          dup = flush
          (w) file
          copyfile
          PDFfile exch setfileposition
          dup /OutputCondition knownoget { (       OutputCondition: ) print = } if
          dup /OutputConditionIdentifier knownoget { (       OutputConditionIdentifier: ) print = } if
          dup /Info knownoget { (       Info: ) print = } if
          /ICCoutcount dup load 1 add def
        } if
        pop	  % done with this OutputIntent dictionary
      } forall
    } if	% OutputIntents known
  } if	% DoICCout
} bind def