Skip to content

Commit

Permalink
Allow chaining of arbitrary # of transformations
Browse files Browse the repository at this point in the history
Also includes some other cleanup, including
allowing arbitrary downsamplers.
  • Loading branch information
Sam Judd committed Aug 19, 2013
1 parent 4b06daa commit 7a58fe7
Show file tree
Hide file tree
Showing 8 changed files with 240 additions and 102 deletions.
132 changes: 74 additions & 58 deletions library/src/com/bumptech/glide/Glide.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import com.bumptech.glide.loader.stream.StreamLoader;
import com.bumptech.glide.loader.transformation.CenterCrop;
import com.bumptech.glide.loader.transformation.FitCenter;
import com.bumptech.glide.loader.transformation.MultiTransformationLoader;
import com.bumptech.glide.loader.transformation.None;
import com.bumptech.glide.loader.transformation.TransformationLoader;
import com.bumptech.glide.presenter.ImagePresenter;
import com.bumptech.glide.presenter.ImageReadyCallback;
Expand All @@ -32,6 +34,7 @@
import java.io.File;
import java.lang.ref.WeakReference;
import java.net.URL;
import java.util.ArrayList;
import java.util.Map;
import java.util.WeakHashMap;

Expand Down Expand Up @@ -398,22 +401,14 @@ public static class Request<T> {
private Context context;
private Target target;

private enum ResizeOption {
APPROXIMATE,
CENTER_CROP,
FIT_CENTER,
AS_IS,
}

private ModelLoaderFactory<T> modelLoaderFactory;
private final T model;

private int animationId = -1;
private int placeholderId = -1;
private int errorId = -1;
private Transformation transformation = Transformation.NONE;
private Downsampler downsampler = Downsampler.AT_LEAST;
private TransformationLoader<T> transformationLoader = null;
private ArrayList<TransformationLoader<T>> transformationLoaders = new ArrayList<TransformationLoader<T>>();

private Request(T model) {
this(model, GLIDE.getFactory(model));
Expand All @@ -432,77 +427,93 @@ private Request(T model, ModelLoaderFactory<T> factory) {
}

/**
* Resize models using {@link CenterCrop}. Replaces any existing resize style
* Load images at a size near the size of the target using {@link Downsampler#AT_LEAST}.
*
* @see #downsample(com.bumptech.glide.resize.load.Downsampler)
*
* @return This Request
*/
public Request<T> centerCrop() {
transformation = Transformation.CENTER_CROP;
downsampler = Downsampler.AT_LEAST;
transformationLoader = null;

return this;
public Request<T> approximate() {
return downsample(Downsampler.AT_LEAST);
}

/**
* Resize models using {@link FitCenter}. Replaces any existing resize style
* Load images at their original size using {@link Downsampler#NONE}.
*
* @see #downsample(com.bumptech.glide.resize.load.Downsampler)
*
* @return This Request
*/
public Request<T> fitCenter() {
transformation = Transformation.FIT_CENTER;
downsampler = Downsampler.AT_LEAST;
transformationLoader = null;

return this;
public Request<T> asIs() {
return downsample(Downsampler.NONE);
}

/**
* Load images at a size near the size of the target using {@link Downsampler#AT_LEAST}. Replaces any existing resize style
* Load images using the given {@link Downsampler}. Replaces any existing downsampler. Defaults to
* {@link Downsampler#AT_LEAST}
*
* @param downsampler The downsampler
* @return This Request
*/
public Request<T> approximate() {
transformation = Transformation.NONE;
downsampler = Downsampler.AT_LEAST;
transformationLoader = null;
public Request<T> downsample(Downsampler downsampler) {
this.downsampler = downsampler;

return this;
}

/**
* Load images at their original size using {@link Downsampler#NONE}. Replaces any existing
* resize style
* Transform images using {@link com.bumptech.glide.loader.transformation.CenterCrop}.
*
* @see #transform(com.bumptech.glide.loader.transformation.TransformationLoader)
*
* @return This Request
*/
public Request<T> asIs() {
transformation = Transformation.NONE;
downsampler = Downsampler.NONE;
transformationLoader = null;
public Request<T> centerCrop() {
return transform(new CenterCrop<T>());
}

return this;
/**
* Transform images using {@link com.bumptech.glide.loader.transformation.FitCenter}.
*
* @see #transform(com.bumptech.glide.loader.transformation.TransformationLoader)
*
* @return This Request
*/
public Request<T> fitCenter() {
return transform(new FitCenter<T>());
}

/**
* Set an arbitrary transformation to apply after an image has been loaded into memory. Replaces any existing
* resize style
* Set an arbitrary transformation to apply after an image has been loaded into memory.
*
* @see #transform(com.bumptech.glide.loader.transformation.TransformationLoader)
*
* @param transformation The transformation to use
* @return This Request
*/
public Request<T> transform(final Transformation transformation) {
this.transformation = transformation;
downsampler = Downsampler.AT_LEAST;
transformationLoader = null;
return transform(new TransformationLoader<T>() {
@Override
public Transformation getTransformation(T model) {
return transformation;
}

return this;
@Override
public String getId() {
return transformation.getId();
}
});
}

/**
* Transform images with the given {@link TransformationLoader}. Appends this transformation onto any existing
* transformations
*
* @param transformationLoader The loader to obtaian a transformation for a given model
* @return This Request
*/
public Request<T> transform(TransformationLoader<T> transformationLoader) {
this.transformationLoader = transformationLoader;
transformation = null;
downsampler = Downsampler.AT_LEAST;
transformationLoaders.add(transformationLoader);

return this;
}
Expand Down Expand Up @@ -601,7 +612,7 @@ private ImagePresenter<T> getImagePresenter(Target target) {
}

private ImagePresenter<T> buildImagePresenter(Target target) {
transformationLoader = getFinalTransformationLoader();
TransformationLoader<T> transformationLoader = getFinalTransformationLoader();

ImagePresenter.Builder<T> builder = new ImagePresenter.Builder<T>()
.setTarget(target, context)
Expand Down Expand Up @@ -633,23 +644,28 @@ public void onImageReady(Target target, boolean fromCache) {
}

private TransformationLoader<T> getFinalTransformationLoader() {
if (transformationLoader != null) {
return transformationLoader;
} else {
return new TransformationLoader<T>() {
@Override
public Transformation getTransformation(T model) {
return transformation;
}
};
switch (transformationLoaders.size()) {
case 0:
return new None<T>();
case 1:
return transformationLoaders.get(0);
default:
return new MultiTransformationLoader<T>(transformationLoaders);
}
}

private String getFinalTransformationId() {
if (transformationLoader != null) {
return transformationLoader.getClass().toString();
} else {
return transformation.getId();
switch (transformationLoaders.size()) {
case 0:
return Transformation.NONE.getId();
case 1:
return transformationLoaders.get(0).getId();
default:
StringBuilder sb = new StringBuilder();
for (TransformationLoader transformationLoader : transformationLoaders) {
sb.append(transformationLoader.getId());
}
return sb.toString();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,9 @@ public class CenterCrop<T> implements TransformationLoader<T>{
public Transformation getTransformation(T model) {
return Transformation.CENTER_CROP;
}

@Override
public String getId() {
return Transformation.CENTER_CROP.getId();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,9 @@ public class FitCenter<T> implements TransformationLoader<T> {
public Transformation getTransformation(T model) {
return Transformation.FIT_CENTER;
}

@Override
public String getId() {
return Transformation.FIT_CENTER.getId();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.bumptech.glide.loader.transformation;

import android.graphics.Bitmap;
import com.bumptech.glide.resize.bitmap_recycle.BitmapPool;
import com.bumptech.glide.resize.load.Transformation;

/**
* A transformation that applies an ordered array of one or more transformations to an image
*/
public class MultiTransformation extends Transformation {
private final Transformation[] transformations;

public MultiTransformation(Transformation... transformations) {
if (transformations.length < 1) {
throw new IllegalArgumentException("MultiTransformation must contain at least one Transformation");
}
this.transformations = transformations;
}

@Override
public Bitmap transform(Bitmap bitmap, BitmapPool pool, int outWidth, int outHeight) {
Bitmap current = null; //we don't want to recycle the original image since that
//will be done by the ImageResizer
Bitmap transformed;
for (Transformation transformation : transformations) {
transformed = transformation.transform(bitmap, pool, outWidth, outHeight);
if (current != null && current != transformed) {
pool.put(current);
}

current = transformed;
}
return current;
}

@Override
public String getId() {
StringBuilder sb = new StringBuilder();
for (Transformation transformation : transformations) {
sb.append(transformation.getId());
}
return sb.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.bumptech.glide.loader.transformation;

import com.bumptech.glide.resize.load.Transformation;

import java.util.Arrays;
import java.util.List;

/**
* A TransformationLoader that uses an ordered list of one or more transformation loaders to produce
* a single transformation that applies each of the {@link Transformation}s produced by the loaders
* in order.
*/
public class MultiTransformationLoader<T> implements TransformationLoader<T> {
private final List<TransformationLoader<T>> transformationLoaders;

@SuppressWarnings("unused")
public MultiTransformationLoader(TransformationLoader<T>... transformationLoaders) {
this(Arrays.asList(transformationLoaders));
}

public MultiTransformationLoader(List<TransformationLoader<T>> transformationLoaders) {
if (transformationLoaders.size() < 1) {
throw new IllegalArgumentException("MultiTransformationLoader must contain at least one " +
"TransformationLoader");
}
this.transformationLoaders = transformationLoaders;
}

@Override
public Transformation getTransformation(T model) {
int num = transformationLoaders.size();
Transformation[] transformations = new Transformation[num];
for (int i = 0; i < num; i++) {
transformations[i] = transformationLoaders.get(i).getTransformation(model);
}

return new MultiTransformation(transformations);
}

@Override
public String getId() {
StringBuilder sb = new StringBuilder();
for (TransformationLoader<T> transformationLoader : transformationLoaders) {
sb.append(transformationLoader.getId());
}
return sb.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,9 @@ public class None<T> implements TransformationLoader<T> {
public Transformation getTransformation(T model) {
return Transformation.NONE;
}

@Override
public String getId() {
return Transformation.NONE.getId();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,11 @@ public interface TransformationLoader<T> {
* @return A new or static (if the transformation is type/model agnostic) {@link Transformation}
*/
public Transformation getTransformation(T model);

/**
* Get a unique identifier for this TransformationLoader.
*
* @return A unique String identifier
*/
public String getId();
}
Loading

0 comments on commit 7a58fe7

Please sign in to comment.