I have an Uri pointing to an image I have chosen. I want to store the image in a Mat variable, edit it and show it in an ImageView. Till now, I just want to load the image in the Mat variable, and show it, without edits. This is my code:
Uri uri = data.getData();
Mat image = Imgcodecs.imread(uri.getPath());
//several edits in future
Bitmap resultBitmap = Bitmap.createBitmap(image.rows(), image.cols(),Bitmap.Config.ARGB_8888);
Utils.matToBitmap(image, resultBitmap);
imageView.setImageBitmap(resultBitmap);
The line that gives the error is Bitmap resultBitmap = Bitmap.createBitmap(image.rows(), image.cols(),Bitmap.Config.ARGB_8888);, and says that image.rows() and image.cols() cannot be 0.
It's logic that if the dimensions are (0, 0) it gives an error, but I can't figure out why they are 0.
The problem was that I was passing a wrong URI to imread, which therefore failed and returned an empty Mat. As Dan MaĊĦek suggested I've called the empty method, that returned true, and I found that I was passing a wrong URI.
Related
I have searched online for a tutorial on how to send a bitmap data over to another activity using the putExtra() method in kotlin, but nothing seems to pop up. I do not know how to code in java so all the tutorials and stack overflow threads that talk about converting to a byte array do not help much. Can someone please help me with maybe a solution?
What I did so far (My project is in no regards to this post) is I saved a image using my camera as a bitmap using the code:
val thumbnail : Bitmap = data!!.extras!!.get("data") as Bitmap
(the key word "data" is a intent inside the upper override function (onActivityResult))
This saves a bitmap of the image I took with the camera and now I tried to send it over, using the putExtra() command as so:
var screenSwitch2 = Intent(this#MainActivity,mlscreen::class.java)
screenSwitch2.putExtra("bitmap", thumbnail)
On the other screen "mlscreen" I tried to recover the data using a intent.getStringExtra("bitmap")
val thumbnail = intent.getStringExtra("bitmap")
and then I set my image view in the "mlscreen" using the setImageBitmap method as here:
iv_image.setImageBitmap(thumbnail)
I got the error that I was looking for a bitmap data and not a string data for the method. I knew this would occur though because I had to use intent.getSTRINGExtra which would mean its converting it to a string I presume.
Any help with this would be appreciated! Thanks.
There are 3 ways to do that :
1 - Using Intent (not recommended)
ByteArrayOutputStream baos = new ByteArrayOutputStream();
thumbnail.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] b = baos.toByteArray();
intent.putExtra("image", b);
startActivity(intent);
2 - Using static (not recommended)
public static Bitmap thumbnail;
3 - Using Path (recommended)
Save your Bitmap as an image file in specific folder (make it invisible to the users).
Get the path from the saved file.
Use intent.putExtrat("imagePath",path);.
Use BitmapFactory.decodeFile(filePath); to get the Bitmap from the path.
Remove the path.
I was wondering about, how to implement Glide along with using Bitmap compression in Kotlin and thought that any of the code below would work. But unfortunately, the app closes as soon as I add an image into any of the imageView for the fourth time.
Here's the code which I tried to implement
val selectedImage = data?.data
val bitmap = MediaStore.Images.Media.getBitmap(contentResolver, selectedImage)
//method 1
Glide.with(this).asBitmap().load(compressBitmap(bitmap,5)).into(imageView!!)
//method 2
var bitmapDrawable = BitmapDrawable( resources , compressBitmap(bitmap,5))
Glide.with(this).load(bitmapDrawable).into(imageView!!)
What would be the correct code, if i'm somewhere wrong here. Thankyou in advance
Try using Recycler View or another component to load the images in. They will handle the load.
I am using EasyImage library to take pictures.
I then convert those Files to Bitmap and then I convert Bitmap to Base64 and upload it to server.
I know, it's not a good way to do it, but that's how I currently do it.
When a picture is taken:
#Override
public void onImagePicked(File imageFile, EasyImage.ImageSource source) {
uploadImage(imageFile);
}
This is the first line inside "uploadImage" method:
Image image = new Image(LoginManager.getInstance(getApplicationContext()).getUsername(), file);
This is the constructor:
public Image(String userName, File imageFile) {
this.userName = userName;
this.imageFile = imageFile;
createBase64(getBitmap());
}
Inside "getBitmap" is where the problem begins. These 2 lines in particular:
bitmap = BitmapFactory.decodeFile(imageFile.getPath());
bitmap = Bitmap.createScaledBitmap(bitmap, 100, 100, false);
imageFile is never null.
I checked with debugger at least a 100 times and it is never null. It also always has path.
getPath() is never null.
However, it still often fails to create bitmap.
Sometimes it is successful and everything is OK, but most of the times, the bitmap is null.
I don't know why.
File (the picture taken) is always created successfully and is never null, but it just fails to create the Bitmap for some reason.
From the documentation
Returns
the resulting decoded bitmap, or null if it could not be decoded.
This can have various reasons, most of the times the bitmap is too large and the space could not be allocated.
Check that the path to the image exists and that you have read / write permissions to the URI specified.
If you do have access but it is still failing you should add BitmapFactory.Options to the method call and set inSampleSize to load a smaller version of the image.
If set to a value > 1, requests the decoder to subsample the original image, returning a smaller image to save memory.
Also you should always check for null returned when working with bitmaps, since memory can always be an issue.
How can I check if a Bitmap object is completely blank, i.e. all its pixels are transparent, without a x-y loop on every pixel?
You can check your Bitmap instance (in the example myBitmap) against an empty one with:
Bitmap emptyBitmap = Bitmap.createBitmap(myBitmap.getWidth(), myBitmap.getHeight(), myBitmap.getConfig());
if (myBitmap.sameAs(emptyBitmap)) {
// myBitmap is empty/blank
}
You can do this very easy but it depends on the application.
If you have an application that prompts the user for a drawing input, like signature or anything similar, you will usually have an ArrayList of Paths which are drawn to the Canvas of that View. You can do a check when you want to return the BitMap look to see if the ArrayList of Paths is bigger than 0 and return the BitMap if so, or else return null.
My app can load quite large images. In an effort to be memory-conservative, I'm attempting to use a temporary bitmap to load and another for the final image after transformation:
.....
finalBitmap.recycle();
finalBitmap = null;
Bitmap tempBitmap = BitmapFactory.decodeStream(fin, ...);
finalBitmap = Bitmap.createBitmap(tempBitmap, ....);
imgview.setImageBitmap(finalBitmap);
.....
Now, at this point we're done with tempBitmap, which was only needed to transport the decoded Bitmap to the transformation step in createBitmap. So:
.....
tempBitmap.recycle();
tempBitmap = null;
.....
And... it crashes with a "trying to use a recycled bitmap" error specifically because of the recycling of tempBitmap. tempBitmap wasn't displayed and is only used right there.
What's going wrong here? Should I just use "finalBitmap" throughout and rely on createBitmap to manage it (finalBitmap = Bitmap.createBitmap(finalBitmap , ....))? I fail to see what ongoing dependency on tempBitmap there would be that would cause such a failure.
Edit: Yes, the null assignment seems to result in the appropriate, eventual garbage collection, but I'm mystified as to why recycle() on a temp Bitmap is so problematic in this case. I get the impression that createBitmap() is holding a reference to it but why, and for how long?
Straight from the Android documentation:
Returns an immutable bitmap from the specified subset of the source
bitmap. The new bitmap may be the same object as source, or a copy may
have been made.
It seems that the createBitmap functions have the potential to re-use the bitmap that you provided. If that is the case, then you shouldn't recycle the temporary bitmap since your final bitmap is using it. One thing you can do is
if(tempBitmap != finalBitmap) {
tempBitmap.recycle();
}
That should only recycle the tempBitmap when it isn't the same as the finalBitmap. At least that seems to be what the documentation is implying.