ImageMagick: composite 4 edges from one image into another, side-by-side - perl

I'm using Perl 5.16 with ImageMagick 6.8 (probably old by now, but it works :). I'm trying to extract all 4 edge regions from one image and composite them into another image, side-by-side, oriented vertically.
I can extract edges and rotate them, but I can't get the offset in the target image right. The edges end up on top of each other. I tried x=>$marg, translate=>"$marg,0", geometry with an offset: no dice. Variables: $marg = the edge width, $im = source, $im2 = target, $ext = extracted region
# left edge
$ext=sprintf("%dx%d+%d+%d",$marg,$h,0,0);
$res=$im2->Composite(image=>$im,compose=>Over,extract=>$ext);
# top edge
$ext=sprintf("%dx%d+%d+%d",$w,$marg,0,0);
$geo=sprintf("%dx%d+%d+%d",$marg,$h,0,0);
$res=$im2->Composite(image=>$im,compose=>Over,extract=>$ext,rotate=>90,translate=>"$marg,0");

I haven't used the PerlMagick bindings for years, but I imagine you would want to create each of your 4 edge strips and then use +append to lay them out horizontally, side-by-side. Here's a crude example, just in Terminal:
magick -size 20x50 xc:red xc:lime xc:blue +append result.png
More specifically addressing your question, and starting with this image:
that would look like this:
#!/bin/bash
magick ~/sample/images/blocks-RGB.png -resize 100x100 +repage -write MPR:orig +delete \
\( MPR:orig -gravity northwest -crop 30x+0+0 \) \
\( MPR:orig -gravity northwest -crop x30+0+0 -rotate 90 \) \
\( MPR:orig -gravity southwest -crop x30+0+0 -rotate 90 \) \
\( MPR:orig -gravity northeast -crop 30x+0+0 \) \
+append result.png
Hopefully you can see the parallels with PerlMagick. The first line creates a copy of the image to work with, the second line crops the left edge, the third line crops the top edge, the fourth line crops the bottom edge, the fifth line crops the right edge and the last line appends the four cropped pieces side-by-side.

Related

Most efficient way making an image with imagemagick

Absolut beginner here.
I got the task to write a workflow to run on a server for a web-platform that uses RoR. Server is linux based.
I want to create an image. Basically, it's a background picture, already on the server, with two green squares, one in the down left and one in the right down corner. Inside the green squares is white text from two input fields on the website (left input text and right input text).
The user uploads a logo of their sports team to be resized and fitted into the upper-right corner.
I would basically do it like:
convert -background none -fill white -font Helvetica -pointsize 100 -size 450x -gravity center caption:“text right input“ right.png
convert -background none -fill white -font Helvetica -pointsize 100 -size 450x -gravity center caption:“text left input“ left.png
composite -gravity Center left.png base.png left_done.png
composite -gravity Center right.png base.png right_done.png
composite -gravity southeast right_done.png background.png bg_right.png
composite -gravity southwest left_done.png bg_right.png bg_left_right.png
convert Logo-upload.jpg -resize 400x230 logo_resized.png
composite -gravity NorthEast logo_resized.png bg_left_right.png done.png
This is step by step command line, how I would do it.
But there must be a more efficient way, isn't it?
I would love to here your comments. Just started out with very basic tasks programming very elementary things. Would love to learn more.
//Edit: The workflow may seem weird, but it was the easiest for me to get it pixel perfect on the background.png (1000x500px)
You can do that in one command line in ImageMagick, if you use parentheses processing. Here is an example using ImageMagick 6 in Unix syntax. See https://legacy.imagemagick.org/Usage/basics/#parenthesis
Input:
Logo:
convert IMG0005.jpg \
\( -size 450x -background green1 -fill white -font Helvetica -pointsize 100 -gravity center caption:"text right input" \) \
-gravity southeast -compose over -composite \
\( -size 450x -background green1 -fill white -font Helvetica -pointsize 100 -gravity center caption:"text left input" \) \
-gravity southwest -compose over -composite \
\( olympic-logo.gif -resize 400x230 \) \
-gravity northeast -compose over -composite \
IMG0005_composite.jpg
Result:
If on Windows, remove the back-slashes from the parentheses and change the end of line back-slash to ^.
If on ImageMagick 7, change "convert" to "magick"

Add watermark after tile in ImageMagick

I got this working code for tiling an image in ImageMagick:
convert D:\tile.jpg -resize 300x300 -write mpr:tiler +delete ^
-size 900x900 tile:mpr:tiler -sharpen 0x2 D:\tiles.jpg
But now i found out that i need to add watermark in the same process. I got this working code for that:
tiles.jpg Wartermark.png -gravity southeast -geometry +0+0 -composite D:\tile-watermark.jpg
But how do i process those two in one line?

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

Imagemagick to merge and mask images

I recently started working with Imagemagick and I had a problem that needs to be solved.
I have such a thumbnail.
And there is such a mask.
I need to get this image on the output.
I looked through this link http://www.imagemagick.org/Usage/thumbnails/ I tried everything there, but I did not get success ((
I hope you will help me.
This should give you a result very much like your example...
convert mask.png image.png -gravity north -composite \
mask.png -compose copyopacity -composite result.png
You can adjust the positioning of the overlay by including something like "-geometry -10+0" before the first composite.
To use this command in Windows you'll need to change that continued line backslash "\" to a caret "^".
In Imagemagick, you should extract the alpha channel of your mask and put that into the alpha channel of your other image. So try
(unix syntax)
convert KlQZ6.png \( 7k9a9.png -alpha extract \) -alpha off -compose copy_opacity -composite result.png
(windows syntax)
convert KlQZ6.png ( 7k9a9.png -alpha extract ) -alpha off -compose copy_opacity -composite result.png

Imagemagick command line, combine two different sized images

I'd like to use "convert" (or whatever) from Imagemagick to combine two different sized images. I'd like them to be aligned at the bottom left corners. For example, I have two images:
trans_alpha.png (a transparent 42x37 blank image)
and shadow.png (a 68x23 image, which I want overlaid on trans_alpha.png aligned at the bottom left)
The result I'd like would be a 68x37 image, NOTE these sizes are examples only, I don't want to put the size into the command line, I just want to use the sizes from the input images.
I have tried a lot of combinations without success:
Attempt no. 776 (close, but aligned to top left, not bottom left)..:
convert trans_alpha.png -background none shadow.png -gravity SouthWest -layers merge +repage result.png
Attempt no. 841 (aligned correctly, but result image isn't wide enough)...
convert trans_alpha.png shadow.png -gravity SouthWest -composite result.png
Hopefully that makes sense.
Thanks,
Paul
In answer to my own question (courtesy of the clever people on www.imagemagick.org)
convert \
trans_alpha.png shadow.png \
-flip \
-background none \
-mosaic \
-flip \
result.png
Imagemagick includes many useful transformations, but occasionally still it lacks the one you need. Since your original images are PNG lossless bitmaps, you can convert both to long-form PBM or a related format like long-form PPM. The advantage of these forms is that they represent the entire image, pixel by pixel, in plain text, which one can write a program -- usually a fairly short program -- to process any way one likes. As storage formats, PBM and PPM are egregiously inefficient, but they are likewise egregiously easy to manipulate, and that's what you want.
The pbm(5) manpage (available for example on Debian/Ubuntu systems in the netpbm package) is well written and explains the process clearly.
I am unable to test at the moment but you can use -page with layers so something like this might work but you may need to calculate the Y offset:
convert \
trans_alpha.png \
-background none \
shadow.png \
-page +0+10 \
-layers merge \
+repage \
result.png
You may not need the -background none