遇到 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
作为一个健康的默认值为您的代码。
我正在尝试生成生成 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
作为一个健康的默认值为您的代码。