第二部分 代码验证

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

其尺寸为162 x 251。

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

  1. import android.app.Activity;
  2. import android.content.Context;
  3. import android.graphics.Bitmap;
  4. import android.graphics.BitmapFactory;
  5. import android.graphics.Canvas;
  6. import android.graphics.Matrix;
  7. import android.os.Bundle;
  8. import android.util.Log;
  9. import android.view.MotionEvent;
  10. import android.view.View;
  11. import android.view.Window;
  12. import android.view.WindowManager;
  13. import android.view.View.OnTouchListener;
  14. import android.widget.ImageView;
  15. public class TestTransformMatrixActivity extends Activity
  16. implements
  17. OnTouchListener
  18. {
  19. private TransformMatrixView view;
  20. @Override
  21. public void onCreate(Bundle savedInstanceState)
  22. {
  23. super.onCreate(savedInstanceState);
  24. requestWindowFeature(Window.FEATURE_NO_TITLE);
  25. this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
  26. view = new TransformMatrixView(this);
  27. view.setScaleType(ImageView.ScaleType.MATRIX);
  28. view.setOnTouchListener(this);
  29. setContentView(view);
  30. }
  31. class TransformMatrixView extends ImageView
  32. {
  33. private Bitmap bitmap;
  34. private Matrix matrix;
  35. public TransformMatrixView(Context context)
  36. {
  37. super(context);
  38. bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sophie);
  39. matrix = new Matrix();
  40. }
  41. @Override
  42. protected void onDraw(Canvas canvas)
  43. {
  44. // 画出原图像
  45. canvas.drawBitmap(bitmap, 0, 0, null);
  46. // 画出变换后的图像
  47. canvas.drawBitmap(bitmap, matrix, null);
  48. super.onDraw(canvas);
  49. }
  50. @Override
  51. public void setImageMatrix(Matrix matrix)
  52. {
  53. this.matrix.set(matrix);
  54. super.setImageMatrix(matrix);
  55. }
  56. public Bitmap getImageBitmap()
  57. {
  58. return bitmap;
  59. }
  60. }
  61. public boolean onTouch(View v, MotionEvent e)
  62. {
  63. if(e.getAction() == MotionEvent.ACTION_UP)
  64. {
  65. Matrix matrix = new Matrix();
  66. // 输出图像的宽度和高度(162 x 251)
  67. Log.e("TestTransformMatrixActivity", "image size: width x height = " +  view.getImageBitmap().getWidth() + " x " + view.getImageBitmap().getHeight());
  68. // 1. 平移
  69. matrix.postTranslate(view.getImageBitmap().getWidth(), view.getImageBitmap().getHeight());
  70. // 在x方向平移view.getImageBitmap().getWidth(),在y轴方向view.getImageBitmap().getHeight()
  71. view.setImageMatrix(matrix);
  72. // 下面的代码是为了查看matrix中的元素
  73. float[] matrixValues = new float[9];
  74. matrix.getValues(matrixValues);
  75. for(int i = 0; i < 3; ++i)
  76. {
  77. String temp = new String();
  78. for(int j = 0; j < 3; ++j)
  79. {
  80. temp += matrixValues[3 * i + j ] + "\t";
  81. }
  82. Log.e("TestTransformMatrixActivity", temp);
  83. }
  84. //          // 2. 旋转(围绕图像的中心点)
  85. //          matrix.setRotate(45f, view.getImageBitmap().getWidth() / 2f, view.getImageBitmap().getHeight() / 2f);
  86. //
  87. //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠
  88. //          matrix.postTranslate(view.getImageBitmap().getWidth() * 1.5f, 0f);
  89. //          view.setImageMatrix(matrix);
  90. //
  91. //          // 下面的代码是为了查看matrix中的元素
  92. //          float[] matrixValues = new float[9];
  93. //          matrix.getValues(matrixValues);
  94. //          for(int i = 0; i < 3; ++i)
  95. //          {
  96. //              String temp = new String();
  97. //              for(int j = 0; j < 3; ++j)
  98. //              {
  99. //                  temp += matrixValues[3 * i + j ] + "\t";
  100. //              }
  101. //              Log.e("TestTransformMatrixActivity", temp);
  102. //          }
  103. //          // 3. 旋转(围绕坐标原点) + 平移(效果同2)
  104. //          matrix.setRotate(45f);
  105. //          matrix.preTranslate(-1f * view.getImageBitmap().getWidth() / 2f, -1f * view.getImageBitmap().getHeight() / 2f);
  106. //          matrix.postTranslate((float)view.getImageBitmap().getWidth() / 2f, (float)view.getImageBitmap().getHeight() / 2f);
  107. //
  108. //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠
  109. //          matrix.postTranslate((float)view.getImageBitmap().getWidth() * 1.5f, 0f);
  110. //          view.setImageMatrix(matrix);
  111. //
  112. //          // 下面的代码是为了查看matrix中的元素
  113. //          float[] 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. //          // 4. 缩放
  125. //          matrix.setScale(2f, 2f);
  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(), view.getImageBitmap().getHeight());
  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. //          // 5. 错切 - 水平
  156. //          matrix.setSkew(0.5f, 0f);
  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(view.getImageBitmap().getWidth(), 0f);
  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. //          // 6. 错切 - 垂直
  187. //          matrix.setSkew(0f, 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. //          7. 错切 - 水平 + 垂直
  218. //          matrix.setSkew(0.5f, 0.5f);
  219. //          // 下面的代码是为了查看matrix中的元素
  220. //          float[] matrixValues = new float[9];
  221. //          matrix.getValues(matrixValues);
  222. //          for(int i = 0; i < 3; ++i)
  223. //          {
  224. //              String temp = new String();
  225. //              for(int j = 0; j < 3; ++j)
  226. //              {
  227. //                  temp += matrixValues[3 * i + j ] + "\t";
  228. //              }
  229. //              Log.e("TestTransformMatrixActivity", temp);
  230. //          }
  231. //
  232. //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠
  233. //          matrix.postTranslate(0f, view.getImageBitmap().getHeight());
  234. //          view.setImageMatrix(matrix);
  235. //
  236. //          // 下面的代码是为了查看matrix中的元素
  237. //          matrixValues = new float[9];
  238. //          matrix.getValues(matrixValues);
  239. //          for(int i = 0; i < 3; ++i)
  240. //          {
  241. //              String temp = new String();
  242. //              for(int j = 0; j < 3; ++j)
  243. //              {
  244. //                  temp += matrixValues[3 * i + j ] + "\t";
  245. //              }
  246. //              Log.e("TestTransformMatrixActivity", temp);
  247. //          }
  248. //          // 8. 对称 (水平对称)
  249. //          float matrix_values[] = {1f, 0f, 0f, 0f, -1f, 0f, 0f, 0f, 1f};
  250. //          matrix.setValues(matrix_values);
  251. //          // 下面的代码是为了查看matrix中的元素
  252. //          float[] matrixValues = new float[9];
  253. //          matrix.getValues(matrixValues);
  254. //          for(int i = 0; i < 3; ++i)
  255. //          {
  256. //              String temp = new String();
  257. //              for(int j = 0; j < 3; ++j)
  258. //              {
  259. //                  temp += matrixValues[3 * i + j ] + "\t";
  260. //              }
  261. //              Log.e("TestTransformMatrixActivity", temp);
  262. //          }
  263. //
  264. //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠
  265. //          matrix.postTranslate(0f, view.getImageBitmap().getHeight() * 2f);
  266. //          view.setImageMatrix(matrix);
  267. //
  268. //          // 下面的代码是为了查看matrix中的元素
  269. //          matrixValues = new float[9];
  270. //          matrix.getValues(matrixValues);
  271. //          for(int i = 0; i < 3; ++i)
  272. //          {
  273. //              String temp = new String();
  274. //              for(int j = 0; j < 3; ++j)
  275. //              {
  276. //                  temp += matrixValues[3 * i + j ] + "\t";
  277. //              }
  278. //              Log.e("TestTransformMatrixActivity", temp);
  279. //          }
  280. //          // 9. 对称 - 垂直
  281. //          float matrix_values[] = {-1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f};
  282. //          matrix.setValues(matrix_values);
  283. //          // 下面的代码是为了查看matrix中的元素
  284. //          float[] matrixValues = new float[9];
  285. //          matrix.getValues(matrixValues);
  286. //          for(int i = 0; i < 3; ++i)
  287. //          {
  288. //              String temp = new String();
  289. //              for(int j = 0; j < 3; ++j)
  290. //              {
  291. //                  temp += matrixValues[3 * i + j ] + "\t";
  292. //              }
  293. //              Log.e("TestTransformMatrixActivity", temp);
  294. //          }
  295. //
  296. //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠
  297. //          matrix.postTranslate(view.getImageBitmap().getWidth() * 2f, 0f);
  298. //          view.setImageMatrix(matrix);
  299. //
  300. //          // 下面的代码是为了查看matrix中的元素
  301. //          matrixValues = new float[9];
  302. //          matrix.getValues(matrixValues);
  303. //          for(int i = 0; i < 3; ++i)
  304. //          {
  305. //              String temp = new String();
  306. //              for(int j = 0; j < 3; ++j)
  307. //              {
  308. //                  temp += matrixValues[3 * i + j ] + "\t";
  309. //              }
  310. //              Log.e("TestTransformMatrixActivity", temp);
  311. //          }
  312. //          // 10. 对称(对称轴为直线y = x)
  313. //          float matrix_values[] = {0f, -1f, 0f, -1f, 0f, 0f, 0f, 0f, 1f};
  314. //          matrix.setValues(matrix_values);
  315. //          // 下面的代码是为了查看matrix中的元素
  316. //          float[] matrixValues = new float[9];
  317. //          matrix.getValues(matrixValues);
  318. //          for(int i = 0; i < 3; ++i)
  319. //          {
  320. //              String temp = new String();
  321. //              for(int j = 0; j < 3; ++j)
  322. //              {
  323. //                  temp += matrixValues[3 * i + j ] + "\t";
  324. //              }
  325. //              Log.e("TestTransformMatrixActivity", temp);
  326. //          }
  327. //
  328. //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠
  329. //          matrix.postTranslate(view.getImageBitmap().getHeight() + view.getImageBitmap().getWidth(),
  330. //                  view.getImageBitmap().getHeight() + view.getImageBitmap().getWidth());
  331. //          view.setImageMatrix(matrix);
  332. //
  333. //          // 下面的代码是为了查看matrix中的元素
  334. //          matrixValues = new float[9];
  335. //          matrix.getValues(matrixValues);
  336. //          for(int i = 0; i < 3; ++i)
  337. //          {
  338. //              String temp = new String();
  339. //              for(int j = 0; j < 3; ++j)
  340. //              {
  341. //                  temp += matrixValues[3 * i + j ] + "\t";
  342. //              }
  343. //              Log.e("TestTransformMatrixActivity", temp);
  344. //          }
  345. view.invalidate();
  346. }
  347. return true;
  348. }
  349. }

