How to make bitmap loading faster in Android? - android

I have a code that loads the thumbnail of the image and feeds it to glide. Then glide will load in the holder. but, As I am loading the thumbnail it returns a bitmap. SO, I am passing bitmap to glide. But, this takes nearly 30sec for initial loading. I mean in the gallery there are lots of photos. So, when the gallery is opened it won't show images for 30sec at all. And then it will show the bitmaps.
on the other hand, if I use URI to feed to glide it will load it immediately. But, Images are being loaded in recycler view. So, only some images will be loaded at the time.
After some images are loaded. When we swipe up and see other photos loading speed then obviously bitmap fed images are loaded way faster than URI fed images. But, bitmap takes 30sec of initial loading time.
Is there any way to make this bitmap load faster?
...
while (cursor.moveToNext()) {
Log.d("FetchImages(): ", " Started");
Bitmap thumbBitmap = null;
int _thumpId = cursor.getInt(column_index_data);
Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, _thumpId);
Size thumbSize = new Size(150, 150);
try {
thumbBitmap = getApplicationContext().getContentResolver().loadThumbnail(uri1, thumbSize, null);
} catch (IOException e) {e.printStackTrace();}
ImageModel ImageModel = new ImageModel();
ImageModel.setBitmap(thumbBitmap);
arrayList.add(ImageModel);
}
Log.d("FetchImages(): ", " Ended");
runOnUiThread(() -> {
Adapter Adapter = new Adapter(getApplicationContext(), arrayList, MainActivity.this);
recyclerView.setAdapter(Adapter);
cursor.close();
Log.d("FetchImages(): ", " RecyclerView Adapter attached");
});
...

Glide .with(context) .load(url).apply(new RequestOptions().override(150, 150)) //for resizing .into(imageView);
No need to create bitmap it takes more computation .
Glide is more faster and efficient.
And still if you want to use bitmap then use AsycTask so it wont block main thread and program will not hang.

Related

how can I show a video thumbnail from a video path?

