Bildgröße ändern, Seitenverhältnis beibehalten

Lesezeit: 6 Minuten

Benutzeravatar von Fofole
Fofole

Ich habe ein Bild, dessen Größe ich verändere:

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());
       }
}

So verkleinere ich das Bild:

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;
}

Jetzt ist das Problem, dass ich auch das Seitenverhältnis beibehalten muss. Das heißt, ich brauche das neue 200/200-Bild, um das neue skalierte Bild zu enthalten. Etwas wie das:
Geben Sie hier die Bildbeschreibung ein

Ich habe einige Dinge ausprobiert, aber sie haben nicht wie erwartet funktioniert. Jede Hilfe ist willkommen.

Ozzys Benutzeravatar
Ozzy

Auf geht’s:

Dimension imgSize = new Dimension(500, 100);
Dimension boundary = new Dimension(200, 200);

Funktion zur Rückgabe der neuen Größe abhängig von der Grenze:

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);
}

Falls jemand auch den Code zur Größenänderung des Bildes benötigt, ist hier eine anständige Lösung.

Wenn Sie sich bei der obigen Lösung nicht sicher sind, gibt es verschiedene Möglichkeiten, dasselbe Ergebnis zu erzielen.

  • Ich habe die gleiche Logik verwendet, um die Größe von Bitmaps in Android zu ändern 🙂

    – James andresakis

    27. Juni 2012 um 0:15 Uhr

  • Die Antwort von @Ozzy ist richtig, außer wenn keine Skalierung erforderlich ist (oder genauer gesagt, wenn die ursprüngliche Breite kleiner als die Grenze ist). Initialisierung new_width und new_height zu zu original_width und original_height behebt das Problem.

    – Ryan Morlok

    29. Januar 2013 um 22:57 Uhr


  • Ich weiß, dass dies für Java ist, aber ich habe es in js konvertiert, falls jemand anderes die Funktion getDimensions (originalWidth, originalHeight, newWidth, newHeight) { var dimensions = {} braucht; abmessungen.breite = originalBreite; Abmessungen.Höhe = ursprünglicheHöhe; Wenn (ursprüngliche Breite > neue Breite) {dimensions.width = neue Breite; abmessungen.höhe = (abmessungen.breite * ursprünglicheHöhe)/ursprünglicheBreite; } Wenn (dimensions.height > newHeight) {dimensions.height = newHeight; abmessungen.breite = (abmessungen.höhe * ursprünglicheBreite) / ursprünglicheHöhe; } Dimensionen zurückgeben; }

    – Morgentau

    17. Dezember 2015 um 4:39 Uhr

  • Dies funktioniert nicht, wenn das Zielmaß größer ist. also sollte ‘scale’ für diese Methode in ‘shrink’ geändert werden.

    – yılmaz

    20. Juni 2018 um 6:11 Uhr

  • Diese Lösung funktionierte für mich, bis ich die Größe eines Bildes auf eine Grenze ändern musste, die größer als das Bild selbst war. Vielleicht diese macht mehr Sinn.

    – Kardinalsystem

    23. Januar 2019 um 20:55 Uhr

Benutzeravatar von Matthias Braun
Mathias Braun

Von hier übersetzt:

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));
}

Sie können auch verwenden imgscalr So ändern Sie die Größe von Bildern unter Beibehaltung des Seitenverhältnisses:

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);

  • Dies sollte die akzeptierte Antwort sein, Code ist kleiner und funktioniert auch für kleinere Bilder! Danke schön!

    – Simon Ludwig

    24. März 2019 um 10:45 Uhr

  • Ich habe Scalr.java in mein Projekt eingefügt und dieses Beispiel hat perfekt funktioniert – ohne Dramatik.

    – Sean Anderson

    18. April um 1:57

davebs Benutzeravatar
daveb

Sie werden auschecken wollen Image.getScaledInstance()und mehr in dieser Antwort: So verbessern Sie die Leistung der Methode g.drawImage() zum Ändern der Bildgröße

Bild laden:

BufferedImage bufferedImage = ImageIO.read(file);   

Größe ändern:

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;
}

Verwendung der Scalr-Bibliothek:

<dependency>
    <groupId>org.imgscalr</groupId>
    <artifactId>imgscalr-lib</artifactId>
    <version>4.2</version>
</dependency>

Versuche dies

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);
}

Benutzeravatar von Hansjörg Hofer
Hansjörg 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);
    }

}

}

Benutzeravatar von Khadzko Aliaksander
Khadzko Aliaksander

Das ist meine Lösung:

/*
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);
}

1436800cookie-checkBildgröße ändern, Seitenverhältnis beibehalten

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy