zoukankan      html  css  js  c++  java
  • 更高效率,Java快速获取图片尺寸宽高分辨率(支持webp)

    Java提供ImageIO.read方法获取包含图片大小、尺寸宽高等数据的BufferedImage对象,但它需要把图片完全加载到内存中,对于某些只想要图片宽高信息的场景来说,这样会更占内存,效率较低。下面提供另外一种性能更好的方式,根据图片字节数组获取图片宽高。

    
    import java.io.*;
    
    /**
     * 快速获取图片的大小
     */
    public class FastImageInfo {
        private int height;
        private int width;
        private String mimeType;
    
        public FastImageInfo(File file) throws IOException {
            try (InputStream is = new FileInputStream(file)) {
                processStream(is);
            }
        }
    
        public FastImageInfo(InputStream is) throws IOException {
            processStream(is);
        }
    
        public FastImageInfo(byte[] bytes) throws IOException {
            try (InputStream is = new ByteArrayInputStream(bytes)) {
                processStream(is);
            }
        }
    
        private void processStream(InputStream is) throws IOException {
            int c1 = is.read();
            int c2 = is.read();
            int c3 = is.read();
    
            mimeType = null;
            width = height = -1;
    
            if (c1 == 'G' && c2 == 'I' && c3 == 'F') { // GIF
                is.skip(3);
                width = readInt(is, 2, false);
                height = readInt(is, 2, false);
                mimeType = "image/gif";
            } else if (c1 == 0xFF && c2 == 0xD8) { // JPG
                while (c3 == 255) {
                    int marker = is.read();
                    int len = readInt(is, 2, true);
                    if (marker == 192 || marker == 193 || marker == 194) {
                        is.skip(1);
                        height = readInt(is, 2, true);
                        width = readInt(is, 2, true);
                        mimeType = "image/jpeg";
                        break;
                    }
                    is.skip(len - 2);
                    c3 = is.read();
                }
            } else if (c1 == 137 && c2 == 80 && c3 == 78) { // PNG
                is.skip(15);
                width = readInt(is, 2, true);
                is.skip(2);
                height = readInt(is, 2, true);
                mimeType = "image/png";
            } else if (c1 == 66 && c2 == 77) { // BMP
                is.skip(15);
                width = readInt(is, 2, false);
                is.skip(2);
                height = readInt(is, 2, false);
                mimeType = "image/bmp";
            } else if (c1 == 'R' && c2 == 'I' && c3 == 'F') { // WEBP
                byte[] bytes = is.readNBytes(27);
                width = ((int) bytes[24] & 0xff) << 8 | ((int) bytes[23] & 0xff);
                height = ((int) bytes[26] & 0xff) << 8 | ((int) bytes[25] & 0xff);
                mimeType = "image/webp";
            } else {
                int c4 = is.read();
                if ((c1 == 'M' && c2 == 'M' && c3 == 0 && c4 == 42)
                        || (c1 == 'I' && c2 == 'I' && c3 == 42 && c4 == 0)) { //TIFF
                    boolean bigEndian = c1 == 'M';
                    int ifd = 0;
                    int entries;
                    ifd = readInt(is, 4, bigEndian);
                    is.skip(ifd - 8);
                    entries = readInt(is, 2, bigEndian);
                    for (int i = 1; i <= entries; i++) {
                        int tag = readInt(is, 2, bigEndian);
                        int fieldType = readInt(is, 2, bigEndian);
                        int valOffset;
                        if ((fieldType == 3 || fieldType == 8)) {
                            valOffset = readInt(is, 2, bigEndian);
                            is.skip(2);
                        } else {
                            valOffset = readInt(is, 4, bigEndian);
                        }
                        if (tag == 256) {
                            width = valOffset;
                        } else if (tag == 257) {
                            height = valOffset;
                        }
                        if (width != -1 && height != -1) {
                            mimeType = "image/tiff";
                            break;
                        }
                    }
                }
            }
            if (mimeType == null) {
                throw new IOException("Unsupported image type");
            }
        }
    
        private int readInt(InputStream is, int noOfBytes, boolean bigEndian) throws IOException {
            int ret = 0;
            int sv = bigEndian ? ((noOfBytes - 1) * 8) : 0;
            int cnt = bigEndian ? -8 : 8;
            for (int i = 0; i < noOfBytes; i++) {
                ret |= is.read() << sv;
                sv += cnt;
            }
            return ret;
        }
    
        public int getHeight() {
            return height;
        }
    
        public void setHeight(int height) {
            this.height = height;
        }
    
        public int getWidth() {
            return width;
        }
    
        public void setWidth(int width) {
            this.width = width;
        }
    
        public String getMimeType() {
            return mimeType;
        }
    
        public void setMimeType(String mimeType) {
            this.mimeType = mimeType;
        }
    
        @Override
        public String toString() {
            return "MIME Type : " + mimeType + "	 Width : " + width
                    + "	 Height : " + height;
        }
    }
    

    使用示例

    FastImageInfo imageInfo = new FastImageInfo(file or byte or inputStream);
    int width = imageInfo.getWidth();
    int height = imageInfo.getHeight();
    
  • 相关阅读:
    黄聪:dreamweaver jquery代码提示安装,DW JQ代码智能提示
    明明白白AOP(你没有理由不心领神会!)
    myeclipse安装svn插件的多种方式
    spring注解
    freemarker入门例子
    MyEclipse10 中的两种FreeMarker插件的安装与配置
    优秀程序员必备的10个技能
    p2psearcher无法连接到KAD网络或ed2k服务器的解决办法
    MyEclipse 8.6.1下载|MyEclipse 8下载|MyEclipse 8.6.1官网下载
    网络技术网站
  • 原文地址:https://www.cnblogs.com/xiaona/p/13869504.html
Copyright © 2011-2022 走看看