壓縮解壓演算法 2

2021-04-12 21:07:01 字數 4410 閱讀 8469

行程編碼(run length coding)的原理也很簡單:將一行中顏色值相同的相鄰象素用乙個計數值和該顏色值來代替。例如aaabccccccddeee可以表示為3a1b6c2d3e。如果一幅圖象是由很多塊顏色相同的大面積區域組成,那麼採用行程編碼的壓縮效率是驚人的。然而,該演算法也導致了乙個致命弱點,如果圖象中每兩個相鄰點的顏色都不同,用這種演算法不但不能壓縮,反而資料量增加一倍。所以現在單純採用行程編碼的壓縮演算法用得並不多,pcx檔案算是其中的一種。

pcx檔案最早是pc paintbrush軟體所採用的一種檔案格式,由於壓縮比不高,現在用的並不是很多了。它也是由頭資訊、調色盤、實際的圖象資料三個部分組成。其中頭資訊的結構為:

typedef struct pcxhead;

其中值得注意的是以下幾個資料:manufacturer為pcx檔案的標識,必須為0x0a;xmin為最小的x座標,xmax最大的x座標,所以圖象的寬度為xmax-xmin+1,同樣圖象的高度為ymax-yin+1;bytes_per_line為每個編碼行所佔的位元組數,下面將詳細介紹。

pcx的調色盤在檔案的最後。以256色pcx檔案為例,倒數第769個位元組為顏色數的標識,256時該位元組必須為12,剩下的768(256×3)為調色盤的rgb值。

為了敘述方便,我們針對256色pcx檔案,介紹一下它的解碼過程。編碼是解碼的逆過程,有興趣的讀者可以試著自己來完成。

解碼是以行為單位的,該行所佔的位元組數由bytes_per_line給定。為此,我們開乙個大小為bytes_per_line的解碼緩衝區。一開始,將緩衝區的所有內容清零。從檔案中讀出乙個位元組c,若c>0xc0,說明是行程(run length)資訊,即c的低6位表示後面連續的位元組個數(所以最多63個連續顏色相同的象素,若還有顏色相同的象素,將在下乙個行程處理),檔案的下乙個位元組就是實際的圖象資料(即該顏色在調色盤中的索引值)。若c<0xc0,則表示c是實際的圖象資料。如此反覆,直到這bytes_per_line個位元組處理完,這一行的解碼完成。pcx就是有若干個這樣的解碼行組成。

下面是實現256色pcx檔案解碼的源程式,其中第二個函式對一行進行解碼,應該把閱讀的重點放在這個函式上。要注意的是,執行時檔案c://test.pcx必須存在,而且是乙個256色pcx檔案。

unsigned int     pcxbytesperline;

bool loadpcxfile (hwnd hwnd,char *pcxfilename)

//讀出頭資訊

fread((char*)&header,1,sizeof(pcxhead),pcxfp);

if(header.manufacturer!=0x0a)

//將檔案指標指向調色盤開始處

fseek(pcxfp,-769l,seek_end);

//獲取顏色數資訊

pcxtag=fgetc(pcxfp)&0xff;

if(pcxtag!=12)

//建立新的bitmapfileheader和bitmapinfoheader

memset((char *)&bf,0,sizeof(bitmapfileheader));     

memset((char *)&bi,0,sizeof(bitmapinfoheader));

//填寫bitmapinfoheader頭資訊

bi.bisize=sizeof(bitmapinfoheader);

//得到圖象的寬和高

bi.biwidth=header.xmax-header.xmin+1;

bi.biheight=header.ymax-header.ymin+1;

bi.biplanes=1;

bi.bibitcount=8;

bi.bicompression=bi_rgb;

imgwidth=bi.biwidth;

imgheight=bi.biheight;

numcolors=256;

linebytes=(dword)widthbytes(bi.biwidth*bi.bibitcount);

imgsize=(dword)linebytes*bi.biheight;

//填寫bitmapfileheader頭資訊

bf.bftype=0x4d42;

bf.bfsize=sizeof(bitmapfileheader)+sizeof(bitmapinfoheader)+

numcolors*sizeof(rgbquad)+imgsize;

