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);
相關推薦
CImage 從記憶體中讀取影象
CImage 的CImage::Load( IStream* pStream) 從記憶體中讀取影象時,需要提供實現了IStream的物件。一般都是採用CreateStreamOnHGlobal建立IStream物件,但這需要重新分配記憶體,再將記憶體中影象複製到
ffmpeg 從記憶體中讀取資料(或將資料輸出到記憶體)
原文見雷大神部落格:http://blog.csdn.net/leixiaohua1020/article/details/12980423 更新記錄(2014.7.24): 1.為了使本文更通俗易懂,更新了部分內容,將例子改為從記憶體中開啟。 2.增加了將資料輸出
FFMPEG記憶體操作(二)從記憶體中讀取數及資料格式的轉換
相關部落格列表: 在雷神的《最簡單的基於FFmpeg的記憶體讀寫例子(記憶體播放器)》中,它是設計回撥函式從輸入檔案中讀取資料。與FFMPEG 官方給出的avio_reading.c不同的是,雷神給的例子是當需要資料的時候,回撥函式才去從輸入檔案讀取資料,而av
openssl從記憶體中讀取RSA公鑰
背景:近期需要在專案中進行RSA簽名驗證,廠商會給出pem格式的RSA公鑰。在以往專案中使用openssl讀取RSA公鑰時基本都是從pem檔案中讀取,基本沒什麼問題,可最近由於專案需要需要從資料庫中讀取RSA公鑰,經查資料發現openssl提供了bio介面以支援各種形式的祕
c++從txt中讀取數據,數據並不是一行路徑(實用)
users from lin filename stream use void red man #include <iostream>#include <fstream>#include <string> using namespace
從excel中讀取用戶數據發送email
img info 發送郵件 可恥 mage color problem item sendmai from openpyxl import load_workbook import smtplib from email.mime.text import MIMEText
python 從檔案中讀取資料,同時去除掉空格和換行
從檔案中讀取資料,同時去除掉空格和換行,程式碼如下 import numpy as np def sort(path): w = open(path,'r') l = w.readlines() col=[] for k in l: k = k.strip('\n')
springboot中配置addResourceHandler和addResourceLocations,使得可以從磁碟中讀取圖片、視訊、音訊等
磁碟目錄 WebMvcConfig的程式碼 //對靜態資源的配置 @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { String os = System.ge
從minio中讀取檔案流進行下載檔案
一、獲取Minio連線 public static String minioUrl; public static String minioUsername;
從Excel中讀取點座標建立參照點
來自Revit SDK案例, public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { Autodesk.
從JSON中讀取數據追加到HTML中
格式 string repl number var str return null ram 本文來自https://www.jianshu.com/p/04127d74d88c,並非本人原創,只是作為自己學習使用的資料,如有瀏覽者請點擊地址自行到原作者頁面瀏覽 有時候我們需
從檔案中讀取擷取字元並對擷取的字元進行排序
#include "stdio.h" #include "stdlib.h" int main(void) { char pathname[50], c_read[5]; int arr[200]={0}; char char_read; FILE *fp; printf("Input
C#從資料庫中讀取二進位制流並生成檔案
下面以圖片檔案為例加以說明。從資料庫表 “圖片儲存”中讀取ID為1的圖片資料並生成圖片檔案。 MySqlConnection conn = new MySqlConnection("Server=localhost;Database=test;charset=utf8;U
讀取Excel二進制寫入DB,並從DB中讀取生成Excel文件
ada pac 讀取excel class rgs unique stat fir tco namespace SendMailSMSService { class Program { static void Main(string[] a
從excel中讀取時間
package com.cheche365.cheche.core.model import org.apache.poi.hssf.usermodel.HSSFCell import org.apache.poi.hssf.usermodel.HSSFRow import org.a
shell 從檔案中讀取批量檔名並做命令列操作
222檔案內容: /home/zhangsuosheng/Desktop/9-30/9_30/1bak/1538291162.png /home/zhangsuosheng/Desktop/9-30/9_30/1bak/1538291212.png /home/zhangsuosheng/Deskto
kalibr 如何從bag中提取影象/由影象生成bag
1. 從bag中提取影象 使用kalibr自帶的bagextractor工具 ./kalibr_bagextractor --image-topics /cam0/image_raw --bag ./static/output.bag 使用python指令碼 2. 由影象生
從HDFS中讀取檔案
2013-02-01 周海漢 2013.2.1 本程式碼可以從本地或hdfs系統中讀取檔案兩次,並在終端打印出來。 /** * test read file from hdfs */ package my.test;
從檔案中讀取圖片,與從資料庫表中讀取圖片評測
一、在 d:\ 下建立 image 資料夾,再放10 張圖片, 名稱從 1.png 到 10.png . 二、先建立新庫 db1, 然後按下面指令碼建立初始環境: USE db1 GO IF OBJECT_ID('t_path') IS NOT NULL DROP TABLE t_pat
Prefuse學習(二)從資料庫中讀取資料
prefuse是一個非常不錯的開源視覺化專案,尤其是用在social network/complex network上,個人感覺要比jung好。不過可惜的是,prefuse的user manual還在建