How to crop section of canvas from Ghostscript printing result to PNG - png

I'm printing barcode using the Barcode Writer in Pure PostScript library.
I figured out everything but the result size of the canvas. I'm calling Gostscript with this command
-dSAFER -dBATCH -dNOPAUSE -r350 -sDEVICE=pnggray -dTextAlphaBits=4 -sOutputFile=test.png barcode_with_sample.ps
Inside of the barcode_with_sample.ps I call
20 755 moveto (2001010042569) (includetext) /ean13 /uk.co.terryburton.bwipp findresource exec
showpage
Everything is exactly as I want it but the resulted file is 2975x3850. I need just 600x220 from the top of left corner.
Even generating the output is pretty resource intensive, because it's so huge file.
Any idea how to get only the exact part of the canvas and not the whole page?
Thank you

You can set the page size with -dDEVICEWIDTHPOINTS & -dDEVICEHEIGHTPOINTS (there are 72 points to an inch), but you'll need to change the 20 755 moveto to something like 20 10 moveto. The 755 equals about 10.5 inches, so when you shrink the page 0.629" high (45.26 points/220 pixels) the 755 will be 10" inches off the page. Making the 20 10 moveto to 20 5 moveto will move it down a bit and 20 15 moveto would move it up a bit.
gswin32c -dDEVICEWIDTHPOINTS=123.43 -dDEVICEHEIGHTPOINTS=45.26 -dSAFER -dBATCH -dNOPAUSE -r350 -sDEVICE=pnggray -dTextAlphaBits=4 -sOutputFile=test.png trash.ps

Related

libvips - generate tiles starting from specific zoom level and specific coordinates

I am using windows cli version libvips. I want to generate map tiles for leaflet from image 8000px x 6000px. This image is old map of my town, and I want to display it on my website, but I am stuck on generating tiles.
How to tell libvips to generate tiles from zoom level 10 to 15. With command
dzsave input.jpg outputdir --layout google
I receive tiles from zoom level 0 to 5.
And second question.
How to set bounds of my map? Generated tiles from above command cover the whole world.
The libvips CLI lets you run any save operation (like jpegsave, tiffsave or dzsave) as part of the write step of a command. You select the saver with the filename suffix and you can pass any parameters in square brackets at the end of the filename (be careful not to use any spaces).
So these two commands do the same thing:
vips jpegsave x.jpg y.jpg --Q 90
vips copy x.jpg x.jpg[Q=90]
The copy command will run jpegsave for you (it sees the .jpg suffix) and set Q to 90.
You can select dzsave with the .dz suffix. If your image is 50,000 x 50,000 pixels, you can save just the centre 50% with:
vips crop my-huge-map.jpg x.dz[layout=google] 12500 12500 25000 25000
I'm not sure what you mean by "layers 10 to 15". Do you only want the low-res layers? Just do a shrink by eg. 16 before running dzsave.

Dimensions change when Ghostscript converts PS to PNG

I use the following minimal PostScript file:
%!PS-Adobe-2.0
%%BoundingBox: 0 0 100 100
0 0 moveto 100 100 rlineto stroke
showpage
This draws a line from (0,0) to (100,100) in a 100x100 box.
I then convert this file minimal.ps to a PNG with this command line, borrowed from GhostScript's documentation:
gs -sDEVICE=pngmono -o minimal.png minimal.ps
With GPL Ghostscript 9.53.3 (current Debian stable) and 9.27 (oldstable) the resulting PNG file has the following dimensions:
> identify minimal.png
minimal.png PNG 612x792 612x792+0+0 8-bit Gray 2c 2994B 0.000u 0:00.000
Both width and height extend far beyond the original BoundingBox, and they are not even equal.
The PNG's dimensions are the same if the output device is pnggray, pngalpha, etc.
The dimensions are also the same if, in the PostScript code, 100 is replaced by 10 or by 10000.
How can I tell GhostScript to create a PNG file whose dimensions automatically fit the PostScript file's BoundingBox?

Imagemagick commands to resize, rotate, wrap, and combine images

