Resize image from camera to fit Imageview - android

I have an Cirle imageview. I am setting the image to the ImageView from the camera and gallery. The problem is that when I set the image from the camera, the image looks too streched inside the circle image view.
Iam Resizing the image in order to avoid any memory leaks.
here is what i do:
CircleImageView.cs
public class CircleImageView : ImageView
{
private int borderWidth;
private int canvasSize;
private Bitmap image;
private Paint paint;
private Paint paintBorder;
public CircleImageView(Context context)
: this(context, null)
{
}
public CircleImageView(Context context, IAttributeSet attrs)
: this(context, attrs, Resource.Attribute.circularImageViewStyle)
{
}
public CircleImageView(Context context, IAttributeSet attrs, int defStyle)
: base(context, attrs, defStyle)
{
// init paint
paint = new Paint();
paint.AntiAlias = true;
paintBorder = new Paint();
paintBorder.AntiAlias = true;
// load the styled attributes and set their properties
TypedArray attributes = context.ObtainStyledAttributes(attrs, Resource.Styleable.CircularImageView, defStyle, 0);
if (attributes.GetBoolean(Resource.Styleable.CircularImageView_border, true))
{
int defaultBorderSize = (int)(4 * context.Resources.DisplayMetrics.Density+ 0.5f);
BorderWidth = attributes.GetDimensionPixelOffset(Resource.Styleable.CircularImageView_border_width, defaultBorderSize);
BorderColor = attributes.GetColor(Resource.Styleable.CircularImageView_border_color, Color.White);
}
if (attributes.GetBoolean(Resource.Styleable.CircularImageView_shadow, false))
{
addShadow();
}
}
public void addShadow()
{
SetLayerType(LayerType.Software, paintBorder);
paintBorder.SetShadowLayer(4.0f, 2.0f, 2.0f, Color.ParseColor("#82C341"));
}
public virtual int BorderWidth
{
set
{
this.borderWidth = 10;
this.RequestLayout();
this.Invalidate();
}
}
public virtual int BorderColor
{
set
{
if (paintBorder != null)
{
paintBorder.Color = Color.Gray;
}
this.Invalidate();
}
}
protected override void OnDraw(Canvas canvas)
{
// load the bitmap
image = drawableToBitmap(Drawable);
// init shader
if (image != null)
{
canvasSize = canvas.Width;
if (canvas.Height < canvasSize)
{
canvasSize = canvas.Height;
}
BitmapShader shader = new BitmapShader(Bitmap.CreateScaledBitmap(image, canvasSize, canvasSize, false), Shader.TileMode.Clamp, Shader.TileMode.Clamp);
paint.SetShader(shader);
// circleCenter is the x or y of the view's center
// radius is the radius in pixels of the cirle to be drawn
// paint contains the shader that will texture the shape
int circleCenter = (canvasSize - (borderWidth * 2)) / 2;
canvas.DrawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) + borderWidth - 4.0f, paintBorder);
canvas.DrawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) - 4.0f, paint);
}
}
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int width = measureWidth(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec);
SetMeasuredDimension(width, height);
}
private int measureWidth(int measureSpec)
{
int result = 0;
var specMode = MeasureSpec.GetMode(measureSpec);
var specSize = MeasureSpec.GetSize(measureSpec);
if (specMode == MeasureSpecMode.Exactly)
{
// The parent has determined an exact size for the child.
result = specSize;
}
else if (specMode == MeasureSpecMode.AtMost)
{
// The child can be as large as it wants up to the specified size.
result = specSize;
}
else
{
// The parent has not imposed any constraint on the child.
result = canvasSize;
}
return result;
}
private int measureHeight(int measureSpecHeight)
{
int result = 0;
var specMode = MeasureSpec.GetMode(measureSpecHeight);
int specSize = MeasureSpec.GetSize(measureSpecHeight);
if (specMode == MeasureSpecMode.Exactly)
{
// We were told how big to be
result = specSize;
}
else if (specMode == MeasureSpecMode.AtMost)
{
// The child can be as large as it wants up to the specified size.
result = specSize;
}
else
{
// Measure the text (beware: ascent is a negative number)
result = canvasSize;
}
return (result + 2);
}
public virtual Bitmap drawableToBitmap(Drawable drawable)
{
if (drawable == null)
{
return null;
}
else if (drawable is BitmapDrawable)
{
return ((BitmapDrawable)drawable).Bitmap;
}
Bitmap bitmap = Bitmap.CreateBitmap(drawable.IntrinsicWidth, drawable.IntrinsicHeight, Bitmap.Config.Argb8888);
Canvas canvas = new Canvas(bitmap);
drawable.SetBounds(0, 0, canvas.Width, canvas.Height);
drawable.Draw(canvas);
return bitmap;
}
}
BitmapHelper.cs
public static Bitmap LoadAndResizeBitmap(this string fileName, int width, int height)
{
// First we get the the dimensions of the file on disk
BitmapFactory.Options options = new BitmapFactory.Options { InJustDecodeBounds = true };
BitmapFactory.DecodeFile(fileName, options);
// Next we calculate the ratio that we need to resize the image by
// in order to fit the requested dimensions.
int outHeight = options.OutHeight;
int outWidth = options.OutWidth;
int inSampleSize = 1;
if (outHeight > height || outWidth > width)
{
inSampleSize = outWidth > outHeight
? outHeight / height
: outWidth / width;
}
// Now we will load the image and have BitmapFactory resize it for us.
options.InSampleSize = inSampleSize;
options.InJustDecodeBounds = false;
Bitmap resizedBitmap = BitmapFactory.DecodeFile(fileName, options);
return resizedBitmap;
}
mylayout.xml
<Utilities.CircleImageView
android:layout_width="180dp"
android:layout_height="180dp"
android:id="#+id/imgProfileCircleImage"
android:src="#drawable/rapidicon"
custom:border="true"
custom:border_color="#d5d5d5"
custom:border_width="4dp"
custom:shadow="true"
android:layout_gravity="center"
android:minHeight="80dp"
android:minWidth="80dp" />
MainActivity
int imgheight = Resources.DisplayMetrics.HeightPixels;
int circleImgWidth = imgProfileCircleImage.Height;
AppHelper._bitmap = AppHelper._file.Path.LoadAndResizeBitmap(circleImgWidth, imgheight);
How do I set the image so that it looks perfectly fit to the imageview?