I want to show a video thumbnail in an ImageView from a video path on storage. Is there a function that takes a video path and returns a bitmap of a thumbnail? I get the video path by this code:
public ArrayList<String> getAllMedia() {
HashSet<String> videoItemHashSet = new HashSet<>();
String[] projection = {MediaStore.Video.VideoColumns.DATA, MediaStore.Video.Media.DISPLAY_NAME};
Cursor cursor = getContext().getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projection, null, null, null);
try {
cursor.moveToFirst();
do {
videoItemHashSet.add((cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA))));
} while(cursor.moveToNext());
cursor.close();
} catch(Exception e) {
e.printStackTrace();
}
ArrayList<String> downloadedList = new ArrayList<>(videoItemHashSet);
return downloadedList;
}
It is the default way to create a thumbnail.
For Mini Kind
Bitmap thumb;
//MINI_KIND, size: 512 x 384 thumbnail
thumb = ThumbnailUtils.createVideoThumbnail(filePath, MediaStore.Video.Thumbnails.MINI_KIND);
img_tumbnail.setImageBitmap(thumb);
For Micro Kind
Bitmap thumb;
//MICRO_KIND, size: 96 x 96 thumbnail
thumb= ThumbnailUtils.createVideoThumbnail(filePath, Thumbnails.MICRO_KIND);
img_tumbnail.setImageBitmap(thumb);
Also, you can use Glide for Url as well as Video path of Device.
Glide.with(context).with(this)
.asBitmap()
.load(videoFilePath) // or URI/path
.into(imgView); //imageview to set thumbnail to
also, you can resize thumbnail by using .override(50,50) with Glide.
Use Glide lib
to show thumbnail from local storage
String filePath = "/storage/emulated/0/Pictures/example_video.mp4";
GlideApp
.with(context)
.asBitmap()
.load(Uri.fromFile(new File(filePath)))
.into(imageViewGifAsBitmap);
You can use ThumbnailUtils to load video thumb in 3 format:
MINI_KIND : Good for media detail view
FULL_SCREEN_KIND : Good for header
MICRO_KIND : Good for recycleView
Ex:
holder.videoThumb.setImageBitmap(ThumbnailUtils.createVideoThumbnail(getItem(position).videoURL, MediaStore.Images.Thumbnails.MICRO_KIND))
The biggest drawback is that ThumbnailUtils operate on UI thread so if you try to use this method in a recycleView then it gone make your app skip frames. Your RecycleView will have laggy scroll and if you have more than 7 items then your app will start throwing ANR.
That means you need to create AsyncTask or Threads which again might lead to memory leaks.
Conclusion; Glide is better in loading video thumbs.
Here DiskCacheStrategy.RESULT is important parameter which worked for me and give a smooth fast scroll in recycle view.
Glide.with(context).load(getItem(position).videoURL)
.asBitmap()
.placeholder(R.drawable.app_icon)
.centerCrop()
.diskCacheStrategy(DiskCacheStrategy.RESULT)
.into(holder.videoThumb)
I have 3rd method to set thumbnail of image/video.
Hope it will help you.
1) ThumbnailUtils --> Effective but Slow
Bitmap thumb = ThumbnailUtils.createVideoThumbnail(thumbPath, MediaStore.Video.Thumbnails.MINI_KIND);
holder.ivThumb.setImageBitmap(thumb);
2) FFmpegMediaMetadataRetriever --> Very Effective but Slow
FFmpegMediaMetadataRetriever retriever = new FFmpegMediaMetadataRetriever();
try {
retriever.setDataSource(thumbPath);
thumb.setImageBitmap(retriever.getFrameAtTime(0));
} catch (Exception ex) {
// Assume this is a corrupt file
}
3) Glide --> Effective and Fast
RequestOptions options = new RequestOptions()
.centerCrop()
.placeholder(android.R.drawable.stat_notify_error)
.error(android.R.drawable.stat_notify_error);
Glide.with(context)
.load(thumPath)
.apply(options)
.into(thumb);
If anyone is looking for a Kotlin version. You can try this extension function.
It is using coil.
/**
* https://github.com/coil-kt/coil/issues/413
*/
fun ImageView.setThumbnail(uri: Uri, frameMillis: Long = 2000) {
val imageLoader = ImageLoader.Builder(context)
.componentRegistry {
add(VideoFrameFileFetcher(context))
add(VideoFrameUriFetcher(context))
}.build()
val request = ImageRequest.Builder(context)
.data(uri)
.videoFrameMillis(frameMillis)
.target(this)
.fetcher(VideoFrameUriFetcher(context))
.build()
findViewTreeLifecycleOwner()?.lifecycleScope?.launch(Dispatchers.Main) {
imageLoader.execute(request)
}
}
In some devices not working for me without FileDescriptorBitmapDecoder
So I used following code with FileDescriptorBitmapDecoder
public static void loadLocalVideoThumbanail(Context context, String path, final ImageView imageView) {
try {
if (path == null || path.isEmpty())
return;
BitmapPool bitmapPool = Glide.get(context).getBitmapPool();
int microSecond = 1000000;// 1st second as an example
VideoBitmapDecoder videoBitmapDecoder = new VideoBitmapDecoder(microSecond);
FileDescriptorBitmapDecoder fileDescriptorBitmapDecoder = new FileDescriptorBitmapDecoder(videoBitmapDecoder, bitmapPool, DecodeFormat.PREFER_ARGB_8888);
Glide.with(context).load(path).asBitmap().thumbnail(0.6f)
.diskCacheStrategy(DiskCacheStrategy.RESULT)
.dontAnimate()
.videoDecoder(fileDescriptorBitmapDecoder)
.override(200,200)
.into(imageView);
} catch (Exception e) {
MyLog.e(TAG, "LoadImage: ", e);
}
}

