Saturday, June 16, 2012

Text To Speech in JSP page (or HTML pages)

In this post we will show how to add text to speech support to your web pages , simplified steps will be followed for that.

We will use eSpeak which is open source project: http://espeak.sourceforge.net/

Link: http://espeak.sourceforge.net/

1) Create Java Web Application : (or HTML page)
2) Create folder JS and place the following files:
- speakWorker.js
- speakGenerator.js
- speakClient.js

3) Edit speakClient.js and change the 3rd line in the file to point to your JS folder :

speakWorker = new Worker('js/speakWorker.js');

4) Create JSP pages (or HTML page) :

a) Add the following JS imports in the header:
 <script src="js/speakGenerator.js"></script>
  <script src="js/speakClient.js"></script>

b) Add this function in the header as well:
  <script>
    function textToSpeech(text){
       // you can change any of these voice characteristics
        speak(text, { amplitude: 100, wordgap: 1, pitch: 50, speed: 175 });
    }
  </script>

c) Add this div to your page body :
  <div id="audio"></div>

5) In your page use the function we have just created like this:
I have added small icon beside each filed to text to speech its content in human friendly way : Name is ..., City is ...., Country is ......


Name : <input type="text" name="name" id="name" size=50 value="Osama Oransa"><img src="images/tts.png" onclick="textToSpeech('Name is '+document.forms[0].name.value); return false" style="cursor:pointer;vertical-align: middle">

The nice thing in this open source project that it support a lot of languages and different voice with ability to tune each voice using many features and if you didn't find your language you can generate the speech generator for it.



Saturday, June 2, 2012

Accessing WebCam within JSP

I keep getting questions about how we can use web camera inside jsp files , in this post i will show you how to use the web cam from within jsp file.


We will use jQuery wrapper of flash plugin for that..
My reference in that is http://www.xarg.org
There is a guide you can follow instead of my post: http://www.xarg.org/project/jquery-webcam-plugin/
Here is the simplified steps:
1.Create resources folder with the following content from the mentioned web site:
jquery.js
jquery-1.js
either : jscam.swf or jscam_canvas_only.swf

2.Create JSP file and put the following code:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<title>Test Web Cam</title>
<style type="text/css">
#webcam, #canvas {
    width: 320px;
    border:20px solid #333;
    background:#eee;
    -webkit-border-radius: 20px;
    -moz-border-radius: 20px;
    border-radius: 20px;
}

#webcam {
    position:relative;
    margin-top:50px;
    margin-bottom:50px;
}

#webcam > span {
    z-index:2;
    position:absolute;
    color:#eee;
    font-size:10px;
    bottom: -16px;
    left:152px;
}

#canvas {    border:20px solid #ccc;
    background:#eee;
}
</style><script type="text/javascript" src="resources/jquery-1.js"></script>
<script type="text/javascript" src="resources/jquery.js"></script>
</head><body>
<p id="status" style="height:22px; color:#c00;font-weight:bold;"></p>
<div id="webcam">
    <span>Your WebCam should be here!</span>
</div>

<p style="width:360px;text-align:center; ">
    <a href="javascript:webcam.capture(3);changeFilter();void(0);">Take a picture after 3 seconds</a> |
    <a href="javascript:webcam.capture();changeFilter();void(0);">Take a picture instantly</a></p>

<script type="text/javascript">
var pos = 0;
var ctx = null;
var cam = null;
var image = null;

var filter_on = false;
var filter_id = 0;

$(function() {

        var pos = 0, ctx = null, saveCB, image = [];
        var canvas = document.createElement("canvas");
        canvas.setAttribute('width', 320);
        canvas.setAttribute('height', 240); 
        if (canvas.toDataURL) {
                ctx = canvas.getContext("2d");             
                image = ctx.getImageData(0, 0, 320, 240);
                saveCB = function(data) {                       
                        var col = data.split(";");
                        var img = image;
                        for(var i = 0; i < 320; i++) {
                                var tmp = parseInt(col[i]);
                                img.data[pos + 0] = (tmp >> 16) & 0xff;
                                img.data[pos + 1] = (tmp >> 8) & 0xff;
                                img.data[pos + 2] = tmp & 0xff;
                                img.data[pos + 3] = 0xff;
                                pos+= 4;
                        }
                        if (pos >= 4 * 320 * 240) {
                                ctx.putImageData(img, 0, 0);
                                $.post("/TestWebCam/UploadServlet", {type: "data", image: canvas.toDataURL("image/png")});
                                pos = 0;
                        }
                };
        } else {
                saveCB = function(data) {
                        image.push(data);                       
                        pos+= 4 * 320;                       
                        if (pos >= 4 * 320 * 240) {
                                $.post("/TestWebCam/UploadServlet", {type: "pixel", image: image.join('|')});
                                pos = 0;
                        }
                };
        }
        $("#webcam").webcam({
                width: 320,
                height: 240,
                mode: "callback",
                swffile: "resources/jscam_canvas_only.swf",
                onSave: saveCB,
                onCapture: function () {
                        webcam.save();
                },
                debug: function (type, string) {
                        console.log(type + ": " + string);
                }
        });

});
</script>
</body>
</html>

