从图像文件中获取图像分辨率

时间:2012-04-11 18:27:14

标签: visual-c++ image-processing

我正在尝试使用此代码从文件中获取图像分辨率

bool GetImageSizeEx(const char *fn, int *x,int *y)
{ 
    FILE *f=fopen(fn,"rb"); 

    if (f==0) return false;

    fseek(f,0,SEEK_END); 
    long len=ftell(f); 
    fseek(f,0,SEEK_SET); 

    if (len<24) {
        fclose(f); 
        return false;
    }

  // Strategy:
  // reading GIF dimensions requires the first 10 bytes of the file
  // reading PNG dimensions requires the first 24 bytes of the file
  // reading JPEG dimensions requires scanning through jpeg chunks
  // In all formats, the file is at least 24 bytes big, so we'll read that always
    unsigned char buf[24]; fread(buf,1,24,f);


  // 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 && buf[3]==0xE0 && buf[6]=='J' && buf[7]=='F' && buf[8]=='I' && buf[9]=='F')
    {
        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];
            if (pos+12>len) break;
            fseek(f,pos,SEEK_SET); 
            fread(buf+2,1,12,f);   
        }
    }


    fclose(f);

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

        return true;
    }

  // GIF: first three bytes say "GIF", next three give version number. Then dimensions
    if (buf[0]=='G' && buf[1]=='I' && buf[2]=='F')
    { 
        *x = buf[6] + (buf[7]<<8);
        *y = buf[8] + (buf[9]<<8);
        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')
    {
        *x = (buf[16]<<24) + (buf[17]<<16) + (buf[18]<<8) + (buf[19]<<0);
        *y = (buf[20]<<24) + (buf[21]<<16) + (buf[22]<<8) + (buf[23]<<0);

        return true;
    }

    return false;
}
对于所有类型和任何分辨率的图像,

始终返回x == 26112和y == 30825

我在Win7 x64上使用VS 2010 SP1编译

更新

我正在尝试打开由Photshop创建的jpg文件。 Photshop编码JPEG文件 使用Exif元数据

调试器显示(右键单击为fullsize)

enter image description here

现在看代码:

if ((buf[0]==0xFF && buf[1]==0xD8 && buf[2]==0xFF && buf[3]==0xE0 && buf[6]=='J' && buf[7]=='F' && buf[8]=='I' && buf[9]=='F') ||
        (buf[0]==0xFF && buf[1]==0xD8 && buf[2]==0xFF && buf[3]==0xE1 && buf[6]=='E' && buf[7]=='x' && buf[8]=='i' && buf[9]=='f'))
    {
        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];
            if (pos+12>len) break;
            fseek(f,pos,SEEK_SET); 
            fread(buf+2,1,12,f);   
        }
    }

1 个答案:

答案 0 :(得分:2)

我为所有三种格式运行了代码,并且它可以完美地运行以获得各种分辨率!我唯一建议的就是适当地调用你的GetImageSizeEx(逃避反斜杠)

这样的东西
int x,y;

GetImageSizeEx("C:\\Users\\IBM_ADMIN\\Desktop\\pavan2.png", &x, &y);
printf("%d %d", x, y );

您可能会注意到失败的一些可能情况fopen本身由于文件名错误而失败,xy永远不会在GetImageSizeEx内修改}。或者另一种情况,即您读错了文件并且无法阅读相应的标题,因此xy根本不会被修改!也许你从未在你的调用函数中初始化xy,因此会显示一些垃圾?

PS :我在Windows 7上用gcc 4.6.1 mingw编译了它