1 /*
2  * Copyright (C) 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.internal.utils.ImageUtil.createBitmapFromImageProxy;
20 
21 import android.annotation.SuppressLint;
22 import android.graphics.Bitmap;
23 import android.graphics.ImageFormat;
24 import android.graphics.PixelFormat;
25 import android.graphics.Rect;
26 import android.media.Image;
27 
28 import org.jspecify.annotations.NonNull;
29 import org.jspecify.annotations.Nullable;
30 
31 import java.nio.ByteBuffer;
32 
33 /** An image proxy which has a similar interface as {@link android.media.Image}. */
34 public interface ImageProxy extends AutoCloseable {
35     /**
36      * Closes the underlying {@link android.media.Image}.
37      *
38      * @see android.media.Image#close()
39      */
40     @Override
close()41     void close();
42 
43     /**
44      * Returns the crop rectangle.
45      *
46      * @see android.media.Image#getCropRect()
47      */
getCropRect()48     @NonNull Rect getCropRect();
49 
50     /**
51      * Sets the crop rectangle.
52      *
53      * @see android.media.Image#setCropRect(Rect)
54      */
setCropRect(@ullable Rect rect)55     void setCropRect(@Nullable Rect rect);
56 
57     /**
58      * Returns the image format.
59      *
60      * <p> The image format can be one of the {@link ImageFormat} or
61      * {@link PixelFormat} constants.
62      *
63      * @see android.media.Image#getFormat()
64      */
getFormat()65     int getFormat();
66 
67     /**
68      * Returns the image height.
69      *
70      * @see android.media.Image#getHeight()
71      */
getHeight()72     int getHeight();
73 
74     /**
75      * Returns the image width.
76      *
77      * @see android.media.Image#getWidth()
78      */
getWidth()79     int getWidth();
80 
81     /**
82      * Returns the array of planes.
83      *
84      * @see android.media.Image#getPlanes()
85      */
86     @SuppressLint("ArrayReturn")
getPlanes()87     PlaneProxy @NonNull [] getPlanes();
88 
89     /** A plane proxy which has an analogous interface as {@link android.media.Image.Plane}. */
90     interface PlaneProxy {
91         /**
92          * Returns the row stride.
93          *
94          * @see android.media.Image.Plane#getRowStride()
95          */
getRowStride()96         int getRowStride();
97 
98         /**
99          * Returns the pixel stride.
100          *
101          * @see android.media.Image.Plane#getPixelStride()
102          */
getPixelStride()103         int getPixelStride();
104 
105         /**
106          * Returns the pixels buffer.
107          *
108          * @see android.media.Image.Plane#getBuffer()
109          */
getBuffer()110         @NonNull ByteBuffer getBuffer();
111     }
112 
113     /** Returns the {@link ImageInfo}. */
getImageInfo()114     @NonNull ImageInfo getImageInfo();
115 
116     /**
117      * Returns the android {@link Image}.
118      *
119      * <p>If the ImageProxy is a wrapper for an android {@link Image}, it will return the
120      * {@link Image}. It is possible for an ImageProxy to wrap something that isn't an
121      * {@link Image}. If that's the case then it will return null.
122      *
123      * <p>The returned image should not be closed by the application. Instead it should be closed by
124      * the ImageProxy, which happens, for example, on return from the {@link ImageAnalysis.Analyzer}
125      * function.  Destroying the {@link ImageAnalysis} will close the underlying
126      * {@link android.media.ImageReader}.  So an {@link Image} obtained with this method will behave
127      * as such.
128      *
129      * @return the android image.
130      * @see android.media.Image#close()
131      */
132     @ExperimentalGetImage
getImage()133     @Nullable Image getImage();
134 
135     /**
136      * Converts {@link ImageProxy} to {@link Bitmap}.
137      *
138      * <p>The supported {@link ImageProxy} format is {@link ImageFormat#YUV_420_888},
139      * {@link ImageFormat#JPEG} or {@link PixelFormat#RGBA_8888}. If format is invalid, an
140      * {@link IllegalArgumentException} will be thrown. If the conversion to bimap failed, an
141      * {@link UnsupportedOperationException} will be thrown.
142      *
143      * @return {@link Bitmap} instance.
144      */
toBitmap()145     default @NonNull Bitmap toBitmap() {
146         return createBitmapFromImageProxy(this);
147     }
148 }
149