Set transparent background using ImageMagick and commandline prompt
Asked Answered
S

8

169

Suppose you have any image (PNG or JPG). This image has a white background and I need to make this background transparent.

I have tried with these examples:

  • convert original.png -background none transparent.png
  • convert original.png -background white -flatten -alpha off transparent.png

but with no desirable results.

How can I make it?

IMPORTANT: Using convert command-line.

Snipes answered 6/2, 2012 at 3:48 Comment(3)
Odd -- I thought the relevant command was convert original.png -transparent white new.png but upon trying it, can't get it to work. As an aside, are you sure your background is actually white (#FFFFFF), or is it just almost-white (e.g. #FEFEFE)?Veta
@Veta Ok I understand, let me check if this is not the case and I'll continue this thread. Thank you.Snipes
@Veta Hi again, I have checked colors and this image has background like #FFFFFF, in other words "white". :( This is not the case!Snipes
K
178

I am using ImageMagick 6.6.9-7 on Ubuntu 12.04.
What worked for me was the following:

convert test.png -transparent white transparent.png

That changed all the white in the test.png to transparent.

Kedah answered 20/6, 2012 at 8:15 Comment(6)
This didn't work for me until I realized JPG won't do transparent. Once I switched to PNG it did exactly what I wanted - just had to change "white" to "rgb($r,$g,$b)".Teirtza
This will not only convert the background to transparent, but every white pixel. Is there a way to convert the background only to transparent?Gilkey
@AlejandroLozdziejski - how are you definining "background"?Undecided
@AlejandroLozdziejski: Good question. Please see my solution which uses a floodfill from the edges, looking for colors approximately the same as the top-left pixel.Skimmia
Can also use hex color codes for the same result: convert test.png -transparent "#ffffff" transparent.pngLanthorn
See https://mcmap.net/q/145157/-imagemagick-extend-canvas-with-transparent-background to ensure the background is transparent (order of args)Metabolic
C
111

I had the same problem: it had to remove white background from a jpg/png image format using ImageMagick.

What worked for me was:

  1. Convert image format to png:

    convert input.jpg input.png
    
  2. convert input.png -fuzz 2% -transparent white output.png
    
Cohlier answered 10/5, 2013 at 11:19 Comment(4)
This is good, to have a smoother edge between transparent background and opaque foreground. If you convert noisy icons in JPG to PNG, and want to add transparency, you can also add some median filtering: mogrify -format png -median 2 -fuzz 5% -transparent white ico_*.jpgWestleigh
Adding -alpha off was the key for meSymphonize
Someone please tag this as the correct answer?Leonardo
Note that the order of the arguments is important. I had -fuzz after -transparent and it didn't affect the color. It must come before -transparent to affect it.Salify
S
76

Solution

color=$( convert filename.png -format "%[pixel:p{0,0}]" info:- )
convert filename.png -alpha off -bordercolor $color -border 1 \
    \( +clone -fuzz 30% -fill none -floodfill +0+0 $color \
       -alpha extract -geometry 200% -blur 0x0.5 \
       -morphology erode square:1 -geometry 50% \) \
    -compose CopyOpacity -composite -shave 1 outputfilename.png

Explanation

This is rather a bit longer than the simple answers previously given, but it gives much better results: (1) The quality is superior due to antialiased alpha, and (2) only the background is removed as opposed to a single color. ("Background" is defined as approximately the same color as the top left pixel, using a floodfill from the picture edges.)

Additionally, the alpha channel is also eroded by half a pixel to avoid halos. Of course, ImageMagick's morphological operations don't (yet?) work at the subpixel level, so you can see I am blowing up the alpha channel to 200% before eroding.

Comparison of results

Here is a comparison of the simple approach ("-fuzz 2% -transparent white") versus my solution, when run on the ImageMagick logo. I've flattened both transparent images onto a saddle brown background to make the differences apparent (click for originals).

The simple replacement of white as transparent doesn't always work Antialiased alphachannel and floodfill looks much better

Notice how the Wizard's beard has disappeared in the simple approach. Compare the edges of the Wizard to see how antialiased alpha helps the figure blend smoothly into the background.

