使用ImageReader读取RGB图像

时间:2014-09-10 23:25:45

标签: android android-camera

我正在尝试使用ImageReader从相机中获取RGB图像。我在运行开发人员预览的Nexus 5上使用Android 5.0“L”的Camera2 API。

我已经为RGB图像配置了SurfaceView工作正常,我知道相机硬件会生成RGB数据(因为Android上的所有色调映射和颜色增益设置都指定为在RGB通道上运行)。

我可以通过以这种方式创建ImageReader从ImageReader获取YUV_420_888图像:

imageReader = ImageReader.newInstance(W, H, ImageFormat.YUV_420_888, 4);

然后将YUV图像转换为RGB。然而,这引入了不需要的量化误差(因为我的应用需要RGB图像)和不必要的处理时间。

然而,当我尝试以这种方式创建图像阅读器时:

imageReader = ImageReader.newInstance(W, H, PixelFormat.RGB_888, 4);

图像捕获失败,但出现以下异常:

java.lang.UnsupportedOperationException: The producer output buffer format 0x22 doesn't match the ImageReader's configured buffer format 0x3.
        at android.media.ImageReader.nativeImageSetup(Native Method)
        at android.media.ImageReader.acquireNextSurfaceImage(ImageReader.java:293)
        at android.media.ImageReader.acquireNextImage(ImageReader.java:339)
        at android.media.ImageReader.acquireLatestImage(ImageReader.java:243)
        at <my code...>

我在两条战线上感到困惑。首先,提到的输出格式0x22不在PixelFormat或ImageFormat中。它似乎是某种未记录的原始模式,但我无法使用ImageReader.newInstance(W, H, 0x22, 4)来捕获它(我得到java.lang.UnsupportedOperationException: Invalid format specified 34)。我希望能够以原始格式捕获,但我不能说服ImageFormat接受它(并且其他原始格式ImageFormat.RAW_SENSOR由于某种原因而非常慢)。

其次,SurfaceView已经乐于消费RGB_888张图片(据我所知),并将它们直接放在屏幕上。那么为什么ImageReader不能正确接受RGB图像呢?我做错了什么?

1 个答案:

答案 0 :(得分:-2)

尝试这个从图像中获取RGB,它对我有用:

private byte[] rgbValuesFromBitmap(Bitmap bitmap)
{
    ColorMatrix colorMatrix = new ColorMatrix();
    ColorFilter colorFilter = new ColorMatrixColorFilter(
            colorMatrix);
    Bitmap argbBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(),
            Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(argbBitmap);

    Paint paint = new Paint();

    paint.setColorFilter(colorFilter);
    canvas.drawBitmap(bitmap, 0, 0, paint);

    int width = bitmap.getWidth();
    int height = bitmap.getHeight();
    int componentsPerPixel = 3;
    int totalPixels = width * height;
    int totalBytes = totalPixels * componentsPerPixel;

    byte[] rgbValues = new byte[totalBytes];
    @ColorInt int[] argbPixels = new int[totalPixels];
    argbBitmap.getPixels(argbPixels, 0, width, 0, 0, width, height);
    for (int i = 0; i < totalPixels; i++) {
        @ColorInt int argbPixel = argbPixels[i];
        int red = Color.red(argbPixel);
        int green = Color.green(argbPixel);
        int blue = Color.blue(argbPixel);
        rgbValues[i * componentsPerPixel + 0] = (byte) red;
        rgbValues[i * componentsPerPixel + 1] = (byte) green;
        rgbValues[i * componentsPerPixel + 2] = (byte) blue;
    }

    return rgbValues;
}

谢谢。