读书人

图片相交形式 setXfermode

发布时间: 2013-10-29 12:07:57 作者: rapoo

图片相交模式 setXfermode

网上的资料 图片倒影 原文地址http://onewayonelife.iteye.com/blog/1169176

MainActivity

Java代码 图片相交形式  setXfermode
  1. package org.wp.activity;
  2. import android.app.Activity;
  3. import android.graphics.Bitmap;
  4. import android.graphics.Canvas;
  5. import android.graphics.LinearGradient;
  6. import android.graphics.Matrix;
  7. import android.graphics.PorterDuffXfermode;
  8. import android.graphics.Bitmap.Config;
  9. import android.graphics.PorterDuff.Mode;
  10. import android.graphics.Shader.TileMode;
  11. import android.graphics.Paint;
  12. import android.graphics.drawable.BitmapDrawable;
  13. import android.os.Bundle;
  14. import android.widget.ImageView;
  15. /**
  16. * ==========================================
  17. * Matrix
  18. * ==========================================
  19. * The Matrix class holds a 3x3 matrix for transforming coordinates.
  20. * Matrix does not have a constructor,
  21. * so it must be explicitly initialized using either reset()
  22. * - to construct an identity matrix,
  23. * or one of the set..() functions
  24. * (e.g. setTranslate, setRotate, etc.).
  25. *
  26. * Matrix 中文里叫矩阵,高等数学里有介绍
  27. * 在图像处理方面,主要是用于平面的缩放、平移、旋转等操作。
  28. * Matrix的操作,总共分为translate(平移),rotate(旋转),
  29. * scale(缩放)和skew(倾斜)四种,
  30. * 每一种变换在Android的API里都提供了set, post和pre三种操作方式
  31. * 除了translate,其他三种操作都可以指定中心点。
  32. *
  33. * ==========================================
  34. * createBitmap
  35. * ==========================================
  36. * public static Bitmap createBitmap (Bitmap source, int x, int y,
  37. * int width, int height, Matrix m, boolean filter)
  38. * Since: API Level 1 Returns an immutable bitmap from subset of the
  39. * source bitmap, transformed by the optional matrix.
  40. * It is initialized with the same density as the original bitmap.
  41. * Parameters
  42. * source The bitmap we are subsetting
  43. * x The x coordinate of the first pixel in source
  44. * y The y coordinate of the first pixel in source
  45. * width The number of pixels in each row
  46. * height The number of rows
  47. * m Optional matrix to be applied to the pixels
  48. * filter true if the source should be filtered.
  49. * Only applies if the matrix contains more than
  50. * just translation.
  51. * Returns
  52. * A bitmap that represents the specified subset of source
  53. * Throws
  54. * IllegalArgumentException
  55. * if the x, y, width, height values are outside of the
  56. * dimensions of the source bitmap.
  57. *
  58. * source 源 bitmap对象
  59. * x 源坐标x位置
  60. * y 源坐标y位置
  61. * width 宽度
  62. * height 高度
  63. * m 接受的maxtrix对象,如果没有可以设置 为null
  64. * filter 该参数仅对maxtrix包含了超过一个翻转才有效
  65. *
  66. * ==========================================
  67. * LinearGradient
  68. * ==========================================
  69. * public LinearGradient (float x0, float y0, float x1, float y1, i
  70. * nt color0, int color1, Shader.TileMode tile)
  71. * Since: API Level 1 Create a shader that draws a linear gradient along a line.
  72. * Parameters
  73. * x0 The x-coordinate for the start of the gradient line
  74. * y0 The y-coordinate for the start of the gradient line
  75. * x1 The x-coordinate for the end of the gradient line
  76. * y1 The y-coordinate for the end of the gradient line
  77. * color0 The color at the start of the gradient line.
  78. * color1 The color at the end of the gradient line.
  79. * tile The Shader tiling mode
  80. *
  81. * 在android.graphics中我们可以找到有关Gradient字样的类,
  82. * 比如LinearGradient 线性渐变、RadialGradient径向渐变 和 角度渐变SweepGradient 三种,
  83. * 他们的基类为android.graphics.Shader。
  84. *
  85. * LinearGradient线性渐变
  86. * 在android平台中提供了两种重载方式来实例化该类分别为,
  87. * 他们的不同之处为参数中第一种方法可以用颜色数组,和位置来实现更细腻的过渡效果,
  88. * 比如颜色采样int[] colors数组中存放20种颜色,则渐变将会逐一处理。
  89. * 而第二种方法参数仅为起初颜色color0和最终颜色color1。
  90. * LinearGradient(float x0, float y0, float x1, float y1,
  91. * int[] colors, float[] positions, Shader.TileMode tile)
  92. * LinearGradient(float x0, float y0, float x1, float y1,
  93. * int color0, int color1, Shader.TileMode tile)
  94. *
  95. * 参数一为渐变起初点坐标x位置,参数二为y轴位置,
  96. * 参数三和四分辨对应渐变终点,最后参数为平铺方式,这里设置为镜像
  97. *
  98. * 刚才已经讲到Gradient是基于Shader类,
  99. * 所以我们通过Paint的setShader方法来设置这个渐变
  100. * p.setShader(lg);
  101. *
  102. * ==========================================
  103. * setXfermode
  104. * ==========================================
  105. * Xfermode
  106. * 可以通过修改Paint的Xfermode来影响在
  107. * Canvas已有的图像上面绘制新的颜色的方式 。
  108. *
  109. * 在正常的情况下,在已有的图像上绘图将会在其上面添加一层新的形状。
  110. * 如果新的Paint是完全不透明的,那么它将完全遮挡住下面的Paint;
  111. * 如果它是部分透明的,那么它将会被染上下面的颜色。
  112. *
  113. * 下面的Xfermode子类可以改变这种行为:
  114. *
  115. * AvoidXfermode 指定了一个颜色和容差,
  116. * 强制Paint避免在它上面绘图(或者只在它上面绘图)。
  117. * PixelXorXfermode 当覆盖已有的颜色时,应用一个简单的像素XOR操作。
  118. *
  119. * PorterDuffXfermode 这是一个非常强大的转换模式,使用它,
  120. * 可以使用图像合成的16条Porter-Duff规则的任意
  121. * 一条来控制Paint如何与已有的Canvas图像进行交互。
  122. *
  123. * 16条Porter-Duff规则
  124. * 1.PorterDuff.Mode.CLEAR
  125. * 2.PorterDuff.Mode.SRC
  126. * 3.PorterDuff.Mode.DST
  127. * 4.PorterDuff.Mode.SRC_OVER
  128. * 5.PorterDuff.Mode.DST_OVER
  129. * 6.PorterDuff.Mode.SRC_IN
  130. * 7.PorterDuff.Mode.DST_IN
  131. * 8.PorterDuff.Mode.SRC_OUT
  132. * 9.PorterDuff.Mode.DST_OUT
  133. * 10.PorterDuff.Mode.SRC_ATOP
  134. * 11.PorterDuff.Mode.DST_ATOP
  135. * 12.PorterDuff.Mode.XOR
  136. * 13.PorterDuff.Mode.DARKEN
  137. * 14.PorterDuff.Mode.LIGHTEN
  138. * 15.PorterDuff.Mode.MULTIPLY
  139. * 16.PorterDuff.Mode.SCREEN
  140. * 图片相交形式  setXfermode
  141. * @author wp
  142. */
  143. public class MainActivity extends Activity {
  144. @Override
  145. public void onCreate(Bundle savedInstanceState) {
  146. super.onCreate(savedInstanceState);
  147. setContentView(R.layout.main);
  148. ImageView myImageView = (ImageView) this.findViewById(R.id.myImageView);
  149. Bitmap bitmap = ((BitmapDrawable) getResources().getDrawable(
  150. R.drawable.qianqian)).getBitmap();
  151. myImageView.setImageBitmap(createReflectedImage(bitmap));
  152. }
  153. private Bitmap createReflectedImage(Bitmap originalBitmap) {
  154. // 图片与倒影间隔距离
  155. final int reflectionGap = 4;
  156. // 图片的宽度
  157. int width = originalBitmap.getWidth();
  158. // 图片的高度
  159. int height = originalBitmap.getHeight();
  160. Matrix matrix = new Matrix();
  161. // 图片缩放,x轴变为原来的1倍,y轴为-1倍,实现图片的反转
  162. matrix.preScale(1, -1);
  163. // 创建反转后的图片Bitmap对象,图片高是原图的一半。
  164. Bitmap reflectionBitmap = Bitmap.createBitmap(originalBitmap, 0,
  165. height / 2, width, height / 2, matrix, false);
  166. // 创建标准的Bitmap对象,宽和原图一致,高是原图的1.5倍。
  167. Bitmap withReflectionBitmap = Bitmap.createBitmap(width, (height
  168. + height / 2 + reflectionGap), Config.ARGB_8888);
  169. // 构造函数传入Bitmap对象,为了在图片上画图
  170. Canvas canvas = new Canvas(withReflectionBitmap);
  171. // 画原始图片
  172. canvas.drawBitmap(originalBitmap, 0, 0, null);
  173. // 画间隔矩形
  174. Paint defaultPaint = new Paint();
  175. canvas.drawRect(0, height, width, height + reflectionGap, defaultPaint);
  176. // 画倒影图片
  177. canvas.drawBitmap(reflectionBitmap, 0, height + reflectionGap, null);
  178. // 实现倒影效果
  179. Paint paint = new Paint();
  180. LinearGradient shader = new LinearGradient(0, originalBitmap.getHeight(),
  181. 0, withReflectionBitmap.getHeight(), 0x70ffffff, 0x00ffffff,
  182. TileMode.MIRROR);
  183. paint.setShader(shader);
  184. paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
  185. // 覆盖效果
  186. canvas.drawRect(0, height, width, withReflectionBitmap.getHeight(), paint);
  187. return withReflectionBitmap;
  188. }
  189. }
