Skip to content

Commit 401e7cb

Browse files
committed
arithmetic coding for images
1 parent 6e10f09 commit 401e7cb

File tree

17 files changed

+3189
-0
lines changed

17 files changed

+3189
-0
lines changed

arithmetic_decode_image.cpp

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
#include <bits/stdc++.h>
2+
using namespace std;
3+
#define STB_IMAGE_WRITE_IMPLEMENTATION
4+
#include "stb_image_write.h"
5+
#define ll long long
6+
7+
const ll MIN = 0;
8+
const ll MAX = 65535;
9+
10+
ll lower[257];
11+
vector <ll> _low, _high;
12+
13+
string write_bits(bool bit, int bit_to_fall){
14+
string tmp;
15+
tmp += to_string(bit);
16+
while(bit_to_fall){
17+
tmp += to_string(!bit);
18+
bit_to_fall -= 1;
19+
}
20+
return tmp;
21+
}
22+
23+
int to_int(int _pos, string &encode){
24+
int n = 0;
25+
for (int i = _pos; i < sizeof(short) * 8 + _pos; i++)
26+
{
27+
n <<= 1;
28+
n |= encode[i] - '0';
29+
}
30+
return n;
31+
}
32+
33+
ll add_bit(ll value, int count_taken, bool &flag, string &encode){
34+
bitset<16> a(value);
35+
36+
if(flag == 1){
37+
a.reset(0);
38+
}
39+
else if(count_taken > encode.length()){
40+
a.set(0);
41+
flag = 1;
42+
}
43+
else if(encode[count_taken] == '1'){
44+
a.set(0);
45+
}
46+
else if(encode[count_taken] == '0'){
47+
a.reset(0);
48+
}
49+
50+
value = (ll)(a.to_ulong());
51+
return value;
52+
}
53+
54+
uint8_t* rgb_image;
55+
string code;
56+
57+
int main()
58+
{
59+
auto start = chrono::high_resolution_clock::now();
60+
61+
ifstream in("arithmetic_encoded.txt");
62+
63+
const ll ONE_QTR = MAX / 4 + 1;
64+
const ll HALF = 2 * ONE_QTR;
65+
const ll THREE_QTR = 3 * ONE_QTR;
66+
67+
ll len;
68+
in >> len;
69+
for(int i=0; i<=256; i++) in >> lower[i];
70+
71+
72+
in >> code;
73+
cout<<code.size()<<"\n";
74+
int height, width, num_channel;
75+
76+
in>>height>>width>>num_channel;
77+
78+
cout<<height<<" "<<width<<" "<<num_channel<<"\n";
79+
80+
rgb_image = (uint8_t*) malloc(width*height*num_channel);
81+
82+
int itr = 0;
83+
84+
_low.resize(len);
85+
_high.resize(len);
86+
87+
_low[0] = MIN;
88+
_high[0] = MAX;
89+
90+
ll value = to_int(0, code);
91+
int count_taken = 16;
92+
bool flag = 0;
93+
for(int i=1;i<len;i++){
94+
ll range = (_high[i-1] - _low[i-1] + 1);
95+
ll nxt = (((value - _low[i-1]) + 1) * len - 1) / range;
96+
97+
int symbol;
98+
for(symbol = 1; lower[symbol] <= nxt; symbol++);
99+
100+
_low[i] = _low[i-1] + (range * lower[symbol-1]) / len;
101+
_high[i] = _low[i-1] + (range * lower[symbol]) / len - 1;
102+
103+
if(symbol == 256)
104+
break;
105+
106+
rgb_image[itr++] = symbol;
107+
108+
for(;;){
109+
if(_high[i] >= HALF){
110+
if(_low[i] >= HALF){
111+
value -= HALF;
112+
_low[i] -= HALF;
113+
_high[i] -= HALF;
114+
}
115+
else if (_low[i] >= ONE_QTR && _high[i] < THREE_QTR)
116+
{
117+
value -= ONE_QTR;
118+
_low[i] -= ONE_QTR;
119+
_high[i] -= ONE_QTR;
120+
}
121+
else
122+
{
123+
break;
124+
}
125+
}
126+
_low[i] = 2 * _low[i];
127+
_high[i] = 2 * _high[i] + 1;
128+
value = add_bit(2 * value, count_taken, flag, code);
129+
count_taken++;
130+
}
131+
}
132+
133+
stbi_write_png("ac_image.png", width, height, num_channel, rgb_image, width*num_channel);
134+
135+
}

arithmetic_encode_image.cpp

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
#include <bits/stdc++.h>
2+
using namespace std;
3+
#define ll long long
4+
#define STB_IMAGE_IMPLEMENTATION
5+
#include "stb_image.h"
6+
7+
const ll MIN = 0;
8+
const ll MAX = 65535;
9+
10+
ll lower[257];
11+
vector <ll> low, high;
12+
13+
string write_bits(bool bit, int bit_to_fall){
14+
string tmp;
15+
tmp += to_string(bit);
16+
while(bit_to_fall){
17+
tmp += to_string(!bit);
18+
bit_to_fall -= 1;
19+
}
20+
return tmp;
21+
}
22+
23+
int to_int(int _pos, string &encode){
24+
int n = 0;
25+
for (int i = _pos; i < sizeof(short) * 8 + _pos; i++)
26+
{
27+
n <<= 1;
28+
n |= encode[i] - '0';
29+
}
30+
return n;
31+
}
32+
33+
ll add_bit(ll value, int count_taken, bool &flag, string &encode){
34+
bitset<16> a(value);
35+
36+
if(flag == 1){
37+
a.reset(0);
38+
}
39+
else if(count_taken > encode.length()){
40+
a.set(0);
41+
flag = 1;
42+
}
43+
else if(encode[count_taken] == '1'){
44+
a.set(0);
45+
}
46+
else if(encode[count_taken] == '0'){
47+
a.reset(0);
48+
}
49+
50+
value = (ll)(a.to_ulong());
51+
return value;
52+
}
53+
54+
ofstream out("arithmetic_encoded.txt");
55+
56+
string image_pixels = "";
57+
string code = "";
58+
59+
int main(int argc, char** argv)
60+
{
61+
62+
int width, height, bpp, num_channel = 1;
63+
64+
65+
if (argc>2)
66+
{
67+
cout<<"Error: Too many arguments\n";
68+
return 0;
69+
}
70+
if (argc==2)
71+
{
72+
if (string(argv[1])!="grey" && string(argv[1])!="rgb")
73+
{
74+
cout<<"Error: Invalid Argument\n";
75+
return 0;
76+
}
77+
if (string(argv[1]) == "rgb")
78+
num_channel = 3;
79+
}
80+
81+
// string filename;
82+
// cin>>filename;
83+
84+
uint8_t* rgb_image = stbi_load("./images/2.bmp", &width, &height, &bpp, num_channel);
85+
86+
const ll ONE_QTR = MAX / 4 + 1;
87+
const ll HALF = 2 * ONE_QTR;
88+
const ll THREE_QTR = 3 * ONE_QTR;
89+
90+
int len = height*width*num_channel + 1;
91+
cout<<height<<" "<<width<<" "<<num_channel<<"\n";
92+
cout<<len<<"\n";
93+
94+
low.resize(len);
95+
high.resize(len);
96+
97+
low[0] = MIN;
98+
high[0] = MAX;
99+
100+
int current = 1;
101+
int i = 0;
102+
103+
int itr = 0;
104+
for (int i = 0; i < height; ++i)
105+
for (int j = 0; j < width; ++j)
106+
for(int k = 0; k < num_channel; ++k){
107+
if (int(rgb_image[itr])==0)
108+
rgb_image[itr] = char(1);
109+
lower[int(rgb_image[itr++])] += 1;
110+
}
111+
112+
lower[256] = 1;
113+
114+
for(int i=1; i<=256; i++){
115+
lower[i] += lower[i-1];
116+
}
117+
118+
int bit_to_fall = 0;
119+
120+
while(i < len){
121+
if(i == len-1) current = 256;
122+
else current = rgb_image[i];
123+
i += 1;
124+
125+
ll range = high[i-1] - low[i-1] + 1;
126+
low[i] = low[i-1] + (range * lower[current-1]) / len;
127+
high[i] = low[i-1] + (range * lower[current]) / len - 1;
128+
129+
while(true){
130+
if(high[i] < HALF){
131+
code += write_bits(0, bit_to_fall);
132+
bit_to_fall = 0;
133+
}
134+
else if(low[i] >= HALF){
135+
code += write_bits(1, bit_to_fall);
136+
bit_to_fall = 0;
137+
low[i] -= HALF;
138+
high[i] -= HALF;
139+
}
140+
else if(low[i] >= ONE_QTR and high[i] < THREE_QTR){
141+
bit_to_fall += 1;
142+
low[i] -= ONE_QTR;
143+
high[i] -= ONE_QTR;
144+
}
145+
else
146+
break;
147+
low[i] = 2 * low[i];
148+
high[i] = 2 * high[i] + 1;
149+
}
150+
}
151+
152+
ll p = low[i-1];
153+
154+
for(int j=15; j>=0; j--){
155+
if((p & (1LL<<j))) code += '1';
156+
else code += '0';
157+
}
158+
159+
out << len << " ";
160+
161+
for(int i=0; i<=256; i++)
162+
out << lower[i] << " ";
163+
164+
out << code << "\n";
165+
166+
cout<<code.size()<<"\n";
167+
168+
out << height << " " << width << " " << num_channel << "\n";
169+
170+
}

images/0.jpg

416 KB
Loading

images/1.bmp

4.07 MB
Binary file not shown.

images/10.ppm

Lines changed: 2884 additions & 0 deletions
Large diffs are not rendered by default.

images/11.png

1.42 KB
Loading

images/12.png

2.56 KB
Loading

images/13.png

4.93 KB
Loading

images/14.png

831 Bytes
Loading

images/2.bmp

1.43 MB
Binary file not shown.

images/3.bmp

1.02 MB
Binary file not shown.

images/4.bmp

538 KB
Binary file not shown.

images/5.bmp

399 KB
Binary file not shown.

images/6.bmp

199 KB
Binary file not shown.

images/7.bmp

43.4 KB
Binary file not shown.

images/8.ppm

48.1 KB
Binary file not shown.

images/9.png

7.64 KB
Loading

0 commit comments

Comments
 (0)