【UE4 C++】 外部图片读取、Texture 保存 png

66 篇文章 7 订阅

蓝图版

导入外部图片

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);
    }
    

要在UE4中使用C++实现TexturerRenderTargetCube读取照片,你需要完成以下步骤: 1. 导入照片:在UE4编辑器中,右键单击Content Browser面板,选择Import选项,然后选择你想要导入的照片。 2. 创建TexturerRenderTargetCube:在你的UE4项目中,找到你想要添加TexturerRenderTargetCube的地方。然后在该位置创建一个TexturerRenderTargetCube对象。 3. 设置TexturerRenderTargetCube属性:在代码中设置你的TexturerRenderTargetCube对象的属性。为了从照片中创建立方体贴图,你需要设置RenderTarget的尺寸以及Texture的格式。 4. 从照片中创建立方体贴图:使用你导入的照片创建立方体贴图。你需要将照片分解为6个面,并将它们作为6个2D纹理分别应用到RenderTargetCube的6个面上。 5. 使用TexturerRenderTargetCube:将TexturerRenderTargetCube用于你的场景或材质中。你可以将它作为材质的纹理或将它用于场景中的天空盒。 下面是一些示例代码来实现这些步骤: ```cpp // 导入照片 UTexture2D* PhotoTexture = LoadObject<UTexture2D>(nullptr, TEXT("/Game/Textures/PhotoTexture.PhotoTexture")); // 创建TexturerRenderTargetCube UTextureRenderTargetCube* CubeRenderTarget = NewObject<UTextureRenderTargetCube>(); CubeRenderTarget->InitAutoFormat(256); // 设置TexturerRenderTargetCube属性 CubeRenderTarget->ClearColor = FLinearColor::Black; // 从照片中创建立方体贴图 int32 CubeFaceSize = CubeRenderTarget->SizeX / 4; for (int32 CubeFaceIndex = 0; CubeFaceIndex < 6; ++CubeFaceIndex) { // 创建一个2D纹理 UTexture2D* CubeFaceTexture = NewObject<UTexture2D>(); CubeFaceTexture->Source.Init(CubeFaceSize, CubeFaceSize, 1, 1, ETextureSourceFormat::TSF_BGRA8, &(PhotoTexture->PlatformData->Mips[0].BulkData)); // 应用2D纹理到RenderTargetCube CubeRenderTarget->GameThread_SetTextureCubeFace((ECubeFace)CubeFaceIndex, CubeFaceTexture, false, false); } // 使用TexturerRenderTargetCube UMaterialInstanceDynamic* DynamicMaterial = UMaterialInstanceDynamic::Create(Material, InWorld); DynamicMaterial->SetTextureParameterValue(TEXT("CubeTexture"), CubeRenderTarget); ``` 这样,你就可以使用C++实现TexturerRenderTargetCube读取照片了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值