カメラアプリ、撮影後の画像表示と合成

410 views
Skip to first unread message

Anshun

unread,
Jun 24, 2011, 11:14:31 PM6/24/11
to Android-SDK-Japan
はじめまして、Anshunと申します。
これからお世話になります。

私は現在、撮影した画像にあらかじめ用意していた画像をランダムで合成するカメラアプリを作っています。
いろいろ試行錯誤していますが、分らない点がございます。

作りたいプログラムの流れは、
撮影した画像を合成して表示、保存です。


現在は撮影画像をビットマップに変換するところで、合成して表示のところでつまづいています。
プログラムを実行すると、
写真は撮影できますが、その後何も表示されません。

以下がソースになります。
よろしくお願いします。

/*
* YUV420データをBitmapに変換する
* @param rgb
* @param yuv420sp
* @param width
* @param height
*/
// YUV420 to BMP

public static final void decodeYUV420SP(int[] rgb, byte[] date, int
width, int height) {
final int frameSize = width * height;

for (int j = 0, yp = 0; j < height; j++) {
int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
for (int i = 0; i < width; i++, yp++) {
int y = (0xff & ((int) date[yp])) - 16;
if (y < 0) y = 0;
if ((i & 1) == 0) {
v = (0xff & date[uvp++]) - 128;
u = (0xff & date[uvp++]) - 128;
}

int y1192 = 1192 * y;
int r = (y1192 + 1634 * v);
int g = (y1192 - 833 * v - 400 * u);
int b = (y1192 + 2066 * u);

if (r < 0) r = 0; else if (r > 262143) r = 262143;
if (g < 0) g = 0; else if (g > 262143) g = 262143;
if (b < 0) b = 0; else if (b > 262143) b = 262143;

rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >>
2) & 0xff00) | ((b >> 10) & 0xff);
}
}
}

private final Camera.PreviewCallback _previewCallback =
new Camera.PreviewCallback()
{
public void onPreviewFrame(byte[] data, Camera camera)
{
final int width = getWidth();// プレビューの幅
final int height = getHeight(); // プレビューの高さ
int[] rgb = new int[(width * height)]; // ARGB8888の画素の配列
try {
Bitmap bmp = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888); // ARGB8888で空のビットマップ作成
decodeYUV420SP(rgb, data, width, height); // 変換
bmp.setPixels(rgb, 0, width, 0, 0, width,
height); // 変換した画素からビットマップにセット

Bitmap bitmap2 =
BitmapFactory.decodeResource(getResources(),R.drawable.hukidashi);
Canvas offScreen = new Canvas(bmp);
offScreen.drawBitmap(bmp, 0, height, (Paint)null);
offScreen.drawBitmap(bitmap2, 0, 0, (Paint)null);

// 保存したり、表示したり
Canvas canv = holder.lockCanvas();
canv.drawBitmap(bmp, 0, 0, null);
canv.drawBitmap(rgb, 0, width, 0, 0, width,
height, false, null);
holder.unlockCanvasAndPost(canv);

//★Bitmap newBitmap =
Bitmap.createBitmap(width, height*2, Bitmap.Config.ARGB_8888);
//ベースとするbitmap画像を新規に作成します。
//ここで作る画像の上に、2枚のbitmap画像を載せていきます。drawBitmap
ImageView image =
(ImageView)findViewById(R.id.ImageView01);
image.setImageBitmap(bmp);
} catch (Exception e) {
// エラー
}
}
};


Keiji Ariyama

unread,
Jun 27, 2011, 7:20:02 AM6/27/11
to android-...@googlegroups.com
有山です。

 実際に画面に表示しているのは、SurfaceViewでしょうか。それともImageView
でしょうか。
 コードが一部しかないのでポイントを外しているかもしれませんが、、、

 ImageViewは、Viewシステムの管理化にあり、別スレッドから操作できません。
 従って、重い変換・合成処理を別スレッドでやっている場合は、そのまま
ImageViewに表示しようとしても、反映されません。
 もし別スレッドからImageViewにアクセスしているのであれば、その部分の処
理をHandlerを経由するか、ThreadでなくAsyncTaskを使っては如何でしょうか。

 当該処理部分を、別スレッドにしていない場合ですが、decodeYUV420SPの処理
には時間がかかるので、メインスレッド内で実行した場合、画面が更新されない
ように見える可能性があります。
 この場合も、AsyncTaskなどで非同期処理にすることをお勧めします。
 また、プレビューフレームをリアルタイムで合成するのは性能的に難しいの
で、適当に中抜きをした方がよいと考えます。

 最後に、Exceptionは、そのままでなく、個別のExceptionをキャッチすること
をお勧めします。個別のExceptionをキャッチせず、また、Exceptionをcatchし
た時に、なんの出力も行わないと、エラーが起こっていてもその事が判らず、開
発の妨げになります。

> int y = (0xff& ((int) date[yp])) - 16;


> if (y< 0) y = 0;

> if ((i& 1) == 0) {
> v = (0xff& date[uvp++]) - 128;
> u = (0xff& date[uvp++]) - 128;


> }
>
> int y1192 = 1192 * y;
> int r = (y1192 + 1634 * v);
> int g = (y1192 - 833 * v - 400 * u);
> int b = (y1192 + 2066 * u);
>
> if (r< 0) r = 0; else if (r> 262143) r = 262143;
> if (g< 0) g = 0; else if (g> 262143) g = 262143;
> if (b< 0) b = 0; else if (b> 262143) b = 262143;
>
> rgb[yp] = 0xff000000 | ((r<< 6)& 0xff0000) | ((g>>

> 2)& 0xff00) | ((b>> 10)& 0xff);

--
Keiji,
ml_an...@c-lis.co.jp

Reply all
Reply to author
Forward
0 new messages