【问题标题】:Renderscript conversion from ARGB8888 to RGB565从 ARGB8888 到 RGB565 的渲染脚本转换
【发布时间】:2013-04-03 18:59:36
【问题描述】:

我正在接收 ARGB8888 格式的位图,但我需要通过一些仅接受 RGB565 的算法对其进行处理。我想使用 Renderscript 将此位图转换为新格式,但似乎分配入和分配出应该相等(或兼容)。 bitmapIn 是 ARGB_8888 类型,bitmapOut 是 RGB_565 类型

原因:android.renderscript.RSIllegalArgumentException:分配类型为 PIXEL_RGBA,类型为 UNSIGNED_8 的 4 个字节,传递的位图为 RGB_565

Java:

public void convert(final Bitmap bitmapIn, Bitmap bitmapOut)
{
    mInAllocation = Allocation.createFromBitmap(mRS, bitmapIn, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
    Type.Builder tb = new Type.Builder(mRS, Element.RGB_565(mRS)).setX(bitmapIn.getWidth()).setY(bitmapOut.getWidth());
    mOutAllocation = Allocation.createTyped(mRS, tb.create());
    // Call custom method (not forEach_root) so we can have uchar4 in and uchar3 out
    mScript.forEach_convert(mInAllocation, mOutAllocation);
    mOutAllocation.copyTo(bitmapOut);
}

渲染脚本:

// Convert to RGB565 by quantizing the individual channels
void convert(const uchar4* v_in, uchar3* v_out)
{
    v_out->x = v_in->x >> 3;
    v_out->y = v_in->y >> 2;
    v_out->z = v_in->z >> 3;
}

请注意,如果我将两个位图都制作为 ARGB_8888 并且在两个 uchar4* 上都使用 convert()(并且只复制 alpha (w) 通道,那么我会看到位图被更改了。

我知道 565 等于 16 位,所以实际上它更可能是 uchar2,但它也与类型分配不兼容。

如何在 Renderscript 中进行这种类型转换?

【问题讨论】:

    标签: android type-conversion renderscript


    【解决方案1】:

    我找不到与 RGB565 图像一起使用的正确 Renderscript 类型,但 uint16_t 可以工作(至少在 Nexus S 上)。正如 Tim Murray 的回答,您必须分别绑定输入或输出分配。

    这是执行转换的 Renderscript,其中输入 RGB8888 分配被单独绑定,并且 rsForEach 在 RGB565 分配上被调用:

    #pragma version(1)
    #pragma rs java_package_name(uk.co.massycat.renderscriptfun.rsfun)
    
    rs_allocation gInImage;
    
    void root(const uint16_t *v_in, uint16_t *v_out, const void *usrData, uint32_t x, uint32_t y) {
        uint16_t colour = 0;
    
        const uchar4 *in_pixel = rsGetElementAt(gInImage, x, y);
    
        uint32_t red = in_pixel->r;
        uint32_t green = in_pixel->g;
        uint32_t blue = in_pixel->b;
    
        red >>= 3;
        green >>= 2;
        blue >>= 3;
    
        // red (5 bits)
        colour |= red << 11;
        // green (6 bits)
        colour |= green << 5;
        // blue (5 bits)
        colour |= blue << 0;
    #if 0
        // red (5 bits)
        colour |= 0x0 << 11;
        // green (6 bits)
        colour |= 0x0 << 5;
        // blue (5 bits)
        colour |= 0x1f << 0;
    #endif
    
        *v_out = colour;
    }
    
    void doWork( rs_script script, rs_allocation alloc_out) {
        rsForEach(script, alloc_out, alloc_out);
    }
    

    在 RGB565 分配上调用 rsForEach 时,在 Java 端,您必须调用 invoke_doWork 脚本对象方法而不是 forEach_root 脚本对象方法,因为 forEach_root 调用将对 RGB565 分配进行类型检查并抛出异常说明与 U16 不兼容。

    这里是Java端:

    mInImageAllocation = Allocation.createFromBitmap(mRS, mInBitmap,
                Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
    Type.Builder tb = new Type.Builder(mRS, Element.RGB_565(mRS)).setX(mInBitmap.getWidth()).setY(mInBitmap.getHeight());
    mOutAllocation = Allocation.createTyped(mRS, tb.create());
    
    mScript.set_gInImage(mInImageAllocation);
    
    mScript.invoke_doWork(mScript, mOutAllocation);
    Bitmap tmp_bitmap = Bitmap.createBitmap(mInBitmap.getWidth(), mInBitmap.getHeight(), Bitmap.Config.RGB_565);
    mOutAllocation.copyTo(tmp_bitmap);
    
    mAnImageView.setImageBitmap(tmp_bitmap);
    mAnImageView.invalidate();
    

    【讨论】:

      【解决方案2】:

      最简单的方法是仅将输出分配传递给内核,并将输入分配绑定为 rs_allocation。使用 rsGetElementAt_uchar4 访问分配,进行转换,并返回一个short。

      【讨论】:

      • 我仍然收到类型转换错误:RSRuntimeException:类型与 U16 不匹配! RS函数:ushort __attribute__((kernel)) root(uint32_t x, uint32_t y) { return 65535; Java:输入为 RGBA_8888,输出为 RGB_565,通过 mScript.set_in_allocation(mAllocationIn) 绑定;
      猜你喜欢
      • 2013-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多