How to center a vector in an image? - java

I have the following code:
public class LetterGenerator {
private static final int NUM_OF_TILE_COLORS = 8;
private final TextPaint mPaint = new TextPaint();
private final Rect mBounds = new Rect();
private final Canvas mCanvas = new Canvas();
private final char[] mFirstChar = new char[1];
private final TypedArray mColors;
private final int mTileLetterFontSize;
private final Bitmap mDefaultBitmap;
private final int mWidth;
private final int mHeight;
public LetterGenerator(Context context) {
final Resources res = context.getResources();
mPaint.setTypeface(Typeface.create("sans-serif-light", Typeface.NORMAL));
mPaint.setColor(Color.WHITE);
mPaint.setTextAlign(Paint.Align.CENTER);
mPaint.setAntiAlias(true);
mColors = res.obtainTypedArray(R.array.avatar_colors);
mTileLetterFontSize = res.getDimensionPixelSize(R.dimen.tile_letter_font_size);
mDefaultBitmap = drawableToBitmap(ContextCompat.getDrawable(context, R.drawable.ic_person_white_24dp));
mWidth = res.getDimensionPixelSize(R.dimen.letter_tile_size);
mHeight = res.getDimensionPixelSize(R.dimen.letter_tile_size);
}
public Bitmap getCircularLetterTile(String displayName) {
final Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
final Canvas c = mCanvas;
c.setBitmap(bitmap);
c.drawColor(pickColor(displayName));
if (displayName.trim().length() == 0) {
c.drawBitmap(mDefaultBitmap, dpToPx(4) ,dpToPx(4), null);
} else {
final char firstChar = displayName.trim().charAt(0);
mFirstChar[0] = Character.toUpperCase(firstChar);
mPaint.setTextSize(mTileLetterFontSize);
mPaint.getTextBounds(mFirstChar, 0, 1, mBounds);
c.drawText(mFirstChar, 0, 1, mWidth / 2, mHeight / 2 + (mBounds.bottom - mBounds.top) / 2, mPaint);
}
return getCircularBitmap(bitmap);
}
private Bitmap getCircularBitmap(Bitmap bitmap) {
Bitmap output;
if (bitmap.getWidth() > bitmap.getHeight()) {
output = Bitmap.createBitmap(bitmap.getHeight(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
} else {
output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getWidth(), Bitmap.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 radius = 0;
if (bitmap.getWidth() > bitmap.getHeight()) {
radius = bitmap.getHeight() / 2;
} else {
radius = bitmap.getWidth() / 2;
}
paint.setAntiAlias(true);
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, rect, rect, paint);
return output;
}
private static Bitmap drawableToBitmap(Drawable drawable) {
Bitmap bitmap;
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
if (bitmapDrawable.getBitmap() != null) {
return bitmapDrawable.getBitmap();
}
}
if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
} else {
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;
}
}
It creates an avatar letter. As default it sets an XML vector icon. But the icon is a bit of. I can't seem to figure out which arguments I need to pass on line c.drawBitmap(mDefaultBitmap, dpToPx(4) ,dpToPx(4), null). The dpToPx method is:
private int dpToPx(int dp) {
return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
What I get:
How can I center the icon?

Change the line
c.drawBitmap(mDefaultBitmap, dpToPx(4) ,dpToPx(4), null);
To:
c.drawBitmap(mDefaultBitmap, mWidth / 2 - mDefaultBitmap.getWidth() / 2, mHeight / 2 - mDefaultBitmap.getHeight() / 2)

Related

How can I draw a triangle with outline in canvas in Android application?

I have run into a problem while trying to paint a triangle with stroke.
I have tried to paint one triangle in canvas using path which represents the outline and then another one over it to represent the actual triangle.
public void drawTriangle(int coordX, int coordY, int sideLen, String fillColor, int strokeWidth, String strokeColor) {
this.marginSTART = coordX;
this.marginTOP = coordY;
this.getLayoutParams().width = sideLen;
this.getLayoutParams().height = sideLen-sideLen/8;
this.setX(this.marginSTART);
this.setY(this.marginTOP);
Paint paint = new Paint();
Bitmap bitmap = Bitmap.createBitmap(sideLen, sideLen, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
paint.setColor(Color.parseColor("#ff0000"));
canvas.drawPaint(paint);
paint.setStrokeWidth(0);
paint.setColor(Color.parseColor(strokeColor));
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setAntiAlias(true);
android.graphics.Point a = new android.graphics.Point(0, sideLen);
android.graphics.Point b = new android.graphics.Point(sideLen, sideLen);
android.graphics.Point c = new android.graphics.Point(sideLen/2, 0);
Path path = new Path();
path.setFillType(Path.FillType.EVEN_ODD);
path.setLastPoint(a.x, a.y);
path.lineTo(b.x, b.y);
path.lineTo(c.x, c.y);
path.lineTo(a.x, a.y);
path.close();
canvas.drawPath(path, paint);
Paint paint2 = new Paint();
paint2.setStrokeWidth(0);
paint2.setColor(Color.parseColor(fillColor));
paint2.setStyle(Paint.Style.FILL_AND_STROKE);
paint2.setAntiAlias(true);
android.graphics.Point a1 = new android.graphics.Point((strokeWidth*8)/10, sideLen-strokeWidth);
android.graphics.Point b1 = new android.graphics.Point(sideLen-(strokeWidth*8)/10, sideLen-strokeWidth);
android.graphics.Point c1 = new android.graphics.Point(sideLen/2, (strokeWidth*8)/10);
Path path2 = new Path();
path2.setFillType(Path.FillType.EVEN_ODD);
path2.setLastPoint(a1.x, a1.y);
path2.lineTo(b1.x, b1.y);
path2.lineTo(c1.x, c1.y);
path2.lineTo(a1.x, a1.y);
path2.close();
canvas.drawPath(path2, paint2);
BitmapDrawable bmpDrawable = new BitmapDrawable(getResources(), bitmap);
this.setBackground(bmpDrawable);
}
The result I have so far: https://i.imgur.com/FVexwhe.png
It looks so bad. It's deformed. I don't get it. Where are my mistakes at?
public void drawTriangle(int coordX, int coordY, int sideLen, String fillColor, int strokeWidth, String strokeColor) {
this.marginSTART = coordX;
this.marginTOP = coordY;
this.fillColor = fillColor;
this.strokeColor = strokeColor;
this.strokeWidth = strokeWidth;
//Съотношение:
double suotnoshenie = 0.857;
this.getLayoutParams().width = sideLen;
this.getLayoutParams().height = (int) Math.floor(sideLen*suotnoshenie);
this.setX(this.marginSTART);
this.setY(this.marginTOP);
//Първи тръигълник, който ще се запълни (реална големина)
Paint paint = new Paint();
Bitmap bitmap = Bitmap.createBitmap(sideLen, (int) Math.floor(sideLen*suotnoshenie), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
/*paint.setColor(Color.parseColor("#ff0000")); //testing
canvas.drawPaint(paint);*/
paint.setStrokeWidth(0);
paint.setColor(Color.parseColor(fillColor));
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
Path path = new Path();
path.setLastPoint(0, (float) (sideLen*suotnoshenie)); // A
path.lineTo(sideLen, (float) (sideLen*suotnoshenie)); // B
path.lineTo((float)(sideLen/2), 0); // C
path.lineTo(0, (float) (sideLen*suotnoshenie)); // A
path.close();
canvas.drawPath(path, paint);
//Втори тръигълник, който няма да се запълва, а само ще stroke-ва
// (линиите, който го очертават трябва да влизат вътре в големия до половината stroke, понеже самият stroke минава от двете страни на линиите...)
Paint paint2 = new Paint();
paint2.setStrokeWidth(strokeWidth);
paint2.setColor(Color.parseColor(strokeColor));
paint2.setStyle(Paint.Style.STROKE);
paint2.setAntiAlias(true);
Path path2 = new Path();
path2.setLastPoint((float) (0+(strokeWidth*1.75)/2), (float) ((sideLen*suotnoshenie)-strokeWidth/2)); // A
path2.lineTo((float) (sideLen-(strokeWidth*1.75)/2), (float) ((sideLen*suotnoshenie)-strokeWidth/2)); // B
path2.lineTo((float) (sideLen/2), (float) (0+strokeWidth)); // C
path2.lineTo((float) (0+(strokeWidth*1.75)/2), (float) ((sideLen*suotnoshenie)-strokeWidth/2)); // A
path2.close();
canvas.drawPath(path2, paint2);
BitmapDrawable bmpDrawable = new BitmapDrawable(getResources(), bitmap);
this.setBackground(bmpDrawable);
}

Fitting Bitmap to Screen In SomeView Class onDrawBitmap method

Firstly its not just about scaling bitmap to all screen. It's not duplicate. I searched for it.
I have a class named SomeView and I'm calling this SomeView class on MainActivity like;
setContentView(new SomeView(MainActivity.this, bitmap ));
Sendind bitmap from MainActivity.
And I'm loading image using
canvas.drawBitmap(bitmap, 0, 0, null);
I also tried.
RectF dest = new RectF(0,0,getWidth(),getHeight());
canvas.drawBitmap(bitmap, null, dest, null);
and also tried..
RectF dest = new RectF(0,0,bitmap.getWidth(),bitmap.getHeight());
canvas.drawBitmap(bitmap, null, dest, null);
But nothing works for me... The coming Bitmap not fitting to screen and not fitting to center.
What I have..
What I need.
My View Activity Codes.
SomeView.Java
public SomeView(Context c, Bitmap b) {
super(c);
bitmap = b;
mContext = c;
setFocusable(true);
setFocusableInTouchMode(true);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.STROKE);
paint.setPathEffect(new DashPathEffect(new float[] { 10, 20 }, 0));
paint.setStrokeWidth(15);
paint.setColor(Color.GREEN);
this.setOnTouchListener(this);
points = new ArrayList<Point>();
bfirstpoint = false;
}
public SomeView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
setFocusable(true);
setFocusableInTouchMode(true);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(2);
paint.setColor(Color.WHITE);
this.setOnTouchListener(this);
points = new ArrayList<Point>();
bfirstpoint = false;
}
public void onDraw(Canvas canvas) {
canvas.drawBitmap(bitmap, 0, 0, null);
Path path = new Path();
boolean first = true;
for (int i = 0; i < points.size(); i += 2) {
Point point = points.get(i);
if (first) {
first = false;
path.moveTo(point.x, point.y);
} else if (i < points.size() - 1) {
Point next = points.get(i + 1);
path.quadTo(point.x, point.y, next.x, next.y);
} else {
mlastpoint = points.get(i);
path.lineTo(point.x, point.y);
}
}
canvas.drawPath(path, paint);
}
Here is the solution.
RectF src = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight());
RectF dst = new RectF(0, 0, getWidth(), getHeight());
matrix = new Matrix();
matrix.setRectToRect(src, dst, Matrix.ScaleToFit.CENTER);
Log.d(TAG, "MATRIX VALUE: " + matrix);
canvas.drawBitmap(bitmap, matrix, null);

How to load a existent bitmap into Picasso

The reason that I'm using Picasso is because I need a rounded image and I could achieve this with Picasso using Transformation:
public class CircleTransform implements Transformation {
#Override
public Bitmap transform(Bitmap source) {
int size = Math.min(source.getWidth(), source.getHeight());
int x = (source.getWidth() - size) / 2;
int y = (source.getHeight() - size) / 2;
Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);
if (squaredBitmap != source) {
source.recycle();
}
Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
BitmapShader shader = new BitmapShader(squaredBitmap,
BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
paint.setShader(shader);
paint.setAntiAlias(true);
float r = size / 2f;
canvas.drawCircle(r, r, r, paint);
squaredBitmap.recycle();
return bitmap;
}
#Override
public String key() {
return "circle";
}
}
And then :
Picasso.with(this).load(R.drawable.image)
.transform(new CircleTransform()).into(photo);
But I'm taking a Bitmap from a Camera and I need to put the image inside of ImageView, rounded! I was trying to use Bitmap to File but it doesnt' work!

How to add shadow to a cropped circle image?

I'm using the following to transform an image into a circle. (The purpose is to have a rounded circle image to use as a button in an Android application.)
I'm trying to add a shade of shadow but I can't get it to work. Can anyone help?
public static class CircleTransform extends BitmapTransformation {
public CircleTransform(Context context) {
super(context);
}
#Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
return circleCrop(pool, toTransform);
}
private static Bitmap circleCrop(BitmapPool pool, Bitmap source) {
if (source == null) return null;
int size = Math.min(source.getWidth(), source.getHeight());
int x = (source.getWidth() - size) / 2;
int y = (source.getHeight() - size) / 2;
Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);
Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888);
if (result == null) {
result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
}
Canvas canvas = new Canvas(result);
Paint paint = new Paint();
paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
paint.setAntiAlias(true);
float r = size / 2f;
canvas.drawCircle(r, r, r, paint);
return result;
}
#Override
public String getId() {
return getClass().getName();
}
}

