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);
今天的文章CImage 从内存中读取图像分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/8932.html