Java ME (J2ME), simulating mobile phone camera using PC Webcam

Membuat aplikasi yang terkait dengan manipulasi kamera handphone dengan Java ME (mobile edition), pada dasarnya tidaklah terlalu susah; karena anda dapat menemukan contohnya dengan sangat mudah dengan memanfaatkan fasilitas search engine. akan tetapi, menguji program tersebut pada emulator tidaklah sama; karena emulator, tidak dilengkapi kamera (ya iyalah :) ). 

Membuat aplikasi, terus deploy ke kamera dan uji (terus berulang), mungkin adalah salah satu cara paling gampang. akan tetapi ini tidak efisien, dalam prosesnya. Maka cara yang paling gampang adalah memanfaatkan usb webcam sebagai “kamera handphone”. Permasalahannya, emulator juga tidak punya fasilitas untuk mendeteksi webcam PC. terus bagaimana dong?

Solusi yang saya buat cukup strightforward, yaitu dengan menjadikan usb webcam camera layaknya IP Camera. oleh karena itu, kita membutuhkan sebuah server camera, dalam hal ini pilihan paling gampang adalah dengan memanfaatkan WebcamXP .  dengan webcamxp, hasil capture dari usb webcam dapat di broadcast pada local server computer (localhost) pada port 8080, pada versi free-nya, dan sepertinya bisa kita bind pada alamat IP tertentu untuk versi komersial. (saya pakai yang free).

idenya sederhana,  hasil broadcast dari webcam server tersebut (berupa frame gambar dalam format jpeg) kita tangkap, dan kita tampilkan di emulator handphone. agar emulator dapat mensimulasikan tampilan webcam secara kontinyu dan realtime, maka setiap saat kita harus mengupdate gambar tersebut.

mari kita lihat kode program ini:
0. pastikan anda telah menginstal WebcamXp, dan webcam dapat berjalan dengan baik, dan dapat hasil capturnya dapat di broadcast di http://localhost:8080/

1. Kita buat sebuah kelas, untuk menangkap gambar dari server

class Process implements Runnable{
  private HelloMIDlet MIDlet;

  public Process(HelloMIDlet MIDlet){
    this.MIDlet = MIDlet;
    System.out.println("Thread Process...");
  }

  public void run(){
    try{
      while(true)
        transmit();
    }catch(Exception error){
      System.err.println(error.toString());
    }
  }

  public void start(){
    Thread thread = new Thread(this);
    try{
      thread.start();
      System.out.println("Thread Start...");
    }catch(Exception error){}
  }

  private void transmit() throws IOException{
      Form frmPngView = this.MIDlet.getFrmPngView();
      try
      {

        Image im;
        if ((im = getImage("http://localhost:8080/cam_1.jpg")) != null)
        {
          ImageItem ii = new ImageItem(null, im, ImageItem.LAYOUT_DEFAULT, null);

          // If there is already an image, set (replace) it
          if (frmPngView.size() != 0)
            frmPngView.set(0, ii);
          else  // Append the image to the empty form
            frmPngView.append(ii);
        }
        else
          frmPngView.append("Unsuccessful download.");

        // Display the form with the image
        Display display = this.MIDlet.getDisplay();
        display.setCurrent(frmPngView);
      }
      catch (Exception e)
      {
        System.err.println("Msg: " + e.toString());
      }
  }
  private Image getImage(String url) throws IOException
  {
    ContentConnection connection = (ContentConnection) Connector.open(url);

    // * There is a bug in MIDP 1.0.3 in which read() sometimes returns
    //   an invalid length. To work around this, I have changed the
    //   stream to DataInputStream and called readFully() instead of read()
//    InputStream iStrm = connection.openInputStream();
    DataInputStream iStrm = connection.openDataInputStream();

    ByteArrayOutputStream bStrm = null;
    Image im = null;

    try
    {
      // ContentConnection includes a length method
      byte imageData[];
      int length = (int) connection.getLength();
      if (length != -1)
      {
        imageData = new byte[length];

        // Read the png into an array
        // iStrm.read(imageData);
        iStrm.readFully(imageData);
      }
      else  // Length not available...
      {
        bStrm = new ByteArrayOutputStream();

        int ch;
        while ((ch = iStrm.read()) != -1)
          bStrm.write(ch);

        imageData = bStrm.toByteArray();
        bStrm.close();
      }

      // Create the image from the byte array
      im = Image.createImage(imageData, 0, imageData.length);
    }
    finally
    {
      // Clean up
      if (iStrm != null)
        iStrm.close();
      if (connection != null)
        connection.close();
      if (bStrm != null)
        bStrm.close();
    }
    return (im == null ? null : im);
  }

}

untuk menangkap data dari server harus dipisahkan dalam thread tersendiri untuk menghindari deadlock pada emulator. pada dasarnya dengan cara yang sama kita bisa membuat sebuah survailance camera, dan memanfaatkan handphone kita sebagai pemantaunya :)

2. Buat midlet untuk menampilkan gambar tersebut (PR bagi anda, simple saja, isinya buat thread & sebuah form untuk menampilkan gambar)

3. hasilnya kurang lebih seperti ini:

nah, gampang kan, banyak manfaat yang bisa diperoleh dengan aplikasi semacam ini, dan salah satunya sedang saya kerjakan.

selamat berkarya :)

44 thoughts on “Java ME (J2ME), simulating mobile phone camera using PC Webcam

Tinggalkan Balasan

Isikan data di bawah atau klik salah satu ikon untuk log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s