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

MIDP 圖片縮放實現:雙通道插值算法與性能優化對比

     編輯:J2ME

MIDP 1.0/2.0 均未提供圖片縮放 API,開發者需自行實現。本文介紹基於 Graphics.drawImage() 裁剪繪製的「雙通道單向插值」算法,並對比「雙重循環像素級複製」方案,量化性能差異給出工程選型建議。

核心原理:分離式單向縮放

將二維縮放分解為兩次一維操作:

  1. 水平縮放:創建 newW × srcH 可變圖像,逐列從源圖按比例采樣繪製
  2. 垂直縮放:在水平結果上創建 newW × newH 目標圖,逐行按比例采樣繪製

利用 Graphics.setClip(x, y, w, h) 限制繪製區域為單行/單列,配合負座標偏移實現「源圖像素映射到目標像素」。

高效實現:scale() — O(W+H) 繪製調用


public static Image scale(Image src, int newW, int newH) {
    int srcW = src.getWidth();
    int srcH = src.getHeight();

    // 1. 水平縮放
    Image tmp = Image.createImage(newW, srcH);
    Graphics g = tmp.getGraphics();
    for (int x = 0; x < newW; x++) {
        g.setClip(x, 0, 1, srcH);                    // 單列裁剪區
        int srcX = x * srcW / newW;                  // 源圖對應列
        g.drawImage(src, x - srcX, 0, Graphics.LEFT | Graphics.TOP);
    }

    // 2. 垂直縮放
    Image dst = Image.createImage(newW, newH);
    g = dst.getGraphics();
    for (int y = 0; y < newH; y++) {
        g.setClip(0, y, newW, 1);                    // 單行裁剪區
        int srcY = y * srcH / newH;                  // 源圖對應行
        g.drawImage(tmp, 0, y - srcY, Graphics.LEFT | Graphics.TOP);
    }
    return dst;
}

朴素實現:scale2() — O(W×H) 像素級操作


public static Image scale2(Image src, int newW, int newH) {
    int srcW = src.getWidth(), srcH = src.getHeight();
    Image dst = Image.createImage(newW, newH);
    Graphics g = dst.getGraphics();
    for (int x = 0; x < newW; x++) {
        for (int y = 0; y < newH; y++) {
            g.setClip(x, y, 1, 1);                   // 單像素裁剪
            int srcX = x * srcW / newW;
            int srcY = y * srcH / newH;
            g.drawImage(src, x - srcX, y - srcY, Graphics.LEFT | Graphics.TOP);
        }
    }
    return dst;
}

性能實測對比 (模擟器 240×320 全屏縮放)

結論:雙重循環方案時間複雜度為平方級,實際耗時接近 2 分鐘,完全不可接受。雙通道方案線性複雜度,毫秒級完成,工程上必須採用。

工程化封裝建議

  • 封裝為 ImageUtils.scale(src, w, h) 靜態方法
  • 添加 SCALE_FAST (最近鄰) / SCALE_SMOOTH (雙線性插值模擬) 模式參數
  • 緩存縮放結果:WeakHashMap<Image, SoftReference<Image>> 避免重複計算
  • 大圖分塊處理:超過 200×200 分塊縮放再拼接,避免堆內存峰值
  • 異步預縮放:啟動/后台線程預生成常用尺寸縮略圖

視覺效果補償

最近鄰插值在放大時產生馬賽克,縮小時出現摩爾紋。工程對策:

  • 放大前先雙線性插值到 2× 再最近鄰縮回目標 (模擬雙線性)
  • 縮小前先應用簡單盒濾波 (均值採樣 2×2 像素) 再縮放
  • UI 設計規避:圖標按 1×、1.5×、2× 整數倍準備多套資源,運行時僅選不縮放

完整示例 MIDlet

文中包含完整 ImageUtil 類與演示 MIDlet,展示原圖、全屏放大、1/4 縮小三種效果對比截圖 (見文中圖片鏈接)。

掌握分離式縮放算法並封裝為復用組件,是 J2ME 遊戲/應用實現高性能圖片自適應顯示的關鍵技能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
方案繪製調用次數耗時相對性能
scale() 雙通道newW + newH = 560~60 ms1× (基準)
scale2() 雙重循環newW × newH = 76,800~7,150 ms~119× 慢