-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMatrixReader.cpp
200 lines (166 loc) · 5.64 KB
/
MatrixReader.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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#include "MatrixReader.hpp"
#include <iostream>
#include <iomanip>
#include <cassert>
#include "utils.hpp"
#include "Exceptions.hpp"
/**
* @brief Private ctor to build a matrix from an existing stream.
* @param matrix
*/
template<size_t size>
dc::MatrixReader<size>::MatrixReader(uint32_t *matrix) {
std::copy_n(matrix, size * size, this->matrix);
std::copy_n(matrix, size * size, this->expanded);
}
/**
* @brief Default ctor.
*/
template<size_t size>
dc::MatrixReader<size>::MatrixReader() : matrix{0}, expanded{0.0} {
}
/**
* @brief Default dtor.
*/
template<size_t size>
dc::MatrixReader<size>::~MatrixReader() {
}
/**
* @brief Read a matrix from an existing bitstream.
* Used for getting the quantization matrix from an encoded image bitstream.
*
* @param reader
* The BitStreamReader to read from.
* @return
* Returns an initialized MatrixReader instance.
*/
template<size_t size>
dc::MatrixReader<> dc::MatrixReader<size>::fromBitstream(util::BitStreamReader &reader) {
const uint32_t bit_size = reader.get(dc::MatrixReader<>::SIZE_LEN_BITS);
uint32_t matrix[size * size] = { 0u };
for (size_t y = 0; y < size; y++) {
for (size_t x = 0; x < size; x++) {
matrix[y * size + x] = reader.get(bit_size);
}
}
return dc::MatrixReader<>(matrix);
}
/**
* @brief Read the matrix contents from a text file located at fileName.
* Every number in the matrix should fit in a uint16_t.
* @param fileName
* @return
*/
template<size_t size>
bool dc::MatrixReader<size>::read(const std::string &fileName) {
const std::string *data = nullptr;
try {
data = util::readStringFromFile(fileName);
} catch (Exceptions::FileReadException const& e) {
util::deallocVar(data);
std::cerr << "[MatrixReader] " << e.getMessage() << std::endl;
return false;
}
std::string line, item;
std::stringstream ss(*data);
bool exception = false;
size_t file_row, file_col;
for (file_row = 0; std::getline(ss, line) && !exception; ++file_row) {
if (file_row >= size) {
std::cerr << "[MatrixReader] Too many rows in matrix! Expected "
<< size << " but got " << file_row << " or more!" << std::endl;
exception = true;
break;
}
std::trim(line);
std::strReplaceConsecutive(line, ' ');
std::stringstream iss(line);
for (file_col = 0; std::getline(iss, item, ' '); ++file_col) {
if (file_col >= size) {
std::cerr << "[MatrixReader] Too many cols in matrix! Expected "
<< size << " but got " << file_col << " or more!" << std::endl;
exception = true;
break;
}
try {
this->matrix[file_row * size + file_col] = util::lexical_cast<uint16_t>(item.c_str());
//printf("Var => %s \tcast = %d\n", item.c_str(), this->matrix[file_row][file_col]);
} catch (Exceptions::CastingException const& e) {
exception = true;
std::cerr << "[MatrixReader] " << e.getMessage() << std::endl;
break;
}
}
if (file_col < size) {
std::cerr << "[MatrixReader] Too little cols in matrix! Expected "
<< size << " but got " << file_col << "!" << std::endl;
exception = true;
break;
}
}
if (!exception && (file_row < size)) {
std::cerr << "[MatrixReader] Too little rows in matrix! Expected "
<< size << " but got " << file_row << "!" << std::endl;
exception = true;
}
if (!exception) {
std::copy_n(this->matrix, size * size, this->expanded);
}
util::deallocVar(data);
return !exception;
}
/**
* @brief Write the matrix to the given BitStreamWriter with a minimal amount of bits.
* Use dc::MatrixReader<>::SIZE_LEN_BITS bits to save the bit length and
* write size*size values of this->getMaxBitLength() bits to the stream.
*
* @param writer
* The bitstream to write to.
*/
template<size_t size>
void dc::MatrixReader<size>::write(util::BitStreamWriter &writer) const {
const uint8_t quant_bit_len = this->getMaxBitLength();
// Assert that quant_bit_len actually fits in dc::MatrixReader<>::SIZE_LEN_BITS bits
assert((quant_bit_len & ((1 << dc::MatrixReader<>::SIZE_LEN_BITS) - 1))
== quant_bit_len);
writer.put(dc::MatrixReader<>::SIZE_LEN_BITS, quant_bit_len);
for (size_t y = 0; y < size; y++) {
for (size_t x = 0; x < size; x++) {
writer.put(quant_bit_len, this->matrix[y * size + x]);
}
}
}
/**
* @brief Return a string representation for the matrix.
*/
template<size_t size>
const std::string dc::MatrixReader<size>::toString(void) const {
size_t row, col;
std::ostringstream oss;
for (row = 0; row < size; row++) {
for (col = 0; col < size; col++) {
oss << std::setw(4) << this->matrix[row * size + col];
}
oss << std::endl;
}
return oss.str();
}
/**
* @brief Get the minimal amount of bits needed to represent every matrix element.
*/
template<size_t size>
uint8_t dc::MatrixReader<size>::getMaxBitLength(void) const {
uint8_t length = 0u;
for (size_t i = 0; i < size * size; i++) {
length = std::max(length, util::ffs(this->matrix[i]));
}
return length;
}
/**
* @brief Get the internal double matrix.
*/
template<size_t size>
const double* dc::MatrixReader<size>::getData() const {
return this->expanded;
}
template class dc::MatrixReader<dc::BlockSize>;