How to Create Java Barcode Reader on Linux with JNI

A few days ago, Dynamsoft Labs released Barcode Reader SDK for Linux. The SDK package provides two shared libraries for C/C++ programming. If you want to write code with high-level programming languages such as Java, you need to create a wrapper. In this post, I will illustrate how to build a simple Java barcode reader on Ubuntu with JNI (Java Native Interface) from scratch.

Read more

How to Benchmark Barcode SDK Performance – ZXing vs ZBar

I saw many posts arguing the performance winner between open-source barcode SDKs – ZXing and ZBar. As an engineer, who is developing commercial barcode reader software for Dynamsoft, I am curious about which open source project is better, ZXing or ZBar? Considering ZXing is implemented in Java, whereas ZBar is implemented in C/C++. To fairly compare their performance, I decided to use JNI to wrap ZBar C/C++ source code and benchmark them in a Java program.

Read more

How to Make Java Barcode Reader with Dynamsoft Barcode SDK

Last week, Dynamsoft released Barcode Reader (DBR) SDK v2.0, which is available for Windows and Mac. The Windows installer contains Barcode libraries for ActiveX, C/C++, and .NET. If you are a Java developer, you have to use JNI to link native C/C++ libraries. In this tutorial, I’ll demonstrate how to invoke the native methods of Dynamsoft Barcode SDK via JNI to create a Java Barcode Reader.

Read more

Uploading and Storing Images in MongoDB via Web Browser

MongoDB is known as a NoSQL database, which uses a JSON-like document structure by key-value pairs. Comparing to the relational database like MySQL, MongoDB is easier and more scalable. Especially when processing big and complex data, MongoDB can perform faster and better. In this tutorial, let’s take a glimpse of how to upload and save scanned images to MongoDB.

Read more

Wrapping C++ OCR Library in Java

Dynamsoft OCR SDK is totally implemented in C++, which means it is easy to be wrapped in high-level programming languages, such as C#, Java, Python and so on. As a proprietary development SDK, so far, only .NET OCR library is available for commercial use. Because some of developers and users are hoping that Dynamsoft could provide a Java OCR library, I wrapped the C++ OCR library for test. Anyone can feel free to use the sample, and I’d like to receive feedbacks from you.

Read more

Getting Started with JNI on Android, Windows and Mac

Java Native Interface (JNI) is the glue between Java and native code such as C, C++, and assembly. With JNI, Java applications are capable of supporting platform-specific features. JNI enables developers to call low-level APIs (e.g. SQL, OpenGL etc.) to make Java application more powerful with higher performance. For example, we can download a JDBC driver, and unzip the jar package to take an insight. The driver is not written in pure Java. It also contains native libraries for Linux, Mac, and Windows.

jdbc

Since JNI is so useful, I’d like to share how to get started with JNI on Android, Windows, and Mac.

JNI on Android

Download NDK and configure the location in Eclipse:

android JNI

Create a new project named hellojni. To automatically generate the native C/C++ code and configuration file, you just need to right-click on your project and select Add Native Support:

add_native_support

After that, a JNI project will be automatically generated. To build the shared library, you just need to implement JNI methods in C/C++, and add configurations in Android.mk.

jni_folder

When you save all changes, the shared library libhellojni.so will be automatically generated. You can also build the library by typing in ndk-build.ndk_build

JNI on Windows

Create a Win32 project named hellojni in Visual Studio:

Read more

How to Implement a Java WebSocket Server for Image Transmission with Jetty

In the previous articles, I shared how to implement a .Net WebSocket server with SuperWebSocket. Today, I’d like to continue the series WebSocket: How-to, talking about how to implement a WebSocket server in Java.

What is Jetty?

“Jetty provides a Web server andjavax.servlet container, plus support forSPDY, WebSocket, OSGi, JMX, JNDI, JAASand many other integrations.” from http://www.eclipse.org/jetty/

Quickly Setup a Java WebSocket Server

Create a class WSHandler which extends the class WebSocketHandler:

import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.server.WebSocketHandler;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;

@WebSocket
public class WSHandler extends WebSocketHandler {

    @OnWebSocketClose
    public void onClose(int statusCode, String reason) {
    }

    @OnWebSocketError
    public void onError(Throwable t) {
    }

    @OnWebSocketConnect
    public void onConnect(Session session) {
    }

    @OnWebSocketMessage
    public void onMessage(String message) {
    }

	@Override
	public void configure(WebSocketServletFactory factory) {
		// TODO Auto-generated method stub
		factory.register(WSHandler.class);
	}
}

Start the server with a port and a handler:

    public static void main(String[] args) throws Exception {
        Server server = new Server(2014);
        server.setHandler(new WSHandler());
        server.setStopTimeout(0);
        server.start();
        server.join();
    }

Done.

JavaScript Client for WebSocket Connection

We can create a simple web client for testing.

Index.htm:

<!DOCTYPE html>
<html>
    <body>
        <script src="websocket.js"></script>
    </body>
</html>

Websocket.js:

var ws = new WebSocket("ws://127.0.0.1:2014/");

ws.onopen = function() {
    alert("Opened");
    ws.send("I'm client");
};

ws.onmessage = function (evt) { 
};

ws.onclose = function() {
    alert("Closed");
};

ws.onerror = function(err) {
    alert("Error: " + err);
};

Run the app and check the message.

Image Transmission Between WebSocket Server & Web Clients

What I’m going to do: Read more

Java TWAIN with Dynamic .NET TWAIN and jni4net

Dynamic .NET TWAIN is one of the excellent TWAIN-compliant SDKs for document scanning and image capture. In this tutorial, I would like to share how to create a bridge to convert .NET TWAIN C# methods to Java methods in order to help Java developers easily implement TWAIN scanner software.

Source Code

JavaTwain

How to Make Demo Work

  1. Download Dynamic .NET TWAIN
  2. Download and learn jni4net to understand how JVM and CLR work together
  3. Correctly configure the paths of JAVA_HOME and  C:\Windows\Microsoft.NET\Framework\v3.5\csc.exe in the system environment
  4. Unzip the sample code, and launch JavaTwain.sln to build JavaTwain.dll
  5. Copy bin and lib folders from jni4net package to your project directory
  6. Run generateProxies.cmd
  7. Run run.cmd

Java TWAIN

How to Make a Java TWAIN Scanner App based on .NET TWAIN with jni4net

To invoke the Dynamic .NET TWAIN instance, we need to create a bridge in C#.

  1. Add DynamicDotNetTWAIN.dll as a reference.TWAIN reference
  2. Create a class named DotNetScanner, and initialize the .NET TWAIN component in the constructor.
            public DotNetScanner()
            {
                // initialize TWAIN Component
                try
                {
                    dynamicDotNetTwain = new Dynamsoft.DotNet.TWAIN.DynamicDotNetTwain();
                    dynamicDotNetTwain.OnPostAllTransfers += new Dynamsoft.DotNet.TWAIN.Delegate.OnPostAllTransfersHandler(this.dynamicDotNetTwain_OnPostAllTransfers);
                    dynamicDotNetTwain.MaxImagesInBuffer = 64;
                    dynamicDotNetTwain.IfAppendImage = true;
                    dynamicDotNetTwain.IfThrowException = true;
                    dynamicDotNetTwain.IfShowUI = false;
                    dynamicDotNetTwain.IfThrowException = true;
                    dynamicDotNetTwain.ScanInNewProcess = true;
                }
                catch 
                {
                    MessageBox.Show(dynamicDotNetTwain.ErrorString);
                }
    
            }
  3. Create interfaces for data transmission between JVM and CLR.
        public interface IJavaProxy
        {
            bool AcquireImage(int iIndex);
            String[] GetSources();
            bool RegisterListener(INativeProxy proxy);
            void CloseSource();
        }
    
        public interface INativeProxy
        {
            bool Notify(String message, String value);
        }
  4. Capture an image and notify the Java layer to load it.
            public bool AcquireImage(int iIndex)
            {
                try
                {
                    //dynamicDotNetTwain.CloseSource();
                    bool success = dynamicDotNetTwain.SelectSourceByIndex(Convert.ToInt16(iIndex));
                    dynamicDotNetTwain.OpenSource();
                    dynamicDotNetTwain.AcquireImage();
                }
                catch (Dynamsoft.DotNet.TWAIN.TwainException exp)
                {
                    String errorstr = "";
                    errorstr += "Error " + exp.Code + "\r\n" + "Description: " + exp.Message + "\r\nPosition: " + exp.TargetSite + "\r\nHelp: " + exp.HelpLink + "\r\n";
                    MessageBox.Show(errorstr);
                }
                catch (Exception exp)
                {
                    String errorstr = "";
                    errorstr += "ErrorMessage: " + exp.Message + "\r\n";
                    MessageBox.Show(errorstr);
                }
    
                return true;
            }
    
            private void dynamicDotNetTwain_OnPostAllTransfers()
            {
                //MessageBox.Show("dynamicDotNetTwain_OnPostAllTransfers");
    
                if (dynamicDotNetTwain.MaxImagesInBuffer < 1)
                {
                    return;
                }
    
                Image img = dynamicDotNetTwain.GetImage(0);
                img = resizeImage(img, new Size(480, 640));
                img.Save("twain.png");
    
                if (listener != null)
                {
                    listener.Notify("data ready", "twain.png");
                }
            }

