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...
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:
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.
I'm newbie in android. My question is how to set shared preferences in image view. I want to shared the image to another activity. Please help me because I'm stocked on it.. Please help me the explain me clearly and codes. Thank you.
The "standard" way to share data across Activities is usign the putExtraXXX methods on the intent class. You can put the image path in your intent:
Intent intent = new Intent(this,MyClassA.class);
intent.putExtra(MyClassA.IMAGE_EXTRA, imagePath);
startActivity(intent);
And you retrieve it and open it in your next Activity:
String filePath = getIntent().getStringExtra(MyClassA.IMAGE_EXTRA);
Here is an implementation of a function that opens and decodes the image and return a Bitmap object, notice that this function requires the image to be located in the assets folder:
private Bitmap getImageFromAssets(String assetsPath,int reqWidth, int reqHeight) {
AssetManager assetManager = getAssets();
InputStream istr;
Bitmap bitmap = null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
try {
istr = assetManager.open(assetsPath);
bitmap = BitmapFactory.decodeStream(istr, null, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeStream(istr, null, options);
} catch (IOException e) {
return null;
}
return bitmap;
}
I am facing a problem I cannot solve myself.
I have to capture image in my android app, and then upload that image to FTP server. Of course, I have to resize it before sending it to FTP because 2MB is definitely unacceptable size :)
I succeded in taking picture, getting its path and upload it in its full size.
This is how I upload it to server.
File file = new File(pathOfTheImage);
String testName =System.currentTimeMillis()+file.getName();
fis = new FileInputStream(file);
// Upload file to the ftp server
result = client.storeFile(testName, fis);
Is it possible, at this point, to resize or compress image in order to reduce its size and after that, to upload it to server?
Any help would be appreciated.
P.S. Sorry for my poor English!
EDIT:
Solved thanks to Alamri.
One more time, man, thank you!!!
In my application i used this before uploading the image:
1- resize,scale and decode the bitmap
private Bitmap decodeFile(File f) {
try {
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
final int REQUIRED_SIZE=450;
int scale=1;
while(o.outWidth/scale/2>=REQUIRED_SIZE && o.outHeight/scale/2>=REQUIRED_SIZE)
scale*=2;
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
Bitmap bit1 = BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
return bit1;
} catch (FileNotFoundException e) {}
return null;
}
2- now let's save the resized bitmap:
private void ImageResizer(Bitmap bitmap) {
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/Pic");
if(!myDir.exists()) myDir.mkdirs();
String fname = "resized.im";
File file = new File (myDir, fname);
if (file.exists()){
file.delete();
SaveResized(file, bitmap);
} else {
SaveResized(file, bitmap);
}
}
private void SaveResized(File file, Bitmap bitmap) {
try {
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
after saving the resized, scaled image. upload it using your code :
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/Pic/resized.im");
String testName =System.currentTimeMillis()+file.getName();
fis = new FileInputStream(file);
// Upload file to the ftp server
result = client.storeFile(testName, fis);
I am trying to move a part of code written in Java (Android) to C# (Mono for android) and I am stuck at finding a way to do this. The part of the code in Java is as follows:
private Bitmap decodeFile(File f){
try {
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, o);
...
} catch(FileNotFoundException ex){
}
Precisely, converting from Java.IO.File to System.IO.Stream as required by the first parameter of DecodeStream is my problem. How should this statement be rewritten?
I usually use the static System.File methods to obtain the corresponding FileStream:
var stream = File.OpenRead("PathToFile")
In your case, you should get rid of the "File" class that you have in java: File is a static class in .NET. Can you pass the path directly (as a String) to your decodeFile function?
private Bitmap decodeFile(string f){
try {
var o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
using (var stream = File.OpenRead(f)) {
BitmapFactory.decodeStream(stream, null, o);
...
}
} catch(FileNotFoundException ex){
}