Java图片压缩转码

该博客展示了如何使用Java处理图像,包括从字节数组读取图像、压缩图像以及转码。主要利用了Java的ImageIO和com.sun.image.codec.jpeg库,实现了不同质量的JPEG压缩,并提供了详细的时间戳记录压缩过程。
摘要由CSDN通过智能技术生成

图片压缩功能以及转码,只列举了压缩,转码方法在内

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.*;
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 {

    public static void main(String args[]) throws Exception {
        ImageTest test = new ImageTest();
        test.test();
    }

    /**
     * @param
     * @throws AWTException
     * @throws IOException
     * @throws FileNotFoundException
     */
    public void test() throws AWTException, FileNotFoundException, IOException {
        File file = new File("C:/Users/Administrator/Desktop/logo.jpg");
        System.out.println("源文件大小: " + file.length());
        Long a = (1024 * 200) / file.length();
        BufferedImage image = readMemoryImage(readBytes(new FileInputStream("C:/Users/Administrator/Desktop/logo.jpg")));
        System.out.println(image.getHeight());
        byte[] picByte = newCompressImage(image, a.floatValue());
        FileOutputStream f = new FileOutputStream("C:/Users/Administrator/Desktop/2-4.jpg");
        f.write(picByte);

        f.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 = (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}读取字节数组
     * <p>
     * <p>
     * 结束时会关闭{@link InputStream}
     * <p>
     * <p>
     * {@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();

    }

}
 
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值