Fofolé
Tengo una imagen que cambio de tamaño:
if((width != null) || (height != null))
{
try{
// Scale image on disk
BufferedImage originalImage = ImageIO.read(file);
int type = originalImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB
: originalImage.getType();
BufferedImage resizedImageJpg = resizeImage(originalImage, type, 200, 200);
ImageIO.write(resizedImageJpg, "jpg", file);
} catch(IOException e) {
System.out.println(e.getMessage());
}
}
Así es como cambio el tamaño de la imagen:
private static BufferedImage resizeImage(BufferedImage originalImage, int type,
Integer imgWidth, Integer imgHeight)
{
var resizedImage = new BufferedImage(imgWidth, imgHeight, type);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, imgWidth, imgHeight, null);
g.dispose();
return resizedImage;
}
Ahora el problema es que también necesito mantener la relación de aspecto. Es decir, necesito que la nueva imagen 200/200 contenga la nueva imagen escalada. Algo como esto:
Intenté algunas cosas pero no funcionaron como esperaba. Cualquier ayuda es apreciada.
Ozzy
Aquí vamos:
Dimension imgSize = new Dimension(500, 100);
Dimension boundary = new Dimension(200, 200);
Función para devolver el nuevo tamaño dependiendo del límite:
public static Dimension getScaledDimension(Dimension imgSize, Dimension boundary) {
int original_width = imgSize.width;
int original_height = imgSize.height;
int bound_width = boundary.width;
int bound_height = boundary.height;
int new_width = original_width;
int new_height = original_height;
// first check if we need to scale width
if (original_width > bound_width) {
//scale width to fit
new_width = bound_width;
//scale height to maintain aspect ratio
new_height = (new_width * original_height) / original_width;
}
// then check if we need to scale even with the new height
if (new_height > bound_height) {
//scale height to fit instead
new_height = bound_height;
//scale width to maintain aspect ratio
new_width = (new_height * original_width) / original_height;
}
return new Dimension(new_width, new_height);
}
En caso de que alguien también necesite el código de cambio de tamaño de la imagen, aquí hay una solución decente.
Si no está seguro acerca de la solución anterior, hay diferentes formas de lograr el mismo resultado.
-
Usé la misma lógica para cambiar el tamaño de los mapas de bits en Android 🙂
–James andresakis
27 de junio de 2012 a las 0:15
-
La respuesta de @Ozzy es correcta, excepto cuando no se requiere escala (o más específicamente cuando el ancho original es más pequeño que el límite). Inicializando
new_width
ynew_height
a aoriginal_width
yoriginal_height
corrige el problema.– Ryan Morlock
29 de enero de 2013 a las 22:57
-
Sé que esto es para Java, pero lo convertí a js en caso de que alguien más necesite la función getDimensions(originalWidth,originalHeight,newWidth,newHeight){ var dimension = {}; dimensiones.ancho = anchooriginal; dimensiones.altura = alturaoriginal; if(originalWidth > newWidth){ dimensiones.width = newWidth; dimensiones.alto = (dimensiones.ancho * altooriginal)/anchooriginal; } if(dimensiones.altura > nuevaAltura){ dimensiones.altura = nuevaAltura; dimensiones.ancho = (dimensiones.altura * anchooriginal) / alturaoriginal; } devolver dimensiones; }
– Rocío de la mañana
17 de diciembre de 2015 a las 4:39
-
Esto no funciona si la dimensión de destino es mayor. por lo tanto, ‘escala’ debe cambiarse a ‘reducir’ para este método.
– yilmaz
20 de junio de 2018 a las 6:11
-
Esta solución funcionó para mí, hasta que necesité cambiar el tamaño de una imagen a un límite más grande que la imagen misma. Tal vez este tiene más sentido.
– Sistema Cardinal
23 de enero de 2019 a las 20:55
Matías Braun
Traducido de aquí:
Dimension getScaledDimension(Dimension imageSize, Dimension boundary) {
double widthRatio = boundary.getWidth() / imageSize.getWidth();
double heightRatio = boundary.getHeight() / imageSize.getHeight();
double ratio = Math.min(widthRatio, heightRatio);
return new Dimension((int) (imageSize.width * ratio),
(int) (imageSize.height * ratio));
}
También puedes usar imgscalr para cambiar el tamaño de las imágenes manteniendo la relación de aspecto:
BufferedImage resizeMe = ImageIO.read(new File("orig.jpg"));
Dimension newMaxSize = new Dimension(255, 255);
BufferedImage resizedImg = Scalr.resize(resizeMe, Method.QUALITY,
newMaxSize.width, newMaxSize.height);
-
Esta debería ser la respuesta aceptada, ¡el código es más pequeño y también funciona para imágenes más pequeñas! ¡Gracias!
– Simón Ludwig
24 de marzo de 2019 a las 10:45
-
Dejé Scalr.java en mi proyecto y este ejemplo funcionó perfectamente, sin ningún drama.
– Sean Anderson
18 de abril a las 1:57
David
Querrás echarle un vistazo Imagen.getScaledInstance()y más en esta respuesta: Cómo mejorar el rendimiento del método g.drawImage() para cambiar el tamaño de las imágenes
Cargar imagen:
BufferedImage bufferedImage = ImageIO.read(file);
Cambiar el tamaño:
private BufferedImage resizeAndCrop(BufferedImage bufferedImage, Integer width, Integer height) {
Mode mode = (double) width / (double) height >= (double) bufferedImage.getWidth() / (double) bufferedImage.getHeight() ? Scalr.Mode.FIT_TO_WIDTH
: Scalr.Mode.FIT_TO_HEIGHT;
bufferedImage = Scalr.resize(bufferedImage, Scalr.Method.ULTRA_QUALITY, mode, width, height);
int x = 0;
int y = 0;
if (mode == Scalr.Mode.FIT_TO_WIDTH) {
y = (bufferedImage.getHeight() - height) / 2;
} else if (mode == Scalr.Mode.FIT_TO_HEIGHT) {
x = (bufferedImage.getWidth() - width) / 2;
}
bufferedImage = Scalr.crop(bufferedImage, x, y, width, height);
return bufferedImage;
}
Usando la biblioteca Scalr:
<dependency>
<groupId>org.imgscalr</groupId>
<artifactId>imgscalr-lib</artifactId>
<version>4.2</version>
</dependency>
prueba esto
float rateX = (float)jpDisplayImagen.getWidth()/(float)img.getWidth();
float rateY = (float)jpDisplayImagen.getHeight()/(float)img.getHeight();
if (rateX>rateY){
int W=(int)(img.getWidth()*rateY);
int H=(int)(img.getHeight()*rateY);
jpDisplayImagen.getGraphics().drawImage(img, 0, 0,W,H, null);
}
else{
int W=(int)(img.getWidth()*rateX);
int H=(int)(img.getHeight()*rateX);
jpDisplayImagen.getGraphics().drawImage(img, 0, 0,W,H, null);
}
Hansjorg Hofer
public class ImageTransformation {
public static final String PNG = "png";
public static byte[] resize(FileItem fileItem, int width, int height) {
try {
ResampleOp resampleOp = new ResampleOp(width, height);
BufferedImage scaledImage = resampleOp.filter(ImageIO.read(fileItem.getInputStream()), null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(scaledImage, PNG, baos);
return baos.toByteArray();
} catch (Exception ex) {
throw new MapsException("An error occured during image resizing.", ex);
}
}
public static byte[] resizeAdjustMax(FileItem fileItem, int maxWidth, int maxHeight) {
try {
BufferedInputStream bis = new BufferedInputStream(fileItem.getInputStream());
BufferedImage bufimg = ImageIO.read(bis);
//check size of image
int img_width = bufimg.getWidth();
int img_height = bufimg.getHeight();
if(img_width > maxWidth || img_height > maxHeight) {
float factx = (float) img_width / maxWidth;
float facty = (float) img_height / maxHeight;
float fact = (factx>facty) ? factx : facty;
img_width = (int) ((int) img_width / fact);
img_height = (int) ((int) img_height / fact);
}
return resize(fileItem,img_width, img_height);
} catch (Exception ex) {
throw new MapsException("An error occured during image resizing.", ex);
}
}
}
Khadzko Aliaksander
Esta es mi solución:
/*
Change dimension of Image
*/
public static Image resizeImage(Image image, int scaledWidth, int scaledHeight, boolean preserveRatio) {
if (preserveRatio) {
double imageHeight = image.getHeight();
double imageWidth = image.getWidth();
if (imageHeight/scaledHeight > imageWidth/scaledWidth) {
scaledWidth = (int) (scaledHeight * imageWidth / imageHeight);
} else {
scaledHeight = (int) (scaledWidth * imageHeight / imageWidth);
}
}
BufferedImage inputBufImage = SwingFXUtils.fromFXImage(image, null);
// creates output image
BufferedImage outputBufImage = new BufferedImage(scaledWidth, scaledHeight, inputBufImage.getType());
// scales the input image to the output image
Graphics2D g2d = outputBufImage.createGraphics();
g2d.drawImage(inputBufImage, 0, 0, scaledWidth, scaledHeight, null);
g2d.dispose();
return SwingFXUtils.toFXImage(outputBufImage, null);
}