如何使用Java调整图像大小?

时间:2008-10-28 17:46:13

标签: java image resize

我需要调整PNG,JPEG和GIF文件的大小。我怎么能用Java做到这一点?

17 个答案:

答案 0 :(得分:178)

FWIW我刚刚发布了(Apache 2,托管在GitHub上)一个简单的Java图像缩放库,名为imgscalr(可在Maven central上找到)。

该库实现了一些不同的图像缩放方法(包括Chris Campbell的渐进式方法和一些小改进),如果您要求它,或者为您提供最佳或最佳的方法,请选择最佳方法(如果你要求的话)。

用法很简单,只是一堆静态方法。最简单的用例是:

BufferedImage scaledImage = Scalr.resize(myImage, 200);

所有操作都保持图像的原始比例,因此在这种情况下,您要求imgscalr在200像素宽和200像素高的范围内调整图像大小,默认情况下,它会自动选择最佳外观和最快速的方法因为它没有指定。

我在一开始就意识到这看起来像是自我推销(它),但我花了相当多的时间在谷歌搜索这个完全相同的主题,并不断提出不同的结果/方法/想法/建议,并决定坐下来并写一个简单的实现,解决80-85%的用例,你有一个图像,可能需要一个缩略图 - 尽可能快或尽可能好看(对于那些尝试过的人,你我会注意到做了一个Graphics.drawImage,即使用BICUBIC插值到一个足够小的图像,它仍然看起来像垃圾。)

答案 1 :(得分:84)

加载图片后,您可以尝试:

BufferedImage createResizedCopy(Image originalImage, 
            int scaledWidth, int scaledHeight, 
            boolean preserveAlpha)
    {
        System.out.println("resizing...");
        int imageType = preserveAlpha ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
        BufferedImage scaledBI = new BufferedImage(scaledWidth, scaledHeight, imageType);
        Graphics2D g = scaledBI.createGraphics();
        if (preserveAlpha) {
            g.setComposite(AlphaComposite.Src);
        }
        g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null); 
        g.dispose();
        return scaledBI;
    }

答案 2 :(得分:49)

Thumbnailator是一个用于Java的开源图像大小调整库,具有流畅的界面,分布在MIT license.

我编写了这个库,因为在Java中制作高质量的缩略图可能会非常困难,并且生成的代码可能非常混乱。使用Thumbnailator,可以使用简单流畅的API表达相当复杂的任务。

一个简单的例子

举一个简单的例子,拍摄一张图像并将其大小调整为100 x 100(保留原始图像的宽高比),并将其保存到文件中可以在一个语句中实现:

Thumbnails.of("path/to/image")
    .size(100, 100)
    .toFile("path/to/thumbnail");

高级示例

使用Thumbnailator的流畅界面简化了复杂的大小调整任务。

我们假设我们想要做以下事情:

  1. 将图像放在目录中,
  2. 将它们调整为100 x 100,使用原始图像的宽高比
  3. 将所有内容全部保存为质量设置为0.85
  4. 的JPEG格式
  5. 其中文件名取自原件,thumbnail.附加到开头
  6. 转换为Thumbnailator,我们可以通过以下方式执行上述操作:

    Thumbnails.of(new File("path/to/directory").listFiles())
        .size(100, 100)
        .outputFormat("JPEG")
        .outputQuality(0.85)
        .toFiles(Rename.PREFIX_DOT_THUMBNAIL);
    

    关于图像质量和速度的说明

    此库还使用Chet Haase和Romain Guy在Filthy Rich Clients中突出显示的渐进式双线性缩放方法,以便在确保可接受的运行时性能的同时生成高质量的缩略图。

答案 3 :(得分:11)

您不需要库来执行此操作。你可以用Java本身来做。

克里斯·坎贝尔(Chris Campbell)对缩放图像进行了精彩而详尽的报道 - 请参阅this article

Chet Haase和Romain Guy在他们的书Filthy Rich Clients中也有一个详细而且非常丰富的图像缩放文章。

答案 4 :(得分:10)

Java Advanced Imaging现在是开源的,并提供您需要的操作。

答案 5 :(得分:9)

如果您正在处理大型图像或想要一个漂亮的结果,那么在java中这不是一项微不足道的任务。只需通过Graphics2D通过rescale op进行操作就不会创建高质量的缩略图。你可以使用JAI来完成它,但是它需要比你想象的更多的工作来获得看起来很好的东西而且JAI有一个讨厌的习惯,就是用OutOfMemory错误来破坏你的JVM。

如果您可以使用它,我建议您使用ImageMagick作为外部可执行文件。它使用简单,它可以正常工作,所以你不必这样做。

答案 6 :(得分:4)

如果您的机器上安装了imagemagick是一个选项,我建议im4java。它在命令行界面上是一个非常薄的抽象层,但它的工作非常好。

答案 7 :(得分:3)

Java API不为图像提供标准缩放功能并降低图像质量。

因此我尝试使用JavaCV中的cvResize,但它似乎会导致问题。

我找到了一个很好的图像缩放库:只需在pom.xml中添加“java-image-scaling”的依赖项。

<dependency>
    <groupId>com.mortennobel</groupId>
    <artifactId>java-image-scaling</artifactId>
    <version>0.8.6</version>
</dependency>

在maven存储库中,您将获得最新版本。

实施例。在你的java程序中

ResampleOp resamOp = new ResampleOp(50, 40);
BufferedImage modifiedImage = resamOp.filter(originalBufferedImage, null);

