本日は、ImageWrapperModuleを用いて、スクリーンショットを、
指定の拡張子にて、書き出す方法をご紹介します。
スクリーンショットを撮る関数に関しては、以前ご紹介した記事を、
参考にしていただけると幸いです。
[UE4]BPで、HUD込みのスクリーンショットを取る方法
今回は、上記の関数に、ImageWapperを用いた部分を中心にご紹介します。
1.下準備
まずは、今回使用するImageWrapperModuleを、
プロジェクトの”プロジェクト名.Build.csの、PublicDependencyModuleNamesへ追加します。
|
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "ImageWrapper" }); |
これで、プロジェクト内で、ImageWrapperModuleを使用できるようになります。
2.ヘッダーでの下準備
ヘッダーにおける下準備は、下記の4点になります。
A. class IImageWrapperModuleの追加。
B. 拡張子選択用UENUMの作成
C. 使用する変数の宣言
D. 関数の宣言
それでは順番にみていきます。
A. class IImageWrapperModuleの追加。
クラス内でImageWapperModuleを使用するため、
まずはclass IImageWrapperModuleを追加します。
B. 拡張子選択用UENUMの作成
ImageWrapperModuleの中に、拡張子選択用のenum classがあるのですが、
UENUMとして書かれていないので、そのままではブループリントで使用できません。
ですので、ImageWrapperModule内のenum classを参考に、UENUM(BlueprintType)として、作成します。
今回は、PNG、JPEG、EXR形式へ、変換できるようにします。
|
UENUM(BlueprintType) enum class EImageFormatType : uint8 { /** Portable Network Graphics. */ PNG = 0, /** Joint Photographic Experts Group. */ JPEG, /** OpenEXR (HDR) image file format. */ EXR = 5, }; |
これで、今回作成するImageWrapperModuleで使用されているのと同じ内容の、
UENUM(BlueprintType)が出来ました。
C. 使用する変数の宣言
関数内で使用する変数を、宣言します。
|
static EImageFormatType format; //今回追加。拡張子選択用 static int quality; //今回追加。圧縮率指定用。100で最大となります。 static FString fileName; static FDelegateHandle delegateHandle; static IImageWrapperModule& ImageWrapperModule; |
D. 関数の宣言
本題の、ImageWrapperを使用する関数を宣言します。
関数名は、今回はOnScreenshotCapturedInternalとしています。
|
static void OnScreenshotCapturedInternal(int32 Width, int32 Height, const TArray& Bitmap); |
また、スクリーンショットをとる、TakeScreenShot関数に、
今回追加された、format、quality変数へ渡すための引数を追加します。
|
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "1"), Category = "TalkCameraDebug") static void TakeScreenShot(const FString& fineName = FString(TEXT("ScreenShot")), EImageFormatType _format = EImageFormatType::PNG, int _quality = 100, bool bInsertTimeStampToFileName = true, bool bInShowUI = true, bool bAddFilenameSuffix = true); |
_formatと、_qualityを追加しました。
ヘッダーの準備は以上になります。
3. cppファイルでの下準備
A. インクルードファイルの追加
B. ヘッダーで宣言した変数の追加
Ç. OnScreenshotCapturedInternal関数の定義
D. TakeScreenShot関数の修正
それでは順番にみていきます。
A. インクルードファイルの追加
下記3つのインクルードファイルを追加します。
|
#include "IImageWrapper.h" #include "IImageWrapperModule.h" #include "ImageUtils.h" |
B. ヘッダーで宣言した変数の追加
|
EImageFormatType UTalkCameraFunctionLibrary::format; int UTalkCameraFunctionLibrary::quality; FString UTalkCameraFunctionLibrary::fileName; FDelegateHandle UTalkCameraFunctionLibrary::delegateHandle; IImageWrapperModule& UTalkCameraFunctionLibrary::ImageWrapperModule = FModuleManager::LoadModuleChecked(FName("ImageWrapper")); |
Ç. OnScreenshotCapturedInternal関数の定義
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
|
void UTalkCameraFunctionLibrary::OnScreenshotCapturedInternal(int32 Width, int32 Height, const TArray& Bitmap) { #if UE_EDITOR TSharedPtr ImageWrapper; if (format == EImageFormatType::PNG) { TArray PNGData; TArray BitmapCopy(Bitmap); FImageUtils::CompressImageArray(Width, Height, BitmapCopy, PNGData); fileName += ".png"; FFileHelper::SaveArrayToFile(PNGData, *fileName); } else if (format == EImageFormatType::JPEG) { ImageWrapper = ImageWrapperModule.CreateImageWrapper(EImageFormat::JPEG); ImageWrapper->SetRaw(Bitmap.GetData(), Bitmap.GetAllocatedSize(), Width, Height, ERGBFormat::BGRA, 8); const TArray& JPEGData = ImageWrapper->GetCompressed(quality); fileName += ".jpg"; FFileHelper::SaveArrayToFile(JPEGData, *fileName); } else if (format == EImageFormatType::EXR) { ImageWrapper = ImageWrapperModule.CreateImageWrapper(EImageFormat::EXR); ImageWrapper->SetRaw(Bitmap.GetData(), Bitmap.GetAllocatedSize(), Width, Height, ERGBFormat::BGRA, 8); const TArray& Data = ImageWrapper->GetCompressed(quality); fileName += ".exr"; FFileHelper::SaveArrayToFile(Data, *fileName); } else { //未定義の画像形式はJPEGでかき出し ImageWrapper = ImageWrapperModule.CreateImageWrapper(EImageFormat::JPEG); ImageWrapper->SetRaw(Bitmap.GetData(), Bitmap.GetAllocatedSize(), Width, Height, ERGBFormat::BGRA, 8); const TArray& JPEGData = ImageWrapper->GetCompressed(quality); fileName += ".jpg"; FFileHelper::SaveArrayToFile(JPEGData, *fileName); } UGameViewportClient::OnScreenshotCaptured().Remove(delegateHandle); ImageWrapper.Reset(); #endif } |
この関数の中で、受け取った画像データを、指定の拡張子のデータに変換します。
D. TakeScreenShot関数の修正
TakeScreenShot関数を、OnScreenshotCapturedInternal関数を組み込む形で、
修正をします。
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
|
void UTalkCameraFunctionLibrary::TakeScreenShot(const FString& fineName, EImageFormatType _format, int _quality, bool bInsertTimeStampToFileName, bool bInShowUI, bool bAddFilenameSuffix) { #if UE_EDITOR FString filename = fineName; format = _format; quality = _quality; //現在時刻でスクリーンショットに名前をつける if (bInsertTimeStampToFileName) { filename += "_" + FDateTime::Now().ToString(); } //ユニークID付きの時はID前に_を付加 if (bAddFilenameSuffix) { filename += "_"; } UTalkCameraFunctionLibrary::fileName = FPaths::ProjectSavedDir() + "ScreenShots/Windows/" + filename; if (!UGameViewportClient::OnScreenshotCaptured().IsBound()) { delegateHandle = UGameViewportClient::OnScreenshotCaptured().AddStatic(&UTalkCameraFunctionLibrary::OnScreenshotCapturedInternal);//今回の追加分。 FScreenshotRequest::RequestScreenshot(filename, bInShowUI, bAddFilenameSuffix); } #endif } |
4. レベルブループリントでテスト
作成した関数を、レベルブループリントで、任意のキーを割り当てて、テストをしてみましょう。

今回はPを押すと、スクリーンショットを撮るようにしました。
Formatを、JPEGにしてあります。

無事に、JPEG画像として、書き出すことが出来ました。
今回は、エンジンバージョン4.18.3で作成していますが、
古いバージョンでは、同じ内容で記述しても、動かないことがありますので、
ご注意の上お試しください。