반응형


iTrans를 업데이트하면서 이미지의 해상도를 읽어야 할 상황이 생겼다.

IJGlibpng를 사용하면 되긴 하지만, 고작 해상도 정보 얻자고 라이브러리까지 쓰긴 좀 그래서 간단한 방법을 쓰기로 했다.


간단히(응?) 파일을 뒤져서 해상도 정보를 찾는 것.


cplusplus.com에서 관련된 소스를 찾을 수 있었다.

그런데, 이 코드에는 사소한 문제들이 있다.


- GIF도 포함된 소스인데, 난 GIF는 안 쓰기 때문에 제거 가능

- 파일 크기를 얻기 위해 fseek() 등을 쓰는데, 필요 없음

- JPEG 헤더를 읽을 때 EXIF가 앞에 들어있는 경우는 제대로 처리하지 못함

- 파일의 형식은 알려주지 않음


아래 코드는 이 내용이 반영된 코드이다.


// itype: 1=JPEG 2=PNG
bool getImageTypeNSize(LPCTSTR lpFile, int &iType, int &iWidth, int &iHeight)
{
    // 참고 사이트: http://www.cplusplus.com/forum/beginner/45217/

    iType = iWidth = iHeight = 0;

    FILE *f;
    if (_tfopen_s(&f, lpFile, _T("rb")) || !f) {
        return false;
    }

    BYTE buf[24];
    if (fread_s(buf, 24, 1, 24, f) != 24) {
        fclose(f);
        return false;
    }

    // For JPEGs, we need to read the first 12 bytes of each chunk.
    // We'll read those 12 bytes at buf+2...buf+14, i.e. overwriting the existing buf.
    if (buf[0] == 0xFF && buf[1] == 0xD8 && buf[2] == 0xFF)
    {
        iType = 1;

        long pos = 2;
        while (buf[2] == 0xFF)
        {
            if (buf[3] == 0xC0 || buf[3] == 0xC1 || buf[3] == 0xC2 || buf[3] == 0xC3 || buf[3] == 0xC9 || buf[3] == 0xCA || buf[3] == 0xCB) break;
            pos += 2 + (buf[4] << 8) + buf[5];
            fseek(f, pos, SEEK_SET);
            if (fread_s(buf + 2, 22, 1, 12, f) != 12) break;
        }
    }

    fclose(f);

    // JPEG: (first two bytes of buf are first two bytes of the jpeg file; rest of buf is the DCT frame
    if (iType ==1 && buf[0] == 0xFF && buf[1] == 0xD8 && buf[2] == 0xFF)
    {
        iHeight = (buf[7] << 8) + buf[8];
        iWidth = (buf[9] << 8) + buf[10];

        return true;
    }

    // PNG: the first frame is by definition an IHDR frame, which gives dimensions
    if (buf[0] == 0x89 && buf[1] == 'P' && buf[2] == 'N' && buf[3] == 'G' && buf[4] == 0x0D && buf[5] == 0x0A && buf[6] == 0x1A && buf[7] == 0x0A
        && buf[12] == 'I' && buf[13] == 'H' && buf[14] == 'D' && buf[15] == 'R')
    {
        iWidth = (buf[16] << 24) + (buf[17] << 16) + (buf[18] << 8) + (buf[19] << 0);
        iHeight = (buf[20] << 24) + (buf[21] << 16) + (buf[22] << 8) + (buf[23] << 0);

        iType = 2;
        return true;
    }

    return false;
}



반응형

공유하기

facebook twitter kakaoTalk kakaostory naver band