二进制图片文件的格式识别

背景:

最近的项目需要一个功能:提供一个接口将图片上传至mongoDB,并返回一个url.图片是以文件形式传到接口,然后将其转化为二进制数组上传到mongoDB,在这里呢,我需要判断图片的格式,根据格式返回不同的url.

现在我的问题是JPEG这个格式识别不出来,虽然我看网上JPG和JPEG是同一个格式,但是经过实践,这两还是有区别的.

所以我去看了识别工具的源码,主要就是这么一段,mag的前几位跟contents(字节数组)前几位对比.

    public static String getFileFormat(byte[] contents) {
        for (int i = 0; i < FILE_MAGS.length; i++) {
            byte[] mag = FILE_MAGS[i];
            if (contents.length >= mag.length) {
                if (Arrays.equals(Arrays.copyOf(contents, mag.length), mag)) {
                    return FILE_EXTS[i];
                }
            }
        }
        return null;
    }

mag取自FILE_MAGS数组,来看下FILE_MAGS内容

    private static final byte[][] FILE_MAGS = new byte[][] {
            new byte[] {(byte)0xFF, (byte)0xD8, (byte)0xFF, (byte)0xE0}, //JPG
            new byte[] {(byte)0x89, (byte)0x50, (byte)0x4E, (byte)0x47}, //PNG
            new byte[] {(byte)0x47, (byte)0x49, (byte)0x46, (byte)0x38}  //GIF
    };

很直观啦,现在我就要取找JPEG图片转成字节数组后前四个字节是什么.

        byte[] fileContent = FileUtils.readFileToByteArray(new File("/home/jiahui/Desktop/sdf.jpg"));
        for(int i =0 ;i<4;i++){
            System.out.println(String.format("0x%2x",fileContent[i]));
        }
        System.out.println();
        fileContent = FileUtils.readFileToByteArray(new File("/home/jiahui/Desktop/O1CN01TzIMM824HfuuzCcRX_!!3776527366.jpeg"));
        for(int i =0 ;i<4;i++){
            System.out.println(String.format("0x%2x",fileContent[i]));
        }

运行之后结果如下,得到了JPEG格式前4位,加到FILE_MAGES数组中,成功识别是JPEG格式


完整工具类

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.ArrayUtils;

import java.io.*;
import java.util.Arrays;

public class FormatJudge {

    /**
     * File extensions.
     */
    private static final String[] FILE_EXTS = {"JPG", "JPEG","PNG", "GIF"};
    /**
     * Magic bytes in a file with above extension.
     */
    private static final byte[][] FILE_MAGS = new byte[][] {
            new byte[] {(byte)0xFF, (byte)0xD8, (byte)0xFF, (byte)0xE0}, //JPG
            new byte[] {(byte)0xFF, (byte)0xD8, (byte)0xFF, (byte)0xDB}, //JPEG
            new byte[] {(byte)0x89, (byte)0x50, (byte)0x4E, (byte)0x47}, //PNG
            new byte[] {(byte)0x47, (byte)0x49, (byte)0x46, (byte)0x38}  //GIF
    };
    /**
     * Get file format from file name.
     * @param fileName file name
     * @return file format, null if unsupported.
     */
    public static String getFileFormat(String fileName) {
        int dp = fileName.lastIndexOf(".");
        if (dp == -1) return null;
        String ext = fileName.substring(dp + 1).toUpperCase();
        if (ext.equals("JPEG")) ext = "JPG"; //JPEG is JPG
        if (ArrayUtils.indexOf(FILE_EXTS, ext) == -1) return null;
        return ext;
    }
    /**
     * Get file format by contents.
     * @param contents file contents
     * @return file format, null if unsupported.
     */
    public static String getFileFormat(byte[] contents) {
        for (int i = 0; i < FILE_MAGS.length; i++) {
            byte[] mag = FILE_MAGS[i];
            if (contents.length >= mag.length) {
                if (Arrays.equals(Arrays.copyOf(contents, mag.length), mag)) {
                    return FILE_EXTS[i];
                }
            }
        }
        return null;
    }
}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容