纯java实现检测exif/jiff规范jpeg(jpg)orientation旋转方向

这段代码主要解析JPEG文件中的Exif信息,寻找TIFF头和Exif头,确定Motorola或Intel字节序,并查找方向标签(Orientation Tag),返回其值。通过对JPEG文件字节的遍历,找到APP1段,然后检查是否包含Exif或TIFF头,进一步获取IFD0的结束索引,最后读取方向标签的值。
摘要由CSDN通过智能技术生成
    private final static byte[] app1 = new byte[] { (byte) 0xFF, (byte) 0xE1 };
    private final static byte[] exifHeader = new byte[] { (byte) 0x45, (byte) 0x78, (byte) 0x69, (byte) 0x66, (byte) 0x00, (byte) 0x00 };
    private final static byte[] tiffHeader = new byte[] { (byte) 0x49, (byte) 0x49, (byte) 0x2A, (byte) 0x00, (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0x00 };
    private final static byte[] orientationTag = new byte[] { (byte) 0x01, (byte) 0x12 };
    private final static byte[] orientationTagDataType = new byte[] { (byte) 0x00, (byte) 0x03 };
    private final static byte[] orientationTagLength = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01 };
    private final static byte[] motorolaAlignType = new byte[] { (byte) 0x4D, (byte) 0x4D };
    public static int detectExif(byte[] jpgFileBytes) {
        boolean findExifOrTIFF = false;
        int alignTypeI = 0;// 字节码的表示方式,Motorola 1为从高到低,intel 2从低到高
        int orientationTagValue = -1;
        int i = 0;
        int searchEndIndex = 0;//搜索结束的字节索引(取自IFD0的entry截止位置)
        for (; i < jpgFileBytes.length; i++) {
            if (!findExifOrTIFF && jpgFileBytes[i] == app1[0] && jpgFileBytes[i + 1] == app1[1]) {
                int headerOffset = i + 4;
                byte[] header = Arrays.copyOfRange(jpgFileBytes, headerOffset, headerOffset + 6);//exif header
                byte[] alignType;
                int TIFF_Start = 0;
                if (Arrays.equals(header, exifHeader)) {
                    TIFF_Start = headerOffset + 6;
                    alignType = Arrays.copyOfRange(jpgFileBytes, TIFF_Start, TIFF_Start + 2);
                    alignTypeI = Arrays.equals(alignType, motorolaAlignType) ? 1 : 2;
                    logger.info("Exif Header,format:" + alignTypeI);
                    
                    searchEndIndex = getIFD0EndIndex(jpgFileBytes, TIFF_Start, alignTypeI);
                    
                    findExifOrTIFF = true;
                    continue;
                } else {
                    header = Arrays.copyOfRange(jpgFileBytes, headerOffset, headerOffset + 8);//tiff header
                    if (Arrays.equals(header, tiffHeader)) {
                        TIFF_Start = headerOffset + 8;
                        alignType = Arrays.copyOfRange(jpgFileBytes, TIFF_Start, TIFF_Start + 2);
                        alignTypeI = Arrays.equals(alignType, motorolaAlignType) ? 1 : 2;
                        logger.info("TIFF Header,format:" + alignTypeI);
                        
                        searchEndIndex = getIFD0EndIndex(jpgFileBytes, TIFF_Start, alignTypeI);
                        
                        findExifOrTIFF = true;
                        continue;
                    }
                }
                break;
            }
            if (findExifOrTIFF) {
                if (i >= searchEndIndex) {
                    break;
                } else if (jpgFileBytes[i] == orientationTag[0] && jpgFileBytes[i + 1] == orientationTag[1] && jpgFileBytes[i + 2] == orientationTagDataType[0] && jpgFileBytes[i + 3] == orientationTagDataType[1] && jpgFileBytes[i + 4] == orientationTagLength[0] && jpgFileBytes[i + 5] == orientationTagLength[1] && jpgFileBytes[i + 6] == orientationTagLength[2] && jpgFileBytes[i + 7] == orientationTagLength[3]) {
                    if (alignTypeI == 1) {
                        orientationTagValue = jpgFileBytes[i + 9];
                        break;
                    } else if (alignTypeI == 2) {
                        orientationTagValue = jpgFileBytes[i + 8];
                        break;
                    }
                }
            }
        }
        return orientationTagValue;
    }
    
    private static int getIFD0EndIndex(byte[] jpgFileBytes, int TIFF_Start, int alignTypeI) {
        byte[] IFD0_OFFSET_VALUE = Arrays.copyOfRange(jpgFileBytes, TIFF_Start + 4, TIFF_Start + 8);
        if(alignTypeI==2) {
            ArrayUtils.reverse(IFD0_OFFSET_VALUE);
        }
        int offSet = Integer.parseInt(byte2HexStr(IFD0_OFFSET_VALUE), 16);
        
        byte[] IFD0_ENTRY_NUM_ARR = Arrays.copyOfRange(jpgFileBytes,TIFF_Start+offSet,TIFF_Start+offSet+2);
        if(alignTypeI==2) {
            ArrayUtils.reverse(IFD0_ENTRY_NUM_ARR);
        }
        int IFD0_ENTRY_NUM = Integer.parseInt(byte2HexStr(IFD0_ENTRY_NUM_ARR), 16);//entry的数目
        int searchEndIndex = TIFF_Start+offSet+2 + IFD0_ENTRY_NUM * 12;//每个entry 12个字节
        return searchEndIndex;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值