カメラ描画とOpenGLのjpg保存方法

2,410 views
Skip to first unread message

fujimoto

unread,
Jul 5, 2011, 11:36:53 AM7/5/11
to 日本Androidの会
こんにちは、
ふじもと
と申します。

カメラの上に 2Dないし3Dを重ねたソフトをつくりました。
今度は、それを静止画でjpg保存をしたいのですが、適当な
回答がないため、どなたか具体的な方法を教えてください。

glReadPixelsをつかってフレームバッファをとる必要があるとかどうとか?
onPictureTakenを使ったりしましたが、引数がいまいちだめだったり。
Android バージョン2.1 です。

何か方法をご存知の方がいらっしゃいましたら
ご教授のほどよろしくお願いいたします。

Python O

unread,
Jul 6, 2011, 4:12:21 AM7/6/11
to android-g...@googlegroups.com
カメラのViewとOpenGLのVIewは別々にSurfaceを持っているので、
一括で画像情報を取得するのは無理だと思います。

OpenGLのViewのバッファはやはりglReadPixelsを使ってバッファを
取得して、Bitmapオブジェクトを作ればいいと思います。

カメラのViewの方は、もしかしたら既にご存知かもしれませんが、
onPictureTakenから取得できる値はRGBじゃなくて
YUVなので(すいませんYUVのどの種類かはちょっと忘れました)、
まずYUVをRGBに変換する必要があります。

すいません。カメラの方はうろ覚えなので、あまり自信はないです。

2011年7月6日0:36 fujimoto <tuyo...@yahoo.co.jp>:

--
このメールは Google グループのグループ「日本Androidの会」の登録者に送られています。
このグループに投稿するには、android-g...@googlegroups.com にメールを送信してください。
このグループから退会するには、android-group-j...@googlegroups.com にメールを送信してください。
詳細については、http://groups.google.com/group/android-group-japan?hl=ja からこのグループにアクセスしてください。


fujimoto

unread,
Jul 10, 2011, 4:12:07 AM7/10/11
to 日本Androidの会
glReadPixels で、ただしく取得できませんでした。

特にCameraクラスとOpenGLクラスは別々につくっています。
glReadPixelsは、OpenGLクラス内で行うと思うのですが、
GL10は、Cameraクラスから拾って使うのか、やり方が違っているようです。

説明がわかりにくいと思いますが
どななた適当なサンプルがあれば
ご教授お願いします。



On Jul 6, 5:12 pm, Python O <a5n22...@gmail.com> wrote:
> カメラのViewとOpenGLのVIewは別々にSurfaceを持っているので、
> 一括で画像情報を取得するのは無理だと思います。
>
> OpenGLのViewのバッファはやはりglReadPixelsを使ってバッファを
> 取得して、Bitmapオブジェクトを作ればいいと思います。
>
> カメラのViewの方は、もしかしたら既にご存知かもしれませんが、
> onPictureTakenから取得できる値はRGBじゃなくて
> YUVなので(すいませんYUVのどの種類かはちょっと忘れました)、
> まずYUVをRGBに変換する必要があります。
>
> すいません。カメラの方はうろ覚えなので、あまり自信はないです。
>
> 2011年7月6日0:36 fujimoto <tuyope...@yahoo.co.jp>:

Python O

unread,
Jul 10, 2011, 6:18:40 AM7/10/11
to android-g...@googlegroups.com
適当に作ったので、どの端末でも動作保障ってわけにはいかないですけど、一応簡単なプロジェクト添付しました

重要なのはViewの描画と一緒でAndroidのOpenGLの描画はシングルスレッドモデルだってことです。
外部のスレッドからOpenGLの操作を行うことはできません。

なので、外部のスレッドからOpenGLの操作を行う場合にはqueueEventメソッドで
操作依頼を出す必要があります。

あと、glReadPixels呼ぶだけだと、OpenGL内部で保持しているピクセル情報と
こちらで保持したいビットマップのピクセル情報にずれがあるので、glPixelStoreiで整えてやる必要があります。

