Making white background transparent using ImageMagick - image

I have about 2700 images that I want to:
Convert to .png
Make the white background, transparent
To do this, I downloaded ImageMagick using Homebrew and ran the below command in the relevant directory:
find . -type f -name "*.jpg" -print0 | while IFS= read -r -d $'\0' file; do convert -verbose "$file" -transparent white "$file.png"; done
This worked, however the images still have a few white specks around them as per the below image. With off-white bottles, it's even harder because it makes some of the bottle transparent too!
In photoshop, you can adjust the "tolerance" of "MagicWand" to ensure that this doesn't happen but I'm not sure how you can do this using ImageMagick and can't find anything on Google.
Example of Image with white crust around outside
Can anyone help? Is there a way of doing this with ImageMagick? Is there a better way of processing these 2700 images to remove the white background?
Thanks
A

Use -fuzz option in ImageMagick
$ convert img.jpg -fuzz 32% -transparent #ffffff out.png
This will allow you to adjust the tolerance value. Hope this helped.

Related

How do I rename images when using mogrify with Image Magick?

I am trying to automate the converting images to specified tif formats. I have it converting just fine, but am also needing to add "_GS" at the end of the file name and before the extension to each file converted. Below is what I have but have had no luck finding a solution to add "_GS" to the file name. Thanks in advance for any help.
for f in "$#"
do
echo "$f"
/usr/local/bin/mogrify -density 300 -resize 1000x1000 -type grayscale -define tiff:endian=msb -compress LZW -format tif "$f" [0]
done
Item 1: With Image Magick, to create a new file instead of overwriting an existing one, use convert, not mogrify (magick convert with newer versions of IM).
Item 2: You can use shell parameter expansion to remove the extension, and then build the new filename from that and the new suffix:
for f in "$#"
do
echo "$f"
/usr/local/bin/convert "$f" -density 300 -resize 1000x1000 -type grayscale \
-define tiff:endian=msb -compress LZW -format tif "${f%.*}_GS.tiff"
done
${variable%pattern} returns the expansion of variable with the shortest match of pattern removed from the end.

Convert entire folder to greyscale using image magick?

I am trying to convert an entire folder to grayscale, using image magick.
convert *.jpg -colorspace Gray -separate -average
is met with this error :
convert: `-average' # error/convert.c/ConvertImageCommand/3290.
What is the correct command for this?
If you have lots of files to process, use mogrify:
magick mogrify -colorspace gray *.jpg
If you have tens of thousands of images and a multi-core CPU, you can get them all done in parallel with GNU Parallel:
parallel -X magick mogrify -colorspace gray ::: *.jpg
Also, the following can be used in a script - for the context menu of file managers like Dolphin, Nautilus, Nemo, Thunar etc:
for filename in "${#}"; do
name="${filename%.*}"
ext="${filename##*.}"
cp "$filename" "$name"-grayscale."$ext"
mogrify -colorspace gray "$name"-grayscale."$ext"
rm "$name"-grayscale."$ext"~
done

copy one picture and paste it on top of the other on terminal

In here I found a piece of code that finds and resizes all images within a folder with applescript
Now I need to apply a stamp to those images one by one. I already have a transparent jpg prepared with the same size and ready to be pasted on all of them.
I just lack the knowledge to do it on terminal so I could mix it with applescript.
Does anyone know how to do this without making a workflow? Because it takes a lot of time and keeps the laptop busy
Updated Again :-)
You can get the height of an image like this:
identify -format "%h" image.jpg
500
and the width like this:
identify -format "%w" image.jpg
800
If you want to find the lesser of the height and the width, and then take 10% of that for your logo size and make it integer, you would do:
identify -format "%[fx:int(0.1*min(h,w))]" image.jpg
50
If you want to put that in a variable, you would do
logosize=$(identify -format "%[fx:int(0.1*min(h,w))]" image.jpg)
echo $logosize
50
You could then use that in the original command below like this:
convert image.jpg -gravity southeast \
\( copyright.png -resize "${logosize}x${logosize} \) \
-composite result.jpg
I suspect you are going to want to run that with the find command, aren't you? :-)
find . -iname \*.jpg -exec bash -c 'echo Processing {};logosize=$(identify -format "%[fx:int(0.1*min(h,w))]" "{}"); echo $logosize;convert "{}" -gravity southeast \( copyright.png -resize "$logosizex$logosize" \) -composite "{}"' \;
Updated Answer
If you want to resize your original image before compositing the logo unchanged on top, use a command like this:
convert image.jpg -resize 2000x1000 -gravity southeast copyright.png -composite result.jpg
If you want to resize the logo before compositing it on top of the unchanged original image, use a command like this:
convert image.jpg -gravity southeast \( copyright.png -resize 700x200! \) -composite result.jpg
Original Answer
I would use ImageMagick. It is extremely powerful and simple to install if you use homebrew. Ask if you don't know how...
Let's assume you have an image called image.jpg and a transparent logo/copyright called copyright.png.
image.jpg
copyright.png
Then the command to do a single image would be:
convert image.jpg copyright.png -composite result.jpg
If your logo/copyright and image are different sizes, and you want to force the logo to, say, the bottom right corner, just set the -gravity accordingly like this:
convert image.jpg -gravity southeast copyright.png -composite result.jpg
If you wanted to do all the JPEGs in the folder, you would need a loop:
#!/bin/bash
shopt -s nullglob
shopt -s nocaseglob
for f in *.jpg; do
convert "$f" copyright.png -composite "$f"
done
By the way, you cannot have a transparent JPEG - that format doesn't support transparency.
If you are really intent on using Applescript - I don't know why anyone would be - you can call the above using do shell script - make the file executable first. Ask if unsure how.
If you want to recurse down into all directories (folders) starting at the one you are currently located in and add the logo/copyright to all images, I would make a copy of them somewhere else first and do a trial run. The command would be:
find . -iname "*.jpg" -exec convert "{}" copyright.png -composite "{}" \;
That says... "find, starting at the current directory (.), disregarding upper/lower case (-iname), all files ending in "JPG", and apply the logo/copyright to them, resaving on top of the original file".
I had same issue years ago, and the only way I found is an Applescript using Photoshop (duplicate layer containing the logo on the photo and flatten file).
the script loops to all file of a folder.
... but you need Photoshop for this script !
I can share that script if it helps

ImageMagik: Blur map a set of images

The example shown on the website is:
convert koala.gif blur_map_gradient.gif \
-compose blur -define compose:args=3 -composite \
blur_koala_gradient.gif
http://www.imagemagick.org/Usage/mapping
I'd like to do this for a whole directory of images.
I've looked into using mogrify, but can't figure out how to set the file input/output to run the process on a whole directory.
Thanks for any help.
You're on the right track with mogrify. To use your command as an example, you could do this:
mogrify -compose blur -define compose:args=3 -composite *.gif
This will apply the changes to all the images in the current directory. This will overwrite the images. If you do not want to overwrite the original images, you can either make a new directory (let's call it '/home/user/new/') or use the -format option to append a suffix to the files.
Here's an example with both options:
`mogrify -path /home/user/new/ -compose blur -define compose:args=3 -composite -format "blur.gif" *.gif
This will place originalimagename.blur.gif files in /home/user/new/, leaving the originals intact.
I was sure that it was possible to use -compose with mogrify. In actuality, mogrify does not recognize the -compose argument.. I think that your best bet is to use a script to loop through each image in the directory and use convert on them.

