MFC处理jpg格式图片(三)

这次主要是对上次MFC处理URL视频里面的一段代码的优化http://blog.csdn.net/zhang2012liang/article/details/9973117,视频加载图片时不再从本地拿取,我在程序里面设置一个缓存,通过缓存来处理图片,然后从缓存里面拿数据来显示图片

涉及到将字节转化为流Istream

HRESULT ShowPic(CString lpstrImgUrl,HWND hWnd,CRect theRect)        
{        
  
	 const int dwBufSize = 1024;
     CInternetSession   *   Session   =   new   CInternetSession; 
     CHttpFile*                 pHttpFile   =   NULL;         
     LPBYTE   lpBuf   =   new   byte[dwBufSize];   
     pHttpFile   =(CHttpFile*)Session->OpenURL( 
     "http://c.hiphotos.baidu.com/album/w%3D2048/sign=be2ad5205fdf8db1bc2e7b643d1bdc54/9e3df8dcd100baa12f5b93034610b912c8fc2e17.jpg", 
      1, 
		INTERNET_FLAG_TRANSFER_BINARY   | 
		INTERNET_FLAG_RELOAD   |   
		INTERNET_FLAG_DONT_CACHE, 
		NULL, 
     0); 
	 int dd=pHttpFile->GetLength();
	 //查询文件长度
     CString strLen;
     pHttpFile ->QueryInfo(HTTP_QUERY_CONTENT_LENGTH,strLen);  
     DWORD nSum =atol((char*)strLen.GetBuffer());  //问题就是这里咯~~~~
     strLen.ReleaseBuffer();
	 LPBYTE  TheSumByte=new  byte[nSum] ;
	 UINT temp=0;
      while(int ThePos=pHttpFile-> Read(lpBuf,   dwBufSize-1   )) 
    { 
	    for(int i=0;i<ThePos;i++)
		{
			TheSumByte[i+temp]=lpBuf[i];
		}
		temp+=ThePos;
     } 
	
	HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, temp);//申请全局内存
	if(hGlobal == NULL)
	{
		
		AfxMessageBox("Can not allocate enough memory\t");
		return(FALSE);
	}
	HDC hDC=GetDC(hWnd);
	void* pData = GlobalLock(hGlobal);//锁定内存 
	memcpy(pData, TheSumByte, temp);//将内容赋值给pData指向的内存
	GlobalUnlock(hGlobal);
	
	IStream* pIStream = NULL;
	IPicture *pIPicture=NULL;//创建一个IPicture接口指针,表示图片对象 
	if(CreateStreamOnHGlobal(hGlobal, TRUE, &pIStream) == S_OK)
	{
	  HRESULT hr=OleLoadPicture(pIStream, 0, false, IID_IPicture, (LPVOID*)&(pIPicture));
	  if(SUCCEEDED(hr))//用OleLoadPicture获得IPicture接口指针
	  {
		        OLE_XSIZE_HIMETRIC hmWidth; 
		    	OLE_YSIZE_HIMETRIC hmHeight; 
				pIPicture->get_Width(&hmWidth); //用接口方法获得图片的宽和高 
				pIPicture->get_Height(&hmHeight); 
				pIPicture->Render(hDC,0,0,theRect.Width(),theRect.Height(),0,hmHeight,hmWidth,-hmHeight,NULL); //在指定的DC上绘出图片 

	  }

	}
	GlobalFree(hGlobal); //释放全局内存 
	pIStream->Release(); //释放pIStream 
	pIPicture->Release(); //释放pIPicture
		}

下面的资料转载的:主要是对上面的代码的后半部分解析的

关于 

OpenURL等Wnnet的看我前面的文章

调用GlobalAlloc函数分配一块内存,该函数会返回分配的内存句柄。 
调用GlobalLock函数锁定内存块,该函数接受一个内存句柄作为参数,然后返回一个指向被锁定的内存块的指针。 您可以用该指针来读写内存。 
调用GlobalUnlock函数来解锁先前被锁定的内存,该函数使得指向内存块的指针无效。 
调用GlobalFree函数来释放内存块。您必须传给该函数一个内存句柄。


GlobalAlloc
  该函数从堆中分配一定数目的字节数。Win32内存管理器并不提供相互分开的局部和全局堆。提供这个函数只是为了与16位的Windows相兼容。
 
  HGLOBAL GlobalAlloc(
    UINT uFlags, // 分配属性(方式)   
    SIZE_T dwBytes // 分配的字节数   
  );
      
返回值:
  若函数调用成功,则返回一个新分配的内存对象的句柄。  
  若函数调用失败,则返回 NULL。可调用 GetLastError 以获得更多错误信息。


