使用IPicture接口读取和显示BMP,GIF,JPG,ICO,EMF,WMF图像

导读:
  使用IPicture接口读取和显示BMP,GIF,JPG,ICO,EMF,WMF图像 (转)
  问题的起源
  很久以来,我都被一个问题困扰。关于程序中显示图像的问题,我在网络上搜索了很长时间,找到了无数的解决方案,比如分析文件格式,直接读取文件的;用控件的(ImgEdit);以及不知道内部实现方法的库(ImageLoad)。而我找到的方法大都不容易使用,特别是那些直接按位读取图像的。很多时候我不得不为每种文件格式写一段代码。
  目前我的解决方案
  在使用了多种图形显示方案之后,我决定使用微软提供的IPicture接口来显示图像。由于MFC的CPictureHolder类是这个接口的一个封装,而且自带了从图像句柄读入图形的功能,所以我的工作以CPictureHolder类为基础。要是你不喜欢MFC的话,你可以把CPictureHolder类的代码从MFC的源代码里面分离出来单独使用。
  CPictureHolder类的设计目的是实现ActiveX控件的Picture属性,允许用户在控件中显示图像。作为默认的Picture属性,开发者可以指定一个位图(Bitmap),图标(Icon),或者图元文件(Metafile)来显示。虽然微软的文档中并未说明支持JPEG格式的图像,但是经过我的测试,在windows98以上,以及Windows2000中,它实际上是支持JPEG格式的,根据微软的文档,支持的图像格式有BMP,DIB,WMF,ICO。笔者并未测试其他图像格式是否被支持,例如PNG、GIF、PCX等等,有兴趣的读者可以去自己测试一下。(据111222的文档.NET/develop/read_article.ASP?id=10632">http://www.csdn.net/develop/read_article.asp?id=10632,也支持GIF格式)
  由于CPictureHolder类并未实现从文件/资源/内存读入图像,使用起来很不方便,所以我扩展了这个类以支持上述功能。部分工作基于Dr. Yovav Gad, (Mailto:[email protected]">[email protected],www.SuperMain.com)和http://www.thecodeproject.com/bitmap/cpicture.asp的代码。
  要使用CPictureHolder类,必须先包含afxctl.h
  源代码

  1. #include 
  2.    class  CPicture: public  CPictureHolder 
  3.   { 
  4.    public
  5.    BOOL  Load(CString sfilePathName); //从文件读取图像 
  6.    BOOL  Load( HINSTANCE  hInstance, LPCTSTR  lpszResourceName,  LPCSTR  ResourceType); //从资源读取图像 
  7.    BOOL  LoadPictureData( BYTE * pBuffer,  int  nSize); //从内存读取图像 
  8.    BOOL  SaveAsBitmap(CString sFilePathName); //写入到BMP文件 
  9.    void  Render(CDC* pDC, LPRECT pDrawRect /*目标矩形,单位是逻辑坐标单位*/ , LPRECT 
  10.   pSrcRect=NULL /*来源矩形,单位是0.01毫米,如果为空,则拉伸整个图像到目标矩形*/ ,LPCRECT prcWBounds=NULL /*图元文件专用,绑定矩形*/ ); //在给定的DC上画图, 
  11.   CPicture(); 
  12.    virtual  ~CPicture(); 
  13.    void  UnloadPicture(); //释放图像,作用同CPictureHolder::~CPictureHolder() 
  14.    public
  15.    LONG  get_Height();  // 以0.01毫米为单位的图像高度 
  16.    LONG  get_Width();  // 以0.01毫米为单位的图像宽度 
  17.   }; 
  18.    //----------------------------------------------------------------------------- 
  19.    // Does: Free The Allocated Memory That Holdes The IPicture Interface Data 
  20.    // ~~~~ And Clear Picture Information 
  21.    // 
  22.    // Note: This Might Also Be Useful If U Only Need To Show The Picture Once 
  23.    // ~~~~~ Or If U Copy The Picture To The Device Context, So It Can Still 
  24.    // Remain On Screen - But IPicture Data Is Not Needed No More 
  25.    // 
  26.    //----------------------------------------------------------------------------- 
  27.    void  CPicture::UnloadPicture() 
  28.    //============================================================================= 
  29.   { 
  30.    if (m_pPict != NULL){ 
  31.   m_pPict->Release(); 
  32.   m_pPict = NULL; 
  33.   } 
  34.   } 
  35.    //----------------------------------------------------------------------------- 
  36.    // Does: Open a Resource And Load It Into IPicture (Interface) 
  37.    // ~~~~ (.BMP .DIB .EMF .GIF .ICO .JPG .WMF) 
  38.    // 
  39.    // Note: When Adding a Bitmap Resource It Would Automatically Show On "Bitmap" 
  40.    // ~~~~ This NOT Good Coz We Need To Load It From a Custom Resource "BMP" 
  41.    // To Add a Custom Rresource: Import Resource -> Open As -> Custom 
  42.    // (Both .BMP And .DIB Should Be Found Under "BMP") 
  43.    // 
  44.    // InPut: ResourceName - As a UINT Defined (Example: IDR_PICTURE_RESOURCE) 
  45.    // ~~~~~ ResourceType - Type Name (Example: "JPG") 
  46.    // 
  47.    // OutPut: TRUE If Succeeded... 
  48.    // ~~~~~~ 
  49.    //----------------------------------------------------------------------------- 
  50.    BOOL  CPicture::Load( HINSTANCE  hInstance, LPCTSTR  lpszResourceName,  LPCSTR  ResourceType) 
  51.    //============================================================================= 
  52.   { 
  53.    HGLOBAL  hGlobal = NULL; 
  54.    HRSRC  hSource = NULL; 
  55.    LPVOID  lpVoid = NULL; 
  56.    int  nSize = 0; 
  57.    BOOL  bResult=FALSE; 
  58.    if (m_pPict != NULL) UnloadPicture();  // Important - Avoid Leaks... 
  59.   hSource = FindResource(hInstance, lpszResourceName, ResourceType); 
  60.    if (hSource == NULL) 
  61.   { 
  62.    HWND  hWnd = AfxGetApp()->GetMainWnd()->m_hWnd; 
  63.   MessageBoxEx(hWnd,  "FindResource() Failedt" , ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH); 
  64.    return (FALSE); 
  65.   } 
  66.   hGlobal = LoadResource(hInstance, hSource); 
  67.    if (hGlobal == NULL) 
  68.   { 
  69.    HWND  hWnd = AfxGetApp()->GetMainWnd()->m_hWnd; 
  70.   MessageBoxEx(hWnd,  "LoadResource() Failedt" , ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH); 
  71.    return (FALSE); 
  72.   } 
  73.   lpVoid = LockResource(hGlobal); 
  74.    if (lpVoid == NULL) 
  75.   { 
  76.    HWND  hWnd = AfxGetApp()->GetMainWnd()->m_hWnd; 
  77.   MessageBoxEx(hWnd,  "LockResource() Failedt" , ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH); 
  78.    return (FALSE); 
  79.   } 
  80.   nSize = ( UINT )SizeofResource(hInstance, hSource); 
  81.    if (LoadPictureData(( BYTE *)hGlobal, nSize)) bResult = TRUE; 
  82.   UnlockResource(hGlobal);  // 16Bit Windows Needs This 
  83.   FreeResource(hGlobal);  // 16Bit Windows Needs This (32Bit - Automatic Release) 
  84.    return (bResult); 
  85.   } 
  86.    //----------------------------------------------------------------------------- 
  87.    // Does: Open a File And Load It Into IPicture (Interface) 
  88.    // ~~~~ (.BMP .DIB .EMF .GIF .ICO .JPG .WMF) 
  89.    // 
  90.    // InPut: sFilePathName - Path And FileName Target To Save 
  91.    // ~~~~~ 
  92.    // 
  93.    // OutPut: TRUE If Succeeded... 
  94.    // ~~~~~~ 
  95.    //----------------------------------------------------------------------------- 
  96.    BOOL  CPicture::Load(CString sFilePathName) 
  97.    //============================================================================= 
  98.   { 
  99.    if (!PathFileExists(sFilePathName)) return  FALSE; 
  100.    BOOL  bResult = FALSE; 
  101.   CFile PictureFile; 
  102.   CFileException e; 
  103.    int  nSize = 0; 
  104.    if (m_pPict != NULL) UnloadPicture();  // Important - Avoid Leaks... 
  105.    if (PictureFile.Open(sFilePathName, CFile::modeRead | CFile::typeBinary, &e)) 
  106.   { 
  107.   nSize = PictureFile.GetLength(); 
  108.    BYTE * pBuffer =  new   BYTE [nSize]; 
  109.    
  110.    if (PictureFile.Read(pBuffer, nSize) >0) 
  111.   { 
  112.    if (LoadPictureData(pBuffer, nSize)) bResult = TRUE; 
  113.   } 
  114.   PictureFile.Close(); 
  115.    delete  [] pBuffer; 
  116.   } 
  117.    else   // Open Failed... 
  118.   { 
  119.    TCHAR  szCause[255]; 
  120.   e.GetErrorMessage(szCause, 255, NULL); 
  121.    HWND  hWnd = AfxGetApp()->GetMainWnd()->m_hWnd; 
  122.   MessageBoxEx(hWnd, szCause, ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH); 
  123.   bResult = FALSE; 
  124.   } 
  125.    return (bResult); 
  126.   } 
  127.    //----------------------------------------------------------------------------- 
  128.    // Does: Read The Picture Data From a Source (File / Resource) 
  129.    // ~~~~ And Load It Into The Current IPicture objectIn Use 
  130.    // 
  131.    // InPut: Buffer Of Data Source (File / Resource) And Its Size 
  132.    // ~~~~~ 
  133.    // 
  134.    // OutPut: Feed The IPicture Object With The Picture Data 
  135.    // ~~~~~~ (Use Draw Functions To Show It On a Device Context) 
  136.    // TRUE If Succeeded... 
  137.    //----------------------------------------------------------------------------- 
  138.    BOOL  CPicture::LoadPictureData( BYTE  *pBuffer,  int  nSize) 
  139.    //============================================================================= 
  140.   { 
  141.    BOOL  bResult = FALSE; 
  142.    HGLOBAL  hGlobal = GlobalAlloc(GMEM_MOVEABLE, nSize); 
  143.    if (hGlobal == NULL) 
  144.   { 
  145.    HWND  hWnd = AfxGetApp()->GetMainWnd()->m_hWnd; 
  146.   MessageBoxEx(hWnd,  "Can not allocate enough memoryt" , ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH); 
  147.    return (FALSE); 
  148.   } 
  149.    void * pData = GlobalLock(hGlobal); 
  150.   memcpy(pData, pBuffer, nSize); 
  151.   GlobalUnlock(hGlobal); 
  152.   IStream* pStream = NULL; 
  153.    if (CreateStreamOnHGlobal(hGlobal, TRUE, &pStream) == S_OK) 
  154.   { 
  155.    HRESULT  hr; 
  156.    if ((hr = OleLoadPicture(pStream, nSize, FALSE, IID_IPicture, ( LPVOID  *)&m_pPict)) == E_NOINTERFACE) 
  157.   { 
  158.    HWND  hWnd = AfxGetApp()->GetMainWnd()->m_hWnd; 
  159.   MessageBoxEx(hWnd,  "IPicture interface is not supportedt" , ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH); 
  160.    return (FALSE); 
  161.   } 
  162.    else   // S_OK 
  163.   { 
  164.   pStream->Release(); 
  165.   pStream = NULL; 
  166.   bResult = TRUE; 
  167.    
  168.   } 
  169.   } 
  170.   FreeResource(hGlobal);  // 16Bit Windows Needs This (32Bit - Automatic Release) 
  171.    return (bResult); 
  172.   } 
  173.    //----------------------------------------------------------------------------- 
  174.    // Does: Draw The Loaded Picture Direct To The Client DC 
  175.    // ~~~~ 
  176.    // 
  177.    // Note: Bigger OR Smaller Dimentions Than The Original Picture Size 
  178.    // ~~~~ Will Draw The Picture Streached To Its New Given NEW Dimentions... 
  179.    // 
  180.    // InPut: pDC - Given DC To Draw On 
  181.    // ~~~~~ pSrcRect- Dimentions Of The Picture To Draw From(As a Rectangle) 
  182.    // DrawRect - Dimentions Of The Picture To Draw To(As a Rectangle) 
  183.    // OutPut: TRUE If Succeeded... 
  184.    // ~~~~~~ 
  185.    //----------------------------------------------------------------------------- 
  186.    //============================================================================= 
  187.    void  CPicture::Render(CDC* pDC, LPRECT pDrawRect, LPRECT pSrcRect /*=NULL*/ ,LPCRECT prcWBounds /*=NULL*/
  188.   { 
  189.    if  (pDC == NULL || m_pPict == NULL)  return  ; 
  190.    
  191.   CRect recrDest(pDrawRect); 
  192.    long  Width = 0; 
  193.    long  Height = 0; 
  194.   m_pPict->get_Width(&Width); 
  195.   m_pPict->get_Height(&Height); 
  196.   CRect SrcRect(0,0,Width,Height); 
  197.    if (pSrcRect){ 
  198.   SrcRect=*pSrcRect; 
  199.   } 
  200.   CRect DrawRect(pDrawRect); 
  201.    HRESULT  hrP = NULL; 
  202.   hrP = m_pPict->Render(pDC->m_hDC, 
  203.   DrawRect.left,  // Left 
  204.   DrawRect.top,  // Top 
  205.   DrawRect.Width(),  // Right 
  206.   DrawRect.Height(),  // Bottom 
  207.   SrcRect.left, 
  208.   SrcRect.top, 
  209.   SrcRect.Width(), 
  210.   SrcRect.Height(), 
  211.   prcWBounds); 
  212.    if  (SUCCEEDED(hrP))  return
  213.   AfxThrowMemoryException(); 
  214.    return
  215.   } //----------------------------------------------------------------------------- 
  216.    // Does: Saves The Picture That Is Stored In The IPicture Object As a Bitmap 
  217.    // ~~~~ (Converts From Any Known Picture Type To a Bitmap / Icon File) 
  218.    // 
  219.    // InPut: sFilePathName - Path And FileName Target To Save 
  220.    // ~~~~~ 
  221.    // 
  222.    // OutPut: TRUE If Succeeded... 
  223.    // ~~~~~~ 
  224.    //----------------------------------------------------------------------------- 
  225.    BOOL  CPicture::SaveAsBitmap(CString sFilePathName) 
  226.    //============================================================================= 
  227.   { 
  228.    BOOL  bResult = FALSE; 
  229.   ILockBytes *Buffer = 0; 
  230.   IStorage *pStorage = 0; 
  231.   IStream *FileStream = 0; 
  232.    BYTE  *BufferBytes; 
  233.   STATSTG BytesStatistics; 
  234.   Dword OutData; 
  235.    long  OutStream; 
  236.   CFile BitmapFile; CFileException e; 
  237.    double  SkipFloat = 0; 
  238.    DWORD  ByteSkip= 0; 
  239.   _ULARGE_INTEGER RealData; 
  240.   CreateILockBytesOnHGlobal(NULL, TRUE, &Buffer);  // Create ILockBytes Buffer 
  241.    HRESULT  hr = ::StgCreateDocfileOnILockBytes(Buffer, 
  242.   STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 0, &pStorage); 
  243.   hr = pStorage->CreateStream(L "PICTURE"
  244.   STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 0, 0, &FileStream); 
  245.   m_pPict->SaveAsFile(FileStream, TRUE, &OutStream);  // Copy Data Stream 
  246.   FileStream->Release(); 
  247.   pStorage->Release(); 
  248.   Buffer->Flush(); 
  249.    // Get Statistics For Final Size Of Byte Array 
  250.   Buffer->Stat(&BytesStatistics, STATFLAG_NONAME); 
  251.    // Cut UnNeeded Data Coming From SaveAsFile() (Leave Only "Pure" Picture Data) 
  252.   SkipFloat = ( double (OutStream) / 512);  // Must Be In a 512 Blocks... 
  253.    if (SkipFloat > DWORD (SkipFloat)) ByteSkip = ( DWORD )SkipFloat + 1; 
  254.    else  ByteSkip = ( DWORD )SkipFloat; 
  255.   ByteSkip = ByteSkip * 512;  // Must Be In a 512 Blocks... 
  256.    
  257.    // Find Difference Between The Two Values 
  258.   ByteSkip = ( DWORD )(BytesStatistics.cbSize.QuadPart - ByteSkip); 
  259.    // Allocate Only The "Pure" Picture Data 
  260.   RealData.LowPart = 0; 
  261.   RealData.HighPart = 0; 
  262.   RealData.QuadPart = ByteSkip; 
  263.   BufferBytes = ( BYTE *)malloc(OutStream); 
  264.    if (BufferBytes == NULL) 
  265.   { 
  266.   Buffer->Release(); 
  267.    HWND  hWnd = AfxGetApp()->GetMainWnd()->m_hWnd; 
  268.   MessageBoxEx(hWnd,  "Can not allocate enough memoryt" , ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH); 
  269.   } 
  270.   Buffer->ReadAt(RealData, BufferBytes, OutStream, &OutData); 
  271.    if (BitmapFile.Open(sFilePathName, CFile::typeBinary | CFile::modeCreate | CFile::modeWrite, &e)) 
  272.   { 
  273.   BitmapFile.Write(BufferBytes, OutData); 
  274.   BitmapFile.Close(); 
  275.   bResult = TRUE; 
  276.   } 
  277.    else   // Write File Failed... 
  278.   { 
  279.    TCHAR  szCause[255]; 
  280.   e.GetErrorMessage(szCause, 255, NULL); 
  281.    HWND  hWnd = AfxGetApp()->GetMainWnd()->m_hWnd; 
  282.   MessageBoxEx(hWnd, szCause, ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH); 
  283.   bResult = FALSE; 
  284.   } 
  285.    
  286.   Buffer->Release(); 
  287.   free(BufferBytes); 
  288.    return (bResult); 
  289.   } 
  290.    LONG  CPicture::get_Height() 
  291.   { 
  292.    LONG  nHeight = 0; 
  293.    if  (m_pPict != NULL) 
  294.   { 
  295.   m_pPict->get_Height(&nHeight); 
  296.   } 
  297.    return  nHeight; 
  298.   } 
  299.    LONG  CPicture::get_Width() 
  300.   { 
  301.    LONG  nWidth = 0; 
  302.    if  (m_pPict != NULL) 
  303.   { 
  304.   m_pPict->get_Width(&nWidth); 
  305.   } 
  306.    return  nWidth; 
  307.   } 

本文转自
http://gugu99.itpub.net/post/34143/451126

你可能感兴趣的:(windows,.net,asp.net,mfc,asp)