2010-02-26 74 views
-2

我的项目有一些困难。我从256x256 bmp图像中获得RGB值。但是,我不知道如何通过使用霍夫曼编码来压缩这些RGB值。 任何人都可以帮助我吗?谢谢你的帮助。使用霍夫曼编码进行图像压缩

#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 

/*-------PROTOTYPES-------*/ 
long getImageInfo(FILE*, long, int); 
void copyImageInfo(FILE* inputFile, FILE* outputFile); 
void copyColorTable(FILE* inputFile, FILE* outputFile, int nColors); 
//void bmpsave (FILE*, unsigned char , int , int); 

/*------STRUCTURES--------*/ 
typedef struct {int rows; int cols; unsigned char* data;} sImage; 

int main(int argc, char* argv[]) 
{ 



    FILE *bmpInput, *rasterOutput, *bmpOutput,*RedText,*GreenText,*BlueText,*ErrorRedText,*ErrorBlueText,*ErrorGreenText; 
    FILE     *entroGreen,*entroBlue,*entroRed; 
    sImage originalImage; 
    unsigned char someChar; 
    unsigned char *pChar; 
    long fileSize; 
    int vectorSize, nColors; 
    int     totalGCount=0, totalBCount=0,totalRCount=0; 
    int r, c, i,j,k=0; 
    int redValue, greenValue, blueValue; 
    int     dummyRed=0 ,dummyGreen=0, dummyBlue=0; 
    int     count[256] = {0},countRed[256]= {0},countBlue[256]= {0},countGreen[256]= {0}; 
    double    EntropyGreen, EntropyBlue, EntropyRed; 
    //int     error[414720]; 
    //int     Red[400][720]; 
    //int     Green[400][720]; 
    //int     Blue[400][720]; 


    unsigned int uint1; 
    short   word1; 
    unsigned char byte1, byte2; 
    FILE   *imdata; 

    int **errorGreen; 
    int **errorRed; 
    int **errorBlue; 
    int **Red; 
    int **Blue; 
    int **Green; 
    int **b; 


    b = malloc (256 * sizeof (int)); 
    for (i = 0; i < 256; ++i) 
    b[i] = malloc (256 * sizeof (int)); 

    errorGreen = malloc (256 * sizeof (int)); 
    for (i = 0; i < 256; ++i) 
    errorGreen[i] = malloc (256 * sizeof (int)); 

    errorRed = malloc (256 * sizeof (int)); 
    for (i = 0; i < 256; ++i) 
    errorRed[i] = malloc (256 * sizeof (int)); 

    errorBlue = malloc (256 * sizeof (int)); 
    for (i = 0; i < 256; ++i) 
    errorBlue[i] = malloc (256 * sizeof (int)); 
    //error = (int *) malloc (414720 * sizeof (int)); //Dynamic Memmory Allocation of 1D Array 
    Red = malloc (256 * sizeof (int)); 
    for (i = 0; i < 256; ++i) 
    Red[i] = malloc (256 * sizeof (int)); 

    Green = malloc (256 * sizeof (int)); 
    for (i = 0; i < 256; ++i) 
    Green[i] = malloc (256 * sizeof (int)); 

    Blue = malloc (256 * sizeof (int)); 
    for (i = 0; i < 256; ++i) 
    Blue[i] = malloc (256 * sizeof (int)); 






    /*--------INITIALIZE POINTER----------*/ 
    someChar = '0'; 
    pChar = &someChar; 

    if(argc < 2) 
    { 
    printf("Usage: %s bmpInput.bmp\n", argv[0]); 
    exit(0); 
    } 

    printf("Reading file %s\n", "Kirschen_256.bmp"); 

    /*----DECLARE INPUT AND OUTPUT FILES----*/ 
    bmpInput = fopen("Kirschen_256.bmp", "rb"); 
    /*RedText = fopen("Red.txt", "w"); 
    BlueText = fopen("Blue.txt", "w"); 
    GreenText = fopen("Green.txt", "w");*/ 
    entroGreen = fopen("entroGreen.txt", "w"); 
    entroRed = fopen("entroRed.txt", "w"); 
    entroBlue = fopen("entroBlue.txt", "w"); 
    ErrorRedText = fopen("ErrorRed.txt", "w"); 
    ErrorBlueText = fopen("ErrorBlue.txt", "w"); 
    ErrorGreenText = fopen("ErrorGreen.txt", "w"); 
    rasterOutput = fopen("Kirschen_256.txt", "w"); 
    bmpOutput = fopen("Kirschen_256().bmp", "wb"); 

    fseek(bmpInput , 0L , SEEK_END); 
    //fseek is a C function belonging to the ANSI C standard library, 
    //and included in the file stdio.h. Its purpose is to change the file position indicator for the specified stream. 
    /*-----GET BMP DATA-----*/ 
    originalImage.cols = (int)getImageInfo(bmpInput, 18, 4); 
    originalImage.rows = (int)getImageInfo(bmpInput, 22, 4); 
    fileSize = getImageInfo(bmpInput, 2, 4); 
    nColors = getImageInfo(bmpInput, 46, 4); 
    //vectorSize = fileSize - (14 + 40 + 4*nColors); 

    /*----PRINT DATA TO SCREEN-----*/ 
    printf("Width: %d\n", originalImage.cols); 
    printf("Height: %d\n", originalImage.rows); 
    printf("File size: %ld\n", fileSize); 
    printf("Bits/pixel: %d\n", getImageInfo(bmpInput, 28, 4)); 
    printf("No. colors: %d\n", nColors); 
    //printf("Vector size: %d\n", vectorSize); 

    copyImageInfo(bmpInput, bmpOutput); 
    //copyColorTable(bmpInput, bmpOutput, nColors); 


    /*----FOR 24-BIT BMP, THERE IS NO COLOR TABLE-----*/ 
    fseek(bmpInput , 54 , SEEK_SET); 
    fseek(bmpOutput , 54 , SEEK_SET); 
    /*-----------READ RASTER DATA-----------*/ 

    for(r=0; r<=originalImage.rows-1; r++) 
    { 
    for(c=0; c<=originalImage.cols-1; c++) 
    { 
     /*----READ FIRST BYTE TO GET BLUE VALUE-----*/ 
    fread(pChar, sizeof(char), 1, bmpInput); 
     blueValue = *pChar; 
     Blue[r][c]=*pChar; 
     if (r==0||c==0){ 
      errorBlue[r][c]=abs(dummyBlue-blueValue); 
      countBlue[abs(dummyBlue-blueValue)]++; 
      count[abs(dummyBlue-blueValue)]++; 
      totalBCount++; 
     } 
     else{ 
      errorBlue[r][c]=abs(((dummyBlue+Blue[r-1][c]+Blue[r-1][c-1])/3)-blueValue); 
      countBlue[abs(((dummyBlue+Blue[r-1][c]+Blue[r-1][c-1])/3)-blueValue)]++; 
      count[abs(((dummyBlue+Blue[r-1][c]+Blue[r-1][c-1])/3)-blueValue)]++; 
      totalBCount++; 
    } 
     //error[k]=abs(dummyBlue-blueValue); 
     //k++; 
     *pChar=dummyBlue; 
     fwrite(pChar, sizeof(char), 1, bmpOutput); 
     dummyBlue=blueValue; 


     /*-----READ NEXT BYTE TO GET GREEN VALUE-----*/ 
    fread(pChar, sizeof(char), 1, bmpInput); 
     greenValue = *pChar; 
     Green[r][c]=*pChar; 
     if (r==0||c==0){ 
      errorGreen[r][c]=abs(dummyGreen-greenValue); 
      countGreen[abs(dummyGreen-greenValue)]++; 
      count[abs(dummyGreen-greenValue)]++; 
      totalGCount++; 
     } 
     else{ 
      errorGreen[r][c]=abs(((dummyGreen+Green[r-1][c]+Green[r-1][c-1])/3)-greenValue); 
      countGreen[abs(((dummyGreen+Green[r-1][c]+Green[r-1][c-1])/3)-greenValue)]++; 
      count[abs(((dummyGreen+Green[r-1][c]+Green[r-1][c-1])/3)-greenValue)]++; 
      totalGCount++; 
    } 
     *pChar=dummyGreen; 
     fwrite(pChar, sizeof(char), 1, bmpOutput); 
     dummyGreen=greenValue; 


     /*-----READ NEXT BYTE TO GET RED VALUE-----*/ 
     fread(pChar, sizeof(char), 1, bmpInput); 
     redValue = *pChar; 
     Red[r][c]=*pChar; 
     if (r==0||c==0){ 
      errorRed[r][c]=abs(dummyRed-redValue); 
      countRed[abs(dummyRed-redValue)]++; 
      count[abs(dummyRed-redValue)]++; 
      totalRCount++; 
     } 
     else{ 
      errorRed[r][c]=abs(((dummyRed+Red[r-1][c]+Red[r-1][c-1])/3)-redValue); 
      countRed[abs(((dummyRed+Red[r-1][c]+Red[r-1][c-1])/3)-redValue)]++; 
      count[abs(((dummyRed+Red[r-1][c]+Red[r-1][c-1])/3)-redValue)]++; 
      totalRCount++; 
    } 
     *pChar=dummyRed; 
     fwrite(pChar, sizeof(char), 1, bmpOutput); 
     dummyRed=redValue; 


     /*---------PRINT TO TEXT FILE---------*/ 
     fprintf(rasterOutput, "(%d %d) = \tRed \t%d", r, c, redValue); 
     fprintf(rasterOutput, "\tGreen \t%d \tBlue \t%d\n", greenValue, blueValue); 

     /*-----read data, reflect and write to output file----*/ 

     //fseek(bmpOutput, 54 , SEEK_SET); 
     //fwrite(pChar, sizeof(char), 1, bmpOutput); 
    } 
    } 
    for (j=0; j<256; j++) { 
      for (i=255; i>=0; i--) { 
        if(i>=256-(count[j]/16)) 
        b[i][j] = 0x00; 
        else 
        b[i][j] = 0xFF; 
      } 
    } 


    imdata = fopen("Kirschen_256after4", "wb"); 
/* if (imdata == NULL) { 
    printf("%s open error.\n", imname); exit(0); 
    } 
*/ 
    byte1 = 'B'; byte2 = 'M'; 
    fwrite(&byte1, 1, 1, imdata); fwrite(&byte2, 1, 1, imdata); 
    uint1 = 54 + 4*256 + originalImage.cols*originalImage.rows; fwrite(&uint1, 4, 1, imdata); 
    word1 = 0; fwrite(&word1, 2, 1, imdata); fwrite(&word1, 2, 1, imdata); 
    uint1 = 54 + 4*256; fwrite(&uint1, 4, 1, imdata); 
    uint1 = 40; fwrite(&uint1, 4, 1, imdata); 
    fwrite(&originalImage.cols, 4, 1, imdata); fwrite(&originalImage.rows, 4, 1, imdata); 
    word1 = 1; fwrite(&word1, 2, 1, imdata); 
    word1 = 8; fwrite(&word1, 2, 1, imdata); 
    uint1 = 0; fwrite(&uint1, 4, 1, imdata); 
    uint1 = originalImage.cols*originalImage.rows; fwrite(&uint1, 4, 1, imdata); 
    j = 11811; fwrite(&j, 4, 1, imdata); fwrite(&j, 4, 1, imdata); 
    uint1 = 256; fwrite(&uint1, 4, 1, imdata); 
    uint1 = 0;  fwrite(&uint1, 4, 1, imdata); 

    for (i=0; i<256; i++) { 
    byte1 = i; 
    fwrite(&byte1, 1, 1, imdata); fwrite(&byte1, 1, 1, imdata); 
    fwrite(&byte1, 1, 1, imdata); fwrite(&byte1, 1, 1, imdata); 
    } 

    for (i=originalImage.rows-1; i>=0; i--) { 
    for (j=0; j<originalImage.cols; j++) { 
     fwrite(&b[i][j], 1, 1, imdata); 
    } 
    } 

    fclose(imdata); 

    for (i=0; i<256; i++) { 
     if (countGreen[i]==0) 
      EntropyGreen += 0; 
     else 
      EntropyGreen += ((double)countGreen[i]/(double)totalGCount) * (log2 ((double)1/((double)countGreen[i]/(double)totalGCount))); 

     if (countRed[i]==0) 
      EntropyRed += 0; 
     else 
      EntropyRed += ((double)countRed[i]/(double)totalRCount) * (log2 ((double)1/((double)countRed[i]/(double)totalRCount))); 

     if (countBlue[i]==0) 
      EntropyBlue +=0; 
     else 
      EntropyBlue += ((double)countBlue[i]/(double)totalBCount) * (log2 ((double)1/((double)countBlue[i]/(double)totalBCount))); 


    } 


     fprintf(entroGreen, "Entropy= %f", EntropyGreen); 
     fprintf(entroRed, "Entropy= %f", EntropyRed); 
     fprintf(entroBlue, "Entropy= %f", EntropyBlue); 

    for (i = 0; i < 256; i++) { 
    for (j = 0; j < 256; j++) { 
     fprintf(ErrorRedText, "[%d][%d] = %2d\n", i, j, errorRed[i][j]); 
     fprintf(ErrorGreenText, "[%d][%d] = %2d\n", i, j, errorGreen[i][j]); 
     fprintf(ErrorBlueText, "[%d][%d] = %2d\n", i, j, errorBlue[i][j]); 

    fprintf (ErrorRedText,"\n"); 
    fprintf (ErrorBlueText,"\n"); 
    fprintf (ErrorGreenText,"\n"); 
    } 
    } 
    /*for (i = 0; i < 768; i++) { 
    for (j = 0; j < 1024; j++) { 
     fprintf(RedText, "a[%d][%d] = %2d\n", i, j, Red[i][j]); 
     fprintf(GreenText, "a[%d][%d] = %2d\n", i, j, Green[i][j]); 
     fprintf(BlueText, "a[%d][%d] = %2d\n", i, j, Blue[i][j]); 
    } 
    fprintf (RedText,"\n"); 
    fprintf (BlueText,"\n"); 
    fprintf (GreenText,"\n"); 
    }*/ 
    /*for (i = 0; i < 414720; i++){ 
     fprintf(ErrorText, "error[%d] = %d\n",i,error[i]); 
     fprintf (ErrorText,"\n"); 
    }*/ 
// PrintHistogram(freq_array, NUM_RANGE); 


    fclose(bmpInput); 
    /*fclose(RedText); 
    fclose(GreenText); 
    fclose(BlueText);*/ 
    fclose(ErrorRedText); 
    fclose(ErrorGreenText); 
    fclose(ErrorBlueText); 
    fclose(rasterOutput); 
    fclose(bmpOutput); 
    fclose(entroGreen); 
    fclose(entroRed); 
    fclose(entroBlue); 


    return 0; 



} 

