Android中图像变换Matrix的原理应用,腾讯Android面试题

如果对称轴是y轴,那么,

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

用矩阵表示就是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果对称轴是_y = x_,如图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

那么,

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

很容易可以解得:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

用矩阵表示就是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

同样的道理,如果对称轴是_y = -x_,那么用矩阵表示就是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

特殊地,如果对称轴是_y = kx_,如下图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

那么,

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

很容易可解得:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

用矩阵表示就是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当_k = 0_时,即_y = 0_,也就是对称轴为_x_轴的情况;当_k_趋于无穷大时,即_x = 0_,也就是对称轴为_y_轴的情况;当_k =1时,即_y = x,也就是对称轴为_y = x_的情况;当_k = -1时,即_y = -x,也就是对称轴为_y = -x_的情况。不难验证,这和我们前面说到的4中具体情况是相吻合的。

如果对称轴是_y = kx + b_这样的情况,只需要在上面的基础上增加两次平移变换即可,即先将坐标原点移动到(0, b),然后做上面的关于_y = kx_的对称变换,再然后将坐标原点移回到原来的坐标原点即可。用矩阵表示大致是这样的:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

需要特别注意:在实际编程中,我们知道屏幕的_y_坐标的正向和数学中_y_坐标的正向刚好是相反的,所以在数学上y = x和屏幕上的_y = -x_才是真正的同一个东西,反之亦然。也就是说,如果要使图片在屏幕上看起来像按照数学意义上_y = x_对称,那么需使用这种转换:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

要使图片在屏幕上看起来像按照数学意义上_y = -x_对称,那么需使用这种转换:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

关于对称轴为_y = kx_ 或_y = kx + b_的情况,同样需要考虑这方面的问题。

第二部分 代码验证

在第一部分中讲到的各种图像变换的验证代码如下,一共列出了10种情况。如果要验证其中的某一种情况,只需将相应的代码反注释即可。试验中用到的图片:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其尺寸为162 x 251。

每种变换的结果,请见代码之后的说明。

[java]  view plain copy

  1. <span style=“font-size:13px;”><pre name=“code” class=“java”>package com.pat.testtransformmatrix;

  2. import android.app.Activity;

  3. import android.content.Context;

  4. import android.graphics.Bitmap;

  5. import android.graphics.BitmapFactory;

  6. import android.graphics.Canvas;

  7. import android.graphics.Matrix;

  8. import android.os.Bundle;

  9. import android.util.Log;

  10. import android.view.MotionEvent;

  11. import android.view.View;

  12. import android.view.Window;

  13. import android.view.WindowManager;

  14. import android.view.View.OnTouchListener;

  15. import android.widget.ImageView;

  16. public class TestTransformMatrixActivity extends Activity

  17. implements

  18. OnTouchListener

  19. {

  20. private TransformMatrixView view;

  21. @Override

  22. public void onCreate(Bundle savedInstanceState)

  23. {

  24. super.onCreate(savedInstanceState);

  25. requestWindowFeature(Window.FEATURE_NO_TITLE);

  26. this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

  27. view = new TransformMatrixView(this);

  28. view.setScaleType(ImageView.ScaleType.MATRIX);

  29. view.setOnTouchListener(this);

  30. setContentView(view);

  31. }

  32. class TransformMatrixView extends ImageView

  33. {

  34. private Bitmap bitmap;

  35. private Matrix matrix;

  36. public TransformMatrixView(Context context)

  37. {

  38. super(context);

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

  40. matrix = new Matrix();

  41. }

  42. @Override

  43. protected void onDraw(Canvas canvas)

  44. {

  45. // 画出原图像

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

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

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

  49. super.onDraw(canvas);

  50. }

  51. @Override

  52. public void setImageMatrix(Matrix matrix)

  53. {

  54. this.matrix.set(matrix);

  55. super.setImageMatrix(matrix);

  56. }

  57. public Bitmap getImageBitmap()

  58. {

  59. return bitmap;

  60. }

  61. }

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

  63. {

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

  65. {

  66. Matrix matrix = new Matrix();

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

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

  69. // 1. 平移

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

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

  72. view.setImageMatrix(matrix);

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

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

  75. matrix.getValues(matrixValues);

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

  77. {

  78. String temp = new String();

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

  80. {

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

  82. }

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

  84. }

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

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

  87. //

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

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

  90. //          view.setImageMatrix(matrix);

  91. //

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

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

  94. //          matrix.getValues(matrixValues);

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

  96. //          {

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

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

  99. //              {

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

  101. //              }

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

  103. //          }

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

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

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

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

  108. //

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

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

  111. //          view.setImageMatrix(matrix);

  112. //

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

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

  115. //          matrix.getValues(matrixValues);

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

  117. //          {

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

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

  120. //              {

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

  122. //              }

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

  124. //          }

  125. //          // 4. 缩放

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

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

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

  129. //          matrix.getValues(matrixValues);

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

  131. //          {

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

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

  134. //              {

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

  136. //              }

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

  138. //          }

  139. //

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

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

  142. //          view.setImageMatrix(matrix);

  143. //

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

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

  146. //          matrix.getValues(matrixValues);

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

  148. //          {

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

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

  151. //              {

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

  153. //              }

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

  155. //          }

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

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

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

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

  160. //          matrix.getValues(matrixValues);

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

  162. //          {

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

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

  165. //              {

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

  167. //              }

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

  169. //          }

  170. //

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

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

  173. //          view.setImageMatrix(matrix);

  174. //

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

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

  177. //          matrix.getValues(matrixValues);

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

  179. //          {

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

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

  182. //              {

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

  184. //              }

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

  186. //          }

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

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

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

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

  191. //          matrix.getValues(matrixValues);

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

  193. //          {

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

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

  196. //              {

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

  198. //              }

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

  200. //          }

  201. //

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

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

  204. //          view.setImageMatrix(matrix);

  205. //

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

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

  208. //          matrix.getValues(matrixValues);

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

  210. //          {

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

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

  213. //              {

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

  215. //              }

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

  217. //          }

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

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

  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. //

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

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

  235. //          view.setImageMatrix(matrix);

  236. //

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

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

  239. //          matrix.getValues(matrixValues);

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

  241. //          {

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

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

  244. //              {

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

  246. //              }

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

  248. //          }

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

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

  251. //          matrix.setValues(matrix_values);

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

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

  254. //          matrix.getValues(matrixValues);

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

  256. //          {

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

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

  259. //              {

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

  261. //              }

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

  263. //          }

  264. //

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

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

  267. //          view.setImageMatrix(matrix);

  268. //

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

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

  271. //          matrix.getValues(matrixValues);

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

  273. //          {

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

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

  276. //              {

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

  278. //              }

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

  280. //          }

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

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

  283. //          matrix.setValues(matrix_values);

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

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

  286. //          matrix.getValues(matrixValues);

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

  288. //          {

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

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

  291. //              {

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

  293. //              }

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

  295. //          }

  296. //

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

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

  299. //          view.setImageMatrix(matrix);

  300. //

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

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

  303. //          matrix.getValues(matrixValues);

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

  305. //          {

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

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

  308. //              {

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

  310. //              }

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

  312. //          }

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

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

  315. //          matrix.setValues(matrix_values);

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

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

  318. //          matrix.getValues(matrixValues);

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

  320. //          {

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

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

  323. //              {

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

  325. //              }

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

  327. //          }

  328. //

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

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

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

  332. //          view.setImageMatrix(matrix);

  333. //

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

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

  336. //          matrix.getValues(matrixValues);

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

  338. //          {

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

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

  341. //              {

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

  343. //              }

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

  345. //          }

  346. view.invalidate();

  347. }

  348. return true;

  349. }

  350. }


  351.   

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

