【Unity】【C#】BMP をランタイムで読み込む 
2019/09/12 Thu [edit]
実は VRM Live Viewer には既に導入されているのだが、BMP を画像素材(テクスチャ)として利用したいこともあるだろう。実装当時、ググっても英語サイトしか出てこなかったので、需要は少ないのかも知れないが、探すのに苦労しないように備忘録として残しておく。
今回紹介する方法は、オープンソースの BMPLoader を使う方法だ。
以前「ランタイム時にファイルをドラッグ&ドロップして取得する」で紹介した「UnityWindowsFileDrag-Drop」の作者の Bunny83 さんの配布ライブラリで、とても簡単に扱えたので、その方法を書いておこう。
(※) Unity 2018.4.8f1 / Windows10(x64) で確認
■BMPLoader を導入する
導入方法は簡単だ。以下の公開サイトへ行き、コピペで C# ファイルを作って欲しい。ページの一番下の方に「Raw Paste Data」という欄があるので、ここからコピーするのが簡単だろう。
・BMPLoader.cs
■簡単なサンプルを作ってみる(基本的なコード)
ググってみるといくつか出てくるので、以下などを参考にするのも良いだろう。
・How to load a BMP file in binary?
・How can I use a .bmp file and create a Texture in Unity at runtime?
実際には BMPLoader.LoadBMP() はいくつかオーバーロードがあるので、利用方法によって使い分けるのも良いかも知れない。ここでは後述する「非同期ロードに対応してみる」に合わせた書き方となっている。定義をみて自分なりに書き換えるのも良いだろう。
●BMPLoadTest.cs(※名前は任意)
using System.IO;
using UnityEngine;
using UnityEngine.UI;
using B83.Image.BMP;
public class BMPLoadTest : MonoBehaviour
{
public RawImage image; //読み込み先(※インスペクタで UI を設定)
public string filePath = "c:/test/image/sample.bmp"; //※ファイルは任意
// Use this for initialization
private void Start()
{
var bytes = File.ReadAllBytes(filePath);
var loader = new BMPLoader();
//loader.ForceAlphaReadWhenPossible = true; // can be uncomment to read alpha
var bmpImage = loader.LoadBMP(bytes);
image.texture = bmpImage.ToTexture2D();
}
private void OnDestroy()
{
if (image.texture != null)
{
Destroy(image.texture);
image.texture = null;
}
}
}
このサンプルではエラーのチェック等は省略しているので、あくまで全て必要なもの(ファイルとか)が揃っている場合であることを留意しておいて欲しい。
とりあえず、BMP をロードして表示できたなら成功だ。
■非同期ロードに対応してみる
とりあえず前述の基本的なコードでも十分なのだが、動作確認が取れたなら、ちょっと手を加えて非同期読み込みすると良いかも知れない。ただし、以下のコードは .NET 4.x 以降である必要がある。
●BMPLoadTest.cs(※名前は任意)
using System.IO;
using System.Threading.Tasks; //※追加
using UnityEngine;
using UnityEngine.UI;
using B83.Image.BMP;
public class BMPLoadTest : MonoBehaviour
{
public RawImage image; //読み込み先(※インスペクタで UI を設定)
public string filePath = "c:/test/image/sample.bmp"; //※ファイルは任意
// Use this for initialization
private async void Start() //※async を追加
{
var bytes = await Task.Run(() => File.ReadAllBytes(filePath)); //※Task で別スレッドで読み込み
var loader = new BMPLoader();
//loader.ForceAlphaReadWhenPossible = true; // can be uncomment to read alpha
var bmpImage = await Task.Run(() => loader.LoadBMP(bytes)); //※Task で別スレッドでロード
image.texture = bmpImage.ToTexture2D();
}
private void OnDestroy()
{
if (image.texture != null)
{
Destroy(image.texture);
image.texture = null;
}
}
}
ファイルの大きさにもよるが、私が計測したところ、非同期にすれば約1.5倍くらいの速度で読み込める。もし、UniRx を使っているのなら、Task は UniTask にした方が良いだろう。
ここでは簡単なサンプルなので Start() でやってしまったが、static なメソッドにしてしまえば、使い回しもできて非常に便利だ。その場合にはファイル名やファイル自体の存在チェック、非同期キャンセルのための CancellationToken など入れた方が良いだろう。Task.Run() は2回に分けてあるが、ファイル読み込み/テクスチャとしてロードするのに時間がかかることを考慮して、それぞれにキャンセルチェックをした方が良いと思う(きちんと実装すると結構長くなるため、今回は要点だけにした)。その辺りはご自由に(笑)。
ちなみに私が提供しているプラグインを使えば、Android でも BMP を読み込めた。実際にスマホで全天球ビューワを作ることも可能だ(これが VRM Live Viewer で実装されている)。
(関連記事)
【Unity】【C#】TGAをランタイムでロードする
【Unity】【C#】ランタイム時にファイルをドラッグ&ドロップして取得する(Windows のみ)
【Unity】スマホで簡易360度(パノラマ, 全天球)ビューワを作る
【Unity】Androidのトーストやダイアログ、通知、音声認識、ハード音量操作など基本的な機能を使えるプラグインを作ってみた
【Unity】AssetStore版 FantomPlugin のセットアップ
- 関連記事
-
-
【Unity】【C#】UI-Text 版 FPS(フレームレート)をリアルタイムに測定して表示する
-
【Unity】【C#】InputSystem.TouchPhase の IsActive(), IsEndedOrCanceled() [拡張メソッド] の具体値
-
【Unity】Androidでチェックボックス付きのアラートダイアログ(AlertDialog)を使う
-
【Unity】【C#】KeyCode をリアルタイムで調べる / Windows 日本語キーボードでの記号の KeyCode 一覧
-
【Unity】UI のフォーカスを外すコードと「Attempting to select while already selecting an object.」
-
トラックバック
トラックバックURL
→http://fantom1x.blog130.fc2.com/tb.php/337-1836a4d9
この記事にトラックバックする(FC2ブログユーザー)
| h o m e |