首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

圖像處理中 clearmem() 函數解析:內存初始化、幀緩衝區拷貝與 CDIB 類替代方案

     編輯:程式設計綜合問答

代碼解讀

void CDynSplitView2::clearmem() {
    CDSplitDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    pDoc->statedoc = 0;        // 重置文檔狀態標志
    state2 = 1;                // 設置視圖狀態
    CDibNew1 = &pDoc->CDibNew; // 指向目標 DIB (處理後圖像)
    CDib1 = &pDoc->CDib;       // 指向源 DIB (原始圖像)
    long int size = CDib1->GetHeight() * CDib1->GetDibWidthBytes(); // 圖像數據字節數
    memcpy(CDibNew1->m_pData, CDib1->m_pData, size); // 核心:拷貝像素數據
}

功能拆解

  1. 狀態重置:`statedoc=0`、`state2=1` 初始化處理流程標志位。
  2. 雙緩衝指針綁定:`CDibNew1` (目標)、`CDib1` (源) 指向文檔中的兩個 `CDib` 對象。
  3. 計算圖像數據大小:`高度 × 行寬字節數` (含 4 字節對齊填充)。
  4. 像素數據完整拷貝:`memcpy` 將源圖像像素數據複製到目標緩衝區,**實現「撤銷/重置」基線** —— 後續濾波/處理操作在 `CDibNew` 上進行,隨時可恢復原圖。

為什麼缺少 CDIB 類會導致中值濾波效果異常?

  • 中值濾波需要**讀取鄰域像素**計算中值並寫入目標圖像。
  • 若無 `clearmem()` 初始化,`CDibNew` (目標緩衝區) 內容不確定 (殘留上次處理結果或隨機垃圾數據)。
  • 濾波算法若**只寫入符合條件的像素**,未寫入區域保留舊數據 → 輸出圖像混雜舊幀殘影,視覺上表現為「效果不對」、「有噪點」、「邊緣殘留」。
  • 正確流程:每次處理前 `clearmem()` 將原圖完整拷貝到目標緩衝區 → 濾波只修改目標緩衝區像素 → 顯示目標緩衝區。

無 CDIB 類時的替代實現 (純 Win32/GDI+)


// 使用 HBITMAP + GetDIBits / SetDIBits 操作像素緩衝區
void ClearMem(HBITMAP hSrcBmp, HBITMAP hDstBmp, int width, int height) {
    BITMAPINFO bmi = {0};
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth = width;
    bmi.bmiHeader.biHeight = -height; // 自上而下 DIB
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 24; // 或 32
    bmi.bmiHeader.biCompression = BI_RGB;

    // 分配緩衝區
    BYTE *srcBits = malloc(width * height * 3);
    BYTE *dstBits = malloc(width * height * 3);
    
    HDC hdc = GetDC(NULL);
    // 讀取源位圖像素到 srcBits
    GetDIBits(hdc, hSrcBmp, 0, height, srcBits, &bmi, DIB_RGB_COLORS);
    // 拷貝到目標緩衝區 (相當於 clearmem 核心動作)
    memcpy(dstBits, srcBits, width * height * 3);
    // 寫回目標位圖
    SetDIBits(hdc, hDstBmp, 0, height, dstBits, &bmi, DIB_RGB_COLORS);
    ReleaseDC(NULL, hdc);
    free(srcBits); free(dstBits);
}

現代 C++ 最佳實踐

  • 使用 `std::vector` 或 `std::unique_ptr` 管理緩衝區生命週期。
  • 封裝 `ImageBuffer` 類:持有 `width, height, stride, format, data_ptr`,提供 `clone()`, `copyFrom()`, `fill()` 方法。
  • 利用 OpenCV `cv::Mat`:`dst = src.clone();` 一行代碼替代整個 `clearmem()`,並自動處理步長、引用計數、ROI、連續性。

總結

`clearmem()` 本質是**雙緩衝渲染/圖像處理中的「幀重置」操作**:將源圖像數據完整拷貝到目標緩衝區,為後續原地修改算法 (如中值濾波、邊緣檢測、幾何變換) 提供乾淨基線。缺少此步驟會導致未修改像素區域殘留舊數據,產生視覺伪影。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved