Skip to content

Commit 82a3be1

Browse files
committed
added improved huffman for image
1 parent 651b9aa commit 82a3be1

File tree

1 file changed

+145
-0
lines changed

1 file changed

+145
-0
lines changed

improved-huffman_image.cpp

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
#include <bits/stdc++.h>
2+
using namespace std;
3+
#define STB_IMAGE_IMPLEMENTATION
4+
#include "stb_image.h"
5+
6+
struct pixel{
7+
float freq;
8+
int label;
9+
pixel* left, *right;
10+
11+
pixel(int x, float y): label(x), freq(y){
12+
left = NULL;
13+
right = NULL;
14+
}
15+
16+
void print(){
17+
cout << label << " " << freq << endl;
18+
}
19+
};
20+
21+
struct huffcode{
22+
int label;
23+
int parent;
24+
string code;
25+
};
26+
27+
struct compare{
28+
bool operator() (pixel* a, pixel* b){
29+
return a->freq > b->freq;
30+
}
31+
};
32+
33+
huffcode codes[256];
34+
35+
void preoder(pixel* root, string s, int level, int parent){
36+
if(root->label < 256){
37+
codes[root->label].parent = parent;
38+
codes[root->label].code = s;
39+
cout << setfill(' ') << setw(3) << root->label
40+
<< " -> " << setw(20) << s << setw(4) << codes[root->label].parent << setw(20)<< fixed << setprecision(10) << root->freq << endl;
41+
return;
42+
}
43+
// out << root->label << " -> " << root->left->label << " [ label = \"" << s+'0' << "\"];"<<endl;
44+
// out << root->label << " -> " << root->right->label << " [ label = \"" << s+'1' << "\"];" << endl;
45+
46+
if(level == 3)
47+
parent = root->label;
48+
49+
preoder(root->left , s + '0', level+1, parent);
50+
preoder(root->right, s + '1', level+1, parent);
51+
52+
return;
53+
}
54+
55+
56+
57+
int main()
58+
{
59+
int width, height, bpp;
60+
61+
uint8_t* rgb_image = stbi_load("colombia.jpg", &width, &height, &bpp, 1);
62+
63+
int image[height][width];
64+
int itr = 0;
65+
for (int i = 0; i < height; ++i)
66+
for (int j = 0; j < width; ++j)
67+
image[i][j] = rgb_image[itr++];
68+
69+
stbi_image_free(rgb_image);
70+
71+
int hist[256] = {0};
72+
73+
for (int i = 0; i < height; i++)
74+
for (int j = 0; j < width; j++)
75+
hist[image[i][j]] += 1;
76+
77+
int totpix = height*width;
78+
79+
float freq[256] = {0};
80+
81+
for (int i = 0; i < 256; ++i)
82+
freq[i] = ((float)hist[i])/totpix;
83+
84+
85+
86+
priority_queue<pixel*, vector<pixel*>, compare> pq;
87+
88+
for(int i = 0; i < 256; i++){
89+
if (freq[i] > 0){
90+
pixel* tmp = new pixel(i, freq[i]);
91+
pq.push(tmp);
92+
}
93+
}
94+
95+
int cnt = 256;
96+
while(pq.size() > 1){
97+
pixel* first = pq.top();
98+
pq.pop();
99+
pixel* second = pq.top();
100+
pq.pop();
101+
pixel* tmp = new pixel(cnt++, first->freq + second->freq);
102+
tmp->left = first;
103+
tmp->right = second;
104+
pq.push(tmp);
105+
}
106+
107+
pixel* root = pq.top();
108+
109+
preoder(root, "", 0, -1);
110+
111+
112+
int compression_size = 0;
113+
int last = -1;
114+
bool f = 0;
115+
for (int i = 0; i < height; ++i)
116+
{
117+
for (int j = 0; j < width; ++j)
118+
{
119+
if(f == 0){
120+
compression_size += codes[image[i][j]].code.size();
121+
}
122+
else if(codes[image[i][j]].parent == codes[last].parent){
123+
compression_size += 1;
124+
string code = codes[image[i][j]].code;
125+
compression_size += code.substr(3, code.length()).size();
126+
}
127+
else{
128+
compression_size += 1;
129+
compression_size += codes[image[i][j]].code.size();
130+
}
131+
if(codes[image[i][j]].parent == -1)
132+
f = 0;
133+
else{
134+
last = image[i][j];
135+
f = 1;
136+
}
137+
}
138+
}
139+
140+
cout << compression_size << " " << 256*256*8 << endl;
141+
142+
143+
return 0;
144+
}
145+

0 commit comments

Comments
 (0)