I have a script that resizes all images from a source directory into a destination directory, but I need to keep the original filenames and add "100-", "200-" and "400-" to the beginning of the file names.
Here is what I have currently:
magick C:\Users\joe\Desktop\Source*.jpg ^
( -clone 0--1 -resize 400x400 +write C:/Users/joe/Desktop/Destination/400.jpg ) ^
( -clone 0--1 -resize 200x200 +write C:/Users/joe/Desktop/Destination/200.jpg ) ^
( -clone 0--1 -resize 100x100 +write C:/Users/joe/Desktop/Destination/100.jpg ) ^
null:
This works, but it doesn't keep the original file names it just does "400-1.jpg", "400-2.jpg", "400-3.jpg" and so on.
How would I get it to maintain the file names and add these on to the start of the name?
Thanks.
Something like this (I'll let you figure out how to replace things in your own incantation:
convert -verbose /tmp/*.png -set filename:out "%[directory]/400-%[basename]" "%[filename:out].jpg"
You can do several variations around this depending on the output directory (explicit, from the input image, or the working directory). The final output substitution can only have a single escape, which is why the name is constructed when setting filename:out.
See this for the gory details.
Related
I would like to crop multiple images files and keep the same name or add a "_2" at the end of the name.
any idea how to do it?
I tried this
magick *jpg -set filename:base "%[basename]" -fuzz 90% "%[filename:base]_2.jpg"
To just keep the same name use magick mogrify. This works exactly like magick or magick convert but overwrites the input file, so there is no output specification. It is quite simple to use on a set of files:
magick mogrify [parameters] file [file...]
each representing a channel and I want to merge them into a single one, like RGB image. The images are RAW, so no file header. I have managed to mix them with
cat imgPl0.raw imgPl1.raw imgPl2.raw >> img.rgb
but this is mixing the planes one after the other, but is there a way to do an interlaced mix ?
Maybe using imagemagick there is another way ?
Well, what I need at the output is a rgb image (not a png, sadly imagemagick is creating a png as output) containing the data interlaced. To be more explicit, cat-ing the images is going to make a rgb image plane-interlaced (that is rrrrrr...ggggggg...bbbbbbb). What I want is an operation that is creating a rgb image line-interlaced (that is rrr...ggg...bbb...rrr...ggg...bbb...rrr...ggg...bbb...). Sorry for not being explicit from the beginning.
About the data, it seems it is 12 bpp or 14 bpp little endian
ImageMagick offers a few techniques, but you'll need to be responsible for defining all the information missing from the headers. Stuff like image size, quantum depth, and colorspace.
One approach.
convert -size 70x46 -depth 8 \
r:imgPl0.raw g:imgPl1.raw b:imgPl2.raw \
-set colorspace RGB -combine -colorspace sRGB \
output.rgb
Another option is to create a blank canvas, and copy the data from the raw files over to the correct canvas channels.
convert -size 70x46 xc: -depth 8 \
r:imgPl0.raw -compose CopyRed -composite \
g:imgPl1.raw -compose CopyGreen -composite \
b:imgPl2.raw -compose CopyBlue -composite \
-colorspace sRGB output.rgb
Other examples can be found here.
Also note: I'm assuming that these .raw data files only contain single channel samples, are unsigned character color sizes, and have a 70x46 image size. YMMV
Update
Well, what I need at the output is a rgb image (not a png, sadly imagemagick is creating a png as output)
Sorry about that. Just switch output.png to output.rgb. ImageMagick will do the rest.
About the data, it seems it is 12 bpp or 14 bpp little endian
Adjust -depth from 8 to 12, or 14 bits-per-part.
There's also a -endian LSB option, but I don't think that's needed.
What I want is an operation that is creating a rgb image line-interlaced
Easy. Set the -interlace Line options.
So... My previous answer is still helpful, but just needs some additional options.
convert -size 70x46 -depth 12 \
r:imgPl0.raw g:imgPl1.raw b:imgPl2.raw \
-set colorspace RGB -combine -colorspace sRGB \
-interlace Line output.rgb
or
convert -size 70x46 xc: -depth 12 \
r:imgPl0.raw -compose CopyRed -composite \
g:imgPl1.raw -compose CopyGreen -composite \
b:imgPl2.raw -compose CopyBlue -composite \
-colorspace sRGB -interlace Line output.rgb
Hope that get's you close.
If your data is 8 bits per sample, you can do it like this which whilst not very efficient, doesn't require any code writing or compiling or anything:
#!/bin/bash
# Bytes per row
bpr=100
row=0
# Loop through all rows of file
while :; do
# Read a row from each channel and output on stdout redirected to result.rgb
for ((chan=0;chan<3;chan++)); do
dd if=imgPl${chan}.raw bs=$bpr count=1 skip=$row > row.tmp 2> /dev/null
[ ! -s row.tmp ] && exit
cat row.tmp
done
((row+=1))
done > result.rgb
I have two images:
a.jpg
b.jpg
Both images are square (100x100 pixel). I want to cut a circle with a radius of 50 from image a.jpg and paste it in the middle of image b.jpg. I want to save the result in c.jpg.
How can I do this with Linux command line tools? I need to do it within a shell script.
Many different techniques can be used. ImageMagick has FX language that can perform complex calculations.
convert a.jpg b.jpg -fx 'Wi=w/2; Hi=h/2; hypot(Wi-i, Hi-j) < 50 ? u : v' c.jpg
For example...
convert -size 100x100 PLASMA: a.jpg
convert -size 100x100 GRADIENT:LIME-ORANGE b.jpg
convert a.jpg b.jpg -fx 'hypot(50-i, 50-j) < 50 ? u : v' c.jpg
Update with another technique.
A faster approach can be leveraging image mask(s) of the shape you wish to crop, and compose/composite it between both images. It'll require a format that supports alpha channels, but only for the initial work. For example...
Create a circle mask, and copy values to alpha channel.
convert -size 100x100 xc:White -fill Black \
-draw 'circle 50 50 50 5' -alpha Copy mask.png
convert \( a.png mask.png -alpha Set -compose Dst_Out -composite \) \
b.png -compose Dst_Atop -composite c.png
Eric's approach is much more succinct, and probably preferable, but here is another way anyway. I am being very environmentally aware and recycling ;-) his start images:
magick b.jpg \( a.jpg \( +clone -threshold 101% -fill white -draw "circle 49,49, 49,99" \) -channel-fx '| gray=>alpha' \) -flatten result.png
That says... "Load b.jpg as the background. Load a.jpg and then create a transparency mask by cloning the entire a.jpg setting it black and drawing a white circle in it and pushing it into the alpha channel. Then flatten that over the top of b.jpg".
The result is the same as Eric's.
I have 2 images of the same size, called image1.png and image2.png. In ImageMagick, is there any way to merge the two images by taking the odd lines from image1.png and merge with the even line from image2.png ?
Sure, make alternate rows transparent:
# Make red test image
convert -size 300x200 xc:red red.png
# Make blue test image
convert -size 300x200 xc:blue blue.png
# Merge with alternate lines made transparent
convert red.png \( blue.png -alpha on -channel A -fx 'j%2' \) -composite result.png
Or, an alternative way of thinking about it is to load both images and then choose pixels from either the first (u) or the second (v) depending on the row:
convert red.png blue.png -fx 'j%2 ? u : v' result.png
On Windows, these two come out as:
REM Do Windows style commands
convert red.png ^( blue.png -alpha on -channel A -fx "j%2" ^) -composite result.png
and
REM Windows style
convert red.png blue.png -fx "j%2 ? u:v" result.png
How do I tile an image using ImageMagick? I don't think I can use montage because I want the columns displaced by 50% of the original image height.
It's probably easier to show an example of what I'm trying to do:
Start with:
End with:
Thanks!
In case you want plain tiles, without shifting down the second column and the rest of the even columns, you can use this script:
convert -size 800x600 tile:Ball.jpg Tiles.jpg
(probably the majority of people landing on this question want such plain tiles, like I did)
My "Ball.jpg" is 200 x 200 pixels, so this script creates a 4x3 tile image.
For ImageMagick 7 users, replace convert with magick.
Thanks to Fred at Fred's ImageMagick Scripts, here's the solution:
infile="tile.png"
h2=`convert $infile -format "%[fx:round(h/2)]" info:`
convert $infile \( -clone 0 -roll +0+$h2 \) +append -write mpr:sometile +delete -size 1000x500 tile:mpr:sometile output.png
This is exactly what I was looking for.
Even though you did not mention anything about context of usage, I will put it here so more people are aware. Fred's scripts are for non-commercial use. I ended with an alternative solution, however, principle is the same:
Creating shifted tile by:
convert _orange_270.jpg -roll +0+135 _orange_270_r.jpg
Create a column of regular tiles:
montage _orange_270.jpg +clone +clone +clone -tile x4 -geometry +0+0 _1col.jpg
Create a column of shifted tiles:
montage _orange_270_r.jpg +clone +clone +clone -tile x4 -geometry +0+0 _2col.jpg
Combined regular and shifted columns:
montage -geometry +0+0 _1col.jpg _2col.jpg _2cols.jpg
Created full tiled image using last output from point 4:
convert _2cols.jpg -write mpr:tile +delete -size 1920x1080 tile:mpr:tile _wallpap.jpg
Result:
If on a unix-like system with ImageMagick, you could just use my script, tileimage at http://www.fmwconcepts.com/imagemagick/tileimage/index.php.
It provides numerous variations on the flipping, rotation and offsets.
If non-commercial use, then it is free, If commercial use, then contact me for a license.
Information about tiling in ImageMagick can found at http://www.imagemagick.org/Usage/canvas/#tile