Преобразование Renderscript из ARGB8888 в RGB565

Я получаю растровые изображения в формате ARGB8888, но мне нужно обработать их с помощью некоторого алгоритма, который принимает только RGB565. Я хочу преобразовать это растровое изображение в новый формат с помощью Renderscript, но кажется, что распределение на входе и выходе должно быть одинаковым (или совместимым). bitmapIn имеет тип ARGB_8888, а bitmapOut имеет тип RGB_565.

Вызвано: android.renderscript.RSIllegalArgumentException: вид выделения — PIXEL_RGBA, тип UNSIGNED_8 из 4 байт, переданное растровое изображение — RGB_565.

Ява:

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 и заставлю convert() работать с обоими uchar4* (и просто скопирую альфа-(w)-канал, то я увижу, что растровое изображение изменено.

Я знаю, что 565 равно 16 битам, так что на самом деле это скорее uchar2, но это также несовместимо с распределением по типу.

Как можно сделать это преобразование типа в Renderscript?


person BCL    schedule 03.04.2013    source источник


Ответы (2)


Я не могу найти правильный тип Renderscript для использования с изображением RGB565, но uint16_t работает (по крайней мере, на Nexus S). Как и в ответе Тима Мюррея, вы должны отдельно привязать входное или выходное распределение.

Вот 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);
}

При вызове rsForEach для выделения RGB565 на стороне 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();
person Massycat    schedule 20.04.2013

Самый простой способ сделать это — передать ядру только выделение вывода и вместо этого привязать выделение ввода как rs_allocation. Получите доступ к выделению с помощью rsGetElementAt_uchar4, выполните преобразование и верните короткий.

person Tim Murray    schedule 04.04.2013
comment
Я все еще получаю ошибки преобразования типов: 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); - person BCL; 04.04.2013