Error when reading texture BulkData

Next code causes unknown unhandled exception:

void UNoxMagicFunctions::RawDataFromTexture(UTexture2D* texture, FTextureRaw& rawData)
{
	rawData.width = texture->Resource->GetSizeX();
	rawData.height = texture->Resource->GetSizeY();
	rawData.pixels.Init(FColor(255, 255, 255, 255), rawData.width * rawData.height);

	FTexture2DMipMap& mip = texture->PlatformData->Mips[0];
	void* data = mip.BulkData.Lock(LOCK_READ_WRITE);
	UE_LOG(LogTemp, Warning, TEXT("%d"), ((FColor*)data)[0].R); // error here
	//FMemory::Memcpy(rawData.pixels.GetData(), data, rawData.width * rawData.height * 4); // and here
	mip.BulkData.Unlock();
	texture->UpdateResource();
}

I tried many checks and everything leads to reading any data from data. It happens even with try-catch block. When I comment error lines, everything works fine. Why?

It was happening because mip.BulkData.Lock(LOCK_READ_WRITE) was returned nullptr. To avoid this, according to this guide, before accessing bulkdata your texture must have next parameters:

  • CompressionSettings set to VectorDisplacementmap
  • MipGenSettings to NoMipmaps
  • SRGB to false

i.e. in my case it looks like:

void UNoxMagicFunctions::RawDataFromTexture(UTexture2D* texture, FTextureRaw& rawData)
{
	// setup required parameters
	TextureCompressionSettings OldCompressionSettings = texture->CompressionSettings;
	TextureMipGenSettings OldMipGenSettings = texture->MipGenSettings;
	bool OldSRGB = texture->SRGB;

	texture->CompressionSettings = TextureCompressionSettings::TC_VectorDisplacementmap;
	texture->MipGenSettings = TextureMipGenSettings::TMGS_NoMipmaps;
	texture->SRGB = false;
	texture->UpdateResource();

	// read data
	rawData.width = texture->Resource->GetSizeX();
	rawData.height = texture->Resource->GetSizeY();
	rawData.pixels.Init(FColor::White, rawData.width * rawData.height);

	FColor* data = (FColor*)texture->PlatformData->Mips[0].BulkData.LockReadOnly();
	FMemory::Memcpy(rawData.pixels.GetData(), data, sizeof(FColor) * rawData.width * rawData.height);

	texture->PlatformData->Mips[0].BulkData.Unlock();

	// return old parameters
	texture->CompressionSettings = OldCompressionSettings;
	texture->MipGenSettings = OldMipGenSettings;
	texture->SRGB = OldSRGB;
	texture->UpdateResource();
}

Note that any operations with MipGenSettings should be wrapped with #if WITH_EDITOR if you packaging build.

2 Likes