简体   繁体   English

Renderscript从ARGB8888转换为RGB565

[英]Renderscript conversion from ARGB8888 to RGB565

I'm receiving Bitmaps in ARGB8888 format, but I need to process it through some algorithm that only accepts RGB565. 我正在接收ARGB8888格式的位图,但是我需要通过一些仅接受RGB565的算法对其进行处理。 I want to convert this bitmap to the new format using Renderscript but it seems the allocation in and allocation out should be of equal (or compatible). 我想使用Renderscript将该位图转换为新格式,但似乎分配入和分配出应该相等(或兼容)。 bitmapIn is of type ARGB_8888 and bitmapOut is of type RGB_565 bitmapIn的类型为ARGB_8888,bitmapOut的类型为RGB_565

Caused by: android.renderscript.RSIllegalArgumentException: Allocation kind is PIXEL_RGBA, type UNSIGNED_8 of 4 bytes, passed bitmap was RGB_565 引起:android.renderscript.RSIllegalArgumentException:分配类型为PIXEL_RGBA,类型为4字节的UNSIGNED_8,传递的位图为RGB_565

Java: 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);
}

Renderscript: 的renderScript:

// 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;
}

Note that if I make both bitmaps ARGB_8888 and have convert() working on both uchar4* (and just copy the alpha (w) channel, then I see the bitmap being altered. 请注意,如果我同时制作两个位图ARGB_8888并且在两个uchar4 *上都使用convert()(并且只复制alpha(w)通道,那么我会看到位图被更改)。

I know that 565 equals 16 bits, so in reality its more likely a uchar2, but it also is incompatible with the allocation in type. 我知道565等于16位,因此实际上它更可能是uchar2,但它也与类型分配不兼容。

How can one do this type conversions in Renderscript? 如何在Renderscript中进行这种类型转换?

The easiest way to do it is to pass only the output allocation to the kernel and instead bind the input allocation as an rs_allocation. 最简单的方法是将输出分配仅传递给内核,而是将输入分配绑定为rs_allocation。 Access the allocation using rsGetElementAt_uchar4, do the conversion, and return a short. 使用rsGetElementAt_uchar4访问分配,进行转换,然后返回简短内容。

I cannot find the correct Renderscript type to use with a RGB565 image but uint16_t works (at least on a Nexus S). 我找不到适用于RGB565图像的正确Renderscript类型,但uint16_t可以工作(至少在Nexus S上有效)。 As in Tim Murray's answer you have to bind either the input or output Allocation separately. 正如Tim Murray的回答一样,你必须分别绑定输入或输出Allocation。

Here is the Renderscript to do the conversion where the input RGB8888 Allocation is bound separately and the rsForEach is called on the RGB565 Allocation: 以下是进行转换的Renderscript,其中输入RGB8888分配单独绑定,并且在RGB565分配上调用rsForEach:

#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);
}

When calling rsForEach on the RGB565 Allocation, on the Java side, you have to call the invoke_doWork script object method instead of the forEach_root script object method as the forEach_root call will do type checking on the RGB565 Allocation and throw an exception saying it is not compatible with U16. 在Java端在RGB565分配上调用rsForEach时,您必须调用invoke_doWork脚本对象方法而不是forEach_root脚本对象方法,因为forEach_root调用将对RGB565分配进行类型检查,并抛出异常,指出该兼容性不兼容与U16。

Here is the Java side: 这是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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM