Android中图像变换Matrix的原理应用

  1. {

  2. private Bitmap bitmap;

  3. private Matrix matrix;

  4. public TransformMatrixView(Context context)

  5. {

  6. super(context);

  7. bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sophie);

  8. matrix = new Matrix();

  9. }

  10. @Override

  11. protected void onDraw(Canvas canvas)

  12. {

  13. // 画出原图像

  14. canvas.drawBitmap(bitmap, 0, 0, null);

  15. // 画出变换后的图像

  16. canvas.drawBitmap(bitmap, matrix, null);

  17. super.onDraw(canvas);

  18. }

  19. @Override

  20. public void setImageMatrix(Matrix matrix)

  21. {

  22. this.matrix.set(matrix);

  23. super.setImageMatrix(matrix);

  24. }

  25. public Bitmap getImageBitmap()

  26. {

  27. return bitmap;

  28. }

  29. }

  30. public boolean onTouch(View v, MotionEvent e)

  31. {

  32. if(e.getAction() == MotionEvent.ACTION_UP)

  33. {

  34. Matrix matrix = new Matrix();

  35. // 输出图像的宽度和高度(162 x 251)

  36. Log.e(“TestTransformMatrixActivity”, "image size: width x height = " +  view.getImageBitmap().getWidth() + " x " + view.getImageBitmap().getHeight());

  37. // 1. 平移

  38. matrix.postTranslate(view.getImageBitmap().getWidth(), view.getImageBitmap().getHeight());

  39. // 在x方向平移view.getImageBitmap().getWidth(),在y轴方向view.getImageBitmap().getHeight()

  40. view.setImageMatrix(matrix);

  41. // 下面的代码是为了查看matrix中的元素

  42. float[] matrixValues = new float[9];

  43. matrix.getValues(matrixValues);

  44. for(int i = 0; i < 3; ++i)

  45. {

  46. String temp = new String();

  47. for(int j = 0; j < 3; ++j)

  48. {

  49. temp += matrixValues[3 * i + j ] + “\t”;

  50. }

  51. Log.e(“TestTransformMatrixActivity”, temp);

  52. }

  53. //          // 2. 旋转(围绕图像的中心点)

  54. //          matrix.setRotate(45f, view.getImageBitmap().getWidth() / 2f, view.getImageBitmap().getHeight() / 2f);

  55. //

  56. //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠

  57. //          matrix.postTranslate(view.getImageBitmap().getWidth() * 1.5f, 0f);

  58. //          view.setImageMatrix(matrix);

  59. //

  60. //          // 下面的代码是为了查看matrix中的元素

  61. //          float[] matrixValues = new float[9];

  62. //          matrix.getValues(matrixValues);

  63. //          for(int i = 0; i < 3; ++i)

  64. //          {

  65. //              String temp = new String();

  66. //              for(int j = 0; j < 3; ++j)

  67. //              {

  68. //                  temp += matrixValues[3 * i + j ] + “\t”;

  69. //              }

  70. //              Log.e(“TestTransformMatrixActivity”, temp);

  71. //          }

  72. //          // 3. 旋转(围绕坐标原点) + 平移(效果同2)

  73. //          matrix.setRotate(45f);

  74. //          matrix.preTranslate(-1f * view.getImageBitmap().getWidth() / 2f, -1f * view.getImageBitmap().getHeight() / 2f);

  75. //          matrix.postTranslate((float)view.getImageBitmap().getWidth() / 2f, (float)view.getImageBitmap().getHeight() / 2f);

  76. //

  77. //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠

  78. //          matrix.postTranslate((float)view.getImageBitmap().getWidth() * 1.5f, 0f);

  79. //          view.setImageMatrix(matrix);

  80. //

  81. //          // 下面的代码是为了查看matrix中的元素

  82. //          float[] matrixValues = new float[9];

  83. //          matrix.getValues(matrixValues);

  84. //          for(int i = 0; i < 3; ++i)

  85. //          {

  86. //              String temp = new String();

  87. //              for(int j = 0; j < 3; ++j)

  88. //              {

  89. //                  temp += matrixValues[3 * i + j ] + “\t”;

  90. //              }

  91. //              Log.e(“TestTransformMatrixActivity”, temp);

  92. //          }

  93. //          // 4. 缩放

  94. //          matrix.setScale(2f, 2f);

  95. //          // 下面的代码是为了查看matrix中的元素

  96. //          float[] matrixValues = new float[9];

  97. //          matrix.getValues(matrixValues);

  98. //          for(int i = 0; i < 3; ++i)

  99. //          {

  100. //              String temp = new String();

  101. //              for(int j = 0; j < 3; ++j)

  102. //              {

  103. //                  temp += matrixValues[3 * i + j ] + “\t”;

  104. //              }

  105. //              Log.e(“TestTransformMatrixActivity”, temp);

  106. //          }

  107. //

  108. //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠

  109. //          matrix.postTranslate(view.getImageBitmap().getWidth(), view.getImageBitmap().getHeight());

  110. //          view.setImageMatrix(matrix);

  111. //

  112. //          // 下面的代码是为了查看matrix中的元素

  113. //          matrixValues = new float[9];

  114. //          matrix.getValues(matrixValues);

  115. //          for(int i = 0; i < 3; ++i)

  116. //          {

  117. //              String temp = new String();

  118. //              for(int j = 0; j < 3; ++j)

  119. //              {

  120. //                  temp += matrixValues[3 * i + j ] + “\t”;

  121. //              }

  122. //              Log.e(“TestTransformMatrixActivity”, temp);

  123. //          }

  124. //          // 5. 错切 - 水平

  125. //          matrix.setSkew(0.5f, 0f);

  126. //          // 下面的代码是为了查看matrix中的元素

  127. //          float[] matrixValues = new float[9];

  128. //          matrix.getValues(matrixValues);

  129. //          for(int i = 0; i < 3; ++i)

  130. //          {

  131. //              String temp = new String();

  132. //              for(int j = 0; j < 3; ++j)

  133. //              {

  134. //                  temp += matrixValues[3 * i + j ] + “\t”;

  135. //              }

  136. //              Log.e(“TestTransformMatrixActivity”, temp);

  137. //          }

  138. //

  139. //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠

  140. //          matrix.postTranslate(view.getImageBitmap().getWidth(), 0f);

  141. //          view.setImageMatrix(matrix);

  142. //

  143. //          // 下面的代码是为了查看matrix中的元素

  144. //          matrixValues = new float[9];

  145. //          matrix.getValues(matrixValues);

  146. //          for(int i = 0; i < 3; ++i)

  147. //          {

  148. //              String temp = new String();

  149. //              for(int j = 0; j < 3; ++j)

  150. //              {

  151. //                  temp += matrixValues[3 * i + j ] + “\t”;

  152. //              }

  153. //              Log.e(“TestTransformMatrixActivity”, temp);

  154. //          }

  155. //          // 6. 错切 - 垂直

  156. //          matrix.setSkew(0f, 0.5f);

  157. //          // 下面的代码是为了查看matrix中的元素

  158. //          float[] matrixValues = new float[9];

  159. //          matrix.getValues(matrixValues);

  160. //          for(int i = 0; i < 3; ++i)

  161. //          {

  162. //              String temp = new String();

  163. //              for(int j = 0; j < 3; ++j)

  164. //              {

  165. //                  temp += matrixValues[3 * i + j ] + “\t”;

  166. //              }

  167. //              Log.e(“TestTransformMatrixActivity”, temp);

  168. //          }

  169. //

  170. //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠

  171. //          matrix.postTranslate(0f, view.getImageBitmap().getHeight());

  172. //          view.setImageMatrix(matrix);

  173. //

  174. //          // 下面的代码是为了查看matrix中的元素

  175. //          matrixValues = new float[9];

  176. //          matrix.getValues(matrixValues);

  177. //          for(int i = 0; i < 3; ++i)

  178. //          {

  179. //              String temp = new String();

  180. //              for(int j = 0; j < 3; ++j)

  181. //              {

  182. //                  temp += matrixValues[3 * i + j ] + “\t”;

  183. //              }

  184. //              Log.e(“TestTransformMatrixActivity”, temp);

  185. //          }

  186. //          7. 错切 - 水平 + 垂直

  187. //          matrix.setSkew(0.5f, 0.5f);

  188. //          // 下面的代码是为了查看matrix中的元素

  189. //          float[] matrixValues = new float[9];

  190. //          matrix.getValues(matrixValues);

  191. //          for(int i = 0; i < 3; ++i)

  192. //          {

  193. //              String temp = new String();

  194. //              for(int j = 0; j < 3; ++j)

  195. //              {

  196. //                  temp += matrixValues[3 * i + j ] + “\t”;

  197. //              }

  198. //              Log.e(“TestTransformMatrixActivity”, temp);

  199. //          }

  200. //

  201. //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠

  202. //          matrix.postTranslate(0f, view.getImageBitmap().getHeight());

  203. //          view.setImageMatrix(matrix);

  204. //

  205. //          // 下面的代码是为了查看matrix中的元素

  206. //          matrixValues = new float[9];

  207. //          matrix.getValues(matrixValues);

  208. //          for(int i = 0; i < 3; ++i)

  209. //          {

  210. //              String temp = new String();

  211. //              for(int j = 0; j < 3; ++j)

  212. //              {

  213. //                  temp += matrixValues[3 * i + j ] + “\t”;

  214. //              }

  215. //              Log.e(“TestTransformMatrixActivity”, temp);

  216. //          }

  217. //          // 8. 对称 (水平对称)

  218. //          float matrix_values[] = {1f, 0f, 0f, 0f, -1f, 0f, 0f, 0f, 1f};

  219. //          matrix.setValues(matrix_values);

  220. //          // 下面的代码是为了查看matrix中的元素

  221. //          float[] matrixValues = new float[9];

  222. //          matrix.getValues(matrixValues);

  223. //          for(int i = 0; i < 3; ++i)

  224. //          {

  225. //              String temp = new String();

  226. //              for(int j = 0; j < 3; ++j)

  227. //              {

  228. //                  temp += matrixValues[3 * i + j ] + “\t”;

  229. //              }

  230. //              Log.e(“TestTransformMatrixActivity”, temp);

  231. //          }

  232. //

2
85. //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠

  1. //          matrix.postTranslate(0f, view.getImageBitmap().getHeight() * 2f);

  2. //          view.setImageMatrix(matrix);

  3. //

  4. //          // 下面的代码是为了查看matrix中的元素

  5. //          matrixValues = new float[9];

  6. //          matrix.getValues(matrixValues);

  7. //          for(int i = 0; i < 3; ++i)

  8. //          {

  9. //              String temp = new String();

  10. //              for(int j = 0; j < 3; ++j)

  11. //              {

  12. //                  temp += matrixValues[3 * i + j ] + “\t”;

  13. //              }

  14. //              Log.e(“TestTransformMatrixActivity”, temp);

  15. //          }

  16. //          // 9. 对称 - 垂直

  17. //          float matrix_values[] = {-1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f};

  18. //          matrix.setValues(matrix_values);

  19. //          // 下面的代码是为了查看matrix中的元素

  20. //          float[] matrixValues = new float[9];

  21. //          matrix.getValues(matrixValues);

  22. //          for(int i = 0; i < 3; ++i)

  23. //          {

  24. //              String temp = new String();

  25. //              for(int j = 0; j < 3; ++j)

  26. //              {

  27. //                  temp += matrixValues[3 * i + j ] + “\t”;

  28. //              }

  29. //              Log.e(“TestTransformMatrixActivity”, temp);

  30. //          }

  31. //

  32. //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠

  33. //          matrix.postTranslate(view.getImageBitmap().getWidth() * 2f, 0f);

  34. //          view.setImageMatrix(matrix);

  35. //

  36. //          // 下面的代码是为了查看matrix中的元素

  37. //          matrixValues = new float[9];

  38. //          matrix.getValues(matrixValues);

  39. //          for(int i = 0; i < 3; ++i)

  40. //          {

  41. //              String temp = new String();

  42. //              for(int j = 0; j < 3; ++j)

  43. //              {

  44. //                  temp += matrixValues[3 * i + j ] + “\t”;

  45. //              }

  46. //              Log.e(“TestTransformMatrixActivity”, temp);

  47. //          }

  48. //          // 10. 对称(对称轴为直线y = x)

  49. //          float matrix_values[] = {0f, -1f, 0f, -1f, 0f, 0f, 0f, 0f, 1f};

  50. //          matrix.setValues(matrix_values);

  51. //          // 下面的代码是为了查看matrix中的元素

  52. //          float[] matrixValues = new float[9];

  53. //          matrix.getValues(matrixValues);

  54. //          for(int i = 0; i < 3; ++i)

  55. //          {

  56. //              String temp = new String();

  57. //              for(int j = 0; j < 3; ++j)

  58. //              {

  59. //                  temp += matrixValues[3 * i + j ] + “\t”;

  60. //              }

  61. //              Log.e(“TestTransformMatrixActivity”, temp);

  62. //          }

  63. //

  64. //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠

  65. //          matrix.postTranslate(view.getImageBitmap().getHeight() + view.getImageBitmap().getWidth(),

  66. //                  view.getImageBitmap().getHeight() + view.getImageBitmap().getWidth());

  67. //          view.setImageMatrix(matrix);

  68. //

  69. //          // 下面的代码是为了查看matrix中的元素

  70. //          matrixValues = new float[9];

  71. //          matrix.getValues(matrixValues);

  72. //          for(int i = 0; i < 3; ++i)

  73. //          {

  74. //              String temp = new String();

  75. //              for(int j = 0; j < 3; ++j)

  76. //              {

  77. //                  temp += matrixValues[3 * i + j ] + “\t”;

  78. //              }

  79. //              Log.e(“TestTransformMatrixActivity”, temp);

  80. //          }

  81. view.invalidate();

  82. }

  83. return true;

  84. }

  85. }


  86.   

