summaryrefslogtreecommitdiffstats
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/Makefile.am59
-rw-r--r--java/net/sourceforge/zbar/Config.java56
-rw-r--r--java/net/sourceforge/zbar/Image.java163
-rw-r--r--java/net/sourceforge/zbar/ImageScanner.java98
-rw-r--r--java/net/sourceforge/zbar/Modifier.java42
-rw-r--r--java/net/sourceforge/zbar/Orientation.java42
-rw-r--r--java/net/sourceforge/zbar/Symbol.java199
-rw-r--r--java/net/sourceforge/zbar/SymbolIterator.java70
-rw-r--r--java/net/sourceforge/zbar/SymbolSet.java82
-rw-r--r--java/test/TestImage.java175
-rw-r--r--java/test/TestImageScanner.java53
-rw-r--r--java/test/TestScanImage.java183
-rw-r--r--java/zbarjni.c618
13 files changed, 1840 insertions, 0 deletions
diff --git a/java/Makefile.am b/java/Makefile.am
new file mode 100644
index 0000000..005c3b2
--- /dev/null
+++ b/java/Makefile.am
@@ -0,0 +1,59 @@
+javadir = $(pkgdatadir)/lib
+
+PKG = net/sourceforge/zbar
+java_DATA = zbar.jar
+
+java_LTLIBRARIES = libzbarjni.la
+libzbarjni_la_CPPFLAGS = $(JAVA_CFLAGS) $(AM_CPPFLAGS)
+libzbarjni_la_LIBADD = $(abs_top_builddir)/zbar/libzbar.la
+
+nodist_libzbarjni_la_SOURCES = zbarjni.h
+libzbarjni_la_SOURCES = zbarjni.c $(nodist_libzbarjni_la_SOURCES)
+BUILT_SOURCES = $(nodist_libzbarjni_la_SOURCES)
+MAINTAINERCLEANFILES = $(nodist_libzbarjni_la_SOURCES)
+
+zbar_jar_SRCS = \
+ $(PKG)/Config.java $(PKG)/Modifier.java $(PKG)/Orientation.java \
+ $(PKG)/Symbol.java $(PKG)/SymbolIterator.java $(PKG)/SymbolSet.java \
+ $(PKG)/Image.java $(PKG)/ImageScanner.java
+
+zbar_jar_CLASSES = $(zbar_jar_SRCS:.java=.class)
+
+test_SRCS = test/TestImage.java test/TestImageScanner.java \
+ test/TestScanImage.java
+test_CLASSES = TestImage TestImageScanner TestScanImage
+
+EXTRA_DIST = $(zbar_jar_SRCS) $(test_SRCS)
+
+CLEANFILES = zbar.jar $(nodist_libzbarjni_la_SOURCES) $(zbar_jar_CLASSES) $(test_CLASSES:=.class)
+
+if HAVE_JAVAH
+
+# Works up to Java 8
+zbarjni.h: $(zbar_jar_SRCS) zbar.jar
+ classes=`echo $(zbar_jar_CLASSES:.class=) | tr / .` ; \
+ $(JAVAH) -o $@ $$classes
+
+else
+
+# After Java 8, it is not possible anymore to build single zbarjni.h
+# As we don't want to break ABI, we need to join several .h files into one
+
+PKGH = ${shell echo ${PKG}|sed s,/,_,g}
+
+zbarjni.h: $(zbar_jar_SRCS)
+ $(JAVAC) -h $(abs_builddir) $(abs_srcdir)/$(PKG)/*.java
+ cat $(abs_builddir)/$(PKGH)_*.h > $(abs_builddir)/zbarjni.h
+ rm $(abs_builddir)/$(PKGH)_*.h
+
+endif
+
+zbar.jar: $(zbar_jar_SRCS)
+ cd $(abs_srcdir); $(JAVAC) -d $(abs_builddir) $(zbar_jar_SRCS)
+ $(JAR) cf $@ $(zbar_jar_CLASSES) || $(RM) $@
+
+#require junit java package
+check-java: zbar.jar libzbarjni.la
+ echo "making check in java"
+ cd $(abs_srcdir); $(JAVAC) -classpath $(abs_builddir)/zbar.jar:.:$(CLASSPATH) -d $(abs_builddir) $(test_SRCS)
+ $(abs_top_builddir)/libtool -dlopen $(abs_top_builddir)/zbar/libzbar.la -dlopen $(abs_builddir)/libzbarjni.la --mode=execute $(JAVA) -Xcheck:jni -classpath zbar.jar:.:$(CLASSPATH) org.junit.runner.JUnitCore $(test_CLASSES)
diff --git a/java/net/sourceforge/zbar/Config.java b/java/net/sourceforge/zbar/Config.java
new file mode 100644
index 0000000..019ea6c
--- /dev/null
+++ b/java/net/sourceforge/zbar/Config.java
@@ -0,0 +1,56 @@
+/*------------------------------------------------------------------------
+ * Config
+ *
+ * Copyright 2010 (c) Jeff Brown <spadix@users.sourceforge.net>
+ *
+ * This file is part of the ZBar Bar Code Reader.
+ *
+ * The ZBar Bar Code Reader is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The ZBar Bar Code Reader 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 Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser Public License
+ * along with the ZBar Bar Code Reader; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * http://sourceforge.net/projects/zbar
+ *------------------------------------------------------------------------*/
+
+package net.sourceforge.zbar;
+
+/** Decoder configuration options.
+ */
+public class Config
+{
+ /** Enable symbology/feature. */
+ public static final int ENABLE = 0;
+ /** Enable check digit when optional. */
+ public static final int ADD_CHECK = 1;
+ /** Return check digit when present. */
+ public static final int EMIT_CHECK = 2;
+ /** Enable full ASCII character set. */
+ public static final int ASCII = 3;
+
+ /** Minimum data length for valid decode. */
+ public static final int MIN_LEN = 0x20;
+ /** Maximum data length for valid decode. */
+ public static final int MAX_LEN = 0x21;
+
+ /** Required video consistency frames. */
+ public static final int UNCERTAINTY = 0x40;
+
+ /** Enable scanner to collect position data. */
+ public static final int POSITION = 0x80;
+
+ /** Image scanner vertical scan density. */
+ public static final int X_DENSITY = 0x100;
+ /** Image scanner horizontal scan density. */
+ public static final int Y_DENSITY = 0x101;
+}
diff --git a/java/net/sourceforge/zbar/Image.java b/java/net/sourceforge/zbar/Image.java
new file mode 100644
index 0000000..8227a4f
--- /dev/null
+++ b/java/net/sourceforge/zbar/Image.java
@@ -0,0 +1,163 @@
+/*------------------------------------------------------------------------
+ * Image
+ *
+ * Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
+ *
+ * This file is part of the ZBar Bar Code Reader.
+ *
+ * The ZBar Bar Code Reader is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The ZBar Bar Code Reader 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 Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser Public License
+ * along with the ZBar Bar Code Reader; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * http://sourceforge.net/projects/zbar
+ *------------------------------------------------------------------------*/
+
+package net.sourceforge.zbar;
+
+/** stores image data samples along with associated format and size
+ * metadata.
+ */
+public class Image
+{
+ /** C pointer to a zbar_symbol_t. */
+ private long peer;
+ private Object data;
+
+ static
+ {
+ System.loadLibrary("zbarjni");
+ init();
+ }
+ private static native void init();
+
+ public Image ()
+ {
+ peer = create();
+ }
+
+ public Image (int width, int height)
+ {
+ this();
+ setSize(width, height);
+ }
+
+ public Image (int width, int height, String format)
+ {
+ this();
+ setSize(width, height);
+ setFormat(format);
+ }
+
+ public Image (String format)
+ {
+ this();
+ setFormat(format);
+ }
+
+ Image (long peer)
+ {
+ this.peer = peer;
+ }
+
+ /** Create an associated peer instance. */
+ private native long create();
+
+ protected void finalize ()
+ {
+ destroy();
+ }
+
+ /** Clean up native data associated with an instance. */
+ public synchronized void destroy ()
+ {
+ if(peer != 0) {
+ destroy(peer);
+ peer = 0;
+ }
+ }
+
+ /** Destroy the associated peer instance. */
+ private native void destroy(long peer);
+
+ /** Image format conversion.
+ * @returns a @em new image with the sample data from the original
+ * image converted to the requested format fourcc. the original
+ * image is unaffected.
+ */
+ public Image convert (String format)
+ {
+ long newpeer = convert(peer, format);
+ if(newpeer == 0)
+ return(null);
+ return(new Image(newpeer));
+ }
+
+ private native long convert(long peer, String format);
+
+ /** Retrieve the image format fourcc. */
+ public native String getFormat();
+
+ /** Specify the fourcc image format code for image sample data. */
+ public native void setFormat(String format);
+
+ /** Retrieve a "sequence" (page/frame) number associated with this
+ * image.
+ */
+ public native int getSequence();
+
+ /** Associate a "sequence" (page/frame) number with this image. */
+ public native void setSequence(int seq);
+
+ /** Retrieve the width of the image. */
+ public native int getWidth();
+
+ /** Retrieve the height of the image. */
+ public native int getHeight();
+
+ /** Retrieve the size of the image. */
+ public native int[] getSize();
+
+ /** Specify the pixel size of the image. */
+ public native void setSize(int width, int height);
+
+ /** Specify the pixel size of the image. */
+ public native void setSize(int[] size);
+
+ /** Retrieve the crop region of the image. */
+ public native int[] getCrop();
+
+ /** Specify the crop region of the image. */
+ public native void setCrop(int x, int y, int width, int height);
+
+ /** Specify the crop region of the image. */
+ public native void setCrop(int[] crop);
+
+ /** Retrieve the image sample data. */
+ public native byte[] getData();
+
+ /** Specify image sample data. */
+ public native void setData(byte[] data);
+
+ /** Specify image sample data. */
+ public native void setData(int[] data);
+
+ /** Retrieve the decoded results associated with this image. */
+ public SymbolSet getSymbols ()
+ {
+ return(new SymbolSet(getSymbols(peer)));
+ }
+
+ private native long getSymbols(long peer);
+
+}
diff --git a/java/net/sourceforge/zbar/ImageScanner.java b/java/net/sourceforge/zbar/ImageScanner.java
new file mode 100644
index 0000000..02a2a1d
--- /dev/null
+++ b/java/net/sourceforge/zbar/ImageScanner.java
@@ -0,0 +1,98 @@
+/*------------------------------------------------------------------------
+ * ImageScanner
+ *
+ * Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
+ *
+ * This file is part of the ZBar Bar Code Reader.
+ *
+ * The ZBar Bar Code Reader is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The ZBar Bar Code Reader 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 Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser Public License
+ * along with the ZBar Bar Code Reader; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * http://sourceforge.net/projects/zbar
+ *------------------------------------------------------------------------*/
+
+package net.sourceforge.zbar;
+
+/** Read barcodes from 2-D images.
+ */
+public class ImageScanner
+{
+ /** C pointer to a zbar_image_scanner_t. */
+ private long peer;
+
+ static
+ {
+ System.loadLibrary("zbarjni");
+ init();
+ }
+ private static native void init();
+
+ public ImageScanner ()
+ {
+ peer = create();
+ }
+
+ /** Create an associated peer instance. */
+ private native long create();
+
+ protected void finalize ()
+ {
+ destroy();
+ }
+
+ /** Clean up native data associated with an instance. */
+ public synchronized void destroy ()
+ {
+ if(peer != 0) {
+ destroy(peer);
+ peer = 0;
+ }
+ }
+
+ /** Destroy the associated peer instance. */
+ private native void destroy(long peer);
+
+ /** Set config for indicated symbology (0 for all) to specified value.
+ */
+ public native void setConfig(int symbology, int config, int value)
+ throws IllegalArgumentException;
+
+ /** Parse configuration string and apply to image scanner. */
+ public native void parseConfig(String config);
+
+ /** Enable or disable the inter-image result cache (default disabled).
+ * Mostly useful for scanning video frames, the cache filters duplicate
+ * results from consecutive images, while adding some consistency
+ * checking and hysteresis to the results. Invoking this method also
+ * clears the cache.
+ */
+ public native void enableCache(boolean enable);
+
+ /** Retrieve decode results for last scanned image.
+ * @returns the SymbolSet result container
+ */
+ public SymbolSet getResults ()
+ {
+ return(new SymbolSet(getResults(peer)));
+ }
+
+ private native long getResults(long peer);
+
+ /** Scan for symbols in provided Image.
+ * The image format must currently be "Y800" or "GRAY".
+ * @returns the number of symbols successfully decoded from the image.
+ */
+ public native int scanImage(Image image);
+}
diff --git a/java/net/sourceforge/zbar/Modifier.java b/java/net/sourceforge/zbar/Modifier.java
new file mode 100644
index 0000000..451bb2e
--- /dev/null
+++ b/java/net/sourceforge/zbar/Modifier.java
@@ -0,0 +1,42 @@
+/*------------------------------------------------------------------------
+ * Modifier
+ *
+ * Copyright 2010 (c) Jeff Brown <spadix@users.sourceforge.net>
+ *
+ * This file is part of the ZBar Bar Code Reader.
+ *
+ * The ZBar Bar Code Reader is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The ZBar Bar Code Reader 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 Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser Public License
+ * along with the ZBar Bar Code Reader; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * http://sourceforge.net/projects/zbar
+ *------------------------------------------------------------------------*/
+
+package net.sourceforge.zbar;
+
+/** Decoder symbology modifiers.
+ */
+public class Modifier
+{
+ /** barcode tagged as GS1 (EAN.UCC) reserved
+ * (eg, FNC1 before first data character).
+ * data may be parsed as a sequence of GS1 AIs
+ */
+ public static final int GS1 = 0;
+
+ /** barcode tagged as AIM reserved
+ * (eg, FNC1 after first character or digit pair)
+ */
+ public static final int AIM = 1;
+}
diff --git a/java/net/sourceforge/zbar/Orientation.java b/java/net/sourceforge/zbar/Orientation.java
new file mode 100644
index 0000000..6643695
--- /dev/null
+++ b/java/net/sourceforge/zbar/Orientation.java
@@ -0,0 +1,42 @@
+/*------------------------------------------------------------------------
+ * Orientation
+ *
+ * Copyright 2010 (c) Jeff Brown <spadix@users.sourceforge.net>
+ *
+ * This file is part of the ZBar Bar Code Reader.
+ *
+ * The ZBar Bar Code Reader is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The ZBar Bar Code Reader 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 Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser Public License
+ * along with the ZBar Bar Code Reader; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * http://sourceforge.net/projects/zbar
+ *------------------------------------------------------------------------*/
+
+package net.sourceforge.zbar;
+
+/** Decoded symbol coarse orientation.
+ */
+public class Orientation
+{
+ /** Unable to determine orientation. */
+ public static final int UNKNOWN = -1;
+ /** Upright, read left to right. */
+ public static final int UP = 0;
+ /** sideways, read top to bottom */
+ public static final int RIGHT = 1;
+ /** upside-down, read right to left */
+ public static final int DOWN = 2;
+ /** sideways, read bottom to top */
+ public static final int LEFT = 3;
+}
diff --git a/java/net/sourceforge/zbar/Symbol.java b/java/net/sourceforge/zbar/Symbol.java
new file mode 100644
index 0000000..54f40f5
--- /dev/null
+++ b/java/net/sourceforge/zbar/Symbol.java
@@ -0,0 +1,199 @@
+/*------------------------------------------------------------------------
+ * Symbol
+ *
+ * Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
+ *
+ * This file is part of the ZBar Bar Code Reader.
+ *
+ * The ZBar Bar Code Reader is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The ZBar Bar Code Reader 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 Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser Public License
+ * along with the ZBar Bar Code Reader; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * http://sourceforge.net/projects/zbar
+ *------------------------------------------------------------------------*/
+
+package net.sourceforge.zbar;
+
+/** Immutable container for decoded result symbols associated with an image
+ * or a composite symbol.
+ */
+public class Symbol
+{
+ /** No symbol decoded. */
+ public static final int NONE = 0;
+ /** Symbol detected but not decoded. */
+ public static final int PARTIAL = 1;
+
+ /** EAN-8. */
+ public static final int EAN8 = 8;
+ /** UPC-E. */
+ public static final int UPCE = 9;
+ /** ISBN-10 (from EAN-13). */
+ public static final int ISBN10 = 10;
+ /** UPC-A. */
+ public static final int UPCA = 12;
+ /** EAN-13. */
+ public static final int EAN13 = 13;
+ /** ISBN-13 (from EAN-13). */
+ public static final int ISBN13 = 14;
+ /** Interleaved 2 of 5. */
+ public static final int I25 = 25;
+ /** DataBar (RSS-14). */
+ public static final int DATABAR = 34;
+ /** DataBar Expanded. */
+ public static final int DATABAR_EXP = 35;
+ /** Codabar. */
+ public static final int CODABAR = 38;
+ /** Code 39. */
+ public static final int CODE39 = 39;
+ /** PDF417. */
+ public static final int PDF417 = 57;
+ /** QR Code. */
+ public static final int QRCODE = 64;
+ /** Code 93. */
+ public static final int CODE93 = 93;
+ /** Code 128. */
+ public static final int CODE128 = 128;
+
+ /** C pointer to a zbar_symbol_t. */
+ private long peer;
+
+ /** Cached attributes. */
+ private int type;
+
+ static
+ {
+ System.loadLibrary("zbarjni");
+ init();
+ }
+ private static native void init();
+
+ /** Symbols are only created by other package methods. */
+ Symbol (long peer)
+ {
+ this.peer = peer;
+ }
+
+ protected void finalize ()
+ {
+ destroy();
+ }
+
+ /** Clean up native data associated with an instance. */
+ public synchronized void destroy ()
+ {
+ if(peer != 0) {
+ destroy(peer);
+ peer = 0;
+ }
+ }
+
+ /** Release the associated peer instance. */
+ private native void destroy(long peer);
+
+ /** Retrieve type of decoded symbol. */
+ public int getType ()
+ {
+ if(type == 0)
+ type = getType(peer);
+ return(type);
+ }
+
+ private native int getType(long peer);
+
+ /** Retrieve symbology boolean configs settings used during decode. */
+ public native int getConfigMask();
+
+ /** Retrieve symbology characteristics detected during decode. */
+ public native int getModifierMask();
+
+ /** Retrieve data decoded from symbol as a String. */
+ public native String getData();
+
+ /** Retrieve raw data bytes decoded from symbol. */
+ public native byte[] getDataBytes();
+
+ /** Retrieve a symbol confidence metric. Quality is an unscaled,
+ * relative quantity: larger values are better than smaller
+ * values, where "large" and "small" are application dependent.
+ */
+ public native int getQuality();
+
+ /** Retrieve current cache count. When the cache is enabled for
+ * the image_scanner this provides inter-frame reliability and
+ * redundancy information for video streams.
+ * @returns < 0 if symbol is still uncertain
+ * @returns 0 if symbol is newly verified
+ * @returns > 0 for duplicate symbols
+ */
+ public native int getCount();
+
+ /** Retrieve an approximate, axis-aligned bounding box for the
+ * symbol.
+ */
+ public int[] getBounds ()
+ {
+ int n = getLocationSize(peer);
+ if(n <= 0)
+ return(null);
+
+ int[] bounds = new int[4];
+ int xmin = Integer.MAX_VALUE;
+ int xmax = Integer.MIN_VALUE;
+ int ymin = Integer.MAX_VALUE;
+ int ymax = Integer.MIN_VALUE;
+
+ for(int i = 0; i < n; i++) {
+ int x = getLocationX(peer, i);
+ if(xmin > x) xmin = x;
+ if(xmax < x) xmax = x;
+
+ int y = getLocationY(peer, i);
+ if(ymin > y) ymin = y;
+ if(ymax < y) ymax = y;
+ }
+ bounds[0] = xmin;
+ bounds[1] = ymin;
+ bounds[2] = xmax - xmin;
+ bounds[3] = ymax - ymin;
+ return(bounds);
+ }
+
+ private native int getLocationSize(long peer);
+ private native int getLocationX(long peer, int idx);
+ private native int getLocationY(long peer, int idx);
+
+ public int[] getLocationPoint (int idx)
+ {
+ int[] p = new int[2];
+ p[0] = getLocationX(peer, idx);
+ p[1] = getLocationY(peer, idx);
+ return(p);
+ }
+
+ /** Retrieve general axis-aligned, orientation of decoded
+ * symbol.
+ */
+ public native int getOrientation();
+
+ /** Retrieve components of a composite result. */
+ public SymbolSet getComponents ()
+ {
+ return(new SymbolSet(getComponents(peer)));
+ }
+
+ private native long getComponents(long peer);
+
+ native long next();
+}
diff --git a/java/net/sourceforge/zbar/SymbolIterator.java b/java/net/sourceforge/zbar/SymbolIterator.java
new file mode 100644
index 0000000..954a5aa
--- /dev/null
+++ b/java/net/sourceforge/zbar/SymbolIterator.java
@@ -0,0 +1,70 @@
+/*------------------------------------------------------------------------
+ * SymbolIterator
+ *
+ * Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
+ *
+ * This file is part of the ZBar Bar Code Reader.
+ *
+ * The ZBar Bar Code Reader is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The ZBar Bar Code Reader 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 Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser Public License
+ * along with the ZBar Bar Code Reader; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * http://sourceforge.net/projects/zbar
+ *------------------------------------------------------------------------*/
+
+package net.sourceforge.zbar;
+
+/** Iterator over a SymbolSet.
+ */
+public class SymbolIterator
+ implements java.util.Iterator<Symbol>
+{
+ /** Next symbol to be returned by the iterator. */
+ private Symbol current;
+
+ /** SymbolIterators are only created by internal interface methods. */
+ SymbolIterator (Symbol first)
+ {
+ current = first;
+ }
+
+ /** Returns true if the iteration has more elements. */
+ public boolean hasNext ()
+ {
+ return(current != null);
+ }
+
+ /** Retrieves the next element in the iteration. */
+ public Symbol next ()
+ {
+ if(current == null)
+ throw(new java.util.NoSuchElementException
+ ("access past end of SymbolIterator"));
+
+ Symbol result = current;
+ long sym = current.next();
+ if(sym != 0)
+ current = new Symbol(sym);
+ else
+ current = null;
+ return(result);
+ }
+
+ /** Raises UnsupportedOperationException. */
+ public void remove ()
+ {
+ throw(new UnsupportedOperationException
+ ("SymbolIterator is immutable"));
+ }
+}
diff --git a/java/net/sourceforge/zbar/SymbolSet.java b/java/net/sourceforge/zbar/SymbolSet.java
new file mode 100644
index 0000000..1c9110a
--- /dev/null
+++ b/java/net/sourceforge/zbar/SymbolSet.java
@@ -0,0 +1,82 @@
+/*------------------------------------------------------------------------
+ * SymbolSet
+ *
+ * Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
+ *
+ * This file is part of the ZBar Bar Code Reader.
+ *
+ * The ZBar Bar Code Reader is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The ZBar Bar Code Reader 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 Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser Public License
+ * along with the ZBar Bar Code Reader; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * http://sourceforge.net/projects/zbar
+ *------------------------------------------------------------------------*/
+
+package net.sourceforge.zbar;
+
+/** Immutable container for decoded result symbols associated with an image
+ * or a composite symbol.
+ */
+public class SymbolSet
+ extends java.util.AbstractCollection<Symbol>
+{
+ /** C pointer to a zbar_symbol_set_t. */
+ private long peer;
+
+ static
+ {
+ System.loadLibrary("zbarjni");
+ init();
+ }
+ private static native void init();
+
+ /** SymbolSets are only created by other package methods. */
+ SymbolSet (long peer)
+ {
+ this.peer = peer;
+ }
+
+ protected void finalize ()
+ {
+ destroy();
+ }
+
+ /** Clean up native data associated with an instance. */
+ public synchronized void destroy ()
+ {
+ if(peer != 0) {
+ destroy(peer);
+ peer = 0;
+ }
+ }
+
+ /** Release the associated peer instance. */
+ private native void destroy(long peer);
+
+ /** Retrieve an iterator over the Symbol elements in this collection. */
+ public java.util.Iterator<Symbol> iterator ()
+ {
+ long sym = firstSymbol(peer);
+ if(sym == 0)
+ return(new SymbolIterator(null));
+
+ return(new SymbolIterator(new Symbol(sym)));
+ }
+
+ /** Retrieve the number of elements in the collection. */
+ public native int size();
+
+ /** Retrieve C pointer to first symbol in the set. */
+ private native long firstSymbol(long peer);
+}
diff --git a/java/test/TestImage.java b/java/test/TestImage.java
new file mode 100644
index 0000000..9666f2b
--- /dev/null
+++ b/java/test/TestImage.java
@@ -0,0 +1,175 @@
+
+import org.junit.Test;
+import org.junit.Before;
+import org.junit.After;
+import static org.junit.Assert.*;
+
+import net.sourceforge.zbar.Image;
+
+public class TestImage
+{
+ protected Image image;
+
+ @Before public void setUp ()
+ {
+ image = new Image();
+ }
+
+ @After public void tearDown ()
+ {
+ image.destroy();
+ image = null;
+ }
+
+
+ @Test public void creation ()
+ {
+ Image img0 = new Image(123, 456);
+ Image img1 = new Image("BGR3");
+ Image img2 = new Image(987, 654, "UYVY");
+
+ assertEquals(123, img0.getWidth());
+ assertEquals(456, img0.getHeight());
+ assertEquals(null, img0.getFormat());
+
+ assertEquals(0, img1.getWidth());
+ assertEquals(0, img1.getHeight());
+ assertEquals("BGR3", img1.getFormat());
+
+ assertEquals(987, img2.getWidth());
+ assertEquals(654, img2.getHeight());
+ assertEquals("UYVY", img2.getFormat());
+ }
+
+ @Test public void sequence ()
+ {
+ assertEquals(0, image.getSequence());
+ image.setSequence(42);
+ assertEquals(42, image.getSequence());
+ }
+
+ @Test public void size ()
+ {
+ assertEquals(0, image.getWidth());
+ assertEquals(0, image.getHeight());
+
+ image.setSize(640, 480);
+ int[] size0 = { 640, 480 };
+ assertArrayEquals(size0, image.getSize());
+
+ int[] size1 = { 320, 240 };
+ image.setSize(size1);
+ assertEquals(320, image.getWidth());
+ assertEquals(240, image.getHeight());
+ }
+
+ @Test public void crop ()
+ {
+ int[] zeros = { 0, 0, 0, 0 };
+ assertArrayEquals(zeros, image.getCrop());
+
+ image.setSize(123, 456);
+ int[] crop0 = { 0, 0, 123, 456 };
+ assertArrayEquals(crop0, image.getCrop());
+
+ image.setCrop(1, 2, 34, 56);
+ int[] crop1 = { 1, 2, 34, 56 };
+ assertArrayEquals(crop1, image.getCrop());
+
+ image.setCrop(-20, -20, 200, 500);
+ assertArrayEquals(crop0, image.getCrop());
+
+ int[] crop2 = { 7, 8, 90, 12};
+ image.setCrop(crop2);
+ assertArrayEquals(crop2, image.getCrop());
+
+ image.setSize(654, 321);
+ int[] crop3 = { 0, 0, 654, 321 };
+ assertArrayEquals(crop3, image.getCrop());
+
+ int[] crop4 = { -10, -10, 700, 400 };
+ image.setCrop(crop4);
+ assertArrayEquals(crop3, image.getCrop());
+ }
+
+ @Test public void format ()
+ {
+ assertNull(image.getFormat());
+ image.setFormat("Y800");
+ assertEquals("Y800", image.getFormat());
+ boolean gotException = false;
+ try {
+ image.setFormat("[]");
+ }
+ catch(IllegalArgumentException e) {
+ // expected
+ gotException = true;
+ }
+ assertTrue("Expected exception", gotException);
+ assertEquals("Y800", image.getFormat());
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void setFormatInvalid0 ()
+ {
+ image.setFormat(null);
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void setFormatInvalid1 ()
+ {
+ image.setFormat("");
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void setFormatInvalid2 ()
+ {
+ image.setFormat("YOMAMA");
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void setFormatInvalid3 ()
+ {
+ image.setFormat("foo");
+ }
+
+ @Test public void data ()
+ {
+ assertNull(image.getData());
+
+ int[] ints = new int[24];
+ image.setData(ints);
+ assertSame(ints, image.getData());
+
+ byte[] bytes = new byte[280];
+ image.setData(bytes);
+ assertSame(bytes, image.getData());
+
+ image.setData((byte[])null);
+ assertNull(image.getData());
+ }
+
+ @Test public void convert ()
+ {
+ image.setSize(4, 4);
+ image.setFormat("RGB4");
+ int[] rgb4 = new int[16];
+ byte[] exp = new byte[16];
+ for(int i = 0; i < 16; i++) {
+ int c = i * 15;
+ rgb4[i] = c | (c << 8) | (c << 16) | (c << 24);
+ exp[i] = (byte)c;
+ }
+ image.setData(rgb4);
+
+ Image gray = image.convert("Y800");
+ assertEquals(4, gray.getWidth());
+ assertEquals(4, gray.getHeight());
+ assertEquals("Y800", gray.getFormat());
+
+ byte[] y800 = gray.getData();
+ assertEquals(16, y800.length);
+
+ assertArrayEquals(exp, y800);
+ }
+}
diff --git a/java/test/TestImageScanner.java b/java/test/TestImageScanner.java
new file mode 100644
index 0000000..0d8eccc
--- /dev/null
+++ b/java/test/TestImageScanner.java
@@ -0,0 +1,53 @@
+
+import org.junit.Test;
+import org.junit.Before;
+import org.junit.After;
+import org.junit.Assert.*;
+
+import net.sourceforge.zbar.ImageScanner;
+import net.sourceforge.zbar.Config;
+
+public class TestImageScanner
+{
+ protected ImageScanner scanner;
+
+ @Before public void setUp ()
+ {
+ scanner = new ImageScanner();
+ }
+
+ @After public void tearDown ()
+ {
+ scanner.destroy();
+ scanner = null;
+ }
+
+
+ @Test public void creation ()
+ {
+ // create/destroy
+ }
+
+ @Test public void callSetConfig ()
+ {
+ scanner.setConfig(0, Config.X_DENSITY, 2);
+ scanner.setConfig(0, Config.Y_DENSITY, 4);
+ }
+
+ @Test public void callParseConfig ()
+ {
+ scanner.parseConfig("disable");
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void callParseConfigInvalid ()
+ {
+ scanner.parseConfig("yomama");
+ }
+
+ @Test public void callEnableCache ()
+ {
+ scanner.enableCache(true);
+ scanner.enableCache(false);
+ }
+}
diff --git a/java/test/TestScanImage.java b/java/test/TestScanImage.java
new file mode 100644
index 0000000..86ed024
--- /dev/null
+++ b/java/test/TestScanImage.java
@@ -0,0 +1,183 @@
+
+import org.junit.Test;
+import org.junit.Before;
+import org.junit.After;
+import static org.junit.Assert.*;
+
+import net.sourceforge.zbar.*;
+
+import java.text.CharacterIterator;
+import java.text.StringCharacterIterator;
+import java.util.Iterator;
+
+public class TestScanImage
+{
+ protected ImageScanner scanner;
+ protected Image image;
+
+ @Before public void setUp ()
+ {
+ scanner = new ImageScanner();
+ image = new Image();
+ }
+
+ @After public void tearDown ()
+ {
+ image = null;
+ scanner = null;
+ System.gc();
+ }
+
+ public static final String encoded_widths =
+ "9 111 212241113121211311141132 11111 311213121312121332111132 111 9";
+
+ protected void generateY800 ()
+ {
+ int width = 114, height = 85;
+ image.setSize(width, height);
+ image.setFormat("Y800");
+ int datalen = width * height;
+ byte[] data = new byte[datalen];
+
+ int y = 0;
+ int p = 0;
+ for(; y < 10 && y < height; y++)
+ for(int x = 0; x < width; x++)
+ data[p++] = -1;
+
+ for(; y < height - 10; y++) {
+ int x = 0;
+ byte color = -1;
+ CharacterIterator it = new StringCharacterIterator(encoded_widths);
+ for(char c = it.first();
+ c != CharacterIterator.DONE;
+ c = it.next())
+ {
+ if(c == ' ')
+ continue;
+ for(int dx = (int)c - 0x30; dx > 0; dx--) {
+ data[p++] = color;
+ x++;
+ }
+ color = (byte)~color;
+ }
+ for(; x < width; x++)
+ data[p++] = (byte)~color;
+ }
+
+ for(; y < height; y++)
+ for(int x = 0; x < width; x++)
+ data[p++] = -1;
+ assert(p == datalen);
+
+ image.setData(data);
+ }
+
+ protected void checkResults (SymbolSet syms)
+ {
+ assertNotNull(syms);
+ assert(syms.size() == 1);
+ Iterator<Symbol> it = syms.iterator();
+ assertTrue(it.hasNext());
+ Symbol sym = it.next();
+ assertNotNull(sym);
+ assertFalse(it.hasNext());
+
+ assertEquals(Symbol.EAN13, sym.getType());
+ assertEquals(sym.EAN13, sym.getType()); // cached
+
+ assertTrue(sym.getQuality() > 1);
+ assertEquals(0, sym.getCount());
+
+ SymbolSet comps = sym.getComponents();
+ assertNotNull(comps);
+ assertEquals(0, comps.size());
+ it = comps.iterator();
+ assertNotNull(it);
+ assertFalse(it.hasNext());
+
+ String data = sym.getData();
+ assertEquals("6268964977804", data);
+
+ byte[] bytes = sym.getDataBytes();
+ byte[] exp = { '6','2','6','8','9','6','4','9','7','7','8','0','4' };
+ assertArrayEquals(exp, bytes);
+
+ int[] r = sym.getBounds();
+ assertTrue(r[0] > 6);
+ assertTrue(r[1] > 6);
+ assertTrue(r[2] < 102);
+ assertTrue(r[3] < 73);
+
+ assertEquals(Orientation.UP, sym.getOrientation());
+ }
+
+ @Test public void generated ()
+ {
+ generateY800();
+ int n = scanner.scanImage(image);
+ assertEquals(1, n);
+
+ checkResults(image.getSymbols());
+ checkResults(scanner.getResults());
+ }
+
+ @Test public void config ()
+ {
+ generateY800();
+ scanner.setConfig(Symbol.EAN13, Config.ENABLE, 0);
+ int n = scanner.scanImage(image);
+ assertEquals(0, n);
+ }
+
+ @Test public void cache ()
+ {
+ generateY800();
+ scanner.enableCache(true);
+
+ int n = 0;
+ for(int i = 0; i < 10; i++) {
+ n = scanner.scanImage(image);
+ if(n > 0) {
+ assertTrue(i > 1);
+ break;
+ }
+ }
+
+ assertEquals(1, n);
+ checkResults(scanner.getResults());
+ }
+
+ @Test public void orientation()
+ {
+ generateY800();
+
+ // flip the image
+ int width = image.getWidth();
+ int height = image.getHeight();
+ byte[] data = image.getData();
+ int p = 0;
+ for(int y = 0; y < height; y++) {
+ for(int x0 = 0; x0 < width / 2; x0++) {
+ int x1 = width - x0 - 1;
+ assert(x0 < x1);
+ byte b = data[p + x0];
+ data[p + x0] = data[p + x1];
+ data[p + x1] = b;
+ }
+ p += width;
+ }
+ image.setData(data);
+
+ int n = scanner.scanImage(image);
+ assertEquals(1, n);
+
+ SymbolSet syms = scanner.getResults();
+ assert(syms.size() == 1);
+ for(Symbol sym : syms) {
+ assertEquals(Symbol.EAN13, sym.getType());
+ assertEquals("6268964977804", sym.getData());
+ assertEquals(Orientation.DOWN, sym.getOrientation());
+ }
+ }
+}
diff --git a/java/zbarjni.c b/java/zbarjni.c
new file mode 100644
index 0000000..3506a32
--- /dev/null
+++ b/java/zbarjni.c
@@ -0,0 +1,618 @@
+/*------------------------------------------------------------------------
+ * Copyright 2010 (c) Jeff Brown <spadix@users.sourceforge.net>
+ *
+ * This file is part of the ZBar Bar Code Reader.
+ *
+ * The ZBar Bar Code Reader is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The ZBar Bar Code Reader 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 Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser Public License
+ * along with the ZBar Bar Code Reader; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * http://sourceforge.net/projects/zbar
+ *------------------------------------------------------------------------*/
+#include <assert.h>
+#include <inttypes.h>
+#include <jni.h>
+#include <zbar.h>
+
+static jfieldID SymbolSet_peer;
+static jfieldID Symbol_peer;
+static jfieldID Image_peer, Image_data;
+static jfieldID ImageScanner_peer;
+
+static struct {
+ int SymbolSet_create, SymbolSet_destroy;
+ int Symbol_create, Symbol_destroy;
+ int Image_create, Image_destroy;
+ int ImageScanner_create, ImageScanner_destroy;
+} stats;
+
+#define PEER_CAST(l) ((void *)(uintptr_t)(l))
+
+#define GET_PEER(c, o) PEER_CAST((*env)->GetLongField(env, (o), c##_peer))
+
+static inline void throw_exc(JNIEnv *env, const char *name, const char *msg)
+{
+ jclass cls = (*env)->FindClass(env, name);
+
+ if (cls)
+ (*env)->ThrowNew(env, cls, msg);
+ (*env)->DeleteLocalRef(env, cls);
+}
+
+static inline uint32_t format_to_fourcc(JNIEnv *env, jstring format)
+{
+ if (!format)
+ goto invalid;
+
+ int n = (*env)->GetStringLength(env, format);
+ if (0 >= n || n > 4)
+ goto invalid;
+
+ char fmtstr[8];
+ (*env)->GetStringUTFRegion(env, format, 0, n, fmtstr);
+
+ uint32_t fourcc = 0;
+ int i;
+ for (i = 0; i < n; i++) {
+ if (fmtstr[i] < ' ' || 'Z' < fmtstr[i] ||
+ ('9' < fmtstr[i] && fmtstr[i] < 'A') ||
+ (' ' < fmtstr[i] && fmtstr[i] < '0'))
+ goto invalid;
+ fourcc |= ((uint32_t)fmtstr[i]) << (8 * i);
+ }
+ return (fourcc);
+
+invalid:
+ throw_exc(env, "java/lang/IllegalArgumentException",
+ "invalid format fourcc");
+ return (0);
+}
+
+static JavaVM *jvm = NULL;
+
+JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *_jvm, void *reserved)
+{
+ jvm = _jvm;
+ return (JNI_VERSION_1_2);
+}
+
+JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *_jvm, void *reserved)
+{
+ assert(stats.SymbolSet_create == stats.SymbolSet_destroy);
+ assert(stats.Symbol_create == stats.Symbol_destroy);
+ assert(stats.Image_create == stats.Image_destroy);
+ assert(stats.ImageScanner_create == stats.ImageScanner_destroy);
+}
+
+JNIEXPORT void JNICALL Java_net_sourceforge_zbar_SymbolSet_init(JNIEnv *env,
+ jclass cls)
+{
+ SymbolSet_peer = (*env)->GetFieldID(env, cls, "peer", "J");
+}
+
+JNIEXPORT void JNICALL Java_net_sourceforge_zbar_SymbolSet_destroy(JNIEnv *env,
+ jobject obj,
+ jlong peer)
+{
+ zbar_symbol_set_ref(PEER_CAST(peer), -1);
+ stats.SymbolSet_destroy++;
+}
+
+JNIEXPORT jint JNICALL Java_net_sourceforge_zbar_SymbolSet_size(JNIEnv *env,
+ jobject obj)
+{
+ zbar_symbol_set_t *zsyms = GET_PEER(SymbolSet, obj);
+ if (!zsyms)
+ return (0);
+ return (zbar_symbol_set_get_size(zsyms));
+}
+
+JNIEXPORT jlong JNICALL Java_net_sourceforge_zbar_SymbolSet_firstSymbol(
+ JNIEnv *env, jobject obj, jlong peer)
+{
+ if (!peer)
+ return (0);
+ const zbar_symbol_t *zsym = zbar_symbol_set_first_symbol(PEER_CAST(peer));
+ if (zsym) {
+ zbar_symbol_ref(zsym, 1);
+ stats.Symbol_create++;
+ }
+ return ((intptr_t)zsym);
+}
+
+JNIEXPORT void JNICALL Java_net_sourceforge_zbar_Symbol_init(JNIEnv *env,
+ jclass cls)
+{
+ Symbol_peer = (*env)->GetFieldID(env, cls, "peer", "J");
+}
+
+JNIEXPORT void JNICALL Java_net_sourceforge_zbar_Symbol_destroy(JNIEnv *env,
+ jobject obj,
+ jlong peer)
+{
+ zbar_symbol_ref(PEER_CAST(peer), -1);
+ stats.Symbol_destroy++;
+}
+
+JNIEXPORT jint JNICALL Java_net_sourceforge_zbar_Symbol_getType(JNIEnv *env,
+ jobject obj,
+ jlong peer)
+{
+ return (zbar_symbol_get_type(PEER_CAST(peer)));
+}
+
+JNIEXPORT jint JNICALL
+Java_net_sourceforge_zbar_Symbol_getConfigMask(JNIEnv *env, jobject obj)
+{
+ return (zbar_symbol_get_configs(GET_PEER(Symbol, obj)));
+}
+
+JNIEXPORT jint JNICALL
+Java_net_sourceforge_zbar_Symbol_getModifierMask(JNIEnv *env, jobject obj)
+{
+ return (zbar_symbol_get_modifiers(GET_PEER(Symbol, obj)));
+}
+
+JNIEXPORT jstring JNICALL Java_net_sourceforge_zbar_Symbol_getData(JNIEnv *env,
+ jobject obj)
+{
+ const char *data = zbar_symbol_get_data(GET_PEER(Symbol, obj));
+
+ return ((*env)->NewStringUTF(env, data));
+}
+
+JNIEXPORT jstring JNICALL
+Java_net_sourceforge_zbar_Symbol_getDataBytes(JNIEnv *env, jobject obj)
+{
+ const zbar_symbol_t *zsym = GET_PEER(Symbol, obj);
+ const void *data = zbar_symbol_get_data(zsym);
+ unsigned long datalen = zbar_symbol_get_data_length(zsym);
+
+ if (!data || !datalen)
+ return (NULL);
+
+ jbyteArray bytes = (*env)->NewByteArray(env, datalen);
+ if (!bytes)
+ return (NULL);
+
+ (*env)->SetByteArrayRegion(env, bytes, 0, datalen, data);
+ return (bytes);
+}
+
+JNIEXPORT jint JNICALL Java_net_sourceforge_zbar_Symbol_getQuality(JNIEnv *env,
+ jobject obj)
+{
+ return (zbar_symbol_get_quality(GET_PEER(Symbol, obj)));
+}
+
+JNIEXPORT jint JNICALL Java_net_sourceforge_zbar_Symbol_getCount(JNIEnv *env,
+ jobject obj)
+{
+ return (zbar_symbol_get_count(GET_PEER(Symbol, obj)));
+}
+
+JNIEXPORT jint JNICALL Java_net_sourceforge_zbar_Symbol_getLocationSize(
+ JNIEnv *env, jobject obj, jlong peer)
+{
+ return (zbar_symbol_get_loc_size(PEER_CAST(peer)));
+}
+
+JNIEXPORT jint JNICALL Java_net_sourceforge_zbar_Symbol_getLocationX(
+ JNIEnv *env, jobject obj, jlong peer, jint idx)
+{
+ return (zbar_symbol_get_loc_x(PEER_CAST(peer), idx));
+}
+
+JNIEXPORT jint JNICALL Java_net_sourceforge_zbar_Symbol_getLocationY(
+ JNIEnv *env, jobject obj, jlong peer, jint idx)
+{
+ return (zbar_symbol_get_loc_y(PEER_CAST(peer), idx));
+}
+
+JNIEXPORT jint JNICALL
+Java_net_sourceforge_zbar_Symbol_getOrientation(JNIEnv *env, jobject obj)
+{
+ return (zbar_symbol_get_orientation(GET_PEER(Symbol, obj)));
+}
+
+JNIEXPORT jlong JNICALL Java_net_sourceforge_zbar_Symbol_getComponents(
+ JNIEnv *env, jobject obj, jlong peer)
+{
+ const zbar_symbol_set_t *zsyms;
+
+ zsyms = zbar_symbol_get_components(PEER_CAST(peer));
+ if (zsyms) {
+ zbar_symbol_set_ref(zsyms, 1);
+ stats.SymbolSet_create++;
+ }
+ return ((intptr_t)zsyms);
+}
+
+JNIEXPORT jlong JNICALL Java_net_sourceforge_zbar_Symbol_next(JNIEnv *env,
+ jobject obj)
+{
+ const zbar_symbol_t *zsym = zbar_symbol_next(GET_PEER(Symbol, obj));
+ if (zsym) {
+ zbar_symbol_ref(zsym, 1);
+ stats.Symbol_create++;
+ }
+ return ((intptr_t)zsym);
+}
+
+static void Image_cleanupByteArray(zbar_image_t *zimg)
+{
+ jobject data = zbar_image_get_userdata(zimg);
+ assert(data);
+
+ JNIEnv *env = NULL;
+ if ((*jvm)->AttachCurrentThread(jvm, (void *)&env, NULL))
+ return;
+ assert(env);
+ if (env && data) {
+ void *raw = (void *)zbar_image_get_data(zimg);
+ assert(raw);
+ /* const image data is unchanged - abort copy back */
+ (*env)->ReleaseByteArrayElements(env, data, raw, JNI_ABORT);
+ (*env)->DeleteGlobalRef(env, data);
+ zbar_image_set_userdata(zimg, NULL);
+ }
+}
+
+static void Image_cleanupIntArray(zbar_image_t *zimg)
+{
+ jobject data = zbar_image_get_userdata(zimg);
+ assert(data);
+
+ JNIEnv *env = NULL;
+ if ((*jvm)->AttachCurrentThread(jvm, (void *)&env, NULL))
+ return;
+ assert(env);
+ if (env && data) {
+ void *raw = (void *)zbar_image_get_data(zimg);
+ assert(raw);
+ /* const image data is unchanged - abort copy back */
+ (*env)->ReleaseIntArrayElements(env, data, raw, JNI_ABORT);
+ (*env)->DeleteGlobalRef(env, data);
+ zbar_image_set_userdata(zimg, NULL);
+ }
+}
+
+JNIEXPORT void JNICALL Java_net_sourceforge_zbar_Image_init(JNIEnv *env,
+ jclass cls)
+{
+ Image_peer = (*env)->GetFieldID(env, cls, "peer", "J");
+ Image_data = (*env)->GetFieldID(env, cls, "data", "Ljava/lang/Object;");
+}
+
+JNIEXPORT jlong JNICALL Java_net_sourceforge_zbar_Image_create(JNIEnv *env,
+ jobject obj)
+{
+ zbar_image_t *zimg = zbar_image_create();
+ if (!zimg) {
+ throw_exc(env, "java/lang/OutOfMemoryError", NULL);
+ return (0);
+ }
+ stats.Image_create++;
+ return ((intptr_t)zimg);
+}
+
+JNIEXPORT void JNICALL Java_net_sourceforge_zbar_Image_destroy(JNIEnv *env,
+ jobject obj,
+ jlong peer)
+{
+ zbar_image_ref(PEER_CAST(peer), -1);
+ stats.Image_destroy++;
+}
+
+JNIEXPORT jlong JNICALL Java_net_sourceforge_zbar_Image_convert(JNIEnv *env,
+ jobject obj,
+ jlong peer,
+ jstring format)
+{
+ uint32_t fourcc = format_to_fourcc(env, format);
+ if (!fourcc)
+ return (0);
+ zbar_image_t *zimg = zbar_image_convert(PEER_CAST(peer), fourcc);
+ if (!zimg)
+ throw_exc(env, "java/lang/UnsupportedOperationException",
+ "unsupported image format");
+ else
+ stats.Image_create++;
+ return ((intptr_t)zimg);
+}
+
+JNIEXPORT jstring JNICALL Java_net_sourceforge_zbar_Image_getFormat(JNIEnv *env,
+ jobject obj)
+{
+ uint32_t fourcc = zbar_image_get_format(GET_PEER(Image, obj));
+
+ if (!fourcc)
+ return (NULL);
+
+ char fmtstr[5] = { fourcc, fourcc >> 8, fourcc >> 16, fourcc >> 24, 0 };
+ return ((*env)->NewStringUTF(env, fmtstr));
+}
+
+JNIEXPORT void JNICALL Java_net_sourceforge_zbar_Image_setFormat(JNIEnv *env,
+ jobject obj,
+ jstring format)
+{
+ uint32_t fourcc = format_to_fourcc(env, format);
+
+ if (!fourcc)
+ return;
+ zbar_image_set_format(GET_PEER(Image, obj), fourcc);
+}
+
+JNIEXPORT jint JNICALL Java_net_sourceforge_zbar_Image_getSequence(JNIEnv *env,
+ jobject obj)
+{
+ return (zbar_image_get_sequence(GET_PEER(Image, obj)));
+}
+
+JNIEXPORT void JNICALL Java_net_sourceforge_zbar_Image_setSequence(JNIEnv *env,
+ jobject obj,
+ jint seq)
+{
+ zbar_image_set_sequence(GET_PEER(Image, obj), seq);
+}
+
+JNIEXPORT jint JNICALL Java_net_sourceforge_zbar_Image_getWidth(JNIEnv *env,
+ jobject obj)
+{
+ return (zbar_image_get_width(GET_PEER(Image, obj)));
+}
+
+JNIEXPORT jint JNICALL Java_net_sourceforge_zbar_Image_getHeight(JNIEnv *env,
+ jobject obj)
+{
+ return (zbar_image_get_height(GET_PEER(Image, obj)));
+}
+
+JNIEXPORT jobject JNICALL Java_net_sourceforge_zbar_Image_getSize(JNIEnv *env,
+ jobject obj)
+{
+ jintArray size = (*env)->NewIntArray(env, 2);
+ if (!size)
+ return (NULL);
+
+ unsigned dims[2];
+ zbar_image_get_size(GET_PEER(Image, obj), dims, dims + 1);
+ jint jdims[2] = { dims[0], dims[1] };
+ (*env)->SetIntArrayRegion(env, size, 0, 2, jdims);
+ return (size);
+}
+
+JNIEXPORT void JNICALL Java_net_sourceforge_zbar_Image_setSize__II(JNIEnv *env,
+ jobject obj,
+ jint width,
+ jint height)
+{
+ if (width < 0)
+ width = 0;
+ if (height < 0)
+ height = 0;
+ zbar_image_set_size(GET_PEER(Image, obj), width, height);
+}
+
+JNIEXPORT void JNICALL Java_net_sourceforge_zbar_Image_setSize___3I(
+ JNIEnv *env, jobject obj, jintArray size)
+{
+ if ((*env)->GetArrayLength(env, size) != 2)
+ throw_exc(env, "java/lang/IllegalArgumentException",
+ "size must be an array of two ints");
+ jint dims[2];
+ (*env)->GetIntArrayRegion(env, size, 0, 2, dims);
+ if (dims[0] < 0)
+ dims[0] = 0;
+ if (dims[1] < 0)
+ dims[1] = 0;
+ zbar_image_set_size(GET_PEER(Image, obj), dims[0], dims[1]);
+}
+
+JNIEXPORT jobject JNICALL Java_net_sourceforge_zbar_Image_getCrop(JNIEnv *env,
+ jobject obj)
+{
+ jintArray crop = (*env)->NewIntArray(env, 4);
+ if (!crop)
+ return (NULL);
+
+ unsigned dims[4];
+ zbar_image_get_crop(GET_PEER(Image, obj), dims, dims + 1, dims + 2,
+ dims + 3);
+ jint jdims[4] = { dims[0], dims[1], dims[2], dims[3] };
+ (*env)->SetIntArrayRegion(env, crop, 0, 4, jdims);
+ return (crop);
+}
+
+#define VALIDATE_CROP(u, m) \
+ if ((u) < 0) { \
+ (m) += (u); \
+ (u) = 0; \
+ }
+
+JNIEXPORT void JNICALL Java_net_sourceforge_zbar_Image_setCrop__IIII(
+ JNIEnv *env, jobject obj, jint x, jint y, jint w, jint h)
+{
+ VALIDATE_CROP(x, w);
+ VALIDATE_CROP(y, h);
+ zbar_image_set_crop(GET_PEER(Image, obj), x, y, w, h);
+}
+
+JNIEXPORT void JNICALL Java_net_sourceforge_zbar_Image_setCrop___3I(
+ JNIEnv *env, jobject obj, jintArray crop)
+{
+ if ((*env)->GetArrayLength(env, crop) != 4)
+ throw_exc(env, "java/lang/IllegalArgumentException",
+ "crop must be an array of four ints");
+ jint dims[4];
+ (*env)->GetIntArrayRegion(env, crop, 0, 4, dims);
+ VALIDATE_CROP(dims[0], dims[2]);
+ VALIDATE_CROP(dims[1], dims[3]);
+ zbar_image_set_crop(GET_PEER(Image, obj), dims[0], dims[1], dims[2],
+ dims[3]);
+}
+#undef VALIDATE_CROP
+
+JNIEXPORT jobject JNICALL Java_net_sourceforge_zbar_Image_getData(JNIEnv *env,
+ jobject obj)
+{
+ jobject data = (*env)->GetObjectField(env, obj, Image_data);
+ if (data)
+ return (data);
+
+ zbar_image_t *zimg = GET_PEER(Image, obj);
+ data = zbar_image_get_userdata(zimg);
+ if (data)
+ return (data);
+
+ unsigned long rawlen = zbar_image_get_data_length(zimg);
+ const void *raw = zbar_image_get_data(zimg);
+ if (!rawlen || !raw)
+ return (NULL);
+
+ data = (*env)->NewByteArray(env, rawlen);
+ if (!data)
+ return (NULL);
+
+ (*env)->SetByteArrayRegion(env, data, 0, rawlen, raw);
+ (*env)->SetObjectField(env, obj, Image_data, data);
+ return (data);
+}
+
+static inline void Image_setData(JNIEnv *env, jobject obj, jbyteArray data,
+ void *raw, unsigned long rawlen,
+ zbar_image_cleanup_handler_t *cleanup)
+{
+ if (!data)
+ cleanup = NULL;
+ (*env)->SetObjectField(env, obj, Image_data, data);
+ zbar_image_t *zimg = GET_PEER(Image, obj);
+ zbar_image_set_data(zimg, raw, rawlen, cleanup);
+ zbar_image_set_userdata(zimg, (*env)->NewGlobalRef(env, data));
+}
+
+JNIEXPORT void JNICALL Java_net_sourceforge_zbar_Image_setData___3B(
+ JNIEnv *env, jobject obj, jbyteArray data)
+{
+ jbyte *raw = NULL;
+ unsigned long rawlen = 0;
+ if (data) {
+ raw = (*env)->GetByteArrayElements(env, data, NULL);
+ if (!raw)
+ return;
+ rawlen = (*env)->GetArrayLength(env, data);
+ }
+ Image_setData(env, obj, data, raw, rawlen, Image_cleanupByteArray);
+}
+
+JNIEXPORT void JNICALL Java_net_sourceforge_zbar_Image_setData___3I(
+ JNIEnv *env, jobject obj, jintArray data)
+{
+ jint *raw = NULL;
+ unsigned long rawlen = 0;
+ if (data) {
+ raw = (*env)->GetIntArrayElements(env, data, NULL);
+ if (!raw)
+ return;
+ rawlen = (*env)->GetArrayLength(env, data) * sizeof(*raw);
+ }
+ Image_setData(env, obj, data, raw, rawlen, Image_cleanupIntArray);
+}
+
+JNIEXPORT jlong JNICALL Java_net_sourceforge_zbar_Image_getSymbols(JNIEnv *env,
+ jobject obj,
+ jlong peer)
+{
+ const zbar_symbol_set_t *zsyms = zbar_image_get_symbols(PEER_CAST(peer));
+ if (zsyms) {
+ zbar_symbol_set_ref(zsyms, 1);
+ stats.SymbolSet_create++;
+ }
+ return ((intptr_t)zsyms);
+}
+
+JNIEXPORT void JNICALL Java_net_sourceforge_zbar_ImageScanner_init(JNIEnv *env,
+ jclass cls)
+{
+ ImageScanner_peer = (*env)->GetFieldID(env, cls, "peer", "J");
+}
+
+JNIEXPORT jlong JNICALL
+Java_net_sourceforge_zbar_ImageScanner_create(JNIEnv *env, jobject obj)
+{
+ zbar_image_scanner_t *zscn = zbar_image_scanner_create();
+ if (!zscn) {
+ throw_exc(env, "java/lang/OutOfMemoryError", NULL);
+ return (0);
+ }
+ stats.ImageScanner_create++;
+ return ((intptr_t)zscn);
+}
+
+JNIEXPORT void JNICALL Java_net_sourceforge_zbar_ImageScanner_destroy(
+ JNIEnv *env, jobject obj, jlong peer)
+{
+ zbar_image_scanner_destroy(PEER_CAST(peer));
+ stats.ImageScanner_destroy++;
+}
+
+JNIEXPORT void JNICALL Java_net_sourceforge_zbar_ImageScanner_setConfig(
+ JNIEnv *env, jobject obj, jint symbology, jint config, jint value)
+{
+ zbar_image_scanner_set_config(GET_PEER(ImageScanner, obj), symbology,
+ config, value);
+}
+
+JNIEXPORT void JNICALL Java_net_sourceforge_zbar_ImageScanner_parseConfig(
+ JNIEnv *env, jobject obj, jstring cfg)
+{
+ const char *cfgstr = (*env)->GetStringUTFChars(env, cfg, NULL);
+ if (!cfgstr)
+ return;
+ if (zbar_image_scanner_parse_config(GET_PEER(ImageScanner, obj), cfgstr))
+ throw_exc(env, "java/lang/IllegalArgumentException",
+ "unknown configuration");
+}
+
+JNIEXPORT void JNICALL Java_net_sourceforge_zbar_ImageScanner_enableCache(
+ JNIEnv *env, jobject obj, jboolean enable)
+{
+ zbar_image_scanner_enable_cache(GET_PEER(ImageScanner, obj), enable);
+}
+
+JNIEXPORT jlong JNICALL Java_net_sourceforge_zbar_ImageScanner_getResults(
+ JNIEnv *env, jobject obj, jlong peer)
+{
+ const zbar_symbol_set_t *zsyms =
+ zbar_image_scanner_get_results(PEER_CAST(peer));
+ if (zsyms) {
+ zbar_symbol_set_ref(zsyms, 1);
+ stats.SymbolSet_create++;
+ }
+ return ((intptr_t)zsyms);
+}
+
+JNIEXPORT jint JNICALL Java_net_sourceforge_zbar_ImageScanner_scanImage(
+ JNIEnv *env, jobject obj, jobject image)
+{
+ zbar_image_scanner_t *zscn = GET_PEER(ImageScanner, obj);
+ zbar_image_t *zimg = GET_PEER(Image, image);
+
+ int n = zbar_scan_image(zscn, zimg);
+ if (n < 0)
+ throw_exc(env, "java/lang/UnsupportedOperationException",
+ "unsupported image format");
+ return (n);
+}