Home | History | Annotate | Download | only in captureintent
      1 /*
      2  * Copyright (C) 2015 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 
     17 package com.android.camera.captureintent;
     18 
     19 import com.android.camera.app.OrientationManager;
     20 import com.android.camera.debug.Log;
     21 import com.android.camera.util.Size;
     22 
     23 import android.graphics.Matrix;
     24 import android.graphics.PointF;
     25 import android.graphics.RectF;
     26 
     27 public class PreviewTransformCalculator {
     28     private static final Log.Tag TAG = new Log.Tag("PviewTransfmCal");
     29 
     30     private final OrientationManager mOrientationManager;
     31 
     32     public PreviewTransformCalculator(OrientationManager orientationManager) {
     33         mOrientationManager = orientationManager;
     34     }
     35 
     36     /**
     37      * Build a matrix which can be used when calling setTransform() on a
     38      * TextureView.
     39      * TODO: write unit test when roboletric is available.
     40      *
     41      * @param previewViewSize The TextureView current layout size.
     42      * @param previewStreamSize The selected preview video stream size.
     43      * @return The matrix to transform TextureView.
     44      */
     45     public Matrix toTransformMatrix(Size previewViewSize, Size previewStreamSize) {
     46         RectF previewViewRect =
     47                 new RectF(0.0f, 0.0f, previewViewSize.width(), previewViewSize.height());
     48         PointF previewViewCenter = new PointF(previewViewRect.centerX(), previewViewRect.centerY());
     49 
     50         // If natural orientation is portrait, rotate the buffer dimensions.
     51         Size previewBufferSize = previewStreamSize;
     52 
     53         if (mOrientationManager.getDeviceNaturalOrientation() == OrientationManager.DeviceNaturalOrientation.PORTRAIT) {
     54             previewBufferSize = new Size(previewStreamSize.height(), previewStreamSize.width());
     55         }
     56 
     57         Matrix transformMatrix = new Matrix();
     58 
     59         // Adjust the effective preview rect to the center of the texture view.
     60         final RectF PreviewBufferRect =
     61                 new RectF(0.0f, 0.0f, previewBufferSize.width(), previewBufferSize.height());
     62         final PointF previewBufferCenter =
     63                 new PointF(PreviewBufferRect.centerX(), PreviewBufferRect.centerY());
     64 
     65         final RectF centeredEffectivePreviewRect = new RectF(PreviewBufferRect);
     66         centeredEffectivePreviewRect.offset(
     67                 previewViewCenter.x - previewBufferCenter.x,
     68                 previewViewCenter.y - previewBufferCenter.y);
     69 
     70         // Undo ScaleToFit.FILL done by the surface
     71         transformMatrix.setRectToRect(
     72                 previewViewRect, centeredEffectivePreviewRect, Matrix.ScaleToFit.FILL);
     73 
     74         // Rotate buffer contents to proper orientation
     75         int rotateDegree = mOrientationManager.getDisplayRotation().getDegrees();
     76         transformMatrix.postRotate(
     77                 rotateDegree,
     78                 previewViewCenter.x, previewViewCenter.y);
     79 
     80         /**
     81          * Scale to fit view, cropping the longest dimension.
     82          *
     83          * surfaceTextureSize is changed with the device orientation. Since
     84          * previewStreamSize is always in landscape. To calculate the scale
     85          * factor, previewStreamSize needs to be rotated if in portrait.
     86          */
     87         Size rotatedPreviewSize = previewStreamSize;
     88         if (mOrientationManager.isInPortrait()) {
     89             rotatedPreviewSize = new Size(previewStreamSize.height(), previewStreamSize.width());
     90         }
     91         float scale = Math.min(
     92                 (float) previewViewSize.width() / (float) rotatedPreviewSize.width(),
     93                 (float) previewViewSize.height() / (float) rotatedPreviewSize.height());
     94         transformMatrix.postScale(scale, scale, previewViewCenter.x, previewViewCenter.y);
     95 
     96         RectF scaledPreviewStreamRect = new RectF(
     97                 0.0f, 0.0f, previewStreamSize.width() * scale, previewStreamSize.height() * scale);
     98         PointF scaledPreviewStreamCenter =
     99                 new PointF(scaledPreviewStreamRect.centerX(), scaledPreviewStreamRect.centerY());
    100         transformMatrix.postTranslate(
    101                 scaledPreviewStreamCenter.x - previewViewCenter.x,
    102                 scaledPreviewStreamCenter.y - previewViewCenter.y);
    103 
    104         return transformMatrix;
    105     }
    106 }
    107