下面给出上述代码中,各种变换的具体结果及其对应的相关变换矩阵

1.     平移

输出的结果:

请对照第一部分中的“一、平移变换”所讲的情形,考察上述矩阵的正确性。

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

输出的结果:

它实际上是

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

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

这两条语句综合作用的结果。根据第一部分中“二、旋转变换”里面关于围绕某点旋转的公式,

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

所产生的转换矩阵就是:

而matrix.postTranslate(view.getImageBitmap().getWidth()* 1.5f, 0f);的意思就是在上述矩阵的左边再乘以下面的矩阵:

关于post是左乘这一点,我们在前面的理论部分曾经提及过,后面我们还会专门讨论这个问题。

所以它实际上就是:

出去计算上的精度误差,我们可以看到我们计算出来的结果,和程序直接输出的结果是一致的。

3.     旋转(围绕坐标原点旋转,在加上两次平移,效果同2)

根据第一部分中“二、旋转变换”里面关于围绕某点旋转的解释,不难知道:

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

等价于

matrix.setRotate(45f);

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

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

其中matrix.setRotate(45f)对应的矩阵是:

matrix.preTranslate(-1f* view.getImageBitmap().getWidth() / 2f, -1f * view.getImageBitmap().getHeight()/ 2f)对应的矩阵是:

