2012-04-20 18 views
46

Tôi có một hình ảnh mà tôi thay đổi kích thước:Java chỉnh sửa ảnh, duy trì tỷ lệ khía cạnh

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 resizeImageJpg = resizeImage(originalImage, type, 200, 200); 
     ImageIO.write(resizeImageJpg, "jpg", file); 

     } catch(IOException e) { 
      System.out.println(e.getMessage()); 
     } 
} 

Đây là cách tôi thay đổi kích thước hình ảnh:

private static BufferedImage resizeImage(BufferedImage originalImage, int type, 
             Integer img_width, Integer img_height) 
{ 
    BufferedImage resizedImage = new BufferedImage(img_width, img_height, type); 
    Graphics2D g = resizedImage.createGraphics(); 
    g.drawImage(originalImage, 0, 0, img_width, img_height, null); 
    g.dispose(); 

    return resizedImage; 
} 

Bây giờ vấn đề là tôi cũng cần phải duy trì khía cạnh tỉ lệ. Tức là, tôi cần hình ảnh 200/200 mới để chứa hình ảnh mới được chia tỷ lệ. Một cái gì đó như thế này: enter image description here

Tôi đã thử một số thứ nhưng không hoạt động như mong đợi. Bất kỳ trợ giúp nào được đánh giá cao. Cảm ơn rất nhiều.

Trả lời

70

Ở đây chúng ta đi:

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

Chức năng để trả lại kích thước mới tùy thuộc vào ranh giới

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

Trong trường hợp bất cứ ai cũng cần thay đổi kích thước hình ảnh mã, here is a decent solution.

Nếu bạn không chắc về giải pháp trên there are different ways để đạt được kết quả tương tự.

+1

Tôi đã sử dụng cùng một logic để thay đổi kích thước bitmap trong android :) –

+2

Câu trả lời của @Ozzy là chính xác ngoại trừ khi không cần mở rộng quy mô (hoặc cụ thể hơn khi độ rộng ban đầu nhỏ hơn ranh giới). Việc khởi tạo 'new_width' và' new_height' thành 'original_width' và' original_height' sửa lỗi. –

+1

Câu trả lời này chỉ làm cho ngày của tôi. : D –

1

thử này

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

} 

}

3

dịch từ here:

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

Bạn cũng có thể sử dụng imgscalr để thay đổi kích thước hình ảnh trong khi duy trì tỷ lệ khía cạnh:

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

Chỉ cần thêm một khối hơn để mã Ozzy của do đó, điều trông như thế này:

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; 
    } 
    // upscale if original is smaller 
    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; 
    } 

    return new Dimension(new_width, new_height); 
} 
+0

Bạn theo nghĩa đen chỉ cần sao chép điều kiện đầu tiên và dán nó sau lần thứ hai ... -_- – Zach

0

Đây là giải pháp của tôi:

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

Tất cả các câu trả lời khác cho biết cách tính chiều cao hình ảnh mới theo chiều rộng hình ảnh mới hoặc ngược lại và cách thay đổi kích thước hình ảnh bằng Jav API hình ảnh. Đối với những người đang tìm kiếm một giải pháp đơn giản, tôi khuyên bạn nên sử dụng bất kỳ khung xử lý hình ảnh java nào có thể thực hiện điều này trong một dòng.

Các dụ dưới đây sử dụng Marvin Framework:

// 300 is the new width. The height is calculated to maintain aspect. 
scale(image.clone(), image, 300); 

cần thiết nhập khẩu:

import static marvin.MarvinPluginCollection.* 
0

tải hình ảnh:

BufferedImage bufferedImage = ImageIO.read(file); 

Thay đổi kích thước nó:

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

Sử dụng thư viện Scalr:

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

Tôi đã tìm thấy câu trả lời được lựa chọn để có vấn đề với upscaling, và vì vậy tôi đã thực hiện (chưa) một phiên bản khác (mà tôi đã thử nghiệm):

public static Point scaleFit(Point src, Point bounds) { 
    int newWidth = src.x; 
    int newHeight = src.y; 
    double boundsAspectRatio = bounds.y/(double) bounds.x; 
    double srcAspectRatio = src.y/(double) src.x; 

    // first check if we need to scale width 
    if (boundsAspectRatio < srcAspectRatio) { 
    // scale width to fit 
    newWidth = bounds.x; 
    //scale height to maintain aspect ratio 
    newHeight = (newWidth * src.y)/src.x; 
    } else { 
    //scale height to fit instead 
    newHeight = bounds.y; 
    //scale width to maintain aspect ratio 
    newWidth = (newHeight * src.x)/src.y; 
    } 

    return new Point(newWidth, newHeight); 
} 

Được viết bằng thuật ngữ Android :-)

như đối với các bài kiểm tra:

@Test public void scaleFit() throws Exception { 
    final Point displaySize = new Point(1080, 1920); 
    assertEquals(displaySize, Util.scaleFit(displaySize, displaySize)); 
    assertEquals(displaySize, Util.scaleFit(new Point(displaySize.x/2, displaySize.y/2), displaySize)); 
    assertEquals(displaySize, Util.scaleFit(new Point(displaySize.x * 2, displaySize.y * 2), displaySize)); 
    assertEquals(new Point(displaySize.x, displaySize.y * 2), Util.scaleFit(new Point(displaySize.x/2, displaySize.y), displaySize)); 
    assertEquals(new Point(displaySize.x * 2, displaySize.y), Util.scaleFit(new Point(displaySize.x, displaySize.y/2), displaySize)); 
    assertEquals(new Point(displaySize.x, displaySize.y * 3/2), Util.scaleFit(new Point(displaySize.x/3, displaySize.y/2), displaySize)); 
}