square/picasso — pull request #613 by piki (2014-08-11 20:32:54+00:00)
Title: add a custom resizing function

I have a fairly straightforward use case that I couldn't find a good way to implement with Picasso, so I added a new `resizer` stage to the decoding pipeline.

The use case is: display images as a column of ImageViews in a ListView, with all images scaled to no-larger-than the ListView's width, while preserving aspect ratio. ImageView heights are sized based on the images Picasso loads into them, rather than the other way around. Think web browser, messaging app, or chat room.

A custom transformation can sort of implement this, but not well enough. Some of the images are pretty big, up to 10 megapixels, which means that merely creating the Bitmap to transform takes 20-40MB of RAM per image. Even if that Bitmap is scaled down and recycled, it's a waste of RAM and CPU to create it full-scale. Doing a whole column of these thrashes the GC, then starts failing image loads with OOM, then eventually crashes the whole app with OOM. I want to scale the images at `decode` time, not `transform` time, but without knowing the exact width and height up front.

So what I want is the ability to pick image bounds after the image is retrieved and its inherent (full-size) bounds are known, but before it is actually decoded into a Bitmap.

Rather than build something specific to my fit-to-width use case -- e.g., `resize(maxImageWidth, -1)` -- I generalized. I added a new function to the fluent builder pipeline, `resizer`, to specify a dynamic resizing function. Here's how it works:

```
Resizer fitWidth = new Resizer() {
@Override
public Point resize(int width, int height) {
if (width <= maxImageWidth) return null; // small enough; don't increase the size
float scaleRatio = maxImageWidth / (float)width;
int newWidth = (int)(width * scaleRatio);
int newHeight = (int)(height * scaleRatio);
return new Point(newWidth, newHeight);
}
};
Picasso.with(context).load(imageUrl).resizer(fitWidth).error(R.drawable.img_broken).into(ivBody);
```

I believe this would be useful for https://github.com/square/picasso/issues/226.