summaryrefslogtreecommitdiff
blob: ab4ede66878a4bf373f6448d9de06506d84fa90d (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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
% 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.
%

% viewpbm.ps
% Display a PBM/PGM/PPM file.
% Requires the Level 2 `image' operator (to handle variable pixel widths).
% If SCALE is defined, maps input pixels to output pixels with that scale;
% if SCALE is undefined, scales the image to fit the page.
% If FITPAGE true, it fits the output page size to the image, honouring SCALE
% When the input is PAM (P7) RGBTAG from bitrgbtags device, -dTAG will show
% the tags is pseudo color:
% TEXT=1, IMAGE=2, PATH=4, UNTOUCHED=8
%  red     green   blue      gray

/s 100 string def
/readmaxv {		% <file> readmaxv -
  10 string readline pop cvx exec /maxv exch def
} bind def
/readrow {		% <file> <row> readrow <row>
  0 1 2 index length 1 sub {
    1 index exch 3 index token pop put
  } for exch pop
} bind def
/read01 {		% <file> <count> read01 <byte>
  0 exch {
    1 index read pop 48 xor dup 1 le { exch dup add add } { pop } ifelse
  } repeat
} bind def
/readrow01 {		% <file> <row> readrow01 <row>
  0 1 w 8 idiv {
    1 index exch 3 index 8 read01 put
  } for
  wrem 0 ne {
     dup rsize 1 sub wrem read01 8 wrem sub bitshift put
  } if
  exch pop
} bind def
/readwh {		% <file> readwh <w> <h>
 dup s readline pop		% check for comment
 (#) anchorsearch {
   pop pop dup s readline pop
 } if
 cvx exec
} bind def
/pbmtypes mark
% The procedures in this dictionary are called as
%	<file> Pn <w> <h> <readproc>
/P1 {			% ASCII 1-bit white/black
  /bpc 1 def /maxv 1 def /rsize w 7 add 8 idiv def
  /wrem w 8 mod def
  /ncomp 1 def /invert true def /DeviceGray setcolorspace
  readwh
        { readrow01 }
} bind
/P2 {			% ASCII 8-bit gray
  readwh
  /bpc 8 def 2 index readmaxv /rsize 2 index def
  /ncomp 1 def /invert false def /DeviceGray setcolorspace
        { readrow }
} bind
/P3 {			% ASCII 8-bit RGB
  readwh
  /bpc 8 def 2 index readmaxv /rsize 2 index 3 mul def
  /ncomp 3 def /invert false def /DeviceRGB setcolorspace
        { readrow }
} bind
/P4 {			% Binary 1-bit white/black
  readwh
  /bpc 1 def /maxv 1 def /rsize 2 index 7 add 8 idiv def
  /ncomp 1 def /invert true def /DeviceGray setcolorspace
        { readstring pop }
} bind
/P5 {			% Binary 8-bit gray
  readwh
  /bpc 8 def 2 index readmaxv /rsize 2 index def
  /ncomp 1 def /invert false def /DeviceGray setcolorspace
        { readstring pop }
} bind
/P6 {			% Binary 8-bit RGB
  readwh
  /bpc 8 def 2 index readmaxv /rsize 2 index 3 mul def
  /ncomp 3 def /invert false def /DeviceRGB setcolorspace
        { readstring pop }
} bind
/P7 {			% Assume Binary 8-bit CMYK -- assumes 'pf' is the input file
% P7
% WIDTH 612	%% used to set rsize and w
% HEIGHT 792	%% used to set h
% DEPTH 4	%% if present and not 1 or 4, then bail
% MAXVAL 255	%% used to set maxv
% TUPLTYPE CMYK | RGB_TAG | RGB_ALPHA | GRAYSCALE %% if present and not one of these, then bail
% ENDHDR	%% skip everything else up to this
  /P7KEYS <<
    /WIDTH { /w pf token pop def }
    /HEIGHT { /h pf token pop def }
    /DEPTH { /d pf token pop def d 4 eq d 1 eq or not {
             (*** Only DEPTH 1 or 4 PAM files supported at this time. ***) = quit
             } if
           }
    /MAXVAL { /maxv pf token pop def }
    /TUPLTYPE { pf token pop dup /CMYK eq 1 index /RGB_TAG eq or 1 index /RGB_ALPHA eq or 1 index /GRAYSCALE eq or not {
                  (*** Only CMYK, RGB_TAG, RGB_ALPHA and GRAYSCALE files supported at this time. ***) = quit
                } if
                /T exch def
              }
    /ENDHDR { exit }
    (#) cvn { pf 255 string readline pop pop }
  >> def
  { pf token not { exit } if P7KEYS exch .knownget { exec } if } loop
  /bpc 8 def
  /rsize w 4 mul def		% same bytes per line for CMYK or RGB_TAG
  /T load /CMYK eq {
    /ncomp 4 def /invert false def /DeviceCMYK setcolorspace
    w h { readstring pop }
  } if
  /T load /RGB_ALPHA eq {
    /ncomp 4 def /invert false def /DeviceCMYK setcolorspace
    w h { readstring pop }
  } if
  /T load /GRAYSCALE eq {
    /ncomp 1 def /invert false def /DeviceGray setcolorspace
    w h { readstring pop }
  } if
  /T load /RGB_TAG eq {
    % not CMYK, must be RGB_TAG since was checked above
    /TAG where {
      pop
      % show the tags as pseudo-color image
      /ncomp 1 def /invert false def /maxv 1 def
      [ /Indexed /DeviceRGB 255
        % UNTOUCHED=0, TEXT=1, IMAGE=2, PATH=4
        %     gray      red     green    blue
        768 string
        dup 0 <cccccc ff0000 00ff00 ffff00 0000ff ff00ff 00ffff ffffff 000000> putinterval
      ] setcolorspace
      w h {
        readstring pop
        % discard all but the tag
        dup length 4 div cvi
        string	% destination string
        0 1 2 index length 1 sub {
          2 index 1 index 4 mul get
          2 index exch 2 index exch
          put
          pop % done with pixel#
        } for
        exch pop
      }
    } {
      % show the image as RGB (ignore tags)
      /ncomp 3 def /invert false def /DeviceRGB setcolorspace
      w h {
        readstring pop
        % re-pack the RGB, discard the tag
        dup length 4 div 3 mul cvi string	% destination string
        0 1 2 index length 3 idiv 1 sub {
          % stack: RGBTstring destRGBstring pixel#
          2 index 1 index 4 mul 4 getinterval
          1 3 getinterval	% RGB values
          % stack RGBTstring destRGBstring pixel# RGBstring
          2 index exch 2 index 3 mul exch
          putinterval
          pop % done with pixel#
        } for
        exch pop
      }
    } ifelse
  } if
} bind

.dicttomark readonly def
/pbmsetup {			% <file> <w> <h> <readproc> pbmsetup <imagedict>
   /readproc exch def
   /h exch def
   /w exch def
   /f exch def
   20 dict begin		% image dictionary
     /ImageType 1 def
     /Width w def
     /Height h def
     /ImageMatrix [w 0 0 h neg 0 h] def
     /BitsPerComponent bpc def
     /Decode [ 0 255 maxv div invert { exch } if ncomp 1 sub { 2 copy } repeat ] def
     /DataSource [ f rsize string /readproc load /exec load ] cvx def
   currentdict end
} def
/imagescale {			% <imagedict> imagescale -
  begin
    /SCALE where {
      pop
      /FITPAGE where {/FITPAGE get}{false} ifelse
      {
          Width SCALE mul Height SCALE mul
      }
      {
        % Map pixels SCALE-for-1.  Assume orthogonal transformation.
        Width 1 0 dtransform add abs div SCALE mul
        Height 0 1 dtransform add abs div SCALE mul
      } ifelse
    } {
      /FITPAGE where {/FITPAGE get}{false} ifelse
      {
          % Scale the image (uniformly) to fit the page.
        clippath pathbbox pop pop translate	% offset to the printable origin
        pathbbox 3 -1 roll sub exch 3 -1 roll sub exch
        % stack printable_width printable_height
        2 copy gt 3 1 roll .min exch
        % stack: min(printable_w, printable_h) landscape?
        {
          % printable height is less than width (landscape)
          dup Height Width gt {
            Width mul Height div exch
          } {
            Height mul Width div
          } ifelse
        } {
          % printable width is less than height (portrait)
          dup Height Width lt {
            Width mul Height div exch
          } {
            Height mul Width div
          } ifelse
        } ifelse
      }
      {
        0 0 translate
        612 792
      }
      ifelse
    }
    ifelse
    scale
  end
} def

% Image a PBM file page by page.
/viewpbm {			% <filename> viewpbm -
  20 dict begin
    (r) file /pf exch def {
      pf token not { exit } if
      pbmtypes exch get pf exch exec pbmsetup
      currentcolorspace			% preserve colorspace around setpagedevice
      /FITPAGE where
      {
        /FITPAGE get
        {
          /SCALE where
          {
            pop
            << /PageSize [ 1 1 dtransform h SCALE mul exch abs div exch w SCALE mul exch abs div exch ] >>
          }
          {
            << /PageSize [ 1 1 dtransform h exch abs div exch w exch abs div exch ] >>
          } ifelse
          setpagedevice
        } if
      } if
      setcolorspace			% restore colorspave in case we did setpagedevice
      dup imagescale image showpage
    } loop
  end
} def

% Reassemble a composite PBM file from the CMYK separations.
/viewpsm {
  20 dict begin
    /fname exch def
    /sources [ 0 1 3 {
      /plane exch def
      /pf fname (r) file def
      pf pbmtypes pf token pop get exec
                % Stack: pf w h readproc
      plane {
        /readproc exch def /h exch def /w exch def pop
        /row rsize string def
        h { pf row readproc pop } repeat
        pf pbmtypes pf token pop get exec
      } repeat
      pbmsetup
    } for ] def
    /datas [ sources { /DataSource get 0 get } forall ] def
    /decode sources 0 get /Decode get
      dup 0 get exch 1 get add cvi 0 exch
      2 copy 4 copy 8 array astore def
    sources 0 get
      dup /MultipleDataSources true put
      dup /DataSource datas put
      dup /Decode decode put
    /DeviceCMYK setcolorspace
    /FITPAGE where
    {
      /FITPAGE get
      {
        /SCALE where
        {
            <</PageSize [w SCALE mul h SCALE mul]>>
        }
        {
            <</PageSize [w h]>>
        }ifelse
        setpagedevice
      } if
    } if
    dup imagescale image showpage
  end
} def

% If the program was invoked from the command line, run it now.
[ .shellarguments
 { counttomark 1 ge
    { ] { viewpbm } forall
    }
    { cleartomark
      (Usage: gs [-dSCALE=#.#] [-dFITPAGE] [--] viewpbm.ps filename.p*m ...\n) print
      ( e.g.: gs [-dSCALE=#.#] [-dFITPAGE] [--] viewpbm.ps my.ppm another.ppm\n) print flush
      (    also -dTAG option can be used to show the pseudo-color tag image from a\n) print flush
      (    P7 RGB_TAG PAM file created by the bitrgbtags device.\n) print flush
    }
   ifelse
 }
 { pop
 }
ifelse