我有一个带有成员缓冲区的类图像,这是一个存储图像像素的无符号字符向量。我希望将此缓冲区作为矩阵处理。我希望以 img [i] [j] 的形式访问缓冲区,但我不知道怎么做?有人可以建议我一个解决方案吗?
这是我的尝试:
unsigned char * &Image::operator[](int i) {
return buffer[ rows+i ]
}
我读了post然后我认为这是可能的。我的班级就是这样:
class Image {
private:
unsigned char * buffer;
int buf_size;
int rows;
int cols;
Phisical_img_manager phisical_img_manager;
const char * in_img_filename;
public:
unsigned char * & operator[](int i);
Image(const char * in_img_filename);
unsigned char * get_buffer();
int get_cols();
int get_rows();
};
答案 0 :(得分:6)
您可以在row-major order中执行以下操作:
class Image {
int rows, cols;
unsigned char *buffer;
public:
// ...
unsigned char* operator[](int const i) { return &(buffer[i * cols]); }
unsigned char const* operator[](int const i) const { return &(buffer[i * cols]); }
};
您的缓冲区是一块连续的内存块。大小N = rows * cols
。
然而,图像的概念是以2D构造/矩阵排列的一组像素:
我们想要的是将这个2D构造安排在计算机内存中的1D缓冲区中。我们可以通过两种方式实现这一目标:
在行主要订单中,我们一个接一个地存储图像的每一行。也就是说,对于以下尺寸2x2
图像
相应的缓冲存储器如下所示:
在列主要订单中,我们一个接一个地存储图像的每一列。也就是说,相同大小的2x2
图像的缓冲区存储看起来像:
支持多维数组的编程语言要么为它们实现行主要或列主要存储顺序。在C和C ++中,使用行主要顺序。
在上面显示的代码中,我们实现了行主要顺序。我们定义了一个重载的下标运算符,它将我们想要访问的行索引(例如i
)作为输入。将此i
与列数相乘,我们得到图像中ith
行的起始索引。我们返回该特定地址中元素的地址。此地址标记原始缓冲区的子数组的开始以及ith
行的开头。为了进一步说明,请参阅以下代码示例:
Image I(2, 3);
I[1][2] = 42;
调用I[1][2] = 42
就像调用:
(I.operator[](1))[2];
子调用I.operator[](1)
返回指向图像第二行开始的地址的指针。然后我们将此返回的指针用作普通的动态分配数组。在这个具体的例子中,我们向这个指针添加2(即,这就是[2]
所做的),因此我们得到行的元素,该行位于行的第一个元素之后的2个位置(即,第三个元素)图像的第二行)。
如果您的编译器支持C ++ 11和智能指针,您可以执行以下方案以避免内存管理。此外,我会重载operator()(std::size_t const, std::size_t const)
因为如上所述重载你暴露缓冲区,因此你正在伤害封装:
class Image {
int rows, cols;
std::unique_ptr<unsigned char[]> buffer;
public:
Image(int const rows_ = 0, int const cols_ = 0)
: rows(rows_), cols(cols_), buffer(new unsigned char[rows * cols]) {}
Image(Image const &other)
: rows(other.rows), cols(other.cols), buffer(new unsigned char[rows * cols]) {
std::copy(other.buffer.get(), other.buffer.get() + (rows * cols), buffer.get());
}
Image(Image &&other)
: rows(other.rows), cols(other.cols), buffer(std::move(other.buffer)) {
other.rows = 0;
other.cols = 0;
}
unsigned char& operator()(std::size_t const i, std::size_t const j) {
return buffer[cols * i + j];
}
unsigned char const& operator()(std::size_t const i, std::size_t const j) const {
return buffer[cols * i + j];
}
Image& operator=(Image const &other) {
rows = other.rows;
cols = other.cols;
buffer.reset(new unsigned char[rows * cols]);
std::copy(other.buffer.get(), other.buffer.get() + (rows * cols), buffer.get());
return *this;
}
Image& operator=(Image &&other) {
rows = other.rows;
cols = other.cols;
buffer.swap(other.buffer);
other.rows = 0;
other.cols = 0;
return *this;
}
// ...
};