3.Create a Servlet named: UploadServlet with the following code:
package osa.ora;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * UploadServlet
 * Author Osama Oransa
 */
public class UploadServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {

    private static final long serialVersionUID = 529869125345702992L;
    public UploadServlet() {
        super();
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("SAVING>>>>>>>>>>>>>>>>>>>>");
        String type = request.getParameter("type");
        String image = request.getParameter("image");
        System.out.println("SAVING>>>>>>>>>>>>>>>>>>>>Type=" + type);
        System.out.println("SAVING>>>>>>>>>>>>>>>>>>>>data=" + image);
        if (type != null) {
            return;
        }

        String byteStr = image.split(",")[1];
        byte[] bytes = Base64.decode(byteStr);
//Now you have the image bytes ready to save in File/DB/....etc..

//Or use the pixel data for old browser and convert the pixel comma separated values into int[] then call methods similar to the following one:

public static Image getImageFromArray(int[] pixels, int width, int height) {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
WritableRaster raster = (WritableRaster) image.getData();
raster.setPixels(0,0,width,height,pixels);
return image;
}
    }
}
           
This will show you the encoded png data ...you can decode it or keep it encoded , save it to DB ...etc...
If you are doing a video chat application you need to capture the images in periodic manner and upload it , you may include the source & destination ids to distribute the chat images correctly..

This code only works with integrated camera in the laptop not with USB external camera.

These are simplified steps so you can copy and paste and let it work easily.
But in case you need more details , you may refer to the original URL for more clarification on how to control it more..

NOTE:
Another alternative is to use the following project:  https://github.com/jhuckaby/webcamjs

Tuesday, April 3, 2012

WebCam Video Capture in Java

I got a lot of requests asking for how to do video capturing in Java as comments on my previous post :

Capture photo / image from Web Cam / USB Camera using Java

In this quick post i will highlight how i did this functionality in Interactive4j

We will use the library LTI-CIVIL which is part of FMJ (Freedom for Media in Java).



PreRequisities:

-Download the library and place it correctly in your classpath and load the native library using JVM parameter exactly as the previous mentioned post above.
Download from here:  https://sourceforge.net/projects/lti-civil/

Steps:

1) Create Interface For Captured Images:
public interface CaptureListener {
/**
* Method called once capturing of the web cam jpg file is done.
* @param filename
*/
public void setCaptureFile(File filename);
}

2) Create A Wrapper Class:
This class wrap the camera functionality..

/**
* JHCaptureUtil class
* Used for capture images through the usb (camera, scanner,...etc)
* Osama Oransa
* Interactive4J
* (c) 2011
**/
package osa.ora.utils;

import com.lti.civil.*;
import com.lti.civil.awt.AWTImageConverter;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import osa.ora.utils.faces.CaptureListener;

