approccio migliore per la memorizzazione di pixel dell'immagine in modo bottom-up in Java
-
20-09-2019 - |
Domanda
Ho un array di byte che rappresentano un'immagine in formato di Windows BMP e vorrei che la mia libreria per presentarlo al l'applicazione Java come BufferedImage
, senza la copia dei dati dei pixel.
Il problema principale è che tutte le implementazioni di Raster
nel JDK pixel dell'immagine negozio in top-down, ordine da sinistra a destra, mentre i dati di pixel vengono memorizzati BMP bottom-up, da sinistra a destra. Se questo non viene compensata, l'immagine risultante sarà girato in verticale.
La "soluzione" più ovvia è impostare la proprietà SampleModel
del scanlineStride
ad un valore negativo e modificare gli offset di banda (o matrice del DataBuffer
offset) per puntare il pixel in alto a sinistra, cioè il primo pixel dell'ultima riga la matrice. Purtroppo questo non funziona perché tutti i costruttori SampleModel
gettare un'eccezione se dato un argomento scanlineStride
negativo.
Al momento sto lavorando intorno ad esso forzando il campo scanlineStride
ad un valore negativo utilizzando la riflessione, ma mi piacerebbe farlo in un modo più pulito e più portabile, se possibile.
per esempio. c'è un altro modo per ingannare il Raster
o SampleModel
nel disporre i pixel in modo bottom-up, ma senza rompere l'incapsulamento? O c'è un qualche libreria che vi avvolgerà il Raster
e SampleModel
, presentando le righe di pixel in ordine inverso?
Io preferirei evitare i seguenti approcci:
- copia l'intera immagine (per motivi di prestazioni. Il codice deve elaborare centinaia di grandi dimensioni (> = 1Mpixels) immagini al secondo e, sebbene l'intera immagine deve essere disponibile per l'applicazione, normalmente accedere solo una piccola (ma hardware da prevedere) parte dell'immagine.)
- Modifica del
DataBuffer
per eseguire trasformazione di coordinate (questo in realtà funziona, ma è un'altra soluzione "sporco" perché il buffer non dovrebbe aver bisogno di conoscere il layout linea di scansione / pixel.) - Re-attuazione dei
Raster
e / oSampleModel
interfacce da zero (a causa del controllo compatibilità modo è implementato (almeno nella Sun JDK), richiedendo sottoclassi specifiche diSampleModel
così una classeBottomUpSampleModel
wrapper generico non funzionerebbe.)
Soluzione
ho scoperto che posso implementare questo utilizzando una sola nuova classe, che ho chiamato BottomUpComponentSampleModel
. Si estende ComponentSampleModel
e nega il valore del campo scanlineStride
(che, fortunatamente, è protected
anziché private
) dopo chiamare il costruttore superclasse. Tutti i calcoli di indirizzi di pixel funzionano bene, anche se la convalida in Raster.createWritableRaster
non (si può non rilevare se si dà una matrice che è troppo piccola), ma questo non è un problema serio.
Questo non è necessario con MultiPixelPackedSampleModel
o SinglePixelPackedSampleModel
, come fanno accettare un scanlineStride
negativo. Non hanno offset della band, ma questo può essere lavorato intorno Impostando un offset sulla DataBuffer
.
Altri suggerimenti
quello di avere la (o livello di accesso) applicazione fare la traduzione e lanciando lavoro sulla sua copia quando si accede alla piccola (ma difficile da prevedere) porzione di immagine?
ancora meglio, suona come l'applicazione non ha bisogno di visualizzare in realtà l'immagine? Perché preoccuparsi di voler capovolgere in primo luogo così sarebbe sembrato corretto sullo schermo? Basta scrivere la logica di lavorare sulla versione hai? Non c'è bisogno di avere un BufferedImage in questo modo sia, lavorare direttamente sulla matrice.