1 /* 2 * Copyright 2024 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 androidx.camera.viewfinder.core 18 19 /** 20 * Transformation information associated with the preview output. 21 * 22 * This information can be used to transform the Surface of a Viewfinder to be suitable to be 23 * displayed. 24 */ 25 class TransformationInfo 26 @JvmOverloads 27 constructor( 28 /** Rotation of the source, relative to the device's natural rotation, in degrees. */ 29 val sourceRotation: Int = 0, 30 31 /** 32 * Indicates whether the source has been mirrored horizontally. 33 * 34 * This is common if the source comes from a camera that is front-facing. 35 * 36 * It is not common for both [isSourceMirroredHorizontally] and [isSourceMirroredVertically] to 37 * be set to `true`. This is equivalent to [sourceRotation] being rotated by an additional 180 38 * degrees. 39 * 40 * @see android.hardware.camera2.params.OutputConfiguration.MIRROR_MODE_AUTO 41 * @see android.hardware.camera2.params.OutputConfiguration.MIRROR_MODE_H 42 * @see androidx.camera.core.SurfaceRequest.TransformationInfo.isMirroring 43 */ 44 val isSourceMirroredHorizontally: Boolean = false, 45 46 /** 47 * Indicates whether the source has been mirrored vertically. 48 * 49 * It is not common for a camera source to be mirror vertically, and typically 50 * [isSourceMirroredHorizontally] will be the appropriate property. 51 * 52 * It is not common for both [isSourceMirroredHorizontally] and [isSourceMirroredVertically] to 53 * be set to `true`. This is equivalent to [sourceRotation] being rotated by an additional 180 54 * degrees. 55 * 56 * @see android.hardware.camera2.params.OutputConfiguration.MIRROR_MODE_V 57 */ 58 val isSourceMirroredVertically: Boolean = false, 59 60 /** 61 * Left offset of the cropRect in pixels. 62 * 63 * The offset is in the coordinates of the original surface, before rotation or mirroring. 64 * 65 * If not set, this value will default to [CROP_NONE], which is equivalent to an offset of 0. 66 */ 67 val cropRectLeft: Float = CROP_NONE, 68 69 /** 70 * Top offset of the cropRect in pixels 71 * 72 * The offset is in the coordinates of the original surface, before rotation or mirroring. 73 * 74 * If not set, this value will default to [CROP_NONE], which is equivalent to an offset of 0. 75 */ 76 val cropRectTop: Float = CROP_NONE, 77 78 /** 79 * Right offset of the cropRect in pixels 80 * 81 * The offset is in the coordinates of the original surface, before rotation or mirroring. 82 * 83 * If not set, this value will default to [CROP_NONE], which is equivalent to an offset of the 84 * width of the surface. 85 */ 86 val cropRectRight: Float = CROP_NONE, 87 88 /** 89 * Bottom offset of the cropRect in pixels 90 * 91 * The offset is in the coordinates of the original surface, before rotation or mirroring. 92 * 93 * If not set, this value will default to [CROP_NONE], which is equivalent to an offset of the 94 * height of the surface. 95 */ 96 val cropRectBottom: Float = CROP_NONE 97 ) { equalsnull98 override fun equals(other: Any?): Boolean { 99 if (this === other) return true 100 if (other !is TransformationInfo) return false 101 102 if (sourceRotation != other.sourceRotation) return false 103 if (isSourceMirroredHorizontally != other.isSourceMirroredHorizontally) return false 104 if (isSourceMirroredVertically != other.isSourceMirroredVertically) return false 105 if (cropRectLeft != other.cropRectLeft) return false 106 if (cropRectTop != other.cropRectTop) return false 107 if (cropRectRight != other.cropRectRight) return false 108 if (cropRectBottom != other.cropRectBottom) return false 109 110 return true 111 } 112 hashCodenull113 override fun hashCode(): Int { 114 var result = sourceRotation 115 result = 31 * result + isSourceMirroredHorizontally.hashCode() 116 result = 31 * result + isSourceMirroredVertically.hashCode() 117 result = 31 * result + cropRectLeft.hashCode() 118 result = 31 * result + cropRectTop.hashCode() 119 result = 31 * result + cropRectRight.hashCode() 120 result = 31 * result + cropRectBottom.hashCode() 121 return result 122 } 123 124 companion object { 125 /** 126 * A crop value specifying no crop should be applied. 127 * 128 * When used as a value for [TransformationInfo.cropRectLeft], 129 * [TransformationInfo.cropRectTop], [TransformationInfo.cropRectRight], or 130 * [TransformationInfo.cropRectBottom], the crop rect dimension will be equivalent to the 131 * resolution of the untransformed surface. 132 */ 133 const val CROP_NONE: Float = Float.NaN 134 135 /** 136 * A [TransformationInfo] with default values. 137 * 138 * This transformation info instance has no source rotation, no mirroring, and no crop 139 * rectangle. 140 */ 141 @JvmField val DEFAULT: TransformationInfo = TransformationInfo() 142 } 143 } 144