1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.dialer.callcomposer;
18
19import android.annotation.TargetApi;
20import android.content.Context;
21import android.graphics.Bitmap;
22import android.graphics.Bitmap.CompressFormat;
23import android.graphics.BitmapFactory;
24import android.media.ExifInterface;
25import android.net.Uri;
26import android.os.Build.VERSION_CODES;
27import android.support.annotation.NonNull;
28import android.support.annotation.Nullable;
29import android.support.v4.util.Pair;
30import com.android.dialer.callcomposer.util.BitmapResizer;
31import com.android.dialer.common.Assert;
32import com.android.dialer.common.concurrent.DialerExecutor.Worker;
33import com.android.dialer.util.DialerUtils;
34import java.io.File;
35import java.io.FileOutputStream;
36import java.io.InputStream;
37import java.io.OutputStream;
38
39/** Task for copying and resizing images to be shared with RCS process. */
40@TargetApi(VERSION_CODES.M)
41class CopyAndResizeImageWorker implements Worker<Uri, Pair<File, String>> {
42  private static final String MIME_TYPE = "image/jpeg";
43
44  private final Context context;
45
46  CopyAndResizeImageWorker(@NonNull Context context) {
47    this.context = Assert.isNotNull(context);
48  }
49
50  /**
51   * @param input The filepath where the image is located.
52   * @return a Pair where the File contains the resized image, and the String is the result File's
53   *     MIME type.
54   */
55  @Nullable
56  @Override
57  public Pair<File, String> doInBackground(@Nullable Uri input) throws Throwable {
58    // BitmapFactory.decodeStream strips exif data, so we need to save it here and apply it later.
59    int rotation = 0;
60    try {
61      rotation =
62          new ExifInterface(input.getPath())
63              .getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
64    } catch (Exception ignored) {
65      // Couldn't get exif tags, not the end of the world
66    }
67
68    try (InputStream inputStream = context.getContentResolver().openInputStream(input)) {
69      Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
70      bitmap = BitmapResizer.resizeForEnrichedCalling(bitmap, exifToDegrees(rotation));
71
72      File outputFile = DialerUtils.createShareableFile(context);
73      try (OutputStream outputStream = new FileOutputStream(outputFile)) {
74        // Encode images to jpeg as it is better for camera pictures which we expect to be sending
75        bitmap.compress(CompressFormat.JPEG, 80, outputStream);
76        return new Pair<>(outputFile, MIME_TYPE);
77      }
78    }
79  }
80
81  private static int exifToDegrees(int exifOrientation) {
82    switch (exifOrientation) {
83      case ExifInterface.ORIENTATION_ROTATE_90:
84        return 90;
85      case ExifInterface.ORIENTATION_ROTATE_180:
86        return 180;
87      case ExifInterface.ORIENTATION_ROTATE_270:
88        return 270;
89      default:
90        return 0;
91    }
92  }
93}
94