2008年8月19日 星期二

簡單壓縮程式

Run_Length.h code
#ifndef Run_Length
#define Run_Length

#include <fstream>

using std::cout;
using std::endl;
using std::cerr;
using std::ios;
using std::fstream;
using std::ifstream;
using std::ofstream;
using std::string;

int Run_Length_Code(const char *input_filename, const char *output_filename )
{
 fstream f_in; //設定輸入流 
 fstream f_out;//設定輸出流 
 
 //開檔 並設為輸入和二位元讀取 
    f_in.open(input_filename,ios::binary|ios::in); 
 if( !f_in )  //輸入檔錯誤
 {
  cerr << "Input file ERROR!! " << endl;
  system("PAUSE");
  exit(1);
 }
 
 //開檔 並設為輸出和二位元寫入 
    f_out.open(output_filename,ios::binary|ios::out);
 if( !f_out ) //輸出檔錯誤 
 {
  cerr << "Output file ERROR!! " << endl;
  system("PAUSE");
  exit(1);
 }

 char temp,n,num,data,next;
 unsigned int Total_in=0,Total_out=0;
 int cont=0;
 //檔頭資訊檔 
 char ch[12] = {0, 255, 67, 72, 55, 95, 67, 83, 73, 69, 0, 255};
 char head[12];

    //檢查檔頭 是否已經壓縮過 
 int count = 0;
 bool check = false;
 for(int i = 0; i < 12; i++)
 {
  f_in.read(&head[i],1);
  if(ch[i] == head[i]) count++;
 }
 if(count==12) check = true;
 
 f_in.close(); //關檔 
 f_in.open(input_filename,ios::binary|ios::in);// 開檔 
 
 if (check) //有檔頭表示是壓縮過的 
 { //解壓縮 
 cout << "The "<< input_filename <<" is a uncompressed file, compressing …";
 for (int i=0;i<sizeof(ch);i++)
  f_in.read(&temp,1);
  while( 1 )
   {
   f_in.read(&n,1);
   if( !f_in ) break; //如果沒有資料就跳出  
   Total_out+=n; //計總共傳了多少 
   Total_in+=n;  //計總共讀了多少 
   f_in.read(&temp,1);
   for(int i = 0; i < n; i++)
     f_out.write(&temp,1);
   }
    } 
 else
 { //壓縮 
 bool ok=true;
 cout << "The "<< input_filename <<" is a compressed file, decompressing …\n";
 f_out.write(ch,sizeof(ch)); //寫入壓縮檔頭 
 while ( 1 )
 {
  if (ok) {
   f_in.read(&data,1); //讀入資料 
   Total_in++; //讀檔計數 
  }
  if( !f_in ) break;//若沒有資料就跳出 
  cont = 1; //重新開始數 

  while ( 1 )
  {
      f_in.read(&next,1);  
      Total_in++; //讀檔計數 
   if( !f_in )
            { 
    if(cont < 256) // 如果計數沒有大於256 
    {
      num = cont; 
     f_out.write(&num,1);
     f_out.write(&data,1);
     break;
    }
    else //看超過幾次256次 
    {      
     for(int i = 0; i < cont / 255; i++)
     {
       num = 255; 
      f_out.write(&num,1);
      f_out.write(&data,1);
      Total_out+=256;
     }
     //再把剩下的數字輸出
     num = cont % 255;;
     f_out.write(&num,1);
     f_out.write(&data,1);
     Total_out+=num;
     break;
    }//end of else 
   }//end of if(!f_in)
            //f_in.read(&nextdata,1); //讀入下一筆資料
            if ( data == next )
               cont++; //當資料相同的時候 計數 
            if ( data != next )
            {
        ok=false;
     if (cont < 256) // 如果計數沒有大於256
      {
        num = cont;  
                  f_out.write(&num,1);//輸出次數 
                  f_out.write(&data,1); // 輸出資料
                  Total_out+=2;
                  data = next;
                  break;
     }
    else {
      //看超過幾次256次
     for(int i = 0; i < cont / 255; i++)
     {
       num = 255; 
      f_out.write(&num,1);
      f_out.write(&data,1);
      Total_out+=256;
     }
     //再把剩下的數字輸出
     num = cont % 255;
     f_out.write(&num,1);
     //f_out.write(&data,1);
     data = next;
     Total_out+=num;
     break;
        }//end of else
            }//end of if !=
  }//end of while
 }//end of while
    }//end of 壓縮 
    
    f_in.close(); //關輸入檔 
    f_out.close(); //關輸出檔
    return (Total_in-Total_out)/Total_in*100;
}

#endif

main.cpp code
#include <iostream>
#include "Run_Length.h"

using namespace std;

int main(int argc, char *argv[])
{
 char in[255],out[255]; //存檔案的名子
 cout << "Please enter input filename : ";
 cin >> in; //輸入檔名 
 cout << "Please enter output filename : ";
 cin >> out;//輸出檔名 

 int Rate;
    Rate=Run_Length_Code(in,out); //壓縮檔案or解壓縮 

 cout << "Finished. The compression rate : " << Rate << "%." << endl;
 
    system("PAUSE");
    return EXIT_SUCCESS;
}

沒有留言: