2009-05-31 3 views
8

Sono un programmatore Java ragionevolmente esperto ma relativamente nuovo a Java2D. Sto cercando di ridimensionare un'immagine, ma sto ottenendo risultati di scarsa qualità. L'immagine è un'anteprima di un pannello, quindi contiene cose come testo e campi di testo. Scenderò sempre verso il basso, mai alzato.Java2D: problemi di ridimensionamento

Attualmente sto usando il seguente codice: -

g.drawImage(panelImage, 0, 0, scaledWidth, scaledHeight, null); 

Dove panelImage è l'anteprima di dimensioni complete (BufferedImage) e scaledWidth e scaledHeight sono le rispettive dimensioni di destinazione. Mi sembra di perdere molti dettagli nel testo e nei bordi di cose come campi di testo ecc.

C'è una chiamata migliore che dovrei usare per ridimensionare l'immagine?

Grazie, John

risposta

11

Un suggerimento che posso fare è quello di ridimensionare prima l'immagine su un separato BufferedImage. Il motivo è che un oggetto Graphics2D dello BufferedImage può essere ottenuto per produrre un'immagine in scala di qualità migliore.

Graphics2D può accettare "suggerimenti di rendering" che indicano il modo in cui l'elaborazione dell'immagine deve essere eseguita dall'oggetto Graphics2D. Il metodo setRenderingHint è uno dei metodi che possono essere utilizzati per impostare questi suggerimenti di rendering. È possibile utilizzare gli hint di rendering della classe RenderingHints.

Quindi, utilizzando l'oggetto Graphics2D, è possibile disegnare un'immagine su BufferedImage utilizzando i suggerimenti di rendering specificati in precedenza.

Un codice di massima (non testato) avrebbe funzionato come i seguenti:

BufferedImage scaledImage = new BufferedImage(
    scaledWidth, 
    scaledHeight, 
    BufferedImage.TYPE_INT_RGB 
); 

Graphics2D g = scaledImage.createGraphics(); 
g.setRenderingHints(
    RenderingHints.Key.KEY_INTERPOLATION, 
    RenderingHints.VALUE_INTERPOLATION_BICUBIC 
); 

g.drawImage(panelImage, 0, 0, scaledWidth, scaledHeight, null); 
g.dispose(); 

Altri suggerimenti di rendering di interesse possono includere:

Il Controlling Rendering Quality sezione di The Java Tutorials als o ha ulteriori informazioni su come controllare la qualità di rendering degli oggetti Graphics2D.

E per un'ottima fonte di informazioni su come gestire le interfacce grafiche in generale, è altamente raccomandato lo Filthy Rich Clients di Chet Haase e Romain Guy. C'è una sezione del libro che affronta il tema del ridimensionamento delle immagini, che sembra abbastanza rilevante.

+0

Grazie, ho una copia di quel libro e mi sono tuffato per leggere il capitolo. Dovrebbe aver pensato di guardare lì prima di postare. Mi sono completamente dimenticato del rendering di suggerimenti per il ridimensionamento. Grazie! John – Johnathan

+0

Prego :) Pagine 98-113 tratta di ridimensionamento delle immagini e include alcuni buoni esempi. Di particolare interesse per me è stata l'idea del progressivo bilanciamento bilineare presentato a pagina 104. – coobird

+0

Sì, l'ho visto, ma non credo che la mia domanda lo giustifichi davvero. BICUBIC o BILINEAR sono abbastanza buone per me. È tempo di sperimentare! – Johnathan

2

può essere che si dovrebbe chiamare:

g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); 

e

g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
0

Coobird ha l'idea corretta. Vorrei anche provare l'interpolazione RenderingHints.VALUE_INTERPOLATION_BILINEAR e vedere se è più bello. Tuttavia, il bicubico funziona meglio con l'upscaling. Per ottenere i migliori risultati durante il downscaling, è necessario effettuare il downscale in diversi passaggi. Per prima cosa dimezza la risoluzione, poi dimezza di nuovo, ecc., Finché non ti avvicini alla risoluzione desiderata (ad esempio non puoi dimezzare o l'immagine diventerà troppo piccola).Il passo finale è ridimensionare fino alla risoluzione desiderata.

Per esempio, diciamo che l'immagine in ingresso è 800x600 e si desidera rimpicciolire a 160x120:

  1. Downscale 50%. ->400x300
  2. Downscale 50%. ->200x150
  3. Downscale a 160x120.
+0

Perché il downscaling in più passaggi è un vantaggio? Si prega di elaborare: D –

+0

Ecco qualcosa sull'argomento: http://www.nobel-joergensen.com/roller/java/entry/downscaling_images_in_java Oltre a questo non ho nulla, ma nella mia esperienza downscaling nei passaggi fornisce un risultato finale migliore. Vale la pena provare almeno. :) – MH114

+1

Questa è l'idea alla base del "ridimensionamento progressivo bilineare": eseguendo un ridimensionamento bilineare in più passaggi, l'informazione di ciascun pixel viene preservata, piuttosto che scartata eseguendo un singolo gradino di riscalaggio bilineare dell'immagine. – coobird

1

Coobird ha ragione che è necessario ridurre gradualmente la scala (preferibilmente utilizzando BICUBIC) per ottenere un risultato di bell'aspetto per una miniatura abbastanza piccola. Image.getScaledInstance lo faceva con l'approccio AREA_AVERAGED, ma è molto più lento del downscale incrementale originariamente proposto da Chris Campbell nel suo articolo "Perils of Image.getScaledInstance()".

Per favore scusate l'autopromozione qui, ma ho tirato fuori una manciata di "best practice Java native" quando si tratta di ridimensionare le immagini in una libreria chiamata imgscalr.

È disponibile con una licenza Apache 2 e la fonte è tutto su GitHub; l'obiettivo della libreria era quello di rendere scalabile l'immagine in Java nativo-dead-easy (1 metodo statico, 5 metodi statici) e assicurare il risultato migliore (che è quello che volevi originariamente), il risultato più veloce (ottimo per il ridimensionamento tra immagini di grandi dimensioni) o un equilibrio tra i due e lasciare che la libreria decida quale usare.

Volevo solo una lib che potesse "Ridimensionare la mia immagine e togliersi di mezzo" e dopo aver letto tutti questi messaggi per alcuni giorni mentre mi rivolgevo al punto di dolore (anche il mio) stava girando e condividendo il lavoro per chiunque altro può aiutare.

+0

Il sito originale non risponde in questo momento, sembra che il repository ufficiale per la lib sia qui https://github.com/rkalla/imgscalr –

+0

Sì, hai trovato il repository giusto - Ho chiuso tutti i vecchi 'The Buzz Le cose dei media (non ho avuto tempo per circa 5 anni per mantenerlo) e ho spostato tutto nel mio spazio personale sul repository. È anche nel repository Maven predefinito. –