问题
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!
回答1:
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.
回答2:
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.
回答3:
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
.
回答4:
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();
}
}
}
来源:https://stackoverflow.com/questions/2155055/java-generating-thumbnails-with-transparency