From e463e2d1b0750285dff47bd7112617a2ef9b3164 Mon Sep 17 00:00:00 2001 From: Yevhen Kozirovskyi Date: Sun, 19 Jan 2025 14:10:47 +0000 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20sk1/compressor.c?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sk1/compressor.c | 275 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 273 insertions(+), 2 deletions(-) diff --git a/sk1/compressor.c b/sk1/compressor.c index aff0f25..8db8eff 100644 --- a/sk1/compressor.c +++ b/sk1/compressor.c @@ -1,4 +1,275 @@ -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); +#include +#include +#include + +#define MAX_TREE_HT 256 + +// A Huffman tree node +struct MinHeapNode { + unsigned char data; + unsigned freq; + struct MinHeapNode *left, *right; +}; + +// A MinHeap +struct MinHeap { + unsigned size; + unsigned capacity; + struct MinHeapNode** array; +}; + +// Function to create a new node +struct MinHeapNode* createNode(unsigned char data, unsigned freq) { + struct MinHeapNode* temp = (struct MinHeapNode*)malloc(sizeof(struct MinHeapNode)); + temp->data = data; + temp->freq = freq; + temp->left = temp->right = NULL; + return temp; +} + +// Function to create a MinHeap +struct MinHeap* createMinHeap(unsigned capacity) { + struct MinHeap* minHeap = (struct MinHeap*)malloc(sizeof(struct MinHeap)); + minHeap->size = 0; + minHeap->capacity = capacity; + minHeap->array = (struct MinHeapNode**)malloc(minHeap->capacity * sizeof(struct MinHeapNode*)); + return minHeap; +} + +// Swap function +void swapMinHeapNode(struct MinHeapNode** a, struct MinHeapNode** b) { + struct MinHeapNode* t = *a; + *a = *b; + *b = t; +} + +// MinHeapify function +void minHeapify(struct MinHeap* minHeap, int idx) { + int smallest = idx; + int left = 2 * idx + 1; + int right = 2 * idx + 2; + + if (left < minHeap->size && minHeap->array[left]->freq < minHeap->array[smallest]->freq) + smallest = left; + + if (right < minHeap->size && minHeap->array[right]->freq < minHeap->array[smallest]->freq) + smallest = right; + + if (smallest != idx) { + swapMinHeapNode(&minHeap->array[smallest], &minHeap->array[idx]); + minHeapify(minHeap, smallest); + } +} + +// Extract minimum value node from heap +struct MinHeapNode* extractMin(struct MinHeap* minHeap) { + struct MinHeapNode* temp = minHeap->array[0]; + minHeap->array[0] = minHeap->array[minHeap->size - 1]; + --minHeap->size; + minHeapify(minHeap, 0); + return temp; +} + +// Insert a new node to MinHeap +void insertMinHeap(struct MinHeap* minHeap, struct MinHeapNode* minHeapNode) { + ++minHeap->size; + int i = minHeap->size - 1; + while (i && minHeapNode->freq < minHeap->array[(i - 1) / 2]->freq) { + minHeap->array[i] = minHeap->array[(i - 1) / 2]; + i = (i - 1) / 2; + } + minHeap->array[i] = minHeapNode; +} + +// Build the MinHeap +void buildMinHeap(struct MinHeap* minHeap) { + int n = minHeap->size - 1; + for (int i = (n - 1) / 2; i >= 0; --i) + minHeapify(minHeap, i); +} + +// Check if size is 1 +int isSizeOne(struct MinHeap* minHeap) { + return (minHeap->size == 1); +} + +// Create and build a MinHeap +struct MinHeap* createAndBuildMinHeap(unsigned char data[], int freq[], int size) { + struct MinHeap* minHeap = createMinHeap(size); + for (int i = 0; i < size; ++i) + minHeap->array[i] = createNode(data[i], freq[i]); + minHeap->size = size; + buildMinHeap(minHeap); + return minHeap; +} + +// Build Huffman Tree +struct MinHeapNode* buildHuffmanTree(unsigned char data[], int freq[], int size) { + struct MinHeapNode *left, *right, *top; + struct MinHeap* minHeap = createAndBuildMinHeap(data, freq, size); + + while (!isSizeOne(minHeap)) { + left = extractMin(minHeap); + right = extractMin(minHeap); + + top = createNode('$', left->freq + right->freq); + top->left = left; + top->right = right; + + insertMinHeap(minHeap, top); + } + return extractMin(minHeap); +} + +// Print Huffman Codes to a map +void storeCodes(struct MinHeapNode* root, char** codes, char* currentCode, int top) { + if (root->left) { + currentCode[top] = '0'; + storeCodes(root->left, codes, currentCode, top + 1); + } + if (root->right) { + currentCode[top] = '1'; + storeCodes(root->right, codes, currentCode, top + 1); + } + if (!(root->left) && !(root->right)) { + currentCode[top] = '\0'; + codes[root->data] = strdup(currentCode); + } +} +// Compress the input file using Huffman Coding +int compressFile(const char* input_file_name, const char* output_file_name) { + FILE* inputFile = fopen(input_file_name, "rb"); + if (!inputFile) { + perror("Error opening input file"); + return -1; + } + + int freq[256] = {0}; + unsigned char buffer; + + // Count frequency of each byte + while (fread(&buffer, sizeof(unsigned char), 1, inputFile)) { + freq[buffer]++; + } + rewind(inputFile); + + unsigned char data[256]; + int frequencies[256], size = 0; + for (int i = 0; i < 256; i++) { + if (freq[i] > 0) { + data[size] = (unsigned char)i; + frequencies[size] = freq[i]; + size++; + } + } + + struct MinHeapNode* root = buildHuffmanTree(data, frequencies, size); + char* codes[256] = {0}; + char currentCode[MAX_TREE_HT]; + storeCodes(root, codes, currentCode, 0); + + FILE* outputFile = fopen(output_file_name, "wb"); + if (!outputFile) { + perror("Error opening output file"); + fclose(inputFile); + return -1; + } + + // Write codes to output file + fwrite(freq, sizeof(int), 256, outputFile); + + unsigned char byte = 0; + int bitCount = 0; + while (fread(&buffer, sizeof(unsigned char), 1, inputFile)) { + char* code = codes[buffer]; + for (int i = 0; code[i] != '\0'; i++) { + byte = (byte << 1) | (code[i] - '0'); + bitCount++; + if (bitCount == 8) { + fwrite(&byte, sizeof(unsigned char), 1, outputFile); + byte = 0; + bitCount = 0; + } + } + } + if (bitCount > 0) { + byte <<= (8 - bitCount); + fwrite(&byte, sizeof(unsigned char), 1, outputFile); + } + + fclose(inputFile); + fclose(outputFile); + return 0; +} + +// Decompress the file +int decompressFile(const char* input_file_name, const char* output_file_name) { + FILE* inputFile = fopen(input_file_name, "rb"); + if (!inputFile) { + perror("Error opening input file"); + return -1; + } + + int freq[256]; + fread(freq, sizeof(int), 256, inputFile); + + unsigned char data[256]; + int frequencies[256], size = 0; + for (int i = 0; i < 256; i++) { + if (freq[i] > 0) { + data[size] = (unsigned char)i; + frequencies[size] = freq[i]; + size++; + } + } + + struct MinHeapNode* root = buildHuffmanTree(data, frequencies, size); + + FILE* outputFile = fopen(output_file_name, "wb"); + if (!outputFile) { + perror("Error opening output file"); + fclose(inputFile); + return -1; + } + + struct MinHeapNode* current = root; + unsigned char buffer; + int bitCount = 0; + while (fread(&buffer, sizeof(unsigned char), 1, inputFile)) { + for (int i = 7; i >= 0; i--) { + int bit = (buffer >> i) & 1; + if (bit == 0) + current = current->left; + else + current = current->right; + + if (!(current->left) && !(current->right)) { + fwrite(¤t->data, sizeof(unsigned char), 1, outputFile); + current = root; + } + } + } + + fclose(inputFile); + fclose(outputFile); + return 0; +} + + + +int compress_1(const char* input_file_name, const char* output_file_name){ + if(compressFile(input_file_name, output_file_name) == 0){ + printf("Succsses!"); + } + return 0; +} + +int decompress_1(const char* input_file_name, const char* output_file_name){ + if(decompressFile(input_file_name, output_file_name) == 0){ + printf("Succsses!"); + } + return 0; + +} 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); \ No newline at end of file