Create a gist now

Instantly share code, notes, and snippets.

Embed
@TargetApi(Build.VERSION_CODES.KITKAT)
static class DocumentExifTransformation implements Transformation {
private static final String[] CONTENT_ORIENTATION = new String[] {
MediaStore.Images.ImageColumns.ORIENTATION
};
final Context context;
final Uri uri;
DocumentExifTransformation(Context context, Uri uri) {
this.context = context;
this.uri = uri;
}
@Override public Bitmap transform(Bitmap source) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return source;
if (!DocumentsContract.isDocumentUri(context, uri)) return source;
int exifRotation = getExifOrientation(context, uri);
if (exifRotation != 0) {
Matrix matrix = new Matrix();
matrix.preRotate(exifRotation);
Bitmap rotated =
Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
if (rotated != source) {
source.recycle();
}
return rotated;
}
return source;
}
@Override public String key() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return "documentTransform()";
return "documentExifTransform(" + DocumentsContract.getDocumentId(uri) + ")";
}
static int getExifOrientation(Context context, Uri uri) {
ContentResolver contentResolver = context.getContentResolver();
Cursor cursor = null;
try {
String id = DocumentsContract.getDocumentId(uri);
id = id.split(":")[1];
cursor = contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
CONTENT_ORIENTATION, MediaStore.Images.Media._ID + " = ?", new String[] { id }, null);
if (cursor == null || !cursor.moveToFirst()) {
return 0;
}
return cursor.getInt(0);
} catch (RuntimeException ignored) {
// If the orientation column doesn't exist, assume no rotation.
return 0;
} finally {
if (cursor != null) {
cursor.close();
}
}
}
}
@lauren7249

This comment has been minimized.

Show comment
Hide comment
@lauren7249

lauren7249 Jul 10, 2014

cool. what is the Transformation interface?

cool. what is the Transformation interface?

@dnkoutso

This comment has been minimized.

Show comment
Hide comment
@dnkoutso

dnkoutso Jul 14, 2014

Picasso allows to pass in custom transformations for your loading task. You can apply anything you want such as crop the image, add effects, color overlay etc.

Owner

dnkoutso commented Jul 14, 2014

Picasso allows to pass in custom transformations for your loading task. You can apply anything you want such as crop the image, add effects, color overlay etc.

@NemSim

This comment has been minimized.

Show comment
Hide comment
@NemSim

NemSim Apr 6, 2016

Thanks for writing this class up! It's helping me a great deal so far.

Something to look out for, I had to update the key method to guard against non-document IDs:

@Override
public String key() {
        if ((Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) || 
                !DocumentsContract.isDocumentUri(context, uri)) return "documentTransform()";
        return "documentExifTransform(" + DocumentsContract.getDocumentId(uri) + ")";
    }

NemSim commented Apr 6, 2016

Thanks for writing this class up! It's helping me a great deal so far.

Something to look out for, I had to update the key method to guard against non-document IDs:

@Override
public String key() {
        if ((Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) || 
                !DocumentsContract.isDocumentUri(context, uri)) return "documentTransform()";
        return "documentExifTransform(" + DocumentsContract.getDocumentId(uri) + ")";
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment