2013-06-18 5 views
5

У меня есть Java-программа, предназначенная для отображения изображений в формате пользовательского файла, через библиотеку C++, используя JNI. Данные загружаются в массив символов на стороне C++ и переносятся на BufferedImage на стороне Java. Поскольку разделы изображения могут быть удалены из памяти и их необходимо перезагружать достаточно регулярно, поэтому я хочу, чтобы эти операции были как можно быстрее.Эффективно передавать большое количество байтовых данных из C++ в Java

То, как я сейчас это делаю, это данные считываются из файла в буфер в памяти библиотеки C++. Чтобы заполнить BufferedImage, Java-код вызывает вызов функции JNI для каждого пикселя для чтения из этого буфера и, при необходимости, загружает еще один фрагмент данных в буфер. Это работает, но с более высокими накладными расходами, чем хотелось бы.

То, что я планировал сделать, чтобы улучшить это, - передать объект BufferedImage на код C++ с помощью вызова JNI и вызвать вызовы функций с этой стороны. Я изучал JNI насколько могу, но мне не удалось выяснить, есть ли какая-либо стоимость в модификации объектов Java из библиотеки C++, которая была загружена JVM. Это хороший способ реализовать это, или есть более быстрый способ передачи больших объемов байтовых данных с помощью JNI?

+4

Звонок на пиксель звучит ужасно! Это будет миллиарды звонков для больших изображений. Как насчет выборки блоков или растровых линий (например, больших единиц изображения) сразу? Могут ли растровые строки считываться последовательно, как упакованные, и избегать дополнительных преобразований? – user2246674

+0

Да, строки и блоки могут быть прочитаны в буфер на стороне C++. Я немного оптимизировал это на стороне C++. Проблема в том, что я не знаю эффективного способа передачи данных обратно в java, поэтому я делаю отдельный вызов для каждого пикселя для чтения данных из буфера C++. – resueman

+1

@resuerman Может что-то [WritableRaster.setSamples] (http://docs.oracle.com/javase/1.5.0/docs/api/java/awt/image/WritableRaster.html#setSamples (int,% 20int,% 20int ,% 20int,% 20int,% 20double []))? Если это возможно, то это может просто найти способ (наиболее эффективно) загрузить данные в массив Java. Есть ли способ привязать массив и/или обернуть память [C++] и избежать [первичной] копии? Даже с дополнительной копией (C++ -> Java Array-> Raster) она все равно должна значительно уменьшить количество вызовов JNI. Также (и я осмелюсь сказать, что это звучит «очень умно»), можно ли использовать OpenGL (текстуры) здесь? – user2246674

ответ

1

Самый эффективный способ перемещения данных через границу JNI, возможно, осуществляется через прямой ByteBuffers. Вы должны перемещать столько, сколько сможете за раз, поскольку оно пересекает границу, которая неэффективна, а не передача. Конечно, более одного пикселя, предпочтительно мегабайт за раз.

+0

Awesome. Это похоже на то, что я искал. Спасибо. – resueman

Смежные вопросы