0%

Java原生Image和Google开源框架Thumbnails处理图片

业务功能包括了重新调整大小,bmp转png或gif,300kb转gif可以实现10kb以下,但是在飞腾CPU+麒麟操作系统中出现了图片模糊的问题,而在龙芯CPU+麒麟上就是正常的,由于过于玄学,花了一天的时间后决定换一个压缩图片的方法。

=====================原生处理方式===============

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
public class test {
public static String getPreviewPngBase64(String base64Code, int width, int height) {

BufferedImage srcImage;
byte[] data = null;
try {
byte[] buffer = Base64.decodeBase64(base64Code);
ByteArrayInputStream in = new ByteArrayInputStream(buffer);
srcImage = ImageIO.read(in);
data = resize(srcImage, width, height);
} catch (IOException e) {
e.printStackTrace();
}
return GetBaseByByte(data);
}
private static byte[] resize(BufferedImage source, int targetW,int targetH) {
byte[] datas=null;
try {
IndexColorModel cm = createIndexColorModel();
BufferedImage target = null;
ImageIcon imageIcon = new ImageIcon(source);
double sx = (double) targetW / source.getWidth();
double sy = (double) targetH / source.getHeight();
if (sx > sy) {
sx = sy;
targetW = (int) (sx * source.getWidth());
} else {
sy = sx;
targetH = (int) (sy * source.getHeight());
}

target= new BufferedImage(
targetW, targetH,
BufferedImage.TYPE_BYTE_INDEXED,cm);
Graphics2D g = target.createGraphics();
g.drawImage(imageIcon.getImage(), 0, 0, targetW,targetH,
imageIcon.getImageObserver());
//将白色像素0xFFFFFFFF或者rgb在color_range内改为0x00FFFFFF透明像素
for (int j1 = target.getMinY(); j1 < target.getHeight(); j1++) {
for (int j2 = target.getMinX(); j2 < target
.getWidth(); j2++) {
int rgb = target.getRGB(j2, j1);
if((rgb==Color.white.getRGB())||colorInRange(rgb)) {
rgb=0x00FFFFFF;
}
target.setRGB(j2, j1, rgb);
}
}
g.drawImage(target, 0, 0, imageIcon.getImageObserver());
ByteArrayOutputStream out=new ByteArrayOutputStream();
ImageIO.write(target, "gif", out);
datas=out.toByteArray();
out.close();
g.dispose();
} catch (Exception e) {
e.printStackTrace();
}

return datas;
}

private static int color_range = 220;
private static boolean colorInRange(int color) {
int red = (color & 0xff0000) >> 16;
int green = (color & 0x00ff00) >> 8;
int blue = (color & 0x0000ff);
return red >= color_range && green >= color_range && blue >= color_range;
}
}

=============Thumbnails=================

用了Thumbnails后颜色正常了,但是又遇到天坑,转出来的图片到本司的软件中底色是透明的,而在web浏览器上并不是,苦思冥想半天也没想通是为什么,第二天突然顿悟可能是本司软件又对图片做了一次转透明的处理。那应该是转出来的图片确实不是透明的,跟原生压缩做一次对比发现确实是这样,原来是需要在builder中设置imageType,没设置时是按照RGB来输出的,少了alpha量,所以遍历RGB转为0x00FFFFFF的操作输出是就被输出为了0xFFFFFF,从而导致底色没有转成透明。

1
Thumbnails.of(in2).imageType(BufferedImage.TYPE_INT_ARGB).size(targetW, targetH).asBufferedImage();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public static String getPreviewGifBase64(String base64Code, int targetW, int targetH) {
BufferedImage srcImage;
byte[] datas = null;
try {
byte[] buffer = Base64.decodeBase64(base64Code);
ByteArrayInputStream in = new ByteArrayInputStream(buffer);
//不能重复读
ByteArrayInputStream in2 = new ByteArrayInputStream(buffer);
srcImage = ImageIO.read(in);
double sx = (double) targetW / srcImage.getWidth();
double sy = (double) targetH / srcImage.getHeight();
if (sx > sy) {
sx = sy;
targetW = (int) (sx * srcImage.getWidth());
} else {
sy = sx;
targetH = (int) (sy * srcImage.getHeight());
}
//输出携带alpha量的ARGB格式
BufferedImage image = Thumbnails.of(in2).imageType(BufferedImage.TYPE_INT_ARGB).size(targetW, targetH).asBufferedImage();
//设置透明
setColor(image);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ImageIO.write(image, "gif", out);
datas=out.toByteArray();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
return GetBaseByByte(datas);
};