Опитвам се да постигна следното:
1) Имам масив от байтове от страна на java, който представлява изображение.
2) Трябва да дам на собствения си код достъп до него.
3) Родният код декодира това изображение с помощта на GraphicsMagick и създава куп миниатюри чрез извикване на resize. Той също така изчислява перцептуален хеш на изображението, което е вектор или масив unint8_t.
4) След като върна тези данни обратно на страната на Java, различни нишки ще ги прочетат. Миниатюрите ще бъдат качени в някоя външна услуга за съхранение чрез HTTP.
Въпросите ми са:
1) Какъв би бил най-ефективният начин за предаване на байтовете от Java към моя собствен код? Имам достъп до него като масив от байтове. Не виждам никакво особено предимство за предаването му като байтов буфер (обвиващ този байтов масив) срещу байтов масив тук.
2) Кой би бил най-добрият начин да върнете тези миниатюри и перцептуалния хеш обратно в кода на Java? Сетих се за няколко варианта:
(i) Бих могъл да разпределя байтов буфер в Java и след това да го предам към моя собствен метод. След това естественият метод може да запише в него и да зададе ограничение, след като е направено, и да върне броя на записаните байтове или някакво булево значение, показващо успех. След това бих могъл да нарязвам и разделям байтовия буфер, за да извлека отделните миниатюри и перцептуалния хеш и да го предам на различните нишки, които ще качат миниатюрите. Проблемът с този подход е, че не знам какъв размер да разпределя. Необходимият размер ще зависи от размера на генерираните миниатюри, който не знам предварително, и от броя на миниатюрите (знам това предварително).
(ii) Бих могъл също да разпределя байтовия буфер в собствен код, след като разбера необходимия размер. Мога да memcpy моите петна в правилния регион въз основа на моя персонализиран протокол за опаковане и да върна този байтов буфер. И двете (i) и (ii) изглеждат сложни поради персонализирания протокол за опаковане, който трябва да посочи дължината на всяка миниатюра и перцептивния хеш.
(iii) Дефинирайте Java клас, който има полета за миниатюри: масив от байтови буфери и перцептуален хеш: байтов масив. Бих могъл да разпределя байтовите буфери в естествен код, когато знам точните необходими размери. След това мога да memcpy байтовете от моя GraphicsMagick blob към директния адрес на всеки байтов буфер. Предполагам, че има и някакъв метод за задаване на броя на байтовете, записани в байтовия буфер, така че кодът на Java да знае колко големи са байтовите буфери. След като байтовите буфери са зададени, мога да попълня своя Java обект и да го върна. В сравнение с (i) и (ii) тук създавам повече байтови буфери, а също и Java обект, но избягвам сложността на потребителски протокол. Обосновка зад (i), (ii) и (iii) - като се има предвид, че единственото нещо, което правя с тези миниатюри, е да ги кача, надявах се да запазя допълнително копие с байтови буфери (срещу байтов масив), когато ги качвам през NIO .
(iv) Дефинирайте Java клас, който има масив от масиви от байтове (вместо буфери от байтове) за миниатюрите и масив от байтове за перцептуалния хеш. Създавам тези Java масиви в собствения си код и копирам байтовете от моя графичен обект GraphicsMagick с помощта на SetByteArrayRegion. Недостатъкът спрямо предишните методи е, че сега ще има още едно копие в земята на Java, когато копирате този байтов масив от купчината в някакъв директен буфер, когато го качвате. Не съм сигурен, че ще спестя нещо по отношение на сложността срещу (iii) и тук.
Всеки съвет би бил страхотен.
РЕДАКТИРАНЕ: @main предложи интересно решение. Редактирам въпроса си, за да проследя тази опция. Ако исках да обвия основната памет в DirectBuffer, както предлага @main, как щях да разбера кога мога безопасно да освободя основната памет?