Of course, I completely admit there are times when you may wish to use the simpler solution. (For example: It's a heck of a lot easier to remember and if you're converting to GIF, you're limited to 1-bit alpha anyhow.)

mktrans shell script

Since it's unlikely you'll want to type this command repeatedly, I recommend wrapping it in a script. You can download a BASH shell script from github which performs my suggested solution. It can be run on multiple files in a directory and includes helpful comments in case you want to tweak things.

bg_removal script

By the way, ImageMagick actually comes with a script called "bg_removal" which uses floodfill in a similar manner as my solution. However, the results are not great because it still uses 1-bit alpha. Also, the bg_removal script runs slower and is a little bit trickier to use (it requires you to specify two different fuzz values). Here's an example of the output from bg_removal.

The bg_removal script: has beard, but lacks antialiasing

Skimmia answered 14/6, 2017 at 10:57 Comment(7)
I needed to modify the fuzz to 2 %, because the image contains a white machine with white background. And although this is not 100 % perfect, it is the best solution I found as I don’t want to do it manualy in gimp or whatever. :)Mccullough
@hackerb9, how do I enter this command in my shell (PowerShell)? I don't know how to structure the call without syntax errors (I think it's the backslashes). Any idea?Limulus
Also, I have images with colored pixels in the top left corner of the image that I want to keep. Is there a way to just specify white as my background without breaking the quality of the script?Limulus
Hi Jay. I haven't used powershell in a long time. You can try typing the command as one long line without any backslashes. Personally, I suggest looking into finding a Unix system. Microsoft's WSL, Windows Subsystem for Linux, might work.Skimmia
Jay: for picking a different pixel than the upper lefthand corner, you can use the mktrans script I linked above as mktrans -p x,y. Note that it uses bash, not powershell.Skimmia
on backgroung with uniform slowly changing, repeating the command to extend the process does not seem to work. Try with this image: thefederalist.com/wp-content/uploads/2019/05/…Supersede
@Supersede For an image with such low contrast between the figures and the background, I'd recommend using a tool like rembg which is a neural net trained to recognize human shapes (see gist.github.com/hackerb9/f7e9213cad009996c1e325921c8fb180 for example output).Skimmia
L
38

This works for me:

convert original.png -fuzz 10% -transparent white transparent.png

where the smaller the fuzz %, the closer to true white or conversely, the larger the %, the more variation from white is allowed to become transparent

Loadstar answered 1/7, 2014 at 13:7 Comment(3)
Wow! This is exactly what I needed! before: i.imgur.com/2Rd7w1N.png, after: i.imgur.com/4RTYygo.pngEditorial
It's not working perfectly because it's unable to handle images with white color and white background. like trump photos.Corticate
For white on white, try using the flood fill solution I posted above. Or use my mktrans shell script: github.com/hackerb9/mktransSkimmia
S
18

You can Use this to make the background transparent

convert test.png -background rgba(0,0,0,0) test1.png

The above gives the prefect transparent background

Sadoff answered 29/1, 2014 at 7:9 Comment(2)
The shell might require some quoting of the (): convert more-icon.png -gravity center -background 'rgba(0,0,0,0)' -extent 27x27 new-more-icon.pngDemicanton
this is best + handles cases where the source image may have white areas (or whatever color you use in -transparent SOMECOLORElseelset
D
11

Using ImageMagick, this is very similar to hackerb9 code and result, but is a little simpler command line. It does assume that the top left pixel is the background color. I just flood fill the background with transparency, then select the alpha channel and blur it and remove half of the blurred area using -level 50x100%. Then turn back on all the channels and flatten it against the brown color. The -blur 0x1 -level 50x100% acts to antialias the boundaries of the alpha channel transparency. You can adjust the fuzz value, blur amount and the -level 50% value to change the degree of antialiasing.

convert logo: -fuzz 25% -fill none -draw "matte 0,0 floodfill" -channel alpha -blur 0x1 -level 50x100% +channel -background saddlebrown -flatten result.jpg

enter image description here

Diathesis answered 14/6, 2017 at 16:42 Comment(6)
Nice. I like that you got the gist of it in a succinct line. This is similar to one of my intermediate steps as I was writing the script. I decided against it because (a) it loses too many sharp details, (b) I wanted to make the color selection obvious so it could easily be changed, and (c) I wanted to floodfill from all the edges, not just the top-left corner. (There may be other things I'm forgetting right now).Skimmia
P.S. I'm going to take a wild guess that "fmw" stands for Fred M. Weinhaus. If so, greetings, Dr. Weinhaus! To anybody who doesn't know who he is, he wrote some of the seminal research in computer graphics starting in the 1970's. Everyone should check out his amazing conucopia of ImageMagick shell scripts at fmwconcepts.com/imagemagick.Skimmia
@hackerb9: Yes, that is me. Do we know each other? Send me an email if you would like. My email address is on my web page you linked.Diathesis
Just to say: StackOverflow at its finest you were both incredibly helpful to me.Ravishing
"The drawing primitive matte was replaced by alpha in ImageMagick 7"Bearwood
@Josh Diel. That is correct, but you need to replace convert with magick also in Imagemagick 7Diathesis
A
5

If you want to control the level of transparency you can use rgba. where a is the alpha. 0 for transparent and 1 for opaque. Make sure that final output file must have .png extension for transparency.

convert 
  test.png 
    -channel rgba 
    -matte 
    -fuzz 40% 
    -fill "rgba(255,255,255,0.5)" 
    -opaque "rgb(255,255,255)" 
       semi_transparent.png
Alroy answered 23/1, 2015 at 19:52 Comment(0)
D
1

Yep. Had this same problem too. Here's the command I ran and it worked perfectly: convert transparent-img1.png transparent-img2.png transparent-img3.png -channel Alpha favicon.ico

Dugong answered 14/10, 2015 at 20:36 Comment(1)
It doesn't work in my case - I'm using splice. Your solution simply adds white areas like most of the answers.Fluxmeter

© 2022 - 2024 — McMap. All rights reserved.