Download

recommended way to replace the FHighResolutionScreenshotConfig SaveImage in 4.21

Hi, I used to capture images from rendertargets using the FHighResolutionScreenshotConfig::SaveImage. Now in 4.21 the function has been removed and I struggle to find the intended replacement. Can anyone point me to the right direction?



    FTextureRenderTargetResource* RTResource = InRenderTarget->GameThread_GetRenderTargetResource();
    TArray<FColor> OutBMP;
    RTResource->ReadPixels(OutBMP, ReadPixelFlags);

    FIntRect SourceRect;
    FIntPoint DestSize(InRenderTarget->GetSurfaceWidth(), InRenderTarget->GetSurfaceHeight());


    FString ResultPath;
    FHighResScreenshotConfig& HighResScreenshotConfig = GetHighResScreenshotConfig();
    HighResScreenshotConfig.SaveImage(Filename, OutBMP, DestSize, &ResultPath);


Push. Cant find anything online…

I tried with ImageWriteTask.h but I get
public\ImageWriteTask.h(74): error C2144: syntax error: ‘bool’ should be preceded by ‘;’
public\ImageWriteTask.h(74): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
public\ImageWriteTask.h(75): error C2144: syntax error: ‘void’ should be preceded by ‘;’
public\ImageWriteTask.h(75): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int

from

IMAGEWRITEQUEUE_API virtual bool RunTask() override final;
IMAGEWRITEQUEUE_API virtual void OnAbandoned() override final;

Here’s a solution I came up with using ImageWriteTask. Any suggestions to improve this would be appreciated.



    FTextureRenderTargetResource* RTResource = InRenderTarget->GameThread_GetRenderTargetResource();

    // We're reading back depth in centimeters from alpha, and linear lighting.
    const ERangeCompressionMode kDontRangeCompress = RCM_MinMax;
    FReadSurfaceDataFlags ReadPixelFlags(kDontRangeCompress);

    // We always want linear output.
    ReadPixelFlags.SetLinearToGamma(false);

    // Create a bitmap
    TArray<FLinearColor> OutBMP;
    RTResource->ReadLinearColorPixels(OutBMP, ReadPixelFlags);

    FIntRect SourceRect;
    FIntPoint DestSize(InRenderTarget->GetSurfaceWidth(), InRenderTarget->GetSurfaceHeight());

    FString ResultPath;
    FHighResScreenshotConfig& HighResScreenshotConfig = GetHighResScreenshotConfig();
    HighResScreenshotConfig.bCaptureHDR = true;

    //HighResScreenshotConfig.SaveImage(Filename, OutBMP, DestSize); -- DEPRECATED 4.21 so using ImageWriteTask instead

    // New Code by vMattC

        // Check to see if ImageWriteQueue has been initialised
        if (!ensureMsgf(HighResScreenshotConfig.ImageWriteQueue, TEXT("Unable to write images unless FHighResScreenshotConfig::Init has been called.")))
        {
            // Do something
        }

        // Create ImageTask
        TUniquePtr<FImageWriteTask> ImageTask = MakeUnique<FImageWriteTask>();

        // Pass bitmap to pixeldata
        ImageTask->PixelData = MakeUnique<TImagePixelData<FLinearColor>>(DestSize, MoveTemp(OutBMP));

        // Populate Task with config data
        HighResScreenshotConfig.PopulateImageTaskParams(*ImageTask);
        ImageTask->Filename = Filename;

        // Specify HDR as output format
        ImageTask->Format = EImageFormat::EXR;

        // Save the bitmap to disc
        TFuture<bool> CompletionFuture = HighResScreenshotConfig.ImageWriteQueue->Enqueue(MoveTemp(ImageTask));
        if (CompletionFuture.IsValid())
        {
            CompletionFuture.Wait();
        }

    // End New Code

and in the Build.CS file, added Json and ImageWriteQueue as module dependencies.



PrivateDependencyModuleNames.AddRange(
            new string]
            {
                "Projects",
                "InputCore",
                "UnrealEd",
                "LevelEditor",
                "CoreUObject",
                "Engine",
                "Slate",
                "SlateCore",
                "Json",
                "ImageWriteQueue",
                "PropertyEditor",
                // ... add private dependencies that you statically link with here ...
            }
 );

Include module “ImageWriteQueue” in the Build.cs file

ImageTask->PixelData = MakeUnique< TImagePixelData<FLinearColor>> (DestSize, MoveTemp(OutBMP) );

this line is giving me compile error

Error C2664 ‘TImagePixelData<FLinearColor>::TImagePixelData(TImagePixelData<FLinearColor> &&)’: cannot convert argument 2 from ‘T’ to ‘TArray<PixelType,FDefaultAllocator64> &&’ MyPluginProject1 C:\Epic Games\UE_4.26\Engine\Source\Runtime\Core\Public\Templates\UniquePtr.h 753

I seem to have been able to get @vMattC’s solution to compile by doing an explicit cast on MoveTemp

Replacing:

ImageTask->PixelData = MakeUnique<TImagePixelData<FLinearColor>>(DestSize, MoveTemp(OutBMP));

with:

ImageTask->PixelData = MakeUnique<TImagePixelData<FLinearColor>>(DestSize, (TArray<FLinearColor, FDefaultAllocator64>) MoveTemp(OutBMP));