CImage 从内存中读取图像

来源:互联网 发布:c语言指针教学视频 编辑:程序博客网 时间:2024/05/22 08:23

CImage 的CImage::Load( IStream* pStream) 从内存中读取图像时,需要提供实现了IStream的对象。一般都是采用CreateStreamOnHGlobal创建IStream对象,但这需要重新分配内存,再将内存中图像复制到新分配的内存中,完了还要释放,多了很多操作,也影响性能。
下面这个类就是实现了IStream,可以实现从内存直接读取图像,省了上述多余的操作。

Stream.h文件

#pragma once#include <windows.h> class CStream : public IStream{public:    //     // IUnknown members     //     HRESULT __stdcall QueryInterface(REFIID iid, void ** ppvObject);    ULONG   __stdcall AddRef(void);    ULONG   __stdcall Release(void);    //     // ISequentialStream members     //     HRESULT __stdcall Read(void *pv, ULONG cb, ULONG *pcbRead);    HRESULT __stdcall Write(const void *pv, ULONG cb, ULONG *pcbWritten);    //     // IStream members     //     HRESULT __stdcall Seek(LARGE_INTEGER  dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition);    HRESULT __stdcall SetSize(ULARGE_INTEGER libNewSize);    HRESULT __stdcall CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten);    HRESULT __stdcall Commit(DWORD grfCommitFlags);    HRESULT __stdcall Revert(void);    HRESULT __stdcall LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType);    HRESULT __stdcall UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType);    HRESULT __stdcall Stat(STATSTG *pstatstg, DWORD grfStatFlag);    HRESULT __stdcall Clone(IStream **ppstm);    //     // Constructor / Destructor     //     CStream(BYTE *pData, ULONG nSize);    ~CStream();private:    //     // private members and functions     //     LONG            m_lRefCount;    STATSTG         m_statstg;          // each IStream needs one of these     ULARGE_INTEGER  m_nOffset;          // offset within the stream     ULARGE_INTEGER  m_nLength;          // length of the stream     BYTE*           m_pData;            // stream data from };

Stream.cpp文件

// //  IStream.cpp //  Implementation of the IStream COM interface // #include "stdafx.h"#include "Stream.h"#define DEFNAME L"Memory IStream" // //  Constructor // CStream::CStream(BYTE *pData, ULONG nSize){    m_lRefCount = 1;    m_pData = pData;    // stream metrics     m_nOffset.QuadPart = 0;    m_nLength.QuadPart = nSize;//len;                            // stream status     m_statstg.type = STGTY_STREAM;      // IStream object     m_statstg.cbSize.QuadPart = 0;//len;                // Set to the length of our stream object     m_statstg.grfLocksSupported = 0;                // Region locking not supported     m_statstg.grfMode = 0;              // access mode     m_statstg.clsid = CLSID_NULL;       // not used for IStreams     m_statstg.grfStateBits = 0;             // not used for IStreams     m_statstg.reserved = 0;             // reserved for     CoFileTimeNow(&m_statstg.ctime);                // creation time     CoFileTimeNow(&m_statstg.atime);                // last access time     CoFileTimeNow(&m_statstg.mtime);                // last modify time }// //  Destructor // CStream::~CStream(){}// //  IUnknown::AddRef // ULONG __stdcall CStream::AddRef(void){    // increment object reference count     return InterlockedIncrement(&m_lRefCount);}// //  IUnknown::Release // ULONG __stdcall CStream::Release(void){    // decrement object reference count     LONG count = InterlockedDecrement(&m_lRefCount);    if (count == 0)    {        delete this;        return 0;    }    else    {        return count;    }}// //  IUnknown::QueryInterface // HRESULT __stdcall CStream::QueryInterface(REFIID iid, void **ppvObject){    // check to see what interface has been requested     if (iid == IID_IStream || iid == IID_IUnknown || iid == IID_ISequentialStream)    {        AddRef();        *ppvObject = this;        return S_OK;    }    else    {        *ppvObject = 0;        return E_NOINTERFACE;    }}// //  ISequentialStream::Read // HRESULT __stdcall CStream::Read(void *pv, ULONG cb, ULONG *pcbRead){    ULONG available;    if (pv == 0)        return STG_E_INVALIDPOINTER;    available = min(cb, (ULONG)(m_nLength.QuadPart - m_nOffset.QuadPart));    memcpy(pv, m_pData + m_nOffset.QuadPart, available);    m_nOffset.QuadPart += available;    if (pcbRead)        *pcbRead = available;    return S_OK;}// //  ISequentialStream::Write // HRESULT __stdcall CStream::Write(const void *pv, ULONG cb, ULONG *pcbWritten){    if (pv == 0)        return STG_E_INVALIDPOINTER;    return E_NOTIMPL;}// //  IStream::Seek // HRESULT __stdcall CStream::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition){    switch (dwOrigin)    {    case STREAM_SEEK_SET:   m_nOffset.QuadPart = dlibMove.QuadPart;                      break;    case STREAM_SEEK_CUR:   m_nOffset.QuadPart = m_nOffset.QuadPart + dlibMove.QuadPart; break;    case STREAM_SEEK_END:   m_nOffset.QuadPart = m_nLength.QuadPart - dlibMove.QuadPart; break;    }    if (plibNewPosition)        *plibNewPosition = m_nOffset;    return S_OK;}// //  IStream::SetSize // HRESULT __stdcall CStream::SetSize(ULARGE_INTEGER libNewSize){    return S_OK;}// //  IStream::CopyTo // HRESULT __stdcall CStream::CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten){    DWORD len, written;    len = (ULONG)min(cb.QuadPart, m_nLength.QuadPart);    pstm->Write(m_pData, len, &written);    if (pcbRead)        pcbRead->QuadPart = len;    if (pcbWritten)        pcbWritten->QuadPart = written;    return S_OK;}// //  IStream::Commit // HRESULT __stdcall CStream::Commit(DWORD grfCommitFlags){    // Transacted mode is not supported     return S_OK;}// //  IStream::Revert // HRESULT __stdcall CStream::Revert(){    // Transacted mode is not supported     return S_OK;}// //  IStream::LockRegion // HRESULT __stdcall CStream::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType){    // locking is not supported     return STG_E_INVALIDFUNCTION;}// //  IStream::UnlockRegion // HRESULT __stdcall CStream::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType){    // locking is not supported     return STG_E_INVALIDFUNCTION;}// //  IStream::Stat // HRESULT __stdcall CStream::Stat(STATSTG *pstatstg, DWORD grfStatFlag){    if (pstatstg == 0)        return STG_E_INVALIDPOINTER;    // return our STATSTG to the caller     m_statstg.cbSize.QuadPart = m_nLength.QuadPart;    *pstatstg = m_statstg;    switch (grfStatFlag)    {    case STATFLAG_DEFAULT:        // allocate a new buffer for the name         if ((pstatstg->pwcsName = (WCHAR *)CoTaskMemAlloc(sizeof(DEFNAME))) == 0)            return STG_E_INSUFFICIENTMEMORY;        lstrcpyW(pstatstg->pwcsName, DEFNAME);        break;    case STATFLAG_NONAME:        pstatstg->pwcsName = 0;        break;    default:        return STG_E_INVALIDFLAG;    }    return S_OK;}// //  IStream::Clone // HRESULT __stdcall CStream::Clone(IStream **ppstm){    return E_NOTIMPL;}

使用就很简单了:
BYTE* pData ; // 图像数据
DWORD nSize; // 图像数据的长度

CStream stream(pData, nSize);CImage img;img.Load(&stream);