我想對bmp(位圖)文件應用DCT(離散餘弦變換)壓縮。我有一個C文件,我在Turbo C++中運行。這實際上並沒有壓縮,但我試圖實現DCT和IDCT。代碼如下:解壓停止在中間和輸出文件填充零(黑色像素)?
/*
the image to be compressed is a bmp with 24 bpp and
with name "college4.bmp" of dimensions 200*160 ie 25*20- 8*8 blocks
o/p is college2.dat
format: 8 bit signed integers starting rowwise from 0,0 to 8,8
the coefficients order is blue,green,red
for the block no 1 then 2 and soon
*/
#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#define WIDTH 25
#define HEIGHT 20
typedef struct {
unsigned int type;
unsigned long int filesize;
unsigned int reserved1,reserved2;
unsigned long int offset;
} BMPHEAD;
typedef struct {
unsigned long int infosize;
unsigned long int width,height;
unsigned int planes,bitsperpixel;
unsigned long int compression;
unsigned long int sizeimage;
long int xpelspermeter,ypelspermeter;
unsigned long int colorused,colorimportant;
} INFOHEAD;
typedef struct {
char rgbquad[4];
} colortable;
BMPHEAD bmphead;
INFOHEAD infohead;
FILE *bmp_fp1,*bmp_fp2;
int buf[WIDTH][8][8][3],buf1[WIDTH][8][8][3];
float pi=3.14159265,DCTcoeff[8][8][8][8];
void generatedctcoeff() {
int y, i, j, x;
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
for (x = 0; x < 8; x++) {
for (y = 0; y < 8; y++) {
DCTcoeff[i][j][x][y] = cos(((2 * y + 1) * pi * j)/16)
* cos(((2 * x + 1) * i * pi)/16);
}
}
}
}
}
void outputtofile1() { // Write into college2.dat
int i, j, x, y, blockno; // One block at a time, buf contains pixel
int redcoef, greencoef, bluecoef; // data of one row of blocks
float gijred, gijgreen, gijblue, c, ci, cj;
c = 1/(sqrt(2));
for (blockno = 0; blockno < WIDTH; blockno++) {
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
gijred = 0;
gijgreen = 0;
gijblue = 0;
for (x = 0; x < 8; x++) {
for (y = 0; y < 8; y++) {
gijblue = gijblue + DCTcoeff[i][j][x][y]
* buf[blockno][x][y][0];
gijgreen = gijgreen + DCTcoeff[i][j][x][y]
* buf[blockno][x][y][1];
gijred = gijred + DCTcoeff[i][j][x][y]
* buf[blockno][x][y][2];
}
}
ci = cj = 1.0;
if (i == 0)
ci = c;
if (j == 0)
cj = c;
gijblue = ci * cj * gijblue/4;
gijgreen = ci * cj * gijgreen/4;
gijred = ci * cj * gijred/4;
bluecoef = (int) gijblue;
greencoef = (int) gijgreen;
redcoef = (int) gijred;
fprintf(bmp_fp2, "%d %d %d ", bluecoef, greencoef, redcoef);
}
}
} /* end of one block processing */
}
void compressimage() {
int rowcount,x,y;
bmp_fp1=fopen("college4.bmp","r");
bmp_fp2=fopen("college2.dat","w");
printf("generating coefficients...\n");
generatedctcoeff();
if(bmp_fp1==NULL) {
printf("can't open");
return;
}
printf("compressing....\n");
fread(&bmphead,1,sizeof(bmphead),bmp_fp1);
fread(&infohead,1,sizeof(infohead),bmp_fp1);
fseek(bmp_fp1,bmphead.offset,SEEK_SET);
for(rowcount=0;rowcount<HEIGHT;rowcount++) {
for(y=0;y<8;y++) {
for(x=0;x<infohead.width;x++) {
buf[x/8][x%8][y][0]=(int)fgetc(bmp_fp1);
buf[x/8][x%8][y][1]=(int)fgetc(bmp_fp1);
buf[x/8][x%8][y][2]=(int)fgetc(bmp_fp1);
}
}
outputtofile1(); //output contents of buf after dct to file
}
fclose(bmp_fp1);
fclose(bmp_fp2);
}
void outputtofile2() { //output buf to college3.bmp
int i, j, x, y, blockno; // buf now contains coefficients
float pxyred, pxygreen, pxyblue, c, ci, cj; // a temp buffer buf1 used to
c = 1/(sqrt(2)); // store one row of block of
for (blockno = 0; blockno < WIDTH; blockno++) { // decoded pixel values
for (x = 0; x < 8; x++)
for (y = 0; y < 8; y++) {
pxyred = 0;
pxygreen = 0;
pxyblue = 0;
for (j = 0; j < 8; j++) {
cj = 1.0;
if (j == 0)
cj = c;
for (i = 0; i < 8; i++) {
ci = 1.0;
if (i == 0)
ci = c;
pxyblue = pxyblue + ci * cj * DCTcoeff[i][j][y][x] * buf[blockno][i][j][0];
pxygreen = pxygreen + ci * cj
* DCTcoeff[i][j][y][x] * buf[blockno][i][j][1];
pxyred = pxyred + ci * cj * DCTcoeff[i][j][y][x] * buf[blockno][i][j][2];
}
}
pxyblue /= 4;
pxygreen /= 4;
pxyred /= 4;
buf1[blockno][y][x][0] = pxyblue;
buf1[blockno][y][x][1] = pxygreen;
buf1[blockno][y][x][2] = pxyred;
}
}
for (y = 0; y < 8; y++) {
for (blockno = 0; blockno < WIDTH; blockno++)
for (x = 0; x < 8; x++) {
fprintf(bmp_fp2, "%c%c%c", (char) buf1[blockno][x][y][0],
(char) buf1[blockno][x][y][1],
(char) buf1[blockno][x][y][2]);
}
}
}
void uncompressimage() {
int blue,green,red,rowcount,colcount,i,j;
bmp_fp1=fopen("college2.dat","r");
bmp_fp2=fopen("college3.bmp","w");
printf("generating coefficients...\n");
generatedctcoeff();
if (bmp_fp1==NULL) {
printf("open failed");
return;
}
printf("uncompressing....\n");
bmphead.type=0x4d42;
bmphead.filesize=30518;
bmphead.reserved1=0;
bmphead.reserved2=0;
bmphead.offset=sizeof(bmphead)+sizeof(infohead);
infohead.infosize=sizeof(infohead);
infohead.width=200;
infohead.height=160;
infohead.planes=1;
infohead.bitsperpixel=24;
infohead.compression=0;
infohead.sizeimage=0;
infohead.xpelspermeter=3780;
infohead.ypelspermeter=3780;
infohead.colorused=0;
infohead.colorimportant=0;
fwrite(&bmphead,sizeof(BMPHEAD),1,bmp_fp2);
fwrite(&infohead,sizeof(INFOHEAD),1,bmp_fp2);
for(rowcount=0;rowcount<HEIGHT;rowcount++) {
for(colcount=0;colcount<WIDTH;colcount++) {
for(i=0;i<8;i++) {
for(j=0;j<8;j++) {
fscanf(bmp_fp1,"%d",&blue);
fscanf(bmp_fp1,"%d",&green);
fscanf(bmp_fp1,"%d",&red);
buf[colcount][i][j][0]=blue;
buf[colcount][i][j][1]=green;
buf[colcount][i][j][2]=red;
}
}
}
outputtofile2();
}
fclose(bmp_fp1);
fclose(bmp_fp2);
}
int main() {
printf("opening files...\n");
compressimage();
printf("opening files...again\n");
uncompressimage();
printf("successful decompression\nenter any key\n");
return 0;
}
這裏是我作爲輸入圖像
(IM srry網站轉換的BMP成PNG你可以把它轉換回BMP使用它。) 這裏是生成的圖像:
文件college3.bmp時生成的大小爲200x160和93.8 KB,但直到圖像季度它已經正確解碼了係數,但後來該文件被黑色像素填充。我截取了o/p的截圖,因爲它是在上傳時不是有效的bmp。自2004年2月以來,我一直在關注這個問題。如果有人能說我哪裏有錯誤,我會非常感激。我已經分析了輸出文件,並在像素開始變黑的地方找到了EOF。我閱讀了有關該主題的其他一些問題,發現轉換因子ci,cj已被錯誤地使用。雖然編碼我也與指數x,y,i和j混淆。所以我希望這個問題我會在幾天內解決。
+1對於坐在這個問題自2004年二月以來 – Ulterior
你可以仔細檢查你的DCT/IDCT代碼與[這個答案](http://stackoverflow.com/a/8553966/968261)?它爲一個通道(藍色或紅色或綠色或黑白)的8x8塊執行JPEG的DCT/IDCT。 –
@Alex我相信這不是緩衝區重用問題,因爲我使用buf來保存像素值並計算coeff並寫入.dat文件。在做IDCT時,我正在從文件(.dat)中讀取buf中存儲的coeff,然後執行IDCT並將像素值複製到buf1中,最後寫入到bmp文件中。我懷疑是錯的就是我爲什麼refered到DCTcoeff [i] [j] [Y] [x]和BUF1 [塊編號] [Y] [X] [0] outputtofile2代替DCTcoeff [i] [j] [ x] [y]和buf1 [blockno] [x] [y] [0]。我不記得我爲什麼那樣做。我無法在eclipse中重新創建問題。 –