Android ScriptIntrinsicYuvToRGB或YUV420分配已中断?

Android ScriptIntrinsicYuvToRGB或YUV420分配已中断?,android,renderscript,android-renderscript,Android,Renderscript,Android Renderscript,我尝试使用renderscript中的ScriptIntrinsicYuvToRGB类进行YUV到RGB的转换,其中源代码为YUV420格式。 我有3个原始平面,我从文件中读取并尝试将它们输入YUV类型的分配,然后通过ScriptIntrinsicYuvToRGB.forEach传递它 它正确地转换亮度(Y平面),但在颜色上失败,因为色度通道似乎从buf[w*h]位置读取所有值-请参阅代码示例中的注释部分。当分配没有正确处理UV平面时,它看起来像一个bug。我这样认为是因为我在脚本中使用分配上的

我尝试使用renderscript中的ScriptIntrinsicYuvToRGB类进行YUV到RGB的转换,其中源代码为YUV420格式。 我有3个原始平面,我从文件中读取并尝试将它们输入YUV类型的分配,然后通过ScriptIntrinsicYuvToRGB.forEach传递它

它正确地转换亮度(Y平面),但在颜色上失败,因为色度通道似乎从buf[w*h]位置读取所有值-请参阅代码示例中的注释部分。当分配没有正确处理UV平面时,它看起来像一个bug。我这样认为是因为我在脚本中使用分配上的
rsGetElementAtYuv\U uchar\U
函数进行了测试,它为任何坐标提供了相同的值(从buf[w*h])

如果我能进一步指定YUV格式,比如跨距/偏移量等,我搜索了所有地方,但除了设置
Element.DataKind.PIXEL\u-YUV
Type.Builder.setYuvFormat(ImageFormat.YUV\u 420\u 888)
之外,我没有找到任何其他内容

有人能帮忙吗

{
      int w = 320, h = 172;
      ScriptIntrinsicYuvToRGB yc = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));
      {
         Element elemYUV = Element.createPixel(rs, Element.DataType.UNSIGNED_8, Element.DataKind.PIXEL_YUV);
         Type typeYUV = new Type.Builder(rs, elemYUV).setX(w).setY(h).setYuvFormat(ImageFormat.YUV_420_888).create();
         Allocation yuv = Allocation.createTyped(rs, typeYUV);
         byte[] buf = new byte[yuv.getBytesSize()];
         int offs = 0;
         for(int i=0; i<3; i++){
            int sz = w*h;
            if(i>0)
               sz /= 4;
            InputStream is = new FileInputStream("/sdcard/yuv/"+(i==0 ? 'y' : i==1 ? 'u' : 'v'));
            int n = is.read(buf, offs, sz);
            if(n!=sz)
               throw new AssertionError("!");
            offs += sz;
            is.close();
         }
//               buf[w*h] = 0x40;
         yuv.copyFrom(buf);
         yc.setInput(yuv);
      }

      Type outType = new Type.Builder(rs, Element.U8_4(rs)).setX(w).setY(h).create();
      Allocation out = Allocation.createTyped(rs, outType);
      yc.forEach(out);

      int[] buf = new int[out.getBytesSize()/4];
      out.copy1DRangeToUnchecked(0, w*h, buf);

      bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
      bm.setPixels(buf, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
      iv.setImageBitmap(bm);

      yc.destroy();
   }
{
int w=320,h=172;
scriptintrinsicyuvtorgbyc=ScriptIntrinsicYuvToRGB.create(rs,Element.U8_4(rs));
{
Element-elemYUV=Element.createPixel(rs,Element.DataType.UNSIGNED_8,Element.DataKind.PIXEL_-YUV);
Type typeYUV=new Type.Builder(rs,elemYUV).setX(w).setY(h).setYuvFormat(ImageFormat.YUV_420_888).create();
分配yuv=分配.createTyped(rs,typeYUV);
byte[]buf=新字节[yuv.getBytesSize()];
整数=0;
对于(int i=0;i0)
sz/=4;
InputStream is=newfileinputstream(“/sdcard/yuv/”+(i==0?'y':i==1?'u':'v');
int n=正在读取(buf、OFF、sz);
如果(n!=sz)
抛出新断言错误(“!”);
offs+=sz;
is.close();
}
//buf[w*h]=0x40;
yuv.copyFrom(buf);
yc.设置输入(yuv);
}
Type outType=new Type.Builder(rs,Element.U8_4(rs)).setX(w).setY(h).create();
分配输出=分配。创建类型(rs,输出类型);
yc.forEach(out);
int[]buf=new int[out.getBytesSize()/4];
out.copy1DRangeToUnchecked(0,w*h,buf);
bm=Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
setPixels(buf,0,bm.getWidth(),0,0,bm.getWidth(),bm.getHeight());
iv.设置图像位图(bm);
yc.destroy();
}

一种解决方案是只需填写U8分配,然后在自定义脚本中自己编制索引:

#pragma rs_fp_relaxed
rs_allocation yuv_in;
uint32_t width;
uint32_t offset_to_u;
uint32_t offset_to_v;
uchar4 RS_KERNEL yuv_to_rgba(uint32_t x, uint32_t y) {
    uint32_t index = y * width + x;
    uint32_t uv_index = (y >> 1) * width + (x >> 1);
    float Y = (float)rsGetElementAt_uchar(yuv_in, index);
    float U = (float)rsGetElementAt_uchar(yuv_in, uv_index + offset_to_u);
    float V = (float)rsGetElementAt_uchar(yuv_in, uv_index + offset_to_v);
    float3 f_out;
    f_out.r = Y + 1.403f * V;
    f_out.g = Y - 0.344f * U - 0.714f * V;
    f_out.b = Y + 1.770f * U;
    f_out = clamp(f_out, 0.f, 255.f);
    uchar4 out;
    out.rgb = convert_uchar3(f_out);
    out.a = 255;
    return out;
}
爪哇:


YUV_420_888更像是一种通用的YUV类型,用于从android中的其他YUV资源导入。我认为没有办法为u/v平面设置跨距/偏移值,使其对自定义转换有用。

我认为您的类型需要
setYuvFormat()
。以下是我用来构建分配的两行代码:

typeYUV=Type.Builder(rs,Element.YUV(rs)).setYuvFormat(ImageFormat.NV21.create();
分配yuv=分配.createSize(rs,类型yuv.element,宽度*高度*3/2);
sc.set_yuv_in(yuv_allocation);
sc.set_width(width);
sc.set_offset_to_u(width * height);
sc.set_offset_to_v(width * height + (width/2 * height/2));
sc.forEach_yuv_to_rba(out);