android图片分辨率改变,android 通过修改图片像素实现CircleImageView

本文介绍了五种实现CircleImageView的方式:clipPath裁剪、PorterDuffXfermode、Shader、像素修改及硬件支持。重点讲解了利用勾股定理和点到圆距离的原理,对比了各方法的优缺点和适用场景。
摘要由CSDN通过智能技术生成

CircleImageView实现方法有很多种,各有优缺点,因此需要按照不同的场景使用。我们今天使用修改图片像素的方法实现CircleImageView,主要知识点无非是勾股定理和点到圆形的距离。

素材图片:

e419e21a4edb8435387bbbc7de413071.gif

0c8b180f6bd47a1a60a7e565bb1d6d8d.png 

e6d6866c15091d208c5dc6583ba6c87f.png

效果如下:

fbce50c68b8ab43374db3ad9ef9f6280.png

1、clipPath裁剪画布

该方法支持的最小版本是Android 4.3(API Level 18),方便快捷,但是不支持硬件加,此外也存在Path既有的缺点,不支持抗锯齿。

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

Paint paint = new Paint();

mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pic);

mPath = new Path();

mPath.addCircle(mBitmap.getWidth() / 2, mBitmap.getHeight() / 2, mBitmap.getWidth() / 2, Path.Direction.CCW);

canvas.clipPath(mPath);

canvas.drawBitmap(mBitmap, 0, 0, paint);

}

2、使用PorterDuffXfermode

PorterDuffXfermode是Android主流的图片合成工具,支持模式多,稳定性强,效果好,质量高,支持抗锯齿备受广大开发者喜爱,可以说是很多应用开发的首选。缺点是难度学习有些高,另外比较占内存。

/**

* 绘制圆形图片

*

*/

@Override

protected void onDraw(Canvas canvas) {

Drawable drawable = getDrawable();

if (null != drawable) {

Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();

Bitmap b = getCircleBitmap(bitmap);

final Rect rectSrc = new Rect(0, 0, b.getWidth(), b.getHeight());

final Rect rectDest = new Rect(0,0,getWidth(),getHeight());

paint.reset();

canvas.drawBitmap(b, rectSrc, rectDest, paint);

} else {

super.onDraw(canvas);

}

}

/**

* 获取圆形图片方法

* @param bitmap

* @param pixels

* @return Bitmap

*/

private Bitmap getCircleBitmap(Bitmap bitmap) {

Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),

bitmap.getHeight(), Config.ARGB_8888);

Canvas canvas = new Canvas(output);

final int color = 0xff424242;

final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());

paint.setAntiAlias(true);

canvas.drawColor(Color.TRANSPARENT);

paint.setColor(color);

int x = bitmap.getWidth();

canvas.drawCircle(x / 2, x / 2, x / 2, paint);

paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));

canvas.drawBitmap(bitmap, rect, rect, paint);

return output;

}

4、设置画笔Paint的Shader,然后用该画笔绘制圆形图片

该方法是Glide和picasso使用的方法,用法简单便捷,占内占有率处于中等水平。

@Override

protected void onDraw(Canvas canvas) {

Drawable drawable = getDrawable();

if (null != drawable) {

Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();

Bitmap b = transform(bitmap);

final Rect rectSrc = new Rect(0, 0, b.getWidth(), b.getHeight());

final Rect rectDest = new Rect(0,0,getWidth(),getHeight());

paint.reset();

canvas.drawBitmap(b, rectSrc, rectDest, paint);

} else {

super.onDraw(canvas);

}

}

public Bitmap transform(Bitmap source) {

int size = Math.min(source.getWidth(), source.getHeight());

int x = (source.getWidth() - size) / 2;

int y = (source.getHeight() - size) / 2;

Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);

if (squaredBitmap != source) {

source.recycle();

}

Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());

Canvas canvas = new Canvas(bitmap);

Paint paint = new Paint();

BitmapShader shader = new BitmapShader(squaredBitmap,

BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);