あと、サンプルではカメラ画像とOpenGL画像の合成は行っていないです。
あくまで、カメラ画像の保存を行うスレッドからOpenGLの画像の保存を行うサンプルということで。

2011年7月10日17:12 fujimoto <tuyo...@yahoo.co.jp>:
SampleCameraGL.zip

fujimoto

unread,
Aug 2, 2011, 9:32:01 AM8/2/11
to 日本Androidの会
SampleCameraGLサンプルありがとうございます。
非常に参考になりました。
あとは、写真2枚の合成方法ですが、
別途関数クラスをつくって処理すべきでしょうか?
それとも、つくれたjpgから合成処理すべきでしょうか。
適度な作成方法がありましたら
ご教授お願いします。


On Jul 10, 7:18 pm, Python O <a5n22...@gmail.com> wrote:
> 適当に作ったので、どの端末でも動作保障ってわけにはいかないですけど、一応簡単なプロジェクト添付しました
>
> 重要なのはViewの描画と一緒でAndroidのOpenGLの描画はシングルスレッドモデルだってことです。
> 外部のスレッドからOpenGLの操作を行うことはできません。
>
> なので、外部のスレッドからOpenGLの操作を行う場合にはqueueEventメソッドで
> 操作依頼を出す必要があります。
>
> あと、glReadPixels呼ぶだけだと、OpenGL内部で保持しているピクセル情報と
> こちらで保持したいビットマップのピクセル情報にずれがあるので、glPixelStoreiで整えてやる必要があります。
>
> あと、サンプルではカメラ画像とOpenGL画像の合成は行っていないです。
> あくまで、カメラ画像の保存を行うスレッドからOpenGLの画像の保存を行うサンプルということで。
>
> 2011年7月10日17:12 fujimoto <tuyope...@yahoo.co.jp>:
> SampleCameraGL.zip
> 88KViewDownload

田代透

unread,
Aug 2, 2011, 1:51:08 PM8/2/11
to android-g...@googlegroups.com
2つの画像がとれているのならばcanvasを作成して合成すれば良いのじゃないですか?

2011年8月2日22:32 fujimoto <tuyo...@yahoo.co.jp>:

--
--
Toru Tashiro
toru...@gmail.com

fujimoto

unread,
Aug 17, 2011, 4:28:55 AM8/17/11
to 日本Androidの会
SampleCameraGLサンプル利用しております。
カメラを横画面にしています。
screenOrientation="landscape" で実行すると
グラフィクが描画しなくなりました。
どなかた解決方法をご教授お願いします。


