Convert ImageView Vector Drawable to Bitmap Android - android

I take a fingerprint from the user and add white background to it using glide. The issue is I need to get the byte array of that image and I can't get it because the Image being hold into the ImageView is a VectorDrawable. I am unable to convert this back to bitmap and thus to a byte array. I tried using it on a dummy png image like following.
Take any dummy PNG Image
firstIV = findViewById(R.id.firstIV);
secondIV = findViewById(R.id.secondIV);
Bitmap currentBmp = BitmapFactory.decodeResource(getResources(), R.drawable.test_image);
Glide.with(this).load(currentBmp).into(new SimpleTarget<Drawable>() {
#Override
public void onResourceReady(Drawable resource, Transition<? super Drawable> glideAnimation) {
final ShapeDrawable background = new ShapeDrawable();
background.getPaint().setColor(Color.WHITE);
final Drawable[] layers = {background, resource};
firstIV.setImageDrawable(new LayerDrawable(layers));
setToAnotherImageView(firstIV.getDrawable().getIntrinsicWidth(), firstIV.getDrawable().getIntrinsicHeight());
}
});
Applied Solution
private void setToAnotherImageView(int width, int height) {
Log.e(TAG, "onCreate: " + width + ":" + height);
Bitmap convertedBmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(convertedBmp);
firstIV.draw(canvas);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
convertedBmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
Bitmap newBmp = BitmapFactory.decodeByteArray(byteArray,0,byteArray.length);
secondIV.setImageBitmap(newBmp);
}
Upon doing so my app crashes with an exception saying the vector drawable can not be converted to bitmap. The following is the error:
Originally what I want to achieve
Originally I want the bytearray of the the picture I have stored in my ImageView so I can convert that bytearray to WSQ bytearray and the send it to my server. I am trying to achieve such with an example defined above.

UPDATE:
Just find out that there is a new way to get Bitmap from ImageView:
imageView.drawToBitmap() //draw from the ImageView size
imageView.drawable.toBitmap() //draw from original Drawable size (I guess)
Convert ImageView to ByteArray:
private fun getImageBytes(): ByteArray {
val bitmap = Bitmap.createBitmap(my_profile_imageView.width, my_profile_imageView.height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
my_profile_imageView.draw(canvas)
val outputStream = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
return outputStream.toByteArray()
}
However, it's not a good idea to store the image ByetArray in local, you should store the uri or url instead.

My question is a duplicate of How to get a Bitmap from VectorDrawable
However I solved it like this
private void setToAnotherImageView() {
Drawable drawable = firstIV.getDrawable();
Bitmap newBmp = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(newBmp);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
secondIV.setImageBitmap(newBmp);
}

Related

How can I add a blur effect to a background in an app?

How can I add a blur effect to a background in an Android app? I would like to know some source with the resources and the steps to add this effect. I understand that I have to add a filter, but I don't know where I am going to add it Please can someone help me? I will put the layout of the section that I want to change, As you can see, it has a normal background, but I want to put the blur effect on that section
<?xml version="1.0" encoding="utf-8" ?>
Here are some libraries for you:
https://github.com/Manabu-GT/EtsyBlur
https://github.com/Manabu-GT/GlassView
Usually, we call this feature Glass View, so you can also google it.
You can try to use RenderScript to blur the Bitmap of image:
public Bitmap blurBitmap(Bitmap bitmap,Context context){
//Let's create an empty bitmap with the same size of the bitmap we want to blur
Bitmap outBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
//Instantiate a new Renderscript
RenderScript rs = RenderScript.create(context);
//Create an Intrinsic Blur Script using the Renderscript
ScriptIntrinsicBlur blurScript = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
//Create the Allocations (in/out) with the Renderscript and the in/out bitmaps
Allocation allIn = Allocation.createFromBitmap(rs, bitmap);
Allocation allOut = Allocation.createFromBitmap(rs, outBitmap);
//Set the radius of the blur
blurScript.setRadius(25.f);
//Perform the Renderscript
blurScript.setInput(allIn);
blurScript.forEach(allOut);
//Copy the final bitmap created by the out Allocation to the outBitmap
allOut.copyTo(outBitmap);
}
//recycle the original bitmap
bitmap.recycle();
//After finishing everything, we destroy the Renderscript.
rs.destroy();
return outBitmap;
}
public Bitmap drawableToBitmap(Drawable drawable) {
int width = drawable.getIntrinsicWidth();
int heigh = drawable.getIntrinsicHeight();
drawable.setBounds(0, 0, width, heigh);
Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
: Bitmap.Config.RGB_565;
Bitmap bitmap = Bitmap.createBitmap(width, heigh, config);
Canvas canvas = new Canvas(bitmap);
drawable.draw(canvas);
return bitmap;
}
public void blurImage(View imageView, Context context){
Drawable drawable = imageView.getBackground();
Bitmap bitmap = drawableToBitmap(drawable);
Bitmap out = blurBitmap(bitmap,context);
BitmapDrawable bitmapDrawable = new BitmapDrawable(context.getResources(),
out);
imageView.setBackground(bitmapDrawable);
}
Use it with a view id is view in a Activity:
View view = findViewById(R.id.view);
blurImage(view,this);

Unable to convert vector drawable to bitmap drawable in android

I am trying to convert a bitmap to byte array in which i have taken an vector drawable image to bitmap and then i have converted it to byte array but when i open the application it shows me an error class cast exception unable to convert vector drawable to bitmap drawable.
Resources res = getResources();
Drawable drawable = res.getDrawable(R.drawable.ic_motorcycle_black);
if (drawable != null) {
drawable.setColorFilter(0xffff0000, PorterDuff.Mode.MULTIPLY);
}
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
final byte[] bike = stream.toByteArray();
Error:
Caused by: java.lang.ClassCastException: android.graphics.drawable.VectorDrawable cannot be cast to android.graphics.drawable.BitmapDrawable
at codingtown.coconut.otherexpense.activity.AddNewExpenseCategoryActivity.intialize(AddNewExpenseCategoryActivity.java:82)
at codingtown.coconut.otherexpense.activity.AddNewExpenseCategoryActivity.onCreate(AddNewExpenseCategoryActivity.java:67)
at android.app.Activity.performCreate(Activity.java:6092)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1112)
You can try this. It works fine with me.
private BitmapDescriptor bitmapDescriptorFromVector(Context context, #DrawableRes int vectorDrawableResourceId) {
Drawable background = ContextCompat.getDrawable(context, R.drawable.ic_map_pin_filled_blue_48dp);
background.setBounds(0, 0, background.getIntrinsicWidth(), background.getIntrinsicHeight());
Drawable vectorDrawable = ContextCompat.getDrawable(context, vectorDrawableResourceId);
vectorDrawable.setBounds(40, 20, vectorDrawable.getIntrinsicWidth() + 40, vectorDrawable.getIntrinsicHeight() + 20);
Bitmap bitmap = Bitmap.createBitmap(background.getIntrinsicWidth(), background.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
background.draw(canvas);
vectorDrawable.draw(canvas);
return BitmapDescriptorFactory.fromBitmap(bitmap);
}
You cannot cast VectorDrawable to BitmapDrawable. They don't have a parent-child relationship. They both are direct subclasses of Drawable class.
to get a bitmap from drawable, you will need to create a Bitmap from the drawable metadata.
Probably something like this in a separate method,
try {
Bitmap bitmap;
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
} catch (OutOfMemoryError e) {
// Handle the error
return null;
}

Get bitmap of videoview

Is there a way to take a screenshot of a video playing in video view. I searched on the forum but could not get the required info. I tried with
Bitmap bitmap = Bitmap.createBitmap(this.view.getWidth(), this.view.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
and
mCustomVideoView.setDrawingCacheEnabled(true);
Bitmap videoView = mCustomVideoView.getDrawingCache(false);
But none of these methods were helpful.
Just make it with that:
videoview.buildDrawingCache();
Bitmap bitmap = yourvideoview.getDrawingCache();
 java.io.ByteArrayOutputStream stream=new java.io.ByteArrayOutputStream(); 
bitmap.compress(Bitmap.CompressFormat.WEBP, 90, stream);
byte[] videoByteArray=stream.toByteArray(); String video_str = Base64.encodeToString(videoByteArray, 0);
The output is the String video_str and the Bitmap bitmap.

Android merge two images

I want to merge two images and then save them on the Android SDCard.One is from the camera and one from the resources folder. The problem is that i get this error: Caused by: java.lang.IllegalStateException: Immutable bitmap passed to Canvas constructor. Thanks.
Bitmap bottomImage = BitmapFactory.decodeResource(getResources(),R.drawable.blink);
Bitmap topImage = (Bitmap) data.getExtras().get("data");
// As described by Steve Pomeroy in a previous comment,
// use the canvas to combine them.
// Start with the first in the constructor..
Canvas comboImage = new Canvas(bottomImage);
// Then draw the second on top of that
comboImage.drawBitmap(topImage, 0f, 0f, null);
// bottomImage is now a composite of the two.
// To write the file out to the SDCard:
OutputStream os = null;
try {
os = new FileOutputStream("/sdcard/DCIM/Camera/" + "myNewFileName.png");
bottomImage.compress(CompressFormat.PNG, 50, os);
//Bitmap image.compress(CompressFormat.PNG, 50, os);
} catch(IOException e) {
Log.v("error saving","error saving");
e.printStackTrace();
}
Managed to fix it by simply doing this change:
int w = bottomImage.getWidth();
int h = bottomImage.getHeight();
Bitmap new_image = Bitmap.createBitmap(w, h ,bottomImage.getConfig());
The problem now is that it doesn't saves the image. Do you know why?
This will help you =)
Edit: (embed answer from link)
the only static "constructor" for Bitmap returning a mutable one is:
(Class: Bitmap) public static Bitmap createBitmap(int width, int
height, boolean hasAlpha)
Returns: a mutable bitmap with the specified width and height.
So you could work with getPixels/setPixels or like this:
Bitmap bitmapResult = bm.createBitmap(widthOfOld, heightOfOld, hasAlpha);
Canvas c = new Canvas();
c.setDevice(bitmapResult); // drawXY will result on that Bitmap
c.drawBitmap(bitmapOld, left, top, paint);
how to get the drawable from Bitmap: by using the BitmapDrawable-Subclass which extends Drawable, like this:
Bitmap myBitmap = BitmapFactory.decode(path);
Drawable bd = new BitmapDrawable(myBitmap);
The bitmap you are retrieving is immutable, meaning it can't be modified. Although it doesn't specify on the Canvas page that the constructor needs a mutable bitmap, it does.
To create a mutable bitmap, you can use this method.

How to read drawable bits as InputStream

There's say some ImageView object. I want to read bits/raw data of this object as InputStream. How to do that?
First get background image of the ImageView as an object of Drawable:
iv.getBackground();
Then convert Drawable image into Bitmap using
BitmapDrawable bitDw = ((BitmapDrawable) d);
Bitmap bitmap = bitDw.getBitmap();
Now use ByteArrayOutputStream to get the Bitmap into a Stream and get bytearray[]; then
convert the bytearray into a ByteArrayInputStream.
You can use the following code to get InputStream from ImageView.
Full Source code
ImageView iv = (ImageView) findViewById(R.id.splashImageView);
Drawable d = iv.getBackground();
BitmapDrawable bitDw = ((BitmapDrawable) d);
Bitmap bitmap = bitDw.getBitmap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] imageInByte = stream.toByteArray();
System.out.println("........length......" + imageInByte);
ByteArrayInputStream bis = new ByteArrayInputStream(imageInByte);
Thanks
Deepak
These methods below are useful because they work with any kind of Drawable (not only BitmapDrawable). If you want to use drawing cache as in David Caunt's suggestion, consider using bitmapToInputStream instead of bitmap.compress, because it should be faster.
public static Bitmap drawableToBitmap (Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable)drawable).getBitmap();
}
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;
}
public static InputStream bitmapToInputStream(Bitmap bitmap) {
int size = bitmap.getHeight() * bitmap.getRowBytes();
ByteBuffer buffer = ByteBuffer.allocate(size);
bitmap.copyPixelsToBuffer(buffer);
return new ByteArrayInputStream(buffer.array());
}
You can use the drawing cache to retrieve a Bitmap representation of any View class.
view.setDrawingCacheEnabled(true);
Bitmap b = view.getDrawingCache();
Then you can write the bitmap to an OutputStream, for example:
b.compress(CompressFormat.JPEG, 80, new FileOutputStream("/view.jpg"));
In your case I think you can use a ByteArrayOutputStream to get a byte[] from which you can create an InputStream. The code would be something like this:
ByteArrayOutputStream os = new ByteArrayOutputStream(b.getByteCount());
b.compress(CompressFormat.JPEG, 80, os);
byte[] bytes = os.toByteArray();
You might be looking for this:
openRawResource

Categories

Resources