从原始标题和图像数据创建位图 我在C++中操纵位图数据是非常新的,我有一个问题。我试着效仿维基百科的例子。以下是我正在使用的代码: #include <iostream> #include <fstream> #include <Windows.h> using namespace std; int main() { //fileheader BITMAPFILEHEADER* bf = new BITMAPFILEHEADER; bf->bfType = 66; bf->bfSize = 70; bf->bfOffBits = 54; //infoheader BITMAPINFOHEADER* bi = new BITMAPINFOHEADER; bi->biSize = 40; bi->biWidth = 2; bi->biHeight = 2; bi->biPlanes = 1; bi->biBitCount = 24; bi->biCompression = 0; bi->biSizeImage = 16; bi->biXPelsPerMeter = 2835; bi->biYPelsPerMeter = 2835; bi->biClrUsed = 0; bi->biClrImportant = 0; //image data unsigned char* thedata = new unsigned char; thedata[0] = 0; thedata[1] = 0; thedata[2] = 255; thedata[3] = 255; thedata[4] = 255; thedata[5] = 255; thedata[6] = 0; thedata[7] = 0; thedata[8] = 255; thedata[9] = 0; thedata[10] = 0; thedata[11] = 0; thedata[12] = 255; thedata[13] = 0; thedata[14] = 0; thedata[15] = 0; //dc HDC dc = GetDC(NULL); //bitmap info BITMAPINFO* bmi = (BITMAPINFO*)bi; //handle to bitmap HBITMAP hbmp = CreateDIBitmap(dc, bi, CBM_INIT, thedata, bmi, DIB_RGB_COLORS); //output to bmp....? ofstream outFile; outFile.open("outtestbmp.bmp"); outFile << hbmp; outFile.close(); }

从原始标题和图像数据创建位图 我在C++中操纵位图数据是非常新的,我有一个问题。我试着效仿维基百科的例子。以下是我正在使用的代码: #include <iostream> #include <fstream> #include <Windows.h> using namespace std; int main() { //fileheader BITMAPFILEHEADER* bf = new BITMAPFILEHEADER; bf->bfType = 66; bf->bfSize = 70; bf->bfOffBits = 54; //infoheader BITMAPINFOHEADER* bi = new BITMAPINFOHEADER; bi->biSize = 40; bi->biWidth = 2; bi->biHeight = 2; bi->biPlanes = 1; bi->biBitCount = 24; bi->biCompression = 0; bi->biSizeImage = 16; bi->biXPelsPerMeter = 2835; bi->biYPelsPerMeter = 2835; bi->biClrUsed = 0; bi->biClrImportant = 0; //image data unsigned char* thedata = new unsigned char; thedata[0] = 0; thedata[1] = 0; thedata[2] = 255; thedata[3] = 255; thedata[4] = 255; thedata[5] = 255; thedata[6] = 0; thedata[7] = 0; thedata[8] = 255; thedata[9] = 0; thedata[10] = 0; thedata[11] = 0; thedata[12] = 255; thedata[13] = 0; thedata[14] = 0; thedata[15] = 0; //dc HDC dc = GetDC(NULL); //bitmap info BITMAPINFO* bmi = (BITMAPINFO*)bi; //handle to bitmap HBITMAP hbmp = CreateDIBitmap(dc, bi, CBM_INIT, thedata, bmi, DIB_RGB_COLORS); //output to bmp....? ofstream outFile; outFile.open("outtestbmp.bmp"); outFile << hbmp; outFile.close(); },c++,bitmap,C++,Bitmap,下面是我正在输出的.bmp的数据: 42 00 46 00 00 00 CD CD CD CD 36 00 00 00 28 00 00 00 02 00 00 00 02 00 00 00 01 00 18 00 00 00 00 00 10 00 00 00 13 0B 00 00 13 0B 00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF 00 00 FF 00 00 00 FF 00 00 00 首先,你没有为所有的像素分配足够的内存

下面是我正在输出的.bmp的数据:

42 00 46 00 00 00 CD CD CD CD 36 00 00 00 28 00 00 00 02 00 00 00 02 00 00 00 01 00 18 
00 00 00 00 00 10 00 00 00 13 0B 00 00 13 0B 00 00 00 00 00 00 00 00 00 00 00 00 FF FF 
FF FF 00 00 FF 00 00 00 FF 00 00 00

首先,你没有为所有的像素分配足够的内存,它应该是沿着

unsigned char* thedata = new unsigned char[numPixels * bytesPerPixel];
在您的情况下,对于
2
by
2
图片和
24 bpp
(每像素位),您应该分配12个字节

每个像素对应于其
红色
绿色
蓝色
通道的一行三个字节


注意:我从来没有使用过Window的位图创建过程,但我使用了许多库来处理图像,包括
FreeImage
SDL
GD
首先,如果没有为所有像素分配足够的内存,那么应该是这样的

