Trying to get image from gallery, my photo uri : content://com.android.providers.media.documents/document/image%3A15672
when i don't use bmOptions(BitmapFactory.decodeStream(inStream)) i get bitmap image succesfully, but when i add bmOptionsBitmapFactory.decodeStream(inStream,null,bmOptions)) i get null bitmap, unable to figure out what am doing wrong.
private void setPic(Uri photoUri) {
InputStream inStream = null;
try {
inStream = getContentResolver().openInputStream(photoUri);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
Log.i("response", "INPUT STREAM| Bitmap : "+ BitmapFactory.decodeStream(inStream,null,bmOptions));
}
That is expected behavior if you use bmOptions.inJustDecodeBounds = true;, which can be translated to human language as don't load the bitmap, just resolve it's size and some other metadata. It is usually used to know Bitmap size before loading it to memory to prevent OOM exceptions, and load bitmap pre-down-scaled.
Related
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:
In my Android app i have to read a lot of images, for this reason i have implemented image caching. This is the method through which i decode my images(that were stored in the assets/ folder):
private Bitmap getBitmapFromAsset(String strName)
{
AssetManager assetManager = context.getAssets();
InputStream istr = null;
try {
istr = assetManager.open(strName);
} catch (IOException e) {
e.printStackTrace();
}
return decodeFileFromAssets(istr);
}
private Bitmap decodeFileFromAssets(InputStream stream ){
//decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(stream,null,o);
final int REQUIRED_WIDTH=1280;
final int REQUIRED_HIGHT=720;
int scale=1;
while(o.outWidth/scale/2>=REQUIRED_WIDTH && o.outHeight/scale/2>=REQUIRED_HIGHT)
scale*=2;
//decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(stream, null, o2);
}
I have notice that when i read .jpg images its all ok, but when i read .png images i came across to this annoying error:
D/skia﹕ --- SkImageDecoder::Factory returned null
how can i resolve this issue without converting all the .png images into .jpg images??
EDIT
This issue is presenting only when i have to show a .png images from the assets folder and not for all other format. Why?
EDIT 2
I have edited my code in order to explain better the function of my methods...
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.
I wrote a little piece of code that download image from internet and cache them into cache dir.
It runs in a secondary thread.
{
String hash = md5(urlString);
File f = new File(m_cacheDir, hash);
if (f.exists())
{
Drawable d = Drawable.createFromPath(f.getAbsolutePath());
return d;
}
try {
InputStream is = download(urlString);
Drawable drawable = Drawable.createFromStream(is, "src");
if (drawable != null)
{
FileOutputStream out = new FileOutputStream(f);
Bitmap bitmap = ((BitmapDrawable)drawable).getBitmap();
bitmap.compress(CompressFormat.JPEG, 90, out);
}
return drawable;
} catch (Throwable e) { }
return null;
}
I use this code to load picture inside a ListView item, and it works fine. If I remove the first if (where i load image from disk) it runs smoothly (and download picture every time!). If I keep it, when you scroll listview you feel some lags during picture's loading from disk, why?
To answer the question "why", I experienced this with lots of gc() messages in my logcat. Android allocates the memory before decoding the file from disk which could cause garbage collection, which is painful for the performance in all threads. Probably the same happens when you encode your jpeg as well.
For decoding part you can try reuse existing bitmap if you have one to let Android decode image in-place. Please have a look at the following snippet:
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = inSampleSize;
options.inJustDecodeBounds = false;
options.inMutable = true;
if (oldBitmap != null) {
options.inBitmap = oldBitmap;
}
return BitmapFactory.decodeFile(f.getAbsolutePath(), options);
http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/
Do in background.( use AsyncTask to load images.)
I am trying to download images from a remote server, the number of images downloaded is 30. The code i am using to download image is as below. Some images download successfully and some images don't download and raises the above exception. What might be the problem.
public static Bitmap loadBitmap(String url)
{
Bitmap bitmap = null;
InputStream in = null;
BufferedOutputStream out = null;
try {
in = new BufferedInputStream(new URL(url).openStream(), 4*1024);
final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
out = new BufferedOutputStream(dataStream, 4 * 1024);
int byte_;
while ((byte_ = in.read()) != -1)
out.write(byte_);
out.flush();
final byte[] data = dataStream.toByteArray();
BitmapFactory.Options options = new BitmapFactory.Options();
//options.inSampleSize = 1;
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length,options);
} catch (IOException e) {
Log.e("","Could not load Bitmap from: " + url);
} finally {
try{
in.close();
out.close();
}catch( IOException e )
{
System.out.println(e);
}
}
return bitmap;
}
Please look on my this post
Image download code works for all image format, issues with PNG format rendering
In my case I solved this error with encode the url
Because image url that i wanted to download has the Persian letters(or other Unicode character) in it
So I replaced all Persian characters with encoded UTF-8 letters