Symfoware

Symfowareについての考察blog

Android Matrixで画像の拡大・縮小

Androidで表示している画像を拡大する方法を調べてみます。


最初のサンプル



画像を拡大するには、「Matrix」を変更すれば良いようです。
Matrix

こんなサンプルを書いてみました。

・activity_main.xml


  1. <?xml version="1.0" encoding="utf-8"?>
  2. <android.support.constraint.ConstraintLayout
  3.     xmlns:android="http://schemas.android.com/apk/res/android"
  4.     xmlns:app="http://schemas.android.com/apk/res-auto"
  5.     xmlns:tools="http://schemas.android.com/tools"
  6.     android:layout_width="match_parent"
  7.     android:layout_height="match_parent"
  8.     tools:context="com.example.baranche.myapplication.MainActivity">
  9.     <Button
  10.         android:id="@+id/btn1"
  11.         android:layout_width="wrap_content"
  12.         android:layout_height="wrap_content"
  13.         android:text="拡大"
  14.         android:onClick="expansionClick"
  15.         app:layout_constraintTop_toTopOf="parent"
  16.         app:layout_constraintLeft_toRightOf="parent">
  17.     </Button>
  18.     <ImageView
  19.         android:id="@+id/imageView"
  20.         android:layout_width="match_parent"
  21.         android:layout_height="match_parent"
  22.         android:scaleType="center"
  23.         app:layout_constraintTop_toTopOf="@+id/btn1"
  24.         app:layout_constraintLeft_toRightOf="parent"
  25.         app:layout_constraintBottom_toBottomOf="parent"
  26.          />
  27. </android.support.constraint.ConstraintLayout>





・MainActivity.java


  1. import android.graphics.Matrix;
  2. import android.support.v7.app.AppCompatActivity;
  3. import android.os.Bundle;
  4. import android.view.View;
  5. import android.widget.ImageView;
  6. public class MainActivity extends AppCompatActivity {
  7.     private ImageView mImage;
  8.     @Override
  9.     protected void onCreate(Bundle savedInstanceState) {
  10.         super.onCreate(savedInstanceState);
  11.         setContentView(R.layout.activity_main);
  12.         mImage = (ImageView)findViewById(R.id.imageView);
  13.         mImage.setImageResource(R.mipmap.ic_launcher);
  14.     }
  15.     public void expansionClick(View view) {
  16.         // matrixを取得
  17.         Matrix m = mImage.getImageMatrix();
  18.         // matrixの値を取得
  19.         float[] values = new float[9];
  20.         m.getValues(values);
  21.         // Xの拡大率を表示
  22.         float scale = values[Matrix.MSCALE_X];
  23.         setTitle("MSCALE_X:" + Float.toString(scale));
  24.         // 一旦matrixをリセット
  25.         m.reset();
  26.         // XYの拡大率を2倍にして再表示
  27.         m.postScale(scale * 2.0f, scale * 2.0f);
  28.         mImage.invalidate();
  29.     }
  30. }





初期表示

795_01.png

ボタンを押したら画像サイズを2倍にする予定ですが、左上によってしまいます。

795_02.png


画像の水平、垂直移動も合わせて指定する必要がありそうです。


  1. import android.graphics.Matrix;
  2. import android.support.v7.app.AppCompatActivity;
  3. import android.os.Bundle;
  4. import android.view.View;
  5. import android.widget.ImageView;
  6. public class MainActivity extends AppCompatActivity {
  7.     private ImageView mImage;
  8.     @Override
  9.     protected void onCreate(Bundle savedInstanceState) {
  10.         super.onCreate(savedInstanceState);
  11.         setContentView(R.layout.activity_main);
  12.         mImage = (ImageView)findViewById(R.id.imageView);
  13.         mImage.setImageResource(R.mipmap.ic_launcher);
  14.     }
  15.     public void expansionClick(View view) {
  16.         // matrixを取得
  17.         Matrix m = mImage.getImageMatrix();
  18.         // matrixの値を取得
  19.         float[] values = new float[9];
  20.         m.getValues(values);
  21.         // Xの拡大率を表示
  22.         float scale = values[Matrix.MSCALE_X];
  23.         setTitle("MSCALE_X:" + Float.toString(scale));
  24.         float transx = values[Matrix.MTRANS_X];
  25.         float transy = values[Matrix.MTRANS_Y];
  26.         // 一旦matrixをリセット
  27.         m.reset();
  28.         // XYの拡大率を2倍にして再表示
  29.         m.postScale(scale * 2.0f, scale * 2.0f, -transx, -transy);
  30.         mImage.invalidate();
  31.     }
  32. }




