mysql显示bmp图片_BMP格式图像的显示

使用多文档编程 也可以使用单文档编程

建立一个DIB图像的显示类 ImageDib

成员变量:

4个指针:

LPBYTE m_lpDib;      //指向DIB的指针

LPBITMAPINFOHEADER m_lpBmpInfoHead;  //图像信息头指针

LPRGBQUAD m_lpColorTable;     //图像颜色表指针

unsigned char * m_pImgData;     //图像数据指针

4个普通变量(存放图像的参数):

int m_imgWidth;       //图像的宽,像素为单位

int m_imgHeight;       //图像的高,像素为单位

int m_nBitCount;      //每像素占的位数

int m_nColorTableLength;      //颜色表长度(多少个表项)

1个句柄:

HPALETTE m_hPalette;     //逻辑调色板句柄

成员函数:

带参数构造函数  ImageDib(CSize size, int nBitCount, LPRGBQUAD lpColorTable, unsigned char *pImgData);           //带参数的构造函数

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.pngView Code

ImageDib::ImageDib(CSize size, intnBitCount, LPRGBQUAD lpColorTable,

unsignedchar *pImgData)

{//如果没有位图数据传入,我们认为是空的DIB,此时不分配DIB内存

if(pImgData==NULL){

m_lpDib=NULL;

m_lpColorTable=NULL;

m_pImgData=NULL; //图像数据

m_lpBmpInfoHead=NULL; //图像信息头

m_hPalette =NULL;

}else{//如果有位图数据传入//可以通过调用ReplaceDib()来实现 代码一样的//ReplaceDib(size,nBitCount,lpColorTable,pImgData);//图像的宽、高、每像素位数等成员变量赋值

m_imgWidth=size.cx;

m_imgHeight=size.cy;

m_nBitCount=nBitCount;//根据每像素位数,计算颜色表长度

m_nColorTableLength=ComputeColorTabalLength(nBitCount);//每行像素所占字节数,必须扩展成4的倍数

int lineByte=(m_imgWidth*nBitCount/8+3)/4*4;//位图数据缓冲区的大小(图像大小)

int imgBufSize=m_imgHeight*lineByte;//为m_lpDib一次性分配内存,生成DIB结构

m_lpDib=new BYTE [sizeof(BITMAPINFOHEADER) +

sizeof(RGBQUAD) * m_nColorTableLength+imgBufSize];//填写BITMAPINFOHEADER结构

m_lpBmpInfoHead =(LPBITMAPINFOHEADER) m_lpDib;

m_lpBmpInfoHead->biSize = sizeof(BITMAPINFOHEADER);

m_lpBmpInfoHead->biWidth =m_imgWidth;

m_lpBmpInfoHead->biHeight =m_imgHeight;

m_lpBmpInfoHead->biPlanes = 1;

m_lpBmpInfoHead->biBitCount =m_nBitCount;

m_lpBmpInfoHead->biCompression =BI_RGB;

m_lpBmpInfoHead->biSizeImage = 0;

m_lpBmpInfoHead->biXPelsPerMeter = 0;

m_lpBmpInfoHead->biYPelsPerMeter = 0;

m_lpBmpInfoHead->biClrUsed =m_nColorTableLength;

m_lpBmpInfoHead->biClrImportant =m_nColorTableLength;//调色板句柄初始化为空,有颜色表时,MakePalette()函数要生成新的调色板

m_hPalette =NULL;//如果有颜色表,则将颜色表拷贝进DIB的颜色表位置

if(m_nColorTableLength!=0){//m_lpColorTable指向DIB颜色表的起始位置

m_lpColorTable=(LPRGBQUAD)(m_lpDib+sizeof(BITMAPINFOHEADER));//颜色表拷贝

memcpy(m_lpColorTable,lpColorTable,sizeof(RGBQUAD) *m_nColorTableLength);//创建逻辑调色板

MakePalette();

}//m_pImgData指向DIB位图数据起始位置

m_pImgData = (LPBYTE)m_lpDib+sizeof(BITMAPINFOHEADER)+

sizeof(RGBQUAD) *m_nColorTableLength;//拷贝图像数据进DIB位图数据区

memcpy(m_pImgData,pImgData,imgBufSize);

}

}