由于是preTranslate,是先乘,也就是右乘,即它应该出现在matrix.setRotate(45f)所对应矩阵的右侧。

matrix.postTranslate((float)view.getImageBitmap().getWidth()/ 2f, (float)view.getImageBitmap().getHeight() / 2f)对应的矩阵是:

这次由于是postTranslate,是后乘,也就是左乘,即它应该出现在matrix.setRotate(45f)所对应矩阵的左侧。

所以综合起来,

matrix.setRotate(45f);

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

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

对应的矩阵就是:

这和下面这个矩阵(围绕图像中心顺时针旋转45度)其实是一样的:

因此,此处变换后的图像和2中变换后的图像时一样的。

4.     缩放变换

程序所输出的两个矩阵分别是:

其中第二个矩阵,其实是下面两个矩阵相乘的结果:

大家可以对照第一部分中的“三、缩放变换”和“一、平移变换”说法,自行验证结果。

5.     错切变换(水平错切)

代码所输出的两个矩阵分别是:

其中,第二个矩阵其实是下面两个矩阵相乘的结果:

大家可以对照第一部分中的“四、错切变换”和“一、平移变换”的相关说法,自行验证结果。

6.     错切变换(垂直错切)

代码所输出的两个矩阵分别是:

其中,第二个矩阵其实是下面两个矩阵相乘的结果:

