Java:生成具有透明度的缩略图

发布于 2024-08-19 11:01:33 字数 2245 浏览 3 评论 0原文

我在生成具有 Alpha 通道(透明度)的图像缩略图时遇到问题。我使用的代码是这样的:

public void saveThumbnail(File file, String imageType) {
    if (bufferedThumb == null) {
        return;
    }

    if(bufferedImage.getColorModel().hasAlpha()) {
        logger.debug("Original image has Alpha channel");
    }

    BufferedImage bi = new BufferedImage(bufferedThumb.getWidth(null), bufferedThumb.getHeight(null), BufferedImage.TYPE_INT_ARGB);
    Graphics g = bi.getGraphics();
    g.drawImage(bufferedThumb, 0, 0, null);
    try {
        ImageIO.write(bi, imageType, file);
    } catch (IOException ioe) {
        ioe.printStackTrace();
        System.out.println("Error occured saving thumbnail");
    }
}

但是,如果我提供例如具有透明背景的 GIF 图像,我总是会得到黑色或彩色背景。

编辑:

这就是使用缩略图从类中调用它的方式,我上次错过了 getThuimbnail() 方法的两个参数版本:

Thumbnail th = new Thumbnail(file.getPath());
th.getThumbnail(100);

添加了用于获取图像的方法:

public Thumbnail(String fileName) {
    try {
        this.bufferedImage = ImageIO.read(new File(fileName));
    } catch (IOException ex) {
        logger.error("Failed to read image file: " + ex.getMessage());
    }
}

public Image getThumbnail(int size) {
    int dir = VERTICAL;
    if (bufferedImage.getHeight() < bufferedImage.getWidth()) {
        dir = HORIZONTAL;
    }
    return getThumbnail(size, dir);
}

/**
 * Creates image with specifed max sized to a specified direction.
 * Will use Image.SCALE_SMOOTH for scaling.
 * @param size Maximum size
 * @param dir Direction of maximum size - 0 = vertical, 1 = height.
 * @return Resized image.
 */
public Image getThumbnail(int size, int dir) {
    return getThumbnail(size, dir, Image.SCALE_SMOOTH);
}

/**
 * Creates image with specified size.
 * @param size Maximum size
 * @param dir Direction of maximum size - 0 = vertical, 1 = height.
 * @param scale Image.Scale to use for conversion.
 * @return Resized image.
 */
public Image getThumbnail(int size, int dir, int scale) {
    if (dir == HORIZONTAL) {
        bufferedThumb = bufferedImage.getScaledInstance(size, -1, scale);
    } else {
        bufferedThumb = bufferedImage.getScaledInstance(-1, size, scale);
    }
    return bufferedThumb;
}

谢谢!

I'm having problems generating thumbnails of images with an Alpha channel (transparency). The code I use is this:

public void saveThumbnail(File file, String imageType) {
    if (bufferedThumb == null) {
        return;
    }

    if(bufferedImage.getColorModel().hasAlpha()) {
        logger.debug("Original image has Alpha channel");
    }

    BufferedImage bi = new BufferedImage(bufferedThumb.getWidth(null), bufferedThumb.getHeight(null), BufferedImage.TYPE_INT_ARGB);
    Graphics g = bi.getGraphics();
    g.drawImage(bufferedThumb, 0, 0, null);
    try {
        ImageIO.write(bi, imageType, file);
    } catch (IOException ioe) {
        ioe.printStackTrace();
        System.out.println("Error occured saving thumbnail");
    }
}

However, if I supply for example a GIF image with a transparent background I always end up with a black or colored background.

EDIT:

This is how it's called from the class using the thumbnail, I missed the two-parameter version of the getThuimbnail()-method the last time:

Thumbnail th = new Thumbnail(file.getPath());
th.getThumbnail(100);

Added methods used for getting the images:

public Thumbnail(String fileName) {
    try {
        this.bufferedImage = ImageIO.read(new File(fileName));
    } catch (IOException ex) {
        logger.error("Failed to read image file: " + ex.getMessage());
    }
}

