47

有人可以帮忙用一些代码为Java中的JPEG创建缩略图。

我是新来的,所以一步一步的解释将不胜感激。

4

15 回答 15

79
Image img = ImageIO.read(new File("test.jpg")).getScaledInstance(100, 100, BufferedImage.SCALE_SMOOTH);

这将创建一个 100x100 像素的缩略图作为 Image 对象。如果要将其写回磁盘,只需将代码转换为:

BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
img.createGraphics().drawImage(ImageIO.read(new File("test.jpg")).getScaledInstance(100, 100, Image.SCALE_SMOOTH),0,0,null);
ImageIO.write(img, "jpg", new File("test_thumb.jpg"));

此外,如果您担心速度问题(如果您想缩放许多图像,上述方法相当慢)请使用这些方法和以下声明:

private BufferedImage scale(BufferedImage source,double ratio) {
  int w = (int) (source.getWidth() * ratio);
  int h = (int) (source.getHeight() * ratio);
  BufferedImage bi = getCompatibleImage(w, h);
  Graphics2D g2d = bi.createGraphics();
  double xScale = (double) w / source.getWidth();
  double yScale = (double) h / source.getHeight();
  AffineTransform at = AffineTransform.getScaleInstance(xScale,yScale);
  g2d.drawRenderedImage(source, at);
  g2d.dispose();
  return bi;
}

private BufferedImage getCompatibleImage(int w, int h) {
  GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
  GraphicsDevice gd = ge.getDefaultScreenDevice();
  GraphicsConfiguration gc = gd.getDefaultConfiguration();
  BufferedImage image = gc.createCompatibleImage(w, h);
  return image;
}

然后调用:

BufferedImage scaled = scale(img,0.5);

其中 0.5 是比例,img 是包含正常大小图像的 BufferedImage。

于 2009-07-01T13:24:39.993 回答
36

您可能已经发现“简单”和“好看的结果”是两个截然不同的东西。我已经将这两个要求都封装到了一个非常简单的java 图像缩放库(Apache 2 许可)中,它可以为您做所有正确的事情。

创建缩略图的示例代码如下所示:

BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, 150);

您的图像比例得到尊重,该库根据缩放(FASTEST、BALANCED 或 QUALITY)引起的图像变化量对它应该使用的方法做出最佳猜测,并且始终使用最受支持的 Java2D 图像类型来做缩放以避免“黑色”结果或看起来非常糟糕的输出(例如过度抖动的 GIF 图像)的问题。

此外,如果您想强制它在 Java 中输出最好看的缩略图,API 调用将如下所示:

BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, Method.QUALITY, 
                                       150, 100, Scalr.OP_ANTIALIAS);

该库不仅将使用 Java2D 推荐的增量缩放来为您提供最佳效果,它还将对缩略图应用可选的抗锯齿效果(ConvolveOp 具有非常微调的内核),以稍微软化像素值之间的过渡,使缩略图看起来更均匀,而不像您从非常大的图像到非常小的图像时可能看到的那样锐利或罂粟。

您可以阅读库中的所有注释(代码本身被大量文档化),以查看所有已解决的不同 JDK 错误或为提高性能或内存使用而进行的优化。我花了很多时间调整这个实现,并且从将它部署到 Web 应用程序和其他 Java 项目中的人们那里得到了很多很好的反馈。

于 2011-07-05T16:47:40.497 回答
12

这是创建 100 X 100 缩略图的简单方法,图像中没有任何拉伸或倾斜。

private  void saveScaledImage(String filePath,String outputFile){
    try {

        BufferedImage sourceImage = ImageIO.read(new File(filePath));
        int width = sourceImage.getWidth();
        int height = sourceImage.getHeight();

        if(width>height){
            float extraSize=    height-100;
            float percentHight = (extraSize/height)*100;
            float percentWidth = width - ((width/100)*percentHight);
            BufferedImage img = new BufferedImage((int)percentWidth, 100, BufferedImage.TYPE_INT_RGB);
            Image scaledImage = sourceImage.getScaledInstance((int)percentWidth, 100, Image.SCALE_SMOOTH);
            img.createGraphics().drawImage(scaledImage, 0, 0, null);
            BufferedImage img2 = new BufferedImage(100, 100 ,BufferedImage.TYPE_INT_RGB);
            img2 = img.getSubimage((int)((percentWidth-100)/2), 0, 100, 100);

            ImageIO.write(img2, "jpg", new File(outputFile));    
        }else{
            float extraSize=    width-100;
            float percentWidth = (extraSize/width)*100;
            float  percentHight = height - ((height/100)*percentWidth);
            BufferedImage img = new BufferedImage(100, (int)percentHight, BufferedImage.TYPE_INT_RGB);
            Image scaledImage = sourceImage.getScaledInstance(100,(int)percentHight, Image.SCALE_SMOOTH);
            img.createGraphics().drawImage(scaledImage, 0, 0, null);
            BufferedImage img2 = new BufferedImage(100, 100 ,BufferedImage.TYPE_INT_RGB);
            img2 = img.getSubimage(0, (int)((percentHight-100)/2), 100, 100);

            ImageIO.write(img2, "jpg", new File(outputFile));
        }

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}
于 2012-04-11T07:34:43.113 回答
4

JMagick库(以及 Java 中ImageMagick的实现)将满足您的需求。

于 2009-07-01T13:26:50.363 回答
3

上面的 Java 代码(使用 scale / getCompatibleImage 方法)对我来说非常有用,但是当我部署到服务器时,它停止工作,因为服务器没有与之关联的显示——任何其他有这个问题的人都可以通过使用来修复它: BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);

