I.Chụp ảnh sử dụng Mobile Media API(MMAPI)
Đặc tả Mobile Media API cung cấp các lớp hỗ trợ chụp ảnh trên thiết bị.
Đầu tiên, Player phải được tạo ra:
Player player;

player = Manager.createPlayer(“capture://video”);
Sau đó player phải được khởi tạo:
Player.relize();
Sau đó, bạn phải nhận “videocontrol” để biểu diễn image ở viewfinder:
VideoControl videoControl;

videoControl = (VideoControl) player.getControl ( “VideoControl”);

VideoControl có 2 kiểu hiển thị:
Vẽ lên đối tượng Canvas trong MIDP UI cấp thấp, hoặc có thể thêm vào trong Form trong MIDP UI cấp cao như một item. Ví dụ như ta sử dụng canvas:
videoControl.initDisplayMode(VideoControl.USE_DIRECT_VIDEO, canvas);
Bắt đầu một player, để người dùng có thể thấy camera:
player.start();
Một khi VideoControl đã được kích hoạt, bạn có thể chụp ảnh:
byte[] pngData = videoControl.getSnapshot(null);
Tham số trong phương thức getSnapShot() là một chuỗi định dạng dữ liệu sẽ được sử dụng. Nếu nó bằng null, dữ liệu sẽ lấy định dạng PNG, định dạng này là định dạng chuẩn và tất cả các máy đều hỗ trợ định dạng này.
Sau đó, dữ liệu có thể sử dụng theo nhiều cách. Có thể là được lưu ở RMS để sử dụng sau, hoặc gửi qua giao thức HTTP đến Server, hoặc hiển thị trực tiếp như một hình ảnh. Để tạo hình ảnh, ta sử dụng phương thức createImage(byte[], int, int) của lớp Image:
Image photoImg = Image.createImage(pngData, 0, pngData.length);
Camera hình ảnh và dữ liệu hình ảnh chiếm dung lượng rất lớn trong bộ nhớ, nên nếu bạn không sử dụng nữa, bạn nên gán tham chiếu của nó bằng null.
II.Thiết kế một ứng dụng CameraMidlet
1.Thiết kế giao diện người dùng
Ứng dụng này có 2 màn hình

  • Màn hình chụp ảnh
  • Màn hình hiển thị hình ảnh sau khi chụp

Màn hình chụp ảnh
Màn hình này biểu diễn một đoạn video đang chạy với hình ảnh kính ngắm(viewfinder) của những cảnh phía trước của máy quay. Khi người dùng quyết định chụp ảnh, họ nhấn vào tùy chọn “Capture” hoặc nhấn phím Fire trên điện thoại.
Màn hình hiển thị hình ảnh sau khi chụp
Màn hình này biểu diễn hình ảnh đã được chụp. Ứng dụng này chỉ minh họa hình ảnh sẽ được hiển thị sau khi chụp, chưa xử lý lưu hay gửi ảnh.

2.Thiết kế phần mềm

Sơ đồ phân lớp:

Lớp CameraMIDlet tạo ra 2 lớp CameraCanvas và DisplayCanvas. CameraCanvas yêu cầu một player chụp video từ lớp Manager và nhận đối tượng thực thi giao diện Player. Từ đối tượng này, nó yêu cầu một điều khiển Video, và nhận một đối tượng thực thi giao diện VideoControl. Bạn sẽ không biết(hoặc không cần biết) lớp thực sự của các đối tượng này, vì bạn chỉ tương tác với chúng thông qua các giao diện của chúng.
4.Mã nguồn
4.1.Lớp CameraMIDlet
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class CameraMIDlet extends MIDlet{
private CameraCanvas cameraCanvas = null;
private DisplayCanvas displayCanvas = null;
public CameraMIDlet()
{}

public void startApp()
{
Displayable current = Display.getDisplay(this).getCurrent();
if (current == null)
{
// first call
cameraCanvas = new CameraCanvas(this);
displayCanvas = new DisplayCanvas(this);
Display.getDisplay(this).setCurrent(cameraCanvas);
cameraCanvas.start();
}
else {
// returning from pauseApp
if (current == cameraCanvas) {
cameraCanvas.start();
}
Display.getDisplay(this).setCurrent(current);
}
}

public void pauseApp()
{
if (Display.getDisplay(this).getCurrent() == cameraCanvas) {
cameraCanvas.stop();
}
}
public void destroyApp(boolean unconditional) {

if (Display.getDisplay(this).getCurrent() == cameraCanvas)
{
cameraCanvas.stop();
}
}
private void exitRequested()
{
destroyApp(false);
notifyDestroyed();
}
void cameraCanvasExit()
{
exitRequested();
}
void cameraCanvasCaptured(byte[] pngData)
{
cameraCanvas.stop();
displayCanvas.setImage(pngData);
Display.getDisplay(this).setCurrent(displayCanvas);
}
void displayCanvasBack()
{
Display.getDisplay(this).setCurrent(cameraCanvas);
cameraCanvas.start();
}
}
4.2.Lớp CameraCanvas
import javax.microedition.lcdui.*;
import javax.microedition.media.*;
import javax.microedition.media.control.*;
import java.io.IOException;

class CameraCanvas extends Canvas implements CommandListener
{
private final CameraMIDlet midlet;
private final Command exitCommand;
private Command captureCommand = null;
private Player player = null;
private VideoControl videoControl = null;
private boolean active = false;

// Two strings for displaying error messages
private String message1 = null;
private String message2 = null;

CameraCanvas(CameraMIDlet midlet)
{
this.midlet = midlet;
exitCommand = new Command(“Exit”, Command.EXIT, 1);
addCommand(exitCommand);
setCommandListener(this);
try
{
player = Manager.createPlayer(“capture://video”);
player.realize();

// Grab the video control and set it to the current display.
videoControl = (VideoControl)(player.getControl(“VideoControl”));
if (videoControl == null)
{
discardPlayer();
message1 = “Unsupported:”;
message2 = “Can’t get video control”;
}
else
{
videoControl.initDisplayMode(VideoControl.USE_DIRECT_VIDEO,
this);

// centre video, letting it be clipped if it’s too big
int canvasWidth = getWidth();
int canvasHeight = getHeight();
int displayWidth = videoControl.getDisplayWidth();
int displayHeight = videoControl.getDisplayHeight();
int x = (canvasWidth – displayWidth) / 2;
int y = (canvasHeight – displayHeight) / 2;
videoControl.setDisplayLocation(x, y);
captureCommand = new Command(“Capture”, Command.SCREEN, 1);
addCommand(captureCommand);
}
}
catch (IOException ioe) {
discardPlayer();
message1 = “IOException:”;
message2 = ioe.getMessage();
}
catch (MediaException me) {
discardPlayer();
message1 = “MediaException:”;
message2 = me.getMessage();
}catch (SecurityException se){
discardPlayer();
message1 = “SecurityException”;
message2 = se.getMessage();
}
}
// Called in case of exception to make sure invalid players are closed
private void discardPlayer()
{
if (player != null)
{
player.close();
player = null;
}
videoControl = null;
}
public void paint(Graphics g)
{
g.setColor(0x00FFFF00); // yellow
g.fillRect(0, 0, getWidth(), getHeight());
if (message1 != null)
{
g.setColor(0x00000000); // black
g.drawString(message1, 1, 1, Graphics.TOP | Graphics.LEFT);
g.drawString(message2, 1, 1 + g.getFont().getHeight(),
Graphics.TOP | Graphics.LEFT);
}
}

synchronized void start() {
if ((player != null) && !active) {
try{
player.start();
videoControl.setVisible(true);
}
catch (MediaException me){
message1 = “Media exception:”;
message2 = me.getMessage();
}catch (SecurityException se) {
message1 = “SecurityException”;
message2 = se.getMessage();
}
active = true;
}
}

synchronized void stop()
{
if ((player != null) && active)
{
try{
videoControl.setVisible(false);
player.stop();
}
catch (MediaException me){
message1 = “MediaException:”;
message2 = me.getMessage();
}
active = false;
}
}

public void commandAction(Command c, Displayable d){
if (c == exitCommand)
{
midlet.cameraCanvasExit();
}
else if (c == captureCommand)
{
takeSnapshot();
}
}
public void keyPressed(int keyCode)
{
if (getGameAction(keyCode) == FIRE)
{
takeSnapshot();
}
}

private void takeSnapshot()
{
if (player != null){
try{
byte[] pngImage = videoControl.getSnapshot(null);
midlet.cameraCanvasCaptured(pngImage);
}
catch (MediaException me){
message1 = “MediaException:”;
message2 = me.getMessage();
}
}
}
}
4.3.Lớp DisplayCanvas
import javax.microedition.lcdui.*;

class DisplayCanvas extends Canvas implements CommandListener
{
private final CameraMIDlet midlet;
private Image image = null;
DisplayCanvas(CameraMIDlet midlet)
{
this.midlet = midlet;
addCommand(new Command(“Back”, Command.BACK, 1));
setCommandListener(this);
}

public void paint(Graphics g){
g.setColor(0x0000FFFF); // cyan
g.fillRect(0, 0, getWidth(), getHeight());
if (image != null){
g.drawImage(image,
getWidth()/2,
getHeight()/2,
Graphics.VCENTER | Graphics.HCENTER);
}
}

void setImage(byte[] pngImage){
image = Image.createImage(pngImage, 0, pngImage.length);
}

public void commandAction(Command c, Displayable d) {
midlet.displayCanvasBack();
}
}

5.Sử dụng Form với VideoControl
Lớp CameraCanvas được sử dụng để hiển thị hình ảnh viewfinder và chụp ảnh. Điều này cũng có thể thực hiện với một Form. Đoạn code dưới đây được dùng để thay CameraCanvas.

import javax.microedition.lcdui.*;
import javax.microedition.media.*;
import javax.microedition.media.control.*;
import java.io.IOException;

class CameraForm extends Form implements CommandListener{
private final FormCameraMIDlet midlet;
private final Command exitCommand;
private Command captureCommand = null;
private Player player;
private VideoControl videoControl;
private boolean active = false;
private StringItem messageItem;

CameraForm(FormCameraMIDlet midlet){
super(“Camera”);
this.midlet = midlet;
messageItem = new StringItem(“Message”, “start”);
append(messageItem);
exitCommand = new Command(“Exit”, Command.EXIT, 1);
addCommand(exitCommand);
setCommandListener(this);

// initialize camera
try{
player = Manager.createPlayer(“capture://video”);
player.realize();

// Grab the video control and set it to the current display.
videoControl = (VideoControl)(player.getControl(“VideoControl”));
if (videoControl != null){
append((Item)(videoControl.initDisplayMode(
VideoControl.USE_GUI_PRIMITIVE, null)));
captureCommand = new Command(“Capture”, Command.SCREEN, 1);
addCommand(captureCommand);
messageItem.setText(“OK”);
}
else{
messageItem.setText(“No video control”);
}
}catch (IOException ioe){
messageItem.setText(“IOException: ” + ioe.getMessage());
}catch (MediaException me){
messageItem.setText(“Media Exception” + me.getMessage());
} catch (SecurityException se){
messageItem.setText(“Security exception: ” + se.getMessage());
}
}

synchronized void start()
{
if (! active){
try{
if (player != null){
player.start();
}
if (videoControl != null){
videoControl.setVisible(true);
}
}catch (MediaException me){
messageItem.setText(“Media exception: ” + me.getMessage());
}catch (SecurityException se){
messageItem.setText(“Security exception: ” + se.getMessage());
}
active = true;
}
}
synchronized void stop()
{
if (active){
try{
if (videoControl != null){
videoControl.setVisible(false);
}

if (player != null) {
player.stop();
}
} catch (MediaException me){
messageItem.setText(“Media exception: ” + me.getMessage());
}
active = false;
}
}

public void commandAction(Command c, Displayable d)
{
if (c == exitCommand) {
midlet.cameraFormExit();
}else if (c == captureCommand){
// if we have a capture command, we know videoControl is not null
try{
byte[] pngImage = videoControl.getSnapshot(null);
midlet.cameraFormCaptured(pngImage);
messageItem.setText(“OK”);
} catch (MediaException me){
messageItem.setText(“Media exception: ” + me.getMessage());
}
}
}
}

Lớp CameraMIDlet tạo ra 2 lớp CameraCanvas và DisplayCanvas. CameraCanvas yêu cầu một player chụp video từ lớp Manager và nhận đối tượng thực thi giao diện Player. Từ đối tượng này, nó yêu cầu một điều khiển Video, và nhận một đối tượng thực thi giao diện VideoControl. Bạn sẽ không biết(hoặc không cần biết) lớp thực sự của các đối tượng này, vì bạn chỉ tương tác với chúng thông qua các giao diện của chúng.
4.Mã nguồn
4.1.Lớp CameraMIDlet
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class CameraMIDlet extends MIDlet{
private CameraCanvas cameraCanvas = null;
private DisplayCanvas displayCanvas = null;
public CameraMIDlet()
{}

public void startApp()
{
Displayable current = Display.getDisplay(this).getCurrent();
if (current == null)
{
// first call
cameraCanvas = new CameraCanvas(this);
displayCanvas = new DisplayCanvas(this);
Display.getDisplay(this).setCurrent(cameraCanvas);
cameraCanvas.start();
}
else {
// returning from pauseApp
if (current == cameraCanvas) {
cameraCanvas.start();
}
Display.getDisplay(this).setCurrent(current);
}
}

public void pauseApp()
{
if (Display.getDisplay(this).getCurrent() == cameraCanvas) {
cameraCanvas.stop();
}
}
public void destroyApp(boolean unconditional) {

if (Display.getDisplay(this).getCurrent() == cameraCanvas)
{
cameraCanvas.stop();
}
}
private void exitRequested()
{
destroyApp(false);
notifyDestroyed();
}
void cameraCanvasExit()
{
exitRequested();
}
void cameraCanvasCaptured(byte[] pngData)
{
cameraCanvas.stop();
displayCanvas.setImage(pngData);
Display.getDisplay(this).setCurrent(displayCanvas);
}
void displayCanvasBack()
{
Display.getDisplay(this).setCurrent(cameraCanvas);
cameraCanvas.start();
}
}
4.2.Lớp CameraCanvas
import javax.microedition.lcdui.*;
import javax.microedition.media.*;
import javax.microedition.media.control.*;
import java.io.IOException;

class CameraCanvas extends Canvas implements CommandListener
{
private final CameraMIDlet midlet;
private final Command exitCommand;
private Command captureCommand = null;
private Player player = null;
private VideoControl videoControl = null;
private boolean active = false;

// Two strings for displaying error messages
private String message1 = null;
private String message2 = null;

CameraCanvas(CameraMIDlet midlet)
{
this.midlet = midlet;
exitCommand = new Command(“Exit”, Command.EXIT, 1);
addCommand(exitCommand);
setCommandListener(this);
try
{
player = Manager.createPlayer(“capture://video”);
player.realize();

// Grab the video control and set it to the current display.
videoControl = (VideoControl)(player.getControl(“VideoControl”));
if (videoControl == null)
{
discardPlayer();
message1 = “Unsupported:”;
message2 = “Can’t get video control”;
}
else
{
videoControl.initDisplayMode(VideoControl.USE_DIRECT_VIDEO,
this);

// centre video, letting it be clipped if it’s too big
int canvasWidth = getWidth();
int canvasHeight = getHeight();
int displayWidth = videoControl.getDisplayWidth();
int displayHeight = videoControl.getDisplayHeight();
int x = (canvasWidth – displayWidth) / 2;
int y = (canvasHeight – displayHeight) / 2;
videoControl.setDisplayLocation(x, y);
captureCommand = new Command(“Capture”, Command.SCREEN, 1);
addCommand(captureCommand);
}
}
catch (IOException ioe) {
discardPlayer();
message1 = “IOException:”;
message2 = ioe.getMessage();
}
catch (MediaException me) {
discardPlayer();
message1 = “MediaException:”;
message2 = me.getMessage();
}catch (SecurityException se){
discardPlayer();
message1 = “SecurityException”;
message2 = se.getMessage();
}
}
// Called in case of exception to make sure invalid players are closed
private void discardPlayer()
{
if (player != null)
{
player.close();
player = null;
}
videoControl = null;
}
public void paint(Graphics g)
{
g.setColor(0x00FFFF00); // yellow
g.fillRect(0, 0, getWidth(), getHeight());
if (message1 != null)
{
g.setColor(0x00000000); // black
g.drawString(message1, 1, 1, Graphics.TOP | Graphics.LEFT);
g.drawString(message2, 1, 1 + g.getFont().getHeight(),
Graphics.TOP | Graphics.LEFT);
}
}

synchronized void start() {
if ((player != null) && !active) {
try{
player.start();
videoControl.setVisible(true);
}
catch (MediaException me){
message1 = “Media exception:”;
message2 = me.getMessage();
}catch (SecurityException se) {
message1 = “SecurityException”;
message2 = se.getMessage();
}
active = true;
}
}

synchronized void stop()
{
if ((player != null) && active)
{
try{
videoControl.setVisible(false);
player.stop();
}
catch (MediaException me){
message1 = “MediaException:”;
message2 = me.getMessage();
}
active = false;
}
}

public void commandAction(Command c, Displayable d){
if (c == exitCommand)
{
midlet.cameraCanvasExit();
}
else if (c == captureCommand)
{
takeSnapshot();
}
}
public void keyPressed(int keyCode)
{
if (getGameAction(keyCode) == FIRE)
{
takeSnapshot();
}
}

private void takeSnapshot()
{
if (player != null){
try{
byte[] pngImage = videoControl.getSnapshot(null);
midlet.cameraCanvasCaptured(pngImage);
}
catch (MediaException me){
message1 = “MediaException:”;
message2 = me.getMessage();
}
}
}
}
4.3.Lớp DisplayCanvas
import javax.microedition.lcdui.*;

class DisplayCanvas extends Canvas implements CommandListener
{
private final CameraMIDlet midlet;
private Image image = null;
DisplayCanvas(CameraMIDlet midlet)
{
this.midlet = midlet;
addCommand(new Command(“Back”, Command.BACK, 1));
setCommandListener(this);
}

public void paint(Graphics g){
g.setColor(0x0000FFFF); // cyan
g.fillRect(0, 0, getWidth(), getHeight());
if (image != null){
g.drawImage(image,
getWidth()/2,
getHeight()/2,
Graphics.VCENTER | Graphics.HCENTER);
}
}

void setImage(byte[] pngImage){
image = Image.createImage(pngImage, 0, pngImage.length);
}

public void commandAction(Command c, Displayable d) {
midlet.displayCanvasBack();
}
}

5.Sử dụng Form với VideoControl
Lớp CameraCanvas được sử dụng để hiển thị hình ảnh viewfinder và chụp ảnh. Điều này cũng có thể thực hiện với một Form. Đoạn code dưới đây được dùng để thay CameraCanvas.

import javax.microedition.lcdui.*;
import javax.microedition.media.*;
import javax.microedition.media.control.*;
import java.io.IOException;

class CameraForm extends Form implements CommandListener{
private final FormCameraMIDlet midlet;
private final Command exitCommand;
private Command captureCommand = null;
private Player player;
private VideoControl videoControl;
private boolean active = false;
private StringItem messageItem;

CameraForm(FormCameraMIDlet midlet){
super(“Camera”);
this.midlet = midlet;
messageItem = new StringItem(“Message”, “start”);
append(messageItem);
exitCommand = new Command(“Exit”, Command.EXIT, 1);
addCommand(exitCommand);
setCommandListener(this);

// initialize camera
try{
player = Manager.createPlayer(“capture://video”);
player.realize();

// Grab the video control and set it to the current display.
videoControl = (VideoControl)(player.getControl(“VideoControl”));
if (videoControl != null){
append((Item)(videoControl.initDisplayMode(
VideoControl.USE_GUI_PRIMITIVE, null)));
captureCommand = new Command(“Capture”, Command.SCREEN, 1);
addCommand(captureCommand);
messageItem.setText(“OK”);
}
else{
messageItem.setText(“No video control”);
}
}catch (IOException ioe){
messageItem.setText(“IOException: ” + ioe.getMessage());
}catch (MediaException me){
messageItem.setText(“Media Exception” + me.getMessage());
} catch (SecurityException se){
messageItem.setText(“Security exception: ” + se.getMessage());
}
}

synchronized void start()
{
if (! active){
try{
if (player != null){
player.start();
}
if (videoControl != null){
videoControl.setVisible(true);
}
}catch (MediaException me){
messageItem.setText(“Media exception: ” + me.getMessage());
}catch (SecurityException se){
messageItem.setText(“Security exception: ” + se.getMessage());
}
active = true;
}
}
synchronized void stop()
{
if (active){
try{
if (videoControl != null){
videoControl.setVisible(false);
}

if (player != null) {
player.stop();
}
} catch (MediaException me){
messageItem.setText(“Media exception: ” + me.getMessage());
}
active = false;
}
}

public void commandAction(Command c, Displayable d)
{
if (c == exitCommand) {
midlet.cameraFormExit();
}else if (c == captureCommand){
// if we have a capture command, we know videoControl is not null
try{
byte[] pngImage = videoControl.getSnapshot(null);
midlet.cameraFormCaptured(pngImage);
messageItem.setText(“OK”);
} catch (MediaException me){
messageItem.setText(“Media exception: ” + me.getMessage());
}
}
}
}