/*----GET IMAGE INFO SUBPROGRAM------*/ 

long getImageInfo(FILE* inputFile, long offset, int numberOfChars) 
{ 
    unsigned char *ptrC; 
    long value=0L; 
    int i; 
    unsigned char dummy; 


    dummy = '0'; 
    ptrC = &dummy; 

    fseek(inputFile, offset, SEEK_SET); 

    for(i=1; i<=numberOfChars; i++) 
    { 
    fread(ptrC, sizeof(char), 1, inputFile); 
    /* calculate value based on adding bytes */ 
    value = (long)(value + (*ptrC)*(pow(256, (i-1)))); 
    } 

    return(value); 
} 

/*-------------COPIES HEADER AND INFO HEADER----------------*/ 
void copyImageInfo(FILE* inputFile, FILE* outputFile) 
{ 
    unsigned char *ptrC; 
    unsigned char dummy; 
    int i; 

    dummy = '0'; 
    ptrC = &dummy; 

    fseek(inputFile, 0L, SEEK_SET); 
    fseek(outputFile, 0L, SEEK_SET); 

    for(i=0; i<=50; i++) 
    { 
    fread(ptrC, sizeof(char), 1, inputFile); 
    fwrite(ptrC, sizeof(char), 1, outputFile); 
    } 

} 

