引言
以前需要做一个图片圆角的功能,在网上搜索代码,然后直接用到项目中。今天又看到这段代码,感觉很陌生。而作为一名不合格的程序员,这种事情是不能不刨根问底的。所以就分析,以便和其他人的理解做对比。
代码
代码如下(stack overflow):
public static Bitmap toRoundCornerImage(Bitmap bitmap, int pixels) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Bitmap output = Bitmap.createBitmap(w, h, Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xfffefefe;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, w, h);
final RectF rectF = new RectF(rect);
final float roundPx = pixels;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
每张图片是由大量的点组成,每个点有颜色值,那么我们怎么来描述世界多姿多彩的颜色呢。科学家发现,组成颜色的三个基本的颜色是红(Red)绿(Green)蓝(Blue)。通过他们之间不同的比例来现实不同的颜色,以前我在小学的时候,老师要我们调颜色,颜料盒有7种颜色,我们胡乱的添加,最后得到非常恶心的颜色,鸡屎紫黄,更像似咖啡。颜色中还有一个属性——通道(alpha),就是你透过有色玻璃看的效果。要叫做透明度。比如我们今天分析的代码,我们传进来的图片是四四方方的,圆角部分则透明现实。
Bitmap output = Bitmap.createBitmap(w, h, Config.ARGB_8888);
所以这家代码中Config.ARGB_8888就表示每个度是8位,总共一个像素是32位。除了代码中的模式,还有其他3种:
public static final Bitmap.Config ALPHA_8
public static final Bitmap.Config ARGB_4444
public static final Bitmap.Config ARGB_8888
public static final Bitmap.Config RGB_565
图片压缩,大部分是减少像素点的位数。
绘图概念
The Canvas class holds the “draw” calls. To draw something, you need 4 basic components: A Bitmap to hold the pixels, a Canvas to host the draw calls (writing into the bitmap), a drawing primitive (e.g. Rect, Path, text, Bitmap), and a paint (to describe the colors and styles for the drawing).[来源](https://developer.android.com/reference/android/graphics/Canvas.html)
canvas(画布)持有绘画调用,要画出东西,你需要4个基础的组件:位图——去获取、持有像素;canvas(画布)主持绘画调用;原始绘图(矩形,路径,文本,位图),和画笔(描述绘画的颜色和样式)
我们中国的文化,把世界的组成基本元素分为金、木、水、火、土。早先的西方世界认为气、土组成,我们比他们丰富。但是西方后面更进一步认识世界,世界是由原子组成,而我们还停留在阴阳五行当中。所以软件绘图,也清楚的定义每个环节。位图用来保存生成的作品,canvas(画布)用来执行绘画,原始绘图用来描述要画的图像,画笔来描述图像的颜色,和样式。把一颗树表示原始绘图,画笔来表示树叶是青绿色,还是红黄色,前者绘出春色,后者描述晚秋。
方法思路
- 首先获取原图的高度、宽度。
- 以原图片的尺寸新建位图对象,并且是32位的。位图相当一个二位数组。
- 新建画布,画布画的内容存储在创建的位图中。
- 新建画笔。
- 新建矩形框,整数型,和浮点数型。浮点数型是为了后面的的绘图更精细。
- 设置画笔无锯齿属性,使得曲线更光滑。
- 第一次画图,用透明色填充画布。
- 第二次画图,用不透明白色画有圆角的图形,如果圆角直径等于正方形边长,则是圆形。
- 设置覆盖模式( PorterDuff及Xfermode详解),这主要是一个思想,画图是根据层来现实,主要是判定重叠的地方是否显示,或者底图现实。通过这个选择,来决定要留下来的图。我们这里代码是选择SRC_IN,表示取两层绘制交集。显示上层。
- 第三次画图,将原图绘制在画布上,保留中间圆形区域像素。
结语
啊------啊----啊,终于写完了。耗费了本少爷好多脑细胞,掉了我一拙黑头发,离光头强形象又进了一步。我想分析一下这个的算法复杂度。如果图片像素点有N个,那么这个方法的复杂度,大O记法O(3N)。因为对图片写了三次。