不依赖三方库从图像数据中获取宽高-gif、bmp、png、jepg

int extract_pic_info(const BYTE *pic, const uint32_t size, int &width, int &height)
{
    int ret = -1;
    width = 0;
    height = 0;
    size_t offset = 0;
    if (pic == NULL)
        return ret;
    if ((pic[0] == 'G') && (pic[1] == 'I') && (pic[2] == 'F') && (pic[3] == '8') && (pic[4] == '9' || '7') && (pic[5] == 'a'))
    {
        //gif
        offset = 6;
        width = MAKEUS(pic[offset + 1], pic[offset]);
        offset += 2;
        height = MAKEUS(pic[offset + 1], pic[offset]);
        ret = 0;
        SS_DEBUG((LM_DEBUG, "extract_pic_info: gif width(%d) height(%d)!
", width, height));
    } else if ((pic[0] == 'B') && (pic[1] == 'M'))
    {
        //BMP
        offset = 18;
        width = MAKEUI(pic[offset + 3], pic[offset + 2], pic[offset + 1], pic[offset + 0]);
        offset += 4;
        height = MAKEUS(pic[offset + 1], pic[offset]);
        ret = 0;
        SS_DEBUG((LM_DEBUG, "extract_pic_info: BMP width(%d) height(%d)!
", width, height));
    } else if (pic[0] == png_signature[0] && pic[1] == png_signature[1] && pic[2] == png_signature[2] 
            && pic[3] == png_signature [3] && pic[4] == png_signature[4] 
            && pic[5] == png_signature[5] && pic[6] == png_signature[6] && pic[7] == png_signature[7])
    {
        //PNG
        offset = 16;
        width = MAKEUI(pic[offset + 0], pic[offset + 1], pic[offset + 2], pic[offset + 3]);
        offset += 4;
        height = MAKEUI(pic[offset + 0], pic[offset + 1], pic[offset + 2], pic[offset + 3]);
        ret = 0;
        SS_DEBUG((LM_DEBUG, "extract_pic_info: PNG width(%d) height(%d)!
", width, height));
    } else if (pic[0] == 255 && pic[1] == 216 && pic[size-2] == 255 && pic[size-1] == 217)
    {
        //JPEG
        bool finish = false;
        offset = 0;
        unsigned char id = 0;
        while(!finish && offset < size)
        {
            if (pic[offset++] != 0xff || offset >= size)
            {
                ret = -2;
                SS_DEBUG((LM_DEBUG, "extract_pic_info: JPEG format error!
"));
                break;
            }
            id = pic[offset++];
            if (id >= M_APP0 && id <= M_APPF) // app data block
            {
                offset += MAKEUS(pic[offset], pic[offset + 1]);
                continue;
            }
            switch(id)
            {
                case M_SOI:
                    break;
                case M_COM:
                case M_DQT:
                case M_DHT:
                case M_DNL:
                case M_DRI:
                    offset += MAKEUS(pic[offset], pic[offset + 1]);
                    break;
                case M_SOF0:
                    offset += 3;
                    height = MAKEUS(pic[offset], pic[offset + 1]);
                    offset += 2;
                    width = MAKEUS(pic[offset], pic[offset + 1]);
                    finish = true;
                    ret = 0;
                    SS_DEBUG((LM_DEBUG, "extract_pic_info: JPEG width(%d) height(%d)!
", width, height));
                    break;
                case M_SOS:
                case M_EOI:
                case M_DATA:
                    finish = true;
                    ret = -1;
                    SS_DEBUG((LM_DEBUG, "extract_pic_info: JPEG can't find SOF0!
"));
                    break;
                default:
                    offset += MAKEUS(pic[offset], pic[offset + 1]);
                    break;
            }
        }
    }
    return ret;
}

JPEG的每个标记都是由2个字节组成,其前一个字节是固定值0xFF。每个标记之前还可以添加数目不限的0xFF填充字节(fill byte)。下面是其中的8个标记:

1.   SOI 0xD 图像开始

2.   APP0 0xE0 JFIF应用数据块

3.   APPn 0xE1 - 0xEF 其他的应用数据块(n, 1~15)

4.   DQT 0xDB 量化表

5.   SOF0 0xC0 帧开始

6.   DHT 0xC4 霍夫曼(Huffman)表

7.   SOS 0xDA 扫描线开始

8.   EOI 0xD9 图像结束

 

原文地址:https://www.cnblogs.com/zl1991/p/10138319.html