skuska
This commit is contained in:
parent
76c9eef337
commit
3019edfe78
@ -115,12 +115,35 @@ void free_huffman_tree(HuffmanNode* root) {
|
|||||||
free(root);
|
free(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void write_bits(FILE* file, const char* bits, unsigned char* buffer, int* bit_pos) {
|
||||||
|
for (int i = 0; bits[i] != '\0'; i++) {
|
||||||
|
if (bits[i] == '1') {
|
||||||
|
buffer[*bit_pos / 8] |= (1 << (7 - (*bit_pos % 8)));
|
||||||
|
}
|
||||||
|
(*bit_pos)++;
|
||||||
|
if (*bit_pos % 8 == 0) {
|
||||||
|
fwrite(buffer, 1, 1, file);
|
||||||
|
buffer[*bit_pos / 8 - 1] = 0; // Clear the written byte
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_bit(FILE* file, unsigned char* buffer, int* bit_pos) {
|
||||||
|
if (*bit_pos % 8 == 0) {
|
||||||
|
if (fread(buffer, 1, 1, file) != 1) return -1;
|
||||||
|
}
|
||||||
|
int bit = (*buffer >> (7 - (*bit_pos % 8))) & 1;
|
||||||
|
(*bit_pos)++;
|
||||||
|
return bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int compress_1(const char* input_file_name, const char* output_file_name) {
|
int compress_1(const char* input_file_name, const char* output_file_name) {
|
||||||
size_t size;
|
size_t size;
|
||||||
unsigned char* data = read_file(input_file_name, &size);
|
unsigned char* data = read_file(input_file_name, &size);
|
||||||
if (!data) return -1;
|
if (!data) return -1;
|
||||||
|
|
||||||
|
|
||||||
HuffmanNode* root = build_huffman_tree(data, size);
|
HuffmanNode* root = build_huffman_tree(data, size);
|
||||||
if (!root) {
|
if (!root) {
|
||||||
free(data);
|
free(data);
|
||||||
@ -142,18 +165,25 @@ int compress_1(const char* input_file_name, const char* output_file_name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
serialize_tree(root, output_file);
|
||||||
|
|
||||||
|
|
||||||
|
unsigned char bit_buffer[1] = {0};
|
||||||
|
int bit_pos = 0;
|
||||||
for (size_t i = 0; i < size; i++) {
|
for (size_t i = 0; i < size; i++) {
|
||||||
fputs(codes[data[i]], output_file);
|
write_bits(output_file, codes[data[i]], bit_buffer, &bit_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (bit_pos % 8 != 0) {
|
||||||
|
fwrite(bit_buffer, 1, 1, output_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(output_file);
|
fclose(output_file);
|
||||||
|
|
||||||
printf("Compressing using Huffman coding...\n");
|
printf("Compressing using Huffman coding...\n");
|
||||||
|
|
||||||
// Clean up
|
|
||||||
for (int i = 0; i < 256; i++) {
|
for (int i = 0; i < 256; i++) {
|
||||||
if (codes[i]) free(codes[i]);
|
if (codes[i]) free(codes[i]);
|
||||||
}
|
}
|
||||||
@ -164,18 +194,55 @@ int compress_1(const char* input_file_name, const char* output_file_name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int decompress_1(const char* input_file_name, const char* output_file_name) {
|
int decompress_1(const char* input_file_name, const char* output_file_name) {
|
||||||
size_t size;
|
FILE* input_file = fopen(input_file_name, "rb");
|
||||||
unsigned char* data = read_file(input_file_name, &size);
|
if (!input_file) {
|
||||||
if (!data) return -1;
|
perror("Error opening input file");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* output_file = fopen(output_file_name, "wb");
|
||||||
|
if (!output_file) {
|
||||||
|
perror("Error opening output file");
|
||||||
|
fclose(input_file);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HuffmanNode* root = deserialize_tree(input_file);
|
||||||
|
if (!root) {
|
||||||
|
fclose(input_file);
|
||||||
|
fclose(output_file);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned char bit_buffer[1];
|
||||||
|
int bit_pos = 0;
|
||||||
|
HuffmanNode* current = root;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
int bit = read_bit(input_file, bit_buffer, &bit_pos);
|
||||||
|
if (bit == -1) break;
|
||||||
|
|
||||||
|
current = (bit == 0) ? current->left : current->right;
|
||||||
|
|
||||||
|
if (!current->left && !current->right) {
|
||||||
|
fputc(current->symbol, output_file);
|
||||||
|
current = root;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(input_file);
|
||||||
|
fclose(output_file);
|
||||||
|
free_huffman_tree(root);
|
||||||
|
|
||||||
printf("Decompressing using Huffman coding...\n");
|
printf("Decompressing using Huffman coding...\n");
|
||||||
|
return 0;
|
||||||
int result = write_file(output_file_name, data, size);
|
|
||||||
free(data);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int compress_2(const char* input_file_name, const char* output_file_name) {
|
int compress_2(const char* input_file_name, const char* output_file_name) {
|
||||||
size_t size;
|
size_t size;
|
||||||
unsigned char* data = read_file(input_file_name, &size);
|
unsigned char* data = read_file(input_file_name, &size);
|
||||||
|
Loading…
Reference in New Issue
Block a user