Bitmap loading very slow - android

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.

Related

How to make bitmap loading faster in 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.

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);
}
}

AQuery select image from gallery

I am using AQuery to load images taken by camera and displaying them in my activity in a image view. The problem is that when I try to do the same but instead of taking a picture, just select the image from my gallery, my image view appears to have nothing in it. This is my code:
//Get image uri that was selected in gallery
Uri selectedImage = data.getData();
//Convert uri to string path
strMainPic = selectedImage.toString();
//Create file to add as parameter to AQuery
File Main = new File(strMainPic);
aq.id(R.id.image_one).image(Main, 100);
If I use the selectedImage and change it to a Bitmap with BitmapFactory, it works but the performance suffers. What am I doing wrong?
I just solved it a couple of seconds ago. I used this code:
Uri selectedImage = data.getData();
try {
bmp = BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
aq.id(R.id.image_one).image(bmp, AQuery.RATIO_PRESERVE);
I just added this to my onActivityResult() method.

How to display rectangle thumbnails for video in android

Hi all i want to display video thumbnail with rectangle shape as in given link .I have used some code and now video is displaying in thumbnail but not with rectangle as display in given link.So please suggest me, is this is possible in android or not .If possible then how..Thanks..
http://lh3.ggpht.com/_xBHTh_QdoYY/S81nyg57zsI/AAAAAAAAA2A/knYE08lHypU/video3e312550f115%5B15%5D.jpg
Use this code to get the thumbnails-
Bitmap _bitmap = null;
thumbnail = new ImageView(mContext);
thumbnail.setScaleType(ImageView.ScaleType.CENTER_CROP);
try {
String path = "SOME PATH GOES HERE...";
_bitmap = ThumbnailUtils.createVideoThumbnail(path, MediaStore.Video.Thumbnails.MICRO_KIND);
thumbnail.setImageBitmap(_bitmap);
} catch (Exception e) {
thumbnail.setBackgroundResource(R.drawable.icon);
e.printStackTrace();
};

creating a drawable from sd card to set as a background in android

I am trying to use an image from the sd card and set it as the background for a relativelayout. I have tried other solutions that i have found here and elsewhere but they havent seemed to work for me. here is my code. I have commented out other ways that i have tried and didnt work. the only thing that worked for me was using setBackgroudnResource and using a resource from the app, but this was just to test to make sure mRoot was set up correctly. when I have tried all the other ways, it just doesn't set anything. Anyone know what I am doing wrong, or if there is a better way to do this?
//one way i tired...
//String extDir = Environment.getExternalStorageDirectory().toString();
//Drawable d = Drawable.createFromPath(extDir + "/pic.png");
//mRoot.setBackgroundDrawable(d);
//another way tried..
//Drawable d = Drawable.createFromPath("/sdcard/pic.png");
//mRoot.setBackgroundDrawable(d);
//last way i tried...
mRoot.setBackgroundDrawable(Drawable.createFromPath(new File(Environment.getExternalStorageDirectory(), "pic.png").getAbsolutePath()));
//worked, only to verify mRoot was setup correctly and it could be changed
//mRoot.setBackgroundResource(R.drawable.bkg);
You do not load a drawable from SD card but a bitmap. Here is a method to load it with the reduced sampling (quality) so the program will not complain if the image is too large. Then I guess you need to process this bitmap i.e. crop it and resize for the background.
// Read bitmap from Uri
public Bitmap readBitmap(Uri selectedImage) {
Bitmap bm = null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2; //reduce quality
AssetFileDescriptor fileDescriptor =null;
try {
fileDescriptor = this.getContentResolver().openAssetFileDescriptor(selectedImage,"r");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
finally{
try {
bm = BitmapFactory.decodeFileDescriptor(fileDescriptor.getFileDescriptor(), null, options);
fileDescriptor.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return bm;
}
The Uri here can be supplied from a gallery picker activity.
The image then can be saved into application resources and loaded into an imageView
private void saveBackground(Bitmap Background) {
String strBackgroundFilename = "background_custom.jpg";
try {
Background.compress(CompressFormat.JPEG, 80, openFileOutput(strBackgroundFilename, MODE_PRIVATE));
} catch (Exception e) {
Log.e(DEBUG_TAG, "Background compression and save failed.", e);
}
Uri imageUriToSaveCameraImageTo = Uri.fromFile(new File(BackgroundSettings.this.getFilesDir(), strBackgroundFilename));
// Load this image
Bitmap bitmapImage = BitmapFactory.decodeFile(imageUriToSaveCameraImageTo.getPath());
Drawable bgrImage = new BitmapDrawable(bitmapImage);
//show it in a view
ImageView backgroundView = (ImageView) findViewById(R.id.BackgroundImageView);
backgroundView.setImageURI(null);
backgroundView.setImageDrawable(bgrImage);
}
File file = new File( url.getAbsolutePath(), imageUrl);
if (file.exists()) {
mDrawable = Drawable.createFromPath(file.getAbsolutePath());
}
I suggest checking that the drawable is being loaded correctly. Some things to try:
Try using a different image on the sd card
Put pic.png in R.drawable and make sure mRoot.setBackgroundResource() does what you expect
After loading the drawable, check d.getBounds() to make sure it is what you expect

Categories

Resources