I'm trying to setup a book to print at Blurb.com. I'm preparing the PDF and want to setup the MediaBox, Bleedbox, and TrimBox to confirm that my document is setup correctly for printing. There is an existing question here about the BleedBox, but, the answers do not change the output as reported by pdfinfo and changing multiple boxes is not covered.
Test Script
#!/bin/sh
gs -o output.pdf \
-sDEVICE=pdfwrite \
-r72 \
-dPDFX \
-sProcessColorModel=DeviceCMYK \
-dFIXEDMEDIA \
-dDEVICEWIDTHPOINTS=660 \
-dDEVICEHEIGHTPOINTS=910 \
-c "[/BleedBox [36 36 600 877] /PAGES pdfmark" \
-f test_in.pdf
pdfinfo -f 1 -l 1 -box output.pdf
Output
GPL Ghostscript 9.50 (2019-10-15)
Copyright (C) 2019 Artifex Software, Inc. All rights reserved.
This software is supplied under the GNU AGPLv3 and comes with NO WARRANTY:
see the file COPYING for details.
Processing pages 1 through 17.
Page 1
Page 2
Page 3
Page 4
Page 5
Page 6
Page 7
Page 8
Page 9
Page 10
Page 11
Page 12
Page 13
Page 14
Page 15
Page 16
Page 17
Producer: GPL Ghostscript 9.50
CreationDate: Sun Jan 5 15:46:42 2020
ModDate: Sun Jan 5 15:46:42 2020
Tagged: no
Form: none
Pages: 17
Encrypted: no
Page 1 size: 660 x 910 pts (rotated 0 degrees)
Page 1 MediaBox: 0.00 0.00 660.00 910.00
Page 1 CropBox: 0.00 0.00 660.00 910.00
Page 1 BleedBox: 0.00 0.00 660.00 910.00
Page 1 TrimBox: 0.00 0.00 660.00 910.00
Page 1 ArtBox: 0.00 0.00 660.00 910.00
File size: 1213265 bytes
Optimized: no
PDF version: 1.3
Your input is a PDF file (rather than, say, a PostScript program), which means it already has a /MediaBox and possibly other boxes as well. Note that setting -dFIXEDMEDIA means that you really shouldn't try and change the MediaBox, I mention this because you reference the MediaBox in your question.
Your command line starts by setting up the BleedBox, and then runs the PDF file. The PDF file's own BleedBox (if present) therefore overwrite the BleedBox you set up using a pdfmark, because it comes after the initial setup.
If you execute the pdfmark after running the PDF file, then the pdfmark will override the PDF file, which is (I believe) what you want.
So to take your command line:
gs -o output.pdf \
-sDEVICE=pdfwrite \
-r72 \
-dPDFX \
-sProcessColorModel=DeviceCMYK \
-dFIXEDMEDIA \
-dDEVICEWIDTHPOINTS=660 \
-dDEVICEHEIGHTPOINTS=910 \
test_in.pdf \
-c "[/BleedBox [36 36 600 877] /PAGES pdfmark" \
-f
NOTE: You are requesting PDF/X-3 output, but you haven't set a PDF/X definition program, which means that the output will not be PDF/X-3 compliant because you have not specified a CMYK ICC profile. See here
To set multiple Box values, you just add them to the pdfmark. The pdfmark reference can be found here today, but be warned that Adobe rearrange the furniture on their web site frequently, it'll probably move. Googling for 'pdfmark technical reference' should find it.
Related
Testing wkhtmltopdf for generating huge pdf reports.
Finaly pdf is about 600 pages. After ~500 pages got the same error
Error:failed to load file .......... with network status code 201 and http status code 0 - Error opening kn_footer.html: Too many open files
The value of fs.file-max was about 1.6M. After error I was increased it to 2097152 but it does not help.
Trying to add file cacheing but it's not working. Command line looks like:
wkhtmltopdf --cache-dir /tmp/ --allow /path/to/my/dir/ --margin-top 20 --load-error-handling ignore --orientation landscape --page-size A4 page kn_utf.html --footer-html kn_footer.html --header-html kn_header.html --footer-spacing 1 kn.pdf
Is there any way to say wkhtmltopdf get header and footer at once or close that files after each iteration?
I too was unable to get any sort of caching to work on a 532 page document. I did achieve some success by converting my footer.html file into wkhtmltopdf footer text. You might also consider splitting it into two documents, run wkhtmltodpf twice, and then use pdfunite to merge the two temporary PDFs into the final document. If you're interested in the text footer approach, here's the set of options I used. Don't forget to set the bottom margin (-B option), otherwise the text footer will get dropped off the page.
wkhtmltopdf \
-O landscape \
-s letter \
-L 20 \
-R 20 \
-T 20 \
-B 20 \
--exclude-from-outline \
--image-dpi 300 \
--header-html $BASE_DIR/header.html \
--footer-line \
--footer-spacing 10 \
--footer-left "$FOOTER_LEFT" \
--footer-center "$FOOTER_CENTER" \
--footer-right "$FOOTER_RIGHT" \
--footer-font-size 10 \
--cache-dir $BASE_DIR/cache \
--user-style-sheet $BASE_DIR/some.css \
$TARGET_DIR/[im]*.html \
$TARGET_DIR/final.pdf
How can I make a Ghostscript overlay text on top of a PostScript file?
I found part of a solution here:
How can I make a program overlay text on a postscript file?
which suggests to do:
gs -o figLabel.pdf -sDEVICE=pdfwrite \
-c "/Helvetica findfont 15 scalefont setfont 50 200 moveto (text) show" \
-f fig.eps`
However in that case the text is behind the image.
Is there an option in Ghostscript to force the text to be in front of the image?
PostScript uses an opaque painting model, so each new thing drawn obscures anything previously drawn. In your command line, the text is drawn and then the EPS file is drawn. It sounds like you want the reverse behavior. So do
gs -o figLabel.pdf -sDEVICE=pdfwrite \
-f fig.eps \
-c "/Helvetica findfont 15 scalefont setfont 50 200 moveto (text) show showpage"
This should work IF the EPS file obeys the rule that it should not call showpage itself. Otherwise, we'll need to add workarounds for that.
If the EPS file calls showpage (even though it ought not to do this), we need to redefine the name /showpage so it does nothing, and save the old definition to call at the end.
gs -o figLabel.pdf -sDEVICE=pdfwrite \
-c "/realshowpage /showpage load def /showpage {} def" \
-f fig.eps \
-c "/Helvetica findfont 15 scalefont setfont 50 200 moveto (text) show realshowpage"
I'm trying to assign a folder action to the a folder with PS files that would automatically convert the PS files droppped in the folder to the PNG files. My shell script looks like follow:
for img in "$#"; do
filename = ${img%.*}
convert "$img" -background white -flatten "$filename.png"
done
and settings for my Automator folder action are provided in the screenshot below
I'm experiencing two problems:
When I drop *.ps files onto the folder the Automator action starts but does not produce files. I'm guessing the the problem is concerned with not passing the file name to the Shell Script but I'm not able to find solution to this.
When I attempt to execute the conversion directly from the terminal with use of the command: convert b.ps b.png the produced image is cut, like in the screenshot below
.
I would like to fix so the Automator action:
- Takes all the files that I decide to specify via the Filter Finder Items option
- Converts them to high resolution, quality PNGs respecting the original PS file sizes (without cutting them or providing extra margins)
(You should spell out clearly in your question, that you are working on Mac OSX.)
You may have encountered a bug in ImageMagick when it comes to converting PS files (see also this discussion in the IM forum about it). Try to add -verbose to your convert command to see what exactly goes on.
Fact is, that ImageMagick cannot by itself consume PostScript (or PDF) input. It has to employ a delegate to do that for you -- and that delegate usually is Ghostscript.
It's a better approach for your task if you made your shell script differentiate between different input types: if you get PS or PDF, let Ghostscript do the job directly:
gs \
-o output.png \
-sDEVICE=pngalpha \
-dAlignToPixels=0 \
-dGridFitTT=2 \
-dTextAlphaBits=4 \
-dGraphicsAlphaBits=4 \
-r72x72 \
input.ps-or-pdf
Should you need further post-processing of the generated output.png (such as making the background white instead of transparent you could pipe the output to an ImageMagick convert-command now....
Update
Since it has been asked in a comment: if you want to use the same filename for output, but replace the .ps suffix by a .png suffix, use this Bashism:
inputfilename=../somedir/somefile.ps
gs \
-o ${inputfilename/.ps/.png} \
-sDEVICE=pngalpha \
-dAlignToPixels=0 \
-dGridFitTT=2 \
-dTextAlphaBits=4 \
-dGraphicsAlphaBits=4 \
-r72x72 \
${inputfilename}
or this one
-o $(dirname ${inputfilename})/$(basename ${inputfilename}).png
Both will allow you to keep the original directory (in case your 'inputfilename' includes an absolute or relative path). The first one is not as flexible with the input file's suffix: it works only for .ps -- for PDF you'd get a .pdf.png suffix...
Update 2
First determine which is the real BoundingBox covered by the original PostScript. This is different from the declared BoundingBox, that may (or may not!) be stated in a %%BoundingBox line of the PostScript code. Ghostscript's -sDEVICE=bbox will do that for you:
gs -q -o - -sDEVICE=bbox a.ps
%%BoundingBox: 102 118 866 698
%%HiResBoundingBox: 102.257997 118.502434 865.278747 697.013979
Now you can use this info to determine how many pixels horizontally and how many pixels vertically you want the PNG output file to be sized. I'll pick 940 pixels wide and 760 pixels high (to allow for some margin around the output. Use -g940x760 with Ghostscript to set this as the page size:
inputfilename=a.ps
gs \
-o ${inputfilename/.ps/.png} \
-sDEVICE=pngalpha \
-dAlignToPixels=0 \
-dGridFitTT=2 \
-dTextAlphaBits=4 \
-dGraphicsAlphaBits=4 \
-g940x760 \
${inputfilename}
The output is here:
I have a directory full of images I want to turn into a gif.
Each file name follows this pattern: <zero_padded_index>_<delay_in_milliseconds>.gif
Example: 00001_1432.gif
I can create the gif animation with imagemagick: convert -loop 0 -delay 10 *.gif out.gif
The problem is, I want each frame to have a different delay based on the second digit in it's name.
convert -delay 0 -loop 0 *.gif output.gif
for gif in *.gif; do
name=${gif%.gif}
index=$(echo ${name%-*} | sed 's/0*//')
delay=${name#*-}
# 1. convert milliseconds to w/e imagemagick -delay uses.
# 2. update the frame at the correct index.
done;
Do I incrementally build up the gif? Or go back and change them after the fact?
My imagemagick chops are not up to par.
So If I was approaching this problem i'd do the following ( If I understand correctly )
Given the following files:
[root#dev7 ~]# ls -lta so/
total 728
drwxr-xr-x 2 root root 4096 Aug 13 18:35 .
dr-xr-x---. 17 root root 4096 Aug 13 18:35 ..
-rw-r--r-- 1 root root 18933 Aug 13 18:23 00007_1432.gif
-rw-r--r-- 1 root root 18594 Aug 13 18:23 00006_1432.gif
-rw-r--r-- 1 root root 18984 Aug 13 18:23 00005_1432.gif
-rw-r--r-- 1 root root 19601 Aug 13 18:23 00004_1444.gif
-rw-r--r-- 1 root root 19408 Aug 13 18:23 00003_1432.gif
-rw-r--r-- 1 root root 18632 Aug 13 18:23 00002_1552.gif
-rw-r--r-- 1 root root 20104 Aug 13 18:23 00001_1432.gif
[root#dev7 ~]#
My script would look like this:
#!/bin/bash -x
# directory of the individual gifs
_dir=/root/so/
# get gifs and make sure your sort them in order
gifs=$(find $_dir -name *.gif|sort|xargs)
# this is going to be the imagemagick command
_CONVERT="convert "
# make sure the list of gifs look correct
echo $gifs
for gif in $gifs; do
# full path of each gif
full_path=$gif
# get just the name of the gif ( originally I was going to use this if everything was happing within the same directory )
name=$(echo ${gif##*/})
#echo -e "\n$name"
# Get the index
index=$(echo ${gif##*/} | cut -d\_ -f1)
#echo -e "\n$index"
# Get the delay of the current image
delay=$(echo ${gif##*/} | cut -d\_ -f2| sed "s,.gif,,")
# echo -e "\n$delay"
# add correct delay options to current gif, append to existing command
_CONVERT="${_CONVERT} -delay $delay $gif "
done;
# add the outpt of where you're going to put your gif
_CONVERT="${_CONVERT} -loop 0 -layers Optimize /root/so/stackoverflow.gif"
# show full command
echo "Convert cmd: $_CONVERT"
# run it, then go get your image
eval $_CONVERT
Example of the command that gets generated:
Convert cmd: convert -delay 1432 /root/so/00001_1432.gif -delay 1552 /root/so/00002_1552.gif -delay 1432 /root/so/00003_1432.gif -delay 1444 /root/so/00004_1444.gif -delay 1432 /root/so/00005_1432.gif -delay 1432 /root/so/00006_1432.gif -delay 1432 /root/so/00007_1432.gif -layers Optimize /root/so/stackoverflow.gif
Hope this is what you're looking for.
What are the parameters that I should pass? The Ghostscript version I'm using is 8.71.
https://gitlab.mister-muffin.de/josch/img2pdf
As mentioned by PleaseStand, GhostScript (edit: prior to v9.23) will decode the JPEG data, resulting in generation loss, as well as performance "ten to hundred" times worse than img2pdf.
Edit: Ghostscript 9.23 (2018-03-21) added a "JPEG Passthrough" capability that resolves the generation-loss/performance issue.
ImageMagick (i.e. convert) also decodes and re-encodes the images.
gs \
-dNOSAFER \
-sDEVICE=pdfwrite \
-o foo.pdf \
/usr/local/share/ghostscript/8.71/lib/viewjpeg.ps \
-c \(my.jpg\) viewJPEG
reads my.jpg and produces foo.pdf. You will have to find where your installation installed the PostScript program viewjpeg.ps.
I've been using the same basic command line Henry gave in his answer for quite some time now in a simple Bash script, with a few tweaks.
My full script converts multiple JPEG images to a multipage PDF, using this modified command:
gs \
-sDEVICE=pdfwrite \
-o foo.pdf \
/usr/local/share/ghostscript/9.02/lib/viewjpeg.ps \
-c "(1st.jpg) viewJPEG showpage \
(2nd.jpg) viewJPEG showpage \
(3rd.jpg) viewJPEG showpage \
(last.jpg) viewJPEG showpage"
It is called like this:
jpegs2pdf.sh output.pdf file1.jpeg [file2.jpeg [file2.jpeg [...]]]
The problem is that this command would use the same (default) page size of Ghostscript (usually Letter or A4 in portrait mode), and each JPEG image will be scaled to fit this pagewidth and/or pageheight, being placed on the lower left corner.
My script makes each PDF page use the same page dimensions as the original JPEG for the page. For auto-discovery of the JPEG's dimensions, I use ImageMagick's identify command:
identify -format "%[fx:(w)] %[fx:(h)]" some.jpeg
Here is the code of the full script:
#!/bin/bash
#
#############################################################################
#
# Shellscript to convert a set of JPEG files to a multipage PDF.
#
# Requirements: (1) Ghostscript needs to be installed on the local system.
# (2) ImageMagick needs to be installed on the local system.
#
# Usage: jpegs2pdf.sh output.pdf file1.jpeg [file2.jpeg [file2.jpeg [...]]]
#
# Copyright (c) 2007, <pipitas#gmail.com>
# Use, distribute and modify without any restrictions.
#
# Versions:
# v1.0.0, Jul 12 2007: initial version
# v1.0.1, Jan 07 2011: set viewJPEG.ps path (self-compiled GS 9.02)
#
#############################################################################
outfile=$1
shift
param=""
for i in "$#" ; do
dimension=$(identify -format "%[fx:(w)] %[fx:(h)]" "${i}")
param="${param} <</PageSize [${dimension}]>> setpagedevice (${i}) viewJPEG showpage"
done
gs \
-dNOSAFER \
-sDEVICE=pdfwrite \
-dPDFSETTINGS=/prepress \
-o "$outfile" \
/usr/local/share/ghostscript/9.02/lib/viewjpeg.ps \
-c "${param}"
alternatively on some linux distros convert pic1.jpg pic2.jpg out.pdf does the job with mixed results
I have Ghostscript version 9.10, so the command with the below line DIDN'T WORKED FOR ME
/usr/local/share/ghostscript/9.02/lib/viewjpeg.ps
so I modifid the command and edited the line and insted used this, IT WORKED FOR ME
viewjpeg.ps
So the NEW MODIFIED COMMAND IS below:
gs \
-sDEVICE=pdfwrite \
-o foo.pdf \
viewjpeg.ps \
-c "(1st.jpg) viewJPEG showpage \
(2nd.jpg) viewJPEG showpage \
(3rd.jpg) viewJPEG showpage \
(last.jpg) viewJPEG showpage"
GhostScript is a PostScript interpreter, so it does not directly support a JPEG input, only a JPEG output. That said, it does support JPEG decompression (except for progressive JPEG).
There's a PostScript program and accompanying shell script that you can use to take advantage of this called jpeg2eps. To get a PDF, most systems have the script pstopdf available for use, which runs each of the input files (you would use the output of the jpeg2eps script) through GhostScript.