Respuestas:
Después de una larga lluvia de ideas, he encontrado 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;
}
static
y usarse en una clase de utilidad no instanciada de métodos estáticos similares.
canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2, bitmap.getWidth() / 2, paint);
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;
}
Puede hacer que su vista de imagen sea circular usando RoundedBitmapDrawable
aquí está el código para lograr una 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);
@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.
c.drawBitmap(b, 0, 0, null);
, que usa la transformación de identidad predeterminada.
Creo que esta solución funciona mejor con cualquier tipo de rectángulo, cambie el tamaño de píxel si desea 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;
}
Esto también se puede hacer fácilmente 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á el fragmento de código que utilicé:
<?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"/>
<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 imagen de salida:
Espero, ¡podría ser útil para alguien! :)
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;
}
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
}
}
Para las personas que quieren el centro del rectángulo (yo), agregue esto antes de cortar:
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()
);
}
}
Basado en la respuesta de [Jachumbelechao Unto Mantekilla], este código funciona como un encanto para las personas que buscan una solución 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
}
Ahora, 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;
}
Función de Kotin
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
}
llámalo por este código
holder.itemFriendImage.setImageBitmap(ImageConverter.getRoundedCornerBitmap(bitmap,600))
Creo que la solución más fácil es crear un BitmapShader de su Bitmap, pasarlo a su objeto de pintura y luego simplemente llamar a algo como canvas.drawCircle (cx, cy, radius, paint);
por ejemplo
Paint p = new Paint();
p.setShader(new BitmapShader(myBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
canvas.drawCircle(getWidth() / 2, getHeight() / 2, getHeight() / 2, p);
Así es como https://github.com/hdodenhof/CircleImageView también lo ha hecho, puedes leer el código fuente aquí: https://github.com/hdodenhof/CircleImageView/blob/master/circleimageview/src/main/java /de/hdodenhof/circleimageview/CircleImageView.java
**Jst Add this to your image Id and get the circuler image.**
imgUserProfile.setImageBitmap(getCircularCenterCropBitmap(bitmap, (int) (150 * denisty)));
Method:-
public void Bitmap getCircularCenterCropBitmap(Bitmap originalBmp, int diameter) {
Bitmap resizedBmp = BitmapUtils.getScaledCroppedBitmap(originalBmp, diameter, diameter);
return BitmapUtils.getRoundedCircularBitmap(resizedBmp, diameter / 2);
}
No estoy seguro de que sea una pregunta de programación, pero ...
La solución más sencilla sería hacer que el área exterior sea transparente en el mapa de bits de origen. De lo contrario, tendrá que calcular qué píxeles están fuera del círculo y configurar el alfa en consecuencia (alfa = 0 para una transparencia total).