图片文件是有固定格式的,像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 ;
这个打印出来的图片是倒过来的,具体什么原因,大家自己去想吧,学以致用才是好,这个代码我也是经常使用的。
如果对代码有问题的,可以回复我。