I'm currently using Photoshop to resize, rotate randomly, and wrap images randomly to create this type of montage....
Comic Covers
I got to thinking that kind of thing should be doable in Imagemagick. I know how to use all of the commands separately, and I can do random rotations and wraps using BASH, but getting a single image out of individual images is eluding me.
Assume that the source pictures are different sizes but should be resized to 250px wide. The images will be named image1.jpg, image2.jpg, etc. Also assume that the destination should be 1000x1000px. Depending on how many pictures I have, the whole 1000x1000 image may not be covered - I understand this. I mainly use BASH, but I have several different environments and shells available to me.
Using ImageMagick 6 or 7, if you have enough memory to read in all your images at once you can resize them, randomly rotate them, and place them all in random locations on a 1000x1000 canvas with a command like this...
convert granite: -duplicate 11 -resize 250x \
-background none -gravity center -extent 1000x1000 \
-distort SRT "%[fx:rand()*45-22.5]" -virtual-pixel tile \
-distort affine "%[fx:w/2],%[fx:h/2] %[fx:rand()*w],%[fx:rand()*h]" \
-flatten result.png
That uses the ImageMagick built-in image "granite:" duplicated 11 more times. Replace "granite: -duplicate 11" with a list of your input files.
It starts by resizing them all to 250 pixels wide, then placing them each in the center of a 1000x1000 transparent canvas.
The real work is done in the distort operations. First "-distort SRT" rotates each image a random amount between -22.5 and +22.5 degrees. Then the "-distort affine" relocates each image to a random location within the canvas. Any part of an image going beyond the canvas will be rolled back into the opposite side. That makes the result suitable for tiling.
This command flattens everything onto a transparent background wherever it might show between the images. Add "-background blue" just before the "-flatten" operation to change the background to blue, for example.
This works on my IM 6 in bash. For IM 6 in Windows change the continued line backslashes "\" to carets "^". For IM version 7 change "convert" to "magick".
Here is a bash Imagemagick 6 script that takes a list of images. You can replace it with your images. It uses subshell processing to avoid needing to write temporary images to disk. It saves the images in a miff: format as one file from the loop. Then it pipes the multipage miff: file to -layers merge, which overlays the images onto the 1000x1000 transparent base image. For Imagemagick 7, replace convert with magick.
list="lena.jpg barn.jpg mandril3.jpg zelda1.jpg"
convert -size 1000x1000 xc:none result.png
(
for img in $list; do
angle=`convert xc: -format "%[fx:round(-22.5+45*(rand()))]" info:`
xoff=`convert xc: -format "%[fx:round(1000*rand())]" info:`
yoff=`convert xc: -format "%[fx:round(1000*rand())]" info:`
#echo >&2 "angle=$angle; xoff=$xoff; yoff=$yoff"
convert "$img" -resize 250x -background none -rotate $angle -set page +${xoff}+${yoff} miff:-
done
) | convert result.png - -layers merge +repage result.png
If you have enough resources to hold all the images at once, then you can also do it in one command line as follows:
convert -size 1000x1000 xc:none \
\( lena.jpg barn.jpg mandril3.jpg zelda1.jpg -virtual-pixel none -background none \
+distort SRT "0,0 %[fx:250/w] %[fx:-22.5+45*rand()] %[fx:rand()*1000],%[fx:rand()*1000]" \) \
-layers merge +repage result.png
Cool, I'll try fmw42's script, but this is a script I came up with. It generates temporary files (which it deletes) and several convert commands, but it does work....
# Create blank montage...
convert -size 750x750 xc:black montage.jpg
for file in $(ls hall*.jpg | grep -v halloweencovers.jpg); do
echo $file
angle=$RANDOM; let "angle %= 32"; let "angle = angle - 16"; let "angle = angle * 5"
offsetx=$RANDOM; let "offsetx %= 75";let "offsetx = offsetx * 10"; offsetx="+$offsetx"
offsety=$RANDOM; let "offsety %= 75";let "offsety = offsety * 10"; offsety="+$offsety"
# Create blank image...
convert -size 750x750 xc:transparent blank.png
# create 250px image and rotate....
convert $file -resize 250x -alpha set -background none -rotate $angle out.png
# add 250px image to blank 750x750 canvas
convert blank.png out.png -composite output.png
# offset and wrap blank canvas with output image
convert output.png -roll ${offsetx}${offsety} output2.png
# merge montage with offset image
convert montage.jpg output2.png -composite montage.jpg
# clean up
rm -f out.png output.png output2.png blank.png
done

PDF to PNG using Ghost Script - crop to top third of page

I am trying to convert a PDF file to an image, and in the process crop to the first third(approx) of top of the first page.
This command gives me the whole page and changing the -g option crops toward the bottom left corner if I make the values smaller.
for %%x in (*) do "......\program\gs\gs9.23\bin\gswin32c.exe" -g2500x3300 -dFIXEDMEDIA -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 -sDEVICE=pngalpha -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -r300x300 -dBATCH -dNOPAUSE -dFirstPage=1 -dLastPage=1 -SOutputFile="%%~nx.png" "%%~nx.pdf"
I want the smaller image so that OCR on the image is then faster, and most letters/docs I am dealing with have the information I am after in the top third.
The origin (0, 0) of the PostScript page (and the PDF page) is at the lower left. So by reducing the media size you make the uppermost portion of the content lie off the media and therefore its not rendered.
So what you need to do is reduce the size of the media (which you have done) **and* translate the origin so that the top of the content lies on the media.
Try adding -c "<< /BeginPage {-300 0 translate} >> setpagedevice" -f before the input PDF file. That should translate the origin to be 1 inch below the bottom of the media at 300 dpi which should make 1 inch more of the top of the page, and 1 inch less of the bottom of the page render.
Obviously since I don't know how large your content is, I can't give you an exact answer.

Batch process images using OS X SIPS (scriptable image processing system) to downsize images only?

I'd like to batch process several folders of 1000's of images to downsize any images with a long side greater than 1440 pixels down to 1440 while ignoring any files that are already smaller than that.
I was looking at sips and can't tell if it skips upsizing by default or if there is a way to filter it using getProperty perhaps? (I'm not the best at deciphering CLI options from man pages).
I was thinking maybe I could use a find or sips query first and then pipe it into another sips to resize, I'm not sure exactly how though and don't think find can search by image size.
(also open to something other than sips to handle this, just seemed the quickest way)
Using spotlight to filter results to to images larger than a particular size works perfectly:
mdfind -0 -onlyin . "kMDItemPixelHeight > 1440 || kMDItemPixelWidth > 1440" | xargs -0 sips -Z 1440
This find images recursively from the current directory with width OR height greater than 1440 pixels and resizes them down to 1440. Files under 1440 get left alone.