Load images with OpenCV from assets folder in Android - android

I'm stuck trying to load an image placed in assets folder with OpenCV 3.0 in Android. I've read a lot of answers here, but I can't figure out what I'm doing wrong.
"my image.jpg" is place directly in the assets folder created by Android Studio.
This is the code I'm using. I've checked and the library has been loaded correctly.
Mat imgOr = Imgcodecs.imread("file:///android_asset/myimage.jpg");
int height = imgOr.height();
int width = imgOr.width();
String h = Integer.toString(height);
String w = Integer.toString(width);
if (imgOr.dataAddr() == 0) {
// If dataAddr() is different from zero, the image has been loaded
// correctly
Log.d(TAG, "WRONG UPLOAD");
}
Log.d(h, "height");
Log.d(w, "width");
When I try to run my app, this is what I get:
08-21 18:13:32.084 23501-23501/com.example.android D/MyActivity: WRONG UPLOAD
08-21 18:13:32.085 23501-23501/com.example.android D/0: height
08-21 18:13:32.085 23501-23501/com.example.android D/0: width
It seems like the image has no dimensions. I guess because it has not been loaded correctly. I'va also tried to load it placing it in the drawable folder, but it doesn't work anyway and I'd prefer to use the assets one.
Anyone can please help me and tell me how to find the right path of the image?
Thanks

Problem: imread needs absolute path and your assets are inside a apk, and the underlying c++ classes cannot read from there.
Option 1: load image into Mat without using imread from drawable folder.
InputStream stream = null;
Uri uri = Uri.parse("android.resource://com.example.aaaaa.circulos/drawable/bbb_2");
try {
stream = getContentResolver().openInputStream(uri);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bmp = BitmapFactory.decodeStream(stream, null, bmpFactoryOptions);
Mat ImageMat = new Mat();
Utils.bitmapToMat(bmp, ImageMat);
Option 2: copy image to cache and load from absolute path.
File file = new File(context.getCacheDir() + "/" + filename);
if (!file.exists())
try {
InputStream is = context.getAssets().open(filename);
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
FileOutputStream fos = new FileOutputStream(file);
fos.write(buffer);
fos.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
if (file.exists()) {
image = cvLoadImage(file.getAbsolutePath(), type);
}

Related

BitmapFactory cannot decode an image

In a React Native app for Android, I am trying to write an image (passed as base64) onto the filesystem and later decode it using BitmapFactory.
Why is BitmapFactory still unable to decode the image after using (Base64.decode) while storing it?
The error:
Cannot decode bitmap:
file:///data/data/com.reactnativeapp/files/rct-image-store/1
The custom written method storing the image:
#ReactMethod
public void addImageFromBase64(String base64_image_data, Callback successCallback, Callback failureCallback){
String imageStorageDir = this.reactContext.getApplicationContext().getFilesDir()+"/rct-image-store/";
String file_uri = imageStorageDir+"1";
try {
File f = new File(imageStorageDir);
if(!f.exists()) {
f.mkdir();
}
FileOutputStream fos = new FileOutputStream(file_uri, false);
byte[] decodedImage = Base64.decode(base64_image_data, Base64.DEFAULT);
fos.write(decodedImage);
fos.close();
successCallback.invoke("file://"+file_uri);
} catch (IOException ioe) {
failureCallback.invoke("Failed to add image from base64String"+ioe.getMessage());
} catch (Exception e) {
failureCallback.invoke("Failed to add image from base64String"+e.getMessage());
}
}
Shortened method for accessing the image (fullResolutionBitmap is null):
InputStream inputStream = mContext.getContentResolver().openInputStream(Uri.parse(uri));;
BitmapFactory.Options outOptions = new BitmapFactory.Options();
Bitmap fullResolutionBitmap = BitmapFactory.decodeStream(inputStream, null, outOptions);/// fullResolutionBitmap==null
Here is the image, the bottom part looks cropped. Since both original and converted image have the grey area, the problem seems to be not with the conversion of the image, but with the source (camera).
Original image:
Converted image:

Android BitmapFactory decodeResource Out of Memory Exception

I'm new to android and developing an app that saves large images from drawable folder to phone storage. These files have resolution of 2560x2560 and I want to save these files without loosing image quality.
I use following method to save images and it gives me Out of Memory Exception. I have seen many answers how to load a large bitmap efficiently. But I cant really find an answer for this problem.
In my code, I use
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), imageId);
File file = new File(root.getAbsolutePath() + "/Pictures/" + getResources().getString(R.string.app_name) + "/" + timeStamp + ".jpg");
file.createNewFile();
FileOutputStream oStream = new FileOutputStream(file);
bitmap.compress(CompressFormat.JPEG, 100, oStream);
oStream.close();
bitmap.recycle();
Is there anything wrong with my code? This works without any exception for smaller images.
If I use android:largeHeap="true", this does not throw any exception. But I know it is not a good practice to use android:largeHeap="true".
Is there any efficient way to save large images from drawable folder without an exception?
Thank you in advance.
If you just want to copy the image file, you shouldn't decode it into a bitmap in the first place.
You can copy a raw resource file with this for example:
InputStream in = getResources().openRawResource(imageId);
String path = root.getAbsolutePath() + "/Pictures/" + getResources().getString(R.string.app_name) + "/" + timeStamp + ".jpg";
FileOutputStream out = new FileOutputStream(path);
try {
byte[] b = new byte[4096];
int len = 0;
while ((len = in.read(b)) > 0) {
out.write(b, 0, len);
}
}
finally {
in.close();
out.close();
}
Note that you have to store your image in the res/raw/ directory instead of res/drawable/.

