www.pudn.com > pccode_2006910124551680.rar > Bmpfile.cpp
// bmpops.cpp : implementation of the BMPFile class
//
// This handles the reading and writing of BMP files.
//
//
#include "stdafx.h"
#include "bmpfile.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
BMPFile::BMPFile()
{
m_errorText="OK";
}
BMPFile::~BMPFile()
{
}
////////////////////////////////////////////////////////////////////////////
// write a 24-bit BMP file
//
// image MUST be a packed buffer (DWORD-aligned)
void BMPFile::SaveBMP(CString fileName, // output path
BYTE * buf, // BGR buffer
int width, // pixels
int height)
{
short res1=0;
short res2=0;
long pixoff=54;
long compression=0;
long cmpsize=0;
long colors=0;
long impcol=0;
char m1='B';
char m2='M';
m_errorText="OK";
int imagesize=(width*24+31)/32*4*height;
long bmfsize=sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
imagesize;
long byteswritten=0;
BITMAPINFOHEADER header;
header.biSize=40; // header size
header.biWidth=width;
header.biHeight=height;
header.biPlanes=1;
header.biBitCount=24; // RGB encoded, 24 bit
header.biCompression=BI_RGB; // no compression
header.biSizeImage=0;
header.biXPelsPerMeter=0;
header.biYPelsPerMeter=0;
header.biClrUsed=0;
header.biClrImportant=0;
FILE *fp;
fp=fopen(fileName,"wb");//写文件到磁盘
if (fp==NULL) {
m_errorText="Can't open file for writing";
return;
}
// should probably check for write errors here...
fwrite((BYTE *)&(m1),1,1,fp); byteswritten+=1;
fwrite((BYTE *)&(m2),1,1,fp); byteswritten+=1;
fwrite((long *)&(bmfsize),4,1,fp); byteswritten+=4;
fwrite((int *)&(res1),2,1,fp); byteswritten+=2;
fwrite((int *)&(res2),2,1,fp); byteswritten+=2;
fwrite((long *)&(pixoff),4,1,fp); byteswritten+=4;
fwrite((BITMAPINFOHEADER *)&header,sizeof(BITMAPINFOHEADER),1,fp);
byteswritten+=sizeof(BITMAPINFOHEADER);
int r=fwrite(buf,imagesize,1,fp); // buf is double word aligned.
if(r=-1){
m_errorText="Write image data failed!";
}
fclose(fp);
}
////////////////////////////////////////////////////////////////////////////////////
//
// 1,4,8 bit BMP stuff
//
// if you have a color-mapped image and a color map...
//
// the BMP saving code in SaveColorMappedBMP modified from Programming
// for Graphics Files in C and C++, by John Levine.
void BMPFile::SaveBMP(CString fileName, // output path
BYTE * colormappedbuffer, // one BYTE per pixel colormapped image
int width,
int height,
int bitsperpixel, // 1, 4, 8
int colors, // number of colors (number of RGBQUADs)
RGBQUAD *colormap) // array of RGBQUADs
{
if(colormap==NULL)
return;
if(colormappedbuffer==NULL)
return;
int datasize, cmapsize, byteswritten, row, col;
m_errorText="OK";
if (bitsperpixel == 24) {
// the routines could be combined, but i don't feel like it
m_errorText="We don't do 24-bit files in here, sorry";
return;
} else
cmapsize = colors * 4;
datasize = BMP_PIXELSIZE(width, height, bitsperpixel);
long filesize = BMP_HEADERSIZE + cmapsize + datasize;
int res1, res2;
res1 = res2 = 0;
long pixeloffset = BMP_HEADERSIZE + cmapsize;
int bmisize = 40;
long cols = width;
long rows = height;
WORD planes = 1;
long compression =0;
long cmpsize = datasize;
long xscale = 0;
long yscale = 0;
long impcolors = colors;
FILE *fp;
fp = fopen(fileName, "wb");
if (fp==NULL) {
m_errorText="Can't Open";
return;
}
char bm[2];
bm[0]='B';
bm[1]='M';
// header stuff
BITMAPFILEHEADER bmfh;
bmfh.bfType=*(WORD *)&bm;
bmfh.bfSize= filesize;
bmfh.bfReserved1=0;
bmfh.bfReserved2=0;
bmfh.bfOffBits=pixeloffset;
fwrite(&bmfh, sizeof (BITMAPFILEHEADER), 1, fp);
BITMAPINFOHEADER bmih;
bmih.biSize = bmisize;
bmih.biWidth = cols;
bmih.biHeight = rows;
bmih.biPlanes = planes;
bmih.biBitCount =bitsperpixel;
bmih.biCompression = compression;
bmih.biSizeImage = cmpsize;
bmih.biXPelsPerMeter = xscale;
bmih.biYPelsPerMeter = yscale;
bmih.biClrUsed = colors;
bmih.biClrImportant = impcolors;
fwrite(&bmih, sizeof (BITMAPINFOHEADER), 1, fp);
if (cmapsize) {
int i;
for (i = 0; i< colors; i++) {
// following was modified by Yejiaming, USTC. May 30,2002
fwrite(&colormap[i],sizeof(RGBQUAD),1,fp);
// putc(colormap[i].rgbRed, fp);
// putc(colormap[i].rgbGreen, fp);
// putc(colormap[i].rgbBlue, fp);
// putc(0, fp); // dummy
}
}
byteswritten = BMP_HEADERSIZE + cmapsize;
for (row = 0; row< (int)height; row++) {
int pixbuf=0;
int nbits = 0;
for (col =0 ; col < (int)width; col++) {
int offset = row * width + col; // offset into our color-mapped RGB buffer
BYTE pval = *(colormappedbuffer + offset);
pixbuf = (pixbuf << bitsperpixel) | pval;
nbits += bitsperpixel;
if (nbits > 8) {
m_errorText="Error : nBits > 8????";
fclose(fp);
return;
}
if (nbits == 8) {
putc(pixbuf, fp);
pixbuf=0;
nbits=0;
byteswritten++;
}
} // cols
if (nbits > 0) {
// the following one sentence was added by Yejiaming, USTC. May 30,2002
pixbuf=pixbuf << (8-nbits);
putc(pixbuf, fp); // write partially filled byte
byteswritten++;
}
// DWORD align
while ((byteswritten -pixeloffset) & 3) {
putc(0, fp);
byteswritten++;
}
} //rows
if (byteswritten!=filesize) {
m_errorText="byteswritten != filesize";
}
fclose(fp);
}
// Following functions was added by Yejiaming,USTC. 2001.10
void BMPFile::DisplayBMP(CDC* pDC, BYTE *buffer, int width, int height, int x, int y, int dstWidth, int dstHeight)
{
if(pDC==NULL)
return;
if(buffer==NULL)
return;
BITMAPINFOHEADER bmiHeader;
bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmiHeader.biWidth = width;
bmiHeader.biHeight = height;
bmiHeader.biPlanes = 1;
bmiHeader.biBitCount = 24;
bmiHeader.biCompression = BI_RGB;
bmiHeader.biSizeImage = 0;
bmiHeader.biXPelsPerMeter = 0;
bmiHeader.biYPelsPerMeter = 0;
bmiHeader.biClrUsed = 0;
bmiHeader.biClrImportant = 0;
pDC->SetStretchBltMode(COLORONCOLOR);
StretchDIBits(pDC->m_hDC,
x,y,
dstWidth,
dstHeight,
0,0,
bmiHeader.biWidth,
bmiHeader.biHeight,
buffer,
(LPBITMAPINFO)&bmiHeader,
DIB_RGB_COLORS,
SRCCOPY);
}
void BMPFile::RGB2Gray(int width, int height, BYTE *pInput, BYTE *pOutput)
{
if(pInput==NULL)
return;
int widthbytes=(width*24+31)/32*4;
int row,col,rowoff,coloff,step=0;
BYTE bb,gg,rr;
for(row=0;row>7);
step++;
}
}
}
void BMPFile::Gray2RGB(int width, int height, BYTE *pInput, BYTE *pOutput)
{
if(pInput==NULL)
return;
int widthbytes=(width*24+31)/32*4;
int row,col,rowoff,coloff,step=0;
BYTE tmpGray;
for(row=0;rowbiCompression!=BI_RGB){
m_errorText="This is a compressed iamge! Ignore it!";
delete [] pBMIH;
pBMIH=NULL;
fclose(pFile);
return NULL;
}
// 输出
width=pBMIH->biWidth;
height=pBMIH->biHeight;
bitcount=pBMIH->biBitCount;
widthbytes=(width*24+31)/32*4;// 输出为24位图像数据,double word aligned!
// 读取图像数据,每行以四字节为边界
int widthbytes1=(width*bitcount+31)/32*4;
int imagesize=widthbytes1*height;
LPBYTE pData=new BYTE[imagesize];
if(!pData){
m_errorText="Allocate memory failed!";
delete [] pBMIH;
pBMIH=NULL;
fclose(pFile);
return NULL;
}
r=fread(pData,imagesize,1,pFile);
if(r==-1){
m_errorText="Read Image Data Error!";
delete [] pBMIH;
delete [] pData;
pData=NULL;
pBMIH=NULL;
fclose(pFile);
return NULL;
}
if(bitcount==24){
delete [] pBMIH;
pBMIH=NULL;
fclose(pFile);
return pData;
}
int outsize=widthbytes*height; // 24 bit,Double word aligned!
LPBYTE pOutBuf=new BYTE[outsize];
if(!pOutBuf){
m_errorText="Allocate memory failed!";
delete [] pData;
delete [] pBMIH;
pData=NULL;
pBMIH=NULL;
fclose(pFile);
return NULL;
}
int i,j;
if(bitcount==32){
for(i=0; i>5)<<3); //green
pOutBuf[offset2+2]=(BYTE)(((temp & 0x7c00)>>10)<<3); // red
}
}
}
if(bitcount==1 || bitcount==4 || bitcount==8){
RGBQUAD* prgb=(RGBQUAD*)((BYTE*)pBMIH+sizeof(BITMAPINFOHEADER));
for(i=0; i>(8-bitcount-s*bitcount))&mask;
pOutBuf[offset2+2]=prgb[index].rgbRed;
pOutBuf[offset2+1]=prgb[index].rgbGreen;
pOutBuf[offset2+0]=prgb[index].rgbBlue;
}
}
}
delete [] pData;
delete [] pBMIH;
pData=NULL;
pBMIH=NULL;
fclose(pFile);
return pOutBuf;
}
// Output: 24 bit-per-pixel, double word aligned
// lpvMem指向BITMAPINFOHEADER 结构
BYTE* BMPFile::AttachMemory(LPVOID lpvMem, int &width, int &height, int &bitcount, int &widthbytes)
{
// assumes contiguous BITMAPINFOHEADER, color table, image data
// color table could be zero length
LPBITMAPINFOHEADER lpBMIH = (LPBITMAPINFOHEADER) lpvMem;
// Output
width=lpBMIH->biWidth;
height=lpBMIH->biHeight;
bitcount=lpBMIH->biBitCount;
widthbytes=(width*24+31)/32*4;// 24 Bit-per-pixel,double word aligned!
int outsize=widthbytes*height;// out image size
BYTE* pImageData=new BYTE[outsize]; // out buf
if(!pImageData){
m_errorText="Allocate memory failed!";
return NULL;
}
if(bitcount==24){
memcpy(pImageData,(BYTE*)lpvMem+sizeof(BITMAPINFOHEADER),outsize);
return pImageData;
}
int widthbytes1=(width*bitcount+31)/32*4;// src image
int imagesize=widthbytes1*height;
BYTE* pSrcData=new BYTE[imagesize];
if(!pSrcData){
m_errorText="Allocate memory failed!";
delete [] pImageData;
pImageData=NULL;
return NULL;
}
int i,j;
if(bitcount==32){
memcpy(pSrcData,(BYTE*)lpvMem+sizeof(BITMAPINFOHEADER),imagesize);
for(i=0; i>5)<<3); //green
pImageData[offset2+2]=(BYTE)(((temp & 0x7c00)>>10)<<3); // red
}
}
}
if(bitcount==1 || bitcount==4 || bitcount==8){
int entry;
if(lpBMIH->biClrUsed==0)
entry=1<biClrUsed;
VERIFY(entry<=256);
RGBQUAD* prgb=(RGBQUAD*)((BYTE*)lpvMem+sizeof(BITMAPINFOHEADER));
int offset=sizeof(BITMAPINFOHEADER)+entry*sizeof(RGBQUAD);
memcpy(pSrcData,(BYTE*)lpvMem+offset,imagesize);
for(i=0; i>(8-bitcount-s*bitcount))&mask;
pImageData[offset2+2]=prgb[index].rgbRed;
pImageData[offset2+1]=prgb[index].rgbGreen;
pImageData[offset2+0]=prgb[index].rgbBlue;
}
}
}
delete [] pSrcData;
pSrcData=NULL;
return pImageData;
}
// Output: 24 bit-per-pixel, double word aligned
BYTE* BMPFile::AttachMapFile(CString filename,int& width,int& height,int& bitcount,int& widthbytes)
{
// if we open the same file twice, Windows treats it as 2 separate files
HANDLE hFile = ::CreateFile(filename, GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
ASSERT(hFile != INVALID_HANDLE_VALUE);
HANDLE hMap = ::CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if(hMap == NULL) {
m_errorText="Empty bitmap file";
CloseHandle(hFile);
return NULL;
}
LPVOID lpvFile = ::MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0); // map whole file
ASSERT(lpvFile != NULL);
LPBITMAPFILEHEADER pBMFH=(LPBITMAPFILEHEADER)lpvFile;
if(pBMFH->bfType != 0x4d42) {
m_errorText="Invalid bitmap file";
::UnmapViewOfFile(lpvFile);
::CloseHandle(hMap);
::CloseHandle(hFile);
hMap=NULL;
hFile = NULL;
return NULL;
}
LPBYTE lpvMem=(BYTE*)lpvFile+sizeof(BITMAPFILEHEADER);
BYTE* pImageData=AttachMemory(lpvMem,width,height,bitcount,widthbytes);
::UnmapViewOfFile(lpvFile);
::CloseHandle(hMap);
::CloseHandle(hFile);
hMap=NULL;
hFile=NULL;
return pImageData;
}
void BMPFile::CopyToMapFile(CString filename,BYTE* pData,int width,int height,int bitcount)
{
// 在这里不考虑颜色表,因为存的是24位BMP文件
int imagesize=(width*24+31)/32*4*height;
BITMAPFILEHEADER bmfh;
bmfh.bfType = 0x4d42; // 'BM'
bmfh.bfSize = imagesize + sizeof(BITMAPINFOHEADER)+sizeof(BITMAPFILEHEADER);
bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
HANDLE hFile = ::CreateFile(filename,
GENERIC_WRITE | GENERIC_READ,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
ASSERT(hFile != INVALID_HANDLE_VALUE);
int filesize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +imagesize; // 文件头+信息头+图像数据大小
HANDLE hMap = ::CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, filesize, NULL);
ASSERT(hMap != NULL);
LPVOID lpvFile = ::MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0); // map whole file
ASSERT(lpvFile != NULL);
LPBYTE lpbCurrent = (LPBYTE) lpvFile; // 同一内存
memcpy(lpbCurrent,&bmfh,sizeof(BITMAPFILEHEADER));
lpbCurrent+=sizeof(BITMAPFILEHEADER);
BITMAPINFOHEADER bmih;
bmih.biBitCount=24;
bmih.biWidth=width;
bmih.biHeight=height;
bmih.biPlanes=1;
bmih.biSize=sizeof(BITMAPINFOHEADER);
bmih.biClrImportant=0;
bmih.biClrUsed=0;
bmih.biCompression=BI_RGB;
bmih.biSizeImage=0;
bmih.biXPelsPerMeter=0;
bmih.biYPelsPerMeter=0;
memcpy(lpbCurrent,&bmih,sizeof(BITMAPINFOHEADER));
lpbCurrent+=sizeof(BITMAPINFOHEADER);
memcpy(lpbCurrent,pData,imagesize);
::UnmapViewOfFile(lpvFile);
::CloseHandle(hMap);
::CloseHandle(hFile);
hMap=NULL;
hFile=NULL;
}