使用霍夫曼编码的图像压缩

时间:2010-02-26 07:24:06

标签: c

我的项目有些困难。我从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);
  }

}

1 个答案:

答案 0 :(得分:0)

我强烈建议您在询问 StackOverflow 之前使用Google等搜索引擎。这是一个很好的例子。我的Google Search会在C和C ++中产生示例

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