利用ImageIO压缩图片
参考上面文章,测试了下 很好用!
500kb左右的图片,压缩4次,1秒内完毕。
import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Iterator;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.MemoryCacheImageInputStream;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
public class ImageTest {
/**
* @param args
* @throws AWTException
* @throws IOException
* @throws FileNotFoundException
*/
public void getImageSize() throws AWTException, FileNotFoundException, IOException {
java.awt.Robot rb = new java.awt.Robot();
Dimension d = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
Rectangle rt = new Rectangle(0, 0, (int) d.getWidth(), (int) d
.getHeight());
BufferedImage image= readMemoryImage(readBytes(new FileInputStream("C:/Users/Administrator/Desktop/2.jpg")));
System.out.println(image.getHeight());
byte[] picByte = bufferedImageTobytes(image, "gif");
byte[] picByte2 = bufferedImageTobytes(image, "jpeg");
byte[] picByte3 = bufferedImageTobytes(image, 0.9f);
byte[] picByte4 = newCompressImage(image, 0.4f);
FileOutputStream f=new FileOutputStream("C:/Users/Administrator/Desktop/2-1.gif");
FileOutputStream f2=new FileOutputStream("C:/Users/Administrator/Desktop/2-2.jpg");
FileOutputStream f3=new FileOutputStream("C:/Users/Administrator/Desktop/2-3.jpg");
FileOutputStream f4=new FileOutputStream("C:/Users/Administrator/Desktop/2-4.jpg");
f.write(picByte);
f2.write(picByte2);
f3.write(picByte3);
f4.write(picByte4);
f.close();
f2.close();
f3.close();
f4.close();
}
/**
* 从内存字节数组中读取图像
*
* @param imgBytes
* 未解码的图像数据
* @return 返回 {@link BufferedImage}
* @throws IOException
* 当读写错误或不识别的格式时抛出
*/
public static final BufferedImage readMemoryImage(byte[] imgBytes) throws IOException {
if (null == imgBytes || 0 == imgBytes.length)
throw new NullPointerException("the argument 'imgBytes' must not be null or empty");
// 将字节数组转为InputStream,再转为MemoryCacheImageInputStream
ImageInputStream imageInputstream = new MemoryCacheImageInputStream(new ByteArrayInputStream(imgBytes));
// 获取所有能识别数据流格式的ImageReader对象
Iterator it = ImageIO.getImageReaders(imageInputstream);
// 迭代器遍历尝试用ImageReader对象进行解码
while (it.hasNext()) {
ImageReader imageReader = it.next();
// 设置解码器的输入流
imageReader.setInput(imageInputstream, true, true);
// 图像文件格式后缀
String suffix = imageReader.getFormatName().trim().toLowerCase();
// 图像宽度
int width = imageReader.getWidth(0);
// 图像高度
int height = imageReader.getHeight(0);
System.out.printf("format %s,%dx%d\n", suffix, width, height);
try {
// 解码成功返回BufferedImage对象
// 0即为对第0张图像解码(gif格式会有多张图像),前面获取宽度高度的方法中的参数0也是同样的意思
return imageReader.read(0, imageReader.getDefaultReadParam());
} catch (Exception e) {
imageReader.dispose();
// 如果解码失败尝试用下一个ImageReader解码
}
}
imageInputstream.close();
// 没有能识别此数据的图像ImageReader对象,抛出异常
throw new IOException("unsupported image format");
}
/**
* 从{@link InputStream}读取字节数组
* 结束时会关闭{@link InputStream}
* {@code in}为{@code null}时抛出{@link NullPointerException}
*
* @param in
* @return 字节数组
* @throws IOException
*/
public static final byte[] readBytes(InputStream in) throws IOException {
if (null == in)
throw new NullPointerException("the argument 'in' must not be null");
try {
int buffSize = Math.max(in.available(), 1024 * 8);
byte[] temp = new byte[buffSize];
ByteArrayOutputStream out = new ByteArrayOutputStream(buffSize);
int size = 0;
while ((size = in.read(temp)) != -1) {
out.write(temp, 0, size);
}
return out.toByteArray();
} finally {
in.close();
}
}
/**
* 用Format对应格式中ImageIO默认参数把IMAGE打包成BYTE[]
* @param image
* @return
*/
private byte[] bufferedImageTobytes(BufferedImage image, String format) {
System.out.println(format + "格式开始打包" + getCurrentTime());
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
ImageIO.write(image, format, out);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(format + "格式完成打包-----" + getCurrentTime()
+ "----lenth------" + out.toByteArray().length);
return out.toByteArray();
}
/**
*
* 自己设置压缩质量来把图片压缩成byte[]
*
* @param image
* 压缩源图片
* @param quality
* 压缩质量,在0-1之间,
* @return 返回的字节数组
*/
private byte[] bufferedImageTobytes(BufferedImage image, float quality) {
System.out.println("jpeg" + quality + "质量开始打包" + getCurrentTime());
// 如果图片空,返回空
if (image == null) {
return null;
}
// 得到指定Format图片的writer
Iterator iter = ImageIO
.getImageWritersByFormatName("jpeg");// 得到迭代器
ImageWriter writer = (ImageWriter) iter.next(); // 得到writer
// 得到指定writer的输出参数设置(ImageWriteParam )
ImageWriteParam iwp = writer.getDefaultWriteParam();
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); // 设置可否压缩
iwp.setCompressionQuality(quality); // 设置压缩质量参数
iwp.setProgressiveMode(ImageWriteParam.MODE_DISABLED);
ColorModel colorModel = ColorModel.getRGBdefault();
// 指定压缩时使用的色彩模式
iwp.setDestinationType(new javax.imageio.ImageTypeSpecifier(colorModel,
colorModel.createCompatibleSampleModel(16, 16)));
// 开始打包图片,写入byte[]
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); // 取得内存输出流
IIOImage iIamge = new IIOImage(image, null, null);
try {
// 此处因为ImageWriter中用来接收write信息的output要求必须是ImageOutput
// 通过ImageIo中的静态方法,得到byteArrayOutputStream的ImageOutput
writer.setOutput(ImageIO
.createImageOutputStream(byteArrayOutputStream));
writer.write(null, iIamge, iwp);
} catch (IOException e) {
System.out.println("write errro");
e.printStackTrace();
}
System.out.println("jpeg" + quality + "质量完成打包-----" + getCurrentTime()
+ "----lenth----" + byteArrayOutputStream.toByteArray().length);
return byteArrayOutputStream.toByteArray();
}
/**
* 自己定义格式,得到当前系统时间
*
* @return
*/
private String getCurrentTime() {
Calendar c = new GregorianCalendar();
int hour = c.get(Calendar.HOUR_OF_DAY);
int min = c.get(Calendar.MINUTE);
int second = c.get(Calendar.SECOND);
int millsecond = c.get(Calendar.MILLISECOND);
String time = hour + "点" + min + "分" + second + "秒" + millsecond;
return time;
}
/**
* 通过 com.sun.image.codec.jpeg.JPEGCodec提供的编码器来实现图像压缩
* @param image
* @param quality
* @return
*/
private byte[] newCompressImage(BufferedImage image, float quality) {
// 如果图片空,返回空
if (image == null) {
return null;
}
// 开始开始,写入byte[]
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); // 取得内存输出流
// 设置压缩参数
JPEGEncodeParam param = JPEGCodec.getDefaultJPEGEncodeParam(image);
param.setQuality(quality, false);
// 设置编码器
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(
byteArrayOutputStream, param);
System.out.println("newCompressive" + quality + "质量开始打包"
+ getCurrentTime());
try {
encoder.encode(image);
} catch (Exception ef){
ef.printStackTrace();
}
System.out.println("newCompressive" + quality + "质量打包完成"
+ getCurrentTime() + "----lenth----"
+ byteArrayOutputStream.toByteArray().length);
return byteArrayOutputStream.toByteArray();
}
public static void main(String args[]) throws Exception {
ImageTest test = new ImageTest();
test.getImageSize();
}
}