Proper syntax for STDIN/STDOUT in imagemagick - powershell

I downloaded ImageMagick so I could batch process folders of images at work, cropping them to size and then slicing them into 12 equal pieces. I can do each task individually, but I'd rather execute it all in one line using STDIN and STDOUT. However, even after looking through answers here and the documentation on the website, I'm not any closer to making it work.
I'm working in Windows Powershell. Here's what I've tried, working with a single image:
convert -crop '5072x3552+87+0' image.jpg jpg:- | convert -crop '1268x1184' - jpg: - | convert -crop '1268x1030+0+0' - C:\folder1\folder2\folder3\square.jpg
This gives me a series of errors:
convert.exe: no decode delegate for this image format `' #
error/constitute.c/ReadImage/508.
convert.exe: no images defined `jpg:-' #
error/convert.c/ConvertImageCommand/3253.
convert.exe: no decode delegate for this image format `' #
error/constitute.c/ReadImage/508.
convert.exe: no images defined
`C:\users\lmcane\desktop\imagem\test\leaf.jpg' #
error/convert.c/ConvertImageCommand/3253
I'm using ImageMagick 7.0.2 on Windows 7. Windows PowerShell is opened as administrator.
Additional guidance on formatting STDIN and STDOUT in imagemagick would be welcome.
Any help appreciated.
image for reference
process for single original image

I would try doing the first trim of the edges using -fuzz (to allow for small differences in the border colour) and -trim. That gets you this:
convert grid.png -fuzz 30% -trim trimmed.png
Then, I would tile to 4x3 and repage the images so they forget their positions in the original image:
convert trimmed.png -crop 4x3# +repage step2.png
Now crop off the tops, bottoms and sides and save the individual 12 frames:
convert step2.png -crop 130x100+20+20 f-%02d.png
Now you can trim the excess, using a slightly different fuzz as there seems to be less variation here than in the outer edge of the original image. And, I have also put all the commands together in one that does all the steps for all 12 images in one go:
convert grid.png -fuzz 30% -trim -crop 4x3# +repage -crop 130x100+20+20 -fuzz 5% -trim f-%02d.png
You may have to play with the fuzz factor for other images, but you should see how it works now.

I can't explain why convert throws these errors, but I was able to get it to work by using xwd as the transport format:
convert -crop '5072x3552+87+0' image.jpg xwd:- |
convert -crop '1268x1184' xwd:- xwd:- |
convert -crop '1268x1030+0+0' xwd:- C:\folder1\folder2\folder3\square.jpg

Related

How can I merge a signature and my module with an ImageMagick command?

I have this starting situation.
I have a jpg picture (A) with a module in which the signature slot is always in the same place.
I have also a signature (B) jpg picture, separated.
I use a program that allows external calls, but one single line only.
Is there an ImageMagick single command line command that allows me to do
Put Image (B) into image (A) at a specific x,y,height and width
Consider WHITE #FFFFFF as the alpha channel for image (B)
?
I am looking since a while now but haven't figured anything out.
Thanks
In ImageMagick, you would first make white transparent and then overlay B onto A. You need to use parentheses processing to keep the processes separate but in the same command line.
Unix syntax for ImageMagick 6:
convert imageA \( imageB -transparent white \) -geometry WxH+X+Y -compose over -composite result
or possibly
convert imageA \( imageB -transparent white -resize WxH \) -geometry +X+Y -compose over -composite result
Best if you provide your input images for demonstration.
See
https://legacy.imagemagick.org/Usage/basics/#parenthesis
https://legacy.imagemagick.org/Usage/compose/#compose
https://legacy.imagemagick.org/Usage/windows/

Resize image and create 3x3 tiles with ImageMagick

I managed to make tiles with ImageMagick like this:
-size 900x900 tile:D:\tile.jpg D:\tiles.jpg
But i want to resize the image before the tiling (300*300px) - and then maybe afterwards apply a sharpen, but the most important is the resizing.
How do i do that in one command line?
Work from a simple command like this...
convert D:\tile.jpg -resize 300x300 -write mpr:tiler +delete ^
-size 900x900 tile:mpr:tiler -sharpen 0x2 D:\tiles.jpg
That starts by reading in your "tile.jpg" image and resizes it to 300x300. Then it writes that resized image to an ImageMagick built-in memory register named "mpr:tiler" and deletes it from the current list. (You can name it "mpr:almost_anything".)
Next the command sets a canvas size of 900x900 and creates a tiled canvas filled with that "mpr:tiler" image.
You can add sharpening and other operations after reading in the input image and before writing it to the memory register, or after creating the tiled image and before writing it to an output file.
The command above is in Windows syntax. To run it in *nix change that continued-line caret "^" to a backslash "\". If you're using ImageMagick v7 replace "convert" with "magick".

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

