C++ 将 BitMap "Right Way up" 读入 1D Vector 的最佳方法
C++ Best way to read BitMap "Right Way up" into 1D Vector
我正在尝试将位图 "The Right Way Up" 读入一维向量。这是我的第一次尝试。它很笨重:
void BitMap::ReadBMP(const char* filename)
{
FILE* f = fopen(filename, "rb");
if(f == NULL)
throw "Argument Exception";
unsigned char info[54];
fread(info, sizeof(unsigned char), 54, f); // read the 54-byte header
// extract image height and width from header
m_width = *(int*)&info[18];
m_height = *(int*)&info[22];
cout << endl;
cout << " Name: " << filename << endl;
cout << " Width: " << m_width << endl;
cout << "Height: " << m_height << endl;
int row_padded = (m_width*3 + 3) & (~3);
unsigned char* data = new unsigned char[row_padded];
unsigned char tmp;
std::deque<Element> mydeque;
std::vector<Element> bmpRow;
for(int i = 0; i < m_height; i++)
{
fread(data, sizeof(unsigned char), row_padded, f);
for(int j = 0; j < m_width*3; j += 3)
{
// BGRA format
Element element;
element.Elements[0] = data[j+2];
element.Elements[1] = data[j+1];
element.Elements[2] = data[j];
element.Elements[3] = 0; // for alpha
bmpRow.push_back(element);
}
mydeque.insert (mydeque.begin(),bmpRow.begin(),bmpRow.end());
bmpRow.clear();
}
std::copy(mydeque.begin(), mydeque.end(), std::back_inserter(m_pixelVec));
cout<< "After Deque Copy" << endl;
fclose(f);
delete data;
}
问题是,我需要像这样在应用程序的不同点遍历数据 - 注意 h 和 W 交换了 setPixel。 请忽略这部分,这只是为了演示上面C++部分的BitMap需要旋转:
for (int h = 0; h<imageHeight; h++)
{
for (int w = 0; w<imageWidth; w++)
{
int p = 0;
Pixel pixel = currentImagePixelVec.get(pixelVecLoc);
p = (pixel.Alpha<<24) | (pixel.Red<<16) | (pixel.Green<<8) | pixel.Blue;
imageData.setPixel(w, h, p);
pixelVecLoc++;
}
}
所以我想在读入 1D Vector 时旋转 BitMap。能推荐个好方法吗?
编辑:
这实际上只是为了测试目的。我只使用 BitMaps 我知道高度和宽度等。我想从算法的角度知道人们会怎么做
据我了解,您想转置图像数据;也就是说,将像素列存储在 m_pixelVec 的连续段中,而不是行。
在我看来,最简单的方法是在读取值时将值放入二维数据结构中,然后将其展平。这使得更改列优先顺序与行优先顺序变得微不足道,只需翻转索引即可。
为了在我想要的时候访问任何点,没有任何 push_backs,我预先分配了整个东西,它假定 Element 类型是默认可构造的。我使用了向量的向量,但二维数组也可以。
我注意到您将读取的第一行 (i == 0) 放在向量的末尾,并假设您希望保留该行为。因此在分配给 bmpcolrow
时索引 m_height-i-1
。
另一种可能性是只使用 bmpcolrow[j][i]
然后在插入时反转列(在最后一行使用 col.rbegin()
和 col.rend()
)。
std::vector<std::vector<Element>> bmpcolrow(m_width, std::vector<Element>(m_height));
for(int i = 0; i < m_height; i++) {
fread(data, sizeof(unsigned char), row_padded, f);
for(int j = 0; j < m_width; j++) {
// BGRA format
Element element;
element.Elements[0] = data[3*j+2];
element.Elements[1] = data[3*j+1];
element.Elements[2] = data[3*j];
element.Elements[3] = 0; // for alpha
bmpcolrow[j][m_height-i-1] = element;
}
}
for (const auto& col : bmpcolrow)
m_pixelVec.insert(m_pixelVec.end(), col.begin(), col.end());
我正在尝试将位图 "The Right Way Up" 读入一维向量。这是我的第一次尝试。它很笨重:
void BitMap::ReadBMP(const char* filename)
{
FILE* f = fopen(filename, "rb");
if(f == NULL)
throw "Argument Exception";
unsigned char info[54];
fread(info, sizeof(unsigned char), 54, f); // read the 54-byte header
// extract image height and width from header
m_width = *(int*)&info[18];
m_height = *(int*)&info[22];
cout << endl;
cout << " Name: " << filename << endl;
cout << " Width: " << m_width << endl;
cout << "Height: " << m_height << endl;
int row_padded = (m_width*3 + 3) & (~3);
unsigned char* data = new unsigned char[row_padded];
unsigned char tmp;
std::deque<Element> mydeque;
std::vector<Element> bmpRow;
for(int i = 0; i < m_height; i++)
{
fread(data, sizeof(unsigned char), row_padded, f);
for(int j = 0; j < m_width*3; j += 3)
{
// BGRA format
Element element;
element.Elements[0] = data[j+2];
element.Elements[1] = data[j+1];
element.Elements[2] = data[j];
element.Elements[3] = 0; // for alpha
bmpRow.push_back(element);
}
mydeque.insert (mydeque.begin(),bmpRow.begin(),bmpRow.end());
bmpRow.clear();
}
std::copy(mydeque.begin(), mydeque.end(), std::back_inserter(m_pixelVec));
cout<< "After Deque Copy" << endl;
fclose(f);
delete data;
}
问题是,我需要像这样在应用程序的不同点遍历数据 - 注意 h 和 W 交换了 setPixel。 请忽略这部分,这只是为了演示上面C++部分的BitMap需要旋转:
for (int h = 0; h<imageHeight; h++)
{
for (int w = 0; w<imageWidth; w++)
{
int p = 0;
Pixel pixel = currentImagePixelVec.get(pixelVecLoc);
p = (pixel.Alpha<<24) | (pixel.Red<<16) | (pixel.Green<<8) | pixel.Blue;
imageData.setPixel(w, h, p);
pixelVecLoc++;
}
}
所以我想在读入 1D Vector 时旋转 BitMap。能推荐个好方法吗?
编辑: 这实际上只是为了测试目的。我只使用 BitMaps 我知道高度和宽度等。我想从算法的角度知道人们会怎么做
据我了解,您想转置图像数据;也就是说,将像素列存储在 m_pixelVec 的连续段中,而不是行。
在我看来,最简单的方法是在读取值时将值放入二维数据结构中,然后将其展平。这使得更改列优先顺序与行优先顺序变得微不足道,只需翻转索引即可。
为了在我想要的时候访问任何点,没有任何 push_backs,我预先分配了整个东西,它假定 Element 类型是默认可构造的。我使用了向量的向量,但二维数组也可以。
我注意到您将读取的第一行 (i == 0) 放在向量的末尾,并假设您希望保留该行为。因此在分配给 bmpcolrow
时索引 m_height-i-1
。
另一种可能性是只使用 bmpcolrow[j][i]
然后在插入时反转列(在最后一行使用 col.rbegin()
和 col.rend()
)。
std::vector<std::vector<Element>> bmpcolrow(m_width, std::vector<Element>(m_height));
for(int i = 0; i < m_height; i++) {
fread(data, sizeof(unsigned char), row_padded, f);
for(int j = 0; j < m_width; j++) {
// BGRA format
Element element;
element.Elements[0] = data[3*j+2];
element.Elements[1] = data[3*j+1];
element.Elements[2] = data[3*j];
element.Elements[3] = 0; // for alpha
bmpcolrow[j][m_height-i-1] = element;
}
}
for (const auto& col : bmpcolrow)
m_pixelVec.insert(m_pixelVec.end(), col.begin(), col.end());