Skip to content

Commit

Permalink
Support loading CMapItemImage version 2
Browse files Browse the repository at this point in the history
This map item version adds the `m_Format` field, which specifies the image format for embedded images. The default value is `CImageInfo::FORMAT_RGBA` for map items of the previous version.
  • Loading branch information
Robyt3 committed Jul 16, 2023
1 parent 4ae0928 commit 54df98b
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 36 deletions.
9 changes: 6 additions & 3 deletions src/game/client/components/mapimages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,21 +105,24 @@ void CMapImages::OnMapLoadImpl(class CLayers *pLayers, IMap *pMap)
for(int i = 0; i < m_Count; i++)
{
int LoadFlag = (((m_aTextureUsedByTileOrQuadLayerFlag[i] & 1) != 0) ? TextureLoadFlag : 0) | (((m_aTextureUsedByTileOrQuadLayerFlag[i] & 2) != 0) ? 0 : (Graphics()->IsTileBufferingEnabled() ? IGraphics::TEXLOAD_NO_2D_TEXTURE : 0));
CMapItemImage *pImg = (CMapItemImage *)pMap->GetItem(Start + i);
if(pImg->m_External)
const CMapItemImage_v2 *pImg = (CMapItemImage_v2 *)pMap->GetItem(Start + i);
const int Format = pImg->m_Version < CMapItemImage_v2::CURRENT_VERSION ? CImageInfo::FORMAT_RGBA : pImg->m_Format;
if(pImg->m_External || (Format != CImageInfo::FORMAT_RGB && Format != CImageInfo::FORMAT_RGBA))
{
char aPath[IO_MAX_PATH_LENGTH];
char *pName = (char *)pMap->GetData(pImg->m_ImageName);
str_format(aPath, sizeof(aPath), "mapres/%s.png", pName);
m_aTextures[i] = Graphics()->LoadTexture(aPath, IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, LoadFlag);
pMap->UnloadData(pImg->m_ImageName);
}
else
{
void *pData = pMap->GetData(pImg->m_ImageData);
char *pName = (char *)pMap->GetData(pImg->m_ImageName);
char aTexName[128];
str_format(aTexName, sizeof(aTexName), "%s %s", "embedded:", pName);
m_aTextures[i] = Graphics()->LoadTextureRaw(pImg->m_Width, pImg->m_Height, CImageInfo::FORMAT_RGBA, pData, CImageInfo::FORMAT_RGBA, LoadFlag, aTexName);
m_aTextures[i] = Graphics()->LoadTextureRaw(pImg->m_Width, pImg->m_Height, Format, pData, CImageInfo::FORMAT_RGBA, LoadFlag, aTexName);
pMap->UnloadData(pImg->m_ImageName);
pMap->UnloadData(pImg->m_ImageData);
}
}
Expand Down
11 changes: 7 additions & 4 deletions src/game/editor/io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,16 @@ bool CEditorMap::Save(const char *pFileName)
pImg->AnalyseTileFlags();

CMapItemImage Item;
Item.m_Version = 1;
Item.m_Version = CMapItemImage::CURRENT_VERSION;