JPEG to PNG conversion with 300 DPI

Unable to convert a JPEG image into a 300 DPI PNG image using ImageMagick.
After conversion the PNG image is 72 DPI only. I'm using ImageMagick 6.9.0-0 Q16 x86 and Ghostscript v9.15.
Below is the line I use in my Perl script:
system("\"$imagemagick\" -set units PixelsPerInch -density 300 \"$jpg\" \"$png\"");
Adjusting the units & density will not alter the underlining image data, but updates meta info for rendering libraries. Important for vector to raster, but not very useful for raster to raster. To adjust the DPI of an image, use the -resample operation.
convert source.jpg -resample 300 out.png
You verify the DPI resolution with the following...
identify -format "%[resolution.x] %[resolution.y]\n" out.png
I'm wondering where the 72dpi is coming from. Assuming you are using X and some kind of Unix, ImageMagick defaults to using the screen resolution (72 dpi). I'm not sure what it does under OSX/XQuartz but it's likely similar. Is your screen resolution set to 72dpi (!?).
I'm with #emcconville #ikegami - just do this straight from ImageMagick on the commandline - passing the right options to be sure.
There are image manipulation modules that you can use from perl without having to resort to system commands as well such as Imager::Transformations, Image::Magick, and GD. Here's how to convert with GD.
perl -MGD -E 'my $imgjpg = GD::Image->newFromJpeg("img.jpg");
open my $imgpng, ">", "img.png" or die; print $imgpng $imgjpg->png();'
With most image manipulation packages the original resolution show be maintained during conversion - though some (including GD) will default to lower color depths (8 bit) unless passed a Truecolor flag.
e.g. GD::Image->newFromJpeg("img.jpg", 1);

Tesseract and tiff format - spp not in set {1,3}

While trying to run this command:
tesseract bond111.tif bond111 batch.nochop makebox
I get the next error
Error in pixReadFromTiffStream: spp not in set {1,3}
Error in pixReadStreamTiff: pix not read
Error in pixReadTiff: pix not read
Assuming that spp not in set is the main error here, what does it mean?
At first it had trouble because the bpp was higher than 24 so I reduced it using Gimp but that did not resolve the issue.
It probably means your TIFF image has an alpha channel and therefore the underlying Leptonica library used by Tesseract doesn't support it. If you're using Imagemagick then be aware that operations such as -draw can cause alpha channels to be added. If you're using convert in your workflow and want to remove the channel again immediately, flatten the image before writing by adding -background white -flatten +matte before the output filename, e.g.:
convert input.tiff -fill white -draw 'rectangle 10,10 20,20' -background white -flatten +matte output.tiff
Tesseract (well, Leptonica) accepts PNGs these days and is less picky about them, so it might be easier to migrate your workflow to PNG anyway.
Sources: magick-users mailing list posting; tesseract-ocr mailing list posting
Thanks for your post ZakW, you pointed me to the right direction.
Anyhow i also needed to set '-depth 8'. Quality was not good enough for OCR, whatever I tried.
What worked for me is this solution:
ghostscript -o document.tiff -sDEVICE=tiffgray -r720x720 -g6120x7920 -sCompression=lzw document.pdf
tesseract document.tiff document -l deu
vim document.txt
This way I got perfect text with Umlauts in german.
Adjusting the conversion to the following line did help me.
convert -density 300 input.pdf -depth 8 -background white -alpha Off output.tiff
Note that the other answers did not work for me since they use the deprecated +matte flag instead of -alpha Off.
You can try using the command 'tiffinfo' provided by libtiff_tools to verify the TIFF format of your src image. A number of TIFF formats exist, with different values for Bits-per-pixel (bpp) and Samples-per-pixel (spp).
Error in pixReadFromTiffStream: spp not in set {1,3,4}
An 'spp' value of 2 is invalid for TIFF.
I solved the problem by saving directly to TIFF format from Gimp, instead of converting from .png to .tif using ImageMagick's 'convert'.
See also: TIFF format