795_03.png


postScaleを使用しないパターンはこちら。


  1. import android.graphics.Matrix;
  2. import android.support.v7.app.AppCompatActivity;
  3. import android.os.Bundle;
  4. import android.view.View;
  5. import android.widget.ImageView;
  6. public class MainActivity extends AppCompatActivity {
  7.     private ImageView mImage;
  8.     @Override
  9.     protected void onCreate(Bundle savedInstanceState) {
  10.         super.onCreate(savedInstanceState);
  11.         setContentView(R.layout.activity_main);
  12.         mImage = (ImageView)findViewById(R.id.imageView);
  13.         mImage.setImageResource(R.mipmap.ic_launcher);
  14.     }
  15.     public void expansionClick(View view) {
  16.         // matrixを取得
  17.         Matrix m = mImage.getImageMatrix();
  18.         // matrixの値を取得
  19.         float[] values = new float[9];
  20.         m.getValues(values);
  21.         // Xの拡大率を表示
  22.         float scale = values[Matrix.MSCALE_X];
  23.         setTitle("MSCALE_X:" + Float.toString(scale));
  24.         // XYの拡大率を2倍に変更
  25.         values[Matrix.MSCALE_X] = scale * 2.0f;
  26.         values[Matrix.MSCALE_Y] = scale * 2.0f;
  27.         // 一旦matrixをリセット
  28.         m.reset();
  29.         m.setValues(values);
  30.         mImage.invalidate();
  31.     }
  32. }



結果はpostScaleを使用した場合と同じになります。




中心を原点に拡大



画像を中央に表示したまま拡大してみます。
元画像 * 拡大サイズを計算し、中央座標に寄るようにXYの移動距離を求めます。


  1. import android.graphics.Matrix;
  2. import android.graphics.Rect;
  3. import android.support.v7.app.AppCompatActivity;
  4. import android.os.Bundle;
  5. import android.view.View;
  6. import android.widget.ImageView;
  7. public class MainActivity extends AppCompatActivity {
  8.     private ImageView mImage;
  9.     @Override
  10.     protected void onCreate(Bundle savedInstanceState) {
  11.         super.onCreate(savedInstanceState);
  12.         setContentView(R.layout.activity_main);
  13.         mImage = (ImageView)findViewById(R.id.imageView);
  14.         mImage.setImageResource(R.mipmap.ic_launcher);
  15.     }
  16.     public void expansionClick(View view) {
  17.         // matrixを取得
  18.         Matrix m = mImage.getImageMatrix();
  19.         // matrixの値を取得
  20.         float[] values = new float[9];
  21.         m.getValues(values);
  22.         // Xの拡大率を表示
  23.         float scale = values[Matrix.MSCALE_X];
  24.         setTitle("MSCALE_X:" + Float.toString(scale));
  25.         // XYの拡大率を2倍に変更
  26.         values[Matrix.MSCALE_X] *= 2.0f;
  27.         values[Matrix.MSCALE_Y] *= 2.0f;
  28.         // XY座標の移動位置を計算
  29.         calcTrans(values);
  30.         // 値を再設定
  31.         m.setValues(values);
  32.         mImage.invalidate();
  33.     }
  34.     private void calcTrans(float[] values) {
  35.         // 画像の描画領域
  36.         Rect rect = new Rect();
  37.         mImage.getDrawingRect(rect);
  38.         // 元画像のサイズ
  39.         int imgWidth = mImage.getDrawable().getIntrinsicWidth();
  40.         int imgHeight = mImage.getDrawable().getIntrinsicHeight();
  41.         // 拡大後の画像幅
  42.         int imgScaledWidth = Math.round(imgWidth * values[Matrix.MSCALE_X]);
  43.         // 拡大後の画像高さ
  44.         int imgScaledHeight = Math.round(imgHeight * values[Matrix.MSCALE_Y]);
  45.         // 表示位置中央X座標 - (拡大後の画像幅 / 2)がX移動距離
  46.         values[Matrix.MTRANS_X] = (rect.width() / 2) - (imgScaledWidth / 2);
  47.         // 表示位置中央Y座標 - (拡大後の画像高さ / 2)がY移動距離
  48.         values[Matrix.MTRANS_Y] = (rect.height() / 2) - (imgScaledHeight / 2);
  49.     }
  50. }




