实时加载本地图片和音效

前言

从本地路径加载图片和音效数据, 得到UTexture2DUSoundWave

UE4Editor_dmHYzjuVWx

图片

从文件加载UTexture2D

一切尽在注释中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

//加载ImageWrapper模块,同时创建一个针对格式操作的辅助对象
static TSharedPtr<IImageWrapper> GetImageWrapperByExtention(const FString InImagePath)
{
IImageWrapperModule& ImageWrapperModule = FModuleManager::GetModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));



if (InImagePath.EndsWith(".png"))
{
return ImageWrapperModule.CreateImageWrapper(EImageFormat::PNG);
}
else if (InImagePath.EndsWith(".jpg") || InImagePath.EndsWith(".jpeg"))
{
return ImageWrapperModule.CreateImageWrapper(EImageFormat::JPEG);
}
else if (InImagePath.EndsWith(".bmp"))
{
return ImageWrapperModule.CreateImageWrapper(EImageFormat::BMP);
}
else if (InImagePath.EndsWith(".ico"))
{
return ImageWrapperModule.CreateImageWrapper(EImageFormat::ICO);
}
else if (InImagePath.EndsWith(".exr"))
{
return ImageWrapperModule.CreateImageWrapper(EImageFormat::EXR);
}
else if (InImagePath.EndsWith(".icns"))
{
return ImageWrapperModule.CreateImageWrapper(EImageFormat::ICNS);
}
return nullptr;
}

UTexture2D* UFlib_IO::LoadTexture2DFromFile(const FString& FilePath, bool& IsValid, int32& Width, int32& Height)
{

IsValid = false;
UTexture2D* LoadedT2D = NULL;


TSharedPtr<IImageWrapper> ImageWrapper = GetImageWrapperByExtention(FilePath);
//得到解压后的源数据
TArray<uint8> RawFileData;
if (!FFileHelper::LoadFileToArray(RawFileData, *FilePath, 0)) return NULL;

if (ImageWrapper.IsValid() && ImageWrapper->SetCompressed(RawFileData.GetData(), RawFileData.Num()))
{
TArray<uint8> UncompressedBGRA;
//设置格式并获取未压缩的数据
if (ImageWrapper->GetRaw(ERGBFormat::BGRA, 8, UncompressedBGRA))
{
//创建UTexture2D*
LoadedT2D = UTexture2D::CreateTransient(ImageWrapper->GetWidth(), ImageWrapper->GetHeight(), PF_B8G8R8A8);

if (!LoadedT2D) return NULL;
//得到高度和宽度
Width = ImageWrapper->GetWidth();
Height = ImageWrapper->GetHeight();
// 锁住他的数据
void* TextureData = LoadedT2D->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_WRITE);
//获取纹理数据
FMemory::Memcpy(TextureData, UncompressedBGRA.GetData(), UncompressedBGRA.Num());
//解锁
LoadedT2D->PlatformData->Mips[0].BulkData.Unlock();

LoadedT2D->UpdateResource();
}
}

IsValid = true;
return LoadedT2D;
}

RenderTarget2D导出成本地图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
bool UFlib_IO::ExportTextureRenderTarget2D2PNG(UTextureRenderTarget2D* TextureRenderTarget, const FString& FilePath)
{

FTextureRenderTargetResource* rtResource = TextureRenderTarget->GameThread_GetRenderTargetResource();
FReadSurfaceDataFlags readPixelFlags(RCM_UNorm);

TArray<FColor> outBMP;

for (FColor& color : outBMP)
{
color.A = 255;
}
outBMP.AddUninitialized(TextureRenderTarget->GetSurfaceWidth() * TextureRenderTarget->GetSurfaceHeight());
rtResource->ReadPixels(outBMP, readPixelFlags);

FIntPoint destSize(TextureRenderTarget->GetSurfaceWidth(), TextureRenderTarget->GetSurfaceHeight());
TArray<uint8> CompressedBitmap;
FImageUtils::CompressImageArray(destSize.X, destSize.Y, outBMP, CompressedBitmap);
bool imageSavedOk = FFileHelper::SaveArrayToFile(CompressedBitmap, *FilePath);

return imageSavedOk;
}

音效

从本地文件加载USoundWave

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class USoundWave* UFlib_IO::LoadWaveDataFromFile(const FString& FilePath)
{
USoundWave* sw = NewObject<USoundWave>(USoundWave::StaticClass());

if (!sw)
return nullptr;


TArray < uint8 > rawFile;

FFileHelper::LoadFileToArray(rawFile, FilePath.GetCharArray().GetData());
FWaveModInfo WaveInfo;

if (WaveInfo.ReadWaveInfo(rawFile.GetData(), rawFile.Num()))
{
sw->InvalidateCompressedData();

sw->RawData.Lock(LOCK_READ_WRITE);
void* LockedData = sw->RawData.Realloc(rawFile.Num());
FMemory::Memcpy(LockedData, rawFile.GetData(), rawFile.Num());
sw->RawData.Unlock();

int32 DurationDiv = *WaveInfo.pChannels * *WaveInfo.pBitsPerSample * *WaveInfo.pSamplesPerSec;
if (DurationDiv)
{
sw->Duration = *WaveInfo.pWaveDataSize * 8.0f / DurationDiv;
}
else
{
sw->Duration = 0.0f;
}

sw->SetSampleRate(*WaveInfo.pSamplesPerSec);
sw->NumChannels = *WaveInfo.pChannels;
sw->RawPCMDataSize = WaveInfo.SampleDataSize;
sw->SoundGroup = ESoundGroup::SOUNDGROUP_Default;
}
else {
return nullptr;
}

return sw;
}