You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
This represents UE4/Main @18073326, Release-5.0 @18081140 and Dev-PerfTest @18045971 [CL 18081471 by aurel cordonnier in ue5-release-engine-test branch]
253 lines
10 KiB
C++
253 lines
10 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "LandscapeFileFormatPng.h"
|
|
#include "Misc/FileHelper.h"
|
|
#include "Modules/ModuleManager.h"
|
|
#include "IImageWrapper.h"
|
|
#include "IImageWrapperModule.h"
|
|
#include "Algo/Transform.h"
|
|
|
|
|
|
#define LOCTEXT_NAMESPACE "LandscapeEditor.NewLandscape"
|
|
|
|
|
|
FLandscapeHeightmapFileFormat_Png::FLandscapeHeightmapFileFormat_Png()
|
|
{
|
|
FileTypeInfo.Description = LOCTEXT("FileFormatPng_HeightmapDesc", "Heightmap .png files");
|
|
FileTypeInfo.Extensions.Add(".png");
|
|
FileTypeInfo.bSupportsExport = true;
|
|
}
|
|
|
|
FLandscapeFileInfo FLandscapeHeightmapFileFormat_Png::Validate(const TCHAR* HeightmapFilename, FName LayerName) const
|
|
{
|
|
FLandscapeFileInfo Result;
|
|
|
|
TArray64<uint8> ImportData;
|
|
if (!FFileHelper::LoadFileToArray(ImportData, HeightmapFilename, FILEREAD_Silent))
|
|
{
|
|
Result.ResultCode = ELandscapeImportResult::Error;
|
|
Result.ErrorMessage = LOCTEXT("Import_HeightmapFileReadError", "Error reading heightmap file");
|
|
}
|
|
else
|
|
{
|
|
IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>("ImageWrapper");
|
|
TSharedPtr<IImageWrapper> ImageWrapper = ImageWrapperModule.CreateImageWrapper(EImageFormat::PNG);
|
|
|
|
if (!ImageWrapper->SetCompressed(ImportData.GetData(), ImportData.Num()) || ImageWrapper->GetWidth() <= 0 || ImageWrapper->GetHeight() <= 0)
|
|
{
|
|
Result.ResultCode = ELandscapeImportResult::Error;
|
|
Result.ErrorMessage = LOCTEXT("Import_HeightmapFileCorruptPng", "The heightmap file cannot be read (corrupt png?)");
|
|
}
|
|
else
|
|
{
|
|
if (ImageWrapper->GetFormat() != ERGBFormat::Gray)
|
|
{
|
|
Result.ResultCode = ELandscapeImportResult::Warning;
|
|
Result.ErrorMessage = LOCTEXT("Import_HeightmapFileColorPng", "The imported layer is not Grayscale. Results in-Editor will not be consistent with the source file.");
|
|
}
|
|
else if (ImageWrapper->GetBitDepth() != 16)
|
|
{
|
|
Result.ResultCode = ELandscapeImportResult::Warning;
|
|
Result.ErrorMessage = LOCTEXT("Import_HeightmapFileLowBitDepth", "The heightmap file appears to be an 8-bit png, 16-bit is preferred. The import *can* continue, but the result may be lower quality than desired.");
|
|
}
|
|
FLandscapeFileResolution ImportResolution;
|
|
ImportResolution.Width = ImageWrapper->GetWidth();
|
|
ImportResolution.Height = ImageWrapper->GetHeight();
|
|
Result.PossibleResolutions.Add(ImportResolution);
|
|
}
|
|
}
|
|
|
|
// possible todo: support sCAL (XY scale) and pCAL (Z scale) png chunks for filling out Result.DataScale
|
|
// I don't know if any heightmap generation software uses these or not
|
|
// if we support their import we should make the exporter write them too
|
|
|
|
return Result;
|
|
}
|
|
|
|
FLandscapeImportData<uint16> FLandscapeHeightmapFileFormat_Png::Import(const TCHAR* HeightmapFilename, FName LayerName, FLandscapeFileResolution ExpectedResolution) const
|
|
{
|
|
FLandscapeImportData<uint16> Result;
|
|
|
|
TArray<uint8> TempData;
|
|
if (!FFileHelper::LoadFileToArray(TempData, HeightmapFilename, FILEREAD_Silent))
|
|
{
|
|
Result.ResultCode = ELandscapeImportResult::Error;
|
|
Result.ErrorMessage = LOCTEXT("Import_HeightmapFileReadError", "Error reading heightmap file");
|
|
}
|
|
else
|
|
{
|
|
IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>("ImageWrapper");
|
|
TSharedPtr<IImageWrapper> ImageWrapper = ImageWrapperModule.CreateImageWrapper(EImageFormat::PNG);
|
|
|
|
if (!ImageWrapper->SetCompressed(TempData.GetData(), TempData.Num()))
|
|
{
|
|
Result.ResultCode = ELandscapeImportResult::Error;
|
|
Result.ErrorMessage = LOCTEXT("Import_HeightmapFileCorruptPng", "The heightmap file cannot be read (corrupt png?)");
|
|
}
|
|
else if (ImageWrapper->GetWidth() != ExpectedResolution.Width || ImageWrapper->GetHeight() != ExpectedResolution.Height)
|
|
{
|
|
Result.ResultCode = ELandscapeImportResult::Error;
|
|
Result.ErrorMessage = LOCTEXT("Import_HeightmapResolutionMismatch", "The heightmap file's resolution does not match the requested resolution");
|
|
}
|
|
else
|
|
{
|
|
if (ImageWrapper->GetFormat() != ERGBFormat::Gray)
|
|
{
|
|
Result.ResultCode = ELandscapeImportResult::Warning;
|
|
Result.ErrorMessage = LOCTEXT("Import_HeightmapFileColorPng", "The imported layer is not Grayscale. Results in-Editor will not be consistent with the source file.");
|
|
}
|
|
else if (ImageWrapper->GetBitDepth() != 16)
|
|
{
|
|
Result.ResultCode = ELandscapeImportResult::Warning;
|
|
Result.ErrorMessage = LOCTEXT("Import_HeightmapFileLowBitDepth", "The heightmap file appears to be an 8-bit png, 16-bit is preferred. The import *can* continue, but the result may be lower quality than desired.");
|
|
}
|
|
|
|
TArray64<uint8> RawData;
|
|
if (ImageWrapper->GetBitDepth() <= 8)
|
|
{
|
|
if (!ImageWrapper->GetRaw(ERGBFormat::Gray, 8, RawData))
|
|
{
|
|
Result.ResultCode = ELandscapeImportResult::Error;
|
|
Result.ErrorMessage = LOCTEXT("Import_HeightmapFileCorruptPng", "The heightmap file cannot be read (corrupt png?)");
|
|
}
|
|
else
|
|
{
|
|
Result.Data.Empty(ExpectedResolution.Width * ExpectedResolution.Height);
|
|
Algo::Transform(RawData, Result.Data, [](uint8 Value) { return Value * 0x101; }); // Expand to 16-bit
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!ImageWrapper->GetRaw(ERGBFormat::Gray, 16, RawData))
|
|
{
|
|
Result.ResultCode = ELandscapeImportResult::Error;
|
|
Result.ErrorMessage = LOCTEXT("Import_HeightmapFileCorruptPng", "The heightmap file cannot be read (corrupt png?)");
|
|
}
|
|
else
|
|
{
|
|
Result.Data.Empty(ExpectedResolution.Width * ExpectedResolution.Height);
|
|
Result.Data.AddUninitialized(ExpectedResolution.Width * ExpectedResolution.Height);
|
|
FMemory::Memcpy(Result.Data.GetData(), RawData.GetData(), ExpectedResolution.Width * ExpectedResolution.Height * 2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
void FLandscapeHeightmapFileFormat_Png::Export(const TCHAR* HeightmapFilename, FName LayerName, TArrayView<const uint16> Data, FLandscapeFileResolution DataResolution, FVector Scale) const
|
|
{
|
|
IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>("ImageWrapper");
|
|
TSharedPtr<IImageWrapper> ImageWrapper = ImageWrapperModule.CreateImageWrapper(EImageFormat::PNG);
|
|
|
|
if (ImageWrapper->SetRaw(Data.GetData(), Data.Num() * 2, DataResolution.Width, DataResolution.Height, ERGBFormat::Gray, 16))
|
|
{
|
|
const TArray64<uint8> TempData = ImageWrapper->GetCompressed();
|
|
FFileHelper::SaveArrayToFile(TempData, HeightmapFilename);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
FLandscapeWeightmapFileFormat_Png::FLandscapeWeightmapFileFormat_Png()
|
|
{
|
|
FileTypeInfo.Description = LOCTEXT("FileFormatPng_WeightmapDesc", "Layer .png files");
|
|
FileTypeInfo.Extensions.Add(".png");
|
|
FileTypeInfo.bSupportsExport = true;
|
|
}
|
|
|
|
FLandscapeFileInfo FLandscapeWeightmapFileFormat_Png::Validate(const TCHAR* WeightmapFilename, FName LayerName) const
|
|
{
|
|
FLandscapeFileInfo Result;
|
|
|
|
TArray64<uint8> ImportData;
|
|
if (!FFileHelper::LoadFileToArray(ImportData, WeightmapFilename, FILEREAD_Silent))
|
|
{
|
|
Result.ResultCode = ELandscapeImportResult::Error;
|
|
Result.ErrorMessage = LOCTEXT("Import_LayerFileReadError", "Error reading layer file");
|
|
}
|
|
else
|
|
{
|
|
IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>("ImageWrapper");
|
|
TSharedPtr<IImageWrapper> ImageWrapper = ImageWrapperModule.CreateImageWrapper(EImageFormat::PNG);
|
|
|
|
if (!ImageWrapper->SetCompressed(ImportData.GetData(), ImportData.Num()))
|
|
{
|
|
Result.ResultCode = ELandscapeImportResult::Error;
|
|
Result.ErrorMessage = LOCTEXT("Import_LayerCorruptPng", "The layer file cannot be read (corrupt png?)");
|
|
}
|
|
else
|
|
{
|
|
if (ImageWrapper->GetFormat() != ERGBFormat::Gray)
|
|
{
|
|
Result.ResultCode = ELandscapeImportResult::Warning;
|
|
Result.ErrorMessage = LOCTEXT("Import_LayerColorPng", "The imported layer is not Grayscale. Results in-Editor will not be consistent with the source file.");
|
|
}
|
|
FLandscapeFileResolution ImportResolution;
|
|
ImportResolution.Width = ImageWrapper->GetWidth();
|
|
ImportResolution.Height = ImageWrapper->GetHeight();
|
|
Result.PossibleResolutions.Add(ImportResolution);
|
|
}
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
FLandscapeImportData<uint8> FLandscapeWeightmapFileFormat_Png::Import(const TCHAR* WeightmapFilename, FName LayerName, FLandscapeFileResolution ExpectedResolution) const
|
|
{
|
|
FLandscapeImportData<uint8> Result;
|
|
|
|
TArray64<uint8> TempData;
|
|
if (!FFileHelper::LoadFileToArray(TempData, WeightmapFilename, FILEREAD_Silent))
|
|
{
|
|
Result.ResultCode = ELandscapeImportResult::Error;
|
|
Result.ErrorMessage = LOCTEXT("Import_LayerFileReadError", "Error reading layer file");
|
|
}
|
|
else
|
|
{
|
|
IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>("ImageWrapper");
|
|
TSharedPtr<IImageWrapper> ImageWrapper = ImageWrapperModule.CreateImageWrapper(EImageFormat::PNG);
|
|
|
|
if (!ImageWrapper->SetCompressed(TempData.GetData(), TempData.Num()))
|
|
{
|
|
Result.ResultCode = ELandscapeImportResult::Error;
|
|
Result.ErrorMessage = LOCTEXT("Import_LayerCorruptPng", "The layer file cannot be read (corrupt png?)");
|
|
}
|
|
else if (ImageWrapper->GetWidth() != ExpectedResolution.Width || ImageWrapper->GetHeight() != ExpectedResolution.Height)
|
|
{
|
|
Result.ResultCode = ELandscapeImportResult::Error;
|
|
Result.ErrorMessage = LOCTEXT("Import_LayerResolutionMismatch", "The layer file's resolution does not match the requested resolution");
|
|
}
|
|
else if (!ImageWrapper->GetRaw(ERGBFormat::Gray, 8, Result.Data))
|
|
{
|
|
Result.ResultCode = ELandscapeImportResult::Error;
|
|
Result.ErrorMessage = LOCTEXT("Import_LayerCorruptPng", "The layer file cannot be read (corrupt png?)");
|
|
}
|
|
else
|
|
{
|
|
if (ImageWrapper->GetFormat() != ERGBFormat::Gray)
|
|
{
|
|
Result.ResultCode = ELandscapeImportResult::Warning;
|
|
Result.ErrorMessage = LOCTEXT("Import_LayerColorPng", "The imported layer is not Grayscale. Results in-Editor will not be consistent with the source file.");
|
|
}
|
|
}
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
void FLandscapeWeightmapFileFormat_Png::Export(const TCHAR* WeightmapFilename, FName LayerName, TArrayView<const uint8> Data, FLandscapeFileResolution DataResolution, FVector Scale) const
|
|
{
|
|
IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>("ImageWrapper");
|
|
TSharedPtr<IImageWrapper> ImageWrapper = ImageWrapperModule.CreateImageWrapper(EImageFormat::PNG);
|
|
|
|
if (ImageWrapper->SetRaw(Data.GetData(), Data.Num(), DataResolution.Width, DataResolution.Height, ERGBFormat::Gray, 8))
|
|
{
|
|
const TArray64<uint8> TempData = ImageWrapper->GetCompressed();
|
|
FFileHelper::SaveArrayToFile(TempData, WeightmapFilename);
|
|
}
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE
|