制作圆形图片
来源:互联网 发布:mac充电灯不亮但能充电 编辑:程序博客网 时间:2024/05/16 12:55
我的简书同步发布:制作圆形图片,你会以下几种?
转载请注明出处:【huachao1001的专栏:http://blog.csdn.net/huachao1001】
说起圆角图片,相信每个人心中都有自己的圆角图片制作方法。但是你是否想知道,除了你所会的那几张方法以外,还什么什么方法制作圆形图片呢?我们一一学习~
1 XferMode
关于通过使用XferMode方式创建圆形图片,hongyang大神的《 Android Xfermode 实战 实现圆形、圆角图片 》有讲,我这里大致把思路总结一下,我们知道,XferMode主要是将2张图片合在一起,由用户自己决定是选中图片重叠的部分还是非重叠的部分,可以参考Android官方提供的图片:
我们可以选择DstIn的方式来绘制圆形图,即在我们的原图上面再画一个实心圆形图,首先,我们先写一个函数,用于生成实心圆形的Bitmap:
private Bitmap mCircleBitmap; //生成一个实心圆形Bitmap,这个Bitmap宽高要与当前的View的宽高相同 private Bitmap getCircleBitmap() { if (mCircleBitmap == null) { mCircleBitmap = Bitmap.createBitmap(2 * mRadius, 2 * mRadius, Config.ARGB_8888); Canvas canvas = new Canvas(mCircleBitmap); mPaint.reset(); mPaint.setStyle(Style.FILL); canvas.drawCircle(mRadius, mRadius, mRadius, mPaint); } return mCircleBitmap; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
然后,再将这个Bitmap“盖”到用户设置的图片上面:
//将两张图片以XferMode(DST_IN)的方式组合到一张照片中 private Bitmap combineBitmap(Drawable drawable, Bitmap maskBitmap) { int width = drawable.getIntrinsicWidth(); int height = drawable.getIntrinsicHeight(); // 将drawable转bitmap Bitmap bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); //将图片自动放缩到View的宽高,即2倍的半径 drawable.setBounds(0, 0, mRadius*2, mRadius*2); drawable.draw(canvas); // 先将XferMode设置好,然后将盖在上面的bitmap绘制出来 mPaint.reset(); mPaint.setXfermode(xfermode); canvas.drawBitmap(maskBitmap, 0, 0, mPaint); mPaint.setXfermode(null); return bitmap; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
最后再将最终的Bitmap绘制到画板上面:
@Override protected void onDraw(Canvas canvas) { //获取设置的src图片 Drawable drawable = getDrawable(); //获取盖在src上面的实心圆形Bitmap Bitmap circleBitmap = getCircleBitmap(); //两张图片以XferMode(DST_IN)的方式组合 Bitmap bitmap = combineBitmap(drawable, circleBitmap); //将最终的bitmap画到画板上面 canvas.drawBitmap(bitmap, 0, 0, mPaint); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
看看完整的代码吧~
package com.hc.circleimage;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Bitmap.Config;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Paint.Style;import android.graphics.PorterDuff;import android.graphics.PorterDuffXfermode;import android.graphics.Xfermode;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.widget.ImageView;public class XfermodeCircleImage extends ImageView { private int mRadius; private Paint mPaint; private Xfermode xfermode; private Bitmap mCircleBitmap; public XfermodeCircleImage(Context context) { super(context); init(); } public XfermodeCircleImage(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { mPaint = new Paint(); xfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = getMeasuredWidth(); int height = getMeasuredHeight(); if (width > height) { mRadius = height / 2; } else { mRadius = width / 2; } setMeasuredDimension(mRadius * 2, mRadius * 2); } //生成一个实心圆形Bitmap,这个Bitmap宽高要与当前的View的宽高相同 private Bitmap getCircleBitmap() { if (mCircleBitmap == null) { mCircleBitmap = Bitmap.createBitmap(2 * mRadius, 2 * mRadius, Config.ARGB_8888); Canvas canvas = new Canvas(mCircleBitmap); mPaint.reset(); mPaint.setStyle(Style.FILL); canvas.drawCircle(mRadius, mRadius, mRadius, mPaint); } return mCircleBitmap; } //将两张图片以XferMode(DST_IN)的方式组合到一张照片中 private Bitmap combineBitmap(Drawable drawable, Bitmap maskBitmap) { int width = drawable.getIntrinsicWidth(); int height = drawable.getIntrinsicHeight(); // 将drawable转bitmap Bitmap bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); //将图片自动放缩到View的宽高,即2倍的半径 drawable.setBounds(0, 0, mRadius*2, mRadius*2); drawable.draw(canvas); // 先将XferMode设置好,然后将盖在上面的bitmap绘制出来 mPaint.reset(); mPaint.setXfermode(xfermode); canvas.drawBitmap(maskBitmap, 0, 0, mPaint); mPaint.setXfermode(null); return bitmap; } @Override protected void onDraw(Canvas canvas) { //获取设置的src图片 Drawable drawable = getDrawable(); //获取盖在src上面的实心圆形Bitmap Bitmap circleBitmap = getCircleBitmap(); //两张图片以XferMode(DST_IN)的方式组合 Bitmap bitmap = combineBitmap(drawable, circleBitmap); //将最终的bitmap画到画板上面 canvas.drawBitmap(bitmap, 0, 0, mPaint); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
对自定义View不熟的童鞋可以参考《自定义View,有这一篇就够了》 。最后看看效果吧~
2 BitmapShader
同样的,hongyang大神也写过关于BitmapShader方式绘制圆形图片《 Android BitmapShader 实战 实现圆形、圆角图片 》,我们同样来个简单总结,Shader翻译成中文叫“着色器”,而我们的BitmapShader是Shader的子类,BitmapShader有啥作用呢,它可以根据你设置的方式(下面介绍)将图片铺满你所选的区域,有哪几种方式“铺”呢?有以下几种:
(1)CLAMP:拉伸,在x方向上是图片的最后一列像素重复平铺,而y方向是最后一行往下拉伸
(2)REPEAT: 重复,很容易理解,图片重复平铺过去
(3)MIRROR:镜像,就是将图片翻转
我们来看几张图片感受一下:
CLAMP的方式:
REPEAT方式
MIRROR方式
使用BitmapShader制作圆形图片的方法非常简单,只需通过Bitmap构造出一个BitmapShader,并将这个BitmapShader设置到当前的Paint当中,用这个Paint绘制一个圆就可以了,先看看onDraw函数:
@Override protected void onDraw(Canvas canvas) { // 将Drawable转为Bitmap Bitmap bmp = drawableToBitmap(getDrawable()); // 通过Bitmap和指定x,y方向的平铺方式构造出BitmapShader对象 BitmapShader mBitmapShader = new BitmapShader(bmp, TileMode.CLAMP, TileMode.CLAMP); // 将BitmapShader设置到当前的Paint对象中 mPaint.setShader(mBitmapShader); // 绘制出一个圆 canvas.drawCircle(mRadius, mRadius, mRadius, mPaint); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
其中,drawableToBitmap是将Drawable对象转为Bitmap对象:
private Bitmap drawableToBitmap(Drawable drawable) { if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable) drawable).getBitmap(); } else { int width = drawable.getIntrinsicWidth(); int height = drawable.getIntrinsicHeight(); Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, width, height); drawable.draw(canvas); return bitmap; }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
我们看看完整代码吧
package com.hc.circleimage;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapShader;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Shader.TileMode;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.widget.ImageView;public class ShaderCircleImage extends ImageView { private int mRadius; private Paint mPaint; public ShaderCircleImage(Context context) { super(context); init(); } public ShaderCircleImage(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { mPaint = new Paint(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = getMeasuredWidth(); int height = getMeasuredHeight(); if (width > height) { mRadius = height / 2; } else { mRadius = width / 2; } setMeasuredDimension(mRadius * 2, 2 * mRadius); } private Bitmap drawableToBitmap(Drawable drawable) { if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable) drawable).getBitmap(); } else { int width = drawable.getIntrinsicWidth(); int height = drawable.getIntrinsicHeight(); Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, mRadius*2, mRadius*2); drawable.draw(canvas); return bitmap; } } @Override protected void onDraw(Canvas canvas) { // 将Drawable转为Bitmap Bitmap bmp = drawableToBitmap(getDrawable()); // 通过Bitmap和指定x,y方向的平铺方式构造出BitmapShader对象 BitmapShader mBitmapShader = new BitmapShader(bmp, TileMode.CLAMP, TileMode.CLAMP); // 将BitmapShader设置到当前的Paint对象中 mPaint.setShader(mBitmapShader); // 绘制出一个圆 canvas.drawCircle(mRadius, mRadius, mRadius, mPaint); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
最后是要看看效果的,但是效果跟前面的效果是一样的,我们还是看一下吧~
3 ClipPath
前面的2中方法我们都见过,我们在看另一种方法吧ClipPath,或许你听说过Canvas对象的clipPath方法,或者是用过这个方法,可是有没有想过这个方法也可以用来绘制圆形图片呢?
我们看看代码吧:
@Overrideprotected void onDraw(Canvas canvas) { // 将Drawable转为Bitmap Bitmap bmp = drawableToBitmap(getDrawable()); Path path = new Path(); //按照逆时针方向添加一个圆 path.addCircle(mRadius, mRadius, mRadius, Direction.CCW); //先将canvas保存 canvas.save(); //设置为在圆形区域内绘制 canvas.clipPath(path); //绘制Bitmap canvas.drawBitmap(bmp, 0, 0, mPaint); //恢复Canvas canvas.restore();}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
是不是如此简单?过于简单,注释已经写明各行代码的意思啦!drawableToBitmap函数在上面一节解释过啦,这里就不再重复解释了,看看完整代码吧:
package com.hc.circleimage;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Path;import android.graphics.Path.Direction;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.widget.ImageView;public class ClipCircleImage extends ImageView { private int mRadius; private Paint mPaint; public ClipCircleImage(Context context) { super(context); init(); } public ClipCircleImage(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { mPaint = new Paint(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = getMeasuredWidth(); int height = getMeasuredHeight(); if (width > height) { mRadius = height / 2; } else { mRadius = width / 2; } setMeasuredDimension(mRadius * 2, 2 * mRadius); } private Bitmap drawableToBitmap(Drawable drawable) { if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable) drawable).getBitmap(); } else { int width = drawable.getIntrinsicWidth(); int height = drawable.getIntrinsicHeight(); Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, mRadius*2, mRadius*2); drawable.draw(canvas); return bitmap; } } @Override protected void onDraw(Canvas canvas) { // 将Drawable转为Bitmap Bitmap bmp = drawableToBitmap(getDrawable()); Path path = new Path(); //按照逆时针方向添加一个圆 path.addCircle(mRadius, mRadius, mRadius, Direction.CCW); //先将canvas保存 canvas.save(); //设置为在圆形区域内绘制 canvas.clipPath(path); //绘制Bitmap canvas.drawBitmap(bmp, 0, 0, mPaint); //恢复Canvas canvas.restore(); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
效果虽然跟上面两节是一样的,但是我们还是看一下效果吧~
4 Alpha提取
现在我们看看一个很少见的方法,这个方法也是我不怎么推荐的方法,它是通过将一个张图的Alpha通道值设置到另外一张图中,啥意思呢?就是说,将两张图片的透明度设置为一模一样!看上去很酷的样子~,虽然不推荐,但是我们可以去学习一下嘛~可能某些项目需求中只能用这种方法去实现呢?
//获取圆形Bitmapprivate Bitmap getCircleMask() { Bitmap bitmap = Bitmap.createBitmap(mRadius * 2, mRadius * 2, Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); canvas.drawCircle(mRadius, mRadius, mRadius, mPaint); return bitmap;}//将rgbBitmap的RGB值与alphaBitmap的alpha值组成新的Bitmapprivate Bitmap getBitmap(Bitmap rgbBitmap, Bitmap alphaBitmap) { Bitmap newBmp = Bitmap.createBitmap(mRadius * 2, mRadius * 2, Config.ARGB_8888); int alphaMask = 0xFF << 24; int rgbMask = ~alphaMask; for (int x = 0; x < 2 * mRadius; x++) { for (int y = 0; y < 2 * mRadius; y++) { int color = (rgbMask & rgbBitmap.getPixel(x, y)) | (alphaMask & alphaBitmap.getPixel(x, y)); newBmp.setPixel(x, y, color); } } return newBmp;}@Overrideprotected void onDraw(Canvas canvas) { // 将Drawable转为Bitmap Bitmap rgbBitmap = drawableToBitmap(getDrawable()); //提取alpha值通道 Bitmap alphaBitmap = getCircleMask().extractAlpha(); //将最终图片绘制出来 canvas.drawBitmap(getBitmap(rgbBitmap, alphaBitmap), 0, 0, mPaint);}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
我们可以看到,通过两个for循环来新建合成一个新的图片,这个效率非常的低下!!!!!实际中不推荐采用这种方式,当然了,我们可以通过使用RenderScript并行处理,最终效率也不会比前面3种方法差!最终效果我就不贴上来了,依然是与前面几种方法是相同的
最后,把源码献上:http://download.csdn.net/detail/huachao1001/9541176
- iOS 制作圆形图片
- 圆形图片的制作
- 制作圆形图片
- iOS制作圆形图片头像
- 使用photoshop将图片制作成圆形
- 安卓图片--PorterDuffXfermode并制作圆形图片
- Android 两种制作圆形/圆角图片的方法
- Android 两种制作圆形/圆角图片的方法
- 制作圆形图片,你会以下几种?
- 1.亿图的使用;2.制作圆形图片
- 如何使用GDI+制作圆形图片(类似QQ头像)
- 圆形图片
- 圆形图片
- 圆形图片
- 圆形图片
- 圆形图片
- 圆形图片
- 圆形图片
- Centos下配置免安装版jdk
- css样式中 border的应用
- Spring-framwork-core-1.1-1.2
- 详解YUV数据格式
- PHP AES 128位加密算法
- 制作圆形图片
- 理解mysql索引背后的数据结构B~Tree(B-Tree/B+Tree)
- json基本使用
- web前端案例-js开发智能鼠标感知遮罩层
- postgres访问认证配置文件pg_hba.conf
- makefile多目录的.c 格式.cpp混合编译
- Java_GC(三) ----不同gc的使用命令
- Nginx监听非80端口反向代理80端口出现跳转错误
- CodeForces-489f