Bitmap loading very slow

I'm using this method for loading albumArt in list
long thisAlbum = musicCursor.getLong(albumColumn);
Bitmap artWork = null;
Uri sArtworkUri = Uri
.parse("content://media/external/audio/albumart");
Uri albumArtUri = ContentUris.withAppendedId(sArtworkUri, thisAlbum);
try {
artWork = MediaStore.Images.Media.getBitmap(
musicResolver, albumArtUri);
artWork = Bitmap.createScaledBitmap(artWork, 150, 150, true);
} catch (FileNotFoundException exception) {
exception.printStackTrace();
artWork = BitmapFactory.decodeResource(getResources(),
R.drawable.no_cover);
} catch (IOException e) {
e.printStackTrace();
}
songsList.add(new Songs(thisId, thisTitle, thisArtist, artWork));
}
everything is working fine but when i open my activity it takes more then 10 seconds to load the activity and when i remove this bunch of code activity open as normally ,can anyone tell me please why it is happening and please tell me also what to do or any update for code
Instead of Bitmap I always use glide library(It gives smoothness to app)
So just add it in build.gradle(Module App)
compile 'com.github.bumptech.glide:glide:3.7.0
code to load image in imageview using glide
Glide.with(context).load(imagePath).crossFade().diskCacheStrategy(DiskCacheStrategy.ALL).thumbnail(0.5f).into(imageView);
I Hope It will Help You :)
You are trying to make the bitmap from the images from your phone.
I think the images in your phone are too large.
You can use Glide to make Bitmap for your local image.
Glide.with(mContext)
.load(new File(pictureUri.getPath())) // Uri of the picture
.asBitmap().
into(100, 100). // Width and height
get();
Remember to run this code within AsyncTask or Thread.
Hope it will helpfull to you.

Android make preview from images on web

I'm trying to make preview as Thumbnail from images on web before downloading, it means i have more item on RecyclerView and i'm trying to view simple blurred preview from images but i dont know whats solution, i use this below code but i think this code download full image, like with social application such as whatsApp or Telegram how can i make preview image on web and show that to users?
new Thread(new Runnable() {
#Override
public void run() {
//First create a new URL object
URL url = null;
try {
if (checkNetWorkConnection()) {
url = new URL("http://wallpaperwarrior.com/wp-content/uploads/2016/09/Wallpaper-2.jpeg");
//Next create a file, the example below will save to the SDCARD using JPEG format
File file = new File(APP.DIR_APP + APP.IMAGE + "/" + "Wallpaper-2.jpg");
//Next create a Bitmap object and download the image to bitmap
Bitmap bitmap = BitmapFactory.decodeStream(url.openStream());
//Finally compress the bitmap, saving to the file previously created
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, new FileOutputStream(file));
}
} catch (MalformedURLException e) {
e.printStackTrace();
Log.e("Error ", e.getMessage());
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.e("Error ", e.getMessage());
} catch (IOException e) {
e.printStackTrace();
Log.e("Error ", e.getMessage());
}
}
}).start();
You can use picasso lib.
Picasso
.with(context)
.load("http://wallpaperwarrior.com/wp-content/uploads/2016/09/Wallpaper-2.jpeg")
.resize(600, 200)
.centerInside()
.into(imageViewResizeCenterInside);
You can give circle shape to image using Transformation api of picasso.
refer this Picasso
You can try implement with this zoom effect. It is being use by many application. With the example you can create your own background like full screen black background but you need to implement it yourself which is pretty simple but kinda lot of work to do.
Beside why not try to use Glide or Picasso to download and display the image? It help you save a lot work such as caching, download in asyncs,resize etc.
When you work with image especially with recycleview or listview there is some problem you need to always remember. Every time you scroll the listView/RecycleView it actually re-download the image so you have to really check wether it already exist in your sdcard to avoid this problem beside there is better to cache is memory although you already save it on sd card but still you can avoid memory crash by cache it in memory. Those hard work done by using either one of the library I just show you.

