读取文件中的图像数据保存为BMP图片问题

时间:2022-03-15 10:06:11
//读取文件数据
CStdioFile TempFile;
CString FilePathName;
CFileDialog FileDlg(TRUE);

if(IDOK ==FileDlg.DoModal())
FilePathName=FileDlg.GetPathName();

if(!TempFile.Open (FilePathName,CFile::modeReadWrite|CFile::typeBinary ))
{
return;
}

BYTE Buffer[8192]={0};
TempFile.Read (Buffer,8192);


// TODO: Add your control notification handler code here
    CFileDialog dlg(FALSE, NULL, NULL ,OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY, "Bitmap Files(*.bmp)|*.bmp", this);
if (dlg.DoModal() == IDOK) {




BITMAPFILEHEADER bfh = {0};
DWORD dwImageSize = 0;
DWORD dwBytesRead = 0;
BOOL bRVal = TRUE;
////////////////////////////////////////////黑白图像保存加入
int nTable = 0;

DWORD dwSize = 0;

if (m_pBmpInfo2->bmiHeader.biBitCount > 8) {
          nTable = 0;
}
else{
nTable = 256;
}
//////////////////////////////////////////////////////////////////////////////////
dwImageSize =  m_nImg2W * m_nImg2H * m_nImg2C*3; //计算图像大小,由视频输出窗口和视频格式确定

bfh.bfType = (WORD)'M' << 8 | 'B'; //定义文件类型

bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+nTable*sizeof(RGBQUAD); //定义文件头大小
// bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); //定义文件头大小

bfh.bfSize = bfh.bfOffBits + dwImageSize; //文件大小


CString strSaveImageName="1.bmp";

HANDLE hFile = ::CreateFile(strSaveImageName,
GENERIC_WRITE ,
0,
NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE) 
{
bRVal = FALSE;
}
else
{
::WriteFile(hFile, &bfh, sizeof(BITMAPFILEHEADER), &dwBytesRead, NULL );

dwSize = sizeof(BITMAPINFOHEADER) + nTable * sizeof(RGBQUAD);
::WriteFile(hFile, m_pBmpInfo2, dwSize, &dwBytesRead, NULL );

::WriteFile(hFile,  Buffer, dwImageSize, &dwBytesRead, NULL );

CloseHandle(hFile);
}

运用上面的方法为什么保存的图片是黑色的啊?文件中保存的是从USB口采集过来的黑白图像数据,Buffer是我从文件中读取的数据,希望指点指点啊


22 个解决方案

#1


你确定数据的格式是正确的么

#2


文件中保存的是从USB口采集过来的黑白图像数据
--------------------------------------
什么格式?黑白可是表示2色位图

#3


就是裸的图像数据保存为文件,我从文件中将它读取出来

xianglitian
 
(向立天) 
您所指的正确的数据格式是什么样的啊?给个提示吧

#4


xianglitian
 
(向立天) 
您所指的正确的数据格式是什么样的啊?
我操作的数据是裸的图像数据

#5


引用 4 楼 xiaoxiao0932 的回复:
xianglitian
 
(向立天) 
您所指的正确的数据格式是什么样的啊?
我操作的数据是裸的图像数据

就是说你这个数据是不是直接符合你要保存的文件的数据要求
很明显你要保存位图文件
所以数据应该是四个字节表示一个像素
然后整个数组应该符合图片的长宽要求

#6


我的图像数据是一个字节表示一个像素点的啊,大小为512*256的8位的图像,求指点啊,现在能保存图片但是锯齿情况严重,还变形啊

#7


引用 6 楼 xiaoxiao0932 的回复:
我的图像数据是一个字节表示一个像素点的啊,大小为512*256的8位的图像,求指点啊,现在能保存图片但是锯齿情况严重,还变形啊

那你这个数据明显不符合格式要求啊
你有其他办法看到图像吗

#8


图像可以通过PAL方式连接到显示器上显示,很清晰,颜色也可以

纠结啊 ,数据不符合格式要求这个有什么办法吗?

#9


如果能显示在vc程序的客户区。
可以写个截屏功能,把显示的内容保存成bmp.
这样做是否满足需求?
引用 8 楼 xiaoxiao0932 的回复:
图像可以通过PAL方式连接到显示器上显示,很清晰,颜色也可以

纠结啊 ,数据不符合格式要求这个有什么办法吗?

#10


引用 8 楼 xiaoxiao0932 的回复:
图像可以通过PAL方式连接到显示器上显示,很清晰,颜色也可以

纠结啊 ,数据不符合格式要求这个有什么办法吗?

你连的是监视器吧
你怎么连的
视频线?

#11


引用 10 楼 xianglitian 的回复:
引用 8 楼 xiaoxiao0932 的回复:

图像可以通过PAL方式连接到显示器上显示,很清晰,颜色也可以

纠结啊 ,数据不符合格式要求这个有什么办法吗?

你连的是监视器吧
你怎么连的
视频线?

我连接的是监视器,用视频线连的PAL制的图像

#12


保存图头文件高宽等参数要设置,bmp文件是左下角为零点

#13


引用 11 楼 xiaoxiao0932 的回复:
引用 10 楼 xianglitian 的回复:
引用 8 楼 xiaoxiao0932 的回复:

图像可以通过PAL方式连接到显示器上显示,很清晰,颜色也可以

纠结啊 ,数据不符合格式要求这个有什么办法吗?

你连的是监视器吧
你怎么连的
视频线?

我连接的是监视器,用视频线连的PAL制的图像

监视器上看到的是模拟信号啊
那你的数据怎么来的
如果你在处理视频那可以通过视频采集工具弄啊
你到底在实现什么需求

#14


图像采集设备先将采集到的图像数据保存,然后我通过USB口用上位机将数据读取出来,由于数据很大,我先将数据保存为TXT文件,然后再从文件读取数据转存为一张一张的BMP图片,现在就是保存BMP文件出现问题啊

我读取的数据是一个字节表示一个像素点,256灰度的,保存成BMP效果很糟糕,锯齿严重还出现变形情况,现在也没找到原因,请指点啊

#15


在bmp中每一行像素所占的空间必须是4字节的整数倍,很有可能是这个造成的。需要补零对其,请查阅相关书籍

#16


(宽度*8+31)/32 *4

是这样吗???

#17


没错
(宽度*8+31)/32 *4 算的是bit数。

#18


USB口采集过来的黑白图像数据,是压缩格式,还是没有经过压缩的格式?

#19


你看看OpenCV的相关资料吧

#20


1、dwImageSize是图像的大小,根据图像尺寸、输出像素色深(8、16、32bpp)以及每行必须4字节对齐计算得到,dwImageSize = m_nImg2W * m_nImg2H * m_nImg2C*3中m_nImg2C*3是什么意思?
2、Buffer是从USB接口采集到的灰度图像像素数组,::WriteFile(hFile, Buffer, dwImageSize, &dwBytesRead, NULL ),是将接收到的数据写入到hFile对应的BMP图像文件中。Buffer总共8192BYTE,dwImageSize为啥还乘以3,8192不能被3整除。如果是乘以3表示32bpp,建议另开辟数组。
3、建议仔细检查BMP文件的前54个字节。

#21


3、建议仔细检查BMP文件的前54个字节。
同意这个,头文件写的有偏差或者头文件里面写入的数值不对

#22


[code=C/C++]

//图形
bool ENtool::LHxxDISPLAY_SAVEBMP( char*  FileName,int x,int y,int w,int h )  
{  
/*
HDC hDC = ::GetDC(NULL); //获取屏幕DC
COLORREF clr = ::GetPixel(hDC, 200, 200); //获取当前鼠标点像素值

D3dCom.tp1.x=GetRValue(clr);
D3dCom.tp1.y=GetGValue(clr); //分解出绿色值
D3dCom.tp1.z=GetBValue(clr); //分解出蓝色值
::ReleaseDC(NULL, hDC); //释放屏幕DC
*/
HBITMAP  hBitmap;
RECT rect;
//获得屏幕分辩率
rect.left=x;
rect.top=y;
rect.right=w+rect.left;
rect.bottom=h+rect.top;
// rect.right=GetSystemMetrics(SM_CXSCREEN);
// rect.bottom=GetSystemMetrics(SM_CYSCREEN);
//调用截屏函数
hBitmap=(HBITMAP)GetScreen(&rect);
//设备描述表  
HDC  hDC;  
//当前分辨率下每象素所占字节数  
int  iBits;  
//位图中每象素所占字节数  
WORD  wBitCount;  
//定义调色板大小,  位图中像素字节大小  ,位图文件大小  ,  写入文件字节数    
DWORD  dwPaletteSize=0,  dwBmBitsSize=0,  dwDIBSize=0,  dwWritten=0;    
//位图属性结构    
BITMAP  Bitmap;      
//位图文件头结构  
BITMAPFILEHEADER  bmfHdr;      
//位图信息头结构    
BITMAPINFOHEADER  bi;      
//指向位图信息头结构      
LPBITMAPINFOHEADER  lpbi;      
//定义文件,分配内存句柄,调色板句柄    
HANDLE  fh,  hDib,  hPal,hOldPal=NULL;   
//计算位图文件每个像素所占字节数    
hDC  =  CreateDC("DISPLAY",  NULL,  NULL,  NULL);  
iBits  =  GetDeviceCaps(hDC,  BITSPIXEL)  *  GetDeviceCaps(hDC,  PLANES);    
DeleteDC(hDC);    
if  (iBits  <=  1)                        wBitCount  =  1;    
else  if  (iBits  <=  4)              wBitCount  =  4;    
else  if  (iBits  <=  8)              wBitCount  =  8;    
else                                                              wBitCount  =  24;     
GetObject(hBitmap,  sizeof(Bitmap),  (LPSTR)&Bitmap);  
bi.biSize                                    =  sizeof(BITMAPINFOHEADER);  
bi.biWidth                                    =  Bitmap.bmWidth;  
bi.biHeight                                    =  Bitmap.bmHeight;  
bi.biPlanes                                    =  1;  
bi.biBitCount                        =  wBitCount;  
bi.biCompression            =  BI_RGB;  
bi.biSizeImage                        =  0;  
bi.biXPelsPerMeter            =  0;  
bi.biYPelsPerMeter            =  0;  
bi.biClrImportant            =  0;  
bi.biClrUsed                        =  0;   
dwBmBitsSize  =  ((Bitmap.bmWidth  *  wBitCount  +  31)  /  32)  *  4  *  Bitmap.bmHeight;   
//为位图内容分配内存    
hDib  =  GlobalAlloc(GHND,dwBmBitsSize  +  dwPaletteSize  +  sizeof(BITMAPINFOHEADER));    
lpbi  =  (LPBITMAPINFOHEADER)GlobalLock(hDib);    
*lpbi  =  bi;    
//  处理调色板      
hPal  =  GetStockObject(DEFAULT_PALETTE);    
if  (hPal)    
{    
   hDC  =  ::GetDC(NULL);    
   hOldPal  =  ::SelectPalette(hDC,  (HPALETTE)hPal,  FALSE);    
   RealizePalette(hDC);    
}  
//  获取该调色板下新的像素值    
GetDIBits(hDC,  hBitmap,  0,  (UINT)  Bitmap.bmHeight,  (LPSTR)lpbi  +  sizeof(BITMAPINFOHEADER)    
   +dwPaletteSize,            (BITMAPINFO  *)lpbi,  DIB_RGB_COLORS);     
//恢复调色板      
if  (hOldPal)    
{    
   ::SelectPalette(hDC,  (HPALETTE)hOldPal,  TRUE);    
   RealizePalette(hDC);    
   ::ReleaseDC(NULL,  hDC);    

//创建位图文件      
fh  =  CreateFile(FileName,  GENERIC_WRITE,0,  NULL,  CREATE_ALWAYS,    
   FILE_ATTRIBUTE_NORMAL    |  FILE_FLAG_SEQUENTIAL_SCAN,  NULL);     
if  (fh  ==  INVALID_HANDLE_VALUE)    return  FALSE;   
//  设置位图文件头    
bmfHdr.bfType  =  0x4D42;  //  "BM"    
dwDIBSize  =  sizeof(BITMAPFILEHEADER)  +  sizeof(BITMAPINFOHEADER)  +  dwPaletteSize  +  dwBmBitsSize;      
bmfHdr.bfSize  =  dwDIBSize;    
bmfHdr.bfReserved1  =  0;    
bmfHdr.bfReserved2  =  0;    
bmfHdr.bfOffBits  =  (DWORD)sizeof(BITMAPFILEHEADER)  +  (DWORD)sizeof(BITMAPINFOHEADER)  +  dwPaletteSize;    
//  写入位图文件头    
WriteFile(fh,  (LPSTR)&bmfHdr,  sizeof(BITMAPFILEHEADER),  &dwWritten,  NULL);    
//  写入位图文件其余内容    
WriteFile(fh,  (LPSTR)lpbi,  dwDIBSize,  &dwWritten,  NULL);    
//清除      
GlobalUnlock(hDib);    
GlobalFree(hDib);    
CloseHandle(fh);
DeleteObject(hBitmap);
return  TRUE;  


[/C/C++]

#1


你确定数据的格式是正确的么

#2


文件中保存的是从USB口采集过来的黑白图像数据
--------------------------------------
什么格式?黑白可是表示2色位图

#3


就是裸的图像数据保存为文件,我从文件中将它读取出来

xianglitian
 
(向立天) 
您所指的正确的数据格式是什么样的啊?给个提示吧

#4


xianglitian
 
(向立天) 
您所指的正确的数据格式是什么样的啊?
我操作的数据是裸的图像数据

#5


引用 4 楼 xiaoxiao0932 的回复:
xianglitian
 
(向立天) 
您所指的正确的数据格式是什么样的啊?
我操作的数据是裸的图像数据

就是说你这个数据是不是直接符合你要保存的文件的数据要求
很明显你要保存位图文件
所以数据应该是四个字节表示一个像素
然后整个数组应该符合图片的长宽要求

#6


我的图像数据是一个字节表示一个像素点的啊,大小为512*256的8位的图像,求指点啊,现在能保存图片但是锯齿情况严重,还变形啊

#7


引用 6 楼 xiaoxiao0932 的回复:
我的图像数据是一个字节表示一个像素点的啊,大小为512*256的8位的图像,求指点啊,现在能保存图片但是锯齿情况严重,还变形啊

那你这个数据明显不符合格式要求啊
你有其他办法看到图像吗

#8


图像可以通过PAL方式连接到显示器上显示,很清晰,颜色也可以

纠结啊 ,数据不符合格式要求这个有什么办法吗?

#9


如果能显示在vc程序的客户区。
可以写个截屏功能,把显示的内容保存成bmp.
这样做是否满足需求?
引用 8 楼 xiaoxiao0932 的回复:
图像可以通过PAL方式连接到显示器上显示,很清晰,颜色也可以

纠结啊 ,数据不符合格式要求这个有什么办法吗?

#10


引用 8 楼 xiaoxiao0932 的回复:
图像可以通过PAL方式连接到显示器上显示,很清晰,颜色也可以

纠结啊 ,数据不符合格式要求这个有什么办法吗?

你连的是监视器吧
你怎么连的
视频线?

#11


引用 10 楼 xianglitian 的回复:
引用 8 楼 xiaoxiao0932 的回复:

图像可以通过PAL方式连接到显示器上显示,很清晰,颜色也可以

纠结啊 ,数据不符合格式要求这个有什么办法吗?

你连的是监视器吧
你怎么连的
视频线?

我连接的是监视器,用视频线连的PAL制的图像

#12


保存图头文件高宽等参数要设置,bmp文件是左下角为零点

#13


引用 11 楼 xiaoxiao0932 的回复:
引用 10 楼 xianglitian 的回复:
引用 8 楼 xiaoxiao0932 的回复:

图像可以通过PAL方式连接到显示器上显示,很清晰,颜色也可以

纠结啊 ,数据不符合格式要求这个有什么办法吗?

你连的是监视器吧
你怎么连的
视频线?

我连接的是监视器,用视频线连的PAL制的图像

监视器上看到的是模拟信号啊
那你的数据怎么来的
如果你在处理视频那可以通过视频采集工具弄啊
你到底在实现什么需求

#14


图像采集设备先将采集到的图像数据保存,然后我通过USB口用上位机将数据读取出来,由于数据很大,我先将数据保存为TXT文件,然后再从文件读取数据转存为一张一张的BMP图片,现在就是保存BMP文件出现问题啊

我读取的数据是一个字节表示一个像素点,256灰度的,保存成BMP效果很糟糕,锯齿严重还出现变形情况,现在也没找到原因,请指点啊

#15


在bmp中每一行像素所占的空间必须是4字节的整数倍,很有可能是这个造成的。需要补零对其,请查阅相关书籍

#16


(宽度*8+31)/32 *4

是这样吗???

#17


没错
(宽度*8+31)/32 *4 算的是bit数。

#18


USB口采集过来的黑白图像数据,是压缩格式,还是没有经过压缩的格式?

#19


你看看OpenCV的相关资料吧

#20


1、dwImageSize是图像的大小,根据图像尺寸、输出像素色深(8、16、32bpp)以及每行必须4字节对齐计算得到,dwImageSize = m_nImg2W * m_nImg2H * m_nImg2C*3中m_nImg2C*3是什么意思?
2、Buffer是从USB接口采集到的灰度图像像素数组,::WriteFile(hFile, Buffer, dwImageSize, &dwBytesRead, NULL ),是将接收到的数据写入到hFile对应的BMP图像文件中。Buffer总共8192BYTE,dwImageSize为啥还乘以3,8192不能被3整除。如果是乘以3表示32bpp,建议另开辟数组。
3、建议仔细检查BMP文件的前54个字节。

#21


3、建议仔细检查BMP文件的前54个字节。
同意这个,头文件写的有偏差或者头文件里面写入的数值不对

#22


[code=C/C++]

//图形
bool ENtool::LHxxDISPLAY_SAVEBMP( char*  FileName,int x,int y,int w,int h )  
{  
/*
HDC hDC = ::GetDC(NULL); //获取屏幕DC
COLORREF clr = ::GetPixel(hDC, 200, 200); //获取当前鼠标点像素值

D3dCom.tp1.x=GetRValue(clr);
D3dCom.tp1.y=GetGValue(clr); //分解出绿色值
D3dCom.tp1.z=GetBValue(clr); //分解出蓝色值
::ReleaseDC(NULL, hDC); //释放屏幕DC
*/
HBITMAP  hBitmap;
RECT rect;
//获得屏幕分辩率
rect.left=x;
rect.top=y;
rect.right=w+rect.left;
rect.bottom=h+rect.top;
// rect.right=GetSystemMetrics(SM_CXSCREEN);
// rect.bottom=GetSystemMetrics(SM_CYSCREEN);
//调用截屏函数
hBitmap=(HBITMAP)GetScreen(&rect);
//设备描述表  
HDC  hDC;  
//当前分辨率下每象素所占字节数  
int  iBits;  
//位图中每象素所占字节数  
WORD  wBitCount;  
//定义调色板大小,  位图中像素字节大小  ,位图文件大小  ,  写入文件字节数    
DWORD  dwPaletteSize=0,  dwBmBitsSize=0,  dwDIBSize=0,  dwWritten=0;    
//位图属性结构    
BITMAP  Bitmap;      
//位图文件头结构  
BITMAPFILEHEADER  bmfHdr;      
//位图信息头结构    
BITMAPINFOHEADER  bi;      
//指向位图信息头结构      
LPBITMAPINFOHEADER  lpbi;      
//定义文件,分配内存句柄,调色板句柄    
HANDLE  fh,  hDib,  hPal,hOldPal=NULL;   
//计算位图文件每个像素所占字节数    
hDC  =  CreateDC("DISPLAY",  NULL,  NULL,  NULL);  
iBits  =  GetDeviceCaps(hDC,  BITSPIXEL)  *  GetDeviceCaps(hDC,  PLANES);    
DeleteDC(hDC);    
if  (iBits  <=  1)                        wBitCount  =  1;    
else  if  (iBits  <=  4)              wBitCount  =  4;    
else  if  (iBits  <=  8)              wBitCount  =  8;    
else                                                              wBitCount  =  24;     
GetObject(hBitmap,  sizeof(Bitmap),  (LPSTR)&Bitmap);  
bi.biSize                                    =  sizeof(BITMAPINFOHEADER);  
bi.biWidth                                    =  Bitmap.bmWidth;  
bi.biHeight                                    =  Bitmap.bmHeight;  
bi.biPlanes                                    =  1;  
bi.biBitCount                        =  wBitCount;  
bi.biCompression            =  BI_RGB;  
bi.biSizeImage                        =  0;  
bi.biXPelsPerMeter            =  0;  
bi.biYPelsPerMeter            =  0;  
bi.biClrImportant            =  0;  
bi.biClrUsed                        =  0;   
dwBmBitsSize  =  ((Bitmap.bmWidth  *  wBitCount  +  31)  /  32)  *  4  *  Bitmap.bmHeight;   
//为位图内容分配内存    
hDib  =  GlobalAlloc(GHND,dwBmBitsSize  +  dwPaletteSize  +  sizeof(BITMAPINFOHEADER));    
lpbi  =  (LPBITMAPINFOHEADER)GlobalLock(hDib);    
*lpbi  =  bi;    
//  处理调色板      
hPal  =  GetStockObject(DEFAULT_PALETTE);    
if  (hPal)    
{    
   hDC  =  ::GetDC(NULL);    
   hOldPal  =  ::SelectPalette(hDC,  (HPALETTE)hPal,  FALSE);    
   RealizePalette(hDC);    
}  
//  获取该调色板下新的像素值    
GetDIBits(hDC,  hBitmap,  0,  (UINT)  Bitmap.bmHeight,  (LPSTR)lpbi  +  sizeof(BITMAPINFOHEADER)    
   +dwPaletteSize,            (BITMAPINFO  *)lpbi,  DIB_RGB_COLORS);     
//恢复调色板      
if  (hOldPal)    
{    
   ::SelectPalette(hDC,  (HPALETTE)hOldPal,  TRUE);    
   RealizePalette(hDC);    
   ::ReleaseDC(NULL,  hDC);    

//创建位图文件      
fh  =  CreateFile(FileName,  GENERIC_WRITE,0,  NULL,  CREATE_ALWAYS,    
   FILE_ATTRIBUTE_NORMAL    |  FILE_FLAG_SEQUENTIAL_SCAN,  NULL);     
if  (fh  ==  INVALID_HANDLE_VALUE)    return  FALSE;   
//  设置位图文件头    
bmfHdr.bfType  =  0x4D42;  //  "BM"    
dwDIBSize  =  sizeof(BITMAPFILEHEADER)  +  sizeof(BITMAPINFOHEADER)  +  dwPaletteSize  +  dwBmBitsSize;      
bmfHdr.bfSize  =  dwDIBSize;    
bmfHdr.bfReserved1  =  0;    
bmfHdr.bfReserved2  =  0;    
bmfHdr.bfOffBits  =  (DWORD)sizeof(BITMAPFILEHEADER)  +  (DWORD)sizeof(BITMAPINFOHEADER)  +  dwPaletteSize;    
//  写入位图文件头    
WriteFile(fh,  (LPSTR)&bmfHdr,  sizeof(BITMAPFILEHEADER),  &dwWritten,  NULL);    
//  写入位图文件其余内容    
WriteFile(fh,  (LPSTR)lpbi,  dwDIBSize,  &dwWritten,  NULL);    
//清除      
GlobalUnlock(hDib);    
GlobalFree(hDib);    
CloseHandle(fh);
DeleteObject(hBitmap);
return  TRUE;  


[/C/C++]