从原始标题和图像数据创建位图 我在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(); }
下面是我正在输出的.bmp的数据:从原始标题和图像数据创建位图 我在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 首先,你没有为所有的像素分配足够的内存
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
by2
图片和24 bpp
(每像素位),您应该分配12个字节
每个像素对应于其红色
、绿色
和蓝色
通道的一行三个字节
注意:我从来没有使用过Window的位图创建过程,但我使用了许多库来处理图像,包括
FreeImage
、SDL
和GD
首先,如果没有为所有像素分配足够的内存,那么应该是这样的
unsigned char* thedata = new unsigned char[numPixels * bytesPerPixel];
bf->bfType == 66;
在您的情况下,对于2
by2
图片和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