diff options
Diffstat (limited to 'java/com/android/dialer/callcomposer/camera/ImagePersistTask.java')
-rw-r--r-- | java/com/android/dialer/callcomposer/camera/ImagePersistTask.java | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/java/com/android/dialer/callcomposer/camera/ImagePersistTask.java b/java/com/android/dialer/callcomposer/camera/ImagePersistTask.java new file mode 100644 index 000000000..150009495 --- /dev/null +++ b/java/com/android/dialer/callcomposer/camera/ImagePersistTask.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.dialer.callcomposer.camera; + +import android.annotation.TargetApi; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.net.Uri; +import android.os.Build.VERSION_CODES; +import android.support.v4.content.FileProvider; +import com.android.dialer.callcomposer.camera.exif.ExifInterface; +import com.android.dialer.callcomposer.camera.exif.ExifTag; +import com.android.dialer.callcomposer.util.CopyAndResizeImageTask; +import com.android.dialer.common.Assert; +import com.android.dialer.common.FallibleAsyncTask; +import com.android.dialer.constants.Constants; +import com.android.dialer.util.DialerUtils; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** Persisting image routine. */ +@TargetApi(VERSION_CODES.M) +public class ImagePersistTask extends FallibleAsyncTask<Void, Void, Uri> { + private int mWidth; + private int mHeight; + private final float mHeightPercent; + private final byte[] mBytes; + private final Context mContext; + private final CameraManager.MediaCallback mCallback; + + ImagePersistTask( + final int width, + final int height, + final float heightPercent, + final byte[] bytes, + final Context context, + final CameraManager.MediaCallback callback) { + Assert.checkArgument(heightPercent >= 0 && heightPercent <= 1); + Assert.isNotNull(bytes); + Assert.isNotNull(context); + Assert.isNotNull(callback); + mWidth = width; + mHeight = height; + mHeightPercent = heightPercent; + mBytes = bytes; + mContext = context; + mCallback = callback; + } + + @Override + protected Uri doInBackgroundFallible(final Void... params) throws Exception { + File outputFile = DialerUtils.createShareableFile(mContext); + + try (OutputStream outputStream = new FileOutputStream(outputFile)) { + if (mHeightPercent != 1.0f) { + writeClippedBitmap(outputStream); + } else { + outputStream.write(mBytes, 0, mBytes.length); + } + } + + return FileProvider.getUriForFile( + mContext, Constants.get().getFileProviderAuthority(), outputFile); + } + + @Override + protected void onPostExecute(FallibleTaskResult<Uri> result) { + if (result.isFailure()) { + mCallback.onMediaFailed(new Exception("Persisting image failed", result.getThrowable())); + } else { + mCallback.onMediaReady(result.getResult(), "image/jpeg", mWidth, mHeight); + } + } + + private void writeClippedBitmap(OutputStream outputStream) throws IOException { + int orientation = android.media.ExifInterface.ORIENTATION_UNDEFINED; + final ExifInterface exifInterface = new ExifInterface(); + try { + exifInterface.readExif(mBytes); + final Integer orientationValue = exifInterface.getTagIntValue(ExifInterface.TAG_ORIENTATION); + if (orientationValue != null) { + orientation = orientationValue.intValue(); + } + } catch (final IOException e) { + // Couldn't get exif tags, not the end of the world + } + Bitmap bitmap = BitmapFactory.decodeByteArray(mBytes, 0, mBytes.length); + final int clippedWidth; + final int clippedHeight; + if (ExifInterface.getOrientationParams(orientation).invertDimensions) { + Assert.checkState(mWidth == bitmap.getHeight()); + Assert.checkState(mHeight == bitmap.getWidth()); + clippedWidth = (int) (mHeight * mHeightPercent); + clippedHeight = mWidth; + } else { + Assert.checkState(mWidth == bitmap.getWidth()); + Assert.checkState(mHeight == bitmap.getHeight()); + clippedWidth = mWidth; + clippedHeight = (int) (mHeight * mHeightPercent); + } + final int offsetTop = (bitmap.getHeight() - clippedHeight) / 2; + final int offsetLeft = (bitmap.getWidth() - clippedWidth) / 2; + mWidth = clippedWidth; + mHeight = clippedHeight; + Bitmap clippedBitmap = + Bitmap.createBitmap(clippedWidth, clippedHeight, Bitmap.Config.ARGB_8888); + clippedBitmap.setDensity(bitmap.getDensity()); + final Canvas clippedBitmapCanvas = new Canvas(clippedBitmap); + final Matrix matrix = new Matrix(); + matrix.postTranslate(-offsetLeft, -offsetTop); + clippedBitmapCanvas.drawBitmap(bitmap, matrix, null /* paint */); + clippedBitmapCanvas.save(); + clippedBitmap = CopyAndResizeImageTask.resizeForEnrichedCalling(clippedBitmap); + // EXIF data can take a big chunk of the file size and is often cleared by the + // carrier, only store orientation since that's critical + final ExifTag orientationTag = exifInterface.getTag(ExifInterface.TAG_ORIENTATION); + exifInterface.clearExif(); + exifInterface.setTag(orientationTag); + exifInterface.writeExif(clippedBitmap, outputStream); + + clippedBitmap.recycle(); + bitmap.recycle(); + } +} |