================================================================================================================================


原文地址http://lipeng88213.iteye.com/blog/1189452

setXfermode


设置两张图片相交时的模式

我们知道 在正常的情况下,在已有的图像上绘图将会在其上面添加一层新的形状。 如果新的Paint是完全不透明的,那么它将完全遮挡住下面的Paint;

而setXfermode就可以来解决这个问题


一般来说 用法是这样的

Java代码 图片相交形式  setXfermode
  1. Canvas canvas = new Canvas(bitmap1);
  2. paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
  3. canvas.drawBitmap(mask, 0f, 0f, paint);

就是在图片bitmap1上面绘制图片mask时 处理两者相交时候显示的问题

canvas原有的图片 可以理解为背景 就是dst
新画上去的图片 可以理解为前景 就是src


Mode的值 如下图

图片相交形式  setXfermode


一个遮罩层的具体例子 原文http://lonesane.iteye.com/blog/791267

图片相交形式  setXfermode

由于中间黄色部分是进度条区域,带有一定的弧度而不是规则的长方形。刚开始想偷懒用了很多办法来实现效果都不理想。后来想到使用遮罩层可以非常方便的实现这个功能。

可以通过修改Paint的Xfermode来实现遮罩的效果。Xfermode的功能非常强大,在API DEMO的Graphics中的最后一项有demo。看一下怎么实现我们的这个进度条吧。

首先用图片处理软件制作一个和中间黄色区域相同的图形,我们将在代码中设置它做为遮罩。


图片相交形式  setXfermode

View的draw方法

Java代码 图片相交形式  setXfermode
  1. public void draw(Canvas canvas) {
  2. //背景部分,也就是上面的图形
  3. Bitmap background = BitmapFactory.decodeResource(getResources(),
  4. R.drawable.guage);
  5. //遮罩,就是提取来部分
  6. Bitmap mask = BitmapFactory.decodeResource(getResources(),
  7. R.drawable.mask);
  8. canvas.drawColor(Color.WHITE);
  9. canvas.drawBitmap(background, 0, 0, null);
  10. Paint paint = new Paint();
  11. paint.setFilterBitmap(false);
  12. int x = 0;
  13. int y = 0;
  14. // draw the src/dst example into our offscreen bitmap
  15. int sc = canvas.saveLayer(x, y, x + background.getWidth(), y + background.getHeight(), null,
  16. Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG
  17. | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG
  18. | Canvas.FULL_COLOR_LAYER_SAVE_FLAG
  19. | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
  20. // canvas.drawBitmap(mDstB, 0, 0, paint);
  21. canvas.drawRect(0, 0, background.getWidth() / 2, background
  22. .getHeight(), paint);
  23. paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
  24. // canvas.drawBitmap(mSrcB, 0, 0, paint);
  25. canvas.drawBitmap(mask, 0f, 0f, paint);
  26. paint.setXfermode(null);
  27. canvas.restoreToCount(sc);
  28. }

只用控制绘制的矩形的长度就可以实现进度条的效果了。


图片相交形式  setXfermode 图片相交形式  setXfermode 图片相交形式  setXfermode

我做的效果是这样的,图片弄成圆的,效果如下

图片相交形式  setXfermode

主要代码

// 圆形头像
cover_user_photo = (CircularImage) view
.findViewById(R.id.cover_user_photo);

String iconpath = getActivity().getApplicationContext().getFilesDir().getAbsolutePath()+ "/";
iconpath += YqApp.mUserSettings.getString(PreferenceKey.USER_PIC, "");
File mfile = new File(iconpath);
Bitmap bm = null;
if (mfile.exists()) {// 若该文件存在
bm = BitmapFactory.decodeFile(iconpath);
}
Drawable drawab = null;
if (null != bm) {
drawab = new BitmapDrawable(createFramedPhoto(
getActivity().getWindowManager().getDefaultDisplay().getWidth()/2,
getActivity().getWindowManager().getDefaultDisplay().getHeight()/2, bm, 400));
}

if (null != drawab)
cover_user_photo.setBackgroundDrawable(drawab);
else
cover_user_photo.setImageResource(R.drawable.face);

private Bitmap createFramedPhoto(int x, int y, Bitmap image, float outerRadiusRat) {
Drawable imageDrawable = new BitmapDrawable(image);
Bitmap output = Bitmap.createBitmap(x, y, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);

RectF outerRect = new RectF(0, 0, x, y);

Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.RED);
canvas.drawRoundRect(outerRect, outerRadiusRat, outerRadiusRat, paint);

paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
imageDrawable.setBounds(0, 0, x, y);
canvas.saveLayer(outerRect, paint, Canvas.ALL_SAVE_FLAG);
imageDrawable.draw(canvas);
canvas.restore();

return output;
}


读书人网 >移动开发

热点推荐