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

MMAPI 攝影實戰教學:從預覽到拍照與縮圖生成的完整流程

     編輯:J2ME

MMAPI 攝影核心流程架構

Mobile Media API (JSR-135) 透過 capture://video 定位符提供攝影功能。核心類別:Player (媒體控制)、VideoControl (影像顯示/捕獲)、RecordControl (錄影)。本文以 Snapper 範例為基礎,完整呈現從初始化到縮圖生成的工程級實現。

開發環境與測試裝置配置

  • 模擬器:Nokia Series 60 MIDP Concept SDK Beta 0.2 (支援攝影模擬)
  • 真機:Nokia 3650 (首支支援 MMAPI 攝影的商用手機)
  • 部署方式:紅外/藍牙/OTA 安裝 MIDlet

攝影 Player 初始化與資源獲取

// 1. 檢測裝置支援性
boolean supportsCapture = "true".equals(
    System.getProperty("supports.video.capture"));

// 2. 建立 Player 並獲取資源
Player player = Manager.createPlayer("capture://video");
player.realize(); // 關鍵:分配攝影機硬體資源

// 3. 獲取 VideoControl
VideoControl videoControl = (VideoControl) player.getControl("VideoControl");
if (videoControl == null) throw new IllegalStateException("裝置不支援 VideoControl");

影像預覽顯示:Canvas 與 Form 兩種模式

模式一:Canvas 直接繪製 (全螢幕、高效能)

public class CameraCanvas extends Canvas {
    private VideoControl videoControl;
    
    public CameraCanvas(VideoControl vc) {
        this.videoControl = vc;
        // 直接視訊模式:繪製至 Canvas 圖形上下文
        videoControl.initDisplayMode(VideoControl.USE_DIRECT_VIDEO, this);
        
        try {
            // 留 2px 邊框顯示綠色框架
            videoControl.setDisplayLocation(2, 2);
            videoControl.setDisplaySize(getWidth()-4, getHeight()-4);
        } catch (MediaException e) {
            try { videoControl.setDisplayFullScreen(true); } 
            catch (MediaException ignored) {}
        }
        videoControl.setVisible(true);
    }
    
    protected void paint(Graphics g) {
        // 繪製綠色取景框
        g.setColor(0x00FF00);
        g.drawRect(1, 1, getWidth()-3, getHeight()-3);
    }
    
    // 按鍵事件觸發拍照
    protected void keyPressed(int keyCode) {
        if (getGameAction(keyCode) == FIRE) {
            midlet.capturePhoto(); // 回調主 MIDlet
        }
    }
}

模式二:Form GUI 元件嵌入 (適合混合介面)

Form form = new Form("Camera Preview");
Item videoItem = (Item) videoControl.initDisplayMode(
    VideoControl.USE_GUI_PRIMITIVE, null);
form.append(videoItem);
Display.getDisplay(midlet).setCurrent(form);

拍照核心:getSnapshot() 與影像處理

// 1. 捕獲原始影像資料 (預設 PNG 格式)
byte[] rawImage = videoControl.getSnapshot(null); // null = 預設編碼

// 2. 建立 Image 物件供顯示/儲存
Image capturedImage = Image.createImage(rawImage, 0, rawImage.length);

// 3. 可選:預先查詢支援編碼格式
String encodings = System.getProperty("video.snapshot.encodings"); // 如 "png jpeg"
// 指定格式捕獲
byte[] jpegImage = videoControl.getSnapshot("encoding=jpeg");

縮圖生成算法:MIDP 1.0 相容純 Java 實現

MIDP 1.0 無 Image.getRGB() 直接像素存取,採用剪裁繪製法:


private Image createThumbnail(Image source) {
    int srcW = source.getWidth();
    int srcH = source.getHeight();
    int thumbW = 64;
    int thumbH = thumbW * srcH / srcW; // 保持比例
    
    Image thumb = Image.createImage(thumbW, thumbH);
    Graphics g = thumb.getGraphics();
    
    // 逐像素採樣:以 1x1 剪裁區域繪製源圖對應區域
    for (int y = 0; y < thumbH; y++) {
        for (int x = 0; x < thumbW; x++) {
            g.setClip(x, y, 1, 1); // 單像素剪裁區
            int srcX = x * srcW / thumbW;
            int srcY = y * srcH / thumbH;
            // 繪製源圖使目標像素 (x,y) 顯示源圖 (srcX, srcY)
            g.drawImage(source, x - srcX, y - srcY, Graphics.LEFT | Graphics.TOP);
        }
    }
    
    // 建立不可變副本釋放 Graphics 資源
    return Image.createImage(thumb);
}

原理:利用 Graphics.setClip() 限制繪製區域為單一像素,透過負座標偏移將源圖對應區域「投影」至目標像素。雖效能較低 (O(W×H)),但在小尺寸縮圖 (64×48) 可接受。

Snapper 範例完整架構

  • SnapperMIDlet:應用邏輯、視圖流程控制、Player/VideoControl 生命週期管理
  • CameraCanvas:預覽顯示、取景框繪製、拍照觸發事件
  • 主表單:以 ImageItem 動態展示縮圖畫廊

擴展功能建議

  1. 全圖儲存:將 rawImage 寫入檔案系統 (JSR-75) 或 RMS
  2. 刪除/排序:縮圖列表支援長按刪除、拖曳排序
  3. 雲端同步:HTTP POST 上傳至伺服器,配合 Web 相簿瀏覽
  4. MIDP 2.0 影像處理:利用 Image.getRGB()/createRGBImage() 實現濾鏡、銳化、幾何變換

關鍵避坑指南

  • Player 狀態機:必須 realize() 後才能獲取 Control,start() 後預覽才啟動
  • 資源釋放:離開攝影介面必須 player.close(),否則攝影機鎖定影響其他應用
  • 記憶體管理:大尺寸影像易致 OOM,拍照後立即生成縮圖並釋放原始 byte[]
  • 權限提示:首次存取攝影機會彈出安全確認,需引導用戶授權

掌握 MMAPI 攝影完整流程,即可開發行動掃描、拍照記帳、人臉識別前端等豐富影像應用。

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