1ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin/*
2ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * Copyright (C) 2014 The Android Open Source Project
3ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin *
4ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * Licensed under the Apache License, Version 2.0 (the "License");
5ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * you may not use this file except in compliance with the License.
6ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * You may obtain a copy of the License at
7ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin *
8ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin *      http://www.apache.org/licenses/LICENSE-2.0
9ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin *
10ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * Unless required by applicable law or agreed to in writing, software
11ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * distributed under the License is distributed on an "AS IS" BASIS,
12ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * See the License for the specific language governing permissions and
14ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * limitations under the License.
15ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin */
16ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin
173830d419691ef865f01b362fee9618bac2aa8888Sascha Haeberlingpackage com.android.camera.processing.imagebackend;
18ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin
19c36bcac14302b1bb3d7a316f221685d4d6ad95cbI-Jong Linimport android.graphics.Bitmap;
20c36bcac14302b1bb3d7a316f221685d4d6ad95cbI-Jong Linimport android.graphics.BitmapFactory;
21ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Linimport android.graphics.ImageFormat;
22ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Linimport android.graphics.Rect;
23ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Linimport android.graphics.YuvImage;
245aa7eb2930b813c97f3754d93fe7fa978651887bSenpo Huimport android.net.Uri;
25ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin
26ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Linimport com.android.camera.debug.Log;
27ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Linimport com.android.camera.one.v2.camera2proxy.ImageProxy;
2830ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Linimport com.android.camera.session.CaptureSession;
29ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin
30ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Linimport java.io.ByteArrayOutputStream;
31ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Linimport java.io.IOException;
32ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Linimport java.nio.ByteBuffer;
336e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Linimport java.util.List;
34ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Linimport java.util.concurrent.Executor;
35ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin
36ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin/**
3730ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin * TaskJpegEncode are the base class of tasks that wish to do JPEG
3830ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin * encoding/decoding. Various helper functions are held in this class.
39ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin */
40ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Linpublic abstract class TaskJpegEncode extends TaskImageContainer {
41ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin
42ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin    protected final static Log.Tag TAG = new Log.Tag("TaskJpegEnc");
43ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin
4430ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin    /**
4530ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin     * Constructor to use for NOT passing the image reference forward.
4630ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin     *
4730ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin     * @param otherTask Parent task that is spawning this task
4830ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin     * @param processingPriority Preferred processing priority for this task
4930ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin     */
50ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin    public TaskJpegEncode(TaskImageContainer otherTask, ProcessingPriority processingPriority) {
51ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin        super(otherTask, processingPriority);
52ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin    }
53ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin
5430ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin    /**
5530ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin     * Constructor to use for initial task definition or complex shared state
5630ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin     * sharing.
5730ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin     *
5830ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin     * @param image Image reference that is required for computation
5930ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin     * @param executor Executor to avoid thread control leakage
603c7b7ec6aa2e51859718a6d6dead3c12d10ea370I-Jong Lin     * @param imageTaskManager ImageBackend associated with
6130ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin     * @param preferredLane Preferred processing priority for this task
6230ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin     * @param captureSession Session associated for UI handling
6330ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin     */
6430ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin    public TaskJpegEncode(ImageToProcess image, Executor executor,
6530ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin            ImageTaskManager imageTaskManager,
6630ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin            TaskImageContainer.ProcessingPriority preferredLane, CaptureSession captureSession) {
673c7b7ec6aa2e51859718a6d6dead3c12d10ea370I-Jong Lin        super(image, executor, imageTaskManager, preferredLane, captureSession);
68ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin    }
69ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin
70ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin    /**
7130ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin     * Converts the YUV420_888 Image into a packed NV21 of a single byte array,
7230ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin     * suitable for JPEG compression by the method convertNv21toJpeg. This
7330ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin     * version will allocate its own byte buffer memory.
74ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin     *
75ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin     * @param img image to be converted
76ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin     * @return byte array of NV21 packed image
77ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin     */
78ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin    public byte[] convertYUV420ImageToPackedNV21(ImageProxy img) {
796e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin        final List<ImageProxy.Plane> planeList = img.getPlanes();
806e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin
816e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin        ByteBuffer y_buffer = planeList.get(0).getBuffer();
826e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin        ByteBuffer u_buffer = planeList.get(1).getBuffer();
836e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin        ByteBuffer v_buffer = planeList.get(2).getBuffer();
84ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin        byte[] dataCopy = new byte[y_buffer.capacity() + u_buffer.capacity() + v_buffer.capacity()];
85ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin
86ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin        return convertYUV420ImageToPackedNV21(img, dataCopy);
87ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin    }
88ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin
89ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin    /**
9030ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin     * Converts the YUV420_888 Image into a packed NV21 of a single byte array,
9130ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin     * suitable for JPEG compression by the method convertNv21toJpeg. Creates a
9230ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin     * memory block with the y component at the head and interleaves the u,v
9330ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin     * components following the y component. Caller is responsible to allocate a
9430ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin     * large enough buffer for results.
95ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin     *
96ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin     * @param img image to be converted
97ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin     * @param dataCopy buffer to write NV21 packed image
98ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin     * @return byte array of NV21 packed image
99ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin     */
100ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin    public byte[] convertYUV420ImageToPackedNV21(ImageProxy img, byte[] dataCopy) {
101ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin        // Get all the relevant information and then release the image.
102ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin        final int w = img.getWidth();
103ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin        final int h = img.getHeight();
1046e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin        final List<ImageProxy.Plane> planeList = img.getPlanes();
105ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin
1066e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin        ByteBuffer y_buffer = planeList.get(0).getBuffer();
1076e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin        ByteBuffer u_buffer = planeList.get(1).getBuffer();
1086e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin        ByteBuffer v_buffer = planeList.get(2).getBuffer();
1096e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin        final int color_pixel_stride = planeList.get(1).getPixelStride();
11030ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin        final int y_size = y_buffer.capacity();
11130ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin        final int u_size = u_buffer.capacity();
11230ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin        final int data_offset = w * h;
113ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin
11430ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin        for (int i = 0; i < y_size; i++) {
11530ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin            dataCopy[i] = (byte) (y_buffer.get(i) & 255);
116ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin        }
117ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin
11830ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin        for (int i = 0; i < u_size / color_pixel_stride; i++) {
119ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin            dataCopy[data_offset + 2 * i] = v_buffer.get(i * color_pixel_stride);
120ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin            dataCopy[data_offset + 2 * i + 1] = u_buffer.get(i * color_pixel_stride);
121ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin        }
122ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin
123ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin        return dataCopy;
124ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin    }
125ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin
126ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin    /**
12730ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin     * Creates a dummy shaded image for testing in packed NV21 format.
12830ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin     *
12930ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin     * @param dataCopy Buffer to contained shaded test image
13030ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin     * @param w Width of image
13130ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin     * @param h Height of Image
13230ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin     */
13330ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin    public void dummyConvertYUV420ImageToPackedNV21(byte[] dataCopy,
13430ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin            final int w, final int h) {
13530ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin        final int y_size = w * h;
13630ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin        final int data_offset = w * h;
13730ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin
13830ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin        for (int i = 0; i < y_size; i++) {
13930ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin            dataCopy[i] = (byte) ((((i % w) * 255) / w) & 255);
14030ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin            dataCopy[i] = 0;
14130ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin        }
14230ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin
14330ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin        for (int i = 0; i < h / 2; i++) {
14430ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin            for (int j = 0; j < w / 2; j++) {
14530ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin                int offset = data_offset + w * i + j * 2;
14630ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin                dataCopy[offset] = (byte) ((255 * i) / (h / 2) & 255);
14730ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin                dataCopy[offset + 1] = (byte) ((255 * j) / (w / 2) & 255);
14830ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin            }
14930ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin        }
15030ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin    }
15130ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin
15230ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin    /**
15330ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin     * Wraps the Android built-in YUV to Jpeg conversion routine. Pass in a
15430ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin     * valid NV21 image and get back a compressed JPEG buffer. A good default
15530ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin     * JPEG compression implementation that should be supported on all
15630ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin     * platforms.
157ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin     *
158ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin     * @param data_copy byte buffer that contains the NV21 image
159ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin     * @param w width of NV21 image
160ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin     * @param h height of N21 image
161ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin     * @return byte array of compressed JPEG image
162ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin     */
163ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin    public byte[] convertNv21toJpeg(byte[] data_copy, int w, int h, int[] strides) {
164ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin        Log.e(TAG, "TIMER_BEGIN NV21 to Jpeg Conversion.");
165ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin        YuvImage yuvImage = new YuvImage(data_copy, ImageFormat.NV21, w, h, strides);
166ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin
167ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin        ByteArrayOutputStream postViewBytes = new ByteArrayOutputStream();
168ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin
169ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin        yuvImage.compressToJpeg(new Rect(0, 0, w, h), 90, postViewBytes);
170ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin        try {
171ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin            postViewBytes.flush();
172ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin        } catch (IOException e) {
173ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin            e.printStackTrace();
174ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin        }
175ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin
176ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin        Log.e(TAG, "TIMER_END NV21 to Jpeg Conversion.");
177ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin        return postViewBytes.toByteArray();
178ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin    }
179ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin
180ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin    /**
181c36bcac14302b1bb3d7a316f221685d4d6ad95cbI-Jong Lin     * Implement cropping through the decompression and re-compression of the JPEG using
182c36bcac14302b1bb3d7a316f221685d4d6ad95cbI-Jong Lin     * the built-in Android bitmap utilities.
183c36bcac14302b1bb3d7a316f221685d4d6ad95cbI-Jong Lin     *
184c36bcac14302b1bb3d7a316f221685d4d6ad95cbI-Jong Lin     * @param jpegData Compressed Image to be cropped
185c36bcac14302b1bb3d7a316f221685d4d6ad95cbI-Jong Lin     * @param crop Crop to be applied
186c36bcac14302b1bb3d7a316f221685d4d6ad95cbI-Jong Lin     * @param recompressionQuality Recompression quality value for cropped JPEG Image
187c36bcac14302b1bb3d7a316f221685d4d6ad95cbI-Jong Lin     * @return JPEG compressed byte array representing the cropped image
188c36bcac14302b1bb3d7a316f221685d4d6ad95cbI-Jong Lin     */
189c36bcac14302b1bb3d7a316f221685d4d6ad95cbI-Jong Lin    public byte[] decompressCropAndRecompressJpegData(final byte[] jpegData, Rect crop,
190c36bcac14302b1bb3d7a316f221685d4d6ad95cbI-Jong Lin            int recompressionQuality) {
191c36bcac14302b1bb3d7a316f221685d4d6ad95cbI-Jong Lin        Bitmap original = BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length);
192c36bcac14302b1bb3d7a316f221685d4d6ad95cbI-Jong Lin
193c36bcac14302b1bb3d7a316f221685d4d6ad95cbI-Jong Lin        final Bitmap croppedResult = Bitmap.createBitmap(original, crop.left, crop.top,
194c36bcac14302b1bb3d7a316f221685d4d6ad95cbI-Jong Lin                crop.width(), crop.height());;
195c36bcac14302b1bb3d7a316f221685d4d6ad95cbI-Jong Lin
196c36bcac14302b1bb3d7a316f221685d4d6ad95cbI-Jong Lin        ByteArrayOutputStream stream = new ByteArrayOutputStream();
197c36bcac14302b1bb3d7a316f221685d4d6ad95cbI-Jong Lin
198c36bcac14302b1bb3d7a316f221685d4d6ad95cbI-Jong Lin        croppedResult.compress(Bitmap.CompressFormat.JPEG, recompressionQuality, stream);
199c36bcac14302b1bb3d7a316f221685d4d6ad95cbI-Jong Lin        return stream.toByteArray();
200c36bcac14302b1bb3d7a316f221685d4d6ad95cbI-Jong Lin    }
201c36bcac14302b1bb3d7a316f221685d4d6ad95cbI-Jong Lin
202c36bcac14302b1bb3d7a316f221685d4d6ad95cbI-Jong Lin    /**
203ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin     * Wraps the onResultCompressed listener for ease of use.
204ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin     *
205ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin     * @param id Unique content id
206ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin     * @param input Specification of image input size
207ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin     * @param result Specification of resultant input size
208ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin     * @param data Container for uncompressed data that represents image
209ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin     */
21030ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin    public void onJpegEncodeDone(long id, TaskImage input, TaskImage result, byte[] data,
21130ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin            TaskInfo.Destination aDestination) {
21230ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin        TaskInfo job = new TaskInfo(id, input, result, aDestination);
2133c7b7ec6aa2e51859718a6d6dead3c12d10ea370I-Jong Lin        final ImageProcessorListener listener = mImageTaskManager.getProxyListener();
214ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin        listener.onResultCompressed(job, new CompressedPayload(data));
215ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin    }
216ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin
2175aa7eb2930b813c97f3754d93fe7fa978651887bSenpo Hu    /**
2185aa7eb2930b813c97f3754d93fe7fa978651887bSenpo Hu     * Wraps the onResultUri listener for ease of use.
2195aa7eb2930b813c97f3754d93fe7fa978651887bSenpo Hu     *
2205aa7eb2930b813c97f3754d93fe7fa978651887bSenpo Hu     * @param id Unique content id
2215aa7eb2930b813c97f3754d93fe7fa978651887bSenpo Hu     * @param input Specification of image input size
2225aa7eb2930b813c97f3754d93fe7fa978651887bSenpo Hu     * @param result Specification of resultant input size
2235aa7eb2930b813c97f3754d93fe7fa978651887bSenpo Hu     * @param imageUri URI of the saved image.
22430ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin     * @param destination Specifies the purpose of the image artifact
2255aa7eb2930b813c97f3754d93fe7fa978651887bSenpo Hu     */
22630ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin    public void onUriResolved(long id, TaskImage input, TaskImage result, final Uri imageUri,
22730ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin            TaskInfo.Destination destination) {
22830ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin        final TaskInfo job = new TaskInfo(id, input, result, destination);
2295aa7eb2930b813c97f3754d93fe7fa978651887bSenpo Hu        final ImageProcessorListener listener = mImageTaskManager.getProxyListener();
2305aa7eb2930b813c97f3754d93fe7fa978651887bSenpo Hu        listener.onResultUri(job, imageUri);
2315aa7eb2930b813c97f3754d93fe7fa978651887bSenpo Hu    }
232ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin}
233