これで中央を原点に拡大してくれました。

795_04.png

795_05.png




中央を原点に縮小



縮小も拡大と同じ計算で良いはずです。


  1. import android.graphics.Matrix;
  2. import android.graphics.Rect;
  3. import android.support.v7.app.AppCompatActivity;
  4. import android.os.Bundle;
  5. import android.view.View;
  6. import android.widget.ImageView;
  7. public class MainActivity extends AppCompatActivity {
  8.     private ImageView mImage;
  9.     @Override
  10.     protected void onCreate(Bundle savedInstanceState) {
  11.         super.onCreate(savedInstanceState);
  12.         setContentView(R.layout.activity_main);
  13.         mImage = (ImageView)findViewById(R.id.imageView);
  14.         mImage.setImageResource(R.mipmap.ic_launcher);
  15.     }
  16.     // 拡大ボタン
  17.     public void expansionClick(View view) {
  18.         // matrixを取得
  19.         Matrix m = mImage.getImageMatrix();
  20.         // matrixの値を取得
  21.         float[] values = new float[9];
  22.         m.getValues(values);
  23.         // Xの拡大率を表示
  24.         float scale = values[Matrix.MSCALE_X];
  25.         setTitle("MSCALE_X:" + Float.toString(scale));
  26.         // XYの拡大率を2倍に変更
  27.         values[Matrix.MSCALE_X] *= 2.0f;
  28.         values[Matrix.MSCALE_Y] *= 2.0f;
  29.         // XY座標の移動位置を計算
  30.         calcTrans(values);
  31.         // 値を再設定
  32.         m.setValues(values);
  33.         mImage.invalidate();
  34.     }
  35.     // 縮小ボタン
  36.     public void reductionClick(View view) {
  37.         // matrixを取得
  38.         Matrix m = mImage.getImageMatrix();
  39.         // matrixの値を取得
  40.         float[] values = new float[9];
  41.         m.getValues(values);
  42.         // Xの拡大率を表示
  43.         float scale = values[Matrix.MSCALE_X];
  44.         setTitle("MSCALE_X:" + Float.toString(scale));
  45.         // XYの拡大率を2倍に変更
  46.         values[Matrix.MSCALE_X] /= 2.0f;
  47.         values[Matrix.MSCALE_Y] /= 2.0f;
  48.         // XY座標の移動位置を計算
  49.         calcTrans(values);
  50.         // 値を再設定
  51.         m.setValues(values);
  52.         mImage.invalidate();
  53.     }
  54.     private void calcTrans(float[] values) {
  55.         // 画像の描画領域
  56.         Rect rect = new Rect();
  57.         mImage.getDrawingRect(rect);
  58.         // 元画像のサイズ
  59.         int imgWidth = mImage.getDrawable().getIntrinsicWidth();
  60.         int imgHeight = mImage.getDrawable().getIntrinsicHeight();
  61.         // 拡大後の画像幅
  62.         int imgScaledWidth = Math.round(imgWidth * values[Matrix.MSCALE_X]);
  63.         // 拡大後の画像高さ
  64.         int imgScaledHeight = Math.round(imgHeight * values[Matrix.MSCALE_Y]);
  65.         // 表示位置中央X座標 - (拡大後の画像幅 / 2)がX移動距離
  66.         values[Matrix.MTRANS_X] = (rect.width() / 2) - (imgScaledWidth / 2);
  67.         // 表示位置中央Y座標 - (拡大後の画像高さ / 2)がY移動距離
  68.         values[Matrix.MTRANS_Y] = (rect.height() / 2) - (imgScaledHeight / 2);
  69.     }
  70. }




これで、中央を原点として画像の拡大と縮小が行えるようになりました。

795_06.png

関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2017/09/03(日) 21:48:31|
  2. Java
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
<<Ubuntu + Android Studioで実機をUSBに接続してデバッグ | ホーム | Linux inotifywait でファイルの更新を監視し、コマンドを実行する>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://symfoware.blog68.fc2.com/tb.php/2055-9b3c60b8
この記事にトラックバックする(FC2ブログユーザー)