From dab88177dd61864fdddf27f22ed4c9057db790f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Fri, 15 Sep 2023 18:26:05 +0200 Subject: [PATCH] Fix images using indexed color palette not being loadable The wrong color channel count was being used for loading images that use an indexed color palette, which was causing the loading to fail with the error "bytes in row incorrect". Now the correct color channel count is retrieved using the libpng API. Closes #7157. --- src/engine/gfx/image_loader.cpp | 88 ++++++++++++++------------------- 1 file changed, 36 insertions(+), 52 deletions(-) diff --git a/src/engine/gfx/image_loader.cpp b/src/engine/gfx/image_loader.cpp index bad7d9c69..76ac23205 100644 --- a/src/engine/gfx/image_loader.cpp +++ b/src/engine/gfx/image_loader.cpp @@ -53,27 +53,19 @@ static void ReadDataFromLoadedBytes(png_structp pPNGStruct, png_bytep pOutBytes, } } -static int LibPNGGetColorChannelCount(int LibPNGColorType) +static EImageFormat LibPNGGetImageFormat(int ColorChannelCount) { - if(LibPNGColorType == PNG_COLOR_TYPE_GRAY) - return 1; - else if(LibPNGColorType == PNG_COLOR_TYPE_PALETTE || LibPNGColorType == PNG_COLOR_TYPE_RGB) - return 3; - else if(LibPNGColorType == PNG_COLOR_TYPE_RGBA) - return 4; - - return 4; -} - -static void LibPNGSetImageFormat(EImageFormat &ImageFormat, int LibPNGColorType) -{ - ImageFormat = IMAGE_FORMAT_RGBA; - if(LibPNGColorType == PNG_COLOR_TYPE_GRAY) - ImageFormat = IMAGE_FORMAT_R; - else if(LibPNGColorType == PNG_COLOR_TYPE_PALETTE || LibPNGColorType == PNG_COLOR_TYPE_RGB) - ImageFormat = IMAGE_FORMAT_RGB; - else if(LibPNGColorType == PNG_COLOR_TYPE_RGBA) - ImageFormat = IMAGE_FORMAT_RGBA; + switch(ColorChannelCount) + { + case 1: + return IMAGE_FORMAT_R; + case 3: + return IMAGE_FORMAT_RGB; + case 4: + return IMAGE_FORMAT_RGBA; + default: + return IMAGE_FORMAT_RGBA; + } } static void LibPNGDeleteReadStruct(png_structp pPNGStruct, png_infop pPNGInfo) @@ -225,47 +217,39 @@ bool LoadPNG(SImageByteBuffer &ByteLoader, const char *pFileName, int &PngliteIn png_read_update_info(pPNGStruct, pPNGInfo); - const int ColorChannelCount = LibPNGGetColorChannelCount(ColorType); + const int ColorChannelCount = png_get_channels(pPNGStruct, pPNGInfo); const int BytesInRow = png_get_rowbytes(pPNGStruct, pPNGInfo); + dbg_assert(BytesInRow == Width * ColorChannelCount, "bytes in row incorrect."); - if(BytesInRow == Width * ColorChannelCount) + pRowPointers = new png_bytep[Height]; + for(int y = 0; y < Height; ++y) { - pRowPointers = new png_bytep[Height]; - for(int y = 0; y < Height; ++y) - { - pRowPointers[y] = new png_byte[BytesInRow]; - } - - png_read_image(pPNGStruct, pRowPointers); - - if(ByteLoader.m_Err == 0) - pImageBuff = (uint8_t *)malloc((size_t)Height * (size_t)Width * (size_t)ColorChannelCount * sizeof(uint8_t)); - - for(int i = 0; i < Height; ++i) - { - if(ByteLoader.m_Err == 0) - mem_copy(&pImageBuff[i * BytesInRow], pRowPointers[i], BytesInRow); - delete[] pRowPointers[i]; - } - delete[] pRowPointers; - pRowPointers = nullptr; - - if(ByteLoader.m_Err != 0) - { - LibPNGDeleteReadStruct(pPNGStruct, pPNGInfo); - dbg_msg("png", "byte loader error."); - return false; - } - - LibPNGSetImageFormat(ImageFormat, ColorType); + pRowPointers[y] = new png_byte[BytesInRow]; } - else + + png_read_image(pPNGStruct, pRowPointers); + + if(ByteLoader.m_Err == 0) + pImageBuff = (uint8_t *)malloc((size_t)Height * (size_t)Width * (size_t)ColorChannelCount * sizeof(uint8_t)); + + for(int i = 0; i < Height; ++i) + { + if(ByteLoader.m_Err == 0) + mem_copy(&pImageBuff[i * BytesInRow], pRowPointers[i], BytesInRow); + delete[] pRowPointers[i]; + } + delete[] pRowPointers; + pRowPointers = nullptr; + + if(ByteLoader.m_Err != 0) { LibPNGDeleteReadStruct(pPNGStruct, pPNGInfo); - dbg_msg("png", "bytes in row incorrect."); + dbg_msg("png", "byte loader error."); return false; } + ImageFormat = LibPNGGetImageFormat(ColorChannelCount); + png_destroy_info_struct(pPNGStruct, &pPNGInfo); png_destroy_read_struct(&pPNGStruct, nullptr, nullptr);