Capturing and Uploading Screenshots in UE4
⚠️ This post was last updated in 2017, meaning its contents may be outdated.
For Estranged, I wanted the ability to capture the contents of the frame buffer, compress it, and upload it to a REST API. This allows users to attach screenshots to an in-game feedback window, to simplify the bug reporting process.
Unreal Engine 4 has APIs around all of those pieces, and in this post, I'll cover sticking them all together.
The full header and source file from the Estranged code is available as a GitHub gist. Below are the important excerpts.
Capturing a Screenshot
This is a two step process. First, you need to register a callback for when the screenshot is captured, then you request a screenshot:
void UEstScreenshotTaker::RequestScreenshot()
{
GEngine->GameViewport->OnScreenshotCaptured().AddUObject(this, &UEstScreenshotTaker::AcceptScreenshot);
FScreenshotRequest::RequestScreenshot(false); // False means don't include any UI
}
void UEstScreenshotTaker::AcceptScreenshot(int32 InSizeX, int32 InSizeY, const TArray<FColor>& InImageData)
{
// See below
}
Compressing the Pixel Data
In the implementation of your AcceptScreenshot
function, you can use the Image Wrapper module to process the image.
First, you need to get a pointer to the JPEG image wrapper, then load in your raw image data, and retrieve the compressed version.
// Load image wrapper module
IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
TSharedPtr<IImageWrapper> ImageWrapper = ImageWrapperModule.CreateImageWrapper(EImageFormat::JPEG);
// Provide image wrapper with raw pixels (TArray<FColor>)
ImageWrapper->SetRaw(&InImageData[0], InImageData.Num() * sizeof(FColor), InSizeX, InSizeY, ERGBFormat::BGRA, 8);
// Get the image using 90% JPEG compression
const TArray<uint8> CompressedImage = ImageWrapper->GetCompressed(90);
Uploading the Image
The array of uint8
that you get back from the GetCompressed
method can be piped directly into a HttpRequest object.
TSharedRef<IHttpRequest> HttpRequest = FHttpModule::Get().CreateRequest();
HttpRequest->SetVerb("POST");
HttpRequest->SetHeader("Content-Type", "image/jpeg");
HttpRequest->SetContent(CompressedImage); // TArray<uint8>
HttpRequest->SetURL(FString("http://example.com/v1/screenshots"));
// Optionally assign HttpRequest->OnProcessRequestComplete() to get a callback when complete
HttpRequest->ProcessRequest();
Your backend can then process and store the JPEG image as appropriate - in my case an API over Amazon S3.
🏷️ image screenshot upload compress capturing estranged api data wrapper jpeg ue4 capture frame buffer rest
Please click here to load comments.