I created a custom view that extends ImageView. When I set the vector drawable whose viewport is smaller, I am noticing that image is blurry.
If I just use the ImageView, I am seeing the vector image is sharp as it is suppose to be.
In my custom view I override "setImageDrawable", where I do call super and then get bitmap from the drawable to paint later in onDraw.
Here is how i am converting to bitmap
public Bitmap getBitmapFromDrawable(Drawable drawable) {
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;
}
You need to get view width and height, not the drawable, and use these as the drawable bounds. I assume your view dimension might change over time so this is not a one time task. I would store the drawable in a member field:
private Drawable drawable;
#Override
public void setImageDrawable(Drawable drawable) {
this.drawable = drawable;
this.drawable.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight());
// invalidate if needed
}
#Override
protected void onMeasure(int wms, int hms) {
super.onMeasure(wms, hms);
if (drawable != null) drawable.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight());
}
Then onDraw, just draw the drawable.
Just do drawable.getIntrinsicWidth()*5(any num.), drawable.getIntrinsicHeight()*5 and pass DisplayMatrices in first parameter, it will increase the quality.
public Bitmap getBitmapFromDrawable(Drawable drawable) {
Bitmap bitmap = Bitmap.createBitmap(context.getResources().getDisplayMetrics(), drawable.getIntrinsicWidth()*5,
drawable.getIntrinsicHeight()*5,
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
Related
I need to change the default cross-icon in ChromeCustomTab Android, I am changing it with back-icon using the code below:
Bitmap icon = BitmapFactory.decodeResource(context.getResources(),R.drawable.ic_arrow_back_white_24dp);
It is working fine with PNGs but not with SVGs.
As per this documentation, we have to maintain size of image according to this documentation.
https://developer.android.com/reference/android/support/customtabs/CustomTabsIntent.html#KEY_ICON
I think it is not working because they are not following the dimensions given in Documentation.
You need to return a valid Bitmap. For a VectorDrawable it is necessary to do something more. You can use these methods:
private static Bitmap bitmapFromDrawable(Context context, int drawableId) {
Drawable drawable = ContextCompat.getDrawable(context, drawableId);
if (drawable instanceof VectorDrawable) {
return bitmapFromVectorDrawable((VectorDrawable) drawable);
}
return ((BitmapDrawable) drawable).getBitmap();
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static Bitmap bitmapFromVectorDrawable(VectorDrawable vectorDrawable) {
Bitmap bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(), vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
vectorDrawable.draw(canvas);
return bitmap;
}
Then you can use it like:
builder.setCloseButtonIcon(bitmapFromDrawable(this, R.drawable. ic_arrow_back_white_24dp));
Because I need my drawable as bitmap descriptor, I convert my resource to a Drawable then to a Bitmap.
But I want to change its color, So I used the following code found somewhere here:
private static Bitmap drawableToBitmap (Drawable drawable) {
Bitmap bitmap = null;
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); // Single color bitmap will be created of 1x1 pixel
} 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());
int iColor = Color.parseColor("#006f00");
drawable.setColorFilter(iColor, PorterDuff.Mode.SRC_ATOP);
drawable.draw(canvas);
return bitmap;
}
But the drawable's color remains black.
Can you please tell me why and how to get it working?
This converts a BitmapDrawable to a Bitmap.
Drawable d = ImagesArrayList.get(0);
Bitmap bitmap = ((BitmapDrawable)d).getBitmap();
And for changing bitmap's color see below link
How to change Bitmap image color in android?
Paint p = new Paint();
ColorFilter filter = new LightingColorFilter(Color.RED, 0);
p.setColorFilter(filter);
canvas.drawBitmap(bitmap, 0, 0, p);
To convert drawable into bitmap use this -
Bitmap icon = BitmapFactory.decodeResource(context.getResources(),
R.drawable.icon_resource);
You can change bitmap pixels color by this-
int[] pixels = new int[myBitmap.getHeight()*myBitmap.getWidth()];
myBitmap.getPixels(pixels, 0, myBitmap.getWidth(), 0, 0, myBitmap.getWidth(), myBitmap.getHeight());
for (int i=0; i<myBitmap.getWidth()*5; i++)
pixels[i] = Color.BLUE;
myBitmap.setPixels(pixels, 0, myBitmap.getWidth(), 0, 0, myBitmap.getWidth(), myBitmap.getHeight());
I think the problem could be PorterDuff.Mode.SRC_ATOP, the method you use for apply the filter. I don't know specifically SRC_ATOP but this link explains all of them.
I don't know how your image is composed, but I'd use DST_ATOP instead of SRC_ATOP.
EDIT: I presumed that this code won't return in the case you are analizing, 'cause if it returns the filter obviously is never reached.
if (drawable instanceof BitmapDrawable)
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
if(bitmapDrawable.getBitmap() != null) {
return bitmapDrawable.getBitmap();
}
}
I'm having this code:
public void saveimage() {
Bitmap bitmap = Bitmap.createBitmap(colorGFX.getWidth(),
colorGFX.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.WHITE);
canvas = colorGFX.canvas;
canvas.setBitmap(bitmap);
saveBitmap(bitmap);
}
colorGFX object extends a SurfaceView.
saveBitmap actually writes the image on the file.
The problem is that most of the times a WHITE image is saved, other times the correct image is saved.
Did I missed something, or why does the image saves only let's say 1/5 of the times?
This worked for me:
Bitmap bitmap = Bitmap.createBitmap(colorGFX.getWidth(),
colorGFX.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(colorGFX.bitmap, 0f, 0f, null);
canvas.drawBitmap(colorGFX.pictureBitmap, 0f, 0f, null);
saveBitmap(bitmap);
Try this:
public void saveimage() {
Bitmap bitmap = Bitmap.createBitmap(colorGFX.getWidth(),
colorGFX.getHeight(), Bitmap.Config.ARGB_8888);
colorGFX.draw(new Canvas(bitmap))
saveBitmap(bitmap);
}
I've built a new view named myview including OnDraw section.
And I tried to use setContentView(myview) in Oncreate, however, it failed and showed some error.
Then I use addview function to add this view to my original layout, and setContent(R.layout.main)
Finally I can see the result on the screen.
What was the problem ? Why I can't directly use setContentView(myview) to show the result ?
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myview2=new MyView2(this);
setContentView(R.layout.main2);
RelativeLayout layout= ( RelativeLayout )findViewById(R.id.dashpage);
layout.addView(myview2);
}
class MyView2 extends View{
public MyView2(Context context) {
super(context);
}
Bitmap themometer = BitmapFactory.decodeResource(getResources(),
R.drawable.the);
Matrix matrix2 = new Matrix();
Bitmap themometerbmp = Bitmap.createBitmap(themometer, 0, 0, themometer.getWidth(),
themometer.getHeight(), matrix2, true);
public void onDraw(Canvas canvas2)
{
canvas2.drawBitmap(themometerbmp,90,5,null);
}
}
I don't think setContentView is the problem. You are trying to use a drawable. Try this:
Add a function in MyView2:
public Bitmap getBitmapFromDrawable (Drawable drawable) {
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
Then, instead of
Bitmap themometer = BitmapFactory.decodeResource(getResources(), R.drawable.the);
use
Bitmap themometer = getBitmapFromDrawable(getDrawable(R.drawable.the));
How can a Drawable loaded from a resource be rotated when it is drawn? For example, I would like to draw an arrow and be able to rotate it to face in different directions when it is drawn?
You need to use Bitmap and Canvas Class functions to prepare drawable:
Bitmap bmpOriginal = BitmapFactory.decodeResource(this.getResources(), R.drawable.image2);
Bitmap bmResult = Bitmap.createBitmap(bmpOriginal.getWidth(), bmpOriginal.getHeight(), Bitmap.Config.ARGB_8888);
Canvas tempCanvas = new Canvas(bmResult);
tempCanvas.rotate(90, bmpOriginal.getWidth()/2, bmpOriginal.getHeight()/2);
tempCanvas.drawBitmap(bmpOriginal, 0, 0, null);
mImageView.setImageBitmap(bmResult);
In this code sample rotation for 90 degrees over image center occurs.
essentially it can be boiled down to: do a(n inverse) canvas transformation instead of transforming drawable
private BitmapDrawable drawable; // or Drawable
protected void onDraw(Canvas canvas) { // inherited from View
//...
canvas.save();
canvas.rotate(degrees, pivotX, pivotY);
drawable.draw(canvas);
canvas.restore();
//...
}
if you have BitmapDrawable it may be desirable to increase quality of the output by setting antialiasing
drawable.setAntialias(true);
Accepted answer doesn't work for me. I have non square image, so I changed his code a bit.
private Bitmap rotateDrawable(#DrawableRes int resId) {
Bitmap bmpOriginal = BitmapFactory.decodeResource(getResources(), resId);
Bitmap bmpResult = Bitmap.createBitmap(bmpOriginal.getHeight(), bmpOriginal.getWidth(), Bitmap.Config.ARGB_8888);
Canvas tempCanvas = new Canvas(bmpResult);
int pivot = bmpOriginal.getHeight() / 2;
tempCanvas.rotate(90, pivot, pivot);
tempCanvas.drawBitmap(bmpOriginal, 0, 0, null);
return bmpResult;
}
mImageView.setImageBitmap(rotateDrawable(R.drawable.some_image));
essentially this:
ImageView spaceshipImage = (ImageView) findViewById(R.id.spaceshipImage);
Animation hyperspaceJumpAnimation = AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
spaceshipImage.startAnimation(hyperspaceJumpAnimation);
source link:
http://developer.android.com/guide/topics/graphics/2d-graphics.html#tween-animation