Namespaces

Variants
Actions

Please note that as of October 24, 2014, the Nokia Developer Wiki will no longer be accepting user contributions, including new entries, edits and comments, as we begin transitioning to our new home, in the Windows Phone Development Wiki. We plan to move over the majority of the existing entries over the next few weeks. Thanks for all your past and future contributions.

如何利用MMAPI实现照相功能

From 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 05:50.
282 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×