5

I need to crop every frame from the camera's onPreviewFrame. I want to crop it directly doing operations with the byte array without converting it to a bitmap. The reason I want to do it directly on the array is because it can't be too slow or too expensive. After the crop operation I will use the output byte array directly so I don't need any bitmap conversion.

int frameWidth;
int frameHeight;    

@Override
public void onPreviewFrame(byte[] data, Camera camera) {
    // Crop the data array directly.

    cropData(data, frameWidth, frameHeight, startCropX, startCropY, outputWidth, outputHeight);

}
fadden
  • 51,356
  • 5
  • 116
  • 166
stanete
  • 4,062
  • 9
  • 21
  • 30
  • Are you asking for help with code you've written, or asking for someone to write code for you? If the former, show what you've tried and explain what doesn't work. If the latter, you might be in the wrong place. – fadden May 03 '16 at 00:24

1 Answers1

3
private static byte[] cropNV21(byte[] img, int imgWidth, @NonNull Rect cropRect) {
    // 1.5 mean 1.0 for Y and 0.25 each for U and V
    int croppedImgSize = (int)Math.floor(cropRect.width() * cropRect.height() * 1.5);
    byte[] croppedImg = new byte[croppedImgSize];

    // Start points of UV plane
    int imgYPlaneSize = (int)Math.ceil(img.length / 1.5);
    int croppedImgYPlaneSize = cropRect.width() * cropRect.height();

    // Y plane copy
    for (int w = 0; w < cropRect.height(); w++) {
        int imgPos = (cropRect.top + w) * imgWidth + cropRect.left;
        int croppedImgPos = w * cropRect.width();
        System.arraycopy(img, imgPos, croppedImg, croppedImgPos, cropRect.width());
    }

    // UV plane copy
    // U and V are reduced by 2 * 2, so each row is the same size as Y
    // and is half U and half V data, and there are Y_rows/2 of UV_rows
    for (int w = 0; w < (int)Math.floor(cropRect.height() / 2.0); w++) {
        int imgPos = imgYPlaneSize + (cropRect.top / 2 + w) * imgWidth + cropRect.left;
        int croppedImgPos = croppedImgYPlaneSize + (w * cropRect.width());
        System.arraycopy(img, imgPos, croppedImg, croppedImgPos, cropRect.width());
    }

    return croppedImg;
}

NV21 structure:

enter image description here

P.S.: Also, if the starting position of your rectangle is odd, the U and V will be swapped. To handle this case, I use:

    if (cropRect.left % 2 == 1) {
        cropRect.left -= 1;
    }
    if (cropRect.top % 2 == 1) {
        cropRect.top -= 1;
    }