首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++Builder 任意角度圖片旋轉演算法:雙緩衝映射實作詳解

     編輯:關於C++

演算法核心:逆向映射 + 雙線性插值(此處採最近鄰簡化)

將目標畫布每個像素 反向投影 回源圖座標,避免「洞洞」與重疊。完整函數簽名:

void S_PicXZ(Graphics::TBitmap *Source, Graphics::TBitmap *NewPic, int angle);

完整代碼逐段解析

1. 角度正規化與弧度轉換

if (angle > 180)  angle = 360 - angle;
if (angle < -180) angle = 360 + angle;
float radians = (2 * 3.1416f * angle) / 360.0f;
float cosine  = cosf(radians);
float sine    = sinf(radians);

將角度限制在 [-180, 180],使用 cosf/sinf 單精度版本提升效能。

2. 計算旋轉後四角座標(源圖原點為左上角)

float p1x = -Source->Height * sine;
float p1y =  Source->Height * cosine;
float p2x =  Source->Width  * cosine - Source->Height * sine;
float p2y =  Source->Height * cosine + Source->Width  * sine;
float p3x =  Source->Width  * cosine;
float p3y =  Source->Width  * sine;

對應源圖三個頂點(左下、右下、右上)旋轉後的位置;左上原點 (0,0) 旋轉不變。

3. 求目標畫布寬高(包絡盒)

float minx = min(0.0f, min(p1x, min(p2x, p3x)));
float miny = min(0.0f, min(p1y, min(p2y, p3y)));
float maxx = max(p1x, max(p2x, p3x));
float maxy = max(p1y, max(p2y, p3y));

int dstW, dstH;
if (angle > 90 && angle < 180)   dstW = (int)ceil(-minx);
else                             dstW = (int)ceil(maxx - minx);

if (angle > -180 && angle < -90) dstH = (int)ceil(-miny);
else                             dstH = (int)ceil(maxy - miny);

NewPic->Width  = dstW;
NewPic->Height = dstH;

根據象限調整寬高計算公式,確保畫布剛好容納旋轉後影像。

4. 雙重迴圈:目標像素 → 來源像素(逆向映射)

for (int x = 0; x < dstW; ++x) {
    for (int y = 0; y < dstH; ++y) {
        int srcX = (int)((x + minx) * cosine + (y + miny) * sine);
        int srcY = (int)((y + miny) * cosine - (x + minx) * sine);

        if (srcX >= 0 && srcX < Source->Width &&
            srcY >= 0 && srcY < Source->Height) {
            NewPic->Canvas->Pixels[x][y] = Source->Canvas->Pixels[srcX][srcY];
        }
    }
}
  • 逆向映射:目標 → 來源,保證每個目標像素都有值。
  • 最近鄰取樣:直接取整數座標,速度最快但有鋸齒。
  • 邊界檢查:超出源圖範圍留白(預設黑/透明)。

效能優化建議

方向做法預期增益
像素存取 改用 ScanLine[] 取得行指標,避免 Pixels[][] 巨大開銷 10-50x
插值升級 實作雙線性插值:取 4 點加權平均 畫質大幅提升
SIMD/平行化 OpenMP 平行化外層迴圈,或手寫 SSE/AVX 內聯 多核心線性加速
快速三角函數 查表或多項式近似替代 cosf/sinf 微幅提升

ScanLine 版本關鍵片段

// 假設 24-bit RGB
for (int y = 0; y < dstH; ++y) {
    BYTE *dstRow = (BYTE*)NewPic->ScanLine[y];
    for (int x = 0; x < dstW; ++x) {
        int srcX = ...; int srcY = ...;
        if (in_bounds) {
            BYTE *srcRow = (BYTE*)Source->ScanLine[srcY];
            dstRow[x*3+0] = srcRow[srcX*3+0]; // B
            dstRow[x*3+1] = srcRow[srcX*3+1]; // G
            dstRow[x*3+2] = srcRow[srcX*3+2]; // R
        }
    }
}

結語

此函數展示了經典的「逆向映射 + 包絡盒計算」旋轉核心邏輯。實際專案中請務必:

  1. 改用 ScanLine 存取像素
  2. 加入雙線性/雙三次插值
  3. 處理 Alpha 通道與像素格式自檢
  4. 考慮以 TGPGraphics::RotateTransform (GDI+) 替代手寫,穩定且硬體加速
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved