×
Namespaces

Variants
Actions
Revision as of 08:50, 23 October 2013 by hamishwillee (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

如何利用MMAPI实现照相功能

From Nokia Developer Wiki
Jump to: navigation, search
WP Metro Icon Chinese.png
Article Metadata

代码示例
文章
max.chen 在 20 Mar 2011 创建
最后由 hamishwillee 在 23 Oct 2013 编辑

MMAPI(Mobile Media API )是在JSR 135中提出的,增强了Java ME平台对多媒体的支持。作为一个可选包(optional package ),MMAPI目前被绝大多数Java ME设备所支持。通过MMAPI中的VideoControl和Player就可以实现照相功能。


Java ME的用户界面大致分为两类:高级界面和低级界面。高级界面使用方便,但自由度不大。低级界面自由度大,但都要靠程序自己来完成所有绘制工作。在这两种界面上VideoControl都可以很好地工作,只需要在初始化时指定对应的工作模式。函数Object initDisplayMode(int mode, Object arg)用来设置VideoControl的显示模式,其中参数mode表示显示的模式,arg则根据mode的取值而变化。目前已有两种显示模式被定义,分别是GUIControl.USE_GUI_PRIMITIVE和VideoControl.USE_DIRECT_VIDEO。如果使用USE_GUI_PRIMITIVE,则说明VideoControl将被放置在一个高级界面的容器中显示出来;相应,使用USE_DIRECT_VIDEO 则说明VideoControl将显示在低级界面上。在这个例子中,我们用到的是Canvas,所以在下面的代码中可以看到USE_DIRECT_VIDEO作为第一个参数传了进去。需要注意到是在USE_DIRECT_VIDEO模式下,默认是不可见的,需要通过setVisible(boolean visible)方法来设置。


import javax.microedition.lcdui.*;
import javax.microedition.media.MediaException;
import javax.microedition.media.control.VideoControl;
 
public class VideoCanvas extends Canvas {
private CameraMIDlet midlet;
 
public VideoCanvas(CameraMIDlet midlet, VideoControl videoControl) {
int width = getWidth();
int height = getHeight();
this.midlet = midlet;
 
videoControl.initDisplayMode(VideoControl.USE_DIRECT_VIDEO, this);
try {
videoControl.setDisplayLocation(2, 2);
videoControl.setDisplaySize(width - 4, height - 4);
} catch (MediaException me) {}
videoControl.setVisible(true);
}
 
public void paint(Graphics g) {
int width = getWidth();
int height = getHeight();
 
g.setColor(0x00ff00);
g.drawRect(0, 0, width - 1, height - 1);
g.drawRect(1, 1, width - 3, height - 3);
}
}


无论是哪种模式,我们都可以对画面的大小进行调整。通过方法setDisplaySize(int width, int height),我们可以设置显示画面的大小。这里注意,是设置显示画面的大小,也就是说,它不会影响到后面谈到的获取的快照的大小。在USE_DIRECT_VIDEO模式下,我们还可以设置画面的位置,方法setDisplayLocation(int x, int y)正是提供了这样的功能,两个参数分别是画面左上角的坐标。而画面的源大小、显示大小、显示位置等信息可以通过VideoControl提供的一些方法来获取,分别是getSourceWidth() 、getSourceHeight() 、getDisplayWidth() 、getDisplayHeight() 、getDisplayX() 、getDisplayY()。



到目前为止,我们所做的工作仅仅是如何控制一个摄像头来取景,而最后一个关键步骤则是获取一张静态图片。方法getSnapshot(String imageType)可以按照指定文件格式返回图片的数据,然后可以利用返回的数据创建一个图片。其中ImageType是图片格式,传进null则是默认的png图片。

    byte[] raw = videoControl.getSnapshot(null);
Image image = Image.createImage(raw, 0, raw.length);

这样我就的得到了图片的数据,我们可以把它保存到本地或传输到网络上。由于这些功能都需要签名,在这个例子中我们只是把图片显示在手机屏幕上。

import java.io.IOException;
import javax.microedition.lcdui.*;
import javax.microedition.media.*;
import javax.microedition.media.control.*;
import javax.microedition.midlet.MIDlet;
import javax.microedition.media.control.VideoControl;
 
public class CameraMIDlet extends MIDlet implements CommandListener {
 
private Display display;
private Form form;
private Command exit,back,capture,camera;
private Player player;
private VideoControl videoControl;
private Video video;
 
public CameraMIDlet() {
 
exit = new Command("Exit", Command.EXIT, 0);
camera = new Command("Camera", Command.SCREEN, 0);
back = new Command("Back", Command.BACK, 0);
capture = new Command("Capture", Command.SCREEN, 0);
 
form = new Form("Capture Video");
form.addCommand(camera);
form.setCommandListener(this);
}
 
public void startApp() {
display = Display.getDisplay(this);
display.setCurrent(form);
}
 
public void pauseApp() {}
 
public void destroyApp(boolean unconditional) {}
 
public void commandAction(Command c, Displayable s) {
if (c == exit) {
destroyApp(true);
notifyDestroyed();
} else if (c == camera) {
showCamera();
} else if (c == back)
display.setCurrent(form);
else if (c == capture) {
video = new Video(this);
video.start();
}
}
 
public void showCamera() {
try {
player = Manager.createPlayer("capture://video"); // "capture://video" is used for S60 devices
//player = Manager.createPlayer("capture://image"); // "capture://image" is used for Series 40 devices
player.realize();
 
videoControl = (VideoControl)player.getControl("VideoControl");
Canvas canvas = new VideoCanvas(this, videoControl);
canvas.addCommand(back);
canvas.addCommand(capture);
canvas.setCommandListener(this);
display.setCurrent(canvas);
player.start();
} catch (IOException ioe) {} catch (MediaException me) {}
}
 
class Video extends Thread {
CameraMIDlet midlet;
public Video(CameraMIDlet midlet) {
this.midlet = midlet;
}
 
public void run() {
captureVideo();
 
}
 
public void captureVideo() {
try {
byte[] raw = videoControl.getSnapshot(null);
Image image = Image.createImage(raw, 0, raw.length);
form.append(image);
display.setCurrent(form);
 
player.close();
player = null;
videoControl = null;
} catch (MediaException me) { }
}
};
}

代码示例:

Media:CameraDemo.zip

其他资源:

http://developers.sun.com/mobility/midp/articles/picture/

http://www.java-tips.org/java-me-tips/midp/capturing-video-on-j2me-devices.html

This page was last modified on 23 October 2013, at 08:50.
166 page views in the last 30 days.