如何解锁锁定的位图

How to unlock a locked bitmap

本文关键字:锁定 位图 解锁 何解锁      更新时间:2023-10-16

我想解锁一个锁定的ID2D1Bitmap我已经尝试m_pBitmap1->Release();但它似乎不工作

hr=m_pBitmap1->CopyFromRenderTarget(nullptr, m_pRenderTarget2, nullptr);给出一个访问冲突错误:

" dent_detection_sys.exe中0x00fb2a46的未处理异常:0xC0000005:访问违反读取位置0x00000024。"

WICRect rcLock = { 0, 0, sc_bitmapWidth , sc_bitmapHeight };
IWICBitmapLock *pILock=NULL;
hr =pWICBitmap->Lock(&rcLock, WICBitmapLockWrite, &pILock);

hr=pRT->CreateSharedBitmap(
    IID_IWICBitmapLock,
    static_cast<void *>(pILock),
    &bp2,
    &m_pBitmap1
    ); 

hr=m_pBitmap1->Release(); 
hr=m_pBitmap1->CopyFromRenderTarget(nullptr, m_pRenderTarget2, nullptr); 

要解锁WIC位图,请释放IWICBitmapLock:

pILock->Release();

你应该只在你不想再使用它的时候释放m_pBitmap1。

hr=m_pBitmap1->CopyFromRenderTarget(nullptr, m_pRenderTarget2, nullptr); 
hr=m_pBitmap1->Release(); 

根据MSDN使用共享WIC位图,渲染目标类型必须为D2D1_RENDER_TARGET_TYPE_SOFTWARE。

cdemo是一个结构对象,具有基本的d2d、wic、dwrite接口指针。示例:cdemo->d2d.factory-> createssomething (), cdemo-> wicc .factory-> createssomething (), cdemo->dwrite.factory-> createssomething, cdemo->xaudio.factory-> createssomething等

cbmp是指向结构体的指针,该结构体具有与WIC位图相关的接口和属性

下面的示例如果没有一些调整和错字修复就不能正常工作,但它可以用来演示如何使用wic编辑位图并直接访问像素此代码假定cdemo->d2d。工厂和cdemo->工厂已经创建。