Try using Picasso or Glide to solve this issue easily
http://square.github.io/picasso/

Related

Wrong XY when drawing CircularImage

I'm writing a custom Circular ImageView in Android. I need to set a Drawable overlay on top of it, so I chose to write a custom CircularImageView that holds the picture itself + the drawable.
Actually I have 2 problems:
The image is drawn top-left, I need it to be drawn on the center of the View
I need my crown to be bigger (drawable) but I don't know how to resize it.
Some imgs to clarify:
What I'd like to achieve:
What I have now:(please, disconsider the black frame border, it's just to clarify the wrong image "gravity")
My view code:
public class CrownCircularImageView extends ImageView {
private Drawable crown;
private int canvasSize;
private int crownWidth;
private int crownHeight;
// Object used to draw
private Bitmap image;
private Drawable drawable;
private Paint paint;
private Paint crownPaint;
public CrownCircularImageView(Context context) {
this(context, null, 0);
}
public CrownCircularImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CrownCircularImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
}
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
crownPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
this.crown = ContextCompat.getDrawable(context, R.drawable.ic_crown);
}
private void loadBitmap() {
if (this.drawable == getDrawable())
return;
this.drawable = getDrawable();
this.image = drawableToBitmap(this.drawable);
updateShader();
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
canvasSize = w - crownWidth;
if (h < canvasSize)
canvasSize = h - crownHeight;
if (image != null)
updateShader();
}
private void updateShader() {
if (image == null)
return;
// Crop Center Image
image = cropBitmap(image);
// Create Shader
BitmapShader shader = new BitmapShader(image, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
// Center Image in Shader
Matrix matrix = new Matrix();
matrix.setScale((float) canvasSize / (float) image.getWidth(), (float) canvasSize / (float) image.getHeight());
shader.setLocalMatrix(matrix);
// Set Shader in Paint
paint.setShader(shader);
}
private Bitmap cropBitmap(Bitmap bitmap) {
Bitmap bmp;
if (bitmap.getWidth() >= bitmap.getHeight()) {
bmp = Bitmap.createBitmap(
bitmap,
bitmap.getWidth() / 2 - bitmap.getHeight() / 2,
0,
bitmap.getHeight(),
bitmap.getHeight());
} else {
bmp = Bitmap.createBitmap(
bitmap,
0,
bitmap.getHeight() / 2 - bitmap.getWidth() / 2,
bitmap.getWidth(),
bitmap.getWidth());
}
return bmp;
}
private Bitmap drawableToBitmap(Drawable drawable) {
if (drawable == null) {
return null;
} else if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
int intrinsicWidth = drawable.getIntrinsicWidth();
int intrinsicHeight = drawable.getIntrinsicHeight();
if (!(intrinsicWidth > 0 && intrinsicHeight > 0))
return null;
try {
// Create Bitmap object out of the drawable
Bitmap bitmap = Bitmap.createBitmap(intrinsicWidth, intrinsicHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
} catch (OutOfMemoryError e) {
// Simply return null of failed bitmap creations
Log.e(getClass().toString(), "Encountered OutOfMemoryError while generating bitmap!");
return null;
}
}
#Override
public void onDraw(Canvas canvas) {
// Load the bitmap
loadBitmap();
// Check if image isn't null
if (image == null)
return;
if (!isInEditMode()) {
canvasSize = canvas.getWidth();
if (canvas.getHeight() < canvasSize) {
canvasSize = canvas.getHeight();
}
}
int circleCenter = (canvasSize - crownHeight) / 2;
int cx = (canvasSize - crownWidth) / 2;
int cy = (canvasSize - crownHeight) / 2;
Bitmap crownBmp = drawableToBitmap(crown);
int crownX = cx;
int crownY = cy;
canvas.drawCircle(cx, cy, circleCenter, paint);
canvas.drawBitmap(crownBmp, crownX, crownY, crownPaint);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = measureWidth(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec);
crownWidth = crown.getIntrinsicWidth();
crownHeight = crown.getIntrinsicHeight();
setMeasuredDimension(width, height);
}
#Override
public ScaleType getScaleType() {
return ScaleType.CENTER_CROP;
}
private int measureWidth(int measureSpec) {
int result;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// The parent has determined an exact size for the child.
result = specSize;
} else if (specMode == MeasureSpec.AT_MOST) {
// The child can be as large as it wants up to the specified size.
result = specSize;
} else {
// The parent has not imposed any constraint on the child.
result = canvasSize;
}
return result + crown.getIntrinsicWidth();
}
private int measureHeight(int measureSpecHeight) {
int result;
int specMode = MeasureSpec.getMode(measureSpecHeight);
int specSize = MeasureSpec.getSize(measureSpecHeight);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else if (specMode == MeasureSpec.AT_MOST) {
// The child can be as large as it wants up to the specified size.
result = specSize;
} else {
// Measure the text (beware: ascent is a negative number)
result = canvasSize;
}
return (result + 2 + crown.getIntrinsicHeight());
}
}
You can create a new bitmap to draw the old one on a transparent background with a circle mask, and then draw the crown on it. This example also allows to add a padding around the image.
You will want to tweak the values of CIRCLE_PADDING and RESIZE_CROWN_FACTOR to fulfill your needs.
public class CrownImageView extends ImageView {
private static final int CIRCLE_PADDING = 25;
private static final float RESIZE_CROWN_FACTOR = 1.5f;
private Bitmap rounded;
private Bitmap resizedCrown;
public CrownImageView(final Context context) {
super(context);
}
public CrownImageView(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
public CrownImageView(final Context context, final AttributeSet attrs, final int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (drawable == null || getWidth() == 0 || getHeight() == 0) {
return;
}
if (resizedCrown == null) {
loadCrown();
}
loadImage(drawable);
canvas.drawBitmap(rounded, 0, 0, null);
canvas.drawBitmap(resizedCrown, canvas.getWidth() - resizedCrown.getWidth(), 0, null);
}
private void loadImage(Drawable drawable) {
Bitmap bmp = bitmapFromDrawable(drawable);
final Rect rect = new Rect(0, 0, bmp.getWidth(), bmp.getHeight());
final Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
rounded = Bitmap.createBitmap(bmp.getWidth(),
bmp.getHeight(), Bitmap.Config.ARGB_8888);
Canvas newCanvas = new Canvas(rounded);
newCanvas.drawARGB(0, 0, 0, 0);
float centerX = getWidth() / 2;
float centerY = getHeight() / 2;
float radius = Math.min(getWidth(), getHeight()) / 2 - CIRCLE_PADDING;
newCanvas.drawCircle(centerX, centerY, radius, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
newCanvas.drawBitmap(bmp, rect, rect, paint);
}
private void loadCrown() {
Bitmap crown = BitmapFactory.decodeResource(getResources(), R.drawable.crown);
resizedCrown = Bitmap.createScaledBitmap(crown,
(int) (crown.getWidth() * RESIZE_CROWN_FACTOR),
(int) (crown.getHeight() * RESIZE_CROWN_FACTOR),
true);
}
private Bitmap bitmapFromDrawable(Drawable drawable) {
Bitmap bmp;
if (drawable instanceof BitmapDrawable) {
bmp = ((BitmapDrawable) drawable).getBitmap();
} else {
bmp = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas bmpCanvas = new Canvas(bmp);
drawable.setBounds(0, 0, bmpCanvas.getWidth(), bmpCanvas.getHeight());
drawable.draw(bmpCanvas);
}
return bmp;
}
}
Update: You can use it with Glide like this
final CrownImageView imageView = (CrownImageView) findViewById(R.id.fragment_kids_row_img_kids);
Glide.with(this).load(yourimageurl).into(imageView);
The image is drawn top-left, I need it to be drawn on the center of the View
Yes, that is because of parameters to .drawCircle
canvas.drawCircle(cx, cy, circleCenter, paint);
You are not calculating them for your image. This should be something like
int centerX = getWidth() / 2;
int centerY = getHeight() / 2;
float bitmapRadius = Math.min(image.getWidth(), image.getHeight()) / 2f;
canvas.drawCircle(centerX, centerY, bitmapRadius, paint);
But I think it is better to save this values and recalculate them when size changes.
I need my crown to be bigger (drawable) but I don't know how to resize it.
You specify size of bitmap yourself - make it a bit bigger by specifying another size.
Bitmap bitmap = Bitmap.createBitmap(
intrinsicWidth + scale,
intrinsicHeight + scale,
Bitmap.Config.ARGB_8888);
I've modified your code: http://pastebin.com/0h02Tqh1

Out of memory exception occurred at Bitmap Shadder android

I am working on android application in which i am using Bitmap, but the problem is that sometimes it shows me an error of out of memory and my application get crashed. I am using bitmaps along with BitmapShadder, my code is given below where my application shows this error.
public class CircularImageView extends ImageView {
private int borderWidth = 0;
private int viewWidth;
private int viewHeight;
private Bitmap image;
private Paint paint;
private Paint paintBorder;
private BitmapShader shader;
public CircularImageView(Context context) {
super(context);
setup();
}
public CircularImageView(Context context, AttributeSet attrs) {
super(context, attrs);
setup();
}
public CircularImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setup();
}
private void setup() {
// init paint
paint = new Paint();
paint.setAntiAlias(true);
paintBorder = new Paint();
setBorderColor(Color.WHITE);
paintBorder.setAntiAlias(true);
this.setLayerType(LAYER_TYPE_SOFTWARE, paintBorder);
// paintBorder.setShadowLayer(4.0f, 0.0f, 2.0f, Color.BLACK);
}
public void setBorderWidth(int borderWidth) {
this.borderWidth = borderWidth;
this.invalidate();
}
public void setBorderColor(int borderColor) {
if (paintBorder != null)
paintBorder.setColor(borderColor);
this.invalidate();
}
private void loadBitmap() {
BitmapDrawable bitmapDrawable = (BitmapDrawable) this.getDrawable();
if (bitmapDrawable != null)
image = bitmapDrawable.getBitmap();
}
// #SuppressLint("DrawAllocation")
#Override
public void onDraw(Canvas canvas) {
// load the bitmap
loadBitmap();
// init shader
if (image != null) {
// Out Of Memory Error Comes Here....
shader = new BitmapShader(Bitmap.createScaledBitmap(image,canvas.getWidth(), canvas.getHeight(), false),Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint.setShader(shader);
int circleCenter = viewWidth / 2;
// circleCenter is the x or y of the view's center
// radius is the radius in pixels of the cirle to be drawn
// paint contains the shader that will texture the shape
canvas.drawCircle(circleCenter + borderWidth, circleCenter
+ borderWidth, circleCenter + borderWidth - 4.0f,
paintBorder);
canvas.drawCircle(circleCenter + borderWidth, circleCenter
+ borderWidth, circleCenter - 4.0f, paint);
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = measureWidth(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec, widthMeasureSpec);
viewWidth = width - (borderWidth * 2);
viewHeight = height - (borderWidth * 2);
setMeasuredDimension(width, height);
}
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text
result = viewWidth;
}
return result;
}
private int measureHeight(int measureSpecHeight, int measureSpecWidth) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpecHeight);
int specSize = MeasureSpec.getSize(measureSpecHeight);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text (beware: ascent is a negative number)
result = viewHeight;
}
return (result + 2);
}
}
Try this in your manifest application tag.
android:largeHeap="true"

