Skip to content

Commit

Permalink
ax::Image converts gray + alpha PNGs to RGBA. (#2230)
Browse files Browse the repository at this point in the history
Prior to this commit these textures where mapped to PixelFormat::RG8
textures. This did not work well as some textures, especially
monochrome black + transparency, were displayed as green +
transparency. This commit instead converts the image to RGBA using
libpng's API.
  • Loading branch information
j-jorge authored Nov 8, 2024
1 parent f03efb8 commit c12cf15
Showing 1 changed file with 12 additions and 22 deletions.
34 changes: 12 additions & 22 deletions core/platform/Image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1221,6 +1221,11 @@ bool Image::initWithPngData(uint8_t* data, ssize_t dataLen)
bit_depth = 8;
png_set_expand_gray_1_2_4_to_8(png_ptr);
}
// Expand gray + alpha to RGBA.
if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
{
png_set_gray_to_rgb(png_ptr);
}
// expand any tRNS chunk data into a full alpha channel
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
{
Expand All @@ -1246,9 +1251,6 @@ bool Image::initWithPngData(uint8_t* data, ssize_t dataLen)
case PNG_COLOR_TYPE_GRAY:
_pixelFormat = backend::PixelFormat::R8;
break;
case PNG_COLOR_TYPE_GRAY_ALPHA:
_pixelFormat = backend::PixelFormat::RG8;
break;
case PNG_COLOR_TYPE_RGB:
_pixelFormat = backend::PixelFormat::RGB8;
break;
Expand Down Expand Up @@ -1285,7 +1287,7 @@ bool Image::initWithPngData(uint8_t* data, ssize_t dataLen)
png_read_end(png_ptr, nullptr);

// premultiplied alpha for RGBA8888
if ((color_type == PNG_COLOR_TYPE_RGB_ALPHA) || (color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
{
if (PNG_PREMULTIPLIED_ALPHA_ENABLED)
{
Expand Down Expand Up @@ -2588,26 +2590,14 @@ bool Image::saveImageToJPG(std::string_view filePath)
void Image::premultiplyAlpha()
{
#if AX_ENABLE_PREMULTIPLIED_ALPHA
AXASSERT((_pixelFormat == backend::PixelFormat::RGBA8)
|| (_pixelFormat == backend::PixelFormat::RG8),
"The pixel format should be RGBA8888 or RG88.");
AXASSERT(_pixelFormat == backend::PixelFormat::RGBA8,
"The pixel format should be RGBA8888.");

if (_pixelFormat == backend::PixelFormat::RGBA8) {
unsigned int* fourBytes = (unsigned int*)_data;
for (int i = 0; i < _width * _height; i++)
{
uint8_t* p = _data + i * 4;
fourBytes[i] = AX_RGB_PREMULTIPLY_ALPHA(p[0], p[1], p[2], p[3]);
}
}
else
unsigned int* fourBytes = (unsigned int*)_data;
for (int i = 0; i < _width * _height; i++)
{
uint16_t* twoBytes = (uint16_t*)_data;
for (int i = 0; i < _width * _height; i++)
{
uint8_t* p = _data + i * 2;
twoBytes[i] = ((p[0] * p[1] + 1) >> 8) | (p[1] << 8);
}
uint8_t* p = _data + i * 4;
fourBytes[i] = AX_RGB_PREMULTIPLY_ALPHA(p[0], p[1], p[2], p[3]);
}

_hasPremultipliedAlpha = true;
Expand Down

0 comments on commit c12cf15

Please sign in to comment.