To make the C# interfaces work in Java:

  1. Load the JavaTwain.j4n.dll which is generated by proxygen.exe.
            private void initTWAIN() {
    		try {
    			Bridge.init();
    			Bridge.LoadAndRegisterAssemblyFrom(new java.io.File("JavaTwain.j4n.dll"));
    		}
    		catch (Exception e) {
                e.printStackTrace();
            }
    
    		mScanner = new DotNetScanner();
    		mScanner.RegisterListener(this);
    	}
  2. Create Swing UI to interact with the C# bridge.
       public ScanDocuments() {
            super(new BorderLayout());
    		initTWAIN();
    
            //Create a file chooser
            mFileChooser = new JFileChooser();
            FileNameExtensionFilter filter = new FileNameExtensionFilter(
                    ".png", "png");
            mFileChooser.setFileFilter(filter);
            mLoad = new JButton("Load");
            mLoad.addActionListener(this);
    
            mScan = new JButton("Scan");
            mScan.addActionListener(this);
    
    		// get sources
    		mSources = mScanner.GetSources();
    
    		if (mSources != null) {
    			mSourceList = new JComboBox(mSources);
    		}
    		else {
    			mSourceList = new JComboBox(new String[]{"N/A"});
    		}
            mSourceList.setSelectedIndex(0);
    
            // button panel
            JPanel buttonPanel = new JPanel(); 
    		buttonPanel.add(mSourceList);
    		buttonPanel.add(mScan);
    		buttonPanel.add(mLoad);
            add(buttonPanel, BorderLayout.PAGE_START);
    
            // image panel
    		JPanel imageViewer = new JPanel();
    		mImage = new JLabel();
    		mImage.setSize(480, 640);
    		imageViewer.add(mImage);
    		add(imageViewer, BorderLayout.CENTER);
        }

Try it yourself and have fun with Dynamic .NET TWAIN in Java.

How to Check Alexa Rank in Java

Since we have known how to check PageRank in Java, let’s strengthen our tool by adding the functionality of checking Alexa rank today.

To get the Alexa rank, you can use following code or read the excellent tutorial.

import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class AlexaRank {

	public static int getAlexaRank(String domain) {

		int result = 0;

		String url = "http://data.alexa.com/data?cli=10&url=" + domain;

		try {

			URLConnection conn = new URL(url).openConnection();
			InputStream is = conn.getInputStream();

			DocumentBuilder dBuilder = DocumentBuilderFactory.newInstance()
					.newDocumentBuilder();
			Document doc = dBuilder.parse(is);

			Element element = doc.getDocumentElement();

			NodeList nodeList = element.getElementsByTagName("POPULARITY");
			if (nodeList.getLength() > 0) {
				Element elementAttribute = (Element) nodeList.item(0);
				String ranking = elementAttribute.getAttribute("TEXT");
				if(!"".equals(ranking)){
					result = Integer.valueOf(ranking);
				}
			}

		} catch (Exception e) {
			System.out.println(e.getMessage());
		}

		return result;
	}
}

Now, let’s update our Java code to write Alexa rank to Excel files.

public void getPageRankAndAlexaRank() {
		// TODO Auto-generated method stub		
		try {
			InputStream excelFile = new FileInputStream(mFileName);
			XSSFWorkbook wb = new XSSFWorkbook(excelFile);
			XSSFSheet sheet = wb.getSheetAt(0);
			XSSFRow row;
			XSSFCell cellPR, cellAR;

			Iterator<Row> rows = sheet.rowIterator();

			int col = 0, colPR = 1, colAR = 2;
			int pageRank = 0, alexaRank = 0;
			String url = null;
			String log = null;

			while (rows.hasNext()) {
				row = (XSSFRow) rows.next();
				url = row.getCell(col).getStringCellValue();
				if (url.matches(Utils.REGEX)) { // check whether URL is valid
					System.out.println(url);
					pageRank = PageRank.get(url); // check page rank
					alexaRank = AlexaRank.getAlexaRank(url); // get alexa rank

					// write PageRank to excel
					cellPR = row.createCell(colPR);
					cellPR.setCellValue(pageRank);

					cellAR = row.createCell(colAR);
					cellAR.setCellValue(alexaRank);

					log = "PR = " + pageRank + ", AR = " + alexaRank;
					if (mEventListener != null) {
						mEventListener.log(log);
					}
					System.out.println(log);
				}
				else {
					System.out.println("URL not valid");
				}

				System.out.println("--------------------------");
			}

			FileOutputStream out = new FileOutputStream(mFileName);
	        wb.write(out);
	        out.flush();
	        out.close();
		}
		catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

Download the updated source package here. Please feel free to contact me at {desmond at dynamsoft dot com} if you have any question.