第三部分 应用

在这一部分,我们会将前面两部分所了解到的内容和Android手势结合起来,利用各种不同的手势对图像进行平移、缩放和旋转,前面两项都是在实践中经常需要用到的功能,后一项据说苹果也是最近才加上的,而实际上在Android中,咱们通过自己的双手,也可以很轻松地实现之。

首先创建一个Android项目PatImageView,同时创建一个Activity:PatImageViewActivity。完成这一步后, 记得在AndroidManifest.xml中增加如下许可:

uses-permissionandroid:name=_“android.permission.VIBRATE”_/

因为我们将要通过短按还是长按,来确定将图片到底是缩放还是旋转。

现在来创建一个ImageView的派生类:PatImageView,其代码(PatImageView.java)如下(2011-11-22 revised):

[java]  view plain copy

  1. package com.pat.imageview;

  2. import android.app.Service;

  3. import android.content.Context;

  4. import android.graphics.Matrix;

  5. import android.graphics.PointF;

  6. import android.os.Vibrator;

  7. import android.util.FloatMath;

  8. import android.view.GestureDetector;

  9. import android.view.MotionEvent;

  10. import android.view.View;

  11. import android.widget.ImageView;

  12. public class PatImageView extends ImageView

  13. {

  14. private Matrix matrix;

  15. private Matrix savedMatrix;

  16. private boolean long_touch = false;

  17. private static int NONE = 0;

  18. private static int DRAG = 1;    // 拖动

  19. private static int ZOOM = 2;    // 缩放

  20. private static int ROTA = 3;    // 旋转

  21. private int mode = NONE;

  22. private PointF startPoint;

  23. private PointF middlePoint;

  24. private float oldDistance;

  25. private float oldAngle;

  26. private Vibrator vibrator;

  27. private GestureDetector gdetector;

  28. public PatImageView(final Context context)

  29. {

  30. super(context);

  31. matrix = new Matrix();

  32. savedMatrix = new Matrix();

  33. matrix.setTranslate(0f, 0f);

  34. setScaleType(ScaleType.MATRIX);

  35. setImageMatrix(matrix);

  36. startPoint = new PointF();

  37. middlePoint = new PointF();

  38. oldDistance = 1f;

  39. gdetector = new GestureDetector(context, new GestureDetector.OnGestureListener()

  40. {

  41. @Override

  42. public boolean onSingleTapUp(MotionEvent e)

  43. {

  44. return true;

  45. }

  46. @Override

  47. public void onShowPress(MotionEvent e)

  48. {

  49. }

  50. @Override

  51. public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)

  52. {

  53. return true;

  54. }

  55. @Override

  56. public void onLongPress(MotionEvent e)

  57. {

  58. long_touch = true;

  59. vibrator = (Vibrator) context.getSystemService(Service.VIBRATOR_SERVICE);

  60. // 振动50ms,提示后续的操作将是旋转图片,而非缩放图片

  61. vibrator.vibrate(50);

  62. }

  63. @Override

  64. public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)

  65. {

  66. return true;

  67. }

  68. @Override

  69. public boolean onDown(MotionEvent e)

  70. {

  71. return true;

  72. }

  73. });

  74. setOnTouchListener(new OnTouchListener()

  75. {

  76. public boolean onTouch(View view, MotionEvent event)

  77. {

  78. switch(event.getAction() & MotionEvent.ACTION_MASK)

  79. {

  80. case MotionEvent.ACTION_DOWN:           // 第一个手指touch

  81. savedMatrix.set(matrix);

  82. startPoint.set(event.getX(), event.getY());

  83. mode = DRAG;

  84. long_touch = false;

  85. break;

  86. case MotionEvent.ACTION_POINTER_DOWN:   // 第二个手指touch

  87. oldDistance = getDistance(event);   // 计算第二个手指touch时,两指之间的距离

  88. oldAngle = getDegree(event);        // 计算第二个手指touch时,两指所形成的直线和x轴的角度

  89. if(oldDistance > 10f)

  90. {

  91. savedMatrix.set(matrix);

  92. middlePoint = midPoint(event);

  93. if(!long_touch)

  94. {

  95. mode = ZOOM;

  96. }

  97. else

  98. {

  99. mode = ROTA;

  100. }

  101. }

  102. break;

  103. case MotionEvent.ACTION_UP:

  104. mode = NONE;

  105. break;

  106. case MotionEvent.ACTION_POINTER_UP:

  107. mode = NONE;

  108. break;

  109. case MotionEvent.ACTION_MOVE:

  110. if(vibrator != null)    vibrator.cancel();

  111. if(mode == DRAG)

  112. {

  113. matrix.set(savedMatrix);

  114. matrix.postTranslate(event.getX() - startPoint.x, event.getY() - startPoint.y);

  115. }

  116. if(mode == ZOOM)

  117. {

  118. float newDistance = getDistance(event);

  119. if(newDistance > 10f)

  120. {

  121. matrix.set(savedMatrix);

  122. float scale = newDistance / oldDistance;

  123. matrix.postScale(scale, scale, middlePoint.x, middlePoint.y);

  124. }

  125. }

  126. if(mode == ROTA)

  127. {

  128. float newAngle = getDegree(event);

  129. matrix.set(savedMatrix);

  130. float degrees = newAngle - oldAngle;

  131. matrix.postRotate(degrees, middlePoint.x, middlePoint.y);

  132. }

  133. break;

  134. }

  135. setImageMatrix(matrix);

  136. invalidate();

  137. gdetector.onTouchEvent(event);

  138. return true;

  139. }

  140. });

  141. }

  142. // 计算两个手指之间的距离

  143. private float getDistance(MotionEvent event)

  144. {

  145. float x = event.getX(0) - event.getX(1);

  146. float y = event.getY(0) - event.getY(1);

  147. return FloatMath.sqrt(x * x + y * y);

  148. }

  149. // 计算两个手指所形成的直线和x轴的角度

  150. private float getDegree(MotionEvent event)

  151. {

  152. return (float)(Math.atan((event.getY(1) - event.getY(0)) / (event.getX(1) - event.getX(0))) * 180f);

  153. }

  154. // 计算两个手指之间,中间点的坐标

  155. private PointF midPoint( MotionEvent event)

  156. {

  157. PointF point = new PointF();

  158. float x = event.getX(0) + event.getX(1);

  159. float y = event.getY(0) + event.getY(1);

  160. point.set(x / 2, y / 2);

  161. return point;

  162. }

  163. }

下面完善PatImageViewActivity.java的代码,使之如下:

[java]  view plain copy

  • 19
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值