1. 程式人生 > >CImage 從記憶體中讀取影象

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還在建