【问题标题】:Why is the Right Side of my Image Being Wrapped Around?为什么我的图像的右侧被环绕?
【发布时间】:2021-02-22 17:07:03
【问题描述】:

本质上,我正在创建一个为构造函数获取 BMP 文件的类。从THIS POST 我得到所有的标题数据,然后将 RGB 数据读入一个向量。然后我将强度计算为 0.25R + 0.5G + 0.25B。我将这些数字逐行放入一个以空格分隔的文件中。上面的原始结果在下面,使用 GNUPlot 打开和绘制图像给了我这个结果。

original

distortion

如您所见,随着图像被写入文件(或在此过程之前的某个位置),图像的右侧始终被进一步环绕。我已经粘贴了下面的代码,有什么帮助吗?

std::vector<char> MImage::readBMP(std::string const file){
static constexpr size_t HEADER_SIZE = 54;

std::ifstream bmp(file, std::ios::binary);

std::array<char, HEADER_SIZE> header;
bmp.read(header.data(), header.size());

auto fileSize = *reinterpret_cast<uint32_t*>(&header[2]);
auto dataOffset = *reinterpret_cast<uint32_t*>(&header[10]);
auto width = *reinterpret_cast<uint32_t*>(&header[18]);
auto height = *reinterpret_cast<uint32_t*>(&header[22]);
auto depth = *reinterpret_cast<uint16_t*>(&header[28]);
/*
std::cout << "fileSize: " << fileSize << std::endl;
std::cout << "dataOffset: " << dataOffset << std::endl;
std::cout << "width: " << width << std::endl;
std::cout << "height: " << height << std::endl;
std::cout << "depth: " << depth << "-bit" << std::endl;
*/
std::vector<char> img(dataOffset - HEADER_SIZE);
//bmp.read(img.data(), img.size());

auto dataSize = ((width * 3 + 3) & (~3)) * height;
img.resize(dataSize);
bmp.read(img.data(), img.size());

char temp = 0;

for (int i = dataSize - 4; i >= 0; i -= 3)
{
    temp = img[i];
    img[i] = img[i + 2];
    img[i + 2] = temp;
}


// Convert to intensity
int k = 0;
int size = (int)img.size();
for (int j = 0; k+2 < size; j++)
{
    //0.25B + 0.5G + 0.25R
    img[j] = ((abs(img[k]) >> 2) + (abs(img[k + 1]) >> 1) + (abs(img[k + 2]) >> 2));
    //OutputDebugStringA((to_string(img[j]) + "\n").c_str());
    
    k += 3;
}
img.resize(dataSize / 3);
//OutputDebugStringA((to_string(img.size()) + "\n").c_str());


int a, b, c = 0;
//Testing @img data
ofstream TestPic;
TestPic.open("testpic.txt");
for (a = 0; a < HEIGHT; a++) {
    for (b = 0; b < WIDTH; b++) {
        TestPic << (int)img[c];
        if (b < WIDTH-1) {
            TestPic << " ";
        }
        c++;
    }
    TestPic << "\n";
}
TestPic.close();

return img; }

GNUPlot 命令:用图像像素绘制 [0:630] [0:354] 'testpic.txt' 矩阵

【问题讨论】:

  • 然后我将强度计算为 0.25R + 0.5G + 0.25B。我将这些数字逐行放入一个以空格分隔的文件中 -- 先测试一下是否可以准确输出读入的内容怎么样?这将确保您至少让代码的输入和输出部分正常工作。
  • 这真的很简单:您不应该编写自己的 BMP 读取函数。问题解决了。但说真的:把它做好是很棘手的,库开发人员花费了大量的时间来解决极端情况。因此,我强烈建议您不要重新实现图形文件格式 I/O 库,除非您的工作是出于某种难以理解的原因开发新的 BMP 库。

标签: c++ arrays image matrix


【解决方案1】:

您看到的问题是由不正确的数据对齐引起的。 .bmp 文件的每个扫描线必须具有可被 4 整除的字节大小。您正在使用此行正确计算输入数据大小:

auto dataSize = ((width * 3 + 3) & (~3)) * height;

但是,在转换 img 数组时,您不会补偿/丢弃每条扫描线末尾的填充。

最好的建议是使用标准 bmp 加载器/转换器,如 STB 库(stb_image.h 文件)中的那个,或者,如果你想自己做,分配另一个数组(img2 或类似的东西)并逐个扫描线迭代img数组扫描线,将灰度值写入img2

顺便说一句,您提到的这个answer 包含针对您的确切问题的解决方案(称为“填充修复”)。

【讨论】:

  • 感谢您的快速回复。我不知道 STB,如果我的方式永远看起来不错,我会调查的。但是,我尝试了“填充修复”答案,但它永远不会正确地从 54 字节标头中加载任何内容(例如,它加载 'width' = -858993460 并且标头的缓冲区只读取过 ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ... ..).
  • -858993460 in HEX 是“-0x33333334”,这是非常可疑的,看起来像一个默认未初始化/损坏的变量)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多