【问题标题】:Java: Generating thumbnails with transparencyJava:生成具有透明度的缩略图
【发布时间】:2011-01-10 10:26:28
【问题描述】:

我在生成带有 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;
}

谢谢!

【问题讨论】:

  • GIF 图像没有 Alpha 通道,只有一种标记为透明的颜色。当您缩小它时,您最终会得到无法以 GIF 表示的数据。
  • 我明白了,所以我最好总是将缩略图保存为 JPEG 或 PNG?
  • 使用PNG会更好。完美的透明度。

标签: java image image-processing thumbnails


【解决方案1】:

用透明颜色缩小 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,而不是使用图形设备。

【讨论】:

  • 谢谢,我已将用于获取图像的方法添加到问题中。图像质量不是太大的问题,拇指会非常小,仅供用户了解它是哪个原始图像。
  • Malakim,您是否尝试过我发布的拇指方法而不是您的缩略图代码?它真的应该工作。只需传递缩略图的图像和框大小(以像素为单位)(代码负责水平和垂直,将其放入框内)。
  • 刚进办公室,马上试试。 - 谢谢!
  • 我不适合我。使用透明 GIF 时,我仍然会得到黑色背景。我尝试添加 if(image.getColorModel().hasAlpha()) { logger.debug("Orignal image has Alpha channel"); } if(thumb.getColorModel().hasAlpha()) { logger.debug("缩略图图像有 Alpha 通道"); } 第一个命中,但不是第二个。我还尝试在图像被渲染到新拇指后设置它(你方法中的最后一件事),但它仍然不会命中调试语句。 -谢谢!
【解决方案2】:

使用 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;

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 谢谢,我已将用于获取图像的方法添加到问题中。
    • 不,你没有。如果您使用getThumbnail(int size) 生成缩略图,则您没有包含您正在调用的getThumbnail 的2 参数实现。如果 getThumbnail 的 3 参数实现是相关的,那么你不会展示你是如何使用它的。
    【解决方案4】:

    您可以使用 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();
            }
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2015-09-10
      • 1970-01-01
      • 2018-12-23
      • 1970-01-01
      • 2015-06-13
      • 1970-01-01
      • 2016-12-29
      • 1970-01-01
      • 2011-04-18
      相关资源
      最近更新 更多