VC学习笔记5图像与文本

来源:互联网 发布:淘宝服装店成本 编辑:程序博客网 时间:2024/06/05 22:31
GDI概述:
图形设备接口,windows操作系统提供的一组函数,为了能够在窗口中绘制各种图形信息。

下面创建MFC单文档程序

要想在视图中显示文字
在void CWdView::OnDraw(CDC* pDC)中加入
pDC->TextOut(10,10,"hello!");  //10,10为坐标
如果想要设置字体呢,可以在前面加上
CFont font;  //CFont字体数据结构
font.CreateFont(24,24,0,0,FW_NORMAL,0,TRUE,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,
        CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_ROMAN,"宋体");
CFont *poldfont=NULL;  //定义原字体指针必须要恢复
poldfont=pDC->SelectObject(&font);  //设置字体,返回原来的字体的指针
pDC->TextOut(10,10,"hello!");
pDC->SelectObject(poldfont);  //重新设置原来的字体
font.DeleteObject(); //这部必须
要是想用画刷显示边框呢
CRect rc(100,20,300,200);  //注意这里用了CRect,在处理GDI时
CString str="hello";
CBrush brush(RGB(0,0,0,0));  //选择画刷
pDC->FrameRect(rc,&brush);  //画边框
pDC->DrawText(str,rc,DT_CENTER|DT_SINGLELINE|DT_VCENTER);//居中,单行,中间显示
brush.DeleteObject();  //这边不需要恢复oldbrush,因为画刷不是默认的

想要加载显示图像
在视图类中先定义句柄变量
HANDLE m_hBmp;
在视图类的构造函数中
m_hBmp=LoadImage(NULL,"demo.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);//后面的两个0固定,当前目录获取
在OnDraw中
CBitmap bmp;  //定义位图类变量
bmp.Attach(m_hBmp);  //连接到句柄
CDC memDC;  //定义一个DC显示位图
memDC.CreateCompatibleDC(pDC);  //选中显示的窗口,这里选中所有显示区窗口
memDC.SelectObject(&bmp);  //选中位图画刷
BITMAP BitInfo;  //定义位图结构变量,注意这里保存位图结构信息
bmp.GetBitmap(&BitInfo);  //把bmp的结构给位图结构变量
int x=BitInfo.bmWidth;  //获取宽度
int y=BitInfo.bmHeight;  //获取高度
pDC->BitBlt(0,0,x,y,&memDC,0,0,SRCCOPY);//从位图00到xy显示,从memDC的00开始显示
bmp.Detach(); //关闭连接
memDC.DeleteDC(); //释放内存

那么如何绘制位图呢
在视图类构造函数中
CFile file;
file.Open("bk.bmp",CFile::modeReadWrite); //读写方式打开
int len=file.GetLength();  //得到文件字节长度,文件中每个字节为char类型
file.Seek(14,CFile::begin); //跳过文件开头的14个字节,因为位图编码中前14个字节不是图像信息
m_pbmpdata=new char[len-14]; //在前面定义了char指针m_pbmpdata,全局变量
file.Read(m_pbmpdata,len-14);  //将文件读入数组
file.close();  //关闭文件
在OnDraw响应函数中,加入
Outputstream(m_pbmpdata);//显然这里的实现函数是自己定义的
绘图实现函数Outputstream(char *ps)定义
char *phead=ps;  //这里的输入是从文件14字节之后的,也就是图像信息
BITMAPINFO bitinfo;  //信息
memset(&bitinfo,0,sizeof(BITMAPINFO));
memcpy(&bitinfo,phead,sizeof(BITMAPINFO));
int x=bitinfo.bmiHeader.biWidth;
int y=bitinfo.bmiHeader.biHeight;
phead+=40;  //这里phead前40字节为调色板的信息
StretchDIBits(GetDC()->m_hDC,0,0,x,y,0,0,x,y,phead,&bitinfo,DIB_RGB_COLORS,SRCCOPY);

来解下疑吧

typedef struct tagBITMAPINFO {
    BITMAPINFOHEADER    bmiHeader;
    RGBQUAD             bmiColors[1];
} BITMAPINFO, FAR *LPBITMAPINFO, *PBITMAPINFO;

这个是BITMAPINFO结构的定义,其中包含信息头BITMAPINFOHEADER和RGB值数组
信息头的定义如下

typedef struct tagBITMAPINFOHEADER{
        DWORD      biSize;  //4byte 文件大小信息
        LONG       biWidth;  //4byte  位图宽
        LONG       biHeight;  //4byte  位图高
        WORD       biPlanes;  //2byte  调色板信息
        WORD       biBitCount;  //2byte  bit数目
        DWORD      biCompression;  //4byte
        DWORD      biSizeImage;   //4byte
        LONG       biXPelsPerMeter;  //4byte
        LONG       biYPelsPerMeter;  //4byte
        DWORD      biClrUsed;  //4byte
        DWORD      biClrImportant;  //4byte
} BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;

当调用StretchDIBits()时,前面的8个int类型参数是从原图哪儿显示到设备的哪儿,
而phead+=40就是跳过信息头刚好40byte的信息,这样接收入StretchDIBits的第10个参数就是RGB数组
那后面的&bitinfo不用多说就是BITMAPINFO,再后面显示RGB图像。

使用GDI+
GDI+是一个类库,虽然没有集成在VC6.0中,但仍可以使用它
配置GDI+网上找的方法http://blog.csdn.net/toss156/article/details/7270513
下面我们实现BMP,JPEG,GIF格式转换
首先将文件路径存至CString类型变量loadname中
要保存到savename路径中
Bitmap bmp(loadname.AllocSysString());
CLSID clsid;
GetCodecClsid(L"image/jpeg",&clsid);
bmp.Save(savename.AllocSysString(),&clsid);

=======第一次修正========

下面解析.bmp文件格式

typedef struct tagBITMAPFILEHEADER {WORD bfType;//固定为0x4d42;    DWORD bfSize; //文件大小    WORD bfReserved1; //保留字,不考虑    WORD bfReserved2; //保留字,同上    DWORD bfOffBits; //实际位图数据的偏移字节数,即前三个部分长度之和    } BITMAPFILEHEADER;
我们跳过了14个char,而一个char表示成16进制由两位组成

下面分析bmp信息头

typedef struct tagBITMAPINFOHEADER{ DWORD biSize; //指定此结构体的长度,为40 LONG biWidth; //位图宽   LONG biHeight; //位图高   WORD biPlanes; //平面数,为1   WORD biBitCount; //采用颜色位数,可以是1,2,4,8,16,24,新的可以是32   DWORD biCompression; //压缩方式,可以是0,1,2,其中0表示不压缩   DWORD biSizeImage; //实际位图数据占用的字节数  LONG biXPelsPerMeter; //X方向分辨率   LONG biYPelsPerMeter; //Y方向分辨率   DWORD biClrUsed; //使用的颜色数,如果为0,则表示默认值(2^颜色位数)   DWORD biClrImportant; //重要颜色数,如果为0,则表示所有颜色都是重要的  } BITMAPINFOHEADER;


从中可以看到,跳过前面14个byte,后面4byte是28 00 00 00这里的编码是先低位再高位,所以为 00 00 00 28刚好为十进制的40

再向下面看biWidth为446,转化成16进制为 1BE,这里的LONG也用了4byte因此编码为 BE 01 00 00


0 0