【问题标题】:Why is my bmp writer not working?为什么我的 bmp 编写器不工作?
【发布时间】:2015-03-19 21:47:29
【问题描述】:

我正在尝试编写一个简单的函数,将一些图像数据保存为位图。我生成的数据是 3601 x 3601。我在调试器中验证了传递给函数的所有数据都是正确的。我还验证了焊盘大小与我对宽度为 3601 (padSize = 1) 的 24 位 BMP 的预期相同。

这个创建的位图比我用相同尺寸的油漆创建的位图大得多,这意味着这里的某些东西写入了太多数据。我将此文件与类似大小的位图进行了十六进制比较,并且标题相同,所以我认为我的问题不存在。我认为我在 charbuffer 上的写入命令必须比预期的要多,但我不知道为什么。任何帮助表示赞赏。

void SaveBMPData(string fname, unsigned char *data, int imgWid, int imgHei)
{

    ofstream file;
    file.open(fname.c_str(), std::ios::out);

    if (file.is_open())
    {
        //string fname = "APnormal.bmp";
        cout << "INFO >> Saving BMP data: " << fname << "." << endl;

        //write header
        unsigned char fileinfo[14] = {
            'B', 'M', // magic
            0, 0, 0, 0, // size in bytes
            0, 0, // app data
            0, 0, // app data
            40 + 14, 0, 0, 0 // start of data offset
        };
        unsigned char info[40] = {
            40, 0, 0, 0, // info hd size
            0, 0, 0, 0, // width
            0, 0, 0, 0, // heigth
            1, 0, // number color planes
            24, 0, // bits per pixel
            0, 0, 0, 0, // compression is none
            0, 0, 0, 0, // image bits size
            0x13, 0x0B, 0, 0, // horz resoluition in pixel / m
            0x13, 0x0B, 0, 0, // vert resolutions (0x03C3 = 96 dpi, 0x0B13 = 72 dpi)
            0, 0, 0, 0, // #colors in pallete
            0, 0, 0, 0, // #important colors
        };    

        int w = imgWid;
        int h = imgHei;

        int padSize = (4 - ((w * 3) % 4)) % 4;
        int sizeData = w*h * 3 +h*padSize;
        int sizeAll = sizeData + sizeof(fileinfo) + sizeof(info);

        fileinfo[2] = (unsigned char)(sizeAll);
        fileinfo[3] = (unsigned char)(sizeAll >> 8);
        fileinfo[4] = (unsigned char)(sizeAll >> 16);
        fileinfo[5] = (unsigned char)(sizeAll >> 24);  

        info[4] = (unsigned char)(w);
        info[5] = (unsigned char)(w >> 8);
        info[6] = (unsigned char)(w >> 16);
        info[7] = (unsigned char)(w >> 24); 

        info[8] = (unsigned char) (h);
        info[9] = (unsigned char) (h >> 8);
        info[10] = (unsigned char)(h >> 16);
        info[11] = (unsigned char)(h >> 24);

        info[20] = (unsigned char)(sizeData);
        info[21] = (unsigned char)(sizeData >> 8);
        info[22] = (unsigned char)(sizeData >> 16);
        info[23] = (unsigned char)(sizeData >> 24);

        file.write((char*)fileinfo, sizeof(fileinfo));
        file.write((char*)info, sizeof(info));

        unsigned char *charbuffer = new unsigned char[w * 3 + padSize];

        for (int y = 0; y<h; y++)
        {
            for (int x = 0; x<w; x++)
            {
                unsigned char red = data[(x + y*imgWid) * 3];
                unsigned char green = data[(x + y*imgWid) * 3 + 1];
                unsigned char blue = data[(x + y*imgWid) * 3 + 2];
                charbuffer[x * 3    ] = blue;
                charbuffer[x * 3 + 1] = green;
                charbuffer[x * 3 + 2] = red;

            }
            file.write((char *)(void*)charbuffer, w*3+padSize);

        }
        file.close();
        delete [] charbuffer;
    }
    else
    {
        cout << "can't read file.\n";
    }

}

【问题讨论】:

    标签: c++ file-io bmp ostream


    【解决方案1】:

    您需要以二进制模式打开文件,否则任何值为0x0a的像素分量都会导致写入0x0d 0x0a的文件。

    file.open(fname.c_str(), std::ios::out | std::ios::binary);
    

    【讨论】:

    • 如果默认情况下以文本模式打开,那很好:) 一种确定方法是在每次写入后使用 long pos = file.tellp(); 来告诉它在哪里在文件中,如果它写的比你预期的多。
    • 这是正确的修复方法,非常感谢!!!这解决了我的问题!!!你是绅士和圣人!
    【解决方案2】:

    您是否将绘图中的位图保存为 24 位 bmp?

    我强烈建议在 Internet 上获取一些代码,例如:http://tipsandtricks.runicsoft.com/Cpp/BitmapTutorial.html 并查看/使用该代码。

    我会避免使用带有值和 cmets(信息、文件信息)的数组,并使用真正的具体结构来定义属性。

    您的问题应该很容易解决,但 IMO 您最好使用一些已经编写的代码,因为这已经完成了很多次所以

    【讨论】:

    • 不幸的是我不能使用外部库。我相信我的标题是正确的,就好像我更改数据以将 rgb 设置为它正确写入的传入数据中的相同值。只有当 img 数据是一个随机变量数组时,它才会混淆并呈现太多信息。感谢您的链接。我会调查的。
    • 您的文件大小是多少?我希望 3601x3601x3 = 38901603 + padding (3601*1) + header info 大约是这个大小。
    • 正确的文件大小应该是 38,905,258 我的文件是 38,926,864。每行增加 6 个字节。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-09
    • 2016-02-12
    • 2015-10-11
    • 1970-01-01
    • 1970-01-01
    • 2013-11-01
    • 1970-01-01
    相关资源
    最近更新 更多