Improving process for using ImageMagick to batch convert TIFF to PNG and resample

I have several folders of 600 dpi TIFFs (CCITT Group IV, so black & white) that I need to convert to screen resolution PNGs - so in ImageMagick terms, I need to convert the format and resample the images to ~80 dpi. My first approach was to perform this in a single mogrify command (this is in bash on Mac OS X):
for folder in $(find * -maxdepth 0 -type d ); \
do mogrify -path "$folder/medium" -format png -resample 31.5% "$folder/tiff/*.tif"; \
done
But the result was awful. The text in the resulting image was completely illegible. So I changed this to a two step process, (1) converting the TIFF to PNG at original resolution, then (2) downsizing the resolution:
for folder in $(find * -maxdepth 0 -type d ); \
do mogrify -path "$folder/medium" -format png "$folder/tiff/*.tif"; \
mogrify -resample 31.5% "$folder/medium/*.png"; \
done
While this process resulted in nice and crisp results at 80 dpi, the process was much slower, since I'm now writing the full resolution file to disk before downsizing the resolution.
Does anyone have a suggestion for the best way to accomplish a conversion and downsizing of resolution in a single step?
The sips tool can be used as follows:
sips -s format png -s dpiHeight 80 -s dpiWidth 80 -z 1200 1600 test.tiff --out test.png
Having said that in the resulting .png, the DPI settings don't seem to have been changed.
Also when resizing, it looks like you can only specify absolute pixel dimensions of the output image, and not a percentage of the input image. So you would have to grab the dimensions of the input image and calculate the new size explicitly:
#!/bin/bash
infile=test.tiff
outfile=test.png
pct=31 # only whole numbers for bash arithmetic
height=$(sips -g pixelHeight $infile | tail -1 | cut -d: -f2)
width=$(sips -g pixelWidth $infile | tail -1 | cut -d: -f2)
sips -s format png -s dpiHeight 180 -s dpiWidth 180 -z $((height*pct/100)) $((width*pct/100)) 1600 $infile --out $outfile
I know I am late to the party, but I was looking at this and wondered why you get poor quality when doing both setps in one go. I wondered if it was maybe down to using mogrify rather than convert, so I set about trying to improve it. So, this would be my first and best attempt:
#!/bin/bash
for f in */tiff/*.tif; do
out="${f%tif}png" # replace "tif" suffix with "png"
out=${out/tiff/medium} # replace "tiff" directory with "medium"
convert "$f" -resample 31.5% "$out"
done
And, if that still doesn't work, I could go for a second attempt which avoids writing the file to disk and then resampling it, and instead writes a PNG to stdout and then pipes that to a second convert that resamples and writes to disk - thereby avoiding the writing to disk of the big, intermediate PNG.
#!/bin/bash
for f in */tiff/*.tif; do
out="${f%tif}png" # replace "tif" suffix with "png"
out=${out/tiff/medium} # replace "tiff" directory with "medium"
convert "$f" PNG:- | convert - -resample 31.5% "$out"
done

Resources