C++ 如何在WinCE中创建.bmp
我有一个摄像头,它可以返回原始图像,这些图像可以很容易地转换为位图,并可以通过以下C#方法(我没有编写)保存到文件中。从各种来源,我已经确定图片每像素有8位,可能是灰度,也可能不是灰度C++ 如何在WinCE中创建.bmp,c++,image-processing,windows-ce,bmp,C++,Image Processing,Windows Ce,Bmp,我有一个摄像头,它可以返回原始图像,这些图像可以很容易地转换为位图,并可以通过以下C#方法(我没有编写)保存到文件中。从各种来源,我已经确定图片每像素有8位,可能是灰度,也可能不是灰度 private void rawImgToBmp(byte[] imgData, String fname) { Bitmap bmp = new Bitmap(getWidth(), getHeight(), System.Drawing.Imaging.PixelFo
private void rawImgToBmp(byte[] imgData, String fname) {
Bitmap bmp = new Bitmap(getWidth(), getHeight(),
System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
for (int i = 0; i < 256; i++)
{ bmp.Palette.Entries[i] = Color.FromArgb(255, i, i, i); }
//Copy the data from the byte array into the bitmap
BitmapData bmpData =
bmp.LockBits( new Rectangle(0, 0, bmp.Width, bmp.Height),
ImageLockMode.WriteOnly, bmp.PixelFormat);
Marshal.Copy(imgData, 0, bmpData.Scan0, getWidth() * getHeight());
bmp.UnlockBits(bmpData); //Unlock the pixels
bmp.Save(FileName);
}
private void rawImgToBmp(字节[]imgData,字符串fname){
位图bmp=新位图(getWidth(),getHeight(),
系统。绘图。成像。像素格式。格式8bpindexed);
对于(int i=0;i<256;i++)
{bmp.palete.Entries[i]=Color.FromArgb(255,i,i,i);}
//将数据从字节数组复制到位图中
BitmapData bmpData=
锁位(新矩形(0,0,bmp.Width,bmp.Height),
ImageLockMode.WriteOnly,bmp.PixelFormat);
Copy(imgData,0,bmpData.Scan0,getWidth()*getHeight());
bmp.UnlockBits(bmpData);//解锁像素
保存(文件名);
}
我的问题是:如何使用Windows CE 4.2?/P>的内置函数,编写C++中的等效方法?
谢谢你的调色板代码,我认为它是对的。根据页面,我已经求助于手动填充其余结构。通常我使用CreateBitmap或CreateCompatibleBitmap在windows中生成位图。我不熟悉WinCE,但功能似乎存在。使用256色调色板,您的数据看起来是8位/像素,因此您很可能还需要CreatePalette、SelectPalette和RealizePalette函数 类似(警告:未测试的代码):
HBITMAP hBmp=CreateBitmap(宽度、高度、1、8、imgData);
LOGPALETTE logpal=(LOGPALETTE)新字节[sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY)];
logpal.palVersion=0x300;
logpal.palNumEntries=256;
int i=0;
{//不知道调色板的格式,但看起来是灰度的吗?
logpal->mypal[i].peRed=i;
logpal->mypal[i].peGreen=i;
logpal->mypal[i].peBlue=i;
logpal->mypal[i].peFlags=NULL;
而(++i这是适合我的代码。它基于erisu的答案。对于使用此答案的任何其他人,我建议您尽可能全面地理解BMP格式,以便您可以相应地调整标题字段
最后的复杂循环是我解决硬件/操作系统问题的方法,它不会写入我提供给fwrite的所有数据。不过,它应该可以在任何环境下工作
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <tchar.h>
#define NPAL_ENT 256
INT WINAPI WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
INT nShowCmd )
{
int w = 1920, h = 1080; // My values, yours may vary
//////////////////////// File Operations ///////////////////////////////
// Reading raw img
FILE* f = fopen("\\FlashDisk\\raw_img.bin","r");
if(NULL == f){printf("BAD");exit(1);}
// Obtaining size of raw img
fseek (f , 0L , SEEK_END);
DWORD fsize = (DWORD)ftell (f);
fseek (f , 0L , SEEK_SET);
char *imgData = (char*) malloc (sizeof(char)*fsize);
if(NULL == imgData) {printf("NOT imgData");exit(2);}
// Copy contents of file into buffer
DWORD result = fread(imgData,1,fsize,f);
if (result != fsize) {
printf ("Reading error. Expected: %d, Got: %d\n",fsize, result );
if(ferror(f)){printf("An error: %d\n", ferror(f)); }
if(feof(f)) {printf("EOF\n");}
delete[] imgData;
fclose(f);
exit (3);
}
fclose(f);
//////////////////////// BMP Operations ///////////////////////////////
/* A bitmap has the following components:
* 1. BMP file header
* 2. Bitmap Information (DIB) header
* 3. Color Palette
* 4. Raw Data
*/
BITMAPFILEHEADER bmfh;
ZeroMemory( &bmfh, sizeof( bmfh ) );
bmfh.bfType = 0x4D42; // Magic #
bmfh.bfSize = sizeof( bmfh ) + sizeof( BITMAPINFOHEADER )
+ NPAL_ENT*sizeof(PALETTEENTRY) + w*h; // Or total file size if w/h not known
bmfh.bfOffBits = sizeof( bmfh ) + sizeof( BITMAPINFOHEADER )
+ NPAL_ENT*sizeof(PALETTEENTRY);
BITMAPINFOHEADER bmih;
ZeroMemory( &bmih, sizeof( bmih ) );
bmih.biWidth = w;
bmih.biHeight = h;
bmih.biSize = sizeof(bmih);
bmih.biPlanes = 1;
bmih.biBitCount = 8;
bmih.biCompression = BI_RGB;
bmih.biSizeImage = w * h;
int palSize = NPAL_ENT*sizeof(PALETTEENTRY);
LOGPALETTE *logpal=(LOGPALETTE*)new BYTE[sizeof(LOGPALETTE)+palSize];
if(!logpal) {delete [] imgData; printf("!logpal\n"); exit(4);}
logpal->palVersion=0x300;
logpal->palNumEntries=NPAL_ENT;
int i=0;
do { // Exact palette format varies. This is what worked for me
logpal->palPalEntry[i].peRed=i;
logpal->palPalEntry[i].peGreen=i;
logpal->palPalEntry[i].peBlue=i;
logpal->palPalEntry[i].peFlags=NULL;
} while(++i<NPAL_ENT);
// Complete bitmap is now in memory, time to save it
TCHAR bmpfname[80];
wsprintf( bmpfname, (TCHAR*) TEXT( "\\USBDisk\\out.bmp" ) );
// open the file for writing
FILE *bmpFile = _wfopen(bmpfname,L"wb");
if(!bmpFile) { delete[] imgData; delete[] logpal; exit(6); }
// write the bitmap to file, in whatever chunks WinCE allows
size_t totWrit = 0, offset = 0, writeAmt = 0;
while(totWrit < bmfh.bfSize){
if(totWrit < sizeof(bmfh)){ // File header
offset = totWrit;
totWrit += fwrite( ((char*)&bmfh)+offset, 1, sizeof(bmfh)-offset, bmpFile );
}
else if(totWrit<sizeof(bmfh)+sizeof(bmih)){ // Image header
offset = totWrit - sizeof(bmfh);
totWrit += fwrite( ((char*)&bmih)+offset, 1, sizeof(bmih)-offset, bmpFile );
}
else if(totWrit<sizeof(bmfh)+sizeof(bmih)+palSize) { // Pallette
offset = totWrit - sizeof(bmfh) - sizeof(bmih);
totWrit += fwrite( ((char*)&logpal->palPalEntry)+offset, 1, palSize-offset, bmpFile );
}
else { // Image data
offset = totWrit - sizeof(bmfh) - sizeof(bmih) - palSize;
if(bmfh.bfSize-totWrit >= IO_SIZE) {
writeAmt = IO_SIZE;
}
else {
writeAmt = bmfh.bfSize-totWrit;
}
totWrit += fwrite( &imageBuffer[offset], 1, writeAmt, bmpFile );
}
// Close and open after each iteration to please WinCE
fflush(bmpFile);
fclose(bmpFile);
Sleep(4000);
bmpFile = _wfopen(bmpfname,L"ab");
if(!bmpFile) {flog->lprintf("Couldn't reopen bmpfile"); delete [] logpal; return 0;}
}
fclose(bmpFile);
if(totWrit != bmfh.bfSize) {
printf("BMP Size mismatch: %d/%d.",totWrit,bmfh.bfSize);
delete [] imgData;
delete [] logpal;
exit(-1);
}
// Cleanup
delete [] imgData;
delete [] logpal;
return 0;
}
\if\u MSC\u VER>1000
#布拉格语一次
#endif/\u MSC\u VER>1000
#定义WIN32_精益_和_平均值
#包括
#包括
#定义NPAL_ENT 256
INT WINAPI WinMain(HINSTANCE HINSTANCE,
HINSTANCE HPPrevenstance,
LPTSTR lpCmdLine,
INT nShowCmd)
{
int w=1920,h=1080;//我的值和你的值可能不同
////////////////////////文件操作///////////////////////////////
//读取原始img
文件*f=fopen(“\\FlashDisk\\raw\u img.bin”,“r”);
如果(NULL==f){printf(“坏”);退出(1);}
//获取原始img的大小
fseek(f,0L,SEEK_END);
DWORD fsize=(DWORD)ftell(f);
fseek(f,0L,SEEK_SET);
char*imgData=(char*)malloc(sizeof(char)*fsize);
如果(NULL==imgData){printf(“非imgData”);退出(2);}
//将文件内容复制到缓冲区
DWORD结果=fread(imgData,1,fsize,f);
如果(结果!=fsize){
printf(“读取错误。应为:%d,获取:%d\n”,fsize,result);
if(ferror(f)){printf(“错误:%d\n”,ferror(f));}
if(feof(f)){printf(“EOF\n”);}
删除[]imgData;
fclose(f);
出口(3);
}
fclose(f);
////////////////////////BMP操作///////////////////////////////
/*位图具有以下组件:
*1.BMP文件头
*2.位图信息(DIB)标题
*3.调色板
*4.原始数据
*/
位图文件头bmfh;
零内存(&bmfh,sizeof(bmfh));
bmfh.bfType=0x4D42;//Magic#
bmfh.bfSize=sizeof(bmfh)+sizeof(BitMapInfo头)
+NPAL_ENT*sizeof(PALETTEENTRY)+w*h;//如果w/h未知,则为总文件大小
bmfh.bfOffBits=sizeof(bmfh)+sizeof(BitMapInfo头)
+NPAL_ENT*sizeof(PALETTEENTRY);
位图信息头;
零内存(&bmih,sizeof(bmih));
bmih.biWidth=w;
bmih.biHeight=h;
bmih.biSize=sizeof(bmih);
双翼飞机=1;
bmih.bibibitcount=8;
bmih.biCompression=BI_RGB;
bmih.biSizeImage=w*h;
int palSize=NPAL_ENT*sizeof(PALETTEENTRY);
LOGPALETTE*logpal=(LOGPALETTE*)新字节[sizeof(LOGPALETTE)+palSize];
如果(!logpal){delete[]imgData;printf(“!logpal\n”);退出(4);}
logpal->palVersion=0x300;
logpal->palNumEntries=NPAL;
int i=0;
确实{//调色板格式各不相同。这对我来说很有用
logpal->palPalEntry[i].peRed=i;
logpal->触诊[i].peGreen=i;
logpal->触诊[i].peBlue=i;
logpal->palPalEntry[i].peFlags=NULL;
}而(++ilprintf(“无法重新打开bmpfile”);删除[]日志;返回0;}
}
fclose(bmpFile);
if(totWrit!=bmfh.bfSize){
printf(“BMP大小不匹配:%d/%d.”,totWrit,bmfh.bfSize);
删除[]imgData;
删除[]logpal;
出口(-1);
}
//清理
删除[]imgData;
删除[]logpal;
返回0;
}
我不会使用文件*
操作读取图像数据:您可以让它工作,但它冗长且容易出现问题,如fread()
认为Ctrl-Z意味着文件结束,而且你必须记住在完成后关闭文件。相反,我会使用MFCCFile
类。这看起来像
BYTE* pbyImageData = NULL;
CFile fileImage;
if(fileImage.Open(_T("\\rawimage.dat"), CFile::modeRead, NULL))
{
pbyImageData = new BYTE[fileImage.GetLength()];
fileImage.Read(pbyImageData, fileImage.GetLength());
}
在Windows CE中使用CDIBSectionCE
类可以轻松处理位图。这可从CodeGuru()获得。使用CDIBSectionCE,您可以执行以下操作
// The BITMAPINFO struct is almost completely unusable because it has
// space for a less-than-generous 1-colour palette, so I always end up
// creating a home-grown version with room for 256 colours:
struct BITMAPINFO256
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[256];
} stcBmpInfo;
// ...Fill in the BITMAPINFO structure -- bitmap size etc.
stcBmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
stcBmpInfo.bmiHeader.biWidth = ....
/// etc ... keep the code you have for filling in bitmap info at present
// Now load up the image into the DIB Section
CDIBSectionCE bmp;
bmp.SetBitmap((BITMAPINFO*)&stcBmpInfo, pbyImageData);
// Now write the bitmap out as a file
bmp.Save(_T("\\mybitmap.bmp");
请注意,cdibsection
处理所有的文件头内容
// The BITMAPINFO struct is almost completely unusable because it has
// space for a less-than-generous 1-colour palette, so I always end up
// creating a home-grown version with room for 256 colours:
struct BITMAPINFO256
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[256];
} stcBmpInfo;
// ...Fill in the BITMAPINFO structure -- bitmap size etc.
stcBmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
stcBmpInfo.bmiHeader.biWidth = ....
/// etc ... keep the code you have for filling in bitmap info at present
// Now load up the image into the DIB Section
CDIBSectionCE bmp;
bmp.SetBitmap((BITMAPINFO*)&stcBmpInfo, pbyImageData);
// Now write the bitmap out as a file
bmp.Save(_T("\\mybitmap.bmp");