CImage 从内存中读取图像

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);
  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值