How to maintain quality of the image downloaded from url to imageview and crop them to a circle?

I am using the following code with the help of 'Android Universal image loader' library, but the quality of the image is very poor and I get too many skipped frames in my logcat,
here is my code, please look and help how can I improve it?
private class DownloadImageTask extends AsyncTask<String, Void,
Bitmap> {
ImageView bmImage;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
// Bitmap mIcon11 = null;
ImageLoader imageLoader = ImageLoader.getInstance();
Bitmap bitmap = imageLoader.loadImageSync(urldisplay);
Bitmap circleBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(),
Bitmap.Config.ARGB_8888);
BitmapShader shader = new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP);
Paint paint = new Paint();
paint.setShader(shader);
Canvas c = new Canvas(circleBitmap);
c.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2, bitmap.getWidth() / 2, paint);
//img1.setImageBitmap(circleBitmap);
//bmImage.setImageBitmap(circleBitmap);
return circleBitmap;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
}
}
Picasso and Volley are very good for images, I use Volley and I made a class that extends NetworkImageView and there I crop the image and make it round.
public class RoundedNetworkImageView extends NetworkImageView {
private Bitmap frame;
public RoundedNetworkImageView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public RoundedNetworkImageView(Context context, AttributeSet attrs) {
super(context, attrs);
// frame = BitmapFactory.decodeResource(context.getResources(), R.drawable.chat_list_profile_frame);
}
public RoundedNetworkImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// frame = BitmapFactory.decodeResource(context.getResources(), R.drawable.chat_list_profile_frame);
}
#Override
protected void onDraw(Canvas canvas) {
// super.onDraw(canvas);
Drawable drawable = getDrawable();
if (drawable == null) {
return;
}
if (getWidth() == 0 || getHeight() == 0) {
return;
}
Bitmap b = ((BitmapDrawable) drawable).getBitmap();
if (b != null) {
Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);
int w = getWidth(), h = getHeight();
Bitmap roundBitmap = getCroppedBitmap(bitmap, w);
canvas.drawBitmap(roundBitmap, 0, 0, null);
// canvas.drawBitmap(frame, 0, 0, null);
}
}
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(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xffa19774;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, sbmp.getWidth(), sbmp.getHeight());
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.parseColor("#FFFFFF"));
canvas.drawCircle(sbmp.getWidth() / 2 + 0.7f, sbmp.getHeight() / 2 + 0.7f, sbmp.getWidth() / 2 + 0.1f, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(sbmp, rect, rect, paint);
return output;
}
}
//--------- and when I am using it public
// declaration
public RoundedNetworkImageView user_status_pic;
// getting the image from the url in an list adapter
viewHolder.user_status_pic.setImageUrl(image_url, imageLoader);
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import com.squareup.picasso.Transformation;
public class CircleTransform implements Transformation {
#Override
public Bitmap transform(Bitmap source) {
int size = Math.min(source.getWidth(), source.getHeight());
int x = (source.getWidth() - size) / 2;
int y = (source.getHeight() - size) / 2;
Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);
if (squaredBitmap != source) {
source.recycle();
}
Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
BitmapShader shader = new BitmapShader(squaredBitmap, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
paint.setShader(shader);
paint.setAntiAlias(true);
float r = size/2f;
canvas.drawCircle(r, r, r, paint);
squaredBitmap.recycle();
return bitmap;
}
#Override
public String key() {
return "circle";
}
}
try like this:
Picasso.with(context).load("url").transform(new CircleTransform()).into(target);

Categories

Resources