Android: not optimal Image load - android

I got this little function that allows me to load an image from a path, named name. It works, the problem is that I have to call this many times, una tantum. Let's say, a dozen of times at the load of a specific activity. It takes few seconds to load them all.
Is it optimal? Is there a lighter way to achieve the same result?
public static Bitmap loadImageFrom(File path, String name)
{
try {
File f = new File(path, name);
return BitmapFactory.decodeStream(new FileInputStream(f));
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
}
I tried adding if(!f.exists()) return null; like this:
public static Bitmap loadImageFrom(File path, String name)
{
try {
File f = new File(path, name);
if(!f.exists()) return null;
return BitmapFactory.decodeStream(new FileInputStream(f));
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
}
I know that is redundant, but I can't remove the Try Catch clause, cause it giving me an error if I do. However, no speed up noticed.
Any suggestion?

It's not that your code is inefficient, as far as I know, loading pictures manually on the main thread will hurt your app's performance. Especially when you have a large amount of pictures and/or using them to populate your ListView or GridView.
Have a look at Picasso or Universal Image Loader, these libraries should help load your pictures efficiently thus speeding up your app.

Related

Grab video thumbnail and show it in a Gridview in android

I am developing a module for which i want to show all the user's videos from sd card into a Gridview. I have grabbed video file paths in usual way (Checking if file or directory and save if its a file) in a arraylist and grabbed its bitmap thumbnail with following code:
Bitmap bmThumbnail = ThumbnailUtils.createVideoThumbnail(VideoValues.get(position).getAbsolutePath(),
Thumbnails.MINI_KIND);
Obviously this code runs in a background thread. But the only problem is that the gribview still freezes a lot while scrolling. According to me the main problem is extracting the bitmap from video, which takes a lot of time. Can anyone suggest me a different way to get bitmap from video and how it in a grid ? I have seen the smooth behavior in other apps like Facebook, etc. But I cannot figure out as to how that can be done.
please use below method for retrive video thumbnail from video
#SuppressLint("NewApi")
public static Bitmap retriveVideoFrameFromVideo(String videoPath)
throws Throwable
{
Bitmap bitmap = null;
MediaMetadataRetriever mediaMetadataRetriever = null;
try
{
mediaMetadataRetriever = new MediaMetadataRetriever();
mediaMetadataRetriever.setDataSource(videoPath);
bitmap = mediaMetadataRetriever.getFrameAtTime();
}
catch (Exception e)
{
throw new Throwable(
"Exception in retriveVideoFrameFromVideo(String videoPath)"
+ e.getMessage());
}
finally
{
if (mediaMetadataRetriever != null)
{
mediaMetadataRetriever.release();
}
}
return bitmap;
}

Android: Bitmap.compress poor quality with PNG format

My application captures video footage and saves it as .mp4 file. I would like to extract one frame from this video and also save it to file. Since I haven't found nothing better, I've decided to use MediaMetadataRetriever.getFrameAtTime() for that. It happens inside the class that inherits from AsyncTask. Here is how my code looks like my doInBackground():
Bitmap bitmap1 = null;
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
try {
retriever.setDataSource(src);
bitmap1 = retriever.getFrameAtTime(timeUs, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
if (Utils.saveBitmap(bitmap1, dst)) {
Log.d(TAG, "doInBackground Image export OK");
} else {
Log.d(TAG, "doInBackground Image export FAILED");
}
} catch (RuntimeException ex) {
Log.d(TAG, "doInBackground Image export FAILED");
} finally {
retriever.release();
if (bitmap1 != null) {
bitmap1.recycle();
}
}
And the saveBitmap() method:
File file = new File(filepath);
boolean result;
try {
result = file.createNewFile();
if (!result) {
return false;
}
FileOutputStream ostream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, ostream);
ostream.close();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
Now, the problem is that the quality of the exported image is noticeably worse then the video quality. I don't think that this should happen with PNG output format. You can see the difference below:
The first image was extracted from the video using ffmpeg on my desktop. The second one was extracted using the code above on Samsung Galaxy S6. The result looks pretty much the same on every Android device I was using.
Can someone tell how can I improve the quality of the exported picture?
I found other solution for the issue. You can use bigflake's example to build mechanism for extracting video frame. The one thing you will have to add is seeking mechanism. This works well, keeps the exact quality and does not require any third-party libraries. Only downside I've noticed so far is that it will result in longer execution time than the original idea.

The most efficient way to show the local image in android

I am currently work on a magazine like apps. Since there is an option to zoom in(150%, 200%, 250% of original source) , I would prefer not to scale down the image. However , the app will force restart when I try to decode the image because of the out of memory. Are there any suggestion to fix that?
The image are local (SD card) , can be retrieve in any approach, but eventually need to be a bitmap as I use something like cavans.drawbitmap to display it. I tried, input stream-> bytes , input stream->bitmap etc... but are there any most efficient way or at least
I can sure the app does not force restart / close? Thanks
try {
InputStream is = (InputStream) new URL(url).getContent();
try {
return BitmapFactory.decodeStream(is);
} finally {
is.close();
}
} catch (Exception e) {
return BitmapFactory.decodeResource(context.getResources(), defaultDrawable);
}
You should consider using nostra's image loader, it deals with memory quite efficiently, you can specify lots of config stuffs, im using it and its working pretty well for large images aswell
This is what smartImageView(by loopj - you can find him on http://loopj.com/) uses to retrieve files from the drive/sd.
private Bitmap getBitmapFromDisk(String imgID) {
Bitmap bitmap = null;
if(diskCacheEnabled){
String filePath = getFilePath(imgID);
File file = new File(filePath);
if(file.exists()) {
bitmap = BitmapFactory.decodeFile(filePath);
}
}
return bitmap;
}

File browser out of memory

I am trying to load the thumbnails for videos in a file browser but its causing me to run out of memory.
public class Filea {
private Bitmap VideoIcon;
public Bitmap getVideoIcon() {
return VideoIcon;
}
public void setVideoIcon(Bitmap videoIcon) {
VideoIcon = videoIcon;
}
This is being done for every video file that is in a folder.
Every time that I load a new folder does it keep the information from the previous folder, and if so how do i get it to delete the unwanted resources?
private List<Filea> LoadFiles(String dirPath) {
inSearch = false;
List<Filea> files = new ArrayList<Filea>();
try {
for(String F:EditedFileList(current)) {
Filea file = new Filea();
file.setVideoIcon(ThumbnailUtils.createVideoThumbnail(current + "/" + getName(F), MediaStore.Images.Thumbnails.MINI_KIND));
files.add(file);
}
} catch (NullPointerException e) {
e.getStackTrace();
} catch (NoSuchElementException e) {
Log.i("LoadFiles", "No files found");
}
return files;
}
This is how the information is obtained.
Along with the video thumbnails I am loading other bits of data E.g. File name, size, permissions, Image icons(as bitmaps) ect..
Most likely you're keeping around a bunch of unneeded references. My suggestion would be to put the images in an LRUCache and load them from there. That way you can set a reasonable maximum amount of memory to use on images.
I found the problem, i was trying to load the full image of picture instead of the thumbnails.`
file.setImageIcon(ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(current + "/" + getName(F)), 100, 100));
Thank. LukeMovement.

How can I set an image from a file path?

I'm saving an image from the device's camera to a directory on the SD card (ex: /sdcard/appName/image.jpg), then I save the path into a database. My problem is that I can't seem to load the images into a ListView with a cursor adapter.
I tried the following code, where helper.getImg(); is a method from my database helper that returns a String (the file path), but it is not working.
icon=(ImageView)row.findViewById(R.id.icon_pura);
String imgPath=helper.getImg(c);
Bitmap myBitmap=BitmapFactory.decodeFile(imgPath);
icon.setImageBitmap(myBitmap);
the answer has to do with URIs, and you need to use the externalstorage() function. Using set paths won't work on every device
anyway you store path into the URI which is more flexible for retrieving and parsings items at that path
String filepath = Environment.getExternalStorageDirectory().getAbsolutePath()+"/Directory name/";
File file = new File(filepath,imagename);
FileInputStream fs = null;
try
{
fs = new FileInputStream(file);
}
catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
BitmapFactory.Options bfOptions = new BitmapFactory.Options();
/*
* bfOptions.inDither=false; //Disable Dithering mode
* bfOptions.inPurgeable=true; //Tell to gc that whether it needs
* free memory, the Bitmap can be cleared
* bfOptions.inInputShareable=true;*/
bfOptions.inJustDecodeBounds = false;
bfOptions.inTempStorage = new byte[32 * 1024];
try {
Bitmap originalImage = BitmapFactory.decodeFileDescriptor(fs.getFD(), null,bfOptions);
icon.setImageBitmap(originalImage);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
If you follow himanshu's (correct) advice, make sure that if you're going to allow the user the option of loading and re-loading the image, make sure to manually icon.setImageBitmap(null); between loads, because otherwise Android will leak that memory and you'll crash your app. It's not 100% consistant, and has something to do with the sizes of the images you're loading, but I just found this leak a few days ago and am 100% certain that it's there.

Categories

Resources