0

I am working on a dynamic thumbnail service based on thumbor which will provide any size thumbnail for given image and will cache it. Ideally I would like to constrain sizes of thumbnails so that cache will be effective and I can pre-cache those size images. Ideally different types of image sizes to be pre-cached should be calculated based on screen density, screen size and network speed so that android will request suitable size image.

I would like to know how to calculate multiple dimensions of images to be pre-cached and how to decide on android which size image to get.

Brute force way is to not to constrain image sizes and just ask for image with width equal to screen width in pixels but will be waste of cache since even minor difference in screen widths of two devices will need different size images to be cached.

based on screen configuration chart in this url, I can cache images of all widths specified in this chart. On runtime, I can calculate which row and column in this chart current device fits based on these links Get screen size, Get screen dpi

Community
  • 1
  • 1
pratsJ
  • 3,369
  • 3
  • 22
  • 41

2 Answers2

2

Two things will help you:

  1. Define the height and width of your ImageView that will contain the thumbnail as dimension resources
  2. When it comes time to determine the size of the image to fetch, convert those dimension resources to pixel values

So, for example, if you're using an ImageView to display thumbnails of size 64x64 dp, define dimension resources like this:

<dimen name="thumbnail_height">64dp</dimen>
<dimen name="thumbnail_width">64dp</dimen>

Use those value in the layout that contains the ImageView:

<ImageView
    ....
    android:layout_height="@dimen/thumbnail_height"
    android:layout_width="@dimen/thumbnail_width"
    />

Then, at runtime, to turn those into raw pixel values for the device:

int height = getResources().getDimensionPixelSize(R.dimen.thumbnail_height);
int width = getResources().getDimensionPixelSize(R.dimen.thumbnail_width);

Now you can use height and width to tell the dynamic thumbnail service how to create the thumbnail image that looks best for the device at hand.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
  • Most of the images are fill width images hence image width equals screen width. But since there is so much device fragmentation in android, my thumbnail service cache will need to store images of all possible widths as there are no of android devices in worst case which is what I am trying to avoid hence creating bucket with handful of fixed widths and on runtime I can calculate which of these buckets my current device fits in and can ask for thumbnail of that size. – pratsJ Apr 23 '16 at 18:53
  • So need a good algo to decide possible widths to store and runtime calculation of which bucket current device falls in based on screen density and size – pratsJ Apr 23 '16 at 18:53
  • "Thumbnail" and "full screen image" seem to me to be conflicting concepts. If you're trying to fill a screen, that doesn't sound like a thumbnail at all. Anyway, do you have a particular absolute requirement that the downloaded image must absolutely be exactly the size of the screen in raw pixels? If someone has state this requirement, you might want to look into getting that relaxed so you can approach this from a more reasonable perspective. – Doug Stevenson Apr 23 '16 at 19:08
  • Yeah my bad. Its downsized image. No requirement as such. Just trying to optimize of network requests being made, initial load time of image and number of images I have to save in server side cache – pratsJ Apr 23 '16 at 19:12
  • Well, you only have to fetch and store the images that are appropriate for the single device that's running the app, not all the images that you'd use for all devices. So if you want to look at the size of the screen and use that for everything, that would be OK. But then you'd be downloading some really huge images for xxhdpi devices, at probably no real benefit. – Doug Stevenson Apr 23 '16 at 19:29
  • Yeah I will only fetch image that is suitable for current device and thumbnail size would never exceed original image size so huge image problem isnt getting worse since anyway I will have to get original image. I implemented method mentioned in questions and working well now. Thanks. – pratsJ Apr 23 '16 at 21:37
1

You can use Picasso or Glide for your purpose they handle resizing and this libraries handle caching of image automatically. For example for a thumbnail of size 600x200 :-

Loading and caching thumbnail with Picasso of exact imageView size

Picasso
    .with(context)
    .load("your_image_your")
    .resize(600, 200) // resizes the image to these dimensions (in pixel)
    .centerCrop() 
    .into(imageViewThumbnail);

Loading and caching thumbnail with Glide of exact imageView Size

 Glide
    .with(context)
    .load("your_image_your")
    .override(600, 200) // resizes the image to these dimensions (in pixel)
    .centerCrop() // this cropping technique scales the image so that it fills the requested bounds and then crops the extra.
    .into(imageViewThumbnail);

Thing to note here is though both libraries does resizing of image but caching is different :-

whatever the size is, Picasso will cache only single size of image, the full-size one.

Glide acts differently, caches separate file for each size of ImageView. Although an image has already been loaded once but if you need to load another size the same image, it needs to be downloaded once again before be resized to the right resolution and then be cached.

So for your use case I will suggest you to use Glide (more about Glide vs Picasso)

Hitesh Sahu
  • 41,955
  • 17
  • 205
  • 154
  • I am already using glide. However it still need to do network request for full size image which is what I want to avoid. Also first time image is displayed, it will also take time to fetch fill size image hence slower loading of images. – pratsJ Apr 23 '16 at 18:49
  • Also I am talking about server side cache rather than android side – pratsJ Apr 23 '16 at 18:54