-1

I am trying to load an image in CircularImageView but it is giving me outOfMemory error. I am using following code for CircularImageView:

CircularImageView.java

    public class CircularImageView extends ImageView {

    public CircularImageView(Context ctx, AttributeSet attrs) {
        super(ctx, attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {

        Drawable drawable = getDrawable();

        if (drawable == null) {
            return;
        }

        if (getWidth() == 0 || getHeight() == 0) {
            return;
        }
        Bitmap b = ((BitmapDrawable) drawable).getBitmap();
        Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);

        int w = getWidth(), h = getHeight();

        Bitmap roundBitmap = getRoundedCroppedBitmap(bitmap, w);
        canvas.drawBitmap(roundBitmap, 0, 0, null);

    }

    public static Bitmap getRoundedCroppedBitmap(Bitmap bitmap, int radius) {
        Bitmap
                finalBitmap;
        if (bitmap.getWidth() != radius || bitmap.getHeight() != radius)
            finalBitmap = Bitmap.createScaledBitmap(bitmap, radius, radius,
                    false);
        else
            finalBitmap = bitmap;
        Bitmap output = Bitmap.createBitmap(finalBitmap.getWidth(),
                finalBitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, finalBitmap.getWidth(),
                finalBitmap.getHeight());

        paint.setAntiAlias(true);
        paint.setFilterBitmap(true);
        paint.setDither(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(Color.parseColor("#BAB399"));
        canvas.drawCircle(finalBitmap.getWidth() / 2 + 0.7f,
                finalBitmap.getHeight() / 2 + 0.7f,
                finalBitmap.getWidth() / 2 + 0.1f, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(finalBitmap, rect, rect, paint);

        return output;
    }

}

I using it in the design as given below:

 <com.almabay.almachat.circularImageView.CircularImageView
    android:id="@+id/img_group"
    android:layout_width="80dp"
    android:layout_height="80dp"
    android:layout_alignParentLeft="true" />

I am getting image from server and trying to display it in the list view using Adapter.Following code is being used here:

Picasso.with(context).load(image_url).error(R.drawable.default_avatar).into(viewHolder.imgGroup);

Here image_url is the URL of the image to be loaded in circular image view.ViewHolder.imgGroup is the circularImageView.

Please help me to fix the issue.

Deepak Rattan
  • 1,279
  • 7
  • 21
  • 47
  • Possible duplicate of [Strange out of memory issue while loading an image to a Bitmap object](http://stackoverflow.com/questions/477572/strange-out-of-memory-issue-while-loading-an-image-to-a-bitmap-object) – Vivek Mishra Apr 14 '16 at 07:49
  • Try some other image.. Which is small in size.. If it is still pertaining then will require to check `CircularImageView` – Jimit Patel Apr 14 '16 at 07:53

2 Answers2

2

I see you are using Picasso for image loading why not use picasso image transformations. it's very simple to implement :-

ImageView im = (ImageView) findViewById(R.id.img1);

    Picasso.with(MainActivity2.this).load(R.drawable.kitten)
            .transform(new CropCircleTransformation()).into(im);

and it looks like this

enter image description here

You just need to add transformation class

import com.squareup.picasso.Transformation;

import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;

public class CropCircleTransformation implements Transformation {

  @Override public Bitmap transform(Bitmap source) {
    int size = Math.min(source.getWidth(), source.getHeight());

    int width = (source.getWidth() - size) / 2;
    int height = (source.getHeight() - size) / 2;

    Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);

    Canvas canvas = new Canvas(bitmap);
    Paint paint = new Paint();
    BitmapShader shader =
        new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
    if (width != 0 || height != 0) {
      // source isn't square, move viewport to center
      Matrix matrix = new Matrix();
      matrix.setTranslate(-width, -height);
      shader.setLocalMatrix(matrix);
    }
    paint.setShader(shader);
    paint.setAntiAlias(true);

    float r = size / 2f;
    canvas.drawCircle(r, r, r, paint);

    source.recycle();

    return bitmap;
  }

  @Override public String key() {
    return "CropCircleTransformation()";
  }
}

More transformations can we find here https://github.com/wasabeef/picasso-transformations

Hitesh Sahu
  • 41,955
  • 17
  • 205
  • 154
  • Please check the code of CircularImageView.java . This line is Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true); is giving me exception. – Deepak Rattan Apr 14 '16 at 11:39
  • Please use this transformation class https://github.com/wasabeef/picasso-transformations/blob/master/transformations/src/main/java/jp/wasabeef/picasso/transformations/CropCircleTransformation.java – Hitesh Sahu Apr 16 '16 at 11:08
1

Normally I'd tell you that the error could be anywhere and you're probably leaking. But you're making 2 new bitmaps in onDraw? And all 3 are in memory? Not only is that hideously wasteful, but your performance will suck- you should even avoid using new in onDraw, much less allocating bitmaps.

Throw this out and rewrite it completely. You should avoid working on a drawable here (especially since you're assuming its a bitmap anyway which is a bad idea), you should take in a filename or resource id of the bitmap and read it in/scale it with 1 createBitmap command by using BitmapOptions. You should do this when the bitmap is set and save the result, do NOT scale in onDraw which is called all the time. You can avoid the 3rd bitmap by using a circular clipping path instead of using porter duff modes and a second canvas. You can do all this with just 1 bitmap, and should.

Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127