In Android: read image from file, for large images reduce size by reducing resolution, save it in a Blob

My Android-App reads image-files from the sd-card and stores the image in a blob in a sqlite database.
Currently i am converting a FileInputStream to a byte array and store this in the blob. A blob cannot exceed the size of 1MB, so in this case i am posting an error-message and cancel the operation.
FileInputStream fis = null;
try {
fis = new FileInputStream(FilePath); // FilePath contains a valid path
} catch (FileNotFoundException e) {
Toast.makeText(MyActivity.this, "File not found: " + FilePath, Toast.LENGTH_LONG).show();
return;
}
BufferedInputStream bis = new BufferedInputStream(fis, 1070);
ByteArrayBuffer bab = new ByteArrayBuffer(128);
int current = 0;
try {
while ((current = bis.read()) != -1) bab.append((byte) current);
} catch (IOException e) {
Toast.makeText(MyActivity.this, "Error reading Picture: " + FilePath, Toast.LENGTH_LONG).show();
return;
}
byte[] imageBa = bab.toByteArray();
if (imageBa.length > 1024*1024)
showErrorDialog();
else {
saveImageInDatabase(imageBa); // sage image byte[] in BLOB-column so sq-lite database
// show image in imageView
imageStream = new ByteArrayInputStream(imageBa);
Bitmap imageBitmap = BitmapFactory.decodeStream(imageStream); // uncompressed imageBitmap has a much bigger size than the image-byte[]
imageView.setImageBitmap(imageBitmap);
}
I want to get rid of the 1MB-limitation and store also bigger images, by reducing the resolution (not the size).
I could go for a solution using the BitmapFactory option inSampleSize to compress an image and / or convert the bitmap back to a byte[], e.g. using bitmap.compress.
However, even an uncompressed bitmap created with BitmapFactory has a much bigger size than the original byte [], so i fear that i lose quality.
Any ideas how to solve my issue? Many thanks in advance, Gerhard.

VuDroid pdf viewer cannot find Bitmap to render or it doesnt render