最后说一下我的学习路线

其实很简单就下面这张图,含概了Android所有需要学的知识点,一共8大板块:

  1. 架构师筑基必备技能
  2. Android框架体系架构(高级UI+FrameWork源码)
  3. 360°Androidapp全方位性能调优
  4. 设计思想解读开源框架
  5. NDK模块开发
  6. 移动架构师专题项目实战环节
  7. 移动架构师不可不学习微信小程序
  8. 混合开发的flutter

Android学习的资料

我呢,把上面八大板块的分支都系统的做了一份学习系统的资料和视频,大概就下面这些,我就不全部写出来了,不然太长了影响大家的阅读。

330页PDF Android学习核心笔记(内含上面8大板块)

Android学习的系统对应视频

总结

我希望通过我自己的学习方法来帮助大家去提升技术:

  • 1、多看书、看源码和做项目,平时多种总结

  • 2、不能停留在一些基本api的使用上,应该往更深层次的方向去研究,比如activity、view的内部运行机制,比如Android内存优化,比如aidl,比如JNI等,并不仅仅停留在会用,而要通过阅读源码,理解其实现原理

  • 3、同时对架构是有一定要求的,架构是抽象的,但是设计模式是具体的,所以一定要加强下设计模式的学习

  • 4、android的方向也很多,高级UI,移动架构师,数据结构与算法和音视频FFMpeg解码,如果你对其中一项比较感兴趣,就大胆的进阶吧!

希望大家多多点赞,转发,评论加关注,你们的支持就是我继续下去的动力!加油!

大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-5J8UGNFU-1711628224689)]

最后说一下我的学习路线

其实很简单就下面这张图,含概了Android所有需要学的知识点,一共8大板块:

  1. 架构师筑基必备技能
  2. Android框架体系架构(高级UI+FrameWork源码)
  3. 360°Androidapp全方位性能调优
  4. 设计思想解读开源框架
  5. NDK模块开发
  6. 移动架构师专题项目实战环节
  7. 移动架构师不可不学习微信小程序
  8. 混合开发的flutter

[外链图片转存中…(img-wN7Z536I-1711628224689)]

Android学习的资料

我呢,把上面八大板块的分支都系统的做了一份学习系统的资料和视频,大概就下面这些,我就不全部写出来了,不然太长了影响大家的阅读。

330页PDF Android学习核心笔记(内含上面8大板块)

[外链图片转存中…(img-NRmXPeGu-1711628224689)]

Android学习的系统对应视频

总结

我希望通过我自己的学习方法来帮助大家去提升技术:

  • 1、多看书、看源码和做项目,平时多种总结

  • 2、不能停留在一些基本api的使用上,应该往更深层次的方向去研究,比如activity、view的内部运行机制,比如Android内存优化,比如aidl,比如JNI等,并不仅仅停留在会用,而要通过阅读源码,理解其实现原理

  • 3、同时对架构是有一定要求的,架构是抽象的,但是设计模式是具体的,所以一定要加强下设计模式的学习

  • 4、android的方向也很多,高级UI,移动架构师,数据结构与算法和音视频FFMpeg解码,如果你对其中一项比较感兴趣,就大胆的进阶吧!

希望大家多多点赞,转发,评论加关注,你们的支持就是我继续下去的动力!加油!

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值