遇到 C++ 位图问题

Having trouble with C++ Bitmaps

我正在尝试生成生成 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;
}

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

谢谢

根据 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 作为一个健康的默认值为您的代码。