Java 2D и изменить размер - PullRequest
       24

Java 2D и изменить размер

4 голосов
/ 12 февраля 2009

У меня есть старый Java 2D-код, который я хочу использовать повторно, но мне было интересно, это лучший способ получить изображения высочайшего качества?

    public static BufferedImage getScaled(BufferedImage imgSrc, Dimension dim) {

    //  This code ensures that all the pixels in the image are loaded.
    Image scaled = imgSrc.getScaledInstance(
            dim.width, dim.height, Image.SCALE_SMOOTH);

    // This code ensures that all the pixels in the image are loaded.
    Image temp = new ImageIcon(scaled).getImage();

    // Create the buffered image.
    BufferedImage bufferedImage = new BufferedImage(temp.getWidth(null), 
            temp.getHeight(null), BufferedImage.TYPE_INT_RGB);

    // Copy image to buffered image.
    Graphics g = bufferedImage.createGraphics();
    // Clear background and paint the image.
    g.setColor(Color.white);
    g.fillRect(0, 0, temp.getWidth(null),temp.getHeight(null));
    g.drawImage(temp, 0, 0, null);
    g.dispose();


    // j2d's image scaling quality is rather poor, especially when
    // scaling down an image to a much smaller size. We'll post filter  
    // our images using a trick found at 
    // http://blogs.cocoondev.org/mpo/archives/003584.html
    // to increase the perceived quality....
    float origArea = imgSrc.getWidth() * imgSrc.getHeight();
    float newArea = dim.width * dim.height;
    if (newArea <= (origArea / 2.)) {
        bufferedImage = blurImg(bufferedImage);
    }

    return bufferedImage;
}

public static BufferedImage blurImg(BufferedImage src) {
    // soften factor - increase to increase blur strength
    float softenFactor = 0.010f;
    // convolution kernel (blur)
    float[] softenArray = {
            0,              softenFactor,       0, 
            softenFactor, 1-(softenFactor*4), softenFactor, 
            0,              softenFactor,       0};

    Kernel kernel = new Kernel(3, 3, softenArray);
    ConvolveOp cOp = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
    return cOp.filter(src, null);
}

Ответы [ 5 ]

4 голосов
/ 13 февраля 2009

У Криса Кэмпбелла отличная и подробная информация о масштабировании изображений - см. эту статью .

Чет Хаас и Ромэн Гай также подробно и очень информативно описывают масштабирование изображений в своей книге, Грязные клиенты .

3 голосов
/ 06 февраля 2011

Добавление некоторой уточняющей информации здесь.

Нет, это не лучший способ получить хорошо выглядящее масштабированное изображение в Java. Использование getScaledInstance и лежащего в основе AreaAveragingScaleFilter не рекомендуется командой Java2D в пользу некоторых более продвинутых методов.

Если вы просто пытаетесь получить симпатичный эскиз, используйте метод Криса Кэмпбелла, предложенный Дэвидом. Что бы это ни стоило, я реализовал этот алгоритм вместе с 2 другими более быстрыми методами в библиотеке масштабирования изображений Java под названием imgscalr (лицензия Apache 2). Задача библиотеки заключалась в том, чтобы конкретно решить этот вопрос в хорошо настроенной библиотеке, которая проста в использовании:

BufferedImage thumbnail = Scalr.resize(srcImg, 150);

Чтобы получить наилучший из возможных масштабированных экземпляров в Java, вызов метода должен выглядеть примерно так:

BufferedImage scaledImg = Scalr.resize(img, Method.QUALITY, 
                                       150, 100, Scalr.OP_ANTIALIAS);

Библиотека будет масштабировать исходное изображение с использованием подхода инкрементного масштабирования, рекомендованного командой Java2D, а затем, чтобы сделать его еще более приятным, к изображению применяется очень мягкий вогнутый элемент, эффективно слегка сглаживая его. Это действительно хорошо для маленьких миниатюр, не так важно для огромных изображений.