读文件:      BOOL Read(LPCTSTR lpszPathName);   //DIB读函数

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.pngView Code

BOOL ImageDib::Read(LPCTSTR lpszPathName)

{//读模式打开图像文件

CFile file;if (!file.Open(lpszPathName, CFile::modeRead |CFile::shareDenyWrite))returnFALSE;

BITMAPFILEHEADER bmfh;//读取BITMAPFILEHEADER结构到变量bmfh中

int nCount=file.Read((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));//为m_lpDib分配空间,读取DIB进内存

if(m_lpDib!=NULL) delete []m_lpDib;

m_lpDib=new BYTE[file.GetLength() -sizeof(BITMAPFILEHEADER)];

file.Read(m_lpDib, file.GetLength()-sizeof(BITMAPFILEHEADER));//m_lpBmpInfoHead位置为m_lpDib起始位置

m_lpBmpInfoHead =(LPBITMAPINFOHEADER)m_lpDib;//为成员变量赋值

m_imgWidth=m_lpBmpInfoHead->biWidth;

m_imgHeight=m_lpBmpInfoHead->biHeight;

m_nBitCount=m_lpBmpInfoHead->biBitCount;//计算颜色表长度

m_nColorTableLength= ComputeColorTabalLength(m_lpBmpInfoHead->biBitCount);//如果有颜色表,则创建逻辑调色板

m_hPalette =NULL;if(m_nColorTableLength!=0){m_lpColorTable=(LPRGBQUAD)(m_lpDib+sizeof(BITMAPINFOHEADER));

MakePalette();

}//m_pImgData指向DIB的位图数据起始位置

m_pImgData = (LPBYTE)m_lpDib+sizeof(BITMAPINFOHEADER) +

sizeof(RGBQUAD) *m_nColorTableLength;returnTRUE;

}

写文件:     BOOL Write(LPCTSTR lpszPathName);       //DIB写函数

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.pngView Code

BOOL ImageDib::Write(LPCTSTR lpszPathName)

{//写模式打开文件

CFile file;if (!file.Open(lpszPathName, CFile::modeCreate |CFile::modeReadWrite|CFile::shareExclusive))returnFALSE;//填写文件头结构

BITMAPFILEHEADER bmfh;

bmfh.bfType= 0x4d42; //'BM'

bmfh.bfSize = 0;

bmfh.bfReserved1= bmfh.bfReserved2 = 0;

bmfh.bfOffBits= sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +

sizeof(RGBQUAD) *m_nColorTableLength;try{//文件头结构写进文件

file.Write((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));//文件信息头结构写进文件

file.Write(m_lpBmpInfoHead, sizeof(BITMAPINFOHEADER));//如果有颜色表的话,颜色表写进文件

if(m_nColorTableLength!=0)

file.Write(m_lpColorTable,sizeof(RGBQUAD) *m_nColorTableLength);//位图数据写进文件

int imgBufSize=(m_imgWidth*m_nBitCount/8+3)/4*4*m_imgHeight;

file.Write(m_pImgData, imgBufSize);

}catch(CException*pe) {

pe->Delete();

AfxMessageBox("write error");returnFALSE;

}//函数返回

returnTRUE;

}

计算颜色表长度:  int ComputeColorTabalLength(int nBitCount); //计算颜色表的长度

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.pngView Code

int ImageDib::ComputeColorTabalLength(intnBitCount)