/**
*
* @author mabdelmo
*/
public class JHCaptureUtil implements CaptureObserver {

CaptureStream captureStream = null;
CaptureListener captureListener;
String fileName;
/**
* Constructor accept the listener and file to save image into.
* @param captureListener
* @param fileName
*/
public JHCaptureUtil(CaptureListener captureListener, String fileName) {
this.fileName = fileName;
this.captureListener = captureListener;
init();
}
private void init(){
System.out.println("Init....");
/*
* initialize capturing to use the current devices...
*/
CaptureSystemFactory factory = DefaultCaptureSystemFactorySingleton.instance();
CaptureSystem system;
try {
system = factory.createCaptureSystem();
system.init();
List list = system.getCaptureDeviceInfoList();
int i = 0;
if (i < list.size()) {
CaptureDeviceInfo info = (CaptureDeviceInfo) list.get(i);
System.out.println((new StringBuilder()).append("Device ID ").append(i).append(": ").append(info.getDeviceID()).toString());
System.out.println((new StringBuilder()).append("Description ").append(i).append(": ").append(info.getDescription()).toString());
captureStream = system.openCaptureDeviceStream(info.getDeviceID());
captureStream.setObserver(this);
}
} catch (CaptureException ex) {
Logger.getLogger(JHCaptureUtil.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* Start capture method
*/
public void start() {
//System.out.println("Start....");
try {
captureStream.start();
} catch (CaptureException ex) {
Logger.getLogger(JHCaptureUtil.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* Stop capture method
*/
public void stop() {
//System.out.println("Stop....");
try {
captureStream.stop();
} catch (CaptureException ex) {
Logger.getLogger(JHCaptureUtil.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
*
* @param stream
* @param image
*/
public void onNewImage(CaptureStream stream, Image image) {
//System.out.println("get new image....");
byte bytes[] = null;
try {
if (image == null) {
return;
}
try {
ByteArrayOutputStream os = new ByteArrayOutputStream();
JPEGImageEncoder jpeg = JPEGCodec.createJPEGEncoder(os);
jpeg.encode(AWTImageConverter.toBufferedImage(image));
os.close();
bytes = os.toByteArray();
if (bytes == null) {
return;
}
} catch (Throwable t) {
t.printStackTrace();
bytes = null;
return;
}
ByteArrayInputStream is = new ByteArrayInputStream(bytes);
File currentImageFile = new File(fileName);
FileOutputStream fos = new FileOutputStream(currentImageFile);
fos.write(bytes);
fos.close();
captureListener.setCaptureFile(currentImageFile);
} catch (IOException ex) {
Logger.getLogger(JHCaptureUtil.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
*
* @param stream
* @param ce
*/
public void onError(CaptureStream stream, CaptureException ce) {
System.out.println("Error : "+ce.getStackTrace());
}
}




3) Write the code that control your wrapper class:
Here is sample usage code that display a dialog with one image or a video .. You need to add 2 buttons 1 for image capture and 1 for video capture and add the action listeners on these buttons..


int mode=0;
static int ONE_PHOTO=0;
static int MULTI_PHOTO=1;
JHCaptureUtil webCam;

//this method to capture one image

private void captureImageButtonActionPerformed(java.awt.event.ActionEvent evt) {
mode=ONE_PHOTO;
if(webCam==null) webCam=new JHCaptureUtil(this, "/myWebCamPic.jpg");
webCam.start();
}

private void captureVideoActionPerformed(java.awt.event.ActionEvent evt) {
mode=MULTI_PHOTO;
if(webCam==null) webCam=new JHCaptureUtil(this, "/myWebCamPic.jpg");
webCam.start();
}


You class must implements : CaptureListener , this interface has 1 method inside it :
public void setCaptureFile(File filename);

And this is the interface method implementation that display the image without saving the photos (you can change the implementation)


JDialog monitorjDialog;
JLabel monitorLabel;
JScrollPane monitorScroll;

public void setCaptureFile(File filename) {
if(mode==ONE_PHOTO){
System.out.println("No more photos");
JDialog jDialog=new JDialog(this.getFrame(),true);
Image image=ImageUtils.loadJPG(filename.getAbsolutePath());
jDialog.setBounds(this.getFrame().getX()+50,this.getFrame().getY()+50,500, 500);
JLabel label=new JLabel(new ImageIcon(image));
JScrollPane jscroll=new JScrollPane(label);
jDialog.add(jscroll);
jDialog.setVisible(true);
jDialog.validate();
webCam.stop();
}else{
System.out.println("display new photo");
if(monitorjDialog==null) {
monitorjDialog=new JDialog(this.getFrame(),false);
monitorjDialog.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
webCam.stop();
}
});
Image image=ImageUtils.loadJPG(filename.getAbsolutePath());
monitorjDialog.setBounds(this.getFrame().getX()+50,this.getFrame().getY()+50,image.getWidth(null), image.getHeight(null));
monitorLabel=new JLabel(new ImageIcon(image));
monitorScroll=new JScrollPane(monitorLabel);
monitorjDialog.add(monitorScroll);
monitorjDialog.setVisible(true);
monitorjDialog.validate();
}else{
Image image=ImageUtils.loadJPG(filename.getAbsolutePath());
monitorjDialog.remove(monitorScroll);
monitorScroll.remove(monitorLabel);
monitorLabel=new JLabel(new ImageIcon(image));
monitorScroll=new JScrollPane(monitorLabel);
monitorjDialog.add(monitorScroll);
monitorjDialog.validate();
}
}
}

4) Utility method used: ImageUtils.loadJPG ..
public static Image loadJPG(String filename) {
FileInputStream in = null;
try {
in = new FileInputStream(filename);
} catch (java.io.FileNotFoundException io) {
System.out.println("File Not Found");
}
JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(in);
BufferedImage bi = null;
try {
bi = decoder.decodeAsBufferedImage();
in.close();
} catch (java.io.IOException io) {
System.out.println("IOException");
}
return bi;
}

That's all needed !

Tuesday, March 20, 2012

Developing HTML 5 Application for Android

Developing HTML 5 Application for Android is an easy process, we will list the few steps needed to achieve this..

1) Create Your Normal Android Project:
-Define the activity and package name in new project wizard.
For example: Activity is TestActivity and package name is osa.ora.test

2) In the main.xml change it to looks like the following:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<WebView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/webView"
/>
</LinearLayout>

This define a web view with the id: webView.

3) In our activity : the following code is needed according to your needs:

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
WebView webView=(WebView)findViewById(R.id.webView);
webView.setWebChromeClient(new WebChromeClient());
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setDatabaseEnabled(true);
webView.getSettings().setDatabasePath("/data/data/osa.ora.test/databases/");
webView.getSettings().setDomStorageEnabled(true);
webView.loadUrl("file:///android_asset/www/index.html");

}

4) In asset folder create a folder with the name "www":

Place all the HTML, JS and CSS (and images) files under it, you must have the index.html that we refereed in our code (or another file name but match what in our java code).

5) Run the emulator , test it then sign it and upload :)

