【问题标题】:Convert image from byte array to bitmap with planar 4:2:0 YUV full scale pixel format将图像从字节数组转换为平面 4:2:0 YUV 全比例像素格式的位图
【发布时间】:2017-12-07 14:16:06
【问题描述】:

更新:我联系了该设备的供应商,他们告诉我它使用的是平面 4:2:0 YUV 全尺寸像素格式。经过研究,我发现 YUV 4:2:0 似乎有 3 种主要格式:I420、J420 和 YV12。 我很兴奋,因为在 android YuvImage 类中有这种图像格式的常量,但是在运行我的代码时,我得到了以下异常:

java.lang.IllegalArgumentException: only support ImageFormat.NV21 and ImageFormat.YUY2 for now

那真是太可惜了..

之后了解了YUV420和NV21的区别:

我尝试编写一些简单的函数来交错 2 个色度平面,如 NV21 像素格式图像所示。

 public static void convertYUY420ToNV21(byte[] data_yuv420, byte[] data_yuv_N21) {
    int idx = (int) (data_yuv_N21.length * (2.0f / 3.0f));
    int j = idx;
    int chroma_plane_end = (int) (idx + ((data_yuv_N21.length - idx) / 2));

    for (int i = idx; i < chroma_plane_end; i++) {
        data_yuv_N21[j] = data_yuv420[i];
        j += 2;
    }
    j = idx + 1;
    for (int i = chroma_plane_end; i < data_yuv_N21.length; i++) {
        data_yuv_N21[j] = data_yuv420[i];
        j += 2;
    }

但是,结果似乎仍然与我的原始代码相同.. 我正在考虑的一个可能原因是字节数组的大小(1843200)。我读到对于 YUV420,一个像素的深度是 12 位。相机分辨率为 1280x720,即 921,600 像素或 1,382,400 字节。这比实际字节数组大小小三分之一。我读到飞机之间可能有一些填充物,但我一直不知道如何找到它。

YuvImage 类在其构造函数中有一个 strides 参数,但即使在阅读了 android 开发人员文档后我也不确定如何使用。

有什么线索吗?

原帖:

我遇到了以下问题:我正在尝试访问设备的摄像头,但没有提供有关所使用的摄像头类型或图像格式的信息。提供的唯一信息是关于如何检索包含视频流输出的字节数组。 然而,我发现分辨率为 1280x720,字节数组大小为 1843200。通过谷歌搜索,我偶然发现了使用 YUYV 和类似像素格式的尺寸和尺寸完全相同的相机。 基于这些知识,我编写了以下代码:

ByteArrayOutputStream out = new ByteArrayOutputStream();
            YuvImage yuv = new YuvImage(data, ImageFormat.YUY2, 1280, 720, null);
            yuv.compressToJpeg(new Rect(0, 0, 1280, 720), 100, out);
            byte[] bytes = out.toByteArray();
            bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
            if (bitmap != null) {
                ImageView cameraImageView = (ImageView) findViewById(R.id.imageView);
                cameraImageView.setImageBitmap(bitmap);
            } 

BitmapFactory.decodeByteArray 函数返回了一个有效的位图,但在显示它时我看到图像有绿色和紫色斑点,可能与颜色通道有关? 示例图片:

有没有办法找出已使用的确切像素格式/编码?我不确定从这里开始还有什么其他的尝试。 任何建议表示赞赏,谢谢!

【问题讨论】:

  • 最常见的YUV422相机格式是uyvy。
  • rawpixels.net开始,找到你从摄像头得到的缓冲区的实际格式
  • 你的链接救了我!他们给了我错误的信息。实际上格式是 RGB565 与 RGBA 像素格式!您解决了我的问题,但我认为我无法将 cmets 标记为已接受的答案? =/
  • 我很高兴我的评论有所帮助,但我无法以 SO 要求可接受的合法答案的形式重写它。欢迎您添加 RGB565 作为自我接受的答案。为了其他同事的利益,请将相机型号添加到您的答案中。

标签: java android camera image-formats pixelformat


【解决方案1】:

试试这个:

    /** 
     * Save YUV image data (NV21 or YUV420sp) as JPEG to a FileOutputStream.
     */
    public static boolean saveYUYToJPEG(byte[] imageData,File saveTo,int format,int quality,int width,int height,int rotation,boolean flipHorizontally){
      FileOutputStream fileOutputStream=null;
      YuvImage yuvImg=null;
      try {
        fileOutputStream=new FileOutputStream(saveTo);
        yuvImg=new YuvImage(imageData,format,width,height,null);
        ByteArrayOutputStream jpegOutput=new ByteArrayOutputStream(imageData.length);
        yuvImg.compressToJpeg(new Rect(0,0,width - 1,height - 1),90,jpegOutput);
        Bitmap yuvBitmap=BitmapFactory.decodeByteArray(jpegOutput.toByteArray(),0,jpegOutput.size());
        Matrix imageMatrix=new Matrix();
        if (rotation != 0) {
          imageMatrix.postRotate(rotation);
        }
        if (flipHorizontally) {
        }
        yuvBitmap=Bitmap.createBitmap(yuvBitmap,0,0,yuvBitmap.getWidth(),yuvBitmap.getHeight(),imageMatrix,true);
        yuvBitmap.compress(CompressFormat.JPEG,quality,fileOutputStream);
      }
     catch (  FileNotFoundException e) {
        return false;
      }
      return true;
    }

【讨论】:

猜你喜欢
  • 2013-07-05
  • 2016-04-06
  • 1970-01-01
  • 2013-01-14
  • 2013-07-29
  • 1970-01-01
  • 2012-11-16
  • 1970-01-01
相关资源
最近更新 更多