diff --git a/sk1/compressor.c b/sk1/compressor.c index 29d9da2..e553728 100644 --- a/sk1/compressor.c +++ b/sk1/compressor.c @@ -115,12 +115,35 @@ void free_huffman_tree(HuffmanNode* 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) { size_t size; unsigned char* data = read_file(input_file_name, &size); if (!data) return -1; - + HuffmanNode* root = build_huffman_tree(data, size); if (!root) { 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++) { - 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); printf("Compressing using Huffman coding...\n"); - // Clean up + for (int i = 0; i < 256; 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) { - size_t size; - unsigned char* data = read_file(input_file_name, &size); - if (!data) return -1; + FILE* input_file = fopen(input_file_name, "rb"); + if (!input_file) { + 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"); - - int result = write_file(output_file_name, data, size); - free(data); - return result; + return 0; } + int compress_2(const char* input_file_name, const char* output_file_name) { size_t size; unsigned char* data = read_file(input_file_name, &size);