{intcolorTableLength;switch(nBitCount) {case 1:

colorTableLength= 2;break;case 4:

colorTableLength= 16;break;case 8:

colorTableLength= 256;break;case 16:case 24:case 32:

colorTableLength= 0;break;default:

ASSERT(FALSE);

}

ASSERT((colorTableLength>= 0) && (colorTableLength <= 256));returncolorTableLength;

}

创建逻辑调色板:  void MakePalette();      //创建逻辑调色板

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.pngView Code

voidImageDib::MakePalette()

{//如果颜色表长度为0,则不创建逻辑调色板

if(m_nColorTableLength == 0)return;//删除旧的逻辑调色板句柄

if(m_hPalette !=NULL) ::DeleteObject(m_hPalette);//申请空间,根据颜色表生成LOGPALETTE结构

LPLOGPALETTE pLogPal = (LPLOGPALETTE) new char[2 * sizeof(WORD) +m_nColorTableLength* sizeof(PALETTEENTRY)];

pLogPal->palVersion = 0x300;

pLogPal->palNumEntries =m_nColorTableLength;

LPRGBQUAD m_lpDibQuad=(LPRGBQUAD) m_lpColorTable;for(int i = 0; i < m_nColorTableLength; i++) {

pLogPal->palPalEntry[i].peRed = m_lpDibQuad->rgbRed;

pLogPal->palPalEntry[i].peGreen = m_lpDibQuad->rgbGreen;

pLogPal->palPalEntry[i].peBlue = m_lpDibQuad->rgbBlue;

pLogPal->palPalEntry[i].peFlags = 0;

m_lpDibQuad++;

}//创建逻辑调色板

m_hPalette =::CreatePalette(pLogPal);//释放空间

delete pLogPal;

}

读取图像维数:  CSize GetDimensions();     //读取图像维数

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.pngView Code

CSize ImageDib::GetDimensions()

{if(m_lpDib == NULL) return CSize(0, 0);returnCSize(m_imgWidth, m_imgHeight);

}

图像绘制:      BOOL Draw(CDC* pDC, CPoint origin, CSize size); //图像绘制

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.pngView Code

BOOL ImageDib::Draw(CDC*pDC, CPoint origin, CSize size)

{

HPALETTE hOldPal=NULL; //旧的调色板句柄

if(m_lpDib == NULL) return FALSE; //如果DIB为空,则返回0

if(m_hPalette != NULL) { //如果DIB有调色板//将调色板选进设备环境中

hOldPal=::SelectPalette(pDC->GetSafeHdc(), m_hPalette, TRUE);

pDC->RealizePalette();

}

pDC->SetStretchBltMode(COLORONCOLOR); //设置位图伸缩模式//将DIB在pDC所指向的设备上进行显示

::StretchDIBits(pDC->GetSafeHdc(), origin.x, origin.y, size.cx, size.cy,0, 0, m_lpBmpInfoHead->biWidth, m_lpBmpInfoHead->biHeight,m_pImgData,

(LPBITMAPINFO) m_lpBmpInfoHead, DIB_RGB_COLORS, SRCCOPY);if(hOldPal!=NULL) //恢复旧的调色板

::SelectPalette(pDC->GetSafeHdc(), hOldPal, TRUE);returnTRUE;

}

用新的数据替代DIB:void ReplaceDib(CSize size, int nBitCount, LPRGBQUAD lpColorTable, unsigned char *pImgData);               //用新的数据替换DIB

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.pngView Code

void ImageDib::ReplaceDib(CSize size, intnBitCount,

LPRGBQUAD lpColorTable,unsignedchar *pImgData)

