Package

Source Code of CameraCanvas

/*
* CameraCanvas.java
*
* Created on August 22, 2006, 2:08 PM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*
* Copyright 2006 by Jon A. Webb
*     This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
*/

/**
*
* @author webb
*/

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.microedition.lcdui.*;
import javax.microedition.media.*;
import javax.microedition.media.control.*;
import javax.microedition.rms.*;

public class CameraCanvas
        extends Canvas
        implements CommandListener
{
   
    /* For calculating barcode and displaying result.
     */
    private BarcodeParam bcp;
    private CharacterizeCamera cc;
    private Command cmdCapture=null;
    private final Command cmdExit;
    private Command cmdFileCapture;
    private Hashtable htFormatCmds = new Hashtable();
    private Hashtable htSourceCmds = new Hashtable();
    private Hashtable htResCmds = new Hashtable();
    private final ReadBarJ midlet;
    private int nCurrentHeight = 0;
    private int nCurrentWidth = 0;
   
    private int nCaptureSource = 0;

    private final int nIdSettings = 0;
   
    private String szCurrentSource;
    //Two strings for displaying error messages
    private String szMessage1=null;
    private String szMessage2=null;
    private final String szRsSettings = "settings";
    private boolean oCaptureFromFile = false;
    private boolean oResultShown = false;
    private boolean oScreenUpdated = false;
    private Player player=null;
    // there doesn't appear to be a reliable way to determine the
    // legal camera resolutions from the API. So here are some
    // reasonable guesses.
    private final int[][] rgxnCameraResolutions =
        {{160,120},
         {320, 240},
         {640, 480},
         {1280, 960}
        };

    private String szCaptureFormat = null;
    private VideoControl videoControl=null;

    /** Creates a new instance of CameraCanvas */
    CameraCanvas(ReadBarJ midlet)
    {
        this.midlet=midlet;
        cmdExit=new Command("Exit",Command.EXIT,1);
        addCommand(cmdExit);
        setCommandListener(this);

        // add a special command for capturing from file
        this.cmdFileCapture = new Command(
            "Choose " + this.nCaptureSource++,
            "Photo from file",
            Command.ITEM,
            2);
        addCommand(this.cmdFileCapture);
        this.cc = new CharacterizeCamera();
        restoreSettings();
        this.bcp = new BarcodeParam();
        // add a command for vanilla capture. if it works add the other
        // source, resolution, and format commands
        if (addcmdCapture()) {
            setupCommands();
        } else {
            Alert a = new Alert(
                    "No camera!",
                    "No cameras are available!",
                    null,
                    AlertType.ERROR);
            try {
                javax.microedition.lcdui.Image i =
                     javax.microedition.lcdui.Image.createImage("/images/camera.png");
                a.setImage(i);
            } catch (Exception e) {
            }
            Display.getDisplay(midlet).setCurrent(a);
        }
    }
   
    private boolean addcmdCapture()
    {
        // if a source hasn't already been set use the first
        Enumeration e = cc.getCaptureSources();
        String szSource = (String) e.nextElement();
        // make sure there's a valid capture source
        if (this.szCurrentSource == null || this.szCurrentSource == "") {
            this.szCurrentSource = szSource;
        }

        if (createPlayer(this.szCurrentSource)) {
            cmdCapture = new Command("Capture", Command.SCREEN, 1);
            addCommand(cmdCapture);
            return true;
        }
        return false;
    }
   
    /**
     * The format and resolution commands are stored in a hashtable so
     * that when we get an input of one of them we can look up the appropriate
     * hashed value and determine what format or resolution we should switch
     * to.
     */
    private void addFormatCommands()
    {
        for (Enumeration e = this.cc.getCaptureFormats(); e.hasMoreElements();) {
            VideoFormat v = (VideoFormat) e.nextElement();
            String szFormat = v.getEncoding();
            int n = szFormat.indexOf("=");
            if (n >= 0) {
                szFormat = szFormat.substring(n+1);
            }
            String szCmdStr = "Photo in " + szFormat;
            if (this.szCaptureFormat == v.getEncoding()) {
                szCmdStr = "+ " + szCmdStr;
            }
            Command command = new Command(
                szFormat,
                szCmdStr,
                Command.ITEM,
                3
            );
            addCommand(command);
            this.htFormatCmds.put(command, v.getEncoding());
        }
    }
   
    private void addResolutionCommands()
    {
        for (int i=0; i<this.rgxnCameraResolutions.length; i++) {
            String szRes = Integer.toString(this.rgxnCameraResolutions[i][0]) +
                "x" +
                Integer.toString(this.rgxnCameraResolutions[i][1]);
            String szCmdStr = "Photo at " + szRes;
            if (this.nCurrentHeight == this.rgxnCameraResolutions[i][1]) {
                szCmdStr = "+ " + szCmdStr;
            }
            Command command = new Command(
                szRes,
                szCmdStr,
                Command.ITEM,
                3
            );
            addCommand(command);
            this.htResCmds.put(command, this.rgxnCameraResolutions[i]);
        }
    }
   
    private void addSourceCommands()
    {
        for (Enumeration e = cc.getCaptureSources(); e.hasMoreElements();)  {
            String szSource = (String) e.nextElement();
            // make sure there's a valid capture source
            if (this.szCurrentSource == null || this.szCurrentSource == "") {
                this.szCurrentSource = szSource;
            }
            Command comSource =
                new Command(
                    "Choose " + nCaptureSource++,
                    "Photo from " + szSource,
                    Command.ITEM,
                    2);
            this.htSourceCmds.put(comSource, szSource);
            addCommand(comSource);
        }

    }
   
    private void clearCommands()
    {
        for (Enumeration e = this.htFormatCmds.keys(); e.hasMoreElements();) {
            Command cmd = (Command) e.nextElement();
            removeCommand(cmd);
        }
        for (Enumeration e = this.htResCmds.keys(); e.hasMoreElements();) {
            Command cmd = (Command) e.nextElement();
            removeCommand(cmd);
        }
        for (Enumeration e = this.htSourceCmds.keys(); e.hasMoreElements();) {
            Command cmd = (Command) e.nextElement();
            removeCommand(cmd);
        }
        this.htFormatCmds.clear();
        this.htResCmds.clear();
        this.htSourceCmds.clear();
    }
   
    private boolean createPlayer(String szSource)
    {
        try {
            this.oCaptureFromFile = false;
            this.player=Manager.createPlayer("capture://" + szSource);
            this.player.realize();
            //Grab the video control and set it to the current display.
            this.videoControl=(VideoControl)(player.getControl("VideoControl"));
            if (this.videoControl==null)
            {
                discardPlayer();
                szMessage1="Unsupported:";
                szMessage2="Can't get videocontrol";
            }
            else
            {
                this.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;
                this.videoControl.setDisplayLocation(x,y);
                }
        } catch(IOException ioe)
        {
            discardPlayer();
            szMessage1="IOException:";
            szMessage2=ioe.getMessage();
            return false;
        } catch(MediaException me)
        {
            discardPlayer();
            szMessage1="MediaException:";
            szMessage2=me.getMessage();
            return false;
        } catch(SecurityException se)
        {
            discardPlayer();
            szMessage1="SecurityException";
            szMessage2=se.getMessage();
            return false;
        }
        this.szCurrentSource = szSource;
        return true;
    }

    // Called in case of exception to make sure invalid players are closed
    private void discardPlayer()
    {
        if(player!=null)
        {
            player.close();
            player=null;
        }
        videoControl=null;
    }
   
    private void doCapture()
    {
        if (this.player.getState() == Player.STARTED) {
            takeSnapshot();
            this.oResultShown = false;
        } else {
            this.bcp.reset();
            repaint();
            start();
        }
    }
   
    public void paint(Graphics g)
    {
        if (this.bcp.imageInput == null) {
            g.setColor(0x00808080); // gray
            g.fillRect(0,0,getWidth(),getHeight());
        }
        this.bcp.paint(g);
        if (!this.oResultShown) {
            if (bcp.getSuccessful()) {
                // successful results are shown by the bcp paint method
            } else if (bcp.getAttempted()) {
                Alert a = new Alert("Barcode not found",
                        "No barcode found",
                        null,
                        AlertType.WARNING);
                a.setTimeout(1000);
                Display.getDisplay(this.midlet).setCurrent(a);
                this.oResultShown = true;
           }
        }
        if(szMessage1!=null)
        {
            Alert a = new Alert(szMessage1, szMessage2,
                    null, AlertType.ERROR);
            a.setTimeout(Alert.FOREVER);
            Display.getDisplay(this.midlet).setCurrent(a);
            szMessage1 = null;
            szMessage2 = null;
        }
    }
   
   
    private void setupCommands() {
        clearCommands();
        addSourceCommands();
        addFormatCommands();
        addResolutionCommands();
    }
   
     synchronized void start()
    {
        if((player!=null) && this.player.getState() != player.STARTED)
        {
            try
            {
                player.start();
                videoControl.setVisible(true);
            } catch(MediaException me)
            {
                szMessage1="Mediaexception:";
                szMessage2=me.getMessage();
            } catch(SecurityException se)
            {
                szMessage1="SecurityException";
                szMessage2=se.getMessage();
            }
        }
    }
    synchronized void stop()
    {
        if((player!=null)&& this.player.getState() == Player.STARTED)
        {
            try
            {
                videoControl.setVisible(false);
                player.stop();
                this.repaint();
            } catch(MediaException me)
            {
                szMessage1="MediaException:";
                szMessage2=me.getMessage();
            }
        }
    }
   
    public void commandAction(Command c,Displayable d)
    {
        if(c==cmdExit)
        {
            midlet.cameraCanvasExit();
        }
        else if(c==cmdCapture)
        {
            doCapture();
        } else if (c == this.cmdFileCapture) {
            this.oCaptureFromFile = true;
            // don't restart player -- we just use the file instead of
            // the videoControl when we capture
        } else { // check source and resolution commands
            boolean oCommandFound = false;
            for (Enumeration cmds = this.htSourceCmds.keys();
                cmds.hasMoreElements() && !oCommandFound;) {
                Command cmd = (Command) cmds.nextElement();
                if (cmd == c) {
                    oCommandFound = true;
                    String szOldSource = this.szCurrentSource;
                    String szSource = (String) this.htSourceCmds.get(cmd);
                    discardPlayer();
                    if (!createPlayer(szSource)) {
                        Alert a = new Alert(szSource + " can't capture",
                                "Can't capture from " + szSource,
                                null,
                                AlertType.ERROR);
                        a.setTimeout(Alert.FOREVER);
                        this.htSourceCmds.remove(cmd);
                        this.removeCommand(cmd);
                        createPlayer(szOldSource);
                    }
                }
            }
            for (Enumeration cmds = this.htFormatCmds.keys();
                cmds.hasMoreElements() && !oCommandFound;) {
                Command cmd = (Command) cmds.nextElement();
                if (cmd == c) {
                    oCommandFound = true;
                    this.szCaptureFormat = (String) this.htFormatCmds.get(cmd);
                }
            }
            if (!oCommandFound) {
                for (Enumeration cmds = this.htResCmds.keys();
                    cmds.hasMoreElements() && !oCommandFound;) {
                    Command cmd = (Command) cmds.nextElement();
                    if (cmd == c) {
                        oCommandFound = true;
                        int[] rgnRes = (int[]) this.htResCmds.get(cmd);
                        this.nCurrentWidth = rgnRes[0];
                        this.nCurrentHeight = rgnRes[1];
                    }
                }
            }
            try {
               saveSettings();
            } catch (Exception ex) {
                Alert a = new Alert("Could not save settings: " + ex.getMessage());
                a.setTimeout(Alert.FOREVER);
                a.setType(AlertType.ERROR);
                Display.getDisplay(this.midlet).setCurrent(a);
           }
            // redisplay commands to show current selection
            setupCommands();
        }
    }
   
    public void keyPressed(int keyCode)
    {
        switch (getGameAction(keyCode)) {
            case FIRE:
                doCapture();
                break;
            default:
        }
    }
   
    /**
     * Note that this and the saveSettings procedure have to stay in sync
     */
    private void restoreSettings()
    {
        try {
            RecordStore rs = RecordStore.openRecordStore(this.szRsSettings,
                    true);
            try {
                RecordEnumeration re = rs.enumerateRecords(null, null, false);
                if (this.cc != null && re.hasNextElement()) {
                    byte[] bSource = re.nextRecord();
                    re.destroy();
                    if (bSource != null) {
                        ByteArrayInputStream bais = new ByteArrayInputStream(bSource);
                        DataInputStream dis = new DataInputStream(bais);
                        int nSource = dis.readInt();
                        int nCapture = dis.readInt();
                        this.nCurrentHeight = dis.readInt();
                        this.nCurrentWidth = dis.readInt();
                        dis = null;
                        bais = null;
                        int n=0;
                        // translate stored indices for source and format back into
                        // strings
                        for (Enumeration e = this.cc.getCaptureSources(); e.hasMoreElements(); n++) {
                            if (n == nSource) {
                                this.szCurrentSource = (String) e.nextElement();
                                break;
                            } else {
                                e.nextElement();
                            }
                        }
                        n = 0;
                        for (Enumeration e = this.cc.getCaptureFormats(); e.hasMoreElements(); n++) {
                            if (n == nCapture) {
                                Object vFormat = e.nextElement();
                                this.szCaptureFormat = vFormat.toString();
                                break;
                            } else {
                                e.nextElement();
                            }
                        }
                   }
                }
                rs.closeRecordStore();
            } catch (Exception ex) {
                /* the record store might not be created yet. We use the
                 * default settings, which have already been set.
                 */
                rs.closeRecordStore();
                return;
            }
        } catch (RecordStoreException rex)  {
            return;
        }
    }
   
    /**
     * Note that this and the restoreSettings procedure have to stay in sync
     */
    private void saveSettings()
    {
        try {
            RecordStore rs = RecordStore.openRecordStore(this.szRsSettings, true);
            // first clear all existing records
            for (RecordEnumeration e = rs.enumerateRecords(null, null, false);
                e.hasNextElement();) {
                rs.deleteRecord(e.nextRecordId());
            }
            // I tried storing the source as a string but couldn't read it back
            // in for some reason. So I store it as an index into the list
            // of sources, which shouldn't change
            int nSource = 0;
            for (Enumeration e = this.cc.getCaptureSources(); e.hasMoreElements(); nSource++) {
                String szSource = (String) e.nextElement();
                if (szSource == this.szCurrentSource) {
                    break;
                }
            }
            // Similarly, couldn't store capture format as a string,
            // so store it as an index instead
            int nCapture = 0;
            for (Enumeration e = this.cc.getCaptureFormats(); e.hasMoreElements(); nCapture++) {
                Object vFormat = e.nextElement();
                String szFormat = vFormat.toString();
                if (szFormat == this.szCaptureFormat) {
                    break;
                }
            }
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            DataOutputStream dos = new DataOutputStream(baos);
            dos.writeInt(nSource);
            dos.writeInt(nCapture);
            dos.writeInt(this.nCurrentHeight);
            dos.writeInt(this.nCurrentWidth);
            dos.flush();
            baos.flush();
            byte[] bRes = baos.toByteArray();
            dos = null;
            baos = null;
            rs.addRecord(bRes, 0, bRes.length);
            bRes = null;
            rs.closeRecordStore();
        } catch (Exception ex) {
            Alert a = new Alert("Could not save settings: " + ex.getMessage());
            a.setTimeout(Alert.FOREVER);
            a.setType(AlertType.ERROR);
            Display.getDisplay(this.midlet).setCurrent(a);
        }
    }
   
    private void setBcpFromIndex()
    {
        this.bcp = new BarcodeParam();       
    }
   
    /** set a particular record in an open record store to a particular
     * byte array.
     * @param rs the record store which will be updated.
     * @param nRecordId the record id to update. This will be created if it
     *        isn't present. Other records may also be created.
     * @param bData the byte array that the record is to be set to.
     * @returns true if the record was successfully set; false if not.
     *
     */
    private void setRecord(RecordStore rs, int nRecordId, byte[] bData)
        throws IllegalArgumentException,
            RecordStoreNotOpenException,
            RecordStoreException
    {
        if (nRecordId <= 0) {
            throw new IllegalArgumentException("nRecordId should be > 0, but" +
                    "is " + nRecordId);
        }
        try {
            /* try to read the record of concern. This will throw
             * InvalidRecordIDException if the record doesn't exist, and
             * other exceptions if the RecordStore can't be read.
             */
            rs.getRecord(nRecordId);
            /* the record is there; set it to the new value.
             */
            rs.setRecord(nRecordId, bData, 0, bData.length);
        } catch (InvalidRecordIDException iriex) {
            /* the record wasn't there. Attempt to write it. There doesn't
             * seem to be any way to ensure that a particular record id
             * is returned from the addRecord so we just keep adding it
             * until we get the right returned number. Note that this
             * might add extra unnecessary records.
             */
            int nReturnedId;
            do {
                 nReturnedId = rs.addRecord(bData, 0, bData.length);
            } while (nRecordId != nReturnedId);               
        }
    }
   
    private void takeSnapshot()
    {
        if(player!=null)
        {
            try
            {
                Image lcdImage;
                if (this.oCaptureFromFile) {
                    lcdImage = javax.microedition.lcdui.Image.createImage(
                         "/images/barcode.png"
                    );
                } else {
                    String szCapture = this.szCaptureFormat;
                    if (this.nCurrentWidth != 0) {
                        if (szCapture != null && szCapture != "") {
                            szCapture += "&";
                        }
                        szCapture += "width=" + this.nCurrentWidth +
                                "&height=" + this.nCurrentHeight;
                    }
                    byte [] image=videoControl.getSnapshot(szCapture);
                    midlet.cameraCanvasCaptured();
                    lcdImage = Image.createImage(image, 0, image.length);
                }
                this.player.stop();
                this.videoControl.setVisible(false);
                this.bcp.setImage(lcdImage);
                repaint();
                serviceRepaints();
                this.bcp.push();
                repaint();
                serviceRepaints();
            } catch (Exception e)
            {
                e.printStackTrace();
                Alert a = new Alert("Error while capturing image");
                a.setString(e.getMessage());
                a.setType(AlertType.ERROR);
                a.setTimeout(Alert.FOREVER);
                Display.getDisplay(this.midlet).setCurrent(a);
            }
        }
    }
}
TOP

Related Classes of CameraCanvas

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.