在JAVA中将透明的图像转换成JPEG格式
在JAVA中将透明的图像转换成JPEG格式
在JAVA中将图像文件转换成JPEG,通常使用下面的代码:
1File __pngFile = new File("exportUnit.png");
2File __jpgFile = new File("exportUnit.jpg");
3writeJPEG(__pngFile, __jpgFile, 80);
4
5public static void writeJPEG(File $source, File $dest, int $quality) throws IOException
6{
7 String __formatName = "jpeg";
8 BufferedImage __image = ImageIO.read($source);
9 ImageWriter __writer = ImageIO.getImageWritersByFormatName(__formatName).next();
10 ImageWriteParam __writeParam = __writer.getDefaultWriteParam();
11 FileOutputStream __out = new FileOutputStream($dest);
12 __writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
13 __writeParam.setCompressionQuality((float)$quality/100f);
14 __writer.setOutput(ImageIO.createImageOutputStream(__out));
15 __writer.write(null, new IIOImage(__image, null, null), __writeParam);
16 __out.flush();
17 __out.close();
18 __writer.dispose();
19}
但是,当被转换的文件是32位带Alpha通道的图像文件转换为JPEG的时候,会出现颜色错误。就像下面这样:
转换前的 PNG 图像
转换后的 JPEG 图像
出现这种错误的原因,是强行将32位的ARGB图像转换成了24位的RGB图像,转换过程中没有指定正确的色彩转换方式。下面的2种方法都可以解决这个问题。
要使用这2种方法,可以在writeJPEG方法中加入下面的判断:
1//如果图像是透明的,就丢弃Alpha通道
2if(__image.getTransparency() == Transparency.TRANSLUCENT)
3 __image = get24BitImage(__image);
4 //__image = get24BitImage(__image, Color.BLACK);
第一种方法,删除32位ARGB颜色中的Alpha通道
根据ARGB的颜色表示法,32位颜色的前8位代表Alpha值。因此只需要将前8位去掉,就得到了不带Alpha通道的24位颜色值。详见下面的代码:
1/**
2 * 使用删除alpha值的方式去掉图像的alpha通道
3 * @param $image
4 * @return
5 */
6protected static BufferedImage get24BitImage(BufferedImage $image)
7{
8 int __w = $image.getWidth();
9 int __h = $image.getHeight();
10 int[] __imgARGB = getRGBs($image.getRGB(0, 0, __w, __h, null, 0, __w));
11 BufferedImage __newImg = new BufferedImage(__w, __h, BufferedImage.TYPE_INT_RGB);
12 __newImg.setRGB(0, 0, __w, __h, __imgARGB, 0, __w);
13 return __newImg;
14}
15
16/**
17 * 将32位色彩转换成24位色彩(丢弃Alpha通道)
18 * @param $argb
19 * @return
20 */
21public static int[] getRGBs(int[] $argb)
22{
23 int[] __rgbs = new int[$argb.length];
24 for(int i=0;i<$argb.length;i++)
25 {
26 __rgbs[i] = $argb[i] & 0xFFFFFF;
27 }
28 return __rgbs;
29}
第二种方法,使用绘制的方式去掉图像的alpha值
使用这种方法的优势在于,可以很方便的控制生成的JPEG图像的背景色。
1/**
2 * 使用绘制的方式去掉图像的alpha值
3 * @param $image
4 * @param $bgColor
5 * @return
6 */
7protected static BufferedImage get24BitImage(BufferedImage $image, Color $bgColor)
8{
9 int $w = $image.getWidth();
10 int $h = $image.getHeight();
11 BufferedImage __image = new BufferedImage($w, $h, BufferedImage.TYPE_INT_RGB);
12 Graphics2D __graphic = __image.createGraphics();
13 __graphic.setColor($bgColor);
14 __graphic.fillRect(0,0,$w,$h);
15 __graphic.drawRenderedImage($image, null);
16 __graphic.dispose();
17 return __image;
18}
完整的代码
1import java.awt.Color;
2import java.awt.Graphics2D;
3import java.awt.Transparency;
4import java.awt.image.BufferedImage;
5import java.io.File;
6import java.io.FileOutputStream;
7import java.io.IOException;
8
9import javax.imageio.IIOImage;
10import javax.imageio.ImageIO;
11import javax.imageio.ImageWriteParam;
12import javax.imageio.ImageWriter;
13
14public class ConvertJPEG
15{
16
17 /**
18 * @param args
19 * @throws IOException
20 */
21 public static void main(String[] args) throws IOException
22 {
23 File __pngFile = new File("exportUnit.png");
24 File __jpgFile = new File("exportUnit.jpg");
25 writeJPEG(__pngFile, __jpgFile, 80);
26 }
27
28 public static void writeJPEG(File $source, File $dest, int $quality) throws IOException
29 {
30 String __formatName = "jpeg";
31 BufferedImage __image = ImageIO.read($source);
32 //如果图像是透明的,就丢弃Alpha通道
33 if(__image.getTransparency() == Transparency.TRANSLUCENT)
34 __image = get24BitImage(__image);
35 //__image = get24BitImage(__image, Color.BLACK);
36 ImageWriter __writer = ImageIO.getImageWritersByFormatName(__formatName).next();
37 ImageWriteParam __writeParam = __writer.getDefaultWriteParam();
38 FileOutputStream __out = new FileOutputStream($dest);
39 __writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
40 __writeParam.setCompressionQuality((float)$quality/100f);
41 __writer.setOutput(ImageIO.createImageOutputStream(__out));
42 __writer.write(null, new IIOImage(__image, null, null), __writeParam);
43 __out.flush();
44 __out.close();
45 __writer.dispose();
46 }
47
48 /**
49 * 使用删除alpha值的方式去掉图像的alpha通道
50 * @param $image
51 * @return
52 */
53 protected static BufferedImage get24BitImage(BufferedImage $image)
54 {
55 int __w = $image.getWidth();
56 int __h = $image.getHeight();
57 int[] __imgARGB = getRGBs($image.getRGB(0, 0, __w, __h, null, 0, __w));
58 BufferedImage __newImg = new BufferedImage(__w, __h, BufferedImage.TYPE_INT_RGB);
59 __newImg.setRGB(0, 0, __w, __h, __imgARGB, 0, __w);
60 return __newImg;
61 }
62
63 /**
64 * 使用绘制的方式去掉图像的alpha值
65 * @param $image
66 * @param $bgColor
67 * @return
68 */
69 protected static BufferedImage get24BitImage(BufferedImage $image, Color $bgColor)
70 {
71 int $w = $image.getWidth();
72 int $h = $image.getHeight();
73 BufferedImage __image = new BufferedImage($w, $h, BufferedImage.TYPE_INT_RGB);
74 Graphics2D __graphic = __image.createGraphics();
75 __graphic.setColor($bgColor);
76 __graphic.fillRect(0,0,$w,$h);
77 __graphic.drawRenderedImage($image, null);
78 __graphic.dispose();
79 return __image;
80 }
81
82 /**
83 * 将32位色彩转换成24位色彩(丢弃Alpha通道)
84 * @param $argb
85 * @return
86 */
87 public static int[] getRGBs(int[] $argb)
88 {
89 int[] __rgbs = new int[$argb.length];
90 for(int i=0;i<$argb.length;i++)
91 {
92 __rgbs[i] = $argb[i] & 0xFFFFFF;
93 }
94 return __rgbs;
95 }
96}
- 文章ID:1462
- 原文作者:zrong
- 原文链接:https://blog.zengrong.net/post/convert_transparent_image_to_jpg_in_java/
- 版权声明:本作品采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可,非商业转载请注明出处(原文作者,原文链接),商业转载请联系作者获得授权。