I am trying to use the VuDroid PDF viewer and I need to take the rendered bitmap and store it as a byte[]. Then I need to convert it back into a Bitmap that can be displayed on a view using something like "canvas.drawBitmap(bitmap, 0, 0, paint);".
I have spent many hours trying to access the Bitmap and I might have done it already, but even if I get the byte[] to return something it still wont render as a Bitmap on the canvas.
Could someone please help me here, I must be missing something. Thank you so much.
I believe it is supposed to accessed via...
PDFPage.java .... public Bitmap renderBitmap(int width, int height, RectF pageSliceBounds)
-or-
through Page.java -or- DocumentView.java -or- DecodeService.java
Like I said I have tried all of these and have gotten results I just cannot see where I am going wrong since I cannot render it to see if the Bitmap was called correctly.
Thank you again :)
The doc says the method returns "null if the image could not be decode." You can try:
byte[] image = services.getImageBuffer(1024, 600);
InputStream is = new ByteArrayInputStream(image);
Bitmap bmp = BitmapFactory.decodeStream(is);
I think This will help you:-
Render a byte[] as Bitmap in Android
How does Bitmap.Save(Stream, ImageFormat) format the data?
Copy image with alpha channel to clipboard with custom background color?
if you want to get each pdf page as independent bitmap you should consider that
VuDroid render the pages,
PDFView only display them.
you should use VuDroid functions.
now you can use this example and create your own codes
Example code : for make bitmap from a specific PDF page
view = (ImageView)findViewById(R.id.imageView1);
pdf_conext = new PdfContext();
PdfDocument d = pdf_conext.openDocument(Environment.getExternalStorageDirectory() + "your PDF path");
PdfPage vuPage = d.getPage(1); // choose your page number
RectF rf = new RectF();
rf.bottom = rf.right = (float)1.0;
Bitmap bitmap = vuPage.renderBitmap(60, 60, rf); //define width and height of bitmap
view.setImageBitmap(bitmap);
for writing this bitmap on SDCARD :
try {
File mediaImage = new File(Environment.getExternalStorageDirectory().toString() + "your path for save thumbnail images ");
FileOutputStream out = new FileOutputStream(mediaImage);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
for retrieve saved image:
File file = new File(Environment.getExternalStorageDirectory().toString()+ "your path for save thumbnail images ");
String path = file.getAbsolutePath();
if (path != null){
view = Bitmap.createScaledBitmap(BitmapFactory.decodeFile(path), YOUR_X, YOUR_Y, false);
}
Try this code to check whether bitmap is properly generating or not
PdfContext pdf_conext = new PdfContext();
PdfDocument d = (PdfDocument) pdf_conext.openDocument(pdfPath);
PdfPage vuPage = (PdfPage) d.getPage(0);
RectF rf = new RectF();
Bitmap bitmap = vuPage.renderBitmap(1000,600, rf);
File dir1 = new File (root.getAbsolutePath() + "/IMAGES");
dir1.mkdirs();
String fname = "Image-"+ 2 +".jpg";
File file = new File (dir1, fname);
if (file.exists ())
file.delete ();
try {
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}

Android: Copy and paste of an image do not work!

I want to copy a picture from asstets folder and paste it in my package, just for test. but final image doesn't show anything. when I want to open picture with paint, it says that "This is not a valid bitmap file".
In my program, I start to read original image in this way:
private void copyImage()
{
AssetManager am = getResources().getAssets();
try{
image = BitmapFactory.decodeStream(am.open("tasnim.png"));
imWidth = image.getWidth();
imHeight = image.getHeight();
}
catch(IOException e){
e.printStackTrace();
System.out.println("Error accoured!");
}
}
next, I'll get pixels of image or extract pixels, and save pixels in array of integer (rgbstream).
private void getPixelsOfImage()
{
rgbStream = new int[imWidth * imHeight];
image.getPixels(rgbStream, 0, imWidth, 0, 0, imWidth, imHeight);
}
finally, I want to save it in my package,
private void createPicture()
{
contextPath = context.getFilesDir().getAbsolutePath();
String path = contextPath + "/" + picName;
try{
FileOutputStream fos = new FileOutputStream(path);
DataOutputStream dos = new DataOutputStream(fos);
for(int i=0; i<rgbStream.length; i++)
dos.writeByte(rgbStream[i]);
dos.flush();
dos.close();
fos.close();
}
catch(IOException e){
System.out.println("IOException : " + e);
}
System.out.println("Picture Created.");
}
Code works fine but result, nothing!!! :(
When I check DDMS it creates new file and store all pixels (because it shows the size of this file is 13300 and dimension of my original picture is 100*133). when I click "pull a file from the device" I can save it on my desktop. However, when I open it :) nothing.
What you think? is there any problem in my code?
Thanks
I don't know what your intent is - do you want to write out a raw image file?
Assuming that you want to write a JPEG or PNG or whatever, you can erase your entire code and do something a lot easier:
Bitmap image = BitmapFactory.decodeStream(am.open("tasnim.png"));
FileOutputStream fos = new FileOutputStream(path);
image.compress(Bitmap.CompressFormat.PNG, 100, fos);
With proper error checking of course.

Categories

Resources