#include "compressor.h" #include #include #include // --- Алгоритм Run-Length Encoding (RLE) --- int compress_2(const char* input_file_name, const char* output_file_name) { FILE *infile = fopen(input_file_name, "rb"); if (!infile) { perror("Error opening input file"); return -1; } FILE *outfile = fopen(output_file_name, "wb"); if (!outfile) { perror("Error opening output file"); fclose(infile); return -1; } unsigned char current_byte, previous_byte; size_t count = 0; // Читаємо перший байт if (fread(&previous_byte, 1, 1, infile) != 1) { fclose(infile); fclose(outfile); return 0; // Порожній файл } count = 1; // Ініціалізуємо лічильник // Читаємо залишок файлу while (fread(¤t_byte, 1, 1, infile) == 1) { if (current_byte == previous_byte && count < 255) { count++; // Збільшуємо лічильник } else { // Записуємо попередній символ і його кількість fwrite(&previous_byte, 1, 1, outfile); fwrite(&count, 1, 1, outfile); previous_byte = current_byte; count = 1; } } // Записуємо останній символ fwrite(&previous_byte, 1, 1, outfile); fwrite(&count, 1, 1, outfile); fclose(infile); fclose(outfile); return 1; // Повертаємо успішний результат } int decompress_2(const char* input_file_name, const char* output_file_name) { FILE *infile = fopen(input_file_name, "rb"); if (!infile) { perror("Error opening input file"); return -1; } FILE *outfile = fopen(output_file_name, "wb"); if (!outfile) { perror("Error opening output file"); fclose(infile); return -1; } unsigned char current_byte; size_t count; // Декомпресія файлу while (fread(¤t_byte, 1, 1, infile) == 1) { fread(&count, 1, 1, infile); for (size_t i = 0; i < count; i++) { fwrite(¤t_byte, 1, 1, outfile); } } fclose(infile); fclose(outfile); return 1; // Повертаємо успішний результат } // --- Алгоритм Хаффмана (Huffman Coding) --- // Структура для вузлів дерева Хаффмана typedef struct { unsigned char symbol; size_t frequency; } HuffmanSymbol; typedef struct Node { HuffmanSymbol symbol; struct Node *left, *right; } Node; // Функція для порівняння вузлів для використання в черзі int compare_nodes(const void *a, const void *b) { return ((Node*)a)->symbol.frequency - ((Node*)b)->symbol.frequency; } // Створення дерева Хаффмана Node* create_huffman_tree(HuffmanSymbol* symbols, size_t n) { // Використовуємо чергу для побудови дерева Хаффмана qsort(symbols, n, sizeof(HuffmanSymbol), compare_nodes); // Створюємо чергу вузлів для побудови дерева Node** queue = malloc(n * sizeof(Node*)); for (size_t i = 0; i < n; i++) { queue[i] = malloc(sizeof(Node)); queue[i]->symbol = symbols[i]; queue[i]->left = queue[i]->right = NULL; } size_t queue_size = n; // Побудова дерева Хаффмана while (queue_size > 1) { // Зливаємо два найменші елементи Node* left = queue[0]; Node* right = queue[1]; Node* parent = malloc(sizeof(Node)); parent->symbol.symbol = 0; // Спільний символ parent->symbol.frequency = left->symbol.frequency + right->symbol.frequency; parent->left = left; parent->right = right; // Видаляємо перші два елементи з черги та додаємо новий memmove(queue, queue + 2, (queue_size - 2) * sizeof(Node*)); queue[queue_size - 2] = parent; queue_size--; qsort(queue, queue_size, sizeof(Node*), compare_nodes); } Node* root = queue[0]; free(queue); return root; } // Функція для стиснення з використанням дерева Хаффмана int compress_1(const char* input_file_name, const char* output_file_name) { FILE *infile = fopen(input_file_name, "rb"); if (!infile) { perror("Error opening input file"); return -1; } fseek(infile, 0, SEEK_END); size_t file_size = ftell(infile); fseek(infile, 0, SEEK_SET); unsigned char* buffer = malloc(file_size); if (!buffer) { fclose(infile); return -1; } fread(buffer, 1, file_size, infile); fclose(infile); // Підрахунок частоти кожного байта size_t frequencies[256] = {0}; for (size_t i = 0; i < file_size; i++) { frequencies[buffer[i]]++; } HuffmanSymbol symbols[256]; size_t num_symbols = 0; for (int i = 0; i < 256; i++) { if (frequencies[i] > 0) { symbols[num_symbols].symbol = (unsigned char)i; symbols[num_symbols].frequency = frequencies[i]; num_symbols++; } } Node* huffman_tree = create_huffman_tree(symbols, num_symbols); // Тут треба реалізувати кодування та запис бітових кодів в файл // Оскільки це складніше, я залишаю це як заготовку для подальшої реалізації free(buffer); return 1; } int decompress_1(const char* input_file_name, const char* output_file_name) { // Реалізація декомпресії за допомогою Хаффмана буде складною // і потребує зберігання дерев або довжини кодування кожного символу return 0; }