float mScale = (mRadius * 2.0f) / Math.min(bitmap.getHeight(), bitmap.getWidth());

Matrix matrix = new Matrix();

matrix.setScale(mScale, mScale);

bitmapShader.setLocalMatrix(matrix);

paint.setShader(shader);

paint.setAntiAlias(true);

float r = size / 2f;

canvas.drawCircle(r, r, r, paint);

squaredBitmap.recycle();

return bitmap;

}

5、修改像素

该方法无法支持抗锯齿,并且不支持Bitmap.Config.HARDWARE格式的bitmap,但用法简单,内存占有率同样处于比较低。

public class CircleImageView extends AppCompatImageView {

public CircleImageView(Context context) {

this(context,null);

}

public CircleImageView(Context context, AttributeSet attrs) {

this(context, attrs,0);

}

public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

}

@Override

public void onDraw(Canvas canvas) {

int width = getWidth();

int height = getHeight();

int minSize = Math.min(width,height)/2;

Drawable drawable = getDrawable();

if(drawable!=null && minSize!=0) {

if(Math.min(drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight())==0) {

return;

}

int intrinsicWidth = drawable.getIntrinsicWidth();

int intrinsicHeight = drawable.getIntrinsicHeight();

float R = Math.min(intrinsicWidth, intrinsicHeight) / 2;

Bitmap bmp = transformBitmap(drawable, intrinsicWidth, intrinsicHeight, R);

Matrix imageMatrix = getImageMatrix();

if((imageMatrix==null || imageMatrix.isIdentity()) && getPaddingTop()==0 && getPaddingLeft()==0){

drawCircleImage(canvas, bmp);

}else {

if (imageMatrix != null && !imageMatrix.isIdentity()) {

canvas.concat(imageMatrix);

}

final int saveCount = canvas.getSaveCount();

canvas.save();

if (getCropToPadding()) {

final int scrollX = getScrollX();

final int scrollY = getScrollY();

canvas.clipRect(scrollX + getPaddingLeft(), scrollY + getPaddingTop(),

scrollX + getRight() - getLeft() - getPaddingRight(),

scrollY + getBottom() - getTop() - getPaddingBottom());

}

canvas.translate(getPaddingLeft(), getPaddingTop());

drawCircleImage(canvas, bmp);

canvas.restoreToCount(saveCount);

}

if(bmp!=null && !bmp.isRecycled()) {

bmp.recycle();

}

}else{

super.onDraw(canvas);

}

}

private void drawCircleImage(Canvas canvas, Bitmap bmp) {

try {

DrawFilter drawFilter = canvas.getDrawFilter();

canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));

canvas.drawBitmap(bmp, 0, 0, null);

canvas.setDrawFilter(drawFilter);

}catch (Exception e){

e.printStackTrace();

return;

}

}

@NonNull

private Bitmap transformBitmap(Drawable drawable, int intrinsicWidth, int intrinsicHeight, float r) {

Bitmap bmp = Bitmap.createBitmap(intrinsicWidth, intrinsicHeight, Bitmap.Config.ARGB_8888);

Canvas targetCanvas = new Canvas(bmp);

try {

drawable.draw(targetCanvas);

for (int y = 0; y < intrinsicHeight; y++) {

for (int x = 0; x < intrinsicWidth; x++) {

if ((Math.pow(x - intrinsicWidth / 2, 2) + Math.pow(y - intrinsicHeight / 2, 2)) <= Math.pow(r, 2)) {

continue;

}

bmp.setPixel(x, y, Color.TRANSPARENT);

}

}

}catch (Exception e){

NCFLog.e("transformBitmap","e="+e.getLocalizedMessage());

e.printStackTrace();

}

return bmp;

}

public boolean isHardware(Bitmap sourceBitmap){

if(sourceBitmap==null) return false;

if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O) {

return sourceBitmap.getConfig() == Bitmap.Config.HARDWARE;

}

return false;

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值