#include "MatrixReader.hpp"
#include
#include
#include
#include "utils.hpp"
#include "Exceptions.hpp"
/**
* @brief Private ctor to build a matrix from an existing stream.
* @param matrix
*/
template
dc::MatrixReader::MatrixReader(uint32_t *matrix) {
std::copy_n(matrix, size * size, this->matrix);
std::copy_n(matrix, size * size, this->expanded);
}
/**
* @brief Default ctor.
*/
template
dc::MatrixReader::MatrixReader() : matrix{0}, expanded{0.0} {
}
/**
* @brief Default dtor.
*/
template
dc::MatrixReader::~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
dc::MatrixReader<> dc::MatrixReader::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
bool dc::MatrixReader::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(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
void dc::MatrixReader::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
const std::string dc::MatrixReader::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
uint8_t dc::MatrixReader::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
const double* dc::MatrixReader::getData() const {
return this->expanded;
}
template class dc::MatrixReader<:blocksize>;