大家可以对照第一部分中的“四、错切变换”和“一、平移变换”的相关说法,自行验证结果。

7.     错切变换(水平+垂直错切)

代码所输出的两个矩阵分别是:

其中,后者是下面两个矩阵相乘的结果:

大家可以对照第一部分中的“四、错切变换”和“一、平移变换”的相关说法,自行验证结果。

8.     对称变换(水平对称)

代码所输出的两个各矩阵分别是:

其中,后者是下面两个矩阵相乘的结果:

大家可以对照第一部分中的“五、对称变换”和“一、平移变换”的相关说法,自行验证结果。

9.     对称变换(垂直对称)

代码所输出的两个矩阵分别是:

其中,后者是下面两个矩阵相乘的结果:

大家可以对照第一部分中的“五、对称变换”和“一、平移变换”的相关说法,自行验证结果。

10.   对称变换(对称轴为直线y = x)

代码所输出的两个矩阵分别是:

其中,后者是下面两个矩阵相乘的结果:

大家可以对照第一部分中的“五、对称变换”和“一、平移变换”的相关说法,自行验证结果。

11.   关于先乘和后乘的问题

由于矩阵的乘法运算不满足交换律,我们在前面曾经多次提及先乘、后乘的问题,即先乘就是矩阵运算中右乘,后乘就是矩阵运算中的左乘。其实先乘、后乘的概念是针对变换操作的时间先后而言的,左乘、右乘是针对矩阵运算的左右位置而言的。以第一部分“二、旋转变换”中围绕某点旋转的情况为例:

越靠近原图像中像素的矩阵,越先乘,越远离原图像中像素的矩阵,越后乘。事实上,图像处理时,矩阵的运算是从右边往左边方向进行运算的。这就形成了越在右边的矩阵(右乘),越先运算(先乘),反之亦然。

当然,在实际中,如果首先指定了一个matrix,比如我们先setRotate(),即指定了上面变换矩阵中,中间的那个矩阵,那么后续的矩阵到底是pre还是post运算,都是相对这个中间矩阵而言的。

所有这些,其实都是很自然的事情。

