I have switch from Imagick version 5 to Imagick version 6 and noticed the following
While using the command:
convert -gravity SouthEast -draw 'image Over 0,0 0,0 overlay.png'
In version 5 the overlay.png is being added the bottom right corner (SouthEast) as expected!
But version 6 of ImageMagick failed and the position of the overlay.png is at the top left corner!
The command is used in typo3 "imgResource.params" http://docs.typo3.org/typo3cms/TyposcriptReference/Functions/Imgresource/Index.html
But I think this has nothing to do with the CMS, but with compatibility of im5 and im6
Anyone knows how to solve this...?
You can use this command instead:
convert background.jpg foreground.jpg -gravity SouthEast -compose Src_Over -composite output.jpg
So if this is our background:
and this is our foreground:
we get the following result:
Actually, I think he looks better on the other side of the image, but flopped to still face inwards :-)
convert background.jpg \( tiger.png -flop \) -gravity SouthWest -compose Src_Over -composite out.jpg
Updated Answer
Sorry to hear that the command doesn't work inside typo3. There is another version here that may work for you...
First get the width and height of the background and foreground images - I guess there is a way to do this in typo3, but I'll do it like this:
identify -format "%w %h" background.jpg
906 603
So the background is 906 px wide and 603 px high, and
identify -format "%w %h" tiger.png
258 296
the tiger is 258 px by 296. Then we can overlay using geometry like this, by subtracting the width and height of tiger from the width and height of the background to give an offset from top left of image:
convert background.jpg tiger.png -geometry +648+307 -composite out.png
which gives the same effect as gravity southeast. Maybe that will get you there...
Updated One Last Time
This one must get you there... just put the correct offsets in your original draw command rather than relying on gravity. So the first two numbers are the x,y offsets of the top left corner of the overlaid image from the top left corner of the background image, and the second x,y pair are the offsets of the bottom right corner of the overlaid image. So basically,
x1,y1 = width background - width overlay, height background - height overlay
x2,y2 = width background, height background
convert background.jpg -draw 'image Over 648,307 906,603 tiger.png' out.jpg
Related
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
I want to add a pattern repeated image as the background of another image that has spaces around. For example i have the pattern 200x200 and an image 1200x800. I have accomplished to add a background color.
The command i'm using to add a background color
convert -background "#333" -resize 768x450 -gravity Center -extent 768x450
Now i need to add a pattern instead of that color. Some suggest that i should make the pattern as one image with the maximum size then use it to add it as background image.
Is it possible to do it with convert or any other command using ImageMagick ?
Not sure what you mean, but I am guessing it's this. Let's make a 200x200 tile to start off with:
convert -size 200x200 radial-gradient:red-blue t200x200.png
And now you want to make a 1200x800 image by tiling that basic unit:
convert -size 1200x800 tile:t200x200.png BigBoy.png
If you now want to overlay a fine-art, high-quality, centred portrait over the top of your harmonious, subtle background, you can do this:
convert -size 1200x800 tile:t200x200.png -gravity center smiley.gif -composite BigBoy.png
Please look at the attached image. It is a GPR profile and using image processing techniques, I am trying to divide this image into 3 zones by labeling with colors the whole image on the top:
when parabolas in the image are very clear and distinct with high pixel values - green zone/ line at the top
when parabolas in the image are blurred but visible - yellow zone
when parabolas are distorted or when not parabolas are present - red zone
What techniques should I use? What's the best approach to solve it?
I have tried various techniques but not with success in every case, because, as you can in the following image, sometimes the parabolas are too close to one another and identifying them is becoming an issue.
A sample of how I want to zone it: https://www.dropbox.com/s/9zm9epgf0gt7591/sample.png?dl=0
One of the tried code: simplest one.
clear all
clc
%read png image
H=imread ('origpng.png');
%convert to gray scale
I = rgb2gray(H);
I(I>150)=0;I(I<100)=0;
figure,imshow(I)
J=I;
J=255-J;
figure, imshow (J)
J(J<255)=0;
figure,imshow (J)
Your question is not very clearly posed, but I spent some time on it and felt like sharing my thoughts. I am not preteding for an instant that this is anywhere near a complete, or rigorous answer - just some musings that might give you some ideas. Also, I use ImageMagick, but if you have and know Matlab, you should use that - I am not suggesting you switch tools.
First, I did a Canny Edge detection like this:
convert http://i.stack.imgur.com/XITAE.png -canny 0x1+15%+50% canny.jpg
that gives me this:
I then "squash" that down till it is just 1 pixel high, which effectively totals up and averages all the columns - I make it 10 pixels high here so you can see it. Where it is white, there are lots of parabolas, elsewhere there are fewer.
Then I stretch that back up to the full height of the original image and blur it a bit - note that everything up to the following image is just one line of "code":
convert http://i.stack.imgur.com/XITAE.png -canny 0x1+15%+50% -resize x1! -normalize -resize 827x310! -blur 0x11 -colorspace gray mask.png
I then use the above as an opacity mask for a red image the same size as your original like this:
convert -size 827x310! xc:red mask.png -compose copy-opacity -composite colouredmask.png
Then I took your original image and coloured it with yellow like this by first creating a yellow image and then blending it onto your image and then I blended the red image from above on top of that:
convert -size 827x310! xc:yellow yellow.png
convert http://i.stack.imgur.com/XITAE.png yellow.png -compose colorize -composite colouredmask.png -compose overlay -composite result.png
giving
Obviously you can set different parameters and use different thresholds and things, but it kind of heads towards the sort of thing you are aiming it.
So the entire process is:
# Make mask of peaky areas - line 1
convert http://i.stack.imgur.com/XITAE.png -canny 0x1+15%+50% -resize x1! -normalize -resize 827x310! -blur 0x11 -colorspace gray mask.png
# Colour mask with red - line 2
convert -size 827x310! xc:red mask.png -compose copy-opacity -composite colouredmask.png
# Tint original image with yellow and then overlay semi-transparent red area
convert -size 827x310! xc:yellow yellow.png
convert http://i.stack.imgur.com/XITAE.png yellow.png -compose colorize -composite colouredmask.png -compose overlay -composite result.png
Notes
Squashing pixels... sorry for confusing you with my terminology! Basically, when I squash the pixels down to a single row, you need to imagine dropping a brick on the top of the image and flattening it down to just one pixel tall. So, essentially, you draw an imaginary line underneath the image and then you work across the image totalling up the number of WHITE (i.e. edge) pixels in each vertical column. Columns that have more white pixels will add up to larger numbers. Columns that have no white pixels will add up to zero. Once you have got the totals for each column, you find the highest total - let's say it is 32 and then you multiply all totals by 255/32 so that everything is normalized to 255, or white. Now the squashed strip represents the edge energy in each column. And I then use that as the opacity for the red when I overlay - so columns with more white edges in the Canny image will show up with more red in the result.
Let's demo what happens if I squash down to 10 pixels wide and 1 pixel high before scaling back up to the original size - basically it means that my resulting mask will have only 10 possible values (or columns) columns and that each column will be a single constant brightness. I'll put the Canny image underneath so you can see that the brightness of the squashed strip represents the edge energy:
convert http://i.stack.imgur.com/XITAE.png -canny 0x1+15%+50% -resize 10x1! -normalize -scale 827x310! mask.png
If you want to introduce another colour, you need to work out what your algorithm is for controlling where that colour should appear. You then do exactly the same thing again - you make a mask that is light where you want that colour in your output image and dark where you don't want that colour. Then you use that mask as the opacity for your new colour (as I did at the line labelled line 2 above) and then you overlay it like I did in the last line of my code above.
I have an image that is 200x200 I want to trim the white space, and make it into an icon that is 32x32.
convert img.png -trim -resize 32x32 imgi.png
This line of code does not work, it will not make the canvas a uniform 32x32. I have tried taking it and adding -canvas 32x32 or -extend 32x32 but then the script does not work at all.
I am doing this from PHP with exec so I do not get an error back.
You can pad to tweak dimensions of the image after cropping. As of ImageMagick version 6.3.2 you can use -extent option to modify end result.
convert img.png -trim -resize 32x32 -gravity center -extent 32x32 imgi.png
For earlier versions it is necessary to play with -border, -crop and +repage.
convert img.png -trim -resize 32x32 -bordercolor white -border 16 -gravity center -crop 32x32+0+0 +repage img.png;
I need to create images that are within a 480w x 360h pixel "canvas".
I did create some images from my remote url, no problem with help from stackoverflow.
However, I desire to maintain aspect ratio of the image but, have the end result be 480x360.. Therefore, a "canvas" or border then crop technique needs to be used (from what I have read) but, I cannot seem to get it going.
Here is what I have:
#!/usr/bin/perl
use Image::Resize;
use Image::Magick;
use strict;
my $new = 'path/to/image/image.jpg';
my $somewords = 'Some words';
my $imageurl='http://myimageurl.com/image.jpg';
my $p = new Image::Magick;
$p->Read("$imageurl");
my ($origw, $origh) = $p->Get('width', 'height');
#### correct size images get processed here with just annotation ########
if (($origw == 480) && ($origh == 360)){
system("convert $imageurl -fill '#FFFFFF' -font Candice -pointsize 12 -undercolor '#00000080' -gravity SouthEast -annotate +1+1 '$somewords' $new");
}
#### process images of incorrect original size WHERE I AM STUCK #######
if (($origw != 480) && ($origh != 360)){
system("convert $imageurl $new");
system("convert $imageurl -resize 480x360\! -fill '#FFFFFF' -font Candice -pointsize 14 -undercolor '#00000080' -gravity SouthWest -annotate +1+1 '$somewords' $new");
}
What I need is this:
A "canvas" size of 480 x 360.
Reduce the original image from the url to correct aspect ratio at either 480w or 360h and place it in the middle of the 480x360 canvas.
I read somewhere, that offered no examples, that I could resize original image while maintaining aspect ratio to correct height or width whichever allows the image to be largest then, divide the other param (h or w) by 2 and then make add border based on that, then crop to size. Confused the "he + double hockey sticks" out of me.
I am so lost on trying to figure this out. I am even unsure if my question here is clear and worthy of asking stackoverflow.
Seems like resizing while maintaining aspect ratio while creating a fixed output image is very difficult! Hours of searching have not helped me.
I praise the one who offers a verbose solution. Thanks.
Isn't it a bit silly to use the Image::Magick module, and then use the external convert command? You can do all of this within your Perl script using Image::Magick.
Anyway, if you read the fine manual, you'll find that ImageMagick will resize to the highest dimensions within 480x360 without changing the aspect ratio by using 480x360. This works both on the command-line with convert and within Image::Magick. When you add the !, you're telling it to resize to exactly 480x360, disregarding the aspect ratio.
This should get you started without using external commands:
...
$p->Resize(geometry=>'480x360');
$p = $p->Montage(geometry=>'480x360', background=>'black', fill=>'white',
stroke=>'white', pointsize=>12, title=>$somewords);
$p->Write($new);
...
The easiest way to get the same aspect ratio would be to calculate and scale by a percentage instead. ImageMagick lets you scale using a percentage for the geometry. IE,
convert -geometry 25%x25% file1.jpg file2.jpg
Note that you can do all of this without calling system() too, though system() is probably easier to get you started and then convert it to internal Image::Magick API calls later.