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