/*----------------COPIES COLOR TABLE-----------------------------*/ 
void copyColorTable(FILE* inputFile, FILE* outputFile, int nColors) 
{ 
    unsigned char *ptrC; 
    unsigned char dummy; 
    int i; 

    dummy = '0'; 
    ptrC = &dummy; 

    fseek(inputFile, 54L, SEEK_SET); 
    fseek(outputFile, 54L, SEEK_SET); 

    for(i=0; i<=(4*nColors); i++) /* there are (4*nColors) bytesin color table */ 
    { 
    fread(ptrC, sizeof(char), 1, inputFile); 
    fwrite(ptrC, sizeof(char), 1, outputFile); 
    } 

} 
+0

你坚持哪一点?你的代码似乎并没有显示你甚至已经开始写任何与huffman相关的东西。如果您对这些概念感到困惑,请提出关于您不理解的概念的具体问题,并且不要发布不相关的代码。如果您对如何让huffman处理代码感到困惑,请发布一个最小的可编译示例来说明您的问题。 – 2010-02-26 09:54:06

+0

这是功课吗?如果是这样,请添加“家庭作业”标签。 – bta 2010-02-26 23:23:50

回答

1

我强烈建议使用搜索引擎如谷歌,要求对StackOverflow的之前。这是一个很好的例子。在C和C++中,我的Google Search产量为示例

如果您的程序有问题,请在此处显示相关代码。