【问题标题】:Having trouble with C++ Bitmaps遇到 C++ 位图问题
【发布时间】:2017-03-28 07:31:31
【问题描述】:

我正在尝试生成代码以生成将 1 个像素设置为黑色的图像,问题是当我尝试将单个像素设置为黑色时,输出是 8 个水平黑色像素。我还尝试将上面的像素设置为黑色,但它导致水平线比原始像素高 8 个像素。

所以我的问题是,如何更改我的代码,以便最终使用位而不是图像中的字节?我只想能够将单个像素设置为黑色而不是一个字节的像素。

这是我的代码:

#include <iostream>
#include <fstream>
#include "windows.h"
using namespace std;

#define IMAGE_SIZE 256
int main(int argc, char* argv[])
{

    BITMAPFILEHEADER bmfh;

    BITMAPINFOHEADER bmih;

    char colorTable[8] = { 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff };

    char bits[IMAGE_SIZE][IMAGE_SIZE];

    ofstream bmpOut("foo.bmp", ios::out + ios::binary);
    if (!bmpOut) {
        cout << "could not open file.";
        return -1;
    }
    bmfh.bfType = 0x4d42;
    bmfh.bfReserved1 = 0;
    bmfh.bfReserved2 = 0;
    bmfh.bfOffBits = sizeof(bmfh) + sizeof(bmih) + sizeof(colorTable);
    bmfh.bfSize = bmfh.bfOffBits + sizeof(bits);

    bmih.biSize = 40;
    bmih.biWidth = IMAGE_SIZE;
    bmih.biHeight = IMAGE_SIZE;
    bmih.biPlanes = 1;
    bmih.biBitCount = 1;
    bmih.biCompression = 0;
    bmih.biSizeImage = 0;
    bmih.biXPelsPerMeter = 2835; 
    bmih.biYPelsPerMeter = 2835;
    bmih.biClrUsed = 0;
    bmih.biClrImportant = 0;

    // Here I am initializing a white background for the bitmap image

    for (int i = 0; i < IMAGE_SIZE; i++) {
        for (int j = 0; j < IMAGE_SIZE; j++) {
            bits[i][j] = 255;
        }
    }

    // Here I attempt to set the most bottom left pixel to black and the pixel above it to black as well

    bits[0][0] = 0;

    bits[1][0] = 0;

    char* workPtr;
    workPtr = (char*)&bmfh;
    bmpOut.write(workPtr, 14);
    workPtr = (char*)&bmih;
    bmpOut.write(workPtr, 40);
    workPtr = &colorTable[0];
    bmpOut.write(workPtr, 8);
    workPtr = &bits[0][0];
    bmpOut.write(workPtr, IMAGE_SIZE*IMAGE_SIZE);
    bmpOut.close();

    system("mspaint foo.bmp");

    return 0;
}

这是生成的位图图像的链接: Scaled up for clarity

谢谢

【问题讨论】:

    标签: c++ bitmap bmp


    【解决方案1】:

    基于BITMAPINFOHEADER documentation,您似乎正在通过设置bmih.biBitCount = 1 将位图设置为单色读取。这样,每个像素都由一位(仅黑色或白色)表示,而不是字节。因此,要将左下角像素设置为黑色,您需要执行bits[0][0] = 127 (127 = 0x7F = 01111111b)。要在它上面设置一个,我想你需要做bits[1][0] = 127。在这种情况下我也相信

    char bits[IMAGE_SIZE][IMAGE_SIZE/8];
    ...
    for (int i = 0; i < IMAGE_SIZE; i++) {
        for (int j = 0; j < IMAGE_SIZE/8; j++) {
            bits[i][j] = 255;
        }
    }
    ...
    workPtr = &bits[0][0];
    bmpOut.write(workPtr, IMAGE_SIZE*(IMAGE_SIZE/8));
    

    足够了。

    如果您打算使用不同的调色板,则应设置不同的biBitCount,如我在开头链接到的文档中所述,我猜您希望bmih.biBitCount = 8 作为代码的健康默认值。

    【讨论】:

    • 感谢您的回复!您澄清说我在设置位时处理的是二进制,所以我现在了解如何专门设置 8 个水平像素的任何类型的排列。我确实尝试过将正上方的像素设置为黑色的方法,但由于某种原因我无法让它工作。
    • @michael874,我知道设置左下角像素有效吗?你是如何尝试设置更高的像素的,你得到了什么结果?我认为将这些信息编辑到问题中对我们俩来说都是最舒服的。
    • @michael874 我已经编辑了我的答案,我对内存布局有点困惑。你有没有这样尝试过(bits[1][0] = 127)?如果您使用(IMAGE_SIZE/8) * (IMAGE_SIZE/8) 大小的简单一维数组而不是二维数组会更容易。
    • 我确实尝试了 bits[1][0] = 127,但它在第 8 行而不是第 2 行(从底部开始)分配了第一个黑色像素。
    • @michael874 此时您的数组声明为char bits[IMAGE_SIZE/8][IMAGE_SIZE/8]char bits[IMAGE_SIZE][IMAGE_SIZE]
    猜你喜欢
    • 2013-10-20
    • 2014-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-20
    • 2013-08-02
    相关资源
    最近更新 更多