How to use CircleImageView with Volley's NetworkImageView?

I need to get circle images from rectangular/square images taken from network. In my application I get images with Volley's NetworkImageView. I found that fantastic library https://github.com/hdodenhof/CircleImageView but I don't understand how I can use it with NetworkImageView.
Can someone help me?
Check this Class
public class CirculaireNetworkImageView extends NetworkImageView {
private int borderWidth;
private int canvasSize;
private Bitmap image;
private Paint paint;
private Paint paintBorder;
public CirculaireNetworkImageView(final Context context) {
this(context, null);
}
public CirculaireNetworkImageView(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.actionButtonStyle);
}
public CirculaireNetworkImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
paint = new Paint();
paint.setAntiAlias(true);
paintBorder = new Paint();
paintBorder.setAntiAlias(true);
}
public void setBorderWidth(int borderWidth) {
this.borderWidth = borderWidth;
this.requestLayout();
this.invalidate();
}
public void setBorderColor(int borderColor) {
if (paintBorder != null)
paintBorder.setColor(borderColor);
this.invalidate();
}
public void addShadow() {
setLayerType(LAYER_TYPE_SOFTWARE, paintBorder);
paintBorder.setShadowLayer(4.0f, 0.0f, 2.0f, Color.BLACK);
}
#SuppressLint("DrawAllocation")
#Override
public void onDraw(Canvas canvas) {
// load the bitmap
image = drawableToBitmap(getDrawable());
// init shader
if (image != null) {
canvasSize = canvas.getWidth();
if(canvas.getHeight()<canvasSize)
canvasSize = canvas.getHeight();
BitmapShader shader = new BitmapShader(Bitmap.createScaledBitmap(image, canvasSize, canvasSize, false), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint.setShader(shader);
// circleCenter is the x or y of the view's center
// radius is the radius in pixels of the cirle to be drawn
// paint contains the shader that will texture the shape
int circleCenter = (canvasSize - (borderWidth * 2)) / 2;
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) + borderWidth - 4.0f, paintBorder);
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) - 4.0f, paint);
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = measureWidth(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec);
setMeasuredDimension(width, height);
}
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// The parent has determined an exact size for the child.
result = specSize;
} else if (specMode == MeasureSpec.AT_MOST) {
// The child can be as large as it wants up to the specified size.
result = specSize;
} else {
// The parent has not imposed any constraint on the child.
result = canvasSize;
}
return result;
}
private int measureHeight(int measureSpecHeight) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpecHeight);
int specSize = MeasureSpec.getSize(measureSpecHeight);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else if (specMode == MeasureSpec.AT_MOST) {
// The child can be as large as it wants up to the specified size.
result = specSize;
} else {
// Measure the text (beware: ascent is a negative number)
result = canvasSize;
}
return (result + 2);
}
public Bitmap drawableToBitmap(Drawable drawable) {
if (drawable == null) {
return null;
} else if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
}
Check the source code of the NetworkImageView here. Modify it to extend your "CircleImageView" instead of the normal ImageView and you are done.

