2016-06-28 10 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

ответ

0

Просто, чтобы закрыть это до .. Я работаю с Samsung Note 5 и реализовали решение в ссылке ниже

YUV_420_888 interpretation on Samsung Galaxy S7 (Camera2)

UPDATE:

Просто упакуйте кто-то натыкается на это. .. вот пример renderscript преобразования изображений yuv420sp (NV21) в RGBA.

https://www.rounds.com/blog/unleash-power-gpu-renderscript/

Совмещенный, оба эти решающие уровни камеры API 1/2 YUV_XX - проблемы> RGBA. Счастливое кодирование!

1

Видимо есть проблема с API 21 , но это разрешено в API 22.
Я нашел это в следующем посте: yuv_420_888-to-rgb
Еще один отличный пост по этой теме можно найти здесь: Solving some android problems

Надеюсь, это поможет!

+0

Я буду проверять это как можно скорее и пометить его как ответ, если это исправление (: – Arjun

+0

это исправить вашу проблему?) – Reyske

+1

Извините, приоритеты менялись немного здесь, будут немного заняты, но это на моей тарелке, чтобы проверить , подтвердите и закройте – Arjun