而不是 BufferedImage bi = getCompatibleImage(w, h);

并删除 getCompatibleImage 方法

(稍后注意 - 事实证明这对大多数图像都很好,但我从公司的营销部门得到了一堆 32 位颜色深度 jpeg 图像,并且库对所有这些图像都抛出了不受支持的图像格式异常:( - - imagemagick / jmagick 开始看起来更具吸引力)

于 2010-07-22T00:04:09.010 回答
3

我知道这是一个很老的帖子。我一直在寻找生成缩略图的解决方案,所以最终使用它

Thumbnails.of(originalImage).scale(0.25).asBufferedImage();

如果您使用的是移动设备,建议您将比例设置为 0.45

Thumbnails.of(originalImage).scale(0.45).asBufferedImage();

https://github.com/coobird/thumbnailator

使用 Graphics2D 这当然要快得多,因为已经测试了这两个选项。

于 2017-04-05T15:13:52.237 回答
3

几年前,我使用 JAI 编写了一个带有静态方法的 util 类。Java Advanced Imaging API 是 Java 中处理图像最可靠的 API。它的矢量插值是 Java 世界中最接近 Photoshop 的东西。这是其中之一:

public static ByteArrayOutputStream resize(InputStream inputStream , int IMG_WIDTH,
        int IMG_HEIGHT) throws Exception {
    BufferedImage originalImage = ImageIO.read(inputStream);
    int type = originalImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB
            : originalImage.getType();
    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();
        g.setComposite(AlphaComposite.Src);

        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.setRenderingHint(RenderingHints.KEY_RENDERING,
                RenderingHints.VALUE_RENDER_QUALITY);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
    }
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ImageIO.write(resizedImage, "png", bos);
    return bos;

} 
于 2016-09-04T04:45:15.230 回答
2

我用过缩略图!它用两行代码解决了我的问题。

https://github.com/coobird/thumbnailator

于 2015-08-11T18:23:35.007 回答
1

我浏览了一个博客,根据该博客您有以下选项 -

  1. 对于简单的 RGB 文件,请使用 ImageScalr 。ImageIO 类用于读取文件,ImageScalr 用于创建缩略图
  2. 为了支持 RGB + CYMK,使用 ImageIO 和 JAI (Java Advanced Imaging) API 读取文件和 ImageScalr 创建缩略图。
  3. 如果您不知道要处理的文件格式和颜色模式,最安全的选择是使用 ImageMagick。

这是链接,它通过代码片段给出了完整的答案。

于 2014-06-03T05:15:56.797 回答
1

我创建了一个名为 fotovault (sourceforge.net) 的应用程序,它可以使用 imagej apis 在 java 中上传图像和创建缩略图。

请在下面阅读我的博客

http://www.gingercart.com/Home/java-snippets/create-image-thumbnail-in-java-using-imagej-api

于 2014-02-16T18:34:21.667 回答
1

有许多可用的图像处理框架,只需几行代码即可完成。下面的示例使用Marvin Framework生成不同分辨率的缩略图(给定宽度作为参考)。这三个缩略图是在92 毫秒内生成的。

输入:

在此处输入图像描述

输出:

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

import static marvin.MarvinPluginCollection.*;

MarvinImage image = MarvinImageIO.loadImage("./res/input.jpg");
MarvinImage scaledImage = new MarvinImage(1,1);

scale(image, scaledImage, 250);
MarvinImageIO.saveImage(scaledImage, "./res/output_x250.jpg");

scale(image, scaledImage, 150);
MarvinImageIO.saveImage(scaledImage, "./res/output_x150.jpg");

scale(image, scaledImage, 50);
MarvinImageIO.saveImage(scaledImage, "./res/output_x50.jpg");
于 2016-05-30T14:13:21.543 回答
1

无需拉伸或库即可创建缩略图的简单方法。也适用于 png 中的透明度。

public File createThumbnail(String imageUrl, String targetPath) {
    final int imageSize = 100;
    File thumbnail = new File(targetPath);

    try {
        thumbnail.getParentFile().mkdirs();
        thumbnail.createNewFile();
        BufferedImage sourceImage = ImageIO.read(new File(imageUrl));
        float width = sourceImage.getWidth();
        float height = sourceImage.getHeight();

        BufferedImage img2;
        if (width > height) {
            float scaledWidth = (width / height) * (float) imageSize;
            float scaledHeight = imageSize;

            BufferedImage img = new BufferedImage((int) scaledWidth, (int) scaledHeight, sourceImage.getType());
            Image scaledImage = sourceImage.getScaledInstance((int) scaledWidth, (int) scaledHeight, Image.SCALE_SMOOTH);
            img.createGraphics().drawImage(scaledImage, 0, 0, null);

            int offset = (int) ((scaledWidth - scaledHeight) / 2f);
            img2 = img.getSubimage(offset, 0, imageSize, imageSize);
        }
        else if (width < height) {
            float scaledWidth = imageSize;
            float scaledHeight = (height / width) * (float) imageSize;

            BufferedImage img = new BufferedImage((int) scaledWidth, (int) scaledHeight, sourceImage.getType());
            Image scaledImage = sourceImage.getScaledInstance((int) scaledWidth, (int) scaledHeight, Image.SCALE_SMOOTH);
            img.createGraphics().drawImage(scaledImage, 0, 0, null);

            int offset = (int) ((scaledHeight - scaledWidth) / 2f);
            img2 = img.getSubimage(0, offset, imageSize, imageSize);
        }
        else {
            img2 = new BufferedImage(imageSize, imageSize, sourceImage.getType());
            Image scaledImage = sourceImage.getScaledInstance(imageSize, imageSize, Image.SCALE_SMOOTH);
            img2.createGraphics().drawImage(scaledImage, 0, 0, null);
        }
        ImageIO.write(img2, "png", thumbnail);
    }
    catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return thumbnail;
}
于 2016-07-20T08:49:40.770 回答
0

也许最简单的方法是:

static public BufferedImage scaleImage(BufferedImage image, int max_width, int max_height) {
    int img_width = image.getWidth();
    int img_height = image.getHeight();

    float horizontal_ratio = 1;
    float vertical_ratio    = 1;


    if(img_height > max_height) {
        vertical_ratio = (float)max_height / (float)img_height;
    }
    if(img_width > max_width) {
        horizontal_ratio = (float)max_width / (float)img_width;
    }

    float scale_ratio = 1;

    if (vertical_ratio < horizontal_ratio) {
        scale_ratio = vertical_ratio;
    }
    else if (horizontal_ratio < vertical_ratio) {
        scale_ratio = horizontal_ratio;
    }

    int dest_width  = (int) (img_width * scale_ratio);
    int dest_height = (int) (img_height * scale_ratio);

    BufferedImage scaled = new BufferedImage(dest_width, dest_height, image.getType());
    Graphics graphics = scaled.getGraphics();
    graphics.drawImage(image, 0, 0, dest_width, dest_height, null);
    graphics.dispose();

    return scaled;

}
于 2020-07-24T16:47:00.110 回答
0

Thumbnails4j(我是维护者,但它归Elastic所有)是一个 Java 库,可用于从图像文件以及其他文件类型创建缩略图。

File input = new File("/path/to/my_file.jpeg");
Thumbnailer thumbnailer = new ImageThumbnailer("png"); // or "jpg", whichever output format you want
List<Dimensions> outputDimensions = Collections.singletonList(new Dimensions(100, 100));
BufferedImage output = thumbnailer.getThumbnails(input, outputDimensions).get(0);
于 2022-01-05T20:46:34.050 回答
0

当您想(75x75)从非方形源创建方形缩略图时的解决方案。

下面的代码首先使用比调整方形图像大小更小的尺寸将原始图像裁剪为方形。

public static void generateThumbnailWithCrop(String imgPath, String thumbnailPath, int size) throws IOException {
    BufferedImage sourceImage = ImageIO.read(new File(imgPath));
    int width = sourceImage.getWidth();
    int height = sourceImage.getHeight();
    int smallerSize = width > height ? height : width;
    BufferedImage quadrateImage = cropToQuadrate(sourceImage, smallerSize);
    int type = quadrateImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : quadrateImage.getType();
    BufferedImage resizedImage = resizeImageWithHint(quadrateImage, type, size, size);
    File thumb = new File(thumbnailPath);
    thumb.getParentFile().mkdirs();
    ImageIO.write(resizedImage, "jpg", thumb);
}

private static BufferedImage cropToQuadrate(BufferedImage sourceImage, int size) {
    BufferedImage img = sourceImage.getSubimage(0, 0, size, size);
    BufferedImage copyOfImage = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB);
    Graphics g = copyOfImage.createGraphics();
    g.drawImage(img, 0, 0, null);
    return copyOfImage;
}
private static BufferedImage resizeImageWithHint(BufferedImage originalImage, int type, int width, int height) {
    BufferedImage resizedImage = new BufferedImage(width, height, type);
    Graphics2D g = resizedImage.createGraphics();
    g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g.setComposite(AlphaComposite.Src);
    g.drawImage(originalImage, 0, 0, width, height, null);
    g.dispose();

    return resizedImage;
}
于 2021-06-18T08:08:44.787 回答