GraveDollの備忘録ブログ

勉強したことや捗るグッズの備忘録です。

修行その壱「フォトメモ」(3)

写真の向きを決める

写真の大きさを決める

今回は端末の向きと写真の向きを合わせてなるべく画面いっぱいに表示するため、写真の向きと大きさを決めます。
PhotoMemoView.javaに回転とリサイズ処理を実装しました。また、PhotoMemoActivity.javaも少し変更しました。
いろいろ見づらいとこがありますが、後で直しますw

PhotoMemoActivity.java

import java.io.File;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.Display;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

// メイン画面(Activity)
public class PhotoMemoActivity extends Activity {
	
	static final int REQUEST_CAPTURE_IMAGE = 100;/*onActivityResult内で識別するためのID*/
	// 描画対象のViewを保持するメンバ変数
	private PhotoMemoView mView;	

	// 画面(Activity)が生成されるときの処理
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);		
		Uri saveUri;
		Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);//カメラアプリ呼び出し
		saveUri = Uri.fromFile(new File(Environment
				.getExternalStorageDirectory() + "/tmp.jpg"));//写真を格納するURI
		intent.putExtra(MediaStore.EXTRA_OUTPUT, saveUri);//カメラアプリをインテントで呼び出すときに写真格納場所情報を渡すよう設定
		startActivityForResult(intent, REQUEST_CAPTURE_IMAGE);//カメラアプリ起動
		mView = null;//Viewを初期化
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (REQUEST_CAPTURE_IMAGE == requestCode && resultCode == Activity.RESULT_OK) {
			File dir = new File(Environment.getExternalStorageDirectory().getPath());//写真を格納するディレクトリ
			if(dir.exists()){
			    File file = new File(dir.getAbsolutePath()+"/tmp.jpg");	//写真のURI		    
			    if (file.exists()) {					
			    	Bitmap capturedImage = BitmapFactory.decodeFile(file.getPath());
			    	// 描画対象のViewを生成し、
			    	mView = new PhotoMemoView(this,capturedImage);		    	
			    	// 描画対象のViewを画面に表示する
			    	setContentView(mView);
			    	mView.setImageBitmap(capturedImage);//ビットマップ画像をimageViewに表示			    	
			    }
		    	else{
		    		//存在しない場合
		    		mView = new PhotoMemoView(this);
		    		setContentView(mView);
		    	}			    
			}			
		}
	}

	// 端末のメニューボタンが押されたときの処理
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// res/menu/menu.xmlを読み込み、メニューを生成する
		getMenuInflater().inflate(R.menu.menu, menu);
		return super.onCreateOptionsMenu(menu);
	}

	// メニューの項目が選ばれたときの処理
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// 選ばれたメニューの種類(ID)に応じて、処理する
		switch (item.getItemId()) {
		// メニュー「線の太さ」の処理
		case R.id.menu_paintwidth:
			// まだ処理を実装していない旨のメッセージを表示する
			Toast.makeText(this, R.string.message_no_function,
					Toast.LENGTH_SHORT).show();
			break;
		// メニュー「線の色」の処理
		case R.id.menu_paintcolor:
			// まだ処理を実装していない旨のメッセージを表示する
			Toast.makeText(this, R.string.message_no_function,
					Toast.LENGTH_SHORT).show();
			break;
		default:
			break;
		}
		return super.onOptionsItemSelected(item);
	}
}

PhotoMemoView.java

import java.io.File;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.widget.ImageView;

// 描画対象となるViewを定義するクラス
public class PhotoMemoView extends ImageView {
	private Bitmap capturedImage;
		
    //コンストラクタ(撮影した写真が存在しない場合)
    public PhotoMemoView(Context context) {
        super(context);        
        // 背景を白にする
        setBackgroundColor(Color.WHITE);        
    }
    
    // コンストラクタ(撮影した写真が存在する場合)
    public PhotoMemoView(Context context, Bitmap bitmap) {
        super(context);        
        capturedImage = bitmap;//撮影した写真で初期化  
        setBackgroundColor(Color.WHITE);// 背景を白にする 
    }
    	
	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {//Viewのサイズが変わったとき

			Resources resources = getResources();
			Configuration config = resources.getConfiguration();
	    		int imageWidth = capturedImage.getWidth();//画像の幅
	    		int imageHeight = capturedImage.getHeight();//画像の高さ
	    		
	    		float scale = 0.0f;//Viewと写真の比率を0で初期化
	    		int scaleWidth = w/imageHeight;//Viewと写真の横縮尺(写真は横サイズと縦サイズが入れ替わるため高さで割っている)
	    		int scaleHeight = h/imageWidth;//Viewと写真の縦縮尺(写真は横サイズと縦サイズが入れ替わるため幅で割っている)

	    		Matrix matrix = new Matrix();
				
	    		//端末の向きと写真の向きを合わせる
				switch(config.orientation) {
				case Configuration.ORIENTATION_PORTRAIT://端末が縦向きの場合
					if(capturedImage.getWidth()>capturedImage.getHeight())//写真が横向きの場合
					matrix.postRotate(90);//90度回転をマトリクスに設定
					break;
				case Configuration.ORIENTATION_LANDSCAPE://端末が横向きの場合
					if(capturedImage.getHeight()>capturedImage.getWidth())//写真が縦向きの場合
					matrix.postRotate(270);//270度回転をマトリクスに設定
					break;
				default :
					}
				//縦縮尺、横縮尺で小さい方をViewと写真全体との縮尺にする
				if(scaleWidth>scaleHeight)
					scale = scaleHeight;
				else
					scale = scaleWidth;
		    	    //縮尺が1より小さい(写真のほうがViewより大きい)場合
				if(scale < 1)
					matrix.postScale(scale,scale);//縮小する比率をマトリクスに設定
				
		    	Bitmap rotatedImage = Bitmap.createBitmap(capturedImage, 0, 0, capturedImage.getWidth(), capturedImage.getHeight(), matrix, true);//回転、縮小した画像		
		    	this.setImageBitmap(rotatedImage);
		}

	}
  • onSizeChanged()はViewのサイズが変わった時に呼び出されるので、ここに写真の回転とリサイズ処理を記述しました。
  • 写真サイズを何に合わせて変更すればよいのかわからなかったので、少し模範演技(実装例)を見てしまいましたw
				//縦縮尺、横縮尺で小さい方をViewと写真全体との比率にする
				if(scaleWidth>scaleHeight)
					scale = scaleHeight;
				else
					scale = scaleWidth;
		    	    //比率が1より小さい(写真のほうがViewより大きい)場合
				if(scale < 1)
					matrix.postScale(scale,scale);//縮小する比率をマトリクスに設定

この部分では、写真がViewより大きい場合に、写真を縮小表示させてViewのサイズに収まるようにしています。そのときは縦と横で縮尺が小さい方に合わせています。これにより、写真がViewのサイズに収まります。