#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 Node { unsigned char symbol; size_t frequency; struct Node *left, *right; } Node; // Структура для кодів Хаффмана typedef struct { unsigned char symbol; char *code; } HuffmanCode; // Функція для порівняння вузлів для використання в черзі int compare_nodes(const void *a, const void *b) { return ((Node*)a)->frequency - ((Node*)b)->frequency; } // Створення дерева Хаффмана Node* create_huffman_tree(unsigned char *data, size_t size) { size_t freq[256] = {0}; for (size_t i = 0; i < size; i++) { freq[data[i]]++; } // Створюємо список вузлів Node *nodes[256]; size_t node_count = 0; for (int i = 0; i < 256; i++) { if (freq[i] > 0) { nodes[node_count] = malloc(sizeof(Node)); nodes[node_count]->symbol = (unsigned char)i; nodes[node_count]->frequency = freq[i]; nodes[node_count]->left = nodes[node_count]->right = NULL; node_count++; } } // Сортуємо вузли по частоті qsort(nodes, node_count, sizeof(Node*), compare_nodes); // Побудова дерева while (node_count > 1) { Node* left = nodes[0]; Node* right = nodes[1]; Node* parent = malloc(sizeof(Node)); parent->symbol = 0; parent->frequency = left->frequency + right->frequency; parent->left = left; parent->right = right; // Зміщуємо вузли в черзі memmove(nodes, nodes + 2, (node_count - 2) * sizeof(Node*)); nodes[node_count - 2] = parent; node_count--; qsort(nodes, node_count, sizeof(Node*), compare_nodes); } return nodes[0]; // Повертаємо корінь дерева } // Функція для рекурсивного запису бітових кодів з дерева Хаффмана void generate_huffman_codes(Node* root, HuffmanCode* codes, char* current_code, int depth) { if (!root) return; if (root->left == NULL && root->right == NULL) { current_code[depth] = '\0'; codes[root->symbol].symbol = root->symbol; codes[root->symbol].code = strdup(current_code); } current_code[depth] = '0'; generate_huffman_codes(root->left, codes, current_code, depth + 1); current_code[depth] = '1'; generate_huffman_codes(root->right, codes, current_code, depth + 1); } // Функція для стиснення за допомогою Хаффмана 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* data = malloc(file_size); if (!data) { fclose(infile); return -1; } fread(data, 1, file_size, infile); fclose(infile); // Створюємо дерево Хаффмана Node* root = create_huffman_tree(data, file_size); // Генерація кодів Хаффмана HuffmanCode codes[256]; for (int i = 0; i < 256; i++) { codes[i].code = NULL; } char current_code[256]; generate_huffman_codes(root, codes, current_code, 0); // Стиснення даних FILE *outfile = fopen(output_file_name, "wb"); if (!outfile) { free(data); return -1; } for (size_t i = 0; i < file_size; i++) { unsigned char symbol = data[i]; const char* code = codes[symbol].code; for (size_t j = 0; code[j] != '\0'; j++) { // Записуємо біт в файл fputc(code[j] == '1' ? 1 : 0, outfile); } } fclose(outfile); free(data); return 1; // Повертаємо успішний результат } // Функція для декомпресії за допомогою Хаффмана int decompress_1(const char* input_file_name, const char* output_file_name) { // Декомпресія за допомогою Хаффмана потребує відновлення дерева та розшифровки бітових кодів return 0; // Не реалізовано повністю }