2013-06-18 14 views
5

Possiedo un programma Java progettato per visualizzare le immagini in un formato di file personalizzato, leggere una libreria C++ utilizzando JNI. I dati vengono caricati in un array di caratteri sul lato C++ e trasferiti in una BufferedImage sul lato Java. Poiché sezioni dell'immagine possono essere rimosse dalla memoria e devono essere ricaricate abbastanza regolarmente, quindi voglio che queste operazioni siano il più veloci possibile.Trasferimento efficiente di grandi quantità di dati di byte da C++ a Java

Il modo in cui sto facendo questo è che i dati vengono letti dal file in un buffer nella memoria della libreria C++. Per popolare la BufferedImage, il codice Java effettua una chiamata alla funzione JNI per ogni pixel da leggere da questo buffer e, se necessario, carica un altro blocco di dati nel buffer. Funziona, ma con un overhead superiore a quello che vorrei.

Quello che ho intenzione di fare per migliorare questo è passare l'oggetto BufferedImage al codice C++ usando una chiamata JNI, ed effettuare chiamate di funzione su di esso da quel lato. Ho fatto ricerche su JNI il più possibile, ma non sono stato in grado di scoprire se ci sono costi nella modifica di oggetti Java da una libreria C++ caricata dalla JVM. Questo è un buon modo per implementare questo, o c'è un modo più veloce per trasferire grandi quantità di dati di byte con JNI?

+4

Una chiamata per pixel suona male! Sarebbero miliardi di chiamate per le immagini più grandi. Che dire dell'acquisizione di blocchi o righe raster (ad esempio unità di immagini più grandi) contemporaneamente? Le righe raster possono essere lette sequenzialmente come impacchettate ed evitare ulteriori conversioni? – user2246674

+0

Sì, le righe e i blocchi possono essere letti in un buffer sul lato C++. Ho fatto un po 'di ottimizzazione sul lato C++. Il problema è che non conosco un modo efficiente per trasferire i dati su java, quindi eseguo una chiamata separata su ciascun pixel per leggere i dati dal buffer C++. – resueman

+1

@resuerman Può qualcosa [WritableRaster.setSamples] (http://docs.oracle.com/javase/1.5.0/docs/api/java/awt/image/WritableRaster.html#setSamples (int,% 20int,% 20int ,% 20int,% 20int,% 20double [])) da utilizzare? Se è possibile, potrebbe essere solo trovare un modo per (più efficientemente) caricare i dati in un array Java. C'è un modo per bloccare una memoria array e/o wrap [C++] ed evitare una copia [primaria]? Anche con un'operazione di copia aggiuntiva (C++ -> Array Java-> Raster), dovrebbe comunque ridurre notevolmente il numero di chiamate JNI. Inoltre (e immagino che questo suoni "extra-intelligente"), possono essere usate le OpenGL (texture) qui? – user2246674

risposta

1

Il modo più efficiente per spostare i dati attraverso il limite JNI è probabilmente tramite diretto ByteBuffers. È necessario spostarsi il più possibile alla volta, poiché attraversa il confine stesso inefficiente, non il trasferimento. Certamente più di un pixel, preferibilmente megabyte alla volta.

+0

Fantastico. Questo sembra esattamente quello che stavo cercando. Grazie. – resueman

Problemi correlati