関連ブログ
- [UE4][UE5]開発環境の容量を少しでも減らす 2024.08.14UE
- [UE5] PushModel型のReplicationを使い、ネットワーク最適化を図る 2024.05.29UE
- [UE5]マテリアルでメッシュをスケールする方法 2024.01.17UE
CATEGORY
2018.02.23UE4UE/ C++
本日は、ImageWrapperModuleを用いて、スクリーンショットを、 指定の拡張子にて、書き出す方法をご紹介します。 スクリーンショットを撮る関数に関しては、以前ご紹介した記事を、 参考にしていただけると幸いです。 https://historia.co.jp/archives/5917/ 今回は、上記の関数に、ImageWapperを用いた部分を中心にご紹介します。 1.下準備 まずは、今回使用するImageWrapperModuleを、 プロジェクトの”プロジェクト名.Build.csの、PublicDependencyModuleNamesへ追加します。
1 |
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形式へ、変換できるようにします。
1 2 3 4 5 6 7 8 9 10 11 12 |
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. 使用する変数の宣言 関数内で使用する変数を、宣言します。
1 2 3 4 5 |
static EImageFormatType format; //今回追加。拡張子選択用 static int quality; //今回追加。圧縮率指定用。100で最大となります。 static FString fileName; static FDelegateHandle delegateHandle; static IImageWrapperModule& ImageWrapperModule; |
D. 関数の宣言 本題の、ImageWrapperを使用する関数を宣言します。 関数名は、今回はOnScreenshotCapturedInternalとしています。
1 |
static void OnScreenshotCapturedInternal(int32 Width, int32 Height, const TArray& Bitmap); |
また、スクリーンショットをとる、TakeScreenShot関数に、 今回追加された、format、quality変数へ渡すための引数を追加します。
1 2 |
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つのインクルードファイルを追加します。
1 2 3 |
#include "IImageWrapper.h" #include "IImageWrapperModule.h" #include "ImageUtils.h" |
B. ヘッダーで宣言した変数の追加
1 2 3 4 5 |
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& amp; 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& amp; 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& amp; 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& amp; 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 & amp; 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で作成していますが、 古いバージョンでは、同じ内容で記述しても、動かないことがありますので、 ご注意の上お試しください。