2024-12-24 18:40:18 +00:00
|
|
|
|
#include "compressor.h"
|
2024-12-24 15:08:56 +00:00
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
// --- Алгоритм Run-Length Encoding (RLE) ---
|
2024-12-24 15:08:56 +00:00
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
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;
|
2024-12-24 15:08:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
FILE *outfile = fopen(output_file_name, "wb");
|
|
|
|
|
if (!outfile) {
|
|
|
|
|
perror("Error opening output file");
|
|
|
|
|
fclose(infile);
|
|
|
|
|
return -1;
|
2024-12-24 15:08:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
unsigned char current_byte, previous_byte;
|
|
|
|
|
size_t count = 0;
|
|
|
|
|
|
|
|
|
|
// Читаємо перший байт
|
|
|
|
|
if (fread(&previous_byte, 1, 1, infile) != 1) {
|
|
|
|
|
fclose(infile);
|
|
|
|
|
fclose(outfile);
|
|
|
|
|
return 0; // Порожній файл
|
|
|
|
|
}
|
2024-12-24 15:08:56 +00:00
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
count = 1; // Ініціалізуємо лічильник
|
2024-12-24 15:08:56 +00:00
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
// Читаємо залишок файлу
|
|
|
|
|
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;
|
|
|
|
|
}
|
2024-12-24 15:08:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
// Записуємо останній символ
|
|
|
|
|
fwrite(&previous_byte, 1, 1, outfile);
|
|
|
|
|
fwrite(&count, 1, 1, outfile);
|
2024-12-24 15:08:56 +00:00
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
fclose(infile);
|
|
|
|
|
fclose(outfile);
|
|
|
|
|
|
|
|
|
|
return 1; // Повертаємо успішний результат
|
2024-12-24 15:08:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
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;
|
2024-12-24 15:08:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
FILE *outfile = fopen(output_file_name, "wb");
|
|
|
|
|
if (!outfile) {
|
|
|
|
|
perror("Error opening output file");
|
|
|
|
|
fclose(infile);
|
|
|
|
|
return -1;
|
2024-12-24 15:08:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
unsigned char current_byte;
|
|
|
|
|
size_t count;
|
2024-12-24 15:08:56 +00:00
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
// Декомпресія файлу
|
|
|
|
|
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);
|
2024-12-24 15:08:56 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
fclose(infile);
|
|
|
|
|
fclose(outfile);
|
2024-12-24 15:08:56 +00:00
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
return 1; // Повертаємо успішний результат
|
|
|
|
|
}
|
2024-12-24 15:08:56 +00:00
|
|
|
|
|
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
// --- Алгоритм Хаффмана (Huffman Coding) ---
|
2024-12-24 15:08:56 +00:00
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
// Структура для вузлів дерева Хаффмана
|
|
|
|
|
typedef struct {
|
|
|
|
|
unsigned char symbol;
|
|
|
|
|
size_t frequency;
|
|
|
|
|
} HuffmanSymbol;
|
2024-12-24 15:08:56 +00:00
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
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;
|
2024-12-24 15:08:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
// Створення дерева Хаффмана
|
|
|
|
|
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;
|
2024-12-24 15:08:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
size_t queue_size = n;
|
2024-12-24 15:08:56 +00:00
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
// Побудова дерева Хаффмана
|
|
|
|
|
while (queue_size > 1) {
|
|
|
|
|
// Зливаємо два найменші елементи
|
|
|
|
|
Node* left = queue[0];
|
|
|
|
|
Node* right = queue[1];
|
2024-12-24 15:08:56 +00:00
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
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);
|
2024-12-24 15:08:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
Node* root = queue[0];
|
|
|
|
|
free(queue);
|
|
|
|
|
|
|
|
|
|
return root;
|
2024-12-24 15:08:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
// Функція для стиснення з використанням дерева Хаффмана
|
|
|
|
|
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;
|
2024-12-24 15:08:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
fseek(infile, 0, SEEK_END);
|
|
|
|
|
size_t file_size = ftell(infile);
|
|
|
|
|
fseek(infile, 0, SEEK_SET);
|
2024-12-24 15:08:56 +00:00
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
unsigned char* buffer = malloc(file_size);
|
|
|
|
|
if (!buffer) {
|
|
|
|
|
fclose(infile);
|
|
|
|
|
return -1;
|
2024-12-24 15:08:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
fread(buffer, 1, file_size, infile);
|
|
|
|
|
fclose(infile);
|
2024-12-24 15:08:56 +00:00
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
// Підрахунок частоти кожного байта
|
|
|
|
|
size_t frequencies[256] = {0};
|
|
|
|
|
for (size_t i = 0; i < file_size; i++) {
|
|
|
|
|
frequencies[buffer[i]]++;
|
2024-12-24 15:08:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
HuffmanSymbol symbols[256];
|
|
|
|
|
size_t num_symbols = 0;
|
2024-12-24 15:08:56 +00:00
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
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++;
|
2024-12-24 15:08:56 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-24 18:40:18 +00:00
|
|
|
|
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;
|
2024-12-24 15:08:56 +00:00
|
|
|
|
}
|