with - set image dimension java




Qualità dell'immagine dopo il ridimensionamento molto basso-Java (3)

Nella sceneggiatura va da circa 300x300 a 60x60. Necessità di migliorare la qualità complessiva dell'immagine in quanto sta venendo fuori molto male al momento.

public static Boolean resizeImage(String sourceImg, String destImg, Integer Width, Integer Height, Integer whiteSpaceAmount) 
{
    BufferedImage origImage;

    try 
    {
        origImage = ImageIO.read(new File(sourceImg));
        int type = origImage.getType() == 0? BufferedImage.TYPE_INT_ARGB : origImage.getType();
        int fHeight = Height;
        int fWidth = Width;
        int whiteSpace = Height + whiteSpaceAmount; //Formatting all to squares so don't need two whiteSpace calcs..
        double aspectRatio;

        //Work out the resized dimensions
        if (origImage.getHeight() > origImage.getWidth()) //If the pictures height is greater than the width then scale appropriately.
        {
            fHeight = Height; //Set the height to 60 as it is the biggest side.

            aspectRatio = (double)origImage.getWidth() / (double)origImage.getHeight(); //Get the aspect ratio of the picture.
            fWidth = (int)Math.round(Width * aspectRatio); //Sets the width as created via the aspect ratio.
        }
        else if (origImage.getHeight() < origImage.getWidth()) //If the pictures width is greater than the height scale appropriately.
        {
            fWidth = Width; //Set the height to 60 as it is the biggest side.

            aspectRatio = (double)origImage.getHeight() / (double)origImage.getWidth(); //Get the aspect ratio of the picture.
            fHeight = (int)Math.round(Height * aspectRatio); //Sets the height as created via the aspect ratio.
        }

        int extraHeight = whiteSpace - fHeight;
        int extraWidth = whiteSpace - fWidth;

        BufferedImage resizedImage = new BufferedImage(whiteSpace, whiteSpace, type);
        Graphics2D g = resizedImage.createGraphics();
        g.setColor(Color.white);
        g.fillRect(0, 0, whiteSpace, whiteSpace);

        g.setComposite(AlphaComposite.Src);
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        g.drawImage(origImage, extraWidth/2, extraHeight/2, fWidth, fHeight, null);
        g.dispose();

        ImageIO.write(resizedImage, "jpg", new File(destImg));
    } 
    catch (IOException ex) 
    {
        return false;
    }

    return true;
}

Devo solo sapere se il loro è qualcosa che posso collegare che farà salire la qualità o se ho bisogno di guardare qualcos'altro interamente.

MODIFICA: Confronto immagini.

Fonte, ho appena scelto una lavatrice casuale da google. http://www.essexappliances.co.uk/images/categories/washing-machine.jpg

La stessa immagine convertita in Photoshop per quello che ho bisogno di essere. http://imgur.com/78B1p

Come sembra essere convertito in questo modo. http://imgur.com/8WlXD


Come già detto, Graphics2D di Java non fornisce un ottimo algoritmo per il down-scaling. Se non si desidera implementare autonomamente un algoritmo sofisticato, è possibile provare le librerie open source attualmente specializzate per questo: Thumbnailator , imgscalr e un'interfaccia Java per ImageMagick .

Durante la ricerca per un progetto privato li ho provati (eccetto ImageMagick) e qui ci sono i risultati visivi con Photoshop come riferimento:

Thumbnailator

A. Thumbnailator 0.4.8 con impostazioni predefinite (nessun ridimensionamento interno aggiuntivo)
B. imgscalr 4.2 con impostazione ULTRA_QUALTY
C. Filtro bicub Photoshop CS5 (salvataggio per Web)
D. Graphics2d con tutti i suggerimenti per il rendering HQ

imgscalr

Thumbnailator e PS creano risultati simili, mentre imgscalr sembra più morbido. È soggettivo che una delle librerie crea i risultati preferibili. Un altro punto da considerare è la performance. Mentre Thumbnailator e Graphics2d hanno un runtime simile, imgscalr è notevolmente più lento (con ULTRA_QUALITY) ImageMagick .

ImageMagick .


Il problema che stai vedendo è in realtà correlato al filtro di ricampionamento utilizzato per il downscaling. Ovviamente, quello usato dalla tua biblioteca è cattivo per la situazione. Il vicino più vicino, bilineare e bicubico sono tipici esempi negativi da utilizzare durante il downscaling. Non conosco il filtro di ricampionamento che Photoshop usa, ma ho usato lanczos a 3 lobi e ho ottenuto il seguente risultato:

Quindi, per risolvere il tuo problema, devi utilizzare un filtro di ricampionamento più intelligente.


dutchman, è per questo che mantengo la libreria imgscalr - per rendere questo tipo di cose dolorosamente facile.

Nel tuo esempio, una singola chiamata al metodo farebbe il trucco, subito dopo la tua prima riga ImageIO.read:

origImage = ImageIO.read(new File(sourceImg));

puoi fare quanto segue per ottenere quello che vuoi ( javadoc per questo metodo ):

origImage = Scalr.resize(origImage, Method.ULTRA_QUALITY, 60);

e se ciò sembra ancora un po 'frastagliato (perché stai rimuovendo così tante informazioni dall'immagine, puoi aggiungere il seguente OP al comando per applicare un filtro anti-aliasing leggero all'immagine in modo che appaia più agevole):

origImage = Scalr.resize(origImage, Method.ULTRA_QUALITY, 60, Scalr.OP_ANTIALIAS);

Questo sostituirà tutto il resto della logica del codice che hai. L'unica altra cosa che consiglierei è di salvare i tuoi campioni veramente piccoli come PNG in modo che non ci sia più alcuna conversione di compressione / perdita fatta sull'immagine O assicurati di usare poca o nessuna compressione sul JPG se lo vuoi veramente nel formato JPG. (Ecco un articolo su come farlo: utilizza la classe ImageWriteParam )

imgscalr è concesso in licenza con una licenza Apache 2 e ospitato su GitHub modo che tu possa fare ciò che vuoi con esso; include anche il supporto per il ridimensionamento asincrono se si utilizza la libreria in un'app lato server e si accodano un numero enorme di operazioni di ridimensionamento e non si vuole uccidere il server.





image-resizing