public Image getThumbnail(int size) {
    int dir = VERTICAL;
    if (bufferedImage.getHeight() < bufferedImage.getWidth()) {
        dir = HORIZONTAL;
    }
    return getThumbnail(size, dir);
}

/**
 * Creates image with specifed max sized to a specified direction.
 * Will use Image.SCALE_SMOOTH for scaling.
 * @param size Maximum size
 * @param dir Direction of maximum size - 0 = vertical, 1 = height.
 * @return Resized image.
 */
public Image getThumbnail(int size, int dir) {
    return getThumbnail(size, dir, Image.SCALE_SMOOTH);
}

/**
 * Creates image with specified size.
 * @param size Maximum size
 * @param dir Direction of maximum size - 0 = vertical, 1 = height.
 * @param scale Image.Scale to use for conversion.
 * @return Resized image.
 */
public Image getThumbnail(int size, int dir, int scale) {
    if (dir == HORIZONTAL) {
        bufferedThumb = bufferedImage.getScaledInstance(size, -1, scale);
    } else {
        bufferedThumb = bufferedImage.getScaledInstance(-1, size, scale);
    }
    return bufferedThumb;
}

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

橘和柠 2024-08-26 11:01:33

缩小具有透明颜色的 GIF 图像应该可以正常工作。我同意 jarnbjo 的观点,问题很可能出在 bufferedThumb 生成中。

也许以下提示会有所帮助:

1)创建缩略图时,从源复制图像类型,例如:

BufferedImage thumb = new BufferedImage(fit, fit, image.getType());

2)使用 2D 方法:

Graphics2D g = thumb.createGraphics();

这里有一些用于简单缩略图创建的示例代码(经过测试并且有效;透明度 GIF,缩略图保持透明度):

  public static BufferedImage thumb(BufferedImage image, int fit) {

    //image = blur(image);
    BufferedImage thumb = new BufferedImage(fit, fit, image.getType());
    Graphics2D g = thumb.createGraphics();

    try {
      int width = image.getWidth();
      int height = image.getHeight();
      int sx1;
      int sy1;
      int sx2;
      int sy2;
      int tmp;

      if (height > width) {
        tmp = height - width;
        sx1 = 0;
        sy1 = tmp / 2;
        sx2 = width;
        sy2 = height - sy1;
      } else if (width > height) {
        tmp = width - height;
        sx1 = tmp / 2;
        sy1 = 0;
        sx2 = width - sx1;
        sy2 = height;
      } else {
        sx1 = 0;
        sy1 = 0;
        sx2 = width;
        sy2 = height;
      }

      g.drawImage(
          image,
          0, 0,
          fit, fit,
          sx1, sy1,
          sx2, sy2,
          null
      );

    } finally {
      g.dispose();
    }
    return thumb;
  }//thumb

注意:简单,我的意思是,如果您尝试在一个步骤中缩放太多(例如,2048 像素入,100 像素出),它不会产生高质量的结果。您可能需要采取多步骤方法,并且可能应该诉诸带有提示的 AffineTransformOp,而不是使用图形设备。

Scaling down GIF images with a transparent color should work fine. I agree with jarnbjo, that the problem is most likely in the bufferedThumb generation.

Maybe the following hints help:

1) When creating the thumb copy the image type from the source e.g.:

BufferedImage thumb = new BufferedImage(fit, fit, image.getType());

2) Use the 2D approach:

Graphics2D g = thumb.createGraphics();

