Merge "Fix can't create thumbnail and wrong orientation issue" into qt-dev

This commit is contained in:
TreeHugger Robot
2019-05-02 05:01:15 +00:00
committed by Android (Google) Code Review
3 changed files with 90 additions and 7 deletions

View File

@@ -16,6 +16,8 @@
package android.content;
import static android.provider.DocumentsContract.EXTRA_ORIENTATION;
import android.accounts.Account;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -40,6 +42,7 @@ import android.graphics.Bitmap;
import android.graphics.ImageDecoder;
import android.graphics.ImageDecoder.ImageInfo;
import android.graphics.ImageDecoder.Source;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
@@ -56,6 +59,7 @@ import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.system.Int32Ref;
import android.text.TextUtils;
import android.util.EventLog;
import android.util.Log;
@@ -3563,9 +3567,14 @@ public abstract class ContentResolver implements ContentInterface {
// Convert to Point, since that's what the API is defined as
final Bundle opts = new Bundle();
opts.putParcelable(EXTRA_SIZE, Point.convert(size));
final Int32Ref orientation = new Int32Ref(0);
return ImageDecoder.decodeBitmap(ImageDecoder.createSource(() -> {
return content.openTypedAssetFile(uri, "image/*", opts, signal);
Bitmap bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(() -> {
final AssetFileDescriptor afd = content.openTypedAssetFile(uri, "image/*", opts,
signal);
final Bundle extras = afd.getExtras();
orientation.value = (extras != null) ? extras.getInt(EXTRA_ORIENTATION, 0) : 0;
return afd;
}), (ImageDecoder decoder, ImageInfo info, Source source) -> {
decoder.setAllocator(allocator);
@@ -3581,6 +3590,20 @@ public abstract class ContentResolver implements ContentInterface {
decoder.setTargetSampleSize(sample);
}
});
// Transform the bitmap if requested. We use a side-channel to
// communicate the orientation, since EXIF thumbnails don't contain
// the rotation flags of the original image.
if (orientation.value != 0) {
final int width = bitmap.getWidth();
final int height = bitmap.getHeight();
final Matrix m = new Matrix();
m.setRotate(orientation.value, width / 2, height / 2);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, m, false);
}
return bitmap;
}
/** {@hide} */

View File

@@ -36,6 +36,7 @@ import android.graphics.Bitmap;
import android.graphics.ImageDecoder;
import android.graphics.Point;
import android.media.ExifInterface;
import android.media.MediaFile;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -1698,6 +1699,18 @@ public final class DocumentsContract {
} catch (IOException e) {
}
// Use ImageDecoder to do full image decode of heif format file
// will have right orientation. So, we don't need to add orientation
// information into extras.
final String mimeType = MediaFile.getMimeTypeForFile(file.getName());
if (mimeType.equals("image/heif")
|| mimeType.equals("image/heif-sequence")
|| mimeType.equals("image/heic")
|| mimeType.equals("image/heic-sequence")) {
return new AssetFileDescriptor(pfd, 0 /* startOffset */,
AssetFileDescriptor.UNKNOWN_LENGTH, null /* extras */);
}
return new AssetFileDescriptor(pfd, 0, AssetFileDescriptor.UNKNOWN_LENGTH, extras);
}

View File

@@ -244,30 +244,77 @@ public class ThumbnailUtils {
final Resizer resizer = new Resizer(size, signal);
final String mimeType = MediaFile.getMimeTypeForFile(file.getName());
Bitmap bitmap = null;
ExifInterface exif = null;
int orientation = 0;
// get orientation
if (MediaFile.isExifMimeType(mimeType)) {
exif = new ExifInterface(file);
switch (exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0)) {
case ExifInterface.ORIENTATION_ROTATE_90:
orientation = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
orientation = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
orientation = 270;
break;
}
}
boolean isHeifFile = false;
if (mimeType.equals("image/heif")
|| mimeType.equals("image/heif-sequence")
|| mimeType.equals("image/heic")
|| mimeType.equals("image/heic-sequence")) {
isHeifFile = true;
try (MediaMetadataRetriever retriever = new MediaMetadataRetriever()) {
retriever.setDataSource(file.getAbsolutePath());
return retriever.getThumbnailImageAtIndex(-1,
bitmap = retriever.getThumbnailImageAtIndex(-1,
new MediaMetadataRetriever.BitmapParams(), size.getWidth(),
size.getWidth() * size.getHeight());
} catch (RuntimeException e) {
throw new IOException("Failed to create thumbnail", e);
}
} else if (MediaFile.isExifMimeType(mimeType)) {
final ExifInterface exif = new ExifInterface(file);
}
if (bitmap == null && exif != null) {
final byte[] raw = exif.getThumbnailBytes();
if (raw != null) {
return ImageDecoder.decodeBitmap(ImageDecoder.createSource(raw), resizer);
try {
bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(raw), resizer);
} catch (ImageDecoder.DecodeException e) {
Log.w(TAG, e);
}
}
}
// Checkpoint before going deeper
if (signal != null) signal.throwIfCanceled();
return ImageDecoder.decodeBitmap(ImageDecoder.createSource(file), resizer);
if (bitmap == null) {
bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(file), resizer);
// Use ImageDecoder to do full image decode of heif format file
// will have right orientation. Don't rotate the bitmap again.
if (isHeifFile) {
return bitmap;
}
}
// Transform the bitmap if the orientation of the image is not 0.
if (orientation != 0 && bitmap != null) {
final int width = bitmap.getWidth();
final int height = bitmap.getHeight();
final Matrix m = new Matrix();
m.setRotate(orientation, width / 2, height / 2);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, m, false);
}
return bitmap;
}
/**