I have a 4-channel image (RGBA). I want to reduce its channel count from 4 to 3.

The method I am using currently is to Right click and Save as a .png file. After that when I Import it in Mathematica, the channel count is reduced to 3. Is there a more elegant way to do that?

Note: RemoveAlphaChannel[] function won't work. Because that will change the appearance of the original image (see the example below).

This is a 4-channel picture from ref / AlphaChannel:

4-channel picture

 img = Import @ "https://i.stack.imgur.com/XvzDc.png"

This is the 3-channel picture which is what I want:

3-channel picture

If I use RemoveAlphaChannel[], I will get this picture instead:

Picture after RemoveAlphaChannel

  • 3
    $\begingroup$ does RemoveAlphaChannel[img, White] not work for you? it does give 3-channel image ( ImageChannels@RemoveAlphaChannel[img, White] is 3). $\endgroup$ – kglr Jan 24 '19 at 7:26
  • $\begingroup$ @kglr Yes it works for that situation. It's amazing, thank you. $\endgroup$ – WW00WW Jan 24 '19 at 7:57

The second example from RemoveAlphaChannel:

  • Remove opacity by blending with a white background:

img2 = RemoveAlphaChannel[img, White]

enter image description here

ImageChannels /@ {img, img2}

{4, 3}

ColorSeparate /@ {img, img2} // Grid

enter image description here

Row[{Labeled[Framed@AlphaChannel@img, "img", Top], 
     Labeled[Framed@AlphaChannel@img2, "img2", Top]}]

enter image description here

  • $\begingroup$ Thank you very much @kglr. I wonder if RemoveAlphaChannel[#, White]& is universal. If it also works for various alpha channels. (I've tried some pictures with different alpha channels and it works, but I am still not sure whether it works for all the cases...) $\endgroup$ – WW00WW Jan 24 '19 at 7:54
  • $\begingroup$ @VoldikSS, I am not sure if it works for all cases. $\endgroup$ – kglr Jan 24 '19 at 8:04

@kglr 's solution is very convenient and powerful. However RemoveAlphaChannel[#, colorname]& does not work for all cases. So I spent some time searching in the web forimage channels andfound the principle of the alpha channel.

Based on that, I get the following solution which can be used for other cases(different images with different alpha channels).

reduceImageChannels[img_] :=
    Map[(#*#[[4]] + 1*(1 - #[[4]])) &,
     (Flatten[ImageData@img, 1])]] // Partition[#, First@ImageDimensions[img]] & // Image

Let's check it,

img = Import @ "https://i.stack.imgur.com/XvzDc.png"

enter image description here

img2 = reduceImageChannels@img

enter image description here



It given me the image exactly what I want!

  • $\begingroup$ I haven't ran the code, but Most gives all but the last element of a list. And what is 120 doing there, is that something to do with the ImageDimensions? $\endgroup$ – SPPearce Jan 26 '19 at 13:42
  • $\begingroup$ Thank you for the suggestion! I will replace Drop[#, {4}] & with Most. You are right, ImageDimensions@img returns {120,120} $\endgroup$ – WW00WW Jan 26 '19 at 13:45
  • $\begingroup$ you can also use reduceImageChannels2[img_] := Map[Most[#*#[[4]] + 1*(1 - #[[4]])] &, ImageData@img, {2}] $\endgroup$ – kglr Jan 26 '19 at 13:56
  • $\begingroup$ @kglr Thanks, it's much more elegant! I even forgot the Map's levelspec option... $\endgroup$ – WW00WW Jan 26 '19 at 13:59
  • 1
    $\begingroup$ for an arbitrary color in the second argument,say Orange, RemoveAlphaChannel[img, Orange] and ImageApply[Most[#]*#[[4]] + {1, 0.5, 0}*(1 - #[[4]]) &, img] gives the same image as ImageApply[Most[#]*#[[4]] + {1, 0.5, 0}*(1 - #[[4]]) &, img] (that is, Max@(ImageData@ ImageApply[Most[#]*#[[4]] + {1, 0.5, 0}*(1 - #[[4]]) &, img] - ImageData[RemoveAlphaChannel[img, Orange]]) .) Note that Orange is RGBColor[1,.5,0]. $\endgroup$ – kglr Jan 26 '19 at 14:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.