From a33cf7a158827599878286fb8822000e836de24c Mon Sep 17 00:00:00 2001 From: VIliam Date: Sun, 19 Jan 2025 19:46:52 +0100 Subject: [PATCH] skuska --- sk1/Makefile | 0 sk1/README.md | 0 sk1/compressor.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++ sk1/compressor.h | 36 ++++++++++ sk1/main.c | 50 +++++++++++++ 5 files changed, 264 insertions(+) create mode 100644 sk1/Makefile create mode 100644 sk1/README.md create mode 100644 sk1/compressor.c create mode 100644 sk1/compressor.h create mode 100644 sk1/main.c diff --git a/sk1/Makefile b/sk1/Makefile new file mode 100644 index 0000000..e69de29 diff --git a/sk1/README.md b/sk1/README.md new file mode 100644 index 0000000..e69de29 diff --git a/sk1/compressor.c b/sk1/compressor.c new file mode 100644 index 0000000..c187d78 --- /dev/null +++ b/sk1/compressor.c @@ -0,0 +1,178 @@ +#include "compressor.h" +#include +#include +#include + +unsigned char* read_file(const char* file_name, size_t* size) { + FILE* file = fopen(file_name, "rb"); + if (!file) { + perror("Error opening file"); + return NULL; + } + + fseek(file, 0, SEEK_END); + *size = ftell(file); + rewind(file); + + unsigned char* buffer = (unsigned char*)malloc(*size); + if (!buffer) { + perror("Memory allocation error"); + fclose(file); + return NULL; + } + + fread(buffer, 1, *size, file); + fclose(file); + return buffer; +} + +int write_file(const char* file_name, const unsigned char* buffer, size_t size) { + FILE* file = fopen(file_name, "wb"); + if (!file) { + perror("Error opening file"); + return -1; + } + + fwrite(buffer, 1, size, file); + fclose(file); + return 0; +} + +HuffmanNode* build_huffman_tree(const unsigned char* data, size_t size) { + size_t frequencies[256] = {0}; + + for (size_t i = 0; i < size; i++) { + frequencies[data[i]]++; + } + + HuffmanNode* nodes[256]; + int node_count = 0; + + for (int i = 0; i < 256; i++) { + if (frequencies[i] > 0) { + HuffmanNode* node = (HuffmanNode*)malloc(sizeof(HuffmanNode)); + node->symbol = (unsigned char)i; + node->frequency = frequencies[i]; + node->left = NULL; + node->right = NULL; + nodes[node_count++] = node; + } + } + + while (node_count > 1) { + + int min1 = 0, min2 = 1; + if (nodes[min2]->frequency < nodes[min1]->frequency) { + min1 = 1; + min2 = 0; + } + + for (int i = 2; i < node_count; i++) { + if (nodes[i]->frequency < nodes[min1]->frequency) { + min2 = min1; + min1 = i; + } else if (nodes[i]->frequency < nodes[min2]->frequency) { + min2 = i; + } + } + + HuffmanNode* new_node = (HuffmanNode*)malloc(sizeof(HuffmanNode)); + new_node->symbol = 0; + new_node->frequency = nodes[min1]->frequency + nodes[min2]->frequency; + new_node->left = nodes[min1]; + new_node->right = nodes[min2]; + + nodes[min1] = new_node; + nodes[min2] = nodes[node_count - 1]; + node_count--; + } + + return nodes[0]; +} + +void generate_huffman_codes(HuffmanNode* root, char** codes, char* buffer, int depth) { + if (!root->left && !root->right) { + buffer[depth] = '\0'; + codes[root->symbol] = strdup(buffer); + return; + } + + if (root->left) { + buffer[depth] = '0'; + generate_huffman_codes(root->left, codes, buffer, depth + 1); + } + + if (root->right) { + buffer[depth] = '1'; + generate_huffman_codes(root->right, codes, buffer, depth + 1); + } +} + +void free_huffman_tree(HuffmanNode* root) { + if (!root) return; + free_huffman_tree(root->left); + free_huffman_tree(root->right); + free(root); +} + +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); + return -1; + } + + char* codes[256] = {0}; + char buffer[256]; + generate_huffman_codes(root, codes, buffer, 0); + + printf("Compressing using Huffman coding...\n"); + + for (int i = 0; i < 256; i++) { + if (codes[i]) free(codes[i]); + } + free_huffman_tree(root); + free(data); + + return 0; +} + +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; + + printf("Decompressing using Huffman coding...\n"); + + 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) { + size_t size; + unsigned char* data = read_file(input_file_name, &size); + if (!data) return -1; + + printf("Compressing using Algorithm 2 (LZ77)...\n"); + + int result = write_file(output_file_name, data, size); + free(data); + return result; +} + +int decompress_2(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; + + printf("Decompressing using Algorithm 2 (LZ77)...\n"); + + int result = write_file(output_file_name, data, size); + free(data); + return result; +} \ No newline at end of file diff --git a/sk1/compressor.h b/sk1/compressor.h new file mode 100644 index 0000000..a19d247 --- /dev/null +++ b/sk1/compressor.h @@ -0,0 +1,36 @@ +#include +#include +#include + +#ifndef COMPRESSOR_H +#define COMPRESSOR_H + + + +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 compress_2(const char* input_file_name, const char* output_file_name); + +int decompress_2(const char* input_file_name, const char* output_file_name); + +unsigned char* read_file(const char* file_name, size_t* size); + +int write_file(const char* file_name, const unsigned char* buffer, size_t size); + + +typedef struct HuffmanNode { + unsigned char symbol; + size_t frequency; + struct HuffmanNode* left; + struct HuffmanNode* right; +} HuffmanNode; + +HuffmanNode* build_huffman_tree(const unsigned char* data, size_t size); + +void generate_huffman_codes(HuffmanNode* root, char** codes, char* buffer, int depth); + +void free_huffman_tree(HuffmanNode* root); + +#endif \ No newline at end of file diff --git a/sk1/main.c b/sk1/main.c new file mode 100644 index 0000000..6b8b607 --- /dev/null +++ b/sk1/main.c @@ -0,0 +1,50 @@ +#include "compressor.h" +#include +#include + +void print_help() { + printf("Usage:\n"); + printf(" ./compressor -c infile outfile Compress using default algorithm (Huffman)\n"); + printf(" ./compressor -d infile outfile Decompress using default algorithm (Huffman)\n"); + printf(" ./compressor -h Print help\n"); +} + +int main(int argc, char* argv[]) { + if (argc < 2) { + print_help(); + return 1; + } + + if (strcmp(argv[1], "-h") == 0) { + print_help(); + return 0; + } + + if (argc != 4) { + fprintf(stderr, "Error: Invalid number of arguments.\n"); + print_help(); + return 1; + } + + const char* input_file = argv[2]; + const char* output_file = argv[3]; + int result = -1; + + if (strcmp(argv[1], "-c") == 0) { + result = compress_1(input_file, output_file); + } else if (strcmp(argv[1], "-d") == 0) { + result = decompress_1(input_file, output_file); + } else { + fprintf(stderr, "Error: Unknown option '%s'.\n", argv[1]); + print_help(); + return 1; + } + + if (result < 0) { + fprintf(stderr, "Error: Operation failed.\n"); + return 1; + } + + printf("Operation completed successfully.\n"); + return 0; +} \ No newline at end of file