This is example application running in the emulator:


A lot of video tutorials exist showing the same way to develop such application.
Click here to watch.

Thursday, March 15, 2012

Using AES encryption in Java Script

Using encryption in Java Script could potentially help establishing secure data communication between the client and the server.

In this post we will wrap existing APIs to do that: JSAES

JSAES:

jsaes is a compact JavaScript implementation of the AES block cipher. Key lengths of 128, 192 and 256 bits are supported.

jsaes is free software, written in 2006 by B. Poettering. The code is licensed under the GNU GPL. The well-functioning of the encryption/decryption routines has been verified for different key lengths with the test vectors given in FIPS-197, Appendix C.

URL:
http://point-at-infinity.org/jsaes/


Download URL:
http://point-at-infinity.org/jsaes/jsaes.js

Our Wrapper code: jsaes_wrapper.js

function init(myKey){
AES_Init();
var key = string2Bin(myKey);
AES_ExpandKey(key);
return key;
}

function encrypt ( inputStr,key ) {
var block = string2Bin(inputStr);
AES_Encrypt(block, key);
var data=bin2String(block);
return data;
}
function decrypt ( inputStr,key ) {
block = string2Bin(inputStr);
AES_Decrypt(block, key);
var data=bin2String(block);
return data;
}
function encryptLongString ( myString,key ) {
if(myString.length>16){
var data='';
for(var i=0;i<myString.length;i=i+16){
data+=encrypt(myString.substr(i,16),key);
}
return data;
}else{
return encrypt(myString,key);
}
}
function decryptLongString ( myString,key ) {
if(myString.length>16){
var data='';
for(var i=0;i<myString.length;i=i+16){
data+=decrypt(myString.substr(i,16),key);
}
return data;
}else{
return decrypt(myString,key);
}
}
function finish(){
AES_Done();
}
function bin2String(array) {
var result = "";
for (var i = 0; i < array.length; i++) {
result += String.fromCharCode(parseInt(array[i], 2));
}
return result;
}
function string2Bin(str) {
var result = [];
for (var i = 0; i < str.length; i++) {
result.push(str.charCodeAt(i));
}
return result;
}

function bin2String(array) {
return String.fromCharCode.apply(String, array);
}

Usage:
This wrapper is adjusted to use key with 16 bytes length.

<html>
<head>
<meta charset="utf-8">
<title>Encryption Example</title>
<script src="jsaes.js"></script>
<script src="jsaes_wrapper.js"></script>
<script>
usedKey="World678World678";
myStr="Osama Oransa2012Osama Oransa2011RashaOsama Oransa2012Osama Oransa2011RashaOsama Oransa2012Osama Oransa2011RashaOsama Oransa2012Osama Oransa2011Rasha";
alert(myStr);
alert(usedKey);
var key=init(usedKey);
alert(key);
encrypted=encryptLongString(myStr,key);
alert('after encrypt='+encrypted);
decrypted=decryptLongString(encrypted,key);
alert('after decrypt='+decrypted);
finish();
</script>
</head>
<body>
</body>
</html>

Sunday, March 11, 2012

HTML 5 Game Development - JDC 2012


Yesterday I gave a session about HTML 5 game development.. It was a very nice experience to give a session out of the Java topics in such conference :)

Abstract:

HTML 5 is the 5th major revision of the core language of the World Wide Web: the Hypertext Markup Language (HTML). In this version, new features are introduced to help Web application authors, new elements are introduced based on research into prevailing authoring practices, and special attention has been given to defining clear conformance criteria for user agents in an effort to improve interoperability.
In our session we will cover quick orientation about HTML 5 new features, then we will dig on how to create games using html5 new features, we will cover all basic components of the gaming including: Animations, Interactions, Controls, Effects, Boundaries, Entry Points, Physics and AI rules.
A step by step game development will be covered in this session to guide the attendees about how to create the game and how to package this into a deployable application for different smart phone devices.
Some advanced topics will be covered like using Box2d Physics engine plus AI engine example.



Materials: