Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Thumbnail images #168

Closed
chrismyer opened this issue May 7, 2020 · 20 comments
Closed

Thumbnail images #168

chrismyer opened this issue May 7, 2020 · 20 comments
Labels
enhancement New feature or request

Comments

@chrismyer
Copy link

chrismyer commented May 7, 2020

Hi, this package is unusable if someone wants to implement their own camera roll because the image sizes returned are huge, causing a very noticeable sluggish performance degradation when loading lots of images into FlatList. It would be great to have smaller thumbnail image sizes returned in addition to the regular full size images. Thanks!

react-native-image-resizer is not a valid workaround since it takes a long time to process images.

Similar to #110

@bartolkaruza
Copy link
Collaborator

Hey there, this is a useful addition to the library and I would be happy to take PR's solving the problem of resizing the images (or retrieving at a smaller size).

@dokkis
Copy link
Contributor

dokkis commented May 13, 2020

I agree this is a must to have for such library and solution based on generating the thumbnail are not good for performance. I looked into it a little bit, for Android we could use:

https://developer.android.com/reference/android/provider/MediaStore.Images.Thumbnails.html

It's deprecated starting from API Level 29 but it's available from API Level 1.
Return thumbnail representing a specific image item. If a thumbnail doesn't exist, this method will block until it's generated. Callers are responsible for their own in-memory caching of returned values.. Interesting thread on stackoverflow here: https://stackoverflow.com/questions/32782085/querying-the-mediastore-joining-thumbnails-and-images-on-id

For iOS it looks like PHCachingImageManager should be used An object that facilitates retrieving or generating preview thumbnails, optimized for batch preloading large numbers of assets.: https://developer.apple.com/documentation/photokit/phcachingimagemanager

@dokkis
Copy link
Contributor

dokkis commented May 24, 2020

@bartolkaruza @noobvim I am trying to look into this improvement, I tried several methods to generate or get existing thumbnail (only in Android and for images, for now):

Performance are observed on Xiaomi Mi A1.

  1. ThumbnailUtils.extractThumbnail (around 70ms, this generated the thumbnail), could always return a base64 thumbnail
  2. Images.Thumbnails.getThumbnail (around 10/20ms, should fetch an existing thumbnail), could return a base64 thumbnail (or null if is not yet generated)
  3. MediaStore.Images.Thumbnails.queryMiniThumbnail (around 5/10ms, it fetches an existing thumbnail), could return the URI of an existing thumbnail (or null if is not yet generated)

Given that I not sure how to easy drop those down, I am wondering if makes more sense having a separate experimental API for fetching the thumbnail, e.g. getPhotoThumbnail.
I don't know how react-native parallelise components, but for example if you try to load 100 components that has an Image that tries to call getPhotoThumbnail(mediaId/mediaUri) is it better than having all embedded into a much slower getPhoto API? Or a getPhotoThumbnails with a list of media to load.

I can also try to optimise by trying to get all thumbnails with one single query/cursor, aggregating first mediaId then try to query once by filtering for those id. This might drop latency in Android but I still not sure about iOS implementation.

@bartolkaruza
Copy link
Collaborator

I really like the getPhotoThumbnails direction. Considering the UI pattern for thumbnails, most likely apps will retrieve many more thumbnails than actual photos, making the retrieving of photos an unnecessary load in those scenario's. Apps can then retrieve individual photos (potentially with slow metadata) through the already optimised getPhotos for the scenario's where they need those.

I suppose it will be a much simpler implementation for the actual retrieval of the thumbnails, at the cost of potentially duplicating some of the logic between getPhotos and getPhotoThumbnails. How does that sound?

@gran33
Copy link

gran33 commented Jun 1, 2020

I think that getPhotoThumbnails isn't a good API.
Return the thumbnail uri for any use-case of getPhotos.
The user will decide whether to use the thumbnail or the original photo.
In this way, the user doesn't need to re-ask the photos again.

@bartolkaruza
Copy link
Collaborator

bartolkaruza commented Jun 8, 2020

I think that getPhotoThumbnails isn't a good API.
Return the thumbnail uri for any use-case of getPhotos.
The user will decide whether to use the thumbnail or the original photo.
In this way, the user doesn't need to re-ask the photos again.

I agree that the API would be nicer to add them to getPhotos from a theoretical point of view, but the performance hit is just too big for this trade off. The thumbnail needs to be generated, which consumes resources unnecessarily.

@gran33 we've had a lot of performance complaints when adding similar resource consuming features on this method, like this one: #175 I'd rather not go in a circle of adding the feature then removing it behind a flag again later, can you understand this point of view?

@dokkis
Copy link
Contributor

