Update to the very latest version of zbar
zbar was using a 2010 snapshot of its hg tree. Take a new snapshot to get zbar's improvements. [Imported from Fedora 26 tree]
This commit is contained in:
parent
1c1f76ea81
commit
cd5b63e5b5
17
.hgignore
17
.hgignore
@ -7,7 +7,7 @@ aclocal.m4
|
||||
configure
|
||||
config
|
||||
config.guess
|
||||
config.h
|
||||
config/config.h
|
||||
config.h.in
|
||||
config.log
|
||||
config.status
|
||||
@ -19,3 +19,18 @@ libtool
|
||||
ltmain.sh
|
||||
autom4te.cache
|
||||
missing
|
||||
python/MANIFEST
|
||||
build
|
||||
*.xcodeproj/*.mode1v3
|
||||
*.xcodeproj/*.pbxuser
|
||||
xcuserdata
|
||||
contents.xcworkspacedata
|
||||
.DS_Store
|
||||
android/obj
|
||||
*.class
|
||||
*.dex
|
||||
android/libs
|
||||
android/examples/*/libs
|
||||
android/*.zip
|
||||
android/local.properties
|
||||
android/examples/*/local.properties
|
||||
|
||||
18
.hgtags
18
.hgtags
@ -9,3 +9,21 @@ f0aa6bf0cab7fda8725ce0da35d3e69473269c71 0.8
|
||||
38265c7b4ad4dfafe7b5e9eae4bb0d43d68b4143 0.9
|
||||
2dc2d73c468a032edc68a127e9ddbbfe5f520777 0.9
|
||||
f3670ba47f2e070f4c43e97f4de3200903720e73 0.10
|
||||
f3670ba47f2e070f4c43e97f4de3200903720e73 0.10
|
||||
563557a923d0e23e36c81878d660aefc1c0fe3e7 0.10
|
||||
b21098d27ff88c4f1a529fe0762f1cb307e04399 iPhoneSDK-0.1
|
||||
b0bda6247b2fe4ffb52db89a776f91244f25d897 iPhoneSDK-0.1.1
|
||||
d1655a680c3df68b3466d3b2c714f30af7223ec6 iPhoneSDK-0.1.2
|
||||
4556c996acaaa6fcd5e8e9879f410f8120746e2b iPhoneSDK-1.0
|
||||
12de07e51dce0d1cfc3e9699bbf9d5c8774a5371 iPhoneSDK-1.0.1
|
||||
12de07e51dce0d1cfc3e9699bbf9d5c8774a5371 iPhoneSDK-1.0.1
|
||||
2541a66ae7d64fbd923168ae677abb156021e88d iPhoneSDK-1.0.1
|
||||
5e5060b563a1878ea297af5a50261d14cf1cb449 iPhoneSDK-1.1
|
||||
f9e46865dbcebd04683ca7592ab32aeda615e772 iPhoneSDK-1.1.1
|
||||
801318a6195060c31259da1f076ecc9a609616cc iPhoneSDK-1.1.2
|
||||
4bbb4e2bdba8c41a282df7e65a02797250f44daa iPhoneSDK-1.1.3
|
||||
1ad84c3c03252c366a82552fa952674ec593c73f iPhoneSDK-1.2
|
||||
9e7bad13ae6a4b65e0f0964512f96284d37f0dc8 iPhoneSDK-1.2.1
|
||||
146b857ff41ae462cc52f8dddf46d867763433a1 iPhoneSDK-1.2.2
|
||||
9b946a7ead73ac99e121de2e7f495213cda88e6f AndroidSDK-0.1
|
||||
5eb3c8786845fe3ad2c74f6a660e70176b88347f iPhoneSDK-1.3.1
|
||||
|
||||
2
COPYING
2
COPYING
@ -1,4 +1,4 @@
|
||||
The ZBar Bar Code Reader is Copyright (C) 2007-2009 Jeff Brown
|
||||
The ZBar Bar Code Reader is Copyright (C) 2007-2011 Jeff Brown
|
||||
<spadix@users.sourceforge.net>
|
||||
The QR Code reader is Copyright (C) 1999-2009 Timothy B. Terriberry
|
||||
<tterribe@xiph.org>
|
||||
|
||||
92
ChangeLog
92
ChangeLog
@ -1,3 +1,95 @@
|
||||
current:
|
||||
* Codabar reliability enhancements
|
||||
- fix missing check
|
||||
- require minimum quality
|
||||
- bump default uncertainty
|
||||
* tweak Codabar bar/space ratio validation
|
||||
* finish Codabar support for python, perl, java and iPhone interfaces
|
||||
- reduce Codabar uncertainty to minimum
|
||||
* add core support for Codabar symbology
|
||||
- TBD: python, perl, java and iPhone interfaces
|
||||
* fix v4l config and build variations (bug #3348888)
|
||||
- thanks to jarekczek for reporting this!
|
||||
- NB v4l1 removed from kernel as of 2.6.38
|
||||
* fix missing python thread initialization (bug #3349199)
|
||||
- thanks to jarekczek for reporting this problem!
|
||||
* fix missing configure check for Python.h (bug #3092663)
|
||||
- thanks to Zoltan Kovacs for reporting this problem!
|
||||
* fix C++ wrapper missing Symbol.quality (bug #3076524)
|
||||
- thanks to Rudy Melli for pointing this out!
|
||||
* fix C++ wrapper bugs (bug #3396068)
|
||||
- thanks to anotheruser1 for reporting this!
|
||||
- add new C++ wrapper test
|
||||
* fix avoid compositing ISBN10 data
|
||||
* add support for GraphicsMagick as ImageMagick alternative
|
||||
* mention xmlto in HACKING (patch #3297039)
|
||||
- thanks to jarekczek for the patch!
|
||||
* disable addons by default until synchronization with main symbol is working
|
||||
* fix image scanner min quality filtering
|
||||
* fix i25 buffer overrun corner case
|
||||
* fix EAN addon enables
|
||||
* fix zbarimg to accept autodetected stdin (lone dash)
|
||||
* fix Qt 4.6.3 compilation error (patch #3178244)
|
||||
- thanks to hrhristov for the patch!
|
||||
* add Python Processor support for request_size interface
|
||||
* fix Python Processor support for GIL, allowing asynchronous scanning
|
||||
* fix jpeg decoder skip handling
|
||||
- thanks to jarekczek for the patch!
|
||||
* rename dprintf macro to avoid conflicts (patch #3128538)
|
||||
- thanks to maurochehab for the patch!
|
||||
* add support for EAN/UPC 2 and 5 digit add-on symbols
|
||||
- deprecate original, unfinished add-on APIs
|
||||
- add self-checking to test_decode
|
||||
* fix support for GS1 AIs
|
||||
- thanks to jockusch for a patch!
|
||||
- add decoder/symbol "modifier" flags and config read access
|
||||
- set flags or emit GS appropriately for Code 128 FNC1
|
||||
- add iphone, java, perl, python bindings for modifiers and configs
|
||||
* add support for Code 93 symbology
|
||||
* add video size request to (Py)GTK widget (req #3034522)
|
||||
- thanks to Jerome Charaoui for the patch!
|
||||
* add support for GS1 DataBar Expanded (RSS Expanded) symbology
|
||||
* add language bindings for DataBar
|
||||
* add preliminary support for GS1 DataBar (RSS-14) symbology
|
||||
* enhance decoder reliability (EAN, Code 39, Code 128)
|
||||
- enhance decoder test
|
||||
* fix documentation of command exit codes (bug #3017322)
|
||||
* fix C++ video callback bug
|
||||
- add C and C++ processor examples
|
||||
* add per-symbology cache consistency
|
||||
- reliable symbologies decode immediately by default
|
||||
- no more need to disable cache with video
|
||||
- also fix crop bugs w/video scanning
|
||||
* add support for scanning partial images (cropping)
|
||||
- update c++, python, perl, java bindings and tests
|
||||
* fix couple of leaks
|
||||
* remove doc hints about GFDL (bug #3004411)
|
||||
- apply LGPL to API docs
|
||||
* relax Code 39 width ratio checks
|
||||
* core library portability improvements
|
||||
- remove some unnecessary C99 syntax
|
||||
- add configure checks for errno
|
||||
- enhance C++ Symbol interface
|
||||
* adjust Python module README (add examples and note DLL in path)
|
||||
* fix QR Code missing from man pages (bug #2969857)
|
||||
* cleanup decoder assertions and locking (bug #2966916)
|
||||
* add Java interface to library via JNI
|
||||
- add Java tools and JNI build tests to configure
|
||||
- fix compiler warnings from binary output changes
|
||||
* fix output of binary data in zbarimg and zbarcam
|
||||
- thanks to fukuchi for a patch!
|
||||
- add base64 format for binary xml output
|
||||
* add coarse symbol orientation information (patch #2913094)
|
||||
- thanks to Anssi for a patch!
|
||||
- add decode direction feedback to decoder
|
||||
- update C++, Python, Perl and ObjC wrappers
|
||||
- add orientation to test suites
|
||||
* fix inconsistent fourcc endian handling bugs (bug #2918994)
|
||||
- thanks to jdccdevel for a patch!
|
||||
- add fourcc conversion and parse interfaces to zbar.h
|
||||
* report QR immediately for video (no inter-frame consistency check)
|
||||
* add python distutils build infrastructure
|
||||
|
||||
version 0.10:
|
||||
* hotfix add MinGW import lib to Windows installer
|
||||
* attempt fix for Qt4 < 4.4
|
||||
|
||||
6
HACKING
6
HACKING
@ -13,6 +13,12 @@ be fine):
|
||||
GNU autoconf 2.61
|
||||
GNU automake 1.10.1
|
||||
GNU libtool 2.2.6
|
||||
GNU gettext 0.18.1.1
|
||||
GNU pkg-config 0.25
|
||||
xmlto 0.0.20-5 (for docs building)
|
||||
all above mentioned tools (except xmlto) must be installed in the same
|
||||
prefix. mixing prefixes (i.g. /usr/bin and /usr/local/bin) may lead to
|
||||
errors in configuration stages
|
||||
|
||||
when you're done hacking and want to make your patch, run:
|
||||
|
||||
|
||||
15
Makefile.am
15
Makefile.am
@ -1,6 +1,3 @@
|
||||
AM_CPPFLAGS = -I$(srcdir)/include
|
||||
AM_CFLAGS = -Wall -Wno-parentheses
|
||||
AM_CXXFLAGS = $(AM_CFLAGS)
|
||||
ACLOCAL_AMFLAGS = -I config
|
||||
bin_PROGRAMS =
|
||||
check_PROGRAMS =
|
||||
@ -9,8 +6,10 @@ lib_LTLIBRARIES =
|
||||
pyexec_LTLIBRARIES =
|
||||
CLEANFILES =
|
||||
DISTCLEANFILES =
|
||||
MAINTAINERCLEANFILES =
|
||||
BUILT_SOURCES =
|
||||
EXTRA_DIST =
|
||||
SUBDIRS = .
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = zbar.pc
|
||||
@ -39,6 +38,9 @@ if HAVE_QT
|
||||
include $(srcdir)/qt/Makefile.am.inc
|
||||
pkgconfig_DATA += zbar-qt.pc
|
||||
endif
|
||||
if HAVE_JAVA
|
||||
SUBDIRS += java
|
||||
endif
|
||||
if HAVE_NPAPI
|
||||
include $(srcdir)/plugin/Makefile.am.inc
|
||||
endif
|
||||
@ -47,11 +49,8 @@ include $(srcdir)/doc/Makefile.am.inc
|
||||
|
||||
EXTRA_DIST += zbar.ico zbar.nsi
|
||||
|
||||
EXTRA_DIST += examples/upcrpc.pl examples/upcrpc.py examples/paginate.pl \
|
||||
examples/barcode.png examples/processor.pl examples/processor.py \
|
||||
examples/read_one.py examples/read_one.pl \
|
||||
examples/scan_image.c examples/scan_image.cpp examples/scan_image.pl \
|
||||
examples/scan_image.py examples/scan_image.vcproj
|
||||
EXTRA_DIST += examples/barcode.png examples/upcrpc.py examples/upcrpc.pl \
|
||||
examples/scan_image.c examples/scan_image.cpp examples/scan_image.vcproj
|
||||
|
||||
EXTRA_DIST += perl/MANIFEST perl/README perl/Changes perl/COPYING.LIB \
|
||||
perl/Makefile.PL perl/typemap perl/ZBar.xs perl/ppport.h \
|
||||
|
||||
6
README
6
README
@ -4,9 +4,9 @@ ZBAR BAR CODE READER
|
||||
ZBar Bar Code Reader is an open source software suite for reading bar
|
||||
codes from various sources, such as video streams, image files and raw
|
||||
intensity sensors. It supports EAN-13/UPC-A, UPC-E, EAN-8, Code 128,
|
||||
Code 39, Interleaved 2 of 5 and QR Code. Included with the library
|
||||
are basic applications for decoding captured bar code images and using
|
||||
a video device (eg, webcam) as a bar code scanner. For application
|
||||
Code 39, Codabar, Interleaved 2 of 5 and QR Code. Included with the
|
||||
library are basic applications for decoding captured bar code images and
|
||||
using a video device (eg, webcam) as a bar code scanner. For application
|
||||
developers, language bindings are included for C, C++, Python and Perl
|
||||
as well as GUI widgets for Qt, GTK and PyGTK.
|
||||
|
||||
|
||||
@ -3,8 +3,8 @@ ZBAR BAR CODE READER
|
||||
|
||||
ZBar Bar Code Reader is an open source software suite for reading bar codes
|
||||
from various sources, such as video streams, image files and raw intensity
|
||||
sensors. It supports EAN-13/UPC-A, UPC-E, EAN-8, Code 128, Code 39,
|
||||
Interleaved 2 of 5 and QR Code. Included with the library are basic
|
||||
sensors. It supports EAN-13/UPC-A, UPC-E, EAN-8, Code 128, Code 93, Code 39,
|
||||
Codabar, Interleaved 2 of 5 and QR Code. Included with the library are basic
|
||||
applications for decoding captured bar code images and using a video device
|
||||
(eg, webcam) as a bar code scanner. For application developers, language
|
||||
bindings are included for C, C++, Python and Perl as well as GUI widgets for
|
||||
|
||||
1
TODO
1
TODO
@ -25,7 +25,6 @@ symbologies:
|
||||
* Code 39, i25 optional features (check digit and ASCII escapes)
|
||||
* handle Code 128 function characters (FNC1-4)
|
||||
* Code 128 trailing quiet zone checks
|
||||
* finish addon decoding
|
||||
|
||||
decoder:
|
||||
* start/stop/abort and location detail APIs (PDF417, OMR)
|
||||
|
||||
15
android/AndroidManifest.xml
Normal file
15
android/AndroidManifest.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="net.sourceforge.zbar.android"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
<application android:label="@string/app_name" >
|
||||
<activity android:name="ACTIVITY_ENTRY_NAME"
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
2
android/ChangeLog
Normal file
2
android/ChangeLog
Normal file
@ -0,0 +1,2 @@
|
||||
version 0.1:
|
||||
* Add initial support for Android platform
|
||||
112
android/README
Normal file
112
android/README
Normal file
@ -0,0 +1,112 @@
|
||||
ZBar Android SDK
|
||||
================
|
||||
|
||||
ZBar Bar Code Reader is an open source software suite for reading bar
|
||||
codes from various sources, such as video streams, image files and raw
|
||||
intensity sensors. It supports EAN-13/UPC-A, UPC-E, EAN-8, Code 128,
|
||||
Code 93, Code 39, Codabar, Interleaved 2 of 5, QR Code and
|
||||
DataBar. These are the JNI wrappers for developing the library on
|
||||
Android platform.
|
||||
|
||||
Check the ZBar home page for the latest release, mailing lists, etc.
|
||||
http://zbar.sourceforge.net/
|
||||
|
||||
Copyright and License
|
||||
---------------------
|
||||
Licensed under the GNU Lesser General Public License, version 2.1.
|
||||
http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
|
||||
Copyright 2008-2012 © Jeff Brown <spadix@users.sourceforge.net> et al
|
||||
|
||||
The Android distribution also includes pre-compiled binaries of
|
||||
supporting libaries, for which copyright, license and source code
|
||||
locations are as follows:
|
||||
* The GNU libiconv character set conversion library
|
||||
Copyright (C) 1999-2011 Free Software Foundation, Inc.
|
||||
This distribution includes GNU libiconv version 1.14, licensed under
|
||||
the LGPL version 2. The source code is available from
|
||||
http://www.gnu.org/software/libiconv
|
||||
|
||||
See included files COPYING and LICENSE for details.
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
After downloading the ZBar-Android-Lib-<version>.zip file, you need to
|
||||
unzip the file and add it to your Android project. Unzip the file
|
||||
using your favorite method (ie: command-line, finder, windows
|
||||
explorer...)
|
||||
|
||||
Follow one of the two options.
|
||||
Option 1 - via command line
|
||||
cd <android project>
|
||||
cp -r ZBar-Android-SDK-<version>/libs .
|
||||
|
||||
Option 2 - via Eclipse
|
||||
Right click on Android Project
|
||||
Select "Import" -> "File System"
|
||||
Select "Browse" (next to "From directory File" and select the
|
||||
ZBar-Android-SDK-<verion>/libs directory and click "Open".
|
||||
Click the check box next to "libs" and the "Options" "Create top-level folder"
|
||||
check box (below).
|
||||
Then click "Finish".
|
||||
|
||||
You should then see a "libs" folder under your project.
|
||||
|
||||
Building
|
||||
--------
|
||||
|
||||
Via Eclipse
|
||||
You have to add the zbar.jar file to your build path
|
||||
1) select zbar.jar under libs
|
||||
2) right-click, select "Build Path" -> "Add to Build Path"
|
||||
|
||||
Via command-line
|
||||
You are all set; ant will automatcially find jar files under the "libs"
|
||||
subdirectory.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
TDB
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
You should be able to open and build the examples directly from the
|
||||
unzipped directory. You will need to run the android tools to setup
|
||||
the local.properties file which sets sdk.dir.
|
||||
1) cd <unzip dir>/examples/CameraTest
|
||||
2) android update project --path .
|
||||
3) ant debug install
|
||||
|
||||
If you have problems with this, please create a new Android project
|
||||
and copy the necessary files from the examples.
|
||||
|
||||
examples/CameraTest is a simple demonstration of how to integrate the
|
||||
ZBar image scanner with the camera.
|
||||
|
||||
Manually building ZBar JNI library
|
||||
----------------------------------
|
||||
First download and unzip the iconv library source from
|
||||
http://www.gnu.org/software/libiconv/
|
||||
|
||||
Then kick off the build from the ZBar android directory. You will
|
||||
need to run the android tools to setup the local.properties file which
|
||||
setups sdk.dir.
|
||||
|
||||
1) cd <zbar project>/android
|
||||
2) android update project --path .
|
||||
3) ant -Dndk.dir=<NDK path> -Diconv.src=<iconv library src> zbar-all
|
||||
|
||||
This will rebuild all source files, create zbar.jar and
|
||||
ZBarAndroidSDK.zip file (which bundles the jar and shared
|
||||
libraries). From here, you can follow the steps for "Integrating ZBar
|
||||
JNI library in Android project".
|
||||
|
||||
To clean run:
|
||||
ant -Dndk.dir=<NDK path> zbar-clean
|
||||
|
||||
See build-ndk.xml for additional target options.
|
||||
|
||||
|
||||
17
android/ant.properties
Normal file
17
android/ant.properties
Normal file
@ -0,0 +1,17 @@
|
||||
# This file is used to override default values used by the Ant build system.
|
||||
#
|
||||
# This file must be checked in Version Control Systems, as it is
|
||||
# integral to the build system of your project.
|
||||
|
||||
# This file is only used by the Ant script.
|
||||
|
||||
# You can use this to override default values such as
|
||||
# 'source.dir' for the location of your java source folder and
|
||||
# 'out.dir' for the location of your output folder.
|
||||
|
||||
# You can also use it define how the release builds are signed by declaring
|
||||
# the following properties:
|
||||
# 'key.store' for the location of your keystore and
|
||||
# 'key.alias' for the name of the key to use.
|
||||
# The password will be asked during the build when you use the 'release' target.
|
||||
|
||||
66
android/build-ndk.xml
Normal file
66
android/build-ndk.xml
Normal file
@ -0,0 +1,66 @@
|
||||
<!--
|
||||
Ant build file to compile the ZBar JNI files using Android NDK tool
|
||||
targets:
|
||||
zbar-clean - removes build generated files, build dir, jar and zip files
|
||||
zbar-ndk-build - builds the zbarjni and iconv shared libraries
|
||||
zbar-compile - builds the zbar java files
|
||||
zbar-jar - builds and jars the zbar java files
|
||||
zbar-zip - Creates ZBarAndroidSDK-x.y.zip of jar, .so, etc
|
||||
zbar-all - performs all the above :)
|
||||
-->
|
||||
<project name="zbar">
|
||||
<property name="project.name" value="zbar" />
|
||||
<property name="project.sdk.name" value="ZBarAndroidSDK" />
|
||||
|
||||
<target name="zbar-clean">
|
||||
<delete dir="../java/build"/>
|
||||
<delete file="libs/${project.name}.jar"/>
|
||||
<delete file="${ant.project.name}.zip"/>
|
||||
<exec executable="${ndk.dir}/ndk-build" failonerror="true">
|
||||
<arg value="clean"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="zbar-ndk-build">
|
||||
<exec executable="${ndk.dir}/ndk-build" failonerror="true">
|
||||
<arg value="ICONV_SRC=${iconv.src}" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="zbar-compile" depends="zbar-ndk-build">
|
||||
<mkdir dir="../java/build" />
|
||||
<javac srcdir="../java/net" destdir="../java/build" />
|
||||
</target>
|
||||
|
||||
<target name="zbar-jar" depends="zbar-compile">
|
||||
<jar destfile="libs/${project.name}.jar" basedir="../java/build">
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
<target name="zbar-zip">
|
||||
<if><condition><not><isset property="version"/></not></condition><then>
|
||||
<property name="version" value="0.2" />
|
||||
</then></if>
|
||||
<zip destfile="${project.sdk.name}-${version}.zip" >
|
||||
<zipfileset dir="../" prefix="${project.sdk.name}-${version}" includes="COPYING, LICENSE"/>
|
||||
<zipfileset dir="." prefix="${project.sdk.name}-${version}" includes="README"/>
|
||||
<zipfileset dir="libs" prefix="${project.sdk.name}-${version}/libs"/>
|
||||
<zipfileset dir="examples" prefix="${project.sdk.name}-${version}/examples"/>
|
||||
<zipfileset dir="libs" prefix="${project.sdk.name}-${version}/examples/CameraTest/libs"/>
|
||||
</zip>
|
||||
</target>
|
||||
|
||||
<target name="zbar-all" depends="zbar-jar">
|
||||
<if><condition><not><isset property="version"/></not></condition><then>
|
||||
<property name="version" value="0.2" />
|
||||
</then></if>
|
||||
<zip destfile="${project.sdk.name}-${version}.zip" >
|
||||
<zipfileset dir="../" prefix="${project.sdk.name}-${version}" includes="COPYING, LICENSE"/>
|
||||
<zipfileset dir="." prefix="${project.sdk.name}-${version}" includes="README"/>
|
||||
<zipfileset dir="libs" prefix="${project.sdk.name}-${version}/libs"/>
|
||||
<zipfileset dir="examples" prefix="${project.sdk.name}-${version}/examples"/>
|
||||
<zipfileset dir="libs" prefix="${project.sdk.name}-${version}/examples/CameraTest/libs"/>
|
||||
</zip>
|
||||
</target>
|
||||
</project>
|
||||
|
||||
86
android/build.xml
Normal file
86
android/build.xml
Normal file
@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="ZBarAndroidSDK" default="help">
|
||||
|
||||
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||
It contains the path to the SDK. It should *NOT* be checked into
|
||||
Version Control Systems. -->
|
||||
<property file="local.properties" />
|
||||
|
||||
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||
'android' tool to add properties to it.
|
||||
This is the place to change some Ant specific build properties.
|
||||
Here are some properties you may want to change/update:
|
||||
|
||||
source.dir
|
||||
The name of the source directory. Default is 'src'.
|
||||
out.dir
|
||||
The name of the output directory. Default is 'bin'.
|
||||
|
||||
For other overridable properties, look at the beginning of the rules
|
||||
files in the SDK, at tools/ant/build.xml
|
||||
|
||||
Properties related to the SDK location or the project target should
|
||||
be updated using the 'android' tool with the 'update' action.
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems.
|
||||
|
||||
-->
|
||||
<property file="ant.properties" />
|
||||
|
||||
<!-- The project.properties file is created and updated by the 'android'
|
||||
tool, as well as ADT.
|
||||
|
||||
This contains project specific properties such as project target, and library
|
||||
dependencies. Lower level build properties are stored in ant.properties
|
||||
(or in .classpath for Eclipse projects).
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems. -->
|
||||
<loadproperties srcFile="project.properties" />
|
||||
|
||||
<!-- quick check on sdk.dir -->
|
||||
<fail
|
||||
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through an env var"
|
||||
unless="sdk.dir"
|
||||
/>
|
||||
|
||||
|
||||
<!-- extension targets. Uncomment the ones where you want to do custom work
|
||||
in between standard targets -->
|
||||
<!--
|
||||
<target name="-pre-build">
|
||||
</target>
|
||||
<target name="-pre-compile">
|
||||
</target>
|
||||
|
||||
/* This is typically used for code obfuscation.
|
||||
Compiled code location: ${out.classes.absolute.dir}
|
||||
If this is not done in place, override ${out.dex.input.absolute.dir} */
|
||||
<target name="-post-compile">
|
||||
<copy file="${out.absolute.dir}/classes.jar" tofile="${jar.libs.dir}/zbar_android.jar" />
|
||||
</target>
|
||||
-->
|
||||
|
||||
<!-- Import the actual build file.
|
||||
|
||||
To customize existing targets, there are two options:
|
||||
- Customize only one target:
|
||||
- copy/paste the target into this file, *before* the
|
||||
<import> task.
|
||||
- customize it to your needs.
|
||||
- Customize the whole content of build.xml
|
||||
- copy/paste the content of the rules files (minus the top node)
|
||||
into this file, replacing the <import> task.
|
||||
- customize to your needs.
|
||||
|
||||
***********************
|
||||
****** IMPORTANT ******
|
||||
***********************
|
||||
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||
in order to avoid having your file be overridden by tools such as "android update project"
|
||||
-->
|
||||
<!-- version-tag: 1 -->
|
||||
<import file="build-ndk.xml" />
|
||||
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||
</project>
|
||||
19
android/examples/CameraTest/AndroidManifest.xml
Normal file
19
android/examples/CameraTest/AndroidManifest.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="net.sourceforge.zbar.android.CameraTest"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
<uses-sdk android:minSdkVersion="8" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-feature android:name="android.hardware.camera" />
|
||||
<uses-feature android:name="android.hardware.camera.autofocus" />
|
||||
<application android:label="@string/app_name" >
|
||||
<activity android:name="CameraTestActivity"
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
17
android/examples/CameraTest/ant.properties
Normal file
17
android/examples/CameraTest/ant.properties
Normal file
@ -0,0 +1,17 @@
|
||||
# This file is used to override default values used by the Ant build system.
|
||||
#
|
||||
# This file must be checked in Version Control Systems, as it is
|
||||
# integral to the build system of your project.
|
||||
|
||||
# This file is only used by the Ant script.
|
||||
|
||||
# You can use this to override default values such as
|
||||
# 'source.dir' for the location of your java source folder and
|
||||
# 'out.dir' for the location of your output folder.
|
||||
|
||||
# You can also use it define how the release builds are signed by declaring
|
||||
# the following properties:
|
||||
# 'key.store' for the location of your keystore and
|
||||
# 'key.alias' for the name of the key to use.
|
||||
# The password will be asked during the build when you use the 'release' target.
|
||||
|
||||
85
android/examples/CameraTest/build.xml
Normal file
85
android/examples/CameraTest/build.xml
Normal file
@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="CameraTest" default="help">
|
||||
|
||||
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||
It contains the path to the SDK. It should *NOT* be checked into
|
||||
Version Control Systems. -->
|
||||
<property file="local.properties" />
|
||||
|
||||
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||
'android' tool to add properties to it.
|
||||
This is the place to change some Ant specific build properties.
|
||||
Here are some properties you may want to change/update:
|
||||
|
||||
source.dir
|
||||
The name of the source directory. Default is 'src'.
|
||||
out.dir
|
||||
The name of the output directory. Default is 'bin'.
|
||||
|
||||
For other overridable properties, look at the beginning of the rules
|
||||
files in the SDK, at tools/ant/build.xml
|
||||
|
||||
Properties related to the SDK location or the project target should
|
||||
be updated using the 'android' tool with the 'update' action.
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems.
|
||||
|
||||
-->
|
||||
<property file="ant.properties" />
|
||||
|
||||
<!-- The project.properties file is created and updated by the 'android'
|
||||
tool, as well as ADT.
|
||||
|
||||
This contains project specific properties such as project target, and library
|
||||
dependencies. Lower level build properties are stored in ant.properties
|
||||
(or in .classpath for Eclipse projects).
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems. -->
|
||||
<loadproperties srcFile="project.properties" />
|
||||
|
||||
<!-- quick check on sdk.dir -->
|
||||
<fail
|
||||
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through an env var"
|
||||
unless="sdk.dir"
|
||||
/>
|
||||
|
||||
|
||||
<!-- extension targets. Uncomment the ones where you want to do custom work
|
||||
in between standard targets -->
|
||||
<!--
|
||||
<target name="-pre-build">
|
||||
</target>
|
||||
<target name="-pre-compile">
|
||||
</target>
|
||||
|
||||
/* This is typically used for code obfuscation.
|
||||
Compiled code location: ${out.classes.absolute.dir}
|
||||
If this is not done in place, override ${out.dex.input.absolute.dir} */
|
||||
<target name="-post-compile">
|
||||
</target>
|
||||
-->
|
||||
|
||||
<!-- Import the actual build file.
|
||||
|
||||
To customize existing targets, there are two options:
|
||||
- Customize only one target:
|
||||
- copy/paste the target into this file, *before* the
|
||||
<import> task.
|
||||
- customize it to your needs.
|
||||
- Customize the whole content of build.xml
|
||||
- copy/paste the content of the rules files (minus the top node)
|
||||
into this file, replacing the <import> task.
|
||||
- customize to your needs.
|
||||
|
||||
***********************
|
||||
****** IMPORTANT ******
|
||||
***********************
|
||||
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||
in order to avoid having your file be overridden by tools such as "android update project"
|
||||
-->
|
||||
<!-- version-tag: 1 -->
|
||||
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||
|
||||
</project>
|
||||
40
android/examples/CameraTest/proguard.cfg
Normal file
40
android/examples/CameraTest/proguard.cfg
Normal file
@ -0,0 +1,40 @@
|
||||
-optimizationpasses 5
|
||||
-dontusemixedcaseclassnames
|
||||
-dontskipnonpubliclibraryclasses
|
||||
-dontpreverify
|
||||
-verbose
|
||||
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
|
||||
|
||||
-keep public class * extends android.app.Activity
|
||||
-keep public class * extends android.app.Application
|
||||
-keep public class * extends android.app.Service
|
||||
-keep public class * extends android.content.BroadcastReceiver
|
||||
-keep public class * extends android.content.ContentProvider
|
||||
-keep public class * extends android.app.backup.BackupAgentHelper
|
||||
-keep public class * extends android.preference.Preference
|
||||
-keep public class com.android.vending.licensing.ILicensingService
|
||||
|
||||
-keepclasseswithmembernames class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
-keepclasseswithmembers class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet);
|
||||
}
|
||||
|
||||
-keepclasseswithmembers class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||
}
|
||||
|
||||
-keepclassmembers class * extends android.app.Activity {
|
||||
public void *(android.view.View);
|
||||
}
|
||||
|
||||
-keepclassmembers enum * {
|
||||
public static **[] values();
|
||||
public static ** valueOf(java.lang.String);
|
||||
}
|
||||
|
||||
-keep class * implements android.os.Parcelable {
|
||||
public static final android.os.Parcelable$Creator *;
|
||||
}
|
||||
11
android/examples/CameraTest/project.properties
Normal file
11
android/examples/CameraTest/project.properties
Normal file
@ -0,0 +1,11 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system use,
|
||||
# "ant.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
|
||||
# Project target.
|
||||
target=android-15
|
||||
28
android/examples/CameraTest/res/layout/main.xml
Normal file
28
android/examples/CameraTest/res/layout/main.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/cameraPreview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/scanText"
|
||||
android:text="Scanning..."
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent">
|
||||
</TextView>
|
||||
<Button
|
||||
android:id="@+id/ScanButton"
|
||||
android:text="Scan"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
/>
|
||||
</LinearLayout>
|
||||
4
android/examples/CameraTest/res/values/strings.xml
Normal file
4
android/examples/CameraTest/res/values/strings.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">ZBar CameraTest</string>
|
||||
</resources>
|
||||
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Barebones implementation of displaying camera preview.
|
||||
*
|
||||
* Created by lisah0 on 2012-02-24
|
||||
*/
|
||||
package net.sourceforge.zbar.android.CameraTest;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.SurfaceHolder;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import android.hardware.Camera;
|
||||
import android.hardware.Camera.PreviewCallback;
|
||||
import android.hardware.Camera.AutoFocusCallback;
|
||||
import android.hardware.Camera.Parameters;
|
||||
|
||||
/** A basic Camera preview class */
|
||||
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
|
||||
private SurfaceHolder mHolder;
|
||||
private Camera mCamera;
|
||||
private PreviewCallback previewCallback;
|
||||
private AutoFocusCallback autoFocusCallback;
|
||||
|
||||
public CameraPreview(Context context, Camera camera,
|
||||
PreviewCallback previewCb,
|
||||
AutoFocusCallback autoFocusCb) {
|
||||
super(context);
|
||||
mCamera = camera;
|
||||
previewCallback = previewCb;
|
||||
autoFocusCallback = autoFocusCb;
|
||||
|
||||
/*
|
||||
* Set camera to continuous focus if supported, otherwise use
|
||||
* software auto-focus. Only works for API level >=9.
|
||||
*/
|
||||
/*
|
||||
Camera.Parameters parameters = camera.getParameters();
|
||||
for (String f : parameters.getSupportedFocusModes()) {
|
||||
if (f == Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) {
|
||||
mCamera.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
|
||||
autoFocusCallback = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Install a SurfaceHolder.Callback so we get notified when the
|
||||
// underlying surface is created and destroyed.
|
||||
mHolder = getHolder();
|
||||
mHolder.addCallback(this);
|
||||
|
||||
// deprecated setting, but required on Android versions prior to 3.0
|
||||
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
|
||||
}
|
||||
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
// The Surface has been created, now tell the camera where to draw the preview.
|
||||
try {
|
||||
mCamera.setPreviewDisplay(holder);
|
||||
} catch (IOException e) {
|
||||
Log.d("DBG", "Error setting camera preview: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
// Camera preview released in activity
|
||||
}
|
||||
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
||||
/*
|
||||
* If your preview can change or rotate, take care of those events here.
|
||||
* Make sure to stop the preview before resizing or reformatting it.
|
||||
*/
|
||||
if (mHolder.getSurface() == null){
|
||||
// preview surface does not exist
|
||||
return;
|
||||
}
|
||||
|
||||
// stop preview before making changes
|
||||
try {
|
||||
mCamera.stopPreview();
|
||||
} catch (Exception e){
|
||||
// ignore: tried to stop a non-existent preview
|
||||
}
|
||||
|
||||
try {
|
||||
// Hard code camera surface rotation 90 degs to match Activity view in portrait
|
||||
mCamera.setDisplayOrientation(90);
|
||||
|
||||
mCamera.setPreviewDisplay(mHolder);
|
||||
mCamera.setPreviewCallback(previewCallback);
|
||||
mCamera.startPreview();
|
||||
mCamera.autoFocus(autoFocusCallback);
|
||||
} catch (Exception e){
|
||||
Log.d("DBG", "Error starting camera preview: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Basic no frills app which integrates the ZBar barcode scanner with
|
||||
* the camera.
|
||||
*
|
||||
* Created by lisah0 on 2012-02-24
|
||||
*/
|
||||
package net.sourceforge.zbar.android.CameraTest;
|
||||
|
||||
import net.sourceforge.zbar.android.CameraTest.CameraPreview;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.Window;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.Button;
|
||||
|
||||
import android.hardware.Camera;
|
||||
import android.hardware.Camera.PreviewCallback;
|
||||
import android.hardware.Camera.AutoFocusCallback;
|
||||
import android.hardware.Camera.Parameters;
|
||||
import android.hardware.Camera.Size;
|
||||
|
||||
import android.widget.TextView;
|
||||
import android.graphics.ImageFormat;
|
||||
|
||||
/* Import ZBar Class files */
|
||||
import net.sourceforge.zbar.ImageScanner;
|
||||
import net.sourceforge.zbar.Image;
|
||||
import net.sourceforge.zbar.Symbol;
|
||||
import net.sourceforge.zbar.SymbolSet;
|
||||
import net.sourceforge.zbar.Config;
|
||||
|
||||
public class CameraTestActivity extends Activity
|
||||
{
|
||||
private Camera mCamera;
|
||||
private CameraPreview mPreview;
|
||||
private Handler autoFocusHandler;
|
||||
|
||||
TextView scanText;
|
||||
Button scanButton;
|
||||
|
||||
ImageScanner scanner;
|
||||
|
||||
private boolean barcodeScanned = false;
|
||||
private boolean previewing = true;
|
||||
|
||||
static {
|
||||
System.loadLibrary("iconv");
|
||||
}
|
||||
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.main);
|
||||
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
|
||||
|
||||
autoFocusHandler = new Handler();
|
||||
mCamera = getCameraInstance();
|
||||
|
||||
/* Instance barcode scanner */
|
||||
scanner = new ImageScanner();
|
||||
scanner.setConfig(0, Config.X_DENSITY, 3);
|
||||
scanner.setConfig(0, Config.Y_DENSITY, 3);
|
||||
|
||||
mPreview = new CameraPreview(this, mCamera, previewCb, autoFocusCB);
|
||||
FrameLayout preview = (FrameLayout)findViewById(R.id.cameraPreview);
|
||||
preview.addView(mPreview);
|
||||
|
||||
scanText = (TextView)findViewById(R.id.scanText);
|
||||
|
||||
scanButton = (Button)findViewById(R.id.ScanButton);
|
||||
|
||||
scanButton.setOnClickListener(new OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
if (barcodeScanned) {
|
||||
barcodeScanned = false;
|
||||
scanText.setText("Scanning...");
|
||||
mCamera.setPreviewCallback(previewCb);
|
||||
mCamera.startPreview();
|
||||
previewing = true;
|
||||
mCamera.autoFocus(autoFocusCB);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
releaseCamera();
|
||||
}
|
||||
|
||||
/** A safe way to get an instance of the Camera object. */
|
||||
public static Camera getCameraInstance(){
|
||||
Camera c = null;
|
||||
try {
|
||||
c = Camera.open();
|
||||
} catch (Exception e){
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
private void releaseCamera() {
|
||||
if (mCamera != null) {
|
||||
previewing = false;
|
||||
mCamera.setPreviewCallback(null);
|
||||
mCamera.release();
|
||||
mCamera = null;
|
||||
}
|
||||
}
|
||||
|
||||
private Runnable doAutoFocus = new Runnable() {
|
||||
public void run() {
|
||||
if (previewing)
|
||||
mCamera.autoFocus(autoFocusCB);
|
||||
}
|
||||
};
|
||||
|
||||
PreviewCallback previewCb = new PreviewCallback() {
|
||||
public void onPreviewFrame(byte[] data, Camera camera) {
|
||||
Camera.Parameters parameters = camera.getParameters();
|
||||
Size size = parameters.getPreviewSize();
|
||||
|
||||
Image barcode = new Image(size.width, size.height, "Y800");
|
||||
barcode.setData(data);
|
||||
|
||||
int result = scanner.scanImage(barcode);
|
||||
|
||||
if (result != 0) {
|
||||
previewing = false;
|
||||
mCamera.setPreviewCallback(null);
|
||||
mCamera.stopPreview();
|
||||
|
||||
SymbolSet syms = scanner.getResults();
|
||||
for (Symbol sym : syms) {
|
||||
scanText.setText("barcode result " + sym.getData());
|
||||
barcodeScanned = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Mimic continuous auto-focusing
|
||||
AutoFocusCallback autoFocusCB = new AutoFocusCallback() {
|
||||
public void onAutoFocus(boolean success, Camera camera) {
|
||||
autoFocusHandler.postDelayed(doAutoFocus, 1000);
|
||||
}
|
||||
};
|
||||
}
|
||||
76
android/jni/Android.mk
Normal file
76
android/jni/Android.mk
Normal file
@ -0,0 +1,76 @@
|
||||
#
|
||||
# Android NDK makefile
|
||||
#
|
||||
# build - <ndk path>/ndk-build ICONV_SRC=<iconv library src>
|
||||
# clean - <ndk path>/ndk-build clean
|
||||
#
|
||||
MY_LOCAL_PATH := $(call my-dir)
|
||||
|
||||
# libiconv
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_PATH := $(ICONV_SRC)
|
||||
|
||||
LOCAL_MODULE := libiconv
|
||||
|
||||
LOCAL_CFLAGS := \
|
||||
-Wno-multichar \
|
||||
-D_ANDROID \
|
||||
-DLIBDIR="c" \
|
||||
-DBUILDING_LIBICONV \
|
||||
-DBUILDING_LIBCHARSET \
|
||||
-DIN_LIBRARY
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
lib/iconv.c \
|
||||
libcharset/lib/localcharset.c \
|
||||
lib/relocatable.c
|
||||
|
||||
LOCAL_C_INCLUDES := \
|
||||
$(ICONV_SRC)/include \
|
||||
$(ICONV_SRC)/libcharset \
|
||||
$(ICONV_SRC)/libcharset/include
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
LOCAL_LDLIBS := -llog -lcharset
|
||||
|
||||
# libzbarjni
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_PATH := $(MY_LOCAL_PATH)
|
||||
LOCAL_MODULE := zbarjni
|
||||
LOCAL_SRC_FILES := ../../java/zbarjni.c \
|
||||
../../zbar/img_scanner.c \
|
||||
../../zbar/decoder.c \
|
||||
../../zbar/image.c \
|
||||
../../zbar/symbol.c \
|
||||
../../zbar/convert.c \
|
||||
../../zbar/config.c \
|
||||
../../zbar/scanner.c \
|
||||
../../zbar/error.c \
|
||||
../../zbar/refcnt.c \
|
||||
../../zbar/video.c \
|
||||
../../zbar/video/null.c \
|
||||
../../zbar/decoder/code128.c \
|
||||
../../zbar/decoder/code39.c \
|
||||
../../zbar/decoder/code93.c \
|
||||
../../zbar/decoder/codabar.c \
|
||||
../../zbar/decoder/databar.c \
|
||||
../../zbar/decoder/ean.c \
|
||||
../../zbar/decoder/i25.c \
|
||||
../../zbar/decoder/qr_finder.c \
|
||||
../../zbar/qrcode/bch15_5.c \
|
||||
../../zbar/qrcode/binarize.c \
|
||||
../../zbar/qrcode/isaac.c \
|
||||
../../zbar/qrcode/qrdec.c \
|
||||
../../zbar/qrcode/qrdectxt.c \
|
||||
../../zbar/qrcode/rs.c \
|
||||
../../zbar/qrcode/util.c
|
||||
|
||||
LOCAL_C_INCLUDES := ../include \
|
||||
../zbar \
|
||||
$(ICONV_SRC)/include
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := libiconv
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
1
android/jni/Application.mk
Normal file
1
android/jni/Application.mk
Normal file
@ -0,0 +1 @@
|
||||
APP_ABI := armeabi armeabi-v7a x86
|
||||
236
android/jni/config.h
Normal file
236
android/jni/config.h
Normal file
@ -0,0 +1,236 @@
|
||||
/* manually customized for iPhone platform */
|
||||
|
||||
#define HAVE_LANGINFO_CODESET 0
|
||||
|
||||
/* whether to build support for Code 128 symbology */
|
||||
#define ENABLE_CODE128 1
|
||||
|
||||
/* whether to build support for Code 93 symbology */
|
||||
#define ENABLE_CODE93 1
|
||||
|
||||
/* whether to build support for Code 39 symbology */
|
||||
#define ENABLE_CODE39 1
|
||||
|
||||
/* whether to build support for Codabar symbology */
|
||||
#define ENABLE_CODABAR 1
|
||||
|
||||
/* whether to build support for DataBar symbology */
|
||||
#define ENABLE_DATABAR 1
|
||||
|
||||
/* whether to build support for EAN symbologies */
|
||||
#define ENABLE_EAN 1
|
||||
|
||||
/* whether to build support for Interleaved 2 of 5 symbology */
|
||||
#define ENABLE_I25 1
|
||||
|
||||
/* whether to build support for PDF417 symbology */
|
||||
#undef ENABLE_PDF417
|
||||
|
||||
/* whether to build support for QR Code */
|
||||
#define ENABLE_QRCODE 1
|
||||
|
||||
/* Define to 1 if you have the `atexit' function. */
|
||||
#undef HAVE_ATEXIT
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#undef HAVE_DLFCN_H
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#undef HAVE_FCNTL_H
|
||||
|
||||
/* Define to 1 if you have the <features.h> header file. */
|
||||
#undef HAVE_FEATURES_H
|
||||
|
||||
/* Define to 1 if you have the `getpagesize' function. */
|
||||
#undef HAVE_GETPAGESIZE
|
||||
|
||||
/* Define if you have the iconv() function and it works. */
|
||||
#undef HAVE_ICONV
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <jpeglib.h> header file. */
|
||||
#undef HAVE_JPEGLIB_H
|
||||
|
||||
/* Define to 1 if you have the `jpeg' library (-ljpeg). */
|
||||
#undef HAVE_LIBJPEG
|
||||
|
||||
/* Define to 1 if you have the `pthread' library (-lpthread). */
|
||||
#undef HAVE_LIBPTHREAD
|
||||
|
||||
/* Define to 1 if you have the <linux/videodev2.h> header file. */
|
||||
#undef HAVE_LINUX_VIDEODEV2_H
|
||||
|
||||
/* Define to 1 if you have the <linux/videodev.h> header file. */
|
||||
#undef HAVE_LINUX_VIDEODEV_H
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the `memset' function. */
|
||||
#define HAVE_MEMSET 1
|
||||
|
||||
/* Define to 1 if you have a working `mmap' system call. */
|
||||
#undef HAVE_MMAP
|
||||
|
||||
/* Define to 1 if you have the <poll.h> header file. */
|
||||
#undef HAVE_POLL_H
|
||||
|
||||
/* Define to 1 if you have the <pthread.h> header file. */
|
||||
#undef HAVE_PTHREAD_H
|
||||
|
||||
/* Define to 1 if you have the `setenv' function. */
|
||||
#undef HAVE_SETENV
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||
#undef HAVE_SYS_IOCTL_H
|
||||
|
||||
/* Define to 1 if you have the <sys/ipc.h> header file. */
|
||||
#undef HAVE_SYS_IPC_H
|
||||
|
||||
/* Define to 1 if you have the <sys/mman.h> header file. */
|
||||
#undef HAVE_SYS_MMAN_H
|
||||
|
||||
/* Define to 1 if you have the <sys/shm.h> header file. */
|
||||
#undef HAVE_SYS_SHM_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/times.h> header file. */
|
||||
#define HAVE_SYS_TIMES_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#define HAVE_SYS_TIME_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if the system has the type `uintptr_t'. */
|
||||
#define HAVE_UINTPTR_T 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to 1 if you have the <vfw.h> header file. */
|
||||
#undef HAVE_VFW_H
|
||||
|
||||
/* Define to 1 if you have the <X11/extensions/XShm.h> header file. */
|
||||
#undef HAVE_X11_EXTENSIONS_XSHM_H
|
||||
|
||||
/* Define to 1 if you have the <X11/extensions/Xvlib.h> header file. */
|
||||
#undef HAVE_X11_EXTENSIONS_XVLIB_H
|
||||
|
||||
/* Define as const if the declaration of iconv() needs const. */
|
||||
#undef ICONV_CONST
|
||||
|
||||
/* Library major version */
|
||||
#define LIB_VERSION_MAJOR 0
|
||||
|
||||
/* Library minor version */
|
||||
#define LIB_VERSION_MINOR 2
|
||||
|
||||
/* Library revision */
|
||||
#define LIB_VERSION_REVISION 0
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#undef LT_OBJDIR
|
||||
|
||||
/* Define to 1 if assertions should be disabled. */
|
||||
//#undef NDEBUG
|
||||
|
||||
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
|
||||
#undef NO_MINUS_C_MINUS_O
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "zbar"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT "spadix@users.sourceforge.net"
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "zbar"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "zbar 0.10"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "zbar"
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "0.10"
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "0.10"
|
||||
|
||||
/* Define to 1 if the X Window System is missing or not being used. */
|
||||
#define X_DISPLAY_MISSING 1
|
||||
|
||||
/* Program major version (before the '.') as a number */
|
||||
#define ZBAR_VERSION_MAJOR 0
|
||||
|
||||
/* Program minor version (after '.') as a number */
|
||||
#define ZBAR_VERSION_MINOR 10
|
||||
|
||||
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
|
||||
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
|
||||
#define below would cause a syntax error. */
|
||||
#undef _UINT32_T
|
||||
|
||||
/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
|
||||
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
|
||||
#define below would cause a syntax error. */
|
||||
#undef _UINT8_T
|
||||
|
||||
/* Minimum Windows API version */
|
||||
#undef _WIN32_WINNT
|
||||
|
||||
/* used only for pthread debug attributes */
|
||||
#undef __USE_UNIX98
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
#undef const
|
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
#ifndef __cplusplus
|
||||
#undef inline
|
||||
#endif
|
||||
|
||||
/* Define to the type of a signed integer type of width exactly 32 bits if
|
||||
such a type exists and the standard includes do not define it. */
|
||||
#undef int32_t
|
||||
|
||||
/* Define to the type of an unsigned integer type of width exactly 32 bits if
|
||||
such a type exists and the standard includes do not define it. */
|
||||
#undef uint32_t
|
||||
|
||||
/* Define to the type of an unsigned integer type of width exactly 8 bits if
|
||||
such a type exists and the standard includes do not define it. */
|
||||
#undef uint8_t
|
||||
|
||||
/* Define to the type of an unsigned integer type wide enough to hold a
|
||||
pointer, if such a type exists, and if the system does not define it. */
|
||||
#undef uintptr_t
|
||||
|
||||
#ifndef X_DISPLAY_MISSING
|
||||
# define HAVE_X
|
||||
#endif
|
||||
|
||||
40
android/proguard.cfg
Normal file
40
android/proguard.cfg
Normal file
@ -0,0 +1,40 @@
|
||||
-optimizationpasses 5
|
||||
-dontusemixedcaseclassnames
|
||||
-dontskipnonpubliclibraryclasses
|
||||
-dontpreverify
|
||||
-verbose
|
||||
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
|
||||
|
||||
-keep public class * extends android.app.Activity
|
||||
-keep public class * extends android.app.Application
|
||||
-keep public class * extends android.app.Service
|
||||
-keep public class * extends android.content.BroadcastReceiver
|
||||
-keep public class * extends android.content.ContentProvider
|
||||
-keep public class * extends android.app.backup.BackupAgentHelper
|
||||
-keep public class * extends android.preference.Preference
|
||||
-keep public class com.android.vending.licensing.ILicensingService
|
||||
|
||||
-keepclasseswithmembernames class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
-keepclasseswithmembers class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet);
|
||||
}
|
||||
|
||||
-keepclasseswithmembers class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||
}
|
||||
|
||||
-keepclassmembers class * extends android.app.Activity {
|
||||
public void *(android.view.View);
|
||||
}
|
||||
|
||||
-keepclassmembers enum * {
|
||||
public static **[] values();
|
||||
public static ** valueOf(java.lang.String);
|
||||
}
|
||||
|
||||
-keep class * implements android.os.Parcelable {
|
||||
public static final android.os.Parcelable$Creator *;
|
||||
}
|
||||
12
android/project.properties
Normal file
12
android/project.properties
Normal file
@ -0,0 +1,12 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system use,
|
||||
# "ant.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
|
||||
android.library=true
|
||||
# Project target.
|
||||
target=android-8
|
||||
13
android/res/layout/main.xml
Normal file
13
android/res/layout/main.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
>
|
||||
<TextView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hello World, ACTIVITY_ENTRY_NAME"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
4
android/res/values/strings.xml
Normal file
4
android/res/values/strings.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">ACTIVITY_ENTRY_NAME</string>
|
||||
</resources>
|
||||
228
configure.ac
228
configure.ac
@ -46,6 +46,13 @@ AC_DEFINE_UNQUOTED([LIB_VERSION_REVISION],
|
||||
[[`echo "$LIB_VERSION" | sed -e 's/^[^:]*:\([^:]*\):.*$/\1/'`]],
|
||||
[Library revision])
|
||||
|
||||
AM_CPPFLAGS="-I$srcdir/include"
|
||||
AM_CFLAGS="-Wall -Wno-parentheses -Werror"
|
||||
AM_CXXFLAGS="$AM_CFLAGS"
|
||||
AC_SUBST([AM_CPPFLAGS])
|
||||
AC_SUBST([AM_CFLAGS])
|
||||
AC_SUBST([AM_CXXFLAGS])
|
||||
|
||||
dnl windows build
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
@ -73,13 +80,36 @@ documentation generation])
|
||||
AC_ARG_VAR([XMLTOFLAGS], [additional arguments for xmlto])
|
||||
AC_CHECK_PROGS([XMLTO], [xmlto], [:])
|
||||
|
||||
have_java="maybe"
|
||||
AC_ARG_VAR([JAVA_HOME], [root location of JDK])
|
||||
AS_IF([test "x$JAVA_HOME" = "x"],
|
||||
[JAVA_PATH="$PATH"],
|
||||
[JAVA_PATH="$JAVA_HOME/bin$PATH_SEPARATOR$PATH"])
|
||||
|
||||
AC_ARG_VAR([JAVAC], [location of Java language compiler])
|
||||
AC_PATH_PROGS([JAVAC], [javac jikes ecj gcj], [:], [$JAVA_PATH])
|
||||
AS_IF([test "x$JAVAC" = "x:"], [have_java="no"])
|
||||
|
||||
AC_ARG_VAR([JAVAH], [location of Java header generator])
|
||||
AC_PATH_PROGS([JAVAH], [javah], [/bin/false], [$JAVA_PATH])
|
||||
|
||||
AC_ARG_VAR([JAR], [location of Java archive tool])
|
||||
AC_PATH_PROGS([JAR], [jar], [:], [$JAVA_PATH])
|
||||
AS_IF([test "x$JAR" = "x:"], [have_java="no"])
|
||||
|
||||
AC_ARG_VAR([JAVA], [location of Java application launcher])
|
||||
AC_PATH_PROGS([JAVA], [java], [/bin/false], [$JAVA_PATH])
|
||||
|
||||
AC_ARG_VAR([CLASSPATH], [Java class path (include JUnit to run java tests)])
|
||||
AS_IF([test "x$CLASSPATH" = "x"], [CLASSPATH="."])
|
||||
|
||||
dnl symbologies
|
||||
|
||||
AC_ARG_ENABLE([codes],
|
||||
[AS_HELP_STRING([--enable-codes=SYMS],
|
||||
[select symbologies to compile [default=ean,i25,code39,code128,qrcode]])],
|
||||
[select symbologies to compile [default=ean,databar,code128,code93,code39,codabar,i25,qrcode]])],
|
||||
[],
|
||||
[enable_codes="ean,code39,code128,i25,qrcode"]) dnl pdf417
|
||||
[enable_codes="ean,databar,code128,code93,code39,codabar,i25,qrcode"])
|
||||
|
||||
AC_DEFUN([ZBAR_CHK_CODE], [
|
||||
AC_MSG_CHECKING([whether to build $2])
|
||||
@ -97,11 +127,14 @@ AC_DEFUN([ZBAR_CHK_CODE], [
|
||||
])dnl
|
||||
|
||||
ZBAR_CHK_CODE([ean], [EAN symbologies])
|
||||
ZBAR_CHK_CODE([databar], [DataBar symbology])
|
||||
ZBAR_CHK_CODE([code128], [Code 128 symbology])
|
||||
ZBAR_CHK_CODE([code93], [Code 93 symbology])
|
||||
ZBAR_CHK_CODE([code39], [Code 39 symbology])
|
||||
ZBAR_CHK_CODE([pdf417], [PDF417 symbology])
|
||||
ZBAR_CHK_CODE([codabar], [Codabar symbology])
|
||||
ZBAR_CHK_CODE([i25], [Interleaved 2 of 5 symbology])
|
||||
ZBAR_CHK_CODE([qrcode], [QR Code])
|
||||
ZBAR_CHK_CODE([pdf417], [PDF417 symbology])
|
||||
|
||||
dnl libraries
|
||||
|
||||
@ -144,16 +177,26 @@ AC_ARG_ENABLE([video],
|
||||
[],
|
||||
[enable_video="yes"])
|
||||
|
||||
with_video="no"
|
||||
AS_IF([test "x$enable_video" != "xno"],
|
||||
[AS_IF([test "x$win32" = "xno"],
|
||||
[AC_CHECK_LIB([v4l2], [v4l2_open], [],
|
||||
[AC_MSG_WARN([v4l2 API not detected, upgrade your kernel!])])],
|
||||
[AC_CHECK_HEADERS([vfw.h], [with_video="vfw"],
|
||||
[AC_MSG_FAILURE([test for VfW video support failed!
|
||||
configure --disable-video to skip building vidoe support.])])])
|
||||
])
|
||||
have_v4l1="no"
|
||||
have_v4l2="no"
|
||||
AS_IF([test "x$enable_video" = "xno"],
|
||||
[],
|
||||
[test "x$win32" = "xno"],
|
||||
[AC_CHECK_HEADERS([linux/videodev.h], [have_v4l1="yes"])
|
||||
AC_CHECK_HEADERS([linux/videodev2.h], [have_v4l2="yes"])
|
||||
AS_IF([test "x$have_v4l2" = "xno" && test "x$have_v4l1" = "xno"],
|
||||
[AC_MSG_FAILURE([test for video support failed!
|
||||
rebuild your kernel to include video4linux support or
|
||||
configure --disable-video to skip building video support.])],
|
||||
[test "x$have_v4l2" = "xno"],
|
||||
[AC_MSG_WARN([v4l2 API not detected, upgrade your kernel!])])],
|
||||
[AC_CHECK_HEADERS([vfw.h], [with_video="vfw"],
|
||||
[AC_MSG_FAILURE([test for VfW video support failed!
|
||||
configure --disable-video to skip building video support.])])])
|
||||
|
||||
AM_CONDITIONAL([HAVE_VIDEO], [test "x$enable_video" != "xno"])
|
||||
AM_CONDITIONAL([HAVE_V4L1], [test "x$have_v4l1" != "xno"])
|
||||
AM_CONDITIONAL([HAVE_V4L2], [test "x$have_v4l2" != "xno"])
|
||||
|
||||
dnl X
|
||||
AC_ARG_VAR([XSHM_LIBS], [linker flags for X shared memory extension])
|
||||
@ -245,51 +288,105 @@ set appropriately or configure --without-jpeg])],
|
||||
])
|
||||
AM_CONDITIONAL([HAVE_JPEG], [test "x$with_jpeg" = "xyes"])
|
||||
|
||||
dnl ImageMagick
|
||||
dnl ImageMagick or GraphicsMagick
|
||||
dnl disable both if IM is explicitly disabled to preserve old behavior
|
||||
|
||||
AC_ARG_WITH([imagemagick],
|
||||
[AS_HELP_STRING([--without-imagemagick],
|
||||
[disable support for scanning images using ImageMagick])],
|
||||
[disable support for scanning images with ImageMagick])],
|
||||
[],
|
||||
[with_imagemagick="yes"])
|
||||
[with_imagemagick="check"])
|
||||
|
||||
AS_IF([test "x$with_imagemagick" != "xno"],
|
||||
[PKG_CHECK_MODULES([MAGICK], [MagickWand >= 6.2.6], [],
|
||||
[dnl Wand is deprecated in favor of MagickWand,
|
||||
dnl but the latter doesn't exist in older verisons (bug #2848437)
|
||||
AC_ARG_WITH([graphicsmagick],
|
||||
[AS_HELP_STRING([--with-graphicsmagick],
|
||||
[use GraphicsMagick alternative to ImageMagick])],
|
||||
[],
|
||||
[with_graphicsmagick="check"])
|
||||
|
||||
magick="UnknownMagick"
|
||||
have_IM="maybe"
|
||||
AS_IF([test "x$with_imagemagick" = "xno"], [],
|
||||
[test "x$with_imagemagick" = "xyes" || \
|
||||
test "x$with_graphicsmagick" != "xyes"],
|
||||
[looked_for="ImageMagick >= 6.2.6"
|
||||
PKG_CHECK_MODULES([MAGICK], [MagickWand >= 6.2.6],
|
||||
[MAGICK_VERSION=`$PKG_CONFIG MagickWand --modversion`],
|
||||
[dnl
|
||||
dnl Wand is deprecated in favor of MagickWand,
|
||||
dnl but the latter doesn't exist in older verisons (bug #2848437)
|
||||
saved_error=$MAGICK_PKG_ERRORS
|
||||
PKG_CHECK_MODULES([MAGICK], [Wand >= 6.2.6], [],
|
||||
[AC_MSG_FAILURE([dnl
|
||||
Unable to find ImageMagick >= 6.2.6:
|
||||
PKG_CHECK_MODULES([MAGICK], [Wand >= 6.2.6],
|
||||
[MAGICK_VERSION=`$PKG_CONFIG Wand --modversion`],
|
||||
[have_IM="no"])])
|
||||
AS_IF([test "x$have_IM" != "xno"],
|
||||
[magick="ImageMagick"
|
||||
AC_MSG_NOTICE([trying ImageMagick version $MAGICK_VERSION])
|
||||
dnl double check ImageMagick install (bug #2582232)
|
||||
CPPFLAGS_save="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $MAGICK_CFLAGS"
|
||||
AC_CHECK_HEADER([wand/MagickWand.h],
|
||||
[have_IM="yes"],
|
||||
[have_IM="broken"])
|
||||
CPPFLAGS="$CPPFLAGS_save"])])
|
||||
|
||||
have_GM="maybe"
|
||||
AS_IF([test "x$have_IM" = "xyes"], [],
|
||||
[test "x$with_graphicsmagick" = "xno"], [],
|
||||
[test "x$with_graphicsmagick" = "xyes" || \
|
||||
test "x$with_imagemagick" = "xcheck"],
|
||||
[AS_IF([test "x$looked_for" = "x"],
|
||||
[looked_for="GraphicsMagick"],
|
||||
[looked_for="$looked_for or GraphicsMagick"])
|
||||
PKG_CHECK_MODULES([MAGICK], [GraphicsMagickWand],
|
||||
[have_GM="yes"
|
||||
magick="GraphicsMagick"
|
||||
MAGICK_VERSION=`$PKG_CONFIG GraphicsMagickWand --modversion`],
|
||||
[have_GM="no"
|
||||
AS_IF([test "x$saved_error" = "x"],
|
||||
[saved_error=$MAGICK_PKG_ERRORS])])])
|
||||
|
||||
dnl now that we have collected all the info abt what Magick is available
|
||||
dnl let the user know what we will or can't do
|
||||
AS_IF([test "x$have_IM" = "xbroken" && test "x$have_GM" = "xyes"],
|
||||
[AC_MSG_WARN([Your ImageMagick install is broken, using GraphicsMagick instead])])
|
||||
|
||||
AS_IF([test "x$have_IM" = "xyes" || test "x$have_GM" = "xyes"],
|
||||
[AC_MSG_NOTICE([using $magick version $MAGICK_VERSION])],
|
||||
[test "x$with_imagemagick" = "xno" && \
|
||||
test "x$with_graphicsmagick" != "xyes"],
|
||||
[AC_MSG_NOTICE([image scanning disabled -- zbarimg will *not* be built])],
|
||||
[test "x$have_IM" = "xbroken"],
|
||||
[AC_MSG_FAILURE([$magick package found but wand/MagickWand.h not installed?!
|
||||
this is a problem with your $magick install, please try again after
|
||||
resolving the inconsistency or installing GraphicsMagick alternative...])],
|
||||
[AC_MSG_FAILURE([dnl
|
||||
Unable to find $looked_for:
|
||||
|
||||
$saved_error
|
||||
|
||||
* Ensure that you installed any "development" packages for ImageMagick.
|
||||
* Ensure that you installed any "development" packages for ImageMagick or
|
||||
GraphicsMagick.
|
||||
* Consider adjusting the PKG_CONFIG_PATH environment variable if you
|
||||
installed software in a non-standard prefix.
|
||||
* You may set the environment variables MAGICK_CFLAGS and MAGICK_LIBS
|
||||
to avoid the need to call pkg-config.
|
||||
See the pkg-config man page for more details.
|
||||
* To avoid using ImageMagick altogether you may add the --without-imagemagick
|
||||
flag to the configure command; the zbarimg program will not be built.
|
||||
])])])
|
||||
MAGICK_VERSION=`$PKG_CONFIG MagickWand --modversion`
|
||||
AC_MSG_NOTICE([using ImageMagick version $MAGICK_VERSION])
|
||||
* To avoid using ImageMagick or GraphicsMagick altogether you may add the
|
||||
--without-imagemagick flag to the configure command; the zbarimg program
|
||||
will *not* be built.
|
||||
])])
|
||||
|
||||
dnl double check ImageMagick install (bug #2582232)
|
||||
CPPFLAGS_save="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $MAGICK_CFLAGS"
|
||||
AC_CHECK_HEADER([wand/MagickWand.h], [],
|
||||
[AC_MSG_FAILURE([ImageMagick package found but wand/MagickWand.h not installed?!
|
||||
this is a problem with your ImageMagick install,
|
||||
please resolve the inconsistency and try again...])])
|
||||
CPPFLAGS="$CPPFLAGS_save"])
|
||||
|
||||
AM_CONDITIONAL([HAVE_MAGICK], [test "x$with_imagemagick" = "xyes"])
|
||||
AS_IF([test "x$have_IM" = "xyes"],
|
||||
[AC_DEFINE([HAVE_IMAGEMAGICK], [1], [Define to 1 to use ImageMagick])],
|
||||
[test "x$have_GM" = "xyes"],
|
||||
[AC_DEFINE([HAVE_GRAPHICSMAGICK], [1], [Define to 1 to use GraphicsMagick])])
|
||||
AM_CONDITIONAL([HAVE_MAGICK],
|
||||
[test "x$have_IM" = "xyes" || test "x$have_GM" = "xyes"])
|
||||
|
||||
dnl Mozilla NPAPI
|
||||
AC_ARG_WITH([npapi],
|
||||
[AS_HELP_STRING([--with-npapi],
|
||||
[enable support for Firefox/Mozilla/OpenOffice NPAPI plugin])],
|
||||
[enable support for Firefox/Mozilla/OpenOffice plugin])],
|
||||
[],
|
||||
[with_npapi="no"])
|
||||
|
||||
@ -343,7 +440,16 @@ AS_IF([test "x$with_python" != "xno"],
|
||||
[test -x "$PYTHON-config"],
|
||||
[PYTHON_CFLAGS=`$PYTHON-config --cflags`],
|
||||
[PYTHON_CFLAGS=`$PYTHON -c 'import distutils.sysconfig as s; print " ".join(s.get_config_vars("CFLAGS")) + " -I"+s.get_python_inc() + " -I"+s.get_python_inc(plat_specific=True)'`])
|
||||
dnl FIXME now should check that #include <Python.h> compiles
|
||||
|
||||
dnl check that #include <Python.h> compiles (bug #3092663)
|
||||
CPPFLAGS_save="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $PYTHON_CFLAGS"
|
||||
AC_CHECK_HEADER([Python.h], [], [AC_MSG_ERROR([dnl
|
||||
Python module enabled, but unable to compile Python.h.
|
||||
Install the development package for python-$am_cv_python_version, or configure
|
||||
--without-python to disable the python bindings.dnl
|
||||
])])
|
||||
CPPFLAGS="$CPPFLAGS_save"
|
||||
|
||||
AS_IF([test "x$with_gtk" = "xyes"],
|
||||
[PKG_CHECK_MODULES([PYGTK], [pygtk-2.0])
|
||||
@ -376,13 +482,39 @@ AS_IF([test "x$with_qt" != "xno"],
|
||||
|
||||
AM_CONDITIONAL([HAVE_QT], [test "x$with_qt" = "xyes"])
|
||||
|
||||
dnl Java
|
||||
AC_ARG_WITH([java],
|
||||
[AS_HELP_STRING([--without-java],
|
||||
[disable support for Java interface])],
|
||||
[],
|
||||
[with_java="check"])
|
||||
|
||||
AC_ARG_VAR([JAVA_CFLAGS], [compiler flags for building JNI extensions])
|
||||
AS_IF([test "x$JAVA_CFLAGS" = "x" && test "x$JAVA_HOME" != "x"],
|
||||
[JAVA_CFLAGS="-I$JAVA_HOME/include"])
|
||||
|
||||
AS_IF([test "x$with_java" != "xno"],
|
||||
[CPPFLAGS_save="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $JAVA_CFLAGS"
|
||||
AC_CHECK_HEADER([jni.h], [], [have_java="no"])
|
||||
CPPFLAGS="$CPPFLAGS_save"
|
||||
AS_IF([test "x$have_java" != "xno"],
|
||||
[with_java="yes"],
|
||||
[test "x$with_java" = "xyes"],
|
||||
[AC_MSG_FAILURE([unable to find Java JNI! ensure CFLAGS are set
|
||||
appropriately or configure --without-java])],
|
||||
[with_java="no"])
|
||||
])
|
||||
AM_CONDITIONAL([HAVE_JAVA], [test "x$with_java" = "xyes"])
|
||||
|
||||
|
||||
dnl header files
|
||||
|
||||
dnl FIXME switches for shm, mmap
|
||||
AC_HEADER_ASSERT
|
||||
AC_CHECK_HEADERS([fcntl.h features.h inttypes.h stdlib.h string.h unistd.h \
|
||||
sys/ioctl.h sys/time.h sys/times.h sys/ipc.h sys/shm.h sys/mman.h])
|
||||
AC_CHECK_HEADERS([errno.h fcntl.h features.h inttypes.h stdlib.h string.h \
|
||||
unistd.h sys/types.h sys/stat.h sys/ioctl.h sys/time.h sys/times.h \
|
||||
sys/ipc.h sys/shm.h sys/mman.h])
|
||||
|
||||
dnl types
|
||||
|
||||
@ -421,6 +553,7 @@ AC_CONFIG_COMMANDS([doc/reldate.xml],
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
java/Makefile
|
||||
zbar.pc
|
||||
zbar-gtk.pc
|
||||
zbar-qt.pc
|
||||
@ -435,14 +568,16 @@ echo "please verify that the detected configuration matches your expectations:"
|
||||
echo "------------------------------------------------------------------------"
|
||||
echo "X --with-x=$have_x"
|
||||
echo "pthreads --enable-pthread=$enable_pthread"
|
||||
echo "v4l2 --enable-video=$enable_video"
|
||||
echo "v4l --enable-video=$enable_video"
|
||||
AS_IF([test "x$enable_video" != "xyes"],
|
||||
[echo " => zbarcam video scanner will *NOT* be built"])
|
||||
echo "jpeg --with-jpeg=$with_jpeg"
|
||||
AS_IF([test "x$with_jpeg" != "xyes"],
|
||||
[echo " => JPEG image conversions will *NOT* be supported"])
|
||||
echo "Magick++ --with-imagemagick=$with_imagemagick"
|
||||
AS_IF([test "x$with_imagemagick" != "xyes"],
|
||||
AS_IF([test "x$have_GM" = "xyes"],
|
||||
[echo "GraphicsMagick --with-graphicsmagick=yes"],
|
||||
[echo "ImageMagick --with-imagemagick=$with_imagemagick"])
|
||||
AS_IF([test "x$have_IM" != "xyes" && test "x$have_GM" != "xyes"],
|
||||
[echo " => the zbarimg file scanner will *NOT* be built"])
|
||||
echo "Python --with-python=$with_python"
|
||||
echo "GTK+ --with-gtk=$with_gtk"
|
||||
@ -453,6 +588,9 @@ AS_IF([test "x$with_gtk" != "xyes"],
|
||||
echo "Qt4 --with-qt=$with_qt"
|
||||
AS_IF([test "x$with_qt" != "xyes"],
|
||||
[echo " => the Qt4 widget will *NOT* be built"])
|
||||
echo "Java --with-java=$with_java"
|
||||
AS_IF([test "x$with_java" != "xyes"],
|
||||
[echo " => the Java interface will *NOT* be built"])
|
||||
#echo "NPAPI Plugin --with-npapi=$with_npapi"
|
||||
#AS_IF([test "x$with_mozilla" != "xyes"],
|
||||
# [echo " => the Mozilla/Firefox/OpenOffice plugin will *NOT* be built"])
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
DOCSOURCES = doc/manual.xml doc/version.xml doc/reldate.xml \
|
||||
doc/ref/zbarimg.xml doc/ref/zbarcam.xml doc/ref/commonoptions.xml
|
||||
|
||||
MAINTAINERCLEANFILES += doc/man/man.stamp doc/version.xml doc/reldate.xml
|
||||
|
||||
# man page targets to distribute and install
|
||||
dist_man_MANS =
|
||||
|
||||
@ -9,9 +9,12 @@
|
||||
|
||||
<address><a href="mailto:spadix@users.sourceforge.net">spadix@users.sourceforge.net</a></address>
|
||||
|
||||
<p>Copyright 2008-2009 (c) Jeff Brown - All Rights Reserved.</p>
|
||||
<p>Verbatim copying and distribution of this entire article are
|
||||
permitted worldwide, without royalty, in any medium, provided this
|
||||
notice, and the copyright notice, are preserved.</p>
|
||||
<p>Copyright 2008-2010 (c) Jeff Brown</p>
|
||||
<p>This documentation is part of the ZBar Barcode Reader; you can
|
||||
redistribute it and/or modify it under the terms of the
|
||||
<a href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">GNU
|
||||
Lesser General Public License</a> as published by the Free Software
|
||||
Foundation; either version 2.1 of the License, or (at your option) any
|
||||
later version.</p>
|
||||
|
||||
</body></html>
|
||||
|
||||
@ -29,10 +29,10 @@
|
||||
<year>2007</year>
|
||||
<year>2008</year>
|
||||
<year>2009</year>
|
||||
<year>2010</year>
|
||||
<holder>Jeff Brown</holder>
|
||||
</copyright>
|
||||
<legalnotice><para>All Rights Reserved</para></legalnotice>
|
||||
<!-- <legalnotice><para>insert GNU FDL header?</para></legalnotice> -->
|
||||
</bookinfo>
|
||||
|
||||
<chapter id="intro">
|
||||
@ -47,7 +47,4 @@
|
||||
&refzbarimg;
|
||||
|
||||
</reference>
|
||||
|
||||
<!-- insert GNU FDL? -->
|
||||
|
||||
</book>
|
||||
|
||||
@ -47,8 +47,9 @@
|
||||
<option>ean13</option>, <option>ean8</option>,
|
||||
<option>upca</option>, <option>upce</option>,
|
||||
<option>isbn13</option>, <option>isbn10</option>,
|
||||
<option>i25</option>, <option>code39</option>,
|
||||
<option>code128</option> or the special value <option>*</option>.
|
||||
<option>i25</option>, <option>codabar</option>, <option>code39</option>,
|
||||
<option>code93</option>, <option>code128</option>,
|
||||
<option>qrcode</option> or the special value <option>*</option>.
|
||||
If <replaceable class="parameter">symbology</replaceable> is
|
||||
omitted or <option>*</option>, the <replaceable
|
||||
class="parameter">config</replaceable> will be set for all
|
||||
@ -128,11 +129,12 @@
|
||||
If a decode result is outside the configured min/max range
|
||||
(inclusive), it will not be reported. Set to 0 to disable the
|
||||
corresponding check. This setting applies to variable-length
|
||||
symbologies: <option>i25</option>, <option>code39</option>,
|
||||
<option>code128</option> and <option>pdf417</option>.
|
||||
<option>min-length</option> defaults to 6 for <option>i25</option>
|
||||
and 1 for <option>code39</option> (per Code 39 autodiscrimination
|
||||
recommendation); all others default to 0</simpara>
|
||||
symbologies: <option>i25</option>, <option>codabar</option>,
|
||||
<option>code39</option>, <option>code128</option> and
|
||||
<option>pdf417</option>. <option>min-length</option> defaults to 6
|
||||
for <option>i25</option> and 1 for <option>code39</option> (per Code
|
||||
39 autodiscrimination recommendation); all others default to
|
||||
0</simpara>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
@ -60,9 +60,10 @@
|
||||
<filename>/dev/video0</filename></para>
|
||||
|
||||
<para>The underlying library currently supports EAN-13 (including
|
||||
UPC and ISBN subsets), EAN-8, Code 128, Code 39, and Interleaved
|
||||
2 of 5 symbologies. The specific type of each detected symbol is
|
||||
printed with the decoded data.</para>
|
||||
UPC and ISBN subsets), EAN-8, DataBar, DataBar Expanded, Code 128,
|
||||
Code 93, Code 39, Codabar, Interleaved 2 of 5 and QR Code symbologies.
|
||||
The specific type of each detected symbol is printed with the decoded
|
||||
data.</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
@ -159,6 +160,37 @@
|
||||
</para>
|
||||
</refsection>
|
||||
|
||||
<refsection>
|
||||
<title>Exit Status</title>
|
||||
|
||||
<para><command>zbarcam</command> returns an exit code to indicate the
|
||||
status of the program execution. Current exit codes are:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>0</term>
|
||||
<listitem>
|
||||
<para>Successful program completion.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>1</term>
|
||||
<listitem>
|
||||
<para>An error occurred. This includes bad arguments and I/O
|
||||
errors.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>2</term>
|
||||
<listitem>
|
||||
<para>A fatal error occurred.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsection>
|
||||
|
||||
<refsection>
|
||||
<title>See Also</title>
|
||||
<para><xref linkend="zbarimg"/></para>
|
||||
|
||||
@ -59,9 +59,10 @@
|
||||
displayed to the screen.</para>
|
||||
|
||||
<para>The underlying library currently supports EAN-13 (including
|
||||
UPC and ISBN subsets), EAN-8, Code 128, Code 39, and Interleaved
|
||||
2 of 5 symbologies. The specific type of each detected symbol is
|
||||
printed with the decoded data.</para>
|
||||
UPC and ISBN subsets), EAN-8, DataBar, DataBar Expanded, Code 128,
|
||||
Code 93, Code 39, Codabar, Interleaved 2 of 5 and QR Code symbologies.
|
||||
The specific type of each detected symbol is printed with the decoded
|
||||
data.</para>
|
||||
|
||||
<para>Note that "<filename><replaceable>image</replaceable></filename>"
|
||||
|
||||
@ -165,6 +166,56 @@
|
||||
</para>
|
||||
</refsection>
|
||||
|
||||
<refsection>
|
||||
<title>Exit Status</title>
|
||||
|
||||
<para><command>zbarimg</command> returns an exit code to indicate the
|
||||
status of the program execution. Current exit codes are:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>0</term>
|
||||
<listitem>
|
||||
<para>Barcodes successfully detected in all images. Warnings may
|
||||
have been generated, but no errors.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>1</term>
|
||||
<listitem>
|
||||
<para>An error occurred while processing some image(s). This
|
||||
includes bad arguments, I/O errors and image handling errors from
|
||||
ImageMagick.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>2</term>
|
||||
<listitem>
|
||||
<para>ImageMagick fatal error.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>3</term>
|
||||
<listitem>
|
||||
<para>The user quit the program before all images were scanned.
|
||||
Only applies when running in interactive mode
|
||||
(with <option>--display</option>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>4</term>
|
||||
<listitem>
|
||||
<para>No barcode was detected in one or more of the images. No
|
||||
other errors occurred.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsection>
|
||||
|
||||
<refsection>
|
||||
<title>See Also</title>
|
||||
<para><xref linkend="zbarcam"/></para>
|
||||
|
||||
@ -1,71 +0,0 @@
|
||||
#!/usr/bin/perl
|
||||
#------------------------------------------------------------------------
|
||||
# Copyright 2009 (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
|
||||
#------------------------------------------------------------------------
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use Barcode::ZBar;
|
||||
use Image::Magick;
|
||||
|
||||
warn("no input files specified?\n") if(!@ARGV);
|
||||
|
||||
# running output document
|
||||
my $out = undef;
|
||||
|
||||
# barcode scanner
|
||||
my $scanner = Barcode::ZBar::ImageScanner->new();
|
||||
|
||||
foreach my $file (@ARGV) {
|
||||
print "scanning from \"$file\"\n";
|
||||
my $imseq = Image::Magick->new();
|
||||
my $err = $imseq->Read($file);
|
||||
warn($err) if($err);
|
||||
|
||||
foreach my $page (@$imseq) {
|
||||
# convert ImageMagick page to ZBar image
|
||||
my $zimg = Barcode::ZBar::Image->new();
|
||||
$zimg->set_format('Y800');
|
||||
$zimg->set_size($page->Get(qw(columns rows)));
|
||||
$zimg->set_data($page->Clone()->ImageToBlob(magick => 'GRAY', depth => 8));
|
||||
|
||||
# scan for barcodes
|
||||
if($scanner->scan_image($zimg)) {
|
||||
# write out previous document
|
||||
$out->write() if($out);
|
||||
|
||||
# use first symbol found to name next image (FIXME sanitize)
|
||||
my $data = ($zimg->get_symbols())[0]->get_data();
|
||||
my $idx = $page->Get('scene') + 1;
|
||||
print "splitting $data from page $idx\n";
|
||||
|
||||
# create new output document
|
||||
$out = Image::Magick->new(filename => $data);
|
||||
}
|
||||
|
||||
# append this page to current output
|
||||
push(@$out, $page) if($out);
|
||||
}
|
||||
|
||||
# write out final document
|
||||
$out->write() if($out);
|
||||
}
|
||||
47
examples/processor.c
Normal file
47
examples/processor.c
Normal file
@ -0,0 +1,47 @@
|
||||
#include <stdio.h>
|
||||
#include <zbar.h>
|
||||
|
||||
static void my_handler (zbar_image_t *image,
|
||||
const void *userdata)
|
||||
{
|
||||
/* extract results */
|
||||
const zbar_symbol_t *symbol = zbar_image_first_symbol(image);
|
||||
for(; symbol; symbol = zbar_symbol_next(symbol)) {
|
||||
/* do something useful with results */
|
||||
zbar_symbol_type_t typ = zbar_symbol_get_type(symbol);
|
||||
const char *data = zbar_symbol_get_data(symbol);
|
||||
printf("decoded %s symbol \"%s\"\n",
|
||||
zbar_get_symbol_name(typ), data);
|
||||
}
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
const char *device = "/dev/video0";
|
||||
|
||||
/* create a Processor */
|
||||
zbar_processor_t *proc = zbar_processor_create(1);
|
||||
|
||||
/* configure the Processor */
|
||||
zbar_processor_set_config(proc, 0, ZBAR_CFG_ENABLE, 1);
|
||||
|
||||
/* initialize the Processor */
|
||||
if(argc > 1)
|
||||
device = argv[1];
|
||||
zbar_processor_init(proc, device, 1);
|
||||
|
||||
/* setup a callback */
|
||||
zbar_processor_set_data_handler(proc, my_handler, NULL);
|
||||
|
||||
/* enable the preview window */
|
||||
zbar_processor_set_visible(proc, 1);
|
||||
zbar_processor_set_active(proc, 1);
|
||||
|
||||
/* keep scanning until user provides key/mouse input */
|
||||
zbar_processor_user_wait(proc, -1);
|
||||
|
||||
/* clean up */
|
||||
zbar_processor_destroy(proc);
|
||||
|
||||
return(0);
|
||||
}
|
||||
45
examples/processor.cpp
Normal file
45
examples/processor.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
#include <iostream>
|
||||
#include <zbar.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace zbar;
|
||||
|
||||
class MyHandler : public Image::Handler
|
||||
{
|
||||
void image_callback (Image &image)
|
||||
{
|
||||
for(SymbolIterator symbol = image.symbol_begin();
|
||||
symbol != image.symbol_end();
|
||||
++symbol)
|
||||
cout << "decoded " << symbol->get_type_name() << " symbol "
|
||||
<< "\"" << symbol->get_data() << "\"" << endl;
|
||||
}
|
||||
};
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
// create and initialize a Processor
|
||||
const char *device = "/dev/video0";
|
||||
if(argc > 1)
|
||||
device = argv[1];
|
||||
Processor proc(true, device);
|
||||
|
||||
// configure the Processor
|
||||
proc.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);
|
||||
|
||||
// setup a callback
|
||||
MyHandler my_handler;
|
||||
proc.set_handler(my_handler);
|
||||
|
||||
// enable the preview window
|
||||
proc.set_visible();
|
||||
proc.set_active();
|
||||
|
||||
try {
|
||||
// keep scanning until user provides key/mouse input
|
||||
proc.user_wait();
|
||||
}
|
||||
catch(ClosedError &e) {
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
#!/usr/bin/env perl
|
||||
use warnings;
|
||||
use strict;
|
||||
require Barcode::ZBar;
|
||||
|
||||
# create a Processor
|
||||
my $proc = Barcode::ZBar::Processor->new();
|
||||
|
||||
# configure the Processor
|
||||
$proc->parse_config("enable");
|
||||
|
||||
# initialize the Processor
|
||||
$proc->init($ARGV[0] || '/dev/video0');
|
||||
|
||||
# setup a callback
|
||||
sub my_handler {
|
||||
my ($proc, $image, $closure) = @_;
|
||||
|
||||
# extract results
|
||||
foreach my $symbol ($proc->get_results()) {
|
||||
# do something useful with results
|
||||
print('decoded ' . $symbol->get_type() .
|
||||
' symbol "' . $symbol->get_data() . "\"\n");
|
||||
}
|
||||
}
|
||||
$proc->set_data_handler(\&my_handler);
|
||||
|
||||
# enable the preview window
|
||||
$proc->set_visible();
|
||||
|
||||
# initiate scanning
|
||||
$proc->set_active();
|
||||
|
||||
# keep scanning until user provides key/mouse input
|
||||
$proc->user_wait();
|
||||
@ -1,29 +0,0 @@
|
||||
#!/usr/bin/env perl
|
||||
use warnings;
|
||||
use strict;
|
||||
require Barcode::ZBar;
|
||||
|
||||
# create a Processor
|
||||
my $proc = Barcode::ZBar::Processor->new();
|
||||
|
||||
# configure the Processor
|
||||
$proc->parse_config("enable");
|
||||
|
||||
# initialize the Processor
|
||||
$proc->init($ARGV[0] || '/dev/video0');
|
||||
|
||||
# enable the preview window
|
||||
$proc->set_visible();
|
||||
|
||||
# read at least one barcode (or until window closed)
|
||||
$proc->process_one();
|
||||
|
||||
# hide the preview window
|
||||
$proc->set_visible(0);
|
||||
|
||||
# extract results
|
||||
foreach my $symbol ($proc->get_results()) {
|
||||
# do something useful with results
|
||||
print('decoded ' . $symbol->get_type() .
|
||||
' symbol "' . $symbol->get_data() . "\"\n");
|
||||
}
|
||||
@ -3,6 +3,20 @@
|
||||
#include <png.h>
|
||||
#include <zbar.h>
|
||||
|
||||
#if !defined(PNG_LIBPNG_VER) || \
|
||||
PNG_LIBPNG_VER < 10018 || \
|
||||
(PNG_LIBPNG_VER > 10200 && \
|
||||
PNG_LIBPNG_VER < 10209)
|
||||
/* Changes to Libpng from version 1.2.42 to 1.4.0 (January 4, 2010)
|
||||
* ...
|
||||
* 2. m. The function png_set_gray_1_2_4_to_8() was removed. It has been
|
||||
* deprecated since libpng-1.0.18 and 1.2.9, when it was replaced with
|
||||
* png_set_expand_gray_1_2_4_to_8() because the former function also
|
||||
* expanded palette images.
|
||||
*/
|
||||
# define png_set_expand_gray_1_2_4_to_8 png_set_gray_1_2_4_to_8
|
||||
#endif
|
||||
|
||||
zbar_image_scanner_t *scanner = NULL;
|
||||
|
||||
/* to complete a runnable example, this abbreviated implementation of
|
||||
@ -30,7 +44,7 @@ static void get_data (const char *name,
|
||||
if(color & PNG_COLOR_TYPE_PALETTE)
|
||||
png_set_palette_to_rgb(png);
|
||||
if(color == PNG_COLOR_TYPE_GRAY && bits < 8)
|
||||
png_set_gray_1_2_4_to_8(png);
|
||||
png_set_expand_gray_1_2_4_to_8(png);
|
||||
if(bits == 16)
|
||||
png_set_strip_16(png);
|
||||
if(color & PNG_COLOR_MASK_ALPHA)
|
||||
@ -65,7 +79,7 @@ int main (int argc, char **argv)
|
||||
|
||||
/* wrap image data */
|
||||
zbar_image_t *image = zbar_image_create();
|
||||
zbar_image_set_format(image, *(int*)"Y800");
|
||||
zbar_image_set_format(image, zbar_fourcc('Y','8','0','0'));
|
||||
zbar_image_set_size(image, width, height);
|
||||
zbar_image_set_data(image, raw, width * height, zbar_image_free_data);
|
||||
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
#!/usr/bin/perl
|
||||
use warnings;
|
||||
use strict;
|
||||
require Image::Magick;
|
||||
require Barcode::ZBar;
|
||||
|
||||
$ARGV[0] || die;
|
||||
|
||||
# create a reader
|
||||
my $scanner = Barcode::ZBar::ImageScanner->new();
|
||||
|
||||
# configure the reader
|
||||
$scanner->parse_config("enable");
|
||||
|
||||
# obtain image data
|
||||
my $magick = Image::Magick->new();
|
||||
$magick->Read($ARGV[0]) && die;
|
||||
my $raw = $magick->ImageToBlob(magick => 'GRAY', depth => 8);
|
||||
|
||||
# wrap image data
|
||||
my $image = Barcode::ZBar::Image->new();
|
||||
$image->set_format('Y800');
|
||||
$image->set_size($magick->Get(qw(columns rows)));
|
||||
$image->set_data($raw);
|
||||
|
||||
# scan the image for barcodes
|
||||
my $n = $scanner->scan_image($image);
|
||||
|
||||
# extract results
|
||||
foreach my $symbol ($image->get_symbols()) {
|
||||
# do something useful with results
|
||||
print('decoded ' . $symbol->get_type() .
|
||||
' symbol "' . $symbol->get_data() . "\"\n");
|
||||
}
|
||||
|
||||
# clean up
|
||||
undef($image);
|
||||
@ -3,7 +3,7 @@ use warnings;
|
||||
use strict;
|
||||
use Frontier::Client;
|
||||
use Data::Dumper;
|
||||
my $s = Frontier::Client->new('url' => 'http://dev.upcdatabase.com/rpc');
|
||||
my $s = Frontier::Client->new('url' => 'http://www.upcdatabase.com/rpc');
|
||||
|
||||
$| = 1; # autoflush
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
from xmlrpclib import ServerProxy
|
||||
import sys, re
|
||||
|
||||
server = ServerProxy("http://dev.upcdatabase.com/rpc")
|
||||
server = ServerProxy("http://www.upcdatabase.com/rpc")
|
||||
ean_re = re.compile(r'^(UPC-A:|EAN-13:)?(\d{11,13})$', re.M)
|
||||
|
||||
def lookup(decode):
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*------------------------------------------------------------------------
|
||||
* Copyright 2008-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
|
||||
* Copyright 2008-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
|
||||
*
|
||||
* This file is part of the ZBar Bar Code Reader.
|
||||
*
|
||||
@ -35,11 +35,6 @@
|
||||
#define DEFAULT_WIDTH 640
|
||||
#define DEFAULT_HEIGHT 480
|
||||
|
||||
/* adapted from v4l2 spec */
|
||||
#define fourcc(a, b, c, d) \
|
||||
((long)(a) | ((long)(b) << 8) | \
|
||||
((long)(c) << 16) | ((long)(d) << 24))
|
||||
|
||||
enum {
|
||||
DECODED,
|
||||
DECODED_TEXT,
|
||||
@ -88,15 +83,15 @@ gboolean zbar_gtk_image_from_pixbuf (zbar_image_t *zimg,
|
||||
|
||||
/* these are all guesses... */
|
||||
if(nchannels == 3 && bps == 8)
|
||||
type = fourcc('R','G','B','3');
|
||||
type = zbar_fourcc('R','G','B','3');
|
||||
else if(nchannels == 4 && bps == 8)
|
||||
type = fourcc('B','G','R','4'); /* FIXME alpha flipped?! */
|
||||
type = zbar_fourcc('B','G','R','4'); /* FIXME alpha flipped?! */
|
||||
else if(nchannels == 1 && bps == 8)
|
||||
type = fourcc('Y','8','0','0');
|
||||
type = zbar_fourcc('Y','8','0','0');
|
||||
else if(nchannels == 3 && bps == 5)
|
||||
type = fourcc('R','G','B','R');
|
||||
type = zbar_fourcc('R','G','B','R');
|
||||
else if(nchannels == 3 && bps == 4)
|
||||
type = fourcc('R','4','4','4'); /* FIXME maybe? */
|
||||
type = zbar_fourcc('R','4','4','4'); /* FIXME maybe? */
|
||||
else {
|
||||
g_warning("unsupported combination: nchannels=%d bps=%d\n",
|
||||
nchannels, bps);
|
||||
@ -142,10 +137,6 @@ static inline gboolean zbar_gtk_video_open (ZBarGtk *self,
|
||||
|
||||
gdk_threads_enter();
|
||||
|
||||
zbar->req_width = DEFAULT_WIDTH;
|
||||
zbar->req_height = DEFAULT_HEIGHT;
|
||||
gtk_widget_queue_resize(GTK_WIDGET(self));
|
||||
|
||||
zbar->video_opened = FALSE;
|
||||
if(zbar->thread)
|
||||
g_object_notify(G_OBJECT(self), "video-opened");
|
||||
@ -184,6 +175,10 @@ static inline gboolean zbar_gtk_video_open (ZBarGtk *self,
|
||||
*/
|
||||
gdk_threads_enter();
|
||||
|
||||
if(zbar->video_width && zbar->video_height)
|
||||
zbar_video_request_size(zbar->video,
|
||||
zbar->video_width, zbar->video_height);
|
||||
|
||||
video_opened = !zbar_negotiate_format(zbar->video, zbar->window);
|
||||
|
||||
if(video_opened) {
|
||||
@ -209,7 +204,7 @@ static inline int zbar_gtk_process_image (ZBarGtk *self,
|
||||
if(!image)
|
||||
return(-1);
|
||||
|
||||
zbar_image_t *tmp = zbar_image_convert(image, fourcc('Y','8','0','0'));
|
||||
zbar_image_t *tmp = zbar_image_convert(image, zbar_fourcc('Y','8','0','0'));
|
||||
if(!tmp)
|
||||
return(-1);
|
||||
|
||||
@ -236,7 +231,6 @@ static inline int zbar_gtk_process_image (ZBarGtk *self,
|
||||
|
||||
/* FIXME skip this when unconnected? */
|
||||
gchar *text = g_strconcat(zbar_get_symbol_name(type),
|
||||
zbar_get_addon_name(type),
|
||||
":",
|
||||
data,
|
||||
NULL);
|
||||
@ -560,6 +554,19 @@ gboolean zbar_gtk_get_video_opened (ZBarGtk *self)
|
||||
return(zbar->video_opened);
|
||||
}
|
||||
|
||||
void zbar_gtk_request_video_size (ZBarGtk *self,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
if(!self->_private || width < 0 || height < 0)
|
||||
return;
|
||||
ZBarGtkPrivate *zbar = ZBAR_GTK_PRIVATE(self->_private);
|
||||
|
||||
zbar->req_width = zbar->video_width = width;
|
||||
zbar->req_height = zbar->video_height = height;
|
||||
gtk_widget_queue_resize(GTK_WIDGET(self));
|
||||
}
|
||||
|
||||
static void zbar_gtk_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
@ -613,8 +620,8 @@ static void zbar_gtk_init (ZBarGtk *self)
|
||||
zbar->window = zbar_window_create();
|
||||
g_assert(zbar->window);
|
||||
|
||||
zbar->req_width = DEFAULT_WIDTH;
|
||||
zbar->req_height = DEFAULT_HEIGHT;
|
||||
zbar->req_width = zbar->video_width = DEFAULT_WIDTH;
|
||||
zbar->req_height = zbar->video_width = DEFAULT_HEIGHT;
|
||||
|
||||
/* spawn a thread to handle decoding and video */
|
||||
zbar->queue = g_async_queue_new();
|
||||
|
||||
@ -71,6 +71,7 @@ typedef struct _ZBarGtkPrivate
|
||||
* protected by main gui lock
|
||||
*/
|
||||
unsigned req_width, req_height;
|
||||
unsigned video_width, video_height;
|
||||
gboolean video_opened;
|
||||
|
||||
/* window is shared: owned by main gui thread.
|
||||
|
||||
196
include/zbar.h
196
include/zbar.h
@ -1,5 +1,5 @@
|
||||
/*------------------------------------------------------------------------
|
||||
* Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
|
||||
* Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
|
||||
*
|
||||
* This file is part of the ZBar Bar Code Reader.
|
||||
*
|
||||
@ -86,23 +86,58 @@ typedef enum zbar_color_e {
|
||||
typedef enum zbar_symbol_type_e {
|
||||
ZBAR_NONE = 0, /**< no symbol decoded */
|
||||
ZBAR_PARTIAL = 1, /**< intermediate status */
|
||||
ZBAR_EAN2 = 2, /**< GS1 2-digit add-on */
|
||||
ZBAR_EAN5 = 5, /**< GS1 5-digit add-on */
|
||||
ZBAR_EAN8 = 8, /**< EAN-8 */
|
||||
ZBAR_UPCE = 9, /**< UPC-E */
|
||||
ZBAR_ISBN10 = 10, /**< ISBN-10 (from EAN-13). @since 0.4 */
|
||||
ZBAR_UPCA = 12, /**< UPC-A */
|
||||
ZBAR_EAN13 = 13, /**< EAN-13 */
|
||||
ZBAR_ISBN13 = 14, /**< ISBN-13 (from EAN-13). @since 0.4 */
|
||||
ZBAR_COMPOSITE = 15, /**< EAN/UPC composite */
|
||||
ZBAR_I25 = 25, /**< Interleaved 2 of 5. @since 0.4 */
|
||||
ZBAR_DATABAR = 34, /**< GS1 DataBar (RSS). @since 0.11 */
|
||||
ZBAR_DATABAR_EXP = 35, /**< GS1 DataBar Expanded. @since 0.11 */
|
||||
ZBAR_CODABAR = 38, /**< Codabar. @since 0.11 */
|
||||
ZBAR_CODE39 = 39, /**< Code 39. @since 0.4 */
|
||||
ZBAR_PDF417 = 57, /**< PDF417. @since 0.6 */
|
||||
ZBAR_QRCODE = 64, /**< QR Code. @since 0.10 */
|
||||
ZBAR_CODE93 = 93, /**< Code 93. @since 0.11 */
|
||||
ZBAR_CODE128 = 128, /**< Code 128 */
|
||||
ZBAR_SYMBOL = 0x00ff, /**< mask for base symbol type */
|
||||
ZBAR_ADDON2 = 0x0200, /**< 2-digit add-on flag */
|
||||
ZBAR_ADDON5 = 0x0500, /**< 5-digit add-on flag */
|
||||
ZBAR_ADDON = 0x0700, /**< add-on flag mask */
|
||||
|
||||
/** mask for base symbol type.
|
||||
* @deprecated in 0.11, remove this from existing code
|
||||
*/
|
||||
ZBAR_SYMBOL = 0x00ff,
|
||||
/** 2-digit add-on flag.
|
||||
* @deprecated in 0.11, a ::ZBAR_EAN2 component is used for
|
||||
* 2-digit GS1 add-ons
|
||||
*/
|
||||
ZBAR_ADDON2 = 0x0200,
|
||||
/** 5-digit add-on flag.
|
||||
* @deprecated in 0.11, a ::ZBAR_EAN5 component is used for
|
||||
* 5-digit GS1 add-ons
|
||||
*/
|
||||
ZBAR_ADDON5 = 0x0500,
|
||||
/** add-on flag mask.
|
||||
* @deprecated in 0.11, GS1 add-ons are represented using composite
|
||||
* symbols of type ::ZBAR_COMPOSITE; add-on components use ::ZBAR_EAN2
|
||||
* or ::ZBAR_EAN5
|
||||
*/
|
||||
ZBAR_ADDON = 0x0700,
|
||||
} zbar_symbol_type_t;
|
||||
|
||||
/** decoded symbol coarse orientation.
|
||||
* @since 0.11
|
||||
*/
|
||||
typedef enum zbar_orientation_e {
|
||||
ZBAR_ORIENT_UNKNOWN = -1, /**< unable to determine orientation */
|
||||
ZBAR_ORIENT_UP, /**< upright, read left to right */
|
||||
ZBAR_ORIENT_RIGHT, /**< sideways, read top to bottom */
|
||||
ZBAR_ORIENT_DOWN, /**< upside-down, read right to left */
|
||||
ZBAR_ORIENT_LEFT, /**< sideways, read bottom to top */
|
||||
} zbar_orientation_t;
|
||||
|
||||
/** error codes. */
|
||||
typedef enum zbar_error_e {
|
||||
ZBAR_OK = 0, /**< no error */
|
||||
@ -133,12 +168,33 @@ typedef enum zbar_config_e {
|
||||
ZBAR_CFG_MIN_LEN = 0x20, /**< minimum data length for valid decode */
|
||||
ZBAR_CFG_MAX_LEN, /**< maximum data length for valid decode */
|
||||
|
||||
ZBAR_CFG_UNCERTAINTY = 0x40,/**< required video consistency frames */
|
||||
|
||||
ZBAR_CFG_POSITION = 0x80, /**< enable scanner to collect position data */
|
||||
|
||||
ZBAR_CFG_X_DENSITY = 0x100, /**< image scanner vertical scan density */
|
||||
ZBAR_CFG_Y_DENSITY, /**< image scanner horizontal scan density */
|
||||
} zbar_config_t;
|
||||
|
||||
/** decoder symbology modifier flags.
|
||||
* @since 0.11
|
||||
*/
|
||||
typedef enum zbar_modifier_e {
|
||||
/** barcode tagged as GS1 (EAN.UCC) reserved
|
||||
* (eg, FNC1 before first data character).
|
||||
* data may be parsed as a sequence of GS1 AIs
|
||||
*/
|
||||
ZBAR_MOD_GS1 = 0,
|
||||
|
||||
/** barcode tagged as AIM reserved
|
||||
* (eg, FNC1 after first character or digit pair)
|
||||
*/
|
||||
ZBAR_MOD_AIM,
|
||||
|
||||
/** number of modifiers */
|
||||
ZBAR_MOD_NUM,
|
||||
} zbar_modifier_t;
|
||||
|
||||
/** retrieve runtime library version information.
|
||||
* @param major set to the running major version (unless NULL)
|
||||
* @param minor set to the running minor version (unless NULL)
|
||||
@ -168,9 +224,32 @@ extern const char *zbar_get_symbol_name(zbar_symbol_type_t sym);
|
||||
* @param sym symbol type encoding
|
||||
* @returns static string name for any addon, or the empty string
|
||||
* if no addons were decoded
|
||||
* @deprecated in 0.11
|
||||
*/
|
||||
extern const char *zbar_get_addon_name(zbar_symbol_type_t sym);
|
||||
|
||||
/** retrieve string name for configuration setting.
|
||||
* @param config setting to name
|
||||
* @returns static string name for config,
|
||||
* or the empty string if value is not a known config
|
||||
*/
|
||||
extern const char *zbar_get_config_name(zbar_config_t config);
|
||||
|
||||
/** retrieve string name for modifier.
|
||||
* @param modifier flag to name
|
||||
* @returns static string name for modifier,
|
||||
* or the empty string if the value is not a known flag
|
||||
*/
|
||||
extern const char *zbar_get_modifier_name(zbar_modifier_t modifier);
|
||||
|
||||
/** retrieve string name for orientation.
|
||||
* @param orientation orientation encoding
|
||||
* @returns the static string name for the specified orientation,
|
||||
* or "UNKNOWN" if the orientation is not recognized
|
||||
* @since 0.11
|
||||
*/
|
||||
extern const char *zbar_get_orientation_name(zbar_orientation_t orientation);
|
||||
|
||||
/** parse a configuration string of the form "[symbology.]config[=value]".
|
||||
* the config must match one of the recognized names.
|
||||
* the symbology, if present, must match one of the recognized names.
|
||||
@ -184,6 +263,30 @@ extern int zbar_parse_config(const char *config_string,
|
||||
zbar_config_t *config,
|
||||
int *value);
|
||||
|
||||
/** consistently compute fourcc values across architectures
|
||||
* (adapted from v4l2 specification)
|
||||
* @since 0.11
|
||||
*/
|
||||
#define zbar_fourcc(a, b, c, d) \
|
||||
((unsigned long)(a) | \
|
||||
((unsigned long)(b) << 8) | \
|
||||
((unsigned long)(c) << 16) | \
|
||||
((unsigned long)(d) << 24))
|
||||
|
||||
/** parse a fourcc string into its encoded integer value.
|
||||
* @since 0.11
|
||||
*/
|
||||
static inline unsigned long zbar_fourcc_parse (const char *format)
|
||||
{
|
||||
unsigned long fourcc = 0;
|
||||
if(format) {
|
||||
int i;
|
||||
for(i = 0; i < 4 && format[i]; i++)
|
||||
fourcc |= ((unsigned long)format[i]) << (i * 8);
|
||||
}
|
||||
return(fourcc);
|
||||
}
|
||||
|
||||
/** @internal type unsafe error API (don't use) */
|
||||
extern int _zbar_error_spew(const void *object,
|
||||
int verbosity);
|
||||
@ -229,6 +332,20 @@ extern void zbar_symbol_ref(const zbar_symbol_t *symbol,
|
||||
*/
|
||||
extern zbar_symbol_type_t zbar_symbol_get_type(const zbar_symbol_t *symbol);
|
||||
|
||||
/** retrieve symbology boolean config settings.
|
||||
* @returns a bitmask indicating which configs were set for the detected
|
||||
* symbology during decoding.
|
||||
* @since 0.11
|
||||
*/
|
||||
extern unsigned int zbar_symbol_get_configs(const zbar_symbol_t *symbol);
|
||||
|
||||
/** retrieve symbology modifier flag settings.
|
||||
* @returns a bitmask indicating which characteristics were detected
|
||||
* during decoding.
|
||||
* @since 0.11
|
||||
*/
|
||||
extern unsigned int zbar_symbol_get_modifiers(const zbar_symbol_t *symbol);
|
||||
|
||||
/** retrieve data decoded from symbol.
|
||||
* @returns the data string
|
||||
*/
|
||||
@ -284,6 +401,14 @@ extern int zbar_symbol_get_loc_x(const zbar_symbol_t *symbol,
|
||||
extern int zbar_symbol_get_loc_y(const zbar_symbol_t *symbol,
|
||||
unsigned index);
|
||||
|
||||
/** retrieve general orientation of decoded symbol.
|
||||
* @returns a coarse, axis-aligned indication of symbol orientation or
|
||||
* ::ZBAR_ORIENT_UNKNOWN if unknown
|
||||
* @since 0.11
|
||||
*/
|
||||
extern zbar_orientation_t
|
||||
zbar_symbol_get_orientation(const zbar_symbol_t *symbol);
|
||||
|
||||
/** iterate the set to which this symbol belongs (there can be only one).
|
||||
* @returns the next symbol in the set, or
|
||||
* @returns NULL when no more results are available
|
||||
@ -357,6 +482,14 @@ extern int zbar_symbol_set_get_size(const zbar_symbol_set_t *symbols);
|
||||
extern const zbar_symbol_t*
|
||||
zbar_symbol_set_first_symbol(const zbar_symbol_set_t *symbols);
|
||||
|
||||
/** raw result iterator.
|
||||
* @returns the first decoded symbol result in a set, *before* filtering
|
||||
* @returns NULL if the set is empty
|
||||
* @since 0.11
|
||||
*/
|
||||
extern const zbar_symbol_t*
|
||||
zbar_symbol_set_first_unfiltered(const zbar_symbol_set_t *symbols);
|
||||
|
||||
/*@}*/
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
@ -456,6 +589,25 @@ extern unsigned zbar_image_get_width(const zbar_image_t *image);
|
||||
*/
|
||||
extern unsigned zbar_image_get_height(const zbar_image_t *image);
|
||||
|
||||
/** retrieve both dimensions of the image.
|
||||
* fills in the width and height in samples
|
||||
*/
|
||||
extern void zbar_image_get_size(const zbar_image_t *image,
|
||||
unsigned *width,
|
||||
unsigned *height);
|
||||
|
||||
/** retrieve the crop rectangle.
|
||||
* fills in the image coordinates of the upper left corner and size
|
||||
* of an axis-aligned rectangular area of the image that will be scanned.
|
||||
* defaults to the full image
|
||||
* @since 0.11
|
||||
*/
|
||||
extern void zbar_image_get_crop(const zbar_image_t *image,
|
||||
unsigned *x,
|
||||
unsigned *y,
|
||||
unsigned *width,
|
||||
unsigned *height);
|
||||
|
||||
/** return the image sample data. the returned data buffer is only
|
||||
* valid until zbar_image_destroy() is called
|
||||
*/
|
||||
@ -505,12 +657,24 @@ extern void zbar_image_set_sequence(zbar_image_t *image,
|
||||
unsigned sequence_num);
|
||||
|
||||
/** specify the pixel size of the image.
|
||||
* @note this also resets the crop rectangle to the full image
|
||||
* (0, 0, width, height)
|
||||
* @note this does not affect the data!
|
||||
*/
|
||||
extern void zbar_image_set_size(zbar_image_t *image,
|
||||
unsigned width,
|
||||
unsigned height);
|
||||
|
||||
/** specify a rectangular region of the image to scan.
|
||||
* the rectangle will be clipped to the image boundaries.
|
||||
* defaults to the full image specified by zbar_image_set_size()
|
||||
*/
|
||||
extern void zbar_image_set_crop(zbar_image_t *image,
|
||||
unsigned x,
|
||||
unsigned y,
|
||||
unsigned width,
|
||||
unsigned height);
|
||||
|
||||
/** specify image sample data. when image data is no longer needed by
|
||||
* the library the specific data cleanup handler will be called
|
||||
* (unless NULL)
|
||||
@ -1148,6 +1312,14 @@ static inline int zbar_decoder_parse_config (zbar_decoder_t *decoder,
|
||||
zbar_decoder_set_config(decoder, sym, cfg, val));
|
||||
}
|
||||
|
||||
/** retrieve symbology boolean config settings.
|
||||
* @returns a bitmask indicating which configs are currently set for the
|
||||
* specified symbology.
|
||||
* @since 0.11
|
||||
*/
|
||||
extern unsigned int zbar_decoder_get_configs(const zbar_decoder_t *decoder,
|
||||
zbar_symbol_type_t symbology);
|
||||
|
||||
/** clear all decoder state.
|
||||
* any partial symbols are flushed
|
||||
*/
|
||||
@ -1195,6 +1367,20 @@ zbar_decoder_get_data_length(const zbar_decoder_t *decoder);
|
||||
extern zbar_symbol_type_t
|
||||
zbar_decoder_get_type(const zbar_decoder_t *decoder);
|
||||
|
||||
/** retrieve modifier flags for the last decoded symbol.
|
||||
* @returns a bitmask indicating which characteristics were detected
|
||||
* during decoding.
|
||||
* @since 0.11
|
||||
*/
|
||||
extern unsigned int zbar_decoder_get_modifiers(const zbar_decoder_t *decoder);
|
||||
|
||||
/** retrieve last decode direction.
|
||||
* @returns 1 for forward and -1 for reverse
|
||||
* @returns 0 if the decode direction is unknown or does not apply
|
||||
* @since 0.11
|
||||
*/
|
||||
extern int zbar_decoder_get_direction(const zbar_decoder_t *decoder);
|
||||
|
||||
/** setup data handler callback.
|
||||
* the registered function will be called by the decoder
|
||||
* just before zbar_decode_width() returns a non-zero value.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
|
||||
// Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
|
||||
//
|
||||
// This file is part of the ZBar Bar Code Reader.
|
||||
//
|
||||
@ -115,6 +115,7 @@ class Decoder {
|
||||
|
||||
/// retrieve string name for last decode addon.
|
||||
/// see zbar_get_addon_name()
|
||||
/// @deprecated in 0.11
|
||||
const char *get_addon_name () const
|
||||
{
|
||||
return(zbar_get_addon_name(zbar_decoder_get_type(_decoder)));
|
||||
@ -149,6 +150,14 @@ class Decoder {
|
||||
return(zbar_decoder_get_data_length(_decoder));
|
||||
}
|
||||
|
||||
/// retrieve last decode direction.
|
||||
/// see zbar_decoder_get_direction()
|
||||
/// @since 0.11
|
||||
int get_direction() const
|
||||
{
|
||||
return(zbar_decoder_get_direction(_decoder));
|
||||
}
|
||||
|
||||
/// setup callback to handle result data.
|
||||
void set_handler (Handler &handler)
|
||||
{
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
|
||||
// Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
|
||||
//
|
||||
// This file is part of the ZBar Bar Code Reader.
|
||||
//
|
||||
@ -67,7 +67,12 @@ public:
|
||||
{
|
||||
if(userdata) {
|
||||
Image *image = (Image*)zbar_image_get_userdata(zimg);
|
||||
((Handler*)userdata)->image_callback(*image);
|
||||
if(image)
|
||||
((Handler*)userdata)->image_callback(*image);
|
||||
else {
|
||||
Image tmp(zimg, 1);
|
||||
((Handler*)userdata)->image_callback(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -110,6 +115,8 @@ public:
|
||||
|
||||
~Image ()
|
||||
{
|
||||
if(zbar_image_get_userdata(_img) == this)
|
||||
zbar_image_set_userdata(_img, NULL);
|
||||
zbar_image_ref(_img, -1);
|
||||
}
|
||||
|
||||
@ -143,12 +150,7 @@ public:
|
||||
/// see zbar_image_set_format()
|
||||
void set_format (const std::string& format)
|
||||
{
|
||||
if(format.length() != 4)
|
||||
throw FormatError();
|
||||
unsigned long fourcc = ((format[0] & 0xff) |
|
||||
((format[1] & 0xff) << 8) |
|
||||
((format[2] & 0xff) << 16) |
|
||||
((format[3] & 0xff) << 24));
|
||||
unsigned long fourcc = zbar_fourcc_parse(format.c_str());
|
||||
zbar_image_set_format(_img, fourcc);
|
||||
}
|
||||
|
||||
@ -183,6 +185,15 @@ public:
|
||||
return(zbar_image_get_height(_img));
|
||||
}
|
||||
|
||||
/// retrieve both dimensions of the image.
|
||||
/// see zbar_image_get_size()
|
||||
/// @since 0.11
|
||||
void get_size (unsigned &width,
|
||||
unsigned &height) const
|
||||
{
|
||||
zbar_image_get_size(_img, &width, &height);
|
||||
}
|
||||
|
||||
/// specify the pixel size of the image.
|
||||
/// see zbar_image_set_size()
|
||||
void set_size (unsigned width,
|
||||
@ -191,6 +202,26 @@ public:
|
||||
zbar_image_set_size(_img, width, height);
|
||||
}
|
||||
|
||||
/// retrieve the scan crop rectangle.
|
||||
/// see zbar_image_get_crop()
|
||||
void get_crop (unsigned &x,
|
||||
unsigned &y,
|
||||
unsigned &width,
|
||||
unsigned &height) const
|
||||
{
|
||||
zbar_image_get_crop(_img, &x, &y, &width, &height);
|
||||
}
|
||||
|
||||
/// set the scan crop rectangle.
|
||||
/// see zbar_image_set_crop()
|
||||
void set_crop (unsigned x,
|
||||
unsigned y,
|
||||
unsigned width,
|
||||
unsigned height)
|
||||
{
|
||||
zbar_image_set_crop(_img, x, y, width, height);
|
||||
}
|
||||
|
||||
/// return the image sample data.
|
||||
/// see zbar_image_get_data()
|
||||
const void *get_data () const
|
||||
@ -224,6 +255,15 @@ public:
|
||||
throw FormatError();
|
||||
}
|
||||
|
||||
/// image format conversion.
|
||||
/// see zbar_image_convert()
|
||||
/// @since 0.11
|
||||
Image convert (std::string format) const
|
||||
{
|
||||
unsigned long fourcc = zbar_fourcc_parse(format.c_str());
|
||||
return(convert(fourcc));
|
||||
}
|
||||
|
||||
/// image format conversion with crop/pad.
|
||||
/// see zbar_image_convert_resize()
|
||||
/// @since 0.4
|
||||
@ -278,7 +318,6 @@ protected:
|
||||
{
|
||||
// by default nothing is cleaned
|
||||
assert(img);
|
||||
assert(zbar_image_get_userdata(img));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
|
||||
// Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
|
||||
//
|
||||
// This file is part of the ZBar Bar Code Reader.
|
||||
//
|
||||
@ -183,8 +183,8 @@ class Processor {
|
||||
void force_format (std::string& input_format,
|
||||
std::string& output_format)
|
||||
{
|
||||
unsigned long ifourcc = *(unsigned long*)input_format.c_str();
|
||||
unsigned long ofourcc = *(unsigned long*)output_format.c_str();
|
||||
unsigned long ifourcc = zbar_fourcc_parse(input_format.c_str());
|
||||
unsigned long ofourcc = zbar_fourcc_parse(output_format.c_str());
|
||||
if(zbar_processor_force_format(_processor, ifourcc, ofourcc))
|
||||
throw_exception(_processor);
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright 2008-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
|
||||
// Copyright 2008-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
|
||||
//
|
||||
// This file is part of the ZBar Bar Code Reader.
|
||||
//
|
||||
@ -53,7 +53,7 @@ public:
|
||||
unsigned width = bpl / 4;
|
||||
unsigned height = qimg.height();
|
||||
set_size(width, height);
|
||||
set_format('B' | ('G' << 8) | ('R' << 16) | ('4' << 24));
|
||||
set_format(zbar_fourcc('B','G','R','4'));
|
||||
unsigned long datalen = qimg.numBytes();
|
||||
set_data(qimg.bits(), datalen);
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
|
||||
// Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
|
||||
//
|
||||
// This file is part of the ZBar Bar Code Reader.
|
||||
//
|
||||
@ -64,6 +64,21 @@ public:
|
||||
ref(-1);
|
||||
}
|
||||
|
||||
/// assignment.
|
||||
SymbolSet& operator= (const SymbolSet& syms)
|
||||
{
|
||||
syms.ref();
|
||||
ref(-1);
|
||||
_syms = syms._syms;
|
||||
return(*this);
|
||||
}
|
||||
|
||||
/// truth testing.
|
||||
bool operator! () const
|
||||
{
|
||||
return(!_syms || !get_size());
|
||||
}
|
||||
|
||||
/// manipulate reference count.
|
||||
void ref (int delta = 1) const
|
||||
{
|
||||
@ -77,7 +92,7 @@ public:
|
||||
return(_syms);
|
||||
}
|
||||
|
||||
int get_size ()
|
||||
int get_size () const
|
||||
{
|
||||
return((_syms) ? zbar_symbol_set_get_size(_syms) : 0);
|
||||
}
|
||||
@ -112,9 +127,16 @@ public:
|
||||
|
||||
/// copy constructor.
|
||||
Point (const Point& pt)
|
||||
: x(pt.x),
|
||||
y(pt.y)
|
||||
{ }
|
||||
|
||||
/// assignment.
|
||||
Point& operator= (const Point& pt)
|
||||
{
|
||||
x = pt.x;
|
||||
y = pt.y;
|
||||
return(*this);
|
||||
}
|
||||
};
|
||||
|
||||
@ -129,31 +151,52 @@ public:
|
||||
: _sym(sym),
|
||||
_index(index)
|
||||
{
|
||||
sym->ref(1);
|
||||
if(sym)
|
||||
sym->ref(1);
|
||||
if(!sym ||
|
||||
(unsigned)_index >= zbar_symbol_get_loc_size(*_sym))
|
||||
_index = -1;
|
||||
}
|
||||
|
||||
/// constructor.
|
||||
/// copy constructor.
|
||||
PointIterator (const PointIterator& iter)
|
||||
: _sym(iter._sym),
|
||||
_index(iter._index)
|
||||
{
|
||||
_sym->ref();
|
||||
if(_sym)
|
||||
_sym->ref();
|
||||
}
|
||||
|
||||
/// destructor.
|
||||
~PointIterator ()
|
||||
{
|
||||
_sym->ref(-1);
|
||||
if(_sym)
|
||||
_sym->ref(-1);
|
||||
}
|
||||
|
||||
/// assignment.
|
||||
PointIterator& operator= (const PointIterator& iter)
|
||||
{
|
||||
if(iter._sym)
|
||||
iter._sym->ref();
|
||||
if(_sym)
|
||||
_sym->ref(-1);
|
||||
_sym = iter._sym;
|
||||
_index = iter._index;
|
||||
return(*this);
|
||||
}
|
||||
|
||||
/// truth testing.
|
||||
bool operator! () const
|
||||
{
|
||||
return(!_sym || _index < 0);
|
||||
}
|
||||
|
||||
/// advance iterator to next Point.
|
||||
PointIterator& operator++ ()
|
||||
{
|
||||
unsigned int i = ++_index;
|
||||
if(i >= zbar_symbol_get_loc_size(*_sym))
|
||||
if(!_sym || i >= zbar_symbol_get_loc_size(*_sym))
|
||||
_index = -1;
|
||||
return(*this);
|
||||
}
|
||||
@ -161,7 +204,9 @@ public:
|
||||
/// retrieve currently referenced Point.
|
||||
const Point operator* () const
|
||||
{
|
||||
assert(_index >= 0);
|
||||
assert(!!*this);
|
||||
if(!*this)
|
||||
return(Point());
|
||||
return(Point(zbar_symbol_get_loc_x(*_sym, _index),
|
||||
zbar_symbol_get_loc_y(*_sym, _index)));
|
||||
}
|
||||
@ -213,6 +258,32 @@ public:
|
||||
ref(-1);
|
||||
}
|
||||
|
||||
/// assignment.
|
||||
Symbol& operator= (const Symbol& sym)
|
||||
{
|
||||
sym.ref(1);
|
||||
ref(-1);
|
||||
_sym = sym._sym;
|
||||
_type = sym._type;
|
||||
_data = sym._data;
|
||||
return(*this);
|
||||
}
|
||||
|
||||
Symbol& operator= (const zbar_symbol_t *sym)
|
||||
{
|
||||
if(sym)
|
||||
zbar_symbol_ref(sym, 1);
|
||||
ref(-1);
|
||||
init(sym);
|
||||
return(*this);
|
||||
}
|
||||
|
||||
/// truth testing.
|
||||
bool operator! () const
|
||||
{
|
||||
return(!_sym);
|
||||
}
|
||||
|
||||
void ref (int delta = 1) const
|
||||
{
|
||||
if(_sym)
|
||||
@ -250,6 +321,7 @@ public:
|
||||
}
|
||||
|
||||
/// retrieve the string name for any addon.
|
||||
/// @deprecated in 0.11
|
||||
const std::string get_addon_name () const
|
||||
{
|
||||
return(zbar_get_addon_name(_type));
|
||||
@ -269,12 +341,20 @@ public:
|
||||
|
||||
/// retrieve inter-frame coherency count.
|
||||
/// see zbar_symbol_get_count()
|
||||
/// @since 1.5
|
||||
/// @since 0.5
|
||||
int get_count () const
|
||||
{
|
||||
return((_sym) ? zbar_symbol_get_count(_sym) : -1);
|
||||
}
|
||||
|
||||
/// retrieve loosely defined relative quality metric.
|
||||
/// see zbar_symbol_get_quality()
|
||||
/// @since 0.11
|
||||
int get_quality () const
|
||||
{
|
||||
return((_sym) ? zbar_symbol_get_quality(_sym) : 0);
|
||||
}
|
||||
|
||||
SymbolSet get_components () const
|
||||
{
|
||||
return(SymbolSet((_sym) ? zbar_symbol_get_components(_sym) : NULL));
|
||||
@ -311,6 +391,13 @@ public:
|
||||
return((_sym) ? zbar_symbol_get_loc_y(_sym, index) : -1);
|
||||
}
|
||||
|
||||
/// see zbar_symbol_get_orientation().
|
||||
/// @since 0.11
|
||||
int get_orientation () const
|
||||
{
|
||||
return(zbar_symbol_get_orientation(_sym));
|
||||
}
|
||||
|
||||
/// see zbar_symbol_xml().
|
||||
const std::string xml () const
|
||||
{
|
||||
@ -320,9 +407,6 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
friend class SymbolIterator;
|
||||
|
||||
/// (re)initialize Symbol from C symbol object.
|
||||
void init (const zbar_symbol_t *sym = NULL)
|
||||
{
|
||||
@ -361,7 +445,7 @@ public:
|
||||
{
|
||||
const zbar_symbol_set_t *zsyms = _syms;
|
||||
if(zsyms)
|
||||
_sym.init(zbar_symbol_set_first_symbol(zsyms));
|
||||
_sym = zbar_symbol_set_first_symbol(zsyms);
|
||||
}
|
||||
|
||||
/// copy constructor.
|
||||
@ -370,25 +454,33 @@ public:
|
||||
{
|
||||
const zbar_symbol_set_t *zsyms = _syms;
|
||||
if(zsyms)
|
||||
_sym.init(zbar_symbol_set_first_symbol(zsyms));
|
||||
_sym = zbar_symbol_set_first_symbol(zsyms);
|
||||
}
|
||||
|
||||
~SymbolIterator ()
|
||||
{
|
||||
_sym.init();
|
||||
}
|
||||
|
||||
/// assignment.
|
||||
SymbolIterator& operator= (const SymbolIterator& iter)
|
||||
{
|
||||
_syms = iter._syms;
|
||||
_sym = iter._sym;
|
||||
return(*this);
|
||||
}
|
||||
|
||||
bool operator! () const
|
||||
{
|
||||
return(!_syms || !_sym);
|
||||
}
|
||||
|
||||
/// advance iterator to next Symbol.
|
||||
SymbolIterator& operator++ ()
|
||||
{
|
||||
const zbar_symbol_t *zsym = _sym;
|
||||
if(zsym)
|
||||
_sym.init(zbar_symbol_next(zsym));
|
||||
else {
|
||||
const zbar_symbol_set_t *zsyms = _syms;
|
||||
if(zsyms)
|
||||
_sym.init(zbar_symbol_set_first_symbol(zsyms));
|
||||
}
|
||||
if(!!_sym)
|
||||
_sym = zbar_symbol_next(_sym);
|
||||
else if(!!_syms)
|
||||
_sym = zbar_symbol_set_first_symbol(_syms);
|
||||
return(*this);
|
||||
}
|
||||
|
||||
@ -440,9 +532,7 @@ inline const SymbolIterator SymbolSet::symbol_end () const {
|
||||
static inline std::ostream& operator<< (std::ostream& out,
|
||||
const Symbol& sym)
|
||||
{
|
||||
out << sym.get_type_name()
|
||||
<< sym.get_addon_name()
|
||||
<< ":" << sym.get_data();
|
||||
out << sym.get_type_name() << ":" << sym.get_data();
|
||||
return(out);
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
|
||||
// Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
|
||||
//
|
||||
// This file is part of the ZBar Bar Code Reader.
|
||||
//
|
||||
@ -92,7 +92,7 @@ public:
|
||||
/// see zbar_video_init()
|
||||
void init (std::string& format)
|
||||
{
|
||||
unsigned int fourcc = *(unsigned int*)format.c_str();
|
||||
unsigned int fourcc = zbar_fourcc_parse(format.c_str());
|
||||
if(zbar_video_init(_video, fourcc))
|
||||
throw_exception(_video);
|
||||
}
|
||||
|
||||
@ -136,7 +136,7 @@ struct _ZBarGtkClass {
|
||||
|
||||
GType zbar_gtk_get_type(void) G_GNUC_CONST;
|
||||
|
||||
/**
|
||||
/**
|
||||
* zbar_gtk_new:
|
||||
* create a new barcode reader widget instance.
|
||||
* initially has no associated video device or image.
|
||||
@ -189,7 +189,17 @@ void zbar_gtk_set_video_enabled(ZBarGtk *zbar,
|
||||
*/
|
||||
gboolean zbar_gtk_get_video_opened(ZBarGtk *zbar);
|
||||
|
||||
/**
|
||||
/** set video camera resolution.
|
||||
* @width: width in pixels
|
||||
* @height: height in pixels
|
||||
*
|
||||
* @note this call must be made before video is initialized
|
||||
*/
|
||||
void zbar_gtk_request_video_size(ZBarGtk *zbar,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
/**
|
||||
* utility function to populate a zbar_image_t from a GdkPixbuf.
|
||||
* @image: the zbar library image destination to populate
|
||||
* @pixbuf: the GdkPixbuf source
|
||||
|
||||
138
iphone/ChangeLog
Normal file
138
iphone/ChangeLog
Normal file
@ -0,0 +1,138 @@
|
||||
version 1.3.1:
|
||||
* fix examples
|
||||
- fix EmbedReader initial iPad orientation
|
||||
- fix TabReader shouldn't show controls
|
||||
* add retry workaround when device lock fails
|
||||
- add iPhone 5 launch image to examples
|
||||
- doc updates
|
||||
* Lion and Xcode updates
|
||||
- fix new warnings/errors
|
||||
- find missing buddy
|
||||
- fix SDK bg image: force resoution to 72dpi
|
||||
* Fix EmbedReader example rotation interaction
|
||||
|
||||
version 1.2.2:
|
||||
* reduce controller present and dismiss latency
|
||||
- add simple shutter to mask video start
|
||||
|
||||
version 1.2.1:
|
||||
* fix overlay resizing bug
|
||||
|
||||
version 1.2:
|
||||
* release updates
|
||||
|
||||
version 1.1.3:
|
||||
* fix UITabViewController rotation interaction
|
||||
|
||||
version 1.1.2:
|
||||
* add maxZoom for increasing zoom range
|
||||
- workaround camera preview initial location/size bug
|
||||
* add emulation for UI videoQuality to adjust camera resolution
|
||||
* fix several simulator-related bugs
|
||||
- fix device property missing from simulated ZBarReaderView
|
||||
- fix AVCaptureDevice referenced from ZBarReaderViewController
|
||||
- fix simulated camera gesture multiple recognition
|
||||
|
||||
version 1.1.1:
|
||||
* fix ReaderSample project path to ZBarSDK
|
||||
* README document new examples
|
||||
- make ReaderSample scheme public
|
||||
* documentation updates
|
||||
* add emulation for UI camera device and flash mode properties
|
||||
* workaround orientation bugs in parent controllers
|
||||
- enable orientation and iPad support for all examples
|
||||
* add orientation detection fall back
|
||||
* fix captureReader not exposed to simulator
|
||||
* fix camera preview stale rotation corner
|
||||
- fix ZBarReaderViewController toolbar layout accomodation
|
||||
- switch pre-release samples to use debug library
|
||||
* update docs to note possible link order dependency
|
||||
* add missing references to new samples
|
||||
* add IB support to ZBarReaderViewController
|
||||
- add tabbed reader sample
|
||||
* add embedded reader sample
|
||||
- factor out camera simulation logic
|
||||
* fix readertest max quality result filtering
|
||||
- thanks to John Boydon for finding this!
|
||||
* improve support for resizing, rotating and embedding the reader
|
||||
* add readertest fixed zoom stops
|
||||
* add manual frame capture
|
||||
- readertest save as PNG
|
||||
* enhance readertest to support default/demo pre-config and distribution
|
||||
* updates for Xcode 4
|
||||
* expose tracking box color
|
||||
|
||||
version 1.1:
|
||||
* fix doc typo (bug #3139087)
|
||||
- add modifier bit docs
|
||||
|
||||
version 1.0.1:
|
||||
* hotfix broken ZBarHelpController back button
|
||||
* release updates
|
||||
- update docs
|
||||
* fix support for GS1 AIs
|
||||
* fix simulated camera image orientation/scaling
|
||||
* cleanup and expose ZBarHelpController
|
||||
* expose enable for reader capture processing
|
||||
* workaround iOS 4.2 hang
|
||||
- update to use latest SDK
|
||||
* add support for Code 93 symbology
|
||||
|
||||
version 1.0:
|
||||
* update to SDK 4.1, clean out LLVM warnings
|
||||
* fix camera simulation gesture
|
||||
|
||||
version 0.1.2:
|
||||
* fix missing header dependency
|
||||
* doc enhancements
|
||||
* force controls to front when showsZBarControls is enabled
|
||||
* fix initial zoom crop (performance bug)
|
||||
* workaround iPhone quartz access past image data
|
||||
|
||||
version 0.1.1:
|
||||
* migrate to binary iPhone SDK distribution (NB backward incompatibilities!)
|
||||
- restructure headers
|
||||
|
||||
version 0.1:
|
||||
* workaround for iPhone simulator builds
|
||||
- refactor ZBarReaderView for capture/simulator specific implementations
|
||||
- fix tracking calculations
|
||||
- fix captured video frame color conversion
|
||||
* fix for poor iPhone 4 performance
|
||||
* enable torch for iPhone 4
|
||||
* fix iPhone circular ref bug
|
||||
* add iPhone cache flush, change new libs to weak refs
|
||||
* fix iPhone async ref bug
|
||||
* enhance iPhone readertest w/more options
|
||||
* add iPhone zoom support, integrate with crop
|
||||
* add iPhone OS 4.0 video capture support
|
||||
- replacement view controller for new camera reader
|
||||
- separate view for use without controller
|
||||
- separate capture delegate for use standalone
|
||||
- add continuous autofocus
|
||||
* cleanup and expose iphone help display API
|
||||
* fixes to new iphone help display
|
||||
* migrate iphone help display to integrated web page (NB resource updates!)
|
||||
- allows easier customization
|
||||
- local links open directly, external links confirm and jump out to Safari
|
||||
- JavaScript hook for help context customization
|
||||
- also enhanced default help (note this changes the required resources)
|
||||
- fix to disable scanning during help overlay
|
||||
- thanks to iafanasyev and others for detailed suggestions
|
||||
* fix iphone custom overlay response (bug #2959617)
|
||||
- thanks to an anonymous user for the patch!
|
||||
* iphone widget performance tuning enhancements
|
||||
- fix crop calculation bug in ZBarImage
|
||||
- add properties to control pre-scan image cropping and scaling
|
||||
- add property for scanner cache control
|
||||
- enable some scanner density control (FIXME should be property)
|
||||
- fix ifdef for quality control (FIXME should be property)
|
||||
- add "sequence" mode test (not actually so useful)
|
||||
* realtime scanning for iphone widget
|
||||
- uses UIGetScreenImage() (NB private)
|
||||
- ZBarImage from CGImage (instead of UIImage)
|
||||
- add crop to scaling step
|
||||
- expose symbol set unfiltered results
|
||||
* iphone widget back compat updates, add basic test app
|
||||
* add Obj-C wrapper
|
||||
* first pass working iPhone "widget"
|
||||
66
iphone/README
Normal file
66
iphone/README
Normal file
@ -0,0 +1,66 @@
|
||||
ZBar iOS SDK
|
||||
============
|
||||
|
||||
ZBar Bar Code Reader is an open source software suite for reading bar
|
||||
codes from various sources, such as video streams, image files and raw
|
||||
intensity sensors. It supports EAN-13/UPC-A, UPC-E, EAN-8, DataBar,
|
||||
Code 128, Code 93, Code 39, Codabar, Interleaved 2 of 5 and QR Code.
|
||||
These are the Objective C wrappers and integrated widget for developing
|
||||
with the library on the iOS platform.
|
||||
|
||||
Check the ZBar project home page for the latest release, forums, etc.
|
||||
|
||||
* http://zbar.sourceforge.net/iphone
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
If you are migrating from a pre-SDK source version of the library,
|
||||
first make sure you remove all of the old references to zbar.xcodeproj
|
||||
and libzbar.a and revert any related build settings.
|
||||
|
||||
To add the SDK to an Xcode project:
|
||||
|
||||
1. Drag ZBarSDK into your Xcode project.
|
||||
3. Add these system frameworks to your project:
|
||||
* AVFoundation.framework (weak)
|
||||
* CoreMedia.framework (weak)
|
||||
* CoreVideo.framework (weak)
|
||||
* QuartzCore.framework
|
||||
* libiconv.dylib
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
See Documentation.html for complete SDK documentation.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
You should be able to open and build the examples directly from the
|
||||
disk image (ignore warnings about the read-only volume). If you have
|
||||
problems with this, please copy the examples to your local drive
|
||||
instead and build from there.
|
||||
|
||||
A tutorial that walks through installing and using the SDK is
|
||||
available in the documentation. The SDK disk image also contains the
|
||||
resulting Xcode project at Examples/ReaderSample.
|
||||
|
||||
Examples/readertest demonstrates most of the configuration options
|
||||
available for the reader.
|
||||
|
||||
Examples/TabReader shows how you can use Interface Builder to add the
|
||||
reader as a tab in a UITabBarController.
|
||||
|
||||
Examples/EmbedReader shows how a ZBarReaderView may be embedded
|
||||
directly in the application view hierarchy.
|
||||
|
||||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Licensed under the GNU Lesser General Public License, version 2.1.
|
||||
http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
|
||||
Copyright 2008-2011 © Jeff Brown <spadix@users.sourceforge.net> et al
|
||||
|
||||
See the included files COPYING and LICENSE for details
|
||||
43
iphone/ZBarCVImage.h
Normal file
43
iphone/ZBarCVImage.h
Normal file
@ -0,0 +1,43 @@
|
||||
//------------------------------------------------------------------------
|
||||
// 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
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
#import <ZBarSDK/ZBarImage.h>
|
||||
#import <CoreVideo/CoreVideo.h>
|
||||
|
||||
// ZBarImage referring to a CVPixelBuffer. used internally to handle
|
||||
// asynchronous conversion to UIImage
|
||||
|
||||
@interface ZBarCVImage
|
||||
: ZBarImage
|
||||
{
|
||||
CVPixelBufferRef pixelBuffer;
|
||||
void *rgbBuffer;
|
||||
NSInvocationOperation *conversion;
|
||||
}
|
||||
|
||||
- (void) waitUntilConverted;
|
||||
|
||||
@property (nonatomic) CVPixelBufferRef pixelBuffer;
|
||||
@property (nonatomic, readonly) void *rgbBuffer;
|
||||
|
||||
@end
|
||||
195
iphone/ZBarCVImage.m
Normal file
195
iphone/ZBarCVImage.m
Normal file
@ -0,0 +1,195 @@
|
||||
//------------------------------------------------------------------------
|
||||
// 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
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
#import "ZBarCVImage.h"
|
||||
#define MODULE ZBarCVImage
|
||||
#import "debug.h"
|
||||
|
||||
static NSOperationQueue *conversionQueue;
|
||||
|
||||
static const void*
|
||||
asyncProvider_getBytePointer (void *info)
|
||||
{
|
||||
// block until data is available
|
||||
ZBarCVImage *image = info;
|
||||
assert(image);
|
||||
[image waitUntilConverted];
|
||||
void *buf = image.rgbBuffer;
|
||||
assert(buf);
|
||||
return(buf);
|
||||
}
|
||||
|
||||
static const CGDataProviderDirectCallbacks asyncProvider = {
|
||||
.version = 0,
|
||||
.getBytePointer = asyncProvider_getBytePointer,
|
||||
.releaseBytePointer = NULL,
|
||||
.getBytesAtPosition = NULL,
|
||||
.releaseInfo = (void*)CFRelease,
|
||||
};
|
||||
|
||||
@implementation ZBarCVImage
|
||||
|
||||
@synthesize pixelBuffer, rgbBuffer;
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
self.pixelBuffer = NULL;
|
||||
if(rgbBuffer) {
|
||||
free(rgbBuffer);
|
||||
rgbBuffer = NULL;
|
||||
}
|
||||
[conversion release];
|
||||
conversion = nil;
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) setPixelBuffer: (CVPixelBufferRef) newbuf
|
||||
{
|
||||
CVPixelBufferRef oldbuf = pixelBuffer;
|
||||
if(newbuf)
|
||||
CVPixelBufferRetain(newbuf);
|
||||
pixelBuffer = newbuf;
|
||||
if(oldbuf)
|
||||
CVPixelBufferRelease(oldbuf);
|
||||
}
|
||||
|
||||
- (void) waitUntilConverted
|
||||
{
|
||||
// operation will at least have been queued already
|
||||
NSOperation *op = [conversion retain];
|
||||
if(!op)
|
||||
return;
|
||||
[op waitUntilFinished];
|
||||
[op release];
|
||||
}
|
||||
|
||||
- (UIImage*) UIImageWithOrientation: (UIImageOrientation) orient
|
||||
{
|
||||
if(!conversion && !rgbBuffer) {
|
||||
// start format conversion in separate thread
|
||||
NSOperationQueue *queue = conversionQueue;
|
||||
if(!queue) {
|
||||
queue = conversionQueue = [NSOperationQueue new];
|
||||
queue.maxConcurrentOperationCount = 1;
|
||||
}
|
||||
else
|
||||
[queue waitUntilAllOperationsAreFinished];
|
||||
|
||||
conversion = [[NSInvocationOperation alloc]
|
||||
initWithTarget: self
|
||||
selector: @selector(convertCVtoRGB)
|
||||
object: nil];
|
||||
[queue addOperation: conversion];
|
||||
[conversion release];
|
||||
}
|
||||
|
||||
// create UIImage before converted data is available
|
||||
CGSize size = self.size;
|
||||
int w = size.width;
|
||||
int h = size.height;
|
||||
|
||||
CGDataProviderRef datasrc =
|
||||
CGDataProviderCreateDirect([self retain], 3 * w * h, &asyncProvider);
|
||||
CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
|
||||
CGImageRef cgimg =
|
||||
CGImageCreate(w, h, 8, 24, 3 * w, cs,
|
||||
kCGBitmapByteOrderDefault, datasrc,
|
||||
NULL, YES, kCGRenderingIntentDefault);
|
||||
CGColorSpaceRelease(cs);
|
||||
CGDataProviderRelease(datasrc);
|
||||
|
||||
UIImage *uiimg =
|
||||
[UIImage imageWithCGImage: cgimg
|
||||
scale: 1
|
||||
orientation: orient];
|
||||
CGImageRelease(cgimg);
|
||||
|
||||
return(uiimg);
|
||||
}
|
||||
|
||||
// convert video frame to a CGImage compatible RGB format
|
||||
// FIXME this is temporary until we can find the native way...
|
||||
- (void) convertCVtoRGB
|
||||
{
|
||||
timer_start;
|
||||
unsigned long format = self.format;
|
||||
assert(format == zbar_fourcc('C','V','2','P'));
|
||||
if(format != zbar_fourcc('C','V','2','P'))
|
||||
return;
|
||||
|
||||
CVPixelBufferLockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly);
|
||||
int w = CVPixelBufferGetWidth(pixelBuffer);
|
||||
int h = CVPixelBufferGetHeight(pixelBuffer);
|
||||
int dy = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0);
|
||||
int duv = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1);
|
||||
uint8_t *py = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0);
|
||||
uint8_t *puv = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1);
|
||||
if(!py || !puv || dy < w || duv < w)
|
||||
goto error;
|
||||
|
||||
int datalen = 3 * w * h;
|
||||
// Quartz accesses some undocumented amount past allocated data?
|
||||
// ...allocate extra to compensate
|
||||
uint8_t *pdst = rgbBuffer = malloc(datalen + 3 * w);
|
||||
if(!pdst)
|
||||
goto error;
|
||||
[self setData: rgbBuffer
|
||||
withLength: datalen];
|
||||
|
||||
for(int y = 0; y < h; y++) {
|
||||
const uint8_t *qy = py;
|
||||
const uint8_t *quv = puv;
|
||||
for(int x = 0; x < w; x++) {
|
||||
int Y1 = *(qy++) - 16;
|
||||
int Cb = *(quv) - 128;
|
||||
int Cr = *(quv + 1) - 128;
|
||||
Y1 *= 4769;
|
||||
quv += (x & 1) << 1;
|
||||
int r = (Y1 + 6537 * Cr + 2048) / 4096;
|
||||
int g = (Y1 - 1604 * Cb - 3329 * Cr + 2048) / 4096;
|
||||
int b = (Y1 + 8263 * Cb + 2048) / 4096;
|
||||
|
||||
r = (r | -!!(r >> 8)) & -((r >> 8) >= 0);
|
||||
g = (g | -!!(g >> 8)) & -((g >> 8) >= 0);
|
||||
b = (b | -!!(b >> 8)) & -((b >> 8) >= 0);
|
||||
|
||||
*(pdst++) = r;
|
||||
*(pdst++) = g;
|
||||
*(pdst++) = b;
|
||||
}
|
||||
py += dy;
|
||||
if(y & 1)
|
||||
puv += duv;
|
||||
}
|
||||
|
||||
error:
|
||||
CVPixelBufferUnlockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly);
|
||||
zlog(@"convert time %gs", timer_elapsed(t_start, timer_now()));
|
||||
|
||||
// release buffer as soon as conversion is complete
|
||||
self.pixelBuffer = NULL;
|
||||
|
||||
conversion = nil;
|
||||
}
|
||||
|
||||
@end
|
||||
120
iphone/ZBarCameraSimulator.m
Normal file
120
iphone/ZBarCameraSimulator.m
Normal file
@ -0,0 +1,120 @@
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright 2010-2011 (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
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
#import <ZBarSDK/ZBarCameraSimulator.h>
|
||||
#import <ZBarSDK/ZBarReaderView.h>
|
||||
|
||||
// hack around missing simulator support for AVCapture interfaces
|
||||
|
||||
@implementation ZBarCameraSimulator
|
||||
|
||||
@synthesize readerView;
|
||||
|
||||
- (id) initWithViewController: (UIViewController*) vc
|
||||
{
|
||||
if(!TARGET_IPHONE_SIMULATOR) {
|
||||
[self release];
|
||||
return(nil);
|
||||
}
|
||||
self = [super init];
|
||||
if(!self)
|
||||
return(nil);
|
||||
|
||||
viewController = vc;
|
||||
|
||||
return(self);
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
viewController = nil;
|
||||
readerView = nil;
|
||||
[picker release];
|
||||
picker = nil;
|
||||
[pickerPopover release];
|
||||
pickerPopover = nil;
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) setReaderView: (ZBarReaderView*) view
|
||||
{
|
||||
ZBarReaderView *oldView = readerView;
|
||||
readerView = [view retain];
|
||||
[oldView release];
|
||||
|
||||
UILongPressGestureRecognizer *gesture =
|
||||
[[UILongPressGestureRecognizer alloc]
|
||||
initWithTarget: self
|
||||
action: @selector(didLongPress:)];
|
||||
gesture.numberOfTouchesRequired = 2;
|
||||
[view addGestureRecognizer: gesture];
|
||||
[gesture release];
|
||||
}
|
||||
|
||||
- (void) didLongPress: (UILongPressGestureRecognizer*) gesture
|
||||
{
|
||||
if(gesture.state == UIGestureRecognizerStateBegan)
|
||||
[self takePicture];
|
||||
}
|
||||
|
||||
- (void) takePicture
|
||||
{
|
||||
if(!picker) {
|
||||
picker = [UIImagePickerController new];
|
||||
picker.delegate = self;
|
||||
}
|
||||
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
if(!pickerPopover)
|
||||
pickerPopover = [[UIPopoverController alloc]
|
||||
initWithContentViewController: picker];
|
||||
[pickerPopover presentPopoverFromRect: CGRectZero
|
||||
inView: readerView
|
||||
permittedArrowDirections: UIPopoverArrowDirectionAny
|
||||
animated: YES];
|
||||
}
|
||||
else
|
||||
[viewController presentModalViewController: picker
|
||||
animated: YES];
|
||||
}
|
||||
|
||||
- (void) imagePickerController: (UIImagePickerController*) _picker
|
||||
didFinishPickingMediaWithInfo: (NSDictionary*) info
|
||||
{
|
||||
UIImage *image = [info objectForKey: UIImagePickerControllerOriginalImage];
|
||||
|
||||
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
|
||||
[pickerPopover dismissPopoverAnimated: YES];
|
||||
else
|
||||
[_picker dismissModalViewControllerAnimated: YES];
|
||||
|
||||
[readerView performSelector: @selector(scanImage:)
|
||||
withObject: image
|
||||
afterDelay: .1];
|
||||
}
|
||||
|
||||
- (void) imagePickerControllerDidCancel: (UIImagePickerController*) _picker
|
||||
{
|
||||
[_picker dismissModalViewControllerAnimated: YES];
|
||||
}
|
||||
|
||||
@end
|
||||
370
iphone/ZBarCaptureReader.m
Normal file
370
iphone/ZBarCaptureReader.m
Normal file
@ -0,0 +1,370 @@
|
||||
//------------------------------------------------------------------------
|
||||
// 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
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
#import <libkern/OSAtomic.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import <CoreMedia/CoreMedia.h>
|
||||
#import <CoreVideo/CoreVideo.h>
|
||||
#import <ZBarSDK/ZBarCaptureReader.h>
|
||||
#import <ZBarSDK/ZBarImageScanner.h>
|
||||
#import "ZBarCVImage.h"
|
||||
|
||||
#define MODULE ZBarCaptureReader
|
||||
#import "debug.h"
|
||||
|
||||
enum {
|
||||
STOPPED = 0,
|
||||
RUNNING = 1,
|
||||
PAUSED = 2,
|
||||
CAPTURE = 4,
|
||||
};
|
||||
|
||||
@implementation ZBarCaptureReader
|
||||
|
||||
@synthesize captureOutput, captureDelegate, scanner, scanCrop, size,
|
||||
framesPerSecond, enableCache;
|
||||
@dynamic enableReader;
|
||||
|
||||
- (void) initResult
|
||||
{
|
||||
[result release];
|
||||
result = [ZBarCVImage new];
|
||||
result.format = [ZBarImage fourcc: @"CV2P"];
|
||||
}
|
||||
|
||||
- (id) initWithImageScanner: (ZBarImageScanner*) _scanner
|
||||
{
|
||||
self = [super init];
|
||||
if(!self)
|
||||
return(nil);
|
||||
|
||||
t_fps = t_frame = timer_now();
|
||||
enableCache = YES;
|
||||
|
||||
scanner = [_scanner retain];
|
||||
scanCrop = CGRectMake(0, 0, 1, 1);
|
||||
image = [ZBarImage new];
|
||||
image.format = [ZBarImage fourcc: @"Y800"];
|
||||
[self initResult];
|
||||
|
||||
captureOutput = [AVCaptureVideoDataOutput new];
|
||||
captureOutput.alwaysDiscardsLateVideoFrames = YES;
|
||||
|
||||
#ifdef FIXED_8697526
|
||||
/* iOS 4.2 introduced a bug that causes [session startRunning] to
|
||||
* hang if the session has a preview layer and this property is
|
||||
* specified at the output. As this happens to be the default
|
||||
* setting for the currently supported devices, it can be omitted
|
||||
* without causing a functional problem (for now...). Of course,
|
||||
* we still have no idea what the real problem is, or how robust
|
||||
* this is as a workaround...
|
||||
*/
|
||||
captureOutput.videoSettings =
|
||||
[NSDictionary
|
||||
dictionaryWithObject:
|
||||
[NSNumber numberWithInt:
|
||||
kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange]
|
||||
forKey: (NSString*)kCVPixelBufferPixelFormatTypeKey];
|
||||
#endif
|
||||
|
||||
queue = dispatch_queue_create("ZBarCaptureReader", NULL);
|
||||
[captureOutput setSampleBufferDelegate:
|
||||
(id<AVCaptureVideoDataOutputSampleBufferDelegate>)self
|
||||
queue: queue];
|
||||
|
||||
return(self);
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
self = [self initWithImageScanner:
|
||||
[[ZBarImageScanner new]
|
||||
autorelease]];
|
||||
if(!self)
|
||||
return(nil);
|
||||
|
||||
[scanner setSymbology: 0
|
||||
config: ZBAR_CFG_X_DENSITY
|
||||
to: 3];
|
||||
[scanner setSymbology: 0
|
||||
config: ZBAR_CFG_Y_DENSITY
|
||||
to: 3];
|
||||
return(self);
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
captureDelegate = nil;
|
||||
|
||||
// queue continues to run after stopping (NB even after DidStopRunning!);
|
||||
// ensure released delegate is not called. (also NB that the queue
|
||||
// may not be null, even in this case...)
|
||||
[captureOutput setSampleBufferDelegate: nil
|
||||
queue: queue];
|
||||
[captureOutput release];
|
||||
captureOutput = nil;
|
||||
dispatch_release(queue);
|
||||
|
||||
[image release];
|
||||
image = nil;
|
||||
[result release];
|
||||
result = nil;
|
||||
[scanner release];
|
||||
scanner = nil;
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (BOOL) enableReader
|
||||
{
|
||||
return(OSAtomicOr32Barrier(0, &state) & RUNNING);
|
||||
}
|
||||
|
||||
- (void) setEnableReader: (BOOL) enable
|
||||
{
|
||||
if(!enable)
|
||||
OSAtomicAnd32Barrier(STOPPED, &state);
|
||||
else if(!(OSAtomicOr32OrigBarrier(RUNNING, &state) & RUNNING)) {
|
||||
OSAtomicAnd32Barrier(~PAUSED, &state);
|
||||
@synchronized(scanner) {
|
||||
scanner.enableCache = enableCache;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void) willStartRunning
|
||||
{
|
||||
self.enableReader = YES;
|
||||
}
|
||||
|
||||
- (void) willStopRunning
|
||||
{
|
||||
self.enableReader = NO;
|
||||
}
|
||||
|
||||
- (void) flushCache
|
||||
{
|
||||
@synchronized(scanner) {
|
||||
scanner.enableCache = enableCache;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) captureFrame
|
||||
{
|
||||
OSAtomicOr32(CAPTURE, &state);
|
||||
}
|
||||
|
||||
- (void) setCaptureDelegate: (id<ZBarCaptureDelegate>) delegate
|
||||
{
|
||||
@synchronized(scanner) {
|
||||
captureDelegate = delegate;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) cropUpdate
|
||||
{
|
||||
@synchronized(scanner) {
|
||||
image.crop = CGRectMake(scanCrop.origin.x * width,
|
||||
scanCrop.origin.y * height,
|
||||
scanCrop.size.width * width,
|
||||
scanCrop.size.height * height);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) setScanCrop: (CGRect) crop
|
||||
{
|
||||
if(CGRectEqualToRect(scanCrop, crop))
|
||||
return;
|
||||
scanCrop = crop;
|
||||
[self cropUpdate];
|
||||
}
|
||||
|
||||
- (void) didTrackSymbols: (ZBarSymbolSet*) syms
|
||||
{
|
||||
[captureDelegate
|
||||
captureReader: self
|
||||
didTrackSymbols: syms];
|
||||
}
|
||||
|
||||
- (void) didReadNewSymbolsFromImage: (ZBarImage*) img
|
||||
{
|
||||
timer_start;
|
||||
[captureDelegate
|
||||
captureReader: self
|
||||
didReadNewSymbolsFromImage: img];
|
||||
OSAtomicAnd32Barrier(~PAUSED, &state);
|
||||
zlog(@"latency: delegate=%gs total=%gs",
|
||||
timer_elapsed(t_start, timer_now()),
|
||||
timer_elapsed(t_scan, timer_now()));
|
||||
}
|
||||
|
||||
- (void) setFramesPerSecond: (CGFloat) fps
|
||||
{
|
||||
framesPerSecond = fps;
|
||||
}
|
||||
|
||||
- (void) updateFPS: (NSNumber*) val
|
||||
{
|
||||
[self setFramesPerSecond: val.doubleValue];
|
||||
}
|
||||
|
||||
- (void) setSize: (CGSize) _size
|
||||
{
|
||||
size = _size;
|
||||
}
|
||||
|
||||
- (void) updateSize: (CFDictionaryRef) val
|
||||
{
|
||||
CGSize _size;
|
||||
if(CGSizeMakeWithDictionaryRepresentation(val, &_size))
|
||||
[self setSize: _size];
|
||||
}
|
||||
|
||||
- (void) captureOutput: (AVCaptureOutput*) output
|
||||
didOutputSampleBuffer: (CMSampleBufferRef) samp
|
||||
fromConnection: (AVCaptureConnection*) conn
|
||||
{
|
||||
// queue is apparently not flushed when stopping;
|
||||
// only process when running
|
||||
uint32_t _state = OSAtomicOr32Barrier(0, &state);
|
||||
if((_state & (PAUSED | RUNNING)) != RUNNING)
|
||||
return;
|
||||
|
||||
NSAutoreleasePool *pool = [NSAutoreleasePool new];
|
||||
image.sequence = framecnt++;
|
||||
|
||||
uint64_t now = timer_now();
|
||||
double dt = timer_elapsed(t_frame, now);
|
||||
t_frame = now;
|
||||
if(dt > 2) {
|
||||
t_fps = now;
|
||||
dt_frame = 0;
|
||||
}
|
||||
else if(!dt_frame)
|
||||
dt_frame = dt;
|
||||
dt_frame = (dt_frame + dt) / 2;
|
||||
if(timer_elapsed(t_fps, now) >= 1) {
|
||||
[self performSelectorOnMainThread: @selector(updateFPS:)
|
||||
withObject: [NSNumber numberWithDouble: 1 / dt_frame]
|
||||
waitUntilDone: NO];
|
||||
t_fps = now;
|
||||
}
|
||||
|
||||
CVImageBufferRef buf = CMSampleBufferGetImageBuffer(samp);
|
||||
if(CMSampleBufferGetNumSamples(samp) != 1 ||
|
||||
!CMSampleBufferIsValid(samp) ||
|
||||
!CMSampleBufferDataIsReady(samp) ||
|
||||
!buf) {
|
||||
zlog(@"ERROR: invalid sample");
|
||||
goto error;
|
||||
}
|
||||
|
||||
OSType format = CVPixelBufferGetPixelFormatType(buf);
|
||||
int planes = CVPixelBufferGetPlaneCount(buf);
|
||||
|
||||
if(format != kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange ||
|
||||
!planes) {
|
||||
zlog(@"ERROR: invalid buffer format");
|
||||
goto error;
|
||||
}
|
||||
|
||||
int w = CVPixelBufferGetBytesPerRowOfPlane(buf, 0);
|
||||
int h = CVPixelBufferGetHeightOfPlane(buf, 0);
|
||||
CVReturn rc =
|
||||
CVPixelBufferLockBaseAddress(buf, kCVPixelBufferLock_ReadOnly);
|
||||
if(!w || !h || rc) {
|
||||
zlog(@"ERROR: invalid buffer data");
|
||||
goto error;
|
||||
}
|
||||
|
||||
void *data = CVPixelBufferGetBaseAddressOfPlane(buf, 0);
|
||||
if(data) {
|
||||
[image setData: data
|
||||
withLength: w * h];
|
||||
|
||||
BOOL doTrack = NO;
|
||||
int ngood = 0;
|
||||
ZBarSymbolSet *syms = nil;
|
||||
@synchronized(scanner) {
|
||||
if(width != w || height != h) {
|
||||
width = w;
|
||||
height = h;
|
||||
CGSize _size = CGSizeMake(w, h);
|
||||
CFDictionaryRef sized =
|
||||
CGSizeCreateDictionaryRepresentation(_size);
|
||||
if(sized) {
|
||||
[self performSelectorOnMainThread: @selector(updateSize:)
|
||||
withObject: (id)sized
|
||||
waitUntilDone: NO];
|
||||
CFRelease(sized);
|
||||
}
|
||||
image.size = _size;
|
||||
[self cropUpdate];
|
||||
}
|
||||
|
||||
ngood = [scanner scanImage: image];
|
||||
syms = scanner.results;
|
||||
doTrack = [captureDelegate respondsToSelector:
|
||||
@selector(captureReader:didTrackSymbols:)];
|
||||
}
|
||||
now = timer_now();
|
||||
|
||||
if(ngood >= 0) {
|
||||
// return unfiltered results for tracking feedback
|
||||
syms.filterSymbols = NO;
|
||||
int nraw = syms.count;
|
||||
if(nraw > 0 || (_state & CAPTURE))
|
||||
zlog(@"scan image: %dx%d crop=%@ ngood=%d nraw=%d st=%d",
|
||||
w, h, NSStringFromCGRect(image.crop), ngood, nraw, _state);
|
||||
|
||||
if(ngood || (_state & CAPTURE)) {
|
||||
// copy image data so we can release the buffer
|
||||
result.size = CGSizeMake(w, h);
|
||||
result.pixelBuffer = buf;
|
||||
result.symbols = syms;
|
||||
t_scan = now;
|
||||
OSAtomicXor32Barrier((_state & CAPTURE) | PAUSED, &state);
|
||||
[self performSelectorOnMainThread:
|
||||
@selector(didReadNewSymbolsFromImage:)
|
||||
withObject: result
|
||||
waitUntilDone: NO];
|
||||
[self initResult];
|
||||
}
|
||||
|
||||
if(nraw && doTrack)
|
||||
[self performSelectorOnMainThread:
|
||||
@selector(didTrackSymbols:)
|
||||
withObject: syms
|
||||
waitUntilDone: NO];
|
||||
}
|
||||
[image setData: NULL
|
||||
withLength: 0];
|
||||
}
|
||||
else
|
||||
zlog(@"ERROR: invalid data");
|
||||
CVPixelBufferUnlockBaseAddress(buf, kCVPixelBufferLock_ReadOnly);
|
||||
|
||||
error:
|
||||
[pool release];
|
||||
}
|
||||
|
||||
@end
|
||||
267
iphone/ZBarHelpController.m
Normal file
267
iphone/ZBarHelpController.m
Normal file
@ -0,0 +1,267 @@
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright 2009-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
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
#import <ZBarSDK/ZBarHelpController.h>
|
||||
|
||||
#define MODULE ZBarHelpController
|
||||
#import "debug.h"
|
||||
|
||||
@implementation ZBarHelpController
|
||||
|
||||
@synthesize delegate;
|
||||
|
||||
- (id) initWithReason: (NSString*) _reason
|
||||
{
|
||||
self = [super init];
|
||||
if(!self)
|
||||
return(nil);
|
||||
|
||||
if(!_reason)
|
||||
_reason = @"INFO";
|
||||
reason = [_reason retain];
|
||||
return(self);
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
return([self initWithReason: nil]);
|
||||
}
|
||||
|
||||
- (void) cleanup
|
||||
{
|
||||
[toolbar release];
|
||||
toolbar = nil;
|
||||
[webView release];
|
||||
webView = nil;
|
||||
[doneBtn release];
|
||||
doneBtn = nil;
|
||||
[backBtn release];
|
||||
backBtn = nil;
|
||||
[space release];
|
||||
space = nil;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[self cleanup];
|
||||
[reason release];
|
||||
reason = nil;
|
||||
[linkURL release];
|
||||
linkURL = nil;
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
UIView *view = self.view;
|
||||
CGRect bounds = self.view.bounds;
|
||||
if(!bounds.size.width || !bounds.size.height)
|
||||
view.frame = bounds = CGRectMake(0, 0, 320, 480);
|
||||
view.backgroundColor = [UIColor colorWithWhite: .125f
|
||||
alpha: 1];
|
||||
view.autoresizingMask = (UIViewAutoresizingFlexibleWidth |
|
||||
UIViewAutoresizingFlexibleHeight);
|
||||
|
||||
webView = [[UIWebView alloc]
|
||||
initWithFrame: CGRectMake(0, 0,
|
||||
bounds.size.width,
|
||||
bounds.size.height - 44)];
|
||||
webView.delegate = self;
|
||||
webView.backgroundColor = [UIColor colorWithWhite: .125f
|
||||
alpha: 1];
|
||||
webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth |
|
||||
UIViewAutoresizingFlexibleHeight |
|
||||
UIViewAutoresizingFlexibleBottomMargin);
|
||||
webView.hidden = YES;
|
||||
[view addSubview: webView];
|
||||
|
||||
toolbar = [[UIToolbar alloc]
|
||||
initWithFrame: CGRectMake(0, bounds.size.height - 44,
|
||||
bounds.size.width, 44)];
|
||||
toolbar.barStyle = UIBarStyleBlackOpaque;
|
||||
toolbar.autoresizingMask = (UIViewAutoresizingFlexibleWidth |
|
||||
UIViewAutoresizingFlexibleHeight |
|
||||
UIViewAutoresizingFlexibleTopMargin);
|
||||
|
||||
doneBtn = [[UIBarButtonItem alloc]
|
||||
initWithBarButtonSystemItem: UIBarButtonSystemItemDone
|
||||
target: self
|
||||
action: @selector(dismiss)];
|
||||
|
||||
backBtn = [[UIBarButtonItem alloc]
|
||||
initWithImage: [UIImage imageNamed: @"zbar-back.png"]
|
||||
style: UIBarButtonItemStylePlain
|
||||
target: webView
|
||||
action: @selector(goBack)];
|
||||
|
||||
space = [[UIBarButtonItem alloc]
|
||||
initWithBarButtonSystemItem:
|
||||
UIBarButtonSystemItemFlexibleSpace
|
||||
target: nil
|
||||
action: nil];
|
||||
|
||||
toolbar.items = [NSArray arrayWithObjects: space, doneBtn, nil];
|
||||
|
||||
[view addSubview: toolbar];
|
||||
|
||||
NSString *path = [[NSBundle mainBundle]
|
||||
pathForResource: @"zbar-help"
|
||||
ofType: @"html"];
|
||||
|
||||
NSURLRequest *req = nil;
|
||||
if(path) {
|
||||
NSURL *url = [NSURL fileURLWithPath: path
|
||||
isDirectory: NO];
|
||||
if(url)
|
||||
req = [NSURLRequest requestWithURL: url];
|
||||
}
|
||||
if(req)
|
||||
[webView loadRequest: req];
|
||||
else
|
||||
NSLog(@"ERROR: unable to load zbar-help.html from bundle");
|
||||
}
|
||||
|
||||
- (void) viewDidUnload
|
||||
{
|
||||
[self cleanup];
|
||||
[super viewDidUnload];
|
||||
}
|
||||
|
||||
- (void) viewWillAppear: (BOOL) animated
|
||||
{
|
||||
assert(webView);
|
||||
if(webView.loading)
|
||||
webView.hidden = YES;
|
||||
webView.delegate = self;
|
||||
[super viewWillAppear: animated];
|
||||
}
|
||||
|
||||
- (void) viewWillDisappear: (BOOL) animated
|
||||
{
|
||||
[webView stopLoading];
|
||||
webView.delegate = nil;
|
||||
[super viewWillDisappear: animated];
|
||||
}
|
||||
|
||||
- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) orient
|
||||
{
|
||||
return([self isInterfaceOrientationSupported: orient]);
|
||||
}
|
||||
|
||||
- (void) willAnimateRotationToInterfaceOrientation: (UIInterfaceOrientation) orient
|
||||
duration: (NSTimeInterval) duration
|
||||
{
|
||||
[webView reload];
|
||||
}
|
||||
|
||||
- (void) didRotateFromInterfaceOrientation: (UIInterfaceOrientation) orient
|
||||
{
|
||||
zlog(@"frame=%@ webView.frame=%@ toolbar.frame=%@",
|
||||
NSStringFromCGRect(self.view.frame),
|
||||
NSStringFromCGRect(webView.frame),
|
||||
NSStringFromCGRect(toolbar.frame));
|
||||
}
|
||||
|
||||
- (BOOL) isInterfaceOrientationSupported: (UIInterfaceOrientation) orient
|
||||
{
|
||||
UIViewController *parent = self.parentViewController;
|
||||
if(parent && !orientations)
|
||||
return([parent shouldAutorotateToInterfaceOrientation: orient]);
|
||||
return((orientations >> orient) & 1);
|
||||
}
|
||||
|
||||
- (void) setInterfaceOrientation: (UIInterfaceOrientation) orient
|
||||
supported: (BOOL) supported
|
||||
{
|
||||
NSUInteger mask = 1 << orient;
|
||||
if(supported)
|
||||
orientations |= mask;
|
||||
else
|
||||
orientations &= ~mask;
|
||||
}
|
||||
|
||||
- (void) dismiss
|
||||
{
|
||||
if([delegate respondsToSelector: @selector(helpControllerDidFinish:)])
|
||||
[delegate helpControllerDidFinish: self];
|
||||
else
|
||||
[self dismissModalViewControllerAnimated: YES];
|
||||
}
|
||||
|
||||
- (void) webViewDidFinishLoad: (UIWebView*) view
|
||||
{
|
||||
if(view.hidden) {
|
||||
[view stringByEvaluatingJavaScriptFromString:
|
||||
[NSString stringWithFormat:
|
||||
@"onZBarHelp({reason:\"%@\"});", reason]];
|
||||
[UIView beginAnimations: @"ZBarHelp"
|
||||
context: nil];
|
||||
view.hidden = NO;
|
||||
[UIView commitAnimations];
|
||||
}
|
||||
|
||||
BOOL canGoBack = [view canGoBack];
|
||||
NSArray *items = toolbar.items;
|
||||
if(canGoBack != ([items objectAtIndex: 0] == backBtn)) {
|
||||
if(canGoBack)
|
||||
items = [NSArray arrayWithObjects: backBtn, space, doneBtn, nil];
|
||||
else
|
||||
items = [NSArray arrayWithObjects: space, doneBtn, nil];
|
||||
[toolbar setItems: items
|
||||
animated: YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL) webView: (UIWebView*) view
|
||||
shouldStartLoadWithRequest: (NSURLRequest*) req
|
||||
navigationType: (UIWebViewNavigationType) nav
|
||||
{
|
||||
NSURL *url = [req URL];
|
||||
if([url isFileURL])
|
||||
return(YES);
|
||||
|
||||
linkURL = [url retain];
|
||||
UIAlertView *alert =
|
||||
[[UIAlertView alloc]
|
||||
initWithTitle: @"Open External Link"
|
||||
message: @"Close this application and open link in Safari?"
|
||||
delegate: nil
|
||||
cancelButtonTitle: @"Cancel"
|
||||
otherButtonTitles: @"OK", nil];
|
||||
alert.delegate = self;
|
||||
[alert show];
|
||||
[alert release];
|
||||
return(NO);
|
||||
}
|
||||
|
||||
- (void) alertView: (UIAlertView*) view
|
||||
clickedButtonAtIndex: (NSInteger) idx
|
||||
{
|
||||
if(idx)
|
||||
[[UIApplication sharedApplication]
|
||||
openURL: linkURL];
|
||||
}
|
||||
|
||||
@end
|
||||
306
iphone/ZBarImage.m
Normal file
306
iphone/ZBarImage.m
Normal file
@ -0,0 +1,306 @@
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright 2009-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
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <ZBarSDK/ZBarImage.h>
|
||||
#import "debug.h"
|
||||
|
||||
static void image_cleanup(zbar_image_t *zimg)
|
||||
{
|
||||
ZBarImage *image = zbar_image_get_userdata(zimg);
|
||||
[image cleanup];
|
||||
}
|
||||
|
||||
@implementation ZBarImage
|
||||
|
||||
@dynamic format, sequence, size, crop, data, dataLength, symbols, zbarImage,
|
||||
UIImage;
|
||||
|
||||
+ (unsigned long) fourcc: (NSString*) format
|
||||
{
|
||||
return(zbar_fourcc_parse([format UTF8String]));
|
||||
}
|
||||
|
||||
- (id) initWithImage: (zbar_image_t*) image
|
||||
{
|
||||
if(!image) {
|
||||
[self release];
|
||||
return(nil);
|
||||
}
|
||||
if(self = [super init]) {
|
||||
zimg = image;
|
||||
zbar_image_ref(image, 1);
|
||||
zbar_image_set_userdata(zimg, self);
|
||||
}
|
||||
return(self);
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
zbar_image_t *image = zbar_image_create();
|
||||
self = [self initWithImage: image];
|
||||
zbar_image_ref(image, -1);
|
||||
return(self);
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
if(zimg) {
|
||||
zbar_image_ref(zimg, -1);
|
||||
zimg = NULL;
|
||||
}
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (id) initWithCGImage: (CGImageRef) image
|
||||
crop: (CGRect) crop
|
||||
size: (CGSize) size
|
||||
{
|
||||
if(!(self = [self init]))
|
||||
return(nil);
|
||||
uint64_t t_start = timer_now();
|
||||
|
||||
unsigned int w = size.width + 0.5;
|
||||
unsigned int h = size.height + 0.5;
|
||||
|
||||
unsigned long datalen = w * h;
|
||||
uint8_t *raw = malloc(datalen);
|
||||
if(!raw) {
|
||||
[self release];
|
||||
return(nil);
|
||||
}
|
||||
|
||||
zbar_image_set_data(zimg, raw, datalen, zbar_image_free_data);
|
||||
zbar_image_set_format(zimg, zbar_fourcc('Y','8','0','0'));
|
||||
zbar_image_set_size(zimg, w, h);
|
||||
|
||||
// scale and crop simultaneously
|
||||
CGFloat scale = size.width / crop.size.width;
|
||||
crop.origin.x *= -scale;
|
||||
crop.size.width = scale * (CGFloat)CGImageGetWidth(image);
|
||||
scale = size.height / crop.size.height;
|
||||
CGFloat height = CGImageGetHeight(image);
|
||||
// compensate for wacky origin
|
||||
crop.origin.y = height - crop.origin.y - crop.size.height;
|
||||
crop.origin.y *= -scale;
|
||||
crop.size.height = scale * height;
|
||||
|
||||
// generate grayscale image data
|
||||
CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();
|
||||
CGContextRef ctx =
|
||||
CGBitmapContextCreate(raw, w, h, 8, w, cs, kCGImageAlphaNone);
|
||||
CGColorSpaceRelease(cs);
|
||||
CGContextSetAllowsAntialiasing(ctx, 0);
|
||||
|
||||
CGContextDrawImage(ctx, crop, image);
|
||||
|
||||
#if 0
|
||||
zlog(@"convert image %dx%d: crop %g,%g %gx%g size %gx%g (%dx%d)",
|
||||
CGImageGetWidth(image), CGImageGetHeight(image),
|
||||
crop.origin.x, crop.origin.y, crop.size.width, crop.size.height,
|
||||
size.width, size.height, w, h);
|
||||
CGImageRef cgdump = CGBitmapContextCreateImage(ctx);
|
||||
UIImage *uidump = [[UIImage alloc]
|
||||
initWithCGImage: cgdump];
|
||||
CGImageRelease(cgdump);
|
||||
UIImageWriteToSavedPhotosAlbum(uidump, nil, nil, NULL);
|
||||
[uidump release];
|
||||
#endif
|
||||
|
||||
CGContextRelease(ctx);
|
||||
|
||||
t_convert = timer_elapsed(t_start, timer_now());
|
||||
return(self);
|
||||
}
|
||||
|
||||
- (id) initWithCGImage: (CGImageRef) image
|
||||
size: (CGSize) size
|
||||
{
|
||||
CGRect crop = CGRectMake(0, 0,
|
||||
CGImageGetWidth(image),
|
||||
CGImageGetHeight(image));
|
||||
return([self initWithCGImage: image
|
||||
crop: crop
|
||||
size: size]);
|
||||
}
|
||||
|
||||
- (id) initWithCGImage: (CGImageRef) image
|
||||
{
|
||||
CGRect crop = CGRectMake(0, 0,
|
||||
CGImageGetWidth(image),
|
||||
CGImageGetHeight(image));
|
||||
return([self initWithCGImage: image
|
||||
crop: crop
|
||||
size: crop.size]);
|
||||
}
|
||||
|
||||
- (zbar_image_t*) image
|
||||
{
|
||||
return(zimg);
|
||||
}
|
||||
|
||||
- (unsigned long) format
|
||||
{
|
||||
return(zbar_image_get_format(zimg));
|
||||
}
|
||||
|
||||
- (void) setFormat: (unsigned long) format
|
||||
{
|
||||
zbar_image_set_format(zimg, format);
|
||||
}
|
||||
|
||||
- (unsigned) sequence
|
||||
{
|
||||
return(zbar_image_get_sequence(zimg));
|
||||
}
|
||||
|
||||
- (void) setSequence: (unsigned) seq
|
||||
{
|
||||
zbar_image_set_sequence(zimg, seq);
|
||||
}
|
||||
|
||||
- (CGSize) size
|
||||
{
|
||||
unsigned w, h;
|
||||
zbar_image_get_size(zimg, &w, &h);
|
||||
return(CGSizeMake(w, h));
|
||||
}
|
||||
|
||||
- (void) setSize: (CGSize) size
|
||||
{
|
||||
zbar_image_set_size(zimg, size.width + .5, size.height + .5);
|
||||
}
|
||||
|
||||
- (CGRect) crop
|
||||
{
|
||||
unsigned x, y, w, h;
|
||||
zbar_image_get_crop(zimg, &x, &y, &w, &h);
|
||||
return(CGRectMake(x, y, w, h));
|
||||
}
|
||||
|
||||
- (void) setCrop: (CGRect) crop
|
||||
{
|
||||
zbar_image_set_crop(zimg, crop.origin.x + .5, crop.origin.y + .5,
|
||||
crop.size.width + .5, crop.size.height + .5);
|
||||
}
|
||||
|
||||
- (ZBarSymbolSet*) symbols
|
||||
{
|
||||
return([[[ZBarSymbolSet alloc]
|
||||
initWithSymbolSet: zbar_image_get_symbols(zimg)]
|
||||
autorelease]);
|
||||
}
|
||||
|
||||
- (void) setSymbols: (ZBarSymbolSet*) symbols
|
||||
{
|
||||
zbar_image_set_symbols(zimg, [symbols zbarSymbolSet]);
|
||||
}
|
||||
|
||||
- (const void*) data
|
||||
{
|
||||
return(zbar_image_get_data(zimg));
|
||||
}
|
||||
|
||||
- (unsigned long) dataLength
|
||||
{
|
||||
return(zbar_image_get_data_length(zimg));
|
||||
}
|
||||
|
||||
- (void) setData: (const void*) data
|
||||
withLength: (unsigned long) length
|
||||
{
|
||||
zbar_image_set_data(zimg, data, length, image_cleanup);
|
||||
}
|
||||
|
||||
- (zbar_image_t*) zbarImage
|
||||
{
|
||||
return(zimg);
|
||||
}
|
||||
|
||||
- (UIImage*) UIImageWithOrientation: (UIImageOrientation) orient
|
||||
{
|
||||
unsigned long format = self.format;
|
||||
size_t bpc, bpp;
|
||||
switch(format)
|
||||
{
|
||||
case zbar_fourcc('R','G','B','3'):
|
||||
bpc = 8;
|
||||
bpp = 24;
|
||||
break;
|
||||
case zbar_fourcc('R','G','B','4'):
|
||||
bpc = 8;
|
||||
bpp = 32;
|
||||
break;
|
||||
case zbar_fourcc('R','G','B','Q'):
|
||||
bpc = 5;
|
||||
bpp = 16;
|
||||
break;
|
||||
default:
|
||||
NSLog(@"ERROR: format %.4s(%08lx) is unsupported",
|
||||
(char*)&format, format);
|
||||
assert(0);
|
||||
return(nil);
|
||||
};
|
||||
|
||||
unsigned w = zbar_image_get_width(zimg);
|
||||
unsigned h = zbar_image_get_height(zimg);
|
||||
const void *data = zbar_image_get_data(zimg);
|
||||
size_t datalen = zbar_image_get_data_length(zimg);
|
||||
CGDataProviderRef datasrc =
|
||||
CGDataProviderCreateWithData(self, data, datalen, (void*)CFRelease);
|
||||
CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
|
||||
CGImageRef cgimg =
|
||||
CGImageCreate(w, h, bpc, bpp, ((bpp + 7) >> 3) * w, cs,
|
||||
kCGBitmapByteOrderDefault |
|
||||
kCGImageAlphaNoneSkipFirst,
|
||||
datasrc, NULL, YES, kCGRenderingIntentDefault);
|
||||
CGColorSpaceRelease(cs);
|
||||
CGDataProviderRelease(datasrc);
|
||||
|
||||
UIImage *uiimg =
|
||||
[UIImage imageWithCGImage: cgimg
|
||||
scale: 1
|
||||
orientation: orient];
|
||||
CGImageRelease(cgimg);
|
||||
return(uiimg);
|
||||
}
|
||||
|
||||
- (UIImage*) UIImage
|
||||
{
|
||||
return([self UIImageWithOrientation: UIImageOrientationUp]);
|
||||
}
|
||||
|
||||
- (void) cleanup
|
||||
{
|
||||
}
|
||||
|
||||
#if 0
|
||||
- (ZBarImage*) convertToFormat: (unsigned long) format
|
||||
{
|
||||
zbar_image_t *zdst = zbar_image_convert(zimg, format);
|
||||
ZBarImage *image = ;
|
||||
return([[[ZBarImage alloc] initWithImage: zdst] autorelease]);
|
||||
}
|
||||
#endif
|
||||
|
||||
@end
|
||||
85
iphone/ZBarImageScanner.m
Normal file
85
iphone/ZBarImageScanner.m
Normal file
@ -0,0 +1,85 @@
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright 2009 (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
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
#import <ZBarSDK/ZBarImageScanner.h>
|
||||
#import "debug.h"
|
||||
|
||||
@implementation ZBarImageScanner
|
||||
|
||||
@dynamic enableCache, results;
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if(self = [super init]) {
|
||||
scanner = zbar_image_scanner_create();
|
||||
}
|
||||
return(self);
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
if(scanner) {
|
||||
zbar_image_scanner_destroy(scanner);
|
||||
scanner = NULL;
|
||||
}
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (BOOL) enableCache
|
||||
{
|
||||
assert(0); // FIXME
|
||||
return(NO);
|
||||
}
|
||||
|
||||
- (void) setEnableCache: (BOOL) enable
|
||||
{
|
||||
zbar_image_scanner_enable_cache(scanner, enable);
|
||||
}
|
||||
|
||||
- (ZBarSymbolSet*) results
|
||||
{
|
||||
const zbar_symbol_set_t *set = zbar_image_scanner_get_results(scanner);
|
||||
return([[[ZBarSymbolSet alloc] initWithSymbolSet: set] autorelease]);
|
||||
}
|
||||
|
||||
// image scanner config wrappers
|
||||
- (void) parseConfig: (NSString*) cfg
|
||||
{
|
||||
zbar_image_scanner_parse_config(scanner, [cfg UTF8String]);
|
||||
// FIXME throw errors
|
||||
}
|
||||
|
||||
- (void) setSymbology: (zbar_symbol_type_t) sym
|
||||
config: (zbar_config_t) cfg
|
||||
to: (int) val
|
||||
{
|
||||
zbar_image_scanner_set_config(scanner, sym, cfg, val);
|
||||
// FIXME throw errors
|
||||
}
|
||||
|
||||
- (NSInteger) scanImage: (ZBarImage*) image
|
||||
{
|
||||
return(zbar_scan_image(scanner, image.zbarImage));
|
||||
}
|
||||
|
||||
@end
|
||||
747
iphone/ZBarReaderController.m
Normal file
747
iphone/ZBarReaderController.m
Normal file
@ -0,0 +1,747 @@
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright 2009-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
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
#import <ZBarSDK/ZBarReaderController.h>
|
||||
#import <ZBarSDK/ZBarHelpController.h>
|
||||
#import "debug.h"
|
||||
|
||||
/* the use of UIGetScreenImage() may no longer be sanctioned, even
|
||||
* though it was previously "allowed". define this to 0 to rip it out
|
||||
* and fall back to cameraMode=Default (manual capture)
|
||||
*/
|
||||
#ifndef USE_PRIVATE_APIS
|
||||
# define USE_PRIVATE_APIS 0
|
||||
#endif
|
||||
|
||||
#ifndef MIN_QUALITY
|
||||
# define MIN_QUALITY 10
|
||||
#endif
|
||||
|
||||
NSString* const ZBarReaderControllerResults = @"ZBarReaderControllerResults";
|
||||
|
||||
#if USE_PRIVATE_APIS
|
||||
// expose undocumented API
|
||||
CF_RETURNS_RETAINED
|
||||
CGImageRef UIGetScreenImage(void);
|
||||
#endif
|
||||
|
||||
@implementation ZBarReaderController
|
||||
|
||||
@synthesize scanner, readerDelegate, cameraMode, scanCrop, maxScanDimension,
|
||||
showsHelpOnFail, takesPicture, enableCache, tracksSymbols;
|
||||
@dynamic showsZBarControls;
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if(self = [super init]) {
|
||||
showsHelpOnFail = YES;
|
||||
hasOverlay = showsZBarControls =
|
||||
[self respondsToSelector: @selector(cameraOverlayView)];
|
||||
enableCache = tracksSymbols = YES;
|
||||
scanCrop = CGRectMake(0, 0, 1, 1);
|
||||
maxScanDimension = 640;
|
||||
|
||||
scanner = [ZBarImageScanner new];
|
||||
[scanner setSymbology: 0
|
||||
config: ZBAR_CFG_X_DENSITY
|
||||
to: 2];
|
||||
[scanner setSymbology: 0
|
||||
config: ZBAR_CFG_Y_DENSITY
|
||||
to: 2];
|
||||
|
||||
if([UIImagePickerController
|
||||
isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera])
|
||||
self.sourceType = UIImagePickerControllerSourceTypeCamera;
|
||||
|
||||
#if USE_PRIVATE_APIS
|
||||
cameraMode = ZBarReaderControllerCameraModeSampling;
|
||||
#else
|
||||
cameraMode = ZBarReaderControllerCameraModeDefault;
|
||||
#endif
|
||||
}
|
||||
return(self);
|
||||
}
|
||||
|
||||
- (void) initOverlay
|
||||
{
|
||||
CGRect bounds = self.view.bounds;
|
||||
overlay = [[UIView alloc] initWithFrame: bounds];
|
||||
overlay.backgroundColor = [UIColor clearColor];
|
||||
|
||||
CGRect r = bounds;
|
||||
r.size.height -= 54;
|
||||
boxView = [[UIView alloc] initWithFrame: r];
|
||||
|
||||
boxLayer = [CALayer new];
|
||||
boxLayer.frame = r;
|
||||
boxLayer.borderWidth = 1;
|
||||
boxLayer.borderColor = [UIColor greenColor].CGColor;
|
||||
[boxView.layer addSublayer: boxLayer];
|
||||
|
||||
toolbar = [UIToolbar new];
|
||||
toolbar.barStyle = UIBarStyleBlackOpaque;
|
||||
r.origin.y = r.size.height;
|
||||
r.size.height = 54;
|
||||
toolbar.frame = r;
|
||||
|
||||
cancelBtn = [[UIBarButtonItem alloc]
|
||||
initWithBarButtonSystemItem: UIBarButtonSystemItemCancel
|
||||
target: self
|
||||
action: @selector(cancel)];
|
||||
cancelBtn.width = r.size.width / 4 - 16;
|
||||
|
||||
scanBtn = [[UIBarButtonItem alloc]
|
||||
initWithTitle: @"Scan!"
|
||||
style: UIBarButtonItemStyleDone
|
||||
target: self
|
||||
action: @selector(scan)];
|
||||
scanBtn.width = r.size.width / 2 - 16;
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
space[i] = [[UIBarButtonItem alloc]
|
||||
initWithBarButtonSystemItem:
|
||||
UIBarButtonSystemItemFlexibleSpace
|
||||
target: nil
|
||||
action: nil];
|
||||
|
||||
space[2] = [[UIBarButtonItem alloc]
|
||||
initWithBarButtonSystemItem:
|
||||
UIBarButtonSystemItemFixedSpace
|
||||
target: nil
|
||||
action: nil];
|
||||
space[2].width = r.size.width / 4 - 16;
|
||||
|
||||
infoBtn = [[UIButton buttonWithType: UIButtonTypeInfoLight] retain];
|
||||
r.origin.x = r.size.width - 54;
|
||||
r.size.width = 54;
|
||||
infoBtn.frame = r;
|
||||
[infoBtn addTarget: self
|
||||
action: @selector(info)
|
||||
forControlEvents: UIControlEventTouchUpInside];
|
||||
}
|
||||
|
||||
- (void) viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
[super setDelegate: self];
|
||||
if(hasOverlay)
|
||||
[self initOverlay];
|
||||
}
|
||||
|
||||
- (void) cleanup
|
||||
{
|
||||
[overlay release];
|
||||
overlay = nil;
|
||||
[boxView release];
|
||||
boxView = nil;
|
||||
[boxLayer release];
|
||||
boxLayer = nil;
|
||||
[toolbar release];
|
||||
toolbar = nil;
|
||||
[cancelBtn release];
|
||||
cancelBtn = nil;
|
||||
[scanBtn release];
|
||||
scanBtn = nil;
|
||||
for(int i = 0; i < 3; i++) {
|
||||
[space[i] release];
|
||||
space[i] = nil;
|
||||
}
|
||||
[infoBtn release];
|
||||
infoBtn = nil;
|
||||
[help release];
|
||||
help = nil;
|
||||
}
|
||||
|
||||
- (void) viewDidUnload
|
||||
{
|
||||
[self cleanup];
|
||||
[super viewDidUnload];
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[self cleanup];
|
||||
[scanner release];
|
||||
scanner = nil;
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) scan
|
||||
{
|
||||
scanBtn.enabled = NO;
|
||||
self.view.userInteractionEnabled = NO;
|
||||
[self takePicture];
|
||||
}
|
||||
|
||||
- (void) cancel
|
||||
{
|
||||
[self performSelector: @selector(imagePickerControllerDidCancel:)
|
||||
withObject: self
|
||||
afterDelay: 0.1];
|
||||
}
|
||||
|
||||
- (void) reenable
|
||||
{
|
||||
scanBtn.enabled = YES;
|
||||
self.view.userInteractionEnabled = YES;
|
||||
}
|
||||
|
||||
- (void) initScanning
|
||||
{
|
||||
if(hasOverlay &&
|
||||
self.sourceType == UIImagePickerControllerSourceTypeCamera) {
|
||||
if(showsZBarControls || ![self cameraOverlayView])
|
||||
[self setCameraOverlayView: overlay];
|
||||
|
||||
UIView *activeOverlay = [self cameraOverlayView];
|
||||
|
||||
if(showsZBarControls) {
|
||||
if(!toolbar.superview) {
|
||||
[overlay addSubview: toolbar];
|
||||
[overlay addSubview: infoBtn];
|
||||
}
|
||||
[self setShowsCameraControls: NO];
|
||||
}
|
||||
else {
|
||||
[toolbar removeFromSuperview];
|
||||
[infoBtn removeFromSuperview];
|
||||
if(activeOverlay == overlay)
|
||||
[self setShowsCameraControls: YES];
|
||||
}
|
||||
|
||||
self.view.userInteractionEnabled = YES;
|
||||
|
||||
sampling = (cameraMode == ZBarReaderControllerCameraModeSampling ||
|
||||
cameraMode == ZBarReaderControllerCameraModeSequence);
|
||||
|
||||
if(sampling) {
|
||||
toolbar.items = [NSArray arrayWithObjects:
|
||||
cancelBtn, space[0], nil];
|
||||
|
||||
t_frame = timer_now();
|
||||
dt_frame = 0;
|
||||
boxLayer.opacity = 0;
|
||||
if(boxView.superview != activeOverlay)
|
||||
[boxView removeFromSuperview];
|
||||
if(!boxView.superview)
|
||||
[activeOverlay insertSubview: boxView atIndex:0];
|
||||
scanner.enableCache = enableCache;
|
||||
|
||||
SEL meth = nil;
|
||||
if(cameraMode == ZBarReaderControllerCameraModeSampling) {
|
||||
// ensure crop rect does not include controls
|
||||
if(scanCrop.origin.x + scanCrop.size.width > .8875)
|
||||
scanCrop.size.width = .8875 - scanCrop.origin.x;
|
||||
|
||||
meth = @selector(scanScreen);
|
||||
}
|
||||
else
|
||||
meth = @selector(takePicture);
|
||||
|
||||
[self performSelector: meth
|
||||
withObject: nil
|
||||
afterDelay: 2];
|
||||
#ifdef DEBUG_OBJC
|
||||
[self performSelector: @selector(dumpFPS)
|
||||
withObject: nil
|
||||
afterDelay: 4];
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
scanBtn.enabled = NO;
|
||||
toolbar.items = [NSArray arrayWithObjects:
|
||||
cancelBtn, space[0], scanBtn, space[1], space[2], nil];
|
||||
|
||||
[self performSelector: @selector(reenable)
|
||||
withObject: nil
|
||||
afterDelay: .5];
|
||||
|
||||
[boxView removeFromSuperview];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void) viewWillAppear: (BOOL) animated
|
||||
{
|
||||
[self initScanning];
|
||||
[super viewWillAppear: animated];
|
||||
}
|
||||
|
||||
- (void) viewWillDisappear: (BOOL) animated
|
||||
{
|
||||
sampling = NO;
|
||||
scanner.enableCache = NO;
|
||||
[super viewWillDisappear: animated];
|
||||
}
|
||||
|
||||
- (BOOL) showsZBarControls
|
||||
{
|
||||
return(showsZBarControls);
|
||||
}
|
||||
|
||||
- (void) setCameraMode: (ZBarReaderControllerCameraMode) mode
|
||||
{
|
||||
#if !USE_PRIVATE_APIS
|
||||
if(mode == ZBarReaderControllerCameraModeSampling)
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"ZBarReaderController cannot set cameraMode=Sampling"
|
||||
@" when USE_PRIVATE_APIS=0"];
|
||||
#endif
|
||||
cameraMode = mode;
|
||||
}
|
||||
|
||||
- (void) setShowsZBarControls: (BOOL) show
|
||||
{
|
||||
if(show && !hasOverlay)
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"ZBarReaderController cannot set showsZBarControls=YES for OS<3.1"];
|
||||
|
||||
showsZBarControls = show;
|
||||
}
|
||||
|
||||
// intercept delegate as readerDelegate
|
||||
|
||||
- (void) setDelegate: (id <UINavigationControllerDelegate,
|
||||
UIImagePickerControllerDelegate>) delegate
|
||||
{
|
||||
self.readerDelegate = (id <ZBarReaderDelegate>)delegate;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG_OBJC
|
||||
- (void) dumpFPS
|
||||
{
|
||||
if(!sampling)
|
||||
return;
|
||||
[self performSelector: @selector(dumpFPS)
|
||||
withObject: nil
|
||||
afterDelay: 2];
|
||||
zlog(@"fps=%g", 1 / dt_frame);
|
||||
}
|
||||
#endif
|
||||
|
||||
- (NSInteger) scanImage: (CGImageRef) image
|
||||
withScaling: (CGFloat) scale
|
||||
{
|
||||
uint64_t now = timer_now();
|
||||
if(dt_frame)
|
||||
dt_frame = (dt_frame + timer_elapsed(t_frame, now)) / 2;
|
||||
else
|
||||
dt_frame = timer_elapsed(t_frame, now);
|
||||
t_frame = now;
|
||||
|
||||
int w = CGImageGetWidth(image);
|
||||
int h = CGImageGetHeight(image);
|
||||
CGRect crop;
|
||||
if(w >= h)
|
||||
crop = CGRectMake(scanCrop.origin.x * w, scanCrop.origin.y * h,
|
||||
scanCrop.size.width * w, scanCrop.size.height * h);
|
||||
else
|
||||
crop = CGRectMake(scanCrop.origin.y * w, scanCrop.origin.x * h,
|
||||
scanCrop.size.height * w, scanCrop.size.width * h);
|
||||
|
||||
CGSize size;
|
||||
if(crop.size.width >= crop.size.height &&
|
||||
crop.size.width > maxScanDimension)
|
||||
size = CGSizeMake(maxScanDimension,
|
||||
crop.size.height * maxScanDimension / crop.size.width);
|
||||
else if(crop.size.height > maxScanDimension)
|
||||
size = CGSizeMake(crop.size.width * maxScanDimension / crop.size.height,
|
||||
maxScanDimension);
|
||||
else
|
||||
size = crop.size;
|
||||
|
||||
if(scale) {
|
||||
size.width *= scale;
|
||||
size.height *= scale;
|
||||
}
|
||||
|
||||
if(self.sourceType != UIImagePickerControllerSourceTypeCamera ||
|
||||
cameraMode == ZBarReaderControllerCameraModeDefault) {
|
||||
// limit the maximum number of scan passes
|
||||
int density;
|
||||
if(size.width > 720)
|
||||
density = (size.width / 240 + 1) / 2;
|
||||
else
|
||||
density = 1;
|
||||
[scanner setSymbology: 0
|
||||
config: ZBAR_CFG_X_DENSITY
|
||||
to: density];
|
||||
|
||||
if(size.height > 720)
|
||||
density = (size.height / 240 + 1) / 2;
|
||||
else
|
||||
density = 1;
|
||||
[scanner setSymbology: 0
|
||||
config: ZBAR_CFG_Y_DENSITY
|
||||
to: density];
|
||||
}
|
||||
|
||||
ZBarImage *zimg = [[ZBarImage alloc]
|
||||
initWithCGImage: image
|
||||
crop: crop
|
||||
size: size];
|
||||
int nsyms = [scanner scanImage: zimg];
|
||||
[zimg release];
|
||||
|
||||
return(nsyms);
|
||||
}
|
||||
|
||||
- (ZBarSymbol*) extractBestResult: (BOOL) filter
|
||||
{
|
||||
ZBarSymbol *sym = nil;
|
||||
ZBarSymbolSet *results = scanner.results;
|
||||
results.filterSymbols = filter;
|
||||
for(ZBarSymbol *s in results)
|
||||
if(!sym || sym.quality < s.quality)
|
||||
sym = s;
|
||||
return(sym);
|
||||
}
|
||||
|
||||
- (void) updateBox: (ZBarSymbol*) sym
|
||||
imageSize: (CGSize) size
|
||||
{
|
||||
[CATransaction begin];
|
||||
[CATransaction setAnimationDuration: .3];
|
||||
[CATransaction setAnimationTimingFunction:
|
||||
[CAMediaTimingFunction functionWithName:
|
||||
kCAMediaTimingFunctionLinear]];
|
||||
|
||||
CGFloat alpha = boxLayer.opacity;
|
||||
if(sym) {
|
||||
CGRect r = sym.bounds;
|
||||
if(r.size.width > 16 && r.size.height > 16) {
|
||||
r.origin.x += scanCrop.origin.y * size.width;
|
||||
r.origin.y += scanCrop.origin.x * size.height;
|
||||
r = CGRectInset(r, -16, -16);
|
||||
if(alpha > .25) {
|
||||
CGRect frame = boxLayer.frame;
|
||||
r.origin.x = (r.origin.x * 3 + frame.origin.x) / 4;
|
||||
r.origin.y = (r.origin.y * 3 + frame.origin.y) / 4;
|
||||
r.size.width = (r.size.width * 3 + frame.size.width) / 4;
|
||||
r.size.height = (r.size.height * 3 + frame.size.height) / 4;
|
||||
}
|
||||
boxLayer.frame = r;
|
||||
boxLayer.opacity = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(alpha > .1)
|
||||
boxLayer.opacity = alpha / 2;
|
||||
else if(alpha)
|
||||
boxLayer.opacity = 0;
|
||||
}
|
||||
[CATransaction commit];
|
||||
}
|
||||
|
||||
#if USE_PRIVATE_APIS
|
||||
|
||||
- (void) scanScreen
|
||||
{
|
||||
if(!sampling)
|
||||
return;
|
||||
|
||||
// FIXME ugly hack: use private API to sample screen
|
||||
CGImageRef image = UIGetScreenImage();
|
||||
|
||||
[self scanImage: image
|
||||
withScaling: 0];
|
||||
CGSize size = CGSizeMake(CGImageGetWidth(image), CGImageGetHeight(image));
|
||||
CGImageRelease(image);
|
||||
|
||||
ZBarSymbol *sym = [self extractBestResult: NO];
|
||||
|
||||
if(sym && !sym.count) {
|
||||
SEL cb = @selector(imagePickerController:didFinishPickingMediaWithInfo:);
|
||||
if(takesPicture) {
|
||||
symbol = [sym retain];
|
||||
[self takePicture];
|
||||
}
|
||||
else if([readerDelegate respondsToSelector: cb]) {
|
||||
symbol = [sym retain];
|
||||
|
||||
[CATransaction begin];
|
||||
[CATransaction setDisableActions: YES];
|
||||
boxLayer.opacity = 0;
|
||||
[CATransaction commit];
|
||||
|
||||
// capture preview image and send to delegate
|
||||
// after box has been hidden
|
||||
[self performSelector: @selector(captureScreen)
|
||||
withObject: nil
|
||||
afterDelay: 0.001];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// reschedule
|
||||
[self performSelector: @selector(scanScreen)
|
||||
withObject: nil
|
||||
afterDelay: 0.001];
|
||||
|
||||
if(tracksSymbols)
|
||||
[self updateBox: sym
|
||||
imageSize: size];
|
||||
}
|
||||
|
||||
- (void) captureScreen
|
||||
{
|
||||
CGImageRef screen = UIGetScreenImage();
|
||||
|
||||
CGRect r = CGRectMake(0, 0,
|
||||
CGImageGetWidth(screen), CGImageGetHeight(screen));
|
||||
if(r.size.width > r.size.height)
|
||||
r.size.width -= 54;
|
||||
else
|
||||
r.size.height -= 54;
|
||||
CGImageRef preview = CGImageCreateWithImageInRect(screen, r);
|
||||
CGImageRelease(screen);
|
||||
|
||||
UIImage *image = [UIImage imageWithCGImage: preview];
|
||||
CGImageRelease(preview);
|
||||
|
||||
[readerDelegate
|
||||
imagePickerController: self
|
||||
didFinishPickingMediaWithInfo:
|
||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
image, UIImagePickerControllerOriginalImage,
|
||||
[NSArray arrayWithObject: symbol],
|
||||
ZBarReaderControllerResults,
|
||||
nil]];
|
||||
[symbol release];
|
||||
symbol = nil;
|
||||
|
||||
// continue scanning until dismissed
|
||||
[self performSelector: @selector(scanScreen)
|
||||
withObject: nil
|
||||
afterDelay: 0.001];
|
||||
}
|
||||
|
||||
#endif /* USE_PRIVATE_APIS */
|
||||
|
||||
- (void) scanSequence: (UIImage*) image
|
||||
{
|
||||
if(!sampling) {
|
||||
[image release];
|
||||
return;
|
||||
}
|
||||
|
||||
int nsyms = [self scanImage: image.CGImage
|
||||
withScaling: 0];
|
||||
|
||||
ZBarSymbol *sym = nil;
|
||||
if(nsyms)
|
||||
[self extractBestResult: NO];
|
||||
|
||||
SEL cb = @selector(imagePickerController:didFinishPickingMediaWithInfo:);
|
||||
if(sym && !sym.count &&
|
||||
[readerDelegate respondsToSelector: cb])
|
||||
[readerDelegate
|
||||
imagePickerController: self
|
||||
didFinishPickingMediaWithInfo:
|
||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
image, UIImagePickerControllerOriginalImage,
|
||||
[NSArray arrayWithObject: sym],
|
||||
ZBarReaderControllerResults,
|
||||
nil]];
|
||||
CGSize size = image.size;
|
||||
[image release];
|
||||
|
||||
// reschedule
|
||||
[self performSelector: @selector(takePicture)
|
||||
withObject: nil
|
||||
afterDelay: 0.001];
|
||||
|
||||
if(tracksSymbols)
|
||||
[self updateBox: sym
|
||||
imageSize: size];
|
||||
}
|
||||
|
||||
- (void) showHelpWithReason: (NSString*) reason
|
||||
{
|
||||
if(help) {
|
||||
[help.view removeFromSuperview];
|
||||
[help release];
|
||||
}
|
||||
help = [[ZBarHelpController alloc]
|
||||
initWithReason: reason];
|
||||
help.delegate = (id<ZBarHelpDelegate>)self;
|
||||
|
||||
if(self.sourceType != UIImagePickerControllerSourceTypeCamera) {
|
||||
[self presentModalViewController: help
|
||||
animated: YES];
|
||||
return;
|
||||
}
|
||||
|
||||
// show help as overlay view to workaround controller bugs
|
||||
sampling = NO;
|
||||
scanner.enableCache = NO;
|
||||
help.wantsFullScreenLayout = YES;
|
||||
help.view.alpha = 0;
|
||||
|
||||
UIView *activeOverlay = [self cameraOverlayView];
|
||||
help.view.frame = [activeOverlay
|
||||
convertRect: CGRectMake(0, 0, 320, 480)
|
||||
fromView: nil];
|
||||
[activeOverlay addSubview: help.view];
|
||||
[UIView beginAnimations: @"ZBarHelp"
|
||||
context: nil];
|
||||
help.view.alpha = 1;
|
||||
[UIView commitAnimations];
|
||||
}
|
||||
|
||||
- (void) info
|
||||
{
|
||||
[self showHelpWithReason: @"INFO"];
|
||||
}
|
||||
|
||||
- (void) imagePickerController: (UIImagePickerController*) picker
|
||||
didFinishPickingMediaWithInfo: (NSDictionary*) info
|
||||
{
|
||||
UIImage *img = [info objectForKey: UIImagePickerControllerOriginalImage];
|
||||
|
||||
id results = nil;
|
||||
if(self.sourceType == UIImagePickerControllerSourceTypeCamera &&
|
||||
cameraMode == ZBarReaderControllerCameraModeSequence) {
|
||||
if(sampling)
|
||||
[self performSelector: @selector(scanSequence:)
|
||||
withObject: [img retain]
|
||||
afterDelay: 0.001];
|
||||
return;
|
||||
}
|
||||
else if(!sampling)
|
||||
results = [self scanImage: img.CGImage];
|
||||
else {
|
||||
results = [NSArray arrayWithObject: symbol];
|
||||
[symbol release];
|
||||
symbol = nil;
|
||||
}
|
||||
|
||||
[self performSelector: @selector(reenable)
|
||||
withObject: nil
|
||||
afterDelay: .25];
|
||||
|
||||
if(results) {
|
||||
NSMutableDictionary *newinfo = [info mutableCopy];
|
||||
[newinfo setObject: results
|
||||
forKey: ZBarReaderControllerResults];
|
||||
SEL cb = @selector(imagePickerController:didFinishPickingMediaWithInfo:);
|
||||
if([readerDelegate respondsToSelector: cb])
|
||||
[readerDelegate imagePickerController: self
|
||||
didFinishPickingMediaWithInfo: newinfo];
|
||||
else
|
||||
[self dismissModalViewControllerAnimated: YES];
|
||||
[newinfo release];
|
||||
return;
|
||||
}
|
||||
|
||||
BOOL camera = (self.sourceType == UIImagePickerControllerSourceTypeCamera);
|
||||
BOOL retry = !camera || (hasOverlay && ![self showsCameraControls]);
|
||||
if(showsHelpOnFail && retry)
|
||||
[self showHelpWithReason: @"FAIL"];
|
||||
|
||||
SEL cb = @selector(readerControllerDidFailToRead:withRetry:);
|
||||
if([readerDelegate respondsToSelector: cb])
|
||||
// assume delegate dismisses controller if necessary
|
||||
[readerDelegate readerControllerDidFailToRead: self
|
||||
withRetry: retry];
|
||||
else if(!retry)
|
||||
// must dismiss stock controller
|
||||
[self dismissModalViewControllerAnimated: YES];
|
||||
}
|
||||
|
||||
- (void) imagePickerControllerDidCancel: (UIImagePickerController*) picker
|
||||
{
|
||||
SEL cb = @selector(imagePickerControllerDidCancel:);
|
||||
if([readerDelegate respondsToSelector: cb])
|
||||
[readerDelegate imagePickerControllerDidCancel: self];
|
||||
else
|
||||
[self dismissModalViewControllerAnimated: YES];
|
||||
}
|
||||
|
||||
// ZBarHelpDelegate
|
||||
|
||||
- (void) helpControllerDidFinish: (ZBarHelpController*) hlp
|
||||
{
|
||||
if(self.sourceType == UIImagePickerControllerSourceTypeCamera) {
|
||||
[UIView beginAnimations: @"ZBarHelp"
|
||||
context: nil];
|
||||
hlp.view.alpha = 0;
|
||||
[UIView commitAnimations];
|
||||
[self initScanning];
|
||||
}
|
||||
else
|
||||
[hlp dismissModalViewControllerAnimated: YES];
|
||||
}
|
||||
|
||||
- (id <NSFastEnumeration>) scanImage: (CGImageRef) image
|
||||
{
|
||||
timer_start;
|
||||
|
||||
int nsyms = [self scanImage: image
|
||||
withScaling: 0];
|
||||
|
||||
if(!nsyms &&
|
||||
CGImageGetWidth(image) >= 640 &&
|
||||
CGImageGetHeight(image) >= 640)
|
||||
// make one more attempt for close up, grainy images
|
||||
nsyms = [self scanImage: image
|
||||
withScaling: .5];
|
||||
|
||||
NSMutableArray *syms = nil;
|
||||
if(nsyms) {
|
||||
// quality/type filtering
|
||||
int max_quality = MIN_QUALITY;
|
||||
for(ZBarSymbol *sym in scanner.results) {
|
||||
zbar_symbol_type_t type = sym.type;
|
||||
int quality;
|
||||
if(type == ZBAR_QRCODE)
|
||||
quality = INT_MAX;
|
||||
else
|
||||
quality = sym.quality;
|
||||
|
||||
if(quality < max_quality) {
|
||||
zlog(@" type=%d quality=%d < %d\n",
|
||||
type, quality, max_quality);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(max_quality < quality) {
|
||||
max_quality = quality;
|
||||
if(syms)
|
||||
[syms removeAllObjects];
|
||||
}
|
||||
zlog(@" type=%d quality=%d\n", type, quality);
|
||||
if(!syms)
|
||||
syms = [NSMutableArray arrayWithCapacity: 1];
|
||||
|
||||
[syms addObject: sym];
|
||||
}
|
||||
}
|
||||
|
||||
zlog(@"read %d filtered symbols in %gs total\n",
|
||||
(!syms) ? 0 : [syms count], timer_elapsed(t_start, timer_now()));
|
||||
return(syms);
|
||||
}
|
||||
|
||||
@end
|
||||
596
iphone/ZBarReaderView.m
Normal file
596
iphone/ZBarReaderView.m
Normal file
@ -0,0 +1,596 @@
|
||||
//------------------------------------------------------------------------
|
||||
// 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
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
#import <ZBarSDK/ZBarReaderView.h>
|
||||
|
||||
#define MODULE ZBarReaderView
|
||||
#import "debug.h"
|
||||
|
||||
// silence warning
|
||||
@interface ZBarReaderViewImpl : NSObject
|
||||
@end
|
||||
|
||||
@implementation ZBarReaderView
|
||||
|
||||
@synthesize readerDelegate, tracksSymbols, trackingColor, torchMode, showsFPS,
|
||||
zoom, maxZoom, scanCrop, previewTransform, captureReader;
|
||||
@dynamic scanner, allowsPinchZoom, enableCache, device, session;
|
||||
|
||||
+ (id) alloc
|
||||
{
|
||||
if(self == [ZBarReaderView class]) {
|
||||
// this is an abstract wrapper for implementation selected
|
||||
// at compile time. replace with concrete subclass.
|
||||
return((id)[ZBarReaderViewImpl alloc]);
|
||||
}
|
||||
return([super alloc]);
|
||||
}
|
||||
|
||||
- (void) initSubviews
|
||||
{
|
||||
assert(preview);
|
||||
|
||||
overlay = [CALayer new];
|
||||
overlay.backgroundColor = [UIColor clearColor].CGColor;
|
||||
[preview addSublayer: overlay];
|
||||
|
||||
#ifndef NDEBUG
|
||||
overlay.borderWidth = 2;
|
||||
overlay.borderColor = [UIColor colorWithRed: 1
|
||||
green: 0
|
||||
blue: 0
|
||||
alpha: .5].CGColor;
|
||||
cropLayer = [CALayer new];
|
||||
cropLayer.backgroundColor = [UIColor clearColor].CGColor;
|
||||
cropLayer.borderWidth = 2;
|
||||
cropLayer.borderColor = [UIColor colorWithRed: 0
|
||||
green: 0
|
||||
blue: 1
|
||||
alpha: .5].CGColor;
|
||||
[overlay addSublayer: cropLayer];
|
||||
#endif
|
||||
|
||||
tracking = [CALayer new];
|
||||
tracking.opacity = 0;
|
||||
tracking.borderWidth = 1;
|
||||
tracking.backgroundColor = [UIColor clearColor].CGColor;
|
||||
[overlay addSublayer: tracking];
|
||||
|
||||
trackingColor = [[UIColor greenColor]
|
||||
retain];
|
||||
tracking.borderColor = trackingColor.CGColor;
|
||||
|
||||
fpsView = [UIView new];
|
||||
fpsView.backgroundColor = [UIColor colorWithWhite: 0
|
||||
alpha: .333];
|
||||
fpsView.layer.cornerRadius = 12;
|
||||
fpsView.hidden = YES;
|
||||
[self addSubview: fpsView];
|
||||
|
||||
fpsLabel = [[UILabel alloc]
|
||||
initWithFrame: CGRectMake(0, 0, 80, 32)];
|
||||
fpsLabel.backgroundColor = [UIColor clearColor];
|
||||
fpsLabel.textColor = [UIColor colorWithRed: .333
|
||||
green: .666
|
||||
blue: 1
|
||||
alpha: 1];
|
||||
fpsLabel.font = [UIFont systemFontOfSize: 18];
|
||||
fpsLabel.textAlignment = UITextAlignmentRight;
|
||||
[fpsView addSubview: fpsLabel];
|
||||
|
||||
self.zoom = 1.25;
|
||||
}
|
||||
|
||||
- (void) _initWithImageScanner: (ZBarImageScanner*) scanner
|
||||
{
|
||||
assert(scanner);
|
||||
|
||||
tracksSymbols = YES;
|
||||
interfaceOrientation = UIInterfaceOrientationPortrait;
|
||||
torchMode = 2; // AVCaptureTorchModeAuto
|
||||
scanCrop = effectiveCrop = CGRectMake(0, 0, 1, 1);
|
||||
imageScale = 1;
|
||||
previewTransform = CGAffineTransformIdentity;
|
||||
maxZoom = 2;
|
||||
|
||||
pinch = [[UIPinchGestureRecognizer alloc]
|
||||
initWithTarget: self
|
||||
action: @selector(handlePinch)];
|
||||
[self addGestureRecognizer: pinch];
|
||||
}
|
||||
|
||||
- (id) initWithImageScanner: (ZBarImageScanner*) scanner
|
||||
{
|
||||
self = [super initWithFrame: CGRectMake(0, 0, 320, 426)];
|
||||
if(!self)
|
||||
return(nil);
|
||||
|
||||
self.backgroundColor = [UIColor blackColor];
|
||||
self.contentMode = UIViewContentModeScaleAspectFill;
|
||||
self.clipsToBounds = YES;
|
||||
self.autoresizingMask =
|
||||
UIViewAutoresizingFlexibleWidth |
|
||||
UIViewAutoresizingFlexibleHeight;
|
||||
|
||||
[self _initWithImageScanner: scanner];
|
||||
return(self);
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
ZBarImageScanner *scanner =
|
||||
[[ZBarImageScanner new]
|
||||
autorelease];
|
||||
self = [self initWithImageScanner: scanner];
|
||||
if(!self)
|
||||
return(nil);
|
||||
|
||||
[scanner setSymbology: 0
|
||||
config: ZBAR_CFG_X_DENSITY
|
||||
to: 3];
|
||||
[scanner setSymbology: 0
|
||||
config: ZBAR_CFG_Y_DENSITY
|
||||
to: 3];
|
||||
return(self);
|
||||
}
|
||||
|
||||
- (id) initWithCoder: (NSCoder*) decoder
|
||||
{
|
||||
self = [super initWithCoder: decoder];
|
||||
if(!self)
|
||||
return(nil);
|
||||
ZBarImageScanner *scanner =
|
||||
[[ZBarImageScanner new]
|
||||
autorelease];
|
||||
[self _initWithImageScanner: scanner];
|
||||
|
||||
[scanner setSymbology: 0
|
||||
config: ZBAR_CFG_X_DENSITY
|
||||
to: 3];
|
||||
[scanner setSymbology: 0
|
||||
config: ZBAR_CFG_Y_DENSITY
|
||||
to: 3];
|
||||
return(self);
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[preview removeFromSuperlayer];
|
||||
[preview release];
|
||||
preview = nil;
|
||||
[overlay release];
|
||||
overlay = nil;
|
||||
[cropLayer release];
|
||||
cropLayer = nil;
|
||||
[tracking release];
|
||||
tracking = nil;
|
||||
[trackingColor release];
|
||||
trackingColor = nil;
|
||||
[fpsLabel release];
|
||||
fpsLabel = nil;
|
||||
[fpsView release];
|
||||
fpsView = nil;
|
||||
[pinch release];
|
||||
pinch = nil;
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) resetTracking
|
||||
{
|
||||
[tracking removeAllAnimations];
|
||||
[CATransaction begin];
|
||||
[CATransaction setDisableActions: YES];
|
||||
CGSize size = overlay.bounds.size;
|
||||
CGRect crop = effectiveCrop;
|
||||
tracking.frame = CGRectMake(crop.origin.x * size.width,
|
||||
crop.origin.y * size.height,
|
||||
crop.size.width * size.width,
|
||||
crop.size.height * size.height);
|
||||
tracking.opacity = 0;
|
||||
[CATransaction commit];
|
||||
}
|
||||
|
||||
- (void) updateCrop
|
||||
{
|
||||
}
|
||||
|
||||
static inline CGFloat rotationForInterfaceOrientation (int orient)
|
||||
{
|
||||
// resolve camera/device image orientation to view/interface orientation
|
||||
switch(orient)
|
||||
{
|
||||
case UIInterfaceOrientationLandscapeLeft:
|
||||
return(M_PI_2);
|
||||
case UIInterfaceOrientationPortraitUpsideDown:
|
||||
return(M_PI);
|
||||
case UIInterfaceOrientationLandscapeRight:
|
||||
return(3 * M_PI_2);
|
||||
case UIInterfaceOrientationPortrait:
|
||||
return(2 * M_PI);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
- (void) layoutSubviews
|
||||
{
|
||||
CGRect bounds = self.bounds;
|
||||
if(!bounds.size.width || !bounds.size.height)
|
||||
return;
|
||||
|
||||
[CATransaction begin];
|
||||
if(animationDuration) {
|
||||
[CATransaction setAnimationDuration: animationDuration];
|
||||
[CATransaction setAnimationTimingFunction:
|
||||
[CAMediaTimingFunction functionWithName:
|
||||
kCAMediaTimingFunctionEaseInEaseOut]];
|
||||
}
|
||||
else
|
||||
[CATransaction setDisableActions: YES];
|
||||
|
||||
[super layoutSubviews];
|
||||
fpsView.frame = CGRectMake(bounds.size.width - 80, bounds.size.height - 32,
|
||||
80 + 12, 32 + 12);
|
||||
|
||||
// orient view bounds to match camera image
|
||||
CGSize psize;
|
||||
if(UIInterfaceOrientationIsPortrait(interfaceOrientation))
|
||||
psize = CGSizeMake(bounds.size.height, bounds.size.width);
|
||||
else
|
||||
psize = bounds.size;
|
||||
|
||||
// calculate scale from view coordinates to image coordinates
|
||||
// FIXME assumes AVLayerVideoGravityResizeAspectFill
|
||||
CGFloat scalex = imageSize.width / psize.width;
|
||||
CGFloat scaley = imageSize.height / psize.height;
|
||||
imageScale = (scalex < scaley) ? scalex : scaley;
|
||||
if(!imageScale)
|
||||
imageScale = 1;
|
||||
// apply zoom
|
||||
imageScale /= zoom;
|
||||
|
||||
// scale crop by zoom factor
|
||||
CGFloat z = 1 / zoom;
|
||||
CGFloat t = (1 - z) / 2;
|
||||
CGRect zoomCrop =
|
||||
CGRectMake(scanCrop.origin.x * z + t,
|
||||
scanCrop.origin.y * z + t,
|
||||
scanCrop.size.width * z,
|
||||
scanCrop.size.height * z);
|
||||
|
||||
// convert effective preview area to normalized image coordinates
|
||||
CGRect previewCrop;
|
||||
if(scalex < scaley && imageSize.height)
|
||||
previewCrop.size =
|
||||
CGSizeMake(z, psize.height * imageScale / imageSize.height);
|
||||
else if(imageSize.width)
|
||||
previewCrop.size =
|
||||
CGSizeMake(psize.width * imageScale / imageSize.width, z);
|
||||
else
|
||||
previewCrop.size = CGSizeMake(1, 1);
|
||||
previewCrop.origin = CGPointMake((1 - previewCrop.size.width) / 2,
|
||||
(1 - previewCrop.size.height) / 2);
|
||||
|
||||
// clip crop to visible preview area
|
||||
effectiveCrop = CGRectIntersection(zoomCrop, previewCrop);
|
||||
if(CGRectIsNull(effectiveCrop))
|
||||
effectiveCrop = zoomCrop;
|
||||
|
||||
// size preview to match image in view coordinates
|
||||
CGFloat viewScale = 1 / imageScale;
|
||||
if(imageSize.width && imageSize.height)
|
||||
psize = CGSizeMake(imageSize.width * viewScale,
|
||||
imageSize.height * viewScale);
|
||||
|
||||
preview.bounds = CGRectMake(0, 0, psize.height, psize.width);
|
||||
// center preview in view
|
||||
preview.position = CGPointMake(bounds.size.width / 2,
|
||||
bounds.size.height / 2);
|
||||
|
||||
CGFloat angle = rotationForInterfaceOrientation(interfaceOrientation);
|
||||
CATransform3D xform =
|
||||
CATransform3DMakeAffineTransform(previewTransform);
|
||||
preview.transform = CATransform3DRotate(xform, angle, 0, 0, 1);
|
||||
|
||||
// scale overlay to match actual image
|
||||
if(imageSize.width && imageSize.height)
|
||||
overlay.bounds = CGRectMake(0, 0, imageSize.width, imageSize.height);
|
||||
else
|
||||
overlay.bounds = CGRectMake(0, 0, psize.width, psize.height);
|
||||
// center overlay in preview
|
||||
overlay.position = CGPointMake(psize.height / 2, psize.width / 2);
|
||||
|
||||
// image coordinates rotated from preview
|
||||
xform = CATransform3DMakeRotation(M_PI_2, 0, 0, 1);
|
||||
overlay.transform = CATransform3DScale(xform, viewScale, viewScale, 1);
|
||||
tracking.borderWidth = imageScale;
|
||||
|
||||
#ifndef NDEBUG
|
||||
preview.backgroundColor = [UIColor yellowColor].CGColor;
|
||||
overlay.borderWidth = 2 * imageScale;
|
||||
cropLayer.borderWidth = 2 * imageScale;
|
||||
cropLayer.frame = CGRectMake(effectiveCrop.origin.x * imageSize.width,
|
||||
effectiveCrop.origin.y * imageSize.height,
|
||||
effectiveCrop.size.width * imageSize.width,
|
||||
effectiveCrop.size.height * imageSize.height);
|
||||
zlog(@"layoutSubviews: bounds=%@ orient=%d image=%@ crop=%@ zoom=%g\n"
|
||||
@"=> preview=%@ crop=(z%@ p%@ %@ i%@) scale=%g %c %g = 1/%g",
|
||||
NSStringFromCGSize(bounds.size), interfaceOrientation,
|
||||
NSStringFromCGSize(imageSize), NSStringFromCGRect(scanCrop), zoom,
|
||||
NSStringFromCGSize(psize), NSStringFromCGRect(zoomCrop),
|
||||
NSStringFromCGRect(previewCrop), NSStringFromCGRect(effectiveCrop),
|
||||
NSStringFromCGRect(cropLayer.frame),
|
||||
scalex, (scalex > scaley) ? '>' : '<', scaley, viewScale);
|
||||
#endif
|
||||
|
||||
[self resetTracking];
|
||||
[self updateCrop];
|
||||
|
||||
[CATransaction commit];
|
||||
animationDuration = 0;
|
||||
}
|
||||
|
||||
- (void) setImageSize: (CGSize) size
|
||||
{
|
||||
zlog(@"imageSize=%@", NSStringFromCGSize(size));
|
||||
imageSize = size;
|
||||
|
||||
// FIXME bug in AVCaptureVideoPreviewLayer fails to update preview location
|
||||
preview.bounds = CGRectMake(0, 0, size.width, size.height);
|
||||
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) orient
|
||||
duration: (NSTimeInterval) duration
|
||||
{
|
||||
if(interfaceOrientation != orient) {
|
||||
zlog(@"orient=%d #%g", orient, duration);
|
||||
interfaceOrientation = orient;
|
||||
animationDuration = duration;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) setScanCrop: (CGRect) r
|
||||
{
|
||||
if(CGRectEqualToRect(scanCrop, r))
|
||||
return;
|
||||
scanCrop = r;
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void) setTracksSymbols: (BOOL) track
|
||||
{
|
||||
if(track == tracksSymbols)
|
||||
return;
|
||||
tracksSymbols = track;
|
||||
[self resetTracking];
|
||||
}
|
||||
|
||||
- (BOOL) allowsPinchZoom
|
||||
{
|
||||
return(pinch.enabled);
|
||||
}
|
||||
|
||||
- (void) setAllowsPinchZoom: (BOOL) enabled
|
||||
{
|
||||
pinch.enabled = enabled;
|
||||
}
|
||||
|
||||
- (void) setTrackingColor: (UIColor*) color
|
||||
{
|
||||
if(!color)
|
||||
return;
|
||||
[color retain];
|
||||
[trackingColor release];
|
||||
trackingColor = color;
|
||||
tracking.borderColor = color.CGColor;
|
||||
}
|
||||
|
||||
- (void) setShowsFPS: (BOOL) show
|
||||
{
|
||||
if(show == showsFPS)
|
||||
return;
|
||||
fpsView.hidden = !show;
|
||||
}
|
||||
|
||||
- (void) setZoom: (CGFloat) z
|
||||
{
|
||||
if(z < 1.0)
|
||||
z = 1.0;
|
||||
if(z > maxZoom)
|
||||
z = maxZoom;
|
||||
if(z == zoom)
|
||||
return;
|
||||
zoom = z;
|
||||
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void) setZoom: (CGFloat) z
|
||||
animated: (BOOL) animated
|
||||
{
|
||||
[CATransaction begin];
|
||||
if(animated) {
|
||||
[CATransaction setAnimationDuration: .1];
|
||||
[CATransaction setAnimationTimingFunction:
|
||||
[CAMediaTimingFunction functionWithName:
|
||||
kCAMediaTimingFunctionLinear]];
|
||||
}
|
||||
else
|
||||
[CATransaction setDisableActions: YES];
|
||||
// FIXME animate from current value
|
||||
self.zoom = z;
|
||||
[self layoutIfNeeded];
|
||||
[CATransaction commit];
|
||||
}
|
||||
|
||||
- (void) setPreviewTransform: (CGAffineTransform) xfrm
|
||||
{
|
||||
previewTransform = xfrm;
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void) start
|
||||
{
|
||||
if(started)
|
||||
return;
|
||||
started = YES;
|
||||
|
||||
[self resetTracking];
|
||||
fpsLabel.text = @"--- fps ";
|
||||
|
||||
[[UIDevice currentDevice]
|
||||
beginGeneratingDeviceOrientationNotifications];
|
||||
}
|
||||
|
||||
- (void) stop
|
||||
{
|
||||
if(!started)
|
||||
return;
|
||||
started = NO;
|
||||
|
||||
[[UIDevice currentDevice]
|
||||
endGeneratingDeviceOrientationNotifications];
|
||||
}
|
||||
|
||||
- (void) flushCache
|
||||
{
|
||||
}
|
||||
|
||||
// UIGestureRecognizer callback
|
||||
|
||||
- (void) handlePinch
|
||||
{
|
||||
if(pinch.state == UIGestureRecognizerStateBegan)
|
||||
zoom0 = zoom;
|
||||
CGFloat z = zoom0 * pinch.scale;
|
||||
[self setZoom: z
|
||||
animated: YES];
|
||||
|
||||
if((zoom < 1.5) != (z < 1.5)) {
|
||||
int d = (z < 1.5) ? 3 : 2;
|
||||
ZBarImageScanner *scanner = self.scanner;
|
||||
@synchronized(scanner) {
|
||||
[scanner setSymbology: 0
|
||||
config: ZBAR_CFG_X_DENSITY
|
||||
to: d];
|
||||
[scanner setSymbology: 0
|
||||
config: ZBAR_CFG_Y_DENSITY
|
||||
to: d];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void) updateTracking: (CALayer*) trk
|
||||
withSymbol: (ZBarSymbol*) sym
|
||||
{
|
||||
if(!sym)
|
||||
return;
|
||||
|
||||
CGRect r = sym.bounds;
|
||||
if(r.size.width <= 32 && r.size.height <= 32)
|
||||
return;
|
||||
r = CGRectInset(r, -24, -24);
|
||||
|
||||
CALayer *current = trk.presentationLayer;
|
||||
CGPoint cp = current.position;
|
||||
CGPoint p = CGPointMake(CGRectGetMidX(r), CGRectGetMidY(r));
|
||||
p = CGPointMake((p.x * 3 + cp.x) / 4, (p.y * 3 + cp.y) / 4);
|
||||
|
||||
CGRect cr = current.bounds;
|
||||
r.origin = cr.origin;
|
||||
r.size.width = (r.size.width * 3 + cr.size.width) / 4;
|
||||
r.size.height = (r.size.height * 3 + cr.size.height) / 4;
|
||||
|
||||
CAMediaTimingFunction *linear =
|
||||
[CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionLinear];
|
||||
|
||||
CABasicAnimation *resize =
|
||||
[CABasicAnimation animationWithKeyPath: @"bounds"];
|
||||
resize.fromValue = [NSValue valueWithCGRect: cr];
|
||||
resize.toValue = [NSValue valueWithCGRect: r];
|
||||
resize.duration = .2;
|
||||
resize.timingFunction = linear;
|
||||
resize.fillMode = kCAFillModeForwards;
|
||||
resize.removedOnCompletion = NO;
|
||||
|
||||
CABasicAnimation *move =
|
||||
[CABasicAnimation animationWithKeyPath: @"position"];
|
||||
move.fromValue = [NSValue valueWithCGPoint: cp];
|
||||
move.toValue = [NSValue valueWithCGPoint: p];
|
||||
move.duration = .2;
|
||||
move.timingFunction = linear;
|
||||
move.fillMode = kCAFillModeForwards;
|
||||
move.removedOnCompletion = NO;
|
||||
|
||||
CABasicAnimation *on =
|
||||
[CABasicAnimation animationWithKeyPath: @"opacity"];
|
||||
on.fromValue = [NSNumber numberWithDouble: current.opacity];
|
||||
on.toValue = [NSNumber numberWithDouble: 1];
|
||||
on.duration = .2;
|
||||
on.timingFunction = linear;
|
||||
on.fillMode = kCAFillModeForwards;
|
||||
on.removedOnCompletion = NO;
|
||||
|
||||
CABasicAnimation *off = nil;
|
||||
if(!TARGET_IPHONE_SIMULATOR) {
|
||||
off = [CABasicAnimation animationWithKeyPath: @"opacity"];
|
||||
off.fromValue = [NSNumber numberWithDouble: 1];
|
||||
off.toValue = [NSNumber numberWithDouble: 0];
|
||||
off.beginTime = .5;
|
||||
off.duration = .5;
|
||||
off.timingFunction = linear;
|
||||
}
|
||||
|
||||
CAAnimationGroup *group = [CAAnimationGroup animation];
|
||||
group.animations = [NSArray arrayWithObjects: resize, move, on, off, nil];
|
||||
group.duration = 1;
|
||||
group.fillMode = kCAFillModeForwards;
|
||||
group.removedOnCompletion = !TARGET_IPHONE_SIMULATOR;
|
||||
[trk addAnimation: group
|
||||
forKey: @"tracking"];
|
||||
}
|
||||
|
||||
- (void) didTrackSymbols: (ZBarSymbolSet*) syms
|
||||
{
|
||||
if(!tracksSymbols)
|
||||
return;
|
||||
|
||||
int n = syms.count;
|
||||
assert(n);
|
||||
if(!n)
|
||||
return;
|
||||
|
||||
ZBarSymbol *sym = nil;
|
||||
for(ZBarSymbol *s in syms)
|
||||
if(!sym || s.type == ZBAR_QRCODE || s.quality > sym.quality)
|
||||
sym = s;
|
||||
assert(sym);
|
||||
if(!sym)
|
||||
return;
|
||||
|
||||
[self updateTracking: tracking
|
||||
withSymbol: sym];
|
||||
}
|
||||
|
||||
@end
|
||||
699
iphone/ZBarReaderViewController.m
Normal file
699
iphone/ZBarReaderViewController.m
Normal file
@ -0,0 +1,699 @@
|
||||
//------------------------------------------------------------------------
|
||||
// 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
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
#import <ZBarSDK/ZBarReaderViewController.h>
|
||||
#import <ZBarSDK/ZBarReaderView.h>
|
||||
#import <ZBarSDK/ZBarCaptureReader.h>
|
||||
#import <ZBarSDK/ZBarHelpController.h>
|
||||
#import <ZBarSDK/ZBarCameraSimulator.h>
|
||||
|
||||
#define MODULE ZBarReaderViewController
|
||||
#import "debug.h"
|
||||
|
||||
static inline AVCaptureDevicePosition
|
||||
AVPositionForUICamera (UIImagePickerControllerCameraDevice camera)
|
||||
{
|
||||
switch(camera) {
|
||||
case UIImagePickerControllerCameraDeviceRear:
|
||||
return(AVCaptureDevicePositionBack);
|
||||
case UIImagePickerControllerCameraDeviceFront:
|
||||
return(AVCaptureDevicePositionFront);
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
static inline UIImagePickerControllerCameraDevice
|
||||
UICameraForAVPosition (AVCaptureDevicePosition position)
|
||||
{
|
||||
switch(position)
|
||||
{
|
||||
case AVCaptureDevicePositionBack:
|
||||
return(UIImagePickerControllerCameraDeviceRear);
|
||||
case AVCaptureDevicePositionFront:
|
||||
return(UIImagePickerControllerCameraDeviceFront);
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
static inline AVCaptureDevice*
|
||||
AVDeviceForUICamera (UIImagePickerControllerCameraDevice camera)
|
||||
{
|
||||
AVCaptureDevicePosition position = AVPositionForUICamera(camera);
|
||||
if(position < 0)
|
||||
return(nil);
|
||||
|
||||
#if !TARGET_IPHONE_SIMULATOR
|
||||
NSArray *allDevices =
|
||||
[AVCaptureDevice devicesWithMediaType: AVMediaTypeVideo];
|
||||
for(AVCaptureDevice *device in allDevices)
|
||||
// FIXME how to quantify "best" of several (theoretical) possibilities
|
||||
if(device.position == position)
|
||||
return(device);
|
||||
#endif
|
||||
return(nil);
|
||||
}
|
||||
|
||||
static inline AVCaptureTorchMode
|
||||
AVTorchModeForUIFlashMode (UIImagePickerControllerCameraFlashMode mode)
|
||||
{
|
||||
switch(mode)
|
||||
{
|
||||
case UIImagePickerControllerCameraFlashModeAuto:
|
||||
return(AVCaptureTorchModeAuto);
|
||||
case UIImagePickerControllerCameraFlashModeOn:
|
||||
return(AVCaptureTorchModeOn);
|
||||
case UIImagePickerControllerCameraFlashModeOff:
|
||||
break;
|
||||
}
|
||||
return(AVCaptureTorchModeOff);
|
||||
}
|
||||
|
||||
static inline NSString*
|
||||
AVSessionPresetForUIVideoQuality (UIImagePickerControllerQualityType quality)
|
||||
{
|
||||
#if !TARGET_IPHONE_SIMULATOR
|
||||
switch(quality)
|
||||
{
|
||||
case UIImagePickerControllerQualityTypeHigh:
|
||||
return(AVCaptureSessionPresetHigh);
|
||||
case UIImagePickerControllerQualityType640x480:
|
||||
return(AVCaptureSessionPreset640x480);
|
||||
case UIImagePickerControllerQualityTypeMedium:
|
||||
return(AVCaptureSessionPresetMedium);
|
||||
case UIImagePickerControllerQualityTypeLow:
|
||||
return(AVCaptureSessionPresetLow);
|
||||
case UIImagePickerControllerQualityTypeIFrame1280x720:
|
||||
return(AVCaptureSessionPresetiFrame1280x720);
|
||||
case UIImagePickerControllerQualityTypeIFrame960x540:
|
||||
return(AVCaptureSessionPresetiFrame960x540);
|
||||
}
|
||||
#endif
|
||||
return(nil);
|
||||
}
|
||||
|
||||
|
||||
@implementation ZBarReaderViewController
|
||||
|
||||
@synthesize scanner, readerDelegate, showsZBarControls,
|
||||
supportedOrientationsMask, tracksSymbols, enableCache, cameraOverlayView,
|
||||
cameraViewTransform, cameraDevice, cameraFlashMode, videoQuality,
|
||||
readerView, scanCrop;
|
||||
@dynamic sourceType, allowsEditing, allowsImageEditing, showsCameraControls,
|
||||
showsHelpOnFail, cameraMode, takesPicture, maxScanDimension;
|
||||
|
||||
+ (BOOL) isSourceTypeAvailable: (UIImagePickerControllerSourceType) sourceType
|
||||
{
|
||||
if(sourceType != UIImagePickerControllerSourceTypeCamera)
|
||||
return(NO);
|
||||
return(TARGET_IPHONE_SIMULATOR ||
|
||||
[UIImagePickerController isSourceTypeAvailable: sourceType]);
|
||||
}
|
||||
|
||||
+ (BOOL) isCameraDeviceAvailable: (UIImagePickerControllerCameraDevice) camera
|
||||
{
|
||||
return(TARGET_IPHONE_SIMULATOR ||
|
||||
[UIImagePickerController isCameraDeviceAvailable: camera]);
|
||||
}
|
||||
|
||||
+ (BOOL) isFlashAvailableForCameraDevice: (UIImagePickerControllerCameraDevice) camera
|
||||
{
|
||||
return(TARGET_IPHONE_SIMULATOR ||
|
||||
[UIImagePickerController isFlashAvailableForCameraDevice: camera]);
|
||||
}
|
||||
|
||||
+ (NSArray*) availableCaptureModesForCameraDevice: (UIImagePickerControllerCameraDevice) camera
|
||||
{
|
||||
if(![self isCameraDeviceAvailable: camera])
|
||||
return([NSArray array]);
|
||||
|
||||
// current reader only supports automatic detection
|
||||
return([NSArray arrayWithObject:
|
||||
[NSNumber numberWithInteger:
|
||||
UIImagePickerControllerCameraCaptureModeVideo]]);
|
||||
}
|
||||
|
||||
- (void) _init
|
||||
{
|
||||
supportedOrientationsMask =
|
||||
ZBarOrientationMask(UIInterfaceOrientationPortrait);
|
||||
showsZBarControls = tracksSymbols = enableCache = YES;
|
||||
scanCrop = CGRectMake(0, 0, 1, 1);
|
||||
cameraViewTransform = CGAffineTransformIdentity;
|
||||
|
||||
cameraFlashMode = UIImagePickerControllerCameraFlashModeAuto;
|
||||
videoQuality = UIImagePickerControllerQualityType640x480;
|
||||
AVCaptureDevice *device = nil;
|
||||
#if !TARGET_IPHONE_SIMULATOR
|
||||
device = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo];
|
||||
#endif
|
||||
if(device)
|
||||
cameraDevice = UICameraForAVPosition(device.position);
|
||||
else
|
||||
cameraDevice = UIImagePickerControllerCameraDeviceRear;
|
||||
|
||||
// create our own scanner to store configuration,
|
||||
// independent of whether view is loaded
|
||||
scanner = [ZBarImageScanner new];
|
||||
[scanner setSymbology: 0
|
||||
config: ZBAR_CFG_X_DENSITY
|
||||
to: 3];
|
||||
[scanner setSymbology: 0
|
||||
config: ZBAR_CFG_Y_DENSITY
|
||||
to: 3];
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if(!TARGET_IPHONE_SIMULATOR &&
|
||||
!NSClassFromString(@"AVCaptureSession")) {
|
||||
// fallback to old interface
|
||||
zlog(@"Falling back to ZBarReaderController");
|
||||
[self release];
|
||||
return((id)[ZBarReaderController new]);
|
||||
}
|
||||
|
||||
self = [super init];
|
||||
if(!self)
|
||||
return(nil);
|
||||
|
||||
self.wantsFullScreenLayout = YES;
|
||||
[self _init];
|
||||
return(self);
|
||||
}
|
||||
|
||||
- (id) initWithCoder: (NSCoder*) decoder
|
||||
{
|
||||
self = [super initWithCoder: decoder];
|
||||
if(!self)
|
||||
return(nil);
|
||||
|
||||
[self _init];
|
||||
return(self);
|
||||
}
|
||||
|
||||
- (void) cleanup
|
||||
{
|
||||
[cameraOverlayView removeFromSuperview];
|
||||
cameraSim.readerView = nil;
|
||||
[cameraSim release];
|
||||
cameraSim = nil;
|
||||
readerView.readerDelegate = nil;
|
||||
[readerView release];
|
||||
readerView = nil;
|
||||
[controls release];
|
||||
controls = nil;
|
||||
[shutter release];
|
||||
shutter = nil;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[self cleanup];
|
||||
[cameraOverlayView release];
|
||||
cameraOverlayView = nil;
|
||||
[scanner release];
|
||||
scanner = nil;
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) initControls
|
||||
{
|
||||
if(!showsZBarControls && controls) {
|
||||
[controls removeFromSuperview];
|
||||
[controls release];
|
||||
controls = nil;
|
||||
}
|
||||
if(!showsZBarControls)
|
||||
return;
|
||||
|
||||
UIView *view = self.view;
|
||||
if(controls) {
|
||||
assert(controls.superview == view);
|
||||
[view bringSubviewToFront: controls];
|
||||
return;
|
||||
}
|
||||
|
||||
CGRect r = view.bounds;
|
||||
r.origin.y = r.size.height - 54;
|
||||
r.size.height = 54;
|
||||
controls = [[UIView alloc]
|
||||
initWithFrame: r];
|
||||
controls.autoresizingMask =
|
||||
UIViewAutoresizingFlexibleWidth |
|
||||
UIViewAutoresizingFlexibleHeight |
|
||||
UIViewAutoresizingFlexibleTopMargin;
|
||||
controls.backgroundColor = [UIColor blackColor];
|
||||
|
||||
UIToolbar *toolbar =
|
||||
[UIToolbar new];
|
||||
r.origin.y = 0;
|
||||
toolbar.frame = r;
|
||||
toolbar.barStyle = UIBarStyleBlackOpaque;
|
||||
toolbar.autoresizingMask =
|
||||
UIViewAutoresizingFlexibleWidth |
|
||||
UIViewAutoresizingFlexibleHeight;
|
||||
|
||||
UIButton *info =
|
||||
[UIButton buttonWithType: UIButtonTypeInfoLight];
|
||||
[info addTarget: self
|
||||
action: @selector(info)
|
||||
forControlEvents: UIControlEventTouchUpInside];
|
||||
|
||||
toolbar.items =
|
||||
[NSArray arrayWithObjects:
|
||||
[[[UIBarButtonItem alloc]
|
||||
initWithBarButtonSystemItem: UIBarButtonSystemItemCancel
|
||||
target: self
|
||||
action: @selector(cancel)]
|
||||
autorelease],
|
||||
[[[UIBarButtonItem alloc]
|
||||
initWithBarButtonSystemItem: UIBarButtonSystemItemFlexibleSpace
|
||||
target: nil
|
||||
action: nil]
|
||||
autorelease],
|
||||
[[[UIBarButtonItem alloc]
|
||||
initWithCustomView: info]
|
||||
autorelease],
|
||||
nil];
|
||||
[controls addSubview: toolbar];
|
||||
[toolbar release];
|
||||
|
||||
[view addSubview: controls];
|
||||
}
|
||||
|
||||
- (void) initVideoQuality
|
||||
{
|
||||
if(!readerView) {
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
AVCaptureSession *session = readerView.session;
|
||||
NSString *preset = AVSessionPresetForUIVideoQuality(videoQuality);
|
||||
if(session && preset && [session canSetSessionPreset: preset]) {
|
||||
zlog(@"set session preset=%@", preset);
|
||||
session.sessionPreset = preset;
|
||||
}
|
||||
else
|
||||
zlog(@"unable to set session preset=%@", preset);
|
||||
}
|
||||
|
||||
- (void) loadView
|
||||
{
|
||||
self.view = [[UIView alloc]
|
||||
initWithFrame: CGRectMake(0, 0, 320, 480)];
|
||||
}
|
||||
|
||||
- (void) viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
UIView *view = self.view;
|
||||
view.backgroundColor = [UIColor blackColor];
|
||||
view.autoresizingMask =
|
||||
UIViewAutoresizingFlexibleWidth |
|
||||
UIViewAutoresizingFlexibleHeight;
|
||||
|
||||
readerView = [[ZBarReaderView alloc]
|
||||
initWithImageScanner: scanner];
|
||||
CGRect bounds = view.bounds;
|
||||
CGRect r = bounds;
|
||||
NSUInteger autoresize =
|
||||
UIViewAutoresizingFlexibleWidth |
|
||||
UIViewAutoresizingFlexibleHeight;
|
||||
|
||||
if(showsZBarControls ||
|
||||
self.parentViewController.modalViewController == self)
|
||||
{
|
||||
autoresize |= UIViewAutoresizingFlexibleBottomMargin;
|
||||
r.size.height -= 54;
|
||||
}
|
||||
readerView.frame = r;
|
||||
readerView.autoresizingMask = autoresize;
|
||||
AVCaptureDevice *device = AVDeviceForUICamera(cameraDevice);
|
||||
if(device && device != readerView.device)
|
||||
readerView.device = device;
|
||||
readerView.torchMode = AVTorchModeForUIFlashMode(cameraFlashMode);
|
||||
[self initVideoQuality];
|
||||
|
||||
readerView.readerDelegate = (id<ZBarReaderViewDelegate>)self;
|
||||
readerView.scanCrop = scanCrop;
|
||||
readerView.previewTransform = cameraViewTransform;
|
||||
readerView.tracksSymbols = tracksSymbols;
|
||||
readerView.enableCache = enableCache;
|
||||
[view addSubview: readerView];
|
||||
|
||||
shutter = [[UIView alloc]
|
||||
initWithFrame: r];
|
||||
shutter.backgroundColor = [UIColor blackColor];
|
||||
shutter.opaque = NO;
|
||||
shutter.autoresizingMask =
|
||||
UIViewAutoresizingFlexibleWidth |
|
||||
UIViewAutoresizingFlexibleHeight;
|
||||
[view addSubview: shutter];
|
||||
|
||||
if(cameraOverlayView) {
|
||||
assert(!cameraOverlayView.superview);
|
||||
[cameraOverlayView removeFromSuperview];
|
||||
[view addSubview: cameraOverlayView];
|
||||
}
|
||||
|
||||
[self initControls];
|
||||
|
||||
if(TARGET_IPHONE_SIMULATOR) {
|
||||
cameraSim = [[ZBarCameraSimulator alloc]
|
||||
initWithViewController: self];
|
||||
cameraSim.readerView = readerView;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) viewDidUnload
|
||||
{
|
||||
[cameraOverlayView removeFromSuperview];
|
||||
[self cleanup];
|
||||
[super viewDidUnload];
|
||||
}
|
||||
|
||||
- (void) viewWillAppear: (BOOL) animated
|
||||
{
|
||||
zlog(@"willAppear: anim=%d orient=%d",
|
||||
animated, self.interfaceOrientation);
|
||||
[self initControls];
|
||||
[super viewWillAppear: animated];
|
||||
|
||||
[readerView willRotateToInterfaceOrientation: self.interfaceOrientation
|
||||
duration: 0];
|
||||
[readerView performSelector: @selector(start)
|
||||
withObject: nil
|
||||
afterDelay: .001];
|
||||
shutter.alpha = 1;
|
||||
shutter.hidden = NO;
|
||||
|
||||
UIApplication *app = [UIApplication sharedApplication];
|
||||
BOOL willHideStatusBar =
|
||||
!didHideStatusBar && self.wantsFullScreenLayout && !app.statusBarHidden;
|
||||
if(willHideStatusBar)
|
||||
[app setStatusBarHidden: YES
|
||||
withAnimation: UIStatusBarAnimationFade];
|
||||
didHideStatusBar = didHideStatusBar || willHideStatusBar;
|
||||
}
|
||||
|
||||
- (void) dismissModalViewControllerAnimated: (BOOL) animated
|
||||
{
|
||||
if(didHideStatusBar) {
|
||||
[[UIApplication sharedApplication]
|
||||
setStatusBarHidden: NO
|
||||
withAnimation: UIStatusBarAnimationFade];
|
||||
didHideStatusBar = NO;
|
||||
}
|
||||
[super dismissModalViewControllerAnimated: animated];
|
||||
}
|
||||
|
||||
- (void) viewWillDisappear: (BOOL) animated
|
||||
{
|
||||
readerView.captureReader.enableReader = NO;
|
||||
|
||||
if(didHideStatusBar) {
|
||||
[[UIApplication sharedApplication]
|
||||
setStatusBarHidden: NO
|
||||
withAnimation: UIStatusBarAnimationFade];
|
||||
didHideStatusBar = NO;
|
||||
}
|
||||
|
||||
[super viewWillDisappear: animated];
|
||||
}
|
||||
|
||||
- (void) viewDidDisappear: (BOOL) animated
|
||||
{
|
||||
// stopRunning can take a really long time (>1s observed),
|
||||
// so defer until the view transitions are complete
|
||||
[readerView stop];
|
||||
}
|
||||
|
||||
- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) orient
|
||||
{
|
||||
return((supportedOrientationsMask >> orient) & 1);
|
||||
}
|
||||
|
||||
- (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) orient
|
||||
duration: (NSTimeInterval) duration
|
||||
{
|
||||
zlog(@"willRotate: orient=%d #%g", orient, duration);
|
||||
rotating = YES;
|
||||
if(readerView)
|
||||
[readerView willRotateToInterfaceOrientation: orient
|
||||
duration: duration];
|
||||
}
|
||||
|
||||
- (void) willAnimateRotationToInterfaceOrientation: (UIInterfaceOrientation) orient
|
||||
duration: (NSTimeInterval) duration
|
||||
{
|
||||
zlog(@"willAnimateRotation: orient=%d #%g", orient, duration);
|
||||
if(helpController)
|
||||
[helpController willAnimateRotationToInterfaceOrientation: orient
|
||||
duration: duration];
|
||||
if(readerView)
|
||||
[readerView setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void) didRotateFromInterfaceOrientation: (UIInterfaceOrientation) orient
|
||||
{
|
||||
zlog(@"didRotate(%d): orient=%d", rotating, orient);
|
||||
if(!rotating && readerView) {
|
||||
// work around UITabBarController bug: willRotate is not called
|
||||
// for non-portrait initial interface orientation
|
||||
[readerView willRotateToInterfaceOrientation: self.interfaceOrientation
|
||||
duration: 0];
|
||||
[readerView setNeedsLayout];
|
||||
}
|
||||
rotating = NO;
|
||||
}
|
||||
|
||||
- (ZBarReaderView*) readerView
|
||||
{
|
||||
// force view to load
|
||||
(void)self.view;
|
||||
assert(readerView);
|
||||
return(readerView);
|
||||
}
|
||||
|
||||
- (void) setTracksSymbols: (BOOL) track
|
||||
{
|
||||
tracksSymbols = track;
|
||||
if(readerView)
|
||||
readerView.tracksSymbols = track;
|
||||
}
|
||||
|
||||
- (void) setEnableCache: (BOOL) enable
|
||||
{
|
||||
enableCache = enable;
|
||||
if(readerView)
|
||||
readerView.enableCache = enable;
|
||||
}
|
||||
|
||||
- (void) setScanCrop: (CGRect) r
|
||||
{
|
||||
scanCrop = r;
|
||||
if(readerView)
|
||||
readerView.scanCrop = r;
|
||||
}
|
||||
|
||||
- (void) setCameraOverlayView: (UIView*) newview
|
||||
{
|
||||
UIView *oldview = cameraOverlayView;
|
||||
[oldview removeFromSuperview];
|
||||
|
||||
cameraOverlayView = [newview retain];
|
||||
if([self isViewLoaded] && newview)
|
||||
[self.view addSubview: newview];
|
||||
|
||||
[oldview release];
|
||||
}
|
||||
|
||||
- (void) setCameraViewTransform: (CGAffineTransform) xfrm
|
||||
{
|
||||
cameraViewTransform = xfrm;
|
||||
if(readerView)
|
||||
readerView.previewTransform = xfrm;
|
||||
}
|
||||
|
||||
- (void) cancel
|
||||
{
|
||||
if(!readerDelegate)
|
||||
return;
|
||||
SEL cb = @selector(imagePickerControllerDidCancel:);
|
||||
if([readerDelegate respondsToSelector: cb])
|
||||
[readerDelegate
|
||||
imagePickerControllerDidCancel: (UIImagePickerController*)self];
|
||||
else
|
||||
[self dismissModalViewControllerAnimated: YES];
|
||||
}
|
||||
|
||||
- (void) info
|
||||
{
|
||||
[self showHelpWithReason: @"INFO"];
|
||||
}
|
||||
|
||||
- (void) showHelpWithReason: (NSString*) reason
|
||||
{
|
||||
if(helpController)
|
||||
return;
|
||||
helpController = [[ZBarHelpController alloc]
|
||||
initWithReason: reason];
|
||||
helpController.delegate = (id<ZBarHelpDelegate>)self;
|
||||
helpController.wantsFullScreenLayout = YES;
|
||||
UIView *helpView = helpController.view;
|
||||
helpView.alpha = 0;
|
||||
helpView.frame = self.view.bounds;
|
||||
[helpController viewWillAppear: YES];
|
||||
[self.view addSubview: helpView];
|
||||
[UIView beginAnimations: @"ZBarHelp"
|
||||
context: nil];
|
||||
helpController.view.alpha = 1;
|
||||
[UIView commitAnimations];
|
||||
}
|
||||
|
||||
- (void) takePicture
|
||||
{
|
||||
if(TARGET_IPHONE_SIMULATOR) {
|
||||
[cameraSim takePicture];
|
||||
// FIXME return selected image
|
||||
}
|
||||
else if(readerView)
|
||||
[readerView.captureReader captureFrame];
|
||||
}
|
||||
|
||||
- (void) setCameraDevice: (UIImagePickerControllerCameraDevice) camera
|
||||
{
|
||||
cameraDevice = camera;
|
||||
if(readerView) {
|
||||
AVCaptureDevice *device = AVDeviceForUICamera(camera);
|
||||
if(device)
|
||||
readerView.device = device;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) setCameraFlashMode: (UIImagePickerControllerCameraFlashMode) mode
|
||||
{
|
||||
cameraFlashMode = mode;
|
||||
if(readerView)
|
||||
readerView.torchMode = AVTorchModeForUIFlashMode(mode);
|
||||
}
|
||||
|
||||
- (UIImagePickerControllerCameraCaptureMode) cameraCaptureMode
|
||||
{
|
||||
return(UIImagePickerControllerCameraCaptureModeVideo);
|
||||
}
|
||||
|
||||
- (void) setCameraCaptureMode: (UIImagePickerControllerCameraCaptureMode) mode
|
||||
{
|
||||
NSAssert2(mode == UIImagePickerControllerCameraCaptureModeVideo,
|
||||
@"attempt to set unsupported value (%d)"
|
||||
@" for %@ property", mode, @"cameraCaptureMode");
|
||||
}
|
||||
|
||||
- (void) setVideoQuality: (UIImagePickerControllerQualityType) quality
|
||||
{
|
||||
videoQuality = quality;
|
||||
if(readerView)
|
||||
[self initVideoQuality];
|
||||
}
|
||||
|
||||
|
||||
// ZBarHelpDelegate
|
||||
|
||||
- (void) helpControllerDidFinish: (ZBarHelpController*) help
|
||||
{
|
||||
assert(help == helpController);
|
||||
[help viewWillDisappear: YES];
|
||||
[UIView beginAnimations: @"ZBarHelp"
|
||||
context: NULL];
|
||||
[UIView setAnimationDelegate: self];
|
||||
[UIView setAnimationDidStopSelector: @selector(removeHelp:done:context:)];
|
||||
help.view.alpha = 0;
|
||||
[UIView commitAnimations];
|
||||
}
|
||||
|
||||
- (void) removeHelp: (NSString*) tag
|
||||
done: (NSNumber*) done
|
||||
context: (void*) ctx
|
||||
{
|
||||
if([tag isEqualToString: @"ZBarHelp"] && helpController) {
|
||||
[helpController.view removeFromSuperview];
|
||||
[helpController release];
|
||||
helpController = nil;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ZBarReaderViewDelegate
|
||||
|
||||
- (void) readerView: (ZBarReaderView*) readerView
|
||||
didReadSymbols: (ZBarSymbolSet*) syms
|
||||
fromImage: (UIImage*) image
|
||||
{
|
||||
[readerDelegate
|
||||
imagePickerController: (UIImagePickerController*)self
|
||||
didFinishPickingMediaWithInfo:
|
||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
image, UIImagePickerControllerOriginalImage,
|
||||
syms, ZBarReaderControllerResults,
|
||||
nil]];
|
||||
}
|
||||
|
||||
- (void) readerViewDidStart: (ZBarReaderView*) readerView
|
||||
{
|
||||
if(!shutter.hidden)
|
||||
[UIView animateWithDuration: .25
|
||||
animations: ^{
|
||||
shutter.alpha = 0;
|
||||
}
|
||||
completion: ^(BOOL finished) {
|
||||
shutter.hidden = YES;
|
||||
}];
|
||||
}
|
||||
|
||||
|
||||
// "deprecated" properties
|
||||
|
||||
#define DEPRECATED_PROPERTY(getter, setter, type, val, ignore) \
|
||||
- (type) getter \
|
||||
{ \
|
||||
return(val); \
|
||||
} \
|
||||
- (void) setter: (type) v \
|
||||
{ \
|
||||
NSAssert2(ignore || v == val, \
|
||||
@"attempt to set unsupported value (%d)" \
|
||||
@" for %@ property", val, @#getter); \
|
||||
}
|
||||
|
||||
DEPRECATED_PROPERTY(sourceType, setSourceType, UIImagePickerControllerSourceType, UIImagePickerControllerSourceTypeCamera, NO)
|
||||
DEPRECATED_PROPERTY(allowsEditing, setAllowsEditing, BOOL, NO, NO)
|
||||
DEPRECATED_PROPERTY(allowsImageEditing, setAllowsImageEditing, BOOL, NO, NO)
|
||||
DEPRECATED_PROPERTY(showsCameraControls, setShowsCameraControls, BOOL, NO, NO)
|
||||
DEPRECATED_PROPERTY(showsHelpOnFail, setShowsHelpOnFail, BOOL, NO, YES)
|
||||
DEPRECATED_PROPERTY(cameraMode, setCameraMode, ZBarReaderControllerCameraMode, ZBarReaderControllerCameraModeSampling, NO)
|
||||
DEPRECATED_PROPERTY(takesPicture, setTakesPicture, BOOL, NO, NO)
|
||||
DEPRECATED_PROPERTY(maxScanDimension, setMaxScanDimension, NSInteger, 640, YES)
|
||||
|
||||
@end
|
||||
402
iphone/ZBarReaderViewImpl_Capture.m
Normal file
402
iphone/ZBarReaderViewImpl_Capture.m
Normal file
@ -0,0 +1,402 @@
|
||||
//------------------------------------------------------------------------
|
||||
// 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
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import <CoreMedia/CoreMedia.h>
|
||||
#import <CoreVideo/CoreVideo.h>
|
||||
#import <ZBarSDK/ZBarReaderView.h>
|
||||
#import <ZBarSDK/ZBarCaptureReader.h>
|
||||
|
||||
#define MODULE ZBarReaderView
|
||||
#import "debug.h"
|
||||
|
||||
// protected APIs
|
||||
@interface ZBarReaderView()
|
||||
- (void) _initWithImageScanner: (ZBarImageScanner*) _scanner;
|
||||
- (void) initSubviews;
|
||||
- (void) updateCrop;
|
||||
- (void) setImageSize: (CGSize) size;
|
||||
- (void) didTrackSymbols: (ZBarSymbolSet*) syms;
|
||||
@end
|
||||
|
||||
@interface ZBarReaderViewImpl
|
||||
: ZBarReaderView
|
||||
{
|
||||
AVCaptureSession *session;
|
||||
AVCaptureDevice *device;
|
||||
AVCaptureInput *input;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation ZBarReaderViewImpl
|
||||
|
||||
@synthesize device, session;
|
||||
|
||||
- (void) _initWithImageScanner: (ZBarImageScanner*) scanner
|
||||
{
|
||||
[super _initWithImageScanner: scanner];
|
||||
|
||||
session = [AVCaptureSession new];
|
||||
NSNotificationCenter *notify =
|
||||
[NSNotificationCenter defaultCenter];
|
||||
[notify addObserver: self
|
||||
selector: @selector(onVideoError:)
|
||||
name: AVCaptureSessionRuntimeErrorNotification
|
||||
object: session];
|
||||
[notify addObserver: self
|
||||
selector: @selector(onVideoStart:)
|
||||
name: AVCaptureSessionDidStartRunningNotification
|
||||
object: session];
|
||||
[notify addObserver: self
|
||||
selector: @selector(onVideoStop:)
|
||||
name: AVCaptureSessionDidStopRunningNotification
|
||||
object: session];
|
||||
[notify addObserver: self
|
||||
selector: @selector(onVideoStop:)
|
||||
name: AVCaptureSessionWasInterruptedNotification
|
||||
object: session];
|
||||
[notify addObserver: self
|
||||
selector: @selector(onVideoStart:)
|
||||
name: AVCaptureSessionInterruptionEndedNotification
|
||||
object: session];
|
||||
|
||||
self.device = [AVCaptureDevice
|
||||
defaultDeviceWithMediaType: AVMediaTypeVideo];
|
||||
|
||||
captureReader = [[ZBarCaptureReader alloc]
|
||||
initWithImageScanner: scanner];
|
||||
captureReader.captureDelegate = (id<ZBarCaptureDelegate>)self;
|
||||
[session addOutput: captureReader.captureOutput];
|
||||
|
||||
if([session canSetSessionPreset: AVCaptureSessionPreset640x480])
|
||||
session.sessionPreset = AVCaptureSessionPreset640x480;
|
||||
|
||||
[captureReader addObserver: self
|
||||
forKeyPath: @"size"
|
||||
options: 0
|
||||
context: NULL];
|
||||
|
||||
[self initSubviews];
|
||||
}
|
||||
|
||||
- (void) initSubviews
|
||||
{
|
||||
AVCaptureVideoPreviewLayer *videoPreview =
|
||||
[[AVCaptureVideoPreviewLayer
|
||||
layerWithSession: session]
|
||||
retain];
|
||||
preview = videoPreview;
|
||||
CGRect bounds = self.bounds;
|
||||
bounds.origin = CGPointZero;
|
||||
preview.bounds = bounds;
|
||||
preview.position = CGPointMake(bounds.size.width / 2,
|
||||
bounds.size.height / 2);
|
||||
videoPreview.videoGravity = AVLayerVideoGravityResizeAspectFill;
|
||||
[self.layer addSublayer: preview];
|
||||
|
||||
[super initSubviews];
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
removeObserver: self];
|
||||
if(showsFPS) {
|
||||
@try {
|
||||
[captureReader removeObserver: self
|
||||
forKeyPath: @"framesPerSecond"];
|
||||
}
|
||||
@catch(...) { }
|
||||
}
|
||||
@try {
|
||||
[captureReader removeObserver: self
|
||||
forKeyPath: @"size"];
|
||||
}
|
||||
@catch(...) { }
|
||||
captureReader.captureDelegate = nil;
|
||||
[captureReader release];
|
||||
captureReader = nil;
|
||||
[device release];
|
||||
device = nil;
|
||||
[input release];
|
||||
input = nil;
|
||||
[session release];
|
||||
session = nil;
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) updateCrop
|
||||
{
|
||||
[super updateCrop];
|
||||
captureReader.scanCrop = effectiveCrop;
|
||||
}
|
||||
|
||||
- (ZBarImageScanner*) scanner
|
||||
{
|
||||
return(captureReader.scanner);
|
||||
}
|
||||
|
||||
- (void) setDevice: (AVCaptureDevice*) newdev
|
||||
{
|
||||
id olddev = device;
|
||||
AVCaptureInput *oldinput = input;
|
||||
assert(!olddev == !oldinput);
|
||||
|
||||
NSError *error = nil;
|
||||
device = [newdev retain];
|
||||
if(device) {
|
||||
assert([device hasMediaType: AVMediaTypeVideo]);
|
||||
input = [[AVCaptureDeviceInput alloc]
|
||||
initWithDevice: newdev
|
||||
error: &error];
|
||||
assert(input);
|
||||
}
|
||||
else
|
||||
input = nil;
|
||||
|
||||
[session beginConfiguration];
|
||||
if(oldinput)
|
||||
[session removeInput: oldinput];
|
||||
if(input)
|
||||
[session addInput: input];
|
||||
[session commitConfiguration];
|
||||
|
||||
[olddev release];
|
||||
[oldinput release];
|
||||
}
|
||||
|
||||
- (BOOL) enableCache
|
||||
{
|
||||
return(captureReader.enableCache);
|
||||
}
|
||||
|
||||
- (void) setEnableCache: (BOOL) enable
|
||||
{
|
||||
captureReader.enableCache = enable;
|
||||
}
|
||||
|
||||
- (void) setTorchMode: (NSInteger) mode
|
||||
{
|
||||
[super setTorchMode: mode];
|
||||
if(running && [device isTorchModeSupported: mode])
|
||||
@try {
|
||||
device.torchMode = mode;
|
||||
}
|
||||
@catch(...) { }
|
||||
}
|
||||
|
||||
- (void) setShowsFPS: (BOOL) show
|
||||
{
|
||||
[super setShowsFPS: show];
|
||||
@try {
|
||||
if(show)
|
||||
[captureReader addObserver: self
|
||||
forKeyPath: @"framesPerSecond"
|
||||
options: 0
|
||||
context: NULL];
|
||||
else
|
||||
[captureReader removeObserver: self
|
||||
forKeyPath: @"framesPerSecond"];
|
||||
}
|
||||
@catch(...) { }
|
||||
}
|
||||
|
||||
- (void) start
|
||||
{
|
||||
if(started)
|
||||
return;
|
||||
[super start];
|
||||
|
||||
[session startRunning];
|
||||
captureReader.enableReader = YES;
|
||||
}
|
||||
|
||||
- (void) stop
|
||||
{
|
||||
if(!started)
|
||||
return;
|
||||
[super stop];
|
||||
|
||||
captureReader.enableReader = NO;
|
||||
[session stopRunning];
|
||||
}
|
||||
|
||||
- (void) flushCache
|
||||
{
|
||||
[captureReader flushCache];
|
||||
}
|
||||
|
||||
- (void) configureDevice
|
||||
{
|
||||
if([device isFocusModeSupported: AVCaptureFocusModeContinuousAutoFocus])
|
||||
device.focusMode = AVCaptureFocusModeContinuousAutoFocus;
|
||||
if([device isTorchModeSupported: torchMode])
|
||||
device.torchMode = torchMode;
|
||||
}
|
||||
|
||||
- (void) lockDevice
|
||||
{
|
||||
if(!running || locked) {
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// lock device and set focus mode
|
||||
NSError *error = nil;
|
||||
if([device lockForConfiguration: &error]) {
|
||||
locked = YES;
|
||||
[self configureDevice];
|
||||
}
|
||||
else {
|
||||
zlog(@"failed to lock device: %@", error);
|
||||
// just keep trying
|
||||
[self performSelector: @selector(lockDevice)
|
||||
withObject: nil
|
||||
afterDelay: .5];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// AVCaptureSession notifications
|
||||
|
||||
- (void) onVideoStart: (NSNotification*) note
|
||||
{
|
||||
zlog(@"onVideoStart: running=%d %@", running, note);
|
||||
if(running)
|
||||
return;
|
||||
running = YES;
|
||||
locked = NO;
|
||||
|
||||
[self lockDevice];
|
||||
|
||||
if([readerDelegate respondsToSelector: @selector(readerViewDidStart:)])
|
||||
[readerDelegate readerViewDidStart: self];
|
||||
}
|
||||
|
||||
- (void) onVideoStop: (NSNotification*) note
|
||||
{
|
||||
zlog(@"onVideoStop: %@", note);
|
||||
if(!running)
|
||||
return;
|
||||
running = NO;
|
||||
|
||||
if(locked)
|
||||
[device unlockForConfiguration];
|
||||
else
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget: self
|
||||
selector: @selector(lockDevice)
|
||||
object: nil];
|
||||
locked = NO;
|
||||
|
||||
if([readerDelegate respondsToSelector:
|
||||
@selector(readerView:didStopWithError:)])
|
||||
[readerDelegate readerView: self
|
||||
didStopWithError: nil];
|
||||
}
|
||||
|
||||
- (void) onVideoError: (NSNotification*) note
|
||||
{
|
||||
zlog(@"onVideoError: %@", note);
|
||||
if(running) {
|
||||
// FIXME does session always stop on error?
|
||||
running = started = NO;
|
||||
[device unlockForConfiguration];
|
||||
}
|
||||
NSError *err =
|
||||
[note.userInfo objectForKey: AVCaptureSessionErrorKey];
|
||||
|
||||
if([readerDelegate respondsToSelector:
|
||||
@selector(readerView:didStopWithError:)])
|
||||
[readerDelegate readerView: self
|
||||
didStopWithError: err];
|
||||
else
|
||||
NSLog(@"ZBarReaderView: ERROR during capture: %@: %@",
|
||||
[err localizedDescription],
|
||||
[err localizedFailureReason]);
|
||||
}
|
||||
|
||||
// NSKeyValueObserving
|
||||
|
||||
- (void) observeValueForKeyPath: (NSString*) path
|
||||
ofObject: (id) obj
|
||||
change: (NSDictionary*) info
|
||||
context: (void*) ctx
|
||||
{
|
||||
if(obj == captureReader &&
|
||||
[path isEqualToString: @"size"])
|
||||
// adjust preview to match image size
|
||||
[self setImageSize: captureReader.size];
|
||||
else if(obj == captureReader &&
|
||||
[path isEqualToString: @"framesPerSecond"])
|
||||
fpsLabel.text = [NSString stringWithFormat: @"%.2ffps ",
|
||||
captureReader.framesPerSecond];
|
||||
}
|
||||
|
||||
// ZBarCaptureDelegate
|
||||
|
||||
- (void) captureReader: (ZBarCaptureReader*) reader
|
||||
didTrackSymbols: (ZBarSymbolSet*) syms
|
||||
{
|
||||
[self didTrackSymbols: syms];
|
||||
}
|
||||
|
||||
- (void) captureReader: (ZBarCaptureReader*) reader
|
||||
didReadNewSymbolsFromImage: (ZBarImage*) zimg
|
||||
{
|
||||
zlog(@"scanned %d symbols: %@", zimg.symbols.count, zimg);
|
||||
if(!readerDelegate)
|
||||
return;
|
||||
|
||||
UIImageOrientation orient = [UIDevice currentDevice].orientation;
|
||||
if(!UIDeviceOrientationIsValidInterfaceOrientation(orient)) {
|
||||
orient = interfaceOrientation;
|
||||
if(orient == UIInterfaceOrientationLandscapeLeft)
|
||||
orient = UIDeviceOrientationLandscapeLeft;
|
||||
else if(orient == UIInterfaceOrientationLandscapeRight)
|
||||
orient = UIDeviceOrientationLandscapeRight;
|
||||
}
|
||||
switch(orient)
|
||||
{
|
||||
case UIDeviceOrientationPortraitUpsideDown:
|
||||
orient = UIImageOrientationLeft;
|
||||
break;
|
||||
case UIDeviceOrientationLandscapeLeft:
|
||||
orient = UIImageOrientationUp;
|
||||
break;
|
||||
case UIDeviceOrientationLandscapeRight:
|
||||
orient = UIImageOrientationDown;
|
||||
break;
|
||||
default:
|
||||
orient = UIImageOrientationRight;
|
||||
break;
|
||||
}
|
||||
|
||||
UIImage *uiimg = [zimg UIImageWithOrientation: orient];
|
||||
[readerDelegate
|
||||
readerView: self
|
||||
didReadSymbols: zimg.symbols
|
||||
fromImage: uiimg];
|
||||
}
|
||||
|
||||
@end
|
||||
219
iphone/ZBarReaderViewImpl_Simulator.m
Normal file
219
iphone/ZBarReaderViewImpl_Simulator.m
Normal file
@ -0,0 +1,219 @@
|
||||
//------------------------------------------------------------------------
|
||||
// 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
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
#import <ZBarSDK/ZBarReaderView.h>
|
||||
#import <ZBarSDK/ZBarReaderViewController.h>
|
||||
|
||||
#define MODULE ZBarReaderView
|
||||
#import "debug.h"
|
||||
|
||||
// hack around missing simulator support for AVCapture interfaces
|
||||
|
||||
// protected APIs
|
||||
@interface ZBarReaderView()
|
||||
- (void) _initWithImageScanner: (ZBarImageScanner*) _scanner;
|
||||
- (void) initSubviews;
|
||||
- (void) setImageSize: (CGSize) size;
|
||||
- (void) didTrackSymbols: (ZBarSymbolSet*) syms;
|
||||
@end
|
||||
|
||||
@interface ZBarReaderViewImpl
|
||||
: ZBarReaderView
|
||||
{
|
||||
ZBarImageScanner *scanner;
|
||||
UILabel *simLabel;
|
||||
UIImage *scanImage;
|
||||
CALayer *previewImage;
|
||||
BOOL enableCache;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation ZBarReaderViewImpl
|
||||
|
||||
@synthesize scanner, enableCache;
|
||||
|
||||
- (void) _initWithImageScanner: (ZBarImageScanner*) _scanner
|
||||
{
|
||||
[super _initWithImageScanner: _scanner];
|
||||
scanner = [_scanner retain];
|
||||
|
||||
[self initSubviews];
|
||||
}
|
||||
|
||||
- (void) initSubviews
|
||||
{
|
||||
simLabel = [UILabel new];
|
||||
simLabel.backgroundColor = [UIColor clearColor];
|
||||
simLabel.textColor = [UIColor whiteColor];
|
||||
simLabel.font = [UIFont boldSystemFontOfSize: 20];
|
||||
simLabel.numberOfLines = 4;
|
||||
simLabel.textAlignment = UITextAlignmentCenter;
|
||||
simLabel.text = @"Camera Simulation\n\n"
|
||||
@"Tap and hold with two \"fingers\" to select image";
|
||||
simLabel.autoresizingMask =
|
||||
UIViewAutoresizingFlexibleWidth |
|
||||
UIViewAutoresizingFlexibleHeight;
|
||||
[self addSubview: simLabel];
|
||||
|
||||
preview = [CALayer new];
|
||||
[self.layer addSublayer: preview];
|
||||
|
||||
previewImage = [CALayer new];
|
||||
[preview addSublayer: previewImage];
|
||||
|
||||
[super initSubviews];
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[scanner release];
|
||||
scanner = nil;
|
||||
[simLabel release];
|
||||
simLabel = nil;
|
||||
[previewImage release];
|
||||
previewImage = nil;
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (AVCaptureDevice*) device
|
||||
{
|
||||
return(nil);
|
||||
}
|
||||
|
||||
- (void) setDevice: (AVCaptureDevice*) device
|
||||
{
|
||||
// simulated camera does nothing with this
|
||||
}
|
||||
|
||||
- (AVCaptureSession*) session
|
||||
{
|
||||
return(nil);
|
||||
}
|
||||
|
||||
- (void) updateCrop
|
||||
{
|
||||
previewImage.frame = preview.bounds;
|
||||
CGRect bounds = self.bounds;
|
||||
simLabel.frame = CGRectInset(bounds,
|
||||
bounds.size.width * .05,
|
||||
bounds.size.height * .05);
|
||||
}
|
||||
|
||||
- (void) start
|
||||
{
|
||||
if(started)
|
||||
return;
|
||||
[super start];
|
||||
running = YES;
|
||||
|
||||
[self performSelector: @selector(onVideoStart)
|
||||
withObject: nil
|
||||
afterDelay: 0.5];
|
||||
}
|
||||
|
||||
- (void) stop
|
||||
{
|
||||
if(!started)
|
||||
return;
|
||||
[super stop];
|
||||
running = NO;
|
||||
|
||||
[self performSelector: @selector(onVideoStop)
|
||||
withObject: nil
|
||||
afterDelay: 0.5];
|
||||
}
|
||||
|
||||
- (void) scanImage: (UIImage*) image
|
||||
{
|
||||
// strip EXIF info
|
||||
CGImageRef cgimage = image.CGImage;
|
||||
image = [[UIImage alloc]
|
||||
initWithCGImage: cgimage
|
||||
scale: 1.0
|
||||
orientation: UIImageOrientationUp];
|
||||
|
||||
[self setImageSize: image.size];
|
||||
[self layoutIfNeeded];
|
||||
|
||||
[CATransaction begin];
|
||||
[CATransaction setDisableActions: YES];
|
||||
previewImage.contentsGravity = kCAGravityResizeAspectFill;
|
||||
previewImage.transform = CATransform3DMakeRotation(M_PI_2, 0, 0, 1);
|
||||
previewImage.contents = (id)cgimage;
|
||||
[CATransaction commit];
|
||||
|
||||
ZBarImage *zimg =
|
||||
[[ZBarImage alloc]
|
||||
initWithCGImage: cgimage];
|
||||
|
||||
CGSize size = zimg.size;
|
||||
zimg.crop = CGRectMake(effectiveCrop.origin.x * size.width,
|
||||
effectiveCrop.origin.y * size.height,
|
||||
effectiveCrop.size.width * size.width,
|
||||
effectiveCrop.size.height * size.height);
|
||||
|
||||
int nsyms = [scanner scanImage: zimg];
|
||||
zlog(@"scan image: %@ crop=%@ nsyms=%d",
|
||||
NSStringFromCGSize(size), NSStringFromCGRect(zimg.crop), nsyms);
|
||||
[zimg release];
|
||||
|
||||
if(nsyms > 0) {
|
||||
scanImage = [image retain];
|
||||
ZBarSymbolSet *syms = scanner.results;
|
||||
[self performSelector: @selector(didReadSymbols:)
|
||||
withObject: syms
|
||||
afterDelay: .4];
|
||||
[self performSelector: @selector(didTrackSymbols:)
|
||||
withObject: syms
|
||||
afterDelay: .001];
|
||||
}
|
||||
[image release];
|
||||
}
|
||||
|
||||
- (void) didReadSymbols: (ZBarSymbolSet*) syms
|
||||
{
|
||||
[readerDelegate
|
||||
readerView: self
|
||||
didReadSymbols: syms
|
||||
fromImage: scanImage];
|
||||
[scanImage release];
|
||||
scanImage = nil;
|
||||
}
|
||||
|
||||
- (void) onVideoStart
|
||||
{
|
||||
if(running &&
|
||||
[readerDelegate respondsToSelector: @selector(readerViewDidStart:)])
|
||||
[readerDelegate readerViewDidStart: self];
|
||||
}
|
||||
|
||||
- (void) onVideoStop
|
||||
{
|
||||
if(!running &&
|
||||
[readerDelegate respondsToSelector:
|
||||
@selector(readerView:didStopWithError:)])
|
||||
[readerDelegate readerView: self
|
||||
didStopWithError: nil];
|
||||
}
|
||||
|
||||
@end
|
||||
197
iphone/ZBarSymbol.m
Normal file
197
iphone/ZBarSymbol.m
Normal file
@ -0,0 +1,197 @@
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright 2009-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
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
#import <ZBarSDK/ZBarSymbol.h>
|
||||
|
||||
@implementation ZBarSymbol
|
||||
|
||||
@dynamic type, typeName, configMask, modifierMask, data, quality, count,
|
||||
zbarSymbol;
|
||||
|
||||
+ (NSString*) nameForType: (zbar_symbol_type_t) type
|
||||
{
|
||||
return([NSString stringWithUTF8String: zbar_get_symbol_name(type)]);
|
||||
}
|
||||
|
||||
- (id) initWithSymbol: (const zbar_symbol_t*) sym
|
||||
{
|
||||
if(self = [super init]) {
|
||||
symbol = sym;
|
||||
zbar_symbol_ref(sym, 1);
|
||||
}
|
||||
return(self);
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
if(symbol) {
|
||||
zbar_symbol_ref(symbol, -1);
|
||||
symbol = NULL;
|
||||
}
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (zbar_symbol_type_t) type
|
||||
{
|
||||
return(zbar_symbol_get_type(symbol));
|
||||
}
|
||||
|
||||
- (NSString*) typeName
|
||||
{
|
||||
return([[self class] nameForType: zbar_symbol_get_type(symbol)]);
|
||||
}
|
||||
|
||||
- (NSUInteger) configMask
|
||||
{
|
||||
return(zbar_symbol_get_configs(symbol));
|
||||
}
|
||||
|
||||
- (NSUInteger) modifierMask
|
||||
{
|
||||
return(zbar_symbol_get_modifiers(symbol));
|
||||
}
|
||||
|
||||
- (NSString*) data
|
||||
{
|
||||
return([NSString stringWithUTF8String: zbar_symbol_get_data(symbol)]);
|
||||
}
|
||||
|
||||
- (int) quality
|
||||
{
|
||||
return(zbar_symbol_get_quality(symbol));
|
||||
}
|
||||
|
||||
- (int) count
|
||||
{
|
||||
return(zbar_symbol_get_count(symbol));
|
||||
}
|
||||
|
||||
- (zbar_orientation_t) orientation
|
||||
{
|
||||
return(zbar_symbol_get_orientation(symbol));
|
||||
}
|
||||
|
||||
- (const zbar_symbol_t*) zbarSymbol
|
||||
{
|
||||
return(symbol);
|
||||
}
|
||||
|
||||
- (ZBarSymbolSet*) components
|
||||
{
|
||||
return([[[ZBarSymbolSet alloc]
|
||||
initWithSymbolSet: zbar_symbol_get_components(symbol)]
|
||||
autorelease]);
|
||||
}
|
||||
|
||||
- (CGRect) bounds
|
||||
{
|
||||
int n = zbar_symbol_get_loc_size(symbol);
|
||||
if(!n)
|
||||
return(CGRectNull);
|
||||
|
||||
int xmin = INT_MAX, xmax = INT_MIN;
|
||||
int ymin = INT_MAX, ymax = INT_MIN;
|
||||
|
||||
for(int i = 0; i < n; i++) {
|
||||
int t = zbar_symbol_get_loc_x(symbol, i);
|
||||
if(xmin > t) xmin = t;
|
||||
if(xmax < t) xmax = t;
|
||||
t = zbar_symbol_get_loc_y(symbol, i);
|
||||
if(ymin > t) ymin = t;
|
||||
if(ymax < t) ymax = t;
|
||||
}
|
||||
return(CGRectMake(xmin, ymin, xmax - xmin, ymax - ymin));
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation ZBarSymbolSet
|
||||
|
||||
@dynamic count, zbarSymbolSet;
|
||||
@synthesize filterSymbols;
|
||||
|
||||
- (id) initWithSymbolSet: (const zbar_symbol_set_t*) s
|
||||
{
|
||||
if(!s) {
|
||||
[self release];
|
||||
return(nil);
|
||||
}
|
||||
if(self = [super init]) {
|
||||
set = s;
|
||||
zbar_symbol_set_ref(s, 1);
|
||||
filterSymbols = YES;
|
||||
}
|
||||
return(self);
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
if(set) {
|
||||
zbar_symbol_set_ref(set, -1);
|
||||
set = NULL;
|
||||
}
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (int) count
|
||||
{
|
||||
if(filterSymbols)
|
||||
return(zbar_symbol_set_get_size(set));
|
||||
|
||||
int n = 0;
|
||||
const zbar_symbol_t *sym = zbar_symbol_set_first_unfiltered(set);
|
||||
for(; sym; sym = zbar_symbol_next(sym))
|
||||
n++;
|
||||
return(n);
|
||||
}
|
||||
|
||||
- (const zbar_symbol_set_t*) zbarSymbolSet
|
||||
{
|
||||
return(set);
|
||||
}
|
||||
|
||||
- (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState*) state
|
||||
objects: (id*) stackbuf
|
||||
count: (NSUInteger) len
|
||||
{
|
||||
const zbar_symbol_t *sym = (void*)state->state; // FIXME
|
||||
if(sym)
|
||||
sym = zbar_symbol_next(sym);
|
||||
else if(set && filterSymbols)
|
||||
sym = zbar_symbol_set_first_symbol(set);
|
||||
else if(set)
|
||||
sym = zbar_symbol_set_first_unfiltered(set);
|
||||
|
||||
if(sym)
|
||||
*stackbuf = [[[ZBarSymbol alloc]
|
||||
initWithSymbol: sym]
|
||||
autorelease];
|
||||
|
||||
state->state = (unsigned long)sym; // FIXME
|
||||
state->itemsPtr = stackbuf;
|
||||
state->mutationsPtr = (void*)self;
|
||||
return((sym) ? 1 : 0);
|
||||
}
|
||||
|
||||
@end
|
||||
23
iphone/bin/BuildUniversal.sh
Normal file
23
iphone/bin/BuildUniversal.sh
Normal file
@ -0,0 +1,23 @@
|
||||
#!/bin/sh
|
||||
set -ux
|
||||
SUBTARGET=${1:?}
|
||||
OUTDIR=${2:-$TARGET_BUILD_DIR}
|
||||
|
||||
# build library for device and simulator
|
||||
xcodebuild -target $SUBTARGET -configuration $CONFIGURATION -sdk iphoneos BUILD_DIR=$BUILD_DIR BUILD_ROOT=$BUILD_ROOT\
|
||||
|| exit 1
|
||||
xcodebuild -target $SUBTARGET -configuration $CONFIGURATION -sdk iphonesimulator BUILD_DIR=$BUILD_DIR BUILD_ROOT=$BUILD_ROOT\
|
||||
|| exit 1
|
||||
|
||||
mkdir -p $OUTDIR
|
||||
|
||||
# combine device and simulator libs into single fat lib.
|
||||
# others have indicated that this approach is "wrong", but for us
|
||||
# the ease of including the universal lib in a project without complicated
|
||||
# changes to build settings outweighs any lack of purity in the approach
|
||||
# ...we can always fix things later, if necessary
|
||||
lipo -create \
|
||||
$BUILD_ROOT/$CONFIGURATION-iphoneos/$SUBTARGET.a \
|
||||
$BUILD_ROOT/$CONFIGURATION-iphonesimulator/$SUBTARGET.a \
|
||||
-output $OUTDIR/$SUBTARGET.a \
|
||||
|| exit 1
|
||||
44
iphone/bin/CreateDMG.sh
Normal file
44
iphone/bin/CreateDMG.sh
Normal file
@ -0,0 +1,44 @@
|
||||
#!/bin/sh
|
||||
set -ux
|
||||
VOLNAME=${1:?}
|
||||
shift
|
||||
RES=$SOURCE_ROOT/res
|
||||
BUDDY=/usr/libexec/PlistBuddy
|
||||
if [ ! -x "$BUDDY" ]; then
|
||||
BUDDY=$(xcrun -find PlistBuddy) \
|
||||
|| exit 1
|
||||
fi
|
||||
VERSION=$($BUDDY -c 'Print :CFBundleVersion' $RES/$VOLNAME-Info.plist) \
|
||||
|| exit 1
|
||||
DMG=$VOLNAME-$VERSION
|
||||
|
||||
mkdir -p $TARGET_BUILD_DIR/.background \
|
||||
|| exit 1
|
||||
cp -af $RES/$VOLNAME.DS_Store $TARGET_BUILD_DIR/.DS_Store
|
||||
cp -af $RES/$VOLNAME-bg.png $TARGET_BUILD_DIR/.background/
|
||||
|
||||
# copy remaining arguments to image directly
|
||||
for content
|
||||
do
|
||||
cp -af $content $TARGET_BUILD_DIR/ \
|
||||
|| exit 1
|
||||
done
|
||||
|
||||
# prepare examples for distribution
|
||||
for example in $(find $TARGET_BUILD_DIR/Examples -depth 1 -not -name '.*')
|
||||
do
|
||||
rm -rf $example/{build,*.xcodeproj/{*.{mode1v3,pbxuser},project.xcworkspace,xcuserdata},ZBarSDK}
|
||||
cp -af $BUILT_PRODUCTS_DIR/ZBarSDK $example/
|
||||
done
|
||||
|
||||
# override subdir .DS_Stores
|
||||
for dir in $(find $TARGET_BUILD_DIR -type d -depth 1)
|
||||
do
|
||||
cp -af $RES/Columns.DS_Store $dir/.DS_Store
|
||||
done
|
||||
|
||||
hdiutil create -ov -fs HFS+ -format UDZO -imagekey zlib-level=9 \
|
||||
-volname $VOLNAME \
|
||||
-srcdir $TARGET_BUILD_DIR \
|
||||
$BUILT_PRODUCTS_DIR/$DMG.dmg \
|
||||
|| exit 1
|
||||
72
iphone/bin/CreateDSStore.pl
Normal file
72
iphone/bin/CreateDSStore.pl
Normal file
@ -0,0 +1,72 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# Quick hack script to generate the .DS_Store for the DMG, which
|
||||
# * allows us to precisely position the window and icons
|
||||
# * is more usefully versioned
|
||||
# * avoids references to my local HD(!?)
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
BEGIN {
|
||||
use File::Spec::Functions qw(rel2abs splitpath);
|
||||
use lib (splitpath(rel2abs($0)))[1];
|
||||
}
|
||||
|
||||
use Data::Plist::BinaryWriter;
|
||||
use Mac::Finder::DSStore qw(writeDSDBEntries makeEntries);
|
||||
use Mac::Finder::AliasRecord;
|
||||
|
||||
$Mac::Finder::DSStore::Entry::types{bwsp} = 'blob';
|
||||
$Mac::Finder::DSStore::Entry::types{icvp} = 'blob';
|
||||
|
||||
writeDSDBEntries($ARGV[0] || "DS_Store",
|
||||
makeEntries(".",
|
||||
bwsp => Data::Plist::BinaryWriter->new(serialize => 0)->write([
|
||||
dict => {
|
||||
WindowBounds => [
|
||||
string => sprintf('{{%d, %d}, {%d, %d}}',
|
||||
512, 128, 512, 608 + 22)
|
||||
],
|
||||
SidebarWidth => [integer => 0],
|
||||
ShowToolbar => [false => 0],
|
||||
ShowSidebar => [false => 0],
|
||||
ShowPathbar => [false => 0],
|
||||
ShowStatusBar => [false => 0],
|
||||
}
|
||||
]),
|
||||
icvp => Data::Plist::BinaryWriter->new(serialize => 0)->write([
|
||||
dict => {
|
||||
viewOptionsVersion => [integer => 0],
|
||||
arrangeBy => [string => "none"],
|
||||
iconSize => [real => 64],
|
||||
textSize => [real => 12],
|
||||
labelOnBottom => [true => 1],
|
||||
gridSpacing => [real => 100],
|
||||
gridOffsetX => [real => 0],
|
||||
gridOffsetY => [real => 0],
|
||||
showItemInfo => [false => 0],
|
||||
showIconPreview => [false => 0],
|
||||
backgroundType => [integer => 2],
|
||||
backgroundColorRed => [real => 0],
|
||||
backgroundColorGreen => [real => 0],
|
||||
backgroundColorBlue => [real => .5],
|
||||
backgroundImageAlias => [
|
||||
data => Mac::Finder::AliasRecord->new(
|
||||
path => 'ZBarSDK:.background:ZBarSDK-bg.png',
|
||||
volumeFS => 'HFS+')->write()
|
||||
],
|
||||
},
|
||||
]),
|
||||
vstl => "icnv",
|
||||
),
|
||||
makeEntries("README", Iloc_xy => [ 4.5 * 32, 2.5 * 32 ]),
|
||||
makeEntries("ZBarSDK", Iloc_xy => [ 4.5 * 32, 7.5 * 32 ]),
|
||||
makeEntries("ChangeLog", Iloc_xy => [ 4 * 32, 12.5 * 32 ]),
|
||||
makeEntries("Documentation.html",
|
||||
Iloc_xy => [ 8 * 32, 12.5 * 32 ]),
|
||||
makeEntries("Examples", Iloc_xy => [ 12 * 32, 12.5 * 32 ]),
|
||||
makeEntries("COPYING", Iloc_xy => [ 4 * 32, 16 * 32 ]),
|
||||
makeEntries("LICENSE", Iloc_xy => [ 8 * 32, 16 * 32 ]),
|
||||
makeEntries("Documentation",Iloc_xy => [ 12 * 32, 16 * 32 ]),
|
||||
);
|
||||
169
iphone/bin/Mac/Finder/AliasRecord.pm
Normal file
169
iphone/bin/Mac/Finder/AliasRecord.pm
Normal file
@ -0,0 +1,169 @@
|
||||
package Mac::Finder::AliasRecord;
|
||||
|
||||
# Generate(/Parse) a Mac "alias record" binary string/file.
|
||||
#
|
||||
# Currently just enough is implemented to satisfy immediate requirements
|
||||
# (ie, write backgroundImageAlias to .DS_Store for DMG)
|
||||
#
|
||||
# based on these documents:
|
||||
# http://www.geocities.com/xhelmboyx/quicktime/formats/alias-layout.txt
|
||||
# http://sebastien.kirche.free.fr/python_stuff/MacOS-aliases.txt
|
||||
#
|
||||
# FIXME interface is very poor...
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
use DateTime;
|
||||
use File::Spec;
|
||||
use File::Spec::Mac;
|
||||
use Encode qw(encode);
|
||||
require Exporter;
|
||||
|
||||
our $VERSION = '0.1';
|
||||
our @ISA = qw(Exporter);
|
||||
|
||||
my %FSEncodings = (
|
||||
MacFS => ['RW', ''],
|
||||
MFS => ['RW', ''],
|
||||
HFS => ['BD', ''],
|
||||
'HFS+' => ['H+', ''],
|
||||
|
||||
AudioCD => ['', 'JH'],
|
||||
ISO9660 => ['', 'AG'],
|
||||
FAT => ['', 'IS'],
|
||||
Joliet => ['', 'Jo'],
|
||||
'ISO9660+Joliet' => ['', 'Jo'],
|
||||
);
|
||||
|
||||
my %DiskEncodings = (
|
||||
HD => 0,
|
||||
FixedHD => 0,
|
||||
Network => 1,
|
||||
NetworkDisk => 1,
|
||||
Floppy => 4,
|
||||
Floppy1440 => 4,
|
||||
Other => 5,
|
||||
OtherDisk => 5,
|
||||
);
|
||||
|
||||
my %RecordEncodings = (
|
||||
parentDir => 0x00,
|
||||
absolutePath => 0x02,
|
||||
unicodeFile => 0x0e,
|
||||
unicodeVolume => 0x0f,
|
||||
volumePath => 0x12,
|
||||
);
|
||||
|
||||
sub new {
|
||||
my $class = shift || __PACKAGE__;
|
||||
my $self = {
|
||||
aliasCreator => '',
|
||||
aliasVersion => 2,
|
||||
aliasType => 'file',
|
||||
volume => '',
|
||||
volumeCreated => 0,
|
||||
volumeFS => 'HFS',
|
||||
volumeDisk => undef,
|
||||
volumeAttrs => 0,
|
||||
directoryID => 0,
|
||||
file => '',
|
||||
fileID => 0,
|
||||
fileCreated => 0,
|
||||
fileType => '',
|
||||
fileCreator => '',
|
||||
nlvlFrom => -1,
|
||||
nlvlTo => -1,
|
||||
records => { },
|
||||
@_
|
||||
};
|
||||
if(exists($self->{path})) {
|
||||
my $path = $self->{path};
|
||||
my ($vol, $dir, $file) = File::Spec::Mac->splitpath($path);
|
||||
$vol =~ s/:$//;
|
||||
my @dir = File::Spec::Mac->splitdir($dir);
|
||||
while(@dir && !$dir[0]) {
|
||||
shift(@dir);
|
||||
}
|
||||
while(@dir && !$dir[-1]) {
|
||||
pop(@dir);
|
||||
}
|
||||
$self->{volume} ||= $vol;
|
||||
$self->{records}{unicodeVolume} ||=
|
||||
pack('na*', length($vol), encode('utf-16be', $vol));
|
||||
|
||||
$self->{file} ||= $file;
|
||||
$self->{records}{parentDir} ||= $dir[-1]
|
||||
if(@dir);
|
||||
$self->{records}{absolutePath} ||= $path;
|
||||
$self->{records}{volumePath} ||= File::Spec->catfile('', @dir, $file);
|
||||
$self->{records}{unicodeFile} ||=
|
||||
pack('na*', length($file), encode('utf-16be', $file));
|
||||
}
|
||||
return(bless($self, ref($class) || $class));
|
||||
}
|
||||
|
||||
sub toFSTime {
|
||||
my $val = shift;
|
||||
if(ref($val) && $val->isa("DateTime")) {
|
||||
$val = $val->epoch - DateTime->new(year => 1904)->epoch();
|
||||
}
|
||||
return($val);
|
||||
}
|
||||
|
||||
sub write {
|
||||
my ($self, $out) = @_;
|
||||
|
||||
my $aliasType = $self->{aliasType};
|
||||
$aliasType = (($aliasType =~ /^d(ir(ectory)?)?$/i && 1) ||
|
||||
($aliasType !~ /^f(ile)?$/ && $aliasType) || 0);
|
||||
|
||||
my $volumeCreated = toFSTime($self->{volumeCreated});
|
||||
my $volumeFS = $self->{volumeFS};
|
||||
if(ref($volumeFS) ne 'ARRAY') {
|
||||
$volumeFS = $FSEncodings{$volumeFS} || ['', ''];
|
||||
}
|
||||
|
||||
my $volumeDisk = $self->{volumeDisk};
|
||||
if(!defined($volumeDisk)) {
|
||||
if($volumeFS->[0] eq 'H+') {
|
||||
$volumeDisk = 'Floppy';
|
||||
}
|
||||
elsif($volumeFS->[0]) {
|
||||
$volumeDisk = 'HD';
|
||||
}
|
||||
else {
|
||||
$volumeDisk = 'Other';
|
||||
}
|
||||
}
|
||||
$volumeDisk = (exists($DiskEncodings{$volumeDisk})
|
||||
? $DiskEncodings{$volumeDisk}
|
||||
: $volumeDisk);
|
||||
|
||||
my $fileCreated = toFSTime($self->{fileCreated});
|
||||
|
||||
my $buf =
|
||||
pack('nn (C/a @28)Na2n N(C/a @64)NNa4a4 n!n!Na2 x10 (n!n/ax!2)*',
|
||||
$self->{aliasVersion}, $aliasType,
|
||||
$self->{volume}, $volumeCreated, $volumeFS->[0], $volumeDisk,
|
||||
$self->{directoryID}, $self->{file}, $self->{fileID}, $fileCreated,
|
||||
$self->{fileType}, $self->{fileCreator}, $self->{nlvlFrom},
|
||||
$self->{nlvlTo}, $self->{volumeAttrs}, $volumeFS->[1],
|
||||
map(((exists($RecordEncodings{$_}) ? $RecordEncodings{$_} : $_)
|
||||
=> $self->{records}{$_}),
|
||||
keys(%{$self->{records}})),
|
||||
(-1, ''));
|
||||
$buf = pack('a4n', $self->{aliasCreator}, length($buf) + 6) . $buf;
|
||||
|
||||
if(!$out) {
|
||||
return($buf);
|
||||
}
|
||||
elsif(ref($out) eq 'GLOB') {
|
||||
print $out $buf;
|
||||
}
|
||||
else {
|
||||
open(my $outfh, '>', $out) || die;
|
||||
print $outfh $buf;
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
53
iphone/debug.h
Normal file
53
iphone/debug.h
Normal file
@ -0,0 +1,53 @@
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright 2009 (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 <mach/mach_time.h>
|
||||
#define xNSSTR(s) @#s
|
||||
#define NSSTR(s) xNSSTR(s)
|
||||
|
||||
#ifdef DEBUG_OBJC
|
||||
# ifndef MODULE
|
||||
# define MODULE ZBarReaderController
|
||||
# endif
|
||||
# define zlog(fmt, ...) \
|
||||
NSLog(NSSTR(MODULE) @": " fmt , ##__VA_ARGS__)
|
||||
|
||||
#define timer_start \
|
||||
uint64_t t_start = timer_now();
|
||||
|
||||
#else
|
||||
# define zlog(...) while(0)
|
||||
# define timer_start
|
||||
#endif
|
||||
|
||||
static inline uint64_t timer_now ()
|
||||
{
|
||||
return(mach_absolute_time());
|
||||
}
|
||||
|
||||
static inline double timer_elapsed (uint64_t start, uint64_t end)
|
||||
{
|
||||
mach_timebase_info_data_t info;
|
||||
mach_timebase_info(&info);
|
||||
return((double)(end - start) * info.numer / (info.denom * 1000000000.));
|
||||
}
|
||||
11
iphone/doc/Documentation.html
Normal file
11
iphone/doc/Documentation.html
Normal file
@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<meta http-equiv="Refresh" content="0; url=Documentation/index.html"/>
|
||||
</head>
|
||||
<body>
|
||||
<p>redirecting to <a href="Documentation/index.html">Documentation/index.html</a></p>
|
||||
</body>
|
||||
</html>
|
||||
150
iphone/doc/ZBarImage.rst
Normal file
150
iphone/doc/ZBarImage.rst
Normal file
@ -0,0 +1,150 @@
|
||||
ZBarImage Class Reference
|
||||
=========================
|
||||
|
||||
.. class:: ZBarImage
|
||||
|
||||
:Inherits from: :class:`NSObject`
|
||||
|
||||
A :class:`ZBarImage` is a wrapper for images passed to the barcode reader.
|
||||
It encapsulates raw image data with the format and size metadata necessary
|
||||
to interpret it.
|
||||
|
||||
An image must be wrapped in a :class:`ZBarImage` in order to be scanned by
|
||||
the library. At least the format, size and data must be set. There are
|
||||
also initialization methods for automatically extracting the data and
|
||||
format from a `CGImage`.
|
||||
|
||||
This class is a wrapper around a :type:`zbar_image_t` C object (q.v.)
|
||||
|
||||
|
||||
Properties
|
||||
----------
|
||||
|
||||
.. member:: unsigned long format
|
||||
|
||||
The image format four-charcter code (fourcc) as a 4-byte integer. Use
|
||||
:ref:`fourcc:<fourcc:>` to create a fourcc value from a string.
|
||||
|
||||
.. member:: unsigned sequence
|
||||
|
||||
A "sequence number" associated with the image. This reference value is
|
||||
unused by the library.
|
||||
|
||||
.. member:: CGSize size
|
||||
|
||||
The size of the image in pixels.
|
||||
|
||||
.. note::
|
||||
|
||||
There is no separate "bytesPerLine" property, the width must match
|
||||
the image data (which is not always the logical image width).
|
||||
|
||||
.. member:: CGRect crop
|
||||
|
||||
Optionally limit the scan region to this rectangle without having to
|
||||
generate a cropped image.
|
||||
|
||||
.. member:: const void *data
|
||||
|
||||
Obtain a pointer to the raw image data. This property is read-only, use
|
||||
:ref:`setData:withLength:<setData:withLength:>` to set the image data.
|
||||
|
||||
.. member:: unsigned long dataLength
|
||||
|
||||
Byte length of the raw image data. This property is read-only, use
|
||||
:ref:`setData:withLength:<setData:withLength:>` to set the image data.
|
||||
|
||||
.. member:: ZBarSymbolSet *symbols
|
||||
|
||||
Barcode results from the last scan.
|
||||
|
||||
.. member:: zbar_image_t *zbarImage
|
||||
|
||||
Retrieve the underlying C object instance. (read-only)
|
||||
|
||||
.. member:: UIImage *UIImage
|
||||
|
||||
Convert the image to a UIImage. Only certain image formats are
|
||||
supported for conversion (read-only)
|
||||
|
||||
:See also: :ref:`UIImageWithOrientation:<UIImageWithOrientation:>`
|
||||
|
||||
|
||||
Class Methods
|
||||
-------------
|
||||
|
||||
.. _`fourcc:`:
|
||||
.. describe:: + (unsigned long) fourcc:(NSString*)format
|
||||
|
||||
Parse the integer four-character code from a string. Alternatively use
|
||||
the :func:`zbar_fourcc` macro to create a constant expression.
|
||||
|
||||
:format: A four character string representing an image format.
|
||||
:Returns: The corresponding 4-byte integer format code.
|
||||
|
||||
|
||||
Instance Methods
|
||||
----------------
|
||||
|
||||
.. _`initWithImage:`:
|
||||
.. describe:: - (id) initWithImage:(zbar_image_t*)image
|
||||
|
||||
Initialize an image wrapper, given the C object to wrap.
|
||||
|
||||
:image: The C object to wrap.
|
||||
:Returns: The initialized :class:`ZBarImage`.
|
||||
|
||||
.. _`initWithCGImage:`:
|
||||
.. describe:: - (id) initWithCGImage:(CGImageRef)image
|
||||
|
||||
Initialize a :class:`ZBarImage` from the data and metadata extracted
|
||||
from a `CGImage`. The image is converted to `Y800` (grayscale) format.
|
||||
|
||||
:image: A `CGImage` to source the data and metadata.
|
||||
:Returns: The initialized :class:`ZBarImage`.
|
||||
:See also: :ref:`initWithCGImage:size:<initWithCGImage:size:>`
|
||||
|
||||
.. _`initWithCGImage:size:`:
|
||||
.. describe:: - (id) initWithCGImage:(CGImageRef)image size:(CGSize)size
|
||||
|
||||
Initialize a :class:`ZBarImage` from the data and metadata extracted
|
||||
from a `CGImage`. The image is converted to `Y800` (grayscale) format
|
||||
and scaled to the specified size.
|
||||
|
||||
:image: A `CGImage` to source the data and metadata.
|
||||
:size: The pixel size of the resulting ZBarImage.
|
||||
:Returns: The initialized :class:`ZBarImage`.
|
||||
:See also: :ref:`initWithCGImage:crop:size:<initWithCGImage:crop:size:>`
|
||||
|
||||
.. _`initWithCGImage:crop:size:`:
|
||||
.. describe:: - (id) initWithCGImage:(CGImageRef)image crop:(CGRect)crop size:(CGSize)size
|
||||
|
||||
Initialize a :class:`ZBarImage` from the data and metadata extracted
|
||||
from a `CGImage`. The image is simultaneously converted to `Y800`
|
||||
(grayscale) format, cropped and scaled to the specified size.
|
||||
|
||||
:image: A `CGImage` to source the data and metadata.
|
||||
:crop: The region to convert, in image coordinates.
|
||||
:size: The pixel size of the resulting ZBarImage.
|
||||
:Returns: The initialized :class:`ZBarImage`.
|
||||
|
||||
.. _`setData:withLength:`:
|
||||
.. describe:: - (void) setData:(const void*)data withLength:(unsigned long)length
|
||||
|
||||
Specify a pointer to the raw image data, for the image format and size.
|
||||
The length of the data must also be provided. Note that the data must
|
||||
remain valid as long as the image has a reference to it. Set data to
|
||||
``NULL`` to clear a previous reference.
|
||||
|
||||
:data: A pointer to a raw image data buffer.
|
||||
:length: The size of the image data buffer.
|
||||
|
||||
.. _`UIImageWithOrientation:`:
|
||||
.. describe:: - (UIImage*) UIImageWithOrientation:(UIImageOrientation)orient
|
||||
|
||||
Convert the image to a UIImage with the specified orientation. Only
|
||||
certain image formats are supported for conversion. (currently
|
||||
``RGB3``, ``RGB4``, ``RGBQ``)
|
||||
|
||||
:orient: Desired orientation of the image.
|
||||
:Returns: A new :class:`UIImage`, or ``nil`` in case of error.
|
||||
99
iphone/doc/ZBarImageScanner.rst
Normal file
99
iphone/doc/ZBarImageScanner.rst
Normal file
@ -0,0 +1,99 @@
|
||||
ZBarImageScanner Class Reference
|
||||
================================
|
||||
|
||||
.. class:: ZBarImageScanner
|
||||
|
||||
:Inherits from: :class:`NSObject`
|
||||
|
||||
This is a low-level interface for programmatically scanning images without
|
||||
a user interface. If you want to scan images manually selected by the user
|
||||
(from the photo library or using the camera), you may prefer to use a
|
||||
:class:`ZBarReaderController` instead.
|
||||
|
||||
This class is a wrapper around a :type:`zbar_image_scanner_t` C object
|
||||
(q.v.)
|
||||
|
||||
|
||||
Properties
|
||||
----------
|
||||
|
||||
.. member:: BOOL enableCache
|
||||
|
||||
Enable the inter-frame consistency cache. Set to ``YES`` for scanning
|
||||
video or ``NO`` for scanning images.
|
||||
|
||||
.. member:: ZBarSymbolSet results
|
||||
|
||||
Decoded symbols resulting from the last scan.
|
||||
|
||||
|
||||
Instance Methods
|
||||
----------------
|
||||
|
||||
.. _`parseConfig:`:
|
||||
.. describe:: - (void) parseConfig:(NSString*)config
|
||||
|
||||
Apply scanner/decoder configuration parsed from a string.
|
||||
|
||||
:config: A configuration setting of the form: `symbology.config[=value]`.
|
||||
|
||||
.. _`setSymbology:config:to:`:
|
||||
.. describe:: - (void) setSymbology:(zbar_symbol_type_t)symbology config:(zbar_config_t)config to:(int)value
|
||||
|
||||
Apply generic scanner/decoder configuration.
|
||||
|
||||
:symbology: The symbology to effect, or 0 for all.
|
||||
:config: The configuration setting to adjust.
|
||||
:value: The value to set for the specific configuration/symbology.
|
||||
|
||||
.. _`scanImage:`:
|
||||
.. describe:: - (NSInteger) scanImage:(ZBarImage*)image
|
||||
|
||||
Scan an image for barcodes using the current configuration. The image
|
||||
must be in ``Y800`` format (8-bpp graysale).
|
||||
|
||||
:image: The :class:`ZBarImage` to scan.
|
||||
:Returns: The number of barcode symbols decoded in the image.
|
||||
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. type:: zbar_config_t
|
||||
|
||||
ZBAR_CFG_ENABLE
|
||||
Control whether specific symbologies will be recognized. Disabling
|
||||
unused symbologies improves performance and prevents bad scans.
|
||||
|
||||
ZBAR_CFG_EMIT_CHECK
|
||||
Whether to include the check digit in the result data string. This
|
||||
value may be set individually for symbologies where it makes sense.
|
||||
|
||||
ZBAR_CFG_MIN_LEN
|
||||
The minimum data length for a symbol to be valid, set to 0 to disable.
|
||||
Use with eg, I2/5 to avoid short scans. This value may be set
|
||||
individually for variable-length symbologies.
|
||||
|
||||
ZBAR_CFG_MAX_LEN
|
||||
The maximum data length for which a symbol is valid, set to 0 to
|
||||
disable. Use with eg, I2/5 to enforce a specific range of data lengths.
|
||||
This value may be set individually for variable-length symbologies.
|
||||
|
||||
ZBAR_CFG_UNCERTAINTY
|
||||
Number of "nearby" frames that must contain a symbol before it will be
|
||||
considered valid. This value may be set for individual symbologies.
|
||||
|
||||
ZBAR_CFG_POSITION
|
||||
Whether to track position information.
|
||||
|
||||
ZBAR_CFG_X_DENSITY
|
||||
The stride to use for scanning vertical columns of the image. This many
|
||||
pixel columns will be skipped between vertical scan passes. Useful for
|
||||
trading off between resolution and performance. This is a scanner
|
||||
setting (use 0 for the symbology).
|
||||
|
||||
ZBAR_CFG_Y_DENSITY
|
||||
The stride to use for scanning horizontal columns of the image. This
|
||||
many pixel rows will be skipped between horizontal scan passes. Useful
|
||||
for trading off between resolution and performance. This is a scanner
|
||||
setting (use 0 for the symbology).
|
||||
156
iphone/doc/ZBarReaderController.rst
Normal file
156
iphone/doc/ZBarReaderController.rst
Normal file
@ -0,0 +1,156 @@
|
||||
ZBarReaderController Class Reference
|
||||
====================================
|
||||
|
||||
.. class:: ZBarReaderController
|
||||
|
||||
:Inherits from: :class:`UIImagePickerController`
|
||||
|
||||
This is the controller to use for scanning images selected by a
|
||||
:class:`UIImagePickerController` either captured manually using the camera,
|
||||
or selected from the Photo Library. For more information, see
|
||||
:doc:`picker`.
|
||||
|
||||
It can support automatic capture from the camera only if the library is
|
||||
re-built to use private APIs (see :doc:`compat`).
|
||||
|
||||
|
||||
Properties
|
||||
----------
|
||||
|
||||
.. member:: ZBarImageScanner *scanner
|
||||
|
||||
Access to the image scanner for configuration. (read-only)
|
||||
|
||||
.. member:: id<ZBarReaderDelegate> readerDelegate
|
||||
|
||||
The delegate that will be notified when new barcode results are
|
||||
available.
|
||||
|
||||
.. member:: BOOL showsZBarControls
|
||||
|
||||
Whether to display a default control set consisting of cancel, scan and
|
||||
info buttons. Disable these if you provide your own controls using the
|
||||
:member:`cameraOverlayView`. Enabling this automatically disables the
|
||||
system controls :member:`showsCameraControls`. (Default ``YES``).
|
||||
|
||||
.. member:: BOOL showsHelpOnFail
|
||||
|
||||
Whether to automatically display the integrated help viewer when an
|
||||
image fails to decode. Even if this is disabled, the integrated help
|
||||
may still be presented manually using ``showHelpWithReason:``.
|
||||
(Default ``YES``)
|
||||
|
||||
.. member:: ZBarReaderControllerCameraMode cameraMode
|
||||
|
||||
Scanning mode to use with the camera. It is generally appropriate to
|
||||
leave this at the default.
|
||||
|
||||
.. member:: BOOL tracksSymbols
|
||||
|
||||
Whether to display the tracking rectangle around detected barcodes.
|
||||
|
||||
.. member:: BOOL takesPicture
|
||||
|
||||
Whether to take a full picture (with ``takePicture``) when a barcode
|
||||
is detected with ``ZBarReaderControllerCameraModeSampling``. The
|
||||
resulting image will be delayed from the actual decode.
|
||||
|
||||
.. member:: BOOL enableCache
|
||||
|
||||
This property is deprecated and should not be modified.
|
||||
|
||||
.. member:: CGRect scanCrop
|
||||
|
||||
Crop images before scanning. The original image will be cropped to this
|
||||
rectangle, which should be in normalized image coordinates, x-axis
|
||||
major. Defaults to the full image ``{{0, 0}, {1, 1}}``.
|
||||
|
||||
.. member:: NSInteger maxScanDimension
|
||||
|
||||
Scale image to scan. After cropping, the image will be scaled if
|
||||
necessary, such that neither of its dimensions exceed this value.
|
||||
Defaults to 640.
|
||||
|
||||
.. note::
|
||||
|
||||
The remaining properties are inherited from
|
||||
:class:`UIImagePickerController`.
|
||||
|
||||
.. member:: UIImagePickerControllerSourceType sourceType
|
||||
|
||||
Image source. Use to select between the camera and photo library.
|
||||
|
||||
.. member:: BOOL showsCameraControls
|
||||
|
||||
Whether to display the system camera controls. Overridden to ``NO``
|
||||
when :member:`showsZBarControls` is ``YES``.
|
||||
|
||||
.. member:: UIView *cameraOverlayView
|
||||
|
||||
A custom view to display over the camera preview. The tracking layer
|
||||
and default controls will be added to this view if they are enabled.
|
||||
|
||||
.. member:: CGAffineTransform cameraViewTransform
|
||||
|
||||
A transform to apply to the camera preview. Ignored by the reader.
|
||||
Possibly useful for eg, a digital zoom effect.
|
||||
|
||||
.. member:: BOOL allowsEditing
|
||||
|
||||
Whether to enable the system image editing dialog after a picture is
|
||||
taken. Possibly useful to improve reader results in some cases using
|
||||
manual intervention.
|
||||
|
||||
|
||||
Instance Methods
|
||||
----------------
|
||||
|
||||
.. _`showHelpWithReason:`:
|
||||
.. describe:: - (void) showHelpWithReason:(NSString*)reason
|
||||
|
||||
Display the integrated help browser. Use this with custom overlays if
|
||||
you don't also want to create your own help view. Should only be called
|
||||
when the reader is displayed. The ``reason`` argument will be passed to
|
||||
the :func:`onZBarHelp` javascript function.
|
||||
|
||||
:reason: A string parameter passed to javascript.
|
||||
|
||||
.. _`scanImage:`:
|
||||
.. describe:: - (id <NSFastEnumeration>) scanImage:(CGImageRef)image
|
||||
|
||||
Scan an image for barcodes. This is a wrapper around
|
||||
``scanner.scanImage`` that applies scanCrop and maxScanDimension. Some
|
||||
additional result filtering is also performed.
|
||||
|
||||
:image: A :class:`CGImage` to scan.
|
||||
:Returns: The result set containing :class:`ZBarSymbol` objects.
|
||||
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. type:: ZBarReaderControllerCameraMode
|
||||
|
||||
The scanning mode to use with the camera.
|
||||
|
||||
ZBarReaderControllerCameraModeDefault
|
||||
The standard mode provided by UIImagePickerController - the user
|
||||
manually captures an image by tapping a control. This is the default
|
||||
unless private APIs are enabled.
|
||||
|
||||
ZBarReaderControllerCameraModeSampling
|
||||
Automatically capture by taking screenshots with
|
||||
:func:`UIGetScreenImage`. Resolution is limited to the screen
|
||||
resolution, so this mode is inappropriate for longer codes. Only
|
||||
available when private APIs are enabled, and becomes the default mode in
|
||||
that case.
|
||||
|
||||
ZBarReaderControllerCameraModeSequence
|
||||
Experimental mode that automatically scans by "rapidly" scanning
|
||||
pictures captured with ``takePicture``. Not recommended for serious
|
||||
use.
|
||||
|
||||
.. c:var:: NSString *ZBarReaderControllerResults
|
||||
|
||||
The info dictionary key used to return decode results to
|
||||
``imagePickerController:didFinishPickingMediaWithInfo:``
|
||||
70
iphone/doc/ZBarReaderDelegate.rst
Normal file
70
iphone/doc/ZBarReaderDelegate.rst
Normal file
@ -0,0 +1,70 @@
|
||||
ZBarReaderDelegate Protocol Reference
|
||||
=====================================
|
||||
|
||||
.. class:: ZBarReaderDelegate
|
||||
|
||||
:Inherits from: :class:`UIImagePickerControllerDelegate`
|
||||
|
||||
This protocol must be implemented by the
|
||||
:member:`~ZBarReaderViewController::readerDelegate` provided to a
|
||||
:class:`ZBarReaderViewController` or :class:`ZBarReaderController`. It is
|
||||
used to notify the delegate of new decode results, when an image fails to
|
||||
decode, or when the user dismisses the reader with the built-in controls.
|
||||
|
||||
|
||||
Instance Methods
|
||||
----------------
|
||||
|
||||
.. describe:: - (void) imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info
|
||||
|
||||
This inherited delegate method is called when a barcode is successfully
|
||||
decoded. The decoded symbols are available from the dictionary as a
|
||||
:class:`ZBarSymbolSet` using the :c:data:`ZBarReaderControllerResults`
|
||||
key. The image from which the barcodes were scanned is available using
|
||||
the :c:data:`UIImagePickerControllerOriginalImage` key. No other keys
|
||||
are guaranteed to be valid.
|
||||
|
||||
.. note::
|
||||
|
||||
The ``picker`` parameter will be the reader controller instance that
|
||||
read the barcodes - not necessarily a
|
||||
:class:`UIImagePickerController` instance. You should cast it to the
|
||||
correct type for anything other than basic view controller access.
|
||||
|
||||
:picker: The reader controller that scanned the barcode(s).
|
||||
:info: A dictionary containing the image and decode results.
|
||||
|
||||
.. describe:: - (void) imagePickerControllerDidCancel:(UIImagePickerController*)picker
|
||||
|
||||
Called when the user taps the "Cancel" button provided by the built-in
|
||||
controls (when :member:`showsZBarControls`\ ``=YES``). The default
|
||||
implementation dismisses the reader. If this method is implemented, it
|
||||
should do the same.
|
||||
|
||||
.. note::
|
||||
|
||||
The ``picker`` parameter will be the reader controller instance that
|
||||
read the barcodes - not necessarily a
|
||||
:class:`UIImagePickerController` instance. You should cast it to the
|
||||
correct type for anything other than basic view controller access.
|
||||
|
||||
:picker: The reader controller that scanned the barcode(s).
|
||||
|
||||
.. describe:: - (void) readerControllerDidFailToRead:(ZBarReaderController*)reader withRetry:(BOOL)retry
|
||||
|
||||
Called when an image, manually captured or selected from the photo
|
||||
library, is scanned and no barcodes were detected.
|
||||
|
||||
If the ``retry`` parameter is ``NO``, the controller must be dismissed
|
||||
before this method returns. Otherwise, another scan may be attempted
|
||||
without re-presenting the controller.
|
||||
|
||||
If the :member:`~ZBarReaderController::showsHelpOnFail` is ``YES`` *and*
|
||||
``retry`` is ``YES``, the integrated help viewer will already be
|
||||
presenting.
|
||||
|
||||
If this method is not implemented, the controller will be dismissed iff
|
||||
``retry`` is ``NO``.
|
||||
|
||||
:reader: The :class:`ZBarReaderController` that scanned the barcode(s).
|
||||
:retry: Whether another scan may be attempted.
|
||||
126
iphone/doc/ZBarReaderView.rst
Normal file
126
iphone/doc/ZBarReaderView.rst
Normal file
@ -0,0 +1,126 @@
|
||||
ZBarReaderView Class Reference
|
||||
==============================
|
||||
|
||||
.. class:: ZBarReaderView
|
||||
|
||||
:Inherits from: :class:`UIView`
|
||||
|
||||
This is a barcode reader encapsulted in a UIView. It manages an
|
||||
:class:`AVCaptureSession` with a camera device and a
|
||||
:class:`ZBarCaptureReader`, presents the video preview and optionally
|
||||
tracks detected barcode symbols. A delegate will usually be assigned for
|
||||
notification of new decode results.
|
||||
|
||||
|
||||
Properties
|
||||
----------
|
||||
|
||||
.. member:: id<ZBarReaderViewDelegate> readerDelegate
|
||||
|
||||
The delegate that will be notified of new decode results.
|
||||
|
||||
.. member:: ZBarImageScanner *scanner
|
||||
|
||||
Access to the image scanner is provided for configuration. (read-only)
|
||||
|
||||
.. member:: BOOL tracksSymbols
|
||||
|
||||
Whether to display the tracking annotation (default ``YES``).
|
||||
|
||||
.. member:: UIColor *trackingColor
|
||||
|
||||
The color of the tracking annotation (default green).
|
||||
|
||||
.. member:: BOOL allowsPinchZoom
|
||||
|
||||
Enable pinch gesture recognition for manually zooming the preview/decode
|
||||
(default ``YES``).
|
||||
|
||||
.. member:: NSInteger torchMode
|
||||
|
||||
An :type:`AVCaptureTorchMode` value that will be applied if/when
|
||||
appropriate. (default Auto)
|
||||
|
||||
.. member:: BOOL showsFPS
|
||||
|
||||
Overlay the decode frame rate on the preview to help with performance
|
||||
optimization. This is for *debug only* and should not be set for
|
||||
production. (default ``NO``)
|
||||
|
||||
.. member:: CGFloat zoom
|
||||
|
||||
Zoom scale factor applied to the video preview *and* scanCrop. This
|
||||
value is also updated by the pinch-zoom gesture. Valid values are in
|
||||
the range [1,maxZoom]. (default 1.25)
|
||||
|
||||
.. member:: CGFloat maxZoom
|
||||
|
||||
Maximum settable zoom level. The zoom property will be clipped to this
|
||||
value.
|
||||
|
||||
.. member:: CGRect scanCrop
|
||||
|
||||
The region of the video image that will be scanned, in normalized image
|
||||
coordinates. Note that the video image is in landscape mode (default
|
||||
{{0, 0}, {1, 1}})
|
||||
|
||||
.. member:: CGAffineTransform previewTransform
|
||||
|
||||
Additional transform that will be applied to the video preview. Note
|
||||
that this transform is *not* applied to scanCrop.
|
||||
|
||||
.. member:: AVCaptureDevice *device
|
||||
|
||||
The capture device may be manipulated or replaced.
|
||||
|
||||
.. member:: AVCaptureSession *session
|
||||
|
||||
Direct access to the capture session. Warranty void if opened.
|
||||
(read-only)
|
||||
|
||||
.. member:: ZBarCaptureReader *captureReader
|
||||
|
||||
Direct access to the capture reader. Warranty void if opened.
|
||||
(read-only)
|
||||
|
||||
.. member:: BOOL enableCache
|
||||
|
||||
:Deprecated:
|
||||
|
||||
Whether to use the inter-frame consistency cache. This should always be
|
||||
set to ``YES``.
|
||||
|
||||
|
||||
Instance Methods
|
||||
----------------
|
||||
|
||||
.. describe:: - (id) initWithImageScanner:(ZBarImageScanner*)imageScanner
|
||||
|
||||
:imageScanner: A pre-configured :class:`ZBarImageScanner` to use for scanning
|
||||
:Returns: The initialized :class:`ZBarReaderView`
|
||||
|
||||
.. describe:: - (void) start
|
||||
|
||||
Begin/resume scanning after a call to ``stop``.
|
||||
|
||||
.. describe:: - (void) stop
|
||||
|
||||
Stop scanning and pause the video feed.
|
||||
|
||||
.. describe:: - (void) flushCache
|
||||
|
||||
Flush the inter-frame consistency cache. Any barcodes in the frame will
|
||||
be re-recognized in subsequent frames.
|
||||
|
||||
.. _`setZoom:animated:`:
|
||||
.. describe:: - (void) setZoom:(CGFloat)zoom animated:(BOOL)animated
|
||||
|
||||
Set the zoom property with optional animation.
|
||||
|
||||
.. _`willRotateTointerfaceOrientation:duration:`:
|
||||
.. describe:: - (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
|
||||
|
||||
Compensate for device / camera / interface orientation. Must be called
|
||||
by containing view controller that supports any non-portrait orientation
|
||||
to restore the camera preview to the correct orientation. Call from
|
||||
view controller method of the same name for correct animation.
|
||||
190
iphone/doc/ZBarReaderViewController.rst
Normal file
190
iphone/doc/ZBarReaderViewController.rst
Normal file
@ -0,0 +1,190 @@
|
||||
ZBarReaderViewController Class Reference
|
||||
========================================
|
||||
|
||||
.. class:: ZBarReaderViewController
|
||||
|
||||
:Inherits from: :class:`UIViewController`
|
||||
|
||||
This is the controller to use for live scanning from the camera feed with
|
||||
automatic capture. For scanning from image files or with manual capture,
|
||||
see :class:`ZBarReaderController`.
|
||||
|
||||
|
||||
Properties
|
||||
----------
|
||||
|
||||
.. member:: ZBarImageScanner *scanner
|
||||
|
||||
Access to the image scanner for configuration. (read-only)
|
||||
|
||||
.. member:: id <ZBarReaderDelegate> readerDelegate
|
||||
|
||||
The delegate that will be notified when new barcode results are
|
||||
available.
|
||||
|
||||
.. member:: BOOL showsZBarControls
|
||||
|
||||
Whether to display a default control set consisting of cancel, scan and
|
||||
info buttons. Disable these if you provide your own controls using the
|
||||
:member:`cameraOverlayView`. (Default ``YES``).
|
||||
|
||||
.. member:: BOOL tracksSymbols
|
||||
|
||||
Whether to display the tracking rectangle around detected barcodes.
|
||||
|
||||
.. member:: NSUInteger supportedOrientationsMask
|
||||
|
||||
Set of interface orientations that the controller should support. Use
|
||||
:func:`ZBarOrientationMask` or ``ZBarOrientationMaskAll`` to
|
||||
generate the mask.
|
||||
|
||||
.. member:: CGRect scanCrop
|
||||
|
||||
Crop images before scanning. The original image will be cropped to this
|
||||
rectangle, which should be in normalized image coordinates (NB the
|
||||
camera image x-axis is *vertical* on the screen). Defaults to the full
|
||||
image ``{{0, 0}, {1, 1}}``.
|
||||
|
||||
.. member:: UIView *cameraOverlayView
|
||||
|
||||
A custom view to display over the camera preview.
|
||||
|
||||
.. member:: CGAffineTransform cameraViewTransform
|
||||
|
||||
A transform to apply to the camera preview. Ignored by the reader.
|
||||
|
||||
.. member:: UIImagePickerControllerCameraDevice cameraDevice
|
||||
|
||||
The camera device to use for scanning. Defaults to the system default
|
||||
camera.
|
||||
|
||||
.. member:: UIImagePickerControllerCameraFlashMode cameraFlashMode
|
||||
|
||||
The "flash" (aka torch) mode to use while scanning. Defaults to
|
||||
UIImagePickerControllerCameraFlashModeAuto.
|
||||
|
||||
.. member:: UIImagePickerControllerQualityType videoQuality
|
||||
|
||||
The resolution to use while scanning. Defaults to
|
||||
UIImagePickerControllerQuality640x480.
|
||||
|
||||
.. member:: ZBarReaderView *readerView
|
||||
|
||||
View that presents the camera preview and performs the scanning. This
|
||||
view has other properties you may use to control the appearance and
|
||||
behavior of the reader.
|
||||
|
||||
Note that this view may be released when it is not displayed (eg, under
|
||||
low memory conditions). You should apply any configuration just before
|
||||
you present the reader.
|
||||
|
||||
.. member:: BOOL enableCache
|
||||
|
||||
This property is deprecated and should not be modified.
|
||||
|
||||
.. warning::
|
||||
|
||||
The remaining properties are deprecated, they are only present for
|
||||
backward compatibility with :class:`ZBarReaderController` and will raise
|
||||
an exception if inappropriate/unsupported values are set.
|
||||
|
||||
.. member:: UIImagePickerControllerSourceType sourceType
|
||||
|
||||
Raises an exception if anything other than
|
||||
``UIImagePickerControllerSourceTypeCamera`` is set. If you want to scan
|
||||
images, use a :class:`ZBarReaderController` instead of this class.
|
||||
|
||||
.. member:: UIImagePickerControllerCameraCaptureMode cameraCaptureMode
|
||||
|
||||
Raises an exception if anything other than
|
||||
``UIImagePickerControllerCameraCaptureModeVideo`` is set.
|
||||
|
||||
.. member:: BOOL allowsEditing
|
||||
|
||||
Raises an exception if anything other than ``NO`` is set.
|
||||
|
||||
.. member:: BOOL showsCameraControls
|
||||
|
||||
Raises an exception if anything other than ``NO`` is set. Use
|
||||
:member:`showsZBarControls` to disable the buit-in overlay.
|
||||
|
||||
.. member:: BOOL showsHelpOnFail
|
||||
|
||||
Any value set to this property is ignored. It is only useful for
|
||||
scanning images, for which you should use :class:`ZBarReaderController`.
|
||||
|
||||
.. member:: ZBarReaderControllerCameraMode cameraMode
|
||||
|
||||
This reader only supports scanning from the camera feed. If you want to
|
||||
scan manually captured images, use a :class:`ZBarReaderController`
|
||||
instead of this class.
|
||||
|
||||
.. member:: BOOL takesPicture
|
||||
|
||||
Raises an exception if anything other than ``NO`` is set. This
|
||||
controller automatically returns the scanned camera frame and does not
|
||||
support capturing a separate image.
|
||||
|
||||
.. member:: NSInteger maxScanDimension
|
||||
|
||||
Any value set to this property is ignored. It is only useful for
|
||||
scanning images, for which you should use :class:`ZBarReaderController`.
|
||||
|
||||
|
||||
Class Methods
|
||||
-------------
|
||||
|
||||
.. describe:: + (BOOL) isSourceTypeAvailable:(UIImagePickerControllerSourceType)source
|
||||
|
||||
Returns ``YES`` only if ``source`` is ``Camera`` and the
|
||||
:class:`UImagePickerController` method of the same name also returns
|
||||
``YES``.
|
||||
|
||||
.. describe:: + (BOOL) isCameraDeviceAvailable:(UIImagePickerControllerCameraDevice)cameraDevice
|
||||
|
||||
See the :class:`UImagePickerController` method of the same name.
|
||||
|
||||
.. describe:: + (BOOL) isFlashAvailableForCameraDevice:(UIImagePickerControllerCameraDevice)cameraDevice
|
||||
|
||||
See the :class:`UImagePickerController` method of the same name.
|
||||
|
||||
.. describe:: + (NSArray*) availableCaptureModesForCameraDevice:(UIImagePickerControllerCameraDevice)cameraDevice
|
||||
|
||||
Returns an array with the single element
|
||||
``UIImagePickerControllerCameraCaptureModeVideo`` if the device is
|
||||
avilable, otherwise returns an empty array.
|
||||
|
||||
|
||||
Instance Methods
|
||||
----------------
|
||||
|
||||
.. _`showHelpWithReason:`:
|
||||
.. describe:: - (void) showHelpWithReason:(NSString*)reason
|
||||
|
||||
Display the integrated help browser. Use this with custom overlays if
|
||||
you don't also want to create your own help view. Should only be called
|
||||
when the reader is displayed. The ``reason`` argument will be passed to
|
||||
the :func:`onZBarHelp` javascript function.
|
||||
|
||||
:reason: A string parameter passed to javascript.
|
||||
|
||||
.. _`takePicture`:
|
||||
.. describe:: - (void) takePicture
|
||||
|
||||
Capture the next available frame and send it over the usual delegate
|
||||
path.
|
||||
|
||||
|
||||
Macros
|
||||
------
|
||||
|
||||
.. function:: ZBarOrientationMask(interfaceOrientation)
|
||||
|
||||
Generate a bit-mask for the specified interface orientation, suitable
|
||||
for setting :member:`supportedOrientationsMask`.
|
||||
|
||||
.. describe:: ZBarOrientationMaskAll
|
||||
|
||||
Combination of :func:`ZBarOrientationMask` for all interface
|
||||
orientations (Portrait, PortraitUpsideDown, LandscapeLeft and
|
||||
LandscapeRight)
|
||||
26
iphone/doc/ZBarReaderViewDelegate.rst
Normal file
26
iphone/doc/ZBarReaderViewDelegate.rst
Normal file
@ -0,0 +1,26 @@
|
||||
ZBarReaderViewDelegate Protocol Reference
|
||||
=========================================
|
||||
|
||||
.. class:: ZBarReaderViewDelegate
|
||||
|
||||
:Inherits from: :class:`NSObject`
|
||||
|
||||
This protocol, which must be implemented by the `readerDelegate` provided
|
||||
to a :class:`ZBarReaderView`, is used to notify the delegate of new decode
|
||||
results.
|
||||
|
||||
|
||||
Instance Methods
|
||||
----------------
|
||||
|
||||
.. describe:: - (void) readerView:(ZBarReaderView*)readerView didReadSymbols:(ZBarSymbolSet*)symbols fromImage:(UIImage*)image
|
||||
|
||||
Called to notify the delegate of new decode results.
|
||||
|
||||
Note that the referenced image is a proxy for a video buffer that is
|
||||
asynchronously being converted to a :class:`UIImage`, attempting to
|
||||
access the data will block until the conversion is complete.
|
||||
|
||||
:readerView: :class:`ZBarReaderView` that scanned the barcode(s).
|
||||
:symbols: :class:`ZBarSymbolSet` containing the decode results.
|
||||
:image: :class:`UIImage` from which the barcode(s) were scanned.
|
||||
186
iphone/doc/ZBarSymbol.rst
Normal file
186
iphone/doc/ZBarSymbol.rst
Normal file
@ -0,0 +1,186 @@
|
||||
ZBarSymbol Class Reference
|
||||
==========================
|
||||
|
||||
.. class:: ZBarSymbol
|
||||
|
||||
:Inherits from: :class:`NSObject`
|
||||
|
||||
A symbol wraps all of the information the library has about a decoded
|
||||
barcode. Use the available properties to retrieve the barcode data, the
|
||||
symbology (type of barcode), location and more.
|
||||
|
||||
This class is a simple wrapper around a :type:`zbar_symbol_t` C object
|
||||
(q.v.)
|
||||
|
||||
|
||||
Properties
|
||||
----------
|
||||
|
||||
.. member:: zbar_symbol_type_t type
|
||||
|
||||
The type of symbology that was decoded. (read-only)
|
||||
|
||||
.. member:: NSString *typeName
|
||||
|
||||
The canonical name used by the library to represent the symbology.
|
||||
(read-only)
|
||||
|
||||
.. member:: NSUInteger configMask
|
||||
|
||||
Bitmask of symbology config settings used during decode.
|
||||
|
||||
.. member:: NSUInteger modifierMask
|
||||
|
||||
Bitmask of symbology characteristics detected during decode. See
|
||||
:type:`zbar_modifier_t` for the currently defined modifier bits.
|
||||
|
||||
.. member:: NSString *data
|
||||
|
||||
The raw decoded barcode data. (read-only)
|
||||
|
||||
.. member:: int quality
|
||||
|
||||
A relative metric indicating rough confidence in the decoded value.
|
||||
Larger values are better than smaller values. (read-only)
|
||||
|
||||
.. member:: zbar_orientation_t orientation
|
||||
|
||||
The general, axis-aligned orientation of the symbol, or
|
||||
ZBAR_ORIENT_UNKNOWN if unknown. (read-only)
|
||||
|
||||
.. member:: ZBarSymbolSet *components
|
||||
|
||||
The components of a composite symbol. (read-only)
|
||||
|
||||
.. member:: const zbar_symbol_t *zbarSymbol
|
||||
|
||||
Retrieve the underlying C object instance. (read-only)
|
||||
|
||||
.. member:: CGRect bounds
|
||||
|
||||
Calculate a rough bounding box for the symbol. (read-only)
|
||||
|
||||
.. note::
|
||||
|
||||
Coordinates are relative to the image *data*, which may not match a
|
||||
displayed UIImage. Make sure to account for the UIImage orientation
|
||||
when using these values.
|
||||
|
||||
|
||||
Class Methods
|
||||
-------------
|
||||
|
||||
.. _`nameForType:`:
|
||||
.. describe:: + (NSString*) nameForType:(zbar_symbol_type_t)type
|
||||
|
||||
Retrieve the canonical name for a symbology used by the library, given
|
||||
its enumerated value.
|
||||
|
||||
:type: The :type:`zbar_symbol_type_t` enumerated symbology value.
|
||||
:Returns: A short string name for the symbology.
|
||||
|
||||
|
||||
Instance Methods
|
||||
----------------
|
||||
|
||||
.. _`initWithSymbol:`:
|
||||
.. describe:: - (id) initWithSymbol:(const zbar_symbol_t*)symbol
|
||||
|
||||
Initialize a symbol wrapper, given the C object to wrap.
|
||||
|
||||
:symbol: The C object to wrap.
|
||||
:Returns: The initialized symbol, or nil if an error occurred.
|
||||
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. type:: zbar_symbol_type_t
|
||||
|
||||
Symbology identifiers.
|
||||
|
||||
ZBAR_NONE
|
||||
No symbol was decoded.
|
||||
|
||||
ZBAR_PARTIAL
|
||||
Intermediate status.
|
||||
|
||||
ZBAR_EAN8
|
||||
EAN-8
|
||||
|
||||
ZBAR_UPCE
|
||||
UPC-E
|
||||
|
||||
ZBAR_ISBN10
|
||||
ISBN-10, converted from EAN-13
|
||||
|
||||
ZBAR_UPCA
|
||||
UPC-A
|
||||
|
||||
ZBAR_EAN13
|
||||
EAN-13
|
||||
|
||||
ZBAR_ISBN13
|
||||
ISBN-13, converted from EAN-13
|
||||
|
||||
ZBAR_I25
|
||||
Interleaved 2 of 5
|
||||
|
||||
ZBAR_DATABAR
|
||||
GS1 DataBar (RSS)
|
||||
|
||||
ZBAR_DATABAR_EXP
|
||||
GS1 DataBar Expanded
|
||||
|
||||
ZBAR_CODABAR
|
||||
Codabar
|
||||
|
||||
ZBAR_CODE39
|
||||
Code 39 (3 of 9)
|
||||
|
||||
ZBAR_QRCODE
|
||||
QR Code
|
||||
|
||||
ZBAR_CODE128
|
||||
Code 128
|
||||
|
||||
.. type:: zbar_orientation_t
|
||||
|
||||
The coarse orientation of a symbol.
|
||||
|
||||
.. note::
|
||||
|
||||
Orientation is relative to the image *data*, which may not match a
|
||||
displayed UIImage. Make sure to account for the UIImage orientation
|
||||
when using these values.
|
||||
|
||||
ZBAR_ORIENT_UNKNOWN
|
||||
Unable to determine orientation.
|
||||
|
||||
ZBAR_ORIENT_UP
|
||||
Upright, read left to right
|
||||
|
||||
ZBAR_ORIENT_RIGHT
|
||||
Sideways, read top to bottom
|
||||
|
||||
ZBAR_ORIENT_DOWN
|
||||
Upside-down, read right to left
|
||||
|
||||
ZBAR_ORIENT_LEFT
|
||||
Sideways, read bottom to top
|
||||
|
||||
.. type:: zbar_modifier_t
|
||||
|
||||
Decoder symbology modifier flags.
|
||||
|
||||
.. note::
|
||||
|
||||
These are bit indices, use eg, (1 << ZBAR_MOD_GS1) to test the
|
||||
modifierMask property.
|
||||
|
||||
ZBAR_MOD_GS1
|
||||
Barcode tagged as GS1 (EAN.UCC) reserved (eg, FNC1 before first data
|
||||
character). Data may be parsed as a sequence of GS1 AIs.
|
||||
|
||||
ZBAR_MOD_AIM
|
||||
Barcode tagged as AIM reserved.
|
||||
43
iphone/doc/ZBarSymbolSet.rst
Normal file
43
iphone/doc/ZBarSymbolSet.rst
Normal file
@ -0,0 +1,43 @@
|
||||
ZBarSymbolSet Class Reference
|
||||
=============================
|
||||
|
||||
.. class:: ZBarSymbolSet
|
||||
|
||||
:Inherits from: :class:`NSObject`
|
||||
:Conforms to: :class:`NSFastEnumeration`
|
||||
|
||||
A symbol set is a simple container for the symbols scanned from an image.
|
||||
It supports :class:`NSFastEnumeration`, and not much else... Use it to
|
||||
iterate through the :class:`ZBarSymbol` objects in a decode result set::
|
||||
|
||||
ZBarSymbolSet *symbols = image.symbols;
|
||||
for(ZBarSymbol *symbol in symbols) {
|
||||
// process result
|
||||
}
|
||||
|
||||
This class is a simple wrapper around a :type:`zbar_symbol_set_t` C object
|
||||
(q.v.)
|
||||
|
||||
|
||||
Properties
|
||||
----------
|
||||
|
||||
.. member:: int count
|
||||
|
||||
The number of symbols in the set. (read-only)
|
||||
|
||||
.. member:: const zbar_symbol_set_t *zbarSymbolSet
|
||||
|
||||
Retrieve the underlying C object instance. (read-only)
|
||||
|
||||
|
||||
Instance Methods
|
||||
----------------
|
||||
|
||||
.. _`initWithSymbolSet:`:
|
||||
.. describe:: - (id) initWithSymbolSet:(const zbar_symbol_set_t*)set
|
||||
|
||||
Initialize a symbol set wrapper, given the C object to wrap.
|
||||
|
||||
:set: The C object to wrap.
|
||||
:Returns: The initialized symbol set, or nil if an error occurred.
|
||||
16
iphone/doc/apiref.rst
Normal file
16
iphone/doc/apiref.rst
Normal file
@ -0,0 +1,16 @@
|
||||
*******************
|
||||
API Reference
|
||||
*******************
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
ZBarImage
|
||||
ZBarImageScanner
|
||||
ZBarReaderController
|
||||
ZBarReaderDelegate
|
||||
ZBarReaderView
|
||||
ZBarReaderViewController
|
||||
ZBarReaderViewDelegate
|
||||
ZBarSymbol
|
||||
ZBarSymbolSet
|
||||
130
iphone/doc/camera.rst
Normal file
130
iphone/doc/camera.rst
Normal file
@ -0,0 +1,130 @@
|
||||
Scanning From the Camera Feed
|
||||
=============================
|
||||
|
||||
Many iOS developers want their application to support automatic recognition of
|
||||
barcodes from the camera feed in real-time. ZBar makes this easy!
|
||||
|
||||
There are three levels that you may choose to integrate at, from least complex
|
||||
(recommended) to most complex these are:
|
||||
|
||||
* Use the fully integrated view controller - this is very easy to implement
|
||||
and is the recommended approach.
|
||||
* Use the reader view with your own controller - this more advanced approach
|
||||
allows you to embed the view directly in your view hierarchy.
|
||||
* Use the capture component with your own AVCapture session - this is not
|
||||
supported and only provided for advanced developers with special needs who
|
||||
are already familiar with AVCapture.
|
||||
|
||||
|
||||
Using a ZBarReaderViewController
|
||||
--------------------------------
|
||||
|
||||
This is the fastest, easiest and recommend way to get the barcode reader into
|
||||
your application. The procedure is the same as using a
|
||||
UIImagePickerController to take a picture with the camera, so it will help if
|
||||
you are familiar with that. Basically you:
|
||||
|
||||
1. Create the reader.
|
||||
|
||||
This is as simple as creating a new :class:`ZBarReaderViewController`::
|
||||
|
||||
ZBarReaderViewController *reader = [[ZBarReaderViewController alloc] init];
|
||||
|
||||
2. Setup a delegate to receive the results.
|
||||
|
||||
The delegate should implement the :class:`ZBarReaderDelegate` protocol,
|
||||
which inherits from :class:`UIImagePickerControllerDelegate`::
|
||||
|
||||
reader.readerDelegate = self;
|
||||
|
||||
3. Configure the reader.
|
||||
|
||||
Aside from the properties of the reader itself, you can configure the
|
||||
decoder via the :member:`~ZBarReaderViewController::scanner` property and
|
||||
further customize the view via the
|
||||
:member:`~ZBarReaderViewController::readerView` property::
|
||||
|
||||
// disable QR Code
|
||||
[reader.scanner setSymbology: ZBAR_QRCODE
|
||||
config: ZBAR_CFG_ENABLE
|
||||
to: 0];
|
||||
reader.readerView.zoom = 1.0;
|
||||
|
||||
See :doc:`custom` and :doc:`optimizing` for more details.
|
||||
|
||||
4. Present the reader to the user.
|
||||
|
||||
Typically the controller is presented modally::
|
||||
|
||||
[self presentModalViewController: reader
|
||||
animated: YES];
|
||||
|
||||
Alternatively, it may be added to a container controller.
|
||||
|
||||
5. Process the results.
|
||||
|
||||
The controller will call the
|
||||
``imagePickerController:didFinishPickingMediaWithInfo:`` method of
|
||||
your delegate every time new results become available. The barcode data
|
||||
can be obtained using the :c:data:`ZBarReaderControllerResults` key of the
|
||||
info dictionary. This key will return "something enumerable"; keep in mind
|
||||
that there may be multiple results. You may also retrieve the
|
||||
corresponding image with :c:data:`UIImagePickerControllerOriginalImage` as
|
||||
usual::
|
||||
|
||||
- (void) imagePickerController: (UIImagePickerController*) reader
|
||||
didFinishPickingMediaWithInfo: (NSDictionary*) info
|
||||
{
|
||||
id<NSFastEnumeration> results =
|
||||
[info objectForKey: ZBarReaderControllerResults];
|
||||
UIImage *image =
|
||||
[info objectForKey: UIImagePickerControllerOriginalImage];
|
||||
...
|
||||
|
||||
The ``reader`` parameter will be the actual type of the reader (not
|
||||
necessarily a :class:`UIImagePickerController`).
|
||||
|
||||
.. note::
|
||||
|
||||
The delegate method should queue the interface response and return as
|
||||
soon as possible; any processing of the results should be deferred until
|
||||
later, otherwise the user will experience unacceptable latency between
|
||||
the actual scan completion and the visual interface feedback.
|
||||
|
||||
6. Dismiss the reader (or not).
|
||||
|
||||
Once you have the results you may dismiss the reader::
|
||||
|
||||
[reader dismissModalViewControllerAnimated: YES];
|
||||
|
||||
.. warning::
|
||||
|
||||
It is very important to dismiss from the *reader* (not the presenting
|
||||
controller) to avoid corrupting the interface.
|
||||
|
||||
Alternatively, you may choose to continue scanning and provide visual
|
||||
feedback another way (eg, maybe by updating your custom overlay with the
|
||||
results). The "continuous" mode of the readertest example does this.
|
||||
|
||||
|
||||
Using a ZBarReaderView
|
||||
----------------------
|
||||
|
||||
:class:`ZBarReaderViewController` is a relatively thin wrapper around a
|
||||
:class:`ZBarReaderView`; it is possible to use the view directly, even from
|
||||
Interface Builder. You lose only some of the simulator and rotation hooks.
|
||||
The documentation is also less complete, so you need to be able to UTSL. See
|
||||
the :file:`EmbedReader` sample for a working example.
|
||||
|
||||
|
||||
Using the ZBarCaptureReader
|
||||
---------------------------
|
||||
|
||||
If you have special requirements for the capture session or just want to use
|
||||
your own preview, you can add your own :class:`ZBarCaptureReader` to your
|
||||
session. You must have a solid understanding of the AVCapture infrastructure
|
||||
if you plan to use this approach.
|
||||
|
||||
.. admonition:: TBD
|
||||
|
||||
sorry, you're on your own here - UTSL :)
|
||||
190
iphone/doc/compat.rst
Normal file
190
iphone/doc/compat.rst
Normal file
@ -0,0 +1,190 @@
|
||||
Backward Compatibility
|
||||
======================
|
||||
|
||||
Generally speaking, we take great care to ensure that each release of the
|
||||
library is backward compatible with previous versions - upgrading the library
|
||||
should not require any changes to your code and will continue to provide
|
||||
equivalent functionality. The notable exception to this is the iOS 4 upgrade
|
||||
and associated "deprecation" of the former automatic capture method by our
|
||||
vendor.
|
||||
|
||||
|
||||
.. warning::
|
||||
|
||||
Versions before iOS 4 are no longer supported by the library. We are no
|
||||
longer able to test anything in this section, so you're on your own if you
|
||||
try to make use of it.
|
||||
|
||||
|
||||
The Private API
|
||||
---------------
|
||||
|
||||
The API that we use for automatic capture with iOS 3.x (namely
|
||||
:func:`UIGetScreenImage`) has an interesting history. It has changed status
|
||||
several times, starting with "Private, unless we like you" moving to
|
||||
"reluctantly Public but undocumeted" by popular demand and reverting to
|
||||
"strictly Private" as of iOS 4. The current story: if you want to distribute
|
||||
on the App Store, you had better not be using it - IOW, no automatic capture
|
||||
for you with iOS 3.x.
|
||||
|
||||
Since App Store distribution is the most common use for the library, the
|
||||
default configuration, and thus the binary SDK, does *not* use any private
|
||||
APIs.
|
||||
|
||||
Users targeting ad-hoc or enterprise distribution may not care about the
|
||||
status of the API and may prefer to continue supporting automatic capture for
|
||||
iOS 3.x. To do this you will need to rebuild the library with the following
|
||||
define set for all configurations:
|
||||
|
||||
.. sourcecode:: sh
|
||||
|
||||
USE_PRIVATE_APIS=1
|
||||
|
||||
For reference, you can check whether your app refers to the offensive function
|
||||
with this command:
|
||||
|
||||
.. sourcecode:: sh
|
||||
|
||||
$ otool -vI MyApp.app/MyApp | grep UIGetScreenImage
|
||||
|
||||
If there is any output, then the executable includes the private API and is
|
||||
bound to be rejected if submitted for review. Otherwise it is "clean" as far
|
||||
as this library is concerned.
|
||||
|
||||
|
||||
Upgrading to iOS 4
|
||||
------------------
|
||||
|
||||
If you were using the reader before iOS 4 was introduced, you will want to
|
||||
upgrade to the new reader controller. The performance has improved quite a
|
||||
bit, and you can continue to support automatic capture on the App Store.
|
||||
|
||||
.. note::
|
||||
|
||||
This discussion only applies to automatic capture from the camera. If you
|
||||
are only scanning image files, or prefer/need to use manual capture, you
|
||||
should not change anything.
|
||||
|
||||
Basically just replace your old :class:`ZBarReaderController` with a new
|
||||
:class:`ZBarReaderViewController` and you're done! See the reference and the
|
||||
next section for compatibility between the two classes.
|
||||
|
||||
Also see the :doc:`install` instructions for details about upgrading the
|
||||
header references to use the SDK.
|
||||
|
||||
|
||||
Supporting iOS 3.x
|
||||
------------------
|
||||
|
||||
The new :class:`ZBarReaderViewController` is intentionally designed to be
|
||||
compatible with the old :class:`ZBarReaderController` in most aspects that
|
||||
relate to reading barcodes. When a :class:`ZBarReaderViewController` is
|
||||
initialized under iOS 3.x, it will *replace* itself with a
|
||||
:class:`ZBarReaderController`. You can leverage the compatibility of these
|
||||
controllers to continue supporting iOS 3.x.
|
||||
|
||||
The following properties and methods should be equivalent across
|
||||
implementations. You may use them without regard for the actual instance
|
||||
type.
|
||||
|
||||
======================================================== ====
|
||||
Equivalent Members
|
||||
======================================================== ====
|
||||
:member:`~ZBarReaderViewController::cameraOverlayView`
|
||||
:member:`~ZBarReaderViewController::cameraViewTransform`
|
||||
:member:`~ZBarReaderViewController::enableCache`
|
||||
:member:`~ZBarReaderViewController::scanner`
|
||||
:member:`~ZBarReaderViewController::readerDelegate`
|
||||
:member:`~ZBarReaderViewController::scanCrop`
|
||||
``showHelpWithReason:``
|
||||
:member:`~ZBarReaderViewController::showsZBarControls`
|
||||
:member:`~ZBarReaderViewController::tracksSymbols`
|
||||
======================================================== ====
|
||||
|
||||
Some properties are available with :class:`ZBarReaderViewController` only for
|
||||
backward compatibility. If these are configured, they must be set as
|
||||
indicated; attempts to set another value will raise an exception.
|
||||
|
||||
==================================================== =======================================
|
||||
:class:`ZBarReaderController` Property :class:`ZBarReaderViewController` Value
|
||||
==================================================== =======================================
|
||||
:member:`~ZBarReaderController::allowsEditing` ``NO``
|
||||
:member:`~ZBarReaderController::cameraMode` ``Sampling``
|
||||
:member:`~ZBarReaderController::maxScanDimension` (ignored)
|
||||
:member:`~ZBarReaderController::showsCameraControls` ``NO``
|
||||
:member:`~ZBarReaderController::showsHelpOnFail` (ignored)
|
||||
:member:`~ZBarReaderController::sourceType` ``Camera``
|
||||
:member:`~ZBarReaderController::takesPicture` ``NO``
|
||||
==================================================== =======================================
|
||||
|
||||
Also, the ``isSourceTypeAvailable:`` class method of
|
||||
:class:`ZBarReaderViewController` will return ``YES`` only for the ``Camera``
|
||||
source.
|
||||
|
||||
All other members of :class:`ZBarReaderController`, including those inherited
|
||||
from :class:`UIImagePickerController` are not supported by
|
||||
:class:`ZBarReaderViewController`. This includes ``takePicture`` and
|
||||
``scanImage:``, among others.
|
||||
|
||||
Remaining members of :class:`ZBarReaderViewController`: are only available
|
||||
with the new implementation. At the moment this is only
|
||||
:member:`~ZBarReaderViewController::readerView`, but any new properties or
|
||||
methods not listed here will also fall in this category.
|
||||
|
||||
To access settings that may not be available in a potential fallback
|
||||
environment, you must verify that they exist and may be set as desired - eg,
|
||||
by testing the specific reader subtype.
|
||||
|
||||
Weak Linking
|
||||
^^^^^^^^^^^^
|
||||
|
||||
When leveraging fallbacks to iOS 3.x, it is important that features introduced
|
||||
in iOS 4 are referenced using *weak* links. You must configure your project
|
||||
correctly to support this:
|
||||
|
||||
* Make sure the iOS 4 frameworks are set to *Weak*. Specifically, these are
|
||||
AVCapture, CoreMedia and CoreVideo.
|
||||
|
||||
* Build with the latest SDK - do *not* use the "Base SDK" setting to target
|
||||
earlier devices.
|
||||
|
||||
* Set the correct iOS 3.x version for the "iPhone OS Deployment Target"
|
||||
build setting.
|
||||
|
||||
|
||||
Example: Fallback to Manual Capture
|
||||
-----------------------------------
|
||||
|
||||
This code example will configure the reader for automatic capture from the
|
||||
camera for iOS 4 and fall back to manual or automatic capture for iOS 3.x,
|
||||
depending on whether the library was compiled to use private APIs::
|
||||
|
||||
if(![ZBarReaderController isSourceTypeAvailable:
|
||||
UIImagePickerControllerSourceTypeCamera]) {
|
||||
// camera unavailable: display warning and abort
|
||||
// or resort to keypad entry, etc...
|
||||
return;
|
||||
}
|
||||
|
||||
ZBarReaderViewController *reader = [ZBarReaderViewController new];
|
||||
// reader will be a ZBarReaderController for iOS 3.x
|
||||
// or a ZBarReaderViewController for iOS 4
|
||||
|
||||
reader.readerDelegate = self;
|
||||
reader.sourceType = UIImagePickerControllerSourceTypeCamera;
|
||||
reader.showsZBarControls = YES;
|
||||
|
||||
if(reader.cameraMode == ZBarReaderControllerCameraModeSampling) {
|
||||
// additional automatic capture configuration here
|
||||
}
|
||||
else {
|
||||
// additional manual capture configuration here
|
||||
}
|
||||
|
||||
[self presentModalViewController: reader
|
||||
animated: YES];
|
||||
|
||||
If you are using a custom control set
|
||||
(:member:`~ZBarReaderViewController::showsZBarControls`\ ``=NO``), you will
|
||||
want to provide a button attached to ``takePicture`` for the manual capture
|
||||
case. The built-in controls do this automatically.
|
||||
77
iphone/doc/conf.py
Normal file
77
iphone/doc/conf.py
Normal file
@ -0,0 +1,77 @@
|
||||
import sys, os
|
||||
from plistlib import readPlist
|
||||
|
||||
# General configuration
|
||||
|
||||
extensions = []
|
||||
templates_path = ['ext']
|
||||
source_suffix = '.rst'
|
||||
master_doc = 'index'
|
||||
exclude_patterns = ['.#*']
|
||||
|
||||
project = u'ZBar iPhone SDK'
|
||||
copyright = u'2010-2012, Jeff Brown et al'
|
||||
|
||||
today_fmt = '%Y-%m-%d'
|
||||
info = readPlist('../res/ZBarSDK-Info.plist')
|
||||
version = 'X.Y'
|
||||
if info:
|
||||
version = info['CFBundleVersion']
|
||||
release = version
|
||||
|
||||
#add_module_names = False
|
||||
|
||||
pygments_style = 'sphinx'
|
||||
highlight_language = 'objc'
|
||||
primary_domain = 'cpp'
|
||||
|
||||
# Options for HTML output
|
||||
|
||||
html_theme = 'default'
|
||||
html_theme_options = {
|
||||
'bgcolor': 'white',
|
||||
'textcolor': 'black',
|
||||
'linkcolor': '#247',
|
||||
'headbgcolor': '#edeff0',
|
||||
'headtextcolor': '#247',
|
||||
'headlinkcolor': '#c11',
|
||||
'sidebarbgcolor': '#247',
|
||||
'sidebartextcolor': 'white',
|
||||
'sidebarlinkcolor': '#cde',
|
||||
'relbarbgcolor': '#247',
|
||||
'relbartextcolor': '#ccc',
|
||||
'relbarlinkcolor': 'white',
|
||||
'footerbgcolor': 'white',
|
||||
'footertextcolor': 'black',
|
||||
'codebgcolor': '#dfe',
|
||||
'codetextcolor': 'black',
|
||||
}
|
||||
|
||||
html_short_title = 'ZBarSDK ' + version
|
||||
html_title = 'ZBar iPhone SDK Documentation'
|
||||
html_static_path = ['static']
|
||||
html_favicon = '../../zbar.ico'
|
||||
html_style = 'style.css'
|
||||
html_use_modindex = False
|
||||
html_use_index = False
|
||||
html_copy_source = False
|
||||
html_show_sourcelink = False
|
||||
htmlhelp_basename = 'doc'
|
||||
|
||||
# Options for LaTeX output
|
||||
|
||||
latex_paper_size = 'letter'
|
||||
latex_font_size = '10pt'
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual])
|
||||
latex_documents = [
|
||||
('index', 'ZBarSDK.tex', u'ZBar iPhone SDK Documentation',
|
||||
u'Jeff Brown', 'manual'),
|
||||
]
|
||||
|
||||
#latex_logo = ''
|
||||
#latex_use_parts = False
|
||||
#latex_preamble = ''
|
||||
#latex_appendices = []
|
||||
#latex_use_modindex = False
|
||||
70
iphone/doc/custom.rst
Normal file
70
iphone/doc/custom.rst
Normal file
@ -0,0 +1,70 @@
|
||||
Customizing the Interface
|
||||
=========================
|
||||
|
||||
The reader supports customization of the camera overlay and the integrated
|
||||
help that is displayed.
|
||||
|
||||
|
||||
Customizing the Overlay
|
||||
-----------------------
|
||||
|
||||
If you are scanning with the camera, whether using a
|
||||
:class:`ZBarReaderViewController` for automatic capture or manually with
|
||||
:class:`ZBarReaderController`, you may want to customize the appearance of the
|
||||
reader. You do this mainly by setting a
|
||||
:member:`~ZBarReaderViewController::cameraOverlayView`.
|
||||
|
||||
Note that if you are scanning images from the photo library, there is no
|
||||
customization - you are limited to the system picker interface provided by the
|
||||
:class:`UIImagePickerController`.
|
||||
|
||||
If you are using a :class:`ZBarReaderViewController` and just want to add to
|
||||
the existing controls, you can simply set your overlay to include the
|
||||
additional view hierarchy::
|
||||
|
||||
reader.cameraOverlayView = myLogoImageView;
|
||||
|
||||
Otherwise, if you are using a :class:`ZBarReaderController` or prefer to
|
||||
completely replace the default controls, you should disable those first. Note
|
||||
that you will need to provide your own controls, which should at least include
|
||||
a way to dismiss the reader::
|
||||
|
||||
reader.showsCameraControls = NO; // for UIImagePickerController
|
||||
reader.showsZBarControls = NO;
|
||||
reader.cameraOverlayView = myControlView;
|
||||
|
||||
For manual capture with :class:`ZBarReaderController`, you should also include
|
||||
a control connected to :member:`~ZBarReaderController::takePicture`.
|
||||
|
||||
In either case, the overlay view may be loaded from a NIB, or simply created
|
||||
programmatically.
|
||||
|
||||
You can also disable the tracking rectangle that highlights barcodes with
|
||||
:member:`~ZBarReaderViewController::tracksSymbols`.
|
||||
|
||||
|
||||
Presenting Help
|
||||
---------------
|
||||
|
||||
If you have set ``showsZBarControls = NO`` and replaced the default controls,
|
||||
you may still present the built-in help viewer. Just hook your custom control
|
||||
to the ``showsHelpWithReason:`` method of the controller. You should only
|
||||
call this method when the reader is actually presented.
|
||||
|
||||
The default reader controls invoke ``showsHelpWithReason:`` with a reason
|
||||
parameter of ``"INFO"`` when the info button is tapped.
|
||||
|
||||
|
||||
Customizing the Help Content
|
||||
----------------------------
|
||||
|
||||
Whether you use the default controls or provide your own, you can still
|
||||
customize the content of the help that is displayed. The integrated viewer
|
||||
uses a UIWebView to display the contents of :file:`zbar-help.html` that we
|
||||
copied into your Resources. You should hack this up as you see fit to give
|
||||
your users the best help experience.
|
||||
|
||||
To allow for runtime customization based on the reason for presenting help,
|
||||
the javascript function ``onZBarHelp`` will be called just before the page is
|
||||
displayed, with the ``reason`` argument set as provided to
|
||||
``showsHelpWithReason:``.
|
||||
13
iphone/doc/devguide.rst
Normal file
13
iphone/doc/devguide.rst
Normal file
@ -0,0 +1,13 @@
|
||||
***********************
|
||||
Developer's Guide
|
||||
***********************
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
camera
|
||||
picker
|
||||
custom
|
||||
optimizing
|
||||
compat
|
||||
licensing
|
||||
101
iphone/doc/faq.rst
Normal file
101
iphone/doc/faq.rst
Normal file
@ -0,0 +1,101 @@
|
||||
Frequently Asked Questions (FAQ)
|
||||
================================
|
||||
|
||||
This is the ever-growing list of answers to commonly asked questions. Please
|
||||
feel free to post you question in our `iPhone Developers forum`_ if you do not
|
||||
find the information you need in this documentation.
|
||||
|
||||
.. _`iPhone Developers Forum`:
|
||||
http://sourceforge.net/projects/zbar/forums/forum/1072195
|
||||
|
||||
|
||||
General
|
||||
-------
|
||||
|
||||
This looks great... Where can I get it?
|
||||
You can download the latest version of the SDK from
|
||||
http://zbar.sf.net/iphone
|
||||
|
||||
|
||||
Compatibility
|
||||
-------------
|
||||
|
||||
Which iPhone devices does this library support?
|
||||
The library works *only* with iOS devices that have an auto-focus camera.
|
||||
Currently, the iPhone 3GS, iPhone 4 and newer devices. The iPad 2 and iPad
|
||||
3 will also work in many cases, *iff* the barcode is printed large enough
|
||||
to achieve good focus.
|
||||
|
||||
Will you make it work with the iPhone 3G?
|
||||
*No* - the 3G it is not supported and is unlikely to ever be supported.
|
||||
|
||||
To be fair, you *can* use the 3G to scan image files, as long as they're in
|
||||
focus (ie, *not* images taken by the built-in fixed-focus camera). There
|
||||
is at least one application that found a use for this...
|
||||
|
||||
What target iOS versions does this library work with?
|
||||
iOS 4, 5 and 6 are fully supported, including the latest video streaming
|
||||
interfaces. Since Apple has dropped support for earlier versions of iOS on
|
||||
the App Store, we recommend that you target only iOS 4 and later for reading
|
||||
barcodes.
|
||||
|
||||
Note that iOS 3.1 is no longer supported; if you really think you need
|
||||
that, you should still be able to get it working... See :doc:`compat` for
|
||||
details about iOS version fallbacks.
|
||||
|
||||
In all cases you should use the latest SDK to build.
|
||||
|
||||
Are any private APIs in use?
|
||||
No - the binary release of the SDK does not use any private APIs.
|
||||
|
||||
Does this support "automatic" barcode capture?
|
||||
Yes - with recent iOS versions, the default configuration will capture
|
||||
barcodes automatically from the video stream.
|
||||
|
||||
|
||||
Building
|
||||
--------
|
||||
|
||||
I get "Undefined symbols" errors when I try to build?
|
||||
Most likely you did not add all of the necessary framework dependencies.
|
||||
See :doc:`tutorial` or :doc:`install` for the list of frameworks you need
|
||||
to link against.
|
||||
|
||||
|
||||
Licensing
|
||||
---------
|
||||
|
||||
Please refer to :doc:`licensing` for questions about licensing.
|
||||
|
||||
|
||||
Barcodes
|
||||
--------
|
||||
|
||||
Why do my UPC barcodes have an extra 0 at the front?
|
||||
The UPC-A_ symbology is the subset of EAN-13_ that starts with a leading 0.
|
||||
The ZBar decoder enables only EAN-13_ by default, so GTIN-13_ product codes
|
||||
are consistently reported. You can choose to receive the 12-digit results
|
||||
instead by explicitly enabling UPC-A_.
|
||||
|
||||
The :member:`~ZBarSymbol::type` property of the symbol can be used to see
|
||||
which type of barcode is reported.
|
||||
|
||||
See EAN-13_ and UPC-A_ for more information.
|
||||
|
||||
Why does my UPC-E (short version) barcode data look completely wrong?
|
||||
UPC-E_ is a "zero compressed" version of UPC-A_; certain of the zeros are
|
||||
removed from the UPC-A_ data to generate the UPC-E_ barcode. The ZBar
|
||||
decoder *expands* this compression by default, again to consistently report
|
||||
GTIN-13_ product codes. You can choose to receive the compressed 8-digit
|
||||
results instead by explicitly enabling UPC-E_.
|
||||
|
||||
The :member:`~ZBarSymbol::type` property of the symbol can be used to see
|
||||
which type of barcode is reported.
|
||||
|
||||
See UPC-E_ for more information.
|
||||
|
||||
.. _GTIN-13:
|
||||
.. _GTIN: http://wikipedia.org/wiki/GTIN
|
||||
.. _EAN-13: http://wikipedia.org/wiki/EAN-13
|
||||
.. _UPC-A: http://wikipedia.org/wiki/UPC-A
|
||||
.. _UPC-E: http://wikipedia.org/wiki/UPC-E#UPC-E
|
||||
12
iphone/doc/getstarted.rst
Normal file
12
iphone/doc/getstarted.rst
Normal file
@ -0,0 +1,12 @@
|
||||
*********************
|
||||
Getting Started
|
||||
*********************
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:numbered:
|
||||
|
||||
install
|
||||
tutorial
|
||||
faq
|
||||
support
|
||||
20
iphone/doc/index.rst
Normal file
20
iphone/doc/index.rst
Normal file
@ -0,0 +1,20 @@
|
||||
################
|
||||
ZBar iOS SDK
|
||||
################
|
||||
|
||||
Welcome to the ZBar SDK for iOS!
|
||||
|
||||
This documentation covers all aspects of developing with the SDK: from adding
|
||||
the SDK to your project, to writing code that uses it, even licensing the
|
||||
library with your app.
|
||||
|
||||
Please let us know if you find anything inaccurate or lacking (even better,
|
||||
send doc patches!)
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:numbered:
|
||||
|
||||
getstarted
|
||||
devguide
|
||||
apiref
|
||||
141
iphone/doc/install.rst
Normal file
141
iphone/doc/install.rst
Normal file
@ -0,0 +1,141 @@
|
||||
Installing the SDK
|
||||
==================
|
||||
|
||||
These are the basic instructions for obtaining the SDK and adding it to an
|
||||
Xcode project.
|
||||
|
||||
You may want to try things out with the :doc:`tutorial` before hacking at your
|
||||
own project.
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
You will need *all* of the following to develop iPhone applications
|
||||
using this SDK:
|
||||
|
||||
* Mac OS X >= 10.6.x (Snow Leopard)
|
||||
* Xcode >= 4.5.1
|
||||
* iPhone SDK >= 4.0
|
||||
* An iPhone 3GS, iPhone 4 or newer iOS device with an auto-focus camera
|
||||
* iOS >= 4.0 running on the device
|
||||
|
||||
.. warning::
|
||||
|
||||
*Only* the iPhone 3GS, iPhone 4 and newer models are supported, as they
|
||||
have a camera with auto-focus. The iPad 2 and iPad 3 will also work, *iff*
|
||||
the barcode is printed large enough to achieve good focus. The ZBar
|
||||
library does not support the iPhone 3G and is unlikely to ever support it.
|
||||
|
||||
|
||||
Downloading
|
||||
-----------
|
||||
|
||||
Download the latest binary release of the ZBar SDK from
|
||||
|
||||
http://zbar.sourceforge.net/iphone
|
||||
|
||||
|
||||
Integration
|
||||
-----------
|
||||
|
||||
The recommended installation method is to simply copy the SDK into your
|
||||
Xcode project:
|
||||
|
||||
1. Open ZBarSDK-|version|.dmg in the Finder.
|
||||
|
||||
2. Drag the :file:`ZBarSDK` folder into your Xcode project. In the dialog
|
||||
that appears, you should choose to **copy** the SDK into your project by
|
||||
checking the box. The target that you want to link with the library should
|
||||
also be selected in the target list.
|
||||
|
||||
3. Link the following additional frameworks to any targets that link with the
|
||||
ZBarSDK. You should set the first three to use weak references and
|
||||
configure an appropriate deployment target if you still need to support
|
||||
iOS 3:
|
||||
|
||||
* :file:`AVFoundation.framework` (weak)
|
||||
* :file:`CoreMedia.framework` (weak)
|
||||
* :file:`CoreVideo.framework` (weak)
|
||||
* :file:`QuartzCore.framework`
|
||||
* :file:`libiconv.dylib`
|
||||
|
||||
If you check "Link Binary With Libraries" for the target(s), you should see
|
||||
all of these frameworks followed by :file:`libzbar.a`.
|
||||
|
||||
.. note::
|
||||
|
||||
Link order may be important for some versions of Xcode; the referenced
|
||||
libraries should be listed *before* :file:`libzbar.a` in the link order.
|
||||
|
||||
4. Import the SDK header from your prefix header to make the barcode reader
|
||||
APIs available::
|
||||
|
||||
#import "ZBarSDK.h"
|
||||
|
||||
Proceed to :doc:`camera` or :doc:`picker` to learn about using the reader APIs
|
||||
to scan barcodes. Use the :doc:`apiref` for specific interface details.
|
||||
|
||||
|
||||
Upgrading from an Older Version
|
||||
-------------------------------
|
||||
|
||||
If you are using an older version of the *SDK* (NB, skip to the next section
|
||||
if you are currently using Mercurial), upgrading is straightforward:
|
||||
|
||||
1. Delete the current ZBarSDK group from your project. You should choose
|
||||
to delete the files if you copied them into your project.
|
||||
2. Drag the new ZBarSDK from the DMG into your project.
|
||||
|
||||
Clean out and rebuild your project with the new version.
|
||||
|
||||
|
||||
Upgrading a Pre-SDK Integration
|
||||
-------------------------------
|
||||
|
||||
If your project was using the library directly from the Mercurial repository,
|
||||
before the SDK was introduced, there are a few incompatibilities that you must
|
||||
resolve in order to upgrade. Don't worry - all of your source stays the same,
|
||||
you just need to update how the library is included in the project and how the
|
||||
headers are imported.
|
||||
|
||||
Switching to the Binary Distribution
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This approach is recommended - the binary releases provide you with a stable
|
||||
development platform, isolating you from temporary instability and transient
|
||||
problems that may occur at the bleeding edge.
|
||||
|
||||
The first task is to reverse the previous ZBar integration:
|
||||
|
||||
1. Remove the reference to zbar.xcodeproj from your project.
|
||||
2. Remove any :file:`zbar-*` files from your Resources.
|
||||
3. In the target build settings, remove any "Header Search Paths" that
|
||||
reference zbar.
|
||||
4. Remove any references to zbar headers in your :file:`prefix.pch` or source
|
||||
files.
|
||||
|
||||
Now just continue with the `integration`_ instructions above and you should be
|
||||
back up and running!
|
||||
|
||||
Continuing with Mercurial
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Alternatively, you may still prefer to select Mercurial revisions. You have a
|
||||
few choices for this:
|
||||
|
||||
* You may build your own ZBarSDK and copy/link it into your project. This is
|
||||
the same as `Switching to the Binary Distribution`_, except that you use
|
||||
your own version of the SDK. In this case you need to manually rebuild the
|
||||
SDK when you update it.
|
||||
* You may leave zbar.xcodeproj as a project dependency and pull the SDK into
|
||||
your project. This is not well tested, so ymmv.
|
||||
* You may leave zbar.xcodeproj as a project dependency and just link libzbar.a
|
||||
into your project, as before. You will need to update the target dependency
|
||||
(the library target changed names to libzbar) and add the
|
||||
:file:`iphone/include/ZBarSDK` directory to "Header Search Paths"
|
||||
|
||||
In any case, you should remove the references to the zbar headers from
|
||||
:file:`prefix.pch` (or your source files) and replace them with::
|
||||
|
||||
#import "ZBarSDK.h"
|
||||
187
iphone/doc/licensing.rst
Normal file
187
iphone/doc/licensing.rst
Normal file
@ -0,0 +1,187 @@
|
||||
Licensing the Library
|
||||
=====================
|
||||
|
||||
First of all, the big disclaimer:
|
||||
|
||||
.. warning::
|
||||
|
||||
We are *not* lawyers; we cannot help you decide if you should use the
|
||||
library or how to apply the license, only your lawyer can advise you
|
||||
concerning legal matters.
|
||||
|
||||
That said, it should also be noted that we have neither the resources (time,
|
||||
cash, etc) nor the patience to enforce the license (at all); the reality is
|
||||
that all of this is left to your discretion.
|
||||
|
||||
If you prefer to leave the lawyers out of it, the rest of this section will
|
||||
help you apply the license to your application.
|
||||
|
||||
|
||||
Licensing FAQ
|
||||
-------------
|
||||
|
||||
Can I use this library with my proprietary (closed source) application?
|
||||
Yes, that is our intent and we do not believe there is any problem
|
||||
regarding the license.
|
||||
|
||||
Will I need to open source my entire app?
|
||||
No, it is not required by the license.
|
||||
|
||||
Will I need to distribute all of my "object files" on the App Store?
|
||||
No, this is also not required by the license, although you should offer to
|
||||
provide them upon request. See below for more detail.
|
||||
|
||||
But I read somewhere that "iPhone apps may not use LGPL code"?
|
||||
That statement is an over-generalization that does not apply in this case.
|
||||
Most likely your source is either:
|
||||
|
||||
* referring to the GPL, which is significantly different from the
|
||||
*L*\ GPL
|
||||
* referring to a different version of the LGPL; we intentionally use
|
||||
version 2.1, which has specific static linking exceptions.
|
||||
* not a lawyer either and too lazy to read the whole license
|
||||
|
||||
Basically, if you leverage the appropriate sections of the license, it
|
||||
should be fully compatible with the App Store restrictions and
|
||||
requirements.
|
||||
|
||||
This is too complicated, can I just pay for an easier license?
|
||||
No, it is not possible. There are multiple problems with this approach,
|
||||
some brief highlights:
|
||||
|
||||
* Most open source projects (including this one) do not have a single
|
||||
author. Tracking down every contributor and getting their approval could
|
||||
be quite a challenge.
|
||||
* The license is meant to protect users' rights to the software. Giving
|
||||
you special treatment bypasses the protection we offered them,
|
||||
effectively revoking their rights. This would be a violation of their
|
||||
trust and completely defeats the purpose of the license.
|
||||
|
||||
You may think of this as the "price" you pay for using our open source
|
||||
library. If you want to make your life easier, you should be petitioning
|
||||
Apple for shared library support...
|
||||
|
||||
What if you add a clause that lets me do whatever I want?
|
||||
No, also not possible. In addition to the problems mentioned above, there
|
||||
are even more problems with this:
|
||||
|
||||
* Sourceforge requires an OSI approved license for hosting our project;
|
||||
an altered license would no longer be approved.
|
||||
* Again we are not lawyers and therefore not qualified to change the
|
||||
license, we would have to pay one of those slimy buggers to do it.
|
||||
|
||||
Do I need to add an "about" dialog to display your copyright/license?
|
||||
No, not as such. We won't discourage you from plugging the library if you
|
||||
like, but it is not a requirement. You should think of our license as a
|
||||
supplement to your own software license, therefore it is appropriate to
|
||||
display it where (and only where) you display your own:
|
||||
|
||||
* If you follow Apple's recommendation, the App Store is the only place
|
||||
that the user accesses your license, so it should also be the only place
|
||||
where the library supplement is available.
|
||||
* If your app already has some kind of "about" view that displays your
|
||||
copyright/license information, it is also appropriate to display the same
|
||||
information for the library.
|
||||
|
||||
Do I need to include the entire library in my application bundle?
|
||||
No, it is not necessary:
|
||||
|
||||
* If you have not modified the library, it is sufficient to provide a link
|
||||
to the project and the version information.
|
||||
* If you are using a modified version, you may provide a link to download
|
||||
that instead of including it in the bundle.
|
||||
|
||||
|
||||
Modifications
|
||||
-------------
|
||||
|
||||
What is a "modification"? Again, we leave it to your discretion with this
|
||||
guidance:
|
||||
|
||||
* If you use the distributed binary SDK you have certainly not modified the
|
||||
library.
|
||||
* If you are working from Mercurial, *any* change you have made to the
|
||||
"source code" of the library is a modification, it does not matter how
|
||||
trivial. You can see what changes have been made by running
|
||||
``hg status -mard``; if this command outputs anything, you have modified
|
||||
the library.
|
||||
|
||||
If you find that you have made changes to the library, you should carefully
|
||||
consider how far you want to proceed down that path. Once you publish your
|
||||
changes you have created a "fork" of the project which you now need to
|
||||
maintain. Are you prepared to merge every time the library is updated?
|
||||
|
||||
If your change adds a useful feature to the library, we absolutely encourage
|
||||
you to submit patches. Assuming you can get your patch into the project, then
|
||||
you will no longer need to use a modified version! When submitting patches,
|
||||
ensure that your changes are appropriate for all of our users. Specifically,
|
||||
we are not interested in patches that simply hack up the library to work the
|
||||
way you want. Compare a patch that changes the default behavior to your
|
||||
preference (probably not acceptable), to a patch that adds a new configuration
|
||||
to support the feature you have added (probably fine).
|
||||
|
||||
|
||||
Object File Distribution
|
||||
------------------------
|
||||
|
||||
Section 6 of the LGPL v2.1 specifically permits static linking with the
|
||||
library. If your project is not open source, this section does require that
|
||||
you make your object files available to your users. The intent, as indicated
|
||||
in the license, is that a user who has obtained your software may exercise
|
||||
their right to modify the library and then re-link their modified version into
|
||||
your application.
|
||||
|
||||
We recommend that you apply Subsection 6c, which only requires that you make a
|
||||
written offer to provide the object files. Now...if you consider the actual
|
||||
utility of this mechanism - that it is only applicable to developers, and only
|
||||
those with in depth knowledge of the tools, the time required for development
|
||||
- all to have a new barcode reader in a specific version of your application
|
||||
that only they can use, the reality is that no one is going to request this.
|
||||
You probably should not even waste time preparing for it until a request is
|
||||
made.
|
||||
|
||||
Additionally, to avoid "casual requests" from nefarious types that just want
|
||||
to inconvenience you, also consider charging a fee for the distribution of
|
||||
this material (as permitted by the license); just add up the cost of burning
|
||||
and shipping a disk. If this cost is "large" compared to the price of your
|
||||
app, the likelyhood of a request is reduced even further.
|
||||
|
||||
|
||||
Using the Unmodified Library
|
||||
----------------------------
|
||||
|
||||
Applying the license in this case is somewhat simpler. These are the basic
|
||||
steps you can follow:
|
||||
|
||||
1. Verify that the rest of your software license is compatible with the LGPL.
|
||||
You cannot use the library if they are incompatible.
|
||||
|
||||
For those using the default App Store license, we have reviewed this and
|
||||
believe it is compatible with the LGPL.
|
||||
|
||||
2. At the end of your license text, in an annex or supplement, start by
|
||||
declaring your use of the library and offering a link to the project.
|
||||
Something like this:
|
||||
|
||||
This software uses the open source ZBar Barcode Reader library, version
|
||||
|version|, which is available from http://zbar.sourceforge.net/iphone
|
||||
|
||||
If you built your own version of the library, replace the version callout
|
||||
with eg, "cloned from Mercurial revision xxxxxxxx"
|
||||
|
||||
3. Then append the contents of the text file COPYING, included with the
|
||||
library. This is all of the copyright information for the library.
|
||||
|
||||
4. Then append the contents of the text file LICENSE, also included with the
|
||||
library. This is just the LGPL version 2.1 which you may also obtain from
|
||||
http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
|
||||
|
||||
5. You may choose to make the written offer for the object files explicit.
|
||||
Provide some text and whatever link or email address is appropriate.
|
||||
|
||||
|
||||
Using a Modified Library
|
||||
------------------------
|
||||
|
||||
We intentionally leave this option vague and force you to refer to the license
|
||||
as an underhanded way of encouraging you to contribute back to the project ;)
|
||||
435
iphone/doc/optimizing.rst
Normal file
435
iphone/doc/optimizing.rst
Normal file
@ -0,0 +1,435 @@
|
||||
Optimizing the Reader
|
||||
=====================
|
||||
|
||||
As good as the iPhone performance is for a mobile device, the reality from an
|
||||
image processing perspective is that it represents a lower performance target.
|
||||
While the default configuration of the iPhone reader has been carefully tuned
|
||||
for the general case, you can often obtain much better results if you optimize
|
||||
for your specific application.
|
||||
|
||||
.. note::
|
||||
|
||||
Performance is a complex topic. The only way to tune performance is by
|
||||
changing settings and comparing measured results. If you are not
|
||||
comfortable with the concepts presented here, it is recommended that you
|
||||
leave the settings at the defaults and avoid compromising reliability.
|
||||
|
||||
Performance of the barcode reader is generally evaluated by two factors:
|
||||
|
||||
* The **latency** - how quickly it "recognizes" a barcode. Specifically this
|
||||
is the time from when the user puts a barcode in the frame or selects an
|
||||
image until a response is indicated back to the them.
|
||||
|
||||
* The **reliability** - it does not matter how quickly an image is scanned if
|
||||
an incorrect result is returned. That may seem obvious, but bad decodes
|
||||
*are* possible and you need to keep this in mind when changing settings that
|
||||
affect the reliability of the reader.
|
||||
|
||||
Basically our goal is to optimize the latency without sacrificing reliability.
|
||||
There are several factors that contribue to latency:
|
||||
|
||||
* The **quality** of the barcode image. Quality includes the available
|
||||
resolution, focus, lighting, noise, etc. We have more control over some of
|
||||
these than others.
|
||||
|
||||
* The **camera**. When scanning from the camera, the time for the
|
||||
autoexposure and autofocus to converge on an image that can be decoded is a
|
||||
significant contribution to the overall latency.
|
||||
|
||||
* The **frame rate** of the reader - this translates to the time it takes the
|
||||
scanner to process an image.
|
||||
|
||||
* The **effort level** of the reader - some of the available settings control
|
||||
"how hard" the reader tries to find barcodes in each frame.
|
||||
|
||||
* The **delegate latency** - the time spent in your application after a
|
||||
barcode has been detected until the user is notified.
|
||||
|
||||
Most of these factors are interrelated. We will discuss those we can control
|
||||
in detail, as well the settings you use to affect them. Then we will provide
|
||||
a few specific case examples.
|
||||
|
||||
|
||||
Measuring Performance
|
||||
---------------------
|
||||
|
||||
Subjective response times are a good place to start (does it "feel" responsive
|
||||
to you?), and possibly the only way to evaluate the overall experience, but to
|
||||
compare incremental changes to interrelated settings and have meaningful
|
||||
performance discussions with others, we need a more quantitative approach.
|
||||
|
||||
The :func:`mach_absolute_time` function is a good tool for accurately
|
||||
measuring small delays. Research this function and learn how to apply it. As
|
||||
when measuring any real-world value, keep in mind that some variance is to be
|
||||
expected - even if you perform exactly the same operation multiple times, you
|
||||
will not see exactly the same measurement. You should collect several
|
||||
samples, discard any obvious outliers, and average the remaining measurements.
|
||||
|
||||
One way that the overall reader latency may be evaluated is by manually
|
||||
marking the time when the barcode is presented to the reader. Add a control
|
||||
to your overlay that captures the start time when tapped and compare this to
|
||||
the end time, just before your delegate returns.
|
||||
|
||||
The reader continually monitors the frame rate at which it is running. The
|
||||
measured value may be displayed for debugging purposes by enabling the
|
||||
:member:`~ZBarReaderView::showsFPS` property. The readertest example does
|
||||
this and also provides control over many of the available settings, so you can
|
||||
quickly test how each setting affects the frame rate. You should target your
|
||||
optimization efforts to achieve a frame rate of at least 8-10fps, although
|
||||
12-15fps is preferable.
|
||||
|
||||
You can measure the latency of your delegate using :func:`mach_absolute_time`.
|
||||
The measured value should be less than about 100ms, the smaller the better, to
|
||||
avoid noticeable lag.
|
||||
|
||||
The readertest is a good tool for testing the performance of the reader. You
|
||||
can tune the settings appropriately for your application and evaluate the
|
||||
effect each change has on the performance.
|
||||
|
||||
|
||||
Delegate Latency
|
||||
----------------
|
||||
|
||||
This latency contributor is the easiest for you to effect (and sometimes the
|
||||
easiest to overlook). Your delegate method should update the interface -
|
||||
dismiss the controller or update your overlay to indicate success - and
|
||||
*nothing* else. All other processing should be deferred until after the
|
||||
animations have started.
|
||||
|
||||
|
||||
Image Quality
|
||||
-------------
|
||||
|
||||
Resolution
|
||||
^^^^^^^^^^
|
||||
|
||||
One might think that "more is better" in terms of resolution, but this is not
|
||||
necessarily the case. Given average image quality, the ideal resolution for
|
||||
scanning is right around three pixels per barcode "module" (the width of the
|
||||
smallest bar or space). Note that this measure is not an absolute image size
|
||||
or even a measure of the physical dimensions represented by a pixel sample, it
|
||||
*only* describes the sampled size of the barcode in the image.
|
||||
|
||||
As the resolution decreases below about two pixels per module, edge fidelity
|
||||
is lost and the bars and spaces start to merge together, making it impossible
|
||||
(for this library) to scan. This affects the density (feature size) and
|
||||
maximum size (data capacity) of the barcodes that can be detected.
|
||||
Conversely, as the resolution increases above about 4 pixels per module, noise
|
||||
can interfere with the edge detection and images will take longer to process.
|
||||
|
||||
Other quality factors, such as poor focus, bad lighting or even excessive
|
||||
noise, can increase (or decrease) the resolution requirement.
|
||||
|
||||
When scanning from the camera, the reader defaults to 640x480, which is good
|
||||
for most applications. On newer devices, you can increase this using a capture
|
||||
:member:`~ZBarReaderView::session` preset. Some older devices do not have a
|
||||
higher resolution option available.
|
||||
|
||||
For scanning images, you can use
|
||||
:member:`~ZBarReaderController::maxScanDimension` to control the scaled size
|
||||
of the converted image, or resort to converting them yourself.
|
||||
|
||||
If you want to read long linear barcodes or dense 2-D symbols, you will
|
||||
probably want to increase the resolution by adjusting these settings.
|
||||
|
||||
Keep in mind that more pixels will take longer to scan, refer to the `frame
|
||||
rate`_ discussion for ways to compensate.
|
||||
|
||||
Focus
|
||||
^^^^^
|
||||
|
||||
Ideally we would fix the focus at a calculated optimum distance and optimize
|
||||
the aperture selection to maximize the depth of field. Unfortunately the APIs
|
||||
do not currently give us control over any of these settings, the best we can
|
||||
do (as of iOS 4) is continuous auto-focus mode - this mode is configured by
|
||||
the reader automatically. It can still take the device as long as 1-2 seconds
|
||||
to find the appropriate macro focus setting, but again, there is currently no
|
||||
way to reduce this delay.
|
||||
|
||||
Lighting and Exposure
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
An image that is too bright or overexposed can completely wash out any
|
||||
barcodes. An image that is too dark or underexposed will not provide
|
||||
sufficient contrast for the scanner. Low light levels also tend to produce
|
||||
noisier images, possibly because the driver uses a faster "ISO" setting to
|
||||
compensate for the lighting.
|
||||
|
||||
The camera defaults to continuous automatic exposure and white balance. Since
|
||||
there are no other useful values, the reader leaves these unchanged from their
|
||||
default setting.
|
||||
|
||||
For some devices, the "torch" can be enabled to provide additional
|
||||
illumination for the camera in low-light conditions. The reader sets the
|
||||
torch to automatic by default, so it should turn on only when needeed...
|
||||
There have been some reports that the torch turns on inappropriately, washing
|
||||
out the image. If you find that this occurs, you should instead set the
|
||||
:member:`~ZBarReaderView::torchMode` property of the :class:`ZBarReaderView`
|
||||
to ``Off``.
|
||||
|
||||
For scanning images from another source, you are again stuck with the
|
||||
available image quality. If you have any control over the image source, you
|
||||
should do what you can to fix quality problems there.
|
||||
|
||||
Noise
|
||||
^^^^^
|
||||
|
||||
Some level of noise is filtered by the reader, but excessive noise levels
|
||||
create additional edges in the image which corrupt barcodes and increase
|
||||
scanning time (decreasing the frame rate).
|
||||
|
||||
As mentioned with `lighting and exposure`_, noise mostly becomes a problem
|
||||
when the light-level is too low, but high-resolution images may also increase
|
||||
exposure to sensor noise.
|
||||
|
||||
We compensate for noise by *reducing* the `resolution`_ from the sensor
|
||||
maximum. Scaling the image down has the effect of averaging several pixels
|
||||
into one value, filtering out the high-frequency noise component.
|
||||
|
||||
|
||||
Frame Rate
|
||||
----------
|
||||
|
||||
The time it takes to scan and decode an image/frame is roughly proportional to
|
||||
the number of pixels that are processed. The number and type of enabled
|
||||
symbologies and image noise can also affect the processing time.
|
||||
|
||||
We have several knobs available that affect the frame rate. Most of these are
|
||||
geared toward reducing the number of image pixels that are scanned.
|
||||
|
||||
Decrease the Resolution
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Adjusting the resolution of the image is an easy way to quickly reduce the
|
||||
number of pixels. Smaller images also mean there is less data to carry
|
||||
around, which helps performance in other ways. For example, reducing each
|
||||
image dimension by 30% (eg, from 640x480 to 448x336) will about double the
|
||||
speed of the reader (to a point). [FIXME verify!]
|
||||
|
||||
Adjusting the resolution is `described above <resolution>`_. As mentioned
|
||||
there, reducing the resolution will negatively impact the minimum feature size
|
||||
and maximum barcode size that can be scanned, but it will help filter noise.
|
||||
|
||||
Crop the Scan Region
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
It may not always be necessary for an application to scan all the way to the
|
||||
edges of the image. By cropping the scan area, you can get most of the
|
||||
benefits of reduced resolution without sacrificing the minimum feature size.
|
||||
Cropping will also not affect image noise, but similar to decreasing the
|
||||
resolution, it does affect the maximum size barcode that can be scanned.
|
||||
|
||||
For all cases you set the crop rectangle
|
||||
:class:`~ZBarReaderViewController::scanCrop` property. Note that the
|
||||
rectangle provided to the controller is *normalized* across image size and
|
||||
rotation. This means that the coordinates range from 0 to 1 and the axes will
|
||||
be arranged such that the x-axis of the crop rectangle corresponds to the
|
||||
major (longer) image axis.
|
||||
|
||||
Your interface will typically need to indicate the cropped scan area to the
|
||||
user with visual queues. Use the
|
||||
:class:`~ZBarReaderViewController::cameraOverlayView` to provide this.
|
||||
|
||||
By default, the :class:`ZBarReaderView` recognizes a pinch gesture to
|
||||
digitally zoom the preview around the center of the image. This zoom does not
|
||||
affect the resolution of the image, but it does crop the scan region to the
|
||||
visible area. You can also disable the pinch gesture and set the
|
||||
:class:`~ZBarReaderView::zoom` programmatically.
|
||||
|
||||
Limit the Scan Density
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The scanner works by making scan passes across the pixel rows and colums of
|
||||
the image. The density of the passes is configured at the scanner as a pixel
|
||||
stride for each axis. ``ZBAR_CFG_Y_DENSITY`` (``ZBAR_CFG_X_DENSITY``)
|
||||
controls the number of pixel rows (columns) that are skipped between
|
||||
successive horizontal (vertical) scan passes. (Note that "density" is really
|
||||
not a good name for the configuation settings... "stride" might be more
|
||||
appropriate.)
|
||||
|
||||
Decreasing the scan density (by increasing the stride setting) is a great way
|
||||
to limit the processing (increasing the frame rate) without sacrificing scan
|
||||
resolution - each scan pass is still made at full image resolution, there are
|
||||
just fewer passes (less redundancy).
|
||||
|
||||
Setting the stride value to 0 completely disables scanning in that direction.
|
||||
This is very useful when reading linear codes with a visual alignment guide -
|
||||
scanning parallel to the bars is a waste of cycles which may be better applied
|
||||
to support higher resolution or increased density of scans across the symbol.
|
||||
Note that some 2-D symbologies (QR Code) require scans in both directions.
|
||||
|
||||
Setting the stride to a very large value will generate a single scan pass
|
||||
through the center of the image. Note that some symbologies will not be
|
||||
detected without multiple successful passes; it is usually better to combine
|
||||
this setting with cropping to generate a number of closely clustered scan
|
||||
passes in the target area.
|
||||
|
||||
Note that the density also affects the aspect ratio and rotation that can be
|
||||
tolerated. If you set it too large, some barcodes will become more difficult
|
||||
to read.
|
||||
|
||||
In general, 2 to 4 is a good target for the stride setting, unless you have
|
||||
very high or low resolution images.
|
||||
|
||||
Disable unused symbologies
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Limiting the symbologies to the set of interest should provide a small
|
||||
performance boost. It also improves decode reliability - it is impossible to
|
||||
receive an incorrect or unexpected decode result from a symbology that is
|
||||
disabled.
|
||||
|
||||
The reader does support full auto-discrimination among the supported
|
||||
symbologies, but with all of them enabled you may need to compensate elsewhere
|
||||
to get a good frame rate.
|
||||
|
||||
For example, if you are only interested in QR codes, disable the others. The
|
||||
robust way to do this is by disabling *all* symbologies and then reenabling
|
||||
only those you want. This helps isolate you from encountering new symbologies
|
||||
that may be added in future versions of the library until you are ready to
|
||||
handle them::
|
||||
|
||||
[scanner setSymbology: 0
|
||||
config: ZBAR_CFG_ENABLE
|
||||
to: 0];
|
||||
[scanner setSymbology: ZBAR_QRCODE
|
||||
config: ZBAR_CFG_ENABLE
|
||||
to: 1];
|
||||
|
||||
Even if you would like your application to support multiple symbologies, you
|
||||
may consider if there is a way to limit the enabled subset based on the
|
||||
scanning context, etc...
|
||||
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
These examples demonstrate several scenarios for scanning from the camera with
|
||||
automatic capture. You can try them yourself using the readertest. For each
|
||||
example, start with the default settings (by tapping the
|
||||
``ZBarReaderViewController`` class), then enable continuous mode and the
|
||||
custom overlay (by disabling
|
||||
:member:`~ZBarReaderViewController::showsZBarControls`). You should also use
|
||||
a release build and avoid running in the debugger.
|
||||
|
||||
Frame rates are approximate, measured on an iPhone 3GS running iOS 4.0.1 in a
|
||||
well lit room. Two measurements are taken for each sample: the rate with the
|
||||
camera pointed at a blank white page such that it fills the frame, and the
|
||||
rate while continuously decoding the provided example. For best results, it
|
||||
is recommended that you print the examples rather than scanning them from the
|
||||
screen.
|
||||
|
||||
For reference, the base frame rates with default settings are 12fps for a
|
||||
blank white page, 7.5fps for this `basic EAN symbol`_ and 2.2fps for this
|
||||
`basic QR symbol`_.
|
||||
|
||||
.. _`basic EAN symbol`:
|
||||
http://zbar.sf.net/test/ean13/9876543210128.png
|
||||
.. _`basic QR symbol`:
|
||||
http://chart.apis.google.com/chart?cht=qr&chs=512x512&chl=http://zbar.sf.net/iphone
|
||||
|
||||
Long Linear Symbols
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For this example, we will use a relatively `long Code 128 barcode`_.
|
||||
|
||||
.. _`long Code 128 barcode`:
|
||||
http://zbar.sf.net/test/code128/ALPHA.png
|
||||
|
||||
While it should be possible to read this symbol with the default settings, you
|
||||
may notice that it is not very reliable. You will have to stretch the symbol
|
||||
across the entire screen, and even then the default settings will only give
|
||||
you about 1.6 pixels per module, well below the ideal target of 3. To improve
|
||||
these results, we want to maximize scanning resolution for the long image
|
||||
axis.
|
||||
|
||||
1. Disable the default zoom/crop - zoom all the way out by hitting "Scan" and
|
||||
pinching the preview; the frame rate immediately drops to 8fps / 4.8fps.
|
||||
|
||||
We should compensate for this reduction in the frame rate:
|
||||
|
||||
2. Crop the image to a long, skinny rectangle - set the
|
||||
:member:`~ZBarReaderViewController::scanCrop` setting to
|
||||
``{{0, 0.3}, {1, 0.4}}``; The frame rate jumps up to 18fps / 8.7fps.
|
||||
|
||||
3. Disable scans across the short image axis - set the ``CFG_X_DENSITY``
|
||||
setting to 0. The frame rate goes all the way to 30fps / 13fps.
|
||||
|
||||
Since we have plenty of margin with the frame rate, we can minimize the total
|
||||
decode latency by performing more scan passes through the symbol:
|
||||
|
||||
4. Increase the scan density - set the ``CFG_Y_DENSITY`` setting to 1 (13.5fps
|
||||
/ 5fps) or 2 (24fps / 9fps).
|
||||
|
||||
You should now be able to quickly and reliably decode long linear symbols.
|
||||
|
||||
If have a newer device, you may also try increasing the resolution to support
|
||||
even longer symbols. You may have to compensate elsewhere to bring the frame
|
||||
rate back to a reasonable level.
|
||||
|
||||
High Density QR Symbols
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For this example we will use a `version 29 QR Code symbol`_.
|
||||
|
||||
.. _`version 29 QR Code symbol`:
|
||||
http://www.qrcomic.com/images/5.png
|
||||
|
||||
In this case we still want to maximize the resolution, but we also need to
|
||||
increase the scan density to reliably pick up the small finder patterns:
|
||||
|
||||
1. Maximize scan density in both directions - set the ``CFG_X_DENSITY`` and
|
||||
``CFG_Y_DENSITY`` settings both to 1. You should be able to scan the symbol
|
||||
now, although the frame rate drops to 4.5fps / 1fps
|
||||
|
||||
2. Disable the default zoom/crop - zoom all the way out by hitting "Scan" and
|
||||
pinching the preview; the frame rate drops further to 3fps / 0.7fps
|
||||
|
||||
We can compensate somewhat for the reduced frame rate:
|
||||
|
||||
3. Crop the image to a square - set ``scanCrop`` to ``{{0.125, 0}, {.75, 1}}``.
|
||||
This boosts the frame rate slightly to 3.7fps / 0.75fps.
|
||||
|
||||
4. Disable linear symbologies - set the symbologies such that only QR Code is
|
||||
enabled (4fps / 1fps)
|
||||
|
||||
Even though the frame rate is still pretty bad, the QR recognition latency
|
||||
should be acceptable.
|
||||
|
||||
If have an iPhone 4, you may also try increasing the resolution to support
|
||||
even denser QR symbols. You may have to compensate elsewhere to bring the
|
||||
frame rate back to a reasonable level.
|
||||
|
||||
Small DataBar Symbols
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For this example we will use a `DataBar symbol`_ printed with a small feature
|
||||
size, typical of the stickers used to tag produce. Scale it when printing
|
||||
such that the printed dimensions are about 1cm square. This symbol should
|
||||
scan with the default settings, but we will attempt to optimize the scan
|
||||
latency for this case.
|
||||
|
||||
.. _`DataBar symbol`:
|
||||
http://zbar.sf.net/test/databar/0109876543210128-so.png
|
||||
|
||||
As well as high barcode resolution, we also want high density passes in both
|
||||
directions to minimize sensitivity to rotation:
|
||||
|
||||
1. Maximize scan density in both directions - set the ``CFG_X_DENSITY`` and
|
||||
``CFG_Y_DENSITY`` settings both to 1. The frame rate drops to 4.5fps /
|
||||
3fps.
|
||||
|
||||
Compensate for the reduction in frame rate by zooming in on the small symbol,
|
||||
which crops the scanned image. Zooming also helps the user see the small
|
||||
barcode:
|
||||
|
||||
2. Zoom all the way in - hit "Scan" and un-pinch the preview. The frame rate
|
||||
recovers to 11fps / 6.2fps.
|
||||
|
||||
3. Crop the image to a square - set ``scanCrop`` to ``{{0.125, 0}, {0.75, 1}}``
|
||||
(14fps / 7.5fps)
|
||||
|
||||
4. Disable all symbologies except DataBar and DataBar Expanded (14.5fps / 9fps)
|
||||
|
||||
The reader should now be very sensitive to DataBar, even when scanned at an
|
||||
angle.
|
||||
104
iphone/doc/picker.rst
Normal file
104
iphone/doc/picker.rst
Normal file
@ -0,0 +1,104 @@
|
||||
Scanning a User-Selected Image
|
||||
==============================
|
||||
|
||||
Some applications may need the full resolution offered by camera snapshots, or
|
||||
need to scan an image or document from the user's photo library. In these
|
||||
cases you use a :class:`ZBarReaderController`. This reader is a *subclass* of
|
||||
:class:`UIImagePickerController`, and you use it the same way. See the
|
||||
documentation for :class:`UIImagePickerController` for more detais.
|
||||
|
||||
1. Create the reader.
|
||||
|
||||
This is as simple as creating a new :class:`ZBarReaderController`::
|
||||
|
||||
ZBarReaderController *reader = [[ZBarReaderController alloc] init];
|
||||
|
||||
2. Setup a delegate to receive the results.
|
||||
|
||||
The delegate should implement the :class:`ZBarReaderDelegate` protocol,
|
||||
which inherits from :class:`UIImagePickerControllerDelegate`::
|
||||
|
||||
reader.readerDelegate = self;
|
||||
|
||||
3. Configure the reader.
|
||||
|
||||
You will need to set the :member:`~ZBarReaderController::sourceType`
|
||||
appropriately. Aside from the properties of the reader itself, you can
|
||||
configure the decoder via the :member:`~ZBarReaderController::scanner`
|
||||
property::
|
||||
|
||||
if([ZBarReaderController isSourceTypeAvailable:
|
||||
UIImagePickerControllerSourceTypeCamera])
|
||||
reader.sourceType = UIImagePickerControllerSourceTypeCamera;
|
||||
[reader.scanner setSymbology: ZBAR_I25
|
||||
config: ZBAR_CFG_ENABLE
|
||||
to: 0];
|
||||
|
||||
See :doc:`custom` and :doc:`optimizing` for more details.
|
||||
|
||||
4. Present the reader to the user.
|
||||
|
||||
As the reader is a UIImagePickerController, it must be presented modally::
|
||||
|
||||
[self presentModalViewController: reader
|
||||
animated: YES];
|
||||
|
||||
5. Process the results.
|
||||
|
||||
The controller will call the
|
||||
``imagePickerController:didFinishPickingMediaWithInfo:`` method of
|
||||
your delegate for a successful decode (NB *not* every time the user takes a
|
||||
picture or selects an image). The barcode data can be obtained using the
|
||||
:c:data:`ZBarReaderControllerResults` key of the info dictionary. This key
|
||||
will return "something enumerable"; keep in mind that there may be multiple
|
||||
results. You may also retrieve the corresponding image with
|
||||
:c:data:`UIImagePickerControllerOriginalImage` as usual::
|
||||
|
||||
- (void) imagePickerController: (UIImagePickerController*) reader
|
||||
didFinishPickingMediaWithInfo: (NSDictionary*) info
|
||||
{
|
||||
id<NSFastEnumeration> results =
|
||||
[info objectForKey: ZBarReaderControllerResults];
|
||||
UIImage *image =
|
||||
[info objectForKey: UIImagePickerControllerOriginalImage];
|
||||
...
|
||||
|
||||
The ``reader`` parameter will be the actual :class:`ZBarReaderController`
|
||||
(again, a subclass :class:`UIImagePickerController`).
|
||||
|
||||
.. note::
|
||||
|
||||
The delegate method should dismiss the reader and return as soon as
|
||||
possible; any processing of the results should be deferred until later,
|
||||
otherwise the user will experience unacceptable latency between the
|
||||
actual scan completion and the visual interface feedback.
|
||||
|
||||
6. Dismiss the reader.
|
||||
|
||||
Once you have the results you should dismiss the reader::
|
||||
|
||||
[reader dismissModalViewControllerAnimated: YES];
|
||||
|
||||
.. warning::
|
||||
|
||||
It is very important to dismiss from the *reader* (not the presenting
|
||||
controller) to avoid corrupting the interface.
|
||||
|
||||
|
||||
Handling Failure
|
||||
----------------
|
||||
|
||||
It is always possible the user selects/takes an image that does not contain
|
||||
barcodes, or that the image quality is not sufficient for the ZBar library to
|
||||
scan successfully.
|
||||
|
||||
In this case, and if :member:`~ZBarReaderController::showsHelpOnFail` is
|
||||
``YES``, the integrated help controller will automatically be displayed with
|
||||
reason set to ``"FAIL"``.
|
||||
|
||||
Your delegate may also choose to implement the optional
|
||||
``readerControllerDidFailToRead:withRetry:`` method to explicitly handle
|
||||
failures. If the ``retry`` parameter is ``NO``, you *must* dismiss the reader
|
||||
before returning, otherwise you may continue and allow the user to retry the
|
||||
operation. Note that, if it is enabled, the integrated help will be displayed
|
||||
when this delegate method is invoked.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user