参数:
  uFlags:指定如何分配内存,若指定为0,则是默认的GMEM_FIXED.这个值可以是下面其中一个或几个位标识(那些指明不兼容的组合除外)
  具体如下:
    GHND  GMEM_MOVEABLE 和 GMEM_ZEROINIT的组合。
    GMEM_FIXED  分配固定的内存,返回值是一个指针。   
    GMEM_MOVEABLE  分配可移动的内存,在Win32中内存块在物理内存中是不可移动的,但在缺省堆中可以。返回值是该内存对象的句柄,可使用函数 GlobalLock 将该句柄转换为一个指针。这个标识不能与 GMEM_FIXED 组合使用。  
    GMEM_ZEROINIT  将所申请内存初始化为0。
    GPTR  GMEM_FIXED和GMEM_ZEROINIT组合。    
    GMEM_DDESHARE、GMEM_DISCARDABLE、GMEM_LOWER、GMEM_NOCOMPACT、GMEM_NODISCARD、GMEM_NOT_BANKED、GMEM_NOTIFY、GMEM_SHARE 均被忽略,这些标识只是为与 16 位 Windows 相兼容而提供的。
  dwBytes:指定要申请的字节数。若该参数为 0 且参数 uFlags 指定为 GMEM_MOVEABLE 则该函数返回一个内存对象的句柄,该内存对象被标识为discarded(可抛弃的)。


注解:
  如果堆内没有足够的空间满足请求,函数将返回 NULL。因为NULL是用于标明错误的,所以不会分配虚拟0地址。   
  因此很容易检测出是否在使用一个NULL指针。
  使用此函数分配内存可以保证8字节的边界。所有的内存均在执行访问时创建;不需要特别的函数来动态执行所产生的代码。
  若函数调用成功,将至少分配所需内存。若实际分配量超过所需,则内存仍然能够充分利用之。可用函数 GlobalSize 来确定实际所分配的字节数。   
  可使用 GlobalFree 来释放内存。
 
GlobalLock
  锁定内存中指定的内存块,并返回一个地址值,令其指向内存块的起始处。除非用 GlobalUnlock 函数将内存块解锁,否则地址会一直保持有效。Windows 为每个内存对象都维持着一个锁定计数。对这个函数的每次调用都应有一个对应的 GlobalUnlock 调用。
  
  LPVOID GlobalLock(
    HGLOBAL hMem   // handle to global memory object
  );
 
  一般情况下我们在编程的时候,给应用程序分配的内存都是可以移动的或者是可以丢弃的,这样能使有限的内存资源充分利用,所以,在某一个时候我们分配的那块内存的地址是不确定的,因为他是可以移动的,所以得先锁定那块内存块,这儿应用程序需要调用API函数GlobalLock函数来锁定句柄。如下: lpMem=GlobalLock(hMem); 这样应用程序才能存取这块内存。 
参数:
  hMem:全局内存对象的句柄。这个句柄是通过GlobalAlloc或GlobalReAlloc来得到的
返回值:
  调用成功,返回指向该对象的第一个字节的指针
  调用失败,返回NULL,可以用GetLastError来获得出错信息
注意:
  调用过GlobalLock锁定一块内存区后,一定要调用GlobalUnlock来解锁。
 
GlobalUnlock
  GlobalUnlock函数解除锁定的内存块,使指向该内存块的指针无效,GlobalLock锁定的内存,一定要用GlobalUnlock解锁。
 
  BOOL GlobalUnlock(
    HGLOBAL hMem   // handle to global memory object
  );
参数:
  hMem:全局内存对象的句柄
返回值:
  非零值,指定的内存对象仍处于被锁定状态
  0,函数执行出错,可以用GetLastError来获得出错信息,如果返回NO_ERROR,则表示内存对象已经解锁了
注意:     
  这个函数实际上是将内存对象的锁定计数器减一,如果计数器不为0,则表示执行过多个GlobalLock函数来对这个内存对象加锁,需要对应数目的GlobalUnlock函数来解锁。
  如果通过GetLastError函数返回错误码为ERROR_NOT_LOCKED,则表示未加锁或已经解锁。
 
注释3:
CreateStreamOnHGlobal
  CreateStreamOnHGlobal函数从指定内存创建流对象。
 
  WINOLEAPI CreateStreamOnHGlobal(
    HGLOBAL hGlobal,              //Memory handle for the stream object
    BOOL fDeleteOnRelease,     //Whether to free memory when the 
                                     // object is released
    LPSTREAM *ppstm             //Address of output variable that 
                                    // receives the IStream interface pointer
 );


参数:
  hGlobal:由GlobalAlloc函数分配的内存句柄。   
  fDeleteOnRelease:该参数指明上一个参数制定的内存在该对象被释放后是否也自动释放。如果该参数设定为FALSE,那么调用者必须显示的释放hGlobal。如果该参数设置为TRUE,则hGlobal最终会自动释放。   
  ppstm:IStream指针的地址,该指针在该函数执行后指向新创建的流对象。该参数不能未NULL。   如果函数创建流对象成功则返回S_OK。


注释4:
OleLoadPicture
  用API OleLoadPicture来加载JPG、GIF格式的图片(注:不支持PNG格式,另外GIF只能加载第一帧,且不支持透明) 
 OleLoadPicture 函数实际上创建了一个IPicture类型的COM接口对象,然后我们可以通过这个COM接口来操作图片(实际上你也可以用API OleCreatePictureIndirect来加载图片,不过相比而言OleLoadPicture函数简化了基于流的IPicture对象的创 建)。



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值