答案 8 :(得分:2)

您可以尝试将GraphicsMagick Image Processing Systemim4java一起用作Java的命令行界面。

GraphicsMagick有很多优点,但对所有人来说都是:

  • GM用于处理数十亿美元 世界上最大的照片文件 网站(例如Flickr和Etsy)。

答案 9 :(得分:1)

Image Magick已被提及。有一个名为JMagick的JNI前端项目。这不是一个特别稳定的项目(而且已知Image Magick本身会发生很大的变化,甚至会破坏兼容性)。也就是说,我们在生产环境中使用JMagick和Image Magick的兼容版本以高吞吐量,低延迟率执行扩展已经有了很好的经验。使用我们之前尝试过的全Java图形库,速度要好得多。

http://www.jmagick.org/index.html

答案 10 :(得分:1)

事实证明,编写高性能的缩放器并非易事。我为开源项目做了一次:ImageScaler

原则上&#39; java.awt.Image#getScaledInstance(int,int,int)&#39;也会做这个工作,但这有一个讨厌的错误 - 请参阅我的链接了解详情。

答案 11 :(得分:1)

只需使用Burkhard的答案,但在创建图形后添加此行:

    g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);

您还可以将值设置为BICUBIC,它将生成质量更好的图像,但操作更昂贵。您可以设置其他渲染提示,但我发现插值产生最显着的效果。 请记住,如果你想要放大很多,java代码很可能会非常慢。我发现较大的图像开始产生大约300%变焦的延迟,即使所有渲染提示都设置为优化速度而不是质量。

答案 12 :(得分:1)

您可以使用Marvin(纯Java图像处理框架)进行此类操作:  http://marvinproject.sourceforge.net

扩展插件: http://marvinproject.sourceforge.net/en/plugins/scale.html

答案 13 :(得分:0)

您可以使用以下热门产品:thumbnailator

答案 14 :(得分:0)

如果您不想导入imgScalr像@Riyad Kalla上面的答案,我测试过的也很好,你可以这样做 取自Peter Walser answer @Peter Walser的另一个问题:

 /**
     * utility method to get an icon from the resources of this class
     * @param name the name of the icon
     * @return the icon, or null if the icon wasn't found.
     */
    public Icon getIcon(String name) {
        Icon icon = null;
        URL url = null;
        ImageIcon imgicon = null;
        BufferedImage scaledImage = null;
        try {
            url = getClass().getResource(name);

            icon = new ImageIcon(url);
            if (icon == null) {
                System.out.println("Couldn't find " + url);
            }

            BufferedImage bi = new BufferedImage(
                    icon.getIconWidth(),
                    icon.getIconHeight(),
                    BufferedImage.TYPE_INT_RGB);
            Graphics g = bi.createGraphics();
            // paint the Icon to the BufferedImage.
            icon.paintIcon(null, g, 0,0);
            g.dispose();

            bi = resizeImage(bi,30,30);
            scaledImage = bi;// or replace with this line Scalr.resize(bi, 30,30);
            imgicon = new ImageIcon(scaledImage);

        } catch (Exception e) {
            System.out.println("Couldn't find " + getClass().getName() + "/" + name);
            e.printStackTrace();
        }
        return imgicon;
    }

 public static BufferedImage resizeImage (BufferedImage image, int areaWidth, int areaHeight) {
        float scaleX = (float) areaWidth / image.getWidth();
        float scaleY = (float) areaHeight / image.getHeight();
        float scale = Math.min(scaleX, scaleY);
        int w = Math.round(image.getWidth() * scale);
        int h = Math.round(image.getHeight() * scale);

        int type = image.getTransparency() == Transparency.OPAQUE ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;

        boolean scaleDown = scale < 1;

        if (scaleDown) {
            // multi-pass bilinear div 2
            int currentW = image.getWidth();
            int currentH = image.getHeight();
            BufferedImage resized = image;
            while (currentW > w || currentH > h) {
                currentW = Math.max(w, currentW / 2);
                currentH = Math.max(h, currentH / 2);

                BufferedImage temp = new BufferedImage(currentW, currentH, type);
                Graphics2D g2 = temp.createGraphics();
                g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                g2.drawImage(resized, 0, 0, currentW, currentH, null);
                g2.dispose();
                resized = temp;
            }
            return resized;
        } else {
            Object hint = scale > 2 ? RenderingHints.VALUE_INTERPOLATION_BICUBIC : RenderingHints.VALUE_INTERPOLATION_BILINEAR;

            BufferedImage resized = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2 = resized.createGraphics();
            g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
            g2.drawImage(image, 0, 0, w, h, null);
            g2.dispose();
            return resized;
        }
    }

答案 15 :(得分:0)

我开发了一个可用于处理GIF动画的免费类(AnimatedGifEncoder,GifDecoder和LWZEncoder)的解决方案。
您可以下载jgifcode jar并运行GifImageUtil类。 链接:http://www.jgifcode.com

答案 16 :(得分:0)

尝试以下方法:

ImageIcon icon = new ImageIcon("image.png");
Image img = icon.getImage();
Image newImg = img.getScaledInstance(350, 350, java.evt.Image.SCALE_SMOOTH);
icon = new ImageIcon(img);
JOptionPane.showMessageDialog(null, "image on The frame", "Display Image", JOptionPane.INFORMATION_MESSAGE, icon);