根据位图数据直接绘图

在处理网格应用传输图像时,接收方收到的将是数据流,如何能够将图像数据显示在窗口中呢?Windows系统提供了StretchDIBits函数,通过它能够根据位图的数据流将图像显示在窗口中。

函数原型:

int StretchDIBits(HDC hdc, int XDest , int YDest , int nDestWidth, int nDestHeight, int XSrc, int Ysrc, int nSrcWidth, int nSrcHeight, CONST VOID *lpBits, CONST BITMAPINFO * lpBitsInfo, UINT iUsage, DWORD dwRop) 


参数含义:

hdc:指向目标设备环境的句柄。

XDest:指定目标矩形左上角位置的X轴坐标,按逻辑单位来表示坐标。

YDest:指定目标矩形左上角的Y轴坐标,按逻辑单位表示坐标。

nDestWidth:指定目标矩形的宽度。

nDestHeight:指定目标矩形的高度。

XSrc:指定DIB中源矩形(左上角)的X轴坐标,坐标以像素点表示。

YSrc:指定DIB中源矩形(左上角)的Y轴坐标,坐标以像素点表示。

nSrcWidth:按像素点指定DIB中源矩形的宽度。

nSrcHeight:按像素点指定DIB中源矩形的高度。

lpBits:指向DIB位的指针,这些位的值按字节类型数组存储。

lpBitsInfo:指向BITMAPINFO结构的指针,该结构包含有关DIB方面的信息。

iUsage:表示是否提供了BITMAPINFO结构中的成员bmiColors,如果提供了,那么该bmiColors是否包含了明确的RGB值或索引。参数iUsage必须取下列值,这些值的含义如下:

DIB_PAL_COLORS:表示该数组包含对源设备环境的逻辑调色板进行索引的16位索引值。

DIB_RGB_COLORS:表示该颜色表包含原义的RGB值。

dwRop:指定源像素点、目标设备环境的当前刷子和目标像素点是如何组合形成新的图像。

 

返回值:

如果函数执行成功,那么返回值是拷贝的扫描线数目,如果函数执行失败,那么返回值是GDI_ERROR

 

(一)示例:使用StretchDIBits根据数据流绘制图像——BMP

步骤如下:

(1)创建一个SDI APP,工程名为 OutPutStream

(2)在View类中定义一个Buffer,用于存储数据流

char* m_pBmpData; //定义一个缓冲区

(3)在View类的构造函数中读取位图文件到数据流中,代码如下: 

COutPutStreamView::COutPutStreamView()
{
	// TODO: 在此处添加构造代码
	TCHAR szPath[MAX_PATH];
	GetModuleFileName(NULL, szPath, MAX_PATH);
	CString PathName(szPath);
	CString PROGRAM_PATH2= PathName.Left(PathName.ReverseFind(_T('Debug')) );
	PROGRAM_PATH2+=_T("OutPutStream\\Res\\QQ截图20140403232339.bmp");
	CFile file;//定义一个文件对象
	file.Open(PROGRAM_PATH2,CFile::modeReadWrite);//打开文件
	int len=file.GetLength();//获取文件长度
	file.Seek(14,CFile::begin);//略过文件头
	m_pBmpData = new char[len-14];//为缓冲区分配空间
	file.Read(m_pBmpData,len-14);//读取文件数据到缓冲区
	file.Close();//关闭文件
}

(4)在视图类的析构函数中释放缓冲区,代码如下:

delete [] m_pBmpData;//释放缓冲区 

(5)向View类中添加一个成员函数,根据数据流输出图像。代码如下:

void COutputStreamView::OutputStream(char *pStream)
{
char* pHeader = pStream;//定义一个临时缓冲区
BITMAPINFO BitInfo;//定义位图信息对象
memset(&BitInfo,0,sizeof(BITMAPINFO));//初始化位图信息对象
memcpy(&BitInfo,pHeader,sizeof(BITMAPINFO));//为位图信息对象赋值
int x= BitInfo.bmiHeader.biWidth;//指向位图宽度
int y= BitInfo.bmiHeader.biHeight;//指向位图高度
pHeader+=40;//指向位图数据
//输出位图信息
StretchDIBits(GetDC()->m_hDC,0,0,x,y,0,0,x,y,pHeader,&BitInfo,DIB_RGB_COLORS,SRCCOPY);
}

(6)在View类的OnDraw方法中调用OutputStream方法绘制图像,代码如下: 

OutputStream(m_pBmpData);//调用OutputStream 方法输出位图 

(7)运行程序,结果如图7-1所示

 根据位图数据直接绘图_第1张图片

 

instruction:由于BMP文件中数据的存储就是以位图文件格式存储的,所以通过BMP文件中的数据可以直接绘制图形。

 

(二)示例:使用StretchDIBits根据数据流绘制图像——JPEG

 

位图文件最大缺点就是压缩比较小,占用空间大,因此网页均不采用位图的格式显示,而是以JPEGGIF格式显示。

Visual C++中,显示JPEG图像并不像显示BMP图像那么简单,它需要通过流操作来实现。

具体思路是将JPEG文件加载到堆中然后在堆中创建一个数据流,接着调用OleLoadPicture 函数加载流中的数据到IPictrue接口中,最后调用IPicture接口的Reader方法输出图像信息。

下面介绍在窗口中显示JPEG图像的具体实现方法。

 

在窗口中显示JPEG图像

步骤如下

(1)创建一个SDI APP ,工程名为 ShowJPEG 

(2)向视图类中添加成员变量,代码如下: 

IStream *m_pStream;//定义流对象

IPicture *m_pPucture;//定义接口对象

OLE_XSIZE_HIMETRIC m_JPGWidth;//图像宽度

OLE_XSIZE_HIMETRIC m_JPGHeight;//图像高度

HGLOBAL hMem;//堆句柄

(3)在View类的构造函数中从磁盘中加载JPEG图像到流中,代码如下: 

CFile file;//定义一个文件对象

file.Open(_T("angle.jpg"),CFile::modeReadWrite);//打开文件

DWORD len=file.GetLength();//获取文件长度

hMem = GlobalAlloc(GMEM_MOVEABLE,len);//在堆中分配内存

LPVOID pData = NULL;//定义一个指针对象

pData = GloballLock(hMem);//锁定内存区域

file.ReadHuge(pData,len);//读取图像数据到堆中

file.Close();

GlobalUnlock(hMem);

CreateStreamOnHGlobal(hMem,TRUE,&m_pStream);

OleLoadPicture(m_pStream,len,TRUE,IID_IPicture,(LPVOID*)&m_pPicture);//

(4)在View类的OnDraw方法中绘制JPEG图像,代码如下:

//绘制JPEG图像

m_pPicture->Render(pDC->MDM_HDLCPPP_AUTH_CHAP,0,0,(int)(m_JPGWidth/26.45),(int)(m_JPGHeight/26.45),0,m_JPGHeight,m_JPGWidth,-m_JPGHeight,NULL); 

(5)运行程序 

Instruction:本实例是通过IPcture接口来绘制IPEG图像的,同样只要修改一下文件扩展名就可以直接绘制GIF的图像。

  

 

你可能感兴趣的:(直接绘图,位图数据)