在Android中从位图裁剪圆形区域
我有一个位图,我想从这个位图裁剪一个圆形的区域。 圆圈外的所有像素都应该是透明的。 我怎样才能做到这一点?
经过长时间的头脑风暴,我find了解决办法
public Bitmap getCroppedBitmap(Bitmap bitmap) { Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888); Canvas canvas = new Canvas(output); final int color = 0xff424242; final Paint paint = new Paint(); final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); // canvas.drawRoundRect(rectF, roundPx, roundPx, paint); canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2, bitmap.getWidth() / 2, paint); paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); canvas.drawBitmap(bitmap, rect, rect, paint); //Bitmap _bmp = Bitmap.createScaledBitmap(output, 60, 60, false); //return _bmp; return output; }
从矩形生成圆
public static Bitmap getCircularBitmap(Bitmap bitmap) { Bitmap output; if (bitmap.getWidth() > bitmap.getHeight()) { output = Bitmap.createBitmap(bitmap.getHeight(), bitmap.getHeight(), Config.ARGB_8888); } else { output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getWidth(), Config.ARGB_8888); } Canvas canvas = new Canvas(output); final int color = 0xff424242; final Paint paint = new Paint(); final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); float r = 0; if (bitmap.getWidth() > bitmap.getHeight()) { r = bitmap.getHeight() / 2; } else { r = bitmap.getWidth() / 2; } paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); canvas.drawCircle(r, r, r, paint); paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); canvas.drawBitmap(bitmap, rect, rect, paint); return output; }
@Gene对上面的答案做了一个评论,build议使用clipPath
作为将图像裁剪成圆的选项。
以下是这个干净的实现:
public static Bitmap GetBitmapClippedCircle(Bitmap bitmap) { final int width = bitmap.getWidth(); final int height = bitmap.getHeight(); final Bitmap outputBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888); final Path path = new Path(); path.addCircle( (float)(width / 2) , (float)(height / 2) , (float) Math.min(width, (height / 2)) , Path.Direction.CCW); final Canvas canvas = new Canvas(outputBitmap); canvas.clipPath(path); canvas.drawBitmap(bitmap, 0, 0, null); return outputBitmap; }
这可以添加到实用程序类。
你可以让你的imageview使用RoundedBitmapDrawable循环
这里是实现roundedImageview的代码:
ImageView profilePic=(ImageView)findViewById(R.id.user_image); //get bitmap of the image Bitmap imageBitmap=BitmapFactory.decodeResource(getResources(), R.drawable.large_icon); RoundedBitmapDrawable roundedBitmapDrawable=RoundedBitmapDrawableFactory.create(getResources(), imageBitmap); //setting radius roundedBitmapDrawable.setCornerRadius(50.0f); roundedBitmapDrawable.setAntiAlias(true); profilePic.setImageDrawable(roundedBitmapDrawable);
这可以很容易地在xml中完成,而不会裁剪实际的位图,您只需要创build一个圆形图像蒙版,并放置在您的实际图像。 这是我使用的一段代码:
circle.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" > <gradient android:startColor="#00FFFFFF" android:endColor="#00FFFFFF" android:angle="270"/> <stroke android:width="10dp" android:color="#FFAAAAAA"/>
your_layout.xml (忽略“android:scaleType =”fitXY“”如果你不需要它的话)
<RelativeLayout android:id="@+id/icon_layout" android:layout_width="@dimen/icon_mask" android:layout_height="@dimen/icon_mask" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" > <ImageView android:id="@+id/icon" android:layout_width="@dimen/icon" android:layout_height="@dimen/icon" android:layout_centerInParent="true" android:scaleType="fitXY" > </ImageView> <ImageView android:id="@+id/icon_mask" android:layout_width="@dimen/icon_mask" android:layout_height="@dimen/icon_mask" android:layout_centerInParent="true" android:background="@drawable/circle" android:scaleType="fitXY" > </ImageView> </RelativeLayout>
dimen.xml
<dimen name="icon">36dp</dimen> <dimen name="icon_mask">55dp</dimen>
输出图像视图:
希望,这可能是有用的人! 🙂
我认为这个解决scheme对于任何types的矩形都可以更好地工作,如果你想要图像小或大,就改变像素大小:
public static Bitmap getCircleBitmap(Bitmap bm) { int sice = Math.min((bm.getWidth()), (bm.getHeight())); Bitmap bitmap = ThumbnailUtils.extractThumbnail(bm, sice, sice); Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(output); final int color = 0xffff0000; final Paint paint = new Paint(); final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); final RectF rectF = new RectF(rect); paint.setAntiAlias(true); paint.setDither(true); paint.setFilterBitmap(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); canvas.drawOval(rectF, paint); paint.setColor(Color.BLUE); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth((float) 4); paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); canvas.drawBitmap(bitmap, rect, rect, paint); return output; }
你可以使用这个代码,它会工作
public Bitmap getRoundedShape(Bitmap scaleBitmapImage) { int targetWidth = 110; int targetHeight = 110; Bitmap targetBitmap = Bitmap.createBitmap(targetWidth, targetHeight,Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(targetBitmap); Path path = new Path(); path.addCircle(((float) targetWidth - 1) / 2, ((float) targetHeight - 1) / 2, (Math.min(((float) targetWidth), ((float) targetHeight)) / 2), Path.Direction.CCW); canvas.clipPath(path); Bitmap sourceBitmap = scaleBitmapImage; canvas.drawBitmap(sourceBitmap, new Rect(0, 0, sourceBitmap.getWidth(), sourceBitmap.getHeight()), new Rect(0, 0, targetWidth, targetHeight), new Paint(Paint.FILTER_BITMAP_FLAG)); return targetBitmap; }
你可以使用这个代码,它会工作
private Bitmap getCircleBitmap(Bitmap bitmap) { final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); final Canvas canvas = new Canvas(output); final int color = Color.RED; final Paint paint = new Paint(); final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); final RectF rectF = new RectF(rect); paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); canvas.drawOval(rectF, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(bitmap, rect, rect, paint); bitmap.recycle(); return output; }
我build议添加bitmap.recycle()
如果你不再需要它,它会防止OutOfMemory错误。
对于想要矩形(我)的中心的人,请在切割之前添加:
public static Bitmap cropBitmapToBlock(Bitmap bitmap) { if (bitmap.getWidth() >= bitmap.getHeight()){ return Bitmap.createBitmap( bitmap, bitmap.getWidth()/2 - bitmap.getHeight()/2, 0, bitmap.getHeight(), bitmap.getHeight() ); }else{ return Bitmap.createBitmap( bitmap, 0, bitmap.getHeight()/2 - bitmap.getWidth()/2, bitmap.getWidth(), bitmap.getWidth() ); } }
Android作物中心的位图
根据[Jachumbelechao Unto Mantekilla]的回答,这段代码对于寻找Kotlin解决scheme的人来说就像一个魅力:
fun cropCircleFromBitmap(originalBitmap: Bitmap): Bitmap { val size = Math.min(originalBitmap.width, originalBitmap.height) val bitmap = ThumbnailUtils.extractThumbnail(originalBitmap, size, size) var output = Bitmap.createBitmap(bitmap.width, bitmap.height, Bitmap.Config.ARGB_8888) val canvas = Canvas(output) val paint = Paint() val rect = Rect(0, 0, bitmap.width, bitmap.height) val rectF = RectF(rect) paint.isAntiAlias = true paint.isDither = true paint.isFilterBitmap = true canvas.drawARGB(0, 0, 0, 0) paint.color = 0xffff0000.toInt() canvas.drawOval(rectF, paint) paint.color = Color.BLUE paint.style = Paint.Style.STROKE paint.strokeWidth = 4f paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN); canvas.drawBitmap(bitmap, rect, rect, paint) return output }
现在,正确答案:
private Bitmap getCroppedBitmap(Bitmap bitmap, Integer cx, Integer cy, Integer radius) { int diam = radius << 1; Bitmap targetBitmap = Bitmap.createBitmap(diam, diam, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(targetBitmap); final int color = 0xff424242; final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); canvas.drawCircle(radius, radius, radius, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(bitmap, -cx+radius, -cy+radius, paint); return targetBitmap; }
这里是使用扩展方法的Kotlin变体
/** * Creates new circular bitmap based on original one. */ fun Bitmap.getCircularBitmap(config: Bitmap.Config = Bitmap.Config.ARGB_8888): Bitmap { // circle configuration val circlePaint = Paint().apply { isAntiAlias = true } val circleRadius = Math.max(width, height) / 2f // output bitmap val outputBitmapPaint = Paint(circlePaint).apply { xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN) } val outputBounds = Rect(0, 0, width, height) val output = Bitmap.createBitmap(width, height, config) return Canvas(output).run { drawCircle(circleRadius, circleRadius, circleRadius, circlePaint) drawBitmap(this@getCircularBitmap, outputBounds, outputBounds, outputBitmapPaint) output } }
不知道这是一个编程问题,但…
最简单的解决scheme是在源位图中使外部区域透明。 否则,您将必须计算哪些像素在圆外,并相应地设置alpha(完全透明为alpha = 0)。