Если вы раньше не работали с convolveops, то МНОГО работы - просто заставить ядро ​​выглядеть идеально, чтобы опера выглядела хорошо во всех случаях использования. Константа OP, определенная в классе Scalr, является результатом недели сотрудничества с сайтом социальной сети в Бразилии, который развернул imgscalr для обработки изображений профиля для своих участников. Мы ходили взад и вперед и пробовали что-то вроде 10 разных ядер, пока не нашли достаточно тонкое, чтобы изображение не было мягким или нечетким, но все же сглаживало переходы между значениями пикселей, чтобы изображение не выглядело «резким» и шумным в небольших размерах.

Если вы хотите, чтобы лучше всего выглядело масштабированное изображение независимо от скорости, воспользуйтесь предложением Джухи использовать библиотеку java-image-scaling. Это очень обширная коллекция Java2D Ops, включающая поддержку алгоритма Lanczsos , который обеспечит вам наилучший результат.

Я бы держался подальше от JAI не потому, что это плохо, а потому, что это просто другой / более широкий инструмент, чем то, что вы пытаетесь решить. Любой из предыдущих трех упомянутых подходов даст вам великолепно выглядящие миниатюры без необходимости добавлять в свой проект совершенно новую платформу обработки изображений с меньшим количеством строк кода.

2 голосов
/ 12 февраля 2009

Вы можете использовать JAI (Java Advanced Imaging), чтобы получить более сложные варианты изменения размера изображения. См. https://jai.dev.java.net/.. Они предоставляют вам гораздо большую гибкость, чем пакет java.awt.image.

1 голос
/ 20 июня 2013

Вы можете изменить размер изображения, используя библиотеку с открытым исходным кодом введите описание ссылки здесь

Я сделал с Large Image to Small и получаю превосходный результат, сохраняя соотношение сторон.

import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.JOptionPane;
import org.imgscalr.*;
import org.imgscalr.Scalr.Method;


public class ImageScaller {
static String SRC_FILES_PATH = "I:\\BigGreen\\";
static String IMAGE_FILE_PATH = "I:\\Resized\\";
public ImageScaller() {         
}   
public static void main(String[] args) {
    // TODO Auto-generated method stub
    try
    {
        ResizeLoad(SRC_FILES_PATH);
    }
    catch(Exception ex)
    {
        System.out.println(ex.toString());
    }
}
public static int ResizeLoad(String path)
{
    String file;
    File folder ;
    File[] listOfFiles = null;       
    listOfFiles = null;
    try
    {           
        folder = new File(path);
        listOfFiles = folder.listFiles();   

        for (int i = 0; i < listOfFiles.length; i++)                    
        {                   
            if (listOfFiles[i].isFile())
            {
                file = listOfFiles[i].getName();
                ScalledImageWrite(listOfFiles[i].getPath(),file);                                   
                //System.out.println(file);
                }
            }
        System.out.println("All Resized");
        }

    catch (Exception e) 
      {
          JOptionPane.showMessageDialog(null,e.toString(),"Resize & Load :Exception",JOptionPane.WARNING_MESSAGE);                
      }
    return listOfFiles.length;
}
private static File ScalledImageWrite(String path,String fileName) 
  {
      try
      {
          BufferedImage img = ImageIO.read(new File(path));            
          BufferedImage scaledImg = Scalr.resize(img, Method.AUTOMATIC, 24, 24);                 
          File destFile = new File(IMAGE_FILE_PATH + fileName);      
          ImageIO.write(scaledImg, "png", destFile);                  
          //System.out.println("Done resizing");
          return destFile;
      }
      catch (Exception e) 
      {
          JOptionPane.showMessageDialog(null,e.toString(),"Scalled Images Write: Exception",JOptionPane.WARNING_MESSAGE);
          return null;
      }
  }

}

Вот вывод в графическом формате этого кода. enter image description here

1 голос
/ 13 мая 2010

Вы также можете посмотреть библиотеку java-image-scaling .

...