#define DEBUG_FAILED_GOTO(a,b) MessageBox(m_hwnd, a, L"FAILED", MB_OK); goto b
#define DEBUG_DISPLAY(a)       MessageBox(m_hwnd, a, L"DEBUG", MB_OK)
#define USING_SHARED_WIC_BITMAP
#define USING_WIC_RENDER_TARGET
#define USING_WICBMP_COPY_TO_D2DBMP
struct COMMON_WIC_BGRA { BYTE b, g, r, a };
struct COMMON_WIC_BMP
{
//// Miscelaneous variables
bool ready;
bool using_d2d_bmp;
bool using_shared_bmp;
bool using_render_tgt;
bool ready_d2d_bmp;
bool ready_shared_bmp;
bool ready_render_tgt;
UINT BPPPP;                                 // Bit-Per-Pixel-Per-Plane
UINT stride;                                // cbStride = row size;
UINT buff_size;                             // (org_size.y * stride);
POINT org_size, clip_TpLt, padding;
POINT cur_size, clip_BtRt;
D2D1_BITMAP_PROPERTIES          props_bmp;  // = D2D1::BitmapProperties();
D2D1_RENDER_TARGET_PROPERTIES   props_tgt;  // = D2D1::RenderTargetProperties();
WICPixelFormatGUID formatGUID;              // =  GUID_WICPixelFormat32bppPBGRA;
WICRect rc_lock;                            // the lock region, usually the entire
//// Interfaces
IWICBitmap*             ifc_bmp;            // WIC bitmap: lock and unlock bmp data;
IWICBitmapLock*         ifc_lock;           // Used to access the pixels to read/write
ID2D1RenderTarget*      ifc_render_tgt;     // Creates a d2d render target
ID2D1Bitmap*            ifc_d2d_bmp;        // creates an d2d bitmap for display
ID2D1Bitmap*            ifc_shared_bmp;     // creates a shared bitmap for display
ID2D1SolidColorBrush*   ifc_render_brush;   // This is needed for the render target  
//// Data pointers
BYTE*                   byte;               // Points to a pixel's byte; 8 bits
COMMON_WIC_BGRA*        wpixel;             // Points to a pixel; 32 bits
};
BOOL Lock_Release (COMON_WIC_BMP *cbmp);
BOOL Lock_Start (COMMON_INTERFACE_STUFF *cdemo, COMMON_WIC_BMP *cbmp, DWORD flags);
void Create_BMP_n_Stuff (
     COMMON_INTERFACE_STUFF *cdemo, 
     COMMON_WIC_BMP *cbmp, 
     int org_xsize, 
     int org_ysize)
{
DEBUG_DISPLAY(L"Gate 0-1 Open: started xxx process");
if (cbmp == NULL) { return E_FAIL; }
if (cdemo == NULL) { return E_FAIL; }
DEBUG_DISPLAY(L"Gate 0-2 Open: passed the sanity test");
HRESULT hr = S_OK;
ZeroMemory(cbmp, sizeof(COMMON_WIC_BMP));
 
// Create a Direct2D render target.
if (cdemo->d2d.hwnd_tgt == NULL)
{   
    RECT rc;
    GetClientRect(m_hwnd, &rc);
    D2D1_SIZE_U size = D2D1::SizeU((rc.right - rc.left), (rc.bottom - rc.top));
    cdemo->d2d.props_tgt      = D2D1::HwndRenderTargetProperties(m_hwnd, size);
    cdemo->d2d.props_tgt_type = D2D1_RENDER_TARGET_TYPE_SOFTWARE;
    cdemo->d2d.props_bmp = D2D1::BitmapProperties();
    hr = cdemo->d2d.factory->CreateHwndRenderTarget(
         cdemo->d2d.props_tgt_type,
         cdemo->d2d.props_tgt,
         &cdemo->d2d.hwnd_tgt);
    if (FAILED(hr)) { goto CleanUp; }
}
DEBUG_DISPLAY(L"Gate 1 Open: hwnd_tgt created");
cbmp->ready = false; // type is: bool
// this option is compatible to D2D bitmap without conversion
cbmp->formatGUID = GUID_WICPixelFormat32bppPBGRA; // type is: WICPixelFormatGUID 
cbmp->buff_size = 0;    // type is: UINT32
cbmp->stride = 0;       // type is: UINT32
cbmp->clip_TpLt.x = 0;   // type is: POINT or POINTS
cbmp->clip_TpLt.y = 0;
cbmp->clip_BtRt.x = cbmp->org_size.x = org_xsize; // type is: POINT or POINTS
cbmp->clip_BtRt.y = cbmp->org_size.y = org_ysize;
cbmp->byte = NULL;  // type is: pointer to BYTE, BYTE*
cbmp->pixel = NULL; // type is: pointer to COMMON_WIC_BGRA, COMMON_WIC_BGRA* 
cbmp->ifc_bmp = NULL;          // type is: IWICBitmap*
cbmp->ifc_d2d_bmp = NULL;      // type is: ID2D1Bitmap*
cbmp->ifc_lock = NULL;         // type is: IWICBitmapLock*
cbmp->ifc_shared_bmp = NULL;   // type is: ID2D1Bitmap*
cbmp->ifc_render_tgt = NULL;   // type is: ID2D1RenderTarget*
cbmp->ifc_render_brush = NULL; // type is: ID2D1SolidColorBrush*
//D2D1_BITMAP_PROPERTIES        props_bmp; = D2D1::BitmapProperties();
//D2D1_RENDER_TARGET_PROPERTIES props_tgt; = D2D1::RenderTargetProperties();
//bool ready;
//bool using_d2d_bmp;
//bool using_shared_bmp;
//bool using_render_tgt;
//bool ready_d2d_bmp;
//bool ready_shared_bmp;
//bool ready_render_tgt;
//UINT BPPPP;                                   // Bit-Per-Pixel-Per-Plane
if (cdemo->wic.factory == NULL)
{   // (re)create the WIC factory
 
    hr = CoCreateInstance(
        CLSID_WICImagingFactory,
        NULL,
        CLSCTX_INPROC_SERVER,
        IID_IWICImagingFactory,
        reinterpret_cast<void **>(&cdemo->wic.factory));
    if (FAILED(hr)) { goto CleanUp; }
}
hr = cdemo->wic.factory->CreateBitmap(
        cbmp->org_size.x,
        cbmp->org_size.y,
        cbmp->formatGUID,
        WICBitmapCacheOnDemand,
        &cbmp->ifc_bmp);
// Experimental debug
//if (FAILED(hr)) { DEBUG_FAILED_GOTO(L"FAILED creating wic bitmap", CleanUp); }
if (FAILED(hr)) { goto CleanUp; }
DEBUG_DISPLAY(L"Gate 2 Open: created the WIC bitmap");
// type is: WICRect;
cbmp->rc_lock = { 0, 0, (UINT)cbmp->org_size.x, (UINT)cbmp->org_size.y };
hr = cbmp->ifc_bmp->Lock(&cbmp->rc_lock, WICBitmapLockWrite, &cbmp->ifc_lock);
hr = cbmp->ifc_lock->GetStride(&cbmp->stride);  //row size = (xsize*BPPP) + xpadding
hr = cbmp->ifc_lock->GetDataPointer(&cbmp->buff_size, &cbmp->byte);
cbmp->wpixel = (COMMON_WIC_BRGA *)cbmp->byte;
// clear the bitmap
ZeroMemory(cbmp->byte, cbmp->buff_size);
#ifdef USING_SHARED_WIC_BITMAP
cbmp->props_bmp = D2D1:BitmapProperties(); 
hr = demo->d2d.hwnd_tgt->CreateSharedBitmap(
     IID_IWICBitmapLock,
     (void*)cbmp->ifc_lock,
     &cbmp->props_bmp,
     &cbmp->ifc_shared_bmp);
if (SUCCEDED(hr)) 
{ 
    cbmp->using_shared_bmp = true; 
    
    DEBUG_DISPLAY(L"Gate 4-1 Open: created shared wic bitmap");
}
#endif
#ifdef USING_WICBMP_COPY_TO_D2DBMP
hr = cdemo->d2d.factory->CreateBitmapFromWicBitmap(
     cbmp->ifc_bmp,
     &cbmp->props_bmp, 
     &cbmp->ifc_d2d_bmp);
if (SUCCEDED(hr)) 
{ 
    cbmp->using_d2d_bmp = true; 
    
    DEBUG_DISPLAY(L"Gate 4-2 Open: created d2d bitmap ");
}
#endif
#ifdef USING_WIC_RENDER_TARGET
cbmp->props_tgt      = D2D1::RenderTargetProperties();
cbmp->props_tgt.type = D2D1_RENDER_TARGET_TYPE_SOFTWARE;
hr = cdemo->d2d.factory->CreateWicBitmapRenderTarget(
    cbmp->ifc_bmp,
    &cbmp->props_tgt,
    &cbmp->ifc_render_tgt);
if (SUCCEDED(hr))
 {
     hr = cbmp->ifc_render_tgt->CreateSolidColorBrush(
          { 1.0f, 1.0f, 1.0f, 1.0f },  // Solid white
          &cbmp->ifc_render_brush);
     cbmp->using_shared_bmp = true; 
     DEBUG_DISPLAY(L"Gate 4-3 Open: created wic render target and brush");
 }
   
#endif
if (FAILED(hr)) { goto CleanUp; }
cbmp->ready = true;
// Rules of engagement if using all possible combinations above
// 1) After SafeRelease(&cbmp->ifc_lock) you cannot use cbmp->byte or cbmp->wpixel
// 2) To use cbmp->ifc_render_tgt you must first SafeRelease(cbmp->ifc_lock) and 
//    SafeRelease(&cbmp->ifc_shared_bmp). Later reinitialize them as needed.
// 3) To display the wic bitmap (cbmp->ifc_bmp) onto cdemo->d2d.hwnd_tgt:
//    you cannot copy the wic bitmap (cbmp->ifc_bmp) directly to an hwnd render target
//    option 1: This is whole point of creating the shared bmp     
//    cdemo->d2d.hwnd_tgt->DrawBMP( [ &dst_rc, ] cbmp->ifc_shared_bmp);
//    option 2: Copy the pixels to the d2d bitmap, copy the d2d bitmap to the target
//    cbmp->ifc_d2d_bmp->CopyFromMemory(cbmp->byte, &dst_rc, cbmp->stride);
//    cdemo->d2d.hwnd_tgt->DrawBMP( [ &dst_rc, ] cbmp->ifc_d2d_bmp);
//    option 3: Copy from the render target to the d2d bitmap 
//    cbmp->ifc_d2d_bmp->CopyFromRenderTarget(&pt_dst, cbmp->ifc_render_tgt, &src_rc);
//    cdemo->d2d.hwnd_tgt->DrawBMP( [ &dst_rc, ] cbmp->ifc_d2d_bmp); 
// 4) When drawing directly to the wic bitmap either use cbmp->ifc_render_tgt or 
//    cbmp->ifc_lock + cbmp->byte + your own algorithms to draw shapes
//  
// 5) for simplicty: it can get confusing when trying to use all methods
        option 1: use the ifc_lock with the ifc_shared_bmp + your own algorithms    
        option 2: use the ifc_render_tgt with the ifc_d2d_bmp
// Example: Draw a filled 12x15 rectangle example:
int x = 20, byte_col = 0, wpixel_col = 0, sizey = 12;
int y = 35, byte_row = 0, wpixel_row = 0, sizex = 15;
D2D1_COLOR_F d2d_colr = { 0.50f, 0.10f, 0.80f, 1.00f }; //some random color
COMMON_WIC_BGRA wic_colr = { 0, 0, 0, 0 };
D2D1_POINT_2U d2d_pt_dst_f = { 0, 0 };
D2D_RECT_F    d2d_outputrect = { 0.0f, 0.0f, 0.0f, 0.0f };
D2D1_RECT_F   d2d_dst_rcf = 
           { 0.0f, 0.0f, (FLOAT)cbmp->org_size.x, (FLOAT)cbmp->org_size.y }; 
D2D1_RECT_U   d2d_src_rcu = 
           { 0, 0, (UINT32)cbmp->org_size.x, (UINT32)cbmp->org_size.y }; 
WIC_RECT_U wic_dst_rcu =  
           { 0, 0, (UINT32)cbmp->org_size.x, (UINT32)cbmp->org_size.y }; 
WIC_RECT_U wic_src_rcu = wic_dst_rcu  
// must release the lock and shared bitmap before using the render target
Lock_End(cbmp);
    
// This should look familiar
d2d_outputrect = { (FLOAT)x, (FLOAT)y, (FLOAT)(x+sizex-1), (FLOAT)(y+sizey-1) };  
cbmp->ifc_render_tgt->BeginDraw();
cbmp->ifc_render_brush->SetColor(d2d_colr);
cbmp->ifc_render_tgt->SetTransform(D2D1::IdentityMatrix());
cbmp->ifc_render_tgt->FillRectangle(&d2d_outputrect, cbmp->ifc_render_brush);
hr = cbmp->ifc_render_tgt->EndDraw();
    
// display the wic bitmap on the hwnd render target
hr = cbmp->ifc_d2d_bmp->CopyFromRenderTarget(
     &d2d_pt_dst, 
     cbmp->ifc_render_tgt, 
     &d2d_src_rc);
hr = cdemo->d2d.hwnd_tgt->DrawBMP(&d2d_dst_rc, cbmp->ifc_d2d_bmp); 
// Alternative: using the ifc_lock with the ifc_shared_bmp + home grown algorithms
if (!Lock_Start(cdemo, cbmp, WICBitmapLockWrite)) { goto CleanUp; }
 
   
// convert D2D1_COLOR_F { b, g, r, a} to BYTE { b, g, r, a }
wic_colr.b = (BYTE)ceil(d2d_colr.b * 255);
wic_colr.g = (BYTE)ceil(d2d_colr.g * 255);
wic_colr.r = (BYTE)ceil(d2d_colr.r * 255);
wic_colr.a = (BYTE)ceil(d2d_colr.a * 255);
     
for (int run_y = 0; run_y < sizey; ++run_y)
{
    // clipping for the y values
    if (((run_y + y) < cbmp->clip_TpLt.y) || ((run_y + y) >= clip_BtRt.y)) 
    { continue; }
    // convert the y to a byte position
    byte_row = ((run_y + y) * cbmp->stride);
    wpixel_row = ((run_y + y) * cbmp->org_size.x) + cbmp->padding.x;  //optional
    for (int run_x = 0; run_x < sizex; ++run_x)
    {
        // clipping for the x values
        if (((run_x + x) < cbmp->clip_TpLt.x) || ((run_x + x) >= clip_BtRt.x)) 
        { continue; }
        // convert the x to an offset position
        byte_col = ((run_x + x) * 4); // must multiply by 4 bytes (b, g, r, a) 
            
        wpixel_col = (run_x + x);  // cbmp->wpixel points to every 4 bytes
          
        // access the pixels by means of pointer[(y_position + x_offset)]
            
        cbmp->byte[(byte_row + byte_col + 0)] = wic_colr.b;
        cbmp->byte[(byte_row + byte_col + 1)] = wic_colr.g;
        cbmp->byte[(byte_row + byte_col + 2)] = wic_colr.r;
        cbmp->byte[(byte_row + byte_col + 3)] = wic_colr.a;
        cbmp->wpixel[(wpixel_row + wpixel_col)] = wic_colr;   // Alternative
        // Another method
        cbmp->wpixel[(wpixel_row + wpixel_col)].b = wic_colr.b;   // Alternatives
        cbmp->wpixel[(wpixel_row + wpixel_col)].g = wic_colr.g;   // Alternatives
        cbmp->wpixel[(wpixel_row + wpixel_col)].r = wic_colr.r;   // Alternatives
        cbmp->wpixel[(wpixel_row + wpixel_col)].a = wic_colr.a;   // Alternatives
    }
}
// display the wic bitmap on the hwnd render target
cdemo->d2d.hwnd_tgt->DrawBMP(&dst_rc, cbmp->ifc_shared_bmp);
  
// Optionally release the lock after every use
// Lock_Release(cbmp);
return; // commnent out if cleanup is required
CleanUp:
// SafeRelease everything that needs to be released
}
BOOL Lock_Start (
     COMMON_INTERFACE_STUFF *cdemo, 
     COMMON_WIC_BMP *cbmp, 
     DWORD flags)
{
     if (cdemo == NULL) { return FALSE; }
     //if (!cdemo->ready) { CreateResouces(cdemo); }
     if (cbmp == NULL) { return FALSE; }
     
     if (cbmp->ifc_lock != NULL) { return TRUE; }
     SafeRelease(&cbmp->ifc_lock);
     hr = cbmp->ifc_bmp->Lock(&cbmp->rc_lock, flags, &cbmp->ifc_lock);
     
     if (FAILED(hr)) { return FALSE; }
     hr = cbmp->ifc_lock->GetStride(&cbmp->stride);
     
     hr = cbmp->ifc_lock->GetDataPointer(&cbmp->buff_size, &cbmp->byte);
     
     cbmp->wpixel = (COMMON_WIC_BGRA *)cbmp->byte;
     // recreate the shared bitmap
     SafeRelease(&cbmp->ifc_shared_bmp);
     hr = cdemo->d2d.factory->CreateSharedBitmap(
            IID_IWICBitmapLock,
            (void*)cbmp->ifc_lock,
            &cbmp->props_bmp,
            &cbmp->ifc_shared_bmp);
     return TRUE;         
} 
BOOL Lock_Release (COMON_WIC_BMP *cbmp)
{
     if (cbmp == NULL) { return FALSE; }
     
     if (cbmp->ifc_lock == NULL) { return TRUE; }
     
     SafeRelease(&cbmp->ifc_lock);
     SafeRelease(&cbmp->ifc_shared_bmp);
     
     cbmp->byte = NULL;
     cbmp->wpixel = NULL;
     
     if (cbmp->using_render_tgt) { cbmp->ready_render_tgt = true; }
    
     return TRUE;
}