|
|
@@ -7,7 +7,6 @@ import android.media.Image;
|
|
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
|
import java.nio.ByteBuffer;
|
|
|
-import java.nio.ReadOnlyBufferException;
|
|
|
|
|
|
public final class ImageUtil {
|
|
|
|
|
|
@@ -56,73 +55,7 @@ public final class ImageUtil {
|
|
|
}
|
|
|
|
|
|
|
|
|
- private static byte[] YUV_420_888toNV21Accept(Image image) {
|
|
|
- int width = image.getWidth();
|
|
|
- int height = image.getHeight();
|
|
|
- int ySize = width * height;
|
|
|
- int uvSize = width * height / 4;
|
|
|
|
|
|
- byte[] nv21 = new byte[ySize + uvSize * 2];
|
|
|
-
|
|
|
- ByteBuffer yBuffer = image.getPlanes()[0].getBuffer(); // Y
|
|
|
- ByteBuffer uBuffer = image.getPlanes()[1].getBuffer(); // U
|
|
|
- ByteBuffer vBuffer = image.getPlanes()[2].getBuffer(); // V
|
|
|
-
|
|
|
- int rowStride = image.getPlanes()[0].getRowStride();
|
|
|
- assert (image.getPlanes()[0].getPixelStride() == 1);
|
|
|
-
|
|
|
- int pos = 0;
|
|
|
-
|
|
|
- if (rowStride == width) { // likely
|
|
|
- yBuffer.get(nv21, 0, ySize);
|
|
|
- pos += ySize;
|
|
|
- } else {
|
|
|
- int yBufferPos = width - rowStride; // not an actual position
|
|
|
- for (; pos < ySize; pos += width) {
|
|
|
- yBufferPos += rowStride - width;
|
|
|
- yBuffer.position(yBufferPos);
|
|
|
- yBuffer.get(nv21, pos, width);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- rowStride = image.getPlanes()[2].getRowStride();
|
|
|
- int pixelStride = image.getPlanes()[2].getPixelStride();
|
|
|
-
|
|
|
- assert (rowStride == image.getPlanes()[1].getRowStride());
|
|
|
- assert (pixelStride == image.getPlanes()[1].getPixelStride());
|
|
|
-
|
|
|
- if (pixelStride == 2 && rowStride == width && uBuffer.get(0) == vBuffer.get(1)) {
|
|
|
- // maybe V an U planes overlap as per NV21, which means vBuffer[1] is alias of uBuffer[0]
|
|
|
- byte savePixel = vBuffer.get(1);
|
|
|
- try {
|
|
|
- vBuffer.put(1, (byte) ~savePixel);
|
|
|
- if (uBuffer.get(0) == (byte) ~savePixel) {
|
|
|
- vBuffer.put(1, savePixel);
|
|
|
- vBuffer.get(nv21, ySize, uvSize);
|
|
|
-
|
|
|
- return nv21; // shortcut
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- // unfortunately, the check failed. We must save U and V pixel by pixel
|
|
|
- vBuffer.put(1, savePixel);
|
|
|
- } catch (ReadOnlyBufferException ex) {
|
|
|
- // unfortunately, we cannot check if vBuffer and uBuffer overlap
|
|
|
- }
|
|
|
-
|
|
|
- // other optimizations could check if (pixelStride == 1) or (pixelStride == 2),
|
|
|
- // but performance gain would be less significant
|
|
|
-
|
|
|
- for (int row = 0; row < height / 2; row++) {
|
|
|
- for (int col = 0; col < width / 2; col++) {
|
|
|
- int vuPos = col * pixelStride + row * rowStride;
|
|
|
- nv21[pos++] = vBuffer.get(vuPos);
|
|
|
- nv21[pos++] = uBuffer.get(vuPos);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return nv21;
|
|
|
- }
|
|
|
|
|
|
|
|
|
}
|