1 /* 2 * Copyright 2019 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.core; 18 19 import static androidx.camera.core.FlashState.FlashState; 20 import static androidx.camera.core.FlashState.UNKNOWN; 21 22 import android.graphics.Matrix; 23 import android.hardware.camera2.CameraCharacteristics; 24 25 import androidx.annotation.RestrictTo; 26 import androidx.camera.core.impl.TagBundle; 27 import androidx.camera.core.impl.utils.ExifData; 28 29 import org.jspecify.annotations.NonNull; 30 31 /** Metadata for an image. */ 32 public interface ImageInfo { 33 /** 34 * Returns all tags stored in the metadata. 35 * 36 */ 37 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) getTagBundle()38 @NonNull TagBundle getTagBundle(); 39 40 /** 41 * Returns the timestamp of the metadata. 42 * 43 * Details on the timestamp depend on the source providing the image, and the method providing 44 * the image contains more documentation. 45 * 46 * @return the timestamp of the image 47 */ getTimestamp()48 long getTimestamp(); 49 50 /** 51 * Returns the rotation needed to transform the image to the correct orientation. 52 * 53 * <p> This is a clockwise rotation in degrees that needs to be applied to the image buffer. 54 * Note that for images that are in {@link android.graphics.ImageFormat#JPEG} this value will 55 * match the rotation defined in the EXIF. 56 * 57 * <p> The target rotation is set at the time the image capture was requested. 58 * 59 * <p> The correct orientation of the image is dependent upon the producer of the image. For 60 * example, if the {@link ImageProxy} that contains this instance of ImageInfo is produced 61 * by an {@link ImageCapture}, then the rotation will be determined by 62 * {@link ImageCapture#setTargetRotation(int)} or 63 * {@link ImageCapture.Builder#setTargetRotation(int)}. 64 * 65 * @return The rotation in degrees which will be a value in {0, 90, 180, 270}. 66 * @see ImageCapture#setTargetRotation(int) 67 * @see ImageCapture.Builder#setTargetRotation(int) 68 * @see ImageAnalysis#setTargetRotation(int) 69 * @see ImageAnalysis.Builder#setTargetRotation(int) 70 */ 71 // TODO(b/122806727) Need to correctly set EXIF in JPEG images getRotationDegrees()72 int getRotationDegrees(); 73 74 /** 75 * Returns the sensor to image buffer transform matrix. 76 * 77 * <p>The returned matrix is a mapping from sensor coordinates to buffer coordinates, 78 * which is, from the value of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE} to 79 * {@code (0, 0, image.getWidth, image.getHeight)}. The matrix can be used to map the 80 * coordinates from one {@link UseCase} to another. For example, mapping coordinates of the 81 * face detected with {@link ImageAnalysis} to {@link ImageCapture}. 82 * 83 * If {@link ImageAnalysis.Builder#setOutputImageRotationEnabled} is set to false, 84 * {@link ImageInfo#getRotationDegrees()} will return the rotation degree that needs to be 85 * applied to the image buffer to user. In this case, the transform matrix can be 86 * calculated using rotation degrees. 87 * 88 * If {@link ImageAnalysis.Builder#setOutputImageRotationEnabled} is set to true, the 89 * ImageAnalysis pipeline will apply the rotation to the image buffer and 90 * {@link ImageInfo#getRotationDegrees()} will always return 0. In this case, the transform 91 * matrix cannot be calculated. 92 * 93 * This API provides the transform matrix which could handle both cases. 94 * 95 * <pre> 96 * <code> 97 * // Calculate the matrix 98 * Matrix analysisToSensor = new Matrix(); 99 * analysisToSensor.invert( 100 * imageAnalysisImageProxy.getImageInfo() 101 * .getSensorToBufferTransformMatrix()); 102 * Matrix sensorToCapture = captureImageProxy.getImageInfo() 103 * .getSensorToBufferTransformMatrix(); 104 * Matrix analysisToCapture = new Matrix(); 105 * analysisToCapture.setConcat(analysisToSensor, sensorToCapture); 106 * 107 * // Transforming the coordinates 108 * Rect faceBoundingBoxInAnalysis; 109 * Rect faceBoundingBoxInCapture; 110 * analysisToCapture.mapRect(faceBoundingBoxInAnalysis, faceBoundingBoxInCapture); 111 * 112 * // faceBoundingBoxInCapture is the desired value 113 * </code> 114 * </pre> 115 * 116 * @return the transform matrix. 117 */ getSensorToBufferTransformMatrix()118 default @NonNull Matrix getSensorToBufferTransformMatrix() { 119 return new Matrix(); 120 } 121 122 /** 123 * Returns the {@link androidx.camera.core.FlashState} value corresponding to the image capture. 124 */ 125 @FlashState getFlashState()126 default int getFlashState() { 127 return UNKNOWN; 128 } 129 130 /** 131 * Adds any stored EXIF information in this ImageInfo into the provided ExifData builder. 132 * 133 */ 134 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) populateExifData(ExifData.@onNull Builder exifBuilder)135 void populateExifData(ExifData.@NonNull Builder exifBuilder); 136 } 137