【UE4 C++】 外部图片读取、Texture 保存 png
2024-08-28 13:33:20
蓝图版
导入外部图片
file://E:/UE___Projects_Test/MyProjectAAA/Plugins/WXimage.jpg
导出图图片
- 一般导出 .hdr 文件
- 导出 png 设置一些格式
C++ 版
读取外部图片
build.cs 添加 ImageWrapper 模块,使用时注意添加相关头文件
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "ImageWrapper" });
支持图片类型
- png
- jpg
- bmp
- ico
- exr
- icns
注意 jpg 读取后 R 和 B 的通道位置
- ERGBFormat::RGBA、PF_R8G8B8A8 → ERGBFormat::BGR、PF_B8G8R8A8
代码实现(4.26)
UENUM(BlueprintType)
enum class EImgFormat : uint8
{ /** Portable Network Graphics. */
PNG = 0, /** Joint Photographic Experts Group. */
JPEG, /** Single channel JPEG. */
GrayscaleJPEG, /** Windows Bitmap. */
BMP, /** Windows Icon resource. */
ICO, /** OpenEXR (HDR) image file format. */
EXR, /** Mac icon. */
ICNS
}; UTexture2D* ADataDriveActor::ImportImage(const FString& path, EImgFormat Type, bool& IsValid, int32& OutWidth, int32& OutHeight)
{
UTexture2D* Texture = nullptr;
IsValid = false;
// 文件是否存在
if (!FPlatformFileManager::Get().GetPlatformFile().FileExists(*path))
{
return nullptr;
}
// 图片是否加载
TArray<uint8> RawFileData;
if (!FFileHelper::LoadFileToArray(RawFileData, *path))
{
return nullptr;
} IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
// 自定义枚举转换 EImageFormat
// IImageWrapperPtr 变更为 TSharedPtr<IImageWrapper>
TSharedPtr<IImageWrapper> ImageWrapper = ImageWrapperModule.CreateImageWrapper(static_cast<EImageFormat>((int8)Type)); if (ImageWrapper.IsValid() && ImageWrapper->SetCompressed(RawFileData.GetData(), RawFileData.Num()))
{
// 此处有所变动 低版本为 const TArray<uint8>* UncompressedRGBA = nullptr;
TArray<uint8> UncompressedRGBA ;
if (ImageWrapper->GetRaw(ERGBFormat::RGBA, 8, UncompressedRGBA))
{
Texture = UTexture2D::CreateTransient(ImageWrapper->GetWidth(), ImageWrapper->GetHeight(), PF_R8G8B8A8);
if (Texture != nullptr)
{
IsValid = true;
OutWidth = ImageWrapper->GetWidth();
OutHeight = ImageWrapper->GetHeight();
void* TextureData = Texture->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_WRITE);
FMemory::Memcpy(TextureData, UncompressedRGBA.GetData(), UncompressedRGBA.Num());
Texture->PlatformData->Mips[0].BulkData.Unlock();
Texture->UpdateResource();
}
}
}
return Texture;
}
Texture 导出 图片
使用 mip.BulkData.Lock(LOCK_READ_WRITE) 前需要对Texture 设置一些参数,否则会返回 nullptr
- CompressionSettings set to VectorDisplacementmap
- MipGenSettings to NoMipmaps
- SRGB to false
代码实现
bool ADataDriveActor::ExportImage(UTexture2D* Texture2D, const FString& Path)
{
// setup required parameters
TextureCompressionSettings OldCompressionSettings = Texture2D->CompressionSettings;
TextureMipGenSettings OldMipGenSettings = Texture2D->MipGenSettings;
bool OldSRGB = Texture2D->SRGB; Texture2D->CompressionSettings = TextureCompressionSettings::TC_VectorDisplacementmap;
Texture2D->MipGenSettings = TextureMipGenSettings::TMGS_NoMipmaps;
Texture2D->SRGB = false;
Texture2D->UpdateResource(); FTexture2DMipMap& mipmap = Texture2D->PlatformData->Mips[0];
uint8* Data = (uint8*)mipmap.BulkData.Lock(LOCK_READ_WRITE);
//FColor* FormatedImageData = static_cast<FColor*>(mipmap.BulkData.Lock(LOCK_READ_WRITE));
if (Data == nullptr)
{
mipmap.BulkData.Unlock(); // 不释放,会卡住
Texture2D->UpdateResource();
return false;
} int width = Texture2D->PlatformData->SizeX;
int height = Texture2D->PlatformData->SizeY;
TArray<FColor> nColors; for (int32 y = 0; y < height; y++)
{
for (int32 x = 0; x < width; x++)
{
FColor bColor;
bColor.B = Data[(y * width + x) * 4 + 0];//B 0 - 255
bColor.G = Data[(y * width + x) * 4 + 1];//G
bColor.R = Data[(y * width + x) * 4 + 2];//R
bColor.A = Data[(y * width + x) * 4 + 3];//A
nColors.Add(bColor);
}
}
mipmap.BulkData.Unlock(); // return old parameters
Texture2D->CompressionSettings = OldCompressionSettings;
Texture2D->MipGenSettings = OldMipGenSettings;
Texture2D->SRGB = OldSRGB; Texture2D->UpdateResource(); //获取 uint8 数据,保存
TArray<uint8> ImgData;
FImageUtils::CompressImageArray(width, height, nColors, ImgData);
return FFileHelper::SaveArrayToFile(ImgData, *Path);
}
最新文章
- Uncaught RangeError: Maximum call stack size exceeded 超出最大调用值(个人解释)
- FASTJSON
- Java面向对象编程之异常处理机制
- poj 1416 (hdu 1539)Shredding Company:剪枝搜索
- Javascript中的Prototype到底是啥
- Python序列切片的注意事项
- MDM基于IOS设备管控功能的所有命令介绍
- QTP自动化测试权威指南 连载(一)
- ng-class用法
- JSP内置对象--web安全性及config对象的使用 (了解即可)
- angular router ui bug !
- Windows server 2008 r2 开启Aero
- webAPP踩坑记录
- [Luogu4230]连体病原体
- jeecg入门操作—菜单管理
- DCDC参数测量及方法
- Using async-await on .net 4
- MYSQL增加tmp_table_size 的操作
- 昂达 v891 连接上adb 调试
- [Javascript] Check both prop exists and value is valid