图片文件是有固定格式的,像BMP图片:文件头+位图的颜色数据。
文件头一般在读取的时候是使用下面的代码:
BITMAPFILEHEADER fileheader={0};
fread(&fileheader,sizeof(fileheader),1,fp);
if(fileheader.bfType!=0x4D42) // 判断是否为BMP图片
{
fclose(fp);
return ;
}
BITMAPINFOHEADER head;
fread(&head,sizeof(BITMAPINFOHEADER),1,fp);
long bmpWidth = head.biWidth; //获取图片的宽
long bmpHeight = head.biHeight; //获取图片的宽
WORD biBitCount = head.biBitCount;
if(biBitCount != 24) // 是否为24位位图
{
::AfxMessageBox(_T("请选择24位位图!"));
fclose(fp);
return ;
}
文件读到这里了就要读到位图的颜色数据了,那么在读取前,我们需要知道数据的大小,这样才能把分配具体大学的缓冲区,之后把数据完整的读取到缓冲区内。
那么计算位图数据的大小一般用下面的代码去做。
int totalSize = (bmpWidth *biBitCount/8+3)/4*4*bmpHeight;
BYTE *pBmpBuf = new BYTE[totalSize];
在这些工作做完之后,我们就使用fread命令直接读取文件内容即可,直到读到文件结束。
整个具体的代码实现如下:
FILE *fp=NULL;
int ret = fopen_s(&fp,"D:\\11.bmp","rb");
if(fp==0)
{
return ;
}
BITMAPFILEHEADER fileheader={0};
fread(&fileheader,sizeof(fileheader),1,fp);
if(fileheader.bfType!=0x4D42)
{
fclose(fp);
return ;
}
BITMAPINFOHEADER head;
fread(&head,sizeof(BITMAPINFOHEADER),1,fp);
long bmpWidth = head.biWidth;
long bmpHeight = head.biHeight;
WORD biBitCount = head.biBitCount;
if(biBitCount != 24)
{
::AfxMessageBox(_T("请选择24位位图!"));
fclose(fp);
return ;
}
int totalSize = (bmpWidth *biBitCount/8+3)/4*4*bmpHeight;
BYTE *pBmpBuf = new BYTE[totalSize];
size_t size = 0;
while(true)
{
int iret = fread(&pBmpBuf[size],1,1,fp);
if(iret == 0)
break;
size = size + iret;
}
fclose(fp);
int i,j;
CClientDC dc(this);
int pitch=bmpWidth%4;
for(i=0;i<bmpHeight;i++)
{
int realPitch=i*pitch;
for(j=0;j<bmpWidth;j++)
{
dc.SetPixel(j,i,RGB(
pBmpBuf[(i*bmpWidth+j)*3+2+realPitch],
pBmpBuf[(i*bmpWidth+j)*3+1+realPitch],
pBmpBuf[(i*bmpWidth+j)*3+realPitch]));
}
}
delete [] pBmpBuf; pBmpBuf = NULL;
return ;
学以致用才是好,以上可能存在有不足的地方欢迎指出讨论。
(更多免费 C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等等多个知识点干货学习资料加群 960994558)