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

J2ME/MIDP 影像旋轉演算法完整實作:數學原理、程式碼與效能優化

     編輯:Java 相關知識

J2ME/MIDP 影像旋轉技術概覽

在資源受限的行動裝置上實作任意角度影像旋轉,需兼顧數學正確性、記憶體效能與執行速度。本文從 2D 旋轉數學推導、MIDP 2.0 API 實作、失真問題解決、CLDC 1.0 相容性到替代方案完整說明。

1. 2D 旋轉數學基礎

座標變換公式

點 P(x,y) 繞原點逆時針旋轉 θ 到 P'(x',y'):

x' = x·cosθ - y·sinθ
y' = x·sinθ + y·cosθ

以任意中心點 Q(x0,y0) 旋轉

x' = x0 + (x-x0)·cosθ - (y-y0)·sinθ
y' = y0 + (y-y0)·cosθ + (x-x0)·sinθ

裝置座標系調整

螢幕左上為原點,Y 軸向下。視 θ 為順時針角度,公式不變。

2. 演算法核心流程

  1. 取得來源影像像素陣列 getRGB()。
  2. 計算旋轉半徑 dr = max(距離四角),建立外切正方形畫布 (2·dr+1)²。
  3. 遍歷來源每個像素,套用旋轉公式計算目標座標 (destX, destY)。
  4. 將像素值寫入目標陣列 destMap[destY·w + destX] = srcMap[y·w + x]。
  5. 建立旋轉後影像 createRGBImage(),回傳位置偏移量供繪製對齊。

3. MIDP 2.0 完整實作程式碼

/**
 * @param imgSource 來源影像
 * @param cx 旋轉中心相對來源左上 X
 * @param cy 旋轉中心相對來源左上 Y
 * @param theta 逆時針旋轉角度(度)
 * @param offset 輸出:新影像相對來源的位移 {dx, dy}
 * @return 旋轉後影像
 */
public Image rotate(Image imgSource, int cx, int cy, double theta, int[] offset) {
    if (Math.abs(theta % 360) < 0.1) return imgSource; // 角度極小直接返回

    int w = imgSource.getWidth();
    int h = imgSource.getHeight();
    int[] src = new int[w * h];
    imgSource.getRGB(src, 0, w, 0, 0, w, h);

    // 計算旋轉半徑(到四角最大距離)
    int dx = Math.max(cx, w - cx);
    int dy = Math.max(cy, h - cy);
    double dr = Math.sqrt(dx*dx + dy*dy);
    int size = (int)(2 * dr) + 1; // 正方形邊長 +1 防越界

    int[] dest = new int[size * size];
    double rad = Math.toRadians(theta);
    double cos = Math.cos(rad), sin = Math.sin(rad);

    for (int y = 0; y < h; y++) {
        for (int x = 0; x < w; x++) {
            int pixel = src[y * w + x];
            if ((pixel >> 24) != 0) { // 忽略全透明像素
                double destX = dr + (x - cx) * cos - (y - cy) * sin;
                double destY = dr + (y - cy) * cos + (x - cx) * sin;
                int ix = (int) destX;
                int iy = (int) destY;
                if (ix >= 0 && ix < size && iy >= 0 && iy < size) {
                    dest[iy * size + ix] = pixel;
                }
            }
        }
    }

    offset[0] = cx - (int)dr; // 繪製位移補償
    offset[1] = cy - (int)dr;
    return Image.createRGBImage(dest, size, size, true);
}

4. 旋轉失真問題與解決方案

成因

前向映射(來源→目標)導致多個來源像素映射到同一目標座標(覆蓋),或目標座標無來源像素(空洞)。

解決策略

方法原理成本
超採樣來源放大 N 倍旋轉再縮小記憶體/運算 ×N²
反向映射遍歷目標座標,反推來源座標雙線性插值品質最佳,運算較重
馬賽克/雙線性補償邊界像素平均/插值低成本,品質中等

反向映射優化版(推薦)

for (int dy = 0; dy < size; dy++) {
    for (int dx = 0; dx < size; dx++) {
        // 目標→來源反向變換
        double sx = cx + (dx - dr) * cos + (dy - dr) * sin;
        double sy = cy - (dx - dr) * sin + (dy - dr) * cos;
        // 雙線性插值取樣...
        dest[dy * size + dx] = bilinearSample(src, w, h, sx, sy);
    }
}

5. CLDC 1.0 無浮點數環境相容

  • 使用定點數學庫(MathFP、JMFP、FPLib)。
  • 預計算三角函數查找表:sin[360]、cos[360](定點數)。
  • 利用對稱性僅儲存 0~90°,推導其他象限。
  • 定點數縮放因子(如 4096)平衡精度與溢位。

6. Sprite 精靈旋轉應用

  • MIDP 2.0 Sprite 內建 90° 倍數旋轉/鏡射。
  • 任意角度需自行實作:每幀旋轉、更新幀影像。
  • 碰撞偵測需改用像素級檢測(collidesWith 配合像素遮罩)。

7. 替代方案比較

方案優點缺點適用場景
即時運算旋轉任意角度、動態中心、無預存成本CPU 密集、失真處理複雜指針、旋轉物件、動態角度
預存多角度幀極快、無運算、品質可控儲存空間大、角度離散角色轉向、固定角度集合
TinyLine 2D 引擎向量圖形、旋轉縮放原生支援、<35KB學習曲線、光柵影像支援有限複雜 2D 繪圖、遊戲 UI

8. 局限性與最佳實務

  • 大影像旋轉記憶體峰值高,分塊處理或降解析度。
  • 固定中心連續旋轉可複用畫布,避免重複配置。
  • Alpha 通道支援為必要條件(MIDP 2.0 強制)。
  • MIDP 1.0 需廠商擴充 API(如 Nokia DirectUtils)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved