forked from sundeshgupta/encoding-algorithm
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy patharithmetic_encode_image.cpp
175 lines (138 loc) · 3.46 KB
/
arithmetic_encode_image.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
const ll MIN = 0;
const ll MAX = 4294967295;
ll lower[257];
vector <ll> low, high;
int parseLine(char* line){
// This assumes that a digit will be found and the line ends in " Kb".
int i = strlen(line);
const char* p = line;
while (*p <'0' || *p > '9') p++;
line[i-3] = '\0';
i = atoi(p);
return i;
}
int getValue(){ //Note: this value is in KB!
FILE* file = fopen("/proc/self/status", "r");
int result = -1;
char line[128];
while (fgets(line, 128, file) != NULL){
if (strncmp(line, "VmRSS:", 6) == 0){
result = parseLine(line);
break;
}
}
fclose(file);
return result;
}
string write_bits(bool bit, int bit_to_fall){
string tmp;
tmp += to_string(bit);
while(bit_to_fall){
tmp += to_string(!bit);
bit_to_fall -= 1;
}
return tmp;
}
ofstream out("arithmetic_encoded.txt");
string image_pixels = "";
string code = "";
uint8_t* rgb_image;
int main(int argc, char** argv)
{
int width, height, bpp, num_channel = 1;
if (argc>2)
{
cout<<"Error: Too many arguments\n";
return 0;
}
if (argc==2)
{
if (string(argv[1])!="grey" && string(argv[1])!="rgb")
{
cout<<"Error: Invalid Argument\n";
return 0;
}
if (string(argv[1]) == "rgb")
num_channel = 3;
}
string filename;
cin>>filename;
auto start = chrono::high_resolution_clock::now();
rgb_image = stbi_load(filename.c_str(), &width, &height, &bpp, num_channel);
const ll ONE_QTR = MAX / 4 + 1;
const ll HALF = 2 * ONE_QTR;
const ll THREE_QTR = 3 * ONE_QTR;
int len = height*width*num_channel + 1;
low.resize(len+1);
high.resize(len+1);
low[0] = MIN;
high[0] = MAX;
int current = 1;
int i = 0;
int itr = 0;
for (int i = 0; i < height; ++i)
for (int j = 0; j < width; ++j)
for(int k = 0; k < num_channel; ++k){
if (int(rgb_image[itr])==0)
rgb_image[itr] = char(1);
lower[int(rgb_image[itr++])] += 1;
}
lower[256] = 1;
for(int i=1; i<=256; i++){
lower[i] += lower[i-1];
}
int bit_to_fall = 0;
while(i < len){
if(i == len-1) current = 256;
else current = rgb_image[i];
i += 1;
ll range = high[i-1] - low[i-1] + 1;
low[i] = low[i-1] + (range * lower[current-1]) / len;
high[i] = low[i-1] + (range * lower[current]) / len - 1;
while(true){
if(high[i] < HALF){
code += write_bits(0, bit_to_fall);
bit_to_fall = 0;
}
else if(low[i] >= HALF){
code += write_bits(1, bit_to_fall);
bit_to_fall = 0;
low[i] -= HALF;
high[i] -= HALF;
}
else if(low[i] >= ONE_QTR and high[i] < THREE_QTR){
bit_to_fall += 1;
low[i] -= ONE_QTR;
high[i] -= ONE_QTR;
}
else
break;
low[i] = 2 * low[i];
high[i] = 2 * high[i] + 1;
}
}
ll p = low[i-1];
for(int j=31; j>=0; j--){
if((p & (1LL<<j))) code += '1';
else code += '0';
}
out << len << " ";
for(int i=0; i<=256; i++)
out << lower[i] << " ";
out << code << "\n";
out << height << " " << width << " " << num_channel << "\n";
auto stop = chrono::high_resolution_clock::now();
auto duration = chrono::duration_cast<chrono::microseconds>(stop - start);
cout<<filename<<",";
float NoBpp = ((float)code.size())/(height*width*num_channel);
float cp = (1 - ((float)code.size())/(height*width*num_channel*8))*100;
cout<<height*width*num_channel<<","<<cp<<",";
cout<<NoBpp<<","<<(duration.count()/1000000.0)<<",";
cout<<getValue()<<",";
return 0;
}