-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhuff_codec.cpp
More file actions
168 lines (147 loc) · 4.34 KB
/
huff_codec.cpp
File metadata and controls
168 lines (147 loc) · 4.34 KB
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
/**
* @file huff_codec.cpp
* @author Marián Tarageľ (xtarag01)
* @brief Image data compression using Huffman encoding
* @date 8.5.2024
*/
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <vector>
#include <unistd.h>
#include "compressor.hpp"
#include "decompressor.hpp"
#include "huff_codec.hpp"
const char *usage =
"./huff_codec (-c -w <width_value> | -d) -i <ifile> -o <ofile> [-m] [-a]) [-h]\n"
" -c compression\n"
" -d decompression\n"
" -m activate model and RLE\n"
" -a activate adaptive scan\n"
" -i <ifile> input file\n"
" -o <ofile> output file\n"
" -w <width_value> width of the image\n"
" -h display help and exit\n";
const char *invalid_combination = "./huff_codec: invalid combination -- %s\n";
const char *invalid_arg = "./huff_codec: invalid option -- %s\n";
void handle_error(const char *error_message)
{
perror(error_message);
exit(EXIT_FAILURE);
}
void print_usage(int exit_status)
{
if (exit_status == EXIT_SUCCESS)
printf("%s", usage);
else
fprintf(stderr, "%s", usage);
exit(exit_status);
}
std::vector<uint8_t> read_file(const char *filename)
{
// open image
FILE *fp = fopen(filename, "rb");
if (fp == NULL)
handle_error("fopen");
// get image size
fseek(fp, 0, SEEK_END);
unsigned long image_size = ftell(fp);
rewind(fp);
// allocate memory for the image buffer
std::vector<uint8_t> buffer;
buffer.resize(image_size);
// copy image bytes to the buffer
size_t ret = fread(&buffer[0], sizeof(uint8_t), image_size, fp);
if (ret != image_size)
handle_error("fread");
// close file
fclose(fp);
return buffer;
}
int main(int argc, char *argv[])
{
int opt;
int compression = 0;
int decompression = 0;
int model = 0;
int adaptive = 0;
const char *ifile = NULL;
const char *ofile = NULL;
long int width = 0;
long int height = 0;
// get options
while ((opt = getopt(argc, argv, "cdmai:o:w:h")) != -1) {
switch ((char) opt) {
case 'c':
compression = 1;
break;
case 'd':
decompression = 1;
break;
case 'm':
model = 1;
break;
case 'a':
adaptive = 1;
break;
case 'i':
ifile = optarg;
break;
case 'o':
ofile = optarg;
break;
case 'w':
char *endptr;
width = strtol(optarg, &endptr, 10);
if (*endptr != '\0') {
fprintf(stderr, invalid_arg, "'width_value' not numeric");
print_usage(EXIT_SUCCESS);
}
if (width < 1) {
fprintf(stderr, invalid_arg, "'width_value' is less than 1");
print_usage(EXIT_FAILURE);
}
break;
case 'h':
print_usage(EXIT_SUCCESS);
break;
default:
print_usage(EXIT_FAILURE);
break;
}
}
// check input options
if (!compression && !decompression) {
fprintf(stderr, invalid_combination, "at least one of 'compression' or 'decompression'");
print_usage(EXIT_FAILURE);
}
if (compression && decompression) {
fprintf(stderr, invalid_combination, "only one of 'compression' and 'decompression'");
print_usage(EXIT_FAILURE);
}
if (ifile == NULL || ofile == NULL) {
fprintf(stderr, invalid_arg, "one of 'ifile' or 'ofile' is not specified");
print_usage(EXIT_FAILURE);
}
if (compression && width == 0) {
fprintf(stderr, invalid_arg, "'width_value' must be specified in compression mode");
print_usage(EXIT_FAILURE);
}
std::vector<u_int8_t> buffer = read_file(ifile);
if (width > 0)
height = buffer.size() / width;
if (compression) {
if (adaptive) {
adaptive_scan(buffer, width, height, model, ofile);
} else {
static_scan(buffer, model, ofile);
}
} else if (decompression) {
if (adaptive) {
adaptive_decompression(buffer, model, ofile);
} else {
static_decompression(buffer, model, ofile);
}
}
return EXIT_SUCCESS;
}