利用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
", 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(); } }


原文地址:https://www.cnblogs.com/thewindkee/p/12873261.html