2016-06-28 126 views
1

我有一些代码在下面..它将YUV_420_888(android camera2 api)图像格式转换为ARGB8888并将其保存为JPEG。但结果几乎完全是绿色..任何想法如何得到这个按预期工作?YUV_420_888到ARGB变成绿色

private ByteBuffer image2ByteBuffer(Image image) { 
    Image.Plane Y = image.getPlanes()[0]; 
    Image.Plane U = image.getPlanes()[1]; 
    Image.Plane V = image.getPlanes()[2]; 

    int yRowStride = Y.getRowStride(); 
    int yPixelStride = Y.getPixelStride(); 
    int uRowStride = U.getRowStride(); 
    int uPixelStride = U.getPixelStride(); 
    int vRowStride = V.getRowStride(); 
    int vPixelStride = V.getPixelStride(); 


    ByteBuffer YBuffer = Y.getBuffer(); 
    ByteBuffer UBuffer = U.getBuffer(); 
    ByteBuffer VBuffer = V.getBuffer(); 

    YBuffer.rewind(); 
    UBuffer.rewind(); 
    VBuffer.rewind(); 

    int yb, ub, vb; 
    yb = YBuffer.capacity(); 
    ub = UBuffer.capacity(); 
    vb = VBuffer.capacity(); 

    byte[] ybb, ubb,vbb; 
    ybb = new byte[yb]; 
    ubb = new byte[ub]; 
    vbb = new byte[vb]; 

    YBuffer.get(ybb); 
    UBuffer.get(ubb); 
    VBuffer.get(vbb); 

    byte[] yData = ybb; 
    byte[] uData = new byte[yb/4]; 
    byte[] vData = new byte[yb/4]; 

    int index = 0; 
    for(int i = 0; (i < (640 * 480 * 0.5)) && (index < (640 * 480 * 0.25)); i += uPixelStride){ 
     uData[index] = ubb[i]; 
     vData[index] = vbb[i]; 
     index++; 
    } 

    byte[] yuv420sp = new byte[(int)(640 * 480 * 1.5)]; 

    // Y DATA FIRST 

    for (int i = 0 ; i < 640 * 480; i++) 
     yuv420sp[i] = yData[i]; 

    //UV INTERLEAVED DATA NEXT 

    index = 640 * 480; 
    for (int i = 0; i < (640 * 480 * 0.25); i++) { 
     yuv420sp[index] = uData[i]; 
     index++; 
     yuv420sp[index] = vData[i]; 
     index++; 
    } 



    int[] decoded = new int[640 * 480]; 
    YUV420Converter.decodeYUV420888(decoded, yuv420sp, 640, 480); 
    Bitmap bitmap = Bitmap.createBitmap(decoded, 640, 480, Bitmap.Config.ARGB_8888); 
    ByteBuffer byteBuffer = ByteBuffer.allocate(640 * 480 * 4); 
    bitmap.copyPixelsToBuffer(byteBuffer); 
    bitmap.recycle(); 
    return byteBuffer; 
} 

代码的下位是从的ImageReader

public void onImageAvailable(ImageReader reader) { 

     Image image = reader.acquireLatestImage(); 

     ByteBuffer byteBuffer = image2ByteBuffer(image); 

     saveImage(byteBuffer); 
     byteBuffer.clear(); 
     image.close(); 
    } 

    public void saveImage(ByteBuffer imageByteBuffer) { 
     try { 
      imageByteBuffer.rewind(); 
      Bitmap imageBitmap = Bitmap.createBitmap(WIDTH, HEIGHT, Bitmap.Config.ARGB_8888); 
      imageBitmap.copyPixelsFromBuffer(imageByteBuffer); 
      String filePath = Environment.getExternalStorageDirectory().getPath() 
        + "/pic" + mImagesCount + ".png"; 
      FileOutputStream fileOutputStream = new FileOutputStream(filePath); 

      imageBitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream); 

      //fileOutputStream.write(imageByteArray); 
      fileOutputStream.flush(); 
      fileOutputStream.close(); 
      imageBitmap.recycle(); 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

用于解码到ARGB一旦我们有一个正确格式化YUV

public static void decodeYUV420888(int[] rgb, byte[] yuv420sp, int width, int height) { 

    final int frameSize = width * height; 

    for (int j = 0, yp = 0; j < height; j++) {  int uvp = frameSize + (j >> 1) * width, u = 0, v = 0; 
     for (int i = 0; i < width; i++, yp++) { 
      int y = (0xff & ((int) yuv420sp[yp])) - 16; 
      if (y < 0) 
       y = 0; 
      if ((i & 1) == 0) { 
       v = (0xff & yuv420sp[uvp++]) - 128; 
       u = (0xff & yuv420sp[uvp++]) - 128; 
      } 

      int y1192 = 1192 * y; 
      int b = (y1192 + 1634 * v); 
      int g = (y1192 - 833 * v - 400 * u); 
      int r = (y1192 + 2066 * u); 

      if (r < 0)     r = 0;    else if (r > 262143) 
       r = 262143; 
      if (g < 0)     g = 0;    else if (g > 262143) 
       g = 262143; 
      if (b < 0)     b = 0;    else if (b > 262143) 
       b = 262143; 

      rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff); 
     } 
    } 
} 
+0

要跟进这个..我实现了答案讨论[这里](http://stackoverflow.com/questions/36212904/yuv-420-888-interpretation-on-samsung-galaxy-s7-camera2) – Arjun

回答

1

显然有一个与API 21个问题,但是这在API 22中解决。
我在以下帖子中发现了这个:yuv_420_888-to-rgb
有关此主题的另一个出色的后可以在这里找到:Solving some android problems

希望这有助于!

+0

我会尽快检查并将其标记为答案,如果它是修复( – Arjun

+0

它是否解决了您的问题? – Reyske

+1

对不起,优先级在这里转换了一下,会有点忙,但这是在我的盘子上测试,验证并关闭 – Arjun