Item.m_Width = pImg->m_Width;
Item.m_Height = pImg->m_Height;
Item.m_External = pImg->m_External;
Item.m_ImageName = df.AddData(str_length(pImg->m_aName) + 1, pImg->m_aName);
if(pImg->m_External)
{
Item.m_ImageData = -1;
}
else
{
if(pImg->m_Format == CImageInfo::FORMAT_RGB)
Expand Down Expand Up @@ -512,14 +514,15 @@ bool CEditorMap::Load(const char *pFileName, int StorageType, const std::functio
DataFile.GetType(MAPITEMTYPE_IMAGE, &Start, &Num);
for(int i = 0; i < Num; i++)
{
CMapItemImage *pItem = (CMapItemImage *)DataFile.GetItem(Start + i);
CMapItemImage_v2 *pItem = (CMapItemImage_v2 *)DataFile.GetItem(Start + i);
char *pName = (char *)DataFile.GetData(pItem->m_ImageName);

// copy base info
CEditorImage *pImg = new CEditorImage(m_pEditor);
pImg->m_External = pItem->m_External;

if(pItem->m_External)
const int Format = pItem->m_Version < CMapItemImage_v2::CURRENT_VERSION ? CImageInfo::FORMAT_RGBA : pItem->m_Format;
if(pImg->m_External || (Format != CImageInfo::FORMAT_RGB && Format != CImageInfo::FORMAT_RGBA))
{
char aBuf[IO_MAX_PATH_LENGTH];
str_format(aBuf, sizeof(aBuf), "mapres/%s.png", pName);
Expand All @@ -541,7 +544,7 @@ bool CEditorMap::Load(const char *pFileName, int StorageType, const std::functio
{
pImg->m_Width = pItem->m_Width;
pImg->m_Height = pItem->m_Height;
pImg->m_Format = CImageInfo::FORMAT_RGBA;
pImg->m_Format = Format;

// copy image data
void *pData = DataFile.GetData(pItem->m_ImageData);
Expand Down
19 changes: 18 additions & 1 deletion src/game/mapitems.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,13 @@ struct CMapItemInfoSettings : CMapItemInfo
int m_Settings;
};

struct CMapItemImage
struct CMapItemImage_v1
{
enum
{
CURRENT_VERSION = 1,
};

int m_Version;
int m_Width;
int m_Height;
Expand All @@ -262,6 +267,18 @@ struct CMapItemImage
int m_ImageData;
};

struct CMapItemImage_v2 : public CMapItemImage_v1
{
enum
{
CURRENT_VERSION = 2,
};

int m_Format; // Default before this version is CImageInfo::FORMAT_RGBA
};

typedef CMapItemImage_v1 CMapItemImage;

struct CMapItemGroup_v1
{
int m_Version;
Expand Down
30 changes: 18 additions & 12 deletions src/tools/map_convert_07.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,24 +96,25 @@ bool CheckImageDimensions(void *pLayerItem, int LayerType, const char *pFilename
return false;
}

void *ReplaceImageItem(void *pItem, int Type, CMapItemImage *pNewImgItem)
void *ReplaceImageItem(CMapItemImage *pImgItem, CMapItemImage *pNewImgItem)
{
if(Type != MAPITEMTYPE_IMAGE)
return pItem;

CMapItemImage *pImgItem = (CMapItemImage *)pItem;

if(!pImgItem->m_External)
return pItem;
return pImgItem;

char *pName = (char *)g_DataReader.GetData(pImgItem->m_ImageName);
dbg_msg("map_convert_07", "embedding image '%s'", pName);

CImageInfo ImgInfo;
char aStr[64];
char aStr[IO_MAX_PATH_LENGTH];
str_format(aStr, sizeof(aStr), "data/mapres/%s.png", pName);
if(!LoadPNG(&ImgInfo, aStr))
return pItem; // keep as external if we don't have a mapres to replace
return pImgItem; // keep as external if we don't have a mapres to replace

if(ImgInfo.m_Format != CImageInfo::FORMAT_RGBA)
{
dbg_msg("map_convert_07", "image '%s' is not in RGBA format", aStr);
return pImgItem;
}

*pNewImgItem = *pImgItem;

Expand Down Expand Up @@ -217,9 +218,14 @@ int main(int argc, const char **argv)
Success &= CheckImageDimensions(pItem, Type, pSourceFileName);

CMapItemImage NewImageItem;
pItem = ReplaceImageItem(pItem, Type, &NewImageItem);
if(!pItem)
return -1;
if(Type == MAPITEMTYPE_IMAGE)
{
pItem = ReplaceImageItem((CMapItemImage *)pItem, &NewImageItem);
if(!pItem)
return -1;
Size = sizeof(CMapItemImage);
NewImageItem.m_Version = CMapItemImage::CURRENT_VERSION;
}
g_DataWriter.AddItem(Type, ID, Size, pItem);
}

Expand Down
17 changes: 15 additions & 2 deletions src/tools/map_extract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <base/logger.h>
#include <base/system.h>
#include <engine/gfx/image_loader.h>
#include <engine/graphics.h>
#include <engine/shared/datafile.h>
#include <engine/storage.h>
#include <game/mapitems.h>
Expand Down Expand Up @@ -39,7 +40,7 @@ bool Process(IStorage *pStorage, const char *pMapName, const char *pPathSave)

for(int i = 0; i < Num; i++)
{
CMapItemImage *pItem = (CMapItemImage *)Reader.GetItem(Start + i);
CMapItemImage_v2 *pItem = (CMapItemImage_v2 *)Reader.GetItem(Start + i);
char *pName = (char *)Reader.GetData(pItem->m_ImageName);

if(pItem->m_External)
Expand All @@ -49,14 +50,26 @@ bool Process(IStorage *pStorage, const char *pMapName, const char *pPathSave)
str_format(aBuf, sizeof(aBuf), "%s/%s.png", pPathSave, pName);
dbg_msg("map_extract", "writing image: %s (%dx%d)", aBuf, pItem->m_Width, pItem->m_Height);

const int Format = pItem->m_Version < CMapItemImage_v2::CURRENT_VERSION ? CImageInfo::FORMAT_RGBA : pItem->m_Format;
EImageFormat OutputFormat;
if(Format == CImageInfo::FORMAT_RGBA)
OutputFormat = IMAGE_FORMAT_RGBA;
else if(Format == CImageInfo::FORMAT_RGB)
OutputFormat = IMAGE_FORMAT_RGB;
else
{
dbg_msg("map_extract", "ignoring image '%s' with unknown format %d", aBuf, Format);
continue;
}

// copy image data
IOHANDLE File = io_open(aBuf, IOFLAG_WRITE);
if(File)
{
TImageByteBuffer ByteBuffer;
SImageByteBuffer ImageByteBuffer(&ByteBuffer);

if(SavePNG(IMAGE_FORMAT_RGBA, (const uint8_t *)Reader.GetData(pItem->m_ImageData), ImageByteBuffer, pItem->m_Width, pItem->m_Height))
if(SavePNG(OutputFormat, (const uint8_t *)Reader.GetData(pItem->m_ImageData), ImageByteBuffer, pItem->m_Width, pItem->m_Height))
io_write(File, &ByteBuffer.front(), ByteBuffer.size());
io_close(File);
}
Expand Down
4 changes: 2 additions & 2 deletions src/tools/map_optimize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,8 @@ int main(int argc, const char **argv)
}
else if(Type == MAPITEMTYPE_IMAGE)
{
CMapItemImage *pImg = (CMapItemImage *)pPtr;
if(!pImg->m_External)
CMapItemImage_v2 *pImg = (CMapItemImage_v2 *)pPtr;
if(!pImg->m_External && pImg->m_Version < CMapItemImage_v2::CURRENT_VERSION)
{
SMapOptimizeItem Item;
Item.m_pImage = pImg;
Expand Down
31 changes: 19 additions & 12 deletions src/tools/map_replace_image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,34 +67,35 @@ int LoadPNG(CImageInfo *pImg, const char *pFilename)
return 1;
}

void *ReplaceImageItem(void *pItem, int Type, const char *pImgName, const char *pImgFile, CMapItemImage *pNewImgItem)
void *ReplaceImageItem(CMapItemImage *pImgItem, const char *pImgName, const char *pImgFile, CMapItemImage *pNewImgItem)
{
if(Type != MAPITEMTYPE_IMAGE)
return pItem;

CMapItemImage *pImgItem = (CMapItemImage *)pItem;
char *pName = (char *)g_DataReader.GetData(pImgItem->m_ImageName);

if(str_comp(pImgName, pName) != 0)
return pItem;
return pImgItem;

dbg_msg("map_replace_image", "found image '%s'", pImgName);

CImageInfo ImgInfo;
if(!LoadPNG(&ImgInfo, pImgFile))
return 0;

if(ImgInfo.m_Format != CImageInfo::FORMAT_RGBA)
{
dbg_msg("map_replace_image", "image '%s' is not in RGBA format", pImgName);
return 0;
}

*pNewImgItem = *pImgItem;

pNewImgItem->m_Width = ImgInfo.m_Width;
pNewImgItem->m_Height = ImgInfo.m_Height;
int PixelSize = ImgInfo.m_Format == CImageInfo::FORMAT_RGB ? 3 : 4;

g_NewNameID = pImgItem->m_ImageName;
IStorage::StripPathAndExtension(pImgFile, g_aNewName, sizeof(g_aNewName));
g_NewDataID = pImgItem->m_ImageData;
g_pNewData = ImgInfo.m_pData;
g_NewDataSize = ImgInfo.m_Width * ImgInfo.m_Height * PixelSize;
g_NewDataSize = ImgInfo.m_Width * ImgInfo.m_Height * 4;

return (void *)pNewImgItem;
}
Expand Down Expand Up @@ -148,12 +149,18 @@ int main(int argc, const char **argv)
if(Type == ITEMTYPE_EX)
continue;

int Size = g_DataReader.GetItemSize(Index);

CMapItemImage NewImageItem;
pItem = ReplaceImageItem(pItem, Type, pImageName, pImageFile, &NewImageItem);
if(!pItem)
return -1;
if(Type == MAPITEMTYPE_IMAGE)
{
pItem = ReplaceImageItem((CMapItemImage *)pItem, pImageName, pImageFile, &NewImageItem);
if(!pItem)
return -1;
Size = sizeof(CMapItemImage);
NewImageItem.m_Version = CMapItemImage::CURRENT_VERSION;
}

int Size = g_DataReader.GetItemSize(Index);
Writer.AddItem(Type, ID, Size, pItem);
}

Expand Down

0 comments on commit 54df98b

Please sign in to comment.