{//释放原DIB所占空间

Empty();//成员变量赋值

m_imgWidth=size.cx;

m_imgHeight=size.cy;

m_nBitCount=nBitCount;//计算颜色表的长度

m_nColorTableLength=ComputeColorTabalLength(nBitCount);//每行像素所占字节数,扩展成4的倍数

int lineByte=(m_imgWidth*nBitCount/8+3)/4*4;//位图数据的大小

int imgBufSize=m_imgHeight*lineByte;//为m_lpDib重新分配空间,以存放新的DIB

m_lpDib=new BYTE [sizeof(BITMAPINFOHEADER) +

sizeof(RGBQUAD) * m_nColorTableLength+imgBufSize];//填写位图信息头BITMAPINFOHEADER结构

m_lpBmpInfoHead =(LPBITMAPINFOHEADER) m_lpDib;

m_lpBmpInfoHead->biSize = sizeof(BITMAPINFOHEADER);

m_lpBmpInfoHead->biWidth =m_imgWidth;

m_lpBmpInfoHead->biHeight =m_imgHeight;

m_lpBmpInfoHead->biPlanes = 1;

m_lpBmpInfoHead->biBitCount =m_nBitCount;

m_lpBmpInfoHead->biCompression =BI_RGB;

m_lpBmpInfoHead->biSizeImage = 0;

m_lpBmpInfoHead->biXPelsPerMeter = 0;

m_lpBmpInfoHead->biYPelsPerMeter = 0;

m_lpBmpInfoHead->biClrUsed =m_nColorTableLength;

m_lpBmpInfoHead->biClrImportant =m_nColorTableLength;//调色板置空

m_hPalette =NULL;//如果有颜色表,则将颜色表拷贝至新生成的DIB,并创建逻辑调色板

if(m_nColorTableLength!=0){

m_lpColorTable=(LPRGBQUAD)(m_lpDib+sizeof(BITMAPINFOHEADER));

memcpy(m_lpColorTable,lpColorTable,sizeof(RGBQUAD) *m_nColorTableLength);

MakePalette();

}//m_pImgData指向DIB的位图数据起始位置

m_pImgData = (LPBYTE)m_lpDib+sizeof(BITMAPINFOHEADER)+

sizeof(RGBQUAD) *m_nColorTableLength;//将新位图数据拷贝至新的DIB中

memcpy(m_pImgData,pImgData,imgBufSize);

}

清理空间函数:  void Empty();                          //清理空间

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.pngView Code

voidImageDib::Empty()

{//释放DIB内存缓冲区

if(m_lpDib !=NULL) {

delete [] m_lpDib;

m_lpDib=NULL;

m_lpColorTable=NULL;

m_pImgData=NULL;

m_lpBmpInfoHead=NULL;

}//释放逻辑调色板缓冲区

if(m_hPalette !=NULL){

::DeleteObject(m_hPalette);

m_hPalette=NULL;

}

}

默认构造函数:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.pngView Code

ImageDib::ImageDib()

{

m_lpDib=NULL;//初始化m_lpDib为空。

m_lpColorTable=NULL; //颜色表指针为空

m_pImgData=NULL; //图像数据指针为空

m_lpBmpInfoHead=NULL; //图像信息头指针为空

m_hPalette = NULL; //调色板为空

}

默认析构函数:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.pngView Code

ImageDib::~ImageDib()

{//释放m_lpDib所指向的内存缓冲区

if(m_lpDib !=NULL)

delete [] m_lpDib;//如果有调色板,释放调色板缓冲区

if(m_hPalette !=NULL)

::DeleteObject(m_hPalette);

}

编写好ImageDib类后,在doc文件类中添加一个ImageDib类的指针,在构造函数中new出来,在析构函数中delete,然后重写OnOpenDocument()函数 在其中调用读函数打开图像 在View类的OnDraw()中调用ImageDib类的绘制函数 将图像绘制在打开的新文件中

总结:编程的关键在于几个指针的赋值,指向DIB的指针的分配空间,位图信息头等结构的赋值等等。

只要记住:

BMP文件=位图头文件+位图信息头+颜色表+数据块    (等号后边的内容按顺序写的)

DIB=位图信息头+颜色表+数据块

位图信息=位图信息头+颜色表

这些图像文件的存储组成及顺序,万事OK!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值