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();
    
  • 相关阅读:
    volley框架使用
    Insert Interval
    candy(贪心)
    Best Time to Buy and Sell Stock
    Best Time to Buy and Sell Stock III
    distinct subsequences
    edit distance(编辑距离,两个字符串之间相似性的问题)
    trapping rain water
    word break II(单词切分)
    sudoku solver(数独)
  • 原文地址:https://www.cnblogs.com/xiaona/p/13869504.html
Copyright © 2011-2022 走看看