huffman编码图片压缩C语言
时间: 2023-07-10 12:34:43 浏览: 188
用Huffman编码对文件进行压缩的C语言实现
Huffman编码是一种基于概率的无损数据压缩算法,可以用于压缩各种类型的数据,包括图片。下面是一个简单的C语言实现Huffman编码图片压缩的示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_TREE_HT 100
typedef struct node {
unsigned char data;
unsigned freq;
struct node *left, *right;
} node;
typedef struct heap {
unsigned size;
unsigned capacity;
node **array;
} heap;
typedef struct huff_code {
unsigned char data;
char *code;
} huff_code;
node *new_node(unsigned char data, unsigned freq)
{
node *temp = (node *)malloc(sizeof(node));
temp->left = temp->right = NULL;
temp->data = data;
temp->freq = freq;
return temp;
}
heap *new_heap(unsigned capacity)
{
heap *temp = (heap *)malloc(sizeof(heap));
temp->size = 0;
temp->capacity = capacity;
temp->array = (node **)malloc(capacity * sizeof(node *));
return temp;
}
void swap_node(node **a, node **b)
{
node *temp = *a;
*a = *b;
*b = temp;
}
void min_heapify(heap *h, int idx)
{
int smallest = idx;
int left = 2 * idx + 1;
int right = 2 * idx + 2;
if (left < h->size && h->array[left]->freq < h->array[smallest]->freq)
smallest = left;
if (right < h->size && h->array[right]->freq < h->array[smallest]->freq)
smallest = right;
if (smallest != idx) {
swap_node(&h->array[smallest], &h->array[idx]);
min_heapify(h, smallest);
}
}
node *extract_min(heap *h)
{
node *temp = h->array[0];
h->array[0] = h->array[h->size - 1];
--h->size;
min_heapify(h, 0);
return temp;
}
void insert_heap(heap *h, node *temp)
{
++h->size;
int i = h->size - 1;
while (i && temp->freq < h->array[(i - 1) / 2]->freq) {
h->array[i] = h->array[(i - 1) / 2];
i = (i - 1) / 2;
}
h->array[i] = temp;
}
void build_heap(heap *h)
{
int n = h->size - 1;
int i;
for (i = (n - 1) / 2; i >= 0; --i)
min_heapify(h, i);
}
int is_leaf(node *root)
{
return !(root->left) && !(root->right);
}
heap *create_heap(char *data, int *freq, int size)
{
heap *h = new_heap(size);
int i;
for (i = 0; i < size; ++i)
h->array[i] = new_node(data[i], freq[i]);
h->size = size;
build_heap(h);
return h;
}
node *build_huffman_tree(char *data, int *freq, int size)
{
node *left, *right, *top;
heap *h = create_heap(data, freq, size);
while (h->size > 1) {
left = extract_min(h);
right = extract_min(h);
top = new_node('$', left->freq + right->freq);
top->left = left;
top->right = right;
insert_heap(h, top);
}
return extract_min(h);
}
void print_codes(node *root, char *code, int top, huff_code *h_codes)
{
if (root->left) {
code[top] = '0';
print_codes(root->left, code, top + 1, h_codes);
}
if (root->right) {
code[top] = '1';
print_codes(root->right, code, top + 1, h_codes);
}
if (is_leaf(root)) {
h_codes[root->data].data = root->data;
h_codes[root->data].code = (char *)malloc((top + 1) * sizeof(char));
memcpy(h_codes[root->data].code, code, top);
h_codes[root->data].code[top] = '\0';
}
}
void encode_image(char *image_path, huff_code *h_codes)
{
FILE *fp = fopen(image_path, "rb");
if (!fp) {
printf("Error opening file %s\n", image_path);
exit(1);
}
fseek(fp, 0L, SEEK_END);
int file_size = ftell(fp);
fseek(fp, 0L, SEEK_SET);
char *image_data = (char *)malloc(file_size * sizeof(char));
fread(image_data, sizeof(char), file_size, fp);
fclose(fp);
int freq[256] = {0};
int i;
for (i = 0; i < file_size; ++i)
++freq[(unsigned char)image_data[i]];
node *root = build_huffman_tree(image_data, freq, 256);
char code[MAX_TREE_HT];
print_codes(root, code, 0, h_codes);
}
void write_codes_to_file(huff_code *h_codes, char *output_file)
{
FILE *fp = fopen(output_file, "wb");
if (!fp) {
printf("Error opening file %s\n", output_file);
exit(1);
}
int i;
fwrite(&h_codes[0].data, sizeof(unsigned char), 1, fp);
for (i = 0; i < 256; ++i) {
if (h_codes[i].code) {
fwrite(&h_codes[i].data, sizeof(unsigned char), 1, fp);
unsigned char code_len = strlen(h_codes[i].code);
fwrite(&code_len, sizeof(unsigned char), 1, fp);
fwrite(h_codes[i].code, sizeof(char), strlen(h_codes[i].code), fp);
}
}
fclose(fp);
}
int main(int argc, char *argv[])
{
char *image_path = argv[1];
char *output_file = argv[2];
huff_code h_codes[256] = {0};
encode_image(image_path, h_codes);
write_codes_to_file(h_codes, output_file);
return 0;
}
```
该代码实现了将指定路径的图片进行Huffman编码压缩,并将压缩后的编码写入指定的输出文件中。其中,`encode_image()`函数用于对图片进行编码,`write_codes_to_file()`函数用于将编码写入文件中。需要注意的是,该代码只实现了压缩部分,解压缩部分需要另外实现。
阅读全文