From 32e924063440c11ba586d6a39347b5cf8ff39f22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 10 Sep 2024 21:11:55 +0200 Subject: [PATCH] Fix editor crash when saving maps with RGB mapres Convert mapres to RGBA immediately when loading them, so the image data is always in RGBA format internally, instead of only converting when the map is saved (which was erroneously removed in #8670). This means the `cl_editor_dilate` setting will now also be applied to converted RGB images. --- src/engine/client/graphics_threaded.cpp | 2 +- src/engine/graphics.h | 2 + src/game/editor/editor.cpp | 51 ++++++++++++++++++------- src/game/editor/mapitems/map_io.cpp | 9 +++++ 4 files changed, 49 insertions(+), 15 deletions(-) diff --git a/src/engine/client/graphics_threaded.cpp b/src/engine/client/graphics_threaded.cpp index 63ea4d104..21e5687fe 100644 --- a/src/engine/client/graphics_threaded.cpp +++ b/src/engine/client/graphics_threaded.cpp @@ -300,7 +300,7 @@ void CGraphics_Threaded::UnloadTexture(CTextureHandle *pIndex) FreeTextureIndex(pIndex); } -static bool ConvertToRGBA(uint8_t *pDest, const CImageInfo &SrcImage) +bool ConvertToRGBA(uint8_t *pDest, const CImageInfo &SrcImage) { if(SrcImage.m_Format == CImageInfo::FORMAT_RGBA) { diff --git a/src/engine/graphics.h b/src/engine/graphics.h index 184e907e8..2528c0d79 100644 --- a/src/engine/graphics.h +++ b/src/engine/graphics.h @@ -124,6 +124,8 @@ public: } }; +bool ConvertToRGBA(uint8_t *pDest, const CImageInfo &SrcImage); + /* Structure: CVideoMode */ diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 86c525d0a..78538e45b 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -4384,7 +4384,7 @@ bool CEditor::ReplaceImage(const char *pFileName, int StorageType, bool CheckDup } } - CEditorImage ImgInfo(this); + CImageInfo ImgInfo; if(!Graphics()->LoadPng(ImgInfo, pFileName, StorageType)) { ShowFileDialogError("Failed to load image from file '%s'.", pFileName); @@ -4394,21 +4394,33 @@ bool CEditor::ReplaceImage(const char *pFileName, int StorageType, bool CheckDup std::shared_ptr pImg = m_Map.m_vpImages[m_SelectedImage]; Graphics()->UnloadTexture(&(pImg->m_Texture)); pImg->Free(); - *pImg = ImgInfo; + pImg->m_Width = ImgInfo.m_Width; + pImg->m_Height = ImgInfo.m_Height; + pImg->m_Format = ImgInfo.m_Format; + pImg->m_pData = ImgInfo.m_pData; str_copy(pImg->m_aName, aBuf); pImg->m_External = IsVanillaImage(pImg->m_aName); - if(!pImg->m_External && g_Config.m_ClEditorDilate == 1 && pImg->m_Format == CImageInfo::FORMAT_RGBA) + if(!pImg->m_External && pImg->m_Format != CImageInfo::FORMAT_RGBA) { - DilateImage(ImgInfo.m_pData, ImgInfo.m_Width, ImgInfo.m_Height); + uint8_t *pRgbaData = static_cast(malloc((size_t)pImg->m_Width * pImg->m_Height * CImageInfo::PixelSize(CImageInfo::FORMAT_RGBA))); + ConvertToRGBA(pRgbaData, *pImg); + free(pImg->m_pData); + pImg->m_pData = pRgbaData; + pImg->m_Format = CImageInfo::FORMAT_RGBA; + } + + if(!pImg->m_External && g_Config.m_ClEditorDilate == 1) + { + DilateImage(pImg->m_pData, pImg->m_Width, pImg->m_Height); } pImg->m_AutoMapper.Load(pImg->m_aName); int TextureLoadFlag = Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE; - if(ImgInfo.m_Width % 16 != 0 || ImgInfo.m_Height % 16 != 0) + if(pImg->m_Width % 16 != 0 || pImg->m_Height % 16 != 0) TextureLoadFlag = 0; - pImg->m_Texture = Graphics()->LoadTextureRaw(ImgInfo, TextureLoadFlag, pFileName); - ImgInfo.m_pData = nullptr; + pImg->m_Texture = Graphics()->LoadTextureRaw(*pImg, TextureLoadFlag, pFileName); + SortImages(); for(size_t i = 0; i < m_Map.m_vpImages.size(); ++i) { @@ -4447,7 +4459,7 @@ bool CEditor::AddImage(const char *pFileName, int StorageType, void *pUser) return false; } - CEditorImage ImgInfo(pEditor); + CImageInfo ImgInfo; if(!pEditor->Graphics()->LoadPng(ImgInfo, pFileName, StorageType)) { pEditor->ShowFileDialogError("Failed to load image from file '%s'.", pFileName); @@ -4455,19 +4467,30 @@ bool CEditor::AddImage(const char *pFileName, int StorageType, void *pUser) } std::shared_ptr pImg = std::make_shared(pEditor); - *pImg = ImgInfo; + pImg->m_Width = ImgInfo.m_Width; + pImg->m_Height = ImgInfo.m_Height; + pImg->m_Format = ImgInfo.m_Format; + pImg->m_pData = ImgInfo.m_pData; pImg->m_External = IsVanillaImage(aBuf); - if(!pImg->m_External && g_Config.m_ClEditorDilate == 1 && pImg->m_Format == CImageInfo::FORMAT_RGBA) + if(pImg->m_Format != CImageInfo::FORMAT_RGBA) { - DilateImage(ImgInfo.m_pData, ImgInfo.m_Width, ImgInfo.m_Height); + uint8_t *pRgbaData = static_cast(malloc((size_t)pImg->m_Width * pImg->m_Height * CImageInfo::PixelSize(CImageInfo::FORMAT_RGBA))); + ConvertToRGBA(pRgbaData, *pImg); + free(pImg->m_pData); + pImg->m_pData = pRgbaData; + pImg->m_Format = CImageInfo::FORMAT_RGBA; + } + + if(!pImg->m_External && g_Config.m_ClEditorDilate == 1) + { + DilateImage(pImg->m_pData, pImg->m_Width, pImg->m_Height); } int TextureLoadFlag = pEditor->Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE; - if(ImgInfo.m_Width % 16 != 0 || ImgInfo.m_Height % 16 != 0) + if(pImg->m_Width % 16 != 0 || pImg->m_Height % 16 != 0) TextureLoadFlag = 0; - pImg->m_Texture = pEditor->Graphics()->LoadTextureRaw(ImgInfo, TextureLoadFlag, pFileName); - ImgInfo.m_pData = nullptr; + pImg->m_Texture = pEditor->Graphics()->LoadTextureRaw(*pImg, TextureLoadFlag, pFileName); str_copy(pImg->m_aName, aBuf); pImg->m_AutoMapper.Load(pImg->m_aName); pEditor->m_Map.m_vpImages.push_back(pImg); diff --git a/src/game/editor/mapitems/map_io.cpp b/src/game/editor/mapitems/map_io.cpp index a3346b1a2..a834a3d99 100644 --- a/src/game/editor/mapitems/map_io.cpp +++ b/src/game/editor/mapitems/map_io.cpp @@ -509,6 +509,15 @@ bool CEditorMap::Load(const char *pFileName, int StorageType, const std::functio pImg->m_Height = ImgInfo.m_Height; pImg->m_Format = ImgInfo.m_Format; pImg->m_pData = ImgInfo.m_pData; + if(pImg->m_Format != CImageInfo::FORMAT_RGBA) + { + uint8_t *pRgbaData = static_cast(malloc((size_t)pImg->m_Width * pImg->m_Height * CImageInfo::PixelSize(CImageInfo::FORMAT_RGBA))); + ConvertToRGBA(pRgbaData, *pImg); + free(pImg->m_pData); + pImg->m_pData = pRgbaData; + pImg->m_Format = CImageInfo::FORMAT_RGBA; + } + int TextureLoadFlag = m_pEditor->Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE; if(ImgInfo.m_Width % 16 != 0 || ImgInfo.m_Height % 16 != 0) TextureLoadFlag = 0;