I am trying to apply watermark to an image of any size using two steps in one command line:
Tile small png image and overlay it over the target image.
Overlay a logo at top left corner without tiling.
I don't understand the imagemagick command line principles and can't create a command line to make these operations without creatig temporary file between steps 1 and 2. But I am sure this is possible :)
Please help me to do that.
Thanks.
There are many ways to achieve this, but the simplest would be to leverage ImageMagick's Stack notation "()".
Simply group the first step into a command wrapped in parentheses, and omit the output filename.
convert \( \
wizard: \
-size 480x640 \
-background transparent \
tile:label.png -composite \
\) \
-gravity NorthEast rose: \
-composite output.png
The above will compose the label.png as a repeating image over the wizard: image. Note, in this example I provided the -size and -background attributes. The result of the Image Stack will be accepted as the input image for the second -composite operation; which, places the rose: image in the top right.
Related
I want to split some images by percentage using ImageMagick.
To be more precise, I want to split an image into two images. The output-image of the left side should be 55% of the left side of the original image, the output-image of the right side should be 55% of the right ride of the original image.
(In case I am not making myself clear: The point is that there is sometimes important information in the middle of the images and this information would be cut off if we split the images exactly in the middle.)
What I have so far is this: mogrify -crop 55%x100% +repage -path ./cropped *.jpg
So at the moment, I am splitting the image into two and saving it in the "cropped"-folder. BUT, only the left side is 55% of the left side of the original image, the right side is 45% of the right side of the original image.
As this is my first time working with ImageMagick, I would really appreciate your help!
Here is another approach to splitting an image to create two output images that are 55% from the left and 55% from the right of the original...
convert input.png -set filename:0 "%[t]" \
\( +clone -roll +55+0% \) -extent 55x100% "%[filename:0]_%d.png"
That starts by setting a file name variable to use for the output. Then it makes a clone of the input image, and rolls it 55% to the right. The result is moving the rightmost 55% of the image out of the frame to the right and back into the frame on the left. Then after the parentheses a simple -extent operation keeps the leftmost 55% of each image. The output files are named from the input file with a "_0" or "_1" added.
As fmw42 suggested, you can make a loop command to run on multiple inputs, and include the path names in the command for your output files.
I think you would have to run a script loop over each image and use convert rather than mogrify. Mogrify can only output one image for each input image. You do not say what platform/OS or what version of ImageMagick. The following assumes Unix-like system with IM 6 and is one way to do that.
infile="original_file.suffix"
convert "$infile" -set filename:fname "%t" -write mpr:img +delete \
\( mpr:img -gravity west -crop 55x100%+0+0 +repage +write "path_to/cropped/%[filename]_0.suffix" \) \
\( mpr:img -gravity east -crop 55x100%+0+0 +repage +write "path_to/cropped/%[filename]_1.suffix" \) \
null:
Or, you could just run mogrify twice. Once for the left side and once for the right side. Use -gravity to control which as in the convert command.
I'm assuming ImageMagick is the best option for this, but please let me know if you have other recommendations that can be scripted.
I am trying to replace all the 32x32 tiles of an image with a single tile. This is an example for the original image:
This is the tile that I want to use to replace all tiles on the original image:
And this is what I want the output to be:
I've figured out from other posts on Stack Overflow that I can use ImageMagick's composite option to overlay the tile onto the original image:
$ convert original.png tile.png -composite overlay.png
Resulting in the following:
And I assume by knowing the original images dimensions I can overlay the tile manually multiple times. But is there a way to automate the process. In the example pictures I have given, I need to overlay the tile 8 times on the original 64x128 image.
How can I do this with ImageMagick or another software? And if ImageMagick, would the montage or composite command be a better option?
Edit: As an additional question, would it be possible to skip tiles that are completely transparent?
Input example:
Output example:
It isn't really important to be able to do this part, but would be nice.
If the tile image fits evenly into the dimensions of the original, a command like this should do most of what you want...
convert original.png tile.png -background none -virtual-pixel tile \
-set option:distort:viewport %[fx:u.w]x%[fx:u.h] -distort SRT 0 +swap \
-compose copyopacity -composite overlay.png
That reads in both images. Then it creates another canvas the size of the original and filled with multiple copies of the tile image. Then it uses the original as a transparency mask to create a copy of the new tiled image with the same transparent cells as the original.
I don't know why you would need to overlay the 8 tiles on the original. Just create it from scratch and name the output the same as your original
You could use Imagemagick montage to do that (unix syntax):
nx=`convert original.png -format "%[fx:w/32]" info:`
ny=`convert original.png -format "%[fx:h/32]" info:`
num=$((nx*ny-1))
montage tile.png -duplicate $num -tile ${nx}x${ny} -geometry +0+0 result.png
Here I use convert to duplicated the tile, but it uses a relatively current -duplicate feature. If you do not have a current enough version of Imagemagick, then just repeat the tile in montage as follows:
montage Ro1Lp.png Ro1Lp.png Ro1Lp.png Ro1Lp.png Ro1Lp.png Ro1Lp.png Ro1Lp.png Ro1Lp.png -tile 2x8 -geometry +0+0 result.png
As Fred (fmw42) says, "why don't you just create the whole image from scratch?".
Maybe your description isn't complete, so here are a couple more pieces that might help you work it out.
Given bluetiles.png and singlered.png:
you can position red ones as you wish like this:
convert bluetiles.png \
singlered.png -geometry +0+32 -composite \
singlered.png -geometry +32+96 -composite result.png
Given bluewithtransparent.png:
you can copy its transparency to the newly-created image like this:
convert bluetiles.png \
singlered.png -geometry +0+32 -composite \
singlered.png -geometry +32+96 -composite \
\( bluewithtransparent.png -alpha extract \) -compose copyopacity -composite result.png
I am trying to make a fast convert of a batch of files like this:
convert ./src/*.png -set filename: '%t' -gravity West -draw 'image over 0,0 424,600 "./panel.png"' ./dest/%[filename:].png
which is pretty similar to COMPOSITE:
convert ./src/*.png ./panel.png -set filename: '%t' -gravity +0+0 -composite ./dest/%[filename:].png
except the last one is not working and just making one first crappy-looking file.
Looks like it's bug?
Does anybody know how to make it more correct with -composite?
for|awk|ls|find for each file in shell is not acceptable - because that is slower than the first example.
Read in the list of files,
set their output filenames,
include the IM special image placeholder "null:",
read in your overlay image,
optionally, set the geometry,
and composite that overlay onto all the other images with "-layers composite".
That null: separates the original input file list from the overlay image so ImageMagick knows where in the stack you want to start doing the composite.
Try something like this (one step per line for readability):
convert ./src/*.png \
-set filename: '%t' \
null: \
./panel.png \
-layers composite ./dest/%[filename:].png
You could use Imagemagick mogrify command. See http://www.imagemagick.org/Usage/basics/#mogrify and http://www.imagemagick.org/Usage/basics/#mogrify_compose
cd to input directory
mogrify -format png -path ./dest -gravity West -draw 'image over 0,0 424,600 "./panel.png"' *.png
Looks like it's bug?
Not a bug. Your second command is telling ImageMagick to consume all files matched into an image stack, and composite it as one.
You can attempt the same solution with the mogrify utility, but I believe it would be way simpler if you expand the bash script with a single for loop.
for f in $(ls src/*.png)
do
dest=$(basename $f);
convert "$f" ./panel.png -gravity West -composite "./dest/$dest"
done
I have several pictures of a landscape.
Using the ImageMagick CLI on OSX, I would like to distort and overlay them properly.
I have looked for distortion coordinates between several of the pictures and a reference picture. I fail to understand the diference between -distort and +distort and how it plays with +repage. When I use -distort, the output has the desired offset but it's incomplete (it needs to be bigger). When I use +distort, I get the full image but it's missing the offset.
Reading the documentation I understand that I could do without the offset if I did the overlay composition in the same command before the offset information is lost but what's happening is that the distort is being applied to both the reference and the distorted images.
This is the result of using -distort:
This is the result of using +distort:
The offset of the -distort result would work once I apply it as an overlay (here using the composite in a separate command, but it's missing a big chunk of the picture.
When I tried to consolidate it in a single command this is the result I get:
This is the command I'm currently using:
convert base.jpg overlay.jpg
-matte -virtual-pixel transparent -distort Perspective '961,1695 1856,2461 2279,1520 3185,2303 3564,2173 4441,2970 1547,2817 2441,3594'
-compose blend -define compose:args=50,100 -composite result.jpg
I understand I could use parenthesis there but I fail to see where should I put them.
Thanks!
Update: this is the result of the overlay when using +distort either in two steps or in a single step as recommended by Mark.
The solution was to use -flatten instead of -composite.
convert base.jpg \( b.jpg -matte -virtual-pixel transparent +distort Perspective '961,1695 1856,2461 2279,1520 3185,2303 3564,2173 4441,2970 1547,2817 2441,3594' \) -compose blend -define compose:args=100,50 -flatten result.jpg
Turns out that -composite ignores the image offsets whereas -flatten works with layers and uses the offset information.
The suggestion came from this thread: http://www.imagemagick.org/discourse-server/viewtopic.php?t=20157
This is the documentation to flatten (link broken in the discussion above): http://www.imagemagick.org/Usage/layers/#flatten
Not sure I understand the issues, but would suggest you try this (untested):
convert base.jpg \
\( overlay.jpg -matte -virtual-pixel transparent -distort Perspective '961,1695 1856,2461 2279,1520 3185,2303 3564,2173 4441,2970 1547,2817 2441,3594' \) \
-define compose:args=50,100 -compose blend -composite result.jpg
That would mean that the perspective distortion is only applied to the overlay, not the base. So, in the code above, the first line only processes the base image, the second line only processes the overlay, and the final line blends the two.
I have a set of source PNG images and I want to use parts of them to assemble a final PNG image. The parts are rectangular and never overlap on the destination but are of different sizes. Sometimes it is the whole of a source image and sometimes just a subsection. I want to edit the sources many times and re-assemble the final image each time, so I tried to write a script using sh and Imagemagick to do it.
I tried this
convert \
-size 512x512 null:\
-page +96+32 source_a.png\
-page +96+0 source_b.png[32x32+16+16] \
-background transparent\
-layers merge\
destination.png
(just with two source images for illustration)
I want all of source_a.png and a piece of source_b.png. The first is OK, but using the 'inline crop' syntax on source_b.png gives me an error:
convert: geometry does not contain image `source_b.png' # warning/transform.c/CropImage/666.
The image is big enough:
$ identify source_b.png
source_b.png PNG 64x48 64x48+0+0 8-bit sRGB 3.7KB 0.000u 0:00.000
What's the best way to do this? I am using ImageMagick 6.9.7-0 Q16 on MacOS 10.12
An alternative might be to use -geometry and -composte to achieve the same effect:
convert -size 512x512 xc:white \
source_a.png -geometry +96+32 -composite \
source_b.png[32x32+16+16] -geometry +96+0 -composite \
result.png
PNG's will preserve the paging from inline cropping, so the addition page will through the ROI out of bounds. I imaging it'll be simpler to -repage the inline crop then attempting to clear previous paging & setting new page.
convert -size 512x512 null: \
-page +96+32 source_a.png \
\( source_b.png[32x32+16+16] -repage +96+0 \) \
-background transparent\
-layers merge\
destination.png