IMHO, a vector<vector< >>
is suitable if rows may have varying lengths but such thing isn't actually called a matrix anymore. (The raw data of the OP's sample forms a matrix stored row-wise.)
Why is it necessary to copy the temp
array to a vector<>
? This is duplicating the data. If the life-time can be granted the temp
might be accessed directly. (Otherwise, it could be copied to a vector<uint8_t>
.)
AFAIK, the packing of components in struct RGB
is not granted. Hence, the reinterpret_cast<RGB*>()
is not the cleanest way to access the bytes.
So, I would like to suggest a solution that prevents all these issues – class Image
which works as a wrapper/accessor to the raw data in temp
:
#include <cstddef>
#include <cstdint>
struct RGB {
uint8_t red, green, blue;
RGB() { } // leaving contents uninitialized
RGB(uint8_t red, uint8_t green, uint8_t blue):
red(red), green(green), blue(blue)
{ }
};
class Image {
private:
const uint8_t *_pData;
public:
class Row {
private:
const uint8_t *_pData;
public:
Row(const uint8_t *pData): _pData(pData) { }
RGB operator[](size_t i) const
{
const uint8_t *pixel = _pData + 3 * i;
return RGB(pixel[0], pixel[1], pixel[2]);
}
};
Image(const uint8_t *pData): _pData(pData) { }
size_t height() const { return _pData[0]; }
size_t width() const { return _pData[1]; }
RGB get(size_t i, size_t j) const
{
const uint8_t *pixel = _pData + 2 + (i * _pData[1] + j) * 3;
return RGB(pixel[0], pixel[1], pixel[2]);
}
Row operator[](size_t i) const
{
return Row(_pData + 2 + i * _pData[1] * 3);
}
};
Access to an RGB-tripel can be performed with Image::get()
as well as with the more intuitive Image::operator[]()
.
Sample code:
#include <iomanip>
#include <iostream>
int main()
{
// data array representing image data - this would really be a bin fle
// header r, g, b r, g, b r, g, b footer
uint8_t temp[22] = { 0x02, 0x03, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xef, 0x05,
0x0a, 0x01, 0x02, 0x0d, 0xfe, 0x00, 0x10, 0xff, 0xff, 0xef, 0xef };
// access via
Image img(temp);
std::cout << std::hex << std::setfill('0');
// via Image::get()
std::cout << "access with img.get(i, j):\n";
for (size_t i = 0, n = img.height(); i < n; ++i) {
for (size_t j = 0, m = img.width(); j < m; ++j) {
RGB rgb = img.get(i, j);
std::cout << " "
<< std::setw(2) << (unsigned)rgb.red << std::setw(0) << ' '
<< std::setw(2) << (unsigned)rgb.green << std::setw(0) << ' '
<< std::setw(2) << (unsigned)rgb.blue << std::setw(0);
}
std::cout << '\n';
}
// via Image::operator[]
std::cout << "access with img[i][j]:\n";
for (size_t i = 0, n = img.height(); i < n; ++i) {
for (size_t j = 0, m = img.width(); j < m; ++j) {
RGB rgb = img[i][j];
std::cout << " "
<< std::setw(2) << (unsigned)rgb.red << std::setw(0) << ' '
<< std::setw(2) << (unsigned)rgb.green << std::setw(0) << ' '
<< std::setw(2) << (unsigned)rgb.blue << std::setw(0);
}
std::cout << '\n';
}
return 0;
}
Output:
access with img.get(i, j):
01 02 03 04 05 06 07 ef 05
0a 01 02 0d fe 00 10 ff ff
access with img[i][j]:
01 02 03 04 05 06 07 ef 05
0a 01 02 0d fe 00 10 ff ff
Live Demo on coliru