原理は単純でデータが連続で続いていたら、そやつらを符号化するだけです。
#ref(): File not found: "gazou1.jpg" at page "もっとも単純なランレングス圧縮"
ここで注意しておきたいのはデータが連続しないときも符号をつかないといけないということです。
でないとプログラム側がデータか符号かがわかりませんから。
つまりこの圧縮方法だとよほどデータが連続してないと圧縮前よりデータ量が増えてしまうということです。
これは次回に解消します。
符号どうりにデータを展開します。
#include<stdio.h> #include<stdlib.h> #include<conio.h> #include<string.h> #define EXP_DATA 0 #define EXP_SYMBOL 1 void RLECompressFile(char *read_file_name); void RLEDecompressFile(char *read_file_name); int main(int argc, char *argv[]) { int input; //コマンドライン引数の例外 if((argc - 1) != 1) { printf("ファイルを指定してください\n"); return 0; } //圧縮or解凍 do { printf("圧縮→'c' 解凍→'t' 終了→'q'\n"); input = getch(); switch(input) { case 'c': printf("ファイルを圧縮します\n\n"); printf("%s\n", argv[1]); RLECompressFile(argv[1]); break; case 't': printf("ファイルを解凍します\n"); printf("%s\n", argv[1]); RLEDecompressFile(argv[1]); break; case 'q': printf("終了します\n"); return 0; default: printf("もう一度入力してください\n"); } }while((input != 'c') && input != 't'); return 0; } //ファイルを圧縮する関数 //引数1:ファイルの名前 void RLECompressFile(char *read_file_name) { FILE *read_fp; FILE *write_fp; fpos_t rfile_size = 0; fpos_t wfile_size = 0; fpos_t file_pos = 0; unsigned char *read_data; unsigned char write_data[2]; //write_data[0] → データ write_data[1] → 何回続くか fpos_t i; unsigned char equ_counter = 1; char write_file_name[_MAX_PATH]; //読み込みファイル if((read_fp = fopen(read_file_name, "rb")) == NULL) { printf("ファイルが開けません(read)\n"); exit(0); } //新規ファイル strcpy(write_file_name, read_file_name); strcat(write_file_name, ".rrr"); //拡張子をrrrに if((write_fp = fopen(write_file_name, "wb")) == NULL) { printf("ファイルが開けません(write)\n"); exit(0); } //ファイルサイズ取得 file_pos = fseek(read_fp, 0, SEEK_END); fgetpos(read_fp, &rfile_size); fseek(read_fp, file_pos, SEEK_SET); printf("圧縮前 %dbyte\n", rfile_size); //メモリ確保 read_data = (unsigned char*)malloc(rfile_size); //読み込み fread(read_data, sizeof(unsigned char), rfile_size, read_fp); //圧縮と書き込み for(i = 1; i < rfile_size + 1; i++) { for(equ_counter = 1; equ_counter < 256; equ_counter++) { if(read_data[i] == read_data[i - 1]) { i++; continue; }else { break; } } write_data[EXP_DATA] = read_data[i - 1]; write_data[EXP_SYMBOL] = equ_counter; fwrite(write_data, sizeof(unsigned char), 2, write_fp); } fgetpos(write_fp, &wfile_size); printf("圧縮後 %dbyte\n", wfile_size); printf("圧縮率 %f%%\n\n", ((float)wfile_size / (float)rfile_size) * 100.0); fclose(read_fp); fclose(write_fp); free(read_data); } //ファイルを解凍する関数 //引数1:ファイルの名前 void RLEDecompressFile(char *read_file_name) { FILE *read_fp; FILE *write_fp; fpos_t rfile_size = 0; fpos_t wfile_size = 0; fpos_t file_pos = 0; unsigned char *read_data; fpos_t i, j; unsigned char equ_counter = 1; char write_file_name[_MAX_PATH]; //読み込みファイル if((read_fp = fopen(read_file_name, "rb")) == NULL) { printf("ファイルが開けません(read)\n"); exit(0); } //新規ファイル strcpy(write_file_name, read_file_name); write_file_name[strlen(write_file_name) - 4] = '\0'; if((write_fp = fopen(write_file_name, "wb")) == NULL) { printf("ファイルが開けません(write)\n"); exit(0); } //ファイルサイズ取得 file_pos = fseek(read_fp, 0, SEEK_END); fgetpos(read_fp, &rfile_size); fseek(read_fp, file_pos, SEEK_SET); //メモリ確保 read_data = (unsigned char*)malloc(rfile_size); //読み込み fread(read_data, sizeof(unsigned char), rfile_size, read_fp); //解答と書き込み for(i = 0; i < rfile_size; i += 2) { for(j = 0; j < read_data[i + 1]; j++) { fwrite(&read_data[i], sizeof(char), 1, write_fp); } } fclose(read_fp); fclose(write_fp); free(read_data); }