244 lines
5.8 KiB
C
244 lines
5.8 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#define WSIZE 250
|
|
#define BSIZE 50
|
|
///----------------------------LZ77-------------
|
|
typedef struct {
|
|
unsigned char pos;
|
|
unsigned char n;
|
|
char symb;
|
|
} LZ77Token;
|
|
int compress_1(const char* input_file, const char* output_file)
|
|
{
|
|
int compr_size = 0, sz = 0;
|
|
FILE* input = fopen(input_file, "rb");
|
|
FILE* output = fopen(output_file, "wb");
|
|
|
|
if (!input || !output)
|
|
{
|
|
exit(-1);
|
|
}
|
|
|
|
char window[WSIZE] = { 0 };
|
|
char buffer[BSIZE] = { 0 };
|
|
|
|
int w_start = 0;
|
|
int w_end = 0;
|
|
|
|
while (!feof(input))
|
|
{
|
|
int blen = fread(buffer, 1, BSIZE, input);
|
|
|
|
for (int bpos = 0; bpos < blen; ++bpos)
|
|
{
|
|
int best_pos = 0;
|
|
int best_n = 0;
|
|
|
|
for (int spos = w_start; spos < w_end; ++spos)
|
|
{
|
|
int mlength = 0;
|
|
|
|
while (mlength < blen - bpos &&
|
|
mlength < WSIZE &&
|
|
(spos + mlength) < w_end &&
|
|
window[(spos + mlength) % WSIZE] == buffer[bpos + mlength])
|
|
{
|
|
++mlength;
|
|
}
|
|
|
|
if (mlength > best_n)
|
|
{
|
|
best_pos = w_end - spos;
|
|
best_n = mlength;
|
|
}
|
|
}
|
|
|
|
LZ77Token token;
|
|
token.pos = best_pos;
|
|
token.n = best_n;
|
|
|
|
if (bpos + best_n < blen)
|
|
{
|
|
token.symb = buffer[bpos + best_n];
|
|
}
|
|
else
|
|
{
|
|
token.symb = '\0';
|
|
}
|
|
|
|
sz=fwrite(&token, sizeof(LZ77Token), 1, output);
|
|
compr_size += sizeof(LZ77Token) * sz;
|
|
|
|
for (int j = 0; j <= best_n && bpos < blen; ++j)
|
|
{
|
|
if (bpos + j < blen)
|
|
{
|
|
window[w_end % WSIZE] = buffer[bpos + j];
|
|
w_end++;
|
|
|
|
if (w_end - w_start > WSIZE)
|
|
{
|
|
w_start++;
|
|
}
|
|
}
|
|
}
|
|
bpos += best_n;
|
|
}
|
|
}
|
|
|
|
fclose(input);
|
|
fclose(output);
|
|
|
|
return compr_size;
|
|
}
|
|
|
|
int decompress_1(const char* input_file, const char* output_file)
|
|
{
|
|
int compr_size = 0;
|
|
FILE* input = fopen(input_file, "rb");
|
|
FILE* output = fopen(output_file, "wb");
|
|
|
|
if (!input || !output)
|
|
{
|
|
exit(-1);
|
|
}
|
|
|
|
char window[WSIZE] = { 0 };
|
|
int window_end = 0;
|
|
|
|
LZ77Token token;
|
|
while (fread(&token, sizeof(LZ77Token), 1, input))
|
|
{
|
|
if (token.pos == 0 && token.n == 0 && token.symb == '\0')
|
|
{
|
|
continue;
|
|
}
|
|
|
|
int start_index = (window_end - token.pos + WSIZE) % WSIZE;
|
|
|
|
for (int i = 0; i < token.n; ++i)
|
|
{
|
|
char ch = window[(start_index + i) % WSIZE];
|
|
compr_size += fwrite(&ch, 1, 1, output);
|
|
window[window_end % WSIZE] = ch;
|
|
window_end = (window_end + 1) % WSIZE;
|
|
}
|
|
|
|
if (token.symb != '\0')
|
|
{
|
|
compr_size += fwrite(&token.symb, 1, 1, output);
|
|
window[window_end % WSIZE] = token.symb;
|
|
window_end = (window_end + 1) % WSIZE;
|
|
}
|
|
}
|
|
fclose(input);
|
|
fclose(output);
|
|
|
|
|
|
return compr_size;
|
|
}//-------------------------------------RLE--------------------
|
|
int compress_2(const char* input_file, const char* output_file) {
|
|
int ch, nchar;
|
|
unsigned char count = 1;
|
|
int compr_size = 0;
|
|
|
|
FILE* in = fopen(input_file, "rb");
|
|
FILE* out = fopen(output_file, "wb");
|
|
|
|
if (!in || !out) {
|
|
if (in) fclose(in);
|
|
if (out) fclose(out);
|
|
return -1;
|
|
}
|
|
|
|
ch = fgetc(in);
|
|
while (ch != EOF) {
|
|
nchar = fgetc(in);
|
|
|
|
if (nchar == ch) {
|
|
|
|
count++;
|
|
if (count == 127) {
|
|
fputc(count, out);
|
|
fputc(ch, out);
|
|
compr_size += 2;
|
|
count = 1;
|
|
ch = fgetc(in);
|
|
}
|
|
}
|
|
else {
|
|
if (count > 1) {
|
|
fputc(count, out);
|
|
fputc(ch, out);
|
|
compr_size += 2;
|
|
}
|
|
else {
|
|
int rizn = 1;
|
|
char buffer[127];
|
|
buffer[0] = ch;
|
|
|
|
while (nchar != EOF && nchar != ch && rizn < 127) {
|
|
buffer[rizn] = nchar;
|
|
rizn++;
|
|
ch = nchar;
|
|
nchar = fgetc(in);
|
|
}
|
|
|
|
fputc(0x80 | rizn, out);
|
|
compr_size += 1;
|
|
for (int i = 0; i < rizn; i++) {
|
|
fputc(buffer[i], out);
|
|
compr_size += 1;
|
|
}
|
|
}
|
|
count = 1;
|
|
ch = nchar;
|
|
}
|
|
}
|
|
|
|
fclose(in);
|
|
fclose(out);
|
|
return compr_size;
|
|
}
|
|
|
|
int decompress_2(const char* input_file, const char* output_file) {
|
|
int byte;
|
|
int compr_size = 0;
|
|
|
|
FILE* in = fopen(input_file, "rb");
|
|
FILE* out = fopen(output_file, "wb");
|
|
|
|
if (!in || !out) {
|
|
if (in) fclose(in);
|
|
if (out) fclose(out);
|
|
return -1;
|
|
}
|
|
|
|
while ((byte = fgetc(in)) != EOF) {
|
|
if (byte & 0x80) {
|
|
|
|
int count = byte & 0x7F;
|
|
for (int i = 0; i < count; i++) {
|
|
int ch = fgetc(in);
|
|
if (ch == EOF) break;
|
|
fputc(ch, out);
|
|
compr_size += 1;
|
|
}
|
|
}
|
|
else {
|
|
|
|
int count = byte;
|
|
int ch = fgetc(in);
|
|
for (int i = 0; i < count; i++) {
|
|
fputc(ch, out);
|
|
compr_size += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
fclose(in);
|
|
fclose(out);
|
|
return compr_size;
|
|
}
|
|
|