Cropping square image into circular image in andro

2020-07-30 03:23发布

问题:

I want a square image to be converted to circular image and displayed in the imageview. Image 1 is the required output, image two is the sqaure source image and image3 is the current output from the code pasted below. Code for cropping square image and than converting into circular image is pasted below. Please have a look at it and correct it.

private Bitmap cutCenterSquare(Bitmap bitmap) {

        Bitmap origialBitmap = bitmap;
        Bitmap cutBitmap = Bitmap.createBitmap(origialBitmap.getWidth() / 2,
                origialBitmap.getHeight() / 2, Config.ARGB_8888);
        Canvas canvas = new Canvas(cutBitmap);
        Rect desRect = new Rect(0,0,(int)(imageview.getWidth()*0.94-imageview.getWidth()*0.06),(int)(imageview.getHeight()*0.725-imageview.getHeight()*0.16));
        Rect srcRect = new Rect((int)(imageview.getWidth()*0.06),(int)(imageview.getHeight()*0.16),
                (int)(imageview.getWidth()*0.94),
                (int)(imageview.getHeight()*0.725));
        canvas.drawBitmap(origialBitmap, srcRect, desRect, null);
        return cutBitmap;
    }

public static Bitmap getCroppedBitmap(Bitmap bmp, int radius) {
        Bitmap sbmp;

        if(bmp.getWidth() != radius || bmp.getHeight() != radius)
            sbmp = Bitmap.createScaledBitmap(bmp, radius, radius, false);
        else
            sbmp = bmp;
        Bitmap output = Bitmap.createBitmap(sbmp.getWidth(), sbmp.getHeight(), Bitmap.Config.ARGB_8888);
        final Rect rect = new Rect(0, 0, sbmp.getWidth(), sbmp.getHeight());

        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setFilterBitmap(true);
        paint.setDither(true);      
        paint.setColor(Color.parseColor("#646464"));

        Canvas c = new Canvas(output);        
        c.drawARGB(0, 0, 0, 0);
        c.drawCircle(sbmp.getWidth() / 2+0.7f, sbmp.getHeight() / 2+0.7f, sbmp.getWidth() / 2+0.1f, paint);
        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        c.drawBitmap(sbmp, rect, rect, paint);
        return output;
    }


<ImageView
                android:id="@+id/profile_image"
                android:layout_width="300dp"
                android:layout_height="300dp"
                android:layout_alignParentTop="true"
                android:layout_centerHorizontal="true"
                android:layout_gravity="center"
                android:layout_marginBottom="8dp"
                android:layout_marginTop="24dp"
                android:background="@drawable/background_circle"
                android:contentDescription=""
                android:scaleType="centerCrop"/>

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">

   <solid 
       android:color="#646464"/>

   <size 
       android:width="1dp"
        android:height="1dp"/>
</shape>

回答1:

Pay attention to your code. You are using 2 bitmaps in memory.

There is a very interesting post about image with rounded corners: http://www.curious-creature.org/2012/12/11/android-recipe-1-image-with-rounded-corners/

It is written by Romain Guy (ex android team at Google).

You can write a circular bitmap with a similar code:

public class CircleDrawable extends Drawable {

    private final BitmapShader mBitmapShader;
    private final Paint mPaint;
    private Paint mWhitePaint;
    int circleCenterX;
    int circleCenterY;
    int mRadus;
    private boolean mUseStroke = false;
    private int mStrokePadding = 0;

    public CircleDrawable(Bitmap bitmap) {

        mBitmapShader = new BitmapShader(bitmap,
                Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setShader(mBitmapShader);

    }

    public CircleDrawable(Bitmap bitmap, boolean mUseStroke) {
        this(bitmap);

        if (mUseStroke) {
            this.mUseStroke = true;
            mStrokePadding = 4;
            mWhitePaint = new Paint();
            mWhitePaint.setStyle(Paint.Style.FILL_AND_STROKE);
            mWhitePaint.setStrokeWidth(0.75f);
            mWhitePaint.setColor(Color.WHITE);
        }
    }

    @Override
    protected void onBoundsChange(Rect bounds) {
        super.onBoundsChange(bounds);
        circleCenterX = bounds.width() / 2;
        circleCenterY = bounds.height() / 2;

        if (bounds.width() >= bounds.height())
            mRadus = bounds.width() / 2;
        else
            mRadus = bounds.height() / 2;
    }

    @Override
    public void draw(Canvas canvas) {
        if (mUseStroke) {
            canvas.drawCircle(circleCenterX, circleCenterY, mRadus, mWhitePaint);
        }
        canvas.drawCircle(circleCenterX, circleCenterY, mRadus - mStrokePadding, mPaint);
    }

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }

    @Override
    public void setAlpha(int alpha) {
        mPaint.setAlpha(alpha);
    }

    @Override
    public void setColorFilter(ColorFilter cf) {
        mPaint.setColorFilter(cf);
    }

    public boolean ismUseStroke() {
        return mUseStroke;
    }

    public void setmUseStroke(boolean mUseStroke) {
        this.mUseStroke = mUseStroke;
    }

}

To use it:

CircleDrawable circle = new CircleDrawable(bitmap,true);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
  imageView.setBackground(circle);
         else
   imageView.setBackgroundDrawable(circle);


回答2:

You can take a look into this project in github. It provides a way to set an image in XML and programmatically, and displays a resizable circular crop window on top of the image. Calling the method getCroppedCircleImage() will then return the Circle Bitmap marked by the circular crop window. Maybe this could come in handy. CIrcleImageCropper

  • Sathya