CircularImageView stretching picture in API 10

I am using circularimageView to display the picture of a person. Here's the class.
public class CircularImageView extends ImageView {
private int borderWidth = 4;
private int viewWidth;
private int viewHeight;
private Bitmap image;
private Paint paint;
private Paint paintBorder;
private BitmapShader shader;
public CircularImageView(Context context) {
super(context);
setup();
}
public CircularImageView(Context context, AttributeSet attrs) {
super(context, attrs);
setup();
}
public CircularImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setup();
}
private void setup() {
// init paint
paint = new Paint();
paintBorder = new Paint();
paint.setAntiAlias(true);
setBorderColor(Color.WHITE);
paintBorder.setAntiAlias(true);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
this.setLayerType(LAYER_TYPE_SOFTWARE, paintBorder);
}
else
{
}
paintBorder.setShadowLayer(4.0f, 0.0f, 2.0f, Color.BLACK);
}
public void setBorderWidth(int borderWidth) {
this.borderWidth = borderWidth;
this.invalidate();
}
public void setBorderColor(int borderColor) {
if (paintBorder != null)
paintBorder.setColor(borderColor);
this.invalidate();
}
private void loadBitmap() {
BitmapDrawable bitmapDrawable = (BitmapDrawable) this.getDrawable();
if (bitmapDrawable != null)
image = bitmapDrawable.getBitmap();
}
#SuppressLint("DrawAllocation")
#Override
public void onDraw(Canvas canvas) {
// load the bitmap
loadBitmap();
// init shader
if (image != null) {
shader = new BitmapShader(Bitmap.createScaledBitmap(image, canvas.getWidth(), canvas.getHeight(), false), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint.setShader(shader);
int circleCenter = viewWidth / 2;
// circleCenter is the x or y of the view's center
// radius is the radius in pixels of the cirle to be drawn
// paint contains the shader that will texture the shape
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, circleCenter + borderWidth - 4.0f, paintBorder);
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, circleCenter - 4.0f, paint);
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = measureWidth(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec, widthMeasureSpec);
viewWidth = width - (borderWidth * 2);
viewHeight = height - (borderWidth * 2);
setMeasuredDimension(width, height);
}
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text
result = viewWidth;
}
return result;
}
private int measureHeight(int measureSpecHeight, int measureSpecWidth) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpecHeight);
int specSize = MeasureSpec.getSize(measureSpecHeight);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text (beware: ascent is a negative number)
result = viewHeight;
}
return (result + 2);
}
}
It works fine in anything > API 10 but in other cases the image gets stretched out and only the top left part of the image is visible and is pixelated. I tried Resizing the bitmap of the picture but it did not help.
Here is the bitmap initialization
PackageManager m = getActivity().getPackageManager();
String s = getActivity().getPackageName();
PackageInfo p = null;
try {
p = m.getPackageInfo(s, 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
s = p.applicationInfo.dataDir;
//String root = Environment.getExternalStorageDirectory().toString();
s += "/player_photos/" + player.getPlayerId() + ".png";
Bitmap bMap = BitmapFactory.decodeFile(s);
Resources res = getResources();
BitmapDrawable icon = new BitmapDrawable(res, bMap);
playerDP.setImageDrawable(icon);
}

Android - Display Image Crop Center

I want to know an Image inside a Circle Mask as follows.
The user usually selected the image from the gallery or shoots one using the camera. Considering that the image is either Landscape or Portrait and not square. is there a way to display a center cropped image after choosing the image?
<com.mikhaellopez.circularimageview.CircularImageView
android:id="#+id/ivCreateCompanyImage"
android:layout_width="#dimen/big_logo_width_height"
android:layout_height="#dimen/big_logo_width_height"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="#dimen/ten_dp"
android:layout_marginTop="#dimen/thirty_dp"
android:src="#drawable/add_image"
android:scaleType="centerCrop"
android:background="#drawable/logo_button_selector"
app:border_color="#color/transparent"
app:border_width="5"
app:shadow="false" />
Java code
public void onActivityResult(int requestCode, int resultCode,
Intent data)
{
if(resultCode != RESULT_OK)
return;
else if (requestCode == SELECT_FILE)
{
// this gives the Uri of the selected image
Uri selectedImageUri = data.getData();
try {
InputStream stream = getActivity().getContentResolver().openInputStream(selectedImageUri);
byte[] bytes = getBytes(stream);
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
int height_width = (int) getResources().getDimension(R.dimen.big_logo_width_height);
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap,height_width,height_width,true);
ivCreateCompanyImage.setImageBitmap(scaledBitmap);
}
catch(Exception ex)
{
}
//ivCreateCompanyImage.setImageURI(selectedImageUri);
}
else if( requestCode == CAPTURE_FROM_CAMERA)
{
File f = new File(Environment.getExternalStorageDirectory().toString());
for (File temp : f.listFiles())
{
if (temp.getName().equals("temp.jpg"))
{
f = temp;
ivCreateCompanyImage.setImageURI(Uri.fromFile(f));
break;
}
}
}
super.onActivityResult(requestCode, resultCode, data);
}
You can do this very simply (I've done this exact thing and its live on millions of devices right now) using Picasso and a Circular Image Transformation.
Here's a gist of the exact code I use in production.
This code is working for me
<com.abc.commons.helper.CircularImageView
android:id="#+id/capture_pic"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center"
android:background="#drawable/payer_profile_image"
android:scaleType="centerCrop"
app:shadow="true" />
Create seperate java class name as CircularImageView.java and paste the entire below code
and just give the reference of this class in your xml imgevoew tag and after that it will take care everything automatically
package com.xyz.commons.helper;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;
/**
* This class is used to set style of image
* means this class will help to set the image in circular form
* #author santoshk
*
*/
#SuppressLint("DrawAllocation")
public class CircularImageView extends ImageView {
private int borderWidth;
private int canvasSize;
private Bitmap image;
private Paint paint;
private Paint paintBorder;
public CircularImageView(final Context context) {
this(context, null);
}
public CircularImageView(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.circularImageViewStyle);
}
#SuppressLint("Recycle")
public CircularImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// init paint
paint = new Paint();
paint.setAntiAlias(true);
paintBorder = new Paint();
paintBorder.setAntiAlias(true);
// load the styled attributes and set their properties
TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.CircularImageView, defStyle, 0);
if(attributes.getBoolean(R.styleable.CircularImageView_border, true)) {
int defaultBorderSize = (int) (4 * getContext().getResources().getDisplayMetrics().density + 0.5f);
setBorderWidth(attributes.getDimensionPixelOffset(R.styleable.CircularImageView_border_width, defaultBorderSize));
setBorderColor(attributes.getColor(R.styleable.CircularImageView_border_color, Color.WHITE));
}
if(attributes.getBoolean(R.styleable.CircularImageView_shadow, false))
addShadow();
}
/**
* This method is used to set the width of border
* #param borderWidth
*/
public void setBorderWidth(int borderWidth) {
this.borderWidth = borderWidth;
this.requestLayout();
this.invalidate();
}
/**
* This method is used to set the color of border
* #param borderColor
*/
public void setBorderColor(int borderColor) {
if (paintBorder != null)
paintBorder.setColor(borderColor);
this.invalidate();
}
/**
* This method is used to set the shadow
*/
public void addShadow() {
setLayerType(LAYER_TYPE_SOFTWARE, paintBorder);
paintBorder.setShadowLayer(4.0f, 0.0f, 2.0f, Color.BLACK);
}
#SuppressLint("DrawAllocation")
#Override
public void onDraw(Canvas canvas) {
// load the bitmap
image = drawableToBitmap(getDrawable());
// init shader
if (image != null) {
canvasSize = canvas.getWidth();
if(canvas.getHeight()<canvasSize)
canvasSize = canvas.getHeight();
BitmapShader shader = new BitmapShader(Bitmap.createScaledBitmap(image, canvasSize, canvasSize, false), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint.setShader(shader);
// circleCenter is the x or y of the view's center
// radius is the radius in pixels of the cirle to be drawn
// paint contains the shader that will texture the shape
int circleCenter = (canvasSize - (borderWidth * 2)) / 2;
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) + borderWidth - 4.0f, paintBorder);
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) - 4.0f, paint);
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = measureWidth(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec);
setMeasuredDimension(width, height);
}
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// The parent has determined an exact size for the child.
result = specSize;
} else if (specMode == MeasureSpec.AT_MOST) {
// The child can be as large as it wants up to the specified size.
result = specSize;
} else {
// The parent has not imposed any constraint on the child.
result = canvasSize;
}
return result;
}
private int measureHeight(int measureSpecHeight) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpecHeight);
int specSize = MeasureSpec.getSize(measureSpecHeight);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else if (specMode == MeasureSpec.AT_MOST) {
result = specSize;
} else {
result = canvasSize;
}
return (result + 2);
}
public Bitmap drawableToBitmap(Drawable drawable) {
if (drawable == null) {
return null;
} else if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
}

Categories

Resources