diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-03-09 00:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-03-09 00:06:44 +0000 |
commit | 44cf8ec67278bd1ab6c7f83a9993f7a5686a9541 (patch) | |
tree | 5eec4b0d1a3f163d279c3c27c03324ba49fa235a /java | |
parent | Initial commit. (diff) | |
download | zbar-upstream.tar.xz zbar-upstream.zip |
Adding upstream version 0.23.93.upstream/0.23.93upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'java')
-rw-r--r-- | java/Makefile.am | 59 | ||||
-rw-r--r-- | java/net/sourceforge/zbar/Config.java | 56 | ||||
-rw-r--r-- | java/net/sourceforge/zbar/Image.java | 163 | ||||
-rw-r--r-- | java/net/sourceforge/zbar/ImageScanner.java | 98 | ||||
-rw-r--r-- | java/net/sourceforge/zbar/Modifier.java | 42 | ||||
-rw-r--r-- | java/net/sourceforge/zbar/Orientation.java | 42 | ||||
-rw-r--r-- | java/net/sourceforge/zbar/Symbol.java | 199 | ||||
-rw-r--r-- | java/net/sourceforge/zbar/SymbolIterator.java | 70 | ||||
-rw-r--r-- | java/net/sourceforge/zbar/SymbolSet.java | 82 | ||||
-rw-r--r-- | java/test/TestImage.java | 175 | ||||
-rw-r--r-- | java/test/TestImageScanner.java | 53 | ||||
-rw-r--r-- | java/test/TestScanImage.java | 183 | ||||
-rw-r--r-- | java/zbarjni.c | 618 |
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); +} |