unsigned char* thedata = new unsigned char[numPixels * bytesPerPixel];
bf->bfType == 66;
在您的情况下,对于
2
by
2
图片和
24 bpp
(每像素位),您应该分配12个字节

每个像素对应于其
红色
绿色
蓝色
通道的一行三个字节

注意:我从未使用过Window的位图创建过程,但我使用了许多库来处理图像,包括
FreeImage
SDL
GD

bf->bfType == 66;
这在两个方面是错误的。首先是错误的值(魔法值是小端机器上的字节'BM'或0x4d42),其次不是赋值

然后:

只分配1个字符

这是:

outFile << hbmp;
这在两个方面是错误的。首先是错误的值(魔法值是小端机器上的字节'BM'或0x4d42),其次不是赋值

然后:

只分配1个字符

这是:

outFile << hbmp;

HBITMAP是位图的句柄,而不是实际的位图。真正的位图存储在内核内存中。如果只是将位图写入文件,则不需要对GDI进行任何调用。即使它是一个实际的位图,也需要一个操作符重载才能将内存结构写入文件,因为它存储在内存中的方式与磁盘上的不同

您只需将BITMAPFILEHEADER写入文件,然后将BitMapInfo头写入文件,然后写入数据(如果我们说的是RGB,则为非索引)

下面是有关位图如何实际存储在磁盘上的更多信息


从文件中读取位图也是一样的。

HBITMAP是位图的句柄,而不是实际的位图。真正的位图存储在内核内存中。如果只是将位图写入文件,则不需要对GDI进行任何调用。即使它是一个实际的位图,也需要一个操作符重载才能将内存结构写入文件,因为它存储在内存中的方式与磁盘上的不同

您只需将BITMAPFILEHEADER写入文件,然后将BitMapInfo头写入文件,然后写入数据(如果我们说的是RGB,则为非索引)

下面是有关位图如何实际存储在磁盘上的更多信息


从文件中读取位图也是一样的。

首先,您需要为像素分配足够的数据:

unsigned char* thedata = new unsigned char[2 * 2 * 3];
然后,您需要使用
write
并以
binary
的形式打开文件

而不是:

outFile.open("outtestbmp.bmp");
outFile << hbmp;
outFile.open(“outtestbmp.bmp”);

outFile首先,您需要为像素分配足够的数据:

unsigned char* thedata = new unsigned char[2 * 2 * 3];
然后,您需要使用
write
并以
binary
的形式打开文件

而不是:

outFile.open("outtestbmp.bmp");
outFile << hbmp;
outFile.open(“outtestbmp.bmp”);

outFile您是否尝试过调试您的输出,例如通过使用hexeditor将数据与已知良好的简单bmp文件进行比较?没有!我现在就去找一个十六进制编辑器来检查一下。至少要做:unsigned char*thedata=newunsigned char[16];要链接到的维基百科文章和下面我的答案中都给出了正确的值。您可能应该添加bf->bfReserved1=0和bf->bfReserved2=0;当您在堆上创建新对象时,存储在该内存地址中的任何以前的值都将仍然存在(或多或少)。您是否尝试过调试输出,例如,将数据与已知良好的简单bmp文件进行比较,并使用hexeditor?不,我没有!我现在就去找一个十六进制编辑器来检查一下。至少要做:unsigned char*thedata=newunsigned char[16];要链接到的维基百科文章和下面我的答案中都给出了正确的值。您可能应该添加bf->bfReserved1=0和bf->bfReserved2=0;当你在堆上创建一个新的对象时,之前存储在内存地址中的任何值都会保留在那里(或多或少)。对了,我已经修复了这个问题,哈哈,我的糟糕,我忘记了当我复制代码时它仍然在那里。另外,如果我不添加新的无符号字符,我会得到一个编译错误,因为指针未初始化。对了,我已经修复了这个问题,哈哈,糟糕,我忘了在复制代码时它还在那里。另外,如果我不添加新的无符号字符,我会得到一个编译错误,因为指针未初始化。实际上,在这种情况下,您应该分配16个字节。每行的宽度必须向上舍入到4字节的倍数;由于自然行大小是2个像素,每个像素有3个字节,因此会产生6个字节,必须四舍五入到8。2行8个“是”等于16个字节。实际上,在这种情况下,您应该分配16个字节。每行的宽度必须向上舍入到4字节的倍数;由于自然行大小是2个像素,每个像素有3个字节,因此会产生6个字节,必须四舍五入到8。2行8字节是16字节。所以
输出文件是,除了数据需要是一组RGBQUAD结构(
结构RGBQUAD{char Blue;char Green;char Red;char Reserved;}
)。请查看该链接,它在解释位图的实际存储方式方面确实做了大量工作。因此,
outFile是的,只是数据需要是一组RGBQUAD结构(
struct RGBQUAD{char B