Fix function to use surface format data

In Windows and macOs the underlying surfaces have different color
components order without this fix images are displayed with incorrect
colors
This commit is contained in:
Martín Capello 2024-10-14 15:02:44 -03:00
parent 0bf62c4545
commit da60d14b11
2 changed files with 36 additions and 7 deletions

View File

@ -20,6 +20,24 @@ namespace app {
using namespace doc;
uint32_t convert_color_to_image(
gfx::Color c,
const os::SurfaceFormatData* fd)
{
uint8_t r = ((c & fd->redMask) >> fd->redShift);
uint8_t g = ((c & fd->greenMask) >> fd->greenShift);
uint8_t b = ((c & fd->blueMask) >> fd->blueShift);
uint8_t a = ((c & fd->alphaMask) >> fd->alphaShift);
if (fd->pixelAlpha == os::PixelAlpha::kPremultiplied) {
r = r * 255 / a;
g = g * 255 / a;
b = b * 255 / a;
}
return rgba(r, g, b, a);
}
// TODO: This implementation has a lot of room for improvement, I made the bare
// minimum to make it work. Right now it only supports converting RGBA surfaces,
// other kind of surfaces won't be converted to an image as expected.
@ -41,12 +59,15 @@ void convert_surface_to_image(
image.reset(Image::create(PixelFormat::IMAGE_RGB, w, h));
for (int v=0; v<h; ++v, ++src_y) {
uint8_t* src_address = surface->getData(0, v);
uint8_t* dst_address = image->getPixelAddress(src_x, src_y);
std::copy(src_address,
src_address + RgbTraits::bytes_per_pixel * w,
dst_address);
os::SurfaceFormatData fd;
surface->getFormat(&fd);
for (int v=0; v<h; ++v) {
for (int u=0; u<w; ++u) {
uint32_t* c = (uint32_t*)(surface->getData(u, v));
image->putPixel(src_x + u,
src_y + v, convert_color_to_image(*c, &fd));
}
}
}

View File

@ -14,6 +14,14 @@
namespace app {
namespace util {
static WEBP_CSP_MODE colorMode()
{
auto surface = os::instance()->makeSurface(1, 1);
os::SurfaceFormatData fd;
surface->getFormat(&fd);
return (fd.redShift == 0 ? MODE_RGBA : MODE_BGRA);
}
os::SurfaceRef decode_webp(const uint8_t* buf, uint32_t len)
{
// I've considered using the FileFormatsManager here but we don't have a file
@ -26,7 +34,7 @@ os::SurfaceRef decode_webp(const uint8_t* buf, uint32_t len)
WebPAnimDecoderOptions dec_options;
WebPAnimDecoderOptionsInit(&dec_options);
dec_options.color_mode = MODE_RGBA;
dec_options.color_mode = colorMode();
WebPAnimDecoder* dec = WebPAnimDecoderNew(&webp_data, &dec_options);
if (dec == nullptr) {