Androidで縦向き正方形撮影する時は色々面倒です。面倒なポイントと、解決方法について書いてみました。
カメラの回転
まず、Androidのカメラは横向きに撮ることを前提に作られているので、縦向きに持っても横向きでプレビューは表示されますし、取得した写真も横向きになってしまいます。
ですので、カメラ設定を修正する必要があります。
プレビューの修正
プレビューの修整はContext#setDisplayOrientation(angle)を使います。
Context mContext; public CameraView(Context context, AttributeSet attrs) { super(context, attrs); mContext=context; ... } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) { if(mContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){ int angle=90; mCamera.setDisplayOrientation(angle); } ... }
取得した写真の修整
onPictureTakenなどで取得した写真は、Matrix#setRotate(angle)を使って90度回転させます。
... Matrix matrix=new Matrix(); matrix.setRotate(90); Bitmap source=Bitmap.createBitmap(tmp,0, 0,x,y, matrix, true); ...
正方形の表示
プレビューで正方形で表示するためには、FrameLayoutを使って、正方形外の部分に画像(黒塗りpng等)などを重ねます。
... <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" > <FrameLayout android:id="@+id/frameLayout1" android:layout_width="match_parent" android:layout_height="match_parent" > <com.tomo.appli.CameraView android:id="@+id/cameraView1" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" /> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="top" > <ImageView android:layout_width="match_parent" android:layout_height="140dp" android:gravity="bottom" android:src="@drawable/camera_padding_xhdpi" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="bottom" > <ImageView android:layout_width="match_parent" android:layout_height="140dp" android:gravity="bottom" android:src="@drawable/camera_padding_xhdpi" /> </LinearLayout> </FrameLayout> </LinearLayout> ...
layout_widthはmatch_parentにして横幅最大にしています。
一方layout_heightは140dpにしています。
今テストしている端末が1280*720(px)で、横幅に合わせて正方形にする場合、上下の280px分に上重ね用の画像をかぶせる必要があります。
で、xhdpi(320dp)の画面密度で開発しているので、280pxをdpに直すと
(xhdpiでのdp)=(px)*(160(Androidでの画面密度の基準)/320) =280 * 0.5 =140
dpとpxの関係はややっこしいのですが、↓を見たらある程度わかるかと思います。
Yukiの枝折: Android:画面密度によるリソースのスケーリング
Androidレイアウトの単位 - dpについて掘り下げる - アンテナ立てて
正方形の画像を取得する
ソースコードが長くなりそうなので、また次回。