Extract equivalent RGB without transparency from PNG with alpha channel

8 views (last 30 days)
FM
FM on 5 Jul 2021
Edited: FM on 6 Jul 2021
I used the "imread" (https://www.mathworks.com/help/matlab/ref/imread.html#btnczv9-1-transparency) function to read a PNG image. I found that the RGB did not all approach 255 in white regions of the image. It turns out that I also needed to read the per-pixel transparency (https://www.mathworks.com/help/matlab/ref/imread.html#btnczv9-1-transparency) data from the PNG file. From a heatmap of the transparency data, I found that it was zero in the white parts, which means full transparency (https://www.w3.org/TR/PNG-DataRep.html).
[im2png,cmap,xparncy]=imread('image2.png');
hm=heatmap(xparncy,'GridVisible','off');
The fact that this shows as white means that the assumed backdrop for the image is pure white.
How do I save this image as PNG *without* alpha channel? I want the pixels where transparency/alpha was 255 as completely determined by the RGB planes. For pixels with less than 225 transparency/alpha, I want the RGB values to be modified to as to mimic the corresponding transparency, *assuming* a white background.
  2 Comments
FM
FM on 6 Jul 2021
I suspect that "between 255 and 255" is a typo?
255 is fully opaque, so the RGB planes completely determine the look.
Transparency < 255 assumes some mixing with the (assumed) white backdrop, and I would want the RGB values to be modified to mimic this so that the backdrop and associated transparency can be dispensed with.

Sign in to comment.

Accepted Answer

Yongjian Feng
Yongjian Feng on 5 Jul 2021
For each color channel, try
re = (1-alpha)*foreground + alpha*background.
Since here background is white, so each channel, background is just 255.
  1 Comment
FM
FM on 6 Jul 2021
Thanks, Yongjian. I arrived at a relationship that is effectively the same:
% Effective pixel RGB without transparency
Peff = p + ( w - p ) ( 1 - alpha/255 )
Here, p is the per-pixel raw data [R G B] and w=[255 255 255].
I'm now off to examine Walter Roberson's code....

Sign in to comment.

More Answers (1)

Walter Roberson
Walter Roberson on 6 Jul 2021
[im2png,cmap,xparncy]=imread('image2.png');
if ~isempty(cmap)
im2png = ind2rgb(im2png, cmap);
end
alpha = repmat(double(xparncy)/255, 1, 1, 3);
white = 255;
im_corrected = uint8(double(im2png) .* alpha + (1-alpha) .* white);
imwrite(im_corrected, 'image2_corrected.png');
  1 Comment
FM
FM on 6 Jul 2021
Thanks, Walter! This matches what I got prompted to derive by your question about how to handle other transparency values. AFTERNOTE: Unfortunately, I can only accept one answer. Both your answer and Yongjian's answer are helpful for different reasons. I wish I can mark both as the answer.
Here is what I boiled the code down to:
[im2png,cmap,xparncy]=imread('image2.png');
% cmap is empty
% Element-by-element operations rely on automatic singleton
% extension to match array sizes
alpha = double(xparncy)/255;
% "imshow" requires "double" RGB values to span interval [0,1]
im2noX = rescale( alpha.*double(im2png) + (1-alpha)*255 );
imshow(im2noX)
% "uint8" is fine without rescaling
im2noX = uint8( alpha.*double(im2png) + (1-alpha)*255 );
imshow(im2noX)

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by