|
通过windows API函数利用已知的二进制数据生成一个bmp文件
BMP file = BMP file header + BMP info header[ + palatte data] + color data 1。调色板数据:对于增强16位或更高彩色的图象,没有调色板数据。 具体内容看msdn,可能是叫RGBQUAD吧 2。颜色数据:单行的数据量大小是length*height*bit per pixel/8 每行对齐到4字节边界,不足的补0x0. 行的存储方式是从左到右,最底下的行最先存储,既存储的上下顺序是倒的,左右顺序不变。 3。根据已知的数据大小,确定位图的长、高和颜色数,填写BMPFILEHEADER和BMPINFOHEADER,如果数据不包含调色板,要先用WIN API创建一个同等数目的调色板(item count = 1<<color bits,即,黑白的有1<<1 = 2项,4色有1<<2 = 4项,16色有1<<4 = 16项,256色有1<<8 = 256项) >= 16-bit时没有调色板 4。依次把BMPFILEHEADER,BMPINFOHEADER,palatte,和颜色数据写入文件就好了,假如没有调色板数据,写完BMPINFOHEADER就写数据.
颜色数据每行对齐到4字节边界,就是说每行的数据的字节数必须是4的倍数。但是他没有给出确切的公式,每行数据的 字节数的计算公式是:(Width*BitPerPixel+31)/32*4。假如你已经有了灰阶 的图像数据(8位),存放次序为从左到右,从上到下,每行数据之间没有添 加额外的数据,那么可以这样生成一个BITMAP文件。 bool SaveGrayDataToBmp(BYTE* Data, int W, int H, const char* BmpFile) { FILE *fp; bool ret; UINT nPad; BYTE Pad[4]; RGBQUAD Quad[256]; BITMAPFILEHEADER bfh; BITMAPINFOHEADER bih; //设定BITMAPFILEHEADER memset(&bfh, 0, sizeof(bfh)); bfh.bfType = 'BM'; bfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof( BITMAPINFOHEADER) + sizeof(RGBQUAD)*256 + ((W*8+31)/32*4)*H; bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof( BITMAPINFOHEADER) + sizeof(RGBQUAD)*256; //设定BITMAPINFOHEADER memset(&bih, 0, sizeof(bih)); bih.biSize = sizeof(bih); bih.biWidth = W; bih.biHeight = H; bih.biPlanes = 1; //必须为1 bih.biBitCount = 8; //设定调色盘数据Quad for(int n=0; n<256; n++) { Quad[n].rgbBlue = n; Quad[n].rgbGreen = n; Quad[n].rgbRed = n; Quad[n].rgbReserved = 0; } //下面写数据到BITMAP文件 fp = fopen(BmpFile, "wb"); if (fp==NULL) return false; fwrite(&bfh, 1, sizeof(bfh), fp); fwrite(&bih, 1, sizeof(bih), fp); fwrite(Quad, 1, sizeof(Quad), fp); //下面写入数据部分,注意,bmp的数据上下是颠倒的 Data = Data + W*(H-1); //因为上下颠倒,所以需要将Data指向最后 //一行,以后再对Data进行减操作。 nPad = ((W*8+31)/32*4) - W; //因为bmp每行的数据为4的倍数,所以 //需要在每行后面补0,nPad为补的字节数 memset(Pad, 0, sizeof(Pad)); for(int h=H-1; h>=0; h--) { fwrite(Data, 1, W, fp); fwrite(Pad, 1, nPad, fp); Data = Data - W; 因为上下颠倒,Data是倒退着写入文件 } ret = ferror()==0; fclose(fp); return ret; } |