19c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall/*
29c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * Copyright (C) 2014 The Android Open Source Project
39c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall *
49c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * Licensed under the Apache License, Version 2.0 (the "License");
59c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * you may not use this file except in compliance with the License.
69c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * You may obtain a copy of the License at
79c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall *
89c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall *      http://www.apache.org/licenses/LICENSE-2.0
99c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall *
109c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * Unless required by applicable law or agreed to in writing, software
119c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * distributed under the License is distributed on an "AS IS" BASIS,
129c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * See the License for the specific language governing permissions and
149c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * limitations under the License.
159c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall */
169c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall
179c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lallpackage com.android.camera.one.v2.camera2proxy;
189c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall
199c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lallimport android.graphics.Rect;
206e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Linimport android.media.Image;
216e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin
22b8397360d318edf3093b20b2b102207d76730e1bPuneet Lallimport com.google.common.base.Objects;
23d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lallimport com.google.common.collect.ImmutableList;
24b8397360d318edf3093b20b2b102207d76730e1bPuneet Lall
256e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Linimport java.nio.ByteBuffer;
266e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Linimport java.util.ArrayList;
276e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Linimport java.util.List;
289c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall
291738db31add0aea5a6a6f2c137ca6fc476a10237Puneet Lallimport javax.annotation.concurrent.GuardedBy;
301738db31add0aea5a6a6f2c137ca6fc476a10237Puneet Lallimport javax.annotation.concurrent.ThreadSafe;
311738db31add0aea5a6a6f2c137ca6fc476a10237Puneet Lall
329c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall/**
339c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall * An {@link ImageProxy} backed by an {@link android.media.Image}.
349c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall */
351738db31add0aea5a6a6f2c137ca6fc476a10237Puneet Lall@ThreadSafe
369c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lallpublic class AndroidImageProxy implements ImageProxy {
376e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin
386e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin    /**
396e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin     * An {@link ImageProxy.Plane} backed by an
406e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin     * {@link android.media.Image.Plane}.
416e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin     */
426e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin    public class Plane implements ImageProxy.Plane {
43d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        private final int mPixelStride;
44d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        private final int mRowStride;
45d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        private final ByteBuffer mBuffer;
466e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin
476e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin        public Plane(Image.Plane imagePlane) {
48d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            // Copying out the contents of the Image.Plane means that this Plane
49d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            // implementation can be thread-safe (without requiring any locking)
50d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            // and can have getters which do not throw a RuntimeException if
51d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            // the underlying Image is closed.
52d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            mPixelStride = imagePlane.getPixelStride();
53d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            mRowStride = imagePlane.getRowStride();
54d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            mBuffer = imagePlane.getBuffer();
556e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin        }
566e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin
576e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin        /**
586e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin         * @see {@link android.media.Image.Plane#getRowStride}
596e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin         */
606e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin        @Override
616e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin        public int getRowStride() {
62d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            return mRowStride;
636e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin        }
646e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin
656e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin        /**
666e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin         * @see {@link android.media.Image.Plane#getPixelStride}
676e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin         */
686e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin        @Override
696e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin        public int getPixelStride() {
70d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            return mPixelStride;
716e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin        }
726e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin
736e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin        /**
746e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin         * @see {@link android.media.Image.Plane#getBuffer}
756e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin         */
766e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin        @Override
776e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin        public ByteBuffer getBuffer() {
78d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            return mBuffer;
796e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin        }
806e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin    }
816e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin
821738db31add0aea5a6a6f2c137ca6fc476a10237Puneet Lall    private final Object mLock;
831738db31add0aea5a6a6f2c137ca6fc476a10237Puneet Lall    /**
841738db31add0aea5a6a6f2c137ca6fc476a10237Puneet Lall     * {@link android.media.Image} is not thread-safe, so all interactions must
851738db31add0aea5a6a6f2c137ca6fc476a10237Puneet Lall     * be guarded by {@link #mLock}.
861738db31add0aea5a6a6f2c137ca6fc476a10237Puneet Lall     */
871738db31add0aea5a6a6f2c137ca6fc476a10237Puneet Lall    @GuardedBy("mLock")
889c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    private final android.media.Image mImage;
89d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall    private final int mFormat;
90d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall    private final int mWidth;
91d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall    private final int mHeight;
92d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall    private final long mTimestamp;
93d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall    private final ImmutableList<ImageProxy.Plane> mPlanes;
94d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall    @GuardedBy("mLock")
95d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall    private Rect mCropRect;
969c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall
979c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    public AndroidImageProxy(android.media.Image image) {
981738db31add0aea5a6a6f2c137ca6fc476a10237Puneet Lall        mLock = new Object();
99d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall
1009c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall        mImage = image;
101d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        // Copying out the contents of the Image means that this Image
102d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        // implementation can be thread-safe (without requiring any locking)
103d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        // and can have getters which do not throw a RuntimeException if
104d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        // the underlying Image is closed.
105d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        mFormat = mImage.getFormat();
106d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        mWidth = mImage.getWidth();
107d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        mHeight = mImage.getHeight();
108d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        mTimestamp = mImage.getTimestamp();
109d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall
110d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        Image.Plane[] planes;
111d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        planes = mImage.getPlanes();
112d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        if (planes == null) {
113d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            mPlanes = ImmutableList.of();
114d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        } else {
115d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            List<ImageProxy.Plane> wrappedPlanes = new ArrayList<>(planes.length);
116d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            for (int i = 0; i < planes.length; i++) {
117d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall                wrappedPlanes.add(new Plane(planes[i]));
118d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            }
119d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            mPlanes = ImmutableList.copyOf(wrappedPlanes);
120d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        }
1219c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    }
1229c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall
1239c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    /**
1249c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall     * @see {@link android.media.Image#getCropRect}
1259c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall     */
1269c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    @Override
1279c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    public Rect getCropRect() {
1281738db31add0aea5a6a6f2c137ca6fc476a10237Puneet Lall        synchronized (mLock) {
129d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            try {
130d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall                mCropRect = mImage.getCropRect();
131d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            } catch (IllegalStateException imageClosedException) {
132d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall                // If the image is closed, then just return the cached CropRect.
133d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall                return mCropRect;
134d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            }
135d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            return mCropRect;
1361738db31add0aea5a6a6f2c137ca6fc476a10237Puneet Lall        }
1379c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    }
1389c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall
1399c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    /**
1409c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall     * @see {@link android.media.Image#setCropRect}
1419c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall     */
1429c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    @Override
1439c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    public void setCropRect(Rect cropRect) {
1441738db31add0aea5a6a6f2c137ca6fc476a10237Puneet Lall        synchronized (mLock) {
145d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            mCropRect = cropRect;
146d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            try {
147d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall                mImage.setCropRect(cropRect);
148d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            } catch (IllegalStateException imageClosedException) {
149d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall                // Ignore.
150d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            }
1511738db31add0aea5a6a6f2c137ca6fc476a10237Puneet Lall        }
1529c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    }
1539c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall
1549c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    /**
1559c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall     * @see {@link android.media.Image#getFormat}
1569c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall     */
1579c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    @Override
1589c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    public int getFormat() {
159d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        return mFormat;
1609c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    }
1619c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall
1629c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    /**
1639c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall     * @see {@link android.media.Image#getHeight}
1649c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall     */
1659c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    @Override
1669c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    public int getHeight() {
167d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        return mHeight;
1689c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    }
1699c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall
1709c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    /**
1719c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall     * @see {@link android.media.Image#getPlanes}
1729c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall     */
1739c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    @Override
1746e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin    public List<ImageProxy.Plane> getPlanes() {
175d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        return mPlanes;
1769c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    }
1779c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall
1789c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    /**
1799c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall     * @see {@link android.media.Image#getTimestamp}
1809c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall     */
1819c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    @Override
1829c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    public long getTimestamp() {
183d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        return mTimestamp;
1849c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    }
1859c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall
1869c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    /**
1879c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall     * @see {@link android.media.Image#getWidth}
1889c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall     */
1899c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    @Override
1909c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    public int getWidth() {
191d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        return mWidth;
1929c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    }
1939c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall
1949c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    /**
1959c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall     * @see {@link android.media.Image#close}
1969c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall     */
1979c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    @Override
1989c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    public void close() {
1991738db31add0aea5a6a6f2c137ca6fc476a10237Puneet Lall        synchronized (mLock) {
2001738db31add0aea5a6a6f2c137ca6fc476a10237Puneet Lall            mImage.close();
2011738db31add0aea5a6a6f2c137ca6fc476a10237Puneet Lall        }
2029c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall    }
203b8397360d318edf3093b20b2b102207d76730e1bPuneet Lall
204b8397360d318edf3093b20b2b102207d76730e1bPuneet Lall    @Override
205b8397360d318edf3093b20b2b102207d76730e1bPuneet Lall    public String toString() {
206d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        return Objects.toStringHelper(this)
207d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall                .add("format", getFormat())
208d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall                .add("timestamp", getTimestamp())
209d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall                .add("width", getWidth())
210d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall                .add("height", getHeight())
211d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall                .toString();
212d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall    }
2131738db31add0aea5a6a6f2c137ca6fc476a10237Puneet Lall
214d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall    @Override
215d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall    public boolean equals(Object other) {
216d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        if (other == null) {
217d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            return false;
2181738db31add0aea5a6a6f2c137ca6fc476a10237Puneet Lall        }
219d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        if (!(other instanceof ImageProxy)) {
220d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall            return false;
221d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        }
222d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        ImageProxy otherImage = (ImageProxy) other;
223d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        return otherImage.getFormat() == getFormat() &&
224d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall                otherImage.getWidth() == getWidth() &&
225d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall                otherImage.getHeight() == getHeight() &&
226d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall                otherImage.getTimestamp() == getTimestamp();
227d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall    }
228d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall
229d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall    @Override
230d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall    public int hashCode() {
231d0316626dd2c2f4bd37ac7a198dbfe9e0ce2277fPuneet Lall        return Objects.hashCode(getFormat(), getWidth(), getHeight(), getTimestamp());
232b8397360d318edf3093b20b2b102207d76730e1bPuneet Lall    }
2339c94ab32a69a1ad3642a0f1e38e68bcfd97d3511Puneet Lall}
234