blob: 1f7ea966e4567324e1c931d475ad52e821460aa2 [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.camera.processing;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
import com.android.camera.debug.Log;
import com.android.camera.one.v2.camera2proxy.ImageProxy;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.Executor;
/**
* TaskImageContainer are the base class of tasks that wish to run with the
* ImageBackend class. It contains the basic information required to interact
* with the ImageBackend class and the ability to identify itself to the UI
* backend for updates on its progress.
*/
public abstract class TaskJpegEncode extends TaskImageContainer {
protected final static Log.Tag TAG = new Log.Tag("TaskJpegEnc");
public TaskJpegEncode(TaskImageContainer otherTask, ProcessingPriority processingPriority) {
super(otherTask, processingPriority);
}
public TaskJpegEncode(ImageProxy image, Executor executor, ImageBackend imageBackend,
TaskImageContainer.ProcessingPriority preferredLane) {
super(image, executor, imageBackend, preferredLane);
}
/**
* Converts the YUV420_888 Image into a packed NV21 of a single byte array, suitable for JPEG
* compression by the method convertNv21toJpeg. This version will allocate its own byte buffer
* memory.
*
* @param img image to be converted
* @return byte array of NV21 packed image
*/
public byte[] convertYUV420ImageToPackedNV21(ImageProxy img) {
ByteBuffer y_buffer = img.getPlanes()[0].getBuffer();
ByteBuffer u_buffer = img.getPlanes()[1].getBuffer();
ByteBuffer v_buffer = img.getPlanes()[2].getBuffer();
byte[] dataCopy = new byte[y_buffer.capacity() + u_buffer.capacity() + v_buffer.capacity()];
return convertYUV420ImageToPackedNV21(img, dataCopy);
}
/**
* Converts the YUV420_888 Image into a packed NV21 of a single byte array, suitable for JPEG
* compression by the method convertNv21toJpeg. Creates a memory block with the y component at
* the head and interleaves the u,v components following the y component. Caller is responsible
* to allocate a large enough buffer for results.
*
* @param img image to be converted
* @param dataCopy buffer to write NV21 packed image
* @return byte array of NV21 packed image
*/
public byte[] convertYUV420ImageToPackedNV21(ImageProxy img, byte[] dataCopy) {
// Get all the relevant information and then release the image.
final int w = img.getWidth();
final int h = img.getHeight();
ByteBuffer y_buffer = img.getPlanes()[0].getBuffer();
ByteBuffer u_buffer = img.getPlanes()[1].getBuffer();
ByteBuffer v_buffer = img.getPlanes()[2].getBuffer();
for (int i = 0; i < y_buffer.capacity(); i++) {
dataCopy[i] = (byte)(y_buffer.get(i) & 255);
}
int color_pixel_stride = img.getPlanes()[1].getPixelStride();
int data_offset = y_buffer.capacity();
for (int i = 0; i < u_buffer.capacity() / color_pixel_stride; i++) {
dataCopy[data_offset + 2 * i] = v_buffer.get(i * color_pixel_stride);
dataCopy[data_offset + 2 * i + 1] = u_buffer.get(i * color_pixel_stride);
}
return dataCopy;
}
/**
* Wraps the Android built-in YUV to Jpeg conversion routine. Pass in a valid NV21 image and get
* back a compressed JPEG buffer. A good default JPEG compression implementation that should be
* supported on all platforms.
*
* @param data_copy byte buffer that contains the NV21 image
* @param w width of NV21 image
* @param h height of N21 image
* @return byte array of compressed JPEG image
*/
public byte[] convertNv21toJpeg(byte[] data_copy, int w, int h, int[] strides) {
Log.e(TAG, "TIMER_BEGIN NV21 to Jpeg Conversion.");
YuvImage yuvImage = new YuvImage(data_copy, ImageFormat.NV21, w, h, strides);
ByteArrayOutputStream postViewBytes = new ByteArrayOutputStream();
yuvImage.compressToJpeg(new Rect(0, 0, w, h), 90, postViewBytes);
try {
postViewBytes.flush();
} catch (IOException e) {
e.printStackTrace();
}
Log.e(TAG, "TIMER_END NV21 to Jpeg Conversion.");
return postViewBytes.toByteArray();
}
/**
* Wraps the onResultCompressed listener for ease of use.
*
* @param id Unique content id
* @param input Specification of image input size
* @param result Specification of resultant input size
* @param data Container for uncompressed data that represents image
*/
public void onJpegEncodeDone(long id, TaskImage input, TaskImage result, byte[] data) {
TaskInfo job = new TaskInfo(id, input, result);
final ImageProcessorListener listener = mImageBackend.getProxyListener();
listener.onResultCompressed(job, new CompressedPayload(data));
}
}