【问题标题】:Bufferedimage resize缓冲图像调整大小
【发布时间】:2012-02-23 16:47:30
【问题描述】:

我正在尝试调整缓冲图像的大小。我能够存储它并显示在 jframe 上没有问题,但我似乎无法调整它的大小。关于如何更改它以使其工作并将图像显示为 200*200 文件的任何提示都会很棒

private void profPic(){
    String path = factory.getString("bottle");
    BufferedImage img = ImageIO.read(new File(path));
}


public static BufferedImage resize(BufferedImage img, int newW, int newH) {  
    int w = img.getWidth();  
    int h = img.getHeight();  
    BufferedImage dimg = new BufferedImage(newW, newH, img.getType());  
    Graphics2D g = dimg.createGraphics();  
    g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
    RenderingHints.VALUE_INTERPOLATION_BILINEAR);  
    g.drawImage(img, 0, 0, newW, newH, 0, 0, w, h, null);  
    g.dispose();  
    return dimg;  
}  

【问题讨论】:

    标签: java bufferedimage


    【解决方案1】:

    更新答案

    我不记得为什么my original answer 有效,但在单独的环境中对其进行了测试,我同意,原来接受的答案不起作用(为什么我说它有效,我也不记得了)。另一方面,这确实有效:

    public static BufferedImage resize(BufferedImage img, int newW, int newH) { 
        Image tmp = img.getScaledInstance(newW, newH, Image.SCALE_SMOOTH);
        BufferedImage dimg = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_ARGB);
    
        Graphics2D g2d = dimg.createGraphics();
        g2d.drawImage(tmp, 0, 0, null);
        g2d.dispose();
    
        return dimg;
    }  
    

    【讨论】:

    • 无法编译 - getScaledInstance 返回的是 Image 而不是 BufferedImage。
    • 仍然不安全 - 在我的 Macbook 上,例如,我收到 ClassCastException - 这不是保证转换。
    • @I82Much 一次编写,随处运行……咳咳。
    • @DHT Mac 不算真正的操作系统。 :P
    • 为什么是TYPE_INT_ARGB 而不是img.getType()
    【解决方案2】:

    如果只需要在resize 方法中调整BufferedImage 的大小,那么Thumbnailator 库可以很容易地做到这一点:

    public static BufferedImage resize(BufferedImage img, int newW, int newH) {
      return Thumbnails.of(img).size(newW, newH).asBufferedImage();
    }
    

    以上代码将调整img 的大小以适应newWnewH 的尺寸,同时保持原始图像的纵横比。

    如果不需要保持纵横比并且需要精确调整到给定尺寸,则可以使用forceSize 方法代替size 方法:

    public static BufferedImage resize(BufferedImage img, int newW, int newH) {
      return Thumbnails.of(img).forceSize(newW, newH).asBufferedImage();
    }
    

    使用Image.getScaledInstance方法并不能保证调整后的图像会保持原始图像的纵横比,而且通常速度很慢。

    Thumbnailator 使用一种技术来逐步调整图像的大小,可以是several times faster than Image.getScaledInstance,同时实现通常可比较的图像质量。

    免责声明:我是这个库的维护者。

    【讨论】:

    • Thumbnailator 真棒!
    【解决方案3】:

    这是我用来调整缓冲图像大小的一些代码,没有多余的装饰,非常快:

    public static BufferedImage scale(BufferedImage src, int w, int h)
    {
        BufferedImage img = 
                new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        int x, y;
        int ww = src.getWidth();
        int hh = src.getHeight();
        int[] ys = new int[h];
        for (y = 0; y < h; y++)
            ys[y] = y * hh / h;
        for (x = 0; x < w; x++) {
            int newX = x * ww / w;
            for (y = 0; y < h; y++) {
                int col = src.getRGB(newX, ys[y]);
                img.setRGB(x, y, col);
            }
        }
        return img;
    }
    

    【讨论】:

    • 很好的方法,但是比例不正确,当我将高度的因子除以两个的平方根时,它工作正常.. =)
    【解决方案4】:

    此类从文件中调整大小并获取格式名称:

    import java.awt.Image;
    import java.awt.image.BufferedImage;
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Iterator;
    import javax.imageio.ImageIO;
    import javax.imageio.ImageReader;
    import javax.imageio.ImageWriter;
    import javax.imageio.stream.ImageInputStream;
    import org.apache.commons.io.IOUtils;
    
    public class ImageResizer {
    
    public static void main(String as[]) throws IOException{
    
        File f = new File("C:/Users/samsungrob/Desktop/shuttle.jpg");
    
        byte[] ba = resize(f, 600, 600);
    
        IOUtils.write(ba, new FileOutputStream( new File("C:/Users/samsungrob/Desktop/shuttle_resized.jpg") ) );
    
    }
    
    
    
    
    public static byte[] resize(File file,
                                int maxWidth, int maxHeight) throws IOException{
        int scaledWidth = 0, scaledHeight = 0;
    
        BufferedImage img = ImageIO.read((ImageInputStream) file );
    
        scaledWidth = maxWidth;
        scaledHeight = (int) (img.getHeight() * ( (double) scaledWidth / img.getWidth() ));
    
        if (scaledHeight> maxHeight) {
            scaledHeight = maxHeight;
            scaledWidth= (int) (img.getWidth() * ( (double) scaledHeight/ img.getHeight() ));
    
            if (scaledWidth > maxWidth) {
                scaledWidth = maxWidth;
                scaledHeight = maxHeight;
            }
        }
    
        Image resized =  img.getScaledInstance( scaledWidth, scaledHeight, Image.SCALE_SMOOTH);
    
        BufferedImage buffered = new BufferedImage(scaledWidth, scaledHeight, Image.SCALE_REPLICATE);
    
        buffered.getGraphics().drawImage(resized, 0, 0 , null);
    
        String formatName = getFormatName( file ) ;
    
        ByteArrayOutputStream out = new ByteArrayOutputStream();
    
        ImageIO.write(buffered,
                formatName,
                out);
    
        return out.toByteArray();
    }
    
    
    private static String getFormatName(ImageInputStream iis) {
        try { 
    
            // Find all image readers that recognize the image format
            Iterator iter = ImageIO.getImageReaders(iis);
            if (!iter.hasNext()) {
                // No readers found
                return null;
            }
    
            // Use the first reader
            ImageReader reader = (ImageReader)iter.next();
    
            // Close stream
            iis.close();
    
            // Return the format name
            return reader.getFormatName();
        } catch (IOException e) {
        }
    
        return null;
    }
    
    private static String getFormatName(File file) throws IOException {
        return getFormatName( ImageIO.createImageInputStream(file) );
    }
    
    private static String getFormatName(InputStream is) throws IOException {
        return getFormatName( ImageIO.createImageInputStream(is) );
    }
    

    }

    【讨论】:

      【解决方案5】:

      如果您只想使用“平衡”平滑,这是 imgscalr 中实际情况的简化版本:

      /**
       * Takes a BufferedImage and resizes it according to the provided targetSize
       *
       * @param src the source BufferedImage
       * @param targetSize maximum height (if portrait) or width (if landscape)
       * @return a resized version of the provided BufferedImage
       */
      private BufferedImage resize(BufferedImage src, int targetSize) {
          if (targetSize <= 0) {
              return src; //this can't be resized
          }
          int targetWidth = targetSize;
          int targetHeight = targetSize;
          float ratio = ((float) src.getHeight() / (float) src.getWidth());
          if (ratio <= 1) { //square or landscape-oriented image
              targetHeight = (int) Math.ceil((float) targetWidth * ratio);
          } else { //portrait image
              targetWidth = Math.round((float) targetHeight / ratio);
          }
          BufferedImage bi = new BufferedImage(targetWidth, targetHeight, src.getTransparency() == Transparency.OPAQUE ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB);
          Graphics2D g2d = bi.createGraphics();
          g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); //produces a balanced resizing (fast and decent quality)
          g2d.drawImage(src, 0, 0, targetWidth, targetHeight, null);
          g2d.dispose();
          return bi;
      }
      

      【讨论】:

        【解决方案6】:

        试试 imgscalr 库。我发现的最好的库——速度非常快、质量好且易于使用

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

        已弃用的链接:http://www.thebuzzmedia.com/software/imgscalr-java-image-scaling-library/

        Apache 2 许可证

        【讨论】:

        • 谢谢!完美运行!
        • 该链接指向各种阴暗的互联网位置。答案很好。 ;)
        • 我会更新我的答案,但你的评论让我很高兴^^ github.com/rkalla/imgscalr
        【解决方案7】:

        看看这个,有帮助:

        BufferedImage bImage = ImageIO.read(new File(C:\image.jpg);
        
        BufferedImage thumbnail = Scalr.resize(bImage,  Scalr.Method.SPEED, Scalr.Mode.FIT_TO_WIDTH,
                                               750, 150, Scalr.OP_ANTIALIAS);
        

        【讨论】:

        猜你喜欢
        • 2020-05-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-03
        • 2019-12-29
        • 1970-01-01
        • 2023-04-05
        相关资源
        最近更新 更多