0

I have tried to use the logic and pictorial representation from this SO. I am though confused with the images since one of them follow 4:1:1 whereas the later one does 4:2:2 nomenclature for YUV image (NV21).

Right now the issue is that i get an image (converted to Bitmap/PNG) with YUV component all over, essentially an unusable image. Any recommendation to fix this?

    private byte[] cropImage(byte[] data, Rect cropRect) {
        int dataHeight = 480;
        int dataWidth = 640;

        int totalWH = dataWidth * dataHeight;

        // make rect points even, currently the width & height is even number
        // adjust x coordinates to make them
        if (cropRect.left % 2 != 0 || cropRect.right % 2 != 0) {
            cropRect.left -= 1;
            cropRect.right -= 1;
        }
        // adjust y coordinates to make them even
        if (cropRect.top % 2 != 0 || cropRect.bottom % 2 != 0) {
            cropRect.top -= 1;
            cropRect.bottom -= 1;
        }

        int area = cropRect.width() * cropRect.height() * 3/2;
        Logger.getLogger().d("Size of byte array " + data.length + " Size of alloc area " + area);

        byte[] pixels = new byte[area];//the size of the array is the dimensions of the sub-photo

//        size.total = size.width * size.height;
//        y = yuv[position.y * size.width + position.x];
//        u = yuv[(position.y / 2) * (size.width / 2) + (position.x / 2) + size.total];
//        v = yuv[(position.y / 2) * (size.width / 2) + (position.x / 2) + size.total + (size.total / 4)];

        try {
            // copy Y plane first
            int srcOffset = cropRect.top * dataWidth;
            int destOffset = 0;
            int lengthToCopy = cropRect.width();

            int y = 0;
            for (; y < cropRect.height(); y++, srcOffset += dataWidth, destOffset += cropRect.width()) {
//            Logger.getLogger().d("IO " + srcOffset + cropRect.left + " oO " + destOffset + " LTC " + lengthToCopy);
                System.arraycopy(data, srcOffset + cropRect.left, pixels, destOffset, lengthToCopy);
            }

            Logger.getLogger().d("Completed Y copy");
            // U and V components are not-interleaved, hence their size is just 1/4th the original size
            // copy U plane
            int nonYPlanerHeight = dataHeight / 4;
            int nonYPlanerWidth = dataWidth / 4;
            srcOffset = totalWH + (cropRect.top / 4 * nonYPlanerWidth);

            for (y = 0; y < cropRect.height();
                 y++, srcOffset += nonYPlanerWidth, destOffset += cropRect.width() / 4) {
                System.arraycopy(data, srcOffset + cropRect.left / 4, pixels, destOffset, cropRect.width() / 4);
            }
            Logger.getLogger().d("Completed U copy " + y + " destOffset=" + destOffset);

            // copy V plane
            srcOffset = totalWH + totalWH / 4 + (cropRect.top / 4 * nonYPlanerWidth);

            for (y = 0; y < cropRect.height();
                 y++, srcOffset += nonYPlanerWidth, destOffset += cropRect.width() / 4) {
                System.arraycopy(data, srcOffset + cropRect.left / 4, pixels, destOffset, cropRect.width() / 4);
            }
            Logger.getLogger().d("Completed V copy " + y + " destOffset=" + destOffset);
        } catch (ArrayIndexOutOfBoundsException ae) {
            // do nothing
            Logger.getLogger().e("Exception " + ae.getLocalizedMessage());
        }

        return pixels;
    }
banerjk
  • 335
  • 2
  • 15
  • The current implementation is based on 4:1:1 format since the total area allocation is 1.5 * width * height, which implies that U and V components are 1/4 the size. – banerjk Feb 09 '18 at 14:59
  • Found the root cause for really bad image - was passing the only byte[] instead of the cropped one. I though still see some banding of chroma image diagonally across the image. What could be wrong? – banerjk Feb 09 '18 at 16:41

0 Answers0