dokkis commented Jul 8, 2020

@gran33 I agree having in getPhotos would be better but performance-wise is not a good idea.

@bartolkaruza I might coming back to this. A getPhotoThumbnails might be trickier to implement when something fails for some reason, what do you return and how to handle partial failures? To keep it simple for now, we can improve it later or add another API later, I am thinking a simple getPhotoThumbnail API that looks like following:

type ThumbnailSize = [number, number];

export type PhotoThumbnailOptions = {
   allowNetworkAccess: boolean, // iOS only
   targetSize: ThumbnailSize,
   quality: number,
 };
 
 export type PhotoThumbnail = {
   thumbnailBase64: string,
 };

function getPhotoThumbnail(uri: string, options: PhotoThumbnailOptions): Promise<PhotoThumbnail>;

allowNetworkAccess might be useful in iOS as the API that we can use has this flag, and you might want to deny to go to cloud to generate the thumbnail, if the photo is on iCloud, device should still have some small representation locally. targetWidth and targetHeight because on iOS or in general the API might not return exact size but something closer to what you request. Quality is jpeg quality to eventually compress if you want a lighter thumbnailBase64.

Additionally, in iOS PHCachingImageManager exists to optimise fetching of multiple assets (useful when you render the gallery in a grid): https://developer.apple.com/documentation/photokit/phcachingimagemanager
We can think of having in the getPhotos API the following parameter:

prepareThumbnails?: ThumbnailSize

So we can warm-up the PHCachingImageManager when this parameter is populated in iOS, so consequent getPhotoThumbnail might already have the image cached if requested with the same ThumbnailSize.

What do you think?

@tvpranav
Copy link

@dokkis Any updates on thumbnail part ?

@anhquan291
Copy link

Hi, this package is unusable if someone wants to implement their own camera roll because the image sizes returned are huge, causing a very noticeable sluggish performance degradation when loading lots of images into FlatList. It would be great to have smaller thumbnail image sizes returned in addition to the regular full size images. Thanks!

react-native-image-resizer is not a valid workaround since it takes a long time to process images.

Similar to #110

I'm having the same problem, the images load slowly even just only 100 :D. It takes like 2-3 seconds. It is sad.
Any suggestion for custom Gallery selection? Thanks everyone

@javascripter
Copy link

javascripter commented Oct 10, 2021

For those who need a quick production fix, you can use MediaLibrary.getAssetsAsync() from expo-media-library. It returns assets array that contain uri prop which is a thumbnail uri on iOS. I observed a significant performance boost with it. You can use like this

const { assets } = await MediaLibrary.getAssetsAsync()
<Image source={{ uri: asset[0].uri }} />

// for full (downloaded) image, you can use assetWithInfo.localUri
const assetWithInfo = await MediaLibrary.getAssetInfoAsync(asset[0].id)

expo/expo#8541 (comment)
expo-media-library requires react-native-unimodules in bare RN, so the setup is a bit heavy.

I think, for API, we can use expo-media-library as a reference for this package too :)

@sgtpsibin
Copy link

any updates on this feature?, i think this will be great feature for render camera roll photo in a grid (very popular case).

@PierreCapo
Copy link

@bartolkaruza If eventually I work on a PR for such a feature, would you be ok to merge it into this library? (Just to be sure I don't work for nothing 😀)

@Arjan-Zuidema
Copy link
Collaborator

Hi @PierreCapo!

@bartolkaruza is currently not an active maintainer. Me and some others are now the active maintainers.
I am happy to review and merge any PR.

Thanks for working on this!

@PierreCapo
Copy link

Awesome, thanks for your fast response 👍

@HERYORDEJY
Copy link

@PierreCapo Thumbnail for videos too would be appreciated

@HERYORDEJY
Copy link

@Arjan-Zuidema I am unable to get Video from the device, only Photos. Even if I set assetType to 'All', only Photos are retrieved. I really need help on this, been on it for almost a week, for a task I should have completed in 3 hours.

@github-actions
Copy link

github-actions bot commented Sep 8, 2023

This issue is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 10 days.

@github-actions github-actions bot added the Stale label Sep 8, 2023
@github-actions
Copy link

This issue was closed because it has been stalled for 10 days with no activity.

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Sep 18, 2023
@jp-23 jp-23 mentioned this issue Sep 21, 2023
4 tasks
@jp-23
Copy link
Contributor

jp-23 commented Sep 26, 2023

I created a PR (536) to add a getPhotoThumbnail method - for iOS only right now.

@bartolkaruza want to take a look?

@Arjan-Zuidema
Copy link
Collaborator

Hi @jp-23

I will take a look at the end of the week. Sorry, really busy now :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests