Преобразование типов JNI + (например, подписанный короткий в неподписанный короткий) - PullRequest
1 голос
/ 31 января 2011

Я в аду JNI с типографскими конверсиями в wazoo:

Вот общий поток вещей:

  • прочитайте файл, и он вернет меня с 1D массив поплавков.
  • конвертировать эти плавает [] в шорты [] (* 4095, я хочу 12-битное число)
  • передать эти шорты [] С, который дублирует их в короткий массив без знака
  • перевернуть биты сделать биты с прямым порядком байтов Java little-endian для обработки изображений
  • преобразовать эти новые числа в двойной [] (/ 4095)
  • передать двойной [] функция обработки изображений
  • конвертировать обработанный двойной [] обратно в короткий [] (* 4095)
  • коротко перевернуть биты [] назад к big-endian
  • конвертировать short [] обратно в число с плавающей точкой (/ 4095), передать обратно в Java
  • передать float [] в int преобразование, которое размещает биты в ARGB_8888 формат

Должен быть лучший способ сделать это.

Помимо всего этого дерьма, оно не работает. Я возвращаю весь шум, который, я чувствую, может быть результатом неподписанных коротких массивов в C (полезно для переключения битов) и подписанных коротких массивов в C. Это серьезная проблема.

Так что я думаю, что мой общий вопрос: как я могу улучшить это, чтобы я не имел дело со всеми этими проблемами преобразования между типами, включая проблемы со знаком / без знака.

Все, что вы можете предложить, будет оценено ..

1 Ответ

2 голосов
/ 31 января 2011

Я не вижу преимущества наличия промежуточного представления short, поскольку код Java работает с числами с плавающей запятой, а код C работает с двойными числами.Я бы сделал что-то вроде этого:

float[] floats = readFile();

// Convert to little-endian doubles
ByteBuffer bb = ByteBuffer.allocateDirect(4 * floats.length);
bb.order(ByteOrder.LITTLE_ENDIAN);
DoubleBuffer db = bb.asDoubleBuffer();
for (int i = 0; i < floats.length; ++ i) {
    db.put(i, floats[i]);
}

doImageProcessing(bb); // Native method

// Convert double values to ARGB
int j = 0;
int[] argb = new int[floats.length / 4];
for (int i = 0; i < floats.length; i += 4) {
    int a = Math.max(0, Math.min((int) (db.get(i) * 256.0), 255));
    int r = Math.max(0, Math.min((int) (db.get(i+1) * 256.0), 255));
    int g = Math.max(0, Math.min((int) (db.get(i+2) * 256.0), 255));
    int b = Math.max(0, Math.min((int) (db.get(i+3) * 256.0), 255));
    argb[j++] = (a<<24)|(r<<16)|(g<<8)|b;
}
...