逐像素编辑 bmp [C++]

Posted

技术标签:

【中文标题】逐像素编辑 bmp [C++]【英文标题】:Editing bmp pixel by pixel [C++] 【发布时间】:2015-12-11 22:42:51 【问题描述】:

我想制作一个程序,它将拍摄一张图像并将每个像素的蓝色分量替换为 0。

所以我写了这个。我在文件夹中有一个 bmp 图像和它的副本,作为输入文件,我输入了原始文件的名称,作为输出名称,我编写了副本。但是当我在程序运行后尝试打开第二个时,它无法正常打开。有人可以帮忙吗?

#include <iostream>
#include <fstream>
#include <cstdlib>

using namespace std;

int main()

    ifstream ifs;
    ofstream ofs;
    char input[80];
    char output[80];

    cout<<"Input file name"<<endl;
    cin>>input;
    ifs.open(input, ios::binary);

    if(!ifs)
    
        cout<<"Error in opening file"<<endl;
        system("pause");
        return 0;
    

    cout<<"Output file name"<<endl;
    cin>>output;
    ofs.open(output, ios::binary);

    ifs.seekg(2);

    int file_size;
    ifs.read((char*)&file_size, sizeof(int));

    ofs<<"Bitmap size: "<<file_size<<"\r\n";

    ifs.seekg(10);
    int beg;
    ifs.read((char*)&beg, sizeof(int));

    ofs<<"Beggining of image: "<<beg<<"\r\n";

    ifs.seekg(18);
    int columns;
    ifs.read((char*)&columns, sizeof(int));

    ofs<<"Column number: "<<columns<<"\r\n";

    ifs.seekg(22);
    int rows;
    ifs.read((char*)&rows, sizeof(int));

    ofs<<"Row number: "<<rows<<"\r\n";

    int image_size=0;
    columns+=(3*columns)%4;
    image_size=3*columns*rows;

    ofs<<"Size of image"<<image_size<<"\r\n";

    ifs.seekg(beg);

    unsigned char R,G,B;
    for(int i=beg; i<image_size+beg; i+=3)
    
        ofs.seekp(i);
        ofs<<char(0);
    


    system("pause");
    return 0;

【问题讨论】:

您是否尝试过如果您的程序只是复制文件会发生什么 - 将字节从输入写入输出而不进行修改? 几乎在代码末尾的 for 呢? Piotr - 不,我没有,但这是个好主意。我会 我对 BMP 格式了解不多,但是……它真的包含诸如“图像大小”或“行号:”之类的字符串吗? @PiotrAleksanderChmielowski 不,当然不是。 【参考方案1】:

没有包含诸如“位图大小:”、“图像开头:”、“列号:”、“行号:”和“图像大小”之类的文本的图像文件格式。

即使有这样的文件格式,你不是在写“开始”,你在写“开始”,那是行不通的。计算机往往非常偏爱正确的拼写。

即使存在这样的文件格式,它也不会与您正在读取的文件格式相同,因为您正在读取偏移量 2 处的 int 并将其解释为某种文件大小,但是您没有在输出文件的偏移量 2 处写入任何大小。

因此,长话短说,您必须对正在阅读的文件格式有一个非常清晰的规范(您没有告诉我们任何相关内容),并且您还必须在书面上遵循完全相同的规范文件。

随心所欲地制定自己的文件格式规范是行不通的。

另外,在未来,请记住,在 *** 上,诸如“它无法正常打开”之类的短语不会被视为对技术问题的有效描述。具体说明正在发生的事情。

提示:您似乎试图通过寻找单个字节并用零覆盖它们来就地编辑文件。这不适用于空文件。将原始文件的全部内容复制到新文件名,然后在副本上查找和覆盖字节。

【讨论】:

这是我在课堂上得到的一个作业,在描述中它说例如 bmp 文件的大小在偏移量 2 处,文件中图像的开头在偏移量 10 处给出等. 它有效,因为它正确地读取了所有信息。抱歉,当我写“无法正常打开”时,我的意思是当我尝试使用默认的 Windows 图像查看器打开文件时,它会显示“Windows 无法打开图像”。 新文件名是bmp的副本,所以我不是在空文件上操作。我有一个我从中读取的,另一个我试图通过寻找单个字节并将它们替换为零来改变它们。 Mateusz,您正在提示用户为输入文件输入一个文件名,为输出文件输入另一个文件名,很明显,您正在使用两个不同的文件。您没有尝试将输入文件的内容复制到输出文件中,因此您正在操作一个必须假定为空的文件。 (它可能碰巧已经存在,但这无关紧要。)如果您的代码依赖于输出文件的先前存在,那么您绝对不会使用输入文件。 我必须为写“将原始文件复制到新文件名”而道歉,因为这不清楚。无法将文件复制到文件名。我的意思当然是“将输入文件的内容复制到输出文件中”。【参考方案2】:

所以我将发表我的评论作为答案: 我不太了解 BMP 格式,但是……它真的包含诸如“图像大小”或“行号:”之类的字符串吗?

如果不是,请删除ofs&lt;&lt;"Beggining of image: "&lt;&lt;beg&lt;&lt;"\r\n";等,我认为您的意思是cout而不是ofs

【讨论】:

【参考方案3】:

好吧,我不读取文件进行修改,而是将原始文件的全部内容复制到输出文件名并进行修改。谢谢大家,也谢谢迈克,我按照你的建议做了。

【讨论】:

Mateusz,这应该是评论,而不是答案。

以上是关于逐像素编辑 bmp [C++]的主要内容,如果未能解决你的问题,请参考以下文章

BMP文件中奇怪的十六进制数字

C++ - 从 BMP 文件中读取每个像素的位数

使用 CImg 编辑 RGB 像素数据 - Visual C++ 2008

C++ 位图每像素位

opencv C++ 三重for循环遍历RGB图像像素(逐像素操作操作像素值遍历像素遍历)

使用 VS6 C++ GUI 编辑器、MFC 以屏幕(像素)为单位调整全屏窗口大小?