画像を拡大縮小、回転させたりするときは、Matrixを使うことができます。ただし基本的に画像処理はパフォーマンス、メモリを使いますので注意しましょう。
2021.3.1
Matrix
画像を拡大縮小させて表示する方法としてはImageViewのレイアウトを使うことで可能です。
Matrixを使って画像そのものを拡大縮小、あるいは回転、フリップさせてしまう方法もあります。
1. ImageView
リソース画像をBitmapで取り出します
2. Rotation
setRotateで画像を回転させる
3. Resize
preScaleで画像の拡大縮小
4. Flip
preScaleの符合を変えてフリップ
5. サンプルコード
ImgeView
最初に画像をdrawableに置きます。これを回転、リサイズ、フリップさせていきます。
あるいは \res\mipmap 以下にあるDroid君のアイコン画像をコピーして代用もできます。
画像をImageViewにセットするためには
1 2 3 |
ImageView imageView = findViewById(R.id.image_view); // resourceからの画像を設定 imageVie.setImageResource(R.drawable.kurumi); |
とすればできますが、画像をこの後 Mtrix に渡していくためにBitmapとして取り出します。
1 2 3 4 |
// resource画像ををbitmapとして取り出す Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.kurumi); // bitmap画像をImgeViewに設定 imageView.setImageBitmap(bitmap1); |
まとめてみると
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public class MainActivity extends AppCompatActivity { private ImageView imageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageView = findViewById(R.id.image_view); Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.kurumi); imageView.setImageBitmap(bitmap1); } } |
Rotation (setRotate)
画像を90度回転させます。
1 2 |
// degrees:回転角度 setRotate(float degrees, float px, float py) |
px, pyを基点として回転させます。
Mtrixを使ってBitmapを再構築します。
1 2 3 4 5 6 7 |
createBitmap(Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter) |
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
... public class MainActivity extends AppCompatActivity { private ImageView imageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageView = findViewById(R.id.image_view); Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.kurumi); // 画像の横、縦サイズを取得 int imageWidth = bitmap1.getWidth(); int imageHeight = bitmap1.getHeight(); // Matrix インスタンス生成 Matrix matrix = new Matrix(); // 画像中心を基点に90度回転 matrix.setRotate(90, imageWidth/2, imageHeight/2); // 90度回転したBitmap画像を生成 Bitmap bitmap2 = Bitmap.createBitmap(bitmap1, 0, 0, imageWidth, imageHeight, matrix, true); imageView.setImageBitmap(bitmap2); } } |
90°回転しました
Resize (preScale)
画像を縮小させてみます。ここでは prescale を使います
1 |
preScale(float sx, float sy) |
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
... public class MainActivity extends AppCompatActivity { private ImageView imageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageView = findViewById(R.id.image_view); Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.kurumi); int imageWidth = bitmap1.getWidth(); int imageHeight = bitmap1.getHeight(); // Matrix インスタンス生成 Matrix matrix = new Matrix(); // 1/2の縮小率 float ratio = 0.5f; // resize matrix.preScale(ratio, ratio); Bitmap bitmap3 = Bitmap.createBitmap(bitmap1, 0, 0, imageWidth, imageHeight, matrix, true); // drawableに変換 Drawable drawable = new BitmapDrawable(getResources(), bitmap3); imageView.setImageDrawable(drawable); } } |
画像が縮小されました。
Flip (preScale)
ボタンの背景として画像を水平方向にフリップさせてみます。
Buttonの背景とする場合は、表示サイズを適正にしないといけませんので、縦横比率と実際の幅、それにスクリーン幅を求めて計算していきます。
フリップは拡大縮小と同じですが符号を変えます
preScale(-1.0f, 1.0f)
と設定すると水平方向でのフリップです。
垂直方向は
preScale(1.0f, -1.0f)
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
... public class MainActivity extends AppCompatActivity { private Button button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = findViewById(R.id.button); Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.kurumi); int imageWidth = bitmap1.getWidth(); int imageHeight = bitmap1.getHeight(); // Matrix インスタンス生成 Matrix matrix = new Matrix(); float ratio = (float)getScreenWidth()/(float)imageWidth; matrix.preScale(ratio, ratio); // flip horizontal matrix.preScale(-1.0f, 1.0f); Bitmap bitmap3 = Bitmap.createBitmap(bitmap1, 0, 0, imageWidth, imageHeight, matrix, true); Drawable drawable = new BitmapDrawable(getResources(), bitmap3); button.setBackground(drawable); } // スクリーンの横幅を取得する private int getScreenWidth(){ WindowManager windowManager = (WindowManager)getSystemService(WINDOW_SERVICE); Display display = windowManager.getDefaultDisplay(); Point pointSize = new Point(); display.getSize(pointSize); return pointSize.x; } } |
水平方向にフリップしました
サンプルコード
以上をまとめてボタンで機能を確認してみます。
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
//package your.package.name; import androidx.appcompat.app.AppCompatActivity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.util.Log; import android.widget.Button; import android.widget.ImageView; public class MainActivity extends AppCompatActivity { private ImageView imageView; private Bitmap bitmap; private int imageWidth, imageHeight; private Matrix matrix; private int degree = 0; private int counter = 1; private float ratio = 1.0f; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageView = findViewById(R.id.image_view); bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.kurumi); // 画像の横、縦サイズを取得 imageWidth = bitmap.getWidth(); imageHeight = bitmap.getHeight(); // Matrix インスタンス生成 matrix = new Matrix(); Button button1 = findViewById(R.id.button1); // expression lambda button1.setOnClickListener( v -> imageRotation()); Button button2 = findViewById(R.id.button2); button2.setOnClickListener( v -> imageResize()); Button button3 = findViewById(R.id.button3); button3.setOnClickListener( v -> imageFlip()); } private void imageRotation(){ // 回転角度 degree += 90; if(degree > 360) degree = 90; // 画像中心を基点に回転 matrix.setRotate(degree, (float)imageWidth/2, (float)imageHeight/2); // 回転したBitmap画像を生成 Bitmap bitmap2 = Bitmap.createBitmap(bitmap, 0, 0, imageWidth, imageHeight, matrix, true); imageView.setImageBitmap(bitmap2); } private void imageResize(){ // 縮小率 if(counter < 4){ ratio -= 0.1f; } else if(counter<8){ ratio += 0.2f; } else{ counter = 0; ratio = 1.0f; } Log.d("debug","counter="+counter); Log.d("debug","ratio="+ratio); // resize matrix.preScale(ratio, ratio); Bitmap bitmap3 = Bitmap.createBitmap(bitmap, 0, 0, imageWidth, imageHeight, matrix, true); // drawableに変換 Drawable drawable = new BitmapDrawable(getResources(), bitmap3); imageView.setImageDrawable(drawable); counter++; } private void imageFlip(){ matrix.preScale(1.0f, 1.0f); // flip horizontal matrix.preScale(-1.0f, 1.0f); Bitmap bitmap4 = Bitmap.createBitmap(bitmap, 0, 0, imageWidth, imageHeight, matrix, true); Drawable drawable = new BitmapDrawable(getResources(), bitmap4); imageView.setImageDrawable(drawable); } } |
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#aaf" tools:context=".MainActivity"> <ImageView android:id="@+id/image_view" android:src="@drawable/kurumi" android:layout_margin="10dp" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" android:contentDescription="@string/description"/> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="280dp" android:layout_marginBottom="16dp" android:text="@string/rotation" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toRightOf="parent" /> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="160dp" android:layout_marginBottom="16dp" android:text="@string/resize" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toRightOf="parent" /> <Button android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="40dp" android:layout_marginBottom="16dp" android:text="@string/flip" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toRightOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> |
strings.xml
1 2 3 4 5 6 7 |
<resources> <string name="app_name">Your App Name</string> <string name="description">Kurumi</string> <string name="rotation">rotation</string> <string name="resize">resize</string> <string name="flip">flip</string> </resources> |
これで実行させてみましょう。
関連:
- 画像の表示
- レイアウトファイルを使わずに画像表示
- 画像をドラッグする
- Matrixで画像を回転、フリップ、縮小させる
Reference:
Matrix