On Aug 2, 10:32 pm, fujimoto <tuyope...@yahoo.co.jp> wrote:
> SampleCameraGLサンプルありがとうございます。
> 非常に参考になりました。
> あとは、写真2枚の合成方法ですが、
> 別途関数クラスをつくって処理すべきでしょうか?
> それとも、つくれたjpgから合成処理すべきでしょうか。
> 適度な作成方法がありましたら
> ご教授お願いします。
>
> On Jul 10, 7:18 pm, Python O <a5n22...@gmail.com> wrote:
>
>
>
>
>
>
>
> > 適当に作ったので、どの端末でも動作保障ってわけにはいかないですけど、一応簡単なプロジェクト添付しました
>
> > 重要なのはViewの描画と一緒でAndroidのOpenGLの描画はシングルスレッドモデルだってことです。
> > 外部のスレッドからOpenGLの操作を行うことはできません。
>
> > なので、外部のスレッドからOpenGLの操作を行う場合にはqueueEventメソッドで
> > 操作依頼を出す必要があります。
>
> > あと、glReadPixels呼ぶだけだと、OpenGL内部で保持しているピクセル情報と
> > こちらで保持したいビットマップのピクセル情報にずれがあるので、glPixelStoreiで整えてやる必要があります。
>
> > あと、サンプルではカメラ画像とOpenGL画像の合成は行っていないです。
> > あくまで、カメラ画像の保存を行うスレッドからOpenGLの画像の保存を行うサンプルということで。
>
> > 2011年7月10日17:12fujimoto<tuyope...@yahoo.co.jp>:
>
> > > glReadPixels で、ただしく取得できませんでした。
>
> > > 特にCameraクラスとOpenGLクラスは別々につくっています。
> > > glReadPixelsは、OpenGLクラス内で行うと思うのですが、
> > > GL10は、Cameraクラスから拾って使うのか、やり方が違っているようです。
>
> > > 説明がわかりにくいと思いますが
> > > どななた適当なサンプルがあれば
> > > ご教授お願いします。
>
> > > On Jul 6, 5:12 pm, Python O <a5n22...@gmail.com> wrote:
> > > > カメラのViewとOpenGLのVIewは別々にSurfaceを持っているので、
> > > > 一括で画像情報を取得するのは無理だと思います。
>
> > > > OpenGLのViewのバッファはやはりglReadPixelsを使ってバッファを
> > > > 取得して、Bitmapオブジェクトを作ればいいと思います。
>
> > > > カメラのViewの方は、もしかしたら既にご存知かもしれませんが、
> > > > onPictureTakenから取得できる値はRGBじゃなくて
> > > > YUVなので(すいませんYUVのどの種類かはちょっと忘れました)、
> > > > まずYUVをRGBに変換する必要があります。
>
> > > > すいません。カメラの方はうろ覚えなので、あまり自信はないです。
>
> > > > 2011年7月6日0:36fujimoto<tuyope...@yahoo.co.jp>:

Tomonori Hatsukaku

unread,
Aug 17, 2011, 5:12:02 AM8/17/11
to android-g...@googlegroups.com
それの解決方法ですが、メニューのプロジェクト>プロパティーを選択して、
ビルドするAndroidのバージョンを2.1以上にしてください。
その後で、SampleCameraGLActivity.java のonCreateメソッドの処理の一番最後に
mGLSurfaceView.setZOrderOnTop(true);を加えてください。

こんな感じです。
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Create OpenGL SurfaceView
        mGLSurfaceView = new MyGLSurfaceView(this);

        // Create CameraView
        mCameraView = new CameraView(this, mGLSurfaceView);

        // Set Contents
        //setContentView(mGLSurfaceView);
        setContentView(mCameraView);
        LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
        addContentView(mGLSurfaceView, params);
        
        mGLSurfaceView.setZOrderOnTop(true);
    }

この問題の原因ですが、どうもandroid:screenOrientation="landscape"をやると、
SurfaceのZ値の値が強制されるようです。
Androidの描画システムは複数のSurfaceから色情報をSurfaceFlingerが受け取って、
SurfaceFlingerがそれらを結合して、ビデオバッファとして送り出すという構造になっています。

普通のビュー(ImageViewやButtonなどのビュー)の場合はRootViewが持っている1つのSurfaceに描画内容が
集約されるので、指定したレイアウトに従って描画されるので順番が狂うことはないですが、
カメラビューやGLSurfaceVIewのようなSurfaceViewを継承したビューの場合は独立したSurfaceを持っています。

複数のSurfaceが存在する場合、SurfaceFlingerは各Surfaceが持っているZ値で描画順序を決定します。
これのせいで、指定したレイアウトとは異なる描画順序でビューが描画されてしまいます。

setZOrderOnTop(true)はAndroid2.1以降にSurfaceViewに追加されたメソッドでそのSurfaceViewのSurfaceのZ値を
一番上に描画するように変更します。

2011年8月17日17:28 fujimoto <tuyo...@yahoo.co.jp>:

fujimoto

unread,
Aug 18, 2011, 10:33:40 AM8/18/11
to 日本Androidの会
非常にわかりやすく説明していだだきありがとうございました。m(._.)m
> 2011年8月17日17:28 fujimoto <tuyope...@yahoo.co.jp>:
Reply all
Reply to author
Forward
0 new messages