10
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Unityから画像のピクセル情報をネイティブに渡す方法

10
Last updated at Posted at 2017-11-30

UnityのRenderTextureなどのテクスチャ画像のピクセル情報をネイティブに渡したいケースがありまして、かなり苦労した(特にAndroid側)のでメモ。
ちなみにAndroidはクソ。さっさと消えてほしい。
もう少し具体的にどんな感じで使うかというと、Unity側のWebCameraを使ってその画像データをJavaのライブラリに渡したいみたいなケースです。

サンプルプロジェクトはこちら
https://bitbucket.org/HoshiyamaTakaaki/pixelreadstest

まずはUnity側の実装

CameraOnPost.cs
RenderTexture.active = m_TargetTexture;
m_TargetTexture2D.ReadPixels(new Rect(0, 0, m_TargetTexture.width, m_TargetTexture.height), 0, 0);
m_TargetTexture2D.Apply();

var col = m_TargetTexture2D.GetPixels32();

var handle = default(GCHandle);
try
{
	handle = GCHandle.Alloc(col, GCHandleType.Pinned);
	var ptr = handle.AddrOfPinnedObject();
	libglutil_SetPixels(ptr.ToInt32(), m_TargetTexture.width, m_TargetTexture.height);
}
finally
{
	if (handle != default(GCHandle))
		handle.Free();
}

iPhone側に関してはUnityのGetPixels32がそこそこ早いので、Unity側で普通に色情報を取得してそのポインタをNative側へ渡してやって問題ないと思います。
RenderTextureの場合、一度Texture2Dに移してやる必要があり、その辺りがオーバーヘッドになるので要注意かもしれないです。

CameraOnPost.cs
m_NativePlugin.CallStatic("sendRgbaFrame", m_Context, m_TargetTexture.GetNativeTexturePtr().ToInt32(), m_TargetTexture.width, m_TargetTexture.height);
GL.InvalidateState();

Androidは残念ながらUnityのReadPixelsではパフォーマンスが出ません。
そしてJavaへのbyte[]の引渡しがとても重いです。
もうこの段階で重すぎて使い物になりません。
なのでAndroidではテクスチャをそのままJavaに渡して、Java側でReadPixelsを行います。
ちなみにNDKへの引渡しはiPhoneでやったような形にすれば受け渡しができます。
大きなByte配列の転送はC#→NDK→JNI経由でJavaに渡した方が早いっぽいです。

Java側ではもらったテクスチャを使い、OpenGLESでフレームバッファにテクスチャを描き込みglReadPixelsで読み出します。
しかしAndroidのglReadPixelsはとても重いです。
結局のところ重いです。
PBO(Pixel Buffer Object)を使うと多少速くなります(逆に遅くなる場合もあります)が、やはり重いです。
しかもPBOはOpenGL ES3.0を要求するし、Javaでは完結しなくなってしまうしで、踏んだり蹴ったりです。
(Java完結させるには最低SDK APIを24まで上げる必要あり。上げられるか、バカ)

取得したRGBA情報をMP4などで保存するには、さらにYUVに変換する必要があり、もうこの段階まで来るとカクカクの状態は避けられません。

苦労した割にはあまり使い道がない気もしますが、RenderTextureのサイズを調整すれば、パフォーマンスはある程度改善します。

その他、Androidは色々と苦労しました。
aarに他で作成されたsoを含める方法も、探すのにかなり苦労しました。
64ビット版のsoファイルを含めるとUnityで作ったアプリを起動した瞬間にポップアップが出て終了するのも解決に時間がかかりました。

今回のサンプルを作成するに辺り、たくさんの先人の情報をお借りしました。
そしてAnswerの無いたくさんのQuestion(屍)を見ました。
みんなAndroidには困ってるんですね。

どうもありがとうございました。

10
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?