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.
Related
I'm trying to use ImageMagick to compose different pieces of a rendered PDF into a target. E.g., I want to have ImageMagick render the PDF at 300dpi, then create a 300x400 pixel output image, then take from the PDF the area 10x20+30+40 and place it in the target (300x400 pixel image) at 12,34. Then take another (and a third and fourth) chunk at different coordinates with different sizes and place them at different places.
I cannot seem to figure out how to do this in one go, and doing it in multiple runs always re-renders the PDF and takes awfully long. Is this even possible?
Here's an idea of how you can approach this. It uses the MPR or "Memory Program Register" that Fred suggested in the comments. It is basically a named chunk of memory that I write into at the start and which I recall later when I need it.
Here is a rather wonderful start image from the Prokudin-Gorskii collection:
The code resizes the image and saves a copy in the MPR. Then, takes a copy of the MPR, crops out a head, resizes it and composites the resized result onto the resized original at a different location and then repeats the process for another head.
magick Prokudin.png -resize 300x400\! -write MPR:orig \
\( MPR:orig -crop 50x50+180+84 -resize 140x140 \) -geometry +10+240 -compose src-over -composite \
\( MPR:orig -crop 40x40+154+184 \) -geometry +40+100 -compose src-over -composite \
result.png
If you have trouble understanding it, try running it with the second or third line omitted so it just does one head ;-)
Hopefully it covers all the aspects of your question and you can adapt it to your PDF.
I have a set of images, and I can use the Imagemagick montage command on them to produce a montage image file with transparent background (let's call this fgimg). Now I have another existing image (let's call this bgimg) that I'd like to use (after some special processing with the convert command) as the background for fgimg, which can be achieved within the same convert command. At this point it seems trivial to avoid writing the temporary fgimg to disk, simply by piping the standard output of montage to the standard input of convert.
My problem is that the special processing I'm applying to bgimg will require some knowledge of the image properties of fgimg (e.g., resizing bgimg to have the same size as fgimg), which I don't know in advance. How can this information be retrieved and used in the convert command?
Note: I'm using Imagemagick version 6.9.7-4 on Linux.
I'll include some commands below to further illustrate the problem in detail.
The following command produces the montage image fgimg from a set of input images. The output is in the 'special' miff format (which seems best for temporary output to be worked on later), and has transparent background so that the actual background can be applied later. Most of the other options here are not important, but the point is that the output size (dimensions) cannot be determined in advance.
montage input_*.jpg -tile 5x -border 2 -geometry '200x200>+20+20' \
-gravity center -set label '%f\n%G' -background none -fill white \
-title 'Sample Title' miff:fgimg
Next, I have another input image bgimg.jpg. I want to perform some processing on it before using it as background to fgimg. The processing can be quite complex in general, but in this example, I want to:
resize bgimg.jpg to fit inside the dimensions of fgimg without any cropping;
apply a fade-to-black effect around the edges;
make it the same size as fgimg, with a black background;
combine this with fgimg to produce the final output.
Notice that I need the size of fgimg in two places. I can first extract this into a shell variable:
size=$(identify -format '%G' miff:fgimg)
Then I can do all the steps above in one convert command (note that $size is used twice):
convert "bgimg.jpg[$size]" -gravity center \
\( +clone -fill white -colorize 100% -bordercolor black \
-shave 20 -border 20 -blur 0x20 \) -compose multiply -composite \
-background black -compose copy -extent $size \
miff:fgimg -compose over -composite final_out.jpg
Now here is the problem: I want to avoid writing the temporary file fgimg to disk.
I could replace miff:fgimg with miff:- in both the montage and convert commands and then just pipe one to the other: montage ... | convert .... But how do I deal with the $size?
I tried to use file descriptors (miff:fd:3) but this does not seem to work, which is confirmed by the comments to this question.
Is there a way to do this (in Imagemagick v6) without creating a temporary file?
This example command uses ImageMagick v6 on a bash shell. Instead of "montage" it starts by using "convert" to create a "logo:", one of IM's built-in sample images, then pipes it out as a MIFF and into the "convert" command that follows. You can pipe the output of "montage" just as easily. And it uses another IM built-in image "rose:" as your "bgimg.jpg"...
convert logo: miff:- | convert - rose: \
+distort SRT "%[fx:t?min(u.w/v.w,u.h/v.h):1] 0" \
-shave 1 +repage -gravity center -bordercolor black \
\( -clone 1 -fill white -colorize 100 -shave 6 -border 6 \
-blur 0x6 -clone 1 -compose multiply -composite \) -delete 1 \
\( -clone 0 -alpha off -fill black -colorize 100 \
-clone 1 -compose over -composite \) -delete 1 \
+swap -composite final_out.jpg
That reads the piped image "-" and the background image "rose:".
Then it uses "+distort" with an FX expression to scale "rose:" to the maximum dimensions that still fit within the original piped input image. That operation adds a pixel all around so we use "-shave 1" to get rid of that.
Next inside parentheses it clones that re-scaled background image, makes an edge blur mask, and composites them to make the fade-to-black edge on the background image. Right after the parentheses it deletes the non-edged background image.
In the next parentheses it clones the input image, makes it black, clones the modified background image, and composites it centered over the black one. Again the non-extended background image is discarded after the parentheses with "-delete 1".
Finally the modified background and the input image are put in the proper order with "+swap" and composited for the final output. Run this command without the last "-composite" to see the two images that result from the prior parts of the command.
Both the main input image and background image can be any size, any dimensions, and any aspect ratio. This works for me on v6.8.9 on a bash shell. It should work on any ImageMagick newer. It should work on Windows by removing all the backslashes that escape parentheses and changing the continued-line backslashes "\" to carets "^".
EDITED TO ADD:
You can use that FX expression to find the scaling amount, save it as a variable, then isolate the background image inside parentheses and use that variable to do the scaling and shaving there. That way it only affects the background image. There may be a rounding error with that, but the main image, which determines the exact final output dimensions, will be unaffected. Note the difference in the first few lines of this command...
convert logo: miff:- | convert - rose: \
-set option:v1 "%[fx:min(u.w/v.w,u.h/v.h)]" \
\( -clone 1 +distort SRT "%[v1] 0" -shave 1 \) -delete 1 \
+repage -gravity center -bordercolor black \
\( -clone 1 -fill white -colorize 100 -shave 6 -border 6 \
-blur 0x6 -clone 1 -compose multiply -composite \) -delete 1 \
\( -clone 0 -alpha off -fill black -colorize 100 \
-clone 1 -compose over -composite \) -delete 1 \
+swap final_out.jpg
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 want a combined command that can perform the following task in single execution. I searched the internet, but hardly found any tutorial that guide us to write any stack command. I can found single command for each operation, such as -composite, -blur, etc, and I know I can pipe the command as such
convert ... mpr:- | convert ... mpr:- | ... | convert ... png:-
However, I want a combined command that use \( ... \) and mpr:{label} since this will increase the performance as all operations are executed in single process (pipeline in shell can degrade the performance, and the process sequence is required to be in order).
The process sequence as such:
put flower.png on top of the frame.png -> mpr:framedFlower
put mpr:framedFlower on top of the background.png -> mpr:out2
blur the heart.png, right-gradient-transparent the smiley.png and put both image on top of mpr:out2 -> mpr:out3
annotate the mpr:out3 with "Hello world" (placement=bottom) -> png:-
I don't include the commands that I have tried because they are too messy and it will be an insult to those users who read it. I tried for many hours, but can't get it done. Please advise.
I haven't spent ages futzing with the exact coordinates as I am only using sample pictures, but this one-liner contains every technique you need to do what you are asking.
There is basically one line of code per element in the final image:
convert frame.png -resize 500x400\! \( flower.png -resize 400x300\! \) -gravity center -composite \
background.png +swap -gravity northwest -geometry +100+150 -composite \
\( heart.png -resize 200x200 -blur 0x8 \) -geometry +1200+250 -composite \
-gravity south -pointsize 72 -fill red -annotate +0+60 'Hello world' \
\( emoji.png -resize 250x250 -channel a -fx "u.a*(1-(i/w))" \) -gravity northwest -geometry +1200+500 -composite result.png
The first line reads in the picture frame and the flower and resizes them each independently because of the parentheses and then composites the flower into the frame.
The next line loads the background and then uses +swap to put it behind the framed picture from the previous line. It then sets -gravity to northwest as the origin for the ensuing -geometry before compositing the framed picture onto the background.
The next line loads the heart and resizes and blurs just the heart before compositing that onto the main picture at your specified position.
Next up is the annotation - the only interesting thing is that I set the -geometry to south which means that the offsets to -annotate are relative to the bottom centre of the background.
Finally, I load the emoji-thing and resize just it in parentheses before compositing over the main image. The only interesting thing is that I use -fx to alter the alpha channel (-channel a) and I multiply the existing transparency (u.a) by the fraction of the inverse of the distance we are across the image, namely (1-(i/w)).
Hope that is fairly clear!
Start Images
I want to add watermark to my_own_png.png file by using:
composite -dissolve 10% -gravity center -quality 100 watermark_350.png my_own_png.png result.png
The result.png is not what I what, I want to keep my_own_png.png's alpha.
Please help~Thank you.
There are a couple of ways of doing this...
Firstly, you could run with your current processing, which I presume you understand and are happy with, and then copy back your original image's alpha over the top of your result, like this:
# Your current processing
composite -dissolve 10% ... result.png
# Now add back the original image's alpha
convert result.png my_own_png.png -compose CopyOpacity -composite result.png
Or, you could do the whole lot in one go using convert rather than composite, and it will look something like this but it is hard to be sure without seeing what you are actually doing:
convert my_own_png.png \
\( +clone -gravity center watermark_350.png -compose dissolve -define compose:args='10' -composite \) \
+swap -compose CopyOpacity -composite result.png
That basically loads up your my_own_png.png and puts it to one side. It then copies it and does the dissolve with your watermark inside the parentheses. After the parentheses, the order of the images is swapped so that the watermarked image is first in the list and the original png is second in the list. It then copies the alpha from the original image and applies it to the watermarked image - hopefully :-)