简体   繁体   中英

Java: Generating thumbnails with transparency

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!

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 eg:

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 (eg 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.

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.

The code you're using for writing the file is correct, at least if you use a format which supports transparency (eg 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 .

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();
        }
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM