その3のバージョンはエディターでしか動作しないものでしたので急遽、実機でもうまくいくバージョンを作成しようと思います。(失敗)
(エディターのバージョンでもほかの方法で、TextureからRowDataが取得できれば使いまわしはできるので興味がある人は、調べてみたもいいかもです。私には無理でした・・・・)
PNGからテキストデータを取得する
今回はTextureデータではなく実際のPNGの画像を使用して、QRコードの読み込みを試みたいと思います。
PNG画像を直接読むのでBPからパスを指定して自前でロードして、ロードのデータからImageを作成して読み込ませる感じです。
では、c++の改良から始めます。
まずは、ヘッダーファイルにBP側でエンジン側のenumを使えるように別の名前で再定義します。
実際のクラスの上に記載をお願いします。
// BP公開用
UENUM(BlueprintType)
enum class EBPImageFormatType : uint8
{
/** Portable Network Graphics. */
PNG = 0,
/** Joint Photographic Experts Group. */
JPEG,
/** Single channel JPEG. */
GrayscaleJPEG,
/** Windows Bitmap. */
BMP,
/** Windows Icon resource. */
ICO,
/** OpenEXR (HDR) image file format. */
EXR,
/** Mac icon. */
ICNS,
/** Truevision TGA / TARGA */
TGA,
/** Hdr file from radiance using RGBE */
HDR,
/** Tag Image File Format files */
TIFF,
/** DirectDraw Surface */
DDS,
};
ロードする画像の定義っぽいですね。
続いてBPからパスと今回読み込む画像のフォーマットを取得します。
UFUNCTION(BlueprintCallable)
FString ReadBarcodes(const FString& FilePath, EBPImageFormatType format);
FilePathに画像のパス,formatに画像フォーマットを指定します。
正直、実際にカメラを起動して、カメラで撮影したものを読み込むようにするのであればPNGファイルなどで固定にしてもいいかと思います。
では、実装のほうへ。
まずはcppファイルにヘッダーのインクルードを追加します
#include "IImageWrapperModule.h"
#include "IImageWrapper.h"
イメージファイルのロード用後にファイルを実際のテクスチャとして読み込むのに必要です。
処理の中身です。
/// <summary>
/// パスから画像ファイル直接読み込みでテキスト情報を返す
/// </summary>
/// <param name="FilePath">画像パス</param>
/// <param name="format">画像フォーマット</param>
/// <returns></returns>
FString ATestZxing::ReadBarcodes(const FString& FilePath, EBPImageFormatType format)
{
FString str = TEXT("");
// BPように外に出しただけなのでintへの変換を経由して元の状態に戻す
EImageFormat trueFormat = (EImageFormat)((int)format);
IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
// 指定されたフォーマットの画像読み込み用設定
TSharedPtr<IImageWrapper> ImageWrapper = ImageWrapperModule.CreateImageWrapper(trueFormat);
// パスの設定
TArray<uint8> RawFileData;
// データの読み込み
if (FFileHelper::LoadFileToArray(RawFileData, *FilePath)) {
TArray<uint8> UncompressedRawData;
if (ImageWrapper.IsValid() &&
// 圧縮データ指定
ImageWrapper->SetCompressed(RawFileData.GetData(), RawFileData.Num()) &&
// 圧縮されていないデータ取得
ImageWrapper->GetRaw(ERGBFormat::BGRA, 8, UncompressedRawData)
)
{
//// 画像を作成
ZXing::ImageView imageView(UncompressedRawData.GetData(), ImageWrapper->GetWidth(), ImageWrapper->GetHeight(), ZXing::ImageFormat::BGRX);
//// リード
ZXing::Result r = ZXing::ReadBarcode(imageView);
// エラーがなければ文字列設定
if (r.error().type() == ZXing::Error::Type::None) {
std::string buff = r.text();
str = buff.c_str();
}
}
}
return str;
}
ImageWrapperModuleの初期時にフォーマットの指定を行い、
LoadFileToArrayで実際のデータをいったん読み込んで、
ImageWrapper->SetCompressedで読み込んだデータを設定して
ImageWrapper->GetRawで画像データとなる元データを取得しています。
そのあとから先はTextureの時と同じですね。
次に、UE側の実装です。
UE側の対応
設定
まずは、忘れないうちにpngの画像を実行ファイル化したときに一緒にコピーされるような設定にします。
1つまで使用したpng画像を別のファルダに移動させます。
今回は「Resource」フォルダを作成してそちらに移動させました。
こちらに画像を配置するときは、ファイルのインポートは不要です。
で、プロジェクト設定でこのResourceファイルは常にコピーされるように設定します。
「編集」→「プロジェクト設定」から「パッケージ化」→「詳細設定」を開きます。
その中に
「コピーする追加の非アセットディレクトリ」というところがあるのでそこに、先ほど追加したResourceを設定します。
「…」の部分をクリックすればエクスプローラーから設定できます。
これで前提の設定は完了です。
実際に処理を実装していきます。
BP実装
ProjectContentDirで「Content」フォルダまでのパスを、
Combineを使って「Resource」フォルダと画像の名前を設定するようにしています。
FileNameはBP側から、設定しています。
これで実行すると右上にURLが出てくるはずです。
(5割くらいデストラクタで例外をはく なんで?・・・・)
では、実行ファイルを作ってみましょう・・・
実行ファイルでは?
結論から申し上げますと、ダメでした。
実行ファイル起動時にすぐにデストラクタのエラーが100%発生して起動すらできない状態です。
ZXingのデストラクタ君なにがダメなの・・・
コメント