Skip to content

Instantly share code, notes, and snippets.

@kamikat
Last active August 29, 2015 14:04
Show Gist options
  • Save kamikat/fc526be4a24abab0c6eb to your computer and use it in GitHub Desktop.
Save kamikat/fc526be4a24abab0c6eb to your computer and use it in GitHub Desktop.
RoboSpice image thumbnail request handling EXIF data of input file
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.media.ExifInterface;
import java.io.File;
public class ImageThumbnailRequest extends ThumbnailRequest {
BitmapFactory.Options mOptions;
public ImageThumbnailRequest(File file) {
this(file, SIZE_AUTO, SIZE_AUTO);
}
public ImageThumbnailRequest(File file, int width, int height) {
super(file, width, height);
}
public Bitmap loadDataFromNetwork() throws Exception {
mOptions = new BitmapFactory.Options();
mOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(getFile().getAbsolutePath(), mOptions);
mOptions.inJustDecodeBounds = false;
// obtain EXIF transformation matrix from file
ExifInterface exif = new ExifInterface(getFile().getAbsolutePath());
Matrix matxif = getExifTransformMatrix(exif);
// get dimension of source bitmap and transform dimension with EXIF information
float[] dimen = { mOptions.outWidth, mOptions.outHeight };
matxif.mapPoints(dimen);
mOptions.inSampleSize = calculateInSampleSize(Math.abs(dimen[0]), Math.abs(dimen[1]));
// decode thumbnail bitmap file into memory
Bitmap bmp = BitmapFactory.decodeFile(getFile().getAbsolutePath(), mOptions);
RectF srcRect = new RectF(0, 0, bmp.getWidth(), bmp.getHeight());
RectF dstRect = new RectF();
matxif.mapRect(dstRect, srcRect);
// create a new bitmap to draw thumbnail with EXIF transformed
Bitmap decorated = Bitmap.createBitmap(
Math.round(dstRect.width()),
Math.round(dstRect.height()),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(decorated);
// pre-processing
preDraw(canvas);
// relocate anchor for the canvas
canvas.translate(-dstRect.left, -dstRect.top);
canvas.concat(matxif);
// draw thumbnail bitmap
canvas.drawBitmap(bmp, null, srcRect, new Paint() {{
setAntiAlias(true);
setFilterBitmap(false);
setDither(false);
}});
// clear matrix
canvas.setMatrix(null);
// post-processing
postDraw(canvas);
// should better gc now
canvas.setBitmap(null);
System.gc();
return decorated;
}
/**
* draw background on to thumbnail canvas (white background by default for JPEG bitmap thumbnail caching)
* @param canvas
*/
public void preDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
}
/**
* draw objects overlaid on source image (default none)
* @param canvas
*/
public void postDraw(Canvas canvas) { }
/**
* use this interface to configure bitmap decode parameters
* the class will take care of inSampleSize and inJustDecodeBound by itself,
* so put other settings here.
*
* @param options
* options passed to BitmapFactory.decodeFile
*/
public void setDecodeOptions(BitmapFactory.Options options) {
mOptions = options;
}
private Matrix getExifTransformMatrix(ExifInterface exif) {
Matrix matrix = new Matrix();
switch(exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)) {
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
matrix.postRotate(180);
break;
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
matrix.postScale(1, -1);
break;
case ExifInterface.ORIENTATION_TRANSPOSE:
matrix.postRotate(90);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_90:
matrix.postRotate(90);
break;
case ExifInterface.ORIENTATION_TRANSVERSE:
matrix.postScale(-1, -1);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
matrix.postRotate(270);
break;
}
return matrix;
}
}
import android.graphics.Bitmap;
import com.octo.android.robospice.request.SpiceRequest;
import java.io.File;
public abstract class ThumbnailRequest extends SpiceRequest<Bitmap> {
public static final int SIZE_AUTO = -1;
protected File mFile;
protected int mWidth;
protected int mHeight;
public ThumbnailRequest(File file) {
this(file, SIZE_AUTO, SIZE_AUTO);
}
public ThumbnailRequest(File file, int width, int height) {
super(Bitmap.class);
mFile = file;
mWidth = width;
mHeight = height;
}
public File getFile() {
return mFile;
}
protected int calculateInSampleSize(float width, float height) {
if (height > mHeight || width > mWidth) {
if ( mWidth == -1 && mHeight == -1) {
return 1;
}
if (mWidth == -1) {
return Math.round(height / (float) mHeight);
}
if (mHeight == -1) {
return Math.round(width / (float) mWidth);
}
if (width < height) {
return Math.round(width / (float) mWidth);
} else {
return Math.round(height / (float) mHeight);
}
} else {
return 1;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment