I'm aware that similar questions have been answered here before:
- postscript - overlay one pdf or ps file on top of another - Stack Overflow
- overlay - Overlaying or merging multiple .ps files - Stack Overflow
... however, as they don't directly answer my specific problem, I'll try asking again.
I would like to know, how I can overlay two postscript files: one - a logo:
... on top of the other - a graphic background:
.... using a command line approach in Linux.
It is of importance here, that the graphic background preserves its original contents to the greatest extent possible. Therefore, I'd probably be happiest if I could somehow concatenate the two original postscript file contents unchanged (see below) - but other than that, I'd like to know how command-line tools like ghostscript
could be used for the purpose.
The problem - logo on top of PCB .ps printout
Here is the problem in more detail - I want to add a logo on top of a PCB board print. I use kicad
to develop the PCB print; once done, I export a postscript document with the individual layers. Usually, I want to have the front copper layer "mirrored"; I have often experimented with loading the .ps output into, say, inkscape
, and then trying to do a mirroring there. Using inkscape
was also convenient, because one can easily add a logo there (and then mirror the print and the logo together).
However, using inkscape
to process postscript output is an expencive operation (because it takes a while for inkscape
to load, and do the mirroring, and the saving)... Although, the main show stopper here is that: after processing, some of the dimensions may be slightly changed in the output file by inkscape
(and it makes a lot of difference, when the target is printing of tracks less than a millimeter wide).
So, given that kicad
s "Plot" command has an option for mirroring - it is, of course, much better for me to "mirror" the layer print directly from kicad
s "Plot" command; the output is again a postscript file. tmp-Front.ps
is an example of such a (mirrored) postscript file. Note that typically, the "copper" part is filled with black - and I'd basically like to have a white logo on top of it.
Now, since this print is already "mirrored" - if I want to add a logo on top of it, I better have the logo mirrored as well. So I fire up inkscape
; and:
- add a text for the logo;
- set up via Document Properties:
- that the document size matches the logo size, and
- that the document should have a black background
- Then change the logo text to have white fill;
- do Object/Flip Horizontal on the logo text; and then
- do File/Save a Copy;
- choose PostScipt (*.ps) as output;
- on the dialog choose PostScript level 2, and
- select "Convert text to paths" before exporting.
This is how logo.ps
linked above was generated (note that - for these kind of small logos: without 'text to paths', the .ps file (with fonts) can be up to 20 kB; as opposed to 5 kB for paths only).
One problem, though, is that postscript doesn't really support something like a "document background" color - apparently you need to define a filled rectangle yourself:
- Adobe Forums: How to change ps file page background to transparent;
- Re: Exporting canvas to PostScript loses background color;
... therefore if you open logo.ps
, you will not see anything - since it contains white letters on white background.
Viewers
If in logo.ps
, the 1 g
line is replaced with 0.5 g
; the logo becomes gray (and visible), and here it is rendered under evince
, gs
raw viewer, and gv
:
Here is the same comparison for tmp-Front.ps
:
Notably, the raw ghostscript
viewer ignores bounding box and page orientation - and even more problematic is, if you use Ubuntu Gnome on a netbook, then the top and bottom bar may cut a bit of the ghostscript
viewer window - enough so that the logo in bottom left corner is invisible; and since "... the raw ghostscript viewer gs ... has no real user interface", a gs
window which started up with the logo cropped, cannot be set to show it afterwards.
Concatenating .ps file contents for overlay
By looking at these references:
- Ghostscript overlaying concatenated postscript files - comp.lang.postscript
- Re: Merge postscript files - comp.lang.postscript;
- Getting rid of pagethrow on merge - Mombu the Programming Forum
... I'm guessing that, in principle, it should be possible to concatenate the file contents of two postscript files; and if there is only a single showpage
command in the merged file - then, in principle, one should obtain an overlay (?!) of the two. However, I tried that, and I cannot really get it to work.
If this is possible, I'd like to somehow just copy/paste the postscript file contents (and thereby avoid any problems with document dimensions/sizes/resolutions) - and then possibly use the translate
postscript command (see Postscript Editing in Gnuplot) to adjust the position of the logo. Having the 'overlaid' (merged) .ps opened in evince
, would refresh the document display each time the translate
parameters are changed in a text editor - so it should be relatively easy to handle the logo positioning in that way.
However, I can foresee some problems here too: for one, the graphic (tmp-Front.ps
) contains:
%%BoundingBox: 0 0 596 843
%%DocumentMedia: A4 595 842 0 () ()
...
0.0072 0.0072 scale
...
30085 54415 moveto
...
... while logo.ps
contains:
%%BoundingBox: 0 0 31 13
...
%%DocumentMedia: 11x4mm 31 13 0 () ()
...
25.539 9.536 m(oveto) ...
...
... thus there are two main differences:
- Document size is not the same for the files
- Scale (or rather resolution/coordinate system) is not the same either
Since I couldn't get concatenation of file contents to work at all - I'm not really sure if these differences would have an influence on the overlay ... I'd certainly hope that they are somehow rendered independently; and the translate
would just help to properly set up their relative position :)
So - how would I go about, if I wanted to achieve an overlay by concatenating postscript file contents? And if that is too troublesome - how could I use a tool such as ghostscript
(or any other), in order to set up an overlay?
Many thanks in advance for any answers,
Cheers!
For reference, here are copies of the mentioned postscript files (as they are not too big):
%!PS-Adobe-3.0
%%Creator: PCBNEW-PS
%%CreationDate: Thu Mar 22 09:50:52 2012
%%Title: /tmp-Front.ps
%%Pages: 1
%%PageOrder: Ascend
%%BoundingBox: 0 0 596 843
%%DocumentMedia: A4 595 842 0 () ()
%%Orientation: Landscape
%%EndComments
%%Page: 1 1
/line {
newpath
moveto
lineto
stroke
} bind def
/cir0 { newpath 0 360 arc stroke } bind def
/cir1 { newpath 0 360 arc gsave fill grestore stroke } bind def
/cir2 { newpath 0 360 arc gsave fill grestore stroke } bind def
/arc0 { newpath arc stroke } bind def
/arc1 { newpath 4 index 4 index moveto arc closepath gsave fill grestore stroke } bind def
/arc2 { newpath 4 index 4 index moveto arc closepath gsave fill grestore stroke } bind def
/poly0 { stroke } bind def
/poly1 { closepath gsave fill grestore stroke } bind def
/poly2 { closepath gsave fill grestore stroke } bind def
/rect0 { rectstroke } bind def
/rect1 { rectfill } bind def
/rect2 { rectfill } bind def
/linemode0 { 0 setlinecap 0 setlinejoin 0 setlinewidth } bind def
/linemode1 { 1 setlinecap 1 setlinejoin } bind def
/dashedline { [50 50] 0 setdash } bind def
/solidline { [] 0 setdash } bind def
gsave
0.0072 0.0072 scale
linemode1
82670 0 translate 90 rotate
60 setlinewidth
60 setlinewidth
newpath
30085 54415 moveto
30085 52585 lineto
31915 52585 lineto
31915 54415 lineto
30085 54415 lineto
poly1
newpath
87950 54930 moveto
32094 54930 lineto
32094 54474 lineto
32094 54415 lineto
32094 52525 lineto
32071 52470 lineto
32029 52428 lineto
31974 52406 lineto
31915 52406 lineto
30025 52406 lineto
29970 52429 lineto
29928 52471 lineto
29906 52526 lineto
29906 52585 lineto
29906 54475 lineto
29929 54530 lineto
29971 54572 lineto
30026 54594 lineto
30085 54594 lineto
31975 54594 lineto
32030 54571 lineto
32072 54529 lineto
32094 54474 lineto
32094 54930 lineto
28300 54930 lineto
28300 17800 lineto
87950 17800 lineto
87950 54930 lineto
poly1
100 setlinewidth
newpath
87950 54930 moveto
32094 54930 lineto
32094 54474 lineto
32094 54415 lineto
32094 52525 lineto
32071 52470 lineto
32029 52428 lineto
31974 52406 lineto
31915 52406 lineto
30025 52406 lineto
29970 52429 lineto
29928 52471 lineto
29906 52526 lineto
29906 52585 lineto
29906 54475 lineto
29929 54530 lineto
29971 54572 lineto
30026 54594 lineto
30085 54594 lineto
31975 54594 lineto
32030 54571 lineto
32072 54529 lineto
32094 54474 lineto
32094 54930 lineto
28300 54930 lineto
28300 17800 lineto
87950 17800 lineto
87950 54930 lineto
poly0
1 1 1 setrgbcolor
60 setlinewidth
31000 53500 170 cir1
0 0 0 setrgbcolor
showpage
grestore
%%EOF
%!PS-Adobe-3.0
%%Creator: cairo 1.10.2 (http://cairographics.org)
%%CreationDate: Thu Mar 22 10:07:46 2012
%%Pages: 1
%%BoundingBox: 0 0 31 13
%%DocumentData: Clean7Bit
%%LanguageLevel: 2
%%DocumentMedia: 11x4mm 31 13 0 () ()
%%EndComments
%%BeginProlog
/languagelevel where
{ pop languagelevel } { 1 } ifelse
2 lt { /Helvetica findfont 12 scalefont setfont 50 500 moveto
(This print job requires a PostScript Language Level 2 printer.) show
showpage quit } if
/q { gsave } bind def
/Q { grestore } bind def
/cm { 6 array astore concat } bind def
/w { setlinewidth } bind def
/J { setlinecap } bind def
/j { setlinejoin } bind def
/M { setmiterlimit } bind def
/d { setdash } bind def
/m { moveto } bind def
/l { lineto } bind def
/c { curveto } bind def
/h { closepath } bind def
/re { exch dup neg 3 1 roll 5 3 roll moveto 0 rlineto
0 exch rlineto 0 rlineto closepath } bind def
/S { stroke } bind def
/f { fill } bind def
/f* { eofill } bind def
/n { newpath } bind def
/W { clip } bind def
/W* { eoclip } bind def
/BT { } bind def
/ET { } bind def
/pdfmark where { pop globaldict /?pdfmark /exec load put }
{ globaldict begin /?pdfmark /pop load def /pdfmark
/cleartomark load def end } ifelse
/BDC { mark 3 1 roll /BDC pdfmark } bind def
/EMC { mark /EMC pdfmark } bind def
/cairo_store_point { /cairo_point_y exch def /cairo_point_x exch def } def
/Tj { show currentpoint cairo_store_point } bind def
/TJ {
{
dup
type /stringtype eq
{ show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse
} forall
currentpoint cairo_store_point
} bind def
/cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore
cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def
/Tf { pop /cairo_font exch def /cairo_font_matrix where
{ pop cairo_selectfont } if } bind def
/Td { matrix translate cairo_font_matrix matrix concatmatrix dup
/cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point
/cairo_font where { pop cairo_selectfont } if } bind def
/Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def
cairo_store_point /cairo_font where { pop cairo_selectfont } if } bind def
/g { setgray } bind def
/rg { setrgbcolor } bind def
/d1 { setcachedevice } bind def
%%EndProlog
%%Page: 1 1
%%BeginPageSetup
%%PageMedia: 11x4mm
%%PageBoundingBox: 0 0 31 13
%%EndPageSetup
q 0 0 31 13 rectclip q
1 g
25.539 9.536 m 25.539 7.567 l 27.227 7.567 l 27.227 3.817 l 27.227
3.055 27.211 2.606 27.18 2.473 c 27.152 2.348 27.078 2.243 26.961 2.161
c 26.848 2.087 26.707 2.052 26.539 2.052 c 26.324 2.052 25.992 2.13
25.555 2.286 c 25.336 0.364 l 25.922 0.118 26.574 -0.011 27.289 -0.011
c 27.738 -0.011 28.145 0.063 28.508 0.208 c 28.863 0.36 29.125 0.559
29.289 0.802 c 29.457 1.04 29.574 1.364 29.633 1.77 c 29.688 2.048
29.711 2.63 29.711 3.505 c 29.711 7.567 l 30.852 7.567 l 30.852 9.536 l
29.711 9.536 l 29.711 11.395 l 27.227 12.833 l 27.227 9.536 l h
18.535 3.177 m 16.082 2.77 l 16.395 1.864 16.898 1.169 17.582 0.692 c
18.262 0.223 19.117 -0.011 20.145 -0.011 c 21.77 -0.011 22.969 0.52
23.738 1.583 c 24.355 2.434 24.66 3.509 24.66 4.802 c 24.66 6.352
24.262 7.567 23.457 8.442 c 22.648 9.313 21.621 9.755 20.379 9.755 c
18.996 9.755 17.902 9.294 17.098 8.38 c 16.297 7.462 15.914 6.055
15.941 4.161 c 22.129 4.161 l 22.121 3.43 21.926 2.86 21.551 2.458 c
21.168 2.052 20.688 1.848 20.113 1.848 c 19.73 1.848 19.406 1.95 19.145
2.161 c 18.875 2.368 18.672 2.708 18.535 3.177 c h
18.395 5.677 m 18.418 6.391 18.605 6.934 18.957 7.302 c 19.312 7.673
19.742 7.864 20.238 7.864 c 20.781 7.864 21.227 7.665 21.566 7.27 c
21.922 6.884 22.098 6.352 22.098 5.677 c h
15.02 2.864 m 12.535 3.255 l 12.434 2.774 12.219 2.407 11.895 2.161 c
11.574 1.911 11.125 1.786 10.551 1.786 c 9.906 1.786 9.422 1.899 9.098
2.13 c 8.891 2.294 8.785 2.512 8.785 2.786 c 8.785 2.97 8.844 3.13
8.957 3.255 c 9.082 3.368 9.359 3.477 9.785 3.583 c 11.777 4.016 13.039
4.419 13.566 4.786 c 14.309 5.282 14.676 5.989 14.676 6.895 c 14.676
7.696 14.359 8.372 13.723 8.927 c 13.078 9.477 12.09 9.755 10.754 9.755
c 9.477 9.755 8.527 9.544 7.91 9.13 c 7.289 8.712 6.855 8.095 6.613
7.286 c 8.941 6.848 l 9.047 7.212 9.242 7.489 9.52 7.677 c 9.793 7.872
10.188 7.973 10.707 7.973 c 11.355 7.973 11.82 7.884 12.098 7.708 c
12.285 7.571 12.379 7.403 12.379 7.208 c 12.379 7.028 12.297 6.876
12.129 6.755 c 11.914 6.587 11.145 6.352 9.832 6.052 c 8.523 5.759
7.598 5.391 7.066 4.958 c 6.559 4.52 6.301 3.907 6.301 3.13 c 6.301
2.274 6.664 1.532 7.379 0.911 c 8.09 0.294 9.148 -0.011 10.551 -0.011 c
11.824 -0.011 12.828 0.247 13.566 0.77 c 14.309 1.29 14.793 1.989 15.02
2.864 c h
0.066 9.536 m 0.066 7.567 l 1.754 7.567 l 1.754 3.817 l 1.754 3.055
1.738 2.606 1.707 2.473 c 1.68 2.348 1.605 2.243 1.488 2.161 c 1.375
2.087 1.234 2.052 1.066 2.052 c 0.852 2.052 0.52 2.13 0.082 2.286 c
-0.137 0.364 l 0.449 0.118 1.102 -0.011 1.816 -0.011 c 2.266 -0.011
2.672 0.063 3.035 0.208 c 3.391 0.36 3.652 0.559 3.816 0.802 c 3.984
1.04 4.102 1.364 4.16 1.77 c 4.215 2.048 4.238 2.63 4.238 3.505 c 4.238
7.567 l 5.379 7.567 l 5.379 9.536 l 4.238 9.536 l 4.238 11.395 l 1.754
12.833 l 1.754 9.536 l h
0.066 9.536 m f
Q Q
showpage
%%Trailer
%%EOF
EDIT: Re: luser droog's answer; if I try to open combo.ps
as written in evince
, I get:
$ evince combo.ps
invalidfileaccess -9
This is probably related to #414002 - gs -dSAFER: /invalidfileaccess with "run" operator - Debian Bug report logs... If I try to add the PostScript header "%!
" at start, I get:
$ nano combo.ps # added %! at start
$ evince combo.ps
undefined -21
undefined -21
I also tried running ps2ps
- this is what comes out:
$ ps2ps combo.ps comboB.ps
Error: /undefined in --load--
Operand stack:
Oldshowpage
Execution stack:
%interp_exit .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- --nostringval-- false 1 %stopped_push 1910 1 3 %oparray_pop 1909 1 3 %oparray_pop 1893 1 3 %oparray_pop 1787 1 3 %oparray_pop --nostringval-- %errorexec_pop .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval--
Dictionary stack:
--dict:1159/1684(ro)(G)-- --dict:0/20(G)-- --dict:77/200(L)--
Current allocation mode is local
Current file position is 30
GPL Ghostscript 9.02: Unrecoverable error, exit code 1
Ok, here is what works for me, thanks to @luserdroog's answer, with unchanged files, and "directly" in
evince
.First of all, get
tmp-Front.ps
,logo.ps
and @luserdroogcombo.ps
(modded below) in a directory. The first problem is that ifevince
encounters%%EOF
, it will stop parsing whatever comes next. So, we first want to get rid of those directives intmp-Front.ps
andlogo.ps
:Second, if
evince
doesn't encounter%%Orientation
and similar directives at the very beginning, then it will not show the document in landscape (as the originaltmp-Front.ps
is). Thus, we should extract these directives fromtmp-Front.ps
, and add them at the beginning ofcombo.ps
- and save all that as new file,combopg.ps
:Here I use the following modification of
combo.ps
:Finally, since
evince
doesn't recognize therun
directive, I use this modification ofpsinc
, psinc.pl to "include" the contents of the files:Now, you can finally open
combopgout.ps
inevince
- and simultaneously in a text editor, where you can look for the line300 300 translate
; editing these arguments in the text editor and saving the file will causeevince
to reload the .ps file and show the latest position - it would look like this for the default:(Note the logo is rotated as per landscape orientation)
Well, I guess this solves it - thanks for the answers!!
A similar approach to KenS's would be to put the "composition" code in a single file and call the component files with the
run
operator. It amounts to the same thing but with a little less shell-work. A limitation is that the -dSAFER option (which is ON by default in most Distiller installations) disables therun
operator.combo.ps:
In order to 'concatenate' the two files, you would need to disable the 'showpage' operator, as otherwise both files will emit their pages separately. But you need to maintain the original definition so that you can emit the final document. Somethign liek:
So if you saved the redefinitions in a file, and the final execution in another file you might
cat 'prolog.ps file1.ps file2.ps epilog.ps'
Neither of your files executes a media request (you can ignore the %% lines, those are comments only).
However, as you rightly say you don't want scaling and transforms to persist between jobs. So you need to save and restore the graphics state. So in this case you also want a 'middle' file.
So
prolog.ps
contains:middle.ps
containsand
epilog.ps
containscat all 5 files together and it ought to work. It does something sensible for me, but I should perhaps mention that your 'logo.ps' produces an empty page for me with Ghostscript and with Adobe Distiller.