2007/05/13

簡單取得JPEG長寬

目前用WxWidgets寫一個線上偵測抓圖的軟體,依規則尋網頁中的圖檔,下載,抓取長寬的設定,判斷是否繼續下載。


Googole CodeSearch搜尋了很久,都是使用LIB或是讀檔的方式比較麻煩,我只是要取得圖檔長寬而已啊.. 在努力搜尋之後,皇天不負苦心人還是讓我找到一篇,並修改成一個函式與大家分享,以下是我改寫的程式:





bool GetJpgWidthHeight(wxChar* buf,int size,int&Width,int& Height)
{
bool ret=false;
#define M_SOF0 0xC0 /* Start Of Frame N */
#define M_SOF1 0xC1 /* N indicates which compression process */
#define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */
#define M_SOF3 0xC3
#define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */
#define M_SOF6 0xC6
#define M_SOF7 0xC7
#define M_SOF9 0xC9
#define M_SOF10 0xCA
#define M_SOF11 0xCB
#define M_SOF13 0xCD
#define M_SOF14 0xCE
#define M_SOF15 0xCF
#define M_SOI 0xD8 /* Start Of Image (beginning of datastream) */
#define M_EOI 0xD9 /* End Of Image (end of datastream) */
#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */
#define M_APP0 0xE0 /* Application-specific marker, type N */
#define M_APP12 0xEC /* (we don't bother to list all 16 APPn's) */
#define M_COM 0xFE /* COMment */

int marker;
int Index=0;

int c1, c2;
c1 = (BYTE)buf[Index++];
c2 = (BYTE)buf[Index++];
if (c1 != 0xFF || c2 != M_SOI)
return false;
else
{
marker = c2;
}

unsigned int SkipLen=0;

for (;;)
{
marker=(BYTE)buf[Index++];

if(Index>=size)
return false;

while (marker != 0xFF)
{
marker=(BYTE)buf[Index++];
if(Index>=size)
return false;
}

do
{
marker=(BYTE)buf[Index++];
if(Index>=size)
return false;

} while (marker == 0xFF);

switch (marker)
{
case M_SOF0: /* Baseline */
case M_SOF1: /* Extended sequential, Huffman */
case M_SOF2: /* Progressive, Huffman */
case M_SOF3: /* Lossless, Huffman */
case M_SOF5: /* Differential sequential, Huffman */
case M_SOF6: /* Differential progressive, Huffman */
case M_SOF7: /* Differential lossless, Huffman */
case M_SOF9: /* Extended sequential, arithmetic */
case M_SOF10: /* Progressive, arithmetic */
case M_SOF11: /* Lossless, arithmetic */
case M_SOF13: /* Differential sequential, arithmetic */
case M_SOF14: /* Differential progressive, arithmetic */
case M_SOF15: /* Differential lossless, arithmetic */
Index+=3;

if(Index>=size)
return false;

c1=(BYTE)buf[Index++];
c2=(BYTE)buf[Index++];

Width=(int)(((unsigned int) c1) << 8) + ((unsigned int) c2);

c1=(BYTE)buf[Index++];
c2=(BYTE)buf[Index++];

Height=(int)(((unsigned int) c1) << 8) + ((unsigned int) c2);

return true;

break;
case M_SOS: /* stop before hitting compressed data */
return false;
break;
case M_EOI: /* in case it's a tables-only JPEG stream */
return false;
break;
default:
c1=(BYTE)buf[Index++];
c2=(BYTE)buf[Index++];

SkipLen=(((unsigned int) c1) << 8) + ((unsigned int) c2);

if (SkipLen < 2)
return false;

Index+=SkipLen-2;
if(Index>=size)
return false;

break;
}

}
return ret;
}

以上有些地方沒有偵測是否超過範圍,也不知道是不是通用所有的JPEG格式,所以使用以上程式發生問題本人概不負責 XD

另外傳入的buffer 要夠大 才會顯示真的長寬,有的圖檔的Width Height 位置非常的後面,並不是固定的位置

歡迎轉載,但請標明出處,謝謝。
參考網址: Google CodeSearch


2 則留言:

匿名 提到...

您好~請問"GetJpgWidthHeight"在main()中如何使用~因為現在不懂怎麼傳buf~不盡感激

山豆兒 提到...

先把jpg檔案讀到一個buf中,再傳進這個function 就可以回傳 長寬了大致上是這樣,由於這個是 wxwidget 的 buff ,所以如果是一般使用的話要改寫成 char* buff,
再開檔,讀檔,傳入即可。