Load bitmap with picasso into ImageView

i'm building a file explorer application, and i'm trying to load large amount of images (more then 5000...), i'm trying to use picasso but its still slow so i'm trying to load a Thumbimage with picasso and not the whole image file..
....
ImageItem item = data.get(position);
ImageView imageView = holder.image;
Bitmap ThumbImage = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(item.getImage().getPath()), 100, 100);
Picasso.with (context) .load (ThumbImage ) .into (imageView); /*/ doesnt work.. cant load ThumbImage with Picasso
Picasso.with (context) .load (item.getImage()) .into (imageView); //work, but too slow
i cant figure out how can i load Thumbimage into ImageView with Picasso.. there is any why to do that? another way to load faster my images?
First I would recommend using RecyclerView instead of a GridView, considering it handles a lot of the memory management for you. Instead of having to load all of the images at once (or manage it yourself), it will only load the images that fit on the screen. And you can use a GridLayoutManager to have it appear just as it would in a GridView.
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recycler);
recyclerView.setLayoutManager(new GridLayoutManager(context, 4);
recyclerView.setAdapter(new MyRecyclerViewAdapter(context, data);
Also, let Picasso handle converting the image for you, this way you do not need to use ThumbnailUtils. Picasso handles image resizing and memory management with the resize() function:
String uri = data.get(position);
Picasso.with(context).load(new File(uri)).resize(100, 100)
.centerCrop().into(imageView)
You can do this in the onBindViewHolder() method of the RecyclerView.Adapter so that each image will only be loaded when the View has to be shown.
I am not sure how you are obtaining the images currently, but if you do not know how to obtain the URI of the image, this should work:
String[] projection = {"*"};
List<String> data = new ArrayList<>();
Cursor cursor = context.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, null, null, null);
if(cursor.moveToFirst()) {
do {
data.add(cursor.getString(cursor
.getColumnIndex(MediaStore.Images.Media.DATA)));
} while(cursor.moveToNext());
}
I do not know if this will fix the problem you have with Picasso not loading the images, but if it does not post a stack trace and we can try to figure that out.

Read and load images from SDcard asynchronously - fail

I'd like to load image which is on SDCARD in folder to imageView of my cell in listView. I've tried different solutions but each of them fails. When I load images normally as it is in every base tutorial everything works. I've observed that, my application slows down when it has to load many images. Images are taken from photo camera of device. I'd like to load each of them asynchronously to avoid UI slow reaction. I've tried to use Thread, Asynctask but each of them throws error: "Only the oryginal thread that created a view hierarchy can touch its views". How to load images to avoid speed problems? SDImageLoader is a class which is possible to get from GITHUB. What I've tried is a standard code but is slows:
In a getView method in ListAdapter:
File imageFile = new File(Options.PATH_TO_FOLDER_PHOTOS_OF_APP + "test.png");
String imageFileString = Options.PATH_TO_FOLDER_PHOTOS_OF_APP + "test.png";
// "test.png" is a test file. Each cell will have different name of file to load.
if(imageFile.exists())
{
Bitmap myBitmap = BitmapFactory.decodeFile(imageFile.getAbsolutePath());
image.setImageBitmap(myBitmap);
// final SDImageLoader loader = new SDImageLoader(context);
// new SDImageLoader().load(imageFileString, image);
//UrlImageViewHelper.setUrlDrawable(image, url);
}
else
{
final SDImageLoader loader = new SDImageLoader();
Resources resources = context.getResources();
int resurceId;
resurceId = resources.getIdentifier("bad", "drawable",context.getPackageName());
loader.load(imageFileString, image);
image.setImageResource(resurceId);
}
Have you tried to refresh your project after adding an external library to your project? It doesn't matter with the fragment. You send exact context to the List Adapter - which should be fragment.this.getActivity().

Categories

Resources