# Extract equivalent RGB without transparency from PNG with alpha channel

14 views (last 30 days)
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).
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 CommentsShowHide 1 older comment
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.

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.
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....

Walter Roberson on 6 Jul 2021
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');
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:
% 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)

R2019a

### Community Treasure Hunt

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

Start Hunting!