java - para - manual de programacion android pdf
Java 2D y cambio de tamaño (5)
Tengo un viejo código 2D de Java que quiero reutilizar, pero me preguntaba si esta es la mejor manera de obtener imágenes de la más alta calidad.
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);
}
Chris Campbell tiene una reseña excelente y detallada sobre la escala de imágenes - ver este artículo .
Chet Haase y Romain Guy también tienen una reseña detallada y muy informativa de escalado de imágenes en su libro, Filthy Rich Clients .
Puede usar JAI (Java Advanced Imaging) para obtener opciones de cambio de tamaño de imagen más sofisticadas. Ver https://jai.dev.java.net/ . Estos le permiten mucha más flexibilidad que el paquete java.awt.image.
También puedes mirar en la biblioteca java-image-scaling .
Agregando algo de información aclaratoria aquí.
No, esa no es la mejor manera de obtener una buena imagen escalada en Java. El uso de getScaledInstance y del AreaAveragingScaleFilter subyacente es obsoleto por el equipo de Java2D a favor de algunos métodos más avanzados.
Si solo está tratando de obtener una miniatura atractiva, usar el método de Chris Campbell como lo sugirió David es el camino a seguir. Por lo que vale, he implementado ese algoritmo junto con otros 2 métodos más rápidos en una biblioteca de escalado de imágenes de Java llamada imgscalr (licencia de Apache 2). El objetivo de la biblioteca era abordar específicamente esta cuestión en una biblioteca altamente optimizada que es fácil de usar:
BufferedImage thumbnail = Scalr.resize(srcImg, 150);
Para obtener la mejor instancia escalada posible en Java, la llamada al método se vería así:
BufferedImage scaledImg = Scalr.resize(img, Method.QUALITY,
150, 100, Scalr.OP_ANTIALIAS);
La biblioteca escalará la imagen original con el enfoque de escalado incremental recomendado por el equipo Java2D y luego, para que se vea aún mejor, se aplicará una convolveción muy suave a la imagen, lo que lo suavizará ligeramente. Esto es realmente bueno para miniaturas pequeñas, no tan importantes para imágenes enormes.
Si no ha trabajado anteriormente con convolvedores, es MUCHO trabajo obtener el núcleo perfecto para que la operación se vea bien en todos los casos de uso. La constante OP definida en la clase Scalr es el resultado de una semana de colaboración con un sitio de redes sociales en Brasil que implementó imgscalr para procesar imágenes de perfil para sus miembros. Fuimos y probamos algo así como 10 kernels diferentes hasta que encontramos uno lo suficientemente sutil como para no hacer que la imagen pareciera suave o difusa, pero aun así suavizar las transiciones entre los valores de píxeles para que la imagen no se viera "nítida" y ruidosa en tamaños pequeños.
Si desea la imagen escalada más atractiva independientemente de la velocidad, siga la sugerencia de Juha de utilizar la biblioteca de escalado de imágenes java. Es una colección muy completa de Java2D Ops e incluye soporte para el algoritmo Lanczsos que le dará el mejor resultado.
Me mantendría alejado de JAI, no porque sea malo, sino porque es solo una herramienta diferente / más amplia que lo que estás tratando de resolver. Cualquiera de los 3 enfoques anteriores mencionados le proporcionará miniaturas de gran atractivo sin la necesidad de agregar una plataforma de imágenes completamente nueva a su proyecto en menos líneas de código.
Puedes cambiar el tamaño de la imagen usando una biblioteca de código abierto ingresa la descripción del enlace aquí
Lo he hecho con Imagen grande a Pequeña y resulta excelente, manteniendo la relación de aspecto bien.
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;
}
}
}
Aquí está la salida en formato pictórico de este código.