Google Image Proxy
Continuing with app that I created as a project for the Udacity Android Nanodegree program, I faced a new challenge! The challenge was to load poster images from TMDb Image server inside my app!
Is it even a challenge? One could say that I could’ve simply used a library like Picasso or Glide to offload image loading to the tried and trusted tools. But my main challenge was not just to load the image but to load the perfect image.
And that means the image should fit-well into ImageView
without much need to resize and/or scale it, and thus, giving a crisp and sharp look and improving
UX.
So, what’s the big deal? Why don’t I just use the different bucket sizes (w185
, w300
, etc.) that TMDb offers?
The thing is that the aspect size of the images served by TMDb is a bit weird (IMO!). For example, for the w185
bucket, the image served has an aspect ratio of 185:278
!
What can be done? Well, the only thing we can do is to download a bigger image (from original
bucket) and resize it on device. But that’s a total no-go because the original
image is too large (2000x3000
) and would consume signifacntly more resources. And also, performing resize on user’s device is not a good idea!
What I initally thought was to setup a Thumbor server. But I quickly dropped the idea because then I would have to maintain the server (which I didn’t want) for the (atleast) lifetime of the project or else the app would simply not work!
This led me to search for open, free and hosted alternatives. Although, I couldn’t find a trustworthy solution, what I found was this Gist. In the Gist, the author reverse engineered (sort of) the URL for the Google Image proxy and the required parameters and leveraged it as a caching and resizing proxy to serve his images!
Cool! how to use that in the project app? Simple! create the primary TMDb image url, append it as a parameter to the Google Image Proxy url and load the resulting url into the ImageView
using your favorite library!
So, here’s a Utility class that I created to handle the stuff!
public final class ImageUtils {
private ImageUtils(){
/* ¯\_(ツ)_/¯ */
}
// Google's image caching and resizing proxy
private static final String GOOGLE_CACHE_BASE =
"https://images1-focus-opensocial.googleusercontent.com/gadgets/proxy";
/**
* Create base tmdb url
*/
@NonNull private static String tmdbUrl(@NonNull String poster){
return String.format(
"%s/original%s",
// or however you get the base url...
BuildConfig.TMDB_IMAGE_BASE,
poster);
}
/**
* Calculate aspect
*/
public static int aspect(int width, int height) {
return height / width;
}
/**
* Calculate the other dimension (either height or width)
* given one dimension and an aspect
*
* Use as: calculateOtherDimension(aspect(4, 3), 400) -> 300
*
* @param aspect aspect ratio
* @param dimension measurement of one dimension
*/
public static int calculateOtherDimension(int aspect, int dimension){
return aspect * dimension;
}
@NonNull public static String createTmdbImageUrl(
@NonNull String poster,
int height,
int width){
return Uri.parse(GOOGLE_CACHE_BASE).buildUpon()
.appendQueryParameter("container", "focus")
.appendQueryParameter("resize_h", "" + height)
.appendQueryParameter("resize_w", "" + width)
.appendQueryParameter("url", tmdbUrl(poster))
.toString();
}
}
Now to use it, just call it as
import static ImageUtils.*;
// ...
createTmdbImageUrl(
movie.getPoster(),
300 /* height */,
calculateOtherDimension(aspect(2 /*w*/, 3 /*h*/), 300)
);
//...
And that’s it! Using this you can load image of any aspect that you need and deliver a crispier and sharper experience to your users. But, I’d sincerely like to request to you to only use this for small, open source projects so that you don’t need to maintain a server! If you are developing a closed-source business application, than it would be much better to use something like Thumbor or ImageProxy as they are dedicated solutions and provide more features!