【问题标题】:How to unlock a locked bitmap如何解锁锁定的位图
【发布时间】:2014-06-06 12:58:31
【问题描述】:

我想解锁一个锁定的 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); 

【问题讨论】:

    标签: c++ visual-c++ mfc direct2d wic


    【解决方案1】:

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

    pILock-&gt;Release();

    【讨论】:

      【解决方案2】:

      只有在不想再使用 m_pBitmap1 时才应该释放它。

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

      【讨论】:

        【解决方案3】:

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

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

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

        如果没有一些调整和错字修复,以下示例无法按原样工作,但它可用于演示如何使用 wic 编辑位图和直接访问像素 此代码假定 cdemo->d2d.factory 和 cdemo->wic.factory 已创建。

        #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;
        }
        

        【讨论】:

          猜你喜欢
          • 2023-01-25
          • 1970-01-01
          • 2012-01-16
          • 1970-01-01
          • 2021-12-23
          • 2015-01-02
          • 1970-01-01
          • 2019-07-29
          • 2012-04-30
          相关资源
          最近更新 更多