bf.bfoffbits=(dword)(numcolors*sizeof(rgbquad)+

sizeof(bitmapfileheader)+sizeof(bitmapinfoheader));

//為新圖分配緩衝區

if((himgdata=globalalloc(ghnd,(dword)

(sizeof(bitmapinfoheader)+

numcolors*sizeof(rgbquad)+imgsize)))==null)

lpimgdata=(lpbitmapinfoheader)globallock(himgdata);

//拷貝頭資訊

memcpy(lpimgdata,(char *)&bi,sizeof(bitmapinfoheader));

lpptr=(char *)lpimgdata+sizeof(bitmapinfoheader);

//為256色調色盤分配記憶體

hpal=localalloc(lhnd,sizeof(logpalette)+

numcolors* sizeof(paletteentry));

ppal =(logpalette *)locallock(hpal);

ppal->palnumentries =256;

ppal->palversion = 0x300;

for (i = 0; i < 256; i++)

//產生新的邏輯調色盤

hpalette=createpalette(ppal);

localunlock(hpal);

localfree(hpal);

hdc=getdc(hwnd);

if(hpalette)

//解碼行所佔的位元組數

pcxbytesperline=(unsigned int)header.bytes_per_line;

//將檔案指標指向圖象資料的開始處

fseek(pcxfp,(long)sizeof(pcxhead),seek_set);

//緩衝區大小

offbits=bf.bfoffbits-sizeof(bitmapfileheader);

//bufsize為緩衝區大小

bufsize=offbits+bi.biheight*linebytes;

for(y=0;y//指向新圖中相應的位置

lpptr=(char *)lpimgdata+bufsize-linebytes-y*linebytes;

//解碼該行,放在陣列linebuffer中

readpcxline(linebuffer,pcxfp);

for(x=0;x*(lpptr++)=linebuffer[x]; //將該行儲存到位圖資料中

}//建立新的點陣圖

hbitmap=createdibitmap(hdc,(lpbitmapinfoheader)lpimgdata,

(long)cbm_init,

(lpstr)lpimgdata+

sizeof(bitmapinfoheader)+

numcolors*sizeof(rgbquad),

(lpbitmapinfo)lpimgdata,

dib_rgb_colors);

if(hpalette && hprevpalette)

hfbmp=_lcreat("c://pcx2bmp.bmp",0);

_lwrite(hfbmp,(lpstr)&bf,sizeof(bitmapfileheader));

_lwrite(hfbmp,(lpstr)lpimgdata,bufsize);

_lclose(hfbmp);

fclose(pcxfp);

//釋放記憶體和資源

releasedc(hwnd,hdc);

globalunlock(himgdata);

return true;

}//對每一行進行解碼,結果儲存到指標p指向的記憶體中

void readpcxline(unsigned char *p,file *fp)

else p[n++]=c; //否則是實際的圖象資料,直接填入到p中

}while (n}

對一幅的pcx檔案格式的圖象解碼後,結果如圖9.2所示。顯示的是我最喜歡的法國影星阿佳妮·伊莎貝拉。

圖9.2一幅pcx檔案格式的圖象

PackBits解壓縮演算法

packbits壓縮方式是每段資料都有乙個頭 有符號的8bit型別資料 和資料。具體形式如下圖所示。當頭部的值為 1 127表示頭部後面的1乙個位元組的資料進行過資料壓縮,解壓縮時需要將頭部後面的乙個位元組的資料重複頭部值的絕對值 1次。當頭部的值為0 127表示頭部後面頭部值 1個位元組的資料沒有...

壓縮解壓縮

壓縮 壓縮後的檔名 包含物理路徑 待壓縮的資料夾 包含物理路徑 public static void packfiles string filename,string directory catch exception 解壓縮 待解壓檔名 包含物理路徑 解壓到哪個目錄中 包含物理路徑 public ...

壓縮 解壓縮

linux使用最廣泛的壓縮格式位gz,使用gzip命令進行壓縮和解壓縮 1 gzip,gunzip,壓縮 解壓縮檔案,compress or expand files gzip acdfhkllnnrtvv19 s suffix name gunzip acfhkllnnrtvv s suffix ...