2013-12-03 14 views
8

Tôi có byte[] yuvByteArray (hình ảnh 540x360 được chụp từ phương pháp Camera.PreviewCallback.onPreviewFrame và được chuyển vào tệp assets/yuv.bin). Tôi muốn chuyển đổi byte[] yuv thành byte[] rgba mảng, sử dụng mã sau (dựa trên ví dụ android của LivePreview).Cách sử dụng ScriptIntrinsicYuvToRGB (chuyển đổi byte [] yuv sang byte [] rgba)

Nhưng tôi nhận được outBytes mảng rgba chứa đầy số không sau khi forEach và sao chép phân bổ out thành outBytes. Có gì sai với mã của tôi?


package hellorender;   
import android.app.Activity; 
import android.content.res.AssetManager; 
import android.graphics.Bitmap; 
import android.os.Bundle; 
import android.support.v8.renderscript.Allocation; 
import android.support.v8.renderscript.Element; 
import android.support.v8.renderscript.RenderScript; 
import android.support.v8.renderscript.ScriptIntrinsicYuvToRGB; 
import android.support.v8.renderscript.Type; 
import android.widget.ImageView; 
import hellorender.R; 

import java.io.IOException; 
import java.io.InputStream; 

public class HelloRenderActivity extends Activity { 

    public static final int W = 540; 
    public static final int H = 360; 
    private RenderScript rs; 
    private ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     AssetManager assets = getAssets(); 
     byte[] yuvByteArray = new byte[291600]; 
     byte[] outBytes = new byte[W * H * 4]; 

     InputStream is = null; 
     try { 
      is = assets.open("yuv.bin"); 
      System.out.println("read: " + is.read(yuvByteArray)); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      try { 
       is.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 

     ImageView iv = (ImageView) findViewById(R.id.image); 
     rs = RenderScript.create(this); 
     yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.RGBA_8888(rs)); 


     Type.Builder yuvType = new Type.Builder(rs, Element.U8(rs)) 
       .setX(W).setY(H) 
       .setYuvFormat(android.graphics.ImageFormat.NV21); 
     Allocation in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT); 


     Type.Builder rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)) 
       .setX(W).setY(H); 
     Allocation out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT); 

     in.copyFrom(yuvByteArray); 

     yuvToRgbIntrinsic.setInput(in); 
     yuvToRgbIntrinsic.forEach(out); 

     out.copyTo(outBytes); 

     Bitmap bmpout = Bitmap.createBitmap(W, H, Bitmap.Config.ARGB_8888); 
     out.copyTo(bmpout); 

     iv.setImageBitmap(bmpout); 
    } 

} 

Trả lời

10

tập tin yuv.bin chắc chắn là ở định dạng NV21, vì nó chụp đây http://developer.android.com/reference/android/hardware/Camera.PreviewCallback.html#onPreviewFrame

phương pháp setYuvFormat là từ cấp API 18, tôi loại bỏ nó

Vì vậy, mã này hoạt động tốt:

rs = RenderScript.create(this); 
    yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs)); 

    Type.Builder yuvType = new Type.Builder(rs, Element.U8(rs)).setX(yuvByteArray.length); 
    Allocation in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT); 

    Type.Builder rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(W).setY(H); 
    Allocation out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT); 

    in.copyFrom(yuvByteArray); 

    yuvToRgbIntrinsic.setInput(in); 
    yuvToRgbIntrinsic.forEach(out); 
+0

Rất vui khi bạn có thể làm cho nó hoạt động. Thật không may, bản chất và hầu hết các RenderScript không được tài liệu hóa tốt nên thật dễ dàng để có những điều kỳ lạ như thế này. –

+0

Làm cách nào để nhận được mảng byte RGB được chuyển đổi? –

+0

Điều này là điên nhanh so với việc có rutine thực hiện trong java tinh khiết !! – slott

0

Thay đổi kiểu đầu ra của bạn truyền cho constructor của ScriptIntrinsicYubToRGBElement.U8_4 thay vì Element.RGBA_8888. Bạn sẽ cần tương tự cho Type.Builder được sử dụng để tạo đầu ra Allocation.

+0

outBytes điền với số không lần nữa. – wilddev

+0

Và có một vụ tai nạn Nguyên nhân: android.support.v8.renderscript.RSIllegalArgumentException: Allocation loại là USER, gõ UNSIGNED_8 của 4 byte, bitmap qua là ARGB_8888 sau 'out.copyTo (bmpout); ' – wilddev

+0

Thay đổi '.setYuvFormat' để sử dụng' android.graphics.ImageFormat.YV21' thay vì 'android.graphics.ImageFormat.NV21', trừ khi nhị phân thô của bạn là YUV nhiều kế hoạch. Trong trường hợp đó, hãy sử dụng 'android.graphics.ImageFormat.YUV_420_888'. –

1

Ứng dụng thử nghiệm nội bộ của chúng tôi sử dụng trình tự sau để tạo phân bổ YUV.

tb = new Type.Builder(mRS, Element.createPixel(mRS, 
       Element.DataType.UNSIGNED_8, Element.DataKind.PIXEL_YUV)); 
    tb.setX(mWidth); 
    tb.setY(mHeight); 
    tb.setYuvFormat(android.graphics.ImageFormat.NV21); 
    mAllocationIn = Allocation.createTyped(mRS, tb.create(), Allocation.USAGE_SCRIPT); 

Sau đó bên trong gọi lại rằng dữ liệu YUV mới có sẵn làm

mAllocationIn.copyFrom(theYuvByteArray); 
1

Sử dụng API18 + câu trả lời wilddev có thể được cải thiện một chút như bạn không cần đối tượng Type.Builder. Có phải tất cả những thứ này trong onCreate() phương pháp:

aIn = Allocation.createSized(rs, Element.U8(rs), H*W*3/2); // what the f**k ? This is 12 bit per pixel, giving the length of the camera data byte array ! 

bmpout = Bitmap.createBitmap(W, H, Bitmap.Config.ARGB_8888); // you will need this bitmap for output anyway 

aOut = Allocation.createFromBitmap(rs, bmpout); // tada ! 

// and set the script´s input 
yuvToRgbIntrinsic.setInput(aIn); 

// as pixel data are stored as int (one byte for red, green, blue, alpha), you first need an int[] array 
int rgba[] = new int[w*h]; // the rgba[] array 

Bây giờ bạn có thể tiếp tục với những dòng hay đặt chúng vào các) phương pháp onPreviewFrame (:

aIn.copyFrom(data); // or aIn.copyFromUnchecked(data); // which is faster and safe for camera data 

yuvToRgbIntrinsic.forEach(aOut); // execute the script 

aOut.copyTo(bmpout); // copy result from aOut to bmpout 

// if you need the rgba-values, do 
bmpout.getPixels(rgba, 0, W, 0, 0, W, H); 

// now you may loop through the rgba[] array and extraxt the r,g,b,a values 
// and put them into a byte[] array(s), BUT this will surely have impact on the performance when doing in Java 
Các vấn đề liên quan