studio programacion para móviles libro edición desarrollo desarrollar curso aprende aplicaciones android android-layout user-interface graphics

programacion - Recortando el área circular de mapa de bits en Android



manual de programacion android pdf (15)

Tengo un mapa de bits y quiero recortar una región circular de este mapa de bits. Todos los píxeles fuera del círculo deben ser transparentes. ¿Cómo puedo hacer esto?


para generar Círculo de rectángulos

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 hizo un comentario sobre la respuesta anterior que sugería usar clipPath como una opción para recortar una imagen como un círculo.

La siguiente es una implementación limpia de esto:

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; }

Esto podría agregarse a una clase de utilidad.


Ahora, la respuesta correcta:

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; }


Aquí está la variante de Kotlin usando el método de extensión

/** * 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 } }


Creo que esta solución funciona mejor con cualquier tipo de rectángulo, cambie el tamaño del píxel si quiere una imagen pequeña o grande:

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; }


Después de una larga lluvia de ideas encontré la solución

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; }


Esto también se puede hacer en xml sin recortar el mapa de bits real. Solo necesita crear una máscara de imagen circular y colocarla sobre su imagen real. Aquí está la pieza de código que utilicé:

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 (Ignore "android: scaleType =" fitXY "" si no lo necesita)

<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>

Vista de la imagen de OutPut:

Espero que pueda ser útil para alguien. :)


Kotin Fucntion

fun getRoundedCornerBitmap(bitmap: Bitmap, pixels: Int): Bitmap { val output = Bitmap.createBitmap(bitmap.width, bitmap.height, Bitmap.Config.ARGB_8888) val canvas = Canvas(output) val color = -0xbdbdbe val paint = Paint() val rect = Rect(0, 0, bitmap.width, bitmap.height) val rectF = RectF(rect) val roundPx = pixels.toFloat() paint.isAntiAlias = true canvas.drawARGB(0, 0, 0, 0) paint.color = color canvas.drawRoundRect(rectF, roundPx, roundPx, paint) paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN) canvas.drawBitmap(bitmap, rect, rect, paint) return output }

llamarlo por este código

holder.itemFriendImage.setImageBitmap(ImageConverter.getRoundedCornerBitmap(bitmap,600))


No estoy seguro de que esto sea una pregunta de programación, pero ...

La solución más fácil sería hacer que el área exterior sea transparente en el mapa de bits de origen. De lo contrario, deberá calcular qué píxeles están fuera del círculo y establecer el alfa en consecuencia (alfa = 0 para una transparencia total).


Para gente que quiere el centro del rectángulo (yo), agregue esto antes del corte:

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 Crop Center of Bitmap


Puedes hacer circular tu vista de imagen usando RoundedBitmapDrawable

aquí está el código para lograr la vista de imagen redondeada:

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);


Recomiendo agregar bitmap.recycle() si ya no lo necesita, evitará el error de OutOfMemory.


Según la respuesta de [Jachumbelechao Unto Mantekilla], este código funciona como un amuleto para las personas que buscan una solución de Kotlin:

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 }


puedes usar este código, funcionará

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; }


puedes usar este código, funcionará

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; }