tomoima525's blog

Androidとか技術とかその他気になったことを書いているブログ。世界の秘密はカレーの中にある!サンフランシスコから発信中。

Androidで縦向き正方形撮影する時の苦労あれこれ(その1)

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等)などを重ねます。


f:id:tomoima525:20140208134302p:plain


...
    <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について掘り下げる - アンテナ立てて

正方形の画像を取得する

ソースコードが長くなりそうなので、また次回。