Android中图像变换Matrix的原理、代码验证和应用(二)的更多相关文章

  1. Android中图像变换Matrix的原理、代码验证和应用(一)

    第一部分 Matrix的数学原理 在Android中,如果你用Matrix进行过图像处理,那么一定知道Matrix这个类.Android中的Matrix是一个3 x 3的矩阵,其内容如下: Matri ...

  2. Android中图像变换Matrix的原理、代码验证和应用(三)

    第三部分 应用 在这一部分,我们会将前面两部分所了解到的内容和Android手势结合起来,利用各种不同的手势对图像进行平移.缩放和旋转,前面两项都是在实践中经常需要用到的功能,后一项据说苹果也是最近才 ...

  3. Android中的LruCache的原理和使用

    Android中的LruCache的原理和使用 LruCache,虽然很多文章都把LRU翻译成"最近最少使用"缓存策略,但Android中的LruCache真的如此吗? 答案是No ...

  4. Android中SensorManager.getRotationMatrix函数原理解释

    SensorManager是Android中的一个类,其有一个函数getRotationMatrix,可以计算出旋转矩阵,进而通过getOrientation求得设备的方向(航向角.俯仰角.横滚角). ...

  5. Android中的Matrix(矩阵)

    写在前面 看这篇笔记之前先看一下参考文章,这篇笔记没有系统的讲述矩阵和代码的东西,参考文章写的也有错误的地方,要辨证的看. 如何计算矩阵乘法 android matrix 最全方法详解与进阶(完整篇) ...

  6. Android 中View的工作原理

    Android中的View在Android的知识体系中扮演着重要的角色.简单来说,View就是Android在视觉的体现.我们所展现的页面就是Android提供的GUI库中控件的组合.但是当要求不能满 ...

  7. Android中微信抢红包插件原理解析和开发实现

    一.前言 自从去年中微信添加抢红包的功能,微信的电商之旅算是正式开始正式火爆起来.但是作为Android开发者来说,我们在抢红包的同时意识到了很多问题,就是手动去抢红包的速度慢了,当然这些有很多原因导 ...

  8. 【转】Android 学习笔记——利用JNI技术在Android中调用、调试C++代码

    原文网址:http://cherishlc.iteye.com/blog/1756762 在Android中调用C++其实就是在Java中调用C++代码,只是在windows下编译生成DLL,在And ...

  9. Android中典型的ROOT原理(5)

    ROOT的作用 Customization 用户的个人定制,如删除一些预安装,定制开机动画等. 特权操作 所有需要特权操作的基本都是要通过ROOT,这也是ROOT的初衷. ROOT的第一步:寻找漏洞并 ...

随机推荐

  1. SWT使用注意点

    出现这个错: java.lang.UnsatisfiedLinkError: no swt-win32-3139 in java.library.path 解决方法: 将swt-win32-3139导 ...

  2. oracle存储过程中的if...elseif...else用法

    if ... then ...   elsif ... then ... else ...   end if; or     if ... then      ...   else ...   end ...

  3. 表单事件onsubmit与onreset

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. Frequently Asked Questions - P-thresholds

    Source: http://mindhive.mit.edu/book/export/html 1. What is the multiple-comparison problem? What is ...

  5. TinyFrame升级之五:全局缓存的设计及实现

    在任何框架中,缓存都是不可或缺的一部分,本框架亦然.在这个框架中,我们的缓存分为两部分:内存缓存和单次请求缓存.简单说来,就是一个使用微软提供的MemoryCache做扩展,并提供全局唯一实例:另一个 ...

  6. vbs外部调用

    一.QTP调用外部VBS的方法 加到QTP的Resource中 在QTP菜单中设置, 菜单FileàSettingsàResource,将要加载的VB脚本添加进来. 举例: 步骤1:在D盘下新建一个V ...

  7. Linux下who命令之C语言实现

    Linux下who命令之C语言实现 Step1:前期准备 首先要有一个清楚的认识:linux中一切皆文件 实现who命令,who命令也是Linux中的一个文件,那我们怎么找到它呢?我们可以" ...

  8. 我理解的Hanlder--android消息传递机制

    每一个学习Android的同学都会觉得Handler是一个神奇的东西,我也一样,开始我以为我懂了Handler的机制,后来发现自己是一知半解,昨天想想,我能否自己实现一个Handler,让子线程与Ac ...

  9. sql server利用开窗函数over() 进行分组统计

    这是一道常见的面试题,在实际项目中经常会用到. 需求:求出以产品类别为分组,各个分组里价格最高的产品信息. 实现过程如下: declare @t table( ProductID int, Produ ...

  10. SQL Server Management Studio无法记住密码

    用sa账户登录sql server 2008,勾选了“记住密码”,但重新登录时,SQL Server Management Studio无法记住密码.   后来发现,在重新登录时,登录名显示的并非是s ...