Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rounded image view with no border #506

Closed
rahulr4 opened this issue Jan 10, 2014 · 6 comments
Closed

Rounded image view with no border #506

rahulr4 opened this issue Jan 10, 2014 · 6 comments
Labels

Comments

@rahulr4
Copy link

rahulr4 commented Jan 10, 2014

Hi, i successfully used your library which i must say is a great one.
I am using RoundedBitmapDisplayer class to give my image a radius . Is it possible to create a border around the image using your library ?

@bagusflyer
Copy link

You find a solution already?

@nostra13
Copy link
Owner

No, UIL doesn't provide this possibility.

@gian1200
Copy link

I made that implementation. @nostra13, it would be great if you agree to add this class, or at least tell me which changes should I need to make in order to get your approval.

This class can create a circle with (or without) a border with a solid color from an image.
By default, it use the center of the image as the center of the circle and create the biggest possible circle where "radius * 2 == min(width, height)" of the image, without a border.

package com.nostra13.universalimageloader.core.display;

import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.Log;

import com.nostra13.universalimageloader.core.assist.LoadedFrom;
import com.nostra13.universalimageloader.core.imageaware.ImageAware;
import com.nostra13.universalimageloader.core.imageaware.ImageViewAware;

public class CircleBitmapDisplayer implements BitmapDisplayer {
    private float radius, centerX, centerY, borderWidth = 0;
    private int borderColor = Color.BLACK;
    private boolean biggestCircle = false, isCentered = true;

    public CircleBitmapDisplayer() {
        this.biggestCircle = true;
    }

    public CircleBitmapDisplayer(float centerX, float centerY) {
        this();
        this.centerX = centerX;
        this.centerY = centerY;
        this.isCentered = false;
    }

    public CircleBitmapDisplayer(float borderWidth, int borderColor) {
        this();
        this.borderWidth = borderWidth;
        this.borderColor = borderColor;
    }

    public CircleBitmapDisplayer(float radius) {
        this.radius = radius;
    }

    public CircleBitmapDisplayer(float radius, float borderWidth,
            int borderColor) {
        this(radius);
        this.borderWidth = borderWidth;
        this.borderColor = borderColor;
    }

    public CircleBitmapDisplayer(float radius, float centerX, float centerY) {
        this(radius);
        this.centerX = centerX;
        this.centerY = centerY;
        this.isCentered = false;
    }

    public CircleBitmapDisplayer(float radius, float centerX, float centerY,
            float borderWidth, int borderColor) {
        this(radius, centerX, centerY);
        this.borderWidth = borderWidth;
        this.borderColor = borderColor;
    }

    @Override
    public void display(Bitmap bitmap, ImageAware imageAware,
            LoadedFrom loadedFrom) {
        if (!(imageAware instanceof ImageViewAware)) {
            throw new IllegalArgumentException(
                    "ImageAware should wrap ImageView. ImageViewAware is expected.");
        }
        int ivWidth = imageAware.getWidth();
        int ivHeight = imageAware.getHeight();
        int bmWidth = bitmap.getWidth();
        int bmHeight = bitmap.getHeight();

        if (isCentered) {
            centerX = (float) ivWidth / 2;
            centerY = (float) ivHeight / 2;
        }
        if (biggestCircle) {
            if (isCentered) {
                radius = ivWidth < ivHeight ? (float) ivWidth / 2
                        : (float) ivHeight / 2;
            } else {
                radius = Math.min(centerX < ivWidth - centerX ? centerX
                        : ivWidth - centerX,
                        centerY < ivHeight - centerY ? centerX : ivHeight
                                - centerY);
            }
        }
        Rect srcRect;
        if (bmWidth < bmHeight) {
            srcRect = new Rect(0, (bmHeight - bmWidth) / 2, bmWidth, bmWidth
                    + (bmHeight - bmWidth) / 2);
        } else {
            srcRect = new Rect((bmWidth - bmHeight) / 2, 0, bmHeight
                    + (bmWidth - bmHeight) / 2, bmHeight);
        }
        RectF destRectF = new RectF(0, 0, ivWidth, ivHeight);
        imageAware.setImageBitmap(getCircledBitmap(bitmap, centerX, centerY,
                radius, srcRect, destRectF, ivWidth, ivHeight, borderWidth,
                borderColor));

    }

    public static Bitmap getCircledBitmap(Bitmap bitmap, float centerX,
            float centerY, float radius, Rect srcRect, RectF destRectF,
            int width, int height, float borderWidth, int borderColor) {

        Bitmap output = Bitmap.createBitmap(width, height, Config.ARGB_8888);
        Canvas canvas = new Canvas(output);
        final Paint paint = new Paint();
        paint.setAntiAlias(true);

        // if 1 pixel is missing, do: radius - borderWidth + 1
        canvas.drawCircle(centerX, centerY, radius - borderWidth, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap, srcRect, destRectF, paint);
        if (0 < borderWidth) {
            paint.setXfermode(null);
            paint.setStyle(Style.STROKE);
            paint.setColor(borderColor);
            paint.setStrokeWidth(borderWidth);
            canvas.drawCircle(centerX, centerY, radius - borderWidth / 2, paint);
        }
        return output;
    }
}

@nostra13
Copy link
Owner

Why do you want this displayer to be included into the library?

@gian1200
Copy link

There are some developers (on Stackoverflow and inside the issue list - like @rahulr4 and @bagusflyer) who uses your library and want "Rounded images" (including myself). Some of them want a border too. Instead of reinventing the wheel, it would be great for us to have the implementation ready to just focus our minds in our apps.

I haven't test it, but I think your implementation of RoundedBitmapDisplayer should be able to make "rounded images" (circles). The 2 problems I see are that it doesn't support borders and drawCircle should perform better thansetRectToRect in this special case scenario.

@nostra13
Copy link
Owner

Ok, I got it, but the primary goal of UIL is loading and caching images. Different manipulations with Bitmap can be done externally and I don't want to make the lib more heavy by including different decorator-classes. I think decorator RoundedImageDisplayer is enough for UIL (maybe even it's redundant). Other features can be implemented externally.
Maybe if CircleBitmapDisplayer is highly polished and tested I will include it. But now I'm focused on core logic of library and have no time for testing and fixing auxiliary classes like CircleBitmapDisplayer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants