Проблема при упаковке 4 uchar в int (RenderScript) - PullRequest
0 голосов
/ 09 января 2019

В моей программе RenderScript я хочу вернуть 32-битное целое число, представляющее цвет (чтобы быть непосредственно цветом в среде Java), поэтому я делаю это следующим образом:

Код RS:

static const uchar k = 51;
static const uchar d = 5;
static int32_t histo[52][52][52];
....

int __attribute__((kernel)) getResult() {
    int maximum = 0;
    uchar3 vect = {0, 0, 0};
    ....
    loops through histogram and puts max's coordinates into vect
    ...
    // Convert coords back to [0, 255] space
    vect.r = (uchar) (vect.s0*d + d/2);
    vect.g = (uchar) (vect.s1*d + d/2);
    vect.b = (uchar) (vect.s2*d + d/2);

    return (0xff) << 24 | (vect.r & 0xff) << 16 | (vect.g & 0xff) << 8 | (vect.b & 0xff);
}

Java-код:

 Allocation bmpAlloc = Allocation.createFromBitmap(rs, bitmap);

 // Allocation where to store the result color (for output purposes)
 Allocation colorAlloc = Allocation.createSized(rs, Element.I32(rs), 1);

 ScriptC_findcolor scriptC = new ScriptC_findcolor(rs);
 scriptC.forEach_channelHist(bmpAlloc);
 scriptC.forEach_getResult(colorAlloc);

 int[] a = new int[1];
 colorAlloc.copyTo(a);
 int color = a[0];

Он отлично работает при использовании эмулятора x86, но по какой-то причине с реальным устройством значение, полученное на стороне Java, совершенно случайно.

Как видите, альфа-канал жестко закодирован в 255 (0xff) в скрипте .rs, но на стороне Java значение совсем не равно 255 (102, 164 ...).

Может кто-нибудь помочь? Спасибо

1 Ответ

0 голосов
/ 10 января 2019

Хорошо, я получил это благодаря ответу (спасибо @Izacus) на андроидев reddit. Во-первых:

  • vect.r & 0xff и другие операции обрезания в операторе return ничего не сделают, потому что vect.r - это uchar, и он будет сам охватывать диапазон [0, 255]. Поэтому, чтобы избежать путаницы, я изменил эту строку на:

    return 0xff << 24 | vect.r << 16 | vect.g << 8 | vect.b;
    
  • Использование типа int опасно при нацеливании на несколько платформ, вместо этого используйте int32_t.

Итак, проблема заключалась в битовой операции. vect.r, vect.g и vect.b являются беззнаковыми символами, и при суммировании их с оператором | для создания со знаком , по-видимому, возникает переполнение или сдвиг 32-битное целое число.

Чтобы исправить это, я изменил uchar3 vect; на int3 vect;

...