Here some sample code for simple thumb creation (tested and works; transparency GIF in, thumb keeps transparency):

  public static BufferedImage thumb(BufferedImage image, int fit) {

    //image = blur(image);
    BufferedImage thumb = new BufferedImage(fit, fit, image.getType());
    Graphics2D g = thumb.createGraphics();

    try {
      int width = image.getWidth();
      int height = image.getHeight();
      int sx1;
      int sy1;
      int sx2;
      int sy2;
      int tmp;

      if (height > width) {
        tmp = height - width;
        sx1 = 0;
        sy1 = tmp / 2;
        sx2 = width;
        sy2 = height - sy1;
      } else if (width > height) {
        tmp = width - height;
        sx1 = tmp / 2;
        sy1 = 0;
        sx2 = width - sx1;
        sy2 = height;
      } else {
        sx1 = 0;
        sy1 = 0;
        sx2 = width;
        sy2 = height;
      }

      g.drawImage(
          image,
          0, 0,
          fit, fit,
          sx1, sy1,
          sx2, sy2,
          null
      );

    } finally {
      g.dispose();
    }
    return thumb;
  }//thumb

Note: with simple, I mean that it won't produce high quality results if you are trying to scale too much in a single step (e.g. 2048 px in, 100px out). You may need to take a multi-step approach, and probably you should resort to an AffineTransformOp with hints instead of using the Graphics device.

丑疤怪 2024-08-26 11:01:33

通过使用 AffineTransform 缩放操作解决了这个问题:

AffineTransform af = new AffineTransform();
af.scale(scaleFactor, scaleFactor);

AffineTransformOp operation = new AffineTransformOp(af, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
bufferedThumb = operation.filter(bufferedImage, null);
return bufferedThumb;

这似乎保留了图像中的任何透明度。

Solved it by using an AffineTransform scale operation:

AffineTransform af = new AffineTransform();
af.scale(scaleFactor, scaleFactor);

AffineTransformOp operation = new AffineTransformOp(af, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
bufferedThumb = operation.filter(bufferedImage, null);
return bufferedThumb;

This seems to preserve any transparency in the image.

败给现实 2024-08-26 11:01:33

您用于写入文件的代码是正确的,至少如果您使用支持透明度的格式(例如 PNG)。最有可能的是,bufferedThumb已经损坏,因此为了帮助您,如果您说明如何获取bufferedImage以及如何创建bufferedThumb,将会更有帮助。代码>.

The code you're using for writing the file is correct, at least if you use a format which supports transparency (e.g. PNG). Most probably, bufferedThumb is already corrupted, so to help you, it would be of more help if you stated how you get bufferedImage and how you create bufferedThumb.

听不够的曲调 2024-08-26 11:01:33

进行尝试:

您可以使用 Image IO Library: PFB 代码

package com.incture.thumbnail;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class Thumnail {

    public static void main(String[] args) {

        String source = "E:/Incture/APAutomation/NewWorkspace/BarCodeReading/download-button.gif";
        String target = "E:/Incture/APAutomation/NewWorkspace/BarCodeReading/thumb1.jpg";

        saveScaledImage(source, target);

    }

    public static void saveScaledImage(String filePath, String outputFile) {

        BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
        try {
            Graphics g=img.getGraphics();
            g.setColor(Color.white);
            g.fillRect(0, 0, img.getWidth(), img.getHeight());   
            g.drawImage(ImageIO.read(new File(filePath)), 0 , 0, 20, 20, null);
            ImageIO.write(img, "png", new File(outputFile));
            System.out.println("done");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

You can try it using Image IO Library:

PFB the code:

package com.incture.thumbnail;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class Thumnail {

    public static void main(String[] args) {

        String source = "E:/Incture/APAutomation/NewWorkspace/BarCodeReading/download-button.gif";
        String target = "E:/Incture/APAutomation/NewWorkspace/BarCodeReading/thumb1.jpg";

        saveScaledImage(source, target);

    }

    public static void saveScaledImage(String filePath, String outputFile) {

        BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
        try {
            Graphics g=img.getGraphics();
            g.setColor(Color.white);
            g.fillRect(0, 0, img.getWidth(), img.getHeight());   
            g.drawImage(ImageIO.read(new File(filePath)), 0 , 0, 20, 20, null);
            ImageIO.write(img, "png", new File(outputFile));
            System.out.println("done");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文