C++ C++;位图到base64
我有以下代码来创建位图:C++ C++;位图到base64,c++,bitmap,biometrics,C++,Bitmap,Biometrics,我有以下代码来创建位图: //raw data PBYTE firstPixel = (PBYTE)((PBYTE)AnsiBdbRecord) + sizeof(WINBIO_BDB_ANSI_381_RECORD); // declare other bmp structures BITMAPFILEHEADER bmfh; BITMAPINFOHEADER info; RGBQUAD rq[256]; // create the grayscale palette for (int i
//raw data
PBYTE firstPixel = (PBYTE)((PBYTE)AnsiBdbRecord) + sizeof(WINBIO_BDB_ANSI_381_RECORD);
// declare other bmp structures
BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER info;
RGBQUAD rq[256];
// create the grayscale palette
for (int i = 0; i<256; i++)
{
rq[i].rgbBlue = i;
rq[i].rgbGreen = i;
rq[i].rgbRed = i;
rq[i].rgbReserved = 0;
}
//RGBQUAD bl = { 0,0,0,0 }; //black color
//RGBQUAD wh = { 0xff,0xff,0xff,0xff }; // white color
// andinitialize them to zero
memset(&bmfh, 0, sizeof(BITMAPFILEHEADER));
memset(&info, 0, sizeof(BITMAPINFOHEADER));
// fill the fileheader with data
bmfh.bfType = 0x4d42; // 0x4d42 = 'BM'
bmfh.bfReserved1 = 0;
bmfh.bfReserved2 = 0;
bmfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); // + padding;
bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD);
// fill the infoheader
info.biSize = sizeof(BITMAPINFOHEADER);
info.biWidth = Width;
info.biHeight = Height;
info.biPlanes = 1; // we only have one bitplane
info.biBitCount = PixelDepth; // RGB mode is 24 bits
info.biCompression = BI_RGB;
info.biSizeImage = 0; // can be 0 for 24 bit images
info.biXPelsPerMeter = 0x0ec4; // paint and PSP use this values
info.biYPelsPerMeter = 0x0ec4;
info.biClrUsed = 0; // we are in RGB mode and have no palette
info.biClrImportant = 0; // all colors are importantenter code here
我认为以上是保存位图图像的标准方法。但是,我不希望保存映像,而是希望它作为BASE64可用,并在HTTP Post中传递它。因此,这个问题涉及到,但是我在将bmp结构转换为BASE64时遇到了很多困难。我从中获取了BASE64编码器,但我不知道如何将BMPFILEHEADER、BMPINFOHEADER、RGBQUAD和原始数据结构作为参数传递给BASE64编码器
关于如何结合我收集的信息,有什么想法或建议吗
更新
多亏了Roman Pustylnikov,我已经走得更远了:
我正在创建这样一个结构:
struct ImageBuffer
{
BITMAPFILEHEADER bfheader;
BITMAPINFOHEADER infobmp;
RGBQUAD rgb[256];
PBYTE bitmap;
};
填写如下:
HANDLE file = CreateFile(bmpfile, GENERIC_WRITE, FILE_SHARE_READ,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (file == NULL)
{
DWORD dw = GetLastError();
CloseHandle(file);
}
// write file header
if (WriteFile(file, &bmfh, sizeof(BITMAPFILEHEADER), &bwritten, NULL) == false)
{
DWORD dw = GetLastError();
CloseHandle(file);
}
// write infoheader
if (WriteFile(file, &info, sizeof(BITMAPINFOHEADER), &bwritten, NULL) == false)
{
DWORD dw = GetLastError();
CloseHandle(file);
}
//write rgbquad for black
if (WriteFile(file, &rq, sizeof(rq), &bwritten, NULL) == false)
{
DWORD dw = GetLastError();
CloseHandle(file);
}
// write image data
if (WriteFile(file, &firstPixel[0], imageSize, &bwritten, NULL) == false)
{
DWORD dw = GetLastError();
CloseHandle(file);
}
// and clean up
CloseHandle(file);
ImageBuffer capture;
capture.bfheader = bmfh;
capture.infobmp = info;
// create the grayscale palette
for (int i = 0; i<256; i++)
{
capture.rgb[i].rgbBlue = i;
capture.rgb[i].rgbGreen = i;
capture.rgb[i].rgbRed = i;
capture.rgb[i].rgbReserved = 0;
}
capture.bitmap = firstPixel;
int totalSize = sizeof(capture.bfheader) + sizeof(capture.infobmp) + sizeof(capture.rgb) + imageSize;
std::string encodedImage = base64_encode(reinterpret_cast<const unsigned char*>(&capture), totalSize);
更新二:解决方案
罗曼·普什蒂尔尼科夫(Roman Pustylnikov)答案的最新更新中可以找到解决方案 您可以使用以下作为编码器/解码器,而无需:
第一种方法是创建连续内存并将其作为输入:
int size=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256 + imageSize ;
unsigned char * bmpBuff = new char[size];
int i = 0;
memcpy((void *)( &( bmpBuff[i] )), (void *) &bfheader,sizeof(BITMAPFILEHEADER) );
i+=sizeof(BITMAPFILEHEADER);
memcpy((void *)( &( bmpBuff[i] )), (void *) &infobmp,sizeof(BITMAPINFOHEADER) );
i+=sizeof(BITMAPINFOHEADER);
memcpy((void *)( &( bmpBuff[i] )), (void *) &rq,sizeof(RGBQUAD)*256 );
i+=sizeof(RGBQUAD)*256;
memcpy((void *)( &( bmpBuff[i] )), (void *) firstPixel, imageSize );
std::string encodedImage = base64_encode(bmpBuff, size);
这种方法的缺点是需要复制内存
另一种方法是处理“丢失的三元组”。为此,我们需要定义一个结构:
struct ScreenShotBuffer
{
BITMAPFILEHEADER bfheader;
BITMAPINFO infobmp;
RGBQUAD rgb[256];
};
现在是棘手的部分。因为编码处理字节的三元组,所以需要处理两个缓冲区之间的边界(我没有测试过,所以它可能包含bug,只是一种通用方法)
int size=sizeof(BITMAPFILEHEADER)+sizeof(bitmapinfo头)+sizeof(RGBQUAD)*256;
unsigned char*info=einterpret_cast&screenshotInfo;
无符号字符*img=einterpret\u cast firstPixel;
std::string encodedInfo=base64_encode(信息,大小);
std::字符串encodedLostTriplet=“”;
整数偏移=大小%3;
无符号字符lostTriplet[3];
如果(偏移){
lostTriplet[0]=信息[大小偏移];
如果(偏移量==2)
lostTriplet[1]=信息[大小偏移量+1];
其他的
lostTriplet[1]=img[0];
lostTriplet[2]=img[2-偏移量];
encodedLostTriplet=base64_encode(lostTriplet,3);
}
否则{
偏移量=3;
}
std::string encodedData=base64_encode(reinterpret_cast&img[3-offset],imageSize-(3-offset));
std::string encodedImage=encodedInfo+lostTriplet+encodedData;
有点乱,但应该在同一个内存上工作 这似乎是正确的方向。我需要先将bitmapfileheader、infoheader、RGBQuad和rawdata连接在一起,然后我相信您可以使用该结构,将头与图像连接在一起。由于头应该始终是恒定长度的一部分(作为头的长度组合和编码),其余部分将是图像数据。应该很容易解码。我已经更新了答案。我想你已经接近了,尽管它仍然不起作用。有关详细信息,请参阅我的问题更新。我可能错了,但是sizeof(PBYTE)是sizeof(char),而不是imageSize。这就是我拆分编码的原因。您必须对图像进行编码,而不是对标题进行编码。位图不必存储在String旁边,所以ToeStand正在从未定义的地方读取数据,长度似乎很好,如果我用C++来保存保存的示例,并将其与C++Base64字符串的长度进行比较,它们的长度相等。我只是在'encodedImage'变量中输入了错误的值。。
struct ScreenShotBuffer
{
BITMAPFILEHEADER bfheader;
BITMAPINFO infobmp;
RGBQUAD rgb[256];
};
int size=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256;
unsigned char *info = einterpret_cast<const unsigned char*> &screenshotInfo;
unsigned char *img = einterpret_cast<const unsigned char*> firstPixel;
std::string encodedInfo = base64_encode(info , size);
std::string encodedLostTriplet = "";
int offset = size%3;
unsigned char lostTriplet[3];
if (offset) {
lostTriplet[0]=info[size-offset];
if (offset==2)
lostTriplet[1] = info[size-offset+1];
else
lostTriplet[1] = img[0];
lostTriplet[2] = img[2-offset];
encodedLostTriplet = base64_encode(lostTriplet, 3);
}
else {
offset=3;
}
std::string encodedData = base64_encode(reinterpret_cast<const unsigned char*> &img[3-offset], imageSize - (3 - offset) );
std::string encodedImage = encodedInfo + lostTriplet + encodedData;