[英]How to scale a Graphics2D image with transparent padding
I'm trying to write a small method which takes a BufferedImage
image and a new width and height and scales the image keeping the aspect ratio by adding transparent border to the left/right or top/bottom depending on the image. 我正在尝试编写一个小方法,它采用BufferedImage
图像和新的宽度和高度,并通过根据图像向左/右或上/下添加透明边框来缩放图像以保持纵横比。 The scaling works fine but for the life of me I can't get the border to be transparent. 缩放工作正常,但对于我的生活,我不能让边框透明。
So far I have the following code posted on pastebin.com which does the scaling well. 到目前为止,我在pastebin.com上发布了以下代码,它可以很好地进行扩展。
I've read a lot of manuals and other SO questions to no avail. 我已经阅读了很多手册和其他SO问题无济于事。 I've tried numerous permutations of fills, composite types, image types, etc.. Sometimes I get a blue background, sometimes white but it never seems to be transparent. 我尝试了很多填充,复合类型,图像类型等的排列。有时我得到一个蓝色的背景,有时是白色但它似乎永远不会透明。
BufferedImage newImg = new BufferedImage(newWidth, newHeight, img.getType());
Graphics2D g = newImg.createGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, newWidth, newHeight);
g.drawImage(img, x, y, x + scaledWidth, y + scaledHeight, 0, 0,
currentWidth, currentHeight, Color.WHITE, null);
g.dispose();
return newImg;
Any idea what Graphics2D call I need to make to have the Color.WHITE
background be transparent and draw the old image over the new? 知道我需要做什么Graphics2D才能使Color.WHITE
背景透明并在新的上面绘制旧图像? Thanks for any help. 谢谢你的帮助。
Edit: 编辑:
It turned out that the problem I was having was that I was trying to generate a transparent color with a JPEG image. 事实证明,我遇到的问题是我试图用JPEG图像生成透明色。 JPEGs do not support transparency. JPEG不支持透明度。 Duh. 咄。
I've just tried it out and it works. 我刚试了一下它就可以了。
Just replace Color.WHITE
with new Color(0, 0, 0, 0)
, and img.getType()
with BufferedImage.TYPE_INT_ARGB
. 只需将Color.WHITE
替换为new Color(0, 0, 0, 0)
img.getType()
new Color(0, 0, 0, 0)
,将img.getType()
替换为BufferedImage.TYPE_INT_ARGB
。
BufferedImage img = ImageIO.read(new File("image.png"));
BufferedImage outImage = scaleWithPadding(img, 300, 100);
ImageIO.write(outImage, "png", new File("newImage.png"));
image.png: (204x53) image.png: (204x53)
newImage.png: (300x100) newImage.png: (300x100)
I had the same requirement as you and your post and this page on how to make a color transparent helped me a lot. 我和你的帖子有相同的要求,这个关于如何使颜色变得透明的页面帮助了我很多。
Here is my final code: 这是我的最终代码:
public BufferedImage getTransparentScaledImage(BufferedImage originalImage, int finalWidth, int finalHeight) {
int originalWidth = originalImage.getWidth();
int originalHeight = originalImage.getHeight();
int newWidth;
int newHeight;
if (originalWidth == 0 || originalHeight == 0
|| (originalWidth == finalWidth && originalHeight == finalHeight)) {
return originalImage;
}
double aspectRatio = (double) originalWidth / (double) originalHeight;
double boundaryAspect = (double) finalWidth / (double) finalHeight;
if (aspectRatio > boundaryAspect) {
newWidth = finalWidth;
newHeight = (int) Math.round(newWidth / aspectRatio);
} else {
newHeight = finalHeight;
newWidth = (int) Math.round(aspectRatio * newHeight);
}
int xOffset = (finalWidth - newWidth) / 2;
int yOffset = (finalHeight - newHeight) / 2;
LoggerManager.getInstance().debug("frontoffice",
"Image Servlet: [" + xOffset + "] [" + yOffset + "] [" + newWidth + "] [" + newHeight + "] [" + originalWidth + "] [" + originalHeight + "] [" + finalWidth + "] [" + finalHeight + "]");
BufferedImage intermediateImage = new BufferedImage(finalWidth, finalHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D gi = intermediateImage.createGraphics();
gi.setComposite(AlphaComposite.SrcOver);
gi.setColor(Color.WHITE);
gi.fillRect(0, 0, finalWidth, finalHeight);
gi.drawImage(originalImage, xOffset, yOffset, xOffset + newWidth, yOffset + newHeight, 0, 0, originalWidth, originalHeight, Color.WHITE, null);
gi.dispose();
//if image from db already had a transparent background, it becomes black when drawing it onto another
//even if we draw it onto a transparent image
//so we set it to a specific color, in this case white
//now we have to set that white background transparent
Image intermediateWithTransparentPixels = makeColorTransparent(intermediateImage, Color.WHITE);
//finalize the transparent image
BufferedImage finalImage = new BufferedImage(finalWidth, finalHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D gf = finalImage.createGraphics();
gf.setComposite(AlphaComposite.SrcOver);
gf.setColor(new Color(0, 0, 0, 0));
gf.fillRect(0, 0, finalWidth, finalHeight);
gf.drawImage(intermediateWithTransparentPixels, 0, 0, finalWidth, finalHeight, new Color(0, 0, 0, 0), null);
gf.dispose();
return finalImage;
}
public static Image makeColorTransparent(Image im, final Color color) {
ImageFilter filter = new RGBImageFilter() {
// the color we are looking for... Alpha bits are set to opaque
public int markerRGB = color.getRGB() | 0xFF000000;
public final int filterRGB(int x, int y, int rgb) {
if ((rgb | 0xFF000000) == markerRGB) {
// Mark the alpha bits as zero - transparent
return 0x00FFFFFF & rgb;
} else {
// nothing to do
return rgb;
}
}
};
ImageProducer ip = new FilteredImageSource(im.getSource(), filter);
return Toolkit.getDefaultToolkit().createImage(ip);
}
I implemented the mentioned solutions (or very similar) just pay attention if you don't use 我实施了上述解决方案(或非常相似),如果你不使用,请注意
graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
graphics2D.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON;
your images will be generated with very poor quality (due to scaling) 您的图像将以非常差的质量生成(由于缩放)
Your original drawImage()
method did not have a transparent background because the Color of the background was being used. 您的原始drawImage()
方法没有透明背景,因为正在使用背景的颜色。 Replace with the following: 替换为以下内容:
g.drawImage(img, x, y, x + scaledWidth, y + scaledHeight, 0, 0, currentWidth, currentHeight, null);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.