You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

337 lines
10 KiB

1 month ago
  1. % Copyright (C) 2001-2023 Artifex Software, Inc.
  2. % All Rights Reserved.
  3. %
  4. % This software is provided AS-IS with no warranty, either express or
  5. % implied.
  6. %
  7. % This software is distributed under license and may not be copied,
  8. % modified or distributed except as expressly authorized under the terms
  9. % of the license contained in the file LICENSE in this distribution.
  10. %
  11. % Refer to licensing information at http://www.artifex.com or contact
  12. % Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
  13. % CA 94129, USA, for further information.
  14. %
  15. % viewpbm.ps
  16. % Display a PBM/PGM/PPM file.
  17. % Requires the Level 2 `image' operator (to handle variable pixel widths).
  18. % If SCALE is defined, maps input pixels to output pixels with that scale;
  19. % if SCALE is undefined, scales the image to fit the page.
  20. % If FITPAGE true, it fits the output page size to the image, honouring SCALE
  21. % When the input is PAM (P7) RGBTAG from bitrgbtags device, -dTAG will show
  22. % the tags is pseudo color:
  23. % TEXT=1, IMAGE=2, PATH=4, UNTOUCHED=8
  24. % red green blue gray
  25. /s 100 string def
  26. /readmaxv { % <file> readmaxv -
  27. 10 string readline pop cvx exec /maxv exch def
  28. } bind def
  29. /readrow { % <file> <row> readrow <row>
  30. 0 1 2 index length 1 sub {
  31. 1 index exch 3 index token pop put
  32. } for exch pop
  33. } bind def
  34. /read01 { % <file> <count> read01 <byte>
  35. 0 exch {
  36. 1 index read pop 48 xor dup 1 le { exch dup add add } { pop } ifelse
  37. } repeat
  38. } bind def
  39. /readrow01 { % <file> <row> readrow01 <row>
  40. 0 1 w 8 idiv {
  41. 1 index exch 3 index 8 read01 put
  42. } for
  43. wrem 0 ne {
  44. dup rsize 1 sub wrem read01 8 wrem sub bitshift put
  45. } if
  46. exch pop
  47. } bind def
  48. /readwh { % <file> readwh <w> <h>
  49. dup s readline pop % check for comment
  50. (#) anchorsearch {
  51. pop pop dup s readline pop
  52. } if
  53. cvx exec
  54. } bind def
  55. /pbmtypes mark
  56. % The procedures in this dictionary are called as
  57. % <file> Pn <w> <h> <readproc>
  58. /P1 { % ASCII 1-bit white/black
  59. /bpc 1 def /maxv 1 def /rsize w 7 add 8 idiv def
  60. /wrem w 8 mod def
  61. /ncomp 1 def /invert true def /DeviceGray setcolorspace
  62. readwh
  63. { readrow01 }
  64. } bind
  65. /P2 { % ASCII 8-bit gray
  66. readwh
  67. /bpc 8 def 2 index readmaxv /rsize 2 index def
  68. /ncomp 1 def /invert false def /DeviceGray setcolorspace
  69. { readrow }
  70. } bind
  71. /P3 { % ASCII 8-bit RGB
  72. readwh
  73. /bpc 8 def 2 index readmaxv /rsize 2 index 3 mul def
  74. /ncomp 3 def /invert false def /DeviceRGB setcolorspace
  75. { readrow }
  76. } bind
  77. /P4 { % Binary 1-bit white/black
  78. readwh
  79. /bpc 1 def /maxv 1 def /rsize 2 index 7 add 8 idiv def
  80. /ncomp 1 def /invert true def /DeviceGray setcolorspace
  81. { readstring pop }
  82. } bind
  83. /P5 { % Binary 8-bit gray
  84. readwh
  85. /bpc 8 def 2 index readmaxv /rsize 2 index def
  86. /ncomp 1 def /invert false def /DeviceGray setcolorspace
  87. { readstring pop }
  88. } bind
  89. /P6 { % Binary 8-bit RGB
  90. readwh
  91. /bpc 8 def 2 index readmaxv /rsize 2 index 3 mul def
  92. /ncomp 3 def /invert false def /DeviceRGB setcolorspace
  93. { readstring pop }
  94. } bind
  95. /P7 { % Assume Binary 8-bit CMYK -- assumes 'pf' is the input file
  96. % P7
  97. % WIDTH 612 %% used to set rsize and w
  98. % HEIGHT 792 %% used to set h
  99. % DEPTH 4 %% if present and not 1 or 4, then bail
  100. % MAXVAL 255 %% used to set maxv
  101. % TUPLTYPE CMYK | RGB_TAG | RGB_ALPHA | GRAYSCALE %% if present and not one of these, then bail
  102. % ENDHDR %% skip everything else up to this
  103. /P7KEYS <<
  104. /WIDTH { /w pf token pop def }
  105. /HEIGHT { /h pf token pop def }
  106. /DEPTH { /d pf token pop def d 4 eq d 1 eq or not {
  107. (*** Only DEPTH 1 or 4 PAM files supported at this time. ***) = quit
  108. } if
  109. }
  110. /MAXVAL { /maxv pf token pop def }
  111. /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 {
  112. (*** Only CMYK, RGB_TAG, RGB_ALPHA and GRAYSCALE files supported at this time. ***) = quit
  113. } if
  114. /T exch def
  115. }
  116. /ENDHDR { exit }
  117. (#) cvn { pf 255 string readline pop pop }
  118. >> def
  119. { pf token not { exit } if P7KEYS exch .knownget { exec } if } loop
  120. /bpc 8 def
  121. /rsize w 4 mul def % same bytes per line for CMYK or RGB_TAG
  122. /T load /CMYK eq {
  123. /ncomp 4 def /invert false def /DeviceCMYK setcolorspace
  124. w h { readstring pop }
  125. } if
  126. /T load /RGB_ALPHA eq {
  127. /ncomp 4 def /invert false def /DeviceCMYK setcolorspace
  128. w h { readstring pop }
  129. } if
  130. /T load /GRAYSCALE eq {
  131. /ncomp 1 def /invert false def /DeviceGray setcolorspace
  132. w h { readstring pop }
  133. } if
  134. /T load /RGB_TAG eq {
  135. % not CMYK, must be RGB_TAG since was checked above
  136. /TAG where {
  137. pop
  138. % show the tags as pseudo-color image
  139. /ncomp 1 def /invert false def /maxv 1 def
  140. [ /Indexed /DeviceRGB 255
  141. % UNTOUCHED=0, TEXT=1, IMAGE=2, PATH=4
  142. % gray red green blue
  143. 768 string
  144. dup 0 <cccccc ff0000 00ff00 ffff00 0000ff ff00ff 00ffff ffffff 000000> putinterval
  145. ] setcolorspace
  146. w h {
  147. readstring pop
  148. % discard all but the tag
  149. dup length 4 div cvi
  150. string % destination string
  151. 0 1 2 index length 1 sub {
  152. 2 index 1 index 4 mul get
  153. 2 index exch 2 index exch
  154. put
  155. pop % done with pixel#
  156. } for
  157. exch pop
  158. }
  159. } {
  160. % show the image as RGB (ignore tags)
  161. /ncomp 3 def /invert false def /DeviceRGB setcolorspace
  162. w h {
  163. readstring pop
  164. % re-pack the RGB, discard the tag
  165. dup length 4 div 3 mul cvi string % destination string
  166. 0 1 2 index length 3 idiv 1 sub {
  167. % stack: RGBTstring destRGBstring pixel#
  168. 2 index 1 index 4 mul 4 getinterval
  169. 1 3 getinterval % RGB values
  170. % stack RGBTstring destRGBstring pixel# RGBstring
  171. 2 index exch 2 index 3 mul exch
  172. putinterval
  173. pop % done with pixel#
  174. } for
  175. exch pop
  176. }
  177. } ifelse
  178. } if
  179. } bind
  180. .dicttomark readonly def
  181. /pbmsetup { % <file> <w> <h> <readproc> pbmsetup <imagedict>
  182. /readproc exch def
  183. /h exch def
  184. /w exch def
  185. /f exch def
  186. 20 dict begin % image dictionary
  187. /ImageType 1 def
  188. /Width w def
  189. /Height h def
  190. /ImageMatrix [w 0 0 h neg 0 h] def
  191. /BitsPerComponent bpc def
  192. /Decode [ 0 255 maxv div invert { exch } if ncomp 1 sub { 2 copy } repeat ] def
  193. /DataSource [ f rsize string /readproc load /exec load ] cvx def
  194. currentdict end
  195. } def
  196. /imagescale { % <imagedict> imagescale -
  197. begin
  198. /SCALE where {
  199. pop
  200. /FITPAGE where {/FITPAGE get}{false} ifelse
  201. {
  202. Width SCALE mul Height SCALE mul
  203. }
  204. {
  205. % Map pixels SCALE-for-1. Assume orthogonal transformation.
  206. Width 1 0 dtransform add abs div SCALE mul
  207. Height 0 1 dtransform add abs div SCALE mul
  208. } ifelse
  209. } {
  210. /FITPAGE where {/FITPAGE get}{false} ifelse
  211. {
  212. % Scale the image (uniformly) to fit the page.
  213. clippath pathbbox pop pop translate % offset to the printable origin
  214. pathbbox 3 -1 roll sub exch 3 -1 roll sub exch
  215. % stack printable_width printable_height
  216. 2 copy gt 3 1 roll .min exch
  217. % stack: min(printable_w, printable_h) landscape?
  218. {
  219. % printable height is less than width (landscape)
  220. dup Height Width gt {
  221. Width mul Height div exch
  222. } {
  223. Height mul Width div
  224. } ifelse
  225. } {
  226. % printable width is less than height (portrait)
  227. dup Height Width lt {
  228. Width mul Height div exch
  229. } {
  230. Height mul Width div
  231. } ifelse
  232. } ifelse
  233. }
  234. {
  235. 0 0 translate
  236. 612 792
  237. }
  238. ifelse
  239. }
  240. ifelse
  241. scale
  242. end
  243. } def
  244. % Image a PBM file page by page.
  245. /viewpbm { % <filename> viewpbm -
  246. 20 dict begin
  247. (r) file /pf exch def {
  248. pf token not { exit } if
  249. pbmtypes exch get pf exch exec pbmsetup
  250. currentcolorspace % preserve colorspace around setpagedevice
  251. /FITPAGE where
  252. {
  253. /FITPAGE get
  254. {
  255. /SCALE where
  256. {
  257. pop
  258. << /PageSize [ 1 1 dtransform h SCALE mul exch abs div exch w SCALE mul exch abs div exch ] >>
  259. }
  260. {
  261. << /PageSize [ 1 1 dtransform h exch abs div exch w exch abs div exch ] >>
  262. } ifelse
  263. setpagedevice
  264. } if
  265. } if
  266. setcolorspace % restore colorspave in case we did setpagedevice
  267. dup imagescale image showpage
  268. } loop
  269. end
  270. } def
  271. % Reassemble a composite PBM file from the CMYK separations.
  272. /viewpsm {
  273. 20 dict begin
  274. /fname exch def
  275. /sources [ 0 1 3 {
  276. /plane exch def
  277. /pf fname (r) file def
  278. pf pbmtypes pf token pop get exec
  279. % Stack: pf w h readproc
  280. plane {
  281. /readproc exch def /h exch def /w exch def pop
  282. /row rsize string def
  283. h { pf row readproc pop } repeat
  284. pf pbmtypes pf token pop get exec
  285. } repeat
  286. pbmsetup
  287. } for ] def
  288. /datas [ sources { /DataSource get 0 get } forall ] def
  289. /decode sources 0 get /Decode get
  290. dup 0 get exch 1 get add cvi 0 exch
  291. 2 copy 4 copy 8 array astore def
  292. sources 0 get
  293. dup /MultipleDataSources true put
  294. dup /DataSource datas put
  295. dup /Decode decode put
  296. /DeviceCMYK setcolorspace
  297. /FITPAGE where
  298. {
  299. /FITPAGE get
  300. {
  301. /SCALE where
  302. {
  303. <</PageSize [w SCALE mul h SCALE mul]>>
  304. }
  305. {
  306. <</PageSize [w h]>>
  307. }ifelse
  308. setpagedevice
  309. } if
  310. } if
  311. dup imagescale image showpage
  312. end
  313. } def
  314. % If the program was invoked from the command line, run it now.
  315. [ .shellarguments
  316. { counttomark 1 ge
  317. { ] { viewpbm } forall
  318. }
  319. { cleartomark
  320. (Usage: gs [-dSCALE=#.#] [-dFITPAGE] [--] viewpbm.ps filename.p*m ...\n) print
  321. ( e.g.: gs [-dSCALE=#.#] [-dFITPAGE] [--] viewpbm.ps my.ppm another.ppm\n) print flush
  322. ( also -dTAG option can be used to show the pseudo-color tag image from a\n) print flush
  323. ( P7 RGB_TAG PAM file created by the bitrgbtags device.\n) print flush
  324. (From version 9.50 you must supply permissions for this program to read the input file(s)\n) print flush
  325. (either by using -dNOSAFER or by supplying --permit-file-read=<filename>\n) = flush
  326. }
  327. ifelse
  328. }
  329. { pop
  330. }
  331. ifelse