From 919d69d73201ad802eb3319f0bfad07233201b48 Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 19 Feb 2007 00:37:11 +0000 Subject: [PATCH 001/328] populate svn with current sources. most of the basic functionality is included and working. still need to combine final decode data, finish addons, etc (see TODO). c++ wrappers are included and tested, but API may need tweaked. zebraimg and zebracam basically working but need cleanup/polish. need to create some basic documentation... --- COPYING.LIB | 504 ++++++++++++++++++++++++++++++++++++++++ INSTALL | 182 +++++++++++++++ Makefile.am | 9 + README | 57 +++++ TODO | 7 + configure.ac | 91 ++++++++ include/zebra.h | 150 ++++++++++++ include/zebra/Decoder.h | 93 ++++++++ include/zebra/Scanner.h | 112 +++++++++ test/Makefile.am | 4 + test/test_decode.c | 145 ++++++++++++ zebra/Makefile.am | 4 + zebra/decoder.c | 456 ++++++++++++++++++++++++++++++++++++ zebra/scanner.c | 206 ++++++++++++++++ zebracam/Makefile.am | 5 + zebracam/zebracam.c | 275 ++++++++++++++++++++++ zebraimg/Makefile.am | 6 + zebraimg/zebraimg.cpp | 97 ++++++++ 18 files changed, 2403 insertions(+) create mode 100644 COPYING.LIB create mode 100644 INSTALL create mode 100644 Makefile.am create mode 100644 README create mode 100644 TODO create mode 100644 configure.ac create mode 100644 include/zebra.h create mode 100644 include/zebra/Decoder.h create mode 100644 include/zebra/Scanner.h create mode 100644 test/Makefile.am create mode 100644 test/test_decode.c create mode 100644 zebra/Makefile.am create mode 100644 zebra/decoder.c create mode 100644 zebra/scanner.c create mode 100644 zebracam/Makefile.am create mode 100644 zebracam/zebracam.c create mode 100644 zebraimg/Makefile.am create mode 100644 zebraimg/zebraimg.cpp diff --git a/COPYING.LIB b/COPYING.LIB new file mode 100644 index 0000000..5ab7695 --- /dev/null +++ b/COPYING.LIB @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..b42a17a --- /dev/null +++ b/INSTALL @@ -0,0 +1,182 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..6ca0b17 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,9 @@ +include_HEADERS = include/zebra.h +SUBDIRS = zebra +if HAVE_MAGICK + SUBDIRS += zebraimg +endif +if HAVE_SDL + SUBDIRS += zebracam +endif +SUBDIRS += test #doc diff --git a/README b/README new file mode 100644 index 0000000..483f0c3 --- /dev/null +++ b/README @@ -0,0 +1,57 @@ +ZEBRA BARCODE READER +==================== + +Zebra is a layered barcode (EAN/UPC) scanning and decoding library. +It includes application front ends for decoding captured bar code +images and using a video device (eg, webcam) as a bar code scanner. +The library features a fast streaming interface with a minimal memory +footprint + +Check the Zebra home page for the latest release, mailing lists, etc. + http://zebra.sourceforge.net/ + +License information can be found in 'COPYING.LIB'. + + +BUILDING +======== + +See 'INSTALL' for generic configuration and build instructions. + +The scanner/decoder library itself only requires a few standard +library functions which should be avilable almost anywhere (and if +they're not, you probably already know how to mock something up) + +The zebraimg program uses ImageMagick to read image files, you can +obtain it from + http://www.imagemagick.org/ + +The zebracam program uses the Simple DirectMedia Layer (SDL) to +display video. SDL is available from + http://www.libsdl.org/ + +zebracam also uses the video4linux API (v4l1) to access the video +device. This interface is part of the kernel. More information is +available at + http://linuxtv.org/v4lwiki/ + +If required libraries are not available the corresponding program will +not be built. + + +RUNNING +======= + +'make install' will install the library and application programs. Run +'zebracam' to start the video scanner. use 'zebraimg barcode.jpg' to +decode a saved image file. + + +REPORTING BUGS +============== + +Bugs can be reported on the sourceforge project page + http://www.sourceforge.net/projects/zebra/ + +Please include the Zebra version number and a detailed description of +the problem. diff --git a/TODO b/TODO new file mode 100644 index 0000000..a428bc7 --- /dev/null +++ b/TODO @@ -0,0 +1,7 @@ + * finish addon decoding + * combine partial decodes into final result + * soft reset when partial mismatches same slot + * parity checking + * add scan patterns to zebraimg & zebracam + * via some kind of reusable library API? + * documentation diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..4069810 --- /dev/null +++ b/configure.ac @@ -0,0 +1,91 @@ +# Process this file with autoconf to produce a configure script. +AC_PREREQ([2.60]) +AC_INIT([zebra], [0.1], [spadix@users.sourceforge.net]) +AM_INIT_AUTOMAKE([-Wall -Werror foreign]) +AC_CONFIG_HEADERS([include/config.h]) +AC_CONFIG_SRCDIR(zebra/scanner.c) + +AC_PROG_CC +AC_PROG_CXX +AC_PROG_LIBTOOL +AC_PROG_RANLIB + +AC_ARG_WITH([imagemagick], + [AS_HELP_STRING([--without-imagemagick], + [disable support for scanning images using ImageMagick])], + [], + [with_imagemagick=check]) + +AC_CHECK_TOOL([MAGICK_CONFIG], [Magick++-config]) +AS_IF([test "x$with_imagemagick" != "xno" && \ + test "x$with_imagemagick" != "xcheck" && \ + test "x$MAGICK_CONFIG" = "x:"], + [AC_MSG_FAILURE( + [--with-imagemagick was given, but test for imagemagick failed])]) +AM_CONDITIONAL([HAVE_MAGICK], [test "x$MAGICK_CONFIG" != "x:"]) +AC_SUBST([MAGICK_CPPFLAGS], [`$MAGICK_CONFIG --cppflags`]) +AC_SUBST([MAGICK_CXXFLAGS], [`$MAGICK_CONFIG --cxxflags`]) +AC_SUBST([MAGICK_LDFLAGS], [`$MAGICK_CONFIG --ldflags`]) +AC_SUBST([MAGICK_LIBS], [`$MAGICK_CONFIG --libs`]) + +AC_ARG_ENABLE([video], + [AS_HELP_STRING([--disable-video], + [exclude video scanner application])], + [], + [enable_video=check]) + +AC_CHECK_HEADER([linux/videodev.h], + [ if test "x$enable_video" = "xcheck"; then enable_video="yes"; fi ], + [ if test "x$enable_video" != "xno" && \ + test "x$enable_video" != "xcheck"; then + AC_MSG_FAILURE( + [--enable-video was given, but test for video support failed]) + fi + ]) + +AC_ARG_WITH([sdl], + [AS_HELP_STRING([--without-sdl], + [disable support for live video display using SDL])], + [], + [ if test "x$enable_video" != "xno"; then + with_sdl=check + else + with_sdl=no + fi + ]) + +AC_CHECK_TOOL([SDL_CONFIG], [sdl-config]) +AS_IF([test "x$enable_video" = "xno"], + [SDL_CONFIG=":"], + [test "x$with_sdl" != "xno" && \ + test "x$with_sdl" != "xcheck" && \ + test "x$SDL_CONFIG" = "x:"], + [AC_MSG_FAILURE( + [--with-sdl was given, but test for SDL failed])]) +AM_CONDITIONAL([HAVE_SDL], [test "x$SDL_CONFIG" != "x:"]) +AC_SUBST([SDL_CPPFLAGS], [`$SDL_CONFIG --cflags`]) +AC_SUBST([SDL_LIBS], [`$SDL_CONFIG --libs`]) + +AC_PATH_X + +AC_HEADER_ASSERT +AC_CHECK_HEADERS([fcntl.h inttypes.h stdlib.h string.h sys/ioctl.h sys/time.h]) + +AC_TYPE_INT32_T +AC_TYPE_UINT32_T +AC_TYPE_UINT8_T + +AC_C_CONST +AC_C_INLINE + +AC_FUNC_MMAP +AC_CHECK_FUNCS([memset atexit setenv]) + +AC_CONFIG_FILES([ + Makefile + zebra/Makefile + zebraimg/Makefile + zebracam/Makefile + test/Makefile +]) +AC_OUTPUT diff --git a/include/zebra.h b/include/zebra.h new file mode 100644 index 0000000..2b950da --- /dev/null +++ b/include/zebra.h @@ -0,0 +1,150 @@ +/*------------------------------------------------------------------------ + * Copyright 2007 (c) Jeff Brown + * + * This file is part of the Zebra Barcode Library. + * + * The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zebra + *------------------------------------------------------------------------*/ +#ifndef _ZEBRA_H_ +#define _ZEBRA_H_ + +#ifdef __cplusplus +namespace zebra { + extern "C" { +#endif + + +/* "color" of element: bar or space */ +typedef enum zebra_color_e { + ZEBRA_SPACE = 0, /* light area or space between bars */ + ZEBRA_BAR = 1, /* dark area or colored bar segment */ +} zebra_color_t; + +/* decoded symbol type */ +typedef enum zebra_symbol_type_e { + ZEBRA_NONE = 0, /* no symbol decoded */ + ZEBRA_PARTIAL = 1, /* intermediate status */ + ZEBRA_EAN8 = 8, /* EAN-8 */ + ZEBRA_UPCE = 11, /* UPC-E */ + ZEBRA_UPCA = 12, /* UPC-A */ + ZEBRA_EAN13 = 13, /* EAN-13 */ + ZEBRA_ADDON2 = 0x20, /* 2-digit add-on flag */ + ZEBRA_ADDON5 = 0x50, /* 5-digit add-on flag */ +} zebra_symbol_type_t; + + +/*------------------------------------------------------------*/ +/* high-level bar width stream decoder interface + * identifies symbols and extracts encoded data + */ + +/* opaque decoder object */ +struct zebra_decoder_s; +typedef struct zebra_decoder_s zebra_decoder_t; + +/* constructor */ +extern zebra_decoder_t *zebra_decoder_create(); + +/* destructor */ +extern void zebra_decoder_destroy(zebra_decoder_t *decoder); + +/* clear all decoder state, including any partial symbols */ +extern void zebra_decoder_reset(zebra_decoder_t *decoder); + +/* mark start of a new scan pass, + * clears any intra-symbol state and resets color to SPACE + * any partially decoded symbol state is retained + */ +extern void zebra_decoder_new_scan(zebra_decoder_t *decoder); + +/* process next bar/space width from input stream + * width is in arbitrary relative units + * first value of scan is SPACE width, alternating from there. + * returns appropriate symbol type if width completes + * decode of a symbol (data is available for retrieval) + * returns ZEBRA_PARTIAL as a hint if part of a symbol was decoded + * returns ZEBRA_NONE (0) if no new symbol data is available + */ +extern zebra_symbol_type_t zebra_decode_width(zebra_decoder_t *decoder, + unsigned width); + +/* returns last decoded data, + * or NULL if no new data available. + * data buffer is maintained by library, + * contents are only valid between non-0 return from zebra_decode_width + * and next library call + */ +extern const char *zebra_decoder_get_data(const zebra_decoder_t *decoder); + + +/*------------------------------------------------------------*/ +/* low-level intensity sample stream scanner interface + * identifies "bar" edges and measures width between them + * optionally passes to bar width decoder + */ + +/* opaque scanner object */ +struct zebra_scanner_s; +typedef struct zebra_scanner_s zebra_scanner_t; + +/* constructor + * if decoder is non-NULL it will be attached to scanner + * and called automatically at each new edge + * current color is initialized to SPACE + * (so an initial BAR->SPACE transition may be discarded) + */ +extern zebra_scanner_t *zebra_scanner_create(zebra_decoder_t *decoder); + +/* destructor */ +extern void zebra_scanner_destroy(zebra_scanner_t *scanner); + +extern void zebra_scanner_reset(zebra_scanner_t *scanner); +extern void zebra_scanner_new_scan(zebra_scanner_t *scanner); + +/* process next sample intensity value (y) + * intensity is in arbitrary relative units + * if decoder is attached, returns result of zebra_decode_width() + * otherwise returns non-0 (ZEBRA_PARTIAL) when new edge is detected + * and 0 (ZEBRA_NONE) if no new edge is detected + */ +extern zebra_symbol_type_t zebra_scan_y(zebra_scanner_t *scanner, + int y); + +/* process next sample from RGB (or BGR) triple */ +static inline zebra_symbol_type_t zebra_scan_rgb24 (zebra_scanner_t *scanner, + unsigned char *rgb) +{ + return(zebra_scan_y(scanner, rgb[0] + rgb[1] + rgb[2])); +} + +/* retrieve last scanned width */ +extern unsigned zebra_scanner_get_width(const zebra_scanner_t *scanner); + +/* retrieve last scanned color */ +extern zebra_color_t zebra_scanner_get_color(const zebra_scanner_t *scanner); + + +#ifdef __cplusplus + } +} + +# include "zebra/Decoder.h" +# include "zebra/Scanner.h" +#endif + +#endif diff --git a/include/zebra/Decoder.h b/include/zebra/Decoder.h new file mode 100644 index 0000000..03b9d52 --- /dev/null +++ b/include/zebra/Decoder.h @@ -0,0 +1,93 @@ +//------------------------------------------------------------------------ +// Copyright 2007 (c) Jeff Brown +// +// This file is part of the Zebra Barcode Library. +// +// The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free +// Software Foundation, Inc., 51 Franklin St, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// http://sourceforge.net/projects/zebra +//------------------------------------------------------------------------ +#ifndef _ZEBRA_DECODER_H_ +#define _ZEBRA_DECODER_H_ + +#ifndef _ZEBRA_H_ +# error "include zebra.h in your application, **not** zebra/Decoder.h" +#endif + +#include + +namespace zebra { + +class Decoder { + public: + Decoder () + { + _decoder = zebra_decoder_create(); + } + + ~Decoder () + { + zebra_decoder_destroy(_decoder); + } + + void reset () + { + zebra_decoder_reset(_decoder); + } + + void new_scan () + { + zebra_decoder_new_scan(_decoder); + } + + zebra_symbol_type_t decode_width (unsigned width) + { + _type = zebra_decode_width(_decoder, width); + return(_type); + } + + Decoder& operator<< (unsigned width) + { + _type = zebra_decode_width(_decoder, width); + return(*this); + } + + zebra_symbol_type_t get_type () const + { + return(_type); + } + + const char *get_data_chars() const + { + return(zebra_decoder_get_data(_decoder)); + } + + const std::string& get_data_string() const + { + ((Decoder*)this)->_data = zebra_decoder_get_data(_decoder); + return(_data); + } + + private: + friend class Scanner; + zebra_decoder_t *_decoder; + zebra_symbol_type_t _type; + std::string _data; +}; + +} + +#endif diff --git a/include/zebra/Scanner.h b/include/zebra/Scanner.h new file mode 100644 index 0000000..b0bfe8a --- /dev/null +++ b/include/zebra/Scanner.h @@ -0,0 +1,112 @@ +//------------------------------------------------------------------------ +// Copyright 2007 (c) Jeff Brown +// +// This file is part of the Zebra Barcode Library. +// +// The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free +// Software Foundation, Inc., 51 Franklin St, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// http://sourceforge.net/projects/zebra +//------------------------------------------------------------------------ +#ifndef _ZEBRA_SCANNER_H_ +#define _ZEBRA_SCANNER_H_ + +#ifndef _ZEBRA_H_ +# error "include zebra.h in your application, **not** zebra/Scanner.h" +#endif + +#include + +namespace zebra { + +class Scanner { + public: + Scanner () + { + _scanner = zebra_scanner_create(NULL); + } + + Scanner (Decoder& decoder) + { + _scanner = zebra_scanner_create(decoder._decoder); + } + + Scanner (Decoder* decoder) + { + _scanner = zebra_scanner_create(decoder->_decoder); + } + + ~Scanner () + { + zebra_scanner_destroy(_scanner); + } + + void reset () + { + zebra_scanner_reset(_scanner); + } + + void new_scan () + { + zebra_scanner_new_scan(_scanner); + } + + zebra_symbol_type_t scan_y (int y) + { + _type = zebra_scan_y(_scanner, y); + return(_type); + } + + Scanner& operator<< (int y) + { + _type = zebra_scan_y(_scanner, y); + return(*this); + } + + zebra_symbol_type_t scan_rgb24 (unsigned char *rgb) + { + _type = zebra_scan_rgb24(_scanner, rgb); + return(_type); + } + + Scanner& operator<< (unsigned char *rgb) + { + _type = zebra_scan_rgb24(_scanner, rgb); + return(*this); + } + + unsigned get_width () const + { + return(zebra_scanner_get_width(_scanner)); + } + + zebra_color_t get_color () const + { + return(zebra_scanner_get_color(_scanner)); + } + + zebra_symbol_type_t get_type () const + { + return(_type); + } + + private: + zebra_scanner_t *_scanner; + zebra_symbol_type_t _type; +}; + +} + +#endif diff --git a/test/Makefile.am b/test/Makefile.am new file mode 100644 index 0000000..7e43a22 --- /dev/null +++ b/test/Makefile.am @@ -0,0 +1,4 @@ +bin_PROGRAMS = test_decode +AM_CPPFLAGS = -I$(srcdir)/../include +AM_CFLAGS = -Wall -Werror +LDADD = ../zebra/libzebra.la diff --git a/test/test_decode.c b/test/test_decode.c new file mode 100644 index 0000000..cf3764b --- /dev/null +++ b/test/test_decode.c @@ -0,0 +1,145 @@ +/*------------------------------------------------------------------------ + * Copyright 2007 (c) Jeff Brown + * + * This file is part of the Zebra Barcode Library. + * + * The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zebra + *------------------------------------------------------------------------*/ + +#include +#include + +#include + +static const unsigned int digits[10] = { + 0x1123, 0x1222, 0x2212, 0x1141, 0x2311, + 0x1321, 0x4111, 0x2131, 0x3121, 0x2113, +}; + +static const unsigned int guard[] = { + 0, 0, + 0x11, /* [2] add-on delineator */ + 0x1117, /* [3] normal guard bars */ + 0x2117, /* [4] add-on guard bars */ + 0x11111, /* [5] center guard bars */ + 0x111111 /* [6] "special" guard bars */ +}; + +static const unsigned char parity_encode[] = { + 0x3f, /* AAAAAA = 0 */ + 0x34, /* AABABB = 1 */ + 0x32, /* AABBAB = 2 */ + 0x31, /* AABBBA = 3 */ + 0x2c, /* ABAABB = 4 */ + 0x26, /* ABBAAB = 5 */ + 0x23, /* ABBBAA = 6 */ + 0x2a, /* ABABAB = 7 */ + 0x29, /* ABABBA = 8 */ + 0x25, /* ABBABA = 9 */ +}; + +zebra_decoder_t *decoder; + +static void encode_junk (int n) +{ + int i; + for(i = 0; i < n; i++) + zebra_decode_width(decoder, 10. * (rand() / (RAND_MAX + 1.))); +} + +#define FWD 1 +#define REV 0 + +static void encode (unsigned int units, + int fwd) +{ + printf(" raw=%x%c\n", units, (fwd) ? '<' : '>'); + if(!fwd) + while(units && !(units >> 0x1c)) + units <<= 4; + + while(units) { + unsigned char w = (fwd) ? units & 0xf : units >> 0x1c; + zebra_decode_width(decoder, w); + if(fwd) + units >>= 4; + else + units <<= 4; + } +} + +static zebra_symbol_type_t encode_ean13 (unsigned char *data) +{ + int i; + unsigned char par = parity_encode[data[0]]; + + printf("------------------------------------------------------------\n" + "encode EAN-13: "); + for(i = 0; i < 13; i++) + printf("%d", data[i]); + printf("(%02x)\n" + " encode start guard:", par); + encode(guard[3], FWD); + for(i = 1; i < 7; i++, par <<= 1) { + printf(" encode %x%d:", (par >> 5) & 1, data[i]); + encode(digits[data[i]], FWD ^ ((par >> 5) & 1)); + } + printf(" encode center guard:"); + encode(guard[5], FWD); + for(; i < 13; i++) { + printf(" encode %x%d:", 0, data[i]); + encode(digits[data[i]], FWD); + } + printf(" encode end guard:"); + encode(guard[3], REV); + + return(0); +} + +int main (int argc, char **argv) +{ + int i; + int rnd_size = 10; /* should be even */ + srand(0xbabeface); + + /* FIXME TBD: + * - random module width (!= 1.0) + * - simulate scan speed variance + * - simulate dark "swelling" and light "blooming" + * - inject parity errors + */ + decoder = zebra_decoder_create(); + + encode_junk(rnd_size); + + unsigned char data[14]; + unsigned int chk = 0; + for(i = 0; i < 12; i++) { + data[i] = (rand() >> 16) % 10; + chk += (i & 1) ? data[i] * 3 : data[i]; + } + data[12] = chk % 10; + data[13] = 0; + + encode_ean13(data); + + encode_junk(rnd_size); + + zebra_decoder_destroy(decoder); + return(0); +} diff --git a/zebra/Makefile.am b/zebra/Makefile.am new file mode 100644 index 0000000..d8b0181 --- /dev/null +++ b/zebra/Makefile.am @@ -0,0 +1,4 @@ +lib_LTLIBRARIES = libzebra.la +AM_CPPFLAGS = -I$(srcdir)/../include +AM_CFLAGS = -Wall -Werror +libzebra_la_SOURCES = scanner.c decoder.c diff --git a/zebra/decoder.c b/zebra/decoder.c new file mode 100644 index 0000000..a577904 --- /dev/null +++ b/zebra/decoder.c @@ -0,0 +1,456 @@ +/*------------------------------------------------------------------------ + * Copyright 2007 (c) Jeff Brown + * + * This file is part of the Zebra Barcode Library. + * + * The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zebra + *------------------------------------------------------------------------*/ + +#include +#ifdef DEBUG_DECODER +# include /* fprintf */ +#endif +#include /* calloc, free */ +#include /* memset */ +#include + +#include "zebra.h" + +#ifdef DEBUG_DECODER +# define dprintf(level, ...) \ + if(level <= DEBUG_DECODER) \ + fprintf(stderr, __VA_ARGS__) +#else +# define dprintf(...) +#endif + +/* convert compact encoded D2E1E2 to character (bit4 is parity) */ +static const char digits[] = { /* E1 E2 */ + 0x06, 0x10, 0x04, 0x13, /* 2 2-5 */ + 0x19, 0x08, 0x11, 0x05, /* 3 2-5 (d2 <= thr) */ + 0x09, 0x12, 0x07, 0x15, /* 4 2-5 (d2 <= thr) */ + 0x16, 0x00, 0x14, 0x03, /* 5 2-5 */ + 0x18, 0x01, 0x02, 0x17, /* E1E2=43,44,33,34 (d2 > thr) */ +}; + +/* partial decode symbol location */ +typedef enum symbol_partial_e { + RIGHT_HALF = 6, + LEFT_HALF = 7, +} symbol_partial_t; + +static const char parity_decode[] = { + 0xf0, /* [xx] BBBBBB = RIGHT half EAN-13 */ + + /* UPC-E check digit encoding */ + 0xff, + 0xff, + 0x0f, /* [07] BBBAAA = 0 */ + 0xff, + 0x1f, /* [0b] BBABAA = 1 */ + 0x2f, /* [0d] BBAABA = 2 */ + 0xf3, /* [0e] BBAAAB = 3 */ + 0xff, + 0x4f, /* [13] BABBAA = 4 */ + 0x7f, /* [15] BABABA = 7 */ + 0xf8, /* [16] BABAAB = 8 */ + 0x5f, /* [19] BAABBA = 5 */ + 0xf9, /* [1a] BAABAB = 9 */ + 0xf6, /* [1c] BAAABB = 6 */ + 0xff, + + /* LEFT half EAN-13 leading digit */ + 0xff, + 0x6f, /* [23] ABBBAA = 6 */ + 0x9f, /* [25] ABBABA = 9 */ + 0xf5, /* [26] ABBAAB = 5 */ + 0x8f, /* [29] ABABBA = 8 */ + 0xf7, /* [2a] ABABAB = 7 */ + 0xf4, /* [2c] ABAABB = 4 */ + 0xff, + 0x3f, /* [31] AABBBA = 3 */ + 0xf2, /* [32] AABBAB = 2 */ + 0xf1, /* [34] AABABB = 1 */ + 0xff, + 0xff, + 0xff, + 0xff, + 0x0f, /* [3f] AAAAAA = 0 */ +}; + + +typedef struct scan_s { + char state; /* module position of w[idx] in symbol */ +#define STATE_ADDON 0x40 /* scanning add-on */ +#define STATE_IDX 0x1f /* element offset into symbol */ + char raw[7]; /* decode in process */ +} scan_t; + +/* decoder state */ +struct zebra_decoder_s { + unsigned char idx; /* current width index */ + unsigned w[8]; /* window of last N bar widths */ + scan_t scans[4]; /* track decode states in parallel */ + char buf[20]; /* decoded characters */ +}; + +zebra_decoder_t *zebra_decoder_create () +{ + zebra_decoder_t *dcode = calloc(1, sizeof(zebra_decoder_t)); + zebra_decoder_new_scan(dcode); + return(dcode); +} + +void zebra_decoder_destroy (zebra_decoder_t *dcode) +{ + free(dcode); +} + +void zebra_decoder_reset (zebra_decoder_t *dcode) +{ + memset(dcode, 0, sizeof(zebra_decoder_t)); +} + +void zebra_decoder_new_scan (zebra_decoder_t *dcode) +{ + /* soft reset decoder */ + memset(dcode->w, 0, 8 * sizeof(unsigned)); + memset(dcode->buf, 0, 20); + dcode->idx = 0; + dcode->scans[0].state = -1; + dcode->scans[1].state = -1; + dcode->scans[2].state = -1; + dcode->scans[3].state = -1; +} + +/* bar+space width are compared as a fraction of the reference dimension "x" + * - +/- 1/2 x tolerance + * - total character width (s) is always 7 "units" for EAN/UPC + * => nominal "x" is 1/7th of "s" + * - bar+space *pair width* "e" is used to factor out bad "exposures" + * ("blooming" or "swelling" of dark or light areas) + * => using like-edge measurements avoids these issues + */ +#define ZEBRA_E_FIXED 6 +#define ZEBRA_E(e) (((e) << ZEBRA_E_FIXED) / 14) + +static inline char decode_e (unsigned e, + unsigned s) +{ + e = (e * 14 + 1) / s; + if(e < 7) { + if(e < 3) return(-1); /* invalid */ + if(e < 5) return(0); /* Ei = 2 (00) */ + else return(1); /* Ei = 3 (01) */ + } + if(e >= 11) return(-1); /* invalid */ + if(e < 9) return(2); /* Ei = 4 (10) */ + else return(3); /* Ei = 5 (11) */ +} + +/* retrieve i-th previous element width */ +static inline unsigned width(zebra_decoder_t *dcode, + unsigned char offset) +{ + return(dcode->w[(dcode->idx - offset) & 7]); +} + +/* calculate module width "x" + * - based on total character width "s" + * => start of character identified by context sensitive offset (<= 4) + */ +static inline unsigned calc_s (zebra_decoder_t *dcode, + unsigned char offset) +{ + return(width(dcode, offset) + + width(dcode, offset + 1) + + width(dcode, offset + 2) + + width(dcode, offset + 3)); +} + +/* evaluate previous N (>= 2) widths as auxiliary pattern, + * using preceding 4 as character width + */ +static inline unsigned char aux_end (zebra_decoder_t *dcode, + unsigned char n) +{ + /* reference width from previous character */ + unsigned s = calc_s(dcode, n); + + char code = 0; + char i; + for(i = 0; i < n - 1; i++) { + unsigned e = width(dcode, i) + width(dcode, i + 1); + code = (code << 2) | decode_e(e, s); + if(code < 0) + return(-1); + } + dprintf(2, " aux=%x", code); + return(code); +} + +/* determine possible auxiliary pattern + * using current 4 as possible character + */ +static inline char aux_start (zebra_decoder_t *dcode, + unsigned s) +{ + /* FIXME NB add-on has no guard in reverse */ + unsigned e2 = width(dcode, 5) + width(dcode, 6); + if(decode_e(e2, s)) { + dprintf(2, " [invalid any]"); + return(/*FIXME ((dcode->idx & 1) == ZEBRA_SPACE) ? STATE_ADDON : */-1); + } + + unsigned e1 = width(dcode, 4) + width(dcode, 5); + unsigned char E1 = decode_e(e1, s); + + if((dcode->idx & 1) == ZEBRA_BAR) { + /* check for quiet-zone */ + if(width(dcode, 7) > (s * 6 / 7)) { + if(!E1) { + dprintf(2, " [valid normal]"); + return(0); /* normal symbol start */ + } + else if(E1 == 1) { + dprintf(2, " [valid add-on]"); + return(STATE_ADDON); /* add-on symbol start */ + } + } + dprintf(2, " [invalid start]"); + return(-1); + } + + if(!E1) { + /* attempting decode from SPACE => validate center guard */ + unsigned e3 = width(dcode, 6) + width(dcode, 7); + if(!decode_e(e3, s)) { + dprintf(2, " [valid center]"); + return(0); /* start after center guard */ + } + } + dprintf(2, " [invalid center]"); + return(/*STATE_ADDON*/-1); +} + +/* attempt to decode previous 4 widths (2 bars and 2 spaces) as a character */ +static inline char decode4 (zebra_decoder_t *dcode, + unsigned s) +{ + /* calculate similar edge measurements */ + unsigned e1 = (((dcode->idx & 1) == ZEBRA_BAR) + ? width(dcode, 0) + width(dcode, 1) + : width(dcode, 2) + width(dcode, 3)); + unsigned e2 = width(dcode, 1) + width(dcode, 2); + dprintf(2, "\n e1=%d e2=%d", e1, e2); + + /* create compacted encoding for direct lookup */ + char code = (decode_e(e1, s) << 2) | decode_e(e2, s); + if(code < 0) + return(-1); + dprintf(2, " code=%x", code); + + /* 4 combinations require additional determinant (D2) + E1E2 == 34 (0110) + E1E2 == 43 (1001) + E1E2 == 33 (0101) + E1E2 == 44 (1010) + */ + if((1 << code) & 0x0660) { + /* use sum of bar widths */ + unsigned d2 = (((dcode->idx & 1) == ZEBRA_BAR) + ? width(dcode, 0) + width(dcode, 2) + : width(dcode, 1) + width(dcode, 3)); + d2 = ((unsigned long)d2 << ZEBRA_E_FIXED) / s; + char alt = (((1 << code) & 0x0420) + ? d2 > ZEBRA_E(6) /* E1E2 in 33,44 */ + : d2 > ZEBRA_E(8)); /* E1E2 in 34,43 */ + if(alt) + code = ((code >> 1) & 3) | 0x10; /* compress code space */ + dprintf(2, " (d2=%d alt=%d)", d2, alt); + } + dprintf(2, " char=%02x", digits[(unsigned char)code]); + assert(code < 0x14); + return(code); +} + +static inline zebra_symbol_type_t partial_end (scan_t *scan, char fwd) +{ + /* calculate parity index */ + char par = ((fwd) + ? ((scan->raw[1] & 0x10) << 1 | + (scan->raw[2] & 0x10) | + (scan->raw[3] & 0x10) >> 1 | + (scan->raw[4] & 0x10) >> 2 | + (scan->raw[5] & 0x10) >> 3 | + (scan->raw[6] & 0x10) >> 4) + : ((scan->raw[1] & 0x10) >> 4 | + (scan->raw[2] & 0x10) >> 3 | + (scan->raw[3] & 0x10) >> 2 | + (scan->raw[4] & 0x10) >> 1 | + (scan->raw[5] & 0x10) | + (scan->raw[6] & 0x10) << 1)); + + /* lookup parity combination */ + scan->raw[0] = parity_decode[par >> 1]; + if(par & 1) + scan->raw[0] >>= 4; + scan->raw[0] &= 0xf; + dprintf(2, " par=%02x(%x)", par, scan->raw[0]); + + if(scan->raw[0] == 0xf) + /* invalid parity combination */ + return(ZEBRA_NONE); + + if(!par == fwd) { + /* reverse sampled digits */ + unsigned char i; + for(i = 1; i < 4; i++) { + char tmp = scan->raw[i]; + scan->raw[i] = scan->raw[6 - i]; + scan->raw[6 - i] = tmp; + } + } + + if(!par) + return(RIGHT_HALF); + if(par & 0x20) + return(LEFT_HALF); + return(ZEBRA_UPCE); +} + +/* update state for one of 4 parallel scans */ +static inline zebra_symbol_type_t decode_scan (zebra_decoder_t *dcode, + scan_t *scan) +{ + scan->state++; + char idx = scan->state & STATE_IDX; + if((1 << idx) & + ((scan->state & STATE_ADDON) + ? 0x00108421 + : 0x00111111)) + { + unsigned s = calc_s(dcode, 0); + dprintf(2, " s=%d", s); + /* validate guard bars before decoding first char of symbol */ + if(!scan->state) { + scan->state = aux_start(dcode, s); + if(scan->state < 0) + return(0); + idx = scan->state & STATE_IDX; + } + char code = decode4(dcode, s); + if(code < 0) + scan->state = -1; + else { + dprintf(2, "\n raw[%x]=%02x =>", idx >> 2, + digits[(unsigned char)code]); + scan->raw[(idx >> 2) + 1] = digits[(unsigned char)code]; + dprintf(2, " raw=%d%d%d%d%d%d%d", + scan->raw[0] & 0xf, scan->raw[1] & 0xf, + scan->raw[2] & 0xf, scan->raw[3] & 0xf, + scan->raw[4] & 0xf, scan->raw[5] & 0xf, + scan->raw[6] & 0xf); + } + } + else if(((dcode->idx & 1) == ZEBRA_BAR) && + ((scan->state & STATE_ADDON) + ? idx == 0x06 || idx == 0x09 || idx == 0x16 || idx == 0x19 + : idx == 0x17 || idx == 0x18)) { + char fwd = idx == 0x18; + dprintf(2, " fwd=%x", fwd); + zebra_symbol_type_t part = ZEBRA_NONE; + if(!aux_end(dcode, (fwd) ? 4 : 3)) { + part = partial_end(scan, fwd); + dprintf(2, "\n"); + dprintf(1, "decode=%x%x%x%x%x%x%x(%x)\n", + scan->raw[0] & 0xf, scan->raw[1] & 0xf, + scan->raw[2] & 0xf, scan->raw[3] & 0xf, + scan->raw[4] & 0xf, scan->raw[5] & 0xf, + scan->raw[6] & 0xf, part); + } + else + dprintf(2, " invalid end guard"); + scan->state = -1; + return(part); + } + return(0); +} + +static inline zebra_symbol_type_t integrate_partial (zebra_decoder_t *dcode, + scan_t *scan, + zebra_symbol_type_t part) +{ + zebra_symbol_type_t sym = ZEBRA_NONE; + + /* FIXME if same partial is not consistent, reset others */ + unsigned char j = 0; + if(part == LEFT_HALF) { + dcode->buf[0] = scan->raw[6] + '0'; + j = 1; + if(dcode->buf[7]) + sym = ((dcode->buf[13]) + ? ZEBRA_EAN13 + ZEBRA_ADDON5 /* FIXME */ + : ZEBRA_EAN13); + } + else if(part == RIGHT_HALF) + j = 7; + else + j = 13; + unsigned char k; + for(k = 0; k < 6; k++) + dcode->buf[j + k] = scan->raw[k] + '0'; + + if(dcode->buf[15]) + if(dcode->buf[0]) + ; + if(dcode->buf[0] && dcode->buf[7] && + dcode->buf[13] && dcode->buf[15]) + sym = ZEBRA_EAN13 + ZEBRA_ADDON5; + else if(dcode->buf[0] && dcode->buf[7] && dcode->buf[13]) + sym = ZEBRA_EAN13 + ZEBRA_ADDON5; + return(sym); +} + +zebra_symbol_type_t zebra_decode_width (zebra_decoder_t *dcode, + unsigned w) +{ + dcode->w[dcode->idx & 7] = w; + + /* process upto 4 separate scans */ + zebra_symbol_type_t sym = ZEBRA_NONE; + unsigned char scan = dcode->idx & 3; + + unsigned char i; + for(i = 0; i < 4; i++) + if(dcode->scans[i].state >= 0 || + i == scan) + { + dprintf(2, " decode[%x/%x]: idx=%x st=%d w=%d", + scan, i, dcode->idx, dcode->scans[i].state, w); + zebra_symbol_type_t part = decode_scan(dcode, &dcode->scans[i]); + if(part) { + /* update accumulated data from new partial decode */ + assert(sym <= 1); + sym = integrate_partial(dcode, &dcode->scans[i], part); + } + dprintf(2, "\n"); + } + dcode->idx++; + return(sym); +} diff --git a/zebra/scanner.c b/zebra/scanner.c new file mode 100644 index 0000000..8423482 --- /dev/null +++ b/zebra/scanner.c @@ -0,0 +1,206 @@ +/*------------------------------------------------------------------------ + * Copyright 2007 (c) Jeff Brown + * + * This file is part of the Zebra Barcode Library. + * + * The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zebra + *------------------------------------------------------------------------*/ + +#include +#ifdef DEBUG_SCANNER +# include /* fprintf */ +#endif +#include /* calloc, free, abs */ + +#include "zebra.h" + +#ifdef DEBUG_SCANNER +# define dprintf(...) \ + fprintf(stderr, __VA_ARGS__) +#else +# define dprintf(...) +#endif + +#ifndef ZEBRA_FIXED +# define ZEBRA_FIXED 5 +#endif + +/* scanner state */ +struct zebra_scanner_s { + zebra_decoder_t *decoder; /* associated bar width decoder */ + + unsigned x; /* relative scan position of next sample */ + int y0[4]; /* short circular buffer of average intensities */ + + int y1_sign; /* slope at last crossing */ + unsigned y1_thresh; /* current slope threshold */ + unsigned y1_min_thresh; /* minimum threshold */ + + unsigned cur_edge; /* interpolated position of tracking edge */ + unsigned last_edge; /* interpolated position of last located edge */ + unsigned width; /* last element width */ +}; + +zebra_scanner_t *zebra_scanner_create (zebra_decoder_t *dcode) +{ + zebra_scanner_t *scn = calloc(1, sizeof(zebra_scanner_t)); + scn->decoder = dcode; + scn->y1_thresh = scn->y1_min_thresh = 8; + return(scn); +} + +void zebra_scanner_destroy (zebra_scanner_t *scn) +{ + free(scn); +} + +unsigned zebra_scanner_get_width (const zebra_scanner_t *scn) +{ + return(scn->width); +} + +zebra_color_t zebra_scanner_get_color (const zebra_scanner_t *scn) +{ + return((scn->y1_sign <= 0) ? ZEBRA_SPACE : ZEBRA_BAR); +} + +static inline unsigned calc_thresh (zebra_scanner_t *scn) +{ + /* threshold 1st to improve noise rejection */ + unsigned thresh = scn->y1_thresh; + if((thresh <= scn->y1_min_thresh) || !scn->width) { + dprintf(" tmin=%d", scn->y1_min_thresh); + return(scn->y1_min_thresh); + } + /* slowly return threshold to min */ + unsigned long t = thresh * ((scn->x << ZEBRA_FIXED) - scn->last_edge); + t /= scn->width; + t /= 4; /* FIXME add config API */ + t = ((t >> (ZEBRA_FIXED - 1)) + 1) >> 1; + thresh -= t; + dprintf(" thr=%d t=%ld x=%d last=%d.%d", + thresh, t, scn->x, scn->last_edge >> ZEBRA_FIXED, + scn->last_edge & ((1 << ZEBRA_FIXED) - 1)); + if(thresh < scn->y1_min_thresh) + thresh = scn->y1_thresh = scn->y1_min_thresh; + return(thresh); +} + +static inline zebra_symbol_type_t process_edge (zebra_scanner_t *scn, + int y1) +{ + scn->width = scn->cur_edge - scn->last_edge; + dprintf(" sgn=%d cur=%d.%d w=%d\n", + scn->y1_sign, scn->cur_edge >> ZEBRA_FIXED, + scn->cur_edge & ((1 << ZEBRA_FIXED) - 1), scn->width); + scn->last_edge = scn->cur_edge; + + /* adaptive thresholding */ + /* start at 1/4 new min/max */ + scn->y1_thresh = abs((y1 + 1) / 2); + if(scn->y1_thresh < scn->y1_min_thresh) + scn->y1_thresh = scn->y1_min_thresh; + + /* pass to decoder */ + if(scn->width) { + scn->y1_sign = y1; + if(scn->decoder) + return(zebra_decode_width(scn->decoder, scn->width)); + return(ZEBRA_PARTIAL); + } + /* skip initial transition */ + return(ZEBRA_NONE); +} + +zebra_symbol_type_t zebra_scan_y (zebra_scanner_t *scn, + int y) +{ + /* retrieve short value history */ + register int y0_1 = scn->y0[(scn->x - 1) & 3]; + register int y0_0; + if(scn->x) + /* update weighted moving average */ + y0_0 = scn->y0[scn->x & 3] = y0_1 + ((y - y0_1 + 1) / 2); + else + y0_0 = scn->y0[0] = scn->y0[1] = scn->y0[2] = scn->y0[3] = y; + register int y0_2 = scn->y0[(scn->x - 2) & 3]; + register int y0_3 = scn->y0[(scn->x - 3) & 3]; + /* 1st differential @ x-1 */ + register int y1_1 = y0_0 - y0_2; + { + register int y1_2 = y0_1 - y0_3; + if(abs(y1_1) < abs(y1_2)) y1_1 = y1_2; + } + /* 2nd differentials @ x-1 & x-2 */ + register int y2_1 = y0_0 - (y0_1 * 2) + y0_2; + register int y2_2 = y0_1 - (y0_2 * 2) + y0_3; + + dprintf("scan: y=%d y0=%d y1=%d y2=%d", y, y0_1, y1_1, y2_1); + + zebra_symbol_type_t edge = ZEBRA_NONE; + /* 2nd zero-crossing is 1st local min/max - could be edge */ + if((!y2_1 || + ((y2_1 > 0) ? y2_2 < 0 : y2_2 > 0)) && + (calc_thresh(scn) < abs(y1_1))) + { + /* check for 1st sign change */ + if((scn->y1_sign > 0) ? y1_1 < 0 : y1_1 > 0) + /* intensity change reversal - finalize previous edge */ + edge = process_edge(scn, y1_1); + else + dprintf("\n"); + + /* update current edge */ + int d = y2_1 - y2_2; + scn->cur_edge = 1 << ZEBRA_FIXED; + if(!d) + scn->cur_edge >>= 1; + else if(y2_1) + /* interpolate zero crossing */ + scn->cur_edge -= ((y2_1 << ZEBRA_FIXED) + 1) / d; + scn->cur_edge += scn->x << ZEBRA_FIXED; + } + else + dprintf("\n"); + /* FIXME add fall-thru pass to decoder after heuristic "idle" period + (eg, 6-8 * last width) */ + scn->x++; + return(edge); +} + +/* undocumented API for drawing cutesy debug graphics */ +void zebra_scanner_get_state (const zebra_scanner_t *scn, + unsigned *x, + unsigned *cur_edge, + unsigned *last_edge, + int *y0, + int *y1, + int *y2, + int *y1_thresh) +{ + register int y0_0 = scn->y0[scn->x & 0x3]; + register int y0_1 = scn->y0[(scn->x - 1) & 3]; + register int y0_2 = scn->y0[(scn->x - 2) & 3]; + if(x) *x = scn->x - 1; + if(cur_edge) *cur_edge = scn->cur_edge; + if(last_edge) *last_edge = scn->last_edge; + if(y0) *y0 = y0_1; + if(y1) *y1 = y0_0 - y0_2; + if(y2) *y2 = y0_0 - (y0_1 * 2) + y0_2; + if(y1_thresh) *y1_thresh = calc_thresh((zebra_scanner_t*)scn); +} diff --git a/zebracam/Makefile.am b/zebracam/Makefile.am new file mode 100644 index 0000000..cfcf15c --- /dev/null +++ b/zebracam/Makefile.am @@ -0,0 +1,5 @@ +bin_PROGRAMS = zebracam +zebracam_SOURCES = zebracam.c +AM_CPPFLAGS = -I$(srcdir)/../include $(SDL_CPPFLAGS) +AM_CFLAGS = -Wall -Werror +LDADD = $(SDL_LIBS) ../zebra/libzebra.la diff --git a/zebracam/zebracam.c b/zebracam/zebracam.c new file mode 100644 index 0000000..a0f70b1 --- /dev/null +++ b/zebracam/zebracam.c @@ -0,0 +1,275 @@ +/*------------------------------------------------------------------------ + * Copyright 2007 (c) Jeff Brown + * + * This file is part of the Zebra Barcode Library. + * + * The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zebra + *------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "zebra.h" + +static int cam_fd; +static struct video_capability vcap; +static struct video_window vwin; +static uint32_t size; +struct video_picture vpic; +struct video_mbuf vbuf; +struct video_mmap vmap; +void *image; +SDL_Surface *screen; +uint8_t *buf; +int streaming = 1, dump = 0; + +zebra_decoder_t *decoder; +zebra_scanner_t *scanner; + +static void init_cam () +{ + cam_fd = open("/dev/video0", O_RDWR); + if(cam_fd < 0) { + perror("ERROR opening /dev/video0\n"); + exit(1); + } + + if(ioctl(cam_fd, VIDIOCGCAP, &vcap) < 0) { + perror("ERROR VIDIOCGCAP: v4l unsupported\n"); + exit(1); + } + printf("found device: \"%s\"\n", vcap.name); + + + /* initialize window properties */ + if(ioctl(cam_fd, VIDIOCGWIN, &vwin) < 0) { + perror("ERROR VIDIOCGWIN"); + exit(1); + } + + if(vwin.width != vcap.maxwidth) { + vwin.width = vcap.maxwidth; + vwin.height = vcap.maxheight; + + if(ioctl(cam_fd, VIDIOCSWIN, &vwin) < 0) { + perror("ERROR VIDIOCSWIN"); + exit(1); + } + if(ioctl(cam_fd, VIDIOCGWIN, &vwin) < 0) { + perror("ERROR VIDIOCGWIN"); + exit(1); + } + } + size = vwin.width * vwin.height; + printf(" win: %dx%d @(%d, %d) = 0x%x bytes\n", + vwin.width, vwin.height, vwin.x, vwin.y, size); + + + /* setup image properties */ + if(ioctl(cam_fd, VIDIOCGPICT, &vpic) < 0) { + perror("ERROR VIDIOCGPICT"); + exit(1); + } + + int palette = VIDEO_PALETTE_RGB24; + if(vpic.palette != palette) { + vpic.palette = palette; + if(ioctl(cam_fd, VIDIOCSPICT, &vpic) < 0) { + perror("ERROR VIDIOCSPICT"); + exit(1); + } + if(ioctl(cam_fd, VIDIOCGPICT, &vpic) < 0) { + perror("ERROR VIDIOCGPICT"); + exit(1); + } + if(vpic.palette != palette) { + fprintf(stderr, "ERROR can't set palette\n"); + exit(1); + } + } + printf(" pict: brite=%04x hue=%04x color=%04x con=%04x" + " wht=%04x deep=%04x pal=%04x\n", + vpic.brightness, vpic.hue, vpic.colour, vpic.contrast, + vpic.whiteness, vpic.depth, vpic.palette); + + + /* map camera image to memory */ + if(ioctl(cam_fd, VIDIOCGMBUF, &vbuf) < 0) { + perror("ERROR VIDIOCGMBUF"); + exit(1); + } + printf(" buf: size=%x num=%x [0]=%x [1]=%x\n", + vbuf.size, vbuf.frames, vbuf.offsets[0], vbuf.offsets[1]); + + /* only need double buffer */ + if(vbuf.frames > 2) + vbuf.frames = 2; + + image = mmap(0, vbuf.size, PROT_READ | PROT_WRITE, MAP_SHARED, cam_fd, 0); + + /* initialize for capture */ + vmap.frame = 0; + vmap.height = vwin.height; + vmap.width = vwin.width; + vmap.format = vpic.palette; +} + +static void init_sdl () +{ + /* initialize SDL */ + if(SDL_Init(SDL_INIT_VIDEO) < 0) { + fprintf(stderr, "ERROR initializing SDL: %s\n", SDL_GetError()); + exit(1); + } + atexit(SDL_Quit); + SDL_WM_SetCaption("zebracam", "zebracam"); + + setenv("SDL_VIDEO_CENTERED", "1", 1); + screen = SDL_SetVideoMode(vwin.width, vwin.height, + 24, SDL_SWSURFACE | SDL_DOUBLEBUF); + if(!screen) { + fprintf(stderr, "ERROR setting video mode: %s\n", SDL_GetError()); + exit(1); + } + + SDL_ShowCursor(1); +} + +static inline int handle_events () +{ + SDL_Event e; + while(SDL_PollEvent(&e)) { + if(e.type == SDL_QUIT || + (e.type == SDL_KEYDOWN && + e.key.keysym.sym == SDLK_q)) + /* exit condition */ + return(1); + if(e.type == SDL_KEYDOWN && + e.key.keysym.sym == SDLK_SPACE) { + /* pause/resume */ + streaming = !streaming; + dump = !streaming; + } + } + return(0); +} + +static inline void sync (int frame) +{ + if(ioctl(cam_fd, VIDIOCSYNC, &frame) < 0) { + perror("ERROR VIDIOCSYNC"); + exit(1); + } +} + +static inline void capture (int frame) +{ + vmap.frame = frame; + if(ioctl(cam_fd, VIDIOCMCAPTURE, &vmap) < 0) { + perror("ERROR VIDIOCMCAPTURE"); + exit(1); + } +} + +static inline void display () +{ + memcpy(screen->pixels, buf, size * 3); +} + +static void process () +{ + uint32_t dy = vwin.width * 3; + uint8_t *p = buf + ((vwin.height + 1) >> 1) * dy; + int i; + for(i = 0; i < vwin.width; i++, p += 3) { + zebra_scan_rgb24(scanner, p); + *(p + 2) = 0xff; + } +} + + +int main (int argc, const char *argv[]) +{ + /* initialization */ + init_cam(); + init_sdl(); + decoder = zebra_decoder_create(); + scanner = zebra_scanner_create(decoder); + + /* main loop */ + int frame = 0; + capture(frame); + capture(1); + + int nframes = 0; + + while(!handle_events()) { + /* wait for latest image */ + sync(frame); + buf = image + vbuf.offsets[frame]; + + if(streaming) { + if(SDL_MUSTLOCK(screen) && + SDL_LockSurface (screen) < 0) { + fprintf(stderr, "ERROR SDL failed to lock screen surface: %s\n", + SDL_GetError()); + return(1); + } + + /* application processing */ + process(); + + /* show result onscreen */ + display(); + + if(SDL_MUSTLOCK(screen)) + SDL_UnlockSurface(screen); + + SDL_Flip(screen); + } + else if(dump) { + process(); + dump = 0; + } + + /* re-start capture of image */ + capture(frame); + + nframes++; + if(!(nframes & 0xf)) { + double ms = SDL_GetTicks(); + double fr = nframes * 1000. / ms; + printf("@%g %gfps\n", ms, fr); + } + frame = (frame + 1) % vbuf.frames; + } + + zebra_scanner_destroy(scanner); + zebra_decoder_destroy(decoder); + return(0); +} diff --git a/zebraimg/Makefile.am b/zebraimg/Makefile.am new file mode 100644 index 0000000..c23497a --- /dev/null +++ b/zebraimg/Makefile.am @@ -0,0 +1,6 @@ +bin_PROGRAMS = zebraimg +zebraimg_SOURCES = zebraimg.cpp +AM_CPPFLAGS = -I$(srcdir)/../include $(MAGICK_CPPFLAGS) +AM_CXXFLAGS = -Wall -Werror $(MAGICK_CXXFLAGS) +AM_LDFLAGS = $(MAGICK_LDFLAGS) +LDADD = $(MAGICK_LIBS) ../zebra/libzebra.la diff --git a/zebraimg/zebraimg.cpp b/zebraimg/zebraimg.cpp new file mode 100644 index 0000000..7d9e6bb --- /dev/null +++ b/zebraimg/zebraimg.cpp @@ -0,0 +1,97 @@ +//------------------------------------------------------------------------ +// Copyright 2007 (c) Jeff Brown +// +// This file is part of the Zebra Barcode Library. +// +// The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free +// Software Foundation, Inc., 51 Franklin St, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// http://sourceforge.net/projects/zebra +//------------------------------------------------------------------------ + +#include +#include +#include + +using namespace std; +using namespace Magick; +using namespace zebra; + +int display = 0; + +Decoder decoder; +Scanner scanner(decoder); + +void scan_image (const char *filename) +{ + Image image; + image.read(filename); + unsigned width = image.columns(); + unsigned height = image.rows(); + + Color red("red"); + image.modifyImage(); + + // extract image pixels + Pixels view(image); + PixelPacket *pxp = view.get(0, (height + 1) / 2, width, 1); + ColorYUV y; + for(unsigned i = 0; i < width; i++) { + y = *pxp; + scanner << (int)(y.y() * 0x100); + *pxp++ = red; + } + view.sync(); + y.y(y.y() * .75); + scanner << (int)(y.y() * 0x100) + << (int)(y.y() * 0x100) + << (int)(y.y() * 0x100); /* flush scan FIXME? */ + + if(display) + image.display(); +} + +int usage (int rc, const char *msg = NULL) +{ + ostream &out = (rc) ? cerr : cout; + if(msg) + out << msg << endl; + out << + "usage: zebraimg [-h|-d|--display|--nodisplay] ..." << endl; + return(rc); +} + +int main (int argc, const char *argv[]) +{ + int num_images = 0; + for(int i = 1; i < argc; i++) { + if(!strcmp(argv[i], "-h") || + !strcmp(argv[i], "--help")) + return(usage(0)); + if(!strcmp(argv[i], "-d") || + !strcmp(argv[i], "--display")) + display = 1; + else if(!strcmp(argv[i], "--nodisplay")) + display = 0; + else { + num_images++; + scan_image(argv[i]); + } + } + if(!num_images) + return(usage(1, "ERROR: specify image file(s) to scan")); + + return(0); +} From 38806a9953f263a4f70605592ab57308c81a0244 Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 28 Feb 2007 05:01:28 +0000 Subject: [PATCH 002/328] * removed recursive makes in favor of monolithic build * renamed some makefiles accordingly * finished some final symbol data construction * added result callbacks to decoder APIs for data reporting * zebraimg hooks into callback * zebracam still seems to "hang" in undecodeable state? --- Makefile.am | 17 ++++-- TODO | 5 +- configure.ac | 11 ++-- include/Makefile.am.inc | 3 ++ include/zebra.h | 32 +++++++++++- include/zebra/Decoder.h | 29 +++++++++-- test/Makefile.am | 4 -- test/Makefile.am.inc | 2 + zebra/Makefile.am | 4 -- zebra/Makefile.am.inc | 2 + zebra/decoder.c | 108 +++++++++++++++++++++++++++------------ zebracam/Makefile.am | 5 -- zebracam/Makefile.am.inc | 6 +++ zebracam/zebracam.c | 5 +- zebraimg/Makefile.am | 6 --- zebraimg/Makefile.am.inc | 8 +++ zebraimg/zebraimg.cpp | 13 +++++ 17 files changed, 184 insertions(+), 76 deletions(-) create mode 100644 include/Makefile.am.inc delete mode 100644 test/Makefile.am create mode 100644 test/Makefile.am.inc delete mode 100644 zebra/Makefile.am create mode 100644 zebra/Makefile.am.inc delete mode 100644 zebracam/Makefile.am create mode 100644 zebracam/Makefile.am.inc delete mode 100644 zebraimg/Makefile.am create mode 100644 zebraimg/Makefile.am.inc diff --git a/Makefile.am b/Makefile.am index 6ca0b17..b5d3e3d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,9 +1,16 @@ -include_HEADERS = include/zebra.h -SUBDIRS = zebra +AM_CPPFLAGS = -I$(srcdir)/include +AM_CFLAGS = -Wall -Werror +bin_PROGRAMS = +check_PROGRAMS = +CLEANFILES = + +include $(srcdir)/include/Makefile.am.inc +include $(srcdir)/zebra/Makefile.am.inc if HAVE_MAGICK - SUBDIRS += zebraimg +include $(srcdir)/zebraimg/Makefile.am.inc endif if HAVE_SDL - SUBDIRS += zebracam +include $(srcdir)/zebracam/Makefile.am.inc endif -SUBDIRS += test #doc +include $(srcdir)/test/Makefile.am.inc +#include $(srcdir)/doc/Makefile.am.inc diff --git a/TODO b/TODO index a428bc7..3accc77 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,6 @@ + * soft reset when partial mismatches same slot + * parity checking * finish addon decoding - * combine partial decodes into final result - * soft reset when partial mismatches same slot - * parity checking * add scan patterns to zebraimg & zebracam * via some kind of reusable library API? * documentation diff --git a/configure.ac b/configure.ac index 4069810..730768d 100644 --- a/configure.ac +++ b/configure.ac @@ -1,11 +1,12 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.60]) AC_INIT([zebra], [0.1], [spadix@users.sourceforge.net]) -AM_INIT_AUTOMAKE([-Wall -Werror foreign]) +AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) AC_CONFIG_HEADERS([include/config.h]) AC_CONFIG_SRCDIR(zebra/scanner.c) AC_PROG_CC +AM_PROG_CC_C_O AC_PROG_CXX AC_PROG_LIBTOOL AC_PROG_RANLIB @@ -81,11 +82,5 @@ AC_C_INLINE AC_FUNC_MMAP AC_CHECK_FUNCS([memset atexit setenv]) -AC_CONFIG_FILES([ - Makefile - zebra/Makefile - zebraimg/Makefile - zebracam/Makefile - test/Makefile -]) +AC_CONFIG_FILES([Makefile]) AC_OUTPUT diff --git a/include/Makefile.am.inc b/include/Makefile.am.inc new file mode 100644 index 0000000..28e41b2 --- /dev/null +++ b/include/Makefile.am.inc @@ -0,0 +1,3 @@ +zincludedir = $(includedir)/zebra +include_HEADERS = include/zebra.h +zinclude_HEADERS = include/zebra/Scanner.h include/zebra/Decoder.h diff --git a/include/zebra.h b/include/zebra.h index 2b950da..8f1dad0 100644 --- a/include/zebra.h +++ b/include/zebra.h @@ -25,7 +25,7 @@ #ifdef __cplusplus namespace zebra { - extern "C" { + extern "C" { #endif @@ -57,6 +57,11 @@ typedef enum zebra_symbol_type_e { struct zebra_decoder_s; typedef struct zebra_decoder_s zebra_decoder_t; +/* decoder data handler callback function. + * called by decoder when new data has just been decoded + */ +typedef void (zebra_decoder_handler_t)(zebra_decoder_t *decoder); + /* constructor */ extern zebra_decoder_t *zebra_decoder_create(); @@ -91,6 +96,29 @@ extern zebra_symbol_type_t zebra_decode_width(zebra_decoder_t *decoder, */ extern const char *zebra_decoder_get_data(const zebra_decoder_t *decoder); +/* returns last decoded type, + * or ZEBRA_NONE if no new data available + */ +extern zebra_symbol_type_t +zebra_decoder_get_type(const zebra_decoder_t *decoder); + +/* setup data handler callback. + * the registered function will be called by the decoder + * just before zebra_decode_width returns a non-zero value. + * pass a NULL value to disable callbacks. + * returns the previously registered handler + */ +extern zebra_decoder_handler_t* +zebra_decoder_set_handler(zebra_decoder_t *decoder, + zebra_decoder_handler_t *handler); + +/* associate user specified data value with the decoder */ +extern void zebra_decoder_set_userdata(zebra_decoder_t *decoder, + void *userdata); + +/* return user specified data value associated with the decoder */ +extern void *zebra_decoder_get_userdata(zebra_decoder_t *decoder); + /*------------------------------------------------------------*/ /* low-level intensity sample stream scanner interface @@ -140,7 +168,7 @@ extern zebra_color_t zebra_scanner_get_color(const zebra_scanner_t *scanner); #ifdef __cplusplus - } + } } # include "zebra/Decoder.h" diff --git a/include/zebra/Decoder.h b/include/zebra/Decoder.h index 03b9d52..18b6a17 100644 --- a/include/zebra/Decoder.h +++ b/include/zebra/Decoder.h @@ -33,7 +33,13 @@ namespace zebra { class Decoder { public: + class Handler { + public: + virtual void decode_callback(Decoder &decoder) = 0; + }; + Decoder () + : _handler(NULL) { _decoder = zebra_decoder_create(); } @@ -55,19 +61,18 @@ class Decoder { zebra_symbol_type_t decode_width (unsigned width) { - _type = zebra_decode_width(_decoder, width); - return(_type); + return(zebra_decode_width(_decoder, width)); } Decoder& operator<< (unsigned width) { - _type = zebra_decode_width(_decoder, width); + zebra_decode_width(_decoder, width); return(*this); } zebra_symbol_type_t get_type () const { - return(_type); + return(zebra_decoder_get_type(_decoder)); } const char *get_data_chars() const @@ -81,11 +86,25 @@ class Decoder { return(_data); } + void set_handler (Handler &handler) + { + _handler = &handler; + zebra_decoder_set_handler(_decoder, _cb); + zebra_decoder_set_userdata(_decoder, this); + } + private: friend class Scanner; zebra_decoder_t *_decoder; - zebra_symbol_type_t _type; std::string _data; + Handler *_handler; + + static void _cb (zebra_decoder_t *cdcode) + { + Decoder *dcode = (Decoder*)zebra_decoder_get_userdata(cdcode); + if(dcode && dcode->_handler) + dcode->_handler->decode_callback(*dcode); + } }; } diff --git a/test/Makefile.am b/test/Makefile.am deleted file mode 100644 index 7e43a22..0000000 --- a/test/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -bin_PROGRAMS = test_decode -AM_CPPFLAGS = -I$(srcdir)/../include -AM_CFLAGS = -Wall -Werror -LDADD = ../zebra/libzebra.la diff --git a/test/Makefile.am.inc b/test/Makefile.am.inc new file mode 100644 index 0000000..dae1eea --- /dev/null +++ b/test/Makefile.am.inc @@ -0,0 +1,2 @@ +check_PROGRAMS += test/test_decode +test_test_decode_LDADD = zebra/libzebra.la diff --git a/zebra/Makefile.am b/zebra/Makefile.am deleted file mode 100644 index d8b0181..0000000 --- a/zebra/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -lib_LTLIBRARIES = libzebra.la -AM_CPPFLAGS = -I$(srcdir)/../include -AM_CFLAGS = -Wall -Werror -libzebra_la_SOURCES = scanner.c decoder.c diff --git a/zebra/Makefile.am.inc b/zebra/Makefile.am.inc new file mode 100644 index 0000000..86d5c54 --- /dev/null +++ b/zebra/Makefile.am.inc @@ -0,0 +1,2 @@ +lib_LTLIBRARIES = zebra/libzebra.la +zebra_libzebra_la_SOURCES = zebra/scanner.c zebra/decoder.c diff --git a/zebra/decoder.c b/zebra/decoder.c index a577904..542a505 100644 --- a/zebra/decoder.c +++ b/zebra/decoder.c @@ -95,18 +95,21 @@ static const char parity_decode[] = { typedef struct scan_s { - char state; /* module position of w[idx] in symbol */ -#define STATE_ADDON 0x40 /* scanning add-on */ -#define STATE_IDX 0x1f /* element offset into symbol */ - char raw[7]; /* decode in process */ + char state; /* module position of w[idx] in symbol */ +#define STATE_ADDON 0x40 /* scanning add-on */ +#define STATE_IDX 0x1f /* element offset into symbol */ + char raw[7]; /* decode in process */ } scan_t; /* decoder state */ struct zebra_decoder_s { - unsigned char idx; /* current width index */ - unsigned w[8]; /* window of last N bar widths */ - scan_t scans[4]; /* track decode states in parallel */ - char buf[20]; /* decoded characters */ + unsigned char idx; /* current width index */ + unsigned w[8]; /* window of last N bar widths */ + scan_t scans[4]; /* track decode states in parallel */ + char buf[20]; /* decoded characters */ + zebra_symbol_type_t type; /* type of last decoded data */ + void *userdata; /* application data */ + zebra_decoder_handler_t *handler; /* application callback */ }; zebra_decoder_t *zebra_decoder_create () @@ -138,6 +141,40 @@ void zebra_decoder_new_scan (zebra_decoder_t *dcode) dcode->scans[3].state = -1; } +const char *zebra_decoder_get_data (const zebra_decoder_t *dcode) +{ + return(dcode->buf); +} + +zebra_decoder_handler_t * +zebra_decoder_set_handler (zebra_decoder_t *dcode, + zebra_decoder_handler_t handler) +{ + zebra_decoder_handler_t *result = dcode->handler; + dcode->handler = handler; + return(result); +} + +void zebra_decoder_set_userdata (zebra_decoder_t *dcode, + void *userdata) +{ + dcode->userdata = userdata; +} + +void *zebra_decoder_get_userdata (zebra_decoder_t *dcode) +{ + return(dcode->userdata); +} + +zebra_symbol_type_t zebra_decoder_get_type (const zebra_decoder_t *dcode) +{ + return((dcode->type == RIGHT_HALF || + dcode->type == LEFT_HALF) + ? ZEBRA_PARTIAL + : dcode->type); +} + + /* bar+space width are compared as a fraction of the reference dimension "x" * - +/- 1/2 x tolerance * - total character width (s) is always 7 "units" for EAN/UPC @@ -396,35 +433,35 @@ static inline zebra_symbol_type_t integrate_partial (zebra_decoder_t *dcode, scan_t *scan, zebra_symbol_type_t part) { - zebra_symbol_type_t sym = ZEBRA_NONE; - /* FIXME if same partial is not consistent, reset others */ - unsigned char j = 0; + /* FIXME UPC-E, EAN-8 */ + unsigned char start; + unsigned char len = 6; + unsigned char i = 0; if(part == LEFT_HALF) { - dcode->buf[0] = scan->raw[6] + '0'; - j = 1; + start = 0; + len = 7; if(dcode->buf[7]) - sym = ((dcode->buf[13]) - ? ZEBRA_EAN13 + ZEBRA_ADDON5 /* FIXME */ - : ZEBRA_EAN13); + part = ZEBRA_EAN13; } - else if(part == RIGHT_HALF) - j = 7; - else - j = 13; - unsigned char k; - for(k = 0; k < 6; k++) - dcode->buf[j + k] = scan->raw[k] + '0'; - - if(dcode->buf[15]) + else if(part == RIGHT_HALF) { + i = 1; + start = 7; if(dcode->buf[0]) - ; - if(dcode->buf[0] && dcode->buf[7] && - dcode->buf[13] && dcode->buf[15]) - sym = ZEBRA_EAN13 + ZEBRA_ADDON5; - else if(dcode->buf[0] && dcode->buf[7] && dcode->buf[13]) - sym = ZEBRA_EAN13 + ZEBRA_ADDON5; - return(sym); + part = ZEBRA_EAN13; + } + else { + start = 13; + len = (part == ZEBRA_ADDON5) ? 5 : 2; + } + if(part == ZEBRA_EAN13 && dcode->buf[13]) + part |= ZEBRA_ADDON5; + + /* copy raw data into output buffer */ + for(; i < len; i++, start++) + dcode->buf[start] = (scan->raw[i] & 0xf) + '0'; + + return(part); } zebra_symbol_type_t zebra_decode_width (zebra_decoder_t *dcode, @@ -446,11 +483,16 @@ zebra_symbol_type_t zebra_decode_width (zebra_decoder_t *dcode, zebra_symbol_type_t part = decode_scan(dcode, &dcode->scans[i]); if(part) { /* update accumulated data from new partial decode */ - assert(sym <= 1); + /*assert(sym <= 1); FIXME why?! */ sym = integrate_partial(dcode, &dcode->scans[i], part); + dcode->type = sym; } dprintf(2, "\n"); } dcode->idx++; + if(sym == LEFT_HALF || sym == RIGHT_HALF) + sym = ZEBRA_PARTIAL; + if(sym && dcode->handler) + dcode->handler(dcode); return(sym); } diff --git a/zebracam/Makefile.am b/zebracam/Makefile.am deleted file mode 100644 index cfcf15c..0000000 --- a/zebracam/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -bin_PROGRAMS = zebracam -zebracam_SOURCES = zebracam.c -AM_CPPFLAGS = -I$(srcdir)/../include $(SDL_CPPFLAGS) -AM_CFLAGS = -Wall -Werror -LDADD = $(SDL_LIBS) ../zebra/libzebra.la diff --git a/zebracam/Makefile.am.inc b/zebracam/Makefile.am.inc new file mode 100644 index 0000000..f68ee69 --- /dev/null +++ b/zebracam/Makefile.am.inc @@ -0,0 +1,6 @@ +bin_PROGRAMS += zebracam/zebracam +zebracam_zebracam_SOURCES = zebracam/zebracam.c +zebracam_zebracam_CPPFLAGS = $(SDL_CPPFLAGS) $(AM_CPPFLAGS) +zebracam_zebracam_LDADD = $(SDL_LIBS) zebra/libzebra.la +# automake bug in "monolithic mode"? +CLEANFILES += zebracam/.libs/zebracam diff --git a/zebracam/zebracam.c b/zebracam/zebracam.c index a0f70b1..b19a392 100644 --- a/zebracam/zebracam.c +++ b/zebracam/zebracam.c @@ -207,7 +207,10 @@ static void process () uint8_t *p = buf + ((vwin.height + 1) >> 1) * dy; int i; for(i = 0; i < vwin.width; i++, p += 3) { - zebra_scan_rgb24(scanner, p); + if(zebra_scan_rgb24(scanner, p) > 1) + printf("%x: %s\n", + zebra_decoder_get_type(decoder), + zebra_decoder_get_data(decoder)); *(p + 2) = 0xff; } } diff --git a/zebraimg/Makefile.am b/zebraimg/Makefile.am deleted file mode 100644 index c23497a..0000000 --- a/zebraimg/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -bin_PROGRAMS = zebraimg -zebraimg_SOURCES = zebraimg.cpp -AM_CPPFLAGS = -I$(srcdir)/../include $(MAGICK_CPPFLAGS) -AM_CXXFLAGS = -Wall -Werror $(MAGICK_CXXFLAGS) -AM_LDFLAGS = $(MAGICK_LDFLAGS) -LDADD = $(MAGICK_LIBS) ../zebra/libzebra.la diff --git a/zebraimg/Makefile.am.inc b/zebraimg/Makefile.am.inc new file mode 100644 index 0000000..f225a0b --- /dev/null +++ b/zebraimg/Makefile.am.inc @@ -0,0 +1,8 @@ +bin_PROGRAMS += zebraimg/zebraimg +zebraimg_zebraimg_SOURCES = zebraimg/zebraimg.cpp +zebraimg_zebraimg_CPPFLAGS = $(MAGICK_CPPFLAGS) $(AM_CPPFLAGS) +zebraimg_zebraimg_CXXFLAGS = $(MAGICK_CXXFLAGS) $(AM_CXXFLAGS) +zebraimg_zebraimg_LDFLAGS = $(MAGICK_LDFLAGS) $(AM_LDFLAGS) +zebraimg_zebraimg_LDADD = $(MAGICK_LIBS) zebra/libzebra.la +# automake bug in "monolithic mode"? +CLEANFILES += zebraimg/.libs/zebraimg diff --git a/zebraimg/zebraimg.cpp b/zebraimg/zebraimg.cpp index 7d9e6bb..fafbb86 100644 --- a/zebraimg/zebraimg.cpp +++ b/zebraimg/zebraimg.cpp @@ -31,6 +31,17 @@ using namespace zebra; int display = 0; + +class ImageHandler : public Decoder::Handler { + virtual void decode_callback (Decoder &decoder) + { + if(decoder.get_type() > ZEBRA_PARTIAL) + cout << decoder.get_type() << ": " + << decoder.get_data_string() << endl; + } +}; + +ImageHandler handler; Decoder decoder; Scanner scanner(decoder); @@ -75,6 +86,8 @@ int usage (int rc, const char *msg = NULL) int main (int argc, const char *argv[]) { + decoder.set_handler(handler); + int num_images = 0; for(int i = 1; i < argc; i++) { if(!strcmp(argv[i], "-h") || From 7362bcf7822f21f3374056df82a1eed6f4419cc1 Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 16 Mar 2007 23:18:04 +0000 Subject: [PATCH 003/328] finish basic decoder symbol assembly/reporting add decoder symbol checksum verification add callback API option to decoder for "async" symbol processing add "image walker" library API to trace scan pattern over 2D images apply image walker to zebracam (C++/zebraimg scan pattern still TBD) add audio feedback to zebracam (still has long latency) add zebracam key cmd to dump frame to file (for debugging) fixes for decoder/scanner reset/new_scan fixes to scanner initialization and algorithm tweaks made decoder less sensitive to violated quiet-zone apply zebraimg workaround for imagemagick image display bug add string names for symbol types to library and API to access them add dbg_scan test program for visually debugging image scanner (and decoder) add test_walk for basic image walker sanity/debug --- Makefile.am | 1 + TODO | 9 +- configure.ac | 2 + include/zebra.h | 90 ++++++++++++++++ include/zebra/Decoder.h | 10 ++ include/zebra/Scanner.h | 5 + test/Makefile.am.inc | 19 ++++ test/dbg_scan.cc | 221 +++++++++++++++++++++++++++++++++++++++ test/test_walk.c | 83 +++++++++++++++ zebra/Makefile.am.inc | 3 +- zebra/decoder.c | 98 ++++++++++++++---- zebra/img_walker.c | 222 ++++++++++++++++++++++++++++++++++++++++ zebra/scanner.c | 76 +++++++++----- zebracam/zebracam.c | 200 ++++++++++++++++++++++++++++-------- zebraimg/zebraimg.cpp | 24 +++-- 15 files changed, 968 insertions(+), 95 deletions(-) create mode 100644 test/dbg_scan.cc create mode 100644 test/test_walk.c create mode 100644 zebra/img_walker.c diff --git a/Makefile.am b/Makefile.am index b5d3e3d..9be7b08 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,6 @@ AM_CPPFLAGS = -I$(srcdir)/include AM_CFLAGS = -Wall -Werror +AM_CXXFLAGS = $(AM_CFLAGS) bin_PROGRAMS = check_PROGRAMS = CLEANFILES = diff --git a/TODO b/TODO index 3accc77..da7c6af 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,7 @@ + * C++ interface to img_walker + * img_walker should have userdata + * scanner: resolve int/fixed inconsistency bug * soft reset when partial mismatches same slot - * parity checking - * finish addon decoding - * add scan patterns to zebraimg & zebracam - * via some kind of reusable library API? + * finish UPC-E, EAN-8 and addon decoding + * profile and weed out obvious oversights * documentation diff --git a/configure.ac b/configure.ac index 730768d..c56685b 100644 --- a/configure.ac +++ b/configure.ac @@ -5,6 +5,8 @@ AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) AC_CONFIG_HEADERS([include/config.h]) AC_CONFIG_SRCDIR(zebra/scanner.c) +AC_SUBST([LIB_VERSION], [1:0:1]) + AC_PROG_CC AM_PROG_CC_C_O AC_PROG_CXX diff --git a/include/zebra.h b/include/zebra.h index 8f1dad0..cd3cf5c 100644 --- a/include/zebra.h +++ b/include/zebra.h @@ -43,10 +43,18 @@ typedef enum zebra_symbol_type_e { ZEBRA_UPCE = 11, /* UPC-E */ ZEBRA_UPCA = 12, /* UPC-A */ ZEBRA_EAN13 = 13, /* EAN-13 */ + ZEBRA_SYMBOL = 0x0f, /* mask for base symbol type */ ZEBRA_ADDON2 = 0x20, /* 2-digit add-on flag */ ZEBRA_ADDON5 = 0x50, /* 5-digit add-on flag */ + ZEBRA_ADDON = 0x70, /* add-on flag mask */ } zebra_symbol_type_t; +/* return string name for symbol encoding */ +extern const char *zebra_get_symbol_name(zebra_symbol_type_t sym); + +/* return string name for addon encoding */ +extern const char *zebra_get_addon_name(zebra_symbol_type_t sym); + /*------------------------------------------------------------*/ /* high-level bar width stream decoder interface @@ -141,7 +149,14 @@ extern zebra_scanner_t *zebra_scanner_create(zebra_decoder_t *decoder); /* destructor */ extern void zebra_scanner_destroy(zebra_scanner_t *scanner); +/* clear all scanner state. + * also resets an associated decoder + */ extern void zebra_scanner_reset(zebra_scanner_t *scanner); + +/* mark start of a new scan pass, resets color to SPACE. + * also updates an associated decoder + */ extern void zebra_scanner_new_scan(zebra_scanner_t *scanner); /* process next sample intensity value (y) @@ -167,6 +182,81 @@ extern unsigned zebra_scanner_get_width(const zebra_scanner_t *scanner); extern zebra_color_t zebra_scanner_get_color(const zebra_scanner_t *scanner); +/*------------------------------------------------------------*/ +/* 2-D image walker interface + * walks a default scan pattern over image data buffers + * using configured image parameters + */ + +/* opaque walker object */ +struct zebra_img_walker_s; +typedef struct zebra_img_walker_s zebra_img_walker_t; + +/* pixel handler callback function. + * called by image walker for each pixel of the walk. + * any non-zero return value will terminate the walk + * with the returned value. + */ +typedef char (zebra_img_walker_handler_t)(zebra_img_walker_t *walker, + void *pixel); + +/* constructor + * create a new image walker instance. image parameters + * must be initialized before a walk can be started + */ +extern zebra_img_walker_t *zebra_img_walker_create(); + +/* destructor */ +extern void zebra_img_walker_destroy(zebra_img_walker_t *walker); + +/* set the pixel handler */ +extern void zebra_img_walker_set_handler(zebra_img_walker_t *walker, + zebra_img_walker_handler_t *handler); + +/* associate user specified data value with the walker */ +extern void zebra_img_walker_set_userdata(zebra_img_walker_t *walker, + void *userdata); + +/* return user specified data value associated with the decoder */ +extern void *zebra_img_walker_get_userdata(zebra_img_walker_t *walker); + +/* set the width of the image in columns, + * and the height of the image in rows + */ +extern void zebra_img_walker_set_size(zebra_img_walker_t *walker, + unsigned width, + unsigned height); + + +/* (optional) set column and row sizes. + * bytes_per_col is the number of bytes in each column + * of the image buffer (eg, often 1 for YUV format + * and 3 for packed RGB). defaults to 1 if unspecified. + * bytes_per_row is the number of bytes in each row + * of the image buffer. defaults to width * bytes_per_col + * if unspecified + */ +extern void zebra_img_walker_set_stride(zebra_img_walker_t *walker, + unsigned bytes_per_col, + unsigned bytes_per_row); + +/* start walking over specified new image + * returns the first non-zero value returned by the handler, + * 0 when walk completes or -1 if walk cannot start + * (usually because some image parameter is in error). + * NB the image buffer is never dereferenced by the walker, + * a NULL value *will* be walked (which could be used as an offset) + */ +extern char zebra_img_walk(zebra_img_walker_t *walker, + const void *image); + +/* return current column location of walker */ +extern unsigned zebra_img_walker_get_col(zebra_img_walker_t *walker); + +/* return current row location of walker */ +extern unsigned zebra_img_walker_get_row(zebra_img_walker_t *walker); + + #ifdef __cplusplus } } diff --git a/include/zebra/Decoder.h b/include/zebra/Decoder.h index 18b6a17..9893f15 100644 --- a/include/zebra/Decoder.h +++ b/include/zebra/Decoder.h @@ -75,6 +75,16 @@ class Decoder { return(zebra_decoder_get_type(_decoder)); } + const char *get_symbol_name () const + { + return(zebra_get_symbol_name(zebra_decoder_get_type(_decoder))); + } + + const char *get_addon_name () const + { + return(zebra_get_addon_name(zebra_decoder_get_type(_decoder))); + } + const char *get_data_chars() const { return(zebra_decoder_get_data(_decoder)); diff --git a/include/zebra/Scanner.h b/include/zebra/Scanner.h index b0bfe8a..dae3ac3 100644 --- a/include/zebra/Scanner.h +++ b/include/zebra/Scanner.h @@ -102,6 +102,11 @@ class Scanner { return(_type); } + const zebra_scanner_t *get_c_scanner () const + { + return(_scanner); + } + private: zebra_scanner_t *_scanner; zebra_symbol_type_t _type; diff --git a/test/Makefile.am.inc b/test/Makefile.am.inc index dae1eea..f585d14 100644 --- a/test/Makefile.am.inc +++ b/test/Makefile.am.inc @@ -1,2 +1,21 @@ check_PROGRAMS += test/test_decode test_test_decode_LDADD = zebra/libzebra.la + +check_PROGRAMS += test/test_walk +test_test_walk_LDADD = zebra/libzebra.la + +# automake bug in "monolithic mode"? +CLEANFILES += test/.libs/test_decode test/.libs/test_walk + +if HAVE_MAGICK + +check_PROGRAMS += test/dbg_scan +test_dbg_scan_SOURCES = test/dbg_scan.cc +test_dbg_scan_CPPFLAGS = $(MAGICK_CPPFLAGS) $(AM_CPPFLAGS) +test_dbg_scan_CXXFLAGS = $(MAGICK_CXXFLAGS) $(AM_CXXFLAGS) +test_dbg_scan_LDFLAGS = $(MAGICK_LDFLAGS) $(AM_LDFLAGS) +test_dbg_scan_LDADD = $(MAGICK_LIBS) zebra/libzebra.la +# automake bug in "monolithic mode"? +CLEANFILES += test/.libs/dbg_scan + +endif diff --git a/test/dbg_scan.cc b/test/dbg_scan.cc new file mode 100644 index 0000000..ec41c2c --- /dev/null +++ b/test/dbg_scan.cc @@ -0,0 +1,221 @@ +/*------------------------------------------------------------------------ + * Copyright 2007 (c) Jeff Brown + * + * This file is part of the Zebra Barcode Library. + * + * The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zebra + *------------------------------------------------------------------------*/ + +#include +#include +#include +#include + +using namespace std; +using namespace Magick; +using namespace zebra; + +#ifndef ZEBRA_FIXED +# define ZEBRA_FIXED 5 +#endif + +#define ZEBRA_FRAC (1 << ZEBRA_FIXED) + +Decoder decoder; +Scanner scanner; + +/* undocumented API for drawing cutesy debug graphics */ +extern "C" void zebra_scanner_get_state(const zebra_scanner_t *scn, + unsigned *x, + unsigned *cur_edge, + unsigned *last_edge, + int *y0, + int *y1, + int *y2, + int *y1_thresh); + +void scan_image (const char *filename) +{ + scanner.reset(); + // normally scanner would reset associated decoder, + // but this debug program connects them manually + // (to make intermediate state more readily available) + // so decoder must also be reset manually + decoder.reset(); + + Image image; + image.read(filename); + ofstream svg((image.baseFilename() + ".svg").c_str()); + + unsigned width = image.columns() + 4 /* for flush */; + unsigned height = image.rows(); + unsigned midy = (height + 1) / 2; + image.crop(Geometry(width - 4, 1, 0, midy)); + image.size(Geometry(width, 1, 0, 0)); + + svg << "" << endl + << "" << endl + << "" << endl + << "" << endl + << "" << endl + << "" << endl; + + // brute force + unsigned raw[width]; + { + // extract scan from image pixels + image.modifyImage(); + Pixels view(image); + PixelPacket *pxp = view.get(0, 0, width, 1); + ColorYUV y; + svg << "" << endl + << "" << endl; + } + image.depth(8); + image.write(image.baseFilename() + ".png"); + + // process scan and capture calculated values + unsigned cur_edge[width], last_edge[width]; + int y0[width], y1[width], y2[width], y1_thr[width]; + + svg << "" << endl; + for(unsigned i = 0; i < width; i++) { + int edge = scanner.scan_y(raw[i]); + unsigned x; + zebra_scanner_get_state(scanner.get_c_scanner(), &x, + &cur_edge[i], &last_edge[i], + &y0[i], &y1[i], &y2[i], &y1_thr[i]); +#ifdef DEBUG_SCANNER + cerr << endl; +#endif + cur_edge[i] += i - x; + if(edge) { + last_edge[i] += i - x; + unsigned w = scanner.get_width(); + svg << "" << endl + << "" << endl + << w << "" << endl; + zebra_symbol_type_t sym = decoder.decode_width(w); + if(sym > ZEBRA_PARTIAL) { + svg << "" + << decoder.get_data_string() << "" << endl; + } + } + else + last_edge[i] = 0; + } + svg << "" << endl + << "" << endl + << "" << endl + << "" << endl + << "" << endl; + + svg << "" << endl + << "" << endl + << "" << endl + << "" << endl + << "" << endl + << "" << endl + << "" << endl + << "" << endl; + + svg << "" << endl; +} + +int main (int argc, const char *argv[]) +{ + if(argc < 2) { + cerr << "ERROR: specify image file(s) to scan" << endl; + return(1); + } + + for(int i = 1; i < argc; i++) + scan_image(argv[i]); + return(0); +} diff --git a/test/test_walk.c b/test/test_walk.c new file mode 100644 index 0000000..c7b92d4 --- /dev/null +++ b/test/test_walk.c @@ -0,0 +1,83 @@ +/*------------------------------------------------------------------------ + * Copyright 2007 (c) Jeff Brown + * + * This file is part of the Zebra Barcode Library. + * + * The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zebra + *------------------------------------------------------------------------*/ + +#include +#include + +#include + +static unsigned w, h, dx, dy; +static zebra_img_walker_t *walker; + +static char test_handler (zebra_img_walker_t *walker, + void *p) +{ + unsigned x = zebra_img_walker_get_col(walker); + if(x >= w) { + fprintf(stderr, "ERROR: x=%x >= w=%x\n", x, w); + return(-1); + } + unsigned y = zebra_img_walker_get_row(walker); + if(y >= h) { + fprintf(stderr, "ERROR: y=%x >= h=%x\n", y, h); + return(-1); + } + unsigned long t = x * dx + y * dy; + if((unsigned long)p != t) { + fprintf(stderr, "ERROR: %x * %x + %x * %x = %06lx != %06lx\n", + x, dx, y, dy, t, (unsigned long)p); + return(-1); + } + return(0); +} + +int main (int argc, char *argv[]) +{ + if(argc < 3) { + fprintf(stderr, "usage: test_walk " + " [ []]\n"); + return(1); + } + + walker = zebra_img_walker_create(); + + w = strtol(argv[1], NULL, 0); + h = strtol(argv[2], NULL, 0); + zebra_img_walker_set_size(walker, w, h); + + dx = 1; + if(argc >= 4) + dx = strtol(argv[3], NULL, 0); + dy = dx * w; + if(argc >= 5) + dy = strtol(argv[4], NULL, 0); + zebra_img_walker_set_stride(walker, dx, dy); + zebra_img_walker_set_handler(walker, test_handler); + + if(zebra_img_walk(walker, 0)) { + fprintf(stderr, "consistency error!\n"); + return(2); + } + + return(0); +} diff --git a/zebra/Makefile.am.inc b/zebra/Makefile.am.inc index 86d5c54..2b3075f 100644 --- a/zebra/Makefile.am.inc +++ b/zebra/Makefile.am.inc @@ -1,2 +1,3 @@ lib_LTLIBRARIES = zebra/libzebra.la -zebra_libzebra_la_SOURCES = zebra/scanner.c zebra/decoder.c +zebra_libzebra_la_SOURCES = zebra/scanner.c zebra/decoder.c zebra/img_walker.c +zebra_libzebra_la_LDFLAGS = -version-info $(LIB_VERSION) diff --git a/zebra/decoder.c b/zebra/decoder.c index 542a505..b18cb84 100644 --- a/zebra/decoder.c +++ b/zebra/decoder.c @@ -25,7 +25,7 @@ #ifdef DEBUG_DECODER # include /* fprintf */ #endif -#include /* calloc, free */ +#include /* malloc, free */ #include /* memset */ #include @@ -114,8 +114,8 @@ struct zebra_decoder_s { zebra_decoder_t *zebra_decoder_create () { - zebra_decoder_t *dcode = calloc(1, sizeof(zebra_decoder_t)); - zebra_decoder_new_scan(dcode); + zebra_decoder_t *dcode = malloc(sizeof(zebra_decoder_t)); + zebra_decoder_reset(dcode); return(dcode); } @@ -126,14 +126,17 @@ void zebra_decoder_destroy (zebra_decoder_t *dcode) void zebra_decoder_reset (zebra_decoder_t *dcode) { - memset(dcode, 0, sizeof(zebra_decoder_t)); + memset(dcode, 0, (long)&dcode->userdata - (long)dcode); + dcode->scans[0].state = -1; + dcode->scans[1].state = -1; + dcode->scans[2].state = -1; + dcode->scans[3].state = -1; } void zebra_decoder_new_scan (zebra_decoder_t *dcode) { /* soft reset decoder */ - memset(dcode->w, 0, 8 * sizeof(unsigned)); - memset(dcode->buf, 0, 20); + memset(dcode->w, 0, sizeof(dcode->w)); dcode->idx = 0; dcode->scans[0].state = -1; dcode->scans[1].state = -1; @@ -174,6 +177,26 @@ zebra_symbol_type_t zebra_decoder_get_type (const zebra_decoder_t *dcode) : dcode->type); } +const char *zebra_get_symbol_name (zebra_symbol_type_t sym) +{ + switch(sym & ZEBRA_SYMBOL) { + case ZEBRA_EAN8: return("EAN8"); + case ZEBRA_UPCE: return("UPC-E"); + case ZEBRA_UPCA: return("UPC-A"); + case ZEBRA_EAN13: return("EAN-13"); + default: return("UNKNOWN"); + } +} + +const char *zebra_get_addon_name (zebra_symbol_type_t sym) +{ + switch(sym & ZEBRA_ADDON) { + case ZEBRA_ADDON2: return("+2"); + case ZEBRA_ADDON5: return("+5"); + default: return(""); + } +} + /* bar+space width are compared as a fraction of the reference dimension "x" * - +/- 1/2 x tolerance @@ -207,9 +230,8 @@ static inline unsigned width(zebra_decoder_t *dcode, return(dcode->w[(dcode->idx - offset) & 7]); } -/* calculate module width "x" - * - based on total character width "s" - * => start of character identified by context sensitive offset (<= 4) +/* calculate total character width "s" + * => start of character identified by context sensitive offset (<= 4) */ static inline unsigned calc_s (zebra_decoder_t *dcode, unsigned char offset) @@ -259,7 +281,7 @@ static inline char aux_start (zebra_decoder_t *dcode, if((dcode->idx & 1) == ZEBRA_BAR) { /* check for quiet-zone */ - if(width(dcode, 7) > (s * 6 / 7)) { + if((width(dcode, 7) * 14 + 1) / s >= 3) { if(!E1) { dprintf(2, " [valid normal]"); return(0); /* normal symbol start */ @@ -359,8 +381,8 @@ static inline zebra_symbol_type_t partial_end (scan_t *scan, char fwd) unsigned char i; for(i = 1; i < 4; i++) { char tmp = scan->raw[i]; - scan->raw[i] = scan->raw[6 - i]; - scan->raw[6 - i] = tmp; + scan->raw[i] = scan->raw[7 - i]; + scan->raw[7 - i] = tmp; } } @@ -368,7 +390,7 @@ static inline zebra_symbol_type_t partial_end (scan_t *scan, char fwd) return(RIGHT_HALF); if(par & 0x20) return(LEFT_HALF); - return(ZEBRA_UPCE); + return(/*ZEBRA_UPCE*/ZEBRA_NONE); } /* update state for one of 4 parallel scans */ @@ -383,6 +405,8 @@ static inline zebra_symbol_type_t decode_scan (zebra_decoder_t *dcode, : 0x00111111)) { unsigned s = calc_s(dcode, 0); + if(!s) + return(0); dprintf(2, " s=%d", s); /* validate guard bars before decoding first char of symbol */ if(!scan->state) { @@ -422,13 +446,40 @@ static inline zebra_symbol_type_t decode_scan (zebra_decoder_t *dcode, scan->raw[6] & 0xf, part); } else - dprintf(2, " invalid end guard"); + dprintf(2, " [invalid end guard]"); scan->state = -1; return(part); } return(0); } +static inline char check_ean13_parity (zebra_decoder_t *dcode) +{ + unsigned char chk = 0; + unsigned char i; + for(i = 0; i < 12; i++) { + unsigned char d = dcode->buf[i] - '0'; + chk += d; + if(i & 1) { + chk += d << 1; + if(chk >= 20) + chk -= 20; + } + if(chk >= 10) + chk -= 10; + } + assert(chk < 10); + if(chk) + chk = 10 - chk; + unsigned char d = dcode->buf[12] - '0'; + assert(d < 10); + if(chk != d) { + dprintf(1, "checksum mismatch %d != %d (%s)\n", chk, d, dcode->buf); + return(-1); + } + return(0); +} + static inline zebra_symbol_type_t integrate_partial (zebra_decoder_t *dcode, scan_t *scan, zebra_symbol_type_t part) @@ -436,11 +487,10 @@ static inline zebra_symbol_type_t integrate_partial (zebra_decoder_t *dcode, /* FIXME if same partial is not consistent, reset others */ /* FIXME UPC-E, EAN-8 */ unsigned char start; - unsigned char len = 6; + unsigned char len = 7; unsigned char i = 0; if(part == LEFT_HALF) { start = 0; - len = 7; if(dcode->buf[7]) part = ZEBRA_EAN13; } @@ -455,12 +505,18 @@ static inline zebra_symbol_type_t integrate_partial (zebra_decoder_t *dcode, len = (part == ZEBRA_ADDON5) ? 5 : 2; } if(part == ZEBRA_EAN13 && dcode->buf[13]) - part |= ZEBRA_ADDON5; + part |= (dcode->buf[15]) ? ZEBRA_ADDON5 : ZEBRA_ADDON2; /* copy raw data into output buffer */ for(; i < len; i++, start++) dcode->buf[start] = (scan->raw[i] & 0xf) + '0'; + if(part == ZEBRA_EAN13 && + start <= 13 && + check_ean13_parity(dcode)) + /* invalid parity */ + part = ZEBRA_NONE; + return(part); } @@ -483,9 +539,15 @@ zebra_symbol_type_t zebra_decode_width (zebra_decoder_t *dcode, zebra_symbol_type_t part = decode_scan(dcode, &dcode->scans[i]); if(part) { /* update accumulated data from new partial decode */ - /*assert(sym <= 1); FIXME why?! */ sym = integrate_partial(dcode, &dcode->scans[i], part); dcode->type = sym; + if(sym) { + /* this scan valid => _reset_ all scans */ + dcode->scans[0].state = -1; + dcode->scans[1].state = -1; + dcode->scans[2].state = -1; + dcode->scans[3].state = -1; + } } dprintf(2, "\n"); } diff --git a/zebra/img_walker.c b/zebra/img_walker.c new file mode 100644 index 0000000..2071546 --- /dev/null +++ b/zebra/img_walker.c @@ -0,0 +1,222 @@ +/*------------------------------------------------------------------------ + * Copyright 2007 (c) Jeff Brown + * + * This file is part of the Zebra Barcode Library. + * + * The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zebra + *------------------------------------------------------------------------*/ + +#include +#ifdef DEBUG_IMG_WALKER +# include /* fprintf */ +#endif +#include /* malloc, free */ +#include + +#include "zebra.h" + +#ifdef DEBUG_IMG_WALKER +# define dprintf(...) \ + fprintf(stderr, __VA_ARGS__) +#else +# define dprintf(...) +#endif + +/* image walker state */ +struct zebra_img_walker_s { + unsigned x, y; /* current column and row */ + unsigned w, h; /* configured width and height */ + unsigned dx, dy; /* configured bytes_per_col and bytes_per_row */ + void *userdata; /* application data */ + zebra_img_walker_handler_t *handler; +}; + +zebra_img_walker_t *zebra_img_walker_create () +{ + zebra_img_walker_t *walk = malloc(sizeof(zebra_img_walker_t)); + return(walk); +} + +void zebra_img_walker_destroy (zebra_img_walker_t *walk) +{ + free(walk); +} + +void zebra_img_walker_set_handler (zebra_img_walker_t *walk, + zebra_img_walker_handler_t *handler) +{ + walk->handler = handler; +} + +void zebra_img_walker_set_userdata (zebra_img_walker_t *walk, + void *userdata) +{ + walk->userdata = userdata; +} + +void *zebra_img_walker_get_userdata (zebra_img_walker_t *walk) +{ + return(walk->userdata); +} + +void zebra_img_walker_set_size (zebra_img_walker_t *walk, + unsigned width, + unsigned height) +{ + walk->w = width; + walk->h = height; +} + +void zebra_img_walker_set_stride (zebra_img_walker_t *walk, + unsigned dx, + unsigned dy) +{ + walk->dx = dx; + walk->dy = dy; +} + +unsigned zebra_img_walker_get_col (zebra_img_walker_t *walk) +{ + return(walk->x); +} + +unsigned zebra_img_walker_get_row (zebra_img_walker_t *walk) +{ + return(walk->y); +} + +typedef struct walk_state_s { + unsigned pdx, pdy; + unsigned x0, y0; + int du, pdu; + const void *p0; +} walk_state_t; + +static char walk_x (zebra_img_walker_t *walk, + walk_state_t *st) +{ + int err = walk->h - walk->w; + const void *p = st->p0; + walk->x = st->x0; + walk->y = st->y0; + while(walk->y < walk->h) { + if(!walk->x || (walk->y == st->y0)) + dprintf("walk_x: %03x,%03x (%06lx)\n", + walk->x, walk->y, (unsigned long)p); + if(walk->handler) { + char rc; + if((rc = walk->handler(walk, (void*)p))) + return(rc); + } + if(err >= 0) { + walk->y += st->du; + p += st->pdu; + err -= walk->w * 2; + } + err += walk->h; + p += st->pdx; + if(++walk->x >= walk->w) { + walk->x = 0; + p -= st->pdy; + } + } + return(0); +} + +static char walk_y (zebra_img_walker_t *walk, + walk_state_t *st) +{ + int err = walk->w - walk->h; + const void *p = st->p0; + walk->x = st->x0; + walk->y = st->y0; + while(walk->y < walk->h) { + if(!walk->x || (walk->y == st->y0)) + dprintf("walk_y: %03x,%03x (%06lx)\n", + walk->x, walk->y, (unsigned long)p); + if(walk->handler) { + char rc; + if((rc = walk->handler(walk, (void*)p))) + return(rc); + } + if(err >= 0) { + if(++walk->x >= walk->w) { + walk->x = 0; + p -= st->pdy; + } + p += st->pdx; + err -= walk->h * 2; + } + err += walk->w; + p += st->pdu; + walk->y += st->du; + } + return(0); +} + +char zebra_img_walk (zebra_img_walker_t *walk, + const void *image) +{ + if(!walk->w || !walk->h) + return(-1); + + char rc; + walk_state_t st; + st.pdx = (walk->dx) ? walk->dx : 1; + unsigned dx_w = st.pdx * walk->w; + st.pdy = (walk->dy >= dx_w) ? walk->dy : dx_w; + + /* FIXME sanitize parameters (no inf loops!) */ + dprintf("walk: w=%x h=%x dx=%x dy=%x x=%x y=%x\n", + walk->w, walk->h, st.pdx, st.pdy, walk->x, walk->y); + + unsigned di = walk->w / 4 /* density (FIXME config) */; + unsigned long dp = di * st.pdx; + st.x0 = st.y0 = 0; + st.p0 = image; + st.du = 1; + st.pdu = st.pdy; + for(st.x0 = 0; st.x0 < walk->w; st.x0 += di, st.p0 += dp) + if((rc = walk_x(walk, &st))) + return(rc); + + st.y0 = walk->h - 1; + st.p0 = image + st.pdy * st.y0; + st.pdu = -st.pdy; + st.du = -1; + for(st.x0 = 0; st.x0 < walk->w; st.x0 += di, st.p0 += dp) + if((rc = walk_x(walk, &st))) + return(rc); + + di /= 2; + dp /= 2; + st.p0 = image + st.pdy * st.y0; + for(st.x0 = 0; st.x0 < walk->w; st.x0 += di, st.p0 += dp) + if((rc = walk_y(walk, &st))) + return(rc); + + st.y0 = 0; + st.p0 = image; + st.du = 1; + st.pdu = st.pdy; + for(st.x0 = 0; st.x0 < walk->w; st.x0 += di, st.p0 += dp) + if((rc = walk_y(walk, &st))) + return(rc); + + return(0); +} diff --git a/zebra/scanner.c b/zebra/scanner.c index 8423482..41b3063 100644 --- a/zebra/scanner.c +++ b/zebra/scanner.c @@ -25,7 +25,8 @@ #ifdef DEBUG_SCANNER # include /* fprintf */ #endif -#include /* calloc, free, abs */ +#include /* malloc, free, abs */ +#include /* memset */ #include "zebra.h" @@ -43,13 +44,13 @@ /* scanner state */ struct zebra_scanner_s { zebra_decoder_t *decoder; /* associated bar width decoder */ + unsigned y1_min_thresh; /* minimum threshold */ unsigned x; /* relative scan position of next sample */ int y0[4]; /* short circular buffer of average intensities */ int y1_sign; /* slope at last crossing */ unsigned y1_thresh; /* current slope threshold */ - unsigned y1_min_thresh; /* minimum threshold */ unsigned cur_edge; /* interpolated position of tracking edge */ unsigned last_edge; /* interpolated position of last located edge */ @@ -58,9 +59,10 @@ struct zebra_scanner_s { zebra_scanner_t *zebra_scanner_create (zebra_decoder_t *dcode) { - zebra_scanner_t *scn = calloc(1, sizeof(zebra_scanner_t)); + zebra_scanner_t *scn = malloc(sizeof(zebra_scanner_t)); scn->decoder = dcode; - scn->y1_thresh = scn->y1_min_thresh = 8; + scn->y1_min_thresh = 4; + zebra_scanner_reset(scn); return(scn); } @@ -69,6 +71,25 @@ void zebra_scanner_destroy (zebra_scanner_t *scn) free(scn); } +void zebra_scanner_reset (zebra_scanner_t *scn) +{ + memset(&scn->x, 0, sizeof(zebra_scanner_t) + (void*)scn - (void*)&scn->x); + scn->y1_thresh = scn->y1_min_thresh; + if(scn->decoder) + zebra_decoder_reset(scn->decoder); +} + +void zebra_scanner_new_scan (zebra_scanner_t *scn) +{ + /* reset color to SPACE + * (actually just resets everything) + */ + memset(&scn->x, 0, sizeof(zebra_scanner_t) + (void*)scn - (void*)&scn->x); + scn->y1_thresh = scn->y1_min_thresh; + if(scn->decoder) + zebra_decoder_new_scan(scn->decoder); +} + unsigned zebra_scanner_get_width (const zebra_scanner_t *scn) { return(scn->width); @@ -105,9 +126,10 @@ static inline zebra_symbol_type_t process_edge (zebra_scanner_t *scn, int y1) { scn->width = scn->cur_edge - scn->last_edge; - dprintf(" sgn=%d cur=%d.%d w=%d\n", + dprintf(" sgn=%d cur=%d.%d w=%d (%s)\n", scn->y1_sign, scn->cur_edge >> ZEBRA_FIXED, - scn->cur_edge & ((1 << ZEBRA_FIXED) - 1), scn->width); + scn->cur_edge & ((1 << ZEBRA_FIXED) - 1), scn->width, + ((y1 > 0) ? "SPACE" : "BAR")); scn->last_edge = scn->cur_edge; /* adaptive thresholding */ @@ -117,8 +139,7 @@ static inline zebra_symbol_type_t process_edge (zebra_scanner_t *scn, scn->y1_thresh = scn->y1_min_thresh; /* pass to decoder */ - if(scn->width) { - scn->y1_sign = y1; + if(scn->width || (y1 > 0)) { if(scn->decoder) return(zebra_decode_width(scn->decoder, scn->width)); return(ZEBRA_PARTIAL); @@ -137,14 +158,16 @@ zebra_symbol_type_t zebra_scan_y (zebra_scanner_t *scn, /* update weighted moving average */ y0_0 = scn->y0[scn->x & 3] = y0_1 + ((y - y0_1 + 1) / 2); else - y0_0 = scn->y0[0] = scn->y0[1] = scn->y0[2] = scn->y0[3] = y; + y0_0 = y0_1 = scn->y0[0] = scn->y0[1] = scn->y0[2] = scn->y0[3] = y; register int y0_2 = scn->y0[(scn->x - 2) & 3]; register int y0_3 = scn->y0[(scn->x - 3) & 3]; /* 1st differential @ x-1 */ register int y1_1 = y0_0 - y0_2; { register int y1_2 = y0_1 - y0_3; - if(abs(y1_1) < abs(y1_2)) y1_1 = y1_2; + if((abs(y1_1) < abs(y1_2)) && + ((y1_1 >= 0) == (y1_2 >= 0))) + y1_1 = y1_2; } /* 2nd differentials @ x-1 & x-2 */ register int y2_1 = y0_0 - (y0_1 * 2) + y0_2; @@ -156,24 +179,28 @@ zebra_symbol_type_t zebra_scan_y (zebra_scanner_t *scn, /* 2nd zero-crossing is 1st local min/max - could be edge */ if((!y2_1 || ((y2_1 > 0) ? y2_2 < 0 : y2_2 > 0)) && - (calc_thresh(scn) < abs(y1_1))) + (calc_thresh(scn) <= abs(y1_1))) { /* check for 1st sign change */ - if((scn->y1_sign > 0) ? y1_1 < 0 : y1_1 > 0) + char y1_rev = (scn->y1_sign > 0) ? y1_1 < 0 : y1_1 > 0; + if(y1_rev || !scn->y1_sign) /* intensity change reversal - finalize previous edge */ edge = process_edge(scn, y1_1); else dprintf("\n"); - /* update current edge */ - int d = y2_1 - y2_2; - scn->cur_edge = 1 << ZEBRA_FIXED; - if(!d) - scn->cur_edge >>= 1; - else if(y2_1) - /* interpolate zero crossing */ - scn->cur_edge -= ((y2_1 << ZEBRA_FIXED) + 1) / d; - scn->cur_edge += scn->x << ZEBRA_FIXED; + if(y1_rev || (abs(scn->y1_sign) < abs(y1_1))) { + /* update current edge */ + scn->y1_sign = y1_1; + int d = y2_1 - y2_2; + scn->cur_edge = 1 << ZEBRA_FIXED; + if(!d) + scn->cur_edge >>= 1; + else if(y2_1) + /* interpolate zero crossing */ + scn->cur_edge -= ((y2_1 << ZEBRA_FIXED) + 1) / d; + scn->cur_edge += scn->x << ZEBRA_FIXED; + } } else dprintf("\n"); @@ -193,14 +220,15 @@ void zebra_scanner_get_state (const zebra_scanner_t *scn, int *y2, int *y1_thresh) { - register int y0_0 = scn->y0[scn->x & 0x3]; - register int y0_1 = scn->y0[(scn->x - 1) & 3]; - register int y0_2 = scn->y0[(scn->x - 2) & 3]; + register int y0_0 = scn->y0[(scn->x - 1) & 3]; + register int y0_1 = scn->y0[(scn->x - 2) & 3]; + register int y0_2 = scn->y0[(scn->x - 3) & 3]; if(x) *x = scn->x - 1; if(cur_edge) *cur_edge = scn->cur_edge; if(last_edge) *last_edge = scn->last_edge; if(y0) *y0 = y0_1; if(y1) *y1 = y0_0 - y0_2; if(y2) *y2 = y0_0 - (y0_1 * 2) + y0_2; + /* NB not quite accurate (uses updated x) */ if(y1_thresh) *y1_thresh = calc_thresh((zebra_scanner_t*)scn); } diff --git a/zebracam/zebracam.c b/zebracam/zebracam.c index b19a392..8f2945b 100644 --- a/zebracam/zebracam.c +++ b/zebracam/zebracam.c @@ -25,17 +25,24 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include #include "zebra.h" +#define DUMP_NAME_MAX 0x20 +#define PPM_HDR_MAX 0x20 +#define SYM_MAX 0x20 +#define SYM_HYST 2000 /* ms */ + static int cam_fd; static struct video_capability vcap; static struct video_window vwin; @@ -46,10 +53,24 @@ struct video_mmap vmap; void *image; SDL_Surface *screen; uint8_t *buf; -int streaming = 1, dump = 0; +int streaming = 1, dumping = 0; +uint64_t nframes = 0; +double last_frame_time = 0; + +SDL_AudioSpec audio; +#define TONE_MAX 4096 +static char tone[TONE_MAX]; +int tone_period = 20; + +zebra_symbol_type_t last_sym_type; +char last_sym_data[SYM_MAX]; +double last_sym_time = 0; + +double beep_time = 0; zebra_decoder_t *decoder; zebra_scanner_t *scanner; +zebra_img_walker_t *walker; static void init_cam () { @@ -63,7 +84,7 @@ static void init_cam () perror("ERROR VIDIOCGCAP: v4l unsupported\n"); exit(1); } - printf("found device: \"%s\"\n", vcap.name); + fprintf(stderr, "found device: \"%s\"\n", vcap.name); /* initialize window properties */ @@ -86,8 +107,8 @@ static void init_cam () } } size = vwin.width * vwin.height; - printf(" win: %dx%d @(%d, %d) = 0x%x bytes\n", - vwin.width, vwin.height, vwin.x, vwin.y, size); + fprintf(stderr, " win: %dx%d @(%d, %d) = 0x%x bytes\n", + vwin.width, vwin.height, vwin.x, vwin.y, size); /* setup image properties */ @@ -112,10 +133,10 @@ static void init_cam () exit(1); } } - printf(" pict: brite=%04x hue=%04x color=%04x con=%04x" - " wht=%04x deep=%04x pal=%04x\n", - vpic.brightness, vpic.hue, vpic.colour, vpic.contrast, - vpic.whiteness, vpic.depth, vpic.palette); + fprintf(stderr, " pict: brite=%04x hue=%04x color=%04x con=%04x" + " wht=%04x deep=%04x pal=%04x\n", + vpic.brightness, vpic.hue, vpic.colour, vpic.contrast, + vpic.whiteness, vpic.depth, vpic.palette); /* map camera image to memory */ @@ -123,8 +144,8 @@ static void init_cam () perror("ERROR VIDIOCGMBUF"); exit(1); } - printf(" buf: size=%x num=%x [0]=%x [1]=%x\n", - vbuf.size, vbuf.frames, vbuf.offsets[0], vbuf.offsets[1]); + fprintf(stderr, " buf: size=%x num=%x [0]=%x [1]=%x\n", + vbuf.size, vbuf.frames, vbuf.offsets[0], vbuf.offsets[1]); /* only need double buffer */ if(vbuf.frames > 2) @@ -139,10 +160,18 @@ static void init_cam () vmap.format = vpic.palette; } +static void audio_cb (void *userdata, + uint8_t *stream, + int len) +{ + memcpy(stream, tone, len); + SDL_PauseAudio(1); +} + static void init_sdl () { /* initialize SDL */ - if(SDL_Init(SDL_INIT_VIDEO) < 0) { + if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { fprintf(stderr, "ERROR initializing SDL: %s\n", SDL_GetError()); exit(1); } @@ -156,24 +185,47 @@ static void init_sdl () fprintf(stderr, "ERROR setting video mode: %s\n", SDL_GetError()); exit(1); } - SDL_ShowCursor(1); + + SDL_AudioSpec audio; + audio.freq = 11025; + audio.format = AUDIO_S8; + audio.channels = 1; + audio.samples = TONE_MAX; + audio.callback = audio_cb; + audio.userdata = NULL; + if(SDL_OpenAudio(&audio, NULL) < 0) { + fprintf(stderr, "ERROR initializing SDL audio: %s\n", SDL_GetError()); + exit(1); + } + fprintf(stderr, "audio: size=%04x silence=%02x\n", + audio.size, audio.silence); + int i; + for(i = 0; (i % tone_period) || (i + tone_period < TONE_MAX); i++) + tone[i] = ((i % tone_period) > (tone_period + 1) / 2) ? 0x7f : -0x7f; + for(; i < TONE_MAX; i++) + tone[i] = audio.silence; } static inline int handle_events () { SDL_Event e; while(SDL_PollEvent(&e)) { - if(e.type == SDL_QUIT || - (e.type == SDL_KEYDOWN && - e.key.keysym.sym == SDLK_q)) - /* exit condition */ + if(e.type == SDL_QUIT) return(1); - if(e.type == SDL_KEYDOWN && - e.key.keysym.sym == SDLK_SPACE) { - /* pause/resume */ - streaming = !streaming; - dump = !streaming; + if(e.type == SDL_KEYDOWN) { + switch(e.key.keysym.sym) { + case SDLK_q: + return(1); + case SDLK_SPACE: + streaming = !streaming; /* pause/resume */ + break; + case SDLK_d: + dumping = 1; /* dump next frame */ + break; + default: + /* ignore */; + } } } return(0); @@ -201,18 +253,70 @@ static inline void display () memcpy(screen->pixels, buf, size * 3); } -static void process () +static inline void dump () { - uint32_t dy = vwin.width * 3; - uint8_t *p = buf + ((vwin.height + 1) >> 1) * dy; - int i; - for(i = 0; i < vwin.width; i++, p += 3) { - if(zebra_scan_rgb24(scanner, p) > 1) - printf("%x: %s\n", - zebra_decoder_get_type(decoder), - zebra_decoder_get_data(decoder)); - *(p + 2) = 0xff; + char name[DUMP_NAME_MAX]; + int len = snprintf(name, DUMP_NAME_MAX, "zebracam-%08llx.ppm", nframes); + assert(len < DUMP_NAME_MAX); + FILE *f = fopen(name, "w"); + if(!f) { + perror("ERROR opening dump file"); + return; + } + char hdr[PPM_HDR_MAX]; + len = snprintf(hdr, PPM_HDR_MAX, "P6\n%d %d\n255\n", + vwin.width, vwin.height); + assert(len < PPM_HDR_MAX); + if(fwrite(hdr, len, 1, f) != 1 || + /* FIXME RB planes swapped... (SDL/v4l is BGR, PPM is RGB) */ + fwrite(buf, 3, size, f) != size) + perror("ERROR dumping to file"); + fclose(f); + fprintf(stderr, "dumped frame to %s\n", name); + dumping = 0; +} + +static inline void process () +{ + zebra_scanner_new_scan(scanner); + zebra_img_walk(walker, buf); +} + +static void symbol_handler (zebra_decoder_t *decoder) +{ + zebra_symbol_type_t sym = zebra_decoder_get_type(decoder); + if(sym <= ZEBRA_PARTIAL) + return; + const char *data = zebra_decoder_get_data(decoder); + + double ms = SDL_GetTicks(); + /* edge detect symbol change w/some hysteresis */ + if(sym == last_sym_type && + !strncmp(data, last_sym_data, SYM_MAX) && + ((ms - last_sym_time) < SYM_HYST)) { + last_sym_time = ms; + return; } + + /* report new symbol */ + last_sym_time = ms; + last_sym_type = sym; + strncpy(last_sym_data, data, SYM_MAX); + printf("%s%s: %s\n", + zebra_get_symbol_name(sym), + zebra_get_addon_name(sym), + zebra_decoder_get_data(decoder)); + beep_time = ms; + SDL_PauseAudio(0); +} + +static char pixel_handler (zebra_img_walker_t *walker, + void *p) +{ + if(zebra_scan_rgb24(scanner, p) > ZEBRA_PARTIAL) + return(1); + *((char*)p + 2) = 0xff; + return(0); } @@ -221,16 +325,26 @@ int main (int argc, const char *argv[]) /* initialization */ init_cam(); init_sdl(); + + /* create decoder object */ decoder = zebra_decoder_create(); + /* attach callback */ + zebra_decoder_set_handler(decoder, symbol_handler); + + /* attach new scanner to decoder */ scanner = zebra_scanner_create(decoder); + /* setup image scan pattern walker */ + walker = zebra_img_walker_create(); + zebra_img_walker_set_size(walker, vwin.width, vwin.height); + zebra_img_walker_set_stride(walker, 3, 0); /* RGB */ + zebra_img_walker_set_handler(walker, pixel_handler); + /* main loop */ int frame = 0; capture(frame); capture(1); - int nframes = 0; - while(!handle_events()) { /* wait for latest image */ sync(frame); @@ -239,7 +353,8 @@ int main (int argc, const char *argv[]) if(streaming) { if(SDL_MUSTLOCK(screen) && SDL_LockSurface (screen) < 0) { - fprintf(stderr, "ERROR SDL failed to lock screen surface: %s\n", + fprintf(stderr, + "ERROR SDL failed to lock screen surface: %s\n", SDL_GetError()); return(1); } @@ -250,24 +365,27 @@ int main (int argc, const char *argv[]) /* show result onscreen */ display(); + /* dump frame to file */ + if(dumping) + dump(); + if(SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen); SDL_Flip(screen); } - else if(dump) { - process(); - dump = 0; - } + else if(dumping) + dump(); /* re-start capture of image */ capture(frame); nframes++; - if(!(nframes & 0xf)) { - double ms = SDL_GetTicks(); + double ms = SDL_GetTicks(); + if(ms >= last_frame_time + 10000) { + last_frame_time += 10000; double fr = nframes * 1000. / ms; - printf("@%g %gfps\n", ms, fr); + fprintf(stderr, "@%g %gfps\n", ms, fr); } frame = (frame + 1) % vbuf.frames; } diff --git a/zebraimg/zebraimg.cpp b/zebraimg/zebraimg.cpp index fafbb86..a2fc89b 100644 --- a/zebraimg/zebraimg.cpp +++ b/zebraimg/zebraimg.cpp @@ -36,8 +36,8 @@ class ImageHandler : public Decoder::Handler { virtual void decode_callback (Decoder &decoder) { if(decoder.get_type() > ZEBRA_PARTIAL) - cout << decoder.get_type() << ": " - << decoder.get_data_string() << endl; + cout << decoder.get_symbol_name() << decoder.get_addon_name() + << ": " << decoder.get_data_string() << endl; } }; @@ -49,6 +49,7 @@ void scan_image (const char *filename) { Image image; image.read(filename); + unsigned width = image.columns(); unsigned height = image.rows(); @@ -65,13 +66,22 @@ void scan_image (const char *filename) *pxp++ = red; } view.sync(); - y.y(y.y() * .75); - scanner << (int)(y.y() * 0x100) - << (int)(y.y() * 0x100) - << (int)(y.y() * 0x100); /* flush scan FIXME? */ + int iy = (int)(y.y() * .75) * 0x100; + scanner << iy << iy << iy; /* flush scan FIXME? */ - if(display) + if(display) { +#if (MagickLibVersion >= 0x632) + image.display(); +#else + // workaround for "no window with specified ID exists" bug + // ref http://www.imagemagick.org/discourse-server/viewtopic.php?t=6315 + // fixed in 6.3.1-25 + char c = image.imageInfo()->filename[0]; + image.imageInfo()->filename[0] = 0; image.display(); + image.imageInfo()->filename[0] = c; +#endif + } } int usage (int rc, const char *msg = NULL) From 9cf06621aa151684e92109096cd8b8b19d352368 Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 24 Mar 2007 20:24:27 +0000 Subject: [PATCH 004/328] fix scanner runaway threshold calculation bug fix zebracam/zebraimg bugs overwriting currently scanning image w/scan pattern add c++ interface to img_walker apply ImageWalker to zebraimg add decoder soft reset on partial mismatch --- TODO | 6 +-- include/zebra.h | 1 + include/zebra/ImageWalker.h | 97 +++++++++++++++++++++++++++++++++++++ zebra/decoder.c | 61 +++++++++++++++-------- zebra/scanner.c | 20 +++++--- zebracam/zebracam.c | 10 ++-- zebraimg/zebraimg.cpp | 64 ++++++++++++++---------- 7 files changed, 198 insertions(+), 61 deletions(-) create mode 100644 include/zebra/ImageWalker.h diff --git a/TODO b/TODO index da7c6af..763aa73 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,5 @@ - * C++ interface to img_walker - * img_walker should have userdata - * scanner: resolve int/fixed inconsistency bug - * soft reset when partial mismatches same slot + * better C++ interface to img_walker + * nice to match STL iterator interface * finish UPC-E, EAN-8 and addon decoding * profile and weed out obvious oversights * documentation diff --git a/include/zebra.h b/include/zebra.h index cd3cf5c..8931b9b 100644 --- a/include/zebra.h +++ b/include/zebra.h @@ -263,6 +263,7 @@ extern unsigned zebra_img_walker_get_row(zebra_img_walker_t *walker); # include "zebra/Decoder.h" # include "zebra/Scanner.h" +# include "zebra/ImageWalker.h" #endif #endif diff --git a/include/zebra/ImageWalker.h b/include/zebra/ImageWalker.h new file mode 100644 index 0000000..5144e61 --- /dev/null +++ b/include/zebra/ImageWalker.h @@ -0,0 +1,97 @@ +//------------------------------------------------------------------------ +// Copyright 2007 (c) Jeff Brown +// +// This file is part of the Zebra Barcode Library. +// +// The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free +// Software Foundation, Inc., 51 Franklin St, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// http://sourceforge.net/projects/zebra +//------------------------------------------------------------------------ +#ifndef _ZEBRA_IMAGE_WALKER_H_ +#define _ZEBRA_IMAGE_WALKER_H_ + +#ifndef _ZEBRA_H_ +# error "include zebra.h in your application, **not** zebra/ImageWalker.h" +#endif + +namespace zebra { + +class ImageWalker { + public: + class Handler { + public: + virtual char walker_callback(ImageWalker &walker, void *pixel) = 0; + }; + + ImageWalker () + : _handler(NULL) + { + _walker = zebra_img_walker_create(); + } + + ~ImageWalker () + { + zebra_img_walker_destroy(_walker); + } + + void set_size (unsigned width, unsigned height) + { + zebra_img_walker_set_size(_walker, width, height); + } + + void set_stride (unsigned bytes_per_col, unsigned bytes_per_row) + { + zebra_img_walker_set_stride(_walker, bytes_per_col, bytes_per_row); + } + + char walk (const void *image) + { + return(zebra_img_walk(_walker, image)); + } + + unsigned get_col() + { + return(zebra_img_walker_get_col(_walker)); + } + + unsigned get_row() + { + return(zebra_img_walker_get_row(_walker)); + } + + void set_handler (Handler &handler) + { + _handler = &handler; + zebra_img_walker_set_handler(_walker, _cb); + zebra_img_walker_set_userdata(_walker, this); + } + + private: + zebra_img_walker_t *_walker; + Handler *_handler; + + static char _cb (zebra_img_walker_t *cwalk, void *pixel) + { + ImageWalker *walk = (ImageWalker*)zebra_img_walker_get_userdata(cwalk); + if(walk && walk->_handler) + return(walk->_handler->walker_callback(*walk, pixel)); + return(0); + } +}; + +} + +#endif diff --git a/zebra/decoder.c b/zebra/decoder.c index b18cb84..8688655 100644 --- a/zebra/decoder.c +++ b/zebra/decoder.c @@ -484,39 +484,62 @@ static inline zebra_symbol_type_t integrate_partial (zebra_decoder_t *dcode, scan_t *scan, zebra_symbol_type_t part) { - /* FIXME if same partial is not consistent, reset others */ /* FIXME UPC-E, EAN-8 */ - unsigned char start; - unsigned char len = 7; - unsigned char i = 0; + /* copy raw data into output buffer */ + /* if same partial is not consistent, reset others */ + unsigned char i; if(part == LEFT_HALF) { - start = 0; - if(dcode->buf[7]) + if(dcode->buf[0] && dcode->buf[7]) part = ZEBRA_EAN13; + + for(i = 0; i < 7; i++) { + char ch = (scan->raw[i] & 0xf) + '0'; + if(part == ZEBRA_EAN13 && + dcode->buf[i] != ch) { + /* partial mismatch - reset other parts */ + dcode->buf[7] = dcode->buf[13] = 0; + part = ZEBRA_PARTIAL; + } + dcode->buf[i] = ch; + } } else if(part == RIGHT_HALF) { - i = 1; - start = 7; - if(dcode->buf[0]) + if(dcode->buf[0] && dcode->buf[7]) part = ZEBRA_EAN13; + for(i = 0; i < 6; i++) { + char ch = (scan->raw[i + 1] & 0xf) + '0'; + if(part == ZEBRA_EAN13 && + dcode->buf[i + 7] != ch) { + /* partial mismatch - reset other parts */ + dcode->buf[0] = dcode->buf[13] = 0; + part = ZEBRA_PARTIAL; + } + dcode->buf[i + 7] = ch; + } } else { - start = 13; - len = (part == ZEBRA_ADDON5) ? 5 : 2; + unsigned char len = (part == ZEBRA_ADDON5) ? 5 : 2; + if(dcode->buf[0] && dcode->buf[7] && dcode->buf[13]) + part |= ZEBRA_EAN13; + for(i = 0; i < len; i++) { + char ch = (scan->raw[i] & 0xf) + '0'; + if((part & ZEBRA_SYMBOL) == ZEBRA_EAN13 && + dcode->buf[i + 13] != ch) { + /* partial mismatch - reset other parts */ + dcode->buf[0] = dcode->buf[7] = 0; + part &= ZEBRA_ADDON; + } + dcode->buf[i + 13] = ch; + } } - if(part == ZEBRA_EAN13 && dcode->buf[13]) - part |= (dcode->buf[15]) ? ZEBRA_ADDON5 : ZEBRA_ADDON2; - - /* copy raw data into output buffer */ - for(; i < len; i++, start++) - dcode->buf[start] = (scan->raw[i] & 0xf) + '0'; - if(part == ZEBRA_EAN13 && - start <= 13 && check_ean13_parity(dcode)) /* invalid parity */ part = ZEBRA_NONE; + if(part == ZEBRA_EAN13 && dcode->buf[13]) + part |= (dcode->buf[15]) ? ZEBRA_ADDON5 : ZEBRA_ADDON2; + return(part); } diff --git a/zebra/scanner.c b/zebra/scanner.c index 41b3063..ebd85e2 100644 --- a/zebra/scanner.c +++ b/zebra/scanner.c @@ -27,6 +27,7 @@ #endif #include /* malloc, free, abs */ #include /* memset */ +#include #include "zebra.h" @@ -109,17 +110,20 @@ static inline unsigned calc_thresh (zebra_scanner_t *scn) return(scn->y1_min_thresh); } /* slowly return threshold to min */ - unsigned long t = thresh * ((scn->x << ZEBRA_FIXED) - scn->last_edge); + unsigned dx = (scn->x << ZEBRA_FIXED) - scn->last_edge; + unsigned long t = thresh * dx; t /= scn->width; t /= 4; /* FIXME add config API */ - t = ((t >> (ZEBRA_FIXED - 1)) + 1) >> 1; - thresh -= t; - dprintf(" thr=%d t=%ld x=%d last=%d.%d", + dprintf(" thr=%d t=%ld x=%d last=%d.%d (%d)", thresh, t, scn->x, scn->last_edge >> ZEBRA_FIXED, - scn->last_edge & ((1 << ZEBRA_FIXED) - 1)); - if(thresh < scn->y1_min_thresh) - thresh = scn->y1_thresh = scn->y1_min_thresh; - return(thresh); + scn->last_edge & ((1 << ZEBRA_FIXED) - 1), dx); + if(thresh > t) { + thresh -= t; + if(thresh > scn->y1_min_thresh) + return(thresh); + } + scn->y1_thresh = scn->y1_min_thresh; + return(scn->y1_min_thresh); } static inline zebra_symbol_type_t process_edge (zebra_scanner_t *scn, diff --git a/zebracam/zebracam.c b/zebracam/zebracam.c index 8f2945b..0d445be 100644 --- a/zebracam/zebracam.c +++ b/zebracam/zebracam.c @@ -315,7 +315,7 @@ static char pixel_handler (zebra_img_walker_t *walker, { if(zebra_scan_rgb24(scanner, p) > ZEBRA_PARTIAL) return(1); - *((char*)p + 2) = 0xff; + *((uint8_t*)p - buf + (uint8_t*)screen->pixels + 2) = 0xff; return(0); } @@ -359,19 +359,19 @@ int main (int argc, const char *argv[]) return(1); } - /* application processing */ - process(); - /* show result onscreen */ display(); + /* application processing */ + process(); + /* dump frame to file */ if(dumping) dump(); if(SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen); - + SDL_Flip(screen); } else if(dumping) diff --git a/zebraimg/zebraimg.cpp b/zebraimg/zebraimg.cpp index a2fc89b..c206adc 100644 --- a/zebraimg/zebraimg.cpp +++ b/zebraimg/zebraimg.cpp @@ -31,55 +31,68 @@ using namespace zebra; int display = 0; +Decoder decoder; +Scanner scanner(decoder); +ImageWalker walker; +const PixelPacket *rd_pxp; +PixelPacket *wr_pxp; + +Color red("red"); + +class PixelHandler : public ImageWalker::Handler { + virtual char walker_callback (ImageWalker &, void *pixel) + { + ColorYUV y; + y = *(rd_pxp + (unsigned)pixel); + scanner << (int)(y.y() * 0x100); + *(wr_pxp + (unsigned)pixel) = red; + return(0); + } +} pixel_handler; -class ImageHandler : public Decoder::Handler { +class SymbolHandler : public Decoder::Handler { virtual void decode_callback (Decoder &decoder) { if(decoder.get_type() > ZEBRA_PARTIAL) cout << decoder.get_symbol_name() << decoder.get_addon_name() << ": " << decoder.get_data_string() << endl; } -}; - -ImageHandler handler; -Decoder decoder; -Scanner scanner(decoder); +} symbol_handler; void scan_image (const char *filename) { Image image; image.read(filename); + Image wr_img = image; unsigned width = image.columns(); unsigned height = image.rows(); + walker.set_size(width, height); - Color red("red"); - image.modifyImage(); + wr_img.modifyImage(); // extract image pixels - Pixels view(image); - PixelPacket *pxp = view.get(0, (height + 1) / 2, width, 1); - ColorYUV y; - for(unsigned i = 0; i < width; i++) { - y = *pxp; - scanner << (int)(y.y() * 0x100); - *pxp++ = red; - } - view.sync(); - int iy = (int)(y.y() * .75) * 0x100; - scanner << iy << iy << iy; /* flush scan FIXME? */ + Pixels rd_view(image); + rd_pxp = rd_view.getConst(0, 0, width, height); + Pixels wr_view(wr_img); + wr_pxp = wr_view.get(0, 0, width, height); + walker.walk(0); + assert(*rd_pxp != red); + + wr_view.sync(); + scanner << 0 << 0 << 0; /* flush scan FIXME? */ if(display) { #if (MagickLibVersion >= 0x632) - image.display(); + wr_img.display(); #else // workaround for "no window with specified ID exists" bug // ref http://www.imagemagick.org/discourse-server/viewtopic.php?t=6315 // fixed in 6.3.1-25 - char c = image.imageInfo()->filename[0]; - image.imageInfo()->filename[0] = 0; - image.display(); - image.imageInfo()->filename[0] = c; + char c = wr_img.imageInfo()->filename[0]; + wr_img.imageInfo()->filename[0] = 0; + wr_img.display(); + wr_img.imageInfo()->filename[0] = c; #endif } } @@ -96,7 +109,8 @@ int usage (int rc, const char *msg = NULL) int main (int argc, const char *argv[]) { - decoder.set_handler(handler); + decoder.set_handler(symbol_handler); + walker.set_handler(pixel_handler); int num_images = 0; for(int i = 1; i < argc; i++) { From b041de4c8acf5c645a038b6aa3dca289f5c51e6d Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 24 Mar 2007 20:32:16 +0000 Subject: [PATCH 005/328] add missing ImageWalker install --- include/Makefile.am.inc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/Makefile.am.inc b/include/Makefile.am.inc index 28e41b2..005ce17 100644 --- a/include/Makefile.am.inc +++ b/include/Makefile.am.inc @@ -1,3 +1,4 @@ zincludedir = $(includedir)/zebra include_HEADERS = include/zebra.h -zinclude_HEADERS = include/zebra/Scanner.h include/zebra/Decoder.h +zinclude_HEADERS = include/zebra/Scanner.h include/zebra/Decoder.h \ + include/zebra/ImageWalker.h From 94eb59ae7027b7dcc74efc9fef55b26c9cf4feca Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 24 Mar 2007 21:26:12 +0000 Subject: [PATCH 006/328] fix some config/build issues found on other boxes --- configure.ac | 4 ++-- include/zebra/Decoder.h | 1 + include/zebra/ImageWalker.h | 1 + zebraimg/zebraimg.cpp | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index c56685b..461034e 100644 --- a/configure.ac +++ b/configure.ac @@ -19,7 +19,7 @@ AC_ARG_WITH([imagemagick], [], [with_imagemagick=check]) -AC_CHECK_TOOL([MAGICK_CONFIG], [Magick++-config]) +AC_CHECK_TOOL([MAGICK_CONFIG], [Magick++-config], [:]) AS_IF([test "x$with_imagemagick" != "xno" && \ test "x$with_imagemagick" != "xcheck" && \ test "x$MAGICK_CONFIG" = "x:"], @@ -57,7 +57,7 @@ AC_ARG_WITH([sdl], fi ]) -AC_CHECK_TOOL([SDL_CONFIG], [sdl-config]) +AC_CHECK_TOOL([SDL_CONFIG], [sdl-config], [:]) AS_IF([test "x$enable_video" = "xno"], [SDL_CONFIG=":"], [test "x$with_sdl" != "xno" && \ diff --git a/include/zebra/Decoder.h b/include/zebra/Decoder.h index 9893f15..d4e35e9 100644 --- a/include/zebra/Decoder.h +++ b/include/zebra/Decoder.h @@ -35,6 +35,7 @@ class Decoder { public: class Handler { public: + virtual ~Handler() { } virtual void decode_callback(Decoder &decoder) = 0; }; diff --git a/include/zebra/ImageWalker.h b/include/zebra/ImageWalker.h index 5144e61..c700beb 100644 --- a/include/zebra/ImageWalker.h +++ b/include/zebra/ImageWalker.h @@ -33,6 +33,7 @@ class ImageWalker { public: class Handler { public: + virtual ~Handler() { } virtual char walker_callback(ImageWalker &walker, void *pixel) = 0; }; diff --git a/zebraimg/zebraimg.cpp b/zebraimg/zebraimg.cpp index c206adc..0c2067c 100644 --- a/zebraimg/zebraimg.cpp +++ b/zebraimg/zebraimg.cpp @@ -24,6 +24,7 @@ #include #include #include +#include using namespace std; using namespace Magick; From 88c4e59a798a768bf0058eb05b4bb7e5756e4e44 Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 24 Mar 2007 22:33:25 +0000 Subject: [PATCH 007/328] add NEWS and ChangeLog --- ChangeLog | 38 ++++++++++++++++++++++++++++++++++++++ NEWS | 7 +++++++ 2 files changed, 45 insertions(+) create mode 100644 ChangeLog create mode 100644 NEWS diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..8c1561c --- /dev/null +++ b/ChangeLog @@ -0,0 +1,38 @@ +version 0.1: + * add NEWS and ChangeLog + * fix some config/build issues found on other boxes + * add missing ImageWalker install + * fix scanner runaway threshold calculation bug + * fix zebracam/zebraimg bugs overwriting currently scanning image w/scan + pattern + * add c++ interface to img_walker + * apply ImageWalker to zebraimg + * add decoder soft reset on partial mismatch + * finish basic decoder symbol assembly/reporting + * add decoder symbol checksum verification + * add callback API option to decoder for "async" symbol processing + * add "image walker" library API to trace scan pattern over 2D images + * apply image walker to zebracam (C++/zebraimg scan pattern still TBD) + * add audio feedback to zebracam (still has long latency) + * add zebracam key cmd to dump frame to file (for debugging) + * fixes for decoder/scanner reset/new_scan + * fixes to scanner initialization and algorithm tweaks + * made decoder less sensitive to violated quiet-zone + * apply zebraimg workaround for imagemagick image display bug + * add string names for symbol types to library and API to access them + * add dbg_scan test program for visually debugging image scanner (and + decoder) + * add test_walk for basic image walker sanity/debug + * removed recursive makes in favor of monolithic build + * renamed some makefiles accordingly + * finished some final symbol data construction + * added result callbacks to decoder APIs for data reporting + * zebraimg hooks into callback + * zebracam still seems to "hang" in undecodeable state? + * populate svn with current sources. + * most of the basic functionality is included and working. + * still need to combine final decode data, finish addons, etc (see TODO). + * c++ wrappers are included and tested, but API may need tweaked. + * zebraimg and zebracam basically working but need cleanup/polish. + * need to create some basic documentation... + * initial repository layout diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..2760e0f --- /dev/null +++ b/NEWS @@ -0,0 +1,7 @@ +Zebra Barcode Reader + +version 0.1 (2007-03-24): + first official Zebra release! + supports basic scanning and decoding of EAN-13 and UPC-A symbols + using a webcam (zebracam) or from stored image files (zebraimg). + still need to add support for addons and EAN-8/UPC-E From fd880e0afc09b7a68179b93a84cf2de1bc915768 Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 13 Apr 2007 04:08:15 +0000 Subject: [PATCH 008/328] * internal decoder restructuring to support additional symbologies - separated out 1-D decoder infrastructure into generic internal API - moved EAN/UPC specific decoding into it's own module * fix confusing configure behavior which quietly avoided building targets with missing dependencies(?!) configure will now fail with a descriptive error message if you do not have Magick++ and fail to specify --without-imagemagick or do not have SDL and fail to specify --without-sdl * add configure summary describing what will be built (req #1698196) * fix parity encoding in test_decode and add decoded symbol output * introduce Code 128 symbol type * increase width of zebra_symbol_type_t to 16 bits * add HACKING (bug #1698202) --- ChangeLog | 15 ++ HACKING | 18 ++ TODO | 3 + configure.ac | 86 +++++--- include/zebra.h | 23 +- test/test_decode.c | 18 +- zebra/Makefile.am.inc | 4 +- zebra/decoder.c | 489 +++--------------------------------------- zebra/decoder.h | 99 +++++++++ zebra/ean.c | 433 +++++++++++++++++++++++++++++++++++++ zebra/ean.h | 51 +++++ 11 files changed, 730 insertions(+), 509 deletions(-) create mode 100644 HACKING create mode 100644 zebra/decoder.h create mode 100644 zebra/ean.c create mode 100644 zebra/ean.h diff --git a/ChangeLog b/ChangeLog index 8c1561c..84c76e6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +current: + * internal decoder restructuring to support additional symbologies + - separated out 1-D decoder infrastructure into generic internal API + - moved EAN/UPC specific decoding into it's own module + * fix confusing configure behavior which quietly avoided building + targets with missing dependencies(?!) + configure will now fail with a descriptive error message if you + do not have Magick++ and fail to specify --without-imagemagick or + do not have SDL and fail to specify --without-sdl + * add configure summary describing what will be built (req #1698196) + * fix parity encoding in test_decode and add decoded symbol output + * introduce Code 128 symbol type + * increase width of zebra_symbol_type_t to 16 bits + * add HACKING (bug #1698202) + version 0.1: * add NEWS and ChangeLog * fix some config/build issues found on other boxes diff --git a/HACKING b/HACKING new file mode 100644 index 0000000..ec09f83 --- /dev/null +++ b/HACKING @@ -0,0 +1,18 @@ +if you're hacking at zebra, PLEASE send patches against the latest SVN! +to get zebra from SVN (if you haven't already), run: + + svn co https://zebra.svn.sourceforge.net/svnroot/zebra/trunk zebra + cd zebra + autoreconf --install + +this will generate configure and all that other foo you usually get with +a release. you will need to have some basic "developer tools" installed +in order for this to work (particularly GNU autotools) + +when you're done hacking and want to make your patch, run: + + svn diff > hacked.patch + +and go post this file in the patches section off the project page: + + https://sourceforge.net/tracker/?group_id=189236&atid=928517 diff --git a/TODO b/TODO index 763aa73..719b75f 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,8 @@ + * decoder needs symbology/feature enable/disable * better C++ interface to img_walker * nice to match STL iterator interface + * redundant output suppression for zebraimg + * decode hook (program/script) to zebracam/(zebraimg?) * finish UPC-E, EAN-8 and addon decoding * profile and weed out obvious oversights * documentation diff --git a/configure.ac b/configure.ac index 461034e..355d03c 100644 --- a/configure.ac +++ b/configure.ac @@ -13,58 +13,67 @@ AC_PROG_CXX AC_PROG_LIBTOOL AC_PROG_RANLIB + AC_ARG_WITH([imagemagick], [AS_HELP_STRING([--without-imagemagick], [disable support for scanning images using ImageMagick])], [], - [with_imagemagick=check]) + [with_imagemagick=yes]) -AC_CHECK_TOOL([MAGICK_CONFIG], [Magick++-config], [:]) +AC_ARG_VAR([MAGICKXX_CONFIG], [full path to Magick++-config program]) +AC_CHECK_TOOL([MAGICKXX_CONFIG], [Magick++-config], [:]) AS_IF([test "x$with_imagemagick" != "xno" && \ - test "x$with_imagemagick" != "xcheck" && \ - test "x$MAGICK_CONFIG" = "x:"], - [AC_MSG_FAILURE( - [--with-imagemagick was given, but test for imagemagick failed])]) -AM_CONDITIONAL([HAVE_MAGICK], [test "x$MAGICK_CONFIG" != "x:"]) -AC_SUBST([MAGICK_CPPFLAGS], [`$MAGICK_CONFIG --cppflags`]) -AC_SUBST([MAGICK_CXXFLAGS], [`$MAGICK_CONFIG --cxxflags`]) -AC_SUBST([MAGICK_LDFLAGS], [`$MAGICK_CONFIG --ldflags`]) -AC_SUBST([MAGICK_LIBS], [`$MAGICK_CONFIG --libs`]) + test "x$MAGICKXX_CONFIG" = "x:"], + [AC_CHECK_TOOL([CONVERT], [convert]) + AS_IF([test "x$CONVERT" != "x" && \ + convert -version | grep ImageMagick >/dev/null 2>&1], + [AC_MSG_FAILURE([test for Magick++ interface failed! +although ImageMagick programs appear to be installed? +make sure you install any ImageMagick development packages +provided by your distribution or configure --without-imagemagick +to skip building programs that use ImageMagick.])], + [AC_MSG_FAILURE([test for ImageMagick failed! +install imagemagick or configure --without-imagemagick +to skip building programs that use ImageMagick.])] +)]) +AM_CONDITIONAL([HAVE_MAGICK], [test "x$MAGICKXX_CONFIG" != "x:"]) +AC_SUBST([MAGICK_CPPFLAGS], [`$MAGICKXX_CONFIG --cppflags`]) +AC_SUBST([MAGICK_CXXFLAGS], [`$MAGICKXX_CONFIG --cxxflags`]) +AC_SUBST([MAGICK_LDFLAGS], [`$MAGICKXX_CONFIG --ldflags`]) +AC_SUBST([MAGICK_LIBS], [`$MAGICKXX_CONFIG --libs`]) + AC_ARG_ENABLE([video], [AS_HELP_STRING([--disable-video], [exclude video scanner application])], [], - [enable_video=check]) + [enable_video=yes]) AC_CHECK_HEADER([linux/videodev.h], - [ if test "x$enable_video" = "xcheck"; then enable_video="yes"; fi ], - [ if test "x$enable_video" != "xno" && \ - test "x$enable_video" != "xcheck"; then - AC_MSG_FAILURE( - [--enable-video was given, but test for video support failed]) - fi - ]) + [], + [AS_IF([test "x$enable_video" != "xno"], + [AC_MSG_FAILURE([test for video support failed! +rebuild your kernel to include video4linux support or +configure --disable-video to skip building programs that use video.])] +)]) + AC_ARG_WITH([sdl], [AS_HELP_STRING([--without-sdl], [disable support for live video display using SDL])], [], - [ if test "x$enable_video" != "xno"; then - with_sdl=check - else - with_sdl=no - fi - ]) + [with_sdl=yes]) +AC_ARG_VAR([SDL_CONFIG], [full path to sdl-config program]) AC_CHECK_TOOL([SDL_CONFIG], [sdl-config], [:]) AS_IF([test "x$enable_video" = "xno"], - [SDL_CONFIG=":"], - [test "x$with_sdl" != "xno" && \ - test "x$with_sdl" != "xcheck" && \ - test "x$SDL_CONFIG" = "x:"], - [AC_MSG_FAILURE( - [--with-sdl was given, but test for SDL failed])]) + [SDL_CONFIG=":"], + [test "x$with_sdl" != "xno" && \ + test "x$SDL_CONFIG" = "x:"], + [AC_MSG_FAILURE([test for SDL failed! +install SDL or configure --without-sdl +to skip building programs that use SDL])] +) AM_CONDITIONAL([HAVE_SDL], [test "x$SDL_CONFIG" != "x:"]) AC_SUBST([SDL_CPPFLAGS], [`$SDL_CONFIG --cflags`]) AC_SUBST([SDL_LIBS], [`$SDL_CONFIG --libs`]) @@ -86,3 +95,18 @@ AC_CHECK_FUNCS([memset atexit setenv]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT + +echo "" +echo "please verify that the detected configuration matches your expectations:" +echo "------------------------------------------------------------------------" +echo "v4l --enable-video=$enable_video" +echo "SDL --with-sdl=$with_sdl" +AS_IF([test "x$enable_video" != "xyes" || test "x$with_sdl" != "xyes"], + [echo " => zebracam video scanner will *NOT* be built"], + [echo " => zebracam video scanner will be built"]) +echo "" +echo "Magick++ --with-imagemagick=$with_imagemagick" +AS_IF([test "x$with_imagemagick" != "xyes"], + [echo " => the zebraimg program will *NOT* be built"], + [echo " => zebraimg image file scanner will be built"]) +echo "" diff --git a/include/zebra.h b/include/zebra.h index 8931b9b..a575c57 100644 --- a/include/zebra.h +++ b/include/zebra.h @@ -37,16 +37,17 @@ typedef enum zebra_color_e { /* decoded symbol type */ typedef enum zebra_symbol_type_e { - ZEBRA_NONE = 0, /* no symbol decoded */ - ZEBRA_PARTIAL = 1, /* intermediate status */ - ZEBRA_EAN8 = 8, /* EAN-8 */ - ZEBRA_UPCE = 11, /* UPC-E */ - ZEBRA_UPCA = 12, /* UPC-A */ - ZEBRA_EAN13 = 13, /* EAN-13 */ - ZEBRA_SYMBOL = 0x0f, /* mask for base symbol type */ - ZEBRA_ADDON2 = 0x20, /* 2-digit add-on flag */ - ZEBRA_ADDON5 = 0x50, /* 5-digit add-on flag */ - ZEBRA_ADDON = 0x70, /* add-on flag mask */ + ZEBRA_NONE = 0, /* no symbol decoded */ + ZEBRA_PARTIAL = 1, /* intermediate status */ + ZEBRA_EAN8 = 8, /* EAN-8 */ + ZEBRA_UPCE = 11, /* UPC-E */ + ZEBRA_UPCA = 12, /* UPC-A */ + ZEBRA_EAN13 = 13, /* EAN-13 */ + ZEBRA_CODE128 = 128, /* Code 128 */ + ZEBRA_SYMBOL = 0x00ff, /* mask for base symbol type */ + ZEBRA_ADDON2 = 0x0200, /* 2-digit add-on flag */ + ZEBRA_ADDON5 = 0x0500, /* 5-digit add-on flag */ + ZEBRA_ADDON = 0x0700, /* add-on flag mask */ } zebra_symbol_type_t; /* return string name for symbol encoding */ @@ -125,7 +126,7 @@ extern void zebra_decoder_set_userdata(zebra_decoder_t *decoder, void *userdata); /* return user specified data value associated with the decoder */ -extern void *zebra_decoder_get_userdata(zebra_decoder_t *decoder); +extern void *zebra_decoder_get_userdata(const zebra_decoder_t *decoder); /*------------------------------------------------------------*/ diff --git a/test/test_decode.c b/test/test_decode.c index cf3764b..3d6b868 100644 --- a/test/test_decode.c +++ b/test/test_decode.c @@ -55,6 +55,17 @@ static const unsigned char parity_encode[] = { zebra_decoder_t *decoder; +static void symbol_handler (zebra_decoder_t *decoder) +{ + zebra_symbol_type_t sym = zebra_decoder_get_type(decoder); + if(sym <= ZEBRA_PARTIAL) + return; + printf("%s%s: %s\n", + zebra_get_symbol_name(sym), + zebra_get_addon_name(sym), + zebra_decoder_get_data(decoder)); +} + static void encode_junk (int n) { int i; @@ -97,7 +108,7 @@ static zebra_symbol_type_t encode_ean13 (unsigned char *data) encode(guard[3], FWD); for(i = 1; i < 7; i++, par <<= 1) { printf(" encode %x%d:", (par >> 5) & 1, data[i]); - encode(digits[data[i]], FWD ^ ((par >> 5) & 1)); + encode(digits[data[i]], REV ^ ((par >> 5) & 1)); } printf(" encode center guard:"); encode(guard[5], FWD); @@ -124,16 +135,19 @@ int main (int argc, char **argv) * - inject parity errors */ decoder = zebra_decoder_create(); + zebra_decoder_set_handler(decoder, symbol_handler); encode_junk(rnd_size); unsigned char data[14]; - unsigned int chk = 0; + int chk = 0; for(i = 0; i < 12; i++) { data[i] = (rand() >> 16) % 10; chk += (i & 1) ? data[i] * 3 : data[i]; } data[12] = chk % 10; + if(data[12]) + data[12] = 10 - data[12]; data[13] = 0; encode_ean13(data); diff --git a/zebra/Makefile.am.inc b/zebra/Makefile.am.inc index 2b3075f..e099ba4 100644 --- a/zebra/Makefile.am.inc +++ b/zebra/Makefile.am.inc @@ -1,3 +1,5 @@ lib_LTLIBRARIES = zebra/libzebra.la -zebra_libzebra_la_SOURCES = zebra/scanner.c zebra/decoder.c zebra/img_walker.c +zebra_libzebra_la_SOURCES = \ + zebra/img_walker.c zebra/scanner.c \ + zebra/decoder.c zebra/ean.c zebra_libzebra_la_LDFLAGS = -version-info $(LIB_VERSION) diff --git a/zebra/decoder.c b/zebra/decoder.c index 8688655..402fb37 100644 --- a/zebra/decoder.c +++ b/zebra/decoder.c @@ -29,92 +29,20 @@ #include /* memset */ #include -#include "zebra.h" +#include "decoder.h" #ifdef DEBUG_DECODER -# define dprintf(level, ...) \ - if(level <= DEBUG_DECODER) \ - fprintf(stderr, __VA_ARGS__) +# define dprintf(...) \ + fprintf(stderr, __VA_ARGS__) #else # define dprintf(...) #endif -/* convert compact encoded D2E1E2 to character (bit4 is parity) */ -static const char digits[] = { /* E1 E2 */ - 0x06, 0x10, 0x04, 0x13, /* 2 2-5 */ - 0x19, 0x08, 0x11, 0x05, /* 3 2-5 (d2 <= thr) */ - 0x09, 0x12, 0x07, 0x15, /* 4 2-5 (d2 <= thr) */ - 0x16, 0x00, 0x14, 0x03, /* 5 2-5 */ - 0x18, 0x01, 0x02, 0x17, /* E1E2=43,44,33,34 (d2 > thr) */ -}; - -/* partial decode symbol location */ -typedef enum symbol_partial_e { - RIGHT_HALF = 6, - LEFT_HALF = 7, -} symbol_partial_t; - -static const char parity_decode[] = { - 0xf0, /* [xx] BBBBBB = RIGHT half EAN-13 */ - - /* UPC-E check digit encoding */ - 0xff, - 0xff, - 0x0f, /* [07] BBBAAA = 0 */ - 0xff, - 0x1f, /* [0b] BBABAA = 1 */ - 0x2f, /* [0d] BBAABA = 2 */ - 0xf3, /* [0e] BBAAAB = 3 */ - 0xff, - 0x4f, /* [13] BABBAA = 4 */ - 0x7f, /* [15] BABABA = 7 */ - 0xf8, /* [16] BABAAB = 8 */ - 0x5f, /* [19] BAABBA = 5 */ - 0xf9, /* [1a] BAABAB = 9 */ - 0xf6, /* [1c] BAAABB = 6 */ - 0xff, - - /* LEFT half EAN-13 leading digit */ - 0xff, - 0x6f, /* [23] ABBBAA = 6 */ - 0x9f, /* [25] ABBABA = 9 */ - 0xf5, /* [26] ABBAAB = 5 */ - 0x8f, /* [29] ABABBA = 8 */ - 0xf7, /* [2a] ABABAB = 7 */ - 0xf4, /* [2c] ABAABB = 4 */ - 0xff, - 0x3f, /* [31] AABBBA = 3 */ - 0xf2, /* [32] AABBAB = 2 */ - 0xf1, /* [34] AABABB = 1 */ - 0xff, - 0xff, - 0xff, - 0xff, - 0x0f, /* [3f] AAAAAA = 0 */ -}; - - -typedef struct scan_s { - char state; /* module position of w[idx] in symbol */ -#define STATE_ADDON 0x40 /* scanning add-on */ -#define STATE_IDX 0x1f /* element offset into symbol */ - char raw[7]; /* decode in process */ -} scan_t; - -/* decoder state */ -struct zebra_decoder_s { - unsigned char idx; /* current width index */ - unsigned w[8]; /* window of last N bar widths */ - scan_t scans[4]; /* track decode states in parallel */ - char buf[20]; /* decoded characters */ - zebra_symbol_type_t type; /* type of last decoded data */ - void *userdata; /* application data */ - zebra_decoder_handler_t *handler; /* application callback */ -}; - zebra_decoder_t *zebra_decoder_create () { zebra_decoder_t *dcode = malloc(sizeof(zebra_decoder_t)); + dcode->buflen = 0x20; + dcode->buf = malloc(dcode->buflen); zebra_decoder_reset(dcode); return(dcode); } @@ -126,11 +54,8 @@ void zebra_decoder_destroy (zebra_decoder_t *dcode) void zebra_decoder_reset (zebra_decoder_t *dcode) { - memset(dcode, 0, (long)&dcode->userdata - (long)dcode); - dcode->scans[0].state = -1; - dcode->scans[1].state = -1; - dcode->scans[2].state = -1; - dcode->scans[3].state = -1; + memset(dcode, 0, (long)&dcode->buf - (long)dcode); + ean_reset(&dcode->ean); } void zebra_decoder_new_scan (zebra_decoder_t *dcode) @@ -138,10 +63,7 @@ void zebra_decoder_new_scan (zebra_decoder_t *dcode) /* soft reset decoder */ memset(dcode->w, 0, sizeof(dcode->w)); dcode->idx = 0; - dcode->scans[0].state = -1; - dcode->scans[1].state = -1; - dcode->scans[2].state = -1; - dcode->scans[3].state = -1; + ean_reset(&dcode->ean); } const char *zebra_decoder_get_data (const zebra_decoder_t *dcode) @@ -164,17 +86,14 @@ void zebra_decoder_set_userdata (zebra_decoder_t *dcode, dcode->userdata = userdata; } -void *zebra_decoder_get_userdata (zebra_decoder_t *dcode) +void *zebra_decoder_get_userdata (const zebra_decoder_t *dcode) { return(dcode->userdata); } zebra_symbol_type_t zebra_decoder_get_type (const zebra_decoder_t *dcode) { - return((dcode->type == RIGHT_HALF || - dcode->type == LEFT_HALF) - ? ZEBRA_PARTIAL - : dcode->type); + return(dcode->type); } const char *zebra_get_symbol_name (zebra_symbol_type_t sym) @@ -184,6 +103,7 @@ const char *zebra_get_symbol_name (zebra_symbol_type_t sym) case ZEBRA_UPCE: return("UPC-E"); case ZEBRA_UPCA: return("UPC-A"); case ZEBRA_EAN13: return("EAN-13"); + case ZEBRA_CODE128: return("CODE-128"); default: return("UNKNOWN"); } } @@ -197,386 +117,27 @@ const char *zebra_get_addon_name (zebra_symbol_type_t sym) } } - -/* bar+space width are compared as a fraction of the reference dimension "x" - * - +/- 1/2 x tolerance - * - total character width (s) is always 7 "units" for EAN/UPC - * => nominal "x" is 1/7th of "s" - * - bar+space *pair width* "e" is used to factor out bad "exposures" - * ("blooming" or "swelling" of dark or light areas) - * => using like-edge measurements avoids these issues - */ -#define ZEBRA_E_FIXED 6 -#define ZEBRA_E(e) (((e) << ZEBRA_E_FIXED) / 14) - -static inline char decode_e (unsigned e, - unsigned s) -{ - e = (e * 14 + 1) / s; - if(e < 7) { - if(e < 3) return(-1); /* invalid */ - if(e < 5) return(0); /* Ei = 2 (00) */ - else return(1); /* Ei = 3 (01) */ - } - if(e >= 11) return(-1); /* invalid */ - if(e < 9) return(2); /* Ei = 4 (10) */ - else return(3); /* Ei = 5 (11) */ -} - -/* retrieve i-th previous element width */ -static inline unsigned width(zebra_decoder_t *dcode, - unsigned char offset) -{ - return(dcode->w[(dcode->idx - offset) & 7]); -} - -/* calculate total character width "s" - * => start of character identified by context sensitive offset (<= 4) - */ -static inline unsigned calc_s (zebra_decoder_t *dcode, - unsigned char offset) -{ - return(width(dcode, offset) + - width(dcode, offset + 1) + - width(dcode, offset + 2) + - width(dcode, offset + 3)); -} - -/* evaluate previous N (>= 2) widths as auxiliary pattern, - * using preceding 4 as character width - */ -static inline unsigned char aux_end (zebra_decoder_t *dcode, - unsigned char n) -{ - /* reference width from previous character */ - unsigned s = calc_s(dcode, n); - - char code = 0; - char i; - for(i = 0; i < n - 1; i++) { - unsigned e = width(dcode, i) + width(dcode, i + 1); - code = (code << 2) | decode_e(e, s); - if(code < 0) - return(-1); - } - dprintf(2, " aux=%x", code); - return(code); -} - -/* determine possible auxiliary pattern - * using current 4 as possible character - */ -static inline char aux_start (zebra_decoder_t *dcode, - unsigned s) -{ - /* FIXME NB add-on has no guard in reverse */ - unsigned e2 = width(dcode, 5) + width(dcode, 6); - if(decode_e(e2, s)) { - dprintf(2, " [invalid any]"); - return(/*FIXME ((dcode->idx & 1) == ZEBRA_SPACE) ? STATE_ADDON : */-1); - } - - unsigned e1 = width(dcode, 4) + width(dcode, 5); - unsigned char E1 = decode_e(e1, s); - - if((dcode->idx & 1) == ZEBRA_BAR) { - /* check for quiet-zone */ - if((width(dcode, 7) * 14 + 1) / s >= 3) { - if(!E1) { - dprintf(2, " [valid normal]"); - return(0); /* normal symbol start */ - } - else if(E1 == 1) { - dprintf(2, " [valid add-on]"); - return(STATE_ADDON); /* add-on symbol start */ - } - } - dprintf(2, " [invalid start]"); - return(-1); - } - - if(!E1) { - /* attempting decode from SPACE => validate center guard */ - unsigned e3 = width(dcode, 6) + width(dcode, 7); - if(!decode_e(e3, s)) { - dprintf(2, " [valid center]"); - return(0); /* start after center guard */ - } - } - dprintf(2, " [invalid center]"); - return(/*STATE_ADDON*/-1); -} - -/* attempt to decode previous 4 widths (2 bars and 2 spaces) as a character */ -static inline char decode4 (zebra_decoder_t *dcode, - unsigned s) -{ - /* calculate similar edge measurements */ - unsigned e1 = (((dcode->idx & 1) == ZEBRA_BAR) - ? width(dcode, 0) + width(dcode, 1) - : width(dcode, 2) + width(dcode, 3)); - unsigned e2 = width(dcode, 1) + width(dcode, 2); - dprintf(2, "\n e1=%d e2=%d", e1, e2); - - /* create compacted encoding for direct lookup */ - char code = (decode_e(e1, s) << 2) | decode_e(e2, s); - if(code < 0) - return(-1); - dprintf(2, " code=%x", code); - - /* 4 combinations require additional determinant (D2) - E1E2 == 34 (0110) - E1E2 == 43 (1001) - E1E2 == 33 (0101) - E1E2 == 44 (1010) - */ - if((1 << code) & 0x0660) { - /* use sum of bar widths */ - unsigned d2 = (((dcode->idx & 1) == ZEBRA_BAR) - ? width(dcode, 0) + width(dcode, 2) - : width(dcode, 1) + width(dcode, 3)); - d2 = ((unsigned long)d2 << ZEBRA_E_FIXED) / s; - char alt = (((1 << code) & 0x0420) - ? d2 > ZEBRA_E(6) /* E1E2 in 33,44 */ - : d2 > ZEBRA_E(8)); /* E1E2 in 34,43 */ - if(alt) - code = ((code >> 1) & 3) | 0x10; /* compress code space */ - dprintf(2, " (d2=%d alt=%d)", d2, alt); - } - dprintf(2, " char=%02x", digits[(unsigned char)code]); - assert(code < 0x14); - return(code); -} - -static inline zebra_symbol_type_t partial_end (scan_t *scan, char fwd) -{ - /* calculate parity index */ - char par = ((fwd) - ? ((scan->raw[1] & 0x10) << 1 | - (scan->raw[2] & 0x10) | - (scan->raw[3] & 0x10) >> 1 | - (scan->raw[4] & 0x10) >> 2 | - (scan->raw[5] & 0x10) >> 3 | - (scan->raw[6] & 0x10) >> 4) - : ((scan->raw[1] & 0x10) >> 4 | - (scan->raw[2] & 0x10) >> 3 | - (scan->raw[3] & 0x10) >> 2 | - (scan->raw[4] & 0x10) >> 1 | - (scan->raw[5] & 0x10) | - (scan->raw[6] & 0x10) << 1)); - - /* lookup parity combination */ - scan->raw[0] = parity_decode[par >> 1]; - if(par & 1) - scan->raw[0] >>= 4; - scan->raw[0] &= 0xf; - dprintf(2, " par=%02x(%x)", par, scan->raw[0]); - - if(scan->raw[0] == 0xf) - /* invalid parity combination */ - return(ZEBRA_NONE); - - if(!par == fwd) { - /* reverse sampled digits */ - unsigned char i; - for(i = 1; i < 4; i++) { - char tmp = scan->raw[i]; - scan->raw[i] = scan->raw[7 - i]; - scan->raw[7 - i] = tmp; - } - } - - if(!par) - return(RIGHT_HALF); - if(par & 0x20) - return(LEFT_HALF); - return(/*ZEBRA_UPCE*/ZEBRA_NONE); -} - -/* update state for one of 4 parallel scans */ -static inline zebra_symbol_type_t decode_scan (zebra_decoder_t *dcode, - scan_t *scan) -{ - scan->state++; - char idx = scan->state & STATE_IDX; - if((1 << idx) & - ((scan->state & STATE_ADDON) - ? 0x00108421 - : 0x00111111)) - { - unsigned s = calc_s(dcode, 0); - if(!s) - return(0); - dprintf(2, " s=%d", s); - /* validate guard bars before decoding first char of symbol */ - if(!scan->state) { - scan->state = aux_start(dcode, s); - if(scan->state < 0) - return(0); - idx = scan->state & STATE_IDX; - } - char code = decode4(dcode, s); - if(code < 0) - scan->state = -1; - else { - dprintf(2, "\n raw[%x]=%02x =>", idx >> 2, - digits[(unsigned char)code]); - scan->raw[(idx >> 2) + 1] = digits[(unsigned char)code]; - dprintf(2, " raw=%d%d%d%d%d%d%d", - scan->raw[0] & 0xf, scan->raw[1] & 0xf, - scan->raw[2] & 0xf, scan->raw[3] & 0xf, - scan->raw[4] & 0xf, scan->raw[5] & 0xf, - scan->raw[6] & 0xf); - } - } - else if(((dcode->idx & 1) == ZEBRA_BAR) && - ((scan->state & STATE_ADDON) - ? idx == 0x06 || idx == 0x09 || idx == 0x16 || idx == 0x19 - : idx == 0x17 || idx == 0x18)) { - char fwd = idx == 0x18; - dprintf(2, " fwd=%x", fwd); - zebra_symbol_type_t part = ZEBRA_NONE; - if(!aux_end(dcode, (fwd) ? 4 : 3)) { - part = partial_end(scan, fwd); - dprintf(2, "\n"); - dprintf(1, "decode=%x%x%x%x%x%x%x(%x)\n", - scan->raw[0] & 0xf, scan->raw[1] & 0xf, - scan->raw[2] & 0xf, scan->raw[3] & 0xf, - scan->raw[4] & 0xf, scan->raw[5] & 0xf, - scan->raw[6] & 0xf, part); - } - else - dprintf(2, " [invalid end guard]"); - scan->state = -1; - return(part); - } - return(0); -} - -static inline char check_ean13_parity (zebra_decoder_t *dcode) -{ - unsigned char chk = 0; - unsigned char i; - for(i = 0; i < 12; i++) { - unsigned char d = dcode->buf[i] - '0'; - chk += d; - if(i & 1) { - chk += d << 1; - if(chk >= 20) - chk -= 20; - } - if(chk >= 10) - chk -= 10; - } - assert(chk < 10); - if(chk) - chk = 10 - chk; - unsigned char d = dcode->buf[12] - '0'; - assert(d < 10); - if(chk != d) { - dprintf(1, "checksum mismatch %d != %d (%s)\n", chk, d, dcode->buf); - return(-1); - } - return(0); -} - -static inline zebra_symbol_type_t integrate_partial (zebra_decoder_t *dcode, - scan_t *scan, - zebra_symbol_type_t part) -{ - /* FIXME UPC-E, EAN-8 */ - /* copy raw data into output buffer */ - /* if same partial is not consistent, reset others */ - unsigned char i; - if(part == LEFT_HALF) { - if(dcode->buf[0] && dcode->buf[7]) - part = ZEBRA_EAN13; - - for(i = 0; i < 7; i++) { - char ch = (scan->raw[i] & 0xf) + '0'; - if(part == ZEBRA_EAN13 && - dcode->buf[i] != ch) { - /* partial mismatch - reset other parts */ - dcode->buf[7] = dcode->buf[13] = 0; - part = ZEBRA_PARTIAL; - } - dcode->buf[i] = ch; - } - } - else if(part == RIGHT_HALF) { - if(dcode->buf[0] && dcode->buf[7]) - part = ZEBRA_EAN13; - for(i = 0; i < 6; i++) { - char ch = (scan->raw[i + 1] & 0xf) + '0'; - if(part == ZEBRA_EAN13 && - dcode->buf[i + 7] != ch) { - /* partial mismatch - reset other parts */ - dcode->buf[0] = dcode->buf[13] = 0; - part = ZEBRA_PARTIAL; - } - dcode->buf[i + 7] = ch; - } - } - else { - unsigned char len = (part == ZEBRA_ADDON5) ? 5 : 2; - if(dcode->buf[0] && dcode->buf[7] && dcode->buf[13]) - part |= ZEBRA_EAN13; - for(i = 0; i < len; i++) { - char ch = (scan->raw[i] & 0xf) + '0'; - if((part & ZEBRA_SYMBOL) == ZEBRA_EAN13 && - dcode->buf[i + 13] != ch) { - /* partial mismatch - reset other parts */ - dcode->buf[0] = dcode->buf[7] = 0; - part &= ZEBRA_ADDON; - } - dcode->buf[i + 13] = ch; - } - } - if(part == ZEBRA_EAN13 && - check_ean13_parity(dcode)) - /* invalid parity */ - part = ZEBRA_NONE; - - if(part == ZEBRA_EAN13 && dcode->buf[13]) - part |= (dcode->buf[15]) ? ZEBRA_ADDON5 : ZEBRA_ADDON2; - - return(part); -} - zebra_symbol_type_t zebra_decode_width (zebra_decoder_t *dcode, unsigned w) { dcode->w[dcode->idx & 7] = w; + dprintf(" decode[%x]: w=%d\n", dcode->idx, w); + + /* each decoder processes width stream in parallel */ + zebra_symbol_type_t sym = dcode->type = ZEBRA_NONE; - /* process upto 4 separate scans */ - zebra_symbol_type_t sym = ZEBRA_NONE; - unsigned char scan = dcode->idx & 3; +/*#ifdef ENABLE_EAN*/ + if((sym = zebra_decode_ean(dcode))) + dcode->type = sym; +/*#endif*/ + +#ifdef ENABLE_CODE128 + if((sym = zebra_decode_code128(dcode)) > ZEBRA_PARTIAL || dcode->type) + dcode->type = sym; +#endif - unsigned char i; - for(i = 0; i < 4; i++) - if(dcode->scans[i].state >= 0 || - i == scan) - { - dprintf(2, " decode[%x/%x]: idx=%x st=%d w=%d", - scan, i, dcode->idx, dcode->scans[i].state, w); - zebra_symbol_type_t part = decode_scan(dcode, &dcode->scans[i]); - if(part) { - /* update accumulated data from new partial decode */ - sym = integrate_partial(dcode, &dcode->scans[i], part); - dcode->type = sym; - if(sym) { - /* this scan valid => _reset_ all scans */ - dcode->scans[0].state = -1; - dcode->scans[1].state = -1; - dcode->scans[2].state = -1; - dcode->scans[3].state = -1; - } - } - dprintf(2, "\n"); - } + dcode->type = sym; dcode->idx++; - if(sym == LEFT_HALF || sym == RIGHT_HALF) - sym = ZEBRA_PARTIAL; if(sym && dcode->handler) dcode->handler(dcode); return(sym); diff --git a/zebra/decoder.h b/zebra/decoder.h new file mode 100644 index 0000000..e6e4ee7 --- /dev/null +++ b/zebra/decoder.h @@ -0,0 +1,99 @@ +/*------------------------------------------------------------------------ + * Copyright 2007 (c) Jeff Brown + * + * This file is part of the Zebra Barcode Library. + * + * The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zebra + *------------------------------------------------------------------------*/ +#ifndef _DECODER_H_ +#define _DECODER_H_ + +#include "zebra.h" +#include "ean.h" + +/* size of bar width history (implementation assumes power of two) */ +#define DECODE_WINDOW 8 + +/* symbology independent decoder state */ +struct zebra_decoder_s { + unsigned char idx; /* current width index */ + unsigned w[DECODE_WINDOW]; /* window of last N bar widths */ + zebra_symbol_type_t type; /* type of last decoded data */ + + /* everything above here is automatically reset */ + char *buf; /* decoded characters */ + unsigned buflen; /* dynamic buffer allocation */ + void *userdata; /* application data */ + zebra_decoder_handler_t *handler; /* application callback */ + + /* symbology specific state */ + ean_decoder_t ean; /* EAN/UPC parallel decode attempts */ +}; + +/* return current element color */ +static inline char get_color (const zebra_decoder_t *dcode) +{ + return(dcode->idx & 1); +} + +/* retrieve i-th previous element width */ +static inline unsigned get_width(const zebra_decoder_t *dcode, + unsigned char offset) +{ + return(dcode->w[(dcode->idx - offset) & (DECODE_WINDOW - 1)]); +} + +/* calculate total character width "s" + * - start of character identified by context sensitive offset + * (<= DECODE_WINDOW - n) + * - size of character is n elements + */ +static inline unsigned calc_s (const zebra_decoder_t *dcode, + unsigned char offset, + unsigned char n) +{ + /* FIXME check that this gets unrolled for constant n */ + unsigned s = 0; + while(n--) + s += get_width(dcode, offset++); + return(s); +} + +/* fixed character width decode assist + * bar+space width are compared as a fraction of the reference dimension "x" + * - +/- 1/2 x tolerance + * - measured total character width (s) compared to symbology baseline (n) + * (n = 7 for EAN/UPC, 11 for Code 128) + * - bar+space *pair width* "e" is used to factor out bad "exposures" + * ("blooming" or "swelling" of dark or light areas) + * => using like-edge measurements avoids these issues + * - n should be > 3 + */ +static inline char decode_e (unsigned e, + unsigned s, + unsigned n) +{ + /* result is encoded number of units - 2 + * (for use as zero based index) + * or -1 if invalid + */ + unsigned char E = ((e * n * 2 + 1) / s - 3) / 2; + return((E >= n - 3) ? -1 : E); +} + +#endif diff --git a/zebra/ean.c b/zebra/ean.c new file mode 100644 index 0000000..00c1852 --- /dev/null +++ b/zebra/ean.c @@ -0,0 +1,433 @@ +/*------------------------------------------------------------------------ + * Copyright 2007 (c) Jeff Brown + * + * This file is part of the Zebra Barcode Library. + * + * The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zebra + *------------------------------------------------------------------------*/ + +#include +#ifdef DEBUG_EAN +# include /* fprintf */ +#endif +#include + +#include "zebra.h" +#include "decoder.h" + +#ifdef DEBUG_EAN +# define dprintf(level, ...) \ + if(level <= DEBUG_EAN) \ + fprintf(stderr, __VA_ARGS__) +#else +# define dprintf(...) +#endif + +/* partial decode symbol location */ +typedef enum symbol_partial_e { + RIGHT_HALF = 6, + LEFT_HALF = 7, +} symbol_partial_t; + +/* convert compact encoded D2E1E2 to character (bit4 is parity) */ +static const char digits[] = { /* E1 E2 */ + 0x06, 0x10, 0x04, 0x13, /* 2 2-5 */ + 0x19, 0x08, 0x11, 0x05, /* 3 2-5 (d2 <= thr) */ + 0x09, 0x12, 0x07, 0x15, /* 4 2-5 (d2 <= thr) */ + 0x16, 0x00, 0x14, 0x03, /* 5 2-5 */ + 0x18, 0x01, 0x02, 0x17, /* E1E2=43,44,33,34 (d2 > thr) */ +}; + +static const char parity_decode[] = { + 0xf0, /* [xx] BBBBBB = RIGHT half EAN-13 */ + + /* UPC-E check digit encoding */ + 0xff, + 0xff, + 0x0f, /* [07] BBBAAA = 0 */ + 0xff, + 0x1f, /* [0b] BBABAA = 1 */ + 0x2f, /* [0d] BBAABA = 2 */ + 0xf3, /* [0e] BBAAAB = 3 */ + 0xff, + 0x4f, /* [13] BABBAA = 4 */ + 0x7f, /* [15] BABABA = 7 */ + 0xf8, /* [16] BABAAB = 8 */ + 0x5f, /* [19] BAABBA = 5 */ + 0xf9, /* [1a] BAABAB = 9 */ + 0xf6, /* [1c] BAAABB = 6 */ + 0xff, + + /* LEFT half EAN-13 leading digit */ + 0xff, + 0x6f, /* [23] ABBBAA = 6 */ + 0x9f, /* [25] ABBABA = 9 */ + 0xf5, /* [26] ABBAAB = 5 */ + 0x8f, /* [29] ABABBA = 8 */ + 0xf7, /* [2a] ABABAB = 7 */ + 0xf4, /* [2c] ABAABB = 4 */ + 0xff, + 0x3f, /* [31] AABBBA = 3 */ + 0xf2, /* [32] AABBAB = 2 */ + 0xf1, /* [34] AABABB = 1 */ + 0xff, + 0xff, + 0xff, + 0xff, + 0x0f, /* [3f] AAAAAA = 0 */ +}; + + +/* evaluate previous N (>= 2) widths as auxiliary pattern, + * using preceding 4 as character width + */ +static inline unsigned char aux_end (zebra_decoder_t *dcode, + unsigned char n) +{ + /* reference width from previous character */ + unsigned s = calc_s(dcode, n, 4); + + char code = 0; + char i; + for(i = 0; i < n - 1; i++) { + unsigned e = get_width(dcode, i) + get_width(dcode, i + 1); + code = (code << 2) | decode_e(e, s, 7); + if(code < 0) + return(-1); + } + dprintf(2, " aux=%x", code); + return(code); +} + +/* determine possible auxiliary pattern + * using current 4 as possible character + */ +static inline char aux_start (zebra_decoder_t *dcode, + unsigned s) +{ + /* FIXME NB add-on has no guard in reverse */ + unsigned e2 = get_width(dcode, 5) + get_width(dcode, 6); + if(decode_e(e2, s, 7)) { + dprintf(2, " [invalid any]"); + return(/*FIXME (get_color(dcode) == ZEBRA_SPACE) ? STATE_ADDON : */-1); + } + + unsigned e1 = get_width(dcode, 4) + get_width(dcode, 5); + unsigned char E1 = decode_e(e1, s, 7); + + if(get_color(dcode) == ZEBRA_BAR) { + /* check for quiet-zone */ + if((get_width(dcode, 7) * 14 + 1) / s >= 3) { + if(!E1) { + dprintf(2, " [valid normal]"); + return(0); /* normal symbol start */ + } + else if(E1 == 1) { + dprintf(2, " [valid add-on]"); + return(STATE_ADDON); /* add-on symbol start */ + } + } + dprintf(2, " [invalid start]"); + return(-1); + } + + if(!E1) { + /* attempting decode from SPACE => validate center guard */ + unsigned e3 = get_width(dcode, 6) + get_width(dcode, 7); + if(!decode_e(e3, s, 7)) { + dprintf(2, " [valid center]"); + return(0); /* start after center guard */ + } + } + dprintf(2, " [invalid center]"); + return(/*STATE_ADDON*/-1); +} + +/* attempt to decode previous 4 widths (2 bars and 2 spaces) as a character */ +static inline char decode4 (zebra_decoder_t *dcode, + unsigned s) +{ + /* calculate similar edge measurements */ + unsigned e1 = ((get_color(dcode) == ZEBRA_BAR) + ? get_width(dcode, 0) + get_width(dcode, 1) + : get_width(dcode, 2) + get_width(dcode, 3)); + unsigned e2 = get_width(dcode, 1) + get_width(dcode, 2); + dprintf(2, "\n e1=%d e2=%d", e1, e2); + + /* create compacted encoding for direct lookup */ + char code = (decode_e(e1, s, 7) << 2) | decode_e(e2, s, 7); + if(code < 0) + return(-1); + dprintf(2, " code=%x", code); + + /* 4 combinations require additional determinant (D2) + E1E2 == 34 (0110) + E1E2 == 43 (1001) + E1E2 == 33 (0101) + E1E2 == 44 (1010) + */ + if((1 << code) & 0x0660) { + /* use sum of bar widths */ + unsigned d2 = ((get_color(dcode) == ZEBRA_BAR) + ? get_width(dcode, 0) + get_width(dcode, 2) + : get_width(dcode, 1) + get_width(dcode, 3)); + char D2 = (d2 * 14 + 1) / s; + char mid = (((1 << code) & 0x0420) + ? 6 /* E1E2 in 33,44 */ + : 8); /* E1E2 in 34,43 */ + char alt = D2 > mid; + if(alt) + code = ((code >> 1) & 3) | 0x10; /* compress code space */ + dprintf(2, " (d2=%d(%d) alt=%d)", d2, D2, alt); + } + dprintf(2, " char=%02x", digits[(unsigned char)code]); + assert(code < 0x14); + return(code); +} + +static inline zebra_symbol_type_t partial_end (ean_pass_t *pass, + char fwd) +{ + /* calculate parity index */ + char par = ((fwd) + ? ((pass->raw[1] & 0x10) << 1 | + (pass->raw[2] & 0x10) | + (pass->raw[3] & 0x10) >> 1 | + (pass->raw[4] & 0x10) >> 2 | + (pass->raw[5] & 0x10) >> 3 | + (pass->raw[6] & 0x10) >> 4) + : ((pass->raw[1] & 0x10) >> 4 | + (pass->raw[2] & 0x10) >> 3 | + (pass->raw[3] & 0x10) >> 2 | + (pass->raw[4] & 0x10) >> 1 | + (pass->raw[5] & 0x10) | + (pass->raw[6] & 0x10) << 1)); + + /* lookup parity combination */ + pass->raw[0] = parity_decode[par >> 1]; + if(par & 1) + pass->raw[0] >>= 4; + pass->raw[0] &= 0xf; + dprintf(2, " par=%02x(%x)", par, pass->raw[0]); + + if(pass->raw[0] == 0xf) + /* invalid parity combination */ + return(ZEBRA_NONE); + + if(!par == fwd) { + /* reverse sampled digits */ + unsigned char i; + for(i = 1; i < 4; i++) { + char tmp = pass->raw[i]; + pass->raw[i] = pass->raw[7 - i]; + pass->raw[7 - i] = tmp; + } + } + + if(!par) + return(RIGHT_HALF); + if(par & 0x20) + return(LEFT_HALF); + return(/*ZEBRA_UPCE*/ZEBRA_NONE); +} + +/* update state for one of 4 parallel passes */ +static inline zebra_symbol_type_t decode_pass (zebra_decoder_t *dcode, + ean_pass_t *pass) +{ + pass->state++; + char idx = pass->state & STATE_IDX; + if((1 << idx) & + ((pass->state & STATE_ADDON) + ? 0x00108421 + : 0x00111111)) + { + unsigned s = calc_s(dcode, 0, 4); + if(!s) + return(0); + dprintf(2, " s=%d", s); + /* validate guard bars before decoding first char of symbol */ + if(!pass->state) { + pass->state = aux_start(dcode, s); + if(pass->state < 0) + return(0); + idx = pass->state & STATE_IDX; + } + char code = decode4(dcode, s); + if(code < 0) + pass->state = -1; + else { + dprintf(2, "\n raw[%x]=%02x =>", idx >> 2, + digits[(unsigned char)code]); + pass->raw[(idx >> 2) + 1] = digits[(unsigned char)code]; + dprintf(2, " raw=%d%d%d%d%d%d%d", + pass->raw[0] & 0xf, pass->raw[1] & 0xf, + pass->raw[2] & 0xf, pass->raw[3] & 0xf, + pass->raw[4] & 0xf, pass->raw[5] & 0xf, + pass->raw[6] & 0xf); + } + } + else if((get_color(dcode) == ZEBRA_BAR) && + ((pass->state & STATE_ADDON) + ? idx == 0x06 || idx == 0x09 || idx == 0x16 || idx == 0x19 + : idx == 0x17 || idx == 0x18)) { + char fwd = idx == 0x18; + dprintf(2, " fwd=%x", fwd); + zebra_symbol_type_t part = ZEBRA_NONE; + if(!aux_end(dcode, (fwd) ? 4 : 3)) { + part = partial_end(pass, fwd); + dprintf(2, "\n"); + dprintf(1, "decode=%x%x%x%x%x%x%x(%x)\n", + pass->raw[0] & 0xf, pass->raw[1] & 0xf, + pass->raw[2] & 0xf, pass->raw[3] & 0xf, + pass->raw[4] & 0xf, pass->raw[5] & 0xf, + pass->raw[6] & 0xf, part); + } + else + dprintf(2, " [invalid end guard]"); + pass->state = -1; + return(part); + } + return(0); +} + +static inline char check_ean13_parity (zebra_decoder_t *dcode) +{ + unsigned char chk = 0; + unsigned char i; + for(i = 0; i < 12; i++) { + unsigned char d = dcode->buf[i] - '0'; + chk += d; + if(i & 1) { + chk += d << 1; + if(chk >= 20) + chk -= 20; + } + if(chk >= 10) + chk -= 10; + } + assert(chk < 10); + if(chk) + chk = 10 - chk; + unsigned char d = dcode->buf[12] - '0'; + assert(d < 10); + if(chk != d) { + dprintf(1, "checksum mismatch %d != %d (%s)\n", chk, d, dcode->buf); + return(-1); + } + return(0); +} + +static inline zebra_symbol_type_t integrate_partial (zebra_decoder_t *dcode, + ean_pass_t *pass, + zebra_symbol_type_t part) +{ + /* FIXME UPC-E, EAN-8 */ + /* copy raw data into output buffer */ + /* if same partial is not consistent, reset others */ + dprintf(2, " integrate part=%x (%x%x%x)\n", + part, dcode->buf[0], dcode->buf[7], dcode->buf[13]); + unsigned char i; + if(part == LEFT_HALF) { + if(dcode->buf[0] && dcode->buf[7]) + part = ZEBRA_EAN13; + + for(i = 0; i < 7; i++) { + char ch = (pass->raw[i] & 0xf) + '0'; + if(part == ZEBRA_EAN13 && + dcode->buf[i] != ch) { + /* partial mismatch - reset other parts */ + dcode->buf[7] = dcode->buf[13] = 0; + part = ZEBRA_PARTIAL; + } + dcode->buf[i] = ch; + } + if(part == LEFT_HALF && dcode->buf[7]) + part = ZEBRA_EAN13; + } + else if(part == RIGHT_HALF) { + if(dcode->buf[0] && dcode->buf[7]) + part = ZEBRA_EAN13; + for(i = 0; i < 6; i++) { + char ch = (pass->raw[i + 1] & 0xf) + '0'; + if(part == ZEBRA_EAN13 && + dcode->buf[i + 7] != ch) { + /* partial mismatch - reset other parts */ + dcode->buf[0] = dcode->buf[13] = 0; + part = ZEBRA_PARTIAL; + } + dcode->buf[i + 7] = ch; + } + if(part == RIGHT_HALF && dcode->buf[0]) + part = ZEBRA_EAN13; + } + else { + unsigned char len = (part == ZEBRA_ADDON5) ? 5 : 2; + if(dcode->buf[0] && dcode->buf[7] && dcode->buf[13]) + part |= ZEBRA_EAN13; + for(i = 0; i < len; i++) { + char ch = (pass->raw[i] & 0xf) + '0'; + if((part & ZEBRA_SYMBOL) == ZEBRA_EAN13 && + dcode->buf[i + 13] != ch) { + /* partial mismatch - reset other parts */ + dcode->buf[0] = dcode->buf[7] = 0; + part &= ZEBRA_ADDON; + } + dcode->buf[i + 13] = ch; + } + } + if(part == ZEBRA_EAN13 && + check_ean13_parity(dcode)) + /* invalid parity */ + part = ZEBRA_NONE; + + if(part == ZEBRA_EAN13 && dcode->buf[13]) + part |= (dcode->buf[15]) ? ZEBRA_ADDON5 : ZEBRA_ADDON2; + + return(part); +} + +zebra_symbol_type_t zebra_decode_ean (zebra_decoder_t *dcode) +{ + /* process upto 4 separate passes */ + zebra_symbol_type_t sym = ZEBRA_NONE; + unsigned char pass_idx = dcode->idx & 3; + + unsigned char i; + for(i = 0; i < 4; i++) { + ean_pass_t *pass = &dcode->ean.pass[i]; + if(pass->state >= 0 || + i == pass_idx) + { + dprintf(2, " decode[%x/%x]: idx=%x st=%d", + pass_idx, i, dcode->idx, pass->state); + zebra_symbol_type_t part = decode_pass(dcode, pass); + if(part) { + /* update accumulated data from new partial decode */ + sym = integrate_partial(dcode, pass, part); + if(sym) + /* this pass valid => _reset_ all passes */ + ean_reset(&dcode->ean); + } + dprintf(2, "\n"); + } + } + if(sym == LEFT_HALF || sym == RIGHT_HALF) + sym = ZEBRA_PARTIAL; + return(sym); +} diff --git a/zebra/ean.h b/zebra/ean.h new file mode 100644 index 0000000..6f49fe0 --- /dev/null +++ b/zebra/ean.h @@ -0,0 +1,51 @@ +/*------------------------------------------------------------------------ + * Copyright 2007 (c) Jeff Brown + * + * This file is part of the Zebra Barcode Library. + * + * The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zebra + *------------------------------------------------------------------------*/ +#ifndef _EAN_H_ +#define _EAN_H_ + +/* state of each parallel decode attempt */ +typedef struct ean_pass_s { + char state; /* module position of w[idx] in symbol */ +#define STATE_ADDON 0x40 /* scanning add-on */ +#define STATE_IDX 0x1f /* element offset into symbol */ + char raw[7]; /* decode in process */ +} ean_pass_t; + +/* EAN/UPC specific decode state */ +typedef struct ean_decoder_s { + ean_pass_t pass[4]; /* state of each parallel decode attempt */ +} ean_decoder_t; + +/* reset EAN/UPC specific state */ +static inline void ean_reset (ean_decoder_t *ean) +{ + ean->pass[0].state = -1; + ean->pass[1].state = -1; + ean->pass[2].state = -1; + ean->pass[3].state = -1; +} + +/* decode EAN/UPC symbols */ +zebra_symbol_type_t zebra_decode_ean(zebra_decoder_t *dcode); + +#endif From adb21ac2cb8f0c1dc94b6f4cdd8f9173d82d2bac Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 18 Apr 2007 18:18:21 +0000 Subject: [PATCH 009/328] * add DocBook template and build infrastructure * add manpages for zebracam and zebraimg * add GNU standard options to zebracam and zebraimg --- ChangeLog | 3 ++ Makefile.am | 2 +- TODO | 2 + configure.ac | 9 +++- doc/Makefile.am.inc | 32 +++++++++++++ doc/manual.xml.in | 49 +++++++++++++++++++ doc/ref/zebracam.xml | 66 ++++++++++++++++++++++++++ doc/ref/zebraimg.xml | 106 ++++++++++++++++++++++++++++++++++++++++++ zebracam/zebracam.c | 29 +++++++++++- zebraimg/zebraimg.cpp | 43 +++++++++++++---- 10 files changed, 328 insertions(+), 13 deletions(-) create mode 100644 doc/Makefile.am.inc create mode 100644 doc/manual.xml.in create mode 100644 doc/ref/zebracam.xml create mode 100644 doc/ref/zebraimg.xml diff --git a/ChangeLog b/ChangeLog index 84c76e6..092d92b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,7 @@ current: + * add DocBook template and build infrastructure + * add manpages for zebracam and zebraimg + * add GNU standard options to zebracam and zebraimg * internal decoder restructuring to support additional symbologies - separated out 1-D decoder infrastructure into generic internal API - moved EAN/UPC specific decoding into it's own module diff --git a/Makefile.am b/Makefile.am index 9be7b08..228179e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -14,4 +14,4 @@ if HAVE_SDL include $(srcdir)/zebracam/Makefile.am.inc endif include $(srcdir)/test/Makefile.am.inc -#include $(srcdir)/doc/Makefile.am.inc +include $(srcdir)/doc/Makefile.am.inc diff --git a/TODO b/TODO index 719b75f..63a03af 100644 --- a/TODO +++ b/TODO @@ -1,8 +1,10 @@ + * rpm packaging * decoder needs symbology/feature enable/disable * better C++ interface to img_walker * nice to match STL iterator interface * redundant output suppression for zebraimg * decode hook (program/script) to zebracam/(zebraimg?) * finish UPC-E, EAN-8 and addon decoding + * add library version query interface * profile and weed out obvious oversights * documentation diff --git a/configure.ac b/configure.ac index 355d03c..e955983 100644 --- a/configure.ac +++ b/configure.ac @@ -1,11 +1,12 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.60]) AC_INIT([zebra], [0.1], [spadix@users.sourceforge.net]) -AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) +AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects std-options dist-bzip2]) AC_CONFIG_HEADERS([include/config.h]) AC_CONFIG_SRCDIR(zebra/scanner.c) AC_SUBST([LIB_VERSION], [1:0:1]) +AC_SUBST([RELDATE], [`date +%Y-%m-%d`]) AC_PROG_CC AM_PROG_CC_C_O @@ -13,6 +14,10 @@ AC_PROG_CXX AC_PROG_LIBTOOL AC_PROG_RANLIB +AC_ARG_VAR([XMLTO], [location of xmlto, used for optional \ +documentation generation]) +AC_ARG_VAR([XMLTOFLAGS], [additional arguments for xmlto]) +AC_CHECK_TOOL([XMLTO], [xmlto], [:]) AC_ARG_WITH([imagemagick], [AS_HELP_STRING([--without-imagemagick], @@ -93,7 +98,7 @@ AC_C_INLINE AC_FUNC_MMAP AC_CHECK_FUNCS([memset atexit setenv]) -AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([Makefile doc/manual.xml]) AC_OUTPUT echo "" diff --git a/doc/Makefile.am.inc b/doc/Makefile.am.inc new file mode 100644 index 0000000..0b0acba --- /dev/null +++ b/doc/Makefile.am.inc @@ -0,0 +1,32 @@ +DOCFILES = doc/manual.xml doc/ref/zebraimg.xml doc/ref/zebracam.xml + +dist_man_MANS = doc/man/zebraimg.1 doc/man/zebracam.1 +#dist_doc_DATA = doc/zebra.pdf doc/zebra.html + +docs: $(dist_man_MANS) +.PHONY: docs + +doc_path = --searchpath $(srcdir)/doc:$(srcdir)/doc/ref + +#pdf: doc/zebra-manual.pdf +#doc/zebra-manual.pdf: $(DOCFILES) +# $(XMLTO) $(XMLTOFLAGS) -o doc pdf $< + +#html: doc/zebra-manual.html +#doc/zebra-manual.html: $(DOCFILES) +# $(XMLTO) $(XMLTOFLAGS) -o doc xhtml-nochunk $< + +man_stamp = doc/man/man.stamp + +$(dist_man_MANS): $(man_stamp) + @if test ! -f $@ ; then \ + rm -f $(man_stamp) ; \ + $(MAKE) $(AM_MAKEFLAGS) $(man_stamp) ; \ + fi + +$(man_stamp): $(DOCFILES) + @$(mkdir_p) doc/man 2>/dev/null + @rm -f $(man_stamp).tmp + @touch $(man_stamp).tmp + $(XMLTO) $(doc_path) $(XMLTOFLAGS) -o doc/man man $< + @mv $(man_stamp).tmp $(man_stamp) diff --git a/doc/manual.xml.in b/doc/manual.xml.in new file mode 100644 index 0000000..04d3829 --- /dev/null +++ b/doc/manual.xml.in @@ -0,0 +1,49 @@ + + + + + + + +]> + + + + Zebra Barcode Reader + zebra-&version; + &date; + + + JeffBrown + +
spadix@users.sourceforge.net
+
+
+ + + 2007 + Jeff Brown + + + +
+ + + Introduction + + + + + Zebra Barcode Reader + + &refzebracam; + &refzebraimg; + + + + + +
diff --git a/doc/ref/zebracam.xml b/doc/ref/zebracam.xml new file mode 100644 index 0000000..cb5c47b --- /dev/null +++ b/doc/ref/zebracam.xml @@ -0,0 +1,66 @@ + + + + zebracam + 1 + + + + zebracam + + scan and decode bar codes from a video stream + + + + + + zebracam + + , + + + + + + + Description + + zebracam scans a video4linux video source + (eg, a webcam) for bar codes and prints any decoded data to the + standard output. The video stream is also displayed to the screen + with the scan pattern overlay + + + + + Options + + This program follows the usual GNU command line syntax, with + long options starting with two dashes (`-'). A summary of options + is included below + + + + , + + Print a short help message describing command line + options to standard output + + + + + + + Print program version information to standard + output and exit + + + + + + + See Also + + + + diff --git a/doc/ref/zebraimg.xml b/doc/ref/zebraimg.xml new file mode 100644 index 0000000..107c2d7 --- /dev/null +++ b/doc/ref/zebraimg.xml @@ -0,0 +1,106 @@ + + + + zebraimg + 1 + + + + zebraimg + + scan and decode bar codes from image file(s) + + + + + + zebraimg + + , + + + image + + + + + zebraimg + + , + + + + + + + Description + + For each specified image file zebraimg + scans the image for bar codes and prints any decoded data to + stdout. The image and scan pattern overlay may optionally be + displayed to the screen + + + + + Options + + This program follows the usual GNU command line syntax, with + long options starting with two dashes (`-'). A summary of options + is included below + + + + , + + Enable display of subsequent image file arguments + to the screen, until is + encountered. This argument may appear multiple + times + + + + + , + + Print a short help message describing command line + options to standard output + + + + + + + Disable display of subsequent image file arguments, + until is encountered. This + argument may appear multiple times. Image display is + disabled by default + + + + + + + Print program version information to standard + output and exit + + + + + + + Example + + Scan a JPEG image of a UPC bar code symbol and pass + resulting data to another program (not provided) that searches for + the code in a database and does something useful with it: + + zebraimg product.jpg | lookup_upc.pl + + + + See Also + + + + diff --git a/zebracam/zebracam.c b/zebracam/zebracam.c index 0d445be..eae3624 100644 --- a/zebracam/zebracam.c +++ b/zebracam/zebracam.c @@ -36,7 +36,8 @@ #include #include -#include "zebra.h" +#include +#include "config.h" #define DUMP_NAME_MAX 0x20 #define PPM_HDR_MAX 0x20 @@ -319,9 +320,35 @@ static char pixel_handler (zebra_img_walker_t *walker, return(0); } +int usage (int rc) +{ + FILE *out = (rc) ? stderr : stdout; + fprintf(out, + "usage: zebracam [-h|--help|--version]\n" + "\n" + "scan and decode bar codes from a video stream\n" + "\n" + "options:\n" + " -h, --help display this help text\n" + " --version display version information and exit\n" + "\n"); + return(rc); +} int main (int argc, const char *argv[]) { + int i; + for(i = 1; i < argc; i++) { + if(!strcmp(argv[i], "-h") || + !strcmp(argv[i], "--help")) + return(usage(0)); + if(!strcmp(argv[i], "--version")) + return(printf(PACKAGE_VERSION "\n") <= 0); + else + fprintf(stderr, "WARNING: ignoring unknown argument: %s\n", + argv[i]); + } + /* initialization */ init_cam(); init_sdl(); diff --git a/zebraimg/zebraimg.cpp b/zebraimg/zebraimg.cpp index 0c2067c..96292e5 100644 --- a/zebraimg/zebraimg.cpp +++ b/zebraimg/zebraimg.cpp @@ -23,14 +23,23 @@ #include #include -#include #include +#include + +/* wand/wand-config.h defines these conflicting values :| */ +#undef PACKAGE_BUGREPORT +#undef PACKAGE_NAME +#undef PACKAGE_STRING +#undef PACKAGE_TARNAME +#undef PACKAGE_VERSION +#include "config.h" + using namespace std; using namespace Magick; using namespace zebra; -int display = 0; +int display = 0, num_images = 0; Decoder decoder; Scanner scanner(decoder); @@ -96,6 +105,7 @@ void scan_image (const char *filename) wr_img.imageInfo()->filename[0] = c; #endif } + num_images++; } int usage (int rc, const char *msg = NULL) @@ -103,8 +113,16 @@ int usage (int rc, const char *msg = NULL) ostream &out = (rc) ? cerr : cout; if(msg) out << msg << endl; - out << - "usage: zebraimg [-h|-d|--display|--nodisplay] ..." << endl; + out << "usage: zebraimg [-h|--help|-d|--display|--nodisplay] ..." << endl + << endl + << "scan and decode bar codes from one or more image files" << endl + << endl + << "options:" << endl + << " -h, --help display this help text" << endl + << " --version display version information and exit" << endl + << " -d, --display enable display of following images to the screen" << endl + << " --nodisplay disable display of following images (default)" << endl + << endl; return(rc); } @@ -113,21 +131,28 @@ int main (int argc, const char *argv[]) decoder.set_handler(symbol_handler); walker.set_handler(pixel_handler); - int num_images = 0; - for(int i = 1; i < argc; i++) { + int i; + for(i = 1; i < argc; i++) { if(!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) return(usage(0)); + if(!strcmp(argv[i], "--version")) { + cout << PACKAGE_VERSION << endl; + return(0); + } if(!strcmp(argv[i], "-d") || !strcmp(argv[i], "--display")) display = 1; else if(!strcmp(argv[i], "--nodisplay")) display = 0; - else { - num_images++; + else if(!strcmp(argv[i], "--")) + break; + else scan_image(argv[i]); - } } + for(i++; i < argc; i++) + scan_image(argv[i]); + if(!num_images) return(usage(1, "ERROR: specify image file(s) to scan")); From 56c26fdf13622959ac2000db887369d644a95b6e Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 18 Apr 2007 19:17:49 +0000 Subject: [PATCH 010/328] =?UTF-8?q?=20=20*=20add=20Debian=20packaging=20so?= =?UTF-8?q?urces=20-=20thanks=20to=20V=C3=83=C2=ADt=20Hrachov=C3=83=C2=BD?= =?UTF-8?q?=20for=20the=20patch!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ChangeLog | 1 + debian/changelog | 6 + debian/compat | 1 + debian/control | 30 +++ debian/copyright | 518 ++++++++++++++++++++++++++++++++++++ debian/docs | 3 + debian/libzebra-dev.install | 6 + debian/libzebra0.install | 1 + debian/rules | 119 +++++++++ debian/shlibs.local | 1 + debian/zebra-tools.install | 2 + 11 files changed, 688 insertions(+) create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/docs create mode 100644 debian/libzebra-dev.install create mode 100644 debian/libzebra0.install create mode 100755 debian/rules create mode 100644 debian/shlibs.local create mode 100644 debian/zebra-tools.install diff --git a/ChangeLog b/ChangeLog index 092d92b..39e47dc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * add Debian packaging sources - thanks to Vít Hrachový for the patch! * add DocBook template and build infrastructure * add manpages for zebracam and zebraimg * add GNU standard options to zebracam and zebraimg diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..43c7d99 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,6 @@ +libzebra (0.1-1) unstable; urgency=low + + * Initial release + + -- Vít Hrachový Wed, 11 Apr 2007 21:15:45 +0200 + diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..92d15aa --- /dev/null +++ b/debian/control @@ -0,0 +1,30 @@ +Source: libzebra +Priority: optional +Maintainer: Vít Hrachový +Build-Depends: debhelper (>= 5), autotools-dev, libmagick++9-dev, autoconf (>= 2.61), automake1.9 (>= 1.9), libtool (>= 1.5.22) +Standards-Version: 3.7.2 +Section: libs + +Package: libzebra-dev +Section: libdevel +Architecture: any +Depends: libzebra (= ${Source-Version}) +Description: Header files for Zebra bar code reading library. + This packages installs files neccessary for development using Zebra barcodes + decoding library. + +Package: libzebra +Section: libs +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: Bar codes reading library with small memory footprint + Zebra is a layered barcode (EAN/UPC) scanning and decoding library. Features a + fast streaming interface with minimal memory footprint. + +Package: zebra-tools +Section: graphics +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, libmagick9 +Description: Reading barcodes using web camera or scanned images + This package provides tools for reading barcodes using web camera or using + scanned images. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..fdf1d09 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,518 @@ +This package was debianized by Vít Hrachový on +Wed, 11 Apr 2007 21:15:45 +0200. + +It was downloaded from Sourceforge.net + +Upstream Author: Jeff Brown + +Copyright: 2006, 2007 Jeff Brown + +License: + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + +The Debian packaging is (C) 2007, Vít Hrachový and +is licensed under the GPL, see `/usr/share/common-licenses/GPL'. + diff --git a/debian/docs b/debian/docs new file mode 100644 index 0000000..5502ed8 --- /dev/null +++ b/debian/docs @@ -0,0 +1,3 @@ +NEWS +README +TODO diff --git a/debian/libzebra-dev.install b/debian/libzebra-dev.install new file mode 100644 index 0000000..3c996c8 --- /dev/null +++ b/debian/libzebra-dev.install @@ -0,0 +1,6 @@ +usr/include/* +usr/lib/lib*.a +usr/lib/lib*.so +usr/lib/pkgconfig/* +usr/lib/*.la +usr/share/pkgconfig/* diff --git a/debian/libzebra0.install b/debian/libzebra0.install new file mode 100644 index 0000000..d0dbfd1 --- /dev/null +++ b/debian/libzebra0.install @@ -0,0 +1 @@ +usr/lib/lib*.so.* diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..ccd6ae7 --- /dev/null +++ b/debian/rules @@ -0,0 +1,119 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +# export DH_VERBOSE=1 + + +# These are used for cross-compiling and for saving the configure script +# from having to guess our platform (since we know it already) +DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) +DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) + + +CFLAGS = -Wall -g + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif + +# shared library versions, option 1 +version=2.0.5 +major=2 +# option 2, assuming the library is created as src/.libs/libfoo.so.2.0.5 or so +#version=`ls src/.libs/lib*.so.* | \ +# awk '{if (match($$0,/[0-9]+\.[0-9]+\.[0-9]+$$/)) print substr($$0,RSTART)}'` +#major=`ls src/.libs/lib*.so.* | \ +# awk '{if (match($$0,/\.so\.[0-9]+$$/)) print substr($$0,RSTART+4)}'` + +config.status: configure + dh_testdir + # Add here commands to configure the package. + autoreconf --install + ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info CFLAGS="$(CFLAGS)" LDFLAGS="-Wl,-z,defs" + + +build: build-stamp +build-stamp: config.status + dh_testdir + + # Add here commands to compile the package. + $(MAKE) + + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f build-stamp + + # Add here commands to clean up after the build process. + -$(MAKE) distclean +ifneq "$(wildcard /usr/share/misc/config.sub)" "" + cp -f /usr/share/misc/config.sub config.sub +endif +ifneq "$(wildcard /usr/share/misc/config.guess)" "" + cp -f /usr/share/misc/config.guess config.guess +endif + + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/ + # Add targets install-lib, install-include, install-bin to Makefile + $(MAKE) install-libLTLIBRARIES DESTDIR=$(CURDIR)/debian/libzebra + $(MAKE) install-includeHEADERS install-zincludeHEADERS DESTDIR=$(CURDIR)/debian/libzebra-dev + $(MAKE) install-binPROGRAMS DESTDIR=$(CURDIR)/debian/zebra-tools + rm -rf $(CURDIR)/debian/zebra-tools/usr/lib + + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs ChangeLog + dh_installdocs + dh_installexamples +# dh_install + dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_installinit +# dh_installcron +# dh_installinfo + dh_installman + dh_link + dh_strip + dh_compress + dh_fixperms +# dh_perl +# dh_python + dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install diff --git a/debian/shlibs.local b/debian/shlibs.local new file mode 100644 index 0000000..dfe6366 --- /dev/null +++ b/debian/shlibs.local @@ -0,0 +1 @@ +libzebra 0.1 libzebra (>> 0.1-0), libzebra (<< 0.1-99) diff --git a/debian/zebra-tools.install b/debian/zebra-tools.install new file mode 100644 index 0000000..91e6a22 --- /dev/null +++ b/debian/zebra-tools.install @@ -0,0 +1,2 @@ +usr/bin/zebraimg +usr/bin/zebracam From 1db8cdbb8bdbe5e7bca3689da23f0f5831431b49 Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 21 Apr 2007 01:29:38 +0000 Subject: [PATCH 011/328] * build and dist fixes - suppress documentation rebuilds in distributed sources --- ChangeLog | 2 ++ configure.ac | 31 +++++++++++++++++++++++++++++-- doc/Makefile.am.inc | 26 +++++++++++++++++++------- doc/{manual.xml.in => manual.xml} | 4 ++-- zebra/Makefile.am.inc | 3 ++- 5 files changed, 54 insertions(+), 12 deletions(-) rename doc/{manual.xml.in => manual.xml} (92%) diff --git a/ChangeLog b/ChangeLog index 39e47dc..551c7a5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * build and dist fixes + - suppress documentation rebuilds in distributed sources * add Debian packaging sources - thanks to Vít Hrachový for the patch! * add DocBook template and build infrastructure * add manpages for zebracam and zebraimg diff --git a/configure.ac b/configure.ac index e955983..9a539f3 100644 --- a/configure.ac +++ b/configure.ac @@ -5,8 +5,19 @@ AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects std-options dist-bzip2]) AC_CONFIG_HEADERS([include/config.h]) AC_CONFIG_SRCDIR(zebra/scanner.c) +# update these before each release (along w/pacakge version above) +# LIB_VERSION update instructions copied from libtool docs: +# library version follows the form current:revision:age +# - If the library source code has changed at all since the last update, +# then increment revision (c:r:a becomes c:r+1:a). +# - If any interfaces have been added, removed, or changed, +# increment current, and set revision to 0. +# - If any interfaces have been added since the last public release, +# then increment age. +# - If any interfaces have been removed since the last public release, +# then set age to 0. AC_SUBST([LIB_VERSION], [1:0:1]) -AC_SUBST([RELDATE], [`date +%Y-%m-%d`]) +AC_SUBST([RELDATE], [2007-03-24]) AC_PROG_CC AM_PROG_CC_C_O @@ -98,7 +109,23 @@ AC_C_INLINE AC_FUNC_MMAP AC_CHECK_FUNCS([memset atexit setenv]) -AC_CONFIG_FILES([Makefile doc/manual.xml]) +# avoid doc rebuilds unless revision info changes +AC_CONFIG_COMMANDS([doc/version.xml], + [AS_IF([test -f doc/version.xml && \ + ! echo $VERSION | diff doc/version.xml - >/dev/null 2>&1 || \ + ! echo $VERSION | diff $srcdir/doc/version.xml - >/dev/null 2>&1 ], + [echo "writing new doc/version.xml" ; echo $VERSION > doc/version.xml ])], + [VERSION=$VERSION] +) +AC_CONFIG_COMMANDS([doc/reldate.xml], + [AS_IF([test -f doc/reldate.xml && \ + ! echo $RELDATE | diff doc/reldate.xml - >/dev/null 2>&1 || \ + ! echo $RELDATE | diff $srcdir/doc/reldate.xml - >/dev/null 2>&1 ], + [echo "writing new doc/reldate.xml" ; echo $RELDATE > doc/reldate.xml ])], + [RELDATE=$RELDATE] +) + +AC_CONFIG_FILES([Makefile]) AC_OUTPUT echo "" diff --git a/doc/Makefile.am.inc b/doc/Makefile.am.inc index 0b0acba..f100b8c 100644 --- a/doc/Makefile.am.inc +++ b/doc/Makefile.am.inc @@ -1,22 +1,34 @@ -DOCFILES = doc/manual.xml doc/ref/zebraimg.xml doc/ref/zebracam.xml +# documentation sources +DOCSOURCES = doc/manual.xml doc/ref/zebraimg.xml doc/ref/zebracam.xml \ + doc/version.xml doc/reldate.xml +# man page targets to distribute and install dist_man_MANS = doc/man/zebraimg.1 doc/man/zebracam.1 + +# witness to man page build (many-to-many workaround) +man_stamp = doc/man/man.stamp + +# TBD add manual content #dist_doc_DATA = doc/zebra.pdf doc/zebra.html -docs: $(dist_man_MANS) +# distribute all documentation related files to avoid end-user rebuilds +EXTRA_DIST = $(DOCSOURCES) $(man_stamp) + +docs: $(dist_man_MANS) #dist_doc_DATA .PHONY: docs -doc_path = --searchpath $(srcdir)/doc:$(srcdir)/doc/ref +doc_path = --searchpath $(abs_srcdir)/doc:$(abs_srcdir)/doc/ref +# FIXME xmlto doesnt seem to apply --searchpath to xmllint? +doc_path += --skip-validation #pdf: doc/zebra-manual.pdf -#doc/zebra-manual.pdf: $(DOCFILES) +#doc/zebra-manual.pdf: $(DOCSOURCES) # $(XMLTO) $(XMLTOFLAGS) -o doc pdf $< #html: doc/zebra-manual.html -#doc/zebra-manual.html: $(DOCFILES) +#doc/zebra-manual.html: $(DOCSOURCES) # $(XMLTO) $(XMLTOFLAGS) -o doc xhtml-nochunk $< -man_stamp = doc/man/man.stamp $(dist_man_MANS): $(man_stamp) @if test ! -f $@ ; then \ @@ -24,7 +36,7 @@ $(dist_man_MANS): $(man_stamp) $(MAKE) $(AM_MAKEFLAGS) $(man_stamp) ; \ fi -$(man_stamp): $(DOCFILES) +$(man_stamp): $(DOCSOURCES) @$(mkdir_p) doc/man 2>/dev/null @rm -f $(man_stamp).tmp @touch $(man_stamp).tmp diff --git a/doc/manual.xml.in b/doc/manual.xml similarity index 92% rename from doc/manual.xml.in rename to doc/manual.xml index 04d3829..6498696 100644 --- a/doc/manual.xml.in +++ b/doc/manual.xml @@ -3,8 +3,8 @@ - + + diff --git a/zebra/Makefile.am.inc b/zebra/Makefile.am.inc index e099ba4..36411a5 100644 --- a/zebra/Makefile.am.inc +++ b/zebra/Makefile.am.inc @@ -1,5 +1,6 @@ lib_LTLIBRARIES = zebra/libzebra.la zebra_libzebra_la_SOURCES = \ zebra/img_walker.c zebra/scanner.c \ - zebra/decoder.c zebra/ean.c + zebra/decoder.h zebra/decoder.c \ + zebra/ean.h zebra/ean.c zebra_libzebra_la_LDFLAGS = -version-info $(LIB_VERSION) From 59cf1e5cf3a6ac9b7000fe098516e3a0ca06e0f2 Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 23 Apr 2007 20:35:21 +0000 Subject: [PATCH 012/328] * fix VPATH doc builds (requires automake-1.10 and autoconf-2.61) --- configure.ac | 4 ++-- doc/Makefile.am.inc | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 9a539f3..03e4c14 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ # Process this file with autoconf to produce a configure script. -AC_PREREQ([2.60]) +AC_PREREQ([2.61]) AC_INIT([zebra], [0.1], [spadix@users.sourceforge.net]) -AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects std-options dist-bzip2]) +AM_INIT_AUTOMAKE([1.10 -Wall -Werror foreign subdir-objects std-options dist-bzip2]) AC_CONFIG_HEADERS([include/config.h]) AC_CONFIG_SRCDIR(zebra/scanner.c) diff --git a/doc/Makefile.am.inc b/doc/Makefile.am.inc index f100b8c..d97795c 100644 --- a/doc/Makefile.am.inc +++ b/doc/Makefile.am.inc @@ -17,7 +17,7 @@ EXTRA_DIST = $(DOCSOURCES) $(man_stamp) docs: $(dist_man_MANS) #dist_doc_DATA .PHONY: docs -doc_path = --searchpath $(abs_srcdir)/doc:$(abs_srcdir)/doc/ref +doc_path = --searchpath $(abs_builddir)/doc # FIXME xmlto doesnt seem to apply --searchpath to xmllint? doc_path += --skip-validation From 1e49ae0d8865f71abeee970814344555d5cd26d2 Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 23 Apr 2007 21:40:44 +0000 Subject: [PATCH 013/328] =?UTF-8?q?=20=20*=20incorporate=20documentation?= =?UTF-8?q?=20into=20Debian=20package=20=20=20=20=20-=20thanks=20to=20V?= =?UTF-8?q?=C3=ADt=20Hrachov=C3=BD=20for=20the=20patch!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ChangeLog | 2 ++ debian/control | 2 +- debian/rules | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 551c7a5..06fdf00 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * incorporate documentation into Debian package + - thanks to Vít Hrachový for the patch! * build and dist fixes - suppress documentation rebuilds in distributed sources * add Debian packaging sources - thanks to Vít Hrachový for the patch! diff --git a/debian/control b/debian/control index 92d15aa..b3cf435 100644 --- a/debian/control +++ b/debian/control @@ -1,7 +1,7 @@ Source: libzebra Priority: optional Maintainer: Vít Hrachový -Build-Depends: debhelper (>= 5), autotools-dev, libmagick++9-dev, autoconf (>= 2.61), automake1.9 (>= 1.9), libtool (>= 1.5.22) +Build-Depends: debhelper (>= 5), autotools-dev, libmagick++9-dev, autoconf (>= 2.61), automake1.9 (>= 1.9), libtool (>= 1.5.22), xmlto (>= 0.0.18) Standards-Version: 3.7.2 Section: libs diff --git a/debian/rules b/debian/rules index ccd6ae7..20cdce9 100755 --- a/debian/rules +++ b/debian/rules @@ -46,6 +46,7 @@ build-stamp: config.status # Add here commands to compile the package. $(MAKE) + $(MAKE) docs touch $@ From 1cb6632c8aa10bb2c698ccd254260fd79a2564b9 Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 24 Apr 2007 21:45:25 +0000 Subject: [PATCH 014/328] * add diagnostic program test_video to dump more verbose video debug --- ChangeLog | 2 + test/Makefile.am.inc | 2 + test/test_video.c | 306 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 310 insertions(+) create mode 100644 test/test_video.c diff --git a/ChangeLog b/ChangeLog index 06fdf00..a45b830 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,8 @@ current: + * add diagnostic program test_video to dump more verbose video debug * incorporate documentation into Debian package - thanks to Vít Hrachový for the patch! + * fix VPATH doc builds (requires automake-1.10 and autoconf-2.61) * build and dist fixes - suppress documentation rebuilds in distributed sources * add Debian packaging sources - thanks to Vít Hrachový for the patch! diff --git a/test/Makefile.am.inc b/test/Makefile.am.inc index f585d14..9ce0913 100644 --- a/test/Makefile.am.inc +++ b/test/Makefile.am.inc @@ -18,4 +18,6 @@ test_dbg_scan_LDADD = $(MAGICK_LIBS) zebra/libzebra.la # automake bug in "monolithic mode"? CLEANFILES += test/.libs/dbg_scan +check_PROGRAMS += test/test_video + endif diff --git a/test/test_video.c b/test/test_video.c new file mode 100644 index 0000000..2bdd73d --- /dev/null +++ b/test/test_video.c @@ -0,0 +1,306 @@ +/*------------------------------------------------------------------------ + * Copyright 2007 (c) Jeff Brown + * + * This file is part of the Zebra Barcode Library. + * + * The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zebra + *------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void dump_window (struct video_window *vwin) +{ + printf(" position : %d x %d\n" + " size : %d x %d\n" + " chromakey : 0x%x\n" + " flags :", + vwin->x, vwin->y, + vwin->width, vwin->height, + vwin->chromakey); + static const char *vwin_flags[] = { + "INTERLACE", "", "", "", "CHROMAKEY", + }; + int i; + for(i = 0; i < 5; i++) + if(vwin->flags & (1 << i)) + printf(" %s", vwin_flags[i]); + printf("\n"); +} + +int main (int argc, char *argv[]) +{ + char *dev = "/dev/video0"; + if(argc > 1) { + if(!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { + printf("usage: %s [/dev/videoX]\n", argv[0]); + return(0); + } + dev = argv[1]; + } + + int fd = open("/dev/video0", O_RDWR); + if(fd < 0) { + fprintf(stderr, "ERROR opening %s: ", dev); + perror(NULL); + fprintf(stderr, + " unable to access your video device:\n" + " - is video4linux installed?\n" + " - is your video driver installed?\n" + " - is your video device located at \"%s\"?\n" + " - do you have read/write permission to access it?\n" + " - does the device work with other programs?\n", dev); + return(1); + } + printf("opened device %s\n", dev); + + /* check capabilities */ + struct video_capability vcap; + if(ioctl(fd, VIDIOCGCAP, &vcap) < 0) { + perror("ERROR VIDIOCGCAP"); + struct v4l2_capability vcap2; + if(ioctl(fd, VIDIOC_QUERYCAP, &vcap2) < 0) + fprintf(stderr, " %s is not a v4l device\n", dev); + else + fprintf(stderr, + " device only supports v4l version 2?\n" + " this program requires v4l version 1 support\n" + " (which should be available in emulation?)\n" + " - make sure you have the latest drivers\n"); + return(1); + } + printf("%s supports v4l1\n" + " name : %s\n" + " type :", + dev, vcap.name); + static const char *types[] = { + "CAPTURE", "TUNER", "TELETEXT", "OVERLAY", + "CHROMAKEY", "CLIPPING", "FRAMERAM", "SCALES", + "MONOCHROME", "SUBCAPTURE", + }; + int i; + for(i = 0; i < 10; i++) + if(vcap.type & (1 << i)) + printf(" %s", types[i]); + printf("\n" + " channels : %d\n" + " audios : %d\n" + " max size : %d x %d\n" + " min size : %d x %d\n" + "\n", + vcap.channels, vcap.audios, + vcap.maxwidth, vcap.maxheight, + vcap.minwidth, vcap.minheight); + + if(!(vcap.type & VID_TYPE_CAPTURE)) { + fprintf(stderr, + "ERROR: CAPTURE to memory not supported by device\n" + " this program requires the CAPTURE function\n" + " - make sure your device is a video capture device\n" + " - make sure the correct device is selected\n" + " - make sure you have the latest drivers\n"); + return(1); + } + + /* initialize window properties */ + struct video_window vwin; + if(ioctl(fd, VIDIOCGWIN, &vwin) < 0) { + perror("ERROR VIDIOCGWIN"); + fprintf(stderr, + " unable to query window settings from driver\n" + " this is an unexpected driver communication error\n" + " - make sure you have the latest drivers\n"); + return(1); + } + + printf("current window setting:\n"); + dump_window(&vwin); + + printf("attempting to set maximum size window...\n"); + vwin.width = vcap.maxwidth; + vwin.height = vcap.maxheight; + + if(ioctl(fd, VIDIOCSWIN, &vwin) < 0) { + perror("ERROR VIDIOCSWIN"); + fprintf(stderr, + " unable to update window settings\n" + " this is an unexpected driver communication error\n" + " - make sure you have the latest drivers\n" + "(continuing anyway w/current window settings)\n"); + } + if(ioctl(fd, VIDIOCGWIN, &vwin) < 0) { + perror("ERROR VIDIOCGWIN"); + fprintf(stderr, + " unable to query window settings from driver\n" + " this is an unexpected driver communication error\n" + " - make sure you have the latest drivers\n" + "(continuing anyway w/current window settings)\n"); + } + printf("new window setting:\n"); + dump_window(&vwin); + printf("\n"); + + /* setup image properties */ + struct video_picture vpic; + if(ioctl(fd, VIDIOCGPICT, &vpic) < 0) { + perror("ERROR VIDIOCGPICT"); + fprintf(stderr, + " unable to query image properties from driver\n" + " this is an unexpected driver communication error\n"); + return(1); + } + static const char *palettes[] = { + "", "GREY", "HI240", "RGB565", + "RGB24", "RGB32", "RGB555", "YUV422", + "YUYV", "UYVY", "YUV420", "YUV411", + "RAW", "YUV422P", "YUV411P", "YUV420P", + "YUV410P", + }; + printf("current image settings:\n" + " brightness: %d\n" + " hue : %d\n" + " colour : %d\n" + " contrast : %d\n" + " whiteness : %d\n" + " depth : %d\n" + " palette : %s\n" + "\n", + vpic.brightness, vpic.hue, vpic.colour, vpic.contrast, + vpic.whiteness, vpic.depth, + ((vpic.palette <= VIDEO_PALETTE_YUV410P) + ? palettes[vpic.palette] : "")); + + printf("probing supported palettes:\n"); + uint32_t supported = 0; + for(i = 1; i <= VIDEO_PALETTE_YUV410P; i++) { + printf(" %-8s...", palettes[i]); + fflush(stdout); + vpic.palette = i; + if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { + printf("no (set fails)\n"); + continue; + } + if(ioctl(fd, VIDIOCGPICT, &vpic) < 0) { + perror("\nERROR VIDIOCGPICT"); + fprintf(stderr, + " unable to query image properties from driver\n" + " this is an unexpected driver communication error\n"); + return(1); + } + if(vpic.palette != i) { + printf("no (set ignored)\n"); + continue; + } + printf("yes\n"); + supported |= 1 << i; + } + printf("\n"); + + if(!(supported & (1 << VIDEO_PALETTE_RGB24))) { + fprintf(stderr, + "ERROR: RGB24 palette not supported by device\n" + " this program currently requires RGB24 palette.\n" + " you can open a \"feature request\" from the sourceforge" + " project page\n" + " to request support for additional palettes:\n" + " https://sourceforge.net/projects/zebra\n" + " please ensure you are running the latest drivers\n" + " and include the full output from this program\n"); + return(1); + } + + /* reset to RGB24 */ + vpic.palette = VIDEO_PALETTE_RGB24; + if(ioctl(fd, VIDIOCSPICT, &vpic) < 0 || + ioctl(fd, VIDIOCGPICT, &vpic) < 0 || + vpic.palette != VIDEO_PALETTE_RGB24) { + fprintf(stderr, + "ERROR: unable to reset to previously set RGB24 palette?!\n" + " this is an unexpected driver communication error\n"); + return(1); + } + + /* map camera image to memory */ + struct video_mbuf vbuf; + if(ioctl(fd, VIDIOCGMBUF, &vbuf) < 0) { + perror("ERROR VIDIOCGMBUF"); + fprintf(stderr, + " device does not support mmap capture interface\n" + " this program currently requires mmap capture support\n" + " - make sure you have the latest drivers\n"); + return(1); + } + + printf("memory buffer information:\n" + " size : %08x\n" + " frames : %d\n", + vbuf.size, vbuf.frames); + for(i = 0; i < vbuf.frames; i++) + printf(" [%02d] : %08x\n", i, vbuf.offsets[i]); + + if(!vbuf.frames) { + fprintf(stderr, + "ERROR: no frames are supported by device?!\n" + " maybe device does not support mmap capture interface\n" + " this program currently requires mmap capture support\n" + " - make sure you have the latest drivers\n"); + return(0); + } + + printf("\nattempting to map memory buffer...\n"); + void *image = mmap(0, vbuf.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if(image == MAP_FAILED) { + perror("ERROR: mmap"); + fprintf(stderr, " failed to map memory?!\n"); + return(1); + } + printf("memory buffer mapped at %p\n\n", image); + + /* now try capturing an image */ + struct video_mmap vmap; + vmap.frame = 0; + vmap.height = vwin.height; + vmap.width = vwin.width; + vmap.format = vpic.palette; + printf("initiating capture...\n"); + if(ioctl(fd, VIDIOCMCAPTURE, &vmap) < 0) { + perror("ERROR VIDIOCMCAPTURE"); + fprintf(stderr, " failed to initiate image capture?\n"); + return(1); + } + printf("waiting for image...\n"); + if(ioctl(fd, VIDIOCSYNC, &vmap.frame) < 0) { + perror("ERROR VIDIOCSYNC"); + fprintf(stderr, " failed to capture image\n"); + return(1); + } + + printf("image capture successful!\n\n" + "video support verified\n\n"); + + return(0); +} From f5273d3addef46e90fbe3432da1253d93fd8f386 Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 28 Apr 2007 23:02:47 +0000 Subject: [PATCH 015/328] * add first-pass partial support for Code 128 - separate out more EAN state from shared state - internal interface changes - finish dynamic buffer management - add shared resource locking - add Code 128 to test_decode program => still needs additional functionality and plenty of debug => reading both Code 128 *and* EAN still destabilized --- ChangeLog | 8 + test/test_decode.c | 167 +++++++++++++----- zebra/Makefile.am.inc | 3 +- zebra/code128.c | 401 ++++++++++++++++++++++++++++++++++++++++++ zebra/code128.h | 45 +++++ zebra/decoder.c | 25 ++- zebra/decoder.h | 63 ++++++- zebra/ean.c | 121 +++++++++---- zebra/ean.h | 16 +- 9 files changed, 754 insertions(+), 95 deletions(-) create mode 100644 zebra/code128.c create mode 100644 zebra/code128.h diff --git a/ChangeLog b/ChangeLog index a45b830..a389336 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,12 @@ current: + * add first-pass partial support for Code 128 + - separate out more EAN state from shared state + - internal interface changes + - finish dynamic buffer management + - add shared resource locking + - add Code 128 to test_decode program + => still needs additional functionality and plenty of debug + => reading both Code 128 *and* EAN still destabilized * add diagnostic program test_video to dump more verbose video debug * incorporate documentation into Debian package - thanks to Vít Hrachový for the patch! diff --git a/test/test_decode.c b/test/test_decode.c index 3d6b868..ebf3f04 100644 --- a/test/test_decode.c +++ b/test/test_decode.c @@ -26,33 +26,6 @@ #include -static const unsigned int digits[10] = { - 0x1123, 0x1222, 0x2212, 0x1141, 0x2311, - 0x1321, 0x4111, 0x2131, 0x3121, 0x2113, -}; - -static const unsigned int guard[] = { - 0, 0, - 0x11, /* [2] add-on delineator */ - 0x1117, /* [3] normal guard bars */ - 0x2117, /* [4] add-on guard bars */ - 0x11111, /* [5] center guard bars */ - 0x111111 /* [6] "special" guard bars */ -}; - -static const unsigned char parity_encode[] = { - 0x3f, /* AAAAAA = 0 */ - 0x34, /* AABABB = 1 */ - 0x32, /* AABBAB = 2 */ - 0x31, /* AABBBA = 3 */ - 0x2c, /* ABAABB = 4 */ - 0x26, /* ABBAAB = 5 */ - 0x23, /* ABBBAA = 6 */ - 0x2a, /* ABABAB = 7 */ - 0x29, /* ABABBA = 8 */ - 0x25, /* ABBABA = 9 */ -}; - zebra_decoder_t *decoder; static void symbol_handler (zebra_decoder_t *decoder) @@ -68,6 +41,7 @@ static void symbol_handler (zebra_decoder_t *decoder) static void encode_junk (int n) { + printf("encode random junk...\n"); int i; for(i = 0; i < n; i++) zebra_decode_width(decoder, 10. * (rand() / (RAND_MAX + 1.))); @@ -94,10 +68,110 @@ static void encode (unsigned int units, } } -static zebra_symbol_type_t encode_ean13 (unsigned char *data) + +/*------------------------------------------------------------*/ +/* Code 128 encoding */ + +typedef enum code128_char_e { + FNC3 = 0x60, + FNC2 = 0x61, + SHIFT = 0x62, + CODE_C = 0x63, + CODE_B = 0x64, + CODE_A = 0x65, + FNC1 = 0x66, + START_A = 0x67, + START_B = 0x68, + START_C = 0x69, + STOP = 0x6a, +} code128_char_t; + +static const unsigned int code128[107] = { + 0x212222, 0x222122, 0x222221, 0x121223, /* 00 */ + 0x121322, 0x131222, 0x122213, 0x122312, + 0x132212, 0x221213, 0x221312, 0x231212, /* 08 */ + 0x112232, 0x122132, 0x122231, 0x113222, + 0x123122, 0x123221, 0x223211, 0x221132, /* 10 */ + 0x221231, 0x213212, 0x223112, 0x312131, + 0x311222, 0x321122, 0x321221, 0x312212, /* 18 */ + 0x322112, 0x322211, 0x212123, 0x212321, + 0x232121, 0x111323, 0x131123, 0x131321, /* 20 */ + 0x112313, 0x132113, 0x132311, 0x211313, + 0x231113, 0x231311, 0x112133, 0x112331, /* 28 */ + 0x132131, 0x113123, 0x113321, 0x133121, + 0x313121, 0x211331, 0x231131, 0x213113, /* 30 */ + 0x213311, 0x213131, 0x311123, 0x311321, + 0x331121, 0x312113, 0x312311, 0x332111, /* 38 */ + 0x314111, 0x221411, 0x431111, 0x111224, + 0x111422, 0x121124, 0x121421, 0x141122, /* 40 */ + 0x141221, 0x112214, 0x112412, 0x122114, + 0x122411, 0x142112, 0x142211, 0x241211, /* 48 */ + 0x221114, 0x413111, 0x241112, 0x134111, + 0x111242, 0x121142, 0x121241, 0x114212, /* 50 */ + 0x124112, 0x124211, 0x411212, 0x421112, + 0x421211, 0x212141, 0x214121, 0x412121, /* 58 */ + 0x111143, 0x111341, 0x131141, 0x114113, + 0x114311, 0x411113, 0x411311, 0x113141, /* 60 */ + 0x114131, 0x311141, 0x411131, 0x211412, + 0x211214, 0x211232, /* 68 */ + 0x2331112, /* STOP (6a) */ +}; + +static void encode_code128 (unsigned char *data) +{ + printf("------------------------------------------------------------\n" + "encode CODE-128: %s\n" + " encode START_B: %02x", data, START_B); + encode(code128[START_B], 0); + int i, chk = START_B; + for(i = 0; data[i]; i++) { + printf(" encode '%c': %02x", data[i], data[i] - 0x20); + encode(code128[data[i] - 0x20], 0); + chk += (i + 1) * (data[i] - 0x20); + } + chk %= 103; + printf(" encode checksum: %02x", chk); + encode(code128[chk], 0); + printf(" encode STOP: %02x", STOP); + encode(code128[STOP], 0); + printf("------------------------------------------------------------\n"); +} + + +/*------------------------------------------------------------*/ +/* EAN/UPC encoding */ + +static const unsigned int ean_digits[10] = { + 0x1123, 0x1222, 0x2212, 0x1141, 0x2311, + 0x1321, 0x4111, 0x2131, 0x3121, 0x2113, +}; + +static const unsigned int ean_guard[] = { + 0, 0, + 0x11, /* [2] add-on delineator */ + 0x1117, /* [3] normal guard bars */ + 0x2117, /* [4] add-on guard bars */ + 0x11111, /* [5] center guard bars */ + 0x111111 /* [6] "special" guard bars */ +}; + +static const unsigned char ean_parity_encode[] = { + 0x3f, /* AAAAAA = 0 */ + 0x34, /* AABABB = 1 */ + 0x32, /* AABBAB = 2 */ + 0x31, /* AABBBA = 3 */ + 0x2c, /* ABAABB = 4 */ + 0x26, /* ABBAAB = 5 */ + 0x23, /* ABBBAA = 6 */ + 0x2a, /* ABABAB = 7 */ + 0x29, /* ABABBA = 8 */ + 0x25, /* ABBABA = 9 */ +}; + +static void encode_ean13 (unsigned char *data) { int i; - unsigned char par = parity_encode[data[0]]; + unsigned char par = ean_parity_encode[data[0]]; printf("------------------------------------------------------------\n" "encode EAN-13: "); @@ -105,23 +179,26 @@ static zebra_symbol_type_t encode_ean13 (unsigned char *data) printf("%d", data[i]); printf("(%02x)\n" " encode start guard:", par); - encode(guard[3], FWD); + encode(ean_guard[3], FWD); for(i = 1; i < 7; i++, par <<= 1) { printf(" encode %x%d:", (par >> 5) & 1, data[i]); - encode(digits[data[i]], REV ^ ((par >> 5) & 1)); + encode(ean_digits[data[i]], REV ^ ((par >> 5) & 1)); } printf(" encode center guard:"); - encode(guard[5], FWD); + encode(ean_guard[5], FWD); for(; i < 13; i++) { printf(" encode %x%d:", 0, data[i]); - encode(digits[data[i]], FWD); + encode(ean_digits[data[i]], FWD); } printf(" encode end guard:"); - encode(guard[3], REV); - - return(0); + encode(ean_guard[3], REV); + printf("------------------------------------------------------------\n"); } + +/*------------------------------------------------------------*/ +/* main test flow */ + int main (int argc, char **argv) { int i; @@ -139,21 +216,29 @@ int main (int argc, char **argv) encode_junk(rnd_size); - unsigned char data[14]; + unsigned char data[32]; int chk = 0; for(i = 0; i < 12; i++) { data[i] = (rand() >> 16) % 10; chk += (i & 1) ? data[i] * 3 : data[i]; } - data[12] = chk % 10; - if(data[12]) - data[12] = 10 - data[12]; - data[13] = 0; + data[i] = chk % 10; + if(data[i]) + data[i] = 10 - data[i]; + data[++i] = 0; encode_ean13(data); encode_junk(rnd_size); + for(i = 0; i < 10; i++) + data[i] = (rand() >> 16) % 0x5f + 0x20; + data[i] = 0; + + encode_code128(data); + + encode_junk(rnd_size); + zebra_decoder_destroy(decoder); return(0); } diff --git a/zebra/Makefile.am.inc b/zebra/Makefile.am.inc index 36411a5..ba8bda4 100644 --- a/zebra/Makefile.am.inc +++ b/zebra/Makefile.am.inc @@ -2,5 +2,6 @@ lib_LTLIBRARIES = zebra/libzebra.la zebra_libzebra_la_SOURCES = \ zebra/img_walker.c zebra/scanner.c \ zebra/decoder.h zebra/decoder.c \ - zebra/ean.h zebra/ean.c + zebra/ean.h zebra/ean.c \ + zebra/code128.h zebra/code128.c zebra_libzebra_la_LDFLAGS = -version-info $(LIB_VERSION) diff --git a/zebra/code128.c b/zebra/code128.c new file mode 100644 index 0000000..d44d2bf --- /dev/null +++ b/zebra/code128.c @@ -0,0 +1,401 @@ +/*------------------------------------------------------------------------ + * Copyright 2007 (c) Jeff Brown + * + * This file is part of the Zebra Barcode Library. + * + * The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zebra + *------------------------------------------------------------------------*/ + +#include +#ifdef DEBUG_CODE128 +# include /* fprintf */ +#endif +#include + +#include "zebra.h" +#include "decoder.h" + +#ifdef DEBUG_CODE128 +# define dprintf(level, ...) \ + if(level <= DEBUG_CODE128) \ + fprintf(stderr, __VA_ARGS__) +#else +# define dprintf(...) +#endif + +#define NUM_CHARS 108 /* total number of character codes */ + +typedef enum code128_char_e { + FNC3 = 0x60, + FNC2 = 0x61, + SHIFT = 0x62, + CODE_C = 0x63, + CODE_B = 0x64, + CODE_A = 0x65, + FNC1 = 0x66, + START_A = 0x67, + START_B = 0x68, + START_C = 0x69, + STOP_FWD = 0x6a, + STOP_REV = 0x6b, + FNC4 = 0x6c, +} code128_char_t; + +static const char characters[NUM_CHARS] = { + 0x5c, 0x3f, 0x21, /* [00] 00 */ + 0x2a, 0x45, 0x0c, 0x24, /* [03] 01 */ + 0x2d, 0x63, 0x0f, /* [07] 02 */ + 0x5f, 0x64, /* [0a] 03 */ + + 0x6b, 0x68, 0x69, 0x27, 0x67, /* [0c] 10 */ + 0x41, 0x51, 0x1e, 0x03, 0x59, 0x00, 0x04, 0x1f, /* [11] 11 */ + 0x47, 0x0d, 0x33, 0x06, 0x35, 0x0e, 0x15, 0x07, /* [19] 12 */ + 0x10, 0x5a, 0x11, /* [21] 13 */ + + 0x36, 0x65, 0x18, 0x37, /* [24] 20 */ + 0x4c, 0x13, 0x39, 0x09, 0x17, 0x14, 0x1b, 0x0a, 0x3a, 0x3d, /* [28] 21 */ + 0x22, 0x5e, 0x01, 0x05, 0x30, 0x02, 0x23, /* [32] 22 */ + 0x25, 0x2c, 0x16, 0x08, 0x3c, 0x12, 0x26, /* [39] 23 */ + + 0x61, 0x66, 0x56, 0x62, /* [40] 30 */ + 0x19, 0x5b, 0x1a, /* [44] 31 */ + 0x28, 0x32, 0x1c, 0x0b, 0x4d, 0x1d, 0x29, /* [47] 32 */ + 0x43, 0x20, 0x44, /* [4e] 33 */ + + 0x50, 0x5d, 0x40, /* [51] 0014 0025 0034 */ + 0x2b, 0x46, /* [54] 0134 0143 */ + 0x2e, /* [56] 0243 */ + 0x53, 0x60, /* [57] 0341 0352 */ + 0x31, /* [59] 1024 */ + 0x52, 0x42, /* [5a] 1114 1134 */ + 0x34, 0x48, /* [5c] 1242 1243 */ + 0x55, /* [5e] 1441 */ + + 0x57, 0x3e, 0x4e, /* [5f] 4100 5200 4300 */ + 0x3b, 0x49, /* [62] 4310 3410 */ + 0x6a, /* [64] 3420 */ + 0x54, 0x4f, /* [65] 1430 2530 */ + 0x38, /* [67] 4201 */ + 0x58, 0x4b, /* [68] 4111 4311 */ + 0x2f, 0x4a, /* [6a] 2421 3421 */ +}; + +static const char lo_base[8] = { + 0x00, 0x07, 0x0c, 0x19, 0x24, 0x32, 0x40, 0x47 +}; + +static const unsigned char lo_offset[0x80] = { + 0xff, 0xf0, 0xff, 0x1f, 0xff, 0xf2, 0xff, 0xff, /* 00 [00] */ + 0xff, 0xff, 0xff, 0x3f, 0xf4, 0xf5, 0xff, 0x6f, /* 01 */ + 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf1, 0xff, 0x2f, /* 02 [07] */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x4f, /* 03 */ + 0xff, 0x0f, 0xf1, 0xf2, 0xff, 0x3f, 0xff, 0xf4, /* 10 [0c] */ + 0xf5, 0xf6, 0xf7, 0x89, 0xff, 0xab, 0xff, 0xfc, /* 11 */ + 0xff, 0xff, 0x0f, 0x1f, 0x23, 0x45, 0xf6, 0x7f, /* 12 [19] */ + 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xf9, 0xaf, /* 13 */ + + 0xf0, 0xf1, 0xff, 0x2f, 0xff, 0xf3, 0xff, 0xff, /* 20 [24] */ + 0x4f, 0x5f, 0x67, 0x89, 0xfa, 0xbf, 0xff, 0xcd, /* 21 */ + 0xf0, 0xf1, 0xf2, 0x3f, 0xf4, 0x56, 0xff, 0xff, /* 22 [32] */ + 0xff, 0xff, 0x7f, 0x8f, 0x9a, 0xff, 0xbc, 0xdf, /* 23 */ + 0x0f, 0x1f, 0xf2, 0xff, 0xff, 0x3f, 0xff, 0xff, /* 30 [40] */ + 0xf4, 0xff, 0xf5, 0x6f, 0xff, 0xff, 0xff, 0xff, /* 31 */ + 0x0f, 0x1f, 0x23, 0xff, 0x45, 0x6f, 0xff, 0xff, /* 32 [47] */ + 0xf7, 0xff, 0xf8, 0x9f, 0xff, 0xff, 0xff, 0xff, /* 33 */ +}; + +static inline char decode_lo (int sig) +{ + unsigned char offset = (((sig >> 1) & 0x01) | + ((sig >> 3) & 0x06) | + ((sig >> 5) & 0x18) | + ((sig >> 7) & 0x60)); + unsigned char idx = lo_offset[offset]; + if(sig & 1) + idx &= 0xf; + else + idx >>= 4; + if(idx == 0xf) + return(-1); + + unsigned char base = (sig >> 11) | ((sig >> 9) & 1); + assert(base < 8); + idx += lo_base[base]; + + assert(idx <= 0x50); + char c = characters[idx]; + dprintf(2, " %02x(%x(%02x)/%x(%02x)) => %02x", + idx, base, lo_base[base], offset, lo_offset[offset], c); + return(c); +} + +static inline char decode_hi (int sig) +{ + char rev = (sig & 0x4400) != 0; + if(rev) + sig = (((sig >> 12) & 0x000f) | + ((sig >> 4) & 0x00f0) | + ((sig << 4) & 0x0f00) | + ((sig << 12) & 0xf000)); + dprintf(2, " rev=%x", rev != 0); + + char idx; + switch(sig) { + case 0x0014: idx = 0x0; break; + case 0x0025: idx = 0x1; break; + case 0x0034: idx = 0x2; break; + case 0x0134: idx = 0x3; break; + case 0x0143: idx = 0x4; break; + case 0x0243: idx = 0x5; break; + case 0x0341: idx = 0x6; break; + case 0x0352: idx = 0x7; break; + case 0x1024: idx = 0x8; break; + case 0x1114: idx = 0x9; break; + case 0x1134: idx = 0xa; break; + case 0x1242: idx = 0xb; break; + case 0x1243: idx = 0xc; break; + case 0x1441: idx = 0xd; break; + default: return(-1); + } + if(rev) + idx += 0xe; + char c = characters[0x51 + idx]; + dprintf(2, " %02x => %02x", idx, c); + return(c); +} + +static inline char decode6 (zebra_decoder_t *dcode) +{ + /* build edge signature of character */ + unsigned s = calc_s(dcode, 0, 6); + dprintf(2, " s=%d", s); + if(s < 5) + return(-1); + /* calculate similar edge measurements */ + int sig = (get_color(dcode) == ZEBRA_BAR) + ? ((decode_e(get_width(dcode, 0) + get_width(dcode, 1), s, 11) << 12) | + (decode_e(get_width(dcode, 1) + get_width(dcode, 2), s, 11) << 8) | + (decode_e(get_width(dcode, 2) + get_width(dcode, 3), s, 11) << 4) | + (decode_e(get_width(dcode, 3) + get_width(dcode, 4), s, 11))) + : ((decode_e(get_width(dcode, 5) + get_width(dcode, 4), s, 11) << 12) | + (decode_e(get_width(dcode, 4) + get_width(dcode, 3), s, 11) << 8) | + (decode_e(get_width(dcode, 3) + get_width(dcode, 2), s, 11) << 4) | + (decode_e(get_width(dcode, 2) + get_width(dcode, 1), s, 11))); + if(sig < 0) + return(-1); + dprintf(2, " sig=%04x", sig); + /* lookup edge signature */ + char c = (sig & 0x4444) ? decode_hi(sig) : decode_lo(sig); + + /* FIXME character validation */ + + return(c); +} + +static inline char validate_checksum (zebra_decoder_t *dcode) +{ + code128_decoder_t *dcode128 = &dcode->code128; + if(dcode128->character < 3) + return(1); + + /* add in irregularly weighted start character */ + unsigned idx = (dcode128->direction) ? dcode128->character - 1 : 0; + unsigned sum = dcode->buf[idx]; + + /* calculate sum in reverse to avoid multiply operations */ + unsigned i, acc = 0; + for(i = dcode128->character - 3; i; i--) { + idx = (dcode128->direction) ? dcode128->character - i : i; + acc += dcode->buf[idx]; + if(acc >= 103) + acc -= 103; + assert(acc < 103); + sum += acc; + if(sum >= 103) + sum -= 103; + assert(sum < 103); + } + + /* and compare to check character */ + idx = (dcode128->direction) ? 1 : dcode128->character - 2; + char check = dcode->buf[idx]; + dprintf(2, " chk=%02x(%02x)", sum, check); + char err = (sum != check); + if(err) + dprintf(1, " [checksum error]\n"); + return(err); +} + +/* resolve scan direction and convert to ASCII */ +static inline char postprocess (zebra_decoder_t *dcode) +{ + code128_decoder_t *dcode128 = &dcode->code128; + char code; + if(dcode128->direction) { + /* reverse */ + assert(dcode->buf[0] == STOP_REV); + code = dcode->buf[dcode128->character - 1]; + } + else { + /* forward */ + assert(dcode->buf[dcode128->character - 1] == STOP_FWD); + code = dcode->buf[0]; + } + assert(code >= START_A && code <= START_C); + unsigned char charset = code - START_A; + + unsigned i, j; + for(i = 1, j = 0; i < dcode128->character - 2; i++) { + unsigned idx = (dcode128->direction) ? dcode128->character - i : i; + char code = dcode->buf[idx]; + assert(!(code & 0x80)); + + if(dcode128->direction && + (i < ((dcode128->character + 1) >> 1))) + /* reverse first half of buffer before overwriting */ + dcode->buf[idx] = dcode->buf[i]; + + if((charset & 0x2) && (code < 100)) { + /* convert character set C to ASCII */ + /* FIXME buffer grows! + * - tag start of each code C section and 2nd pass grow at end... + */ + dcode->buf[j] = 0; + if(code >= 50) { + code -= 50; + dcode->buf[j] += 0x50; + } + if(code >= 30) { + code -= 30; + dcode->buf[j] += 0x30; + } + if(code >= 20) { + code -= 20; + dcode->buf[j] += 0x20; + } + if(code >= 10) { + code -= 10; + dcode->buf[j] += 0x10; + } + assert(code <= 9); + assert((unsigned char)dcode->buf[j] <= 0x90); + dcode->buf[j++] |= code; + } + else if(code < 0x60) { + /* convert character set B to ASCII */ + code = code + 0x20; + if((!charset || (charset == 0x81)) && (code >= 0x60)) + /* convert character set A to ASCII */ + code -= 0x60; + dcode->buf[j++] = code; + if(charset & 0x80) + charset &= 0x7f; + } + else if(code < CODE_C) { + if(code == SHIFT) + charset |= 0x80; + else if(code == FNC2) + /* FIXME FNC2 - message append */; + else if(code == FNC3) + /* FIXME FNC3 - initialize */; + } + else if(code == FNC1) + /* FIXME FNC1 - Code 128 subsets or ASCII 0x1d */; + else if(code >= START_A) { + dprintf(1, " [truncated]\n"); + return(1); + } + else { + assert(code >= CODE_C && code <= CODE_A); + unsigned char newset = CODE_A - code; + assert(newset <= 2); + if(newset != charset) + charset = newset; + else + /* FIXME FNC4 - extended ASCII */; + } + } + dcode->buf[j] = '\0'; + return(0); +} + +zebra_symbol_type_t zebra_decode_code128 (zebra_decoder_t *dcode) +{ + code128_decoder_t *dcode128 = &dcode->code128; + if(/* process every 6th element of active symbol */ + (dcode128->character >= 0 && + (++dcode128->element) != 6) || + /* decode color based on direction */ + (get_color(dcode) != dcode128->direction)) + return(0); + + dprintf(2, " code128[%c%02d+%x]:", + (dcode128->direction) ? '<' : '>', + dcode128->character, dcode128->element); + + char c = decode6(dcode); + if(dcode128->character < 0) { + if(c < START_A || c > STOP_REV || c == STOP_FWD) { + dprintf(2, " [invalid]\n"); + return(0); + } + /* decoded valid start/stop */ + /* initialize state */ + dcode128->character = 0; + if(c == STOP_REV) { + dcode128->direction = ZEBRA_BAR; + dcode128->element = 7; + } + else + dcode128->direction = ZEBRA_SPACE; + /* lock shared resources */ + dcode->lock = 1; + dprintf(2, " dir=%x [valid start]", dcode128->direction); + } + else if((c < 0) || + ((dcode128->character > BUFFER_MIN) && + size_buf(dcode, dcode128->character + 1))) { + dprintf(1, (c < 0) ? " [aborted]\n" : " [overflow]\n"); + dcode->lock = 0; + code128_reset(dcode128); + return(0); + } + dcode128->element = 0; + + assert(dcode->buflen > dcode128->character); + dcode->buf[dcode128->character++] = c; + + if(dcode128->character > 2 && + ((dcode128->direction) + ? c >= START_A && c <= START_C + : c == STOP_FWD)) { + /* FIXME STOP_FWD should check extra bar */ + zebra_symbol_type_t sym = ZEBRA_CODE128; + if(validate_checksum(dcode) || postprocess(dcode)) { + dcode->lock = 0; + sym = ZEBRA_NONE; + } + else + dprintf(2, " [valid end]\n"); + code128_reset(dcode128); + return(sym); + } + + dprintf(2, "\n"); + return(0); +} diff --git a/zebra/code128.h b/zebra/code128.h new file mode 100644 index 0000000..7ec9b34 --- /dev/null +++ b/zebra/code128.h @@ -0,0 +1,45 @@ +/*------------------------------------------------------------------------ + * Copyright 2007 (c) Jeff Brown + * + * This file is part of the Zebra Barcode Library. + * + * The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zebra + *------------------------------------------------------------------------*/ +#ifndef _CODE128_H_ +#define _CODE128_H_ + +/* Code 128 specific decode state */ +typedef struct code128_decoder_s { + int direction : 1; /* scan direction: 0=fwd/space, 1=rev/bar */ + unsigned element : 3; /* element offset 0-5 */ + int character : 12; /* character position in symbol */ + char buf[6]; /* holding buffer */ +} code128_decoder_t; + +/* reset Code 128 specific state */ +static inline void code128_reset (code128_decoder_t *dcode128) +{ + dcode128->direction = 0; + dcode128->element = 0; + dcode128->character = -1; +} + +/* decode Code 128 symbols */ +zebra_symbol_type_t zebra_decode_code128(zebra_decoder_t *dcode); + +#endif diff --git a/zebra/decoder.c b/zebra/decoder.c index 402fb37..e89ffdd 100644 --- a/zebra/decoder.c +++ b/zebra/decoder.c @@ -41,7 +41,7 @@ zebra_decoder_t *zebra_decoder_create () { zebra_decoder_t *dcode = malloc(sizeof(zebra_decoder_t)); - dcode->buflen = 0x20; + dcode->buflen = BUFFER_MIN; dcode->buf = malloc(dcode->buflen); zebra_decoder_reset(dcode); return(dcode); @@ -56,6 +56,7 @@ void zebra_decoder_reset (zebra_decoder_t *dcode) { memset(dcode, 0, (long)&dcode->buf - (long)dcode); ean_reset(&dcode->ean); + code128_reset(&dcode->code128); } void zebra_decoder_new_scan (zebra_decoder_t *dcode) @@ -63,7 +64,8 @@ void zebra_decoder_new_scan (zebra_decoder_t *dcode) /* soft reset decoder */ memset(dcode->w, 0, sizeof(dcode->w)); dcode->idx = 0; - ean_reset(&dcode->ean); + ean_new_scan(&dcode->ean); + code128_reset(&dcode->code128); } const char *zebra_decoder_get_data (const zebra_decoder_t *dcode) @@ -126,19 +128,24 @@ zebra_symbol_type_t zebra_decode_width (zebra_decoder_t *dcode, /* each decoder processes width stream in parallel */ zebra_symbol_type_t sym = dcode->type = ZEBRA_NONE; -/*#ifdef ENABLE_EAN*/ +#define ENABLE_EAN +#ifdef ENABLE_EAN if((sym = zebra_decode_ean(dcode))) dcode->type = sym; -/*#endif*/ +#endif +#define ENABLE_CODE128 #ifdef ENABLE_CODE128 - if((sym = zebra_decode_code128(dcode)) > ZEBRA_PARTIAL || dcode->type) + if((sym = zebra_decode_code128(dcode)) > ZEBRA_PARTIAL) dcode->type = sym; #endif - dcode->type = sym; dcode->idx++; - if(sym && dcode->handler) - dcode->handler(dcode); - return(sym); + if(dcode->type) { + if(dcode->handler) + dcode->handler(dcode); + if(dcode->lock) + dcode->lock = 0; + } + return(dcode->type); } diff --git a/zebra/decoder.h b/zebra/decoder.h index e6e4ee7..5e565ea 100644 --- a/zebra/decoder.h +++ b/zebra/decoder.h @@ -23,17 +23,40 @@ #ifndef _DECODER_H_ #define _DECODER_H_ +#include /* realloc */ + #include "zebra.h" #include "ean.h" +#include "code128.h" /* size of bar width history (implementation assumes power of two) */ -#define DECODE_WINDOW 8 +#ifndef DECODE_WINDOW +# define DECODE_WINDOW 8 +#endif + +/* initial data buffer allocation */ +#ifndef BUFFER_MIN +# define BUFFER_MIN 0x20 +#endif + +/* maximum data buffer allocation + * (longer symbols are rejected) + */ +#ifndef BUFFER_MAX +# define BUFFER_MAX 0x100 +#endif + +/* buffer allocation increment */ +#ifndef BUFFER_INCR +# define BUFFER_INCR 0x10 +#endif /* symbology independent decoder state */ struct zebra_decoder_s { unsigned char idx; /* current width index */ unsigned w[DECODE_WINDOW]; /* window of last N bar widths */ zebra_symbol_type_t type; /* type of last decoded data */ + unsigned lock : 1; /* buffer lock */ /* everything above here is automatically reset */ char *buf; /* decoded characters */ @@ -43,6 +66,7 @@ struct zebra_decoder_s { /* symbology specific state */ ean_decoder_t ean; /* EAN/UPC parallel decode attempts */ + code128_decoder_t code128; /* Code 128 decode state */ }; /* return current element color */ @@ -84,9 +108,9 @@ static inline unsigned calc_s (const zebra_decoder_t *dcode, * => using like-edge measurements avoids these issues * - n should be > 3 */ -static inline char decode_e (unsigned e, - unsigned s, - unsigned n) +static inline int decode_e (unsigned e, + unsigned s, + unsigned n) { /* result is encoded number of units - 2 * (for use as zero based index) @@ -96,4 +120,35 @@ static inline char decode_e (unsigned e, return((E >= n - 3) ? -1 : E); } +/* acquire shared state lock */ +static inline char get_lock (zebra_decoder_t *dcode) +{ + if(dcode->lock) + return(1); + dcode->lock = 1; + return(0); +} + +/* ensure output buffer has sufficient allocation for request */ +static inline char size_buf (zebra_decoder_t *dcode, + unsigned len) +{ + if(len < dcode->buflen) + /* FIXME size reduction heuristic? */ + return(0); + if(len > BUFFER_MAX) + return(1); + if(len < dcode->buflen + BUFFER_INCR) { + len = dcode->buflen + BUFFER_INCR; + if(len > BUFFER_MAX) + len = BUFFER_MAX; + } + char *buf = realloc(dcode->buf, len); + if(!buf) + return(1); + dcode->buf = buf; + dcode->buflen = len; + return(0); +} + #endif diff --git a/zebra/ean.c b/zebra/ean.c index 00c1852..8ac3c1d 100644 --- a/zebra/ean.c +++ b/zebra/ean.c @@ -92,6 +92,30 @@ static const char parity_decode[] = { 0x0f, /* [3f] AAAAAA = 0 */ }; +#ifdef DEBUG_EAN +static char debug_buf[0x18]; + +static inline const char *dsprintbuf(ean_decoder_t *ean) +{ + int i; + for(i = 0; i < 7; i++) + debug_buf[i] = ((ean->buf[0] < 0 || ean->buf[i] < 0) + ? '-' + : ean->buf[i] + '0'); + debug_buf[i] = ' '; + for(; i < 13; i++) + debug_buf[i + 1] = ((ean->buf[7] < 0 || ean->buf[i] < 0) + ? '-' + : ean->buf[i] + '0'); + debug_buf[i + 1] = ' '; + for(; i < 18; i++) + debug_buf[i + 2] = ((ean->buf[13] < 0 || ean->buf[i] < 0) + ? '-' + : ean->buf[i] + '0'); + debug_buf[i + 2] = '\0'; + return(debug_buf); +} +#endif /* evaluate previous N (>= 2) widths as auxiliary pattern, * using preceding 4 as character width @@ -306,12 +330,13 @@ static inline zebra_symbol_type_t decode_pass (zebra_decoder_t *dcode, return(0); } -static inline char check_ean13_parity (zebra_decoder_t *dcode) +static inline char check_ean13_parity (ean_decoder_t *ean) { unsigned char chk = 0; unsigned char i; for(i = 0; i < 12; i++) { - unsigned char d = dcode->buf[i] - '0'; + unsigned char d = ean->buf[i]; + assert(d < 10); chk += d; if(i & 1) { chk += d << 1; @@ -324,84 +349,102 @@ static inline char check_ean13_parity (zebra_decoder_t *dcode) assert(chk < 10); if(chk) chk = 10 - chk; - unsigned char d = dcode->buf[12] - '0'; + unsigned char d = ean->buf[12]; assert(d < 10); if(chk != d) { - dprintf(1, "checksum mismatch %d != %d (%s)\n", chk, d, dcode->buf); + dprintf(1, "checksum mismatch %d != %d (%s)\n", + chk, d, dsprintbuf(ean)); return(-1); } return(0); } -static inline zebra_symbol_type_t integrate_partial (zebra_decoder_t *dcode, +static inline zebra_symbol_type_t integrate_partial (ean_decoder_t *ean, ean_pass_t *pass, zebra_symbol_type_t part) { /* FIXME UPC-E, EAN-8 */ - /* copy raw data into output buffer */ + /* copy raw data into holding buffer */ /* if same partial is not consistent, reset others */ - dprintf(2, " integrate part=%x (%x%x%x)\n", - part, dcode->buf[0], dcode->buf[7], dcode->buf[13]); + dprintf(2, " integrate part=%x (%s)", part, dsprintbuf(ean)); unsigned char i; if(part == LEFT_HALF) { - if(dcode->buf[0] && dcode->buf[7]) + if(ean->buf[0] >= 0 && ean->buf[7] >= 0) part = ZEBRA_EAN13; - + for(i = 0; i < 7; i++) { - char ch = (pass->raw[i] & 0xf) + '0'; + char digit = pass->raw[i] & 0xf; if(part == ZEBRA_EAN13 && - dcode->buf[i] != ch) { + ean->buf[i] != digit) { /* partial mismatch - reset other parts */ - dcode->buf[7] = dcode->buf[13] = 0; + ean->buf[7] = ean->buf[13] = -1; part = ZEBRA_PARTIAL; } - dcode->buf[i] = ch; + ean->buf[i] = digit; } - if(part == LEFT_HALF && dcode->buf[7]) + if(part == LEFT_HALF && ean->buf[7] >= 0) part = ZEBRA_EAN13; } else if(part == RIGHT_HALF) { - if(dcode->buf[0] && dcode->buf[7]) + if(ean->buf[0] >= 0 && ean->buf[7] >= 0) part = ZEBRA_EAN13; for(i = 0; i < 6; i++) { - char ch = (pass->raw[i + 1] & 0xf) + '0'; + char digit = pass->raw[i + 1] & 0xf; if(part == ZEBRA_EAN13 && - dcode->buf[i + 7] != ch) { + ean->buf[i + 7] != digit) { /* partial mismatch - reset other parts */ - dcode->buf[0] = dcode->buf[13] = 0; + ean->buf[0] = ean->buf[13] = -1; part = ZEBRA_PARTIAL; } - dcode->buf[i + 7] = ch; + ean->buf[i + 7] = digit; } - if(part == RIGHT_HALF && dcode->buf[0]) + if(part == RIGHT_HALF && ean->buf[0] >= 0) part = ZEBRA_EAN13; } else { unsigned char len = (part == ZEBRA_ADDON5) ? 5 : 2; - if(dcode->buf[0] && dcode->buf[7] && dcode->buf[13]) + if(ean->buf[0] >= 0 && ean->buf[7] >= 0 && ean->buf[13] >= 0) part |= ZEBRA_EAN13; for(i = 0; i < len; i++) { - char ch = (pass->raw[i] & 0xf) + '0'; + char digit = pass->raw[i] & 0xf; if((part & ZEBRA_SYMBOL) == ZEBRA_EAN13 && - dcode->buf[i + 13] != ch) { + ean->buf[i + 13] != digit) { /* partial mismatch - reset other parts */ - dcode->buf[0] = dcode->buf[7] = 0; + ean->buf[0] = ean->buf[7] = -1; part &= ZEBRA_ADDON; } - dcode->buf[i + 13] = ch; + ean->buf[i + 13] = digit; } } if(part == ZEBRA_EAN13 && - check_ean13_parity(dcode)) + check_ean13_parity(ean)) /* invalid parity */ part = ZEBRA_NONE; - if(part == ZEBRA_EAN13 && dcode->buf[13]) - part |= (dcode->buf[15]) ? ZEBRA_ADDON5 : ZEBRA_ADDON2; + if(part == ZEBRA_EAN13 && ean->buf[13] >= 0) + part |= (ean->buf[15] >= 0) ? ZEBRA_ADDON5 : ZEBRA_ADDON2; + if(part == LEFT_HALF || part == RIGHT_HALF) + part = ZEBRA_PARTIAL; return(part); } +/* copy result to output buffer */ +static inline void postprocess (zebra_decoder_t *dcode, + zebra_symbol_type_t sym) +{ + ean_decoder_t *ean = &dcode->ean; + int i; + if((sym & ZEBRA_SYMBOL) > ZEBRA_PARTIAL) + for(i = 0; i < 12 && ean->buf[i] >= 0; i++) + dcode->buf[i] = ean->buf[i] + '0'; + int j = i; + if(sym & ZEBRA_ADDON) + for(i = 13; ean->buf[i] >= 0; i++) + dcode->buf[j++] = ean->buf[i] + '0'; + dcode->buf[j] = '\0'; +} + zebra_symbol_type_t zebra_decode_ean (zebra_decoder_t *dcode) { /* process upto 4 separate passes */ @@ -414,20 +457,28 @@ zebra_symbol_type_t zebra_decode_ean (zebra_decoder_t *dcode) if(pass->state >= 0 || i == pass_idx) { - dprintf(2, " decode[%x/%x]: idx=%x st=%d", + dprintf(2, " ean[%x/%x]: idx=%x st=%d", pass_idx, i, dcode->idx, pass->state); zebra_symbol_type_t part = decode_pass(dcode, pass); if(part) { /* update accumulated data from new partial decode */ - sym = integrate_partial(dcode, pass, part); - if(sym) + sym = integrate_partial(&dcode->ean, pass, part); + if(sym) { /* this pass valid => _reset_ all passes */ - ean_reset(&dcode->ean); + dprintf(2, " sym=%x", sym); + ean_new_scan(&dcode->ean); + if(sym > ZEBRA_PARTIAL) { + if(!get_lock(dcode)) + postprocess(dcode, sym); + else { + dprintf(1, " [locked]"); + sym = ZEBRA_PARTIAL; + } + } + } } dprintf(2, "\n"); } } - if(sym == LEFT_HALF || sym == RIGHT_HALF) - sym = ZEBRA_PARTIAL; return(sym); } diff --git a/zebra/ean.h b/zebra/ean.h index 6f49fe0..e2cec56 100644 --- a/zebra/ean.h +++ b/zebra/ean.h @@ -34,15 +34,21 @@ typedef struct ean_pass_s { /* EAN/UPC specific decode state */ typedef struct ean_decoder_s { ean_pass_t pass[4]; /* state of each parallel decode attempt */ + char buf[18]; /* holding buffer */ } ean_decoder_t; -/* reset EAN/UPC specific state */ +/* reset EAN/UPC pass specific state */ +static inline void ean_new_scan (ean_decoder_t *ean) +{ + ean->pass[0].state = ean->pass[1].state = -1; + ean->pass[2].state = ean->pass[3].state = -1; +} + +/* reset all EAN/UPC state */ static inline void ean_reset (ean_decoder_t *ean) { - ean->pass[0].state = -1; - ean->pass[1].state = -1; - ean->pass[2].state = -1; - ean->pass[3].state = -1; + ean_new_scan(ean); + ean->buf[0] = ean->buf[7] = ean->buf[13] = ean->buf[15] = -1; } /* decode EAN/UPC symbols */ From 4e12f349e447e948fb6469f0c90ee6365dce4a56 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 10 May 2007 12:34:11 +0000 Subject: [PATCH 016/328] * cleanup 64-bit compile warnings in zebraimg (bug #1712504) --- ChangeLog | 1 + configure.ac | 1 + zebra/ean.c | 4 ++-- zebraimg/zebraimg.cpp | 7 +++++-- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index a389336..560bdde 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * cleanup 64-bit compile warnings in zebraimg (bug #1712504) * add first-pass partial support for Code 128 - separate out more EAN state from shared state - internal interface changes diff --git a/configure.ac b/configure.ac index 03e4c14..1dd7d1d 100644 --- a/configure.ac +++ b/configure.ac @@ -102,6 +102,7 @@ AC_CHECK_HEADERS([fcntl.h inttypes.h stdlib.h string.h sys/ioctl.h sys/time.h]) AC_TYPE_INT32_T AC_TYPE_UINT32_T AC_TYPE_UINT8_T +AC_TYPE_UINTPTR_T AC_C_CONST AC_C_INLINE diff --git a/zebra/ean.c b/zebra/ean.c index 8ac3c1d..4f2df05 100644 --- a/zebra/ean.c +++ b/zebra/ean.c @@ -434,9 +434,9 @@ static inline void postprocess (zebra_decoder_t *dcode, zebra_symbol_type_t sym) { ean_decoder_t *ean = &dcode->ean; - int i; + int i = 0; if((sym & ZEBRA_SYMBOL) > ZEBRA_PARTIAL) - for(i = 0; i < 12 && ean->buf[i] >= 0; i++) + for(; i < 12 && ean->buf[i] >= 0; i++) dcode->buf[i] = ean->buf[i] + '0'; int j = i; if(sym & ZEBRA_ADDON) diff --git a/zebraimg/zebraimg.cpp b/zebraimg/zebraimg.cpp index 96292e5..271c99e 100644 --- a/zebraimg/zebraimg.cpp +++ b/zebraimg/zebraimg.cpp @@ -21,6 +21,9 @@ // http://sourceforge.net/projects/zebra //------------------------------------------------------------------------ +#ifdef HAVE_INTTYPES_H +# include +#endif #include #include #include @@ -53,9 +56,9 @@ class PixelHandler : public ImageWalker::Handler { virtual char walker_callback (ImageWalker &, void *pixel) { ColorYUV y; - y = *(rd_pxp + (unsigned)pixel); + y = *(rd_pxp + (uintptr_t)pixel); scanner << (int)(y.y() * 0x100); - *(wr_pxp + (unsigned)pixel) = red; + *(wr_pxp + (uintptr_t)pixel) = red; return(0); } } pixel_handler; From da9a3ecc048e695ae59bd340f6dc0e8770e03113 Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 11 May 2007 17:56:40 +0000 Subject: [PATCH 017/328] * significant scanner improvements - changed "classic" [-1 0 1] first differential kernel to [-1 1] to improve minimum edge resolution to single pixel elements => still need to do some more research and validate assumptions - adaptive thresholding fixes - adjusted filtering for better edge detection - separate constants out to defines (FIXME add config API?) * fix EAN-13 secondary determinant decoding * dbg_scan tweaks to make annotations smaller/more usable * add get_color() interface to decoder * annotated zebraimg scan pattern for marginally useful high-level debug * random include cleanup --- ChangeLog | 12 ++++++++ include/zebra.h | 3 ++ include/zebra/Decoder.h | 5 ++++ test/dbg_scan.cc | 14 +++++----- zebra/decoder.c | 7 +++++ zebra/decoder.h | 2 +- zebra/ean.c | 16 ++++++----- zebra/scanner.c | 62 ++++++++++++++++++++++++++++++----------- zebracam/zebracam.c | 2 +- zebraimg/zebraimg.cpp | 8 ++++-- 10 files changed, 95 insertions(+), 36 deletions(-) diff --git a/ChangeLog b/ChangeLog index 560bdde..d132097 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,16 @@ current: + * significant scanner improvements + - changed "classic" [-1 0 1] first differential kernel to [-1 1] + to improve minimum edge resolution to single pixel elements + => still need to do some more research and validate assumptions + - adaptive thresholding fixes + - adjusted filtering for better edge detection + - separate constants out to defines (FIXME add config API?) + * fix EAN-13 secondary determinant decoding + * dbg_scan tweaks to make annotations smaller/more usable + * add get_color() interface to decoder + * annotated zebraimg scan pattern for marginally useful high-level debug + * random include cleanup * cleanup 64-bit compile warnings in zebraimg (bug #1712504) * add first-pass partial support for Code 128 - separate out more EAN state from shared state diff --git a/include/zebra.h b/include/zebra.h index a575c57..da01e38 100644 --- a/include/zebra.h +++ b/include/zebra.h @@ -97,6 +97,9 @@ extern void zebra_decoder_new_scan(zebra_decoder_t *decoder); extern zebra_symbol_type_t zebra_decode_width(zebra_decoder_t *decoder, unsigned width); +/* return color of *next* element passed to zebra_decode_width() */ +extern zebra_color_t zebra_decoder_get_color(const zebra_decoder_t *decoder); + /* returns last decoded data, * or NULL if no new data available. * data buffer is maintained by library, diff --git a/include/zebra/Decoder.h b/include/zebra/Decoder.h index d4e35e9..dfb25d5 100644 --- a/include/zebra/Decoder.h +++ b/include/zebra/Decoder.h @@ -71,6 +71,11 @@ class Decoder { return(*this); } + zebra_color_t get_color () const + { + return(zebra_decoder_get_color(_decoder)); + } + zebra_symbol_type_t get_type () const { return(zebra_decoder_get_type(_decoder)); diff --git a/test/dbg_scan.cc b/test/dbg_scan.cc index ec41c2c..cf2de6f 100644 --- a/test/dbg_scan.cc +++ b/test/dbg_scan.cc @@ -64,7 +64,7 @@ void scan_image (const char *filename) unsigned width = image.columns() + 4 /* for flush */; unsigned height = image.rows(); - unsigned midy = (height + 1) / 2; + unsigned midy = (height + 1) / 2 + 2; image.crop(Geometry(width - 4, 1, 0, midy)); image.size(Geometry(width, 1, 0, 0)); @@ -77,8 +77,8 @@ void scan_image (const char *filename) << " xmlns='http://www.w3.org/2000/svg'>" << endl << "" << endl << "" << endl + << " xlink:href='" << file << ".png'/>" << endl << "" << endl; // brute force @@ -128,13 +133,13 @@ void scan_image (const char *filename) << "" << endl; } image.depth(8); - image.write(image.baseFilename() + ".png"); + image.write(file + ".png"); // process scan and capture calculated values unsigned cur_edge[width], last_edge[width]; int y0[width], y1[width], y2[width], y1_thr[width]; - svg << "" << endl; + svg << "" << endl; for(unsigned i = 0; i < width; i++) { int edge = scanner.scan_y(raw[i]); unsigned x; diff --git a/zebra/code128.c b/zebra/code128.c index 929c84e..0c73af2 100644 --- a/zebra/code128.c +++ b/zebra/code128.c @@ -64,7 +64,7 @@ static const char characters[NUM_CHARS] = { 0x5f, 0xe4, /* [0a] 03 */ 0x6b, 0xe8, 0x69, 0xa7, 0xe7, /* [0c] 10 */ - 0xc1, 0x51, 0x1e, 0x83, 0xc9, 0x00, 0x84, 0x1f, /* [11] 11 */ + 0xc1, 0x51, 0x1e, 0x83, 0xd9, 0x00, 0x84, 0x1f, /* [11] 11 */ 0xc7, 0x0d, 0x33, 0x86, 0xb5, 0x0e, 0x15, 0x87, /* [19] 12 */ 0x10, 0xda, 0x11, /* [21] 13 */ @@ -171,7 +171,7 @@ static inline char decode_hi (int sig) case 0x1134: idx = 0xa; break; case 0x1242: idx = 0xb; break; case 0x1243: idx = 0xc; break; - case 0x1441: idx = 0xd; break; + case 0x1441: idx = 0xd; rev = 0; break; default: return(-1); } if(rev) @@ -244,7 +244,7 @@ static inline char validate_checksum (zebra_decoder_t *dcode) /* calculate sum in reverse to avoid multiply operations */ unsigned i, acc = 0; for(i = dcode128->character - 3; i; i--) { - idx = (dcode128->direction) ? dcode128->character - i : i; + idx = (dcode128->direction) ? dcode128->character - 1 - i : i; acc += dcode->buf[idx]; if(acc >= 103) acc -= 103; @@ -325,7 +325,7 @@ static inline char postprocess (zebra_decoder_t *dcode) dcode->buf[i] = dcode->buf[j]; dcode->buf[j] = code; } - assert(code == STOP_REV); + assert(dcode->buf[dcode128->character - 1] == STOP_REV); } else assert(dcode->buf[dcode128->character - 1] == STOP_FWD); @@ -407,6 +407,7 @@ zebra_symbol_type_t zebra_decode_code128 (zebra_decoder_t *dcode) /* decode color based on direction */ (get_color(dcode) != dcode128->direction)) return(0); + dcode128->element = 0; dprintf(2, " code128[%c%02d+%x]:", (dcode128->direction) ? '<' : '>', @@ -433,14 +434,13 @@ zebra_symbol_type_t zebra_decode_code128 (zebra_decoder_t *dcode) dprintf(2, " dir=%x [valid start]", dcode128->direction); } else if((c < 0) || - ((dcode128->character > BUFFER_MIN) && + ((dcode128->character >= BUFFER_MIN) && size_buf(dcode, dcode128->character + 1))) { dprintf(1, (c < 0) ? " [aborted]\n" : " [overflow]\n"); dcode->lock = 0; code128_reset(dcode128); return(0); } - dcode128->element = 0; assert(dcode->buflen > dcode128->character); dcode->buf[dcode128->character++] = c; diff --git a/zebra/code128.h b/zebra/code128.h index 7ec9b34..1d7104f 100644 --- a/zebra/code128.h +++ b/zebra/code128.h @@ -25,7 +25,7 @@ /* Code 128 specific decode state */ typedef struct code128_decoder_s { - int direction : 1; /* scan direction: 0=fwd/space, 1=rev/bar */ + unsigned direction : 1; /* scan direction: 0=fwd/space, 1=rev/bar */ unsigned element : 3; /* element offset 0-5 */ int character : 12; /* character position in symbol */ char buf[6]; /* holding buffer */ diff --git a/zebra/scanner.c b/zebra/scanner.c index 4da3912..07448b9 100644 --- a/zebra/scanner.c +++ b/zebra/scanner.c @@ -94,23 +94,13 @@ void zebra_scanner_destroy (zebra_scanner_t *scn) free(scn); } -void zebra_scanner_reset (zebra_scanner_t *scn) +zebra_symbol_type_t zebra_scanner_reset (zebra_scanner_t *scn) { memset(&scn->x, 0, sizeof(zebra_scanner_t) + (void*)scn - (void*)&scn->x); scn->y1_thresh = scn->y1_min_thresh; if(scn->decoder) zebra_decoder_reset(scn->decoder); -} - -void zebra_scanner_new_scan (zebra_scanner_t *scn) -{ - /* reset color to SPACE - * (actually just resets everything) - */ - memset(&scn->x, 0, sizeof(zebra_scanner_t) + (void*)scn - (void*)&scn->x); - scn->y1_thresh = scn->y1_min_thresh; - if(scn->decoder) - zebra_decoder_new_scan(scn->decoder); + return(ZEBRA_NONE); } unsigned zebra_scanner_get_width (const zebra_scanner_t *scn) @@ -168,6 +158,21 @@ static inline zebra_symbol_type_t process_edge (zebra_scanner_t *scn, return(ZEBRA_NONE); } +zebra_symbol_type_t zebra_scanner_new_scan (zebra_scanner_t *scn) +{ + /* finalize outstanding edge */ + zebra_symbol_type_t edge = process_edge(scn, 0); + + /* reset color to SPACE + * (actually just resets everything) + */ + memset(&scn->x, 0, sizeof(zebra_scanner_t) + (void*)scn - (void*)&scn->x); + scn->y1_thresh = scn->y1_min_thresh; + if(scn->decoder) + zebra_decoder_new_scan(scn->decoder); + return(edge); +} + zebra_symbol_type_t zebra_scan_y (zebra_scanner_t *scn, int y) { diff --git a/zebracam/zebracam.c b/zebracam/zebracam.c index b62433b..02691be 100644 --- a/zebracam/zebracam.c +++ b/zebracam/zebracam.c @@ -41,8 +41,10 @@ #define DUMP_NAME_MAX 0x20 #define PPM_HDR_MAX 0x20 -#define SYM_MAX 0x20 +#define SYM_MAX 0x200 #define SYM_HYST 2000 /* ms */ +#define UNCERTAINTY 20 /* frames */ +#define CERTAINTY 3 /* frames */ static int cam_fd; static struct video_capability vcap; @@ -66,6 +68,8 @@ int tone_period = 20; zebra_symbol_type_t last_sym_type; char last_sym_data[SYM_MAX]; double last_sym_time = 0; +uint64_t last_sym_frame = 0; +uint32_t last_sym_count = 0; double beep_time = 0; @@ -281,6 +285,7 @@ static inline void process () { zebra_scanner_new_scan(scanner); zebra_img_walk(walker, buf); + zebra_scanner_new_scan(scanner); /* flush scan */ } static void symbol_handler (zebra_decoder_t *decoder) @@ -290,19 +295,33 @@ static void symbol_handler (zebra_decoder_t *decoder) return; const char *data = zebra_decoder_get_data(decoder); - double ms = SDL_GetTicks(); - /* edge detect symbol change w/some hysteresis */ - if(sym == last_sym_type && - !strncmp(data, last_sym_data, SYM_MAX) && - ((ms - last_sym_time) < SYM_HYST)) { - last_sym_time = ms; + int match = (sym == last_sym_type && + !strncmp(data, last_sym_data, SYM_MAX)); + int uncertain = nframes > (last_sym_frame + UNCERTAINTY); + + last_sym_frame = nframes; + last_sym_type = sym; + + /* uncertainty filtering + * symbols are only reported after they have been + * observed consistently in several nearby frames + */ + if(!match || uncertain) { + strncpy(last_sym_data, data, SYM_MAX); + last_sym_count = 0; return; } + if(++last_sym_count < CERTAINTY) + return; - /* report new symbol */ + /* edge detect symbol change w/some hysteresis */ + double ms = SDL_GetTicks(); + int edge = match && ((ms - last_sym_time) < SYM_HYST); last_sym_time = ms; - last_sym_type = sym; - strncpy(last_sym_data, data, SYM_MAX); + if(edge) + return; + + /* report new symbol */ printf("%s%s: %s\n", zebra_get_symbol_name(sym), zebra_get_addon_name(sym), @@ -314,8 +333,12 @@ static void symbol_handler (zebra_decoder_t *decoder) static char pixel_handler (zebra_img_walker_t *walker, void *p) { - if(zebra_scan_rgb24(scanner, p) > ZEBRA_PARTIAL) - return(1); + if(!zebra_img_walker_get_col(walker) || + !zebra_img_walker_get_row(walker)) + zebra_scanner_new_scan(scanner); + + zebra_scan_rgb24(scanner, p); + *((uint8_t*)p - buf + (uint8_t*)screen->pixels + 2) = 0xff; return(0); } diff --git a/zebraimg/zebraimg.cpp b/zebraimg/zebraimg.cpp index 5f245af..b28befb 100644 --- a/zebraimg/zebraimg.cpp +++ b/zebraimg/zebraimg.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -50,6 +51,9 @@ ImageWalker walker; const PixelPacket *rd_pxp; PixelPacket *wr_pxp; unsigned width, height; +map datahist; +string data_max; +unsigned data_cnt; ColorRGB space_fill(1., 0., 0.); ColorRGB bar_fill(.5, 0., 0.); @@ -62,6 +66,8 @@ class PixelHandler : public ImageWalker::Handler { assert(walker.get_col() < width); assert(walker.get_row() < height); assert((uintptr_t)pixel < width * height); + if(!walker.get_col() || !walker.get_row()) + scanner.new_scan(); scanner << (int)(y.y() * 0x100); *(wr_pxp + (uintptr_t)pixel) = (scanner.get_color() == ZEBRA_SPACE) ? bar_fill : space_fill; @@ -72,14 +78,24 @@ class PixelHandler : public ImageWalker::Handler { class SymbolHandler : public Decoder::Handler { virtual void decode_callback (Decoder &decoder) { - if(decoder.get_type() > ZEBRA_PARTIAL) - cout << decoder.get_symbol_name() << decoder.get_addon_name() - << ": " << decoder.get_data_string() << endl; + if(decoder.get_type() > ZEBRA_PARTIAL) { + string data = (string(decoder.get_symbol_name()) + + string(decoder.get_addon_name()) + + ":" + decoder.get_data_string()); + if(++datahist[data] > data_cnt) { + data_max = data; + data_cnt = datahist[data]; + } + } } } symbol_handler; void scan_image (const char *filename) { + scanner.reset(); + datahist.clear(); + data_cnt = 0; + Image image; image.read(filename); Image wr_img = image; @@ -97,10 +113,12 @@ void scan_image (const char *filename) Pixels wr_view(wr_img); wr_pxp = wr_view.get(0, 0, width, height); walker.walk(0); - assert(*rd_pxp != space_fill); - + scanner.new_scan(); /* flush scan */ wr_view.sync(); - scanner << 0 << 0 << 0; /* flush scan FIXME? */ + + // display result data + if(data_cnt) + cout << data_max << endl; if(display) { #if (MagickLibVersion >= 0x632) From 22dd15af0efc37df434a9a40e0330533f883f26c Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 19 May 2007 15:47:17 +0000 Subject: [PATCH 020/328] =?UTF-8?q?=20=20*=20Debian=20package=20patch=20fo?= =?UTF-8?q?r=200.2=20-=20thanks=20to=20V=C3=ADt=20Hrachov=C3=BD:=20=20=20?= =?UTF-8?q?=20=20-=20add=20libsdl1.2-dev=20as=20a=20build=20dependency=20?= =?UTF-8?q?=20=20=20=20-=20update=20automake=20(>=3D=201:1.10)=20as=20a=20?= =?UTF-8?q?build=20dependency=20=20=20=20=20-=20new=20package?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ChangeLog | 6 ++++++ debian/changelog | 7 +++++++ debian/control | 2 +- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index c5a787f..17b75c7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +current: + * Debian package patch for 0.2 - thanks to Vít Hrachový: + - add libsdl1.2-dev as a build dependency + - update automake (>= 1:1.10) as a build dependency + - new package + version 0.2: * update distribution to include debian packaging * add consistency checking to zebracam diff --git a/debian/changelog b/debian/changelog index 43c7d99..81cd8a1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +libzebra (0.2-1) unstable; urgency=low + + * Added libsdl dependency + * automake1.10 is now required + + -- Vít Hrachový Thu, 17 May 2007 9:20:45 +0200 + libzebra (0.1-1) unstable; urgency=low * Initial release diff --git a/debian/control b/debian/control index b3cf435..d76697d 100644 --- a/debian/control +++ b/debian/control @@ -1,7 +1,7 @@ Source: libzebra Priority: optional Maintainer: Vít Hrachový -Build-Depends: debhelper (>= 5), autotools-dev, libmagick++9-dev, autoconf (>= 2.61), automake1.9 (>= 1.9), libtool (>= 1.5.22), xmlto (>= 0.0.18) +Build-Depends: debhelper (>= 5), autotools-dev, libmagick++9-dev, autoconf (>= 2.61), automake (>= 1:1.10), libtool (>= 1.5.22), xmlto (>= 0.0.18), libsdl1.2-dev Standards-Version: 3.7.2 Section: libs From 5ca570b5bcd497677f141a409e0ad3f067d3e422 Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 9 Jun 2007 23:35:58 +0000 Subject: [PATCH 021/328] =?UTF-8?q?=20=20*=20integrate=20RPM=20packaging?= =?UTF-8?q?=20spec=20file=20-=20thanks=20to=20V=C3=ADt=20Hrachov=C3=BD=20f?= =?UTF-8?q?or=20the=20draft!=20=20=20=20=20(patch=20#1723536)=20=20=20*=20?= =?UTF-8?q?finally=20add=20HACKING=20to=20distribution/install=20(bug=20#1?= =?UTF-8?q?698202)=20=20=20*=20add=20extra=20documentation=20files=20to=20?= =?UTF-8?q?install=20(README=20NEWS=20INSTALL,=20etc)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ChangeLog | 4 +++ Makefile.am | 5 +++- TODO | 1 + configure.ac | 2 +- zebra.spec.in | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 zebra.spec.in diff --git a/ChangeLog b/ChangeLog index 17b75c7..8a6cbbd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,8 @@ current: + * integrate RPM packaging spec file - thanks to Vít Hrachový for the draft! + (patch #1723536) + * finally add HACKING to distribution/install (bug #1698202) + * add extra documentation files to install (README NEWS INSTALL, etc) * Debian package patch for 0.2 - thanks to Vít Hrachový: - add libsdl1.2-dev as a build dependency - update automake (>= 1:1.10) as a build dependency diff --git a/Makefile.am b/Makefile.am index 6f5f805..bf71528 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,6 +5,8 @@ bin_PROGRAMS = check_PROGRAMS = CLEANFILES = +dist_doc_DATA = COPYING.LIB HACKING INSTALL NEWS README TODO + include $(srcdir)/include/Makefile.am.inc include $(srcdir)/zebra/Makefile.am.inc if HAVE_MAGICK @@ -16,6 +18,7 @@ endif include $(srcdir)/test/Makefile.am.inc include $(srcdir)/doc/Makefile.am.inc -EXTRA_DIST += debian/changelog debian/compat debian/control debian/copyright \ +EXTRA_DIST += zebra.spec.in zebra.spec \ + debian/changelog debian/compat debian/control debian/copyright \ debian/docs debian/libzebra0.install debian/libzebra-dev.install \ debian/rules debian/shlibs.local debian/zebra-tools.install diff --git a/TODO b/TODO index 4e9917e..4b3986e 100644 --- a/TODO +++ b/TODO @@ -13,3 +13,4 @@ * add library version query interface * profile and weed out obvious oversights * documentation + * hook up doxygen or robodoc for API docs diff --git a/configure.ac b/configure.ac index 5d224b9..ab1f9dc 100644 --- a/configure.ac +++ b/configure.ac @@ -125,7 +125,7 @@ AC_CONFIG_COMMANDS([doc/reldate.xml], [RELDATE=$RELDATE] ) -AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([Makefile zebra.spec]) AC_OUTPUT echo "" diff --git a/zebra.spec.in b/zebra.spec.in new file mode 100644 index 0000000..629b56c --- /dev/null +++ b/zebra.spec.in @@ -0,0 +1,83 @@ +Name: zebra +Summary: Scan and decode barcodes using a video device or from image files +Version: @VERSION@ +Release: 1 +License: LGPL +Group: Applications/Multimedia +URL: http://zebra.sourceforge.net +Packager: Vit Hrachovy +Source: zebra-%{version}.tar.gz +Requires: ImageMagick-c++, SDL +BuildPreReq: ImageMagick-c++-devel, SDL-devel +Prefix: %{_prefix} +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root + +%description +Zebra is a layered barcode (EAN/UPC/Code 128) scanning and decoding +library. Includes applications for decoding captured barcode images +and using a video device (eg, webcam) as a barcode scanner. Features +a fast streaming interface with minimal memory footprint. + +%package devel +Group: Development/Libraries +Summary: Header files and static libraries for Zebra bar code reading library. +Requires: %{name} = %{version} + +%description devel +This package installs files neccessary for development of bar code +applications using Zebra barcode reader library. + +%prep +%setup -q -n zebra-%{version} + +%build +./configure --host=%{_host} --build=%{_build} \ + CFLAGS="${CFLAGS:-%optflags}" \ + CXXFLAGS="${CXXFLAGS:-%optflags}" \ + --prefix=$RPM_BUILD_ROOT/%{_prefix} \ + --docdir=$RPM_BUILD_ROOT/%{_docdir}/%{name}-%{version} +make + +%install +rm -rf $RPM_BUILD_ROOT +make install + +%clean +rm -rf $RPM_BUILD_ROOT + +%post +ldconfig + +%postun +ldconfig + +%files +%defattr(-,root,root) +%doc %{_docdir}/%{name}-%{version}/COPYING.LIB +%doc %{_docdir}/%{name}-%{version}/HACKING +%doc %{_docdir}/%{name}-%{version}/INSTALL +%doc %{_docdir}/%{name}-%{version}/NEWS +%doc %{_docdir}/%{name}-%{version}/README +%doc %{_docdir}/%{name}-%{version}/TODO +%{_datadir}/man/man1/* +%{_libdir}/libzebra.so.0.2.0 +%{_libdir}/libzebra.so.0 +%{_libdir}/libzebra.so +%{_bindir}/zebraimg +%{_bindir}/zebracam + +%files devel +%defattr(-,root,root) +%{_libdir}/libzebra.la +%{_libdir}/libzebra.a +%{_includedir}/zebra.h +%{_includedir}/zebra/Scanner.h +%{_includedir}/zebra/Decoder.h +%{_includedir}/zebra/ImageWalker.h + +%changelog +* Fri Jun 08 2007 spadix +- first release + +* Tue May 22 2007 Vít Hrachový +- Initial draft From 1e8bce3ffb23d1d10dcef06af919d28ae6ae7043 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 12 Jul 2007 04:15:53 +0000 Subject: [PATCH 022/328] * flush zebracam output after each scanned symbol --- ChangeLog | 1 + TODO | 3 ++- zebracam/zebracam.c | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 8a6cbbd..7e7146d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * flush zebracam output after each scanned symbol * integrate RPM packaging spec file - thanks to Vít Hrachový for the draft! (patch #1723536) * finally add HACKING to distribution/install (bug #1698202) diff --git a/TODO b/TODO index 4b3986e..0b376c3 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,5 @@ - * rpm packaging * handle Code 128 function characters (FNC1-4) + * integrated high-level image API * decoder needs symbology/feature enable/disable * better C++ interface to img_walker * nice to match STL iterator interface @@ -7,6 +7,7 @@ * img_walker skip uselessly short scan lines * img_walker pattern selection * higher img_walker pattern density (cfg even better) + * zebracam support for v4l2 API * support for other v4l image formats * decode hook (program/script) to zebracam/(zebraimg?) * finish UPC-E, EAN-8 and addon decoding diff --git a/zebracam/zebracam.c b/zebracam/zebracam.c index 02691be..297561e 100644 --- a/zebracam/zebracam.c +++ b/zebracam/zebracam.c @@ -326,6 +326,7 @@ static void symbol_handler (zebra_decoder_t *decoder) zebra_get_symbol_name(sym), zebra_get_addon_name(sym), zebra_decoder_get_data(decoder)); + fflush(stdout); beep_time = ms; SDL_PauseAudio(0); } From f1b6cb453bac9af92f37c7a04bed0bc4510741b5 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 12 Jul 2007 18:28:29 +0000 Subject: [PATCH 023/328] * add configure check for ImageMagick version >= 6.3.0 * configure dumps ImageMagick, SDL and firefox versions for debug * add NPAPI plugin stub and build infrastructure --- ChangeLog | 3 ++ Makefile.am | 4 +++ configure.ac | 74 ++++++++++++++++++++++++++++++++++++++++-- plugin/Makefile.am.inc | 5 +++ plugin/plugin.c | 25 ++++++++++++++ zebra/Makefile.am.inc | 2 +- zebra/decoder.c | 2 +- 7 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 plugin/Makefile.am.inc create mode 100644 plugin/plugin.c diff --git a/ChangeLog b/ChangeLog index 7e7146d..c86296f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,7 @@ current: + * add configure check for ImageMagick version >= 6.3.0 + * configure dumps ImageMagick, SDL and firefox versions for debug + * add NPAPI plugin stub and build infrastructure * flush zebracam output after each scanned symbol * integrate RPM packaging spec file - thanks to Vít Hrachový for the draft! (patch #1723536) diff --git a/Makefile.am b/Makefile.am index bf71528..5d6d09f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,6 +3,7 @@ AM_CFLAGS = -Wall -Werror AM_CXXFLAGS = $(AM_CFLAGS) bin_PROGRAMS = check_PROGRAMS = +lib_LTLIBRARIES = CLEANFILES = dist_doc_DATA = COPYING.LIB HACKING INSTALL NEWS README TODO @@ -15,6 +16,9 @@ endif if HAVE_SDL include $(srcdir)/zebracam/Makefile.am.inc endif +if HAVE_MOZILLA +include $(srcdir)/plugin/Makefile.am.inc +endif include $(srcdir)/test/Makefile.am.inc include $(srcdir)/doc/Makefile.am.inc diff --git a/configure.ac b/configure.ac index ab1f9dc..500e171 100644 --- a/configure.ac +++ b/configure.ac @@ -29,6 +29,9 @@ documentation generation]) AC_ARG_VAR([XMLTOFLAGS], [additional arguments for xmlto]) AC_CHECK_TOOL([XMLTO], [xmlto], [:]) +AC_ARG_VAR([PKG_CONFIG], [full path to pkg-config utility]) +AC_CHECK_TOOL([PKG_CONFIG], [pkg-config], [:]) + AC_ARG_WITH([imagemagick], [AS_HELP_STRING([--without-imagemagick], [disable support for scanning images using ImageMagick])], @@ -51,20 +54,31 @@ to skip building programs that use ImageMagick.])], install imagemagick or configure --without-imagemagick to skip building programs that use ImageMagick.])] )]) + +AS_IF([test "x$with_imagemagick" != "xno"], + [AC_MSG_CHECKING([ImageMagick version]) + MAGICK_VERSION=`$MAGICKXX_CONFIG --version` + AC_MSG_RESULT([$MAGICK_VERSION]) + AS_CASE([$MAGICK_VERSION], + [[[0-5].* | 6.[0-2].*]], + [AC_MSG_FAILURE([test for ImageMagick version >= 6.3.0 failed! +upgrade ImageMagick or configure --without-imagemagick +to skip building programs that use ImageMagick.])]) +]) + AM_CONDITIONAL([HAVE_MAGICK], [test "x$MAGICKXX_CONFIG" != "x:"]) AC_SUBST([MAGICK_CPPFLAGS], [`$MAGICKXX_CONFIG --cppflags`]) AC_SUBST([MAGICK_CXXFLAGS], [`$MAGICKXX_CONFIG --cxxflags`]) AC_SUBST([MAGICK_LDFLAGS], [`$MAGICKXX_CONFIG --ldflags`]) AC_SUBST([MAGICK_LIBS], [`$MAGICKXX_CONFIG --libs`]) - AC_ARG_ENABLE([video], [AS_HELP_STRING([--disable-video], [exclude video scanner application])], [], [enable_video=yes]) -AC_CHECK_HEADER([linux/videodev.h], +AC_CHECK_HEADERS([linux/videodev.h], [], [AS_IF([test "x$enable_video" != "xno"], [AC_MSG_FAILURE([test for video support failed! @@ -72,6 +86,16 @@ rebuild your kernel to include video4linux support or configure --disable-video to skip building programs that use video.])] )]) +AS_IF([test "x$enable_video" != "xno"], + [AC_CHECK_HEADERS([linux/videodev2.h], + [], + [AC_MSG_WARN([v4l2 API not detected, upgrade your kernel!])], + [[#include +#include +#ifdef HAVE_VIDEODEV_H +# include +#endif +]])]) AC_ARG_WITH([sdl], [AS_HELP_STRING([--without-sdl], @@ -89,10 +113,51 @@ AS_IF([test "x$enable_video" = "xno"], install SDL or configure --without-sdl to skip building programs that use SDL])] ) + +AS_IF([test "x$with_sdl" != "xno"], + [AC_MSG_CHECKING([SDL version]) + SDL_VERSION=`$SDL_CONFIG --version` + AC_MSG_RESULT([$SDL_VERSION]) +]) + AM_CONDITIONAL([HAVE_SDL], [test "x$SDL_CONFIG" != "x:"]) AC_SUBST([SDL_CPPFLAGS], [`$SDL_CONFIG --cflags`]) AC_SUBST([SDL_LIBS], [`$SDL_CONFIG --libs`]) +AC_ARG_WITH([mozilla], + [AS_HELP_STRING([--without-mozilla], + [disable support for Firefox/Mozilla/OpenOffice NPAPI plugin])], + [], + [with_mozilla=yes]) + +AC_ARG_VAR([MOZILLA_CFLAGS], + [C compiler flags for Firefox/Mozilla plugin (overrides pkg-config)]) +AS_IF([test "x$MOZILLA_CFLAGS" = "x"], + [MOZILLA_CFLAGS=`$PKG_CONFIG --cflags firefox-plugin`]) + +AC_ARG_VAR([MOZILLA_LIBS], + [linker flags for Firefox/Mozilla plugin (overrides pkg-config)]) +AS_IF([test "x$MOZILLA_LIBS" = "x"], + [MOZILLA_LIBS=`$PKG_CONFIG --libs firefox-plugin`]) + +AS_IF([test "x$with_mozilla" = "xno"], + [], + [test "x$MOZILLA_CFLAGS" = "x" || \ + test "x$MOZILLA_LIBS" = "x"], + [AC_MSG_FAILURE([test for Firefox/Mozilla plugin (NPAPI) interface failed! + - install pkg-config and Firefox + - *or* install Firefox or the Mozilla SDK and manually specify + MOZILLA_CFLAGS and MOZILLA_LIBS + - *or* configure --without-mozilla to skip building the plugin])] +) +AS_IF([test "x$with_mozilla" != "xno"], + [AC_MSG_CHECKING([Mozilla version]) + MOZILLA_VERSION=`$PKG_CONFIG --modversion firefox-plugin` + AC_MSG_RESULT([$MOZILLA_VERSION]) +]) + +AM_CONDITIONAL([HAVE_MOZILLA], [test "x$with_mozilla" != "xno"]) + AC_PATH_X AC_HEADER_ASSERT @@ -142,3 +207,8 @@ AS_IF([test "x$with_imagemagick" != "xyes"], [echo " => the zebraimg program will *NOT* be built"], [echo " => zebraimg image file scanner will be built"]) echo "" +echo "Mozilla Plugin --with-mozilla=$with_mozilla" +AS_IF([test "x$with_mozilla" != "xyes"], + [echo " => the Mozilla/Firefox/OpenOffice plugin will *NOT* be built"], + [echo " => the Mozilla/Firefox/OpenOffice plugin will be built"]) +echo "" diff --git a/plugin/Makefile.am.inc b/plugin/Makefile.am.inc new file mode 100644 index 0000000..763af24 --- /dev/null +++ b/plugin/Makefile.am.inc @@ -0,0 +1,5 @@ +lib_LTLIBRARIES += plugin/libzebraplugin.la +plugin_libzebraplugin_la_SOURCES = \ + plugin/plugin.c +plugin_libzebraplugin_la_CPPFLAGS = $(MOZILLA_CFLAGS) $(AM_CPPFLAGS) +plugin_libzebraplugin_la_LDFLAGS = $(MOZILLA_LIBS) $(AM_LDFLAGS) diff --git a/plugin/plugin.c b/plugin/plugin.c new file mode 100644 index 0000000..2559714 --- /dev/null +++ b/plugin/plugin.c @@ -0,0 +1,25 @@ +/*------------------------------------------------------------------------ + * Copyright 2007 (c) Jeff Brown + * + * This file is part of the Zebra Barcode Library. + * + * The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zebra + *------------------------------------------------------------------------*/ + +#include + diff --git a/zebra/Makefile.am.inc b/zebra/Makefile.am.inc index ba8bda4..07da3e3 100644 --- a/zebra/Makefile.am.inc +++ b/zebra/Makefile.am.inc @@ -1,4 +1,4 @@ -lib_LTLIBRARIES = zebra/libzebra.la +lib_LTLIBRARIES += zebra/libzebra.la zebra_libzebra_la_SOURCES = \ zebra/img_walker.c zebra/scanner.c \ zebra/decoder.h zebra/decoder.c \ diff --git a/zebra/decoder.c b/zebra/decoder.c index dceed46..f3fdd15 100644 --- a/zebra/decoder.c +++ b/zebra/decoder.c @@ -130,7 +130,7 @@ zebra_symbol_type_t zebra_decode_width (zebra_decoder_t *dcode, unsigned w) { dcode->w[dcode->idx & 7] = w; - dprintf(" decode[%x]: w=%d\n", dcode->idx, w); + dprintf(" decode[%x]: w=%d (%g)\n", dcode->idx, w, (w / 32.)); /* each decoder processes width stream in parallel */ zebra_symbol_type_t sym = dcode->type = ZEBRA_NONE; From 75dfe1e64da46a2e7193e0b821488f5445b4d5de Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 14 Jul 2007 21:11:06 +0000 Subject: [PATCH 024/328] * add integrated 2D image scanning API - automatically ties to internal scanner and decoder - results reported via new symbol API - deprecated previous, cumbersome img_walker interface - uses new simpler/faster and denser grid pattern (FIXME add 45 and 135) - first step toward more sophisticated image processing * updated zebraimg to use new ImageScanner API - add initial decode location tracking * updated zebracam to use new img_scanner API - extended cache to track multiple symbols per-image - add initial decode location tracking - removed scan grid overlay --- ChangeLog | 12 ++ include/Makefile.am.inc | 1 + include/zebra.h | 126 ++++++++++++++--- include/zebra/Decoder.h | 11 +- include/zebra/ImageScanner.h | 96 +++++++++++++ include/zebra/Symbol.h | 90 ++++++++++++ zebra/Makefile.am.inc | 3 +- zebra/img_scanner.c | 265 +++++++++++++++++++++++++++++++++++ zebra/symbol.c | 66 +++++++++ zebra/symbol.h | 42 ++++++ zebracam/zebracam.c | 214 +++++++++++++++++++--------- zebraimg/zebraimg.cpp | 200 ++++++++++++++------------ 12 files changed, 947 insertions(+), 179 deletions(-) create mode 100644 include/zebra/ImageScanner.h create mode 100644 include/zebra/Symbol.h create mode 100644 zebra/img_scanner.c create mode 100644 zebra/symbol.c create mode 100644 zebra/symbol.h diff --git a/ChangeLog b/ChangeLog index c86296f..4e9ce74 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,16 @@ current: + * add integrated 2D image scanning API + - automatically ties to internal scanner and decoder + - results reported via new symbol API + - deprecated previous, cumbersome img_walker interface + - uses new simpler/faster and denser grid pattern (FIXME add 45 and 135) + - first step toward more sophisticated image processing + * updated zebraimg to use new ImageScanner API + - add initial decode location tracking + * updated zebracam to use new img_scanner API + - extended cache to track multiple symbols per-image + - add initial decode location tracking + - removed scan grid overlay * add configure check for ImageMagick version >= 6.3.0 * configure dumps ImageMagick, SDL and firefox versions for debug * add NPAPI plugin stub and build infrastructure diff --git a/include/Makefile.am.inc b/include/Makefile.am.inc index 005ce17..848eccb 100644 --- a/include/Makefile.am.inc +++ b/include/Makefile.am.inc @@ -1,4 +1,5 @@ zincludedir = $(includedir)/zebra include_HEADERS = include/zebra.h zinclude_HEADERS = include/zebra/Scanner.h include/zebra/Decoder.h \ + include/zebra/Symbol.h include/zebra/ImageScanner.h \ include/zebra/ImageWalker.h diff --git a/include/zebra.h b/include/zebra.h index f0d80b3..fd42c8d 100644 --- a/include/zebra.h +++ b/include/zebra.h @@ -58,7 +58,43 @@ extern const char *zebra_get_addon_name(zebra_symbol_type_t sym); /*------------------------------------------------------------*/ -/* high-level bar width stream decoder interface +/* decoded barcode symbol result object. + * stores type, data, and location of decoded symbol. + * all memory is owned by the library + */ + +/* opaque decoded symbol object */ +struct zebra_symbol_s; +typedef struct zebra_symbol_s zebra_symbol_t; + +/* return type of decoded symbol */ +extern zebra_symbol_type_t zebra_symbol_get_type(zebra_symbol_t *symbol); + +/* return ASCII data decoded from symbol */ +extern const char *zebra_symbol_get_data(zebra_symbol_t *symbol); + +/* return the number of points in the location polygon, + * which defines the image area that the symbol was extracted from + */ +extern unsigned char zebra_symbol_get_loc_size(zebra_symbol_t *symbol); + +/* return the x-coordinate for a point in the location polygon. + * points are specified by 0-based index. + * returns -1 if index is out of range + */ +extern int zebra_symbol_get_loc_x(zebra_symbol_t *symbol, + unsigned char index); + +/* return the y-coordinate for a point in the location polygon. + * points are specified by 0-based index. + * returns -1 if index is out of range + */ +extern int zebra_symbol_get_loc_y(zebra_symbol_t *symbol, + unsigned char index); + + +/*------------------------------------------------------------*/ +/* high-level bar width stream decoder interface. * identifies symbols and extracts encoded data */ @@ -100,7 +136,7 @@ extern zebra_symbol_type_t zebra_decode_width(zebra_decoder_t *decoder, /* return color of *next* element passed to zebra_decode_width() */ extern zebra_color_t zebra_decoder_get_color(const zebra_decoder_t *decoder); -/* returns last decoded data, +/* returns last decoded data in ASCII format, * or NULL if no new data available. * data buffer is maintained by library, * contents are only valid between non-0 return from zebra_decode_width @@ -133,7 +169,7 @@ extern void *zebra_decoder_get_userdata(const zebra_decoder_t *decoder); /*------------------------------------------------------------*/ -/* low-level intensity sample stream scanner interface +/* low-level intensity sample stream scanner interface. * identifies "bar" edges and measures width between them * optionally passes to bar width decoder */ @@ -187,16 +223,72 @@ extern zebra_color_t zebra_scanner_get_color(const zebra_scanner_t *scanner); /*------------------------------------------------------------*/ -/* 2-D image walker interface +/* integrated 2-D image scanner interface. + * extracts symbols from image data buffers + * using configured image parameters + */ + +/* opaque scanner object */ +struct zebra_img_scanner_s; +typedef struct zebra_img_scanner_s zebra_img_scanner_t; + +/* constructor + * create a new image scanner instance. image parameters + * must be initialized before images can be scanned + */ +extern zebra_img_scanner_t *zebra_img_scanner_create(); + +/* destructor */ +extern void zebra_img_scanner_destroy(zebra_img_scanner_t *scanner); + +/* associate user specified data value with the image scanner */ +extern void zebra_img_scanner_set_userdata(zebra_img_scanner_t *scanner, + void *userdata); + +/* return user specified data value associated with the image scanner */ +extern void* +zebra_img_scanner_get_userdata(const zebra_img_scanner_t *scanner); + +/* set the size of the next image(s) to scan. + * width is specified as number of columns and height as number of rows + */ +extern void zebra_img_scanner_set_size(zebra_img_scanner_t *scanner, + unsigned width, + unsigned height); + +/* scan for symbols in specified image. + * the image must be in packed 8bpp grayscale format. + * returns the number of symbols successfully decoded from the image + * or -1 if an error occurs + */ +extern int zebra_img_scan_y(zebra_img_scanner_t *scanner, + const void *image); + +/* return number of symbols in the current result set + * (from last scanned image) + */ +extern unsigned char +zebra_img_scanner_get_result_size(const zebra_img_scanner_t *scanner); + +/* return a symbol from the result set, specified by 0-based index. + * returns NULL if index is out of range + */ +extern zebra_symbol_t* +zebra_img_scanner_get_result(const zebra_img_scanner_t *scanner, + unsigned char index); + + +/*------------------------------------------------------------*/ +/* *DEPRECATED* 2-D image walker interface * walks a default scan pattern over image data buffers * using configured image parameters */ -/* opaque walker object */ +/* *DEPRECATED* opaque walker object */ struct zebra_img_walker_s; typedef struct zebra_img_walker_s zebra_img_walker_t; -/* pixel handler callback function. +/* *DEPRECATED* pixel handler callback function. * called by image walker for each pixel of the walk. * any non-zero return value will terminate the walk * with the returned value. @@ -204,27 +296,27 @@ typedef struct zebra_img_walker_s zebra_img_walker_t; typedef char (zebra_img_walker_handler_t)(zebra_img_walker_t *walker, void *pixel); -/* constructor +/* *DEPRECATED* constructor * create a new image walker instance. image parameters * must be initialized before a walk can be started */ extern zebra_img_walker_t *zebra_img_walker_create(); -/* destructor */ +/* *DEPRECATED* destructor */ extern void zebra_img_walker_destroy(zebra_img_walker_t *walker); -/* set the pixel handler */ +/* *DEPRECATED* set the pixel handler */ extern void zebra_img_walker_set_handler(zebra_img_walker_t *walker, zebra_img_walker_handler_t *handler); -/* associate user specified data value with the walker */ +/* *DEPRECATED* associate user specified data value with the walker */ extern void zebra_img_walker_set_userdata(zebra_img_walker_t *walker, void *userdata); -/* return user specified data value associated with the decoder */ +/* *DEPRECATED* return user specified data value associated with the walker */ extern void *zebra_img_walker_get_userdata(zebra_img_walker_t *walker); -/* set the width of the image in columns, +/* *DEPRECATED* set the width of the image in columns, * and the height of the image in rows */ extern void zebra_img_walker_set_size(zebra_img_walker_t *walker, @@ -232,7 +324,7 @@ extern void zebra_img_walker_set_size(zebra_img_walker_t *walker, unsigned height); -/* (optional) set column and row sizes. +/* *DEPRECATED* (optional) set column and row sizes. * bytes_per_col is the number of bytes in each column * of the image buffer (eg, often 1 for YUV format * and 3 for packed RGB). defaults to 1 if unspecified. @@ -244,7 +336,7 @@ extern void zebra_img_walker_set_stride(zebra_img_walker_t *walker, unsigned bytes_per_col, unsigned bytes_per_row); -/* start walking over specified new image +/* *DEPRECATED* start walking over specified new image * returns the first non-zero value returned by the handler, * 0 when walk completes or -1 if walk cannot start * (usually because some image parameter is in error). @@ -254,10 +346,10 @@ extern void zebra_img_walker_set_stride(zebra_img_walker_t *walker, extern char zebra_img_walk(zebra_img_walker_t *walker, const void *image); -/* return current column location of walker */ +/* *DEPRECATED* return current column location of walker */ extern unsigned zebra_img_walker_get_col(zebra_img_walker_t *walker); -/* return current row location of walker */ +/* *DEPRECATED* return current row location of walker */ extern unsigned zebra_img_walker_get_row(zebra_img_walker_t *walker); @@ -267,7 +359,9 @@ extern unsigned zebra_img_walker_get_row(zebra_img_walker_t *walker); # include "zebra/Decoder.h" # include "zebra/Scanner.h" +# include "zebra/Symbol.h" # include "zebra/ImageWalker.h" +# include "zebra/ImageScanner.h" #endif #endif diff --git a/include/zebra/Decoder.h b/include/zebra/Decoder.h index dfb25d5..eef418d 100644 --- a/include/zebra/Decoder.h +++ b/include/zebra/Decoder.h @@ -96,10 +96,14 @@ class Decoder { return(zebra_decoder_get_data(_decoder)); } - const std::string& get_data_string() const + const std::string get_data_string() const { - ((Decoder*)this)->_data = zebra_decoder_get_data(_decoder); - return(_data); + return(zebra_decoder_get_data(_decoder)); + } + + const std::string get_data() const + { + return(zebra_decoder_get_data(_decoder)); } void set_handler (Handler &handler) @@ -112,7 +116,6 @@ class Decoder { private: friend class Scanner; zebra_decoder_t *_decoder; - std::string _data; Handler *_handler; static void _cb (zebra_decoder_t *cdcode) diff --git a/include/zebra/ImageScanner.h b/include/zebra/ImageScanner.h new file mode 100644 index 0000000..75b6fe8 --- /dev/null +++ b/include/zebra/ImageScanner.h @@ -0,0 +1,96 @@ +//------------------------------------------------------------------------ +// Copyright 2007 (c) Jeff Brown +// +// This file is part of the Zebra Barcode Library. +// +// The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free +// Software Foundation, Inc., 51 Franklin St, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// http://sourceforge.net/projects/zebra +//------------------------------------------------------------------------ +#ifndef _ZEBRA_IMAGE_SCANNER_H_ +#define _ZEBRA_IMAGE_SCANNER_H_ + +#ifndef _ZEBRA_H_ +# error "include zebra.h in your application, **not** zebra/ImageScanner.h" +#endif + +#include "Symbol.h" + +namespace zebra { + +class ImageScanner { + public: + class RangeException : public std::exception { + virtual const char* what () const throw() + { + return("index out of range"); + } + }; + + ImageScanner () + { + _scanner = zebra_img_scanner_create(); + } + + ImageScanner (unsigned width, unsigned height) + { + _scanner = zebra_img_scanner_create(); + set_size(width, height); + } + + ~ImageScanner () + { + zebra_img_scanner_destroy(_scanner); + } + + void set_size (unsigned width, unsigned height) + { + zebra_img_scanner_set_size(_scanner, width, height); + } + + int scan_y (const void *image) + { + return(zebra_img_scan_y(_scanner, image)); + } + + int get_result_size () + { + return(zebra_img_scanner_get_result_size(_scanner)); + } + + Symbol get_result (unsigned index) + { + zebra_symbol_t *sym = zebra_img_scanner_get_result(_scanner, index); + if(sym) + return(Symbol(sym)); + throw RangeException(); + } + + template + OutputIterator result_iter (OutputIterator out) + { + for(int i = get_result_size(); i; i--) + *out++ = get_result(i); + return(out); + } + + private: + zebra_img_scanner_t *_scanner; +}; + +} + +#endif diff --git a/include/zebra/Symbol.h b/include/zebra/Symbol.h new file mode 100644 index 0000000..1e384eb --- /dev/null +++ b/include/zebra/Symbol.h @@ -0,0 +1,90 @@ +//------------------------------------------------------------------------ +// Copyright 2007 (c) Jeff Brown +// +// This file is part of the Zebra Barcode Library. +// +// The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free +// Software Foundation, Inc., 51 Franklin St, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// http://sourceforge.net/projects/zebra +//------------------------------------------------------------------------ +#ifndef _ZEBRA_SYMBOL_H_ +#define _ZEBRA_SYMBOL_H_ + +#ifndef _ZEBRA_H_ +# error "include zebra.h in your application, **not** zebra/Symbol.h" +#endif + +#include + +namespace zebra { + +class Symbol { + public: + Symbol (zebra_symbol_t *sym) + : _sym(sym), + _type(zebra_symbol_get_type(sym)), + _data(zebra_symbol_get_data(sym)) + { + } + + ~Symbol () + { + } + + zebra_symbol_type_t get_type () const + { + return(_type); + } + + const std::string get_type_name () const + { + return(zebra_get_symbol_name(_type)); + } + + const std::string get_addon_name () const + { + return(zebra_get_addon_name(_type)); + } + + const std::string get_data () const + { + return(_data); + } + + int get_location_size () const + { + return(zebra_symbol_get_loc_size(_sym)); + } + + int get_location_x (unsigned index) const + { + return(zebra_symbol_get_loc_x(_sym, index)); + } + + int get_location_y (unsigned index) const + { + return(zebra_symbol_get_loc_y(_sym, index)); + } + + private: + zebra_symbol_t *_sym; + zebra_symbol_type_t _type; + std::string _data; +}; + +} + +#endif diff --git a/zebra/Makefile.am.inc b/zebra/Makefile.am.inc index 07da3e3..7d09ea9 100644 --- a/zebra/Makefile.am.inc +++ b/zebra/Makefile.am.inc @@ -1,6 +1,7 @@ lib_LTLIBRARIES += zebra/libzebra.la zebra_libzebra_la_SOURCES = \ - zebra/img_walker.c zebra/scanner.c \ + zebra/symbol.h zebra/symbol.c \ + zebra/img_scanner.c zebra/img_walker.c zebra/scanner.c \ zebra/decoder.h zebra/decoder.c \ zebra/ean.h zebra/ean.c \ zebra/code128.h zebra/code128.c diff --git a/zebra/img_scanner.c b/zebra/img_scanner.c new file mode 100644 index 0000000..ddaf0b9 --- /dev/null +++ b/zebra/img_scanner.c @@ -0,0 +1,265 @@ +/*------------------------------------------------------------------------ + * Copyright 2007 (c) Jeff Brown + * + * This file is part of the Zebra Barcode Library. + * + * The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zebra + *------------------------------------------------------------------------*/ + +#include +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef DEBUG_IMG_SCANNER +# include /* fprintf */ +#endif +#include /* malloc, free */ +#include /* strlen, strcmp, memset, memcpy */ +#include + +#include "zebra.h" +#include "symbol.h" + +#ifdef DEBUG_IMG_SCANNER +# define dprintf(...) \ + fprintf(stderr, __VA_ARGS__) +# define ASSERT_POS \ + assert(iscn->p == img + iscn->x + iscn->y * iscn->w); +#else +# define dprintf(...) +#define ASSERT_POS +#endif + +/* image scanner state */ +struct zebra_img_scanner_s { + zebra_scanner_t *scn; /* associated linear intensity scanner */ + zebra_decoder_t *dcode; /* associated symbol decoder */ + + unsigned w, h; /* configured width and height */ + void *userdata; /* application data */ + + int x, y; /* current image location */ + const unsigned char *p; + + int nsyms; /* current syms entries */ + unsigned symslen; /* allocated size of syms */ + zebra_symbol_t *syms; /* decoded symbol data */ +}; + +static void symbol_handler (zebra_decoder_t *dcode) +{ + zebra_img_scanner_t *iscn = zebra_decoder_get_userdata(dcode); + assert(iscn->dcode == dcode); + + zebra_symbol_type_t type = zebra_decoder_get_type(dcode); + /* FIXME assert(type == ZEBRA_PARTIAL) */ + /* FIXME debug flag to save/display all PARTIALs */ + if(type <= ZEBRA_PARTIAL) + return; + + /* FIXME check if (x, y) is inside existing polygon */ + + zebra_symbol_t *sym = &iscn->syms[iscn->nsyms]; + sym->npts = 0; + /* FIXME extract bars from image and decode */ + + if(++sym->npts >= sym->ptslen) + sym->pts = realloc(sym->pts, ++sym->ptslen * sizeof(point_t)); + sym->pts[0].x = iscn->x; + sym->pts[0].y = iscn->y; + + const char *data = zebra_decoder_get_data(dcode); + int i; + for(i = 0; i < iscn->nsyms; i++) { + zebra_symbol_t *isym = &iscn->syms[i]; + if(isym->type == type && + !strcmp(isym->data, data)) { + isym->refcnt++; + return; + } + } + + /* save new symbol */ + int datalen = strlen(data) + 1; + if(sym->datalen < datalen) { + if(sym->data) + free(sym->data); + sym->data = malloc(datalen); + sym->datalen = datalen; + } + sym->type = type; + memcpy(sym->data, data, datalen); + sym->refcnt = 1; + + if(++iscn->nsyms >= iscn->symslen) { + iscn->symslen++; + assert(iscn->nsyms < iscn->symslen); + iscn->syms = realloc(iscn->syms, + iscn->symslen * sizeof(zebra_symbol_t)); + sym = &iscn->syms[iscn->nsyms]; + memset(sym, 0, sizeof(zebra_symbol_t)); + } +} + +zebra_img_scanner_t *zebra_img_scanner_create () +{ + zebra_img_scanner_t *iscn = calloc(1, sizeof(zebra_img_scanner_t)); + assert(iscn); + iscn->dcode = zebra_decoder_create(); + zebra_decoder_set_userdata(iscn->dcode, iscn); + zebra_decoder_set_handler(iscn->dcode, symbol_handler); + iscn->scn = zebra_scanner_create(iscn->dcode); + iscn->symslen = 1; + iscn->syms = calloc(1, sizeof(zebra_symbol_t)); + return(iscn); +} + +void zebra_img_scanner_destroy (zebra_img_scanner_t *iscn) +{ + assert(iscn); + zebra_scanner_destroy(iscn->scn); + zebra_decoder_destroy(iscn->dcode); + free(iscn); +} + +void zebra_img_scanner_set_userdata (zebra_img_scanner_t *iscn, + void *userdata) +{ + assert(iscn); + iscn->userdata = userdata; +} + +void *zebra_img_scanner_get_userdata (const zebra_img_scanner_t *iscn) +{ + assert(iscn); + return(iscn->userdata); +} + +void zebra_img_scanner_set_size (zebra_img_scanner_t *iscn, + unsigned width, + unsigned height) +{ + assert(iscn); + iscn->w = width; + iscn->h = height; +} + +unsigned char +zebra_img_scanner_get_result_size (const zebra_img_scanner_t *iscn) +{ + assert(iscn); + return(iscn->nsyms); +} + +zebra_symbol_t* +zebra_img_scanner_get_result (const zebra_img_scanner_t *iscn, + unsigned char idx) +{ + assert(iscn); + if(idx < iscn->nsyms) + return(&iscn->syms[idx]); + else + return(NULL); +} + + +static inline void quiet_border (zebra_img_scanner_t *iscn, + unsigned samples) +{ + unsigned i; + for(i = samples; i; i--) + zebra_scan_y(iscn->scn, 0); + zebra_scanner_new_scan(iscn->scn); +} + +static inline void movedelta (zebra_img_scanner_t *iscn, + int dx, + int dy) +{ + iscn->x += dx; + iscn->y += dy; + iscn->p += dx + dy * iscn->w; +} + +int zebra_img_scan_y (zebra_img_scanner_t *iscn, + const void *img) +{ + int quiet; + if(!iscn || !iscn->w || !iscn->h) + return(-1); + + assert(iscn->symslen); + iscn->nsyms = 0; + + /* FIXME add density config api (calc optimal default) */ + quiet = iscn->w / 32; + if(quiet < 8) + quiet = 8; + + zebra_scanner_new_scan(iscn->scn); + + iscn->x = iscn->y = 0; + iscn->p = img; + for(movedelta(iscn, 0, 8); iscn->y < iscn->h; movedelta(iscn, 1, 16)) { + dprintf("img_x+: %03x,%03x (%p)\n", iscn->x, iscn->y, iscn->p); + for(; iscn->x < iscn->w; movedelta(iscn, 1, 0)) { + ASSERT_POS; + zebra_scan_y(iscn->scn, *iscn->p); + } + quiet_border(iscn, quiet); + + movedelta(iscn, -1, 16); + if(iscn->y >= iscn->h) + break; + + dprintf("img_x-: %03x,%03x (%p)\n", iscn->x, iscn->y, iscn->p); + for(; iscn->x > 0; movedelta(iscn, -1, 0)) { + ASSERT_POS; + zebra_scan_y(iscn->scn, *iscn->p); + } + quiet_border(iscn, quiet); + } + + iscn->x = iscn->y = 0; + iscn->p = img; + for(movedelta(iscn, 8, 0); iscn->x < iscn->w; movedelta(iscn, 16, 1)) { + dprintf("img_y+: %03x,%03x (%p)\n", iscn->x, iscn->y, iscn->p); + for(; iscn->y < iscn->h; movedelta(iscn, 0, 1)) { + ASSERT_POS; + zebra_scan_y(iscn->scn, *iscn->p); + } + quiet_border(iscn, quiet); + + movedelta(iscn, 16, -1); + if(iscn->x >= iscn->w) + break; + + dprintf("img_y-: %03x,%03x (%p)\n", iscn->x, iscn->y, iscn->p); + for(; iscn->y >= 0; movedelta(iscn, 0, -1)) { + ASSERT_POS; + zebra_scan_y(iscn->scn, *iscn->p); + } + quiet_border(iscn, quiet); + } + + /* flush scanner pipe */ + zebra_scanner_new_scan(iscn->scn); + + assert(iscn->nsyms < iscn->symslen); + return(iscn->nsyms); +} diff --git a/zebra/symbol.c b/zebra/symbol.c new file mode 100644 index 0000000..1c0c810 --- /dev/null +++ b/zebra/symbol.c @@ -0,0 +1,66 @@ +/*------------------------------------------------------------------------ + * Copyright 2007 (c) Jeff Brown + * + * This file is part of the Zebra Barcode Library. + * + * The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zebra + *------------------------------------------------------------------------*/ + +#include +#include + +#include +#include "symbol.h" + +zebra_symbol_type_t zebra_symbol_get_type (zebra_symbol_t *sym) +{ + assert(sym); + return(sym->type); +} + +const char *zebra_symbol_get_data (zebra_symbol_t *sym) +{ + assert(sym); + return(sym->data); +} + +unsigned char zebra_symbol_get_loc_size (zebra_symbol_t *sym) +{ + assert(sym); + return(sym->npts); +} + +int zebra_symbol_get_loc_x (zebra_symbol_t *sym, + unsigned char idx) +{ + assert(sym); + if(idx < sym->npts) + return(sym->pts[idx].x); + else + return(-1); +} + +int zebra_symbol_get_loc_y (zebra_symbol_t *sym, + unsigned char idx) +{ + assert(sym); + if(idx < sym->npts) + return(sym->pts[idx].y); + else + return(-1); +} diff --git a/zebra/symbol.h b/zebra/symbol.h new file mode 100644 index 0000000..4294152 --- /dev/null +++ b/zebra/symbol.h @@ -0,0 +1,42 @@ +/*------------------------------------------------------------------------ + * Copyright 2007 (c) Jeff Brown + * + * This file is part of the Zebra Barcode Library. + * + * The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zebra + *------------------------------------------------------------------------*/ +#ifndef _SYMBOL_H_ +#define _SYMBOL_H_ + +#include + +typedef struct point_s { + int x, y; +} point_t; + +struct zebra_symbol_s { + zebra_symbol_type_t type; /* symbol type */ + unsigned int datalen; /* allocation size of data */ + char *data; /* ascii symbol data */ + unsigned ptslen; /* allocation size of pts */ + unsigned npts; /* number of points in location polygon */ + point_t *pts; /* list of points in location polygon */ + unsigned int refcnt; /* tmp heuristic */ +}; + +#endif diff --git a/zebracam/zebracam.c b/zebracam/zebracam.c index 297561e..65f50ff 100644 --- a/zebracam/zebracam.c +++ b/zebracam/zebracam.c @@ -39,12 +39,19 @@ #include +#ifdef DEBUG_ZEBRACAM +# define dprintf(...) \ + fprintf(stderr, __VA_ARGS__) +#else +# define dprintf(...) +#endif + #define DUMP_NAME_MAX 0x20 #define PPM_HDR_MAX 0x20 -#define SYM_MAX 0x200 -#define SYM_HYST 2000 /* ms */ #define UNCERTAINTY 20 /* frames */ #define CERTAINTY 3 /* frames */ +#define SYM_HYST 2000 /* ms */ +#define CACHE_TIMEOUT (SYM_HYST + 2000) /* ms */ static int cam_fd; static struct video_capability vcap; @@ -65,17 +72,30 @@ SDL_AudioSpec audio; static char tone[TONE_MAX]; int tone_period = 20; -zebra_symbol_type_t last_sym_type; -char last_sym_data[SYM_MAX]; -double last_sym_time = 0; -uint64_t last_sym_frame = 0; -uint32_t last_sym_count = 0; - -double beep_time = 0; - -zebra_decoder_t *decoder; -zebra_scanner_t *scanner; -zebra_img_walker_t *walker; +typedef struct symbol_cache_entry_s { + zebra_symbol_type_t type; /* cached symbol type */ + unsigned datalen; /* data allocation */ + char *data; /* cached symbol data */ + double time; /* last cache entry use */ + uint64_t frame; /* cache entry start frame */ + uint32_t count; +} symbol_cache_entry_t; + +int sym_cachelen = 0; +symbol_cache_entry_t *sym_cache = NULL; + +zebra_img_scanner_t *scanner; +void *scan_buf; + +static const char marker[] = { /* +--------------+ */ + 0x08, /* | ** | */ + 0x3e, /* | ********** | */ + 0x2a, /* | ** ** ** | */ + 0x7f, /* |**************| */ + 0x2a, /* | ** ** ** | */ + 0x3e, /* | ********** | */ + 0x08, /* | ** | */ +}; /* +--------------+ */ static void init_cam () { @@ -281,70 +301,139 @@ static inline void dump () dumping = 0; } -static inline void process () +static inline void *convert_gray () { - zebra_scanner_new_scan(scanner); - zebra_img_walk(walker, buf); - zebra_scanner_new_scan(scanner); /* flush scan */ + // FIXME support for other V4L formats + unsigned char *dst = scan_buf, *src = buf; + int x, y; + for(y = 0; y < vwin.height; y++) + for(x = 0; x < vwin.width; x++, src += 3) + *dst++ = (*(src + 1) + *(src + 2) + *(src + 3)) / 3; + return(scan_buf); } -static void symbol_handler (zebra_decoder_t *decoder) +static inline symbol_cache_entry_t *lookup_symbol (zebra_symbol_t *sym, + double ms) { - zebra_symbol_type_t sym = zebra_decoder_get_type(decoder); - if(sym <= ZEBRA_PARTIAL) - return; - const char *data = zebra_decoder_get_data(decoder); + zebra_symbol_type_t type = zebra_symbol_get_type(sym); + if(type <= ZEBRA_PARTIAL) + return(NULL); + const char *data = zebra_symbol_get_data(sym); + + dprintf("%d: %s", type, data); + + /* search for matching entry in cache */ + int i, flush = -1; + symbol_cache_entry_t *entry = NULL; + for(i = 0; i < sym_cachelen; i++) { + entry = &sym_cache[i]; + if((flush < 0) && ((ms - entry->time) > CACHE_TIMEOUT)) + flush = i; + if(entry->type == type && !strcmp(entry->data, data)) { + dprintf(" [%g %lld %d]\n", + ms - entry->time, nframes - entry->frame, entry->count); + return(entry); + } + } - int match = (sym == last_sym_type && - !strncmp(data, last_sym_data, SYM_MAX)); - int uncertain = nframes > (last_sym_frame + UNCERTAINTY); + /* not found */ + int datalen = strlen(data) + 1; + if(flush >= 0) { + /* recycle timed out entry */ + dprintf(" (recycled %d %g)", flush, ms - entry->time); + entry = &sym_cache[flush]; + } + else { + /* allocate new entry */ + sym_cache = realloc(sym_cache, + ++sym_cachelen * sizeof(symbol_cache_entry_t)); + dprintf(" (new %d)", sym_cachelen); + entry = &sym_cache[sym_cachelen - 1]; + memset(entry, 0, sizeof(symbol_cache_entry_t)); + } + dprintf(" (%d %d)", entry->datalen, datalen); + if(entry->datalen < datalen) { + if(entry->data) + free(entry->data); + entry->data = malloc(datalen); + entry->datalen = datalen; + } + dprintf("%p\n", entry->data); + strcpy(entry->data, data); + entry->type = type; + entry->time = ms - SYM_HYST; + entry->count = 0; + return(entry); +} - last_sym_frame = nframes; - last_sym_type = sym; +static inline void draw_marker (int x, int y) +{ + if(x < 3) + x = 3; + else if(x > vwin.width - 4) + x = vwin.width - 4; + if(y < 3) + y = 3; + else if(y > vwin.height - 4) + y = vwin.height - 4; + dprintf("(%d, %d) = %p\n", x, y, p); + + uint8_t *p = screen->pixels + 3 * ((x - 3) + (y - 3) * vwin.width) + 2; + for(y = 0; y < 7; y++) { + char m = marker[y]; + for(x = 0; x < 7; x++, p += 3, m >>= 1) + if(m & 1) + *p = 0xff; + p += (vwin.width - 7) * 3; + } +} + +static void process_symbol (zebra_symbol_t *sym) +{ + double ms = SDL_GetTicks(); + symbol_cache_entry_t *entry = lookup_symbol(sym, ms); + if(!entry) + return; + + /* track location overlay on image */ + if(zebra_symbol_get_loc_size(sym)) + draw_marker(zebra_symbol_get_loc_x(sym, 0), + zebra_symbol_get_loc_y(sym, 0)); /* uncertainty filtering * symbols are only reported after they have been * observed consistently in several nearby frames */ - if(!match || uncertain) { - strncpy(last_sym_data, data, SYM_MAX); - last_sym_count = 0; - return; - } - if(++last_sym_count < CERTAINTY) + int uncertain = nframes > (entry->frame + UNCERTAINTY); + entry->frame = nframes; + if(uncertain || (++entry->count < CERTAINTY)) return; /* edge detect symbol change w/some hysteresis */ - double ms = SDL_GetTicks(); - int edge = match && ((ms - last_sym_time) < SYM_HYST); - last_sym_time = ms; - if(edge) + int edge = (ms - entry->time) >= SYM_HYST; + entry->time = ms; + if(!edge) return; /* report new symbol */ printf("%s%s: %s\n", - zebra_get_symbol_name(sym), - zebra_get_addon_name(sym), - zebra_decoder_get_data(decoder)); + zebra_get_symbol_name(entry->type), + zebra_get_addon_name(entry->type), + entry->data); fflush(stdout); - beep_time = ms; SDL_PauseAudio(0); } -static char pixel_handler (zebra_img_walker_t *walker, - void *p) +static inline void process () { - if(!zebra_img_walker_get_col(walker) || - !zebra_img_walker_get_row(walker)) - zebra_scanner_new_scan(scanner); - - zebra_scan_rgb24(scanner, p); - - *((uint8_t*)p - buf + (uint8_t*)screen->pixels + 2) = 0xff; - return(0); + int n_syms = zebra_img_scan_y(scanner, convert_gray()); + assert(n_syms >= 0); + int i; + for(i = 0; i < n_syms; i++) + process_symbol(zebra_img_scanner_get_result(scanner, i)); } -int usage (int rc) +static int usage (int rc) { FILE *out = (rc) ? stderr : stdout; fprintf(out, @@ -377,19 +466,10 @@ int main (int argc, const char *argv[]) init_cam(); init_sdl(); - /* create decoder object */ - decoder = zebra_decoder_create(); - /* attach callback */ - zebra_decoder_set_handler(decoder, symbol_handler); - - /* attach new scanner to decoder */ - scanner = zebra_scanner_create(decoder); - - /* setup image scan pattern walker */ - walker = zebra_img_walker_create(); - zebra_img_walker_set_size(walker, vwin.width, vwin.height); - zebra_img_walker_set_stride(walker, 3, 0); /* RGB */ - zebra_img_walker_set_handler(walker, pixel_handler); + /* setup zebra library image scanner */ + scanner = zebra_img_scanner_create(); + zebra_img_scanner_set_size(scanner, vwin.width, vwin.height); + scan_buf = malloc(vwin.width * vwin.height); /* main loop */ int frame = 0; @@ -436,12 +516,12 @@ int main (int argc, const char *argv[]) if(ms >= last_frame_time + 10000) { last_frame_time += 10000; double fr = nframes * 1000. / ms; + /* FIXME use enabled overlay */ fprintf(stderr, "@%g %gfps\n", ms, fr); } frame = (frame + 1) % vbuf.frames; } - zebra_scanner_destroy(scanner); - zebra_decoder_destroy(decoder); + zebra_img_scanner_destroy(scanner); return(0); } diff --git a/zebraimg/zebraimg.cpp b/zebraimg/zebraimg.cpp index b28befb..0e09c4f 100644 --- a/zebraimg/zebraimg.cpp +++ b/zebraimg/zebraimg.cpp @@ -21,15 +21,7 @@ // http://sourceforge.net/projects/zebra //------------------------------------------------------------------------ -#ifdef HAVE_INTTYPES_H -# include -#endif #include -#include -#include -#include - -#include /* wand/wand-config.h defines these conflicting values :| */ #undef PACKAGE_BUGREPORT @@ -37,7 +29,14 @@ #undef PACKAGE_STRING #undef PACKAGE_TARNAME #undef PACKAGE_VERSION + #include "config.h" +#include +#include +#include +#include + +#include using namespace std; using namespace Magick; @@ -45,95 +44,117 @@ using namespace zebra; int display = 0, num_images = 0; -Decoder decoder; -Scanner scanner(decoder); -ImageWalker walker; -const PixelPacket *rd_pxp; -PixelPacket *wr_pxp; -unsigned width, height; -map datahist; -string data_max; -unsigned data_cnt; - -ColorRGB space_fill(1., 0., 0.); -ColorRGB bar_fill(.5, 0., 0.); - -class PixelHandler : public ImageWalker::Handler { - virtual char walker_callback (ImageWalker &, void *pixel) - { - ColorYUV y; - y = *(rd_pxp + (uintptr_t)pixel); - assert(walker.get_col() < width); - assert(walker.get_row() < height); - assert((uintptr_t)pixel < width * height); - if(!walker.get_col() || !walker.get_row()) - scanner.new_scan(); - scanner << (int)(y.y() * 0x100); - *(wr_pxp + (uintptr_t)pixel) = - (scanner.get_color() == ZEBRA_SPACE) ? bar_fill : space_fill; - return(0); +ImageScanner scanner; + +static inline void overlay_grid (Image& img) +{ + unsigned width = img.columns(); + unsigned height = img.rows(); + list overlay; + overlay.push_back(DrawableStrokeWidth(1)); + overlay.push_back(DrawableStrokeColor(ColorGray(1))); + overlay.push_back(DrawableFillOpacity(0)); + overlay.push_back(DrawableStrokeOpacity(.15)); + for(unsigned i = 8; i < width; i += 16) + overlay.push_back(DrawableLine(i, 0, i, height - 1)); + for(unsigned i = 8; i < height; i += 16) + overlay.push_back(DrawableLine(0, i, width, i)); + img.draw(overlay); +} + +static inline void overlay_symbol (Image& img, + Symbol& sym) +{ + list overlay; + overlay.push_back(DrawableStrokeColor(ColorRGB(1,0,0))); + overlay.push_back(DrawableFillOpacity(0)); + overlay.push_back(DrawableStrokeOpacity(.5)); + overlay.push_back(DrawableStrokeWidth(3)); + + // FIXME eventually will always have at least 4 points + int n_pts = sym.get_location_size(); + assert(n_pts); + if(n_pts == 1) { + int x = sym.get_location_x(0); + int y = sym.get_location_y(0); + cerr << "(" << x << "," << y << ")" << endl; + overlay.push_back(DrawablePoint(x, y)); + overlay.push_back(DrawableCircle(x, y, x - 5, y - 5)); + } + else if(n_pts == 2) + overlay.push_back(DrawableLine(sym.get_location_x(0), + sym.get_location_y(0), + sym.get_location_x(1), + sym.get_location_y(1))); + else { + list poly; + for(int j = 0; j < n_pts; j++) + poly.push_back(Coordinate(sym.get_location_x(j), + sym.get_location_y(j))); + overlay.push_back(DrawablePolygon(poly)); + } + img.draw(overlay); +} + +static int scan_image (const char *filename) +{ + Image disp_img; + try { + disp_img.read(filename); + } + catch (Exception &e) { + cout << "ERROR: " << e.what() << endl + << "while reading " << filename << endl; + return(1); } -} pixel_handler; -class SymbolHandler : public Decoder::Handler { - virtual void decode_callback (Decoder &decoder) { - if(decoder.get_type() > ZEBRA_PARTIAL) { - string data = (string(decoder.get_symbol_name()) + - string(decoder.get_addon_name()) + - ":" + decoder.get_data_string()); - if(++datahist[data] > data_cnt) { - data_max = data; - data_cnt = datahist[data]; - } - } + // extract grayscale image pixels + Image scan_img = disp_img; + scan_img.modifyImage(); + Blob scan_data; + scan_img.write(&scan_data, "GRAY", 8); + unsigned width = disp_img.columns(); + unsigned height = disp_img.rows(); + assert(scan_data.length() == width * height); + scanner.set_size(width, height); + scanner.scan_y(scan_data.data()); } -} symbol_handler; -void scan_image (const char *filename) -{ - scanner.reset(); - datahist.clear(); - data_cnt = 0; - - Image image; - image.read(filename); - Image wr_img = image; - - width = image.columns(); - height = image.rows(); - walker.set_size(width, height); - - wr_img.type(TrueColorType); - wr_img.modifyImage(); - - // extract image pixels - Pixels rd_view(image); - rd_pxp = rd_view.getConst(0, 0, width, height); - Pixels wr_view(wr_img); - wr_pxp = wr_view.get(0, 0, width, height); - walker.walk(0); - scanner.new_scan(); /* flush scan */ - wr_view.sync(); - - // display result data - if(data_cnt) - cout << data_max << endl; + if(display) { + // FIXME overlay optional + disp_img.modifyImage(); + disp_img.type(TrueColorType); + overlay_grid(disp_img); + } + + // output result data + for(int i = 0; i < scanner.get_result_size(); i++) { + Symbol symbol = scanner.get_result(i); + cout << (string(symbol.get_type_name()) + + string(symbol.get_addon_name()) + + ":" + symbol.get_data()) << endl; + cout.flush(); + + if(display) + overlay_symbol(disp_img, symbol); + } if(display) { #if (MagickLibVersion >= 0x632) - wr_img.display(); + disp_img.display(); #else // workaround for "no window with specified ID exists" bug // ref http://www.imagemagick.org/discourse-server/viewtopic.php?t=6315 // fixed in 6.3.1-25 - char c = wr_img.imageInfo()->filename[0]; - wr_img.imageInfo()->filename[0] = 0; - wr_img.display(); - wr_img.imageInfo()->filename[0] = c; + char c = disp_img.imageInfo()->filename[0]; + disp_img.imageInfo()->filename[0] = 0; + disp_img.display(); + disp_img.imageInfo()->filename[0] = c; #endif } num_images++; + return(0); } int usage (int rc, const char *msg = NULL) @@ -156,17 +177,14 @@ int usage (int rc, const char *msg = NULL) int main (int argc, const char *argv[]) { - decoder.set_handler(symbol_handler); - walker.set_handler(pixel_handler); - - int i; + int i, rc = 0; for(i = 1; i < argc; i++) { if(!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) - return(usage(0)); + return(usage(rc)); if(!strcmp(argv[i], "--version")) { cout << PACKAGE_VERSION << endl; - return(0); + return(rc); } if(!strcmp(argv[i], "-d") || !strcmp(argv[i], "--display")) @@ -176,13 +194,13 @@ int main (int argc, const char *argv[]) else if(!strcmp(argv[i], "--")) break; else - scan_image(argv[i]); + rc |= scan_image(argv[i]); } for(i++; i < argc; i++) - scan_image(argv[i]); + rc |= scan_image(argv[i]); if(!num_images) return(usage(1, "ERROR: specify image file(s) to scan")); - return(0); + return(rc); } From 875edea779e6205497d9458f27c74712a686113e Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 16 Aug 2007 04:17:13 +0000 Subject: [PATCH 025/328] * add missing xlink namespace to dbg_scan generated output (bug #1764188) * qualify char types as [un]signed to avoid non-portable C ambiguity - thanks to mhirsch45@users.sf.net for the patch! (bug #1759914) --- ChangeLog | 3 ++ TODO | 22 +++++++----- test/dbg_scan.cc | 1 + zebra/code128.c | 38 ++++++++++----------- zebra/code128.h | 2 +- zebra/ean.c | 88 ++++++++++++++++++++++++------------------------ zebra/ean.h | 6 ++-- 7 files changed, 85 insertions(+), 75 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4e9ce74..3ab6075 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,7 @@ current: + * add missing xlink namespace to dbg_scan generated output (bug #1764188) + * qualify char types as [un]signed to avoid non-portable C ambiguity + - thanks to mhirsch45@users.sf.net for the patch! (bug #1759914) * add integrated 2D image scanning API - automatically ties to internal scanner and decoder - results reported via new symbol API diff --git a/TODO b/TODO index 0b376c3..8672372 100644 --- a/TODO +++ b/TODO @@ -1,14 +1,20 @@ * handle Code 128 function characters (FNC1-4) - * integrated high-level image API * decoder needs symbology/feature enable/disable - * better C++ interface to img_walker - * nice to match STL iterator interface * space lead in/out from each scan line - * img_walker skip uselessly short scan lines - * img_walker pattern selection - * higher img_walker pattern density (cfg even better) - * zebracam support for v4l2 API - * support for other v4l image formats + * reader skip uselessly short scan lines + * configurable reader pattern density + * support for other X visuals (16 bit depth) + * zebraimg features + * message when no result found (w/o -q) + * xml output format + * zebracam features + * support for v4l2 API + * support for other v4l image formats + * specify device + * hide cursor + * deactivate sound + * errors opening sound device + * simple image manipulations scale/mirror * decode hook (program/script) to zebracam/(zebraimg?) * finish UPC-E, EAN-8 and addon decoding * add library version query interface diff --git a/test/dbg_scan.cc b/test/dbg_scan.cc index 93c2cf6..5fb1f87 100644 --- a/test/dbg_scan.cc +++ b/test/dbg_scan.cc @@ -79,6 +79,7 @@ void scan_image (const char *filename) << "" << endl << "

Copyright 2008 (c) Jeff Brown - All Rights Reserved.

+

Copyright 2008-2009 (c) Jeff Brown - All Rights Reserved.

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.

diff --git a/doc/doxygen.conf.in b/doc/doxygen.conf.in index 546d433..c7a2390 100644 --- a/doc/doxygen.conf.in +++ b/doc/doxygen.conf.in @@ -1,9 +1,9 @@ -PROJECT_NAME = "Zebra Barcode Reader Library" +PROJECT_NAME = "ZBar Bar Code Reader Library" PROJECT_NUMBER = "version @VERSION@" INPUT = @top_srcdir@/include RECURSIVE = YES -EXCLUDE = @top_srcdir@/include/zebra/zebragtk.h +EXCLUDE = @top_srcdir@/include/zbar/zbargtk.h EXCLUDE_PATTERNS = */.svn/* STRIP_FROM_PATH = @top_srcdir@ diff --git a/doc/manual.xml b/doc/manual.xml index 3c4edea..076ca23 100644 --- a/doc/manual.xml +++ b/doc/manual.xml @@ -7,14 +7,14 @@ - - + + ]> - Zebra Barcode Reader + ZBar Barcode Reader - zebra-&version; + zbar-&version; &date; @@ -31,7 +31,6 @@ Jeff Brown All Rights Reserved - @@ -41,10 +40,10 @@ - Zebra Barcode Reader - Command Reference + ZBar Barcode Reader - Command Reference - &refzebracam; - &refzebraimg; + &refzbarcam; + &refzbarimg; diff --git a/doc/ref/commonoptions.xml b/doc/ref/commonoptions.xml index 53543ca..15665f2 100644 --- a/doc/ref/commonoptions.xml +++ b/doc/ref/commonoptions.xml @@ -111,7 +111,5 @@ - - diff --git a/doc/ref/zebracam.xml b/doc/ref/zbarcam.xml similarity index 86% rename from doc/ref/zebracam.xml rename to doc/ref/zbarcam.xml index 1eaf894..a0be014 100644 --- a/doc/ref/zebracam.xml +++ b/doc/ref/zbarcam.xml @@ -1,13 +1,13 @@ - - zebracam + zbarcam 1 - zebracam + zbarcam scan and decode bar codes from a video device @@ -15,7 +15,7 @@ - zebracam + zbarcam @@ -37,7 +37,7 @@ - zebracam + zbarcam @@ -49,7 +49,7 @@ Description - zebracam scans a video4linux video source + zbarcam scans a video4linux video source (eg, a webcam) for bar codes and prints any decoded data to the standard output. The video stream is also displayed to the screen. @@ -100,7 +100,7 @@ Stream results using an XML output format. This format wraps the raw data from the symbol with information about the scan in an easy to parse format. The latest - schema is available from . + schema is available from . @@ -126,7 +126,7 @@ resulting data through a script that searches for each code in a database and does something useful with them: - zebracam /dev/video1 | upcrpc.py + zbarcam /dev/video1 | upcrpc.py The upcrpc.py example script included in the examples/ subdirectory of the distribution @@ -138,21 +138,21 @@ Interleaved 2 of 5 codes to prevent confusion with other symbologies or background noise: - zebracam + zbarcam Scan only for Code 39, without using the preview window - maybe for a fixed installation. To enable only Code 39, first all symbologies are disabled, then Code 39 is re-enabled: - zebracam + zbarcam See Also - - + + diff --git a/doc/ref/zebraimg.xml b/doc/ref/zbarimg.xml similarity index 87% rename from doc/ref/zebraimg.xml rename to doc/ref/zbarimg.xml index dae2602..b3e5616 100644 --- a/doc/ref/zebraimg.xml +++ b/doc/ref/zbarimg.xml @@ -1,13 +1,13 @@ - - zebraimg + zbarimg 1 - zebraimg + zbarimg scan and decode bar codes from image file(s) @@ -15,7 +15,7 @@ - zebraimg + zbarimg See Also - - + + diff --git a/examples/paginate.pl b/examples/paginate.pl index 2426208..68ffe50 100755 --- a/examples/paginate.pl +++ b/examples/paginate.pl @@ -2,29 +2,29 @@ #------------------------------------------------------------------------ # Copyright 2009 (c) Jeff Brown # -# This file is part of the Zebra Barcode Library. +# This file is part of the ZBar Bar Code Reader. # -# The Zebra Barcode Library is free software; you can redistribute it +# 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 Zebra Barcode Library is distributed in the hope that it will be +# 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 Zebra Barcode Library; if not, write to the Free +# 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/zebra +# http://sourceforge.net/projects/zbar #------------------------------------------------------------------------ use warnings; use strict; -use Barcode::Zebra; +use Barcode::ZBar; use Image::Magick; warn("no input files specified?\n") if(!@ARGV); @@ -33,7 +33,7 @@ my $out = undef; # barcode scanner -my $scanner = Barcode::Zebra::ImageScanner->new(); +my $scanner = Barcode::ZBar::ImageScanner->new(); foreach my $file (@ARGV) { print "scanning from \"$file\"\n"; @@ -42,8 +42,8 @@ warn($err) if($err); foreach my $page (@$imseq) { - # convert ImageMagick page to Zebra image - my $zimg = Barcode::Zebra::Image->new(); + # 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)); diff --git a/examples/processor.pl b/examples/processor.pl index ef1f201..e14a4a3 100755 --- a/examples/processor.pl +++ b/examples/processor.pl @@ -1,10 +1,10 @@ #!/usr/bin/env perl use warnings; use strict; -require Barcode::Zebra; +require Barcode::ZBar; # create a Processor -my $proc = Barcode::Zebra::Processor->new(); +my $proc = Barcode::ZBar::Processor->new(); # configure the Processor $proc->parse_config("enable"); diff --git a/examples/processor.py b/examples/processor.py index 8d86a84..e565164 100755 --- a/examples/processor.py +++ b/examples/processor.py @@ -1,9 +1,9 @@ #!/usr/bin/python from sys import argv -import zebra +import zbar # create a Processor -proc = zebra.Processor() +proc = zbar.Processor() # configure the Processor proc.parse_config('enable') @@ -31,5 +31,5 @@ def my_handler(proc, image, closure): proc.active = True try: proc.user_wait() -except zebra.WindowClosed, e: +except zbar.WindowClosed, e: pass diff --git a/examples/scan_image.c b/examples/scan_image.c index b8b81c1..2ce4a68 100644 --- a/examples/scan_image.c +++ b/examples/scan_image.c @@ -1,9 +1,9 @@ #include #include #include -#include +#include -zebra_image_scanner_t *scanner = NULL; +zbar_image_scanner_t *scanner = NULL; /* to complete a runnable example, this abbreviated implementation of * get_data() will use libpng to read an image file. refer to libpng @@ -53,10 +53,10 @@ int main (int argc, char **argv) if(argc < 2) return(1); /* create a reader */ - scanner = zebra_image_scanner_create(); + scanner = zbar_image_scanner_create(); /* configure the reader */ - zebra_image_scanner_set_config(scanner, 0, ZEBRA_CFG_ENABLE, 1); + zbar_image_scanner_set_config(scanner, 0, ZBAR_CFG_ENABLE, 1); /* obtain image data */ int width = 0, height = 0; @@ -64,26 +64,26 @@ int main (int argc, char **argv) get_data(argv[1], &width, &height, &raw); /* wrap image data */ - zebra_image_t *image = zebra_image_create(); - zebra_image_set_format(image, *(int*)"Y800"); - zebra_image_set_size(image, width, height); - zebra_image_set_data(image, raw, width * height, zebra_image_free_data); + zbar_image_t *image = zbar_image_create(); + zbar_image_set_format(image, *(int*)"Y800"); + zbar_image_set_size(image, width, height); + zbar_image_set_data(image, raw, width * height, zbar_image_free_data); /* scan the image for barcodes */ - int n = zebra_scan_image(scanner, image); + int n = zbar_scan_image(scanner, image); /* extract results */ - const zebra_symbol_t *symbol = zebra_image_first_symbol(image); - for(; symbol; symbol = zebra_symbol_next(symbol)) { + const zbar_symbol_t *symbol = zbar_image_first_symbol(image); + for(; symbol; symbol = zbar_symbol_next(symbol)) { /* do something useful with results */ - zebra_symbol_type_t typ = zebra_symbol_get_type(symbol); - const char *data = zebra_symbol_get_data(symbol); + zbar_symbol_type_t typ = zbar_symbol_get_type(symbol); + const char *data = zbar_symbol_get_data(symbol); printf("decoded %s symbol \"%s\"\n", - zebra_get_symbol_name(typ), data); + zbar_get_symbol_name(typ), data); } /* clean up */ - zebra_image_destroy(image); + zbar_image_destroy(image); return(0); } diff --git a/examples/scan_image.cpp b/examples/scan_image.cpp index 8edf06b..18a65a3 100644 --- a/examples/scan_image.cpp +++ b/examples/scan_image.cpp @@ -1,9 +1,9 @@ #include #include -#include +#include using namespace std; -using namespace zebra; +using namespace zbar; int main (int argc, char **argv) { @@ -13,7 +13,7 @@ int main (int argc, char **argv) ImageScanner scanner; // configure the reader - scanner.set_config(ZEBRA_NONE, ZEBRA_CFG_ENABLE, 1); + scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1); // obtain image data Magick::Image magick(argv[1]); // read an image file diff --git a/examples/scan_image.pl b/examples/scan_image.pl index 93185e5..3734d19 100755 --- a/examples/scan_image.pl +++ b/examples/scan_image.pl @@ -2,12 +2,12 @@ use warnings; use strict; require Image::Magick; -require Barcode::Zebra; +require Barcode::ZBar; $ARGV[0] || die; # create a reader -my $scanner = Barcode::Zebra::ImageScanner->new(); +my $scanner = Barcode::ZBar::ImageScanner->new(); # configure the reader $scanner->parse_config("enable"); @@ -18,7 +18,7 @@ my $raw = $magick->ImageToBlob(magick => 'GRAY'); # wrap image data -my $image = Barcode::Zebra::Image->new(); +my $image = Barcode::ZBar::Image->new(); $image->set_format('Y800'); $image->set_size($magick->Get(qw(columns rows))); $image->set_data($raw); diff --git a/examples/scan_image.py b/examples/scan_image.py index ec584ad..2a80759 100755 --- a/examples/scan_image.py +++ b/examples/scan_image.py @@ -1,12 +1,12 @@ #!/usr/bin/python from sys import argv -import zebra +import zbar import Image if len(argv) < 2: exit(1) # create a reader -scanner = zebra.ImageScanner() +scanner = zbar.ImageScanner() # configure the reader scanner.parse_config('enable') @@ -17,7 +17,7 @@ raw = pil.tostring() # wrap image data -image = zebra.Image(width, height, 'Y800', raw) +image = zbar.Image(width, height, 'Y800', raw) # scan the image for barcodes scanner.scan(image) diff --git a/gtk/Makefile.am.inc b/gtk/Makefile.am.inc index 2bc511e..cf5132d 100644 --- a/gtk/Makefile.am.inc +++ b/gtk/Makefile.am.inc @@ -1,18 +1,18 @@ -lib_LTLIBRARIES += gtk/libzebragtk.la -gtk_libzebragtk_la_CPPFLAGS = -Igtk $(GTK_CFLAGS) $(AM_CPPFLAGS) -gtk_libzebragtk_la_LDFLAGS = -version-info $(ZGTK_LIB_VERSION) \ - -export-symbols-regex "^zebra_gtk_.*" $(AM_LDFLAGS) -gtk_libzebragtk_la_LIBADD = $(GTK_LIBS) zebra/libzebra.la $(AM_LIBADD) +lib_LTLIBRARIES += gtk/libzbargtk.la +gtk_libzbargtk_la_CPPFLAGS = -Igtk $(GTK_CFLAGS) $(AM_CPPFLAGS) +gtk_libzbargtk_la_LDFLAGS = -version-info $(ZGTK_LIB_VERSION) \ + -export-symbols-regex "^zbar_gtk_.*" $(AM_LDFLAGS) +gtk_libzbargtk_la_LIBADD = $(GTK_LIBS) zbar/libzbar.la $(AM_LIBADD) -gtk_libzebragtk_la_SOURCES = gtk/zebragtk.c gtk/zebragtkprivate.h \ - gtk/zebramarshal.c gtk/zebramarshal.h -BUILT_SOURCES += gtk/zebramarshal.c gtk/zebramarshal.h -EXTRA_DIST += gtk/zebramarshal.list +gtk_libzbargtk_la_SOURCES = gtk/zbargtk.c gtk/zbargtkprivate.h \ + gtk/zbarmarshal.c gtk/zbarmarshal.h +BUILT_SOURCES += gtk/zbarmarshal.c gtk/zbarmarshal.h +EXTRA_DIST += gtk/zbarmarshal.list %.h: %.list - $(GLIB_GENMARSHAL) --g-fatal-warnings --prefix=zebra_marshal \ + $(GLIB_GENMARSHAL) --g-fatal-warnings --prefix=zbar_marshal \ --header $^ > $@ %.c: %.list - $(GLIB_GENMARSHAL) --g-fatal-warnings --prefix=zebra_marshal \ + $(GLIB_GENMARSHAL) --g-fatal-warnings --prefix=zbar_marshal \ --body $^ > $@ diff --git a/gtk/zebragtk.c b/gtk/zbargtk.c similarity index 52% rename from gtk/zebragtk.c rename to gtk/zbargtk.c index 75418d4..67dc842 100644 --- a/gtk/zebragtk.c +++ b/gtk/zbargtk.c @@ -1,32 +1,32 @@ /*------------------------------------------------------------------------ - * Copyright 2008 (c) Jeff Brown + * Copyright 2008-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include #include -#include -#include "zebragtkprivate.h" -#include "zebramarshal.h" +#include +#include "zbargtkprivate.h" +#include "zbarmarshal.h" #ifndef G_PARAM_STATIC_STRINGS # define G_PARAM_STATIC_STRINGS (G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB) @@ -53,27 +53,27 @@ enum { PROP_VIDEO_OPENED, }; -static guint zebra_gtk_signals[LAST_SIGNAL] = { 0 }; +static guint zbar_gtk_signals[LAST_SIGNAL] = { 0 }; -static gpointer zebra_gtk_parent_class = NULL; +static gpointer zbar_gtk_parent_class = NULL; /* FIXME what todo w/errors? OOM? */ /* FIXME signal failure notifications to main gui thread */ -void zebra_gtk_release_pixbuf (zebra_image_t *img) +void zbar_gtk_release_pixbuf (zbar_image_t *img) { - GdkPixbuf *pixbuf = zebra_image_get_userdata(img); + GdkPixbuf *pixbuf = zbar_image_get_userdata(img); g_assert(GDK_IS_PIXBUF(pixbuf)); /* remove reference */ - zebra_image_set_userdata(img, NULL); + zbar_image_set_userdata(img, NULL); /* release reference to associated pixbuf and it's data */ g_object_unref(pixbuf); } -gboolean zebra_gtk_image_from_pixbuf (zebra_image_t *zimg, - GdkPixbuf *pixbuf) +gboolean zbar_gtk_image_from_pixbuf (zbar_image_t *zimg, + GdkPixbuf *pixbuf) { /* apparently should always be packed RGB? */ GdkColorspace colorspace = gdk_pixbuf_get_colorspace(pixbuf); @@ -102,7 +102,7 @@ gboolean zebra_gtk_image_from_pixbuf (zebra_image_t *zimg, nchannels, bps); return(FALSE); } - zebra_image_set_format(zimg, type); + zbar_image_set_format(zimg, type); /* FIXME we don't deal w/bpl... * this will cause problems w/unpadded pixbufs :| @@ -117,15 +117,15 @@ gboolean zebra_gtk_image_from_pixbuf (zebra_image_t *zimg, unsigned height = gdk_pixbuf_get_height(pixbuf); /* FIXME this isn't correct either */ unsigned long datalen = width * height * nchannels; - zebra_image_set_size(zimg, width, height); + zbar_image_set_size(zimg, width, height); - /* when the zebra image is released, the pixbuf will be + /* when the zbar image is released, the pixbuf will be * automatically be released */ - zebra_image_set_userdata(zimg, pixbuf); - zebra_image_set_data(zimg, gdk_pixbuf_get_pixels(pixbuf), datalen, - zebra_gtk_release_pixbuf); -#ifdef DEBUG_ZEBRAGTK + zbar_image_set_userdata(zimg, pixbuf); + zbar_image_set_data(zimg, gdk_pixbuf_get_pixels(pixbuf), datalen, + zbar_gtk_release_pixbuf); +#ifdef DEBUG_ZBARGTK g_message("colorspace=%d nchannels=%d bps=%d type=%.4s(%08lx)\n" "\tpitch=%d width=%d height=%d datalen=0x%lx\n", colorspace, nchannels, bps, (char*)&type, type, @@ -134,47 +134,47 @@ gboolean zebra_gtk_image_from_pixbuf (zebra_image_t *zimg, return(TRUE); } -static inline gboolean zebra_gtk_video_open (ZebraGtk *self, - const char *video_device) +static inline gboolean zbar_gtk_video_open (ZBarGtk *self, + const char *video_device) { - ZebraGtkPrivate *zebra = ZEBRA_GTK_PRIVATE(self->_private); + ZBarGtkPrivate *zbar = ZBAR_GTK_PRIVATE(self->_private); gboolean video_opened = FALSE; gdk_threads_enter(); - zebra->req_width = DEFAULT_WIDTH; - zebra->req_height = DEFAULT_HEIGHT; + zbar->req_width = DEFAULT_WIDTH; + zbar->req_height = DEFAULT_HEIGHT; gtk_widget_queue_resize(GTK_WIDGET(self)); - zebra->video_opened = FALSE; - if(zebra->thread) + zbar->video_opened = FALSE; + if(zbar->thread) g_object_notify(G_OBJECT(self), "video-opened"); - if(zebra->window) { + if(zbar->window) { /* ensure old video doesn't have image ref * (FIXME handle video destroyed w/images outstanding) */ - zebra_window_draw(zebra->window, NULL); + zbar_window_draw(zbar->window, NULL); gtk_widget_queue_draw(GTK_WIDGET(self)); } gdk_threads_leave(); - if(zebra->video) { - zebra_video_destroy(zebra->video); - zebra->video = NULL; + if(zbar->video) { + zbar_video_destroy(zbar->video); + zbar->video = NULL; } - if(video_device && video_device[0] && zebra->thread) { + if(video_device && video_device[0] && zbar->thread) { /* create video * FIXME video should support re-open */ - zebra->video = zebra_video_create(); - g_assert(zebra->video); + zbar->video = zbar_video_create(); + g_assert(zbar->video); - if(zebra_video_open(zebra->video, video_device)) { - zebra_video_error_spew(zebra->video, 0); - zebra_video_destroy(zebra->video); - zebra->video = NULL; + if(zbar_video_open(zbar->video, video_device)) { + zbar_video_error_spew(zbar->video, 0); + zbar_video_destroy(zbar->video); + zbar->video = NULL; /* FIXME error propagation */ return(FALSE); } @@ -184,16 +184,16 @@ static inline gboolean zebra_gtk_video_open (ZebraGtk *self, */ gdk_threads_enter(); - video_opened = !zebra_negotiate_format(zebra->video, zebra->window); + video_opened = !zbar_negotiate_format(zbar->video, zbar->window); if(video_opened) { - zebra->req_width = zebra_video_get_width(zebra->video); - zebra->req_height = zebra_video_get_height(zebra->video); + zbar->req_width = zbar_video_get_width(zbar->video); + zbar->req_height = zbar_video_get_height(zbar->video); } gtk_widget_queue_resize(GTK_WIDGET(self)); - zebra->video_opened = video_opened; - if(zebra->thread) + zbar->video_opened = video_opened; + if(zbar->thread) g_object_notify(G_OBJECT(self), "video-opened"); gdk_threads_leave(); @@ -201,45 +201,45 @@ static inline gboolean zebra_gtk_video_open (ZebraGtk *self, return(video_opened); } -static inline int zebra_gtk_process_image (ZebraGtk *self, - zebra_image_t *image) +static inline int zbar_gtk_process_image (ZBarGtk *self, + zbar_image_t *image) { - ZebraGtkPrivate *zebra = ZEBRA_GTK_PRIVATE(self->_private); + ZBarGtkPrivate *zbar = ZBAR_GTK_PRIVATE(self->_private); if(!image) return(-1); - int rc = zebra_scan_image(zebra->scanner, image); + int rc = zbar_scan_image(zbar->scanner, image); if(rc < 0) return(rc); gdk_threads_enter(); - if(rc && zebra->thread) { + if(rc && zbar->thread) { /* update decode results */ - const zebra_symbol_t *sym; - for(sym = zebra_image_first_symbol(image); + const zbar_symbol_t *sym; + for(sym = zbar_image_first_symbol(image); sym; - sym = zebra_symbol_next(sym)) - if(!zebra_symbol_get_count(sym)) { - zebra_symbol_type_t type = zebra_symbol_get_type(sym); - const char *data = zebra_symbol_get_data(sym); - g_signal_emit(self, zebra_gtk_signals[DECODED], 0, + sym = zbar_symbol_next(sym)) + if(!zbar_symbol_get_count(sym)) { + zbar_symbol_type_t type = zbar_symbol_get_type(sym); + const char *data = zbar_symbol_get_data(sym); + g_signal_emit(self, zbar_gtk_signals[DECODED], 0, type, data); /* FIXME skip this when unconnected? */ - gchar *text = g_strconcat(zebra_get_symbol_name(type), - zebra_get_addon_name(type), + gchar *text = g_strconcat(zbar_get_symbol_name(type), + zbar_get_addon_name(type), ":", data, NULL); - g_signal_emit(self, zebra_gtk_signals[DECODED_TEXT], 0, text); + g_signal_emit(self, zbar_gtk_signals[DECODED_TEXT], 0, text); g_free(text); } } - if(zebra->window) { - rc = zebra_window_draw(zebra->window, image); + if(zbar->window) { + rc = zbar_window_draw(zbar->window, image); gtk_widget_queue_draw(GTK_WIDGET(self)); } else @@ -248,18 +248,18 @@ static inline int zebra_gtk_process_image (ZebraGtk *self, return(rc); } -static void *zebra_gtk_processing_thread (void *arg) +static void *zbar_gtk_processing_thread (void *arg) { - ZebraGtk *self = ZEBRA_GTK(arg); + ZBarGtk *self = ZBAR_GTK(arg); if(!self->_private) return(NULL); - ZebraGtkPrivate *zebra = ZEBRA_GTK_PRIVATE(self->_private); - g_object_ref(zebra); - g_assert(zebra->queue); - g_async_queue_ref(zebra->queue); + ZBarGtkPrivate *zbar = ZBAR_GTK_PRIVATE(self->_private); + g_object_ref(zbar); + g_assert(zbar->queue); + g_async_queue_ref(zbar->queue); - zebra->scanner = zebra_image_scanner_create(); - g_assert(zebra->scanner); + zbar->scanner = zbar_image_scanner_create(); + g_assert(zbar->scanner); /* thread side enabled state */ gboolean video_enabled = FALSE; @@ -267,7 +267,7 @@ static void *zebra_gtk_processing_thread (void *arg) while(TRUE) { if(!msg) - msg = g_async_queue_pop(zebra->queue); + msg = g_async_queue_pop(zbar->queue); g_assert(G_IS_VALUE(msg)); GType type = G_VALUE_TYPE(msg); @@ -287,17 +287,17 @@ static void *zebra_gtk_processing_thread (void *arg) else if(type == G_TYPE_STRING) { /* open new video device */ const char *video_device = g_value_get_string(msg); - video_enabled = zebra_gtk_video_open(self, video_device); + video_enabled = zbar_gtk_video_open(self, video_device); } else if(type == GDK_TYPE_PIXBUF) { /* scan provided image and broadcast results */ - zebra_image_t *image = zebra_image_create(); + zbar_image_t *image = zbar_image_create(); GdkPixbuf *pixbuf = GDK_PIXBUF(g_value_dup_object(msg)); - if(zebra_gtk_image_from_pixbuf(image, pixbuf)) - zebra_gtk_process_image(self, image); + if(zbar_gtk_image_from_pixbuf(image, pixbuf)) + zbar_gtk_process_image(self, image); else g_object_unref(pixbuf); - zebra_image_destroy(image); + zbar_image_destroy(image); } else { gchar *dbg = g_strdup_value_contents(msg); @@ -311,52 +311,52 @@ static void *zebra_gtk_processing_thread (void *arg) if(video_enabled) { /* release reference to any previous pixbuf */ - zebra_window_draw(zebra->window, NULL); + zbar_window_draw(zbar->window, NULL); - if(zebra_video_enable(zebra->video, 1)) { - zebra_video_error_spew(zebra->video, 0); + if(zbar_video_enable(zbar->video, 1)) { + zbar_video_error_spew(zbar->video, 0); video_enabled = FALSE; continue; } - zebra_image_scanner_enable_cache(zebra->scanner, 1); + zbar_image_scanner_enable_cache(zbar->scanner, 1); while(video_enabled && - !(msg = g_async_queue_try_pop(zebra->queue))) { - zebra_image_t *image = zebra_video_next_image(zebra->video); - if(zebra_gtk_process_image(self, image) < 0) + !(msg = g_async_queue_try_pop(zbar->queue))) { + zbar_image_t *image = zbar_video_next_image(zbar->video); + if(zbar_gtk_process_image(self, image) < 0) video_enabled = FALSE; if(image) - zebra_image_destroy(image); + zbar_image_destroy(image); } - zebra_image_scanner_enable_cache(zebra->scanner, 0); - if(zebra_video_enable(zebra->video, 0)) { - zebra_video_error_spew(zebra->video, 0); + zbar_image_scanner_enable_cache(zbar->scanner, 0); + if(zbar_video_enable(zbar->video, 0)) { + zbar_video_error_spew(zbar->video, 0); video_enabled = FALSE; } /* release video image and revert to logo */ - if(zebra->window) { - zebra_window_draw(zebra->window, NULL); + if(zbar->window) { + zbar_window_draw(zbar->window, NULL); gtk_widget_queue_draw(GTK_WIDGET(self)); } if(!video_enabled) /* must have been an error while streaming */ - zebra_gtk_video_open(self, NULL); + zbar_gtk_video_open(self, NULL); } } - if(zebra->window) - zebra_window_draw(zebra->window, NULL); - g_object_unref(zebra); + if(zbar->window) + zbar_window_draw(zbar->window, NULL); + g_object_unref(zbar); return(NULL); } -static void zebra_gtk_realize (GtkWidget *widget) +static void zbar_gtk_realize (GtkWidget *widget) { - ZebraGtk *self = ZEBRA_GTK(widget); + ZBarGtk *self = ZBAR_GTK(widget); if(!self->_private) return; - ZebraGtkPrivate *zebra = ZEBRA_GTK_PRIVATE(self->_private); + ZBarGtkPrivate *zbar = ZBAR_GTK_PRIVATE(self->_private); GTK_WIDGET_UNSET_FLAGS(widget, GTK_DOUBLE_BUFFERED); GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED); @@ -377,36 +377,36 @@ static void zebra_gtk_realize (GtkWidget *widget) gdk_window_set_user_data(widget->window, widget); gdk_window_set_back_pixmap(widget->window, NULL, TRUE); - /* attach zebra_window to underlying X window */ - if(zebra_window_attach(zebra->window, + /* attach zbar_window to underlying X window */ + if(zbar_window_attach(zbar->window, gdk_x11_drawable_get_xdisplay(widget->window), gdk_x11_drawable_get_xid(widget->window))) - zebra_window_error_spew(zebra->window, 0); + zbar_window_error_spew(zbar->window, 0); } -static inline GValue *zebra_gtk_new_value (GType type) +static inline GValue *zbar_gtk_new_value (GType type) { return(g_value_init(g_malloc0(sizeof(GValue)), type)); } -static void zebra_gtk_unrealize (GtkWidget *widget) +static void zbar_gtk_unrealize (GtkWidget *widget) { if(GTK_WIDGET_MAPPED(widget)) gtk_widget_unmap(widget); - ZebraGtk *self = ZEBRA_GTK(widget); + ZBarGtk *self = ZBAR_GTK(widget); if(!self->_private) return; - ZebraGtkPrivate *zebra = ZEBRA_GTK_PRIVATE(self->_private); + ZBarGtkPrivate *zbar = ZBAR_GTK_PRIVATE(self->_private); - if(zebra->video_enabled) { - zebra->video_enabled = FALSE; - GValue *msg = zebra_gtk_new_value(G_TYPE_INT); + if(zbar->video_enabled) { + zbar->video_enabled = FALSE; + GValue *msg = zbar_gtk_new_value(G_TYPE_INT); g_value_set_int(msg, 0); - g_async_queue_push(zebra->queue, msg); + g_async_queue_push(zbar->queue, msg); } - zebra_window_attach(zebra->window, NULL, 0); + zbar_window_attach(zbar->window, NULL, 0); GTK_WIDGET_UNSET_FLAGS(widget, GTK_REALIZED); @@ -415,101 +415,101 @@ static void zebra_gtk_unrealize (GtkWidget *widget) widget->window = NULL; } -static void zebra_gtk_size_request (GtkWidget *widget, - GtkRequisition *requisition) +static void zbar_gtk_size_request (GtkWidget *widget, + GtkRequisition *requisition) { - ZebraGtk *self = ZEBRA_GTK(widget); + ZBarGtk *self = ZBAR_GTK(widget); if(!self->_private) return; - ZebraGtkPrivate *zebra = ZEBRA_GTK_PRIVATE(self->_private); + ZBarGtkPrivate *zbar = ZBAR_GTK_PRIVATE(self->_private); /* use native video size (max) if available, * arbitrary defaults otherwise. * video attributes maintained under main gui thread lock */ - requisition->width = zebra->req_width; - requisition->height = zebra->req_height; + requisition->width = zbar->req_width; + requisition->height = zbar->req_height; } -static void zebra_gtk_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) +static void zbar_gtk_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) { - ZebraGtk *self = ZEBRA_GTK(widget); + ZBarGtk *self = ZBAR_GTK(widget); if(!self->_private) return; - ZebraGtkPrivate *zebra = ZEBRA_GTK_PRIVATE(self->_private); + ZBarGtkPrivate *zbar = ZBAR_GTK_PRIVATE(self->_private); - (*GTK_WIDGET_CLASS(zebra_gtk_parent_class)->size_allocate) + (*GTK_WIDGET_CLASS(zbar_gtk_parent_class)->size_allocate) (widget, allocation); - if(zebra->window) - zebra_window_resize(zebra->window, + if(zbar->window) + zbar_window_resize(zbar->window, allocation->width, allocation->height); } -static gboolean zebra_gtk_expose (GtkWidget *widget, - GdkEventExpose *event) +static gboolean zbar_gtk_expose (GtkWidget *widget, + GdkEventExpose *event) { - ZebraGtk *self = ZEBRA_GTK(widget); + ZBarGtk *self = ZBAR_GTK(widget); if(!self->_private) return(FALSE); - ZebraGtkPrivate *zebra = ZEBRA_GTK_PRIVATE(self->_private); + ZBarGtkPrivate *zbar = ZBAR_GTK_PRIVATE(self->_private); if(GTK_WIDGET_VISIBLE(widget) && GTK_WIDGET_MAPPED(widget) && - zebra_window_redraw(zebra->window)) + zbar_window_redraw(zbar->window)) return(TRUE); return(FALSE); } -void zebra_gtk_scan_image (ZebraGtk *self, - GdkPixbuf *img) +void zbar_gtk_scan_image (ZBarGtk *self, + GdkPixbuf *img) { if(!self->_private) return; - ZebraGtkPrivate *zebra = ZEBRA_GTK_PRIVATE(self->_private); + ZBarGtkPrivate *zbar = ZBAR_GTK_PRIVATE(self->_private); g_object_ref(G_OBJECT(img)); /* queue for scanning by the processor thread */ - GValue *msg = zebra_gtk_new_value(GDK_TYPE_PIXBUF); + GValue *msg = zbar_gtk_new_value(GDK_TYPE_PIXBUF); /* this grabs a new reference to the image, * eventually released by the processor thread */ g_value_set_object(msg, img); - g_async_queue_push(zebra->queue, msg); + g_async_queue_push(zbar->queue, msg); } -const char *zebra_gtk_get_video_device (ZebraGtk *self) +const char *zbar_gtk_get_video_device (ZBarGtk *self) { if(!self->_private) return(NULL); - ZebraGtkPrivate *zebra = ZEBRA_GTK_PRIVATE(self->_private); - if(zebra->video_device) - return(zebra->video_device); + ZBarGtkPrivate *zbar = ZBAR_GTK_PRIVATE(self->_private); + if(zbar->video_device) + return(zbar->video_device); else return(""); } -void zebra_gtk_set_video_device (ZebraGtk *self, - const char *video_device) +void zbar_gtk_set_video_device (ZBarGtk *self, + const char *video_device) { if(!self->_private) return; - ZebraGtkPrivate *zebra = ZEBRA_GTK_PRIVATE(self->_private); + ZBarGtkPrivate *zbar = ZBAR_GTK_PRIVATE(self->_private); - g_free((void*)zebra->video_device); - zebra->video_device = g_strdup(video_device); - zebra->video_enabled = video_device && video_device[0]; + g_free((void*)zbar->video_device); + zbar->video_device = g_strdup(video_device); + zbar->video_enabled = video_device && video_device[0]; /* push another copy to processor thread */ - GValue *msg = zebra_gtk_new_value(G_TYPE_STRING); + GValue *msg = zbar_gtk_new_value(G_TYPE_STRING); if(video_device) g_value_set_string(msg, video_device); else g_value_set_static_string(msg, ""); - g_async_queue_push(zebra->queue, msg); + g_async_queue_push(zbar->queue, msg); g_object_freeze_notify(G_OBJECT(self)); g_object_notify(G_OBJECT(self), "video-device"); @@ -517,180 +517,180 @@ void zebra_gtk_set_video_device (ZebraGtk *self, g_object_thaw_notify(G_OBJECT(self)); } -gboolean zebra_gtk_get_video_enabled (ZebraGtk *self) +gboolean zbar_gtk_get_video_enabled (ZBarGtk *self) { if(!self->_private) return(FALSE); - ZebraGtkPrivate *zebra = ZEBRA_GTK_PRIVATE(self->_private); - return(zebra->video_enabled); + ZBarGtkPrivate *zbar = ZBAR_GTK_PRIVATE(self->_private); + return(zbar->video_enabled); } -void zebra_gtk_set_video_enabled (ZebraGtk *self, - gboolean video_enabled) +void zbar_gtk_set_video_enabled (ZBarGtk *self, + gboolean video_enabled) { if(!self->_private) return; - ZebraGtkPrivate *zebra = ZEBRA_GTK_PRIVATE(self->_private); + ZBarGtkPrivate *zbar = ZBAR_GTK_PRIVATE(self->_private); video_enabled = (video_enabled != FALSE); - if(zebra->video_enabled != video_enabled) { - zebra->video_enabled = video_enabled; + if(zbar->video_enabled != video_enabled) { + zbar->video_enabled = video_enabled; /* push state change to processor thread */ - GValue *msg = zebra_gtk_new_value(G_TYPE_INT); - g_value_set_int(msg, zebra->video_enabled); - g_async_queue_push(zebra->queue, msg); + GValue *msg = zbar_gtk_new_value(G_TYPE_INT); + g_value_set_int(msg, zbar->video_enabled); + g_async_queue_push(zbar->queue, msg); g_object_notify(G_OBJECT(self), "video-enabled"); } } -gboolean zebra_gtk_get_video_opened (ZebraGtk *self) +gboolean zbar_gtk_get_video_opened (ZBarGtk *self) { if(!self->_private) return(FALSE); - ZebraGtkPrivate *zebra = ZEBRA_GTK_PRIVATE(self->_private); - return(zebra->video_opened); + ZBarGtkPrivate *zbar = ZBAR_GTK_PRIVATE(self->_private); + return(zbar->video_opened); } -static void zebra_gtk_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) +static void zbar_gtk_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) { - ZebraGtk *self = ZEBRA_GTK(object); + ZBarGtk *self = ZBAR_GTK(object); switch(prop_id) { case PROP_VIDEO_DEVICE: - zebra_gtk_set_video_device(self, g_value_get_string(value)); + zbar_gtk_set_video_device(self, g_value_get_string(value)); break; case PROP_VIDEO_ENABLED: - zebra_gtk_set_video_enabled(self, g_value_get_boolean(value)); + zbar_gtk_set_video_enabled(self, g_value_get_boolean(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); } } -static void zebra_gtk_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) +static void zbar_gtk_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) { - ZebraGtk *self = ZEBRA_GTK(object); + ZBarGtk *self = ZBAR_GTK(object); if(!self->_private) return; - ZebraGtkPrivate *zebra = ZEBRA_GTK_PRIVATE(self->_private); + ZBarGtkPrivate *zbar = ZBAR_GTK_PRIVATE(self->_private); switch(prop_id) { case PROP_VIDEO_DEVICE: - if(zebra->video_device) - g_value_set_string(value, zebra->video_device); + if(zbar->video_device) + g_value_set_string(value, zbar->video_device); else g_value_set_static_string(value, ""); break; case PROP_VIDEO_ENABLED: - g_value_set_boolean(value, zebra->video_enabled); + g_value_set_boolean(value, zbar->video_enabled); break; case PROP_VIDEO_OPENED: - g_value_set_boolean(value, zebra->video_opened); + g_value_set_boolean(value, zbar->video_opened); default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); } } -static void zebra_gtk_init (ZebraGtk *self) +static void zbar_gtk_init (ZBarGtk *self) { - ZebraGtkPrivate *zebra = g_object_new(ZEBRA_TYPE_GTK_PRIVATE, NULL); - self->_private = (void*)zebra; + ZBarGtkPrivate *zbar = g_object_new(ZBAR_TYPE_GTK_PRIVATE, NULL); + self->_private = (void*)zbar; - zebra->window = zebra_window_create(); - g_assert(zebra->window); + zbar->window = zbar_window_create(); + g_assert(zbar->window); - zebra->req_width = DEFAULT_WIDTH; - zebra->req_height = DEFAULT_HEIGHT; + zbar->req_width = DEFAULT_WIDTH; + zbar->req_height = DEFAULT_HEIGHT; /* spawn a thread to handle decoding and video */ - zebra->queue = g_async_queue_new(); - zebra->thread = g_thread_create(zebra_gtk_processing_thread, self, + zbar->queue = g_async_queue_new(); + zbar->thread = g_thread_create(zbar_gtk_processing_thread, self, FALSE, NULL); - g_assert(zebra->thread); + g_assert(zbar->thread); } -static void zebra_gtk_dispose (GObject *object) +static void zbar_gtk_dispose (GObject *object) { - ZebraGtk *self = ZEBRA_GTK(object); + ZBarGtk *self = ZBAR_GTK(object); if(!self->_private) return; - ZebraGtkPrivate *zebra = ZEBRA_GTK_PRIVATE(self->_private); + ZBarGtkPrivate *zbar = ZBAR_GTK_PRIVATE(self->_private); self->_private = NULL; - g_free((void*)zebra->video_device); - zebra->video_device = NULL; + g_free((void*)zbar->video_device); + zbar->video_device = NULL; /* signal processor thread to exit */ - GValue *msg = zebra_gtk_new_value(G_TYPE_INT); + GValue *msg = zbar_gtk_new_value(G_TYPE_INT); g_value_set_int(msg, -1); - g_async_queue_push(zebra->queue, msg); - zebra->thread = NULL; + g_async_queue_push(zbar->queue, msg); + zbar->thread = NULL; /* there are no external references which might call other APIs */ - g_async_queue_unref(zebra->queue); + g_async_queue_unref(zbar->queue); - g_object_unref(G_OBJECT(zebra)); + g_object_unref(G_OBJECT(zbar)); } -static void zebra_gtk_private_finalize (GObject *object) +static void zbar_gtk_private_finalize (GObject *object) { - ZebraGtkPrivate *zebra = ZEBRA_GTK_PRIVATE(object); - if(zebra->window) { - zebra_window_destroy(zebra->window); - zebra->window = NULL; + ZBarGtkPrivate *zbar = ZBAR_GTK_PRIVATE(object); + if(zbar->window) { + zbar_window_destroy(zbar->window); + zbar->window = NULL; } - if(zebra->scanner) { - zebra_image_scanner_destroy(zebra->scanner); - zebra->scanner = NULL; + if(zbar->scanner) { + zbar_image_scanner_destroy(zbar->scanner); + zbar->scanner = NULL; } - if(zebra->video) { - zebra_video_destroy(zebra->video); - zebra->video = NULL; + if(zbar->video) { + zbar_video_destroy(zbar->video); + zbar->video = NULL; } - g_async_queue_unref(zebra->queue); - zebra->queue = NULL; + g_async_queue_unref(zbar->queue); + zbar->queue = NULL; } -static void zebra_gtk_class_init (ZebraGtkClass *klass) +static void zbar_gtk_class_init (ZBarGtkClass *klass) { - zebra_gtk_parent_class = g_type_class_peek_parent(klass); + zbar_gtk_parent_class = g_type_class_peek_parent(klass); GObjectClass *object_class = G_OBJECT_CLASS(klass); - object_class->dispose = zebra_gtk_dispose; - object_class->set_property = zebra_gtk_set_property; - object_class->get_property = zebra_gtk_get_property; + object_class->dispose = zbar_gtk_dispose; + object_class->set_property = zbar_gtk_set_property; + object_class->get_property = zbar_gtk_get_property; GtkWidgetClass *widget_class = (GtkWidgetClass*)klass; - widget_class->realize = zebra_gtk_realize; - widget_class->unrealize = zebra_gtk_unrealize; - widget_class->size_request = zebra_gtk_size_request; - widget_class->size_allocate = zebra_gtk_size_allocate; - widget_class->expose_event = zebra_gtk_expose; + widget_class->realize = zbar_gtk_realize; + widget_class->unrealize = zbar_gtk_unrealize; + widget_class->size_request = zbar_gtk_size_request; + widget_class->size_allocate = zbar_gtk_size_allocate; + widget_class->expose_event = zbar_gtk_expose; widget_class->unmap = NULL; - zebra_gtk_signals[DECODED] = + zbar_gtk_signals[DECODED] = g_signal_new("decoded", G_TYPE_FROM_CLASS(object_class), G_SIGNAL_RUN_CLEANUP, - G_STRUCT_OFFSET(ZebraGtkClass, decoded), + G_STRUCT_OFFSET(ZBarGtkClass, decoded), NULL, NULL, - zebra_marshal_VOID__INT_STRING, + zbar_marshal_VOID__INT_STRING, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING); - zebra_gtk_signals[DECODED_TEXT] = + zbar_gtk_signals[DECODED_TEXT] = g_signal_new("decoded-text", G_TYPE_FROM_CLASS(object_class), G_SIGNAL_RUN_CLEANUP, - G_STRUCT_OFFSET(ZebraGtkClass, decoded_text), + G_STRUCT_OFFSET(ZBarGtkClass, decoded_text), NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, @@ -718,50 +718,50 @@ static void zebra_gtk_class_init (ZebraGtkClass *klass) g_object_class_install_property(object_class, PROP_VIDEO_OPENED, p); } -GType zebra_gtk_get_type () +GType zbar_gtk_get_type () { static GType type = 0; if(!type) { static const GTypeInfo info = { - sizeof(ZebraGtkClass), + sizeof(ZBarGtkClass), NULL, /* base_init */ NULL, /* base_finalize */ - (GClassInitFunc)zebra_gtk_class_init, + (GClassInitFunc)zbar_gtk_class_init, NULL, /* class_finalize */ NULL, /* class_data */ - sizeof(ZebraGtk), + sizeof(ZBarGtk), 0, - (GInstanceInitFunc)zebra_gtk_init, + (GInstanceInitFunc)zbar_gtk_init, }; - type = g_type_register_static(GTK_TYPE_WIDGET, "ZebraGtk", &info, 0); + type = g_type_register_static(GTK_TYPE_WIDGET, "ZBarGtk", &info, 0); } return(type); } -static void zebra_gtk_private_class_init (ZebraGtkPrivateClass *klass) +static void zbar_gtk_private_class_init (ZBarGtkPrivateClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); - object_class->finalize = zebra_gtk_private_finalize; + object_class->finalize = zbar_gtk_private_finalize; } -static GType zebra_gtk_private_get_type () +static GType zbar_gtk_private_get_type () { static GType type = 0; if(!type) { static const GTypeInfo info = { - sizeof(ZebraGtkPrivateClass), + sizeof(ZBarGtkPrivateClass), NULL, NULL, - (GClassInitFunc)zebra_gtk_private_class_init, + (GClassInitFunc)zbar_gtk_private_class_init, NULL, NULL, - sizeof(ZebraGtkPrivate), + sizeof(ZBarGtkPrivate), }; - type = g_type_register_static(G_TYPE_OBJECT, "ZebraGtkPrivate", + type = g_type_register_static(G_TYPE_OBJECT, "ZBarGtkPrivate", &info, 0); } return(type); } -GtkWidget *zebra_gtk_new () +GtkWidget *zbar_gtk_new () { - return(GTK_WIDGET(g_object_new(ZEBRA_TYPE_GTK, NULL))); + return(GTK_WIDGET(g_object_new(ZBAR_TYPE_GTK, NULL))); } diff --git a/gtk/zebragtkprivate.h b/gtk/zbargtkprivate.h similarity index 58% rename from gtk/zebragtkprivate.h rename to gtk/zbargtkprivate.h index 2375d81..7832e76 100644 --- a/gtk/zebragtkprivate.h +++ b/gtk/zbargtkprivate.h @@ -1,51 +1,51 @@ /*------------------------------------------------------------------------ - * Copyright 2008 (c) Jeff Brown + * Copyright 2008-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ -#ifndef __ZEBRA_GTK_PRIVATE_H__ -#define __ZEBRA_GTK_PRIVATE_H__ +#ifndef __ZBAR_GTK_PRIVATE_H__ +#define __ZBAR_GTK_PRIVATE_H__ #include #include #include -#include +#include G_BEGIN_DECLS -#define ZEBRA_TYPE_GTK_PRIVATE (zebra_gtk_private_get_type()) -#define ZEBRA_GTK_PRIVATE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), ZEBRA_TYPE_GTK_PRIVATE, ZebraGtkPrivate)) -#define ZEBRA_GTK_PRIVATE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), ZEBRA_TYPE_GTK_PRIVATE, ZebraGtkPrivateClass)) -#define ZEBRA_IS_GTK_PRIVATE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), ZEBRA_TYPE_GTK_PRIVATE)) -#define ZEBRA_IS_GTK_PRIVATE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), ZEBRA_TYPE_GTK_PRIVATE)) -#define ZEBRA_GTK_PRIVATE_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), ZEBRA_TYPE_GTK_PRIVATE, ZebraGtkPrivateClass)) - - -/* zebra widget processor thread shared/private data */ -typedef struct _ZebraGtkPrivate +#define ZBAR_TYPE_GTK_PRIVATE (zbar_gtk_private_get_type()) +#define ZBAR_GTK_PRIVATE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), ZBAR_TYPE_GTK_PRIVATE, ZBarGtkPrivate)) +#define ZBAR_GTK_PRIVATE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), ZBAR_TYPE_GTK_PRIVATE, ZBarGtkPrivateClass)) +#define ZBAR_IS_GTK_PRIVATE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), ZBAR_TYPE_GTK_PRIVATE)) +#define ZBAR_IS_GTK_PRIVATE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), ZBAR_TYPE_GTK_PRIVATE)) +#define ZBAR_GTK_PRIVATE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), ZBAR_TYPE_GTK_PRIVATE, ZBarGtkPrivateClass)) + + +/* zbar widget processor thread shared/private data */ +typedef struct _ZBarGtkPrivate { GObject object; @@ -77,23 +77,23 @@ typedef struct _ZebraGtkPrivate * processor thread only calls draw() and negotiate_format(). * protected by main gui lock (and internal lock) */ - zebra_window_t *window; + zbar_window_t *window; /* video and scanner are owned by the processor thread */ - zebra_video_t *video; - zebra_image_scanner_t *scanner; + zbar_video_t *video; + zbar_image_scanner_t *scanner; -} ZebraGtkPrivate; +} ZBarGtkPrivate; -typedef struct _ZebraGtkPrivateClass +typedef struct _ZBarGtkPrivateClass { GObjectClass parent_class; -} ZebraGtkPrivateClass; +} ZBarGtkPrivateClass; -static GType zebra_gtk_private_get_type() G_GNUC_CONST; +static GType zbar_gtk_private_get_type() G_GNUC_CONST; G_END_DECLS diff --git a/gtk/zebramarshal.list b/gtk/zbarmarshal.list similarity index 100% rename from gtk/zebramarshal.list rename to gtk/zbarmarshal.list diff --git a/include/Makefile.am.inc b/include/Makefile.am.inc index 3efa39c..a782b29 100644 --- a/include/Makefile.am.inc +++ b/include/Makefile.am.inc @@ -1,13 +1,13 @@ -zincludedir = $(includedir)/zebra -include_HEADERS = include/zebra.h -zinclude_HEADERS = include/zebra/Scanner.h include/zebra/Decoder.h \ - include/zebra/Exception.h include/zebra/Symbol.h include/zebra/Image.h \ - include/zebra/ImageScanner.h include/zebra/Video.h include/zebra/Window.h \ - include/zebra/Processor.h +zincludedir = $(includedir)/zbar +include_HEADERS = include/zbar.h +zinclude_HEADERS = include/zbar/Scanner.h include/zbar/Decoder.h \ + include/zbar/Exception.h include/zbar/Symbol.h include/zbar/Image.h \ + include/zbar/ImageScanner.h include/zbar/Video.h include/zbar/Window.h \ + include/zbar/Processor.h if HAVE_GTK -zinclude_HEADERS += include/zebra/zebragtk.h +zinclude_HEADERS += include/zbar/zbargtk.h endif if HAVE_QT -zinclude_HEADERS += include/zebra/QZebra.h include/zebra/QZebraImage.h +zinclude_HEADERS += include/zbar/QZBar.h include/zbar/QZBarImage.h endif diff --git a/include/zebra.h b/include/zbar.h similarity index 52% rename from include/zebra.h rename to include/zbar.h index bbd5eaf..7bb9572 100644 --- a/include/zebra.h +++ b/include/zbar.h @@ -1,30 +1,30 @@ /*------------------------------------------------------------------------ * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ -#ifndef _ZEBRA_H_ -#define _ZEBRA_H_ +#ifndef _ZBAR_H_ +#define _ZBAR_H_ /** @file - * Zebra Barcode Reader Library C API definition + * ZBar Barcode Reader C API definition */ /** @mainpage @@ -38,37 +38,37 @@ * package for a specific toolkit: * - the "GTK+ 2.x widget" may be used with GTK GUI applications. a * Python wrapper is included for PyGtk - * - the @ref zebra::QZebra "Qt4 widget" may be used with Qt GUI + * - the @ref zbar::QZBar "Qt4 widget" may be used with Qt GUI * applications * - the Processor interface (in @ref c-processor "C" or @ref - * zebra::Processor "C++") adds a scanning window to an application + * zbar::Processor "C++") adds a scanning window to an application * with no GUI. * * @section mid-level Intermediate Interfaces * * building blocks used to construct high-level interfaces: * - the ImageScanner (in @ref c-imagescanner "C" or @ref - * zebra::ImageScanner "C++") looks for barcodes in a library defined + * zbar::ImageScanner "C++") looks for barcodes in a library defined * image object * - the Window abstraction (in @ref c-window "C" or @ref - * zebra::Window "C++") sinks library images, displaying them on the + * zbar::Window "C++") sinks library images, displaying them on the * platform display - * - the Video abstraction (in @ref c-video "C" or @ref zebra::Video + * - the Video abstraction (in @ref c-video "C" or @ref zbar::Video * "C++") sources library images from a video device * * @section low-level Low-Level Interfaces * * direct interaction with barcode scanning and decoding: - * - the Scanner (in @ref c-scanner "C" or @ref zebra::Scanner "C++") + * - the Scanner (in @ref c-scanner "C" or @ref zbar::Scanner "C++") * looks for barcodes in a linear intensity sample stream - * - the Decoder (in @ref c-decoder "C" or @ref zebra::Decoder "C++") + * - the Decoder (in @ref c-decoder "C" or @ref zbar::Decoder "C++") * extracts barcodes from a stream of bar and space widths */ #ifdef __cplusplus /** C++ namespace for library interfaces */ -namespace zebra { +namespace zbar { extern "C" { #endif @@ -77,95 +77,95 @@ namespace zebra { /*@{*/ /** "color" of element: bar or space. */ -typedef enum zebra_color_e { - ZEBRA_SPACE = 0, /**< light area or space between bars */ - ZEBRA_BAR = 1, /**< dark area or colored bar segment */ -} zebra_color_t; +typedef enum zbar_color_e { + ZBAR_SPACE = 0, /**< light area or space between bars */ + ZBAR_BAR = 1, /**< dark area or colored bar segment */ +} zbar_color_t; /** decoded symbol type. */ -typedef enum zebra_symbol_type_e { - ZEBRA_NONE = 0, /**< no symbol decoded */ - ZEBRA_PARTIAL = 1, /**< intermediate status */ - ZEBRA_EAN8 = 8, /**< EAN-8 */ - ZEBRA_UPCE = 9, /**< UPC-E */ - ZEBRA_ISBN10 = 10, /**< ISBN-10 (from EAN-13). @since 0.4 */ - ZEBRA_UPCA = 12, /**< UPC-A */ - ZEBRA_EAN13 = 13, /**< EAN-13 */ - ZEBRA_ISBN13 = 14, /**< ISBN-13 (from EAN-13). @since 0.4 */ - ZEBRA_I25 = 25, /**< Interleaved 2 of 5. @since 0.4 */ - ZEBRA_CODE39 = 39, /**< Code 39. @since 0.4 */ - ZEBRA_PDF417 = 57, /**< PDF417. @since 0.6 */ - ZEBRA_CODE128 = 128, /**< Code 128 */ - ZEBRA_SYMBOL = 0x00ff, /**< mask for base symbol type */ - ZEBRA_ADDON2 = 0x0200, /**< 2-digit add-on flag */ - ZEBRA_ADDON5 = 0x0500, /**< 5-digit add-on flag */ - ZEBRA_ADDON = 0x0700, /**< add-on flag mask */ -} zebra_symbol_type_t; +typedef enum zbar_symbol_type_e { + ZBAR_NONE = 0, /**< no symbol decoded */ + ZBAR_PARTIAL = 1, /**< intermediate status */ + 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_I25 = 25, /**< Interleaved 2 of 5. @since 0.4 */ + ZBAR_CODE39 = 39, /**< Code 39. @since 0.4 */ + ZBAR_PDF417 = 57, /**< PDF417. @since 0.6 */ + 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 */ +} zbar_symbol_type_t; /** error codes. */ -typedef enum zebra_error_e { - ZEBRA_OK = 0, /**< no error */ - ZEBRA_ERR_NOMEM, /**< out of memory */ - ZEBRA_ERR_INTERNAL, /**< internal library error */ - ZEBRA_ERR_UNSUPPORTED, /**< unsupported request */ - ZEBRA_ERR_INVALID, /**< invalid request */ - ZEBRA_ERR_SYSTEM, /**< system error */ - ZEBRA_ERR_LOCKING, /**< locking error */ - ZEBRA_ERR_BUSY, /**< all resources busy */ - ZEBRA_ERR_XDISPLAY, /**< X11 display error */ - ZEBRA_ERR_XPROTO, /**< X11 protocol error */ - ZEBRA_ERR_CLOSED, /**< output window is closed */ - ZEBRA_ERR_NUM /**< number of error codes */ -} zebra_error_t; +typedef enum zbar_error_e { + ZBAR_OK = 0, /**< no error */ + ZBAR_ERR_NOMEM, /**< out of memory */ + ZBAR_ERR_INTERNAL, /**< internal library error */ + ZBAR_ERR_UNSUPPORTED, /**< unsupported request */ + ZBAR_ERR_INVALID, /**< invalid request */ + ZBAR_ERR_SYSTEM, /**< system error */ + ZBAR_ERR_LOCKING, /**< locking error */ + ZBAR_ERR_BUSY, /**< all resources busy */ + ZBAR_ERR_XDISPLAY, /**< X11 display error */ + ZBAR_ERR_XPROTO, /**< X11 protocol error */ + ZBAR_ERR_CLOSED, /**< output window is closed */ + ZBAR_ERR_NUM /**< number of error codes */ +} zbar_error_t; /** decoder configuration options. * @since 0.4 */ -typedef enum zebra_config_e { - ZEBRA_CFG_ENABLE = 0, /**< enable symbology/feature */ - ZEBRA_CFG_ADD_CHECK, /**< enable check digit when optional */ - ZEBRA_CFG_EMIT_CHECK, /**< return check digit when present */ - ZEBRA_CFG_ASCII, /**< enable full ASCII character set */ - ZEBRA_CFG_NUM, /**< number of boolean configs */ +typedef enum zbar_config_e { + ZBAR_CFG_ENABLE = 0, /**< enable symbology/feature */ + ZBAR_CFG_ADD_CHECK, /**< enable check digit when optional */ + ZBAR_CFG_EMIT_CHECK, /**< return check digit when present */ + ZBAR_CFG_ASCII, /**< enable full ASCII character set */ + ZBAR_CFG_NUM, /**< number of boolean configs */ - ZEBRA_CFG_MIN_LEN = 0x20, /**< minimum data length for valid decode */ - ZEBRA_CFG_MAX_LEN, /**< maximum data length for valid decode */ + ZBAR_CFG_MIN_LEN = 0x20, /**< minimum data length for valid decode */ + ZBAR_CFG_MAX_LEN, /**< maximum data length for valid decode */ - ZEBRA_CFG_X_DENSITY = 0x100,/**< image scanner vertical scan density */ - ZEBRA_CFG_Y_DENSITY, /**< image scanner horizontal scan density */ -} zebra_config_t; + ZBAR_CFG_X_DENSITY = 0x100, /**< image scanner vertical scan density */ + ZBAR_CFG_Y_DENSITY, /**< image scanner horizontal scan density */ +} zbar_config_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) * @returns 0 */ -extern int zebra_version(unsigned *major, - unsigned *minor); +extern int zbar_version(unsigned *major, + unsigned *minor); /** set global library debug level. * @param verbosity desired debug level. higher values create more spew */ -extern void zebra_set_verbosity(int verbosity); +extern void zbar_set_verbosity(int verbosity); /** increase global library debug level. * eg, for -vvvv */ -extern void zebra_increase_verbosity(); +extern void zbar_increase_verbosity(); /** retrieve string name for symbol encoding. * @param sym symbol type encoding * @returns the static string name for the specified symbol type, * or "UNKNOWN" if the encoding is not recognized */ -extern const char *zebra_get_symbol_name(zebra_symbol_type_t sym); +extern const char *zbar_get_symbol_name(zbar_symbol_type_t sym); /** retrieve string name for addon encoding. * @param sym symbol type encoding * @returns static string name for any addon, or the empty string * if no addons were decoded */ -extern const char *zebra_get_addon_name(zebra_symbol_type_t sym); +extern const char *zbar_get_addon_name(zbar_symbol_type_t sym); /** parse a configuration string of the form "[symbology.]config[=value]". * the config must match one of the recognized names. @@ -175,17 +175,17 @@ extern const char *zebra_get_addon_name(zebra_symbol_type_t sym); * @returns 0 if the config is parsed successfully, 1 otherwise * @since 0.4 */ -extern int zebra_parse_config(const char *config_string, - zebra_symbol_type_t *symbology, - zebra_config_t *config, - int *value); +extern int zbar_parse_config(const char *config_string, + zbar_symbol_type_t *symbology, + zbar_config_t *config, + int *value); /** @internal type unsafe error API (don't use) */ -extern int _zebra_error_spew(const void *object, - int verbosity); -extern const char *_zebra_error_string(const void *object, - int verbosity); -extern zebra_error_t _zebra_get_error_code(const void *object); +extern int _zbar_error_spew(const void *object, + int verbosity); +extern const char *_zbar_error_string(const void *object, + int verbosity); +extern zbar_error_t _zbar_get_error_code(const void *object); /*@}*/ @@ -197,19 +197,19 @@ extern zebra_error_t _zebra_get_error_code(const void *object); */ /*@{*/ -struct zebra_symbol_s; +struct zbar_symbol_s; /** opaque decoded symbol object. */ -typedef struct zebra_symbol_s zebra_symbol_t; +typedef struct zbar_symbol_s zbar_symbol_t; /** retrieve type of decoded symbol. * @returns the symbol type */ -extern zebra_symbol_type_t zebra_symbol_get_type(const zebra_symbol_t *symbol); +extern zbar_symbol_type_t zbar_symbol_get_type(const zbar_symbol_t *symbol); /** retrieve ASCII data decoded from symbol. * @returns the data string */ -extern const char *zebra_symbol_get_data(const zebra_symbol_t *symbol); +extern const char *zbar_symbol_get_data(const zbar_symbol_t *symbol); /** retrieve current cache count. when the cache is enabled for the * image_scanner this provides inter-frame reliability and redundancy @@ -218,7 +218,7 @@ extern const char *zebra_symbol_get_data(const zebra_symbol_t *symbol); * @returns 0 if symbol is newly verified. * @returns > 0 for duplicate symbols */ -extern int zebra_symbol_get_count(const zebra_symbol_t *symbol); +extern int zbar_symbol_get_count(const zbar_symbol_t *symbol); /** retrieve the number of points in the location polygon. the * location polygon defines the image area that the symbol was @@ -227,32 +227,32 @@ extern int zebra_symbol_get_count(const zebra_symbol_t *symbol); * @note this is currently not a polygon, but the scan locations * where the symbol was decoded */ -extern unsigned zebra_symbol_get_loc_size(const zebra_symbol_t *symbol); +extern unsigned zbar_symbol_get_loc_size(const zbar_symbol_t *symbol); /** retrieve location polygon x-coordinates. * points are specified by 0-based index. * @returns the x-coordinate for a point in the location polygon. * @returns -1 if index is out of range */ -extern int zebra_symbol_get_loc_x(const zebra_symbol_t *symbol, - unsigned index); +extern int zbar_symbol_get_loc_x(const zbar_symbol_t *symbol, + unsigned index); /** retrieve location polygon y-coordinates. * points are specified by 0-based index. * @returns the y-coordinate for a point in the location polygon. * @returns -1 if index is out of range */ -extern int zebra_symbol_get_loc_y(const zebra_symbol_t *symbol, - unsigned index); +extern int zbar_symbol_get_loc_y(const zbar_symbol_t *symbol, + unsigned index); /** iterate the result set. * @returns the next result symbol, or * @returns NULL when no more results are available */ -extern const zebra_symbol_t *zebra_symbol_next(const zebra_symbol_t *symbol); +extern const zbar_symbol_t *zbar_symbol_next(const zbar_symbol_t *symbol); /** print XML symbol element representation to user result buffer. - * @see http://zebra.sourceforge.net/2008/barcode.xsd for the schema. + * @see http://zbar.sourceforge.net/2008/barcode.xsd for the schema. * @param symbol is the symbol to print * @param buffer is the inout result pointer, it will be reallocated * with a larger size if necessary. @@ -260,9 +260,9 @@ extern const zebra_symbol_t *zebra_symbol_next(const zebra_symbol_t *symbol); * @returns the buffer pointer * @since 0.6 */ -extern char *zebra_symbol_xml(const zebra_symbol_t *symbol, - char **buffer, - unsigned *buflen); +extern char *zbar_symbol_xml(const zbar_symbol_t *symbol, + char **buffer, + unsigned *buflen); /*@}*/ @@ -273,27 +273,27 @@ extern char *zebra_symbol_xml(const zebra_symbol_t *symbol, */ /*@{*/ -struct zebra_image_s; +struct zbar_image_s; /** opaque image object. */ -typedef struct zebra_image_s zebra_image_t; +typedef struct zbar_image_s zbar_image_t; /** cleanup handler callback function. * called to free sample data when an image is destroyed. */ -typedef void (zebra_image_cleanup_handler_t)(zebra_image_t *image); +typedef void (zbar_image_cleanup_handler_t)(zbar_image_t *image); /** data handler callback function. * called when decoded symbol results are available for an image */ -typedef void (zebra_image_data_handler_t)(zebra_image_t *image, - const void *userdata); +typedef void (zbar_image_data_handler_t)(zbar_image_t *image, + const void *userdata); /** new image constructor. * @returns a new image object with uninitialized data and format. - * this image should be destroyed (using zebra_image_destroy()) as + * this image should be destroyed (using zbar_image_destroy()) as * soon as the application is finished with it */ -extern zebra_image_t *zebra_image_create(); +extern zbar_image_t *zbar_image_create(); /** image destructor. all images created by or returned to the * application should be destroyed using this function. when an image @@ -304,17 +304,17 @@ extern zebra_image_t *zebra_image_create(); * is still using them. if necessary, use the cleanup handler hook * to keep track of image data buffers */ -extern void zebra_image_destroy(zebra_image_t *image); +extern void zbar_image_destroy(zbar_image_t *image); /** image reference count manipulation. * increment the reference count when you store a new reference to the * image. decrement when the reference is no longer used. do not * refer to the image any longer once the count is decremented. - * zebra_image_ref(image, -1) is the same as zebra_image_destroy(image) + * zbar_image_ref(image, -1) is the same as zbar_image_destroy(image) * @since 0.5 */ -extern void zebra_image_ref(zebra_image_t *image, - int refs); +extern void zbar_image_ref(zbar_image_t *image, + int refs); /** image format conversion. refer to the documentation for supported * image formats @@ -324,8 +324,8 @@ extern void zebra_image_ref(zebra_image_t *image, * @note the converted image size may be rounded (up) due to format * constraints */ -extern zebra_image_t *zebra_image_convert(const zebra_image_t *image, - unsigned long format); +extern zbar_image_t *zbar_image_convert(const zbar_image_t *image, + unsigned long format); /** image format conversion with crop/pad. * if the requested size is larger than the image, the last row/column @@ -335,97 +335,97 @@ extern zebra_image_t *zebra_image_convert(const zebra_image_t *image, * @returns a @em new image with the sample data from the original * image converted to the requested format and size. * @note the image is @em not scaled - * @see zebra_image_convert() + * @see zbar_image_convert() * @since 0.4 */ -extern zebra_image_t *zebra_image_convert_resize(const zebra_image_t *image, - unsigned long format, - unsigned width, - unsigned height); +extern zbar_image_t *zbar_image_convert_resize(const zbar_image_t *image, + unsigned long format, + unsigned width, + unsigned height); /** retrieve the image format. * @returns the fourcc describing the format of the image sample data */ -extern unsigned long zebra_image_get_format(const zebra_image_t *image); +extern unsigned long zbar_image_get_format(const zbar_image_t *image); /** retrieve a "sequence" (page/frame) number associated with this image. * @since 0.6 */ -extern unsigned zebra_image_get_sequence(const zebra_image_t *image); +extern unsigned zbar_image_get_sequence(const zbar_image_t *image); /** retrieve the width of the image. * @returns the width in sample columns */ -extern unsigned zebra_image_get_width(const zebra_image_t *image); +extern unsigned zbar_image_get_width(const zbar_image_t *image); /** retrieve the height of the image. * @returns the height in sample rows */ -extern unsigned zebra_image_get_height(const zebra_image_t *image); +extern unsigned zbar_image_get_height(const zbar_image_t *image); /** return the image sample data. the returned data buffer is only - * valid until zebra_image_destroy() is called + * valid until zbar_image_destroy() is called */ -extern const void *zebra_image_get_data(const zebra_image_t *image); +extern const void *zbar_image_get_data(const zbar_image_t *image); /** return the size of image data. * @since 0.6 */ -unsigned long zebra_image_get_data_length(const zebra_image_t *img); +unsigned long zbar_image_get_data_length(const zbar_image_t *img); /** image_scanner decode result iterator. * @returns the first decoded symbol result for an image * or NULL if no results are available */ -extern const zebra_symbol_t* -zebra_image_first_symbol(const zebra_image_t *image); +extern const zbar_symbol_t* +zbar_image_first_symbol(const zbar_image_t *image); /** specify the fourcc image format code for image sample data. * refer to the documentation for supported formats. * @note this does not convert the data! - * (see zebra_image_convert() for that) + * (see zbar_image_convert() for that) */ -extern void zebra_image_set_format(zebra_image_t *image, - unsigned long format); +extern void zbar_image_set_format(zbar_image_t *image, + unsigned long format); /** associate a "sequence" (page/frame) number with this image. * @since 0.6 */ -extern void zebra_image_set_sequence(zebra_image_t *image, - unsigned sequence_num); +extern void zbar_image_set_sequence(zbar_image_t *image, + unsigned sequence_num); /** specify the pixel size of the image. * @note this does not affect the data! */ -extern void zebra_image_set_size(zebra_image_t *image, - unsigned width, - unsigned height); +extern void zbar_image_set_size(zbar_image_t *image, + 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) * @note application image data will not be modified by the library */ -extern void zebra_image_set_data(zebra_image_t *image, - const void *data, - unsigned long data_byte_length, - zebra_image_cleanup_handler_t *cleanup_hndlr); +extern void zbar_image_set_data(zbar_image_t *image, + const void *data, + unsigned long data_byte_length, + zbar_image_cleanup_handler_t *cleanup_hndlr); /** built-in cleanup handler. * passes the image data buffer to free() */ -extern void zebra_image_free_data(zebra_image_t *image); +extern void zbar_image_free_data(zbar_image_t *image); /** associate user specified data value with an image. * @since 0.5 */ -extern void zebra_image_set_userdata(zebra_image_t *image, - void *userdata); +extern void zbar_image_set_userdata(zbar_image_t *image, + void *userdata); /** return user specified data value associated with the image. * @since 0.5 */ -extern void *zebra_image_get_userdata(const zebra_image_t *image); +extern void *zbar_image_get_userdata(const zbar_image_t *image); /** dump raw image data to a file for debug. * the data will be prefixed with a 16 byte header consisting of: @@ -450,13 +450,13 @@ extern void *zebra_image_get_userdata(const zebra_image_t *image); * XXXX is the format fourcc * @returns 0 on success or a system error code on failure */ -extern int zebra_image_write(const zebra_image_t *image, - const char *filebase); +extern int zbar_image_write(const zbar_image_t *image, + const char *filebase); -/** read back an image in the format written by zebra_image_write() +/** read back an image in the format written by zbar_image_write() * @note TBD */ -extern zebra_image_t *zebra_image_read(char *filename); +extern zbar_image_t *zbar_image_read(char *filename); /*@}*/ @@ -469,44 +469,44 @@ extern zebra_image_t *zebra_image_read(char *filename); */ /*@{*/ -struct zebra_processor_s; +struct zbar_processor_s; /** opaque standalone processor object. */ -typedef struct zebra_processor_s zebra_processor_t; +typedef struct zbar_processor_s zbar_processor_t; /** constructor. * if threaded is set and threading is available the processor * will spawn threads where appropriate to avoid blocking and * improve responsiveness */ -extern zebra_processor_t *zebra_processor_create(int threaded); +extern zbar_processor_t *zbar_processor_create(int threaded); /** destructor. cleans up all resources associated with the processor */ -extern void zebra_processor_destroy(zebra_processor_t *processor); +extern void zbar_processor_destroy(zbar_processor_t *processor); /** (re)initialization. * opens a video input device and/or prepares to display output */ -extern int zebra_processor_init(zebra_processor_t *processor, - const char *video_device, - int enable_display); +extern int zbar_processor_init(zbar_processor_t *processor, + const char *video_device, + int enable_display); /** request a preferred size for the video image from the device. * the request may be adjusted or completely ignored by the driver. - * @note must be called before zebra_processor_init() + * @note must be called before zbar_processor_init() * @since 0.6 */ -extern int zebra_processor_request_size(zebra_processor_t *processor, - unsigned width, - unsigned height); +extern int zbar_processor_request_size(zbar_processor_t *processor, + unsigned width, + unsigned height); /** request a preferred video driver interface version for * debug/testing. - * @note must be called before zebra_processor_init() + * @note must be called before zbar_processor_init() * @since 0.6 */ -extern int zebra_processor_request_interface(zebra_processor_t *processor, - int version); +extern int zbar_processor_request_interface(zbar_processor_t *processor, + int version); /** request a preferred video I/O mode for debug/testing. You will * get errors if the driver does not support the specified mode. @@ -516,18 +516,18 @@ extern int zebra_processor_request_interface(zebra_processor_t *processor, 2 = force memory mapped I/O using mmap() 3 = force USERPTR I/O (v4l2 only) @endverbatim - * @note must be called before zebra_processor_init() + * @note must be called before zbar_processor_init() * @since 0.7 */ -extern int zebra_processor_request_iomode(zebra_processor_t *video, - int iomode); +extern int zbar_processor_request_iomode(zbar_processor_t *video, + int iomode); /** force specific input and output formats for debug/testing. - * @note must be called before zebra_processor_init() + * @note must be called before zbar_processor_init() */ -extern int zebra_processor_force_format(zebra_processor_t *processor, - unsigned long input_format, - unsigned long output_format); +extern int zbar_processor_force_format(zbar_processor_t *processor, + unsigned long input_format, + unsigned long output_format); /** setup result handler callback. * the specified function will be called by the processor whenever @@ -535,86 +535,86 @@ extern int zebra_processor_force_format(zebra_processor_t *processor, * pass a NULL value to disable callbacks. * @param processor the object on which to set the handler. * @param handler the function to call when new results are available. - * @param userdata is set as with zebra_processor_set_userdata(). + * @param userdata is set as with zbar_processor_set_userdata(). * @returns the previously registered handler */ -extern zebra_image_data_handler_t* -zebra_processor_set_data_handler(zebra_processor_t *processor, - zebra_image_data_handler_t *handler, - const void *userdata); +extern zbar_image_data_handler_t* +zbar_processor_set_data_handler(zbar_processor_t *processor, + zbar_image_data_handler_t *handler, + const void *userdata); /** associate user specified data value with the processor. * @since 0.6 */ -extern void zebra_processor_set_userdata(zebra_processor_t *processor, - void *userdata); +extern void zbar_processor_set_userdata(zbar_processor_t *processor, + void *userdata); /** return user specified data value associated with the processor. * @since 0.6 */ -extern void *zebra_processor_get_userdata(const zebra_processor_t *processor); +extern void *zbar_processor_get_userdata(const zbar_processor_t *processor); /** set config for indicated symbology (0 for all) to specified value. * @returns 0 for success, non-0 for failure (config does not apply to * specified symbology, or value out of range) - * @see zebra_decoder_set_config() + * @see zbar_decoder_set_config() * @since 0.4 */ -extern int zebra_processor_set_config(zebra_processor_t *processor, - zebra_symbol_type_t symbology, - zebra_config_t config, - int value); +extern int zbar_processor_set_config(zbar_processor_t *processor, + zbar_symbol_type_t symbology, + zbar_config_t config, + int value); -/** parse configuration string using zebra_parse_config() - * and apply to processor using zebra_processor_set_config(). +/** parse configuration string using zbar_parse_config() + * and apply to processor using zbar_processor_set_config(). * @returns 0 for success, non-0 for failure - * @see zebra_parse_config() - * @see zebra_processor_set_config() + * @see zbar_parse_config() + * @see zbar_processor_set_config() * @since 0.4 */ -static inline int zebra_processor_parse_config (zebra_processor_t *processor, - const char *config_string) +static inline int zbar_processor_parse_config (zbar_processor_t *processor, + const char *config_string) { - zebra_symbol_type_t sym; - zebra_config_t cfg; + zbar_symbol_type_t sym; + zbar_config_t cfg; int val; - return(zebra_parse_config(config_string, &sym, &cfg, &val) || - zebra_processor_set_config(processor, sym, cfg, val)); + return(zbar_parse_config(config_string, &sym, &cfg, &val) || + zbar_processor_set_config(processor, sym, cfg, val)); } /** retrieve the current state of the ouput window. * @returns 1 if the output window is currently displayed, 0 if not. * @returns -1 if an error occurs */ -extern int zebra_processor_is_visible(zebra_processor_t *processor); +extern int zbar_processor_is_visible(zbar_processor_t *processor); /** show or hide the display window owned by the library. * the size will be adjusted to the input size */ -extern int zebra_processor_set_visible(zebra_processor_t *processor, - int visible); +extern int zbar_processor_set_visible(zbar_processor_t *processor, + int visible); /** control the processor in free running video mode. * only works if video input is initialized. if threading is in use, * scanning will occur in the background, otherwise this is only - * useful wrapping calls to zebra_processor_user_wait(). if the + * useful wrapping calls to zbar_processor_user_wait(). if the * library output window is visible, video display will be enabled. */ -extern int zebra_processor_set_active(zebra_processor_t *processor, - int active); +extern int zbar_processor_set_active(zbar_processor_t *processor, + int active); /** wait for input to the display window from the user * (via mouse or keyboard). * @returns >0 when input is received, 0 if timeout ms expired * with no input or -1 in case of an error */ -extern int zebra_processor_user_wait(zebra_processor_t *processor, - int timeout); +extern int zbar_processor_user_wait(zbar_processor_t *processor, + int timeout); /** process from the video stream until a result is available, * or the timeout (in milliseconds) expires. * specify a timeout of -1 to scan indefinitely - * (zebra_processor_set_active() may still be used to abort the scan + * (zbar_processor_set_active() may still be used to abort the scan * from another thread). * if the library window is visible, video display will be enabled. * @note that multiple results may still be returned (despite the @@ -623,40 +623,40 @@ extern int zebra_processor_user_wait(zebra_processor_t *processor, * 0 if no symbols were found (ie, the timeout expired) * or -1 if an error occurs */ -extern int zebra_process_one(zebra_processor_t *processor, - int timeout); +extern int zbar_process_one(zbar_processor_t *processor, + int timeout); /** process the provided image for barcodes. * if the library window is visible, the image will be displayed. * @returns >0 if symbols were successfully decoded, * 0 if no symbols were found or -1 if an error occurs */ -extern int zebra_process_image(zebra_processor_t *processor, - zebra_image_t *image); +extern int zbar_process_image(zbar_processor_t *processor, + zbar_image_t *image); /** display detail for last processor error to stderr. * @returns a non-zero value suitable for passing to exit() */ static inline int -zebra_processor_error_spew (const zebra_processor_t *processor, - int verbosity) +zbar_processor_error_spew (const zbar_processor_t *processor, + int verbosity) { - return(_zebra_error_spew(processor, verbosity)); + return(_zbar_error_spew(processor, verbosity)); } /** retrieve the detail string for the last processor error. */ static inline const char* -zebra_processor_error_string (const zebra_processor_t *processor, - int verbosity) +zbar_processor_error_string (const zbar_processor_t *processor, + int verbosity) { - return(_zebra_error_string(processor, verbosity)); + return(_zbar_error_string(processor, verbosity)); } /** retrieve the type code for the last processor error. */ -static inline zebra_error_t -zebra_processor_get_error_code (const zebra_processor_t *processor) +static inline zbar_error_t +zbar_processor_get_error_code (const zbar_processor_t *processor) { - return(_zebra_get_error_code(processor)); + return(_zbar_get_error_code(processor)); } /*@}*/ @@ -669,15 +669,15 @@ zebra_processor_get_error_code (const zebra_processor_t *processor) */ /*@{*/ -struct zebra_video_s; +struct zbar_video_s; /** opaque video object. */ -typedef struct zebra_video_s zebra_video_t; +typedef struct zbar_video_s zbar_video_t; /** constructor. */ -extern zebra_video_t *zebra_video_create(); +extern zbar_video_t *zbar_video_create(); /** destructor. */ -extern void zebra_video_destroy(zebra_video_t *video); +extern void zbar_video_destroy(zbar_video_t *video); /** open and probe a video device. * the device specified by platform specific unique name @@ -685,8 +685,8 @@ extern void zebra_video_destroy(zebra_video_t *video); * DirectShow DevicePath property in windows). * @returns 0 if successful or -1 if an error occurs */ -extern int zebra_video_open(zebra_video_t *video, - const char *device); +extern int zbar_video_open(zbar_video_t *video, + const char *device); /** retrieve file descriptor associated with open *nix video device * useful for using select()/poll() to tell when new images are @@ -694,7 +694,7 @@ extern int zebra_video_open(zebra_video_t *video, * @returns the file descriptor or -1 if the video device is not open * or the driver only supports v4l1 */ -extern int zebra_video_get_fd(const zebra_video_t *video); +extern int zbar_video_get_fd(const zbar_video_t *video); /** request a preferred size for the video image from the device. * the request may be adjusted or completely ignored by the driver. @@ -702,16 +702,16 @@ extern int zebra_video_get_fd(const zebra_video_t *video); * initialized * @since 0.6 */ -extern int zebra_video_request_size(zebra_video_t *video, - unsigned width, - unsigned height); +extern int zbar_video_request_size(zbar_video_t *video, + unsigned width, + unsigned height); /** request a preferred driver interface version for debug/testing. - * @note must be called before zebra_video_open() + * @note must be called before zbar_video_open() * @since 0.6 */ -extern int zebra_video_request_interface(zebra_video_t *video, - int version); +extern int zbar_video_request_interface(zbar_video_t *video, + int version); /** request a preferred I/O mode for debug/testing. You will get * errors if the driver does not support the specified mode. @@ -721,62 +721,62 @@ extern int zebra_video_request_interface(zebra_video_t *video, 2 = force memory mapped I/O using mmap() 3 = force USERPTR I/O (v4l2 only) @endverbatim - * @note must be called before zebra_video_open() + * @note must be called before zbar_video_open() * @since 0.7 */ -extern int zebra_video_request_iomode(zebra_video_t *video, - int iomode); +extern int zbar_video_request_iomode(zbar_video_t *video, + int iomode); /** retrieve current output image width. * @returns the width or 0 if the video device is not open */ -extern int zebra_video_get_width(const zebra_video_t *video); +extern int zbar_video_get_width(const zbar_video_t *video); /** retrieve current output image height. * @returns the height or 0 if the video device is not open */ -extern int zebra_video_get_height(const zebra_video_t *video); +extern int zbar_video_get_height(const zbar_video_t *video); /** initialize video using a specific format for debug. - * use zebra_negotiate_format() to automatically select and initialize + * use zbar_negotiate_format() to automatically select and initialize * the best available format */ -extern int zebra_video_init(zebra_video_t *video, - unsigned long format); +extern int zbar_video_init(zbar_video_t *video, + unsigned long format); /** start/stop video capture. * all buffered images are retired when capture is disabled. * @returns 0 if successful or -1 if an error occurs */ -extern int zebra_video_enable(zebra_video_t *video, - int enable); +extern int zbar_video_enable(zbar_video_t *video, + int enable); /** retrieve next captured image. blocks until an image is available. * @returns NULL if video is not enabled or an error occurs */ -extern zebra_image_t *zebra_video_next_image(zebra_video_t *video); +extern zbar_image_t *zbar_video_next_image(zbar_video_t *video); /** display detail for last video error to stderr. * @returns a non-zero value suitable for passing to exit() */ -static inline int zebra_video_error_spew (const zebra_video_t *video, - int verbosity) +static inline int zbar_video_error_spew (const zbar_video_t *video, + int verbosity) { - return(_zebra_error_spew(video, verbosity)); + return(_zbar_error_spew(video, verbosity)); } /** retrieve the detail string for the last video error. */ -static inline const char *zebra_video_error_string (const zebra_video_t *video, - int verbosity) +static inline const char *zbar_video_error_string (const zbar_video_t *video, + int verbosity) { - return(_zebra_error_string(video, verbosity)); + return(_zbar_error_string(video, verbosity)); } /** retrieve the type code for the last video error. */ -static inline zebra_error_t -zebra_video_get_error_code (const zebra_video_t *video) +static inline zbar_error_t +zbar_video_get_error_code (const zbar_video_t *video) { - return(_zebra_get_error_code(video)); + return(_zbar_get_error_code(video)); } /*@}*/ @@ -789,15 +789,15 @@ zebra_video_get_error_code (const zebra_video_t *video) */ /*@{*/ -struct zebra_window_s; +struct zbar_window_s; /** opaque window object. */ -typedef struct zebra_window_s zebra_window_t; +typedef struct zbar_window_s zbar_window_t; /** constructor. */ -extern zebra_window_t *zebra_window_create(); +extern zbar_window_t *zbar_window_create(); /** destructor. */ -extern void zebra_window_destroy(zebra_window_t *window); +extern void zbar_window_destroy(zbar_window_t *window); /** associate reader with an existing platform window. * This can be any "Drawable" for X Windows or a "HWND" for windows. @@ -805,9 +805,9 @@ extern void zebra_window_destroy(zebra_window_t *window); * pass NULL to detach from the resource, further input will be * ignored */ -extern int zebra_window_attach(zebra_window_t *window, - void *x11_display_w32_hwnd, - unsigned long x11_drawable); +extern int zbar_window_attach(zbar_window_t *window, + void *x11_display_w32_hwnd, + unsigned long x11_drawable); /** control content level of the reader overlay. * the overlay displays graphical data for informational or debug @@ -818,46 +818,46 @@ extern int zebra_window_attach(zebra_window_t *window, 2 = also track and display input frame rate @endverbatim */ -extern void zebra_window_set_overlay(zebra_window_t *window, - int level); +extern void zbar_window_set_overlay(zbar_window_t *window, + int level); /** draw a new image into the output window. */ -extern int zebra_window_draw(zebra_window_t *window, - zebra_image_t *image); +extern int zbar_window_draw(zbar_window_t *window, + zbar_image_t *image); /** redraw the last image (exposure handler). */ -extern int zebra_window_redraw(zebra_window_t *window); +extern int zbar_window_redraw(zbar_window_t *window); /** resize the image window (reconfigure handler). * this does @em not update the contents of the window * @since 0.3, changed in 0.4 to not redraw window */ -extern int zebra_window_resize(zebra_window_t *window, - unsigned width, - unsigned height); +extern int zbar_window_resize(zbar_window_t *window, + unsigned width, + unsigned height); /** display detail for last window error to stderr. * @returns a non-zero value suitable for passing to exit() */ -static inline int zebra_window_error_spew (const zebra_window_t *window, - int verbosity) +static inline int zbar_window_error_spew (const zbar_window_t *window, + int verbosity) { - return(_zebra_error_spew(window, verbosity)); + return(_zbar_error_spew(window, verbosity)); } /** retrieve the detail string for the last window error. */ static inline const char* -zebra_window_error_string (const zebra_window_t *window, - int verbosity) +zbar_window_error_string (const zbar_window_t *window, + int verbosity) { - return(_zebra_error_string(window, verbosity)); + return(_zbar_error_string(window, verbosity)); } /** retrieve the type code for the last window error. */ -static inline zebra_error_t -zebra_window_get_error_code (const zebra_window_t *window) +static inline zbar_error_t +zbar_window_get_error_code (const zbar_window_t *window) { - return(_zebra_get_error_code(window)); + return(_zbar_get_error_code(window)); } @@ -867,8 +867,8 @@ zebra_window_get_error_code (const zebra_window_t *window) * barcode scanning. if a format conversion is necessary, it will * heuristically attempt to minimize the cost of the conversion */ -extern int zebra_negotiate_format(zebra_video_t *video, - zebra_window_t *window); +extern int zbar_negotiate_format(zbar_video_t *video, + zbar_window_t *window); /*@}*/ @@ -880,15 +880,15 @@ extern int zebra_negotiate_format(zebra_video_t *video, */ /*@{*/ -struct zebra_image_scanner_s; +struct zbar_image_scanner_s; /** opaque image scanner object. */ -typedef struct zebra_image_scanner_s zebra_image_scanner_t; +typedef struct zbar_image_scanner_s zbar_image_scanner_t; /** constructor. */ -extern zebra_image_scanner_t *zebra_image_scanner_create(); +extern zbar_image_scanner_t *zbar_image_scanner_create(); /** destructor. */ -extern void zebra_image_scanner_destroy(zebra_image_scanner_t *scanner); +extern void zbar_image_scanner_destroy(zbar_image_scanner_t *scanner); /** setup result handler callback. * the specified function will be called by the scanner whenever @@ -896,39 +896,39 @@ extern void zebra_image_scanner_destroy(zebra_image_scanner_t *scanner); * pass a NULL value to disable callbacks. * @returns the previously registered handler */ -extern zebra_image_data_handler_t* -zebra_image_scanner_set_data_handler(zebra_image_scanner_t *scanner, - zebra_image_data_handler_t *handler, - const void *userdata); +extern zbar_image_data_handler_t* +zbar_image_scanner_set_data_handler(zbar_image_scanner_t *scanner, + zbar_image_data_handler_t *handler, + const void *userdata); /** set config for indicated symbology (0 for all) to specified value. * @returns 0 for success, non-0 for failure (config does not apply to * specified symbology, or value out of range) - * @see zebra_decoder_set_config() + * @see zbar_decoder_set_config() * @since 0.4 */ -extern int zebra_image_scanner_set_config(zebra_image_scanner_t *scanner, - zebra_symbol_type_t symbology, - zebra_config_t config, - int value); +extern int zbar_image_scanner_set_config(zbar_image_scanner_t *scanner, + zbar_symbol_type_t symbology, + zbar_config_t config, + int value); -/** parse configuration string using zebra_parse_config() - * and apply to image scanner using zebra_image_scanner_set_config(). +/** parse configuration string using zbar_parse_config() + * and apply to image scanner using zbar_image_scanner_set_config(). * @returns 0 for success, non-0 for failure - * @see zebra_parse_config() - * @see zebra_image_scanner_set_config() + * @see zbar_parse_config() + * @see zbar_image_scanner_set_config() * @since 0.4 */ static inline int -zebra_image_scanner_parse_config (zebra_image_scanner_t *scanner, - const char *config_string) +zbar_image_scanner_parse_config (zbar_image_scanner_t *scanner, + const char *config_string) { - zebra_symbol_type_t sym; - zebra_config_t cfg; + zbar_symbol_type_t sym; + zbar_config_t cfg; int val; - return(zebra_parse_config(config_string, &sym, &cfg, &val) || - zebra_image_scanner_set_config(scanner, sym, cfg, val)); + return(zbar_parse_config(config_string, &sym, &cfg, &val) || + zbar_image_scanner_set_config(scanner, sym, cfg, val)); } /** enable or disable the inter-image result cache (default disabled). @@ -937,15 +937,15 @@ zebra_image_scanner_parse_config (zebra_image_scanner_t *scanner, * consistency checking and hysteresis to the results. * this interface also clears the cache */ -extern void zebra_image_scanner_enable_cache(zebra_image_scanner_t *scanner, - int enable); +extern void zbar_image_scanner_enable_cache(zbar_image_scanner_t *scanner, + int enable); /** scan for symbols in provided image. * @returns >0 if symbols were successfully decoded from the image, * 0 if no symbols were found or -1 if an error occurs */ -extern int zebra_scan_image(zebra_image_scanner_t *scanner, - zebra_image_t *image); +extern int zbar_scan_image(zbar_image_scanner_t *scanner, + zbar_image_t *image); /*@}*/ @@ -957,104 +957,104 @@ extern int zebra_scan_image(zebra_image_scanner_t *scanner, */ /*@{*/ -struct zebra_decoder_s; +struct zbar_decoder_s; /** opaque decoder object. */ -typedef struct zebra_decoder_s zebra_decoder_t; +typedef struct zbar_decoder_s zbar_decoder_t; /** decoder data handler callback function. * called by decoder when new data has just been decoded */ -typedef void (zebra_decoder_handler_t)(zebra_decoder_t *decoder); +typedef void (zbar_decoder_handler_t)(zbar_decoder_t *decoder); /** constructor. */ -extern zebra_decoder_t *zebra_decoder_create(); +extern zbar_decoder_t *zbar_decoder_create(); /** destructor. */ -extern void zebra_decoder_destroy(zebra_decoder_t *decoder); +extern void zbar_decoder_destroy(zbar_decoder_t *decoder); /** set config for indicated symbology (0 for all) to specified value. * @returns 0 for success, non-0 for failure (config does not apply to * specified symbology, or value out of range) * @since 0.4 */ -extern int zebra_decoder_set_config(zebra_decoder_t *decoder, - zebra_symbol_type_t symbology, - zebra_config_t config, - int value); +extern int zbar_decoder_set_config(zbar_decoder_t *decoder, + zbar_symbol_type_t symbology, + zbar_config_t config, + int value); -/** parse configuration string using zebra_parse_config() - * and apply to decoder using zebra_decoder_set_config(). +/** parse configuration string using zbar_parse_config() + * and apply to decoder using zbar_decoder_set_config(). * @returns 0 for success, non-0 for failure - * @see zebra_parse_config() - * @see zebra_decoder_set_config() + * @see zbar_parse_config() + * @see zbar_decoder_set_config() * @since 0.4 */ -static inline int zebra_decoder_parse_config (zebra_decoder_t *decoder, - const char *config_string) +static inline int zbar_decoder_parse_config (zbar_decoder_t *decoder, + const char *config_string) { - zebra_symbol_type_t sym; - zebra_config_t cfg; + zbar_symbol_type_t sym; + zbar_config_t cfg; int val; - return(zebra_parse_config(config_string, &sym, &cfg, &val) || - zebra_decoder_set_config(decoder, sym, cfg, val)); + return(zbar_parse_config(config_string, &sym, &cfg, &val) || + zbar_decoder_set_config(decoder, sym, cfg, val)); } /** clear all decoder state. * any partial symbols are flushed */ -extern void zebra_decoder_reset(zebra_decoder_t *decoder); +extern void zbar_decoder_reset(zbar_decoder_t *decoder); /** mark start of a new scan pass. - * clears any intra-symbol state and resets color to ::ZEBRA_SPACE. + * clears any intra-symbol state and resets color to ::ZBAR_SPACE. * any partially decoded symbol state is retained */ -extern void zebra_decoder_new_scan(zebra_decoder_t *decoder); +extern void zbar_decoder_new_scan(zbar_decoder_t *decoder); /** process next bar/space width from input stream. * the width is in arbitrary relative units. first value of a scan - * is ::ZEBRA_SPACE width, alternating from there. + * is ::ZBAR_SPACE width, alternating from there. * @returns appropriate symbol type if width completes * decode of a symbol (data is available for retrieval) - * @returns ::ZEBRA_PARTIAL as a hint if part of a symbol was decoded - * @returns ::ZEBRA_NONE (0) if no new symbol data is available + * @returns ::ZBAR_PARTIAL as a hint if part of a symbol was decoded + * @returns ::ZBAR_NONE (0) if no new symbol data is available */ -extern zebra_symbol_type_t zebra_decode_width(zebra_decoder_t *decoder, - unsigned width); +extern zbar_symbol_type_t zbar_decode_width(zbar_decoder_t *decoder, + unsigned width); /** retrieve color of @em next element passed to - * zebra_decode_width(). */ -extern zebra_color_t zebra_decoder_get_color(const zebra_decoder_t *decoder); + * zbar_decode_width(). */ +extern zbar_color_t zbar_decoder_get_color(const zbar_decoder_t *decoder); /** retrieve last decoded data in ASCII format. * @returns the data string or NULL if no new data available. * the returned data buffer is owned by library, contents are only - * valid between non-0 return from zebra_decode_width and next library + * valid between non-0 return from zbar_decode_width and next library * call */ -extern const char *zebra_decoder_get_data(const zebra_decoder_t *decoder); +extern const char *zbar_decoder_get_data(const zbar_decoder_t *decoder); /** retrieve last decoded symbol type. - * @returns the type or ::ZEBRA_NONE if no new data available + * @returns the type or ::ZBAR_NONE if no new data available */ -extern zebra_symbol_type_t -zebra_decoder_get_type(const zebra_decoder_t *decoder); +extern zbar_symbol_type_t +zbar_decoder_get_type(const zbar_decoder_t *decoder); /** setup data handler callback. * the registered function will be called by the decoder - * just before zebra_decode_width() returns a non-zero value. + * just before zbar_decode_width() returns a non-zero value. * pass a NULL value to disable callbacks. * @returns the previously registered handler */ -extern zebra_decoder_handler_t* -zebra_decoder_set_handler(zebra_decoder_t *decoder, - zebra_decoder_handler_t *handler); +extern zbar_decoder_handler_t* +zbar_decoder_set_handler(zbar_decoder_t *decoder, + zbar_decoder_handler_t *handler); /** associate user specified data value with the decoder. */ -extern void zebra_decoder_set_userdata(zebra_decoder_t *decoder, - void *userdata); +extern void zbar_decoder_set_userdata(zbar_decoder_t *decoder, + void *userdata); /** return user specified data value associated with the decoder. */ -extern void *zebra_decoder_get_userdata(const zebra_decoder_t *decoder); +extern void *zbar_decoder_get_userdata(const zbar_decoder_t *decoder); /*@}*/ @@ -1067,55 +1067,55 @@ extern void *zebra_decoder_get_userdata(const zebra_decoder_t *decoder); */ /*@{*/ -struct zebra_scanner_s; +struct zbar_scanner_s; /** opaque scanner object. */ -typedef struct zebra_scanner_s zebra_scanner_t; +typedef struct zbar_scanner_s zbar_scanner_t; /** constructor. * if decoder is non-NULL it will be attached to scanner * and called automatically at each new edge - * current color is initialized to ::ZEBRA_SPACE + * current color is initialized to ::ZBAR_SPACE * (so an initial BAR->SPACE transition may be discarded) */ -extern zebra_scanner_t *zebra_scanner_create(zebra_decoder_t *decoder); +extern zbar_scanner_t *zbar_scanner_create(zbar_decoder_t *decoder); /** destructor. */ -extern void zebra_scanner_destroy(zebra_scanner_t *scanner); +extern void zbar_scanner_destroy(zbar_scanner_t *scanner); /** clear all scanner state. * also resets an associated decoder */ -extern zebra_symbol_type_t zebra_scanner_reset(zebra_scanner_t *scanner); +extern zbar_symbol_type_t zbar_scanner_reset(zbar_scanner_t *scanner); -/** mark start of a new scan pass. resets color to ::ZEBRA_SPACE. +/** mark start of a new scan pass. resets color to ::ZBAR_SPACE. * also updates an associated decoder. * @returns any decode results flushed from the pipeline * @note when not using callback handlers, the return value should - * be checked the same as zebra_scan_y() + * be checked the same as zbar_scan_y() */ -extern zebra_symbol_type_t zebra_scanner_new_scan(zebra_scanner_t *scanner); +extern zbar_symbol_type_t zbar_scanner_new_scan(zbar_scanner_t *scanner); /** process next sample intensity value. * intensity (y) is in arbitrary relative units. - * @returns result of zebra_decode_width() if a decoder is attached, - * otherwise @returns (::ZEBRA_PARTIAL) when new edge is detected - * or 0 (::ZEBRA_NONE) if no new edge is detected + * @returns result of zbar_decode_width() if a decoder is attached, + * otherwise @returns (::ZBAR_PARTIAL) when new edge is detected + * or 0 (::ZBAR_NONE) if no new edge is detected */ -extern zebra_symbol_type_t zebra_scan_y(zebra_scanner_t *scanner, - int y); +extern zbar_symbol_type_t zbar_scan_y(zbar_scanner_t *scanner, + int y); /** process next sample from RGB (or BGR) triple. */ -static inline zebra_symbol_type_t zebra_scan_rgb24 (zebra_scanner_t *scanner, +static inline zbar_symbol_type_t zbar_scan_rgb24 (zbar_scanner_t *scanner, unsigned char *rgb) { - return(zebra_scan_y(scanner, rgb[0] + rgb[1] + rgb[2])); + return(zbar_scan_y(scanner, rgb[0] + rgb[1] + rgb[2])); } /** retrieve last scanned width. */ -extern unsigned zebra_scanner_get_width(const zebra_scanner_t *scanner); +extern unsigned zbar_scanner_get_width(const zbar_scanner_t *scanner); /** retrieve last scanned color. */ -extern zebra_color_t zebra_scanner_get_color(const zebra_scanner_t *scanner); +extern zbar_color_t zbar_scanner_get_color(const zbar_scanner_t *scanner); /*@}*/ @@ -1123,15 +1123,15 @@ extern zebra_color_t zebra_scanner_get_color(const zebra_scanner_t *scanner); } } -# include "zebra/Exception.h" -# include "zebra/Decoder.h" -# include "zebra/Scanner.h" -# include "zebra/Symbol.h" -# include "zebra/Image.h" -# include "zebra/ImageScanner.h" -# include "zebra/Video.h" -# include "zebra/Window.h" -# include "zebra/Processor.h" +# include "zbar/Exception.h" +# include "zbar/Decoder.h" +# include "zbar/Scanner.h" +# include "zbar/Symbol.h" +# include "zbar/Image.h" +# include "zbar/ImageScanner.h" +# include "zbar/Video.h" +# include "zbar/Window.h" +# include "zbar/Processor.h" #endif #endif diff --git a/include/zebra/Decoder.h b/include/zbar/Decoder.h similarity index 56% rename from include/zebra/Decoder.h rename to include/zbar/Decoder.h index 65b60d6..2c5ce78 100644 --- a/include/zebra/Decoder.h +++ b/include/zbar/Decoder.h @@ -1,38 +1,38 @@ //------------------------------------------------------------------------ -// Copyright 2007-2008 (c) Jeff Brown +// Copyright 2007-2009 (c) Jeff Brown // -// This file is part of the Zebra Barcode Library. +// This file is part of the ZBar Bar Code Reader. // -// The Zebra Barcode Library is free software; you can redistribute it +// 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 Zebra Barcode Library is distributed in the hope that it will be +// 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 Zebra Barcode Library; if not, write to the Free +// 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/zebra +// http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#ifndef _ZEBRA_DECODER_H_ -#define _ZEBRA_DECODER_H_ +#ifndef _ZBAR_DECODER_H_ +#define _ZBAR_DECODER_H_ /// @file /// Decoder C++ wrapper -#ifndef _ZEBRA_H_ -# error "include zebra.h in your application, **not** zebra/Decoder.h" +#ifndef _ZBAR_H_ +# error "include zbar.h in your application, **not** zbar/Decoder.h" #endif #include -namespace zebra { +namespace zbar { /// low-level bar width stream decoder interface. /// identifies symbols and extracts encoded data @@ -55,126 +55,126 @@ class Decoder { Decoder () : _handler(NULL) { - _decoder = zebra_decoder_create(); + _decoder = zbar_decoder_create(); } ~Decoder () { - zebra_decoder_destroy(_decoder); + zbar_decoder_destroy(_decoder); } /// clear all decoder state. - /// see zebra_decoder_reset() + /// see zbar_decoder_reset() void reset () { - zebra_decoder_reset(_decoder); + zbar_decoder_reset(_decoder); } /// mark start of a new scan pass. - /// see zebra_decoder_new_scan() + /// see zbar_decoder_new_scan() void new_scan () { - zebra_decoder_new_scan(_decoder); + zbar_decoder_new_scan(_decoder); } /// process next bar/space width from input stream. - /// see zebra_decode_width() - zebra_symbol_type_t decode_width (unsigned width) + /// see zbar_decode_width() + zbar_symbol_type_t decode_width (unsigned width) { - return(zebra_decode_width(_decoder, width)); + return(zbar_decode_width(_decoder, width)); } /// process next bar/space width from input stream. - /// see zebra_decode_width() + /// see zbar_decode_width() Decoder& operator<< (unsigned width) { - zebra_decode_width(_decoder, width); + zbar_decode_width(_decoder, width); return(*this); } /// retrieve color of @em next element passed to Decoder. - /// see zebra_decoder_get_color() - zebra_color_t get_color () const + /// see zbar_decoder_get_color() + zbar_color_t get_color () const { - return(zebra_decoder_get_color(_decoder)); + return(zbar_decoder_get_color(_decoder)); } /// retrieve last decoded symbol type. - /// see zebra_decoder_get_type() - zebra_symbol_type_t get_type () const + /// see zbar_decoder_get_type() + zbar_symbol_type_t get_type () const { - return(zebra_decoder_get_type(_decoder)); + return(zbar_decoder_get_type(_decoder)); } /// retrieve string name of last decoded symbol type. - /// see zebra_get_symbol_name() + /// see zbar_get_symbol_name() const char *get_symbol_name () const { - return(zebra_get_symbol_name(zebra_decoder_get_type(_decoder))); + return(zbar_get_symbol_name(zbar_decoder_get_type(_decoder))); } /// retrieve string name for last decode addon. - /// see zebra_get_addon_name() + /// see zbar_get_addon_name() const char *get_addon_name () const { - return(zebra_get_addon_name(zebra_decoder_get_type(_decoder))); + return(zbar_get_addon_name(zbar_decoder_get_type(_decoder))); } /// retrieve last decoded data in ASCII format as a char array. - /// see zebra_decoder_get_data() + /// see zbar_decoder_get_data() const char *get_data_chars() const { - return(zebra_decoder_get_data(_decoder)); + return(zbar_decoder_get_data(_decoder)); } /// retrieve last decoded data in ASCII format as a std::string. - /// see zebra_decoder_get_data() + /// see zbar_decoder_get_data() const std::string get_data_string() const { - return(zebra_decoder_get_data(_decoder)); + return(zbar_decoder_get_data(_decoder)); } /// retrieve last decoded data in ASCII format as a std::string. - /// see zebra_decoder_get_data() + /// see zbar_decoder_get_data() const std::string get_data() const { - return(zebra_decoder_get_data(_decoder)); + return(zbar_decoder_get_data(_decoder)); } /// setup callback to handle result data. void set_handler (Handler &handler) { _handler = &handler; - zebra_decoder_set_handler(_decoder, _cb); - zebra_decoder_set_userdata(_decoder, this); + zbar_decoder_set_handler(_decoder, _cb); + zbar_decoder_set_userdata(_decoder, this); } /// set config for indicated symbology (0 for all) to specified value. - /// @see zebra_decoder_set_config() + /// @see zbar_decoder_set_config() /// @since 0.4 - int set_config (zebra_symbol_type_t symbology, - zebra_config_t config, + int set_config (zbar_symbol_type_t symbology, + zbar_config_t config, int value) { - return(zebra_decoder_set_config(_decoder, symbology, config, value)); + return(zbar_decoder_set_config(_decoder, symbology, config, value)); } /// set config parsed from configuration string. - /// @see zebra_decoder_parse_config() + /// @see zbar_decoder_parse_config() /// @since 0.4 int set_config (std::string cfgstr) { - return(zebra_decoder_parse_config(_decoder, cfgstr.c_str())); + return(zbar_decoder_parse_config(_decoder, cfgstr.c_str())); } private: friend class Scanner; - zebra_decoder_t *_decoder; + zbar_decoder_t *_decoder; Handler *_handler; - static void _cb (zebra_decoder_t *cdcode) + static void _cb (zbar_decoder_t *cdcode) { - Decoder *dcode = (Decoder*)zebra_decoder_get_userdata(cdcode); + Decoder *dcode = (Decoder*)zbar_decoder_get_userdata(cdcode); if(dcode && dcode->_handler) dcode->_handler->decode_callback(*dcode); } diff --git a/include/zebra/Exception.h b/include/zbar/Exception.h similarity index 79% rename from include/zebra/Exception.h rename to include/zbar/Exception.h index c18c2bd..236622f 100644 --- a/include/zebra/Exception.h +++ b/include/zbar/Exception.h @@ -1,39 +1,39 @@ //------------------------------------------------------------------------ -// Copyright 2007-2008 (c) Jeff Brown +// Copyright 2007-2009 (c) Jeff Brown // -// This file is part of the Zebra Barcode Library. +// This file is part of the ZBar Bar Code Reader. // -// The Zebra Barcode Library is free software; you can redistribute it +// 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 Zebra Barcode Library is distributed in the hope that it will be +// 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 Zebra Barcode Library; if not, write to the Free +// 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/zebra +// http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#ifndef _ZEBRA_EXCEPTION_H_ -#define _ZEBRA_EXCEPTION_H_ +#ifndef _ZBAR_EXCEPTION_H_ +#define _ZBAR_EXCEPTION_H_ /// @file /// C++ Exception definitions -#ifndef _ZEBRA_H_ -# error "include zebra.h in your application, **not** zebra/Exception.h" +#ifndef _ZBAR_H_ +# error "include zbar.h in your application, **not** zbar/Exception.h" #endif #include #include -namespace zebra { +namespace zbar { /// base class for exceptions defined by this API. class Exception : public std::exception { @@ -51,8 +51,8 @@ class Exception : public std::exception { virtual const char* what () const throw() { if(!_obj) - return("zebra library unspecified generic error"); - return(_zebra_error_string(_obj, 0)); + return("zbar library unspecified generic error"); + return(_zbar_error_string(_obj, 0)); } private: @@ -156,26 +156,26 @@ class FormatError : public Exception { /// extract error information and create exception. static inline std::exception throw_exception (const void *obj) { - switch(_zebra_get_error_code(obj)) { - case ZEBRA_ERR_NOMEM: + switch(_zbar_get_error_code(obj)) { + case ZBAR_ERR_NOMEM: throw std::bad_alloc(); - case ZEBRA_ERR_INTERNAL: + case ZBAR_ERR_INTERNAL: throw InternalError(obj); - case ZEBRA_ERR_UNSUPPORTED: + case ZBAR_ERR_UNSUPPORTED: throw UnsupportedError(obj); - case ZEBRA_ERR_INVALID: + case ZBAR_ERR_INVALID: throw InvalidError(obj); - case ZEBRA_ERR_SYSTEM: + case ZBAR_ERR_SYSTEM: throw SystemError(obj); - case ZEBRA_ERR_LOCKING: + case ZBAR_ERR_LOCKING: throw LockingError(obj); - case ZEBRA_ERR_BUSY: + case ZBAR_ERR_BUSY: throw BusyError(obj); - case ZEBRA_ERR_XDISPLAY: + case ZBAR_ERR_XDISPLAY: throw XDisplayError(obj); - case ZEBRA_ERR_XPROTO: + case ZBAR_ERR_XPROTO: throw XProtoError(obj); - case ZEBRA_ERR_CLOSED: + case ZBAR_ERR_CLOSED: throw ClosedError(obj); default: throw Exception(obj); diff --git a/include/zebra/Image.h b/include/zbar/Image.h similarity index 71% rename from include/zebra/Image.h rename to include/zbar/Image.h index c20dc92..387cb27 100644 --- a/include/zebra/Image.h +++ b/include/zbar/Image.h @@ -1,33 +1,33 @@ //------------------------------------------------------------------------ -// Copyright 2007-2008 (c) Jeff Brown +// Copyright 2007-2009 (c) Jeff Brown // -// This file is part of the Zebra Barcode Library. +// This file is part of the ZBar Bar Code Reader. // -// The Zebra Barcode Library is free software; you can redistribute it +// 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 Zebra Barcode Library is distributed in the hope that it will be +// 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 Zebra Barcode Library; if not, write to the Free +// 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/zebra +// http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#ifndef _ZEBRA_IMAGE_H_ -#define _ZEBRA_IMAGE_H_ +#ifndef _ZBAR_IMAGE_H_ +#define _ZBAR_IMAGE_H_ /// @file /// Image C++ wrapper -#ifndef _ZEBRA_H_ -# error "include zebra.h in your application, **not** zebra/Image.h" +#ifndef _ZBAR_H_ +# error "include zbar.h in your application, **not** zbar/Image.h" #endif #include @@ -35,7 +35,7 @@ #include "Symbol.h" #include "Exception.h" -namespace zebra { +namespace zbar { class Video; @@ -56,17 +56,17 @@ class Image { virtual void image_callback(Image &image) = 0; /// cast this handler to the C handler - operator zebra_image_data_handler_t* () const + operator zbar_image_data_handler_t* () const { return(_cb); } private: - static void _cb (zebra_image_t *zimg, + static void _cb (zbar_image_t *zimg, const void *userdata) { if(userdata) { - Image *image = (Image*)zebra_image_get_userdata(zimg); + Image *image = (Image*)zbar_image_get_userdata(zimg); ((Handler*)userdata)->image_callback(*image); } } @@ -81,7 +81,7 @@ class Image { SymbolIterator (const Image *img = NULL) { if(img) { - const zebra_symbol_t *zsym = zebra_image_first_symbol(*img); + const zbar_symbol_t *zsym = zbar_image_first_symbol(*img); _sym.init(zsym); } } @@ -94,9 +94,9 @@ class Image { /// advance iterator to next Symbol. SymbolIterator& operator++ () { - const zebra_symbol_t *zsym = _sym; + const zbar_symbol_t *zsym = _sym; if(zsym) { - zsym = zebra_symbol_next(zsym); + zsym = zbar_symbol_next(zsym); _sym.init(zsym); } return(*this); @@ -138,9 +138,9 @@ class Image { const std::string& format = "", const void *data = NULL, unsigned long length = 0) - : _img(zebra_image_create()) + : _img(zbar_image_create()) { - zebra_image_set_userdata(_img, this); + zbar_image_set_userdata(_img, this); if(width && height) set_size(width, height); if(format.length()) @@ -151,37 +151,37 @@ class Image { ~Image () { - zebra_image_ref(_img, -1); + zbar_image_ref(_img, -1); } /// cast to C image object - operator const zebra_image_t* () const + operator const zbar_image_t* () const { return(_img); } /// cast to C image object - operator zebra_image_t* () + operator zbar_image_t* () { return(_img); } /// retrieve the image format. - /// see zebra_image_get_format() + /// see zbar_image_get_format() unsigned long get_format () const { - return(zebra_image_get_format(_img)); + return(zbar_image_get_format(_img)); } /// specify the fourcc image format code for image sample data. - /// see zebra_image_set_format() + /// see zbar_image_set_format() void set_format (unsigned long format) { - zebra_image_set_format(_img, format); + zbar_image_set_format(_img, format); } /// specify the fourcc image format code for image sample data. - /// see zebra_image_set_format() + /// see zbar_image_set_format() void set_format (const std::string& format) { if(format.length() != 4) @@ -190,90 +190,90 @@ class Image { ((format[1] & 0xff) << 8) | ((format[2] & 0xff) << 16) | ((format[3] & 0xff) << 24)); - zebra_image_set_format(_img, fourcc); + zbar_image_set_format(_img, fourcc); } /// retrieve a "sequence" (page/frame) number associated with this /// image. - /// see zebra_image_get_sequence() + /// see zbar_image_get_sequence() /// @since 0.6 unsigned get_sequence () const { - return(zebra_image_get_sequence(_img)); + return(zbar_image_get_sequence(_img)); } /// associate a "sequence" (page/frame) number with this image. - /// see zebra_image_set_sequence() + /// see zbar_image_set_sequence() /// @since 0.6 void set_sequence (unsigned sequence_num) { - zebra_image_set_sequence(_img, sequence_num); + zbar_image_set_sequence(_img, sequence_num); } /// retrieve the width of the image. - /// see zebra_image_get_width() + /// see zbar_image_get_width() unsigned get_width () const { - return(zebra_image_get_width(_img)); + return(zbar_image_get_width(_img)); } /// retrieve the height of the image. - /// see zebra_image_get_height() + /// see zbar_image_get_height() unsigned get_height () const { - return(zebra_image_get_height(_img)); + return(zbar_image_get_height(_img)); } /// specify the pixel size of the image. - /// see zebra_image_set_size() + /// see zbar_image_set_size() void set_size (unsigned width, unsigned height) { - zebra_image_set_size(_img, width, height); + zbar_image_set_size(_img, width, height); } /// return the image sample data. - /// see zebra_image_get_data() + /// see zbar_image_get_data() const void *get_data () const { - return(zebra_image_get_data(_img)); + return(zbar_image_get_data(_img)); } /// return the size of the image sample data. - /// see zebra_image_get_data_length() + /// see zbar_image_get_data_length() /// @since 0.6 unsigned long get_data_length () const { - return(zebra_image_get_data_length(_img)); + return(zbar_image_get_data_length(_img)); } /// specify image sample data. - /// see zebra_image_set_data() + /// see zbar_image_set_data() void set_data (const void *data, unsigned long length) { - zebra_image_set_data(_img, data, length, _cleanup); + zbar_image_set_data(_img, data, length, _cleanup); } /// image format conversion. - /// see zebra_image_convert() + /// see zbar_image_convert() Image convert (unsigned long format) const { - zebra_image_t *img = zebra_image_convert(_img, format); + zbar_image_t *img = zbar_image_convert(_img, format); if(img) return(Image(img)); throw FormatError(); } /// image format conversion with crop/pad. - /// see zebra_image_convert_resize() + /// see zbar_image_convert_resize() /// @since 0.4 Image convert (unsigned long format, unsigned width, unsigned height) const { - zebra_image_t *img = - zebra_image_convert_resize(_img, format, width, height); + zbar_image_t *img = + zbar_image_convert_resize(_img, format, width, height); if(img) return(Image(img)); throw FormatError(); @@ -295,27 +295,27 @@ class Image { /// constructor. /// @internal - /// create a new Image from a zebra_image_t C object - Image (zebra_image_t *src, + /// create a new Image from a zbar_image_t C object + Image (zbar_image_t *src, int refs = 0) : _img(src) { if(refs) - zebra_image_ref(_img, refs); - zebra_image_set_userdata(_img, this); + zbar_image_ref(_img, refs); + zbar_image_set_userdata(_img, this); } /// default data cleanup (noop) /// @internal - static void _cleanup (zebra_image_t *img) + static void _cleanup (zbar_image_t *img) { // by default nothing is cleaned assert(img); - assert(zebra_image_get_userdata(img)); + assert(zbar_image_get_userdata(img)); } private: - zebra_image_t *_img; + zbar_image_t *_img; SymbolIterator _sym_iter_end; }; diff --git a/include/zebra/ImageScanner.h b/include/zbar/ImageScanner.h similarity index 57% rename from include/zebra/ImageScanner.h rename to include/zbar/ImageScanner.h index 7370fce..a401d2e 100644 --- a/include/zebra/ImageScanner.h +++ b/include/zbar/ImageScanner.h @@ -1,38 +1,38 @@ //------------------------------------------------------------------------ -// Copyright 2007-2008 (c) Jeff Brown +// Copyright 2007-2009 (c) Jeff Brown // -// This file is part of the Zebra Barcode Library. +// This file is part of the ZBar Bar Code Reader. // -// The Zebra Barcode Library is free software; you can redistribute it +// 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 Zebra Barcode Library is distributed in the hope that it will be +// 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 Zebra Barcode Library; if not, write to the Free +// 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/zebra +// http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#ifndef _ZEBRA_IMAGE_SCANNER_H_ -#define _ZEBRA_IMAGE_SCANNER_H_ +#ifndef _ZBAR_IMAGE_SCANNER_H_ +#define _ZBAR_IMAGE_SCANNER_H_ /// @file /// Image Scanner C++ wrapper -#ifndef _ZEBRA_H_ -# error "include zebra.h in your application, **not** zebra/ImageScanner.h" +#ifndef _ZBAR_H_ +# error "include zbar.h in your application, **not** zbar/ImageScanner.h" #endif #include "Image.h" -namespace zebra { +namespace zbar { /// mid-level image scanner interface. /// reads barcodes from a 2-D Image @@ -40,21 +40,21 @@ namespace zebra { class ImageScanner { public: /// constructor. - ImageScanner (zebra_image_scanner_t *scanner = NULL) + ImageScanner (zbar_image_scanner_t *scanner = NULL) { if(scanner) _scanner = scanner; else - _scanner = zebra_image_scanner_create(); + _scanner = zbar_image_scanner_create(); } ~ImageScanner () { - zebra_image_scanner_destroy(_scanner); + zbar_image_scanner_destroy(_scanner); } /// cast to C image_scanner object - operator zebra_image_scanner_t* () const + operator zbar_image_scanner_t* () const { return(_scanner); } @@ -62,44 +62,44 @@ class ImageScanner { /// setup result handler callback. void set_handler (Image::Handler &handler) { - zebra_image_scanner_set_data_handler(_scanner, handler, &handler); + zbar_image_scanner_set_data_handler(_scanner, handler, &handler); } /// set config for indicated symbology (0 for all) to specified value. - /// @see zebra_image_scanner_set_config() + /// @see zbar_image_scanner_set_config() /// @since 0.4 - int set_config (zebra_symbol_type_t symbology, - zebra_config_t config, + int set_config (zbar_symbol_type_t symbology, + zbar_config_t config, int value) { - return(zebra_image_scanner_set_config(_scanner, symbology, + return(zbar_image_scanner_set_config(_scanner, symbology, config, value)); } /// set config parsed from configuration string. - /// @see zebra_image_scanner_parse_config() + /// @see zbar_image_scanner_parse_config() /// @since 0.4 int set_config (std::string cfgstr) { - return(zebra_image_scanner_parse_config(_scanner, cfgstr.c_str())); + return(zbar_image_scanner_parse_config(_scanner, cfgstr.c_str())); } /// enable or disable the inter-image result cache. - /// see zebra_image_scanner_enable_cache() + /// see zbar_image_scanner_enable_cache() void enable_cache (bool enable = true) { - zebra_image_scanner_enable_cache(_scanner, enable); + zbar_image_scanner_enable_cache(_scanner, enable); } /// scan for symbols in provided image. - /// see zebra_scan_image() + /// see zbar_scan_image() int scan (Image& image) { - return(zebra_scan_image(_scanner, image)); + return(zbar_scan_image(_scanner, image)); } /// scan for symbols in provided image. - /// see zebra_scan_image() + /// see zbar_scan_image() ImageScanner& operator<< (Image& image) { scan(image); @@ -107,7 +107,7 @@ class ImageScanner { } private: - zebra_image_scanner_t *_scanner; + zbar_image_scanner_t *_scanner; }; } diff --git a/include/zebra/Processor.h b/include/zbar/Processor.h similarity index 65% rename from include/zebra/Processor.h rename to include/zbar/Processor.h index b66d939..d89f9c7 100644 --- a/include/zebra/Processor.h +++ b/include/zbar/Processor.h @@ -1,39 +1,39 @@ //------------------------------------------------------------------------ // Copyright 2007-2009 (c) Jeff Brown // -// This file is part of the Zebra Barcode Library. +// This file is part of the ZBar Bar Code Reader. // -// The Zebra Barcode Library is free software; you can redistribute it +// 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 Zebra Barcode Library is distributed in the hope that it will be +// 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 Zebra Barcode Library; if not, write to the Free +// 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/zebra +// http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#ifndef _ZEBRA_PROCESSOR_H_ -#define _ZEBRA_PROCESSOR_H_ +#ifndef _ZBAR_PROCESSOR_H_ +#define _ZBAR_PROCESSOR_H_ /// @file /// Processor C++ wrapper -#ifndef _ZEBRA_H_ -# error "include zebra.h in your application, **not** zebra/Processor.h" +#ifndef _ZBAR_H_ +# error "include zbar.h in your application, **not** zbar/Processor.h" #endif #include "Exception.h" #include "Image.h" -namespace zebra { +namespace zbar { /// high-level self-contained image processor. /// processes video and images for barcodes, optionally displaying @@ -49,7 +49,7 @@ class Processor { const char *video_device = "", bool enable_display = true) { - _processor = zebra_processor_create(threaded); + _processor = zbar_processor_create(threaded); if(!_processor) throw std::bad_alloc(); init(video_device, enable_display); @@ -57,104 +57,104 @@ class Processor { ~Processor () { - zebra_processor_destroy(_processor); + zbar_processor_destroy(_processor); } /// cast to C processor object. - operator zebra_processor_t* () + operator zbar_processor_t* () { return(_processor); } /// opens a video input device and/or prepares to display output. - /// see zebra_processor_init() + /// see zbar_processor_init() void init (const char *video_device = "", bool enable_display = true) { - if(zebra_processor_init(_processor, video_device, enable_display)) + if(zbar_processor_init(_processor, video_device, enable_display)) throw_exception(_processor); } /// setup result handler callback. - /// see zebra_processor_set_data_handler() + /// see zbar_processor_set_data_handler() void set_handler (Image::Handler& handler) { - zebra_processor_set_data_handler(_processor, handler, &handler); + zbar_processor_set_data_handler(_processor, handler, &handler); } /// set config for indicated symbology (0 for all) to specified value. - /// @see zebra_processor_set_config() + /// @see zbar_processor_set_config() /// @since 0.4 - int set_config (zebra_symbol_type_t symbology, - zebra_config_t config, + int set_config (zbar_symbol_type_t symbology, + zbar_config_t config, int value) { - return(zebra_processor_set_config(_processor, symbology, + return(zbar_processor_set_config(_processor, symbology, config, value)); } /// set config parsed from configuration string. - /// @see zebra_processor_parse_config() + /// @see zbar_processor_parse_config() /// @since 0.4 int set_config (std::string cfgstr) { - return(zebra_processor_parse_config(_processor, cfgstr.c_str())); + return(zbar_processor_parse_config(_processor, cfgstr.c_str())); } /// retrieve the current state of the ouput window. - /// see zebra_processor_is_visible() + /// see zbar_processor_is_visible() bool is_visible () { - int rc = zebra_processor_is_visible(_processor); + int rc = zbar_processor_is_visible(_processor); if(rc < 0) throw_exception(_processor); return(rc != 0); } /// show or hide the display window owned by the library. - /// see zebra_processor_set_visible() + /// see zbar_processor_set_visible() void set_visible (bool visible = true) { - if(zebra_processor_set_visible(_processor, visible) < 0) + if(zbar_processor_set_visible(_processor, visible) < 0) throw_exception(_processor); } /// control the processor in free running video mode. - /// see zebra_processor_set_active() + /// see zbar_processor_set_active() void set_active (bool active = true) { - if(zebra_processor_set_active(_processor, active) < 0) + if(zbar_processor_set_active(_processor, active) < 0) throw_exception(_processor); } /// wait for input to the display window from the user. - /// see zebra_processor_user_wait() + /// see zbar_processor_user_wait() int user_wait (int timeout = FOREVER) { - int rc = zebra_processor_user_wait(_processor, timeout); + int rc = zbar_processor_user_wait(_processor, timeout); if(rc < 0) throw_exception(_processor); return(rc); } /// process from the video stream until a result is available. - /// see zebra_process_one() + /// see zbar_process_one() void process_one (int timeout = FOREVER) { - if(zebra_process_one(_processor, timeout) < 0) + if(zbar_process_one(_processor, timeout) < 0) throw_exception(_processor); } /// process the provided image for barcodes. - /// see zebra_process_image() + /// see zbar_process_image() void process_image (Image& image) { - if(zebra_process_image(_processor, image) < 0) + if(zbar_process_image(_processor, image) < 0) throw_exception(_processor); } /// process the provided image for barcodes. - /// see zebra_process_image() + /// see zbar_process_image() Processor& operator<< (Image& image) { process_image(image); @@ -162,53 +162,53 @@ class Processor { } /// force specific input and output formats for debug/testing. - /// see zebra_processor_force_format() + /// see zbar_processor_force_format() void force_format (unsigned long input_format, unsigned long output_format) { - if(zebra_processor_force_format(_processor, input_format, + if(zbar_processor_force_format(_processor, input_format, output_format)) throw_exception(_processor); } /// force specific input and output formats for debug/testing. - /// see zebra_processor_force_format() + /// see zbar_processor_force_format() 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(); - if(zebra_processor_force_format(_processor, ifourcc, ofourcc)) + if(zbar_processor_force_format(_processor, ifourcc, ofourcc)) throw_exception(_processor); } /// request a preferred size for the video image from the device. - /// see zebra_processor_request_size() + /// see zbar_processor_request_size() /// @since 0.6 void request_size (int width, int height) { - zebra_processor_request_size(_processor, width, height); + zbar_processor_request_size(_processor, width, height); } /// request a preferred driver interface version for debug/testing. - /// see zebra_processor_request_interface() + /// see zbar_processor_request_interface() /// @since 0.6 void request_interface (int version) { - zebra_processor_request_interface(_processor, version); + zbar_processor_request_interface(_processor, version); } /// request a preferred I/O mode for debug/testing. - /// see zebra_processor_request_iomode() + /// see zbar_processor_request_iomode() /// @since 0.7 void request_iomode (int iomode) { - if(zebra_processor_request_iomode(_processor, iomode)) + if(zbar_processor_request_iomode(_processor, iomode)) throw_exception(_processor); } private: - zebra_processor_t *_processor; + zbar_processor_t *_processor; }; } diff --git a/include/zebra/QZebra.h b/include/zbar/QZBar.h similarity index 81% rename from include/zebra/QZebra.h rename to include/zbar/QZBar.h index 2d7a86a..db6d51d 100644 --- a/include/zebra/QZebra.h +++ b/include/zbar/QZBar.h @@ -1,52 +1,52 @@ //------------------------------------------------------------------------ -// Copyright 2008 (c) Jeff Brown +// Copyright 2008-2009 (c) Jeff Brown // -// This file is part of the Zebra Barcode Library. +// This file is part of the ZBar Bar Code Reader. // -// The Zebra Barcode Library is free software; you can redistribute it +// 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 Zebra Barcode Library is distributed in the hope that it will be +// 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 Zebra Barcode Library; if not, write to the Free +// 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/zebra +// http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#ifndef _QZEBRA_H_ -#define _QZEBRA_H_ +#ifndef _QZBAR_H_ +#define _QZBAR_H_ /// @file /// Barcode Reader Qt4 Widget #include -namespace zebra { +namespace zbar { -class QZebraThread; +class QZBarThread; /// barcode reader Qt4 widget. /// embeds a barcode reader directly into a Qt4 based GUI. the widget -/// can process barcodes from a video source (using the QZebra::videoDevice -/// and QZebra::videoEnabled properties) or from individual QImages -/// supplied to the QZebra::scanImage() slot +/// can process barcodes from a video source (using the QZBar::videoDevice +/// and QZBar::videoEnabled properties) or from individual QImages +/// supplied to the QZBar::scanImage() slot /// @since 1.5 -class QZebra : public QWidget +class QZBar : public QWidget { Q_OBJECT /// the currently opened video device. /// /// setting a new device opens it and automatically sets - /// QZebra::videoEnabled + /// QZBar::videoEnabled /// /// @see videoDevice(), setVideoDevice() Q_PROPERTY(QString videoDevice @@ -66,7 +66,7 @@ class QZebra : public QWidget /// video device opened state. /// - /// (re)setting QZebra::videoDevice should eventually cause it + /// (re)setting QZBar::videoDevice should eventually cause it /// to be opened or closed. any errors while streaming/scanning /// will also cause the device to be closed /// @@ -78,9 +78,9 @@ class QZebra : public QWidget public: /// constructs a barcode reader widget with the given @a parent - QZebra(QWidget *parent = NULL); + QZBar(QWidget *parent = NULL); - ~QZebra(); + ~QZBar(); /// retrieve the currently opened video device. /// @returns the current video device or the empty string if no @@ -124,7 +124,7 @@ public Q_SLOTS: Q_SIGNALS: /// emitted when when a video device is opened or closed. /// - /// (re)setting QZebra::videoDevice should eventually cause it + /// (re)setting QZBar::videoDevice should eventually cause it /// to be opened or closed. any errors while streaming/scanning /// will also cause the device to be closed void videoOpened(bool videoOpened); @@ -155,7 +155,7 @@ protected Q_SLOTS: /// @} private: - QZebraThread *thread; + QZBarThread *thread; QString _videoDevice; bool _videoEnabled; }; diff --git a/include/zebra/QZebraImage.h b/include/zbar/QZBarImage.h similarity index 73% rename from include/zebra/QZebraImage.h rename to include/zbar/QZBarImage.h index 92dcbe1..ce98401 100644 --- a/include/zebra/QZebraImage.h +++ b/include/zbar/QZBarImage.h @@ -1,46 +1,46 @@ //------------------------------------------------------------------------ -// Copyright 2008 (c) Jeff Brown +// Copyright 2008-2009 (c) Jeff Brown // -// This file is part of the Zebra Barcode Library. +// This file is part of the ZBar Bar Code Reader. // -// The Zebra Barcode Library is free software; you can redistribute it +// 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 Zebra Barcode Library is distributed in the hope that it will be +// 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 Zebra Barcode Library; if not, write to the Free +// 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/zebra +// http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#ifndef _QZEBRAIMAGE_H_ -#define _QZEBRAIMAGE_H_ +#ifndef _QZBARIMAGE_H_ +#define _QZBARIMAGE_H_ /// @file /// QImage to Image type conversion wrapper #include -#include +#include -namespace zebra { +namespace zbar { /// wrap a QImage and convert into a format suitable for scanning. -class QZebraImage +class QZBarImage : public Image { public: - /// construct a zebra library image based on an existing QImage. + /// construct a zbar library image based on an existing QImage. - QZebraImage (const QImage &qimg) + QZBarImage (const QImage &qimg) : qimg(qimg) { QImage::Format fmt = qimg.format(); diff --git a/include/zebra/Scanner.h b/include/zbar/Scanner.h similarity index 58% rename from include/zebra/Scanner.h rename to include/zbar/Scanner.h index 51340df..3191f58 100644 --- a/include/zebra/Scanner.h +++ b/include/zbar/Scanner.h @@ -1,38 +1,38 @@ //------------------------------------------------------------------------ -// Copyright 2007-2008 (c) Jeff Brown +// Copyright 2007-2009 (c) Jeff Brown // -// This file is part of the Zebra Barcode Library. +// This file is part of the ZBar Bar Code Reader. // -// The Zebra Barcode Library is free software; you can redistribute it +// 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 Zebra Barcode Library is distributed in the hope that it will be +// 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 Zebra Barcode Library; if not, write to the Free +// 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/zebra +// http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#ifndef _ZEBRA_SCANNER_H_ -#define _ZEBRA_SCANNER_H_ +#ifndef _ZBAR_SCANNER_H_ +#define _ZBAR_SCANNER_H_ /// @file /// Scanner C++ wrapper -#ifndef _ZEBRA_H_ -# error "include zebra.h in your application, **not** zebra/Scanner.h" +#ifndef _ZBAR_H_ +# error "include zbar.h in your application, **not** zbar/Scanner.h" #endif #include -namespace zebra { +namespace zbar { /// low-level linear intensity sample stream scanner interface. /// identifies "bar" edges and measures width between them. @@ -46,7 +46,7 @@ class Scanner { /// be passed scan results automatically Scanner (Decoder& decoder) { - _scanner = zebra_scanner_create(decoder._decoder); + _scanner = zbar_scanner_create(decoder._decoder); } /// constructor. @@ -54,98 +54,98 @@ class Scanner { /// be passed scan results automatically Scanner (Decoder* decoder = NULL) { - zebra_decoder_t *zdcode = NULL; + zbar_decoder_t *zdcode = NULL; if(decoder) zdcode = decoder->_decoder; - _scanner = zebra_scanner_create(zdcode); + _scanner = zbar_scanner_create(zdcode); } ~Scanner () { - zebra_scanner_destroy(_scanner); + zbar_scanner_destroy(_scanner); } /// clear all scanner state. - /// see zebra_scanner_reset() + /// see zbar_scanner_reset() void reset () { - zebra_scanner_reset(_scanner); + zbar_scanner_reset(_scanner); } /// mark start of a new scan pass. - /// see zebra_scanner_new_scan() + /// see zbar_scanner_new_scan() void new_scan () { - zebra_scanner_new_scan(_scanner); + zbar_scanner_new_scan(_scanner); } /// process next sample intensity value. - /// see zebra_scan_y() - zebra_symbol_type_t scan_y (int y) + /// see zbar_scan_y() + zbar_symbol_type_t scan_y (int y) { - _type = zebra_scan_y(_scanner, y); + _type = zbar_scan_y(_scanner, y); return(_type); } /// process next sample intensity value. - /// see zebra_scan_y() + /// see zbar_scan_y() Scanner& operator<< (int y) { - _type = zebra_scan_y(_scanner, y); + _type = zbar_scan_y(_scanner, y); return(*this); } /// process next sample from RGB (or BGR) triple. - /// see zebra_scan_rgb24() - zebra_symbol_type_t scan_rgb24 (unsigned char *rgb) + /// see zbar_scan_rgb24() + zbar_symbol_type_t scan_rgb24 (unsigned char *rgb) { - _type = zebra_scan_rgb24(_scanner, rgb); + _type = zbar_scan_rgb24(_scanner, rgb); return(_type); } /// process next sample from RGB (or BGR) triple. - /// see zebra_scan_rgb24() + /// see zbar_scan_rgb24() Scanner& operator<< (unsigned char *rgb) { - _type = zebra_scan_rgb24(_scanner, rgb); + _type = zbar_scan_rgb24(_scanner, rgb); return(*this); } /// retrieve last scanned width. - /// see zebra_scanner_get_width() + /// see zbar_scanner_get_width() unsigned get_width () const { - return(zebra_scanner_get_width(_scanner)); + return(zbar_scanner_get_width(_scanner)); } /// retrieve last scanned color. - /// see zebra_scanner_get_color() - zebra_color_t get_color () const + /// see zbar_scanner_get_color() + zbar_color_t get_color () const { - return(zebra_scanner_get_color(_scanner)); + return(zbar_scanner_get_color(_scanner)); } /// retrieve last scan result. - zebra_symbol_type_t get_type () const + zbar_symbol_type_t get_type () const { return(_type); } /// cast to C scanner - operator zebra_scanner_t* () const + operator zbar_scanner_t* () const { return(_scanner); } /// retrieve C scanner - const zebra_scanner_t *get_c_scanner () const + const zbar_scanner_t *get_c_scanner () const { return(_scanner); } private: - zebra_scanner_t *_scanner; - zebra_symbol_type_t _type; + zbar_scanner_t *_scanner; + zbar_symbol_type_t _type; }; } diff --git a/include/zebra/Symbol.h b/include/zbar/Symbol.h similarity index 75% rename from include/zebra/Symbol.h rename to include/zbar/Symbol.h index 6d56fd4..a04fc61 100644 --- a/include/zebra/Symbol.h +++ b/include/zbar/Symbol.h @@ -1,39 +1,39 @@ //------------------------------------------------------------------------ -// Copyright 2007-2008 (c) Jeff Brown +// Copyright 2007-2009 (c) Jeff Brown // -// This file is part of the Zebra Barcode Library. +// This file is part of the ZBar Bar Code Reader. // -// The Zebra Barcode Library is free software; you can redistribute it +// 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 Zebra Barcode Library is distributed in the hope that it will be +// 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 Zebra Barcode Library; if not, write to the Free +// 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/zebra +// http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#ifndef _ZEBRA_SYMBOL_H_ -#define _ZEBRA_SYMBOL_H_ +#ifndef _ZBAR_SYMBOL_H_ +#define _ZBAR_SYMBOL_H_ /// @file /// Symbol C++ wrapper -#ifndef _ZEBRA_H_ -# error "include zebra.h in your application, **not** zebra/Symbol.h" +#ifndef _ZBAR_H_ +# error "include zbar.h in your application, **not** zbar/Symbol.h" #endif #include #include -namespace zebra { +namespace zbar { /// decoded barcode symbol result object. stores type, data, and /// image location of decoded symbol @@ -69,7 +69,7 @@ class Symbol { _index(index) { if(!sym || - (unsigned)_index >= zebra_symbol_get_loc_size(*_sym)) + (unsigned)_index >= zbar_symbol_get_loc_size(*_sym)) _index = -1; } @@ -83,8 +83,8 @@ class Symbol { PointIterator& operator++ () { if(_index >= 0) { - _pt.x = zebra_symbol_get_loc_x(*_sym, ++_index); - _pt.y = zebra_symbol_get_loc_y(*_sym, _index); + _pt.x = zbar_symbol_get_loc_x(*_sym, ++_index); + _pt.y = zbar_symbol_get_loc_y(*_sym, _index); if(_pt.x < 0 || _pt.y < 0) _index = -1; } @@ -119,7 +119,7 @@ class Symbol { }; /// constructor. - Symbol (const zebra_symbol_t *sym = NULL) + Symbol (const zbar_symbol_t *sym = NULL) : _xmlbuf(NULL), _xmllen(0) { @@ -132,23 +132,23 @@ class Symbol { } /// initialize Symbol from C symbol object. - void init (const zebra_symbol_t *sym) + void init (const zbar_symbol_t *sym) { _sym = sym; if(sym) { - _type = zebra_symbol_get_type(sym); - _data = zebra_symbol_get_data(sym); - _count = zebra_symbol_get_count(sym); + _type = zbar_symbol_get_type(sym); + _data = zbar_symbol_get_data(sym); + _count = zbar_symbol_get_count(sym); } else { - _type = ZEBRA_NONE; + _type = ZBAR_NONE; _data = ""; _count = -1; } } /// cast to C symbol. - operator const zebra_symbol_t* () const + operator const zbar_symbol_t* () const { return(_sym); } @@ -166,7 +166,7 @@ class Symbol { } /// retrieve type of decoded symbol. - zebra_symbol_type_t get_type () const + zbar_symbol_type_t get_type () const { return(_type); } @@ -174,13 +174,13 @@ class Symbol { /// retrieve the string name of the symbol type. const std::string get_type_name () const { - return(zebra_get_symbol_name(_type)); + return(zbar_get_symbol_name(_type)); } /// retrieve the string name for any addon. const std::string get_addon_name () const { - return(zebra_get_addon_name(_type)); + return(zbar_get_addon_name(_type)); } /// retrieve ASCII data decoded from symbol. @@ -190,7 +190,7 @@ class Symbol { } /// retrieve inter-frame coherency count. - /// see zebra_symbol_get_count() + /// see zbar_symbol_get_count() /// @since 1.5 int get_count () const { @@ -210,33 +210,33 @@ class Symbol { return(_point_iter_end); } - /// see zebra_symbol_get_loc_size(). + /// see zbar_symbol_get_loc_size(). int get_location_size () const { - return(zebra_symbol_get_loc_size(_sym)); + return(zbar_symbol_get_loc_size(_sym)); } - /// see zebra_symbol_get_loc_x(). + /// see zbar_symbol_get_loc_x(). int get_location_x (unsigned index) const { - return(zebra_symbol_get_loc_x(_sym, index)); + return(zbar_symbol_get_loc_x(_sym, index)); } - /// see zebra_symbol_get_loc_y(). + /// see zbar_symbol_get_loc_y(). int get_location_y (unsigned index) const { - return(zebra_symbol_get_loc_y(_sym, index)); + return(zbar_symbol_get_loc_y(_sym, index)); } - /// see zebra_symbol_xml(). + /// see zbar_symbol_xml(). const std::string xml () const { - return(zebra_symbol_xml(_sym, (char**)&_xmlbuf, (unsigned*)&_xmllen)); + return(zbar_symbol_xml(_sym, (char**)&_xmlbuf, (unsigned*)&_xmllen)); } private: - const zebra_symbol_t *_sym; - zebra_symbol_type_t _type; + const zbar_symbol_t *_sym; + zbar_symbol_type_t _type; std::string _data; int _count; PointIterator _point_iter_end; diff --git a/include/zebra/Video.h b/include/zbar/Video.h similarity index 61% rename from include/zebra/Video.h rename to include/zbar/Video.h index 8e41fdc..2787d86 100644 --- a/include/zebra/Video.h +++ b/include/zbar/Video.h @@ -1,38 +1,38 @@ //------------------------------------------------------------------------ -// Copyright 2007-2008 (c) Jeff Brown +// Copyright 2007-2009 (c) Jeff Brown // -// This file is part of the Zebra Barcode Library. +// This file is part of the ZBar Bar Code Reader. // -// The Zebra Barcode Library is free software; you can redistribute it +// 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 Zebra Barcode Library is distributed in the hope that it will be +// 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 Zebra Barcode Library; if not, write to the Free +// 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/zebra +// http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#ifndef _ZEBRA_VIDEO_H_ -#define _ZEBRA_VIDEO_H_ +#ifndef _ZBAR_VIDEO_H_ +#define _ZBAR_VIDEO_H_ /// @file /// Video Input C++ wrapper -#ifndef _ZEBRA_H_ -# error "include zebra.h in your application, **not** zebra/Video.h" +#ifndef _ZBAR_H_ +# error "include zbar.h in your application, **not** zbar/Video.h" #endif #include "Image.h" -namespace zebra { +namespace zbar { /// mid-level video source abstraction. /// captures images from a video device @@ -40,28 +40,28 @@ namespace zebra { class Video { public: /// constructor. - Video (zebra_video_t *video = NULL) + Video (zbar_video_t *video = NULL) { if(video) _video = video; else - _video = zebra_video_create(); + _video = zbar_video_create(); } /// constructor. Video (std::string& device) { - _video = zebra_video_create(); + _video = zbar_video_create(); open(device); } ~Video () { - zebra_video_destroy(_video); + zbar_video_destroy(_video); } /// cast to C video object. - operator zebra_video_t* () const + operator zbar_video_t* () const { return(_video); } @@ -69,100 +69,100 @@ class Video { /// open and probe a video device. void open (std::string& device) { - if(zebra_video_open(_video, device.c_str())) + if(zbar_video_open(_video, device.c_str())) throw_exception(_video); } /// close video device if open. void close () { - if(zebra_video_open(_video, NULL)) + if(zbar_video_open(_video, NULL)) throw_exception(_video); } /// initialize video using a specific format for debug. - /// see zebra_video_init() + /// see zbar_video_init() void init (unsigned long fourcc) { - if(zebra_video_init(_video, fourcc)) + if(zbar_video_init(_video, fourcc)) throw_exception(_video); } /// initialize video using a specific format for debug. - /// see zebra_video_init() + /// see zbar_video_init() void init (std::string& format) { unsigned int fourcc = *(unsigned int*)format.c_str(); - if(zebra_video_init(_video, fourcc)) + if(zbar_video_init(_video, fourcc)) throw_exception(_video); } /// retrieve file descriptor associated with open *nix video device. - /// see zebra_video_get_fd() + /// see zbar_video_get_fd() int get_fd () { - return(zebra_video_get_fd(_video)); + return(zbar_video_get_fd(_video)); } /// retrieve current output image width. - /// see zebra_video_get_width() + /// see zbar_video_get_width() int get_width () { - return(zebra_video_get_width(_video)); + return(zbar_video_get_width(_video)); } /// retrieve current output image height. - /// see zebra_video_get_height() + /// see zbar_video_get_height() int get_height () { - return(zebra_video_get_height(_video)); + return(zbar_video_get_height(_video)); } /// start/stop video capture. - /// see zebra_video_enable() + /// see zbar_video_enable() void enable (bool enable = true) { - if(zebra_video_enable(_video, enable)) + if(zbar_video_enable(_video, enable)) throw_exception(_video); } /// retrieve next captured image. - /// see zebra_video_next_image() + /// see zbar_video_next_image() Image next_image () { - zebra_image_t *img = zebra_video_next_image(_video); + zbar_image_t *img = zbar_video_next_image(_video); if(!img) throw_exception(_video); return(Image(img)); } /// request a preferred size for the video image from the device. - /// see zebra_video_request_size() + /// see zbar_video_request_size() /// @since 0.6 void request_size (int width, int height) { - zebra_video_request_size(_video, width, height); + zbar_video_request_size(_video, width, height); } /// request a preferred driver interface version for debug/testing. - /// see zebra_video_request_interface() + /// see zbar_video_request_interface() /// @since 0.6 void request_interface (int version) { - zebra_video_request_interface(_video, version); + zbar_video_request_interface(_video, version); } /// request a preferred I/O mode for debug/testing. - /// see zebra_video_request_iomode() + /// see zbar_video_request_iomode() /// @since 0.7 void request_iomode (int iomode) { - if(zebra_video_request_iomode(_video, iomode)) + if(zbar_video_request_iomode(_video, iomode)) throw_exception(_video); } private: - zebra_video_t *_video; + zbar_video_t *_video; }; } diff --git a/include/zebra/Window.h b/include/zbar/Window.h similarity index 63% rename from include/zebra/Window.h rename to include/zbar/Window.h index f34861f..8cba07e 100644 --- a/include/zebra/Window.h +++ b/include/zbar/Window.h @@ -1,38 +1,38 @@ //------------------------------------------------------------------------ -// Copyright 2007-2008 (c) Jeff Brown +// Copyright 2007-2009 (c) Jeff Brown // -// This file is part of the Zebra Barcode Library. +// This file is part of the ZBar Bar Code Reader. // -// The Zebra Barcode Library is free software; you can redistribute it +// 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 Zebra Barcode Library is distributed in the hope that it will be +// 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 Zebra Barcode Library; if not, write to the Free +// 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/zebra +// http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#ifndef _ZEBRA_WINDOW_H_ -#define _ZEBRA_WINDOW_H_ +#ifndef _ZBAR_WINDOW_H_ +#define _ZBAR_WINDOW_H_ /// @file /// Output Window C++ wrapper -#ifndef _ZEBRA_H_ -# error "include zebra.h in your application, **not** zebra/Window.h" +#ifndef _ZBAR_H_ +# error "include zbar.h in your application, **not** zbar/Window.h" #endif #include "Image.h" -namespace zebra { +namespace zbar { /// mid-level output window abstraction. /// displays images to user-specified platform specific output window @@ -40,91 +40,91 @@ namespace zebra { class Window { public: /// constructor. - Window (zebra_window_t *window = NULL) + Window (zbar_window_t *window = NULL) { if(window) _window = window; else - _window = zebra_window_create(); + _window = zbar_window_create(); } /// constructor. Window (void *x11_display_w32_hwnd, unsigned long x11_drawable) { - _window = zebra_window_create(); + _window = zbar_window_create(); attach(x11_display_w32_hwnd, x11_drawable); } ~Window () { - zebra_window_destroy(_window); + zbar_window_destroy(_window); } /// cast to C window object. - operator zebra_window_t* () const + operator zbar_window_t* () const { return(_window); } /// associate reader with an existing platform window. - /// see zebra_window_attach() + /// see zbar_window_attach() void attach (void *x11_display_w32_hwnd, unsigned long x11_drawable = 0) { - if(zebra_window_attach(_window, + if(zbar_window_attach(_window, x11_display_w32_hwnd, x11_drawable) < 0) throw_exception(_window); } /// control content level of the reader overlay. - /// see zebra_window_set_overlay() + /// see zbar_window_set_overlay() void set_overlay (int level) { - zebra_window_set_overlay(_window, level); + zbar_window_set_overlay(_window, level); } /// draw a new image into the output window. - /// see zebra_window_draw() + /// see zbar_window_draw() void draw (Image& image) { - if(zebra_window_draw(_window, image) < 0) + if(zbar_window_draw(_window, image) < 0) throw_exception(_window); } /// clear the image from the output window. - /// see zebra_window_draw() + /// see zbar_window_draw() void clear () { - if(zebra_window_draw(_window, NULL) < 0) + if(zbar_window_draw(_window, NULL) < 0) throw_exception(_window); } /// redraw the last image. - /// zebra_window_redraw() + /// zbar_window_redraw() void redraw () { - if(zebra_window_redraw(_window) < 0) + if(zbar_window_redraw(_window) < 0) throw_exception(_window); } /// resize the image window. - /// zebra_window_resize() + /// zbar_window_resize() void resize (unsigned width, unsigned height) { - if(zebra_window_resize(_window, width, height) < 0) + if(zbar_window_resize(_window, width, height) < 0) throw_exception(_window); } private: - zebra_window_t *_window; + zbar_window_t *_window; }; /// select a compatible format between video input and output window. -/// see zebra_negotiate_format() +/// see zbar_negotiate_format() static inline void negotiate_format (Video& video, Window& window) { - if(zebra_negotiate_format(video, window) < 0) + if(zbar_negotiate_format(video, window) < 0) throw_exception(video); } diff --git a/include/zebra/zebragtk.h b/include/zbar/zbargtk.h similarity index 56% rename from include/zebra/zebragtk.h rename to include/zbar/zbargtk.h index 9b3351d..5d4ddc0 100644 --- a/include/zebra/zebragtk.h +++ b/include/zbar/zbargtk.h @@ -1,36 +1,36 @@ /*------------------------------------------------------------------------ - * Copyright 2008 (c) Jeff Brown + * Copyright 2008-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ -#ifndef __ZEBRA_GTK_H__ -#define __ZEBRA_GTK_H__ +#ifndef __ZBAR_GTK_H__ +#define __ZBAR_GTK_H__ -/** SECTION:ZebraGtk +/** SECTION:ZBarGtk * @short_description: barcode reader GTK+ 2.x widget - * @include: zebra/zebragtk.h + * @include: zbar/zbargtk.h * * embeds a barcode reader directly into a GTK+ based GUI. the widget * can process barcodes from a video source (using the - * #ZebraGtk:video-device and #ZebraGtk:video-enabled properties) or - * from individual GdkPixbufs supplied to zebra_gtk_scan_image() + * #ZBarGtk:video-device and #ZBarGtk:video-enabled properties) or + * from individual GdkPixbufs supplied to zbar_gtk_scan_image() * * Since: 1.5 */ @@ -39,43 +39,43 @@ #include #include -#include +#include G_BEGIN_DECLS -#define ZEBRA_TYPE_GTK (zebra_gtk_get_type()) -#define ZEBRA_GTK(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), ZEBRA_TYPE_GTK, ZebraGtk)) -#define ZEBRA_GTK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), ZEBRA_TYPE_GTK, ZebraGtkClass)) -#define ZEBRA_IS_GTK(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), ZEBRA_TYPE_GTK)) -#define ZEBRA_IS_GTK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), ZEBRA_TYPE_GTK)) -#define ZEBRA_GTK_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), ZEBRA_TYPE_GTK, ZebraGtkClass)) - -typedef struct _ZebraGtk ZebraGtk; -typedef struct _ZebraGtkClass ZebraGtkClass; - -struct _ZebraGtk { +#define ZBAR_TYPE_GTK (zbar_gtk_get_type()) +#define ZBAR_GTK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), ZBAR_TYPE_GTK, ZBarGtk)) +#define ZBAR_GTK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), ZBAR_TYPE_GTK, ZBarGtkClass)) +#define ZBAR_IS_GTK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), ZBAR_TYPE_GTK)) +#define ZBAR_IS_GTK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), ZBAR_TYPE_GTK)) +#define ZBAR_GTK_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), ZBAR_TYPE_GTK, ZBarGtkClass)) + +typedef struct _ZBarGtk ZBarGtk; +typedef struct _ZBarGtkClass ZBarGtkClass; + +struct _ZBarGtk { GtkWidget widget; gpointer *_private; /* properties */ /** - * ZebraGtk:video-device: + * ZBarGtk:video-device: * * the currently set video device. * * setting a new device opens it and automatically sets - * #ZebraGtk:video-enabled. set the empty string ("") or NULL to + * #ZBarGtk:video-enabled. set the empty string ("") or NULL to * close. */ /** - * ZebraGtk:video-enabled: + * ZBarGtk:video-enabled: * * video device streaming state. * @@ -83,37 +83,37 @@ struct _ZebraGtk { */ /** - * ZebraGtk:video-opened: + * ZBarGtk:video-opened: * * video device opened state. * - * (re)setting #ZebraGtk:video-device should eventually cause it + * (re)setting #ZBarGtk:video-device should eventually cause it * to be opened or closed. any errors while streaming/scanning * will also cause the device to be closed */ }; -struct _ZebraGtkClass { +struct _ZBarGtkClass { GtkWidgetClass parent_class; /* signals */ /** - * ZebraGtk::decoded: + * ZBarGtk::decoded: * @widget: the object that received the signal - * @symbol_type: the type of symbol decoded (a zebra_symbol_type_t) + * @symbol_type: the type of symbol decoded (a zbar_symbol_type_t) * @data: the data decoded from the symbol * * emitted when a barcode is decoded from an image. * the symbol type and contained data are provided as separate * parameters */ - void (*decoded) (ZebraGtk *zebra, - zebra_symbol_type_t symbol_type, + void (*decoded) (ZBarGtk *zbar, + zbar_symbol_type_t symbol_type, const char *data); /** - * ZebraGtk::decoded-text: + * ZBarGtk::decoded-text: * @widget: the object that received the signal * @text: the decoded data prefixed by the string name of the * symbol type (separated by a colon) @@ -122,41 +122,41 @@ struct _ZebraGtkClass { * the symbol type name is prefixed to the data, separated by a * colon */ - void (*decoded_text) (ZebraGtk *zebra, + void (*decoded_text) (ZBarGtk *zbar, const char *text); /** - * ZebraGtk::scan-image: + * ZBarGtk::scan-image: * @widget: the object that received the signal * @image: the image to scan for barcodes */ - void (*scan_image) (ZebraGtk *zebra, + void (*scan_image) (ZBarGtk *zbar, GdkPixbuf *image); }; -GType zebra_gtk_get_type() G_GNUC_CONST; +GType zbar_gtk_get_type() G_GNUC_CONST; /** - * zebra_gtk_new: + * zbar_gtk_new: * create a new barcode reader widget instance. * initially has no associated video device or image. * - * Returns: a new #ZebraGtk widget instance + * Returns: a new #ZBarGtk widget instance */ -GtkWidget *zebra_gtk_new(); +GtkWidget *zbar_gtk_new(); /** - * zebra_gtk_scan_image: + * zbar_gtk_scan_image: * */ -void zebra_gtk_scan_image(ZebraGtk *zebra, - GdkPixbuf *image); +void zbar_gtk_scan_image(ZBarGtk *zbar, + GdkPixbuf *image); /** retrieve the currently opened video device. * * Returns: the current video device or NULL if no device is opened */ -const char *zebra_gtk_get_video_device(ZebraGtk *zebra); +const char *zbar_gtk_get_video_device(ZBarGtk *zbar); /** open a new video device. * @@ -166,39 +166,39 @@ const char *zebra_gtk_get_video_device(ZebraGtk *zebra); * @note since opening a device may take some time, this call will * return immediately and the device will be opened asynchronously */ -void zebra_gtk_set_video_device(ZebraGtk *zebra, - const char *video_device); +void zbar_gtk_set_video_device(ZBarGtk *zbar, + const char *video_device); /** retrieve the current video enabled state. * * Returns: true if video scanning is currently enabled, false otherwise */ -gboolean zebra_gtk_get_video_enabled(ZebraGtk *zebra); +gboolean zbar_gtk_get_video_enabled(ZBarGtk *zbar); /** enable/disable video scanning. * @video_enabled: true to enable video scanning, false to disable * * has no effect unless a video device is opened */ -void zebra_gtk_set_video_enabled(ZebraGtk *zebra, - gboolean video_enabled); +void zbar_gtk_set_video_enabled(ZBarGtk *zbar, + gboolean video_enabled); /** retrieve the current video opened state. * * Returns: true if video device is currently opened, false otherwise */ -gboolean zebra_gtk_get_video_opened(ZebraGtk *zebra); +gboolean zbar_gtk_get_video_opened(ZBarGtk *zbar); /** - * utility function to populate a zebra_image_t from a GdkPixbuf. - * @image: the zebra library image destination to populate + * utility function to populate a zbar_image_t from a GdkPixbuf. + * @image: the zbar library image destination to populate * @pixbuf: the GdkPixbuf source * * Returns: TRUE if successful or FALSE if the conversion could not be * performed for some reason */ -gboolean zebra_gtk_image_from_pixbuf(zebra_image_t *image, - GdkPixbuf *pixbuf); +gboolean zbar_gtk_image_from_pixbuf(zbar_image_t *image, + GdkPixbuf *pixbuf); G_END_DECLS diff --git a/perl/Changes b/perl/Changes index 618612a..2bba2b3 100644 --- a/perl/Changes +++ b/perl/Changes @@ -1,4 +1,7 @@ -Revision history for Perl extension Barcode::Zebra. +Revision history for Perl extension Barcode::ZBar. + +0.02 2009-04-16 spadix + * project name change: package becomes Barcode::ZBar 0.01 2009-02-28 spadix * add Barcode:: namespace prefix diff --git a/perl/MANIFEST b/perl/MANIFEST index 8146a67..77ed362 100644 --- a/perl/MANIFEST +++ b/perl/MANIFEST @@ -4,16 +4,18 @@ Changes COPYING.LIB Makefile.PL typemap -Zebra.xs +ZBar.xs ppport.h -Zebra.pm -Zebra/Image.pod -Zebra/ImageScanner.pod -Zebra/Processor.pod -Zebra/Symbol.pod +ZBar.pm +ZBar/Image.pod +ZBar/ImageScanner.pod +ZBar/Processor.pod +ZBar/Symbol.pod t/barcode.png t/Decoder.t t/Image.t t/Processor.t t/Scanner.t -t/Zebra.t +t/ZBar.t +t/pod.t +t/pod-coverage.t diff --git a/perl/Makefile.PL b/perl/Makefile.PL index 5ed763d..db23798 100644 --- a/perl/Makefile.PL +++ b/perl/Makefile.PL @@ -1,10 +1,26 @@ use 5.006; use ExtUtils::MakeMaker; +use lib qw(inc); +use Devel::CheckLib; + +check_lib_or_exit( + lib => 'zbar', + header => 'zbar.h', + LIBS => join(' ', map({ /^LIBS=(.*)/; $1 } grep(/^LIBS=/, @ARGV))), + INC => join(' ', map({ /^INC=(.*)/; $1 } grep(/^INC=/, @ARGV))), +); + WriteMakefile( - NAME => 'Barcode::Zebra', - VERSION_FROM => "Zebra.pm", - ABSTRACT_FROM => "Zebra.pm", + NAME => 'Barcode::ZBar', + VERSION_FROM => "ZBar.pm", + ABSTRACT_FROM => "ZBar.pm", AUTHOR => 'Jeff Brown ', - LIBS => ['-lzebra'], + LICENSE => 'lgpl', + LIBS => ['-lzbar'], + META_MERGE => { + build_requires => { + 'Test::More' => 0, + } + }, ); diff --git a/perl/README b/perl/README index d873565..1824af5 100644 --- a/perl/README +++ b/perl/README @@ -1,15 +1,14 @@ -Barcode::Zebra Perl module -========================== +Barcode::ZBar Perl module +========================= -The Zebra Barcode Reader library is a library for scanning and -decoding bar codes from various sources such as video streams, image -files or raw intensity sensors. It supports EAN, UPC, Code 128, Code -39 and Interleaved 2 of 5. These are the Perl bindings for the -library. +The ZBar Bar Code Reader is a library for scanning and decoding bar +codes from various sources such as video streams, image files or raw +intensity sensors. It supports EAN, UPC, Code 128, Code 39 and +Interleaved 2 of 5. These are the Perl bindings for the library. -Check the zebra library home page for the latest release, mailing +Check the ZBar project home page for the latest release, mailing lists, etc. - http://zebra.sourceforge.net/ + http://zbar.sourceforge.net/ INSTALLATION @@ -24,10 +23,10 @@ To install this module type the following: DEPENDENCIES -This module requires the Zebra Barcode Reader library, which may be -obtained from: +This module requires the ZBar Bar Code Reader, which may be obtained +from: - http://zebra.sourceforge.net/ + http://zbar.sourceforge.net/ COPYRIGHT AND LICENCE diff --git a/perl/Zebra.pm b/perl/ZBar.pm similarity index 64% rename from perl/Zebra.pm rename to perl/ZBar.pm index 4a28b18..8e0a902 100644 --- a/perl/Zebra.pm +++ b/perl/ZBar.pm @@ -1,26 +1,26 @@ #------------------------------------------------------------------------ # Copyright 2008-2009 (c) Jeff Brown # -# This file is part of the Zebra Barcode Library. +# This file is part of the ZBar Bar Code Reader. # -# The Zebra Barcode Library is free software; you can redistribute it +# 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 Zebra Barcode Library is distributed in the hope that it will be +# 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 Zebra Barcode Library; if not, write to the Free +# 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/zebra +# http://sourceforge.net/projects/zbar #------------------------------------------------------------------------ -package Barcode::Zebra; +package Barcode::ZBar; use 5.006; use strict; @@ -32,12 +32,12 @@ our @ISA = qw(Exporter); our @EXPORT_OK = qw(SPACE BAR version increase_verbosity set_verbosity); -our $VERSION = '0.1'; +our $VERSION = '0.02'; require XSLoader; -XSLoader::load('Barcode::Zebra', $VERSION); +XSLoader::load('Barcode::ZBar', $VERSION); -package Barcode::Zebra::Error; +package Barcode::ZBar::Error; use overload '""' => sub { return($_[0]->error_string()) }; @@ -47,22 +47,22 @@ __END__ =head1 NAME -Barcode::Zebra - Perl interface to the Zebra Barcode Reader Library +Barcode::ZBar - Perl interface to the ZBar Barcode Reader =head1 SYNOPSIS setup: - use Barcode::Zebra; + use Barcode::ZBar; - my $reader = Barcode::Zebra::Processor->new(); + my $reader = Barcode::ZBar::Processor->new(); $reader->init(); $reader->set_data_handler(\&my_handler); scan an image: - my $image = Barcode::Zebra::Image->new(); + my $image = Barcode::ZBar::Image->new(); $image->set_format('422P'); $image->set_size(114, 80); $image->set_data($raw_bits); @@ -84,10 +84,10 @@ collect results: =head1 DESCRIPTION -The Zebra Barcode Reader library is a library for scanning and -decoding bar codes from various sources such as video streams, image -files or raw intensity sensors. It supports EAN, UPC, Code 128, Code -39 and Interleaved 2 of 5. +The ZBar Bar Code Reader is a library for scanning and decoding bar +codes from various sources such as video streams, image files or raw +intensity sensors. It supports EAN, UPC, Code 128, Code 39 and +Interleaved 2 of 5. These are the bindings for interacting directly with the library from Perl. @@ -101,7 +101,7 @@ Perl. =item version() -Returns the version of the zebra library as "I.I". +Returns the version of the zbar library as "I.I". =item increase_verbosity() @@ -112,6 +112,13 @@ Increases global library debug by one level. Sets global library debug to the indicated level. Higher numbers give more verbosity. +=item parse_config(I) + +Parse a decoder configuration setting into a list containing the +symbology constant, config constant, and value to set. See the +documentation for C/C for available configuration +options. + =back =head2 Constants @@ -133,13 +140,13 @@ Dark area or colored bar segment. =head1 SEE ALSO -Barcode::Zebra::Processor, Barcode::Zebra::ImageScanner, -Barcode::Zebra::Image, Barcode::Zebra::Symbol, -Barcode::Zebra::Scanner, Barcode::Zebra::Decoder +Barcode::ZBar::Processor, Barcode::ZBar::ImageScanner, +Barcode::ZBar::Image, Barcode::ZBar::Symbol, +Barcode::ZBar::Scanner, Barcode::ZBar::Decoder -zebraimg(1), zebracam(1) +zbarimg(1), zbarcam(1) -http://zebra.sf.net +http://zbar.sf.net =head1 AUTHOR @@ -151,7 +158,7 @@ Jeff Brown, Espadix@users.sourceforge.netE Copyright 2008-2009 (c) Jeff Brown Espadix@users.sourceforge.netE -The Zebra Barcode Library is free software; you can redistribute it +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. diff --git a/perl/ZBar.xs b/perl/ZBar.xs new file mode 100644 index 0000000..65f8f97 --- /dev/null +++ b/perl/ZBar.xs @@ -0,0 +1,712 @@ +//------------------------------------------------------------------------ +// Copyright 2008-2009 (c) Jeff Brown +// +// 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 "EXTERN.h" +#include "perl.h" +#include "XSUB.h" + +#include "ppport.h" + +#include + +typedef zbar_symbol_t *Barcode__ZBar__Symbol; +typedef zbar_image_t *Barcode__ZBar__Image; +typedef zbar_processor_t *Barcode__ZBar__Processor; +typedef zbar_video_t *Barcode__ZBar__Video; +typedef zbar_window_t *Barcode__ZBar__Window; +typedef zbar_image_scanner_t *Barcode__ZBar__ImageScanner; +typedef zbar_decoder_t *Barcode__ZBar__Decoder; +typedef zbar_scanner_t *Barcode__ZBar__Scanner; +typedef void *Barcode__ZBar__Error; + +typedef unsigned long fourcc_t; +typedef int timeout_t; +typedef int config_error; + +typedef struct handler_wrapper_s { + SV *instance; + SV *handler; + SV *closure; +} handler_wrapper_t; + + +static AV *LOOKUP_zbar_color_t = NULL; +static AV *LOOKUP_zbar_symbol_type_t = NULL; +static AV *LOOKUP_zbar_error_t = NULL; +static AV *LOOKUP_zbar_config_t = NULL; + +#define CONSTANT(typ, prefix, sym, name) \ + do { \ + SV *c = newSViv(ZBAR_ ## prefix ## sym); \ + sv_setpv(c, name); \ + SvIOK_on(c); \ + newCONSTSUB(stash, #sym, c); \ + av_store(LOOKUP_zbar_ ## typ ## _t, \ + ZBAR_ ## prefix ## sym, \ + SvREFCNT_inc(c)); \ + } while(0) + +#define LOOKUP_ENUM(typ, val) \ + lookup_enum(LOOKUP_zbar_ ## typ ## _t, val) + +static inline SV *lookup_enum (AV *lookup, int val) +{ + SV **tmp = av_fetch(lookup, val, 0); + return((tmp) ? *tmp : sv_newmortal()); +} + +static inline void check_error (int rc, void *obj) +{ + if(rc < 0) { + sv_setref_pv(get_sv("@", TRUE), "Barcode::ZBar::Error", obj); + croak(NULL); + } +} + +static void image_cleanup_handler (zbar_image_t *image) +{ + SV *data = zbar_image_get_userdata(image); + if(!data) + /* FIXME this is internal error */ + return; + + /* release reference to cleanup data */ + SvREFCNT_dec(data); +} + +static inline int set_handler (handler_wrapper_t **wrapp, + SV *instance, + SV *handler, + SV *closure) +{ + handler_wrapper_t *wrap = *wrapp; + if(!handler || !SvOK(handler)) { + if(wrap) { + if(wrap->instance) SvREFCNT_dec(wrap->instance); + if(wrap->handler) SvREFCNT_dec(wrap->handler); + if(wrap->closure) SvREFCNT_dec(wrap->closure); + wrap->instance = wrap->handler = wrap->closure = NULL; + } + return(0); + } + + if(!wrap) { + Newxz(wrap, 1, handler_wrapper_t); + wrap->instance = newSVsv(instance); + wrap->closure = newSV(0); + *wrapp = wrap; + } + + if(wrap->handler) + SvSetSV(wrap->handler, handler); + else + wrap->handler = newSVsv(handler); + + if(!closure || !SvOK(closure)) + SvSetSV(wrap->closure, &PL_sv_undef); + else + SvSetSV(wrap->closure, closure); + return(1); +} + +static inline void activate_handler (handler_wrapper_t *wrap, + SV *param) +{ + dSP; + if(!wrap) + /* FIXME this is internal error */ + return; + + ENTER; + SAVETMPS; + + PUSHMARK(SP); + EXTEND(SP, 2); + PUSHs(sv_mortalcopy(wrap->instance)); + if(param) + PUSHs(param); + PUSHs(sv_mortalcopy(wrap->closure)); + PUTBACK; + + call_sv(wrap->handler, G_DISCARD); + + FREETMPS; + LEAVE; +} + +static void processor_handler (zbar_image_t *image, + const void *userdata) +{ + SV *img; + zbar_image_ref(image, 1); + img = sv_setref_pv(newSV(0), "Barcode::ZBar::Image", image); + activate_handler((void*)userdata, img); + SvREFCNT_dec(img); +} + +static void decoder_handler (zbar_decoder_t *decoder) +{ + activate_handler(zbar_decoder_get_userdata(decoder), NULL); +} + + +MODULE = Barcode::ZBar PACKAGE = Barcode::ZBar PREFIX = zbar_ + +PROTOTYPES: ENABLE + +BOOT: + { + HV *stash = gv_stashpv("Barcode::ZBar", TRUE); + + LOOKUP_zbar_color_t = newAV(); + CONSTANT(color, , SPACE, "SPACE"); + CONSTANT(color, , BAR, "BAR"); + } + +SV * +zbar_version() + PREINIT: + unsigned major; + unsigned minor; + CODE: + zbar_version(&major, &minor); + RETVAL = newSVpvf("%u.%u", major, minor); + OUTPUT: + RETVAL + +void +zbar_increase_verbosity() + +void +zbar_set_verbosity(verbosity) + int verbosity + +SV * +parse_config(config_string) + const char * config_string + PREINIT: + zbar_symbol_type_t sym; + zbar_config_t cfg; + int val; + PPCODE: + if(zbar_parse_config(config_string, &sym, &cfg, &val)) + croak("invalid configuration setting: %s", config_string); + EXTEND(SP, 3); + PUSHs(LOOKUP_ENUM(symbol_type, sym)); + PUSHs(LOOKUP_ENUM(config, cfg)); + mPUSHi(val); + + +MODULE = Barcode::ZBar PACKAGE = Barcode::ZBar::Error PREFIX = zbar_ + +BOOT: + { + HV *stash = gv_stashpv("Barcode::ZBar::Error", TRUE); + + LOOKUP_zbar_error_t = newAV(); + CONSTANT(error, ERR_, NOMEM, "out of memory"); + CONSTANT(error, ERR_, INTERNAL, "internal library error"); + CONSTANT(error, ERR_, UNSUPPORTED, "unsupported request"); + CONSTANT(error, ERR_, INVALID, "invalid request"); + CONSTANT(error, ERR_, SYSTEM, "system error"); + CONSTANT(error, ERR_, LOCKING, "locking error"); + CONSTANT(error, ERR_, BUSY, "all resources busy"); + CONSTANT(error, ERR_, XDISPLAY, "X11 display error"); + CONSTANT(error, ERR_, XPROTO, "X11 protocol error"); + CONSTANT(error, ERR_, CLOSED, "output window is closed"); + } + +zbar_error_t +get_error_code(err) + Barcode::ZBar::Error err + CODE: + RETVAL = _zbar_get_error_code(err); + OUTPUT: + RETVAL + +const char * +error_string(err) + Barcode::ZBar::Error err + CODE: + RETVAL = _zbar_error_string(err, 1); + OUTPUT: + RETVAL + + +MODULE = Barcode::ZBar PACKAGE = Barcode::ZBar::Config PREFIX = zbar_config_ + +BOOT: + { + HV *stash = gv_stashpv("Barcode::ZBar::Config", TRUE); + + LOOKUP_zbar_config_t = newAV(); + CONSTANT(config, CFG_, ENABLE, "enable"); + CONSTANT(config, CFG_, ADD_CHECK, "add-check"); + CONSTANT(config, CFG_, EMIT_CHECK, "emit-check"); + CONSTANT(config, CFG_, ASCII, "ascii"); + CONSTANT(config, CFG_, MIN_LEN, "min-length"); + CONSTANT(config, CFG_, MAX_LEN, "max-length"); + CONSTANT(config, CFG_, X_DENSITY, "x-density"); + CONSTANT(config, CFG_, Y_DENSITY, "y-density"); + } + + +MODULE = Barcode::ZBar PACKAGE = Barcode::ZBar::Symbol PREFIX = zbar_symbol_ + +BOOT: + { + HV *stash = gv_stashpv("Barcode::ZBar::Symbol", TRUE); + + LOOKUP_zbar_symbol_type_t = newAV(); + CONSTANT(symbol_type, , NONE, "None"); + CONSTANT(symbol_type, , PARTIAL, "Partial"); + CONSTANT(symbol_type, , EAN8, zbar_get_symbol_name(ZBAR_EAN8)); + CONSTANT(symbol_type, , UPCE, zbar_get_symbol_name(ZBAR_UPCE)); + CONSTANT(symbol_type, , ISBN10, zbar_get_symbol_name(ZBAR_ISBN10)); + CONSTANT(symbol_type, , UPCA, zbar_get_symbol_name(ZBAR_UPCA)); + CONSTANT(symbol_type, , EAN13, zbar_get_symbol_name(ZBAR_EAN13)); + CONSTANT(symbol_type, , ISBN13, zbar_get_symbol_name(ZBAR_ISBN13)); + CONSTANT(symbol_type, , I25, zbar_get_symbol_name(ZBAR_I25)); + CONSTANT(symbol_type, , CODE39, zbar_get_symbol_name(ZBAR_CODE39)); + CONSTANT(symbol_type, , PDF417, zbar_get_symbol_name(ZBAR_PDF417)); + CONSTANT(symbol_type, , CODE128, zbar_get_symbol_name(ZBAR_CODE128)); + } + +zbar_symbol_type_t +zbar_symbol_get_type(symbol) + Barcode::ZBar::Symbol symbol + +const char * +zbar_symbol_get_data(symbol) + Barcode::ZBar::Symbol symbol + +int +zbar_symbol_get_count(symbol) + Barcode::ZBar::Symbol symbol + +SV * +zbar_symbol_get_loc(symbol) + Barcode::ZBar::Symbol symbol + PREINIT: + unsigned i, size; + PPCODE: + size = zbar_symbol_get_loc_size(symbol); + EXTEND(SP, size); + for(i = 0; i < size; i++) { + AV *pt = (AV*)sv_2mortal((SV*)newAV()); + PUSHs(newRV((SV*)pt)); + av_push(pt, newSVuv(zbar_symbol_get_loc_x(symbol, i))); + av_push(pt, newSVuv(zbar_symbol_get_loc_y(symbol, i))); + } + + +MODULE = Barcode::ZBar PACKAGE = Barcode::ZBar::Image PREFIX = zbar_image_ + +Barcode::ZBar::Image +new(package) + char * package + CODE: + RETVAL = zbar_image_create(); + OUTPUT: + RETVAL + +void +DESTROY(image) + Barcode::ZBar::Image image + CODE: + zbar_image_destroy(image); + +Barcode::ZBar::Image +zbar_image_convert(image, format) + Barcode::ZBar::Image image + fourcc_t format + +Barcode::ZBar::Image +zbar_image_convert_resize(image, format, width, height) + Barcode::ZBar::Image image + fourcc_t format + unsigned width + unsigned height + +fourcc_t +zbar_image_get_format(image) + Barcode::ZBar::Image image + +unsigned +zbar_image_get_sequence(image) + Barcode::ZBar::Image image + +void +get_size(image) + Barcode::ZBar::Image image + PPCODE: + EXTEND(SP, 2); + mPUSHu(zbar_image_get_width(image)); + mPUSHu(zbar_image_get_height(image)); + +SV * +zbar_image_get_data(image) + Barcode::ZBar::Image image + CODE: + RETVAL = newSVpvn(zbar_image_get_data(image), + zbar_image_get_data_length(image)); + OUTPUT: + RETVAL + +SV * +get_symbols(image) + Barcode::ZBar::Image image + PREINIT: + const zbar_symbol_t *sym; + PPCODE: + sym = zbar_image_first_symbol(image); + for(; sym; sym = zbar_symbol_next(sym)) + XPUSHs(sv_setref_pv(sv_newmortal(), "Barcode::ZBar::Symbol", + (void*)sym)); + +void +zbar_image_set_format(image, format) + Barcode::ZBar::Image image + fourcc_t format + +void +zbar_image_set_sequence(image, seq_num) + Barcode::ZBar::Image image + unsigned seq_num + +void +zbar_image_set_size(image, width, height) + Barcode::ZBar::Image image + unsigned width + unsigned height + +void +zbar_image_set_data(image, data) + Barcode::ZBar::Image image + SV * data + PREINIT: + SV *old; + CODE: + if(!data || !SvOK(data)) { + zbar_image_set_data(image, NULL, 0, NULL); + zbar_image_set_userdata(image, NULL); + } + else if(SvPOK(data)) { + /* FIXME is this copy of data or new ref to same data? + * not sure this is correct: + * need to retain a reference to image data, + * but do not really want to copy it...maybe an RV? + */ + SV *copy = newSVsv(data); + STRLEN len; + void *raw = SvPV(copy, len); + zbar_image_set_data(image, raw, len, image_cleanup_handler); + zbar_image_set_userdata(image, copy); + } + else + croak("image data must be binary string"); + + +MODULE = Barcode::ZBar PACKAGE = Barcode::ZBar::Processor PREFIX = zbar_processor_ + +Barcode::ZBar::Processor +new(package, threaded=0) + char * package + bool threaded + CODE: + RETVAL = zbar_processor_create(threaded); + OUTPUT: + RETVAL + +void +DESTROY(processor) + Barcode::ZBar::Processor processor + CODE: + zbar_processor_destroy(processor); + +void +zbar_processor_init(processor, video_device="/dev/video0", enable_display=1) + Barcode::ZBar::Processor processor + const char * video_device + bool enable_display + CODE: + check_error(zbar_processor_init(processor, video_device, enable_display), + processor); + +void +zbar_processor_request_size(processor, width, height) + Barcode::ZBar::Processor processor + unsigned width + unsigned height + CODE: + check_error(zbar_processor_request_size(processor, width, height), + processor); + +void +zbar_processor_force_format(processor, input_format=0, output_format=0) + Barcode::ZBar::Processor processor + fourcc_t input_format + fourcc_t output_format + CODE: + check_error(zbar_processor_force_format(processor, input_format, output_format), + processor); + +void +zbar_processor_set_config(processor, symbology, config, value=1) + Barcode::ZBar::Processor processor + zbar_symbol_type_t symbology + zbar_config_t config + int value + +config_error +zbar_processor_parse_config(processor, config_string) + Barcode::ZBar::Processor processor + const char *config_string + +bool +zbar_processor_is_visible(processor) + Barcode::ZBar::Processor processor + CODE: + check_error((RETVAL = zbar_processor_is_visible(processor)), + processor); + OUTPUT: + RETVAL + +void +zbar_processor_set_visible(processor, visible=1) + Barcode::ZBar::Processor processor + bool visible + CODE: + check_error(zbar_processor_set_visible(processor, visible), + processor); + +void +zbar_processor_set_active(processor, active=1) + Barcode::ZBar::Processor processor + bool active + CODE: + check_error(zbar_processor_set_active(processor, active), + processor); + +int +zbar_processor_user_wait(processor, timeout=-1) + Barcode::ZBar::Processor processor + timeout_t timeout + CODE: + check_error((RETVAL = zbar_processor_user_wait(processor, timeout)), + processor); + OUTPUT: + RETVAL + +int +process_one(processor, timeout=-1) + Barcode::ZBar::Processor processor + timeout_t timeout + CODE: + check_error((RETVAL = zbar_process_one(processor, timeout)), + processor); + OUTPUT: + RETVAL + +int +process_image(processor, image) + Barcode::ZBar::Processor processor + Barcode::ZBar::Image image + CODE: + check_error((RETVAL = zbar_process_image(processor, image)), + processor); + OUTPUT: + RETVAL + +void +zbar_processor_set_data_handler(processor, handler = 0, closure = 0) + Barcode::ZBar::Processor processor + SV * handler + SV * closure + PREINIT: + handler_wrapper_t *wrap; + zbar_image_data_handler_t *callback = NULL; + CODE: + wrap = zbar_processor_get_userdata(processor); + if(set_handler(&wrap, ST(0), handler, closure)) + callback = processor_handler; + zbar_processor_set_data_handler(processor, callback, wrap); + + +MODULE = Barcode::ZBar PACKAGE = Barcode::ZBar::ImageScanner PREFIX = zbar_image_scanner_ + +Barcode::ZBar::ImageScanner +new(package) + char * package + CODE: + RETVAL = zbar_image_scanner_create(); + OUTPUT: + RETVAL + +void +DESTROY(scanner) + Barcode::ZBar::ImageScanner scanner + CODE: + zbar_image_scanner_destroy(scanner); + +void +zbar_image_scanner_set_config(scanner, symbology, config, value=1) + Barcode::ZBar::ImageScanner scanner + zbar_symbol_type_t symbology + zbar_config_t config + int value + +config_error +zbar_image_scanner_parse_config(scanner, config_string) + Barcode::ZBar::ImageScanner scanner + const char *config_string + +void +zbar_image_scanner_enable_cache(scanner, enable) + Barcode::ZBar::ImageScanner scanner + int enable + +int +scan_image(scanner, image) + Barcode::ZBar::ImageScanner scanner + Barcode::ZBar::Image image + CODE: + RETVAL = zbar_scan_image(scanner, image); + OUTPUT: + RETVAL + + +MODULE = Barcode::ZBar PACKAGE = Barcode::ZBar::Decoder PREFIX = zbar_decoder_ + +Barcode::ZBar::Decoder +new(package) + char * package + CODE: + RETVAL = zbar_decoder_create(); + OUTPUT: + RETVAL + +void +DESTROY(decoder) + Barcode::ZBar::Decoder decoder + CODE: + /* FIXME cleanup handler wrapper */ + zbar_decoder_destroy(decoder); + +void +zbar_decoder_set_config(decoder, symbology, config, value=1) + Barcode::ZBar::Decoder decoder + zbar_symbol_type_t symbology + zbar_config_t config + int value + +config_error +zbar_decoder_parse_config(decoder, config_string) + Barcode::ZBar::Decoder decoder + const char *config_string + +void +zbar_decoder_reset(decoder) + Barcode::ZBar::Decoder decoder + +void +zbar_decoder_new_scan(decoder) + Barcode::ZBar::Decoder decoder + +zbar_symbol_type_t +decode_width(decoder, width) + Barcode::ZBar::Decoder decoder + unsigned width + CODE: + RETVAL = zbar_decode_width(decoder, width); + OUTPUT: + RETVAL + +zbar_color_t +zbar_decoder_get_color(decoder) + Barcode::ZBar::Decoder decoder + +const char * +zbar_decoder_get_data(decoder) + Barcode::ZBar::Decoder decoder + +zbar_symbol_type_t +zbar_decoder_get_type(decoder) + Barcode::ZBar::Decoder decoder + +void +zbar_decoder_set_handler(decoder, handler = 0, closure = 0) + Barcode::ZBar::Decoder decoder + SV * handler + SV * closure + PREINIT: + handler_wrapper_t *wrap; + CODE: + wrap = zbar_decoder_get_userdata(decoder); + zbar_decoder_set_handler(decoder, NULL); + if(set_handler(&wrap, ST(0), handler, closure)) { + zbar_decoder_set_userdata(decoder, wrap); + zbar_decoder_set_handler(decoder, decoder_handler); + } + + +MODULE = Barcode::ZBar PACKAGE = Barcode::ZBar::Scanner PREFIX = zbar_scanner_ + +Barcode::ZBar::Scanner +new(package, decoder = 0) + char * package + Barcode::ZBar::Decoder decoder + CODE: + RETVAL = zbar_scanner_create(decoder); + OUTPUT: + RETVAL + +void +DESTROY(scanner) + Barcode::ZBar::Scanner scanner + CODE: + zbar_scanner_destroy(scanner); + +zbar_symbol_type_t +zbar_scanner_reset(scanner) + Barcode::ZBar::Scanner scanner + +zbar_symbol_type_t +zbar_scanner_new_scan(scanner) + Barcode::ZBar::Scanner scanner + +zbar_color_t +zbar_scanner_get_color(scanner) + Barcode::ZBar::Scanner scanner + +unsigned +zbar_scanner_get_width(scanner) + Barcode::ZBar::Scanner scanner + +zbar_symbol_type_t +scan_y(scanner, y) + Barcode::ZBar::Scanner scanner + int y + CODE: + RETVAL = zbar_scan_y(scanner, y); + OUTPUT: + RETVAL diff --git a/perl/Zebra/Image.pod b/perl/ZBar/Image.pod similarity index 75% rename from perl/Zebra/Image.pod rename to perl/ZBar/Image.pod index f3322f1..6b3fc31 100644 --- a/perl/Zebra/Image.pod +++ b/perl/ZBar/Image.pod @@ -1,37 +1,37 @@ #------------------------------------------------------------------------ # Copyright 2008-2009 (c) Jeff Brown # -# This file is part of the Zebra Barcode Library. +# This file is part of the ZBar Bar Code Reader. # -# The Zebra Barcode Library is free software; you can redistribute it +# 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 Zebra Barcode Library is distributed in the hope that it will be +# 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 Zebra Barcode Library; if not, write to the Free +# 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/zebra +# http://sourceforge.net/projects/zbar #------------------------------------------------------------------------ =pod =head1 NAME -Barcode::Zebra::Image - image object to scan for bar codes +Barcode::ZBar::Image - image object to scan for bar codes =head1 SYNOPSIS - use Barcode::Zebra; + use Barcode::ZBar; - my $image = Barcode::Zebra::Image->new(); + my $image = Barcode::ZBar::Image->new(); $image->set_format('422P'); $image->set_size(114, 80); $image->set_data($raw_bits); @@ -40,7 +40,7 @@ Barcode::Zebra::Image - image object to scan for bar codes =head1 DESCRIPTION -Barcode::Zebra::Image is used to pass images to the bar code scanner. +Barcode::ZBar::Image is used to pass images to the bar code scanner. It wraps raw image data with the meta-data required to interpret it (size, pixel format, etc) @@ -76,7 +76,7 @@ Examples: =item new() -Create a new Barcode::Zebra::Image object. The size, pixel format and +Create a new Barcode::ZBar::Image object. The size, pixel format and data must be defined before the object may be used. =item get_format() @@ -105,12 +105,12 @@ Return/specify the raw image data as a binary string. =item get_symbols() -Return a list of scanned Barcode::Zebra::Symbol results attached to +Return a list of scanned Barcode::ZBar::Symbol results attached to this image. =item convert(I) -Return a new Barcode::Zebra::Image object converted to the indicated +Return a new Barcode::ZBar::Image object converted to the indicated fourcc format. Returns C if the conversion is not supported. Conversion complexity ranges from CPU intensive to trivial depending on the formats involved. Note that only a few conversions retain @@ -120,11 +120,11 @@ color information. =head1 SEE ALSO -Barcode::Zebra, Barcode::Zebra::Image, Barcode::Zebra::Symbol +Barcode::ZBar, Barcode::ZBar::Image, Barcode::ZBar::Symbol -zebraimg(1), zebracam(1) +zbarimg(1), zbarcam(1) -http://zebra.sf.net +http://zbar.sf.net =head1 AUTHOR @@ -134,7 +134,7 @@ Jeff Brown, Espadix@users.sourceforge.netE Copyright 2008-2009 (c) Jeff Brown Espadix@users.sourceforge.netE -The Zebra Barcode Library is free software; you can redistribute it +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. diff --git a/perl/Zebra/ImageScanner.pod b/perl/ZBar/ImageScanner.pod similarity index 67% rename from perl/Zebra/ImageScanner.pod rename to perl/ZBar/ImageScanner.pod index e557d4a..db19982 100644 --- a/perl/Zebra/ImageScanner.pod +++ b/perl/ZBar/ImageScanner.pod @@ -1,44 +1,44 @@ #------------------------------------------------------------------------ # Copyright 2008-2009 (c) Jeff Brown # -# This file is part of the Zebra Barcode Library. +# This file is part of the ZBar Bar Code Reader. # -# The Zebra Barcode Library is free software; you can redistribute it +# 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 Zebra Barcode Library is distributed in the hope that it will be +# 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 Zebra Barcode Library; if not, write to the Free +# 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/zebra +# http://sourceforge.net/projects/zbar #------------------------------------------------------------------------ =pod =head1 NAME -Barcode::Zebra::ImageScanner - scan images for bar codes +Barcode::ZBar::ImageScanner - scan images for bar codes =head1 SYNOPSIS - use Barcode::Zebra; + use Barcode::ZBar; - my $scanner = Barcode::Zebra::ImageScanner->new(); + my $scanner = Barcode::ZBar::ImageScanner->new(); $scanner->parse_config('i25.disable'); $scanner->scan_image($image); =head1 DESCRIPTION -A Barcode::Zebra::ImageScanner is used to scan for bar codes in a -Barcode::Zebra::Image. +A Barcode::ZBar::ImageScanner is used to scan for bar codes in a +Barcode::ZBar::Image. =head1 REFERENCE @@ -52,7 +52,7 @@ Create a new bar code image scanner instance. =item scan_image([I]) -Scan a Barcode::Zebra::Image for bar codes. +Scan a Barcode::ZBar::Image for bar codes. =item enable_cache([I]) @@ -61,15 +61,15 @@ Enable the inter-image result consistency cache. =item parse_config(I) Apply a decoder configuration setting. See the documentation for -C/C for available configuration options. +C/C for available configuration options. =back =head1 SEE ALSO -Barcode::Zebra, Barcode::Zebra::Image, zebraimg(1), zebracam(1) +Barcode::ZBar, Barcode::ZBar::Image, zbarimg(1), zbarcam(1) -http://zebra.sf.net +http://zbar.sf.net =head1 AUTHOR @@ -79,7 +79,7 @@ Jeff Brown, Espadix@users.sourceforge.netE Copyright 2008-2009 (c) Jeff Brown Espadix@users.sourceforge.netE -The Zebra Barcode Library is free software; you can redistribute it +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. diff --git a/perl/Zebra/Processor.pod b/perl/ZBar/Processor.pod similarity index 77% rename from perl/Zebra/Processor.pod rename to perl/ZBar/Processor.pod index 5d70bc0..0db7b74 100644 --- a/perl/Zebra/Processor.pod +++ b/perl/ZBar/Processor.pod @@ -1,39 +1,39 @@ #------------------------------------------------------------------------ # Copyright 2008-2009 (c) Jeff Brown # -# This file is part of the Zebra Barcode Library. +# This file is part of the ZBar Bar Code Reader. # -# The Zebra Barcode Library is free software; you can redistribute it +# 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 Zebra Barcode Library is distributed in the hope that it will be +# 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 Zebra Barcode Library; if not, write to the Free +# 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/zebra +# http://sourceforge.net/projects/zbar #------------------------------------------------------------------------ =pod =head1 NAME -Barcode::Zebra::Processor - self-contained bar code reader +Barcode::ZBar::Processor - self-contained bar code reader =head1 SYNOPSIS setup: - use Barcode::Zebra; + use Barcode::ZBar; - my $reader = Barcode::Zebra::Processor->new(); + my $reader = Barcode::ZBar::Processor->new(); $reader->init("/dev/video1", 1); $reader->parse_config('code39.disable'); $reader->set_data_handler(\&my_handler); @@ -50,13 +50,13 @@ scan from video: =head1 DESCRIPTION -A Barcode::Zebra::Processor may be used to quickly create stand-alone +A Barcode::ZBar::Processor may be used to quickly create stand-alone bar code scanning applications. It has interfaces to scan images or video and to optionally display a video/image preview to a window. This interface is not well suited for integration with an existing GUI, as the library manages the optional preview window and any user -interaction. Use a Barcode::Zebra::ImageScanner or Investigate the +interaction. Use a Barcode::ZBar::ImageScanner or Investigate the avilable widget interfaces for GUI applications. =head1 REFERENCE @@ -77,7 +77,7 @@ Open a video input device and/or prepare to display output. Setup a callback to process results whenever new results are available from the video stream or a static image. The specified callable will -be invoked with the associated Barcode::Zebra::Processor object and +be invoked with the associated Barcode::ZBar::Processor object and I as arguments. Closure may be achieved either using standard Perl closure or by manually passing a scalar via I. @@ -103,12 +103,12 @@ multiple results may still be returned. =item process_image([I]) -Scan a Barcode::Zebra::Image for bar codes. +Scan a Barcode::ZBar::Image for bar codes. =item parse_config(I) Apply a decoder configuration setting. See the documentation for -C/C for available configuration options. +C/C for available configuration options. =item request_size(I, I) @@ -120,11 +120,11 @@ called before C =head1 SEE ALSO -Barcode::Zebra, Barcode::Zebra::Image, Barcode::Zebra::ImageScanner +Barcode::ZBar, Barcode::ZBar::Image, Barcode::ZBar::ImageScanner -zebraimg(1), zebracam(1) +zbarimg(1), zbarcam(1) -http://zebra.sf.net +http://zbar.sf.net =head1 AUTHOR @@ -134,7 +134,7 @@ Jeff Brown, Espadix@users.sourceforge.netE Copyright 2008-2009 (c) Jeff Brown Espadix@users.sourceforge.netE -The Zebra Barcode Library is free software; you can redistribute it +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. diff --git a/perl/Zebra/Symbol.pod b/perl/ZBar/Symbol.pod similarity index 79% rename from perl/Zebra/Symbol.pod rename to perl/ZBar/Symbol.pod index 4bef64a..c8f9192 100644 --- a/perl/Zebra/Symbol.pod +++ b/perl/ZBar/Symbol.pod @@ -1,31 +1,31 @@ #------------------------------------------------------------------------ # Copyright 2008-2009 (c) Jeff Brown # -# This file is part of the Zebra Barcode Library. +# This file is part of the ZBar Bar Code Reader. # -# The Zebra Barcode Library is free software; you can redistribute it +# 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 Zebra Barcode Library is distributed in the hope that it will be +# 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 Zebra Barcode Library; if not, write to the Free +# 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/zebra +# http://sourceforge.net/projects/zbar #------------------------------------------------------------------------ =pod =head1 NAME -Barcode::Zebra::Symbol - bar code scan result object +Barcode::ZBar::Symbol - bar code scan result object =head1 SYNOPSIS @@ -38,7 +38,7 @@ Barcode::Zebra::Symbol - bar code scan result object =head1 DESCRIPTION -Barcode::Zebra::Symbol objects are constant results returned for each +Barcode::ZBar::Symbol objects are constant results returned for each bar code scanned from images or video. This object wraps the raw symbol data with additional information about the decode (symbology, confidence, location, etc) @@ -62,7 +62,7 @@ data. Current cache count of the symbol. This integer value provides inter-scan reliability and redundancy information if enabled at the -Barcode::Zebra::ImageScanner. +Barcode::ZBar::ImageScanner. =over 2 @@ -115,11 +115,11 @@ Bar code type "symbology" constants: =head1 SEE ALSO -Barcode::Zebra, Barcode::Zebra::Image +Barcode::ZBar, Barcode::ZBar::Image -zebraimg(1), zebracam(1) +zbarimg(1), zbarcam(1) -http://zebra.sf.net +http://zbar.sf.net =head1 AUTHOR @@ -129,7 +129,7 @@ Jeff Brown, Espadix@users.sourceforge.netE Copyright 2008-2009 (c) Jeff Brown Espadix@users.sourceforge.netE -The Zebra Barcode Library is free software; you can redistribute it +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. diff --git a/perl/Zebra.xs b/perl/Zebra.xs deleted file mode 100644 index 0f3b7b8..0000000 --- a/perl/Zebra.xs +++ /dev/null @@ -1,712 +0,0 @@ -//------------------------------------------------------------------------ -// Copyright 2008-2009 (c) Jeff Brown -// -// This file is part of the Zebra Barcode Library. -// -// The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free -// Software Foundation, Inc., 51 Franklin St, Fifth Floor, -// Boston, MA 02110-1301 USA -// -// http://sourceforge.net/projects/zebra -//------------------------------------------------------------------------ -#include "EXTERN.h" -#include "perl.h" -#include "XSUB.h" - -#include "ppport.h" - -#include - -typedef zebra_symbol_t *Barcode__Zebra__Symbol; -typedef zebra_image_t *Barcode__Zebra__Image; -typedef zebra_processor_t *Barcode__Zebra__Processor; -typedef zebra_video_t *Barcode__Zebra__Video; -typedef zebra_window_t *Barcode__Zebra__Window; -typedef zebra_image_scanner_t *Barcode__Zebra__ImageScanner; -typedef zebra_decoder_t *Barcode__Zebra__Decoder; -typedef zebra_scanner_t *Barcode__Zebra__Scanner; -typedef void *Barcode__Zebra__Error; - -typedef unsigned long fourcc_t; -typedef int timeout_t; -typedef int config_error; - -typedef struct handler_wrapper_s { - SV *instance; - SV *handler; - SV *closure; -} handler_wrapper_t; - - -static AV *LOOKUP_zebra_color_t = NULL; -static AV *LOOKUP_zebra_symbol_type_t = NULL; -static AV *LOOKUP_zebra_error_t = NULL; -static AV *LOOKUP_zebra_config_t = NULL; - -#define CONSTANT(typ, prefix, sym, name) \ - do { \ - SV *c = newSViv(ZEBRA_ ## prefix ## sym); \ - sv_setpv(c, name); \ - SvIOK_on(c); \ - newCONSTSUB(stash, #sym, c); \ - av_store(LOOKUP_zebra_ ## typ ## _t, \ - ZEBRA_ ## prefix ## sym, \ - SvREFCNT_inc(c)); \ - } while(0) - -#define LOOKUP_ENUM(typ, val) \ - lookup_enum(LOOKUP_zebra_ ## typ ## _t, val) - -static inline SV *lookup_enum (AV *lookup, int val) -{ - SV **tmp = av_fetch(lookup, val, 0); - return((tmp) ? *tmp : sv_newmortal()); -} - -static inline void check_error (int rc, void *obj) -{ - if(rc < 0) { - sv_setref_pv(get_sv("@", TRUE), "Barcode::Zebra::Error", obj); - croak(NULL); - } -} - -static void image_cleanup_handler (zebra_image_t *image) -{ - SV *data = zebra_image_get_userdata(image); - if(!data) - /* FIXME this is internal error */ - return; - - /* release reference to cleanup data */ - SvREFCNT_dec(data); -} - -static inline int set_handler (handler_wrapper_t **wrapp, - SV *instance, - SV *handler, - SV *closure) -{ - handler_wrapper_t *wrap = *wrapp; - if(!handler || !SvOK(handler)) { - if(wrap) { - if(wrap->instance) SvREFCNT_dec(wrap->instance); - if(wrap->handler) SvREFCNT_dec(wrap->handler); - if(wrap->closure) SvREFCNT_dec(wrap->closure); - wrap->instance = wrap->handler = wrap->closure = NULL; - } - return(0); - } - - if(!wrap) { - Newxz(wrap, 1, handler_wrapper_t); - wrap->instance = newSVsv(instance); - wrap->closure = newSV(0); - *wrapp = wrap; - } - - if(wrap->handler) - SvSetSV(wrap->handler, handler); - else - wrap->handler = newSVsv(handler); - - if(!closure || !SvOK(closure)) - SvSetSV(wrap->closure, &PL_sv_undef); - else - SvSetSV(wrap->closure, closure); - return(1); -} - -static inline void activate_handler (handler_wrapper_t *wrap, - SV *param) -{ - dSP; - if(!wrap) - /* FIXME this is internal error */ - return; - - ENTER; - SAVETMPS; - - PUSHMARK(SP); - EXTEND(SP, 2); - PUSHs(sv_mortalcopy(wrap->instance)); - if(param) - PUSHs(param); - PUSHs(sv_mortalcopy(wrap->closure)); - PUTBACK; - - call_sv(wrap->handler, G_DISCARD); - - FREETMPS; - LEAVE; -} - -static void processor_handler (zebra_image_t *image, - const void *userdata) -{ - SV *img; - zebra_image_ref(image, 1); - img = sv_setref_pv(newSV(0), "Barcode::Zebra::Image", image); - activate_handler((void*)userdata, img); - SvREFCNT_dec(img); -} - -static void decoder_handler (zebra_decoder_t *decoder) -{ - activate_handler(zebra_decoder_get_userdata(decoder), NULL); -} - - -MODULE = Barcode::Zebra PACKAGE = Barcode::Zebra PREFIX = zebra_ - -PROTOTYPES: ENABLE - -BOOT: - { - HV *stash = gv_stashpv("Barcode::Zebra", TRUE); - - LOOKUP_zebra_color_t = newAV(); - CONSTANT(color, , SPACE, "SPACE"); - CONSTANT(color, , BAR, "BAR"); - } - -SV * -zebra_version() - PREINIT: - unsigned major; - unsigned minor; - CODE: - zebra_version(&major, &minor); - RETVAL = newSVpvf("%u.%u", major, minor); - OUTPUT: - RETVAL - -void -zebra_increase_verbosity() - -void -zebra_set_verbosity(verbosity) - int verbosity - -SV * -parse_config(config_string) - const char * config_string - PREINIT: - zebra_symbol_type_t sym; - zebra_config_t cfg; - int val; - PPCODE: - if(zebra_parse_config(config_string, &sym, &cfg, &val)) - croak("invalid configuration setting: %s", config_string); - EXTEND(SP, 3); - PUSHs(LOOKUP_ENUM(symbol_type, sym)); - PUSHs(LOOKUP_ENUM(config, cfg)); - mPUSHi(val); - - -MODULE = Barcode::Zebra PACKAGE = Barcode::Zebra::Error PREFIX = zebra_ - -BOOT: - { - HV *stash = gv_stashpv("Barcode::Zebra::Error", TRUE); - - LOOKUP_zebra_error_t = newAV(); - CONSTANT(error, ERR_, NOMEM, "out of memory"); - CONSTANT(error, ERR_, INTERNAL, "internal library error"); - CONSTANT(error, ERR_, UNSUPPORTED, "unsupported request"); - CONSTANT(error, ERR_, INVALID, "invalid request"); - CONSTANT(error, ERR_, SYSTEM, "system error"); - CONSTANT(error, ERR_, LOCKING, "locking error"); - CONSTANT(error, ERR_, BUSY, "all resources busy"); - CONSTANT(error, ERR_, XDISPLAY, "X11 display error"); - CONSTANT(error, ERR_, XPROTO, "X11 protocol error"); - CONSTANT(error, ERR_, CLOSED, "output window is closed"); - } - -zebra_error_t -get_error_code(err) - Barcode::Zebra::Error err - CODE: - RETVAL = _zebra_get_error_code(err); - OUTPUT: - RETVAL - -const char * -error_string(err) - Barcode::Zebra::Error err - CODE: - RETVAL = _zebra_error_string(err, 1); - OUTPUT: - RETVAL - - -MODULE = Barcode::Zebra PACKAGE = Barcode::Zebra::Config PREFIX = zebra_config_ - -BOOT: - { - HV *stash = gv_stashpv("Barcode::Zebra::Config", TRUE); - - LOOKUP_zebra_config_t = newAV(); - CONSTANT(config, CFG_, ENABLE, "enable"); - CONSTANT(config, CFG_, ADD_CHECK, "add-check"); - CONSTANT(config, CFG_, EMIT_CHECK, "emit-check"); - CONSTANT(config, CFG_, ASCII, "ascii"); - CONSTANT(config, CFG_, MIN_LEN, "min-length"); - CONSTANT(config, CFG_, MAX_LEN, "max-length"); - CONSTANT(config, CFG_, X_DENSITY, "x-density"); - CONSTANT(config, CFG_, Y_DENSITY, "y-density"); - } - - -MODULE = Barcode::Zebra PACKAGE = Barcode::Zebra::Symbol PREFIX = zebra_symbol_ - -BOOT: - { - HV *stash = gv_stashpv("Barcode::Zebra::Symbol", TRUE); - - LOOKUP_zebra_symbol_type_t = newAV(); - CONSTANT(symbol_type, , NONE, "None"); - CONSTANT(symbol_type, , PARTIAL, "Partial"); - CONSTANT(symbol_type, , EAN8, zebra_get_symbol_name(ZEBRA_EAN8)); - CONSTANT(symbol_type, , UPCE, zebra_get_symbol_name(ZEBRA_UPCE)); - CONSTANT(symbol_type, , ISBN10, zebra_get_symbol_name(ZEBRA_ISBN10)); - CONSTANT(symbol_type, , UPCA, zebra_get_symbol_name(ZEBRA_UPCA)); - CONSTANT(symbol_type, , EAN13, zebra_get_symbol_name(ZEBRA_EAN13)); - CONSTANT(symbol_type, , ISBN13, zebra_get_symbol_name(ZEBRA_ISBN13)); - CONSTANT(symbol_type, , I25, zebra_get_symbol_name(ZEBRA_I25)); - CONSTANT(symbol_type, , CODE39, zebra_get_symbol_name(ZEBRA_CODE39)); - CONSTANT(symbol_type, , PDF417, zebra_get_symbol_name(ZEBRA_PDF417)); - CONSTANT(symbol_type, , CODE128, zebra_get_symbol_name(ZEBRA_CODE128)); - } - -zebra_symbol_type_t -zebra_symbol_get_type(symbol) - Barcode::Zebra::Symbol symbol - -const char * -zebra_symbol_get_data(symbol) - Barcode::Zebra::Symbol symbol - -int -zebra_symbol_get_count(symbol) - Barcode::Zebra::Symbol symbol - -SV * -zebra_symbol_get_loc(symbol) - Barcode::Zebra::Symbol symbol - PREINIT: - unsigned i, size; - PPCODE: - size = zebra_symbol_get_loc_size(symbol); - EXTEND(SP, size); - for(i = 0; i < size; i++) { - AV *pt = (AV*)sv_2mortal((SV*)newAV()); - PUSHs(newRV((SV*)pt)); - av_push(pt, newSVuv(zebra_symbol_get_loc_x(symbol, i))); - av_push(pt, newSVuv(zebra_symbol_get_loc_y(symbol, i))); - } - - -MODULE = Barcode::Zebra PACKAGE = Barcode::Zebra::Image PREFIX = zebra_image_ - -Barcode::Zebra::Image -new(package) - char * package - CODE: - RETVAL = zebra_image_create(); - OUTPUT: - RETVAL - -void -DESTROY(image) - Barcode::Zebra::Image image - CODE: - zebra_image_destroy(image); - -Barcode::Zebra::Image -zebra_image_convert(image, format) - Barcode::Zebra::Image image - fourcc_t format - -Barcode::Zebra::Image -zebra_image_convert_resize(image, format, width, height) - Barcode::Zebra::Image image - fourcc_t format - unsigned width - unsigned height - -fourcc_t -zebra_image_get_format(image) - Barcode::Zebra::Image image - -unsigned -zebra_image_get_sequence(image) - Barcode::Zebra::Image image - -void -get_size(image) - Barcode::Zebra::Image image - PPCODE: - EXTEND(SP, 2); - mPUSHu(zebra_image_get_width(image)); - mPUSHu(zebra_image_get_height(image)); - -SV * -zebra_image_get_data(image) - Barcode::Zebra::Image image - CODE: - RETVAL = newSVpvn(zebra_image_get_data(image), - zebra_image_get_data_length(image)); - OUTPUT: - RETVAL - -SV * -get_symbols(image) - Barcode::Zebra::Image image - PREINIT: - const zebra_symbol_t *sym; - PPCODE: - sym = zebra_image_first_symbol(image); - for(; sym; sym = zebra_symbol_next(sym)) - XPUSHs(sv_setref_pv(sv_newmortal(), "Barcode::Zebra::Symbol", - (void*)sym)); - -void -zebra_image_set_format(image, format) - Barcode::Zebra::Image image - fourcc_t format - -void -zebra_image_set_sequence(image, seq_num) - Barcode::Zebra::Image image - unsigned seq_num - -void -zebra_image_set_size(image, width, height) - Barcode::Zebra::Image image - unsigned width - unsigned height - -void -zebra_image_set_data(image, data) - Barcode::Zebra::Image image - SV * data - PREINIT: - SV *old; - CODE: - if(!data || !SvOK(data)) { - zebra_image_set_data(image, NULL, 0, NULL); - zebra_image_set_userdata(image, NULL); - } - else if(SvPOK(data)) { - /* FIXME is this copy of data or new ref to same data? - * not sure this is correct: - * need to retain a reference to image data, - * but do not really want to copy it...maybe an RV? - */ - SV *copy = newSVsv(data); - STRLEN len; - void *raw = SvPV(copy, len); - zebra_image_set_data(image, raw, len, image_cleanup_handler); - zebra_image_set_userdata(image, copy); - } - else - croak("image data must be binary string"); - - -MODULE = Barcode::Zebra PACKAGE = Barcode::Zebra::Processor PREFIX = zebra_processor_ - -Barcode::Zebra::Processor -new(package, threaded=0) - char * package - bool threaded - CODE: - RETVAL = zebra_processor_create(threaded); - OUTPUT: - RETVAL - -void -DESTROY(processor) - Barcode::Zebra::Processor processor - CODE: - zebra_processor_destroy(processor); - -void -zebra_processor_init(processor, video_device="/dev/video0", enable_display=1) - Barcode::Zebra::Processor processor - const char * video_device - bool enable_display - CODE: - check_error(zebra_processor_init(processor, video_device, enable_display), - processor); - -void -zebra_processor_request_size(processor, width, height) - Barcode::Zebra::Processor processor - unsigned width - unsigned height - CODE: - check_error(zebra_processor_request_size(processor, width, height), - processor); - -void -zebra_processor_force_format(processor, input_format=0, output_format=0) - Barcode::Zebra::Processor processor - fourcc_t input_format - fourcc_t output_format - CODE: - check_error(zebra_processor_force_format(processor, input_format, output_format), - processor); - -void -zebra_processor_set_config(processor, symbology, config, value=1) - Barcode::Zebra::Processor processor - zebra_symbol_type_t symbology - zebra_config_t config - int value - -config_error -zebra_processor_parse_config(processor, config_string) - Barcode::Zebra::Processor processor - const char *config_string - -bool -zebra_processor_is_visible(processor) - Barcode::Zebra::Processor processor - CODE: - check_error((RETVAL = zebra_processor_is_visible(processor)), - processor); - OUTPUT: - RETVAL - -void -zebra_processor_set_visible(processor, visible=1) - Barcode::Zebra::Processor processor - bool visible - CODE: - check_error(zebra_processor_set_visible(processor, visible), - processor); - -void -zebra_processor_set_active(processor, active=1) - Barcode::Zebra::Processor processor - bool active - CODE: - check_error(zebra_processor_set_active(processor, active), - processor); - -int -zebra_processor_user_wait(processor, timeout=-1) - Barcode::Zebra::Processor processor - timeout_t timeout - CODE: - check_error((RETVAL = zebra_processor_user_wait(processor, timeout)), - processor); - OUTPUT: - RETVAL - -int -process_one(processor, timeout=-1) - Barcode::Zebra::Processor processor - timeout_t timeout - CODE: - check_error((RETVAL = zebra_process_one(processor, timeout)), - processor); - OUTPUT: - RETVAL - -int -process_image(processor, image) - Barcode::Zebra::Processor processor - Barcode::Zebra::Image image - CODE: - check_error((RETVAL = zebra_process_image(processor, image)), - processor); - OUTPUT: - RETVAL - -void -zebra_processor_set_data_handler(processor, handler = 0, closure = 0) - Barcode::Zebra::Processor processor - SV * handler - SV * closure - PREINIT: - handler_wrapper_t *wrap; - zebra_image_data_handler_t *callback = NULL; - CODE: - wrap = zebra_processor_get_userdata(processor); - if(set_handler(&wrap, ST(0), handler, closure)) - callback = processor_handler; - zebra_processor_set_data_handler(processor, callback, wrap); - - -MODULE = Barcode::Zebra PACKAGE = Barcode::Zebra::ImageScanner PREFIX = zebra_image_scanner_ - -Barcode::Zebra::ImageScanner -new(package) - char * package - CODE: - RETVAL = zebra_image_scanner_create(); - OUTPUT: - RETVAL - -void -DESTROY(scanner) - Barcode::Zebra::ImageScanner scanner - CODE: - zebra_image_scanner_destroy(scanner); - -void -zebra_image_scanner_set_config(scanner, symbology, config, value=1) - Barcode::Zebra::ImageScanner scanner - zebra_symbol_type_t symbology - zebra_config_t config - int value - -config_error -zebra_image_scanner_parse_config(scanner, config_string) - Barcode::Zebra::ImageScanner scanner - const char *config_string - -void -zebra_image_scanner_enable_cache(scanner, enable) - Barcode::Zebra::ImageScanner scanner - int enable - -int -scan_image(scanner, image) - Barcode::Zebra::ImageScanner scanner - Barcode::Zebra::Image image - CODE: - RETVAL = zebra_scan_image(scanner, image); - OUTPUT: - RETVAL - - -MODULE = Barcode::Zebra PACKAGE = Barcode::Zebra::Decoder PREFIX = zebra_decoder_ - -Barcode::Zebra::Decoder -new(package) - char * package - CODE: - RETVAL = zebra_decoder_create(); - OUTPUT: - RETVAL - -void -DESTROY(decoder) - Barcode::Zebra::Decoder decoder - CODE: - /* FIXME cleanup handler wrapper */ - zebra_decoder_destroy(decoder); - -void -zebra_decoder_set_config(decoder, symbology, config, value=1) - Barcode::Zebra::Decoder decoder - zebra_symbol_type_t symbology - zebra_config_t config - int value - -config_error -zebra_decoder_parse_config(decoder, config_string) - Barcode::Zebra::Decoder decoder - const char *config_string - -void -zebra_decoder_reset(decoder) - Barcode::Zebra::Decoder decoder - -void -zebra_decoder_new_scan(decoder) - Barcode::Zebra::Decoder decoder - -zebra_symbol_type_t -decode_width(decoder, width) - Barcode::Zebra::Decoder decoder - unsigned width - CODE: - RETVAL = zebra_decode_width(decoder, width); - OUTPUT: - RETVAL - -zebra_color_t -zebra_decoder_get_color(decoder) - Barcode::Zebra::Decoder decoder - -const char * -zebra_decoder_get_data(decoder) - Barcode::Zebra::Decoder decoder - -zebra_symbol_type_t -zebra_decoder_get_type(decoder) - Barcode::Zebra::Decoder decoder - -void -zebra_decoder_set_handler(decoder, handler = 0, closure = 0) - Barcode::Zebra::Decoder decoder - SV * handler - SV * closure - PREINIT: - handler_wrapper_t *wrap; - CODE: - wrap = zebra_decoder_get_userdata(decoder); - zebra_decoder_set_handler(decoder, NULL); - if(set_handler(&wrap, ST(0), handler, closure)) { - zebra_decoder_set_userdata(decoder, wrap); - zebra_decoder_set_handler(decoder, decoder_handler); - } - - -MODULE = Barcode::Zebra PACKAGE = Barcode::Zebra::Scanner PREFIX = zebra_scanner_ - -Barcode::Zebra::Scanner -new(package, decoder = 0) - char * package - Barcode::Zebra::Decoder decoder - CODE: - RETVAL = zebra_scanner_create(decoder); - OUTPUT: - RETVAL - -void -DESTROY(scanner) - Barcode::Zebra::Scanner scanner - CODE: - zebra_scanner_destroy(scanner); - -zebra_symbol_type_t -zebra_scanner_reset(scanner) - Barcode::Zebra::Scanner scanner - -zebra_symbol_type_t -zebra_scanner_new_scan(scanner) - Barcode::Zebra::Scanner scanner - -zebra_color_t -zebra_scanner_get_color(scanner) - Barcode::Zebra::Scanner scanner - -unsigned -zebra_scanner_get_width(scanner) - Barcode::Zebra::Scanner scanner - -zebra_symbol_type_t -scan_y(scanner, y) - Barcode::Zebra::Scanner scanner - int y - CODE: - RETVAL = zebra_scan_y(scanner, y); - OUTPUT: - RETVAL diff --git a/perl/examples/paginate.pl b/perl/examples/paginate.pl new file mode 100755 index 0000000..68ffe50 --- /dev/null +++ b/perl/examples/paginate.pl @@ -0,0 +1,71 @@ +#!/usr/bin/perl +#------------------------------------------------------------------------ +# Copyright 2009 (c) Jeff Brown +# +# 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); +} diff --git a/perl/examples/processor.pl b/perl/examples/processor.pl new file mode 100755 index 0000000..e14a4a3 --- /dev/null +++ b/perl/examples/processor.pl @@ -0,0 +1,34 @@ +#!/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 ($image->get_symbols()) { + # do something useful with results + print('decoded ' . $symbol->get_type() . + ' symbol "' . $symbol->get_data() . "\"\n") + if(!$symbol->get_count()); + } +} +$proc->set_data_handler(\&my_handler); + +# enable the preview window +$proc->set_visible(); + +# initiate scanning +$proc->set_active(); +$proc->user_wait(); diff --git a/perl/examples/scan_image.pl b/perl/examples/scan_image.pl new file mode 100755 index 0000000..3734d19 --- /dev/null +++ b/perl/examples/scan_image.pl @@ -0,0 +1,37 @@ +#!/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'); + +# 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); diff --git a/perl/inc/Devel/CheckLib.pm b/perl/inc/Devel/CheckLib.pm new file mode 100644 index 0000000..d7167f4 --- /dev/null +++ b/perl/inc/Devel/CheckLib.pm @@ -0,0 +1,350 @@ +# $Id: CheckLib.pm,v 1.22 2008/03/12 19:52:50 drhyde Exp $ + +package Devel::CheckLib; + +use strict; +use vars qw($VERSION @ISA @EXPORT); +$VERSION = '0.5'; +use Config; + +use File::Spec; +use File::Temp; + +require Exporter; +@ISA = qw(Exporter); +@EXPORT = qw(assert_lib check_lib_or_exit); + +# localising prevents the warningness leaking out of this module +local $^W = 1; # use warnings is a 5.6-ism + +_findcc(); # bomb out early if there's no compiler + +=head1 NAME + +Devel::CheckLib - check that a library is available + +=head1 DESCRIPTION + +Devel::CheckLib is a perl module that checks whether a particular C +library and its headers are available. + +=head1 SYNOPSIS + + # in a Makefile.PL or Build.PL + use lib qw(inc); + use Devel::CheckLib; + + check_lib_or_exit( lib => 'jpeg', header => 'jpeglib.h' ); + check_lib_or_exit( lib => [ 'iconv', 'jpeg' ] ); + + # or prompt for path to library and then do this: + check_lib_or_exit( lib => 'jpeg', libpath => $additional_path ); + +=head1 HOW IT WORKS + +You pass named parameters to a function, describing to it how to build +and link to the libraries. + +It works by trying to compile this: + + int main(void) { return 0; } + +and linking it to the specified libraries. If something pops out the end +which looks executable, then we know that it worked. That tiny program is +built once for each library that you specify, and (without linking) once +for each header file. + +=head1 FUNCTIONS + +All of these take the same named parameters and are exported by default. +To avoid exporting them, C. + +=head2 assert_lib + +This takes several named parameters, all of which are optional, and dies +with an error message if any of the libraries listed can +not be found. B: dying in a Makefile.PL or Build.PL may provoke +a 'FAIL' report from CPAN Testers' automated smoke testers. Use +C instead. + +The named parameters are: + +=over + +=item lib + +Must be either a string with the name of a single +library or a reference to an array of strings of library names. Depending +on the compiler found, library names will be fed to the compiler either as +C<-l> arguments or as C<.lib> file names. (E.g. C<-ljpeg> or C) + +=item libpath + +a string or an array of strings +representing additional paths to search for libraries. + +=item LIBS + +a C-style space-seperated list of +libraries (each preceded by '-l') and directories (preceded by '-L'). + +=back + +And libraries are no use without header files, so ... + +=over + +=item header + +Must be either a string with the name of a single +header file or a reference to an array of strings of header file names. + +=item incpath + +a string or an array of strings +representing additional paths to search for headers. + +=item INC + +a C-style space-seperated list of +incpaths, each preceded by '-I'. + +=back + +=head2 check_lib_or_exit + +This behaves exactly the same as C except that instead of +dieing, it warns (with exactly the same error message) and exits. +This is intended for use in Makefile.PL / Build.PL +when you might want to prompt the user for various paths and +things before checking that what they've told you is sane. + +If any library or header is missing, it exits with an exit value of 0 to avoid +causing a CPAN Testers 'FAIL' report. CPAN Testers should ignore this +result -- which is what you want if an external library dependency is not +available. + +=cut + +sub check_lib_or_exit { + eval 'assert_lib(@_)'; + if($@) { + warn $@; + exit; + } +} + +sub assert_lib { + my %args = @_; + my (@libs, @libpaths, @headers, @incpaths); + + # FIXME: these four just SCREAM "refactor" at me + @libs = (ref($args{lib}) ? @{$args{lib}} : $args{lib}) + if $args{lib}; + @libpaths = (ref($args{libpath}) ? @{$args{libpath}} : $args{libpath}) + if $args{libpath}; + @headers = (ref($args{header}) ? @{$args{header}} : $args{header}) + if $args{header}; + @incpaths = (ref($args{incpath}) ? @{$args{incpath}} : $args{incpath}) + if $args{incpath}; + + # work-a-like for Makefile.PL's LIBS and INC arguments + if(defined($args{LIBS})) { + foreach my $arg (split(/\s+/, $args{LIBS})) { + die("LIBS argument badly-formed: $arg\n") unless($arg =~ /^-l/i); + push @{$arg =~ /^-l/ ? \@libs : \@libpaths}, substr($arg, 2); + } + } + if(defined($args{INC})) { + foreach my $arg (split(/\s+/, $args{INC})) { + die("INC argument badly-formed: $arg\n") unless($arg =~ /^-I/); + push @incpaths, substr($arg, 2); + } + } + + my @cc = _findcc(); + my @missing; + + # first figure out which headers we can't find ... + for my $header (@headers) { + my($ch, $cfile) = File::Temp::tempfile( + 'assertlibXXXXXXXX', SUFFIX => '.c' + ); + print $ch qq{#include <$header>\nint main(void) { return 0; }\n}; + close($ch); + my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe}; + my @sys_cmd; + # FIXME: re-factor - almost identical code later when linking + if ( $Config{cc} eq 'cl' ) { # Microsoft compiler + require Win32; + @sys_cmd = (@cc, $cfile, "/Fe$exefile", (map { '/I'.Win32::GetShortPathName($_) } @incpaths)); + } elsif($Config{cc} =~ /bcc32(\.exe)?/) { # Borland + @sys_cmd = (@cc, (map { "-I$_" } @incpaths), "-o$exefile", $cfile); + } else { # Unix-ish + # gcc, Sun, AIX (gcc, cc) + @sys_cmd = (@cc, $cfile, (map { "-I$_" } @incpaths), "-o", "$exefile"); + } + warn "# @sys_cmd\n" if $args{debug}; + my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd); + push @missing, $header if $rv != 0 || ! -x $exefile; + _cleanup_exe($exefile); + unlink $cfile; + } + + # now do each library in turn with no headers + my($ch, $cfile) = File::Temp::tempfile( + 'assertlibXXXXXXXX', SUFFIX => '.c' + ); + print $ch "int main(void) { return 0; }\n"; + close($ch); + for my $lib ( @libs ) { + my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe}; + my @sys_cmd; + if ( $Config{cc} eq 'cl' ) { # Microsoft compiler + require Win32; + my @libpath = map { + q{/libpath:} . Win32::GetShortPathName($_) + } @libpaths; + @sys_cmd = (@cc, $cfile, "${lib}.lib", "/Fe$exefile", + "/link", @libpath + ); + } elsif($Config{cc} eq 'CC/DECC') { # VMS + } elsif($Config{cc} =~ /bcc32(\.exe)?/) { # Borland + my @libpath = map { "-L$_" } @libpaths; + @sys_cmd = (@cc, "-o$exefile", "-l$lib", @libpath, $cfile); + } else { # Unix-ish + # gcc, Sun, AIX (gcc, cc) + my @libpath = map { "-L$_" } @libpaths; + @sys_cmd = (@cc, $cfile, "-o", "$exefile", "-l$lib", @libpath); + } + warn "# @sys_cmd\n" if $args{debug}; + my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd); + push @missing, $lib if $rv != 0 || ! -x $exefile; + _cleanup_exe($exefile); + } + unlink $cfile; + + my $miss_string = join( q{, }, map { qq{'$_'} } @missing ); + die("Can't link/include $miss_string\n") if @missing; +} + +sub _cleanup_exe { + my ($exefile) = @_; + my $ofile = $exefile; + $ofile =~ s/$Config{_exe}$/$Config{_o}/; + unlink $exefile if -f $exefile; + unlink $ofile if -f $ofile; + unlink "$exefile\.manifest" if -f "$exefile\.manifest"; + return +} + +sub _findcc { + my @paths = split(/$Config{path_sep}/, $ENV{PATH}); + my @cc = split(/\s+/, $Config{cc}); + return @cc if -x $cc[0]; + foreach my $path (@paths) { + my $compiler = File::Spec->catfile($path, $cc[0]) . $Config{_exe}; + return ($compiler, @cc[1 .. $#cc]) if -x $compiler; + } + die("Couldn't find your C compiler\n"); +} + +# code substantially borrowed from IPC::Run3 +sub _quiet_system { + my (@cmd) = @_; + + # save handles + local *STDOUT_SAVE; + local *STDERR_SAVE; + open STDOUT_SAVE, ">&STDOUT" or die "CheckLib: $! saving STDOUT"; + open STDERR_SAVE, ">&STDERR" or die "CheckLib: $! saving STDERR"; + + # redirect to nowhere + local *DEV_NULL; + open DEV_NULL, ">" . File::Spec->devnull + or die "CheckLib: $! opening handle to null device"; + open STDOUT, ">&" . fileno DEV_NULL + or die "CheckLib: $! redirecting STDOUT to null handle"; + open STDERR, ">&" . fileno DEV_NULL + or die "CheckLib: $! redirecting STDERR to null handle"; + + # run system command + my $rv = system(@cmd); + + # restore handles + open STDOUT, ">&" . fileno STDOUT_SAVE + or die "CheckLib: $! restoring STDOUT handle"; + open STDERR, ">&" . fileno STDERR_SAVE + or die "CheckLib: $! restoring STDERR handle"; + + return $rv; +} + +=head1 PLATFORMS SUPPORTED + +You must have a C compiler installed. We check for C<$Config{cc}>, +both literally as it is in Config.pm and also in the $PATH. + +It has been tested with varying degrees on rigourousness on: + +=over + +=item gcc (on Linux, *BSD, Mac OS X, Solaris, Cygwin) + +=item Sun's compiler tools on Solaris + +=item IBM's tools on AIX + +=item Microsoft's tools on Windows + +=item MinGW on Windows (with Strawberry Perl) + +=item Borland's tools on Windows + +=back + +=head1 WARNINGS, BUGS and FEEDBACK + +This is a very early release intended primarily for feedback from +people who have discussed it. The interface may change and it has +not been adequately tested. + +Feedback is most welcome, including constructive criticism. +Bug reports should be made using L or by email. + +When submitting a bug report, please include the output from running: + + perl -V + perl -MDevel::CheckLib -e0 + +=head1 SEE ALSO + +L + +L + +=head1 AUTHORS + +David Cantrell Edavid@cantrell.org.ukE + +David Golden Edagolden@cpan.orgE + +Thanks to the cpan-testers-discuss mailing list for prompting us to write it +in the first place; + +to Chris Williams for help with Borland support. + +=head1 COPYRIGHT and LICENCE + +Copyright 2007 David Cantrell. Portions copyright 2007 David Golden. + +This module is free-as-in-speech software, and may be used, distributed, +and modified under the same conditions as perl itself. + +=head1 CONSPIRACY + +This module is also free-as-in-mason software. + +=cut + +1; diff --git a/perl/t/Decoder.t b/perl/t/Decoder.t index cd91c46..2938d8d 100755 --- a/perl/t/Decoder.t +++ b/perl/t/Decoder.t @@ -7,12 +7,12 @@ use Test::More tests => 13; ######################### -BEGIN { use_ok('Barcode::Zebra') } +BEGIN { use_ok('Barcode::ZBar') } ######################### -my $decoder = Barcode::Zebra::Decoder->new(); -isa_ok($decoder, 'Barcode::Zebra::Decoder', 'decoder'); +my $decoder = Barcode::ZBar::Decoder->new(); +isa_ok($decoder, 'Barcode::ZBar::Decoder', 'decoder'); $decoder->parse_config('enable'); @@ -24,7 +24,7 @@ can_ok($decoder, qw(set_config parse_config reset new_scan decode_width ######################### my $sym = $decoder->decode_width(5); -is($sym, Barcode::Zebra::Symbol::NONE, 'enum/enum compare'); +is($sym, Barcode::ZBar::Symbol::NONE, 'enum/enum compare'); ######################### @@ -46,7 +46,7 @@ $decoder->set_handler(sub { my $type = $_[0]->get_type(); $handler_type = $type - if(!$handler_type or $type > Barcode::Zebra::Symbol::PARTIAL); + if(!$handler_type or $type > Barcode::ZBar::Symbol::PARTIAL); ${$_[1]} += 1 }, \$explicit_closure); @@ -54,7 +54,7 @@ $decoder->set_handler(sub { ######################### $decoder->reset(); -is($decoder->get_color(), Barcode::Zebra::SPACE, 'reset color'); +is($decoder->get_color(), Barcode::ZBar::SPACE, 'reset color'); ######################### @@ -63,11 +63,11 @@ my $encoded = foreach my $width (split(/ */, $encoded)) { my $tmp = $decoder->decode_width($width); - if($tmp > Barcode::Zebra::Symbol::PARTIAL) { - $sym = ($sym == Barcode::Zebra::Symbol::NONE) ? $tmp : -1; + if($tmp > Barcode::ZBar::Symbol::PARTIAL) { + $sym = ($sym == Barcode::ZBar::Symbol::NONE) ? $tmp : -1; } } -is($sym, Barcode::Zebra::Symbol::EAN13, 'EAN-13 type'); +is($sym, Barcode::ZBar::Symbol::EAN13, 'EAN-13 type'); ######################### @@ -75,11 +75,11 @@ is($decoder->get_data(), '6268964977804', 'EAN-13 data'); ######################### -is($decoder->get_color(), Barcode::Zebra::BAR, 'post-scan color'); +is($decoder->get_color(), Barcode::ZBar::BAR, 'post-scan color'); ######################### -is($handler_type, Barcode::Zebra::Symbol::EAN13, 'handler type'); +is($handler_type, Barcode::ZBar::Symbol::EAN13, 'handler type'); ######################### diff --git a/perl/t/Image.t b/perl/t/Image.t index 7ff08f5..86f5ceb 100755 --- a/perl/t/Image.t +++ b/perl/t/Image.t @@ -7,19 +7,19 @@ use Test::More tests => 16; ######################### -BEGIN { use_ok('Barcode::Zebra') } +BEGIN { use_ok('Barcode::ZBar') } -Barcode::Zebra::set_verbosity(16); +Barcode::ZBar::set_verbosity(16); ######################### -my $image = Barcode::Zebra::Image->new(); -isa_ok($image, 'Barcode::Zebra::Image', 'image'); +my $image = Barcode::ZBar::Image->new(); +isa_ok($image, 'Barcode::ZBar::Image', 'image'); ######################### -my $scanner = Barcode::Zebra::ImageScanner->new(); -isa_ok($scanner, 'Barcode::Zebra::ImageScanner', 'image scanner'); +my $scanner = Barcode::ZBar::ImageScanner->new(); +isa_ok($scanner, 'Barcode::ZBar::ImageScanner', 'image scanner'); ######################### @@ -77,7 +77,7 @@ SKIP: { ######################### my $sym = $symbols[0]; - isa_ok($sym, 'Barcode::Zebra::Symbol', 'symbol'); + isa_ok($sym, 'Barcode::ZBar::Symbol', 'symbol'); ######################### @@ -85,7 +85,7 @@ SKIP: { ######################### - is($sym->get_type(), Barcode::Zebra::Symbol::EAN13, 'result type'); + is($sym->get_type(), Barcode::ZBar::Symbol::EAN13, 'result type'); ######################### diff --git a/perl/t/Processor.t b/perl/t/Processor.t index 2aa88f4..12e0c12 100755 --- a/perl/t/Processor.t +++ b/perl/t/Processor.t @@ -7,14 +7,14 @@ use Test::More tests => 19; ######################### -BEGIN { use_ok('Barcode::Zebra') } +BEGIN { use_ok('Barcode::ZBar') } -Barcode::Zebra::set_verbosity(32); +Barcode::ZBar::set_verbosity(32); ######################### -my $proc = Barcode::Zebra::Processor->new(); -isa_ok($proc, 'Barcode::Zebra::Processor', 'processor'); +my $proc = Barcode::ZBar::Processor->new(); +isa_ok($proc, 'Barcode::ZBar::Processor', 'processor'); ######################### @@ -41,7 +41,7 @@ $proc->set_data_handler(sub { ######################### my $image = $_[1]; - isa_ok($image, 'Barcode::Zebra::Image', 'image'); + isa_ok($image, 'Barcode::ZBar::Image', 'image'); ######################### @@ -51,11 +51,11 @@ $proc->set_data_handler(sub { ######################### my $sym = $symbols[0]; - isa_ok($sym, 'Barcode::Zebra::Symbol', 'symbol'); + isa_ok($sym, 'Barcode::ZBar::Symbol', 'symbol'); ######################### - is($sym->get_type(), Barcode::Zebra::Symbol::EAN13, 'result type'); + is($sym->get_type(), Barcode::ZBar::Symbol::EAN13, 'result type'); ######################### @@ -94,7 +94,7 @@ SKIP: { my $im = Image::Magick->new(); my $err = $im->Read('t/barcode.png'); die($err) if($err); - my $image = Barcode::Zebra::Image->new(); + my $image = Barcode::ZBar::Image->new(); $image->set_format('422P'); $image->set_size($im->Get(qw(columns rows))); $image->set_data($im->ImageToBlob( diff --git a/perl/t/Scanner.t b/perl/t/Scanner.t index 23834e0..99b8942 100755 --- a/perl/t/Scanner.t +++ b/perl/t/Scanner.t @@ -7,12 +7,12 @@ use Test::More tests => 3; ######################### -BEGIN { use_ok('Barcode::Zebra') } +BEGIN { use_ok('Barcode::ZBar') } ######################### -my $scanner = Barcode::Zebra::Scanner->new(); -isa_ok($scanner, 'Barcode::Zebra::Scanner', 'scanner'); +my $scanner = Barcode::ZBar::Scanner->new(); +isa_ok($scanner, 'Barcode::ZBar::Scanner', 'scanner'); ######################### diff --git a/perl/t/Zebra.t b/perl/t/ZBar.t similarity index 52% rename from perl/t/Zebra.t rename to perl/t/ZBar.t index a970a37..f9a7e8e 100755 --- a/perl/t/Zebra.t +++ b/perl/t/ZBar.t @@ -1,5 +1,5 @@ # Before `make install' is performed this script should be runnable with -# `make test'. After `make install' it should work as `perl Zebra.t' +# `make test'. After `make install' it should work as `perl ZBar.t' use warnings; use strict; @@ -7,16 +7,16 @@ use Test::More tests => 3; ######################### -BEGIN { use_ok('Barcode::Zebra') } +BEGIN { use_ok('Barcode::ZBar') } ######################### -like(Barcode::Zebra::version(), qr<\d.\d>, 'version'); +like(Barcode::ZBar::version(), qr<\d.\d>, 'version'); ######################### -Barcode::Zebra::set_verbosity(16); -Barcode::Zebra::increase_verbosity(); +Barcode::ZBar::set_verbosity(16); +Barcode::ZBar::increase_verbosity(); pass('verbosity'); ######################### diff --git a/perl/t/pod-coverage.t b/perl/t/pod-coverage.t new file mode 100644 index 0000000..97c2df8 --- /dev/null +++ b/perl/t/pod-coverage.t @@ -0,0 +1,12 @@ +# Before `make install' is performed this script should be runnable with +# `make test'. After `make install' it should work as `perl pod.t' + +use warnings; +use strict; +use Test::More; + +eval "use Test::Pod::Coverage"; +plan skip_all => "Test::Pod::Coverage required for testing pod coverage" + if $@; + +all_pod_coverage_ok(); diff --git a/perl/t/pod.t b/perl/t/pod.t new file mode 100644 index 0000000..a83ee7d --- /dev/null +++ b/perl/t/pod.t @@ -0,0 +1,12 @@ +# Before `make install' is performed this script should be runnable with +# `make test'. After `make install' it should work as `perl pod.t' + +use warnings; +use strict; +use Test::More; + +eval { use Test::Pod 1.00 }; +plan skip_all => "Test::Pod 1.00 required for testing POD" + if $@; + +all_pod_files_ok(); diff --git a/perl/typemap b/perl/typemap index 5ff79dd..4cad035 100644 --- a/perl/typemap +++ b/perl/typemap @@ -1,19 +1,19 @@ # objects -Barcode::Zebra::Error T_PTROBJ -Barcode::Zebra::Symbol T_PTROBJ -Barcode::Zebra::Image T_PTROBJ -Barcode::Zebra::Processor T_PTROBJ -Barcode::Zebra::Video T_PTROBJ -Barcode::Zebra::Window T_PTROBJ -Barcode::Zebra::ImageScanner T_PTROBJ -Barcode::Zebra::Decoder T_PTROBJ -Barcode::Zebra::Scanner T_PTROBJ +Barcode::ZBar::Error T_PTROBJ +Barcode::ZBar::Symbol T_PTROBJ +Barcode::ZBar::Image T_PTROBJ +Barcode::ZBar::Processor T_PTROBJ +Barcode::ZBar::Video T_PTROBJ +Barcode::ZBar::Window T_PTROBJ +Barcode::ZBar::ImageScanner T_PTROBJ +Barcode::ZBar::Decoder T_PTROBJ +Barcode::ZBar::Scanner T_PTROBJ # enums -zebra_color_t T_ENUM -zebra_error_t T_ENUM -zebra_symbol_type_t T_ENUM -zebra_config_t T_ENUM +zbar_color_t T_ENUM +zbar_error_t T_ENUM +zbar_symbol_type_t T_ENUM +zbar_config_t T_ENUM # special scalars fourcc_t T_FOURCC diff --git a/plugin/Makefile.am.inc b/plugin/Makefile.am.inc index 763af24..c1d4425 100644 --- a/plugin/Makefile.am.inc +++ b/plugin/Makefile.am.inc @@ -1,5 +1,5 @@ -lib_LTLIBRARIES += plugin/libzebraplugin.la -plugin_libzebraplugin_la_SOURCES = \ +lib_LTLIBRARIES += plugin/libzbarplugin.la +plugin_libzbarplugin_la_SOURCES = \ plugin/plugin.c -plugin_libzebraplugin_la_CPPFLAGS = $(MOZILLA_CFLAGS) $(AM_CPPFLAGS) -plugin_libzebraplugin_la_LDFLAGS = $(MOZILLA_LIBS) $(AM_LDFLAGS) +plugin_libzbarplugin_la_CPPFLAGS = $(MOZILLA_CFLAGS) $(AM_CPPFLAGS) +plugin_libzbarplugin_la_LDFLAGS = $(MOZILLA_LIBS) $(AM_LDFLAGS) diff --git a/plugin/plugin.c b/plugin/plugin.c index 2559714..5fbd512 100644 --- a/plugin/plugin.c +++ b/plugin/plugin.c @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ - * Copyright 2007 (c) Jeff Brown + * Copyright 2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include diff --git a/pygtk/Makefile.am.inc b/pygtk/Makefile.am.inc index a5663da..fba1adc 100644 --- a/pygtk/Makefile.am.inc +++ b/pygtk/Makefile.am.inc @@ -1,19 +1,21 @@ -pyexec_LTLIBRARIES += pygtk/zebrapygtk.la -pygtk_zebrapygtk_la_CPPFLAGS = \ +pyexec_LTLIBRARIES += pygtk/zbarpygtk.la +pygtk_zbarpygtk_la_CPPFLAGS = \ $(GTK_CFLAGS) $(PYTHON_CFLAGS) $(PYGTK_CFLAGS) $(AM_CPPFLAGS) -pygtk_zebrapygtk_la_LDFLAGS = -shared -module -avoid-version -export-dynamic \ - -export-symbols-regex initzebrapygtk -pygtk_zebrapygtk_la_LIBADD = \ - $(PYTHON_LIBS) $(PYGTK_LIBS) gtk/libzebragtk.la $(AM_LIBADD) +pygtk_zbarpygtk_la_LDFLAGS = -shared -module -avoid-version -export-dynamic \ + -export-symbols-regex initzbarpygtk +pygtk_zbarpygtk_la_LIBADD = \ + $(PYTHON_LIBS) $(PYGTK_LIBS) gtk/libzbargtk.la $(AM_LIBADD) -pygtk_zebrapygtk_la_SOURCES = pygtk/zebrapygtkmodule.c pygtk/zebrapygtk.c -BUILT_SOURCES += pygtk/zebrapygtk.c pygtk/zebrapygtk.defs -EXTRA_DIST += pygtk/zebrapygtk.override pygtk/zebrapygtk.c pygtk/zebrapygtk.defs +pygtk_zbarpygtk_la_SOURCES = pygtk/zbarpygtkmodule.c pygtk/zbarpygtk.c +BUILT_SOURCES += pygtk/zbarpygtk.c pygtk/zbarpygtk.defs +EXTRA_DIST += pygtk/zbarpygtk.override pygtk/zbarpygtk.c pygtk/zbarpygtk.defs -pygtk/zebrapygtk.defs: include/zebra/zebragtk.h - $(PYTHON) $(PYGTK_H2DEF) $< > $@ +# FIXME ugly hack to fixup new name... now non-standard? +pygtk/zbarpygtk.defs: include/zbar/zbargtk.h + $(PYTHON) $(PYGTK_H2DEF) $< | \ + $(SED) -e 's/Z_TYPE_BAR_/ZBAR_TYPE_/' > $@ -pygtk/%.c: pygtk/%.defs $(srcdir)/pygtk/zebrapygtk.override - $(PYGTK_CODEGEN) --prefix zebrapygtk \ +pygtk/%.c: pygtk/%.defs $(srcdir)/pygtk/zbarpygtk.override + $(PYGTK_CODEGEN) --prefix zbarpygtk \ --register $(PYGTK_DEFS)/gdk-types.defs \ - --override $(srcdir)/pygtk/zebrapygtk.override $< > $@ + --override $(srcdir)/pygtk/zbarpygtk.override $< > $@ diff --git a/pygtk/zebrapygtk.override b/pygtk/zbarpygtk.override similarity index 58% rename from pygtk/zebrapygtk.override rename to pygtk/zbarpygtk.override index 3aea00b..a66ceb9 100644 --- a/pygtk/zebrapygtk.override +++ b/pygtk/zbarpygtk.override @@ -2,19 +2,19 @@ headers #include #include -#include +#include %% -modulename zebrapygtk +modulename zbarpygtk %% import gtk.Widget as PyGtkWidget_Type import gtk.gdk.Pixbuf as PyGdkPixbuf_Type %% ignore-type - ZebraGtkError + ZBarGtkError %% ignore-glob *_get_type %% ignore - zebra_gtk_image_from_pixbuf # until base library wrappers are in place + zbar_gtk_image_from_pixbuf # until base library wrappers are in place %% diff --git a/pygtk/zebrapygtkmodule.c b/pygtk/zbarpygtkmodule.c similarity index 60% rename from pygtk/zebrapygtkmodule.c rename to pygtk/zbarpygtkmodule.c index 64008ad..581d362 100644 --- a/pygtk/zebrapygtkmodule.c +++ b/pygtk/zbarpygtkmodule.c @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ - * Copyright 2008 (c) Jeff Brown + * Copyright 2008-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ /* avoid "multiple definition" darwin link errors @@ -28,19 +28,19 @@ #include -void zebrapygtk_register_classes(PyObject*); -extern PyMethodDef zebrapygtk_functions[]; +void zbarpygtk_register_classes(PyObject*); +extern PyMethodDef zbarpygtk_functions[]; DL_EXPORT(void) -initzebrapygtk(void) +initzbarpygtk(void) { init_pygobject(); - PyObject *mod = Py_InitModule("zebrapygtk", zebrapygtk_functions); + PyObject *mod = Py_InitModule("zbarpygtk", zbarpygtk_functions); PyObject *dict = PyModule_GetDict(mod); - zebrapygtk_register_classes(dict); + zbarpygtk_register_classes(dict); if(PyErr_Occurred()) - Py_FatalError("unable to initialise module zebrapygtk"); + Py_FatalError("unable to initialise module zbarpygtk"); } diff --git a/python/Makefile.am.inc b/python/Makefile.am.inc index 3cf848e..f2839d4 100644 --- a/python/Makefile.am.inc +++ b/python/Makefile.am.inc @@ -1,9 +1,11 @@ -pyexec_LTLIBRARIES += python/zebra.la -python_zebra_la_CPPFLAGS = $(PYTHON_CFLAGS) $(AM_CPPFLAGS) -python_zebra_la_LDFLAGS = -shared -module -avoid-version -export-dynamic \ - -export-symbols-regex initzebra -python_zebra_la_LIBADD = $(PYTHON_LIBS) zebra/libzebra.la $(AM_LIBADD) +pyexec_LTLIBRARIES += python/zbar.la +python_zbar_la_CPPFLAGS = $(PYTHON_CFLAGS) $(AM_CPPFLAGS) +python_zbar_la_LDFLAGS = -shared -module -avoid-version -export-dynamic \ + -export-symbols-regex initzbar +python_zbar_la_LIBADD = $(PYTHON_LIBS) zbar/libzbar.la $(AM_LIBADD) -python_zebra_la_SOURCES = python/zebramodule.c python/zebramodule.h \ +python_zbar_la_SOURCES = python/zbarmodule.c python/zbarmodule.h \ python/enum.c python/exception.c python/symbol.c python/image.c \ python/processor.c python/imagescanner.c python/decoder.c python/scanner.c + +EXTRA_DIST += python/test/barcode.png python/test/test_zbar.py diff --git a/python/decoder.c b/python/decoder.c index 53ff92f..81b82e6 100644 --- a/python/decoder.c +++ b/python/decoder.c @@ -1,11 +1,34 @@ -#include "zebramodule.h" +/*------------------------------------------------------------------------ + * Copyright 2009 (c) Jeff Brown + * + * 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 "zbarmodule.h" static char decoder_doc[] = PyDoc_STR( "low level decode of measured bar/space widths.\n" "\n" "FIXME."); -static zebraDecoder* +static zbarDecoder* decoder_new (PyTypeObject *type, PyObject *args, PyObject *kwds) @@ -14,12 +37,12 @@ decoder_new (PyTypeObject *type, if(!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist)) return(NULL); - zebraDecoder *self = (zebraDecoder*)type->tp_alloc(type, 0); + zbarDecoder *self = (zbarDecoder*)type->tp_alloc(type, 0); if(!self) return(NULL); - self->zdcode = zebra_decoder_create(); - zebra_decoder_set_userdata(self->zdcode, self); + self->zdcode = zbar_decoder_create(); + zbar_decoder_set_userdata(self->zdcode, self); if(!self->zdcode) { Py_DECREF(self); return(NULL); @@ -29,7 +52,7 @@ decoder_new (PyTypeObject *type, } static int -decoder_traverse (zebraDecoder *self, +decoder_traverse (zbarDecoder *self, visitproc visit, void *arg) { @@ -39,52 +62,52 @@ decoder_traverse (zebraDecoder *self, } static int -decoder_clear (zebraDecoder *self) +decoder_clear (zbarDecoder *self) { - zebra_decoder_set_handler(self->zdcode, NULL); - zebra_decoder_set_userdata(self->zdcode, NULL); + zbar_decoder_set_handler(self->zdcode, NULL); + zbar_decoder_set_userdata(self->zdcode, NULL); Py_CLEAR(self->handler); Py_CLEAR(self->args); return(0); } static void -decoder_dealloc (zebraDecoder *self) +decoder_dealloc (zbarDecoder *self) { decoder_clear(self); - zebra_decoder_destroy(self->zdcode); + zbar_decoder_destroy(self->zdcode); ((PyObject*)self)->ob_type->tp_free((PyObject*)self); } -static zebraEnumItem* -decoder_get_color (zebraDecoder *self, +static zbarEnumItem* +decoder_get_color (zbarDecoder *self, void *closure) { - zebra_color_t zcol = zebra_decoder_get_color(self->zdcode); - assert(zcol == ZEBRA_BAR || zcol == ZEBRA_SPACE); - zebraEnumItem *color = color_enum[zcol]; + zbar_color_t zcol = zbar_decoder_get_color(self->zdcode); + assert(zcol == ZBAR_BAR || zcol == ZBAR_SPACE); + zbarEnumItem *color = color_enum[zcol]; Py_INCREF((PyObject*)color); return(color); } -static zebraEnumItem* -decoder_get_type (zebraDecoder *self, +static zbarEnumItem* +decoder_get_type (zbarDecoder *self, void *closure) { - zebra_symbol_type_t sym = zebra_decoder_get_type(self->zdcode); - if(sym == ZEBRA_NONE) { + zbar_symbol_type_t sym = zbar_decoder_get_type(self->zdcode); + if(sym == ZBAR_NONE) { /* hardcode most common case */ Py_INCREF((PyObject*)symbol_NONE); return(symbol_NONE); } - return(zebraSymbol_LookupEnum(sym)); + return(zbarSymbol_LookupEnum(sym)); } static PyObject* -decoder_get_data (zebraDecoder *self, +decoder_get_data (zbarDecoder *self, void *closure) { - return(PyString_FromString(zebra_decoder_get_data(self->zdcode))); + return(PyString_FromString(zbar_decoder_get_data(self->zdcode))); } static PyGetSetDef decoder_getset[] = { @@ -95,19 +118,19 @@ static PyGetSetDef decoder_getset[] = { }; static PyObject* -decoder_set_config (zebraDecoder *self, +decoder_set_config (zbarDecoder *self, PyObject *args, PyObject *kwds) { - zebra_symbol_type_t sym = ZEBRA_NONE; - zebra_config_t cfg = ZEBRA_CFG_ENABLE; + zbar_symbol_type_t sym = ZBAR_NONE; + zbar_config_t cfg = ZBAR_CFG_ENABLE; int val = 1; static char *kwlist[] = { "symbology", "config", "value", NULL }; if(!PyArg_ParseTupleAndKeywords(args, kwds, "|iii", kwlist, &sym, &cfg, &val)) return(NULL); - if(zebra_decoder_set_config(self->zdcode, sym, cfg, val)) { + if(zbar_decoder_set_config(self->zdcode, sym, cfg, val)) { PyErr_SetString(PyExc_ValueError, "invalid configuration setting"); return(NULL); } @@ -115,7 +138,7 @@ decoder_set_config (zebraDecoder *self, } static PyObject* -decoder_parse_config (zebraDecoder *self, +decoder_parse_config (zbarDecoder *self, PyObject *args, PyObject *kwds) { @@ -124,7 +147,7 @@ decoder_parse_config (zebraDecoder *self, if(!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &cfg)) return(NULL); - if(zebra_decoder_parse_config(self->zdcode, cfg)) { + if(zbar_decoder_parse_config(self->zdcode, cfg)) { PyErr_Format(PyExc_ValueError, "invalid configuration setting: %s", cfg); return(NULL); @@ -133,7 +156,7 @@ decoder_parse_config (zebraDecoder *self, } static PyObject* -decoder_reset (zebraDecoder *self, +decoder_reset (zbarDecoder *self, PyObject *args, PyObject *kwds) { @@ -141,12 +164,12 @@ decoder_reset (zebraDecoder *self, if(!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist)) return(NULL); - zebra_decoder_reset(self->zdcode); + zbar_decoder_reset(self->zdcode); Py_RETURN_NONE; } static PyObject* -decoder_new_scan (zebraDecoder *self, +decoder_new_scan (zbarDecoder *self, PyObject *args, PyObject *kwds) { @@ -154,15 +177,15 @@ decoder_new_scan (zebraDecoder *self, if(!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist)) return(NULL); - zebra_decoder_new_scan(self->zdcode); + zbar_decoder_new_scan(self->zdcode); Py_RETURN_NONE; } void -decode_handler (zebra_decoder_t *zdcode) +decode_handler (zbar_decoder_t *zdcode) { assert(zdcode); - zebraDecoder *self = zebra_decoder_get_userdata(zdcode); + zbarDecoder *self = zbar_decoder_get_userdata(zdcode); assert(self); assert(self->zdcode == zdcode); assert(self->handler); @@ -172,7 +195,7 @@ decode_handler (zebra_decoder_t *zdcode) } static PyObject* -decoder_set_handler (zebraDecoder *self, +decoder_set_handler (zbarDecoder *self, PyObject *args, PyObject *kwds) { @@ -204,17 +227,17 @@ decoder_set_handler (zebraDecoder *self, Py_INCREF(handler); self->handler = handler; - zebra_decoder_set_handler(self->zdcode, decode_handler); + zbar_decoder_set_handler(self->zdcode, decode_handler); } else { self->handler = self->args = NULL; - zebra_decoder_set_handler(self->zdcode, NULL); + zbar_decoder_set_handler(self->zdcode, NULL); } Py_RETURN_NONE; } -static zebraEnumItem* -decoder_decode_width (zebraDecoder *self, +static zbarEnumItem* +decoder_decode_width (zbarDecoder *self, PyObject *args, PyObject *kwds) { @@ -223,16 +246,16 @@ decoder_decode_width (zebraDecoder *self, if(!PyArg_ParseTupleAndKeywords(args, kwds, "I", kwlist, &width)) return(NULL); - zebra_symbol_type_t sym = zebra_decode_width(self->zdcode, width); + zbar_symbol_type_t sym = zbar_decode_width(self->zdcode, width); if(PyErr_Occurred()) /* propagate errors during callback */ return(NULL); - if(sym == ZEBRA_NONE) { + if(sym == ZBAR_NONE) { /* hardcode most common case */ Py_INCREF((PyObject*)symbol_NONE); return(symbol_NONE); } - return(zebraSymbol_LookupEnum(sym)); + return(zbarSymbol_LookupEnum(sym)); } static PyMethodDef decoder_methods[] = { @@ -251,11 +274,11 @@ static PyMethodDef decoder_methods[] = { { NULL, }, }; -PyTypeObject zebraDecoder_Type = { +PyTypeObject zbarDecoder_Type = { PyObject_HEAD_INIT(NULL) - .tp_name = "zebra.Decoder", + .tp_name = "zbar.Decoder", .tp_doc = decoder_doc, - .tp_basicsize = sizeof(zebraDecoder), + .tp_basicsize = sizeof(zbarDecoder), .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .tp_new = (newfunc)decoder_new, diff --git a/python/enum.c b/python/enum.c index 640961b..8a51532 100644 --- a/python/enum.c +++ b/python/enum.c @@ -1,11 +1,34 @@ -#include "zebramodule.h" +/*------------------------------------------------------------------------ + * Copyright 2009 (c) Jeff Brown + * + * 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 "zbarmodule.h" static char enumitem_doc[] = PyDoc_STR( "simple enumeration item.\n" "\n" "associates an int value with a name for printing."); -static zebraEnumItem* +static zbarEnumItem* enumitem_new (PyTypeObject *type, PyObject *args, PyObject *kwds) @@ -16,7 +39,7 @@ enumitem_new (PyTypeObject *type, if(!PyArg_ParseTupleAndKeywords(args, kwds, "iS", kwlist, &val, &name)) return(NULL); - zebraEnumItem *self = (zebraEnumItem*)type->tp_alloc(type, 0); + zbarEnumItem *self = (zbarEnumItem*)type->tp_alloc(type, 0); if(!self) return(NULL); @@ -26,21 +49,21 @@ enumitem_new (PyTypeObject *type, } static void -enumitem_dealloc (zebraEnumItem *self) +enumitem_dealloc (zbarEnumItem *self) { Py_CLEAR(self->name); ((PyObject*)self)->ob_type->tp_free((PyObject*)self); } static PyObject* -enumitem_str (zebraEnumItem *self) +enumitem_str (zbarEnumItem *self) { Py_INCREF(self->name); return(self->name); } static int -enumitem_print (zebraEnumItem *self, +enumitem_print (zbarEnumItem *self, FILE *fp, int flags) { @@ -48,7 +71,7 @@ enumitem_print (zebraEnumItem *self, } static PyObject* -enumitem_repr (zebraEnumItem *self) +enumitem_repr (zbarEnumItem *self) { PyObject *name = PyObject_Repr(self->name); if(!name) @@ -62,11 +85,11 @@ enumitem_repr (zebraEnumItem *self) return((PyObject*)repr); } -PyTypeObject zebraEnumItem_Type = { +PyTypeObject zbarEnumItem_Type = { PyObject_HEAD_INIT(NULL) - .tp_name = "zebra.EnumItem", + .tp_name = "zbar.EnumItem", .tp_doc = enumitem_doc, - .tp_basicsize = sizeof(zebraEnumItem), + .tp_basicsize = sizeof(zbarEnumItem), .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .tp_new = (newfunc)enumitem_new, .tp_dealloc = (destructor)enumitem_dealloc, @@ -76,13 +99,13 @@ PyTypeObject zebraEnumItem_Type = { }; -zebraEnumItem* -zebraEnumItem_New (PyObject *byname, - PyObject *byvalue, - int val, - const char *name) +zbarEnumItem* +zbarEnumItem_New (PyObject *byname, + PyObject *byvalue, + int val, + const char *name) { - zebraEnumItem *self = PyObject_New(zebraEnumItem, &zebraEnumItem_Type); + zbarEnumItem *self = PyObject_New(zbarEnumItem, &zbarEnumItem_Type); if(!self) return(NULL); self->val.ob_ival = val; @@ -105,7 +128,7 @@ static char enum_doc[] = PyDoc_STR( /* FIXME add iteration */ static int -enum_traverse (zebraEnum *self, +enum_traverse (zbarEnum *self, visitproc visit, void *arg) { @@ -115,7 +138,7 @@ enum_traverse (zebraEnum *self, } static int -enum_clear (zebraEnum *self) +enum_clear (zbarEnum *self) { Py_CLEAR(self->byname); Py_CLEAR(self->byvalue); @@ -123,30 +146,30 @@ enum_clear (zebraEnum *self) } static void -enum_dealloc (zebraEnum *self) +enum_dealloc (zbarEnum *self) { enum_clear(self); ((PyObject*)self)->ob_type->tp_free((PyObject*)self); } -PyTypeObject zebraEnum_Type = { +PyTypeObject zbarEnum_Type = { PyObject_HEAD_INIT(NULL) - .tp_name = "zebra.Enum", + .tp_name = "zbar.Enum", .tp_doc = enum_doc, - .tp_basicsize = sizeof(zebraEnum), + .tp_basicsize = sizeof(zbarEnum), .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, - .tp_dictoffset = offsetof(zebraEnum, byname), + .tp_dictoffset = offsetof(zbarEnum, byname), .tp_traverse = (traverseproc)enum_traverse, .tp_clear = (inquiry)enum_clear, .tp_dealloc = (destructor)enum_dealloc, }; -zebraEnum* -zebraEnum_New () +zbarEnum* +zbarEnum_New () { - zebraEnum *self = PyObject_GC_New(zebraEnum, &zebraEnum_Type); + zbarEnum *self = PyObject_GC_New(zbarEnum, &zbarEnum_Type); if(!self) return(NULL); self->byname = PyDict_New(); @@ -159,12 +182,12 @@ zebraEnum_New () } int -zebraEnum_Add (zebraEnum *self, - int val, - const char *name) +zbarEnum_Add (zbarEnum *self, + int val, + const char *name) { - zebraEnumItem *item; - item = zebraEnumItem_New(self->byname, self->byvalue, val, name); + zbarEnumItem *item; + item = zbarEnumItem_New(self->byname, self->byvalue, val, name); if(!item) return(-1); return(0); diff --git a/python/exception.c b/python/exception.c index 9056b95..47432b0 100644 --- a/python/exception.c +++ b/python/exception.c @@ -1,17 +1,40 @@ -#include "zebramodule.h" +/*------------------------------------------------------------------------ + * Copyright 2009 (c) Jeff Brown + * + * 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 "zbarmodule.h" static inline PyObject* -exc_get_message (zebraException *self, +exc_get_message (zbarException *self, void *closure) { PyBaseExceptionObject *super = (PyBaseExceptionObject*)self; if(!PyString_Size(super->message)) { Py_CLEAR(super->message); - if(!self->obj || !zebraProcessor_Check(self->obj)) - super->message = PyString_FromString("unknown zebra error"); + if(!self->obj || !zbarProcessor_Check(self->obj)) + super->message = PyString_FromString("unknown zbar error"); else { - const void *zobj = ((zebraProcessor*)self->obj)->zproc; - super->message = PyString_FromString(_zebra_error_string(zobj, 1)); + const void *zobj = ((zbarProcessor*)self->obj)->zproc; + super->message = PyString_FromString(_zbar_error_string(zobj, 1)); } } Py_INCREF(super->message); @@ -19,7 +42,7 @@ exc_get_message (zebraException *self, } static int -exc_init (zebraException *self, +exc_init (zbarException *self, PyObject *args, PyObject *kwds) { @@ -39,7 +62,7 @@ exc_init (zebraException *self, } static int -exc_traverse (zebraException *self, +exc_traverse (zbarException *self, visitproc visit, void *arg) { @@ -49,7 +72,7 @@ exc_traverse (zebraException *self, } static int -exc_clear (zebraException *self) +exc_clear (zbarException *self) { Py_CLEAR(self->obj); ((PyTypeObject*)PyExc_Exception)->tp_clear((PyObject*)self); @@ -57,20 +80,20 @@ exc_clear (zebraException *self) } static void -exc_dealloc (zebraException *self) +exc_dealloc (zbarException *self) { exc_clear(self); ((PyTypeObject*)PyExc_Exception)->tp_dealloc((PyObject*)self); } static PyObject* -exc_str (zebraException *self) +exc_str (zbarException *self) { return(exc_get_message(self, NULL)); } static int -exc_set_message (zebraException *self, +exc_set_message (zbarException *self, PyObject *value, void *closure) { @@ -89,10 +112,10 @@ static PyGetSetDef exc_getset[] = { { NULL, }, }; -PyTypeObject zebraException_Type = { +PyTypeObject zbarException_Type = { PyObject_HEAD_INIT(NULL) - .tp_name = "zebra.Exception", - .tp_basicsize = sizeof(zebraException), + .tp_name = "zbar.Exception", + .tp_basicsize = sizeof(zbarException), .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .tp_init = (initproc)exc_init, @@ -104,19 +127,19 @@ PyTypeObject zebraException_Type = { }; PyObject* -zebraErr_Set (PyObject *self) +zbarErr_Set (PyObject *self) { - const void *zobj = ((zebraProcessor*)self)->zproc; - zebra_error_t err = _zebra_get_error_code(zobj); + const void *zobj = ((zbarProcessor*)self)->zproc; + zbar_error_t err = _zbar_get_error_code(zobj); - if(err == ZEBRA_ERR_NOMEM) + if(err == ZBAR_ERR_NOMEM) PyErr_NoMemory(); - else if(err < ZEBRA_ERR_NUM) { - PyObject *type = zebra_exc[err]; + else if(err < ZBAR_ERR_NUM) { + PyObject *type = zbar_exc[err]; assert(type); PyErr_SetObject(type, self); } else - PyErr_SetObject(zebra_exc[0], self); + PyErr_SetObject(zbar_exc[0], self); return(NULL); } diff --git a/python/image.c b/python/image.c index e110122..901c856 100644 --- a/python/image.c +++ b/python/image.c @@ -1,4 +1,27 @@ -#include "zebramodule.h" +/*------------------------------------------------------------------------ + * Copyright 2009 (c) Jeff Brown + * + * 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 "zbarmodule.h" static char symboliter_doc[] = PyDoc_STR( "symbol iterator.\n" @@ -6,7 +29,7 @@ static char symboliter_doc[] = PyDoc_STR( "iterates over decode results attached to an image."); static int -symboliter_traverse (zebraSymbolIter *self, +symboliter_traverse (zbarSymbolIter *self, visitproc visit, void *arg) { @@ -15,43 +38,43 @@ symboliter_traverse (zebraSymbolIter *self, } static int -symboliter_clear (zebraSymbolIter *self) +symboliter_clear (zbarSymbolIter *self) { Py_CLEAR(self->img); return(0); } static void -symboliter_dealloc (zebraSymbolIter *self) +symboliter_dealloc (zbarSymbolIter *self) { symboliter_clear(self); ((PyObject*)self)->ob_type->tp_free((PyObject*)self); } -static zebraSymbolIter* -symboliter_iter (zebraSymbolIter *self) +static zbarSymbolIter* +symboliter_iter (zbarSymbolIter *self) { Py_INCREF(self); return(self); } -static zebraSymbol* -symboliter_iternext (zebraSymbolIter *self) +static zbarSymbol* +symboliter_iternext (zbarSymbolIter *self) { if(!self->zsym) - self->zsym = zebra_image_first_symbol(self->img->zimg); + self->zsym = zbar_image_first_symbol(self->img->zimg); else - self->zsym = zebra_symbol_next(self->zsym); + self->zsym = zbar_symbol_next(self->zsym); if(!self->zsym) return(NULL); - return(zebraSymbol_FromSymbol(self->img, self->zsym)); + return(zbarSymbol_FromSymbol(self->img, self->zsym)); } -PyTypeObject zebraSymbolIter_Type = { +PyTypeObject zbarSymbolIter_Type = { PyObject_HEAD_INIT(NULL) - .tp_name = "zebra.SymbolIter", + .tp_name = "zbar.SymbolIter", .tp_doc = symboliter_doc, - .tp_basicsize = sizeof(zebraSymbolIter), + .tp_basicsize = sizeof(zbarSymbolIter), .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .tp_traverse = (traverseproc)symboliter_traverse, @@ -61,11 +84,11 @@ PyTypeObject zebraSymbolIter_Type = { .tp_iternext = (iternextfunc)symboliter_iternext, }; -static zebraSymbolIter* -zebraSymbolIter_New (zebraImage *img) +static zbarSymbolIter* +zbarSymbolIter_New (zbarImage *img) { - zebraSymbolIter *self; - self = PyObject_GC_New(zebraSymbolIter, &zebraSymbolIter_Type); + zbarSymbolIter *self; + self = PyObject_GC_New(zbarSymbolIter, &zbarSymbolIter_Type); if(!self) return(NULL); @@ -81,26 +104,26 @@ static char image_doc[] = PyDoc_STR( "\n" "stores image data samples along with associated format and size metadata."); -static zebraImage* +static zbarImage* image_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { - zebraImage *self = (zebraImage*)type->tp_alloc(type, 0); + zbarImage *self = (zbarImage*)type->tp_alloc(type, 0); if(!self) return(NULL); - self->zimg = zebra_image_create(); + self->zimg = zbar_image_create(); if(!self->zimg) { Py_DECREF(self); return(NULL); } - zebra_image_set_userdata(self->zimg, self); + zbar_image_set_userdata(self->zimg, self); return(self); } static int -image_traverse (zebraImage *self, +image_traverse (zbarImage *self, visitproc visit, void *arg) { @@ -109,47 +132,47 @@ image_traverse (zebraImage *self, } static int -image_clear (zebraImage *self) +image_clear (zbarImage *self) { - zebra_image_t *zimg = self->zimg; + zbar_image_t *zimg = self->zimg; self->zimg = NULL; if(zimg) { - assert(zebra_image_get_userdata(zimg) == self); + assert(zbar_image_get_userdata(zimg) == self); if(self->data) { - /* attach data directly to zebra image */ - zebra_image_set_userdata(zimg, self->data); + /* attach data directly to zbar image */ + zbar_image_set_userdata(zimg, self->data); self->data = NULL; } else - zebra_image_set_userdata(zimg, NULL); - zebra_image_destroy(zimg); + zbar_image_set_userdata(zimg, NULL); + zbar_image_destroy(zimg); } return(0); } static void -image_dealloc (zebraImage *self) +image_dealloc (zbarImage *self) { image_clear(self); ((PyObject*)self)->ob_type->tp_free((PyObject*)self); } -static zebraSymbolIter* -image_iter (zebraImage *self) +static zbarSymbolIter* +image_iter (zbarImage *self) { - return(zebraSymbolIter_New(self)); + return(zbarSymbolIter_New(self)); } static PyObject* -image_get_format (zebraImage *self, +image_get_format (zbarImage *self, void *closure) { - unsigned long format = zebra_image_get_format(self->zimg); + unsigned long format = zbar_image_get_format(self->zimg); return(PyString_FromStringAndSize((char*)&format, 4)); } static int -image_set_format (zebraImage *self, +image_set_format (zbarImage *self, PyObject *value, void *closure) { @@ -166,21 +189,21 @@ image_set_format (zebraImage *self, format); return(-1); } - zebra_image_set_format(self->zimg,*((unsigned long*)format)); + zbar_image_set_format(self->zimg,*((unsigned long*)format)); return(0); } static PyObject* -image_get_size (zebraImage *self, +image_get_size (zbarImage *self, void *closure) { - unsigned int width = zebra_image_get_width(self->zimg); - unsigned int height = zebra_image_get_height(self->zimg); + unsigned int width = zbar_image_get_width(self->zimg); + unsigned int height = zbar_image_get_height(self->zimg); return(PyTuple_Pack(2, PyInt_FromLong(width), PyInt_FromLong(height))); } static int -image_set_size (zebraImage *self, +image_set_size (zbarImage *self, PyObject *value, void *closure) { @@ -206,7 +229,7 @@ image_set_size (zebraImage *self, if(height == -1 && PyErr_Occurred()) goto error; - zebra_image_set_size(self->zimg, width, height); + zbar_image_set_size(self->zimg, width, height); rc = 0; error: @@ -219,17 +242,17 @@ image_set_size (zebraImage *self, } static PyObject* -image_get_int (zebraImage *self, +image_get_int (zbarImage *self, void *closure) { unsigned int val = -1; switch((int)closure) { case 0: - val = zebra_image_get_width(self->zimg); break; + val = zbar_image_get_width(self->zimg); break; case 1: - val = zebra_image_get_height(self->zimg); break; + val = zbar_image_get_height(self->zimg); break; case 2: - val = zebra_image_get_sequence(self->zimg); break; + val = zbar_image_get_sequence(self->zimg); break; default: assert(0); } @@ -237,7 +260,7 @@ image_get_int (zebraImage *self, } static int -image_set_int (zebraImage *self, +image_set_int (zbarImage *self, PyObject *value, void *closure) { @@ -248,15 +271,15 @@ image_set_int (zebraImage *self, } switch((int)closure) { case 0: - tmp = zebra_image_get_height(self->zimg); - zebra_image_set_size(self->zimg, val, tmp); + tmp = zbar_image_get_height(self->zimg); + zbar_image_set_size(self->zimg, val, tmp); break; case 1: - tmp = zebra_image_get_width(self->zimg); - zebra_image_set_size(self->zimg, tmp, val); + tmp = zbar_image_get_width(self->zimg); + zbar_image_set_size(self->zimg, tmp, val); break; case 2: - zebra_image_set_sequence(self->zimg, val); + zbar_image_set_sequence(self->zimg, val); default: assert(0); } @@ -264,17 +287,17 @@ image_set_int (zebraImage *self, } static PyObject* -image_get_data (zebraImage *self, +image_get_data (zbarImage *self, void *closure) { - assert(zebra_image_get_userdata(self->zimg) == self); + assert(zbar_image_get_userdata(self->zimg) == self); if(self->data) { Py_INCREF(self->data); return(self->data); } - const char *data = zebra_image_get_data(self->zimg); - unsigned long datalen = zebra_image_get_data_length(self->zimg); + const char *data = zbar_image_get_data(self->zimg); + unsigned long datalen = zbar_image_get_data_length(self->zimg); if(!data || !datalen) { Py_INCREF(Py_None); return(Py_None); @@ -286,14 +309,14 @@ image_get_data (zebraImage *self, } void -image_cleanup (zebra_image_t *zimg) +image_cleanup (zbar_image_t *zimg) { - PyObject *data = zebra_image_get_userdata(zimg); - zebra_image_set_userdata(zimg, NULL); + PyObject *data = zbar_image_get_userdata(zimg); + zbar_image_set_userdata(zimg, NULL); if(!data) return; /* FIXME internal error */ - if(PyObject_TypeCheck(data, &zebraImage_Type)) { - zebraImage *self = (zebraImage*)data; + if(PyObject_TypeCheck(data, &zbarImage_Type)) { + zbarImage *self = (zbarImage*)data; assert(self->zimg == zimg); Py_CLEAR(self->data); } @@ -302,12 +325,12 @@ image_cleanup (zebra_image_t *zimg) } static int -image_set_data (zebraImage *self, +image_set_data (zbarImage *self, PyObject *value, void *closure) { if(!value) { - zebra_image_free_data(self->zimg); + zbar_image_free_data(self->zimg); return(0); } char *data; @@ -316,10 +339,10 @@ image_set_data (zebraImage *self, return(-1); Py_INCREF(value); - zebra_image_set_data(self->zimg, data, datalen, image_cleanup); + zbar_image_set_data(self->zimg, data, datalen, image_cleanup); assert(!self->data); self->data = value; - zebra_image_set_userdata(self->zimg, self); + zbar_image_set_userdata(self->zimg, self); return(0); } @@ -337,7 +360,7 @@ static PyGetSetDef image_getset[] = { }; static int -image_init (zebraImage *self, +image_init (zbarImage *self, PyObject *args, PyObject *kwds) { @@ -349,7 +372,7 @@ image_init (zebraImage *self, return(-1); if(width > 0 && height > 0) - zebra_image_set_size(self->zimg, width, height); + zbar_image_set_size(self->zimg, width, height); if(format && image_set_format(self, format, NULL)) return(-1); if(data && image_set_data(self, data, NULL)) @@ -357,8 +380,8 @@ image_init (zebraImage *self, return(0); } -static zebraImage* -image_convert (zebraImage *self, +static zbarImage* +image_convert (zbarImage *self, PyObject *args, PyObject *kwds) { @@ -377,24 +400,24 @@ image_convert (zebraImage *self, return(NULL); } - zebraImage *img = PyObject_GC_New(zebraImage, &zebraImage_Type); + zbarImage *img = PyObject_GC_New(zbarImage, &zbarImage_Type); if(!img) return(NULL); img->data = NULL; if(width > 0 && height > 0) img->zimg = - zebra_image_convert_resize(self->zimg, + zbar_image_convert_resize(self->zimg, *((unsigned long*)format), width, height); else - img->zimg = zebra_image_convert(self->zimg, *((unsigned long*)format)); + img->zimg = zbar_image_convert(self->zimg, *((unsigned long*)format)); if(!img->zimg) { /* FIXME propagate exception */ Py_DECREF(img); return(NULL); } - zebra_image_set_userdata(img->zimg, img); + zbar_image_set_userdata(img->zimg, img); return(img); } @@ -404,11 +427,11 @@ static PyMethodDef image_methods[] = { { NULL, }, }; -PyTypeObject zebraImage_Type = { +PyTypeObject zbarImage_Type = { PyObject_HEAD_INIT(NULL) - .tp_name = "zebra.Image", + .tp_name = "zbar.Image", .tp_doc = image_doc, - .tp_basicsize = sizeof(zebraImage), + .tp_basicsize = sizeof(zbarImage), .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .tp_new = (newfunc)image_new, @@ -421,26 +444,26 @@ PyTypeObject zebraImage_Type = { .tp_iter = (getiterfunc)image_iter, }; -zebraImage* -zebraImage_FromImage (zebra_image_t *zimg) +zbarImage* +zbarImage_FromImage (zbar_image_t *zimg) { - zebraImage *self = PyObject_GC_New(zebraImage, &zebraImage_Type); + zbarImage *self = PyObject_GC_New(zbarImage, &zbarImage_Type); if(!self) return(NULL); - zebra_image_ref(zimg, 1); - zebra_image_set_userdata(zimg, self); + zbar_image_ref(zimg, 1); + zbar_image_set_userdata(zimg, self); self->zimg = zimg; self->data = NULL; return(self); } int -zebraImage_validate (zebraImage *img) +zbarImage_validate (zbarImage *img) { - if(!zebra_image_get_width(img->zimg) || - !zebra_image_get_height(img->zimg) || - !zebra_image_get_data(img->zimg) || - !zebra_image_get_data_length(img->zimg)) { + if(!zbar_image_get_width(img->zimg) || + !zbar_image_get_height(img->zimg) || + !zbar_image_get_data(img->zimg) || + !zbar_image_get_data_length(img->zimg)) { PyErr_Format(PyExc_ValueError, "image size and data must be defined"); return(-1); } diff --git a/python/imagescanner.c b/python/imagescanner.c index cf528b7..1500e71 100644 --- a/python/imagescanner.c +++ b/python/imagescanner.c @@ -1,11 +1,34 @@ -#include "zebramodule.h" +/*------------------------------------------------------------------------ + * Copyright 2009 (c) Jeff Brown + * + * 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 "zbarmodule.h" static char imagescanner_doc[] = PyDoc_STR( "scan images for barcodes.\n" "\n" "attaches symbols to image for each decoded result."); -static zebraImageScanner* +static zbarImageScanner* imagescanner_new (PyTypeObject *type, PyObject *args, PyObject *kwds) @@ -14,11 +37,11 @@ imagescanner_new (PyTypeObject *type, if(!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist)) return(NULL); - zebraImageScanner *self = (zebraImageScanner*)type->tp_alloc(type, 0); + zbarImageScanner *self = (zbarImageScanner*)type->tp_alloc(type, 0); if(!self) return(NULL); - self->zscn = zebra_image_scanner_create(); + self->zscn = zbar_image_scanner_create(); if(!self->zscn) { Py_DECREF(self); return(NULL); @@ -28,26 +51,26 @@ imagescanner_new (PyTypeObject *type, } static void -imagescanner_dealloc (zebraImageScanner *self) +imagescanner_dealloc (zbarImageScanner *self) { - zebra_image_scanner_destroy(self->zscn); + zbar_image_scanner_destroy(self->zscn); ((PyObject*)self)->ob_type->tp_free((PyObject*)self); } static PyObject* -imagescanner_set_config (zebraImageScanner *self, +imagescanner_set_config (zbarImageScanner *self, PyObject *args, PyObject *kwds) { - zebra_symbol_type_t sym = ZEBRA_NONE; - zebra_config_t cfg = ZEBRA_CFG_ENABLE; + zbar_symbol_type_t sym = ZBAR_NONE; + zbar_config_t cfg = ZBAR_CFG_ENABLE; int val = 1; static char *kwlist[] = { "symbology", "config", "value", NULL }; if(!PyArg_ParseTupleAndKeywords(args, kwds, "|iii", kwlist, &sym, &cfg, &val)) return(NULL); - if(zebra_image_scanner_set_config(self->zscn, sym, cfg, val)) { + if(zbar_image_scanner_set_config(self->zscn, sym, cfg, val)) { PyErr_SetString(PyExc_ValueError, "invalid configuration setting"); return(NULL); } @@ -55,7 +78,7 @@ imagescanner_set_config (zebraImageScanner *self, } static PyObject* -imagescanner_parse_config (zebraImageScanner *self, +imagescanner_parse_config (zbarImageScanner *self, PyObject *args, PyObject *kwds) { @@ -64,7 +87,7 @@ imagescanner_parse_config (zebraImageScanner *self, if(!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &cfg)) return(NULL); - if(zebra_image_scanner_parse_config(self->zscn, cfg)) { + if(zbar_image_scanner_parse_config(self->zscn, cfg)) { PyErr_Format(PyExc_ValueError, "invalid configuration setting: %s", cfg); return(NULL); @@ -73,7 +96,7 @@ imagescanner_parse_config (zebraImageScanner *self, } static PyObject* -imagescanner_enable_cache (zebraImageScanner *self, +imagescanner_enable_cache (zbarImageScanner *self, PyObject *args, PyObject *kwds) { @@ -83,25 +106,25 @@ imagescanner_enable_cache (zebraImageScanner *self, object_to_bool, &enable)) return(NULL); - zebra_image_scanner_enable_cache(self->zscn, enable); + zbar_image_scanner_enable_cache(self->zscn, enable); Py_RETURN_NONE; } static PyObject* -imagescanner_scan (zebraImageScanner *self, +imagescanner_scan (zbarImageScanner *self, PyObject *args, PyObject *kwds) { - zebraImage *img = NULL; + zbarImage *img = NULL; static char *kwlist[] = { "image", NULL }; if(!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, - &zebraImage_Type, &img)) + &zbarImage_Type, &img)) return(NULL); - if(zebraImage_validate(img)) + if(zbarImage_validate(img)) return(NULL); - int n = zebra_scan_image(self->zscn, img->zimg); + int n = zbar_scan_image(self->zscn, img->zimg); if(n < 0) { PyErr_Format(PyExc_ValueError, "unsupported image format"); return(NULL); @@ -121,11 +144,11 @@ static PyMethodDef imagescanner_methods[] = { { NULL, }, }; -PyTypeObject zebraImageScanner_Type = { +PyTypeObject zbarImageScanner_Type = { PyObject_HEAD_INIT(NULL) - .tp_name = "zebra.ImageScanner", + .tp_name = "zbar.ImageScanner", .tp_doc = imagescanner_doc, - .tp_basicsize = sizeof(zebraImageScanner), + .tp_basicsize = sizeof(zbarImageScanner), .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .tp_new = (newfunc)imagescanner_new, .tp_dealloc = (destructor)imagescanner_dealloc, diff --git a/python/processor.c b/python/processor.c index 8bb662d..41745e4 100644 --- a/python/processor.c +++ b/python/processor.c @@ -1,11 +1,34 @@ -#include "zebramodule.h" +/*------------------------------------------------------------------------ + * Copyright 2009 (c) Jeff Brown + * + * 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 "zbarmodule.h" static char processor_doc[] = PyDoc_STR( "low level decode of measured bar/space widths.\n" "\n" "FIXME."); -static zebraProcessor* +static zbarProcessor* processor_new (PyTypeObject *type, PyObject *args, PyObject *kwds) @@ -14,12 +37,12 @@ processor_new (PyTypeObject *type, if(!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist)) return(NULL); - zebraProcessor *self = (zebraProcessor*)type->tp_alloc(type, 0); + zbarProcessor *self = (zbarProcessor*)type->tp_alloc(type, 0); if(!self) return(NULL); - self->zproc = zebra_processor_create(0/*FIXME*/); - zebra_processor_set_userdata(self->zproc, self); + self->zproc = zbar_processor_create(0/*FIXME*/); + zbar_processor_set_userdata(self->zproc, self); if(!self->zproc) { Py_DECREF(self); return(NULL); @@ -28,7 +51,7 @@ processor_new (PyTypeObject *type, } static int -processor_traverse (zebraProcessor *self, +processor_traverse (zbarProcessor *self, visitproc visit, void *arg) { @@ -38,43 +61,43 @@ processor_traverse (zebraProcessor *self, } static int -processor_clear (zebraProcessor *self) +processor_clear (zbarProcessor *self) { - zebra_processor_set_data_handler(self->zproc, NULL, NULL); - zebra_processor_set_userdata(self->zproc, NULL); + zbar_processor_set_data_handler(self->zproc, NULL, NULL); + zbar_processor_set_userdata(self->zproc, NULL); Py_CLEAR(self->handler); Py_CLEAR(self->closure); return(0); } static void -processor_dealloc (zebraProcessor *self) +processor_dealloc (zbarProcessor *self) { processor_clear(self); - zebra_processor_destroy(self->zproc); + zbar_processor_destroy(self->zproc); ((PyObject*)self)->ob_type->tp_free((PyObject*)self); } static PyObject* -processor_get_bool (zebraProcessor *self, +processor_get_bool (zbarProcessor *self, void *closure) { int val; switch((int)closure) { case 0: - val = zebra_processor_is_visible(self->zproc); + val = zbar_processor_is_visible(self->zproc); break; default: assert(0); return(NULL); } if(val < 0) - return(zebraErr_Set((PyObject*)self)); + return(zbarErr_Set((PyObject*)self)); return(PyBool_FromLong(val)); } static int -processor_set_bool (zebraProcessor *self, +processor_set_bool (zbarProcessor *self, PyObject *value, void *closure) { @@ -87,17 +110,17 @@ processor_set_bool (zebraProcessor *self, return(-1); switch((int)closure) { case 0: - rc = zebra_processor_set_visible(self->zproc, val); + rc = zbar_processor_set_visible(self->zproc, val); break; case 1: - rc = zebra_processor_set_active(self->zproc, val); + rc = zbar_processor_set_active(self->zproc, val); break; default: assert(0); return(-1); } if(rc < 0) { - zebraErr_Set((PyObject*)self); + zbarErr_Set((PyObject*)self); return(-1); } return(0); @@ -112,19 +135,19 @@ static PyGetSetDef processor_getset[] = { }; static PyObject* -processor_set_config (zebraProcessor *self, +processor_set_config (zbarProcessor *self, PyObject *args, PyObject *kwds) { - zebra_symbol_type_t sym = ZEBRA_NONE; - zebra_config_t cfg = ZEBRA_CFG_ENABLE; + zbar_symbol_type_t sym = ZBAR_NONE; + zbar_config_t cfg = ZBAR_CFG_ENABLE; int val = 1; static char *kwlist[] = { "symbology", "config", "value", NULL }; if(!PyArg_ParseTupleAndKeywords(args, kwds, "|iii", kwlist, &sym, &cfg, &val)) return(NULL); - if(zebra_processor_set_config(self->zproc, sym, cfg, val)) { + if(zbar_processor_set_config(self->zproc, sym, cfg, val)) { PyErr_SetString(PyExc_ValueError, "invalid configuration setting"); return(NULL); } @@ -132,7 +155,7 @@ processor_set_config (zebraProcessor *self, } static PyObject* -processor_init_ (zebraProcessor *self, +processor_init_ (zbarProcessor *self, PyObject *args, PyObject *kwds) { @@ -143,13 +166,13 @@ processor_init_ (zebraProcessor *self, &dev, object_to_bool, &disp)) return(NULL); - if(zebra_processor_init(self->zproc, dev, disp)) - return(zebraErr_Set((PyObject*)self)); + if(zbar_processor_init(self->zproc, dev, disp)) + return(zbarErr_Set((PyObject*)self)); Py_RETURN_NONE; } static PyObject* -processor_parse_config (zebraProcessor *self, +processor_parse_config (zbarProcessor *self, PyObject *args, PyObject *kwds) { @@ -158,7 +181,7 @@ processor_parse_config (zebraProcessor *self, if(!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &cfg)) return(NULL); - if(zebra_processor_parse_config(self->zproc, cfg)) { + if(zbar_processor_parse_config(self->zproc, cfg)) { PyErr_Format(PyExc_ValueError, "invalid configuration setting: %s", cfg); return(NULL); @@ -182,7 +205,7 @@ object_to_timeout (PyObject *obj, } static PyObject* -processor_user_wait (zebraProcessor *self, +processor_user_wait (zbarProcessor *self, PyObject *args, PyObject *kwds) { @@ -192,14 +215,14 @@ processor_user_wait (zebraProcessor *self, object_to_timeout, &timeout)) return(NULL); - int rc = zebra_processor_user_wait(self->zproc, timeout); + int rc = zbar_processor_user_wait(self->zproc, timeout); if(rc < 0) - return(zebraErr_Set((PyObject*)self)); + return(zbarErr_Set((PyObject*)self)); return(PyInt_FromLong(rc)); } static PyObject* -processor_process_one (zebraProcessor *self, +processor_process_one (zbarProcessor *self, PyObject *args, PyObject *kwds) { @@ -209,44 +232,44 @@ processor_process_one (zebraProcessor *self, object_to_timeout, &timeout)) return(NULL); - int rc = zebra_process_one(self->zproc, timeout); + int rc = zbar_process_one(self->zproc, timeout); if(rc < 0) - return(zebraErr_Set((PyObject*)self)); + return(zbarErr_Set((PyObject*)self)); return(PyInt_FromLong(rc)); } static PyObject* -processor_process_image (zebraProcessor *self, +processor_process_image (zbarProcessor *self, PyObject *args, PyObject *kwds) { - zebraImage *img = NULL; + zbarImage *img = NULL; static char *kwlist[] = { "image", NULL }; if(!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, - &zebraImage_Type, &img)) + &zbarImage_Type, &img)) return(NULL); - if(zebraImage_validate(img)) + if(zbarImage_validate(img)) return(NULL); - int n = zebra_process_image(self->zproc, img->zimg); + int n = zbar_process_image(self->zproc, img->zimg); if(n < 0) - return(zebraErr_Set((PyObject*)self)); + return(zbarErr_Set((PyObject*)self)); return(PyInt_FromLong(n)); } void -process_handler (zebra_image_t *zimg, +process_handler (zbar_image_t *zimg, const void *userdata) { - zebraProcessor *self = (zebraProcessor*)userdata; + zbarProcessor *self = (zbarProcessor*)userdata; assert(self); assert(self->handler); assert(self->closure); - zebraImage *img = zebra_image_get_userdata(zimg); + zbarImage *img = zbar_image_get_userdata(zimg); if(!img || img->zimg != zimg) { - img = zebraImage_FromImage(zimg); + img = zbarImage_FromImage(zimg); if(!img) { PyErr_NoMemory(); return; @@ -268,7 +291,7 @@ process_handler (zebra_image_t *zimg, } static PyObject* -processor_set_data_handler (zebraProcessor *self, +processor_set_data_handler (zbarProcessor *self, PyObject *args, PyObject *kwds) { @@ -295,11 +318,11 @@ processor_set_data_handler (zebraProcessor *self, Py_INCREF(closure); self->closure = closure; - zebra_processor_set_data_handler(self->zproc, process_handler, self); + zbar_processor_set_data_handler(self->zproc, process_handler, self); } else { self->handler = self->closure = NULL; - zebra_processor_set_data_handler(self->zproc, NULL, self); + zbar_processor_set_data_handler(self->zproc, NULL, self); } Py_RETURN_NONE; } @@ -322,11 +345,11 @@ static PyMethodDef processor_methods[] = { { NULL, }, }; -PyTypeObject zebraProcessor_Type = { +PyTypeObject zbarProcessor_Type = { PyObject_HEAD_INIT(NULL) - .tp_name = "zebra.Processor", + .tp_name = "zbar.Processor", .tp_doc = processor_doc, - .tp_basicsize = sizeof(zebraProcessor), + .tp_basicsize = sizeof(zbarProcessor), .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .tp_new = (newfunc)processor_new, diff --git a/python/scanner.c b/python/scanner.c index fb4d7bd..b0b4c21 100644 --- a/python/scanner.c +++ b/python/scanner.c @@ -1,4 +1,27 @@ -#include "zebramodule.h" +/*------------------------------------------------------------------------ + * Copyright 2009 (c) Jeff Brown + * + * 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 "zbarmodule.h" static char scanner_doc[] = PyDoc_STR( "low level intensity sample stream scanner. identifies \"bar\" edges" @@ -6,28 +29,28 @@ static char scanner_doc[] = PyDoc_STR( "\n" "FIXME."); -static zebraScanner* +static zbarScanner* scanner_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { - zebraDecoder *decoder = NULL; + zbarDecoder *decoder = NULL; static char *kwlist[] = { "decoder", NULL }; if(!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", kwlist, - &decoder, zebraDecoder_Type)) + &decoder, zbarDecoder_Type)) return(NULL); - zebraScanner *self = (zebraScanner*)type->tp_alloc(type, 0); + zbarScanner *self = (zbarScanner*)type->tp_alloc(type, 0); if(!self) return(NULL); - zebra_decoder_t *zdcode = NULL; + zbar_decoder_t *zdcode = NULL; if(decoder) { Py_INCREF(decoder); self->decoder = decoder; zdcode = decoder->zdcode; } - self->zscn = zebra_scanner_create(zdcode); + self->zscn = zbar_scanner_create(zdcode); if(!self->zscn) { Py_DECREF(self); return(NULL); @@ -37,7 +60,7 @@ scanner_new (PyTypeObject *type, } static int -scanner_traverse (zebraScanner *self, +scanner_traverse (zbarScanner *self, visitproc visit, void *arg) { @@ -46,35 +69,35 @@ scanner_traverse (zebraScanner *self, } static int -scanner_clear (zebraScanner *self) +scanner_clear (zbarScanner *self) { Py_CLEAR(self->decoder); return(0); } static void -scanner_dealloc (zebraScanner *self) +scanner_dealloc (zbarScanner *self) { scanner_clear(self); - zebra_scanner_destroy(self->zscn); + zbar_scanner_destroy(self->zscn); ((PyObject*)self)->ob_type->tp_free((PyObject*)self); } static PyObject* -scanner_get_width (zebraScanner *self, +scanner_get_width (zbarScanner *self, void *closure) { - unsigned int width = zebra_scanner_get_width(self->zscn); + unsigned int width = zbar_scanner_get_width(self->zscn); return(PyInt_FromLong(width)); } -static zebraEnumItem* -scanner_get_color (zebraScanner *self, +static zbarEnumItem* +scanner_get_color (zbarScanner *self, void *closure) { - zebra_color_t zcol = zebra_scanner_get_color(self->zscn); - assert(zcol == ZEBRA_BAR || zcol == ZEBRA_SPACE); - zebraEnumItem *color = color_enum[zcol]; + zbar_color_t zcol = zbar_scanner_get_color(self->zscn); + assert(zcol == ZBAR_BAR || zcol == ZBAR_SPACE); + zbarEnumItem *color = color_enum[zcol]; Py_INCREF((PyObject*)color); return(color); } @@ -86,7 +109,7 @@ static PyGetSetDef scanner_getset[] = { }; static PyObject* -scanner_reset (zebraScanner *self, +scanner_reset (zbarScanner *self, PyObject *args, PyObject *kwds) { @@ -94,12 +117,12 @@ scanner_reset (zebraScanner *self, if(!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist)) return(NULL); - zebra_scanner_reset(self->zscn); + zbar_scanner_reset(self->zscn); Py_RETURN_NONE; } static PyObject* -scanner_new_scan (zebraScanner *self, +scanner_new_scan (zbarScanner *self, PyObject *args, PyObject *kwds) { @@ -107,12 +130,12 @@ scanner_new_scan (zebraScanner *self, if(!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist)) return(NULL); - zebra_scanner_new_scan(self->zscn); + zbar_scanner_new_scan(self->zscn); Py_RETURN_NONE; } -static zebraEnumItem* -scanner_scan_y (zebraScanner *self, +static zbarEnumItem* +scanner_scan_y (zbarScanner *self, PyObject *args, PyObject *kwds) { @@ -122,16 +145,16 @@ scanner_scan_y (zebraScanner *self, if(!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &y)) return(NULL); - zebra_symbol_type_t sym = zebra_scan_y(self->zscn, y); + zbar_symbol_type_t sym = zbar_scan_y(self->zscn, y); if(PyErr_Occurred()) /* propagate errors during callback */ return(NULL); - if(sym == ZEBRA_NONE) { + if(sym == ZBAR_NONE) { /* hardcode most common case */ Py_INCREF((PyObject*)symbol_NONE); return(symbol_NONE); } - return(zebraSymbol_LookupEnum(sym)); + return(zbarSymbol_LookupEnum(sym)); } static PyMethodDef scanner_methods[] = { @@ -144,11 +167,11 @@ static PyMethodDef scanner_methods[] = { { NULL, }, }; -PyTypeObject zebraScanner_Type = { +PyTypeObject zbarScanner_Type = { PyObject_HEAD_INIT(NULL) - .tp_name = "zebra.Scanner", + .tp_name = "zbar.Scanner", .tp_doc = scanner_doc, - .tp_basicsize = sizeof(zebraScanner), + .tp_basicsize = sizeof(zbarScanner), .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .tp_new = (newfunc)scanner_new, diff --git a/python/symbol.c b/python/symbol.c index d631a93..9b4e0ab 100644 --- a/python/symbol.c +++ b/python/symbol.c @@ -1,4 +1,27 @@ -#include "zebramodule.h" +/*------------------------------------------------------------------------ + * Copyright 2009 (c) Jeff Brown + * + * 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 "zbarmodule.h" static char symbol_doc[] = PyDoc_STR( "symbol result object.\n" @@ -6,7 +29,7 @@ static char symbol_doc[] = PyDoc_STR( "data and associated information about a successful decode."); static int -symbol_traverse (zebraSymbol *self, +symbol_traverse (zbarSymbol *self, visitproc visit, void *arg) { @@ -15,7 +38,7 @@ symbol_traverse (zebraSymbol *self, } static int -symbol_clear (zebraSymbol *self) +symbol_clear (zbarSymbol *self) { Py_CLEAR(self->img); Py_CLEAR(self->data); @@ -24,32 +47,32 @@ symbol_clear (zebraSymbol *self) } static void -symbol_dealloc (zebraSymbol *self) +symbol_dealloc (zbarSymbol *self) { symbol_clear(self); ((PyObject*)self)->ob_type->tp_free((PyObject*)self); } -static zebraEnumItem* -symbol_get_type (zebraSymbol *self, +static zbarEnumItem* +symbol_get_type (zbarSymbol *self, void *closure) { - return(zebraSymbol_LookupEnum(zebra_symbol_get_type(self->zsym))); + return(zbarSymbol_LookupEnum(zbar_symbol_get_type(self->zsym))); } static PyObject* -symbol_get_count (zebraSymbol *self, +symbol_get_count (zbarSymbol *self, void *closure) { - return(PyInt_FromLong(zebra_symbol_get_count(self->zsym))); + return(PyInt_FromLong(zbar_symbol_get_count(self->zsym))); } static PyObject* -symbol_get_data (zebraSymbol *self, +symbol_get_data (zbarSymbol *self, void *closure) { if(!self->data) { - self->data = PyString_FromString(zebra_symbol_get_data(self->zsym)); + self->data = PyString_FromString(zbar_symbol_get_data(self->zsym)); if(!self->data) return(NULL); } @@ -58,18 +81,18 @@ symbol_get_data (zebraSymbol *self, } static PyObject* -symbol_get_location (zebraSymbol *self, +symbol_get_location (zbarSymbol *self, void *closure) { if(!self->loc) { /* build tuple of 2-tuples representing location polygon */ - unsigned int n = zebra_symbol_get_loc_size(self->zsym); + unsigned int n = zbar_symbol_get_loc_size(self->zsym); self->loc = PyTuple_New(n); unsigned int i; for(i = 0; i < n; i++) { PyObject *x, *y; - x = PyInt_FromLong(zebra_symbol_get_loc_x(self->zsym, i)); - y = PyInt_FromLong(zebra_symbol_get_loc_y(self->zsym, i)); + x = PyInt_FromLong(zbar_symbol_get_loc_x(self->zsym, i)); + y = PyInt_FromLong(zbar_symbol_get_loc_y(self->zsym, i)); PyTuple_SET_ITEM(self->loc, i, PyTuple_Pack(2, x, y)); } } @@ -85,11 +108,11 @@ static PyGetSetDef symbol_getset[] = { { NULL, }, }; -PyTypeObject zebraSymbol_Type = { +PyTypeObject zbarSymbol_Type = { PyObject_HEAD_INIT(NULL) - .tp_name = "zebra.Symbol", + .tp_name = "zbar.Symbol", .tp_doc = symbol_doc, - .tp_basicsize = sizeof(zebraSymbol), + .tp_basicsize = sizeof(zbarSymbol), .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .tp_traverse = (traverseproc)symbol_traverse, @@ -98,12 +121,12 @@ PyTypeObject zebraSymbol_Type = { .tp_getset = symbol_getset, }; -zebraSymbol* -zebraSymbol_FromSymbol (zebraImage *img, - const zebra_symbol_t *zsym) +zbarSymbol* +zbarSymbol_FromSymbol (zbarImage *img, + const zbar_symbol_t *zsym) { /* FIXME symbol object recycle cache */ - zebraSymbol *self = PyObject_GC_New(zebraSymbol, &zebraSymbol_Type); + zbarSymbol *self = PyObject_GC_New(zbarSymbol, &zbarSymbol_Type); if(!self) return(NULL); assert(img); @@ -116,13 +139,13 @@ zebraSymbol_FromSymbol (zebraImage *img, return(self); } -zebraEnumItem* -zebraSymbol_LookupEnum (zebra_symbol_type_t type) +zbarEnumItem* +zbarSymbol_LookupEnum (zbar_symbol_type_t type) { PyObject *key = PyInt_FromLong(type); - zebraEnumItem *e = (zebraEnumItem*)PyDict_GetItem(symbol_enum, key); + zbarEnumItem *e = (zbarEnumItem*)PyDict_GetItem(symbol_enum, key); if(!e) - return((zebraEnumItem*)key); + return((zbarEnumItem*)key); Py_INCREF((PyObject*)e); Py_DECREF(key); return(e); diff --git a/python/test/test_zebra.py b/python/test/test_zbar.py similarity index 75% rename from python/test/test_zebra.py rename to python/test/test_zbar.py index f0c3190..b556d74 100755 --- a/python/test/test_zebra.py +++ b/python/test/test_zbar.py @@ -1,7 +1,7 @@ #!/usr/bin/python import sys, os import unittest as ut -import zebra +import zbar # FIXME this needs to be conditional # would be even better to auto-select PIL or ImageMagick (or...) @@ -24,46 +24,46 @@ def load_image(): if 'VIDEO_DEVICE' in os.environ: VIDEO_DEVICE = os.environ['VIDEO_DEVICE'] -class TestZebraFunctions(ut.TestCase): +class TestZBarFunctions(ut.TestCase): def test_version(self): - ver = zebra.version() + ver = zbar.version() self.assert_(isinstance(ver, tuple)) self.assertEqual(len(ver), 2) for v in ver: self.assert_(isinstance(v, int)) def test_verbosity(self): - zebra.increase_verbosity() - zebra.set_verbosity(16) + zbar.increase_verbosity() + zbar.set_verbosity(16) def test_exceptions(self): - self.assert_(isinstance(zebra.Exception, type)) - self.assert_(issubclass(zebra.InternalError, zebra.Exception)) - self.assert_(issubclass(zebra.UnsupportedError, zebra.Exception)) - self.assert_(issubclass(zebra.InvalidRequestError, zebra.Exception)) - self.assert_(issubclass(zebra.SystemError, zebra.Exception)) - self.assert_(issubclass(zebra.LockingError, zebra.Exception)) - self.assert_(issubclass(zebra.BusyError, zebra.Exception)) - self.assert_(issubclass(zebra.X11DisplayError, zebra.Exception)) - self.assert_(issubclass(zebra.X11ProtocolError, zebra.Exception)) - self.assert_(issubclass(zebra.WindowClosed, zebra.Exception)) + self.assert_(isinstance(zbar.Exception, type)) + self.assert_(issubclass(zbar.InternalError, zbar.Exception)) + self.assert_(issubclass(zbar.UnsupportedError, zbar.Exception)) + self.assert_(issubclass(zbar.InvalidRequestError, zbar.Exception)) + self.assert_(issubclass(zbar.SystemError, zbar.Exception)) + self.assert_(issubclass(zbar.LockingError, zbar.Exception)) + self.assert_(issubclass(zbar.BusyError, zbar.Exception)) + self.assert_(issubclass(zbar.X11DisplayError, zbar.Exception)) + self.assert_(issubclass(zbar.X11ProtocolError, zbar.Exception)) + self.assert_(issubclass(zbar.WindowClosed, zbar.Exception)) class TestScanner(ut.TestCase): def setUp(self): - self.scn = zebra.Scanner() + self.scn = zbar.Scanner() def tearDown(self): del(self.scn) def test_type(self): - self.assert_(isinstance(self.scn, zebra.Scanner)) + self.assert_(isinstance(self.scn, zbar.Scanner)) self.assert_(callable(self.scn.reset)) self.assert_(callable(self.scn.new_scan)) self.assert_(callable(self.scn.scan_y)) def set_color(color): self.scn.color = color - self.assertRaises(AttributeError, set_color, zebra.BAR) + self.assertRaises(AttributeError, set_color, zbar.BAR) def set_width(width): self.scn.width = width @@ -73,13 +73,13 @@ def set_width(width): class TestDecoder(ut.TestCase): def setUp(self): - self.dcode = zebra.Decoder() + self.dcode = zbar.Decoder() def tearDown(self): del(self.dcode) def test_type(self): - self.assert_(isinstance(self.dcode, zebra.Decoder)) + self.assert_(isinstance(self.dcode, zbar.Decoder)) self.assert_(callable(self.dcode.set_config)) self.assert_(callable(self.dcode.parse_config)) self.assert_(callable(self.dcode.reset)) @@ -89,11 +89,11 @@ def test_type(self): def set_type(typ): self.dcode.type = typ - self.assertRaises(AttributeError, set_type, zebra.Symbol.CODE128) + self.assertRaises(AttributeError, set_type, zbar.Symbol.CODE128) def set_color(color): self.dcode.color = color - self.assertRaises(AttributeError, set_color, zebra.BAR) + self.assertRaises(AttributeError, set_color, zbar.BAR) def set_data(data): self.dcode.data = data @@ -101,7 +101,7 @@ def set_data(data): def test_width(self): sym = self.dcode.decode_width(5) - self.assert_(sym is zebra.Symbol.NONE) + self.assert_(sym is zbar.Symbol.NONE) self.assert_(not sym) self.assertEqual(str(sym), 'NONE') @@ -109,17 +109,17 @@ def test_width(self): self.assert_(sym is typ) def test_reset(self): - self.assert_(self.dcode.color is zebra.SPACE) + self.assert_(self.dcode.color is zbar.SPACE) sym = self.dcode.decode_width(1) - self.assert_(self.dcode.color is zebra.BAR) + self.assert_(self.dcode.color is zbar.BAR) self.dcode.reset() - self.assert_(self.dcode.color is zebra.SPACE) + self.assert_(self.dcode.color is zbar.SPACE) def test_decode(self): inline_sym = [ -1 ] def handler(dcode, closure): self.assert_(dcode is self.dcode) - if dcode.type > zebra.Symbol.PARTIAL: + if dcode.type > zbar.Symbol.PARTIAL: inline_sym[0] = dcode.type closure[0] += 1 @@ -130,36 +130,36 @@ def handler(dcode, closure): if width == ' ': continue sym = self.dcode.decode_width(int(width)) if i < len(encoded_widths) - 1: - self.assert_(sym is zebra.Symbol.NONE or - sym is zebra.Symbol.PARTIAL) + self.assert_(sym is zbar.Symbol.NONE or + sym is zbar.Symbol.PARTIAL) else: - self.assert_(sym is zebra.Symbol.EAN13) + self.assert_(sym is zbar.Symbol.EAN13) self.assertEqual(self.dcode.data, '6268964977804') - self.assert_(self.dcode.color is zebra.BAR) - self.assert_(sym is zebra.Symbol.EAN13) - self.assert_(inline_sym[0] is zebra.Symbol.EAN13) + self.assert_(self.dcode.color is zbar.BAR) + self.assert_(sym is zbar.Symbol.EAN13) + self.assert_(inline_sym[0] is zbar.Symbol.EAN13) self.assertEqual(explicit_closure, [ 2 ]) # FIXME test exception during callback class TestImage(ut.TestCase): def setUp(self): - self.image = zebra.Image(123, 456, 'Y800') + self.image = zbar.Image(123, 456, 'Y800') def tearDown(self): del(self.image) def test_type(self): - self.assert_(isinstance(self.image, zebra.Image)) + self.assert_(isinstance(self.image, zbar.Image)) self.assert_(callable(self.image.convert)) def test_new(self): self.assertEqual(self.image.format, 'Y800') self.assertEqual(self.image.size, (123, 456)) - image = zebra.Image() - self.assert_(isinstance(image, zebra.Image)) + image = zbar.Image() + self.assert_(isinstance(image, zbar.Image)) self.assertEqual(image.format, '\0\0\0\0') self.assertEqual(image.size, (0, 0)) @@ -196,13 +196,13 @@ def set_size(sz): class TestImageScanner(ut.TestCase): def setUp(self): - self.scn = zebra.ImageScanner() + self.scn = zbar.ImageScanner() def tearDown(self): del(self.scn) def test_type(self): - self.assert_(isinstance(self.scn, zebra.ImageScanner)) + self.assert_(isinstance(self.scn, zbar.ImageScanner)) self.assert_(callable(self.scn.set_config)) self.assert_(callable(self.scn.parse_config)) self.assert_(callable(self.scn.enable_cache)) @@ -221,8 +221,8 @@ def test_parse_config(self): class TestImageScan(ut.TestCase): def setUp(self): - self.scn = zebra.ImageScanner() - self.image = zebra.Image(size[0], size[1], 'Y800', data) + self.scn = zbar.ImageScanner() + self.image = zbar.Image(size[0], size[1], 'Y800', data) def tearDown(self): del(self.image) @@ -233,14 +233,14 @@ def test_scan(self): self.assertEqual(n, 1) i = iter(self.image) - self.assert_(isinstance(i, zebra.SymbolIter)) + self.assert_(isinstance(i, zbar.SymbolIter)) sym = i.next() self.assertRaises(StopIteration, i.next) # this is the only way to obtain a Symbol, # so test Symbol here - self.assert_(isinstance(sym, zebra.Symbol)) - self.assert_(sym.type is zebra.Symbol.EAN13) + self.assert_(isinstance(sym, zbar.Symbol)) + self.assert_(sym.type is zbar.Symbol.EAN13) self.assert_(sym.type is sym.EAN13) self.assertEqual(str(sym.type), 'EAN13') self.assertEqual(sym.count, 0) @@ -264,13 +264,13 @@ def test_scan_again(self): class TestProcessor(ut.TestCase): def setUp(self): - self.proc = zebra.Processor() + self.proc = zbar.Processor() def tearDown(self): del(self.proc) def test_type(self): - self.assert_(isinstance(self.proc, zebra.Processor)) + self.assert_(isinstance(self.proc, zbar.Processor)) self.assert_(callable(self.proc.init)) self.assert_(callable(self.proc.set_config)) self.assert_(callable(self.proc.parse_config)) @@ -297,7 +297,7 @@ def test_processing(self): self.assert_(self.proc.visible is True) self.assertEqual(self.proc.user_wait(1.1), 0) - self.image = zebra.Image(size[0], size[1], 'Y800', data) + self.image = zbar.Image(size[0], size[1], 'Y800', data) count = [ 0 ] def data_handler(proc, image, closure): @@ -307,13 +307,13 @@ def data_handler(proc, image, closure): count[0] += 1 symiter = iter(image) - self.assert_(isinstance(symiter, zebra.SymbolIter)) + self.assert_(isinstance(symiter, zbar.SymbolIter)) symbols = tuple(image) self.assertEqual(len(symbols), 1) for symbol in symbols: - self.assert_(isinstance(symbol, zebra.Symbol)) - self.assert_(symbol.type is zebra.Symbol.EAN13) + self.assert_(isinstance(symbol, zbar.Symbol)) + self.assert_(symbol.type is zbar.Symbol.EAN13) self.assertEqual(symbol.data, '9876543210128') closure[0] += 1 diff --git a/python/zbarmodule.c b/python/zbarmodule.c new file mode 100644 index 0000000..03c822d --- /dev/null +++ b/python/zbarmodule.c @@ -0,0 +1,193 @@ +/*------------------------------------------------------------------------ + * Copyright 2009 (c) Jeff Brown + * + * 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 "zbarmodule.h" + +static char *exc_names[] = { + "zbar.Exception", + NULL, + "zbar.InternalError", + "zbar.UnsupportedError", + "zbar.InvalidRequestError", + "zbar.SystemError", + "zbar.LockingError", + "zbar.BusyError", + "zbar.X11DisplayError", + "zbar.X11ProtocolError", + "zbar.WindowClosed", +}; + +int +object_to_bool (PyObject *obj, + int *val) +{ + int tmp = PyObject_IsTrue(obj); + if(tmp < 0) + return(0); + *val = tmp; + return(1); +} + +PyObject *zbar_exc[ZBAR_ERR_NUM]; +zbarEnumItem *color_enum[2]; +zbarEnum *config_enum; +PyObject *symbol_enum; +zbarEnumItem *symbol_NONE; + +static PyObject* +version (PyObject *self, + PyObject *args) +{ + if(!PyArg_ParseTuple(args, "")) + return(NULL); + + unsigned int major, minor; + zbar_version(&major, &minor); + + return(Py_BuildValue("II", major, minor)); +} + +static PyObject* +set_verbosity (PyObject *self, + PyObject *args) +{ + int verbosity; + if(!PyArg_ParseTuple(args, "i", &verbosity)) + return(NULL); + + zbar_set_verbosity(verbosity); + + Py_INCREF(Py_None); + return(Py_None); +} + +static PyObject* +increase_verbosity (PyObject *self, + PyObject *args) +{ + if(!PyArg_ParseTuple(args, "")) + return(NULL); + + zbar_increase_verbosity(); + + Py_INCREF(Py_None); + return(Py_None); +} + +static PyMethodDef zbar_functions[] = { + { "version", version, METH_VARARGS, NULL }, + { "set_verbosity", set_verbosity, METH_VARARGS, NULL }, + { "increase_verbosity", increase_verbosity, METH_VARARGS, NULL }, + { NULL, }, +}; + +PyMODINIT_FUNC +initzbar () +{ + /* initialize constant containers */ + config_enum = zbarEnum_New(); + symbol_enum = PyDict_New(); + if(!config_enum || !symbol_enum) + return; + + /* initialize types */ + zbarEnumItem_Type.tp_base = &PyInt_Type; + zbarException_Type.tp_base = (PyTypeObject*)PyExc_Exception; + + if(PyType_Ready(&zbarException_Type) < 0 || + PyType_Ready(&zbarEnumItem_Type) < 0 || + PyType_Ready(&zbarEnum_Type) < 0 || + PyType_Ready(&zbarImage_Type) < 0 || + PyType_Ready(&zbarSymbol_Type) < 0 || + PyType_Ready(&zbarSymbolIter_Type) < 0 || + PyType_Ready(&zbarProcessor_Type) < 0 || + PyType_Ready(&zbarImageScanner_Type) < 0 || + PyType_Ready(&zbarDecoder_Type) < 0 || + PyType_Ready(&zbarScanner_Type) < 0) + return; + + zbar_exc[0] = (PyObject*)&zbarException_Type; + zbar_exc[ZBAR_ERR_NOMEM] = NULL; + zbar_error_t ei; + for(ei = ZBAR_ERR_INTERNAL; ei < ZBAR_ERR_NUM; ei++) { + zbar_exc[ei] = PyErr_NewException(exc_names[ei], zbar_exc[0], NULL); + if(!zbar_exc[ei]) + return; + } + + /* internally created/read-only type overrides */ + zbarEnum_Type.tp_new = NULL; + zbarEnum_Type.tp_setattr = NULL; + zbarEnum_Type.tp_setattro = NULL; + + /* initialize module */ + PyObject *mod = Py_InitModule("zbar", zbar_functions); + if(!mod) + return; + + /* add types to module */ + PyModule_AddObject(mod, "EnumItem", (PyObject*)&zbarEnumItem_Type); + PyModule_AddObject(mod, "Image", (PyObject*)&zbarImage_Type); + PyModule_AddObject(mod, "Config", (PyObject*)config_enum); + PyModule_AddObject(mod, "Symbol", (PyObject*)&zbarSymbol_Type); + PyModule_AddObject(mod, "SymbolIter", (PyObject*)&zbarSymbolIter_Type); + PyModule_AddObject(mod, "Processor", (PyObject*)&zbarProcessor_Type); + PyModule_AddObject(mod, "ImageScanner", (PyObject*)&zbarImageScanner_Type); + PyModule_AddObject(mod, "Decoder", (PyObject*)&zbarDecoder_Type); + PyModule_AddObject(mod, "Scanner", (PyObject*)&zbarScanner_Type); + + for(ei = 0; ei < ZBAR_ERR_NUM; ei++) + if(zbar_exc[ei]) + PyModule_AddObject(mod, exc_names[ei] + 5, zbar_exc[ei]); + + /* add constants */ + PyObject *dict = PyModule_GetDict(mod); + color_enum[ZBAR_SPACE] = + zbarEnumItem_New(dict, NULL, ZBAR_SPACE, "SPACE"); + color_enum[ZBAR_BAR] = + zbarEnumItem_New(dict, NULL, ZBAR_BAR, "BAR"); + + zbarEnum_Add(config_enum, ZBAR_CFG_ENABLE, "ENABLE"); + zbarEnum_Add(config_enum, ZBAR_CFG_ADD_CHECK, "ADD_CHECK"); + zbarEnum_Add(config_enum, ZBAR_CFG_EMIT_CHECK, "EMIT_CHECK"); + zbarEnum_Add(config_enum, ZBAR_CFG_ASCII, "ASCII"); + zbarEnum_Add(config_enum, ZBAR_CFG_MIN_LEN, "MIN_LEN"); + zbarEnum_Add(config_enum, ZBAR_CFG_MAX_LEN, "MAX_LEN"); + zbarEnum_Add(config_enum, ZBAR_CFG_X_DENSITY, "X_DENSITY"); + zbarEnum_Add(config_enum, ZBAR_CFG_Y_DENSITY, "Y_DENSITY"); + + PyObject *tp_dict = zbarSymbol_Type.tp_dict; + symbol_NONE = + zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_NONE, "NONE"); + zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_PARTIAL, "PARTIAL"); + zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_EAN8, "EAN8"); + zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_UPCE, "UPCE"); + zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_ISBN10, "ISBN10"); + zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_UPCA, "UPCA"); + zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_EAN13, "EAN13"); + zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_ISBN13, "ISBN13"); + zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_I25, "I25"); + zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_CODE39, "CODE39"); + zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_PDF417, "PDF417"); + zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_CODE128, "CODE128"); +} diff --git a/python/zbarmodule.h b/python/zbarmodule.h new file mode 100644 index 0000000..e968d74 --- /dev/null +++ b/python/zbarmodule.h @@ -0,0 +1,141 @@ +/*------------------------------------------------------------------------ + * Copyright 2009 (c) Jeff Brown + * + * 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 +#include +#include + +#ifndef _ZBARMODULE_H_ +#define _ZBARMODULE_H_ + +typedef struct { + PyBaseExceptionObject base; + PyObject *obj; +} zbarException; + +extern PyTypeObject zbarException_Type; +extern PyObject *zbar_exc[ZBAR_ERR_NUM]; + +extern PyObject *zbarErr_Set(PyObject *self); + +typedef struct { + PyIntObject val; /* integer value is super type */ + PyObject *name; /* associated string name */ +} zbarEnumItem; + +extern PyTypeObject zbarEnumItem_Type; + +extern zbarEnumItem *zbarEnumItem_New(PyObject *byname, + PyObject *byvalue, + int val, + const char *name); + +typedef struct { + PyObject_HEAD + PyObject *byname, *byvalue; /* zbarEnumItem content dictionaries */ +} zbarEnum; + +extern PyTypeObject zbarEnum_Type; + +extern zbarEnum *zbarEnum_New(); +extern int zbarEnum_Add(zbarEnum *self, + int val, + const char *name); + +typedef struct { + PyObject_HEAD + zbar_image_t *zimg; + PyObject *data; +} zbarImage; + +extern PyTypeObject zbarImage_Type; + +extern zbarImage *zbarImage_FromImage(zbar_image_t *zimg); +extern int zbarImage_validate(zbarImage *image); + +typedef struct { + PyObject_HEAD + const zbar_symbol_t *zsym; + zbarImage *img; + PyObject *data; + PyObject *loc; +} zbarSymbol; + +extern PyTypeObject zbarSymbol_Type; + +extern zbarSymbol *zbarSymbol_FromSymbol(zbarImage *img, + const zbar_symbol_t *zsym); +extern zbarEnumItem *zbarSymbol_LookupEnum(zbar_symbol_type_t type); + +typedef struct { + PyObject_HEAD + const zbar_symbol_t *zsym; + zbarImage *img; +} zbarSymbolIter; + +extern PyTypeObject zbarSymbolIter_Type; + +typedef struct { + PyObject_HEAD + zbar_processor_t *zproc; + PyObject *handler; + PyObject *closure; +} zbarProcessor; + +extern PyTypeObject zbarProcessor_Type; + +#define zbarProcessor_Check(obj) PyObject_TypeCheck(obj, &zbarProcessor_Type) + +typedef struct { + PyObject_HEAD + zbar_image_scanner_t *zscn; +} zbarImageScanner; + +extern PyTypeObject zbarImageScanner_Type; + +typedef struct { + PyObject_HEAD + zbar_decoder_t *zdcode; + PyObject *handler; + PyObject *args; +} zbarDecoder; + +extern PyTypeObject zbarDecoder_Type; + +typedef struct { + PyObject_HEAD + zbar_scanner_t *zscn; + zbarDecoder *decoder; +} zbarScanner; + +extern PyTypeObject zbarScanner_Type; + +extern zbarEnumItem *color_enum[2]; +extern zbarEnum *config_enum; +extern PyObject *symbol_enum; +extern zbarEnumItem *symbol_NONE; + +int object_to_bool(PyObject *obj, + int *val); + +#endif diff --git a/python/zebramodule.c b/python/zebramodule.c deleted file mode 100644 index 3df3202..0000000 --- a/python/zebramodule.c +++ /dev/null @@ -1,170 +0,0 @@ -#include "zebramodule.h" - -static char *exc_names[] = { - "zebra.Exception", - NULL, - "zebra.InternalError", - "zebra.UnsupportedError", - "zebra.InvalidRequestError", - "zebra.SystemError", - "zebra.LockingError", - "zebra.BusyError", - "zebra.X11DisplayError", - "zebra.X11ProtocolError", - "zebra.WindowClosed", -}; - -int -object_to_bool (PyObject *obj, - int *val) -{ - int tmp = PyObject_IsTrue(obj); - if(tmp < 0) - return(0); - *val = tmp; - return(1); -} - -PyObject *zebra_exc[ZEBRA_ERR_NUM]; -zebraEnumItem *color_enum[2]; -zebraEnum *config_enum; -PyObject *symbol_enum; -zebraEnumItem *symbol_NONE; - -static PyObject* -version (PyObject *self, - PyObject *args) -{ - if(!PyArg_ParseTuple(args, "")) - return(NULL); - - unsigned int major, minor; - zebra_version(&major, &minor); - - return(Py_BuildValue("II", major, minor)); -} - -static PyObject* -set_verbosity (PyObject *self, - PyObject *args) -{ - int verbosity; - if(!PyArg_ParseTuple(args, "i", &verbosity)) - return(NULL); - - zebra_set_verbosity(verbosity); - - Py_INCREF(Py_None); - return(Py_None); -} - -static PyObject* -increase_verbosity (PyObject *self, - PyObject *args) -{ - if(!PyArg_ParseTuple(args, "")) - return(NULL); - - zebra_increase_verbosity(); - - Py_INCREF(Py_None); - return(Py_None); -} - -static PyMethodDef zebra_functions[] = { - { "version", version, METH_VARARGS, NULL }, - { "set_verbosity", set_verbosity, METH_VARARGS, NULL }, - { "increase_verbosity", increase_verbosity, METH_VARARGS, NULL }, - { NULL, }, -}; - -PyMODINIT_FUNC -initzebra () -{ - /* initialize constant containers */ - config_enum = zebraEnum_New(); - symbol_enum = PyDict_New(); - if(!config_enum || !symbol_enum) - return; - - /* initialize types */ - zebraEnumItem_Type.tp_base = &PyInt_Type; - zebraException_Type.tp_base = (PyTypeObject*)PyExc_Exception; - - if(PyType_Ready(&zebraException_Type) < 0 || - PyType_Ready(&zebraEnumItem_Type) < 0 || - PyType_Ready(&zebraEnum_Type) < 0 || - PyType_Ready(&zebraImage_Type) < 0 || - PyType_Ready(&zebraSymbol_Type) < 0 || - PyType_Ready(&zebraSymbolIter_Type) < 0 || - PyType_Ready(&zebraProcessor_Type) < 0 || - PyType_Ready(&zebraImageScanner_Type) < 0 || - PyType_Ready(&zebraDecoder_Type) < 0 || - PyType_Ready(&zebraScanner_Type) < 0) - return; - - zebra_exc[0] = (PyObject*)&zebraException_Type; - zebra_exc[ZEBRA_ERR_NOMEM] = NULL; - zebra_error_t ei; - for(ei = ZEBRA_ERR_INTERNAL; ei < ZEBRA_ERR_NUM; ei++) { - zebra_exc[ei] = PyErr_NewException(exc_names[ei], zebra_exc[0], NULL); - if(!zebra_exc[ei]) - return; - } - - /* internally created/read-only type overrides */ - zebraEnum_Type.tp_new = NULL; - zebraEnum_Type.tp_setattr = NULL; - zebraEnum_Type.tp_setattro = NULL; - - /* initialize module */ - PyObject *mod = Py_InitModule("zebra", zebra_functions); - if(!mod) - return; - - /* add types to module */ - PyModule_AddObject(mod, "EnumItem", (PyObject*)&zebraEnumItem_Type); - PyModule_AddObject(mod, "Image", (PyObject*)&zebraImage_Type); - PyModule_AddObject(mod, "Config", (PyObject*)config_enum); - PyModule_AddObject(mod, "Symbol", (PyObject*)&zebraSymbol_Type); - PyModule_AddObject(mod, "SymbolIter", (PyObject*)&zebraSymbolIter_Type); - PyModule_AddObject(mod, "Processor", (PyObject*)&zebraProcessor_Type); - PyModule_AddObject(mod, "ImageScanner", (PyObject*)&zebraImageScanner_Type); - PyModule_AddObject(mod, "Decoder", (PyObject*)&zebraDecoder_Type); - PyModule_AddObject(mod, "Scanner", (PyObject*)&zebraScanner_Type); - - for(ei = 0; ei < ZEBRA_ERR_NUM; ei++) - if(zebra_exc[ei]) - PyModule_AddObject(mod, exc_names[ei] + 6, zebra_exc[ei]); - - /* add constants */ - PyObject *dict = PyModule_GetDict(mod); - color_enum[ZEBRA_SPACE] = - zebraEnumItem_New(dict, NULL, ZEBRA_SPACE, "SPACE"); - color_enum[ZEBRA_BAR] = - zebraEnumItem_New(dict, NULL, ZEBRA_BAR, "BAR"); - - zebraEnum_Add(config_enum, ZEBRA_CFG_ENABLE, "ENABLE"); - zebraEnum_Add(config_enum, ZEBRA_CFG_ADD_CHECK, "ADD_CHECK"); - zebraEnum_Add(config_enum, ZEBRA_CFG_EMIT_CHECK, "EMIT_CHECK"); - zebraEnum_Add(config_enum, ZEBRA_CFG_ASCII, "ASCII"); - zebraEnum_Add(config_enum, ZEBRA_CFG_MIN_LEN, "MIN_LEN"); - zebraEnum_Add(config_enum, ZEBRA_CFG_MAX_LEN, "MAX_LEN"); - zebraEnum_Add(config_enum, ZEBRA_CFG_X_DENSITY, "X_DENSITY"); - zebraEnum_Add(config_enum, ZEBRA_CFG_Y_DENSITY, "Y_DENSITY"); - - PyObject *tp_dict = zebraSymbol_Type.tp_dict; - symbol_NONE = - zebraEnumItem_New(tp_dict, symbol_enum, ZEBRA_NONE, "NONE"); - zebraEnumItem_New(tp_dict, symbol_enum, ZEBRA_PARTIAL, "PARTIAL"); - zebraEnumItem_New(tp_dict, symbol_enum, ZEBRA_EAN8, "EAN8"); - zebraEnumItem_New(tp_dict, symbol_enum, ZEBRA_UPCE, "UPCE"); - zebraEnumItem_New(tp_dict, symbol_enum, ZEBRA_ISBN10, "ISBN10"); - zebraEnumItem_New(tp_dict, symbol_enum, ZEBRA_UPCA, "UPCA"); - zebraEnumItem_New(tp_dict, symbol_enum, ZEBRA_EAN13, "EAN13"); - zebraEnumItem_New(tp_dict, symbol_enum, ZEBRA_ISBN13, "ISBN13"); - zebraEnumItem_New(tp_dict, symbol_enum, ZEBRA_I25, "I25"); - zebraEnumItem_New(tp_dict, symbol_enum, ZEBRA_CODE39, "CODE39"); - zebraEnumItem_New(tp_dict, symbol_enum, ZEBRA_PDF417, "PDF417"); - zebraEnumItem_New(tp_dict, symbol_enum, ZEBRA_CODE128, "CODE128"); -} diff --git a/python/zebramodule.h b/python/zebramodule.h deleted file mode 100644 index 3985c87..0000000 --- a/python/zebramodule.h +++ /dev/null @@ -1,118 +0,0 @@ -#include -#include -#include - -#ifndef _ZEBRAMODULE_H_ -#define _ZEBRAMODULE_H_ - -typedef struct { - PyBaseExceptionObject base; - PyObject *obj; -} zebraException; - -extern PyTypeObject zebraException_Type; -extern PyObject *zebra_exc[ZEBRA_ERR_NUM]; - -extern PyObject *zebraErr_Set(PyObject *self); - -typedef struct { - PyIntObject val; /* integer value is super type */ - PyObject *name; /* associated string name */ -} zebraEnumItem; - -extern PyTypeObject zebraEnumItem_Type; - -extern zebraEnumItem *zebraEnumItem_New(PyObject *byname, - PyObject *byvalue, - int val, - const char *name); - -typedef struct { - PyObject_HEAD - PyObject *byname, *byvalue; /* zebraEnumItem content dictionaries */ -} zebraEnum; - -extern PyTypeObject zebraEnum_Type; - -extern zebraEnum *zebraEnum_New(); -extern int zebraEnum_Add(zebraEnum *self, - int val, - const char *name); - -typedef struct { - PyObject_HEAD - zebra_image_t *zimg; - PyObject *data; -} zebraImage; - -extern PyTypeObject zebraImage_Type; - -extern zebraImage *zebraImage_FromImage(zebra_image_t *zimg); -extern int zebraImage_validate(zebraImage *image); - -typedef struct { - PyObject_HEAD - const zebra_symbol_t *zsym; - zebraImage *img; - PyObject *data; - PyObject *loc; -} zebraSymbol; - -extern PyTypeObject zebraSymbol_Type; - -extern zebraSymbol *zebraSymbol_FromSymbol(zebraImage *img, - const zebra_symbol_t *zsym); -extern zebraEnumItem *zebraSymbol_LookupEnum(zebra_symbol_type_t type); - -typedef struct { - PyObject_HEAD - const zebra_symbol_t *zsym; - zebraImage *img; -} zebraSymbolIter; - -extern PyTypeObject zebraSymbolIter_Type; - -typedef struct { - PyObject_HEAD - zebra_processor_t *zproc; - PyObject *handler; - PyObject *closure; -} zebraProcessor; - -extern PyTypeObject zebraProcessor_Type; - -#define zebraProcessor_Check(obj) PyObject_TypeCheck(obj, &zebraProcessor_Type) - -typedef struct { - PyObject_HEAD - zebra_image_scanner_t *zscn; -} zebraImageScanner; - -extern PyTypeObject zebraImageScanner_Type; - -typedef struct { - PyObject_HEAD - zebra_decoder_t *zdcode; - PyObject *handler; - PyObject *args; -} zebraDecoder; - -extern PyTypeObject zebraDecoder_Type; - -typedef struct { - PyObject_HEAD - zebra_scanner_t *zscn; - zebraDecoder *decoder; -} zebraScanner; - -extern PyTypeObject zebraScanner_Type; - -extern zebraEnumItem *color_enum[2]; -extern zebraEnum *config_enum; -extern PyObject *symbol_enum; -extern zebraEnumItem *symbol_NONE; - -int object_to_bool(PyObject *obj, - int *val); - -#endif diff --git a/qt/Makefile.am.inc b/qt/Makefile.am.inc index 9999b92..dc1525e 100644 --- a/qt/Makefile.am.inc +++ b/qt/Makefile.am.inc @@ -1,15 +1,15 @@ -lib_LTLIBRARIES += qt/libzebraqt.la -qt_libzebraqt_la_CPPFLAGS = -Iqt $(QT_CFLAGS) $(AM_CPPFLAGS) -qt_libzebraqt_la_LDFLAGS = -version-info $(ZQT_LIB_VERSION) $(AM_LDFLAGS) -qt_libzebraqt_la_LIBADD = $(QT_LIBS) zebra/libzebra.la $(AM_LIBADD) +lib_LTLIBRARIES += qt/libzbarqt.la +qt_libzbarqt_la_CPPFLAGS = -Iqt $(QT_CFLAGS) $(AM_CPPFLAGS) +qt_libzbarqt_la_LDFLAGS = -version-info $(ZQT_LIB_VERSION) $(AM_LDFLAGS) +qt_libzbarqt_la_LIBADD = $(QT_LIBS) zbar/libzbar.la $(AM_LIBADD) -qt_libzebraqt_la_SOURCES = qt/QZebra.cpp qt/QZebraThread.h qt/QZebraThread.cpp -nodist_qt_libzebraqt_la_SOURCES = qt/moc_QZebra.cpp qt/moc_QZebraThread.cpp -BUILT_SOURCES += $(nodist_qt_libzebraqt_la_SOURCES) -DISTCLEANFILES += $(nodist_qt_libzebraqt_la_SOURCES) +qt_libzbarqt_la_SOURCES = qt/QZBar.cpp qt/QZBarThread.h qt/QZBarThread.cpp +nodist_qt_libzbarqt_la_SOURCES = qt/moc_QZBar.cpp qt/moc_QZBarThread.cpp +BUILT_SOURCES += $(nodist_qt_libzbarqt_la_SOURCES) +DISTCLEANFILES += $(nodist_qt_libzbarqt_la_SOURCES) qt/moc_%.cpp: qt/%.h - $(MOC) $(qt_libzebraqt_la_CPPFLAGS) $< -o $@ + $(MOC) $(qt_libzbarqt_la_CPPFLAGS) $< -o $@ -qt/moc_%.cpp: include/zebra/%.h - $(MOC) $(qt_libzebraqt_la_CPPFLAGS) $< -o $@ +qt/moc_%.cpp: include/zbar/%.h + $(MOC) $(qt_libzbarqt_la_CPPFLAGS) $< -o $@ diff --git a/qt/QZebra.cpp b/qt/QZBar.cpp similarity index 73% rename from qt/QZebra.cpp rename to qt/QZBar.cpp index 5011112..d4246be 100644 --- a/qt/QZebra.cpp +++ b/qt/QZBar.cpp @@ -1,35 +1,35 @@ //------------------------------------------------------------------------ -// Copyright 2008 (c) Jeff Brown +// Copyright 2008-2009 (c) Jeff Brown // -// This file is part of the Zebra Barcode Library. +// This file is part of the ZBar Bar Code Reader. // -// The Zebra Barcode Library is free software; you can redistribute it +// 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 Zebra Barcode Library is distributed in the hope that it will be +// 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 Zebra Barcode Library; if not, write to the Free +// 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/zebra +// http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ #include #include #include -#include -#include "QZebraThread.h" +#include +#include "QZBarThread.h" -using namespace zebra; +using namespace zbar; -QZebra::QZebra (QWidget *parent) +QZBar::QZBar (QWidget *parent) : QWidget(parent), thread(NULL), _videoDevice(), @@ -42,7 +42,7 @@ QZebra::QZebra (QWidget *parent) sizing.setHeightForWidth(true); setSizePolicy(sizing); - thread = new QZebraThread; + thread = new QZBarThread; if(testAttribute(Qt::WA_WState_Created)) thread->window.attach(x11Info().display(), winId()); connect(thread, SIGNAL(videoOpened(bool)), @@ -58,48 +58,48 @@ QZebra::QZebra (QWidget *parent) thread->start(); } -QZebra::~QZebra () +QZBar::~QZBar () { if(thread) { thread->window.attach(NULL); - thread->pushEvent(new QEvent((QEvent::Type)QZebraThread::Exit)); + thread->pushEvent(new QEvent((QEvent::Type)QZBarThread::Exit)); thread->wait(); thread = NULL; } } -QString QZebra::videoDevice () const +QString QZBar::videoDevice () const { return(_videoDevice); } -void QZebra::setVideoDevice (const QString& videoDevice) +void QZBar::setVideoDevice (const QString& videoDevice) { if(!thread) return; if(_videoDevice != videoDevice) { _videoDevice = videoDevice; _videoEnabled = !_videoDevice.isEmpty(); - thread->pushEvent(new QZebraThread::VideoDeviceEvent(videoDevice)); + thread->pushEvent(new QZBarThread::VideoDeviceEvent(videoDevice)); } } -bool QZebra::isVideoEnabled () const +bool QZBar::isVideoEnabled () const { return(_videoEnabled); } -void QZebra::setVideoEnabled (bool videoEnabled) +void QZBar::setVideoEnabled (bool videoEnabled) { if(!thread) return; if(_videoEnabled != videoEnabled) { _videoEnabled = videoEnabled; - thread->pushEvent(new QZebraThread::VideoEnabledEvent(videoEnabled)); + thread->pushEvent(new QZBarThread::VideoEnabledEvent(videoEnabled)); } } -bool QZebra::isVideoOpened () const +bool QZBar::isVideoOpened () const { if(!thread) return(false); @@ -107,21 +107,21 @@ bool QZebra::isVideoOpened () const return(thread->_videoOpened); } -void QZebra::scanImage (const QImage &image) +void QZBar::scanImage (const QImage &image) { if(!thread) return; - thread->pushEvent(new QZebraThread::ScanImageEvent(image)); + thread->pushEvent(new QZBarThread::ScanImageEvent(image)); } -void QZebra::dragEnterEvent (QDragEnterEvent *event) +void QZBar::dragEnterEvent (QDragEnterEvent *event) { if(event->mimeData()->hasImage() || event->mimeData()->hasUrls()) event->acceptProposedAction(); } -void QZebra::dropEvent (QDropEvent *event) +void QZBar::dropEvent (QDropEvent *event) { if(event->mimeData()->hasImage()) { QImage image = qvariant_cast(event->mimeData()->imageData()); @@ -144,7 +144,7 @@ void QZebra::dropEvent (QDropEvent *event) } } -QSize QZebra::sizeHint () const +QSize QZBar::sizeHint () const { if(!thread) return(QSize(640, 480)); @@ -152,7 +152,7 @@ QSize QZebra::sizeHint () const return(QSize(thread->reqWidth, thread->reqHeight)); } -int QZebra::heightForWidth (int width) const +int QZBar::heightForWidth (int width) const { if(thread) { QMutexLocker locker(&thread->mutex); @@ -164,26 +164,26 @@ int QZebra::heightForWidth (int width) const return(width * 3 / 4); } -void QZebra::paintEvent (QPaintEvent *) +void QZBar::paintEvent (QPaintEvent *) { if(thread) thread->window.redraw(); } -void QZebra::resizeEvent (QResizeEvent *event) +void QZBar::resizeEvent (QResizeEvent *event) { QSize size = event->size(); if(thread) thread->window.resize(size.rwidth(), size.rheight()); } -void QZebra::changeEvent(QEvent *event) +void QZBar::changeEvent(QEvent *event) { if(event->type() == QEvent::ParentChange) thread->window.attach(x11Info().display(), winId()); } -void QZebra::sizeChange () +void QZBar::sizeChange () { update(); updateGeometry(); diff --git a/qt/QZebraThread.cpp b/qt/QZBarThread.cpp similarity index 84% rename from qt/QZebraThread.cpp rename to qt/QZBarThread.cpp index 957aa7e..a193470 100644 --- a/qt/QZebraThread.cpp +++ b/qt/QZBarThread.cpp @@ -1,34 +1,34 @@ //------------------------------------------------------------------------ -// Copyright 2008 (c) Jeff Brown +// Copyright 2008-2009 (c) Jeff Brown // -// This file is part of the Zebra Barcode Library. +// This file is part of the ZBar Bar Code Reader. // -// The Zebra Barcode Library is free software; you can redistribute it +// 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 Zebra Barcode Library is distributed in the hope that it will be +// 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 Zebra Barcode Library; if not, write to the Free +// 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/zebra +// http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ #include -#include "QZebraThread.h" +#include "QZBarThread.h" -using namespace zebra; +using namespace zbar; static const QString textFormat("%1%2:%3"); -QZebraThread::QZebraThread () +QZBarThread::QZBarThread () : reqWidth(DEFAULT_WIDTH), reqHeight(DEFAULT_HEIGHT), video(NULL), @@ -40,7 +40,7 @@ QZebraThread::QZebraThread () scanner.set_handler(*this); } -void QZebraThread::image_callback (Image &image) +void QZBarThread::image_callback (Image &image) { for(Image::SymbolIterator sym = image.symbol_begin(); sym != image.symbol_end(); @@ -56,7 +56,7 @@ void QZebraThread::image_callback (Image &image) } } -void QZebraThread::processImage (Image &image) +void QZBarThread::processImage (Image &image) { scanner.scan(image); window.draw(image); @@ -67,7 +67,7 @@ void QZebraThread::processImage (Image &image) emit update(); } -void QZebraThread::enableVideo (bool enable) +void QZBarThread::enableVideo (bool enable) { if(!video) { videoRunning = videoEnabled = false; @@ -88,7 +88,7 @@ void QZebraThread::enableVideo (bool enable) } } -void QZebraThread::openVideo (const QString &device) +void QZBarThread::openVideo (const QString &device) { if(videoRunning) enableVideo(false); @@ -133,25 +133,25 @@ void QZebraThread::openVideo (const QString &device) } -void QZebraThread::videoDeviceEvent (VideoDeviceEvent *e) +void QZBarThread::videoDeviceEvent (VideoDeviceEvent *e) { openVideo(e->device); } -void QZebraThread::videoEnabledEvent (VideoEnabledEvent *e) +void QZBarThread::videoEnabledEvent (VideoEnabledEvent *e) { if(videoRunning && !e->enabled) enableVideo(false); videoEnabled = e->enabled; } -void QZebraThread::scanImageEvent (ScanImageEvent *e) +void QZBarThread::scanImageEvent (ScanImageEvent *e) { if(videoRunning) enableVideo(false); try { - image = new QZebraImage(e->image); + image = new QZBarImage(e->image); processImage(*image); } catch(std::exception &e) { @@ -160,7 +160,7 @@ void QZebraThread::scanImageEvent (ScanImageEvent *e) } } -bool QZebraThread::event (QEvent *e) +bool QZBarThread::event (QEvent *e) { switch(e->type()) { case VideoDevice: @@ -184,7 +184,7 @@ bool QZebraThread::event (QEvent *e) } -void QZebraThread::run () +void QZBarThread::run () { QEvent *e = NULL; while(running) { diff --git a/qt/QZebraThread.h b/qt/QZBarThread.h similarity index 85% rename from qt/QZebraThread.h rename to qt/QZBarThread.h index a78e7ac..0e4b000 100644 --- a/qt/QZebraThread.h +++ b/qt/QZBarThread.h @@ -1,42 +1,42 @@ //------------------------------------------------------------------------ -// Copyright 2008 (c) Jeff Brown +// Copyright 2008-2009 (c) Jeff Brown // -// This file is part of the Zebra Barcode Library. +// This file is part of the ZBar Bar Code Reader. // -// The Zebra Barcode Library is free software; you can redistribute it +// 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 Zebra Barcode Library is distributed in the hope that it will be +// 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 Zebra Barcode Library; if not, write to the Free +// 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/zebra +// http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#ifndef _QZEBRATHREAD_H_ -#define _QZEBRATHREAD_H_ +#ifndef _QZBARTHREAD_H_ +#define _QZBARTHREAD_H_ #include #include #include #include -#include -#include -#include +#include +#include +#include #define DEFAULT_WIDTH 640 #define DEFAULT_HEIGHT 480 -namespace zebra { +namespace zbar { -class QZebraThread +class QZBarThread : public QThread, public Image::Handler { @@ -100,7 +100,7 @@ class QZebraThread Window window; - QZebraThread(); + QZBarThread(); void pushEvent (QEvent *e) { @@ -141,7 +141,7 @@ class QZebraThread private: Video *video; ImageScanner scanner; - QZebraImage *image; + QZBarImage *image; bool running; bool videoRunning; bool videoEnabled; diff --git a/test/Makefile.am.inc b/test/Makefile.am.inc index 3267e7e..64d0b3f 100644 --- a/test/Makefile.am.inc +++ b/test/Makefile.am.inc @@ -1,27 +1,27 @@ check_PROGRAMS += test/test_decode test_test_decode_SOURCES = test/test_decode.c test/pdf417_encode.h test_test_decode_CFLAGS = -Wno-unused $(AM_CFLAGS) -test_test_decode_LDADD = zebra/libzebra.la $(AM_LDADD) +test_test_decode_LDADD = zbar/libzbar.la $(AM_LDADD) TEST_IMAGE_SOURCES = test/test_images.c test/test_images.h check_PROGRAMS += test/test_convert test_test_convert_SOURCES = test/test_convert.c $(TEST_IMAGE_SOURCES) -test_test_convert_LDADD = zebra/libzebra.la $(AM_LDADD) +test_test_convert_LDADD = zbar/libzbar.la $(AM_LDADD) if HAVE_POLL check_PROGRAMS += test/test_proc test_test_proc_SOURCES = test/test_proc.c $(TEST_IMAGE_SOURCES) -test_test_proc_LDADD = zebra/libzebra.la $(AM_LDADD) +test_test_proc_LDADD = zbar/libzbar.la $(AM_LDADD) check_PROGRAMS += test/test_cpp test_test_cpp_SOURCES = test/test_cpp.cpp -test_test_cpp_LDADD = zebra/libzebra.la $(AM_LDADD) +test_test_cpp_LDADD = zbar/libzbar.la $(AM_LDADD) if HAVE_JPEG check_PROGRAMS += test/test_jpeg test_test_jpeg_SOURCES = test/test_jpeg.c -test_test_jpeg_LDADD = zebra/libzebra.la $(AM_LDADD) +test_test_jpeg_LDADD = zbar/libzbar.la $(AM_LDADD) endif endif @@ -29,14 +29,14 @@ if HAVE_MAGICK check_PROGRAMS += test/dbg_scan test_dbg_scan_SOURCES = test/dbg_scan.cpp test_dbg_scan_CPPFLAGS = $(MAGICK_CFLAGS) $(AM_CPPFLAGS) -test_dbg_scan_LDADD = $(MAGICK_LIBS) zebra/libzebra.la $(AM_LDADD) +test_dbg_scan_LDADD = $(MAGICK_LIBS) zbar/libzbar.la $(AM_LDADD) endif if HAVE_GTK check_PROGRAMS += test/test_gtk test_test_gtk_SOURCES = test/test_gtk.c test/scan_video.c test_test_gtk_CPPFLAGS = $(GTK_CFLAGS) $(AM_CPPFLAGS) -test_test_gtk_LDADD = $(GTK_LIBS) gtk/libzebragtk.la $(AM_LDADD) +test_test_gtk_LDADD = $(GTK_LIBS) gtk/libzbargtk.la $(AM_LDADD) endif if HAVE_QT @@ -44,7 +44,7 @@ check_PROGRAMS += test/test_qt test_test_qt_SOURCES = test/test_qt.cpp test/scan_video.c nodist_test_test_qt_SOURCES = test/moc_test_qt.h test_test_qt_CPPFLAGS = -Itest $(QT_CFLAGS) $(AM_CPPFLAGS) -test_test_qt_LDADD = $(QT_LIBS) qt/libzebraqt.la $(AM_LDADD) +test_test_qt_LDADD = $(QT_LIBS) qt/libzbarqt.la $(AM_LDADD) BUILT_SOURCES += $(nodist_test_test_qt_SOURCES) DISTCLEANFILES += $(nodist_test_test_qt_SOURCES) diff --git a/test/dbg_scan.cpp b/test/dbg_scan.cpp index fcaf59d..e0e52c5 100644 --- a/test/dbg_scan.cpp +++ b/test/dbg_scan.cpp @@ -1,46 +1,46 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include #include #include #include -#include +#include using namespace std; -using namespace zebra; +using namespace zbar; -#ifndef ZEBRA_FIXED -# define ZEBRA_FIXED 5 +#ifndef ZBAR_FIXED +# define ZBAR_FIXED 5 #endif -#define ZEBRA_FRAC (1 << ZEBRA_FIXED) +#define ZBAR_FRAC (1 << ZBAR_FIXED) Decoder decoder; Scanner scanner; /* undocumented API for drawing cutesy debug graphics */ -extern "C" void zebra_scanner_get_state(const zebra_scanner_t *scn, +extern "C" void zbar_scanner_get_state(const zbar_scanner_t *scn, unsigned *x, unsigned *cur_edge, unsigned *last_edge, @@ -156,7 +156,7 @@ void scan_image (const char *filename) for(unsigned i = 0; i < width; i++) { int edge = scanner.scan_y(raw[i]); unsigned x; - zebra_scanner_get_state(scanner.get_c_scanner(), &x, + zbar_scanner_get_state(scanner.get_c_scanner(), &x, &cur_edge[i], &last_edge[i], &y0[i], &y1[i], &y2[i], &y1_thr[i]); #ifdef DEBUG_SCANNER @@ -166,19 +166,19 @@ void scan_image (const char *filename) if(edge) { last_edge[i] += i - x; unsigned w = scanner.get_width(); - svg << "" << endl << "" << endl << w << "" << endl; - zebra_symbol_type_t sym = decoder.decode_width(w); - if(sym > ZEBRA_PARTIAL) { + zbar_symbol_type_t sym = decoder.decode_width(w); + if(sym > ZBAR_PARTIAL) { svg << "" << decoder.get_data_string() << "" << endl; } @@ -192,7 +192,7 @@ void scan_image (const char *filename) << "" << endl << "
" << endl << "" << endl @@ -207,7 +207,7 @@ void scan_image (const char *filename) << "" << endl << " 1) srcfmt = *(uint32_t*)argv[1]; - zebra_image_t *img = zebra_image_create(); - zebra_image_set_size(img, 640, 480); - zebra_image_set_format(img, srcfmt); + zbar_image_t *img = zbar_image_create(); + zbar_image_set_size(img, 640, 480); + zbar_image_set_format(img, srcfmt); if(test_image_bars(img)) return(2); - if(zebra_image_write(img, "base")) + if(zbar_image_write(img, "base")) return(1); return(0); } diff --git a/test/test_cpp.cpp b/test/test_cpp.cpp index 3eec707..14c1c22 100644 --- a/test/test_cpp.cpp +++ b/test/test_cpp.cpp @@ -1,29 +1,29 @@ //------------------------------------------------------------------------ -// Copyright 2007-2008 (c) Jeff Brown +// Copyright 2007-2009 (c) Jeff Brown // -// This file is part of the Zebra Barcode Library. +// This file is part of the ZBar Bar Code Reader. // -// The Zebra Barcode Library is free software; you can redistribute it +// 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 Zebra Barcode Library is distributed in the hope that it will be +// 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 Zebra Barcode Library; if not, write to the Free +// 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/zebra +// http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ // NB do not put anything before this header // it's here to check that we didn't omit any dependencies -#include +#include int main (int argc, char **argv) { @@ -31,13 +31,13 @@ int main (int argc, char **argv) if(argc > 1) video_dev = argv[1]; - zebra::Processor proc = zebra::Processor(true, video_dev); + zbar::Processor proc = zbar::Processor(true, video_dev); proc.set_visible(); proc.set_active(); try { proc.user_wait(); } - catch(zebra::ClosedError) { } + catch(zbar::ClosedError) { } return(0); } diff --git a/test/test_decode.c b/test/test_decode.c index d240654..4fd743f 100644 --- a/test/test_decode.c +++ b/test/test_decode.c @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include @@ -27,19 +27,19 @@ #include #include -#include +#include -zebra_decoder_t *decoder; +zbar_decoder_t *decoder; -static void symbol_handler (zebra_decoder_t *decoder) +static void symbol_handler (zbar_decoder_t *decoder) { - zebra_symbol_type_t sym = zebra_decoder_get_type(decoder); - if(sym <= ZEBRA_PARTIAL) + zbar_symbol_type_t sym = zbar_decoder_get_type(decoder); + if(sym <= ZBAR_PARTIAL) return; printf("%s%s:%s\n", - zebra_get_symbol_name(sym), - zebra_get_addon_name(sym), - zebra_decoder_get_data(decoder)); + zbar_get_symbol_name(sym), + zbar_get_addon_name(sym), + zbar_decoder_get_data(decoder)); /* FIXME add check! */ } @@ -48,7 +48,7 @@ static void encode_junk (int n) printf("encode random junk...\n"); int i; for(i = 0; i < n; i++) - zebra_decode_width(decoder, 10. * (rand() / (RAND_MAX + 1.))); + zbar_decode_width(decoder, 10. * (rand() / (RAND_MAX + 1.))); } #define FWD 1 @@ -65,7 +65,7 @@ static void encode (uint64_t units, while(units) { unsigned char w = (fwd) ? units & 0xf : units >> 0x3c; - zebra_decode_width(decoder, w); + zbar_decode_width(decoder, w); if(fwd) units >>= 4; else @@ -451,9 +451,9 @@ int main (int argc, char **argv) * - simulate dark "swelling" and light "blooming" * - inject parity errors */ - decoder = zebra_decoder_create(); - zebra_decoder_set_handler(decoder, symbol_handler); - zebra_decoder_set_config(decoder, 0, ZEBRA_CFG_MIN_LEN, 0); + decoder = zbar_decoder_create(); + zbar_decoder_set_handler(decoder, symbol_handler); + zbar_decoder_set_config(decoder, 0, ZBAR_CFG_MIN_LEN, 0); encode_junk(rnd_size + 1); @@ -501,6 +501,6 @@ int main (int argc, char **argv) encode_junk(rnd_size); - zebra_decoder_destroy(decoder); + zbar_decoder_destroy(decoder); return(0); } diff --git a/test/test_gtk.c b/test/test_gtk.c index c632d55..eef9121 100644 --- a/test/test_gtk.c +++ b/test/test_gtk.c @@ -1,28 +1,28 @@ /*------------------------------------------------------------------------ - * Copyright 2008 (c) Jeff Brown + * Copyright 2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include -#include +#include static GtkWidget *window = NULL; static GtkWidget *status_image = NULL; @@ -37,15 +37,15 @@ int scan_video(void *add_device, * puts the decoded result in the textbox */ static void decoded (GtkWidget *widget, - zebra_symbol_type_t symbol, + zbar_symbol_type_t symbol, const char *result, gpointer data) { GtkTextBuffer *resultbuf = gtk_text_view_get_buffer(results); GtkTextIter end; gtk_text_buffer_get_end_iter(resultbuf, &end); - gtk_text_buffer_insert(resultbuf, &end, zebra_get_symbol_name(symbol), -1); - gtk_text_buffer_insert(resultbuf, &end, zebra_get_addon_name(symbol), -1); + gtk_text_buffer_insert(resultbuf, &end, zbar_get_symbol_name(symbol), -1); + gtk_text_buffer_insert(resultbuf, &end, zbar_get_addon_name(symbol), -1); gtk_text_buffer_insert(resultbuf, &end, ":", -1); gtk_text_buffer_insert(resultbuf, &end, result, -1); gtk_text_buffer_insert(resultbuf, &end, "\n", -1); @@ -59,9 +59,9 @@ static void video_enabled (GObject *object, GParamSpec *param, gpointer data) { - ZebraGtk *zebra = ZEBRA_GTK(object); - gboolean enabled = zebra_gtk_get_video_enabled(zebra); - gboolean opened = zebra_gtk_get_video_opened(zebra); + ZBarGtk *zbar = ZBAR_GTK(object); + gboolean enabled = zbar_gtk_get_video_enabled(zbar); + gboolean opened = zbar_gtk_get_video_opened(zbar); GtkToggleButton *button = GTK_TOGGLE_BUTTON(data); gboolean active = gtk_toggle_button_get_active(button); @@ -73,9 +73,9 @@ static void video_opened (GObject *object, GParamSpec *param, gpointer data) { - ZebraGtk *zebra = ZEBRA_GTK(object); - gboolean opened = zebra_gtk_get_video_opened(zebra); - gboolean enabled = zebra_gtk_get_video_enabled(zebra); + ZBarGtk *zbar = ZBAR_GTK(object); + gboolean opened = zbar_gtk_get_video_opened(zbar); + gboolean enabled = zbar_gtk_get_video_enabled(zbar); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data), opened && enabled); gtk_widget_set_sensitive(GTK_WIDGET(data), opened); @@ -88,7 +88,7 @@ static void video_changed (GtkWidget *widget, { const char *video_device = gtk_combo_box_get_active_text(GTK_COMBO_BOX(widget)); - zebra_gtk_set_video_device(ZEBRA_GTK(data), + zbar_gtk_set_video_device(ZBAR_GTK(data), ((video_device && video_device[0] != '<') ? video_device : NULL)); @@ -97,12 +97,12 @@ static void video_changed (GtkWidget *widget, static void status_button_toggled (GtkToggleButton *button, gpointer data) { - ZebraGtk *zebra = ZEBRA_GTK(data); - gboolean opened = zebra_gtk_get_video_opened(zebra); - gboolean enabled = zebra_gtk_get_video_enabled(zebra); + ZBarGtk *zbar = ZBAR_GTK(data); + gboolean opened = zbar_gtk_get_video_opened(zbar); + gboolean enabled = zbar_gtk_get_video_enabled(zbar); gboolean active = gtk_toggle_button_get_active(button); if(opened && (active != enabled)) - zebra_gtk_set_video_enabled(ZEBRA_GTK(data), active); + zbar_gtk_set_video_enabled(ZBAR_GTK(data), active); gtk_image_set_from_stock(GTK_IMAGE(status_image), (opened && active) ? GTK_STOCK_YES : GTK_STOCK_NO, GTK_ICON_SIZE_BUTTON); @@ -128,7 +128,7 @@ static void open_button_clicked (GtkButton *button, gchar *file = gtk_file_chooser_get_filename(chooser); GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(file, NULL); if(pixbuf) - zebra_gtk_scan_image(ZEBRA_GTK(data), pixbuf); + zbar_gtk_scan_image(ZBAR_GTK(data), pixbuf); else fprintf(stderr, "ERROR: unable to open image file: %s\n", file); @@ -141,7 +141,7 @@ static void open_button_clicked (GtkButton *button, /* build a simple gui w/: * - a combo box to select the desired video device - * - the zebra widget to display video + * - the zbar widget to display video * - a non-editable text box to display any results */ int main (int argc, char *argv[]) @@ -163,16 +163,16 @@ int main (int argc, char *argv[]) g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); - GtkWidget *zebra = zebra_gtk_new(); + GtkWidget *zbar = zbar_gtk_new(); - g_signal_connect(G_OBJECT(zebra), "decoded", + g_signal_connect(G_OBJECT(zbar), "decoded", G_CALLBACK(decoded), NULL); /* video device list combo box */ GtkWidget *video_list = gtk_combo_box_new_text(); g_signal_connect(G_OBJECT(video_list), "changed", - G_CALLBACK(video_changed), zebra); + G_CALLBACK(video_changed), zbar); /* enable/disable status button */ GtkWidget *status_button = gtk_toggle_button_new(); @@ -184,17 +184,17 @@ int main (int argc, char *argv[]) /* bind status button state and video state */ g_signal_connect(G_OBJECT(status_button), "toggled", - G_CALLBACK(status_button_toggled), zebra); - g_signal_connect(G_OBJECT(zebra), "notify::video-enabled", + G_CALLBACK(status_button_toggled), zbar); + g_signal_connect(G_OBJECT(zbar), "notify::video-enabled", G_CALLBACK(video_enabled), status_button); - g_signal_connect(G_OBJECT(zebra), "notify::video-opened", + g_signal_connect(G_OBJECT(zbar), "notify::video-opened", G_CALLBACK(video_opened), status_button); /* open image file button */ GtkWidget *open_button = gtk_button_new_from_stock(GTK_STOCK_OPEN); g_signal_connect(G_OBJECT(open_button), "clicked", - G_CALLBACK(open_button_clicked), zebra); + G_CALLBACK(open_button_clicked), zbar); gtk_combo_box_append_text(GTK_COMBO_BOX(video_list), ""); int active = scan_video(gtk_combo_box_append_text, video_list, video_arg); @@ -215,18 +215,18 @@ int main (int argc, char *argv[]) gtk_text_view_set_cursor_visible(results, FALSE); gtk_text_view_set_left_margin(results, 4); - /* vbox for hbox, zebra test widget and result text box */ + /* vbox for hbox, zbar test widget and result text box */ GtkWidget *vbox = gtk_vbox_new(FALSE, 8); gtk_container_add(GTK_CONTAINER(window), vbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(vbox), zebra, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(vbox), zbar, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(results), FALSE, FALSE, 0); GdkGeometry hints; hints.min_width = 320; hints.min_height = 240; - gtk_window_set_geometry_hints(GTK_WINDOW(window), zebra, &hints, + gtk_window_set_geometry_hints(GTK_WINDOW(window), zbar, &hints, GDK_HINT_MIN_SIZE); gtk_widget_show_all(window); diff --git a/test/test_images.c b/test/test_images.c index 5ecae6c..eb20536 100644 --- a/test/test_images.c +++ b/test/test_images.c @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include "test_images.h" typedef enum format_type_e { @@ -108,9 +108,9 @@ int test_image_check_cleanup () return(allocated_images); } -static void test_cleanup_handler (zebra_image_t *img) +static void test_cleanup_handler (zbar_image_t *img) { - void *data = (void*)zebra_image_get_data(img); + void *data = (void*)zbar_image_get_data(img); fprintf(stderr, "cleanup image data @%p\n", data); free(data); allocated_images--; @@ -336,15 +336,15 @@ static inline uint8_t *fill_bars_rgb (uint8_t *p, return(((uint8_t*)q) + headlen); } -int test_image_bars (zebra_image_t *img) +int test_image_bars (zbar_image_t *img) { allocated_images++; - unsigned w = zebra_image_get_width(img); - unsigned h = zebra_image_get_height(img); + unsigned w = zbar_image_get_width(img); + unsigned h = zbar_image_get_height(img); const format_def_t *fmt; for(fmt = formats; fmt->format; fmt++) - if(fmt->format == zebra_image_get_format(img)) + if(fmt->format == zbar_image_get_format(img)) break; if(!fmt->format) return(-1); @@ -352,7 +352,7 @@ int test_image_bars (zebra_image_t *img) unsigned long planelen = w * h; unsigned long datalen = planelen * fmt->bpp / 8; uint8_t *data = malloc(datalen); - zebra_image_set_data(img, data, datalen, test_cleanup_handler); + zbar_image_set_data(img, data, datalen, test_cleanup_handler); fprintf(stderr, "create %.4s(%08" PRIx32 ") image data %lx bytes @%p\n", (char*)&fmt->format, fmt->format, datalen, data); diff --git a/test/test_images.h b/test/test_images.h index 3a4c05a..50dfef9 100644 --- a/test/test_images.h +++ b/test/test_images.h @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #ifndef _TEST_IMAGES_H_ #define _TEST_IMAGES_H_ @@ -29,6 +29,6 @@ ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24)) int test_image_check_cleanup(); -int test_image_bars(zebra_image_t*); +int test_image_bars(zbar_image_t*); #endif diff --git a/test/test_jpeg.c b/test/test_jpeg.c index b11c99c..1194737 100644 --- a/test/test_jpeg.c +++ b/test/test_jpeg.c @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ * Copyright 2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include @@ -29,7 +29,7 @@ #include #include -#include +#include #include "test_images.h" @@ -108,32 +108,32 @@ unsigned char rgb[8*8*3] = { int main (int argc, char **argv) { - zebra_set_verbosity(32); + zbar_set_verbosity(32); - zebra_processor_t *proc = zebra_processor_create(0); + zbar_processor_t *proc = zbar_processor_create(0); assert(proc); - if(zebra_processor_init(proc, NULL, 1)) + if(zbar_processor_init(proc, NULL, 1)) return(2); - zebra_image_t *img = zebra_image_create(); - zebra_image_set_size(img, 8, 8); - zebra_image_set_format(img, fourcc('J','P','E','G')); - zebra_image_set_data(img, jpeg, sizeof(jpeg), NULL); + zbar_image_t *img = zbar_image_create(); + zbar_image_set_size(img, 8, 8); + zbar_image_set_format(img, fourcc('J','P','E','G')); + zbar_image_set_data(img, jpeg, sizeof(jpeg), NULL); - zebra_image_t *test = zebra_image_convert(img, fourcc('Y','8','0','0')); + zbar_image_t *test = zbar_image_convert(img, fourcc('Y','8','0','0')); if(!test) return(2); printf("converted: %d x %d (%lx) %08lx\n", - zebra_image_get_width(test), - zebra_image_get_height(test), - zebra_image_get_data_length(test), - zebra_image_get_format(test)); + zbar_image_get_width(test), + zbar_image_get_height(test), + zbar_image_get_data_length(test), + zbar_image_get_format(test)); - if(zebra_process_image(proc, test) < 0) + if(zbar_process_image(proc, test) < 0) return(3); - if(zebra_processor_set_visible(proc, 1)) + if(zbar_processor_set_visible(proc, 1)) return(4); - zebra_processor_user_wait(proc, -1); + zbar_processor_user_wait(proc, -1); return(0); } diff --git a/test/test_perl.pl b/test/test_perl.pl index 7616fbf..cc28ffb 100755 --- a/test/test_perl.pl +++ b/test/test_perl.pl @@ -1,36 +1,36 @@ #!/usr/bin/env perl #------------------------------------------------------------------------ -# Copyright 2008 (c) Jeff Brown +# Copyright 2008-2009 (c) Jeff Brown # -# This file is part of the Zebra Barcode Library. +# This file is part of the ZBar Bar Code Reader. # -# The Zebra Barcode Library is free software; you can redistribute it +# 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 Zebra Barcode Library is distributed in the hope that it will be +# 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 Zebra Barcode Library; if not, write to the Free +# 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/zebra +# http://sourceforge.net/projects/zbar #------------------------------------------------------------------------ use 5.006; use warnings; use strict; -use Zebra; +use Barcode::ZBar; -Zebra::set_verbosity(15); +Barcode::ZBar::set_verbosity(15); -my $proc = Zebra::Processor->new(1); +my $proc = Barcode::ZBar::Processor->new(1); $proc->init($ARGV[0] || '/dev/video0'); diff --git a/test/test_proc.c b/test/test_proc.c index 3154da8..225c19c 100644 --- a/test/test_proc.c +++ b/test/test_proc.c @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include @@ -33,10 +33,10 @@ #include #include -#include +#include #include "test_images.h" -zebra_processor_t *proc = NULL; +zbar_processor_t *proc = NULL; int input_wait (int timeout) { @@ -46,12 +46,12 @@ int input_wait (int timeout) else printf("waiting indefinitely for input..."); fflush(stdout); - int rc = zebra_processor_user_wait(proc, timeout); + int rc = zbar_processor_user_wait(proc, timeout); if(rc > 0) printf("got input\n"); else if(!rc || (rc < 0 && - zebra_processor_get_error_code(proc) == ZEBRA_ERR_CLOSED)) { + zbar_processor_get_error_code(proc) == ZBAR_ERR_CLOSED)) { printf("timed out\n"); return(0); } @@ -60,7 +60,7 @@ int input_wait (int timeout) int main (int argc, char **argv) { - zebra_set_verbosity(31); + zbar_set_verbosity(31); char *video_dev = NULL; int i, use_threads = 0, use_window = 0; for(i = 1; i < argc; i++) { @@ -76,36 +76,36 @@ int main (int argc, char **argv) video_dev = argv[i]; } - proc = zebra_processor_create(use_threads); + proc = zbar_processor_create(use_threads); assert(proc); printf("created processor (%sthreaded)\n", (!use_threads) ? "un" : ""); - if(zebra_processor_init(proc, NULL, 0)) + if(zbar_processor_init(proc, NULL, 0)) return(2); printf("initialized (video=disabled, window=disabled)\n"); - zebra_image_t *img = zebra_image_create(); - zebra_image_set_size(img, 640, 480); - zebra_image_set_format(img, fourcc('Y','V','1','2')); + zbar_image_t *img = zbar_image_create(); + zbar_image_set_size(img, 640, 480); + zbar_image_set_format(img, fourcc('Y','V','1','2')); test_image_bars(img); - if(zebra_process_image(proc, img) < 0) + if(zbar_process_image(proc, img) < 0) return(3); printf("processed test image\n"); - if(zebra_processor_init(proc, video_dev, use_window)) + if(zbar_processor_init(proc, video_dev, use_window)) return(2); printf("reinitialized (video=%s, window=%s)\n", (video_dev) ? video_dev : "disabled", (use_window) ? "enabled" : "disabled"); - if(zebra_process_image(proc, img) < 0) + if(zbar_process_image(proc, img) < 0) return(3); printf("processed test image\n"); - zebra_image_destroy(img); + zbar_image_destroy(img); if(use_window) { - if(zebra_processor_set_visible(proc, 1)) + if(zbar_processor_set_visible(proc, 1)) return(4); printf("window visible\n"); } @@ -114,14 +114,14 @@ int main (int argc, char **argv) return(5); if(video_dev) { - if(zebra_processor_set_active(proc, 1)) + if(zbar_processor_set_active(proc, 1)) return(3); printf("video activated\n"); if(input_wait((use_window) ? -1 : 4000) < 0) return(5); - if(zebra_processor_set_active(proc, 0)) + if(zbar_processor_set_active(proc, 0)) return(3); printf("video deactivated\n"); @@ -131,14 +131,14 @@ int main (int argc, char **argv) /* FIXME test process_one() */ } - if(zebra_process_image(proc, NULL)) + if(zbar_process_image(proc, NULL)) return(3); printf("flushed image\n"); if(input_wait((use_window && !video_dev) ? -1 : 2500) < 0) return(5); - zebra_processor_destroy(proc); + zbar_processor_destroy(proc); proc = NULL; if(test_image_check_cleanup()) return(32); diff --git a/test/test_pygtk.py b/test/test_pygtk.py index 270a42b..902b8ff 100755 --- a/test/test_pygtk.py +++ b/test/test_pygtk.py @@ -1,32 +1,32 @@ #!/usr/bin/env python #------------------------------------------------------------------------ -# Copyright 2008 (c) Jeff Brown +# Copyright 2008-2009 (c) Jeff Brown # -# This file is part of the Zebra Barcode Library. +# This file is part of the ZBar Bar Code Reader. # -# The Zebra Barcode Library is free software; you can redistribute it +# 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 Zebra Barcode Library is distributed in the hope that it will be +# 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 Zebra Barcode Library; if not, write to the Free +# 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/zebra +# http://sourceforge.net/projects/zbar #------------------------------------------------------------------------ import sys, os, stat import pygtk, gtk -import zebrapygtk +import zbarpygtk -def decoded(zebra, data): - """callback invoked when a barcode is decoded by the zebra widget. +def decoded(zbar, data): + """callback invoked when a barcode is decoded by the zbar widget. displays the decoded data in the text box """ buf = results.props.buffer @@ -34,44 +34,44 @@ def decoded(zebra, data): buf.insert(end, data + "\n") results.scroll_to_iter(end, 0) -def video_enabled(zebra, param): - """callback invoked when the zebra widget enables or disables +def video_enabled(zbar, param): + """callback invoked when the zbar widget enables or disables video streaming. updates the status button state to reflect the current video state """ - enabled = zebra.get_video_enabled() + enabled = zbar.get_video_enabled() if status_button.get_active() != enabled: status_button.set_active(enabled) -def video_opened(zebra, param): - """callback invoked when the zebra widget opens or closes a video +def video_opened(zbar, param): + """callback invoked when the zbar widget opens or closes a video device. also called when a device is closed due to error. updates the status button state to reflect the current video state """ - opened = zebra.get_video_opened() + opened = zbar.get_video_opened() status_button.set_sensitive(opened) - set_status_label(opened, zebra.get_video_enabled()) + set_status_label(opened, zbar.get_video_enabled()) def video_changed(widget): """callback invoked when a new video device is selected from the - drop-down list. sets the new device for the zebra widget, + drop-down list. sets the new device for the zbar widget, which will eventually cause it to be opened and enabled """ dev = video_list.get_active_text() if dev[0] == '<': dev = '' - zebra.set_video_device(dev) + zbar.set_video_device(dev) def status_button_toggled(button): """callback invoked when the status button changes state - (interactively or programmatically). ensures the zebra widget + (interactively or programmatically). ensures the zbar widget video streaming state is consistent and updates the display of the button to represent the current state """ - opened = zebra.get_video_opened() + opened = zbar.get_video_opened() active = status_button.get_active() - if opened and (active != zebra.get_video_enabled()): - zebra.set_video_enabled(active) + if opened and (active != zbar.get_video_enabled()): + zbar.set_video_enabled(active) set_status_label(opened, active) if active: status_image.set_from_stock(gtk.STOCK_YES, gtk.ICON_SIZE_BUTTON) @@ -81,7 +81,7 @@ def status_button_toggled(button): def open_button_clicked(button): """callback invoked when the 'Open' button is clicked. pops up an 'Open File' dialog which the user may use to select an image file. - if the image is successfully opened, it is passed to the zebra + if the image is successfully opened, it is passed to the zbar widget which displays it and scans it for barcodes. results are returned using the same hook used to report video results """ @@ -97,7 +97,7 @@ def open_button_clicked(button): open_file = dialog.get_filename() pixbuf = gtk.gdk.pixbuf_new_from_file(open_file) if pixbuf: - zebra.scan_image(pixbuf) + zbar.scan_image(pixbuf) finally: dialog.destroy() @@ -116,7 +116,7 @@ def set_status_label(opened, enabled): if len(sys.argv) > 1: video_device = sys.argv[1] -# threads *must* be properly initialized to use zebrapygtk +# threads *must* be properly initialized to use zbarpygtk gtk.gdk.threads_init() gtk.gdk.threads_enter() @@ -125,8 +125,8 @@ def set_status_label(opened, enabled): window.set_border_width(8) window.connect("destroy", gtk.main_quit) -zebra = zebrapygtk.Gtk() -zebra.connect("decoded-text", decoded) +zbar = zbarpygtk.Gtk() +zbar.connect("decoded-text", decoded) # video device list combo box video_list = gtk.combo_box_new_text() @@ -140,8 +140,8 @@ def set_status_label(opened, enabled): # bind status button state and video state status_button.connect("toggled", status_button_toggled) -zebra.connect("notify::video-enabled", video_enabled) -zebra.connect("notify::video-opened", video_opened) +zbar.connect("notify::video-enabled", video_enabled) +zbar.connect("notify::video-opened", video_opened) # open image file button open_button = gtk.Button(stock=gtk.STOCK_OPEN) @@ -182,11 +182,11 @@ def set_status_label(opened, enabled): # combine inputs, scanner, and results vertically vbox = gtk.VBox(spacing=8) vbox.pack_start(hbox, expand=False) -vbox.pack_start(zebra) +vbox.pack_start(zbar) vbox.pack_start(results, expand=False) window.add(vbox) -window.set_geometry_hints(zebra, min_width=320, min_height=240) +window.set_geometry_hints(zbar, min_width=320, min_height=240) window.show_all() gtk.main() diff --git a/test/test_qt.cpp b/test/test_qt.cpp index 628ebc8..96d2f95 100644 --- a/test/test_qt.cpp +++ b/test/test_qt.cpp @@ -1,24 +1,24 @@ //------------------------------------------------------------------------ -// Copyright 2008 (c) Jeff Brown +// Copyright 2008-2009 (c) Jeff Brown // -// This file is part of the Zebra Barcode Library. +// This file is part of the ZBar Bar Code Reader. // -// The Zebra Barcode Library is free software; you can redistribute it +// 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 Zebra Barcode Library is distributed in the hope that it will be +// 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 Zebra Barcode Library; if not, write to the Free +// 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/zebra +// http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ #include @@ -29,7 +29,7 @@ #include #include #include -#include +#include #define TEST_IMAGE_FORMATS \ "Image Files (*.png *.jpg *.jpeg *.bmp *.gif *.ppm *.pgm *.pbm *.tiff *.xpm *.xbm)" @@ -40,7 +40,7 @@ int scan_video(void *add_device, const char *default_device); } -class TestQZebra : public QWidget +class TestQZBar : public QWidget { Q_OBJECT @@ -52,7 +52,7 @@ class TestQZebra : public QWidget } public: - TestQZebra (const char *default_device) + TestQZBar (const char *default_device) { // drop-down list of video devices QComboBox *videoList = new QComboBox; @@ -84,8 +84,8 @@ class TestQZebra : public QWidget hbox->addWidget(openButton, 1); // video barcode scanner - zebra = new zebra::QZebra; - zebra->setAcceptDrops(true); + zbar = new zbar::QZBar; + zbar->setAcceptDrops(true); // text box for results QTextEdit *results = new QTextEdit; @@ -93,7 +93,7 @@ class TestQZebra : public QWidget QVBoxLayout *vbox = new QVBoxLayout; vbox->addLayout(hbox); - vbox->addWidget(zebra); + vbox->addWidget(zbar); vbox->addWidget(results); setLayout(vbox); @@ -103,25 +103,25 @@ class TestQZebra : public QWidget // directly connect combo box change signal to scanner video open connect(videoList, SIGNAL(currentIndexChanged(const QString&)), - zebra, SLOT(setVideoDevice(const QString&))); + zbar, SLOT(setVideoDevice(const QString&))); // directly connect status button state to video enabled state connect(statusButton, SIGNAL(toggled(bool)), - zebra, SLOT(setVideoEnabled(bool))); + zbar, SLOT(setVideoEnabled(bool))); // also update status button state when video is opened/closed - connect(zebra, SIGNAL(videoOpened(bool)), + connect(zbar, SIGNAL(videoOpened(bool)), statusButton, SLOT(setEnabled(bool))); // enable/disable status button when video is opened/closed - connect(zebra, SIGNAL(videoOpened(bool)), + connect(zbar, SIGNAL(videoOpened(bool)), statusButton, SLOT(setChecked(bool))); // prompt for image file to scan when openButton is clicked connect(openButton, SIGNAL(clicked()), SLOT(openImage())); // directly connect video scanner decode result to display in text box - connect(zebra, SIGNAL(decodedText(const QString&)), + connect(zbar, SIGNAL(decodedText(const QString&)), results, SLOT(append(const QString&))); if(active >= 0) @@ -134,12 +134,12 @@ public Q_SLOTS: file = QFileDialog::getOpenFileName(this, "Open Image", file, TEST_IMAGE_FORMATS); if(!file.isEmpty()) - zebra->scanImage(QImage(file)); + zbar->scanImage(QImage(file)); } private: QString file; - zebra::QZebra *zebra; + zbar::QZBar *zbar; }; #include "moc_test_qt.h" @@ -152,7 +152,7 @@ int main (int argc, char *argv[]) if(argc > 1) dev = argv[1]; - TestQZebra window(dev); + TestQZBar window(dev); window.show(); return(app.exec()); } diff --git a/test/test_video.c b/test/test_video.c index 5e9eb8a..fa80b6b 100644 --- a/test/test_video.c +++ b/test/test_video.c @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include @@ -33,15 +33,15 @@ #include #include -#include +#include #include "processor.h" /* reuse some processor guts */ #include "test_images.h" -zebra_processor_t proc; +zbar_processor_t proc; int main (int argc, char *argv[]) { - zebra_set_verbosity(10); + zbar_set_verbosity(10); const char *dev = "/dev/video0"; if(argc > 1) { @@ -57,15 +57,15 @@ int main (int argc, char *argv[]) } memset(&proc, 0, sizeof(proc)); - proc.video = zebra_video_create(); - proc.window = zebra_window_create(); + proc.video = zbar_video_create(); + proc.window = zbar_window_create(); if(!proc.video || !proc.window) { fprintf(stderr, "unable to allocate memory?!\n"); return(1); } - if(zebra_video_open(proc.video, dev)) { - zebra_video_error_spew(proc.video, 0); + if(zbar_video_open(proc.video, dev)) { + zbar_video_error_spew(proc.video, 0); fprintf(stderr, "ERROR: unable to access your video device\n" "this program requires video capture support using" @@ -81,65 +81,65 @@ int main (int argc, char *argv[]) return(1); } printf("opened video device: %s (fd=%d)\n", - dev, zebra_video_get_fd(proc.video)); + dev, zbar_video_get_fd(proc.video)); - if(_zebra_window_open(&proc, "zebra video test", 640, 480) || - zebra_window_attach(proc.window, proc.display, proc.xwin) || - _zebra_window_set_visible(&proc, 1)) + if(_zbar_window_open(&proc, "zbar video test", 640, 480) || + zbar_window_attach(proc.window, proc.display, proc.xwin) || + _zbar_window_set_visible(&proc, 1)) fprintf(stderr, "WARNING: failed to open test window\n"); - else if(zebra_negotiate_format(proc.video, proc.window)) + else if(zbar_negotiate_format(proc.video, proc.window)) fprintf(stderr, "WARNING: failed to negotiate compatible format\n"); - zebra_image_t *img = zebra_image_create(); - zebra_image_set_size(img, 640, 480); - zebra_image_set_format(img, fourcc('Y','V','1','2')); + zbar_image_t *img = zbar_image_create(); + zbar_image_set_size(img, 640, 480); + zbar_image_set_format(img, fourcc('Y','V','1','2')); test_image_bars(img); - if(proc.display && zebra_window_draw(proc.window, img)) { + if(proc.display && zbar_window_draw(proc.window, img)) { fprintf(stderr, "ERROR: drawing image\n"); - return(zebra_window_error_spew(proc.window, 0)); + return(zbar_window_error_spew(proc.window, 0)); } - if(zebra_video_enable(proc.video, 1)) { + if(zbar_video_enable(proc.video, 1)) { fprintf(stderr, "ERROR: starting video stream\n"); - return(zebra_video_error_spew(proc.video, 0)); + return(zbar_video_error_spew(proc.video, 0)); } - zebra_image_t *image = zebra_video_next_image(proc.video); + zbar_image_t *image = zbar_video_next_image(proc.video); if(!image) { fprintf(stderr, "ERROR: unable to capture image\n"); - return(zebra_video_error_spew(proc.video, 0)); + return(zbar_video_error_spew(proc.video, 0)); } - uint32_t format = zebra_image_get_format(image); - unsigned width = zebra_image_get_width(image); - unsigned height = zebra_image_get_height(image); - const uint8_t *data = zebra_image_get_data(image); + uint32_t format = zbar_image_get_format(image); + unsigned width = zbar_image_get_width(image); + unsigned height = zbar_image_get_height(image); + const uint8_t *data = zbar_image_get_data(image); printf("captured image: %d x %d %.4s @%p\n", width, height, (char*)&format, data); - if(proc.display && zebra_window_draw(proc.window, image)) { + if(proc.display && zbar_window_draw(proc.window, image)) { fprintf(stderr, "ERROR: drawing image\n"); - return(zebra_window_error_spew(proc.window, 0)); + return(zbar_window_error_spew(proc.window, 0)); } - zebra_image_destroy(image); + zbar_image_destroy(image); printf("\nstreaming...click to continue\n"); struct timespec start, end; clock_gettime(CLOCK_REALTIME, &start); int n = 0; while(1) { - if(proc.display && _zebra_window_handle_events(&proc, 0)) + if(proc.display && _zbar_window_handle_events(&proc, 0)) break; - zebra_image_t *image = zebra_video_next_image(proc.video); + zbar_image_t *image = zbar_video_next_image(proc.video); if(!image) { fprintf(stderr, "ERROR: unable to capture image\n"); - return(zebra_video_error_spew(proc.video, 0)); + return(zbar_video_error_spew(proc.video, 0)); } - if(proc.display && zebra_window_draw(proc.window, image)) { + if(proc.display && zbar_window_draw(proc.window, image)) { fprintf(stderr, "ERROR: drawing image\n"); - return(zebra_window_error_spew(proc.window, 0)); + return(zbar_window_error_spew(proc.window, 0)); } - zebra_image_destroy(image); + zbar_image_destroy(image); n++; } clock_gettime(CLOCK_REALTIME, &end); @@ -148,24 +148,24 @@ int main (int argc, char *argv[]) double fps = n / ms; printf("\nprocessed %d images in %gs @%gfps\n", n, ms, fps); - if(zebra_video_enable(proc.video, 0)) { + if(zbar_video_enable(proc.video, 0)) { fprintf(stderr, "ERROR: while stopping video stream\n"); - return(zebra_video_error_spew(proc.video, 0)); + return(zbar_video_error_spew(proc.video, 0)); } printf("\nvideo support verified\n\n"); - if(proc.display && zebra_window_draw(proc.window, img)) { + if(proc.display && zbar_window_draw(proc.window, img)) { fprintf(stderr, "error drawing image\n"); - return(zebra_window_error_spew(proc.window, 0)); + return(zbar_window_error_spew(proc.window, 0)); } - zebra_image_destroy(img); + zbar_image_destroy(img); printf("click to end...\n"); if(proc.display) - _zebra_window_handle_events(&proc, 1); + _zbar_window_handle_events(&proc, 1); - zebra_window_destroy(proc.window); - zebra_video_destroy(proc.video); + zbar_window_destroy(proc.window); + zbar_video_destroy(proc.video); if(test_image_check_cleanup()) return(32); diff --git a/test/test_window.c b/test/test_window.c index 4dbd386..9beebe1 100644 --- a/test/test_window.c +++ b/test/test_window.c @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include @@ -31,26 +31,26 @@ #include #include -#include +#include #include "processor.h" #include "test_images.h" -extern int _zebra_draw_logo(zebra_image_t *img); +extern int _zbar_draw_logo(zbar_image_t *img); -zebra_processor_t proc; +zbar_processor_t proc; static void input_wait () { fprintf(stderr, "waiting for input...\n"); - _zebra_window_handle_events(&proc, 1); + _zbar_window_handle_events(&proc, 1); } int main (int argc, char *argv[]) { - zebra_set_verbosity(32); + zbar_set_verbosity(32); - err_init(&proc.err, ZEBRA_MOD_PROCESSOR); - proc.window = zebra_window_create(); + err_init(&proc.err, ZBAR_MOD_PROCESSOR); + proc.window = zbar_window_create(); if(!proc.window) { fprintf(stderr, "unable to allocate memory?!\n"); return(1); @@ -59,17 +59,17 @@ int main (int argc, char *argv[]) int width = 640 * .25; int height = 480 * .25; - if(_zebra_window_open(&proc, "zebra window test", width, height) || - zebra_window_attach(proc.window, proc.display, proc.xwin) || - _zebra_window_set_visible(&proc, 1)) { + if(_zbar_window_open(&proc, "zbar window test", width, height) || + zbar_window_attach(proc.window, proc.display, proc.xwin) || + _zbar_window_set_visible(&proc, 1)) { fprintf(stderr, "failed to open test window\n"); return(1); } input_wait(); - zebra_image_t *img = zebra_image_create(); - zebra_image_set_size(img, width, height); - /*zebra_image_set_format(img, fourcc('Y','8','0','0'));*/ + zbar_image_t *img = zbar_image_create(); + zbar_image_set_size(img, width, height); + /*zbar_image_set_format(img, fourcc('Y','8','0','0'));*/ /*fourcc('I','4','2','0')*/ /*fourcc('Y','V','1','2')*/ /*fourcc('U','Y','V','Y')*/ @@ -77,14 +77,14 @@ int main (int argc, char *argv[]) /*fourcc('R','G','B','3')*/ /*fourcc('Y','8','0','0')*/ /*test_image_bars(img);*/ - _zebra_draw_logo(img); + _zbar_draw_logo(img); - if(zebra_window_draw(proc.window, img) || - zebra_window_redraw(proc.window)) { + if(zbar_window_draw(proc.window, img) || + zbar_window_redraw(proc.window)) { fprintf(stderr, "error drawing image\n"); return(1); } - zebra_image_destroy(img); + zbar_image_destroy(img); img = NULL; input_wait(); @@ -92,7 +92,7 @@ int main (int argc, char *argv[]) /* FIXME display cmd arg images? or formats? */ fprintf(stderr, "cleaning up\n"); - zebra_window_destroy(proc.window); + zbar_window_destroy(proc.window); /* FIXME destructor check? */ if(test_image_check_cleanup()) diff --git a/zebra-gtk.pc.in b/zbar-gtk.pc.in similarity index 60% rename from zebra-gtk.pc.in rename to zbar-gtk.pc.in index b68b7dd..fc712a2 100644 --- a/zebra-gtk.pc.in +++ b/zbar-gtk.pc.in @@ -3,10 +3,10 @@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ -Name: zebra-gtk +Name: zbar-gtk Description: bar code scanning and decoding GTK widget -URL: http://zebra.sourceforge.net +URL: http://zbar.sourceforge.net Version: @VERSION@ -Requires: zebra, gtk+-2.0, gthread-2.0 -Libs: -L${libdir} -lzebragtk +Requires: zbar, gtk+-2.0, gthread-2.0 +Libs: -L${libdir} -lzbargtk Cflags: -I${includedir} diff --git a/zebra-qt.pc.in b/zbar-qt.pc.in similarity index 60% rename from zebra-qt.pc.in rename to zbar-qt.pc.in index 1bcd5d7..5eadf47 100644 --- a/zebra-qt.pc.in +++ b/zbar-qt.pc.in @@ -3,10 +3,10 @@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ -Name: zebra-qt +Name: zbar-qt Description: bar code scanning and decoding Qt4 widget -URL: http://zebra.sourceforge.net +URL: http://zbar.sourceforge.net Version: @VERSION@ -Requires: zebra, QtCore >= 4, QtGui >= 4 -Libs: -L${libdir} -lzebraqt +Requires: zbar, QtCore >= 4, QtGui >= 4 +Libs: -L${libdir} -lzbarqt Cflags: -I${includedir} diff --git a/zebra.pc.in b/zbar.pc.in similarity index 70% rename from zebra.pc.in rename to zbar.pc.in index 45449be..953a5ca 100644 --- a/zebra.pc.in +++ b/zbar.pc.in @@ -3,9 +3,9 @@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ -Name: zebra +Name: zbar Description: bar code scanning and decoding -URL: http://zebra.sourceforge.net +URL: http://zbar.sourceforge.net Version: @VERSION@ -Libs: -L${libdir} -lzebra +Libs: -L${libdir} -lzbar Cflags: -I${includedir} diff --git a/zebra.spec.in b/zbar.spec.in similarity index 51% rename from zebra.spec.in rename to zbar.spec.in index d50c59f..89931cd 100644 --- a/zebra.spec.in +++ b/zbar.spec.in @@ -1,23 +1,23 @@ -Name: zebra -Summary: bar code scanning and decoding library +Name: zbar +Summary: bar code scanning and decoding Version: @VERSION@ Release: 1 License: LGPL Group: Development/Libraries -URL: http://zebra.sourceforge.net +URL: http://zbar.sourceforge.net Packager: Vit Hrachovy -Source: zebra-%{version}.tar.gz +Source: zbar-%{version}.tar.gz Requires: ImageMagick-c++ BuildPreReq: pkgconfig, libX11-devel, python-devel, gtk2-devel, pygtk2-devel, qt-devel >= 4, ImageMagick-c++-devel Prefix: %{_prefix} BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root %description -The Zebra Barcode Reader library is a library for scanning and -decoding bar codes from various sources such as video streams, image -files or raw intensity sensors. It supports EAN, UPC, Code 128, Code -39 and Interleaved 2 of 5. The flexible, layered architecture features -a fast, streaming interface with a minimal memory footprint. +The ZBar Barcode Reader is a library for scanning and decoding bar +codes from various sources such as video streams, image files or raw +intensity sensors. It supports EAN, UPC, Code 128, Code 39 and +Interleaved 2 of 5. The flexible, layered architecture features a +fast, streaming interface with a minimal memory footprint. %package devel Group: Development/Libraries @@ -25,11 +25,11 @@ Summary: bar code library extra development files Requires: %{name} = %{version} %description devel -The Zebra Barcode Reader library is a library for scanning and -decoding bar codes from various sources such as video streams, image -files or raw intensity sensors. It supports EAN, UPC, Code 128, Code -39 and Interleaved 2 of 5. The flexible, layered architecture features -a fast, streaming interface with a minimal memory footprint. +The ZBar Barcode Reader is a library for scanning and decoding bar +codes from various sources such as video streams, image files or raw +intensity sensors. It supports EAN, UPC, Code 128, Code 39 and +Interleaved 2 of 5. The flexible, layered architecture features a +fast, streaming interface with a minimal memory footprint. This package contains header files and additional libraries used for developing applications that read bar codes with this library. @@ -40,11 +40,11 @@ Summary: bar code reader GTK widget Requires: %{name} = %{version}, gtk2 %description gtk -The Zebra Barcode Reader library is a library for scanning and -decoding bar codes from various sources such as video streams, image -files or raw intensity sensors. It supports EAN, UPC, Code 128, Code -39 and Interleaved 2 of 5. The flexible, layered architecture features -a fast, streaming interface with a minimal memory footprint. +The ZBar Barcode Reader is a library for scanning and decoding bar +codes from various sources such as video streams, image files or raw +intensity sensors. It supports EAN, UPC, Code 128, Code 39 and +Interleaved 2 of 5. The flexible, layered architecture features a +fast, streaming interface with a minimal memory footprint. This package contains a bar code scanning widget for use with GUI applications based on GTK+-2.0. @@ -55,11 +55,11 @@ Summary: bar code reader GTK widget extra development files Requires: %{name}-gtk = %{version}, %{name}-devel = %{version}, gtk2-devel %description gtk-devel -The Zebra Barcode Reader library is a library for scanning and -decoding bar codes from various sources such as video streams, image -files or raw intensity sensors. It supports EAN, UPC, Code 128, Code -39 and Interleaved 2 of 5. The flexible, layered architecture features -a fast, streaming interface with a minimal memory footprint. +The ZBar Barcode Reader is a library for scanning and decoding bar +codes from various sources such as video streams, image files or raw +intensity sensors. It supports EAN, UPC, Code 128, Code 39 and +Interleaved 2 of 5. The flexible, layered architecture features a +fast, streaming interface with a minimal memory footprint. This package contains header files and additional libraries used for developing GUI applications based on GTK+-2.0 that include a bar code @@ -71,11 +71,11 @@ Summary: bar code reader PyGTK widget Requires: %{name} = %{version}, pygtk2 %description pygtk -The Zebra Barcode Reader library is a library for scanning and -decoding bar codes from various sources such as video streams, image -files or raw intensity sensors. It supports EAN, UPC, Code 128, Code -39 and Interleaved 2 of 5. The flexible, layered architecture features -a fast, streaming interface with a minimal memory footprint. +The ZBar Barcode Reader is a library for scanning and decoding bar +codes from various sources such as video streams, image files or raw +intensity sensors. It supports EAN, UPC, Code 128, Code 39 and +Interleaved 2 of 5. The flexible, layered architecture features a +fast, streaming interface with a minimal memory footprint. This package contains a bar code scanning widget for use in GUI applications based on PyGTK. @@ -86,11 +86,11 @@ Summary: bar code reader Qt widget Requires: %{name} = %{version}, qt >= 4 %description qt -The Zebra Barcode Reader library is a library for scanning and -decoding bar codes from various sources such as video streams, image -files or raw intensity sensors. It supports EAN, UPC, Code 128, Code -39 and Interleaved 2 of 5. The flexible, layered architecture features -a fast, streaming interface with a minimal memory footprint. +The ZBar Barcode Reader is a library for scanning and decoding bar +codes from various sources such as video streams, image files or raw +intensity sensors. It supports EAN, UPC, Code 128, Code 39 and +Interleaved 2 of 5. The flexible, layered architecture features a +fast, streaming interface with a minimal memory footprint. This package contains a bar code scanning widget for use with GUI applications based on Qt4. @@ -101,18 +101,18 @@ Summary: bar code reader Qt widget extra development files Requires: %{name}-qt = %{version}, %{name}-devel = %{version}, qt-devel >= 4 %description qt-devel -The Zebra Barcode Reader library is a library for scanning and -decoding bar codes from various sources such as video streams, image -files or raw intensity sensors. It supports EAN, UPC, Code 128, Code -39 and Interleaved 2 of 5. The flexible, layered architecture features -a fast, streaming interface with a minimal memory footprint. +The ZBar Barcode Reader is a library for scanning and decoding bar +codes from various sources such as video streams, image files or raw +intensity sensors. It supports EAN, UPC, Code 128, Code 39 and +Interleaved 2 of 5. The flexible, layered architecture features a +fast, streaming interface with a minimal memory footprint. This package contains header files and additional libraries used for developing GUI applications based on Qt4 that include a bar code scanning widget. %prep -%setup -q -n zebra-%{version} +%setup -q -n zbar-%{version} %build ./configure --host=%{_host} --build=%{_build} \ @@ -137,9 +137,9 @@ ldconfig %files %defattr(-,root,root) -%{_bindir}/zebraimg -%{_bindir}/zebracam -%{_libdir}/libzebra.so.* +%{_bindir}/zbarimg +%{_bindir}/zbarcam +%{_libdir}/libzbar.so.* %{_datadir}/man/man1/* %doc %{_docdir}/%{name}-%{version}/COPYING.LIB %doc %{_docdir}/%{name}-%{version}/HACKING @@ -150,32 +150,32 @@ ldconfig %files devel %defattr(-,root,root) -%{_libdir}/libzebra.la -%{_libdir}/libzebra.a -%{_libdir}/libzebra.so -%{_libdir}/pkgconfig/zebra.pc -%{_includedir}/zebra.h -%{_includedir}/zebra/Exception.h -%{_includedir}/zebra/Symbol.h -%{_includedir}/zebra/Image.h -%{_includedir}/zebra/Scanner.h -%{_includedir}/zebra/Decoder.h -%{_includedir}/zebra/ImageScanner.h -%{_includedir}/zebra/Video.h -%{_includedir}/zebra/Window.h -%{_includedir}/zebra/Processor.h +%{_libdir}/libzbar.la +%{_libdir}/libzbar.a +%{_libdir}/libzbar.so +%{_libdir}/pkgconfig/zbar.pc +%{_includedir}/zbar.h +%{_includedir}/zbar/Exception.h +%{_includedir}/zbar/Symbol.h +%{_includedir}/zbar/Image.h +%{_includedir}/zbar/Scanner.h +%{_includedir}/zbar/Decoder.h +%{_includedir}/zbar/ImageScanner.h +%{_includedir}/zbar/Video.h +%{_includedir}/zbar/Window.h +%{_includedir}/zbar/Processor.h %files gtk %defattr(-,root,root) -%{_libdir}/libzebragtk.so.* +%{_libdir}/libzbargtk.so.* %files gtk-devel %defattr(-,root,root) -%{_libdir}/libzebragtk.la -%{_libdir}/libzebragtk.a -%{_libdir}/libzebragtk.so -%{_libdir}/pkgconfig/zebra-gtk.pc -%{_includedir}/zebra/zebragtk.h +%{_libdir}/libzbargtk.la +%{_libdir}/libzbargtk.a +%{_libdir}/libzbargtk.so +%{_libdir}/pkgconfig/zbar-gtk.pc +%{_includedir}/zbar/zbargtk.h %files pygtk %defattr(-,root,root) @@ -183,17 +183,20 @@ ldconfig %files qt %defattr(-,root,root) -%{_libdir}/libzebraqt.so.* +%{_libdir}/libzbarqt.so.* %files qt-devel %defattr(-,root,root) -%{_libdir}/libzebraqt.la -%{_libdir}/libzebraqt.a -%{_libdir}/libzebraqt.so -%{_libdir}/pkgconfig/zebra-qt.pc -%{_includedir}/zebra/QZebra*.h +%{_libdir}/libzbarqt.la +%{_libdir}/libzbarqt.a +%{_libdir}/libzbarqt.so +%{_libdir}/pkgconfig/zbar-qt.pc +%{_includedir}/zbar/QZBar*.h %changelog +* Thu Apr 16 2009 spadix +- project name change + * Thu Jul 24 2008 spadix - version 0.5 updates (new widget packages) diff --git a/zbar/Makefile.am.inc b/zbar/Makefile.am.inc new file mode 100644 index 0000000..0f142b3 --- /dev/null +++ b/zbar/Makefile.am.inc @@ -0,0 +1,62 @@ +lib_LTLIBRARIES += zbar/libzbar.la +zbar_libzbar_la_CPPFLAGS = -I$(srcdir)/zbar $(AM_CPPFLAGS) +zbar_libzbar_la_LDFLAGS = -no-undefined -version-info $(LIB_VERSION) \ + -export-symbols-regex "^(zbar|_zbar.*_error)_.*" $(AM_LDFLAGS) +zbar_libzbar_la_LIBADD = + +zbar_libzbar_la_SOURCES = zbar/debug.h zbar/config.c \ + zbar/error.h zbar/error.c zbar/symbol.h zbar/symbol.c \ + zbar/image.h zbar/image.c zbar/convert.c zbar/logo.c \ + zbar/window.h zbar/window.c zbar/video.h zbar/video.c \ + zbar/img_scanner.c zbar/scanner.c \ + zbar/decoder.h zbar/decoder.c + +if HAVE_POLL +zbar_libzbar_la_SOURCES += zbar/processor.h zbar/processor.c +endif + +if ENABLE_EAN +zbar_libzbar_la_SOURCES += zbar/decoder/ean.h zbar/decoder/ean.c +endif +if ENABLE_CODE128 +zbar_libzbar_la_SOURCES += zbar/decoder/code128.h zbar/decoder/code128.c +endif +if ENABLE_CODE39 +zbar_libzbar_la_SOURCES += zbar/decoder/code39.h zbar/decoder/code39.c +endif +if ENABLE_I25 +zbar_libzbar_la_SOURCES += zbar/decoder/i25.h zbar/decoder/i25.c +endif +if ENABLE_PDF417 +zbar_libzbar_la_SOURCES += zbar/decoder/pdf417.h zbar/decoder/pdf417.c \ + zbar/decoder/pdf417_hash.h +endif + +if HAVE_V4L1 +zbar_libzbar_la_SOURCES += zbar/video/v4l1.c +if HAVE_V4L2 +zbar_libzbar_la_SOURCES += zbar/video/v4l2.c +endif +else +zbar_libzbar_la_SOURCES += zbar/video/null.c +endif + +if HAVE_JPEG +zbar_libzbar_la_SOURCES += zbar/jpeg.c +endif + +if HAVE_X +zbar_libzbar_la_SOURCES += zbar/window/x.c zbar/window/ximage.c +zbar_libzbar_la_CPPFLAGS += $(X_CFLAGS) +zbar_libzbar_la_LDFLAGS += $(X_LIBS) +zbar_libzbar_la_LIBADD += $(X_PRE_LIBS) -lX11 $(X_EXTRA_LIBS) +if HAVE_XV +zbar_libzbar_la_SOURCES += zbar/window/xv.c +zbar_libzbar_la_LIBADD += $(XV_LIBS) +endif +else +zbar_libzbar_la_SOURCES += zbar/window/null.c +endif + +zbar_libzbar_la_LDFLAGS += $(AM_LDFLAGS) +zbar_libzbar_la_LIBADD += $(AM_LIBADD) diff --git a/zebra/config.c b/zbar/config.c similarity index 71% rename from zebra/config.c rename to zbar/config.c index b6aa931..df854d3 100644 --- a/zebra/config.c +++ b/zbar/config.c @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ - * Copyright 2008 (c) Jeff Brown + * Copyright 2008-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include @@ -27,11 +27,11 @@ #include #include -#include +#include -int zebra_parse_config (const char *cfgstr, - zebra_symbol_type_t *sym, - zebra_config_t *cfg, +int zbar_parse_config (const char *cfgstr, + zbar_symbol_type_t *sym, + zbar_config_t *cfg, int *val) { if(!cfgstr) @@ -45,40 +45,40 @@ int zebra_parse_config (const char *cfgstr, else if(len < 3) return(1); else if(!strncmp(cfgstr, "upca", len)) - *sym = ZEBRA_UPCA; + *sym = ZBAR_UPCA; else if(!strncmp(cfgstr, "upce", len)) - *sym = ZEBRA_UPCE; + *sym = ZBAR_UPCE; else if(!strncmp(cfgstr, "ean13", len)) - *sym = ZEBRA_EAN13; + *sym = ZBAR_EAN13; else if(!strncmp(cfgstr, "ean8", len)) - *sym = ZEBRA_EAN8; + *sym = ZBAR_EAN8; else if(!strncmp(cfgstr, "i25", len)) - *sym = ZEBRA_I25; + *sym = ZBAR_I25; else if(len < 4) return(1); else if(!strncmp(cfgstr, "scanner", len)) - *sym = ZEBRA_PARTIAL; /* FIXME lame */ + *sym = ZBAR_PARTIAL; /* FIXME lame */ else if(!strncmp(cfgstr, "isbn13", len)) - *sym = ZEBRA_ISBN13; + *sym = ZBAR_ISBN13; else if(!strncmp(cfgstr, "isbn10", len)) - *sym = ZEBRA_ISBN10; + *sym = ZBAR_ISBN10; #if 0 /* FIXME addons are configured per-main symbol type */ else if(!strncmp(cfgstr, "addon2", len)) - *sym = ZEBRA_ADDON2; + *sym = ZBAR_ADDON2; else if(!strncmp(cfgstr, "addon5", len)) - *sym = ZEBRA_ADDON5; + *sym = ZBAR_ADDON5; #endif else if(len < 6) return(1); else if(!strncmp(cfgstr, "code39", len)) - *sym = ZEBRA_CODE39; + *sym = ZBAR_CODE39; else if(!strncmp(cfgstr, "pdf417", len)) - *sym = ZEBRA_PDF417; + *sym = ZBAR_PDF417; else if(len < 7) return(1); else if(!strncmp(cfgstr, "code128", len)) - *sym = ZEBRA_CODE128; + *sym = ZBAR_CODE128; else return(1); cfgstr = dot + 1; @@ -103,29 +103,29 @@ int zebra_parse_config (const char *cfgstr, if(len < 1) return(1); else if(!strncmp(cfgstr, "y-density", len)) - *cfg = ZEBRA_CFG_Y_DENSITY; + *cfg = ZBAR_CFG_Y_DENSITY; else if(!strncmp(cfgstr, "x-density", len)) - *cfg = ZEBRA_CFG_X_DENSITY; + *cfg = ZBAR_CFG_X_DENSITY; else if(len < 2) return(1); else if(!strncmp(cfgstr, "enable", len)) - *cfg = ZEBRA_CFG_ENABLE; + *cfg = ZBAR_CFG_ENABLE; else if(len < 3) return(1); else if(!strncmp(cfgstr, "disable", len)) { - *cfg = ZEBRA_CFG_ENABLE; + *cfg = ZBAR_CFG_ENABLE; negate = !negate; /* no-disable ?!? */ } else if(!strncmp(cfgstr, "min-length", len)) - *cfg = ZEBRA_CFG_MIN_LEN; + *cfg = ZBAR_CFG_MIN_LEN; else if(!strncmp(cfgstr, "max-length", len)) - *cfg = ZEBRA_CFG_MAX_LEN; + *cfg = ZBAR_CFG_MAX_LEN; else if(!strncmp(cfgstr, "ascii", len)) - *cfg = ZEBRA_CFG_ASCII; + *cfg = ZBAR_CFG_ASCII; else if(!strncmp(cfgstr, "add-check", len)) - *cfg = ZEBRA_CFG_ADD_CHECK; + *cfg = ZBAR_CFG_ADD_CHECK; else if(!strncmp(cfgstr, "emit-check", len)) - *cfg = ZEBRA_CFG_EMIT_CHECK; + *cfg = ZBAR_CFG_EMIT_CHECK; else return(1); diff --git a/zebra/convert.c b/zbar/convert.c similarity index 77% rename from zebra/convert.c rename to zbar/convert.c index 3fc7b5f..07aba95 100644 --- a/zebra/convert.c +++ b/zbar/convert.c @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include "image.h" @@ -29,10 +29,10 @@ */ #define RGB_BITS(off, size) ((((8 - (size)) & 0x7) << 5) | ((off) & 0x1f)) -typedef void (conversion_handler_t)(zebra_image_t*, - const zebra_format_def_t*, - const zebra_image_t*, - const zebra_format_def_t*); +typedef void (conversion_handler_t)(zbar_image_t*, + const zbar_format_def_t*, + const zbar_image_t*, + const zbar_format_def_t*); typedef struct conversion_def_s { int cost; /* conversion "badness" */ @@ -107,62 +107,62 @@ static const uint32_t format_prefs[] = { }; static const int num_format_prefs = - sizeof(format_prefs) / sizeof(zebra_format_def_t); + sizeof(format_prefs) / sizeof(zbar_format_def_t); /* format definitions */ -static const zebra_format_def_t format_defs[] = { +static const zbar_format_def_t format_defs[] = { - { fourcc('R','G','B','4'), ZEBRA_FMT_RGB_PACKED, + { fourcc('R','G','B','4'), ZBAR_FMT_RGB_PACKED, { { 4, RGB_BITS(8, 8), RGB_BITS(16, 8), RGB_BITS(24, 8) } } }, - { fourcc('B','G','R','1'), ZEBRA_FMT_RGB_PACKED, + { fourcc('B','G','R','1'), ZBAR_FMT_RGB_PACKED, { { 1, RGB_BITS(0, 3), RGB_BITS(3, 3), RGB_BITS(6, 2) } } }, - { fourcc('4','2','2','P'), ZEBRA_FMT_YUV_PLANAR, { { 1, 0, 0 /*UV*/ } } }, - { fourcc('Y','8','0','0'), ZEBRA_FMT_GRAY, }, - { fourcc('Y','U','Y','2'), ZEBRA_FMT_YUV_PACKED, + { fourcc('4','2','2','P'), ZBAR_FMT_YUV_PLANAR, { { 1, 0, 0 /*UV*/ } } }, + { fourcc('Y','8','0','0'), ZBAR_FMT_GRAY, }, + { fourcc('Y','U','Y','2'), ZBAR_FMT_YUV_PACKED, { { 1, 0, 0, /*YUYV*/ } } }, - { fourcc('J','P','E','G'), ZEBRA_FMT_JPEG, }, - { fourcc('Y','V','Y','U'), ZEBRA_FMT_YUV_PACKED, + { fourcc('J','P','E','G'), ZBAR_FMT_JPEG, }, + { fourcc('Y','V','Y','U'), ZBAR_FMT_YUV_PACKED, { { 1, 0, 1, /*YVYU*/ } } }, - { fourcc('Y','8', 0 , 0 ), ZEBRA_FMT_GRAY, }, - { fourcc('N','V','2','1'), ZEBRA_FMT_YUV_NV, { { 1, 1, 1 /*VU*/ } } }, - { fourcc('N','V','1','2'), ZEBRA_FMT_YUV_NV, { { 1, 1, 0 /*UV*/ } } }, - { fourcc('B','G','R','3'), ZEBRA_FMT_RGB_PACKED, + { fourcc('Y','8', 0 , 0 ), ZBAR_FMT_GRAY, }, + { fourcc('N','V','2','1'), ZBAR_FMT_YUV_NV, { { 1, 1, 1 /*VU*/ } } }, + { fourcc('N','V','1','2'), ZBAR_FMT_YUV_NV, { { 1, 1, 0 /*UV*/ } } }, + { fourcc('B','G','R','3'), ZBAR_FMT_RGB_PACKED, { { 3, RGB_BITS(16, 8), RGB_BITS(8, 8), RGB_BITS(0, 8) } } }, - { fourcc('Y','V','U','9'), ZEBRA_FMT_YUV_PLANAR, { { 2, 2, 1 /*VU*/ } } }, - { fourcc('R','G','B','O'), ZEBRA_FMT_RGB_PACKED, + { fourcc('Y','V','U','9'), ZBAR_FMT_YUV_PLANAR, { { 2, 2, 1 /*VU*/ } } }, + { fourcc('R','G','B','O'), ZBAR_FMT_RGB_PACKED, { { 2, RGB_BITS(10, 5), RGB_BITS(5, 5), RGB_BITS(0, 5) } } }, - { fourcc('R','G','B','Q'), ZEBRA_FMT_RGB_PACKED, + { fourcc('R','G','B','Q'), ZBAR_FMT_RGB_PACKED, { { 2, RGB_BITS(2, 5), RGB_BITS(13, 5), RGB_BITS(8, 5) } } }, - { fourcc('G','R','E','Y'), ZEBRA_FMT_GRAY, }, - { fourcc( 3 , 0 , 0 , 0 ), ZEBRA_FMT_RGB_PACKED, + { fourcc('G','R','E','Y'), ZBAR_FMT_GRAY, }, + { fourcc( 3 , 0 , 0 , 0 ), ZBAR_FMT_RGB_PACKED, { { 4, RGB_BITS(16, 8), RGB_BITS(8, 8), RGB_BITS(0, 8) } } }, - { fourcc('Y','8',' ',' '), ZEBRA_FMT_GRAY, }, - { fourcc('I','4','2','0'), ZEBRA_FMT_YUV_PLANAR, { { 1, 1, 0 /*UV*/ } } }, - { fourcc('R','G','B','1'), ZEBRA_FMT_RGB_PACKED, + { fourcc('Y','8',' ',' '), ZBAR_FMT_GRAY, }, + { fourcc('I','4','2','0'), ZBAR_FMT_YUV_PLANAR, { { 1, 1, 0 /*UV*/ } } }, + { fourcc('R','G','B','1'), ZBAR_FMT_RGB_PACKED, { { 1, RGB_BITS(5, 3), RGB_BITS(2, 3), RGB_BITS(0, 2) } } }, - { fourcc('Y','U','1','2'), ZEBRA_FMT_YUV_PLANAR, { { 1, 1, 0 /*UV*/ } } }, - { fourcc('Y','V','1','2'), ZEBRA_FMT_YUV_PLANAR, { { 1, 1, 1 /*VU*/ } } }, - { fourcc('R','G','B','3'), ZEBRA_FMT_RGB_PACKED, + { fourcc('Y','U','1','2'), ZBAR_FMT_YUV_PLANAR, { { 1, 1, 0 /*UV*/ } } }, + { fourcc('Y','V','1','2'), ZBAR_FMT_YUV_PLANAR, { { 1, 1, 1 /*VU*/ } } }, + { fourcc('R','G','B','3'), ZBAR_FMT_RGB_PACKED, { { 3, RGB_BITS(0, 8), RGB_BITS(8, 8), RGB_BITS(16, 8) } } }, - { fourcc('R','4','4','4'), ZEBRA_FMT_RGB_PACKED, + { fourcc('R','4','4','4'), ZBAR_FMT_RGB_PACKED, { { 2, RGB_BITS(8, 4), RGB_BITS(4, 4), RGB_BITS(0, 4) } } }, - { fourcc('B','G','R','4'), ZEBRA_FMT_RGB_PACKED, + { fourcc('B','G','R','4'), ZBAR_FMT_RGB_PACKED, { { 4, RGB_BITS(16, 8), RGB_BITS(8, 8), RGB_BITS(0, 8) } } }, - { fourcc('Y','U','V','9'), ZEBRA_FMT_YUV_PLANAR, { { 2, 2, 0 /*UV*/ } } }, - { fourcc('M','J','P','G'), ZEBRA_FMT_JPEG, }, - { fourcc('4','1','1','P'), ZEBRA_FMT_YUV_PLANAR, { { 2, 0, 0 /*UV*/ } } }, - { fourcc('R','G','B','P'), ZEBRA_FMT_RGB_PACKED, + { fourcc('Y','U','V','9'), ZBAR_FMT_YUV_PLANAR, { { 2, 2, 0 /*UV*/ } } }, + { fourcc('M','J','P','G'), ZBAR_FMT_JPEG, }, + { fourcc('4','1','1','P'), ZBAR_FMT_YUV_PLANAR, { { 2, 0, 0 /*UV*/ } } }, + { fourcc('R','G','B','P'), ZBAR_FMT_RGB_PACKED, { { 2, RGB_BITS(11, 5), RGB_BITS(5, 6), RGB_BITS(0, 5) } } }, - { fourcc('R','G','B','R'), ZEBRA_FMT_RGB_PACKED, + { fourcc('R','G','B','R'), ZBAR_FMT_RGB_PACKED, { { 2, RGB_BITS(3, 5), RGB_BITS(13, 6), RGB_BITS(8, 5) } } }, - { fourcc('Y','U','Y','V'), ZEBRA_FMT_YUV_PACKED, + { fourcc('Y','U','Y','V'), ZBAR_FMT_YUV_PACKED, { { 1, 0, 0, /*YUYV*/ } } }, - { fourcc('U','Y','V','Y'), ZEBRA_FMT_YUV_PACKED, + { fourcc('U','Y','V','Y'), ZBAR_FMT_YUV_PACKED, { { 1, 0, 2, /*UYVY*/ } } }, }; static const int num_format_defs = - sizeof(format_defs) / sizeof(zebra_format_def_t); + sizeof(format_defs) / sizeof(zbar_format_def_t); #ifdef DEBUG_CONVERT static int intsort (const void *a, @@ -225,8 +225,8 @@ static inline int verify_format_sort () return(-1); } -static inline void uv_round (zebra_image_t *img, - const zebra_format_def_t *fmt) +static inline void uv_round (zbar_image_t *img, + const zbar_format_def_t *fmt) { img->width >>= fmt->p.yuv.xsub2; img->width <<= fmt->p.yuv.xsub2; @@ -234,10 +234,10 @@ static inline void uv_round (zebra_image_t *img, img->height <<= fmt->p.yuv.ysub2; } -static inline void uv_roundup (zebra_image_t *img, - const zebra_format_def_t *fmt) +static inline void uv_roundup (zbar_image_t *img, + const zbar_format_def_t *fmt) { - if(fmt->group == ZEBRA_FMT_GRAY) + if(fmt->group == ZBAR_FMT_GRAY) return; unsigned xmask = (1 << fmt->p.yuv.xsub2) - 1; if(img->width & xmask) @@ -247,10 +247,10 @@ static inline void uv_roundup (zebra_image_t *img, img->height = (img->height + ymask) & ~ymask; } -static inline unsigned long uvp_size (const zebra_image_t *img, - const zebra_format_def_t *fmt) +static inline unsigned long uvp_size (const zbar_image_t *img, + const zbar_format_def_t *fmt) { - if(fmt->group == ZEBRA_FMT_GRAY) + if(fmt->group == ZBAR_FMT_GRAY) return(0); return((img->width >> fmt->p.yuv.xsub2) * (img->height >> fmt->p.yuv.ysub2)); @@ -292,19 +292,19 @@ static inline void convert_write_rgb (uint8_t *dstp, } /* cleanup linked image by unrefing */ -static void cleanup_ref (zebra_image_t *img) +static void cleanup_ref (zbar_image_t *img) { if(img->next) - _zebra_image_refcnt(img->next, -1); + _zbar_image_refcnt(img->next, -1); } /* resize y plane, drop extra columns/rows from the right/bottom, * or duplicate last column/row to pad missing data */ -static inline void convert_y_resize (zebra_image_t *dst, - const zebra_format_def_t *dstfmt, - const zebra_image_t *src, - const zebra_format_def_t *srcfmt, +static inline void convert_y_resize (zbar_image_t *dst, + const zbar_format_def_t *dstfmt, + const zbar_image_t *src, + const zbar_format_def_t *srcfmt, size_t n) { if(dst->width == src->width && dst->height == src->height) { @@ -338,18 +338,18 @@ static inline void convert_y_resize (zebra_image_t *dst, } /* make new image w/reference to the same image data */ -static void convert_copy (zebra_image_t *dst, - const zebra_format_def_t *dstfmt, - const zebra_image_t *src, - const zebra_format_def_t *srcfmt) +static void convert_copy (zbar_image_t *dst, + const zbar_format_def_t *dstfmt, + const zbar_image_t *src, + const zbar_format_def_t *srcfmt) { if(src->width == dst->width && src->height == dst->height) { dst->data = src->data; dst->datalen = src->datalen; dst->cleanup = cleanup_ref; - dst->next = (zebra_image_t*)src; - ((zebra_image_t*)src)->refcnt++; + dst->next = (zbar_image_t*)src; + ((zbar_image_t*)src)->refcnt++; } else /* NB only for GRAY/YUV_PLANAR formats */ @@ -357,10 +357,10 @@ static void convert_copy (zebra_image_t *dst, } /* append neutral UV plane to grayscale image */ -static void convert_uvp_append (zebra_image_t *dst, - const zebra_format_def_t *dstfmt, - const zebra_image_t *src, - const zebra_format_def_t *srcfmt) +static void convert_uvp_append (zbar_image_t *dst, + const zbar_format_def_t *dstfmt, + const zbar_image_t *src, + const zbar_format_def_t *srcfmt) { uv_roundup(dst, dstfmt); dst->datalen = uvp_size(dst, dstfmt) * 2; @@ -377,10 +377,10 @@ static void convert_uvp_append (zebra_image_t *dst, } /* interleave YUV planes into packed YUV */ -static void convert_yuv_pack (zebra_image_t *dst, - const zebra_format_def_t *dstfmt, - const zebra_image_t *src, - const zebra_format_def_t *srcfmt) +static void convert_yuv_pack (zbar_image_t *dst, + const zbar_format_def_t *dstfmt, + const zbar_image_t *src, + const zbar_format_def_t *srcfmt) { uv_roundup(dst, dstfmt); dst->datalen = dst->width * dst->height + uvp_size(dst, dstfmt) * 2; @@ -443,10 +443,10 @@ static void convert_yuv_pack (zebra_image_t *dst, /* split packed YUV samples and join into YUV planes * FIXME currently ignores color and grayscales the image */ -static void convert_yuv_unpack (zebra_image_t *dst, - const zebra_format_def_t *dstfmt, - const zebra_image_t *src, - const zebra_format_def_t *srcfmt) +static void convert_yuv_unpack (zbar_image_t *dst, + const zbar_format_def_t *dstfmt, + const zbar_image_t *src, + const zbar_format_def_t *srcfmt) { uv_roundup(dst, dstfmt); unsigned long dstn = dst->width * dst->height; @@ -486,10 +486,10 @@ static void convert_yuv_unpack (zebra_image_t *dst, /* resample and resize UV plane(s) * FIXME currently ignores color and grayscales the image */ -static void convert_uvp_resample (zebra_image_t *dst, - const zebra_format_def_t *dstfmt, - const zebra_image_t *src, - const zebra_format_def_t *srcfmt) +static void convert_uvp_resample (zbar_image_t *dst, + const zbar_format_def_t *dstfmt, + const zbar_image_t *src, + const zbar_format_def_t *srcfmt) { uv_roundup(dst, dstfmt); unsigned long dstn = dst->width * dst->height; @@ -503,10 +503,10 @@ static void convert_uvp_resample (zebra_image_t *dst, } /* rearrange interleaved UV componets */ -static void convert_uv_resample (zebra_image_t *dst, - const zebra_format_def_t *dstfmt, - const zebra_image_t *src, - const zebra_format_def_t *srcfmt) +static void convert_uv_resample (zbar_image_t *dst, + const zbar_format_def_t *dstfmt, + const zbar_image_t *src, + const zbar_format_def_t *srcfmt) { uv_roundup(dst, dstfmt); unsigned long dstn = dst->width * dst->height; @@ -555,10 +555,10 @@ static void convert_uv_resample (zebra_image_t *dst, /* YUV planes to packed RGB * FIXME currently ignores color and grayscales the image */ -static void convert_yuvp_to_rgb (zebra_image_t *dst, - const zebra_format_def_t *dstfmt, - const zebra_image_t *src, - const zebra_format_def_t *srcfmt) +static void convert_yuvp_to_rgb (zbar_image_t *dst, + const zbar_format_def_t *dstfmt, + const zbar_image_t *src, + const zbar_format_def_t *srcfmt) { dst->datalen = dst->width * dst->height * dstfmt->p.rgb.bpp; dst->data = malloc(dst->datalen); @@ -601,10 +601,10 @@ static void convert_yuvp_to_rgb (zebra_image_t *dst, /* packed RGB to YUV planes * FIXME currently ignores color and grayscales the image */ -static void convert_rgb_to_yuvp (zebra_image_t *dst, - const zebra_format_def_t *dstfmt, - const zebra_image_t *src, - const zebra_format_def_t *srcfmt) +static void convert_rgb_to_yuvp (zbar_image_t *dst, + const zbar_format_def_t *dstfmt, + const zbar_image_t *src, + const zbar_format_def_t *srcfmt) { uv_roundup(dst, dstfmt); unsigned long dstn = dst->width * dst->height; @@ -654,10 +654,10 @@ static void convert_rgb_to_yuvp (zebra_image_t *dst, } /* packed YUV to packed RGB */ -static void convert_yuv_to_rgb (zebra_image_t *dst, - const zebra_format_def_t *dstfmt, - const zebra_image_t *src, - const zebra_format_def_t *srcfmt) +static void convert_yuv_to_rgb (zbar_image_t *dst, + const zbar_format_def_t *dstfmt, + const zbar_image_t *src, + const zbar_format_def_t *srcfmt) { unsigned long dstn = dst->width * dst->height; dst->datalen = dstn * dstfmt->p.rgb.bpp; @@ -712,10 +712,10 @@ static void convert_yuv_to_rgb (zebra_image_t *dst, /* packed RGB to packed YUV * FIXME currently ignores color and grayscales the image */ -static void convert_rgb_to_yuv (zebra_image_t *dst, - const zebra_format_def_t *dstfmt, - const zebra_image_t *src, - const zebra_format_def_t *srcfmt) +static void convert_rgb_to_yuv (zbar_image_t *dst, + const zbar_format_def_t *dstfmt, + const zbar_image_t *src, + const zbar_format_def_t *srcfmt) { uv_roundup(dst, dstfmt); dst->datalen = dst->width * dst->height + uvp_size(dst, dstfmt) * 2; @@ -767,10 +767,10 @@ static void convert_rgb_to_yuv (zebra_image_t *dst, } /* resample and resize packed RGB components */ -static void convert_rgb_resample (zebra_image_t *dst, - const zebra_format_def_t *dstfmt, - const zebra_image_t *src, - const zebra_format_def_t *srcfmt) +static void convert_rgb_resample (zbar_image_t *dst, + const zbar_format_def_t *dstfmt, + const zbar_image_t *src, + const zbar_format_def_t *srcfmt) { unsigned long dstn = dst->width * dst->height; dst->datalen = dstn * dstfmt->p.rgb.bpp; @@ -825,19 +825,19 @@ static void convert_rgb_resample (zebra_image_t *dst, } #ifdef HAVE_LIBJPEG -void _zebra_convert_jpeg_to_y(zebra_image_t *dst, - const zebra_format_def_t *dstfmt, - const zebra_image_t *src, - const zebra_format_def_t *srcfmt); - -static void convert_jpeg(zebra_image_t *dst, - const zebra_format_def_t *dstfmt, - const zebra_image_t *src, - const zebra_format_def_t *srcfmt); +void _zbar_convert_jpeg_to_y(zbar_image_t *dst, + const zbar_format_def_t *dstfmt, + const zbar_image_t *src, + const zbar_format_def_t *srcfmt); + +static void convert_jpeg(zbar_image_t *dst, + const zbar_format_def_t *dstfmt, + const zbar_image_t *src, + const zbar_format_def_t *srcfmt); #endif /* group conversion matrix */ -static conversion_def_t conversions[][ZEBRA_FMT_NUM] = { +static conversion_def_t conversions[][ZBAR_FMT_NUM] = { { /* *from* GRAY */ { 0, convert_copy }, /* to GRAY */ { 8, convert_uvp_append }, /* to YUV_PLANAR */ @@ -880,7 +880,7 @@ static conversion_def_t conversions[][ZEBRA_FMT_NUM] = { }, #ifdef HAVE_LIBJPEG { /* from JPEG */ - { 96, _zebra_convert_jpeg_to_y }, /* to GRAY */ + { 96, _zbar_convert_jpeg_to_y }, /* to GRAY */ { 104, convert_jpeg }, /* to YUV_PLANAR */ { 116, convert_jpeg }, /* to YUV_PACKED */ { 256, convert_jpeg }, /* to RGB_PACKED */ @@ -899,9 +899,9 @@ static conversion_def_t conversions[][ZEBRA_FMT_NUM] = { #endif }; -const zebra_format_def_t *_zebra_format_lookup (uint32_t fmt) +const zbar_format_def_t *_zbar_format_lookup (uint32_t fmt) { - const zebra_format_def_t *def = NULL; + const zbar_format_def_t *def = NULL; int i = 0; while(i < num_format_defs) { def = &format_defs[i]; @@ -916,17 +916,17 @@ const zebra_format_def_t *_zebra_format_lookup (uint32_t fmt) #ifdef HAVE_LIBJPEG /* convert JPEG data via an intermediate format supported by libjpeg */ -static void convert_jpeg (zebra_image_t *dst, - const zebra_format_def_t *dstfmt, - const zebra_image_t *src, - const zebra_format_def_t *srcfmt) +static void convert_jpeg (zbar_image_t *dst, + const zbar_format_def_t *dstfmt, + const zbar_image_t *src, + const zbar_format_def_t *srcfmt) { /* define intermediate image in a format supported by libjpeg * (currently only grayscale) */ - zebra_image_t *tmp; + zbar_image_t *tmp; if(!src->src) { - tmp = zebra_image_create(); + tmp = zbar_image_create(); tmp->format = fourcc('Y','8','0','0'); tmp->width = dst->width; tmp->height = dst->height; @@ -938,11 +938,11 @@ static void convert_jpeg (zebra_image_t *dst, dst->height = tmp->height; } - const zebra_format_def_t *tmpfmt = _zebra_format_lookup(tmp->format); + const zbar_format_def_t *tmpfmt = _zbar_format_lookup(tmp->format); assert(tmpfmt); /* convert to intermediate format */ - _zebra_convert_jpeg_to_y(tmp, tmpfmt, src, srcfmt); + _zbar_convert_jpeg_to_y(tmp, tmpfmt, src, srcfmt); /* now convert to dst */ dst->width = tmp->width; @@ -954,16 +954,16 @@ static void convert_jpeg (zebra_image_t *dst, func(dst, dstfmt, tmp, tmpfmt); if(!src->src) - zebra_image_destroy(tmp); + zbar_image_destroy(tmp); } #endif -zebra_image_t *zebra_image_convert_resize (const zebra_image_t *src, - unsigned long fmt, - unsigned width, - unsigned height) +zbar_image_t *zbar_image_convert_resize (const zbar_image_t *src, + unsigned long fmt, + unsigned width, + unsigned height) { - zebra_image_t *dst = zebra_image_create(); + zbar_image_t *dst = zbar_image_create(); dst->format = fmt; dst->width = width; dst->height = height; @@ -974,8 +974,8 @@ zebra_image_t *zebra_image_convert_resize (const zebra_image_t *src, return(dst); } - const zebra_format_def_t *srcfmt = _zebra_format_lookup(src->format); - const zebra_format_def_t *dstfmt = _zebra_format_lookup(dst->format); + const zbar_format_def_t *srcfmt = _zbar_format_lookup(src->format); + const zbar_format_def_t *dstfmt = _zbar_format_lookup(dst->format); if(!srcfmt || !dstfmt) /* FIXME free dst */ return(NULL); @@ -991,20 +991,20 @@ zebra_image_t *zebra_image_convert_resize (const zebra_image_t *src, conversion_handler_t *func = conversions[srcfmt->group][dstfmt->group].func; - dst->cleanup = zebra_image_free_data; + dst->cleanup = zbar_image_free_data; func(dst, dstfmt, src, srcfmt); if(!dst->data) { /* conversion failed */ - zebra_image_destroy(dst); + zbar_image_destroy(dst); return(NULL); } return(dst); } -zebra_image_t *zebra_image_convert (const zebra_image_t *src, - unsigned long fmt) +zbar_image_t *zbar_image_convert (const zbar_image_t *src, + unsigned long fmt) { - return(zebra_image_convert_resize(src, fmt, src->width, src->height)); + return(zbar_image_convert_resize(src, fmt, src->width, src->height)); } static inline int has_format (uint32_t fmt, @@ -1017,9 +1017,9 @@ static inline int has_format (uint32_t fmt, } /* select least cost conversion from src format to available dsts */ -int _zebra_best_format (uint32_t src, - uint32_t *dst, - const uint32_t *dsts) +int _zbar_best_format (uint32_t src, + uint32_t *dst, + const uint32_t *dsts) { if(dst) *dst = 0; @@ -1031,14 +1031,14 @@ int _zebra_best_format (uint32_t src, *dst = src; return(0); } - const zebra_format_def_t *srcfmt = _zebra_format_lookup(src); + const zbar_format_def_t *srcfmt = _zbar_format_lookup(src); if(!srcfmt) return(-1); zprintf(8, "from %.4s(%08" PRIx32 ") to", (char*)&src, src); unsigned min_cost = -1; for(; *dsts; dsts++) { - const zebra_format_def_t *dstfmt = _zebra_format_lookup(*dsts); + const zbar_format_def_t *dstfmt = _zbar_format_lookup(*dsts); if(!dstfmt) continue; int cost; @@ -1048,7 +1048,7 @@ int _zebra_best_format (uint32_t src, else cost = conversions[srcfmt->group][dstfmt->group].cost; - if(_zebra_verbosity >= 8) + if(_zbar_verbosity >= 8) fprintf(stderr, " %.4s(%08" PRIx32 ")=%d", (char*)dsts, *dsts, cost); if(cost >= 0 && min_cost > cost) { @@ -1057,13 +1057,13 @@ int _zebra_best_format (uint32_t src, *dst = *dsts; } } - if(_zebra_verbosity >= 8) + if(_zbar_verbosity >= 8) fprintf(stderr, "\n"); return(min_cost); } -int zebra_negotiate_format (zebra_video_t *vdo, - zebra_window_t *win) +int zbar_negotiate_format (zbar_video_t *vdo, + zbar_window_t *win) { if(!vdo && !win) return(0); @@ -1075,14 +1075,14 @@ int zebra_negotiate_format (zebra_video_t *vdo, if(verify_format_sort()) { if(win) (void)window_unlock(win); - return(err_capture(errdst, SEV_FATAL, ZEBRA_ERR_INTERNAL, __func__, + return(err_capture(errdst, SEV_FATAL, ZBAR_ERR_INTERNAL, __func__, "image format list is not sorted!?")); } if((vdo && !vdo->formats) || (win && !win->formats)) { if(win) (void)window_unlock(win); - return(err_capture(errdst, SEV_ERROR, ZEBRA_ERR_UNSUPPORTED, __func__, + return(err_capture(errdst, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "no input or output formats available")); } @@ -1098,7 +1098,7 @@ int zebra_negotiate_format (zebra_video_t *vdo, if(!has_format(*fmt, srcs)) continue; uint32_t win_fmt = 0; - int cost = _zebra_best_format(*fmt, &win_fmt, dsts); + int cost = _zbar_best_format(*fmt, &win_fmt, dsts); if(cost < 0) { zprintf(4, "%.4s(%08" PRIx32 ") -> ? (unsupported)\n", (char*)fmt, *fmt); @@ -1117,12 +1117,12 @@ int zebra_negotiate_format (zebra_video_t *vdo, (void)window_unlock(win); if(!min_fmt) - return(err_capture(errdst, SEV_ERROR, ZEBRA_ERR_UNSUPPORTED, __func__, + return(err_capture(errdst, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "no supported image formats available")); if(!vdo) return(0); zprintf(2, "setting best format %.4s(%08" PRIx32 ") (%d)\n", (char*)&min_fmt, min_fmt, min_cost); - return(zebra_video_init(vdo, min_fmt)); + return(zbar_video_init(vdo, min_fmt)); } diff --git a/zebra/debug.h b/zbar/debug.h similarity index 87% rename from zebra/debug.h rename to zbar/debug.h index 8717018..482ca8d 100644 --- a/zebra/debug.h +++ b/zbar/debug.h @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ /* varargs variations on compile time debug spew */ diff --git a/zebra/decoder.c b/zbar/decoder.c similarity index 55% rename from zebra/decoder.c rename to zbar/decoder.c index e8004a9..663f847 100644 --- a/zebra/decoder.c +++ b/zbar/decoder.c @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include @@ -26,7 +26,7 @@ #include /* snprintf */ #include /* memset, strlen */ -#include +#include #include "decoder.h" #if defined(DEBUG_DECODER) || defined(DEBUG_EAN) || defined(DEBUG_CODE128) || \ @@ -36,9 +36,9 @@ #endif #include "debug.h" -zebra_decoder_t *zebra_decoder_create () +zbar_decoder_t *zbar_decoder_create () { - zebra_decoder_t *dcode = malloc(sizeof(zebra_decoder_t)); + zbar_decoder_t *dcode = malloc(sizeof(zbar_decoder_t)); dcode->buflen = BUFFER_MIN; dcode->buf = malloc(dcode->buflen); dcode->handler = dcode->userdata = NULL; @@ -46,42 +46,42 @@ zebra_decoder_t *zebra_decoder_create () /* initialize default configs */ #ifdef ENABLE_EAN dcode->ean.enable = 1; - dcode->ean.ean13_config = ((1 << ZEBRA_CFG_ENABLE) | - (1 << ZEBRA_CFG_EMIT_CHECK)); - dcode->ean.ean8_config = ((1 << ZEBRA_CFG_ENABLE) | - (1 << ZEBRA_CFG_EMIT_CHECK)); - dcode->ean.upca_config = 1 << ZEBRA_CFG_EMIT_CHECK; - dcode->ean.upce_config = 1 << ZEBRA_CFG_EMIT_CHECK; - dcode->ean.isbn10_config = 1 << ZEBRA_CFG_EMIT_CHECK; - dcode->ean.isbn13_config = 1 << ZEBRA_CFG_EMIT_CHECK; + dcode->ean.ean13_config = ((1 << ZBAR_CFG_ENABLE) | + (1 << ZBAR_CFG_EMIT_CHECK)); + dcode->ean.ean8_config = ((1 << ZBAR_CFG_ENABLE) | + (1 << ZBAR_CFG_EMIT_CHECK)); + dcode->ean.upca_config = 1 << ZBAR_CFG_EMIT_CHECK; + dcode->ean.upce_config = 1 << ZBAR_CFG_EMIT_CHECK; + dcode->ean.isbn10_config = 1 << ZBAR_CFG_EMIT_CHECK; + dcode->ean.isbn13_config = 1 << ZBAR_CFG_EMIT_CHECK; #endif #ifdef ENABLE_I25 - dcode->i25.config = 1 << ZEBRA_CFG_ENABLE; - CFG(dcode->i25, ZEBRA_CFG_MIN_LEN) = 6; + dcode->i25.config = 1 << ZBAR_CFG_ENABLE; + CFG(dcode->i25, ZBAR_CFG_MIN_LEN) = 6; #endif #ifdef ENABLE_CODE39 - dcode->code39.config = 1 << ZEBRA_CFG_ENABLE; - CFG(dcode->code39, ZEBRA_CFG_MIN_LEN) = 6; + dcode->code39.config = 1 << ZBAR_CFG_ENABLE; + CFG(dcode->code39, ZBAR_CFG_MIN_LEN) = 6; #endif #ifdef ENABLE_CODE128 - dcode->code128.config = 1 << ZEBRA_CFG_ENABLE; + dcode->code128.config = 1 << ZBAR_CFG_ENABLE; #endif #ifdef ENABLE_PDF417 - dcode->pdf417.config = 1 << ZEBRA_CFG_ENABLE; + dcode->pdf417.config = 1 << ZBAR_CFG_ENABLE; #endif - zebra_decoder_reset(dcode); + zbar_decoder_reset(dcode); return(dcode); } -void zebra_decoder_destroy (zebra_decoder_t *dcode) +void zbar_decoder_destroy (zbar_decoder_t *dcode) { if(dcode->buf) free(dcode->buf); free(dcode); } -void zebra_decoder_reset (zebra_decoder_t *dcode) +void zbar_decoder_reset (zbar_decoder_t *dcode) { memset(dcode, 0, (long)&dcode->buf - (long)dcode); #ifdef ENABLE_EAN @@ -101,7 +101,7 @@ void zebra_decoder_reset (zebra_decoder_t *dcode) #endif } -void zebra_decoder_new_scan (zebra_decoder_t *dcode) +void zbar_decoder_new_scan (zbar_decoder_t *dcode) { /* soft reset decoder */ memset(dcode->w, 0, sizeof(dcode->w)); @@ -125,73 +125,73 @@ void zebra_decoder_new_scan (zebra_decoder_t *dcode) } -zebra_color_t zebra_decoder_get_color (const zebra_decoder_t *dcode) +zbar_color_t zbar_decoder_get_color (const zbar_decoder_t *dcode) { return(get_color(dcode)); } -const char *zebra_decoder_get_data (const zebra_decoder_t *dcode) +const char *zbar_decoder_get_data (const zbar_decoder_t *dcode) { return((char*)dcode->buf); } -zebra_decoder_handler_t * -zebra_decoder_set_handler (zebra_decoder_t *dcode, - zebra_decoder_handler_t handler) +zbar_decoder_handler_t * +zbar_decoder_set_handler (zbar_decoder_t *dcode, + zbar_decoder_handler_t handler) { - zebra_decoder_handler_t *result = dcode->handler; + zbar_decoder_handler_t *result = dcode->handler; dcode->handler = handler; return(result); } -void zebra_decoder_set_userdata (zebra_decoder_t *dcode, - void *userdata) +void zbar_decoder_set_userdata (zbar_decoder_t *dcode, + void *userdata) { dcode->userdata = userdata; } -void *zebra_decoder_get_userdata (const zebra_decoder_t *dcode) +void *zbar_decoder_get_userdata (const zbar_decoder_t *dcode) { return(dcode->userdata); } -zebra_symbol_type_t zebra_decoder_get_type (const zebra_decoder_t *dcode) +zbar_symbol_type_t zbar_decoder_get_type (const zbar_decoder_t *dcode) { return(dcode->type); } -zebra_symbol_type_t zebra_decode_width (zebra_decoder_t *dcode, - unsigned w) +zbar_symbol_type_t zbar_decode_width (zbar_decoder_t *dcode, + unsigned w) { dcode->w[dcode->idx & (DECODE_WINDOW - 1)] = w; dprintf(1, " decode[%x]: w=%d (%g)\n", dcode->idx, w, (w / 32.)); /* each decoder processes width stream in parallel */ - zebra_symbol_type_t sym = dcode->type = ZEBRA_NONE; + zbar_symbol_type_t sym = dcode->type = ZBAR_NONE; #ifdef ENABLE_EAN if((dcode->ean.enable) && - (sym = _zebra_decode_ean(dcode))) + (sym = _zbar_decode_ean(dcode))) dcode->type = sym; #endif #ifdef ENABLE_CODE39 - if(TEST_CFG(dcode->code39.config, ZEBRA_CFG_ENABLE) && - (sym = _zebra_decode_code39(dcode)) > ZEBRA_PARTIAL) + if(TEST_CFG(dcode->code39.config, ZBAR_CFG_ENABLE) && + (sym = _zbar_decode_code39(dcode)) > ZBAR_PARTIAL) dcode->type = sym; #endif #ifdef ENABLE_CODE128 - if(TEST_CFG(dcode->code128.config, ZEBRA_CFG_ENABLE) && - (sym = _zebra_decode_code128(dcode)) > ZEBRA_PARTIAL) + if(TEST_CFG(dcode->code128.config, ZBAR_CFG_ENABLE) && + (sym = _zbar_decode_code128(dcode)) > ZBAR_PARTIAL) dcode->type = sym; #endif #ifdef ENABLE_I25 - if(TEST_CFG(dcode->i25.config, ZEBRA_CFG_ENABLE) && - (sym = _zebra_decode_i25(dcode)) > ZEBRA_PARTIAL) + if(TEST_CFG(dcode->i25.config, ZBAR_CFG_ENABLE) && + (sym = _zbar_decode_i25(dcode)) > ZBAR_PARTIAL) dcode->type = sym; #endif #ifdef ENABLE_PDF417 - if(TEST_CFG(dcode->pdf417.config, ZEBRA_CFG_ENABLE) && - (sym = _zebra_decode_pdf417(dcode)) > ZEBRA_PARTIAL) + if(TEST_CFG(dcode->pdf417.config, ZBAR_CFG_ENABLE) && + (sym = _zbar_decode_pdf417(dcode)) > ZBAR_PARTIAL) dcode->type = sym; #endif @@ -199,65 +199,65 @@ zebra_symbol_type_t zebra_decode_width (zebra_decoder_t *dcode, if(dcode->type) { if(dcode->handler) dcode->handler(dcode); - if(dcode->lock && dcode->type > ZEBRA_PARTIAL) + if(dcode->lock && dcode->type > ZBAR_PARTIAL) dcode->lock = 0; } return(dcode->type); } -static inline int decoder_set_config_bool (zebra_decoder_t *dcode, - zebra_symbol_type_t sym, - zebra_config_t cfg, +static inline int decoder_set_config_bool (zbar_decoder_t *dcode, + zbar_symbol_type_t sym, + zbar_config_t cfg, int val) { unsigned *config = NULL; switch(sym) { #ifdef ENABLE_EAN - case ZEBRA_EAN13: + case ZBAR_EAN13: config = &dcode->ean.ean13_config; break; - case ZEBRA_EAN8: + case ZBAR_EAN8: config = &dcode->ean.ean8_config; break; - case ZEBRA_UPCA: + case ZBAR_UPCA: config = &dcode->ean.upca_config; break; - case ZEBRA_UPCE: + case ZBAR_UPCE: config = &dcode->ean.upce_config; break; - case ZEBRA_ISBN10: + case ZBAR_ISBN10: config = &dcode->ean.isbn10_config; break; - case ZEBRA_ISBN13: + case ZBAR_ISBN13: config = &dcode->ean.isbn13_config; break; #endif #ifdef ENABLE_I25 - case ZEBRA_I25: + case ZBAR_I25: config = &dcode->i25.config; break; #endif #ifdef ENABLE_CODE39 - case ZEBRA_CODE39: + case ZBAR_CODE39: config = &dcode->code39.config; break; #endif #ifdef ENABLE_CODE128 - case ZEBRA_CODE128: + case ZBAR_CODE128: config = &dcode->code128.config; break; #endif #ifdef ENABLE_PDF417 - case ZEBRA_PDF417: + case ZBAR_PDF417: config = &dcode->pdf417.config; break; #endif @@ -267,7 +267,7 @@ static inline int decoder_set_config_bool (zebra_decoder_t *dcode, default: return(1); } - if(!config || cfg >= ZEBRA_CFG_NUM) + if(!config || cfg >= ZBAR_CFG_NUM) return(1); if(!val) @@ -284,36 +284,36 @@ static inline int decoder_set_config_bool (zebra_decoder_t *dcode, dcode->ean.upce_config | dcode->ean.isbn10_config | dcode->ean.isbn13_config, - ZEBRA_CFG_ENABLE); + ZBAR_CFG_ENABLE); #endif return(0); } -static inline int decoder_set_config_int (zebra_decoder_t *dcode, - zebra_symbol_type_t sym, - zebra_config_t cfg, +static inline int decoder_set_config_int (zbar_decoder_t *dcode, + zbar_symbol_type_t sym, + zbar_config_t cfg, int val) { switch(sym) { #ifdef ENABLE_I25 - case ZEBRA_I25: + case ZBAR_I25: CFG(dcode->i25, cfg) = val; break; #endif #ifdef ENABLE_CODE39 - case ZEBRA_CODE39: + case ZBAR_CODE39: CFG(dcode->code39, cfg) = val; break; #endif #ifdef ENABLE_CODE128 - case ZEBRA_CODE128: + case ZBAR_CODE128: CFG(dcode->code128, cfg) = val; break; #endif #ifdef ENABLE_PDF417 - case ZEBRA_PDF417: + case ZBAR_PDF417: CFG(dcode->pdf417, cfg) = val; break; #endif @@ -324,28 +324,28 @@ static inline int decoder_set_config_int (zebra_decoder_t *dcode, return(0); } -int zebra_decoder_set_config (zebra_decoder_t *dcode, - zebra_symbol_type_t sym, - zebra_config_t cfg, - int val) +int zbar_decoder_set_config (zbar_decoder_t *dcode, + zbar_symbol_type_t sym, + zbar_config_t cfg, + int val) { - if(sym == ZEBRA_NONE) { - zebra_decoder_set_config(dcode, ZEBRA_EAN13, cfg, val); - zebra_decoder_set_config(dcode, ZEBRA_EAN8, cfg, val); - zebra_decoder_set_config(dcode, ZEBRA_UPCA, cfg, val); - zebra_decoder_set_config(dcode, ZEBRA_UPCE, cfg, val); - zebra_decoder_set_config(dcode, ZEBRA_ISBN10, cfg, val); - zebra_decoder_set_config(dcode, ZEBRA_ISBN13, cfg, val); - zebra_decoder_set_config(dcode, ZEBRA_I25, cfg, val); - zebra_decoder_set_config(dcode, ZEBRA_CODE39, cfg, val); - zebra_decoder_set_config(dcode, ZEBRA_CODE128, cfg, val); - zebra_decoder_set_config(dcode, ZEBRA_PDF417, cfg, val); + if(sym == ZBAR_NONE) { + zbar_decoder_set_config(dcode, ZBAR_EAN13, cfg, val); + zbar_decoder_set_config(dcode, ZBAR_EAN8, cfg, val); + zbar_decoder_set_config(dcode, ZBAR_UPCA, cfg, val); + zbar_decoder_set_config(dcode, ZBAR_UPCE, cfg, val); + zbar_decoder_set_config(dcode, ZBAR_ISBN10, cfg, val); + zbar_decoder_set_config(dcode, ZBAR_ISBN13, cfg, val); + zbar_decoder_set_config(dcode, ZBAR_I25, cfg, val); + zbar_decoder_set_config(dcode, ZBAR_CODE39, cfg, val); + zbar_decoder_set_config(dcode, ZBAR_CODE128, cfg, val); + zbar_decoder_set_config(dcode, ZBAR_PDF417, cfg, val); return(0); } - if(cfg >= 0 && cfg < ZEBRA_CFG_NUM) + if(cfg >= 0 && cfg < ZBAR_CFG_NUM) return(decoder_set_config_bool(dcode, sym, cfg, val)); - else if(cfg >= ZEBRA_CFG_MIN_LEN && cfg <= ZEBRA_CFG_MAX_LEN) + else if(cfg >= ZBAR_CFG_MIN_LEN && cfg <= ZBAR_CFG_MAX_LEN) return(decoder_set_config_int(dcode, sym, cfg, val)); else return(1); @@ -354,8 +354,8 @@ int zebra_decoder_set_config (zebra_decoder_t *dcode, static char *decoder_dump = NULL; -const char *_zebra_decoder_buf_dump (unsigned char *buf, - unsigned int buflen) +const char *_zbar_decoder_buf_dump (unsigned char *buf, + unsigned int buflen) { int dumplen = (buflen * 3) + 12; if(!decoder_dump || dumplen > strlen(decoder_dump)) { diff --git a/zebra/decoder.h b/zbar/decoder.h similarity index 82% rename from zebra/decoder.h rename to zbar/decoder.h index 5ae4fc0..f8ed9b5 100644 --- a/zebra/decoder.h +++ b/zbar/decoder.h @@ -1,33 +1,33 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #ifndef _DECODER_H_ #define _DECODER_H_ #include /* realloc */ -#include +#include -#define NUM_CFGS (ZEBRA_CFG_MAX_LEN - ZEBRA_CFG_MIN_LEN + 1) +#define NUM_CFGS (ZBAR_CFG_MAX_LEN - ZBAR_CFG_MIN_LEN + 1) #ifdef ENABLE_EAN # include "decoder/ean.h" @@ -67,21 +67,21 @@ # define BUFFER_INCR 0x10 #endif -#define CFG(dcode, cfg) ((dcode).configs[(cfg) - ZEBRA_CFG_MIN_LEN]) +#define CFG(dcode, cfg) ((dcode).configs[(cfg) - ZBAR_CFG_MIN_LEN]) #define TEST_CFG(config, cfg) (((config) >> (cfg)) & 1) /* symbology independent decoder state */ -struct zebra_decoder_s { +struct zbar_decoder_s { unsigned char idx; /* current width index */ unsigned w[DECODE_WINDOW]; /* window of last N bar widths */ - zebra_symbol_type_t type; /* type of last decoded data */ + zbar_symbol_type_t type; /* type of last decoded data */ unsigned lock : 1; /* buffer lock */ /* everything above here is automatically reset */ unsigned char *buf; /* decoded characters */ unsigned buflen; /* dynamic buffer allocation */ void *userdata; /* application data */ - zebra_decoder_handler_t *handler; /* application callback */ + zbar_decoder_handler_t *handler; /* application callback */ /* symbology specific state */ #ifdef ENABLE_EAN @@ -102,20 +102,20 @@ struct zebra_decoder_s { }; /* return current element color */ -static inline char get_color (const zebra_decoder_t *dcode) +static inline char get_color (const zbar_decoder_t *dcode) { return(dcode->idx & 1); } /* retrieve i-th previous element width */ -static inline unsigned get_width (const zebra_decoder_t *dcode, +static inline unsigned get_width (const zbar_decoder_t *dcode, unsigned char offset) { return(dcode->w[(dcode->idx - offset) & (DECODE_WINDOW - 1)]); } /* retrieve bar+space pair width starting at offset i */ -static inline unsigned pair_width (const zebra_decoder_t *dcode, +static inline unsigned pair_width (const zbar_decoder_t *dcode, unsigned char offset) { return(get_width(dcode, offset) + get_width(dcode, offset + 1)); @@ -126,7 +126,7 @@ static inline unsigned pair_width (const zebra_decoder_t *dcode, * (<= DECODE_WINDOW - n) * - size of character is n elements */ -static inline unsigned calc_s (const zebra_decoder_t *dcode, +static inline unsigned calc_s (const zbar_decoder_t *dcode, unsigned char offset, unsigned char n) { @@ -160,7 +160,7 @@ static inline int decode_e (unsigned e, } /* acquire shared state lock */ -static inline char get_lock (zebra_decoder_t *dcode) +static inline char get_lock (zbar_decoder_t *dcode) { if(dcode->lock) return(1); @@ -169,7 +169,7 @@ static inline char get_lock (zebra_decoder_t *dcode) } /* ensure output buffer has sufficient allocation for request */ -static inline char size_buf (zebra_decoder_t *dcode, +static inline char size_buf (zbar_decoder_t *dcode, unsigned len) { if(len < dcode->buflen) @@ -190,7 +190,7 @@ static inline char size_buf (zebra_decoder_t *dcode, return(0); } -extern const char *_zebra_decoder_buf_dump (unsigned char *buf, +extern const char *_zbar_decoder_buf_dump (unsigned char *buf, unsigned int buflen); #endif diff --git a/zebra/decoder/code128.c b/zbar/decoder/code128.c similarity index 89% rename from zebra/decoder/code128.c rename to zbar/decoder/code128.c index c3a0028..3dc1120 100644 --- a/zebra/decoder/code128.c +++ b/zbar/decoder/code128.c @@ -1,30 +1,30 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include #include /* memmove */ -#include +#include #include "decoder.h" #ifdef DEBUG_CODE128 @@ -188,7 +188,7 @@ static inline unsigned char calc_check (unsigned char c) return((c < 0x67) ? 0x20 : 0x10); } -static inline signed char decode6 (zebra_decoder_t *dcode) +static inline signed char decode6 (zbar_decoder_t *dcode) { /* build edge signature of character */ unsigned s = dcode->code128.s6; @@ -196,7 +196,7 @@ static inline signed char decode6 (zebra_decoder_t *dcode) if(s < 5) return(-1); /* calculate similar edge measurements */ - int sig = (get_color(dcode) == ZEBRA_BAR) + int sig = (get_color(dcode) == ZBAR_BAR) ? ((decode_e(get_width(dcode, 0) + get_width(dcode, 1), s, 11) << 12) | (decode_e(get_width(dcode, 1) + get_width(dcode, 2), s, 11) << 8) | (decode_e(get_width(dcode, 2) + get_width(dcode, 3), s, 11) << 4) | @@ -214,7 +214,7 @@ static inline signed char decode6 (zebra_decoder_t *dcode) return(-1); /* character validation */ - unsigned bars = (get_color(dcode) == ZEBRA_BAR) + unsigned bars = (get_color(dcode) == ZBAR_BAR) ? (get_width(dcode, 0) + get_width(dcode, 2) + get_width(dcode, 4)) : (get_width(dcode, 1) + get_width(dcode, 3) + get_width(dcode, 5)); bars = bars * 11 * 4 / s; @@ -226,7 +226,7 @@ static inline signed char decode6 (zebra_decoder_t *dcode) return(c & 0x7f); } -static inline unsigned char validate_checksum (zebra_decoder_t *dcode) +static inline unsigned char validate_checksum (zbar_decoder_t *dcode) { code128_decoder_t *dcode128 = &dcode->code128; if(dcode128->character < 3) @@ -243,14 +243,14 @@ static inline unsigned char validate_checksum (zebra_decoder_t *dcode) for(i = dcode128->character - 3; i; i--) { zassert(sum < 103, -1, "dir=%x i=%x sum=%x acc=%x %s\n", dcode128->direction, i, sum, acc, - _zebra_decoder_buf_dump(dcode->buf, dcode128->character)); + _zbar_decoder_buf_dump(dcode->buf, dcode128->character)); idx = (dcode128->direction) ? dcode128->character - 1 - i : i; acc += dcode->buf[idx]; if(acc >= 103) acc -= 103; zassert(acc < 103, -1, "dir=%x i=%x sum=%x acc=%x %s\n", dcode128->direction, i, sum, acc, - _zebra_decoder_buf_dump(dcode->buf, dcode128->character)); + _zbar_decoder_buf_dump(dcode->buf, dcode128->character)); sum += acc; if(sum >= 103) sum -= 103; @@ -267,7 +267,7 @@ static inline unsigned char validate_checksum (zebra_decoder_t *dcode) } /* expand and decode character set C */ -static inline unsigned postprocess_c (zebra_decoder_t *dcode, +static inline unsigned postprocess_c (zbar_decoder_t *dcode, unsigned start, unsigned end, unsigned dst) @@ -305,17 +305,17 @@ static inline unsigned postprocess_c (zebra_decoder_t *dcode, } zassert(dcode->buf[j] <= '9', delta, "start=%x end=%x i=%x j=%x %s\n", start, end, i, j, - _zebra_decoder_buf_dump(dcode->buf, dcode->code128.character)); + _zbar_decoder_buf_dump(dcode->buf, dcode->code128.character)); zassert(code <= 9, delta, "start=%x end=%x i=%x j=%x %s\n", start, end, i, j, - _zebra_decoder_buf_dump(dcode->buf, dcode->code128.character)); + _zbar_decoder_buf_dump(dcode->buf, dcode->code128.character)); dcode->buf[j + 1] = '0' + code; } return(delta); } /* resolve scan direction and convert to ASCII */ -static inline unsigned char postprocess (zebra_decoder_t *dcode) +static inline unsigned char postprocess (zbar_decoder_t *dcode) { code128_decoder_t *dcode128 = &dcode->code128; dprintf(2, "\n postproc len=%d", dcode128->character); @@ -332,16 +332,16 @@ static inline unsigned char postprocess (zebra_decoder_t *dcode) } zassert(dcode->buf[dcode128->character - 1] == STOP_REV, 1, "dir=%x %s\n", dcode128->direction, - _zebra_decoder_buf_dump(dcode->buf, dcode->code128.character)); + _zbar_decoder_buf_dump(dcode->buf, dcode->code128.character)); } else zassert(dcode->buf[dcode128->character - 1] == STOP_FWD, 1, "dir=%x %s\n", dcode128->direction, - _zebra_decoder_buf_dump(dcode->buf, dcode->code128.character)); + _zbar_decoder_buf_dump(dcode->buf, dcode->code128.character)); code = dcode->buf[0]; zassert(code >= START_A && code <= START_C, 1, "%s\n", - _zebra_decoder_buf_dump(dcode->buf, dcode->code128.character)); + _zbar_decoder_buf_dump(dcode->buf, dcode->code128.character)); unsigned char charset = code - START_A; unsigned cexp = (code == START_C) ? 1 : 0; @@ -352,7 +352,7 @@ static inline unsigned char postprocess (zebra_decoder_t *dcode) zassert(!(code & 0x80), 1, "i=%x j=%x code=%02x charset=%x cexp=%x %s\n", i, j, code, charset, cexp, - _zebra_decoder_buf_dump(dcode->buf, dcode->code128.character)); + _zbar_decoder_buf_dump(dcode->buf, dcode->code128.character)); if((charset & 0x2) && (code < 100)) /* defer character set C for expansion */ @@ -373,7 +373,7 @@ static inline unsigned char postprocess (zebra_decoder_t *dcode) /* expand character set C to ASCII */ zassert(cexp, 1, "i=%x j=%x code=%02x charset=%x cexp=%x %s\n", i, j, code, charset, cexp, - _zebra_decoder_buf_dump(dcode->buf, + _zbar_decoder_buf_dump(dcode->buf, dcode->code128.character)); unsigned delta = postprocess_c(dcode, cexp, i, j); i += delta; @@ -398,7 +398,7 @@ static inline unsigned char postprocess (zebra_decoder_t *dcode) zassert(code >= CODE_C && code <= CODE_A, 1, "i=%x j=%x code=%02x charset=%x cexp=%x %s\n", i, j, code, charset, cexp, - _zebra_decoder_buf_dump(dcode->buf, + _zbar_decoder_buf_dump(dcode->buf, dcode->code128.character)); unsigned char newset = CODE_A - code; if(newset != charset) @@ -413,7 +413,7 @@ static inline unsigned char postprocess (zebra_decoder_t *dcode) if(charset & 0x2) { zassert(cexp, 1, "i=%x j=%x code=%02x charset=%x cexp=%x %s\n", i, j, code, charset, cexp, - _zebra_decoder_buf_dump(dcode->buf, + _zbar_decoder_buf_dump(dcode->buf, dcode->code128.character)); j += postprocess_c(dcode, cexp, i, j) * 2; } @@ -422,7 +422,7 @@ static inline unsigned char postprocess (zebra_decoder_t *dcode) return(0); } -zebra_symbol_type_t _zebra_decode_code128 (zebra_decoder_t *dcode) +zbar_symbol_type_t _zbar_decode_code128 (zbar_decoder_t *dcode) { code128_decoder_t *dcode128 = &dcode->code128; @@ -459,11 +459,11 @@ zebra_symbol_type_t _zebra_decode_code128 (zebra_decoder_t *dcode) /* initialize state */ dcode128->character = 0; if(c == STOP_REV) { - dcode128->direction = ZEBRA_BAR; + dcode128->direction = ZBAR_BAR; dcode128->element = 7; } else - dcode128->direction = ZEBRA_SPACE; + dcode128->direction = ZBAR_SPACE; dprintf(2, " dir=%x [valid start]", dcode128->direction); } else if((c < 0) || @@ -478,7 +478,7 @@ zebra_symbol_type_t _zebra_decode_code128 (zebra_decoder_t *dcode) zassert(dcode->buflen > dcode128->character, 0, "buflen=%x idx=%x c=%02x %s\n", dcode->buflen, dcode128->character, c, - _zebra_decoder_buf_dump(dcode->buf, dcode->buflen)); + _zbar_decoder_buf_dump(dcode->buf, dcode->buflen)); dcode->buf[dcode128->character++] = c; @@ -487,14 +487,14 @@ zebra_symbol_type_t _zebra_decode_code128 (zebra_decoder_t *dcode) ? c >= START_A && c <= START_C : c == STOP_FWD)) { /* FIXME STOP_FWD should check extra bar (and QZ!) */ - zebra_symbol_type_t sym = ZEBRA_CODE128; + zbar_symbol_type_t sym = ZBAR_CODE128; if(validate_checksum(dcode) || postprocess(dcode)) - sym = ZEBRA_NONE; - else if(dcode128->character < CFG(*dcode128, ZEBRA_CFG_MIN_LEN) || - (CFG(*dcode128, ZEBRA_CFG_MAX_LEN) > 0 && - dcode128->character > CFG(*dcode128, ZEBRA_CFG_MAX_LEN))) { + sym = ZBAR_NONE; + else if(dcode128->character < CFG(*dcode128, ZBAR_CFG_MIN_LEN) || + (CFG(*dcode128, ZBAR_CFG_MAX_LEN) > 0 && + dcode128->character > CFG(*dcode128, ZBAR_CFG_MAX_LEN))) { dprintf(2, " [invalid len]\n"); - sym = ZEBRA_NONE; + sym = ZBAR_NONE; } else dprintf(2, " [valid end]\n"); diff --git a/zebra/decoder/code128.h b/zbar/decoder/code128.h similarity index 76% rename from zebra/decoder/code128.h rename to zbar/decoder/code128.h index 2eb3d58..6e5153a 100644 --- a/zebra/decoder/code128.h +++ b/zbar/decoder/code128.h @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #ifndef _CODE128_H_ #define _CODE128_H_ @@ -44,6 +44,6 @@ static inline void code128_reset (code128_decoder_t *dcode128) } /* decode Code 128 symbols */ -zebra_symbol_type_t _zebra_decode_code128(zebra_decoder_t *dcode); +zbar_symbol_type_t _zbar_decode_code128(zbar_decoder_t *dcode); #endif diff --git a/zebra/decoder/code39.c b/zbar/decoder/code39.c similarity index 86% rename from zebra/decoder/code39.c rename to zbar/decoder/code39.c index 0d36883..2edb262 100644 --- a/zebra/decoder/code39.c +++ b/zbar/decoder/code39.c @@ -1,30 +1,30 @@ /*------------------------------------------------------------------------ - * Copyright 2008 (c) Jeff Brown + * Copyright 2008-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include #include /* memmove */ -#include +#include #include "decoder.h" #ifdef DEBUG_CODE39 @@ -143,7 +143,7 @@ static inline unsigned char code39_decode1 (unsigned char enc, return(enc); } -static inline signed char code39_decode9 (zebra_decoder_t *dcode) +static inline signed char code39_decode9 (zbar_decoder_t *dcode) { code39_decoder_t *dcode39 = &dcode->code39; @@ -189,7 +189,7 @@ static inline signed char code39_decode9 (zebra_decoder_t *dcode) return((dcode39->direction) ? c->rev : c->fwd); } -static inline signed char code39_decode_start (zebra_decoder_t *dcode) +static inline signed char code39_decode_start (zbar_decoder_t *dcode) { code39_decoder_t *dcode39 = &dcode->code39; @@ -198,7 +198,7 @@ static inline signed char code39_decode_start (zebra_decoder_t *dcode) dcode39->direction ^= 1; else if(c != 0x2b) { dprintf(2, "\n"); - return(ZEBRA_NONE); + return(ZBAR_NONE); } /* check leading quiet zone - spec is 10x, we require at least 3x */ @@ -206,16 +206,16 @@ static inline signed char code39_decode_start (zebra_decoder_t *dcode) if(quiet && get_width(dcode, 10) && quiet < dcode39->s9 / 4) { dprintf(2, " [invalid quiet]\n"); - return(ZEBRA_NONE); + return(ZBAR_NONE); } dcode39->element = 9; dcode39->character = 0; dprintf(1, " dir=%x [valid start]\n", dcode39->direction); - return(ZEBRA_PARTIAL); + return(ZBAR_PARTIAL); } -static inline void code39_postprocess (zebra_decoder_t *dcode) +static inline void code39_postprocess (zbar_decoder_t *dcode) { code39_decoder_t *dcode39 = &dcode->code39; int i; @@ -236,7 +236,7 @@ static inline void code39_postprocess (zebra_decoder_t *dcode) dcode->buf[i] = '\0'; } -zebra_symbol_type_t _zebra_decode_code39 (zebra_decoder_t *dcode) +zbar_symbol_type_t _zbar_decode_code39 (zbar_decoder_t *dcode) { code39_decoder_t *dcode39 = &dcode->code39; @@ -245,14 +245,14 @@ zebra_symbol_type_t _zebra_decode_code39 (zebra_decoder_t *dcode) dcode39->s9 += get_width(dcode, 0); if(dcode39->character < 0) { - if(get_color(dcode) != ZEBRA_BAR) - return(ZEBRA_NONE); + if(get_color(dcode) != ZBAR_BAR) + return(ZBAR_NONE); dprintf(2, " code39:"); return(code39_decode_start(dcode)); } if(++dcode39->element < 9) - return(ZEBRA_NONE); + return(ZBAR_NONE); dprintf(2, " code39[%c%02d+%x]", (dcode39->direction) ? '<' : '>', @@ -264,18 +264,18 @@ zebra_symbol_type_t _zebra_decode_code39 (zebra_decoder_t *dcode) dcode->buf[dcode39->character - 1] == 0x2b) { /* STOP */ /* trim STOP character */ dcode39->character--; - zebra_symbol_type_t sym = ZEBRA_CODE39; + zbar_symbol_type_t sym = ZBAR_CODE39; /* trailing quiet zone check */ if(space < dcode39->width / 4) { dprintf(2, " [invalid qz]\n"); - sym = ZEBRA_NONE; + sym = ZBAR_NONE; } - else if(dcode39->character < CFG(*dcode39, ZEBRA_CFG_MIN_LEN) || - (CFG(*dcode39, ZEBRA_CFG_MAX_LEN) > 0 && - dcode39->character > CFG(*dcode39, ZEBRA_CFG_MAX_LEN))) { + else if(dcode39->character < CFG(*dcode39, ZBAR_CFG_MIN_LEN) || + (CFG(*dcode39, ZBAR_CFG_MAX_LEN) > 0 && + dcode39->character > CFG(*dcode39, ZBAR_CFG_MAX_LEN))) { dprintf(2, " [invalid len]\n"); - sym = ZEBRA_NONE; + sym = ZBAR_NONE; } else { /* FIXME checksum (needs config enable) */ @@ -295,7 +295,7 @@ zebra_symbol_type_t _zebra_decode_code39 (zebra_decoder_t *dcode) } dcode39->element = 0; dprintf(2, "\n"); - return(ZEBRA_NONE); + return(ZBAR_NONE); } signed char c = code39_decode9(dcode); @@ -305,7 +305,7 @@ zebra_symbol_type_t _zebra_decode_code39 (zebra_decoder_t *dcode) if(!dcode39->character && get_lock(dcode)) { dcode39->character = -1; dprintf(1, " [locked]\n"); - return(ZEBRA_PARTIAL); + return(ZBAR_PARTIAL); } if(c < 0 || @@ -314,14 +314,14 @@ zebra_symbol_type_t _zebra_decode_code39 (zebra_decoder_t *dcode) dprintf(1, (c < 0) ? " [aborted]\n" : " [overflow]\n"); dcode->lock = 0; dcode39->character = -1; - return(ZEBRA_NONE); + return(ZBAR_NONE); } else { - zassert(c < 0x2c, ZEBRA_NONE, "c=%02x s9=%x\n", c, dcode39->s9); + zassert(c < 0x2c, ZBAR_NONE, "c=%02x s9=%x\n", c, dcode39->s9); dprintf(2, "\n"); } dcode->buf[dcode39->character++] = c; - return(ZEBRA_NONE); + return(ZBAR_NONE); } diff --git a/zebra/decoder/code39.h b/zbar/decoder/code39.h similarity index 77% rename from zebra/decoder/code39.h rename to zbar/decoder/code39.h index 00b006f..9b2356f 100644 --- a/zebra/decoder/code39.h +++ b/zbar/decoder/code39.h @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ - * Copyright 2008 (c) Jeff Brown + * Copyright 2008-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #ifndef _CODE39_H_ #define _CODE39_H_ @@ -45,6 +45,6 @@ static inline void code39_reset (code39_decoder_t *dcode39) } /* decode Code 39 symbols */ -zebra_symbol_type_t _zebra_decode_code39(zebra_decoder_t *dcode); +zbar_symbol_type_t _zbar_decode_code39(zbar_decoder_t *dcode); #endif diff --git a/zebra/decoder/ean.c b/zbar/decoder/ean.c similarity index 77% rename from zebra/decoder/ean.c rename to zbar/decoder/ean.c index 2849fa4..2ef22f0 100644 --- a/zebra/decoder/ean.c +++ b/zbar/decoder/ean.c @@ -1,28 +1,28 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include -#include +#include #include "decoder.h" #ifdef DEBUG_EAN @@ -112,7 +112,7 @@ static inline const unsigned char *dsprintbuf(ean_decoder_t *ean) /* evaluate previous N (>= 2) widths as auxiliary pattern, * using preceding 4 as character width */ -static inline signed char aux_end (zebra_decoder_t *dcode, +static inline signed char aux_end (zbar_decoder_t *dcode, unsigned char fwd) { /* reference width from previous character */ @@ -143,19 +143,19 @@ static inline signed char aux_end (zebra_decoder_t *dcode, /* determine possible auxiliary pattern * using current 4 as possible character */ -static inline signed char aux_start (zebra_decoder_t *dcode) +static inline signed char aux_start (zbar_decoder_t *dcode) { /* FIXME NB add-on has no guard in reverse */ unsigned e2 = get_width(dcode, 5) + get_width(dcode, 6); if(decode_e(e2, dcode->ean.s4, 7)) { dprintf(2, " [invalid any]"); - return(/*FIXME (get_color(dcode) == ZEBRA_SPACE) ? STATE_ADDON : */-1); + return(/*FIXME (get_color(dcode) == ZBAR_SPACE) ? STATE_ADDON : */-1); } unsigned e1 = get_width(dcode, 4) + get_width(dcode, 5); unsigned char E1 = decode_e(e1, dcode->ean.s4, 7); - if(get_color(dcode) == ZEBRA_BAR) { + if(get_color(dcode) == ZBAR_BAR) { /* check for quiet-zone */ if((get_width(dcode, 7) * 14 + 1) / dcode->ean.s4 >= 3) { if(!E1) { @@ -184,10 +184,10 @@ static inline signed char aux_start (zebra_decoder_t *dcode) } /* attempt to decode previous 4 widths (2 bars and 2 spaces) as a character */ -static inline signed char decode4 (zebra_decoder_t *dcode) +static inline signed char decode4 (zbar_decoder_t *dcode) { /* calculate similar edge measurements */ - unsigned e1 = ((get_color(dcode) == ZEBRA_BAR) + unsigned e1 = ((get_color(dcode) == ZBAR_BAR) ? get_width(dcode, 0) + get_width(dcode, 1) : get_width(dcode, 2) + get_width(dcode, 3)); unsigned e2 = get_width(dcode, 1) + get_width(dcode, 2); @@ -208,7 +208,7 @@ static inline signed char decode4 (zebra_decoder_t *dcode) */ if((1 << code) & 0x0660) { /* use sum of bar widths */ - unsigned d2 = ((get_color(dcode) == ZEBRA_BAR) + unsigned d2 = ((get_color(dcode) == ZBAR_BAR) ? get_width(dcode, 0) + get_width(dcode, 2) : get_width(dcode, 1) + get_width(dcode, 3)); d2 *= 7; @@ -226,8 +226,8 @@ static inline signed char decode4 (zebra_decoder_t *dcode) return(code); } -static inline zebra_symbol_type_t ean_part_end4 (ean_pass_t *pass, - unsigned char fwd) +static inline zbar_symbol_type_t ean_part_end4 (ean_pass_t *pass, + unsigned char fwd) { /* extract parity bits */ unsigned char par = ((pass->raw[1] & 0x10) >> 1 | @@ -238,7 +238,7 @@ static inline zebra_symbol_type_t ean_part_end4 (ean_pass_t *pass, dprintf(2, " par=%x", par); if(par && par != 0xf) /* invalid parity combination */ - return(ZEBRA_NONE); + return(ZBAR_NONE); if(!par == fwd) { /* reverse sampled digits */ @@ -255,13 +255,13 @@ static inline zebra_symbol_type_t ean_part_end4 (ean_pass_t *pass, pass->raw[1] & 0xf, pass->raw[2] & 0xf, pass->raw[3] & 0xf, pass->raw[4] & 0xf); if(!par) - return(ZEBRA_EAN8 | EAN_RIGHT); - return(ZEBRA_EAN8 | EAN_LEFT); + return(ZBAR_EAN8 | EAN_RIGHT); + return(ZBAR_EAN8 | EAN_LEFT); } -static inline zebra_symbol_type_t ean_part_end7 (ean_decoder_t *ean, - ean_pass_t *pass, - unsigned char fwd) +static inline zbar_symbol_type_t ean_part_end7 (ean_decoder_t *ean, + ean_pass_t *pass, + unsigned char fwd) { /* calculate parity index */ unsigned char par = ((fwd) @@ -287,7 +287,7 @@ static inline zebra_symbol_type_t ean_part_end7 (ean_decoder_t *ean, if(pass->raw[0] == 0xf) /* invalid parity combination */ - return(ZEBRA_NONE); + return(ZBAR_NONE); if(!par == fwd) { /* reverse sampled digits */ @@ -306,32 +306,32 @@ static inline zebra_symbol_type_t ean_part_end7 (ean_decoder_t *ean, pass->raw[4] & 0xf, pass->raw[5] & 0xf, pass->raw[6] & 0xf, par); - if(TEST_CFG(ean->ean13_config, ZEBRA_CFG_ENABLE)) { + if(TEST_CFG(ean->ean13_config, ZBAR_CFG_ENABLE)) { if(!par) - return(ZEBRA_EAN13 | EAN_RIGHT); + return(ZBAR_EAN13 | EAN_RIGHT); if(par & 0x20) - return(ZEBRA_EAN13 | EAN_LEFT); + return(ZBAR_EAN13 | EAN_LEFT); } if(par && !(par & 0x20)) - return(ZEBRA_UPCE); + return(ZBAR_UPCE); - return(ZEBRA_NONE); + return(ZBAR_NONE); } /* update state for one of 4 parallel passes */ -static inline zebra_symbol_type_t decode_pass (zebra_decoder_t *dcode, - ean_pass_t *pass) +static inline zbar_symbol_type_t decode_pass (zbar_decoder_t *dcode, + ean_pass_t *pass) { pass->state++; unsigned char idx = pass->state & STATE_IDX; unsigned char fwd = pass->state & 1; - if(get_color(dcode) == ZEBRA_SPACE && + if(get_color(dcode) == ZBAR_SPACE && (idx == 0x10 || idx == 0x11) && - TEST_CFG(dcode->ean.ean8_config, ZEBRA_CFG_ENABLE) && + TEST_CFG(dcode->ean.ean8_config, ZBAR_CFG_ENABLE) && !aux_end(dcode, fwd)) { dprintf(2, " fwd=%x", fwd); - zebra_symbol_type_t part = ean_part_end4(pass, fwd); + zbar_symbol_type_t part = ean_part_end4(pass, fwd); pass->state = -1; return(part); } @@ -361,9 +361,9 @@ static inline zebra_symbol_type_t decode_pass (zebra_decoder_t *dcode, } } - if(get_color(dcode) == ZEBRA_SPACE && + if(get_color(dcode) == ZBAR_SPACE && (idx == 0x18 || idx == 0x19)) { - zebra_symbol_type_t part = ZEBRA_NONE; + zbar_symbol_type_t part = ZBAR_NONE; dprintf(2, " fwd=%x", fwd); if(!aux_end(dcode, fwd)) part = ean_part_end7(&dcode->ean, pass, fwd); @@ -381,7 +381,7 @@ static inline signed char ean_verify_checksum (ean_decoder_t *ean, for(i = 0; i < n; i++) { unsigned char d = ean->buf[i]; zassert(d < 10, -1, "i=%x d=%x chk=%x %s\n", i, d, chk, - _zebra_decoder_buf_dump((void*)ean->buf, 18)); + _zbar_decoder_buf_dump((void*)ean->buf, 18)); chk += d; if((i ^ n) & 1) { chk += d << 1; @@ -392,12 +392,12 @@ static inline signed char ean_verify_checksum (ean_decoder_t *ean, chk -= 10; } zassert(chk < 10, -1, "chk=%x n=%x %s", chk, n, - _zebra_decoder_buf_dump((void*)ean->buf, 18)); + _zbar_decoder_buf_dump((void*)ean->buf, 18)); if(chk) chk = 10 - chk; unsigned char d = ean->buf[n]; zassert(d < 10, -1, "n=%x d=%x chk=%x %s\n", n, d, chk, - _zebra_decoder_buf_dump((void*)ean->buf, 18)); + _zbar_decoder_buf_dump((void*)ean->buf, 18)); if(chk != d) { dprintf(1, "\nchecksum mismatch %d != %d (%s)\n", chk, d, dsprintbuf(ean)); @@ -413,7 +413,7 @@ static inline unsigned char isbn10_calc_checksum (ean_decoder_t *ean) for(w = 10; w > 1; w--) { unsigned char d = ean->buf[13 - w]; zassert(d < 10, '?', "w=%x d=%x chk=%x %s\n", w, d, chk, - _zebra_decoder_buf_dump((void*)ean->buf, 18)); + _zbar_decoder_buf_dump((void*)ean->buf, 18)); chk += d * w; } chk = chk % 11; @@ -447,93 +447,93 @@ static inline void ean_expand_upce (ean_decoder_t *ean, ean->buf[11] = (decode < 5) ? pass->raw[i++] & 0xf : decode; } -static inline zebra_symbol_type_t integrate_partial (ean_decoder_t *ean, - ean_pass_t *pass, - zebra_symbol_type_t part) +static inline zbar_symbol_type_t integrate_partial (ean_decoder_t *ean, + ean_pass_t *pass, + zbar_symbol_type_t part) { /* copy raw data into holding buffer */ /* if same partial is not consistent, reset others */ dprintf(2, " integrate part=%x (%s)", part, dsprintbuf(ean)); signed char i, j; - if(part & ZEBRA_ADDON) { + if(part & ZBAR_ADDON) { /* FIXME TBD */ - for(i = (part == ZEBRA_ADDON5) ? 4 : 1; i >= 0; i--) { + for(i = (part == ZBAR_ADDON5) ? 4 : 1; i >= 0; i--) { unsigned char digit = pass->raw[i] & 0xf; if(ean->addon && ean->buf[i + 13] != digit) { /* partial mismatch - reset collected parts */ - ean->left = ean->right = ean->addon = ZEBRA_NONE; + ean->left = ean->right = ean->addon = ZBAR_NONE; } ean->buf[i + 13] = digit; } ean->addon = part; } else { - if((ean->left && ((part & ZEBRA_SYMBOL) != ean->left)) || - (ean->right && ((part & ZEBRA_SYMBOL) != ean->right))) { + if((ean->left && ((part & ZBAR_SYMBOL) != ean->left)) || + (ean->right && ((part & ZBAR_SYMBOL) != ean->right))) { /* partial mismatch - reset collected parts */ dprintf(2, " rst(type %x %x)", ean->left, ean->right); - ean->left = ean->right = ean->addon = ZEBRA_NONE; + ean->left = ean->right = ean->addon = ZBAR_NONE; } if(part & EAN_RIGHT) { - part &= ZEBRA_SYMBOL; - j = (part == ZEBRA_EAN13) ? 12 : 7; - for(i = (part == ZEBRA_EAN13) ? 6 : 4; i; i--, j--) { + part &= ZBAR_SYMBOL; + j = (part == ZBAR_EAN13) ? 12 : 7; + for(i = (part == ZBAR_EAN13) ? 6 : 4; i; i--, j--) { unsigned char digit = pass->raw[i] & 0xf; if(ean->right && ean->buf[j] != digit) { /* partial mismatch - reset collected parts */ dprintf(2, " rst(right)"); - ean->left = ean->right = ean->addon = ZEBRA_NONE; + ean->left = ean->right = ean->addon = ZBAR_NONE; } ean->buf[j] = digit; } ean->right = part; } - else if(part != ZEBRA_UPCE) /* EAN_LEFT */ { - j = (part == ZEBRA_EAN13) ? 6 : 3; - for(i = (part == ZEBRA_EAN13) ? 6 : 4; j >= 0; i--, j--) { + else if(part != ZBAR_UPCE) /* EAN_LEFT */ { + j = (part == ZBAR_EAN13) ? 6 : 3; + for(i = (part == ZBAR_EAN13) ? 6 : 4; j >= 0; i--, j--) { unsigned char digit = pass->raw[i] & 0xf; if(ean->left && ean->buf[j] != digit) { /* partial mismatch - reset collected parts */ dprintf(2, " rst(left)"); - ean->left = ean->right = ean->addon = ZEBRA_NONE; + ean->left = ean->right = ean->addon = ZBAR_NONE; } ean->buf[j] = digit; } ean->left = part; } - else /* ZEBRA_UPCE */ + else /* ZBAR_UPCE */ ean_expand_upce(ean, pass); } - if((part & ZEBRA_SYMBOL) != ZEBRA_UPCE) { + if((part & ZBAR_SYMBOL) != ZBAR_UPCE) { part = (ean->left & ean->right); if(!part) - part = ZEBRA_PARTIAL; + part = ZBAR_PARTIAL; } - if(((part == ZEBRA_EAN13 || - part == ZEBRA_UPCE) && ean_verify_checksum(ean, 12)) || - (part == ZEBRA_EAN8 && ean_verify_checksum(ean, 7))) + if(((part == ZBAR_EAN13 || + part == ZBAR_UPCE) && ean_verify_checksum(ean, 12)) || + (part == ZBAR_EAN8 && ean_verify_checksum(ean, 7))) /* invalid parity */ - part = ZEBRA_NONE; + part = ZBAR_NONE; - if(part == ZEBRA_EAN13) { + if(part == ZBAR_EAN13) { /* special case EAN-13 subsets */ - if(!ean->buf[0] && TEST_CFG(ean->upca_config, ZEBRA_CFG_ENABLE)) - part = ZEBRA_UPCA; + if(!ean->buf[0] && TEST_CFG(ean->upca_config, ZBAR_CFG_ENABLE)) + part = ZBAR_UPCA; else if(ean->buf[0] == 9 && ean->buf[1] == 7) { /* ISBN-10 has priority over ISBN-13(?) */ if(ean->buf[2] == 8 && - TEST_CFG(ean->isbn10_config, ZEBRA_CFG_ENABLE)) - part = ZEBRA_ISBN10; + TEST_CFG(ean->isbn10_config, ZBAR_CFG_ENABLE)) + part = ZBAR_ISBN10; else if((ean->buf[2] == 8 || ean->buf[2] == 9) && - TEST_CFG(ean->isbn13_config, ZEBRA_CFG_ENABLE)) - part = ZEBRA_ISBN13; + TEST_CFG(ean->isbn13_config, ZBAR_CFG_ENABLE)) + part = ZBAR_ISBN13; } } - else if(part == ZEBRA_UPCE) { - if(TEST_CFG(ean->upce_config, ZEBRA_CFG_ENABLE)) { + else if(part == ZBAR_UPCE) { + if(TEST_CFG(ean->upce_config, ZBAR_CFG_ENABLE)) { /* UPC-E was decompressed for checksum verification, * but user requested compressed result */ @@ -542,16 +542,16 @@ static inline zebra_symbol_type_t integrate_partial (ean_decoder_t *ean, ean->buf[i] = pass->raw[i - 1] & 0xf; ean->buf[i] = pass->raw[0] & 0xf; } - else if(TEST_CFG(ean->upca_config, ZEBRA_CFG_ENABLE)) + else if(TEST_CFG(ean->upca_config, ZBAR_CFG_ENABLE)) /* UPC-E reported as UPC-A has priority over EAN-13 */ - part = ZEBRA_UPCA; - else if(TEST_CFG(ean->ean13_config, ZEBRA_CFG_ENABLE)) - part = ZEBRA_EAN13; + part = ZBAR_UPCA; + else if(TEST_CFG(ean->ean13_config, ZBAR_CFG_ENABLE)) + part = ZBAR_EAN13; else - part = ZEBRA_NONE; + part = ZBAR_NONE; } - if(part > ZEBRA_PARTIAL) + if(part > ZBAR_PARTIAL) part |= ean->addon; dprintf(2, " %x/%x=%x", ean->left, ean->right, part); @@ -559,46 +559,46 @@ static inline zebra_symbol_type_t integrate_partial (ean_decoder_t *ean, } /* copy result to output buffer */ -static inline void postprocess (zebra_decoder_t *dcode, - zebra_symbol_type_t sym) +static inline void postprocess (zbar_decoder_t *dcode, + zbar_symbol_type_t sym) { ean_decoder_t *ean = &dcode->ean; - zebra_symbol_type_t base = sym & ZEBRA_SYMBOL; + zbar_symbol_type_t base = sym & ZBAR_SYMBOL; int i = 0, j = 0; - if(base > ZEBRA_PARTIAL) { - if(base == ZEBRA_UPCA) + if(base > ZBAR_PARTIAL) { + if(base == ZBAR_UPCA) i = 1; - else if(base == ZEBRA_UPCE) { + else if(base == ZBAR_UPCE) { i = 1; base--; } - else if(base == ZEBRA_ISBN13) - base = ZEBRA_EAN13; - else if(base == ZEBRA_ISBN10) + else if(base == ZBAR_ISBN13) + base = ZBAR_EAN13; + else if(base == ZBAR_ISBN10) i = 3; - if(base == ZEBRA_ISBN10 || - !TEST_CFG(ean_get_config(ean, sym), ZEBRA_CFG_EMIT_CHECK)) + if(base == ZBAR_ISBN10 || + !TEST_CFG(ean_get_config(ean, sym), ZBAR_CFG_EMIT_CHECK)) base--; for(; j < base && ean->buf[i] >= 0; i++, j++) dcode->buf[j] = ean->buf[i] + '0'; - if((sym & ZEBRA_SYMBOL) == ZEBRA_ISBN10 && j == 9 && - TEST_CFG(ean->isbn10_config, ZEBRA_CFG_EMIT_CHECK)) + if((sym & ZBAR_SYMBOL) == ZBAR_ISBN10 && j == 9 && + TEST_CFG(ean->isbn10_config, ZBAR_CFG_EMIT_CHECK)) /* recalculate ISBN-10 check digit */ dcode->buf[j++] = isbn10_calc_checksum(ean); } - if(sym & ZEBRA_ADDON) + if(sym & ZBAR_ADDON) for(i = 13; ean->buf[i] >= 0; i++, j++) dcode->buf[j] = ean->buf[i] + '0'; dcode->buf[j] = '\0'; } -zebra_symbol_type_t _zebra_decode_ean (zebra_decoder_t *dcode) +zbar_symbol_type_t _zbar_decode_ean (zbar_decoder_t *dcode) { /* process upto 4 separate passes */ - zebra_symbol_type_t sym = ZEBRA_NONE; + zbar_symbol_type_t sym = ZBAR_NONE; unsigned char pass_idx = dcode->idx & 3; /* update latest character width */ @@ -613,7 +613,7 @@ zebra_symbol_type_t _zebra_decode_ean (zebra_decoder_t *dcode) { dprintf(2, " ean[%x/%x]: idx=%x st=%d s=%d", pass_idx, i, dcode->idx, pass->state, dcode->ean.s4); - zebra_symbol_type_t part = decode_pass(dcode, pass); + zbar_symbol_type_t part = decode_pass(dcode, pass); if(part) { /* update accumulated data from new partial decode */ sym = integrate_partial(&dcode->ean, pass, part); @@ -622,12 +622,12 @@ zebra_symbol_type_t _zebra_decode_ean (zebra_decoder_t *dcode) dprintf(2, " sym=%x", sym); dcode->ean.pass[0].state = dcode->ean.pass[1].state = -1; dcode->ean.pass[2].state = dcode->ean.pass[3].state = -1; - if(sym > ZEBRA_PARTIAL) { + if(sym > ZBAR_PARTIAL) { if(!get_lock(dcode)) postprocess(dcode, sym); else { dprintf(1, " [locked]"); - sym = ZEBRA_PARTIAL; + sym = ZBAR_PARTIAL; } } } diff --git a/zebra/decoder/ean.h b/zbar/decoder/ean.h similarity index 66% rename from zebra/decoder/ean.h rename to zbar/decoder/ean.h index cb57f3c..183b841 100644 --- a/zebra/decoder/ean.h +++ b/zbar/decoder/ean.h @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #ifndef _EAN_H_ #define _EAN_H_ @@ -34,9 +34,9 @@ typedef struct ean_pass_s { /* EAN/UPC specific decode state */ typedef struct ean_decoder_s { ean_pass_t pass[4]; /* state of each parallel decode attempt */ - zebra_symbol_type_t left; /* current holding buffer contents */ - zebra_symbol_type_t right; - zebra_symbol_type_t addon; + zbar_symbol_type_t left; /* current holding buffer contents */ + zbar_symbol_type_t right; + zbar_symbol_type_t addon; unsigned s4; /* character width */ signed char buf[18]; /* holding buffer */ @@ -61,24 +61,24 @@ static inline void ean_new_scan (ean_decoder_t *ean) static inline void ean_reset (ean_decoder_t *ean) { ean_new_scan(ean); - ean->left = ean->right = ean->addon = ZEBRA_NONE; + ean->left = ean->right = ean->addon = ZBAR_NONE; } static inline unsigned ean_get_config (ean_decoder_t *ean, - zebra_symbol_type_t sym) + zbar_symbol_type_t sym) { - switch(sym & ZEBRA_SYMBOL) { - case ZEBRA_EAN13: return(ean->ean13_config); - case ZEBRA_EAN8: return(ean->ean8_config); - case ZEBRA_UPCA: return(ean->upca_config); - case ZEBRA_UPCE: return(ean->upce_config); - case ZEBRA_ISBN10: return(ean->isbn10_config); - case ZEBRA_ISBN13: return(ean->isbn13_config); + switch(sym & ZBAR_SYMBOL) { + case ZBAR_EAN13: return(ean->ean13_config); + case ZBAR_EAN8: return(ean->ean8_config); + case ZBAR_UPCA: return(ean->upca_config); + case ZBAR_UPCE: return(ean->upce_config); + case ZBAR_ISBN10: return(ean->isbn10_config); + case ZBAR_ISBN13: return(ean->isbn13_config); default: return(0); } } /* decode EAN/UPC symbols */ -zebra_symbol_type_t _zebra_decode_ean(zebra_decoder_t *dcode); +zbar_symbol_type_t _zbar_decode_ean(zbar_decoder_t *dcode); #endif diff --git a/zebra/decoder/i25.c b/zbar/decoder/i25.c similarity index 80% rename from zebra/decoder/i25.c rename to zbar/decoder/i25.c index 588eb84..ffa0e3d 100644 --- a/zebra/decoder/i25.c +++ b/zbar/decoder/i25.c @@ -1,30 +1,30 @@ /*------------------------------------------------------------------------ - * Copyright 2008 (c) Jeff Brown + * Copyright 2008-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include #include /* memmove */ -#include +#include #include "decoder.h" #ifdef DEBUG_I25 @@ -45,7 +45,7 @@ static inline unsigned char i25_decode1 (unsigned char enc, return(enc); } -static inline unsigned char i25_decode10 (zebra_decoder_t *dcode, +static inline unsigned char i25_decode10 (zbar_decoder_t *dcode, unsigned char offset) { i25_decoder_t *dcode25 = &dcode->i25; @@ -88,11 +88,11 @@ static inline unsigned char i25_decode10 (zebra_decoder_t *dcode, return(enc); } -static inline signed char i25_decode_start (zebra_decoder_t *dcode) +static inline signed char i25_decode_start (zbar_decoder_t *dcode) { i25_decoder_t *dcode25 = &dcode->i25; if(dcode25->s10 < 10) - return(ZEBRA_NONE); + return(ZBAR_NONE); unsigned char enc = 0; unsigned char i = 10; @@ -100,24 +100,24 @@ static inline signed char i25_decode_start (zebra_decoder_t *dcode) enc = i25_decode1(enc, get_width(dcode, i++), dcode25->s10); enc = i25_decode1(enc, get_width(dcode, i++), dcode25->s10); - if((get_color(dcode) == ZEBRA_BAR) + if((get_color(dcode) == ZBAR_BAR) ? enc != 4 : i25_decode1(enc, get_width(dcode, i++), dcode25->s10)) - return(ZEBRA_NONE); + return(ZBAR_NONE); /* check leading quiet zone - spec is 10x(?), we require at least 7x */ unsigned quiet = get_width(dcode, i++); if(quiet && get_width(dcode, i++) && quiet < dcode25->s10 / 4) - return(ZEBRA_NONE); + return(ZBAR_NONE); dcode25->direction = get_color(dcode); dcode25->element = 1; dcode25->character = 0; - return(ZEBRA_PARTIAL); + return(ZBAR_PARTIAL); } -static inline signed char i25_decode_end (zebra_decoder_t *dcode) +static inline signed char i25_decode_end (zbar_decoder_t *dcode) { i25_decoder_t *dcode25 = &dcode->i25; @@ -125,7 +125,7 @@ static inline signed char i25_decode_end (zebra_decoder_t *dcode) if(get_width(dcode, 0) < dcode25->width / 4 || decode_e(get_width(dcode, 1), dcode25->width, 45) > 2 || decode_e(get_width(dcode, 2), dcode25->width, 45) > 2) - return(ZEBRA_NONE); + return(ZBAR_NONE); /* check exit condition */ unsigned char E = decode_e(get_width(dcode, 3), dcode25->width, 45); @@ -133,7 +133,7 @@ static inline signed char i25_decode_end (zebra_decoder_t *dcode) ? E - 3 > 4 : (E > 2 || decode_e(get_width(dcode, 4), dcode25->width, 45) > 2)) - return(ZEBRA_NONE); + return(ZBAR_NONE); if(dcode25->direction) { /* reverse buffer */ @@ -147,22 +147,22 @@ static inline signed char i25_decode_end (zebra_decoder_t *dcode) } } - if(dcode25->character < CFG(*dcode25, ZEBRA_CFG_MIN_LEN) || - (CFG(*dcode25, ZEBRA_CFG_MAX_LEN) > 0 && - dcode25->character > CFG(*dcode25, ZEBRA_CFG_MAX_LEN))) { + if(dcode25->character < CFG(*dcode25, ZBAR_CFG_MIN_LEN) || + (CFG(*dcode25, ZBAR_CFG_MAX_LEN) > 0 && + dcode25->character > CFG(*dcode25, ZBAR_CFG_MAX_LEN))) { dprintf(2, " [invalid len]\n"); dcode->lock = 0; dcode25->character = -1; - return(ZEBRA_NONE); + return(ZBAR_NONE); } dcode->buf[dcode25->character] = '\0'; dprintf(2, " [valid end]\n"); dcode25->character = -1; - return(ZEBRA_I25); + return(ZBAR_I25); } -zebra_symbol_type_t _zebra_decode_i25 (zebra_decoder_t *dcode) +zbar_symbol_type_t _zbar_decode_i25 (zbar_decoder_t *dcode) { i25_decoder_t *dcode25 = &dcode->i25; @@ -172,12 +172,12 @@ zebra_symbol_type_t _zebra_decode_i25 (zebra_decoder_t *dcode) if(dcode25->character < 0 && !i25_decode_start(dcode)) - return(ZEBRA_NONE); + return(ZBAR_NONE); if(--dcode25->element == 6 - dcode25->direction) return(i25_decode_end(dcode)); else if(dcode25->element) - return(ZEBRA_NONE); + return(ZBAR_NONE); /* FIXME check current character width against previous */ dcode25->width = dcode25->s10; @@ -190,7 +190,7 @@ zebra_symbol_type_t _zebra_decode_i25 (zebra_decoder_t *dcode) if(!dcode25->character && get_lock(dcode)) { dcode25->character = -1; dprintf(2, " [locked]\n"); - return(ZEBRA_PARTIAL); + return(ZBAR_PARTIAL); } unsigned char c = i25_decode10(dcode, 1); @@ -202,7 +202,7 @@ zebra_symbol_type_t _zebra_decode_i25 (zebra_decoder_t *dcode) dprintf(2, (c > 9) ? " [aborted]\n" : " [overflow]\n"); dcode->lock = 0; dcode25->character = -1; - return(ZEBRA_NONE); + return(ZBAR_NONE); } dcode->buf[dcode25->character++] = c + '0'; @@ -212,12 +212,12 @@ zebra_symbol_type_t _zebra_decode_i25 (zebra_decoder_t *dcode) dprintf(2, " [aborted]\n"); dcode->lock = 0; dcode25->character = -1; - return(ZEBRA_NONE); + return(ZBAR_NONE); } else dprintf(2, "\n"); dcode->buf[dcode25->character++] = c + '0'; dcode25->element = 10; - return((dcode25->character == 2) ? ZEBRA_PARTIAL : ZEBRA_NONE); + return((dcode25->character == 2) ? ZBAR_PARTIAL : ZBAR_NONE); } diff --git a/zebra/decoder/i25.h b/zbar/decoder/i25.h similarity index 77% rename from zebra/decoder/i25.h rename to zbar/decoder/i25.h index bcec89a..4f4bee0 100644 --- a/zebra/decoder/i25.h +++ b/zbar/decoder/i25.h @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ - * Copyright 2008 (c) Jeff Brown + * Copyright 2008-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #ifndef _I25_H_ #define _I25_H_ @@ -45,6 +45,6 @@ static inline void i25_reset (i25_decoder_t *i25) } /* decode interleaved 2 of 5 symbols */ -zebra_symbol_type_t _zebra_decode_i25(zebra_decoder_t *dcode); +zbar_symbol_type_t _zbar_decode_i25(zbar_decoder_t *dcode); #endif diff --git a/zebra/decoder/pdf417.c b/zbar/decoder/pdf417.c similarity index 81% rename from zebra/decoder/pdf417.c rename to zbar/decoder/pdf417.c index cc21caf..2c9f043 100644 --- a/zebra/decoder/pdf417.c +++ b/zbar/decoder/pdf417.c @@ -1,29 +1,29 @@ /*------------------------------------------------------------------------ - * Copyright 2008 (c) Jeff Brown + * Copyright 2008-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include -#include +#include #include "decoder.h" #include "pdf417_hash.h" @@ -35,7 +35,7 @@ #define PDF417_STOP 0xbff -static inline signed short pdf417_decode8 (zebra_decoder_t *dcode) +static inline signed short pdf417_decode8 (zbar_decoder_t *dcode) { /* build edge signature of character * from similar edge measurements @@ -49,7 +49,7 @@ static inline signed short pdf417_decode8 (zebra_decoder_t *dcode) signed char e; unsigned char i; for(i = 0; i < 7; i++) { - if(get_color(dcode) == ZEBRA_SPACE) + if(get_color(dcode) == ZBAR_SPACE) e = decode_e(get_width(dcode, i) + get_width(dcode, i + 1), s, 17); else @@ -70,7 +70,7 @@ static inline signed short pdf417_decode8 (zebra_decoder_t *dcode) dprintf(2, " k=%d", clst); zassert(clst >= 0 && clst < 9, -1, "dir=%x sig=%lx k=%x %s\n", dcode->pdf417.direction, sig, clst, - _zebra_decoder_buf_dump(dcode->buf, dcode->pdf417.character)); + _zbar_decoder_buf_dump(dcode->buf, dcode->pdf417.character)); if(clst != 0 && clst != 3 && clst != 6) { if(get_color(dcode) && clst == 7 && sig == 0x080007) @@ -86,7 +86,7 @@ static inline signed short pdf417_decode8 (zebra_decoder_t *dcode) zassert(g[0] >= 0 && g[1] >= 0 && g[2] >= 0, -1, "dir=%x sig=%lx k=%x g0=%03x g1=%03x g2=%03x %s\n", dcode->pdf417.direction, sig, clst, g[0], g[1], g[2], - _zebra_decoder_buf_dump(dcode->buf, dcode->pdf417.character)); + _zbar_decoder_buf_dump(dcode->buf, dcode->pdf417.character)); unsigned short c = (g[0] + g[1] + g[2]) & PDF417_HASH_MASK; dprintf(2, " g0=%x g1=%x g2=%x c=%03d(%d)", @@ -94,14 +94,14 @@ static inline signed short pdf417_decode8 (zebra_decoder_t *dcode) return(c); } -static inline signed char pdf417_decode_start(zebra_decoder_t *dcode) +static inline signed char pdf417_decode_start(zbar_decoder_t *dcode) { unsigned s = dcode->pdf417.s8; if(s < 8) return(0); int ei = decode_e(get_width(dcode, 0) + get_width(dcode, 1), s, 17); - int ex = (get_color(dcode) == ZEBRA_SPACE) ? 2 : 6; + int ex = (get_color(dcode) == ZBAR_SPACE) ? 2 : 6; if(ei != ex) return(0); @@ -110,12 +110,12 @@ static inline signed char pdf417_decode_start(zebra_decoder_t *dcode) return(0); ei = decode_e(get_width(dcode, 2) + get_width(dcode, 3), s, 17); - ex = (get_color(dcode) == ZEBRA_SPACE) ? 0 : 2; + ex = (get_color(dcode) == ZBAR_SPACE) ? 0 : 2; if(ei != ex) return(0); ei = decode_e(get_width(dcode, 3) + get_width(dcode, 4), s, 17); - ex = (get_color(dcode) == ZEBRA_SPACE) ? 0 : 2; + ex = (get_color(dcode) == ZBAR_SPACE) ? 0 : 2; if(ei != ex) return(0); @@ -128,14 +128,14 @@ static inline signed char pdf417_decode_start(zebra_decoder_t *dcode) return(0); ei = decode_e(get_width(dcode, 6) + get_width(dcode, 7), s, 17); - ex = (get_color(dcode) == ZEBRA_SPACE) ? 7 : 1; + ex = (get_color(dcode) == ZBAR_SPACE) ? 7 : 1; if(ei != ex) return(0); ei = decode_e(get_width(dcode, 7) + get_width(dcode, 8), s, 17); - ex = (get_color(dcode) == ZEBRA_SPACE) ? 8 : 1; + ex = (get_color(dcode) == ZBAR_SPACE) ? 8 : 1; - if(get_color(dcode) == ZEBRA_BAR) { + if(get_color(dcode) == ZBAR_BAR) { /* stop character has extra bar */ if(ei != 1) return(0); @@ -163,10 +163,10 @@ static inline signed char pdf417_decode_start(zebra_decoder_t *dcode) dcode417->character = 0; dprintf(2, " [valid start]\n"); - return(ZEBRA_PARTIAL); + return(ZBAR_PARTIAL); } -zebra_symbol_type_t _zebra_decode_pdf417 (zebra_decoder_t *dcode) +zbar_symbol_type_t _zbar_decode_pdf417 (zbar_decoder_t *dcode) { pdf417_decoder_t *dcode417 = &dcode->pdf417; @@ -192,10 +192,10 @@ zebra_symbol_type_t _zebra_decode_pdf417 (zebra_decoder_t *dcode) int c = dcode417->character; dcode->lock = 0; dcode417->character = -1; - zassert(get_color(dcode) == dcode417->direction, ZEBRA_NONE, + zassert(get_color(dcode) == dcode417->direction, ZBAR_NONE, "color=%x dir=%x char=%d elem=0 %s\n", get_color(dcode), dcode417->direction, c, - _zebra_decoder_buf_dump(dcode->buf, c)); + _zbar_decoder_buf_dump(dcode->buf, c)); } signed short c = pdf417_decode8(dcode); diff --git a/zebra/decoder/pdf417.h b/zbar/decoder/pdf417.h similarity index 76% rename from zebra/decoder/pdf417.h rename to zbar/decoder/pdf417.h index ffe43a9..38e9688 100644 --- a/zebra/decoder/pdf417.h +++ b/zbar/decoder/pdf417.h @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ - * Copyright 2008 (c) Jeff Brown + * Copyright 2008-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #ifndef _PDF417_H_ #define _PDF417_H_ @@ -44,6 +44,6 @@ static inline void pdf417_reset (pdf417_decoder_t *pdf417) } /* decode PDF417 symbols */ -zebra_symbol_type_t _zebra_decode_pdf417(zebra_decoder_t *dcode); +zbar_symbol_type_t _zbar_decode_pdf417(zbar_decoder_t *dcode); #endif diff --git a/zebra/decoder/pdf417_hash.h b/zbar/decoder/pdf417_hash.h similarity index 98% rename from zebra/decoder/pdf417_hash.h rename to zbar/decoder/pdf417_hash.h index aaeb8b5..12b4f35 100644 --- a/zebra/decoder/pdf417_hash.h +++ b/zbar/decoder/pdf417_hash.h @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ - * Copyright 2008 (c) Jeff Brown + * Copyright 2008-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #ifndef _PDF417_HASH_H_ #define _PDF417_HASH_H_ diff --git a/zebra/error.c b/zbar/error.c similarity index 70% rename from zebra/error.c rename to zbar/error.c index f1fb986..2fb3848 100644 --- a/zebra/error.c +++ b/zbar/error.c @@ -1,30 +1,30 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include "error.h" #include -int _zebra_verbosity = 0; +int _zbar_verbosity = 0; static const char * const sev_str[] = { "FATAL ERROR", "ERROR", "OK", "WARNING", "NOTE" @@ -34,7 +34,7 @@ static const char * const sev_str[] = { static const char * const mod_str[] = { "processor", "video", "window", "image scanner", "" }; -#define MOD_MAX (strlen(mod_str[ZEBRA_MOD_IMAGE_SCANNER])) +#define MOD_MAX (strlen(mod_str[ZBAR_MOD_IMAGE_SCANNER])) static const char const * err_str[] = { "no error", /* OK */ @@ -50,53 +50,53 @@ static const char const * err_str[] = { "output window is closed", /* CLOSED */ "unknown error" /* NUM */ }; -#define ERR_MAX (strlen(err_str[ZEBRA_ERR_CLOSED])) +#define ERR_MAX (strlen(err_str[ZBAR_ERR_CLOSED])) -int zebra_version (unsigned *major, - unsigned *minor) +int zbar_version (unsigned *major, + unsigned *minor) { if(major) - *major = ZEBRA_VERSION_MAJOR; + *major = ZBAR_VERSION_MAJOR; if(minor) - *minor = ZEBRA_VERSION_MINOR; + *minor = ZBAR_VERSION_MINOR; return(0); } -void zebra_set_verbosity (int level) +void zbar_set_verbosity (int level) { - _zebra_verbosity = level; + _zbar_verbosity = level; } -void zebra_increase_verbosity () +void zbar_increase_verbosity () { - if(!_zebra_verbosity) - _zebra_verbosity++; + if(!_zbar_verbosity) + _zbar_verbosity++; else - _zebra_verbosity <<= 1; + _zbar_verbosity <<= 1; } -int _zebra_error_spew (const void *container, - int verbosity) +int _zbar_error_spew (const void *container, + int verbosity) { const errinfo_t *err = container; assert(err->magic == ERRINFO_MAGIC); - fprintf(stderr, "%s", _zebra_error_string(err, verbosity)); + fprintf(stderr, "%s", _zbar_error_string(err, verbosity)); return(-err->sev); } -zebra_error_t _zebra_get_error_code (const void *container) +zbar_error_t _zbar_get_error_code (const void *container) { const errinfo_t *err = container; assert(err->magic == ERRINFO_MAGIC); return(err->type); } -/* ERROR: zebra video in v4l1_set_format(): +/* ERROR: zbar video in v4l1_set_format(): * system error: blah[: blah] */ -const char *_zebra_error_string (const void *container, - int verbosity) +const char *_zbar_error_string (const void *container, + int verbosity) { errinfo_t *err = (errinfo_t*)container; assert(err->magic == ERRINFO_MAGIC); @@ -108,21 +108,21 @@ const char *_zebra_error_string (const void *container, sev = sev_str[1]; const char *mod; - if(err->module >= ZEBRA_MOD_PROCESSOR && - err->module < ZEBRA_MOD_UNKNOWN) + if(err->module >= ZBAR_MOD_PROCESSOR && + err->module < ZBAR_MOD_UNKNOWN) mod = mod_str[err->module]; else - mod = mod_str[ZEBRA_MOD_UNKNOWN]; + mod = mod_str[ZBAR_MOD_UNKNOWN]; const char *func = (err->func) ? err->func : ""; const char *type; - if(err->type >= 0 && err->type < ZEBRA_ERR_NUM) + if(err->type >= 0 && err->type < ZBAR_ERR_NUM) type = err_str[err->type]; else - type = err_str[ZEBRA_ERR_NUM]; + type = err_str[ZBAR_ERR_NUM]; - char basefmt[] = "%s: zebra %s in %s():\n %s: "; + char basefmt[] = "%s: zbar %s in %s():\n %s: "; int len = SEV_MAX + MOD_MAX + ERR_MAX + strlen(func) + sizeof(basefmt); err->buf = realloc(err->buf, len); len = sprintf(err->buf, basefmt, sev, mod, func, type); @@ -149,7 +149,7 @@ const char *_zebra_error_string (const void *container, return(""); } - if(err->type == ZEBRA_ERR_SYSTEM) { + if(err->type == ZBAR_ERR_SYSTEM) { char sysfmt[] = ": %s (%d)\n"; const char *syserr = strerror(err->errnum); err->buf = realloc(err->buf, len + strlen(sysfmt) + strlen(syserr)); diff --git a/zebra/error.h b/zbar/error.h similarity index 83% rename from zebra/error.h rename to zbar/error.h index 6f20ae1..4c9945f 100644 --- a/zebra/error.h +++ b/zbar/error.h @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #ifndef _ERROR_H_ #define _ERROR_H_ @@ -33,7 +33,7 @@ #include #include -#include +#include #if __STDC_VERSION__ < 199901L # if __GNUC__ >= 2 @@ -54,11 +54,11 @@ typedef enum errsev_e { } errsev_t; typedef enum errmodule_e { - ZEBRA_MOD_PROCESSOR, - ZEBRA_MOD_VIDEO, - ZEBRA_MOD_WINDOW, - ZEBRA_MOD_IMAGE_SCANNER, - ZEBRA_MOD_UNKNOWN, + ZBAR_MOD_PROCESSOR, + ZBAR_MOD_VIDEO, + ZBAR_MOD_WINDOW, + ZBAR_MOD_IMAGE_SCANNER, + ZBAR_MOD_UNKNOWN, } errmodule_t; typedef struct errinfo_s { @@ -68,19 +68,19 @@ typedef struct errinfo_s { int errnum; /* errno for system errors */ errsev_t sev; - zebra_error_t type; + zbar_error_t type; const char *func; /* reporting function */ const char *detail; /* description */ char *arg_str; /* single string argument */ int arg_int; /* single integer argument */ } errinfo_t; -extern int _zebra_verbosity; +extern int _zbar_verbosity; /* FIXME don't we need varargs hacks here? */ #define zprintf(level, format, ...) do { \ - if(_zebra_verbosity >= level) \ + if(_zbar_verbosity >= level) \ fprintf(stderr, "%s: " format, __func__ , ##__VA_ARGS__); \ } while(0) @@ -105,26 +105,26 @@ static inline int err_copy (void *dst_c, static inline int err_capture (const void *container, errsev_t sev, - zebra_error_t type, + zbar_error_t type, const char *func, const char *detail) { errinfo_t *err = (errinfo_t*)container; assert(err->magic == ERRINFO_MAGIC); - if(type == ZEBRA_ERR_SYSTEM) + if(type == ZBAR_ERR_SYSTEM) err->errnum = errno; err->sev = sev; err->type = type; err->func = func; err->detail = detail; - if(_zebra_verbosity >= 1) - _zebra_error_spew(err, 0); + if(_zbar_verbosity >= 1) + _zbar_error_spew(err, 0); return(-1); } static inline int err_capture_str (const void *container, errsev_t sev, - zebra_error_t type, + zbar_error_t type, const char *func, const char *detail, const char *arg) @@ -139,7 +139,7 @@ static inline int err_capture_str (const void *container, static inline int err_capture_int (const void *container, errsev_t sev, - zebra_error_t type, + zbar_error_t type, const char *func, const char *detail, int arg) @@ -152,7 +152,7 @@ static inline int err_capture_int (const void *container, static inline int err_capture_num (const void *container, errsev_t sev, - zebra_error_t type, + zbar_error_t type, const char *func, const char *detail, int num) diff --git a/zebra/image.c b/zbar/image.c similarity index 59% rename from zebra/image.c rename to zbar/image.c index 426e20b..c1506be 100644 --- a/zebra/image.c +++ b/zbar/image.c @@ -1,107 +1,107 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include "error.h" #include "image.h" -zebra_image_t *zebra_image_create () +zbar_image_t *zbar_image_create () { - zebra_image_t *img = calloc(1, sizeof(zebra_image_t)); + zbar_image_t *img = calloc(1, sizeof(zbar_image_t)); img->refcnt = 1; img->srcidx = -1; return(img); } -void zebra_image_destroy (zebra_image_t *img) +void zbar_image_destroy (zbar_image_t *img) { - _zebra_image_refcnt(img, -1); + _zbar_image_refcnt(img, -1); } -void zebra_image_ref (zebra_image_t *img, - int refs) +void zbar_image_ref (zbar_image_t *img, + int refs) { - _zebra_image_refcnt(img, refs); + _zbar_image_refcnt(img, refs); } -unsigned long zebra_image_get_format (const zebra_image_t *img) +unsigned long zbar_image_get_format (const zbar_image_t *img) { return(img->format); } -unsigned zebra_image_get_sequence (const zebra_image_t *img) +unsigned zbar_image_get_sequence (const zbar_image_t *img) { return(img->seq); } -unsigned zebra_image_get_width (const zebra_image_t *img) +unsigned zbar_image_get_width (const zbar_image_t *img) { return(img->width); } -unsigned zebra_image_get_height (const zebra_image_t *img) +unsigned zbar_image_get_height (const zbar_image_t *img) { return(img->height); } -const void *zebra_image_get_data (const zebra_image_t *img) +const void *zbar_image_get_data (const zbar_image_t *img) { return(img->data); } -unsigned long zebra_image_get_data_length (const zebra_image_t *img) +unsigned long zbar_image_get_data_length (const zbar_image_t *img) { return(img->datalen); } -void zebra_image_set_format (zebra_image_t *img, - unsigned long fmt) +void zbar_image_set_format (zbar_image_t *img, + unsigned long fmt) { img->format = fmt; } -void zebra_image_set_sequence (zebra_image_t *img, - unsigned seq) +void zbar_image_set_sequence (zbar_image_t *img, + unsigned seq) { img->seq = seq; } -void zebra_image_set_size (zebra_image_t *img, - unsigned w, - unsigned h) +void zbar_image_set_size (zbar_image_t *img, + unsigned w, + unsigned h) { img->width = w; img->height = h; } -inline void zebra_image_free_data (zebra_image_t *img) +inline void zbar_image_free_data (zbar_image_t *img) { if(!img) return; if(img->src) { /* replace video image w/new copy */ assert(img->refcnt); - zebra_image_t *newimg = zebra_image_create(); - memcpy(newimg, img, sizeof(zebra_image_t)); + zbar_image_t *newimg = zbar_image_create(); + memcpy(newimg, img, sizeof(zbar_image_t)); /* recycle video image */ newimg->cleanup(newimg); /* detach old image from src */ @@ -110,7 +110,7 @@ inline void zebra_image_free_data (zebra_image_t *img) img->srcidx = -1; } else if(img->cleanup && img->data) { - if(img->cleanup != zebra_image_free_data) + if(img->cleanup != zbar_image_free_data) img->cleanup(img); else free((void*)img->data); @@ -118,31 +118,31 @@ inline void zebra_image_free_data (zebra_image_t *img) img->data = NULL; } -void zebra_image_set_data (zebra_image_t *img, - const void *data, - unsigned long len, - zebra_image_cleanup_handler_t *cleanup) +void zbar_image_set_data (zbar_image_t *img, + const void *data, + unsigned long len, + zbar_image_cleanup_handler_t *cleanup) { - zebra_image_free_data(img); + zbar_image_free_data(img); img->data = data; img->datalen = len; img->cleanup = cleanup; } -void zebra_image_set_userdata (zebra_image_t *img, - void *userdata) +void zbar_image_set_userdata (zbar_image_t *img, + void *userdata) { img->userdata = userdata; } -void *zebra_image_get_userdata (const zebra_image_t *img) +void *zbar_image_get_userdata (const zbar_image_t *img) { return(img->userdata); } -zebra_image_t *zebra_image_copy (const zebra_image_t *src) +zbar_image_t *zbar_image_copy (const zbar_image_t *src) { - zebra_image_t *dst = zebra_image_create(); + zbar_image_t *dst = zbar_image_create(); dst->format = src->format; dst->width = src->width; dst->height = src->height; @@ -150,11 +150,11 @@ zebra_image_t *zebra_image_copy (const zebra_image_t *src) dst->data = malloc(src->datalen); assert(dst->data); memcpy((void*)dst->data, src->data, src->datalen); - dst->cleanup = zebra_image_free_data; + dst->cleanup = zbar_image_free_data; return(dst); } -const zebra_symbol_t *zebra_image_first_symbol (const zebra_image_t *img) +const zbar_symbol_t *zbar_image_first_symbol (const zbar_image_t *img) { /* symbols stored on root image */ while(img->next) @@ -168,8 +168,8 @@ typedef struct zimg_hdr_s { uint32_t size; } zimg_hdr_t; -int zebra_image_write (const zebra_image_t *img, - const char *filebase) +int zbar_image_write (const zbar_image_t *img, + const char *filebase) { int len = strlen(filebase) + 16; char filename[len]; diff --git a/zebra/image.h b/zbar/image.h similarity index 71% rename from zebra/image.h rename to zbar/image.h index 45a97a1..a70c72a 100644 --- a/zebra/image.h +++ b/zbar/image.h @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #ifndef _IMAGE_H_ #define _IMAGE_H_ @@ -30,7 +30,7 @@ #include #include -#include +#include #include "error.h" #include "symbol.h" @@ -46,20 +46,20 @@ /* coarse image format categorization. * to limit conversion variations */ -typedef enum zebra_format_group_e { - ZEBRA_FMT_GRAY, - ZEBRA_FMT_YUV_PLANAR, - ZEBRA_FMT_YUV_PACKED, - ZEBRA_FMT_RGB_PACKED, - ZEBRA_FMT_YUV_NV, - ZEBRA_FMT_JPEG, +typedef enum zbar_format_group_e { + ZBAR_FMT_GRAY, + ZBAR_FMT_YUV_PLANAR, + ZBAR_FMT_YUV_PACKED, + ZBAR_FMT_RGB_PACKED, + ZBAR_FMT_YUV_NV, + ZBAR_FMT_JPEG, /* enum size */ - ZEBRA_FMT_NUM -} zebra_format_group_t; + ZBAR_FMT_NUM +} zbar_format_group_t; -struct zebra_image_s { +struct zbar_image_s { uint32_t format; /* fourcc image format code */ unsigned width, height; /* image size */ const void *data; /* image sample data */ @@ -67,21 +67,21 @@ struct zebra_image_s { void *userdata; /* user specified data associated w/image */ /* cleanup handler */ - zebra_image_cleanup_handler_t *cleanup; + zbar_image_cleanup_handler_t *cleanup; int refcnt; /* reference count */ - zebra_video_t *src; /* originator */ + zbar_video_t *src; /* originator */ int srcidx; /* index used by originator */ - zebra_image_t *next; /* internal image lists */ + zbar_image_t *next; /* internal image lists */ unsigned seq; /* page/frame sequence number */ int nsyms; /* number of valid symbols */ - zebra_symbol_t *syms; /* first of decoded symbol results */ + zbar_symbol_t *syms; /* first of decoded symbol results */ }; /* description of an image format */ -typedef struct zebra_format_def_s { +typedef struct zbar_format_def_s { uint32_t format; /* fourcc */ - zebra_format_group_t group; /* coarse categorization */ + zbar_format_group_t group; /* coarse categorization */ union { uint8_t gen[4]; /* raw bytes */ struct { @@ -97,10 +97,10 @@ typedef struct zebra_format_def_s { } yuv; uint32_t cmp; /* quick compare equivalent formats */ } p; -} zebra_format_def_t; +} zbar_format_def_t; -static inline void _zebra_image_refcnt (zebra_image_t *img, - int delta) +static inline void _zbar_image_refcnt (zbar_image_t *img, + int delta) { img->refcnt += delta; assert(img->refcnt >= 0); @@ -112,7 +112,7 @@ static inline void _zebra_image_refcnt (zebra_image_t *img, } } -extern int _zebra_best_format(uint32_t, uint32_t*, const uint32_t*); -extern const zebra_format_def_t *_zebra_format_lookup(uint32_t); +extern int _zbar_best_format(uint32_t, uint32_t*, const uint32_t*); +extern const zbar_format_def_t *_zbar_format_lookup(uint32_t); #endif diff --git a/zebra/img_scanner.c b/zbar/img_scanner.c similarity index 68% rename from zebra/img_scanner.c rename to zbar/img_scanner.c index cea8339..0d1cdd8 100644 --- a/zebra/img_scanner.c +++ b/zbar/img_scanner.c @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include @@ -32,7 +32,7 @@ #include /* strlen, strcmp, memset, memcpy */ #include -#include +#include #include "error.h" #include "image.h" @@ -63,38 +63,38 @@ */ #define CACHE_TIMEOUT (CACHE_HYSTERESIS * 2) /* ms */ -#define NUM_SCN_CFGS (ZEBRA_CFG_Y_DENSITY - ZEBRA_CFG_X_DENSITY + 1) +#define NUM_SCN_CFGS (ZBAR_CFG_Y_DENSITY - ZBAR_CFG_X_DENSITY + 1) -#define CFG(iscn, cfg) ((iscn)->configs[(cfg) - ZEBRA_CFG_X_DENSITY]) +#define CFG(iscn, cfg) ((iscn)->configs[(cfg) - ZBAR_CFG_X_DENSITY]) /* image scanner state */ -struct zebra_image_scanner_s { - zebra_scanner_t *scn; /* associated linear intensity scanner */ - zebra_decoder_t *dcode; /* associated symbol decoder */ +struct zbar_image_scanner_s { + zbar_scanner_t *scn; /* associated linear intensity scanner */ + zbar_decoder_t *dcode; /* associated symbol decoder */ const void *userdata; /* application data */ /* user result callback */ - zebra_image_data_handler_t *handler; + zbar_image_data_handler_t *handler; - zebra_image_t *img; /* currently scanning image *root* */ + zbar_image_t *img; /* currently scanning image *root* */ int nsyms; /* total cached symbols */ - zebra_symbol_t *syms; /* recycled symbols */ + zbar_symbol_t *syms; /* recycled symbols */ int enable_cache; /* current result cache state */ - zebra_symbol_t *cache; /* inter-image result cache entries */ + zbar_symbol_t *cache; /* inter-image result cache entries */ /* configuration settings */ int configs[NUM_SCN_CFGS]; }; -static inline void recycle_syms (zebra_image_scanner_t *iscn, - zebra_image_t *img) +static inline void recycle_syms (zbar_image_scanner_t *iscn, + zbar_image_t *img) { /* walk to root of clone tree */ while(img) { img->nsyms = 0; - zebra_symbol_t *sym = img->syms; + zbar_symbol_t *sym = img->syms; if(sym) { /* recycle image symbols */ iscn->nsyms++; @@ -112,19 +112,19 @@ static inline void recycle_syms (zebra_image_scanner_t *iscn, } } -static inline zebra_symbol_t *alloc_sym (zebra_image_scanner_t *iscn, - zebra_symbol_type_t type, - const char *data) +static inline zbar_symbol_t *alloc_sym (zbar_image_scanner_t *iscn, + zbar_symbol_type_t type, + const char *data) { /* recycle old or alloc new symbol */ - zebra_symbol_t *sym = iscn->syms; + zbar_symbol_t *sym = iscn->syms; if(sym) { iscn->syms = sym->next; assert(iscn->nsyms); iscn->nsyms--; } else { - sym = calloc(1, sizeof(zebra_symbol_t)); + sym = calloc(1, sizeof(zbar_symbol_t)); assert(!iscn->nsyms); } @@ -142,18 +142,18 @@ static inline zebra_symbol_t *alloc_sym (zebra_image_scanner_t *iscn, return(sym); } -static inline zebra_symbol_t *cache_lookup (zebra_image_scanner_t *iscn, - zebra_symbol_t *sym) +static inline zbar_symbol_t *cache_lookup (zbar_image_scanner_t *iscn, + zbar_symbol_t *sym) { /* search for matching entry in cache */ - zebra_symbol_t **entry = &iscn->cache; + zbar_symbol_t **entry = &iscn->cache; while(*entry) { if((*entry)->type == sym->type && !strcmp((*entry)->data, sym->data)) break; if((sym->time - (*entry)->time) > CACHE_TIMEOUT) { /* recycle stale cache entry */ - zebra_symbol_t *next = (*entry)->next; + zbar_symbol_t *next = (*entry)->next; (*entry)->next = iscn->syms; iscn->syms = *entry; iscn->nsyms++; @@ -165,20 +165,20 @@ static inline zebra_symbol_t *cache_lookup (zebra_image_scanner_t *iscn, return(*entry); } -static void symbol_handler (zebra_image_scanner_t *iscn, +static void symbol_handler (zbar_image_scanner_t *iscn, int x, int y) { - zebra_symbol_type_t type = zebra_decoder_get_type(iscn->dcode); - /* FIXME assert(type == ZEBRA_PARTIAL) */ + zbar_symbol_type_t type = zbar_decoder_get_type(iscn->dcode); + /* FIXME assert(type == ZBAR_PARTIAL) */ /* FIXME debug flag to save/display all PARTIALs */ - if(type <= ZEBRA_PARTIAL) + if(type <= ZBAR_PARTIAL) return; - const char *data = zebra_decoder_get_data(iscn->dcode); + const char *data = zbar_decoder_get_data(iscn->dcode); /* FIXME deprecate - instead check (x, y) inside existing polygon */ - zebra_symbol_t *sym; + zbar_symbol_t *sym; for(sym = iscn->img->syms; sym; sym = sym->next) if(sym->type == type && !strcmp(sym->data, data)) { @@ -211,7 +211,7 @@ static void symbol_handler (zebra_image_scanner_t *iscn, iscn->img->nsyms++; if(iscn->enable_cache) { - zebra_symbol_t *entry = cache_lookup(iscn, sym); + zbar_symbol_t *entry = cache_lookup(iscn, sym); if(!entry) { entry = alloc_sym(iscn, sym->type, sym->data); entry->time = sym->time - CACHE_HYSTERESIS; @@ -241,72 +241,72 @@ static void symbol_handler (zebra_image_scanner_t *iscn, iscn->handler(iscn->img, iscn->userdata); } -zebra_image_scanner_t *zebra_image_scanner_create () +zbar_image_scanner_t *zbar_image_scanner_create () { - zebra_image_scanner_t *iscn = calloc(1, sizeof(zebra_image_scanner_t)); + zbar_image_scanner_t *iscn = calloc(1, sizeof(zbar_image_scanner_t)); if(!iscn) return(NULL); - iscn->dcode = zebra_decoder_create(); - iscn->scn = zebra_scanner_create(iscn->dcode); + iscn->dcode = zbar_decoder_create(); + iscn->scn = zbar_scanner_create(iscn->dcode); if(!iscn->dcode || !iscn->scn) { - zebra_image_scanner_destroy(iscn); + zbar_image_scanner_destroy(iscn); return(NULL); } /* apply default configuration */ - CFG(iscn, ZEBRA_CFG_X_DENSITY) = 16; - CFG(iscn, ZEBRA_CFG_Y_DENSITY) = 16; + CFG(iscn, ZBAR_CFG_X_DENSITY) = 16; + CFG(iscn, ZBAR_CFG_Y_DENSITY) = 16; return(iscn); } -void zebra_image_scanner_destroy (zebra_image_scanner_t *iscn) +void zbar_image_scanner_destroy (zbar_image_scanner_t *iscn) { if(iscn->scn) - zebra_scanner_destroy(iscn->scn); + zbar_scanner_destroy(iscn->scn); iscn->scn = NULL; if(iscn->dcode) - zebra_decoder_destroy(iscn->dcode); + zbar_decoder_destroy(iscn->dcode); iscn->dcode = NULL; while(iscn->syms) { - zebra_symbol_t *next = iscn->syms->next; + zbar_symbol_t *next = iscn->syms->next; sym_destroy(iscn->syms); iscn->syms = next; } free(iscn); } -zebra_image_data_handler_t* -zebra_image_scanner_set_data_handler (zebra_image_scanner_t *iscn, - zebra_image_data_handler_t *handler, - const void *userdata) +zbar_image_data_handler_t* +zbar_image_scanner_set_data_handler (zbar_image_scanner_t *iscn, + zbar_image_data_handler_t *handler, + const void *userdata) { - zebra_image_data_handler_t *result = iscn->handler; + zbar_image_data_handler_t *result = iscn->handler; iscn->handler = handler; iscn->userdata = userdata; return(result); } -int zebra_image_scanner_set_config (zebra_image_scanner_t *iscn, - zebra_symbol_type_t sym, - zebra_config_t cfg, - int val) +int zbar_image_scanner_set_config (zbar_image_scanner_t *iscn, + zbar_symbol_type_t sym, + zbar_config_t cfg, + int val) { - if(cfg >= ZEBRA_CFG_X_DENSITY && cfg <= ZEBRA_CFG_Y_DENSITY) { - if(sym > ZEBRA_PARTIAL) + if(cfg >= ZBAR_CFG_X_DENSITY && cfg <= ZBAR_CFG_Y_DENSITY) { + if(sym > ZBAR_PARTIAL) return(1); CFG(iscn, cfg) = val; return(0); } - return(zebra_decoder_set_config(iscn->dcode, sym, cfg, val)); + return(zbar_decoder_set_config(iscn->dcode, sym, cfg, val)); } -void zebra_image_scanner_enable_cache(zebra_image_scanner_t *iscn, - int enable) +void zbar_image_scanner_enable_cache(zbar_image_scanner_t *iscn, + int enable) { if(iscn->cache) { /* recycle all cached syms */ - zebra_symbol_t *entry; + zbar_symbol_t *entry; for(entry = iscn->cache; entry->next; entry = entry->next) iscn->nsyms++; iscn->nsyms++; @@ -317,20 +317,20 @@ void zebra_image_scanner_enable_cache(zebra_image_scanner_t *iscn, iscn->enable_cache = enable; } -static inline void quiet_border (zebra_image_scanner_t *iscn, +static inline void quiet_border (zbar_image_scanner_t *iscn, unsigned samples, int x, int y) { unsigned i; for(i = samples; i; i--) - if(zebra_scan_y(iscn->scn, 255)) + if(zbar_scan_y(iscn->scn, 255)) symbol_handler(iscn, x, y); /* flush final transition with 2 black pixels */ for(i = 2; i; i--) - if(zebra_scan_y(iscn->scn, 0)) + if(zbar_scan_y(iscn->scn, 0)) symbol_handler(iscn, x, y); - if(zebra_scanner_new_scan(iscn->scn)) + if(zbar_scanner_new_scan(iscn->scn)) symbol_handler(iscn, x, y); } @@ -340,26 +340,26 @@ static inline void quiet_border (zebra_image_scanner_t *iscn, p += (dx) + ((intptr_t)(dy) * w); \ } while(0); -int zebra_scan_image (zebra_image_scanner_t *iscn, - zebra_image_t *img) +int zbar_scan_image (zbar_image_scanner_t *iscn, + zbar_image_t *img) { recycle_syms(iscn, img); /* get grayscale image, convert if necessary */ - img = zebra_image_convert(img, fourcc('Y','8','0','0')); + img = zbar_image_convert(img, fourcc('Y','8','0','0')); if(!img) return(-1); - unsigned w = zebra_image_get_width(img); - unsigned h = zebra_image_get_height(img); - const uint8_t *data = zebra_image_get_data(img); + unsigned w = zbar_image_get_width(img); + unsigned h = zbar_image_get_height(img); + const uint8_t *data = zbar_image_get_data(img); /* FIXME less arbitrary lead-out default */ int quiet = w / 32; if(quiet < 8) quiet = 8; - int density = CFG(iscn, ZEBRA_CFG_Y_DENSITY); + int density = CFG(iscn, ZBAR_CFG_Y_DENSITY); if(density > 0) { const uint8_t *p = data; int x = 0, y = 0; @@ -369,14 +369,14 @@ int zebra_scan_image (zebra_image_scanner_t *iscn, border = h / 2; movedelta(0, border); - if(zebra_scanner_new_scan(iscn->scn)) + if(zbar_scanner_new_scan(iscn->scn)) symbol_handler(iscn, x, y); while(y < h) { zprintf(32, "img_x+: %03x,%03x @%p\n", x, y, p); while(x < w) { ASSERT_POS; - if(zebra_scan_y(iscn->scn, *p)) + if(zbar_scan_y(iscn->scn, *p)) symbol_handler(iscn, x, y); movedelta(1, 0); } @@ -389,7 +389,7 @@ int zebra_scan_image (zebra_image_scanner_t *iscn, zprintf(32, "img_x-: %03x,%03x @%p\n", x, y, p); while(x > 0) { ASSERT_POS; - if(zebra_scan_y(iscn->scn, *p)) + if(zbar_scan_y(iscn->scn, *p)) symbol_handler(iscn, x, y); movedelta(-1, 0); } @@ -399,7 +399,7 @@ int zebra_scan_image (zebra_image_scanner_t *iscn, } } - density = CFG(iscn, ZEBRA_CFG_X_DENSITY); + density = CFG(iscn, ZBAR_CFG_X_DENSITY); if(density > 0) { const uint8_t *p = data; int x = 0, y = 0; @@ -413,7 +413,7 @@ int zebra_scan_image (zebra_image_scanner_t *iscn, zprintf(32, "img_y+: %03x,%03x @%p\n", x, y, p); while(y < h) { ASSERT_POS; - if(zebra_scan_y(iscn->scn, *p)) + if(zbar_scan_y(iscn->scn, *p)) symbol_handler(iscn, x, y); movedelta(0, 1); } @@ -426,7 +426,7 @@ int zebra_scan_image (zebra_image_scanner_t *iscn, zprintf(32, "img_y-: %03x,%03x @%p\n", x, y, p); while(y >= 0) { ASSERT_POS; - if(zebra_scan_y(iscn->scn, *p)) + if(zbar_scan_y(iscn->scn, *p)) symbol_handler(iscn, x, y); movedelta(0, -1); } @@ -437,6 +437,6 @@ int zebra_scan_image (zebra_image_scanner_t *iscn, } /* release reference to converted image */ - zebra_image_destroy(img); + zbar_image_destroy(img); return(iscn->img->nsyms); } diff --git a/zebra/jpeg.c b/zbar/jpeg.c similarity index 82% rename from zebra/jpeg.c rename to zbar/jpeg.c index d20aaea..e489197 100644 --- a/zebra/jpeg.c +++ b/zbar/jpeg.c @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ * Copyright 2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include @@ -28,7 +28,7 @@ #include /* FIXME tmp debug */ #undef HAVE_STDLIB_H -#include +#include #include "image.h" #include "video.h" @@ -41,7 +41,7 @@ typedef struct errenv_s { jmp_buf env; } errenv_t; -void zebra_jpeg_error (j_common_ptr cinfo) +void zbar_jpeg_error (j_common_ptr cinfo) { errenv_t *jerr = (errenv_t*)cinfo->err; assert(jerr->valid); @@ -52,10 +52,10 @@ void zebra_jpeg_error (j_common_ptr cinfo) #endif -typedef struct zebra_src_mgr_s { +typedef struct zbar_src_mgr_s { struct jpeg_source_mgr src; - const zebra_image_t *img; -} zebra_src_mgr_t; + const zbar_image_t *img; +} zbar_src_mgr_t; static const JOCTET fake_eoi[2] = { 0xff, JPEG_EOI }; @@ -63,7 +63,7 @@ void init_source (j_decompress_ptr cinfo) { /* buffer/length refer to compressed data */ /* FIXME find img */ - const zebra_image_t *img = ((zebra_src_mgr_t*)cinfo->src)->img; + const zbar_image_t *img = ((zbar_src_mgr_t*)cinfo->src)->img; cinfo->src->next_input_byte = img->data; cinfo->src->bytes_in_buffer = img->datalen; } @@ -88,7 +88,7 @@ void term_source (j_decompress_ptr cinfo) /* nothing todo */ } -struct jpeg_decompress_struct * _zebra_jpeg_decomp_create () +struct jpeg_decompress_struct * _zbar_jpeg_decomp_create () { j_decompress_ptr cinfo = calloc(1, sizeof(struct jpeg_decompress_struct)); if(!cinfo) @@ -101,7 +101,7 @@ struct jpeg_decompress_struct * _zebra_jpeg_decomp_create () } cinfo->err = jpeg_std_error(&jerr->err); - jerr->err.error_exit = zebra_jpeg_error; + jerr->err.error_exit = zbar_jpeg_error; jerr->valid = 1; if(setjmp(jerr->env)) { @@ -121,7 +121,7 @@ struct jpeg_decompress_struct * _zebra_jpeg_decomp_create () return(cinfo); } -void _zebra_jpeg_decomp_destroy (struct jpeg_decompress_struct *cinfo) +void _zbar_jpeg_decomp_destroy (struct jpeg_decompress_struct *cinfo) { if(cinfo->err) { free(cinfo->err); @@ -137,16 +137,16 @@ void _zebra_jpeg_decomp_destroy (struct jpeg_decompress_struct *cinfo) } /* invoke libjpeg to decompress JPEG format to luminance plane */ -void _zebra_convert_jpeg_to_y (zebra_image_t *dst, - const zebra_format_def_t *dstfmt, - const zebra_image_t *src, - const zebra_format_def_t *srcfmt) +void _zbar_convert_jpeg_to_y (zbar_image_t *dst, + const zbar_format_def_t *dstfmt, + const zbar_image_t *src, + const zbar_format_def_t *srcfmt) { /* create decompressor, or use cached video stream decompressor */ errenv_t *jerr = NULL; j_decompress_ptr cinfo; if(!src->src) - cinfo = _zebra_jpeg_decomp_create(); + cinfo = _zbar_jpeg_decomp_create(); else { cinfo = src->src->jpeg; assert(cinfo); @@ -169,7 +169,7 @@ void _zebra_convert_jpeg_to_y (zebra_image_t *dst, /* setup input image */ if(!cinfo->src) { - cinfo->src = calloc(1, sizeof(zebra_src_mgr_t)); + cinfo->src = calloc(1, sizeof(zbar_src_mgr_t)); cinfo->src->init_source = init_source; cinfo->src->fill_input_buffer = fill_input_buffer; cinfo->src->skip_input_data = skip_input_data; @@ -178,7 +178,7 @@ void _zebra_convert_jpeg_to_y (zebra_image_t *dst, } cinfo->src->next_input_byte = NULL; cinfo->src->bytes_in_buffer = 0; - ((zebra_src_mgr_t*)cinfo->src)->img = src; + ((zbar_src_mgr_t*)cinfo->src)->img = src; int rc = jpeg_read_header(cinfo, TRUE); zprintf(30, "header: %s\n", (rc == 2) ? "tables-only" : "normal"); @@ -209,7 +209,7 @@ void _zebra_convert_jpeg_to_y (zebra_image_t *dst, if(!dst->data) { dst->datalen = datalen; dst->data = malloc(dst->datalen); - dst->cleanup = zebra_image_free_data; + dst->cleanup = zbar_image_free_data; } else assert(datalen <= dst->datalen); @@ -231,5 +231,5 @@ void _zebra_convert_jpeg_to_y (zebra_image_t *dst, jerr->valid = 0; if(!src->src && cinfo) /* cleanup only if we allocated locally */ - _zebra_jpeg_decomp_destroy(cinfo); + _zbar_jpeg_decomp_destroy(cinfo); } diff --git a/zbar/logo.c b/zbar/logo.c new file mode 100644 index 0000000..0b43a99 --- /dev/null +++ b/zbar/logo.c @@ -0,0 +1,32 @@ +/*------------------------------------------------------------------------ + * Copyright 2008-2009 (c) Jeff Brown + * + * 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 +#include "window.h" +#include "error.h" + +int _zbar_draw_logo (zbar_window_t *w) +{ + _zbar_window_clear(w); + return(0); +} diff --git a/zebra/processor.c b/zbar/processor.c similarity index 70% rename from zebra/processor.c rename to zbar/processor.c index ec029e8..240d266 100644 --- a/zebra/processor.c +++ b/zbar/processor.c @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include "processor.h" @@ -37,7 +37,7 @@ static inline void proc_mutex_unlock (void *arg) } /* acquire window access semaphore */ -static inline int proc_lock (zebra_processor_t *proc) +static inline int proc_lock (zbar_processor_t *proc) { if(!proc->threaded) return(0); @@ -51,13 +51,13 @@ static inline int proc_lock (zebra_processor_t *proc) } pthread_cleanup_pop(1); if(rc) - err_capture(proc, SEV_ERROR, ZEBRA_ERR_LOCKING, __func__, + err_capture(proc, SEV_ERROR, ZBAR_ERR_LOCKING, __func__, "unable to lock processor"); return(rc); } /* release window access semaphore */ -static inline void proc_unlock (zebra_processor_t *proc) +static inline void proc_unlock (zbar_processor_t *proc) { if(!proc->threaded) return; @@ -86,36 +86,36 @@ static inline void proc_destroy_thread (pthread_t thread, #endif /* lock is already held */ -static inline int process_image (zebra_processor_t *proc, - zebra_image_t *img) +static inline int process_image (zbar_processor_t *proc, + zbar_image_t *img) { if(img) { - uint32_t format = zebra_image_get_format(img); + uint32_t format = zbar_image_get_format(img); zprintf(16, "processing: %.4s(%08" PRIx32 ") %dx%d @%p\n", (char*)&format, format, - zebra_image_get_width(img), zebra_image_get_height(img), - zebra_image_get_data(img)); + zbar_image_get_width(img), zbar_image_get_height(img), + zbar_image_get_data(img)); /* FIXME locking all other interfaces while processing is conservative * but easier for now and we don't expect this to take long... */ - int nsyms = zebra_scan_image(proc->scanner, img); + int nsyms = zbar_scan_image(proc->scanner, img); if(nsyms < 0) - return(err_capture(proc, SEV_ERROR, ZEBRA_ERR_UNSUPPORTED, + return(err_capture(proc, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "unknown image format")); - if(_zebra_verbosity >= 8) { - const zebra_symbol_t *sym = zebra_image_first_symbol(img); + if(_zbar_verbosity >= 8) { + const zbar_symbol_t *sym = zbar_image_first_symbol(img); while(sym) { - zebra_symbol_type_t type = zebra_symbol_get_type(sym); - int count = zebra_symbol_get_count(sym); + zbar_symbol_type_t type = zbar_symbol_get_type(sym); + int count = zbar_symbol_get_count(sym); zprintf(8, "%s%s: %s (%s)\n", - zebra_get_symbol_name(type), - zebra_get_addon_name(type), - zebra_symbol_get_data(sym), + zbar_get_symbol_name(type), + zbar_get_addon_name(type), + zbar_symbol_get_data(sym), (count < 0) ? "uncertain" : (count > 0) ? "duplicate" : "new"); - sym = zebra_symbol_next(sym); + sym = zbar_symbol_next(sym); } } @@ -127,44 +127,44 @@ static inline int process_image (zebra_processor_t *proc, } if(proc->force_output) { - img = zebra_image_convert(img, proc->force_output); + img = zbar_image_convert(img, proc->force_output); if(!img) - return(err_capture(proc, SEV_ERROR, ZEBRA_ERR_UNSUPPORTED, + return(err_capture(proc, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "unknown image format")); } } /* display to window if enabled */ if(proc->window && - (zebra_window_draw(proc->window, img) || - _zebra_window_invalidate(proc->window))) + (zbar_window_draw(proc->window, img) || + _zbar_window_invalidate(proc->window))) return(err_copy(proc, proc->window)); #if 0 /* FIXME still don't understand why we need this */ - if(proc->window && _zebra_window_handle_events(proc, 0)) + if(proc->window && _zbar_window_handle_events(proc, 0)) return(-1); #endif if(proc->force_output && img) - zebra_image_destroy(img); + zbar_image_destroy(img); return(0); } /* used by poll interface. lock is already held */ -static int proc_video_handler (zebra_processor_t *proc, +static int proc_video_handler (zbar_processor_t *proc, int i) { if(!proc->active) return(0); /* not expected to block */ - zebra_image_t *img = zebra_video_next_image(proc->video); + zbar_image_t *img = zbar_video_next_image(proc->video); if(!img) return(-1); int rc = process_image(proc, img); - zebra_image_destroy(img); + zbar_image_destroy(img); return(rc); } -static inline int proc_poll_inputs (zebra_processor_t *proc, +static inline int proc_poll_inputs (zbar_processor_t *proc, poll_desc_t *p, int timeout) { @@ -213,7 +213,7 @@ static inline int proc_calc_abstime (struct timespec *abstime, } #ifdef HAVE_LIBPTHREAD -static inline int proc_event_wait_threaded (zebra_processor_t *proc, +static inline int proc_event_wait_threaded (zbar_processor_t *proc, unsigned event, int timeout, struct timespec *abstime) @@ -245,21 +245,21 @@ static inline int proc_event_wait_threaded (zebra_processor_t *proc, } #endif -static inline int proc_event_wait_unthreaded (zebra_processor_t *proc, +static inline int proc_event_wait_unthreaded (zbar_processor_t *proc, unsigned event, int timeout, struct timespec *abstime) { - int blocking = proc->active && zebra_video_get_fd(proc->video) < 0; + int blocking = proc->active && zbar_video_get_fd(proc->video) < 0; proc->events &= ~event; /* unthreaded, poll here for window input */ while(!(proc->events & event)) { if(blocking) { - zebra_image_t *img = zebra_video_next_image(proc->video); + zbar_image_t *img = zbar_video_next_image(proc->video); if(!img) return(-1); process_image(proc, img); - zebra_image_destroy(img); + zbar_image_destroy(img); } int reltime = timeout; if(reltime >= 0) { @@ -295,7 +295,7 @@ static inline int proc_event_wait_unthreaded (zebra_processor_t *proc, return(1); } -static inline int proc_event_wait (zebra_processor_t *proc, +static inline int proc_event_wait (zbar_processor_t *proc, unsigned event, int timeout) { @@ -311,7 +311,7 @@ static inline int proc_event_wait (zebra_processor_t *proc, #ifdef HAVE_LIBPTHREAD /* make a thread-local copy of polling data */ -static inline void proc_cache_polling (zebra_processor_t *proc) +static inline void proc_cache_polling (zbar_processor_t *proc) { (void)proc_lock(proc); int n = proc->polling.num; @@ -335,7 +335,7 @@ static inline void proc_block_sigs () /* input handler thread to poll available inputs */ static void *proc_input_thread (void *arg) { - zebra_processor_t *proc = arg; + zbar_processor_t *proc = arg; proc_block_sigs(); /* wait for registered inputs and process using associated handler */ @@ -359,7 +359,7 @@ static void *proc_input_thread (void *arg) /* separate thread to handle non-pollable video (v4l1) */ static void *proc_video_thread (void *arg) { - zebra_processor_t *proc = arg; + zbar_processor_t *proc = arg; proc_block_sigs(); (void)proc_lock(proc); @@ -376,26 +376,26 @@ static void *proc_video_thread (void *arg) pthread_cleanup_pop(1); /* unlocked blocking image input */ - zebra_image_t *img = zebra_video_next_image(proc->video); + zbar_image_t *img = zbar_video_next_image(proc->video); if(!img) return(NULL); (void)proc_lock(proc); if(proc->active) process_image(proc, img); - zebra_image_destroy(img); + zbar_image_destroy(img); } } #endif -zebra_processor_t *zebra_processor_create (int threaded) +zbar_processor_t *zbar_processor_create (int threaded) { - zebra_processor_t *proc = calloc(1, sizeof(zebra_processor_t)); + zbar_processor_t *proc = calloc(1, sizeof(zbar_processor_t)); if(!proc) return(NULL); - err_init(&proc->err, ZEBRA_MOD_PROCESSOR); + err_init(&proc->err, ZBAR_MOD_PROCESSOR); proc->kick_fds[0] = proc->kick_fds[1] = -1; - proc->scanner = zebra_image_scanner_create(); + proc->scanner = zbar_image_scanner_create(); if(!proc->scanner) { free(proc); return(NULL); @@ -419,22 +419,22 @@ zebra_processor_t *zebra_processor_create (int threaded) return(proc); } -void zebra_processor_destroy (zebra_processor_t *proc) +void zbar_processor_destroy (zbar_processor_t *proc) { (void)proc_lock(proc); proc_destroy_thread(proc->video_thread, &proc->video_started); proc_destroy_thread(proc->input_thread, &proc->input_started); if(proc->window) { - zebra_window_destroy(proc->window); + zbar_window_destroy(proc->window); proc->window = NULL; - _zebra_window_close(proc); + _zbar_window_close(proc); } if(proc->video) { - zebra_video_destroy(proc->video); + zbar_video_destroy(proc->video); proc->video = NULL; } if(proc->scanner) { - zebra_image_scanner_destroy(proc->scanner); + zbar_image_scanner_destroy(proc->scanner); proc->scanner = NULL; } proc_unlock(proc); @@ -463,9 +463,9 @@ void zebra_processor_destroy (zebra_processor_t *proc) free(proc); } -int zebra_processor_init (zebra_processor_t *proc, - const char *dev, - int enable_display) +int zbar_processor_init (zbar_processor_t *proc, + const char *dev, + int enable_display) { if(proc_lock(proc) < 0) return(-1); @@ -475,16 +475,16 @@ int zebra_processor_init (zebra_processor_t *proc, int rc = 0; if(proc->video) { if(dev) - zebra_video_open(proc->video, NULL); + zbar_video_open(proc->video, NULL); else { - zebra_video_destroy(proc->video); + zbar_video_destroy(proc->video); proc->video = NULL; } } if(proc->window) { - zebra_window_destroy(proc->window); + zbar_window_destroy(proc->window); proc->window = NULL; - _zebra_window_close(proc); + _zbar_window_close(proc); } if(!dev && !enable_display) @@ -492,38 +492,38 @@ int zebra_processor_init (zebra_processor_t *proc, goto done; if(enable_display) { - proc->window = zebra_window_create(); + proc->window = zbar_window_create(); if(!proc->window) { - rc = err_capture(proc, SEV_FATAL, ZEBRA_ERR_NOMEM, + rc = err_capture(proc, SEV_FATAL, ZBAR_ERR_NOMEM, __func__, "allocating window resources"); goto done; } } if(dev) { - proc->video = zebra_video_create(); + proc->video = zbar_video_create(); if(!proc->video) { - rc = err_capture(proc, SEV_FATAL, ZEBRA_ERR_NOMEM, + rc = err_capture(proc, SEV_FATAL, ZBAR_ERR_NOMEM, __func__, "allocating video resources"); goto done; } if(proc->req_width || proc->req_height) - zebra_video_request_size(proc->video, + zbar_video_request_size(proc->video, proc->req_width, proc->req_height); if(proc->req_v4l) - zebra_video_request_interface(proc->video, proc->req_v4l); + zbar_video_request_interface(proc->video, proc->req_v4l); if((proc->req_iomode && - zebra_video_request_iomode(proc->video, proc->req_iomode)) || - zebra_video_open(proc->video, dev)) { + zbar_video_request_iomode(proc->video, proc->req_iomode)) || + zbar_video_open(proc->video, dev)) { rc = err_copy(proc, proc->video); goto done; } - if(zebra_video_get_fd(proc->video) < 0 && proc->threaded) { + if(zbar_video_get_fd(proc->video) < 0 && proc->threaded) { #ifdef HAVE_LIBPTHREAD /* spawn blocking video thread */ if((rc = pthread_create(&proc->video_thread, NULL, proc_video_thread, proc))) { - rc = err_capture_num(proc, SEV_ERROR, ZEBRA_ERR_SYSTEM, + rc = err_capture_num(proc, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "spawning video thread", rc); goto done; } @@ -539,7 +539,7 @@ int zebra_processor_init (zebra_processor_t *proc, /* spawn input monitor thread */ if((rc = pthread_create(&proc->input_thread, NULL, proc_input_thread, proc))) { - rc = err_capture_num(proc, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + rc = err_capture_num(proc, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "spawning input thread", rc); goto done; } @@ -552,37 +552,37 @@ int zebra_processor_init (zebra_processor_t *proc, /* arbitrary default */ int width = 640, height = 480; if(proc->video) { - width = zebra_video_get_width(proc->video); - height = zebra_video_get_height(proc->video); + width = zbar_video_get_width(proc->video); + height = zbar_video_get_height(proc->video); } - if(_zebra_window_open(proc, "zebra barcode reader", width, height)) { + if(_zbar_window_open(proc, "zbar barcode reader", width, height)) { rc = -1; goto done; } - else if(zebra_window_attach(proc->window, proc->display, proc->xwin)) { + else if(zbar_window_attach(proc->window, proc->display, proc->xwin)) { rc = err_copy(proc, proc->window); goto done; } } if(proc->video && proc->force_input) { - if(zebra_video_init(proc->video, proc->force_input)) + if(zbar_video_init(proc->video, proc->force_input)) rc = err_copy(proc, proc->video); } else if(proc->video) - while(zebra_negotiate_format(proc->video, proc->window)) { + while(zbar_negotiate_format(proc->video, proc->window)) { if(proc->video && proc->window) { fprintf(stderr, "WARNING: no compatible input to output format\n" "...trying again with output disabled\n"); - zebra_window_destroy(proc->window); + zbar_window_destroy(proc->window); proc->window = NULL; } else { zprintf(1, "ERROR: no compatible %s format\n", (proc->video) ? "video input" : "window output"); - rc = err_capture(proc, SEV_ERROR, ZEBRA_ERR_UNSUPPORTED, + rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "no compatible image format"); goto done; } @@ -593,22 +593,22 @@ int zebra_processor_init (zebra_processor_t *proc, return(rc); } -zebra_image_data_handler_t* -zebra_processor_set_data_handler (zebra_processor_t *proc, - zebra_image_data_handler_t *handler, - const void *userdata) +zbar_image_data_handler_t* +zbar_processor_set_data_handler (zbar_processor_t *proc, + zbar_image_data_handler_t *handler, + const void *userdata) { if(proc_lock(proc) < 0) return(NULL); - zebra_image_data_handler_t *result = proc->handler; + zbar_image_data_handler_t *result = proc->handler; proc->handler = handler; proc->userdata = userdata; proc_unlock(proc); return(result); } -void zebra_processor_set_userdata (zebra_processor_t *proc, - void *userdata) +void zbar_processor_set_userdata (zbar_processor_t *proc, + void *userdata) { if(proc_lock(proc) < 0) return; @@ -616,52 +616,52 @@ void zebra_processor_set_userdata (zebra_processor_t *proc, proc_unlock(proc); } -void *zebra_processor_get_userdata (const zebra_processor_t *proc) +void *zbar_processor_get_userdata (const zbar_processor_t *proc) { return((void*)proc->userdata); } -int zebra_processor_set_config (zebra_processor_t *proc, - zebra_symbol_type_t sym, - zebra_config_t cfg, - int val) +int zbar_processor_set_config (zbar_processor_t *proc, + zbar_symbol_type_t sym, + zbar_config_t cfg, + int val) { - return(zebra_image_scanner_set_config(proc->scanner, sym, cfg, val)); + return(zbar_image_scanner_set_config(proc->scanner, sym, cfg, val)); } -int zebra_processor_request_size (zebra_processor_t *proc, - unsigned width, - unsigned height) +int zbar_processor_request_size (zbar_processor_t *proc, + unsigned width, + unsigned height) { proc->req_width = width; proc->req_height = height; return(0); } -int zebra_processor_request_interface (zebra_processor_t *proc, - int ver) +int zbar_processor_request_interface (zbar_processor_t *proc, + int ver) { proc->req_v4l = ver; return(0); } -int zebra_processor_request_iomode (zebra_processor_t *proc, - int iomode) +int zbar_processor_request_iomode (zbar_processor_t *proc, + int iomode) { proc->req_iomode = iomode; return(0); } -int zebra_processor_force_format (zebra_processor_t *proc, - unsigned long input, - unsigned long output) +int zbar_processor_force_format (zbar_processor_t *proc, + unsigned long input, + unsigned long output) { proc->force_input = input; proc->force_output = output; return(0); } -int zebra_processor_is_visible (zebra_processor_t *proc) +int zbar_processor_is_visible (zbar_processor_t *proc) { if(proc_lock(proc) < 0) return(-1); @@ -670,29 +670,29 @@ int zebra_processor_is_visible (zebra_processor_t *proc) return(visible); } -int zebra_processor_set_visible (zebra_processor_t *proc, - int visible) +int zbar_processor_set_visible (zbar_processor_t *proc, + int visible) { if(proc_lock(proc) < 0) return(-1); int rc = 0; if(proc->window) { if(proc->video) - rc = _zebra_window_resize(proc, - zebra_video_get_width(proc->video), - zebra_video_get_height(proc->video)); + rc = _zbar_window_resize(proc, + zbar_video_get_width(proc->video), + zbar_video_get_height(proc->video)); if(!rc) - rc = _zebra_window_set_visible(proc, visible); + rc = _zbar_window_set_visible(proc, visible); } else if(visible) - rc = err_capture(proc, SEV_ERROR, ZEBRA_ERR_INVALID, __func__, + rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "processor display window not initialized"); proc_unlock(proc); return(rc); } -int zebra_processor_user_wait (zebra_processor_t *proc, - int timeout) +int zbar_processor_user_wait (zbar_processor_t *proc, + int timeout) { if(proc_lock(proc) < 0) return(-1); @@ -703,13 +703,13 @@ int zebra_processor_user_wait (zebra_processor_t *proc, rc = proc->input; proc_unlock(proc); if(!proc->visible) - return(err_capture(proc, SEV_WARNING, ZEBRA_ERR_CLOSED, __func__, + return(err_capture(proc, SEV_WARNING, ZBAR_ERR_CLOSED, __func__, "display window not available for input")); return(rc); } -int zebra_processor_set_active (zebra_processor_t *proc, - int active) +int zbar_processor_set_active (zbar_processor_t *proc, + int active) { if(proc_lock(proc) < 0) return(-1); @@ -717,10 +717,10 @@ int zebra_processor_set_active (zebra_processor_t *proc, proc_unlock(proc); return(-1); } - zebra_image_scanner_enable_cache(proc->scanner, active); - int rc = zebra_video_enable(proc->video, active); + zbar_image_scanner_enable_cache(proc->scanner, active); + int rc = zbar_video_enable(proc->video, active); if(!rc) { - int vid_fd = zebra_video_get_fd(proc->video); + int vid_fd = zbar_video_get_fd(proc->video); if(vid_fd >= 0) { if(active) add_poll(proc, vid_fd, proc_video_handler); @@ -748,17 +748,17 @@ int zebra_processor_set_active (zebra_processor_t *proc, return(rc); } -int zebra_process_one (zebra_processor_t *proc, - int timeout) +int zbar_process_one (zbar_processor_t *proc, + int timeout) { if(proc_lock(proc) < 0) return(-1); int rc = 0; if(proc->video) { - zebra_image_scanner_enable_cache(proc->scanner, 1); - rc = zebra_video_enable(proc->video, 1); + zbar_image_scanner_enable_cache(proc->scanner, 1); + rc = zbar_video_enable(proc->video, 1); /* FIXME failure recovery? */ - int vid_fd = zebra_video_get_fd(proc->video); + int vid_fd = zbar_video_get_fd(proc->video); if(vid_fd >= 0) add_poll(proc, vid_fd, proc_video_handler); proc->active = 1; @@ -766,12 +766,12 @@ int zebra_process_one (zebra_processor_t *proc, pthread_cond_broadcast(&proc->event); #endif proc_event_wait(proc, EVENT_OUTPUT, timeout); - rc = zebra_video_enable(proc->video, 0); + rc = zbar_video_enable(proc->video, 0); if(vid_fd >= 0) remove_poll(proc, vid_fd); proc->active = 0; proc->events &= ~EVENT_INPUT; - zebra_image_scanner_enable_cache(proc->scanner, 0); + zbar_image_scanner_enable_cache(proc->scanner, 0); } else rc = -1; @@ -779,21 +779,21 @@ int zebra_process_one (zebra_processor_t *proc, return(rc); } -int zebra_process_image (zebra_processor_t *proc, - zebra_image_t *img) +int zbar_process_image (zbar_processor_t *proc, + zbar_image_t *img) { if(proc_lock(proc) < 0) return(-1); int rc = 0; if(img && proc->window) - rc = _zebra_window_resize(proc, - zebra_image_get_width(img), - zebra_image_get_height(img)); + rc = _zbar_window_resize(proc, + zbar_image_get_width(img), + zbar_image_get_height(img)); if(!rc) { - zebra_image_scanner_enable_cache(proc->scanner, 0); + zbar_image_scanner_enable_cache(proc->scanner, 0); rc = process_image(proc, img); if(proc->active) - zebra_image_scanner_enable_cache(proc->scanner, 1); + zbar_image_scanner_enable_cache(proc->scanner, 1); } proc_unlock(proc); return(rc); diff --git a/zebra/processor.h b/zbar/processor.h similarity index 81% rename from zebra/processor.h rename to zbar/processor.h index b9f48be..cda4b6b 100644 --- a/zebra/processor.h +++ b/zbar/processor.h @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #ifndef _PROCESSOR_H_ #define _PROCESSOR_H_ @@ -40,10 +40,10 @@ # include #endif -#include +#include #include "error.h" -typedef int (poll_handler_t)(zebra_processor_t*, int); +typedef int (poll_handler_t)(zbar_processor_t*, int); /* poll information */ typedef struct poll_desc_s { @@ -52,15 +52,15 @@ typedef struct poll_desc_s { poll_handler_t **handlers; /* poll handlers */ } poll_desc_t; -struct zebra_processor_s { +struct zbar_processor_s { errinfo_t err; /* error reporting */ const void *userdata; /* application data */ - zebra_video_t *video; /* input video device abstraction */ - zebra_window_t *window; /* output window abstraction */ - zebra_image_scanner_t *scanner; /* barcode scanner */ + zbar_video_t *video; /* input video device abstraction */ + zbar_window_t *window; /* output window abstraction */ + zbar_image_scanner_t *scanner; /* barcode scanner */ - zebra_image_data_handler_t *handler; /* application data handler */ + zbar_image_data_handler_t *handler; /* application data handler */ unsigned req_width, req_height; /* application requested video size */ int req_v4l, req_iomode; /* application requested v4l version */ @@ -111,7 +111,7 @@ static inline int alloc_polls (volatile poll_desc_t *p) return(0); } -static inline int add_poll (zebra_processor_t *proc, +static inline int add_poll (zbar_processor_t *proc, int fd, poll_handler_t *handler) { @@ -133,7 +133,7 @@ static inline int add_poll (zebra_processor_t *proc, return(i); } -static inline int remove_poll (zebra_processor_t *proc, +static inline int remove_poll (zbar_processor_t *proc, int fd) { int i; @@ -161,7 +161,7 @@ static inline int remove_poll (zebra_processor_t *proc, return(rc); } -static inline void emit (zebra_processor_t *proc, +static inline void emit (zbar_processor_t *proc, unsigned mask) { proc->events |= mask; @@ -172,11 +172,11 @@ static inline void emit (zebra_processor_t *proc, #endif } -extern int _zebra_window_open(zebra_processor_t*, char*, unsigned, unsigned); -extern int _zebra_window_close(zebra_processor_t*); -extern int _zebra_window_set_visible(zebra_processor_t*, int); -extern int _zebra_window_invalidate(zebra_window_t*); -extern int _zebra_window_resize(zebra_processor_t*, unsigned, unsigned); -extern int _zebra_window_handle_events(zebra_processor_t*, int); +extern int _zbar_window_open(zbar_processor_t*, char*, unsigned, unsigned); +extern int _zbar_window_close(zbar_processor_t*); +extern int _zbar_window_set_visible(zbar_processor_t*, int); +extern int _zbar_window_invalidate(zbar_window_t*); +extern int _zbar_window_resize(zbar_processor_t*, unsigned, unsigned); +extern int _zbar_window_handle_events(zbar_processor_t*, int); #endif diff --git a/zebra/scanner.c b/zbar/scanner.c similarity index 61% rename from zebra/scanner.c rename to zbar/scanner.c index ad92477..248ca56 100644 --- a/zebra/scanner.c +++ b/zbar/scanner.c @@ -1,66 +1,66 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include #include /* malloc, free, abs */ #include /* memset */ -#include +#include #ifdef DEBUG_SCANNER # define DEBUG_LEVEL (DEBUG_SCANNER) #endif #include "debug.h" -#ifndef ZEBRA_FIXED -# define ZEBRA_FIXED 5 +#ifndef ZBAR_FIXED +# define ZBAR_FIXED 5 #endif -#define ROUND (1 << (ZEBRA_FIXED - 1)) +#define ROUND (1 << (ZBAR_FIXED - 1)) /* FIXME add runtime config API for these */ -#ifndef ZEBRA_SCANNER_THRESH_MIN -# define ZEBRA_SCANNER_THRESH_MIN 4 +#ifndef ZBAR_SCANNER_THRESH_MIN +# define ZBAR_SCANNER_THRESH_MIN 4 #endif -#ifndef ZEBRA_SCANNER_THRESH_INIT_WEIGHT -# define ZEBRA_SCANNER_THRESH_INIT_WEIGHT .44 +#ifndef ZBAR_SCANNER_THRESH_INIT_WEIGHT +# define ZBAR_SCANNER_THRESH_INIT_WEIGHT .44 #endif -#define THRESH_INIT ((unsigned)((ZEBRA_SCANNER_THRESH_INIT_WEIGHT \ - * (1 << (ZEBRA_FIXED + 1)) + 1) / 2)) +#define THRESH_INIT ((unsigned)((ZBAR_SCANNER_THRESH_INIT_WEIGHT \ + * (1 << (ZBAR_FIXED + 1)) + 1) / 2)) -#ifndef ZEBRA_SCANNER_THRESH_FADE -# define ZEBRA_SCANNER_THRESH_FADE 8 +#ifndef ZBAR_SCANNER_THRESH_FADE +# define ZBAR_SCANNER_THRESH_FADE 8 #endif -#ifndef ZEBRA_SCANNER_EWMA_WEIGHT -# define ZEBRA_SCANNER_EWMA_WEIGHT .78 +#ifndef ZBAR_SCANNER_EWMA_WEIGHT +# define ZBAR_SCANNER_EWMA_WEIGHT .78 #endif -#define EWMA_WEIGHT ((unsigned)((ZEBRA_SCANNER_EWMA_WEIGHT \ - * (1 << (ZEBRA_FIXED + 1)) + 1) / 2)) +#define EWMA_WEIGHT ((unsigned)((ZBAR_SCANNER_EWMA_WEIGHT \ + * (1 << (ZBAR_FIXED + 1)) + 1) / 2)) /* scanner state */ -struct zebra_scanner_s { - zebra_decoder_t *decoder; /* associated bar width decoder */ +struct zbar_scanner_s { + zbar_decoder_t *decoder; /* associated bar width decoder */ unsigned y1_min_thresh; /* minimum threshold */ unsigned x; /* relative scan position of next sample */ @@ -74,40 +74,40 @@ struct zebra_scanner_s { unsigned width; /* last element width */ }; -zebra_scanner_t *zebra_scanner_create (zebra_decoder_t *dcode) +zbar_scanner_t *zbar_scanner_create (zbar_decoder_t *dcode) { - zebra_scanner_t *scn = malloc(sizeof(zebra_scanner_t)); + zbar_scanner_t *scn = malloc(sizeof(zbar_scanner_t)); scn->decoder = dcode; - scn->y1_min_thresh = ZEBRA_SCANNER_THRESH_MIN; - zebra_scanner_reset(scn); + scn->y1_min_thresh = ZBAR_SCANNER_THRESH_MIN; + zbar_scanner_reset(scn); return(scn); } -void zebra_scanner_destroy (zebra_scanner_t *scn) +void zbar_scanner_destroy (zbar_scanner_t *scn) { free(scn); } -zebra_symbol_type_t zebra_scanner_reset (zebra_scanner_t *scn) +zbar_symbol_type_t zbar_scanner_reset (zbar_scanner_t *scn) { - memset(&scn->x, 0, sizeof(zebra_scanner_t) + (void*)scn - (void*)&scn->x); + memset(&scn->x, 0, sizeof(zbar_scanner_t) + (void*)scn - (void*)&scn->x); scn->y1_thresh = scn->y1_min_thresh; if(scn->decoder) - zebra_decoder_reset(scn->decoder); - return(ZEBRA_NONE); + zbar_decoder_reset(scn->decoder); + return(ZBAR_NONE); } -unsigned zebra_scanner_get_width (const zebra_scanner_t *scn) +unsigned zbar_scanner_get_width (const zbar_scanner_t *scn) { return(scn->width); } -zebra_color_t zebra_scanner_get_color (const zebra_scanner_t *scn) +zbar_color_t zbar_scanner_get_color (const zbar_scanner_t *scn) { - return((scn->y1_sign <= 0) ? ZEBRA_SPACE : ZEBRA_BAR); + return((scn->y1_sign <= 0) ? ZBAR_SPACE : ZBAR_BAR); } -static inline unsigned calc_thresh (zebra_scanner_t *scn) +static inline unsigned calc_thresh (zbar_scanner_t *scn) { /* threshold 1st to improve noise rejection */ unsigned thresh = scn->y1_thresh; @@ -116,13 +116,13 @@ static inline unsigned calc_thresh (zebra_scanner_t *scn) return(scn->y1_min_thresh); } /* slowly return threshold to min */ - unsigned dx = (scn->x << ZEBRA_FIXED) - scn->last_edge; + unsigned dx = (scn->x << ZBAR_FIXED) - scn->last_edge; unsigned long t = thresh * dx; t /= scn->width; - t /= ZEBRA_SCANNER_THRESH_FADE; + t /= ZBAR_SCANNER_THRESH_FADE; dprintf(1, " thr=%d t=%ld x=%d last=%d.%d (%d)", - thresh, t, scn->x, scn->last_edge >> ZEBRA_FIXED, - scn->last_edge & ((1 << ZEBRA_FIXED) - 1), dx); + thresh, t, scn->x, scn->last_edge >> ZBAR_FIXED, + scn->last_edge & ((1 << ZBAR_FIXED) - 1), dx); if(thresh > t) { thresh -= t; if(thresh > scn->y1_min_thresh) @@ -132,43 +132,43 @@ static inline unsigned calc_thresh (zebra_scanner_t *scn) return(scn->y1_min_thresh); } -static inline zebra_symbol_type_t process_edge (zebra_scanner_t *scn, - int y1) +static inline zbar_symbol_type_t process_edge (zbar_scanner_t *scn, + int y1) { scn->width = scn->cur_edge - scn->last_edge; dprintf(1, " sgn=%d cur=%d.%d w=%d (%s)\n", - scn->y1_sign, scn->cur_edge >> ZEBRA_FIXED, - scn->cur_edge & ((1 << ZEBRA_FIXED) - 1), scn->width, + scn->y1_sign, scn->cur_edge >> ZBAR_FIXED, + scn->cur_edge & ((1 << ZBAR_FIXED) - 1), scn->width, ((y1 > 0) ? "SPACE" : "BAR")); scn->last_edge = scn->cur_edge; /* pass to decoder */ if(scn->width || (y1 > 0)) { if(scn->decoder) - return(zebra_decode_width(scn->decoder, scn->width)); - return(ZEBRA_PARTIAL); + return(zbar_decode_width(scn->decoder, scn->width)); + return(ZBAR_PARTIAL); } /* skip initial transition */ - return(ZEBRA_NONE); + return(ZBAR_NONE); } -zebra_symbol_type_t zebra_scanner_new_scan (zebra_scanner_t *scn) +zbar_symbol_type_t zbar_scanner_new_scan (zbar_scanner_t *scn) { /* finalize outstanding edge */ - zebra_symbol_type_t edge = process_edge(scn, 0); + zbar_symbol_type_t edge = process_edge(scn, 0); /* reset color to SPACE * (actually just resets everything) */ - memset(&scn->x, 0, sizeof(zebra_scanner_t) + (void*)scn - (void*)&scn->x); + memset(&scn->x, 0, sizeof(zbar_scanner_t) + (void*)scn - (void*)&scn->x); scn->y1_thresh = scn->y1_min_thresh; if(scn->decoder) - zebra_decoder_new_scan(scn->decoder); + zbar_decoder_new_scan(scn->decoder); return(edge); } -zebra_symbol_type_t zebra_scan_y (zebra_scanner_t *scn, - int y) +zbar_symbol_type_t zbar_scan_y (zbar_scanner_t *scn, + int y) { /* FIXME calc and clip to max y range... */ /* retrieve short value history */ @@ -176,7 +176,7 @@ zebra_symbol_type_t zebra_scan_y (zebra_scanner_t *scn, register int y0_0 = y0_1; if(scn->x) { /* update weighted moving average */ - y0_0 += ((int)((y - y0_1) * EWMA_WEIGHT)) >> ZEBRA_FIXED; + y0_0 += ((int)((y - y0_1) * EWMA_WEIGHT)) >> ZBAR_FIXED; scn->y0[scn->x & 3] = y0_0; } else @@ -198,7 +198,7 @@ zebra_symbol_type_t zebra_scan_y (zebra_scanner_t *scn, dprintf(1, "scan: y=%d y0=%d y1=%d y2=%d", y, y0_1, y1_1, y2_1); - zebra_symbol_type_t edge = ZEBRA_NONE; + zbar_symbol_type_t edge = ZBAR_NONE; /* 2nd zero-crossing is 1st local min/max - could be edge */ if((!y2_1 || ((y2_1 > 0) ? y2_2 < 0 : y2_2 > 0)) && @@ -217,20 +217,20 @@ zebra_symbol_type_t zebra_scan_y (zebra_scanner_t *scn, /* adaptive thresholding */ /* start at multiple of new min/max */ - scn->y1_thresh = (abs(y1_1) * THRESH_INIT + ROUND) >> ZEBRA_FIXED; + scn->y1_thresh = (abs(y1_1) * THRESH_INIT + ROUND) >> ZBAR_FIXED; dprintf(1, " thr=%d", scn->y1_thresh); if(scn->y1_thresh < scn->y1_min_thresh) scn->y1_thresh = scn->y1_min_thresh; /* update current edge */ int d = y2_1 - y2_2; - scn->cur_edge = 1 << ZEBRA_FIXED; + scn->cur_edge = 1 << ZBAR_FIXED; if(!d) scn->cur_edge >>= 1; else if(y2_1) /* interpolate zero crossing */ - scn->cur_edge -= ((y2_1 << ZEBRA_FIXED) + 1) / d; - scn->cur_edge += scn->x << ZEBRA_FIXED; + scn->cur_edge -= ((y2_1 << ZBAR_FIXED) + 1) / d; + scn->cur_edge += scn->x << ZBAR_FIXED; } } else @@ -242,14 +242,14 @@ zebra_symbol_type_t zebra_scan_y (zebra_scanner_t *scn, } /* undocumented API for drawing cutesy debug graphics */ -void zebra_scanner_get_state (const zebra_scanner_t *scn, - unsigned *x, - unsigned *cur_edge, - unsigned *last_edge, - int *y0, - int *y1, - int *y2, - int *y1_thresh) +void zbar_scanner_get_state (const zbar_scanner_t *scn, + unsigned *x, + unsigned *cur_edge, + unsigned *last_edge, + int *y0, + int *y1, + int *y2, + int *y1_thresh) { register int y0_0 = scn->y0[(scn->x - 1) & 3]; register int y0_1 = scn->y0[(scn->x - 2) & 3]; @@ -261,6 +261,6 @@ void zebra_scanner_get_state (const zebra_scanner_t *scn, if(y1) *y1 = y0_1 - y0_2; if(y2) *y2 = y0_0 - (y0_1 * 2) + y0_2; /* NB not quite accurate (uses updated x) */ - zebra_scanner_t *mut_scn = (zebra_scanner_t*)scn; + zbar_scanner_t *mut_scn = (zbar_scanner_t*)scn; if(y1_thresh) *y1_thresh = calc_thresh(mut_scn); } diff --git a/zebra/symbol.c b/zbar/symbol.c similarity index 60% rename from zebra/symbol.c rename to zbar/symbol.c index de44422..61dc28f 100644 --- a/zebra/symbol.c +++ b/zbar/symbol.c @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include @@ -26,57 +26,57 @@ #include #include -#include +#include #include "symbol.h" -const char *zebra_get_symbol_name (zebra_symbol_type_t sym) +const char *zbar_get_symbol_name (zbar_symbol_type_t sym) { - switch(sym & ZEBRA_SYMBOL) { - case ZEBRA_EAN8: return("EAN-8"); - case ZEBRA_UPCE: return("UPC-E"); - case ZEBRA_ISBN10: return("ISBN-10"); - case ZEBRA_UPCA: return("UPC-A"); - case ZEBRA_EAN13: return("EAN-13"); - case ZEBRA_ISBN13: return("ISBN-13"); - case ZEBRA_I25: return("I2/5"); - case ZEBRA_CODE39: return("CODE-39"); - case ZEBRA_CODE128: return("CODE-128"); - case ZEBRA_PDF417: return("PDF417"); + switch(sym & ZBAR_SYMBOL) { + case ZBAR_EAN8: return("EAN-8"); + case ZBAR_UPCE: return("UPC-E"); + case ZBAR_ISBN10: return("ISBN-10"); + case ZBAR_UPCA: return("UPC-A"); + case ZBAR_EAN13: return("EAN-13"); + case ZBAR_ISBN13: return("ISBN-13"); + case ZBAR_I25: return("I2/5"); + case ZBAR_CODE39: return("CODE-39"); + case ZBAR_CODE128: return("CODE-128"); + case ZBAR_PDF417: return("PDF417"); default: return("UNKNOWN"); } } -const char *zebra_get_addon_name (zebra_symbol_type_t sym) +const char *zbar_get_addon_name (zbar_symbol_type_t sym) { - switch(sym & ZEBRA_ADDON) { - case ZEBRA_ADDON2: return("+2"); - case ZEBRA_ADDON5: return("+5"); + switch(sym & ZBAR_ADDON) { + case ZBAR_ADDON2: return("+2"); + case ZBAR_ADDON5: return("+5"); default: return(""); } } -zebra_symbol_type_t zebra_symbol_get_type (const zebra_symbol_t *sym) +zbar_symbol_type_t zbar_symbol_get_type (const zbar_symbol_t *sym) { return(sym->type); } -const char *zebra_symbol_get_data (const zebra_symbol_t *sym) +const char *zbar_symbol_get_data (const zbar_symbol_t *sym) { return(sym->data); } -int zebra_symbol_get_count (const zebra_symbol_t *sym) +int zbar_symbol_get_count (const zbar_symbol_t *sym) { return(sym->cache_count); } -unsigned zebra_symbol_get_loc_size (const zebra_symbol_t *sym) +unsigned zbar_symbol_get_loc_size (const zbar_symbol_t *sym) { return(sym->npts); } -int zebra_symbol_get_loc_x (const zebra_symbol_t *sym, - unsigned idx) +int zbar_symbol_get_loc_x (const zbar_symbol_t *sym, + unsigned idx) { if(idx < sym->npts) return(sym->pts[idx].x); @@ -84,8 +84,8 @@ int zebra_symbol_get_loc_x (const zebra_symbol_t *sym, return(-1); } -int zebra_symbol_get_loc_y (const zebra_symbol_t *sym, - unsigned idx) +int zbar_symbol_get_loc_y (const zbar_symbol_t *sym, + unsigned idx) { if(idx < sym->npts) return(sym->pts[idx].y); @@ -93,7 +93,7 @@ int zebra_symbol_get_loc_y (const zebra_symbol_t *sym, return(-1); } -const zebra_symbol_t *zebra_symbol_next (const zebra_symbol_t *sym) +const zbar_symbol_t *zbar_symbol_next (const zbar_symbol_t *sym) { return((sym) ? sym->next : NULL); } @@ -115,11 +115,11 @@ static inline void growbuf (unsigned **buf, { } -char *zebra_symbol_xml (const zebra_symbol_t *sym, - char **buf, - unsigned *len) +char *zbar_symbol_xml (const zbar_symbol_t *sym, + char **buf, + unsigned *len) { - const char *type = zebra_get_symbol_name(sym->type); + const char *type = zbar_get_symbol_name(sym->type); unsigned datalen = strlen(sym->data); unsigned maxlen = (strlen(xmlfmt[0]) + strlen(xmlfmt[1]) + strlen(xmlfmt[2]) + strlen(xmlfmt[3]) + diff --git a/zebra/symbol.h b/zbar/symbol.h similarity index 72% rename from zebra/symbol.h rename to zbar/symbol.h index 5bafa21..9fb44ab 100644 --- a/zebra/symbol.h +++ b/zbar/symbol.h @@ -1,37 +1,37 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #ifndef _SYMBOL_H_ #define _SYMBOL_H_ #include -#include +#include typedef struct point_s { int x, y; } point_t; -struct zebra_symbol_s { - zebra_symbol_type_t type; /* symbol type */ +struct zbar_symbol_s { + zbar_symbol_type_t type; /* symbol type */ unsigned int datalen; /* allocation size of data */ char *data; /* ascii symbol data */ @@ -39,12 +39,12 @@ struct zebra_symbol_s { unsigned npts; /* number of points in location polygon */ point_t *pts; /* list of points in location polygon */ - zebra_symbol_t *next; /* linked list of results */ + zbar_symbol_t *next; /* linked list of results */ unsigned long time; /* relative symbol capture time */ int cache_count; /* cache state */ }; -static inline void sym_add_point (zebra_symbol_t *sym, +static inline void sym_add_point (zbar_symbol_t *sym, int x, int y) { @@ -55,7 +55,7 @@ static inline void sym_add_point (zebra_symbol_t *sym, sym->pts[i].y = y; } -static inline void sym_destroy (zebra_symbol_t *sym) +static inline void sym_destroy (zbar_symbol_t *sym) { if(sym->pts) free(sym->pts); diff --git a/zebra/video.c b/zbar/video.c similarity index 64% rename from zebra/video.c rename to zbar/video.c index ad8d740..0944aae 100644 --- a/zebra/video.c +++ b/zbar/video.c @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include "video.h" @@ -26,13 +26,13 @@ #ifdef HAVE_LIBJPEG -extern struct jpeg_decompress_struct *_zebra_jpeg_decomp_create(); -extern void _zebra_jpeg_decomp_destroy(struct jpeg_decompress_struct *cinfo); +extern struct jpeg_decompress_struct *_zbar_jpeg_decomp_create(); +extern void _zbar_jpeg_decomp_destroy(struct jpeg_decompress_struct *cinfo); #endif -static void _zebra_video_recycle_image (zebra_image_t *img) +static void _zbar_video_recycle_image (zbar_image_t *img) { - zebra_video_t *vdo = img->src; + zbar_video_t *vdo = img->src; assert(vdo); assert(img->srcidx >= 0); (void)video_lock(vdo); @@ -44,9 +44,9 @@ static void _zebra_video_recycle_image (zebra_image_t *img) (void)video_unlock(vdo); } -static void _zebra_video_recycle_shadow (zebra_image_t *img) +static void _zbar_video_recycle_shadow (zbar_image_t *img) { - zebra_video_t *vdo = img->src; + zbar_video_t *vdo = img->src; assert(vdo); assert(img->srcidx == -1); (void)video_lock(vdo); @@ -55,12 +55,12 @@ static void _zebra_video_recycle_shadow (zebra_image_t *img) (void)video_unlock(vdo); } -zebra_video_t *zebra_video_create () +zbar_video_t *zbar_video_create () { - zebra_video_t *vdo = calloc(1, sizeof(zebra_video_t)); + zbar_video_t *vdo = calloc(1, sizeof(zbar_video_t)); if(!vdo) return(NULL); - err_init(&vdo->err, ZEBRA_MOD_VIDEO); + err_init(&vdo->err, ZBAR_MOD_VIDEO); vdo->fd = -1; #ifdef HAVE_LIBPTHREAD @@ -71,22 +71,22 @@ zebra_video_t *zebra_video_create () #endif /* pre-allocate images */ - vdo->num_images = ZEBRA_VIDEO_IMAGES_MAX; - vdo->images = calloc(ZEBRA_VIDEO_IMAGES_MAX, sizeof(zebra_image_t*)); + vdo->num_images = ZBAR_VIDEO_IMAGES_MAX; + vdo->images = calloc(ZBAR_VIDEO_IMAGES_MAX, sizeof(zbar_image_t*)); if(!vdo->images) { - zebra_video_destroy(vdo); + zbar_video_destroy(vdo); return(NULL); } int i; - for(i = 0; i < ZEBRA_VIDEO_IMAGES_MAX; i++) { - zebra_image_t *img = vdo->images[i] = zebra_image_create(); + for(i = 0; i < ZBAR_VIDEO_IMAGES_MAX; i++) { + zbar_image_t *img = vdo->images[i] = zbar_image_create(); if(!img) { - zebra_video_destroy(vdo); + zbar_video_destroy(vdo); return(NULL); } img->refcnt = 0; - img->cleanup = _zebra_video_recycle_image; + img->cleanup = _zbar_video_recycle_image; img->srcidx = i; img->src = vdo; } @@ -94,19 +94,19 @@ zebra_video_t *zebra_video_create () return(vdo); } -void zebra_video_destroy (zebra_video_t *vdo) +void zbar_video_destroy (zbar_video_t *vdo) { if(vdo->fd >= 0) - zebra_video_open(vdo, NULL); + zbar_video_open(vdo, NULL); if(vdo->images) { int i; - for(i = 0; i < ZEBRA_VIDEO_IMAGES_MAX; i++) + for(i = 0; i < ZBAR_VIDEO_IMAGES_MAX; i++) if(vdo->images[i]) free(vdo->images[i]); free(vdo->images); } while(vdo->shadow_image) { - zebra_image_t *img = vdo->shadow_image; + zbar_image_t *img = vdo->shadow_image; vdo->shadow_image = img->next; free((void*)img->data); img->data = NULL; @@ -122,43 +122,43 @@ void zebra_video_destroy (zebra_video_t *vdo) #endif #ifdef HAVE_LIBJPEG if(vdo->jpeg_img) { - zebra_image_destroy(vdo->jpeg_img); + zbar_image_destroy(vdo->jpeg_img); vdo->jpeg_img = NULL; } if(vdo->jpeg) { - _zebra_jpeg_decomp_destroy(vdo->jpeg); + _zbar_jpeg_decomp_destroy(vdo->jpeg); vdo->jpeg = NULL; } #endif free(vdo); } -int zebra_video_open (zebra_video_t *vdo, - const char *dev) +int zbar_video_open (zbar_video_t *vdo, + const char *dev) { - return(_zebra_video_open(vdo, dev)); + return(_zbar_video_open(vdo, dev)); } -int zebra_video_get_fd (const zebra_video_t *vdo) +int zbar_video_get_fd (const zbar_video_t *vdo) { if(vdo->fd >= 0 && vdo->intf == VIDEO_V4L2) return(vdo->fd); if(vdo->intf != VIDEO_V4L2) - return(err_capture(vdo, SEV_WARNING, ZEBRA_ERR_UNSUPPORTED, __func__, + return(err_capture(vdo, SEV_WARNING, ZBAR_ERR_UNSUPPORTED, __func__, "v4l1 API does not support polling")); - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_INVALID, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "video device not opened")); } -int zebra_video_request_size (zebra_video_t *vdo, - unsigned width, - unsigned height) +int zbar_video_request_size (zbar_video_t *vdo, + unsigned width, + unsigned height) { if(vdo->initialized) /* FIXME re-init different format? */ - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_INVALID, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "already initialized, unable to resize")); vdo->width = width; @@ -167,46 +167,46 @@ int zebra_video_request_size (zebra_video_t *vdo, return(0); } -int zebra_video_request_interface (zebra_video_t *vdo, - int ver) +int zbar_video_request_interface (zbar_video_t *vdo, + int ver) { if(vdo->fd >= 0) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_INVALID, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "device already opened, unable to change interface")); vdo->intf = (video_interface_t)ver; zprintf(1, "request interface version %d\n", vdo->intf); return(0); } -int zebra_video_request_iomode (zebra_video_t *vdo, - int iomode) +int zbar_video_request_iomode (zbar_video_t *vdo, + int iomode) { if(vdo->fd >= 0) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_INVALID, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "device already opened, unable to change iomode")); if(iomode < 0 || iomode > VIDEO_USERPTR) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_INVALID, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "invalid iomode requested")); vdo->iomode = iomode; return(0); } -int zebra_video_get_width (const zebra_video_t *vdo) +int zbar_video_get_width (const zbar_video_t *vdo) { return(vdo->width); } -int zebra_video_get_height (const zebra_video_t *vdo) +int zbar_video_get_height (const zbar_video_t *vdo) { return(vdo->height); } -uint32_t zebra_video_get_format (const zebra_video_t *vdo) +uint32_t zbar_video_get_format (const zbar_video_t *vdo) { return(vdo->format); } -static inline int video_init_images (zebra_video_t *vdo) +static inline int video_init_images (zbar_video_t *vdo) { assert(vdo->datalen); @@ -215,7 +215,7 @@ static inline int video_init_images (zebra_video_t *vdo) vdo->buflen = vdo->num_images * vdo->datalen; vdo->buf = malloc(vdo->buflen); if(!vdo->buf) - return(err_capture(vdo, SEV_FATAL, ZEBRA_ERR_NOMEM, __func__, + return(err_capture(vdo, SEV_FATAL, ZBAR_ERR_NOMEM, __func__, "unable to allocate image buffers")); zprintf(1, "pre-allocated %d %s buffers size=0x%lx\n", vdo->num_images, (vdo->iomode == VIDEO_READWRITE) ? "READ" : "USERPTR", @@ -223,7 +223,7 @@ static inline int video_init_images (zebra_video_t *vdo) } int i; for(i = 0; i < vdo->num_images; i++) { - zebra_image_t *img = vdo->images[i]; + zbar_image_t *img = vdo->images[i]; img->format = vdo->format; img->width = vdo->width; img->height = vdo->height; @@ -242,12 +242,12 @@ static inline int video_init_images (zebra_video_t *vdo) return(0); } -int zebra_video_init (zebra_video_t *vdo, - unsigned long fmt) +int zbar_video_init (zbar_video_t *vdo, + unsigned long fmt) { if(vdo->initialized) /* FIXME re-init different format? */ - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_INVALID, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "already initialized, re-init unimplemented")); if(vdo->init(vdo, fmt)) @@ -256,16 +256,16 @@ int zebra_video_init (zebra_video_t *vdo, if(video_init_images(vdo)) return(-1); #ifdef HAVE_LIBJPEG - const zebra_format_def_t *vidfmt = _zebra_format_lookup(fmt); - if(vidfmt->group == ZEBRA_FMT_JPEG) { + const zbar_format_def_t *vidfmt = _zbar_format_lookup(fmt); + if(vidfmt->group == ZBAR_FMT_JPEG) { /* prepare for decoding */ if(!vdo->jpeg) - vdo->jpeg = _zebra_jpeg_decomp_create(); + vdo->jpeg = _zbar_jpeg_decomp_create(); if(vdo->jpeg_img) - zebra_image_destroy(vdo->jpeg_img); + zbar_image_destroy(vdo->jpeg_img); /* create intermediate image for decoder to use*/ - zebra_image_t *img = vdo->jpeg_img = zebra_image_create(); + zbar_image_t *img = vdo->jpeg_img = zbar_image_create(); img->format = fourcc('Y','8','0','0'); img->width = vdo->width; img->height = vdo->height; @@ -276,19 +276,19 @@ int zebra_video_init (zebra_video_t *vdo, return(0); } -int zebra_video_enable (zebra_video_t *vdo, - int enable) +int zbar_video_enable (zbar_video_t *vdo, + int enable) { if(vdo->active == enable) return(0); if(enable) { if(vdo->fd < 0) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_INVALID, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "video device not opened")); if(!vdo->initialized && - zebra_negotiate_format(vdo, NULL)) + zbar_negotiate_format(vdo, NULL)) return(-1); } @@ -301,37 +301,37 @@ int zebra_video_enable (zebra_video_t *vdo, return(vdo->stop(vdo)); } -zebra_image_t *zebra_video_next_image (zebra_video_t *vdo) +zbar_image_t *zbar_video_next_image (zbar_video_t *vdo) { if(video_lock(vdo)) return(NULL); if(!vdo->active) { - err_capture(vdo, SEV_ERROR, ZEBRA_ERR_INVALID, __func__, + err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "video not enabled"); (void)video_unlock(vdo); return(NULL); } unsigned frame = vdo->frame++; - zebra_image_t *img = vdo->dq(vdo); + zbar_image_t *img = vdo->dq(vdo); if(img) { img->seq = frame; if(vdo->num_images < 2) { /* return a *copy* of the video image and immediately recycle * the driver's buffer to avoid deadlocking the resources */ - zebra_image_t *tmp = img; + zbar_image_t *tmp = img; (void)video_lock(vdo); img = vdo->shadow_image; vdo->shadow_image = (img) ? img->next : NULL; (void)video_unlock(vdo); if(!img) { - img = zebra_image_create(); + img = zbar_image_create(); assert(img); img->refcnt = 0; img->src = vdo; /* recycle the shadow images */ - img->cleanup = _zebra_video_recycle_shadow; + img->cleanup = _zbar_video_recycle_shadow; img->format = vdo->format; img->width = vdo->width; @@ -341,7 +341,7 @@ zebra_image_t *zebra_video_next_image (zebra_video_t *vdo) } img->seq = frame; memcpy((void*)img->data, tmp->data, img->datalen); - _zebra_video_recycle_image(tmp); + _zbar_video_recycle_image(tmp); } img->refcnt++; } diff --git a/zebra/video.h b/zbar/video.h similarity index 72% rename from zebra/video.h rename to zbar/video.h index a77f380..fa9f602 100644 --- a/zebra/video.h +++ b/zbar/video.h @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #ifndef _VIDEO_H_ #define _VIDEO_H_ @@ -36,12 +36,12 @@ # include #endif -#include +#include #include "error.h" /* number of images to preallocate */ -#define ZEBRA_VIDEO_IMAGES_MAX 4 +#define ZBAR_VIDEO_IMAGES_MAX 4 typedef enum video_interface_e { VIDEO_INVALID = 0, /* uninitialized */ @@ -55,7 +55,7 @@ typedef enum video_iomode_e { VIDEO_USERPTR, /* userspace buffers */ } video_iomode_t; -struct zebra_video_s { +struct zbar_video_s { errinfo_t err; /* error reporting */ int fd; /* open camera device */ unsigned width, height; /* video frame size */ @@ -74,10 +74,10 @@ struct zebra_video_s { void *buf; /* image data buffer */ int num_images; /* number of allocated images */ - zebra_image_t **images; /* indexed list of images */ - zebra_image_t *nq_image; /* last image enqueued */ - zebra_image_t *dq_image; /* first image to dequeue (when ordered) */ - zebra_image_t *shadow_image; /* special case internal double buffering */ + zbar_image_t **images; /* indexed list of images */ + zbar_image_t *nq_image; /* last image enqueued */ + zbar_image_t *dq_image; /* first image to dequeue (when ordered) */ + zbar_image_t *shadow_image; /* special case internal double buffering */ #ifdef HAVE_LIBPTHREAD pthread_mutex_t qlock; /* lock image queue */ @@ -85,18 +85,18 @@ struct zebra_video_s { #ifdef HAVE_LIBJPEG struct jpeg_decompress_struct *jpeg; /* JPEG decompressor */ - zebra_image_t *jpeg_img; /* temporary image */ + zbar_image_t *jpeg_img; /* temporary image */ #endif unsigned frame; /* frame count */ /* interface dependent methods */ - int (*init)(zebra_video_t*, uint32_t); - int (*cleanup)(zebra_video_t*); - int (*start)(zebra_video_t*); - int (*stop)(zebra_video_t*); - int (*nq)(zebra_video_t*, zebra_image_t*); - zebra_image_t* (*dq)(zebra_video_t*); + int (*init)(zbar_video_t*, uint32_t); + int (*cleanup)(zbar_video_t*); + int (*start)(zbar_video_t*); + int (*stop)(zbar_video_t*); + int (*nq)(zbar_video_t*, zbar_image_t*); + zbar_image_t* (*dq)(zbar_video_t*); }; @@ -105,11 +105,11 @@ struct zebra_video_s { /* video.next_image and video.recycle_image have to be thread safe * wrt/other apis */ -static inline int video_lock (zebra_video_t *vdo) +static inline int video_lock (zbar_video_t *vdo) { int rc = 0; if((rc = pthread_mutex_lock(&vdo->qlock))) { - err_capture(vdo, SEV_FATAL, ZEBRA_ERR_LOCKING, __func__, + err_capture(vdo, SEV_FATAL, ZBAR_ERR_LOCKING, __func__, "unable to acquire lock"); vdo->err.errnum = rc; return(-1); @@ -117,11 +117,11 @@ static inline int video_lock (zebra_video_t *vdo) return(0); } -static inline int video_unlock (zebra_video_t *vdo) +static inline int video_unlock (zbar_video_t *vdo) { int rc = 0; if((rc = pthread_mutex_unlock(&vdo->qlock))) { - err_capture(vdo, SEV_FATAL, ZEBRA_ERR_LOCKING, __func__, + err_capture(vdo, SEV_FATAL, ZBAR_ERR_LOCKING, __func__, "unable to release lock"); vdo->err.errnum = rc; return(-1); @@ -134,7 +134,7 @@ static inline int video_unlock (zebra_video_t *vdo) # define video_unlock(...) (0) #endif -extern int _zebra_video_open(zebra_video_t*, const char*); -extern int _zebra_v4l2_probe(zebra_video_t*); +extern int _zbar_video_open(zbar_video_t*, const char*); +extern int _zbar_v4l2_probe(zbar_video_t*); #endif diff --git a/zebra/video/null.c b/zbar/video/null.c similarity index 64% rename from zebra/video/null.c rename to zbar/video/null.c index 8807d28..2522870 100644 --- a/zebra/video/null.c +++ b/zbar/video/null.c @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ - * Copyright 2008 (c) Jeff Brown + * Copyright 2008-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include "video.h" @@ -26,12 +26,12 @@ static inline int null_error (void *m, const char *func) { - return(err_capture(m, SEV_ERROR, ZEBRA_ERR_UNSUPPORTED, func, + return(err_capture(m, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, func, "not compiled with video input support")); } -int _zebra_video_open (zebra_video_t *vdo, - const char *device) +int _zbar_video_open (zbar_video_t *vdo, + const char *device) { return(null_error(vdo, __func__)); } diff --git a/zebra/video/v4l1.c b/zbar/video/v4l1.c similarity index 83% rename from zebra/video/v4l1.c rename to zbar/video/v4l1.c index 585f9ca..2fb0792 100644 --- a/zebra/video/v4l1.c +++ b/zbar/video/v4l1.c @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include @@ -80,8 +80,8 @@ static const v4l1_format_t v4l1_formats[17] = { { fourcc('Y','U','V','9'), 9 }, /* YUV410P */ }; -static int v4l1_nq (zebra_video_t *vdo, - zebra_image_t *img) +static int v4l1_nq (zbar_video_t *vdo, + zbar_image_t *img) { /* v4l1 maintains queued buffers in order */ img->next = NULL; @@ -102,15 +102,15 @@ static int v4l1_nq (zebra_video_t *vdo, vmap.height = vdo->height; vmap.format = vdo->palette; if(ioctl(vdo->fd, VIDIOCMCAPTURE, &vmap) < 0) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "initiating video capture (VIDIOCMCAPTURE)")); return(0); } -static zebra_image_t *v4l1_dq (zebra_video_t *vdo) +static zbar_image_t *v4l1_dq (zbar_video_t *vdo) { - zebra_image_t *img = NULL; + zbar_image_t *img = NULL; img = vdo->dq_image; if(img) { vdo->dq_image = img->next; @@ -121,7 +121,7 @@ static zebra_image_t *v4l1_dq (zebra_video_t *vdo) if(!img) { /* FIXME block until available? */ - err_capture(vdo, SEV_ERROR, ZEBRA_ERR_BUSY, __func__, + err_capture(vdo, SEV_ERROR, ZBAR_ERR_BUSY, __func__, "all allocated video images busy"); return(NULL); } @@ -129,27 +129,27 @@ static zebra_image_t *v4l1_dq (zebra_video_t *vdo) if(vdo->iomode == VIDEO_MMAP) { int frame = img->srcidx; if(ioctl(vdo->fd, VIDIOCSYNC, &frame) < 0) { - err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "capturing video image (VIDIOCSYNC)"); return(NULL); } } else if(read(vdo->fd, (void*)img->data, img->datalen) != img->datalen) { - err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "reading video image"); return(NULL); } return(img); } -static int v4l1_mmap_buffers (zebra_video_t *vdo) +static int v4l1_mmap_buffers (zbar_video_t *vdo) { #ifdef HAVE_SYS_MMAN_H /* map camera image to memory */ struct video_mbuf vbuf; memset(&vbuf, 0, sizeof(vbuf)); if(ioctl(vdo->fd, VIDIOCGMBUF, &vbuf) < 0) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying video frame buffers (VIDIOCGMBUF)")); assert(vbuf.frames && vbuf.size); @@ -158,12 +158,12 @@ static int v4l1_mmap_buffers (zebra_video_t *vdo) vdo->buf = mmap(0, vbuf.size, PROT_READ | PROT_WRITE, MAP_SHARED, vdo->fd, 0); if(vdo->buf == MAP_FAILED) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "mapping video frame buffers")); int i; for(i = 0; i < vbuf.frames; i++) { - zebra_image_t *img = vdo->images[i]; + zbar_image_t *img = vdo->images[i]; zprintf(2, " [%02d] @%08x\n", img->srcidx, vbuf.offsets[i]); img->data = vdo->buf + vbuf.offsets[i]; img->datalen = vdo->datalen; @@ -180,12 +180,12 @@ static int v4l1_mmap_buffers (zebra_video_t *vdo) } return(0); #else - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_UNSUPPORTED, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "memory mapping not supported")); #endif } -static int v4l1_start (zebra_video_t *vdo) +static int v4l1_start (zbar_video_t *vdo) { /* enqueue all buffers */ int i; @@ -196,7 +196,7 @@ static int v4l1_start (zebra_video_t *vdo) return(0); } -static int v4l1_stop (zebra_video_t *vdo) +static int v4l1_stop (zbar_video_t *vdo) { int i; for(i = 0; i < vdo->num_images; i++) @@ -205,13 +205,13 @@ static int v4l1_stop (zebra_video_t *vdo) return(video_unlock(vdo)); } -static inline int v4l1_set_format (zebra_video_t *vdo, +static inline int v4l1_set_format (zbar_video_t *vdo, uint32_t fmt) { struct video_picture vpic; memset(&vpic, 0, sizeof(vpic)); if(ioctl(vdo->fd, VIDIOCGPICT, &vpic) < 0) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying video format (VIDIOCGPICT)")); vdo->palette = 0; @@ -220,18 +220,18 @@ static inline int v4l1_set_format (zebra_video_t *vdo, if(v4l1_formats[ifmt].format == fmt) break; if(!fmt || ifmt >= VIDEO_PALETTE_YUV410P) - return(err_capture_int(vdo, SEV_ERROR, ZEBRA_ERR_INVALID, __func__, + return(err_capture_int(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "invalid v4l1 format: %08x", fmt)); vpic.palette = ifmt; vpic.depth = v4l1_formats[ifmt].bpp; if(ioctl(vdo->fd, VIDIOCSPICT, &vpic) < 0) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "setting format (VIDIOCSPICT)")); memset(&vpic, 0, sizeof(vpic)); if(ioctl(vdo->fd, VIDIOCGPICT, &vpic) < 0) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying video format (VIDIOCGPICT)")); if(vpic.palette != ifmt || vpic.depth != v4l1_formats[ifmt].bpp) { @@ -240,7 +240,7 @@ static inline int v4l1_set_format (zebra_video_t *vdo, " but probed palette %d with depth %d bpp?" " ...continuing anyway\n", ifmt, v4l1_formats[ifmt].bpp, vpic.palette, vpic.depth); - err_capture_int(vdo, SEV_WARNING, ZEBRA_ERR_INVALID, __func__, + err_capture_int(vdo, SEV_WARNING, ZBAR_ERR_INVALID, __func__, "driver format (%x) inconsistency", fmt); } vdo->format = fmt; @@ -253,7 +253,7 @@ static inline int v4l1_set_format (zebra_video_t *vdo, return(0); } -static int v4l1_init (zebra_video_t *vdo, +static int v4l1_init (zbar_video_t *vdo, uint32_t fmt) { if(v4l1_set_format(vdo, fmt)) @@ -263,13 +263,13 @@ static int v4l1_init (zebra_video_t *vdo, return(0); } -static int v4l1_cleanup (zebra_video_t *vdo) +static int v4l1_cleanup (zbar_video_t *vdo) { #ifdef HAVE_SYS_MMAN_H /* FIXME should avoid holding onto mmap'd buffers so long? */ if(vdo->iomode == VIDEO_MMAP && vdo->buf) { if(munmap(vdo->buf, vdo->buflen)) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "unmapping video frame buffers")); vdo->buf = NULL; /* FIXME reset image */ @@ -278,7 +278,7 @@ static int v4l1_cleanup (zebra_video_t *vdo) return(0); } -static int v4l1_probe_iomode (zebra_video_t *vdo) +static int v4l1_probe_iomode (zbar_video_t *vdo) { vdo->iomode = VIDEO_READWRITE; #ifdef HAVE_SYS_MMAN_H @@ -286,7 +286,7 @@ static int v4l1_probe_iomode (zebra_video_t *vdo) memset(&vbuf, 0, sizeof(vbuf)); if(ioctl(vdo->fd, VIDIOCGMBUF, &vbuf) < 0) { if(errno != EINVAL) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying video frame buffers (VIDIOCGMBUF)")); /* not supported */ return(0); @@ -302,12 +302,12 @@ static int v4l1_probe_iomode (zebra_video_t *vdo) return(0); } -static inline int v4l1_probe_formats (zebra_video_t *vdo) +static inline int v4l1_probe_formats (zbar_video_t *vdo) { struct video_picture vpic; memset(&vpic, 0, sizeof(vpic)); if(ioctl(vdo->fd, VIDIOCGPICT, &vpic) < 0) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying format (VIDIOCGPICT)")); vdo->format = 0; @@ -319,7 +319,7 @@ static inline int v4l1_probe_formats (zebra_video_t *vdo) vdo->formats = calloc(16, sizeof(uint32_t)); if(!vdo->formats) - return(err_capture(vdo, SEV_FATAL, ZEBRA_ERR_NOMEM, __func__, + return(err_capture(vdo, SEV_FATAL, ZBAR_ERR_NOMEM, __func__, "allocating format list")); int num_formats = 0; @@ -351,12 +351,12 @@ static inline int v4l1_probe_formats (zebra_video_t *vdo) return(v4l1_set_format(vdo, vdo->format)); } -static inline int v4l1_init_window (zebra_video_t *vdo) +static inline int v4l1_init_window (zbar_video_t *vdo) { struct video_window vwin; memset(&vwin, 0, sizeof(vwin)); if(ioctl(vdo->fd, VIDIOCGWIN, &vwin) < 0) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying video window settings (VIDIOCGWIN)")); zprintf(1, "current window: %d x %d @(%d, %d)%s\n", @@ -384,7 +384,7 @@ static inline int v4l1_init_window (zebra_video_t *vdo) /* re-query resulting parameters */ memset(&vwin, 0, sizeof(vwin)); if(ioctl(vdo->fd, VIDIOCGWIN, &vwin) < 0) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying video window settings (VIDIOCGWIN)")); zprintf(1, " final window: %d x %d @(%d, %d)%s\n", @@ -395,13 +395,13 @@ static inline int v4l1_init_window (zebra_video_t *vdo) return(0); } -static int _zebra_v4l1_probe (zebra_video_t *vdo) +static int _zbar_v4l1_probe (zbar_video_t *vdo) { /* check capabilities */ struct video_capability vcap; memset(&vcap, 0, sizeof(vcap)); if(ioctl(vdo->fd, VIDIOCGCAP, &vcap) < 0) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_UNSUPPORTED, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "video4linux version 1 not supported (VIDIOCGCAP)")); zprintf(1, "%s (%sCAPTURE) (%d x %d) - (%d x %d)\n", @@ -409,7 +409,7 @@ static int _zebra_v4l1_probe (zebra_video_t *vdo) vcap.minwidth, vcap.minheight, vcap.maxwidth, vcap.maxheight); if(!(vcap.type & VID_TYPE_CAPTURE)) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_UNSUPPORTED, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "v4l1 device does not support CAPTURE")); if(!vdo->width || !vdo->height) { @@ -432,8 +432,8 @@ static int _zebra_v4l1_probe (zebra_video_t *vdo) return(0); } -int _zebra_video_open (zebra_video_t *vdo, - const char *dev) +int _zbar_video_open (zbar_video_t *vdo, + const char *dev) { /* close open device */ if(vdo->fd >= 0) { @@ -460,19 +460,19 @@ int _zebra_video_open (zebra_video_t *vdo, vdo->fd = open(dev, O_RDWR); if(vdo->fd < 0) - return(err_capture_str(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture_str(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "opening video device '%s'", dev)); zprintf(1, "opened camera device %s (fd=%d)\n", dev, vdo->fd); int rc = -1; #ifdef HAVE_LINUX_VIDEODEV2_H if(vdo->intf != VIDEO_V4L1) - rc = _zebra_v4l2_probe(vdo); + rc = _zbar_v4l2_probe(vdo); if(rc) #else zprintf(1, "WARNING: not compiled with v4l2 support, trying v4l1\n"); #endif - rc = _zebra_v4l1_probe(vdo); + rc = _zbar_v4l1_probe(vdo); if(rc && vdo->fd >= 0) { close(vdo->fd); vdo->fd = -1; diff --git a/zebra/video/v4l2.c b/zbar/video/v4l2.c similarity index 85% rename from zebra/video/v4l2.c rename to zbar/video/v4l2.c index e4c622a..e09b8f9 100644 --- a/zebra/video/v4l2.c +++ b/zbar/video/v4l2.c @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include @@ -45,8 +45,8 @@ #define V4L2_FORMATS_MAX 64 -static int v4l2_nq (zebra_video_t *vdo, - zebra_image_t *img) +static int v4l2_nq (zbar_video_t *vdo, + zbar_image_t *img) { if(vdo->iomode != VIDEO_READWRITE) { if(video_unlock(vdo)) @@ -66,7 +66,7 @@ static int v4l2_nq (zebra_video_t *vdo, vbuf.index = img->srcidx; /* FIXME workaround broken drivers */ } if(ioctl(vdo->fd, VIDIOC_QBUF, &vbuf) < 0) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "queuing video buffer (VIDIOC_QBUF)")); } else { @@ -77,9 +77,9 @@ static int v4l2_nq (zebra_video_t *vdo, return(0); } -static zebra_image_t *v4l2_dq (zebra_video_t *vdo) +static zbar_image_t *v4l2_dq (zbar_video_t *vdo) { - zebra_image_t *img; + zbar_image_t *img; if(vdo->iomode != VIDEO_READWRITE) { if(video_unlock(vdo)) @@ -94,7 +94,7 @@ static zebra_image_t *v4l2_dq (zebra_video_t *vdo) vbuf.memory = V4L2_MEMORY_USERPTR; if(ioctl(vdo->fd, VIDIOC_DQBUF, &vbuf) < 0) { - err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "dequeuing video buffer (VIDIOC_DQBUF)"); return(NULL); } @@ -123,7 +123,7 @@ static zebra_image_t *v4l2_dq (zebra_video_t *vdo) if(video_unlock(vdo)) return(NULL); if(!img) { - err_capture(vdo, SEV_ERROR, ZEBRA_ERR_BUSY, __func__, + err_capture(vdo, SEV_ERROR, ZBAR_ERR_BUSY, __func__, "all allocated video images busy"); return(NULL); } @@ -131,7 +131,7 @@ static zebra_image_t *v4l2_dq (zebra_video_t *vdo) /* FIXME should read entire image */ unsigned long datalen = read(vdo->fd, (void*)img->data, img->datalen); if(datalen < 0) { - err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "reading video image"); return(NULL); } @@ -142,7 +142,7 @@ static zebra_image_t *v4l2_dq (zebra_video_t *vdo) return(img); } -static int v4l2_start (zebra_video_t *vdo) +static int v4l2_start (zbar_video_t *vdo) { /* enqueue all buffers */ int i; @@ -156,12 +156,12 @@ static int v4l2_start (zebra_video_t *vdo) enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if(ioctl(vdo->fd, VIDIOC_STREAMON, &type) < 0) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "starting video stream (VIDIOC_STREAMON)")); return(0); } -static int v4l2_stop (zebra_video_t *vdo) +static int v4l2_stop (zbar_video_t *vdo) { int i; for(i = 0; i < vdo->num_images; i++) @@ -175,12 +175,12 @@ static int v4l2_stop (zebra_video_t *vdo) enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if(ioctl(vdo->fd, VIDIOC_STREAMOFF, &type) < 0) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "stopping video stream (VIDIOC_STREAMOFF)")); return(0); } -static int v4l2_cleanup (zebra_video_t *vdo) +static int v4l2_cleanup (zbar_video_t *vdo) { if(vdo->iomode == VIDEO_READWRITE) return(0); @@ -192,10 +192,10 @@ static int v4l2_cleanup (zebra_video_t *vdo) rb.memory = V4L2_MEMORY_MMAP; int i; for(i = 0; i < vdo->num_images; i++) { - zebra_image_t *img = vdo->images[i]; + zbar_image_t *img = vdo->images[i]; if(img->data && munmap((void*)img->data, img->datalen)) - err_capture(vdo, SEV_WARNING, ZEBRA_ERR_SYSTEM, __func__, + err_capture(vdo, SEV_WARNING, ZBAR_ERR_SYSTEM, __func__, "unmapping video frame buffers"); img->data = NULL; img->datalen = 0; @@ -208,13 +208,13 @@ static int v4l2_cleanup (zebra_video_t *vdo) * should implicitly disable streaming */ if(ioctl(vdo->fd, VIDIOC_REQBUFS, &rb) < 0) - err_capture(vdo, SEV_WARNING, ZEBRA_ERR_SYSTEM, __func__, + err_capture(vdo, SEV_WARNING, ZBAR_ERR_SYSTEM, __func__, "releasing video frame buffers (VIDIOC_REQBUFS)"); return(0); } -static int v4l2_mmap_buffers (zebra_video_t *vdo) +static int v4l2_mmap_buffers (zbar_video_t *vdo) { struct v4l2_requestbuffers rb; memset(&rb, 0, sizeof(rb)); @@ -222,12 +222,12 @@ static int v4l2_mmap_buffers (zebra_video_t *vdo) rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; rb.memory = V4L2_MEMORY_MMAP; if(ioctl(vdo->fd, VIDIOC_REQBUFS, &rb) < 0) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "requesting video frame buffers (VIDIOC_REQBUFS)")); zprintf(1, "mapping %u buffers (of %d requested)\n", rb.count, vdo->num_images); if(!rb.count) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_INVALID, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "driver returned 0 buffers")); if(vdo->num_images > rb.count) vdo->num_images = rb.count; @@ -242,7 +242,7 @@ static int v4l2_mmap_buffers (zebra_video_t *vdo) vbuf.index = i; if(ioctl(vdo->fd, VIDIOC_QUERYBUF, &vbuf) < 0) /* FIXME cleanup */ - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying video buffer (VIDIOC_QUERYBUF)")); if(vbuf.length < vdo->datalen) @@ -251,13 +251,13 @@ static int v4l2_mmap_buffers (zebra_video_t *vdo) i, vbuf.length, vdo->datalen, vdo->width, vdo->height, (char*)&vdo->format, vdo->format); - zebra_image_t *img = vdo->images[i]; + zbar_image_t *img = vdo->images[i]; img->datalen = vbuf.length; img->data = mmap(NULL, vbuf.length, PROT_READ | PROT_WRITE, MAP_SHARED, vdo->fd, vbuf.m.offset); if(img->data == MAP_FAILED) /* FIXME cleanup */ - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "mapping video frame buffers")); zprintf(2, " buf[%d] 0x%lx bytes @%p\n", i, img->datalen, img->data); @@ -265,7 +265,7 @@ static int v4l2_mmap_buffers (zebra_video_t *vdo) return(0); } -static int v4l2_set_format (zebra_video_t *vdo, +static int v4l2_set_format (zbar_video_t *vdo, uint32_t fmt) { struct v4l2_format vfmt; @@ -289,7 +289,7 @@ static int v4l2_set_format (zebra_video_t *vdo, vpix->field = V4L2_FIELD_INTERLACED; if(ioctl(vdo->fd, VIDIOC_S_FMT, &vfmt) < 0) - return(err_capture_int(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture_int(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "setting format %x (VIDIOC_S_FMT)", fmt)); zprintf(0, "WARNING: broken driver returned error when non-interlaced" @@ -301,17 +301,17 @@ static int v4l2_set_format (zebra_video_t *vdo, memset(&newfmt, 0, sizeof(newfmt)); newfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if(ioctl(vdo->fd, VIDIOC_G_FMT, &newfmt) < 0) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying format (VIDIOC_G_FMT)")); if(newpix->field != V4L2_FIELD_NONE) - err_capture(vdo, SEV_WARNING, ZEBRA_ERR_INVALID, __func__, + err_capture(vdo, SEV_WARNING, ZBAR_ERR_INVALID, __func__, "video driver only supports interlaced format," " vertical scanning may not work"); if(newpix->pixelformat != fmt /* FIXME bpl/bpp checks? */) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_INVALID, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "video driver can't provide compatible format")); vdo->format = fmt; @@ -325,7 +325,7 @@ static int v4l2_set_format (zebra_video_t *vdo, return(0); } -static int v4l2_init (zebra_video_t *vdo, +static int v4l2_init (zbar_video_t *vdo, uint32_t fmt) { if(v4l2_set_format(vdo, fmt)) @@ -335,7 +335,7 @@ static int v4l2_init (zebra_video_t *vdo, return(0); } -static int v4l2_probe_iomode (zebra_video_t *vdo) +static int v4l2_probe_iomode (zbar_video_t *vdo) { struct v4l2_requestbuffers rb; memset(&rb, 0, sizeof(rb)); @@ -348,11 +348,11 @@ static int v4l2_probe_iomode (zebra_video_t *vdo) if(ioctl(vdo->fd, VIDIOC_REQBUFS, &rb) < 0) { if(vdo->iomode) - return(err_capture_int(vdo, SEV_ERROR, ZEBRA_ERR_INVALID, __func__, + return(err_capture_int(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "unsupported iomode requested (%d)", vdo->iomode)); else if(errno != EINVAL) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying streaming mode (VIDIOC_REQBUFS)")); #ifdef HAVE_SYS_MMAN_H vdo->iomode = VIDEO_MMAP; @@ -367,7 +367,7 @@ static int v4l2_probe_iomode (zebra_video_t *vdo) return(0); } -static inline int v4l2_probe_formats (zebra_video_t *vdo) +static inline int v4l2_probe_formats (zbar_video_t *vdo) { zprintf(2, "enumerating supported formats:\n"); struct v4l2_fmtdesc desc; @@ -384,7 +384,7 @@ static inline int v4l2_probe_formats (zebra_video_t *vdo) vdo->formats[desc.index] = desc.pixelformat; } if(!desc.index) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "enumerating video formats (VIDIOC_ENUM_FMT)")); vdo->formats[desc.index] = 0; @@ -393,7 +393,7 @@ static inline int v4l2_probe_formats (zebra_video_t *vdo) memset(&fmt, 0, sizeof(fmt)); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if(ioctl(vdo->fd, VIDIOC_G_FMT, &fmt) < 0) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying current video format (VIDIO_G_FMT)")); zprintf(1, "current format: %.4s(%08x) %u x %u%s (line=0x%x size=0x%x)\n", @@ -423,7 +423,7 @@ static inline int v4l2_probe_formats (zebra_video_t *vdo) memset(&fmt, 0, sizeof(fmt)); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if(ioctl(vdo->fd, VIDIOC_G_FMT, &fmt) < 0) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying current video format (VIDIOC_G_FMT)")); zprintf(1, "final format: %.4s(%08x) %u x %u%s (line=0x%x size=0x%x)\n", @@ -438,14 +438,14 @@ static inline int v4l2_probe_formats (zebra_video_t *vdo) return(0); } -static inline int v4l2_reset_crop (zebra_video_t *vdo) +static inline int v4l2_reset_crop (zbar_video_t *vdo) { /* check cropping */ struct v4l2_cropcap ccap; memset(&ccap, 0, sizeof(ccap)); ccap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if(ioctl(vdo->fd, VIDIOC_CROPCAP, &ccap) < 0) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying crop support (VIDIOC_CROPCAP)")); zprintf(1, "crop bounds: %d x %d @ (%d, %d)\n", @@ -467,18 +467,18 @@ static inline int v4l2_reset_crop (zebra_video_t *vdo) crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; crop.c = ccap.defrect; if(ioctl(vdo->fd, VIDIOC_S_CROP, &crop) < 0 && errno != EINVAL) - return(err_capture(vdo, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "setting default crop window (VIDIOC_S_CROP)")); return(0); } -int _zebra_v4l2_probe (zebra_video_t *vdo) +int _zbar_v4l2_probe (zbar_video_t *vdo) { /* check capabilities */ struct v4l2_capability vcap; memset(&vcap, 0, sizeof(vcap)); if(ioctl(vdo->fd, VIDIOC_QUERYCAP, &vcap) < 0) - return(err_capture(vdo, SEV_WARNING, ZEBRA_ERR_UNSUPPORTED, __func__, + return(err_capture(vdo, SEV_WARNING, ZBAR_ERR_UNSUPPORTED, __func__, "video4linux version 2 not supported (VIDIOC_QUERYCAP)")); @@ -494,7 +494,7 @@ int _zebra_v4l2_probe (zebra_video_t *vdo) if(!(vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE) || !(vcap.capabilities & (V4L2_CAP_READWRITE | V4L2_CAP_STREAMING))) - return(err_capture(vdo, SEV_WARNING, ZEBRA_ERR_UNSUPPORTED, __func__, + return(err_capture(vdo, SEV_WARNING, ZBAR_ERR_UNSUPPORTED, __func__, "v4l2 device does not support usable CAPTURE")); if(v4l2_reset_crop(vdo)) diff --git a/zebra/window.c b/zbar/window.c similarity index 52% rename from zebra/window.c rename to zbar/window.c index 6a0283f..2faa9d4 100644 --- a/zebra/window.c +++ b/zbar/window.c @@ -1,59 +1,55 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include "window.h" #include "image.h" -extern int _zebra_draw_logo(zebra_image_t *img); +extern int _zbar_draw_logo(zbar_window_t *w); -zebra_window_t *zebra_window_create () +zbar_window_t *zbar_window_create () { - zebra_window_t *w = calloc(1, sizeof(zebra_window_t)); + zbar_window_t *w = calloc(1, sizeof(zbar_window_t)); if(!w) return(NULL); - err_init(&w->err, ZEBRA_MOD_WINDOW); + err_init(&w->err, ZBAR_MOD_WINDOW); w->overlay = 1; return(w); } -void zebra_window_destroy (zebra_window_t *w) +void zbar_window_destroy (zbar_window_t *w) { /* detach */ - zebra_window_attach(w, NULL, 0); - if(w->logo) { - _zebra_image_refcnt(w->logo, -1); - w->logo = NULL; - } + zbar_window_attach(w, NULL, 0); err_cleanup(&w->err); free(w); } -int zebra_window_attach (zebra_window_t *w, - void *display, - unsigned long drawable) +int zbar_window_attach (zbar_window_t *w, + void *display, + unsigned long drawable) { /* release image */ - zebra_window_draw(w, NULL); + zbar_window_draw(w, NULL); if(w->cleanup) { w->cleanup(w); w->cleanup = NULL; @@ -63,24 +59,24 @@ int zebra_window_attach (zebra_window_t *w, free(w->formats); w->formats = NULL; } - return(_zebra_window_attach(w, display, drawable)); + return(_zbar_window_attach(w, display, drawable)); } -static inline int window_draw_overlay (zebra_window_t *w) +static inline int window_draw_overlay (zbar_window_t *w) { /* FIXME TBD - * _zebra_draw_line, _zebra_draw_polygon, _zebra_draw_text, etc... + * _zbar_draw_line, _zbar_draw_polygon, _zbar_draw_text, etc... */ if(!w->overlay) return(0); if(w->overlay >= 1 && w->image) { /* FIXME outline each symbol */ - const zebra_symbol_t *sym = zebra_image_first_symbol(w->image); + const zbar_symbol_t *sym = zbar_image_first_symbol(w->image); for(; sym; sym = sym->next) { int i; for(i = 0; i < sym->npts; i++) { uint32_t color = ((sym->cache_count < 0) ? 4 : 2); - _zebra_window_draw_marker(w, color, &sym->pts[i]); + _zbar_window_draw_marker(w, color, &sym->pts[i]); } } } @@ -90,45 +86,42 @@ static inline int window_draw_overlay (zebra_window_t *w) return(0); } -inline int zebra_window_redraw (zebra_window_t *w) +inline int zbar_window_redraw (zbar_window_t *w) { if(window_lock(w)) return(-1); - if(!w->draw_image || !w->logo) { + if(!w->draw_image) { (void)window_unlock(w); - return(_zebra_window_clear(w)); + return(_zbar_window_clear(w)); } - int rc; + int rc = 0; if(w->image) rc = w->draw_image(w, w->image); - else { - rc = w->draw_image(w, w->logo); - if(w->image) - w->logo->refcnt++; - } + else + _zbar_draw_logo(w); if(!rc) rc = window_draw_overlay(w); (void)window_unlock(w); return(rc); } -int zebra_window_draw (zebra_window_t *w, - zebra_image_t *img) +int zbar_window_draw (zbar_window_t *w, + zbar_image_t *img) { if(window_lock(w)) return(-1); if(!w->draw_image) img = NULL; if(w->image) - _zebra_image_refcnt(w->image, -1); + _zbar_image_refcnt(w->image, -1); w->image = img; if(img) img->refcnt++; return(window_unlock(w)); } -void zebra_window_set_overlay (zebra_window_t *w, - int lvl) +void zbar_window_set_overlay (zbar_window_t *w, + int lvl) { if(lvl < 0) lvl = 0; @@ -141,21 +134,13 @@ void zebra_window_set_overlay (zebra_window_t *w, (void)window_unlock(w); } -int zebra_window_resize (zebra_window_t *w, - unsigned width, - unsigned height) +int zbar_window_resize (zbar_window_t *w, + unsigned width, + unsigned height) { if(window_lock(w)) return(-1); w->width = width; w->height = height; - if(!w->logo) { - w->logo = zebra_image_create(); - w->logo->refcnt++; - } - if(w->logo->width != width || w->logo->height != height) { - zebra_image_set_size(w->logo, width, height); - _zebra_draw_logo(w->logo); - } return(window_unlock(w)); } diff --git a/zebra/window.h b/zbar/window.h similarity index 72% rename from zebra/window.h rename to zbar/window.h index 520cf2d..e9abfee 100644 --- a/zebra/window.h +++ b/zbar/window.h @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #ifndef _WINDOW_H_ #define _WINDOW_H_ @@ -44,13 +44,13 @@ # include #endif -#include +#include #include "image.h" #include "error.h" -struct zebra_window_s { +struct zbar_window_s { errinfo_t err; /* error reporting */ - zebra_image_t *image; /* last displayed image + zbar_image_t *image; /* last displayed image * NB image access must be locked! */ unsigned overlay; /* user set overlay level */ @@ -58,13 +58,12 @@ struct zebra_window_s { uint32_t format; /* output format */ unsigned width, height; /* current output size */ unsigned max_width, max_height; - zebra_image_t *logo; /* logo image for current width x height */ uint32_t *formats; /* supported formats (zero terminated) */ /* interface dependent methods */ - int (*draw_image)(zebra_window_t*, zebra_image_t*); - int (*cleanup)(zebra_window_t*); + int (*draw_image)(zbar_window_t*, zbar_image_t*); + int (*cleanup)(zbar_window_t*); #ifdef HAVE_X Display *display; /* display connection */ @@ -104,11 +103,11 @@ struct zebra_window_s { /* window.draw has to be thread safe wrt/other apis * FIXME should be a semaphore */ -static inline int window_lock (zebra_window_t *w) +static inline int window_lock (zbar_window_t *w) { int rc = 0; if((rc = pthread_mutex_lock(&w->imglock))) { - err_capture(w, SEV_FATAL, ZEBRA_ERR_LOCKING, __func__, + err_capture(w, SEV_FATAL, ZBAR_ERR_LOCKING, __func__, "unable to acquire lock"); w->err.errnum = rc; return(-1); @@ -116,11 +115,11 @@ static inline int window_lock (zebra_window_t *w) return(0); } -static inline int window_unlock (zebra_window_t *w) +static inline int window_unlock (zbar_window_t *w) { int rc = 0; if((rc = pthread_mutex_unlock(&w->imglock))) { - err_capture(w, SEV_FATAL, ZEBRA_ERR_LOCKING, __func__, + err_capture(w, SEV_FATAL, ZBAR_ERR_LOCKING, __func__, "unable to release lock"); w->err.errnum = rc; return(-1); @@ -133,7 +132,7 @@ static inline int window_unlock (zebra_window_t *w) # define window_unlock(...) (0) #endif -static inline int _zebra_window_add_format (zebra_window_t *w, +static inline int _zbar_window_add_format (zbar_window_t *w, uint32_t fmt) { int i; @@ -147,22 +146,22 @@ static inline int _zebra_window_add_format (zebra_window_t *w, return(i); } -extern int _zebra_window_probe_ximage(zebra_window_t*); -extern int _zebra_window_probe_xshm(zebra_window_t*); -extern int _zebra_window_probe_xv(zebra_window_t*); +extern int _zbar_window_probe_ximage(zbar_window_t*); +extern int _zbar_window_probe_xshm(zbar_window_t*); +extern int _zbar_window_probe_xv(zbar_window_t*); -extern int _zebra_window_attach(zebra_window_t*, void*, unsigned long); +extern int _zbar_window_attach(zbar_window_t*, void*, unsigned long); -extern int _zebra_window_clear(zebra_window_t*); +extern int _zbar_window_clear(zbar_window_t*); -extern int _zebra_window_draw_marker(zebra_window_t*, uint32_t, +extern int _zbar_window_draw_marker(zbar_window_t*, uint32_t, const point_t*); #if 0 -extern int _zebra_window_draw_line(zebra_window_t*, uint32_t, +extern int _zbar_window_draw_line(zbar_window_t*, uint32_t, const point_t*, const point_t*); -extern int _zebra_window_draw_outline(zebra_window_t*, uint32_t, +extern int _zbar_window_draw_outline(zbar_window_t*, uint32_t, const symbol_t*); -extern int _zebra_window_draw_text(zebra_window_t*, uint32_t, +extern int _zbar_window_draw_text(zbar_window_t*, uint32_t, const point_t*, const char*); #endif diff --git a/zbar/window/null.c b/zbar/window/null.c new file mode 100644 index 0000000..20182c1 --- /dev/null +++ b/zbar/window/null.c @@ -0,0 +1,87 @@ +/*------------------------------------------------------------------------ + * Copyright 2008-2009 (c) Jeff Brown + * + * 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 "window.h" + +static inline int null_error (void *m, + const char *func) +{ + return(err_capture(m, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, func, + "not compiled with output window support")); +} + +int _zbar_window_attach (zbar_window_t *w, + void *display, + unsigned long win) +{ + return(null_error(w, __func__)); +} + +int _zbar_window_handle_events (zbar_processor_t *proc, + int block) +{ + return(null_error(proc, __func__)); +} + +int _zbar_window_open (zbar_processor_t *proc, + char *title, + unsigned width, + unsigned height) +{ + return(null_error(proc, __func__)); +} + +int _zbar_window_close (zbar_processor_t *proc) +{ + return(null_error(proc, __func__)); +} + +int _zbar_window_resize (zbar_processor_t *proc, + unsigned width, + unsigned height) +{ + return(null_error(proc, __func__)); +} + +int _zbar_window_set_visible (zbar_processor_t *proc, + int visible) +{ + return(null_error(proc, __func__)); +} + +int _zbar_window_clear (zbar_window_t *w) +{ + return(null_error(w, __func__)); +} + +int _zbar_window_invalidate (zbar_window_t *w) +{ + return(0); +} + +int _zbar_window_draw_marker(zbar_window_t *w, + uint32_t rgb, + const point_t *p) +{ + return(null_error(w, __func__)); +} diff --git a/zebra/window/x.c b/zbar/window/x.c similarity index 75% rename from zebra/window/x.c rename to zbar/window/x.c index 88729af..9c140d4 100644 --- a/zebra/window/x.c +++ b/zbar/window/x.c @@ -1,31 +1,31 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include "window.h" #include "processor.h" #include -static inline int window_alloc_colors (zebra_window_t *w) +static inline int window_alloc_colors (zbar_window_t *w) { Colormap cmap = DefaultColormap(w->display, DefaultScreen(w->display)); XColor color; @@ -41,7 +41,7 @@ static inline int window_alloc_colors (zebra_window_t *w) return(0); } -static inline int window_hide_cursor (zebra_window_t *w) +static inline int window_hide_cursor (zbar_window_t *w) { /* FIXME this seems lame...there must be a better way */ Pixmap empty = XCreatePixmap(w->display, w->xwin, 1, 1, 1); @@ -60,9 +60,9 @@ static inline int window_hide_cursor (zebra_window_t *w) return(0); } -int _zebra_window_attach (zebra_window_t *w, - void *display, - unsigned long win) +int _zbar_window_attach (zbar_window_t *w, + void *display, + unsigned long win) { if(w->display) { /* cleanup existing resources */ @@ -89,15 +89,15 @@ int _zebra_window_attach (zebra_window_t *w, /* FIXME add interface preference override */ #ifdef HAVE_X11_EXTENSIONS_XVLIB_H - if(!_zebra_window_probe_xv(w)) + if(!_zbar_window_probe_xv(w)) return(0); #endif zprintf(1, "falling back to XImage\n"); - return(_zebra_window_probe_ximage(w)); + return(_zbar_window_probe_ximage(w)); } -static int x_handle_event (zebra_processor_t *proc) +static int x_handle_event (zbar_processor_t *proc) { XEvent ev; XNextEvent(proc->display, &ev); @@ -106,13 +106,13 @@ static int x_handle_event (zebra_processor_t *proc) case Expose: /* FIXME ignore when running */ if(!ev.xexpose.count) - zebra_window_redraw(proc->window); + zbar_window_redraw(proc->window); break; case ConfigureNotify: zprintf(3, "resized to %d x %d\n", ev.xconfigure.width, ev.xconfigure.height); - zebra_window_resize(proc->window, + zbar_window_resize(proc->window, ev.xconfigure.width, ev.xconfigure.height); break; @@ -123,8 +123,8 @@ static int x_handle_event (zebra_processor_t *proc) (ev.xclient.data.l[0] == XInternAtom(proc->display, "WM_DELETE_WINDOW", 0))) { zprintf(3, "WM_DELETE_WINDOW\n"); - _zebra_window_set_visible(proc, 0); - return(err_capture(proc, SEV_WARNING, ZEBRA_ERR_CLOSED, __func__, + _zbar_window_set_visible(proc, 0); + return(err_capture(proc, SEV_WARNING, ZBAR_ERR_CLOSED, __func__, "user closed display window")); } @@ -150,8 +150,8 @@ static int x_handle_event (zebra_processor_t *proc) return(0); } -int _zebra_window_handle_events (zebra_processor_t *proc, - int block) +int _zbar_window_handle_events (zbar_processor_t *proc, + int block) { int rc = 0; while(!rc && (block || XPending(proc->display))) { @@ -161,8 +161,8 @@ int _zebra_window_handle_events (zebra_processor_t *proc, switch(rc) { case 'q': - _zebra_window_set_visible(proc, 0); - rc = err_capture(proc, SEV_WARNING, ZEBRA_ERR_CLOSED, __func__, + _zbar_window_set_visible(proc, 0); + rc = err_capture(proc, SEV_WARNING, ZBAR_ERR_CLOSED, __func__, "user closed display window"); break; @@ -170,7 +170,7 @@ int _zebra_window_handle_events (zebra_processor_t *proc, /* FIXME localtime not threadsafe */ /* FIXME need ms resolution */ /*struct tm *t = localtime(time(NULL));*/ - zebra_image_write(proc->window->image, "zebra"); + zbar_image_write(proc->window->image, "zbar"); break; } } @@ -180,17 +180,17 @@ int _zebra_window_handle_events (zebra_processor_t *proc, return(rc); } -static int x_connection_handler (zebra_processor_t *proc, +static int x_connection_handler (zbar_processor_t *proc, int i) { - return(_zebra_window_handle_events(proc, 0)); + return(_zbar_window_handle_events(proc, 0)); } -static int x_internal_handler (zebra_processor_t *proc, +static int x_internal_handler (zbar_processor_t *proc, int i) { XProcessInternalConnection(proc->display, proc->polling.fds[i].fd); - return(_zebra_window_handle_events(proc, 0)); + return(_zbar_window_handle_events(proc, 0)); } static void x_internal_watcher (Display *display, @@ -199,21 +199,21 @@ static void x_internal_watcher (Display *display, Bool opening, XPointer *watch_arg) { - zebra_processor_t *proc = (void*)client_arg; + zbar_processor_t *proc = (void*)client_arg; if(opening) add_poll(proc, fd, x_internal_handler); else remove_poll(proc, fd); } -int _zebra_window_open (zebra_processor_t *proc, - char *title, - unsigned width, - unsigned height) +int _zbar_window_open (zbar_processor_t *proc, + char *title, + unsigned width, + unsigned height) { proc->display = XOpenDisplay(NULL); if(!proc->display) - return(err_capture_str(proc, SEV_ERROR, ZEBRA_ERR_XDISPLAY, __func__, + return(err_capture_str(proc, SEV_ERROR, ZBAR_ERR_XDISPLAY, __func__, "unable to open X display", XDisplayName(NULL))); @@ -232,15 +232,15 @@ int _zebra_window_open (zebra_processor_t *proc, CopyFromParent, CWEventMask, &attr); if(!proc->xwin) { XCloseDisplay(proc->display); - return(err_capture(proc, SEV_ERROR, ZEBRA_ERR_XPROTO, __func__, + return(err_capture(proc, SEV_ERROR, ZBAR_ERR_XPROTO, __func__, "creating window")); } XStoreName(proc->display, proc->xwin, title); XClassHint *class_hint = XAllocClassHint(); - class_hint->res_name = "zebra"; - class_hint->res_class = "zebra"; + class_hint->res_name = "zbar"; + class_hint->res_class = "zbar"; XSetClassHint(proc->display, proc->xwin, class_hint); XFree(class_hint); class_hint = NULL; @@ -252,7 +252,7 @@ int _zebra_window_open (zebra_processor_t *proc, return(0); } -int _zebra_window_close (zebra_processor_t *proc) +int _zbar_window_close (zbar_processor_t *proc) { if(proc->display) { if(proc->xwin) { @@ -266,20 +266,20 @@ int _zebra_window_close (zebra_processor_t *proc) return(0); } -int _zebra_window_resize (zebra_processor_t *proc, - unsigned width, - unsigned height) +int _zbar_window_resize (zbar_processor_t *proc, + unsigned width, + unsigned height) { if(proc->display) { XResizeWindow(proc->display, proc->xwin, width, height); - _zebra_window_clear(proc->window); + _zbar_window_clear(proc->window); XFlush(proc->display); } return(0); } -int _zebra_window_set_visible (zebra_processor_t *proc, - int visible) +int _zbar_window_set_visible (zbar_processor_t *proc, + int visible) { if(visible) XMapRaised(proc->display, proc->xwin); @@ -290,7 +290,7 @@ int _zebra_window_set_visible (zebra_processor_t *proc, return(0); } -int _zebra_window_invalidate (zebra_window_t *w) +int _zbar_window_invalidate (zbar_window_t *w) { if(!w->display) return(0); @@ -299,7 +299,7 @@ int _zebra_window_invalidate (zebra_window_t *w) return(0); } -int _zebra_window_clear (zebra_window_t *w) +int _zbar_window_clear (zbar_window_t *w) { if(!w->display) return(0); @@ -309,9 +309,9 @@ int _zebra_window_clear (zebra_window_t *w) return(0); } -int _zebra_window_draw_marker(zebra_window_t *w, - uint32_t rgb, - const point_t *p) +int _zbar_window_draw_marker(zbar_window_t *w, + uint32_t rgb, + const point_t *p) { XSetForeground(w->display, w->gc, w->colors[rgb]); diff --git a/zebra/window/ximage.c b/zbar/window/ximage.c similarity index 83% rename from zebra/window/ximage.c rename to zbar/window/ximage.c index 539eb20..67c15e1 100644 --- a/zebra/window/ximage.c +++ b/zbar/window/ximage.c @@ -1,29 +1,29 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include "window.h" -static int ximage_cleanup (zebra_window_t *w) +static int ximage_cleanup (zbar_window_t *w) { if(w->img.x) free(w->img.x); @@ -31,8 +31,8 @@ static int ximage_cleanup (zebra_window_t *w) return(0); } -static inline int ximage_init (zebra_window_t *w, - zebra_image_t *img) +static inline int ximage_init (zbar_window_t *w, + zbar_image_t *img) { if(w->img.x) { free(w->img.x); @@ -40,9 +40,9 @@ static inline int ximage_init (zebra_window_t *w, } if(w->src_format != img->format && w->format != img->format) { - _zebra_best_format(img->format, &w->format, w->formats); + _zbar_best_format(img->format, &w->format, w->formats); if(!w->format) { - err_capture_int(w, SEV_ERROR, ZEBRA_ERR_UNSUPPORTED, __func__, + err_capture_int(w, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "no conversion from %x to supported formats", img->format); return(-1); @@ -58,8 +58,8 @@ static inline int ximage_init (zebra_window_t *w, ximg->bitmap_bit_order = MSBFirst; ximg->bitmap_pad = 8; - const zebra_format_def_t *fmt = _zebra_format_lookup(w->format); - if(fmt->group == ZEBRA_FMT_RGB_PACKED) { + const zbar_format_def_t *fmt = _zbar_format_lookup(w->format); + if(fmt->group == ZBAR_FMT_RGB_PACKED) { ximg->depth = ximg->bits_per_pixel = fmt->p.rgb.bpp << 3; ximg->red_mask = (0xff >> RGB_SIZE(fmt->p.rgb.red)) @@ -77,7 +77,7 @@ static inline int ximage_init (zebra_window_t *w, } if(!XInitImage(ximg)) - return(err_capture_int(w, SEV_ERROR, ZEBRA_ERR_XPROTO, __func__, + return(err_capture_int(w, SEV_ERROR, ZBAR_ERR_XPROTO, __func__, "unable to init XImage for format %x", w->format)); zprintf(3, "new XImage %.4s(%08" PRIx32 ") %dx%d" @@ -89,8 +89,8 @@ static inline int ximage_init (zebra_window_t *w, return(0); } -static int ximage_draw (zebra_window_t *w, - zebra_image_t *img) +static int ximage_draw (zbar_window_t *w, + zbar_image_t *img) { XImage *ximg = w->img.x; if(!ximg || @@ -104,8 +104,8 @@ static int ximage_draw (zebra_window_t *w, } if(img->format != w->format) { /* save *converted* image for redraw */ - w->image = zebra_image_convert(img, w->format); - zebra_image_destroy(img); + w->image = zbar_image_convert(img, w->format); + zbar_image_destroy(img); img = w->image; } @@ -175,10 +175,10 @@ static uint32_t ximage_formats[4][5] = { }, }; -static int ximage_probe_format (zebra_window_t *w, +static int ximage_probe_format (zbar_window_t *w, uint32_t format) { - const zebra_format_def_t *fmt = _zebra_format_lookup(format); + const zbar_format_def_t *fmt = _zbar_format_lookup(format); XVisualInfo visreq, *visuals = NULL; memset(&visreq, 0, sizeof(XVisualInfo)); @@ -209,13 +209,13 @@ static int ximage_probe_format (zebra_window_t *w, return(0); } -int _zebra_window_probe_ximage (zebra_window_t *w) +int _zbar_window_probe_ximage (zbar_window_t *w) { /* FIXME determine supported formats/depths */ int n; XPixmapFormatValues *formats = XListPixmapFormats(w->display, &n); if(!formats) - return(err_capture(w, SEV_ERROR, ZEBRA_ERR_XPROTO, __func__, + return(err_capture(w, SEV_ERROR, ZBAR_ERR_XPROTO, __func__, "unable to query XImage formats")); int i; @@ -234,7 +234,7 @@ int _zebra_window_probe_ximage (zebra_window_t *w) i, formats[i].depth, formats[i].bits_per_pixel, (char*)&ximage_formats[fmtidx][j], ximage_formats[fmtidx][j]); - _zebra_window_add_format(w, ximage_formats[fmtidx][j]); + _zbar_window_add_format(w, ximage_formats[fmtidx][j]); n++; } if(!n) @@ -244,7 +244,7 @@ int _zebra_window_probe_ximage (zebra_window_t *w) XFree(formats); if(!w->formats || !w->formats[0]) - return(err_capture(w, SEV_ERROR, ZEBRA_ERR_UNSUPPORTED, __func__, + return(err_capture(w, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "no usable XImage formats found")); w->draw_image = ximage_draw; diff --git a/zebra/window/xv.c b/zbar/window/xv.c similarity index 87% rename from zebra/window/xv.c rename to zbar/window/xv.c index 78c9302..de5b227 100644 --- a/zebra/window/xv.c +++ b/zbar/window/xv.c @@ -1,30 +1,30 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2008 (c) Jeff Brown + * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include "window.h" #include /* strcmp */ -static int xv_cleanup (zebra_window_t *w) +static int xv_cleanup (zbar_window_t *w) { if(w->img.xv) { XFree(w->img.xv); @@ -44,8 +44,8 @@ static int xv_cleanup (zebra_window_t *w) return(0); } -static inline int xv_init (zebra_window_t *w, - zebra_image_t *img) +static inline int xv_init (zbar_window_t *w, + zbar_image_t *img) { if(w->img.xv) { XFree(w->img.xv); @@ -53,9 +53,9 @@ static inline int xv_init (zebra_window_t *w, } if(w->src_format != img->format && w->format != img->format) { - _zebra_best_format(img->format, &w->format, w->formats); + _zbar_best_format(img->format, &w->format, w->formats); if(!w->format) { - err_capture_int(w, SEV_ERROR, ZEBRA_ERR_UNSUPPORTED, __func__, + err_capture_int(w, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "no conversion from %x to supported Xv formats", img->format); return(-1); @@ -92,7 +92,7 @@ static inline int xv_init (zebra_window_t *w, if(w->dst_width < img->width || xvimg->height < img->height) { XFree(xvimg); /* FIXME fallback to XImage... */ - return(err_capture(w, SEV_ERROR, ZEBRA_ERR_UNSUPPORTED, __func__, + return(err_capture(w, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "output image size mismatch (XvCreateImage)")); } w->img.xv = xvimg; @@ -100,8 +100,8 @@ static inline int xv_init (zebra_window_t *w, return(0); } -static int xv_draw (zebra_window_t *w, - zebra_image_t *img) +static int xv_draw (zbar_window_t *w, + zbar_image_t *img) { XvImage *xvimg = w->img.xv; /* FIXME preserve aspect ratio (config?) */ @@ -122,10 +122,10 @@ static int xv_draw (zebra_window_t *w, w->src_width = img->width; w->src_height = img->height; /* save *converted* image for redraw */ - w->image = zebra_image_convert_resize(img, w->format, + w->image = zbar_image_convert_resize(img, w->format, w->dst_width, xvimg->height); - zebra_image_destroy(img); + zbar_image_destroy(img); img = w->image; } @@ -139,11 +139,11 @@ static int xv_draw (zebra_window_t *w, return(0); } -static inline int xv_add_format (zebra_window_t *w, +static inline int xv_add_format (zbar_window_t *w, uint32_t fmt, XvPortID port) { - int i = _zebra_window_add_format(w, fmt); + int i = _zbar_window_add_format(w, fmt); if(!w->formats[i + 1]) w->xv_ports = realloc(w->xv_ports, (i + 1) * sizeof(uint32_t)); @@ -153,13 +153,13 @@ static inline int xv_add_format (zebra_window_t *w, return(i); } -static int xv_probe_port (zebra_window_t *w, +static int xv_probe_port (zbar_window_t *w, XvPortID port) { unsigned n; XvEncodingInfo *encodings = NULL; if(XvQueryEncodings(w->display, port, &n, &encodings)) - return(err_capture(w, SEV_ERROR, ZEBRA_ERR_XPROTO, __func__, + return(err_capture(w, SEV_ERROR, ZBAR_ERR_XPROTO, __func__, "querying XVideo encodings")); zprintf(1, "probing port %u with %d encodings:\n", (unsigned)port, n); @@ -181,7 +181,7 @@ static int xv_probe_port (zebra_window_t *w, encodings = NULL; if(!width || !height) - return(err_capture(w, SEV_ERROR, ZEBRA_ERR_INVALID, __func__, + return(err_capture(w, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "no XV_IMAGE encodings found")); zprintf(1, "max XV_IMAGE size %dx%d\n", width, height); if(w->max_width > width) @@ -192,7 +192,7 @@ static int xv_probe_port (zebra_window_t *w, XvImageFormatValues *formats = XvListImageFormats(w->display, port, (int*)&n); if(!formats) - return(err_capture(w, SEV_ERROR, ZEBRA_ERR_XPROTO, __func__, + return(err_capture(w, SEV_ERROR, ZBAR_ERR_XPROTO, __func__, "querying XVideo image formats")); zprintf(1, "%d image formats\n", n); @@ -210,7 +210,7 @@ static int xv_probe_port (zebra_window_t *w, return(0); } -int _zebra_window_probe_xv (zebra_window_t *w) +int _zbar_window_probe_xv (zbar_window_t *w) { unsigned xv_major, xv_minor, xv_req, xv_ev, xv_err; if(XvQueryExtension(w->display, &xv_major, &xv_minor, @@ -224,7 +224,7 @@ int _zebra_window_probe_xv (zebra_window_t *w) unsigned n; XvAdaptorInfo *adaptors = NULL; if(XvQueryAdaptors(w->display, w->xwin, &n, &adaptors)) - return(err_capture(w, SEV_ERROR, ZEBRA_ERR_XPROTO, __func__, + return(err_capture(w, SEV_ERROR, ZBAR_ERR_XPROTO, __func__, "unable to query XVideo adaptors")); w->num_xv_adaptors = 0; diff --git a/zbarcam/Makefile.am.inc b/zbarcam/Makefile.am.inc new file mode 100644 index 0000000..ebc369d --- /dev/null +++ b/zbarcam/Makefile.am.inc @@ -0,0 +1,5 @@ +bin_PROGRAMS += zbarcam/zbarcam +zbarcam_zbarcam_SOURCES = zbarcam/zbarcam.c +zbarcam_zbarcam_LDADD = zbar/libzbar.la +# automake bug in "monolithic mode"? +CLEANFILES += zbarcam/.libs/zbarcam diff --git a/zebracam/zebracam.c b/zbarcam/zbarcam.c similarity index 75% rename from zebracam/zebracam.c rename to zbarcam/zbarcam.c index e4025d8..898d25d 100644 --- a/zebracam/zebracam.c +++ b/zbarcam/zbarcam.c @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ * Copyright 2007-2009 (c) Jeff Brown * - * This file is part of the Zebra Barcode Library. + * This file is part of the ZBar Bar Code Reader. * - * The Zebra Barcode Library is free software; you can redistribute it + * 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 Zebra Barcode Library is distributed in the hope that it will be + * 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 Zebra Barcode Library; if not, write to the Free + * 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/zebra + * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ #include @@ -27,12 +27,12 @@ #include #include -#include +#include #define BELL "\a" static const char *note_usage = - "usage: zebracam [options] [/dev/video?]\n" + "usage: zbarcam [options] [/dev/video?]\n" "\n" "scan and decode bar codes from a video stream\n" "\n" @@ -52,12 +52,12 @@ static const char *note_usage = "\n"; static const char *xml_head = - "" + "" "\n"; static const char *xml_foot = "\n"; -static zebra_processor_t *proc; +static zbar_processor_t *proc; static int quiet = 0; static int xml = 0; @@ -78,31 +78,31 @@ static inline int parse_config (const char *cfgstr, int i, int n, char *arg) return(1); } - if(zebra_processor_parse_config(proc, cfgstr)) { + if(zbar_processor_parse_config(proc, cfgstr)) { fprintf(stderr, "ERROR: invalid configuration setting: %s\n", cfgstr); return(1); } return(0); } -static void data_handler (zebra_image_t *img, const void *userdata) +static void data_handler (zbar_image_t *img, const void *userdata) { - const zebra_symbol_t *sym = zebra_image_first_symbol(img); + const zbar_symbol_t *sym = zbar_image_first_symbol(img); assert(sym); int n = 0; - for(; sym; sym = zebra_symbol_next(sym)) { - if(zebra_symbol_get_count(sym)) + for(; sym; sym = zbar_symbol_next(sym)) { + if(zbar_symbol_get_count(sym)) continue; if(!xml) { - zebra_symbol_type_t type = zebra_symbol_get_type(sym); + zbar_symbol_type_t type = zbar_symbol_get_type(sym); printf("%s%s:%s\n", - zebra_get_symbol_name(type), zebra_get_addon_name(type), - zebra_symbol_get_data(sym)); + zbar_get_symbol_name(type), zbar_get_addon_name(type), + zbar_symbol_get_data(sym)); } else { if(!n) - printf("\n", zebra_image_get_sequence(img)); - printf("%s\n", zebra_symbol_xml(sym, &xml_buf, &xml_len)); + printf("\n", zbar_image_get_sequence(img)); + printf("%s\n", zbar_symbol_xml(sym, &xml_buf, &xml_len)); } n++; } @@ -117,15 +117,15 @@ static void data_handler (zebra_image_t *img, const void *userdata) int main (int argc, const char *argv[]) { - /* setup zebra library standalone processor, + /* setup zbar library standalone processor, * threads will be used if available */ - proc = zebra_processor_create(1); + proc = zbar_processor_create(1); if(!proc) { fprintf(stderr, "ERROR: unable to allocate memory?\n"); return(1); } - zebra_processor_set_data_handler(proc, data_handler, NULL); + zbar_processor_set_data_handler(proc, data_handler, NULL); const char *video_device = "/dev/video0"; int display = 1; @@ -146,7 +146,7 @@ int main (int argc, const char *argv[]) } switch(argv[i][j]) { case 'h': return(usage(0)); - case 'v': zebra_increase_verbosity(); break; + case 'v': zbar_increase_verbosity(); break; case 'q': quiet = 1; break; default: fprintf(stderr, "ERROR: unknown bundled config: -%c\n\n", @@ -179,9 +179,9 @@ int main (int argc, const char *argv[]) else if(!strcmp(argv[i], "--nodisplay")) display = 0; else if(!strcmp(argv[i], "--verbose")) - zebra_increase_verbosity(); + zbar_increase_verbosity(); else if(!strncmp(argv[i], "--verbose=", 10)) - zebra_set_verbosity(strtol(argv[i] + 10, NULL, 0)); + zbar_set_verbosity(strtol(argv[i] + 10, NULL, 0)); else if(!strncmp(argv[i], "--prescale=", 11)) { char *x = NULL; long int w = strtol(argv[i] + 11, &x, 10); @@ -192,15 +192,15 @@ int main (int argc, const char *argv[]) fprintf(stderr, "ERROR: invalid prescale: %s\n\n", argv[i]); return(usage(1)); } - zebra_processor_request_size(proc, w, h); + zbar_processor_request_size(proc, w, h); } else if(!strncmp(argv[i], "--v4l=", 6)) { long int v = strtol(argv[i] + 6, NULL, 0); - zebra_processor_request_interface(proc, v); + zbar_processor_request_interface(proc, v); } else if(!strncmp(argv[i], "--iomode=", 9)) { long int v = strtol(argv[i] + 9, NULL, 0); - zebra_processor_request_iomode(proc, v); + zbar_processor_request_iomode(proc, v); } else if(!strncmp(argv[i], "--infmt=", 8) && strlen(argv[i]) == 12) @@ -218,13 +218,13 @@ int main (int argc, const char *argv[]) } if(infmt || outfmt) - zebra_processor_force_format(proc, infmt, outfmt); + zbar_processor_force_format(proc, infmt, outfmt); /* open video device, open window */ - if(zebra_processor_init(proc, video_device, display) || + if(zbar_processor_init(proc, video_device, display) || /* show window */ - (display && zebra_processor_set_visible(proc, 1))) - return(zebra_processor_error_spew(proc, 0)); + (display && zbar_processor_set_visible(proc, 1))) + return(zbar_processor_error_spew(proc, 0)); if(xml) { printf(xml_head, video_device); @@ -232,23 +232,23 @@ int main (int argc, const char *argv[]) } /* start video */ - if(zebra_processor_set_active(proc, 1)) - return(zebra_processor_error_spew(proc, 0)); + if(zbar_processor_set_active(proc, 1)) + return(zbar_processor_error_spew(proc, 0)); /* let the callback handle data */ int rc; - while((rc = zebra_processor_user_wait(proc, -1)) >= 0) { + while((rc = zbar_processor_user_wait(proc, -1)) >= 0) { if(rc == 'q') break; } /* report any errors that aren't "window closed" */ if(rc && rc != 'q' && - zebra_processor_get_error_code(proc) != ZEBRA_ERR_CLOSED) - return(zebra_processor_error_spew(proc, 0)); + zbar_processor_get_error_code(proc) != ZBAR_ERR_CLOSED) + return(zbar_processor_error_spew(proc, 0)); /* free resources (leak check) */ - zebra_processor_destroy(proc); + zbar_processor_destroy(proc); if(xml) { printf(xml_foot); diff --git a/zbarimg/Makefile.am.inc b/zbarimg/Makefile.am.inc new file mode 100644 index 0000000..45041f9 --- /dev/null +++ b/zbarimg/Makefile.am.inc @@ -0,0 +1,6 @@ +bin_PROGRAMS += zbarimg/zbarimg +zbarimg_zbarimg_SOURCES = zbarimg/zbarimg.cpp +zbarimg_zbarimg_CPPFLAGS = $(MAGICK_CFLAGS) $(AM_CPPFLAGS) +zbarimg_zbarimg_LDADD = $(MAGICK_LIBS) zbar/libzbar.la +# automake bug in "monolithic mode"? +CLEANFILES += zbarimg/.libs/zbarimg diff --git a/zebraimg/zebraimg.cpp b/zbarimg/zbarimg.cpp similarity index 93% rename from zebraimg/zebraimg.cpp rename to zbarimg/zbarimg.cpp index 34099b1..7724022 100644 --- a/zebraimg/zebraimg.cpp +++ b/zbarimg/zbarimg.cpp @@ -1,24 +1,24 @@ //------------------------------------------------------------------------ -// Copyright 2007-2008 (c) Jeff Brown +// Copyright 2007-2009 (c) Jeff Brown // -// This file is part of the Zebra Barcode Library. +// This file is part of the ZBar Bar Code Reader. // -// The Zebra Barcode Library is free software; you can redistribute it +// 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 Zebra Barcode Library is distributed in the hope that it will be +// 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 Zebra Barcode Library; if not, write to the Free +// 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/zebra +// http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ #include @@ -47,13 +47,13 @@ #include #include -#include +#include using namespace std; -using namespace zebra; +using namespace zbar; static const char *note_usage = - "usage: zebraimg [options] ...\n" + "usage: zbarimg [options] ...\n" "\n" "scan and decode bar codes from one or more image files\n" "\n" @@ -83,7 +83,7 @@ static const char *warning_not_found = " - is there sufficient contrast/illumination?\n"; static const char *xml_head = - ""; + ""; static const char *xml_foot = ""; @@ -200,7 +200,7 @@ int main (int argc, const char *argv[]) switch(arg[j]) { case 'h': return(usage(0)); case 'q': quiet = true; break; - case 'v': zebra_increase_verbosity(); break; + case 'v': zbar_increase_verbosity(); break; case 'd': display = true; break; case 'D': break; default: @@ -220,12 +220,12 @@ int main (int argc, const char *argv[]) argv[i] = NULL; } else if(arg == "--verbose") - zebra_increase_verbosity(); + zbar_increase_verbosity(); else if(arg.substr(0, 10) == "--verbose=") { istringstream scan(arg.substr(10)); int level; scan >> level; - zebra_set_verbosity(level); + zbar_set_verbosity(level); } else if(arg == "--display") display = true; diff --git a/zebra/Makefile.am.inc b/zebra/Makefile.am.inc deleted file mode 100644 index 005e825..0000000 --- a/zebra/Makefile.am.inc +++ /dev/null @@ -1,62 +0,0 @@ -lib_LTLIBRARIES += zebra/libzebra.la -zebra_libzebra_la_CPPFLAGS = -I$(srcdir)/zebra $(AM_CPPFLAGS) -zebra_libzebra_la_LDFLAGS = -no-undefined -version-info $(LIB_VERSION) \ - -export-symbols-regex "^(zebra|_zebra.*_error)_.*" $(AM_LDFLAGS) -zebra_libzebra_la_LIBADD = - -zebra_libzebra_la_SOURCES = zebra/debug.h zebra/config.c \ - zebra/error.h zebra/error.c zebra/symbol.h zebra/symbol.c \ - zebra/image.h zebra/image.c zebra/convert.c zebra/logo.c \ - zebra/window.h zebra/window.c zebra/video.h zebra/video.c \ - zebra/img_scanner.c zebra/scanner.c \ - zebra/decoder.h zebra/decoder.c - -if HAVE_POLL -zebra_libzebra_la_SOURCES += zebra/processor.h zebra/processor.c -endif - -if ENABLE_EAN -zebra_libzebra_la_SOURCES += zebra/decoder/ean.h zebra/decoder/ean.c -endif -if ENABLE_CODE128 -zebra_libzebra_la_SOURCES += zebra/decoder/code128.h zebra/decoder/code128.c -endif -if ENABLE_CODE39 -zebra_libzebra_la_SOURCES += zebra/decoder/code39.h zebra/decoder/code39.c -endif -if ENABLE_I25 -zebra_libzebra_la_SOURCES += zebra/decoder/i25.h zebra/decoder/i25.c -endif -if ENABLE_PDF417 -zebra_libzebra_la_SOURCES += zebra/decoder/pdf417.h zebra/decoder/pdf417.c \ - zebra/decoder/pdf417_hash.h -endif - -if HAVE_V4L1 -zebra_libzebra_la_SOURCES += zebra/video/v4l1.c -if HAVE_V4L2 -zebra_libzebra_la_SOURCES += zebra/video/v4l2.c -endif -else -zebra_libzebra_la_SOURCES += zebra/video/null.c -endif - -if HAVE_JPEG -zebra_libzebra_la_SOURCES += zebra/jpeg.c -endif - -if HAVE_X -zebra_libzebra_la_SOURCES += zebra/window/x.c zebra/window/ximage.c -zebra_libzebra_la_CPPFLAGS += $(X_CFLAGS) -zebra_libzebra_la_LDFLAGS += $(X_LIBS) -zebra_libzebra_la_LIBADD += $(X_PRE_LIBS) -lX11 $(X_EXTRA_LIBS) -if HAVE_XV -zebra_libzebra_la_SOURCES += zebra/window/xv.c -zebra_libzebra_la_LIBADD += $(XV_LIBS) -endif -else -zebra_libzebra_la_SOURCES += zebra/window/null.c -endif - -zebra_libzebra_la_LDFLAGS += $(AM_LDFLAGS) -zebra_libzebra_la_LIBADD += $(AM_LIBADD) diff --git a/zebra/logo.c b/zebra/logo.c deleted file mode 100644 index 3ae5b27..0000000 --- a/zebra/logo.c +++ /dev/null @@ -1,386 +0,0 @@ -/*------------------------------------------------------------------------ - * Copyright 2008 (c) Jeff Brown - * - * This file is part of the Zebra Barcode Library. - * - * The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301 USA - * - * http://sourceforge.net/projects/zebra - *------------------------------------------------------------------------*/ - -#include -#include "image.h" -#include "error.h" - -#define LOGO_WIDTH 432 -#define LOGO_HEIGHT 304 -#define LOGO_RLE_SIZE 0x62c - -static const uint8_t logo_rle[LOGO_RLE_SIZE] = { - 0x87,0x66, 0x04, 0x01, 0x60, 0x03, /*col 0*/ - 0x8f,0x0e, 0x02, 0x80,0x02, 0x02, /*col 1*/ - 0x8f,0x0a, 0x04, 0x80,0x06, 0x02, /*col 2*/ - 0x8f,0x07, 0x80,0x0a, /*col 3*/ - 0xaf,0xbf, 0x01, 0x80,0x15, /*col 8*/ - 0x87,0xf8, 0x04, 0x80,0x17, /*col 9*/ - 0x87,0xf7, 0x80,0x19, 0x01, /*col 10*/ - 0x87,0xf4, 0x80,0x1c, /*col 11*/ - 0xaf,0xa8, 0x06, 0x01, 0x80,0x27, /*col 16*/ - 0x87,0xe3, 0x06, 0x03, 0x80,0x2b, /*col 17*/ - 0x87,0xd3, 0x06, 0x04, 0x03, 0x42, 0x01, 0x80,0x2f, 0x01, /*col 18*/ - 0x87,0xcc, 0x03, 0x01, 0x80,0x41, 0x04, /*col 19*/ - 0x87,0xc9, 0x03, 0x80,0x45, /*col 20*/ - 0x87,0xc7, 0x06, 0x80,0x48, /*col 21*/ - 0x87,0xc6, 0x01, 0x80,0x48, 0x05, /*col 22*/ - 0x87,0xc4, 0x05, 0x80,0x4a, /*col 23*/ - 0xaf,0x64, 0x01, 0x80,0x67, /*col 28*/ - 0x87,0xa7, 0x80,0x68, /*col 29*/ - 0x87,0xa7, 0x80,0x68, /*col 30*/ - 0x87,0xa7, 0x80,0x68, /*col 31*/ - 0x87,0xa7, 0x80,0x68, /*col 32*/ - 0x87,0xa6, 0x06, 0x80,0x68, /*col 33*/ - 0x87,0xa6, 0x02, 0x80,0x68, /*col 34*/ - 0x87,0xa6, 0x80,0x68, 0x01, /*col 35*/ - 0x87,0xa6, 0x80,0x68, 0x01, /*col 36*/ - 0x87,0xa5, 0x05, 0x80,0x68, 0x02, /*col 37*/ - 0x87,0xa5, 0x03, 0x80,0x68, 0x01, /*col 38*/ - 0x87,0xa5, 0x02, 0x80,0x69, /*col 39*/ - 0xc7,0x02,0x20, 0x03, 0x80,0x67, 0x03, /*col 48*/ - 0x87,0xa7, 0x80,0x68, /*col 49*/ - 0x87,0xa8, 0x80,0x67, /*col 50*/ - 0x87,0xa9, 0x80,0x66, 0x06, /*col 51*/ - 0xc7,0x06,0xe8, 0x03, 0x80,0x5c, /*col 64*/ - 0x87,0xb3, 0x03, 0x80,0x5b, /*col 65*/ - 0x87,0xb4, 0x03, 0x80,0x5a, /*col 66*/ - 0x87,0xb5, 0x03, 0x80,0x59, 0x06, /*col 67*/ - 0xc7,0x0b,0xbb, 0x80,0x5b, 0x01, /*col 84*/ - 0x87,0xb4, 0x03, 0x80,0x5c, /*col 85*/ - 0x87,0xb4, 0x80,0x5d, /*col 86*/ - 0x87,0xb3, 0x80,0x5e, /*col 87*/ - 0xaf,0x73, 0x80,0x62, /*col 92*/ - 0x87,0xae, 0x04, 0x80,0x62, /*col 93*/ - 0x87,0xae, 0x80,0x62, 0x01, /*col 94*/ - 0x87,0xad, 0x80,0x63, 0x04, /*col 95*/ - 0xaf,0x6d, 0x01, 0x80,0x66, /*col 100*/ - 0x87,0xa9, 0x06, 0x80,0x67, /*col 101*/ - 0x87,0xa9, 0x80,0x67, 0x01, /*col 102*/ - 0x87,0xa8, 0x80,0x68, 0x01, /*col 103*/ - 0x87,0xa7, 0x04, 0x80,0x68, 0x02, /*col 104*/ - 0x87,0xa7, 0x80,0x69, 0x02, /*col 105*/ - 0x87,0xa6, 0x80,0x6a, 0x01, /*col 106*/ - 0x87,0xa5, 0x02, 0x80,0x6a, 0x01, /*col 107*/ - 0xc7,0x06,0xe8, 0x80,0x7f, 0x03, /*col 120*/ - 0x87,0x90, 0x80,0x81, 0x06, /*col 121*/ - 0x87,0x8e, 0x80,0x82, 0x01, /*col 122*/ - 0x87,0x8d, 0x03, 0x80,0x83, /*col 123*/ - 0xc7,0x02,0x10, 0x80,0x89, 0x04, /*col 132*/ - 0x87,0x86, 0x06, 0x80,0x8b, 0x03, 0x87,0x67, 0x01, 0x08, 0x05, /*col 133*/ - 0x87,0x09, 0x80,0x8e, 0x03, 0x87,0x62, 0x01, 0x20, 0x02, /*col 134*/ - 0x87,0x08, 0x05, 0x80,0x90, 0x03, 0x87,0x5d, 0x06, 0x38, 0x06, /*col 135*/ - 0x87,0x08, 0x80,0x93, 0x02, 0x87,0x59, 0x04, 0x48, /*col 136*/ - 0x87,0x08, 0x05, 0x80,0x95, 0x02, 0x87,0x55, 0x02, 0x50, /*col 137*/ - 0x87,0x09, 0x80,0x98, 0x05, 0x87,0x51, 0x02, 0x58, /*col 138*/ - 0x87,0x09, 0x04, 0x80,0x99, 0x01, 0x87,0x4e, 0x01, 0x60, 0x03, /*col 139*/ - 0x87,0x09, 0x80,0x9c, 0x03, 0x87,0x4a, 0x78, /*col 140*/ - 0x87,0x09, 0x03, 0x80,0x9e, 0x04, 0x87,0x46, 0x01, 0x78, /*col 141*/ - 0x87,0x0a, 0x80,0xa1, 0x01, 0x05, 0x87,0x41, 0x02, 0x80,0x01, /*col 142*/ - 0x87,0x0a, 0x04, 0x80,0xa5, 0x02, 0x05, 0x87,0x3b, 0x01, 0x80,0x02, /*col 143*/ - 0xa7,0xcd, 0x03, 0x80,0xbe, 0x02, 0x05, 0x87,0x17, 0x03, 0x80,0x09, 0x01, /*col 148*/ - 0x87,0x0e, 0x01, 0x80,0xc3, 0x01, 0x03, 0x04, 0x86,0x0c, 0x04, 0x01, 0x80,0x0c, 0x05, /*col 149*/ - 0x87,0x0f, 0x03, 0x80,0xff, /*col 150*/ - 0x87,0x11, 0x05, 0x80,0xfe, /*col 151*/ - 0xa7,0xd8, 0x80,0xf1, 0x04, /*col 156*/ - 0x87,0x1f, 0x01, 0x80,0xea, 0x06, /*col 157*/ - 0x87,0x25, 0x05, 0x80,0xe7, /*col 158*/ - 0x87,0x2a, 0x80,0xe5, /*col 159*/ - 0x87,0x2c, 0x02, 0x80,0xe2, /*col 160*/ - 0x87,0x2f, 0x01, 0x80,0xdf, /*col 161*/ - 0x87,0x31, 0x05, 0x80,0xdd, 0x05, /*col 162*/ - 0x87,0x33, 0x80,0xac, 0x01, 0x02, 0x03, 0x0c, 0x05, 0x06, 0x3f, 0x06, 0x0d, 0x04, 0x03, 0x02, 0x01, 0x80,0x0a, /*col 163*/ - 0x87,0x35, 0x80,0x8d, 0x09, 0x02, 0x03, 0x04, 0x0e, 0x87,0x28, 0x06, 0x04, 0x01, 0x48, 0x01, /*col 164*/ - 0x87,0x36, 0x02, 0x80,0x77, 0x02, 0x03, 0x0d, 0x06, 0x87,0x45, 0x04, 0x01, 0x18, 0x06, /*col 165*/ - 0x87,0x38, 0x80,0x74, 0x05, /*col 166*/ - 0x87,0x9b, 0x80,0x76, 0x06, /*col 167*/ - 0x87,0x99, 0x80,0x78, 0x06, /*col 168*/ - 0x87,0x97, 0x80,0x7a, 0x05, /*col 169*/ - 0x87,0x95, 0x01, 0x80,0x7b, 0x02, /*col 170*/ - 0x87,0x93, 0x03, 0x80,0x7e, 0x06, /*col 171*/ - 0xaf,0x51, 0x80,0x8c, 0x02, 0x06, /*col 176*/ - 0x87,0x82, 0x80,0x90, 0x02, 0x05, /*col 177*/ - 0x87,0x7e, 0x80,0x94, 0x01, 0x04, /*col 178*/ - 0x87,0x7a, 0x01, 0x80,0x98, 0x01, 0x05, /*col 179*/ - 0xaf,0x36, 0x80,0xa8, 0x01, /*col 184*/ - 0x87,0x67, 0x80,0xaa, 0x03, /*col 185*/ - 0x87,0x65, 0x80,0xac, 0x06, 0x87,0x23, 0x02, 0x10, 0x01, /*col 186*/ - 0x87,0x2b, 0x80,0xae, 0x06, 0x87,0x1f, 0x01, 0x30, /*col 187*/ - 0xa7,0xeb, 0x04, 0x80,0xc2, 0x04, 0x7f, 0x06, 0x78, 0x01, /*col 192*/ - 0x87,0x2b, 0x80,0xc9, 0x09, 0x02, 0x03, 0x04, 0x0d, 0x04, 0x80,0x03, 0x01, /*col 193*/ - 0x87,0x2b, 0x80,0xe4, 0x01, /*col 194*/ - 0x87,0x2b, 0x06, 0x80,0xe3, 0x01, /*col 195*/ - 0xa7,0xed, 0x80,0x6e, 0x87,0x22, 0x06, 0x04, 0x02, 0x80,0x2f, 0x02, /*col 200*/ - 0x87,0x2d, 0x05, 0x80,0x6e, 0x87,0x29, 0x05, 0x03, 0x01, 0x80,0x27, 0x04, /*col 201*/ - 0x87,0x2e, 0x80,0x6e, 0x05, 0x87,0x2f, 0x06, 0x04, 0x02, 0x80,0x20, /*col 202*/ - 0x87,0x2f, 0x80,0x6f, 0x87,0x36, 0x06, 0x04, 0x02, 0x80,0x18, 0x01, /*col 203*/ - 0x87,0x2f, 0x05, 0x80,0x6e, 0x05, 0x87,0x3d, 0x05, 0x03, 0x01, 0x80,0x0f, 0x02, /*col 204*/ - 0x87,0x31, 0x80,0x6f, 0x87,0x44, 0x06, 0x03, 0x78, 0x01, 0x06, /*col 205*/ - 0x87,0x39, 0x80,0x6f, 0x87,0x48, 0x06, 0x01, 0x48, 0x04, /*col 206*/ - 0x87,0x3c, 0x01, 0x80,0x6e, 0x01, 0x87,0x4b, 0x04, 0x18, 0x04, /*col 207*/ - 0xaf,0x00, 0x01, 0x80,0x6f, 0x06, /*col 212*/ - 0x87,0x9f, 0x03, 0x80,0x6f, 0x03, /*col 213*/ - 0x87,0x9f, 0x03, 0x80,0x70, /*col 214*/ - 0x87,0x9f, 0x03, 0x80,0x70, /*col 215*/ - 0x87,0x9f, 0x03, 0x80,0x70, /*col 216*/ - 0x87,0x9f, 0x03, 0x80,0x70, 0x04, /*col 217*/ - 0x87,0x9e, 0x03, 0x80,0x71, /*col 218*/ - 0x87,0x9e, 0x03, 0x80,0x71, /*col 219*/ - 0xc7,0x02,0x1e, 0x03, 0x80,0x74, /*col 228*/ - 0x87,0x9b, 0x02, 0x80,0x74, /*col 229*/ - 0x87,0x9b, 0x01, 0x80,0x74, 0x06, /*col 230*/ - 0x87,0x9a, 0x80,0x75, 0x03, /*col 231*/ - 0x87,0x9a, 0x80,0x75, 0x01, /*col 232*/ - 0x87,0x9a, 0x80,0x76, /*col 233*/ - 0x87,0x9a, 0x80,0x76, /*col 234*/ - 0x87,0x9a, 0x80,0x76, /*col 235*/ - 0xc7,0x02,0x19, 0x80,0x77, /*col 244*/ - 0x87,0x98, 0x06, 0x80,0x77, /*col 245*/ - 0x87,0x98, 0x04, 0x80,0x77, /*col 246*/ - 0x87,0x98, 0x02, 0x80,0x77, 0x06, /*col 247*/ - 0x87,0x97, 0x80,0x78, 0x06, /*col 248*/ - 0x87,0x97, 0x80,0x78, 0x05, /*col 249*/ - 0x87,0x96, 0x04, 0x80,0x78, 0x02, /*col 250*/ - 0x87,0x96, 0x80,0x7a, /*col 251*/ - 0xaf,0x55, 0x80,0x7b, 0x06, /*col 256*/ - 0x87,0x93, 0x02, 0x80,0x7b, 0x06, /*col 257*/ - 0x87,0x93, 0x80,0x7c, /*col 258*/ - 0x87,0x94, 0x80,0x7c, /*col 259*/ - 0x87,0x93, 0x04, 0x80,0x7c, /*col 260*/ - 0x87,0x93, 0x80,0x7d, /*col 261*/ - 0x87,0x93, 0x80,0x7c, 0x02, /*col 262*/ - 0x87,0x92, 0x05, 0x80,0x7c, 0x05, /*col 263*/ - 0x87,0x92, 0x01, 0x80,0x7c, /*col 264*/ - 0x87,0x93, 0x80,0x7d, /*col 265*/ - 0x87,0x93, 0x80,0x7c, 0x04, /*col 266*/ - 0x87,0x92, 0x02, 0x80,0x7c, /*col 267*/ - 0xc7,0x02,0x11, 0x80,0x7c, /*col 276*/ - 0x87,0x94, 0x80,0x7b, 0x04, /*col 277*/ - 0x87,0x93, 0x06, 0x80,0x7b, /*col 278*/ - 0x87,0x94, 0x05, 0x80,0x7a, 0x02, /*col 279*/ - 0xaf,0x54, 0x80,0x79, /*col 284*/ - 0x87,0x97, 0x80,0x78, 0x01, /*col 285*/ - 0x87,0x97, 0x80,0x78, /*col 286*/ - 0x87,0x98, 0x80,0x77, 0x03, /*col 287*/ - 0x87,0x97, 0x04, 0x80,0x77, /*col 288*/ - 0x87,0x98, 0x80,0x77, 0x03, /*col 289*/ - 0x87,0x98, 0x80,0x77, /*col 290*/ - 0x87,0x99, 0x80,0x76, 0x04, /*col 291*/ - 0xc7,0x02,0x16, 0x05, 0x80,0x72, /*col 300*/ - 0x87,0x9d, 0x01, 0x80,0x71, /*col 301*/ - 0x87,0x9e, 0x80,0x71, /*col 302*/ - 0x87,0x9f, 0x80,0x6f, 0x01, /*col 303*/ - 0x87,0x9f, 0x06, 0x80,0x6e, 0x03, /*col 304*/ - 0x87,0xa0, 0x02, 0x80,0x6d, 0x03, /*col 305*/ - 0x87,0xa1, 0x80,0x6d, 0x03, /*col 306*/ - 0x87,0xa2, 0x80,0x6c, 0x02, /*col 307*/ - 0xaf,0x62, 0x05, 0x80,0x6f, 0x01, /*col 312*/ - 0x87,0x9f, 0x05, 0x80,0x71, 0x02, 0x87,0x54, 0x05, 0x0a, 0x04, /*col 313*/ - 0x87,0x35, 0x05, 0x80,0x73, 0x03, 0x87,0x4e, 0x06, 0x38, 0x06, /*col 314*/ - 0x87,0x33, 0x05, 0x80,0x75, 0x04, 0x87,0x4a, 0x04, 0x50, 0x02, /*col 315*/ - 0x87,0x32, 0x05, 0x80,0x77, 0x05, 0x87,0x46, 0x02, 0x68, 0x01, /*col 316*/ - 0x87,0x31, 0x05, 0x80,0x79, 0x06, 0x87,0x42, 0x06, 0x80,0x01, /*col 317*/ - 0x87,0x31, 0x05, 0x80,0x7b, 0x87,0x40, 0x80,0x03, 0x03, /*col 318*/ - 0x87,0x30, 0x05, 0x80,0x7c, 0x01, 0x87,0x3b, 0x04, 0x80,0x06, /*col 319*/ - 0xa7,0xf0, 0x05, 0x80,0x85, 0x87,0x24, 0x05, 0x01, 0x80,0x13, /*col 324*/ - 0x87,0x31, 0x05, 0x80,0x86, 0x01, 0x87,0x1e, 0x06, 0x02, 0x80,0x16, 0x01, /*col 325*/ - 0x87,0x31, 0x05, 0x80,0x88, 0x02, 0x87,0x17, 0x05, 0x03, 0x01, 0x80,0x1a, /*col 326*/ - 0x87,0x32, 0x05, 0x80,0x8b, 0x01, 0x82,0x0e, 0x01, 0x80,0x21, 0x06, /*col 327*/ - 0x87,0x32, 0x05, 0x80,0xdb, 0x05, /*col 328*/ - 0x87,0x33, 0x05, 0x80,0xda, 0x02, /*col 329*/ - 0x87,0x34, 0x05, 0x80,0xca, 0x01, 0x03, 0x14, 0x48, 0x03, /*col 330*/ - 0x87,0x35, 0x05, 0x80,0xc4, 0x01, 0x04, 0x47, 0x40, 0x01, /*col 331*/ - 0xc7,0x01,0xb7, 0x01, 0x80,0xd7, 0x05, /*col 340*/ - 0x87,0x38, 0x80,0xd6, 0x06, /*col 341*/ - 0x87,0x39, 0x01, 0x80,0xd4, /*col 342*/ - 0x87,0x3c, 0x80,0xd2, 0x06, /*col 343*/ - 0xc7,0x01,0xc2, 0x04, 0x80,0x65, 0x01, 0x7f, 0x02, 0x80,0x1d, 0x03, 0x06, /*col 352*/ - 0x87,0x6a, 0x80,0x64, 0x05, 0x87,0x02, 0x06, 0x80,0x16, 0x02, 0x04, /*col 353*/ - 0x87,0x71, 0x80,0x62, 0x06, 0x87,0x05, 0x01, 0x80,0x0f, 0x03, 0x06, /*col 354*/ - 0x87,0x76, 0x02, 0x80,0x5f, 0x04, 0x87,0x08, 0x04, 0x80,0x08, 0x01, 0x04, /*col 355*/ - 0xc7,0x06,0xc7, 0x01, 0x80,0x33, 0x01, /*col 368*/ - 0x87,0xdc, 0x02, 0x80,0x30, 0x03, /*col 369*/ - 0x87,0xdf, 0x04, 0x80,0x2d, 0x04, /*col 370*/ - 0x87,0xe2, 0x06, 0x80,0x2a, 0x03, /*col 371*/ - 0xa7,0xa7, 0x04, 0x01, 0x78, 0x09, 0x02, 0x03, 0x04, 0x06, /*col 375*/ - 0x87,0xde, 0x04, 0x01, 0x80,0x34, 0x01, 0x03, 0x06, /*col 376*/ - 0x87,0xdc, 0x05, 0x03, 0x01, 0x80,0x33, 0x01, 0x06, /*col 377*/ - 0x87,0xe0, 0x06, 0x05, 0x04, 0x02, 0x01, 0x80,0x01, 0x02, 0x01, 0x80,0x19, 0x03, /*col 378*/ - 0x87,0xf3, 0x0a, 0x01, 0x80,0x1b, 0x02, /*col 379*/ - 0x87,0xf8, 0x04, 0x80,0x18, 0x05, /*col 380*/ - 0x87,0xfa, 0x06, 0x02, 0x80,0x15, /*col 381*/ - 0x87,0xfd, 0x05, 0x01, 0x80,0x12, 0x06, /*col 382*/ - 0x87,0xfe, 0x06, 0x01, 0x80,0x10, 0x05, /*col 383*/ - 0x8f,0x00, 0x06, 0x01, 0x80,0x0e, 0x02, /*col 384*/ - 0x8f,0x02, 0x06, 0x01, 0x80,0x0d, /*col 385*/ - 0x8f,0x04, 0x04, 0x80,0x0c, /*col 386*/ - 0x8f,0x05, 0x06, 0x80,0x0b, /*col 387*/ - 0x8f,0x07, 0x01, 0x80,0x09, /*col 388*/ - 0x8f,0x08, 0x03, 0x80,0x07, 0x01, /*col 389*/ - 0x8f,0x09, 0x03, 0x80,0x06, 0x03, /*col 390*/ - 0x8f,0x0a, 0x80,0x06, 0x06, /*col 391*/ - 0x8f,0x0a, 0x04, 0x80,0x05, /*col 392*/ - 0x8f,0x0c, 0x80,0x05, /*col 393*/ - 0x8f,0x0c, 0x80,0x05, /*col 394*/ - 0x8f,0x0c, 0x03, 0x80,0x03, 0x04, /*col 395*/ - 0x8f,0x0c, 0x06, 0x80,0x03, /*col 396*/ - 0x8f,0x0e, 0x80,0x03, /*col 397*/ - 0x8f,0x0e, 0x01, 0x80,0x01, 0x05, /*col 398*/ - 0x8f,0x0e, 0x06, 0x80,0x01, /*col 399*/ - 0x8f,0x10, 0x01, 0x70, 0x01, /*col 400*/ - 0x8f,0x11, 0x70, 0x06, /*col 401*/ - 0x8f,0x11, 0x03, 0x68, /*col 402*/ - 0x8f,0x13, 0x60, 0x04, /*col 403*/ - 0x8f,0x13, 0x03, 0x58, /*col 404*/ - 0x8f,0x14, 0x06, 0x50, 0x02, /*col 405*/ - 0x8f,0x15, 0x50, /*col 406*/ - 0x8f,0x16, 0x48, 0x01, /*col 407*/ - 0x8f,0x15, 0x06, 0x48, /*col 408*/ - 0x8f,0x16, 0x01, 0x48, /*col 409*/ - 0x8f,0x16, 0x48, 0x05, /*col 410*/ - 0x8f,0x15, 0x02, 0x48, /*col 411*/ - 0x8f,0x16, 0x50, /*col 412*/ - 0x8f,0x15, 0x05, 0x48, 0x03, /*col 413*/ - 0x8f,0x15, 0x50, /*col 414*/ - 0x8f,0x15, 0x06, 0x50, /*col 415*/ - 0x8f,0x15, 0x01, 0x48, 0x03, /*col 416*/ - 0x8f,0x15, 0x50, /*col 417*/ - 0x8f,0x15, 0x02, 0x48, 0x01, /*col 418*/ - 0x8f,0x15, 0x50, /*col 419*/ - 0x8f,0x15, 0x05, 0x48, 0x03, /*col 420*/ - 0x8f,0x15, 0x48, /*col 421*/ - 0x8f,0x16, 0x06, 0x40, /*col 422*/ - 0x8f,0x17, 0x01, 0x38, /*col 423*/ - 0x8f,0x18, 0x38, /*col 424*/ - 0x8f,0x18, 0x03, 0x30, 0x05, /*col 425*/ - 0x8f,0x18, 0x10, 0x07, 0x18, /*col 426*/ - 0x8f,0x18, 0x05, 0x08, 0x0f, 0x05, 0x08, 0x05, /*col 427*/ - 0x8f,0x18, 0x08, 0x1f, 0x03, 0x00, /*col 428*/ - 0x8f,0x19, 0x00, /*col 429*/ - 0x8f,0x1f, 0x01, /*col 430*/ - 0x8f,0x99, -}; - -int _zebra_draw_logo (zebra_image_t *img) -{ - unsigned w = zebra_image_get_width(img); - unsigned h = zebra_image_get_height(img); - if(w < 128 || h < 90) { - w = 128; - h = 90; - zebra_image_set_size(img, w, h); - } - - zebra_image_set_format(img, fourcc('Y','8','0','0')); - zprintf(5, "fitting (%d x %d) into (%d x %d)\n", - LOGO_WIDTH, LOGO_HEIGHT, w, h); - - unsigned sw = 1, sh = 1; - int sf; - for(sf = 3; sf >= -2; sf--) { - sw = (LOGO_WIDTH << 3) >> (3 - sf); - sh = (LOGO_HEIGHT << 3) >> (3 - sf); - /* FIXME add minimum border */ - zprintf(6, " trying << %d => %d x %d\n", sf, sw, sh); - if(sw <= w && sh <= h) - break; - } - - int datalen = w * h; - uint8_t *data = malloc(datalen); - assert(data); - zebra_image_set_data(img, data, datalen, zebra_image_free_data); - memset(data, 0xff, datalen); - - unsigned xpad = (w - sw + 1) / 2; - unsigned ypad = (h - sh + 1) / 2; - - const uint8_t *rle = logo_rle; - uint8_t *p = NULL; /* (((pix & 0x7) * 255 + 6) / 7) */ - unsigned n = 0, pix = 0x7; - unsigned x, y, i, j, mask = (sf >= 0) ? (1 << sf) - 1 : (1 << -sf) - 1; - - for(x = 0; x < LOGO_WIDTH; x++) { - p = data + (ypad * w) + xpad + ((x << 3) >> (3 - sf)); - zprintf(64, " [%03d]", x); - for(y = 0; y < LOGO_HEIGHT; y++) { - if(!n) { - pix = *(rle++); - if((pix & 0xc0) == 0xc0) { - n = *(rle++) << 8; - n += *(rle++) + 0x810; - } - else if(pix & 0x80) - n = (((pix & 0x38) << 5) | *(rle++)) + 0x10; - else - n = ((pix >> 3) & 0x0f) + 1; - pix &= 0x7; - if(sf >= 0) - pix = ((pix * 255) + 6) / 7; - if(_zebra_verbosity >= 64) - fprintf(stderr, " (%03d) pix=%02x n=%04x", y, pix, n); - - } - - if(!sf) { - *p = pix; - p += w; - } - else if(sf > 0) - for(i = 0; i <= mask; i++) { - for(j = 0; j <= mask; j++) - *(p++) = pix; - p += w - mask - 1; - } - else { - if(!((x | y) & mask)) - *p = pix; - else - *p += pix; - if((y & mask) == mask) - p += w; - } - n--; - } - if(_zebra_verbosity >= 64) - fprintf(stderr, "\n"); - } - - if(sf < 0) { - /* make 2nd pass to finish merging subsamples */ - p = data + (ypad * w) + xpad; - unsigned div = (mask + 1) * (mask + 1) * 7; - for(y = 0; y < sh; y++) { - for(x = 0; x < sw; x++, p++) - *p = (((unsigned)*p) * 255 + div - 1) / div; - p += w - sw; - } - } - - zprintf(6, " rle=%p + size=%x = %p\n", logo_rle, LOGO_RLE_SIZE, rle); - if(rle != logo_rle + LOGO_RLE_SIZE) - fprintf(stderr, "WARNING: zebra internal: logo rle not at end?\n"); - zprintf(6, " data=%p + len=%x = %p\n", data, datalen, p); - - return(0); -} diff --git a/zebra/window/null.c b/zebra/window/null.c deleted file mode 100644 index f620682..0000000 --- a/zebra/window/null.c +++ /dev/null @@ -1,87 +0,0 @@ -/*------------------------------------------------------------------------ - * Copyright 2008 (c) Jeff Brown - * - * This file is part of the Zebra Barcode Library. - * - * The Zebra Barcode Library 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 Zebra Barcode Library 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 Zebra Barcode Library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301 USA - * - * http://sourceforge.net/projects/zebra - *------------------------------------------------------------------------*/ - -#include "window.h" - -static inline int null_error (void *m, - const char *func) -{ - return(err_capture(m, SEV_ERROR, ZEBRA_ERR_UNSUPPORTED, func, - "not compiled with output window support")); -} - -int _zebra_window_attach (zebra_window_t *w, - void *display, - unsigned long win) -{ - return(null_error(w, __func__)); -} - -int _zebra_window_handle_events (zebra_processor_t *proc, - int block) -{ - return(null_error(proc, __func__)); -} - -int _zebra_window_open (zebra_processor_t *proc, - char *title, - unsigned width, - unsigned height) -{ - return(null_error(proc, __func__)); -} - -int _zebra_window_close (zebra_processor_t *proc) -{ - return(null_error(proc, __func__)); -} - -int _zebra_window_resize (zebra_processor_t *proc, - unsigned width, - unsigned height) -{ - return(null_error(proc, __func__)); -} - -int _zebra_window_set_visible (zebra_processor_t *proc, - int visible) -{ - return(null_error(proc, __func__)); -} - -int _zebra_window_clear (zebra_window_t *w) -{ - return(null_error(w, __func__)); -} - -int _zebra_window_invalidate (zebra_window_t *w) -{ - return(0); -} - -int _zebra_window_draw_marker(zebra_window_t *w, - uint32_t rgb, - const point_t *p) -{ - return(null_error(w, __func__)); -} diff --git a/zebracam/Makefile.am.inc b/zebracam/Makefile.am.inc deleted file mode 100644 index 694057b..0000000 --- a/zebracam/Makefile.am.inc +++ /dev/null @@ -1,5 +0,0 @@ -bin_PROGRAMS += zebracam/zebracam -zebracam_zebracam_SOURCES = zebracam/zebracam.c -zebracam_zebracam_LDADD = zebra/libzebra.la -# automake bug in "monolithic mode"? -CLEANFILES += zebracam/.libs/zebracam diff --git a/zebraimg/Makefile.am.inc b/zebraimg/Makefile.am.inc deleted file mode 100644 index 7d48ef8..0000000 --- a/zebraimg/Makefile.am.inc +++ /dev/null @@ -1,6 +0,0 @@ -bin_PROGRAMS += zebraimg/zebraimg -zebraimg_zebraimg_SOURCES = zebraimg/zebraimg.cpp -zebraimg_zebraimg_CPPFLAGS = $(MAGICK_CFLAGS) $(AM_CPPFLAGS) -zebraimg_zebraimg_LDADD = $(MAGICK_LIBS) zebra/libzebra.la -# automake bug in "monolithic mode"? -CLEANFILES += zebraimg/.libs/zebraimg From 290956efdc2650fddeb1efe41770a5cb268b516e Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 21 Apr 2009 00:41:33 +0000 Subject: [PATCH 084/328] * draw new logo (rough, no Xrender yet) * fix Makefile.am syntax error --- ChangeLog | 2 + Makefile.am | 2 +- zbar/processor.c | 18 ++++-- zbar/processor.h | 2 +- zbar/window.c | 5 +- zbar/window.h | 22 +++++-- zbar/window/null.c | 16 ++++- zbar/window/x.c | 158 ++++++++++++++++++++++++++++++++++++++++----- zbarcam/zbarcam.c | 8 ++- 9 files changed, 197 insertions(+), 36 deletions(-) diff --git a/ChangeLog b/ChangeLog index faf3d68..c674304 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ version 0.7: + * draw new logo (rough, no Xrender yet) + * fix Makefile.am syntax error * fixup some perl distribution details * project name change: everything "zebra" becomes "zbar" * remove old logo diff --git a/Makefile.am b/Makefile.am index 65b5b3f..6c57307 100644 --- a/Makefile.am +++ b/Makefile.am @@ -49,7 +49,7 @@ EXTRA_DIST += examples/upcrpc.pl examples/upcrpc.py examples/paginate.pl \ EXTRA_DIST += perl/MANIFEST perl/README perl/Changes perl/COPYING.LIB \ perl/Makefile.PL perl/typemap perl/ZBar.xs perl/ppport.h \ - perl/ZBar.pm perl/inc/Devel/CheckLib.pm perl/ZBar/Image.pod + perl/ZBar.pm perl/inc/Devel/CheckLib.pm perl/ZBar/Image.pod \ perl/ZBar/ImageScanner.pod perl/ZBar/Processor.pod perl/ZBar/Symbol.pod \ perl/examples/paginate.pl perl/examples/processor.pl \ perl/examples/scan_image.pl \ diff --git a/zbar/processor.c b/zbar/processor.c index 240d266..9b7812b 100644 --- a/zbar/processor.c +++ b/zbar/processor.c @@ -678,9 +678,9 @@ int zbar_processor_set_visible (zbar_processor_t *proc, int rc = 0; if(proc->window) { if(proc->video) - rc = _zbar_window_resize(proc, - zbar_video_get_width(proc->video), - zbar_video_get_height(proc->video)); + rc = _zbar_window_set_size(proc, + zbar_video_get_width(proc->video), + zbar_video_get_height(proc->video)); if(!rc) rc = _zbar_window_set_visible(proc, visible); } @@ -718,6 +718,7 @@ int zbar_processor_set_active (zbar_processor_t *proc, return(-1); } zbar_image_scanner_enable_cache(proc->scanner, active); + int rc = zbar_video_enable(proc->video, active); if(!rc) { int vid_fd = zbar_video_get_fd(proc->video); @@ -734,6 +735,11 @@ int zbar_processor_set_active (zbar_processor_t *proc, else err_copy(proc, proc->video); + if(!active && proc->window && + (zbar_window_draw(proc->window, NULL) || + _zbar_window_invalidate(proc->window)) && !rc) + rc = err_copy(proc, proc->window); + #ifdef HAVE_LIBPTHREAD if(proc->threaded) { assert(!proc->sem); @@ -786,9 +792,9 @@ int zbar_process_image (zbar_processor_t *proc, return(-1); int rc = 0; if(img && proc->window) - rc = _zbar_window_resize(proc, - zbar_image_get_width(img), - zbar_image_get_height(img)); + rc = _zbar_window_set_size(proc, + zbar_image_get_width(img), + zbar_image_get_height(img)); if(!rc) { zbar_image_scanner_enable_cache(proc->scanner, 0); rc = process_image(proc, img); diff --git a/zbar/processor.h b/zbar/processor.h index cda4b6b..941e204 100644 --- a/zbar/processor.h +++ b/zbar/processor.h @@ -176,7 +176,7 @@ extern int _zbar_window_open(zbar_processor_t*, char*, unsigned, unsigned); extern int _zbar_window_close(zbar_processor_t*); extern int _zbar_window_set_visible(zbar_processor_t*, int); extern int _zbar_window_invalidate(zbar_window_t*); -extern int _zbar_window_resize(zbar_processor_t*, unsigned, unsigned); +extern int _zbar_window_set_size(zbar_processor_t*, unsigned, unsigned); extern int _zbar_window_handle_events(zbar_processor_t*, int); #endif diff --git a/zbar/window.c b/zbar/window.c index 2faa9d4..c087e60 100644 --- a/zbar/window.c +++ b/zbar/window.c @@ -24,7 +24,7 @@ #include "window.h" #include "image.h" -extern int _zbar_draw_logo(zbar_window_t *w); +extern int _zbar_window_draw_logo(zbar_window_t *w); zbar_window_t *zbar_window_create () { @@ -98,7 +98,7 @@ inline int zbar_window_redraw (zbar_window_t *w) if(w->image) rc = w->draw_image(w, w->image); else - _zbar_draw_logo(w); + _zbar_window_draw_logo(w); if(!rc) rc = window_draw_overlay(w); (void)window_unlock(w); @@ -142,5 +142,6 @@ int zbar_window_resize (zbar_window_t *w, return(-1); w->width = width; w->height = height; + _zbar_window_resize(w); return(window_unlock(w)); } diff --git a/zbar/window.h b/zbar/window.h index e9abfee..fc563bd 100644 --- a/zbar/window.h +++ b/zbar/window.h @@ -90,6 +90,15 @@ struct zbar_window_s { # endif unsigned long colors[8]; /* pre-allocated colors */ + + Region exposed; + + /* pre-calculated logo geometries */ + int logo_scale; + unsigned long logo_colors[2]; + Region logo_zbars; + XPoint logo_z[4]; + XRectangle logo_bars[5]; #endif #ifdef HAVE_LIBPTHREAD @@ -150,19 +159,22 @@ extern int _zbar_window_probe_ximage(zbar_window_t*); extern int _zbar_window_probe_xshm(zbar_window_t*); extern int _zbar_window_probe_xv(zbar_window_t*); -extern int _zbar_window_attach(zbar_window_t*, void*, unsigned long); +extern int _zbar_window_attach(zbar_window_t*, + void*, + unsigned long); +extern int _zbar_window_resize(zbar_window_t *w); extern int _zbar_window_clear(zbar_window_t*); extern int _zbar_window_draw_marker(zbar_window_t*, uint32_t, - const point_t*); + const point_t*); #if 0 extern int _zbar_window_draw_line(zbar_window_t*, uint32_t, - const point_t*, const point_t*); + const point_t*, const point_t*); extern int _zbar_window_draw_outline(zbar_window_t*, uint32_t, - const symbol_t*); + const symbol_t*); extern int _zbar_window_draw_text(zbar_window_t*, uint32_t, - const point_t*, const char*); + const point_t*, const char*); #endif #endif diff --git a/zbar/window/null.c b/zbar/window/null.c index 20182c1..0ceab3c 100644 --- a/zbar/window/null.c +++ b/zbar/window/null.c @@ -30,6 +30,11 @@ static inline int null_error (void *m, "not compiled with output window support")); } +int _zbar_window_resize (zbar_window_t *w) +{ + return(0); +} + int _zbar_window_attach (zbar_window_t *w, void *display, unsigned long win) @@ -56,9 +61,9 @@ int _zbar_window_close (zbar_processor_t *proc) return(null_error(proc, __func__)); } -int _zbar_window_resize (zbar_processor_t *proc, - unsigned width, - unsigned height) +int _zbar_window_set_size (zbar_processor_t *proc, + unsigned width, + unsigned height) { return(null_error(proc, __func__)); } @@ -85,3 +90,8 @@ int _zbar_window_draw_marker(zbar_window_t *w, { return(null_error(w, __func__)); } + +int _zbar_window_draw_logo (zbar_window_t *w) +{ + return(null_error(w, __func__)); +} diff --git a/zbar/window/x.c b/zbar/window/x.c index 9c140d4..49cdcac 100644 --- a/zbar/window/x.c +++ b/zbar/window/x.c @@ -25,19 +25,34 @@ #include "processor.h" #include +static inline unsigned long window_alloc_color (zbar_window_t *w, + Colormap cmap, + unsigned short r, + unsigned short g, + unsigned short b) +{ + XColor color; + color.red = r; + color.green = g; + color.blue = b; + color.flags = 0; + XAllocColor(w->display, cmap, &color); + return(color.pixel); +} + static inline int window_alloc_colors (zbar_window_t *w) { Colormap cmap = DefaultColormap(w->display, DefaultScreen(w->display)); - XColor color; int i; - for(i = 0; i < 8; i++) { - color.red = (i & 4) ? (0xcc * 0x101) : 0; - color.green = (i & 2) ? (0xcc * 0x101) : 0; - color.blue = (i & 1) ? (0xcc * 0x101) : 0; - color.flags = 0; - XAllocColor(w->display, cmap, &color); - w->colors[i] = color.pixel; - } + for(i = 0; i < 8; i++) + w->colors[i] = + window_alloc_color(w, cmap, + (i & 4) ? (0xcc * 0x101) : 0, + (i & 2) ? (0xcc * 0x101) : 0, + (i & 1) ? (0xcc * 0x101) : 0); + + w->logo_colors[0] = window_alloc_color(w, cmap, 0xd709, 0x3333, 0x3333); + w->logo_colors[1] = window_alloc_color(w, cmap, 0xa3d6, 0x0000, 0x0000); return(0); } @@ -60,6 +75,48 @@ static inline int window_hide_cursor (zbar_window_t *w) return(0); } +int _zbar_window_resize (zbar_window_t *w) +{ + int lbw; + if(w->height * 8 / 10 <= w->width) + lbw = w->height / 36; + else + lbw = w->width * 5 / 144; + if(lbw < 1) + lbw = 1; + w->logo_scale = lbw; + if(w->logo_zbars) + XDestroyRegion(w->logo_zbars); + w->logo_zbars = XCreateRegion(); + + int x0 = w->width / 2; + int y0 = w->height / 2; + int by0 = y0 - 54 * lbw / 5; + int bh = 108 * lbw / 5; + + static const int bx[5] = { -6, -3, -1, 2, 5 }; + static const int bw[5] = { 1, 1, 2, 2, 1 }; + + int i; + for(i = 0; i < 5; i++) { + XRectangle *bar = &w->logo_bars[i]; + bar->x = x0 + lbw * bx[i]; + bar->y = by0; + bar->width = lbw * bw[i]; + bar->height = bh; + XUnionRectWithRegion(bar, w->logo_zbars, w->logo_zbars); + } + + static const int zx[4] = { -7, 7, -7, 7 }; + static const int zy[4] = { -8, -8, 8, 8 }; + + for(i = 0; i < 4; i++) { + w->logo_z[i].x = x0 + lbw * zx[i]; + w->logo_z[i].y = y0 + lbw * zy[i]; + } + return(0); +} + int _zbar_window_attach (zbar_window_t *w, void *display, unsigned long win) @@ -68,6 +125,11 @@ int _zbar_window_attach (zbar_window_t *w, /* cleanup existing resources */ if(w->gc) XFreeGC(w->display, w->gc); + assert(!w->exposed); + if(w->logo_zbars) { + XDestroyRegion(w->logo_zbars); + w->logo_zbars = NULL; + } w->display = NULL; } w->xwin = 0; @@ -83,6 +145,7 @@ int _zbar_window_attach (zbar_window_t *w, XGetWindowAttributes(w->display, w->xwin, &attr); w->width = attr.width; w->height = attr.height; + _zbar_window_resize(w); window_alloc_colors(w); window_hide_cursor(w); @@ -103,17 +166,37 @@ static int x_handle_event (zbar_processor_t *proc) XNextEvent(proc->display, &ev); switch(ev.type) { - case Expose: - /* FIXME ignore when running */ - if(!ev.xexpose.count) - zbar_window_redraw(proc->window); + case Expose: { + /* FIXME ignore when running(?) */ + XExposeEvent *exp = (XExposeEvent*)&ev; + XRectangle r; + Region exposed = XCreateRegion(); + while(1) { + assert(ev.type == Expose); + r.x = exp->x; + r.y = exp->y; + r.width = exp->width; + r.height = exp->height; + XUnionRectWithRegion(&r, exposed, exposed); + + if(!exp->count) + break; + XNextEvent(proc->display, &ev); + } + + proc->window->exposed = exposed; + zbar_window_redraw(proc->window); + proc->window->exposed = 0; + + XDestroyRegion(exposed); break; + } case ConfigureNotify: zprintf(3, "resized to %d x %d\n", ev.xconfigure.width, ev.xconfigure.height); zbar_window_resize(proc->window, - ev.xconfigure.width, ev.xconfigure.height); + ev.xconfigure.width, ev.xconfigure.height); break; case ClientMessage: @@ -266,9 +349,9 @@ int _zbar_window_close (zbar_processor_t *proc) return(0); } -int _zbar_window_resize (zbar_processor_t *proc, - unsigned width, - unsigned height) +int _zbar_window_set_size (zbar_processor_t *proc, + unsigned width, + unsigned height) { if(proc->display) { XResizeWindow(proc->display, proc->xwin, width, height); @@ -332,3 +415,44 @@ int _zbar_window_draw_marker(zbar_window_t *w, XDrawLine(w->display, w->xwin, w->gc, x - 3, y, x + 3, y); return(0); } + +int _zbar_window_draw_logo (zbar_window_t *w) +{ + if(w->exposed) + XSetRegion(w->display, w->gc, w->exposed); + + int screen = DefaultScreen(w->display); + + /* clear to white */ + XSetForeground(w->display, w->gc, WhitePixel(w->display, screen)); + XFillRectangle(w->display, w->xwin, w->gc, 0, 0, w->width, w->height); + + if(!w->logo_scale || !w->logo_zbars) + return(0); + + XSetForeground(w->display, w->gc, BlackPixel(w->display, screen)); + XFillRectangles(w->display, w->xwin, w->gc, w->logo_bars, 5); + + XSetLineAttributes(w->display, w->gc, 2 * w->logo_scale, + LineSolid, CapRound, JoinRound); + + XSetForeground(w->display, w->gc, w->logo_colors[0]); + XDrawLines(w->display, w->xwin, w->gc, w->logo_z, 4, CoordModeOrigin); + + if(w->exposed) { + XIntersectRegion(w->logo_zbars, w->exposed, w->exposed); + XSetRegion(w->display, w->gc, w->exposed); + } + else + XSetRegion(w->display, w->gc, w->logo_zbars); + + XSetForeground(w->display, w->gc, w->logo_colors[1]); + XDrawLines(w->display, w->xwin, w->gc, w->logo_z, 4, CoordModeOrigin); + XFlush(w->display); + + /* reset GC */ + XSetLineAttributes(w->display, w->gc, 0, + LineSolid, CapButt, JoinMiter); + XSetClipMask(w->display, w->gc, None); + return(0); +} diff --git a/zbarcam/zbarcam.c b/zbarcam/zbarcam.c index 898d25d..46522df 100644 --- a/zbarcam/zbarcam.c +++ b/zbarcam/zbarcam.c @@ -232,7 +232,8 @@ int main (int argc, const char *argv[]) } /* start video */ - if(zbar_processor_set_active(proc, 1)) + int active = 1; + if(zbar_processor_set_active(proc, active)) return(zbar_processor_error_spew(proc, 0)); /* let the callback handle data */ @@ -240,6 +241,11 @@ int main (int argc, const char *argv[]) while((rc = zbar_processor_user_wait(proc, -1)) >= 0) { if(rc == 'q') break; + if(rc == ' ') { + active = !active; + if(zbar_processor_set_active(proc, active)) + return(zbar_processor_error_spew(proc, 0)); + } } /* report any errors that aren't "window closed" */ From 8651a17ddaa0928896dde26d7cba83e6ec714259 Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 21 Apr 2009 14:45:52 +0000 Subject: [PATCH 085/328] * release updates (version, NEWS, packaging) * adjust [py]gtk distributed files --- ChangeLog | 2 ++ Makefile.am | 8 ++++++-- NEWS | 7 +++++++ configure.ac | 4 ++-- gtk/Makefile.am.inc | 5 +++-- pygtk/Makefile.am.inc | 6 ++++-- zbar.spec.in | 18 +++++++++--------- 7 files changed, 33 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index c674304..d650e0f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ version 0.7: + * release updates (version, NEWS, packaging) + * adjust [py]gtk distributed files * draw new logo (rough, no Xrender yet) * fix Makefile.am syntax error * fixup some perl distribution details diff --git a/Makefile.am b/Makefile.am index 6c57307..dfeea13 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ AM_CPPFLAGS = -I$(srcdir)/include -AM_CFLAGS = -Wall -Werror +AM_CFLAGS = -Wall AM_CXXFLAGS = $(AM_CFLAGS) ACLOCAL_AMFLAGS = -I config bin_PROGRAMS = @@ -44,8 +44,12 @@ endif include $(srcdir)/test/Makefile.am.inc include $(srcdir)/doc/Makefile.am.inc +EXTRA_DIST += zbar.spec.in zbar.spec + EXTRA_DIST += examples/upcrpc.pl examples/upcrpc.py examples/paginate.pl \ - zbar.spec.in zbar.spec + examples/barcode.png examples/processor.pl examples/processor.py \ + examples/scan_image.c examples/scan_image.cpp examples/scan_image.pl \ + examples/scan_image.py EXTRA_DIST += perl/MANIFEST perl/README perl/Changes perl/COPYING.LIB \ perl/Makefile.PL perl/typemap perl/ZBar.xs perl/ppport.h \ diff --git a/NEWS b/NEWS index 3ee6dbb..fdffb3d 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,12 @@ ZBar Barcode Reader +version 0.7 (2009-04-21): + Welcome to ZBar! In addition to finalizing the project name change, + this release adds new bindings for Python and fixes a few bugs with + the Perl interface. The decoder also has several new features and + addresses missing checks that will improve reliability with + excessively noisy images. + version 0.6 (2009-02-28): This release fixes many bugs and adds several improvements suggested by users: support for decoding UPC-E is finished. zebraimg is diff --git a/configure.ac b/configure.ac index 55fdff2..be4e81c 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ([2.61]) -AC_INIT([zbar], [0.6], [spadix@users.sourceforge.net]) +AC_INIT([zbar], [0.7], [spadix@users.sourceforge.net]) AC_CONFIG_AUX_DIR(config) AC_CONFIG_MACRO_DIR(config) AM_INIT_AUTOMAKE([1.10 -Wall -Werror foreign subdir-objects std-options dist-bzip2]) @@ -21,7 +21,7 @@ dnl then increment age. dnl - If any interfaces have been removed since the last public release, dnl then set age to 0. AC_SUBST([LIB_VERSION], [0:0:0]) -AC_SUBST([RELDATE], [2009-02-28]) +AC_SUBST([RELDATE], [2009-04-21]) dnl widget libraries use their own versioning. dnl NB pygtk wrapper is *unversioned* diff --git a/gtk/Makefile.am.inc b/gtk/Makefile.am.inc index cf5132d..406fd86 100644 --- a/gtk/Makefile.am.inc +++ b/gtk/Makefile.am.inc @@ -4,9 +4,10 @@ gtk_libzbargtk_la_LDFLAGS = -version-info $(ZGTK_LIB_VERSION) \ -export-symbols-regex "^zbar_gtk_.*" $(AM_LDFLAGS) gtk_libzbargtk_la_LIBADD = $(GTK_LIBS) zbar/libzbar.la $(AM_LIBADD) -gtk_libzbargtk_la_SOURCES = gtk/zbargtk.c gtk/zbargtkprivate.h \ - gtk/zbarmarshal.c gtk/zbarmarshal.h +dist_gtk_libzbargtk_la_SOURCES = gtk/zbargtk.c gtk/zbargtkprivate.h +nodist_gtk_libzbargtk_la_SOURCES = gtk/zbarmarshal.c gtk/zbarmarshal.h BUILT_SOURCES += gtk/zbarmarshal.c gtk/zbarmarshal.h +CLEANFILES += gtk/zbarmarshal.c gtk/zbarmarshal.h EXTRA_DIST += gtk/zbarmarshal.list %.h: %.list diff --git a/pygtk/Makefile.am.inc b/pygtk/Makefile.am.inc index fba1adc..433412c 100644 --- a/pygtk/Makefile.am.inc +++ b/pygtk/Makefile.am.inc @@ -6,9 +6,11 @@ pygtk_zbarpygtk_la_LDFLAGS = -shared -module -avoid-version -export-dynamic \ pygtk_zbarpygtk_la_LIBADD = \ $(PYTHON_LIBS) $(PYGTK_LIBS) gtk/libzbargtk.la $(AM_LIBADD) -pygtk_zbarpygtk_la_SOURCES = pygtk/zbarpygtkmodule.c pygtk/zbarpygtk.c +dist_pygtk_zbarpygtk_la_SOURCES = pygtk/zbarpygtkmodule.c +nodist_pygtk_zbarpygtk_la_SOURCES = pygtk/zbarpygtk.c BUILT_SOURCES += pygtk/zbarpygtk.c pygtk/zbarpygtk.defs -EXTRA_DIST += pygtk/zbarpygtk.override pygtk/zbarpygtk.c pygtk/zbarpygtk.defs +CLEANFILES += pygtk/zbarpygtk.c pygtk/zbarpygtk.defs +EXTRA_DIST += pygtk/zbarpygtk.override # FIXME ugly hack to fixup new name... now non-standard? pygtk/zbarpygtk.defs: include/zbar/zbargtk.h diff --git a/zbar.spec.in b/zbar.spec.in index 89931cd..071c751 100644 --- a/zbar.spec.in +++ b/zbar.spec.in @@ -13,7 +13,7 @@ Prefix: %{_prefix} BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root %description -The ZBar Barcode Reader is a library for scanning and decoding bar +The ZBar Bar Code Reader is a library for scanning and decoding bar codes from various sources such as video streams, image files or raw intensity sensors. It supports EAN, UPC, Code 128, Code 39 and Interleaved 2 of 5. The flexible, layered architecture features a @@ -25,7 +25,7 @@ Summary: bar code library extra development files Requires: %{name} = %{version} %description devel -The ZBar Barcode Reader is a library for scanning and decoding bar +The ZBar Bar Code Reader is a library for scanning and decoding bar codes from various sources such as video streams, image files or raw intensity sensors. It supports EAN, UPC, Code 128, Code 39 and Interleaved 2 of 5. The flexible, layered architecture features a @@ -40,7 +40,7 @@ Summary: bar code reader GTK widget Requires: %{name} = %{version}, gtk2 %description gtk -The ZBar Barcode Reader is a library for scanning and decoding bar +The ZBar Bar Code Reader is a library for scanning and decoding bar codes from various sources such as video streams, image files or raw intensity sensors. It supports EAN, UPC, Code 128, Code 39 and Interleaved 2 of 5. The flexible, layered architecture features a @@ -55,7 +55,7 @@ Summary: bar code reader GTK widget extra development files Requires: %{name}-gtk = %{version}, %{name}-devel = %{version}, gtk2-devel %description gtk-devel -The ZBar Barcode Reader is a library for scanning and decoding bar +The ZBar Bar Code Reader is a library for scanning and decoding bar codes from various sources such as video streams, image files or raw intensity sensors. It supports EAN, UPC, Code 128, Code 39 and Interleaved 2 of 5. The flexible, layered architecture features a @@ -71,7 +71,7 @@ Summary: bar code reader PyGTK widget Requires: %{name} = %{version}, pygtk2 %description pygtk -The ZBar Barcode Reader is a library for scanning and decoding bar +The ZBar Bar Code Reader is a library for scanning and decoding bar codes from various sources such as video streams, image files or raw intensity sensors. It supports EAN, UPC, Code 128, Code 39 and Interleaved 2 of 5. The flexible, layered architecture features a @@ -86,7 +86,7 @@ Summary: bar code reader Qt widget Requires: %{name} = %{version}, qt >= 4 %description qt -The ZBar Barcode Reader is a library for scanning and decoding bar +The ZBar Bar Code Reader is a library for scanning and decoding bar codes from various sources such as video streams, image files or raw intensity sensors. It supports EAN, UPC, Code 128, Code 39 and Interleaved 2 of 5. The flexible, layered architecture features a @@ -101,7 +101,7 @@ Summary: bar code reader Qt widget extra development files Requires: %{name}-qt = %{version}, %{name}-devel = %{version}, qt-devel >= 4 %description qt-devel -The ZBar Barcode Reader is a library for scanning and decoding bar +The ZBar Bar Code Reader is a library for scanning and decoding bar codes from various sources such as video streams, image files or raw intensity sensors. It supports EAN, UPC, Code 128, Code 39 and Interleaved 2 of 5. The flexible, layered architecture features a @@ -194,8 +194,8 @@ ldconfig %{_includedir}/zbar/QZBar*.h %changelog -* Thu Apr 16 2009 spadix -- project name change +* Thu Apr 21 2009 spadix +- version 0.7 project name change * Thu Jul 24 2008 spadix - version 0.5 updates (new widget packages) From 4018ef28ec48a5d0cf2046810edbb9822b0ad682 Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 21 Apr 2009 16:02:59 +0000 Subject: [PATCH 086/328] * fix perl MANIFEST --- ChangeLog | 1 + perl/MANIFEST | 1 + 2 files changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index d650e0f..3f23b51 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ version 0.7: + * fix perl MANIFEST * release updates (version, NEWS, packaging) * adjust [py]gtk distributed files * draw new logo (rough, no Xrender yet) diff --git a/perl/MANIFEST b/perl/MANIFEST index 77ed362..8d98fa5 100644 --- a/perl/MANIFEST +++ b/perl/MANIFEST @@ -19,3 +19,4 @@ t/Scanner.t t/ZBar.t t/pod.t t/pod-coverage.t +inc/Devel/CheckLib.pm From 1a64e1538e37c291cfc1627a90526d82623c9898 Mon Sep 17 00:00:00 2001 From: convert-repo Date: Fri, 29 May 2009 03:20:38 +0000 Subject: [PATCH 087/328] update tags From f263f33dc234c80798a236361d1a34edf14f37b1 Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 29 May 2009 13:00:14 -0400 Subject: [PATCH 088/328] initial Windows support for window interface - currently supports VFW DrawDib interface for image display (DirectDraw and others TBD) - also basic processor window creation/manipulation - Windows configure tests --- .hgignore | 21 +++ ChangeLog | 7 + Makefile.am | 2 +- configure.ac | 16 ++ include/zbar.h | 1 + test/Makefile.am.inc | 9 ++ test/test_window.c | 14 +- zbar/Makefile.am.inc | 23 ++- zbar/error.c | 19 +++ zbar/processor.c | 6 +- zbar/processor.h | 22 ++- zbar/window.c | 11 +- zbar/window.h | 32 +++- zbar/window/vfw.c | 150 ++++++++++++++++++ zbar/window/win.c | 363 +++++++++++++++++++++++++++++++++++++++++++ zbar/window/x.c | 4 + 16 files changed, 661 insertions(+), 39 deletions(-) create mode 100644 .hgignore create mode 100644 zbar/window/vfw.c create mode 100644 zbar/window/win.c diff --git a/.hgignore b/.hgignore new file mode 100644 index 0000000..b00bc3c --- /dev/null +++ b/.hgignore @@ -0,0 +1,21 @@ +syntax: glob + +*~ +Makefile +Makefile.in +aclocal.m4 +configure +config +config.guess +config.h +config.h.in +config.log +config.status +config.sub +depcomp +compile +install-sh +libtool +ltmain.sh +autom4te.cache +missing diff --git a/ChangeLog b/ChangeLog index 3f23b51..2d63075 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +current: + * initial Windows support for window interface + - currently supports VFW DrawDib interface for image display + (DirectDraw and others TBD) + - also basic processor window creation/manipulation + - Windows configure tests + version 0.7: * fix perl MANIFEST * release updates (version, NEWS, packaging) diff --git a/Makefile.am b/Makefile.am index dfeea13..6b0ee0a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ AM_CPPFLAGS = -I$(srcdir)/include -AM_CFLAGS = -Wall +AM_CFLAGS = -Wall -Werror AM_CXXFLAGS = $(AM_CFLAGS) ACLOCAL_AMFLAGS = -I config bin_PROGRAMS = diff --git a/configure.ac b/configure.ac index be4e81c..9cd56a9 100644 --- a/configure.ac +++ b/configure.ac @@ -35,6 +35,21 @@ AC_DEFINE_UNQUOTED([ZBAR_VERSION_MINOR], [[`echo "$PACKAGE_VERSION" | sed -e 's/^[^.]*\.\([^.]*\)$/\1/'`]], [Program minor version (after '.') as a number]) +dnl windows build + +AC_CANONICAL_HOST +case $host_os in + *cygwin* | *mingw* | *uwin* | *djgpp* | *ems* ) + win32="yes" + AC_DEFINE([_WIN32_WINNT], [0x0500], [Minimum Windows API version]) + ;; + * ) + win32="no" + ;; +esac + +AM_CONDITIONAL([WIN32], [test "x$win32" = "xyes"]) + dnl programs AC_PROG_CC @@ -83,6 +98,7 @@ AC_SEARCH_LIBS([clock_gettime], [rt]) dnl poll support dnl without poll() we exclude processor layer +dnl FIXME superceded by WIN32 checks(?) have_poll="no" AC_CHECK_HEADERS([poll.h], [have_poll="yes"]) diff --git a/include/zbar.h b/include/zbar.h index 7bb9572..122c98f 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -115,6 +115,7 @@ typedef enum zbar_error_e { ZBAR_ERR_XDISPLAY, /**< X11 display error */ ZBAR_ERR_XPROTO, /**< X11 protocol error */ ZBAR_ERR_CLOSED, /**< output window is closed */ + ZBAR_ERR_WINAPI, /**< windows system error */ ZBAR_ERR_NUM /**< number of error codes */ } zbar_error_t; diff --git a/test/Makefile.am.inc b/test/Makefile.am.inc index 64d0b3f..106a13a 100644 --- a/test/Makefile.am.inc +++ b/test/Makefile.am.inc @@ -9,6 +9,15 @@ check_PROGRAMS += test/test_convert test_test_convert_SOURCES = test/test_convert.c $(TEST_IMAGE_SOURCES) test_test_convert_LDADD = zbar/libzbar.la $(AM_LDADD) +#check_PROGRAMS += test/test_window +#test_test_window_SOURCES = test/test_window.c $(TEST_IMAGE_SOURCES) +#test_test_window_CPPFLAGS = -I$(srcdir)/zbar $(AM_CPPFLAGS) +#test_test_window_LDADD = zbar/libzbar.la $(AM_LDADD) + +#check_PROGRAMS += test/test_video +#test_test_convert_SOURCES = test/test_video.c $(TEST_IMAGE_SOURCES) +#test_test_convert_LDADD = zbar/libzbar.la $(AM_LDADD) + if HAVE_POLL check_PROGRAMS += test/test_proc test_test_proc_SOURCES = test/test_proc.c $(TEST_IMAGE_SOURCES) diff --git a/test/test_window.c b/test/test_window.c index 9beebe1..1a17346 100644 --- a/test/test_window.c +++ b/test/test_window.c @@ -35,14 +35,13 @@ #include "processor.h" #include "test_images.h" -extern int _zbar_draw_logo(zbar_image_t *img); - zbar_processor_t proc; static void input_wait () { fprintf(stderr, "waiting for input...\n"); - _zbar_window_handle_events(&proc, 1); + if(_zbar_window_handle_events(&proc, 1) < 0) + zbar_processor_error_spew(&proc, 1); } int main (int argc, char *argv[]) @@ -56,8 +55,8 @@ int main (int argc, char *argv[]) return(1); } - int width = 640 * .25; - int height = 480 * .25; + int width = 640; + int height = 480; if(_zbar_window_open(&proc, "zbar window test", width, height) || zbar_window_attach(proc.window, proc.display, proc.xwin) || @@ -69,15 +68,14 @@ int main (int argc, char *argv[]) zbar_image_t *img = zbar_image_create(); zbar_image_set_size(img, width, height); - /*zbar_image_set_format(img, fourcc('Y','8','0','0'));*/ + zbar_image_set_format(img, fourcc('B','G','R','4')); /*fourcc('I','4','2','0')*/ /*fourcc('Y','V','1','2')*/ /*fourcc('U','Y','V','Y')*/ /*fourcc('Y','U','Y','V')*/ /*fourcc('R','G','B','3')*/ /*fourcc('Y','8','0','0')*/ - /*test_image_bars(img);*/ - _zbar_draw_logo(img); + test_image_bars(img); if(zbar_window_draw(proc.window, img) || zbar_window_redraw(proc.window)) { diff --git a/zbar/Makefile.am.inc b/zbar/Makefile.am.inc index 0f142b3..5a3e7d6 100644 --- a/zbar/Makefile.am.inc +++ b/zbar/Makefile.am.inc @@ -6,15 +6,11 @@ zbar_libzbar_la_LIBADD = zbar_libzbar_la_SOURCES = zbar/debug.h zbar/config.c \ zbar/error.h zbar/error.c zbar/symbol.h zbar/symbol.c \ - zbar/image.h zbar/image.c zbar/convert.c zbar/logo.c \ - zbar/window.h zbar/window.c zbar/video.h zbar/video.c \ + zbar/image.h zbar/image.c zbar/convert.c \ + zbar/window.h zbar/window.c zbar/video.h zbar/video.c zbar/processor.h \ zbar/img_scanner.c zbar/scanner.c \ zbar/decoder.h zbar/decoder.c -if HAVE_POLL -zbar_libzbar_la_SOURCES += zbar/processor.h zbar/processor.c -endif - if ENABLE_EAN zbar_libzbar_la_SOURCES += zbar/decoder/ean.h zbar/decoder/ean.c endif @@ -32,6 +28,16 @@ zbar_libzbar_la_SOURCES += zbar/decoder/pdf417.h zbar/decoder/pdf417.c \ zbar/decoder/pdf417_hash.h endif +if HAVE_POLL +zbar_libzbar_la_SOURCES += zbar/processor.c +# FIXME +# zbar/processor/posix.c +endif +if WIN32 +# FIXME +#zbar_libzbar_la_SOURCES += zbar/processor/win32.c +endif + if HAVE_V4L1 zbar_libzbar_la_SOURCES += zbar/video/v4l1.c if HAVE_V4L2 @@ -55,8 +61,13 @@ zbar_libzbar_la_SOURCES += zbar/window/xv.c zbar_libzbar_la_LIBADD += $(XV_LIBS) endif else +if WIN32 +zbar_libzbar_la_SOURCES += zbar/window/win.c zbar/window/vfw.c +zbar_libzbar_la_LIBADD += -lgdi32 -lvfw32 +else zbar_libzbar_la_SOURCES += zbar/window/null.c endif +endif zbar_libzbar_la_LDFLAGS += $(AM_LDFLAGS) zbar_libzbar_la_LIBADD += $(AM_LIBADD) diff --git a/zbar/error.c b/zbar/error.c index 2fb3848..a8958c0 100644 --- a/zbar/error.c +++ b/zbar/error.c @@ -24,6 +24,10 @@ #include "error.h" #include +#ifdef _WIN32 +# include +#endif + int _zbar_verbosity = 0; static const char * const sev_str[] = { @@ -155,6 +159,21 @@ const char *_zbar_error_string (const void *container, err->buf = realloc(err->buf, len + strlen(sysfmt) + strlen(syserr)); len += sprintf(err->buf + len, sysfmt, syserr, err->errnum); } +#ifdef _WIN32 + else if(err->type == ZBAR_ERR_WINAPI) { + char *syserr = NULL; + if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err->errnum, 0, (LPTSTR)&syserr, 1, NULL) && + syserr) { + char sysfmt[] = ": %s (%d)\n"; + err->buf = realloc(err->buf, len + strlen(sysfmt) + strlen(syserr)); + len += sprintf(err->buf + len, sysfmt, syserr, err->errnum); + LocalFree(syserr); + } + } +#endif else { err->buf = realloc(err->buf, len + 2); len += sprintf(err->buf + len, "\n"); diff --git a/zbar/processor.c b/zbar/processor.c index 9b7812b..b99b681 100644 --- a/zbar/processor.c +++ b/zbar/processor.c @@ -139,11 +139,7 @@ static inline int process_image (zbar_processor_t *proc, (zbar_window_draw(proc->window, img) || _zbar_window_invalidate(proc->window))) return(err_copy(proc, proc->window)); -#if 0 - /* FIXME still don't understand why we need this */ - if(proc->window && _zbar_window_handle_events(proc, 0)) - return(-1); -#endif + if(proc->force_output && img) zbar_image_destroy(img); return(0); diff --git a/zbar/processor.h b/zbar/processor.h index 941e204..6f3fa03 100644 --- a/zbar/processor.h +++ b/zbar/processor.h @@ -30,7 +30,9 @@ #include #include #include -#include +#ifdef HAVE_POLL_H +# include +#endif #ifdef HAVE_X # include @@ -40,9 +42,14 @@ # include #endif +#ifdef _WIN32 +# include +#endif + #include #include "error.h" +#ifdef HAVE_POLL_H typedef int (poll_handler_t)(zbar_processor_t*, int); /* poll information */ @@ -51,6 +58,7 @@ typedef struct poll_desc_s { struct pollfd *fds; /* poll descriptors */ poll_handler_t **handlers; /* poll handlers */ } poll_desc_t; +#endif struct zbar_processor_s { errinfo_t err; /* error reporting */ @@ -78,9 +86,11 @@ struct zbar_processor_s { int input; /* user input status */ +#ifdef HAVE_POLL_H volatile poll_desc_t polling; /* polling registration */ poll_desc_t thr_polling; /* thread copy */ int kick_fds[2]; /* poll kicker */ +#endif #ifdef HAVE_LIBPTHREAD int sem; /* window access semaphore */ @@ -97,12 +107,15 @@ struct zbar_processor_s { #ifdef HAVE_X Display *display; /* X display connection */ Window xwin; /* toplevel window */ -#else - void *display; /* generic placeholder */ - unsigned long xwin; /* unused */ +#endif + +#ifdef _WIN32 + HWND display; /* window handle */ + long xwin; /* unused */ #endif }; +#ifdef HAVE_POLL_H static inline int alloc_polls (volatile poll_desc_t *p) { p->fds = realloc(p->fds, p->num * sizeof(struct pollfd)); @@ -160,6 +173,7 @@ static inline int remove_poll (zbar_processor_t *proc, #endif return(rc); } +#endif static inline void emit (zbar_processor_t *proc, unsigned mask) diff --git a/zbar/window.c b/zbar/window.c index c087e60..af7ea88 100644 --- a/zbar/window.c +++ b/zbar/window.c @@ -90,17 +90,14 @@ inline int zbar_window_redraw (zbar_window_t *w) { if(window_lock(w)) return(-1); - if(!w->draw_image) { - (void)window_unlock(w); - return(_zbar_window_clear(w)); - } int rc = 0; - if(w->image) + if(w->draw_image && w->image) { rc = w->draw_image(w, w->image); + if(!rc) + rc = window_draw_overlay(w); + } else _zbar_window_draw_logo(w); - if(!rc) - rc = window_draw_overlay(w); (void)window_unlock(w); return(rc); } diff --git a/zbar/window.h b/zbar/window.h index fc563bd..4082120 100644 --- a/zbar/window.h +++ b/zbar/window.h @@ -44,6 +44,10 @@ # include #endif +#ifdef _WIN32 +# include +#endif + #include #include "image.h" #include "error.h" @@ -59,6 +63,9 @@ struct zbar_window_s { unsigned width, height; /* current output size */ unsigned max_width, max_height; + uint32_t src_format; /* current input format */ + unsigned dst_width; /* conversion target */ + uint32_t *formats; /* supported formats (zero terminated) */ /* interface dependent methods */ @@ -75,11 +82,10 @@ struct zbar_window_s { XvImage *xv; #endif } img; - uint32_t src_format; /* current input format */ + XID img_port; /* current format port */ + unsigned src_width; /* last displayed image size */ unsigned src_height; - unsigned dst_width; /* conversion target */ - XID img_port; /* current format port */ XID *xv_ports; /* best port for format */ int num_xv_adaptors; /* number of adaptors */ @@ -104,6 +110,20 @@ struct zbar_window_s { #ifdef HAVE_LIBPTHREAD pthread_mutex_t imglock; /* lock displayed image */ #endif + +#ifdef _WIN32 + HWND hwnd; + void* hdd; + + BITMAPINFOHEADER bih; + unsigned dst_height; + + /* pre-calculated logo geometries */ + int logo_scale; + HRGN logo_zbars; + HPEN logo_zpen, logo_zbpen; + POINT logo_z[4]; +#endif }; @@ -142,7 +162,7 @@ static inline int window_unlock (zbar_window_t *w) #endif static inline int _zbar_window_add_format (zbar_window_t *w, - uint32_t fmt) + uint32_t fmt) { int i; for(i = 0; w->formats && w->formats[i]; i++) @@ -155,10 +175,6 @@ static inline int _zbar_window_add_format (zbar_window_t *w, return(i); } -extern int _zbar_window_probe_ximage(zbar_window_t*); -extern int _zbar_window_probe_xshm(zbar_window_t*); -extern int _zbar_window_probe_xv(zbar_window_t*); - extern int _zbar_window_attach(zbar_window_t*, void*, unsigned long); diff --git a/zbar/window/vfw.c b/zbar/window/vfw.c new file mode 100644 index 0000000..0eb9b73 --- /dev/null +++ b/zbar/window/vfw.c @@ -0,0 +1,150 @@ +/*------------------------------------------------------------------------ + * Copyright 2009 (c) Jeff Brown + * + * 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 "window.h" +#include "vfw.h" + +static int +vfw_cleanup (zbar_window_t *w) +{ + if(w->hdd) { + DrawDibClose(w->hdd); + w->hdd = NULL; + } + return(0); +} + +static int +vfw_init (zbar_window_t *w, + zbar_image_t *img, + HDC hdc) +{ + if(w->src_format != img->format && + w->format != img->format) { + _zbar_best_format(img->format, &w->format, w->formats); + if(!w->format) { + err_capture_int(w, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, + "no conversion from %x to supported Xv formats", + img->format); + return(-1); + } + w->src_format = img->format; + + w->bih.biPlanes = 1; + w->bih.biXPelsPerMeter = + 1000L * GetDeviceCaps(hdc, HORZRES) / GetDeviceCaps(hdc, HORZSIZE); + w->bih.biYPelsPerMeter = + 1000L * GetDeviceCaps(hdc, VERTRES) / GetDeviceCaps(hdc, VERTSIZE); + + switch(img->format) { + case fourcc('J','P','E','G'): { + w->bih.biBitCount = 0; + w->bih.biCompression = BI_JPEG; + break; + } + case fourcc('B','G','R','3'): { + w->bih.biBitCount = 24; + w->bih.biCompression = BI_RGB; + break; + } + case fourcc('B','G','R','4'): { + w->bih.biBitCount = 32; + w->bih.biCompression = BI_RGB; + break; + } + default: + assert(0); + /* FIXME PNG? */ + } + w->bih.biSizeImage = img->datalen; + } + + w->bih.biSize = sizeof(w->bih); + w->bih.biWidth = img->width; + w->bih.biHeight = img->height; + w->dst_width = w->width; + w->dst_height = w->height; + + if(!DrawDibBegin(w->hdd, hdc, w->width, w->height, + &w->bih, img->width, img->height, 0)) + return(-1/*FIXME*/); + return(0); +} + +static int +vfw_draw (zbar_window_t *w, + zbar_image_t *img) +{ + HDC hdc = GetDC(w->hwnd); + if(!hdc) + return(-1/*FIXME*/); + + if(((img->format != w->src_format && + img->format != w->format) || + img->width != w->bih.biWidth || + img->height != w->bih.biHeight || + w->width != w->dst_width || + w->height != w->dst_height) && + vfw_init(w, img, hdc)) + return(-1); + + if(img->format != w->format) { + w->image = zbar_image_convert(img, w->format); + zbar_image_destroy(img); + img = w->image; + } + + zprintf(24, "DrawDibDraw(%dx%d -> %dx%d)\n", + img->width, img->height, w->width, w->height); + DrawDibDraw(w->hdd, hdc, + 0, 0, w->width, w->height, + &w->bih, (void*)img->data, + 0, 0, img->width, img->height, + DDF_SAME_DRAW); + ValidateRect(w->hwnd, NULL); + return(0); +} + +static uint32_t vfw_formats[] = { + fourcc('B','G','R','3'), + fourcc('B','G','R','4'), + fourcc('J','P','E','G'), + 0 +}; + +int +_zbar_window_vfw_init (zbar_window_t *w) +{ + w->hdd = DrawDibOpen(); + if(!w->hdd) + return(err_capture(w, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, + "unable to initialize DrawDib")); + + uint32_t *fmt; + for(fmt = vfw_formats; *fmt; fmt++) + _zbar_window_add_format(w, *fmt); + + w->draw_image = vfw_draw; + w->cleanup = vfw_cleanup; + return(0); +} diff --git a/zbar/window/win.c b/zbar/window/win.c new file mode 100644 index 0000000..23abac7 --- /dev/null +++ b/zbar/window/win.c @@ -0,0 +1,363 @@ +/*------------------------------------------------------------------------ + * Copyright 2007-2009 (c) Jeff Brown + * + * 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 "window.h" +#include "processor.h" + +int _zbar_window_vfw_init(zbar_window_t *w); + +static LRESULT CALLBACK +proc_handle_event (HWND hwnd, + UINT message, + WPARAM wparam, + LPARAM lparam) +{ + zbar_processor_t *proc = + (zbar_processor_t*)GetWindowLongPtr(hwnd, GWL_USERDATA); + + switch(message) { + + case WM_NCCREATE: + proc = ((LPCREATESTRUCT)lparam)->lpCreateParams; + SetWindowLongPtr(hwnd, GWL_USERDATA, (LONG_PTR)proc); + proc->display = hwnd; + break; + + case WM_SIZE: { + RECT r; + GetClientRect(hwnd, &r); + assert(proc); + zbar_window_resize(proc->window, r.right, r.bottom); + return(0); + } + + case WM_PAINT: { + PAINTSTRUCT ps; + zbar_window_redraw(proc->window); + EndPaint(hwnd, &ps); + return(0); + } + + case WM_CHAR: { + proc->input = wparam; + return(0); + } + + case WM_LBUTTONDOWN: { + proc->input = 1; + return(0); + } + + case WM_MBUTTONDOWN: { + proc->input = 2; + return(0); + } + + case WM_RBUTTONDOWN: { + proc->input = 3; + return(0); + } + + case WM_DESTROY: + zprintf(1, "DESTROY\n"); + proc->display = NULL; + _zbar_window_attach(proc->window, NULL, 0); + PostQuitMessage(0); + return(0); + } + return(DefWindowProc(hwnd, message, wparam, lparam)); +} + +static inline ATOM +proc_register_class (HINSTANCE hmod) +{ + BYTE and_mask[1] = { 0xff }; + BYTE xor_mask[1] = { 0x00 }; + + WNDCLASSEX wc = { sizeof(WNDCLASSEX), 0, }; + wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wc.hInstance = hmod; + wc.lpfnWndProc = proc_handle_event; + wc.lpszClassName = "_ZBar Class"; + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wc.hCursor = CreateCursor(hmod, 0, 0, 1, 1, and_mask, xor_mask); + + return(RegisterClassEx(&wc)); +} + +int +_zbar_window_open (zbar_processor_t *proc, + char *title, + unsigned width, + unsigned height) +{ + HMODULE hmod = NULL; + if(!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + (void*)_zbar_window_open, (HINSTANCE*)&hmod)) { + proc->err.errnum = GetLastError(); + return(err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, + "failed to obtain module handle")); + } + zprintf(1, "hmod=%p\n", hmod); + + ATOM wca = proc_register_class(hmod); + zprintf(1, "wca=%x\n", wca); + if(!wca) { + proc->err.errnum = GetLastError(); + return(err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, + "failed to register window class")); + } + + DWORD style = WS_OVERLAPPEDWINDOW; + DWORD exstyle = (WS_EX_APPWINDOW | + WS_EX_OVERLAPPEDWINDOW /*| + WS_EX_ACCEPTFILES*/); + + proc->display = CreateWindowEx(exstyle, (LPCTSTR)(long)wca, "ZBar", style, + CW_USEDEFAULT, CW_USEDEFAULT, width, height, + NULL, NULL, hmod, proc); + if(!proc->display) { + proc->err.errnum = GetLastError(); + return(err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, + "failed to open window")); + } + + return(0); +} + +int _zbar_window_close (zbar_processor_t *proc) +{ + if(proc->display) { + DestroyWindow(proc->display); + proc->display = NULL; + } + return(0); +} + +int +_zbar_window_set_visible (zbar_processor_t *proc, + int visible) +{ + zprintf(1, "\n"); + ShowWindow(proc->display, (visible) ? SW_SHOWNORMAL : SW_HIDE); + if(visible) + UpdateWindow(proc->display); + proc->visible = (visible != 0); + /* no error conditions */ + return(0); +} + +int _zbar_window_invalidate (zbar_window_t *w) +{ + if(!InvalidateRect(w->hwnd, NULL, 0)) + return(-1/*FIXME*/); + + return(0); +} + +int +_zbar_window_handle_events (zbar_processor_t *proc, + int block) +{ + MSG msg; + proc->input = 0; + while(!proc->input) { + int rc = 0; + if(proc->display) { + if(block) + rc = GetMessage(&msg, proc->display, 0, 0); + else { + rc = PeekMessage(&msg, proc->display, 0, 0, + PM_NOYIELD | PM_REMOVE); + if(!rc) + break; + } + /*zprintf(1, "rc=%d blk=%d msg=%d\n", rc, block, msg.message);*/ + if(rc < 0) { + proc->err.errnum = GetLastError(); + return(err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, + "failed to obtain event")); + } + } + + if(!rc || msg.message == WM_QUIT) { + zprintf(1, "QUIT\n"); + _zbar_window_set_visible(proc, 0); + return(err_capture(proc, SEV_WARNING, ZBAR_ERR_CLOSED, __func__, + "user closed display window")); + } + + TranslateMessage(&msg); + DispatchMessage(&msg); + } + return(proc->input); +} + +int +_zbar_window_draw_marker(zbar_window_t *w, + uint32_t rgb, + const point_t *p) +{ + return(-1); +} + +int _zbar_window_set_size (zbar_processor_t *proc, + unsigned width, + unsigned height) +{ + if(!SetWindowPos(proc->display, NULL, 0, 0, width, height, + SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOMOVE | + SWP_NOZORDER | SWP_NOREPOSITION)) + return(-1/*FIXME*/); + + return(0); +} + +int +_zbar_window_resize (zbar_window_t *w) +{ + int lbw; + if(w->height * 8 / 10 <= w->width) + lbw = w->height / 36; + else + lbw = w->width * 5 / 144; + if(lbw < 1) + lbw = 1; + w->logo_scale = lbw; + if(w->logo_zbars) { + DeleteObject(w->logo_zbars); + w->logo_zbars = NULL; + } + if(w->logo_zpen) + DeleteObject(w->logo_zpen); + if(w->logo_zbpen) + DeleteObject(w->logo_zbpen); + + LOGBRUSH lb = { 0, }; + lb.lbStyle = BS_SOLID; + lb.lbColor = RGB(0xd7, 0x33, 0x33); + w->logo_zpen = ExtCreatePen(PS_GEOMETRIC | PS_SOLID | + PS_ENDCAP_ROUND | PS_JOIN_ROUND, + lbw * 2, &lb, 0, NULL); + + lb.lbColor = RGB(0xa4, 0x00, 0x00); + w->logo_zbpen = ExtCreatePen(PS_GEOMETRIC | PS_SOLID | + PS_ENDCAP_ROUND | PS_JOIN_ROUND, + lbw * 2, &lb, 0, NULL); + + int x0 = w->width / 2; + int y0 = w->height / 2; + int by0 = y0 - 54 * lbw / 5; + int bh = 108 * lbw / 5; + + static const int bx[5] = { -6, -3, -1, 2, 5 }; + static const int bw[5] = { 1, 1, 2, 2, 1 }; + + int i; + for(i = 0; i < 5; i++) { + int x = x0 + lbw * bx[i]; + HRGN bar = CreateRectRgn(x, by0, + x + lbw * bw[i], by0 + bh); + if(w->logo_zbars) { + CombineRgn(w->logo_zbars, w->logo_zbars, bar, RGN_OR); + DeleteObject(bar); + } + else + w->logo_zbars = bar; + } + + static const int zx[4] = { -7, 7, -7, 7 }; + static const int zy[4] = { -8, -8, 8, 8 }; + + for(i = 0; i < 4; i++) { + w->logo_z[i].x = x0 + lbw * zx[i]; + w->logo_z[i].y = y0 + lbw * zy[i]; + } + return(0); +} + +int +_zbar_window_attach (zbar_window_t *w, + void *display, + unsigned long win) +{ + zprintf(1, "\n"); + if(w->hwnd) { + /* FIXME cleanup existing resources */ + w->hwnd = NULL; + } + + if(!display) + return(0); + + w->hwnd = display; + + return(_zbar_window_vfw_init(w)); +} + +int +_zbar_window_clear (zbar_window_t *w) +{ + HDC hdc = GetDC(w->hwnd); + if(!hdc) + return(-1/*FIXME*/); + + RECT r = { 0, 0, w->width, w->height }; + FillRect(hdc, &r, GetStockObject(BLACK_BRUSH)); + + ReleaseDC(w->hwnd, hdc); + ValidateRect(w->hwnd, NULL); + return(0); +} + +int +_zbar_window_draw_logo (zbar_window_t *w) +{ + HDC hdc = GetDC(w->hwnd); + if(!hdc || !SaveDC(hdc)) + return(-1/*FIXME*/); + + HRGN rgn = CreateRectRgn(0, 0, 0, 0); + GetUpdateRgn(w->hwnd, rgn, 0); + SelectClipRgn(hdc, rgn); + + SetRectRgn(rgn, 0, 0, w->width, w->height); + CombineRgn(rgn, rgn, w->logo_zbars, RGN_DIFF); + FillRgn(hdc, rgn, GetStockObject(WHITE_BRUSH)); + DeleteObject(rgn); + + FillRgn(hdc, w->logo_zbars, GetStockObject(BLACK_BRUSH)); + + SelectObject(hdc, w->logo_zpen); + Polyline(hdc, w->logo_z, 4); + + ExtSelectClipRgn(hdc, w->logo_zbars, RGN_AND); + SelectObject(hdc, w->logo_zbpen); + Polyline(hdc, w->logo_z, 4); + + RestoreDC(hdc, -1); + ReleaseDC(w->hwnd, hdc); + ValidateRect(w->hwnd, NULL); + return(0); +} diff --git a/zbar/window/x.c b/zbar/window/x.c index 49cdcac..14e91a8 100644 --- a/zbar/window/x.c +++ b/zbar/window/x.c @@ -25,6 +25,10 @@ #include "processor.h" #include +extern int _zbar_window_probe_ximage(zbar_window_t*); +extern int _zbar_window_probe_xshm(zbar_window_t*); +extern int _zbar_window_probe_xv(zbar_window_t*); + static inline unsigned long window_alloc_color (zbar_window_t *w, Colormap cmap, unsigned short r, From 76d9296d341d604d9c495f4a650244b3b21c7fc8 Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 2 Jun 2009 21:19:14 -0400 Subject: [PATCH 089/328] switchover from subversion to mercurial --- .hgignore | 21 +++++++++++++++++++++ ChangeLog | 3 +++ HACKING | 22 +++++++++++++--------- config/.keep | 0 doc/doxygen.conf.in | 2 +- 5 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 .hgignore create mode 100644 config/.keep diff --git a/.hgignore b/.hgignore new file mode 100644 index 0000000..b00bc3c --- /dev/null +++ b/.hgignore @@ -0,0 +1,21 @@ +syntax: glob + +*~ +Makefile +Makefile.in +aclocal.m4 +configure +config +config.guess +config.h +config.h.in +config.log +config.status +config.sub +depcomp +compile +install-sh +libtool +ltmain.sh +autom4te.cache +missing diff --git a/ChangeLog b/ChangeLog index 3f23b51..8b1d526 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +current: + * switchover from subversion to mercurial + version 0.7: * fix perl MANIFEST * release updates (version, NEWS, packaging) diff --git a/HACKING b/HACKING index dc5566b..d73943d 100644 --- a/HACKING +++ b/HACKING @@ -1,22 +1,26 @@ -if you're hacking at ZBar, PLEASE send patches against the latest SVN! -if you haven't already, get ZBar from SVN by running: +when hacking at ZBar, PLEASE send patches against the latest Mercurial! +if you haven't already, grab the ZBar Mercurial repository by running: - svn co https://zbar.svn.sourceforge.net/svnroot/zbar/trunk zbar + hg clone http://zbar.hg.sourceforge.net:8000/hgroot/zbar cd zbar autoreconf --install this will generate configure and all that other foo you usually get with -a release. you will need to have some basic "developer tools" installed -in order for this to work (particularly GNU autotools) +a release. you will need to have recent versions of some basic "developer +tools" installed in order for this to work, particularly GNU autotools. +these versions of autotools are known to work (newer versions should also +be fine): + GNU autoconf 2.61 + GNU automake 1.10.1 + GNU libtool 2.2.6 when you're done hacking and want to make your patch, run: - svn diff > hacked.patch + hg diff --git > hacked.patch -from the toplevel directory, and go post this file in the patches -section off the project page: +and go post this file in the patches section off the project page: - https://sourceforge.net/tracker/?group_id=189236&atid=928517 + http://sourceforge.net/tracker/?group_id=189236&atid=928517 finally, some interesting reading if you want to increase your chances of patch acceptance: diff --git a/config/.keep b/config/.keep new file mode 100644 index 0000000..e69de29 diff --git a/doc/doxygen.conf.in b/doc/doxygen.conf.in index c7a2390..0ccad3d 100644 --- a/doc/doxygen.conf.in +++ b/doc/doxygen.conf.in @@ -4,7 +4,7 @@ PROJECT_NUMBER = "version @VERSION@" INPUT = @top_srcdir@/include RECURSIVE = YES EXCLUDE = @top_srcdir@/include/zbar/zbargtk.h -EXCLUDE_PATTERNS = */.svn/* +EXCLUDE_PATTERNS = */.svn/* */.hg/* STRIP_FROM_PATH = @top_srcdir@ OUTPUT_DIRECTORY = doc/api From 894cffc8931a5102ae5b532a030232105a9ced0b Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 2 Jun 2009 21:51:48 -0400 Subject: [PATCH 090/328] fix uninitialized decoder configs (bug #2800163) --- ChangeLog | 1 + Makefile.am | 2 +- zbar/decoder.c | 5 ++--- zbar/decoder.h | 1 + 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8b1d526..739a649 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * fix uninitialized decoder configs (bug #2800163) * switchover from subversion to mercurial version 0.7: diff --git a/Makefile.am b/Makefile.am index dfeea13..6b0ee0a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ AM_CPPFLAGS = -I$(srcdir)/include -AM_CFLAGS = -Wall +AM_CFLAGS = -Wall -Werror AM_CXXFLAGS = $(AM_CFLAGS) ACLOCAL_AMFLAGS = -I config bin_PROGRAMS = diff --git a/zbar/decoder.c b/zbar/decoder.c index 663f847..8b5db3d 100644 --- a/zbar/decoder.c +++ b/zbar/decoder.c @@ -22,7 +22,7 @@ *------------------------------------------------------------------------*/ #include -#include /* malloc, free */ +#include /* malloc, calloc, free */ #include /* snprintf */ #include /* memset, strlen */ @@ -38,10 +38,9 @@ zbar_decoder_t *zbar_decoder_create () { - zbar_decoder_t *dcode = malloc(sizeof(zbar_decoder_t)); + zbar_decoder_t *dcode = calloc(1, sizeof(zbar_decoder_t)); dcode->buflen = BUFFER_MIN; dcode->buf = malloc(dcode->buflen); - dcode->handler = dcode->userdata = NULL; /* initialize default configs */ #ifdef ENABLE_EAN diff --git a/zbar/decoder.h b/zbar/decoder.h index f8ed9b5..ef2fba6 100644 --- a/zbar/decoder.h +++ b/zbar/decoder.h @@ -23,6 +23,7 @@ #ifndef _DECODER_H_ #define _DECODER_H_ +#include #include /* realloc */ #include From 2f53ec74b6ccf246fa621875041984e7a2dd7b6d Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 3 Jun 2009 15:02:33 -0400 Subject: [PATCH 091/328] fix zbar_image_free_data windows recursion loop (bug #2796277) --- ChangeLog | 1 + zbar/image.c | 11 +++++++++-- zbar/video.c | 4 +++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 739a649..5cba3c7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * fix zbar_image_free_data windows recursion loop (bug #2796277) * fix uninitialized decoder configs (bug #2800163) * switchover from subversion to mercurial diff --git a/zbar/image.c b/zbar/image.c index c1506be..0fe30a7 100644 --- a/zbar/image.c +++ b/zbar/image.c @@ -110,8 +110,15 @@ inline void zbar_image_free_data (zbar_image_t *img) img->srcidx = -1; } else if(img->cleanup && img->data) { - if(img->cleanup != zbar_image_free_data) - img->cleanup(img); + if(img->cleanup != zbar_image_free_data) { + /* using function address to detect this case is a bad idea; + * windows link libraries add an extra layer of indirection... + * this works around that problem (bug #2796277) + */ + zbar_image_cleanup_handler_t *cleanup = img->cleanup; + img->cleanup = zbar_image_free_data; + cleanup(img); + } else free((void*)img->data); } diff --git a/zbar/video.c b/zbar/video.c index 0944aae..a643afb 100644 --- a/zbar/video.c +++ b/zbar/video.c @@ -331,7 +331,6 @@ zbar_image_t *zbar_video_next_image (zbar_video_t *vdo) img->refcnt = 0; img->src = vdo; /* recycle the shadow images */ - img->cleanup = _zbar_video_recycle_shadow; img->format = vdo->format; img->width = vdo->width; @@ -339,10 +338,13 @@ zbar_image_t *zbar_video_next_image (zbar_video_t *vdo) img->datalen = vdo->datalen; img->data = malloc(vdo->datalen); } + img->cleanup = _zbar_video_recycle_shadow; img->seq = frame; memcpy((void*)img->data, tmp->data, img->datalen); _zbar_video_recycle_image(tmp); } + else + img->cleanup = _zbar_video_recycle_image; img->refcnt++; } return(img); From 525b4fcbce3ae91617e6d74d14f0070918d5ba15 Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 3 Jun 2009 16:11:04 -0400 Subject: [PATCH 092/328] fix Code 39 min length and document min/max configs (bug #2787925) --- ChangeLog | 1 + doc/ref/commonoptions.xml | 16 ++++++++++++++++ zbar/decoder.c | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 5cba3c7..128b606 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * fix Code 39 min length and document min/max configs (bug #2787925) * fix zbar_image_free_data windows recursion loop (bug #2796277) * fix uninitialized decoder configs (bug #2800163) * switchover from subversion to mercurial diff --git a/doc/ref/commonoptions.xml b/doc/ref/commonoptions.xml index 15665f2..c809d9e 100644 --- a/doc/ref/commonoptions.xml +++ b/doc/ref/commonoptions.xml @@ -109,6 +109,22 @@ except that it's not implemented either... + + + + + + Bound the number of decoded characters in a valid symbol. + 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: , , + and . + defaults to 6 for + and 1 for (per Code 39 autodiscrimination + recommendation); all others default to 0 + + diff --git a/zbar/decoder.c b/zbar/decoder.c index 8b5db3d..e35e88e 100644 --- a/zbar/decoder.c +++ b/zbar/decoder.c @@ -60,7 +60,7 @@ zbar_decoder_t *zbar_decoder_create () #endif #ifdef ENABLE_CODE39 dcode->code39.config = 1 << ZBAR_CFG_ENABLE; - CFG(dcode->code39, ZBAR_CFG_MIN_LEN) = 6; + CFG(dcode->code39, ZBAR_CFG_MIN_LEN) = 1; #endif #ifdef ENABLE_CODE128 dcode->code128.config = 1 << ZBAR_CFG_ENABLE; From b475f57fe80778ff8be41cf137462486c2e77e1f Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 3 Jun 2009 17:59:19 -0400 Subject: [PATCH 093/328] add "raw" output option (without symbology prefix) to apps (req #2671863) --- ChangeLog | 1 + doc/ref/zbarcam.xml | 14 ++++++++++++-- doc/ref/zbarimg.xml | 9 +++++++++ zbarcam/zbarcam.c | 21 ++++++++++++++------- zbarimg/zbarimg.cpp | 8 +++++++- 5 files changed, 43 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 128b606..65c1db9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * add "raw" output option (without symbology prefix) to apps (req #2671863) * fix Code 39 min length and document min/max configs (bug #2787925) * fix zbar_image_free_data windows recursion loop (bug #2796277) * fix uninitialized decoder configs (bug #2800163) diff --git a/doc/ref/zbarcam.xml b/doc/ref/zbarcam.xml index a0be014..4121a98 100644 --- a/doc/ref/zbarcam.xml +++ b/doc/ref/zbarcam.xml @@ -100,7 +100,17 @@ Stream results using an XML output format. This format wraps the raw data from the symbol with information about the scan in an easy to parse format. The latest - schema is available from . + schema is available from + + + + + + + Use raw symbol data output format. This format + prints symbol data separated by newlines without the + additional symbology type information that is printed by + default @@ -112,7 +122,7 @@ Request video input scaling from the camera driver. Possibly useful for reducing huge frames to achieve a higher frame rate. Note that the driver may adjust or completely - ignore the scaling request. + ignore the scaling request diff --git a/doc/ref/zbarimg.xml b/doc/ref/zbarimg.xml index b3e5616..520ddd6 100644 --- a/doc/ref/zbarimg.xml +++ b/doc/ref/zbarimg.xml @@ -122,6 +122,15 @@ + + + + Enable raw symbol data output. This format prints symbol + data separated by newlines without the additional symbology type + information that is printed by default + + + diff --git a/zbarcam/zbarcam.c b/zbarcam/zbarcam.c index 46522df..66c3c4e 100644 --- a/zbarcam/zbarcam.c +++ b/zbarcam/zbarcam.c @@ -43,6 +43,7 @@ static const char *note_usage = " -v, --verbose increase debug output level\n" " --verbose=N set specific debug output level\n" " --xml use XML output format\n" + " --raw output decoded symbol data without symbology prefix\n" " --nodisplay disable video display window\n" " --prescale=x\n" " request alternate video image size from driver\n" @@ -59,7 +60,9 @@ static const char *xml_foot = static zbar_processor_t *proc; static int quiet = 0; -static int xml = 0; +static enum { + DEFAULT, RAW, XML +} format = DEFAULT; static char *xml_buf = NULL; static unsigned xml_len = 0; @@ -93,13 +96,15 @@ static void data_handler (zbar_image_t *img, const void *userdata) for(; sym; sym = zbar_symbol_next(sym)) { if(zbar_symbol_get_count(sym)) continue; - if(!xml) { + if(!format) { zbar_symbol_type_t type = zbar_symbol_get_type(sym); printf("%s%s:%s\n", zbar_get_symbol_name(type), zbar_get_addon_name(type), zbar_symbol_get_data(sym)); } - else { + else if(format == RAW) + printf("%s\n", zbar_symbol_get_data(sym)); + else if(format == XML) { if(!n) printf("\n", zbar_image_get_sequence(img)); printf("%s\n", zbar_symbol_xml(sym, &xml_buf, &xml_len)); @@ -107,7 +112,7 @@ static void data_handler (zbar_image_t *img, const void *userdata) n++; } - if(xml && n) + if(format == XML && n) printf("\n"); fflush(stdout); @@ -175,7 +180,9 @@ int main (int argc, const char *argv[]) else if(!strcmp(argv[i], "--quiet")) quiet = 1; else if(!strcmp(argv[i], "--xml")) - xml = 1; + format = XML; + else if(!strcmp(argv[i], "--raw")) + format = RAW; else if(!strcmp(argv[i], "--nodisplay")) display = 0; else if(!strcmp(argv[i], "--verbose")) @@ -226,7 +233,7 @@ int main (int argc, const char *argv[]) (display && zbar_processor_set_visible(proc, 1))) return(zbar_processor_error_spew(proc, 0)); - if(xml) { + if(format == XML) { printf(xml_head, video_device); fflush(stdout); } @@ -256,7 +263,7 @@ int main (int argc, const char *argv[]) /* free resources (leak check) */ zbar_processor_destroy(proc); - if(xml) { + if(format == XML) { printf(xml_foot); fflush(stdout); } diff --git a/zbarimg/zbarimg.cpp b/zbarimg/zbarimg.cpp index 7724022..e1984e2 100644 --- a/zbarimg/zbarimg.cpp +++ b/zbarimg/zbarimg.cpp @@ -66,6 +66,7 @@ static const char *note_usage = " -d, --display enable display of following images to the screen\n" " -D, --nodisplay disable display of following images (default)\n" " --xml, --noxml enable/disable XML output format\n" + " --raw output decoded symbol data without symbology prefix\n" " -S[=], --set [=]\n" " set decoder/scanner to (or 1)\n" // FIXME overlay level @@ -125,6 +126,8 @@ static void scan_image (const std::string& filename) { if(!xmllvl) cout << *sym << endl; + else if(xmllvl < 0) + cout << sym->get_data() << endl; else { if(xmllvl < 2) { xmllvl++; @@ -233,6 +236,7 @@ int main (int argc, const char *argv[]) arg == "--set" || arg == "--xml" || arg == "--noxml" || + arg == "--raw" || arg.substr(0, 6) == "--set=") continue; else if(arg == "--") { @@ -281,11 +285,13 @@ int main (int argc, const char *argv[]) cout << xml_head << endl; } } - else if(arg == "--noxml") { + else if(arg == "--noxml" || arg == "--raw") { if(xmllvl > 0) { xmllvl--; cout << xml_foot << endl; } + if(arg == "--raw") + xmllvl = -1; } else if(arg == "--set") { if(parse_config(string(argv[++i]), "--set")) From 638875e28ab8ce97b38ce3f4c1507fe558dd4cff Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 5 Jun 2009 15:52:50 -0400 Subject: [PATCH 094/328] release updates --- ChangeLog | 3 ++- Makefile.am | 2 +- NEWS | 5 +++++ README | 14 +++++++------- configure.ac | 6 +++--- 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 65c1db9..31106ef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ -current: +version 0.8: + * release updates * add "raw" output option (without symbology prefix) to apps (req #2671863) * fix Code 39 min length and document min/max configs (bug #2787925) * fix zbar_image_free_data windows recursion loop (bug #2796277) diff --git a/Makefile.am b/Makefile.am index 6b0ee0a..dfeea13 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ AM_CPPFLAGS = -I$(srcdir)/include -AM_CFLAGS = -Wall -Werror +AM_CFLAGS = -Wall AM_CXXFLAGS = $(AM_CFLAGS) ACLOCAL_AMFLAGS = -I config bin_PROGRAMS = diff --git a/NEWS b/NEWS index fdffb3d..9a9544e 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,10 @@ ZBar Barcode Reader +version 0.8 (2009-06-05): + This is a bugfix release just to clean up a few issues found in the + last release. Existing users are encouraged to upgrade to pick up + these fixes. + version 0.7 (2009-04-21): Welcome to ZBar! In addition to finalizing the project name change, this release adds new bindings for Python and fixes a few bugs with diff --git a/README b/README index 382bd86..b2b5ee3 100644 --- a/README +++ b/README @@ -1,13 +1,13 @@ ZBAR BAR CODE READER ==================== -The ZBar Bar Code Reader is a library for scanning and decoding bar -codes from various sources such as video streams, image files or raw -intensity sensors. It supports EAN/UPC, Code 128, Code 39 and -Interleaved 2 of 5. 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. The flexible, layered architecture -features a fast, streaming interface with a minimal memory footprint. +ZBar Bar Code Reader is a library for scanning and decoding bar codes +from various sources such as video streams, image files or raw intensity +sensors. It supports EAN/UPC, Code 128, Code 39 and Interleaved 2 of 5. +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. Check the zbar home page for the latest release, mailing lists, etc. http://zbar.sourceforge.net/ diff --git a/configure.ac b/configure.ac index be4e81c..fca2946 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ([2.61]) -AC_INIT([zbar], [0.7], [spadix@users.sourceforge.net]) +AC_INIT([zbar], [0.8], [spadix@users.sourceforge.net]) AC_CONFIG_AUX_DIR(config) AC_CONFIG_MACRO_DIR(config) AM_INIT_AUTOMAKE([1.10 -Wall -Werror foreign subdir-objects std-options dist-bzip2]) @@ -20,8 +20,8 @@ dnl - If any interfaces have been added since the last public release, dnl then increment age. dnl - If any interfaces have been removed since the last public release, dnl then set age to 0. -AC_SUBST([LIB_VERSION], [0:0:0]) -AC_SUBST([RELDATE], [2009-04-21]) +AC_SUBST([LIB_VERSION], [0:1:0]) +AC_SUBST([RELDATE], [2009-06-05]) dnl widget libraries use their own versioning. dnl NB pygtk wrapper is *unversioned* From 5163e6672a338f0cbb29415461e4e5935c38fe9e Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 5 Jun 2009 16:59:07 -0400 Subject: [PATCH 095/328] Added tag 0.8 for changeset f0aa6bf0cab7 From b1fdda623447d06c43c6665a55fbd5f7be84582c Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 14 Jun 2009 15:04:28 -0400 Subject: [PATCH 096/328] * refactor processor implementation to support cross-platform - first pass windows processor (before debugging) - make processor locks reentrant (call APIs from callback) --- ChangeLog | 3 + config/.keep | 0 include/zbar/Symbol.h | 1 + test/Makefile.am.inc | 2 - test/test_proc.c | 56 ++-- zbar/Makefile.am.inc | 13 +- zbar/error.c | 1 + zbar/error.h | 2 +- zbar/img_scanner.c | 2 +- zbar/processor.c | 619 ++++++++++------------------------------- zbar/processor.h | 160 ++--------- zbar/processor/posix.c | 485 ++++++++++++++++++++++++++++++++ zbar/processor/posix.h | 136 +++++++++ zbar/processor/win.c | 608 ++++++++++++++++++++++++++++++++++++++++ zbar/processor/win.h | 107 +++++++ zbar/processor/x.c | 261 +++++++++++++++++ zbar/window.c | 2 +- zbar/window/vfw.c | 300 ++++++++++---------- zbar/window/win.c | 525 +++++++++++----------------------- zbar/window/x.c | 224 --------------- 20 files changed, 2120 insertions(+), 1387 deletions(-) create mode 100644 config/.keep create mode 100644 zbar/processor/posix.c create mode 100644 zbar/processor/posix.h create mode 100644 zbar/processor/win.c create mode 100644 zbar/processor/win.h create mode 100644 zbar/processor/x.c diff --git a/ChangeLog b/ChangeLog index 2d63075..9287370 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,7 @@ current: + * refactor processor implementation to support cross-platform + - first pass windows processor (before debugging) + - make processor locks reentrant (call APIs from callback) * initial Windows support for window interface - currently supports VFW DrawDib interface for image display (DirectDraw and others TBD) diff --git a/config/.keep b/config/.keep new file mode 100644 index 0000000..e69de29 diff --git a/include/zbar/Symbol.h b/include/zbar/Symbol.h index a04fc61..8925db0 100644 --- a/include/zbar/Symbol.h +++ b/include/zbar/Symbol.h @@ -30,6 +30,7 @@ # error "include zbar.h in your application, **not** zbar/Symbol.h" #endif +#include #include #include diff --git a/test/Makefile.am.inc b/test/Makefile.am.inc index 106a13a..261797d 100644 --- a/test/Makefile.am.inc +++ b/test/Makefile.am.inc @@ -18,7 +18,6 @@ test_test_convert_LDADD = zbar/libzbar.la $(AM_LDADD) #test_test_convert_SOURCES = test/test_video.c $(TEST_IMAGE_SOURCES) #test_test_convert_LDADD = zbar/libzbar.la $(AM_LDADD) -if HAVE_POLL check_PROGRAMS += test/test_proc test_test_proc_SOURCES = test/test_proc.c $(TEST_IMAGE_SOURCES) test_test_proc_LDADD = zbar/libzbar.la $(AM_LDADD) @@ -32,7 +31,6 @@ check_PROGRAMS += test/test_jpeg test_test_jpeg_SOURCES = test/test_jpeg.c test_test_jpeg_LDADD = zbar/libzbar.la $(AM_LDADD) endif -endif if HAVE_MAGICK check_PROGRAMS += test/dbg_scan diff --git a/test/test_proc.c b/test/test_proc.c index 225c19c..5a6ffc0 100644 --- a/test/test_proc.c +++ b/test/test_proc.c @@ -41,20 +41,18 @@ zbar_processor_t *proc = NULL; int input_wait (int timeout) { if(timeout >= 0) - printf("waiting %d.%03ds for input...", + fprintf(stderr, "waiting %d.%03ds for input...", timeout / 1000, timeout % 1000); else - printf("waiting indefinitely for input..."); + fprintf(stderr, "waiting indefinitely for input..."); fflush(stdout); int rc = zbar_processor_user_wait(proc, timeout); if(rc > 0) - printf("got input\n"); - else if(!rc || - (rc < 0 && - zbar_processor_get_error_code(proc) == ZBAR_ERR_CLOSED)) { - printf("timed out\n"); + fprintf(stderr, "got input\n"); + else if(!rc) + fprintf(stderr, "timed out\n"); + else if(zbar_processor_get_error_code(proc) == ZBAR_ERR_CLOSED) return(0); - } return(rc); } @@ -62,13 +60,13 @@ int main (int argc, char **argv) { zbar_set_verbosity(31); char *video_dev = NULL; - int i, use_threads = 0, use_window = 0; + int i, use_threads = 1, use_window = 1; for(i = 1; i < argc; i++) { if(argv[i][0] == '-') { if(!strncmp(argv[i], "-thr", 4)) - use_threads = 1; + use_threads = 0; else if(!strncmp(argv[i], "-win", 4)) - use_window = 1; + use_window = 0; else return(1); } @@ -78,52 +76,56 @@ int main (int argc, char **argv) proc = zbar_processor_create(use_threads); assert(proc); - printf("created processor (%sthreaded)\n", (!use_threads) ? "un" : ""); + fprintf(stderr, "created processor (%sthreaded)\n", + (!use_threads) ? "un" : ""); if(zbar_processor_init(proc, NULL, 0)) return(2); - printf("initialized (video=disabled, window=disabled)\n"); + fprintf(stderr, "initialized (video=disabled, window=disabled)\n"); zbar_image_t *img = zbar_image_create(); zbar_image_set_size(img, 640, 480); - zbar_image_set_format(img, fourcc('Y','V','1','2')); + zbar_image_set_format(img, fourcc('B','G','R','3')); test_image_bars(img); if(zbar_process_image(proc, img) < 0) return(3); - printf("processed test image\n"); + fprintf(stderr, "processed test image\n"); if(zbar_processor_init(proc, video_dev, use_window)) return(2); - printf("reinitialized (video=%s, window=%s)\n", - (video_dev) ? video_dev : "disabled", - (use_window) ? "enabled" : "disabled"); - - if(zbar_process_image(proc, img) < 0) - return(3); - printf("processed test image\n"); - zbar_image_destroy(img); + fprintf(stderr, "reinitialized (video=%s, window=%s)\n", + (video_dev) ? video_dev : "disabled", + (use_window) ? "enabled" : "disabled"); if(use_window) { if(zbar_processor_set_visible(proc, 1)) return(4); - printf("window visible\n"); + fprintf(stderr, "window visible\n"); } + if(input_wait((use_window && !video_dev) ? -1 : 2000) < 0) + return(5); + + if(zbar_process_image(proc, img) < 0) + return(3); + fprintf(stderr, "processed test image\n"); + zbar_image_destroy(img); + if(input_wait((use_window && !video_dev) ? -1 : 3333) < 0) return(5); if(video_dev) { if(zbar_processor_set_active(proc, 1)) return(3); - printf("video activated\n"); + fprintf(stderr, "video activated\n"); if(input_wait((use_window) ? -1 : 4000) < 0) return(5); if(zbar_processor_set_active(proc, 0)) return(3); - printf("video deactivated\n"); + fprintf(stderr, "video deactivated\n"); if(input_wait((use_window) ? -1 : 4000) < 0) return(5); @@ -133,7 +135,7 @@ int main (int argc, char **argv) if(zbar_process_image(proc, NULL)) return(3); - printf("flushed image\n"); + fprintf(stderr, "flushed image\n"); if(input_wait((use_window && !video_dev) ? -1 : 2500) < 0) return(5); diff --git a/zbar/Makefile.am.inc b/zbar/Makefile.am.inc index 5a3e7d6..ac43193 100644 --- a/zbar/Makefile.am.inc +++ b/zbar/Makefile.am.inc @@ -7,7 +7,8 @@ zbar_libzbar_la_LIBADD = zbar_libzbar_la_SOURCES = zbar/debug.h zbar/config.c \ zbar/error.h zbar/error.c zbar/symbol.h zbar/symbol.c \ zbar/image.h zbar/image.c zbar/convert.c \ - zbar/window.h zbar/window.c zbar/video.h zbar/video.c zbar/processor.h \ + zbar/processor.c zbar/processor.h \ + zbar/window.h zbar/window.c zbar/video.h zbar/video.c \ zbar/img_scanner.c zbar/scanner.c \ zbar/decoder.h zbar/decoder.c @@ -29,13 +30,10 @@ zbar_libzbar_la_SOURCES += zbar/decoder/pdf417.h zbar/decoder/pdf417.c \ endif if HAVE_POLL -zbar_libzbar_la_SOURCES += zbar/processor.c -# FIXME -# zbar/processor/posix.c +zbar_libzbar_la_SOURCES += zbar/processor/posix.h zbar/processor/posix.c endif if WIN32 -# FIXME -#zbar_libzbar_la_SOURCES += zbar/processor/win32.c +zbar_libzbar_la_SOURCES += zbar/processor/win.h zbar/processor/win.c endif if HAVE_V4L1 @@ -52,7 +50,8 @@ zbar_libzbar_la_SOURCES += zbar/jpeg.c endif if HAVE_X -zbar_libzbar_la_SOURCES += zbar/window/x.c zbar/window/ximage.c +zbar_libzbar_la_SOURCES += zbar/processor/x.c \ + zbar/window/x.c zbar/window/ximage.c zbar_libzbar_la_CPPFLAGS += $(X_CFLAGS) zbar_libzbar_la_LDFLAGS += $(X_LIBS) zbar_libzbar_la_LIBADD += $(X_PRE_LIBS) -lX11 $(X_EXTRA_LIBS) diff --git a/zbar/error.c b/zbar/error.c index a8958c0..2d3e646 100644 --- a/zbar/error.c +++ b/zbar/error.c @@ -52,6 +52,7 @@ static const char const * err_str[] = { "X11 display error", /* XDISPLAY */ "X11 protocol error", /* XPROTO */ "output window is closed", /* CLOSED */ + "windows system error", /* WINAPI */ "unknown error" /* NUM */ }; #define ERR_MAX (strlen(err_str[ZBAR_ERR_CLOSED])) diff --git a/zbar/error.h b/zbar/error.h index 4c9945f..113d3ea 100644 --- a/zbar/error.h +++ b/zbar/error.h @@ -80,7 +80,7 @@ extern int _zbar_verbosity; /* FIXME don't we need varargs hacks here? */ #define zprintf(level, format, ...) do { \ - if(_zbar_verbosity >= level) \ + if(_zbar_verbosity >= level) \ fprintf(stderr, "%s: " format, __func__ , ##__VA_ARGS__); \ } while(0) diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 0d1cdd8..1f95d6d 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -314,7 +314,7 @@ void zbar_image_scanner_enable_cache(zbar_image_scanner_t *iscn, iscn->syms = iscn->cache; iscn->cache = NULL; } - iscn->enable_cache = enable; + iscn->enable_cache = (enable) ? 1 : 0; } static inline void quiet_border (zbar_image_scanner_t *iscn, diff --git a/zbar/processor.c b/zbar/processor.c index b99b681..c9a1e44 100644 --- a/zbar/processor.c +++ b/zbar/processor.c @@ -22,72 +22,11 @@ *------------------------------------------------------------------------*/ #include "processor.h" -#include -#include -#include -#include /* gettimeofday */ #include -#include - -#ifdef HAVE_LIBPTHREAD - -static inline void proc_mutex_unlock (void *arg) -{ - pthread_mutex_unlock((pthread_mutex_t*)arg); -} - -/* acquire window access semaphore */ -static inline int proc_lock (zbar_processor_t *proc) -{ - if(!proc->threaded) - return(0); - int rc = pthread_mutex_lock(&proc->mutex); - pthread_cleanup_push(proc_mutex_unlock, &proc->mutex); - while(!rc && !proc->sem) - rc = pthread_cond_wait(&proc->cond, &proc->mutex); - if(!rc) { - proc->sem--; - proc->sem_owner = pthread_self(); - } - pthread_cleanup_pop(1); - if(rc) - err_capture(proc, SEV_ERROR, ZBAR_ERR_LOCKING, __func__, - "unable to lock processor"); - return(rc); -} - -/* release window access semaphore */ -static inline void proc_unlock (zbar_processor_t *proc) -{ - if(!proc->threaded) - return; - assert(!proc->sem); - assert(pthread_equal(proc->sem_owner, pthread_self())); - pthread_mutex_lock(&proc->mutex); - proc->sem++; - pthread_cond_signal(&proc->cond); - pthread_mutex_unlock(&proc->mutex); -} - -static inline void proc_destroy_thread (pthread_t thread, - unsigned *started) -{ - if(*started) { - pthread_cancel(thread); - pthread_join(thread, NULL); - *started = 0; - } -} - -#else -# define proc_lock(...) (0) -# define proc_unlock(...) -# define proc_destroy_thread(...) -#endif /* lock is already held */ -static inline int process_image (zbar_processor_t *proc, - zbar_image_t *img) +int _zbar_process_image (zbar_processor_t *proc, + zbar_image_t *img) { if(img) { uint32_t format = zbar_image_get_format(img); @@ -120,9 +59,9 @@ static inline int process_image (zbar_processor_t *proc, } if(nsyms) { - emit(proc, EVENT_OUTPUT); + _zbar_processor_notify(proc, EVENT_OUTPUT); if(proc->handler) - /* FIXME only call after filtering (unlocked...?) */ + /* FIXME only call after filtering */ proc->handler(img, proc->userdata); } @@ -137,7 +76,7 @@ static inline int process_image (zbar_processor_t *proc, /* display to window if enabled */ if(proc->window && (zbar_window_draw(proc->window, img) || - _zbar_window_invalidate(proc->window))) + _zbar_processor_invalidate(proc))) return(err_copy(proc, proc->window)); if(proc->force_output && img) @@ -145,251 +84,12 @@ static inline int process_image (zbar_processor_t *proc, return(0); } -/* used by poll interface. lock is already held */ -static int proc_video_handler (zbar_processor_t *proc, - int i) -{ - if(!proc->active) - return(0); - /* not expected to block */ - zbar_image_t *img = zbar_video_next_image(proc->video); - if(!img) - return(-1); - int rc = process_image(proc, img); - zbar_image_destroy(img); - return(rc); -} - -static inline int proc_poll_inputs (zbar_processor_t *proc, - poll_desc_t *p, - int timeout) -{ - assert(p->num); - int rc = poll(p->fds, p->num, timeout); - if(rc <= 0) - /* FIXME detect and handle fatal errors (somehow) */ - return(rc); - (void)proc_lock(proc); - if(p->fds[0].revents && p->fds[0].fd == proc->kick_fds[0]) { - unsigned junk[2]; - read(proc->kick_fds[0], junk, 2 * sizeof(unsigned)); - proc_unlock(proc); - return(1); - } - int i; - for(i = 0; i < p->num; i++) - if(p->fds[i].revents) { - if(p->handlers[i]) - p->handlers[i](proc, i); - p->fds[i].revents = 0; /* debug */ - rc--; - } - proc_unlock(proc); - assert(!rc); - return(0); -} - -static inline int proc_calc_abstime (struct timespec *abstime, - int timeout) -{ - if(timeout >= 0) { -#if _POSIX_TIMERS > 0 - clock_gettime(CLOCK_REALTIME, abstime); -#else - struct timeval ustime; - gettimeofday(&ustime, NULL); - abstime->tv_nsec = ustime.tv_usec * 1000; - abstime->tv_sec = ustime.tv_sec; -#endif - abstime->tv_nsec += (timeout % 1000) * 1000000; - abstime->tv_sec += (timeout / 1000) + (abstime->tv_nsec / 1000000000); - abstime->tv_nsec %= 1000000000; - } - return(0); -} - -#ifdef HAVE_LIBPTHREAD -static inline int proc_event_wait_threaded (zbar_processor_t *proc, - unsigned event, - int timeout, - struct timespec *abstime) -{ - assert(!proc->sem); - assert(pthread_equal(proc->sem_owner, pthread_self())); - int rc = pthread_mutex_lock(&proc->mutex); - proc->events &= ~event; - proc->sem++; - pthread_cond_signal(&proc->cond); - pthread_cleanup_push(proc_mutex_unlock, &proc->mutex); - while(!rc && !(proc->events & event)) - if(timeout < 0) - rc = pthread_cond_wait(&proc->event, &proc->mutex); - else - rc = pthread_cond_timedwait(&proc->event, &proc->mutex, abstime); - if(rc == ETIMEDOUT) - rc = 0; - while(!rc && !proc->sem) - rc = pthread_cond_wait(&proc->cond, &proc->mutex); - proc->sem--; - proc->sem_owner = pthread_self(); - pthread_cleanup_pop(1); - if(rc) - return(-1); /* error */ - if(proc->events & event) - return(1); /* got event */ - return(0); /* timed out */ -} -#endif - -static inline int proc_event_wait_unthreaded (zbar_processor_t *proc, - unsigned event, - int timeout, - struct timespec *abstime) -{ - int blocking = proc->active && zbar_video_get_fd(proc->video) < 0; - proc->events &= ~event; - /* unthreaded, poll here for window input */ - while(!(proc->events & event)) { - if(blocking) { - zbar_image_t *img = zbar_video_next_image(proc->video); - if(!img) - return(-1); - process_image(proc, img); - zbar_image_destroy(img); - } - int reltime = timeout; - if(reltime >= 0) { - struct timespec now; -#if _POSIX_TIMERS > 0 - clock_gettime(CLOCK_REALTIME, &now); -#else - struct timeval ustime; - gettimeofday(&ustime, NULL); - now.tv_nsec = ustime.tv_usec * 1000; - now.tv_sec = ustime.tv_sec; -#endif - reltime = ((abstime->tv_sec - now.tv_sec) * 1000 + - (abstime->tv_nsec - now.tv_nsec) / 1000000); - if(reltime <= 0) - return(0); - } - if(blocking && (reltime < 0 || reltime > 10)) - reltime = 10; - if(proc->polling.num) - proc_poll_inputs(proc, (poll_desc_t*)&proc->polling, reltime); - else if(!blocking) { - proc_unlock(proc); - struct timespec sleepns, remns; - sleepns.tv_sec = timeout / 1000; - sleepns.tv_nsec = (timeout % 1000) * 1000000; - while(nanosleep(&sleepns, &remns) && errno == EINTR) - sleepns = remns; - (void)proc_lock(proc); - return(0); - } - } - return(1); -} - -static inline int proc_event_wait (zbar_processor_t *proc, - unsigned event, - int timeout) -{ - struct timespec abstime; - proc_calc_abstime(&abstime, timeout); -#ifdef HAVE_LIBPTHREAD - if(proc->threaded) - return(proc_event_wait_threaded(proc, event, timeout, &abstime)); - else -#endif - return(proc_event_wait_unthreaded(proc, event, timeout, &abstime)); -} - -#ifdef HAVE_LIBPTHREAD -/* make a thread-local copy of polling data */ -static inline void proc_cache_polling (zbar_processor_t *proc) -{ - (void)proc_lock(proc); - int n = proc->polling.num; - zprintf(5, "%d fds\n", n); - proc->thr_polling.num = n; - alloc_polls(&proc->thr_polling); - memcpy(proc->thr_polling.fds, proc->polling.fds, - n * sizeof(struct pollfd)); - memcpy(proc->thr_polling.handlers, proc->polling.handlers, - n * sizeof(poll_handler_t*)); - proc_unlock(proc); -} - -static inline void proc_block_sigs () -{ - sigset_t sigs; - sigfillset(&sigs); - pthread_sigmask(SIG_BLOCK, &sigs, NULL); -} - -/* input handler thread to poll available inputs */ -static void *proc_input_thread (void *arg) -{ - zbar_processor_t *proc = arg; - proc_block_sigs(); - - /* wait for registered inputs and process using associated handler */ - while(1) { - proc_cache_polling(proc); - - int rc = 0; - while(!rc) { - if(proc->polling.num) - rc = proc_poll_inputs(proc, &proc->thr_polling, -1); - else { - struct timespec t; - t.tv_sec = 4; - t.tv_nsec = 0; - rc = nanosleep(&t, NULL); - } - } - } -} - -/* separate thread to handle non-pollable video (v4l1) */ -static void *proc_video_thread (void *arg) -{ - zbar_processor_t *proc = arg; - proc_block_sigs(); - - (void)proc_lock(proc); - while(1) { - /* wait for active to be set */ - assert(!proc->sem); - assert(pthread_equal(proc->sem_owner, pthread_self())); - pthread_mutex_lock(&proc->mutex); - proc->sem++; - pthread_cond_signal(&proc->cond); - pthread_cleanup_push(proc_mutex_unlock, &proc->mutex); - while(!proc->active) - pthread_cond_wait(&proc->event, &proc->mutex); - pthread_cleanup_pop(1); - - /* unlocked blocking image input */ - zbar_image_t *img = zbar_video_next_image(proc->video); - if(!img) - return(NULL); - (void)proc_lock(proc); - if(proc->active) - process_image(proc, img); - zbar_image_destroy(img); - } -} -#endif - zbar_processor_t *zbar_processor_create (int threaded) { zbar_processor_t *proc = calloc(1, sizeof(zbar_processor_t)); if(!proc) return(NULL); err_init(&proc->err, ZBAR_MOD_PROCESSOR); - proc->kick_fds[0] = proc->kick_fds[1] = -1; proc->scanner = zbar_image_scanner_create(); if(!proc->scanner) { @@ -397,65 +97,28 @@ zbar_processor_t *zbar_processor_create (int threaded) return(NULL); } - if(threaded) { -#ifdef HAVE_LIBPTHREAD - proc->threaded = 1; - proc->sem = 1; - /* FIXME check errors */ - pthread_mutex_init(&proc->mutex, NULL); - pthread_cond_init(&proc->cond, NULL); - pthread_cond_init(&proc->event, NULL); - pipe(proc->kick_fds); - add_poll(proc, proc->kick_fds[0], NULL); -#else - /* FIXME record warning */ -#endif - } + _zbar_processor_threads_init(proc, threaded); return(proc); } void zbar_processor_destroy (zbar_processor_t *proc) { - (void)proc_lock(proc); - proc_destroy_thread(proc->video_thread, &proc->video_started); - proc_destroy_thread(proc->input_thread, &proc->input_started); - if(proc->window) { - zbar_window_destroy(proc->window); - proc->window = NULL; - _zbar_window_close(proc); - } - if(proc->video) { - zbar_video_destroy(proc->video); - proc->video = NULL; - } + _zbar_processor_lock(proc); + + zbar_processor_init(proc, NULL, 0); + if(proc->scanner) { zbar_image_scanner_destroy(proc->scanner); proc->scanner = NULL; } - proc_unlock(proc); + + _zbar_processor_unlock(proc); + + _zbar_processor_threads_cleanup(proc); + err_cleanup(&proc->err); -#ifdef HAVE_LIBPTHREAD - pthread_cond_destroy(&proc->event); - pthread_cond_destroy(&proc->cond); - pthread_mutex_destroy(&proc->mutex); -#endif - if(proc->polling.fds) { - free(proc->polling.fds); - proc->polling.fds = NULL; - } - if(proc->polling.handlers) { - free(proc->polling.handlers); - proc->polling.handlers = NULL; - } - if(proc->thr_polling.fds) { - free(proc->thr_polling.fds); - proc->thr_polling.fds = NULL; - } - if(proc->thr_polling.handlers) { - free(proc->thr_polling.handlers); - proc->thr_polling.handlers = NULL; - } + free(proc); } @@ -463,11 +126,11 @@ int zbar_processor_init (zbar_processor_t *proc, const char *dev, int enable_display) { - if(proc_lock(proc) < 0) + if(_zbar_processor_lock(proc)) return(-1); - proc_destroy_thread(proc->video_thread, &proc->video_started); - proc_destroy_thread(proc->input_thread, &proc->input_started); - proc->video_started = proc->input_started = 0; + + _zbar_processor_threads_stop(proc); + int rc = 0; if(proc->video) { if(dev) @@ -477,10 +140,12 @@ int zbar_processor_init (zbar_processor_t *proc, proc->video = NULL; } } + + _zbar_processor_close(proc); + if(proc->window) { zbar_window_destroy(proc->window); proc->window = NULL; - _zbar_window_close(proc); } if(!dev && !enable_display) @@ -506,43 +171,19 @@ int zbar_processor_init (zbar_processor_t *proc, if(proc->req_width || proc->req_height) zbar_video_request_size(proc->video, proc->req_width, proc->req_height); - if(proc->req_v4l) - zbar_video_request_interface(proc->video, proc->req_v4l); + if(proc->req_intf) + zbar_video_request_interface(proc->video, proc->req_intf); if((proc->req_iomode && zbar_video_request_iomode(proc->video, proc->req_iomode)) || zbar_video_open(proc->video, dev)) { rc = err_copy(proc, proc->video); goto done; } - if(zbar_video_get_fd(proc->video) < 0 && proc->threaded) { -#ifdef HAVE_LIBPTHREAD - /* spawn blocking video thread */ - if((rc = pthread_create(&proc->video_thread, NULL, - proc_video_thread, proc))) { - rc = err_capture_num(proc, SEV_ERROR, ZBAR_ERR_SYSTEM, - __func__, "spawning video thread", rc); - goto done; - } - proc->video_started = 1; - zprintf(4, "spawned video thread\n"); -#endif - } } -#ifdef HAVE_LIBPTHREAD - if(proc->threaded && (proc->window || - (proc->video && !proc->video_started))) { - /* spawn input monitor thread */ - if((rc = pthread_create(&proc->input_thread, NULL, - proc_input_thread, proc))) { - rc = err_capture_num(proc, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, - "spawning input thread", rc); - goto done; - } - proc->input_started = 1; - zprintf(4, "spawned input thread\n"); - } -#endif + rc = _zbar_processor_threads_start(proc); + if(rc) + goto done; if(proc->window) { /* arbitrary default */ @@ -552,40 +193,38 @@ int zbar_processor_init (zbar_processor_t *proc, height = zbar_video_get_height(proc->video); } - if(_zbar_window_open(proc, "zbar barcode reader", width, height)) { + if(_zbar_processor_open(proc, "zbar barcode reader", width, height)) { rc = -1; goto done; } - else if(zbar_window_attach(proc->window, proc->display, proc->xwin)) { - rc = err_copy(proc, proc->window); - goto done; - } } if(proc->video && proc->force_input) { if(zbar_video_init(proc->video, proc->force_input)) rc = err_copy(proc, proc->video); } - else if(proc->video) - while(zbar_negotiate_format(proc->video, proc->window)) { - if(proc->video && proc->window) { + else if(proc->video) { + int retry = -1; + if(proc->window) { + retry = zbar_negotiate_format(proc->video, proc->window); + if(retry) fprintf(stderr, "WARNING: no compatible input to output format\n" "...trying again with output disabled\n"); - zbar_window_destroy(proc->window); - proc->window = NULL; - } - else { - zprintf(1, "ERROR: no compatible %s format\n", - (proc->video) ? "video input" : "window output"); - rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, - __func__, "no compatible image format"); - goto done; - } } + if(retry) + retry = zbar_negotiate_format(proc->video, NULL); + + if(retry) { + zprintf(1, "ERROR: no compatible %s format\n", + (proc->video) ? "video input" : "window output"); + rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, + __func__, "no compatible image format"); + } + } done: - proc_unlock(proc); + _zbar_processor_unlock(proc); return(rc); } @@ -594,27 +233,36 @@ zbar_processor_set_data_handler (zbar_processor_t *proc, zbar_image_data_handler_t *handler, const void *userdata) { - if(proc_lock(proc) < 0) + if(_zbar_processor_lock(proc) < 0) return(NULL); + zbar_image_data_handler_t *result = proc->handler; proc->handler = handler; proc->userdata = userdata; - proc_unlock(proc); + + _zbar_processor_unlock(proc); return(result); } void zbar_processor_set_userdata (zbar_processor_t *proc, void *userdata) { - if(proc_lock(proc) < 0) + if(_zbar_processor_lock(proc) < 0) return; + proc->userdata = userdata; - proc_unlock(proc); + + _zbar_processor_unlock(proc); } void *zbar_processor_get_userdata (const zbar_processor_t *proc) { - return((void*)proc->userdata); + _zbar_processor_lock(proc); + + void *userdata = (void*)proc->userdata; + + _zbar_processor_unlock(proc); + return(userdata); } int zbar_processor_set_config (zbar_processor_t *proc, @@ -622,29 +270,48 @@ int zbar_processor_set_config (zbar_processor_t *proc, zbar_config_t cfg, int val) { - return(zbar_image_scanner_set_config(proc->scanner, sym, cfg, val)); + if(_zbar_processor_lock(proc) < 0) + return(-1); + int rc = zbar_image_scanner_set_config(proc->scanner, sym, cfg, val); + _zbar_processor_unlock(proc); + return(rc); } int zbar_processor_request_size (zbar_processor_t *proc, unsigned width, unsigned height) { + if(_zbar_processor_lock(proc) < 0) + return(-1); + proc->req_width = width; proc->req_height = height; + + _zbar_processor_unlock(proc); return(0); } int zbar_processor_request_interface (zbar_processor_t *proc, int ver) { - proc->req_v4l = ver; + if(_zbar_processor_lock(proc) < 0) + return(-1); + + proc->req_intf = ver; + + _zbar_processor_unlock(proc); return(0); } int zbar_processor_request_iomode (zbar_processor_t *proc, int iomode) { + if(_zbar_processor_lock(proc) < 0) + return(-1); + proc->req_iomode = iomode; + + _zbar_processor_unlock(proc); return(0); } @@ -652,151 +319,147 @@ int zbar_processor_force_format (zbar_processor_t *proc, unsigned long input, unsigned long output) { + if(_zbar_processor_lock(proc) < 0) + return(-1); + proc->force_input = input; proc->force_output = output; + + _zbar_processor_unlock(proc); return(0); } int zbar_processor_is_visible (zbar_processor_t *proc) { - if(proc_lock(proc) < 0) + if(_zbar_processor_lock(proc) < 0) return(-1); + int visible = proc->window && proc->visible; - proc_unlock(proc); + + _zbar_processor_unlock(proc); return(visible); } int zbar_processor_set_visible (zbar_processor_t *proc, int visible) { - if(proc_lock(proc) < 0) + if(_zbar_processor_lock(proc) < 0) return(-1); + int rc = 0; if(proc->window) { if(proc->video) - rc = _zbar_window_set_size(proc, - zbar_video_get_width(proc->video), - zbar_video_get_height(proc->video)); + rc = _zbar_processor_set_size(proc, + zbar_video_get_width(proc->video), + zbar_video_get_height(proc->video)); if(!rc) - rc = _zbar_window_set_visible(proc, visible); + rc = _zbar_processor_set_visible(proc, visible); } else if(visible) rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "processor display window not initialized"); - proc_unlock(proc); + + _zbar_processor_unlock(proc); return(rc); } int zbar_processor_user_wait (zbar_processor_t *proc, int timeout) { - if(proc_lock(proc) < 0) + if(_zbar_processor_lock(proc) < 0) return(-1); + int rc = -1; if(proc->visible || proc->active || timeout > 0) - rc = proc_event_wait(proc, EVENT_INPUT, timeout); + rc = _zbar_processor_wait(proc, EVENT_INPUT, timeout); if(rc > 0) rc = proc->input; - proc_unlock(proc); + if(!proc->visible) - return(err_capture(proc, SEV_WARNING, ZBAR_ERR_CLOSED, __func__, - "display window not available for input")); + rc = err_capture(proc, SEV_WARNING, ZBAR_ERR_CLOSED, __func__, + "display window not available for input"); + + _zbar_processor_unlock(proc); return(rc); } int zbar_processor_set_active (zbar_processor_t *proc, int active) { - if(proc_lock(proc) < 0) + if(_zbar_processor_lock(proc) < 0) return(-1); + if(!proc->video) { - proc_unlock(proc); - return(-1); + _zbar_processor_unlock(proc); + return(err_capture(proc, SEV_ERROR, ZBAR_ERR_INVALID, __func__, + "video input not initialized")); } - zbar_image_scanner_enable_cache(proc->scanner, active); + zbar_image_scanner_enable_cache(proc->scanner, active); int rc = zbar_video_enable(proc->video, active); if(!rc) { - int vid_fd = zbar_video_get_fd(proc->video); - if(vid_fd >= 0) { - if(active) - add_poll(proc, vid_fd, proc_video_handler); - else - remove_poll(proc, vid_fd); - } - /* FIXME failure recovery? */ + _zbar_processor_enable(proc, active); proc->active = active; proc->events &= ~EVENT_INPUT; } else err_copy(proc, proc->video); - if(!active && proc->window && + if(!proc->active && proc->window && (zbar_window_draw(proc->window, NULL) || - _zbar_window_invalidate(proc->window)) && !rc) + _zbar_processor_invalidate(proc)) && !rc) rc = err_copy(proc, proc->window); -#ifdef HAVE_LIBPTHREAD - if(proc->threaded) { - assert(!proc->sem); - assert(pthread_equal(proc->sem_owner, pthread_self())); - pthread_mutex_lock(&proc->mutex); - proc->sem++; - pthread_cond_broadcast(&proc->event); - pthread_cond_signal(&proc->cond); - pthread_mutex_unlock(&proc->mutex); - } -#endif + _zbar_processor_notify(proc, 0); + _zbar_processor_unlock(proc); return(rc); } int zbar_process_one (zbar_processor_t *proc, int timeout) { - if(proc_lock(proc) < 0) + if(_zbar_processor_lock(proc) < 0) return(-1); + int rc = 0; - if(proc->video) { - zbar_image_scanner_enable_cache(proc->scanner, 1); - rc = zbar_video_enable(proc->video, 1); - /* FIXME failure recovery? */ - int vid_fd = zbar_video_get_fd(proc->video); - if(vid_fd >= 0) - add_poll(proc, vid_fd, proc_video_handler); - proc->active = 1; -#ifdef HAVE_LIBPTHREAD - pthread_cond_broadcast(&proc->event); -#endif - proc_event_wait(proc, EVENT_OUTPUT, timeout); - rc = zbar_video_enable(proc->video, 0); - if(vid_fd >= 0) - remove_poll(proc, vid_fd); - proc->active = 0; - proc->events &= ~EVENT_INPUT; - zbar_image_scanner_enable_cache(proc->scanner, 0); + if(!proc->video) { + rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_INVALID, __func__, + "video input not initialized"); + goto done; } - else + + rc = zbar_processor_set_active(proc, 1); + if(rc) + goto done; + + rc = _zbar_processor_wait(proc, EVENT_OUTPUT, timeout); + + if(zbar_processor_set_active(proc, 0)) rc = -1; - proc_unlock(proc); + + done: + _zbar_processor_unlock(proc); return(rc); } int zbar_process_image (zbar_processor_t *proc, zbar_image_t *img) { - if(proc_lock(proc) < 0) + if(_zbar_processor_lock(proc) < 0) return(-1); + int rc = 0; if(img && proc->window) - rc = _zbar_window_set_size(proc, - zbar_image_get_width(img), - zbar_image_get_height(img)); + rc = _zbar_processor_set_size(proc, + zbar_image_get_width(img), + zbar_image_get_height(img)); if(!rc) { zbar_image_scanner_enable_cache(proc->scanner, 0); - rc = process_image(proc, img); + rc = _zbar_process_image(proc, img); if(proc->active) zbar_image_scanner_enable_cache(proc->scanner, 1); } - proc_unlock(proc); + + _zbar_processor_unlock(proc); return(rc); } diff --git a/zbar/processor.h b/zbar/processor.h index 6f3fa03..ab2cf94 100644 --- a/zbar/processor.h +++ b/zbar/processor.h @@ -30,35 +30,12 @@ #include #include #include -#ifdef HAVE_POLL_H -# include -#endif - -#ifdef HAVE_X -# include -#endif - -#ifdef HAVE_PTHREAD_H -# include -#endif - -#ifdef _WIN32 -# include -#endif #include #include "error.h" -#ifdef HAVE_POLL_H -typedef int (poll_handler_t)(zbar_processor_t*, int); - -/* poll information */ -typedef struct poll_desc_s { - int num; /* number of descriptors */ - struct pollfd *fds; /* poll descriptors */ - poll_handler_t **handlers; /* poll handlers */ -} poll_desc_t; -#endif +/* platform specific state wrapper */ +typedef struct processor_state_s processor_state_t; struct zbar_processor_s { errinfo_t err; /* error reporting */ @@ -71,126 +48,43 @@ struct zbar_processor_s { zbar_image_data_handler_t *handler; /* application data handler */ unsigned req_width, req_height; /* application requested video size */ - int req_v4l, req_iomode; /* application requested v4l version */ + int req_intf, req_iomode; /* application requested interface */ uint32_t force_input; /* force input format (debug) */ uint32_t force_output; /* force format conversion (debug) */ + int input; /* user input status */ + /* state flags */ - unsigned threaded : 1; /* threading requested */ - unsigned visible : 1; /* output window mapped to display */ + unsigned threaded : 1; + unsigned visible : 1; /* output window mapped to display */ volatile unsigned active : 1; /* async processor thread running */ volatile unsigned events; /* synchronization events */ #define EVENT_INPUT 0x01 /* user input */ #define EVENT_OUTPUT 0x02 /* decoded output data available */ - int input; /* user input status */ - -#ifdef HAVE_POLL_H - volatile poll_desc_t polling; /* polling registration */ - poll_desc_t thr_polling; /* thread copy */ - int kick_fds[2]; /* poll kicker */ -#endif - -#ifdef HAVE_LIBPTHREAD - int sem; /* window access semaphore */ - pthread_t sem_owner; /* semaphore owner */ - pthread_mutex_t mutex; /* semaphore lock */ - pthread_cond_t cond; /* semaphore condition */ - pthread_cond_t event; - pthread_t video_thread; /* video input handler */ - pthread_t input_thread; /* window event handler */ -#endif - unsigned video_started; /* thread active flags */ - unsigned input_started; - -#ifdef HAVE_X - Display *display; /* X display connection */ - Window xwin; /* toplevel window */ -#endif + void *display; /* X display connection */ + unsigned long xwin; /* toplevel window */ -#ifdef _WIN32 - HWND display; /* window handle */ - long xwin; /* unused */ -#endif + processor_state_t *state; }; -#ifdef HAVE_POLL_H -static inline int alloc_polls (volatile poll_desc_t *p) -{ - p->fds = realloc(p->fds, p->num * sizeof(struct pollfd)); - p->handlers = realloc(p->handlers, p->num * sizeof(poll_handler_t*)); - /* FIXME should check for ENOMEM */ - return(0); -} - -static inline int add_poll (zbar_processor_t *proc, - int fd, - poll_handler_t *handler) -{ - unsigned i = proc->polling.num++; - zprintf(5, "[%d] fd=%d handler=%p\n", i, fd, handler); - if(alloc_polls(&proc->polling)) - return(-1); - memset(&proc->polling.fds[i], 0, sizeof(struct pollfd)); - proc->polling.fds[i].fd = fd; - proc->polling.fds[i].events = POLLIN; - proc->polling.handlers[i] = handler; -#ifdef HAVE_LIBPTHREAD - if(proc->input_started) { - assert(proc->kick_fds[1] >= 0); - write(proc->kick_fds[1], &i /* unused */, sizeof(unsigned)); - /* FIXME should sync */ - } -#endif - return(i); -} - -static inline int remove_poll (zbar_processor_t *proc, - int fd) -{ - int i; - for(i = proc->polling.num - 1; i >= 0; i--) - if(proc->polling.fds[i].fd == fd) - break; - zprintf(5, "[%d] fd=%d n=%d\n", i, fd, proc->polling.num); - if(i < 0) - return(1); - if(i + 1 < proc->polling.num) { - int n = proc->polling.num - i - 1; - memmove(&proc->polling.fds[i], &proc->polling.fds[i + 1], - n * sizeof(struct pollfd)); - memmove(&proc->polling.handlers[i], &proc->polling.handlers[i + 1], - n * sizeof(poll_handler_t)); - } - proc->polling.num--; - int rc = alloc_polls(&proc->polling); -#ifdef HAVE_LIBPTHREAD - if(proc->input_started) { - write(proc->kick_fds[1], &i /* unused */, sizeof(unsigned)); - /* FIXME should sync */ - } -#endif - return(rc); -} -#endif - -static inline void emit (zbar_processor_t *proc, - unsigned mask) -{ - proc->events |= mask; -#ifdef HAVE_LIBPTHREAD - if(!proc->threaded) - return; - pthread_cond_broadcast(&proc->event); -#endif -} - -extern int _zbar_window_open(zbar_processor_t*, char*, unsigned, unsigned); -extern int _zbar_window_close(zbar_processor_t*); -extern int _zbar_window_set_visible(zbar_processor_t*, int); -extern int _zbar_window_invalidate(zbar_window_t*); -extern int _zbar_window_set_size(zbar_processor_t*, unsigned, unsigned); -extern int _zbar_window_handle_events(zbar_processor_t*, int); +extern int _zbar_processor_lock(const zbar_processor_t*); +extern int _zbar_processor_unlock(const zbar_processor_t*); +extern int _zbar_processor_notify(zbar_processor_t*, unsigned); +extern int _zbar_processor_wait(zbar_processor_t*, unsigned, int); + +extern int _zbar_processor_threads_init(zbar_processor_t*, int); +extern int _zbar_processor_threads_cleanup(zbar_processor_t*); +extern int _zbar_processor_threads_start(zbar_processor_t*); +extern int _zbar_processor_threads_stop(zbar_processor_t*); + +extern int _zbar_processor_open(zbar_processor_t*, char*, unsigned, unsigned); +extern int _zbar_processor_close(zbar_processor_t*); +extern int _zbar_processor_set_visible(zbar_processor_t*, int); +extern int _zbar_processor_set_size(zbar_processor_t*, unsigned, unsigned); +extern int _zbar_processor_invalidate(zbar_processor_t*); +extern int _zbar_processor_enable(zbar_processor_t*, int); +extern int _zbar_process_image(zbar_processor_t*, zbar_image_t*); #endif diff --git a/zbar/processor/posix.c b/zbar/processor/posix.c new file mode 100644 index 0000000..7f4e8d3 --- /dev/null +++ b/zbar/processor/posix.c @@ -0,0 +1,485 @@ +/*------------------------------------------------------------------------ + * Copyright 2007-2009 (c) Jeff Brown + * + * 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 "processor.h" +#include "posix.h" +#include +#include +#include +#include /* gettimeofday */ +#include +#include + +#ifdef HAVE_LIBPTHREAD + +static inline void proc_mutex_unlock (void *arg) +{ + pthread_mutex_unlock((pthread_mutex_t*)arg); +} + +/* acquire window access semaphore */ +inline int _zbar_processor_lock (const zbar_processor_t *proc) +{ + if(!proc->threaded) + return(0); + + processor_state_t *state = proc->state; + pthread_t self = pthread_self(); + + int rc = pthread_mutex_lock(&state->mutex); + pthread_cleanup_push(proc_mutex_unlock, &state->mutex); + + if(!rc && state->lock_level && pthread_equal(state->lock_owner, self)) + state->lock_level++; + else { + while(!rc && state->lock_level) + rc = pthread_cond_wait(&state->cond, &state->mutex); + if(!rc) { + state->lock_level++; + state->lock_owner = self; + } + } + + pthread_cleanup_pop(1); + + if(rc) + err_capture(proc, SEV_ERROR, ZBAR_ERR_LOCKING, __func__, + "unable to lock processor"); + return(rc); +} + +/* release window access semaphore */ +inline int _zbar_processor_unlock (const zbar_processor_t *proc) +{ + if(!proc->threaded) + return(0); + processor_state_t *state = proc->state; + + pthread_mutex_lock(&state->mutex); + + assert(state->lock_level > 0); + assert(pthread_equal(state->lock_owner, pthread_self())); + if(!--state->lock_level) + pthread_cond_signal(&state->cond); + + pthread_mutex_unlock(&state->mutex); + + return(0); +} + +inline int _zbar_processor_notify (zbar_processor_t *proc, + unsigned event) +{ + proc->events |= event; +#ifdef HAVE_LIBPTHREAD + processor_state_t *state = proc->state; + pthread_cond_broadcast(&state->event); +#endif + return(0); +} + +static inline void proc_destroy_thread (pthread_t thread, + unsigned *started) +{ + if(*started) { + pthread_cancel(thread); + pthread_join(thread, NULL); + *started = 0; + } +} + +#else +# define _zbar_processor_lock(...) (0) +# define _zbar_processor_unlock(...) (0) +# define proc_destroy_thread(...) +#endif + + +/* used by poll interface. lock is already held */ +static int proc_video_handler (zbar_processor_t *proc, + int i) +{ + if(!proc->active) + return(0); + /* not expected to block */ + zbar_image_t *img = zbar_video_next_image(proc->video); + if(!img) + return(-1); + int rc = _zbar_process_image(proc, img); + zbar_image_destroy(img); + return(rc); +} + +static inline int proc_poll_inputs (zbar_processor_t *proc, + poll_desc_t *p, + int timeout) +{ + assert(p->num); + int rc = poll(p->fds, p->num, timeout); + if(rc <= 0) + /* FIXME detect and handle fatal errors (somehow) */ + return(rc); + processor_state_t *state = proc->state; + _zbar_processor_lock(proc); + if(p->fds[0].revents && p->fds[0].fd == state->kick_fds[0]) { + unsigned junk[2]; + read(state->kick_fds[0], junk, 2 * sizeof(unsigned)); + _zbar_processor_unlock(proc); + return(1); + } + int i; + for(i = 0; i < p->num; i++) + if(p->fds[i].revents) { + if(p->handlers[i]) + p->handlers[i](proc, i); + p->fds[i].revents = 0; /* debug */ + rc--; + } + _zbar_processor_unlock(proc); + assert(!rc); + return(0); +} + +static inline int proc_calc_abstime (struct timespec *abstime, + int timeout) +{ + if(timeout >= 0) { +#if _POSIX_TIMERS > 0 + clock_gettime(CLOCK_REALTIME, abstime); +#else + struct timeval ustime; + gettimeofday(&ustime, NULL); + abstime->tv_nsec = ustime.tv_usec * 1000; + abstime->tv_sec = ustime.tv_sec; +#endif + abstime->tv_nsec += (timeout % 1000) * 1000000; + abstime->tv_sec += (timeout / 1000) + (abstime->tv_nsec / 1000000000); + abstime->tv_nsec %= 1000000000; + } + return(0); +} + +#ifdef HAVE_LIBPTHREAD +static inline int proc_wait_threaded (zbar_processor_t *proc, + unsigned event, + int timeout, + struct timespec *abstime) +{ + processor_state_t *state = proc->state; + pthread_t self = pthread_self(); + + int rc = pthread_mutex_lock(&state->mutex); + + assert(state->lock_level > 0); + assert(pthread_equal(state->lock_owner, self)); + proc->events &= ~event; + + int save_level = state->lock_level; + state->lock_level = 0; + + pthread_cond_signal(&state->cond); + + pthread_cleanup_push(proc_mutex_unlock, &state->mutex); + while(!rc && !(proc->events & event)) + if(timeout < 0) + rc = pthread_cond_wait(&state->event, &state->mutex); + else + rc = pthread_cond_timedwait(&state->event, &state->mutex, abstime); + if(rc == ETIMEDOUT) + rc = 0; + + while(!rc && state->lock_level) + rc = pthread_cond_wait(&state->cond, &state->mutex); + if(!rc) { + state->lock_level = save_level; + state->lock_owner = self; + } + + pthread_cleanup_pop(1); + + if(rc) + return(-1); /* error (FIXME save info) */ + if(proc->events & event) + return(1); /* got event */ + return(0); /* timed out */ +} +#endif + +static inline int proc_wait_unthreaded (zbar_processor_t *proc, + unsigned event, + int timeout, + struct timespec *abstime) +{ + processor_state_t *state = proc->state; + int blocking = proc->active && zbar_video_get_fd(proc->video) < 0; + proc->events &= ~event; + /* unthreaded, poll here for window input */ + while(!(proc->events & event)) { + if(blocking) { + zbar_image_t *img = zbar_video_next_image(proc->video); + if(!img) + return(-1); + _zbar_process_image(proc, img); + zbar_image_destroy(img); + } + int reltime = timeout; + if(reltime >= 0) { + struct timespec now; +#if _POSIX_TIMERS > 0 + clock_gettime(CLOCK_REALTIME, &now); +#else + struct timeval ustime; + gettimeofday(&ustime, NULL); + now.tv_nsec = ustime.tv_usec * 1000; + now.tv_sec = ustime.tv_sec; +#endif + reltime = ((abstime->tv_sec - now.tv_sec) * 1000 + + (abstime->tv_nsec - now.tv_nsec) / 1000000); + if(reltime <= 0) + return(0); + } + if(blocking && (reltime < 0 || reltime > 10)) + reltime = 10; + if(state->polling.num) + proc_poll_inputs(proc, (poll_desc_t*)&state->polling, reltime); + else if(!blocking) { + _zbar_processor_unlock(proc); + struct timespec sleepns, remns; + sleepns.tv_sec = timeout / 1000; + sleepns.tv_nsec = (timeout % 1000) * 1000000; + while(nanosleep(&sleepns, &remns) && errno == EINTR) + sleepns = remns; + (void)_zbar_processor_lock(proc); + return(0); + } + } + return(1); +} + +inline int _zbar_processor_wait (zbar_processor_t *proc, + unsigned event, + int timeout) +{ + struct timespec abstime; + proc_calc_abstime(&abstime, timeout); +#ifdef HAVE_LIBPTHREAD + if(proc->threaded) + return(proc_wait_threaded(proc, event, timeout, &abstime)); + else +#endif + return(proc_wait_unthreaded(proc, event, timeout, &abstime)); +} + +#ifdef HAVE_LIBPTHREAD +/* make a thread-local copy of polling data */ +static inline void proc_cache_polling (zbar_processor_t *proc) +{ + (void)_zbar_processor_lock(proc); + processor_state_t *state = proc->state; + int n = state->polling.num; + zprintf(5, "%d fds\n", n); + state->thr_polling.num = n; + alloc_polls(&state->thr_polling); + memcpy(state->thr_polling.fds, state->polling.fds, + n * sizeof(struct pollfd)); + memcpy(state->thr_polling.handlers, state->polling.handlers, + n * sizeof(poll_handler_t*)); + _zbar_processor_unlock(proc); +} + +static inline void proc_block_sigs () +{ + sigset_t sigs; + sigfillset(&sigs); + pthread_sigmask(SIG_BLOCK, &sigs, NULL); +} + +/* input handler thread to poll available inputs */ +static void *proc_input_thread (void *arg) +{ + zbar_processor_t *proc = arg; + processor_state_t *state = proc->state; + proc_block_sigs(); + + /* wait for registered inputs and process using associated handler */ + while(1) { + proc_cache_polling(proc); + + int rc = 0; + while(!rc) { + if(state->polling.num) + rc = proc_poll_inputs(proc, &state->thr_polling, -1); + else { + struct timespec t; + t.tv_sec = 4; + t.tv_nsec = 0; + rc = nanosleep(&t, NULL); + } + } + } +} + +/* separate thread to handle non-pollable video (v4l1) */ +static void *proc_video_thread (void *arg) +{ + zbar_processor_t *proc = arg; + processor_state_t *state = proc->state; + pthread_t self = pthread_self(); + proc_block_sigs(); + + (void)_zbar_processor_lock(proc); + while(1) { + /* wait for active to be set */ + assert(state->lock_level == 1); + assert(pthread_equal(state->lock_owner, self)); + pthread_mutex_lock(&state->mutex); + state->lock_level = 0; + pthread_cond_signal(&state->cond); + pthread_cleanup_push(proc_mutex_unlock, &state->mutex); + while(!proc->active) + pthread_cond_wait(&state->event, &state->mutex); + pthread_cleanup_pop(1); + + /* unlocked blocking image input */ + zbar_image_t *img = zbar_video_next_image(proc->video); + if(!img) + return(NULL); + (void)_zbar_processor_lock(proc); + if(proc->active) + _zbar_process_image(proc, img); + zbar_image_destroy(img); + } +} +#endif + +int _zbar_processor_threads_init (zbar_processor_t *proc, + int threaded) +{ + processor_state_t *state = proc->state = + calloc(1, sizeof(processor_state_t)); + state->kick_fds[0] = state->kick_fds[1] = -1; + + if(threaded) { +#ifdef HAVE_LIBPTHREAD + /* FIXME check errors */ + pthread_mutex_init(&state->mutex, NULL); + pthread_cond_init(&state->cond, NULL); + pthread_cond_init(&state->event, NULL); + pipe(state->kick_fds); + add_poll(state, state->kick_fds[0], NULL); + proc->threaded = 1; +#else + /* FIXME record warning */ +#endif + } + return(0); +} + +int _zbar_processor_threads_start (zbar_processor_t *proc) +{ + if(!proc->threaded) + return(0); + +#ifdef HAVE_LIBPTHREAD + processor_state_t *state = proc->state; + if(proc->video && zbar_video_get_fd(proc->video) < 0) { + /* spawn blocking video thread */ + int rc; + if((rc = pthread_create(&state->video_thread, NULL, + proc_video_thread, proc))) + return(err_capture_num(proc, SEV_ERROR, ZBAR_ERR_SYSTEM, + __func__, "spawning video thread", rc)); + + state->video_started = 1; + zprintf(4, "spawned video thread\n"); + } + + if(proc->window || + (proc->video && !state->video_started)) { + /* spawn input monitor thread */ + int rc; + if((rc = pthread_create(&state->input_thread, NULL, + proc_input_thread, proc))) + return(err_capture_num(proc, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, + "spawning input thread", rc)); + state->input_started = 1; + zprintf(4, "spawned input thread\n"); + } +#endif + + return(0); +} + +int _zbar_processor_threads_stop (zbar_processor_t *proc) +{ +#ifdef HAVE_LIBPTHREAD + processor_state_t *state = proc->state; + proc_destroy_thread(state->video_thread, &state->video_started); + proc_destroy_thread(state->input_thread, &state->input_started); +#endif + return(0); +} + +int _zbar_processor_threads_cleanup (zbar_processor_t *proc) +{ + processor_state_t *state = proc->state; +#ifdef HAVE_LIBPTHREAD + pthread_cond_destroy(&state->event); + pthread_cond_destroy(&state->cond); + pthread_mutex_destroy(&state->mutex); +#endif + if(state->polling.fds) { + free(state->polling.fds); + state->polling.fds = NULL; + } + if(state->polling.handlers) { + free(state->polling.handlers); + state->polling.handlers = NULL; + } + if(state->thr_polling.fds) { + free(state->thr_polling.fds); + state->thr_polling.fds = NULL; + } + if(state->thr_polling.handlers) { + free(state->thr_polling.handlers); + state->thr_polling.handlers = NULL; + } + free(proc->state); + proc->state = NULL; + return(0); +} + +int _zbar_processor_enable (zbar_processor_t *proc, + int active) +{ + int vid_fd = zbar_video_get_fd(proc->video); + processor_state_t *state = proc->state; + if(vid_fd >= 0) { + if(active) + add_poll(state, vid_fd, proc_video_handler); + else + remove_poll(state, vid_fd); + } + /* FIXME failure recovery? */ + return(0); +} diff --git a/zbar/processor/posix.h b/zbar/processor/posix.h new file mode 100644 index 0000000..d90a991 --- /dev/null +++ b/zbar/processor/posix.h @@ -0,0 +1,136 @@ +/*------------------------------------------------------------------------ + * Copyright 2007-2009 (c) Jeff Brown + * + * 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 + *------------------------------------------------------------------------*/ +#ifndef _PROCESSOR_POSIX_H_ +#define _PROCESSOR_POSIX_H_ + +#include "processor.h" + +#ifdef HAVE_POLL_H +# include +#endif + +#ifdef HAVE_X +# include +#endif + +#ifdef HAVE_PTHREAD_H +# include +#endif + +#ifdef HAVE_POLL_H +typedef int (poll_handler_t)(zbar_processor_t*, int); + +/* poll information */ +typedef struct poll_desc_s { + int num; /* number of descriptors */ + struct pollfd *fds; /* poll descriptors */ + poll_handler_t **handlers; /* poll handlers */ +} poll_desc_t; +#endif + +struct processor_state_s { +#ifdef HAVE_POLL_H + volatile poll_desc_t polling; /* polling registration */ + poll_desc_t thr_polling; /* thread copy */ + int kick_fds[2]; /* poll kicker */ +#endif + +#ifdef HAVE_LIBPTHREAD + int lock_level; /* API serialization lock */ + pthread_t lock_owner; /* lock owner */ + pthread_mutex_t mutex; /* lock mutex */ + pthread_cond_t cond; /* lock notification condition */ + pthread_cond_t event; + + pthread_t video_thread; /* video input handler */ + pthread_t input_thread; /* window event handler */ + + unsigned video_started; /* thread active flags */ + unsigned input_started; +#endif +}; + + +#ifdef HAVE_POLL_H +static inline int alloc_polls (volatile poll_desc_t *p) +{ + p->fds = realloc(p->fds, p->num * sizeof(struct pollfd)); + p->handlers = realloc(p->handlers, p->num * sizeof(poll_handler_t*)); + /* FIXME should check for ENOMEM */ + return(0); +} + +static inline int add_poll (processor_state_t *state, + int fd, + poll_handler_t *handler) +{ + volatile poll_desc_t *polling = &state->polling; + unsigned i = polling->num++; + zprintf(5, "[%d] fd=%d handler=%p\n", i, fd, handler); + if(alloc_polls(polling)) + return(-1); + memset(&polling->fds[i], 0, sizeof(struct pollfd)); + polling->fds[i].fd = fd; + polling->fds[i].events = POLLIN; + polling->handlers[i] = handler; +#ifdef HAVE_LIBPTHREAD + if(state->input_started) { + assert(state->kick_fds[1] >= 0); + write(state->kick_fds[1], &i /* unused */, sizeof(unsigned)); + /* FIXME should sync */ + } +#endif + return(i); +} + +static inline int remove_poll (processor_state_t *state, + int fd) +{ + volatile poll_desc_t *polling = &state->polling; + int i; + for(i = polling->num - 1; i >= 0; i--) + if(polling->fds[i].fd == fd) + break; + zprintf(5, "[%d] fd=%d n=%d\n", i, fd, polling->num); + if(i < 0) + return(1); + if(i + 1 < polling->num) { + int n = polling->num - i - 1; + memmove(&polling->fds[i], &polling->fds[i + 1], + n * sizeof(struct pollfd)); + memmove(&polling->handlers[i], &polling->handlers[i + 1], + n * sizeof(poll_handler_t)); + } + polling->num--; + int rc = alloc_polls(polling); +#ifdef HAVE_LIBPTHREAD + if(state->input_started) { + write(state->kick_fds[1], &i /* unused */, sizeof(unsigned)); + /* FIXME should sync */ + } +#endif + return(rc); +} +#endif + +#endif diff --git a/zbar/processor/win.c b/zbar/processor/win.c new file mode 100644 index 0000000..580fff5 --- /dev/null +++ b/zbar/processor/win.c @@ -0,0 +1,608 @@ +/*------------------------------------------------------------------------ + * Copyright 2007-2009 (c) Jeff Brown + * + * 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 "processor.h" +#include "win.h" +#include + +static inline int proc_lock (processor_state_t *state, + DWORD self) +{ + if(!state->lock_level) { + state->lock_owner = self; + state->lock_level = 1; + return(0); + } + + if(state->lock_owner == self) { + state->lock_level++; + return(0); + } + + wait_entry_t *entry = proc_entry_alloc(state, self); + proc_entry_queue(&state->lock_queue, entry); + + LeaveCriticalSection(&state->mutex); + int rc = WaitForSingleObject(entry->notify, INFINITE); + EnterCriticalSection(&state->mutex); + + assert(state->lock_level == 1); + assert(state->lock_owner == self); + + proc_entry_free(state, entry); + return(rc); +} + +static inline int proc_unlock (processor_state_t *state, + DWORD self, + int all) +{ + assert(state->lock_level > 0); + assert(state->lock_owner == self); + + if(all) + state->lock_level = 0; + else + state->lock_level--; + + if(!state->lock_level) { + wait_entry_t *entry = proc_entry_dequeue(&state->lock_queue); + if(entry) { + state->lock_level = 1; + state->lock_owner = entry->requester; + SetEvent(entry->notify); + } + } + return(0); +} + +static inline void proc_notify (zbar_processor_t *proc) +{ + processor_state_t *state = proc->state; + wait_entry_t **q = &state->wait_queue.head; + while(*q) { + wait_entry_t *entry = *q; + if(entry->requester & proc->events) { + *q = entry->next; + SetEvent(entry->notify); + } + q = &entry->next; + entry->next = NULL; + } +} + +inline int _zbar_processor_lock (const zbar_processor_t *proc) +{ + processor_state_t *state = proc->state; + + EnterCriticalSection(&state->mutex); + int rc = proc_lock(state, GetCurrentThreadId()); + LeaveCriticalSection(&state->mutex); + + if(rc) + /* FIXME save system code */ + rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_LOCKING, __func__, + "unable to lock processor"); + return(rc); +} + +inline int _zbar_processor_unlock (const zbar_processor_t *proc) +{ + processor_state_t *state = proc->state; + + EnterCriticalSection(&state->mutex); + proc_unlock(state, GetCurrentThreadId(), 0); + LeaveCriticalSection(&state->mutex); + + return(0); +} + +inline int _zbar_processor_notify (zbar_processor_t *proc, + unsigned event) +{ + processor_state_t *state = proc->state; + + EnterCriticalSection(&state->mutex); + proc->events |= event; + + SetEvent(state->video_thread.activity); + proc_notify(proc); + + LeaveCriticalSection(&state->mutex); + return(0); +} + +inline int _zbar_processor_wait (zbar_processor_t *proc, + unsigned event, + int timeout) +{ + processor_state_t *state = proc->state; + DWORD self = GetCurrentThreadId(); + + proc->events &= ~event; + + EnterCriticalSection(&state->mutex); + + int save_level = state->lock_level; + wait_entry_t *entry = proc_entry_alloc(state, event); + proc_entry_queue(&state->wait_queue, entry); + proc_unlock(state, self, 1); + + LeaveCriticalSection(&state->mutex); + int rc = WaitForSingleObject(entry->notify, timeout); + EnterCriticalSection(&state->mutex); + + proc_entry_free(state, entry); + proc_lock(state, self); + state->lock_level = save_level; + if(!rc) + assert(proc->events & event); + + LeaveCriticalSection(&state->mutex); + + if(!rc) + return(1); /* got event */ + if(rc == WAIT_TIMEOUT) + return(0); /* timed out */ + return(-1); /* error (FIXME save info) */ +} + +static inline int proc_thread_start (zbar_processor_t *proc, + thread_state_t *tstate, + LPTHREAD_START_ROUTINE thread) +{ + assert(!tstate->running); + tstate->running = 1; + HANDLE hthr = CreateThread(NULL, 0, thread, proc, 0, NULL); + if(!hthr) { + tstate->running = 0; + return(-1/*FIXME*/); + } + CloseHandle(hthr); + + HANDLE status[2] = { tstate->started, tstate->stopped }; + int rc = WaitForMultipleObjects(2, status, 0, INFINITE); + if(rc) { + tstate->running = 0; + return(-1/*FIXME*/); + } + + return(0); +} + +static inline int proc_thread_stop (processor_state_t *state, + thread_state_t *tstate) +{ + if(tstate->running) { + tstate->running = 0; + SetEvent(tstate->activity); + LeaveCriticalSection(&state->mutex); + WaitForSingleObject(tstate->stopped, INFINITE); + EnterCriticalSection(&state->mutex); + } + return(0); +} + +int _zbar_processor_threads_init (zbar_processor_t *proc, + int threaded) +{ + processor_state_t *state = proc->state = + calloc(1, sizeof(processor_state_t)); + + InitializeCriticalSection(&state->mutex); + + state->video_thread.activity = CreateEvent(NULL, 0, 0, NULL); + state->video_thread.started = CreateEvent(NULL, 0, 0, NULL); + state->video_thread.stopped = CreateEvent(NULL, 0, 0, NULL); + + state->input_thread.activity = CreateEvent(NULL, 0, 0, NULL); + state->input_thread.started = CreateEvent(NULL, 0, 0, NULL); + state->input_thread.stopped = CreateEvent(NULL, 0, 0, NULL); + return(0); +} + +int _zbar_processor_threads_cleanup (zbar_processor_t *proc) +{ + processor_state_t *state = proc->state; + + CloseHandle(state->video_thread.activity); + CloseHandle(state->video_thread.started); + CloseHandle(state->video_thread.stopped); + + CloseHandle(state->input_thread.activity); + CloseHandle(state->input_thread.started); + CloseHandle(state->input_thread.stopped); + + DeleteCriticalSection(&state->mutex); + + free(state); + proc->state = NULL; + return(0); +} + + +static DWORD WINAPI proc_video_thread (void *arg) +{ + zbar_processor_t *proc = arg; + processor_state_t *state = proc->state; + thread_state_t *tstate = &state->video_thread; + DWORD self = GetCurrentThreadId(); + int rc = 0; + + EnterCriticalSection(&state->mutex); + SetEvent(tstate->started); + + wait_entry_t *entry = proc_entry_alloc(state, self); + HANDLE activity[2] = { tstate->activity, entry->notify }; + + while(tstate->running) { + while(!proc->active && tstate->running) { + LeaveCriticalSection(&state->mutex); + rc = WaitForSingleObject(tstate->activity, INFINITE); + EnterCriticalSection(&state->mutex); + } + if(!tstate->running) + break; + + /* unlocked blocking image input */ + LeaveCriticalSection(&state->mutex); + zbar_image_t *img = zbar_video_next_image(proc->video); + EnterCriticalSection(&state->mutex); + + if(!img) + break; + + if(!state->lock_level) { + state->lock_owner = self; + state->lock_level = 1; + } + else { + proc_entry_queue(&state->lock_queue, entry); + rc = 0; + while(!rc && tstate->running) { + LeaveCriticalSection(&state->mutex); + rc = WaitForMultipleObjects(2, activity, 0, INFINITE); + EnterCriticalSection(&state->mutex); + } + if(rc || !tstate->running) + break; + } + + assert(state->lock_level == 1); + assert(state->lock_owner == self); + LeaveCriticalSection(&state->mutex); + + if(proc->active) + _zbar_process_image(proc, img); + + zbar_image_destroy(img); + + EnterCriticalSection(&state->mutex); + + wait_entry_t *next = proc_entry_dequeue(&state->lock_queue); + if(next) { + state->lock_owner = next->requester; + SetEvent(next->notify); + } + } + + proc_entry_free(state, entry); + + LeaveCriticalSection(&state->mutex); + + SetEvent(tstate->stopped); + return(0); +} + +int _zbar_processor_threads_start (zbar_processor_t *proc) +{ + return(proc_thread_start(proc, &proc->state->video_thread, + proc_video_thread)); +} + +int _zbar_processor_threads_stop (zbar_processor_t *proc) +{ + processor_state_t *state = proc->state; + EnterCriticalSection(&state->mutex); + int rc = proc_thread_stop(proc->state, &proc->state->video_thread); + LeaveCriticalSection(&state->mutex); + return(rc); +} + + +static LRESULT CALLBACK proc_handle_event (HWND hwnd, + UINT message, + WPARAM wparam, + LPARAM lparam) +{ + zbar_processor_t *proc = + (zbar_processor_t*)GetWindowLongPtr(hwnd, GWL_USERDATA); + processor_state_t *state = NULL; + /* initialized during window creation */ + if(proc) + state = proc->state; + else if(message == WM_NCCREATE) { + proc = ((LPCREATESTRUCT)lparam)->lpCreateParams; + assert(proc); + state = proc->state; + assert(state); + SetWindowLongPtr(hwnd, GWL_USERDATA, (LONG_PTR)proc); + proc->display = state->hwnd = hwnd; + + zbar_window_attach(proc->window, proc->display, proc->xwin); + } + else + return(DefWindowProc(hwnd, message, wparam, lparam)); + + switch(message) { + + case WM_SIZE: { + RECT r; + GetClientRect(hwnd, &r); + zprintf(3, "WM_SIZE %dx%d\n", r.right, r.bottom); + assert(proc); + zbar_window_resize(proc->window, r.right, r.bottom); + InvalidateRect(hwnd, NULL, 0); + return(0); + } + + case WM_PAINT: { + PAINTSTRUCT ps; + BeginPaint(hwnd, &ps); + if(zbar_window_redraw(proc->window)) { + HDC hdc = GetDC(hwnd); + RECT r; + GetClientRect(hwnd, &r); + FillRect(hdc, &r, GetStockObject(BLACK_BRUSH)); + ReleaseDC(hwnd, hdc); + } + EndPaint(hwnd, &ps); + return(0); + } + + case WM_CHAR: { + state->input = wparam; + return(0); + } + + case WM_LBUTTONDOWN: { + state->input = 1; + return(0); + } + + case WM_MBUTTONDOWN: { + state->input = 2; + return(0); + } + + case WM_RBUTTONDOWN: { + state->input = 3; + return(0); + } + + case WM_CLOSE: { + zprintf(3, "WM_CLOSE\n"); + _zbar_processor_set_visible(proc, 0); + return(1); + } + + case WM_DESTROY: { + zprintf(3, "WM_DESTROY\n"); + state->hwnd = proc->display = NULL; + zbar_window_attach(proc->window, NULL, 0); + return(0); + } + } + return(DefWindowProc(hwnd, message, wparam, lparam)); +} + +static inline int proc_handle_events (zbar_processor_t *proc) +{ + processor_state_t *state = proc->state; + while(1) { + MSG msg; + int rc = PeekMessage(&msg, state->hwnd, 0, 0, PM_NOYIELD | PM_REMOVE); + if(!rc) + return(0); + if(rc < 0) { + proc->err.errnum = GetLastError(); + return(err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, + "failed to obtain event")); + } + + TranslateMessage(&msg); + DispatchMessage(&msg); + + if(state->input) { + EnterCriticalSection(&state->mutex); + proc->input = state->input; + proc->events |= EVENT_INPUT; + proc_notify(proc); + LeaveCriticalSection(&state->mutex); + state->input = 0; + } + } +} + +static inline ATOM proc_register_class (HINSTANCE hmod) +{ + BYTE and_mask[1] = { 0xff }; + BYTE xor_mask[1] = { 0x00 }; + + WNDCLASSEX wc = { sizeof(WNDCLASSEX), 0, }; + wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wc.hInstance = hmod; + wc.lpfnWndProc = proc_handle_event; + wc.lpszClassName = "_ZBar Class"; + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wc.hCursor = CreateCursor(hmod, 0, 0, 1, 1, and_mask, xor_mask); + + return(RegisterClassEx(&wc)); +} + +static inline int proc_open (zbar_processor_t *proc, + unsigned width, + unsigned height) +{ + processor_state_t *state = proc->state; + HMODULE hmod = NULL; + if(!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + (void*)_zbar_processor_open, (HINSTANCE*)&hmod)) { + proc->err.errnum = GetLastError(); + return(err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, + "failed to obtain module handle")); + } + + ATOM wca = proc_register_class(hmod); + if(!wca) { + proc->err.errnum = GetLastError(); + return(err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, + "failed to register window class")); + } + + DWORD style = WS_OVERLAPPEDWINDOW; + DWORD exstyle = (WS_EX_APPWINDOW | + WS_EX_OVERLAPPEDWINDOW /*| + WS_EX_ACCEPTFILES*/); + + state->hwnd = CreateWindowEx(exstyle, (LPCTSTR)(long)wca, "ZBar", style, + CW_USEDEFAULT, CW_USEDEFAULT, width, height, + NULL, NULL, hmod, proc); + + if(!state->hwnd) { + proc->err.errnum = GetLastError(); + return(err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, + "failed to open window")); + } + return(0); +} + +static DWORD WINAPI proc_input_thread (void *arg) +{ + zbar_processor_t *proc = arg; + processor_state_t *state = proc->state; + thread_state_t *tstate = &state->input_thread; + state->input = 0; + + int rc = proc_open(proc, state->width, state->height); + if(rc) { + SetEvent(tstate->stopped); + return(-1); + } + + EnterCriticalSection(&state->mutex); + SetEvent(tstate->started); + + while(!rc && tstate->running) { + LeaveCriticalSection(&state->mutex); + + rc = MsgWaitForMultipleObjects(1, &tstate->activity, 0, + INFINITE, QS_ALLINPUT); + if(rc == 1) + rc = proc_handle_events(proc); + + EnterCriticalSection(&state->mutex); + } + LeaveCriticalSection(&state->mutex); + + if(state->hwnd) { + DestroyWindow(state->hwnd); + state->hwnd = proc->display = NULL; + } + + SetEvent(tstate->stopped); + return(0); +} + + +int _zbar_processor_open (zbar_processor_t *proc, + char *title, + unsigned width, + unsigned height) +{ + processor_state_t *state = proc->state; + state->width = width; + state->height = height; + return(proc_thread_start(proc, &state->input_thread, + proc_input_thread)); +} + +int _zbar_processor_close (zbar_processor_t *proc) +{ + processor_state_t *state = proc->state; + EnterCriticalSection(&state->mutex); + int rc = proc_thread_stop(proc->state, &proc->state->input_thread); + LeaveCriticalSection(&state->mutex); + return(rc); +} + +int _zbar_processor_set_visible (zbar_processor_t *proc, + int visible) +{ + processor_state_t *state = proc->state; + ShowWindow(state->hwnd, (visible) ? SW_SHOWNORMAL : SW_HIDE); + if(visible) + InvalidateRect(state->hwnd, NULL, 0); + else { + EnterCriticalSection(&state->mutex); + if(!(proc->events & EVENT_INPUT)) { + proc->input = err_capture(proc, SEV_WARNING, ZBAR_ERR_CLOSED, + __func__, "user closed display window"); + proc->events |= EVENT_INPUT; + } + proc_notify(proc); + LeaveCriticalSection(&state->mutex); + } + proc->visible = (visible != 0); + /* no error conditions */ + return(0); +} + +int _zbar_processor_set_size (zbar_processor_t *proc, + unsigned width, + unsigned height) +{ + processor_state_t *state = proc->state; + if(!SetWindowPos(state->hwnd, NULL, 0, 0, width, height, + SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOMOVE | + SWP_NOZORDER | SWP_NOREPOSITION)) + return(-1/*FIXME*/); + + return(0); +} + +int _zbar_processor_invalidate (zbar_processor_t *proc) +{ + processor_state_t *state = proc->state; + if(!InvalidateRect(state->hwnd, NULL, 0)) + return(-1/*FIXME*/); + + return(0); +} + +int _zbar_processor_enable (zbar_processor_t *proc, + int active) +{ + return(0); +} diff --git a/zbar/processor/win.h b/zbar/processor/win.h new file mode 100644 index 0000000..6c47fa0 --- /dev/null +++ b/zbar/processor/win.h @@ -0,0 +1,107 @@ +/*------------------------------------------------------------------------ + * Copyright 2007-2009 (c) Jeff Brown + * + * 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 + *------------------------------------------------------------------------*/ +#ifndef _PROCESSOR_WIN_H_ +#define _PROCESSOR_WIN_H_ + +#include + +/* specific notification events */ +typedef struct wait_entry_s { + struct wait_entry_s *next; + HANDLE notify; + DWORD requester; +} wait_entry_t; + +typedef struct wait_queue_s { + wait_entry_t *head, *tail; +} wait_queue_t; + +typedef struct thread_state_s { + int running; + HANDLE activity, started, stopped; +} thread_state_t; + +struct processor_state_s { + HWND hwnd; /* window handle */ + int input; + unsigned width, height; + + CRITICAL_SECTION mutex; /* shared data mutex */ + + int lock_level; /* API serialization lock */ + DWORD lock_owner; + wait_queue_t lock_queue; + wait_queue_t wait_queue; + wait_entry_t *free_entry; + + thread_state_t video_thread; + thread_state_t input_thread; +}; + +static inline wait_entry_t *proc_entry_alloc (processor_state_t *state, + DWORD self) +{ + wait_entry_t *entry = state->free_entry; + if(entry) + state->free_entry = entry->next; + else { + entry = malloc(sizeof(wait_queue_t)); + entry->notify = CreateEvent(NULL, 0, 0, NULL); + } + entry->next = NULL; + entry->requester = self; + return(entry); +} + +static inline void proc_entry_free (processor_state_t *state, + wait_entry_t *entry) +{ + if(entry) { + entry->next = state->free_entry; + state->free_entry = entry; + } +} + +static inline void proc_entry_queue (wait_queue_t *queue, + wait_entry_t *entry) +{ + if(queue->head) + queue->tail->next = entry; + else + queue->head = entry; + queue->tail = entry; +} + +static inline wait_entry_t *proc_entry_dequeue (wait_queue_t *queue) +{ + wait_entry_t *entry = queue->head; + if(entry) { + queue->head = entry->next; + if(!entry->next) + queue->tail = NULL; + entry->next = NULL; + } + return(entry); +} + +#endif diff --git a/zbar/processor/x.c b/zbar/processor/x.c new file mode 100644 index 0000000..cdd9026 --- /dev/null +++ b/zbar/processor/x.c @@ -0,0 +1,261 @@ +/*------------------------------------------------------------------------ + * Copyright 2007-2009 (c) Jeff Brown + * + * 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 "window.h" +#include "processor.h" +#include "posix.h" +#include + +static int x_handle_event (zbar_processor_t *proc) +{ + XEvent ev; + XNextEvent(proc->display, &ev); + + switch(ev.type) { + case Expose: { + /* FIXME ignore when running(?) */ + XExposeEvent *exp = (XExposeEvent*)&ev; + XRectangle r; + Region exposed = XCreateRegion(); + while(1) { + assert(ev.type == Expose); + r.x = exp->x; + r.y = exp->y; + r.width = exp->width; + r.height = exp->height; + XUnionRectWithRegion(&r, exposed, exposed); + + if(!exp->count) + break; + XNextEvent(proc->display, &ev); + } + + proc->window->exposed = exposed; + zbar_window_redraw(proc->window); + proc->window->exposed = 0; + + XDestroyRegion(exposed); + break; + } + + case ConfigureNotify: + zprintf(3, "resized to %d x %d\n", + ev.xconfigure.width, ev.xconfigure.height); + zbar_window_resize(proc->window, + ev.xconfigure.width, ev.xconfigure.height); + _zbar_processor_invalidate(proc); + break; + + case ClientMessage: + if((ev.xclient.message_type == + XInternAtom(proc->display, "WM_PROTOCOLS", 0)) && + ev.xclient.format == 32 && + (ev.xclient.data.l[0] == + XInternAtom(proc->display, "WM_DELETE_WINDOW", 0))) { + zprintf(3, "WM_DELETE_WINDOW\n"); + _zbar_processor_set_visible(proc, 0); + return(err_capture(proc, SEV_WARNING, ZBAR_ERR_CLOSED, __func__, + "user closed display window")); + } + + case KeyPress: { + KeySym key = XLookupKeysym(&ev.xkey, 0); + if((key & 0xff00) == 0xff00) + key &= 0x00ff; + /* FIXME this doesn't really work... */ + return(key & 0xffff); + } + case ButtonPress: + switch(ev.xbutton.button) { + case Button2: return(2); + case Button3: return(3); + case Button4: return(4); + case Button5: return(5); + } + return(1); + + case DestroyNotify: + zbar_window_attach(proc->window, NULL, 0); + proc->xwin = 0; + return(0); + + default: + /* ignored */; + } + return(0); +} + +int _zbar_processor_handle_events (zbar_processor_t *proc, + int block) +{ + int rc = 0; + while(!rc && (block || XPending(proc->display))) { + proc->input = x_handle_event(proc); + rc = proc->input; + } + + switch(rc) { + case 'q': + _zbar_processor_set_visible(proc, 0); + rc = err_capture(proc, SEV_WARNING, ZBAR_ERR_CLOSED, __func__, + "user closed display window"); + break; + + case 'd': { + /* FIXME localtime not threadsafe */ + /* FIXME need ms resolution */ + /*struct tm *t = localtime(time(NULL));*/ + zbar_image_write(proc->window->image, "zbar"); + break; + } + } + + if(rc) + _zbar_processor_notify(proc, EVENT_INPUT); + return(rc); +} + +static int x_connection_handler (zbar_processor_t *proc, + int i) +{ + return(_zbar_processor_handle_events(proc, 0)); +} + +static int x_internal_handler (zbar_processor_t *proc, + int i) +{ + XProcessInternalConnection(proc->display, proc->state->polling.fds[i].fd); + return(_zbar_processor_handle_events(proc, 0)); +} + +static void x_internal_watcher (Display *display, + XPointer client_arg, + int fd, + Bool opening, + XPointer *watch_arg) +{ + zbar_processor_t *proc = (void*)client_arg; + if(opening) + add_poll(proc->state, fd, x_internal_handler); + else + remove_poll(proc->state, fd); +} + +int _zbar_processor_open (zbar_processor_t *proc, + char *title, + unsigned width, + unsigned height) +{ + proc->display = XOpenDisplay(NULL); + if(!proc->display) + return(err_capture_str(proc, SEV_ERROR, ZBAR_ERR_XDISPLAY, __func__, + "unable to open X display", + XDisplayName(NULL))); + + add_poll(proc->state, ConnectionNumber(proc->display), + x_connection_handler); + XAddConnectionWatch(proc->display, x_internal_watcher, (void*)proc); + + int screen = DefaultScreen(proc->display); + XSetWindowAttributes attr; + attr.event_mask = (ExposureMask | StructureNotifyMask | + KeyPressMask | ButtonPressMask); + + proc->xwin = XCreateWindow(proc->display, + RootWindow(proc->display, screen), + 0, 0, width, height, 0, + CopyFromParent, InputOutput, + CopyFromParent, CWEventMask, &attr); + if(!proc->xwin) { + XCloseDisplay(proc->display); + return(err_capture(proc, SEV_ERROR, ZBAR_ERR_XPROTO, __func__, + "creating window")); + } + + XStoreName(proc->display, proc->xwin, title); + + XClassHint *class_hint = XAllocClassHint(); + class_hint->res_name = "zbar"; + class_hint->res_class = "zbar"; + XSetClassHint(proc->display, proc->xwin, class_hint); + XFree(class_hint); + class_hint = NULL; + + Atom wm_delete_window = XInternAtom(proc->display, "WM_DELETE_WINDOW", 0); + if(wm_delete_window) + XSetWMProtocols(proc->display, proc->xwin, &wm_delete_window, 1); + + if(zbar_window_attach(proc->window, proc->display, proc->xwin)) + return(err_copy(proc, proc->window)); + return(0); +} + +int _zbar_processor_close (zbar_processor_t *proc) +{ + if(proc->window) + zbar_window_attach(proc->window, NULL, 0); + + if(proc->display) { + if(proc->xwin) { + XDestroyWindow(proc->display, proc->xwin); + proc->xwin = 0; + } + remove_poll(proc->state, ConnectionNumber(proc->display)); + XCloseDisplay(proc->display); + proc->display = NULL; + } + return(0); +} + +int _zbar_processor_invalidate (zbar_processor_t *proc) +{ + if(!proc->display || !proc->xwin) + return(0); + XClearArea(proc->display, proc->xwin, 0, 0, + proc->window->width, proc->window->height, 1); + XFlush(proc->display); + return(0); +} + +int _zbar_processor_set_size (zbar_processor_t *proc, + unsigned width, + unsigned height) +{ + if(proc->display || !proc->xwin) { + XResizeWindow(proc->display, proc->xwin, width, height); + XFlush(proc->display); + } + return(0); +} + +int _zbar_processor_set_visible (zbar_processor_t *proc, + int visible) +{ + if(visible) + XMapRaised(proc->display, proc->xwin); + else + XUnmapWindow(proc->display, proc->xwin); + XFlush(proc->display); + proc->visible = visible != 0; + return(0); +} diff --git a/zbar/window.c b/zbar/window.c index af7ea88..4cac05b 100644 --- a/zbar/window.c +++ b/zbar/window.c @@ -97,7 +97,7 @@ inline int zbar_window_redraw (zbar_window_t *w) rc = window_draw_overlay(w); } else - _zbar_window_draw_logo(w); + rc = _zbar_window_draw_logo(w); (void)window_unlock(w); return(rc); } diff --git a/zbar/window/vfw.c b/zbar/window/vfw.c index 0eb9b73..6d02086 100644 --- a/zbar/window/vfw.c +++ b/zbar/window/vfw.c @@ -1,150 +1,150 @@ -/*------------------------------------------------------------------------ - * Copyright 2009 (c) Jeff Brown - * - * 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 "window.h" -#include "vfw.h" - -static int -vfw_cleanup (zbar_window_t *w) -{ - if(w->hdd) { - DrawDibClose(w->hdd); - w->hdd = NULL; - } - return(0); -} - -static int -vfw_init (zbar_window_t *w, - zbar_image_t *img, - HDC hdc) -{ - if(w->src_format != img->format && - w->format != img->format) { - _zbar_best_format(img->format, &w->format, w->formats); - if(!w->format) { - err_capture_int(w, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, - "no conversion from %x to supported Xv formats", - img->format); - return(-1); - } - w->src_format = img->format; - - w->bih.biPlanes = 1; - w->bih.biXPelsPerMeter = - 1000L * GetDeviceCaps(hdc, HORZRES) / GetDeviceCaps(hdc, HORZSIZE); - w->bih.biYPelsPerMeter = - 1000L * GetDeviceCaps(hdc, VERTRES) / GetDeviceCaps(hdc, VERTSIZE); - - switch(img->format) { - case fourcc('J','P','E','G'): { - w->bih.biBitCount = 0; - w->bih.biCompression = BI_JPEG; - break; - } - case fourcc('B','G','R','3'): { - w->bih.biBitCount = 24; - w->bih.biCompression = BI_RGB; - break; - } - case fourcc('B','G','R','4'): { - w->bih.biBitCount = 32; - w->bih.biCompression = BI_RGB; - break; - } - default: - assert(0); - /* FIXME PNG? */ - } - w->bih.biSizeImage = img->datalen; - } - - w->bih.biSize = sizeof(w->bih); - w->bih.biWidth = img->width; - w->bih.biHeight = img->height; - w->dst_width = w->width; - w->dst_height = w->height; - - if(!DrawDibBegin(w->hdd, hdc, w->width, w->height, - &w->bih, img->width, img->height, 0)) - return(-1/*FIXME*/); - return(0); -} - -static int -vfw_draw (zbar_window_t *w, - zbar_image_t *img) -{ - HDC hdc = GetDC(w->hwnd); - if(!hdc) - return(-1/*FIXME*/); - - if(((img->format != w->src_format && - img->format != w->format) || - img->width != w->bih.biWidth || - img->height != w->bih.biHeight || - w->width != w->dst_width || - w->height != w->dst_height) && - vfw_init(w, img, hdc)) - return(-1); - - if(img->format != w->format) { - w->image = zbar_image_convert(img, w->format); - zbar_image_destroy(img); - img = w->image; - } - - zprintf(24, "DrawDibDraw(%dx%d -> %dx%d)\n", - img->width, img->height, w->width, w->height); - DrawDibDraw(w->hdd, hdc, - 0, 0, w->width, w->height, - &w->bih, (void*)img->data, - 0, 0, img->width, img->height, - DDF_SAME_DRAW); - ValidateRect(w->hwnd, NULL); - return(0); -} - -static uint32_t vfw_formats[] = { - fourcc('B','G','R','3'), - fourcc('B','G','R','4'), - fourcc('J','P','E','G'), - 0 -}; - -int -_zbar_window_vfw_init (zbar_window_t *w) -{ - w->hdd = DrawDibOpen(); - if(!w->hdd) - return(err_capture(w, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, - "unable to initialize DrawDib")); - - uint32_t *fmt; - for(fmt = vfw_formats; *fmt; fmt++) - _zbar_window_add_format(w, *fmt); - - w->draw_image = vfw_draw; - w->cleanup = vfw_cleanup; - return(0); -} +/*------------------------------------------------------------------------ + * Copyright 2009 (c) Jeff Brown + * + * 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 "window.h" +#include "vfw.h" + +static int +vfw_cleanup (zbar_window_t *w) +{ + if(w->hdd) { + DrawDibClose(w->hdd); + w->hdd = NULL; + } + return(0); +} + +static int +vfw_init (zbar_window_t *w, + zbar_image_t *img, + HDC hdc) +{ + if(w->src_format != img->format && + w->format != img->format) { + _zbar_best_format(img->format, &w->format, w->formats); + if(!w->format) { + err_capture_int(w, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, + "no conversion from %x to supported Xv formats", + img->format); + return(-1); + } + w->src_format = img->format; + + w->bih.biPlanes = 1; + w->bih.biXPelsPerMeter = + 1000L * GetDeviceCaps(hdc, HORZRES) / GetDeviceCaps(hdc, HORZSIZE); + w->bih.biYPelsPerMeter = + 1000L * GetDeviceCaps(hdc, VERTRES) / GetDeviceCaps(hdc, VERTSIZE); + + switch(w->format) { + case fourcc('J','P','E','G'): { + w->bih.biBitCount = 0; + w->bih.biCompression = BI_JPEG; + break; + } + case fourcc('B','G','R','3'): { + w->bih.biBitCount = 24; + w->bih.biCompression = BI_RGB; + break; + } + case fourcc('B','G','R','4'): { + w->bih.biBitCount = 32; + w->bih.biCompression = BI_RGB; + break; + } + default: + assert(0); + /* FIXME PNG? */ + } + w->bih.biSizeImage = img->datalen; + } + + w->bih.biSize = sizeof(w->bih); + w->bih.biWidth = img->width; + w->bih.biHeight = img->height; + w->dst_width = w->width; + w->dst_height = w->height; + + if(!DrawDibBegin(w->hdd, hdc, w->width, w->height, + &w->bih, img->width, img->height, 0)) + return(-1/*FIXME*/); + return(0); +} + +static int +vfw_draw (zbar_window_t *w, + zbar_image_t *img) +{ + HDC hdc = GetDC(w->hwnd); + if(!hdc) + return(-1/*FIXME*/); + + if(((img->format != w->src_format && + img->format != w->format) || + img->width != w->bih.biWidth || + img->height != w->bih.biHeight || + w->width != w->dst_width || + w->height != w->dst_height) && + vfw_init(w, img, hdc)) + return(-1); + + if(img->format != w->format) { + w->image = zbar_image_convert(img, w->format); + zbar_image_destroy(img); + img = w->image; + } + + zprintf(24, "DrawDibDraw(%dx%d -> %dx%d)\n", + img->width, img->height, w->width, w->height); + DrawDibDraw(w->hdd, hdc, + 0, 0, w->width, w->height, + &w->bih, (void*)img->data, + 0, 0, img->width, img->height, + DDF_SAME_DRAW); + ValidateRect(w->hwnd, NULL); + return(0); +} + +static uint32_t vfw_formats[] = { + fourcc('B','G','R','3'), + fourcc('B','G','R','4'), + fourcc('J','P','E','G'), + 0 +}; + +int +_zbar_window_vfw_init (zbar_window_t *w) +{ + w->hdd = DrawDibOpen(); + if(!w->hdd) + return(err_capture(w, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, + "unable to initialize DrawDib")); + + uint32_t *fmt; + for(fmt = vfw_formats; *fmt; fmt++) + _zbar_window_add_format(w, *fmt); + + w->draw_image = vfw_draw; + w->cleanup = vfw_cleanup; + return(0); +} diff --git a/zbar/window/win.c b/zbar/window/win.c index 23abac7..1dea9e3 100644 --- a/zbar/window/win.c +++ b/zbar/window/win.c @@ -1,363 +1,162 @@ -/*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown - * - * 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 "window.h" -#include "processor.h" - -int _zbar_window_vfw_init(zbar_window_t *w); - -static LRESULT CALLBACK -proc_handle_event (HWND hwnd, - UINT message, - WPARAM wparam, - LPARAM lparam) -{ - zbar_processor_t *proc = - (zbar_processor_t*)GetWindowLongPtr(hwnd, GWL_USERDATA); - - switch(message) { - - case WM_NCCREATE: - proc = ((LPCREATESTRUCT)lparam)->lpCreateParams; - SetWindowLongPtr(hwnd, GWL_USERDATA, (LONG_PTR)proc); - proc->display = hwnd; - break; - - case WM_SIZE: { - RECT r; - GetClientRect(hwnd, &r); - assert(proc); - zbar_window_resize(proc->window, r.right, r.bottom); - return(0); - } - - case WM_PAINT: { - PAINTSTRUCT ps; - zbar_window_redraw(proc->window); - EndPaint(hwnd, &ps); - return(0); - } - - case WM_CHAR: { - proc->input = wparam; - return(0); - } - - case WM_LBUTTONDOWN: { - proc->input = 1; - return(0); - } - - case WM_MBUTTONDOWN: { - proc->input = 2; - return(0); - } - - case WM_RBUTTONDOWN: { - proc->input = 3; - return(0); - } - - case WM_DESTROY: - zprintf(1, "DESTROY\n"); - proc->display = NULL; - _zbar_window_attach(proc->window, NULL, 0); - PostQuitMessage(0); - return(0); - } - return(DefWindowProc(hwnd, message, wparam, lparam)); -} - -static inline ATOM -proc_register_class (HINSTANCE hmod) -{ - BYTE and_mask[1] = { 0xff }; - BYTE xor_mask[1] = { 0x00 }; - - WNDCLASSEX wc = { sizeof(WNDCLASSEX), 0, }; - wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); - wc.hInstance = hmod; - wc.lpfnWndProc = proc_handle_event; - wc.lpszClassName = "_ZBar Class"; - wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; - wc.hCursor = CreateCursor(hmod, 0, 0, 1, 1, and_mask, xor_mask); - - return(RegisterClassEx(&wc)); -} - -int -_zbar_window_open (zbar_processor_t *proc, - char *title, - unsigned width, - unsigned height) -{ - HMODULE hmod = NULL; - if(!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | - GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, - (void*)_zbar_window_open, (HINSTANCE*)&hmod)) { - proc->err.errnum = GetLastError(); - return(err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, - "failed to obtain module handle")); - } - zprintf(1, "hmod=%p\n", hmod); - - ATOM wca = proc_register_class(hmod); - zprintf(1, "wca=%x\n", wca); - if(!wca) { - proc->err.errnum = GetLastError(); - return(err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, - "failed to register window class")); - } - - DWORD style = WS_OVERLAPPEDWINDOW; - DWORD exstyle = (WS_EX_APPWINDOW | - WS_EX_OVERLAPPEDWINDOW /*| - WS_EX_ACCEPTFILES*/); - - proc->display = CreateWindowEx(exstyle, (LPCTSTR)(long)wca, "ZBar", style, - CW_USEDEFAULT, CW_USEDEFAULT, width, height, - NULL, NULL, hmod, proc); - if(!proc->display) { - proc->err.errnum = GetLastError(); - return(err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, - "failed to open window")); - } - - return(0); -} - -int _zbar_window_close (zbar_processor_t *proc) -{ - if(proc->display) { - DestroyWindow(proc->display); - proc->display = NULL; - } - return(0); -} - -int -_zbar_window_set_visible (zbar_processor_t *proc, - int visible) -{ - zprintf(1, "\n"); - ShowWindow(proc->display, (visible) ? SW_SHOWNORMAL : SW_HIDE); - if(visible) - UpdateWindow(proc->display); - proc->visible = (visible != 0); - /* no error conditions */ - return(0); -} - -int _zbar_window_invalidate (zbar_window_t *w) -{ - if(!InvalidateRect(w->hwnd, NULL, 0)) - return(-1/*FIXME*/); - - return(0); -} - -int -_zbar_window_handle_events (zbar_processor_t *proc, - int block) -{ - MSG msg; - proc->input = 0; - while(!proc->input) { - int rc = 0; - if(proc->display) { - if(block) - rc = GetMessage(&msg, proc->display, 0, 0); - else { - rc = PeekMessage(&msg, proc->display, 0, 0, - PM_NOYIELD | PM_REMOVE); - if(!rc) - break; - } - /*zprintf(1, "rc=%d blk=%d msg=%d\n", rc, block, msg.message);*/ - if(rc < 0) { - proc->err.errnum = GetLastError(); - return(err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, - "failed to obtain event")); - } - } - - if(!rc || msg.message == WM_QUIT) { - zprintf(1, "QUIT\n"); - _zbar_window_set_visible(proc, 0); - return(err_capture(proc, SEV_WARNING, ZBAR_ERR_CLOSED, __func__, - "user closed display window")); - } - - TranslateMessage(&msg); - DispatchMessage(&msg); - } - return(proc->input); -} - -int -_zbar_window_draw_marker(zbar_window_t *w, - uint32_t rgb, - const point_t *p) -{ - return(-1); -} - -int _zbar_window_set_size (zbar_processor_t *proc, - unsigned width, - unsigned height) -{ - if(!SetWindowPos(proc->display, NULL, 0, 0, width, height, - SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOMOVE | - SWP_NOZORDER | SWP_NOREPOSITION)) - return(-1/*FIXME*/); - - return(0); -} - -int -_zbar_window_resize (zbar_window_t *w) -{ - int lbw; - if(w->height * 8 / 10 <= w->width) - lbw = w->height / 36; - else - lbw = w->width * 5 / 144; - if(lbw < 1) - lbw = 1; - w->logo_scale = lbw; - if(w->logo_zbars) { - DeleteObject(w->logo_zbars); - w->logo_zbars = NULL; - } - if(w->logo_zpen) - DeleteObject(w->logo_zpen); - if(w->logo_zbpen) - DeleteObject(w->logo_zbpen); - - LOGBRUSH lb = { 0, }; - lb.lbStyle = BS_SOLID; - lb.lbColor = RGB(0xd7, 0x33, 0x33); - w->logo_zpen = ExtCreatePen(PS_GEOMETRIC | PS_SOLID | - PS_ENDCAP_ROUND | PS_JOIN_ROUND, - lbw * 2, &lb, 0, NULL); - - lb.lbColor = RGB(0xa4, 0x00, 0x00); - w->logo_zbpen = ExtCreatePen(PS_GEOMETRIC | PS_SOLID | - PS_ENDCAP_ROUND | PS_JOIN_ROUND, - lbw * 2, &lb, 0, NULL); - - int x0 = w->width / 2; - int y0 = w->height / 2; - int by0 = y0 - 54 * lbw / 5; - int bh = 108 * lbw / 5; - - static const int bx[5] = { -6, -3, -1, 2, 5 }; - static const int bw[5] = { 1, 1, 2, 2, 1 }; - - int i; - for(i = 0; i < 5; i++) { - int x = x0 + lbw * bx[i]; - HRGN bar = CreateRectRgn(x, by0, - x + lbw * bw[i], by0 + bh); - if(w->logo_zbars) { - CombineRgn(w->logo_zbars, w->logo_zbars, bar, RGN_OR); - DeleteObject(bar); - } - else - w->logo_zbars = bar; - } - - static const int zx[4] = { -7, 7, -7, 7 }; - static const int zy[4] = { -8, -8, 8, 8 }; - - for(i = 0; i < 4; i++) { - w->logo_z[i].x = x0 + lbw * zx[i]; - w->logo_z[i].y = y0 + lbw * zy[i]; - } - return(0); -} - -int -_zbar_window_attach (zbar_window_t *w, - void *display, - unsigned long win) -{ - zprintf(1, "\n"); - if(w->hwnd) { - /* FIXME cleanup existing resources */ - w->hwnd = NULL; - } - - if(!display) - return(0); - - w->hwnd = display; - - return(_zbar_window_vfw_init(w)); -} - -int -_zbar_window_clear (zbar_window_t *w) -{ - HDC hdc = GetDC(w->hwnd); - if(!hdc) - return(-1/*FIXME*/); - - RECT r = { 0, 0, w->width, w->height }; - FillRect(hdc, &r, GetStockObject(BLACK_BRUSH)); - - ReleaseDC(w->hwnd, hdc); - ValidateRect(w->hwnd, NULL); - return(0); -} - -int -_zbar_window_draw_logo (zbar_window_t *w) -{ - HDC hdc = GetDC(w->hwnd); - if(!hdc || !SaveDC(hdc)) - return(-1/*FIXME*/); - - HRGN rgn = CreateRectRgn(0, 0, 0, 0); - GetUpdateRgn(w->hwnd, rgn, 0); - SelectClipRgn(hdc, rgn); - - SetRectRgn(rgn, 0, 0, w->width, w->height); - CombineRgn(rgn, rgn, w->logo_zbars, RGN_DIFF); - FillRgn(hdc, rgn, GetStockObject(WHITE_BRUSH)); - DeleteObject(rgn); - - FillRgn(hdc, w->logo_zbars, GetStockObject(BLACK_BRUSH)); - - SelectObject(hdc, w->logo_zpen); - Polyline(hdc, w->logo_z, 4); - - ExtSelectClipRgn(hdc, w->logo_zbars, RGN_AND); - SelectObject(hdc, w->logo_zbpen); - Polyline(hdc, w->logo_z, 4); - - RestoreDC(hdc, -1); - ReleaseDC(w->hwnd, hdc); - ValidateRect(w->hwnd, NULL); - return(0); -} +/*------------------------------------------------------------------------ + * Copyright 2007-2009 (c) Jeff Brown + * + * 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 "window.h" + +int _zbar_window_vfw_init(zbar_window_t *w); + +int +_zbar_window_draw_marker(zbar_window_t *w, + uint32_t rgb, + const point_t *p) +{ + return(-1); +} + +int +_zbar_window_resize (zbar_window_t *w) +{ + int lbw; + if(w->height * 8 / 10 <= w->width) + lbw = w->height / 36; + else + lbw = w->width * 5 / 144; + if(lbw < 1) + lbw = 1; + w->logo_scale = lbw; + zprintf(7, "%dx%d scale=%d\n", w->width, w->height, lbw); + if(w->logo_zbars) { + DeleteObject(w->logo_zbars); + w->logo_zbars = NULL; + } + if(w->logo_zpen) + DeleteObject(w->logo_zpen); + if(w->logo_zbpen) + DeleteObject(w->logo_zbpen); + + LOGBRUSH lb = { 0, }; + lb.lbStyle = BS_SOLID; + lb.lbColor = RGB(0xd7, 0x33, 0x33); + w->logo_zpen = ExtCreatePen(PS_GEOMETRIC | PS_SOLID | + PS_ENDCAP_ROUND | PS_JOIN_ROUND, + lbw * 2, &lb, 0, NULL); + + lb.lbColor = RGB(0xa4, 0x00, 0x00); + w->logo_zbpen = ExtCreatePen(PS_GEOMETRIC | PS_SOLID | + PS_ENDCAP_ROUND | PS_JOIN_ROUND, + lbw * 2, &lb, 0, NULL); + + int x0 = w->width / 2; + int y0 = w->height / 2; + int by0 = y0 - 54 * lbw / 5; + int bh = 108 * lbw / 5; + + static const int bx[5] = { -6, -3, -1, 2, 5 }; + static const int bw[5] = { 1, 1, 2, 2, 1 }; + + int i; + for(i = 0; i < 5; i++) { + int x = x0 + lbw * bx[i]; + HRGN bar = CreateRectRgn(x, by0, + x + lbw * bw[i], by0 + bh); + if(w->logo_zbars) { + CombineRgn(w->logo_zbars, w->logo_zbars, bar, RGN_OR); + DeleteObject(bar); + } + else + w->logo_zbars = bar; + } + + static const int zx[4] = { -7, 7, -7, 7 }; + static const int zy[4] = { -8, -8, 8, 8 }; + + for(i = 0; i < 4; i++) { + w->logo_z[i].x = x0 + lbw * zx[i]; + w->logo_z[i].y = y0 + lbw * zy[i]; + } + return(0); +} + +int +_zbar_window_attach (zbar_window_t *w, + void *display, + unsigned long win) +{ + if(w->hwnd) { + /* FIXME cleanup existing resources */ + w->hwnd = NULL; + } + + if(!display) + return(0); + + w->hwnd = display; + + return(_zbar_window_vfw_init(w)); +} + +int +_zbar_window_clear (zbar_window_t *w) +{ + HDC hdc = GetDC(w->hwnd); + if(!hdc) + return(-1/*FIXME*/); + + RECT r = { 0, 0, w->width, w->height }; + FillRect(hdc, &r, GetStockObject(BLACK_BRUSH)); + + ReleaseDC(w->hwnd, hdc); + ValidateRect(w->hwnd, NULL); + return(0); +} + +int +_zbar_window_draw_logo (zbar_window_t *w) +{ + if(!w->hwnd) + return(-1); + + HDC hdc = GetDC(w->hwnd); + if(!hdc || !SaveDC(hdc)) + return(-1/*FIXME*/); + + /* FIXME buffer offscreen */ + HRGN rgn = CreateRectRgn(0, 0, w->width, w->height); + CombineRgn(rgn, rgn, w->logo_zbars, RGN_DIFF); + FillRgn(hdc, rgn, GetStockObject(WHITE_BRUSH)); + DeleteObject(rgn); + + FillRgn(hdc, w->logo_zbars, GetStockObject(BLACK_BRUSH)); + + SelectObject(hdc, w->logo_zpen); + Polyline(hdc, w->logo_z, 4); + + ExtSelectClipRgn(hdc, w->logo_zbars, RGN_AND); + SelectObject(hdc, w->logo_zbpen); + Polyline(hdc, w->logo_z, 4); + + RestoreDC(hdc, -1); + ReleaseDC(w->hwnd, hdc); + ValidateRect(w->hwnd, NULL); + return(0); +} diff --git a/zbar/window/x.c b/zbar/window/x.c index 14e91a8..f7c99ad 100644 --- a/zbar/window/x.c +++ b/zbar/window/x.c @@ -22,8 +22,6 @@ *------------------------------------------------------------------------*/ #include "window.h" -#include "processor.h" -#include extern int _zbar_window_probe_ximage(zbar_window_t*); extern int _zbar_window_probe_xshm(zbar_window_t*); @@ -164,228 +162,6 @@ int _zbar_window_attach (zbar_window_t *w, return(_zbar_window_probe_ximage(w)); } -static int x_handle_event (zbar_processor_t *proc) -{ - XEvent ev; - XNextEvent(proc->display, &ev); - - switch(ev.type) { - case Expose: { - /* FIXME ignore when running(?) */ - XExposeEvent *exp = (XExposeEvent*)&ev; - XRectangle r; - Region exposed = XCreateRegion(); - while(1) { - assert(ev.type == Expose); - r.x = exp->x; - r.y = exp->y; - r.width = exp->width; - r.height = exp->height; - XUnionRectWithRegion(&r, exposed, exposed); - - if(!exp->count) - break; - XNextEvent(proc->display, &ev); - } - - proc->window->exposed = exposed; - zbar_window_redraw(proc->window); - proc->window->exposed = 0; - - XDestroyRegion(exposed); - break; - } - - case ConfigureNotify: - zprintf(3, "resized to %d x %d\n", - ev.xconfigure.width, ev.xconfigure.height); - zbar_window_resize(proc->window, - ev.xconfigure.width, ev.xconfigure.height); - break; - - case ClientMessage: - if((ev.xclient.message_type == - XInternAtom(proc->display, "WM_PROTOCOLS", 0)) && - ev.xclient.format == 32 && - (ev.xclient.data.l[0] == - XInternAtom(proc->display, "WM_DELETE_WINDOW", 0))) { - zprintf(3, "WM_DELETE_WINDOW\n"); - _zbar_window_set_visible(proc, 0); - return(err_capture(proc, SEV_WARNING, ZBAR_ERR_CLOSED, __func__, - "user closed display window")); - } - - case KeyPress: { - KeySym key = XLookupKeysym(&ev.xkey, 0); - if((key & 0xff00) == 0xff00) - key &= 0x00ff; - /* FIXME this doesn't really work... */ - return(key & 0xffff); - } - case ButtonPress: - switch(ev.xbutton.button) { - case Button2: return(2); - case Button3: return(3); - case Button4: return(4); - case Button5: return(5); - } - return(1); - - default: - /* ignored */; - } - return(0); -} - -int _zbar_window_handle_events (zbar_processor_t *proc, - int block) -{ - int rc = 0; - while(!rc && (block || XPending(proc->display))) { - proc->input = x_handle_event(proc); - rc = proc->input; - } - - switch(rc) { - case 'q': - _zbar_window_set_visible(proc, 0); - rc = err_capture(proc, SEV_WARNING, ZBAR_ERR_CLOSED, __func__, - "user closed display window"); - break; - - case 'd': { - /* FIXME localtime not threadsafe */ - /* FIXME need ms resolution */ - /*struct tm *t = localtime(time(NULL));*/ - zbar_image_write(proc->window->image, "zbar"); - break; - } - } - - if(rc) - emit(proc, EVENT_INPUT); - return(rc); -} - -static int x_connection_handler (zbar_processor_t *proc, - int i) -{ - return(_zbar_window_handle_events(proc, 0)); -} - -static int x_internal_handler (zbar_processor_t *proc, - int i) -{ - XProcessInternalConnection(proc->display, proc->polling.fds[i].fd); - return(_zbar_window_handle_events(proc, 0)); -} - -static void x_internal_watcher (Display *display, - XPointer client_arg, - int fd, - Bool opening, - XPointer *watch_arg) -{ - zbar_processor_t *proc = (void*)client_arg; - if(opening) - add_poll(proc, fd, x_internal_handler); - else - remove_poll(proc, fd); -} - -int _zbar_window_open (zbar_processor_t *proc, - char *title, - unsigned width, - unsigned height) -{ - proc->display = XOpenDisplay(NULL); - if(!proc->display) - return(err_capture_str(proc, SEV_ERROR, ZBAR_ERR_XDISPLAY, __func__, - "unable to open X display", - XDisplayName(NULL))); - - add_poll(proc, ConnectionNumber(proc->display), x_connection_handler); - XAddConnectionWatch(proc->display, x_internal_watcher, (void*)proc); - - int screen = DefaultScreen(proc->display); - XSetWindowAttributes attr; - attr.event_mask = (ExposureMask | StructureNotifyMask | - KeyPressMask | ButtonPressMask); - - proc->xwin = XCreateWindow(proc->display, - RootWindow(proc->display, screen), - 0, 0, width, height, 0, - CopyFromParent, InputOutput, - CopyFromParent, CWEventMask, &attr); - if(!proc->xwin) { - XCloseDisplay(proc->display); - return(err_capture(proc, SEV_ERROR, ZBAR_ERR_XPROTO, __func__, - "creating window")); - } - - XStoreName(proc->display, proc->xwin, title); - - XClassHint *class_hint = XAllocClassHint(); - class_hint->res_name = "zbar"; - class_hint->res_class = "zbar"; - XSetClassHint(proc->display, proc->xwin, class_hint); - XFree(class_hint); - class_hint = NULL; - - Atom wm_delete_window = XInternAtom(proc->display, "WM_DELETE_WINDOW", 0); - if(wm_delete_window) - XSetWMProtocols(proc->display, proc->xwin, &wm_delete_window, 1); - - return(0); -} - -int _zbar_window_close (zbar_processor_t *proc) -{ - if(proc->display) { - if(proc->xwin) { - XDestroyWindow(proc->display, proc->xwin); - proc->xwin = 0; - } - remove_poll(proc, ConnectionNumber(proc->display)); - XCloseDisplay(proc->display); - proc->display = NULL; - } - return(0); -} - -int _zbar_window_set_size (zbar_processor_t *proc, - unsigned width, - unsigned height) -{ - if(proc->display) { - XResizeWindow(proc->display, proc->xwin, width, height); - _zbar_window_clear(proc->window); - XFlush(proc->display); - } - return(0); -} - -int _zbar_window_set_visible (zbar_processor_t *proc, - int visible) -{ - if(visible) - XMapRaised(proc->display, proc->xwin); - else - XUnmapWindow(proc->display, proc->xwin); - XFlush(proc->display); - proc->visible = visible != 0; - return(0); -} - -int _zbar_window_invalidate (zbar_window_t *w) -{ - if(!w->display) - return(0); - XClearArea(w->display, w->xwin, 0, 0, w->width, w->height, 1); - XFlush(w->display); - return(0); -} - int _zbar_window_clear (zbar_window_t *w) { if(!w->display) From 2a0d17d1c2e4074b837d3509495cf206c8e104af Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 16 Jun 2009 12:43:01 -0400 Subject: [PATCH 097/328] convert zbarimg to C (cross compiled C++ cannot run w/native libraries) - fix DrawDib image width granularity - fix window resize dimensions to include decorations - images still inverted, otherwise zbarimg now "working" in windows --- ChangeLog | 4 + Makefile.am | 1 + configure.ac | 12 +- test/Makefile.am.inc | 2 +- zbar/processor/win.c | 32 ++-- zbar/window/vfw.c | 21 ++- zbarimg/Makefile.am.inc | 2 +- zbarimg/zbarimg.c | 378 ++++++++++++++++++++++++++++++++++++++++ zbarimg/zbarimg.cpp | 338 ----------------------------------- 9 files changed, 428 insertions(+), 362 deletions(-) create mode 100644 zbarimg/zbarimg.c delete mode 100644 zbarimg/zbarimg.cpp diff --git a/ChangeLog b/ChangeLog index 9287370..deb6c87 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,8 @@ current: + * convert zbarimg to C (cross compiled C++ cannot run w/native libraries) + - fix DrawDib image width granularity + - fix window resize dimensions to include decorations + - images still inverted, otherwise zbarimg now "working" in windows * refactor processor implementation to support cross-platform - first pass windows processor (before debugging) - make processor locks reentrant (call APIs from callback) diff --git a/Makefile.am b/Makefile.am index 6b0ee0a..a429e36 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,6 +4,7 @@ AM_CXXFLAGS = $(AM_CFLAGS) ACLOCAL_AMFLAGS = -I config bin_PROGRAMS = check_PROGRAMS = +EXTRA_PROGRAMS = lib_LTLIBRARIES = pyexec_LTLIBRARIES = CLEANFILES = diff --git a/configure.ac b/configure.ac index 9cd56a9..7741c7e 100644 --- a/configure.ac +++ b/configure.ac @@ -242,20 +242,18 @@ AC_ARG_WITH([imagemagick], [with_imagemagick="yes"]) AS_IF([test "x$with_imagemagick" != "xno"], - [PKG_CHECK_MODULES([MAGICK], [ImageMagick++ >= 6.2.6]) - MAGICK_VERSION=`$PKG_CONFIG ImageMagick++ --modversion` + [PKG_CHECK_MODULES([MAGICK], [MagickWand >= 6.2.6]) + MAGICK_VERSION=`$PKG_CONFIG MagickWand --modversion` AC_MSG_NOTICE([using ImageMagick version $MAGICK_VERSION]) dnl double check ImageMagick install (bug #2582232) - AC_LANG_PUSH([C++]) CPPFLAGS_save="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $MAGICK_CFLAGS" - AC_CHECK_HEADER([Magick++.h], [], - [AC_MSG_FAILURE([ImageMagick++ package found but Magick++.h not installed?! + 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" - AC_LANG_POP([C++])]) + CPPFLAGS="$CPPFLAGS_save"]) AM_CONDITIONAL([HAVE_MAGICK], [test "x$with_imagemagick" = "xyes"]) diff --git a/test/Makefile.am.inc b/test/Makefile.am.inc index 261797d..ccab8bb 100644 --- a/test/Makefile.am.inc +++ b/test/Makefile.am.inc @@ -33,7 +33,7 @@ test_test_jpeg_LDADD = zbar/libzbar.la $(AM_LDADD) endif if HAVE_MAGICK -check_PROGRAMS += test/dbg_scan +EXTRA_PROGRAMS += test/dbg_scan test_dbg_scan_SOURCES = test/dbg_scan.cpp test_dbg_scan_CPPFLAGS = $(MAGICK_CFLAGS) $(AM_CPPFLAGS) test_dbg_scan_LDADD = $(MAGICK_LIBS) zbar/libzbar.la $(AM_LDADD) diff --git a/zbar/processor/win.c b/zbar/processor/win.c index 580fff5..4441873 100644 --- a/zbar/processor/win.c +++ b/zbar/processor/win.c @@ -25,6 +25,13 @@ #include "win.h" #include +#define WIN_STYLE (WS_CAPTION | \ + WS_SYSMENU | \ + WS_THICKFRAME | \ + WS_MINIMIZEBOX | \ + WS_MAXIMIZEBOX) +#define EXT_STYLE (WS_EX_APPWINDOW | WS_EX_OVERLAPPEDWINDOW) + static inline int proc_lock (processor_state_t *state, DWORD self) { @@ -359,7 +366,7 @@ static LRESULT CALLBACK proc_handle_event (HWND hwnd, case WM_SIZE: { RECT r; GetClientRect(hwnd, &r); - zprintf(3, "WM_SIZE %dx%d\n", r.right, r.bottom); + zprintf(3, "WM_SIZE %ldx%ld\n", r.right, r.bottom); assert(proc); zbar_window_resize(proc->window, r.right, r.bottom); InvalidateRect(hwnd, NULL, 0); @@ -481,13 +488,12 @@ static inline int proc_open (zbar_processor_t *proc, "failed to register window class")); } - DWORD style = WS_OVERLAPPEDWINDOW; - DWORD exstyle = (WS_EX_APPWINDOW | - WS_EX_OVERLAPPEDWINDOW /*| - WS_EX_ACCEPTFILES*/); - - state->hwnd = CreateWindowEx(exstyle, (LPCTSTR)(long)wca, "ZBar", style, - CW_USEDEFAULT, CW_USEDEFAULT, width, height, + RECT r = { 0, 0, width, height }; + AdjustWindowRectEx(&r, WIN_STYLE, 0, EXT_STYLE); + state->hwnd = CreateWindowEx(EXT_STYLE, (LPCTSTR)(long)wca, + "ZBar", WIN_STYLE, + CW_USEDEFAULT, CW_USEDEFAULT, + r.right - r.left, r.bottom - r.top, NULL, NULL, hmod, proc); if(!state->hwnd) { @@ -583,9 +589,15 @@ int _zbar_processor_set_size (zbar_processor_t *proc, unsigned width, unsigned height) { + RECT r = { 0, 0, width, height }; processor_state_t *state = proc->state; - if(!SetWindowPos(state->hwnd, NULL, 0, 0, width, height, - SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOMOVE | + int rc = AdjustWindowRectEx(&r, GetWindowLong(state->hwnd, GWL_STYLE), + 0, GetWindowLong(state->hwnd, GWL_EXSTYLE)); + zprintf(5, "%dx%d %ld,%ld-%ld,%ld (%d)\n", width, height, + r.left, r.top, r.right, r.bottom, rc); + if(!SetWindowPos(state->hwnd, NULL, + 0, 0, r.right - r.left, r.bottom - r.top, + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOREPOSITION)) return(-1/*FIXME*/); diff --git a/zbar/window/vfw.c b/zbar/window/vfw.c index 6d02086..f512578 100644 --- a/zbar/window/vfw.c +++ b/zbar/window/vfw.c @@ -77,17 +77,23 @@ vfw_init (zbar_window_t *w, /* FIXME PNG? */ } w->bih.biSizeImage = img->datalen; + zprintf(20, "%.4s(%08x)%dx%d->%.4s(%08x) ppm=%ldx%ld comp=%d bpp=%d\n", + (char*)&img->format, img->format, img->width, img->height, + (char*)&w->format, w->format, + w->bih.biXPelsPerMeter, w->bih.biYPelsPerMeter, + (int)w->bih.biCompression, w->bih.biBitCount); } w->bih.biSize = sizeof(w->bih); - w->bih.biWidth = img->width; + w->bih.biWidth = (img->width + 3) & ~3; w->bih.biHeight = img->height; w->dst_width = w->width; w->dst_height = w->height; if(!DrawDibBegin(w->hdd, hdc, w->width, w->height, - &w->bih, img->width, img->height, 0)) + &w->bih, w->bih.biWidth, w->bih.biHeight, 0)) return(-1/*FIXME*/); + zprintf(24, "out=%ldx%ld\n", w->bih.biWidth, w->bih.biHeight); return(0); } @@ -99,23 +105,28 @@ vfw_draw (zbar_window_t *w, if(!hdc) return(-1/*FIXME*/); + int width = (img->width + 3) & ~3; + if(((img->format != w->src_format && img->format != w->format) || - img->width != w->bih.biWidth || + width != w->bih.biWidth || img->height != w->bih.biHeight || w->width != w->dst_width || w->height != w->dst_height) && vfw_init(w, img, hdc)) return(-1); - if(img->format != w->format) { - w->image = zbar_image_convert(img, w->format); + if(img->format != w->format || + img->width != width) { + w->image = zbar_image_convert_resize(img, w->format, + width, img->height); zbar_image_destroy(img); img = w->image; } zprintf(24, "DrawDibDraw(%dx%d -> %dx%d)\n", img->width, img->height, w->width, w->height); + DrawDibDraw(w->hdd, hdc, 0, 0, w->width, w->height, &w->bih, (void*)img->data, diff --git a/zbarimg/Makefile.am.inc b/zbarimg/Makefile.am.inc index 45041f9..520b077 100644 --- a/zbarimg/Makefile.am.inc +++ b/zbarimg/Makefile.am.inc @@ -1,5 +1,5 @@ bin_PROGRAMS += zbarimg/zbarimg -zbarimg_zbarimg_SOURCES = zbarimg/zbarimg.cpp +zbarimg_zbarimg_SOURCES = zbarimg/zbarimg.c zbarimg_zbarimg_CPPFLAGS = $(MAGICK_CFLAGS) $(AM_CPPFLAGS) zbarimg_zbarimg_LDADD = $(MAGICK_LIBS) zbar/libzbar.la # automake bug in "monolithic mode"? diff --git a/zbarimg/zbarimg.c b/zbarimg/zbarimg.c new file mode 100644 index 0000000..a41f86f --- /dev/null +++ b/zbarimg/zbarimg.c @@ -0,0 +1,378 @@ +/*------------------------------------------------------------------------ + * Copyright 2007-2009 (c) Jeff Brown + * + * 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 +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_SYS_TIMES_H +# include +#endif +#include + +#include +#include + +static const char *note_usage = + "usage: zbarimg [options] ...\n" + "\n" + "scan and decode bar codes from one or more image files\n" + "\n" + "options:\n" + " -h, --help display this help text\n" + " --version display version information and exit\n" + " -q, --quiet minimal output, only print decoded symbol data\n" + " -v, --verbose increase debug output level\n" + " --verbose=N set specific debug output level\n" + " -d, --display enable display of following images to the screen\n" + " -D, --nodisplay disable display of following images (default)\n" + " --xml, --noxml enable/disable XML output format\n" + " -S[=], --set [=]\n" + " set decoder/scanner to (or 1)\n" + // FIXME overlay level + "\n" + ; + +static const char *warning_not_found = + "\n" + "WARNING: barcode data was not detected in some image(s)\n" + " things to check:\n" + " - is the barcode type supported?" + " currently supported symbologies are:\n" + " EAN/UPC (EAN-13, EAN-8, UPC-A, UPC-E, ISBN-10, ISBN-13),\n" + " Code 128, Code 39 and Interleaved 2 of 5\n" + " - is the barcode large enough in the image?\n" + " - is the barcode mostly in focus?\n" + " - is there sufficient contrast/illumination?\n" + "\n"; + +static const char *xml_head = + "\n"; +static const char *xml_foot = + "\n"; + +static int notfound = 0, exit_code = 0; +static int num_images = 0, num_symbols = 0; +static int xmllvl = 0; + +char *xmlbuf = NULL; +unsigned xmlbuflen = 0; + +static zbar_processor_t *processor = NULL; + +static void cleanup_blob (zbar_image_t *img) +{ + MagickRelinquishMemory((void*)zbar_image_get_data(img)); +} + +static inline int dump_error(MagickWand *wand) +{ + char *desc; + ExceptionType severity; + desc = MagickGetException(wand, &severity); + + if(severity >= FatalErrorException) + exit_code = 2; + else if(severity >= ErrorException) + exit_code = 1; + else + exit_code = 0; + + static const char *sevdesc[] = { "WARNING", "ERROR", "FATAL" }; + fprintf(stderr, "%s: %s\n", sevdesc[exit_code], desc); + + MagickRelinquishMemory(desc); + return(exit_code); +} + +static int scan_image (const char *filename) +{ + int found = 0; + MagickWand *images = NewMagickWand(); + if(!MagickReadImage(images, filename) && dump_error(images)) + return(-1); + + zbar_image_t *zimage = zbar_image_create(); + assert(zimage); + zbar_image_set_format(zimage, *(unsigned long*)"Y800"); + + unsigned seq, n = MagickGetNumberImages(images); + for(seq = 0; seq < n; seq++) { + if(!MagickSetIteratorIndex(images, seq) && dump_error(images)) + return(-1); + + /* FIXME assuming this no longer applies... + image->modifyImage(); + */ + + if(!MagickSetFormat(images, "GRAY") && dump_error(images)) + return(-1); + + if(!MagickSetDepth(images, 8) && dump_error(images)) + return(-1); + + int width = MagickGetImageWidth(images); + int height = MagickGetImageHeight(images); + zbar_image_set_size(zimage, width, height); + + // extract grayscale image pixels + // FIXME color!! ...preserve most color w/422P + // (but only if it's a color image) + size_t bloblen = 0; + unsigned char *blob = MagickGetImageBlob(images, &bloblen); + assert(bloblen == width * height); + zbar_image_set_data(zimage, blob, bloblen, cleanup_blob); + + zbar_process_image(processor, zimage); + + // output result data + const zbar_symbol_t *sym = zbar_image_first_symbol(zimage); + for(; sym; sym = zbar_symbol_next(sym)) { + if(!xmllvl) { + zbar_symbol_type_t typ = zbar_symbol_get_type(sym); + printf("%s%s:%s\n", + zbar_get_symbol_name(typ), + zbar_get_addon_name(typ), + zbar_symbol_get_data(sym)); + } + else { + if(xmllvl < 2) { + xmllvl++; + printf("\n", filename); + } + if(xmllvl < 3) { + xmllvl++; + printf("\n", seq); + } + zbar_symbol_xml(sym, &xmlbuf, &xmlbuflen); + printf("%s\n", xmlbuf); + } + found++; + num_symbols++; + } + if(xmllvl > 2) { + xmllvl--; + printf("\n"); + } + fflush(stdout); + + num_images++; + if(zbar_processor_is_visible(processor)) + zbar_processor_user_wait(processor, -1); + } + + zbar_image_destroy(zimage); + + if(xmllvl > 1) { + xmllvl--; + printf("\n"); + } + + if(!found) + notfound++; + return(0); +} + +int usage (int rc, + const char *msg, + const char *arg) +{ + FILE *out = (rc) ? stderr : stdout; + if(msg) { + fprintf(out, "%s", msg); + if(arg) + fprintf(out, "%s", arg); + fprintf(out, "\n\n"); + } + fprintf(out, note_usage); + return(rc); +} + +static inline int parse_config (const char *cfgstr, const char *arg) +{ + if(!cfgstr || !cfgstr[0]) + return(usage(1, "ERROR: need argument for option: ", arg)); + + if(zbar_processor_parse_config(processor, cfgstr)) + return(usage(1, "ERROR: invalid configuration setting: ", cfgstr)); + + return(0); +} + +int main (int argc, const char *argv[]) +{ + // option pre-scan + int quiet = 0; + int display = 0; + int i, j; + for(i = 1; i < argc; i++) { + const char *arg = argv[i]; + if(arg[0] != '-') + // first pass, skip images + num_images++; + else if(arg[1] != '-') + for(j = 1; arg[j]; j++) { + if(arg[j] == 'S') { + if(!arg[++j] && ++i >= argc) + return(parse_config("", "-S")); + break; + } + switch(arg[j]) { + case 'h': return(usage(0, NULL, NULL)); + case 'q': quiet = 1; break; + case 'v': zbar_increase_verbosity(); break; + case 'd': display = 1; break; + case 'D': break; + default: + return(usage(1, "ERROR: unknown bundled option: -", + arg + j)); + } + } + else if(!strcmp(arg, "--help")) + return(usage(0, NULL, NULL)); + else if(!strcmp(arg, "--version")) { + printf("%s\n", PACKAGE_VERSION); + return(0); + } + else if(!strcmp(arg, "--quiet")) { + quiet = 1; + argv[i] = NULL; + } + else if(!strcmp(arg, "--verbose")) + zbar_increase_verbosity(); + else if(!strncmp(arg, "--verbose=", 10)) + zbar_set_verbosity(strtol(argv[i] + 10, NULL, 0)); + else if(!strcmp(arg, "--display")) + display++; + else if(!strcmp(arg, "--nodisplay") || + !strcmp(arg, "--set") || + !strcmp(arg, "--xml") || + !strcmp(arg, "--noxml") || + !strncmp(arg, "--set=", 6)) + continue; + else if(!strcmp(arg, "--")) { + num_images += argc - i - 1; + break; + } + else + return(usage(1, "ERROR: unknown option: ", arg)); + } + + if(!num_images) + return(usage(1, "ERROR: specify image file(s) to scan", NULL)); + num_images = 0; + + processor = zbar_processor_create(0); + assert(processor); + if(zbar_processor_init(processor, NULL, display)) { + zbar_processor_error_spew(processor, 0); + return(1); + } + + for(i = 1; i < argc; i++) { + const char *arg = argv[i]; + if(!arg) + continue; + + if(arg[0] != '-') { + if(scan_image(arg)) + return(exit_code); + } + else if(arg[1] != '-') + for(j = 1; arg[j]; j++) { + if(arg[j] == 'S') { + if((arg[++j]) + ? parse_config(arg + j, "-S") + : parse_config(argv[++i], "-S")) + return(1); + break; + } + switch(arg[j]) { + case 'd': zbar_processor_set_visible(processor, 1); break; + case 'D': zbar_processor_set_visible(processor, 0); break; + } + } + else if(!strcmp(arg, "--display")) + zbar_processor_set_visible(processor, 1); + else if(!strcmp(arg, "--nodisplay")) + zbar_processor_set_visible(processor, 0); + else if(!strcmp(arg, "--xml")) { + if(xmllvl < 1) { + xmllvl++; + printf(xml_head); + } + } + else if(!strcmp(arg, "--noxml")) { + if(xmllvl > 0) { + xmllvl--; + printf(xml_foot); + fflush(stdout); + } + } + else if(!strcmp(arg, "--set")) { + if(parse_config(argv[++i], "--set")) + return(1); + } + else if(!strncmp(arg, "--set=", 6)) { + if(parse_config(arg + 6, "--set=")) + return(1); + } + else if(!strcmp(arg, "--")) + break; + } + for(i++; i < argc; i++) + if(scan_image(argv[i])) + return(exit_code); + + if(xmllvl > 0) { + xmllvl--; + printf(xml_foot); + fflush(stdout); + } + + if(xmlbuf) + free(xmlbuf); + + if(num_images && !quiet) { + fprintf(stderr, "scanned %d barcode symbols from %d images", + num_symbols, num_images); +#ifdef HAVE_SYS_TIMES_H +#ifdef HAVE_UNISTD_H + long clk_tck = sysconf(_SC_CLK_TCK); + struct tms tms; + if(clk_tck > 0 && times(&tms) >= 0) { + double secs = tms.tms_utime + tms.tms_stime; + secs /= clk_tck; + fprintf(stderr, " in %.2g seconds\n", secs); + } +#endif +#endif + fprintf(stderr, "\n"); + if(notfound) + fprintf(stderr, warning_not_found); + } + return(exit_code); +} diff --git a/zbarimg/zbarimg.cpp b/zbarimg/zbarimg.cpp deleted file mode 100644 index 7724022..0000000 --- a/zbarimg/zbarimg.cpp +++ /dev/null @@ -1,338 +0,0 @@ -//------------------------------------------------------------------------ -// Copyright 2007-2009 (c) Jeff Brown -// -// 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 - -/* wand/wand-config.h (or magick/deprecate.h?) - * defines these conflicting values :| - */ -#undef PACKAGE -#undef VERSION -#undef PACKAGE_BUGREPORT -#undef PACKAGE_NAME -#undef PACKAGE_STRING -#undef PACKAGE_TARNAME -#undef PACKAGE_VERSION - -#include -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif -#ifdef HAVE_SYS_TIMES_H -# include -#endif -#include -#include -#include - -#include - -using namespace std; -using namespace zbar; - -static const char *note_usage = - "usage: zbarimg [options] ...\n" - "\n" - "scan and decode bar codes from one or more image files\n" - "\n" - "options:\n" - " -h, --help display this help text\n" - " --version display version information and exit\n" - " -q, --quiet minimal output, only print decoded symbol data\n" - " -v, --verbose increase debug output level\n" - " --verbose=N set specific debug output level\n" - " -d, --display enable display of following images to the screen\n" - " -D, --nodisplay disable display of following images (default)\n" - " --xml, --noxml enable/disable XML output format\n" - " -S[=], --set [=]\n" - " set decoder/scanner to (or 1)\n" - // FIXME overlay level - ; - -static const char *warning_not_found = - "WARNING: barcode data was not detected in some image(s)\n" - " things to check:\n" - " - is the barcode type supported?" - " currently supported symbologies are:\n" - " EAN/UPC (EAN-13, EAN-8, UPC-A, UPC-E, ISBN-10, ISBN-13),\n" - " Code 128, Code 39 and Interleaved 2 of 5\n" - " - is the barcode large enough in the image?\n" - " - is the barcode mostly in focus?\n" - " - is there sufficient contrast/illumination?\n"; - -static const char *xml_head = - ""; -static const char *xml_foot = - ""; - -static int notfound = 0; -static int num_images = 0, num_symbols = 0; -static int xmllvl = 0; - -static Processor *processor = NULL; - -static void scan_image (const std::string& filename) -{ - bool found = false; - list images; - Magick::readImages(&images, filename); - int seq = 0; - for(list::iterator image = images.begin(); - image != images.end(); - ++image, seq++) - { - image->modifyImage(); - - // extract grayscale image pixels - // FIXME color!! ...preserve most color w/422P - // (but only if it's a color image) - Magick::Blob scan_data; - image->write(&scan_data, "GRAY", 8); - unsigned width = image->columns(); - unsigned height = image->rows(); - assert(scan_data.length() == width * height); - - Image zimage(width, height, "Y800", - scan_data.data(), scan_data.length()); - processor->process_image(zimage); - - // output result data - for(Image::SymbolIterator sym = zimage.symbol_begin(); - sym != zimage.symbol_end(); - ++sym) - { - if(!xmllvl) - cout << *sym << endl; - else { - if(xmllvl < 2) { - xmllvl++; - cout << "" << endl; - } - if(xmllvl < 3) { - xmllvl++; - cout << "" << endl; - } - cout << sym->xml() << endl; - } - found = true; - num_symbols++; - } - if(xmllvl > 2) { - xmllvl--; - cout << "" << endl; - } - cout.flush(); - - num_images++; - if(processor->is_visible()) - processor->user_wait(); - } - if(xmllvl > 1) { - xmllvl--; - cout << "" << endl; - } - - if(!found) - notfound++; -} - -int usage (int rc, const string& msg = "") -{ - ostream &out = (rc) ? cerr : cout; - if(msg.length()) - out << msg << endl << endl; - out << note_usage << endl; - return(rc); -} - -static inline int parse_config (const string& cfgstr, const string& arg) -{ - if(!cfgstr.length()) - return(usage(1, string("ERROR: need argument for option: " + arg))); - - if(processor->set_config(cfgstr.c_str())) - return(usage(1, string("ERROR: invalid configuration setting: " + - cfgstr))); - - return(0); -} - -int main (int argc, const char *argv[]) -{ - // option pre-scan - bool quiet = false; - bool display = false; - int i; - for(i = 1; i < argc; i++) { - string arg(argv[i]); - if(arg[0] != '-') - // first pass, skip images - num_images++; - else if(arg[1] != '-') { - for(int j = 1; arg[j]; j++) { - if(arg[j] == 'S') { - if(!arg[++j] && ++i >= argc) - return(parse_config("", "-S")); - break; - } - switch(arg[j]) { - case 'h': return(usage(0)); - case 'q': quiet = true; break; - case 'v': zbar_increase_verbosity(); break; - case 'd': display = true; break; - case 'D': break; - default: - return(usage(1, string("ERROR: unknown bundled option: -") + - arg[j])); - } - } - } - else if(arg == "--help") - return(usage(0)); - else if(arg == "--version") { - cout << PACKAGE_VERSION << endl; - return(0); - } - else if(arg == "--quiet") { - quiet = true; - argv[i] = NULL; - } - else if(arg == "--verbose") - zbar_increase_verbosity(); - else if(arg.substr(0, 10) == "--verbose=") { - istringstream scan(arg.substr(10)); - int level; - scan >> level; - zbar_set_verbosity(level); - } - else if(arg == "--display") - display = true; - else if(arg == "--nodisplay" || - arg == "--set" || - arg == "--xml" || - arg == "--noxml" || - arg.substr(0, 6) == "--set=") - continue; - else if(arg == "--") { - num_images += argc - i - 1; - break; - } - else - return(usage(1, "ERROR: unknown option: " + arg)); - } - - if(!num_images) - return(usage(1, "ERROR: specify image file(s) to scan")); - num_images = 0; - - try { - /* process and optionally display images (no video) unthreaded */ - processor = new Processor(false, NULL, display); - - for(i = 1; i < argc; i++) { - if(!argv[i]) - continue; - string arg(argv[i]); - if(arg[0] != '-') - scan_image(arg); - else if(arg[1] != '-') - for(int j = 1; arg[j]; j++) { - if(arg[j] == 'S') { - if((arg[++j]) - ? parse_config(arg.substr(j), "-S") - : parse_config(string(argv[++i]), "-S")) - return(1); - break; - } - switch(arg[j]) { - case 'd': processor->set_visible(true); break; - case 'D': processor->set_visible(false); break; - } - } - else if(arg == "--display") - processor->set_visible(true); - else if(arg == "--nodisplay") - processor->set_visible(false); - else if(arg == "--xml") { - if(xmllvl < 1) { - xmllvl++; - cout << xml_head << endl; - } - } - else if(arg == "--noxml") { - if(xmllvl > 0) { - xmllvl--; - cout << xml_foot << endl; - } - } - else if(arg == "--set") { - if(parse_config(string(argv[++i]), "--set")) - return(1); - } - else if(arg.substr(0, 6) == "--set=") { - if(parse_config(arg.substr(6), "--set=")) - return(1); - } - else if(arg == "--") - break; - } - for(i++; i < argc; i++) - scan_image(argv[i]); - } - catch(Exception &e) { - cerr << e.what() << endl; - return(1); - } - catch(std::exception &e) { - cerr << "ERROR: " << e.what() << endl; - return(1); - } - - if(xmllvl > 0) { - xmllvl--; - cout << xml_foot << endl; - cout.flush(); - } - - if(num_images && !quiet) { - cerr << "scanned " << num_symbols << " barcode symbols from " - << num_images << " images"; -#ifdef HAVE_SYS_TIMES_H -#ifdef HAVE_UNISTD_H - long clk_tck = sysconf(_SC_CLK_TCK); - struct tms tms; - if(clk_tck > 0 && times(&tms) >= 0) { - double secs = tms.tms_utime + tms.tms_stime; - secs /= clk_tck; - cerr << " in " << secs << " seconds"; - } -#endif -#endif - cerr << endl; - if(notfound) - cerr << endl << warning_not_found << endl; - } - return(0); -} From cf878336b4984d49e413ae824cb9a7088df8cb86 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 18 Jun 2009 01:16:28 -0400 Subject: [PATCH 098/328] zbarimg working in windows! - switch to StretchDIBits over DrawDib - refactor some window drawing code to remove redundancies - make refcounts thread safe - clean up alloc/free bugs --- ChangeLog | 5 ++ zbar/Makefile.am.inc | 9 ++-- zbar/convert.c | 2 +- zbar/decoder.c | 5 +- zbar/image.c | 6 ++- zbar/image.h | 8 ++-- zbar/img_scanner.c | 8 ++-- zbar/processor.h | 8 ++-- zbar/processor/posix.c | 8 ++-- zbar/processor/win.h | 2 +- zbar/refcnt.c | 49 +++++++++++++++++++ zbar/refcnt.h | 72 ++++++++++++++++++++++++++++ zbar/video.c | 2 +- zbar/window.c | 59 +++++++++++++++++++++-- zbar/window.h | 36 +++++++++++--- zbar/window/dib.c | 77 ++++++++++++++++++++++++++++++ zbar/window/vfw.c | 104 +++++++++-------------------------------- zbar/window/win.c | 46 +++++++++++++++++- zbar/window/ximage.c | 36 ++++---------- zbar/window/xv.c | 52 ++++----------------- zbarimg/zbarimg.c | 29 ++++++++---- 21 files changed, 425 insertions(+), 198 deletions(-) create mode 100644 zbar/refcnt.c create mode 100644 zbar/refcnt.h create mode 100644 zbar/window/dib.c diff --git a/ChangeLog b/ChangeLog index deb6c87..518725b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,9 @@ current: + * zbarimg working in windows + - switch to StretchDIBits over DrawDib + - refactor some window drawing code to remove redundancies + - make refcounts thread safe + - clean up alloc/free bugs * convert zbarimg to C (cross compiled C++ cannot run w/native libraries) - fix DrawDib image width granularity - fix window resize dimensions to include decorations diff --git a/zbar/Makefile.am.inc b/zbar/Makefile.am.inc index ac43193..12fc2ab 100644 --- a/zbar/Makefile.am.inc +++ b/zbar/Makefile.am.inc @@ -7,7 +7,7 @@ zbar_libzbar_la_LIBADD = zbar_libzbar_la_SOURCES = zbar/debug.h zbar/config.c \ zbar/error.h zbar/error.c zbar/symbol.h zbar/symbol.c \ zbar/image.h zbar/image.c zbar/convert.c \ - zbar/processor.c zbar/processor.h \ + zbar/processor.c zbar/processor.h zbar/refcnt.h zbar/refcnt.c \ zbar/window.h zbar/window.c zbar/video.h zbar/video.c \ zbar/img_scanner.c zbar/scanner.c \ zbar/decoder.h zbar/decoder.c @@ -34,6 +34,8 @@ zbar_libzbar_la_SOURCES += zbar/processor/posix.h zbar/processor/posix.c endif if WIN32 zbar_libzbar_la_SOURCES += zbar/processor/win.h zbar/processor/win.c +zbar_libzbar_la_CPPFLAGS += -mthreads +zbar_libzbar_la_LDFLAGS += -mthreads endif if HAVE_V4L1 @@ -61,8 +63,9 @@ zbar_libzbar_la_LIBADD += $(XV_LIBS) endif else if WIN32 -zbar_libzbar_la_SOURCES += zbar/window/win.c zbar/window/vfw.c -zbar_libzbar_la_LIBADD += -lgdi32 -lvfw32 +zbar_libzbar_la_SOURCES += zbar/window/win.c zbar/window/dib.c +# zbar/window/vfw.c -lvfw32 +zbar_libzbar_la_LIBADD += -lgdi32 else zbar_libzbar_la_SOURCES += zbar/window/null.c endif diff --git a/zbar/convert.c b/zbar/convert.c index 07aba95..850def7 100644 --- a/zbar/convert.c +++ b/zbar/convert.c @@ -349,7 +349,7 @@ static void convert_copy (zbar_image_t *dst, dst->datalen = src->datalen; dst->cleanup = cleanup_ref; dst->next = (zbar_image_t*)src; - ((zbar_image_t*)src)->refcnt++; + _zbar_image_refcnt((zbar_image_t*)src, 1); } else /* NB only for GRAY/YUV_PLANAR formats */ diff --git a/zbar/decoder.c b/zbar/decoder.c index 663f847..8b5db3d 100644 --- a/zbar/decoder.c +++ b/zbar/decoder.c @@ -22,7 +22,7 @@ *------------------------------------------------------------------------*/ #include -#include /* malloc, free */ +#include /* malloc, calloc, free */ #include /* snprintf */ #include /* memset, strlen */ @@ -38,10 +38,9 @@ zbar_decoder_t *zbar_decoder_create () { - zbar_decoder_t *dcode = malloc(sizeof(zbar_decoder_t)); + zbar_decoder_t *dcode = calloc(1, sizeof(zbar_decoder_t)); dcode->buflen = BUFFER_MIN; dcode->buf = malloc(dcode->buflen); - dcode->handler = dcode->userdata = NULL; /* initialize default configs */ #ifdef ENABLE_EAN diff --git a/zbar/image.c b/zbar/image.c index c1506be..6a98af5 100644 --- a/zbar/image.c +++ b/zbar/image.c @@ -23,11 +23,13 @@ #include "error.h" #include "image.h" +#include "refcnt.h" zbar_image_t *zbar_image_create () { zbar_image_t *img = calloc(1, sizeof(zbar_image_t)); - img->refcnt = 1; + _zbar_refcnt_init(); + _zbar_image_refcnt(img, 1); img->srcidx = -1; return(img); } @@ -99,7 +101,7 @@ inline void zbar_image_free_data (zbar_image_t *img) return; if(img->src) { /* replace video image w/new copy */ - assert(img->refcnt); + assert(img->refcnt); /* FIXME needs lock */ zbar_image_t *newimg = zbar_image_create(); memcpy(newimg, img, sizeof(zbar_image_t)); /* recycle video image */ diff --git a/zbar/image.h b/zbar/image.h index a70c72a..9673804 100644 --- a/zbar/image.h +++ b/zbar/image.h @@ -33,6 +33,7 @@ #include #include "error.h" #include "symbol.h" +#include "refcnt.h" /* adapted from v4l2 spec */ #define fourcc(a, b, c, d) \ @@ -68,7 +69,7 @@ struct zbar_image_s { /* cleanup handler */ zbar_image_cleanup_handler_t *cleanup; - int refcnt; /* reference count */ + refcnt_t refcnt; /* reference count */ zbar_video_t *src; /* originator */ int srcidx; /* index used by originator */ zbar_image_t *next; /* internal image lists */ @@ -99,12 +100,11 @@ typedef struct zbar_format_def_s { } p; } zbar_format_def_t; + static inline void _zbar_image_refcnt (zbar_image_t *img, int delta) { - img->refcnt += delta; - assert(img->refcnt >= 0); - if(!img->refcnt) { + if(!_zbar_refcnt(&img->refcnt, delta)) { if(img->cleanup) img->cleanup(img); if(!img->src) diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 1f95d6d..2b304bb 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -224,12 +224,12 @@ static void symbol_handler (zbar_image_scanner_t *iscn, /* consistency check and hysteresis */ uint32_t age = sym->time - entry->time; entry->time = sym->time; - int near = (age < CACHE_PROXIMITY); - int far = (age >= CACHE_HYSTERESIS); + int near_thresh = (age < CACHE_PROXIMITY); + int far_thresh = (age >= CACHE_HYSTERESIS); int dup = (entry->cache_count >= 0); - if((!dup && !near) || far) + if((!dup && !near_thresh) || far_thresh) entry->cache_count = -CACHE_CONSISTENCY; - else if(dup || near) + else if(dup || near_thresh) entry->cache_count++; sym->cache_count = entry->cache_count; diff --git a/zbar/processor.h b/zbar/processor.h index ab2cf94..100da4a 100644 --- a/zbar/processor.h +++ b/zbar/processor.h @@ -55,11 +55,11 @@ struct zbar_processor_s { int input; /* user input status */ /* state flags */ - unsigned threaded : 1; - unsigned visible : 1; /* output window mapped to display */ - volatile unsigned active : 1; /* async processor thread running */ + int threaded; + int visible; /* output window mapped to display */ + int active; /* async processor thread running */ - volatile unsigned events; /* synchronization events */ + unsigned events; /* synchronization events */ #define EVENT_INPUT 0x01 /* user input */ #define EVENT_OUTPUT 0x02 /* decoded output data available */ diff --git a/zbar/processor/posix.c b/zbar/processor/posix.c index 7f4e8d3..d92c7b1 100644 --- a/zbar/processor/posix.c +++ b/zbar/processor/posix.c @@ -444,9 +444,11 @@ int _zbar_processor_threads_cleanup (zbar_processor_t *proc) { processor_state_t *state = proc->state; #ifdef HAVE_LIBPTHREAD - pthread_cond_destroy(&state->event); - pthread_cond_destroy(&state->cond); - pthread_mutex_destroy(&state->mutex); + if(proc->threaded) { + pthread_cond_destroy(&state->event); + pthread_cond_destroy(&state->cond); + pthread_mutex_destroy(&state->mutex); + } #endif if(state->polling.fds) { free(state->polling.fds); diff --git a/zbar/processor/win.h b/zbar/processor/win.h index 6c47fa0..464b498 100644 --- a/zbar/processor/win.h +++ b/zbar/processor/win.h @@ -65,7 +65,7 @@ static inline wait_entry_t *proc_entry_alloc (processor_state_t *state, if(entry) state->free_entry = entry->next; else { - entry = malloc(sizeof(wait_queue_t)); + entry = malloc(sizeof(wait_entry_t)); entry->notify = CreateEvent(NULL, 0, 0, NULL); } entry->next = NULL; diff --git a/zbar/refcnt.c b/zbar/refcnt.c new file mode 100644 index 0000000..6c8f68b --- /dev/null +++ b/zbar/refcnt.c @@ -0,0 +1,49 @@ +/*------------------------------------------------------------------------ + * Copyright 2007-2009 (c) Jeff Brown + * + * 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 "refcnt.h" + +#ifdef HAVE_LIBPTHREAD + +pthread_once_t initialized = PTHREAD_ONCE_INIT; +pthread_mutex_t _zbar_reflock; + +static void initialize () +{ + pthread_mutex_init(&_zbar_reflock, NULL); +} + +void _zbar_refcnt_init () +{ + pthread_once(&initialized, initialize); +} + +#endif + +#ifdef _WIN32 + +void _zbar_refcnt_init () +{ +} + +#endif diff --git a/zbar/refcnt.h b/zbar/refcnt.h new file mode 100644 index 0000000..7caf9c1 --- /dev/null +++ b/zbar/refcnt.h @@ -0,0 +1,72 @@ +/*------------------------------------------------------------------------ + * Copyright 2007-2009 (c) Jeff Brown + * + * 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 + *------------------------------------------------------------------------*/ +#ifndef _REFCNT_H_ +#define _REFCNT_H_ + +#include +#include + +#ifdef HAVE_LIBPTHREAD +# include + +typedef int refcnt_t; + +extern pthread_mutex_t _zbar_reflock; + +static inline int _zbar_refcnt (refcnt_t *cnt, + int delta) +{ + pthread_mutex_lock(&_zbar_reflock); + int rc = (*cnt += delta); + pthread_mutex_unlock(&_zbar_reflock); + assert(rc >= 0); + return(rc); +} + +#endif + + +#ifdef _WIN32 +# include + +typedef volatile LONG refcnt_t; + +static inline int _zbar_refcnt (refcnt_t *cnt, + int delta) +{ + int rc = -1; + if(delta > 0) + while(delta--) + rc = InterlockedIncrement(cnt); + else if(delta < 0) + while(delta++) + rc = InterlockedDecrement(cnt); + assert(rc >= 0); + return(rc); +} + +#endif + +void _zbar_refcnt_init(); + +#endif diff --git a/zbar/video.c b/zbar/video.c index 0944aae..0475242 100644 --- a/zbar/video.c +++ b/zbar/video.c @@ -343,7 +343,7 @@ zbar_image_t *zbar_video_next_image (zbar_video_t *vdo) memcpy((void*)img->data, tmp->data, img->datalen); _zbar_video_recycle_image(tmp); } - img->refcnt++; + _zbar_image_refcnt(img, 1); } return(img); } diff --git a/zbar/window.c b/zbar/window.c index 4cac05b..4df71c8 100644 --- a/zbar/window.c +++ b/zbar/window.c @@ -23,6 +23,7 @@ #include "window.h" #include "image.h" +#include "refcnt.h" extern int _zbar_window_draw_logo(zbar_window_t *w); @@ -33,6 +34,12 @@ zbar_window_t *zbar_window_create () return(NULL); err_init(&w->err, ZBAR_MOD_WINDOW); w->overlay = 1; +#ifdef HAVE_LIBPTHREAD + pthread_mutex_init(&w->imglock, NULL); +#endif +#ifdef _WIN32 + InitializeCriticalSection(&w->imglock); +#endif return(w); } @@ -59,6 +66,9 @@ int zbar_window_attach (zbar_window_t *w, free(w->formats); w->formats = NULL; } + w->src_format = 0; + w->src_width = w->src_height = 0; + w->dst_width = w->dst_height = 0; return(_zbar_window_attach(w, display, drawable)); } @@ -91,8 +101,49 @@ inline int zbar_window_redraw (zbar_window_t *w) if(window_lock(w)) return(-1); int rc = 0; - if(w->draw_image && w->image) { - rc = w->draw_image(w, w->image); + zbar_image_t *img = w->image; + if(w->init && w->draw_image && img) { + int format_change = (w->src_format != img->format && + w->format != img->format); + if(format_change) { + _zbar_best_format(img->format, &w->format, w->formats); + if(!w->format) + rc = err_capture_int(w, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, + "no conversion from %x to supported formats", + img->format); + w->src_format = img->format; + w->src_width = img->width; + w->src_height = img->height; + } + + /* FIXME preserve aspect ratio (config?) */ + if(!rc && + (format_change || + (img->width != w->src_width && img->width != w->dst_width) || + (img->height != w->src_height && img->height != w->dst_height))) { + rc = w->init(w, img, format_change); + zprintf(24, "src=%.4s(%08x) %dx%d dst=%.4s(%08x) %dx%d\n", + (char*)&w->src_format, w->src_format, + w->src_width, w->src_height, + (char*)&w->format, w->format, + w->dst_width, w->dst_height); + } + + if(!rc && + (img->format != w->format || + img->width != w->dst_width || + img->height != w->dst_height)) { + w->src_width = img->width; + w->src_height = img->height; + /* save *converted* image for redraw */ + w->image = zbar_image_convert_resize(img, w->format, + w->dst_width, w->dst_height); + zbar_image_destroy(img); + img = w->image; + } + + if(!rc) + rc = w->draw_image(w, w->image); if(!rc) rc = window_draw_overlay(w); } @@ -109,11 +160,11 @@ int zbar_window_draw (zbar_window_t *w, return(-1); if(!w->draw_image) img = NULL; + if(img) + _zbar_image_refcnt(img, 1); if(w->image) _zbar_image_refcnt(w->image, -1); w->image = img; - if(img) - img->refcnt++; return(window_unlock(w)); } diff --git a/zbar/window.h b/zbar/window.h index 4082120..ac7c962 100644 --- a/zbar/window.h +++ b/zbar/window.h @@ -64,11 +64,16 @@ struct zbar_window_s { unsigned max_width, max_height; uint32_t src_format; /* current input format */ + unsigned src_width; /* last displayed image size */ + unsigned src_height; + unsigned dst_width; /* conversion target */ + unsigned dst_height; uint32_t *formats; /* supported formats (zero terminated) */ /* interface dependent methods */ + int (*init)(zbar_window_t*, zbar_image_t*, int); int (*draw_image)(zbar_window_t*, zbar_image_t*); int (*cleanup)(zbar_window_t*); @@ -84,9 +89,6 @@ struct zbar_window_s { } img; XID img_port; /* current format port */ - unsigned src_width; /* last displayed image size */ - unsigned src_height; - XID *xv_ports; /* best port for format */ int num_xv_adaptors; /* number of adaptors */ XID *xv_adaptors; /* port grabbed for each adaptor */ @@ -116,17 +118,17 @@ struct zbar_window_s { void* hdd; BITMAPINFOHEADER bih; - unsigned dst_height; /* pre-calculated logo geometries */ int logo_scale; HRGN logo_zbars; HPEN logo_zpen, logo_zbpen; POINT logo_z[4]; + + CRITICAL_SECTION imglock; #endif }; - #ifdef HAVE_LIBPTHREAD /* window.draw has to be thread safe wrt/other apis @@ -157,8 +159,24 @@ static inline int window_unlock (zbar_window_t *w) } #else -# define window_lock(...) (0) -# define window_unlock(...) (0) +# ifdef _WIN32 + +static inline int window_lock (zbar_window_t *w) +{ + EnterCriticalSection(&w->imglock); + return(0); +} + +static inline int window_unlock (zbar_window_t *w) +{ + LeaveCriticalSection(&w->imglock); + return(0); +} + +# else +# define window_lock(...) (0) +# define window_unlock(...) (0) +# endif #endif static inline int _zbar_window_add_format (zbar_window_t *w, @@ -193,4 +211,8 @@ extern int _zbar_window_draw_text(zbar_window_t*, uint32_t, const point_t*, const char*); #endif +#ifdef _WIN32 +extern int _zbar_window_bih_init(zbar_window_t*, zbar_image_t*); +#endif + #endif diff --git a/zbar/window/dib.c b/zbar/window/dib.c new file mode 100644 index 0000000..19a9cda --- /dev/null +++ b/zbar/window/dib.c @@ -0,0 +1,77 @@ +/*------------------------------------------------------------------------ + * Copyright 2009 (c) Jeff Brown + * + * 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 "window.h" + +static int dib_cleanup (zbar_window_t *w) +{ + return(0); +} + +static int dib_init (zbar_window_t *w, + zbar_image_t *img, + int new_format) +{ + if(new_format) + _zbar_window_bih_init(w, img); + + w->dst_width = w->bih.biWidth = (img->width + 3) & ~3; + w->dst_height = w->bih.biHeight = img->height; + return(0); +} + +static int dib_draw (zbar_window_t *w, + zbar_image_t *img) +{ + HDC hdc = GetDC(w->hwnd); + if(!hdc) + return(-1); + + StretchDIBits(hdc, 0, w->height - 1, w->width, -w->height, + 0, 0, w->src_width, w->src_height, + (void*)img->data, (BITMAPINFO*)&w->bih, + DIB_RGB_COLORS, SRCCOPY); + + ValidateRect(w->hwnd, NULL); + ReleaseDC(w->hwnd, hdc); + return(0); +} + +static uint32_t dib_formats[] = { + fourcc('B','G','R','3'), + fourcc('B','G','R','4'), + fourcc('J','P','E','G'), + 0 +}; + +int _zbar_window_dib_init (zbar_window_t *w) +{ + uint32_t *fmt; + for(fmt = dib_formats; *fmt; fmt++) + _zbar_window_add_format(w, *fmt); + + w->init = dib_init; + w->draw_image = dib_draw; + w->cleanup = dib_cleanup; + return(0); +} diff --git a/zbar/window/vfw.c b/zbar/window/vfw.c index f512578..d2d54f3 100644 --- a/zbar/window/vfw.c +++ b/zbar/window/vfw.c @@ -22,10 +22,9 @@ *------------------------------------------------------------------------*/ #include "window.h" -#include "vfw.h" +#include -static int -vfw_cleanup (zbar_window_t *w) +static int vfw_cleanup (zbar_window_t *w) { if(w->hdd) { DrawDibClose(w->hdd); @@ -34,105 +33,46 @@ vfw_cleanup (zbar_window_t *w) return(0); } -static int -vfw_init (zbar_window_t *w, - zbar_image_t *img, - HDC hdc) +static int vfw_init (zbar_window_t *w, + zbar_image_t *img, + int new_format) { - if(w->src_format != img->format && - w->format != img->format) { - _zbar_best_format(img->format, &w->format, w->formats); - if(!w->format) { - err_capture_int(w, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, - "no conversion from %x to supported Xv formats", - img->format); - return(-1); - } - w->src_format = img->format; + if(new_format) + _zbar_window_bih_init(w, img); - w->bih.biPlanes = 1; - w->bih.biXPelsPerMeter = - 1000L * GetDeviceCaps(hdc, HORZRES) / GetDeviceCaps(hdc, HORZSIZE); - w->bih.biYPelsPerMeter = - 1000L * GetDeviceCaps(hdc, VERTRES) / GetDeviceCaps(hdc, VERTSIZE); + w->dst_width = w->bih.biWidth = (img->width + 3) & ~3; + w->dst_height = w->bih.biHeight = img->height; - switch(w->format) { - case fourcc('J','P','E','G'): { - w->bih.biBitCount = 0; - w->bih.biCompression = BI_JPEG; - break; - } - case fourcc('B','G','R','3'): { - w->bih.biBitCount = 24; - w->bih.biCompression = BI_RGB; - break; - } - case fourcc('B','G','R','4'): { - w->bih.biBitCount = 32; - w->bih.biCompression = BI_RGB; - break; - } - default: - assert(0); - /* FIXME PNG? */ - } - w->bih.biSizeImage = img->datalen; - zprintf(20, "%.4s(%08x)%dx%d->%.4s(%08x) ppm=%ldx%ld comp=%d bpp=%d\n", - (char*)&img->format, img->format, img->width, img->height, - (char*)&w->format, w->format, - w->bih.biXPelsPerMeter, w->bih.biYPelsPerMeter, - (int)w->bih.biCompression, w->bih.biBitCount); - } - - w->bih.biSize = sizeof(w->bih); - w->bih.biWidth = (img->width + 3) & ~3; - w->bih.biHeight = img->height; - w->dst_width = w->width; - w->dst_height = w->height; + HDC hdc = GetDC(w->hwnd); + if(!hdc) + return(-1/*FIXME*/); if(!DrawDibBegin(w->hdd, hdc, w->width, w->height, - &w->bih, w->bih.biWidth, w->bih.biHeight, 0)) + &w->bih, img->width, img->height, 0)) return(-1/*FIXME*/); - zprintf(24, "out=%ldx%ld\n", w->bih.biWidth, w->bih.biHeight); + + ReleaseDC(w->hwnd, hdc); return(0); } -static int -vfw_draw (zbar_window_t *w, - zbar_image_t *img) +static int vfw_draw (zbar_window_t *w, + zbar_image_t *img) { HDC hdc = GetDC(w->hwnd); if(!hdc) return(-1/*FIXME*/); - int width = (img->width + 3) & ~3; - - if(((img->format != w->src_format && - img->format != w->format) || - width != w->bih.biWidth || - img->height != w->bih.biHeight || - w->width != w->dst_width || - w->height != w->dst_height) && - vfw_init(w, img, hdc)) - return(-1); - - if(img->format != w->format || - img->width != width) { - w->image = zbar_image_convert_resize(img, w->format, - width, img->height); - zbar_image_destroy(img); - img = w->image; - } - zprintf(24, "DrawDibDraw(%dx%d -> %dx%d)\n", img->width, img->height, w->width, w->height); DrawDibDraw(w->hdd, hdc, 0, 0, w->width, w->height, &w->bih, (void*)img->data, - 0, 0, img->width, img->height, + 0, 0, w->src_width, w->src_height, DDF_SAME_DRAW); + ValidateRect(w->hwnd, NULL); + ReleaseDC(w->hwnd, hdc); return(0); } @@ -143,8 +83,7 @@ static uint32_t vfw_formats[] = { 0 }; -int -_zbar_window_vfw_init (zbar_window_t *w) +int _zbar_window_vfw_init (zbar_window_t *w) { w->hdd = DrawDibOpen(); if(!w->hdd) @@ -155,6 +94,7 @@ _zbar_window_vfw_init (zbar_window_t *w) for(fmt = vfw_formats; *fmt; fmt++) _zbar_window_add_format(w, *fmt); + w->init = vfw_init; w->draw_image = vfw_draw; w->cleanup = vfw_cleanup; return(0); diff --git a/zbar/window/win.c b/zbar/window/win.c index 1dea9e3..1068607 100644 --- a/zbar/window/win.c +++ b/zbar/window/win.c @@ -24,6 +24,7 @@ #include "window.h" int _zbar_window_vfw_init(zbar_window_t *w); +int _zbar_window_dib_init(zbar_window_t *w); int _zbar_window_draw_marker(zbar_window_t *w, @@ -112,7 +113,19 @@ _zbar_window_attach (zbar_window_t *w, w->hwnd = display; - return(_zbar_window_vfw_init(w)); + w->bih.biSize = sizeof(w->bih); + w->bih.biPlanes = 1; + + HDC hdc = GetDC(w->hwnd); + if(!hdc) + return(-1/*FIXME*/); + w->bih.biXPelsPerMeter = + 1000L * GetDeviceCaps(hdc, HORZRES) / GetDeviceCaps(hdc, HORZSIZE); + w->bih.biYPelsPerMeter = + 1000L * GetDeviceCaps(hdc, VERTRES) / GetDeviceCaps(hdc, VERTSIZE); + ReleaseDC(w->hwnd, hdc); + + return(_zbar_window_dib_init(w)); } int @@ -160,3 +173,34 @@ _zbar_window_draw_logo (zbar_window_t *w) ValidateRect(w->hwnd, NULL); return(0); } + +int _zbar_window_bih_init (zbar_window_t *w, + zbar_image_t *img) +{ + switch(w->format) { + case fourcc('J','P','E','G'): { + w->bih.biBitCount = 0; + w->bih.biCompression = BI_JPEG; + break; + } + case fourcc('B','G','R','3'): { + w->bih.biBitCount = 24; + w->bih.biCompression = BI_RGB; + break; + } + case fourcc('B','G','R','4'): { + w->bih.biBitCount = 32; + w->bih.biCompression = BI_RGB; + break; + } + default: + assert(0); + /* FIXME PNG? */ + } + w->bih.biSizeImage = img->datalen; + + zprintf(20, "biCompression=%d biBitCount=%d\n", + (int)w->bih.biCompression, w->bih.biBitCount); + + return(0); +} diff --git a/zbar/window/ximage.c b/zbar/window/ximage.c index 67c15e1..93ed7e1 100644 --- a/zbar/window/ximage.c +++ b/zbar/window/ximage.c @@ -32,23 +32,13 @@ static int ximage_cleanup (zbar_window_t *w) } static inline int ximage_init (zbar_window_t *w, - zbar_image_t *img) + zbar_image_t *img, + int format_change) { if(w->img.x) { free(w->img.x); w->img.x = NULL; } - if(w->src_format != img->format && - w->format != img->format) { - _zbar_best_format(img->format, &w->format, w->formats); - if(!w->format) { - err_capture_int(w, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, - "no conversion from %x to supported formats", - img->format); - return(-1); - } - w->src_format = img->format; - } XImage *ximg = w->img.x = calloc(1, sizeof(XImage)); ximg->width = img->width; ximg->height = img->height; @@ -80,6 +70,10 @@ static inline int ximage_init (zbar_window_t *w, return(err_capture_int(w, SEV_ERROR, ZBAR_ERR_XPROTO, __func__, "unable to init XImage for format %x", w->format)); + + w->dst_width = img->width; + w->dst_height = img->height; + zprintf(3, "new XImage %.4s(%08" PRIx32 ") %dx%d" " from %.4s(%08" PRIx32 ") %dx%d\n", (char*)&w->format, w->format, ximg->width, ximg->height, @@ -93,22 +87,7 @@ static int ximage_draw (zbar_window_t *w, zbar_image_t *img) { XImage *ximg = w->img.x; - if(!ximg || - (w->src_format != img->format && - w->format != img->format) || - ximg->width != img->width || - ximg->height != img->height) { - if(ximage_init(w, img)) - return(-1); - ximg = w->img.x; - } - if(img->format != w->format) { - /* save *converted* image for redraw */ - w->image = zbar_image_convert(img, w->format); - zbar_image_destroy(img); - img = w->image; - } - + assert(ximg); ximg->data = (void*)img->data; int screen = DefaultScreen(w->display); @@ -247,6 +226,7 @@ int _zbar_window_probe_ximage (zbar_window_t *w) return(err_capture(w, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "no usable XImage formats found")); + w->init = ximage_init; w->draw_image = ximage_draw; w->cleanup = ximage_cleanup; return(0); diff --git a/zbar/window/xv.c b/zbar/window/xv.c index de5b227..52ff778 100644 --- a/zbar/window/xv.c +++ b/zbar/window/xv.c @@ -45,22 +45,10 @@ static int xv_cleanup (zbar_window_t *w) } static inline int xv_init (zbar_window_t *w, - zbar_image_t *img) + zbar_image_t *img, + int format_change) { - if(w->img.xv) { - XFree(w->img.xv); - w->img.xv = NULL; - } - if(w->src_format != img->format && - w->format != img->format) { - _zbar_best_format(img->format, &w->format, w->formats); - if(!w->format) { - err_capture_int(w, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, - "no conversion from %x to supported Xv formats", - img->format); - return(-1); - } - w->src_format = img->format; + if(format_change) { /* lookup port for format */ w->img_port = 0; int i; @@ -71,8 +59,10 @@ static inline int xv_init (zbar_window_t *w, } assert(w->img_port > 0); } - w->src_width = img->width; - w->src_height = img->height; + if(w->img.xv) { + XFree(w->img.xv); + w->img.xv = NULL; + } XvImage *xvimg = XvCreateImage(w->display, w->img_port, w->format, NULL, img->width, img->height); zprintf(3, "new XvImage %.4s(%08" PRIx32 ") %dx%d(%d)" @@ -87,6 +77,7 @@ static inline int xv_init (zbar_window_t *w, w->dst_width = ((xvimg->num_planes <= 1) ? xvimg->width : xvimg->pitches[0]); + w->dst_height = xvimg->height; /* FIXME datalen check */ if(w->dst_width < img->width || xvimg->height < img->height) { @@ -104,31 +95,7 @@ static int xv_draw (zbar_window_t *w, zbar_image_t *img) { XvImage *xvimg = w->img.xv; - /* FIXME preserve aspect ratio (config?) */ - if(!xvimg || - (img->format != w->src_format && - img->format != w->format) || - (img->width != w->src_width && - img->width != w->dst_width) || - (img->height != w->src_height && - img->height != xvimg->height)) { - if(xv_init(w, img)) - return(-1); - xvimg = w->img.xv; - } - if(img->format != w->format || - img->width != w->dst_width || - img->height != xvimg->height) { - w->src_width = img->width; - w->src_height = img->height; - /* save *converted* image for redraw */ - w->image = zbar_image_convert_resize(img, w->format, - w->dst_width, - xvimg->height); - zbar_image_destroy(img); - img = w->image; - } - + assert(xvimg); xvimg->data = (void*)img->data; zprintf(24, "XvPutImage(%dx%d -> %dx%d)\n", w->src_width, w->src_height, w->width, w->height); @@ -289,6 +256,7 @@ int _zbar_window_probe_xv (zbar_window_t *w) } } + w->init = xv_init; w->draw_image = xv_draw; w->cleanup = xv_cleanup; return(0); diff --git a/zbarimg/zbarimg.c b/zbarimg/zbarimg.c index a41f86f..3b86817 100644 --- a/zbarimg/zbarimg.c +++ b/zbarimg/zbarimg.c @@ -115,10 +115,6 @@ static int scan_image (const char *filename) if(!MagickReadImage(images, filename) && dump_error(images)) return(-1); - zbar_image_t *zimage = zbar_image_create(); - assert(zimage); - zbar_image_set_format(zimage, *(unsigned long*)"Y800"); - unsigned seq, n = MagickGetNumberImages(images); for(seq = 0; seq < n; seq++) { if(!MagickSetIteratorIndex(images, seq) && dump_error(images)) @@ -134,6 +130,10 @@ static int scan_image (const char *filename) if(!MagickSetDepth(images, 8) && dump_error(images)) return(-1); + zbar_image_t *zimage = zbar_image_create(); + assert(zimage); + zbar_image_set_format(zimage, *(unsigned long*)"Y800"); + int width = MagickGetImageWidth(images); int height = MagickGetImageHeight(images); zbar_image_set_size(zimage, width, height); @@ -179,13 +179,18 @@ static int scan_image (const char *filename) } fflush(stdout); + zbar_image_destroy(zimage); + num_images++; - if(zbar_processor_is_visible(processor)) - zbar_processor_user_wait(processor, -1); + if(zbar_processor_is_visible(processor)) { + int rc = zbar_processor_user_wait(processor, -1); + if(rc < 0 || rc == 'q' || rc == 'Q') { + exit_code = 3; + return(-1); + } + } } - zbar_image_destroy(zimage); - if(xmllvl > 1) { xmllvl--; printf("\n"); @@ -193,6 +198,8 @@ static int scan_image (const char *filename) if(!found) notfound++; + + DestroyMagickWand(images); return(0); } @@ -237,6 +244,7 @@ int main (int argc, const char *argv[]) for(j = 1; arg[j]; j++) { if(arg[j] == 'S') { if(!arg[++j] && ++i >= argc) + /* FIXME parse check */ return(parse_config("", "-S")); break; } @@ -285,6 +293,8 @@ int main (int argc, const char *argv[]) return(usage(1, "ERROR: specify image file(s) to scan", NULL)); num_images = 0; + MagickWandGenesis(); + processor = zbar_processor_create(0); assert(processor); if(zbar_processor_init(processor, NULL, display)) { @@ -374,5 +384,8 @@ int main (int argc, const char *argv[]) if(notfound) fprintf(stderr, warning_not_found); } + + zbar_processor_destroy(processor); + MagickWandTerminus(); return(exit_code); } From 1d5c6ad5f68df48a0185c36bb34e2b586702b038 Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 22 Jun 2009 01:13:03 -0400 Subject: [PATCH 099/328] first pass installer - add version and icon resources for libzbar, zbarimg --- ChangeLog | 2 + Makefile.am | 26 ++++ README.windows | 61 +++++++++ TODO | 3 +- configure.ac | 11 ++ examples/scan_image.vcproj | 46 +++++++ zbar.ico | Bin 0 -> 6318 bytes zbar.nsi | 268 +++++++++++++++++++++++++++++++++++++ zbar/Makefile.am.inc | 4 +- zbar/libzbar.rc | 32 +++++ zbarimg/Makefile.am.inc | 5 + zbarimg/zbarimg.rc | 30 +++++ 12 files changed, 485 insertions(+), 3 deletions(-) create mode 100644 README.windows create mode 100644 examples/scan_image.vcproj create mode 100644 zbar.ico create mode 100644 zbar.nsi create mode 100644 zbar/libzbar.rc create mode 100644 zbarimg/zbarimg.rc diff --git a/ChangeLog b/ChangeLog index 518725b..efd27a2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * first pass installer + - add version and icon resources for libzbar, zbarimg * zbarimg working in windows - switch to StretchDIBits over DrawDib - refactor some window drawing code to remove redundancies diff --git a/Makefile.am b/Makefile.am index a429e36..e4403c2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -60,3 +60,29 @@ EXTRA_DIST += perl/MANIFEST perl/README perl/Changes perl/COPYING.LIB \ perl/examples/scan_image.pl \ perl/t/barcode.png perl/t/ZBar.t perl/t/Decoder.t perl/t/Image.t \ perl/t/Processor.t perl/t/Scanner.t perl/t/pod.t perl/t/pod-coverage.t + +if WIN32 +dist_doc_DATA += README.windows +pkgdata_DATA = $(srcdir)/examples/barcode.png \ + $(srcdir)/examples/scan_image.cpp $(srcdir)/examples/scan_image.vcproj + +%-rc.o: %.rc + $(RC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) -o $@ $< +%-rc.lo: %.rc + $(LIBTOOL) --tag=RC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(RC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) -o $@ $< + +# install to tmp dest and run NSIS to generate installer +dist-nsis: html-local + test ! -e _nsis || test -d _nsis && rm -rf _nsis + mkdir _nsis + tmpinst=`cd _nsis && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR=$$tmpinst prefix=/ install + cp zbar/.libs/libzbar-0.dll.def _nsis/lib/libzbar-0.def + cp -r doc/html _nsis/share/doc/zbar/ + $(WINEXEC) lib.exe /machine:x86 /def:_nsis/lib/libzbar-0.def /out:_nsis/lib/libzbar-0.lib + cd _nsis && \ + makensis -NOCD -V2 -DVERSION=$(VERSION) $(srcdir)/zbar.nsi +endif diff --git a/README.windows b/README.windows new file mode 100644 index 0000000..28726b0 --- /dev/null +++ b/README.windows @@ -0,0 +1,61 @@ +ZBAR BAR CODE READER +==================== + +The ZBar Bar Code Reader is a library for scanning and decoding bar +codes from various sources such as video streams, image files or raw +intensity sensors. It supports EAN/UPC, Code 128, Code 39 and +Interleaved 2 of 5. 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. The flexible, layered architecture +features a fast, streaming interface with a minimal memory footprint. + +Check the ZBar home page for the latest release, mailing lists, etc. + http://zbar.sourceforge.net/ + +License information can be found in 'COPYING.LIB'. + + +INSTALLING +========== + +The zbarimg program uses ImageMagick to read image files. You will +need at least ImageMagick version 6.2.6 if you want to scan image +files. ImageMagick may be obtained from + http://www.imagemagick.org/ + +Download and install the current Windows binary release, making sure +that you select the *Dynamic* (DLL) version, eg: + ImageMagick-x.y.z-w-Q16-windows-dll.exe + +You will also want the "Update executable search path" box checked +during installation. + + +RUNNING +======= + +This version of the package includes *only command line programs*. +(The graphical interface is scheduled for a future release) + +Invoke Start -> Programs -> ZBar Bar Code Reader -> Start ZBar Command Prompt +to open a shell that has the zbarimg command available (in the PATH). + +To decode an image file, type: + zbarimg "C:\path\to\barcode.png" + +For basic command instructions, type: + zbarimg --help + +Check the manual for more details. + + +REPORTING BUGS +============== + +Bugs can be reported on the SourceForge project page + http://www.sourceforge.net/projects/zbar/ + +Please include the ZBar version number and a detailed description of +the problem. You'll probably have better luck if you're also familiar +with the concepts from: + http://www.catb.org/~esr/faqs/smart-questions.html diff --git a/TODO b/TODO index 4bb7f54..9c517b3 100644 --- a/TODO +++ b/TODO @@ -15,8 +15,6 @@ wrappers: * drag-and-drop for widgets (configurable...) * Perl build support integration? * Perl object lifetime problems? (eg Symbol) - * base library python bindings - * start w/enum wrappers * GTK and Qt perl bindings * C++ global wrappers @@ -59,6 +57,7 @@ image formats: window: * add XShm support * X protocol error handling + * Direct2D * API to query used interface (video, window?) (/format?) * mode to preserve aspect ratio (default?) * simple image manipulations scale(xv?)/mirror diff --git a/configure.ac b/configure.ac index 7741c7e..2773285 100644 --- a/configure.ac +++ b/configure.ac @@ -8,6 +8,7 @@ AC_CONFIG_HEADERS([include/config.h]) AC_CONFIG_SRCDIR(zbar/scanner.c) LT_PREREQ([2.2]) LT_INIT([dlopen win32-dll]) +LT_LANG([Windows Resource]) dnl update these just before each release (along w/pacakge version above) dnl LIB_VERSION update instructions copied from libtool docs: @@ -35,6 +36,16 @@ AC_DEFINE_UNQUOTED([ZBAR_VERSION_MINOR], [[`echo "$PACKAGE_VERSION" | sed -e 's/^[^.]*\.\([^.]*\)$/\1/'`]], [Program minor version (after '.') as a number]) +cur=`echo "$LIB_VERSION" | sed -e 's/:.*$//'` +age=`echo "$LIB_VERSION" | sed -e 's/^.*://'` +AC_DEFINE_UNQUOTED([LIB_VERSION_MAJOR], [[$(( $cur - $age ))]], + [Library major version]) +AC_DEFINE_UNQUOTED([LIB_VERSION_MINOR], [[$age]], + [Library minor version]) +AC_DEFINE_UNQUOTED([LIB_VERSION_REVISION], + [[`echo "$LIB_VERSION" | sed -e 's/^[^:]*:\([^:]*\):.*$/\1/'`]], + [Library revision]) + dnl windows build AC_CANONICAL_HOST diff --git a/examples/scan_image.vcproj b/examples/scan_image.vcproj new file mode 100644 index 0000000..1b2b64b --- /dev/null +++ b/examples/scan_image.vcproj @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/zbar.ico b/zbar.ico new file mode 100644 index 0000000000000000000000000000000000000000..82a09fa0414190a27e7d448540f9f79e8ac7513f GIT binary patch literal 6318 zcmeHLZ%k8H6#qes;!{d#E8qjApg@r-w1umnz$?^0I2Eyz&JD4J$u#>g7qczdVl-;p zmo0A5keFpkG+8t;W}3OLIFe2IP&*xG(t!@@tE`N+Ex-%~a1qAJaU^`4D5<*Q zzuY!a&R}$O4582%#>U1bx+Q7>Edb4I4g@^DERWqjq5V~Qzu%{8&1V%jttm^_fvieC zP79=XbPbO~wBfhwTC+R29h%8D;Wzf3=yxTim=wZ!a*}8yoKI1rbcs4~8!L|=|4G#j zjEww6dL79zk^+*Cp=meq;fFuM=evQHmMhekjw46<1+PFFyxyx=yY>nmJ{%=m7tWn~ zfUd6FRPP}qyG5ZQBs` z?!8O(5)vDZAMeNR-FK*d2qh&0VC)9fGjZX_8P^_+(H;*3K!mPi1|-hlF+Wi?B3jj_VMvv%VIb4Ea!7Jn7=8D zxzihs?cR!+Zl%s;INs}@VO8Aa3yk~|Uu7%ZY_`eZ`r7)zrO;ux|D}aY$(dtpM{S|P=GPmJ2Yj^usY&dZ zMdzbB+4-B#*piGS=QA^pDV{}1&hOG?iaV_!$@y+l-7Mdh8tW3#MRP{V;w$DVaa`NOb zp%`*24GkzZcDSHd8xIMO_5qxaF> zeOu&DKo0ep$j5i&e+$(k=;-Jo?I4*h(+oTt23kdFK?~PH1?fYhb3Q#g`7x3@ zKQm?$UR_coi$~T*PHSzBq<^%eaeQdDG`_W6Y=a^HE97nDC*wMbh_ueJ8&u3reKlhs=%qW)(=|TXV%t)a2iv zHRAqO3s$Axs}20VuiVaAmBJUjz~6_)Y*{>Z&EfCK%WEb5(_cIpoYlGMa`T~;cJJUU zdCgMu=gchH%2{f6Mj!e~?@7Y4c zJ5K~4nRrywz;ATw3Ne645JevyUDlNM?Zx^0MprH57#V!9Y#qPRO%z_@@J_37JnH0l zwRzHezF0g|)Ggj0ejoo4kJ94(M`A!@{G@m!;a`jQ?_6v=e?6YIPl~6Ut;BpvpMUB1 ZN; +# +# 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 +#------------------------------------------------------------------------ + +!ifndef VERSION + !define VERSION "test" +!endif + +!define ZBAR_KEY "Software\ZBar" +!define UNINSTALL_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\ZBar" + +OutFile zbar-${VERSION}-setup.exe + +SetCompressor /SOLID bzip2 + +InstType "Typical" +InstType "Full" + +InstallDir $PROGRAMFILES\ZBar +InstallDirRegKey HKLM ${ZBAR_KEY} "InstallDir" + +!define SMPROG_ZBAR "$SMPROGRAMS\ZBar Bar Code Reader" + +# do we need admin to install DLL and uninstall info? +RequestExecutionLevel admin + + +!include "MUI2.nsh" +!include "Memento.nsh" + + +Name "ZBar" +Caption "ZBar ${VERSION} Setup" + + +# Check that ImageMagick is installed +Function .onInit + SearchPath $0 "CORE_RL_wand_.dll" + IfErrors 0 goinstall + MessageBox MB_OKCANCEL|MB_ICONSTOP \ + "ImageMagick was not found in your PATH!$\n\ + $\n\ + The zbarimg program will not be able to scan image files \ + unless you install ImageMagick$\n\ + $\n\ + See the README for more details$\n\ + $\n\ + Press OK to continue anyway...$\n\ + Press Cancel to abort the installation..." \ + /SD IDCANCEL \ + IDOK goinstall + Abort +goinstall: +FunctionEnd + + +!define MEMENTO_REGISTRY_ROOT HKLM +!define MEMENTO_REGISTRY_KEY ${UNINSTALL_KEY} + +!define MUI_ABORTWARNING +!define MUI_FINISHPAGE_NOAUTOCLOSE +!define MUI_UNFINISHPAGE_NOAUTOCLOSE + +!define MUI_ICON ${NSISDIR}\Contrib\Graphics\Icons\orange-install.ico +!define MUI_UNICON ${NSISDIR}\Contrib\Graphics\Icons\orange-uninstall.ico + +!define MUI_WELCOMEFINISHPAGE_BITMAP ${NSISDIR}\Contrib\Graphics\Wizard\orange.bmp +!define MUI_UNWELCOMEFINISHPAGE_BITMAP ${NSISDIR}\Contrib\Graphics\Wizard\orange-uninstall.bmp + +!define MUI_HEADERIMAGE +!define MUI_HEADERIMAGE_BITMAP ${NSISDIR}\Contrib\Graphics\Header\orange.bmp +!define MUI_HEADERIMAGE_UNBITMAP ${NSISDIR}\Contrib\Graphics\Header\orange-uninstall.bmp + +!define MUI_WELCOMEPAGE_TITLE "Welcome to the ZBar ${VERSION} Setup Wizard" +!define MUI_WELCOMEPAGE_TEXT \ + "This wizard will guide you through the installation of the \ + ZBar Bar Code Reader version ${VERSION}." + +!insertmacro MUI_PAGE_WELCOME +!insertmacro MUI_PAGE_LICENSE "share\doc\zbar\COPYING.LIB" + +!define MUI_COMPONENTSPAGE_SMALLDESC +!define MUI_COMPONENTSPAGE_CHECKBITMAP ${NSISDIR}\Contrib\Graphics\Checks\simple-round2.bmp + +!insertmacro MUI_PAGE_COMPONENTS +!insertmacro MUI_PAGE_DIRECTORY +!insertmacro MUI_PAGE_INSTFILES + +Function ShowREADME + Exec '"notepad.exe" "$INSTDIR\README.windows"' +FunctionEnd + +!define MUI_FINISHPAGE_NOREBOOTSUPPORT +!define MUI_FINISHPAGE_SHOWREADME +!define MUI_FINISHPAGE_SHOWREADME_FUNCTION ShowREADME +!define MUI_FINISHPAGE_LINK \ + "Visit the ZBar website for the latest news, FAQs and support" +!define MUI_FINISHPAGE_LINK_LOCATION "http://zbar.sourceforge.net/" + +!insertmacro MUI_PAGE_FINISH + +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_INSTFILES + +!insertmacro MUI_LANGUAGE "English" + +Section "ZBar Core Files (required)" SecCore + DetailPrint "Installing ZBar Program and Library..." + SectionIn 1 2 RO + + SetOutPath $INSTDIR + File share\doc\zbar\README.windows + File share\doc\zbar\NEWS + File share\doc\zbar\TODO + File share\doc\zbar\COPYING.LIB + + # emit a batch file to add the install directory to the path + FileOpen $0 zbarvars.bat w + FileWrite $0 "@rem Add the ZBar installation directory to the path$\n" + FileWrite $0 "@rem so programs may be run from the command prompt$\n" + FileWrite $0 "@set PATH=%PATH%;$INSTDIR\bin$\n" + FileWrite $0 "@echo For basic command instructions type:$\n" + FileWrite $0 "@echo zbarimg --help$\n" + FileClose $0 + + SetOutPath $INSTDIR\bin + File bin\libzbar-0.dll + File bin\zbarimg.exe + + SetOutPath $INSTDIR\doc + File share\doc\zbar\html\* + + SetOutPath $INSTDIR\examples + File share\zbar\barcode.png +SectionEnd + +#SectionGroup "Start Menu and Desktop Shortcuts" SecShortcuts + Section "Start Menu Shortcut" SecShortcutsStartMenu + DetailPrint "Creating Start Menu Shortcut..." + SectionIn 1 2 + SetOutPath $INSTDIR + #CreateShortCut "${SMPROG_ZBAR}\ZBar.lnk" "$INSTDIR\ZBar.exe" + CreateDirectory "${SMPROG_ZBAR}" + ExpandEnvStrings $0 '%comspec%' + CreateShortCut "${SMPROG_ZBAR}\Start ZBar Command Prompt.lnk" \ + $0 "/k $\"$\"$INSTDIR\zbarvars.bat$\"$\"" $0 + CreateShortCut "${SMPROG_ZBAR}\Command Reference.lnk" \ + "$\"$INSTDIR\doc\zbarimg.html$\"" + SectionEnd + +# Section "Desktop Shortcut" SecShortcutsDesktop +# DetailPrint "Creating Desktop Shortcut..." +# SectionIn 1 2 +# SetOutPath $INSTDIR +# #CreateShortCut "$DESKTOP\ZBar.lnk" "$INSTDIR\ZBar.exe" +# SectionEnd +#SectionGroupEnd + +Section "Development Headers and Libraries" SecDevel + DetailPrint "Installing ZBar Development Files..." + SectionIn 2 + + SetOutPath $INSTDIR\include + File include\zbar.h + + SetOutPath $INSTDIR\include\zbar + File include\zbar\Video.h + File include\zbar\Exception.h + File include\zbar\Symbol.h + File include\zbar\Image.h + File include\zbar\ImageScanner.h + File include\zbar\Window.h + File include\zbar\Processor.h + File include\zbar\Decoder.h + File include\zbar\Scanner.h + + SetOutPath $INSTDIR\lib + File lib\libzbar-0.def + File lib\libzbar-0.lib + + SetOutPath $INSTDIR\examples + File share\zbar\scan_image.cpp + File share\zbar\scan_image.vcproj +SectionEnd + +Section -post + DetailPrint "Creating Registry Keys..." + SetOutPath $INSTDIR + WriteRegStr HKLM ${ZBAR_KEY} "InstallDir" $INSTDIR + + # register uninstaller + WriteRegStr HKLM ${UNINSTALL_KEY} "UninstallString" \ + "$\"$INSTDIR\uninstall.exe$\"" + WriteRegStr HKLM ${UNINSTALL_KEY} "QuietUninstallString" \ + "$\"$INSTDIR\uninstall.exe$\" /S" + WriteRegStr HKLM ${UNINSTALL_KEY} "InstallLocation" "$\"$INSTDIR$\"" + + WriteRegStr HKLM ${UNINSTALL_KEY} "DisplayName" "ZBar Bar Code Reader" + WriteRegStr HKLM ${UNINSTALL_KEY} "DisplayIcon" "$INSTDIR\zbarimg.exe,0" + WriteRegStr HKLM ${UNINSTALL_KEY} "DisplayVersion" "${VERSION}" + + WriteRegStr HKLM ${UNINSTALL_KEY} "URLInfoAbout" "http://zbar.sf.net/" + WriteRegStr HKLM ${UNINSTALL_KEY} "HelpLink" "http://zbar.sf.net/" + WriteRegDWORD HKLM ${UNINSTALL_KEY} "NoModify" "1" + WriteRegDWORD HKLM ${UNINSTALL_KEY} "NoRepair" "1" + + DetailPrint "Generating Uninstaller..." + WriteUninstaller $INSTDIR\uninstall.exe +SectionEnd + + +Section Uninstall + DetailPrint "Uninstalling ZBar Bar Code Reader.." + + DetailPrint "Deleting Files..." + RMDir /r $INSTDIR\examples + RMDir /r $INSTDIR\include + RMDir /r $INSTDIR\doc + RMDir /r $INSTDIR\lib + RMDir /r $INSTDIR\bin + Delete $INSTDIR\README.windows + Delete $INSTDIR\NEWS + Delete $INSTDIR\TODO + Delete $INSTDIR\COPYING.LIB + Delete $INSTDIR\zbarvars.bat + Delete $INSTDIR\uninstall.exe + RMDir $INSTDIR + + DetailPrint "Removing Shortcuts..." + RMDir /r "${SMPROG_ZBAR}" + + DetailPrint "Deleting Registry Keys..." + DeleteRegKey HKLM ${ZBAR_KEY} + DeleteRegKey HKLM ${UNINSTALL_KEY} +SectionEnd + + +!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN + !insertmacro MUI_DESCRIPTION_TEXT ${SecCore} \ + "The core files required to use the bar code reader" +# !insertmacro MUI_DESCRIPTION_TEXT ${SecShortcuts} \ +# "Adds icons to your start menu and/or your desktop for easy access" + !insertmacro MUI_DESCRIPTION_TEXT ${SecShortcutsStartMenu} \ + "Adds shortcuts to your start menu" +# !insertmacro MUI_DESCRIPTION_TEXT ${SecShortcutsDesktop} \ +# "Adds an icon on your desktop" + !insertmacro MUI_DESCRIPTION_TEXT ${SecDevel} \ + "Optional files used to develop other applications using ZBar" +!insertmacro MUI_FUNCTION_DESCRIPTION_END diff --git a/zbar/Makefile.am.inc b/zbar/Makefile.am.inc index 12fc2ab..2220e48 100644 --- a/zbar/Makefile.am.inc +++ b/zbar/Makefile.am.inc @@ -33,9 +33,11 @@ if HAVE_POLL zbar_libzbar_la_SOURCES += zbar/processor/posix.h zbar/processor/posix.c endif if WIN32 -zbar_libzbar_la_SOURCES += zbar/processor/win.h zbar/processor/win.c +zbar_libzbar_la_SOURCES += zbar/processor/win.h zbar/processor/win.c \ + zbar/libzbar.rc zbar_libzbar_la_CPPFLAGS += -mthreads zbar_libzbar_la_LDFLAGS += -mthreads +zbar_libzbar_la_LIBADD += zbar/libzbar-rc.lo endif if HAVE_V4L1 diff --git a/zbar/libzbar.rc b/zbar/libzbar.rc new file mode 100644 index 0000000..3ce2b9c --- /dev/null +++ b/zbar/libzbar.rc @@ -0,0 +1,32 @@ +#include +#include + +#define STR(s) #s +#define XSTR(s) STR(s) + +VS_VERSION_INFO VERSIONINFO + FILEVERSION LIB_VERSION_MAJOR, LIB_VERSION_MINOR, LIB_VERSION_REVISION, 0 + PRODUCTVERSION ZBAR_VERSION_MAJOR, ZBAR_VERSION_MINOR, 0, 0 + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL +{ + BLOCK "StringFileInfo" { + BLOCK "040904E4" { + VALUE "ProductName", "ZBar Bar Code Reader" + VALUE "Company Name", "ZBar Bar Code Reader" + VALUE "InternalName", "libzbar" + VALUE "OriginalFilename", "libzbar-" XSTR(LIB_VERSION_MAJOR) ".dll" + + VALUE "FileVersion", XSTR(LIB_VERSION_MAJOR) "." \ + XSTR(LIB_VERSION_MINOR) "." XSTR(LIB_VERSION_REVISION) + VALUE "ProductVersion", PACKAGE_VERSION + + VALUE "FileDescription", "Bar code scanning library" + + VALUE "LegalCopyright", "Copyright 2007-2009 (c) Jeff Brown " + } + } + BLOCK "VarFileInfo" { + VALUE "Translation", 0x0409, 0x04e4 + } +} diff --git a/zbarimg/Makefile.am.inc b/zbarimg/Makefile.am.inc index 520b077..8ba4e3c 100644 --- a/zbarimg/Makefile.am.inc +++ b/zbarimg/Makefile.am.inc @@ -4,3 +4,8 @@ zbarimg_zbarimg_CPPFLAGS = $(MAGICK_CFLAGS) $(AM_CPPFLAGS) zbarimg_zbarimg_LDADD = $(MAGICK_LIBS) zbar/libzbar.la # automake bug in "monolithic mode"? CLEANFILES += zbarimg/.libs/zbarimg + +if WIN32 +zbarimg_zbarimg_SOURCES += zbarimg/zbarimg.rc +zbarimg_zbarimg_LDADD += zbarimg/zbarimg-rc.o +endif diff --git a/zbarimg/zbarimg.rc b/zbarimg/zbarimg.rc new file mode 100644 index 0000000..ba70033 --- /dev/null +++ b/zbarimg/zbarimg.rc @@ -0,0 +1,30 @@ +#include +#include + +VS_VERSION_INFO VERSIONINFO + FILEVERSION ZBAR_VERSION_MAJOR, ZBAR_VERSION_MINOR, 0, 0 + PRODUCTVERSION ZBAR_VERSION_MAJOR, ZBAR_VERSION_MINOR, 0, 0 + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP +{ + BLOCK "StringFileInfo" { + BLOCK "040904E4" { + VALUE "ProductName", "ZBar Bar Code Reader" + VALUE "Company Name", "ZBar Bar Code Reader" + VALUE "InternalName", "zbarimg" + VALUE "OriginalFilename", "zbarimg.exe" + + VALUE "FileVersion", PACKAGE_VERSION + VALUE "ProductVersion", PACKAGE_VERSION + + VALUE "FileDescription", "Scan bar codes from image files" + + VALUE "LegalCopyright", "Copyright 2007-2009 (c) Jeff Brown " + } + } + BLOCK "VarFileInfo" { + VALUE "Translation", 0x0409, 0x04e4 + } +} + +APP_ICON ICON "zbar.ico" From 9f19b2bd4ab5521fb1ab52631cc35adad79cfa1d Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 30 Jun 2009 21:21:24 -0400 Subject: [PATCH 100/328] fix Code39 max ICS checks - add decoder lock owner tracking (debug) - update dbg_scan to match img_scanner --- ChangeLog | 3 +++ test/dbg_scan.cpp | 8 ++++++-- zbar/decoder.h | 7 ++++--- zbar/decoder/code128.c | 4 ++-- zbar/decoder/code39.c | 8 ++++---- zbar/decoder/ean.c | 4 ++-- zbar/decoder/i25.c | 4 ++-- zbar/decoder/pdf417.c | 4 ++-- 8 files changed, 25 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index eaaa45b..721a605 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,7 @@ current: + * fix Code39 max ICS checks + - add decoder lock owner tracking (debug) + - update dbg_scan to match img_scanner * first pass installer - add version and icon resources for libzbar, zbarimg * zbarimg working in windows diff --git a/test/dbg_scan.cpp b/test/dbg_scan.cpp index e0e52c5..47eb8af 100644 --- a/test/dbg_scan.cpp +++ b/test/dbg_scan.cpp @@ -68,10 +68,14 @@ void scan_image (const char *filename) unsigned inwidth = image.columns(); unsigned flush1 = inwidth / 32; + if(flush1 < 8) + flush1 = 8; unsigned flush0 = 2; unsigned width = inwidth + flush1 + flush0; unsigned height = image.rows(); - unsigned midy = (height + 1) / 2 + 2; + unsigned midy = height / 2; + cerr << "x+: " << midy << endl; + image.crop(Magick::Geometry(inwidth, 1, 0, midy)); image.size(Magick::Geometry(width, 1, 0, 0)); @@ -129,7 +133,7 @@ void scan_image (const char *filename) y.v(0); *pxp = y; } - y.y(max); /* flush scan FIXME? */ + y.y(1.0); /* flush scan FIXME? */ for(; i < inwidth + flush1; i++) { raw[i] = (unsigned)(y.y() * 0x100); svg << " " << i << "," << raw[i]; diff --git a/zbar/decoder.h b/zbar/decoder.h index ef2fba6..8f0a120 100644 --- a/zbar/decoder.h +++ b/zbar/decoder.h @@ -76,7 +76,7 @@ struct zbar_decoder_s { unsigned char idx; /* current width index */ unsigned w[DECODE_WINDOW]; /* window of last N bar widths */ zbar_symbol_type_t type; /* type of last decoded data */ - unsigned lock : 1; /* buffer lock */ + zbar_symbol_type_t lock; /* buffer lock */ /* everything above here is automatically reset */ unsigned char *buf; /* decoded characters */ @@ -161,11 +161,12 @@ static inline int decode_e (unsigned e, } /* acquire shared state lock */ -static inline char get_lock (zbar_decoder_t *dcode) +static inline char get_lock (zbar_decoder_t *dcode, + zbar_symbol_type_t req) { if(dcode->lock) return(1); - dcode->lock = 1; + dcode->lock = req; return(0); } diff --git a/zbar/decoder/code128.c b/zbar/decoder/code128.c index 3dc1120..d8f3ff5 100644 --- a/zbar/decoder/code128.c +++ b/zbar/decoder/code128.c @@ -450,8 +450,8 @@ zbar_symbol_type_t _zbar_decode_code128 (zbar_decoder_t *dcode) return(0); } /* lock shared resources */ - if(get_lock(dcode)) { - dprintf(2, " [locked]\n"); + if(get_lock(dcode, ZBAR_CODE128)) { + dprintf(2, " [locked %d]\n", dcode->lock); dcode128->character = -1; return(0); } diff --git a/zbar/decoder/code39.c b/zbar/decoder/code39.c index 2edb262..8c1c1f3 100644 --- a/zbar/decoder/code39.c +++ b/zbar/decoder/code39.c @@ -267,7 +267,7 @@ zbar_symbol_type_t _zbar_decode_code39 (zbar_decoder_t *dcode) zbar_symbol_type_t sym = ZBAR_CODE39; /* trailing quiet zone check */ - if(space < dcode39->width / 4) { + if(space < dcode39->width / 2) { dprintf(2, " [invalid qz]\n"); sym = ZBAR_NONE; } @@ -287,7 +287,7 @@ zbar_symbol_type_t _zbar_decode_code39 (zbar_decoder_t *dcode) dcode->lock = 0; return(sym); } - if(space > dcode39->width / 4) { + if(space > dcode39->width / 2) { /* inter-character space check failure */ dcode->lock = 0; dcode39->character = -1; @@ -302,9 +302,9 @@ zbar_symbol_type_t _zbar_decode_code39 (zbar_decoder_t *dcode) dprintf(2, " c=%d", c); /* lock shared resources */ - if(!dcode39->character && get_lock(dcode)) { + if(!dcode39->character && get_lock(dcode, ZBAR_CODE39)) { dcode39->character = -1; - dprintf(1, " [locked]\n"); + dprintf(1, " [locked %d]\n", dcode->lock); return(ZBAR_PARTIAL); } diff --git a/zbar/decoder/ean.c b/zbar/decoder/ean.c index 2ef22f0..9f16196 100644 --- a/zbar/decoder/ean.c +++ b/zbar/decoder/ean.c @@ -623,10 +623,10 @@ zbar_symbol_type_t _zbar_decode_ean (zbar_decoder_t *dcode) dcode->ean.pass[0].state = dcode->ean.pass[1].state = -1; dcode->ean.pass[2].state = dcode->ean.pass[3].state = -1; if(sym > ZBAR_PARTIAL) { - if(!get_lock(dcode)) + if(!get_lock(dcode, ZBAR_EAN13)) postprocess(dcode, sym); else { - dprintf(1, " [locked]"); + dprintf(1, " [locked %d]", dcode->lock); sym = ZBAR_PARTIAL; } } diff --git a/zbar/decoder/i25.c b/zbar/decoder/i25.c index ffa0e3d..6be9232 100644 --- a/zbar/decoder/i25.c +++ b/zbar/decoder/i25.c @@ -187,9 +187,9 @@ zbar_symbol_type_t _zbar_decode_i25 (zbar_decoder_t *dcode) dcode25->character, dcode25->element); /* lock shared resources */ - if(!dcode25->character && get_lock(dcode)) { + if(!dcode25->character && get_lock(dcode, ZBAR_I25)) { dcode25->character = -1; - dprintf(2, " [locked]\n"); + dprintf(2, " [locked %d]\n", dcode->lock); return(ZBAR_PARTIAL); } diff --git a/zbar/decoder/pdf417.c b/zbar/decoder/pdf417.c index 2c9f043..ac948e9 100644 --- a/zbar/decoder/pdf417.c +++ b/zbar/decoder/pdf417.c @@ -152,8 +152,8 @@ static inline signed char pdf417_decode_start(zbar_decoder_t *dcode) } /* lock shared resources */ - if(get_lock(dcode)) { - dprintf(2, " [locked]\n"); + if(get_lock(dcode, ZBAR_PDF417)) { + dprintf(2, " [locked %d]\n", dcode->lock); return(0); } From 8e126b7ee996928a81a5af0e004694965a1aae1a Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 2 Jul 2009 21:08:59 -0400 Subject: [PATCH 101/328] fix scan (image) boundary QZ handling (bug #2807538) - add linear scanner manual flush API - linear scanner always starts/ends w/a space of width 0 - remove artificial image scanner border - decoders special case 0 width space for QZ checks - add missing Code 128 leading QZ check --- ChangeLog | 8 ++++- Makefile.am | 2 +- include/zbar.h | 12 ++++++++ include/zbar/Scanner.h | 13 +++++++-- test/Makefile.am.inc | 2 +- test/dbg_scan.cpp | 66 +++++++++++++++++------------------------- zbar/decoder/code128.c | 5 ++++ zbar/decoder/code39.c | 7 ++--- zbar/decoder/ean.c | 6 ++-- zbar/decoder/i25.c | 8 ++--- zbar/img_scanner.c | 27 ++++++----------- zbar/scanner.c | 57 ++++++++++++++++++++++++++---------- 12 files changed, 124 insertions(+), 89 deletions(-) diff --git a/ChangeLog b/ChangeLog index 721a605..08e9a89 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ current: - * fix Code39 max ICS checks + * fix scan (image) boundary QZ handling (bug #2807538) + - add linear scanner manual flush API + - linear scanner always starts/ends w/a space of width 0 + - remove artificial image scanner border + - decoders special case 0 width space for QZ checks + - add missing Code 128 leading QZ check + * fix Code39 max ICS checks (bug #2807447) - add decoder lock owner tracking (debug) - update dbg_scan to match img_scanner * first pass installer diff --git a/Makefile.am b/Makefile.am index 37120d5..e4403c2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ AM_CPPFLAGS = -I$(srcdir)/include -AM_CFLAGS = -Wall +AM_CFLAGS = -Wall -Werror AM_CXXFLAGS = $(AM_CFLAGS) ACLOCAL_AMFLAGS = -I config bin_PROGRAMS = diff --git a/include/zbar.h b/include/zbar.h index 122c98f..1f5caed 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -1093,9 +1093,21 @@ extern zbar_symbol_type_t zbar_scanner_reset(zbar_scanner_t *scanner); * @returns any decode results flushed from the pipeline * @note when not using callback handlers, the return value should * be checked the same as zbar_scan_y() + * @note call zbar_scanner_flush() at least twice before calling this + * method to ensure no decode results are lost */ extern zbar_symbol_type_t zbar_scanner_new_scan(zbar_scanner_t *scanner); +/** flush scanner processing pipeline. + * forces current scanner position to be a scan boundary. + * call multiple times (max 3) to completely flush decoder. + * @returns any decode/scan results flushed from the pipeline + * @note when not using callback handlers, the return value should + * be checked the same as zbar_scan_y() + * @since 0.9 + */ +extern zbar_symbol_type_t zbar_scanner_flush(zbar_scanner_t *scanner); + /** process next sample intensity value. * intensity (y) is in arbitrary relative units. * @returns result of zbar_decode_width() if a decoder is attached, diff --git a/include/zbar/Scanner.h b/include/zbar/Scanner.h index 3191f58..8c9a756 100644 --- a/include/zbar/Scanner.h +++ b/include/zbar/Scanner.h @@ -74,9 +74,18 @@ class Scanner { /// mark start of a new scan pass. /// see zbar_scanner_new_scan() - void new_scan () + zbar_symbol_type_t new_scan () { - zbar_scanner_new_scan(_scanner); + _type = zbar_scanner_new_scan(_scanner); + return(_type); + } + + /// flush scanner pipeline. + /// see zbar_scanner_flush() + zbar_symbol_type_t flush () + { + _type = zbar_scanner_flush(_scanner); + return(_type); } /// process next sample intensity value. diff --git a/test/Makefile.am.inc b/test/Makefile.am.inc index ccab8bb..e3b2c00 100644 --- a/test/Makefile.am.inc +++ b/test/Makefile.am.inc @@ -36,7 +36,7 @@ if HAVE_MAGICK EXTRA_PROGRAMS += test/dbg_scan test_dbg_scan_SOURCES = test/dbg_scan.cpp test_dbg_scan_CPPFLAGS = $(MAGICK_CFLAGS) $(AM_CPPFLAGS) -test_dbg_scan_LDADD = $(MAGICK_LIBS) zbar/libzbar.la $(AM_LDADD) +test_dbg_scan_LDADD = $(MAGICK_LIBS) -lMagick++ zbar/libzbar.la $(AM_LDADD) endif if HAVE_GTK diff --git a/test/dbg_scan.cpp b/test/dbg_scan.cpp index 47eb8af..da0d38e 100644 --- a/test/dbg_scan.cpp +++ b/test/dbg_scan.cpp @@ -67,17 +67,12 @@ void scan_image (const char *filename) ofstream svg((file + ".svg").c_str()); unsigned inwidth = image.columns(); - unsigned flush1 = inwidth / 32; - if(flush1 < 8) - flush1 = 8; - unsigned flush0 = 2; - unsigned width = inwidth + flush1 + flush0; + unsigned width = inwidth + 3; unsigned height = image.rows(); unsigned midy = height / 2; cerr << "x+: " << midy << endl; image.crop(Magick::Geometry(inwidth, 1, 0, midy)); - image.size(Magick::Geometry(width, 1, 0, 0)); svg << "" << endl << "" << endl - << "" << endl << "" << endl; // brute force - unsigned raw[width]; + unsigned raw[inwidth]; { // extract scan from image pixels image.modifyImage(); Magick::Pixels view(image); - Magick::PixelPacket *pxp = view.get(0, 0, width, 1); + Magick::PixelPacket *pxp = view.get(0, 0, inwidth, 1); Magick::ColorYUV y; double max = 0; svg << "" << endl << "" << endl; @@ -158,27 +141,28 @@ void scan_image (const char *filename) svg << "" << endl; for(unsigned i = 0; i < width; i++) { - int edge = scanner.scan_y(raw[i]); + int edge; + if(i < inwidth) + edge = scanner.scan_y(raw[i]); + else + edge = scanner.flush(); + unsigned x; - zbar_scanner_get_state(scanner.get_c_scanner(), &x, - &cur_edge[i], &last_edge[i], - &y0[i], &y1[i], &y2[i], &y1_thr[i]); -#ifdef DEBUG_SCANNER - cerr << endl; -#endif - cur_edge[i] += i - x; + zbar_scanner_get_state(scanner, &x, + &cur_edge[i], &last_edge[i], + &y0[i], &y1[i], &y2[i], &y1_thr[i]); if(edge) { - last_edge[i] += i - x; unsigned w = scanner.get_width(); - svg << "" << endl - << "" << endl - << w << "" << endl; + if(w) + svg << "" << endl + << "" << endl + << w << "" << endl; zbar_symbol_type_t sym = decoder.decode_width(w); if(sym > ZBAR_PARTIAL) { svg << " Date: Fri, 3 Jul 2009 09:12:39 -0400 Subject: [PATCH 103/328] initial hooks for QR Code, first pass at finder --- ChangeLog | 1 + Makefile.am | 2 +- configure.ac | 3 +- include/zbar.h | 1 + test/dbg_scan.cpp | 2 +- zbar/Makefile.am.inc | 3 ++ zbar/config.c | 4 ++ zbar/decoder.c | 23 +++++++++++- zbar/decoder.h | 6 +++ zbar/decoder/qr_finder.c | 80 ++++++++++++++++++++++++++++++++++++++++ zbar/decoder/qr_finder.h | 20 ++++++++++ zbar/symbol.c | 1 + 12 files changed, 142 insertions(+), 4 deletions(-) create mode 100644 zbar/decoder/qr_finder.c create mode 100644 zbar/decoder/qr_finder.h diff --git a/ChangeLog b/ChangeLog index eaaa45b..c63dc18 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * initial hooks for QR Code, first pass at finder * first pass installer - add version and icon resources for libzbar, zbarimg * zbarimg working in windows diff --git a/Makefile.am b/Makefile.am index 37120d5..e4403c2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ AM_CPPFLAGS = -I$(srcdir)/include -AM_CFLAGS = -Wall +AM_CFLAGS = -Wall -Werror AM_CXXFLAGS = $(AM_CFLAGS) ACLOCAL_AMFLAGS = -I config bin_PROGRAMS = diff --git a/configure.ac b/configure.ac index 517b178..3fb3ddb 100644 --- a/configure.ac +++ b/configure.ac @@ -80,7 +80,7 @@ AC_ARG_ENABLE([codes], [AS_HELP_STRING([--enable-codes=SYMS], [select symbologies to compile [default=ean,i25,code39,code128]])], [], - [enable_codes="ean,code39,code128,i25"]) dnl pdf417 + [enable_codes="ean,code39,code128,i25"]) dnl pdf417,qr AC_DEFUN([ZBAR_CHK_CODE], [ AC_MSG_CHECKING([whether to build $2]) @@ -102,6 +102,7 @@ ZBAR_CHK_CODE([code128], [Code 128 symbology]) ZBAR_CHK_CODE([code39], [Code 39 symbology]) ZBAR_CHK_CODE([pdf417], [PDF417 symbology]) ZBAR_CHK_CODE([i25], [Interleaved 2 of 5 symbology]) +ZBAR_CHK_CODE([qr], [QR Code]) dnl libraries diff --git a/include/zbar.h b/include/zbar.h index 122c98f..cd1b431 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -95,6 +95,7 @@ typedef enum zbar_symbol_type_e { ZBAR_I25 = 25, /**< Interleaved 2 of 5. @since 0.4 */ ZBAR_CODE39 = 39, /**< Code 39. @since 0.4 */ ZBAR_PDF417 = 57, /**< PDF417. @since 0.6 */ + ZBAR_QR = 64, /**< QR Code. @since 0.9 */ ZBAR_CODE128 = 128, /**< Code 128 */ ZBAR_SYMBOL = 0x00ff, /**< mask for base symbol type */ ZBAR_ADDON2 = 0x0200, /**< 2-digit add-on flag */ diff --git a/test/dbg_scan.cpp b/test/dbg_scan.cpp index e0e52c5..4ef6366 100644 --- a/test/dbg_scan.cpp +++ b/test/dbg_scan.cpp @@ -71,7 +71,7 @@ void scan_image (const char *filename) unsigned flush0 = 2; unsigned width = inwidth + flush1 + flush0; unsigned height = image.rows(); - unsigned midy = (height + 1) / 2 + 2; + unsigned midy = height / 2; image.crop(Magick::Geometry(inwidth, 1, 0, midy)); image.size(Magick::Geometry(width, 1, 0, 0)); diff --git a/zbar/Makefile.am.inc b/zbar/Makefile.am.inc index 2220e48..e84e16d 100644 --- a/zbar/Makefile.am.inc +++ b/zbar/Makefile.am.inc @@ -28,6 +28,9 @@ if ENABLE_PDF417 zbar_libzbar_la_SOURCES += zbar/decoder/pdf417.h zbar/decoder/pdf417.c \ zbar/decoder/pdf417_hash.h endif +if ENABLE_QR +zbar_libzbar_la_SOURCES += zbar/decoder/qr_finder.h zbar/decoder/qr_finder.c +endif if HAVE_POLL zbar_libzbar_la_SOURCES += zbar/processor/posix.h zbar/processor/posix.c diff --git a/zbar/config.c b/zbar/config.c index df854d3..a2f450b 100644 --- a/zbar/config.c +++ b/zbar/config.c @@ -42,6 +42,10 @@ int zbar_parse_config (const char *cfgstr, int len = dot - cfgstr; if(!len || (len == 1 && !strncmp(cfgstr, "*", len))) *sym = 0; + else if(len < 2) + return(1); + else if(!strncmp(cfgstr, "qrcode", len)) + *sym = ZBAR_QR; else if(len < 3) return(1); else if(!strncmp(cfgstr, "upca", len)) diff --git a/zbar/decoder.c b/zbar/decoder.c index e35e88e..1dcd2e3 100644 --- a/zbar/decoder.c +++ b/zbar/decoder.c @@ -30,7 +30,7 @@ #include "decoder.h" #if defined(DEBUG_DECODER) || defined(DEBUG_EAN) || defined(DEBUG_CODE128) || \ - defined(DEBUG_CODE39) || defined(DEBUG_I25) || \ + defined(DEBUG_CODE39) || defined(DEBUG_I25) || defined(DEBUG_QR) || \ (defined(DEBUG_PDF417) && (DEBUG_PDF417 >= 4)) # define DEBUG_LEVEL 1 #endif @@ -68,6 +68,9 @@ zbar_decoder_t *zbar_decoder_create () #ifdef ENABLE_PDF417 dcode->pdf417.config = 1 << ZBAR_CFG_ENABLE; #endif +#ifdef ENABLE_QR + dcode->qrf.config = 1 << ZBAR_CFG_ENABLE; +#endif zbar_decoder_reset(dcode); return(dcode); @@ -98,6 +101,9 @@ void zbar_decoder_reset (zbar_decoder_t *dcode) #ifdef ENABLE_PDF417 pdf417_reset(&dcode->pdf417); #endif +#ifdef ENABLE_QR + qr_finder_reset(&dcode->qrf); +#endif } void zbar_decoder_new_scan (zbar_decoder_t *dcode) @@ -121,6 +127,9 @@ void zbar_decoder_new_scan (zbar_decoder_t *dcode) #ifdef ENABLE_PDF417 pdf417_reset(&dcode->pdf417); #endif +#ifdef ENABLE_QR + qr_finder_reset(&dcode->qrf); +#endif } @@ -193,6 +202,11 @@ zbar_symbol_type_t zbar_decode_width (zbar_decoder_t *dcode, (sym = _zbar_decode_pdf417(dcode)) > ZBAR_PARTIAL) dcode->type = sym; #endif +#ifdef ENABLE_QR + if(TEST_CFG(dcode->qrf.config, ZBAR_CFG_ENABLE) && + (sym = _zbar_find_qr(dcode)) > ZBAR_PARTIAL) + dcode->type = sym; +#endif dcode->idx++; if(dcode->type) { @@ -261,6 +275,12 @@ static inline int decoder_set_config_bool (zbar_decoder_t *dcode, break; #endif +#ifdef ENABLE_QR + case ZBAR_QR: + config = &dcode->qrf.config; + break; +#endif + /* FIXME handle addons */ default: @@ -339,6 +359,7 @@ int zbar_decoder_set_config (zbar_decoder_t *dcode, zbar_decoder_set_config(dcode, ZBAR_CODE39, cfg, val); zbar_decoder_set_config(dcode, ZBAR_CODE128, cfg, val); zbar_decoder_set_config(dcode, ZBAR_PDF417, cfg, val); + zbar_decoder_set_config(dcode, ZBAR_QR, cfg, val); return(0); } diff --git a/zbar/decoder.h b/zbar/decoder.h index ef2fba6..584bd94 100644 --- a/zbar/decoder.h +++ b/zbar/decoder.h @@ -45,6 +45,9 @@ #ifdef ENABLE_PDF417 # include "decoder/pdf417.h" #endif +#ifdef ENABLE_QR +# include "decoder/qr_finder.h" +#endif /* size of bar width history (implementation assumes power of two) */ #ifndef DECODE_WINDOW @@ -100,6 +103,9 @@ struct zbar_decoder_s { #ifdef ENABLE_PDF417 pdf417_decoder_t pdf417; /* PDF417 decode state */ #endif +#ifdef ENABLE_QR + qr_finder_t qrf; /* QR Code finder state */ +#endif }; /* return current element color */ diff --git a/zbar/decoder/qr_finder.c b/zbar/decoder/qr_finder.c new file mode 100644 index 0000000..61e2105 --- /dev/null +++ b/zbar/decoder/qr_finder.c @@ -0,0 +1,80 @@ +#include +#include + +#include +#include "decoder.h" + +#ifdef DEBUG_QR +# define DEBUG_LEVEL (DEBUG_QR) +#endif +#include "debug.h" + + +zbar_symbol_type_t _zbar_find_qr (zbar_decoder_t *dcode) +{ + qr_finder_t *qrf = &dcode->qrf; + + /* update latest finder pattern width */ + qrf->s5 -= get_width(dcode, 6); + qrf->s5 += get_width(dcode, 1); + unsigned s = qrf->s5; + + if(get_color(dcode) != ZBAR_SPACE || s < 7) + return(0); + + dprintf(2, " qrf: s=%d", s); + + int ei = decode_e(pair_width(dcode, 1), s, 7); + dprintf(2, " %d", ei); + if(ei) + return(0); + + ei = decode_e(pair_width(dcode, 2), s, 7); + dprintf(2, "%d", ei); + if(ei != 2) + return(0); + + ei = decode_e(pair_width(dcode, 3), s, 7); + dprintf(2, "%d", ei); + if(ei != 2) + return(0); + + ei = decode_e(pair_width(dcode, 4), s, 7); + dprintf(2, "%d", ei); + if(ei) + return(0); + + int tqz = get_width(dcode, 5); + if(tqz) { + tqz = (tqz + 1) * 7 / s; + dprintf(2, "%d", tqz); + if(tqz < 1) + return(0); + } + else + tqz = 4; + + int lqz = get_width(dcode, 0); + if(lqz) { + lqz = (lqz + 1) * 7 / s; + dprintf(2, "%d", lqz); + if(lqz < 0) + return(0); + } + else + lqz = 4; + + /* one border must be full QZ */ + if(tqz < 3 && lqz < 3) { + dprintf(2, " [invalid qz]\n"); + return(0); + } + + /* valid QR finder symbol */ + dprintf(2, " [valid]\n"); + + /* FIXME TBD: mark positions needed by decoder */ + assert(0); + + return(ZBAR_QR); +} diff --git a/zbar/decoder/qr_finder.h b/zbar/decoder/qr_finder.h new file mode 100644 index 0000000..b3d39aa --- /dev/null +++ b/zbar/decoder/qr_finder.h @@ -0,0 +1,20 @@ +#ifndef _DECODER_QR_FINDER_H_ +#define _DECODER_QR_FINDER_H_ + +/* QR Code symbol finder state */ +typedef struct qr_finder_s { + unsigned s5; /* finder pattern width */ + + unsigned config; +} qr_finder_t; + +/* reset QR finder specific state */ +static inline void qr_finder_reset (qr_finder_t *qrf) +{ + qrf->s5 = 0; +} + +/* find QR Code symbols */ +zbar_symbol_type_t _zbar_find_qr (zbar_decoder_t *dcode); + +#endif diff --git a/zbar/symbol.c b/zbar/symbol.c index 61dc28f..666c550 100644 --- a/zbar/symbol.c +++ b/zbar/symbol.c @@ -42,6 +42,7 @@ const char *zbar_get_symbol_name (zbar_symbol_type_t sym) case ZBAR_CODE39: return("CODE-39"); case ZBAR_CODE128: return("CODE-128"); case ZBAR_PDF417: return("PDF417"); + case ZBAR_QR: return("QR"); default: return("UNKNOWN"); } } From c70a0806ec3e0b250d695d45ea62781253b2f1bc Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 6 Jul 2009 14:12:01 -0400 Subject: [PATCH 104/328] zbar-side updates for QR Code integration - add linear scanner position interface - add QR finder position feedback - integrate QR Code reader with img_scanner - refactor some symbol/image interaction - change default scanner density to 1 - add iconv to build infrastructure --- ChangeLog | 7 +++ Makefile.am | 2 +- configure.ac | 1 + include/zbar.h | 7 +++ zbar/Makefile.am.inc | 11 +++- zbar/decoder.c | 5 +- zbar/decoder/qr_finder.c | 73 ++++++++++++++-------- zbar/decoder/qr_finder.h | 3 + zbar/image.h | 12 ++++ zbar/img_scanner.c | 130 ++++++++++++++++++++++++++++++++++----- zbar/scanner.c | 16 ++++- 11 files changed, 220 insertions(+), 47 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3c7d577..05e8353 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,11 @@ current: + * zbar-side updates for QR Code integration + - add linear scanner position interface + - add QR finder position feedback + - integrate QR Code reader with img_scanner + - refactor some symbol/image interaction + - change default scanner density to 1 + - add iconv to build infrastructure * initial hooks for QR Code, first pass at finder * fix zbarimg b&w format handling * fix scan (image) boundary QZ handling (bug #2807538) diff --git a/Makefile.am b/Makefile.am index e4403c2..fa17b15 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ AM_CPPFLAGS = -I$(srcdir)/include -AM_CFLAGS = -Wall -Werror +AM_CFLAGS = -Wall -Werror -Wno-parentheses AM_CXXFLAGS = $(AM_CFLAGS) ACLOCAL_AMFLAGS = -I config bin_PROGRAMS = diff --git a/configure.ac b/configure.ac index 3fb3ddb..3bd25b7 100644 --- a/configure.ac +++ b/configure.ac @@ -107,6 +107,7 @@ ZBAR_CHK_CODE([qr], [QR Code]) dnl libraries AC_SEARCH_LIBS([clock_gettime], [rt]) +AM_ICONV() dnl poll support dnl without poll() we exclude processor layer diff --git a/include/zbar.h b/include/zbar.h index 06b49a0..d646e3c 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -1128,6 +1128,13 @@ static inline zbar_symbol_type_t zbar_scan_rgb24 (zbar_scanner_t *scanner, /** retrieve last scanned width. */ extern unsigned zbar_scanner_get_width(const zbar_scanner_t *scanner); +/** retrieve sample position of last edge. + * @since 0.9 + */ +extern unsigned zbar_scanner_get_edge(const zbar_scanner_t *scn, + unsigned offset, + int prec); + /** retrieve last scanned color. */ extern zbar_color_t zbar_scanner_get_color(const zbar_scanner_t *scanner); diff --git a/zbar/Makefile.am.inc b/zbar/Makefile.am.inc index e84e16d..b27bb16 100644 --- a/zbar/Makefile.am.inc +++ b/zbar/Makefile.am.inc @@ -2,7 +2,7 @@ lib_LTLIBRARIES += zbar/libzbar.la zbar_libzbar_la_CPPFLAGS = -I$(srcdir)/zbar $(AM_CPPFLAGS) zbar_libzbar_la_LDFLAGS = -no-undefined -version-info $(LIB_VERSION) \ -export-symbols-regex "^(zbar|_zbar.*_error)_.*" $(AM_LDFLAGS) -zbar_libzbar_la_LIBADD = +zbar_libzbar_la_LIBADD = $(LTLIBICONV) zbar_libzbar_la_SOURCES = zbar/debug.h zbar/config.c \ zbar/error.h zbar/error.c zbar/symbol.h zbar/symbol.c \ @@ -29,7 +29,14 @@ zbar_libzbar_la_SOURCES += zbar/decoder/pdf417.h zbar/decoder/pdf417.c \ zbar/decoder/pdf417_hash.h endif if ENABLE_QR -zbar_libzbar_la_SOURCES += zbar/decoder/qr_finder.h zbar/decoder/qr_finder.c +zbar_libzbar_la_SOURCES += zbar/decoder/qrcode.h \ + zbar/decoder/qr_finder.h zbar/decoder/qr_finder.c \ + zbar/decoder/qr/qrdec.c zbar/decoder/qr/qrdectxt.c \ + zbar/decoder/qr/rs.h zbar/decoder/qr/rs.c \ + zbar/decoder/qr/isaac.h zbar/decoder/qr/isaac.c \ + zbar/decoder/qr/bch15_5.h zbar/decoder/qr/bch15_5.c \ + zbar/decoder/qr/binarize.h zbar/decoder/qr/binarize.c \ + zbar/decoder/qr/util.h zbar/decoder/qr/util.c endif if HAVE_POLL diff --git a/zbar/decoder.c b/zbar/decoder.c index 1dcd2e3..daf7eac 100644 --- a/zbar/decoder.c +++ b/zbar/decoder.c @@ -29,8 +29,9 @@ #include #include "decoder.h" -#if defined(DEBUG_DECODER) || defined(DEBUG_EAN) || defined(DEBUG_CODE128) || \ - defined(DEBUG_CODE39) || defined(DEBUG_I25) || defined(DEBUG_QR) || \ +#if defined(DEBUG_DECODER) || defined(DEBUG_EAN) || \ + defined(DEBUG_CODE39) || defined(DEBUG_I25) || \ + defined(DEBUG_CODE128) || defined(DEBUG_QR_FINDER) || \ (defined(DEBUG_PDF417) && (DEBUG_PDF417 >= 4)) # define DEBUG_LEVEL 1 #endif diff --git a/zbar/decoder/qr_finder.c b/zbar/decoder/qr_finder.c index 61e2105..934ef38 100644 --- a/zbar/decoder/qr_finder.c +++ b/zbar/decoder/qr_finder.c @@ -4,11 +4,18 @@ #include #include "decoder.h" -#ifdef DEBUG_QR -# define DEBUG_LEVEL (DEBUG_QR) +#ifdef DEBUG_QR_FINDER +# define DEBUG_LEVEL (DEBUG_QR_FINDER) #endif #include "debug.h" +/* at this point lengths are all decode unit offsets from the decode edge + * NB owned by finder + */ +qr_finder_line *_zbar_decoder_get_qr_finder_line (zbar_decoder_t *dcode) +{ + return(&dcode->qrf.line); +} zbar_symbol_type_t _zbar_find_qr (zbar_decoder_t *dcode) { @@ -27,54 +34,68 @@ zbar_symbol_type_t _zbar_find_qr (zbar_decoder_t *dcode) int ei = decode_e(pair_width(dcode, 1), s, 7); dprintf(2, " %d", ei); if(ei) - return(0); + goto invalid; ei = decode_e(pair_width(dcode, 2), s, 7); dprintf(2, "%d", ei); if(ei != 2) - return(0); + goto invalid; ei = decode_e(pair_width(dcode, 3), s, 7); dprintf(2, "%d", ei); if(ei != 2) - return(0); + goto invalid; ei = decode_e(pair_width(dcode, 4), s, 7); dprintf(2, "%d", ei); if(ei) - return(0); - - int tqz = get_width(dcode, 5); - if(tqz) { - tqz = (tqz + 1) * 7 / s; - dprintf(2, "%d", tqz); - if(tqz < 1) - return(0); - } - else - tqz = 4; + goto invalid; - int lqz = get_width(dcode, 0); + int lqz = get_width(dcode, 6); if(lqz) { lqz = (lqz + 1) * 7 / s; - dprintf(2, "%d", lqz); - if(lqz < 0) - return(0); + if(lqz < 1) + goto invalid; } else lqz = 4; + dprintf(2, "%d", lqz); + + int tqz = get_width(dcode, 0); + if(tqz) { + tqz = (tqz + 1) * 7 / s; + if(tqz < 0) + goto invalid; + } + else + tqz = 4; + dprintf(2, "%d", tqz); /* one border must be full QZ */ - if(tqz < 3 && lqz < 3) { + if(lqz < 3 && tqz < 3) { dprintf(2, " [invalid qz]\n"); return(0); } - /* valid QR finder symbol */ - dprintf(2, " [valid]\n"); - - /* FIXME TBD: mark positions needed by decoder */ - assert(0); + /* valid QR finder symbol + * mark positions needed by decoder + */ + unsigned qz = get_width(dcode, 0); + unsigned w = get_width(dcode, 1); + qrf->line.eoffs = qz + (w + 1) / 2; + qrf->line.len = qz + w + get_width(dcode, 2); + qrf->line.pos[0] = qrf->line.len + get_width(dcode, 3); + qrf->line.pos[1] = qrf->line.pos[0]; + w = get_width(dcode, 5); + qrf->line.boffs = qrf->line.pos[0] + get_width(dcode, 4) + (w + 1) / 2; + + dprintf(2, " boff=%d pos=%d len=%d eoff=%d [valid]\n", + qrf->line.boffs, qrf->line.pos[0], qrf->line.len, + qrf->line.eoffs); return(ZBAR_QR); + +invalid: + dprintf(2, " [invalid]\n"); + return(0); } diff --git a/zbar/decoder/qr_finder.h b/zbar/decoder/qr_finder.h index b3d39aa..11ab784 100644 --- a/zbar/decoder/qr_finder.h +++ b/zbar/decoder/qr_finder.h @@ -1,9 +1,12 @@ #ifndef _DECODER_QR_FINDER_H_ #define _DECODER_QR_FINDER_H_ +#include "qrcode.h" + /* QR Code symbol finder state */ typedef struct qr_finder_s { unsigned s5; /* finder pattern width */ + qr_finder_line line; /* position info needed by decoder */ unsigned config; } qr_finder_t; diff --git a/zbar/image.h b/zbar/image.h index 9673804..28d81f1 100644 --- a/zbar/image.h +++ b/zbar/image.h @@ -112,6 +112,18 @@ static inline void _zbar_image_refcnt (zbar_image_t *img, } } +static inline void _zbar_image_attach_symbol (zbar_image_t *img, + zbar_symbol_t *sym) +{ + /* symbols stored on root image */ + while(img->next) + img = img->next; + + sym->next = img->syms; + img->syms = sym; + img->nsyms++; +} + extern int _zbar_best_format(uint32_t, uint32_t*, const uint32_t*); extern const zbar_format_def_t *_zbar_format_lookup(uint32_t); diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 5592624..8dc3c7b 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -35,6 +35,9 @@ #include #include "error.h" #include "image.h" +#ifdef ENABLE_QR +# include "decoder/qrcode.h" +#endif #if 1 # define ASSERT_POS \ @@ -72,12 +75,16 @@ struct zbar_image_scanner_s { zbar_scanner_t *scn; /* associated linear intensity scanner */ zbar_decoder_t *dcode; /* associated symbol decoder */ +#ifdef ENABLE_QR + qr_reader *qr; /* QR Code 2D reader */ +#endif const void *userdata; /* application data */ /* user result callback */ zbar_image_data_handler_t *handler; zbar_image_t *img; /* currently scanning image *root* */ + int dx, dy; /* current scan direction */ int nsyms; /* total cached symbols */ zbar_symbol_t *syms; /* recycled symbols */ @@ -112,9 +119,10 @@ static inline void recycle_syms (zbar_image_scanner_t *iscn, } } -static inline zbar_symbol_t *alloc_sym (zbar_image_scanner_t *iscn, - zbar_symbol_type_t type, - const char *data) +inline zbar_symbol_t* +_zbar_image_scanner_alloc_sym (zbar_image_scanner_t *iscn, + zbar_symbol_type_t type, + const char *data) { /* recycle old or alloc new symbol */ zbar_symbol_t *sym = iscn->syms; @@ -165,6 +173,67 @@ static inline zbar_symbol_t *cache_lookup (zbar_image_scanner_t *iscn, return(*entry); } +#ifdef ENABLE_QR +extern qr_finder_line *_zbar_decoder_get_qr_finder_line(zbar_decoder_t*); + +# define QR_FIXED(v, rnd) ((((v) << 1) + (rnd)) << (QR_FINDER_SUBPREC - 1)) +# define PRINT_FIXED(val, prec) \ + ((val) >> (prec)), \ + (1000 * ((val) & ((1 << (prec)) - 1)) / (1 << (prec))) + +static void qr_handler (zbar_image_scanner_t *iscn, + int x, + int y) +{ + qr_finder_line *line = _zbar_decoder_get_qr_finder_line(iscn->dcode); + assert(line); + unsigned u = zbar_scanner_get_edge(iscn->scn, line->pos[0], + QR_FINDER_SUBPREC); + line->boffs = u - zbar_scanner_get_edge(iscn->scn, line->boffs, + QR_FINDER_SUBPREC); + line->len = zbar_scanner_get_edge(iscn->scn, line->len, + QR_FINDER_SUBPREC); + line->eoffs = zbar_scanner_get_edge(iscn->scn, line->eoffs, + QR_FINDER_SUBPREC) - line->len; + line->len -= u; + + if(iscn->dx) { + assert(!iscn->dy); + line->pos[1] = QR_FIXED(y, 1); + if(iscn->dx > 0) + line->pos[0] = u; + else { + line->pos[0] = QR_FIXED(iscn->img->width, 0) - u - line->len; + } + } + else { + assert(iscn->dy); + line->pos[0] = QR_FIXED(x, 1); + if(iscn->dy > 0) + line->pos[1] = u; + else { + line->pos[1] = QR_FIXED(iscn->img->height, 0) - u - line->len; + } + } + if(iscn->dx < 0 || iscn->dy < 0) { + int tmp = line->boffs; + line->boffs = line->eoffs; + line->eoffs = tmp; + } + + zprintf(54, "qrf: u=%d.%03d boff=%d.%03d pos=%d.%03d,%d.%03d" + " len=%d.%03d eoff=%d.%03d\n", + PRINT_FIXED(u, QR_FINDER_SUBPREC), + PRINT_FIXED(line->boffs, QR_FINDER_SUBPREC), + PRINT_FIXED(line->pos[0], QR_FINDER_SUBPREC), + PRINT_FIXED(line->pos[1], QR_FINDER_SUBPREC), + PRINT_FIXED(line->len, QR_FINDER_SUBPREC), + PRINT_FIXED(line->eoffs, QR_FINDER_SUBPREC)); + + _zbar_qr_found_line(iscn->qr, !iscn->dx, line); +} +#endif + static void symbol_handler (zbar_image_scanner_t *iscn, int x, int y) @@ -175,6 +244,13 @@ static void symbol_handler (zbar_image_scanner_t *iscn, if(type <= ZBAR_PARTIAL) return; +#ifdef ENABLE_QR + if(type == ZBAR_QR) { + qr_handler(iscn, x, y); + return; + } +#endif + const char *data = zbar_decoder_get_data(iscn->dcode); /* FIXME deprecate - instead check (x, y) inside existing polygon */ @@ -188,7 +264,7 @@ static void symbol_handler (zbar_image_scanner_t *iscn, return; } - sym = alloc_sym(iscn, type, data); + sym = _zbar_image_scanner_alloc_sym(iscn, type, data); /* timestamp symbol */ #if _POSIX_TIMERS > 0 @@ -206,14 +282,12 @@ static void symbol_handler (zbar_image_scanner_t *iscn, sym_add_point(sym, x, y); /* attach to current root image */ - sym->next = iscn->img->syms; - iscn->img->syms = sym; - iscn->img->nsyms++; + _zbar_image_attach_symbol(iscn->img, sym); if(iscn->enable_cache) { zbar_symbol_t *entry = cache_lookup(iscn, sym); if(!entry) { - entry = alloc_sym(iscn, sym->type, sym->data); + entry = _zbar_image_scanner_alloc_sym(iscn, sym->type, sym->data); entry->time = sym->time - CACHE_HYSTERESIS; entry->cache_count = -CACHE_CONSISTENCY; /* add to cache */ @@ -253,9 +327,13 @@ zbar_image_scanner_t *zbar_image_scanner_create () return(NULL); } +#ifdef ENABLE_QR + iscn->qr = qr_reader_alloc(); +#endif + /* apply default configuration */ - CFG(iscn, ZBAR_CFG_X_DENSITY) = 16; - CFG(iscn, ZBAR_CFG_Y_DENSITY) = 16; + CFG(iscn, ZBAR_CFG_X_DENSITY) = 1; + CFG(iscn, ZBAR_CFG_Y_DENSITY) = 1; return(iscn); } @@ -272,6 +350,12 @@ void zbar_image_scanner_destroy (zbar_image_scanner_t *iscn) sym_destroy(iscn->syms); iscn->syms = next; } +#ifdef ENABLE_QR + if(iscn->qr) { + qr_reader_free(iscn->qr); + iscn->qr = NULL; + } +#endif free(iscn); } @@ -326,6 +410,8 @@ static inline void quiet_border (zbar_image_scanner_t *iscn, symbol_handler(iscn, x, y); if(zbar_scanner_flush(iscn->scn)) symbol_handler(iscn, x, y); + if(zbar_scanner_flush(iscn->scn)) + symbol_handler(iscn, x, y); if(zbar_scanner_new_scan(iscn->scn)) symbol_handler(iscn, x, y); } @@ -341,6 +427,10 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, { recycle_syms(iscn, img); +#ifdef ENABLE_QR + qr_reader_reset(iscn->qr); +#endif + /* get grayscale image, convert if necessary */ img = zbar_image_convert(img, fourcc('Y','8','0','0')); if(!img) @@ -354,6 +444,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, if(density > 0) { const uint8_t *p = data; int x = 0, y = 0; + iscn->dy = 0; int border = (((h - 1) % density) + 1) / 2; if(border > h / 2) @@ -364,7 +455,8 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, symbol_handler(iscn, x, y); while(y < h) { - zprintf(32, "img_x+: %03x,%03x @%p\n", x, y, p); + zprintf(32, "img_x+: %04d,%04d @%p\n", x, y, p); + iscn->dx = 1; while(x < w) { ASSERT_POS; if(zbar_scan_y(iscn->scn, *p)) @@ -377,8 +469,9 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, if(y >= h) break; - zprintf(32, "img_x-: %03x,%03x @%p\n", x, y, p); - while(x > 0) { + zprintf(32, "img_x-: %04d,%04d @%p\n", x, y, p); + iscn->dx = -1; + while(x >= 0) { ASSERT_POS; if(zbar_scan_y(iscn->scn, *p)) symbol_handler(iscn, x, y); @@ -394,6 +487,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, if(density > 0) { const uint8_t *p = data; int x = 0, y = 0; + iscn->dx = 0; int border = (((w - 1) % density) + 1) / 2; if(border > w / 2) @@ -401,7 +495,8 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, movedelta(border, 0); while(x < w) { - zprintf(32, "img_y+: %03x,%03x @%p\n", x, y, p); + zprintf(32, "img_y+: %04d,%04d @%p\n", x, y, p); + iscn->dy = 1; while(y < h) { ASSERT_POS; if(zbar_scan_y(iscn->scn, *p)) @@ -414,7 +509,8 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, if(x >= w) break; - zprintf(32, "img_y-: %03x,%03x @%p\n", x, y, p); + zprintf(32, "img_y-: %04d,%04d @%p\n", x, y, p); + iscn->dy = -1; while(y >= 0) { ASSERT_POS; if(zbar_scan_y(iscn->scn, *p)) @@ -427,6 +523,10 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, } } +#ifdef ENABLE_QR + _zbar_qr_decode(iscn, iscn->qr, img); +#endif + /* release reference to converted image */ zbar_image_destroy(img); return(iscn->img->nsyms); diff --git a/zbar/scanner.c b/zbar/scanner.c index 08c9205..c9990e1 100644 --- a/zbar/scanner.c +++ b/zbar/scanner.c @@ -102,6 +102,20 @@ unsigned zbar_scanner_get_width (const zbar_scanner_t *scn) return(scn->width); } +unsigned zbar_scanner_get_edge (const zbar_scanner_t *scn, + unsigned offset, + int prec) +{ + unsigned edge = scn->last_edge - offset - (1 << ZBAR_FIXED) - ROUND; + prec = ZBAR_FIXED - prec; + if(prec > 0) + return(edge >> prec); + else if(!prec) + return(edge); + else + return(edge << -prec); +} + zbar_color_t zbar_scanner_get_color (const zbar_scanner_t *scn) { return((scn->y1_sign <= 0) ? ZBAR_SPACE : ZBAR_BAR); @@ -158,7 +172,7 @@ inline zbar_symbol_type_t zbar_scanner_flush (zbar_scanner_t *scn) if(!scn->y1_sign) return(ZBAR_NONE); - unsigned x = ((scn->x + 1) << ZBAR_FIXED) + ROUND; + unsigned x = (scn->x << ZBAR_FIXED) + ROUND; if(scn->cur_edge != x || scn->y1_sign > 0) { dprintf(1, "flush0:"); From beb1d6317e14bbff3edef67bf8450dbf51713c1a Mon Sep 17 00:00:00 2001 From: tterribe Date: Mon, 6 Jul 2009 23:57:37 +0000 Subject: [PATCH 105/328] Minor comment and macro updates, and an integer hypot implementation (for more accurate line fitting). --- qrcode/src/qrcode.h | 5 ++-- qrcode/src/qrdec.c | 48 +++++++++++++++++--------------------- qrcode/src/util.c | 57 +++++++++++++++++++++++++++++++++++++++------ qrcode/src/util.h | 10 ++++---- 4 files changed, 80 insertions(+), 40 deletions(-) diff --git a/qrcode/src/qrcode.h b/qrcode/src/qrcode.h index a7eb252..df5d886 100644 --- a/qrcode/src/qrcode.h +++ b/qrcode/src/qrcode.h @@ -42,7 +42,7 @@ typedef enum qr_mode{ Currently this is only modes with exactly one bit set.*/ #define QR_MODE_HAS_DATA(_mode) (!((_mode)&(_mode)-1)) -/*ECI may be used to signal a character encode for the data.*/ +/*ECI may be used to signal a character encoding for the data.*/ typedef enum qr_eci_encoding{ /*GLI0 is like CP437, but the encoding is reset at the beginning of each structured append symbol.*/ @@ -50,7 +50,8 @@ typedef enum qr_eci_encoding{ /*GLI1 is like ISO8859_1, but the encoding is reset at the beginning of each structured append symbol.*/ QR_ECI_GLI1, - /*The remaining encodings do not reset at next structured append symbol.*/ + /*The remaining encodings do not reset at the start of the next structured + append symbol.*/ QR_ECI_CP437, /*Western European.*/ QR_ECI_ISO8859_1, diff --git a/qrcode/src/qrdec.c b/qrcode/src/qrdec.c index 7ab987b..86eeb2d 100644 --- a/qrcode/src/qrdec.c +++ b/qrcode/src/qrdec.c @@ -86,8 +86,8 @@ void qr_reader_free(qr_reader *_reader){ /*A line crossing a finder pattern. Whether the line is horizontal or vertical is determined by context. The offsts to various parts of the finder pattern are as follows: - |*****| |*****************| |*****| - |*****| |*****************| |*****| + |*****| |*****|*****|*****| |*****| + |*****| |*****|*****|*****| |*****| ^ ^ ^ ^ | | | | | | | pos[v]+len+eoffs @@ -248,6 +248,7 @@ static int qr_finder_cluster_lines(qr_finder_cluster *_clusters, int nneighbors; int nclusters; int i; + /*TODO: Kalman filters!*/ mark=(unsigned char *)calloc(_nlines,sizeof(*mark)); neighbors=_neighbors; nclusters=0; @@ -657,27 +658,22 @@ static void qr_line_fit(qr_line _l,int _x0,int _y0, int u; int v; int w; - /*This part can easily overflow with moderate sizes, so we compute a shift - factor to scale it down into a managable range. - What we really want is a way of computing sqrt(a*a+b*b) without actually - squaring a and b (e.g., an integer equivalent of hypot()). - We'd still need to scale down the result: we ensure that the product of any - two of _l[0] and _l[1] fits within _res bits, which allows computation of - line intersections without overflow.*/ u=abs(_sxx-_syy); v=-_sxy<<1; + w=qr_ihypot(u,v); + /*Computations in later stages can easily overflow with moderate sizes, so we + compute a shift factor to scale things down into a managable range. + We ensure that the product of any two of _l[0] and _l[1] fits within _res + bits, which allows computation of line intersections without overflow.*/ dshift=QR_MAXI(0,QR_MAXI(qr_ilog(u),qr_ilog(abs(v)))+1-(_res+1>>1)); dround=(1<>1; - u=u+dround>>dshift; - v=v+dround>>dshift; - w=qr_isqrt(u*u+v*v); if(_sxx>_syy){ - _l[0]=v; - _l[1]=u+w; + _l[0]=v+dround>>dshift; + _l[1]=u+w+dround>>dshift; } else{ - _l[0]=u+w; - _l[1]=v; + _l[0]=u+w+dround>>dshift; + _l[1]=v+dround>>dshift; } _l[2]=-(_x0*_l[0]+_y0*_l[1]); } @@ -712,8 +708,8 @@ static void qr_line_fit_points(qr_line _l,qr_point *_p,int _np,int _res){ ymin=QR_MINI(ymin,_p[i][1]); ymax=QR_MAXI(ymax,_p[i][1]); } - xbar=((sx<<1)+_np)/(_np<<1); - ybar=((sy<<1)+_np)/(_np<<1); + xbar=(sx+(_np>>1))/_np; + ybar=(sy+(_np>>1))/_np; sshift=QR_MAXI(0,qr_ilog(_np*QR_MAXI(QR_MAXI(xmax-xbar,xbar-xmin), QR_MAXI(ymax-ybar,ybar-ymin)))-(QR_INT_BITS-1>>1)); sround=(1<>1; @@ -1059,8 +1055,8 @@ static void qr_finder_edge_pts_hom_classify(qr_finder *_f,const qr_hom *_hom){ } /*TODO: Perhaps these thresholds should be on the module size instead? - Unfortunately, I'd need real-world images of code with larger versions to see - if these thresholds are still effective, but such versions aren't used + Unfortunately, I'd need real-world images of codes with larger versions to + see if these thresholds are still effective, but such versions aren't used often.*/ /*The amount that the estimated version numbers are allowed to differ from the @@ -1705,12 +1701,12 @@ static void qr_hom_cell_init(qr_hom_cell *_cell,int _u0,int _v0, The quotient is often exact (e.g., when the source points contain no projective distortion), and is never zero. Hence we can use zero to signal "infinity" when the divisor is zero.*/ - if(i00)i00=QR_COPYSIGNI(QR_DIVROUND(i22,abs(i00)),i00); - if(i01)i01=QR_COPYSIGNI(QR_DIVROUND(i22,abs(i01)),i01); - if(i10)i10=QR_COPYSIGNI(QR_DIVROUND(i22,abs(i10)),i10); - if(i11)i11=QR_COPYSIGNI(QR_DIVROUND(i22,abs(i11)),i11); - if(i20)i20=QR_COPYSIGNI(QR_DIVROUND(i22,abs(i20)),i20); - if(i21)i21=QR_COPYSIGNI(QR_DIVROUND(i22,abs(i21)),i21); + if(i00)i00=QR_FLIPSIGNI(QR_DIVROUND(i22,abs(i00)),i00); + if(i01)i01=QR_FLIPSIGNI(QR_DIVROUND(i22,abs(i01)),i01); + if(i10)i10=QR_FLIPSIGNI(QR_DIVROUND(i22,abs(i10)),i10); + if(i11)i11=QR_FLIPSIGNI(QR_DIVROUND(i22,abs(i11)),i11); + if(i20)i20=QR_FLIPSIGNI(QR_DIVROUND(i22,abs(i20)),i20); + if(i21)i21=QR_FLIPSIGNI(QR_DIVROUND(i22,abs(i21)),i21); /*Now compute the map from the unit square into the image.*/ dx10=_x1-_x0; dx20=_x2-_x0; diff --git a/qrcode/src/util.c b/qrcode/src/util.c index b2311fc..a01bfc1 100644 --- a/qrcode/src/util.c +++ b/qrcode/src/util.c @@ -1,5 +1,7 @@ +#include #include "util.h" +/*Computes floor(sqrt(_val)) exactly.*/ unsigned qr_isqrt(unsigned _val){ unsigned g; unsigned b; @@ -22,13 +24,54 @@ unsigned qr_isqrt(unsigned _val){ return g; } -/*TODO: ihypot - a>b => g=a+r && add e iff (a+r+e)*(a+r+e) <= a*a+b*b - 2*(a-b+r+e)*(r+e) <= (b-r-e)*(b-r-e) - 2*(a/(b-r-e)-1)*(r+e) <= b-r-e - 2*a*(r+e)/(b-r-e) <= b+r+e - 2*(a-b+r+e)/(b-r-e) <= b/(r+e) -*/ +/*Computes sqrt(_x*_x+_y*_y) using CORDIC. + This implementation is valid for all 32-bit inputs and returns a result + accurate to about 27 bits of precision. + It has been tested for all postiive 16-bit inputs, where it returns correctly + rounded results in 99.998% of cases and the maximum error is + 0.500137134862598032 (for _x=48140, _y=63018). + Very nearly all results less than (1<<16) are correctly rounded. + All Pythagorean triples with a hypotenuse of less than ((1<<27)-1) evaluate + correctly, and the total bias over all Pythagorean triples is -0.04579, with + a relative RMS error of 7.2864E-10 and a relative peak error of 7.4387E-9.*/ +unsigned qr_ihypot(int _x,int _y){ + unsigned x; + unsigned y; + int mask; + int shift; + int u; + int v; + int i; + x=_x=abs(_x); + y=_y=abs(_y); + mask=-(x>y)&(_x^_y); + x^=mask; + y^=mask; + _y^=mask; + shift=31-qr_ilog(y); + shift=QR_MAXI(shift,0); + x=(unsigned)((x<>32); + _y=(int)((_y<>32); + u=x; + mask=-(_y<0); + x+=_y+mask^mask; + _y-=u+mask^mask; + u=x+1>>1; + v=_y+1>>1; + mask=-(_y<0); + x+=v+mask^mask; + _y-=u+mask^mask; + for(i=1;i<16;i++){ + int r; + u=x+1>>2; + r=(1<<2*i)>>1; + v=_y+r>>2*i; + mask=-(_y<0); + x+=v+mask^mask; + _y=_y-(u+mask^mask)<<1; + } + return x+((1U<>1)>>shift; +} #if defined(__GNUC__) # include diff --git a/qrcode/src/util.h b/qrcode/src/util.h index da9fc18..aa4a829 100644 --- a/qrcode/src/util.h +++ b/qrcode/src/util.h @@ -5,12 +5,11 @@ #define QR_MINI(_a,_b) ((_a)+((_b)-(_a)&-((_b)<(_a)))) #define QR_SIGNI(_x) (((_x)>0)-((_x)<0)) #define QR_SIGNMASK(_x) (-((_x)<0)) -/*Unlike copysign(), simply inverts the sign of _a if _b is negative. - Call with abs(_a) to emulate the standard copysign() behavior.*/ -#define QR_COPYSIGNI(_a,_b) ((_a)+QR_SIGNMASK(_b)^QR_SIGNMASK(_b)) +/*Unlike copysign(), simply inverts the sign of _a if _b is negative.*/ +#define QR_FLIPSIGNI(_a,_b) ((_a)+QR_SIGNMASK(_b)^QR_SIGNMASK(_b)) +#define QR_COPYSIGNI(_a,_b) QR_FLIPSIGNI(abs(_a),_b) /*Divides a signed integer by a positive value with exact rounding.*/ -#define QR_DIVROUND(_x,_y) \ - (((_x)+QR_COPYSIGNI(_y>>1,_x))/(_y)) +#define QR_DIVROUND(_x,_y) (((_x)+QR_FLIPSIGNI(_y>>1,_x))/(_y)) #define QR_CLAMPI(_a,_b,_c) (QR_MAXI(_a,QR_MINI(_b,_c))) #define QR_CLAMP255(_x) ((unsigned char)((((_x)<0)-1)&((_x)|-((_x)>255)))) /*Swaps two integers _a and _b if _a>_b.*/ @@ -38,6 +37,7 @@ #define QR_EXTMUL(_a,_b,_r) ((_a)*(long long)(_b)+(_r)) unsigned qr_isqrt(unsigned _val); +unsigned qr_ihypot(int _x,int _y); int qr_ilog(unsigned _val); #endif From ddc96c7827e2a7af4b4ed25b950227daaae31035 Mon Sep 17 00:00:00 2001 From: tterribe Date: Tue, 7 Jul 2009 01:13:03 +0000 Subject: [PATCH 106/328] Add license information and copyright headers. --- qrcode/COPYING | 24 ++ qrcode/LICENSE | 504 ++++++++++++++++++++++++++++++++++++++++++ qrcode/src/bch15_5.c | 5 + qrcode/src/bch15_5.h | 5 + qrcode/src/binarize.c | 5 + qrcode/src/binarize.h | 5 + qrcode/src/image.c | 5 + qrcode/src/image.h | 5 + qrcode/src/isaac.c | 2 + qrcode/src/isaac.h | 2 + qrcode/src/qrcode.h | 5 + qrcode/src/qrdec.c | 5 + qrcode/src/qrdectxt.c | 5 + qrcode/src/reader.c | 5 + qrcode/src/rs.c | 8 +- qrcode/src/rs.h | 6 + qrcode/src/util.c | 5 + qrcode/src/util.h | 5 + 18 files changed, 605 insertions(+), 1 deletion(-) create mode 100644 qrcode/COPYING create mode 100644 qrcode/LICENSE diff --git a/qrcode/COPYING b/qrcode/COPYING new file mode 100644 index 0000000..336bea5 --- /dev/null +++ b/qrcode/COPYING @@ -0,0 +1,24 @@ +Copyright (C) 1999-2009 Timothy B. Terriberry (tterribe@xiph.org) + +You can redistribute this library and/or modify it under the terms of the GNU + Lesser General Public License as published by the Free Software Foundation; + either version 2.1 of the License, or (at your option) any later version. + +This library 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 General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +ISAAC is based on the public domain implementation by Robert J. Jenkins Jr., + and is itself public domain. + +Portions of the bit stream reader are copyright (C) The Xiph.Org Foundation + 1994-2008, and are licensed under a BSD-style license. + +The Reed-Solomon decoder is derived from an implementation (C) 1991-1995 Henry + Minsky (hqm@ua.com, hqm@ai.mit.edu), and is licensed under the LGPL with + permission. diff --git a/qrcode/LICENSE b/qrcode/LICENSE new file mode 100644 index 0000000..602bfc9 --- /dev/null +++ b/qrcode/LICENSE @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/qrcode/src/bch15_5.c b/qrcode/src/bch15_5.c index 3939857..e7f3ec1 100644 --- a/qrcode/src/bch15_5.c +++ b/qrcode/src/bch15_5.c @@ -1,3 +1,8 @@ +/*Copyright (C) 2008-2009 Timothy B. Terriberry (tterribe@xiph.org) + You can redistribute this library and/or modify it under the terms of the + GNU Lesser General Public License as published by the Free Software + Foundation; either version 2.1 of the License, or (at your option) any later + version.*/ #include "bch15_5.h" /*A cycle in GF(2**4) generated by alpha=(x**4+x+1). diff --git a/qrcode/src/bch15_5.h b/qrcode/src/bch15_5.h index 0940564..d13fe93 100644 --- a/qrcode/src/bch15_5.h +++ b/qrcode/src/bch15_5.h @@ -1,3 +1,8 @@ +/*Copyright (C) 2008-2009 Timothy B. Terriberry (tterribe@xiph.org) + You can redistribute this library and/or modify it under the terms of the + GNU Lesser General Public License as published by the Free Software + Foundation; either version 2.1 of the License, or (at your option) any later + version.*/ #if !defined(_bch15_5_H) # define _bch15_5_H (1) diff --git a/qrcode/src/binarize.c b/qrcode/src/binarize.c index 21085ac..0601230 100644 --- a/qrcode/src/binarize.c +++ b/qrcode/src/binarize.c @@ -1,3 +1,8 @@ +/*Copyright (C) 2008-2009 Timothy B. Terriberry (tterribe@xiph.org) + You can redistribute this library and/or modify it under the terms of the + GNU Lesser General Public License as published by the Free Software + Foundation; either version 2.1 of the License, or (at your option) any later + version.*/ #include #include #include diff --git a/qrcode/src/binarize.h b/qrcode/src/binarize.h index 520b70d..a30febe 100644 --- a/qrcode/src/binarize.h +++ b/qrcode/src/binarize.h @@ -1,3 +1,8 @@ +/*Copyright (C) 2008-2009 Timothy B. Terriberry (tterribe@xiph.org) + You can redistribute this library and/or modify it under the terms of the + GNU Lesser General Public License as published by the Free Software + Foundation; either version 2.1 of the License, or (at your option) any later + version.*/ #if !defined(_qrcode_binarize_H) # define _qrcode_binarize_H (1) diff --git a/qrcode/src/image.c b/qrcode/src/image.c index d63e213..944010d 100644 --- a/qrcode/src/image.c +++ b/qrcode/src/image.c @@ -1,3 +1,8 @@ +/*Copyright (C) 2008-2009 Timothy B. Terriberry (tterribe@xiph.org) + You can redistribute this library and/or modify it under the terms of the + GNU Lesser General Public License as published by the Free Software + Foundation; either version 2.1 of the License, or (at your option) any later + version.*/ #include #include #include diff --git a/qrcode/src/image.h b/qrcode/src/image.h index 67126dc..afb1408 100644 --- a/qrcode/src/image.h +++ b/qrcode/src/image.h @@ -1,3 +1,8 @@ +/*Copyright (C) 2008-2009 Timothy B. Terriberry (tterribe@xiph.org) + You can redistribute this library and/or modify it under the terms of the + GNU Lesser General Public License as published by the Free Software + Foundation; either version 2.1 of the License, or (at your option) any later + version.*/ #if !defined(_qrcode_image_H) # define _qrcode_image_H (1) #include diff --git a/qrcode/src/isaac.c b/qrcode/src/isaac.c index 7d391ef..e9ebfd8 100644 --- a/qrcode/src/isaac.c +++ b/qrcode/src/isaac.c @@ -1,3 +1,5 @@ +/*Written by Timothy B. Terriberry (tterribe@xiph.org) 1999-2009 public domain. + Based on the public domain implementation by Robert J. Jenkins Jr.*/ #include #include #include diff --git a/qrcode/src/isaac.h b/qrcode/src/isaac.h index 982ee86..93b276d 100644 --- a/qrcode/src/isaac.h +++ b/qrcode/src/isaac.h @@ -1,3 +1,5 @@ +/*Written by Timothy B. Terriberry (tterribe@xiph.org) 1999-2009 public domain. + Based on the public domain implementation by Robert J. Jenkins Jr.*/ #if !defined(_isaac_H) # define _isaac_H (1) diff --git a/qrcode/src/qrcode.h b/qrcode/src/qrcode.h index df5d886..4567b7e 100644 --- a/qrcode/src/qrcode.h +++ b/qrcode/src/qrcode.h @@ -1,3 +1,8 @@ +/*Copyright (C) 2008-2009 Timothy B. Terriberry (tterribe@xiph.org) + You can redistribute this library and/or modify it under the terms of the + GNU Lesser General Public License as published by the Free Software + Foundation; either version 2.1 of the License, or (at your option) any later + version.*/ #if !defined(_qrcode_H) # define _qrcode_H (1) diff --git a/qrcode/src/qrdec.c b/qrcode/src/qrdec.c index 86eeb2d..9e3bac3 100644 --- a/qrcode/src/qrdec.c +++ b/qrcode/src/qrdec.c @@ -1,3 +1,8 @@ +/*Copyright (C) 2008-2009 Timothy B. Terriberry (tterribe@xiph.org) + You can redistribute this library and/or modify it under the terms of the + GNU Lesser General Public License as published by the Free Software + Foundation; either version 2.1 of the License, or (at your option) any later + version.*/ #include #include #include diff --git a/qrcode/src/qrdectxt.c b/qrcode/src/qrdectxt.c index 4ee7265..866dc5b 100644 --- a/qrcode/src/qrdectxt.c +++ b/qrcode/src/qrdectxt.c @@ -1,3 +1,8 @@ +/*Copyright (C) 2008-2009 Timothy B. Terriberry (tterribe@xiph.org) + You can redistribute this library and/or modify it under the terms of the + GNU Lesser General Public License as published by the Free Software + Foundation; either version 2.1 of the License, or (at your option) any later + version.*/ #include #include #include diff --git a/qrcode/src/reader.c b/qrcode/src/reader.c index 257647e..17e88fc 100644 --- a/qrcode/src/reader.c +++ b/qrcode/src/reader.c @@ -1,3 +1,8 @@ +/*Copyright (C) 2008-2009 Timothy B. Terriberry (tterribe@xiph.org) + You can redistribute this library and/or modify it under the terms of the + GNU Lesser General Public License as published by the Free Software + Foundation; either version 2.1 of the License, or (at your option) any later + version.*/ #include #include #include "image.h" diff --git a/qrcode/src/rs.c b/qrcode/src/rs.c index 66cd96f..d14fe53 100644 --- a/qrcode/src/rs.c +++ b/qrcode/src/rs.c @@ -1,3 +1,9 @@ +/*Copyright (C) 1991-1995 Henry Minsky (hqm@ua.com, hqm@ai.mit.edu) + Copyright (C) 2008-2009 Timothy B. Terriberry (tterribe@xiph.org) + You can redistribute this library and/or modify it under the terms of the + GNU Lesser General Public License as published by the Free Software + Foundation; either version 2.1 of the License, or (at your option) any later + version.*/ #include #include #include "rs.h" @@ -5,7 +11,7 @@ /*Reed-Solomon encoder and decoder. Original implementation (C) Henry Minsky (hqm@ua.com, hqm@ai.mit.edu), Universal Access 1991-1995. - Updates by Timothy B. Terriberry (C) 2008: + Updates by Timothy B. Terriberry (C) 2008-2009: - Properly reject codes when error-locator polynomial has repeated roots or non-trivial irreducible factors. - Removed the hard-coded parity size and performed general API cleanup. diff --git a/qrcode/src/rs.h b/qrcode/src/rs.h index 071b9ad..c39b069 100644 --- a/qrcode/src/rs.h +++ b/qrcode/src/rs.h @@ -1,3 +1,9 @@ +/*Copyright (C) 1991-1995 Henry Minsky (hqm@ua.com, hqm@ai.mit.edu) + Copyright (C) 2008-2009 Timothy B. Terriberry (tterribe@xiph.org) + You can redistribute this library and/or modify it under the terms of the + GNU Lesser General Public License as published by the Free Software + Foundation; either version 2.1 of the License, or (at your option) any later + version.*/ #if !defined(_qrcode_rs_H) # define _qrcode_rs_H (1) diff --git a/qrcode/src/util.c b/qrcode/src/util.c index a01bfc1..b5b8f92 100644 --- a/qrcode/src/util.c +++ b/qrcode/src/util.c @@ -1,3 +1,8 @@ +/*Copyright (C) 2008-2009 Timothy B. Terriberry (tterribe@xiph.org) + You can redistribute this library and/or modify it under the terms of the + GNU Lesser General Public License as published by the Free Software + Foundation; either version 2.1 of the License, or (at your option) any later + version.*/ #include #include "util.h" diff --git a/qrcode/src/util.h b/qrcode/src/util.h index aa4a829..cb89d96 100644 --- a/qrcode/src/util.h +++ b/qrcode/src/util.h @@ -1,3 +1,8 @@ +/*Copyright (C) 2008-2009 Timothy B. Terriberry (tterribe@xiph.org) + You can redistribute this library and/or modify it under the terms of the + GNU Lesser General Public License as published by the Free Software + Foundation; either version 2.1 of the License, or (at your option) any later + version.*/ #if !defined(_qrcode_util_H) # define _qrcode_util_H (1) From e381d36a277eab9a0331c00aaade14ad38315890 Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 8 Jul 2009 20:25:33 -0400 Subject: [PATCH 107/328] rearrange directories in preparation for zbar merge --- qrcode/COPYING => COPYING | 0 qrcode/LICENSE => LICENSE | 0 qrcode/unix/Makefile | 138 ------------------ {qrcode/src => zbar/decoder}/qrcode.h | 0 {qrcode/src => zbar/decoder/qrcode}/bch15_5.c | 0 {qrcode/src => zbar/decoder/qrcode}/bch15_5.h | 0 .../src => zbar/decoder/qrcode}/binarize.c | 0 .../src => zbar/decoder/qrcode}/binarize.h | 0 {qrcode/src => zbar/decoder/qrcode}/image.c | 0 {qrcode/src => zbar/decoder/qrcode}/image.h | 0 {qrcode/src => zbar/decoder/qrcode}/isaac.c | 0 {qrcode/src => zbar/decoder/qrcode}/isaac.h | 0 {qrcode/src => zbar/decoder/qrcode}/qrdec.c | 0 .../src => zbar/decoder/qrcode}/qrdectxt.c | 0 {qrcode/src => zbar/decoder/qrcode}/reader.c | 0 {qrcode/src => zbar/decoder/qrcode}/rs.c | 0 {qrcode/src => zbar/decoder/qrcode}/rs.h | 0 {qrcode/src => zbar/decoder/qrcode}/util.c | 0 {qrcode/src => zbar/decoder/qrcode}/util.h | 0 19 files changed, 138 deletions(-) rename qrcode/COPYING => COPYING (100%) rename qrcode/LICENSE => LICENSE (100%) delete mode 100644 qrcode/unix/Makefile rename {qrcode/src => zbar/decoder}/qrcode.h (100%) rename {qrcode/src => zbar/decoder/qrcode}/bch15_5.c (100%) rename {qrcode/src => zbar/decoder/qrcode}/bch15_5.h (100%) rename {qrcode/src => zbar/decoder/qrcode}/binarize.c (100%) rename {qrcode/src => zbar/decoder/qrcode}/binarize.h (100%) rename {qrcode/src => zbar/decoder/qrcode}/image.c (100%) rename {qrcode/src => zbar/decoder/qrcode}/image.h (100%) rename {qrcode/src => zbar/decoder/qrcode}/isaac.c (100%) rename {qrcode/src => zbar/decoder/qrcode}/isaac.h (100%) rename {qrcode/src => zbar/decoder/qrcode}/qrdec.c (100%) rename {qrcode/src => zbar/decoder/qrcode}/qrdectxt.c (100%) rename {qrcode/src => zbar/decoder/qrcode}/reader.c (100%) rename {qrcode/src => zbar/decoder/qrcode}/rs.c (100%) rename {qrcode/src => zbar/decoder/qrcode}/rs.h (100%) rename {qrcode/src => zbar/decoder/qrcode}/util.c (100%) rename {qrcode/src => zbar/decoder/qrcode}/util.h (100%) diff --git a/qrcode/COPYING b/COPYING similarity index 100% rename from qrcode/COPYING rename to COPYING diff --git a/qrcode/LICENSE b/LICENSE similarity index 100% rename from qrcode/LICENSE rename to LICENSE diff --git a/qrcode/unix/Makefile b/qrcode/unix/Makefile deleted file mode 100644 index 4f19ce1..0000000 --- a/qrcode/unix/Makefile +++ /dev/null @@ -1,138 +0,0 @@ -# NOTE: This Makefile requires GNU make -# Location to put the targets. -TARGETBINDIR = . -TARGETLIBDIR = . -# Name of the targets -LIBQRCODE_TARGET = libqrcode.a -QRREADER_TARGET = qrreader -# The compiler to use -CC = gcc -# The command to use to generate dependency information -MAKEDEPEND = gcc -MM -#MAKEDEPEND = makedepend -f- -Y -- -# The location of include files. -CINCLUDE = `pkg-config --cflags libpng` -# These are gcc-only, but not actually critical. -CFLAGS = -Wall -Wno-parentheses -Wpointer-arith -Wsign-compare -CFLAGS += -std=c89 -pedantic -Wno-long-long -CFLAGS += -pipe -fvisibility=hidden - -# Extra compilation flags. -# You may get speed increases by including flags such as -O2 or -O3 or -# -ffast-math, or additional flags, depending on your system and compiler. -CFLAGS += -mfpu=vfp -mfloat-abi=softfp -mcpu=arm1136j-s -mtune=arm1136j-s -# -fforce-addr doesn't seem to have much effect on execution time, but it does -# make the binary smaller. -CFLAGS += -Os -fforce-addr -#CFLAGS += -ftree-vectorize -ftree-vectorizer-verbose=0 -# The -g flag will generally include debugging information. -#CFLAGS += -g -#CFLAGS += -DQR_DEBUG -LIBS = `pkg-config --libs libpng` - -# ANYTHING BELOW THIS LINE PROBABLY DOES NOT NEED EDITING -CINCLUDE := -I../include ${CINCLUDE} -LIBSRCDIR = ../src -BINSRCDIR = ../src -WORKDIR = objs - -# C source file lists -LIBQRCODE_CSOURCES = \ -bch15_5.c \ -binarize.c \ -image.c \ -isaac.c \ -qrdec.c \ -qrdectxt.c \ -rs.c \ -util.c \ - -LIBQRCODE_CHEADERS = \ -bch15_5.h \ -binarize.h \ -image.h \ -isaac.h \ -qrcode.h \ -rs.h \ -util.h \ - -QRREADER_CSOURCES = reader.c - -# Create object file list. -LIBQRCODE_OBJ:= ${WORKDIR}/qrdec.o -LIBQRCODE_ASM:= ${LIBQRCODE_OBJ:%.o=%.s} -LIBQRCODE_DEP:= ${LIBQRCODE_OBJ:%.o=%.d} -QRREADER_OBJS:= ${QRREADER_CSOURCES:%.c=${WORKDIR}/%.o} -ALL_OBJS:= ${LIBQRCODE_OBJ} ${QRREADER_OBJS} -# Create the dependency file list -ALL_DEPS:= ${ALL_OBJS:%.o=%.d} -# Prepend source path to file names. -LIBQRCODE_CSOURCES:= ${LIBQRCODE_CSOURCES:%=${LIBSRCDIR}/%} -LIBQRCODE_CHEADERS:= ${LIBQRCODE_CHEADERS:%=${LIBSRCDIR}/%} -QRREADER_CSOURCES:= ${QRREADER_CSOURCES:%=${BINSRCDIR}/%} -ALL_CSOURCES:= ${LIBQRCODE_CSOURCES} ${QRREADER_CSOURCES} -# Prepand target path to file names. -LIBQRCODE_TARGET:= ${TARGETLIBDIR}/${LIBQRCODE_TARGET} -QRREADER_TARGET:= ${TARGETBINDIR}/${QRREADER_TARGET} -ALL_TARGETS:= ${LIBQRCODE_TARGET} ${QRREADER_TARGET} - -# Targets: -# Everything (default) -all: ${ALL_TARGETS} - -# libqrcode -${LIBQRCODE_DEP}: ${LIBQRCODE_CSOURCES} -${LIBQRCODE_ASM}: ${LIBQRCODE_CSOURCES} -${LIBQRCODE_OBJ}: ${LIBQRCODE_CSOURCES} -${LIBQRCODE_TARGET}: ${LIBQRCODE_OBJ} - mkdir -p ${TARGETLIBDIR} - ar cqs $@ $< - -# qrreader -${QRREADER_TARGET}: ${QRREADER_OBJS} ${LIBQRCODE_TARGET} - mkdir -p ${TARGETBINDIR} - ${CC} ${CFLAGS} -o $@ ${QRREADER_OBJS} ${LIBS} ${LIBQRCODE_TARGET} - -# Assembly listing -ALL_ASM := ${ALL_OBJS:%.o=%.s} -asm: ${ALL_ASM} - -# Remove all targets. -clean: - -rm ${ALL_ASM} ${ALL_OBJS} ${ALL_DEPS} ${ALL_TARGETS} - -rmdir ${WORKDIR} - -# Make everything depend on changes in the Makefile -${ALL_ASM} ${ALL_OBJS} ${ALL_DEPS} ${ALL_TARGETS} : Makefile - -# Specify which targets are phony for GNU make -.PHONY : all clean - -# Rules -# These are set up to compile each library as a single unit, to allow gcc to do -# Inter Module Analysis (IMA) when optimizing. -${WORKDIR}/%.d: ${LIBSRCDIR}/%.c - mkdir -p ${dir $@} - ${MAKEDEPEND} ${CINCLUDE} ${CFLAGS} $(filter %.c,$^) \ - -MT ${@:%.d=%.o} > $@ - ${MAKEDEPEND} ${CINCLUDE} ${CFLAGS} $(filter %.c,$^) \ - -MT ${@:%.d=%.s} >> $@ - ${MAKEDEPEND} ${CINCLUDE} ${CFLAGS} $(filter %.c,$^) \ - -MT $@ >> $@ -${WORKDIR}/%.s: ${LIBSRCDIR}/%.c - ${CC} ${CINCLUDE} ${CFLAGS} -S -o $@ -combine $(filter %.c,$^) -${WORKDIR}/%.o: ${LIBSRCDIR}/%.c - ${CC} ${CINCLUDE} ${CFLAGS} -c -o $@ -combine $(filter %.c,$^) - -#${WORKDIR}/%.d : ${BINSRCDIR}/%.c -# mkdir -p ${dir $@} -# ${MAKEDEPEND} ${CINCLUDE} ${CFLAGS} $< -MT ${@:%.d=%.o} > $@ -#${WORKDIR}/%.s : ${BINSRCDIR}/%.c ${WORKDIR}/%.o -# mkdir -p ${dir $@} -# ${CC} ${CINCLUDE} ${CFLAGS} -S -o $@ $< -#${WORKDIR}/%.o : ${BINSRCDIR}/%.c -# mkdir -p ${dir $@} -# ${CC} ${CINCLUDE} ${CFLAGS} -c -o $@ $< - -# Include header file dependencies -include ${ALL_DEPS} diff --git a/qrcode/src/qrcode.h b/zbar/decoder/qrcode.h similarity index 100% rename from qrcode/src/qrcode.h rename to zbar/decoder/qrcode.h diff --git a/qrcode/src/bch15_5.c b/zbar/decoder/qrcode/bch15_5.c similarity index 100% rename from qrcode/src/bch15_5.c rename to zbar/decoder/qrcode/bch15_5.c diff --git a/qrcode/src/bch15_5.h b/zbar/decoder/qrcode/bch15_5.h similarity index 100% rename from qrcode/src/bch15_5.h rename to zbar/decoder/qrcode/bch15_5.h diff --git a/qrcode/src/binarize.c b/zbar/decoder/qrcode/binarize.c similarity index 100% rename from qrcode/src/binarize.c rename to zbar/decoder/qrcode/binarize.c diff --git a/qrcode/src/binarize.h b/zbar/decoder/qrcode/binarize.h similarity index 100% rename from qrcode/src/binarize.h rename to zbar/decoder/qrcode/binarize.h diff --git a/qrcode/src/image.c b/zbar/decoder/qrcode/image.c similarity index 100% rename from qrcode/src/image.c rename to zbar/decoder/qrcode/image.c diff --git a/qrcode/src/image.h b/zbar/decoder/qrcode/image.h similarity index 100% rename from qrcode/src/image.h rename to zbar/decoder/qrcode/image.h diff --git a/qrcode/src/isaac.c b/zbar/decoder/qrcode/isaac.c similarity index 100% rename from qrcode/src/isaac.c rename to zbar/decoder/qrcode/isaac.c diff --git a/qrcode/src/isaac.h b/zbar/decoder/qrcode/isaac.h similarity index 100% rename from qrcode/src/isaac.h rename to zbar/decoder/qrcode/isaac.h diff --git a/qrcode/src/qrdec.c b/zbar/decoder/qrcode/qrdec.c similarity index 100% rename from qrcode/src/qrdec.c rename to zbar/decoder/qrcode/qrdec.c diff --git a/qrcode/src/qrdectxt.c b/zbar/decoder/qrcode/qrdectxt.c similarity index 100% rename from qrcode/src/qrdectxt.c rename to zbar/decoder/qrcode/qrdectxt.c diff --git a/qrcode/src/reader.c b/zbar/decoder/qrcode/reader.c similarity index 100% rename from qrcode/src/reader.c rename to zbar/decoder/qrcode/reader.c diff --git a/qrcode/src/rs.c b/zbar/decoder/qrcode/rs.c similarity index 100% rename from qrcode/src/rs.c rename to zbar/decoder/qrcode/rs.c diff --git a/qrcode/src/rs.h b/zbar/decoder/qrcode/rs.h similarity index 100% rename from qrcode/src/rs.h rename to zbar/decoder/qrcode/rs.h diff --git a/qrcode/src/util.c b/zbar/decoder/qrcode/util.c similarity index 100% rename from qrcode/src/util.c rename to zbar/decoder/qrcode/util.c diff --git a/qrcode/src/util.h b/zbar/decoder/qrcode/util.h similarity index 100% rename from qrcode/src/util.h rename to zbar/decoder/qrcode/util.h From 9fe8886b25dda87ee96f20d77a6f6f4455022c3e Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 9 Jul 2009 17:06:32 -0400 Subject: [PATCH 108/328] finish initial integration of QR Code reader from maemo-barcode project --- COPYING | 5 +- COPYING.LIB | 504 --------------------------------- ChangeLog | 1 + Makefile.am | 2 +- README | 2 +- README.windows | 2 +- config/config.rpath | 0 configure.ac | 6 +- include/zbar.h | 2 +- zbar.nsi | 5 +- zbar.spec.in | 3 +- zbar/Makefile.am.inc | 14 +- zbar/config.c | 2 +- zbar/decoder.c | 14 +- zbar/decoder.h | 4 +- zbar/decoder/qr_finder.c | 2 +- zbar/decoder/qrcode.h | 52 ++++ zbar/decoder/qrcode/binarize.c | 7 +- zbar/decoder/qrcode/binarize.h | 2 +- zbar/decoder/qrcode/image.c | 143 ---------- zbar/decoder/qrcode/image.h | 13 - zbar/decoder/qrcode/qrdec.c | 130 ++++++++- zbar/decoder/qrcode/qrdectxt.c | 2 +- zbar/decoder/qrcode/reader.c | 74 ----- zbar/img_scanner.c | 18 +- zbar/symbol.c | 2 +- 26 files changed, 218 insertions(+), 793 deletions(-) delete mode 100644 COPYING.LIB create mode 100644 config/config.rpath delete mode 100644 zbar/decoder/qrcode/image.c delete mode 100644 zbar/decoder/qrcode/image.h delete mode 100644 zbar/decoder/qrcode/reader.c diff --git a/COPYING b/COPYING index 336bea5..6a9d036 100644 --- a/COPYING +++ b/COPYING @@ -1,4 +1,7 @@ -Copyright (C) 1999-2009 Timothy B. Terriberry (tterribe@xiph.org) +The ZBar Bar Code Reader is Copyright (C) 2007-2009 Jeff Brown + +The QR Code reader is Copyright (C) 1999-2009 Timothy B. Terriberry + You can redistribute this library and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; diff --git a/COPYING.LIB b/COPYING.LIB deleted file mode 100644 index 5ab7695..0000000 --- a/COPYING.LIB +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/ChangeLog b/ChangeLog index 05e8353..061e467 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * finish initial integration of QR Code reader from maemo-barcode project * zbar-side updates for QR Code integration - add linear scanner position interface - add QR finder position feedback diff --git a/Makefile.am b/Makefile.am index fa17b15..4e88b53 100644 --- a/Makefile.am +++ b/Makefile.am @@ -15,7 +15,7 @@ EXTRA_DIST = pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = zbar.pc -dist_doc_DATA = COPYING.LIB HACKING INSTALL NEWS README TODO +dist_doc_DATA = COPYING HACKING INSTALL LICENSE NEWS README TODO include $(srcdir)/include/Makefile.am.inc include $(srcdir)/zbar/Makefile.am.inc diff --git a/README b/README index b2b5ee3..d0c35bf 100644 --- a/README +++ b/README @@ -12,7 +12,7 @@ C, C++, Python and Perl as well as GUI widgets for Qt, GTK and PyGTK. Check the zbar home page for the latest release, mailing lists, etc. http://zbar.sourceforge.net/ -License information can be found in 'COPYING.LIB'. +License information can be found in 'COPYING'. BUILDING diff --git a/README.windows b/README.windows index 28726b0..b7c55ff 100644 --- a/README.windows +++ b/README.windows @@ -12,7 +12,7 @@ features a fast, streaming interface with a minimal memory footprint. Check the ZBar home page for the latest release, mailing lists, etc. http://zbar.sourceforge.net/ -License information can be found in 'COPYING.LIB'. +License information can be found in 'COPYING'. INSTALLING diff --git a/config/config.rpath b/config/config.rpath new file mode 100644 index 0000000..e69de29 diff --git a/configure.ac b/configure.ac index 3bd25b7..ad92146 100644 --- a/configure.ac +++ b/configure.ac @@ -78,9 +78,9 @@ dnl symbologies AC_ARG_ENABLE([codes], [AS_HELP_STRING([--enable-codes=SYMS], - [select symbologies to compile [default=ean,i25,code39,code128]])], + [select symbologies to compile [default=ean,i25,code39,code128,qrcode]])], [], - [enable_codes="ean,code39,code128,i25"]) dnl pdf417,qr + [enable_codes="ean,code39,code128,i25,qrcode"]) dnl pdf417 AC_DEFUN([ZBAR_CHK_CODE], [ AC_MSG_CHECKING([whether to build $2]) @@ -102,7 +102,7 @@ ZBAR_CHK_CODE([code128], [Code 128 symbology]) ZBAR_CHK_CODE([code39], [Code 39 symbology]) ZBAR_CHK_CODE([pdf417], [PDF417 symbology]) ZBAR_CHK_CODE([i25], [Interleaved 2 of 5 symbology]) -ZBAR_CHK_CODE([qr], [QR Code]) +ZBAR_CHK_CODE([qrcode], [QR Code]) dnl libraries diff --git a/include/zbar.h b/include/zbar.h index d646e3c..a22a315 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -95,7 +95,7 @@ typedef enum zbar_symbol_type_e { ZBAR_I25 = 25, /**< Interleaved 2 of 5. @since 0.4 */ ZBAR_CODE39 = 39, /**< Code 39. @since 0.4 */ ZBAR_PDF417 = 57, /**< PDF417. @since 0.6 */ - ZBAR_QR = 64, /**< QR Code. @since 0.9 */ + ZBAR_QRCODE = 64, /**< QR Code. @since 0.9 */ ZBAR_CODE128 = 128, /**< Code 128 */ ZBAR_SYMBOL = 0x00ff, /**< mask for base symbol type */ ZBAR_ADDON2 = 0x0200, /**< 2-digit add-on flag */ diff --git a/zbar.nsi b/zbar.nsi index ce2fb12..6fe5572 100644 --- a/zbar.nsi +++ b/zbar.nsi @@ -96,7 +96,7 @@ FunctionEnd ZBar Bar Code Reader version ${VERSION}." !insertmacro MUI_PAGE_WELCOME -!insertmacro MUI_PAGE_LICENSE "share\doc\zbar\COPYING.LIB" +!insertmacro MUI_PAGE_LICENSE "share\doc\zbar\LICENSE" !define MUI_COMPONENTSPAGE_SMALLDESC !define MUI_COMPONENTSPAGE_CHECKBITMAP ${NSISDIR}\Contrib\Graphics\Checks\simple-round2.bmp @@ -131,7 +131,8 @@ Section "ZBar Core Files (required)" SecCore File share\doc\zbar\README.windows File share\doc\zbar\NEWS File share\doc\zbar\TODO - File share\doc\zbar\COPYING.LIB + File share\doc\zbar\COPYING + File share\doc\zbar\LICENSE # emit a batch file to add the install directory to the path FileOpen $0 zbarvars.bat w diff --git a/zbar.spec.in b/zbar.spec.in index 071c751..d846d84 100644 --- a/zbar.spec.in +++ b/zbar.spec.in @@ -141,9 +141,10 @@ ldconfig %{_bindir}/zbarcam %{_libdir}/libzbar.so.* %{_datadir}/man/man1/* -%doc %{_docdir}/%{name}-%{version}/COPYING.LIB +%doc %{_docdir}/%{name}-%{version}/COPYING %doc %{_docdir}/%{name}-%{version}/HACKING %doc %{_docdir}/%{name}-%{version}/INSTALL +%doc %{_docdir}/%{name}-%{version}/LICENSE %doc %{_docdir}/%{name}-%{version}/NEWS %doc %{_docdir}/%{name}-%{version}/README %doc %{_docdir}/%{name}-%{version}/TODO diff --git a/zbar/Makefile.am.inc b/zbar/Makefile.am.inc index b27bb16..956b16e 100644 --- a/zbar/Makefile.am.inc +++ b/zbar/Makefile.am.inc @@ -28,15 +28,15 @@ if ENABLE_PDF417 zbar_libzbar_la_SOURCES += zbar/decoder/pdf417.h zbar/decoder/pdf417.c \ zbar/decoder/pdf417_hash.h endif -if ENABLE_QR +if ENABLE_QRCODE zbar_libzbar_la_SOURCES += zbar/decoder/qrcode.h \ zbar/decoder/qr_finder.h zbar/decoder/qr_finder.c \ - zbar/decoder/qr/qrdec.c zbar/decoder/qr/qrdectxt.c \ - zbar/decoder/qr/rs.h zbar/decoder/qr/rs.c \ - zbar/decoder/qr/isaac.h zbar/decoder/qr/isaac.c \ - zbar/decoder/qr/bch15_5.h zbar/decoder/qr/bch15_5.c \ - zbar/decoder/qr/binarize.h zbar/decoder/qr/binarize.c \ - zbar/decoder/qr/util.h zbar/decoder/qr/util.c + zbar/decoder/qrcode/qrdec.c zbar/decoder/qrcode/qrdectxt.c \ + zbar/decoder/qrcode/rs.h zbar/decoder/qrcode/rs.c \ + zbar/decoder/qrcode/isaac.h zbar/decoder/qrcode/isaac.c \ + zbar/decoder/qrcode/bch15_5.h zbar/decoder/qrcode/bch15_5.c \ + zbar/decoder/qrcode/binarize.h zbar/decoder/qrcode/binarize.c \ + zbar/decoder/qrcode/util.h zbar/decoder/qrcode/util.c endif if HAVE_POLL diff --git a/zbar/config.c b/zbar/config.c index a2f450b..f2ab0b5 100644 --- a/zbar/config.c +++ b/zbar/config.c @@ -45,7 +45,7 @@ int zbar_parse_config (const char *cfgstr, else if(len < 2) return(1); else if(!strncmp(cfgstr, "qrcode", len)) - *sym = ZBAR_QR; + *sym = ZBAR_QRCODE; else if(len < 3) return(1); else if(!strncmp(cfgstr, "upca", len)) diff --git a/zbar/decoder.c b/zbar/decoder.c index daf7eac..2322535 100644 --- a/zbar/decoder.c +++ b/zbar/decoder.c @@ -69,7 +69,7 @@ zbar_decoder_t *zbar_decoder_create () #ifdef ENABLE_PDF417 dcode->pdf417.config = 1 << ZBAR_CFG_ENABLE; #endif -#ifdef ENABLE_QR +#ifdef ENABLE_QRCODE dcode->qrf.config = 1 << ZBAR_CFG_ENABLE; #endif @@ -102,7 +102,7 @@ void zbar_decoder_reset (zbar_decoder_t *dcode) #ifdef ENABLE_PDF417 pdf417_reset(&dcode->pdf417); #endif -#ifdef ENABLE_QR +#ifdef ENABLE_QRCODE qr_finder_reset(&dcode->qrf); #endif } @@ -128,7 +128,7 @@ void zbar_decoder_new_scan (zbar_decoder_t *dcode) #ifdef ENABLE_PDF417 pdf417_reset(&dcode->pdf417); #endif -#ifdef ENABLE_QR +#ifdef ENABLE_QRCODE qr_finder_reset(&dcode->qrf); #endif } @@ -203,7 +203,7 @@ zbar_symbol_type_t zbar_decode_width (zbar_decoder_t *dcode, (sym = _zbar_decode_pdf417(dcode)) > ZBAR_PARTIAL) dcode->type = sym; #endif -#ifdef ENABLE_QR +#ifdef ENABLE_QRCODE if(TEST_CFG(dcode->qrf.config, ZBAR_CFG_ENABLE) && (sym = _zbar_find_qr(dcode)) > ZBAR_PARTIAL) dcode->type = sym; @@ -276,8 +276,8 @@ static inline int decoder_set_config_bool (zbar_decoder_t *dcode, break; #endif -#ifdef ENABLE_QR - case ZBAR_QR: +#ifdef ENABLE_QRCODE + case ZBAR_QRCODE: config = &dcode->qrf.config; break; #endif @@ -360,7 +360,7 @@ int zbar_decoder_set_config (zbar_decoder_t *dcode, zbar_decoder_set_config(dcode, ZBAR_CODE39, cfg, val); zbar_decoder_set_config(dcode, ZBAR_CODE128, cfg, val); zbar_decoder_set_config(dcode, ZBAR_PDF417, cfg, val); - zbar_decoder_set_config(dcode, ZBAR_QR, cfg, val); + zbar_decoder_set_config(dcode, ZBAR_QRCODE, cfg, val); return(0); } diff --git a/zbar/decoder.h b/zbar/decoder.h index 4a13b28..348fca9 100644 --- a/zbar/decoder.h +++ b/zbar/decoder.h @@ -45,7 +45,7 @@ #ifdef ENABLE_PDF417 # include "decoder/pdf417.h" #endif -#ifdef ENABLE_QR +#ifdef ENABLE_QRCODE # include "decoder/qr_finder.h" #endif @@ -103,7 +103,7 @@ struct zbar_decoder_s { #ifdef ENABLE_PDF417 pdf417_decoder_t pdf417; /* PDF417 decode state */ #endif -#ifdef ENABLE_QR +#ifdef ENABLE_QRCODE qr_finder_t qrf; /* QR Code finder state */ #endif }; diff --git a/zbar/decoder/qr_finder.c b/zbar/decoder/qr_finder.c index 934ef38..ee9a6ee 100644 --- a/zbar/decoder/qr_finder.c +++ b/zbar/decoder/qr_finder.c @@ -93,7 +93,7 @@ zbar_symbol_type_t _zbar_find_qr (zbar_decoder_t *dcode) qrf->line.boffs, qrf->line.pos[0], qrf->line.len, qrf->line.eoffs); - return(ZBAR_QR); + return(ZBAR_QRCODE); invalid: dprintf(2, " [invalid]\n"); diff --git a/zbar/decoder/qrcode.h b/zbar/decoder/qrcode.h index 4567b7e..5f9f2ad 100644 --- a/zbar/decoder/qrcode.h +++ b/zbar/decoder/qrcode.h @@ -6,6 +6,8 @@ #if !defined(_qrcode_H) # define _qrcode_H (1) +#include + # if defined(__cplusplus) extern "C" { # endif @@ -18,6 +20,48 @@ typedef struct qr_code_data_entry qr_code_data_entry; typedef struct qr_code_data qr_code_data; typedef struct qr_code_data_list qr_code_data_list; +typedef struct qr_finder_line qr_finder_line; + +/*The number of bits of subpel precision to store image coordinates in. + This helps when estimating positions in low-resolution images, which may have + a module pitch only a pixel or two wide, making rounding errors matter a + great deal.*/ +#define QR_FINDER_SUBPREC (2) + +/*A line crossing a finder pattern. + Whether the line is horizontal or vertical is determined by context. + The offsts to various parts of the finder pattern are as follows: + |*****| |*****|*****|*****| |*****| + |*****| |*****|*****|*****| |*****| + ^ ^ ^ ^ + | | | | + | | | pos[v]+len+eoffs + | | pos[v]+len + | pos[v] + pos[v]-boffs + Here v is 0 for horizontal and 1 for vertical lines.*/ +struct qr_finder_line{ + /*The location of the upper/left endpoint of the line. + The left/upper edge of the center section is used, since other lines must + cross in this region.*/ + qr_point pos; + /*The length of the center section. + This extends to the right/bottom of the center section, since other lines + must cross in this region.*/ + int len; + /*The offset to the midpoint of the upper/left section (part of the outside + ring), or 0 if we couldn't identify the edge of the beginning section. + We use the midpoint instead of the edge because it can be located more + reliably.*/ + int boffs; + /*The offset to the midpoint of the end section (part of the outside ring), + or 0 if we couldn't identify the edge of the end section. + We use the midpoint instead of the edge because it can be located more + reliably.*/ + int eoffs; +}; + + typedef enum qr_mode{ /*Numeric digits ('0'...'9').*/ QR_MODE_NUM=1, @@ -175,6 +219,7 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, qr_reader *qr_reader_alloc(void); void qr_reader_free(qr_reader *_reader); +void qr_reader_reset(qr_reader *reader); /*Locate all the QR codes in the given binary image.*/ int qr_reader_locate(qr_reader *_reader,qr_code_data_list *_qrlist, @@ -190,6 +235,13 @@ void qr_text_list_free(char **_text,int _ntext); See http://www.nttdocomo.co.jp/english/service/imode/make/content/barcode/function/application/ for details.*/ +int _zbar_qr_found_line(qr_reader *reader, + int direction, + const qr_finder_line *line); +int _zbar_qr_decode(zbar_image_scanner_t *iscn, + qr_reader *reader, + zbar_image_t *img); + # if defined(__cplusplus) } # endif diff --git a/zbar/decoder/qrcode/binarize.c b/zbar/decoder/qrcode/binarize.c index 0601230..1bdf799 100644 --- a/zbar/decoder/qrcode/binarize.c +++ b/zbar/decoder/qrcode/binarize.c @@ -520,9 +520,9 @@ void qr_binarize(unsigned char *_img,int _width,int _height){ /*A simplified adaptive thresholder. This compares the current pixel value to the mean value of a (large) window surrounding it.*/ -void qr_binarize(unsigned char *_img,int _width,int _height){ +unsigned char *qr_binarize(const unsigned char *_img,int _width,int _height){ + unsigned char *mask = NULL; if(_width>0&&_height>0){ - unsigned char *mask; unsigned *col_sums; int logwindw; int logwindh; @@ -587,8 +587,6 @@ void qr_binarize(unsigned char *_img,int _width,int _height){ } } free(col_sums); - memcpy(_img,mask,_width*_height*sizeof(*_img)); - free(mask); } #if defined(QR_DEBUG) { @@ -598,6 +596,7 @@ void qr_binarize(unsigned char *_img,int _width,int _height){ fclose(fout); } #endif + return(mask); } #endif diff --git a/zbar/decoder/qrcode/binarize.h b/zbar/decoder/qrcode/binarize.h index a30febe..93d9303 100644 --- a/zbar/decoder/qrcode/binarize.h +++ b/zbar/decoder/qrcode/binarize.h @@ -12,6 +12,6 @@ void qr_image_cross_masking_median_filter(unsigned char *_img, void qr_wiener_filter(unsigned char *_img,int _width,int _height); /*Binarizes a grayscale image.*/ -void qr_binarize(unsigned char *_img,int _width,int _height); +unsigned char *qr_binarize(const unsigned char *_img,int _width,int _height); #endif diff --git a/zbar/decoder/qrcode/image.c b/zbar/decoder/qrcode/image.c deleted file mode 100644 index 944010d..0000000 --- a/zbar/decoder/qrcode/image.c +++ /dev/null @@ -1,143 +0,0 @@ -/*Copyright (C) 2008-2009 Timothy B. Terriberry (tterribe@xiph.org) - You can redistribute this library and/or modify it under the terms of the - GNU Lesser General Public License as published by the Free Software - Foundation; either version 2.1 of the License, or (at your option) any later - version.*/ -#include -#include -#include -#include -#include "png.h" - -static void png_read(png_structp _png,png_bytep _data,png_size_t _sz){ - size_t ret; - ret=fread(_data,_sz,1,(FILE *)png_get_io_ptr(_png)); - if(ret!=1)png_error(_png,"Read Error"); -} - -static void png_write(png_structp _png,png_bytep _data,png_size_t _sz){ - size_t ret; - ret=fwrite(_data,_sz,1,(FILE *)png_get_io_ptr(_png)); - if(ret!=1)png_error(_png,"Write Error"); -} - -static void png_flush(png_structp _png){ - fflush((FILE *)png_get_io_ptr(_png)); -} - -int image_read_png(unsigned char **_img,int *_width,int *_height,FILE *_fp){ - unsigned char *img; - unsigned char header[8]; - png_structp png; - png_infop info; - png_infop end; - png_color_16p bkgd; - png_bytep *rows; - png_uint_32 width; - png_uint_32 height; - int bit_depth; - int color_type; - int interlace_type; - int compression_type; - int filter_method; - int y; - if(fread(header,1,8,_fp)<1){ - if(feof(_fp))return -EINVAL; - return -errno; - } - if(png_sig_cmp(header,0,8))return -EINVAL; - png=png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); - if(png==NULL)return -ENOMEM; - info=png_create_info_struct(png); - if(info==NULL){ - png_destroy_read_struct(&png,NULL,NULL); - return -ENOMEM; - } - end=png_create_info_struct(png); - if(end==NULL){ - png_destroy_read_struct(&png,&info,NULL); - return -ENOMEM; - } - img=NULL; - rows=NULL; - if(setjmp(png_jmpbuf(png))){ - png_free(png,rows); - free(img); - png_destroy_read_struct(&png,&info,&end); - return -EINVAL; - } - png_set_read_fn(png,_fp,png_read); - png_set_sig_bytes(png,8); - png_read_info(png,info); - png_get_IHDR(png,info,&width,&height,&bit_depth,&color_type, - &interlace_type,&compression_type,&filter_method); - if(width>INT_MAX||height>INT_MAX||width*(png_size_t)height>INT_MAX){ - png_destroy_read_struct(&png,&info,&end); - return -EINVAL; - } - png_set_expand(png); - if(bit_depth<8)png_set_packing(png); - if(bit_depth==16)png_set_strip_16(png); - if(color_type&PNG_COLOR_MASK_COLOR)png_set_rgb_to_gray(png,1,-1,-1); - /*Note that color_types 2 and 3 can also have alpha, despite not setting the - PNG_COLOR_MASK_ALPHA bit.*/ - if(png_get_bKGD(png,info,&bkgd)){ - png_set_background(png,bkgd,PNG_BACKGROUND_GAMMA_FILE,1,1.0); - } - png_set_strip_alpha(png); - img=(unsigned char *)malloc(height*width*sizeof(*img)); - if(img==NULL){ - png_destroy_read_struct(&png,&info,&end); - return -ENOMEM; - } - rows=(png_bytep *)png_malloc(png,height*png_sizeof(png_bytep)); - if(rows==NULL){ - free(img); - png_destroy_read_struct(&png,&info,&end); - return -ENOMEM; - } - for(y=0;y<(int)height;y++)rows[y]=img+y*width; - png_read_image(png,rows); - png_read_end(png,end); - png_free(png,rows); - png_destroy_read_struct(&png,&info,&end); - *_img=img; - *_width=(int)width; - *_height=(int)height; - return 0; -} - -int image_write_png(const unsigned char *_img,int _width,int _height,FILE *_fp){ - png_structp png; - png_infop info; - png_bytep *rows; - int y; - png=png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); - if(png==NULL)return -ENOMEM; - info=png_create_info_struct(png); - if(info==NULL){ - png_destroy_write_struct(&png,NULL); - return -ENOMEM; - } - rows=(png_bytep *)png_malloc(png,_height*png_sizeof(png_bytep)); - if(rows==NULL){ - png_destroy_write_struct(&png,&info); - return -ENOMEM; - } - for(y=0;y<_height;y++)rows[y]=(void *)(_img+y*_width); - if(setjmp(png_jmpbuf(png))){ - png_free(png,rows); - png_destroy_write_struct(&png,&info); - return -EINVAL; - } - png_set_write_fn(png,_fp,png_write,png_flush); - png_set_compression_level(png,Z_BEST_COMPRESSION); - png_set_IHDR(png,info,_width,_height,8,PNG_COLOR_TYPE_GRAY, - PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT); - png_set_rows(png,info,rows); - png_write_png(png,info,PNG_TRANSFORM_IDENTITY,NULL); - png_write_end(png,info); - png_free(png,rows); - png_destroy_write_struct(&png,&info); - return 0; -} diff --git a/zbar/decoder/qrcode/image.h b/zbar/decoder/qrcode/image.h deleted file mode 100644 index afb1408..0000000 --- a/zbar/decoder/qrcode/image.h +++ /dev/null @@ -1,13 +0,0 @@ -/*Copyright (C) 2008-2009 Timothy B. Terriberry (tterribe@xiph.org) - You can redistribute this library and/or modify it under the terms of the - GNU Lesser General Public License as published by the Free Software - Foundation; either version 2.1 of the License, or (at your option) any later - version.*/ -#if !defined(_qrcode_image_H) -# define _qrcode_image_H (1) -#include - -int image_read_png(unsigned char **_img,int *_width,int *_height,FILE *_fp); -int image_write_png(const unsigned char *_img,int _width,int _height,FILE *_fp); - -#endif diff --git a/zbar/decoder/qrcode/qrdec.c b/zbar/decoder/qrcode/qrdec.c index 9e3bac3..b055e16 100644 --- a/zbar/decoder/qrcode/qrdec.c +++ b/zbar/decoder/qrcode/qrdec.c @@ -7,15 +7,16 @@ #include #include #include -#include "qrcode.h" +#include "decoder/qrcode.h" #include "bch15_5.h" #include "rs.h" #include "isaac.h" #include "util.h" +#include "binarize.h" +#include "image.h" typedef int qr_line[3]; -typedef struct qr_finder_line qr_finder_line; typedef struct qr_finder_cluster qr_finder_cluster; typedef struct qr_finder_edge_pt qr_finder_edge_pt; typedef struct qr_finder_center qr_finder_center; @@ -35,11 +36,13 @@ typedef struct qr_pack_buf qr_pack_buf; #define QR_INT_BITS ((int)sizeof(int)*CHAR_BIT) #define QR_INT_LOGBITS (QR_ILOG(QR_INT_BITS)) +#ifdef SPADIX /* moved to qrcode.h */ /*The number of bits of subpel precision to store image coordinates in. This helps when estimating positions in low-resolution images, which may have a module pitch only a pixel or two wide, making rounding errors matter a great deal.*/ #define QR_FINDER_SUBPREC (2) +#endif /*A 14 bit resolution for a homography ensures that the ideal module size for a version 40 code differs from that of a version 39 code by at least 2.*/ @@ -55,12 +58,20 @@ typedef struct qr_pack_buf qr_pack_buf; #define QR_ALIGN_SUBPREC (2) +/* collection of finder lines */ +typedef struct qr_finder_lines { + int num_lines, max_lines; + qr_finder_line *lines; +} qr_finder_lines; + struct qr_reader{ /*The GF(256) representation used in Reed-Solomon decoding.*/ rs_gf256 gf; /*The random number generator used by RANSAC.*/ isaac_ctx isaac; + /* current finder state, horizontal and vertical lines */ + qr_finder_lines finder_lines[2]; }; @@ -76,17 +87,30 @@ static void qr_reader_init(qr_reader *_reader){ /*Allocates a client reader handle.*/ qr_reader *qr_reader_alloc(void){ qr_reader *reader; - reader=(qr_reader *)malloc(sizeof(*reader)); + reader=(qr_reader *)calloc(1, sizeof(*reader)); qr_reader_init(reader); return reader; } /*Frees a client reader handle.*/ void qr_reader_free(qr_reader *_reader){ + if(_reader->finder_lines[0].lines) + free(_reader->finder_lines[0].lines); + if(_reader->finder_lines[1].lines) + free(_reader->finder_lines[1].lines); free(_reader); } +/* reset finder state between scans */ +void qr_reader_reset (qr_reader *reader) +{ + reader->finder_lines[0].num_lines = 0; + reader->finder_lines[1].num_lines = 0; +} + +#ifdef SPADIX /* moved to qrcode.h */ +typedef struct qr_finder_line qr_finder_line; /*A line crossing a finder pattern. Whether the line is horizontal or vertical is determined by context. @@ -121,6 +145,8 @@ struct qr_finder_line{ int eoffs; }; +#endif + /*A cluster of lines crossing a finder pattern (all in the same direction).*/ struct qr_finder_cluster{ @@ -162,7 +188,7 @@ struct qr_finder_center{ int nedge_pts; }; - +#ifdef SPADIX /*Check to see if a set of lengths for a (dark:light:dark:light:dark) pattern roughly has the ratios 1:1:3:1:1. If it does, the location of the line segments are stored in _line. @@ -224,6 +250,7 @@ static int qr_finder_check_pattern(qr_finder_line *_line,int _len_buf[5], _line->eoffs=x3-x2; return 1; } +#endif static int qr_finder_vline_cmp(const void *_a,const void *_b){ const qr_finder_line *a; @@ -478,8 +505,9 @@ static int qr_finder_find_crossings(qr_finder_center *_centers, _height: The height of the image. Return: The number of putative finder centers located.*/ static int qr_finder_centers_locate(qr_finder_center **_centers, - qr_finder_edge_pt **_edge_pts,const unsigned char *_img, + qr_finder_edge_pt **_edge_pts, qr_reader *reader, int _width,int _height){ +#ifdef SPADIX typedef int vect5i[5]; qr_finder_line *hlines; int nhlines; @@ -489,13 +517,6 @@ static int qr_finder_centers_locate(qr_finder_center **_centers, int cvlines; vect5i *ylen_bufs; int *ybps; - qr_finder_line **hneighbors; - qr_finder_cluster *hclusters; - int nhclusters; - qr_finder_line **vneighbors; - qr_finder_cluster *vclusters; - int nvclusters; - int ncenters; int x; int y; if(_width<1||_height<1)return 0; @@ -553,6 +574,21 @@ static int qr_finder_centers_locate(qr_finder_center **_centers, } free(ybps); free(ylen_bufs); +#else + qr_finder_line *hlines = reader->finder_lines[0].lines; + int nhlines = reader->finder_lines[0].num_lines; + qr_finder_line *vlines = reader->finder_lines[1].lines; + int nvlines = reader->finder_lines[1].num_lines; +#endif + + qr_finder_line **hneighbors; + qr_finder_cluster *hclusters; + int nhclusters; + qr_finder_line **vneighbors; + qr_finder_cluster *vclusters; + int nvclusters; + int ncenters; + /*Cluster the detected lines.*/ hneighbors=(qr_finder_line **)malloc(nhlines*sizeof(*hneighbors)); /*We require more than one line per cluster, so there are at most nhlines/2.*/ @@ -590,8 +626,10 @@ static int qr_finder_centers_locate(qr_finder_center **_centers, free(vneighbors); free(hclusters); free(hneighbors); +#ifdef SPADIX free(vlines); free(hlines); +#endif return ncenters; } @@ -4004,7 +4042,7 @@ int qr_reader_locate(qr_reader *_reader,qr_code_data_list *_qrlist, centers=NULL; edge_pts=NULL; nqrdata=_qrlist->nqrdata; - ncenters=qr_finder_centers_locate(¢ers,&edge_pts,_img,_width,_height); + ncenters=qr_finder_centers_locate(¢ers,&edge_pts,NULL,_width,_height); if(ncenters>=3){ qr_reader_match_centers(_reader,_qrlist,centers,ncenters, _img,_width,_height); @@ -4019,7 +4057,7 @@ int qr_reader_extract_text(qr_reader *_reader,const unsigned char *_img, qr_code_data_list qrlist; int ntext; qr_code_data_list_init(&qrlist); - if(qr_reader_locate(_reader,&qrlist,_img,_width,_height)>0){ + if(qr_reader_locate(_reader,&qrlist,NULL,_width,_height)>0){ ntext=qr_code_data_list_extract_text(&qrlist,_text,_allow_partial_sa); qr_code_data_list_clear(&qrlist); } @@ -4029,3 +4067,67 @@ int qr_reader_extract_text(qr_reader *_reader,const unsigned char *_img, } return ntext; } + +int _zbar_qr_found_line (qr_reader *reader, + int direction, + const qr_finder_line *line) +{ + /* minimally intrusive brute force version */ + qr_finder_lines *lines = &reader->finder_lines[direction]; + + if(lines->num_lines >= lines->max_lines) { + lines->max_lines *= 2; + lines->lines = realloc(lines->lines, + ++lines->max_lines * sizeof(*lines->lines)); + } + + memcpy(lines->lines + lines->num_lines++, line, sizeof(*line)); + return(1); +} + +/* FIXME API cleanup */ +zbar_symbol_t *_zbar_image_scanner_alloc_sym(zbar_image_scanner_t *iscn, + zbar_symbol_type_t type, + const char *data); + +int _zbar_qr_decode (zbar_image_scanner_t *iscn, + qr_reader *reader, + zbar_image_t *img) +{ + int nqrdata = 0; + qr_finder_edge_pt *edge_pts = NULL; + qr_finder_center *centers = NULL; + + int ncenters = qr_finder_centers_locate(¢ers, &edge_pts, reader, 0, 0); + + if(ncenters >= 3) { + void *bin = qr_binarize(img->data, img->width, img->height); + + qr_code_data_list qrlist; + qr_code_data_list_init(&qrlist); + + qr_reader_match_centers(reader, &qrlist, centers, ncenters, + bin, img->width, img->height); + + if(qrlist.nqrdata > 0) { + char **text; + int i, ntext = qr_code_data_list_extract_text(&qrlist, &text, 1); + for(i = 0; i < ntext; i++) { + zbar_symbol_t *sym; + sym = _zbar_image_scanner_alloc_sym(iscn, ZBAR_QRCODE, text[i]); + _zbar_image_attach_symbol(img, sym); + } + qr_text_list_free(text, ntext); + } + + nqrdata = qrlist.nqrdata; + qr_code_data_list_clear(&qrlist); + free(bin); + } + + if(centers) + free(centers); + if(edge_pts) + free(edge_pts); + return(nqrdata); +} diff --git a/zbar/decoder/qrcode/qrdectxt.c b/zbar/decoder/qrcode/qrdectxt.c index 866dc5b..edafc7d 100644 --- a/zbar/decoder/qrcode/qrdectxt.c +++ b/zbar/decoder/qrcode/qrdectxt.c @@ -7,7 +7,7 @@ #include #include #include -#include "qrcode.h" +#include "decoder/qrcode.h" #include "util.h" static int text_is_ascii(const unsigned char *_text,int _len){ diff --git a/zbar/decoder/qrcode/reader.c b/zbar/decoder/qrcode/reader.c deleted file mode 100644 index 17e88fc..0000000 --- a/zbar/decoder/qrcode/reader.c +++ /dev/null @@ -1,74 +0,0 @@ -/*Copyright (C) 2008-2009 Timothy B. Terriberry (tterribe@xiph.org) - You can redistribute this library and/or modify it under the terms of the - GNU Lesser General Public License as published by the Free Software - Foundation; either version 2.1 of the License, or (at your option) any later - version.*/ -#include -#include -#include "image.h" -#include "binarize.h" -#include "qrcode.h" - -static int qr_code_data_cmp(const void *_a,const void *_b){ - const qr_code_data *a; - const qr_code_data *b; - int ai; - int bi; - int i; - a=(const qr_code_data *)_a; - b=(const qr_code_data *)_b; - /*Find the top-left corner of each bounding box.*/ - ai=bi=0; - for(i=1;i<4;i++){ - if(a->bbox[i][1]bbox[ai][1]|| - a->bbox[i][1]==a->bbox[ai][1]&&a->bbox[i][0]bbox[ai][0]){ - ai=i; - } - if(b->bbox[i][1]bbox[bi][1]|| - b->bbox[i][1]==b->bbox[bi][1]&&b->bbox[i][0]bbox[bi][0]){ - bi=i; - } - } - /*Sort the codes in top-down, left-right order.*/ - return ((a->bbox[ai][1]>b->bbox[bi][1])-(a->bbox[ai][1]bbox[bi][1])<<1)+ - (a->bbox[ai][0]>b->bbox[bi][0])-(a->bbox[ai][0]bbox[bi][0]); -} - -int main(int _argc,char **_argv){ - qr_reader *reader; - qr_code_data_list qrlist; - char **text; - int i; - unsigned char *img; - int width; - int height; - if(_argc<2){ - fprintf(stderr,"usage: %s .png\n",_argv[0]); - return EXIT_FAILURE; - } - { - FILE *fin; - fin=fopen(_argv[1],"rb"); - if(fin==NULL){ - fprintf(stderr,"'%s' not found.\n",_argv[1]); - return EXIT_FAILURE; - } - image_read_png(&img,&width,&height,fin); - fclose(fin); - } - qr_binarize(img,width,height); - reader=qr_reader_alloc(); - qr_code_data_list_init(&qrlist); - if(qr_reader_locate(reader,&qrlist,img,width,height)>0){ - int ntext; - /*Sort the codes to make test results reproducable.*/ - qsort(qrlist.qrdata,qrlist.nqrdata,sizeof(*qrlist.qrdata),qr_code_data_cmp); - ntext=qr_code_data_list_extract_text(&qrlist,&text,1); - qr_code_data_list_clear(&qrlist); - for(i=0;i #include "error.h" #include "image.h" -#ifdef ENABLE_QR +#ifdef ENABLE_QRCODE # include "decoder/qrcode.h" #endif @@ -75,7 +75,7 @@ struct zbar_image_scanner_s { zbar_scanner_t *scn; /* associated linear intensity scanner */ zbar_decoder_t *dcode; /* associated symbol decoder */ -#ifdef ENABLE_QR +#ifdef ENABLE_QRCODE qr_reader *qr; /* QR Code 2D reader */ #endif @@ -173,7 +173,7 @@ static inline zbar_symbol_t *cache_lookup (zbar_image_scanner_t *iscn, return(*entry); } -#ifdef ENABLE_QR +#ifdef ENABLE_QRCODE extern qr_finder_line *_zbar_decoder_get_qr_finder_line(zbar_decoder_t*); # define QR_FIXED(v, rnd) ((((v) << 1) + (rnd)) << (QR_FINDER_SUBPREC - 1)) @@ -244,8 +244,8 @@ static void symbol_handler (zbar_image_scanner_t *iscn, if(type <= ZBAR_PARTIAL) return; -#ifdef ENABLE_QR - if(type == ZBAR_QR) { +#ifdef ENABLE_QRCODE + if(type == ZBAR_QRCODE) { qr_handler(iscn, x, y); return; } @@ -327,7 +327,7 @@ zbar_image_scanner_t *zbar_image_scanner_create () return(NULL); } -#ifdef ENABLE_QR +#ifdef ENABLE_QRCODE iscn->qr = qr_reader_alloc(); #endif @@ -350,7 +350,7 @@ void zbar_image_scanner_destroy (zbar_image_scanner_t *iscn) sym_destroy(iscn->syms); iscn->syms = next; } -#ifdef ENABLE_QR +#ifdef ENABLE_QRCODE if(iscn->qr) { qr_reader_free(iscn->qr); iscn->qr = NULL; @@ -427,7 +427,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, { recycle_syms(iscn, img); -#ifdef ENABLE_QR +#ifdef ENABLE_QRCODE qr_reader_reset(iscn->qr); #endif @@ -523,7 +523,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, } } -#ifdef ENABLE_QR +#ifdef ENABLE_QRCODE _zbar_qr_decode(iscn, iscn->qr, img); #endif diff --git a/zbar/symbol.c b/zbar/symbol.c index 666c550..8cc6dca 100644 --- a/zbar/symbol.c +++ b/zbar/symbol.c @@ -42,7 +42,7 @@ const char *zbar_get_symbol_name (zbar_symbol_type_t sym) case ZBAR_CODE39: return("CODE-39"); case ZBAR_CODE128: return("CODE-128"); case ZBAR_PDF417: return("PDF417"); - case ZBAR_QR: return("QR"); + case ZBAR_QRCODE: return("QR-Code"); default: return("UNKNOWN"); } } From 4a77e979e3f25a0b30b9ade86fe474877a7da914 Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 13 Jul 2009 11:59:04 -0400 Subject: [PATCH 109/328] QZ and clustering fixes to QR integration - remove qr_finder QZ checks - decrease center clustering threshold from 1/3 to 1/5 of length - add img_scanner svg debug output - manually add config.rpath to workaround broken autofoo --- ChangeLog | 5 + config/config.rpath | 666 ++++++++++++++++++++++++++++++++++++ zbar/decoder/qr_finder.c | 26 -- zbar/decoder/qrcode/qrdec.c | 22 +- zbar/img_scanner.c | 55 ++- 5 files changed, 744 insertions(+), 30 deletions(-) mode change 100644 => 100755 config/config.rpath diff --git a/ChangeLog b/ChangeLog index 061e467..a4873c3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,9 @@ current: + * QZ and clustering fixes to QR integration + - remove qr_finder QZ checks + - decrease center clustering threshold from 1/3 to 1/5 of length + - add img_scanner svg debug output + - manually add config.rpath to workaround broken autofoo * finish initial integration of QR Code reader from maemo-barcode project * zbar-side updates for QR Code integration - add linear scanner position interface diff --git a/config/config.rpath b/config/config.rpath old mode 100644 new mode 100755 index e69de29..c547c68 --- a/config/config.rpath +++ b/config/config.rpath @@ -0,0 +1,666 @@ +#! /bin/sh +# Output a system dependent set of variables, describing how to set the +# run time search path of shared libraries in an executable. +# +# Copyright 1996-2007 Free Software Foundation, Inc. +# Taken from GNU libtool, 2001 +# Originally by Gordon Matzigkeit , 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# The first argument passed to this file is the canonical host specification, +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld +# should be set by the caller. +# +# The set of defined variables is at the end of this script. + +# Known limitations: +# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer +# than 256 bytes, otherwise the compiler driver will dump core. The only +# known workaround is to choose shorter directory names for the build +# directory and/or the installation directory. + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a +shrext=.so + +host="$1" +host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + +# Code taken from libtool.m4's _LT_CC_BASENAME. + +for cc_temp in $CC""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'` + +# Code taken from libtool.m4's AC_LIBTOOL_PROG_COMPILER_PIC. + +wl= +if test "$GCC" = yes; then + wl='-Wl,' +else + case "$host_os" in + aix*) + wl='-Wl,' + ;; + darwin*) + case $cc_basename in + xlc*) + wl='-Wl,' + ;; + esac + ;; + mingw* | cygwin* | pw32* | os2*) + ;; + hpux9* | hpux10* | hpux11*) + wl='-Wl,' + ;; + irix5* | irix6* | nonstopux*) + wl='-Wl,' + ;; + newsos6) + ;; + linux* | k*bsd*-gnu) + case $cc_basename in + icc* | ecc*) + wl='-Wl,' + ;; + pgcc | pgf77 | pgf90) + wl='-Wl,' + ;; + ccc*) + wl='-Wl,' + ;; + como) + wl='-lopt=' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + wl='-Wl,' + ;; + esac + ;; + esac + ;; + osf3* | osf4* | osf5*) + wl='-Wl,' + ;; + rdos*) + ;; + solaris*) + wl='-Wl,' + ;; + sunos4*) + wl='-Qoption ld ' + ;; + sysv4 | sysv4.2uw2* | sysv4.3*) + wl='-Wl,' + ;; + sysv4*MP*) + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + wl='-Wl,' + ;; + unicos*) + wl='-Wl,' + ;; + uts4*) + ;; + esac +fi + +# Code taken from libtool.m4's AC_LIBTOOL_PROG_LD_SHLIBS. + +hardcode_libdir_flag_spec= +hardcode_libdir_separator= +hardcode_direct=no +hardcode_minus_L=no + +case "$host_os" in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; +esac + +ld_shlibs=yes +if test "$with_gnu_ld" = yes; then + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + # Unlike libtool, we use -rpath here, not --rpath, since the documented + # option of GNU ld is called -rpath, not --rpath. + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + case "$host_os" in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + fi + ;; + amigaos*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we cannot use + # them. + ld_shlibs=no + ;; + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + cygwin* | mingw* | pw32*) + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + interix[3-9]*) + hardcode_direct=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + gnu* | linux* | k*bsd*-gnu) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + netbsd*) + ;; + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + else + ld_shlibs=no + fi + ;; + esac + ;; + sunos4*) + hardcode_direct=yes + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + esac + if test "$ld_shlibs" = no; then + hardcode_libdir_flag_spec= + fi +else + case "$host_os" in + aix3*) + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + else + aix_use_runtimelinking=no + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + fi + hardcode_direct=yes + hardcode_libdir_separator=':' + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + fi + # Begin _LT_AC_SYS_LIBPATH_AIX. + echo 'int main () { return 0; }' > conftest.c + ${CC} ${LDFLAGS} conftest.c -o conftest + aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` + if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` + fi + if test -z "$aix_libpath"; then + aix_libpath="/usr/lib:/lib" + fi + rm -f conftest.c conftest + # End _LT_AC_SYS_LIBPATH_AIX. + if test "$aix_use_runtimelinking" = yes; then + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + else + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + fi + fi + ;; + amigaos*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + # see comment about different semantics on the GNU ld section + ld_shlibs=no + ;; + bsdi[45]*) + ;; + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec=' ' + libext=lib + ;; + darwin* | rhapsody*) + hardcode_direct=no + if test "$GCC" = yes ; then + : + else + case $cc_basename in + xlc*) + ;; + *) + ld_shlibs=no + ;; + esac + fi + ;; + dgux*) + hardcode_libdir_flag_spec='-L$libdir' + ;; + freebsd1*) + ld_shlibs=no + ;; + freebsd2.2*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + freebsd2*) + hardcode_direct=yes + hardcode_minus_L=yes + ;; + freebsd* | dragonfly*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + hpux9*) + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + hpux10*) + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + hpux11*) + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + ;; + *) + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + irix5* | irix6* | nonstopux*) + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + netbsd*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + newsos6) + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + else + case "$host_os" in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + else + ld_shlibs=no + fi + ;; + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + osf3*) + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + osf4* | osf5*) + if test "$GCC" = yes; then + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + # Both cc and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + hardcode_libdir_separator=: + ;; + solaris*) + hardcode_libdir_flag_spec='-R$libdir' + ;; + sunos4*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + ;; + sysv4) + case $host_vendor in + sni) + hardcode_direct=yes # is this really true??? + ;; + siemens) + hardcode_direct=no + ;; + motorola) + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + ;; + sysv4.3*) + ;; + sysv4*MP*) + if test -d /usr/nec; then + ld_shlibs=yes + fi + ;; + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + ;; + sysv5* | sco3.2v5* | sco5v6*) + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator=':' + ;; + uts4*) + hardcode_libdir_flag_spec='-L$libdir' + ;; + *) + ld_shlibs=no + ;; + esac +fi + +# Check dynamic linker characteristics +# Code taken from libtool.m4's AC_LIBTOOL_SYS_DYNAMIC_LINKER. +# Unlike libtool.m4, here we don't care about _all_ names of the library, but +# only about the one the linker finds when passed -lNAME. This is the last +# element of library_names_spec in libtool.m4, or possibly two of them if the +# linker has special search rules. +library_names_spec= # the last element of library_names_spec in libtool.m4 +libname_spec='lib$name' +case "$host_os" in + aix3*) + library_names_spec='$libname.a' + ;; + aix4* | aix5*) + library_names_spec='$libname$shrext' + ;; + amigaos*) + library_names_spec='$libname.a' + ;; + beos*) + library_names_spec='$libname$shrext' + ;; + bsdi[45]*) + library_names_spec='$libname$shrext' + ;; + cygwin* | mingw* | pw32*) + shrext=.dll + library_names_spec='$libname.dll.a $libname.lib' + ;; + darwin* | rhapsody*) + shrext=.dylib + library_names_spec='$libname$shrext' + ;; + dgux*) + library_names_spec='$libname$shrext' + ;; + freebsd1*) + ;; + freebsd* | dragonfly*) + case "$host_os" in + freebsd[123]*) + library_names_spec='$libname$shrext$versuffix' ;; + *) + library_names_spec='$libname$shrext' ;; + esac + ;; + gnu*) + library_names_spec='$libname$shrext' + ;; + hpux9* | hpux10* | hpux11*) + case $host_cpu in + ia64*) + shrext=.so + ;; + hppa*64*) + shrext=.sl + ;; + *) + shrext=.sl + ;; + esac + library_names_spec='$libname$shrext' + ;; + interix[3-9]*) + library_names_spec='$libname$shrext' + ;; + irix5* | irix6* | nonstopux*) + library_names_spec='$libname$shrext' + case "$host_os" in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;; + *) libsuff= shlibsuff= ;; + esac + ;; + esac + ;; + linux*oldld* | linux*aout* | linux*coff*) + ;; + linux* | k*bsd*-gnu) + library_names_spec='$libname$shrext' + ;; + knetbsd*-gnu) + library_names_spec='$libname$shrext' + ;; + netbsd*) + library_names_spec='$libname$shrext' + ;; + newsos6) + library_names_spec='$libname$shrext' + ;; + nto-qnx*) + library_names_spec='$libname$shrext' + ;; + openbsd*) + library_names_spec='$libname$shrext$versuffix' + ;; + os2*) + libname_spec='$name' + shrext=.dll + library_names_spec='$libname.a' + ;; + osf3* | osf4* | osf5*) + library_names_spec='$libname$shrext' + ;; + rdos*) + ;; + solaris*) + library_names_spec='$libname$shrext' + ;; + sunos4*) + library_names_spec='$libname$shrext$versuffix' + ;; + sysv4 | sysv4.3*) + library_names_spec='$libname$shrext' + ;; + sysv4*MP*) + library_names_spec='$libname$shrext' + ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + library_names_spec='$libname$shrext' + ;; + uts4*) + library_names_spec='$libname$shrext' + ;; +esac + +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' +escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` +shlibext=`echo "$shrext" | sed -e 's,^\.,,'` +escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` +escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` +escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` + +LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <=len){ + if(nneighbors*(5<=len){ _clusters[nclusters].lines=neighbors; _clusters[nclusters].nlines=nneighbors; for(j=0;jfinder_lines[0].num_lines, + reader->finder_lines[1].num_lines, + ncenters); + if(_zbar_verbosity >= 18) { + int i, j; + for(i = 0; i < ncenters; i++) { + qr_finder_center *cen = centers + i; + fprintf(stderr, "\t[%d] %d,%d:", i, cen->pos[0], cen->pos[1]); + for(j = 0; j < cen->nedge_pts; j++) { + qr_finder_edge_pt *edge = cen->edge_pts + j; + fprintf(stderr, " %d,%dx%d@%d", + edge->pos[0], edge->pos[1], + edge->extent, edge->edge); + } + fprintf(stderr, "\n"); + } + } + if(ncenters >= 3) { void *bin = qr_binarize(img->data, img->width, img->height); diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index f04118c..b4a327e 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -39,6 +39,11 @@ # include "decoder/qrcode.h" #endif +#ifdef DEBUG_IMG_SCANNER +# define DEBUG_LEVEL (DEBUG_IMG_SCANNER) +#endif +#include "debug.h" + #if 1 # define ASSERT_POS \ assert(p == data + x + y * w) @@ -230,6 +235,28 @@ static void qr_handler (zbar_image_scanner_t *iscn, PRINT_FIXED(line->len, QR_FINDER_SUBPREC), PRINT_FIXED(line->eoffs, QR_FINDER_SUBPREC)); + dprintf(1, "\n" + "\n", + PRINT_FIXED(line->pos[0], QR_FINDER_SUBPREC), + PRINT_FIXED(line->pos[1], QR_FINDER_SUBPREC), + (iscn->dx) ? 'h' : 'v', + PRINT_FIXED(line->len, QR_FINDER_SUBPREC), + + PRINT_FIXED(line->pos[0] - ((iscn->dx) ? line->boffs : 1), + QR_FINDER_SUBPREC), + PRINT_FIXED(line->pos[1] - ((iscn->dx) ? 1 : line->boffs), + QR_FINDER_SUBPREC), + (iscn->dx) ? 'v' : 'h', + PRINT_FIXED(2, QR_FINDER_SUBPREC), + + PRINT_FIXED(line->pos[0] + ((iscn->dx) ? line->len + line->eoffs : -1), + QR_FINDER_SUBPREC), + PRINT_FIXED(line->pos[1] + ((iscn->dx) ? -1 : line->len + line->eoffs), + QR_FINDER_SUBPREC), + (iscn->dx) ? 'v' : 'h', + PRINT_FIXED(2, QR_FINDER_SUBPREC)); + _zbar_qr_found_line(iscn->qr, !iscn->dx, line); } #endif @@ -416,6 +443,25 @@ static inline void quiet_border (zbar_image_scanner_t *iscn, symbol_handler(iscn, x, y); } +#ifdef DEBUG_IMG_SCANNER +const char svg_head[] = + "\n" + "\n" + "\n" + "\n" + "\n"; +#endif + #define movedelta(dx, dy) do { \ x += (dx); \ y += (dy); \ @@ -436,9 +482,11 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, if(!img) return(-1); - unsigned w = zbar_image_get_width(img); - unsigned h = zbar_image_get_height(img); - const uint8_t *data = zbar_image_get_data(img); + unsigned w = img->width; + unsigned h = img->height; + const uint8_t *data = img->data; + + dprintf(1, svg_head, w, h, w, h); int density = CFG(iscn, ZBAR_CFG_Y_DENSITY); if(density > 0) { @@ -526,6 +574,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, #ifdef ENABLE_QRCODE _zbar_qr_decode(iscn, iscn->qr, img); #endif + dprintf(1, "\n"); /* release reference to converted image */ zbar_image_destroy(img); From dba6de37d5eac83ef9fab9cbfe4deb1eeadcd81c Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 30 Jul 2009 18:21:43 -0400 Subject: [PATCH 110/328] add support for binary symbol data --- ChangeLog | 1 + TODO | 1 - include/zbar.h | 18 +++++++++++++++--- perl/ZBar.xs | 15 +++++++++++++-- python/decoder.c | 3 ++- python/symbol.c | 4 +++- python/zbarmodule.c | 1 + zbar/decoder.c | 11 ++++++++--- zbar/decoder.h | 11 ++++++----- zbar/decoder/code128.c | 9 +++++---- zbar/decoder/code39.c | 1 + zbar/decoder/ean.c | 1 + zbar/decoder/i25.c | 1 + zbar/img_scanner.c | 22 +++++++++++++--------- zbar/symbol.c | 12 ++++++------ zbar/symbol.h | 13 +++++++------ 16 files changed, 83 insertions(+), 41 deletions(-) diff --git a/ChangeLog b/ChangeLog index 876f731..b3cfc34 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * add support for binary symbol data * fix zbarimg b&w format handling * fix scan (image) boundary QZ handling (bug #2807538) - add linear scanner manual flush API diff --git a/TODO b/TODO index 9c517b3..ca992e8 100644 --- a/TODO +++ b/TODO @@ -29,7 +29,6 @@ symbologies: * finish addon decoding decoder: - * support for binary symbol data (PDF417, Code 128) * start/stop/abort and location detail APIs (PDF417, OMR) * more configuration options * disable for at least UPC-E (maybe UPC-A?) diff --git a/include/zbar.h b/include/zbar.h index 1f5caed..224bed6 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -207,11 +207,16 @@ typedef struct zbar_symbol_s zbar_symbol_t; */ extern zbar_symbol_type_t zbar_symbol_get_type(const zbar_symbol_t *symbol); -/** retrieve ASCII data decoded from symbol. +/** retrieve data decoded from symbol. * @returns the data string */ extern const char *zbar_symbol_get_data(const zbar_symbol_t *symbol); +/** retrieve length of binary data. + * @returns the length of the decoded data + */ +extern unsigned int zbar_symbol_get_data_length(const zbar_symbol_t *symbol); + /** retrieve current cache count. when the cache is enabled for the * image_scanner this provides inter-frame reliability and redundancy * information for video streams. @@ -372,7 +377,7 @@ extern const void *zbar_image_get_data(const zbar_image_t *image); /** return the size of image data. * @since 0.6 */ -unsigned long zbar_image_get_data_length(const zbar_image_t *img); +extern unsigned long zbar_image_get_data_length(const zbar_image_t *img); /** image_scanner decode result iterator. * @returns the first decoded symbol result for an image @@ -1026,7 +1031,7 @@ extern zbar_symbol_type_t zbar_decode_width(zbar_decoder_t *decoder, * zbar_decode_width(). */ extern zbar_color_t zbar_decoder_get_color(const zbar_decoder_t *decoder); -/** retrieve last decoded data in ASCII format. +/** retrieve last decoded data. * @returns the data string or NULL if no new data available. * the returned data buffer is owned by library, contents are only * valid between non-0 return from zbar_decode_width and next library @@ -1034,6 +1039,13 @@ extern zbar_color_t zbar_decoder_get_color(const zbar_decoder_t *decoder); */ extern const char *zbar_decoder_get_data(const zbar_decoder_t *decoder); +/** retrieve length of binary data. + * @returns the length of the decoded data or 0 if no new data + * available. + */ +extern unsigned int +zbar_decoder_get_data_length(const zbar_decoder_t *decoder); + /** retrieve last decoded symbol type. * @returns the type or ::ZBAR_NONE if no new data available */ diff --git a/perl/ZBar.xs b/perl/ZBar.xs index 65f8f97..2eab08d 100644 --- a/perl/ZBar.xs +++ b/perl/ZBar.xs @@ -233,6 +233,7 @@ BOOT: CONSTANT(error, ERR_, XDISPLAY, "X11 display error"); CONSTANT(error, ERR_, XPROTO, "X11 protocol error"); CONSTANT(error, ERR_, CLOSED, "output window is closed"); + CONSTANT(error, ERR_, WINAPI, "windows system error"); } zbar_error_t @@ -295,9 +296,14 @@ zbar_symbol_type_t zbar_symbol_get_type(symbol) Barcode::ZBar::Symbol symbol -const char * +SV * zbar_symbol_get_data(symbol) Barcode::ZBar::Symbol symbol + CODE: + RETVAL = newSVpvn(zbar_symbol_get_data(symbol), + zbar_symbol_get_data_length(symbol)); + OUTPUT: + RETVAL int zbar_symbol_get_count(symbol) @@ -645,9 +651,14 @@ zbar_color_t zbar_decoder_get_color(decoder) Barcode::ZBar::Decoder decoder -const char * +SV * zbar_decoder_get_data(decoder) Barcode::ZBar::Decoder decoder + CODE: + RETVAL = newSVpvn(zbar_decoder_get_data(decoder), + zbar_decoder_get_data_length(decoder)); + OUTPUT: + RETVAL zbar_symbol_type_t zbar_decoder_get_type(decoder) diff --git a/python/decoder.c b/python/decoder.c index 81b82e6..26cb8a8 100644 --- a/python/decoder.c +++ b/python/decoder.c @@ -107,7 +107,8 @@ static PyObject* decoder_get_data (zbarDecoder *self, void *closure) { - return(PyString_FromString(zbar_decoder_get_data(self->zdcode))); + return(PyString_FromStringAndSize(zbar_decoder_get_data(self->zdcode), + zbar_decoder_get_data_length(self->zdcode))); } static PyGetSetDef decoder_getset[] = { diff --git a/python/symbol.c b/python/symbol.c index 9b4e0ab..5e25785 100644 --- a/python/symbol.c +++ b/python/symbol.c @@ -72,7 +72,9 @@ symbol_get_data (zbarSymbol *self, void *closure) { if(!self->data) { - self->data = PyString_FromString(zbar_symbol_get_data(self->zsym)); + self->data = + PyString_FromStringAndSize(zbar_symbol_get_data(self->zsym), + zbar_symbol_get_data_length(self->zsym)); if(!self->data) return(NULL); } diff --git a/python/zbarmodule.c b/python/zbarmodule.c index 03c822d..c511201 100644 --- a/python/zbarmodule.c +++ b/python/zbarmodule.c @@ -35,6 +35,7 @@ static char *exc_names[] = { "zbar.X11DisplayError", "zbar.X11ProtocolError", "zbar.WindowClosed", + "zbar.WinAPI", }; int diff --git a/zbar/decoder.c b/zbar/decoder.c index e35e88e..39a1ecc 100644 --- a/zbar/decoder.c +++ b/zbar/decoder.c @@ -39,8 +39,8 @@ zbar_decoder_t *zbar_decoder_create () { zbar_decoder_t *dcode = calloc(1, sizeof(zbar_decoder_t)); - dcode->buflen = BUFFER_MIN; - dcode->buf = malloc(dcode->buflen); + dcode->buf_alloc = BUFFER_MIN; + dcode->buf = malloc(dcode->buf_alloc); /* initialize default configs */ #ifdef ENABLE_EAN @@ -82,7 +82,7 @@ void zbar_decoder_destroy (zbar_decoder_t *dcode) void zbar_decoder_reset (zbar_decoder_t *dcode) { - memset(dcode, 0, (long)&dcode->buf - (long)dcode); + memset(dcode, 0, (long)&dcode->buf_alloc - (long)dcode); #ifdef ENABLE_EAN ean_reset(&dcode->ean); #endif @@ -134,6 +134,11 @@ const char *zbar_decoder_get_data (const zbar_decoder_t *dcode) return((char*)dcode->buf); } +unsigned int zbar_decoder_get_data_length (const zbar_decoder_t *dcode) +{ + return(dcode->buflen); +} + zbar_decoder_handler_t * zbar_decoder_set_handler (zbar_decoder_t *dcode, zbar_decoder_handler_t handler) diff --git a/zbar/decoder.h b/zbar/decoder.h index 8f0a120..e390243 100644 --- a/zbar/decoder.h +++ b/zbar/decoder.h @@ -79,8 +79,9 @@ struct zbar_decoder_s { zbar_symbol_type_t lock; /* buffer lock */ /* everything above here is automatically reset */ + unsigned buf_alloc; /* dynamic buffer allocation */ + unsigned buflen; /* binary data length */ unsigned char *buf; /* decoded characters */ - unsigned buflen; /* dynamic buffer allocation */ void *userdata; /* application data */ zbar_decoder_handler_t *handler; /* application callback */ @@ -174,13 +175,13 @@ static inline char get_lock (zbar_decoder_t *dcode, static inline char size_buf (zbar_decoder_t *dcode, unsigned len) { - if(len < dcode->buflen) + if(len < dcode->buf_alloc) /* FIXME size reduction heuristic? */ return(0); if(len > BUFFER_MAX) return(1); - if(len < dcode->buflen + BUFFER_INCR) { - len = dcode->buflen + BUFFER_INCR; + if(len < dcode->buf_alloc + BUFFER_INCR) { + len = dcode->buf_alloc + BUFFER_INCR; if(len > BUFFER_MAX) len = BUFFER_MAX; } @@ -188,7 +189,7 @@ static inline char size_buf (zbar_decoder_t *dcode, if(!buf) return(1); dcode->buf = buf; - dcode->buflen = len; + dcode->buf_alloc = len; return(0); } diff --git a/zbar/decoder/code128.c b/zbar/decoder/code128.c index f435b1b..86d5723 100644 --- a/zbar/decoder/code128.c +++ b/zbar/decoder/code128.c @@ -417,6 +417,7 @@ static inline unsigned char postprocess (zbar_decoder_t *dcode) dcode->code128.character)); j += postprocess_c(dcode, cexp, i, j) * 2; } + dcode->buflen = j; dcode->buf[j] = '\0'; dcode->code128.character = j; return(0); @@ -480,10 +481,10 @@ zbar_symbol_type_t _zbar_decode_code128 (zbar_decoder_t *dcode) return(0); } - zassert(dcode->buflen > dcode128->character, 0, - "buflen=%x idx=%x c=%02x %s\n", - dcode->buflen, dcode128->character, c, - _zbar_decoder_buf_dump(dcode->buf, dcode->buflen)); + zassert(dcode->buf_alloc > dcode128->character, 0, + "alloc=%x idx=%x c=%02x %s\n", + dcode->buf_alloc, dcode128->character, c, + _zbar_decoder_buf_dump(dcode->buf, dcode->buf_alloc)); dcode->buf[dcode128->character++] = c; diff --git a/zbar/decoder/code39.c b/zbar/decoder/code39.c index 0ba0d0f..da60db8 100644 --- a/zbar/decoder/code39.c +++ b/zbar/decoder/code39.c @@ -232,6 +232,7 @@ static inline void code39_postprocess (zbar_decoder_t *dcode) dcode->buf[i] = ((dcode->buf[i] < 0x2b) ? code39_characters[(unsigned)dcode->buf[i]] : '?'); + dcode->buflen = i; dcode->buf[i] = '\0'; } diff --git a/zbar/decoder/ean.c b/zbar/decoder/ean.c index 1a335da..dee0523 100644 --- a/zbar/decoder/ean.c +++ b/zbar/decoder/ean.c @@ -594,6 +594,7 @@ static inline void postprocess (zbar_decoder_t *dcode, if(sym & ZBAR_ADDON) for(i = 13; ean->buf[i] >= 0; i++, j++) dcode->buf[j] = ean->buf[i] + '0'; + dcode->buflen = j; dcode->buf[j] = '\0'; } diff --git a/zbar/decoder/i25.c b/zbar/decoder/i25.c index 1bf297c..5fbb4e8 100644 --- a/zbar/decoder/i25.c +++ b/zbar/decoder/i25.c @@ -156,6 +156,7 @@ static inline signed char i25_decode_end (zbar_decoder_t *dcode) return(ZBAR_NONE); } + dcode->buflen = dcode25->character; dcode->buf[dcode25->character] = '\0'; dprintf(2, " [valid end]\n"); dcode25->character = -1; diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 5592624..4f8469b 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -29,7 +29,7 @@ #include /* malloc, free */ #include /* clock_gettime */ #include /* gettimeofday */ -#include /* strlen, strcmp, memset, memcpy */ +#include /* memcmp, memset, memcpy */ #include #include @@ -114,7 +114,8 @@ static inline void recycle_syms (zbar_image_scanner_t *iscn, static inline zbar_symbol_t *alloc_sym (zbar_image_scanner_t *iscn, zbar_symbol_type_t type, - const char *data) + const char *data, + int datalen) { /* recycle old or alloc new symbol */ zbar_symbol_t *sym = iscn->syms; @@ -130,12 +131,12 @@ static inline zbar_symbol_t *alloc_sym (zbar_image_scanner_t *iscn, /* save new symbol data */ sym->type = type; - int datalen = strlen(data) + 1; - if(sym->datalen < datalen) { + sym->datalen = datalen++; + if(sym->data_alloc < datalen) { if(sym->data) free(sym->data); + sym->data_alloc = datalen; sym->data = malloc(datalen); - sym->datalen = datalen; } memcpy(sym->data, data, datalen); @@ -149,7 +150,8 @@ static inline zbar_symbol_t *cache_lookup (zbar_image_scanner_t *iscn, zbar_symbol_t **entry = &iscn->cache; while(*entry) { if((*entry)->type == sym->type && - !strcmp((*entry)->data, sym->data)) + (*entry)->datalen == sym->datalen && + !memcmp((*entry)->data, sym->data, sym->datalen)) break; if((sym->time - (*entry)->time) > CACHE_TIMEOUT) { /* recycle stale cache entry */ @@ -176,19 +178,21 @@ static void symbol_handler (zbar_image_scanner_t *iscn, return; const char *data = zbar_decoder_get_data(iscn->dcode); + unsigned datalen = zbar_decoder_get_data_length(iscn->dcode); /* FIXME deprecate - instead check (x, y) inside existing polygon */ zbar_symbol_t *sym; for(sym = iscn->img->syms; sym; sym = sym->next) if(sym->type == type && - !strcmp(sym->data, data)) { + sym->datalen == datalen && + !memcmp(sym->data, data, datalen)) { /* add new point to existing set */ /* FIXME should be polygon */ sym_add_point(sym, x, y); return; } - sym = alloc_sym(iscn, type, data); + sym = alloc_sym(iscn, type, data, datalen); /* timestamp symbol */ #if _POSIX_TIMERS > 0 @@ -213,7 +217,7 @@ static void symbol_handler (zbar_image_scanner_t *iscn, if(iscn->enable_cache) { zbar_symbol_t *entry = cache_lookup(iscn, sym); if(!entry) { - entry = alloc_sym(iscn, sym->type, sym->data); + entry = alloc_sym(iscn, sym->type, sym->data, sym->datalen); entry->time = sym->time - CACHE_HYSTERESIS; entry->cache_count = -CACHE_CONSISTENCY; /* add to cache */ diff --git a/zbar/symbol.c b/zbar/symbol.c index 61dc28f..ad60356 100644 --- a/zbar/symbol.c +++ b/zbar/symbol.c @@ -65,6 +65,11 @@ const char *zbar_symbol_get_data (const zbar_symbol_t *sym) return(sym->data); } +unsigned int zbar_symbol_get_data_length (const zbar_symbol_t *sym) +{ + return(sym->datalen); +} + int zbar_symbol_get_count (const zbar_symbol_t *sym) { return(sym->cache_count); @@ -109,17 +114,12 @@ static const char *xmlfmt[] = { /* FIXME suspect... */ #define MAX_INT_DIGITS 10 -static inline void growbuf (unsigned **buf, - unsigned *len, - unsigned newlen) -{ -} - char *zbar_symbol_xml (const zbar_symbol_t *sym, char **buf, unsigned *len) { const char *type = zbar_get_symbol_name(sym->type); + /* FIXME binary data */ unsigned datalen = strlen(sym->data); unsigned maxlen = (strlen(xmlfmt[0]) + strlen(xmlfmt[1]) + strlen(xmlfmt[2]) + strlen(xmlfmt[3]) + diff --git a/zbar/symbol.h b/zbar/symbol.h index 9fb44ab..b56ec2e 100644 --- a/zbar/symbol.h +++ b/zbar/symbol.h @@ -32,10 +32,11 @@ typedef struct point_s { struct zbar_symbol_s { zbar_symbol_type_t type; /* symbol type */ - unsigned int datalen; /* allocation size of data */ - char *data; /* ascii symbol data */ + unsigned int data_alloc; /* allocation size of data */ + unsigned int datalen; /* length of binary symbol data */ + char *data; /* symbol data */ - unsigned ptslen; /* allocation size of pts */ + unsigned pts_alloc; /* allocation size of pts */ unsigned npts; /* number of points in location polygon */ point_t *pts; /* list of points in location polygon */ @@ -49,8 +50,8 @@ static inline void sym_add_point (zbar_symbol_t *sym, int y) { int i = sym->npts; - if(++sym->npts >= sym->ptslen) - sym->pts = realloc(sym->pts, ++sym->ptslen * sizeof(point_t)); + if(++sym->npts >= sym->pts_alloc) + sym->pts = realloc(sym->pts, ++sym->pts_alloc * sizeof(point_t)); sym->pts[i].x = x; sym->pts[i].y = y; } @@ -59,7 +60,7 @@ static inline void sym_destroy (zbar_symbol_t *sym) { if(sym->pts) free(sym->pts); - if(sym->data) + if(sym->data_alloc && sym->data) free(sym->data); free(sym); } From 347663c81de2524155f9455215a175f96486efa7 Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 2 Aug 2009 19:45:10 -0400 Subject: [PATCH 111/328] initial VFW video support - mostly working with uvc driver, broken for others - use /dev/video* VFW pseudo-devices - factor out common video buffer handling - fix processor to destroy window *before* video (ref TODO) - windows configure skip non-windows checks - prep for platform refactoring --- ChangeLog | 7 + TODO | 5 +- configure.ac | 29 ++- test/Makefile.am.inc | 8 +- test/test_video.c | 134 ++++++----- zbar/Makefile.am.inc | 10 +- zbar/convert.c | 7 +- zbar/error.c | 4 - zbar/error.h | 18 +- zbar/libzbar.rc | 2 +- zbar/processor.c | 21 +- zbar/processor.h | 3 +- zbar/processor/posix.c | 7 +- zbar/processor/win.c | 47 ++-- zbar/processor/win.h | 1 + zbar/video.c | 49 +++- zbar/video.h | 66 +++++- zbar/video/v4l1.c | 41 +--- zbar/video/v4l2.c | 66 ++---- zbar/video/vfw.c | 510 +++++++++++++++++++++++++++++++++++++++++ zbar/window.c | 8 +- zbarcam/zbarcam.c | 2 +- 22 files changed, 824 insertions(+), 221 deletions(-) create mode 100644 zbar/video/vfw.c diff --git a/ChangeLog b/ChangeLog index 876f731..c48d565 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,11 @@ current: + * initial VFW video support + - mostly working with uvc driver, broken for others + - factor out common video buffer handling + - fix processor to destroy window *before* video (ref TODO) + - use /dev/video* VFW pseudo-devices + - windows configure skip non-windows checks + - prep for platform refactoring * fix zbarimg b&w format handling * fix scan (image) boundary QZ handling (bug #2807538) - add linear scanner manual flush API diff --git a/TODO b/TODO index 9c517b3..06f5797 100644 --- a/TODO +++ b/TODO @@ -4,10 +4,11 @@ general: * handle video destroyed w/images outstanding * dbg_scan background image stretched (still...) * profile and weed out obvious oversights - * windows port - * fix processor layer and/or add more appropriate windows interface * example using SANE to scan symbol(s) +windows port: + * libzbar-0.dll should be zbar-0.dll + wrappers: * build API docs for zbargtk, zbarpygtk * is zbargtk/QZBar BGR4 alpha swapped? diff --git a/configure.ac b/configure.ac index 517b178..c8dd1e2 100644 --- a/configure.ac +++ b/configure.ac @@ -58,7 +58,6 @@ case $host_os in win32="no" ;; esac - AM_CONDITIONAL([WIN32], [test "x$win32" = "xyes"]) dnl programs @@ -108,8 +107,6 @@ dnl libraries AC_SEARCH_LIBS([clock_gettime], [rt]) dnl poll support -dnl without poll() we exclude processor layer -dnl FIXME superceded by WIN32 checks(?) have_poll="no" AC_CHECK_HEADERS([poll.h], [have_poll="yes"]) @@ -119,11 +116,12 @@ dnl pthreads dnl FIXME this doesn't port well, integrate something like this: dnl http://autoconf-archive.cryp.to/acx_pthread.html +enable_pthread="no" AC_ARG_ENABLE([pthread], [AS_HELP_STRING([--disable-pthread], [omit support for threaded applications])], [], - [enable_pthread="yes"]) + [AS_IF([test "x$win32" = "xno"], [enable_pthread="yes"])]) AS_IF([test "x$enable_pthread" != "xno"], [AC_CHECK_HEADERS([pthread.h], [], @@ -144,12 +142,16 @@ AC_ARG_ENABLE([video], with_video="no" AS_IF([test "x$enable_video" != "xno"], - [AC_CHECK_HEADERS([linux/videodev.h], [with_video="v4l1"], - [AC_MSG_FAILURE([test for video support failed! + [AS_IF([test "x$win32" = "xno"], + [AC_CHECK_HEADERS([linux/videodev.h], [with_video="v4l1"], + [AC_MSG_FAILURE([test for video support failed! rebuild your kernel to include video4linux support or configure --disable-video to skip building video support.])]) - AC_CHECK_HEADERS([linux/videodev2.h], [with_video="v4l2"], - [AC_MSG_WARN([v4l2 API not detected, upgrade your kernel!])]) + AC_CHECK_HEADERS([linux/videodev2.h], [with_video="v4l2"], + [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.])])]) ]) AM_CONDITIONAL([HAVE_VIDEO], [test "x$enable_video" != "xno"]) AM_CONDITIONAL([HAVE_V4L1], @@ -157,15 +159,19 @@ AM_CONDITIONAL([HAVE_V4L1], AM_CONDITIONAL([HAVE_V4L2], [test "x$with_video" = "xv4l2"]) dnl X +AC_ARG_VAR([XSHM_LIBS], [linker flags for X shared memory extension]) + +with_x="no" AC_PATH_XTRA -AH_BOTTOM([#ifndef X_DISPLAY_MISSING +AS_IF([test "x$win32" = "xno"], + [AH_BOTTOM([#ifndef X_DISPLAY_MISSING # define HAVE_X #endif + ]) + AS_IF([test "x$no_x" != "xyes"], [with_x="yes"]) ]) -AS_IF([test "x$no_x" != "xyes"], [with_x="yes"], [with_x="no"]) AM_CONDITIONAL([HAVE_X], [test "x$with_x" = "xyes"]) -AC_ARG_VAR([XSHM_LIBS], [linker flags for X shared memory extension]) AS_IF([test "x$XSHM_LIBS" = "x"], [XSHM_LIBS="-lXext"]) AC_ARG_WITH([xshm], [AS_HELP_STRING([--without-xshm], @@ -242,7 +248,6 @@ AS_IF([test "x$with_jpeg" != "xno"], set appropriately or configure --without-jpeg])], [with_jpeg="no"]) ]) - AM_CONDITIONAL([HAVE_JPEG], [test "x$with_jpeg" = "xyes"]) dnl ImageMagick diff --git a/test/Makefile.am.inc b/test/Makefile.am.inc index e3b2c00..82291ed 100644 --- a/test/Makefile.am.inc +++ b/test/Makefile.am.inc @@ -14,9 +14,11 @@ test_test_convert_LDADD = zbar/libzbar.la $(AM_LDADD) #test_test_window_CPPFLAGS = -I$(srcdir)/zbar $(AM_CPPFLAGS) #test_test_window_LDADD = zbar/libzbar.la $(AM_LDADD) -#check_PROGRAMS += test/test_video -#test_test_convert_SOURCES = test/test_video.c $(TEST_IMAGE_SOURCES) -#test_test_convert_LDADD = zbar/libzbar.la $(AM_LDADD) +if HAVE_VIDEO +check_PROGRAMS += test/test_video +test_test_video_SOURCES = test/test_video.c $(TEST_IMAGE_SOURCES) +test_test_video_LDADD = zbar/libzbar.la $(AM_LDADD) +endif check_PROGRAMS += test/test_proc test_test_proc_SOURCES = test/test_proc.c $(TEST_IMAGE_SOURCES) diff --git a/test/test_video.c b/test/test_video.c index fa80b6b..5c1af9d 100644 --- a/test/test_video.c +++ b/test/test_video.c @@ -31,19 +31,26 @@ #include #include #include +#include #include #include -#include "processor.h" /* reuse some processor guts */ #include "test_images.h" -zbar_processor_t proc; +#ifdef _WIN32 +struct timespec { + time_t tv_sec; + long tv_nsec; +}; +#endif + +zbar_video_t *video; int main (int argc, char *argv[]) { - zbar_set_verbosity(10); + zbar_set_verbosity(32); - const char *dev = "/dev/video0"; + const char *dev = ""; if(argc > 1) { if(!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { printf("usage: %s [/dev/[v4l/]videoX]\n", argv[0]); @@ -56,20 +63,20 @@ int main (int argc, char *argv[]) dev = argv[1]; } - memset(&proc, 0, sizeof(proc)); - proc.video = zbar_video_create(); - proc.window = zbar_window_create(); - if(!proc.video || !proc.window) { + video = zbar_video_create(); + if(!video) { fprintf(stderr, "unable to allocate memory?!\n"); return(1); } - if(zbar_video_open(proc.video, dev)) { - zbar_video_error_spew(proc.video, 0); + zbar_video_request_size(video, 640, 480); + + if(zbar_video_open(video, dev)) { + zbar_video_error_spew(video, 0); fprintf(stderr, "ERROR: unable to access your video device\n" "this program requires video capture support using" - " v4l version 1 or 2\n" + " v4l version 1 or 2 or VfW\n" " - is your video device located at \"%s\"?\n" " - is your video driver installed? (check dmesg)\n" " - make sure you have the latest drivers\n" @@ -80,94 +87,85 @@ int main (int argc, char *argv[]) dev); return(1); } - printf("opened video device: %s (fd=%d)\n", - dev, zbar_video_get_fd(proc.video)); - - if(_zbar_window_open(&proc, "zbar video test", 640, 480) || - zbar_window_attach(proc.window, proc.display, proc.xwin) || - _zbar_window_set_visible(&proc, 1)) - fprintf(stderr, "WARNING: failed to open test window\n"); - else if(zbar_negotiate_format(proc.video, proc.window)) - fprintf(stderr, "WARNING: failed to negotiate compatible format\n"); - - zbar_image_t *img = zbar_image_create(); - zbar_image_set_size(img, 640, 480); - zbar_image_set_format(img, fourcc('Y','V','1','2')); - test_image_bars(img); - if(proc.display && zbar_window_draw(proc.window, img)) { - fprintf(stderr, "ERROR: drawing image\n"); - return(zbar_window_error_spew(proc.window, 0)); + fprintf(stderr, "opened video device: %s (fd=%d)\n", + dev, zbar_video_get_fd(video)); + fflush(stderr); + + uint32_t vidfmt = fourcc('Y','U','Y','2'); + if(zbar_video_init(video, vidfmt)) { + fprintf(stderr, "ERROR: failed to set format: %.4s(%08x)\n", + (char*)&vidfmt, vidfmt); + return(zbar_video_error_spew(video, 0)); } - if(zbar_video_enable(proc.video, 1)) { + if(zbar_video_enable(video, 1)) { fprintf(stderr, "ERROR: starting video stream\n"); - return(zbar_video_error_spew(proc.video, 0)); + return(zbar_video_error_spew(video, 0)); } + fprintf(stderr, "started video stream...\n"); + fflush(stderr); - zbar_image_t *image = zbar_video_next_image(proc.video); + zbar_image_t *image = zbar_video_next_image(video); if(!image) { fprintf(stderr, "ERROR: unable to capture image\n"); - return(zbar_video_error_spew(proc.video, 0)); + return(zbar_video_error_spew(video, 0)); } uint32_t format = zbar_image_get_format(image); unsigned width = zbar_image_get_width(image); unsigned height = zbar_image_get_height(image); const uint8_t *data = zbar_image_get_data(image); - printf("captured image: %d x %d %.4s @%p\n", - width, height, (char*)&format, data); + fprintf(stderr, "captured image: %d x %d %.4s @%p\n", + width, height, (char*)&format, data); + fflush(stderr); - if(proc.display && zbar_window_draw(proc.window, image)) { - fprintf(stderr, "ERROR: drawing image\n"); - return(zbar_window_error_spew(proc.window, 0)); - } zbar_image_destroy(image); - printf("\nstreaming...click to continue\n"); + fprintf(stderr, "\nstreaming 100 frames...\n"); + fflush(stderr); + struct timespec start, end; +#if _POSIX_TIMERS > 0 clock_gettime(CLOCK_REALTIME, &start); - int n = 0; - while(1) { - if(proc.display && _zbar_window_handle_events(&proc, 0)) - break; - zbar_image_t *image = zbar_video_next_image(proc.video); +#else + struct timeval ustime; + gettimeofday(&ustime, NULL); + start.tv_nsec = ustime.tv_usec * 1000; + start.tv_sec = ustime.tv_sec; +#endif + + int i; + for(i = 0; i < 100; i++) { + zbar_image_t *image = zbar_video_next_image(video); if(!image) { fprintf(stderr, "ERROR: unable to capture image\n"); - return(zbar_video_error_spew(proc.video, 0)); - } - - if(proc.display && zbar_window_draw(proc.window, image)) { - fprintf(stderr, "ERROR: drawing image\n"); - return(zbar_window_error_spew(proc.window, 0)); + return(zbar_video_error_spew(video, 0)); } zbar_image_destroy(image); - n++; } + +#if _POSIX_TIMERS > 0 clock_gettime(CLOCK_REALTIME, &end); +#else + gettimeofday(&ustime, NULL); + end.tv_nsec = ustime.tv_usec * 1000; + end.tv_sec = ustime.tv_sec; +#endif double ms = (end.tv_sec - start.tv_sec + (end.tv_nsec - start.tv_nsec) / 1000000000.); - double fps = n / ms; - printf("\nprocessed %d images in %gs @%gfps\n", n, ms, fps); + double fps = i / ms; + fprintf(stderr, "\nprocessed %d images in %gs @%gfps\n", i, ms, fps); + fflush(stderr); - if(zbar_video_enable(proc.video, 0)) { + if(zbar_video_enable(video, 0)) { fprintf(stderr, "ERROR: while stopping video stream\n"); - return(zbar_video_error_spew(proc.video, 0)); + return(zbar_video_error_spew(video, 0)); } - printf("\nvideo support verified\n\n"); - - if(proc.display && zbar_window_draw(proc.window, img)) { - fprintf(stderr, "error drawing image\n"); - return(zbar_window_error_spew(proc.window, 0)); - } - zbar_image_destroy(img); - printf("click to end...\n"); - if(proc.display) - _zbar_window_handle_events(&proc, 1); - - zbar_window_destroy(proc.window); - zbar_video_destroy(proc.video); + zbar_video_destroy(video); if(test_image_check_cleanup()) return(32); + + fprintf(stderr, "\nvideo support verified\n\n"); return(0); } diff --git a/zbar/Makefile.am.inc b/zbar/Makefile.am.inc index 2220e48..8455f36 100644 --- a/zbar/Makefile.am.inc +++ b/zbar/Makefile.am.inc @@ -37,6 +37,7 @@ zbar_libzbar_la_SOURCES += zbar/processor/win.h zbar/processor/win.c \ zbar/libzbar.rc zbar_libzbar_la_CPPFLAGS += -mthreads zbar_libzbar_la_LDFLAGS += -mthreads +# FIXME broken zbar_libzbar_la_LIBADD += zbar/libzbar-rc.lo endif @@ -45,7 +46,14 @@ zbar_libzbar_la_SOURCES += zbar/video/v4l1.c if HAVE_V4L2 zbar_libzbar_la_SOURCES += zbar/video/v4l2.c endif -else +endif +if WIN32 +if HAVE_VIDEO +zbar_libzbar_la_SOURCES += zbar/video/vfw.c +zbar_libzbar_la_LIBADD += -lvfw32 +endif +endif +if !HAVE_VIDEO zbar_libzbar_la_SOURCES += zbar/video/null.c endif diff --git a/zbar/convert.c b/zbar/convert.c index 850def7..4a39659 100644 --- a/zbar/convert.c +++ b/zbar/convert.c @@ -43,7 +43,7 @@ typedef struct conversion_def_s { /* NULL terminated list of known formats, in order of preference * (NB Cr=V Cb=U) */ -static const uint32_t format_prefs[] = { +const uint32_t _zbar_formats[] = { /* planar YUV formats */ fourcc('4','2','2','P'), /* FIXME also YV16? */ @@ -106,8 +106,7 @@ static const uint32_t format_prefs[] = { 0 }; -static const int num_format_prefs = - sizeof(format_prefs) / sizeof(zbar_format_def_t); +const int _zbar_num_formats = sizeof(_zbar_formats) / sizeof(uint32_t); /* format definitions */ static const zbar_format_def_t format_defs[] = { @@ -1093,7 +1092,7 @@ int zbar_negotiate_format (zbar_video_t *vdo, unsigned min_cost = -1; uint32_t min_fmt = 0; const uint32_t *fmt; - for(fmt = format_prefs; *fmt; fmt++) { + for(fmt = _zbar_formats; *fmt; fmt++) { /* only consider formats supported by video device */ if(!has_format(*fmt, srcs)) continue; diff --git a/zbar/error.c b/zbar/error.c index 2d3e646..7bd3caf 100644 --- a/zbar/error.c +++ b/zbar/error.c @@ -24,10 +24,6 @@ #include "error.h" #include -#ifdef _WIN32 -# include -#endif - int _zbar_verbosity = 0; static const char * const sev_str[] = { diff --git a/zbar/error.h b/zbar/error.h index 113d3ea..89dcba2 100644 --- a/zbar/error.h +++ b/zbar/error.h @@ -35,6 +35,10 @@ #include +#ifdef _WIN32 +# include +#endif + #if __STDC_VERSION__ < 199901L # if __GNUC__ >= 2 # define __func__ __FUNCTION__ @@ -79,9 +83,17 @@ extern int _zbar_verbosity; /* FIXME don't we need varargs hacks here? */ +#ifdef _WIN32 +# define ZFLUSH fflush(stderr); +#else +# define ZFLUSH +#endif + #define zprintf(level, format, ...) do { \ - if(_zbar_verbosity >= level) \ + if(_zbar_verbosity >= level) { \ fprintf(stderr, "%s: " format, __func__ , ##__VA_ARGS__); \ + ZFLUSH \ + } \ } while(0) static inline int err_copy (void *dst_c, @@ -113,6 +125,10 @@ static inline int err_capture (const void *container, assert(err->magic == ERRINFO_MAGIC); if(type == ZBAR_ERR_SYSTEM) err->errnum = errno; +#ifdef _WIN32 + else if(type == ZBAR_ERR_WINAPI) + err->errnum = GetLastError(); +#endif err->sev = sev; err->type = type; err->func = func; diff --git a/zbar/libzbar.rc b/zbar/libzbar.rc index 3ce2b9c..a847368 100644 --- a/zbar/libzbar.rc +++ b/zbar/libzbar.rc @@ -21,7 +21,7 @@ VS_VERSION_INFO VERSIONINFO XSTR(LIB_VERSION_MINOR) "." XSTR(LIB_VERSION_REVISION) VALUE "ProductVersion", PACKAGE_VERSION - VALUE "FileDescription", "Bar code scanning library" + VALUE "FileDescription", "Bar code reader library" VALUE "LegalCopyright", "Copyright 2007-2009 (c) Jeff Brown " } diff --git a/zbar/processor.c b/zbar/processor.c index c9a1e44..030e98f 100644 --- a/zbar/processor.c +++ b/zbar/processor.c @@ -131,6 +131,13 @@ int zbar_processor_init (zbar_processor_t *proc, _zbar_processor_threads_stop(proc); + _zbar_processor_close(proc); + + if(proc->window) { + zbar_window_destroy(proc->window); + proc->window = NULL; + } + int rc = 0; if(proc->video) { if(dev) @@ -141,13 +148,6 @@ int zbar_processor_init (zbar_processor_t *proc, } } - _zbar_processor_close(proc); - - if(proc->window) { - zbar_window_destroy(proc->window); - proc->window = NULL; - } - if(!dev && !enable_display) /* nothing to do */ goto done; @@ -173,15 +173,14 @@ int zbar_processor_init (zbar_processor_t *proc, proc->req_width, proc->req_height); if(proc->req_intf) zbar_video_request_interface(proc->video, proc->req_intf); - if((proc->req_iomode && - zbar_video_request_iomode(proc->video, proc->req_iomode)) || - zbar_video_open(proc->video, dev)) { + if(proc->req_iomode && + zbar_video_request_iomode(proc->video, proc->req_iomode)) { rc = err_copy(proc, proc->video); goto done; } } - rc = _zbar_processor_threads_start(proc); + rc = _zbar_processor_threads_start(proc, dev); if(rc) goto done; diff --git a/zbar/processor.h b/zbar/processor.h index 100da4a..fbf91c7 100644 --- a/zbar/processor.h +++ b/zbar/processor.h @@ -76,7 +76,8 @@ extern int _zbar_processor_wait(zbar_processor_t*, unsigned, int); extern int _zbar_processor_threads_init(zbar_processor_t*, int); extern int _zbar_processor_threads_cleanup(zbar_processor_t*); -extern int _zbar_processor_threads_start(zbar_processor_t*); +extern int _zbar_processor_threads_start(zbar_processor_t*, + const char*); extern int _zbar_processor_threads_stop(zbar_processor_t*); extern int _zbar_processor_open(zbar_processor_t*, char*, unsigned, unsigned); diff --git a/zbar/processor/posix.c b/zbar/processor/posix.c index d92c7b1..39c07af 100644 --- a/zbar/processor/posix.c +++ b/zbar/processor/posix.c @@ -395,8 +395,13 @@ int _zbar_processor_threads_init (zbar_processor_t *proc, return(0); } -int _zbar_processor_threads_start (zbar_processor_t *proc) +int _zbar_processor_threads_start (zbar_processor_t *proc, + const char *dev) { + if(proc->video && + zbar_video_open(proc->video, dev)) + return(err_copy(proc, proc->video)); + if(!proc->threaded) return(0); diff --git a/zbar/processor/win.c b/zbar/processor/win.c index 4441873..a7f3128 100644 --- a/zbar/processor/win.c +++ b/zbar/processor/win.c @@ -213,6 +213,10 @@ static inline int proc_thread_stop (processor_state_t *state, int _zbar_processor_threads_init (zbar_processor_t *proc, int threaded) { + if(!threaded) + err_capture(proc, SEV_WARNING, ZBAR_ERR_UNSUPPORTED, + __func__, "windows processor does not support unthreaded"); + processor_state_t *state = proc->state = calloc(1, sizeof(processor_state_t)); @@ -242,6 +246,11 @@ int _zbar_processor_threads_cleanup (zbar_processor_t *proc) DeleteCriticalSection(&state->mutex); + if(state->video_dev) { + free(state->video_dev); + state->video_dev = NULL; + } + free(state); proc->state = NULL; return(0); @@ -256,7 +265,15 @@ static DWORD WINAPI proc_video_thread (void *arg) DWORD self = GetCurrentThreadId(); int rc = 0; + /* windows video must be opened from driving thread */ + if(zbar_video_open(proc->video, state->video_dev)) { + err_copy(proc, proc->video); + SetEvent(tstate->stopped); + return(0); + } + EnterCriticalSection(&state->mutex); + zprintf(4, "spawned video thread\n"); SetEvent(tstate->started); wait_entry_t *entry = proc_entry_alloc(state, self); @@ -305,12 +322,15 @@ static DWORD WINAPI proc_video_thread (void *arg) zbar_image_destroy(img); EnterCriticalSection(&state->mutex); + assert(state->lock_level == 1); wait_entry_t *next = proc_entry_dequeue(&state->lock_queue); if(next) { state->lock_owner = next->requester; SetEvent(next->notify); } + else + state->lock_level = 0; } proc_entry_free(state, entry); @@ -321,10 +341,14 @@ static DWORD WINAPI proc_video_thread (void *arg) return(0); } -int _zbar_processor_threads_start (zbar_processor_t *proc) +int _zbar_processor_threads_start (zbar_processor_t *proc, + const char *dev) { - return(proc_thread_start(proc, &proc->state->video_thread, - proc_video_thread)); + processor_state_t *state = proc->state; + if(state->video_dev) + free(state->video_dev); + state->video_dev = strdup(dev); + return(proc_thread_start(proc, &state->video_thread, proc_video_thread)); } int _zbar_processor_threads_stop (zbar_processor_t *proc) @@ -431,11 +455,9 @@ static inline int proc_handle_events (zbar_processor_t *proc) int rc = PeekMessage(&msg, state->hwnd, 0, 0, PM_NOYIELD | PM_REMOVE); if(!rc) return(0); - if(rc < 0) { - proc->err.errnum = GetLastError(); + if(rc < 0) return(err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, "failed to obtain event")); - } TranslateMessage(&msg); DispatchMessage(&msg); @@ -475,18 +497,14 @@ static inline int proc_open (zbar_processor_t *proc, HMODULE hmod = NULL; if(!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, - (void*)_zbar_processor_open, (HINSTANCE*)&hmod)) { - proc->err.errnum = GetLastError(); + (void*)_zbar_processor_open, (HINSTANCE*)&hmod)) return(err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, "failed to obtain module handle")); - } ATOM wca = proc_register_class(hmod); - if(!wca) { - proc->err.errnum = GetLastError(); + if(!wca) return(err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, "failed to register window class")); - } RECT r = { 0, 0, width, height }; AdjustWindowRectEx(&r, WIN_STYLE, 0, EXT_STYLE); @@ -496,11 +514,9 @@ static inline int proc_open (zbar_processor_t *proc, r.right - r.left, r.bottom - r.top, NULL, NULL, hmod, proc); - if(!state->hwnd) { - proc->err.errnum = GetLastError(); + if(!state->hwnd) return(err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, "failed to open window")); - } return(0); } @@ -518,6 +534,7 @@ static DWORD WINAPI proc_input_thread (void *arg) } EnterCriticalSection(&state->mutex); + zprintf(4, "spawned input thread\n"); SetEvent(tstate->started); while(!rc && tstate->running) { diff --git a/zbar/processor/win.h b/zbar/processor/win.h index 464b498..29c8bde 100644 --- a/zbar/processor/win.h +++ b/zbar/processor/win.h @@ -42,6 +42,7 @@ typedef struct thread_state_s { } thread_state_t; struct processor_state_s { + char *video_dev; /* device name */ HWND hwnd; /* window handle */ int input; unsigned width, height; diff --git a/zbar/video.c b/zbar/video.c index 39b0f4d..413290b 100644 --- a/zbar/video.c +++ b/zbar/video.c @@ -69,6 +69,10 @@ zbar_video_t *zbar_video_create () return(NULL); } #endif +#ifdef _WIN32 + InitializeCriticalSection(&vdo->qlock); + vdo->notify = CreateEvent(NULL, 0, 0, NULL); +#endif /* pre-allocate images */ vdo->num_images = ZBAR_VIDEO_IMAGES_MAX; @@ -120,6 +124,10 @@ void zbar_video_destroy (zbar_video_t *vdo) #ifdef HAVE_LIBPTHREAD pthread_mutex_destroy(&vdo->qlock); #endif +#ifdef _WIN32 + DeleteCriticalSection(&vdo->qlock); + CloseHandle(vdo->notify); +#endif #ifdef HAVE_LIBJPEG if(vdo->jpeg_img) { zbar_image_destroy(vdo->jpeg_img); @@ -141,15 +149,14 @@ int zbar_video_open (zbar_video_t *vdo, int zbar_video_get_fd (const zbar_video_t *vdo) { - if(vdo->fd >= 0 && vdo->intf == VIDEO_V4L2) - return(vdo->fd); - - if(vdo->intf != VIDEO_V4L2) + if(vdo->intf == VIDEO_INVALID) + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, + "video device not opened")); + if(vdo->intf == VIDEO_V4L1) return(err_capture(vdo, SEV_WARNING, ZBAR_ERR_UNSUPPORTED, __func__, "v4l1 API does not support polling")); - - return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, - "video device not opened")); + assert(vdo->fd >= 0); + return(vdo->fd); } int zbar_video_request_size (zbar_video_t *vdo, @@ -170,7 +177,7 @@ int zbar_video_request_size (zbar_video_t *vdo, int zbar_video_request_interface (zbar_video_t *vdo, int ver) { - if(vdo->fd >= 0) + if(vdo->intf != VIDEO_INVALID) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "device already opened, unable to change interface")); vdo->intf = (video_interface_t)ver; @@ -181,7 +188,7 @@ int zbar_video_request_interface (zbar_video_t *vdo, int zbar_video_request_iomode (zbar_video_t *vdo, int iomode) { - if(vdo->fd >= 0) + if(vdo->intf != VIDEO_INVALID) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "device already opened, unable to change iomode")); if(iomode < 0 || iomode > VIDEO_USERPTR) @@ -233,11 +240,13 @@ static inline int video_init_images (zbar_video_t *vdo) img->data = vdo->buf + offset; zprintf(2, " [%02d] @%08lx\n", i, offset); } +#ifndef _WIN32 else { assert(img->data); assert(img->datalen); assert(img->datalen >= vdo->datalen); } +#endif } return(0); } @@ -283,7 +292,7 @@ int zbar_video_enable (zbar_video_t *vdo, return(0); if(enable) { - if(vdo->fd < 0) + if(vdo->intf == VIDEO_INVALID) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "video device not opened")); @@ -295,10 +304,26 @@ int zbar_video_enable (zbar_video_t *vdo, if(video_lock(vdo)) return(-1); vdo->active = enable; - if(enable) + if(enable) { + /* enqueue all buffers */ + int i; + for(i = 0; i < vdo->num_images; i++) + if(vdo->nq(vdo, vdo->images[i]) || + ((i + 1 < vdo->num_images) && video_lock(vdo))) + return(-1); + return(vdo->start(vdo)); - else + } + else { + int i; + for(i = 0; i < vdo->num_images; i++) + vdo->images[i]->next = NULL; + vdo->nq_image = vdo->dq_image = NULL; + if(video_unlock(vdo)) + return(-1); + return(vdo->stop(vdo)); + } } zbar_image_t *zbar_video_next_image (zbar_video_t *vdo) diff --git a/zbar/video.h b/zbar/video.h index fa9f602..d164fbe 100644 --- a/zbar/video.h +++ b/zbar/video.h @@ -36,8 +36,13 @@ # include #endif +#ifdef _WIN32 +# include +#endif + #include +#include "image.h" #include "error.h" /* number of images to preallocate */ @@ -47,6 +52,7 @@ typedef enum video_interface_e { VIDEO_INVALID = 0, /* uninitialized */ VIDEO_V4L1, /* v4l protocol version 1 */ VIDEO_V4L2, /* v4l protocol version 2 */ + VIDEO_VFW, /* video for windows */ } video_interface_t; typedef enum video_iomode_e { @@ -82,6 +88,14 @@ struct zbar_video_s { #ifdef HAVE_LIBPTHREAD pthread_mutex_t qlock; /* lock image queue */ #endif +#ifdef _WIN32 + HWND hwnd; /* vfw interface */ + CRITICAL_SECTION qlock; /* lock image queue */ + HANDLE notify; /* capture thread status change */ + int bi_size; /* size of bih */ + BITMAPINFOHEADER *bih; /* video format details */ + zbar_image_t *image; /* currently capturing frame */ +#endif #ifdef HAVE_LIBJPEG struct jpeg_decompress_struct *jpeg; /* JPEG decompressor */ @@ -130,11 +144,57 @@ static inline int video_unlock (zbar_video_t *vdo) } #else -# define video_lock(...) (0) -# define video_unlock(...) (0) +# ifdef _WIN32 + +static inline int video_lock (zbar_video_t *vdo) +{ + EnterCriticalSection(&vdo->qlock); + return(0); +} + +static inline int video_unlock (zbar_video_t *vdo) +{ + LeaveCriticalSection(&vdo->qlock); + return(0); +} + +# else +# define video_lock(...) (0) +# define video_unlock(...) (0) +# endif #endif +static inline int video_nq_image (zbar_video_t *vdo, + zbar_image_t *img) +{ + /* maintains queued buffers in order */ + img->next = NULL; + if(vdo->nq_image) + vdo->nq_image->next = img; + vdo->nq_image = img; + if(!vdo->dq_image) + vdo->dq_image = img; + return(video_unlock(vdo)); +} + +static inline zbar_image_t *video_dq_image (zbar_video_t *vdo) +{ + zbar_image_t *img = vdo->dq_image; + if(img) { + vdo->dq_image = img->next; + img->next = NULL; + } + if(video_unlock(vdo)) + /* FIXME reclaim image */ + return(NULL); + + if(!img) + /* FIXME block until available? */ + err_capture(vdo, SEV_ERROR, ZBAR_ERR_BUSY, __func__, + "all allocated video images busy"); + return(img); +} + extern int _zbar_video_open(zbar_video_t*, const char*); -extern int _zbar_v4l2_probe(zbar_video_t*); #endif diff --git a/zbar/video/v4l1.c b/zbar/video/v4l1.c index 2fb0792..d6efef0 100644 --- a/zbar/video/v4l1.c +++ b/zbar/video/v4l1.c @@ -46,6 +46,8 @@ #include "video.h" #include "image.h" +extern int _zbar_v4l2_probe(zbar_video_t*); + typedef struct v4l1_format_s { uint32_t format; uint8_t bpp; @@ -83,14 +85,7 @@ static const v4l1_format_t v4l1_formats[17] = { static int v4l1_nq (zbar_video_t *vdo, zbar_image_t *img) { - /* v4l1 maintains queued buffers in order */ - img->next = NULL; - if(vdo->nq_image) - vdo->nq_image->next = img; - vdo->nq_image = img; - if(!vdo->dq_image) - vdo->dq_image = img; - if(video_unlock(vdo)) + if(video_nq_image(vdo, img)) return(-1); if(vdo->iomode != VIDEO_MMAP) @@ -110,21 +105,9 @@ static int v4l1_nq (zbar_video_t *vdo, static zbar_image_t *v4l1_dq (zbar_video_t *vdo) { - zbar_image_t *img = NULL; - img = vdo->dq_image; - if(img) { - vdo->dq_image = img->next; - img->next = NULL; - } - if(video_unlock(vdo)) - return(NULL); - - if(!img) { - /* FIXME block until available? */ - err_capture(vdo, SEV_ERROR, ZBAR_ERR_BUSY, __func__, - "all allocated video images busy"); + zbar_image_t *img = video_dq_image(vdo); + if(!img) return(NULL); - } if(vdo->iomode == VIDEO_MMAP) { int frame = img->srcidx; @@ -187,22 +170,12 @@ static int v4l1_mmap_buffers (zbar_video_t *vdo) static int v4l1_start (zbar_video_t *vdo) { - /* enqueue all buffers */ - int i; - for(i = 0; i < vdo->num_images; i++) - if(vdo->nq(vdo, vdo->images[i]) || - ((i + 1 < vdo->num_images) && video_lock(vdo))) - return(-1); return(0); } static int v4l1_stop (zbar_video_t *vdo) { - int i; - for(i = 0; i < vdo->num_images; i++) - vdo->images[i]->next = NULL; - vdo->nq_image = vdo->dq_image = NULL; - return(video_unlock(vdo)); + return(0); } static inline int v4l1_set_format (zbar_video_t *vdo, @@ -221,7 +194,7 @@ static inline int v4l1_set_format (zbar_video_t *vdo, break; if(!fmt || ifmt >= VIDEO_PALETTE_YUV410P) return(err_capture_int(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, - "invalid v4l1 format: %08x", fmt)); + "invalid v4l1 format: %x", fmt)); vpic.palette = ifmt; vpic.depth = v4l1_formats[ifmt].bpp; diff --git a/zbar/video/v4l2.c b/zbar/video/v4l2.c index e09b8f9..301d93d 100644 --- a/zbar/video/v4l2.c +++ b/zbar/video/v4l2.c @@ -48,32 +48,28 @@ static int v4l2_nq (zbar_video_t *vdo, zbar_image_t *img) { - if(vdo->iomode != VIDEO_READWRITE) { - if(video_unlock(vdo)) - return(-1); + if(vdo->iomode == VIDEO_READWRITE) + return(video_nq_image(vdo, img)); - struct v4l2_buffer vbuf; - memset(&vbuf, 0, sizeof(vbuf)); - vbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if(vdo->iomode == VIDEO_MMAP) { - vbuf.memory = V4L2_MEMORY_MMAP; - vbuf.index = img->srcidx; - } - else { - vbuf.memory = V4L2_MEMORY_USERPTR; - vbuf.m.userptr = (unsigned long)img->data; - vbuf.length = img->datalen; - vbuf.index = img->srcidx; /* FIXME workaround broken drivers */ - } - if(ioctl(vdo->fd, VIDIOC_QBUF, &vbuf) < 0) - return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, - "queuing video buffer (VIDIOC_QBUF)")); + if(video_unlock(vdo)) + return(-1); + + struct v4l2_buffer vbuf; + memset(&vbuf, 0, sizeof(vbuf)); + vbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if(vdo->iomode == VIDEO_MMAP) { + vbuf.memory = V4L2_MEMORY_MMAP; + vbuf.index = img->srcidx; } else { - img->next = vdo->nq_image; - vdo->nq_image = img; - return(video_unlock(vdo)); + vbuf.memory = V4L2_MEMORY_USERPTR; + vbuf.m.userptr = (unsigned long)img->data; + vbuf.length = img->datalen; + vbuf.index = img->srcidx; /* FIXME workaround broken drivers */ } + if(ioctl(vdo->fd, VIDIOC_QBUF, &vbuf) < 0) + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, + "queuing video buffer (VIDIOC_QBUF)")); return(0); } @@ -116,17 +112,9 @@ static zbar_image_t *v4l2_dq (zbar_video_t *vdo) } } else { - /* FIXME block until image available? */ - img = vdo->nq_image; - if(img) - vdo->nq_image = img->next; - if(video_unlock(vdo)) - return(NULL); - if(!img) { - err_capture(vdo, SEV_ERROR, ZBAR_ERR_BUSY, __func__, - "all allocated video images busy"); + zbar_image_t *img = video_dq_image(vdo); + if(!img) return(NULL); - } /* FIXME should read entire image */ unsigned long datalen = read(vdo->fd, (void*)img->data, img->datalen); @@ -144,13 +132,6 @@ static zbar_image_t *v4l2_dq (zbar_video_t *vdo) static int v4l2_start (zbar_video_t *vdo) { - /* enqueue all buffers */ - int i; - for(i = 0; i < vdo->num_images; i++) - if(vdo->nq(vdo, vdo->images[i]) || - ((i + 1 < vdo->num_images) && video_lock(vdo))) - return(-1); - if(vdo->iomode == VIDEO_READWRITE) return(0); @@ -163,13 +144,6 @@ static int v4l2_start (zbar_video_t *vdo) static int v4l2_stop (zbar_video_t *vdo) { - int i; - for(i = 0; i < vdo->num_images; i++) - vdo->images[i]->next = NULL; - vdo->nq_image = vdo->dq_image = NULL; - if(video_unlock(vdo)) - return(-1); - if(vdo->iomode == VIDEO_READWRITE) return(0); diff --git a/zbar/video/vfw.c b/zbar/video/vfw.c new file mode 100644 index 0000000..35a9692 --- /dev/null +++ b/zbar/video/vfw.c @@ -0,0 +1,510 @@ +/*------------------------------------------------------------------------ + * Copyright 2009 (c) Jeff Brown + * + * 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 "video.h" +#include + +#include + +#define MAX_DRIVERS 10 +#define MAX_NAME 128 + +#define BIH_FMT "%ldx%ld @%dbpp (%lx) cmp=%.4s(%08lx) res=%ldx%ld clr=%ld/%ld (%lx)" +#define BIH_FIELDS(bih) \ + (bih)->biWidth, (bih)->biHeight, (bih)->biBitCount, (bih)->biSizeImage, \ + (char*)&(bih)->biCompression, (bih)->biCompression, \ + (bih)->biXPelsPerMeter, (bih)->biYPelsPerMeter, \ + (bih)->biClrImportant, (bih)->biClrUsed, (bih)->biSize + +static const uint32_t vfw_formats[] = { + /* planar YUV formats */ + fourcc('I','4','2','0'), + /* FIXME YU12 is IYUV is windows */ + fourcc('Y','V','1','2'), + /* FIXME IMC[1-4]? */ + + /* planar Y + packed UV plane */ + fourcc('N','V','1','2'), + + /* packed YUV formats */ + fourcc('U','Y','V','Y'), + fourcc('Y','U','Y','2'), /* FIXME add YVYU */ + /* FIXME AYUV? Y411? Y41P? */ + + /* packed rgb formats */ + fourcc('B','G','R','3'), + fourcc('B','G','R','4'), + + fourcc('Y','V','U','9'), + + /* basic grayscale format */ + fourcc('G','R','E','Y'), + fourcc('Y','8','0','0'), + + /* compressed formats */ + fourcc('J','P','E','G'), + + /* terminator */ + 0 +}; + +#define VFW_NUM_FORMATS (sizeof(vfw_formats) / sizeof(uint32_t)) + +/* this seems to be required so the message pump can run, even when + * we're not capturing...anyway, what's one more thread in the huge + * fabric that is vfw? :| + */ +#define ZBAR_VFW_THREADED 1 + +#ifdef ZBAR_VFW_THREADED +static DWORD WINAPI vfw_capture_thread (void *arg) +{ + zbar_video_t *vdo = arg; + + vdo->hwnd = capCreateCaptureWindow(NULL, WS_POPUP, 0, 0, 1, 1, NULL, 0); + + /* FIXME error */ + assert(vdo->hwnd); + + SetEvent(vdo->notify); + zprintf(4, "spawned vfw capture thread\n"); + + MSG msg; + int rc = -2; + while((rc = GetMessage(&msg, NULL, 0, 0)) > 0) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + if(vdo->hwnd) { + DestroyWindow(vdo->hwnd); + vdo->hwnd = NULL; + } + zprintf(4, "exiting vfw capture thread\n"); + return(rc); +} +#endif + +static LRESULT CALLBACK vfw_stream_cb (HWND hwnd, + VIDEOHDR *hdr) +{ + if(!hwnd || !hdr) + return(0); + zbar_video_t *vdo = (void*)capGetUserData(hwnd); + + video_lock(vdo); + zbar_image_t *img = vdo->image; + if(!img) { + video_lock(vdo); + img = video_dq_image(vdo); + } + if(img) { + img->data = hdr->lpData; + img->datalen = hdr->dwBufferLength; + vdo->image = img; + SetEvent(vdo->notify); + } + video_unlock(vdo); + + zprintf(64, "img=%p\n", vdo->image); + return(1); +} + +static LRESULT CALLBACK vfw_control_cb (HWND hwnd, + int state) +{ + if(!hwnd) + return(0); + zbar_video_t *vdo = (void*)capGetUserData(hwnd); + zprintf(64, "thr=%04lx vdo=%p state=%d\n", + GetCurrentThreadId(), vdo, state); + +#if 0 + switch(state) { + case CONTROLCALLBACK_PREROLL: + break; + case CONTROLCALLBACK_CAPTURING: + break; + } +#endif + return(1); +} + +static LRESULT CALLBACK vfw_error_cb (HWND hwnd, + int errid, + const char *errmsg) +{ + if(!hwnd) + return(0); + zbar_video_t *vdo = (void*)capGetUserData(hwnd); + zprintf(2, "thr=%04lx vdo=%p id=%d msg=%s\n", + GetCurrentThreadId(), vdo, errid, errmsg); + return(1); +} + +static int vfw_nq (zbar_video_t *vdo, + zbar_image_t *img) +{ + zprintf(64,"thr=%04lx vdo=%p img=%p\n", GetCurrentThreadId(), vdo, img); + img->data = NULL; + img->datalen = 0; + return(video_nq_image(vdo, img)); +} + +static zbar_image_t *vfw_dq (zbar_video_t *vdo) +{ + zbar_image_t *img = vdo->image; + zprintf(64,"thr=%04lx vdo=%p img=%p\n", GetCurrentThreadId(), vdo, img); + if(!img) { + video_unlock(vdo); + +#ifdef ZBAR_VFW_THREADED + WaitForSingleObject(vdo->notify, INFINITE); +#else + int rc = 1; + while(rc == 1) { + MSG msg; + rc = MsgWaitForMultipleObjects(1, &vdo->notify, + 0, INFINITE, QS_ALLINPUT); + if(rc == 1) { + GetMessage(&msg, NULL, 0, 0); + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } +#endif + video_lock(vdo); + img = vdo->image; + /*FIXME errors */ + } + if(img) + vdo->image = NULL; + video_unlock(vdo); + + zprintf(64,"img=%p\n", img); + return(img); +} + +static int vfw_start (zbar_video_t *vdo) +{ + zprintf(64,"enter...\n"); + if(!capCaptureSequenceNoFile(vdo->hwnd)) + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, + "starting video stream")); + zprintf(64,"...leave\n"); + return(0); +} + +static int vfw_stop (zbar_video_t *vdo) +{ + zprintf(64,"\n"); + if(!capCaptureAbort(vdo->hwnd)) + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, + "stopping video stream")); + return(0); +} + +static int vfw_set_format (zbar_video_t *vdo, + uint32_t fmt) +{ + const zbar_format_def_t *fmtdef = _zbar_format_lookup(fmt); + if(!fmtdef->format) + return(err_capture_int(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, + "unsupported vfw format: %x", fmt)); + + BITMAPINFOHEADER *bih = vdo->bih; + assert(vdo->bih); + bih->biWidth = vdo->width; + bih->biHeight = vdo->height; + switch(fmtdef->group) { + case ZBAR_FMT_GRAY: + bih->biBitCount = 8; + break; + case ZBAR_FMT_YUV_PLANAR: + case ZBAR_FMT_YUV_PACKED: + case ZBAR_FMT_YUV_NV: + bih->biBitCount = 8 + (16 >> (fmtdef->p.yuv.xsub2 + fmtdef->p.yuv.ysub2)); + break; + case ZBAR_FMT_RGB_PACKED: + bih->biBitCount = fmtdef->p.rgb.bpp * 8; + break; + default: + bih->biBitCount = 0; + } + bih->biClrUsed = bih->biClrImportant = 0; + bih->biCompression = fmt; + + zprintf(4, "seting format: %.4s(%08x) " BIH_FMT "\n", + (char*)&fmt, fmt, BIH_FIELDS(bih)); + + if(!capSetVideoFormat(vdo->hwnd, bih, vdo->bi_size)) + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, + "setting format")); + + if(!capGetVideoFormat(vdo->hwnd, bih, vdo->bi_size)) + return(-1/*FIXME*/); + + if(bih->biCompression != fmt) + return(-1/*FIXME*/); + + vdo->format = fmt; + vdo->width = bih->biWidth; + vdo->height = bih->biHeight; + vdo->datalen = bih->biSizeImage; + + zprintf(4, "set new format: %.4s(%08x) " BIH_FMT "\n", + (char*)&fmt, fmt, BIH_FIELDS(bih)); + return(0); +} + +static int vfw_init (zbar_video_t *vdo, + uint32_t fmt) +{ + if(vfw_set_format(vdo, fmt)) + return(-1); + + CAPTUREPARMS cp; + if(!capCaptureGetSetup(vdo->hwnd, &cp, sizeof(cp))) + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, + "retrieving capture parameters")); + + cp.dwRequestMicroSecPerFrame = 33333; + cp.fMakeUserHitOKToCapture = 0; + cp.wPercentDropForError = 90; + cp.fYield = 1; + cp.wNumVideoRequested = vdo->num_images; + cp.fCaptureAudio = 0; + cp.vKeyAbort = 0; + cp.fAbortLeftMouse = 0; + cp.fAbortRightMouse = 0; + cp.fLimitEnabled = 0; + + if(!capCaptureSetSetup(vdo->hwnd, &cp, sizeof(cp))) + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, + "setting capture parameters")); + + if(!capCaptureGetSetup(vdo->hwnd, &cp, sizeof(cp))) + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, + "checking capture parameters")); + + /* ignore errors since we skipped checking fHasOverlay */ + capOverlay(vdo->hwnd, 0); + + if(!capPreview(vdo->hwnd, 0) || + !capPreviewScale(vdo->hwnd, 0)) + err_capture(vdo, SEV_WARNING, ZBAR_ERR_WINAPI, __func__, + "disabling preview"); + + capSetCallbackOnCapControl(vdo->hwnd, vfw_control_cb); + + if(!capSetCallbackOnVideoStream(vdo->hwnd, vfw_stream_cb) || + !capSetCallbackOnError(vdo->hwnd, vfw_error_cb)) + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_BUSY, __func__, + "setting capture callbacks")); + + vdo->num_images = cp.wNumVideoRequested; + vdo->iomode = VIDEO_MMAP; /* driver provides "locked" buffers */ + + zprintf(3, "initialized video capture: %d buffers %ldms/frame\n", + vdo->num_images, cp.dwRequestMicroSecPerFrame); + + return(0); +} + +static int vfw_probe_format (zbar_video_t *vdo, + uint32_t fmt) +{ + const zbar_format_def_t *fmtdef = _zbar_format_lookup(fmt); + if(!fmtdef) + return(0); + + zprintf(4, " trying %.4s(%08x)...\n", (char*)&fmt, fmt); + BITMAPINFOHEADER *bih = vdo->bih; + bih->biWidth = vdo->width; + bih->biHeight = vdo->height; + switch(fmtdef->group) { + case ZBAR_FMT_GRAY: + bih->biBitCount = 8; + break; + case ZBAR_FMT_YUV_PLANAR: + case ZBAR_FMT_YUV_PACKED: + case ZBAR_FMT_YUV_NV: + bih->biBitCount = 8 + (16 >> (fmtdef->p.yuv.xsub2 + fmtdef->p.yuv.ysub2)); + break; + case ZBAR_FMT_RGB_PACKED: + bih->biBitCount = fmtdef->p.rgb.bpp * 8; + break; + default: + bih->biBitCount = 0; + } + bih->biCompression = fmt; + + if(!capSetVideoFormat(vdo->hwnd, bih, vdo->bi_size)) { + zprintf(4, "\tno (set fails)\n"); + return(0); + } + + if(!capGetVideoFormat(vdo->hwnd, bih, vdo->bi_size)) + return(0/*FIXME error...*/); + + zprintf(6, "\tactual: " BIH_FMT "\n", BIH_FIELDS(bih)); + + if(bih->biCompression != fmt) { + zprintf(4, "\tno (set ignored)\n"); + return(0); + } + + zprintf(4, "\tyes\n"); + return(1); +} + +static int vfw_probe (zbar_video_t *vdo) +{ + if(!capSetUserData(vdo->hwnd, (LONG)vdo)) + return(-1/*FIXME*/); + + vdo->bi_size = capGetVideoFormatSize(vdo->hwnd); + if(!vdo->bi_size) + return(-1/*FIXME*/); + + BITMAPINFOHEADER *bih = vdo->bih = realloc(vdo->bih, vdo->bi_size); + /* FIXME check OOM */ + if(!capGetVideoFormat(vdo->hwnd, bih, vdo->bi_size)) + return(-1/*FIXME*/); + + zprintf(3, "initial format: " BIH_FMT " (bisz=%x)\n", + BIH_FIELDS(bih), vdo->bi_size); + + if(!vdo->width || !vdo->height) { + vdo->width = bih->biWidth; + vdo->height = bih->biHeight; + } + vdo->datalen = bih->biSizeImage; + + zprintf(2, "probing supported formats:\n"); + vdo->formats = calloc(VFW_NUM_FORMATS, sizeof(uint32_t)); + + int n = 0; + const uint32_t *fmt; + for(fmt = vfw_formats; *fmt; fmt++) + if(vfw_probe_format(vdo, *fmt)) + vdo->formats[n++] = *fmt; + + vdo->formats = realloc(vdo->formats, (n + 1) * sizeof(uint32_t)); + + vdo->width = bih->biWidth; + vdo->height = bih->biHeight; + vdo->intf = VIDEO_VFW; + vdo->init = vfw_init; + vdo->start = vfw_start; + vdo->stop = vfw_stop; + vdo->cleanup = vfw_stop; + vdo->nq = vfw_nq; + vdo->dq = vfw_dq; + return(0); +} + +int _zbar_video_open (zbar_video_t *vdo, + const char *dev) +{ + /* close open device */ + if(vdo->hwnd) { + video_lock(vdo); + if(vdo->active) { + vdo->active = 0; + vdo->stop(vdo); + } + if(vdo->cleanup) + vdo->cleanup(vdo); + + SendMessage(vdo->hwnd, WM_QUIT, 0, 0); + /* FIXME wait for thread to terminate */ + /*assert(!vdo->hwnd);*/ + + zprintf(1, "closed camera\n"); + vdo->hwnd = NULL; + vdo->intf = VIDEO_INVALID; + vdo->fd = -1; + video_unlock(vdo); + } + if(!dev) + return(0); + + int devid; + if(*(unsigned char*)dev < 0x10) + devid = *dev; + else if((!strncmp(dev, "/dev/video", 10) || + !strncmp(dev, "\\dev\\video", 10)) && + dev[10] >= '0' && dev[10] <= '9' && !dev[11]) + devid = dev[10] - '0'; + else + devid = -1; + + zprintf(6, "searching for camera: %s (%d)\n", dev, devid); + char name[MAX_NAME], desc[MAX_NAME]; + for(vdo->fd = 0; vdo->fd < MAX_DRIVERS; vdo->fd++) { + if(!capGetDriverDescription(vdo->fd, name, MAX_NAME, desc, MAX_NAME)) { + /* FIXME TBD error */ + zprintf(6, " [%d] not found...\n", vdo->fd); + continue; + } + zprintf(6, " [%d] %.100s - %.100s\n", vdo->fd, name, desc); + if((devid >= 0) + ? vdo->fd == devid + : !strncmp(dev, name, MAX_NAME)) + break; + } + if(vdo->fd >= MAX_DRIVERS) + return(err_capture_str(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, + "video device not found '%s'", dev)); + +#ifdef ZBAR_VFW_THREADED + HANDLE hthr = CreateThread(NULL, 0, vfw_capture_thread, vdo, 0, NULL); + if(!hthr) + return(-1/*FIXME*/); + CloseHandle(hthr); + + if(WaitForSingleObject(vdo->notify, INFINITE)) + return(-1/*FIXME*/); +#else + vdo->hwnd = capCreateCaptureWindow(NULL, WS_POPUP, 0, 0, 1, 1, NULL, 0); +#endif + + /* FIXME error */ + assert(vdo->hwnd); + + if(!capDriverConnect(vdo->hwnd, vdo->fd)) { + DestroyWindow(vdo->hwnd); + /* FIXME error: failed to connect to camera */ + assert(0); + } + + zprintf(1, "opened camera: %.60s (thr=%04lx)\n", + name, GetCurrentThreadId()); + + if(vfw_probe(vdo)) { + _zbar_video_open(vdo, NULL); + return(-1); + } + return(0); +} diff --git a/zbar/window.c b/zbar/window.c index 4df71c8..f781230 100644 --- a/zbar/window.c +++ b/zbar/window.c @@ -48,6 +48,12 @@ void zbar_window_destroy (zbar_window_t *w) /* detach */ zbar_window_attach(w, NULL, 0); err_cleanup(&w->err); +#ifdef HAVE_LIBPTHREAD + pthread_mutex_destroy(&w->imglock); +#endif +#ifdef _WIN32 + DeleteCriticalSection(&w->imglock); +#endif free(w); } @@ -143,7 +149,7 @@ inline int zbar_window_redraw (zbar_window_t *w) } if(!rc) - rc = w->draw_image(w, w->image); + rc = w->draw_image(w, img); if(!rc) rc = window_draw_overlay(w); } diff --git a/zbarcam/zbarcam.c b/zbarcam/zbarcam.c index 66c3c4e..df76c90 100644 --- a/zbarcam/zbarcam.c +++ b/zbarcam/zbarcam.c @@ -132,7 +132,7 @@ int main (int argc, const char *argv[]) } zbar_processor_set_data_handler(proc, data_handler, NULL); - const char *video_device = "/dev/video0"; + const char *video_device = ""; int display = 1; unsigned long infmt = 0, outfmt = 0; int i; From 5937df660b7644850b34e18a96d6a09f558c3760 Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 3 Aug 2009 15:02:04 -0400 Subject: [PATCH 112/328] fix symbol leaks - add symbol reference counting --- ChangeLog | 2 ++ TODO | 2 -- doc/Makefile.am.inc | 2 ++ include/zbar.h | 13 +++++++++++++ perl/ZBar.xs | 13 +++++++++++-- python/image.c | 12 +++++++++++- python/symbol.c | 8 ++++++++ zbar/convert.c | 3 ++- zbar/decoder.c | 4 +++- zbar/image.c | 10 ++++++++++ zbar/image.h | 11 ++++++----- zbar/img_scanner.c | 25 +++++++++++++++++-------- zbar/symbol.c | 6 ++++++ zbar/symbol.h | 9 +++++++++ 14 files changed, 100 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index b3cfc34..5df76cf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * fix symbol leaks + - add symbol reference counting * add support for binary symbol data * fix zbarimg b&w format handling * fix scan (image) boundary QZ handling (bug #2807538) diff --git a/TODO b/TODO index ca992e8..ed614d0 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,4 @@ general: - * cleanup symbol leaks * finish error handling * handle video destroyed w/images outstanding * dbg_scan background image stretched (still...) @@ -14,7 +13,6 @@ wrappers: * widget config APIs * drag-and-drop for widgets (configurable...) * Perl build support integration? - * Perl object lifetime problems? (eg Symbol) * GTK and Qt perl bindings * C++ global wrappers diff --git a/doc/Makefile.am.inc b/doc/Makefile.am.inc index fea5f36..55ae5b6 100644 --- a/doc/Makefile.am.inc +++ b/doc/Makefile.am.inc @@ -26,6 +26,8 @@ docs: $(dist_man_MANS) #dist_doc_DATA .PHONY: docs doc_path = --searchpath $(abs_builddir)/doc -m $(abs_srcdir)/doc/style.xsl +# xmlto --searchpath broken again... +doc_path += --skip-validation #pdf: doc/zbar-manual.pdf #doc/zbar-manual.pdf: $(DOCSOURCES) diff --git a/include/zbar.h b/include/zbar.h index 224bed6..2a996e7 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -202,6 +202,19 @@ struct zbar_symbol_s; /** opaque decoded symbol object. */ typedef struct zbar_symbol_s zbar_symbol_t; +/** symbol reference count manipulation. + * increment the reference count when you store a new reference to the + * symbol. decrement when the reference is no longer used. do not + * refer to the symbol once the count is decremented and the + * containing image has been recycled or destroyed. + * @note the containing image holds a reference to the symbol, so you + * only need to use this if you keep a symbol after the image has been + * destroyed or reused. + * @since 0.9 + */ +extern void zbar_symbol_ref(zbar_symbol_t *symbol, + int refs); + /** retrieve type of decoded symbol. * @returns the symbol type */ diff --git a/perl/ZBar.xs b/perl/ZBar.xs index 2eab08d..af1ee39 100644 --- a/perl/ZBar.xs +++ b/perl/ZBar.xs @@ -292,6 +292,12 @@ BOOT: CONSTANT(symbol_type, , CODE128, zbar_get_symbol_name(ZBAR_CODE128)); } +void +DESTROY(symbol) + Barcode::ZBar::Symbol symbol + CODE: + zbar_symbol_ref(symbol, -1); + zbar_symbol_type_t zbar_symbol_get_type(symbol) Barcode::ZBar::Symbol symbol @@ -385,9 +391,12 @@ get_symbols(image) const zbar_symbol_t *sym; PPCODE: sym = zbar_image_first_symbol(image); - for(; sym; sym = zbar_symbol_next(sym)) + for(; sym; sym = zbar_symbol_next(sym)) { + zbar_symbol_t *s = (zbar_symbol_t*)sym; + zbar_symbol_ref(s, 1); XPUSHs(sv_setref_pv(sv_newmortal(), "Barcode::ZBar::Symbol", (void*)sym)); + } void zbar_image_set_format(image, format) @@ -450,7 +459,7 @@ DESTROY(processor) zbar_processor_destroy(processor); void -zbar_processor_init(processor, video_device="/dev/video0", enable_display=1) +zbar_processor_init(processor, video_device="", enable_display=1) Barcode::ZBar::Processor processor const char * video_device bool enable_display diff --git a/python/image.c b/python/image.c index 901c856..debc504 100644 --- a/python/image.c +++ b/python/image.c @@ -40,6 +40,11 @@ symboliter_traverse (zbarSymbolIter *self, static int symboliter_clear (zbarSymbolIter *self) { + if(self->zsym) { + zbar_symbol_t *zsym = (zbar_symbol_t*)self->zsym; + self->zsym = NULL; + zbar_symbol_ref(zsym, -1); + } Py_CLEAR(self->img); return(0); } @@ -63,10 +68,15 @@ symboliter_iternext (zbarSymbolIter *self) { if(!self->zsym) self->zsym = zbar_image_first_symbol(self->img->zimg); - else + else { + zbar_symbol_t *zsym = (zbar_symbol_t*)self->zsym; + zbar_symbol_ref(zsym, -1); self->zsym = zbar_symbol_next(self->zsym); + } if(!self->zsym) return(NULL); + zbar_symbol_t *zsym = (zbar_symbol_t*)self->zsym; + zbar_symbol_ref(zsym, 1); return(zbarSymbol_FromSymbol(self->img, self->zsym)); } diff --git a/python/symbol.c b/python/symbol.c index 5e25785..92dfe85 100644 --- a/python/symbol.c +++ b/python/symbol.c @@ -40,6 +40,11 @@ symbol_traverse (zbarSymbol *self, static int symbol_clear (zbarSymbol *self) { + if(self->zsym) { + zbar_symbol_t *zsym = (zbar_symbol_t*)self->zsym; + self->zsym = NULL; + zbar_symbol_ref(zsym, -1); + } Py_CLEAR(self->img); Py_CLEAR(self->data); Py_CLEAR(self->loc); @@ -72,6 +77,7 @@ symbol_get_data (zbarSymbol *self, void *closure) { if(!self->data) { + /* FIXME this could be a buffer now */ self->data = PyString_FromStringAndSize(zbar_symbol_get_data(self->zsym), zbar_symbol_get_data_length(self->zsym)); @@ -134,6 +140,8 @@ zbarSymbol_FromSymbol (zbarImage *img, assert(img); assert(zsym); Py_INCREF(img); + zbar_symbol_t *zs = (zbar_symbol_t*)zsym; + zbar_symbol_ref(zs, 1); self->zsym = zsym; self->img = img; self->data = NULL; diff --git a/zbar/convert.c b/zbar/convert.c index 850def7..c753971 100644 --- a/zbar/convert.c +++ b/zbar/convert.c @@ -349,7 +349,8 @@ static void convert_copy (zbar_image_t *dst, dst->datalen = src->datalen; dst->cleanup = cleanup_ref; dst->next = (zbar_image_t*)src; - _zbar_image_refcnt((zbar_image_t*)src, 1); + zbar_image_t *s = (zbar_image_t*)src; + _zbar_image_refcnt(s, 1); } else /* NB only for GRAY/YUV_PLANAR formats */ diff --git a/zbar/decoder.c b/zbar/decoder.c index 39a1ecc..5a989f6 100644 --- a/zbar/decoder.c +++ b/zbar/decoder.c @@ -357,15 +357,17 @@ int zbar_decoder_set_config (zbar_decoder_t *dcode, static char *decoder_dump = NULL; +static unsigned decoder_dumplen = 0; const char *_zbar_decoder_buf_dump (unsigned char *buf, unsigned int buflen) { int dumplen = (buflen * 3) + 12; - if(!decoder_dump || dumplen > strlen(decoder_dump)) { + if(!decoder_dump || dumplen > decoder_dumplen) { if(decoder_dump) free(decoder_dump); decoder_dump = malloc(dumplen); + decoder_dumplen = dumplen; } char *p = decoder_dump + snprintf(decoder_dump, 12, "buf[%04x]=", diff --git a/zbar/image.c b/zbar/image.c index adf5a7f..f646409 100644 --- a/zbar/image.c +++ b/zbar/image.c @@ -34,6 +34,16 @@ zbar_image_t *zbar_image_create () return(img); } +void _zbar_image_free (zbar_image_t *img) +{ + zbar_symbol_t *sym, *next; + for(sym = img->syms; sym; sym = next) { + next = sym->next; + _zbar_symbol_refcnt(sym, -1); + } + free(img); +} + void zbar_image_destroy (zbar_image_t *img) { _zbar_image_refcnt(img, -1); diff --git a/zbar/image.h b/zbar/image.h index 9673804..37a322b 100644 --- a/zbar/image.h +++ b/zbar/image.h @@ -101,18 +101,19 @@ typedef struct zbar_format_def_s { } zbar_format_def_t; +extern int _zbar_best_format(uint32_t, uint32_t*, const uint32_t*); +extern const zbar_format_def_t *_zbar_format_lookup(uint32_t); +extern void _zbar_image_free(zbar_image_t *img); + static inline void _zbar_image_refcnt (zbar_image_t *img, int delta) { - if(!_zbar_refcnt(&img->refcnt, delta)) { + if(!_zbar_refcnt(&img->refcnt, delta) && delta <= 0) { if(img->cleanup) img->cleanup(img); if(!img->src) - free(img); + _zbar_image_free(img); } } -extern int _zbar_best_format(uint32_t, uint32_t*, const uint32_t*); -extern const zbar_format_def_t *_zbar_format_lookup(uint32_t); - #endif diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 4f8469b..f7ce52f 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -94,18 +94,24 @@ static inline void recycle_syms (zbar_image_scanner_t *iscn, /* walk to root of clone tree */ while(img) { img->nsyms = 0; - zbar_symbol_t *sym = img->syms; - if(sym) { - /* recycle image symbols */ - iscn->nsyms++; - while(sym->next) { - sym = sym->next; + /* recycle image symbols */ + zbar_symbol_t **symp = &img->syms, *sym; + while((sym = *symp)) + if(_zbar_refcnt(&sym->refcnt, -1)) { + *symp = sym->next; + sym->next = NULL; + } + else { iscn->nsyms++; + symp = &sym->next; } - sym->next = iscn->syms; + + if(symp != &img->syms) { + *symp = iscn->syms; iscn->syms = img->syms; - img->syms = NULL; } + img->syms = NULL; + /* save root */ iscn->img = img; img = img->next; @@ -193,6 +199,7 @@ static void symbol_handler (zbar_image_scanner_t *iscn, } sym = alloc_sym(iscn, type, data, datalen); + _zbar_symbol_refcnt(sym, 1); /* timestamp symbol */ #if _POSIX_TIMERS > 0 @@ -217,6 +224,7 @@ static void symbol_handler (zbar_image_scanner_t *iscn, if(iscn->enable_cache) { zbar_symbol_t *entry = cache_lookup(iscn, sym); if(!entry) { + /* FIXME reuse sym */ entry = alloc_sym(iscn, sym->type, sym->data, sym->datalen); entry->time = sym->time - CACHE_HYSTERESIS; entry->cache_count = -CACHE_CONSISTENCY; @@ -241,6 +249,7 @@ static void symbol_handler (zbar_image_scanner_t *iscn, else sym->cache_count = 0; + /* FIXME option to only report count == 0 */ if(iscn->handler) iscn->handler(iscn->img, iscn->userdata); } diff --git a/zbar/symbol.c b/zbar/symbol.c index ad60356..6d0cd01 100644 --- a/zbar/symbol.c +++ b/zbar/symbol.c @@ -55,6 +55,12 @@ const char *zbar_get_addon_name (zbar_symbol_type_t sym) } } +void zbar_symbol_ref (zbar_symbol_t *sym, + int refs) +{ + _zbar_symbol_refcnt(sym, refs); +} + zbar_symbol_type_t zbar_symbol_get_type (const zbar_symbol_t *sym) { return(sym->type); diff --git a/zbar/symbol.h b/zbar/symbol.h index b56ec2e..ad317a3 100644 --- a/zbar/symbol.h +++ b/zbar/symbol.h @@ -25,6 +25,7 @@ #include #include +#include "refcnt.h" typedef struct point_s { int x, y; @@ -40,6 +41,7 @@ struct zbar_symbol_s { unsigned npts; /* number of points in location polygon */ point_t *pts; /* list of points in location polygon */ + refcnt_t refcnt; /* reference count */ zbar_symbol_t *next; /* linked list of results */ unsigned long time; /* relative symbol capture time */ int cache_count; /* cache state */ @@ -65,4 +67,11 @@ static inline void sym_destroy (zbar_symbol_t *sym) free(sym); } +static inline void _zbar_symbol_refcnt (zbar_symbol_t *sym, + int delta) +{ + if(!_zbar_refcnt(&sym->refcnt, delta) && delta <= 0) + sym_destroy(sym); +} + #endif From 94e90873025b004adf350d4e80fd8372687e21b7 Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 12 Aug 2009 14:57:13 -0400 Subject: [PATCH 113/328] major restructuring to improve platform abstraction - add lock, thread and timer abstractions - migrate specific notification locks to platform independent layer - fixes to vfw capture interface - fix window format conversion issues - fix some broken configure checks - zbarcam working in windows! --- ChangeLog | 9 +- configure.ac | 26 +- test/test_proc.c | 35 ++- test/test_video.c | 24 +- zbar/Makefile.am.inc | 14 +- zbar/event.h | 63 ++++ zbar/mutex.h | 160 ++++++++++ zbar/processor.c | 370 ++++++++++++++++------- zbar/processor.h | 63 +++- zbar/processor/lock.c | 217 ++++++++++++++ zbar/processor/posix.c | 529 +++++++++++---------------------- zbar/processor/posix.h | 95 +++--- zbar/processor/win.c | 538 ++++++++-------------------------- zbar/processor/win.h | 108 ------- zbar/processor/x.c | 87 ++---- zbar/thread.h | 123 ++++++++ zbar/timer.h | 120 ++++++++ zbar/video.c | 65 ++-- zbar/video.h | 57 +--- zbar/video/v4l1.c | 30 +- zbar/video/v4l2.c | 8 +- zbar/video/vfw.c | 292 +++++++++--------- zbar/window.c | 38 +-- zbar/window.h | 123 ++------ zbar/window/dib.c | 16 +- zbar/window/vfw.c | 3 + zbar/window/win.c | 145 +++++---- zbar/{logo.c => window/win.h} | 29 +- zbar/window/x.c | 151 ++++++---- zbar/window/x.h | 73 +++++ zbar/window/ximage.c | 31 +- zbar/window/xv.c | 91 +++--- 32 files changed, 2020 insertions(+), 1713 deletions(-) create mode 100644 zbar/event.h create mode 100644 zbar/mutex.h create mode 100644 zbar/processor/lock.c delete mode 100644 zbar/processor/win.h create mode 100644 zbar/thread.h create mode 100644 zbar/timer.h rename zbar/{logo.c => window/win.h} (69%) create mode 100644 zbar/window/x.h diff --git a/ChangeLog b/ChangeLog index 8942672..f89b1b0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ current: - * fix symbol leaks + * major restructuring to improve platform abstraction + - add lock, thread and timer abstractions + - migrate specific notification locks to platform independent layer + - fixes to vfw capture interface + - fix window format conversion issues + - fix some broken configure checks + - zbarcam working in windows! + * fix symbol leaks (bug #2820658) - add symbol reference counting * add support for binary symbol data * initial VFW video support diff --git a/configure.ac b/configure.ac index c8dd1e2..2e02509 100644 --- a/configure.ac +++ b/configure.ac @@ -108,20 +108,21 @@ AC_SEARCH_LIBS([clock_gettime], [rt]) dnl poll support -have_poll="no" -AC_CHECK_HEADERS([poll.h], [have_poll="yes"]) +AC_CHECK_HEADERS([poll.h], [have_poll="yes"], [have_poll="no"]) AM_CONDITIONAL([HAVE_POLL], [test "x$have_poll" = "xyes"]) dnl pthreads dnl FIXME this doesn't port well, integrate something like this: dnl http://autoconf-archive.cryp.to/acx_pthread.html -enable_pthread="no" AC_ARG_ENABLE([pthread], [AS_HELP_STRING([--disable-pthread], [omit support for threaded applications])], [], - [AS_IF([test "x$win32" = "xno"], [enable_pthread="yes"])]) + [AS_IF([test "x$win32" = "xno"], + [enable_pthread="yes"], + [enable_pthread="no" +])]) AS_IF([test "x$enable_pthread" != "xno"], [AC_CHECK_HEADERS([pthread.h], [], @@ -131,6 +132,7 @@ configure --disable-pthread to skip threaded support.])]) [AC_MSG_FAILURE([unable to link against -lpthread, although you appear to have pthread.h? set LDFLAGS and/or LIBS to help the linker, or configure --disable-pthread to skip threaded support.])]) + AC_DEFINE([__USE_UNIX98], [1], [used only for pthread debug attributes]) ]) dnl video @@ -161,16 +163,14 @@ AM_CONDITIONAL([HAVE_V4L2], [test "x$with_video" = "xv4l2"]) dnl X AC_ARG_VAR([XSHM_LIBS], [linker flags for X shared memory extension]) -with_x="no" -AC_PATH_XTRA -AS_IF([test "x$win32" = "xno"], - [AH_BOTTOM([#ifndef X_DISPLAY_MISSING +AS_IF([test "x$win32" != "xno"], + [have_x="no"], + [AC_PATH_XTRA + AH_BOTTOM([#ifndef X_DISPLAY_MISSING # define HAVE_X #endif - ]) - AS_IF([test "x$no_x" != "xyes"], [with_x="yes"]) -]) -AM_CONDITIONAL([HAVE_X], [test "x$with_x" = "xyes"]) +])]) +AM_CONDITIONAL([HAVE_X], [test "x$have_x" = "xyes"]) AS_IF([test "x$XSHM_LIBS" = "x"], [XSHM_LIBS="-lXext"]) AC_ARG_WITH([xshm], @@ -421,7 +421,7 @@ dnl summary log echo "" echo "please verify that the detected configuration matches your expectations:" echo "------------------------------------------------------------------------" -echo "X --with-x=$with_x" +echo "X --with-x=$have_x" echo "pthreads --enable-pthread=$enable_pthread" echo "v4l --enable-video=$enable_video" AS_IF([test "x$enable_video" != "xyes"], diff --git a/test/test_proc.c b/test/test_proc.c index 5a6ffc0..172a89a 100644 --- a/test/test_proc.c +++ b/test/test_proc.c @@ -37,6 +37,7 @@ #include "test_images.h" zbar_processor_t *proc = NULL; +int use_threads = 1, use_window = 1; int input_wait (int timeout) { @@ -45,14 +46,15 @@ int input_wait (int timeout) timeout / 1000, timeout % 1000); else fprintf(stderr, "waiting indefinitely for input..."); - fflush(stdout); + fflush(stderr); int rc = zbar_processor_user_wait(proc, timeout); if(rc > 0) - fprintf(stderr, "got input\n"); + fprintf(stderr, "got input (%02x)\n", rc); else if(!rc) fprintf(stderr, "timed out\n"); else if(zbar_processor_get_error_code(proc) == ZBAR_ERR_CLOSED) - return(0); + use_window = rc = 0; + fflush(stderr); return(rc); } @@ -60,7 +62,8 @@ int main (int argc, char **argv) { zbar_set_verbosity(31); char *video_dev = NULL; - int i, use_threads = 1, use_window = 1; + uint32_t fmt = 0; + int i, j = 0; for(i = 1; i < argc; i++) { if(argv[i][0] == '-') { if(!strncmp(argv[i], "-thr", 4)) @@ -70,38 +73,51 @@ int main (int argc, char **argv) else return(1); } - else + else if(!j++) video_dev = argv[i]; + else if(j++ == 1) { + int n = strlen(argv[i]); + if(n > 4) + n = 4; + memcpy((char*)&fmt, argv[i], n); + } } + if(!fmt) + fmt = fourcc('B','G','R','3'); proc = zbar_processor_create(use_threads); assert(proc); fprintf(stderr, "created processor (%sthreaded)\n", (!use_threads) ? "un" : ""); + fflush(stderr); if(zbar_processor_init(proc, NULL, 0)) return(2); fprintf(stderr, "initialized (video=disabled, window=disabled)\n"); + fflush(stderr); zbar_image_t *img = zbar_image_create(); zbar_image_set_size(img, 640, 480); - zbar_image_set_format(img, fourcc('B','G','R','3')); + zbar_image_set_format(img, fmt); test_image_bars(img); if(zbar_process_image(proc, img) < 0) return(3); fprintf(stderr, "processed test image\n"); + fflush(stderr); if(zbar_processor_init(proc, video_dev, use_window)) return(2); fprintf(stderr, "reinitialized (video=%s, window=%s)\n", (video_dev) ? video_dev : "disabled", (use_window) ? "enabled" : "disabled"); + fflush(stderr); if(use_window) { if(zbar_processor_set_visible(proc, 1)) return(4); fprintf(stderr, "window visible\n"); + fflush(stderr); } if(input_wait((use_window && !video_dev) ? -1 : 2000) < 0) @@ -110,6 +126,7 @@ int main (int argc, char **argv) if(zbar_process_image(proc, img) < 0) return(3); fprintf(stderr, "processed test image\n"); + fflush(stderr); zbar_image_destroy(img); if(input_wait((use_window && !video_dev) ? -1 : 3333) < 0) @@ -119,6 +136,7 @@ int main (int argc, char **argv) if(zbar_processor_set_active(proc, 1)) return(3); fprintf(stderr, "video activated\n"); + fflush(stderr); if(input_wait((use_window) ? -1 : 4000) < 0) return(5); @@ -126,6 +144,7 @@ int main (int argc, char **argv) if(zbar_processor_set_active(proc, 0)) return(3); fprintf(stderr, "video deactivated\n"); + fflush(stderr); if(input_wait((use_window) ? -1 : 4000) < 0) return(5); @@ -136,10 +155,14 @@ int main (int argc, char **argv) if(zbar_process_image(proc, NULL)) return(3); fprintf(stderr, "flushed image\n"); + fflush(stderr); if(input_wait((use_window && !video_dev) ? -1 : 2500) < 0) return(5); + fprintf(stderr, "cleaning up...\n"); + fflush(stderr); + zbar_processor_destroy(proc); proc = NULL; if(test_image_check_cleanup()) diff --git a/test/test_video.c b/test/test_video.c index 5c1af9d..bdd5c9c 100644 --- a/test/test_video.c +++ b/test/test_video.c @@ -48,20 +48,22 @@ zbar_video_t *video; int main (int argc, char *argv[]) { - zbar_set_verbosity(32); + zbar_set_verbosity(31); const char *dev = ""; + uint32_t vidfmt = 0; if(argc > 1) { - if(!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { - printf("usage: %s [/dev/[v4l/]videoX]\n", argv[0]); - return(0); - } - else if(!strcmp(argv[1], "--version")) { - printf(PACKAGE_VERSION "\n"); - return(0); - } dev = argv[1]; + + if(argc > 2) { + int n = strlen(argv[2]); + if(n > 4) + n = 4; + memcpy((char*)&vidfmt, argv[2], n); + } } + if(!vidfmt) + vidfmt = fourcc('B','G','R','3'); video = zbar_video_create(); if(!video) { @@ -91,7 +93,6 @@ int main (int argc, char *argv[]) dev, zbar_video_get_fd(video)); fflush(stderr); - uint32_t vidfmt = fourcc('Y','U','Y','2'); if(zbar_video_init(video, vidfmt)) { fprintf(stderr, "ERROR: failed to set format: %.4s(%08x)\n", (char*)&vidfmt, vidfmt); @@ -161,6 +162,9 @@ int main (int argc, char *argv[]) return(zbar_video_error_spew(video, 0)); } + fprintf(stderr, "\ncleaning up...\n"); + fflush(stderr); + zbar_video_destroy(video); if(test_image_check_cleanup()) diff --git a/zbar/Makefile.am.inc b/zbar/Makefile.am.inc index 8455f36..931cb23 100644 --- a/zbar/Makefile.am.inc +++ b/zbar/Makefile.am.inc @@ -7,7 +7,9 @@ zbar_libzbar_la_LIBADD = zbar_libzbar_la_SOURCES = zbar/debug.h zbar/config.c \ zbar/error.h zbar/error.c zbar/symbol.h zbar/symbol.c \ zbar/image.h zbar/image.c zbar/convert.c \ - zbar/processor.c zbar/processor.h zbar/refcnt.h zbar/refcnt.c \ + zbar/processor.c zbar/processor.h zbar/processor/lock.c \ + zbar/refcnt.h zbar/refcnt.c zbar/timer.h zbar/mutex.h \ + zbar/event.h zbar/thread.h \ zbar/window.h zbar/window.c zbar/video.h zbar/video.c \ zbar/img_scanner.c zbar/scanner.c \ zbar/decoder.h zbar/decoder.c @@ -33,12 +35,11 @@ if HAVE_POLL zbar_libzbar_la_SOURCES += zbar/processor/posix.h zbar/processor/posix.c endif if WIN32 -zbar_libzbar_la_SOURCES += zbar/processor/win.h zbar/processor/win.c \ - zbar/libzbar.rc +zbar_libzbar_la_SOURCES += zbar/processor/win.c zbar/libzbar.rc zbar_libzbar_la_CPPFLAGS += -mthreads zbar_libzbar_la_LDFLAGS += -mthreads # FIXME broken -zbar_libzbar_la_LIBADD += zbar/libzbar-rc.lo +#zbar_libzbar_la_LIBADD += zbar/libzbar-rc.lo endif if HAVE_V4L1 @@ -73,9 +74,10 @@ zbar_libzbar_la_LIBADD += $(XV_LIBS) endif else if WIN32 -zbar_libzbar_la_SOURCES += zbar/window/win.c zbar/window/dib.c +zbar_libzbar_la_SOURCES += zbar/window/win.h zbar/window/win.c \ + zbar/window/dib.c # zbar/window/vfw.c -lvfw32 -zbar_libzbar_la_LIBADD += -lgdi32 +zbar_libzbar_la_LIBADD += -lgdi32 -lwinmm else zbar_libzbar_la_SOURCES += zbar/window/null.c endif diff --git a/zbar/event.h b/zbar/event.h new file mode 100644 index 0000000..483d647 --- /dev/null +++ b/zbar/event.h @@ -0,0 +1,63 @@ +/*------------------------------------------------------------------------ + * Copyright 2007-2009 (c) Jeff Brown + * + * 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 + *------------------------------------------------------------------------*/ +#ifndef _ZBAR_EVENT_H_ +#define _ZBAR_EVENT_H_ + +#include +#include "mutex.h" +#include "timer.h" + +/* platform synchronization "event" abstraction + */ + +#if defined(_WIN32) + +# include + +typedef HANDLE zbar_event_t; + + +#elif defined(HAVE_LIBPTHREAD) + +# include + +typedef struct zbar_event_s { + int state; + pthread_cond_t cond; + int pollfd; +} zbar_event_t; + + +#else + +typedef int zbar_event_t[0]; + +#endif + + +extern int _zbar_event_init(zbar_event_t*); +extern void _zbar_event_destroy(zbar_event_t*); +extern void _zbar_event_trigger(zbar_event_t*); +extern int _zbar_event_wait(zbar_event_t*, zbar_mutex_t*, zbar_timer_t*); + +#endif diff --git a/zbar/mutex.h b/zbar/mutex.h new file mode 100644 index 0000000..ac4c0a9 --- /dev/null +++ b/zbar/mutex.h @@ -0,0 +1,160 @@ +/*------------------------------------------------------------------------ + * Copyright 2007-2009 (c) Jeff Brown + * + * 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 + *------------------------------------------------------------------------*/ +#ifndef _ZBAR_MUTEX_H_ +#define _ZBAR_MUTEX_H_ + +#include + +/* simple platform mutex abstraction + */ + +#if defined(_WIN32) + +# include + +# define DEBUG_LOCKS +# ifdef DEBUG_LOCKS + +typedef struct zbar_mutex_s { + int count; + CRITICAL_SECTION mutex; +} zbar_mutex_t; + +static inline int _zbar_mutex_init (zbar_mutex_t *lock) +{ + lock->count = 1; + InitializeCriticalSection(&lock->mutex); + return(0); +} + +static inline void _zbar_mutex_destroy (zbar_mutex_t *lock) +{ + DeleteCriticalSection(&lock->mutex); +} + +static inline int _zbar_mutex_lock (zbar_mutex_t *lock) +{ + EnterCriticalSection(&lock->mutex); + if(lock->count++ < 1) + assert(0); + return(0); +} + +static inline int _zbar_mutex_unlock (zbar_mutex_t *lock) +{ + if(lock->count-- <= 1) + assert(0); + LeaveCriticalSection(&lock->mutex); + return(0); +} + +# else + +typedef CRITICAL_SECTION zbar_mutex_t; + +static inline int _zbar_mutex_init (zbar_mutex_t *lock) +{ + InitializeCriticalSection(lock); + return(0); +} + +static inline void _zbar_mutex_destroy (zbar_mutex_t *lock) +{ + DeleteCriticalSection(lock); +} + +static inline int _zbar_mutex_lock (zbar_mutex_t *lock) +{ + EnterCriticalSection(lock); + return(0); +} + +static inline int _zbar_mutex_unlock (zbar_mutex_t *lock) +{ + LeaveCriticalSection(lock); + return(0); +} + +# endif + + +#elif defined(HAVE_LIBPTHREAD) + +# include + +typedef pthread_mutex_t zbar_mutex_t; + +static inline int _zbar_mutex_init (zbar_mutex_t *lock) +{ +# ifdef DEBUG_LOCKS + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); + int rc = pthread_mutex_init(lock, &attr); + pthread_mutexattr_destroy(&attr); + return(rc); +# else + return(pthread_mutex_init(lock, NULL)); +# endif +} + +static inline void _zbar_mutex_destroy (zbar_mutex_t *lock) +{ + pthread_mutex_destroy(lock); +} + +static inline int _zbar_mutex_lock (zbar_mutex_t *lock) +{ + int rc = pthread_mutex_lock(lock); +# ifdef DEBUG_LOCKS + assert(!rc); +# endif + /* FIXME save system code */ + /*rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_LOCKING, __func__, + "unable to lock processor");*/ + return(rc); +} + +static inline int _zbar_mutex_unlock (zbar_mutex_t *lock) +{ + int rc = pthread_mutex_unlock(lock); +# ifdef DEBUG_LOCKS + assert(!rc); +# endif + /* FIXME save system code */ + return(rc); +} + + +#else + +typedef int zbar_mutex_t[0]; + +#define _zbar_mutex_init(l) -1 +#define _zbar_mutex_destroy(l) +#define _zbar_mutex_lock(l) 0 +#define _zbar_mutex_unlock(l) 0 + +#endif + +#endif diff --git a/zbar/processor.c b/zbar/processor.c index 030e98f..0857d14 100644 --- a/zbar/processor.c +++ b/zbar/processor.c @@ -22,9 +22,33 @@ *------------------------------------------------------------------------*/ #include "processor.h" -#include +#include "window.h" -/* lock is already held */ +static inline int proc_enter (zbar_processor_t *proc) +{ + _zbar_mutex_lock(&proc->mutex); + return(_zbar_processor_lock(proc)); +} + +static inline int proc_leave (zbar_processor_t *proc) +{ + int rc = _zbar_processor_unlock(proc, 0); + _zbar_mutex_unlock(&proc->mutex); + return(rc); +} + +static inline int proc_open (zbar_processor_t *proc) +{ + /* arbitrary default */ + int width = 640, height = 480; + if(proc->video) { + width = zbar_video_get_width(proc->video); + height = zbar_video_get_height(proc->video); + } + return(_zbar_processor_open(proc, "zbar barcode reader", width, height)); +} + +/* API lock is already held */ int _zbar_process_image (zbar_processor_t *proc, zbar_image_t *img) { @@ -35,6 +59,11 @@ int _zbar_process_image (zbar_processor_t *proc, zbar_image_get_width(img), zbar_image_get_height(img), zbar_image_get_data(img)); + if(proc->dumping) { + zbar_image_write(proc->window->image, "zbar"); + proc->dumping = 0; + } + /* FIXME locking all other interfaces while processing is conservative * but easier for now and we don't expect this to take long... */ @@ -59,7 +88,9 @@ int _zbar_process_image (zbar_processor_t *proc, } if(nsyms) { + _zbar_mutex_lock(&proc->mutex); _zbar_processor_notify(proc, EVENT_OUTPUT); + _zbar_mutex_unlock(&proc->mutex); if(proc->handler) /* FIXME only call after filtering */ proc->handler(img, proc->userdata); @@ -84,6 +115,113 @@ int _zbar_process_image (zbar_processor_t *proc, return(0); } +int _zbar_processor_handle_input (zbar_processor_t *proc, + int input) +{ + + switch(input) { + case 'q': + input = -1; + case -1: + _zbar_processor_set_visible(proc, 0); + err_capture(proc, SEV_WARNING, ZBAR_ERR_CLOSED, __func__, + "user closed display window"); + break; + + case 'd': + /* FIXME localtime not threadsafe */ + /* FIXME need ms resolution */ + /*struct tm *t = localtime(time(NULL));*/ + proc->dumping = 1; + return(0); + } + + _zbar_mutex_lock(&proc->mutex); + proc->input = input; + _zbar_processor_notify(proc, EVENT_INPUT); + _zbar_mutex_unlock(&proc->mutex); + return(input); +} + +#ifdef ZTHREAD + +static ZTHREAD proc_video_thread (void *arg) +{ + zbar_processor_t *proc = arg; + zbar_thread_t *thread = &proc->video_thread; + + _zbar_mutex_lock(&proc->mutex); + _zbar_thread_init(thread); + zprintf(4, "spawned video thread\n"); + + while(thread->started) { + /* wait for video stream to be active */ + while(thread->started && !proc->streaming) + _zbar_event_wait(&thread->notify, &proc->mutex, NULL); + if(!thread->started) + break; + + /* blocking capture image from video */ + _zbar_mutex_unlock(&proc->mutex); + zbar_image_t *img = zbar_video_next_image(proc->video); + _zbar_mutex_lock(&proc->mutex); + + if(!img) + /* FIXME could abort streaming and keep running? */ + break; + + /* acquire API lock */ + _zbar_processor_lock(proc); + _zbar_mutex_unlock(&proc->mutex); + + if(thread->started && proc->streaming) + _zbar_process_image(proc, img); + + zbar_image_destroy(img); + + _zbar_mutex_lock(&proc->mutex); + /* release API lock */ + _zbar_processor_unlock(proc, 0); + } + + thread->running = 0; + _zbar_event_trigger(&thread->activity); + _zbar_mutex_unlock(&proc->mutex); + return(0); +} + +static ZTHREAD proc_input_thread (void *arg) +{ + zbar_processor_t *proc = arg; + zbar_thread_t *thread = &proc->input_thread; + if(proc->window && proc_open(proc)) + goto done; + + _zbar_mutex_lock(&proc->mutex); + thread->running = 1; + _zbar_event_trigger(&thread->activity); + zprintf(4, "spawned input thread\n"); + + int rc = 0; + while(thread->started && rc >= 0) { + _zbar_mutex_unlock(&proc->mutex); + rc = _zbar_processor_input_wait(proc, &thread->notify, -1); + _zbar_mutex_lock(&proc->mutex); + } + + _zbar_mutex_unlock(&proc->mutex); + _zbar_processor_close(proc); + _zbar_mutex_lock(&proc->mutex); + + done: + thread->running = 0; + _zbar_event_trigger(&thread->activity); + _zbar_mutex_unlock(&proc->mutex); + return(0); +} + +#endif + zbar_processor_t *zbar_processor_create (int threaded) { zbar_processor_t *proc = calloc(1, sizeof(zbar_processor_t)); @@ -97,15 +235,13 @@ zbar_processor_t *zbar_processor_create (int threaded) return(NULL); } - _zbar_processor_threads_init(proc, threaded); - + proc->threaded = !_zbar_mutex_init(&proc->mutex) && threaded; + _zbar_processor_init(proc); return(proc); } void zbar_processor_destroy (zbar_processor_t *proc) { - _zbar_processor_lock(proc); - zbar_processor_init(proc, NULL, 0); if(proc->scanner) { @@ -113,12 +249,21 @@ void zbar_processor_destroy (zbar_processor_t *proc) proc->scanner = NULL; } - _zbar_processor_unlock(proc); + _zbar_mutex_destroy(&proc->mutex); + _zbar_processor_cleanup(proc); - _zbar_processor_threads_cleanup(proc); + assert(!proc->wait_head); + assert(!proc->wait_tail); + assert(!proc->wait_next); - err_cleanup(&proc->err); + proc_waiter_t *w, *next; + for(w = proc->free_waiter; w; w = next) { + next = w->next; + _zbar_event_destroy(&w->notify); + free(w); + } + err_cleanup(&proc->err); free(proc); } @@ -126,12 +271,18 @@ int zbar_processor_init (zbar_processor_t *proc, const char *dev, int enable_display) { - if(_zbar_processor_lock(proc)) - return(-1); + if(proc->video) + zbar_processor_set_active(proc, 0); - _zbar_processor_threads_stop(proc); + if(proc->window && !proc->input_thread.started) + _zbar_processor_close(proc); - _zbar_processor_close(proc); + _zbar_mutex_lock(&proc->mutex); + _zbar_thread_stop(&proc->input_thread, &proc->mutex); + _zbar_thread_stop(&proc->video_thread, &proc->mutex); + + _zbar_processor_lock(proc); + _zbar_mutex_unlock(&proc->mutex); if(proc->window) { zbar_window_destroy(proc->window); @@ -140,12 +291,8 @@ int zbar_processor_init (zbar_processor_t *proc, int rc = 0; if(proc->video) { - if(dev) - zbar_video_open(proc->video, NULL); - else { - zbar_video_destroy(proc->video); - proc->video = NULL; - } + zbar_video_destroy(proc->video); + proc->video = NULL; } if(!dev && !enable_display) @@ -173,31 +320,42 @@ int zbar_processor_init (zbar_processor_t *proc, proc->req_width, proc->req_height); if(proc->req_intf) zbar_video_request_interface(proc->video, proc->req_intf); - if(proc->req_iomode && - zbar_video_request_iomode(proc->video, proc->req_iomode)) { + if((proc->req_iomode && + zbar_video_request_iomode(proc->video, proc->req_iomode)) || + zbar_video_open(proc->video, dev)) { rc = err_copy(proc, proc->video); goto done; } } - rc = _zbar_processor_threads_start(proc, dev); - if(rc) + /* spawn blocking video thread */ + int video_threaded = (proc->threaded && proc->video && + zbar_video_get_fd(proc->video) < 0); + if(video_threaded && + _zbar_thread_start(&proc->video_thread, proc_video_thread, proc, + &proc->mutex)) { + rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, + "spawning video thread"); goto done; + } - if(proc->window) { - /* arbitrary default */ - int width = 640, height = 480; - if(proc->video) { - width = zbar_video_get_width(proc->video); - height = zbar_video_get_height(proc->video); - } + /* spawn input monitor thread */ + int input_threaded = (proc->threaded && + (proc->window || + (proc->video && !video_threaded))); - if(_zbar_processor_open(proc, "zbar barcode reader", width, height)) { - rc = -1; - goto done; - } + if(input_threaded && + _zbar_thread_start(&proc->input_thread, proc_input_thread, proc, + &proc->mutex)) { + rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, + "spawning input thread"); + goto done; } + if(proc->window && !input_threaded && + (rc = proc_open(proc))) + goto done; + if(proc->video && proc->force_input) { if(zbar_video_init(proc->video, proc->force_input)) rc = err_copy(proc, proc->video); @@ -223,7 +381,8 @@ int zbar_processor_init (zbar_processor_t *proc, } done: - _zbar_processor_unlock(proc); + _zbar_mutex_lock(&proc->mutex); + proc_leave(proc); return(rc); } @@ -232,35 +391,31 @@ zbar_processor_set_data_handler (zbar_processor_t *proc, zbar_image_data_handler_t *handler, const void *userdata) { - if(_zbar_processor_lock(proc) < 0) - return(NULL); + zbar_image_data_handler_t *result = NULL; + proc_enter(proc); - zbar_image_data_handler_t *result = proc->handler; + result = proc->handler; proc->handler = handler; proc->userdata = userdata; - _zbar_processor_unlock(proc); + proc_leave(proc); return(result); } void zbar_processor_set_userdata (zbar_processor_t *proc, void *userdata) { - if(_zbar_processor_lock(proc) < 0) - return; - + _zbar_mutex_lock(&proc->mutex); proc->userdata = userdata; - - _zbar_processor_unlock(proc); + _zbar_mutex_unlock(&proc->mutex); } void *zbar_processor_get_userdata (const zbar_processor_t *proc) { - _zbar_processor_lock(proc); - + zbar_processor_t *p = (zbar_processor_t*)proc; + _zbar_mutex_lock(&p->mutex); void *userdata = (void*)proc->userdata; - - _zbar_processor_unlock(proc); + _zbar_mutex_unlock(&p->mutex); return(userdata); } @@ -269,10 +424,9 @@ int zbar_processor_set_config (zbar_processor_t *proc, zbar_config_t cfg, int val) { - if(_zbar_processor_lock(proc) < 0) - return(-1); + proc_enter(proc); int rc = zbar_image_scanner_set_config(proc->scanner, sym, cfg, val); - _zbar_processor_unlock(proc); + proc_leave(proc); return(rc); } @@ -280,37 +434,28 @@ int zbar_processor_request_size (zbar_processor_t *proc, unsigned width, unsigned height) { - if(_zbar_processor_lock(proc) < 0) - return(-1); - + proc_enter(proc); proc->req_width = width; proc->req_height = height; - - _zbar_processor_unlock(proc); + proc_leave(proc); return(0); } int zbar_processor_request_interface (zbar_processor_t *proc, int ver) { - if(_zbar_processor_lock(proc) < 0) - return(-1); - + proc_enter(proc); proc->req_intf = ver; - - _zbar_processor_unlock(proc); + proc_leave(proc); return(0); } int zbar_processor_request_iomode (zbar_processor_t *proc, int iomode) { - if(_zbar_processor_lock(proc) < 0) - return(-1); - + proc_enter(proc); proc->req_iomode = iomode; - - _zbar_processor_unlock(proc); + proc_leave(proc); return(0); } @@ -318,32 +463,26 @@ int zbar_processor_force_format (zbar_processor_t *proc, unsigned long input, unsigned long output) { - if(_zbar_processor_lock(proc) < 0) - return(-1); - + proc_enter(proc); proc->force_input = input; proc->force_output = output; - - _zbar_processor_unlock(proc); + proc_leave(proc); return(0); } int zbar_processor_is_visible (zbar_processor_t *proc) { - if(_zbar_processor_lock(proc) < 0) - return(-1); - + proc_enter(proc); int visible = proc->window && proc->visible; - - _zbar_processor_unlock(proc); + proc_leave(proc); return(visible); } int zbar_processor_set_visible (zbar_processor_t *proc, int visible) { - if(_zbar_processor_lock(proc) < 0) - return(-1); + proc_enter(proc); + _zbar_mutex_unlock(&proc->mutex); int rc = 0; if(proc->window) { @@ -353,24 +492,31 @@ int zbar_processor_set_visible (zbar_processor_t *proc, zbar_video_get_height(proc->video)); if(!rc) rc = _zbar_processor_set_visible(proc, visible); + + if(!rc) + proc->visible = (visible != 0); } else if(visible) rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "processor display window not initialized"); - _zbar_processor_unlock(proc); + _zbar_mutex_lock(&proc->mutex); + proc_leave(proc); return(rc); } int zbar_processor_user_wait (zbar_processor_t *proc, int timeout) { - if(_zbar_processor_lock(proc) < 0) - return(-1); + proc_enter(proc); + _zbar_mutex_unlock(&proc->mutex); int rc = -1; - if(proc->visible || proc->active || timeout > 0) - rc = _zbar_processor_wait(proc, EVENT_INPUT, timeout); + if(proc->visible || proc->streaming || timeout >= 0) { + zbar_timer_t timer; + rc = _zbar_processor_wait(proc, EVENT_INPUT, + _zbar_timer_init(&timer, timeout)); + } if(rc > 0) rc = proc->input; @@ -378,47 +524,53 @@ int zbar_processor_user_wait (zbar_processor_t *proc, rc = err_capture(proc, SEV_WARNING, ZBAR_ERR_CLOSED, __func__, "display window not available for input"); - _zbar_processor_unlock(proc); + _zbar_mutex_lock(&proc->mutex); + proc_leave(proc); return(rc); } int zbar_processor_set_active (zbar_processor_t *proc, int active) { - if(_zbar_processor_lock(proc) < 0) - return(-1); + proc_enter(proc); + int rc; if(!proc->video) { - _zbar_processor_unlock(proc); - return(err_capture(proc, SEV_ERROR, ZBAR_ERR_INVALID, __func__, - "video input not initialized")); + rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_INVALID, __func__, + "video input not initialized"); + goto done; } + _zbar_mutex_unlock(&proc->mutex); zbar_image_scanner_enable_cache(proc->scanner, active); - int rc = zbar_video_enable(proc->video, active); + + rc = zbar_video_enable(proc->video, active); if(!rc) { - _zbar_processor_enable(proc, active); - proc->active = active; - proc->events &= ~EVENT_INPUT; + proc->streaming = active; + rc = _zbar_processor_enable(proc); } else err_copy(proc, proc->video); - if(!proc->active && proc->window && - (zbar_window_draw(proc->window, NULL) || - _zbar_processor_invalidate(proc)) && !rc) - rc = err_copy(proc, proc->window); + if(!proc->streaming && proc->window) { + if(zbar_window_draw(proc->window, NULL) && !rc) + rc = err_copy(proc, proc->window); + _zbar_processor_invalidate(proc); + } - _zbar_processor_notify(proc, 0); - _zbar_processor_unlock(proc); + _zbar_mutex_lock(&proc->mutex); + _zbar_event_trigger(&proc->video_thread.notify); + + done: + proc_leave(proc); return(rc); } int zbar_process_one (zbar_processor_t *proc, int timeout) { - if(_zbar_processor_lock(proc) < 0) - return(-1); + proc_enter(proc); + _zbar_mutex_unlock(&proc->mutex); int rc = 0; if(!proc->video) { @@ -431,21 +583,24 @@ int zbar_process_one (zbar_processor_t *proc, if(rc) goto done; - rc = _zbar_processor_wait(proc, EVENT_OUTPUT, timeout); + zbar_timer_t timer; + rc = _zbar_processor_wait(proc, EVENT_OUTPUT, + _zbar_timer_init(&timer, timeout)); if(zbar_processor_set_active(proc, 0)) rc = -1; done: - _zbar_processor_unlock(proc); + _zbar_mutex_lock(&proc->mutex); + proc_leave(proc); return(rc); } int zbar_process_image (zbar_processor_t *proc, zbar_image_t *img) { - if(_zbar_processor_lock(proc) < 0) - return(-1); + proc_enter(proc); + _zbar_mutex_unlock(&proc->mutex); int rc = 0; if(img && proc->window) @@ -455,10 +610,11 @@ int zbar_process_image (zbar_processor_t *proc, if(!rc) { zbar_image_scanner_enable_cache(proc->scanner, 0); rc = _zbar_process_image(proc, img); - if(proc->active) + if(proc->streaming) zbar_image_scanner_enable_cache(proc->scanner, 1); } - _zbar_processor_unlock(proc); + _zbar_mutex_lock(&proc->mutex); + proc_leave(proc); return(rc); } diff --git a/zbar/processor.h b/zbar/processor.h index fbf91c7..9a9f659 100644 --- a/zbar/processor.h +++ b/zbar/processor.h @@ -33,10 +33,30 @@ #include #include "error.h" +#include "thread.h" +#include "event.h" + +/* max time to wait for input before looking for the next frame. + * only used in unthreaded mode with blocking (non-pollable) video. + * NB subject to precision of whatever timer is in use + */ +#define MAX_INPUT_BLOCK 15/*ms*/ /* platform specific state wrapper */ typedef struct processor_state_s processor_state_t; +/* specific notification tracking */ +typedef struct proc_waiter_s { + struct proc_waiter_s *next; + zbar_event_t notify; + zbar_thread_id_t requester; + unsigned events; +} proc_waiter_t; + +/* high-level API events */ +#define EVENT_INPUT 0x01 /* user input */ +#define EVENT_OUTPUT 0x02 /* decoded output data available */ + struct zbar_processor_s { errinfo_t err; /* error reporting */ const void *userdata; /* application data */ @@ -57,35 +77,46 @@ struct zbar_processor_s { /* state flags */ int threaded; int visible; /* output window mapped to display */ - int active; /* async processor thread running */ - - unsigned events; /* synchronization events */ -#define EVENT_INPUT 0x01 /* user input */ -#define EVENT_OUTPUT 0x02 /* decoded output data available */ + int streaming; /* video enabled */ + int dumping; /* debug image dump */ void *display; /* X display connection */ unsigned long xwin; /* toplevel window */ + zbar_thread_t input_thread; /* video input handler */ + zbar_thread_t video_thread; /* window event handler */ + + zbar_mutex_t mutex; /* shared data mutex */ + + /* API serialization lock */ + int lock_level; + zbar_thread_id_t lock_owner; + proc_waiter_t *wait_head, *wait_tail, *wait_next; + proc_waiter_t *free_waiter; + processor_state_t *state; }; -extern int _zbar_processor_lock(const zbar_processor_t*); -extern int _zbar_processor_unlock(const zbar_processor_t*); -extern int _zbar_processor_notify(zbar_processor_t*, unsigned); -extern int _zbar_processor_wait(zbar_processor_t*, unsigned, int); +/* processor lock API */ +extern int _zbar_processor_lock(zbar_processor_t*); +extern int _zbar_processor_unlock(zbar_processor_t*, int); +extern void _zbar_processor_notify(zbar_processor_t*, unsigned); +extern int _zbar_processor_wait(zbar_processor_t*, unsigned, zbar_timer_t*); -extern int _zbar_processor_threads_init(zbar_processor_t*, int); -extern int _zbar_processor_threads_cleanup(zbar_processor_t*); -extern int _zbar_processor_threads_start(zbar_processor_t*, - const char*); -extern int _zbar_processor_threads_stop(zbar_processor_t*); +/* platform API */ +extern int _zbar_processor_init(zbar_processor_t*); +extern int _zbar_processor_cleanup(zbar_processor_t*); +extern int _zbar_processor_input_wait(zbar_processor_t*, zbar_event_t*, int); +extern int _zbar_processor_enable(zbar_processor_t*); +extern int _zbar_process_image(zbar_processor_t*, zbar_image_t*); +extern int _zbar_processor_handle_input(zbar_processor_t*, int); + +/* windowing platform API */ extern int _zbar_processor_open(zbar_processor_t*, char*, unsigned, unsigned); extern int _zbar_processor_close(zbar_processor_t*); extern int _zbar_processor_set_visible(zbar_processor_t*, int); extern int _zbar_processor_set_size(zbar_processor_t*, unsigned, unsigned); extern int _zbar_processor_invalidate(zbar_processor_t*); -extern int _zbar_processor_enable(zbar_processor_t*, int); -extern int _zbar_process_image(zbar_processor_t*, zbar_image_t*); #endif diff --git a/zbar/processor/lock.c b/zbar/processor/lock.c new file mode 100644 index 0000000..6722b07 --- /dev/null +++ b/zbar/processor/lock.c @@ -0,0 +1,217 @@ +/*------------------------------------------------------------------------ + * Copyright 2007-2009 (c) Jeff Brown + * + * 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 "processor.h" +#include + +/* the processor api lock is a recursive mutex with added capabilities + * to completely drop all lock levels before blocking and atomically + * unblock a waiting set. the lock is implemented using a variation + * of the "specific notification pattern" [cargill], which makes it + * easy to provide these features across platforms with consistent, + * predictable semantics. probably overkill, but additional overhead + * associated with this mechanism should fall in the noise, as locks + * are only exchanged O(frame/image) + * + * [cargill] + * http://www.profcon.com/profcon/cargill/jgf/9809/SpecificNotification.html + */ + +static inline proc_waiter_t *proc_waiter_queue (zbar_processor_t *proc) +{ + proc_waiter_t *waiter = proc->free_waiter; + if(waiter) + proc->free_waiter = waiter->next; + else { + waiter = calloc(1, sizeof(proc_waiter_t)); + _zbar_event_init(&waiter->notify); + } + + waiter->next = NULL; + waiter->requester = _zbar_thread_self(); + + if(proc->wait_head) + proc->wait_tail->next = waiter; + else + proc->wait_head = waiter; + proc->wait_tail = waiter; + return(waiter); +} + +static inline proc_waiter_t *proc_waiter_dequeue (zbar_processor_t *proc) +{ + proc_waiter_t *waiter = proc->wait_next; + if(!waiter) + waiter = proc->wait_head; + while(waiter && waiter->events) + waiter = waiter->next; + + if(waiter) { + proc->wait_next = waiter->next; + if(proc->wait_head == waiter) { + proc->wait_head = waiter->next; + if(!waiter->next) + proc->wait_tail = NULL; + } + waiter->next = NULL; + + proc->lock_level = 1; + proc->lock_owner = waiter->requester; + } + return(waiter); +} + +static inline void proc_waiter_release (zbar_processor_t *proc, + proc_waiter_t *waiter) +{ + if(waiter) { + waiter->next = proc->free_waiter; + proc->free_waiter = waiter; + } +} + +int _zbar_processor_lock (zbar_processor_t *proc) +{ + if(!proc->lock_level) { + proc->lock_owner = _zbar_thread_self(); + proc->lock_level = 1; + return(0); + } + + if(_zbar_thread_is_self(proc->lock_owner)) { + proc->lock_level++; + return(0); + } + + proc_waiter_t *waiter = proc_waiter_queue(proc); + _zbar_event_wait(&waiter->notify, &proc->mutex, NULL); + + assert(proc->lock_level == 1); + assert(_zbar_thread_is_self(proc->lock_owner)); + + proc_waiter_release(proc, waiter); + return(0); +} + +int _zbar_processor_unlock (zbar_processor_t *proc, + int all) +{ + assert(proc->lock_level > 0); + assert(_zbar_thread_is_self(proc->lock_owner)); + + if(all) + proc->lock_level = 0; + else + proc->lock_level--; + + if(!proc->lock_level) { + proc_waiter_t *waiter = proc_waiter_dequeue(proc); + if(waiter) + _zbar_event_trigger(&waiter->notify); + } + return(0); +} + +void _zbar_processor_notify (zbar_processor_t *proc, + unsigned events) +{ + proc->wait_next = NULL; + proc_waiter_t *waiter; + for(waiter = proc->wait_head; waiter; waiter = waiter->next) + waiter->events &= ~events; + + if(!proc->lock_level) { + waiter = proc_waiter_dequeue(proc); + if(waiter) + _zbar_event_trigger(&waiter->notify); + } +} + +static inline int proc_wait_unthreaded (zbar_processor_t *proc, + proc_waiter_t *waiter, + zbar_timer_t *timeout) +{ + int blocking = proc->streaming && zbar_video_get_fd(proc->video) < 0; + _zbar_mutex_unlock(&proc->mutex); + + int rc = 1; + while(rc > 0 && waiter->events) { + /* FIXME lax w/the locking (though shouldn't matter...) */ + if(blocking) { + zbar_image_t *img = zbar_video_next_image(proc->video); + if(!img) { + rc = -1; + break; + } + + /* FIXME reacquire API lock! (refactor w/video thread?) */ + _zbar_mutex_lock(&proc->mutex); + _zbar_process_image(proc, img); + zbar_image_destroy(img); + _zbar_mutex_unlock(&proc->mutex); + } + int reltime = (timeout) ? _zbar_timer_check(timeout) : -1; + if(blocking && (reltime < 0 || reltime > MAX_INPUT_BLOCK)) + reltime = MAX_INPUT_BLOCK; + rc = _zbar_processor_input_wait(proc, NULL, reltime); + } + _zbar_mutex_lock(&proc->mutex); + return(rc); +} + +int _zbar_processor_wait (zbar_processor_t *proc, + unsigned events, + zbar_timer_t *timeout) +{ + _zbar_mutex_lock(&proc->mutex); + int save_level = proc->lock_level; + proc_waiter_t *waiter = proc_waiter_queue(proc); + waiter->events = events; + + _zbar_processor_unlock(proc, 1); + int rc; + if(proc->threaded) + rc = _zbar_event_wait(&waiter->notify, &proc->mutex, timeout); + else + rc = proc_wait_unthreaded(proc, waiter, timeout); + + if(rc <= 0 || !proc->threaded) { + /* reacquire api lock */ + waiter->events = 0; + if(!proc->lock_level) { + proc_waiter_t *w = proc_waiter_dequeue(proc); + assert(w == waiter); + } + else + _zbar_event_wait(&waiter->notify, &proc->mutex, NULL); + } + + assert(proc->lock_level == 1); + assert(_zbar_thread_is_self(proc->lock_owner)); + + proc->lock_level = save_level; + proc_waiter_release(proc, waiter); + _zbar_mutex_unlock(&proc->mutex); + return(rc); +} + diff --git a/zbar/processor/posix.c b/zbar/processor/posix.c index 39c07af..011e52e 100644 --- a/zbar/processor/posix.c +++ b/zbar/processor/posix.c @@ -24,129 +24,173 @@ #include "processor.h" #include "posix.h" #include -#include -#include -#include /* gettimeofday */ #include #include -#ifdef HAVE_LIBPTHREAD - -static inline void proc_mutex_unlock (void *arg) +int _zbar_event_init (zbar_event_t *event) { - pthread_mutex_unlock((pthread_mutex_t*)arg); + event->state = 0; + event->pollfd = -1; + pthread_cond_init(&event->cond, NULL); + return(0); } -/* acquire window access semaphore */ -inline int _zbar_processor_lock (const zbar_processor_t *proc) +void _zbar_event_destroy (zbar_event_t *event) { - if(!proc->threaded) - return(0); - - processor_state_t *state = proc->state; - pthread_t self = pthread_self(); + event->state = -1; + event->pollfd = -1; + pthread_cond_destroy(&event->cond); +} - int rc = pthread_mutex_lock(&state->mutex); - pthread_cleanup_push(proc_mutex_unlock, &state->mutex); +/* lock must be held */ +void _zbar_event_trigger (zbar_event_t *event) +{ + event->state = 1; + pthread_cond_broadcast(&event->cond); + if(event->pollfd >= 0) { + unsigned i = 0; /* unused */ + write(event->pollfd, &i, sizeof(unsigned)); + event->pollfd = -1; + } +} - if(!rc && state->lock_level && pthread_equal(state->lock_owner, self)) - state->lock_level++; - else { - while(!rc && state->lock_level) - rc = pthread_cond_wait(&state->cond, &state->mutex); - if(!rc) { - state->lock_level++; - state->lock_owner = self; +/* lock must be held */ +int _zbar_event_wait (zbar_event_t *event, + zbar_mutex_t *lock, + zbar_timer_t *timeout) +{ + int rc = 0; + while(!rc && !event->state) { + if(!timeout) + rc = pthread_cond_wait(&event->cond, lock); + else { + struct timespec *timer; +# if _POSIX_TIMERS > 0 + timer = timeout; +# else + struct timespec tmp; + tmp.tv_sec = timeout->tv_sec; + tmp.tv_nsec = timeout->tv_usec * 1000; + timer = *tmp; +# endif + rc = pthread_cond_timedwait(&event->cond, lock, timer); } } - pthread_cleanup_pop(1); + /* consume/reset event */ + event->state = 0; - if(rc) - err_capture(proc, SEV_ERROR, ZBAR_ERR_LOCKING, __func__, - "unable to lock processor"); - return(rc); + if(!rc) + return(1); /* got event */ + if(rc == ETIMEDOUT) + return(0); /* timed out */ + return(-1); /* error (FIXME save info) */ } -/* release window access semaphore */ -inline int _zbar_processor_unlock (const zbar_processor_t *proc) +int _zbar_thread_start (zbar_thread_t *thr, + zbar_thread_proc_t *proc, + void *arg, + zbar_mutex_t *lock) { - if(!proc->threaded) - return(0); - processor_state_t *state = proc->state; - - pthread_mutex_lock(&state->mutex); - - assert(state->lock_level > 0); - assert(pthread_equal(state->lock_owner, pthread_self())); - if(!--state->lock_level) - pthread_cond_signal(&state->cond); - - pthread_mutex_unlock(&state->mutex); + if(thr->started || thr->running) + return(-1/*FIXME*/); + thr->started = 1; + _zbar_event_init(&thr->notify); + _zbar_event_init(&thr->activity); + + int rc = 0; + _zbar_mutex_lock(lock); + if(pthread_create(&thr->tid, NULL, proc, arg) || + _zbar_event_wait(&thr->activity, lock, NULL) < 0 || + !thr->running) { + thr->started = 0; + _zbar_event_destroy(&thr->notify); + _zbar_event_destroy(&thr->activity); + /*rc = err_capture_num(proc, SEV_ERROR, ZBAR_ERR_SYSTEM, + __func__, "spawning thread", rc);*/ + rc = -1/*FIXME*/; + } + _zbar_mutex_unlock(lock); + return(rc); +} +int _zbar_thread_stop (zbar_thread_t *thr, + zbar_mutex_t *lock) +{ + if(thr->started) { + thr->started = 0; + _zbar_event_trigger(&thr->notify); + while(thr->running) + /* FIXME time out and abandon? */ + _zbar_event_wait(&thr->activity, lock, NULL); + pthread_join(thr->tid, NULL); + _zbar_event_destroy(&thr->notify); + _zbar_event_destroy(&thr->activity); + } return(0); } -inline int _zbar_processor_notify (zbar_processor_t *proc, - unsigned event) +/* used by poll interface. lock is already held */ +static int proc_video_handler (zbar_processor_t *proc, + int i) { - proc->events |= event; -#ifdef HAVE_LIBPTHREAD - processor_state_t *state = proc->state; - pthread_cond_broadcast(&state->event); -#endif + _zbar_mutex_lock(&proc->mutex); + _zbar_processor_lock(proc); + _zbar_mutex_unlock(&proc->mutex); + + zbar_image_t *img = NULL; + if(proc->streaming) { + /* not expected to block */ + img = zbar_video_next_image(proc->video); + if(img) + _zbar_process_image(proc, img); + } + + _zbar_mutex_lock(&proc->mutex); + _zbar_processor_unlock(proc, 0); + _zbar_mutex_unlock(&proc->mutex); + if(img) + zbar_image_destroy(img); return(0); } -static inline void proc_destroy_thread (pthread_t thread, - unsigned *started) +static inline void proc_cache_polling (processor_state_t *state) { - if(*started) { - pthread_cancel(thread); - pthread_join(thread, NULL); - *started = 0; - } + /* make a thread-local copy of polling data */ + int n = state->thr_polling.num = state->polling.num; + alloc_polls(&state->thr_polling); + memcpy(state->thr_polling.fds, state->polling.fds, + n * sizeof(struct pollfd)); + memcpy(state->thr_polling.handlers, state->polling.handlers, + n * sizeof(poll_handler_t*)); } -#else -# define _zbar_processor_lock(...) (0) -# define _zbar_processor_unlock(...) (0) -# define proc_destroy_thread(...) -#endif +static int proc_kick_handler (zbar_processor_t *proc, + int i) +{ + processor_state_t *state = proc->state; + zprintf(5, "kicking %d fds\n", state->polling.num); + unsigned junk[2]; + read(state->kick_fds[0], junk, 2 * sizeof(unsigned)); -/* used by poll interface. lock is already held */ -static int proc_video_handler (zbar_processor_t *proc, - int i) -{ - if(!proc->active) - return(0); - /* not expected to block */ - zbar_image_t *img = zbar_video_next_image(proc->video); - if(!img) - return(-1); - int rc = _zbar_process_image(proc, img); - zbar_image_destroy(img); - return(rc); + assert(proc->threaded); + _zbar_mutex_lock(&proc->mutex); + proc_cache_polling(proc->state); + _zbar_mutex_unlock(&proc->mutex); + return(0); } static inline int proc_poll_inputs (zbar_processor_t *proc, - poll_desc_t *p, int timeout) { + processor_state_t *state = proc->state; + poll_desc_t *p = &state->thr_polling; assert(p->num); int rc = poll(p->fds, p->num, timeout); if(rc <= 0) /* FIXME detect and handle fatal errors (somehow) */ return(rc); - processor_state_t *state = proc->state; - _zbar_processor_lock(proc); - if(p->fds[0].revents && p->fds[0].fd == state->kick_fds[0]) { - unsigned junk[2]; - read(state->kick_fds[0], junk, 2 * sizeof(unsigned)); - _zbar_processor_unlock(proc); - return(1); - } int i; for(i = 0; i < p->num; i++) if(p->fds[i].revents) { @@ -155,313 +199,72 @@ static inline int proc_poll_inputs (zbar_processor_t *proc, p->fds[i].revents = 0; /* debug */ rc--; } - _zbar_processor_unlock(proc); - assert(!rc); - return(0); -} - -static inline int proc_calc_abstime (struct timespec *abstime, - int timeout) -{ - if(timeout >= 0) { -#if _POSIX_TIMERS > 0 - clock_gettime(CLOCK_REALTIME, abstime); -#else - struct timeval ustime; - gettimeofday(&ustime, NULL); - abstime->tv_nsec = ustime.tv_usec * 1000; - abstime->tv_sec = ustime.tv_sec; -#endif - abstime->tv_nsec += (timeout % 1000) * 1000000; - abstime->tv_sec += (timeout / 1000) + (abstime->tv_nsec / 1000000000); - abstime->tv_nsec %= 1000000000; - } - return(0); -} - -#ifdef HAVE_LIBPTHREAD -static inline int proc_wait_threaded (zbar_processor_t *proc, - unsigned event, - int timeout, - struct timespec *abstime) -{ - processor_state_t *state = proc->state; - pthread_t self = pthread_self(); - - int rc = pthread_mutex_lock(&state->mutex); - - assert(state->lock_level > 0); - assert(pthread_equal(state->lock_owner, self)); - proc->events &= ~event; - - int save_level = state->lock_level; - state->lock_level = 0; - - pthread_cond_signal(&state->cond); - - pthread_cleanup_push(proc_mutex_unlock, &state->mutex); - while(!rc && !(proc->events & event)) - if(timeout < 0) - rc = pthread_cond_wait(&state->event, &state->mutex); - else - rc = pthread_cond_timedwait(&state->event, &state->mutex, abstime); - if(rc == ETIMEDOUT) - rc = 0; - - while(!rc && state->lock_level) - rc = pthread_cond_wait(&state->cond, &state->mutex); - if(!rc) { - state->lock_level = save_level; - state->lock_owner = self; - } - - pthread_cleanup_pop(1); - - if(rc) - return(-1); /* error (FIXME save info) */ - if(proc->events & event) - return(1); /* got event */ - return(0); /* timed out */ -} -#endif - -static inline int proc_wait_unthreaded (zbar_processor_t *proc, - unsigned event, - int timeout, - struct timespec *abstime) -{ - processor_state_t *state = proc->state; - int blocking = proc->active && zbar_video_get_fd(proc->video) < 0; - proc->events &= ~event; - /* unthreaded, poll here for window input */ - while(!(proc->events & event)) { - if(blocking) { - zbar_image_t *img = zbar_video_next_image(proc->video); - if(!img) - return(-1); - _zbar_process_image(proc, img); - zbar_image_destroy(img); - } - int reltime = timeout; - if(reltime >= 0) { - struct timespec now; -#if _POSIX_TIMERS > 0 - clock_gettime(CLOCK_REALTIME, &now); -#else - struct timeval ustime; - gettimeofday(&ustime, NULL); - now.tv_nsec = ustime.tv_usec * 1000; - now.tv_sec = ustime.tv_sec; -#endif - reltime = ((abstime->tv_sec - now.tv_sec) * 1000 + - (abstime->tv_nsec - now.tv_nsec) / 1000000); - if(reltime <= 0) - return(0); - } - if(blocking && (reltime < 0 || reltime > 10)) - reltime = 10; - if(state->polling.num) - proc_poll_inputs(proc, (poll_desc_t*)&state->polling, reltime); - else if(!blocking) { - _zbar_processor_unlock(proc); - struct timespec sleepns, remns; - sleepns.tv_sec = timeout / 1000; - sleepns.tv_nsec = (timeout % 1000) * 1000000; - while(nanosleep(&sleepns, &remns) && errno == EINTR) - sleepns = remns; - (void)_zbar_processor_lock(proc); - return(0); - } - } return(1); } -inline int _zbar_processor_wait (zbar_processor_t *proc, - unsigned event, - int timeout) -{ - struct timespec abstime; - proc_calc_abstime(&abstime, timeout); -#ifdef HAVE_LIBPTHREAD - if(proc->threaded) - return(proc_wait_threaded(proc, event, timeout, &abstime)); - else -#endif - return(proc_wait_unthreaded(proc, event, timeout, &abstime)); -} - -#ifdef HAVE_LIBPTHREAD -/* make a thread-local copy of polling data */ -static inline void proc_cache_polling (zbar_processor_t *proc) +static inline int proc_sleep (int timeout) { - (void)_zbar_processor_lock(proc); - processor_state_t *state = proc->state; - int n = state->polling.num; - zprintf(5, "%d fds\n", n); - state->thr_polling.num = n; - alloc_polls(&state->thr_polling); - memcpy(state->thr_polling.fds, state->polling.fds, - n * sizeof(struct pollfd)); - memcpy(state->thr_polling.handlers, state->polling.handlers, - n * sizeof(poll_handler_t*)); - _zbar_processor_unlock(proc); -} - -static inline void proc_block_sigs () -{ - sigset_t sigs; - sigfillset(&sigs); - pthread_sigmask(SIG_BLOCK, &sigs, NULL); + assert(timeout > 0); + struct timespec sleepns, remns; + sleepns.tv_sec = timeout / 1000; + sleepns.tv_nsec = (timeout % 1000) * 1000000; + while(nanosleep(&sleepns, &remns) && errno == EINTR) + sleepns = remns; + return(1); } -/* input handler thread to poll available inputs */ -static void *proc_input_thread (void *arg) +int _zbar_processor_input_wait (zbar_processor_t *proc, + zbar_event_t *event, + int timeout) { - zbar_processor_t *proc = arg; processor_state_t *state = proc->state; - proc_block_sigs(); - - /* wait for registered inputs and process using associated handler */ - while(1) { - proc_cache_polling(proc); - - int rc = 0; - while(!rc) { - if(state->polling.num) - rc = proc_poll_inputs(proc, &state->thr_polling, -1); - else { - struct timespec t; - t.tv_sec = 4; - t.tv_nsec = 0; - rc = nanosleep(&t, NULL); - } + if(state->thr_polling.num) { + if(event) { + _zbar_mutex_lock(&proc->mutex); + event->pollfd = state->kick_fds[1]; + _zbar_mutex_unlock(&proc->mutex); } + return(proc_poll_inputs(proc, timeout)); } + else if(timeout) + return(proc_sleep(timeout)); + return(-1); } -/* separate thread to handle non-pollable video (v4l1) */ -static void *proc_video_thread (void *arg) -{ - zbar_processor_t *proc = arg; - processor_state_t *state = proc->state; - pthread_t self = pthread_self(); - proc_block_sigs(); - - (void)_zbar_processor_lock(proc); - while(1) { - /* wait for active to be set */ - assert(state->lock_level == 1); - assert(pthread_equal(state->lock_owner, self)); - pthread_mutex_lock(&state->mutex); - state->lock_level = 0; - pthread_cond_signal(&state->cond); - pthread_cleanup_push(proc_mutex_unlock, &state->mutex); - while(!proc->active) - pthread_cond_wait(&state->event, &state->mutex); - pthread_cleanup_pop(1); - - /* unlocked blocking image input */ - zbar_image_t *img = zbar_video_next_image(proc->video); - if(!img) - return(NULL); - (void)_zbar_processor_lock(proc); - if(proc->active) - _zbar_process_image(proc, img); - zbar_image_destroy(img); - } -} -#endif - -int _zbar_processor_threads_init (zbar_processor_t *proc, - int threaded) +int _zbar_processor_init (zbar_processor_t *proc) { processor_state_t *state = proc->state = calloc(1, sizeof(processor_state_t)); state->kick_fds[0] = state->kick_fds[1] = -1; - if(threaded) { -#ifdef HAVE_LIBPTHREAD + if(proc->threaded) { /* FIXME check errors */ - pthread_mutex_init(&state->mutex, NULL); - pthread_cond_init(&state->cond, NULL); - pthread_cond_init(&state->event, NULL); pipe(state->kick_fds); - add_poll(state, state->kick_fds[0], NULL); - proc->threaded = 1; -#else - /* FIXME record warning */ -#endif - } - return(0); -} - -int _zbar_processor_threads_start (zbar_processor_t *proc, - const char *dev) -{ - if(proc->video && - zbar_video_open(proc->video, dev)) - return(err_copy(proc, proc->video)); - - if(!proc->threaded) - return(0); - -#ifdef HAVE_LIBPTHREAD - processor_state_t *state = proc->state; - if(proc->video && zbar_video_get_fd(proc->video) < 0) { - /* spawn blocking video thread */ - int rc; - if((rc = pthread_create(&state->video_thread, NULL, - proc_video_thread, proc))) - return(err_capture_num(proc, SEV_ERROR, ZBAR_ERR_SYSTEM, - __func__, "spawning video thread", rc)); - - state->video_started = 1; - zprintf(4, "spawned video thread\n"); - } - - if(proc->window || - (proc->video && !state->video_started)) { - /* spawn input monitor thread */ - int rc; - if((rc = pthread_create(&state->input_thread, NULL, - proc_input_thread, proc))) - return(err_capture_num(proc, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, - "spawning input thread", rc)); - state->input_started = 1; - zprintf(4, "spawned input thread\n"); + add_poll(proc, state->kick_fds[0], proc_kick_handler); + proc_cache_polling(proc->state); } -#endif - return(0); } -int _zbar_processor_threads_stop (zbar_processor_t *proc) +int _zbar_processor_cleanup (zbar_processor_t *proc) { -#ifdef HAVE_LIBPTHREAD processor_state_t *state = proc->state; - proc_destroy_thread(state->video_thread, &state->video_started); - proc_destroy_thread(state->input_thread, &state->input_started); -#endif - return(0); -} - -int _zbar_processor_threads_cleanup (zbar_processor_t *proc) -{ - processor_state_t *state = proc->state; -#ifdef HAVE_LIBPTHREAD if(proc->threaded) { - pthread_cond_destroy(&state->event); - pthread_cond_destroy(&state->cond); - pthread_mutex_destroy(&state->mutex); + close(state->kick_fds[0]); + close(state->kick_fds[1]); + state->kick_fds[0] = state->kick_fds[1] = -1; } -#endif if(state->polling.fds) { free(state->polling.fds); state->polling.fds = NULL; + if(!proc->threaded) + state->thr_polling.fds = NULL; } if(state->polling.handlers) { free(state->polling.handlers); state->polling.handlers = NULL; + if(!proc->threaded) + state->thr_polling.handlers = NULL; } if(state->thr_polling.fds) { free(state->thr_polling.fds); @@ -476,17 +279,15 @@ int _zbar_processor_threads_cleanup (zbar_processor_t *proc) return(0); } -int _zbar_processor_enable (zbar_processor_t *proc, - int active) +int _zbar_processor_enable (zbar_processor_t *proc) { int vid_fd = zbar_video_get_fd(proc->video); - processor_state_t *state = proc->state; if(vid_fd >= 0) { - if(active) - add_poll(state, vid_fd, proc_video_handler); + if(proc->streaming) + add_poll(proc, vid_fd, proc_video_handler); else - remove_poll(state, vid_fd); + remove_poll(proc, vid_fd); + /* FIXME failure recovery? */ } - /* FIXME failure recovery? */ return(0); } diff --git a/zbar/processor/posix.h b/zbar/processor/posix.h index d90a991..6a1320b 100644 --- a/zbar/processor/posix.h +++ b/zbar/processor/posix.h @@ -29,11 +29,7 @@ # include #endif -#ifdef HAVE_X -# include -#endif - -#ifdef HAVE_PTHREAD_H +#ifdef HAVE_LIBPTHREAD # include #endif @@ -50,24 +46,16 @@ typedef struct poll_desc_s { struct processor_state_s { #ifdef HAVE_POLL_H - volatile poll_desc_t polling; /* polling registration */ + poll_desc_t polling; /* polling registration */ poll_desc_t thr_polling; /* thread copy */ - int kick_fds[2]; /* poll kicker */ #endif + int kick_fds[2]; /* poll kicker */ -#ifdef HAVE_LIBPTHREAD int lock_level; /* API serialization lock */ pthread_t lock_owner; /* lock owner */ pthread_mutex_t mutex; /* lock mutex */ pthread_cond_t cond; /* lock notification condition */ pthread_cond_t event; - - pthread_t video_thread; /* video input handler */ - pthread_t input_thread; /* window event handler */ - - unsigned video_started; /* thread active flags */ - unsigned input_started; -#endif }; @@ -80,56 +68,79 @@ static inline int alloc_polls (volatile poll_desc_t *p) return(0); } -static inline int add_poll (processor_state_t *state, +static inline int add_poll (zbar_processor_t *proc, int fd, poll_handler_t *handler) { - volatile poll_desc_t *polling = &state->polling; + processor_state_t *state = proc->state; + + _zbar_mutex_lock(&proc->mutex); + + poll_desc_t *polling = &state->polling; unsigned i = polling->num++; zprintf(5, "[%d] fd=%d handler=%p\n", i, fd, handler); - if(alloc_polls(polling)) - return(-1); - memset(&polling->fds[i], 0, sizeof(struct pollfd)); - polling->fds[i].fd = fd; - polling->fds[i].events = POLLIN; - polling->handlers[i] = handler; -#ifdef HAVE_LIBPTHREAD - if(state->input_started) { + if(!alloc_polls(polling)) { + memset(&polling->fds[i], 0, sizeof(struct pollfd)); + polling->fds[i].fd = fd; + polling->fds[i].events = POLLIN; + polling->handlers[i] = handler; + } + else + i = -1; + + _zbar_mutex_unlock(&proc->mutex); + + if(proc->input_thread.started) { assert(state->kick_fds[1] >= 0); write(state->kick_fds[1], &i /* unused */, sizeof(unsigned)); /* FIXME should sync */ } -#endif + else if(!proc->threaded) { + state->thr_polling.num = polling->num; + state->thr_polling.fds = polling->fds; + state->thr_polling.handlers = polling->handlers; + } return(i); } -static inline int remove_poll (processor_state_t *state, +static inline int remove_poll (zbar_processor_t *proc, int fd) { - volatile poll_desc_t *polling = &state->polling; + processor_state_t *state = proc->state; + + _zbar_mutex_lock(&proc->mutex); + + poll_desc_t *polling = &state->polling; int i; for(i = polling->num - 1; i >= 0; i--) if(polling->fds[i].fd == fd) break; zprintf(5, "[%d] fd=%d n=%d\n", i, fd, polling->num); - if(i < 0) - return(1); - if(i + 1 < polling->num) { - int n = polling->num - i - 1; - memmove(&polling->fds[i], &polling->fds[i + 1], - n * sizeof(struct pollfd)); - memmove(&polling->handlers[i], &polling->handlers[i + 1], - n * sizeof(poll_handler_t)); + + if(i >= 0) { + if(i + 1 < polling->num) { + int n = polling->num - i - 1; + memmove(&polling->fds[i], &polling->fds[i + 1], + n * sizeof(struct pollfd)); + memmove(&polling->handlers[i], &polling->handlers[i + 1], + n * sizeof(poll_handler_t)); + } + polling->num--; + i = alloc_polls(polling); } - polling->num--; - int rc = alloc_polls(polling); -#ifdef HAVE_LIBPTHREAD - if(state->input_started) { + + _zbar_mutex_unlock(&proc->mutex); + + if(proc->input_thread.started) { write(state->kick_fds[1], &i /* unused */, sizeof(unsigned)); /* FIXME should sync */ } -#endif - return(rc); + else if(!proc->threaded) { + state->thr_polling.num = polling->num; + state->thr_polling.fds = polling->fds; + state->thr_polling.handlers = polling->handlers; + } + return(i); } #endif diff --git a/zbar/processor/win.c b/zbar/processor/win.c index a7f3128..46844d3 100644 --- a/zbar/processor/win.c +++ b/zbar/processor/win.c @@ -22,7 +22,7 @@ *------------------------------------------------------------------------*/ #include "processor.h" -#include "win.h" +#include #include #define WIN_STYLE (WS_CAPTION | \ @@ -32,140 +32,36 @@ WS_MAXIMIZEBOX) #define EXT_STYLE (WS_EX_APPWINDOW | WS_EX_OVERLAPPEDWINDOW) -static inline int proc_lock (processor_state_t *state, - DWORD self) -{ - if(!state->lock_level) { - state->lock_owner = self; - state->lock_level = 1; - return(0); - } - - if(state->lock_owner == self) { - state->lock_level++; - return(0); - } - - wait_entry_t *entry = proc_entry_alloc(state, self); - proc_entry_queue(&state->lock_queue, entry); - - LeaveCriticalSection(&state->mutex); - int rc = WaitForSingleObject(entry->notify, INFINITE); - EnterCriticalSection(&state->mutex); - assert(state->lock_level == 1); - assert(state->lock_owner == self); - - proc_entry_free(state, entry); - return(rc); -} - -static inline int proc_unlock (processor_state_t *state, - DWORD self, - int all) +int _zbar_event_init (zbar_event_t *event) { - assert(state->lock_level > 0); - assert(state->lock_owner == self); - - if(all) - state->lock_level = 0; - else - state->lock_level--; - - if(!state->lock_level) { - wait_entry_t *entry = proc_entry_dequeue(&state->lock_queue); - if(entry) { - state->lock_level = 1; - state->lock_owner = entry->requester; - SetEvent(entry->notify); - } - } - return(0); + *event = CreateEvent(NULL, 0, 0, NULL); + return((*event) ? 0 : -1); } -static inline void proc_notify (zbar_processor_t *proc) +void _zbar_event_destroy (zbar_event_t *event) { - processor_state_t *state = proc->state; - wait_entry_t **q = &state->wait_queue.head; - while(*q) { - wait_entry_t *entry = *q; - if(entry->requester & proc->events) { - *q = entry->next; - SetEvent(entry->notify); - } - q = &entry->next; - entry->next = NULL; + if(*event) { + CloseHandle(*event); + *event = NULL; } } -inline int _zbar_processor_lock (const zbar_processor_t *proc) -{ - processor_state_t *state = proc->state; - - EnterCriticalSection(&state->mutex); - int rc = proc_lock(state, GetCurrentThreadId()); - LeaveCriticalSection(&state->mutex); - - if(rc) - /* FIXME save system code */ - rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_LOCKING, __func__, - "unable to lock processor"); - return(rc); -} - -inline int _zbar_processor_unlock (const zbar_processor_t *proc) +void _zbar_event_trigger (zbar_event_t *event) { - processor_state_t *state = proc->state; - - EnterCriticalSection(&state->mutex); - proc_unlock(state, GetCurrentThreadId(), 0); - LeaveCriticalSection(&state->mutex); - - return(0); + SetEvent(*event); } -inline int _zbar_processor_notify (zbar_processor_t *proc, - unsigned event) +/* lock must be held */ +int _zbar_event_wait (zbar_event_t *event, + zbar_mutex_t *lock, + zbar_timer_t *timeout) { - processor_state_t *state = proc->state; - - EnterCriticalSection(&state->mutex); - proc->events |= event; - - SetEvent(state->video_thread.activity); - proc_notify(proc); - - LeaveCriticalSection(&state->mutex); - return(0); -} - -inline int _zbar_processor_wait (zbar_processor_t *proc, - unsigned event, - int timeout) -{ - processor_state_t *state = proc->state; - DWORD self = GetCurrentThreadId(); - - proc->events &= ~event; - - EnterCriticalSection(&state->mutex); - - int save_level = state->lock_level; - wait_entry_t *entry = proc_entry_alloc(state, event); - proc_entry_queue(&state->wait_queue, entry); - proc_unlock(state, self, 1); - - LeaveCriticalSection(&state->mutex); - int rc = WaitForSingleObject(entry->notify, timeout); - EnterCriticalSection(&state->mutex); - - proc_entry_free(state, entry); - proc_lock(state, self); - state->lock_level = save_level; - if(!rc) - assert(proc->events & event); - - LeaveCriticalSection(&state->mutex); + if(lock) + _zbar_mutex_unlock(lock); + int rc = WaitForSingleObject(*event, _zbar_timer_check(timeout)); + if(lock) + _zbar_mutex_lock(lock); if(!rc) return(1); /* got event */ @@ -174,215 +70,64 @@ inline int _zbar_processor_wait (zbar_processor_t *proc, return(-1); /* error (FIXME save info) */ } -static inline int proc_thread_start (zbar_processor_t *proc, - thread_state_t *tstate, - LPTHREAD_START_ROUTINE thread) +int _zbar_thread_start (zbar_thread_t *thr, + zbar_thread_proc_t *proc, + void *arg, + zbar_mutex_t *lock) { - assert(!tstate->running); - tstate->running = 1; - HANDLE hthr = CreateThread(NULL, 0, thread, proc, 0, NULL); - if(!hthr) { - tstate->running = 0; + if(thr->started || thr->running) return(-1/*FIXME*/); - } + thr->started = 1; + _zbar_event_init(&thr->notify); + _zbar_event_init(&thr->activity); + + HANDLE hthr = CreateThread(NULL, 0, proc, arg, 0, NULL); + int rc = (!hthr || + _zbar_event_wait(&thr->activity, NULL, NULL) < 0 || + !thr->running); CloseHandle(hthr); - - HANDLE status[2] = { tstate->started, tstate->stopped }; - int rc = WaitForMultipleObjects(2, status, 0, INFINITE); if(rc) { - tstate->running = 0; + thr->started = 0; + _zbar_event_destroy(&thr->notify); + _zbar_event_destroy(&thr->activity); return(-1/*FIXME*/); } - return(0); } -static inline int proc_thread_stop (processor_state_t *state, - thread_state_t *tstate) +int _zbar_thread_stop (zbar_thread_t *thr, + zbar_mutex_t *lock) { - if(tstate->running) { - tstate->running = 0; - SetEvent(tstate->activity); - LeaveCriticalSection(&state->mutex); - WaitForSingleObject(tstate->stopped, INFINITE); - EnterCriticalSection(&state->mutex); + if(thr->started) { + thr->started = 0; + _zbar_event_trigger(&thr->notify); + while(thr->running) + /* FIXME time out and abandon? */ + _zbar_event_wait(&thr->activity, lock, NULL); + _zbar_event_destroy(&thr->notify); + _zbar_event_destroy(&thr->activity); } return(0); } -int _zbar_processor_threads_init (zbar_processor_t *proc, - int threaded) -{ - if(!threaded) - err_capture(proc, SEV_WARNING, ZBAR_ERR_UNSUPPORTED, - __func__, "windows processor does not support unthreaded"); - - processor_state_t *state = proc->state = - calloc(1, sizeof(processor_state_t)); - - InitializeCriticalSection(&state->mutex); - state->video_thread.activity = CreateEvent(NULL, 0, 0, NULL); - state->video_thread.started = CreateEvent(NULL, 0, 0, NULL); - state->video_thread.stopped = CreateEvent(NULL, 0, 0, NULL); - - state->input_thread.activity = CreateEvent(NULL, 0, 0, NULL); - state->input_thread.started = CreateEvent(NULL, 0, 0, NULL); - state->input_thread.stopped = CreateEvent(NULL, 0, 0, NULL); - return(0); -} - -int _zbar_processor_threads_cleanup (zbar_processor_t *proc) -{ - processor_state_t *state = proc->state; - - CloseHandle(state->video_thread.activity); - CloseHandle(state->video_thread.started); - CloseHandle(state->video_thread.stopped); - - CloseHandle(state->input_thread.activity); - CloseHandle(state->input_thread.started); - CloseHandle(state->input_thread.stopped); - - DeleteCriticalSection(&state->mutex); - - if(state->video_dev) { - free(state->video_dev); - state->video_dev = NULL; - } - - free(state); - proc->state = NULL; - return(0); -} - - -static DWORD WINAPI proc_video_thread (void *arg) -{ - zbar_processor_t *proc = arg; - processor_state_t *state = proc->state; - thread_state_t *tstate = &state->video_thread; - DWORD self = GetCurrentThreadId(); - int rc = 0; - - /* windows video must be opened from driving thread */ - if(zbar_video_open(proc->video, state->video_dev)) { - err_copy(proc, proc->video); - SetEvent(tstate->stopped); - return(0); - } - - EnterCriticalSection(&state->mutex); - zprintf(4, "spawned video thread\n"); - SetEvent(tstate->started); - - wait_entry_t *entry = proc_entry_alloc(state, self); - HANDLE activity[2] = { tstate->activity, entry->notify }; - - while(tstate->running) { - while(!proc->active && tstate->running) { - LeaveCriticalSection(&state->mutex); - rc = WaitForSingleObject(tstate->activity, INFINITE); - EnterCriticalSection(&state->mutex); - } - if(!tstate->running) - break; - - /* unlocked blocking image input */ - LeaveCriticalSection(&state->mutex); - zbar_image_t *img = zbar_video_next_image(proc->video); - EnterCriticalSection(&state->mutex); - - if(!img) - break; - - if(!state->lock_level) { - state->lock_owner = self; - state->lock_level = 1; - } - else { - proc_entry_queue(&state->lock_queue, entry); - rc = 0; - while(!rc && tstate->running) { - LeaveCriticalSection(&state->mutex); - rc = WaitForMultipleObjects(2, activity, 0, INFINITE); - EnterCriticalSection(&state->mutex); - } - if(rc || !tstate->running) - break; - } - - assert(state->lock_level == 1); - assert(state->lock_owner == self); - LeaveCriticalSection(&state->mutex); - - if(proc->active) - _zbar_process_image(proc, img); - - zbar_image_destroy(img); - - EnterCriticalSection(&state->mutex); - assert(state->lock_level == 1); - - wait_entry_t *next = proc_entry_dequeue(&state->lock_queue); - if(next) { - state->lock_owner = next->requester; - SetEvent(next->notify); - } - else - state->lock_level = 0; - } - - proc_entry_free(state, entry); - - LeaveCriticalSection(&state->mutex); - - SetEvent(tstate->stopped); - return(0); -} - -int _zbar_processor_threads_start (zbar_processor_t *proc, - const char *dev) -{ - processor_state_t *state = proc->state; - if(state->video_dev) - free(state->video_dev); - state->video_dev = strdup(dev); - return(proc_thread_start(proc, &state->video_thread, proc_video_thread)); -} - -int _zbar_processor_threads_stop (zbar_processor_t *proc) -{ - processor_state_t *state = proc->state; - EnterCriticalSection(&state->mutex); - int rc = proc_thread_stop(proc->state, &proc->state->video_thread); - LeaveCriticalSection(&state->mutex); - return(rc); -} - - -static LRESULT CALLBACK proc_handle_event (HWND hwnd, - UINT message, - WPARAM wparam, - LPARAM lparam) +static LRESULT CALLBACK win_handle_event (HWND hwnd, + UINT message, + WPARAM wparam, + LPARAM lparam) { zbar_processor_t *proc = (zbar_processor_t*)GetWindowLongPtr(hwnd, GWL_USERDATA); - processor_state_t *state = NULL; /* initialized during window creation */ - if(proc) - state = proc->state; - else if(message == WM_NCCREATE) { + if(message == WM_NCCREATE) { proc = ((LPCREATESTRUCT)lparam)->lpCreateParams; assert(proc); - state = proc->state; - assert(state); SetWindowLongPtr(hwnd, GWL_USERDATA, (LONG_PTR)proc); - proc->display = state->hwnd = hwnd; + proc->display = hwnd; zbar_window_attach(proc->window, proc->display, proc->xwin); } - else + else if(!proc) return(DefWindowProc(hwnd, message, wparam, lparam)); switch(message) { @@ -412,34 +157,34 @@ static LRESULT CALLBACK proc_handle_event (HWND hwnd, } case WM_CHAR: { - state->input = wparam; + _zbar_processor_handle_input(proc, wparam); return(0); } case WM_LBUTTONDOWN: { - state->input = 1; + _zbar_processor_handle_input(proc, 1); return(0); } case WM_MBUTTONDOWN: { - state->input = 2; + _zbar_processor_handle_input(proc, 2); return(0); } case WM_RBUTTONDOWN: { - state->input = 3; + _zbar_processor_handle_input(proc, 3); return(0); } case WM_CLOSE: { zprintf(3, "WM_CLOSE\n"); - _zbar_processor_set_visible(proc, 0); + _zbar_processor_handle_input(proc, -1); return(1); } case WM_DESTROY: { zprintf(3, "WM_DESTROY\n"); - state->hwnd = proc->display = NULL; + proc->display = NULL; zbar_window_attach(proc->window, NULL, 0); return(0); } @@ -447,12 +192,12 @@ static LRESULT CALLBACK proc_handle_event (HWND hwnd, return(DefWindowProc(hwnd, message, wparam, lparam)); } -static inline int proc_handle_events (zbar_processor_t *proc) +static inline int win_handle_events (zbar_processor_t *proc) { - processor_state_t *state = proc->state; + int rc = 0; while(1) { MSG msg; - int rc = PeekMessage(&msg, state->hwnd, 0, 0, PM_NOYIELD | PM_REMOVE); + rc = PeekMessage(&msg, proc->display, 0, 0, PM_NOYIELD | PM_REMOVE); if(!rc) return(0); if(rc < 0) @@ -461,19 +206,45 @@ static inline int proc_handle_events (zbar_processor_t *proc) TranslateMessage(&msg); DispatchMessage(&msg); + } +} - if(state->input) { - EnterCriticalSection(&state->mutex); - proc->input = state->input; - proc->events |= EVENT_INPUT; - proc_notify(proc); - LeaveCriticalSection(&state->mutex); - state->input = 0; - } +int _zbar_processor_init (zbar_processor_t *proc) +{ + return(0); +} + +int _zbar_processor_cleanup (zbar_processor_t *proc) +{ + return(0); +} + +int _zbar_processor_input_wait (zbar_processor_t *proc, + zbar_event_t *event, + int timeout) +{ + int n = (event) ? 1 : 0; + int rc = MsgWaitForMultipleObjects(n, event, 0, timeout, QS_ALLINPUT); + + if(rc == n) { + if(win_handle_events(proc) < 0) + return(-1); + return(1); } + if(!rc) + return(1); + if(rc == WAIT_TIMEOUT) + return(0); + return(-1); +} + +int _zbar_processor_enable (zbar_processor_t *proc) +{ + return(0); } -static inline ATOM proc_register_class (HINSTANCE hmod) + +static inline ATOM win_register_class (HINSTANCE hmod) { BYTE and_mask[1] = { 0xff }; BYTE xor_mask[1] = { 0x00 }; @@ -481,7 +252,7 @@ static inline ATOM proc_register_class (HINSTANCE hmod) WNDCLASSEX wc = { sizeof(WNDCLASSEX), 0, }; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hInstance = hmod; - wc.lpfnWndProc = proc_handle_event; + wc.lpfnWndProc = win_handle_event; wc.lpszClassName = "_ZBar Class"; wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wc.hCursor = CreateCursor(hmod, 0, 0, 1, 1, and_mask, xor_mask); @@ -489,11 +260,11 @@ static inline ATOM proc_register_class (HINSTANCE hmod) return(RegisterClassEx(&wc)); } -static inline int proc_open (zbar_processor_t *proc, - unsigned width, - unsigned height) +int _zbar_processor_open (zbar_processor_t *proc, + char *title, + unsigned width, + unsigned height) { - processor_state_t *state = proc->state; HMODULE hmod = NULL; if(!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, @@ -501,103 +272,40 @@ static inline int proc_open (zbar_processor_t *proc, return(err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, "failed to obtain module handle")); - ATOM wca = proc_register_class(hmod); + ATOM wca = win_register_class(hmod); if(!wca) return(err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, "failed to register window class")); RECT r = { 0, 0, width, height }; AdjustWindowRectEx(&r, WIN_STYLE, 0, EXT_STYLE); - state->hwnd = CreateWindowEx(EXT_STYLE, (LPCTSTR)(long)wca, - "ZBar", WIN_STYLE, - CW_USEDEFAULT, CW_USEDEFAULT, - r.right - r.left, r.bottom - r.top, - NULL, NULL, hmod, proc); + proc->display = CreateWindowEx(EXT_STYLE, (LPCTSTR)(long)wca, + "ZBar", WIN_STYLE, + CW_USEDEFAULT, CW_USEDEFAULT, + r.right - r.left, r.bottom - r.top, + NULL, NULL, hmod, proc); - if(!state->hwnd) + if(!proc->display) return(err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, "failed to open window")); return(0); } -static DWORD WINAPI proc_input_thread (void *arg) +int _zbar_processor_close (zbar_processor_t *proc) { - zbar_processor_t *proc = arg; - processor_state_t *state = proc->state; - thread_state_t *tstate = &state->input_thread; - state->input = 0; - - int rc = proc_open(proc, state->width, state->height); - if(rc) { - SetEvent(tstate->stopped); - return(-1); + if(proc->display) { + DestroyWindow(proc->display); + proc->display = NULL; } - - EnterCriticalSection(&state->mutex); - zprintf(4, "spawned input thread\n"); - SetEvent(tstate->started); - - while(!rc && tstate->running) { - LeaveCriticalSection(&state->mutex); - - rc = MsgWaitForMultipleObjects(1, &tstate->activity, 0, - INFINITE, QS_ALLINPUT); - if(rc == 1) - rc = proc_handle_events(proc); - - EnterCriticalSection(&state->mutex); - } - LeaveCriticalSection(&state->mutex); - - if(state->hwnd) { - DestroyWindow(state->hwnd); - state->hwnd = proc->display = NULL; - } - - SetEvent(tstate->stopped); return(0); } - -int _zbar_processor_open (zbar_processor_t *proc, - char *title, - unsigned width, - unsigned height) -{ - processor_state_t *state = proc->state; - state->width = width; - state->height = height; - return(proc_thread_start(proc, &state->input_thread, - proc_input_thread)); -} - -int _zbar_processor_close (zbar_processor_t *proc) -{ - processor_state_t *state = proc->state; - EnterCriticalSection(&state->mutex); - int rc = proc_thread_stop(proc->state, &proc->state->input_thread); - LeaveCriticalSection(&state->mutex); - return(rc); -} - int _zbar_processor_set_visible (zbar_processor_t *proc, int visible) { - processor_state_t *state = proc->state; - ShowWindow(state->hwnd, (visible) ? SW_SHOWNORMAL : SW_HIDE); + ShowWindow(proc->display, (visible) ? SW_SHOWNORMAL : SW_HIDE); if(visible) - InvalidateRect(state->hwnd, NULL, 0); - else { - EnterCriticalSection(&state->mutex); - if(!(proc->events & EVENT_INPUT)) { - proc->input = err_capture(proc, SEV_WARNING, ZBAR_ERR_CLOSED, - __func__, "user closed display window"); - proc->events |= EVENT_INPUT; - } - proc_notify(proc); - LeaveCriticalSection(&state->mutex); - } - proc->visible = (visible != 0); + InvalidateRect(proc->display, NULL, 0); /* no error conditions */ return(0); } @@ -607,12 +315,9 @@ int _zbar_processor_set_size (zbar_processor_t *proc, unsigned height) { RECT r = { 0, 0, width, height }; - processor_state_t *state = proc->state; - int rc = AdjustWindowRectEx(&r, GetWindowLong(state->hwnd, GWL_STYLE), - 0, GetWindowLong(state->hwnd, GWL_EXSTYLE)); - zprintf(5, "%dx%d %ld,%ld-%ld,%ld (%d)\n", width, height, - r.left, r.top, r.right, r.bottom, rc); - if(!SetWindowPos(state->hwnd, NULL, + AdjustWindowRectEx(&r, GetWindowLong(proc->display, GWL_STYLE), + 0, GetWindowLong(proc->display, GWL_EXSTYLE)); + if(!SetWindowPos(proc->display, NULL, 0, 0, r.right - r.left, r.bottom - r.top, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOREPOSITION)) @@ -623,15 +328,8 @@ int _zbar_processor_set_size (zbar_processor_t *proc, int _zbar_processor_invalidate (zbar_processor_t *proc) { - processor_state_t *state = proc->state; - if(!InvalidateRect(state->hwnd, NULL, 0)) + if(!InvalidateRect(proc->display, NULL, 0)) return(-1/*FIXME*/); return(0); } - -int _zbar_processor_enable (zbar_processor_t *proc, - int active) -{ - return(0); -} diff --git a/zbar/processor/win.h b/zbar/processor/win.h deleted file mode 100644 index 29c8bde..0000000 --- a/zbar/processor/win.h +++ /dev/null @@ -1,108 +0,0 @@ -/*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown - * - * 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 - *------------------------------------------------------------------------*/ -#ifndef _PROCESSOR_WIN_H_ -#define _PROCESSOR_WIN_H_ - -#include - -/* specific notification events */ -typedef struct wait_entry_s { - struct wait_entry_s *next; - HANDLE notify; - DWORD requester; -} wait_entry_t; - -typedef struct wait_queue_s { - wait_entry_t *head, *tail; -} wait_queue_t; - -typedef struct thread_state_s { - int running; - HANDLE activity, started, stopped; -} thread_state_t; - -struct processor_state_s { - char *video_dev; /* device name */ - HWND hwnd; /* window handle */ - int input; - unsigned width, height; - - CRITICAL_SECTION mutex; /* shared data mutex */ - - int lock_level; /* API serialization lock */ - DWORD lock_owner; - wait_queue_t lock_queue; - wait_queue_t wait_queue; - wait_entry_t *free_entry; - - thread_state_t video_thread; - thread_state_t input_thread; -}; - -static inline wait_entry_t *proc_entry_alloc (processor_state_t *state, - DWORD self) -{ - wait_entry_t *entry = state->free_entry; - if(entry) - state->free_entry = entry->next; - else { - entry = malloc(sizeof(wait_entry_t)); - entry->notify = CreateEvent(NULL, 0, 0, NULL); - } - entry->next = NULL; - entry->requester = self; - return(entry); -} - -static inline void proc_entry_free (processor_state_t *state, - wait_entry_t *entry) -{ - if(entry) { - entry->next = state->free_entry; - state->free_entry = entry; - } -} - -static inline void proc_entry_queue (wait_queue_t *queue, - wait_entry_t *entry) -{ - if(queue->head) - queue->tail->next = entry; - else - queue->head = entry; - queue->tail = entry; -} - -static inline wait_entry_t *proc_entry_dequeue (wait_queue_t *queue) -{ - wait_entry_t *entry = queue->head; - if(entry) { - queue->head = entry->next; - if(!entry->next) - queue->tail = NULL; - entry->next = NULL; - } - return(entry); -} - -#endif diff --git a/zbar/processor/x.c b/zbar/processor/x.c index cdd9026..ab61156 100644 --- a/zbar/processor/x.c +++ b/zbar/processor/x.c @@ -24,9 +24,12 @@ #include "window.h" #include "processor.h" #include "posix.h" + +#include +#include #include -static int x_handle_event (zbar_processor_t *proc) +static inline int x_handle_event (zbar_processor_t *proc) { XEvent ev; XNextEvent(proc->display, &ev); @@ -35,26 +38,15 @@ static int x_handle_event (zbar_processor_t *proc) case Expose: { /* FIXME ignore when running(?) */ XExposeEvent *exp = (XExposeEvent*)&ev; - XRectangle r; - Region exposed = XCreateRegion(); while(1) { assert(ev.type == Expose); - r.x = exp->x; - r.y = exp->y; - r.width = exp->width; - r.height = exp->height; - XUnionRectWithRegion(&r, exposed, exposed); - + _zbar_window_expose(proc->window, exp->x, exp->y, + exp->width, exp->height); if(!exp->count) break; XNextEvent(proc->display, &ev); } - - proc->window->exposed = exposed; zbar_window_redraw(proc->window); - proc->window->exposed = 0; - - XDestroyRegion(exposed); break; } @@ -73,28 +65,31 @@ static int x_handle_event (zbar_processor_t *proc) (ev.xclient.data.l[0] == XInternAtom(proc->display, "WM_DELETE_WINDOW", 0))) { zprintf(3, "WM_DELETE_WINDOW\n"); - _zbar_processor_set_visible(proc, 0); - return(err_capture(proc, SEV_WARNING, ZBAR_ERR_CLOSED, __func__, - "user closed display window")); + return(_zbar_processor_handle_input(proc, -1)); } case KeyPress: { KeySym key = XLookupKeysym(&ev.xkey, 0); if((key & 0xff00) == 0xff00) key &= 0x00ff; + zprintf(16, "KeyPress(%04lx)\n", key); /* FIXME this doesn't really work... */ - return(key & 0xffff); + return(_zbar_processor_handle_input(proc, key & 0xffff)); } - case ButtonPress: + case ButtonPress: { + zprintf(16, "ButtonPress(%d)\n", ev.xbutton.button); + int idx = 1; switch(ev.xbutton.button) { - case Button2: return(2); - case Button3: return(3); - case Button4: return(4); - case Button5: return(5); + case Button2: idx = 2; break; + case Button3: idx = 3; break; + case Button4: idx = 4; break; + case Button5: idx = 5; break; } - return(1); + return(_zbar_processor_handle_input(proc, idx)); + } case DestroyNotify: + zprintf(16, "DestroyNotify\n"); zbar_window_attach(proc->window, NULL, 0); proc->xwin = 0; return(0); @@ -105,47 +100,27 @@ static int x_handle_event (zbar_processor_t *proc) return(0); } -int _zbar_processor_handle_events (zbar_processor_t *proc, - int block) +static int x_handle_events (zbar_processor_t *proc) { int rc = 0; - while(!rc && (block || XPending(proc->display))) { - proc->input = x_handle_event(proc); - rc = proc->input; - } - - switch(rc) { - case 'q': - _zbar_processor_set_visible(proc, 0); - rc = err_capture(proc, SEV_WARNING, ZBAR_ERR_CLOSED, __func__, - "user closed display window"); - break; - - case 'd': { - /* FIXME localtime not threadsafe */ - /* FIXME need ms resolution */ - /*struct tm *t = localtime(time(NULL));*/ - zbar_image_write(proc->window->image, "zbar"); - break; - } - } - - if(rc) - _zbar_processor_notify(proc, EVENT_INPUT); + while(!rc && XPending(proc->display)) + rc = x_handle_event(proc); return(rc); } static int x_connection_handler (zbar_processor_t *proc, int i) { - return(_zbar_processor_handle_events(proc, 0)); + x_handle_events(proc); + return(0); } static int x_internal_handler (zbar_processor_t *proc, int i) { XProcessInternalConnection(proc->display, proc->state->polling.fds[i].fd); - return(_zbar_processor_handle_events(proc, 0)); + x_handle_events(proc); + return(0); } static void x_internal_watcher (Display *display, @@ -156,9 +131,9 @@ static void x_internal_watcher (Display *display, { zbar_processor_t *proc = (void*)client_arg; if(opening) - add_poll(proc->state, fd, x_internal_handler); + add_poll(proc, fd, x_internal_handler); else - remove_poll(proc->state, fd); + remove_poll(proc, fd); } int _zbar_processor_open (zbar_processor_t *proc, @@ -172,8 +147,7 @@ int _zbar_processor_open (zbar_processor_t *proc, "unable to open X display", XDisplayName(NULL))); - add_poll(proc->state, ConnectionNumber(proc->display), - x_connection_handler); + add_poll(proc, ConnectionNumber(proc->display), x_connection_handler); XAddConnectionWatch(proc->display, x_internal_watcher, (void*)proc); int screen = DefaultScreen(proc->display); @@ -220,7 +194,7 @@ int _zbar_processor_close (zbar_processor_t *proc) XDestroyWindow(proc->display, proc->xwin); proc->xwin = 0; } - remove_poll(proc->state, ConnectionNumber(proc->display)); + remove_poll(proc, ConnectionNumber(proc->display)); XCloseDisplay(proc->display); proc->display = NULL; } @@ -256,6 +230,5 @@ int _zbar_processor_set_visible (zbar_processor_t *proc, else XUnmapWindow(proc->display, proc->xwin); XFlush(proc->display); - proc->visible = visible != 0; return(0); } diff --git a/zbar/thread.h b/zbar/thread.h new file mode 100644 index 0000000..776e1a2 --- /dev/null +++ b/zbar/thread.h @@ -0,0 +1,123 @@ +/*------------------------------------------------------------------------ + * Copyright 2007-2009 (c) Jeff Brown + * + * 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 + *------------------------------------------------------------------------*/ +#ifndef _ZBAR_THREAD_H_ +#define _ZBAR_THREAD_H_ + +/* simple platform thread abstraction + */ + +#include +#include "event.h" + +#if defined(_WIN32) + +# include +# define HAVE_THREADS +# define ZTHREAD DWORD WINAPI + +typedef ZTHREAD (zbar_thread_proc_t)(void*); + +typedef DWORD zbar_thread_id_t; + +#elif defined(HAVE_LIBPTHREAD) + +# include +# include +# define HAVE_THREADS +# define ZTHREAD void* + +typedef ZTHREAD (zbar_thread_proc_t)(void*); + +typedef pthread_t zbar_thread_id_t; + +#else + +# undef HAVE_THREADS +# undef ZTHREAD + +typedef void zbar_thread_proc_t; +typedef int zbar_thread_id_t[0]; + +#endif + + +typedef struct zbar_thread_s { + zbar_thread_id_t tid; + int started, running; + zbar_event_t notify, activity; +} zbar_thread_t; + + +#if defined(_WIN32) + +static inline void _zbar_thread_init (zbar_thread_t *thr) +{ + thr->running = 1; + _zbar_event_trigger(&thr->activity); +} + +static inline zbar_thread_id_t _zbar_thread_self () +{ + return(GetCurrentThreadId()); +} + +static inline int _zbar_thread_is_self (zbar_thread_id_t tid) +{ + return(tid == GetCurrentThreadId()); +} + + +#elif defined(HAVE_LIBPTHREAD) + +static inline void _zbar_thread_init (zbar_thread_t *thr) +{ + sigset_t sigs; + sigfillset(&sigs); + pthread_sigmask(SIG_BLOCK, &sigs, NULL); + thr->running = 1; + _zbar_event_trigger(&thr->activity); +} + +static inline zbar_thread_id_t _zbar_thread_self () +{ + return(pthread_self()); +} + +static inline int _zbar_thread_is_self (zbar_thread_id_t tid) +{ + return(pthread_equal(tid, pthread_self())); +} + + +#else + +# define _zbar_thread_start(...) -1 +# define _zbar_thread_is_self(...) 1 + +#endif + +extern int _zbar_thread_start(zbar_thread_t*, zbar_thread_proc_t*, + void*, zbar_mutex_t*); +extern int _zbar_thread_stop(zbar_thread_t*, zbar_mutex_t*); + +#endif diff --git a/zbar/timer.h b/zbar/timer.h new file mode 100644 index 0000000..b7492ff --- /dev/null +++ b/zbar/timer.h @@ -0,0 +1,120 @@ +/*------------------------------------------------------------------------ + * Copyright 2007-2009 (c) Jeff Brown + * + * 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 + *------------------------------------------------------------------------*/ +#ifndef _ZBAR_TIMER_H_ +#define _ZBAR_TIMER_H_ + +#include +#include /* gettimeofday */ + +/* platform timer abstraction + * + * zbar_timer_t stores the absolute expiration of a delay from + * when the timer was initialized. + * + * _zbar_timer_init() initialized timer with specified ms delay. + * returns timer or NULL if timeout < 0 (no/infinite timeout) + * _zbar_timer_check() returns ms remaining until expiration. + * will be <= 0 if timer has expired + */ + +#if _POSIX_TIMERS > 0 + +typedef struct timespec zbar_timer_t; + +static inline zbar_timer_t *_zbar_timer_init (zbar_timer_t *timer, + int delay) +{ + if(delay < 0) + return(NULL); + + clock_gettime(CLOCK_REALTIME, timer); + timer->tv_nsec += (delay % 1000) * 1000000; + timer->tv_sec += (delay / 1000) + (timer->tv_nsec / 1000000000); + timer->tv_nsec %= 1000000000; + return(timer); +} + +static inline int _zbar_timer_check (zbar_timer_t *timer) +{ + struct timespec now; + clock_gettime(CLOCK_REALTIME, &now); + int delay = ((timer->tv_sec - now.tv_sec) * 1000 + + (timer->tv_nsec - now.tv_nsec) / 1000000); + return((delay >= 0) ? delay : 0); +} + + +#elif defined(_WIN32) + +# include + +typedef DWORD zbar_timer_t; + +static inline zbar_timer_t *_zbar_timer_init (zbar_timer_t *timer, + int delay) +{ + if(delay < 0) + return(NULL); + + *timer = timeGetTime() + delay; + return(timer); +} + +static inline int _zbar_timer_check (zbar_timer_t *timer) +{ + if(!timer) + return(INFINITE); + + int delay = *timer - timeGetTime(); + return((delay >= 0) ? delay : 0); +} + + +#else + +typedef struct timeval zbar_timer_t; + +static inline zbar_timer_t *_zbar_timer_init (zbar_timer_t *timer, + int delay) +{ + if(delay < 0) + return(NULL); + + gettimeofday(timer, NULL); + timer->tv_usec += (delay % 1000) * 1000; + timer->tv_sec += (delay / 1000) + (timer->tv_usec / 1000000); + timer->tv_usec %= 1000000; + return(timer); +} + +static inline int _zbar_timer_check (zbar_timer_t *timer) +{ + struct timeval now; + gettimeofday(&now, NULL); + return((timer->tv_sec - now.tv_sec) * 1000 + + (timer->tv_usec - now.tv_usec) / 1000); +} + +#endif + +#endif diff --git a/zbar/video.c b/zbar/video.c index 413290b..1669795 100644 --- a/zbar/video.c +++ b/zbar/video.c @@ -63,16 +63,7 @@ zbar_video_t *zbar_video_create () err_init(&vdo->err, ZBAR_MOD_VIDEO); vdo->fd = -1; -#ifdef HAVE_LIBPTHREAD - if(pthread_mutex_init(&vdo->qlock, NULL)) { - free(vdo); - return(NULL); - } -#endif -#ifdef _WIN32 - InitializeCriticalSection(&vdo->qlock); - vdo->notify = CreateEvent(NULL, 0, 0, NULL); -#endif + _zbar_mutex_init(&vdo->qlock); /* pre-allocate images */ vdo->num_images = ZBAR_VIDEO_IMAGES_MAX; @@ -100,7 +91,7 @@ zbar_video_t *zbar_video_create () void zbar_video_destroy (zbar_video_t *vdo) { - if(vdo->fd >= 0) + if(vdo->intf != VIDEO_INVALID) zbar_video_open(vdo, NULL); if(vdo->images) { int i; @@ -121,13 +112,8 @@ void zbar_video_destroy (zbar_video_t *vdo) if(vdo->formats) free(vdo->formats); err_cleanup(&vdo->err); -#ifdef HAVE_LIBPTHREAD - pthread_mutex_destroy(&vdo->qlock); -#endif -#ifdef _WIN32 - DeleteCriticalSection(&vdo->qlock); - CloseHandle(vdo->notify); -#endif + _zbar_mutex_destroy(&vdo->qlock); + #ifdef HAVE_LIBJPEG if(vdo->jpeg_img) { zbar_image_destroy(vdo->jpeg_img); @@ -144,7 +130,34 @@ void zbar_video_destroy (zbar_video_t *vdo) int zbar_video_open (zbar_video_t *vdo, const char *dev) { - return(_zbar_video_open(vdo, dev)); + zbar_video_enable(vdo, 0); + video_lock(vdo); + if(vdo->intf != VIDEO_INVALID) { + if(vdo->cleanup) { + vdo->cleanup(vdo); + vdo->cleanup = NULL; + } + zprintf(1, "closed camera (fd=%d)\n", vdo->fd); + vdo->intf = VIDEO_INVALID; + } + video_unlock(vdo); + + if(!dev) + return(0); + + char *ldev = NULL; + if((unsigned char)dev[0] < 0x10) { + /* default linux device, overloaded for other platforms */ + int id = dev[0]; + dev = ldev = strdup("/dev/video0"); + ldev[10] = '0' + id; + } + + int rc = _zbar_video_open(vdo, dev); + + if(ldev) + free(ldev); + return(rc); } int zbar_video_get_fd (const zbar_video_t *vdo) @@ -152,10 +165,9 @@ int zbar_video_get_fd (const zbar_video_t *vdo) if(vdo->intf == VIDEO_INVALID) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "video device not opened")); - if(vdo->intf == VIDEO_V4L1) + if(vdo->fd < 0) return(err_capture(vdo, SEV_WARNING, ZBAR_ERR_UNSUPPORTED, __func__, - "v4l1 API does not support polling")); - assert(vdo->fd >= 0); + "video driver does not support polling")); return(vdo->fd); } @@ -240,13 +252,6 @@ static inline int video_init_images (zbar_video_t *vdo) img->data = vdo->buf + offset; zprintf(2, " [%02d] @%08lx\n", i, offset); } -#ifndef _WIN32 - else { - assert(img->data); - assert(img->datalen); - assert(img->datalen >= vdo->datalen); - } -#endif } return(0); } @@ -266,7 +271,7 @@ int zbar_video_init (zbar_video_t *vdo, return(-1); #ifdef HAVE_LIBJPEG const zbar_format_def_t *vidfmt = _zbar_format_lookup(fmt); - if(vidfmt->group == ZBAR_FMT_JPEG) { + if(vidfmt && vidfmt->group == ZBAR_FMT_JPEG) { /* prepare for decoding */ if(!vdo->jpeg) vdo->jpeg = _zbar_jpeg_decomp_create(); diff --git a/zbar/video.h b/zbar/video.h index d164fbe..6585c2c 100644 --- a/zbar/video.h +++ b/zbar/video.h @@ -32,18 +32,11 @@ #include #include -#ifdef HAVE_PTHREAD_H -# include -#endif - -#ifdef _WIN32 -# include -#endif - #include #include "image.h" #include "error.h" +#include "mutex.h" /* number of images to preallocate */ #define ZBAR_VIDEO_IMAGES_MAX 4 @@ -61,6 +54,8 @@ typedef enum video_iomode_e { VIDEO_USERPTR, /* userspace buffers */ } video_iomode_t; +typedef struct video_state_s video_state_t; + struct zbar_video_s { errinfo_t err; /* error reporting */ int fd; /* open camera device */ @@ -79,31 +74,22 @@ struct zbar_video_s { unsigned long buflen; /* total size of image data buffer */ void *buf; /* image data buffer */ + unsigned frame; /* frame count */ + + zbar_mutex_t qlock; /* lock image queue */ int num_images; /* number of allocated images */ zbar_image_t **images; /* indexed list of images */ zbar_image_t *nq_image; /* last image enqueued */ zbar_image_t *dq_image; /* first image to dequeue (when ordered) */ zbar_image_t *shadow_image; /* special case internal double buffering */ -#ifdef HAVE_LIBPTHREAD - pthread_mutex_t qlock; /* lock image queue */ -#endif -#ifdef _WIN32 - HWND hwnd; /* vfw interface */ - CRITICAL_SECTION qlock; /* lock image queue */ - HANDLE notify; /* capture thread status change */ - int bi_size; /* size of bih */ - BITMAPINFOHEADER *bih; /* video format details */ - zbar_image_t *image; /* currently capturing frame */ -#endif + video_state_t *state; /* platform/interface specific state */ #ifdef HAVE_LIBJPEG struct jpeg_decompress_struct *jpeg; /* JPEG decompressor */ zbar_image_t *jpeg_img; /* temporary image */ #endif - unsigned frame; /* frame count */ - /* interface dependent methods */ int (*init)(zbar_video_t*, uint32_t); int (*cleanup)(zbar_video_t*); @@ -114,15 +100,13 @@ struct zbar_video_s { }; -#ifdef HAVE_LIBPTHREAD - /* video.next_image and video.recycle_image have to be thread safe * wrt/other apis */ static inline int video_lock (zbar_video_t *vdo) { int rc = 0; - if((rc = pthread_mutex_lock(&vdo->qlock))) { + if((rc = _zbar_mutex_lock(&vdo->qlock))) { err_capture(vdo, SEV_FATAL, ZBAR_ERR_LOCKING, __func__, "unable to acquire lock"); vdo->err.errnum = rc; @@ -134,7 +118,7 @@ static inline int video_lock (zbar_video_t *vdo) static inline int video_unlock (zbar_video_t *vdo) { int rc = 0; - if((rc = pthread_mutex_unlock(&vdo->qlock))) { + if((rc = _zbar_mutex_unlock(&vdo->qlock))) { err_capture(vdo, SEV_FATAL, ZBAR_ERR_LOCKING, __func__, "unable to release lock"); vdo->err.errnum = rc; @@ -143,27 +127,6 @@ static inline int video_unlock (zbar_video_t *vdo) return(0); } -#else -# ifdef _WIN32 - -static inline int video_lock (zbar_video_t *vdo) -{ - EnterCriticalSection(&vdo->qlock); - return(0); -} - -static inline int video_unlock (zbar_video_t *vdo) -{ - LeaveCriticalSection(&vdo->qlock); - return(0); -} - -# else -# define video_lock(...) (0) -# define video_unlock(...) (0) -# endif -#endif - static inline int video_nq_image (zbar_video_t *vdo, zbar_image_t *img) { @@ -195,6 +158,8 @@ static inline zbar_image_t *video_dq_image (zbar_video_t *vdo) return(img); } + +/* PAL interface */ extern int _zbar_video_open(zbar_video_t*, const char*); #endif diff --git a/zbar/video/v4l1.c b/zbar/video/v4l1.c index d6efef0..b26f21f 100644 --- a/zbar/video/v4l1.c +++ b/zbar/video/v4l1.c @@ -248,6 +248,12 @@ static int v4l1_cleanup (zbar_video_t *vdo) /* FIXME reset image */ } #endif + + /* close open device */ + if(vdo->fd >= 0) { + close(vdo->fd); + vdo->fd = -1; + } return(0); } @@ -408,29 +414,6 @@ static int _zbar_v4l1_probe (zbar_video_t *vdo) int _zbar_video_open (zbar_video_t *vdo, const char *dev) { - /* close open device */ - if(vdo->fd >= 0) { - (void)video_lock(vdo); - if(vdo->active) { - vdo->active = 0; - vdo->stop(vdo); - } - if(vdo->cleanup) - vdo->cleanup(vdo); - - close(vdo->fd); - zprintf(1, "closed camera fd=%d\n", vdo->fd); - vdo->fd = -1; - vdo->intf = VIDEO_INVALID; - (void)video_unlock(vdo); - } - if(!dev) - return(0); - - if(!dev[0]) - /* default linux device */ - dev = "/dev/video0"; - vdo->fd = open(dev, O_RDWR); if(vdo->fd < 0) return(err_capture_str(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, @@ -446,6 +429,7 @@ int _zbar_video_open (zbar_video_t *vdo, zprintf(1, "WARNING: not compiled with v4l2 support, trying v4l1\n"); #endif rc = _zbar_v4l1_probe(vdo); + if(rc && vdo->fd >= 0) { close(vdo->fd); vdo->fd = -1; diff --git a/zbar/video/v4l2.c b/zbar/video/v4l2.c index 301d93d..a27ce63 100644 --- a/zbar/video/v4l2.c +++ b/zbar/video/v4l2.c @@ -112,7 +112,7 @@ static zbar_image_t *v4l2_dq (zbar_video_t *vdo) } } else { - zbar_image_t *img = video_dq_image(vdo); + img = video_dq_image(vdo); if(!img) return(NULL); @@ -185,6 +185,12 @@ static int v4l2_cleanup (zbar_video_t *vdo) err_capture(vdo, SEV_WARNING, ZBAR_ERR_SYSTEM, __func__, "releasing video frame buffers (VIDIOC_REQBUFS)"); + + /* close open device */ + if(vdo->fd >= 0) { + close(vdo->fd); + vdo->fd = -1; + } return(0); } diff --git a/zbar/video/vfw.c b/zbar/video/vfw.c index 35a9692..af3e4d0 100644 --- a/zbar/video/vfw.c +++ b/zbar/video/vfw.c @@ -22,6 +22,7 @@ *------------------------------------------------------------------------*/ #include "video.h" +#include "thread.h" #include #include @@ -36,10 +37,20 @@ (bih)->biXPelsPerMeter, (bih)->biYPelsPerMeter, \ (bih)->biClrImportant, (bih)->biClrUsed, (bih)->biSize +struct video_state_s { + zbar_thread_t thread; /* capture message pump */ + HANDLE captured; + HWND hwnd; /* vfw interface */ + HANDLE notify; /* capture thread status change */ + int bi_size; /* size of bih */ + BITMAPINFOHEADER *bih; /* video format details */ + zbar_image_t *image; /* currently capturing frame */ +}; + static const uint32_t vfw_formats[] = { /* planar YUV formats */ fourcc('I','4','2','0'), - /* FIXME YU12 is IYUV is windows */ + /* FIXME YU12 is IYUV in windows */ fourcc('Y','V','1','2'), /* FIXME IMC[1-4]? */ @@ -70,40 +81,43 @@ static const uint32_t vfw_formats[] = { #define VFW_NUM_FORMATS (sizeof(vfw_formats) / sizeof(uint32_t)) -/* this seems to be required so the message pump can run, even when - * we're not capturing...anyway, what's one more thread in the huge - * fabric that is vfw? :| - */ -#define ZBAR_VFW_THREADED 1 - -#ifdef ZBAR_VFW_THREADED -static DWORD WINAPI vfw_capture_thread (void *arg) +static ZTHREAD vfw_capture_thread (void *arg) { zbar_video_t *vdo = arg; + video_state_t *state = vdo->state; + zbar_thread_t *thr = &state->thread; - vdo->hwnd = capCreateCaptureWindow(NULL, WS_POPUP, 0, 0, 1, 1, NULL, 0); + state->hwnd = capCreateCaptureWindow(NULL, WS_POPUP, 0, 0, 1, 1, NULL, 0); + if(!state->hwnd) + goto done; - /* FIXME error */ - assert(vdo->hwnd); - - SetEvent(vdo->notify); - zprintf(4, "spawned vfw capture thread\n"); + _zbar_mutex_lock(&vdo->qlock); + _zbar_thread_init(thr); + zprintf(4, "spawned vfw capture thread (thr=%04lx)\n", + _zbar_thread_self()); MSG msg; - int rc = -2; - while((rc = GetMessage(&msg, NULL, 0, 0)) > 0) { - TranslateMessage(&msg); - DispatchMessage(&msg); + int rc = 0; + while(thr->started && rc >= 0 && rc <= 1) { + _zbar_mutex_unlock(&vdo->qlock); + rc = MsgWaitForMultipleObjects(1, &thr->notify, 0, + INFINITE, QS_ALLINPUT); + if(rc == 1) { + rc = PeekMessage(&msg, NULL, 0, 0, PM_NOYIELD | PM_REMOVE); + if(rc > 0) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + _zbar_mutex_lock(&vdo->qlock); } - if(vdo->hwnd) { - DestroyWindow(vdo->hwnd); - vdo->hwnd = NULL; - } - zprintf(4, "exiting vfw capture thread\n"); + done: + thr->running = 0; + _zbar_event_trigger(&thr->activity); + _zbar_mutex_unlock(&vdo->qlock); return(rc); } -#endif static LRESULT CALLBACK vfw_stream_cb (HWND hwnd, VIDEOHDR *hdr) @@ -113,7 +127,7 @@ static LRESULT CALLBACK vfw_stream_cb (HWND hwnd, zbar_video_t *vdo = (void*)capGetUserData(hwnd); video_lock(vdo); - zbar_image_t *img = vdo->image; + zbar_image_t *img = vdo->state->image; if(!img) { video_lock(vdo); img = video_dq_image(vdo); @@ -121,12 +135,11 @@ static LRESULT CALLBACK vfw_stream_cb (HWND hwnd, if(img) { img->data = hdr->lpData; img->datalen = hdr->dwBufferLength; - vdo->image = img; - SetEvent(vdo->notify); + vdo->state->image = img; + SetEvent(vdo->state->captured); } video_unlock(vdo); - zprintf(64, "img=%p\n", vdo->image); return(1); } @@ -135,11 +148,8 @@ static LRESULT CALLBACK vfw_control_cb (HWND hwnd, { if(!hwnd) return(0); - zbar_video_t *vdo = (void*)capGetUserData(hwnd); - zprintf(64, "thr=%04lx vdo=%p state=%d\n", - GetCurrentThreadId(), vdo, state); - #if 0 + zbar_video_t *vdo = (void*)capGetUserData(hwnd); switch(state) { case CONTROLCALLBACK_PREROLL: break; @@ -165,7 +175,6 @@ static LRESULT CALLBACK vfw_error_cb (HWND hwnd, static int vfw_nq (zbar_video_t *vdo, zbar_image_t *img) { - zprintf(64,"thr=%04lx vdo=%p img=%p\n", GetCurrentThreadId(), vdo, img); img->data = NULL; img->datalen = 0; return(video_nq_image(vdo, img)); @@ -173,54 +182,50 @@ static int vfw_nq (zbar_video_t *vdo, static zbar_image_t *vfw_dq (zbar_video_t *vdo) { - zbar_image_t *img = vdo->image; - zprintf(64,"thr=%04lx vdo=%p img=%p\n", GetCurrentThreadId(), vdo, img); + zbar_image_t *img = vdo->state->image; + zbar_thread_t *thr = &vdo->state->thread; + HANDLE status[2] = { vdo->state->captured, thr->activity }; if(!img) { - video_unlock(vdo); - -#ifdef ZBAR_VFW_THREADED - WaitForSingleObject(vdo->notify, INFINITE); -#else - int rc = 1; - while(rc == 1) { - MSG msg; - rc = MsgWaitForMultipleObjects(1, &vdo->notify, - 0, INFINITE, QS_ALLINPUT); - if(rc == 1) { - GetMessage(&msg, NULL, 0, 0); - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } -#endif - video_lock(vdo); - img = vdo->image; + _zbar_mutex_unlock(&vdo->qlock); + int rc = WaitForMultipleObjects(2, status, 0, INFINITE); + _zbar_mutex_lock(&vdo->qlock); + img = (!rc) ? vdo->state->image : NULL; /*FIXME errors */ } + else + ResetEvent(vdo->state->captured); if(img) - vdo->image = NULL; - video_unlock(vdo); + vdo->state->image = NULL; - zprintf(64,"img=%p\n", img); + video_unlock(vdo); return(img); } static int vfw_start (zbar_video_t *vdo) { - zprintf(64,"enter...\n"); - if(!capCaptureSequenceNoFile(vdo->hwnd)) + ResetEvent(vdo->state->captured); + + if(!capCaptureSequenceNoFile(vdo->state->hwnd)) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "starting video stream")); - zprintf(64,"...leave\n"); return(0); } static int vfw_stop (zbar_video_t *vdo) { - zprintf(64,"\n"); - if(!capCaptureAbort(vdo->hwnd)) + video_state_t *state = vdo->state; + if(!capCaptureAbort(state->hwnd)) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "stopping video stream")); + + _zbar_mutex_lock(&vdo->qlock); + zbar_image_t *img = state->image; + if(img) { + state->image = NULL; + zbar_image_destroy(img); + } + SetEvent(state->captured); + _zbar_mutex_unlock(&vdo->qlock); return(0); } @@ -232,8 +237,8 @@ static int vfw_set_format (zbar_video_t *vdo, return(err_capture_int(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "unsupported vfw format: %x", fmt)); - BITMAPINFOHEADER *bih = vdo->bih; - assert(vdo->bih); + BITMAPINFOHEADER *bih = vdo->state->bih; + assert(bih); bih->biWidth = vdo->width; bih->biHeight = vdo->height; switch(fmtdef->group) { @@ -254,14 +259,14 @@ static int vfw_set_format (zbar_video_t *vdo, bih->biClrUsed = bih->biClrImportant = 0; bih->biCompression = fmt; - zprintf(4, "seting format: %.4s(%08x) " BIH_FMT "\n", + zprintf(8, "seting format: %.4s(%08x) " BIH_FMT "\n", (char*)&fmt, fmt, BIH_FIELDS(bih)); - if(!capSetVideoFormat(vdo->hwnd, bih, vdo->bi_size)) + if(!capSetVideoFormat(vdo->state->hwnd, bih, vdo->state->bi_size)) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "setting format")); - if(!capGetVideoFormat(vdo->hwnd, bih, vdo->bi_size)) + if(!capGetVideoFormat(vdo->state->hwnd, bih, vdo->state->bi_size)) return(-1/*FIXME*/); if(bih->biCompression != fmt) @@ -283,8 +288,9 @@ static int vfw_init (zbar_video_t *vdo, if(vfw_set_format(vdo, fmt)) return(-1); + HWND hwnd = vdo->state->hwnd; CAPTUREPARMS cp; - if(!capCaptureGetSetup(vdo->hwnd, &cp, sizeof(cp))) + if(!capCaptureGetSetup(hwnd, &cp, sizeof(cp))) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, "retrieving capture parameters")); @@ -299,26 +305,26 @@ static int vfw_init (zbar_video_t *vdo, cp.fAbortRightMouse = 0; cp.fLimitEnabled = 0; - if(!capCaptureSetSetup(vdo->hwnd, &cp, sizeof(cp))) + if(!capCaptureSetSetup(hwnd, &cp, sizeof(cp))) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, "setting capture parameters")); - if(!capCaptureGetSetup(vdo->hwnd, &cp, sizeof(cp))) + if(!capCaptureGetSetup(hwnd, &cp, sizeof(cp))) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, "checking capture parameters")); /* ignore errors since we skipped checking fHasOverlay */ - capOverlay(vdo->hwnd, 0); + capOverlay(hwnd, 0); - if(!capPreview(vdo->hwnd, 0) || - !capPreviewScale(vdo->hwnd, 0)) + if(!capPreview(hwnd, 0) || + !capPreviewScale(hwnd, 0)) err_capture(vdo, SEV_WARNING, ZBAR_ERR_WINAPI, __func__, "disabling preview"); - capSetCallbackOnCapControl(vdo->hwnd, vfw_control_cb); + capSetCallbackOnCapControl(hwnd, vfw_control_cb); - if(!capSetCallbackOnVideoStream(vdo->hwnd, vfw_stream_cb) || - !capSetCallbackOnError(vdo->hwnd, vfw_error_cb)) + if(!capSetCallbackOnVideoStream(hwnd, vfw_stream_cb) || + !capSetCallbackOnError(hwnd, vfw_error_cb)) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_BUSY, __func__, "setting capture callbacks")); @@ -331,6 +337,23 @@ static int vfw_init (zbar_video_t *vdo, return(0); } +static int vfw_cleanup (zbar_video_t *vdo) +{ + /* close open device */ + video_state_t *state = vdo->state; + /* NB this has to go here so the thread can pump messages during cleanup */ + capDriverDisconnect(state->hwnd); + DestroyWindow(state->hwnd); + state->hwnd = NULL; + _zbar_thread_stop(&state->thread, &vdo->qlock); + + if(state->captured) { + CloseHandle(state->captured); + state->captured = NULL; + } + return(0); +} + static int vfw_probe_format (zbar_video_t *vdo, uint32_t fmt) { @@ -339,7 +362,7 @@ static int vfw_probe_format (zbar_video_t *vdo, return(0); zprintf(4, " trying %.4s(%08x)...\n", (char*)&fmt, fmt); - BITMAPINFOHEADER *bih = vdo->bih; + BITMAPINFOHEADER *bih = vdo->state->bih; bih->biWidth = vdo->width; bih->biHeight = vdo->height; switch(fmtdef->group) { @@ -359,12 +382,12 @@ static int vfw_probe_format (zbar_video_t *vdo, } bih->biCompression = fmt; - if(!capSetVideoFormat(vdo->hwnd, bih, vdo->bi_size)) { + if(!capSetVideoFormat(vdo->state->hwnd, bih, vdo->state->bi_size)) { zprintf(4, "\tno (set fails)\n"); return(0); } - if(!capGetVideoFormat(vdo->hwnd, bih, vdo->bi_size)) + if(!capGetVideoFormat(vdo->state->hwnd, bih, vdo->state->bi_size)) return(0/*FIXME error...*/); zprintf(6, "\tactual: " BIH_FMT "\n", BIH_FIELDS(bih)); @@ -380,20 +403,21 @@ static int vfw_probe_format (zbar_video_t *vdo, static int vfw_probe (zbar_video_t *vdo) { - if(!capSetUserData(vdo->hwnd, (LONG)vdo)) + video_state_t *state = vdo->state; + if(!capSetUserData(state->hwnd, (LONG)vdo)) return(-1/*FIXME*/); - vdo->bi_size = capGetVideoFormatSize(vdo->hwnd); - if(!vdo->bi_size) + state->bi_size = capGetVideoFormatSize(state->hwnd); + if(!state->bi_size) return(-1/*FIXME*/); - BITMAPINFOHEADER *bih = vdo->bih = realloc(vdo->bih, vdo->bi_size); + BITMAPINFOHEADER *bih = state->bih = realloc(state->bih, state->bi_size); /* FIXME check OOM */ - if(!capGetVideoFormat(vdo->hwnd, bih, vdo->bi_size)) + if(!capGetVideoFormat(state->hwnd, bih, state->bi_size)) return(-1/*FIXME*/); zprintf(3, "initial format: " BIH_FMT " (bisz=%x)\n", - BIH_FIELDS(bih), vdo->bi_size); + BIH_FIELDS(bih), state->bi_size); if(!vdo->width || !vdo->height) { vdo->width = bih->biWidth; @@ -418,7 +442,7 @@ static int vfw_probe (zbar_video_t *vdo) vdo->init = vfw_init; vdo->start = vfw_start; vdo->stop = vfw_stop; - vdo->cleanup = vfw_stop; + vdo->cleanup = vfw_cleanup; vdo->nq = vfw_nq; vdo->dq = vfw_dq; return(0); @@ -427,83 +451,59 @@ static int vfw_probe (zbar_video_t *vdo) int _zbar_video_open (zbar_video_t *vdo, const char *dev) { - /* close open device */ - if(vdo->hwnd) { - video_lock(vdo); - if(vdo->active) { - vdo->active = 0; - vdo->stop(vdo); - } - if(vdo->cleanup) - vdo->cleanup(vdo); - - SendMessage(vdo->hwnd, WM_QUIT, 0, 0); - /* FIXME wait for thread to terminate */ - /*assert(!vdo->hwnd);*/ - - zprintf(1, "closed camera\n"); - vdo->hwnd = NULL; - vdo->intf = VIDEO_INVALID; - vdo->fd = -1; - video_unlock(vdo); - } - if(!dev) - return(0); - - int devid; - if(*(unsigned char*)dev < 0x10) - devid = *dev; - else if((!strncmp(dev, "/dev/video", 10) || - !strncmp(dev, "\\dev\\video", 10)) && - dev[10] >= '0' && dev[10] <= '9' && !dev[11]) - devid = dev[10] - '0'; - else - devid = -1; - - zprintf(6, "searching for camera: %s (%d)\n", dev, devid); + video_state_t *state = vdo->state; + if(!state) + state = vdo->state = calloc(1, sizeof(video_state_t)); + + int reqid = -1; + if((!strncmp(dev, "/dev/video", 10) || + !strncmp(dev, "\\dev\\video", 10)) && + dev[10] >= '0' && dev[10] <= '9' && !dev[11]) + reqid = dev[10] - '0'; + else if(strlen(dev) == 1 && + dev[0] >= '0' && dev[0] <= '9') + reqid = dev[0] - '0'; + + zprintf(6, "searching for camera: %s (%d)\n", dev, reqid); char name[MAX_NAME], desc[MAX_NAME]; - for(vdo->fd = 0; vdo->fd < MAX_DRIVERS; vdo->fd++) { - if(!capGetDriverDescription(vdo->fd, name, MAX_NAME, desc, MAX_NAME)) { + int devid; + for(devid = 0; devid < MAX_DRIVERS; devid++) { + if(!capGetDriverDescription(devid, name, MAX_NAME, desc, MAX_NAME)) { /* FIXME TBD error */ - zprintf(6, " [%d] not found...\n", vdo->fd); + zprintf(6, " [%d] not found...\n", devid); continue; } - zprintf(6, " [%d] %.100s - %.100s\n", vdo->fd, name, desc); - if((devid >= 0) - ? vdo->fd == devid + zprintf(6, " [%d] %.100s - %.100s\n", devid, name, desc); + if((reqid >= 0) + ? devid == reqid : !strncmp(dev, name, MAX_NAME)) break; } - if(vdo->fd >= MAX_DRIVERS) + if(devid >= MAX_DRIVERS) return(err_capture_str(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "video device not found '%s'", dev)); -#ifdef ZBAR_VFW_THREADED - HANDLE hthr = CreateThread(NULL, 0, vfw_capture_thread, vdo, 0, NULL); - if(!hthr) - return(-1/*FIXME*/); - CloseHandle(hthr); + if(!state->captured) + state->captured = CreateEvent(NULL, 0, 0, NULL); + else + ResetEvent(state->captured); - if(WaitForSingleObject(vdo->notify, INFINITE)) - return(-1/*FIXME*/); -#else - vdo->hwnd = capCreateCaptureWindow(NULL, WS_POPUP, 0, 0, 1, 1, NULL, 0); -#endif + if(_zbar_thread_start(&state->thread, vfw_capture_thread, vdo, NULL)) + return(-1); /* FIXME error */ - assert(vdo->hwnd); + assert(state->hwnd); - if(!capDriverConnect(vdo->hwnd, vdo->fd)) { - DestroyWindow(vdo->hwnd); - /* FIXME error: failed to connect to camera */ - assert(0); + if(!capDriverConnect(state->hwnd, devid)) { + _zbar_thread_stop(&state->thread, NULL); + return(-1/*FIXME error: failed to connect to camera*/); } - zprintf(1, "opened camera: %.60s (thr=%04lx)\n", - name, GetCurrentThreadId()); + zprintf(1, "opened camera: %.60s (%d) (thr=%04lx)\n", + name, devid, _zbar_thread_self()); if(vfw_probe(vdo)) { - _zbar_video_open(vdo, NULL); + _zbar_thread_stop(&state->thread, NULL); return(-1); } return(0); diff --git a/zbar/window.c b/zbar/window.c index f781230..dbaaae4 100644 --- a/zbar/window.c +++ b/zbar/window.c @@ -23,9 +23,6 @@ #include "window.h" #include "image.h" -#include "refcnt.h" - -extern int _zbar_window_draw_logo(zbar_window_t *w); zbar_window_t *zbar_window_create () { @@ -34,12 +31,7 @@ zbar_window_t *zbar_window_create () return(NULL); err_init(&w->err, ZBAR_MOD_WINDOW); w->overlay = 1; -#ifdef HAVE_LIBPTHREAD - pthread_mutex_init(&w->imglock, NULL); -#endif -#ifdef _WIN32 - InitializeCriticalSection(&w->imglock); -#endif + _zbar_mutex_init(&w->imglock); return(w); } @@ -48,12 +40,7 @@ void zbar_window_destroy (zbar_window_t *w) /* detach */ zbar_window_attach(w, NULL, 0); err_cleanup(&w->err); -#ifdef HAVE_LIBPTHREAD - pthread_mutex_destroy(&w->imglock); -#endif -#ifdef _WIN32 - DeleteCriticalSection(&w->imglock); -#endif + _zbar_mutex_destroy(&w->imglock); free(w); } @@ -117,31 +104,35 @@ inline int zbar_window_redraw (zbar_window_t *w) rc = err_capture_int(w, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "no conversion from %x to supported formats", img->format); - w->src_format = img->format; - w->src_width = img->width; - w->src_height = img->height; } + if(w->src_format != img->format) + w->src_format = img->format; /* FIXME preserve aspect ratio (config?) */ if(!rc && (format_change || - (img->width != w->src_width && img->width != w->dst_width) || + (img->width != w->src_width && img->width != w->dst_width) || (img->height != w->src_height && img->height != w->dst_height))) { - rc = w->init(w, img, format_change); - zprintf(24, "src=%.4s(%08x) %dx%d dst=%.4s(%08x) %dx%d\n", + zprintf(24, "init: src=%.4s(%08x) %dx%d dst=%.4s(%08x) %dx%d\n", (char*)&w->src_format, w->src_format, w->src_width, w->src_height, (char*)&w->format, w->format, w->dst_width, w->dst_height); + rc = w->init(w, img, format_change); + } + if(w->src_width != img->width || w->src_height != img->height) { + w->src_width = img->width; + w->src_height = img->height; } if(!rc && (img->format != w->format || img->width != w->dst_width || img->height != w->dst_height)) { - w->src_width = img->width; - w->src_height = img->height; /* save *converted* image for redraw */ + zprintf(48, "convert: %.4s(%08x) %dx%d => %.4s(%08x) %dx%d\n", + (char*)&img->format, img->format, img->width, img->height, + (char*)&w->format, w->format, w->dst_width, w->dst_height); w->image = zbar_image_convert_resize(img, w->format, w->dst_width, w->dst_height); zbar_image_destroy(img); @@ -155,6 +146,7 @@ inline int zbar_window_redraw (zbar_window_t *w) } else rc = _zbar_window_draw_logo(w); + _zbar_window_flush(w); (void)window_unlock(w); return(rc); } diff --git a/zbar/window.h b/zbar/window.h index ac7c962..5ce34fb 100644 --- a/zbar/window.h +++ b/zbar/window.h @@ -29,28 +29,12 @@ #endif #include -#ifdef HAVE_X -# include -# include -# ifdef HAVE_X11_EXTENSIONS_XSHM_H -# include -# endif -#ifdef HAVE_X11_EXTENSIONS_XVLIB_H -# include -#endif -#endif - -#ifdef HAVE_PTHREAD_H -# include -#endif - -#ifdef _WIN32 -# include -#endif - #include -#include "image.h" +#include "symbol.h" #include "error.h" +#include "mutex.h" + +typedef struct window_state_s window_state_t; struct zbar_window_s { errinfo_t err; /* error reporting */ @@ -72,72 +56,26 @@ struct zbar_window_s { uint32_t *formats; /* supported formats (zero terminated) */ + zbar_mutex_t imglock; /* lock displayed image */ + + void *display; + unsigned long xwin; + + window_state_t *state; /* platform/interface specific state */ + /* interface dependent methods */ int (*init)(zbar_window_t*, zbar_image_t*, int); int (*draw_image)(zbar_window_t*, zbar_image_t*); int (*cleanup)(zbar_window_t*); - -#ifdef HAVE_X - Display *display; /* display connection */ - Drawable xwin; /* platform window handle */ - GC gc; /* graphics context */ - union { - XImage *x; -#ifdef HAVE_X11_EXTENSIONS_XVLIB_H - XvImage *xv; -#endif - } img; - XID img_port; /* current format port */ - - XID *xv_ports; /* best port for format */ - int num_xv_adaptors; /* number of adaptors */ - XID *xv_adaptors; /* port grabbed for each adaptor */ - -# ifdef HAVE_X11_EXTENSIONS_XSHM_H - XShmSegmentInfo shm; /* shared memory segment */ -# endif - - unsigned long colors[8]; /* pre-allocated colors */ - - Region exposed; - - /* pre-calculated logo geometries */ - int logo_scale; - unsigned long logo_colors[2]; - Region logo_zbars; - XPoint logo_z[4]; - XRectangle logo_bars[5]; -#endif - -#ifdef HAVE_LIBPTHREAD - pthread_mutex_t imglock; /* lock displayed image */ -#endif - -#ifdef _WIN32 - HWND hwnd; - void* hdd; - - BITMAPINFOHEADER bih; - - /* pre-calculated logo geometries */ - int logo_scale; - HRGN logo_zbars; - HPEN logo_zpen, logo_zbpen; - POINT logo_z[4]; - - CRITICAL_SECTION imglock; -#endif }; -#ifdef HAVE_LIBPTHREAD - /* window.draw has to be thread safe wrt/other apis * FIXME should be a semaphore */ static inline int window_lock (zbar_window_t *w) { int rc = 0; - if((rc = pthread_mutex_lock(&w->imglock))) { + if((rc = _zbar_mutex_lock(&w->imglock))) { err_capture(w, SEV_FATAL, ZBAR_ERR_LOCKING, __func__, "unable to acquire lock"); w->err.errnum = rc; @@ -149,7 +87,7 @@ static inline int window_lock (zbar_window_t *w) static inline int window_unlock (zbar_window_t *w) { int rc = 0; - if((rc = pthread_mutex_unlock(&w->imglock))) { + if((rc = _zbar_mutex_unlock(&w->imglock))) { err_capture(w, SEV_FATAL, ZBAR_ERR_LOCKING, __func__, "unable to release lock"); w->err.errnum = rc; @@ -158,27 +96,6 @@ static inline int window_unlock (zbar_window_t *w) return(0); } -#else -# ifdef _WIN32 - -static inline int window_lock (zbar_window_t *w) -{ - EnterCriticalSection(&w->imglock); - return(0); -} - -static inline int window_unlock (zbar_window_t *w) -{ - LeaveCriticalSection(&w->imglock); - return(0); -} - -# else -# define window_lock(...) (0) -# define window_unlock(...) (0) -# endif -#endif - static inline int _zbar_window_add_format (zbar_window_t *w, uint32_t fmt) { @@ -193,15 +110,17 @@ static inline int _zbar_window_add_format (zbar_window_t *w, return(i); } + +/* PAL interface */ extern int _zbar_window_attach(zbar_window_t*, void*, unsigned long); +extern int _zbar_window_expose(zbar_window_t *w, int, int, int, int); extern int _zbar_window_resize(zbar_window_t *w); - extern int _zbar_window_clear(zbar_window_t*); - -extern int _zbar_window_draw_marker(zbar_window_t*, uint32_t, - const point_t*); +extern int _zbar_window_flush(zbar_window_t*); +extern int _zbar_window_draw_logo(zbar_window_t *w); +extern int _zbar_window_draw_marker(zbar_window_t*, uint32_t, const point_t*); #if 0 extern int _zbar_window_draw_line(zbar_window_t*, uint32_t, const point_t*, const point_t*); @@ -211,8 +130,4 @@ extern int _zbar_window_draw_text(zbar_window_t*, uint32_t, const point_t*, const char*); #endif -#ifdef _WIN32 -extern int _zbar_window_bih_init(zbar_window_t*, zbar_image_t*); -#endif - #endif diff --git a/zbar/window/dib.c b/zbar/window/dib.c index 19a9cda..1cf2b51 100644 --- a/zbar/window/dib.c +++ b/zbar/window/dib.c @@ -22,6 +22,8 @@ *------------------------------------------------------------------------*/ #include "window.h" +#include "image.h" +#include "win.h" static int dib_cleanup (zbar_window_t *w) { @@ -35,25 +37,27 @@ static int dib_init (zbar_window_t *w, if(new_format) _zbar_window_bih_init(w, img); - w->dst_width = w->bih.biWidth = (img->width + 3) & ~3; - w->dst_height = w->bih.biHeight = img->height; + window_state_t *win = w->state; + w->dst_width = win->bih.biWidth = (img->width + 3) & ~3; + w->dst_height = win->bih.biHeight = img->height; return(0); } static int dib_draw (zbar_window_t *w, zbar_image_t *img) { - HDC hdc = GetDC(w->hwnd); + HDC hdc = GetDC(w->display); if(!hdc) return(-1); + window_state_t *win = w->state; StretchDIBits(hdc, 0, w->height - 1, w->width, -w->height, 0, 0, w->src_width, w->src_height, - (void*)img->data, (BITMAPINFO*)&w->bih, + (void*)img->data, (BITMAPINFO*)&win->bih, DIB_RGB_COLORS, SRCCOPY); - ValidateRect(w->hwnd, NULL); - ReleaseDC(w->hwnd, hdc); + ValidateRect(w->display, NULL); + ReleaseDC(w->display, hdc); return(0); } diff --git a/zbar/window/vfw.c b/zbar/window/vfw.c index d2d54f3..a4bb288 100644 --- a/zbar/window/vfw.c +++ b/zbar/window/vfw.c @@ -24,6 +24,9 @@ #include "window.h" #include +extern int _zbar_window_bih_init(zbar_window_t *w, + zbar_image_t *img); + static int vfw_cleanup (zbar_window_t *w) { if(w->hdd) { diff --git a/zbar/window/win.c b/zbar/window/win.c index 1068607..827ea2c 100644 --- a/zbar/window/win.c +++ b/zbar/window/win.c @@ -22,21 +22,22 @@ *------------------------------------------------------------------------*/ #include "window.h" +#include "image.h" +#include "win.h" int _zbar_window_vfw_init(zbar_window_t *w); int _zbar_window_dib_init(zbar_window_t *w); -int -_zbar_window_draw_marker(zbar_window_t *w, - uint32_t rgb, - const point_t *p) +int _zbar_window_draw_marker(zbar_window_t *w, + uint32_t rgb, + const point_t *p) { return(-1); } -int -_zbar_window_resize (zbar_window_t *w) +int _zbar_window_resize (zbar_window_t *w) { + window_state_t *win = w->state; int lbw; if(w->height * 8 / 10 <= w->width) lbw = w->height / 36; @@ -44,28 +45,28 @@ _zbar_window_resize (zbar_window_t *w) lbw = w->width * 5 / 144; if(lbw < 1) lbw = 1; - w->logo_scale = lbw; + win->logo_scale = lbw; zprintf(7, "%dx%d scale=%d\n", w->width, w->height, lbw); - if(w->logo_zbars) { - DeleteObject(w->logo_zbars); - w->logo_zbars = NULL; + if(win->logo_zbars) { + DeleteObject(win->logo_zbars); + win->logo_zbars = NULL; } - if(w->logo_zpen) - DeleteObject(w->logo_zpen); - if(w->logo_zbpen) - DeleteObject(w->logo_zbpen); + if(win->logo_zpen) + DeleteObject(win->logo_zpen); + if(win->logo_zbpen) + DeleteObject(win->logo_zbpen); LOGBRUSH lb = { 0, }; lb.lbStyle = BS_SOLID; lb.lbColor = RGB(0xd7, 0x33, 0x33); - w->logo_zpen = ExtCreatePen(PS_GEOMETRIC | PS_SOLID | - PS_ENDCAP_ROUND | PS_JOIN_ROUND, - lbw * 2, &lb, 0, NULL); + win->logo_zpen = ExtCreatePen(PS_GEOMETRIC | PS_SOLID | + PS_ENDCAP_ROUND | PS_JOIN_ROUND, + lbw * 2, &lb, 0, NULL); lb.lbColor = RGB(0xa4, 0x00, 0x00); - w->logo_zbpen = ExtCreatePen(PS_GEOMETRIC | PS_SOLID | - PS_ENDCAP_ROUND | PS_JOIN_ROUND, - lbw * 2, &lb, 0, NULL); + win->logo_zbpen = ExtCreatePen(PS_GEOMETRIC | PS_SOLID | + PS_ENDCAP_ROUND | PS_JOIN_ROUND, + lbw * 2, &lb, 0, NULL); int x0 = w->width / 2; int y0 = w->height / 2; @@ -80,127 +81,141 @@ _zbar_window_resize (zbar_window_t *w) int x = x0 + lbw * bx[i]; HRGN bar = CreateRectRgn(x, by0, x + lbw * bw[i], by0 + bh); - if(w->logo_zbars) { - CombineRgn(w->logo_zbars, w->logo_zbars, bar, RGN_OR); + if(win->logo_zbars) { + CombineRgn(win->logo_zbars, win->logo_zbars, bar, RGN_OR); DeleteObject(bar); } else - w->logo_zbars = bar; + win->logo_zbars = bar; } static const int zx[4] = { -7, 7, -7, 7 }; static const int zy[4] = { -8, -8, 8, 8 }; for(i = 0; i < 4; i++) { - w->logo_z[i].x = x0 + lbw * zx[i]; - w->logo_z[i].y = y0 + lbw * zy[i]; + win->logo_z[i].x = x0 + lbw * zx[i]; + win->logo_z[i].y = y0 + lbw * zy[i]; } return(0); } -int -_zbar_window_attach (zbar_window_t *w, - void *display, - unsigned long win) +int _zbar_window_attach (zbar_window_t *w, + void *display, + unsigned long unused) { - if(w->hwnd) { + window_state_t *win = w->state; + if(w->display) { /* FIXME cleanup existing resources */ - w->hwnd = NULL; + w->display = NULL; } - if(!display) + if(!display) { + if(win) { + free(win); + w->state = NULL; + } return(0); + } - w->hwnd = display; + if(!win) + win = w->state = calloc(1, sizeof(window_state_t)); - w->bih.biSize = sizeof(w->bih); - w->bih.biPlanes = 1; + w->display = display; - HDC hdc = GetDC(w->hwnd); + win->bih.biSize = sizeof(win->bih); + win->bih.biPlanes = 1; + + HDC hdc = GetDC(w->display); if(!hdc) return(-1/*FIXME*/); - w->bih.biXPelsPerMeter = + win->bih.biXPelsPerMeter = 1000L * GetDeviceCaps(hdc, HORZRES) / GetDeviceCaps(hdc, HORZSIZE); - w->bih.biYPelsPerMeter = + win->bih.biYPelsPerMeter = 1000L * GetDeviceCaps(hdc, VERTRES) / GetDeviceCaps(hdc, VERTSIZE); - ReleaseDC(w->hwnd, hdc); + ReleaseDC(w->display, hdc); return(_zbar_window_dib_init(w)); } -int -_zbar_window_clear (zbar_window_t *w) +int _zbar_window_clear (zbar_window_t *w) { - HDC hdc = GetDC(w->hwnd); + HDC hdc = GetDC(w->display); if(!hdc) return(-1/*FIXME*/); RECT r = { 0, 0, w->width, w->height }; FillRect(hdc, &r, GetStockObject(BLACK_BRUSH)); - ReleaseDC(w->hwnd, hdc); - ValidateRect(w->hwnd, NULL); + ReleaseDC(w->display, hdc); + ValidateRect(w->display, NULL); + return(0); +} + +int _zbar_window_flush (zbar_window_t *w) +{ return(0); } -int -_zbar_window_draw_logo (zbar_window_t *w) +int _zbar_window_draw_logo (zbar_window_t *w) { - if(!w->hwnd) + if(!w->display) return(-1); - HDC hdc = GetDC(w->hwnd); + HDC hdc = GetDC(w->display); if(!hdc || !SaveDC(hdc)) return(-1/*FIXME*/); + window_state_t *win = w->state; + /* FIXME buffer offscreen */ HRGN rgn = CreateRectRgn(0, 0, w->width, w->height); - CombineRgn(rgn, rgn, w->logo_zbars, RGN_DIFF); + CombineRgn(rgn, rgn, win->logo_zbars, RGN_DIFF); FillRgn(hdc, rgn, GetStockObject(WHITE_BRUSH)); DeleteObject(rgn); - FillRgn(hdc, w->logo_zbars, GetStockObject(BLACK_BRUSH)); + FillRgn(hdc, win->logo_zbars, GetStockObject(BLACK_BRUSH)); - SelectObject(hdc, w->logo_zpen); - Polyline(hdc, w->logo_z, 4); + SelectObject(hdc, win->logo_zpen); + Polyline(hdc, win->logo_z, 4); - ExtSelectClipRgn(hdc, w->logo_zbars, RGN_AND); - SelectObject(hdc, w->logo_zbpen); - Polyline(hdc, w->logo_z, 4); + ExtSelectClipRgn(hdc, win->logo_zbars, RGN_AND); + SelectObject(hdc, win->logo_zbpen); + Polyline(hdc, win->logo_z, 4); RestoreDC(hdc, -1); - ReleaseDC(w->hwnd, hdc); - ValidateRect(w->hwnd, NULL); + ReleaseDC(w->display, hdc); + ValidateRect(w->display, NULL); return(0); } int _zbar_window_bih_init (zbar_window_t *w, zbar_image_t *img) { + window_state_t *win = w->state; switch(w->format) { case fourcc('J','P','E','G'): { - w->bih.biBitCount = 0; - w->bih.biCompression = BI_JPEG; + win->bih.biBitCount = 0; + win->bih.biCompression = BI_JPEG; break; } case fourcc('B','G','R','3'): { - w->bih.biBitCount = 24; - w->bih.biCompression = BI_RGB; + win->bih.biBitCount = 24; + win->bih.biCompression = BI_RGB; break; } case fourcc('B','G','R','4'): { - w->bih.biBitCount = 32; - w->bih.biCompression = BI_RGB; + win->bih.biBitCount = 32; + win->bih.biCompression = BI_RGB; break; } default: assert(0); /* FIXME PNG? */ } - w->bih.biSizeImage = img->datalen; + win->bih.biSizeImage = img->datalen; zprintf(20, "biCompression=%d biBitCount=%d\n", - (int)w->bih.biCompression, w->bih.biBitCount); + (int)win->bih.biCompression, win->bih.biBitCount); return(0); } diff --git a/zbar/logo.c b/zbar/window/win.h similarity index 69% rename from zbar/logo.c rename to zbar/window/win.h index 0b43a99..076b35e 100644 --- a/zbar/logo.c +++ b/zbar/window/win.h @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2008-2009 (c) Jeff Brown + * Copyright 2009 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -20,13 +20,24 @@ * * http://sourceforge.net/projects/zbar *------------------------------------------------------------------------*/ +#ifndef _WINDOW_WIN_H_ +#define _WINDOW_WIN_H_ -#include -#include "window.h" -#include "error.h" +#include -int _zbar_draw_logo (zbar_window_t *w) -{ - _zbar_window_clear(w); - return(0); -} +struct window_state_s { + void* hdd; + + BITMAPINFOHEADER bih; + + /* pre-calculated logo geometries */ + int logo_scale; + HRGN logo_zbars; + HPEN logo_zpen, logo_zbpen; + POINT logo_z[4]; +}; + +extern int _zbar_window_bih_init(zbar_window_t *w, + zbar_image_t *img); + +#endif diff --git a/zbar/window/x.c b/zbar/window/x.c index f7c99ad..8a732b9 100644 --- a/zbar/window/x.c +++ b/zbar/window/x.c @@ -22,10 +22,7 @@ *------------------------------------------------------------------------*/ #include "window.h" - -extern int _zbar_window_probe_ximage(zbar_window_t*); -extern int _zbar_window_probe_xshm(zbar_window_t*); -extern int _zbar_window_probe_xv(zbar_window_t*); +#include "x.h" static inline unsigned long window_alloc_color (zbar_window_t *w, Colormap cmap, @@ -44,17 +41,17 @@ static inline unsigned long window_alloc_color (zbar_window_t *w, static inline int window_alloc_colors (zbar_window_t *w) { + window_state_t *x = w->state; Colormap cmap = DefaultColormap(w->display, DefaultScreen(w->display)); int i; for(i = 0; i < 8; i++) - w->colors[i] = - window_alloc_color(w, cmap, - (i & 4) ? (0xcc * 0x101) : 0, - (i & 2) ? (0xcc * 0x101) : 0, - (i & 1) ? (0xcc * 0x101) : 0); - - w->logo_colors[0] = window_alloc_color(w, cmap, 0xd709, 0x3333, 0x3333); - w->logo_colors[1] = window_alloc_color(w, cmap, 0xa3d6, 0x0000, 0x0000); + x->colors[i] = window_alloc_color(w, cmap, + (i & 4) ? (0xcc * 0x101) : 0, + (i & 2) ? (0xcc * 0x101) : 0, + (i & 1) ? (0xcc * 0x101) : 0); + + x->logo_colors[0] = window_alloc_color(w, cmap, 0xd709, 0x3333, 0x3333); + x->logo_colors[1] = window_alloc_color(w, cmap, 0xa3d6, 0x0000, 0x0000); return(0); } @@ -79,6 +76,7 @@ static inline int window_hide_cursor (zbar_window_t *w) int _zbar_window_resize (zbar_window_t *w) { + window_state_t *x = w->state; int lbw; if(w->height * 8 / 10 <= w->width) lbw = w->height / 36; @@ -86,10 +84,10 @@ int _zbar_window_resize (zbar_window_t *w) lbw = w->width * 5 / 144; if(lbw < 1) lbw = 1; - w->logo_scale = lbw; - if(w->logo_zbars) - XDestroyRegion(w->logo_zbars); - w->logo_zbars = XCreateRegion(); + x->logo_scale = lbw; + if(x->logo_zbars) + XDestroyRegion(x->logo_zbars); + x->logo_zbars = XCreateRegion(); int x0 = w->width / 2; int y0 = w->height / 2; @@ -101,20 +99,20 @@ int _zbar_window_resize (zbar_window_t *w) int i; for(i = 0; i < 5; i++) { - XRectangle *bar = &w->logo_bars[i]; + XRectangle *bar = &x->logo_bars[i]; bar->x = x0 + lbw * bx[i]; bar->y = by0; bar->width = lbw * bw[i]; bar->height = bh; - XUnionRectWithRegion(bar, w->logo_zbars, w->logo_zbars); + XUnionRectWithRegion(bar, x->logo_zbars, x->logo_zbars); } static const int zx[4] = { -7, 7, -7, 7 }; static const int zy[4] = { -8, -8, 8, 8 }; for(i = 0; i < 4; i++) { - w->logo_z[i].x = x0 + lbw * zx[i]; - w->logo_z[i].y = y0 + lbw * zy[i]; + x->logo_z[i].x = x0 + lbw * zx[i]; + x->logo_z[i].y = y0 + lbw * zy[i]; } return(0); } @@ -123,25 +121,38 @@ int _zbar_window_attach (zbar_window_t *w, void *display, unsigned long win) { + window_state_t *x = w->state; if(w->display) { /* cleanup existing resources */ - if(w->gc) - XFreeGC(w->display, w->gc); - assert(!w->exposed); - if(w->logo_zbars) { - XDestroyRegion(w->logo_zbars); - w->logo_zbars = NULL; + if(x->gc) + XFreeGC(w->display, x->gc); + assert(!x->exposed); + if(x->logo_zbars) { + XDestroyRegion(x->logo_zbars); + x->logo_zbars = NULL; + } + if(x->exposed) { + XDestroyRegion(x->exposed); + x->exposed = NULL; } w->display = NULL; } w->xwin = 0; - if(!display || !win) + if(!display || !win) { + if(x) { + free(x); + w->state = NULL; + } return(0); + } + + if(!x) + x = w->state = calloc(1, sizeof(window_state_t)); w->display = display; w->xwin = win; - w->gc = XCreateGC(display, win, 0, NULL); + x->gc = XCreateGC(display, win, 0, NULL); XWindowAttributes attr; XGetWindowAttributes(w->display, w->xwin, &attr); @@ -162,13 +173,46 @@ int _zbar_window_attach (zbar_window_t *w, return(_zbar_window_probe_ximage(w)); } +int _zbar_window_expose (zbar_window_t *w, + int x, + int y, + int width, + int height) +{ + window_lock(w); + window_state_t *xs = w->state; + if(!xs->exposed) + xs->exposed = XCreateRegion(); + XRectangle r; + r.x = x; + r.y = y; + r.width = width; + r.height = height; + XUnionRectWithRegion(&r, xs->exposed, xs->exposed); + window_unlock(w); + return(0); +} + +int _zbar_window_flush (zbar_window_t *w) +{ + window_state_t *x = w->state; + XFlush(w->display); + XSetClipMask(w->display, x->gc, None); + if(x->exposed) { + XDestroyRegion(x->exposed); + x->exposed = NULL; + } + return(0); +} + int _zbar_window_clear (zbar_window_t *w) { if(!w->display) return(0); + window_state_t *x = w->state; int screen = DefaultScreen(w->display); - XSetForeground(w->display, w->gc, WhitePixel(w->display, screen)); - XFillRectangle(w->display, w->xwin, w->gc, 0, 0, w->width, w->height); + XSetForeground(w->display, x->gc, WhitePixel(w->display, screen)); + XFillRectangle(w->display, w->xwin, x->gc, 0, 0, w->width, w->height); return(0); } @@ -176,7 +220,8 @@ int _zbar_window_draw_marker(zbar_window_t *w, uint32_t rgb, const point_t *p) { - XSetForeground(w->display, w->gc, w->colors[rgb]); + window_state_t *xs = w->state; + XSetForeground(w->display, xs->gc, xs->colors[rgb]); int x = p->x; if(x < 3) @@ -190,49 +235,49 @@ int _zbar_window_draw_marker(zbar_window_t *w, else if(y > w->height - 4) y = w->height - 4; - XDrawRectangle(w->display, w->xwin, w->gc, x - 2, y - 2, 4, 4); - XDrawLine(w->display, w->xwin, w->gc, x, y - 3, x, y + 3); - XDrawLine(w->display, w->xwin, w->gc, x - 3, y, x + 3, y); + XDrawRectangle(w->display, w->xwin, xs->gc, x - 2, y - 2, 4, 4); + XDrawLine(w->display, w->xwin, xs->gc, x, y - 3, x, y + 3); + XDrawLine(w->display, w->xwin, xs->gc, x - 3, y, x + 3, y); return(0); } int _zbar_window_draw_logo (zbar_window_t *w) { - if(w->exposed) - XSetRegion(w->display, w->gc, w->exposed); + window_state_t *x = w->state; + if(x->exposed) + XSetRegion(w->display, x->gc, x->exposed); int screen = DefaultScreen(w->display); /* clear to white */ - XSetForeground(w->display, w->gc, WhitePixel(w->display, screen)); - XFillRectangle(w->display, w->xwin, w->gc, 0, 0, w->width, w->height); + XSetForeground(w->display, x->gc, WhitePixel(w->display, screen)); + XFillRectangle(w->display, w->xwin, x->gc, 0, 0, w->width, w->height); - if(!w->logo_scale || !w->logo_zbars) + if(!x->logo_scale || !x->logo_zbars) return(0); - XSetForeground(w->display, w->gc, BlackPixel(w->display, screen)); - XFillRectangles(w->display, w->xwin, w->gc, w->logo_bars, 5); + XSetForeground(w->display, x->gc, BlackPixel(w->display, screen)); + XFillRectangles(w->display, w->xwin, x->gc, x->logo_bars, 5); - XSetLineAttributes(w->display, w->gc, 2 * w->logo_scale, + XSetLineAttributes(w->display, x->gc, 2 * x->logo_scale, LineSolid, CapRound, JoinRound); - XSetForeground(w->display, w->gc, w->logo_colors[0]); - XDrawLines(w->display, w->xwin, w->gc, w->logo_z, 4, CoordModeOrigin); + XSetForeground(w->display, x->gc, x->logo_colors[0]); + XDrawLines(w->display, w->xwin, x->gc, x->logo_z, 4, CoordModeOrigin); + XFlush(w->display); - if(w->exposed) { - XIntersectRegion(w->logo_zbars, w->exposed, w->exposed); - XSetRegion(w->display, w->gc, w->exposed); + if(x->exposed) { + XIntersectRegion(x->logo_zbars, x->exposed, x->exposed); + XSetRegion(w->display, x->gc, x->exposed); } else - XSetRegion(w->display, w->gc, w->logo_zbars); + XSetRegion(w->display, x->gc, x->logo_zbars); - XSetForeground(w->display, w->gc, w->logo_colors[1]); - XDrawLines(w->display, w->xwin, w->gc, w->logo_z, 4, CoordModeOrigin); - XFlush(w->display); + XSetForeground(w->display, x->gc, x->logo_colors[1]); + XDrawLines(w->display, w->xwin, x->gc, x->logo_z, 4, CoordModeOrigin); /* reset GC */ - XSetLineAttributes(w->display, w->gc, 0, + XSetLineAttributes(w->display, x->gc, 0, LineSolid, CapButt, JoinMiter); - XSetClipMask(w->display, w->gc, None); return(0); } diff --git a/zbar/window/x.h b/zbar/window/x.h new file mode 100644 index 0000000..b49dfaa --- /dev/null +++ b/zbar/window/x.h @@ -0,0 +1,73 @@ +/*------------------------------------------------------------------------ + * Copyright 2007-2009 (c) Jeff Brown + * + * 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 + *------------------------------------------------------------------------*/ +#ifndef _WINDOW_X_H_ +#define _WINDOW_X_H_ + +#include "window.h" + +#ifdef HAVE_X +# include +# include +# ifdef HAVE_X11_EXTENSIONS_XSHM_H +# include +# endif +#ifdef HAVE_X11_EXTENSIONS_XVLIB_H +# include +#endif +#endif + +struct window_state_s { + unsigned long colors[8]; /* pre-allocated colors */ + + GC gc; /* graphics context */ + Region exposed; /* region to redraw */ + + /* pre-calculated logo geometries */ + int logo_scale; + unsigned long logo_colors[2]; + Region logo_zbars; + XPoint logo_z[4]; + XRectangle logo_bars[5]; + +#ifdef HAVE_X11_EXTENSIONS_XSHM_H + XShmSegmentInfo shm; /* shared memory segment */ +#endif + + union { + XImage *x; +#ifdef HAVE_X11_EXTENSIONS_XVLIB_H + XvImage *xv; +#endif + } img; + + XID img_port; /* current format port */ + XID *xv_ports; /* best port for format */ + int num_xv_adaptors; /* number of adaptors */ + XID *xv_adaptors; /* port grabbed for each adaptor */ +}; + +extern int _zbar_window_probe_ximage(zbar_window_t*); +extern int _zbar_window_probe_xshm(zbar_window_t*); +extern int _zbar_window_probe_xv(zbar_window_t*); + +#endif diff --git a/zbar/window/ximage.c b/zbar/window/ximage.c index 93ed7e1..764ab2e 100644 --- a/zbar/window/ximage.c +++ b/zbar/window/ximage.c @@ -22,12 +22,15 @@ *------------------------------------------------------------------------*/ #include "window.h" +#include "x.h" +#include "image.h" static int ximage_cleanup (zbar_window_t *w) { - if(w->img.x) - free(w->img.x); - w->img.x = NULL; + window_state_t *x = w->state; + if(x->img.x) + free(x->img.x); + x->img.x = NULL; return(0); } @@ -35,11 +38,8 @@ static inline int ximage_init (zbar_window_t *w, zbar_image_t *img, int format_change) { - if(w->img.x) { - free(w->img.x); - w->img.x = NULL; - } - XImage *ximg = w->img.x = calloc(1, sizeof(XImage)); + ximage_cleanup(w); + XImage *ximg = w->state->img.x = calloc(1, sizeof(XImage)); ximg->width = img->width; ximg->height = img->height; ximg->format = ZPixmap; @@ -86,12 +86,13 @@ static inline int ximage_init (zbar_window_t *w, static int ximage_draw (zbar_window_t *w, zbar_image_t *img) { - XImage *ximg = w->img.x; + window_state_t *x = w->state; + XImage *ximg = x->img.x; assert(ximg); ximg->data = (void*)img->data; int screen = DefaultScreen(w->display); - XSetForeground(w->display, w->gc, WhitePixel(w->display, screen)); + XSetForeground(w->display, x->gc, WhitePixel(w->display, screen)); /* FIXME implement some basic scaling */ unsigned height = img->height; @@ -103,9 +104,9 @@ static int ximage_draw (zbar_window_t *w, else if(w->height != img->height) { dst_y = (w->height - img->height) >> 1; /* fill border */ - XFillRectangle(w->display, w->xwin, w->gc, + XFillRectangle(w->display, w->xwin, x->gc, 0, 0, w->width, dst_y); - XFillRectangle(w->display, w->xwin, w->gc, + XFillRectangle(w->display, w->xwin, x->gc, 0, dst_y + img->height, w->width, dst_y); } @@ -118,13 +119,13 @@ static int ximage_draw (zbar_window_t *w, else if(w->width != img->width) { dst_x = (w->width - img->width) >> 1; /* fill border */ - XFillRectangle(w->display, w->xwin, w->gc, + XFillRectangle(w->display, w->xwin, x->gc, 0, dst_y, dst_x, img->height); - XFillRectangle(w->display, w->xwin, w->gc, + XFillRectangle(w->display, w->xwin, x->gc, img->width + dst_x, dst_y, dst_x, img->height); } - XPutImage(w->display, w->xwin, w->gc, ximg, + XPutImage(w->display, w->xwin, x->gc, ximg, src_x, src_y, dst_x, dst_y, width, height); ximg->data = NULL; return(0); diff --git a/zbar/window/xv.c b/zbar/window/xv.c index 52ff778..d96e186 100644 --- a/zbar/window/xv.c +++ b/zbar/window/xv.c @@ -22,25 +22,28 @@ *------------------------------------------------------------------------*/ #include "window.h" +#include "x.h" +#include "image.h" #include /* strcmp */ static int xv_cleanup (zbar_window_t *w) { - if(w->img.xv) { - XFree(w->img.xv); - w->img.xv = NULL; + window_state_t *x = w->state; + if(x->img.xv) { + XFree(x->img.xv); + x->img.xv = NULL; } int i; - for(i = 0; i < w->num_xv_adaptors; i++) - if(w->xv_adaptors[i]) { - XvUngrabPort(w->display, w->xv_adaptors[i], CurrentTime); - w->xv_adaptors[i] = 0; + for(i = 0; i < x->num_xv_adaptors; i++) + if(x->xv_adaptors[i]) { + XvUngrabPort(w->display, x->xv_adaptors[i], CurrentTime); + x->xv_adaptors[i] = 0; } - free(w->xv_ports); - free(w->xv_adaptors); - w->xv_ports = NULL; - w->num_xv_adaptors = 0; - w->xv_adaptors = NULL; + free(x->xv_ports); + free(x->xv_adaptors); + x->xv_ports = NULL; + x->num_xv_adaptors = 0; + x->xv_adaptors = NULL; return(0); } @@ -48,22 +51,23 @@ static inline int xv_init (zbar_window_t *w, zbar_image_t *img, int format_change) { + window_state_t *x = w->state; + if(x->img.xv) { + XFree(x->img.xv); + x->img.xv = NULL; + } if(format_change) { /* lookup port for format */ - w->img_port = 0; + x->img_port = 0; int i; for(i = 0; w->formats[i]; i++) if(w->formats[i] == w->format) { - w->img_port = w->xv_ports[i]; + x->img_port = x->xv_ports[i]; break; } - assert(w->img_port > 0); - } - if(w->img.xv) { - XFree(w->img.xv); - w->img.xv = NULL; + assert(x->img_port > 0); } - XvImage *xvimg = XvCreateImage(w->display, w->img_port, w->format, + XvImage *xvimg = XvCreateImage(w->display, x->img_port, w->format, NULL, img->width, img->height); zprintf(3, "new XvImage %.4s(%08" PRIx32 ") %dx%d(%d)" " from %.4s(%08" PRIx32 ") %dx%d\n", @@ -86,7 +90,7 @@ static inline int xv_init (zbar_window_t *w, return(err_capture(w, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "output image size mismatch (XvCreateImage)")); } - w->img.xv = xvimg; + x->img.xv = xvimg; return(0); } @@ -94,12 +98,13 @@ static inline int xv_init (zbar_window_t *w, static int xv_draw (zbar_window_t *w, zbar_image_t *img) { - XvImage *xvimg = w->img.xv; + window_state_t *x = w->state; + XvImage *xvimg = x->img.xv; assert(xvimg); xvimg->data = (void*)img->data; zprintf(24, "XvPutImage(%dx%d -> %dx%d)\n", w->src_width, w->src_height, w->width, w->height); - XvPutImage(w->display, w->img_port, w->xwin, w->gc, xvimg, + XvPutImage(w->display, x->img_port, w->xwin, x->gc, xvimg, 0, 0, w->src_width, w->src_height, 0, 0, w->width, w->height); xvimg->data = NULL; /* FIXME hold shm image until completion */ @@ -112,11 +117,12 @@ static inline int xv_add_format (zbar_window_t *w, { int i = _zbar_window_add_format(w, fmt); + window_state_t *x = w->state; if(!w->formats[i + 1]) - w->xv_ports = realloc(w->xv_ports, (i + 1) * sizeof(uint32_t)); + x->xv_ports = realloc(x->xv_ports, (i + 1) * sizeof(uint32_t)); /* FIXME could prioritize by something (rate? size?) */ - w->xv_ports[i] = port; + x->xv_ports[i] = port; return(i); } @@ -194,8 +200,9 @@ int _zbar_window_probe_xv (zbar_window_t *w) return(err_capture(w, SEV_ERROR, ZBAR_ERR_XPROTO, __func__, "unable to query XVideo adaptors")); - w->num_xv_adaptors = 0; - w->xv_adaptors = calloc(n, sizeof(int)); + window_state_t *x = w->state; + x->num_xv_adaptors = 0; + x->xv_adaptors = calloc(n, sizeof(int)); int i; for(i = 0; i < n; i++) { XvAdaptorInfo *adapt = &adaptors[i]; @@ -211,7 +218,7 @@ int _zbar_window_probe_xv (zbar_window_t *w) if(!XvGrabPort(w->display, adapt->base_id + j, CurrentTime)) { zprintf(3, " grabbed port %u\n", (unsigned)(adapt->base_id + j)); - w->xv_adaptors[w->num_xv_adaptors++] = adapt->base_id + j; + x->xv_adaptors[x->num_xv_adaptors++] = adapt->base_id + j; break; } @@ -221,23 +228,23 @@ int _zbar_window_probe_xv (zbar_window_t *w) XvFreeAdaptorInfo(adaptors); adaptors = NULL; - if(!w->num_xv_adaptors) { + if(!x->num_xv_adaptors) { zprintf(1, "WARNING: no XVideo adaptor supporting XvImages found\n"); - free(w->xv_adaptors); - w->xv_adaptors = NULL; + free(x->xv_adaptors); + x->xv_adaptors = NULL; return(-1); } - if(w->num_xv_adaptors < n) - w->xv_adaptors = realloc(w->xv_adaptors, - w->num_xv_adaptors * sizeof(int)); + if(x->num_xv_adaptors < n) + x->xv_adaptors = realloc(x->xv_adaptors, + x->num_xv_adaptors * sizeof(int)); w->max_width = w->max_height = 65536; w->formats = realloc(w->formats, sizeof(uint32_t)); w->formats[0] = 0; - for(i = 0; i < w->num_xv_adaptors; i++) - if(xv_probe_port(w, w->xv_adaptors[i])) { - XvUngrabPort(w->display, w->xv_adaptors[i], CurrentTime); - w->xv_adaptors[i] = 0; + for(i = 0; i < x->num_xv_adaptors; i++) + if(xv_probe_port(w, x->xv_adaptors[i])) { + XvUngrabPort(w->display, x->xv_adaptors[i], CurrentTime); + x->xv_adaptors[i] = 0; } if(!w->formats[0] || w->max_width == 65536 || w->max_height == 65536) { xv_cleanup(w); @@ -245,14 +252,14 @@ int _zbar_window_probe_xv (zbar_window_t *w) } /* clean out any unused adaptors */ - for(i = 0; i < w->num_xv_adaptors; i++) { + for(i = 0; i < x->num_xv_adaptors; i++) { int j; for(j = 0; w->formats[j]; j++) - if(w->xv_ports[j] == w->xv_adaptors[i]) + if(x->xv_ports[j] == x->xv_adaptors[i]) break; if(!w->formats[j]) { - XvUngrabPort(w->display, w->xv_adaptors[i], CurrentTime); - w->xv_adaptors[i] = 0; + XvUngrabPort(w->display, x->xv_adaptors[i], CurrentTime); + x->xv_adaptors[i] = 0; } } From e46f6cdf9ab2907d6a9ce7aa3013c9c14da6215c Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 14 Aug 2009 12:32:30 -0400 Subject: [PATCH 114/328] add zbarcam to windows installer --- ChangeLog | 1 + README.windows | 11 ++++++++--- zbar.nsi | 40 +++++++++++++++++++++++++++++----------- zbar/Makefile.am.inc | 2 +- zbar/video/vfw.c | 2 +- zbarcam/Makefile.am.inc | 5 +++++ zbarcam/zbarcam.rc | 30 ++++++++++++++++++++++++++++++ 7 files changed, 75 insertions(+), 16 deletions(-) create mode 100644 zbarcam/zbarcam.rc diff --git a/ChangeLog b/ChangeLog index f89b1b0..74d5c73 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * add zbarcam to windows installer * major restructuring to improve platform abstraction - add lock, thread and timer abstractions - migrate specific notification locks to platform independent layer diff --git a/README.windows b/README.windows index 28726b0..02ee17c 100644 --- a/README.windows +++ b/README.windows @@ -38,13 +38,18 @@ This version of the package includes *only command line programs*. (The graphical interface is scheduled for a future release) Invoke Start -> Programs -> ZBar Bar Code Reader -> Start ZBar Command Prompt -to open a shell that has the zbarimg command available (in the PATH). +to open a shell that has the zbarimg and zbarcam commands available +(in the PATH). -To decode an image file, type: - zbarimg "C:\path\to\barcode.png" +To start the webcam reader using the default camera, type: + zbarcam + +To decode an image file, type eg: + zbarimg -d examples\barcode.png For basic command instructions, type: zbarimg --help + zbarcam --help Check the manual for more details. diff --git a/zbar.nsi b/zbar.nsi index ce2fb12..4b00592 100644 --- a/zbar.nsi +++ b/zbar.nsi @@ -40,8 +40,11 @@ InstallDirRegKey HKLM ${ZBAR_KEY} "InstallDir" !define SMPROG_ZBAR "$SMPROGRAMS\ZBar Bar Code Reader" +Icon ${NSISDIR}\Contrib\Graphics\Icons\orange-install.ico +UninstallIcon ${NSISDIR}\Contrib\Graphics\Icons\orange-uninstall.ico + # do we need admin to install DLL and uninstall info? -RequestExecutionLevel admin +#RequestExecutionLevel admin !include "MUI2.nsh" @@ -59,15 +62,17 @@ Function .onInit MessageBox MB_OKCANCEL|MB_ICONSTOP \ "ImageMagick was not found in your PATH!$\n\ $\n\ - The zbarimg program will not be able to scan image files \ - unless you install ImageMagick$\n\ + The zbarimg program will not be able to scan image files $\n\ + unless you install ImageMagick (http://www.imagemagick.org)$\n\ $\n\ See the README for more details$\n\ $\n\ Press OK to continue anyway...$\n\ Press Cancel to abort the installation..." \ - /SD IDCANCEL \ + /SD IDOK \ IDOK goinstall + + ExecShell "open" "http://www.imagemagick.org/" Abort goinstall: FunctionEnd @@ -138,13 +143,24 @@ Section "ZBar Core Files (required)" SecCore FileWrite $0 "@rem Add the ZBar installation directory to the path$\n" FileWrite $0 "@rem so programs may be run from the command prompt$\n" FileWrite $0 "@set PATH=%PATH%;$INSTDIR\bin$\n" + FileWrite $0 "@cd /D $INSTDIR$\n" FileWrite $0 "@echo For basic command instructions type:$\n" + FileWrite $0 "@echo zbarcam --help$\n" FileWrite $0 "@echo zbarimg --help$\n" + FileWrite $0 "@echo Try running:$\n" + FileWrite $0 "@echo zbarimg -d examples\barcode.png$\n" FileClose $0 SetOutPath $INSTDIR\bin File bin\libzbar-0.dll File bin\zbarimg.exe + File bin\zbarcam.exe + + FileOpen $0 zbarcam.bat w + FileWrite $0 "@set PATH=%PATH%;$INSTDIR\bin$\n" + FileWrite $0 "@zbarcam.exe$\n" + FileWrite $0 "@pause$\n" + FileClose $0 SetOutPath $INSTDIR\doc File share\doc\zbar\html\* @@ -154,17 +170,19 @@ Section "ZBar Core Files (required)" SecCore SectionEnd #SectionGroup "Start Menu and Desktop Shortcuts" SecShortcuts - Section "Start Menu Shortcut" SecShortcutsStartMenu - DetailPrint "Creating Start Menu Shortcut..." + Section "Start Menu Shortcuts" SecShortcutsStartMenu + DetailPrint "Creating Start Menu Shortcuts..." SectionIn 1 2 - SetOutPath $INSTDIR + SetOutPath "${SMPROG_ZBAR}" #CreateShortCut "${SMPROG_ZBAR}\ZBar.lnk" "$INSTDIR\ZBar.exe" CreateDirectory "${SMPROG_ZBAR}" + CreateShortCut "zbarcam.lnk" "$\"$INSTDIR\bin\zbarcam.bat$\"" "" \ + "$INSTDIR\bin\zbarcam.exe" ExpandEnvStrings $0 '%comspec%' - CreateShortCut "${SMPROG_ZBAR}\Start ZBar Command Prompt.lnk" \ + CreateShortCut "Start ZBar Command Prompt.lnk" \ $0 "/k $\"$\"$INSTDIR\zbarvars.bat$\"$\"" $0 - CreateShortCut "${SMPROG_ZBAR}\Command Reference.lnk" \ - "$\"$INSTDIR\doc\zbarimg.html$\"" + CreateShortCut "Command Reference.lnk" \ + "$\"$INSTDIR\doc\ref.html$\"" SectionEnd # Section "Desktop Shortcut" SecShortcutsDesktop @@ -215,7 +233,7 @@ Section -post WriteRegStr HKLM ${UNINSTALL_KEY} "InstallLocation" "$\"$INSTDIR$\"" WriteRegStr HKLM ${UNINSTALL_KEY} "DisplayName" "ZBar Bar Code Reader" - WriteRegStr HKLM ${UNINSTALL_KEY} "DisplayIcon" "$INSTDIR\zbarimg.exe,0" + WriteRegStr HKLM ${UNINSTALL_KEY} "DisplayIcon" "$INSTDIR\bin\zbarimg.exe,0" WriteRegStr HKLM ${UNINSTALL_KEY} "DisplayVersion" "${VERSION}" WriteRegStr HKLM ${UNINSTALL_KEY} "URLInfoAbout" "http://zbar.sf.net/" diff --git a/zbar/Makefile.am.inc b/zbar/Makefile.am.inc index 931cb23..0a3ccd5 100644 --- a/zbar/Makefile.am.inc +++ b/zbar/Makefile.am.inc @@ -39,7 +39,7 @@ zbar_libzbar_la_SOURCES += zbar/processor/win.c zbar/libzbar.rc zbar_libzbar_la_CPPFLAGS += -mthreads zbar_libzbar_la_LDFLAGS += -mthreads # FIXME broken -#zbar_libzbar_la_LIBADD += zbar/libzbar-rc.lo +zbar_libzbar_la_LIBADD += zbar/libzbar-rc.lo endif if HAVE_V4L1 diff --git a/zbar/video/vfw.c b/zbar/video/vfw.c index af3e4d0..e7758ea 100644 --- a/zbar/video/vfw.c +++ b/zbar/video/vfw.c @@ -116,7 +116,7 @@ static ZTHREAD vfw_capture_thread (void *arg) thr->running = 0; _zbar_event_trigger(&thr->activity); _zbar_mutex_unlock(&vdo->qlock); - return(rc); + return(0); } static LRESULT CALLBACK vfw_stream_cb (HWND hwnd, diff --git a/zbarcam/Makefile.am.inc b/zbarcam/Makefile.am.inc index ebc369d..ea869bc 100644 --- a/zbarcam/Makefile.am.inc +++ b/zbarcam/Makefile.am.inc @@ -3,3 +3,8 @@ zbarcam_zbarcam_SOURCES = zbarcam/zbarcam.c zbarcam_zbarcam_LDADD = zbar/libzbar.la # automake bug in "monolithic mode"? CLEANFILES += zbarcam/.libs/zbarcam + +if WIN32 +zbarcam_zbarcam_SOURCES += zbarcam/zbarcam.rc +zbarcam_zbarcam_LDADD += zbarcam/zbarcam-rc.o +endif diff --git a/zbarcam/zbarcam.rc b/zbarcam/zbarcam.rc new file mode 100644 index 0000000..3877915 --- /dev/null +++ b/zbarcam/zbarcam.rc @@ -0,0 +1,30 @@ +#include +#include + +VS_VERSION_INFO VERSIONINFO + FILEVERSION ZBAR_VERSION_MAJOR, ZBAR_VERSION_MINOR, 0, 0 + PRODUCTVERSION ZBAR_VERSION_MAJOR, ZBAR_VERSION_MINOR, 0, 0 + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP +{ + BLOCK "StringFileInfo" { + BLOCK "040904E4" { + VALUE "ProductName", "ZBar Bar Code Reader" + VALUE "Company Name", "ZBar Bar Code Reader" + VALUE "InternalName", "zbarcam" + VALUE "OriginalFilename", "zbarcam.exe" + + VALUE "FileVersion", PACKAGE_VERSION + VALUE "ProductVersion", PACKAGE_VERSION + + VALUE "FileDescription", "Scan bar codes from video devices" + + VALUE "LegalCopyright", "Copyright 2007-2009 (c) Jeff Brown " + } + } + BLOCK "VarFileInfo" { + VALUE "Translation", 0x0409, 0x04e4 + } +} + +APP_ICON ICON "zbar.ico" From 0b3264df3f20c05e7c24fde52818c986450bbb15 Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 16 Aug 2009 21:14:24 -0400 Subject: [PATCH 115/328] change default image scanner density to 1x1 - random cleanup, vfw hang, quit key - fix scan_image example MSVC project - windows installer tweaks --- ChangeLog | 4 ++++ examples/scan_image.cpp | 8 ++++++++ examples/scan_image.vcproj | 10 +++++----- zbar.nsi | 16 +++++++++++----- zbar/img_scanner.c | 4 ++-- zbar/processor.c | 12 +++++++----- zbar/video/vfw.c | 30 ++++++++++++++---------------- zbarcam/zbarcam.c | 4 ++-- 8 files changed, 53 insertions(+), 35 deletions(-) diff --git a/ChangeLog b/ChangeLog index 74d5c73..eae3e03 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,8 @@ current: + * change default image scanner density to 1x1 + - random cleanup, vfw hang, quit key + - fix scan_image example MSVC project + - windows installer tweaks * add zbarcam to windows installer * major restructuring to improve platform abstraction - add lock, thread and timer abstractions diff --git a/examples/scan_image.cpp b/examples/scan_image.cpp index 18a65a3..555fb25 100644 --- a/examples/scan_image.cpp +++ b/examples/scan_image.cpp @@ -1,6 +1,7 @@ #include #include #include +#define STR(s) #s using namespace std; using namespace zbar; @@ -9,6 +10,13 @@ int main (int argc, char **argv) { if(argc < 2) return(1); +#ifdef MAGICK_HOME + // http://www.imagemagick.org/Magick++/ + // under Windows it is necessary to initialize the ImageMagick + // library prior to using the Magick++ library + Magick::InitializeMagick(MAGICK_HOME); +#endif + // create a reader ImageScanner scanner; diff --git a/examples/scan_image.vcproj b/examples/scan_image.vcproj index 1b2b64b..37937de 100644 --- a/examples/scan_image.vcproj +++ b/examples/scan_image.vcproj @@ -13,21 +13,21 @@ video); _zbar_mutex_lock(&proc->mutex); - if(!img) + if(!img && !proc->streaming) + continue; + else if(!img) /* FIXME could abort streaming and keep running? */ break; @@ -546,7 +545,9 @@ int zbar_processor_set_active (zbar_processor_t *proc, rc = zbar_video_enable(proc->video, active); if(!rc) { + _zbar_mutex_lock(&proc->mutex); proc->streaming = active; + _zbar_mutex_unlock(&proc->mutex); rc = _zbar_processor_enable(proc); } else @@ -559,7 +560,8 @@ int zbar_processor_set_active (zbar_processor_t *proc, } _zbar_mutex_lock(&proc->mutex); - _zbar_event_trigger(&proc->video_thread.notify); + if(proc->video_thread.started) + _zbar_event_trigger(&proc->video_thread.notify); done: proc_leave(proc); diff --git a/zbar/video/vfw.c b/zbar/video/vfw.c index e7758ea..d3d4357 100644 --- a/zbar/video/vfw.c +++ b/zbar/video/vfw.c @@ -219,11 +219,8 @@ static int vfw_stop (zbar_video_t *vdo) "stopping video stream")); _zbar_mutex_lock(&vdo->qlock); - zbar_image_t *img = state->image; - if(img) { + if(state->image) state->image = NULL; - zbar_image_destroy(img); - } SetEvent(state->captured); _zbar_mutex_unlock(&vdo->qlock); return(0); @@ -264,13 +261,15 @@ static int vfw_set_format (zbar_video_t *vdo, if(!capSetVideoFormat(vdo->state->hwnd, bih, vdo->state->bi_size)) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, - "setting format")); + "setting video format")); if(!capGetVideoFormat(vdo->state->hwnd, bih, vdo->state->bi_size)) - return(-1/*FIXME*/); + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, + "getting video format")); if(bih->biCompression != fmt) - return(-1/*FIXME*/); + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, + "video format set ignored")); vdo->format = fmt; vdo->width = bih->biWidth; @@ -404,17 +403,15 @@ static int vfw_probe_format (zbar_video_t *vdo, static int vfw_probe (zbar_video_t *vdo) { video_state_t *state = vdo->state; - if(!capSetUserData(state->hwnd, (LONG)vdo)) - return(-1/*FIXME*/); - state->bi_size = capGetVideoFormatSize(state->hwnd); - if(!state->bi_size) - return(-1/*FIXME*/); - BITMAPINFOHEADER *bih = state->bih = realloc(state->bih, state->bi_size); /* FIXME check OOM */ - if(!capGetVideoFormat(state->hwnd, bih, state->bi_size)) - return(-1/*FIXME*/); + + if(!capSetUserData(state->hwnd, (LONG)vdo) || + !state->bi_size || !bih || + !capGetVideoFormat(state->hwnd, bih, state->bi_size)) + return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, + "setting up video capture")); zprintf(3, "initial format: " BIH_FMT " (bisz=%x)\n", BIH_FIELDS(bih), state->bi_size); @@ -496,7 +493,8 @@ int _zbar_video_open (zbar_video_t *vdo, if(!capDriverConnect(state->hwnd, devid)) { _zbar_thread_stop(&state->thread, NULL); - return(-1/*FIXME error: failed to connect to camera*/); + return(err_capture_str(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, + "failed to connect to camera '%s'", dev)); } zprintf(1, "opened camera: %.60s (%d) (thr=%04lx)\n", diff --git a/zbarcam/zbarcam.c b/zbarcam/zbarcam.c index df76c90..0bf712a 100644 --- a/zbarcam/zbarcam.c +++ b/zbarcam/zbarcam.c @@ -246,7 +246,7 @@ int main (int argc, const char *argv[]) /* let the callback handle data */ int rc; while((rc = zbar_processor_user_wait(proc, -1)) >= 0) { - if(rc == 'q') + if(rc == 'q' || rc == 'Q') break; if(rc == ' ') { active = !active; @@ -256,7 +256,7 @@ int main (int argc, const char *argv[]) } /* report any errors that aren't "window closed" */ - if(rc && rc != 'q' && + if(rc && rc != 'q' && rc != 'Q' && zbar_processor_get_error_code(proc) != ZBAR_ERR_CLOSED) return(zbar_processor_error_spew(proc, 0)); From e2de540d6cee643f8e8d0404bff879648deef1d9 Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 18 Aug 2009 19:23:26 -0400 Subject: [PATCH 116/328] more testing, fixes and cleanup - fix v4l1 - fix/add null processor interface --- ChangeLog | 3 ++ Makefile.am | 4 +-- configure.ac | 1 - include/zbar/Decoder.h | 14 ++++++--- include/zbar/Symbol.h | 11 +++++-- perl/t/Image.t | 2 +- perl/t/Processor.t | 2 +- python/test/test_zbar.py | 2 +- test/test_proc.c | 2 +- zbar/Makefile.am.inc | 9 +++--- zbar/img_scanner.c | 8 +++--- zbar/processor.c | 19 ++++++------ zbar/processor/lock.c | 3 +- zbar/processor/null.c | 62 ++++++++++++++++++++++++++++++++++++++++ zbar/processor/posix.c | 7 +++-- zbar/timer.h | 6 ++++ zbar/video.c | 19 ++++++------ zbar/video.h | 5 ---- zbar/video/v4l1.c | 15 ++++------ zbar/video/v4l2.c | 18 +++++------- zbar/video/vfw.c | 58 ++++++++++++++----------------------- zbar/window/null.c | 36 ++--------------------- zbar/window/x.c | 5 ++-- zbarimg/zbarimg.c | 3 ++ 24 files changed, 171 insertions(+), 143 deletions(-) create mode 100644 zbar/processor/null.c diff --git a/ChangeLog b/ChangeLog index eae3e03..0f0f9c8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,7 @@ current: + * more testing, fixes and cleanup + - fix v4l1 + - fix/add null processor interface * change default image scanner density to 1x1 - random cleanup, vfw hang, quit key - fix scan_image example MSVC project diff --git a/Makefile.am b/Makefile.am index e4403c2..0524e5b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -45,12 +45,12 @@ endif include $(srcdir)/test/Makefile.am.inc include $(srcdir)/doc/Makefile.am.inc -EXTRA_DIST += zbar.spec.in zbar.spec +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/scan_image.c examples/scan_image.cpp examples/scan_image.pl \ - examples/scan_image.py + examples/scan_image.py 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 \ diff --git a/configure.ac b/configure.ac index 2e02509..dc22223 100644 --- a/configure.ac +++ b/configure.ac @@ -411,7 +411,6 @@ Makefile zbar.pc zbar-gtk.pc zbar-qt.pc -zbar.spec doc/doxygen.conf ]) AC_OUTPUT diff --git a/include/zbar/Decoder.h b/include/zbar/Decoder.h index 2c5ce78..4900e7c 100644 --- a/include/zbar/Decoder.h +++ b/include/zbar/Decoder.h @@ -127,18 +127,24 @@ class Decoder { return(zbar_decoder_get_data(_decoder)); } - /// retrieve last decoded data in ASCII format as a std::string. + /// retrieve last decoded data as a std::string. /// see zbar_decoder_get_data() const std::string get_data_string() const { - return(zbar_decoder_get_data(_decoder)); + return(std::string(zbar_decoder_get_data(_decoder), + zbar_decoder_get_data_length(_decoder))); } - /// retrieve last decoded data in ASCII format as a std::string. + /// retrieve last decoded data as a std::string. /// see zbar_decoder_get_data() const std::string get_data() const { - return(zbar_decoder_get_data(_decoder)); + return(get_data_string()); + } + + int get_data_length() const + { + return(zbar_decoder_get_data_length(_decoder)); } /// setup callback to handle result data. diff --git a/include/zbar/Symbol.h b/include/zbar/Symbol.h index 8925db0..8fde92b 100644 --- a/include/zbar/Symbol.h +++ b/include/zbar/Symbol.h @@ -138,7 +138,8 @@ class Symbol { _sym = sym; if(sym) { _type = zbar_symbol_get_type(sym); - _data = zbar_symbol_get_data(sym); + _data = std::string(zbar_symbol_get_data(sym), + zbar_symbol_get_data_length(sym)); _count = zbar_symbol_get_count(sym); } else { @@ -184,12 +185,18 @@ class Symbol { return(zbar_get_addon_name(_type)); } - /// retrieve ASCII data decoded from symbol. + /// retrieve data decoded from symbol. const std::string get_data () const { return(_data); } + /// retrieve length of binary data + unsigned get_data_length () const + { + return(zbar_symbol_get_data_length(_sym)); + } + /// retrieve inter-frame coherency count. /// see zbar_symbol_get_count() /// @since 1.5 diff --git a/perl/t/Image.t b/perl/t/Image.t index 86f5ceb..9067434 100755 --- a/perl/t/Image.t +++ b/perl/t/Image.t @@ -94,7 +94,7 @@ SKIP: { ######################### my @loc = $sym->get_loc(); - is(scalar(@loc), 4, 'location size'); + ok(scalar(@loc) >= 4, 'location size'); ######################### diff --git a/perl/t/Processor.t b/perl/t/Processor.t index 12e0c12..b936c3e 100755 --- a/perl/t/Processor.t +++ b/perl/t/Processor.t @@ -64,7 +64,7 @@ $proc->set_data_handler(sub { ######################### my @loc = $sym->get_loc(); - is(scalar(@loc), 4, 'location size'); + ok(scalar(@loc) >= 4, 'location size'); # structure checked by Image.t diff --git a/python/test/test_zbar.py b/python/test/test_zbar.py index b556d74..c5c3124 100755 --- a/python/test/test_zbar.py +++ b/python/test/test_zbar.py @@ -249,7 +249,7 @@ def test_scan(self): self.assertEqual(data, '9876543210128') loc = sym.location - self.assertEqual(len(loc), 4) + self.assert_(len(loc) >= 4) # FIXME self.assert_(isinstance(loc, tuple)) for pt in loc: self.assert_(isinstance(pt, tuple)) diff --git a/test/test_proc.c b/test/test_proc.c index 172a89a..e81b968 100644 --- a/test/test_proc.c +++ b/test/test_proc.c @@ -60,7 +60,7 @@ int input_wait (int timeout) int main (int argc, char **argv) { - zbar_set_verbosity(31); + zbar_set_verbosity(127); char *video_dev = NULL; uint32_t fmt = 0; int i, j = 0; diff --git a/zbar/Makefile.am.inc b/zbar/Makefile.am.inc index 0a3ccd5..be04c1e 100644 --- a/zbar/Makefile.am.inc +++ b/zbar/Makefile.am.inc @@ -31,15 +31,14 @@ zbar_libzbar_la_SOURCES += zbar/decoder/pdf417.h zbar/decoder/pdf417.c \ zbar/decoder/pdf417_hash.h endif -if HAVE_POLL -zbar_libzbar_la_SOURCES += zbar/processor/posix.h zbar/processor/posix.c -endif if WIN32 zbar_libzbar_la_SOURCES += zbar/processor/win.c zbar/libzbar.rc zbar_libzbar_la_CPPFLAGS += -mthreads zbar_libzbar_la_LDFLAGS += -mthreads # FIXME broken zbar_libzbar_la_LIBADD += zbar/libzbar-rc.lo +else +zbar_libzbar_la_SOURCES += zbar/processor/posix.h zbar/processor/posix.c endif if HAVE_V4L1 @@ -64,7 +63,7 @@ endif if HAVE_X zbar_libzbar_la_SOURCES += zbar/processor/x.c \ - zbar/window/x.c zbar/window/ximage.c + zbar/window/x.h zbar/window/x.c zbar/window/ximage.c zbar_libzbar_la_CPPFLAGS += $(X_CFLAGS) zbar_libzbar_la_LDFLAGS += $(X_LIBS) zbar_libzbar_la_LIBADD += $(X_PRE_LIBS) -lX11 $(X_EXTRA_LIBS) @@ -79,7 +78,7 @@ zbar_libzbar_la_SOURCES += zbar/window/win.h zbar/window/win.c \ # zbar/window/vfw.c -lvfw32 zbar_libzbar_la_LIBADD += -lgdi32 -lwinmm else -zbar_libzbar_la_SOURCES += zbar/window/null.c +zbar_libzbar_la_SOURCES += zbar/processor/null.c zbar/window/null.c endif endif diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index b2c9c30..f071b32 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -377,7 +377,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, symbol_handler(iscn, x, y); while(y < h) { - zprintf(32, "img_x+: %03x,%03x @%p\n", x, y, p); + zprintf(128, "img_x+: %03x,%03x @%p\n", x, y, p); while(x < w) { ASSERT_POS; if(zbar_scan_y(iscn->scn, *p)) @@ -390,7 +390,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, if(y >= h) break; - zprintf(32, "img_x-: %03x,%03x @%p\n", x, y, p); + zprintf(128, "img_x-: %03x,%03x @%p\n", x, y, p); while(x > 0) { ASSERT_POS; if(zbar_scan_y(iscn->scn, *p)) @@ -414,7 +414,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, movedelta(border, 0); while(x < w) { - zprintf(32, "img_y+: %03x,%03x @%p\n", x, y, p); + zprintf(128, "img_y+: %03x,%03x @%p\n", x, y, p); while(y < h) { ASSERT_POS; if(zbar_scan_y(iscn->scn, *p)) @@ -427,7 +427,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, if(x >= w) break; - zprintf(32, "img_y-: %03x,%03x @%p\n", x, y, p); + zprintf(128, "img_y-: %03x,%03x @%p\n", x, y, p); while(y >= 0) { ASSERT_POS; if(zbar_scan_y(iscn->scn, *p)) diff --git a/zbar/processor.c b/zbar/processor.c index 9cf7719..3ce57bd 100644 --- a/zbar/processor.c +++ b/zbar/processor.c @@ -52,18 +52,19 @@ static inline int proc_open (zbar_processor_t *proc) int _zbar_process_image (zbar_processor_t *proc, zbar_image_t *img) { + uint32_t force_fmt = proc->force_output; if(img) { + if(proc->dumping) { + zbar_image_write(proc->window->image, "zbar"); + proc->dumping = 0; + } + uint32_t format = zbar_image_get_format(img); zprintf(16, "processing: %.4s(%08" PRIx32 ") %dx%d @%p\n", (char*)&format, format, zbar_image_get_width(img), zbar_image_get_height(img), zbar_image_get_data(img)); - if(proc->dumping) { - zbar_image_write(proc->window->image, "zbar"); - proc->dumping = 0; - } - /* FIXME locking all other interfaces while processing is conservative * but easier for now and we don't expect this to take long... */ @@ -88,16 +89,16 @@ int _zbar_process_image (zbar_processor_t *proc, } if(nsyms) { + /* FIXME only call after filtering */ _zbar_mutex_lock(&proc->mutex); _zbar_processor_notify(proc, EVENT_OUTPUT); _zbar_mutex_unlock(&proc->mutex); if(proc->handler) - /* FIXME only call after filtering */ proc->handler(img, proc->userdata); } - if(proc->force_output) { - img = zbar_image_convert(img, proc->force_output); + if(force_fmt) { + img = zbar_image_convert(img, force_fmt); if(!img) return(err_capture(proc, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "unknown image format")); @@ -110,7 +111,7 @@ int _zbar_process_image (zbar_processor_t *proc, _zbar_processor_invalidate(proc))) return(err_copy(proc, proc->window)); - if(proc->force_output && img) + if(force_fmt && img) zbar_image_destroy(img); return(0); } diff --git a/zbar/processor/lock.c b/zbar/processor/lock.c index 6722b07..df0fdc6 100644 --- a/zbar/processor/lock.c +++ b/zbar/processor/lock.c @@ -170,7 +170,7 @@ static inline int proc_wait_unthreaded (zbar_processor_t *proc, zbar_image_destroy(img); _zbar_mutex_unlock(&proc->mutex); } - int reltime = (timeout) ? _zbar_timer_check(timeout) : -1; + int reltime = _zbar_timer_check(timeout); if(blocking && (reltime < 0 || reltime > MAX_INPUT_BLOCK)) reltime = MAX_INPUT_BLOCK; rc = _zbar_processor_input_wait(proc, NULL, reltime); @@ -214,4 +214,3 @@ int _zbar_processor_wait (zbar_processor_t *proc, _zbar_mutex_unlock(&proc->mutex); return(rc); } - diff --git a/zbar/processor/null.c b/zbar/processor/null.c new file mode 100644 index 0000000..86a62a9 --- /dev/null +++ b/zbar/processor/null.c @@ -0,0 +1,62 @@ +/*------------------------------------------------------------------------ + * Copyright 2008-2009 (c) Jeff Brown + * + * 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 "processor.h" + +static inline int null_error (void *m, + const char *func) +{ + return(err_capture(m, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, func, + "not compiled with output window support")); +} + +int _zbar_processor_open (zbar_processor_t *proc, + char *name, + unsigned w, + unsigned h) +{ + return(null_error(proc, __func__)); +} + +int _zbar_processor_close (zbar_processor_t *proc) +{ + return(null_error(proc, __func__)); +} + +int _zbar_processor_set_visible (zbar_processor_t *proc, + int vis) +{ + return(null_error(proc, __func__)); +} + +int _zbar_processor_set_size (zbar_processor_t *proc, + unsigned width, + unsigned height) +{ + return(null_error(proc, __func__)); +} + +int _zbar_processor_invalidate (zbar_processor_t *proc) +{ + return(null_error(proc, __func__)); +} diff --git a/zbar/processor/posix.c b/zbar/processor/posix.c index 011e52e..203c1b7 100644 --- a/zbar/processor/posix.c +++ b/zbar/processor/posix.c @@ -192,13 +192,14 @@ static inline int proc_poll_inputs (zbar_processor_t *proc, /* FIXME detect and handle fatal errors (somehow) */ return(rc); int i; - for(i = 0; i < p->num; i++) + for(i = p->num - 1; i >= 0; i--) if(p->fds[i].revents) { if(p->handlers[i]) p->handlers[i](proc, i); p->fds[i].revents = 0; /* debug */ rc--; } + assert(!rc); return(1); } @@ -281,8 +282,8 @@ int _zbar_processor_cleanup (zbar_processor_t *proc) int _zbar_processor_enable (zbar_processor_t *proc) { - int vid_fd = zbar_video_get_fd(proc->video); - if(vid_fd >= 0) { + int vid_fd; + if(proc->threaded && ((vid_fd = zbar_video_get_fd(proc->video)) >= 0)) { if(proc->streaming) add_poll(proc, vid_fd, proc_video_handler); else diff --git a/zbar/timer.h b/zbar/timer.h index b7492ff..3f33f29 100644 --- a/zbar/timer.h +++ b/zbar/timer.h @@ -56,6 +56,9 @@ static inline zbar_timer_t *_zbar_timer_init (zbar_timer_t *timer, static inline int _zbar_timer_check (zbar_timer_t *timer) { + if(!timer) + return(-1); + struct timespec now; clock_gettime(CLOCK_REALTIME, &now); int delay = ((timer->tv_sec - now.tv_sec) * 1000 + @@ -109,6 +112,9 @@ static inline zbar_timer_t *_zbar_timer_init (zbar_timer_t *timer, static inline int _zbar_timer_check (zbar_timer_t *timer) { + if(!timer) + return(-1); + struct timeval now; gettimeofday(&now, NULL); return((timer->tv_sec - now.tv_sec) * 1000 + diff --git a/zbar/video.c b/zbar/video.c index 1669795..130cc58 100644 --- a/zbar/video.c +++ b/zbar/video.c @@ -35,13 +35,13 @@ static void _zbar_video_recycle_image (zbar_image_t *img) zbar_video_t *vdo = img->src; assert(vdo); assert(img->srcidx >= 0); - (void)video_lock(vdo); + video_lock(vdo); if(vdo->images[img->srcidx] != img) vdo->images[img->srcidx] = img; if(vdo->active) vdo->nq(vdo, img); else - (void)video_unlock(vdo); + video_unlock(vdo); } static void _zbar_video_recycle_shadow (zbar_image_t *img) @@ -49,10 +49,10 @@ static void _zbar_video_recycle_shadow (zbar_image_t *img) zbar_video_t *vdo = img->src; assert(vdo); assert(img->srcidx == -1); - (void)video_lock(vdo); + video_lock(vdo); img->next = vdo->shadow_image; vdo->shadow_image = img; - (void)video_unlock(vdo); + video_unlock(vdo); } zbar_video_t *zbar_video_create () @@ -165,7 +165,7 @@ int zbar_video_get_fd (const zbar_video_t *vdo) if(vdo->intf == VIDEO_INVALID) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "video device not opened")); - if(vdo->fd < 0) + if(vdo->intf != VIDEO_V4L2) return(err_capture(vdo, SEV_WARNING, ZBAR_ERR_UNSUPPORTED, __func__, "video driver does not support polling")); return(vdo->fd); @@ -336,11 +336,10 @@ zbar_image_t *zbar_video_next_image (zbar_video_t *vdo) if(video_lock(vdo)) return(NULL); if(!vdo->active) { - err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, - "video not enabled"); - (void)video_unlock(vdo); + video_unlock(vdo); return(NULL); } + unsigned frame = vdo->frame++; zbar_image_t *img = vdo->dq(vdo); if(img) { @@ -350,10 +349,10 @@ zbar_image_t *zbar_video_next_image (zbar_video_t *vdo) * the driver's buffer to avoid deadlocking the resources */ zbar_image_t *tmp = img; - (void)video_lock(vdo); + video_lock(vdo); img = vdo->shadow_image; vdo->shadow_image = (img) ? img->next : NULL; - (void)video_unlock(vdo); + video_unlock(vdo); if(!img) { img = zbar_image_create(); diff --git a/zbar/video.h b/zbar/video.h index 6585c2c..801f9da 100644 --- a/zbar/video.h +++ b/zbar/video.h @@ -150,11 +150,6 @@ static inline zbar_image_t *video_dq_image (zbar_video_t *vdo) if(video_unlock(vdo)) /* FIXME reclaim image */ return(NULL); - - if(!img) - /* FIXME block until available? */ - err_capture(vdo, SEV_ERROR, ZBAR_ERR_BUSY, __func__, - "all allocated video images busy"); return(img); } diff --git a/zbar/video/v4l1.c b/zbar/video/v4l1.c index b26f21f..89b1da2 100644 --- a/zbar/video/v4l1.c +++ b/zbar/video/v4l1.c @@ -105,23 +105,20 @@ static int v4l1_nq (zbar_video_t *vdo, static zbar_image_t *v4l1_dq (zbar_video_t *vdo) { + video_iomode_t iomode = vdo->iomode; + int fd = vdo->fd; zbar_image_t *img = video_dq_image(vdo); if(!img) return(NULL); - if(vdo->iomode == VIDEO_MMAP) { + if(iomode == VIDEO_MMAP) { int frame = img->srcidx; - if(ioctl(vdo->fd, VIDIOCSYNC, &frame) < 0) { - err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, - "capturing video image (VIDIOCSYNC)"); + if(ioctl(fd, VIDIOCSYNC, &frame) < 0) return(NULL); - } } - else if(read(vdo->fd, (void*)img->data, img->datalen) != img->datalen) { - err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, - "reading video image"); + else if(read(fd, (void*)img->data, img->datalen) != img->datalen) return(NULL); - } + return(img); } diff --git a/zbar/video/v4l2.c b/zbar/video/v4l2.c index a27ce63..ec59bd8 100644 --- a/zbar/video/v4l2.c +++ b/zbar/video/v4l2.c @@ -76,26 +76,25 @@ static int v4l2_nq (zbar_video_t *vdo, static zbar_image_t *v4l2_dq (zbar_video_t *vdo) { zbar_image_t *img; + int fd = vdo->fd; if(vdo->iomode != VIDEO_READWRITE) { + video_iomode_t iomode = vdo->iomode; if(video_unlock(vdo)) return(NULL); struct v4l2_buffer vbuf; memset(&vbuf, 0, sizeof(vbuf)); vbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if(vdo->iomode == VIDEO_MMAP) + if(iomode == VIDEO_MMAP) vbuf.memory = V4L2_MEMORY_MMAP; else vbuf.memory = V4L2_MEMORY_USERPTR; - if(ioctl(vdo->fd, VIDIOC_DQBUF, &vbuf) < 0) { - err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, - "dequeuing video buffer (VIDIOC_DQBUF)"); + if(ioctl(fd, VIDIOC_DQBUF, &vbuf) < 0) return(NULL); - } - if(vdo->iomode == VIDEO_MMAP) { + if(iomode == VIDEO_MMAP) { assert(vbuf.index >= 0); assert(vbuf.index < vdo->num_images); img = vdo->images[vbuf.index]; @@ -117,12 +116,9 @@ static zbar_image_t *v4l2_dq (zbar_video_t *vdo) return(NULL); /* FIXME should read entire image */ - unsigned long datalen = read(vdo->fd, (void*)img->data, img->datalen); - if(datalen < 0) { - err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, - "reading video image"); + unsigned long datalen = read(fd, (void*)img->data, img->datalen); + if(datalen < 0) return(NULL); - } else if(datalen != img->datalen) zprintf(0, "WARNING: read() size mismatch: 0x%lx != 0x%lx\n", datalen, img->datalen); diff --git a/zbar/video/vfw.c b/zbar/video/vfw.c index d3d4357..7e46bf0 100644 --- a/zbar/video/vfw.c +++ b/zbar/video/vfw.c @@ -100,15 +100,16 @@ static ZTHREAD vfw_capture_thread (void *arg) int rc = 0; while(thr->started && rc >= 0 && rc <= 1) { _zbar_mutex_unlock(&vdo->qlock); + rc = MsgWaitForMultipleObjects(1, &thr->notify, 0, INFINITE, QS_ALLINPUT); - if(rc == 1) { - rc = PeekMessage(&msg, NULL, 0, 0, PM_NOYIELD | PM_REMOVE); - if(rc > 0) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } + if(rc == 1) + while(PeekMessage(&msg, NULL, 0, 0, PM_NOYIELD | PM_REMOVE)) + if(rc > 0) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + _zbar_mutex_lock(&vdo->qlock); } @@ -126,10 +127,10 @@ static LRESULT CALLBACK vfw_stream_cb (HWND hwnd, return(0); zbar_video_t *vdo = (void*)capGetUserData(hwnd); - video_lock(vdo); + _zbar_mutex_lock(&vdo->qlock); zbar_image_t *img = vdo->state->image; if(!img) { - video_lock(vdo); + _zbar_mutex_lock(&vdo->qlock); img = video_dq_image(vdo); } if(img) { @@ -138,25 +139,8 @@ static LRESULT CALLBACK vfw_stream_cb (HWND hwnd, vdo->state->image = img; SetEvent(vdo->state->captured); } - video_unlock(vdo); - - return(1); -} + _zbar_mutex_unlock(&vdo->qlock); -static LRESULT CALLBACK vfw_control_cb (HWND hwnd, - int state) -{ - if(!hwnd) - return(0); -#if 0 - zbar_video_t *vdo = (void*)capGetUserData(hwnd); - switch(state) { - case CONTROLCALLBACK_PREROLL: - break; - case CONTROLCALLBACK_CAPTURING: - break; - } -#endif return(1); } @@ -167,8 +151,11 @@ static LRESULT CALLBACK vfw_error_cb (HWND hwnd, if(!hwnd) return(0); zbar_video_t *vdo = (void*)capGetUserData(hwnd); - zprintf(2, "thr=%04lx vdo=%p id=%d msg=%s\n", - GetCurrentThreadId(), vdo, errid, errmsg); + zprintf(2, "id=%d msg=%s\n", errid, errmsg); + _zbar_mutex_lock(&vdo->qlock); + vdo->state->image = NULL; + SetEvent(vdo->state->captured); + _zbar_mutex_unlock(&vdo->qlock); return(1); } @@ -183,14 +170,15 @@ static int vfw_nq (zbar_video_t *vdo, static zbar_image_t *vfw_dq (zbar_video_t *vdo) { zbar_image_t *img = vdo->state->image; - zbar_thread_t *thr = &vdo->state->thread; - HANDLE status[2] = { vdo->state->captured, thr->activity }; if(!img) { _zbar_mutex_unlock(&vdo->qlock); - int rc = WaitForMultipleObjects(2, status, 0, INFINITE); + int rc = WaitForSingleObject(vdo->state->captured, INFINITE); _zbar_mutex_lock(&vdo->qlock); - img = (!rc) ? vdo->state->image : NULL; - /*FIXME errors */ + if(!rc) + img = vdo->state->image; + else + img = NULL; + /*FIXME handle errors? */ } else ResetEvent(vdo->state->captured); @@ -320,8 +308,6 @@ static int vfw_init (zbar_video_t *vdo, err_capture(vdo, SEV_WARNING, ZBAR_ERR_WINAPI, __func__, "disabling preview"); - capSetCallbackOnCapControl(hwnd, vfw_control_cb); - if(!capSetCallbackOnVideoStream(hwnd, vfw_stream_cb) || !capSetCallbackOnError(hwnd, vfw_error_cb)) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_BUSY, __func__, diff --git a/zbar/window/null.c b/zbar/window/null.c index 0ceab3c..9588747 100644 --- a/zbar/window/null.c +++ b/zbar/window/null.c @@ -42,36 +42,9 @@ int _zbar_window_attach (zbar_window_t *w, return(null_error(w, __func__)); } -int _zbar_window_handle_events (zbar_processor_t *proc, - int block) +int _zbar_window_flush (zbar_window_t *w) { - return(null_error(proc, __func__)); -} - -int _zbar_window_open (zbar_processor_t *proc, - char *title, - unsigned width, - unsigned height) -{ - return(null_error(proc, __func__)); -} - -int _zbar_window_close (zbar_processor_t *proc) -{ - return(null_error(proc, __func__)); -} - -int _zbar_window_set_size (zbar_processor_t *proc, - unsigned width, - unsigned height) -{ - return(null_error(proc, __func__)); -} - -int _zbar_window_set_visible (zbar_processor_t *proc, - int visible) -{ - return(null_error(proc, __func__)); + return(null_error(w, __func__)); } int _zbar_window_clear (zbar_window_t *w) @@ -79,11 +52,6 @@ int _zbar_window_clear (zbar_window_t *w) return(null_error(w, __func__)); } -int _zbar_window_invalidate (zbar_window_t *w) -{ - return(0); -} - int _zbar_window_draw_marker(zbar_window_t *w, uint32_t rgb, const point_t *p) diff --git a/zbar/window/x.c b/zbar/window/x.c index 8a732b9..14b79b7 100644 --- a/zbar/window/x.c +++ b/zbar/window/x.c @@ -77,6 +77,9 @@ static inline int window_hide_cursor (zbar_window_t *w) int _zbar_window_resize (zbar_window_t *w) { window_state_t *x = w->state; + if(!x) + return(0); + int lbw; if(w->height * 8 / 10 <= w->width) lbw = w->height / 36; @@ -179,7 +182,6 @@ int _zbar_window_expose (zbar_window_t *w, int width, int height) { - window_lock(w); window_state_t *xs = w->state; if(!xs->exposed) xs->exposed = XCreateRegion(); @@ -189,7 +191,6 @@ int _zbar_window_expose (zbar_window_t *w, r.width = width; r.height = height; XUnionRectWithRegion(&r, xs->exposed, xs->exposed); - window_unlock(w); return(0); } diff --git a/zbarimg/zbarimg.c b/zbarimg/zbarimg.c index b6d0cc8..646ed04 100644 --- a/zbarimg/zbarimg.c +++ b/zbarimg/zbarimg.c @@ -303,6 +303,9 @@ int main (int argc, const char *argv[]) zbar_processor_error_spew(processor, 0); return(1); } + /* FIXME tmp hack until EAN is more robust */ + zbar_processor_set_config(processor, 0, ZBAR_CFG_X_DENSITY, 16); + zbar_processor_set_config(processor, 0, ZBAR_CFG_Y_DENSITY, 8); for(i = 1; i < argc; i++) { const char *arg = argv[i]; From 074995402fb811297aa5936ad33c9d71bc9c1772 Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 26 Aug 2009 09:12:22 -0400 Subject: [PATCH 117/328] potential fix for display init ordering (bug #2844846) - new workaround for filtering bad EAN results in the image scanner --- ChangeLog | 2 ++ zbar.nsi | 10 ++++++++-- zbar/img_scanner.c | 23 ++++++++++++++++++++++- zbar/processor.c | 3 ++- zbar/window/x.c | 6 ++++++ zbarimg/zbarimg.c | 3 --- 6 files changed, 40 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0f0f9c8..87a1549 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * potential fix for display init ordering (bug #2844846) + - new workaround for filtering bad EAN results in the image scanner * more testing, fixes and cleanup - fix v4l1 - fix/add null processor interface diff --git a/zbar.nsi b/zbar.nsi index b7d7090..b0dee01 100644 --- a/zbar.nsi +++ b/zbar.nsi @@ -161,8 +161,14 @@ Section "ZBar Core Files (required)" SecCore FileOpen $0 zbarcam.bat w FileWrite $0 "@set PATH=%PATH%;$INSTDIR\bin$\n" - FileWrite $0 "@zbarcam.exe$\n" - FileWrite $0 "@pause$\n" + FileWrite $0 "@echo This is the zbarcam output window.$\n" + FileWrite $0 "@echo Hold a bar code in front of the camera (make sure it's in focus!)$\n" + FileWrite $0 "@echo and decoded results will appear below.$\n" + FileWrite $0 "@echo.$\n" + FileWrite $0 "@echo Initializing camera, please wait...$\n" + FileWrite $0 "@echo.$\n" + FileWrite $0 "@zbarcam.exe --prescale=640x480$\n" + FileWrite $0 "@if errorlevel 1 pause$\n" FileClose $0 SetOutPath $INSTDIR\doc diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index f071b32..807d878 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -442,5 +442,26 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, /* release reference to converted image */ zbar_image_destroy(img); - return(iscn->img->nsyms); + img = iscn->img; + iscn->img = NULL; + + /* FIXME tmp hack to filter bad EAN results */ + if(img->nsyms && !iscn->enable_cache && + (density == 1 || CFG(iscn, ZBAR_CFG_Y_DENSITY) == 1)) { + zbar_symbol_t **symp = &img->syms, *sym; + while((sym = *symp)) { + if(sym->type < ZBAR_I25 && sym->type > ZBAR_PARTIAL && + sym->npts < 2) { + /* recycle */ + *symp = sym->next; + iscn->nsyms++; + sym->next = iscn->syms; + iscn->syms = sym; + } + else + symp = &sym->next; + } + } + + return(img->nsyms); } diff --git a/zbar/processor.c b/zbar/processor.c index 3ce57bd..7630156 100644 --- a/zbar/processor.c +++ b/zbar/processor.c @@ -78,10 +78,11 @@ int _zbar_process_image (zbar_processor_t *proc, while(sym) { zbar_symbol_type_t type = zbar_symbol_get_type(sym); int count = zbar_symbol_get_count(sym); - zprintf(8, "%s%s: %s (%s)\n", + zprintf(8, "%s%s: %s (%d pts) (%s)\n", zbar_get_symbol_name(type), zbar_get_addon_name(type), zbar_symbol_get_data(sym), + zbar_symbol_get_loc_size(sym), (count < 0) ? "uncertain" : (count > 0) ? "duplicate" : "new"); sym = zbar_symbol_next(sym); diff --git a/zbar/window/x.c b/zbar/window/x.c index 14b79b7..974be1f 100644 --- a/zbar/window/x.c +++ b/zbar/window/x.c @@ -196,6 +196,9 @@ int _zbar_window_expose (zbar_window_t *w, int _zbar_window_flush (zbar_window_t *w) { + if(!w->display) + return(-1); + window_state_t *x = w->state; XFlush(w->display); XSetClipMask(w->display, x->gc, None); @@ -244,6 +247,9 @@ int _zbar_window_draw_marker(zbar_window_t *w, int _zbar_window_draw_logo (zbar_window_t *w) { + if(!w->display) + return(-1); + window_state_t *x = w->state; if(x->exposed) XSetRegion(w->display, x->gc, x->exposed); diff --git a/zbarimg/zbarimg.c b/zbarimg/zbarimg.c index 646ed04..b6d0cc8 100644 --- a/zbarimg/zbarimg.c +++ b/zbarimg/zbarimg.c @@ -303,9 +303,6 @@ int main (int argc, const char *argv[]) zbar_processor_error_spew(processor, 0); return(1); } - /* FIXME tmp hack until EAN is more robust */ - zbar_processor_set_config(processor, 0, ZBAR_CFG_X_DENSITY, 16); - zbar_processor_set_config(processor, 0, ZBAR_CFG_Y_DENSITY, 8); for(i = 1; i < argc; i++) { const char *arg = argv[i]; From cf7a286b8fce4f944cf11d2f3ceaaf734ec8bf3d Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 26 Aug 2009 10:04:26 -0400 Subject: [PATCH 118/328] finish fix for Qt init ordering (bug #2844846) --- ChangeLog | 1 + qt/QZBar.cpp | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 87a1549..40f3dd7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * finish fix for Qt init ordering (bug #2844846) * potential fix for display init ordering (bug #2844846) - new workaround for filtering bad EAN results in the image scanner * more testing, fixes and cleanup diff --git a/qt/QZBar.cpp b/qt/QZBar.cpp index d4246be..4e8eb9b 100644 --- a/qt/QZBar.cpp +++ b/qt/QZBar.cpp @@ -166,8 +166,14 @@ int QZBar::heightForWidth (int width) const void QZBar::paintEvent (QPaintEvent *) { - if(thread) - thread->window.redraw(); + try { + if(thread) + thread->window.redraw(); + } + catch(Exception) { + // sometimes Qt attempts to paint the widget before it's parented(?) + // just ignore this (can't throw from event anyway) + } } void QZBar::resizeEvent (QResizeEvent *event) From c9a8771138382fde4734032d8bb0b1d89621064e Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 26 Aug 2009 12:43:39 -0400 Subject: [PATCH 119/328] more Qt window creation hook fixes - NB may still cause problems if video is opened before window is visible --- ChangeLog | 2 ++ include/zbar/QZBar.h | 7 +++++-- qt/QZBar.cpp | 21 +++++++++++++++++++-- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 40f3dd7..ccfbd15 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * more Qt window creation hook fixes + - NB may still cause problems if video is opened before window is visible * finish fix for Qt init ordering (bug #2844846) * potential fix for display init ordering (bug #2844846) - new workaround for filtering bad EAN results in the image scanner diff --git a/include/zbar/QZBar.h b/include/zbar/QZBar.h index db6d51d..5f2cb54 100644 --- a/include/zbar/QZBar.h +++ b/include/zbar/QZBar.h @@ -101,6 +101,7 @@ class QZBar : public QWidget QSize sizeHint() const; int heightForWidth(int) const; + QPaintEngine *paintEngine() const; /// @} @@ -143,8 +144,9 @@ public Q_SLOTS: /// @internal protected: - void paintEvent(QPaintEvent *); - void resizeEvent(QResizeEvent *); + void showEvent(QShowEvent*); + void paintEvent(QPaintEvent*); + void resizeEvent(QResizeEvent*); void changeEvent(QEvent*); void dragEnterEvent(QDragEnterEvent*); void dropEvent(QDropEvent*); @@ -158,6 +160,7 @@ protected Q_SLOTS: QZBarThread *thread; QString _videoDevice; bool _videoEnabled; + bool _attached; }; }; diff --git a/qt/QZBar.cpp b/qt/QZBar.cpp index 4e8eb9b..21d4497 100644 --- a/qt/QZBar.cpp +++ b/qt/QZBar.cpp @@ -37,14 +37,18 @@ QZBar::QZBar (QWidget *parent) { setAttribute(Qt::WA_OpaquePaintEvent); setAttribute(Qt::WA_PaintOnScreen); + setAttribute(Qt::WA_NativeWindow); + setAttribute(Qt::WA_DontCreateNativeAncestors); QSizePolicy sizing(QSizePolicy::Preferred, QSizePolicy::Preferred); sizing.setHeightForWidth(true); setSizePolicy(sizing); thread = new QZBarThread; - if(testAttribute(Qt::WA_WState_Created)) + if(testAttribute(Qt::WA_WState_Created)) { thread->window.attach(x11Info().display(), winId()); + _attached = 1; + } connect(thread, SIGNAL(videoOpened(bool)), this, SIGNAL(videoOpened(bool))); connect(this, SIGNAL(videoOpened(bool)), @@ -68,6 +72,11 @@ QZBar::~QZBar () } } +QPaintEngine *QZBar::paintEngine () const +{ + return(NULL); +} + QString QZBar::videoDevice () const { return(_videoDevice); @@ -164,7 +173,7 @@ int QZBar::heightForWidth (int width) const return(width * 3 / 4); } -void QZBar::paintEvent (QPaintEvent *) +void QZBar::paintEvent (QPaintEvent *event) { try { if(thread) @@ -189,6 +198,14 @@ void QZBar::changeEvent(QEvent *event) thread->window.attach(x11Info().display(), winId()); } +void QZBar::showEvent (QShowEvent *event) +{ + if(!_attached) { + thread->window.attach(x11Info().display(), winId()); + _attached = 1; + } +} + void QZBar::sizeChange () { update(); From 23b91cb0b868860c751926ab37cd4d1cca268d66 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 27 Aug 2009 11:34:06 -0400 Subject: [PATCH 120/328] Qt widget cleanup - handle video device set before window attached - prevent exceptions from escaping event handlers --- ChangeLog | 3 +++ include/zbar/QZBar.h | 1 + qt/QZBar.cpp | 40 +++++++++++++++++++++++++++++++--------- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index ccfbd15..6933465 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,7 @@ current: + * Qt widget cleanup + - handle video device set before window attached + - prevent exceptions from escaping event handlers * more Qt window creation hook fixes - NB may still cause problems if video is opened before window is visible * finish fix for Qt init ordering (bug #2844846) diff --git a/include/zbar/QZBar.h b/include/zbar/QZBar.h index 5f2cb54..1044499 100644 --- a/include/zbar/QZBar.h +++ b/include/zbar/QZBar.h @@ -144,6 +144,7 @@ public Q_SLOTS: /// @internal protected: + void attach(); void showEvent(QShowEvent*); void paintEvent(QPaintEvent*); void resizeEvent(QResizeEvent*); diff --git a/qt/QZBar.cpp b/qt/QZBar.cpp index 21d4497..d31ad8c 100644 --- a/qt/QZBar.cpp +++ b/qt/QZBar.cpp @@ -65,9 +65,9 @@ QZBar::QZBar (QWidget *parent) QZBar::~QZBar () { if(thread) { - thread->window.attach(NULL); thread->pushEvent(new QEvent((QEvent::Type)QZBarThread::Exit)); thread->wait(); + delete thread; thread = NULL; } } @@ -88,8 +88,9 @@ void QZBar::setVideoDevice (const QString& videoDevice) return; if(_videoDevice != videoDevice) { _videoDevice = videoDevice; - _videoEnabled = !_videoDevice.isEmpty(); - thread->pushEvent(new QZBarThread::VideoDeviceEvent(videoDevice)); + _videoEnabled = _attached && !videoDevice.isEmpty(); + if(_attached) + thread->pushEvent(new QZBarThread::VideoDeviceEvent(videoDevice)); } } @@ -188,22 +189,43 @@ void QZBar::paintEvent (QPaintEvent *event) void QZBar::resizeEvent (QResizeEvent *event) { QSize size = event->size(); - if(thread) - thread->window.resize(size.rwidth(), size.rheight()); + try { + if(thread) + thread->window.resize(size.rwidth(), size.rheight()); + } + catch(Exception) { /* ignore */ } } void QZBar::changeEvent(QEvent *event) { - if(event->type() == QEvent::ParentChange) - thread->window.attach(x11Info().display(), winId()); + try { + QMutexLocker locker(&thread->mutex); + if(event->type() == QEvent::ParentChange) + thread->window.attach(x11Info().display(), winId()); + } + catch(Exception) { /* ignore (FIXME do something w/error) */ } } -void QZBar::showEvent (QShowEvent *event) +void QZBar::attach () { - if(!_attached) { + if(_attached) + return; + + try { thread->window.attach(x11Info().display(), winId()); _attached = 1; + + _videoEnabled = !_videoDevice.isEmpty(); + if(_videoEnabled) + thread->pushEvent(new QZBarThread::VideoDeviceEvent(_videoDevice)); } + catch(Exception) { /* ignore (FIXME do something w/error) */ } +} + +void QZBar::showEvent (QShowEvent *event) +{ + if(thread && !_attached) + attach(); } void QZBar::sizeChange () From aeb76e10773b6e70157a43034bf8e88e16e0175d Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 28 Aug 2009 09:35:56 -0400 Subject: [PATCH 121/328] compatibility fixes - work around ImageMagick API breakages - fix some OS X compile issues --- ChangeLog | 3 +++ gtk/zbargtk.c | 6 +++--- gtk/zbargtkprivate.h | 2 +- include/zbar.h | 12 ++++++------ include/zbar/zbargtk.h | 4 ++-- python/zbarmodule.c | 2 +- python/zbarmodule.h | 2 +- test/test_decode.c | 2 +- test/test_images.h | 2 +- zbar/convert.c | 2 +- zbar/jpeg.c | 2 +- zbar/processor/posix.c | 2 +- zbar/refcnt.c | 2 +- zbar/refcnt.h | 2 +- zbar/thread.h | 2 +- zbar/video.c | 2 +- zbarimg/zbarimg.c | 9 +++++++++ 17 files changed, 35 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6933465..3dc4a90 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,7 @@ current: + * compatibility fixes + - work around ImageMagick API breakages + - fix some OS X compile issues * Qt widget cleanup - handle video device set before window attached - prevent exceptions from escaping event handlers diff --git a/gtk/zbargtk.c b/gtk/zbargtk.c index 67dc842..cce62bf 100644 --- a/gtk/zbargtk.c +++ b/gtk/zbargtk.c @@ -718,7 +718,7 @@ static void zbar_gtk_class_init (ZBarGtkClass *klass) g_object_class_install_property(object_class, PROP_VIDEO_OPENED, p); } -GType zbar_gtk_get_type () +GType zbar_gtk_get_type (void) { static GType type = 0; if(!type) { @@ -744,7 +744,7 @@ static void zbar_gtk_private_class_init (ZBarGtkPrivateClass *klass) object_class->finalize = zbar_gtk_private_finalize; } -static GType zbar_gtk_private_get_type () +static GType zbar_gtk_private_get_type (void) { static GType type = 0; if(!type) { @@ -761,7 +761,7 @@ static GType zbar_gtk_private_get_type () return(type); } -GtkWidget *zbar_gtk_new () +GtkWidget *zbar_gtk_new (void) { return(GTK_WIDGET(g_object_new(ZBAR_TYPE_GTK, NULL))); } diff --git a/gtk/zbargtkprivate.h b/gtk/zbargtkprivate.h index 7832e76..9cd0525 100644 --- a/gtk/zbargtkprivate.h +++ b/gtk/zbargtkprivate.h @@ -93,7 +93,7 @@ typedef struct _ZBarGtkPrivateClass } ZBarGtkPrivateClass; -static GType zbar_gtk_private_get_type() G_GNUC_CONST; +static GType zbar_gtk_private_get_type(void) G_GNUC_CONST; G_END_DECLS diff --git a/include/zbar.h b/include/zbar.h index 2a996e7..a6bac3c 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -152,7 +152,7 @@ extern void zbar_set_verbosity(int verbosity); /** increase global library debug level. * eg, for -vvvv */ -extern void zbar_increase_verbosity(); +extern void zbar_increase_verbosity(void); /** retrieve string name for symbol encoding. * @param sym symbol type encoding @@ -312,7 +312,7 @@ typedef void (zbar_image_data_handler_t)(zbar_image_t *image, * this image should be destroyed (using zbar_image_destroy()) as * soon as the application is finished with it */ -extern zbar_image_t *zbar_image_create(); +extern zbar_image_t *zbar_image_create(void); /** image destructor. all images created by or returned to the * application should be destroyed using this function. when an image @@ -693,7 +693,7 @@ struct zbar_video_s; typedef struct zbar_video_s zbar_video_t; /** constructor. */ -extern zbar_video_t *zbar_video_create(); +extern zbar_video_t *zbar_video_create(void); /** destructor. */ extern void zbar_video_destroy(zbar_video_t *video); @@ -813,7 +813,7 @@ struct zbar_window_s; typedef struct zbar_window_s zbar_window_t; /** constructor. */ -extern zbar_window_t *zbar_window_create(); +extern zbar_window_t *zbar_window_create(void); /** destructor. */ extern void zbar_window_destroy(zbar_window_t *window); @@ -904,7 +904,7 @@ struct zbar_image_scanner_s; typedef struct zbar_image_scanner_s zbar_image_scanner_t; /** constructor. */ -extern zbar_image_scanner_t *zbar_image_scanner_create(); +extern zbar_image_scanner_t *zbar_image_scanner_create(void); /** destructor. */ extern void zbar_image_scanner_destroy(zbar_image_scanner_t *scanner); @@ -986,7 +986,7 @@ typedef struct zbar_decoder_s zbar_decoder_t; typedef void (zbar_decoder_handler_t)(zbar_decoder_t *decoder); /** constructor. */ -extern zbar_decoder_t *zbar_decoder_create(); +extern zbar_decoder_t *zbar_decoder_create(void); /** destructor. */ extern void zbar_decoder_destroy(zbar_decoder_t *decoder); diff --git a/include/zbar/zbargtk.h b/include/zbar/zbargtk.h index 5d4ddc0..02b3662 100644 --- a/include/zbar/zbargtk.h +++ b/include/zbar/zbargtk.h @@ -134,7 +134,7 @@ struct _ZBarGtkClass { GdkPixbuf *image); }; -GType zbar_gtk_get_type() G_GNUC_CONST; +GType zbar_gtk_get_type(void) G_GNUC_CONST; /** * zbar_gtk_new: @@ -143,7 +143,7 @@ GType zbar_gtk_get_type() G_GNUC_CONST; * * Returns: a new #ZBarGtk widget instance */ -GtkWidget *zbar_gtk_new(); +GtkWidget *zbar_gtk_new(void); /** * zbar_gtk_scan_image: diff --git a/python/zbarmodule.c b/python/zbarmodule.c index c511201..8be03dd 100644 --- a/python/zbarmodule.c +++ b/python/zbarmodule.c @@ -103,7 +103,7 @@ static PyMethodDef zbar_functions[] = { }; PyMODINIT_FUNC -initzbar () +initzbar (void) { /* initialize constant containers */ config_enum = zbarEnum_New(); diff --git a/python/zbarmodule.h b/python/zbarmodule.h index e968d74..0b6dd4d 100644 --- a/python/zbarmodule.h +++ b/python/zbarmodule.h @@ -57,7 +57,7 @@ typedef struct { extern PyTypeObject zbarEnum_Type; -extern zbarEnum *zbarEnum_New(); +extern zbarEnum *zbarEnum_New(void); extern int zbarEnum_Add(zbarEnum *self, int val, const char *name); diff --git a/test/test_decode.c b/test/test_decode.c index 4fd743f..0881ac5 100644 --- a/test/test_decode.c +++ b/test/test_decode.c @@ -280,7 +280,7 @@ static void encode_row417 (int r, encode((dir) ? PDF417_START : PDF417_STOP, dir); } -static void encode_pdf417 () +static void encode_pdf417 (unsigned char *data) { printf("------------------------------------------------------------\n" "encode PDF417: hello world\n"); diff --git a/test/test_images.h b/test/test_images.h index 50dfef9..c1bc379 100644 --- a/test/test_images.h +++ b/test/test_images.h @@ -28,7 +28,7 @@ ((uint32_t)(a) | ((uint32_t)(b) << 8) | \ ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24)) -int test_image_check_cleanup(); +int test_image_check_cleanup(void); int test_image_bars(zbar_image_t*); #endif diff --git a/zbar/convert.c b/zbar/convert.c index 8cae6ac..103e36e 100644 --- a/zbar/convert.c +++ b/zbar/convert.c @@ -172,7 +172,7 @@ static int intsort (const void *a, #endif /* verify that format list is in required sort order */ -static inline int verify_format_sort () +static inline int verify_format_sort (void) { int i; for(i = 0; i < num_format_defs; i++) { diff --git a/zbar/jpeg.c b/zbar/jpeg.c index e489197..fb566f4 100644 --- a/zbar/jpeg.c +++ b/zbar/jpeg.c @@ -88,7 +88,7 @@ void term_source (j_decompress_ptr cinfo) /* nothing todo */ } -struct jpeg_decompress_struct * _zbar_jpeg_decomp_create () +struct jpeg_decompress_struct * _zbar_jpeg_decomp_create (void) { j_decompress_ptr cinfo = calloc(1, sizeof(struct jpeg_decompress_struct)); if(!cinfo) diff --git a/zbar/processor/posix.c b/zbar/processor/posix.c index 203c1b7..697c3dd 100644 --- a/zbar/processor/posix.c +++ b/zbar/processor/posix.c @@ -71,7 +71,7 @@ int _zbar_event_wait (zbar_event_t *event, struct timespec tmp; tmp.tv_sec = timeout->tv_sec; tmp.tv_nsec = timeout->tv_usec * 1000; - timer = *tmp; + timer = &tmp; # endif rc = pthread_cond_timedwait(&event->cond, lock, timer); } diff --git a/zbar/refcnt.c b/zbar/refcnt.c index 6c8f68b..3d7b14c 100644 --- a/zbar/refcnt.c +++ b/zbar/refcnt.c @@ -28,7 +28,7 @@ pthread_once_t initialized = PTHREAD_ONCE_INIT; pthread_mutex_t _zbar_reflock; -static void initialize () +static void initialize (void) { pthread_mutex_init(&_zbar_reflock, NULL); } diff --git a/zbar/refcnt.h b/zbar/refcnt.h index 7caf9c1..a176514 100644 --- a/zbar/refcnt.h +++ b/zbar/refcnt.h @@ -67,6 +67,6 @@ static inline int _zbar_refcnt (refcnt_t *cnt, #endif -void _zbar_refcnt_init(); +void _zbar_refcnt_init(void); #endif diff --git a/zbar/thread.h b/zbar/thread.h index 776e1a2..040d955 100644 --- a/zbar/thread.h +++ b/zbar/thread.h @@ -98,7 +98,7 @@ static inline void _zbar_thread_init (zbar_thread_t *thr) _zbar_event_trigger(&thr->activity); } -static inline zbar_thread_id_t _zbar_thread_self () +static inline zbar_thread_id_t _zbar_thread_self (void) { return(pthread_self()); } diff --git a/zbar/video.c b/zbar/video.c index 130cc58..17da25c 100644 --- a/zbar/video.c +++ b/zbar/video.c @@ -26,7 +26,7 @@ #ifdef HAVE_LIBJPEG -extern struct jpeg_decompress_struct *_zbar_jpeg_decomp_create(); +extern struct jpeg_decompress_struct *_zbar_jpeg_decomp_create(void); extern void _zbar_jpeg_decomp_destroy(struct jpeg_decompress_struct *cinfo); #endif diff --git a/zbarimg/zbarimg.c b/zbarimg/zbarimg.c index b6d0cc8..3fc80bd 100644 --- a/zbarimg/zbarimg.c +++ b/zbarimg/zbarimg.c @@ -36,6 +36,15 @@ #include #include +/* in 6.4.5.4 MagickGetImagePixels changed to MagickExportImagePixels. + * (still not sure this check is quite right... + * how does MagickGetAuthenticImagePixels fit in?) + * ref http://bugs.gentoo.org/247292 + */ +#if MagickLibVersion < 0x645 +# define MagickExportImagePixels MagickGetImagePixels +#endif + static const char *note_usage = "usage: zbarimg [options] ...\n" "\n" From 88884a5ed16fbaf0a8ac706d0deac2f1d8ea0712 Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 28 Aug 2009 14:26:29 -0400 Subject: [PATCH 122/328] add symbol quality metric and image scanner position config - update python, perl and docs --- ChangeLog | 2 ++ doc/ref/commonoptions.xml | 21 ++++++++++++++++++++ include/zbar.h | 15 +++++++++++++- perl/ZBar.xs | 5 +++++ perl/ZBar/Symbol.pod | 10 ++++++++++ perl/t/Image.t | 8 ++++++-- perl/t/Processor.t | 6 +++++- python/symbol.c | 14 +++++++++---- python/test/test_zbar.py | 2 ++ python/zbarmodule.c | 3 ++- zbar/config.c | 2 ++ zbar/img_scanner.c | 42 ++++++++++++++++++++++++++++++--------- zbar/processor.c | 3 ++- zbar/symbol.c | 9 +++++++-- zbar/symbol.h | 1 + 15 files changed, 122 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3dc4a90..cc93def 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * add symbol quality metric and image scanner position config + - update python, perl and docs * compatibility fixes - work around ImageMagick API breakages - fix some OS X compile issues diff --git a/doc/ref/commonoptions.xml b/doc/ref/commonoptions.xml index c809d9e..8ea3ea1 100644 --- a/doc/ref/commonoptions.xml +++ b/doc/ref/commonoptions.xml @@ -110,6 +110,16 @@ + + + + Enable collection of symbol position information. + Enabled by default. Currently, the position information is + unusable, so you can save a few cycles by disabling + this. + + + @@ -125,6 +135,17 @@ recommendation); all others default to 0 + + + + + + Adjust the density of the scanner passes. Lower values + scan more of the image at the cost of decreased performance. + Setting to 0 disables scanning along that axis. Defaults are both + 1. + + diff --git a/include/zbar.h b/include/zbar.h index a6bac3c..cdea171 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -127,11 +127,13 @@ typedef enum zbar_config_e { ZBAR_CFG_ADD_CHECK, /**< enable check digit when optional */ ZBAR_CFG_EMIT_CHECK, /**< return check digit when present */ ZBAR_CFG_ASCII, /**< enable full ASCII character set */ - ZBAR_CFG_NUM, /**< number of boolean configs */ + ZBAR_CFG_NUM, /**< number of boolean decoder configs */ ZBAR_CFG_MIN_LEN = 0x20, /**< minimum data length for valid decode */ ZBAR_CFG_MAX_LEN, /**< maximum data length for valid decode */ + 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; @@ -230,6 +232,17 @@ extern const char *zbar_symbol_get_data(const zbar_symbol_t *symbol); */ extern unsigned int zbar_symbol_get_data_length(const zbar_symbol_t *symbol); +/** retrieve a symbol confidence metric. + * @returns an unscaled, relative quantity: larger values are better + * than smaller values, where "large" and "small" are application + * dependent. + * @note expect the exact definition of this quantity to change as the + * metric is refined. currently, only the ordered relationship + * between two values is defined and will remain stable in the future + * @since 0.9 + */ +extern int zbar_symbol_get_quality(const zbar_symbol_t *symbol); + /** retrieve current cache count. when the cache is enabled for the * image_scanner this provides inter-frame reliability and redundancy * information for video streams. diff --git a/perl/ZBar.xs b/perl/ZBar.xs index af1ee39..858d85a 100644 --- a/perl/ZBar.xs +++ b/perl/ZBar.xs @@ -266,6 +266,7 @@ BOOT: CONSTANT(config, CFG_, ASCII, "ascii"); CONSTANT(config, CFG_, MIN_LEN, "min-length"); CONSTANT(config, CFG_, MAX_LEN, "max-length"); + CONSTANT(config, CFG_, POSITION, "position"); CONSTANT(config, CFG_, X_DENSITY, "x-density"); CONSTANT(config, CFG_, Y_DENSITY, "y-density"); } @@ -315,6 +316,10 @@ int zbar_symbol_get_count(symbol) Barcode::ZBar::Symbol symbol +int +zbar_symbol_get_quality(symbol) + Barcode::ZBar::Symbol symbol + SV * zbar_symbol_get_loc(symbol) Barcode::ZBar::Symbol symbol diff --git a/perl/ZBar/Symbol.pod b/perl/ZBar/Symbol.pod index c8f9192..7838549 100644 --- a/perl/ZBar/Symbol.pod +++ b/perl/ZBar/Symbol.pod @@ -58,6 +58,14 @@ The type of bar code "symbology" from which the data was decoded. The decoded data string. Note that some symbologies can encode binary data. +=item get_quality() + +Confidence metric. An unscaled integer value that indicates something +(intentionally unspecified) about the reliability of this result +relative to another. Larger values are better than smaller values, +where "large" and "small" are application dependent. Expect this +definition to become more specific as the metric is enhanced. + =item get_count() Current cache count of the symbol. This integer value provides @@ -111,6 +119,8 @@ Bar code type "symbology" constants: =item CODE128 +=item PDF417 + =back =head1 SEE ALSO diff --git a/perl/t/Image.t b/perl/t/Image.t index 9067434..960540e 100755 --- a/perl/t/Image.t +++ b/perl/t/Image.t @@ -3,7 +3,7 @@ use warnings; use strict; -use Test::More tests => 16; +use Test::More tests => 17; ######################### @@ -81,7 +81,7 @@ SKIP: { ######################### - can_ok($sym, qw(get_type get_data get_count get_loc)); + can_ok($sym, qw(get_type get_data get_quality get_count get_loc)); ######################### @@ -93,6 +93,10 @@ SKIP: { ######################### + ok($sym->get_quality() > 0, 'quality'); + + ######################### + my @loc = $sym->get_loc(); ok(scalar(@loc) >= 4, 'location size'); diff --git a/perl/t/Processor.t b/perl/t/Processor.t index b936c3e..aa6734c 100755 --- a/perl/t/Processor.t +++ b/perl/t/Processor.t @@ -3,7 +3,7 @@ use warnings; use strict; -use Test::More tests => 19; +use Test::More tests => 20; ######################### @@ -63,6 +63,10 @@ $proc->set_data_handler(sub { ######################### + ok($sym->get_quality() > 0, 'quality'); + + ######################### + my @loc = $sym->get_loc(); ok(scalar(@loc) >= 4, 'location size'); diff --git a/python/symbol.c b/python/symbol.c index 92dfe85..90cd2d9 100644 --- a/python/symbol.c +++ b/python/symbol.c @@ -66,10 +66,15 @@ symbol_get_type (zbarSymbol *self, } static PyObject* -symbol_get_count (zbarSymbol *self, - void *closure) +symbol_get_long (zbarSymbol *self, + void *closure) { - return(PyInt_FromLong(zbar_symbol_get_count(self->zsym))); + int val; + if(!closure) + val = zbar_symbol_get_quality(self->zsym); + else + val = zbar_symbol_get_count(self->zsym); + return(PyInt_FromLong(val)); } static PyObject* @@ -110,7 +115,8 @@ symbol_get_location (zbarSymbol *self, static PyGetSetDef symbol_getset[] = { { "type", (getter)symbol_get_type, }, - { "count", (getter)symbol_get_count, }, + { "quality", (getter)symbol_get_long, NULL, NULL, (void*)0 }, + { "count", (getter)symbol_get_long, NULL, NULL, (void*)1 }, { "data", (getter)symbol_get_data, }, { "location", (getter)symbol_get_location, }, { NULL, }, diff --git a/python/test/test_zbar.py b/python/test/test_zbar.py index c5c3124..dd37b92 100755 --- a/python/test/test_zbar.py +++ b/python/test/test_zbar.py @@ -243,6 +243,7 @@ def test_scan(self): self.assert_(sym.type is zbar.Symbol.EAN13) self.assert_(sym.type is sym.EAN13) self.assertEqual(str(sym.type), 'EAN13') + self.assert_(sym.quality > 0) self.assertEqual(sym.count, 0) data = sym.data @@ -315,6 +316,7 @@ def data_handler(proc, image, closure): self.assert_(isinstance(symbol, zbar.Symbol)) self.assert_(symbol.type is zbar.Symbol.EAN13) self.assertEqual(symbol.data, '9876543210128') + self.assert_(symbol.quality > 0) closure[0] += 1 explicit_closure = [ 0 ] diff --git a/python/zbarmodule.c b/python/zbarmodule.c index 8be03dd..6cb5507 100644 --- a/python/zbarmodule.c +++ b/python/zbarmodule.c @@ -174,12 +174,13 @@ initzbar (void) zbarEnum_Add(config_enum, ZBAR_CFG_ASCII, "ASCII"); zbarEnum_Add(config_enum, ZBAR_CFG_MIN_LEN, "MIN_LEN"); zbarEnum_Add(config_enum, ZBAR_CFG_MAX_LEN, "MAX_LEN"); + zbarEnum_Add(config_enum, ZBAR_CFG_X_DENSITY, "POSITION"); zbarEnum_Add(config_enum, ZBAR_CFG_X_DENSITY, "X_DENSITY"); zbarEnum_Add(config_enum, ZBAR_CFG_Y_DENSITY, "Y_DENSITY"); PyObject *tp_dict = zbarSymbol_Type.tp_dict; symbol_NONE = - zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_NONE, "NONE"); + zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_NONE, "NONE"); zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_PARTIAL, "PARTIAL"); zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_EAN8, "EAN8"); zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_UPCE, "UPCE"); diff --git a/zbar/config.c b/zbar/config.c index df854d3..062e2ed 100644 --- a/zbar/config.c +++ b/zbar/config.c @@ -126,6 +126,8 @@ int zbar_parse_config (const char *cfgstr, *cfg = ZBAR_CFG_ADD_CHECK; else if(!strncmp(cfgstr, "emit-check", len)) *cfg = ZBAR_CFG_EMIT_CHECK; + else if(!strncmp(cfgstr, "position", len)) + *cfg = ZBAR_CFG_POSITION; else return(1); diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 807d878..05d9db6 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -66,6 +66,7 @@ #define NUM_SCN_CFGS (ZBAR_CFG_Y_DENSITY - ZBAR_CFG_X_DENSITY + 1) #define CFG(iscn, cfg) ((iscn)->configs[(cfg) - ZBAR_CFG_X_DENSITY]) +#define TEST_CFG(iscn, cfg) (((iscn)->config >> ((cfg) - ZBAR_CFG_POSITION)) & 1) /* image scanner state */ @@ -85,7 +86,8 @@ struct zbar_image_scanner_s { zbar_symbol_t *cache; /* inter-image result cache entries */ /* configuration settings */ - int configs[NUM_SCN_CFGS]; + unsigned config; /* config flags */ + int configs[NUM_SCN_CFGS]; /* int valued configurations */ }; static inline void recycle_syms (zbar_image_scanner_t *iscn, @@ -137,6 +139,7 @@ static inline zbar_symbol_t *alloc_sym (zbar_image_scanner_t *iscn, /* save new symbol data */ sym->type = type; + sym->quality = 1; sym->datalen = datalen++; if(sym->data_alloc < datalen) { if(sym->data) @@ -192,9 +195,11 @@ static void symbol_handler (zbar_image_scanner_t *iscn, if(sym->type == type && sym->datalen == datalen && !memcmp(sym->data, data, datalen)) { - /* add new point to existing set */ - /* FIXME should be polygon */ - sym_add_point(sym, x, y); + sym->quality++; + if(TEST_CFG(iscn, ZBAR_CFG_POSITION)) + /* add new point to existing set */ + /* FIXME should be polygon */ + sym_add_point(sym, x, y); return; } @@ -214,7 +219,8 @@ static void symbol_handler (zbar_image_scanner_t *iscn, /* initialize first point */ sym->npts = 0; - sym_add_point(sym, x, y); + if(TEST_CFG(iscn, ZBAR_CFG_POSITION)) + sym_add_point(sym, x, y); /* attach to current root image */ sym->next = iscn->img->syms; @@ -269,6 +275,7 @@ zbar_image_scanner_t *zbar_image_scanner_create () /* apply default configuration */ CFG(iscn, ZBAR_CFG_X_DENSITY) = 1; CFG(iscn, ZBAR_CFG_Y_DENSITY) = 1; + zbar_image_scanner_set_config(iscn, 0, ZBAR_CFG_POSITION, 1); return(iscn); } @@ -304,14 +311,30 @@ int zbar_image_scanner_set_config (zbar_image_scanner_t *iscn, zbar_config_t cfg, int val) { + if(cfg < ZBAR_CFG_POSITION) + return(zbar_decoder_set_config(iscn->dcode, sym, cfg, val)); + + if(sym > ZBAR_PARTIAL) + return(1); + if(cfg >= ZBAR_CFG_X_DENSITY && cfg <= ZBAR_CFG_Y_DENSITY) { - if(sym > ZBAR_PARTIAL) - return(1); CFG(iscn, cfg) = val; return(0); } - return(zbar_decoder_set_config(iscn->dcode, sym, cfg, val)); + + if(cfg > ZBAR_CFG_POSITION) + return(1); + cfg -= ZBAR_CFG_POSITION; + + if(!val) + iscn->config &= ~(1 << cfg); + else if(val == 1) + iscn->config |= (1 << cfg); + else + return(1); + + return(0); } void zbar_image_scanner_enable_cache(zbar_image_scanner_t *iscn, @@ -451,10 +474,11 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, zbar_symbol_t **symp = &img->syms, *sym; while((sym = *symp)) { if(sym->type < ZBAR_I25 && sym->type > ZBAR_PARTIAL && - sym->npts < 2) { + sym->quality < 3) { /* recycle */ *symp = sym->next; iscn->nsyms++; + img->nsyms--; sym->next = iscn->syms; iscn->syms = sym; } diff --git a/zbar/processor.c b/zbar/processor.c index 7630156..a9882dd 100644 --- a/zbar/processor.c +++ b/zbar/processor.c @@ -78,11 +78,12 @@ int _zbar_process_image (zbar_processor_t *proc, while(sym) { zbar_symbol_type_t type = zbar_symbol_get_type(sym); int count = zbar_symbol_get_count(sym); - zprintf(8, "%s%s: %s (%d pts) (%s)\n", + zprintf(8, "%s%s: %s (%d pts) (q=%d) (%s)\n", zbar_get_symbol_name(type), zbar_get_addon_name(type), zbar_symbol_get_data(sym), zbar_symbol_get_loc_size(sym), + zbar_symbol_get_quality(sym), (count < 0) ? "uncertain" : (count > 0) ? "duplicate" : "new"); sym = zbar_symbol_next(sym); diff --git a/zbar/symbol.c b/zbar/symbol.c index 6d0cd01..5d820e4 100644 --- a/zbar/symbol.c +++ b/zbar/symbol.c @@ -81,6 +81,11 @@ int zbar_symbol_get_count (const zbar_symbol_t *sym) return(sym->cache_count); } +int zbar_symbol_get_quality (const zbar_symbol_t *sym) +{ + return(sym->quality); +} + unsigned zbar_symbol_get_loc_size (const zbar_symbol_t *sym) { return(sym->npts); @@ -111,7 +116,7 @@ const zbar_symbol_t *zbar_symbol_next (const zbar_symbol_t *sym) static const char *xmlfmt[] = { - "", @@ -138,7 +143,7 @@ char *zbar_symbol_xml (const zbar_symbol_t *sym, *len = maxlen; } - int n = snprintf(*buf, maxlen, xmlfmt[0], type); + int n = snprintf(*buf, maxlen, xmlfmt[0], type, sym->quality); assert(n > 0); assert(n <= maxlen); diff --git a/zbar/symbol.h b/zbar/symbol.h index ad317a3..1f06aa8 100644 --- a/zbar/symbol.h +++ b/zbar/symbol.h @@ -45,6 +45,7 @@ struct zbar_symbol_s { zbar_symbol_t *next; /* linked list of results */ unsigned long time; /* relative symbol capture time */ int cache_count; /* cache state */ + int quality; /* relative symbol reliability metric */ }; static inline void sym_add_point (zbar_symbol_t *sym, From c53c230c0e47f1ba502e10f3ac7654f64ca7c327 Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 28 Aug 2009 21:04:26 -0400 Subject: [PATCH 123/328] move image conversion out of image scanner up to higher levels (preparation for library split) --- ChangeLog | 2 ++ TODO | 3 +-- gtk/zbargtk.c | 7 ++++++- include/zbar.h | 5 ++++- qt/QZBarThread.cpp | 5 ++++- zbar/img_scanner.c | 15 +++++++-------- zbar/processor.c | 19 ++++++++++++++----- 7 files changed, 38 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index cc93def..72f8167 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * move image conversion out of image scanner up to higher levels + (preparation for library split) * add symbol quality metric and image scanner position config - update python, perl and docs * compatibility fixes diff --git a/TODO b/TODO index 7af02f9..0fd9662 100644 --- a/TODO +++ b/TODO @@ -36,9 +36,8 @@ decoder: * standard symbology identifiers (which standard?) * set consistency requirements * set scanner filter params - * fix min/max length check during decode + * fix max length check during decode * revisit noise and resolution independence - * support for a "confidence" metric image scanner: * extract and track symbol polygons diff --git a/gtk/zbargtk.c b/gtk/zbargtk.c index cce62bf..3c6e82c 100644 --- a/gtk/zbargtk.c +++ b/gtk/zbargtk.c @@ -209,7 +209,12 @@ static inline int zbar_gtk_process_image (ZBarGtk *self, if(!image) return(-1); - int rc = zbar_scan_image(zbar->scanner, image); + zbar_image_t *tmp = zbar_image_convert(image, fourcc('Y','8','0','0')); + if(!tmp) + return(-1); + + int rc = zbar_scan_image(zbar->scanner, tmp); + zbar_image_destroy(tmp); if(rc < 0) return(rc); diff --git a/include/zbar.h b/include/zbar.h index cdea171..e939aa1 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -972,9 +972,12 @@ zbar_image_scanner_parse_config (zbar_image_scanner_t *scanner, extern void zbar_image_scanner_enable_cache(zbar_image_scanner_t *scanner, int enable); -/** scan for symbols in provided image. +/** scan for symbols in provided image. The image format must be + * "Y800" or "GRAY". * @returns >0 if symbols were successfully decoded from the image, * 0 if no symbols were found or -1 if an error occurs + * @see zbar_image_convert() + * @since 0.9 - changed to only accept grayscale images */ extern int zbar_scan_image(zbar_image_scanner_t *scanner, zbar_image_t *image); diff --git a/qt/QZBarThread.cpp b/qt/QZBarThread.cpp index a193470..ca96d7f 100644 --- a/qt/QZBarThread.cpp +++ b/qt/QZBarThread.cpp @@ -58,7 +58,10 @@ void QZBarThread::image_callback (Image &image) void QZBarThread::processImage (Image &image) { - scanner.scan(image); + { + Image tmp = image.convert(*(long*)"Y800"); + scanner.scan(tmp); + } window.draw(image); if(this->image && this->image != &image) { delete this->image; diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 05d9db6..c64e2de 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -375,16 +375,16 @@ static inline void quiet_border (zbar_image_scanner_t *iscn, int zbar_scan_image (zbar_image_scanner_t *iscn, zbar_image_t *img) { - recycle_syms(iscn, img); - /* get grayscale image, convert if necessary */ - img = zbar_image_convert(img, fourcc('Y','8','0','0')); - if(!img) + if(img->format != fourcc('Y','8','0','0') && + img->format != fourcc('G','R','A','Y')) return(-1); - unsigned w = zbar_image_get_width(img); - unsigned h = zbar_image_get_height(img); - const uint8_t *data = zbar_image_get_data(img); + recycle_syms(iscn, img); + + unsigned w = img->width; + unsigned h = img->height; + const uint8_t *data = img->data; int density = CFG(iscn, ZBAR_CFG_Y_DENSITY); if(density > 0) { @@ -464,7 +464,6 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, } /* release reference to converted image */ - zbar_image_destroy(img); img = iscn->img; iscn->img = NULL; diff --git a/zbar/processor.c b/zbar/processor.c index a9882dd..e64e853 100644 --- a/zbar/processor.c +++ b/zbar/processor.c @@ -23,6 +23,7 @@ #include "processor.h" #include "window.h" +#include "image.h" static inline int proc_enter (zbar_processor_t *proc) { @@ -68,10 +69,15 @@ int _zbar_process_image (zbar_processor_t *proc, /* FIXME locking all other interfaces while processing is conservative * but easier for now and we don't expect this to take long... */ - int nsyms = zbar_scan_image(proc->scanner, img); + zbar_image_t *tmp = zbar_image_convert(img, fourcc('Y','8','0','0')); + if(!img) + goto error; + + int nsyms = zbar_scan_image(proc->scanner, tmp); + zbar_image_destroy(tmp); + tmp = NULL; if(nsyms < 0) - return(err_capture(proc, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, - __func__, "unknown image format")); + goto error; if(_zbar_verbosity >= 8) { const zbar_symbol_t *sym = zbar_image_first_symbol(img); @@ -102,8 +108,7 @@ int _zbar_process_image (zbar_processor_t *proc, if(force_fmt) { img = zbar_image_convert(img, force_fmt); if(!img) - return(err_capture(proc, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, - __func__, "unknown image format")); + goto error; } } @@ -116,6 +121,10 @@ int _zbar_process_image (zbar_processor_t *proc, if(force_fmt && img) zbar_image_destroy(img); return(0); + +error: + return(err_capture(proc, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, + __func__, "unknown image format")); } int _zbar_processor_handle_input (zbar_processor_t *proc, From 0369e3f5576af66b52de7915bbb081348d328e47 Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 30 Aug 2009 08:10:37 -0400 Subject: [PATCH 124/328] compatibility fixes --- ChangeLog | 1 + zbar/error.h | 25 ++++++++++++++++++++++++- zbar/img_scanner.c | 17 ++++++++--------- zbar/refcnt.c | 4 +--- zbar/refcnt.h | 38 +++++++++++++++++++++++++------------- 5 files changed, 59 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0f0f9c8..6ba0afb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * compatibility fixes * more testing, fixes and cleanup - fix v4l1 - fix/add null processor interface diff --git a/zbar/error.h b/zbar/error.h index 89dcba2..e15da1c 100644 --- a/zbar/error.h +++ b/zbar/error.h @@ -89,12 +89,35 @@ extern int _zbar_verbosity; # define ZFLUSH #endif -#define zprintf(level, format, ...) do { \ +#ifdef ZNO_MESSAGES + +# ifdef __GNUC__ + /* older versions of gcc (< 2.95) require a named varargs parameter */ +# define zprintf(args...) +# else + /* unfortunately named vararg parameter is a gcc-specific extension */ +# define zprintf(...) +# endif + +#else + +# ifdef __GNUC__ +# define zprintf(level, format, args...) do { \ + if(_zbar_verbosity >= level) { \ + fprintf(stderr, "%s: " format, __func__ , args); \ + ZFLUSH \ + } \ + } while(0) +# else +# define zprintf(level, format, ...) do { \ if(_zbar_verbosity >= level) { \ fprintf(stderr, "%s: " format, __func__ , ##__VA_ARGS__); \ ZFLUSH \ } \ } while(0) +# endif + +#endif static inline int err_copy (void *dst_c, void *src_c) diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index f071b32..4b37bb8 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -354,14 +354,16 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, { recycle_syms(iscn, img); - /* get grayscale image, convert if necessary */ - img = zbar_image_convert(img, fourcc('Y','8','0','0')); - if(!img) + /* get image format, must be Y800 + * FIXME support RGB3/4 and BGR3/4 directly + */ + uint32_t fmt = img->format; + if(fmt != fourcc('Y','8','0','0')) return(-1); - unsigned w = zbar_image_get_width(img); - unsigned h = zbar_image_get_height(img); - const uint8_t *data = zbar_image_get_data(img); + unsigned w = img->width; + unsigned h = img->height; + const uint8_t *data = img->data; int density = CFG(iscn, ZBAR_CFG_Y_DENSITY); if(density > 0) { @@ -439,8 +441,5 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, movedelta(density, 1); } } - - /* release reference to converted image */ - zbar_image_destroy(img); return(iscn->img->nsyms); } diff --git a/zbar/refcnt.c b/zbar/refcnt.c index 6c8f68b..213e1a8 100644 --- a/zbar/refcnt.c +++ b/zbar/refcnt.c @@ -38,9 +38,7 @@ void _zbar_refcnt_init () pthread_once(&initialized, initialize); } -#endif - -#ifdef _WIN32 +#else void _zbar_refcnt_init () { diff --git a/zbar/refcnt.h b/zbar/refcnt.h index 7caf9c1..d3afb7c 100644 --- a/zbar/refcnt.h +++ b/zbar/refcnt.h @@ -26,7 +26,27 @@ #include #include -#ifdef HAVE_LIBPTHREAD +#if defined(_WIN32) +# include + +typedef volatile LONG refcnt_t; /* FIXME where did volatile come from? */ + +static inline int _zbar_refcnt (refcnt_t *cnt, + int delta) +{ + int rc = -1; + if(delta > 0) + while(delta--) + rc = InterlockedIncrement(cnt); + else if(delta < 0) + while(delta++) + rc = InterlockedDecrement(cnt); + assert(rc >= 0); + return(rc); +} + + +#elif defined(HAVE_LIBPTHREAD) # include typedef int refcnt_t; @@ -43,30 +63,22 @@ static inline int _zbar_refcnt (refcnt_t *cnt, return(rc); } -#endif - +#else -#ifdef _WIN32 -# include -typedef volatile LONG refcnt_t; +typedef int refcnt_t; static inline int _zbar_refcnt (refcnt_t *cnt, int delta) { - int rc = -1; - if(delta > 0) - while(delta--) - rc = InterlockedIncrement(cnt); - else if(delta < 0) - while(delta++) - rc = InterlockedDecrement(cnt); + int rc = (*cnt += delta); assert(rc >= 0); return(rc); } #endif + void _zbar_refcnt_init(); #endif From 95dfda67ba6de1f0da9b94e66daf365d91d05e6b Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 30 Aug 2009 12:09:05 -0400 Subject: [PATCH 125/328] fix uninitialized member in Qt widget (bug #2844846) --- ChangeLog | 1 + qt/QZBar.cpp | 3 ++- qt/QZBarThread.cpp | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 72f8167..f118fc8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * fix uninitialized member in Qt widget (bug #2844846) * move image conversion out of image scanner up to higher levels (preparation for library split) * add symbol quality metric and image scanner position config diff --git a/qt/QZBar.cpp b/qt/QZBar.cpp index d31ad8c..bff10ea 100644 --- a/qt/QZBar.cpp +++ b/qt/QZBar.cpp @@ -33,7 +33,8 @@ QZBar::QZBar (QWidget *parent) : QWidget(parent), thread(NULL), _videoDevice(), - _videoEnabled(false) + _videoEnabled(false), + _attached(false) { setAttribute(Qt::WA_OpaquePaintEvent); setAttribute(Qt::WA_PaintOnScreen); diff --git a/qt/QZBarThread.cpp b/qt/QZBarThread.cpp index ca96d7f..b105c73 100644 --- a/qt/QZBarThread.cpp +++ b/qt/QZBarThread.cpp @@ -29,7 +29,8 @@ using namespace zbar; static const QString textFormat("%1%2:%3"); QZBarThread::QZBarThread () - : reqWidth(DEFAULT_WIDTH), + : _videoOpened(false), + reqWidth(DEFAULT_WIDTH), reqHeight(DEFAULT_HEIGHT), video(NULL), image(NULL), From 2dc6cef9e669ef6e741595619c83c6568af64212 Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 31 Aug 2009 08:46:41 -0400 Subject: [PATCH 126/328] release updates --- ChangeLog | 3 ++- Makefile.am | 2 +- NEWS | 8 ++++++++ configure.ac | 10 +++++----- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index f118fc8..b4fff69 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ -current: +version 0.9: + * release updates * fix uninitialized member in Qt widget (bug #2844846) * move image conversion out of image scanner up to higher levels (preparation for library split) diff --git a/Makefile.am b/Makefile.am index 0524e5b..f049aa8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ AM_CPPFLAGS = -I$(srcdir)/include -AM_CFLAGS = -Wall -Werror +AM_CFLAGS = -Wall AM_CXXFLAGS = $(AM_CFLAGS) ACLOCAL_AMFLAGS = -I config bin_PROGRAMS = diff --git a/NEWS b/NEWS index 9a9544e..0d3fe33 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,13 @@ ZBar Barcode Reader +version 0.9 (2009-08-31): + Introducing ZBar for Windows! So far we only have straight ports of + the command line applications, but work on a cross-platform GUI has + already begun. This release also has a few scanner/decoder + enhancements and fixes several bugs. Many internal changes are + represented, so please open a support request if you experience any + problems. + version 0.8 (2009-06-05): This is a bugfix release just to clean up a few issues found in the last release. Existing users are encouraged to upgrade to pick up diff --git a/configure.ac b/configure.ac index dc22223..54f3928 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ([2.61]) -AC_INIT([zbar], [0.8], [spadix@users.sourceforge.net]) +AC_INIT([zbar], [0.9], [spadix@users.sourceforge.net]) AC_CONFIG_AUX_DIR(config) AC_CONFIG_MACRO_DIR(config) AM_INIT_AUTOMAKE([1.10 -Wall -Werror foreign subdir-objects std-options dist-bzip2]) @@ -21,13 +21,13 @@ dnl - If any interfaces have been added since the last public release, dnl then increment age. dnl - If any interfaces have been removed since the last public release, dnl then set age to 0. -AC_SUBST([LIB_VERSION], [0:1:0]) -AC_SUBST([RELDATE], [2009-06-05]) +AC_SUBST([LIB_VERSION], [1:0:1]) +AC_SUBST([RELDATE], [2009-08-31]) dnl widget libraries use their own versioning. dnl NB pygtk wrapper is *unversioned* -AC_SUBST([ZGTK_LIB_VERSION], [0:0:0]) -AC_SUBST([ZQT_LIB_VERSION], [0:0:0]) +AC_SUBST([ZGTK_LIB_VERSION], [0:1:0]) +AC_SUBST([ZQT_LIB_VERSION], [0:1:0]) AC_DEFINE_UNQUOTED([ZBAR_VERSION_MAJOR], [[`echo "$PACKAGE_VERSION" | sed -e 's/\..*$//'`]], From 2e82dc59805ecee3c43b466baf3e810e2f53f43e Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 31 Aug 2009 08:52:36 -0400 Subject: [PATCH 127/328] add missing API doc --- include/zbar/Decoder.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/zbar/Decoder.h b/include/zbar/Decoder.h index 4900e7c..3e65d5e 100644 --- a/include/zbar/Decoder.h +++ b/include/zbar/Decoder.h @@ -142,6 +142,8 @@ class Decoder { return(get_data_string()); } + /// retrieve length of decoded binary data. + /// see zbar_decoder_get_data_length() int get_data_length() const { return(zbar_decoder_get_data_length(_decoder)); From 7a5d918aa2d61cbab7744f371c37d24cdaceff3d Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 31 Aug 2009 09:11:07 -0400 Subject: [PATCH 128/328] fix non-VPATH nsis build --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index f049aa8..0714349 100644 --- a/Makefile.am +++ b/Makefile.am @@ -84,5 +84,5 @@ dist-nsis: html-local cp -r doc/html _nsis/share/doc/zbar/ $(WINEXEC) lib.exe /machine:x86 /def:_nsis/lib/libzbar-0.def /out:_nsis/lib/libzbar-0.lib cd _nsis && \ - makensis -NOCD -V2 -DVERSION=$(VERSION) $(srcdir)/zbar.nsi + makensis -NOCD -V2 -DVERSION=$(VERSION) $(abs_srcdir)/zbar.nsi endif From 9b5fc7cc127359c149cf569b08bc3be37226fd50 Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 31 Aug 2009 10:59:33 -0400 Subject: [PATCH 129/328] Added tag 0.9 for changeset 38265c7b4ad4 From ee77d3fb956ad069e4c081fe072f04dbaa4e95a3 Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 1 Sep 2009 12:25:30 -0400 Subject: [PATCH 130/328] hotfix trim extraneous MagickWand calls (bug #2848445) --- ChangeLog | 1 + zbarimg/zbarimg.c | 6 ------ 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index b4fff69..3514ab1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ version 0.9: + * hotfix trim extraneous MagickWand calls (bug #2848445) * release updates * fix uninitialized member in Qt widget (bug #2844846) * move image conversion out of image scanner up to higher levels diff --git a/zbarimg/zbarimg.c b/zbarimg/zbarimg.c index 3fc80bd..4db01e6 100644 --- a/zbarimg/zbarimg.c +++ b/zbarimg/zbarimg.c @@ -129,12 +129,6 @@ static int scan_image (const char *filename) image->modifyImage(); */ - if(!MagickSetFormat(images, "GRAY") && dump_error(images)) - return(-1); - - if(!MagickSetDepth(images, 8) && dump_error(images)) - return(-1); - zbar_image_t *zimage = zbar_image_create(); assert(zimage); zbar_image_set_format(zimage, *(unsigned long*)"Y800"); From b3d00f46da81300c99d40be61f177ee46706bc33 Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 1 Sep 2009 13:22:19 -0400 Subject: [PATCH 131/328] hotfix configure check for Wand as well as MagickWand (bug #2848437) --- ChangeLog | 1 + configure.ac | 20 +++++++++++++++++++- zbarimg/zbarimg.c | 4 ---- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3514ab1..d9a01e3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ version 0.9: + * hotfix configure check for Wand as well as MagickWand (bug #2848437) * hotfix trim extraneous MagickWand calls (bug #2848445) * release updates * fix uninitialized member in Qt widget (bug #2844846) diff --git a/configure.ac b/configure.ac index 54f3928..f1f30b3 100644 --- a/configure.ac +++ b/configure.ac @@ -258,7 +258,25 @@ AC_ARG_WITH([imagemagick], [with_imagemagick="yes"]) AS_IF([test "x$with_imagemagick" != "xno"], - [PKG_CHECK_MODULES([MAGICK], [MagickWand >= 6.2.6]) + [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) + saved_error=$MAGICK_PKG_ERRORS + PKG_CHECK_MODULES([MAGICK], [Wand >= 6.2.6], [], + [AC_MSG_FAILURE([dnl +Unable to find ImageMagick >= 6.2.6: + +$saved_error + +* Ensure that you installed any "development" packages for ImageMagick. +* 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]) diff --git a/zbarimg/zbarimg.c b/zbarimg/zbarimg.c index 4db01e6..c6cd296 100644 --- a/zbarimg/zbarimg.c +++ b/zbarimg/zbarimg.c @@ -125,10 +125,6 @@ static int scan_image (const char *filename) if(!MagickSetIteratorIndex(images, seq) && dump_error(images)) return(-1); - /* FIXME assuming this no longer applies... - image->modifyImage(); - */ - zbar_image_t *zimage = zbar_image_create(); assert(zimage); zbar_image_set_format(zimage, *(unsigned long*)"Y800"); From c1773e8287809c0c62ed2aa7beb890938351aa46 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 3 Sep 2009 12:03:18 -0400 Subject: [PATCH 132/328] Added tag 0.9 for changeset 2dc2d73c468a From d74c50ba86587225eeba6a169a98bb5c17b274e8 Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 16 Sep 2009 16:36:44 -0400 Subject: [PATCH 133/328] factor image scanner cache and apply to QR - fix image scanner handler called once per-image (vs every decode) --- ChangeLog | 2 + zbar/decoder/qrcode/qrdec.c | 4 ++ zbar/img_scanner.c | 105 ++++++++++++++++++++---------------- 3 files changed, 64 insertions(+), 47 deletions(-) diff --git a/ChangeLog b/ChangeLog index 475d147..558d02e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * factor image scanner cache and apply to QR + - fix image scanner handler called once per-image (vs every decode) * QZ and clustering fixes to QR integration - remove qr_finder QZ checks - decrease center clustering threshold from 1/3 to 1/5 of length diff --git a/zbar/decoder/qrcode/qrdec.c b/zbar/decoder/qrcode/qrdec.c index 28761a1..0fc11a9 100644 --- a/zbar/decoder/qrcode/qrdec.c +++ b/zbar/decoder/qrcode/qrdec.c @@ -4092,6 +4092,9 @@ zbar_symbol_t *_zbar_image_scanner_alloc_sym(zbar_image_scanner_t *iscn, const char *data, int datalen); +void _zbar_image_scanner_cache_sym(zbar_image_scanner_t *iscn, + zbar_symbol_t *sym); + int _zbar_qr_decode (zbar_image_scanner_t *iscn, qr_reader *reader, zbar_image_t *img) @@ -4138,6 +4141,7 @@ int _zbar_qr_decode (zbar_image_scanner_t *iscn, sym = _zbar_image_scanner_alloc_sym(iscn, ZBAR_QRCODE, text[i], strlen(text[i]) /* FIXME binary data? */); _zbar_image_attach_symbol(img, sym); + _zbar_image_scanner_cache_sym(iscn, sym); } qr_text_list_free(text, ntext); } diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 86e10c7..5d5ea29 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -89,6 +89,7 @@ struct zbar_image_scanner_s { /* user result callback */ zbar_image_data_handler_t *handler; + unsigned long time; /* scan start time */ zbar_image_t *img; /* currently scanning image *root* */ int dx, dy; /* current scan direction */ int nsyms; /* total cached symbols */ @@ -154,6 +155,9 @@ _zbar_image_scanner_alloc_sym (zbar_image_scanner_t *iscn, sym->type = type; sym->quality = 1; sym->datalen = datalen++; + sym->npts = 0; + sym->cache_count = 0; + sym->time = iscn->time; if(sym->data_alloc < datalen) { if(sym->data) free(sym->data); @@ -189,6 +193,39 @@ static inline zbar_symbol_t *cache_lookup (zbar_image_scanner_t *iscn, return(*entry); } +inline void _zbar_image_scanner_cache_sym (zbar_image_scanner_t *iscn, + zbar_symbol_t *sym) +{ + if(iscn->enable_cache) { + zbar_symbol_t *entry = cache_lookup(iscn, sym); + if(!entry) { + /* FIXME reuse sym */ + entry = _zbar_image_scanner_alloc_sym(iscn, sym->type, + sym->data, sym->datalen); + entry->time = sym->time - CACHE_HYSTERESIS; + entry->cache_count = -CACHE_CONSISTENCY; + /* add to cache */ + entry->next = iscn->cache; + iscn->cache = entry; + } + + /* consistency check and hysteresis */ + uint32_t age = sym->time - entry->time; + entry->time = sym->time; + int near_thresh = (age < CACHE_PROXIMITY); + int far_thresh = (age >= CACHE_HYSTERESIS); + int dup = (entry->cache_count >= 0); + if((!dup && !near_thresh) || far_thresh) + entry->cache_count = -CACHE_CONSISTENCY; + else if(dup || near_thresh) + entry->cache_count++; + + sym->cache_count = entry->cache_count; + } + else + sym->cache_count = 0; +} + #ifdef ENABLE_QRCODE extern qr_finder_line *_zbar_decoder_get_qr_finder_line(zbar_decoder_t*); @@ -294,7 +331,7 @@ static void symbol_handler (zbar_image_scanner_t *iscn, const char *data = zbar_decoder_get_data(iscn->dcode); unsigned datalen = zbar_decoder_get_data_length(iscn->dcode); - /* FIXME deprecate - instead check (x, y) inside existing polygon */ + /* FIXME need better search */ zbar_symbol_t *sym; for(sym = iscn->img->syms; sym; sym = sym->next) if(sym->type == type && @@ -310,57 +347,14 @@ static void symbol_handler (zbar_image_scanner_t *iscn, sym = _zbar_image_scanner_alloc_sym(iscn, type, data, datalen); - /* attach to current root image */ - _zbar_image_attach_symbol(iscn->img, sym); - - /* timestamp symbol */ -#if _POSIX_TIMERS > 0 - struct timespec abstime; - clock_gettime(CLOCK_REALTIME, &abstime); - sym->time = (abstime.tv_sec * 1000) + ((abstime.tv_nsec / 500000) + 1) / 2; -#else - struct timeval abstime; - gettimeofday(&abstime, NULL); - sym->time = (abstime.tv_sec * 1000) + ((abstime.tv_usec / 500) + 1) / 2; -#endif - /* initialize first point */ - sym->npts = 0; if(TEST_CFG(iscn, ZBAR_CFG_POSITION)) sym_add_point(sym, x, y); - if(iscn->enable_cache) { - zbar_symbol_t *entry = cache_lookup(iscn, sym); - if(!entry) { - /* FIXME reuse sym */ - entry = _zbar_image_scanner_alloc_sym(iscn, sym->type, - sym->data, sym->datalen); - entry->time = sym->time - CACHE_HYSTERESIS; - entry->cache_count = -CACHE_CONSISTENCY; - /* add to cache */ - entry->next = iscn->cache; - iscn->cache = entry; - } - - /* consistency check and hysteresis */ - uint32_t age = sym->time - entry->time; - entry->time = sym->time; - int near_thresh = (age < CACHE_PROXIMITY); - int far_thresh = (age >= CACHE_HYSTERESIS); - int dup = (entry->cache_count >= 0); - if((!dup && !near_thresh) || far_thresh) - entry->cache_count = -CACHE_CONSISTENCY; - else if(dup || near_thresh) - entry->cache_count++; - - sym->cache_count = entry->cache_count; - } - else - sym->cache_count = 0; + /* attach to current root image */ + _zbar_image_attach_symbol(iscn->img, sym); - /* FIXME option to only report count == 0 */ - if(iscn->handler) - iscn->handler(iscn->img, iscn->userdata); + _zbar_image_scanner_cache_sym(iscn, sym); } zbar_image_scanner_t *zbar_image_scanner_create () @@ -507,6 +501,19 @@ const char svg_head[] = int zbar_scan_image (zbar_image_scanner_t *iscn, zbar_image_t *img) { + /* timestamp image + * FIXME prefer video timestamp + */ +#if _POSIX_TIMERS > 0 + struct timespec abstime; + clock_gettime(CLOCK_REALTIME, &abstime); + iscn->time = (abstime.tv_sec * 1000) + ((abstime.tv_nsec / 500000) + 1) / 2; +#else + struct timeval abstime; + gettimeofday(&abstime, NULL); + iscn->time = (abstime.tv_sec * 1000) + ((abstime.tv_usec / 500) + 1) / 2; +#endif + #ifdef ENABLE_QRCODE qr_reader_reset(iscn->qr); #endif @@ -635,5 +642,9 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, } } + /* FIXME option to only report count == 0 */ + if(img->nsyms && iscn->handler) + iscn->handler(iscn->img, iscn->userdata); + return(img->nsyms); } From 6d1e4a79a16b28ece1df7d1b71f32335d1b50204 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 17 Sep 2009 13:20:15 -0400 Subject: [PATCH 134/328] fix broken builds with --disable-pthread --- ChangeLog | 3 ++ doc/manual.xml | 1 + zbar/event.h | 13 ++++----- zbar/processor.c | 5 ++-- zbar/processor/posix.c | 62 +++++++++++++++++++++++++++++++++--------- zbar/processor/posix.h | 10 ------- zbar/thread.h | 6 +++- zbar/video.c | 2 +- zbar/window.c | 2 +- 9 files changed, 68 insertions(+), 36 deletions(-) diff --git a/ChangeLog b/ChangeLog index d9a01e3..ca8e17d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +current: + * fix broken builds with --disable-pthread + version 0.9: * hotfix configure check for Wand as well as MagickWand (bug #2848437) * hotfix trim extraneous MagickWand calls (bug #2848445) diff --git a/doc/manual.xml b/doc/manual.xml index 076ca23..6a000d3 100644 --- a/doc/manual.xml +++ b/doc/manual.xml @@ -22,6 +22,7 @@
spadix@users.sourceforge.net
+ Lead developer diff --git a/zbar/event.h b/zbar/event.h index 483d647..3206d26 100644 --- a/zbar/event.h +++ b/zbar/event.h @@ -37,21 +37,20 @@ typedef HANDLE zbar_event_t; -#elif defined(HAVE_LIBPTHREAD) +#else -# include +# ifdef HAVE_LIBPTHREAD +# include +# endif typedef struct zbar_event_s { int state; +# ifdef HAVE_LIBPTHREAD pthread_cond_t cond; +# endif int pollfd; } zbar_event_t; - -#else - -typedef int zbar_event_t[0]; - #endif diff --git a/zbar/processor.c b/zbar/processor.c index e64e853..4ca36c8 100644 --- a/zbar/processor.c +++ b/zbar/processor.c @@ -423,10 +423,9 @@ void zbar_processor_set_userdata (zbar_processor_t *proc, void *zbar_processor_get_userdata (const zbar_processor_t *proc) { - zbar_processor_t *p = (zbar_processor_t*)proc; - _zbar_mutex_lock(&p->mutex); + _zbar_mutex_lock(&((zbar_processor_t*)proc)->mutex); void *userdata = (void*)proc->userdata; - _zbar_mutex_unlock(&p->mutex); + _zbar_mutex_unlock(&((zbar_processor_t*)proc)->mutex); return(userdata); } diff --git a/zbar/processor/posix.c b/zbar/processor/posix.c index 697c3dd..1d72cd5 100644 --- a/zbar/processor/posix.c +++ b/zbar/processor/posix.c @@ -27,11 +27,25 @@ #include #include + +static inline int proc_sleep (int timeout) +{ + assert(timeout > 0); + struct timespec sleepns, remns; + sleepns.tv_sec = timeout / 1000; + sleepns.tv_nsec = (timeout % 1000) * 1000000; + while(nanosleep(&sleepns, &remns) && errno == EINTR) + sleepns = remns; + return(1); +} + int _zbar_event_init (zbar_event_t *event) { event->state = 0; event->pollfd = -1; +#ifdef HAVE_LIBPTHREAD pthread_cond_init(&event->cond, NULL); +#endif return(0); } @@ -39,14 +53,18 @@ void _zbar_event_destroy (zbar_event_t *event) { event->state = -1; event->pollfd = -1; +#ifdef HAVE_LIBPTHREAD pthread_cond_destroy(&event->cond); +#endif } /* lock must be held */ void _zbar_event_trigger (zbar_event_t *event) { event->state = 1; +#ifdef HAVE_LIBPTHREAD pthread_cond_broadcast(&event->cond); +#endif if(event->pollfd >= 0) { unsigned i = 0; /* unused */ write(event->pollfd, &i, sizeof(unsigned)); @@ -54,6 +72,8 @@ void _zbar_event_trigger (zbar_event_t *event) } } +#ifdef HAVE_LIBPTHREAD + /* lock must be held */ int _zbar_event_wait (zbar_event_t *event, zbar_mutex_t *lock, @@ -130,6 +150,33 @@ int _zbar_thread_stop (zbar_thread_t *thr, return(0); } +#else + +int _zbar_event_wait (zbar_event_t *event, + zbar_mutex_t *lock, + zbar_timer_t *timeout) +{ + int rc = !event->state; + if(rc) { + if(!timeout) + /* FIXME was that error or hang? */ + return(-1); + + int sleep = _zbar_timer_check(timeout); + if(sleep) + proc_sleep(sleep); + } + + rc = !event->state; + + /* consume/reset event */ + event->state = 0; + + return(rc); +} + +#endif + /* used by poll interface. lock is already held */ static int proc_video_handler (zbar_processor_t *proc, int i) @@ -203,17 +250,6 @@ static inline int proc_poll_inputs (zbar_processor_t *proc, return(1); } -static inline int proc_sleep (int timeout) -{ - assert(timeout > 0); - struct timespec sleepns, remns; - sleepns.tv_sec = timeout / 1000; - sleepns.tv_nsec = (timeout % 1000) * 1000000; - while(nanosleep(&sleepns, &remns) && errno == EINTR) - sleepns = remns; - return(1); -} - int _zbar_processor_input_wait (zbar_processor_t *proc, zbar_event_t *event, int timeout) @@ -282,8 +318,8 @@ int _zbar_processor_cleanup (zbar_processor_t *proc) int _zbar_processor_enable (zbar_processor_t *proc) { - int vid_fd; - if(proc->threaded && ((vid_fd = zbar_video_get_fd(proc->video)) >= 0)) { + int vid_fd = zbar_video_get_fd(proc->video); + if(vid_fd >= 0) { if(proc->streaming) add_poll(proc, vid_fd, proc_video_handler); else diff --git a/zbar/processor/posix.h b/zbar/processor/posix.h index 6a1320b..0bcafee 100644 --- a/zbar/processor/posix.h +++ b/zbar/processor/posix.h @@ -29,10 +29,6 @@ # include #endif -#ifdef HAVE_LIBPTHREAD -# include -#endif - #ifdef HAVE_POLL_H typedef int (poll_handler_t)(zbar_processor_t*, int); @@ -50,12 +46,6 @@ struct processor_state_s { poll_desc_t thr_polling; /* thread copy */ #endif int kick_fds[2]; /* poll kicker */ - - int lock_level; /* API serialization lock */ - pthread_t lock_owner; /* lock owner */ - pthread_mutex_t mutex; /* lock mutex */ - pthread_cond_t cond; /* lock notification condition */ - pthread_cond_t event; }; diff --git a/zbar/thread.h b/zbar/thread.h index 040d955..96d6415 100644 --- a/zbar/thread.h +++ b/zbar/thread.h @@ -56,7 +56,7 @@ typedef pthread_t zbar_thread_id_t; # undef ZTHREAD typedef void zbar_thread_proc_t; -typedef int zbar_thread_id_t[0]; +typedef int zbar_thread_id_t; #endif @@ -112,12 +112,16 @@ static inline int _zbar_thread_is_self (zbar_thread_id_t tid) #else # define _zbar_thread_start(...) -1 +# define _zbar_thread_stop(...) 0 +# define _zbar_thread_self(...) 0 # define _zbar_thread_is_self(...) 1 #endif +#ifdef HAVE_THREADS extern int _zbar_thread_start(zbar_thread_t*, zbar_thread_proc_t*, void*, zbar_mutex_t*); extern int _zbar_thread_stop(zbar_thread_t*, zbar_mutex_t*); +#endif #endif diff --git a/zbar/video.c b/zbar/video.c index 17da25c..01afb26 100644 --- a/zbar/video.c +++ b/zbar/video.c @@ -63,7 +63,7 @@ zbar_video_t *zbar_video_create () err_init(&vdo->err, ZBAR_MOD_VIDEO); vdo->fd = -1; - _zbar_mutex_init(&vdo->qlock); + (void)_zbar_mutex_init(&vdo->qlock); /* pre-allocate images */ vdo->num_images = ZBAR_VIDEO_IMAGES_MAX; diff --git a/zbar/window.c b/zbar/window.c index dbaaae4..8c044e6 100644 --- a/zbar/window.c +++ b/zbar/window.c @@ -31,7 +31,7 @@ zbar_window_t *zbar_window_create () return(NULL); err_init(&w->err, ZBAR_MOD_WINDOW); w->overlay = 1; - _zbar_mutex_init(&w->imglock); + (void)_zbar_mutex_init(&w->imglock); return(w); } From c67d6f26babffaabb574932d9e86383e31cd6fee Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 19 Sep 2009 11:12:20 -0400 Subject: [PATCH 135/328] cleanup QR result integration - add hierarchy to symbol results - extract QR symbols during text decode, preserving position and structure - outline QR symbols in window overlay - tmp fix converted image result propagation --- ChangeLog | 5 ++ include/zbar.h | 7 ++ zbar/convert.c | 7 +- zbar/decoder/qrcode.h | 26 ++------ zbar/decoder/qrcode/qrdec.c | 60 +---------------- zbar/decoder/qrcode/qrdectxt.c | 116 ++++++++++++++++++++++++--------- zbar/img_scanner.c | 87 ++++++++++++++++--------- zbar/symbol.c | 5 ++ zbar/symbol.h | 3 +- zbar/window.c | 22 +++++-- zbar/window.h | 13 ++-- zbar/window/win.c | 10 +++ zbar/window/x.c | 37 ++++++++++- 13 files changed, 245 insertions(+), 153 deletions(-) diff --git a/ChangeLog b/ChangeLog index 558d02e..66ebdee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,9 @@ current: + * cleanup QR result integration + - add hierarchy to symbol results + - extract symbols during text decode, preserving position and structure + - outline QR symbols in window overlay + - tmp fix converted image result propagation * factor image scanner cache and apply to QR - fix image scanner handler called once per-image (vs every decode) * QZ and clustering fixes to QR integration diff --git a/include/zbar.h b/include/zbar.h index d6fa21b..19fb4db 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -284,6 +284,13 @@ extern int zbar_symbol_get_loc_y(const zbar_symbol_t *symbol, */ extern const zbar_symbol_t *zbar_symbol_next(const zbar_symbol_t *symbol); +/** iterate components of a composite result. + * @returns the first physical component symbol of a composite result + * @returns NULL if the symbol is already a physical symbol + */ +extern const zbar_symbol_t* +zbar_symbol_first_component(const zbar_symbol_t *symbol); + /** print XML symbol element representation to user result buffer. * @see http://zbar.sourceforge.net/2008/barcode.xsd for the schema. * @param symbol is the symbol to print diff --git a/zbar/convert.c b/zbar/convert.c index 103e36e..cf65cdb 100644 --- a/zbar/convert.c +++ b/zbar/convert.c @@ -347,9 +347,11 @@ static void convert_copy (zbar_image_t *dst, dst->data = src->data; dst->datalen = src->datalen; dst->cleanup = cleanup_ref; - dst->next = (zbar_image_t*)src; +#if 0 zbar_image_t *s = (zbar_image_t*)src; + dst->next = s; _zbar_image_refcnt(s, 1); +#endif } else /* NB only for GRAY/YUV_PLANAR formats */ @@ -967,6 +969,9 @@ zbar_image_t *zbar_image_convert_resize (const zbar_image_t *src, dst->format = fmt; dst->width = width; dst->height = height; + zbar_image_t *s = (zbar_image_t*)src; + dst->next = s; + _zbar_image_refcnt(s, 1); if(src->format == fmt && src->width == width && src->height == height) { diff --git a/zbar/decoder/qrcode.h b/zbar/decoder/qrcode.h index 5f9f2ad..edf0b77 100644 --- a/zbar/decoder/qrcode.h +++ b/zbar/decoder/qrcode.h @@ -201,36 +201,24 @@ void qr_code_data_list_init(qr_code_data_list *_qrlist); /*Free a list of decoded QR code data returned by qr_reader_locate().*/ void qr_code_data_list_clear(qr_code_data_list *_qrlist); -/*Extract text from a list of QR codes. - All text is returned in UTF-8. - If _allow_partial_sa is non-zero, then any structured-append group that does - not have all of its members is decoded as separate strings for each - contiguous group of codes which are present; otherwise the whole group is - ignored. +/*Extract symbol data from a list of QR codes and attach to the image. + All text is converted to UTF-8. + Any structured-append group that does not have all of its members is decoded + as ZBAR_PARTIAL with ZBAR_PARTIAL components for the discontinuities. Note that isolated members of a structured-append group may be decoded with the wrong character set, since the correct setting cannot be propagated between codes. - Return: The number of strings which were successfully extracted from the + Return: The number of symbols which were successfully extracted from the codes; this will be at most the number of codes.*/ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, - char ***_text,int _allow_partial_sa); - + zbar_image_scanner_t *iscn, + zbar_image_t *img); qr_reader *qr_reader_alloc(void); void qr_reader_free(qr_reader *_reader); void qr_reader_reset(qr_reader *reader); -/*Locate all the QR codes in the given binary image.*/ -int qr_reader_locate(qr_reader *_reader,qr_code_data_list *_qrlist, - const unsigned char *_img,int _width,int _height); -/*Extract text from all QR codes in the given binary image. - All text is returned in UTF-8.*/ -int qr_reader_extract_text(qr_reader *_reader,const unsigned char *_img, - int _width,int _height,char ***_text,int _allow_partial_sa); - -void qr_text_list_free(char **_text,int _ntext); - /*TODO: Parse DoCoMo standard barcode data formats. See http://www.nttdocomo.co.jp/english/service/imode/make/content/barcode/function/application/ for details.*/ diff --git a/zbar/decoder/qrcode/qrdec.c b/zbar/decoder/qrcode/qrdec.c index 0fc11a9..67ee845 100644 --- a/zbar/decoder/qrcode/qrdec.c +++ b/zbar/decoder/qrcode/qrdec.c @@ -4033,42 +4033,6 @@ void qr_reader_match_centers(qr_reader *_reader,qr_code_data_list *_qrlist, free(mark); } -/*Locate (and decode) all the QR codes in the image.*/ -int qr_reader_locate(qr_reader *_reader,qr_code_data_list *_qrlist, - const unsigned char *_img,int _width,int _height){ - qr_finder_edge_pt *edge_pts; - qr_finder_center *centers; - int ncenters; - int nqrdata; - centers=NULL; - edge_pts=NULL; - nqrdata=_qrlist->nqrdata; - ncenters=qr_finder_centers_locate(¢ers,&edge_pts,NULL,_width,_height); - if(ncenters>=3){ - qr_reader_match_centers(_reader,_qrlist,centers,ncenters, - _img,_width,_height); - } - free(centers); - free(edge_pts); - return _qrlist->nqrdata-nqrdata; -} - -int qr_reader_extract_text(qr_reader *_reader,const unsigned char *_img, - int _width,int _height,char ***_text,int _allow_partial_sa){ - qr_code_data_list qrlist; - int ntext; - qr_code_data_list_init(&qrlist); - if(qr_reader_locate(_reader,&qrlist,NULL,_width,_height)>0){ - ntext=qr_code_data_list_extract_text(&qrlist,_text,_allow_partial_sa); - qr_code_data_list_clear(&qrlist); - } - else{ - *_text=NULL; - ntext=0; - } - return ntext; -} - int _zbar_qr_found_line (qr_reader *reader, int direction, const qr_finder_line *line) @@ -4086,15 +4050,6 @@ int _zbar_qr_found_line (qr_reader *reader, return(1); } -/* FIXME API cleanup */ -zbar_symbol_t *_zbar_image_scanner_alloc_sym(zbar_image_scanner_t *iscn, - zbar_symbol_type_t type, - const char *data, - int datalen); - -void _zbar_image_scanner_cache_sym(zbar_image_scanner_t *iscn, - zbar_symbol_t *sym); - int _zbar_qr_decode (zbar_image_scanner_t *iscn, qr_reader *reader, zbar_image_t *img) @@ -4133,20 +4088,9 @@ int _zbar_qr_decode (zbar_image_scanner_t *iscn, qr_reader_match_centers(reader, &qrlist, centers, ncenters, bin, img->width, img->height); - if(qrlist.nqrdata > 0) { - char **text; - int i, ntext = qr_code_data_list_extract_text(&qrlist, &text, 1); - for(i = 0; i < ntext; i++) { - zbar_symbol_t *sym; - sym = _zbar_image_scanner_alloc_sym(iscn, ZBAR_QRCODE, text[i], - strlen(text[i]) /* FIXME binary data? */); - _zbar_image_attach_symbol(img, sym); - _zbar_image_scanner_cache_sym(iscn, sym); - } - qr_text_list_free(text, ntext); - } + if(qrlist.nqrdata > 0) + nqrdata = qr_code_data_list_extract_text(&qrlist, iscn, img); - nqrdata = qrlist.nqrdata; qr_code_data_list_clear(&qrlist); free(bin); } diff --git a/zbar/decoder/qrcode/qrdectxt.c b/zbar/decoder/qrcode/qrdectxt.c index edafc7d..78868ec 100644 --- a/zbar/decoder/qrcode/qrdectxt.c +++ b/zbar/decoder/qrcode/qrdectxt.c @@ -9,6 +9,8 @@ #include #include "decoder/qrcode.h" #include "util.h" +#include "image.h" +#include "error.h" static int text_is_ascii(const unsigned char *_text,int _len){ int i; @@ -36,8 +38,22 @@ static void enc_list_mtf(iconv_t _enc_list[3],iconv_t _enc){ } } +/* FIXME API cleanup */ +zbar_symbol_t *_zbar_image_scanner_alloc_sym(zbar_image_scanner_t *iscn, + zbar_symbol_type_t type, + const char *data, + int datalen); + +void _zbar_image_scanner_cache_sym(zbar_image_scanner_t *iscn, + zbar_symbol_t *sym); + +void _zbar_image_scanner_recycle_syms(zbar_image_scanner_t*, + zbar_symbol_t**); + int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, - char ***_text,int _allow_partial_sa){ + zbar_image_scanner_t *iscn, + zbar_image_t *img) +{ iconv_t sjis_cd; iconv_t utf8_cd; iconv_t latin1_cd; @@ -88,16 +104,13 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, mark[j]=1; } } - if(!_allow_partial_sa){ - for(j=0;jnext) { + *sym = _zbar_image_scanner_alloc_sym(iscn, ZBAR_QRCODE, NULL, sa_ntext); if(sa[j]<0){ + /* generic placeholder for unfinished results */ + (*sym)->type = ZBAR_PARTIAL; + /*Skip all contiguous missing segments.*/ for(j++;j=sa_size)break; - /*Otherwise save off the current string and allocate the next one.*/ + + /* mark break in data */ sa_text[sa_ntext++]='\0'; - if(sa_ctext+1>sa_ntext){ - sa_text=(char *)realloc(sa_text,sa_ntext*sizeof(*sa_text)); - } - text[ntext++]=sa_text; - sa_ctext-=sa_ntext; - sa_ntext=0; - sa_text=(char *)malloc((sa_ctext+1)*sizeof(*sa_text)); + + /* advance to next symbol */ + *sym = _zbar_image_scanner_alloc_sym(iscn, ZBAR_QRCODE, NULL, sa_ntext); + sym = &(*sym)->next; } + qrdataj=qrdata+sa[j]; + /* expose bounding box */ + sym_add_point(*sym, qrdataj->bbox[0][0], qrdataj->bbox[0][1]); + sym_add_point(*sym, qrdataj->bbox[2][0], qrdataj->bbox[2][1]); + sym_add_point(*sym, qrdataj->bbox[3][0], qrdataj->bbox[3][1]); + sym_add_point(*sym, qrdataj->bbox[1][0], qrdataj->bbox[1][1]); + for(k=0;knentries&&!err;k++){ size_t inleft; size_t outleft; @@ -321,25 +343,59 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, if(sa_ctext+1>sa_ntext){ sa_text=(char *)realloc(sa_text,sa_ntext*sizeof(*sa_text)); } - text[ntext++]=sa_text; + + zbar_symbol_t *sa_sym; + if(sa_size > 1) { + /* create "virtual" container symbol for composite result */ + sa_sym = _zbar_image_scanner_alloc_sym(iscn, ZBAR_QRCODE, NULL, 0); + sa_sym->syms = syms; + } + else + sa_sym = syms; + sa_sym->data = sa_text; + sa_sym->data_alloc = sa_ntext; + sa_sym->datalen = sa_ntext - 1; + + /* cheap out w/axis aligned bbox for now */ + int xmin = img->width, xmax = -2; + int ymin = img->height, ymax = -2; + + /* fixup data references */ + for(syms = sa_sym->syms; syms; syms = syms->next) { + if(syms->type == ZBAR_PARTIAL) + sa_sym->type = ZBAR_PARTIAL; + else + for(j = 0; j < syms->npts; j++) { + int u = syms->pts[j].x; + if(xmin >= u) xmin = u - 1; + if(xmax <= u) xmax = u + 1; + u = syms->pts[j].y; + if(ymin >= u) ymin = u - 1; + if(ymax <= u) ymax = u + 1; + } + syms->data = sa_text + syms->datalen; + int next = (syms->next) ? syms->next->datalen : sa_ntext; + assert(next > syms->datalen); + syms->datalen = next - syms->datalen - 1; + } + if(sa_sym->syms && xmax >= -1) { + sym_add_point(sa_sym, xmin, ymin); + sym_add_point(sa_sym, xmin, ymax); + sym_add_point(sa_sym, xmax, ymax); + sym_add_point(sa_sym, xmax, ymin); + } + + _zbar_image_attach_symbol(img, sa_sym); + _zbar_image_scanner_cache_sym(iscn, sa_sym); + } + else { + _zbar_image_scanner_recycle_syms(iscn, &syms); + free(sa_text); } - else free(sa_text); } if(utf8_cd!=(iconv_t)-1)iconv_close(utf8_cd); if(sjis_cd!=(iconv_t)-1)iconv_close(sjis_cd); if(latin1_cd!=(iconv_t)-1)iconv_close(latin1_cd); free(mark); - if(ntext<=0){ - free(text); - text=NULL; - } - else if(ntextrefcnt, -1)) { + /* unlink referenced symbol */ + *symp = sym->next; + sym->next = NULL; + } + else { + /* recycle unreferenced symbol */ + if(sym->syms) { + /* FIXME retain parent ref for refd children */ + zbar_symbol_t *s; + for(s = sym->syms; s; s = s->next) { + s->data = NULL; + s->datalen = s->data_alloc = 0; + } + /* recurse */ + _zbar_image_scanner_recycle_syms(iscn, &sym->syms); + } + iscn->nsyms++; + symp = &sym->next; + } + + if(symp != symlist) { + *symp = iscn->syms; + iscn->syms = *symlist; + } + *symlist = NULL; +} + +static inline void recycle_image_syms (zbar_image_scanner_t *iscn, + zbar_image_t *img) { /* walk to root of clone tree */ while(img) { img->nsyms = 0; /* recycle image symbols */ - zbar_symbol_t **symp = &img->syms, *sym; - while((sym = *symp)) - if(_zbar_refcnt(&sym->refcnt, -1)) { - *symp = sym->next; - sym->next = NULL; - } - else { - iscn->nsyms++; - symp = &sym->next; - } - - if(symp != &img->syms) { - *symp = iscn->syms; - iscn->syms = img->syms; - } - img->syms = NULL; + _zbar_image_scanner_recycle_syms(iscn, &img->syms); /* save root */ iscn->img = img; @@ -143,6 +162,7 @@ _zbar_image_scanner_alloc_sym (zbar_image_scanner_t *iscn, zbar_symbol_t *sym = iscn->syms; if(sym) { iscn->syms = sym->next; + sym->next = NULL; assert(iscn->nsyms); iscn->nsyms--; } @@ -154,18 +174,27 @@ _zbar_image_scanner_alloc_sym (zbar_image_scanner_t *iscn, /* save new symbol data */ sym->type = type; sym->quality = 1; - sym->datalen = datalen++; sym->npts = 0; sym->cache_count = 0; sym->time = iscn->time; - if(sym->data_alloc < datalen) { + assert(!sym->syms); + if(data) { + sym->datalen = datalen++; + if(sym->data_alloc < datalen) { + if(sym->data) + free(sym->data); + sym->data_alloc = datalen; + sym->data = malloc(datalen); + } + memcpy(sym->data, data, datalen); + } + else { if(sym->data) free(sym->data); - sym->data_alloc = datalen; - sym->data = malloc(datalen); + sym->data = NULL; + sym->datalen = datalen; + sym->data_alloc = 0; } - memcpy(sym->data, data, datalen); - return(sym); } @@ -523,7 +552,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, img->format != fourcc('G','R','E','Y')) return(-1); - recycle_syms(iscn, img); + recycle_image_syms(iscn, img); unsigned w = img->width; unsigned h = img->height; @@ -615,14 +644,14 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, } iscn->dy = 0; + img = iscn->img; + iscn->img = NULL; + #ifdef ENABLE_QRCODE _zbar_qr_decode(iscn, iscn->qr, img); #endif dprintf(1, "\n"); - img = iscn->img; - iscn->img = NULL; - /* FIXME tmp hack to filter bad EAN results */ if(img->nsyms && !iscn->enable_cache && (density == 1 || CFG(iscn, ZBAR_CFG_Y_DENSITY) == 1)) { @@ -644,7 +673,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, /* FIXME option to only report count == 0 */ if(img->nsyms && iscn->handler) - iscn->handler(iscn->img, iscn->userdata); + iscn->handler(img, iscn->userdata); return(img->nsyms); } diff --git a/zbar/symbol.c b/zbar/symbol.c index cf131a1..2f0da03 100644 --- a/zbar/symbol.c +++ b/zbar/symbol.c @@ -115,6 +115,11 @@ const zbar_symbol_t *zbar_symbol_next (const zbar_symbol_t *sym) return((sym) ? sym->next : NULL); } +const zbar_symbol_t *zbar_symbol_first_component (const zbar_symbol_t *sym) +{ + return((sym) ? sym->syms : NULL); +} + static const char *xmlfmt[] = { "syms; s; s = s->next) + window_outline_symbol(w, 1, s); + _zbar_window_draw_polygon(w, color, sym->pts, sym->npts); +} + static inline int window_draw_overlay (zbar_window_t *w) { /* FIXME TBD @@ -76,10 +86,14 @@ static inline int window_draw_overlay (zbar_window_t *w) /* FIXME outline each symbol */ const zbar_symbol_t *sym = zbar_image_first_symbol(w->image); for(; sym; sym = sym->next) { - int i; - for(i = 0; i < sym->npts; i++) { - uint32_t color = ((sym->cache_count < 0) ? 4 : 2); - _zbar_window_draw_marker(w, color, &sym->pts[i]); + uint32_t color = ((sym->cache_count < 0) ? 4 : 2); + if(sym->type == ZBAR_QRCODE) + window_outline_symbol(w, color, sym); + else { + /* FIXME linear bbox broken */ + int i; + for(i = 0; i < sym->npts; i++) + _zbar_window_draw_marker(w, color, &sym->pts[i]); } } } diff --git a/zbar/window.h b/zbar/window.h index 5ce34fb..67b22b5 100644 --- a/zbar/window.h +++ b/zbar/window.h @@ -112,20 +112,17 @@ static inline int _zbar_window_add_format (zbar_window_t *w, /* PAL interface */ -extern int _zbar_window_attach(zbar_window_t*, - void*, - unsigned long); -extern int _zbar_window_expose(zbar_window_t *w, int, int, int, int); -extern int _zbar_window_resize(zbar_window_t *w); +extern int _zbar_window_attach(zbar_window_t*, void*, unsigned long); +extern int _zbar_window_expose(zbar_window_t*, int, int, int, int); +extern int _zbar_window_resize(zbar_window_t*); extern int _zbar_window_clear(zbar_window_t*); extern int _zbar_window_flush(zbar_window_t*); -extern int _zbar_window_draw_logo(zbar_window_t *w); +extern int _zbar_window_draw_logo(zbar_window_t*); extern int _zbar_window_draw_marker(zbar_window_t*, uint32_t, const point_t*); +extern int _zbar_window_draw_polygon(zbar_window_t*, uint32_t, const point_t*, int); #if 0 extern int _zbar_window_draw_line(zbar_window_t*, uint32_t, const point_t*, const point_t*); -extern int _zbar_window_draw_outline(zbar_window_t*, uint32_t, - const symbol_t*); extern int _zbar_window_draw_text(zbar_window_t*, uint32_t, const point_t*, const char*); #endif diff --git a/zbar/window/win.c b/zbar/window/win.c index 827ea2c..31c4787 100644 --- a/zbar/window/win.c +++ b/zbar/window/win.c @@ -28,10 +28,20 @@ int _zbar_window_vfw_init(zbar_window_t *w); int _zbar_window_dib_init(zbar_window_t *w); +int _zbar_window_draw_polygon (zbar_window_t *w, + uint32_t rgb, + const point_t *pts, + int npts) +{ + /* FIXME TBD */ + return(-1); +} + int _zbar_window_draw_marker(zbar_window_t *w, uint32_t rgb, const point_t *p) { + /* FIXME TBD */ return(-1); } diff --git a/zbar/window/x.c b/zbar/window/x.c index 974be1f..9e2f05e 100644 --- a/zbar/window/x.c +++ b/zbar/window/x.c @@ -22,6 +22,7 @@ *------------------------------------------------------------------------*/ #include "window.h" +#include "image.h" #include "x.h" static inline unsigned long window_alloc_color (zbar_window_t *w, @@ -220,9 +221,34 @@ int _zbar_window_clear (zbar_window_t *w) return(0); } -int _zbar_window_draw_marker(zbar_window_t *w, - uint32_t rgb, - const point_t *p) +int _zbar_window_draw_polygon (zbar_window_t *w, + uint32_t rgb, + const point_t *pts, + int npts) +{ + window_state_t *xs = w->state; + XSetForeground(w->display, xs->gc, xs->colors[rgb]); + + XPoint xpts[npts + 1]; + int i; + for(i = 0; i < npts; i++) { + xpts[i].x = pts[i].x; + if(w->width != w->image->width) + xpts[i].x = xpts[i].x * w->width / w->image->width; + xpts[i].y = pts[i].y; + if(w->height != w->image->height) + xpts[i].y = xpts[i].y * w->height / w->image->height; + } + xpts[npts] = xpts[0]; + + XDrawLines(w->display, w->xwin, xs->gc, xpts, npts + 1, CoordModeOrigin); + + return(0); +} + +int _zbar_window_draw_marker (zbar_window_t *w, + uint32_t rgb, + const point_t *p) { window_state_t *xs = w->state; XSetForeground(w->display, xs->gc, xs->colors[rgb]); @@ -239,6 +265,11 @@ int _zbar_window_draw_marker(zbar_window_t *w, else if(y > w->height - 4) y = w->height - 4; + if(w->width != w->image->width) + x = x * w->width / w->image->width; + if(w->height != w->image->height) + y = y * w->height / w->image->height; + XDrawRectangle(w->display, w->xwin, xs->gc, x - 2, y - 2, 4, 4); XDrawLine(w->display, w->xwin, xs->gc, x, y - 3, x, y + 3); XDrawLine(w->display, w->xwin, xs->gc, x - 3, y, x + 3, y); From f1224ac0a23b71df3a468536f5c08849df20aa8f Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 24 Sep 2009 11:35:22 -0400 Subject: [PATCH 136/328] extract explicit result container, separate from image - remove (broken/tmp) converted image result sharing - add explicit symbol recycle API, update processor/widgets to use - cleanup and update C++ API - update Python/Perl APIs - fix broken and add new Python/Perl tests --- ChangeLog | 6 + gtk/zbargtk.c | 2 + include/zbar.h | 93 +++++++++++- include/zbar/Image.h | 81 +++------- include/zbar/ImageScanner.h | 5 + include/zbar/Symbol.h | 249 ++++++++++++++++++++++++++---- perl/ZBar.pm | 2 +- perl/ZBar.xs | 39 +++-- perl/ZBar/ImageScanner.pod | 5 + perl/ZBar/Symbol.pod | 7 + perl/t/Decoder.t | 3 + perl/t/Image.t | 30 +++- python/Makefile.am.inc | 3 +- python/image.c | 121 +++++---------- python/imagescanner.c | 17 +++ python/symbol.c | 37 +++-- python/symboliter.c | 112 ++++++++++++++ python/symbolset.c | 90 +++++++++++ python/test/test_zbar.py | 125 +++++++++++---- python/zbarmodule.c | 5 +- python/zbarmodule.h | 20 ++- qt/QZBarThread.cpp | 2 + zbar/Makefile.am.inc | 2 +- zbar/convert.c | 5 - zbar/decoder/qrcode/qrdec.c | 184 ---------------------- zbar/decoder/qrcode/qrdectxt.c | 92 ++++++----- zbar/image.c | 27 +++- zbar/image.h | 19 +-- zbar/img_scanner.c | 268 +++++++++++++++++++++++---------- zbar/img_scanner.h | 38 +++++ zbar/processor.c | 8 +- zbar/symbol.c | 60 +++++++- zbar/symbol.h | 34 +++-- zbar/window.c | 15 +- 34 files changed, 1196 insertions(+), 610 deletions(-) create mode 100644 python/symboliter.c create mode 100644 python/symbolset.c create mode 100644 zbar/img_scanner.h diff --git a/ChangeLog b/ChangeLog index 7354fb9..49e89f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,10 @@ current: + * extract explicit result container, separate from image + - remove (broken/tmp) converted image result sharing + - add explicit symbol recycle API, update processor/widgets to use + - cleanup and update C++ API + - update Python/Perl APIs + - fix broken and add new Python/Perl tests * cleanup QR result integration - add hierarchy to symbol results - extract symbols during text decode, preserving position and structure diff --git a/gtk/zbargtk.c b/gtk/zbargtk.c index 3c6e82c..eb03227 100644 --- a/gtk/zbargtk.c +++ b/gtk/zbargtk.c @@ -213,7 +213,9 @@ static inline int zbar_gtk_process_image (ZBarGtk *self, if(!tmp) return(-1); + zbar_image_scanner_recycle_image(zbar->scanner, image); int rc = zbar_scan_image(zbar->scanner, tmp); + zbar_image_set_symbols(image, zbar_image_get_symbols(tmp)); zbar_image_destroy(tmp); if(rc < 0) return(rc); diff --git a/include/zbar.h b/include/zbar.h index 19fb4db..1121872 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -95,7 +95,7 @@ typedef enum zbar_symbol_type_e { ZBAR_I25 = 25, /**< Interleaved 2 of 5. @since 0.4 */ ZBAR_CODE39 = 39, /**< Code 39. @since 0.4 */ ZBAR_PDF417 = 57, /**< PDF417. @since 0.6 */ - ZBAR_QRCODE = 64, /**< QR Code. @since 0.9 */ + ZBAR_QRCODE = 64, /**< QR Code. @since 0.10 */ ZBAR_CODE128 = 128, /**< Code 128 */ ZBAR_SYMBOL = 0x00ff, /**< mask for base symbol type */ ZBAR_ADDON2 = 0x0200, /**< 2-digit add-on flag */ @@ -193,6 +193,12 @@ extern zbar_error_t _zbar_get_error_code(const void *object); /*@}*/ +struct zbar_symbol_s; +typedef struct zbar_symbol_s zbar_symbol_t; + +struct zbar_symbol_set_s; +typedef struct zbar_symbol_set_s zbar_symbol_set_t; + /*------------------------------------------------------------*/ /** @name Symbol interface @@ -201,9 +207,9 @@ extern zbar_error_t _zbar_get_error_code(const void *object); */ /*@{*/ -struct zbar_symbol_s; -/** opaque decoded symbol object. */ -typedef struct zbar_symbol_s zbar_symbol_t; +/** @typedef zbar_symbol_t + * opaque decoded symbol object. + */ /** symbol reference count manipulation. * increment the reference count when you store a new reference to the @@ -278,15 +284,24 @@ 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); -/** iterate the result set. - * @returns the next result symbol, or +/** 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 */ extern const zbar_symbol_t *zbar_symbol_next(const zbar_symbol_t *symbol); +/** retrieve components of a composite result. + * @returns the symbol set containing the components + * @returns NULL if the symbol is already a physical symbol + * @since 0.10 + */ +extern const zbar_symbol_set_t* +zbar_symbol_get_components(const zbar_symbol_t *symbol); + /** iterate components of a composite result. * @returns the first physical component symbol of a composite result * @returns NULL if the symbol is already a physical symbol + * @since 0.10 */ extern const zbar_symbol_t* zbar_symbol_first_component(const zbar_symbol_t *symbol); @@ -306,6 +321,44 @@ extern char *zbar_symbol_xml(const zbar_symbol_t *symbol, /*@}*/ +/*------------------------------------------------------------*/ +/** @name Symbol Set interface + * container for decoded result symbols associated with an image + * or a composite symbol. + * @since 0.10 + */ +/*@{*/ + +/** @typedef zbar_symbol_set_t + * opaque symbol iterator object. + * @since 0.10 + */ + +/** reference count manipulation. + * increment the reference count when you store a new reference. + * decrement when the reference is no longer used. do not refer to + * the object any longer once references have been released. + * @since 0.10 + */ +extern void zbar_symbol_set_ref(zbar_symbol_set_t *symbols, + int refs); + +/** retrieve set size. + * @returns the number of symbols in the set. + * @since 0.10 + */ +extern int zbar_symbol_set_get_size(const zbar_symbol_set_t *symbols); + +/** set iterator. + * @returns the first decoded symbol result in a set + * @returns NULL if the set is empty + * @since 0.10 + */ +extern const zbar_symbol_t* +zbar_symbol_set_first_symbol(const zbar_symbol_set_t *symbols); + +/*@}*/ + /*------------------------------------------------------------*/ /** @name Image interface * stores image data samples along with associated format and size @@ -413,6 +466,23 @@ extern const void *zbar_image_get_data(const zbar_image_t *image); */ extern unsigned long zbar_image_get_data_length(const zbar_image_t *img); +/** retrieve the decoded results. + * @returns the (possibly empty) set of decoded symbols + * @returns NULL if the image has not been scanned + * @since 0.10 + */ +extern const zbar_symbol_set_t* +zbar_image_get_symbols(const zbar_image_t *image); + +/** associate the specified symbol set with the image, replacing any + * existing results. use NULL to release the current results from the + * image. + * @see zbar_image_scanner_recycle_image() + * @since 0.10 + */ +extern void zbar_image_set_symbols(zbar_image_t *image, + const zbar_symbol_set_t *symbols); + /** image_scanner decode result iterator. * @returns the first decoded symbol result for an image * or NULL if no results are available @@ -980,6 +1050,15 @@ zbar_image_scanner_parse_config (zbar_image_scanner_t *scanner, extern void zbar_image_scanner_enable_cache(zbar_image_scanner_t *scanner, int enable); +/** remove any previously decoded results from the image scanner and the + * specified image. somewhat more efficient version of + * zbar_image_set_symbols(image, NULL) which may retain memory for + * subsequent decodes + * @since 0.10 + */ +extern void zbar_image_scanner_recycle_image(zbar_image_scanner_t *scanner, + zbar_image_t *image); + /** scan for symbols in provided image. The image format must be * "Y800" or "GRAY". * @returns >0 if symbols were successfully decoded from the image, @@ -1177,7 +1256,7 @@ static inline zbar_symbol_type_t zbar_scan_rgb24 (zbar_scanner_t *scanner, extern unsigned zbar_scanner_get_width(const zbar_scanner_t *scanner); /** retrieve sample position of last edge. - * @since 0.9 + * @since 0.10 */ extern unsigned zbar_scanner_get_edge(const zbar_scanner_t *scn, unsigned offset, diff --git a/include/zbar/Image.h b/include/zbar/Image.h index 387cb27..e1d9644 100644 --- a/include/zbar/Image.h +++ b/include/zbar/Image.h @@ -72,65 +72,24 @@ class Image { } }; - /// iteration over Symbol result objects in a scanned Image. - class SymbolIterator - : public std::iterator { - + class SymbolIterator : public zbar::SymbolIterator { public: - /// constructor. - SymbolIterator (const Image *img = NULL) - { - if(img) { - const zbar_symbol_t *zsym = zbar_image_first_symbol(*img); - _sym.init(zsym); - } - } + /// default constructor. + SymbolIterator () + : zbar::SymbolIterator() + { } /// constructor. - SymbolIterator (const SymbolIterator& iter) - : _sym(iter._sym) + SymbolIterator (const SymbolSet &syms) + : zbar::SymbolIterator(syms) { } - /// advance iterator to next Symbol. - SymbolIterator& operator++ () - { - const zbar_symbol_t *zsym = _sym; - if(zsym) { - zsym = zbar_symbol_next(zsym); - _sym.init(zsym); - } - return(*this); - } - - /// retrieve currently referenced Symbol. - const Symbol& operator* () const - { - return(_sym); - } - - /// access currently referenced Symbol. - const Symbol* operator-> () const - { - return(&_sym); - } - - /// test if two iterators refer to the same Symbol - bool operator== (const SymbolIterator& iter) const - { - return(_sym == iter._sym); - } - - /// test if two iterators refer to the same Symbol - bool operator!= (const SymbolIterator& iter) const - { - return(!(*this == iter)); - } - - private: - Symbol _sym; + /// copy constructor. + SymbolIterator (const SymbolIterator& iter) + : zbar::SymbolIterator(iter) + { } }; - /// constructor. /// create a new Image with the specified parameters Image (unsigned width = 0, @@ -279,14 +238,22 @@ class Image { throw FormatError(); } + const SymbolSet get_symbols () const { + return(SymbolSet(zbar_image_get_symbols(_img))); + } + + void set_symbols (const SymbolSet &syms) { + zbar_image_set_symbols(_img, syms); + } + /// create a new SymbolIterator over decoded results. - SymbolIterator symbol_begin() const { - return(SymbolIterator(this)); + SymbolIterator symbol_begin () const { + return(SymbolIterator(get_symbols())); } /// return a SymbolIterator suitable for ending iteration. - SymbolIterator symbol_end() const { - return(SymbolIterator(_sym_iter_end)); + SymbolIterator symbol_end () const { + return(SymbolIterator()); } protected: @@ -316,10 +283,8 @@ class Image { private: zbar_image_t *_img; - SymbolIterator _sym_iter_end; }; } #endif - diff --git a/include/zbar/ImageScanner.h b/include/zbar/ImageScanner.h index a401d2e..2e7ebf4 100644 --- a/include/zbar/ImageScanner.h +++ b/include/zbar/ImageScanner.h @@ -91,6 +91,11 @@ class ImageScanner { zbar_image_scanner_enable_cache(_scanner, enable); } + void recycle_image (Image &image) + { + zbar_image_scanner_recycle_image(_scanner, image); + } + /// scan for symbols in provided image. /// see zbar_scan_image() int scan (Image& image) diff --git a/include/zbar/Symbol.h b/include/zbar/Symbol.h index 8fde92b..61cbe38 100644 --- a/include/zbar/Symbol.h +++ b/include/zbar/Symbol.h @@ -33,9 +33,65 @@ #include #include #include +#include namespace zbar { +class SymbolIterator; + +/// container for decoded result symbols associated with an image +/// or a composite symbol. + +class SymbolSet { +public: + /// constructor. + SymbolSet (const zbar_symbol_set_t *syms = NULL) + : _syms(syms) + { + ref(); + } + + /// copy constructor. + SymbolSet (const SymbolSet& syms) + : _syms(syms._syms) + { + ref(); + } + + /// destructor. + ~SymbolSet () + { + ref(-1); + } + + /// manipulate reference count. + void ref (int delta = 1) const + { + if(_syms) + zbar_symbol_set_ref((zbar_symbol_set_t*)_syms, delta); + } + + /// cast to C symbol set. + operator const zbar_symbol_set_t* () const + { + return(_syms); + } + + int get_size () + { + return((_syms) ? zbar_symbol_set_get_size(_syms) : 0); + } + + /// create a new SymbolIterator over decoded results. + SymbolIterator symbol_begin() const; + + /// return a SymbolIterator suitable for ending iteration. + const SymbolIterator symbol_end() const; + +private: + const zbar_symbol_set_t *_syms; +}; + /// decoded barcode symbol result object. stores type, data, and /// image location of decoded symbol @@ -50,6 +106,10 @@ class Symbol { Point () { } + Point(int x, int y) + : x(x), y(y) + { } + /// copy constructor. Point (const Point& pt) { @@ -69,6 +129,7 @@ class Symbol { : _sym(sym), _index(index) { + sym->ref(1); if(!sym || (unsigned)_index >= zbar_symbol_get_loc_size(*_sym)) _index = -1; @@ -78,24 +139,31 @@ class Symbol { PointIterator (const PointIterator& iter) : _sym(iter._sym), _index(iter._index) - { } + { + _sym->ref(); + } + + /// destructor. + ~PointIterator () + { + _sym->ref(-1); + } /// advance iterator to next Point. PointIterator& operator++ () { - if(_index >= 0) { - _pt.x = zbar_symbol_get_loc_x(*_sym, ++_index); - _pt.y = zbar_symbol_get_loc_y(*_sym, _index); - if(_pt.x < 0 || _pt.y < 0) - _index = -1; - } + unsigned int i = ++_index; + if(i >= zbar_symbol_get_loc_size(*_sym)) + _index = -1; return(*this); } /// retrieve currently referenced Point. - const Point& operator* () const + const Point operator* () const { - return(_pt); + assert(_index >= 0); + return(Point(zbar_symbol_get_loc_x(*_sym, _index), + zbar_symbol_get_loc_y(*_sym, _index))); } /// test if two iterators refer to the same Point in the same @@ -116,7 +184,6 @@ class Symbol { private: const Symbol *_sym; int _index; - Point _pt; }; /// constructor. @@ -125,28 +192,31 @@ class Symbol { _xmllen(0) { init(sym); + ref(); } + /// copy constructor. + Symbol (const Symbol& sym) + : _sym(sym._sym), + _type(sym._type), + _data(sym._data), + _xmlbuf(NULL), + _xmllen(0) + { + ref(); + } + + /// destructor. ~Symbol () { if(_xmlbuf) free(_xmlbuf); + ref(-1); } - /// initialize Symbol from C symbol object. - void init (const zbar_symbol_t *sym) + void ref (int delta = 1) const { - _sym = sym; - if(sym) { - _type = zbar_symbol_get_type(sym); - _data = std::string(zbar_symbol_get_data(sym), - zbar_symbol_get_data_length(sym)); - _count = zbar_symbol_get_count(sym); - } - else { - _type = ZBAR_NONE; - _data = ""; - _count = -1; - } + if(_sym) + zbar_symbol_ref((zbar_symbol_t*)_sym, delta); } /// cast to C symbol. @@ -194,7 +264,7 @@ class Symbol { /// retrieve length of binary data unsigned get_data_length () const { - return(zbar_symbol_get_data_length(_sym)); + return((_sym) ? zbar_symbol_get_data_length(_sym) : 0); } /// retrieve inter-frame coherency count. @@ -202,7 +272,12 @@ class Symbol { /// @since 1.5 int get_count () const { - return(_count); + return((_sym) ? zbar_symbol_get_count(_sym) : -1); + } + + SymbolSet get_components () const + { + return(SymbolSet((_sym) ? zbar_symbol_get_components(_sym) : NULL)); } /// create a new PointIterator at the start of the location @@ -213,45 +288,153 @@ class Symbol { } /// return a PointIterator suitable for ending iteration. - const PointIterator& point_end() const + const PointIterator point_end() const { - return(_point_iter_end); + return(PointIterator()); } /// see zbar_symbol_get_loc_size(). int get_location_size () const { - return(zbar_symbol_get_loc_size(_sym)); + return((_sym) ? zbar_symbol_get_loc_size(_sym) : 0); } /// see zbar_symbol_get_loc_x(). int get_location_x (unsigned index) const { - return(zbar_symbol_get_loc_x(_sym, index)); + return((_sym) ? zbar_symbol_get_loc_x(_sym, index) : -1); } /// see zbar_symbol_get_loc_y(). int get_location_y (unsigned index) const { - return(zbar_symbol_get_loc_y(_sym, index)); + return((_sym) ? zbar_symbol_get_loc_y(_sym, index) : -1); } /// see zbar_symbol_xml(). const std::string xml () const { + if(!_sym) + return(""); return(zbar_symbol_xml(_sym, (char**)&_xmlbuf, (unsigned*)&_xmllen)); } +protected: + + friend class SymbolIterator; + + /// (re)initialize Symbol from C symbol object. + void init (const zbar_symbol_t *sym = NULL) + { + _sym = sym; + if(sym) { + _type = zbar_symbol_get_type(sym); + _data = std::string(zbar_symbol_get_data(sym), + zbar_symbol_get_data_length(sym)); + } + else { + _type = ZBAR_NONE; + _data = ""; + } + } + private: const zbar_symbol_t *_sym; zbar_symbol_type_t _type; std::string _data; - int _count; - PointIterator _point_iter_end; char *_xmlbuf; unsigned _xmllen; }; +/// iteration over Symbol result objects in a scanned Image or SymbolSet. +class SymbolIterator + : public std::iterator { + +public: + /// default constructor. + SymbolIterator () + { } + + /// constructor. + SymbolIterator (const SymbolSet &syms) + : _syms(syms) + { + const zbar_symbol_set_t *zsyms = _syms; + if(zsyms) + _sym.init(zbar_symbol_set_first_symbol(zsyms)); + } + + /// copy constructor. + SymbolIterator (const SymbolIterator& iter) + : _syms(iter._syms) + { + const zbar_symbol_set_t *zsyms = _syms; + if(zsyms) + _sym.init(zbar_symbol_set_first_symbol(zsyms)); + } + + ~SymbolIterator () + { + _sym.init(); + } + + /// 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)); + } + return(*this); + } + + /// retrieve currently referenced Symbol. + const Symbol operator* () const + { + return(_sym); + } + + /// access currently referenced Symbol. + const Symbol* operator-> () const + { + return(&_sym); + } + + /// test if two iterators refer to the same Symbol + bool operator== (const SymbolIterator& iter) const + { + // it is enough to test the symbols, as they belong + // to only one set (also simplifies invalid case) + return(_sym == iter._sym); + } + + /// test if two iterators refer to the same Symbol + bool operator!= (const SymbolIterator& iter) const + { + return(!(*this == iter)); + } + + const SymbolIterator end () const { + return(SymbolIterator()); + } + +private: + const SymbolSet _syms; + Symbol _sym; +}; + +inline SymbolIterator SymbolSet::symbol_begin () const { + return(SymbolIterator(*this)); +} + +inline const SymbolIterator SymbolSet::symbol_end () const { + return(SymbolIterator()); +} + /// @relates Symbol /// stream the string representation of a Symbol. static inline std::ostream& operator<< (std::ostream& out, diff --git a/perl/ZBar.pm b/perl/ZBar.pm index 8e0a902..f289c01 100644 --- a/perl/ZBar.pm +++ b/perl/ZBar.pm @@ -32,7 +32,7 @@ our @ISA = qw(Exporter); our @EXPORT_OK = qw(SPACE BAR version increase_verbosity set_verbosity); -our $VERSION = '0.02'; +our $VERSION = '0.03'; require XSLoader; XSLoader::load('Barcode::ZBar', $VERSION); diff --git a/perl/ZBar.xs b/perl/ZBar.xs index 858d85a..208a799 100644 --- a/perl/ZBar.xs +++ b/perl/ZBar.xs @@ -56,12 +56,12 @@ static AV *LOOKUP_zbar_config_t = NULL; #define CONSTANT(typ, prefix, sym, name) \ do { \ - SV *c = newSViv(ZBAR_ ## prefix ## sym); \ + SV *c = newSViv(ZBAR_ ## prefix ## sym); \ sv_setpv(c, name); \ SvIOK_on(c); \ newCONSTSUB(stash, #sym, c); \ - av_store(LOOKUP_zbar_ ## typ ## _t, \ - ZBAR_ ## prefix ## sym, \ + av_store(LOOKUP_zbar_ ## typ ## _t, \ + ZBAR_ ## prefix ## sym, \ SvREFCNT_inc(c)); \ } while(0) @@ -82,6 +82,17 @@ static inline void check_error (int rc, void *obj) } } +#define PUSH_SYMS(x) \ + do { \ + const zbar_symbol_t *sym = (const zbar_symbol_t*)(x); \ + for(; sym; sym = zbar_symbol_next(sym)) { \ + zbar_symbol_t *s = (zbar_symbol_t*)sym; \ + zbar_symbol_ref(s, 1); \ + XPUSHs(sv_setref_pv(sv_newmortal(), "Barcode::ZBar::Symbol", \ + (void*)sym)); \ + } \ + } while(0); + static void image_cleanup_handler (zbar_image_t *image) { SV *data = zbar_image_get_userdata(image); @@ -290,6 +301,7 @@ BOOT: CONSTANT(symbol_type, , I25, zbar_get_symbol_name(ZBAR_I25)); CONSTANT(symbol_type, , CODE39, zbar_get_symbol_name(ZBAR_CODE39)); CONSTANT(symbol_type, , PDF417, zbar_get_symbol_name(ZBAR_PDF417)); + CONSTANT(symbol_type, , QRCODE, zbar_get_symbol_name(ZBAR_QRCODE)); CONSTANT(symbol_type, , CODE128, zbar_get_symbol_name(ZBAR_CODE128)); } @@ -335,6 +347,12 @@ zbar_symbol_get_loc(symbol) av_push(pt, newSVuv(zbar_symbol_get_loc_y(symbol, i))); } +SV * +get_components(symbol) + Barcode::ZBar::Symbol symbol + PPCODE: + PUSH_SYMS(zbar_symbol_first_component(symbol)); + MODULE = Barcode::ZBar PACKAGE = Barcode::ZBar::Image PREFIX = zbar_image_ @@ -392,16 +410,8 @@ zbar_image_get_data(image) SV * get_symbols(image) Barcode::ZBar::Image image - PREINIT: - const zbar_symbol_t *sym; PPCODE: - sym = zbar_image_first_symbol(image); - for(; sym; sym = zbar_symbol_next(sym)) { - zbar_symbol_t *s = (zbar_symbol_t*)sym; - zbar_symbol_ref(s, 1); - XPUSHs(sv_setref_pv(sv_newmortal(), "Barcode::ZBar::Symbol", - (void*)sym)); - } + PUSH_SYMS(zbar_image_first_symbol(image)); void zbar_image_set_format(image, format) @@ -605,6 +615,11 @@ zbar_image_scanner_enable_cache(scanner, enable) Barcode::ZBar::ImageScanner scanner int enable +void +zbar_image_scanner_recycle_image(scanner, image) + Barcode::ZBar::ImageScanner scanner + Barcode::ZBar::Image image + int scan_image(scanner, image) Barcode::ZBar::ImageScanner scanner diff --git a/perl/ZBar/ImageScanner.pod b/perl/ZBar/ImageScanner.pod index db19982..b42ebf0 100644 --- a/perl/ZBar/ImageScanner.pod +++ b/perl/ZBar/ImageScanner.pod @@ -63,6 +63,11 @@ Enable the inter-image result consistency cache. Apply a decoder configuration setting. See the documentation for C/C for available configuration options. +=item recycle_image([I]) + +Remove previously decoded results from a Barcode::ZBar::Image and +recycle the associated memory. + =back =head1 SEE ALSO diff --git a/perl/ZBar/Symbol.pod b/perl/ZBar/Symbol.pod index 7838549..4ccd9b5 100644 --- a/perl/ZBar/Symbol.pod +++ b/perl/ZBar/Symbol.pod @@ -72,6 +72,11 @@ Current cache count of the symbol. This integer value provides inter-scan reliability and redundancy information if enabled at the Barcode::ZBar::ImageScanner. +=item get_components() + +Components of a composite result. This yields an array of physical +component symbols that were combined to form a composite result. + =over 2 =item * @@ -119,6 +124,8 @@ Bar code type "symbology" constants: =item CODE128 +=item QRCODE + =item PDF417 =back diff --git a/perl/t/Decoder.t b/perl/t/Decoder.t index 2938d8d..f7e16f4 100755 --- a/perl/t/Decoder.t +++ b/perl/t/Decoder.t @@ -58,6 +58,9 @@ is($decoder->get_color(), Barcode::ZBar::SPACE, 'reset color'); ######################### +$decoder->set_config(Barcode::ZBar::Symbol::QRCODE, + Barcode::ZBar::Config::ENABLE, 0); + my $encoded = '9 111 212241113121211311141132 11111 311213121312121332111132 111 9'; diff --git a/perl/t/Image.t b/perl/t/Image.t index 960540e..7df06e9 100755 --- a/perl/t/Image.t +++ b/perl/t/Image.t @@ -3,7 +3,7 @@ use warnings; use strict; -use Test::More tests => 17; +use Test::More tests => 22; ######################### @@ -51,7 +51,7 @@ is_deeply([$image->get_size()], [114, 80], 'size accessors'); # FIXME avoid skipping these (eg embed image vs ImageMagick) SKIP: { eval { require Image::Magick }; - skip "Image::Magick not installed", 8 if $@; + skip "Image::Magick not installed", 13 if $@; my $im = Image::Magick->new(); my $err = $im->Read('t/barcode.png'); @@ -67,6 +67,19 @@ SKIP: { $image->set_data($data); } + $image = $image->convert('Y800'); + isa_ok($image, 'Barcode::ZBar::Image', 'image'); + + ######################### + + is($image->get_format(), 'Y800', 'converted image format'); + + ######################### + + is_deeply([$image->get_size()], [114, 80], 'converted image size'); + + ######################### + is($scanner->scan_image($image), 1, 'scan result'); ######################### @@ -119,6 +132,19 @@ SKIP: { diag($failure); ######################### + + my @comps = $sym->get_components(); + is(scalar(@comps), 0, 'components size'); + + ######################### } +$scanner->recycle_image($image); + +my @symbols = $image->get_symbols(); +is(scalar(@symbols), 0, 'recycled result size'); + +######################### + + # FIXME more image tests diff --git a/python/Makefile.am.inc b/python/Makefile.am.inc index f2839d4..ac12c03 100644 --- a/python/Makefile.am.inc +++ b/python/Makefile.am.inc @@ -5,7 +5,8 @@ python_zbar_la_LDFLAGS = -shared -module -avoid-version -export-dynamic \ python_zbar_la_LIBADD = $(PYTHON_LIBS) zbar/libzbar.la $(AM_LIBADD) python_zbar_la_SOURCES = python/zbarmodule.c python/zbarmodule.h \ - python/enum.c python/exception.c python/symbol.c python/image.c \ + python/enum.c python/exception.c python/symbol.c python/symbolset.c \ + python/symboliter.c python/image.c \ python/processor.c python/imagescanner.c python/decoder.c python/scanner.c EXTRA_DIST += python/test/barcode.png python/test/test_zbar.py diff --git a/python/image.c b/python/image.c index debc504..1749c79 100644 --- a/python/image.c +++ b/python/image.c @@ -23,92 +23,6 @@ #include "zbarmodule.h" -static char symboliter_doc[] = PyDoc_STR( - "symbol iterator.\n" - "\n" - "iterates over decode results attached to an image."); - -static int -symboliter_traverse (zbarSymbolIter *self, - visitproc visit, - void *arg) -{ - Py_VISIT(self->img); - return(0); -} - -static int -symboliter_clear (zbarSymbolIter *self) -{ - if(self->zsym) { - zbar_symbol_t *zsym = (zbar_symbol_t*)self->zsym; - self->zsym = NULL; - zbar_symbol_ref(zsym, -1); - } - Py_CLEAR(self->img); - return(0); -} - -static void -symboliter_dealloc (zbarSymbolIter *self) -{ - symboliter_clear(self); - ((PyObject*)self)->ob_type->tp_free((PyObject*)self); -} - -static zbarSymbolIter* -symboliter_iter (zbarSymbolIter *self) -{ - Py_INCREF(self); - return(self); -} - -static zbarSymbol* -symboliter_iternext (zbarSymbolIter *self) -{ - if(!self->zsym) - self->zsym = zbar_image_first_symbol(self->img->zimg); - else { - zbar_symbol_t *zsym = (zbar_symbol_t*)self->zsym; - zbar_symbol_ref(zsym, -1); - self->zsym = zbar_symbol_next(self->zsym); - } - if(!self->zsym) - return(NULL); - zbar_symbol_t *zsym = (zbar_symbol_t*)self->zsym; - zbar_symbol_ref(zsym, 1); - return(zbarSymbol_FromSymbol(self->img, self->zsym)); -} - -PyTypeObject zbarSymbolIter_Type = { - PyObject_HEAD_INIT(NULL) - .tp_name = "zbar.SymbolIter", - .tp_doc = symboliter_doc, - .tp_basicsize = sizeof(zbarSymbolIter), - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC, - .tp_traverse = (traverseproc)symboliter_traverse, - .tp_clear = (inquiry)symboliter_clear, - .tp_dealloc = (destructor)symboliter_dealloc, - .tp_iter = (getiterfunc)symboliter_iter, - .tp_iternext = (iternextfunc)symboliter_iternext, -}; - -static zbarSymbolIter* -zbarSymbolIter_New (zbarImage *img) -{ - zbarSymbolIter *self; - self = PyObject_GC_New(zbarSymbolIter, &zbarSymbolIter_Type); - if(!self) - return(NULL); - - Py_INCREF(img); - self->img = img; - self->zsym = NULL; - return(self); -} - - static char image_doc[] = PyDoc_STR( "image object.\n" "\n" @@ -167,10 +81,42 @@ image_dealloc (zbarImage *self) ((PyObject*)self)->ob_type->tp_free((PyObject*)self); } +static zbarSymbolSet* +image_get_symbols (zbarImage *self, + void *closure) +{ + const zbar_symbol_set_t *zsyms = zbar_image_get_symbols(self->zimg); + return(zbarSymbolSet_FromSymbolSet(zsyms)); +} + +static int +image_set_symbols (zbarImage *self, + PyObject *value, + void *closure) +{ + const zbar_symbol_set_t *zsyms; + if(!value || value == Py_None) + zsyms = NULL; + else if(zbarSymbolSet_Check(value)) + zsyms = ((zbarSymbolSet*)value)->zsyms; + else { + PyErr_Format(PyExc_TypeError, + "must set image symbols to a zbar.SymbolSet, not '%.50s'", + value->ob_type->tp_name); + return(-1); + } + + zbar_image_set_symbols(self->zimg, zsyms); + return(0); +} + static zbarSymbolIter* image_iter (zbarImage *self) { - return(zbarSymbolIter_New(self)); + zbarSymbolSet *syms = image_get_symbols(self, NULL); + if(!syms) + return(NULL); + return(zbarSymbolIter_FromSymbolSet(syms)); } static PyObject* @@ -366,6 +312,7 @@ static PyGetSetDef image_getset[] = { { "sequence", (getter)image_get_int, (setter)image_set_int, NULL, (void*)2 }, { "data", (getter)image_get_data, (setter)image_set_data, }, + { "symbols", (getter)image_get_symbols,(setter)image_set_symbols, }, { NULL, }, }; diff --git a/python/imagescanner.c b/python/imagescanner.c index 1500e71..2f0f995 100644 --- a/python/imagescanner.c +++ b/python/imagescanner.c @@ -110,6 +110,21 @@ imagescanner_enable_cache (zbarImageScanner *self, Py_RETURN_NONE; } +static PyObject* +imagescanner_recycle (zbarImageScanner *self, + PyObject *args, + PyObject *kwds) +{ + zbarImage *img = NULL; + static char *kwlist[] = { "image", NULL }; + if(!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, + &zbarImage_Type, &img)) + return(NULL); + + zbar_image_scanner_recycle_image(self->zscn, img->zimg); + Py_RETURN_NONE; +} + static PyObject* imagescanner_scan (zbarImageScanner *self, PyObject *args, @@ -139,6 +154,8 @@ static PyMethodDef imagescanner_methods[] = { METH_VARARGS | METH_KEYWORDS, }, { "enable_cache", (PyCFunction)imagescanner_enable_cache, METH_VARARGS | METH_KEYWORDS, }, + { "recycle", (PyCFunction)imagescanner_recycle, + METH_VARARGS | METH_KEYWORDS, }, { "scan", (PyCFunction)imagescanner_scan, METH_VARARGS | METH_KEYWORDS, }, { NULL, }, diff --git a/python/symbol.c b/python/symbol.c index 90cd2d9..6c91274 100644 --- a/python/symbol.c +++ b/python/symbol.c @@ -33,7 +33,6 @@ symbol_traverse (zbarSymbol *self, visitproc visit, void *arg) { - Py_VISIT(self->img); return(0); } @@ -45,7 +44,6 @@ symbol_clear (zbarSymbol *self) self->zsym = NULL; zbar_symbol_ref(zsym, -1); } - Py_CLEAR(self->img); Py_CLEAR(self->data); Py_CLEAR(self->loc); return(0); @@ -58,6 +56,23 @@ symbol_dealloc (zbarSymbol *self) ((PyObject*)self)->ob_type->tp_free((PyObject*)self); } +static zbarSymbolSet* +symbol_get_components (zbarSymbol *self, + void *closure) +{ + const zbar_symbol_set_t *zsyms = zbar_symbol_get_components(self->zsym); + return(zbarSymbolSet_FromSymbolSet(zsyms)); +} + +static zbarSymbolIter* +symbol_iter (zbarSymbol *self) +{ + zbarSymbolSet *syms = symbol_get_components(self, NULL); + zbarSymbolIter *iter = zbarSymbolIter_FromSymbolSet(syms); + Py_XDECREF(syms); + return(iter); +} + static zbarEnumItem* symbol_get_type (zbarSymbol *self, void *closure) @@ -114,11 +129,12 @@ symbol_get_location (zbarSymbol *self, } static PyGetSetDef symbol_getset[] = { - { "type", (getter)symbol_get_type, }, - { "quality", (getter)symbol_get_long, NULL, NULL, (void*)0 }, - { "count", (getter)symbol_get_long, NULL, NULL, (void*)1 }, - { "data", (getter)symbol_get_data, }, - { "location", (getter)symbol_get_location, }, + { "type", (getter)symbol_get_type, }, + { "quality", (getter)symbol_get_long, NULL, NULL, (void*)0 }, + { "count", (getter)symbol_get_long, NULL, NULL, (void*)1 }, + { "data", (getter)symbol_get_data, }, + { "location", (getter)symbol_get_location, }, + { "components", (getter)symbol_get_components, }, { NULL, }, }; @@ -132,24 +148,21 @@ PyTypeObject zbarSymbol_Type = { .tp_traverse = (traverseproc)symbol_traverse, .tp_clear = (inquiry)symbol_clear, .tp_dealloc = (destructor)symbol_dealloc, + .tp_iter = (getiterfunc)symbol_iter, .tp_getset = symbol_getset, }; zbarSymbol* -zbarSymbol_FromSymbol (zbarImage *img, - const zbar_symbol_t *zsym) +zbarSymbol_FromSymbol (const zbar_symbol_t *zsym) { /* FIXME symbol object recycle cache */ zbarSymbol *self = PyObject_GC_New(zbarSymbol, &zbarSymbol_Type); if(!self) return(NULL); - assert(img); assert(zsym); - Py_INCREF(img); zbar_symbol_t *zs = (zbar_symbol_t*)zsym; zbar_symbol_ref(zs, 1); self->zsym = zsym; - self->img = img; self->data = NULL; self->loc = NULL; return(self); diff --git a/python/symboliter.c b/python/symboliter.c new file mode 100644 index 0000000..e1e04d0 --- /dev/null +++ b/python/symboliter.c @@ -0,0 +1,112 @@ +/*------------------------------------------------------------------------ + * Copyright 2009 (c) Jeff Brown + * + * 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 "zbarmodule.h" + +static char symboliter_doc[] = PyDoc_STR( + "symbol iterator.\n" + "\n" + "iterates over decode results attached to an image."); + +static int +symboliter_traverse (zbarSymbolIter *self, + visitproc visit, + void *arg) +{ + Py_VISIT(self->syms); + return(0); +} + +static int +symboliter_clear (zbarSymbolIter *self) +{ + if(self->zsym) { + zbar_symbol_t *zsym = (zbar_symbol_t*)self->zsym; + self->zsym = NULL; + zbar_symbol_ref(zsym, -1); + } + Py_CLEAR(self->syms); + return(0); +} + +static void +symboliter_dealloc (zbarSymbolIter *self) +{ + symboliter_clear(self); + ((PyObject*)self)->ob_type->tp_free((PyObject*)self); +} + +static zbarSymbolIter* +symboliter_iter (zbarSymbolIter *self) +{ + Py_INCREF(self); + return(self); +} + +static zbarSymbol* +symboliter_iternext (zbarSymbolIter *self) +{ + if(self->zsym) { + zbar_symbol_t *zsym = (zbar_symbol_t*)self->zsym; + zbar_symbol_ref(zsym, -1); + self->zsym = zbar_symbol_next(self->zsym); + } + else if(self->syms->zsyms) + self->zsym = zbar_symbol_set_first_symbol(self->syms->zsyms); + else + self->zsym = NULL; + + zbar_symbol_t *zsym = (zbar_symbol_t*)self->zsym; + if(!zsym) + return(NULL); + zbar_symbol_ref(zsym, 1); + return(zbarSymbol_FromSymbol(self->zsym)); +} + +PyTypeObject zbarSymbolIter_Type = { + PyObject_HEAD_INIT(NULL) + .tp_name = "zbar.SymbolIter", + .tp_doc = symboliter_doc, + .tp_basicsize = sizeof(zbarSymbolIter), + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC, + .tp_traverse = (traverseproc)symboliter_traverse, + .tp_clear = (inquiry)symboliter_clear, + .tp_dealloc = (destructor)symboliter_dealloc, + .tp_iter = (getiterfunc)symboliter_iter, + .tp_iternext = (iternextfunc)symboliter_iternext, +}; + +zbarSymbolIter* +zbarSymbolIter_FromSymbolSet (zbarSymbolSet *syms) +{ + zbarSymbolIter *self; + self = PyObject_GC_New(zbarSymbolIter, &zbarSymbolIter_Type); + if(!self) + return(NULL); + + Py_INCREF(syms); + self->syms = syms; + self->zsym = NULL; + return(self); +} diff --git a/python/symbolset.c b/python/symbolset.c new file mode 100644 index 0000000..634a807 --- /dev/null +++ b/python/symbolset.c @@ -0,0 +1,90 @@ +/*------------------------------------------------------------------------ + * Copyright 2009 (c) Jeff Brown + * + * 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 "zbarmodule.h" + +static char symbolset_doc[] = PyDoc_STR( + "symbol result container.\n" + "\n" + "collection of symbols."); + +static int +symbolset_clear (zbarSymbolSet *self) +{ + if(self->zsyms) { + zbar_symbol_set_t *zsyms = (zbar_symbol_set_t*)self->zsyms; + self->zsyms = NULL; + zbar_symbol_set_ref(zsyms, -1); + } + return(0); +} + +static void +symbolset_dealloc (zbarSymbolSet *self) +{ + symbolset_clear(self); + ((PyObject*)self)->ob_type->tp_free((PyObject*)self); +} + +static zbarSymbolIter* +symbolset_iter (zbarSymbolSet *self) +{ + return(zbarSymbolIter_FromSymbolSet(self)); +} + +Py_ssize_t +symbolset_length (zbarSymbolSet *self) +{ + if(self->zsyms) + return(zbar_symbol_set_get_size(self->zsyms)); + return(0); +} + +static PySequenceMethods symbolset_as_sequence = { + .sq_length = (lenfunc)symbolset_length, +}; + +PyTypeObject zbarSymbolSet_Type = { + PyObject_HEAD_INIT(NULL) + .tp_name = "zbar.SymbolSet", + .tp_doc = symbolset_doc, + .tp_basicsize = sizeof(zbarSymbolSet), + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_dealloc = (destructor)symbolset_dealloc, + .tp_iter = (getiterfunc)symbolset_iter, + .tp_as_sequence = &symbolset_as_sequence, +}; + +zbarSymbolSet* +zbarSymbolSet_FromSymbolSet(const zbar_symbol_set_t *zsyms) +{ + zbarSymbolSet *self = PyObject_New(zbarSymbolSet, &zbarSymbolSet_Type); + if(!self) + return(NULL); + if(zsyms) { + zbar_symbol_set_t *ncsyms = (zbar_symbol_set_t*)zsyms; + zbar_symbol_set_ref(ncsyms, 1); + } + self->zsyms = zsyms; + return(self); +} diff --git a/python/test/test_zbar.py b/python/test/test_zbar.py index dd37b92..2772152 100755 --- a/python/test/test_zbar.py +++ b/python/test/test_zbar.py @@ -1,5 +1,5 @@ #!/usr/bin/python -import sys, os +import sys, os, re import unittest as ut import zbar @@ -24,6 +24,8 @@ def load_image(): if 'VIDEO_DEVICE' in os.environ: VIDEO_DEVICE = os.environ['VIDEO_DEVICE'] +is_identifier = re.compile(r'^[A-Z][A-Z_0-9]*$') + class TestZBarFunctions(ut.TestCase): def test_version(self): ver = zbar.version() @@ -38,15 +40,49 @@ def test_verbosity(self): def test_exceptions(self): self.assert_(isinstance(zbar.Exception, type)) - self.assert_(issubclass(zbar.InternalError, zbar.Exception)) - self.assert_(issubclass(zbar.UnsupportedError, zbar.Exception)) - self.assert_(issubclass(zbar.InvalidRequestError, zbar.Exception)) - self.assert_(issubclass(zbar.SystemError, zbar.Exception)) - self.assert_(issubclass(zbar.LockingError, zbar.Exception)) - self.assert_(issubclass(zbar.BusyError, zbar.Exception)) - self.assert_(issubclass(zbar.X11DisplayError, zbar.Exception)) - self.assert_(issubclass(zbar.X11ProtocolError, zbar.Exception)) - self.assert_(issubclass(zbar.WindowClosed, zbar.Exception)) + for err in (zbar.InternalError, + zbar.UnsupportedError, + zbar.InvalidRequestError, + zbar.SystemError, + zbar.LockingError, + zbar.BusyError, + zbar.X11DisplayError, + zbar.X11ProtocolError, + zbar.WindowClosed, + zbar.WinAPIError): + self.assert_(issubclass(err, zbar.Exception)) + + def test_configs(self): + for cfg in (zbar.Config.ENABLE, + zbar.Config.ADD_CHECK, + zbar.Config.EMIT_CHECK, + zbar.Config.ASCII, + zbar.Config.MIN_LEN, + zbar.Config.MAX_LEN, + zbar.Config.POSITION, + zbar.Config.X_DENSITY, + zbar.Config.Y_DENSITY): + self.assert_(isinstance(cfg, zbar.EnumItem)) + self.assert_(int(cfg) >= 0) + self.assert_(is_identifier.match(str(cfg))) + + def test_symbologies(self): + for sym in (zbar.Symbol.NONE, + zbar.Symbol.PARTIAL, + zbar.Symbol.EAN8, + zbar.Symbol.UPCE, + zbar.Symbol.ISBN10, + zbar.Symbol.UPCA, + zbar.Symbol.EAN13, + zbar.Symbol.ISBN13, + zbar.Symbol.I25, + zbar.Symbol.CODE39, + zbar.Symbol.PDF417, + zbar.Symbol.QRCODE, + zbar.Symbol.CODE128): + self.assert_(isinstance(sym, zbar.EnumItem)) + self.assert_(int(sym) >= 0) + self.assert_(is_identifier.match(str(sym))) class TestScanner(ut.TestCase): def setUp(self): @@ -125,6 +161,7 @@ def handler(dcode, closure): explicit_closure = [ 0 ] self.dcode.set_handler(handler, explicit_closure) + self.dcode.set_config(zbar.Symbol.QRCODE, zbar.Config.ENABLE, 0) for (i, width) in enumerate(encoded_widths): if width == ' ': continue @@ -232,33 +269,56 @@ def test_scan(self): n = self.scn.scan(self.image) self.assertEqual(n, 1) + syms = self.image.symbols + self.assert_(isinstance(syms, zbar.SymbolSet)) + self.assertEqual(len(syms), 1) + i = iter(self.image) + j = iter(syms) self.assert_(isinstance(i, zbar.SymbolIter)) - sym = i.next() + self.assert_(isinstance(j, zbar.SymbolIter)) + symi = i.next() + symj = j.next() self.assertRaises(StopIteration, i.next) + self.assertRaises(StopIteration, j.next) # this is the only way to obtain a Symbol, # so test Symbol here - self.assert_(isinstance(sym, zbar.Symbol)) - self.assert_(sym.type is zbar.Symbol.EAN13) - self.assert_(sym.type is sym.EAN13) - self.assertEqual(str(sym.type), 'EAN13') - self.assert_(sym.quality > 0) - self.assertEqual(sym.count, 0) - - data = sym.data - self.assertEqual(data, '9876543210128') - - loc = sym.location - self.assert_(len(loc) >= 4) # FIXME - self.assert_(isinstance(loc, tuple)) - for pt in loc: - self.assert_(isinstance(pt, tuple)) - self.assertEqual(len(pt), 2) - # FIXME test values (API currently in flux) - - self.assert_(data is sym.data) - self.assert_(loc is sym.location) + for sym in (symi, symj): + self.assert_(isinstance(sym, zbar.Symbol)) + self.assert_(sym.type is zbar.Symbol.EAN13) + self.assert_(sym.type is sym.EAN13) + self.assertEqual(str(sym.type), 'EAN13') + self.assert_(sym.quality > 0) + self.assertEqual(sym.count, 0) + + # FIXME put a nice QR S-A in here + comps = sym.components + self.assert_(isinstance(comps, zbar.SymbolSet)) + self.assertEqual(len(comps), 0) + self.assert_(not comps) + self.assert_(tuple(comps) is ()) + + data = sym.data + self.assertEqual(data, '9876543210128') + + loc = sym.location + self.assert_(len(loc) >= 4) # FIXME + self.assert_(isinstance(loc, tuple)) + for pt in loc: + self.assert_(isinstance(pt, tuple)) + self.assertEqual(len(pt), 2) + # FIXME test values (API currently in flux) + + self.assert_(data is sym.data) + self.assert_(loc is sym.location) + + def set_symbols(syms): + self.image.symbols = syms + self.assertRaises(TypeError, set_symbols, ()) + + self.scn.recycle(self.image) + self.assertEqual(len(self.image.symbols), 0) def test_scan_again(self): self.test_scan() @@ -324,6 +384,9 @@ def data_handler(proc, image, closure): rc = self.proc.process_image(self.image) self.assertEqual(rc, 0) + self.assertEqual(len(self.image.symbols), 1) + del(self.image.symbols) + self.assertEqual(len(self.image.symbols), 0) self.assertEqual(self.proc.user_wait(.9), 0) diff --git a/python/zbarmodule.c b/python/zbarmodule.c index 6cb5507..27cce34 100644 --- a/python/zbarmodule.c +++ b/python/zbarmodule.c @@ -35,7 +35,7 @@ static char *exc_names[] = { "zbar.X11DisplayError", "zbar.X11ProtocolError", "zbar.WindowClosed", - "zbar.WinAPI", + "zbar.WinAPIError", }; int @@ -120,6 +120,7 @@ initzbar (void) PyType_Ready(&zbarEnum_Type) < 0 || PyType_Ready(&zbarImage_Type) < 0 || PyType_Ready(&zbarSymbol_Type) < 0 || + PyType_Ready(&zbarSymbolSet_Type) < 0 || PyType_Ready(&zbarSymbolIter_Type) < 0 || PyType_Ready(&zbarProcessor_Type) < 0 || PyType_Ready(&zbarImageScanner_Type) < 0 || @@ -151,6 +152,7 @@ initzbar (void) PyModule_AddObject(mod, "Image", (PyObject*)&zbarImage_Type); PyModule_AddObject(mod, "Config", (PyObject*)config_enum); PyModule_AddObject(mod, "Symbol", (PyObject*)&zbarSymbol_Type); + PyModule_AddObject(mod, "SymbolSet", (PyObject*)&zbarSymbolSet_Type); PyModule_AddObject(mod, "SymbolIter", (PyObject*)&zbarSymbolIter_Type); PyModule_AddObject(mod, "Processor", (PyObject*)&zbarProcessor_Type); PyModule_AddObject(mod, "ImageScanner", (PyObject*)&zbarImageScanner_Type); @@ -191,5 +193,6 @@ initzbar (void) zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_I25, "I25"); zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_CODE39, "CODE39"); zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_PDF417, "PDF417"); + zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_QRCODE, "QRCODE"); zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_CODE128, "CODE128"); } diff --git a/python/zbarmodule.h b/python/zbarmodule.h index 0b6dd4d..b6b660f 100644 --- a/python/zbarmodule.h +++ b/python/zbarmodule.h @@ -73,28 +73,40 @@ extern PyTypeObject zbarImage_Type; extern zbarImage *zbarImage_FromImage(zbar_image_t *zimg); extern int zbarImage_validate(zbarImage *image); +typedef struct { + PyObject_HEAD + const zbar_symbol_set_t *zsyms; +} zbarSymbolSet; + +extern PyTypeObject zbarSymbolSet_Type; + +extern zbarSymbolSet* +zbarSymbolSet_FromSymbolSet(const zbar_symbol_set_t *zsyms); + +#define zbarSymbolSet_Check(obj) PyObject_TypeCheck(obj, &zbarSymbolSet_Type) + typedef struct { PyObject_HEAD const zbar_symbol_t *zsym; - zbarImage *img; PyObject *data; PyObject *loc; } zbarSymbol; extern PyTypeObject zbarSymbol_Type; -extern zbarSymbol *zbarSymbol_FromSymbol(zbarImage *img, - const zbar_symbol_t *zsym); +extern zbarSymbol *zbarSymbol_FromSymbol(const zbar_symbol_t *zsym); extern zbarEnumItem *zbarSymbol_LookupEnum(zbar_symbol_type_t type); typedef struct { PyObject_HEAD const zbar_symbol_t *zsym; - zbarImage *img; + zbarSymbolSet *syms; } zbarSymbolIter; extern PyTypeObject zbarSymbolIter_Type; +extern zbarSymbolIter *zbarSymbolIter_FromSymbolSet(zbarSymbolSet *syms); + typedef struct { PyObject_HEAD zbar_processor_t *zproc; diff --git a/qt/QZBarThread.cpp b/qt/QZBarThread.cpp index b105c73..e392674 100644 --- a/qt/QZBarThread.cpp +++ b/qt/QZBarThread.cpp @@ -60,8 +60,10 @@ void QZBarThread::image_callback (Image &image) void QZBarThread::processImage (Image &image) { { + scanner.recycle_image(image); Image tmp = image.convert(*(long*)"Y800"); scanner.scan(tmp); + image.set_symbols(tmp.get_symbols()); } window.draw(image); if(this->image && this->image != &image) { diff --git a/zbar/Makefile.am.inc b/zbar/Makefile.am.inc index 03a890e..eedbd93 100644 --- a/zbar/Makefile.am.inc +++ b/zbar/Makefile.am.inc @@ -11,7 +11,7 @@ zbar_libzbar_la_SOURCES = zbar/debug.h zbar/config.c \ zbar/refcnt.h zbar/refcnt.c zbar/timer.h zbar/mutex.h \ zbar/event.h zbar/thread.h \ zbar/window.h zbar/window.c zbar/video.h zbar/video.c \ - zbar/img_scanner.c zbar/scanner.c \ + zbar/img_scanner.h zbar/img_scanner.c zbar/scanner.c \ zbar/decoder.h zbar/decoder.c if ENABLE_EAN diff --git a/zbar/convert.c b/zbar/convert.c index cf65cdb..1a90381 100644 --- a/zbar/convert.c +++ b/zbar/convert.c @@ -347,11 +347,9 @@ static void convert_copy (zbar_image_t *dst, dst->data = src->data; dst->datalen = src->datalen; dst->cleanup = cleanup_ref; -#if 0 zbar_image_t *s = (zbar_image_t*)src; dst->next = s; _zbar_image_refcnt(s, 1); -#endif } else /* NB only for GRAY/YUV_PLANAR formats */ @@ -969,9 +967,6 @@ zbar_image_t *zbar_image_convert_resize (const zbar_image_t *src, dst->format = fmt; dst->width = width; dst->height = height; - zbar_image_t *s = (zbar_image_t*)src; - dst->next = s; - _zbar_image_refcnt(s, 1); if(src->format == fmt && src->width == width && src->height == height) { diff --git a/zbar/decoder/qrcode/qrdec.c b/zbar/decoder/qrcode/qrdec.c index 67ee845..a488f90 100644 --- a/zbar/decoder/qrcode/qrdec.c +++ b/zbar/decoder/qrcode/qrdec.c @@ -37,14 +37,6 @@ typedef struct qr_pack_buf qr_pack_buf; #define QR_INT_BITS ((int)sizeof(int)*CHAR_BIT) #define QR_INT_LOGBITS (QR_ILOG(QR_INT_BITS)) -#ifdef SPADIX /* moved to qrcode.h */ -/*The number of bits of subpel precision to store image coordinates in. - This helps when estimating positions in low-resolution images, which may have - a module pitch only a pixel or two wide, making rounding errors matter a - great deal.*/ -#define QR_FINDER_SUBPREC (2) -#endif - /*A 14 bit resolution for a homography ensures that the ideal module size for a version 40 code differs from that of a version 39 code by at least 2.*/ #define QR_HOM_BITS (14) @@ -110,45 +102,6 @@ void qr_reader_reset (qr_reader *reader) } -#ifdef SPADIX /* moved to qrcode.h */ -typedef struct qr_finder_line qr_finder_line; - -/*A line crossing a finder pattern. - Whether the line is horizontal or vertical is determined by context. - The offsts to various parts of the finder pattern are as follows: - |*****| |*****|*****|*****| |*****| - |*****| |*****|*****|*****| |*****| - ^ ^ ^ ^ - | | | | - | | | pos[v]+len+eoffs - | | pos[v]+len - | pos[v] - pos[v]-boffs - Here v is 0 for horizontal and 1 for vertical lines.*/ -struct qr_finder_line{ - /*The location of the upper/left endpoint of the line. - The left/upper edge of the center section is used, since other lines must - cross in this region.*/ - qr_point pos; - /*The length of the center section. - This extends to the right/bottom of the center section, since other lines - must cross in this region.*/ - int len; - /*The offset to the midpoint of the upper/left section (part of the outside - ring), or 0 if we couldn't identify the edge of the beginning section. - We use the midpoint instead of the edge because it can be located more - reliably.*/ - int boffs; - /*The offset to the midpoint of the end section (part of the outside ring), - or 0 if we couldn't identify the edge of the end section. - We use the midpoint instead of the edge because it can be located more - reliably.*/ - int eoffs; -}; - -#endif - - /*A cluster of lines crossing a finder pattern (all in the same direction).*/ struct qr_finder_cluster{ /*Pointers to the lines crossing the pattern.*/ @@ -189,70 +142,6 @@ struct qr_finder_center{ int nedge_pts; }; -#ifdef SPADIX -/*Check to see if a set of lengths for a (dark:light:dark:light:dark) pattern - roughly has the ratios 1:1:3:1:1. - If it does, the location of the line segments are stored in _line. - _len_buf: The circular buffer containing lengths of each segment. - _bp: The index of the last segment in the list. - _x: The coordinate of the last pixel on the same axis as the segments. - _y: The coordinate of all the pixels on the perpendicular axis. - _v: 0 for horizontal lines, or 1 for vertical lines. - Return: 1 if the line passes, and 0 otherwise.*/ -static int qr_finder_check_pattern(qr_finder_line *_line,int _len_buf[5], - int _bp,int _x,int _y,int _v){ - static const int MODEL_RATIO[5]={2,2,6,2,2}; - int len_buf[5]; - int base_len; - int dev; - int i; - int x0; - int x1; - int x2; - int x3; - base_len=0; - for(i=0;i<5;i++){ - base_len+=_len_buf[i]; - if(_len_buf[i]<1)return 0; - } - /*Allowed deviation is 1/2 of the expected module size, rounded up to deal - with small resolutions better.*/ - dev=(base_len+13)/14; - /*TODO: People do not do a very good job of keeping the dead zone around the - code clear of clutter, and so the ability to recognize finder patterns - when one of the outside edges is obscured could help our recognition. - However, it would produce significantly more false alarms.*/ - for(i=0;i<5;i++){ - int len; - int model_len; - int j; - j=_bp+i+1; - if(j>=5)j-=5; - len=_len_buf[j]; - model_len=base_len*MODEL_RATIO[i]; - /*Round the threshold down for the min test, and up for the max test, - again to deal with small resolutions better.*/ - if(len+dev(model_len+13)/14)return 0; - len_buf[i]=len; - } - /*We place the endpoints of the line at the midpoints of the two - outer bins. - This is more reliable than using the full extent of the bins, - since blurring may cause regions of a given color to shrink or - grow, but will not change the midpoint.*/ - x0=((_x+1-base_len<<1)+len_buf[0]<>1; - x2=_x+1-len_buf[4]-len_buf[3]<>1; - _line->pos[_v]=x1; - _line->pos[1-_v]=((_y<<1|1)<>1; - _line->len=x2-x1; - _line->boffs=x1-x0; - _line->eoffs=x3-x2; - return 1; -} -#endif - static int qr_finder_vline_cmp(const void *_a,const void *_b){ const qr_finder_line *a; const qr_finder_line *b; @@ -508,79 +397,10 @@ static int qr_finder_find_crossings(qr_finder_center *_centers, static int qr_finder_centers_locate(qr_finder_center **_centers, qr_finder_edge_pt **_edge_pts, qr_reader *reader, int _width,int _height){ -#ifdef SPADIX - typedef int vect5i[5]; - qr_finder_line *hlines; - int nhlines; - int chlines; - qr_finder_line *vlines; - int nvlines; - int cvlines; - vect5i *ylen_bufs; - int *ybps; - int x; - int y; - if(_width<1||_height<1)return 0; - /*Detect line segments which cross a finder pattern. - TODO: We should also check diagonal lines, though this will make subsequent - steps more complicated.*/ - nhlines=nvlines=0; - chlines=cvlines=31; - hlines=(qr_finder_line *)malloc(chlines*sizeof(*hlines)); - vlines=(qr_finder_line *)malloc(cvlines*sizeof(*vlines)); - ylen_bufs=(vect5i *)calloc(_width,sizeof(*ylen_bufs)); - ybps=(int *)calloc(_width,sizeof(*ybps)); - for(x=0;x<_width;x++)ylen_bufs[x][0]=1; - for(y=0;y<_height;y++){ - vect5i xlen_buf; - int xbp; - unsigned xnext; - memset(xlen_buf,0,sizeof(xlen_buf)); - xlen_buf[0]=1; - xbp=0; - xnext=_img[y*_width]!=0; - for(x=0;x<_width;x++){ - unsigned ynext; - unsigned cur; - cur=xnext; - xnext=x+1<_width?_img[y*_width+x+1]!=0:!cur; - if(cur!=xnext){ - if(!xnext&& - qr_finder_check_pattern(hlines+nhlines,xlen_buf,xbp,x,y,0)>0){ - nhlines++; - if(nhlines>=chlines){ - chlines=chlines<<1|1; - hlines=(qr_finder_line *)realloc(hlines,chlines*sizeof(*hlines)); - } - } - if(++xbp>=5)xbp-=5; - xlen_buf[xbp]=1; - } - else xlen_buf[xbp]++; - ynext=y+1<_height?_img[(y+1)*_width+x]!=0:!cur; - if(cur!=ynext){ - if(!ynext&& - qr_finder_check_pattern(vlines+nvlines,ylen_bufs[x],ybps[x],y,x,1)>0){ - nvlines++; - if(nvlines>=cvlines){ - cvlines=cvlines<<1|1; - vlines=(qr_finder_line *)realloc(vlines,cvlines*sizeof(*vlines)); - } - } - if(++ybps[x]>=5)ybps[x]-=5; - ylen_bufs[x][ybps[x]]=1; - } - else ylen_bufs[x][ybps[x]]++; - } - } - free(ybps); - free(ylen_bufs); -#else qr_finder_line *hlines = reader->finder_lines[0].lines; int nhlines = reader->finder_lines[0].num_lines; qr_finder_line *vlines = reader->finder_lines[1].lines; int nvlines = reader->finder_lines[1].num_lines; -#endif qr_finder_line **hneighbors; qr_finder_cluster *hclusters; @@ -627,10 +447,6 @@ static int qr_finder_centers_locate(qr_finder_center **_centers, free(vneighbors); free(hclusters); free(hneighbors); -#ifdef SPADIX - free(vlines); - free(hlines); -#endif return ncenters; } diff --git a/zbar/decoder/qrcode/qrdectxt.c b/zbar/decoder/qrcode/qrdectxt.c index 78868ec..39ac6d4 100644 --- a/zbar/decoder/qrcode/qrdectxt.c +++ b/zbar/decoder/qrcode/qrdectxt.c @@ -11,6 +11,7 @@ #include "util.h" #include "image.h" #include "error.h" +#include "img_scanner.h" static int text_is_ascii(const unsigned char *_text,int _len){ int i; @@ -38,18 +39,6 @@ static void enc_list_mtf(iconv_t _enc_list[3],iconv_t _enc){ } } -/* FIXME API cleanup */ -zbar_symbol_t *_zbar_image_scanner_alloc_sym(zbar_image_scanner_t *iscn, - zbar_symbol_type_t type, - const char *data, - int datalen); - -void _zbar_image_scanner_cache_sym(zbar_image_scanner_t *iscn, - zbar_symbol_t *sym); - -void _zbar_image_scanner_recycle_syms(zbar_image_scanner_t*, - zbar_symbol_t**); - int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, zbar_image_scanner_t *iscn, zbar_image_t *img) @@ -150,7 +139,8 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, err=0; zbar_symbol_t *syms = NULL, **sym = &syms; for(j = 0; j < sa_size && !err; j++, sym = &(*sym)->next) { - *sym = _zbar_image_scanner_alloc_sym(iscn, ZBAR_QRCODE, NULL, sa_ntext); + *sym = _zbar_image_scanner_alloc_sym(iscn, ZBAR_QRCODE, 0); + (*sym)->datalen = sa_ntext; if(sa[j]<0){ /* generic placeholder for unfinished results */ (*sym)->type = ZBAR_PARTIAL; @@ -164,7 +154,8 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, sa_text[sa_ntext++]='\0'; /* advance to next symbol */ - *sym = _zbar_image_scanner_alloc_sym(iscn, ZBAR_QRCODE, NULL, sa_ntext); + *sym = _zbar_image_scanner_alloc_sym(iscn, ZBAR_QRCODE, 0); + (*sym)->datalen = sa_ntext; sym = &(*sym)->next; } @@ -345,51 +336,52 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, } zbar_symbol_t *sa_sym; - if(sa_size > 1) { + if(sa_size == 1) + sa_sym = syms; + else { /* create "virtual" container symbol for composite result */ - sa_sym = _zbar_image_scanner_alloc_sym(iscn, ZBAR_QRCODE, NULL, 0); - sa_sym->syms = syms; + sa_sym = _zbar_image_scanner_alloc_sym(iscn, ZBAR_QRCODE, 0); + sa_sym->syms = _zbar_symbol_set_create(); + sa_sym->syms->head = syms; + + /* cheap out w/axis aligned bbox for now */ + int xmin = img->width, xmax = -2; + int ymin = img->height, ymax = -2; + + /* fixup data references */ + for(; syms; syms = syms->next) { + if(syms->type == ZBAR_PARTIAL) + sa_sym->type = ZBAR_PARTIAL; + else + for(j = 0; j < syms->npts; j++) { + int u = syms->pts[j].x; + if(xmin >= u) xmin = u - 1; + if(xmax <= u) xmax = u + 1; + u = syms->pts[j].y; + if(ymin >= u) ymin = u - 1; + if(ymax <= u) ymax = u + 1; + } + syms->data = sa_text + syms->datalen; + int next = (syms->next) ? syms->next->datalen : sa_ntext; + assert(next > syms->datalen); + syms->datalen = next - syms->datalen - 1; + } + if(xmax >= -1) { + sym_add_point(sa_sym, xmin, ymin); + sym_add_point(sa_sym, xmin, ymax); + sym_add_point(sa_sym, xmax, ymax); + sym_add_point(sa_sym, xmax, ymin); + } } - else - sa_sym = syms; sa_sym->data = sa_text; sa_sym->data_alloc = sa_ntext; sa_sym->datalen = sa_ntext - 1; - /* cheap out w/axis aligned bbox for now */ - int xmin = img->width, xmax = -2; - int ymin = img->height, ymax = -2; - - /* fixup data references */ - for(syms = sa_sym->syms; syms; syms = syms->next) { - if(syms->type == ZBAR_PARTIAL) - sa_sym->type = ZBAR_PARTIAL; - else - for(j = 0; j < syms->npts; j++) { - int u = syms->pts[j].x; - if(xmin >= u) xmin = u - 1; - if(xmax <= u) xmax = u + 1; - u = syms->pts[j].y; - if(ymin >= u) ymin = u - 1; - if(ymax <= u) ymax = u + 1; - } - syms->data = sa_text + syms->datalen; - int next = (syms->next) ? syms->next->datalen : sa_ntext; - assert(next > syms->datalen); - syms->datalen = next - syms->datalen - 1; - } - if(sa_sym->syms && xmax >= -1) { - sym_add_point(sa_sym, xmin, ymin); - sym_add_point(sa_sym, xmin, ymax); - sym_add_point(sa_sym, xmax, ymax); - sym_add_point(sa_sym, xmax, ymin); - } - - _zbar_image_attach_symbol(img, sa_sym); + _zbar_symbol_set_add(img->syms, sa_sym); _zbar_image_scanner_cache_sym(iscn, sa_sym); } else { - _zbar_image_scanner_recycle_syms(iscn, &syms); + _zbar_image_scanner_recycle_syms(iscn, syms); free(sa_text); } } diff --git a/zbar/image.c b/zbar/image.c index f646409..ec36150 100644 --- a/zbar/image.c +++ b/zbar/image.c @@ -36,10 +36,9 @@ zbar_image_t *zbar_image_create () void _zbar_image_free (zbar_image_t *img) { - zbar_symbol_t *sym, *next; - for(sym = img->syms; sym; sym = next) { - next = sym->next; - _zbar_symbol_refcnt(sym, -1); + if(img->syms) { + zbar_symbol_set_ref(img->syms, -1); + img->syms = NULL; } free(img); } @@ -173,14 +172,26 @@ zbar_image_t *zbar_image_copy (const zbar_image_t *src) return(dst); } -const zbar_symbol_t *zbar_image_first_symbol (const zbar_image_t *img) +const zbar_symbol_set_t *zbar_image_get_symbols (const zbar_image_t *img) { - /* symbols stored on root image */ - while(img->next) - img = img->next; return(img->syms); } +void zbar_image_set_symbols (zbar_image_t *img, + const zbar_symbol_set_t *syms) +{ + if(img->syms) + zbar_symbol_set_ref(img->syms, -1); + img->syms = (zbar_symbol_set_t*)syms; + if(syms) + zbar_symbol_set_ref(img->syms, 1); +} + +const zbar_symbol_t *zbar_image_first_symbol (const zbar_image_t *img) +{ + return((img->syms) ? img->syms->head : NULL); +} + typedef struct zimg_hdr_s { uint32_t magic, format; uint16_t width, height; diff --git a/zbar/image.h b/zbar/image.h index 2aa89ac..5c4a794 100644 --- a/zbar/image.h +++ b/zbar/image.h @@ -75,8 +75,7 @@ struct zbar_image_s { zbar_image_t *next; /* internal image lists */ unsigned seq; /* page/frame sequence number */ - int nsyms; /* number of valid symbols */ - zbar_symbol_t *syms; /* first of decoded symbol results */ + zbar_symbol_set_t *syms; /* decoded result set */ }; /* description of an image format */ @@ -116,18 +115,12 @@ static inline void _zbar_image_refcnt (zbar_image_t *img, } } -static inline void _zbar_image_attach_symbol (zbar_image_t *img, - zbar_symbol_t *sym) +static inline void _zbar_image_swap_symbols (zbar_image_t *a, + zbar_image_t *b) { - /* symbols stored on root image */ - while(img->next) - img = img->next; - - sym->next = img->syms; - img->syms = sym; - img->nsyms++; - - _zbar_symbol_refcnt(sym, 1); + zbar_symbol_set_t *tmp = a->syms; + a->syms = b->syms; + b->syms = tmp; } #endif diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 5c259dd..4e0ee1e 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -38,6 +38,7 @@ #ifdef ENABLE_QRCODE # include "decoder/qrcode.h" #endif +#include "img_scanner.h" #ifdef DEBUG_IMG_SCANNER # define DEBUG_LEVEL (DEBUG_IMG_SCANNER) @@ -76,6 +77,19 @@ #define CFG(iscn, cfg) ((iscn)->configs[(cfg) - ZBAR_CFG_X_DENSITY]) #define TEST_CFG(iscn, cfg) (((iscn)->config >> ((cfg) - ZBAR_CFG_POSITION)) & 1) +#ifndef NO_STATS +# define STAT(x) iscn->stat_##x++ +#else +# define STAT(...) +# define dump_stats(...) +#endif + +#define RECYCLE_BUCKETS 5 + +typedef struct recycle_bucket_s { + int nsyms; + zbar_symbol_t *head; +} recycle_bucket_t; /* image scanner state */ struct zbar_image_scanner_s { @@ -92,8 +106,9 @@ struct zbar_image_scanner_s { unsigned long time; /* scan start time */ zbar_image_t *img; /* currently scanning image *root* */ int dx, dy; /* current scan direction */ - int nsyms; /* total cached symbols */ - zbar_symbol_t *syms; /* recycled symbols */ + zbar_symbol_set_t *syms; /* previous decode results */ + /* recycled symbols in 4^n size buckets */ + recycle_bucket_t recycle[RECYCLE_BUCKETS]; int enable_cache; /* current result cache state */ zbar_symbol_t *cache; /* inter-image result cache entries */ @@ -101,84 +116,144 @@ struct zbar_image_scanner_s { /* configuration settings */ unsigned config; /* config flags */ int configs[NUM_SCN_CFGS]; /* int valued configurations */ + +#ifndef NO_STATS + int stat_syms_new; + int stat_iscn_syms_inuse, stat_iscn_syms_recycle; + int stat_img_syms_inuse, stat_img_syms_recycle; + int stat_sym_new; + int stat_sym_recycle[RECYCLE_BUCKETS]; +#endif }; void _zbar_image_scanner_recycle_syms (zbar_image_scanner_t *iscn, - zbar_symbol_t **symlist) + zbar_symbol_t *sym) { - zbar_symbol_t **symp = symlist; - zbar_symbol_t *sym; - while((sym = *symp)) - if(_zbar_refcnt(&sym->refcnt, -1)) { + zbar_symbol_t *next = NULL; + for(; sym; sym = next) { + next = sym->next; + if(sym->refcnt && _zbar_refcnt(&sym->refcnt, -1)) { /* unlink referenced symbol */ - *symp = sym->next; + /* FIXME handle outstanding component refs (currently unsupported) + */ + assert(sym->data_alloc); sym->next = NULL; } else { /* recycle unreferenced symbol */ + if(!sym->data_alloc) { + sym->data = NULL; + sym->datalen = 0; + } if(sym->syms) { - /* FIXME retain parent ref for refd children */ - zbar_symbol_t *s; - for(s = sym->syms; s; s = s->next) { - s->data = NULL; - s->datalen = s->data_alloc = 0; - } - /* recurse */ - _zbar_image_scanner_recycle_syms(iscn, &sym->syms); + if(_zbar_refcnt(&sym->syms->refcnt, -1)) + assert(0); + _zbar_image_scanner_recycle_syms(iscn, sym->syms->head); + _zbar_symbol_set_free(sym->syms); + sym->syms = NULL; } - iscn->nsyms++; - symp = &sym->next; + int i; + for(i = 0; i < RECYCLE_BUCKETS; i++) + if(sym->data_alloc < 1 << (i * 2)) + break; + if(i == RECYCLE_BUCKETS) { + assert(sym->data); + free(sym->data); + sym->data = NULL; + sym->data_alloc = 0; + i = 0; + } + recycle_bucket_t *bucket = &iscn->recycle[i]; + /* FIXME cap bucket fill */ + bucket->nsyms++; + sym->next = bucket->head; + bucket->head = sym; } - - if(symp != symlist) { - *symp = iscn->syms; - iscn->syms = *symlist; } - *symlist = NULL; } -static inline void recycle_image_syms (zbar_image_scanner_t *iscn, - zbar_image_t *img) +static inline int recycle_syms (zbar_image_scanner_t *iscn, + zbar_symbol_set_t *syms) { - /* walk to root of clone tree */ - while(img) { - img->nsyms = 0; - /* recycle image symbols */ - _zbar_image_scanner_recycle_syms(iscn, &img->syms); - - /* save root */ - iscn->img = img; - img = img->next; + if(_zbar_refcnt(&syms->refcnt, -1)) + return(1); + + _zbar_image_scanner_recycle_syms(iscn, syms->head); + syms->head = NULL; + syms->nsyms = 0; + return(0); +} + +inline void zbar_image_scanner_recycle_image (zbar_image_scanner_t *iscn, + zbar_image_t *img) +{ + zbar_symbol_set_t *syms = iscn->syms; + if(syms && syms->refcnt) { + if(recycle_syms(iscn, syms)) { + STAT(iscn_syms_inuse); + iscn->syms = NULL; + } + else + STAT(iscn_syms_recycle); + } + + syms = img->syms; + img->syms = NULL; + if(syms && recycle_syms(iscn, syms)) { + STAT(img_syms_inuse); + syms = iscn->syms; + } + else if(syms) { + STAT(img_syms_recycle); + + /* select one set to resurrect, destroy the other */ + if(iscn->syms) { + _zbar_symbol_set_free(syms); + syms = iscn->syms; + } + else + iscn->syms = syms; } } inline zbar_symbol_t* _zbar_image_scanner_alloc_sym (zbar_image_scanner_t *iscn, zbar_symbol_type_t type, - const char *data, int datalen) { /* recycle old or alloc new symbol */ - zbar_symbol_t *sym = iscn->syms; + int i; + for(i = 0; i < RECYCLE_BUCKETS - 1; i++) + if(datalen + 1 <= 1 << (i * 2)) + break; + + zbar_symbol_t *sym = NULL; + for(; i > 0; i--) + if((sym = iscn->recycle[i].head)) { + STAT(sym_recycle[i]); + break; + } + if(sym) { - iscn->syms = sym->next; + iscn->recycle[i].head = sym->next; sym->next = NULL; - assert(iscn->nsyms); - iscn->nsyms--; + assert(iscn->recycle[i].nsyms); + iscn->recycle[i].nsyms--; } else { sym = calloc(1, sizeof(zbar_symbol_t)); - assert(!iscn->nsyms); + STAT(sym_new); } - /* save new symbol data */ + /* init new symbol */ sym->type = type; sym->quality = 1; sym->npts = 0; sym->cache_count = 0; sym->time = iscn->time; assert(!sym->syms); - if(data) { + + if(datalen) { sym->datalen = datalen++; if(sym->data_alloc < datalen) { if(sym->data) @@ -186,14 +261,12 @@ _zbar_image_scanner_alloc_sym (zbar_image_scanner_t *iscn, sym->data_alloc = datalen; sym->data = malloc(datalen); } - memcpy(sym->data, data, datalen); } else { if(sym->data) free(sym->data); sym->data = NULL; - sym->datalen = datalen; - sym->data_alloc = 0; + sym->datalen = sym->data_alloc = 0; } return(sym); } @@ -211,9 +284,8 @@ static inline zbar_symbol_t *cache_lookup (zbar_image_scanner_t *iscn, if((sym->time - (*entry)->time) > CACHE_TIMEOUT) { /* recycle stale cache entry */ zbar_symbol_t *next = (*entry)->next; - (*entry)->next = iscn->syms; - iscn->syms = *entry; - iscn->nsyms++; + (*entry)->next = NULL; + _zbar_image_scanner_recycle_syms(iscn, *entry); *entry = next; } else @@ -230,7 +302,8 @@ inline void _zbar_image_scanner_cache_sym (zbar_image_scanner_t *iscn, if(!entry) { /* FIXME reuse sym */ entry = _zbar_image_scanner_alloc_sym(iscn, sym->type, - sym->data, sym->datalen); + sym->datalen); + memcpy(entry->data, sym->data, sym->datalen + 1); entry->time = sym->time - CACHE_HYSTERESIS; entry->cache_count = -CACHE_CONSISTENCY; /* add to cache */ @@ -303,7 +376,7 @@ static void qr_handler (zbar_image_scanner_t *iscn, line->eoffs = tmp; } - zprintf(54, "qrf: u=%d.%03d boff=%d.%03d pos=%d.%03d,%d.%03d" + zprintf(127, "qrf: u=%d.%03d boff=%d.%03d pos=%d.%03d,%d.%03d" " len=%d.%03d eoff=%d.%03d\n", PRINT_FIXED(u, QR_FINDER_SUBPREC), PRINT_FIXED(line->boffs, QR_FINDER_SUBPREC), @@ -360,9 +433,9 @@ static void symbol_handler (zbar_image_scanner_t *iscn, const char *data = zbar_decoder_get_data(iscn->dcode); unsigned datalen = zbar_decoder_get_data_length(iscn->dcode); - /* FIXME need better search */ + /* FIXME need better symbol matching */ zbar_symbol_t *sym; - for(sym = iscn->img->syms; sym; sym = sym->next) + for(sym = iscn->syms->head; sym; sym = sym->next) if(sym->type == type && sym->datalen == datalen && !memcmp(sym->data, data, datalen)) { @@ -374,15 +447,16 @@ static void symbol_handler (zbar_image_scanner_t *iscn, return; } - sym = _zbar_image_scanner_alloc_sym(iscn, type, data, datalen); + sym = _zbar_image_scanner_alloc_sym(iscn, type, datalen); + /* FIXME grab decoder buffer */ + memcpy(sym->data, data, datalen + 1); /* initialize first point */ if(TEST_CFG(iscn, ZBAR_CFG_POSITION)) sym_add_point(sym, x, y); - /* attach to current root image */ - _zbar_image_attach_symbol(iscn->img, sym); - + /* add to current result set */ + _zbar_symbol_set_add(iscn->syms, sym); _zbar_image_scanner_cache_sym(iscn, sym); } @@ -409,18 +483,45 @@ zbar_image_scanner_t *zbar_image_scanner_create () return(iscn); } +#ifndef NO_STATS +static inline void dump_stats (const zbar_image_scanner_t *iscn) +{ + zprintf(1, "symbol sets allocated = %-4d\n", iscn->stat_syms_new); + zprintf(1, " scanner syms in use = %-4d\trecycled = %-4d\n", + iscn->stat_iscn_syms_inuse, iscn->stat_iscn_syms_recycle); + zprintf(1, " image syms in use = %-4d\trecycled = %-4d\n", + iscn->stat_img_syms_inuse, iscn->stat_img_syms_recycle); + zprintf(1, "symbols allocated = %-4d\n", iscn->stat_sym_new); + int i; + for(i = 0; i < RECYCLE_BUCKETS; i++) + zprintf(1, " recycled[%d] = %-4d\n", + i, iscn->stat_sym_recycle[i]); +} +#endif + void zbar_image_scanner_destroy (zbar_image_scanner_t *iscn) { + dump_stats(iscn); + if(iscn->syms) { + if(iscn->syms->refcnt) + zbar_symbol_set_ref(iscn->syms, -1); + else + _zbar_symbol_set_free(iscn->syms); + iscn->syms = NULL; + } if(iscn->scn) zbar_scanner_destroy(iscn->scn); iscn->scn = NULL; if(iscn->dcode) zbar_decoder_destroy(iscn->dcode); iscn->dcode = NULL; - while(iscn->syms) { - zbar_symbol_t *next = iscn->syms->next; - sym_destroy(iscn->syms); - iscn->syms = next; + int i; + for(i = 0; i < RECYCLE_BUCKETS; i++) { + zbar_symbol_t *sym, *next; + for(sym = iscn->recycle[i].head; sym; sym = next) { + next = sym->next; + _zbar_symbol_free(sym); + } } #ifdef ENABLE_QRCODE if(iscn->qr) { @@ -478,12 +579,7 @@ void zbar_image_scanner_enable_cache(zbar_image_scanner_t *iscn, { if(iscn->cache) { /* recycle all cached syms */ - zbar_symbol_t *entry; - for(entry = iscn->cache; entry->next; entry = entry->next) - iscn->nsyms++; - iscn->nsyms++; - entry->next = iscn->syms; - iscn->syms = iscn->cache; + _zbar_image_scanner_recycle_syms(iscn, iscn->cache); iscn->cache = NULL; } iscn->enable_cache = (enable) ? 1 : 0; @@ -551,8 +647,19 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, if(img->format != fourcc('Y','8','0','0') && img->format != fourcc('G','R','E','Y')) return(-1); - - recycle_image_syms(iscn, img); + iscn->img = img; + + /* recycle previous scanner and image results */ + zbar_image_scanner_recycle_image(iscn, img); + zbar_symbol_set_t *syms = iscn->syms; + if(!syms) { + syms = iscn->syms = _zbar_symbol_set_create(); + STAT(syms_new); + zbar_symbol_set_ref(syms, 1); + } + else + zbar_symbol_set_ref(syms, 2); + img->syms = syms; unsigned w = img->width; unsigned h = img->height; @@ -578,11 +685,11 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, zprintf(128, "img_x+: %04d,%04d @%p\n", x, y, p); iscn->dx = 1; while(x < w) { - ASSERT_POS; if(zbar_scan_y(iscn->scn, *p)) symbol_handler(iscn, x, y); movedelta(1, 0); } + ASSERT_POS; quiet_border(iscn, x, y); movedelta(-1, density); @@ -592,11 +699,11 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, zprintf(128, "img_x-: %04d,%04d @%p\n", x, y, p); iscn->dx = -1; while(x >= 0) { - ASSERT_POS; if(zbar_scan_y(iscn->scn, *p)) symbol_handler(iscn, x, y); movedelta(-1, 0); } + ASSERT_POS; quiet_border(iscn, x, y); movedelta(1, density); @@ -618,11 +725,11 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, zprintf(128, "img_y+: %04d,%04d @%p\n", x, y, p); iscn->dy = 1; while(y < h) { - ASSERT_POS; if(zbar_scan_y(iscn->scn, *p)) symbol_handler(iscn, x, y); movedelta(0, 1); } + ASSERT_POS; quiet_border(iscn, x, y); movedelta(density, -1); @@ -632,19 +739,17 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, zprintf(128, "img_y-: %04d,%04d @%p\n", x, y, p); iscn->dy = -1; while(y >= 0) { - ASSERT_POS; if(zbar_scan_y(iscn->scn, *p)) symbol_handler(iscn, x, y); movedelta(0, -1); } + ASSERT_POS; quiet_border(iscn, x, y); movedelta(density, 1); } } iscn->dy = 0; - - img = iscn->img; iscn->img = NULL; #ifdef ENABLE_QRCODE @@ -653,18 +758,17 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, dprintf(1, "\n"); /* FIXME tmp hack to filter bad EAN results */ - if(img->nsyms && !iscn->enable_cache && + if(syms->nsyms && !iscn->enable_cache && (density == 1 || CFG(iscn, ZBAR_CFG_Y_DENSITY) == 1)) { - zbar_symbol_t **symp = &img->syms, *sym; + zbar_symbol_t **symp = &syms->head, *sym; while((sym = *symp)) { if(sym->type < ZBAR_I25 && sym->type > ZBAR_PARTIAL && sym->quality < 3) { /* recycle */ *symp = sym->next; - iscn->nsyms++; - img->nsyms--; - sym->next = iscn->syms; - iscn->syms = sym; + syms->nsyms--; + sym->next = NULL; + _zbar_image_scanner_recycle_syms(iscn, sym); } else symp = &sym->next; @@ -672,8 +776,8 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, } /* FIXME option to only report count == 0 */ - if(img->nsyms && iscn->handler) + if(syms->nsyms && iscn->handler) iscn->handler(img, iscn->userdata); - return(img->nsyms); + return(syms->nsyms); } diff --git a/zbar/img_scanner.h b/zbar/img_scanner.h new file mode 100644 index 0000000..a1fc24a --- /dev/null +++ b/zbar/img_scanner.h @@ -0,0 +1,38 @@ +/*------------------------------------------------------------------------ + * Copyright 2007-2009 (c) Jeff Brown + * + * 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 + *------------------------------------------------------------------------*/ +#ifndef _IMG_SCANNER_H_ +#define _IMG_SCANNER_H_ + +#include + +/* internal image scanner APIs for 2D readers */ + +extern zbar_symbol_t *_zbar_image_scanner_alloc_sym(zbar_image_scanner_t*, + zbar_symbol_type_t, + int); +extern void _zbar_image_scanner_cache_sym(zbar_image_scanner_t*, + zbar_symbol_t*); +extern void _zbar_image_scanner_recycle_syms(zbar_image_scanner_t*, + zbar_symbol_t*); + +#endif diff --git a/zbar/processor.c b/zbar/processor.c index 4ca36c8..ee6ab23 100644 --- a/zbar/processor.c +++ b/zbar/processor.c @@ -70,10 +70,13 @@ int _zbar_process_image (zbar_processor_t *proc, * but easier for now and we don't expect this to take long... */ zbar_image_t *tmp = zbar_image_convert(img, fourcc('Y','8','0','0')); - if(!img) + if(!tmp) goto error; + zbar_image_scanner_recycle_image(proc->scanner, img); int nsyms = zbar_scan_image(proc->scanner, tmp); + _zbar_image_swap_symbols(img, tmp); + zbar_image_destroy(tmp); tmp = NULL; if(nsyms < 0) @@ -106,9 +109,12 @@ int _zbar_process_image (zbar_processor_t *proc, } if(force_fmt) { + zbar_symbol_set_t *syms = img->syms; img = zbar_image_convert(img, force_fmt); if(!img) goto error; + img->syms = syms; + zbar_symbol_set_ref(syms, 1); } } diff --git a/zbar/symbol.c b/zbar/symbol.c index 2f0da03..4eb54ef 100644 --- a/zbar/symbol.c +++ b/zbar/symbol.c @@ -56,6 +56,20 @@ const char *zbar_get_addon_name (zbar_symbol_type_t sym) } } + +void _zbar_symbol_free (zbar_symbol_t *sym) +{ + if(sym->syms) { + zbar_symbol_set_ref(sym->syms, -1); + sym->syms = NULL; + } + if(sym->pts) + free(sym->pts); + if(sym->data_alloc && sym->data) + free(sym->data); + free(sym); +} + void zbar_symbol_ref (zbar_symbol_t *sym, int refs) { @@ -115,9 +129,15 @@ const zbar_symbol_t *zbar_symbol_next (const zbar_symbol_t *sym) return((sym) ? sym->next : NULL); } +const zbar_symbol_set_t* +zbar_symbol_get_components (const zbar_symbol_t *sym) +{ + return(sym->syms); +} + const zbar_symbol_t *zbar_symbol_first_component (const zbar_symbol_t *sym) { - return((sym) ? sym->syms : NULL); + return((sym && sym->syms) ? sym->syms->head : NULL); } @@ -179,3 +199,41 @@ char *zbar_symbol_xml (const zbar_symbol_t *sym, *len = n; return(*buf); } + + +zbar_symbol_set_t *_zbar_symbol_set_create () +{ + zbar_symbol_set_t *syms = calloc(1, sizeof(*syms)); + _zbar_refcnt(&syms->refcnt, 1); + return(syms); +} + +inline void _zbar_symbol_set_free (zbar_symbol_set_t *syms) +{ + zbar_symbol_t *sym, *next; + for(sym = syms->head; sym; sym = next) { + next = sym->next; + sym->next = NULL; + _zbar_symbol_refcnt(sym, -1); + } + syms->head = NULL; + free(syms); +} + +void zbar_symbol_set_ref (zbar_symbol_set_t *syms, + int delta) +{ + if(!_zbar_refcnt(&syms->refcnt, delta) && delta <= 0) + _zbar_symbol_set_free(syms); +} + +int zbar_symbol_set_get_size (const zbar_symbol_set_t *syms) +{ + return(syms->nsyms); +} + +const zbar_symbol_t* +zbar_symbol_set_first_symbol (const zbar_symbol_set_t *syms) +{ + return(syms->head); +} diff --git a/zbar/symbol.h b/zbar/symbol.h index 00fbc0b..4ec5357 100644 --- a/zbar/symbol.h +++ b/zbar/symbol.h @@ -31,6 +31,12 @@ typedef struct point_s { int x, y; } point_t; +struct zbar_symbol_set_s { + refcnt_t refcnt; + int nsyms; /* number of valid symbols */ + zbar_symbol_t *head; /* first of decoded symbol results */ +}; + struct zbar_symbol_s { zbar_symbol_type_t type; /* symbol type */ unsigned int data_alloc; /* allocation size of data */ @@ -43,12 +49,17 @@ struct zbar_symbol_s { refcnt_t refcnt; /* reference count */ zbar_symbol_t *next; /* linked list of results (or siblings) */ - zbar_symbol_t *syms; /* first component of composite result */ + zbar_symbol_set_t *syms; /* components of composite result */ unsigned long time; /* relative symbol capture time */ int cache_count; /* cache state */ int quality; /* relative symbol reliability metric */ }; +extern void _zbar_symbol_free(zbar_symbol_t*); + +extern zbar_symbol_set_t *_zbar_symbol_set_create(void); +extern void _zbar_symbol_set_free(zbar_symbol_set_t*); + static inline void sym_add_point (zbar_symbol_t *sym, int x, int y) @@ -60,20 +71,21 @@ static inline void sym_add_point (zbar_symbol_t *sym, sym->pts[i].y = y; } -static inline void sym_destroy (zbar_symbol_t *sym) -{ - if(sym->pts) - free(sym->pts); - if(sym->data_alloc && sym->data) - free(sym->data); - free(sym); -} - static inline void _zbar_symbol_refcnt (zbar_symbol_t *sym, int delta) { if(!_zbar_refcnt(&sym->refcnt, delta) && delta <= 0) - sym_destroy(sym); + _zbar_symbol_free(sym); +} + +static inline void _zbar_symbol_set_add (zbar_symbol_set_t *syms, + zbar_symbol_t *sym) +{ + sym->next = syms->head; + syms->head = sym; + syms->nsyms++; + + _zbar_symbol_refcnt(sym, 1); } #endif diff --git a/zbar/window.c b/zbar/window.c index 68436f9..3bb32f5 100644 --- a/zbar/window.c +++ b/zbar/window.c @@ -69,9 +69,11 @@ static void window_outline_symbol (zbar_window_t *w, uint32_t color, const zbar_symbol_t *sym) { - const zbar_symbol_t *s; - for(s = sym->syms; s; s = s->next) - window_outline_symbol(w, 1, s); + if(sym->syms) { + const zbar_symbol_t *s; + for(s = sym->syms->head; s; s = s->next) + window_outline_symbol(w, 1, s); + } _zbar_window_draw_polygon(w, color, sym->pts, sym->npts); } @@ -82,9 +84,9 @@ static inline int window_draw_overlay (zbar_window_t *w) */ if(!w->overlay) return(0); - if(w->overlay >= 1 && w->image) { + if(w->overlay >= 1 && w->image && w->image->syms) { /* FIXME outline each symbol */ - const zbar_symbol_t *sym = zbar_image_first_symbol(w->image); + const zbar_symbol_t *sym = w->image->syms->head; for(; sym; sym = sym->next) { uint32_t color = ((sym->cache_count < 0) ? 4 : 2); if(sym->type == ZBAR_QRCODE) @@ -149,6 +151,9 @@ inline int zbar_window_redraw (zbar_window_t *w) (char*)&w->format, w->format, w->dst_width, w->dst_height); w->image = zbar_image_convert_resize(img, w->format, w->dst_width, w->dst_height); + w->image->syms = img->syms; + if(img->syms) + zbar_symbol_set_ref(img->syms, 1); zbar_image_destroy(img); img = w->image; } From 2306d0f13aee4f1d8fd04c9d930bf7c6e111ca1a Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 25 Sep 2009 10:35:46 -0400 Subject: [PATCH 137/328] cleanup SVG debug dump (partial) - some QR integration API cleanup --- ChangeLog | 2 + zbar/Makefile.am.inc | 2 + zbar/decoder/qrcode.h | 191 ++------------------------------- zbar/decoder/qrcode/qrdec.c | 126 +++++++++++++--------- zbar/decoder/qrcode/qrdec.h | 168 +++++++++++++++++++++++++++++ zbar/decoder/qrcode/qrdectxt.c | 1 + zbar/image.c | 60 +++++++++++ zbar/image.h | 8 +- zbar/img_scanner.c | 75 +++---------- zbar/svg.c | 171 +++++++++++++++++++++++++++++ zbar/svg.h | 63 +++++++++++ 11 files changed, 576 insertions(+), 291 deletions(-) create mode 100644 zbar/decoder/qrcode/qrdec.h create mode 100644 zbar/svg.c create mode 100644 zbar/svg.h diff --git a/ChangeLog b/ChangeLog index 49e89f3..9439db6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * cleanup SVG debug dump (partial) + - some QR integration API cleanup * extract explicit result container, separate from image - remove (broken/tmp) converted image result sharing - add explicit symbol recycle API, update processor/widgets to use diff --git a/zbar/Makefile.am.inc b/zbar/Makefile.am.inc index eedbd93..0e0a464 100644 --- a/zbar/Makefile.am.inc +++ b/zbar/Makefile.am.inc @@ -14,6 +14,8 @@ zbar_libzbar_la_SOURCES = zbar/debug.h zbar/config.c \ zbar/img_scanner.h zbar/img_scanner.c zbar/scanner.c \ zbar/decoder.h zbar/decoder.c +EXTRA_zbar_libzbar_la_SOURCES = zbar/svg.h zbar/svg.c + if ENABLE_EAN zbar_libzbar_la_SOURCES += zbar/decoder/ean.h zbar/decoder/ean.c endif diff --git a/zbar/decoder/qrcode.h b/zbar/decoder/qrcode.h index edf0b77..13470e7 100644 --- a/zbar/decoder/qrcode.h +++ b/zbar/decoder/qrcode.h @@ -3,24 +3,15 @@ GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.*/ -#if !defined(_qrcode_H) -# define _qrcode_H (1) +#ifndef _QRCODE_H_ +#define _QRCODE_H_ #include -# if defined(__cplusplus) -extern "C" { -# endif +typedef struct qr_reader qr_reader; typedef int qr_point[2]; - -typedef struct qr_reader qr_reader; - -typedef struct qr_code_data_entry qr_code_data_entry; -typedef struct qr_code_data qr_code_data; -typedef struct qr_code_data_list qr_code_data_list; - -typedef struct qr_finder_line qr_finder_line; +typedef struct qr_finder_line qr_finder_line; /*The number of bits of subpel precision to store image coordinates in. This helps when estimating positions in low-resolution images, which may have @@ -40,7 +31,7 @@ typedef struct qr_finder_line qr_finder_line; | pos[v] pos[v]-boffs Here v is 0 for horizontal and 1 for vertical lines.*/ -struct qr_finder_line{ +struct qr_finder_line { /*The location of the upper/left endpoint of the line. The left/upper edge of the center section is used, since other lines must cross in this region.*/ @@ -61,177 +52,15 @@ struct qr_finder_line{ int eoffs; }; - -typedef enum qr_mode{ - /*Numeric digits ('0'...'9').*/ - QR_MODE_NUM=1, - /*Alphanumeric characters ('0'...'9', 'A'...'Z', plus the punctuation - ' ', '$', '%', '*', '+', '-', '.', '/', ':').*/ - QR_MODE_ALNUM, - /*Structured-append header.*/ - QR_MODE_STRUCT, - /*Raw 8-bit bytes.*/ - QR_MODE_BYTE, - /*FNC1 marker (for more info, see http://www.mecsw.com/specs/uccean128.html). - In the "first position" data is formatted in accordance with GS1 General - Specifications.*/ - QR_MODE_FNC1_1ST, - /*Mode 6 reserved?*/ - /*Extended Channel Interpretation code.*/ - QR_MODE_ECI=7, - /*SJIS kanji characters.*/ - QR_MODE_KANJI, - /*FNC1 marker (for more info, see http://www.mecsw.com/specs/uccean128.html). - In the "second position" data is formatted in accordance with an industry - application as specified by AIM Inc.*/ - QR_MODE_FNC1_2ND -}qr_mode; - -/*Check if a mode has a data buffer associated with it. - Currently this is only modes with exactly one bit set.*/ -#define QR_MODE_HAS_DATA(_mode) (!((_mode)&(_mode)-1)) - -/*ECI may be used to signal a character encoding for the data.*/ -typedef enum qr_eci_encoding{ - /*GLI0 is like CP437, but the encoding is reset at the beginning of each - structured append symbol.*/ - QR_ECI_GLI0, - /*GLI1 is like ISO8859_1, but the encoding is reset at the beginning of each - structured append symbol.*/ - QR_ECI_GLI1, - /*The remaining encodings do not reset at the start of the next structured - append symbol.*/ - QR_ECI_CP437, - /*Western European.*/ - QR_ECI_ISO8859_1, - /*Central European.*/ - QR_ECI_ISO8859_2, - /*South European.*/ - QR_ECI_ISO8859_3, - /*North European.*/ - QR_ECI_ISO8859_4, - /*Cyrillic.*/ - QR_ECI_ISO8859_5, - /*Arabic.*/ - QR_ECI_ISO8859_6, - /*Greek.*/ - QR_ECI_ISO8859_7, - /*Hebrew.*/ - QR_ECI_ISO8859_8, - /*Turkish.*/ - QR_ECI_ISO8859_9, - /*Nordic.*/ - QR_ECI_ISO8859_10, - /*Thai.*/ - QR_ECI_ISO8859_11, - /*There is no ISO/IEC 8859-12.*/ - /*Baltic rim.*/ - QR_ECI_ISO8859_13=QR_ECI_ISO8859_11+2, - /*Celtic.*/ - QR_ECI_ISO8859_14, - /*Western European with euro.*/ - QR_ECI_ISO8859_15, - /*South-Eastern European (with euro).*/ - QR_ECI_ISO8859_16, - /*ECI 000019 is reserved?*/ - /*Shift-JIS.*/ - QR_ECI_SJIS=20 -}qr_eci_encoding; - - -/*A single unit of parsed QR code data.*/ -struct qr_code_data_entry{ - /*The mode of this data block.*/ - qr_mode mode; - union{ - /*Data buffer for modes that have one.*/ - struct{ - unsigned char *buf; - int len; - }data; - /*Decoded "Extended Channel Interpretation" data.*/ - unsigned eci; - /*Structured-append header data.*/ - struct{ - unsigned char sa_index; - unsigned char sa_size; - unsigned char sa_parity; - }sa; - }payload; -}; - - - -/*Low-level QR code data.*/ -struct qr_code_data{ - /*The decoded data entries.*/ - qr_code_data_entry *entries; - int nentries; - /*The code version (1...40).*/ - unsigned char version; - /*The ECC level (0...3, corresponding to 'L', 'M', 'Q', and 'H').*/ - unsigned char ecc_level; - /*Structured-append information.*/ - /*The index of this code in the structured-append group. - If sa_size is zero, this is undefined.*/ - unsigned char sa_index; - /*The size of the structured-append group, or 0 if there was no S-A header.*/ - unsigned char sa_size; - /*The parity of the entire structured-append group. - If sa_size is zero, this is undefined.*/ - unsigned char sa_parity; - /*The parity of this code. - If sa_size is zero, this is undefined.*/ - unsigned char self_parity; - /*An approximate bounding box for the code. - Points appear in the order up-left, up-right, down-left, down-right, - relative to the orientation of the QR code.*/ - qr_point bbox[4]; -}; - - -struct qr_code_data_list{ - qr_code_data *qrdata; - int nqrdata; - int cqrdata; -}; - -/*Initialize an empty list of qrcode data.*/ -void qr_code_data_list_init(qr_code_data_list *_qrlist); -/*Free a list of decoded QR code data returned by qr_reader_locate().*/ -void qr_code_data_list_clear(qr_code_data_list *_qrlist); - -/*Extract symbol data from a list of QR codes and attach to the image. - All text is converted to UTF-8. - Any structured-append group that does not have all of its members is decoded - as ZBAR_PARTIAL with ZBAR_PARTIAL components for the discontinuities. - Note that isolated members of a structured-append group may be decoded with - the wrong character set, since the correct setting cannot be propagated - between codes. - Return: The number of symbols which were successfully extracted from the - codes; this will be at most the number of codes.*/ -int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, - zbar_image_scanner_t *iscn, - zbar_image_t *img); - - -qr_reader *qr_reader_alloc(void); -void qr_reader_free(qr_reader *_reader); -void qr_reader_reset(qr_reader *reader); - -/*TODO: Parse DoCoMo standard barcode data formats. - See http://www.nttdocomo.co.jp/english/service/imode/make/content/barcode/function/application/ - for details.*/ +qr_reader *_zbar_qr_create(void); +void _zbar_qr_destroy(qr_reader *reader); +void _zbar_qr_reset(qr_reader *reader); int _zbar_qr_found_line(qr_reader *reader, int direction, const qr_finder_line *line); -int _zbar_qr_decode(zbar_image_scanner_t *iscn, - qr_reader *reader, +int _zbar_qr_decode(qr_reader *reader, + zbar_image_scanner_t *iscn, zbar_image_t *img); -# if defined(__cplusplus) -} -# endif - #endif diff --git a/zbar/decoder/qrcode/qrdec.c b/zbar/decoder/qrcode/qrdec.c index a488f90..e190e27 100644 --- a/zbar/decoder/qrcode/qrdec.c +++ b/zbar/decoder/qrcode/qrdec.c @@ -8,6 +8,7 @@ #include #include #include "decoder/qrcode.h" +#include "qrdec.h" #include "bch15_5.h" #include "rs.h" #include "isaac.h" @@ -15,12 +16,13 @@ #include "binarize.h" #include "image.h" #include "error.h" +#include "svg.h" typedef int qr_line[3]; typedef struct qr_finder_cluster qr_finder_cluster; -typedef struct qr_finder_edge_pt qr_finder_edge_pt; -typedef struct qr_finder_center qr_finder_center; +typedef struct qr_finder_edge_pt qr_finder_edge_pt; +typedef struct qr_finder_center qr_finder_center; typedef struct qr_aff qr_aff; typedef struct qr_hom qr_hom; @@ -58,47 +60,49 @@ typedef struct qr_finder_lines { } qr_finder_lines; -struct qr_reader{ - /*The GF(256) representation used in Reed-Solomon decoding.*/ - rs_gf256 gf; - /*The random number generator used by RANSAC.*/ - isaac_ctx isaac; - /* current finder state, horizontal and vertical lines */ - qr_finder_lines finder_lines[2]; +struct qr_reader { + /*The GF(256) representation used in Reed-Solomon decoding.*/ + rs_gf256 gf; + /*The random number generator used by RANSAC.*/ + isaac_ctx isaac; + /* current finder state, horizontal and vertical lines */ + qr_finder_lines finder_lines[2]; }; /*Initializes a client reader handle.*/ -static void qr_reader_init(qr_reader *_reader){ - /*time_t now; - now=time(NULL); - isaac_init(&_reader->isaac,&now,sizeof(now));*/ - isaac_init(&_reader->isaac,NULL,0); - rs_gf256_init(&_reader->gf,QR_PPOLY); +static void qr_reader_init (qr_reader *reader) +{ + /*time_t now; + now=time(NULL); + isaac_init(&_reader->isaac,&now,sizeof(now));*/ + isaac_init(&reader->isaac, NULL, 0); + rs_gf256_init(&reader->gf, QR_PPOLY); } /*Allocates a client reader handle.*/ -qr_reader *qr_reader_alloc(void){ - qr_reader *reader; - reader=(qr_reader *)calloc(1, sizeof(*reader)); - qr_reader_init(reader); - return reader; +qr_reader *_zbar_qr_create (void) +{ + qr_reader *reader = (qr_reader*)calloc(1, sizeof(*reader)); + qr_reader_init(reader); + return(reader); } /*Frees a client reader handle.*/ -void qr_reader_free(qr_reader *_reader){ - if(_reader->finder_lines[0].lines) - free(_reader->finder_lines[0].lines); - if(_reader->finder_lines[1].lines) - free(_reader->finder_lines[1].lines); - free(_reader); +void _zbar_qr_destroy (qr_reader *reader) +{ + if(reader->finder_lines[0].lines) + free(reader->finder_lines[0].lines); + if(reader->finder_lines[1].lines) + free(reader->finder_lines[1].lines); + free(reader); } /* reset finder state between scans */ -void qr_reader_reset (qr_reader *reader) +void _zbar_qr_reset (qr_reader *reader) { - reader->finder_lines[0].num_lines = 0; - reader->finder_lines[1].num_lines = 0; + reader->finder_lines[0].num_lines = 0; + reader->finder_lines[1].num_lines = 0; } @@ -142,6 +146,7 @@ struct qr_finder_center{ int nedge_pts; }; + static int qr_finder_vline_cmp(const void *_a,const void *_b){ const qr_finder_line *a; const qr_finder_line *b; @@ -2565,6 +2570,17 @@ static const unsigned char QR_ALIGNMENT_SPACING[34]={ 24,26,26,26,28,28 }; +static inline void qr_svg_points(const char *cls, + qr_point *p, + int n) +{ + svg_path_start(cls, 1, 0, 0); + int i; + for(i = 0; i < n; i++, p++) + svg_path_moveto(SVG_ABS, p[0][0], p[0][1]); + svg_path_end(); +} + /*Initialize the sampling grid for each region of the code. _version: The (decoded) version number. _ul_pos: The location of the UL finder pattern. @@ -2705,6 +2721,7 @@ static void qr_sampling_grid_init(qr_sampling_grid *_grid,int _version, } } } + qr_svg_points("align", p, nalign * nalign); free(q); free(p); } @@ -2937,6 +2954,7 @@ static void qr_sampling_grid_sample(const qr_sampling_grid *_grid, qr_data_mask_fill(_data_bits,_dim,_fmt_info&7); stride=_dim+QR_INT_BITS-1>>QR_INT_LOGBITS; u0=0; + svg_path_start("sampling-grid", 1, 0, 0); /*We read data cell-by-cell to avoid having to constantly change which projection we're using as we read each bit. This (and the position-dependent data mask) is the reason we buffer the @@ -2979,6 +2997,7 @@ static void qr_sampling_grid_sample(const qr_sampling_grid *_grid, qr_hom_cell_fproject(p,cell,x,y,w); _data_bits[u*stride+(v>>QR_INT_LOGBITS)]^= qr_img_get_bit(_img,_width,_height,p[0],p[1])<<(v&QR_INT_BITS-1); + svg_path_moveto(SVG_ABS, p[0], p[1]); } x+=cell->fwd[0][1]; y+=cell->fwd[1][1]; @@ -2992,6 +3011,7 @@ static void qr_sampling_grid_sample(const qr_sampling_grid *_grid, } u0=u1; } + svg_path_end(); } /*Arranges the sample bits read by qr_sampling_grid_sample() into bytes and @@ -3850,11 +3870,11 @@ void qr_reader_match_centers(qr_reader *_reader,qr_code_data_list *_qrlist, } int _zbar_qr_found_line (qr_reader *reader, - int direction, + int dir, const qr_finder_line *line) { /* minimally intrusive brute force version */ - qr_finder_lines *lines = &reader->finder_lines[direction]; + qr_finder_lines *lines = &reader->finder_lines[dir]; if(lines->num_lines >= lines->max_lines) { lines->max_lines *= 2; @@ -3863,37 +3883,46 @@ int _zbar_qr_found_line (qr_reader *reader, } memcpy(lines->lines + lines->num_lines++, line, sizeof(*line)); - return(1); + + return(0); } -int _zbar_qr_decode (zbar_image_scanner_t *iscn, - qr_reader *reader, +static inline void qr_svg_centers (const qr_finder_center *centers, + int ncenters) +{ + int i, j; + svg_path_start("centers", 1, 0, 0); + for(i = 0; i < ncenters; i++) + svg_path_moveto(SVG_ABS, centers[i].pos[0], centers[i].pos[1]); + svg_path_end(); + + svg_path_start("edge-pts", 1, 0, 0); + for(i = 0; i < ncenters; i++) { + const qr_finder_center *cen = centers + i; + for(j = 0; j < cen->nedge_pts; j++) + svg_path_moveto(SVG_ABS, + cen->edge_pts[j].pos[0], cen->edge_pts[j].pos[1]); + } + svg_path_end(); +} + +int _zbar_qr_decode (qr_reader *reader, + zbar_image_scanner_t *iscn, zbar_image_t *img) { int nqrdata = 0; qr_finder_edge_pt *edge_pts = NULL; qr_finder_center *centers = NULL; + svg_group_start("finder", 1. / (1 << QR_FINDER_SUBPREC), 0, 0); + int ncenters = qr_finder_centers_locate(¢ers, &edge_pts, reader, 0, 0); zprintf(14, "%dx%d finders, %d centers:\n", reader->finder_lines[0].num_lines, reader->finder_lines[1].num_lines, ncenters); - if(_zbar_verbosity >= 18) { - int i, j; - for(i = 0; i < ncenters; i++) { - qr_finder_center *cen = centers + i; - fprintf(stderr, "\t[%d] %d,%d:", i, cen->pos[0], cen->pos[1]); - for(j = 0; j < cen->nedge_pts; j++) { - qr_finder_edge_pt *edge = cen->edge_pts + j; - fprintf(stderr, " %d,%dx%d@%d", - edge->pos[0], edge->pos[1], - edge->extent, edge->edge); - } - fprintf(stderr, "\n"); - } - } + qr_svg_centers(centers, ncenters); if(ncenters >= 3) { void *bin = qr_binarize(img->data, img->width, img->height); @@ -3910,6 +3939,7 @@ int _zbar_qr_decode (zbar_image_scanner_t *iscn, qr_code_data_list_clear(&qrlist); free(bin); } + svg_group_end(); if(centers) free(centers); diff --git a/zbar/decoder/qrcode/qrdec.h b/zbar/decoder/qrcode/qrdec.h new file mode 100644 index 0000000..2074e68 --- /dev/null +++ b/zbar/decoder/qrcode/qrdec.h @@ -0,0 +1,168 @@ +/*Copyright (C) 2008-2009 Timothy B. Terriberry (tterribe@xiph.org) + You can redistribute this library and/or modify it under the terms of the + GNU Lesser General Public License as published by the Free Software + Foundation; either version 2.1 of the License, or (at your option) any later + version.*/ +#if !defined(_qrdec_H) +# define _qrdec_H (1) + +#include + +typedef struct qr_code_data_entry qr_code_data_entry; +typedef struct qr_code_data qr_code_data; +typedef struct qr_code_data_list qr_code_data_list; + +typedef enum qr_mode{ + /*Numeric digits ('0'...'9').*/ + QR_MODE_NUM=1, + /*Alphanumeric characters ('0'...'9', 'A'...'Z', plus the punctuation + ' ', '$', '%', '*', '+', '-', '.', '/', ':').*/ + QR_MODE_ALNUM, + /*Structured-append header.*/ + QR_MODE_STRUCT, + /*Raw 8-bit bytes.*/ + QR_MODE_BYTE, + /*FNC1 marker (for more info, see http://www.mecsw.com/specs/uccean128.html). + In the "first position" data is formatted in accordance with GS1 General + Specifications.*/ + QR_MODE_FNC1_1ST, + /*Mode 6 reserved?*/ + /*Extended Channel Interpretation code.*/ + QR_MODE_ECI=7, + /*SJIS kanji characters.*/ + QR_MODE_KANJI, + /*FNC1 marker (for more info, see http://www.mecsw.com/specs/uccean128.html). + In the "second position" data is formatted in accordance with an industry + application as specified by AIM Inc.*/ + QR_MODE_FNC1_2ND +}qr_mode; + +/*Check if a mode has a data buffer associated with it. + Currently this is only modes with exactly one bit set.*/ +#define QR_MODE_HAS_DATA(_mode) (!((_mode)&(_mode)-1)) + +/*ECI may be used to signal a character encoding for the data.*/ +typedef enum qr_eci_encoding{ + /*GLI0 is like CP437, but the encoding is reset at the beginning of each + structured append symbol.*/ + QR_ECI_GLI0, + /*GLI1 is like ISO8859_1, but the encoding is reset at the beginning of each + structured append symbol.*/ + QR_ECI_GLI1, + /*The remaining encodings do not reset at the start of the next structured + append symbol.*/ + QR_ECI_CP437, + /*Western European.*/ + QR_ECI_ISO8859_1, + /*Central European.*/ + QR_ECI_ISO8859_2, + /*South European.*/ + QR_ECI_ISO8859_3, + /*North European.*/ + QR_ECI_ISO8859_4, + /*Cyrillic.*/ + QR_ECI_ISO8859_5, + /*Arabic.*/ + QR_ECI_ISO8859_6, + /*Greek.*/ + QR_ECI_ISO8859_7, + /*Hebrew.*/ + QR_ECI_ISO8859_8, + /*Turkish.*/ + QR_ECI_ISO8859_9, + /*Nordic.*/ + QR_ECI_ISO8859_10, + /*Thai.*/ + QR_ECI_ISO8859_11, + /*There is no ISO/IEC 8859-12.*/ + /*Baltic rim.*/ + QR_ECI_ISO8859_13=QR_ECI_ISO8859_11+2, + /*Celtic.*/ + QR_ECI_ISO8859_14, + /*Western European with euro.*/ + QR_ECI_ISO8859_15, + /*South-Eastern European (with euro).*/ + QR_ECI_ISO8859_16, + /*ECI 000019 is reserved?*/ + /*Shift-JIS.*/ + QR_ECI_SJIS=20 +}qr_eci_encoding; + + +/*A single unit of parsed QR code data.*/ +struct qr_code_data_entry{ + /*The mode of this data block.*/ + qr_mode mode; + union{ + /*Data buffer for modes that have one.*/ + struct{ + unsigned char *buf; + int len; + }data; + /*Decoded "Extended Channel Interpretation" data.*/ + unsigned eci; + /*Structured-append header data.*/ + struct{ + unsigned char sa_index; + unsigned char sa_size; + unsigned char sa_parity; + }sa; + }payload; +}; + + + +/*Low-level QR code data.*/ +struct qr_code_data{ + /*The decoded data entries.*/ + qr_code_data_entry *entries; + int nentries; + /*The code version (1...40).*/ + unsigned char version; + /*The ECC level (0...3, corresponding to 'L', 'M', 'Q', and 'H').*/ + unsigned char ecc_level; + /*Structured-append information.*/ + /*The index of this code in the structured-append group. + If sa_size is zero, this is undefined.*/ + unsigned char sa_index; + /*The size of the structured-append group, or 0 if there was no S-A header.*/ + unsigned char sa_size; + /*The parity of the entire structured-append group. + If sa_size is zero, this is undefined.*/ + unsigned char sa_parity; + /*The parity of this code. + If sa_size is zero, this is undefined.*/ + unsigned char self_parity; + /*An approximate bounding box for the code. + Points appear in the order up-left, up-right, down-left, down-right, + relative to the orientation of the QR code.*/ + qr_point bbox[4]; +}; + + +struct qr_code_data_list{ + qr_code_data *qrdata; + int nqrdata; + int cqrdata; +}; + + +/*Extract symbol data from a list of QR codes and attach to the image. + All text is converted to UTF-8. + Any structured-append group that does not have all of its members is decoded + as ZBAR_PARTIAL with ZBAR_PARTIAL components for the discontinuities. + Note that isolated members of a structured-append group may be decoded with + the wrong character set, since the correct setting cannot be propagated + between codes. + Return: The number of symbols which were successfully extracted from the + codes; this will be at most the number of codes.*/ +int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, + zbar_image_scanner_t *iscn, + zbar_image_t *img); + + +/*TODO: Parse DoCoMo standard barcode data formats. + See http://www.nttdocomo.co.jp/english/service/imode/make/content/barcode/function/application/ + for details.*/ + +#endif diff --git a/zbar/decoder/qrcode/qrdectxt.c b/zbar/decoder/qrcode/qrdectxt.c index 39ac6d4..3f8beb3 100644 --- a/zbar/decoder/qrcode/qrdectxt.c +++ b/zbar/decoder/qrcode/qrdectxt.c @@ -8,6 +8,7 @@ #include #include #include "decoder/qrcode.h" +#include "qrdec.h" #include "util.h" #include "image.h" #include "error.h" diff --git a/zbar/image.c b/zbar/image.c index ec36150..3beadcd 100644 --- a/zbar/image.c +++ b/zbar/image.c @@ -240,3 +240,63 @@ int zbar_image_write (const zbar_image_t *img, } return(fclose(f)); } + +#ifdef DEBUG_SVG +# include + +int zbar_image_write_png (const zbar_image_t *img, + const char *filename) +{ + int rc = -1; + FILE *file = NULL; + png_struct *png = NULL; + png_info *info = NULL; + const uint8_t **rows = NULL; + + rows = malloc(img->height * sizeof(*rows)); + if(!rows) + goto done; + + rows[0] = img->data; + int y; + for(y = 1; y < img->height; y++) + rows[y] = rows[y - 1] + img->width; + + file = fopen(filename, "w"); + if(!file) + goto done; + + png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if(!png) + goto done; + + info = png_create_info_struct(png); + if(!info) + goto done; + + if(setjmp(png_jmpbuf(png))) + goto done; + + png_init_io(png, file); + png_set_compression_level(png, 9); + png_set_IHDR(png, info, img->width, img->height, 8, PNG_COLOR_TYPE_GRAY, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + + png_set_rows(png, info, (void*)rows); + png_write_png(png, info, PNG_TRANSFORM_IDENTITY, NULL); + + png_write_end(png,info); + rc = 0; + +done: + if(png) + png_destroy_write_struct(&png, &info); + if(rows) + free(rows); + if(file) + fclose(file); + return(rc); +} + +#endif diff --git a/zbar/image.h b/zbar/image.h index 5c4a794..8886ead 100644 --- a/zbar/image.h +++ b/zbar/image.h @@ -102,7 +102,13 @@ typedef struct zbar_format_def_s { extern int _zbar_best_format(uint32_t, uint32_t*, const uint32_t*); extern const zbar_format_def_t *_zbar_format_lookup(uint32_t); -extern void _zbar_image_free(zbar_image_t *img); +extern void _zbar_image_free(zbar_image_t*); + +#ifdef DEBUG_SVG +extern int zbar_image_write_png(const zbar_image_t*, const char*); +#else +# define zbar_image_write_png(...) +#endif static inline void _zbar_image_refcnt (zbar_image_t *img, int delta) diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 4e0ee1e..448556d 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -39,11 +39,7 @@ # include "decoder/qrcode.h" #endif #include "img_scanner.h" - -#ifdef DEBUG_IMG_SCANNER -# define DEBUG_LEVEL (DEBUG_IMG_SCANNER) -#endif -#include "debug.h" +#include "svg.h" #if 1 # define ASSERT_POS \ @@ -376,37 +372,6 @@ static void qr_handler (zbar_image_scanner_t *iscn, line->eoffs = tmp; } - zprintf(127, "qrf: u=%d.%03d boff=%d.%03d pos=%d.%03d,%d.%03d" - " len=%d.%03d eoff=%d.%03d\n", - PRINT_FIXED(u, QR_FINDER_SUBPREC), - PRINT_FIXED(line->boffs, QR_FINDER_SUBPREC), - PRINT_FIXED(line->pos[0], QR_FINDER_SUBPREC), - PRINT_FIXED(line->pos[1], QR_FINDER_SUBPREC), - PRINT_FIXED(line->len, QR_FINDER_SUBPREC), - PRINT_FIXED(line->eoffs, QR_FINDER_SUBPREC)); - - dprintf(1, "\n" - "\n", - PRINT_FIXED(line->pos[0], QR_FINDER_SUBPREC), - PRINT_FIXED(line->pos[1], QR_FINDER_SUBPREC), - (iscn->dx) ? 'h' : 'v', - PRINT_FIXED(line->len, QR_FINDER_SUBPREC), - - PRINT_FIXED(line->pos[0] - ((iscn->dx) ? line->boffs : 1), - QR_FINDER_SUBPREC), - PRINT_FIXED(line->pos[1] - ((iscn->dx) ? 1 : line->boffs), - QR_FINDER_SUBPREC), - (iscn->dx) ? 'v' : 'h', - PRINT_FIXED(2, QR_FINDER_SUBPREC), - - PRINT_FIXED(line->pos[0] + ((iscn->dx) ? line->len + line->eoffs : -1), - QR_FINDER_SUBPREC), - PRINT_FIXED(line->pos[1] + ((iscn->dx) ? -1 : line->len + line->eoffs), - QR_FINDER_SUBPREC), - (iscn->dx) ? 'v' : 'h', - PRINT_FIXED(2, QR_FINDER_SUBPREC)); - _zbar_qr_found_line(iscn->qr, !iscn->dx, line); } #endif @@ -473,7 +438,7 @@ zbar_image_scanner_t *zbar_image_scanner_create () } #ifdef ENABLE_QRCODE - iscn->qr = qr_reader_alloc(); + iscn->qr = _zbar_qr_create(); #endif /* apply default configuration */ @@ -525,7 +490,7 @@ void zbar_image_scanner_destroy (zbar_image_scanner_t *iscn) } #ifdef ENABLE_QRCODE if(iscn->qr) { - qr_reader_free(iscn->qr); + _zbar_qr_destroy(iscn->qr); iscn->qr = NULL; } #endif @@ -598,25 +563,6 @@ static inline void quiet_border (zbar_image_scanner_t *iscn, symbol_handler(iscn, x, y); } -#ifdef DEBUG_IMG_SCANNER -const char svg_head[] = - "\n" - "\n" - "\n" - "\n" - "\n"; -#endif - #define movedelta(dx, dy) do { \ x += (dx); \ y += (dy); \ @@ -640,7 +586,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, #endif #ifdef ENABLE_QRCODE - qr_reader_reset(iscn->qr); + _zbar_qr_reset(iscn->qr); #endif /* get grayscale image, convert if necessary */ @@ -665,7 +611,9 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, unsigned h = img->height; const uint8_t *data = img->data; - dprintf(1, svg_head, w, h, w, h); + zbar_image_write_png(img, "debug.png"); + svg_open("debug.svg", 0, 0, w, h); + svg_image("debug.png", w, h); int density = CFG(iscn, ZBAR_CFG_Y_DENSITY); if(density > 0) { @@ -753,9 +701,8 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, iscn->img = NULL; #ifdef ENABLE_QRCODE - _zbar_qr_decode(iscn, iscn->qr, img); + _zbar_qr_decode(iscn->qr, iscn, img); #endif - dprintf(1, "\n"); /* FIXME tmp hack to filter bad EAN results */ if(syms->nsyms && !iscn->enable_cache && @@ -779,5 +726,11 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, if(syms->nsyms && iscn->handler) iscn->handler(img, iscn->userdata); + svg_close(); return(syms->nsyms); } + +#ifdef DEBUG_SVG +/* FIXME lame...*/ +# include "svg.c" +#endif diff --git a/zbar/svg.c b/zbar/svg.c new file mode 100644 index 0000000..fe8c5a9 --- /dev/null +++ b/zbar/svg.c @@ -0,0 +1,171 @@ +/*------------------------------------------------------------------------ + * Copyright 2009 (c) Jeff Brown + * + * 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 +#include +#include + +#include "svg.h" + +static const char svg_head[] = + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n"; + +static FILE *svg = NULL; + +void svg_open (const char *name, double x, double y, double w, double h) +{ + svg = fopen(name, "w"); + if(!svg) return; + + /* FIXME calc scaled size */ + fprintf(svg, svg_head, x, y, w, h); +} + +void svg_close () +{ + if(!svg) return; + fprintf(svg, "\n"); + fclose(svg); + svg = NULL; +} + +void svg_commentf (const char *format, ...) +{ + if(!svg) return; + fprintf(svg, "\n"); +} + +void svg_image (const char *name, double width, double height) +{ + if(!svg) return; + fprintf(svg, "\n", + width, height, name); +} + +void svg_group_start (const char *cls, + double scale, + double x, + double y) +{ + if(!svg) return; + fprintf(svg, "\n"); +} + +void svg_group_end () +{ + fprintf(svg, "\n"); +} + +void svg_path_start (const char *cls, + double scale, + double x, + double y) +{ + if(!svg) return; + fprintf(svg, "\n"); +} + +void svg_path_close () +{ + if(!svg) return; + fprintf(svg, "z"); +} + +void svg_path_moveto (svg_absrel_t abs, double x, double y) +{ + if(!svg) return; + fprintf(svg, " %c%g,%g", (abs) ? 'M' : 'm', x, y); +} + +void svg_path_lineto(svg_absrel_t abs, double x, double y) +{ + if(!svg) return; + if(x && y) + fprintf(svg, "%c%g,%g", (abs) ? 'L' : 'l', x, y); + else if(x) + fprintf(svg, "%c%g", (abs) ? 'H' : 'h', x); + else if(y) + fprintf(svg, "%c%g", (abs) ? 'V' : 'v', y); +} diff --git a/zbar/svg.h b/zbar/svg.h new file mode 100644 index 0000000..bcd348f --- /dev/null +++ b/zbar/svg.h @@ -0,0 +1,63 @@ +/*------------------------------------------------------------------------ + * Copyright 2009 (c) Jeff Brown + * + * 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 + *------------------------------------------------------------------------*/ +#ifndef _SVG_H_ +#define _SVG_H_ + +#ifdef DEBUG_SVG + +typedef enum { SVG_REL, SVG_ABS } svg_absrel_t; + +void svg_open(const char *name, double x, double y, double w, double h); +void svg_close(void); + +void svg_commentf(const char *format, ...); +void svg_image(const char *name, double width, double height); + +void svg_group_start(const char *class, double scale, double x, double y); +void svg_group_end(void); + +void svg_path_start(const char *class, double scale, double x, double y); +void svg_path_end(void); +void svg_path_close(void); +void svg_path_moveto(svg_absrel_t abs, double x, double y); +void svg_path_lineto(svg_absrel_t abs, double x, double y); + +#else + +# define svg_open(...) +# define svg_close(...) + +# define svg_image(...) + +# define svg_group_start(...) +# define svg_group_end(...) + +# define svg_path_start(...) +# define svg_path_end(...) +# define svg_path_moveto(...) +# define svg_path_lineto(...) +# define svg_path_close(...) + +#endif + +#endif From 5830d650d2057a98ee2b0fa887c03af3a9abe657 Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 25 Sep 2009 15:57:07 -0400 Subject: [PATCH 138/328] fix QR structured append result handling --- ChangeLog | 1 + zbar/decoder/qrcode/qrdectxt.c | 5 +++-- zbar/img_scanner.c | 1 + zbarcam/zbarcam.c | 9 ++++++--- zbarimg/zbarimg.c | 7 ++++--- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9439db6..61ab992 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * fix QR structured append result handling * cleanup SVG debug dump (partial) - some QR integration API cleanup * extract explicit result container, separate from image diff --git a/zbar/decoder/qrcode/qrdectxt.c b/zbar/decoder/qrcode/qrdectxt.c index 3f8beb3..fde8ac7 100644 --- a/zbar/decoder/qrcode/qrdectxt.c +++ b/zbar/decoder/qrcode/qrdectxt.c @@ -153,11 +153,11 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, /* mark break in data */ sa_text[sa_ntext++]='\0'; + (*sym)->datalen = sa_ntext; /* advance to next symbol */ - *sym = _zbar_image_scanner_alloc_sym(iscn, ZBAR_QRCODE, 0); - (*sym)->datalen = sa_ntext; sym = &(*sym)->next; + *sym = _zbar_image_scanner_alloc_sym(iscn, ZBAR_QRCODE, 0); } qrdataj=qrdata+sa[j]; @@ -351,6 +351,7 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, /* fixup data references */ for(; syms; syms = syms->next) { + _zbar_symbol_refcnt(syms, 1); if(syms->type == ZBAR_PARTIAL) sa_sym->type = ZBAR_PARTIAL; else diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 448556d..37cfc08 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -145,6 +145,7 @@ void _zbar_image_scanner_recycle_syms (zbar_image_scanner_t *iscn, if(_zbar_refcnt(&sym->syms->refcnt, -1)) assert(0); _zbar_image_scanner_recycle_syms(iscn, sym->syms->head); + sym->syms->head = NULL; _zbar_symbol_set_free(sym->syms); sym->syms = NULL; } diff --git a/zbarcam/zbarcam.c b/zbarcam/zbarcam.c index 0bf712a..ab6c08a 100644 --- a/zbarcam/zbarcam.c +++ b/zbarcam/zbarcam.c @@ -96,12 +96,15 @@ static void data_handler (zbar_image_t *img, const void *userdata) for(; sym; sym = zbar_symbol_next(sym)) { if(zbar_symbol_get_count(sym)) continue; - if(!format) { - zbar_symbol_type_t type = zbar_symbol_get_type(sym); + + zbar_symbol_type_t type = zbar_symbol_get_type(sym); + if(type == ZBAR_PARTIAL) + continue; + + if(!format) printf("%s%s:%s\n", zbar_get_symbol_name(type), zbar_get_addon_name(type), zbar_symbol_get_data(sym)); - } else if(format == RAW) printf("%s\n", zbar_symbol_get_data(sym)); else if(format == XML) { diff --git a/zbarimg/zbarimg.c b/zbarimg/zbarimg.c index c6cd296..9a04ec4 100644 --- a/zbarimg/zbarimg.c +++ b/zbarimg/zbarimg.c @@ -149,13 +149,14 @@ static int scan_image (const char *filename) // output result data const zbar_symbol_t *sym = zbar_image_first_symbol(zimage); for(; sym; sym = zbar_symbol_next(sym)) { - if(!xmllvl) { - zbar_symbol_type_t typ = zbar_symbol_get_type(sym); + zbar_symbol_type_t typ = zbar_symbol_get_type(sym); + if(typ == ZBAR_PARTIAL) + continue; + else if(!xmllvl) printf("%s%s:%s\n", zbar_get_symbol_name(typ), zbar_get_addon_name(typ), zbar_symbol_get_data(sym)); - } else if(xmllvl < 0) printf("%s\n", zbar_symbol_get_data(sym)); else { From b8a0a54674d8a94c3965fd34682f2046bba5cff8 Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 2 Oct 2009 09:59:37 -0400 Subject: [PATCH 139/328] fix zero length symbol data --- ChangeLog | 1 + examples/scan_image.c | 1 + zbar/decoder/qrcode/qrdec.c | 29 ++++++++++++++++++----------- zbar/img_scanner.c | 12 ++++++------ zbar/svg.c | 4 ++++ zbar/svg.h | 4 ++-- 6 files changed, 32 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index 61ab992..2aafd6b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * fix zero length symbol data * fix QR structured append result handling * cleanup SVG debug dump (partial) - some QR integration API cleanup diff --git a/examples/scan_image.c b/examples/scan_image.c index 2ce4a68..52db035 100644 --- a/examples/scan_image.c +++ b/examples/scan_image.c @@ -84,6 +84,7 @@ int main (int argc, char **argv) /* clean up */ zbar_image_destroy(image); + zbar_image_scanner_destroy(scanner); return(0); } diff --git a/zbar/decoder/qrcode/qrdec.c b/zbar/decoder/qrcode/qrdec.c index e190e27..f770d47 100644 --- a/zbar/decoder/qrcode/qrdec.c +++ b/zbar/decoder/qrcode/qrdec.c @@ -55,8 +55,8 @@ typedef struct qr_pack_buf qr_pack_buf; /* collection of finder lines */ typedef struct qr_finder_lines { - int num_lines, max_lines; qr_finder_line *lines; + int nlines, clines; } qr_finder_lines; @@ -91,6 +91,9 @@ qr_reader *_zbar_qr_create (void) /*Frees a client reader handle.*/ void _zbar_qr_destroy (qr_reader *reader) { + zprintf(1, "max finder lines = %dx%d\n", + reader->finder_lines[0].clines, + reader->finder_lines[1].clines); if(reader->finder_lines[0].lines) free(reader->finder_lines[0].lines); if(reader->finder_lines[1].lines) @@ -101,8 +104,8 @@ void _zbar_qr_destroy (qr_reader *reader) /* reset finder state between scans */ void _zbar_qr_reset (qr_reader *reader) { - reader->finder_lines[0].num_lines = 0; - reader->finder_lines[1].num_lines = 0; + reader->finder_lines[0].nlines = 0; + reader->finder_lines[1].nlines = 0; } @@ -403,9 +406,9 @@ static int qr_finder_centers_locate(qr_finder_center **_centers, qr_finder_edge_pt **_edge_pts, qr_reader *reader, int _width,int _height){ qr_finder_line *hlines = reader->finder_lines[0].lines; - int nhlines = reader->finder_lines[0].num_lines; + int nhlines = reader->finder_lines[0].nlines; qr_finder_line *vlines = reader->finder_lines[1].lines; - int nvlines = reader->finder_lines[1].num_lines; + int nvlines = reader->finder_lines[1].nlines; qr_finder_line **hneighbors; qr_finder_cluster *hclusters; @@ -3876,13 +3879,13 @@ int _zbar_qr_found_line (qr_reader *reader, /* minimally intrusive brute force version */ qr_finder_lines *lines = &reader->finder_lines[dir]; - if(lines->num_lines >= lines->max_lines) { - lines->max_lines *= 2; + if(lines->nlines >= lines->clines) { + lines->clines *= 2; lines->lines = realloc(lines->lines, - ++lines->max_lines * sizeof(*lines->lines)); + ++lines->clines * sizeof(*lines->lines)); } - memcpy(lines->lines + lines->num_lines++, line, sizeof(*line)); + memcpy(lines->lines + lines->nlines++, line, sizeof(*line)); return(0); } @@ -3914,13 +3917,17 @@ int _zbar_qr_decode (qr_reader *reader, qr_finder_edge_pt *edge_pts = NULL; qr_finder_center *centers = NULL; + if(reader->finder_lines[0].nlines < 9 || + reader->finder_lines[1].nlines < 9) + return(0); + svg_group_start("finder", 1. / (1 << QR_FINDER_SUBPREC), 0, 0); int ncenters = qr_finder_centers_locate(¢ers, &edge_pts, reader, 0, 0); zprintf(14, "%dx%d finders, %d centers:\n", - reader->finder_lines[0].num_lines, - reader->finder_lines[1].num_lines, + reader->finder_lines[0].nlines, + reader->finder_lines[1].nlines, ncenters); qr_svg_centers(centers, ncenters); diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 37cfc08..175d6ae 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -221,7 +221,7 @@ _zbar_image_scanner_alloc_sym (zbar_image_scanner_t *iscn, /* recycle old or alloc new symbol */ int i; for(i = 0; i < RECYCLE_BUCKETS - 1; i++) - if(datalen + 1 <= 1 << (i * 2)) + if(datalen <= 1 << (i * 2)) break; zbar_symbol_t *sym = NULL; @@ -250,8 +250,8 @@ _zbar_image_scanner_alloc_sym (zbar_image_scanner_t *iscn, sym->time = iscn->time; assert(!sym->syms); - if(datalen) { - sym->datalen = datalen++; + if(datalen > 0) { + sym->datalen = datalen - 1; if(sym->data_alloc < datalen) { if(sym->data) free(sym->data); @@ -299,8 +299,8 @@ inline void _zbar_image_scanner_cache_sym (zbar_image_scanner_t *iscn, if(!entry) { /* FIXME reuse sym */ entry = _zbar_image_scanner_alloc_sym(iscn, sym->type, - sym->datalen); - memcpy(entry->data, sym->data, sym->datalen + 1); + sym->datalen + 1); + memcpy(entry->data, sym->data, sym->datalen); entry->time = sym->time - CACHE_HYSTERESIS; entry->cache_count = -CACHE_CONSISTENCY; /* add to cache */ @@ -413,7 +413,7 @@ static void symbol_handler (zbar_image_scanner_t *iscn, return; } - sym = _zbar_image_scanner_alloc_sym(iscn, type, datalen); + sym = _zbar_image_scanner_alloc_sym(iscn, type, datalen + 1); /* FIXME grab decoder buffer */ memcpy(sym->data, data, datalen + 1); diff --git a/zbar/svg.c b/zbar/svg.c index fe8c5a9..2ed0b63 100644 --- a/zbar/svg.c +++ b/zbar/svg.c @@ -50,6 +50,10 @@ static const char svg_head[] = ".hedge { marker: url(#hedge) }\n" ".vedge { marker: url(#vedge) }\n" ".finder .hedge, .finder .vedge { /*stroke: #a0c;*/ stroke-width: .9 }\n" + ".cluster { stroke: #a0c; stroke-width: 1; stroke-opacity: .45 }\n" + ".cluster.valid { stroke: #c0a; stroke-width: 1; stroke-opacity: .666 }\n" + ".h.cluster { marker: url(#vedge) }\n" + ".v.cluster { marker: url(#hedge) }\n" ".centers { marker: url(#target); stroke-width: 3 }\n" ".edge-pts { marker: url(#ydot); stroke-width: .5 }\n" ".align { marker: url(#mdot); stroke-width: 1.5 }\n" diff --git a/zbar/svg.h b/zbar/svg.h index bcd348f..7b77181 100644 --- a/zbar/svg.h +++ b/zbar/svg.h @@ -33,10 +33,10 @@ void svg_close(void); void svg_commentf(const char *format, ...); void svg_image(const char *name, double width, double height); -void svg_group_start(const char *class, double scale, double x, double y); +void svg_group_start(const char *cls, double scale, double x, double y); void svg_group_end(void); -void svg_path_start(const char *class, double scale, double x, double y); +void svg_path_start(const char *cls, double scale, double x, double y); void svg_path_end(void); void svg_path_close(void); void svg_path_moveto(svg_absrel_t abs, double x, double y); From 9a6a37a7c1b2f50cf1a5f98b7965f5c7bada186d Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 2 Oct 2009 10:30:59 -0400 Subject: [PATCH 140/328] trim deep qrcode hierarchy --- ChangeLog | 1 + zbar/Makefile.am.inc | 14 +++++++------- zbar/img_scanner.c | 2 +- zbar/{decoder => }/qrcode.h | 0 zbar/{decoder => }/qrcode/bch15_5.c | 0 zbar/{decoder => }/qrcode/bch15_5.h | 0 zbar/{decoder => }/qrcode/binarize.c | 0 zbar/{decoder => }/qrcode/binarize.h | 0 zbar/{decoder => }/qrcode/isaac.c | 0 zbar/{decoder => }/qrcode/isaac.h | 0 zbar/{decoder => }/qrcode/qrdec.c | 2 +- zbar/{decoder => }/qrcode/qrdec.h | 0 zbar/{decoder => }/qrcode/qrdectxt.c | 2 +- zbar/{decoder => }/qrcode/rs.c | 0 zbar/{decoder => }/qrcode/rs.h | 0 zbar/{decoder => }/qrcode/util.c | 0 zbar/{decoder => }/qrcode/util.h | 0 17 files changed, 11 insertions(+), 10 deletions(-) rename zbar/{decoder => }/qrcode.h (100%) rename zbar/{decoder => }/qrcode/bch15_5.c (100%) rename zbar/{decoder => }/qrcode/bch15_5.h (100%) rename zbar/{decoder => }/qrcode/binarize.c (100%) rename zbar/{decoder => }/qrcode/binarize.h (100%) rename zbar/{decoder => }/qrcode/isaac.c (100%) rename zbar/{decoder => }/qrcode/isaac.h (100%) rename zbar/{decoder => }/qrcode/qrdec.c (99%) rename zbar/{decoder => }/qrcode/qrdec.h (100%) rename zbar/{decoder => }/qrcode/qrdectxt.c (99%) rename zbar/{decoder => }/qrcode/rs.c (100%) rename zbar/{decoder => }/qrcode/rs.h (100%) rename zbar/{decoder => }/qrcode/util.c (100%) rename zbar/{decoder => }/qrcode/util.h (100%) diff --git a/ChangeLog b/ChangeLog index 2aafd6b..0dceb0d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * trim deep qrcode hierarchy * fix zero length symbol data * fix QR structured append result handling * cleanup SVG debug dump (partial) diff --git a/zbar/Makefile.am.inc b/zbar/Makefile.am.inc index 0e0a464..7fa4c25 100644 --- a/zbar/Makefile.am.inc +++ b/zbar/Makefile.am.inc @@ -33,14 +33,14 @@ zbar_libzbar_la_SOURCES += zbar/decoder/pdf417.h zbar/decoder/pdf417.c \ zbar/decoder/pdf417_hash.h endif if ENABLE_QRCODE -zbar_libzbar_la_SOURCES += zbar/decoder/qrcode.h \ +zbar_libzbar_la_SOURCES += zbar/qrcode.h \ zbar/decoder/qr_finder.h zbar/decoder/qr_finder.c \ - zbar/decoder/qrcode/qrdec.c zbar/decoder/qrcode/qrdectxt.c \ - zbar/decoder/qrcode/rs.h zbar/decoder/qrcode/rs.c \ - zbar/decoder/qrcode/isaac.h zbar/decoder/qrcode/isaac.c \ - zbar/decoder/qrcode/bch15_5.h zbar/decoder/qrcode/bch15_5.c \ - zbar/decoder/qrcode/binarize.h zbar/decoder/qrcode/binarize.c \ - zbar/decoder/qrcode/util.h zbar/decoder/qrcode/util.c + zbar/qrcode/qrdec.c zbar/qrcode/qrdectxt.c \ + zbar/qrcode/rs.h zbar/qrcode/rs.c \ + zbar/qrcode/isaac.h zbar/qrcode/isaac.c \ + zbar/qrcode/bch15_5.h zbar/qrcode/bch15_5.c \ + zbar/qrcode/binarize.h zbar/qrcode/binarize.c \ + zbar/qrcode/util.h zbar/qrcode/util.c endif if WIN32 diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 175d6ae..68079a5 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -36,7 +36,7 @@ #include "error.h" #include "image.h" #ifdef ENABLE_QRCODE -# include "decoder/qrcode.h" +# include "qrcode.h" #endif #include "img_scanner.h" #include "svg.h" diff --git a/zbar/decoder/qrcode.h b/zbar/qrcode.h similarity index 100% rename from zbar/decoder/qrcode.h rename to zbar/qrcode.h diff --git a/zbar/decoder/qrcode/bch15_5.c b/zbar/qrcode/bch15_5.c similarity index 100% rename from zbar/decoder/qrcode/bch15_5.c rename to zbar/qrcode/bch15_5.c diff --git a/zbar/decoder/qrcode/bch15_5.h b/zbar/qrcode/bch15_5.h similarity index 100% rename from zbar/decoder/qrcode/bch15_5.h rename to zbar/qrcode/bch15_5.h diff --git a/zbar/decoder/qrcode/binarize.c b/zbar/qrcode/binarize.c similarity index 100% rename from zbar/decoder/qrcode/binarize.c rename to zbar/qrcode/binarize.c diff --git a/zbar/decoder/qrcode/binarize.h b/zbar/qrcode/binarize.h similarity index 100% rename from zbar/decoder/qrcode/binarize.h rename to zbar/qrcode/binarize.h diff --git a/zbar/decoder/qrcode/isaac.c b/zbar/qrcode/isaac.c similarity index 100% rename from zbar/decoder/qrcode/isaac.c rename to zbar/qrcode/isaac.c diff --git a/zbar/decoder/qrcode/isaac.h b/zbar/qrcode/isaac.h similarity index 100% rename from zbar/decoder/qrcode/isaac.h rename to zbar/qrcode/isaac.h diff --git a/zbar/decoder/qrcode/qrdec.c b/zbar/qrcode/qrdec.c similarity index 99% rename from zbar/decoder/qrcode/qrdec.c rename to zbar/qrcode/qrdec.c index f770d47..62e30ec 100644 --- a/zbar/decoder/qrcode/qrdec.c +++ b/zbar/qrcode/qrdec.c @@ -7,7 +7,7 @@ #include #include #include -#include "decoder/qrcode.h" +#include "qrcode.h" #include "qrdec.h" #include "bch15_5.h" #include "rs.h" diff --git a/zbar/decoder/qrcode/qrdec.h b/zbar/qrcode/qrdec.h similarity index 100% rename from zbar/decoder/qrcode/qrdec.h rename to zbar/qrcode/qrdec.h diff --git a/zbar/decoder/qrcode/qrdectxt.c b/zbar/qrcode/qrdectxt.c similarity index 99% rename from zbar/decoder/qrcode/qrdectxt.c rename to zbar/qrcode/qrdectxt.c index fde8ac7..a748f56 100644 --- a/zbar/decoder/qrcode/qrdectxt.c +++ b/zbar/qrcode/qrdectxt.c @@ -7,7 +7,7 @@ #include #include #include -#include "decoder/qrcode.h" +#include "qrcode.h" #include "qrdec.h" #include "util.h" #include "image.h" diff --git a/zbar/decoder/qrcode/rs.c b/zbar/qrcode/rs.c similarity index 100% rename from zbar/decoder/qrcode/rs.c rename to zbar/qrcode/rs.c diff --git a/zbar/decoder/qrcode/rs.h b/zbar/qrcode/rs.h similarity index 100% rename from zbar/decoder/qrcode/rs.h rename to zbar/qrcode/rs.h diff --git a/zbar/decoder/qrcode/util.c b/zbar/qrcode/util.c similarity index 100% rename from zbar/decoder/qrcode/util.c rename to zbar/qrcode/util.c diff --git a/zbar/decoder/qrcode/util.h b/zbar/qrcode/util.h similarity index 100% rename from zbar/decoder/qrcode/util.h rename to zbar/qrcode/util.h From 48e518917ed53cf8975fc7e629dd88162c5f37d0 Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 2 Oct 2009 12:06:19 -0400 Subject: [PATCH 141/328] tweak linear code position info --- ChangeLog | 1 + zbar/img_scanner.c | 49 ++++++++++++++++++++++++---------------------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0dceb0d..20422b1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * tweak linear code position info * trim deep qrcode hierarchy * fix zero length symbol data * fix QR structured append result handling diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 68079a5..f46122a 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -101,7 +101,7 @@ struct zbar_image_scanner_s { unsigned long time; /* scan start time */ zbar_image_t *img; /* currently scanning image *root* */ - int dx, dy; /* current scan direction */ + int dx, dy, du, umin; /* current scan direction */ zbar_symbol_set_t *syms; /* previous decode results */ /* recycled symbols in 4^n size buckets */ recycle_bucket_t recycle[RECYCLE_BUCKETS]; @@ -349,25 +349,14 @@ static void qr_handler (zbar_image_scanner_t *iscn, QR_FINDER_SUBPREC) - line->len; line->len -= u; - if(iscn->dx) { - assert(!iscn->dy); - line->pos[1] = QR_FIXED(y, 1); - if(iscn->dx > 0) - line->pos[0] = u; - else { - line->pos[0] = QR_FIXED(iscn->img->width, 0) - u - line->len; - } - } - else { - assert(iscn->dy); + line->pos[!iscn->dx] = QR_FIXED(iscn->umin, 0) + iscn->du * u; + if(!iscn->dx) line->pos[0] = QR_FIXED(x, 1); - if(iscn->dy > 0) - line->pos[1] = u; - else { - line->pos[1] = QR_FIXED(iscn->img->height, 0) - u - line->len; - } - } - if(iscn->dx < 0 || iscn->dy < 0) { + else + line->pos[1] = QR_FIXED(y, 1); + + if(iscn->du < 0) { + line->pos[!iscn->dx] -= line->len; int tmp = line->boffs; line->boffs = line->eoffs; line->eoffs = tmp; @@ -399,6 +388,16 @@ static void symbol_handler (zbar_image_scanner_t *iscn, const char *data = zbar_decoder_get_data(iscn->dcode); unsigned datalen = zbar_decoder_get_data_length(iscn->dcode); + if(TEST_CFG(iscn, ZBAR_CFG_POSITION)) { + /* tmp position fixup */ + int w = zbar_scanner_get_width(iscn->scn); + int u = iscn->umin + iscn->du * zbar_scanner_get_edge(iscn->scn, w, 0); + if(iscn->dx) + x = u; + else + y = u; + } + /* FIXME need better symbol matching */ zbar_symbol_t *sym; for(sym = iscn->syms->head; sym; sym = sym->next) @@ -632,7 +631,8 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, while(y < h) { zprintf(128, "img_x+: %04d,%04d @%p\n", x, y, p); - iscn->dx = 1; + iscn->dx = iscn->du = 1; + iscn->umin = 0; while(x < w) { if(zbar_scan_y(iscn->scn, *p)) symbol_handler(iscn, x, y); @@ -646,7 +646,8 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, break; zprintf(128, "img_x-: %04d,%04d @%p\n", x, y, p); - iscn->dx = -1; + iscn->dx = iscn->du = -1; + iscn->umin = w; while(x >= 0) { if(zbar_scan_y(iscn->scn, *p)) symbol_handler(iscn, x, y); @@ -672,7 +673,8 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, while(x < w) { zprintf(128, "img_y+: %04d,%04d @%p\n", x, y, p); - iscn->dy = 1; + iscn->dy = iscn->du = 1; + iscn->umin = 0; while(y < h) { if(zbar_scan_y(iscn->scn, *p)) symbol_handler(iscn, x, y); @@ -686,7 +688,8 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, break; zprintf(128, "img_y-: %04d,%04d @%p\n", x, y, p); - iscn->dy = -1; + iscn->dy = iscn->du = -1; + iscn->umin = h; while(y >= 0) { if(zbar_scan_y(iscn->scn, *p)) symbol_handler(iscn, x, y); From 6447c35bf1644a79ad8c8035b7f1c5852f04aebf Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 5 Oct 2009 20:13:47 -0400 Subject: [PATCH 142/328] overlay enhancements - add fps to overlay - add overlay control to processor - add windows overlay drawing --- ChangeLog | 4 ++ include/zbar.h | 6 ++ include/zbar/Window.h | 3 + zbar/image.c | 2 +- zbar/processor.c | 18 +++++- zbar/qrcode/util.c | 4 +- zbar/window.c | 31 +++++++++ zbar/window.h | 6 +- zbar/window/win.c | 144 ++++++++++++++++++++++++++++++++++++------ zbar/window/win.h | 2 + zbar/window/x.c | 47 ++++++++++++++ zbar/window/x.h | 1 + 12 files changed, 240 insertions(+), 28 deletions(-) diff --git a/ChangeLog b/ChangeLog index 20422b1..533abad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,8 @@ current: + * overlay enhancements + - add fps to overlay + - add overlay control to processor + - add windows overlay drawing * tweak linear code position info * trim deep qrcode hierarchy * fix zero length symbol data diff --git a/include/zbar.h b/include/zbar.h index 1121872..4e857cc 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -931,6 +931,12 @@ extern int zbar_window_attach(zbar_window_t *window, extern void zbar_window_set_overlay(zbar_window_t *window, int level); +/** retrieve current content level of reader overlay. + * @see zbar_window_set_overlay() + * @since 0.10 + */ +extern int zbar_window_get_overlay(const zbar_window_t *window); + /** draw a new image into the output window. */ extern int zbar_window_draw(zbar_window_t *window, zbar_image_t *image); diff --git a/include/zbar/Window.h b/include/zbar/Window.h index 8cba07e..c91a405 100644 --- a/include/zbar/Window.h +++ b/include/zbar/Window.h @@ -84,6 +84,9 @@ class Window { zbar_window_set_overlay(_window, level); } + /// retrieve current content level of reader overlay. + /// see zbar_window_get_overlay() + /// draw a new image into the output window. /// see zbar_window_draw() void draw (Image& image) diff --git a/zbar/image.c b/zbar/image.c index 3beadcd..04f681d 100644 --- a/zbar/image.c +++ b/zbar/image.c @@ -262,7 +262,7 @@ int zbar_image_write_png (const zbar_image_t *img, for(y = 1; y < img->height; y++) rows[y] = rows[y - 1] + img->width; - file = fopen(filename, "w"); + file = fopen(filename, "wb"); if(!file) goto done; diff --git a/zbar/processor.c b/zbar/processor.c index ee6ab23..4ecab13 100644 --- a/zbar/processor.c +++ b/zbar/processor.c @@ -144,11 +144,23 @@ int _zbar_processor_handle_input (zbar_processor_t *proc, break; case 'd': - /* FIXME localtime not threadsafe */ - /* FIXME need ms resolution */ - /*struct tm *t = localtime(time(NULL));*/ proc->dumping = 1; return(0); + + case '+': + case '=': + if(proc->window) { + int ovl = zbar_window_get_overlay(proc->window); + zbar_window_set_overlay(proc->window, ovl + 1); + } + break; + + case '-': + if(proc->window) { + int ovl = zbar_window_get_overlay(proc->window); + zbar_window_set_overlay(proc->window, ovl - 1); + } + break; } _zbar_mutex_lock(&proc->mutex); diff --git a/zbar/qrcode/util.c b/zbar/qrcode/util.c index b5b8f92..7297788 100644 --- a/zbar/qrcode/util.c +++ b/zbar/qrcode/util.c @@ -78,7 +78,7 @@ unsigned qr_ihypot(int _x,int _y){ return x+((1U<>1)>>shift; } -#if defined(__GNUC__) +#if defined(__GNUC__) && !defined(_WIN32) # include # if __GNUC_PREREQ(3,4) # include @@ -114,7 +114,7 @@ int qr_ilog(unsigned _v){ _v>>=m; ret|=m; ret|=!!(_v&0x2); - return ret; + return ret + !!_v; #endif } diff --git a/zbar/window.c b/zbar/window.c index 3bb32f5..62bad11 100644 --- a/zbar/window.c +++ b/zbar/window.c @@ -23,6 +23,8 @@ #include "window.h" #include "image.h" +#include /* clock_gettime */ +#include /* gettimeofday */ zbar_window_t *zbar_window_create () { @@ -99,8 +101,27 @@ static inline int window_draw_overlay (zbar_window_t *w) } } } + if(w->overlay >= 2) { /* calculate/display frame rate */ + unsigned long time; +#if _POSIX_TIMERS > 0 + struct timespec abstime; + clock_gettime(CLOCK_REALTIME, &abstime); + time = (abstime.tv_sec * 1000) + ((abstime.tv_nsec / 500000) + 1) / 2; +#else + struct timeval abstime; + gettimeofday(&abstime, NULL); + time = (abstime.tv_sec * 1000) + ((abstime.tv_usec / 500) + 1) / 2; +#endif + point_t p = { -8, -1 }; + char text[32]; + if(w->time) { + int avg = w->time_avg = (w->time_avg + time - w->time) / 2; + sprintf(text, "%d.%01d fps", 1000 / avg, (10000 / avg) % 10); + _zbar_window_draw_text(w, 3, &p, text); + } + w->time = time; } return(0); } @@ -199,6 +220,16 @@ void zbar_window_set_overlay (zbar_window_t *w, (void)window_unlock(w); } +int zbar_window_get_overlay (const zbar_window_t *w) +{ + zbar_window_t *ncw = (zbar_window_t*)w; + if(window_lock(ncw)) + return(-1); + int lvl = w->overlay; + (void)window_unlock(ncw); + return(lvl); +} + int zbar_window_resize (zbar_window_t *w, unsigned width, unsigned height) diff --git a/zbar/window.h b/zbar/window.h index 67b22b5..808b3f9 100644 --- a/zbar/window.h +++ b/zbar/window.h @@ -60,6 +60,8 @@ struct zbar_window_s { void *display; unsigned long xwin; + unsigned long time; /* last image display in milliseconds */ + unsigned long time_avg; /* average of inter-frame times */ window_state_t *state; /* platform/interface specific state */ @@ -120,11 +122,7 @@ extern int _zbar_window_flush(zbar_window_t*); extern int _zbar_window_draw_logo(zbar_window_t*); extern int _zbar_window_draw_marker(zbar_window_t*, uint32_t, const point_t*); extern int _zbar_window_draw_polygon(zbar_window_t*, uint32_t, const point_t*, int); -#if 0 -extern int _zbar_window_draw_line(zbar_window_t*, uint32_t, - const point_t*, const point_t*); extern int _zbar_window_draw_text(zbar_window_t*, uint32_t, const point_t*, const char*); -#endif #endif diff --git a/zbar/window/win.c b/zbar/window/win.c index 31c4787..46acd8f 100644 --- a/zbar/window/win.c +++ b/zbar/window/win.c @@ -24,27 +24,11 @@ #include "window.h" #include "image.h" #include "win.h" +#include int _zbar_window_vfw_init(zbar_window_t *w); int _zbar_window_dib_init(zbar_window_t *w); -int _zbar_window_draw_polygon (zbar_window_t *w, - uint32_t rgb, - const point_t *pts, - int npts) -{ - /* FIXME TBD */ - return(-1); -} - -int _zbar_window_draw_marker(zbar_window_t *w, - uint32_t rgb, - const point_t *p) -{ - /* FIXME TBD */ - return(-1); -} - int _zbar_window_resize (zbar_window_t *w) { window_state_t *win = w->state; @@ -142,11 +126,29 @@ int _zbar_window_attach (zbar_window_t *w, 1000L * GetDeviceCaps(hdc, HORZRES) / GetDeviceCaps(hdc, HORZSIZE); win->bih.biYPelsPerMeter = 1000L * GetDeviceCaps(hdc, VERTRES) / GetDeviceCaps(hdc, VERTSIZE); + + int height = -MulDiv(11, GetDeviceCaps(hdc, LOGPIXELSY), 96); + HFONT font = CreateFontW(height, 0, 0, 0, 0, 0, 0, 0, + ANSI_CHARSET, 0, 0, 0, + FF_MODERN | FIXED_PITCH, NULL); + + SelectObject(hdc, font); + DeleteObject(font); + + TEXTMETRIC tm; + GetTextMetrics(hdc, &tm); + win->font_height = tm.tmHeight; + ReleaseDC(w->display, hdc); return(_zbar_window_dib_init(w)); } +int _zbar_window_flush (zbar_window_t *w) +{ + return(0); +} + int _zbar_window_clear (zbar_window_t *w) { HDC hdc = GetDC(w->display); @@ -161,8 +163,114 @@ int _zbar_window_clear (zbar_window_t *w) return(0); } -int _zbar_window_flush (zbar_window_t *w) +static inline void win_set_rgb (HDC hdc, + uint32_t rgb) +{ + SelectObject(hdc, GetStockObject(DC_PEN)); + SetDCPenColor(hdc, RGB((rgb & 4) * 0x33, + (rgb & 2) * 0x66, + (rgb & 1) * 0xcc)); +} + +int _zbar_window_draw_polygon (zbar_window_t *w, + uint32_t rgb, + const point_t *pts, + int npts) +{ + HDC hdc = GetDC(w->display); + if(!hdc || !SaveDC(hdc)) + return(-1/*FIXME*/); + win_set_rgb(hdc, rgb); + + POINT gdipts[npts + 1]; + int i; + for(i = 0; i < npts; i++) { + gdipts[i].x = pts[i].x; + if(w->width != w->image->width) + gdipts[i].x = gdipts[i].x * w->width / w->image->width; + gdipts[i].y = pts[i].y; + if(w->height != w->image->height) + gdipts[i].y = gdipts[i].y * w->height / w->image->height; + } + gdipts[npts] = gdipts[0]; + + Polyline(hdc, gdipts, npts + 1); + + RestoreDC(hdc, -1); + ReleaseDC(w->display, hdc); + return(0); +} + +int _zbar_window_draw_marker(zbar_window_t *w, + uint32_t rgb, + const point_t *p) { + HDC hdc = GetDC(w->display); + if(!hdc || !SaveDC(hdc)) + return(-1/*FIXME*/); + win_set_rgb(hdc, rgb); + + int x = p->x; + if(w->width != w->image->width) + x = x * w->width / w->image->width; + int y = p->y; + if(w->height != w->image->height) + y = y * w->height / w->image->height; + + static const DWORD npolys[3] = { 5, 2, 2 }; + POINT polys[9] = { + { x - 2, y - 2 }, + { x - 2, y + 2 }, + { x + 2, y + 2 }, + { x + 2, y - 2 }, + { x - 2, y - 2 }, + + { x - 3, y }, + { x + 4, y }, + + { x, y - 3 }, + { x, y + 4 }, + }; + PolyPolyline(hdc, polys, npolys, 3); + + RestoreDC(hdc, -1); + ReleaseDC(w->display, hdc); + return(0); +} + +int _zbar_window_draw_text (zbar_window_t *w, + uint32_t rgb, + const point_t *p, + const char *text) +{ + HDC hdc = GetDC(w->display); + if(!hdc || !SaveDC(hdc)) + return(-1/*FIXME*/); + SetTextColor(hdc, RGB((rgb & 4) * 0x33, + (rgb & 2) * 0x66, + (rgb & 1) * 0xcc)); + SetBkMode(hdc, TRANSPARENT); + + int n = 0; + while(n < 32 && text[n] && isprint(text[n])) + n++; + + int x = p->x; + if(x >= 0) + SetTextAlign(hdc, TA_BASELINE | TA_CENTER); + else { + SetTextAlign(hdc, TA_BASELINE | TA_RIGHT); + x += w->width; + } + + int y = p->y; + if(y < 0) + y = w->height + y * w->state->font_height * 5 / 4; + + TextOut(hdc, x, y, text, n); + + RestoreDC(hdc, -1); + ReleaseDC(w->display, hdc); return(0); } diff --git a/zbar/window/win.h b/zbar/window/win.h index 076b35e..fe646e4 100644 --- a/zbar/window/win.h +++ b/zbar/window/win.h @@ -35,6 +35,8 @@ struct window_state_s { HRGN logo_zbars; HPEN logo_zpen, logo_zbpen; POINT logo_z[4]; + + int font_height; }; extern int _zbar_window_bih_init(zbar_window_t *w, diff --git a/zbar/window/x.c b/zbar/window/x.c index 9e2f05e..eda4e80 100644 --- a/zbar/window/x.c +++ b/zbar/window/x.c @@ -24,6 +24,11 @@ #include "window.h" #include "image.h" #include "x.h" +#include + +#ifndef ZBAR_OVERLAY_FONT +# define ZBAR_OVERLAY_FONT "-*-fixed-medium-r-*-*-*-120-75-75-*-*-ISO8859-1" +#endif static inline unsigned long window_alloc_color (zbar_window_t *w, Colormap cmap, @@ -131,6 +136,10 @@ int _zbar_window_attach (zbar_window_t *w, if(x->gc) XFreeGC(w->display, x->gc); assert(!x->exposed); + if(x->font) { + XFreeFont(w->display, x->font); + x->font = NULL; + } if(x->logo_zbars) { XDestroyRegion(x->logo_zbars); x->logo_zbars = NULL; @@ -167,6 +176,11 @@ int _zbar_window_attach (zbar_window_t *w, window_alloc_colors(w); window_hide_cursor(w); + /* load overlay font */ + x->font = XLoadQueryFont(w->display, ZBAR_OVERLAY_FONT); + if(x->font) + XSetFont(w->display, x->gc, x->font->fid); + /* FIXME add interface preference override */ #ifdef HAVE_X11_EXTENSIONS_XVLIB_H if(!_zbar_window_probe_xv(w)) @@ -276,6 +290,39 @@ int _zbar_window_draw_marker (zbar_window_t *w, return(0); } +int _zbar_window_draw_text (zbar_window_t *w, + uint32_t rgb, + const point_t *p, + const char *text) +{ + window_state_t *xs = w->state; + if(!xs->font) + return(-1); + + XSetForeground(w->display, xs->gc, xs->colors[rgb]); + + int n = 0; + while(n < 32 && text[n] && isprint(text[n])) + n++; + + int width = XTextWidth(xs->font, text, n); + int x = p->x; + if(x >= 0) + x -= width / 2; + else + x += w->width - width; + + int y = p->y; + int dy = xs->font->ascent + xs->font->descent; + if(y >= 0) + y -= dy / 2; + else + y = w->height + y * dy * 5 / 4; + + XDrawString(w->display, w->xwin, xs->gc, x, y, text, n); + return(0); +} + int _zbar_window_draw_logo (zbar_window_t *w) { if(!w->display) diff --git a/zbar/window/x.h b/zbar/window/x.h index b49dfaa..2075d87 100644 --- a/zbar/window/x.h +++ b/zbar/window/x.h @@ -41,6 +41,7 @@ struct window_state_s { GC gc; /* graphics context */ Region exposed; /* region to redraw */ + XFontStruct *font; /* overlay font */ /* pre-calculated logo geometries */ int logo_scale; From 1a3de731b999efa14109f15e4fcdc33049c61e96 Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 6 Oct 2009 13:53:03 -0400 Subject: [PATCH 143/328] add configure check for features.h --- ChangeLog | 1 + configure.ac | 2 +- zbar/qrcode/util.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 533abad..510a71a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * add configure check for features.h * overlay enhancements - add fps to overlay - add overlay control to processor diff --git a/configure.ac b/configure.ac index 1f5641a..a499664 100644 --- a/configure.ac +++ b/configure.ac @@ -388,7 +388,7 @@ dnl header files dnl FIXME switches for shm, mmap AC_HEADER_ASSERT -AC_CHECK_HEADERS([fcntl.h inttypes.h stdlib.h string.h unistd.h \ +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]) dnl types diff --git a/zbar/qrcode/util.c b/zbar/qrcode/util.c index 7297788..78317bb 100644 --- a/zbar/qrcode/util.c +++ b/zbar/qrcode/util.c @@ -78,7 +78,7 @@ unsigned qr_ihypot(int _x,int _y){ return x+((1U<>1)>>shift; } -#if defined(__GNUC__) && !defined(_WIN32) +#if defined(__GNUC__) && defined(HAVE_FEATURES_H) # include # if __GNUC_PREREQ(3,4) # include From 7443bda86bd9f94597127e8033fa0ada0072d5fc Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 6 Oct 2009 17:06:47 -0400 Subject: [PATCH 144/328] always use separate video thread when threads enabled (even v4l2) --- ChangeLog | 1 + zbar/processor.c | 8 ++------ zbar/processor/posix.c | 18 +++++++++++------- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index ca8e17d..2b58f27 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * always use separate video thread when threads enabled (even v4l2) * fix broken builds with --disable-pthread version 0.9: diff --git a/zbar/processor.c b/zbar/processor.c index 4ca36c8..3d81523 100644 --- a/zbar/processor.c +++ b/zbar/processor.c @@ -340,8 +340,7 @@ int zbar_processor_init (zbar_processor_t *proc, } /* spawn blocking video thread */ - int video_threaded = (proc->threaded && proc->video && - zbar_video_get_fd(proc->video) < 0); + int video_threaded = proc->threaded && proc->video; if(video_threaded && _zbar_thread_start(&proc->video_thread, proc_video_thread, proc, &proc->mutex)) { @@ -351,10 +350,7 @@ int zbar_processor_init (zbar_processor_t *proc, } /* spawn input monitor thread */ - int input_threaded = (proc->threaded && - (proc->window || - (proc->video && !video_threaded))); - + int input_threaded = proc->threaded && proc->window; if(input_threaded && _zbar_thread_start(&proc->input_thread, proc_input_thread, proc, &proc->mutex)) { diff --git a/zbar/processor/posix.c b/zbar/processor/posix.c index 1d72cd5..712e7fe 100644 --- a/zbar/processor/posix.c +++ b/zbar/processor/posix.c @@ -318,13 +318,17 @@ int _zbar_processor_cleanup (zbar_processor_t *proc) int _zbar_processor_enable (zbar_processor_t *proc) { + if(proc->threaded) + return(0); + int vid_fd = zbar_video_get_fd(proc->video); - if(vid_fd >= 0) { - if(proc->streaming) - add_poll(proc, vid_fd, proc_video_handler); - else - remove_poll(proc, vid_fd); - /* FIXME failure recovery? */ - } + if(vid_fd < 0) + return(0); + + if(proc->streaming) + add_poll(proc, vid_fd, proc_video_handler); + else + remove_poll(proc, vid_fd); + /* FIXME failure recovery? */ return(0); } From f19e74636a33bfc17c4ab69a5a661f4246f39aab Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 9 Oct 2009 00:27:36 -0400 Subject: [PATCH 145/328] bug hunt and stability improvements - fix broken processor locks - fix X connection polling, revert previous separate thread workaround - refuse to resize windows larger than screen size - fix window output scaling - preserve image aspect ratio, adjust overlay - fix window redraw - fix crash on Xv image creation failure (still need XImage fallback) - clean up zbarimg exit cases (last image window close, missing decodes) --- ChangeLog | 8 +++ TODO | 2 - zbar/processor.c | 19 ++++--- zbar/processor/lock.c | 25 +++++---- zbar/processor/posix.c | 6 +-- zbar/processor/posix.h | 1 + zbar/processor/x.c | 49 ++++++++++++++--- zbar/window.c | 118 ++++++++++++++++++++++++++++++++++------- zbar/window.h | 23 ++++++-- zbar/window/dib.c | 14 ++--- zbar/window/win.c | 107 ++++++++++++++++++------------------- zbar/window/win.h | 1 + zbar/window/x.c | 86 +++++++++++++----------------- zbar/window/ximage.c | 49 ++++++----------- zbar/window/xv.c | 9 ++-- zbarimg/zbarimg.c | 16 ++++-- 16 files changed, 330 insertions(+), 203 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7992292..4cdd5b7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,12 @@ current: + * bug hunt and stability improvements + - fix broken processor locks + - fix X connection polling, revert previous separate thread workaround + - refuse to resize windows larger than screen size + - fix window output scaling - preserve image aspect ratio, adjust overlay + - fix window redraw + - fix crash on Xv image creation failure (still need XImage fallback) + - clean up zbarimg exit cases (last image window close, missing decodes) * always use separate video thread when threads enabled (even v4l2) * add configure check for features.h * overlay enhancements diff --git a/TODO b/TODO index 0fd9662..2eaff8a 100644 --- a/TODO +++ b/TODO @@ -56,10 +56,8 @@ window: * X protocol error handling * Direct2D * API to query used interface (video, window?) (/format?) - * mode to preserve aspect ratio (default?) * simple image manipulations scale(xv?)/mirror * maintain aspect ratio - * overlay doesn't resize w/window * more overlay details * decoded result(?) * stats diff --git a/zbar/processor.c b/zbar/processor.c index 263afdc..bb53048 100644 --- a/zbar/processor.c +++ b/zbar/processor.c @@ -119,14 +119,16 @@ int _zbar_process_image (zbar_processor_t *proc, } /* display to window if enabled */ - if(proc->window && - (zbar_window_draw(proc->window, img) || - _zbar_processor_invalidate(proc))) - return(err_copy(proc, proc->window)); + int rc = 0; + if(proc->window) { + if((rc = zbar_window_draw(proc->window, img))) + err_copy(proc, proc->window); + _zbar_processor_invalidate(proc); + } if(force_fmt && img) zbar_image_destroy(img); - return(0); + return(rc); error: return(err_capture(proc, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, @@ -358,7 +360,8 @@ int zbar_processor_init (zbar_processor_t *proc, } /* spawn blocking video thread */ - int video_threaded = proc->threaded && proc->video; + int video_threaded = (proc->threaded && proc->video && + zbar_video_get_fd(proc->video) < 0); if(video_threaded && _zbar_thread_start(&proc->video_thread, proc_video_thread, proc, &proc->mutex)) { @@ -368,7 +371,9 @@ int zbar_processor_init (zbar_processor_t *proc, } /* spawn input monitor thread */ - int input_threaded = proc->threaded && proc->window; + int input_threaded = (proc->threaded && + (proc->window || + (proc->video && !video_threaded))); if(input_threaded && _zbar_thread_start(&proc->input_thread, proc_input_thread, proc, &proc->mutex)) { diff --git a/zbar/processor/lock.c b/zbar/processor/lock.c index df0fdc6..d1d80bc 100644 --- a/zbar/processor/lock.c +++ b/zbar/processor/lock.c @@ -40,8 +40,10 @@ static inline proc_waiter_t *proc_waiter_queue (zbar_processor_t *proc) { proc_waiter_t *waiter = proc->free_waiter; - if(waiter) + if(waiter) { proc->free_waiter = waiter->next; + waiter->events = 0; + } else { waiter = calloc(1, sizeof(proc_waiter_t)); _zbar_event_init(&waiter->notify); @@ -60,19 +62,24 @@ static inline proc_waiter_t *proc_waiter_queue (zbar_processor_t *proc) static inline proc_waiter_t *proc_waiter_dequeue (zbar_processor_t *proc) { - proc_waiter_t *waiter = proc->wait_next; - if(!waiter) + proc_waiter_t *prev = proc->wait_next, *waiter; + if(prev) + waiter = prev->next; + else waiter = proc->wait_head; - while(waiter && waiter->events) + while(waiter && waiter->events) { + prev = waiter; + proc->wait_next = waiter; waiter = waiter->next; + } if(waiter) { - proc->wait_next = waiter->next; - if(proc->wait_head == waiter) { + if(prev) + prev->next = waiter->next; + else proc->wait_head = waiter->next; - if(!waiter->next) - proc->wait_tail = NULL; - } + if(!waiter->next) + proc->wait_tail = prev; waiter->next = NULL; proc->lock_level = 1; diff --git a/zbar/processor/posix.c b/zbar/processor/posix.c index 712e7fe..33a4cdc 100644 --- a/zbar/processor/posix.c +++ b/zbar/processor/posix.c @@ -232,6 +232,9 @@ static inline int proc_poll_inputs (zbar_processor_t *proc, int timeout) { processor_state_t *state = proc->state; + if(state->pre_poll_handler) + state->pre_poll_handler(proc, -1); + poll_desc_t *p = &state->thr_polling; assert(p->num); int rc = poll(p->fds, p->num, timeout); @@ -318,9 +321,6 @@ int _zbar_processor_cleanup (zbar_processor_t *proc) int _zbar_processor_enable (zbar_processor_t *proc) { - if(proc->threaded) - return(0); - int vid_fd = zbar_video_get_fd(proc->video); if(vid_fd < 0) return(0); diff --git a/zbar/processor/posix.h b/zbar/processor/posix.h index 0bcafee..1ae0050 100644 --- a/zbar/processor/posix.h +++ b/zbar/processor/posix.h @@ -46,6 +46,7 @@ struct processor_state_s { poll_desc_t thr_polling; /* thread copy */ #endif int kick_fds[2]; /* poll kicker */ + poll_handler_t *pre_poll_handler; /* special case */ }; diff --git a/zbar/processor/x.c b/zbar/processor/x.c index ab61156..8bb5c67 100644 --- a/zbar/processor/x.c +++ b/zbar/processor/x.c @@ -70,6 +70,8 @@ static inline int x_handle_event (zbar_processor_t *proc) case KeyPress: { KeySym key = XLookupKeysym(&ev.xkey, 0); + if(IsModifierKey(key)) + break; if((key & 0xff00) == 0xff00) key &= 0x00ff; zprintf(16, "KeyPress(%04lx)\n", key); @@ -103,7 +105,7 @@ static inline int x_handle_event (zbar_processor_t *proc) static int x_handle_events (zbar_processor_t *proc) { int rc = 0; - while(!rc && XPending(proc->display)) + while(rc >= 0 && XPending(proc->display)) rc = x_handle_event(proc); return(rc); } @@ -111,7 +113,15 @@ static int x_handle_events (zbar_processor_t *proc) static int x_connection_handler (zbar_processor_t *proc, int i) { + _zbar_mutex_lock(&proc->mutex); + _zbar_processor_lock(proc); + _zbar_mutex_unlock(&proc->mutex); + x_handle_events(proc); + + _zbar_mutex_lock(&proc->mutex); + _zbar_processor_unlock(proc, 0); + _zbar_mutex_unlock(&proc->mutex); return(0); } @@ -119,7 +129,7 @@ static int x_internal_handler (zbar_processor_t *proc, int i) { XProcessInternalConnection(proc->display, proc->state->polling.fds[i].fd); - x_handle_events(proc); + x_connection_handler(proc, i); return(0); } @@ -149,6 +159,8 @@ int _zbar_processor_open (zbar_processor_t *proc, add_poll(proc, ConnectionNumber(proc->display), x_connection_handler); XAddConnectionWatch(proc->display, x_internal_watcher, (void*)proc); + /* must also flush X event queue before polling */ + proc->state->pre_poll_handler = x_connection_handler; int screen = DefaultScreen(proc->display); XSetWindowAttributes attr; @@ -194,6 +206,7 @@ int _zbar_processor_close (zbar_processor_t *proc) XDestroyWindow(proc->display, proc->xwin); proc->xwin = 0; } + proc->state->pre_poll_handler = NULL; remove_poll(proc, ConnectionNumber(proc->display)); XCloseDisplay(proc->display); proc->display = NULL; @@ -205,8 +218,7 @@ int _zbar_processor_invalidate (zbar_processor_t *proc) { if(!proc->display || !proc->xwin) return(0); - XClearArea(proc->display, proc->xwin, 0, 0, - proc->window->width, proc->window->height, 1); + XClearArea(proc->display, proc->xwin, 0, 0, 0, 0, 1); XFlush(proc->display); return(0); } @@ -215,10 +227,33 @@ int _zbar_processor_set_size (zbar_processor_t *proc, unsigned width, unsigned height) { - if(proc->display || !proc->xwin) { - XResizeWindow(proc->display, proc->xwin, width, height); - XFlush(proc->display); + if(!proc->display || !proc->xwin) + return(0); + + /* refuse to resize greater than (default) screen size */ + XWindowAttributes attr; + XGetWindowAttributes(proc->display, proc->xwin, &attr); + + int maxw = WidthOfScreen(attr.screen); + int maxh = HeightOfScreen(attr.screen); + int w, h; + if(width > maxw) { + h = (maxw * height + width - 1) / width; + w = maxw; + } + else { + w = width; + h = height; + } + if(h > maxh) { + w = (maxh * width + height - 1) / height; + h = maxh; } + assert(w <= maxw); + assert(h <= maxh); + + XResizeWindow(proc->display, proc->xwin, w, h); + XFlush(proc->display); return(0); } diff --git a/zbar/window.c b/zbar/window.c index 62bad11..e01077d 100644 --- a/zbar/window.c +++ b/zbar/window.c @@ -63,7 +63,10 @@ int zbar_window_attach (zbar_window_t *w, } w->src_format = 0; w->src_width = w->src_height = 0; + w->scaled_size.x = w->scaled_size.y = 0; w->dst_width = w->dst_height = 0; + w->max_width = w->max_height = 1 << 15; + w->scale_num = w->scale_den = 1; return(_zbar_window_attach(w, display, drawable)); } @@ -81,9 +84,6 @@ static void window_outline_symbol (zbar_window_t *w, static inline int window_draw_overlay (zbar_window_t *w) { - /* FIXME TBD - * _zbar_draw_line, _zbar_draw_polygon, _zbar_draw_text, etc... - */ if(!w->overlay) return(0); if(w->overlay >= 1 && w->image && w->image->syms) { @@ -95,9 +95,22 @@ static inline int window_draw_overlay (zbar_window_t *w) window_outline_symbol(w, color, sym); else { /* FIXME linear bbox broken */ + point_t org = w->scaled_offset; int i; - for(i = 0; i < sym->npts; i++) - _zbar_window_draw_marker(w, color, &sym->pts[i]); + for(i = 0; i < sym->npts; i++) { + point_t p = window_scale_pt(w, sym->pts[i]); + p.x += org.x; + p.y += org.y; + if(p.x < 3) + p.x = 3; + else if(p.x > w->width - 4) + p.x = w->width - 4; + if(p.y < 3) + p.y = 3; + else if(p.y > w->height - 4) + p.y = w->height - 4; + _zbar_window_draw_marker(w, color, p); + } } } } @@ -119,7 +132,7 @@ static inline int window_draw_overlay (zbar_window_t *w) if(w->time) { int avg = w->time_avg = (w->time_avg + time - w->time) / 2; sprintf(text, "%d.%01d fps", 1000 / avg, (10000 / avg) % 10); - _zbar_window_draw_text(w, 3, &p, text); + _zbar_window_draw_text(w, 3, p, text); } w->time = time; } @@ -130,6 +143,11 @@ inline int zbar_window_redraw (zbar_window_t *w) { if(window_lock(w)) return(-1); + if(!w->display || _zbar_window_begin(w)) { + (void)window_unlock(w); + return(-1); + } + int rc = 0; zbar_image_t *img = w->image; if(w->init && w->draw_image && img) { @@ -141,25 +159,53 @@ inline int zbar_window_redraw (zbar_window_t *w) rc = err_capture_int(w, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "no conversion from %x to supported formats", img->format); - } - if(w->src_format != img->format) w->src_format = img->format; + } - /* FIXME preserve aspect ratio (config?) */ - if(!rc && - (format_change || - (img->width != w->src_width && img->width != w->dst_width) || - (img->height != w->src_height && img->height != w->dst_height))) { + if(!rc && (format_change || !w->scaled_size.x || !w->dst_width)) { zprintf(24, "init: src=%.4s(%08x) %dx%d dst=%.4s(%08x) %dx%d\n", (char*)&w->src_format, w->src_format, w->src_width, w->src_height, (char*)&w->format, w->format, w->dst_width, w->dst_height); + if(!w->dst_width) { + w->src_width = img->width; + w->src_height = img->height; + } + + point_t size = { w->width, w->height }; + if(size.x > w->max_width) + size.x = w->max_width; + if(size.y > w->max_height) + size.y = w->max_height; + + if(size.x * w->src_height < size.y * w->src_width) { + w->scale_num = size.x; + w->scale_den = w->src_width; + } + else { + w->scale_num = size.y; + w->scale_den = w->src_height; + } + rc = w->init(w, img, format_change); - } - if(w->src_width != img->width || w->src_height != img->height) { - w->src_width = img->width; - w->src_height = img->height; + + if(!rc) { + size.x = w->src_width; + size.y = w->src_height; + w->scaled_size = size = window_scale_pt(w, size); + w->scaled_offset.x = ((int)w->width - size.x) / 2; + w->scaled_offset.y = ((int)w->height - size.y) / 2; + zprintf(24, "scale: src=%dx%d win=%dx%d by %d/%d => %dx%d @%d,%d\n", + w->src_width, w->src_height, w->width, w->height, + w->scale_num, w->scale_den, + size.x, size.y, w->scaled_offset.x, w->scaled_offset.y); + } + else { + /* unable to display this image */ + _zbar_image_refcnt(img, -1); + w->image = img = NULL; + } } if(!rc && @@ -179,14 +225,41 @@ inline int zbar_window_redraw (zbar_window_t *w) img = w->image; } - if(!rc) + if(!rc) { rc = w->draw_image(w, img); + + point_t org = w->scaled_offset; + if(org.x > 0) { + point_t p = { 0, org.y }; + point_t s = { org.x, w->scaled_size.y }; + _zbar_window_fill_rect(w, 0, p, s); + s.x = w->width - w->scaled_size.x - s.x; + if(s.x > 0) { + p.x = w->width - s.x; + _zbar_window_fill_rect(w, 0, p, s); + } + } + if(org.y > 0) { + point_t p = { 0, 0 }; + point_t s = { w->width, org.y }; + _zbar_window_fill_rect(w, 0, p, s); + s.y = w->height - w->scaled_size.y - s.y; + if(s.y > 0) { + p.y = w->height - s.y; + _zbar_window_fill_rect(w, 0, p, s); + } + } + } if(!rc) rc = window_draw_overlay(w); } else + rc = 1; + + if(rc) rc = _zbar_window_draw_logo(w); - _zbar_window_flush(w); + + _zbar_window_end(w); (void)window_unlock(w); return(rc); } @@ -198,8 +271,12 @@ int zbar_window_draw (zbar_window_t *w, return(-1); if(!w->draw_image) img = NULL; - if(img) + if(img) { _zbar_image_refcnt(img, 1); + if(img->width != w->src_width || + img->height != w->src_height) + w->dst_width = 0; + } if(w->image) _zbar_image_refcnt(w->image, -1); w->image = img; @@ -238,6 +315,7 @@ int zbar_window_resize (zbar_window_t *w, return(-1); w->width = width; w->height = height; + w->scaled_size.x = 0; _zbar_window_resize(w); return(window_unlock(w)); } diff --git a/zbar/window.h b/zbar/window.h index 808b3f9..bba52cf 100644 --- a/zbar/window.h +++ b/zbar/window.h @@ -54,6 +54,12 @@ struct zbar_window_s { unsigned dst_width; /* conversion target */ unsigned dst_height; + unsigned scale_num; /* output scaling */ + unsigned scale_den; + + point_t scaled_offset; /* output position and size */ + point_t scaled_size; + uint32_t *formats; /* supported formats (zero terminated) */ zbar_mutex_t imglock; /* lock displayed image */ @@ -112,17 +118,28 @@ static inline int _zbar_window_add_format (zbar_window_t *w, return(i); } +static inline point_t window_scale_pt (zbar_window_t *w, + point_t p) +{ + p.x = ((long)p.x * w->scale_num + w->scale_den - 1) / w->scale_den; + p.y = ((long)p.y * w->scale_num + w->scale_den - 1) / w->scale_den; + return(p); +} + /* PAL interface */ extern int _zbar_window_attach(zbar_window_t*, void*, unsigned long); extern int _zbar_window_expose(zbar_window_t*, int, int, int, int); extern int _zbar_window_resize(zbar_window_t*); extern int _zbar_window_clear(zbar_window_t*); -extern int _zbar_window_flush(zbar_window_t*); +extern int _zbar_window_begin(zbar_window_t*); +extern int _zbar_window_end(zbar_window_t*); extern int _zbar_window_draw_logo(zbar_window_t*); -extern int _zbar_window_draw_marker(zbar_window_t*, uint32_t, const point_t*); +extern int _zbar_window_draw_marker(zbar_window_t*, uint32_t, point_t); extern int _zbar_window_draw_polygon(zbar_window_t*, uint32_t, const point_t*, int); extern int _zbar_window_draw_text(zbar_window_t*, uint32_t, - const point_t*, const char*); + point_t, const char*); +extern int _zbar_window_fill_rect(zbar_window_t*, uint32_t, + point_t, const point_t); #endif diff --git a/zbar/window/dib.c b/zbar/window/dib.c index 1cf2b51..9cb5adc 100644 --- a/zbar/window/dib.c +++ b/zbar/window/dib.c @@ -46,18 +46,12 @@ static int dib_init (zbar_window_t *w, static int dib_draw (zbar_window_t *w, zbar_image_t *img) { - HDC hdc = GetDC(w->display); - if(!hdc) - return(-1); - - window_state_t *win = w->state; - StretchDIBits(hdc, 0, w->height - 1, w->width, -w->height, + StretchDIBits(w->state->hdc, + w->scaled_offset.x, w->scaled_offset.y + w->scaled_size.y - 1, + w->scaled_size.x, -w->scaled_size.y, 0, 0, w->src_width, w->src_height, - (void*)img->data, (BITMAPINFO*)&win->bih, + (void*)img->data, (BITMAPINFO*)&w->state->bih, DIB_RGB_COLORS, SRCCOPY); - - ValidateRect(w->display, NULL); - ReleaseDC(w->display, hdc); return(0); } diff --git a/zbar/window/win.c b/zbar/window/win.c index 46acd8f..f6288e9 100644 --- a/zbar/window/win.c +++ b/zbar/window/win.c @@ -144,8 +144,21 @@ int _zbar_window_attach (zbar_window_t *w, return(_zbar_window_dib_init(w)); } -int _zbar_window_flush (zbar_window_t *w) +int _zbar_window_begin (zbar_window_t *w) { + HDC hdc = w->state->hdc = GetDC(w->display); + if(!hdc || !SaveDC(hdc)) + return(-1/*FIXME*/); + return(0); +} + +int _zbar_window_end (zbar_window_t *w) +{ + HDC hdc = w->state->hdc; + w->state->hdc = NULL; + RestoreDC(hdc, -1); + ReleaseDC(w->display, hdc); + ValidateRect(w->display, NULL); return(0); } @@ -177,9 +190,7 @@ int _zbar_window_draw_polygon (zbar_window_t *w, const point_t *pts, int npts) { - HDC hdc = GetDC(w->display); - if(!hdc || !SaveDC(hdc)) - return(-1/*FIXME*/); + HDC hdc = w->state->hdc; win_set_rgb(hdc, rgb); POINT gdipts[npts + 1]; @@ -195,57 +206,41 @@ int _zbar_window_draw_polygon (zbar_window_t *w, gdipts[npts] = gdipts[0]; Polyline(hdc, gdipts, npts + 1); - - RestoreDC(hdc, -1); - ReleaseDC(w->display, hdc); return(0); } -int _zbar_window_draw_marker(zbar_window_t *w, - uint32_t rgb, - const point_t *p) +int _zbar_window_draw_marker (zbar_window_t *w, + uint32_t rgb, + point_t p) { - HDC hdc = GetDC(w->display); - if(!hdc || !SaveDC(hdc)) - return(-1/*FIXME*/); + HDC hdc = w->state->hdc; win_set_rgb(hdc, rgb); - int x = p->x; - if(w->width != w->image->width) - x = x * w->width / w->image->width; - int y = p->y; - if(w->height != w->image->height) - y = y * w->height / w->image->height; - static const DWORD npolys[3] = { 5, 2, 2 }; POINT polys[9] = { - { x - 2, y - 2 }, - { x - 2, y + 2 }, - { x + 2, y + 2 }, - { x + 2, y - 2 }, - { x - 2, y - 2 }, + { p.x - 2, p.y - 2 }, + { p.x - 2, p.y + 2 }, + { p.x + 2, p.y + 2 }, + { p.x + 2, p.y - 2 }, + { p.x - 2, p.y - 2 }, - { x - 3, y }, - { x + 4, y }, + { p.x - 3, p.y }, + { p.x + 4, p.y }, - { x, y - 3 }, - { x, y + 4 }, + { p.x, p.y - 3 }, + { p.x, p.y + 4 }, }; - PolyPolyline(hdc, polys, npolys, 3); - RestoreDC(hdc, -1); - ReleaseDC(w->display, hdc); + PolyPolyline(hdc, polys, npolys, 3); return(0); } int _zbar_window_draw_text (zbar_window_t *w, uint32_t rgb, - const point_t *p, + point_t p, const char *text) { - HDC hdc = GetDC(w->display); - if(!hdc || !SaveDC(hdc)) - return(-1/*FIXME*/); + HDC hdc = w->state->hdc; SetTextColor(hdc, RGB((rgb & 4) * 0x33, (rgb & 2) * 0x66, (rgb & 1) * 0xcc)); @@ -255,33 +250,39 @@ int _zbar_window_draw_text (zbar_window_t *w, while(n < 32 && text[n] && isprint(text[n])) n++; - int x = p->x; - if(x >= 0) + if(p.x >= 0) SetTextAlign(hdc, TA_BASELINE | TA_CENTER); else { SetTextAlign(hdc, TA_BASELINE | TA_RIGHT); - x += w->width; + p.x += w->width; } - int y = p->y; - if(y < 0) - y = w->height + y * w->state->font_height * 5 / 4; + if(p.y < 0) + p.y = w->height + p.y * w->state->font_height * 5 / 4; - TextOut(hdc, x, y, text, n); + TextOut(hdc, p.x, p.y, text, n); + return(0); +} - RestoreDC(hdc, -1); - ReleaseDC(w->display, hdc); +int _zbar_window_fill_rect (zbar_window_t *w, + uint32_t rgb, + point_t org, + point_t size) +{ + HDC hdc = w->state->hdc; + SetDCBrushColor(hdc, RGB((rgb & 4) * 0x33, + (rgb & 2) * 0x66, + (rgb & 1) * 0xcc)); + + RECT r = { org.x, org.y, org.x + size.x, org.y + size.y }; + + FillRect(hdc, &r, GetStockObject(DC_BRUSH)); return(0); } int _zbar_window_draw_logo (zbar_window_t *w) { - if(!w->display) - return(-1); - - HDC hdc = GetDC(w->display); - if(!hdc || !SaveDC(hdc)) - return(-1/*FIXME*/); + HDC hdc = w->state->hdc; window_state_t *win = w->state; @@ -299,10 +300,6 @@ int _zbar_window_draw_logo (zbar_window_t *w) ExtSelectClipRgn(hdc, win->logo_zbars, RGN_AND); SelectObject(hdc, win->logo_zbpen); Polyline(hdc, win->logo_z, 4); - - RestoreDC(hdc, -1); - ReleaseDC(w->display, hdc); - ValidateRect(w->display, NULL); return(0); } diff --git a/zbar/window/win.h b/zbar/window/win.h index fe646e4..31db432 100644 --- a/zbar/window/win.h +++ b/zbar/window/win.h @@ -26,6 +26,7 @@ #include struct window_state_s { + HDC hdc; void* hdd; BITMAPINFOHEADER bih; diff --git a/zbar/window/x.c b/zbar/window/x.c index eda4e80..ba152cb 100644 --- a/zbar/window/x.c +++ b/zbar/window/x.c @@ -209,18 +209,24 @@ int _zbar_window_expose (zbar_window_t *w, return(0); } -int _zbar_window_flush (zbar_window_t *w) +int _zbar_window_begin (zbar_window_t *w) { - if(!w->display) - return(-1); + window_state_t *xs = w->state; + if(xs->exposed) + XSetRegion(w->display, xs->gc, xs->exposed); + + return(0); +} +int _zbar_window_end (zbar_window_t *w) +{ window_state_t *x = w->state; - XFlush(w->display); XSetClipMask(w->display, x->gc, None); if(x->exposed) { XDestroyRegion(x->exposed); x->exposed = NULL; } + XFlush(w->display); return(0); } @@ -243,15 +249,13 @@ int _zbar_window_draw_polygon (zbar_window_t *w, window_state_t *xs = w->state; XSetForeground(w->display, xs->gc, xs->colors[rgb]); + point_t org = w->scaled_offset; XPoint xpts[npts + 1]; int i; for(i = 0; i < npts; i++) { - xpts[i].x = pts[i].x; - if(w->width != w->image->width) - xpts[i].x = xpts[i].x * w->width / w->image->width; - xpts[i].y = pts[i].y; - if(w->height != w->image->height) - xpts[i].y = xpts[i].y * w->height / w->image->height; + point_t p = window_scale_pt(w, pts[i]); + xpts[i].x = p.x + org.x; + xpts[i].y = p.y + org.y; } xpts[npts] = xpts[0]; @@ -262,37 +266,19 @@ int _zbar_window_draw_polygon (zbar_window_t *w, int _zbar_window_draw_marker (zbar_window_t *w, uint32_t rgb, - const point_t *p) + point_t p) { window_state_t *xs = w->state; XSetForeground(w->display, xs->gc, xs->colors[rgb]); - - int x = p->x; - if(x < 3) - x = 3; - else if(x > w->width - 4) - x = w->width - 4; - - int y = p->y; - if(y < 3) - y = 3; - else if(y > w->height - 4) - y = w->height - 4; - - if(w->width != w->image->width) - x = x * w->width / w->image->width; - if(w->height != w->image->height) - y = y * w->height / w->image->height; - - XDrawRectangle(w->display, w->xwin, xs->gc, x - 2, y - 2, 4, 4); - XDrawLine(w->display, w->xwin, xs->gc, x, y - 3, x, y + 3); - XDrawLine(w->display, w->xwin, xs->gc, x - 3, y, x + 3, y); + XDrawRectangle(w->display, w->xwin, xs->gc, p.x - 2, p.y - 2, 4, 4); + XDrawLine(w->display, w->xwin, xs->gc, p.x, p.y - 3, p.x, p.y + 3); + XDrawLine(w->display, w->xwin, xs->gc, p.x - 3, p.y, p.x + 3, p.y); return(0); } int _zbar_window_draw_text (zbar_window_t *w, uint32_t rgb, - const point_t *p, + point_t p, const char *text) { window_state_t *xs = w->state; @@ -306,32 +292,35 @@ int _zbar_window_draw_text (zbar_window_t *w, n++; int width = XTextWidth(xs->font, text, n); - int x = p->x; - if(x >= 0) - x -= width / 2; + if(p.x >= 0) + p.x -= width / 2; else - x += w->width - width; + p.x += w->width - width; - int y = p->y; int dy = xs->font->ascent + xs->font->descent; - if(y >= 0) - y -= dy / 2; + if(p.y >= 0) + p.y -= dy / 2; else - y = w->height + y * dy * 5 / 4; + p.y = w->height + p.y * dy * 5 / 4; - XDrawString(w->display, w->xwin, xs->gc, x, y, text, n); + XDrawString(w->display, w->xwin, xs->gc, p.x, p.y, text, n); return(0); } -int _zbar_window_draw_logo (zbar_window_t *w) +int _zbar_window_fill_rect (zbar_window_t *w, + uint32_t rgb, + point_t org, + point_t size) { - if(!w->display) - return(-1); + window_state_t *xs = w->state; + XSetForeground(w->display, xs->gc, xs->colors[rgb]); + XFillRectangle(w->display, w->xwin, xs->gc, org.x, org.y, size.x, size.y); + return(0); +} +int _zbar_window_draw_logo (zbar_window_t *w) +{ window_state_t *x = w->state; - if(x->exposed) - XSetRegion(w->display, x->gc, x->exposed); - int screen = DefaultScreen(w->display); /* clear to white */ @@ -349,7 +338,6 @@ int _zbar_window_draw_logo (zbar_window_t *w) XSetForeground(w->display, x->gc, x->logo_colors[0]); XDrawLines(w->display, w->xwin, x->gc, x->logo_z, 4, CoordModeOrigin); - XFlush(w->display); if(x->exposed) { XIntersectRegion(x->logo_zbars, x->exposed, x->exposed); diff --git a/zbar/window/ximage.c b/zbar/window/ximage.c index 764ab2e..6efa7d7 100644 --- a/zbar/window/ximage.c +++ b/zbar/window/ximage.c @@ -74,6 +74,9 @@ static inline int ximage_init (zbar_window_t *w, w->dst_width = img->width; w->dst_height = img->height; + /* FIXME implement some basic scaling */ + w->scale_num = w->scale_den = 1; + zprintf(3, "new XImage %.4s(%08" PRIx32 ") %dx%d" " from %.4s(%08" PRIx32 ") %dx%d\n", (char*)&w->format, w->format, ximg->width, ximg->height, @@ -91,42 +94,24 @@ static int ximage_draw (zbar_window_t *w, assert(ximg); ximg->data = (void*)img->data; - int screen = DefaultScreen(w->display); - XSetForeground(w->display, x->gc, WhitePixel(w->display, screen)); - - /* FIXME implement some basic scaling */ - unsigned height = img->height; - unsigned src_y = 0, dst_y = 0; - if(w->height < img->height) { - height = w->height; - src_y = (img->height - w->height) >> 1; - } - else if(w->height != img->height) { - dst_y = (w->height - img->height) >> 1; - /* fill border */ - XFillRectangle(w->display, w->xwin, x->gc, - 0, 0, w->width, dst_y); - XFillRectangle(w->display, w->xwin, x->gc, - 0, dst_y + img->height, w->width, dst_y); - } - - unsigned width = img->width; - unsigned src_x = 0, dst_x = 0; - if(w->width < img->width) { - width = w->width; - src_x = (img->width - w->width) >> 1; + point_t src = { 0, 0 }; + point_t dst = w->scaled_offset; + if(dst.x < 0) { + src.x = -dst.x; + dst.x = 0; } - else if(w->width != img->width) { - dst_x = (w->width - img->width) >> 1; - /* fill border */ - XFillRectangle(w->display, w->xwin, x->gc, - 0, dst_y, dst_x, img->height); - XFillRectangle(w->display, w->xwin, x->gc, - img->width + dst_x, dst_y, dst_x, img->height); + if(dst.y < 0) { + src.y = -dst.y; + dst.y = 0; } + point_t size = w->scaled_size; + if(size.x > w->width) + size.x = w->width; + if(size.y > w->height) + size.y = w->height; XPutImage(w->display, w->xwin, x->gc, ximg, - src_x, src_y, dst_x, dst_y, width, height); + src.x, src.y, dst.x, dst.y, size.x, size.y); ximg->data = NULL; return(0); } diff --git a/zbar/window/xv.c b/zbar/window/xv.c index d96e186..855ffe1 100644 --- a/zbar/window/xv.c +++ b/zbar/window/xv.c @@ -67,6 +67,7 @@ static inline int xv_init (zbar_window_t *w, } assert(x->img_port > 0); } + XvImage *xvimg = XvCreateImage(w->display, x->img_port, w->format, NULL, img->width, img->height); zprintf(3, "new XvImage %.4s(%08" PRIx32 ") %dx%d(%d)" @@ -102,11 +103,13 @@ static int xv_draw (zbar_window_t *w, XvImage *xvimg = x->img.xv; assert(xvimg); xvimg->data = (void*)img->data; - zprintf(24, "XvPutImage(%dx%d -> %dx%d)\n", - w->src_width, w->src_height, w->width, w->height); + zprintf(24, "XvPutImage(%dx%d -> %dx%d (%08lx))\n", + w->src_width, w->src_height, w->scaled_size.x, w->scaled_size.y, + img->datalen); XvPutImage(w->display, x->img_port, w->xwin, x->gc, xvimg, 0, 0, w->src_width, w->src_height, - 0, 0, w->width, w->height); + w->scaled_offset.x, w->scaled_offset.y, + w->scaled_size.x, w->scaled_size.y); xvimg->data = NULL; /* FIXME hold shm image until completion */ return(0); } diff --git a/zbarimg/zbarimg.c b/zbarimg/zbarimg.c index 9a04ec4..58800df 100644 --- a/zbarimg/zbarimg.c +++ b/zbarimg/zbarimg.c @@ -115,6 +115,9 @@ static inline int dump_error(MagickWand *wand) static int scan_image (const char *filename) { + if(exit_code == 3) + return(-1); + int found = 0; MagickWand *images = NewMagickWand(); if(!MagickReadImage(images, filename) && dump_error(images)) @@ -122,6 +125,9 @@ static int scan_image (const char *filename) unsigned seq, n = MagickGetNumberImages(images); for(seq = 0; seq < n; seq++) { + if(exit_code == 3) + return(-1); + if(!MagickSetIteratorIndex(images, seq) && dump_error(images)) return(-1); @@ -185,10 +191,8 @@ static int scan_image (const char *filename) num_images++; if(zbar_processor_is_visible(processor)) { int rc = zbar_processor_user_wait(processor, -1); - if(rc < 0 || rc == 'q' || rc == 'Q') { + if(rc < 0 || rc == 'q' || rc == 'Q') exit_code = 3; - return(-1); - } } } @@ -361,6 +365,10 @@ int main (int argc, const char *argv[]) if(scan_image(argv[i])) return(exit_code); + /* ignore quit during last image */ + if(exit_code == 3) + exit_code = 0; + if(xmllvl > 0) { xmllvl--; printf(xml_foot); @@ -388,6 +396,8 @@ int main (int argc, const char *argv[]) if(notfound) fprintf(stderr, warning_not_found); } + if(num_images && notfound && !exit_code) + exit_code = 4; zbar_processor_destroy(processor); MagickWandTerminus(); From f2874ec2775d66992e6b9aa97e1b085c11245ea7 Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 9 Oct 2009 16:11:07 -0400 Subject: [PATCH 146/328] image scanner cleanup and minor performance enhancements --- ChangeLog | 1 + zbar/img_scanner.c | 93 ++++++++++++++++++++++++---------------------- zbar/scanner.c | 17 +++++---- 3 files changed, 59 insertions(+), 52 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4cdd5b7..ad856c1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * image scanner cleanup and minor performance enhancements * bug hunt and stability improvements - fix broken processor locks - fix X connection polling, revert previous separate thread workaround diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index f46122a..57bbb46 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -101,7 +101,7 @@ struct zbar_image_scanner_s { unsigned long time; /* scan start time */ zbar_image_t *img; /* currently scanning image *root* */ - int dx, dy, du, umin; /* current scan direction */ + int dx, dy, du, umin, v; /* current scan direction */ zbar_symbol_set_t *syms; /* previous decode results */ /* recycled symbols in 4^n size buckets */ recycle_bucket_t recycle[RECYCLE_BUCKETS]; @@ -333,9 +333,7 @@ extern qr_finder_line *_zbar_decoder_get_qr_finder_line(zbar_decoder_t*); ((val) >> (prec)), \ (1000 * ((val) & ((1 << (prec)) - 1)) / (1 << (prec))) -static void qr_handler (zbar_image_scanner_t *iscn, - int x, - int y) +static inline void qr_handler (zbar_image_scanner_t *iscn) { qr_finder_line *line = _zbar_decoder_get_qr_finder_line(iscn->dcode); assert(line); @@ -349,28 +347,25 @@ static void qr_handler (zbar_image_scanner_t *iscn, QR_FINDER_SUBPREC) - line->len; line->len -= u; - line->pos[!iscn->dx] = QR_FIXED(iscn->umin, 0) + iscn->du * u; - if(!iscn->dx) - line->pos[0] = QR_FIXED(x, 1); - else - line->pos[1] = QR_FIXED(y, 1); - + u = QR_FIXED(iscn->umin, 0) + iscn->du * u; if(iscn->du < 0) { - line->pos[!iscn->dx] -= line->len; + u -= line->len; int tmp = line->boffs; line->boffs = line->eoffs; line->eoffs = tmp; } + int vert = !iscn->dx; + line->pos[vert] = u; + line->pos[!vert] = QR_FIXED(iscn->v, 1); - _zbar_qr_found_line(iscn->qr, !iscn->dx, line); + _zbar_qr_found_line(iscn->qr, vert, line); } #endif -static void symbol_handler (zbar_image_scanner_t *iscn, - int x, - int y) +static void symbol_handler (zbar_decoder_t *dcode) { - zbar_symbol_type_t type = zbar_decoder_get_type(iscn->dcode); + zbar_image_scanner_t *iscn = zbar_decoder_get_userdata(dcode); + zbar_symbol_type_t type = zbar_decoder_get_type(dcode); /* FIXME assert(type == ZBAR_PARTIAL) */ /* FIXME debug flag to save/display all PARTIALs */ if(type <= ZBAR_PARTIAL) @@ -378,24 +373,29 @@ static void symbol_handler (zbar_image_scanner_t *iscn, #ifdef ENABLE_QRCODE if(type == ZBAR_QRCODE) { - qr_handler(iscn, x, y); + qr_handler(iscn); return; } #else assert(type != ZBAR_QRCODE); #endif - const char *data = zbar_decoder_get_data(iscn->dcode); - unsigned datalen = zbar_decoder_get_data_length(iscn->dcode); + const char *data = zbar_decoder_get_data(dcode); + unsigned datalen = zbar_decoder_get_data_length(dcode); + int x = 0, y = 0; if(TEST_CFG(iscn, ZBAR_CFG_POSITION)) { /* tmp position fixup */ int w = zbar_scanner_get_width(iscn->scn); int u = iscn->umin + iscn->du * zbar_scanner_get_edge(iscn->scn, w, 0); - if(iscn->dx) + if(iscn->dx) { x = u; - else + y = iscn->v; + } + else { + x = iscn->v; y = u; + } } /* FIXME need better symbol matching */ @@ -436,6 +436,8 @@ zbar_image_scanner_t *zbar_image_scanner_create () zbar_image_scanner_destroy(iscn); return(NULL); } + zbar_decoder_set_userdata(iscn->dcode, iscn); + zbar_decoder_set_handler(iscn->dcode, symbol_handler); #ifdef ENABLE_QRCODE iscn->qr = _zbar_qr_create(); @@ -550,17 +552,13 @@ void zbar_image_scanner_enable_cache(zbar_image_scanner_t *iscn, iscn->enable_cache = (enable) ? 1 : 0; } -static inline void quiet_border (zbar_image_scanner_t *iscn, - int x, - int y) +static inline void quiet_border (zbar_image_scanner_t *iscn) { /* flush scanner pipeline */ - if(zbar_scanner_flush(iscn->scn)) - symbol_handler(iscn, x, y); - if(zbar_scanner_flush(iscn->scn)) - symbol_handler(iscn, x, y); - if(zbar_scanner_new_scan(iscn->scn)) - symbol_handler(iscn, x, y); + zbar_scanner_t *scn = iscn->scn; + zbar_scanner_flush(scn); + zbar_scanner_flush(scn); + zbar_scanner_new_scan(scn); } #define movedelta(dx, dy) do { \ @@ -615,6 +613,8 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, svg_open("debug.svg", 0, 0, w, h); svg_image("debug.png", w, h); + zbar_scanner_t *scn = iscn->scn; + int density = CFG(iscn, ZBAR_CFG_Y_DENSITY); if(density > 0) { const uint8_t *p = data; @@ -625,23 +625,24 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, if(border > h / 2) border = h / 2; movedelta(0, border); + iscn->v = y; - if(zbar_scanner_new_scan(iscn->scn)) - symbol_handler(iscn, x, y); + zbar_scanner_new_scan(scn); while(y < h) { zprintf(128, "img_x+: %04d,%04d @%p\n", x, y, p); iscn->dx = iscn->du = 1; iscn->umin = 0; while(x < w) { - if(zbar_scan_y(iscn->scn, *p)) - symbol_handler(iscn, x, y); + uint8_t d = *p; movedelta(1, 0); + zbar_scan_y(scn, d); } ASSERT_POS; - quiet_border(iscn, x, y); + quiet_border(iscn); movedelta(-1, density); + iscn->v = y; if(y >= h) break; @@ -649,14 +650,15 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, iscn->dx = iscn->du = -1; iscn->umin = w; while(x >= 0) { - if(zbar_scan_y(iscn->scn, *p)) - symbol_handler(iscn, x, y); + uint8_t d = *p; movedelta(-1, 0); + zbar_scan_y(scn, d); } ASSERT_POS; - quiet_border(iscn, x, y); + quiet_border(iscn); movedelta(1, density); + iscn->v = y; } } iscn->dx = 0; @@ -670,20 +672,22 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, if(border > w / 2) border = w / 2; movedelta(border, 0); + iscn->v = x; while(x < w) { zprintf(128, "img_y+: %04d,%04d @%p\n", x, y, p); iscn->dy = iscn->du = 1; iscn->umin = 0; while(y < h) { - if(zbar_scan_y(iscn->scn, *p)) - symbol_handler(iscn, x, y); + uint8_t d = *p; movedelta(0, 1); + zbar_scan_y(scn, d); } ASSERT_POS; - quiet_border(iscn, x, y); + quiet_border(iscn); movedelta(density, -1); + iscn->v = x; if(x >= w) break; @@ -691,14 +695,15 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, iscn->dy = iscn->du = -1; iscn->umin = h; while(y >= 0) { - if(zbar_scan_y(iscn->scn, *p)) - symbol_handler(iscn, x, y); + uint8_t d = *p; movedelta(0, -1); + zbar_scan_y(scn, d); } ASSERT_POS; - quiet_border(iscn, x, y); + quiet_border(iscn); movedelta(density, 1); + iscn->v = x; } } iscn->dy = 0; diff --git a/zbar/scanner.c b/zbar/scanner.c index c9990e1..cb0c64d 100644 --- a/zbar/scanner.c +++ b/zbar/scanner.c @@ -210,17 +210,18 @@ zbar_symbol_type_t zbar_scan_y (zbar_scanner_t *scn, { /* FIXME calc and clip to max y range... */ /* retrieve short value history */ - register int y0_1 = scn->y0[(scn->x - 1) & 3]; + register int x = scn->x; + register int y0_1 = scn->y0[(x - 1) & 3]; register int y0_0 = y0_1; - if(scn->x) { + if(x) { /* update weighted moving average */ y0_0 += ((int)((y - y0_1) * EWMA_WEIGHT)) >> ZBAR_FIXED; - scn->y0[scn->x & 3] = y0_0; + scn->y0[x & 3] = y0_0; } else y0_0 = y0_1 = scn->y0[0] = scn->y0[1] = scn->y0[2] = scn->y0[3] = y; - register int y0_2 = scn->y0[(scn->x - 2) & 3]; - register int y0_3 = scn->y0[(scn->x - 3) & 3]; + register int y0_2 = scn->y0[(x - 2) & 3]; + register int y0_3 = scn->y0[(x - 3) & 3]; /* 1st differential @ x-1 */ register int y1_1 = y0_1 - y0_2; { @@ -235,7 +236,7 @@ zbar_symbol_type_t zbar_scan_y (zbar_scanner_t *scn, register int y2_2 = y0_1 - (y0_2 * 2) + y0_3; dprintf(1, "scan: x=%d y=%d y0=%d y1=%d y2=%d", - scn->x, y, y0_1, y1_1, y2_1); + x, y, y0_1, y1_1, y2_1); zbar_symbol_type_t edge = ZBAR_NONE; /* 2nd zero-crossing is 1st local min/max - could be edge */ @@ -267,7 +268,7 @@ zbar_symbol_type_t zbar_scan_y (zbar_scanner_t *scn, else if(y2_1) /* interpolate zero crossing */ scn->cur_edge -= ((y2_1 << ZBAR_FIXED) + 1) / d; - scn->cur_edge += scn->x << ZBAR_FIXED; + scn->cur_edge += x << ZBAR_FIXED; dprintf(1, "\n"); } } @@ -275,7 +276,7 @@ zbar_symbol_type_t zbar_scan_y (zbar_scanner_t *scn, dprintf(1, "\n"); /* FIXME add fall-thru pass to decoder after heuristic "idle" period (eg, 6-8 * last width) */ - scn->x++; + scn->x = x + 1; return(edge); } From e80479ff5802188947d56668754844e89bfad9a7 Mon Sep 17 00:00:00 2001 From: tterribe Date: Mon, 12 Oct 2009 10:53:51 -0400 Subject: [PATCH 147/328] Fix ASSERT_POS to handle negative indices on 64-bit systems with 32-bit int. --- zbar/img_scanner.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 57bbb46..ff5568a 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -43,7 +43,7 @@ #if 1 # define ASSERT_POS \ - assert(p == data + x + y * w) + assert(p == data + x + y * (intptr_t)w) #else # define ASSERT_POS #endif From bc0ea8492b0e616e2a70516babe2c68a396c3b25 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 15 Oct 2009 16:21:40 -0400 Subject: [PATCH 148/328] add regression script - add zbarimg xml output for every source (even empty) - add edge detection to svg debug overlay --- ChangeLog | 3 + test/barcodetest.py | 367 ++++++++++++++++++++++++++++++++++++++++++++ zbar/img_scanner.c | 12 ++ zbar/qrcode/qrdec.c | 2 +- zbar/scanner.c | 5 + zbar/svg.c | 21 ++- zbar/svg.h | 4 +- zbarimg/zbarimg.c | 9 +- 8 files changed, 411 insertions(+), 12 deletions(-) create mode 100755 test/barcodetest.py diff --git a/ChangeLog b/ChangeLog index ad856c1..6c6dc69 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,7 @@ current: + * add regression script + - add zbarimg xml output for every source (even empty) + - add edge detection to svg debug overlay * image scanner cleanup and minor performance enhancements * bug hunt and stability improvements - fix broken processor locks diff --git a/test/barcodetest.py b/test/barcodetest.py new file mode 100755 index 0000000..6b17311 --- /dev/null +++ b/test/barcodetest.py @@ -0,0 +1,367 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import sys, re, unittest as UT, xml.etree.ElementTree as ET +from os import path, getcwd +from errno import EISDIR +from StringIO import StringIO +from subprocess import Popen, PIPE +from urllib2 import urlopen, HTTPError +from urlparse import urljoin, urlunparse +from traceback import format_exception + +debug = False + +# program to run - None means we still need to search for it +zbarimg = None +# arguments to said program +zbarimg_args = [ '-q', '--xml' ] + + +# namespace support +try: + register_namespace = ET.register_namespace +except AttributeError: + def register_namespace(prefix, uri): + ET._namespace_map[uri] = prefix + +# barcode results +BC = 'http://zbar.sourceforge.net/2008/barcode' +register_namespace('bc', BC) + +# testcase extensions +TS = 'http://zbar.sourceforge.net/2009/test-spec' +register_namespace('test', TS) + + +# printing support +def fixtag(node): + return str(node.tag).split('}', 1)[-1] + +def toxml(node): + s = StringIO() + ET.ElementTree(node).write(s) + return s.getvalue() + + +# search for a file in the distribution +def distdir_search(subdir, base, suffixes=('',)): + # start with current dir, + # then try script invocation path + rundir = path.dirname(sys.argv[0]) + search = [ '', rundir ] + + # finally, attempt to follow VPATH if present + try: + import re + with open('Makefile') as makefile: + for line in makefile: + if re.match('^VPATH\s*=', line): + vpath = line.split('=', 1)[1].strip() + if vpath and vpath != rundir: + search.append(vpath) + break + except: + pass + + # poke around for subdir + subdirs = tuple((subdir, path.join('..', subdir), '..', '')) + + for prefix in search: + for subdir in subdirs: + for suffix in suffixes: + file = path.realpath(path.join(prefix, subdir, base + suffix)) + if path.isfile(file): + return(file) + return None + + +def find_zbarimg(): + """search for zbarimg program to run. + """ + global zbarimg + # look in dist dir first + zbarimg = distdir_search('zbarimg', 'zbarimg', ('', '.exe')) + if not zbarimg: + # fall back to PATH + zbarimg = 'zbarimg' + if debug: + print('using zbarimg from PATH') + elif debug: + print('using:', zbarimg) + + +def run_zbarimg(images): + """invoke zbarimg for the specified files. + + return results as an ET.Element + """ + args = [ zbarimg ] + args.extend(zbarimg_args) + args.extend(images) + if debug: + print("running:", ' '.join(args)) + + # FIXME should be able to pipe (feed) parser straight from output + child = Popen(args, stdout = PIPE, stderr = PIPE) + (xml, err) = child.communicate() + + rc = child.returncode + if debug: + print("zbarimg returned", rc) + + # FIXME trim usage from error msg + assert rc in (0, 4), \ + 'zbarimg returned error status (%d)\n' % rc + err + + result = ET.XML(xml) + assert result.tag == ET.QName(BC, 'barcodes') + return result + + +class TestCase(UT.TestCase): + """single barcode source test. + + must have source attribute set to an ET.Element representation of a + bc:source tag before test is run. + """ + def shortDescription(self): + return self.source.get('href') + + def setUp(self): + if not zbarimg: + find_zbarimg() + + def runTest(self): + expect = self.source + assert expect is not None + assert expect.tag == ET.QName(BC, 'source') + actual = run_zbarimg((expect.get('href'),)) + + self.assertEqual(len(actual), 1) + + try: + compare_sources(expect, actual[0]) + except AssertionError: + if expect.get(str(ET.QName(TS, 'exception'))) != 'TODO': + raise + # ignore + + +class BuiltinTestCase(TestCase): + def __init__(self, methodName='runTest'): + TestCase.__init__(self, methodName) + + href = distdir_search('examples', 'barcode.png') + if not href: + href = 'http://zbar.sf.net/test/barcode.png' + + self.source = src = ET.Element(ET.QName(BC, 'source'), href=href) + sym = ET.SubElement(src, ET.QName(BC, 'symbol'), type='EAN-13') + data = ET.SubElement(sym, ET.QName(BC, 'data')) + data.text = '9876543210128' + + +def compare_maps(expect, actual, compare_func): + errors = [] + notes = [] + for key, iact in actual.iteritems(): + iexp = expect.pop(key, None) + if iexp is None: + errors.append('bonus unexpected result:\n' + toxml(iact)) + continue + + try: + compare_func(iexp, iact) + except: + errors.append(''.join(format_exception(*sys.exc_info()))) + + if iexp.get(str(ET.QName(TS, 'exception'))) == 'TODO': + notes.append('TODO unexpected result:\n' + toxml(iact)) + + for key, iexp in expect.iteritems(): + if iexp.get(str(ET.QName(TS, 'exception'))) == 'TODO': + notes.append('TODO missing expected result:\n' + toxml(iexp)) + else: + errors.append('missing expected result:\n' + toxml(iexp)) + + if len(notes) == 1: + print("(TODO)", end='', file=sys.stderr) + elif notes: + print("(%d TODO)" % len(notes), end='', file=sys.stderr) + assert not errors, '\n'.join(errors) + + +def compare_sources(expect, actual): + assert actual.tag == ET.QName(BC, 'source') + assert actual.get('href').endswith(expect.get('href')), \ + 'source href mismatch: %s != %s' % (acthref, exphref) + + # FIXME process/trim test:* contents + + def map_source(src): + if not len(src) or src[0].tag != ET.QName(BC, 'index'): + # insert artificial hierarchy + syms = src[:] + del src[:] + idx = ET.SubElement(src, ET.QName(BC, 'index'), num='0') + idx[:] = syms + exc = src.get(str(ET.QName(TS, 'exception'))) + if exc is not None: + idx.set(str(ET.QName(TS, 'exception')), exc) + return { '0': idx } + elif len(src): + assert src[0].tag != ET.QName(BC, 'symbol'), \ + 'invalid source element: ' + \ + 'expecting "index" or "symbol", got "%s"' % fixtag(src[0]) + + srcmap = { } + for idx in src: + srcmap[idx.get('num')] = idx + return srcmap + + compare_maps(map_source(expect), map_source(actual), compare_indices) + + +def compare_indices(expect, actual): + assert actual.tag == ET.QName(BC, 'index') + assert actual.get('num') == expect.get('num') + + # FIXME process/trim test:* contents + + def map_index(idx): + idxmap = { } + for sym in idx: + assert sym.tag == ET.QName(BC, 'symbol') + typ = sym.get('type') + assert typ is not None + data = sym.find(str(ET.QName(BC, 'data'))).text + idxmap[typ, data] = sym + return idxmap + + try: + compare_maps(map_index(expect), map_index(actual), compare_symbols) + except AssertionError: + if expect.get(str(ET.QName(TS, 'exception'))) != 'TODO': + raise + + +def compare_symbols(expect, actual): + pass + + +# override unittest.TestLoader to populate tests from xml description +class TestLoader: + suiteClass = UT.TestSuite + + def __init__(self): + self.cwd = urlunparse(('file', '', getcwd() + '/', '', '', '')) + if debug: + print('cwd =', self.cwd) + + def loadTestsFromModule(self, module): + return self.suiteClass([BuiltinTestCase()]) + + def loadTestsFromNames(self, names, module=None): + suites = [ self.loadTestsFromName(name, module) for name in names ] + return self.suiteClass(suites) + + def loadTestsFromURL(self, url=None, file=None): + if debug: + print('loading url:', url) + + target = None + if not file: + if not url: + return self.suiteClass([BuiltinTestCase()]) + + content = None + url = urljoin(self.cwd, url) + # FIXME grok fragment + + try: + if debug: + print('trying:', url) + file = urlopen(url) + content = file.info().get('Content-Type') + except HTTPError, e: + # possible remote directory + pass + except IOError, e: + if e.errno != EISDIR: + raise + # local directory + + if (not file or + content == 'text/html' or + (isinstance(file, HTTPError) and file.code != 200)): + # could be directory, try opening index + try: + tmp = urljoin(url + '/', 'index.xml') + if debug: + print('trying index:', tmp) + file = urlopen(tmp) + content = file.info().get('Content-Type') + url = tmp + except IOError: + raise IOError('no test index found at: %s' % url) + + if debug: + print('\tContent-Type:', content) + + if content not in ('application/xml', 'text/xml'): + # assume url is image to test, try containing index + # FIXME should be able to keep searching up + try: + target = url.rsplit('/', 1)[1] + index = urljoin(url, 'index.xml') + if debug: + print('trying index:', index) + file = urlopen(index) + content = file.info().get('Content-Type') + if debug: + print('\tContent-Type:', content) + assert content in ('application/xml', 'text/xml') + url = index + except IOError: + raise IOError('no index found for: %s' % url) + + index = ET.ElementTree(file=file).getroot() + assert index.tag == ET.QName(BC, 'barcodes') + + suite = self.suiteClass() + for src in index: + # FIXME trim any meta info + href = src.get('href') + if target and target != href: + continue + if src.tag == ET.QName(BC, 'source'): + test = TestCase() + src.set('href', urljoin(url, href)) + test.source = src + suite.addTest(test) + elif src.tag == ET.QName(TS, 'index'): + suite.addTest(self.loadTestsFromURL(urljoin(url, href))) + else: + raise AssertionError('malformed test index') # FIXME detail + + assert suite.countTestCases(), 'empty test index: %s' % url + return suite + + def loadTestsFromName(self, name=None, module=None): + return self.loadTestsFromURL(name) + + def unsupported(self, *args, **kwargs): + raise TypeError("unsupported TestLoader API") + + loadTestsFromTestCase = unsupported + getTestCaseNames = unsupported + + +if __name__ == '__main__': + if '-d' in sys.argv: + debug = True + sys.argv.remove('-d') + + UT.main(module=None, testLoader=TestLoader()) diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 57bbb46..dc0984c 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -617,6 +617,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, int density = CFG(iscn, ZBAR_CFG_Y_DENSITY); if(density > 0) { + svg_group_start("scanner", 0, 1, 1, 0, 0); const uint8_t *p = data; int x = 0, y = 0; iscn->dy = 0; @@ -631,6 +632,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, while(y < h) { zprintf(128, "img_x+: %04d,%04d @%p\n", x, y, p); + svg_path_start("vedge", 1. / 32, 0, y + 0.5); iscn->dx = iscn->du = 1; iscn->umin = 0; while(x < w) { @@ -640,6 +642,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, } ASSERT_POS; quiet_border(iscn); + svg_path_end(); movedelta(-1, density); iscn->v = y; @@ -647,6 +650,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, break; zprintf(128, "img_x-: %04d,%04d @%p\n", x, y, p); + svg_path_start("vedge", -1. / 32, w, y + 0.5); iscn->dx = iscn->du = -1; iscn->umin = w; while(x >= 0) { @@ -656,15 +660,18 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, } ASSERT_POS; quiet_border(iscn); + svg_path_end(); movedelta(1, density); iscn->v = y; } + svg_group_end(); } iscn->dx = 0; density = CFG(iscn, ZBAR_CFG_X_DENSITY); if(density > 0) { + svg_group_start("scanner", 90, 1, -1, 0, 0); const uint8_t *p = data; int x = 0, y = 0; @@ -676,6 +683,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, while(x < w) { zprintf(128, "img_y+: %04d,%04d @%p\n", x, y, p); + svg_path_start("vedge", 1. / 32, 0, x + 0.5); iscn->dy = iscn->du = 1; iscn->umin = 0; while(y < h) { @@ -685,6 +693,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, } ASSERT_POS; quiet_border(iscn); + svg_path_end(); movedelta(density, -1); iscn->v = x; @@ -692,6 +701,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, break; zprintf(128, "img_y-: %04d,%04d @%p\n", x, y, p); + svg_path_start("vedge", -1. / 32, h, x + 0.5); iscn->dy = iscn->du = -1; iscn->umin = h; while(y >= 0) { @@ -701,10 +711,12 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, } ASSERT_POS; quiet_border(iscn); + svg_path_end(); movedelta(density, 1); iscn->v = x; } + svg_group_end(); } iscn->dy = 0; iscn->img = NULL; diff --git a/zbar/qrcode/qrdec.c b/zbar/qrcode/qrdec.c index 62e30ec..3349380 100644 --- a/zbar/qrcode/qrdec.c +++ b/zbar/qrcode/qrdec.c @@ -3921,7 +3921,7 @@ int _zbar_qr_decode (qr_reader *reader, reader->finder_lines[1].nlines < 9) return(0); - svg_group_start("finder", 1. / (1 << QR_FINDER_SUBPREC), 0, 0); + svg_group_start("finder", 0, 1. / (1 << QR_FINDER_SUBPREC), 0, 0, 0); int ncenters = qr_finder_centers_locate(¢ers, &edge_pts, reader, 0, 0); diff --git a/zbar/scanner.c b/zbar/scanner.c index cb0c64d..3e932ce 100644 --- a/zbar/scanner.c +++ b/zbar/scanner.c @@ -26,6 +26,7 @@ #include /* memset */ #include +#include "svg.h" #ifdef DEBUG_SCANNER # define DEBUG_LEVEL (DEBUG_SCANNER) @@ -161,6 +162,10 @@ static inline zbar_symbol_type_t process_edge (zbar_scanner_t *scn, ((y1 > 0) ? "SPACE" : "BAR")); scn->last_edge = scn->cur_edge; +#if DEBUG_SVG > 1 + svg_path_moveto(SVG_ABS, scn->last_edge - (1 << ZBAR_FIXED) - ROUND, 0); +#endif + /* pass to decoder */ if(scn->decoder) return(zbar_decode_width(scn->decoder, scn->width)); diff --git a/zbar/svg.c b/zbar/svg.c index 2ed0b63..d0f6964 100644 --- a/zbar/svg.c +++ b/zbar/svg.c @@ -49,6 +49,7 @@ static const char svg_head[] = "#cross * { stroke: #44f }\n" ".hedge { marker: url(#hedge) }\n" ".vedge { marker: url(#vedge) }\n" + ".scanner .hedge, .scanner .vedge { stroke-width: 8 }\n" ".finder .hedge, .finder .vedge { /*stroke: #a0c;*/ stroke-width: .9 }\n" ".cluster { stroke: #a0c; stroke-width: 1; stroke-opacity: .45 }\n" ".cluster.valid { stroke: #c0a; stroke-width: 1; stroke-opacity: .666 }\n" @@ -105,18 +106,26 @@ void svg_image (const char *name, double width, double height) } void svg_group_start (const char *cls, - double scale, + double deg, + double sx, + double sy, double x, double y) { if(!svg) return; fprintf(svg, "\n"); @@ -136,10 +145,10 @@ void svg_path_start (const char *cls, fprintf(svg, "\n", filename); + } + zbar_process_image(processor, zimage); // output result data @@ -166,10 +171,6 @@ static int scan_image (const char *filename) else if(xmllvl < 0) printf("%s\n", zbar_symbol_get_data(sym)); else { - if(xmllvl < 2) { - xmllvl++; - printf("\n", filename); - } if(xmllvl < 3) { xmllvl++; printf("\n", seq); From 7b3ecab737357167f57dfee5d1fdcae2178a6564 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 15 Oct 2009 16:31:46 -0400 Subject: [PATCH 149/328] fix excessive i25 QZ checks --- ChangeLog | 1 + zbar/decoder/code128.c | 2 +- zbar/decoder/i25.c | 20 +++++++++++++++----- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6c6dc69..9dfab56 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * fix excessive i25 QZ checks * add regression script - add zbarimg xml output for every source (even empty) - add edge detection to svg debug overlay diff --git a/zbar/decoder/code128.c b/zbar/decoder/code128.c index 86d5723..8674854 100644 --- a/zbar/decoder/code128.c +++ b/zbar/decoder/code128.c @@ -452,7 +452,7 @@ zbar_symbol_type_t _zbar_decode_code128 (zbar_decoder_t *dcode) } unsigned qz = get_width(dcode, 6); if(qz && qz < (dcode->code128.s6 * 3) / 4) { - dprintf(2, " [invalid qz %d]\n"); + dprintf(2, " [invalid qz %d]\n", qz); return(0); } /* lock shared resources */ diff --git a/zbar/decoder/i25.c b/zbar/decoder/i25.c index 5fbb4e8..903eb9d 100644 --- a/zbar/decoder/i25.c +++ b/zbar/decoder/i25.c @@ -102,13 +102,21 @@ static inline signed char i25_decode_start (zbar_decoder_t *dcode) if((get_color(dcode) == ZBAR_BAR) ? enc != 4 - : i25_decode1(enc, get_width(dcode, i++), dcode25->s10)) + : (enc = i25_decode1(enc, get_width(dcode, i++), dcode25->s10))) { + dprintf(4, " i25: s=%d enc=%x [invalid]\n", dcode25->s10, enc); return(ZBAR_NONE); + } - /* check leading quiet zone - spec is 10x(?) */ + /* check leading quiet zone - spec is 10n(?) + * we require 5.25n for w=2n to 6.75n for w=3n + * (FIXME should really factor in w:n ratio) + */ unsigned quiet = get_width(dcode, i++); - if(quiet && quiet < dcode25->s10 * 3 / 4) + if(quiet && quiet < dcode25->s10 * 3 / 8) { + dprintf(3, " i25: s=%d enc=%x q=%d [invalid qz]\n", + dcode25->s10, enc, quiet); return(ZBAR_NONE); + } dcode25->direction = get_color(dcode); dcode25->element = 1; @@ -122,10 +130,12 @@ static inline signed char i25_decode_end (zbar_decoder_t *dcode) /* check trailing quiet zone */ unsigned quiet = get_width(dcode, 0); - if((quiet && quiet < dcode25->width * 3 / 4) || + if((quiet && quiet < dcode25->width * 3 / 8) || decode_e(get_width(dcode, 1), dcode25->width, 45) > 2 || - decode_e(get_width(dcode, 2), dcode25->width, 45) > 2) + decode_e(get_width(dcode, 2), dcode25->width, 45) > 2) { + dprintf(3, " s=%d q=%d [invalid qz]\n", dcode25->width, quiet); return(ZBAR_NONE); + } /* check exit condition */ unsigned char E = decode_e(get_width(dcode, 3), dcode25->width, 45); From 3ad278965e24a763da107a60b85cdfae700c77cf Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 15 Oct 2009 17:11:33 -0400 Subject: [PATCH 150/328] cleanup warnings from newer gccs --- ChangeLog | 1 + python/image.c | 7 +++++-- python/processor.c | 7 +++++-- zbar/processor/posix.c | 11 +++++++---- zbar/processor/posix.h | 8 ++++---- zbarcam/zbarcam.c | 15 +++++++++------ zbarimg/zbarimg.c | 10 +++++----- 7 files changed, 36 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9dfab56..d75f962 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * cleanup warnings from newer gcc versions * fix excessive i25 QZ checks * add regression script - add zbarimg xml output for every source (even empty) diff --git a/python/image.c b/python/image.c index 1749c79..d0d778d 100644 --- a/python/image.c +++ b/python/image.c @@ -22,6 +22,9 @@ *------------------------------------------------------------------------*/ #include "zbarmodule.h" +#ifdef HAVE_INTTYPES_H +# include +#endif static char image_doc[] = PyDoc_STR( "image object.\n" @@ -202,7 +205,7 @@ image_get_int (zbarImage *self, void *closure) { unsigned int val = -1; - switch((int)closure) { + switch((intptr_t)closure) { case 0: val = zbar_image_get_width(self->zimg); break; case 1: @@ -225,7 +228,7 @@ image_set_int (zbarImage *self, PyErr_SetString(PyExc_TypeError, "expecting an integer"); return(-1); } - switch((int)closure) { + switch((intptr_t)closure) { case 0: tmp = zbar_image_get_height(self->zimg); zbar_image_set_size(self->zimg, val, tmp); diff --git a/python/processor.c b/python/processor.c index 41745e4..06543f6 100644 --- a/python/processor.c +++ b/python/processor.c @@ -22,6 +22,9 @@ *------------------------------------------------------------------------*/ #include "zbarmodule.h" +#ifdef HAVE_INTTYPES_H +# include +#endif static char processor_doc[] = PyDoc_STR( "low level decode of measured bar/space widths.\n" @@ -83,7 +86,7 @@ processor_get_bool (zbarProcessor *self, void *closure) { int val; - switch((int)closure) { + switch((intptr_t)closure) { case 0: val = zbar_processor_is_visible(self->zproc); break; @@ -108,7 +111,7 @@ processor_set_bool (zbarProcessor *self, int rc, val = PyObject_IsTrue(value); if(val < 0) return(-1); - switch((int)closure) { + switch((intptr_t)closure) { case 0: rc = zbar_processor_set_visible(self->zproc, val); break; diff --git a/zbar/processor/posix.c b/zbar/processor/posix.c index 33a4cdc..1692783 100644 --- a/zbar/processor/posix.c +++ b/zbar/processor/posix.c @@ -67,7 +67,8 @@ void _zbar_event_trigger (zbar_event_t *event) #endif if(event->pollfd >= 0) { unsigned i = 0; /* unused */ - write(event->pollfd, &i, sizeof(unsigned)); + if(write(event->pollfd, &i, sizeof(unsigned)) < 0) + perror(""); event->pollfd = -1; } } @@ -219,13 +220,13 @@ static int proc_kick_handler (zbar_processor_t *proc, zprintf(5, "kicking %d fds\n", state->polling.num); unsigned junk[2]; - read(state->kick_fds[0], junk, 2 * sizeof(unsigned)); + int rc = read(state->kick_fds[0], junk, 2 * sizeof(unsigned)); assert(proc->threaded); _zbar_mutex_lock(&proc->mutex); proc_cache_polling(proc->state); _zbar_mutex_unlock(&proc->mutex); - return(0); + return(rc); } static inline int proc_poll_inputs (zbar_processor_t *proc, @@ -279,7 +280,9 @@ int _zbar_processor_init (zbar_processor_t *proc) if(proc->threaded) { /* FIXME check errors */ - pipe(state->kick_fds); + if(pipe(state->kick_fds)) + return(err_capture(proc, SEV_FATAL, ZBAR_ERR_SYSTEM, __func__, + "failed to open pipe")); add_poll(proc, state->kick_fds[0], proc_kick_handler); proc_cache_polling(proc->state); } diff --git a/zbar/processor/posix.h b/zbar/processor/posix.h index 1ae0050..5bc77c3 100644 --- a/zbar/processor/posix.h +++ b/zbar/processor/posix.h @@ -83,8 +83,8 @@ static inline int add_poll (zbar_processor_t *proc, if(proc->input_thread.started) { assert(state->kick_fds[1] >= 0); - write(state->kick_fds[1], &i /* unused */, sizeof(unsigned)); - /* FIXME should sync */ + if(write(state->kick_fds[1], &i /* unused */, sizeof(unsigned)) < 0) + return(-1); } else if(!proc->threaded) { state->thr_polling.num = polling->num; @@ -123,8 +123,8 @@ static inline int remove_poll (zbar_processor_t *proc, _zbar_mutex_unlock(&proc->mutex); if(proc->input_thread.started) { - write(state->kick_fds[1], &i /* unused */, sizeof(unsigned)); - /* FIXME should sync */ + if(write(state->kick_fds[1], &i /* unused */, sizeof(unsigned)) < 0) + return(-1); } else if(!proc->threaded) { state->thr_polling.num = polling->num; diff --git a/zbarcam/zbarcam.c b/zbarcam/zbarcam.c index ab6c08a..e52e188 100644 --- a/zbarcam/zbarcam.c +++ b/zbarcam/zbarcam.c @@ -70,7 +70,7 @@ static unsigned xml_len = 0; static int usage (int rc) { FILE *out = (rc) ? stderr : stdout; - fprintf(out, note_usage); + fprintf(out, "%s", note_usage); return(rc); } @@ -146,9 +146,11 @@ int main (int argc, const char *argv[]) int j; for(j = 1; argv[i][j]; j++) { if(argv[i][j] == 'S') { - if((argv[i][++j]) - ? parse_config(&argv[i][j], i, argc, "-S") - : parse_config(argv[++i], i, argc, "-S")) + if(!argv[i][++j]) { + i++; + j = 0; + } + if(parse_config(&argv[i][j], i, argc, "-S")) return(usage(1)); break; } @@ -173,7 +175,8 @@ int main (int argc, const char *argv[]) else if(!strcmp(argv[i], "--version")) return(printf(PACKAGE_VERSION "\n") <= 0); else if(!strcmp(argv[i], "--set")) { - if(parse_config(argv[++i], i, argc, "--set")) + i++; + if(parse_config(argv[i], i, argc, "--set")) return(usage(1)); } else if(!strncmp(argv[i], "--set=", 6)) { @@ -267,7 +270,7 @@ int main (int argc, const char *argv[]) zbar_processor_destroy(proc); if(format == XML) { - printf(xml_foot); + printf("%s", xml_foot); fflush(stdout); } return(0); diff --git a/zbarimg/zbarimg.c b/zbarimg/zbarimg.c index f94c8b7..b3cc886 100644 --- a/zbarimg/zbarimg.c +++ b/zbarimg/zbarimg.c @@ -220,7 +220,7 @@ int usage (int rc, fprintf(out, "%s", arg); fprintf(out, "\n\n"); } - fprintf(out, note_usage); + fprintf(out, "%s", note_usage); return(rc); } @@ -339,13 +339,13 @@ int main (int argc, const char *argv[]) else if(!strcmp(arg, "--xml")) { if(xmllvl < 1) { xmllvl++; - printf(xml_head); + printf("%s", xml_head); } } else if(!strcmp(arg, "--noxml") || !strcmp(arg, "--raw")) { if(xmllvl > 0) { xmllvl--; - printf(xml_foot); + printf("%s", xml_foot); fflush(stdout); } if(!strcmp(arg, "--raw")) @@ -372,7 +372,7 @@ int main (int argc, const char *argv[]) if(xmllvl > 0) { xmllvl--; - printf(xml_foot); + printf("%s", xml_foot); fflush(stdout); } @@ -395,7 +395,7 @@ int main (int argc, const char *argv[]) #endif fprintf(stderr, "\n"); if(notfound) - fprintf(stderr, warning_not_found); + fprintf(stderr, "%s", warning_not_found); } if(num_images && notfound && !exit_code) exit_code = 4; From e7737b7f1ce99a66e16f34190e3d7caa56b93e5c Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 15 Oct 2009 17:50:33 -0400 Subject: [PATCH 151/328] add regression tests to makefile --- ChangeLog | 1 + zbarimg/Makefile.am.inc | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/ChangeLog b/ChangeLog index d75f962..beab38b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * add regression tests to makefile * cleanup warnings from newer gcc versions * fix excessive i25 QZ checks * add regression script diff --git a/zbarimg/Makefile.am.inc b/zbarimg/Makefile.am.inc index 8ba4e3c..b674c00 100644 --- a/zbarimg/Makefile.am.inc +++ b/zbarimg/Makefile.am.inc @@ -9,3 +9,11 @@ if WIN32 zbarimg_zbarimg_SOURCES += zbarimg/zbarimg.rc zbarimg_zbarimg_LDADD += zbarimg/zbarimg-rc.o endif + +check-local: + $(PYTHON) $(srcdir)/test/barcodetest.py + +regress: + suite='$(ZBAR_TESTS)'; \ + if test "x$$suite" = "x"; then suite='http://zbar.sf.net/test'; fi ; \ + $(PYTHON) $(srcdir)/test/barcodetest.py $$suite From 45d6a82d48306bb446330e439e16eb3d28ab122d Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 20 Oct 2009 15:13:00 -0400 Subject: [PATCH 152/328] Windows updates - update installer and README for distribution of dependency libraries - fix applications to use binary output for xml and raw modes --- ChangeLog | 3 ++ Makefile.am | 1 + README | 19 +++++----- README.windows | 81 ++++++++++++++++++++++++++++++++--------- test/barcodetest.py | 18 +++++++-- zbar.nsi | 40 +++++++------------- zbar/Makefile.am.inc | 2 +- zbarcam/zbarcam.c | 8 ++++ zbarimg/Makefile.am.inc | 2 + zbarimg/zbarimg.c | 26 ++++++++++--- 10 files changed, 138 insertions(+), 62 deletions(-) diff --git a/ChangeLog b/ChangeLog index beab38b..2bf034a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,7 @@ current: + * Windows updates + - update installer and README for distribution of dependency libraries + - fix applications to use binary output for xml and raw modes * add regression tests to makefile * cleanup warnings from newer gcc versions * fix excessive i25 QZ checks diff --git a/Makefile.am b/Makefile.am index 4147e9a..0c3fdf6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -85,4 +85,5 @@ dist-nsis: html-local $(WINEXEC) lib.exe /machine:x86 /def:_nsis/lib/libzbar-0.def /out:_nsis/lib/libzbar-0.lib cd _nsis && \ makensis -NOCD -V2 -DVERSION=$(VERSION) $(abs_srcdir)/zbar.nsi + @ls -l _nsis/zbar-$(VERSION)-setup.exe endif diff --git a/README b/README index d0c35bf..933e4a0 100644 --- a/README +++ b/README @@ -1,15 +1,16 @@ ZBAR BAR CODE READER ==================== -ZBar Bar Code Reader is a library for scanning and decoding bar codes -from various sources such as video streams, image files or raw intensity -sensors. It supports EAN/UPC, Code 128, Code 39 and Interleaved 2 of 5. -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. - -Check the zbar home page for the latest release, mailing lists, etc. +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 +developers, language bindings are included for C, C++, Python and Perl +as well as GUI widgets for Qt, GTK and PyGTK. + +Check the ZBar home page for the latest release, mailing lists, etc. http://zbar.sourceforge.net/ License information can be found in 'COPYING'. diff --git a/README.windows b/README.windows index a4efd26..e7c547b 100644 --- a/README.windows +++ b/README.windows @@ -1,34 +1,79 @@ ZBAR BAR CODE READER ==================== -The ZBar Bar Code Reader is a library for scanning and decoding bar -codes from various sources such as video streams, image files or raw -intensity sensors. It supports EAN/UPC, Code 128, Code 39 and -Interleaved 2 of 5. 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. The flexible, layered architecture -features a fast, streaming interface with a minimal memory footprint. +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 developers, language +bindings are included for C, C++, Python and Perl as well as GUI widgets for +Qt, GTK and PyGTK. Check the ZBar home page for the latest release, mailing lists, etc. http://zbar.sourceforge.net/ License information can be found in 'COPYING'. +This Windows distribution also includes pre-compiled binaries of several +supporting libraries, for which the copyright, license and source code +locations are as follows: + + * The GNU libiconv character set conversion library + Copyright (C) 1999-2008 Free Software Foundation, Inc. + This distribution includes GNU libiconv version 1.13.1, licensed under + the LGPL version 2. The source code is available from + http://www.gnu.org/software/libiconv + + * The ImageMagick software imaging library + Copyright 1999-2009 ImageMagick Studio LLC + This distribution includes ImageMagick version 6.5.4-10, licensed under + its own terms. The source code is available from + http://imagemagick.org + + * The libxml2 XML C parser and toolkit + Copyright (C) 1998-2003 Daniel Veillard. + This distribution includes libxml2 version 2.7.3, provided under the MIT + license. The source code is available from + http://xmlsoft.org + + * IJG JPEG library + Copyright (C) 1991-2009, Thomas G. Lane, Guido Vollbeding. + This distribution includes jpeg version 7, licensed under its own + terms. The source code is available from + http://www.ijg.org + + * libtiff, a library for reading and writing TIFF + Copyright (c) 1988-1997 Sam Leffler + Copyright (c) 1991-1997 Silicon Graphics, Inc. + This distribution includes libtiff version 3.9.1, which is provided + "as-is". The source code is available from + http://www.remotesensing.org/libtiff + + * libpng, the official PNG reference library + Copyright (c) 1998-2009 Glenn Randers-Pehrson + This distribution includes libpng version 1.2.40, licensed under its own + terms. The source code is available from + http://www.libpng.org/pub/png/libpng.html + + * The zlib general purpose compression library + Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler. + This distribution includes zlib version 1.2.3, licensed under its own + terms. The source code is available from + http://zlib.net + + * The bzip2 compression library + Copyright (C) 1996-2007 Julian Seward. + This distribution includes bzip2 version 1.0.5, licensed under its own + terms. The source code is available from + http://bzip.org + INSTALLING ========== -The zbarimg program uses ImageMagick to read image files. You will -need at least ImageMagick version 6.2.6 if you want to scan image -files. ImageMagick may be obtained from - http://www.imagemagick.org/ - -Download and install the current Windows binary release, making sure -that you select the *Dynamic* (DLL) version, eg: - ImageMagick-x.y.z-w-Q16-windows-dll.exe - -You will also want the "Update executable search path" box checked -during installation. +ZBar for Windows is distributed with an installer, simply run the installer +and follow the prompts to install the software. RUNNING diff --git a/test/barcodetest.py b/test/barcodetest.py index 6b17311..798a166 100755 --- a/test/barcodetest.py +++ b/test/barcodetest.py @@ -4,7 +4,7 @@ import sys, re, unittest as UT, xml.etree.ElementTree as ET from os import path, getcwd -from errno import EISDIR +from errno import EISDIR, EINVAL, EACCES from StringIO import StringIO from subprocess import Popen, PIPE from urllib2 import urlopen, HTTPError @@ -44,6 +44,17 @@ def toxml(node): ET.ElementTree(node).write(s) return s.getvalue() +def hexdump(data): + print(data) + for i, c in enumerate(data): + if i & 0x7 == 0: + print('[%04x]' % i, end='') + print(' %04x' % ord(c), end='') + if i & 0x7 == 0x7: + print() + if len(c) & 0x7 != 0x7: + print('\n') + # search for a file in the distribution def distdir_search(subdir, base, suffixes=('',)): @@ -238,6 +249,7 @@ def map_index(idx): assert typ is not None data = sym.find(str(ET.QName(BC, 'data'))).text idxmap[typ, data] = sym + return idxmap try: @@ -289,9 +301,9 @@ def loadTestsFromURL(self, url=None, file=None): # possible remote directory pass except IOError, e: - if e.errno != EISDIR: + if e.errno not in (EISDIR, EINVAL, EACCES): raise - # local directory + # could be local directory if (not file or content == 'text/html' or diff --git a/zbar.nsi b/zbar.nsi index 116dd95..fbe11c2 100644 --- a/zbar.nsi +++ b/zbar.nsi @@ -24,6 +24,9 @@ !ifndef VERSION !define VERSION "test" !endif +!ifndef PREFIX + !define PREFIX "\usr\mingw32\usr" +!endif !define ZBAR_KEY "Software\ZBar" !define UNINSTALL_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\ZBar" @@ -43,7 +46,7 @@ InstallDirRegKey HKLM ${ZBAR_KEY} "InstallDir" Icon ${NSISDIR}\Contrib\Graphics\Icons\orange-install.ico UninstallIcon ${NSISDIR}\Contrib\Graphics\Icons\orange-uninstall.ico -# do we need admin to install DLL and uninstall info? +# do we need admin to install uninstall info? #RequestExecutionLevel admin @@ -54,30 +57,6 @@ UninstallIcon ${NSISDIR}\Contrib\Graphics\Icons\orange-uninstall.ico Name "ZBar" Caption "ZBar ${VERSION} Setup" -Var MAGICKDIR - -# Check that ImageMagick is installed -Function CheckMagick - SearchPath $MAGICKDIR "CORE_RL_wand_.dll" - IfErrors 0 goinstall - MessageBox MB_OKCANCEL|MB_ICONSTOP \ - "ImageMagick was not found in your PATH!$\n\ - $\n\ - The zbarimg program will not be able to scan image files $\n\ - unless you install ImageMagick (http://www.imagemagick.org)$\n\ - $\n\ - See the README for more details$\n\ - $\n\ - Press OK to continue anyway...$\n\ - Press Cancel to abort the installation..." \ - /SD IDOK \ - IDOK goinstall - - ExecShell "open" "http://www.imagemagick.org/" - Quit -goinstall: -FunctionEnd - !define MEMENTO_REGISTRY_ROOT HKLM !define MEMENTO_REGISTRY_KEY ${UNINSTALL_KEY} @@ -103,7 +82,6 @@ FunctionEnd !insertmacro MUI_PAGE_WELCOME -!define MUI_PAGE_CUSTOMFUNCTION_SHOW CheckMagick !insertmacro MUI_PAGE_LICENSE "share\doc\zbar\LICENSE" !define MUI_COMPONENTSPAGE_SMALLDESC @@ -160,6 +138,16 @@ Section "ZBar Core Files (required)" SecCore File bin\zbarimg.exe File bin\zbarcam.exe + # dependencies + File ${PREFIX}\bin\zlib1.dll + File ${PREFIX}\bin\libjpeg-7.dll + File ${PREFIX}\bin\libpng12-0.dll + File ${PREFIX}\bin\libtiff-3.dll + File ${PREFIX}\bin\libxml2-2.dll + File ${PREFIX}\bin\libiconv-2.dll + File ${PREFIX}\bin\libMagickCore-2.dll + File ${PREFIX}\bin\libMagickWand-2.dll + FileOpen $0 zbarcam.bat w FileWrite $0 "@set PATH=%PATH%;$INSTDIR\bin$\n" FileWrite $0 "@echo This is the zbarcam output window.$\n" diff --git a/zbar/Makefile.am.inc b/zbar/Makefile.am.inc index 7fa4c25..8d38484 100644 --- a/zbar/Makefile.am.inc +++ b/zbar/Makefile.am.inc @@ -35,7 +35,7 @@ endif if ENABLE_QRCODE zbar_libzbar_la_SOURCES += zbar/qrcode.h \ zbar/decoder/qr_finder.h zbar/decoder/qr_finder.c \ - zbar/qrcode/qrdec.c zbar/qrcode/qrdectxt.c \ + zbar/qrcode/qrdec.h zbar/qrcode/qrdec.c zbar/qrcode/qrdectxt.c \ zbar/qrcode/rs.h zbar/qrcode/rs.c \ zbar/qrcode/isaac.h zbar/qrcode/isaac.c \ zbar/qrcode/bch15_5.h zbar/qrcode/bch15_5.c \ diff --git a/zbarcam/zbarcam.c b/zbarcam/zbarcam.c index e52e188..56536b3 100644 --- a/zbarcam/zbarcam.c +++ b/zbarcam/zbarcam.c @@ -25,6 +25,10 @@ #include #include #include +#ifdef _WIN32 +# include +# include +#endif #include #include @@ -240,6 +244,10 @@ int main (int argc, const char *argv[]) return(zbar_processor_error_spew(proc, 0)); if(format == XML) { +#ifdef _WIN32 + fflush(stdout); + _setmode(_fileno(stdout), _O_BINARY); +#endif printf(xml_head, video_device); fflush(stdout); } diff --git a/zbarimg/Makefile.am.inc b/zbarimg/Makefile.am.inc index b674c00..de66019 100644 --- a/zbarimg/Makefile.am.inc +++ b/zbarimg/Makefile.am.inc @@ -10,6 +10,8 @@ zbarimg_zbarimg_SOURCES += zbarimg/zbarimg.rc zbarimg_zbarimg_LDADD += zbarimg/zbarimg-rc.o endif +EXTRA_DIST += test/barcodetest.py + check-local: $(PYTHON) $(srcdir)/test/barcodetest.py diff --git a/zbarimg/zbarimg.c b/zbarimg/zbarimg.c index b3cc886..5d2db34 100644 --- a/zbarimg/zbarimg.c +++ b/zbarimg/zbarimg.c @@ -31,6 +31,10 @@ #ifdef HAVE_SYS_TIMES_H # include #endif +#ifdef _WIN32 +# include +# include +#endif #include #include @@ -338,18 +342,30 @@ int main (int argc, const char *argv[]) zbar_processor_set_visible(processor, 0); else if(!strcmp(arg, "--xml")) { if(xmllvl < 1) { - xmllvl++; + xmllvl = 1; +#ifdef _WIN32 + fflush(stdout); + _setmode(_fileno(stdout), _O_BINARY); +#endif printf("%s", xml_head); } } else if(!strcmp(arg, "--noxml") || !strcmp(arg, "--raw")) { if(xmllvl > 0) { - xmllvl--; + xmllvl = 0; printf("%s", xml_foot); fflush(stdout); +#ifdef _WIN32 + _setmode(_fileno(stdout), _O_TEXT); +#endif } - if(!strcmp(arg, "--raw")) + if(!strcmp(arg, "--raw")) { xmllvl = -1; +#ifdef _WIN32 + fflush(stdout); + _setmode(_fileno(stdout), _O_BINARY); +#endif + } } else if(!strcmp(arg, "--set")) { if(parse_config(argv[++i], "--set")) @@ -371,7 +387,7 @@ int main (int argc, const char *argv[]) exit_code = 0; if(xmllvl > 0) { - xmllvl--; + xmllvl = -1; printf("%s", xml_foot); fflush(stdout); } @@ -379,7 +395,7 @@ int main (int argc, const char *argv[]) if(xmlbuf) free(xmlbuf); - if(num_images && !quiet) { + if(num_images && !quiet && xmllvl <= 0) { fprintf(stderr, "scanned %d barcode symbols from %d images", num_symbols, num_images); #ifdef HAVE_SYS_TIMES_H From 55795339551e8deb47714df9bcefd07d39c0a9eb Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 21 Oct 2009 10:34:43 -0400 Subject: [PATCH 153/328] add result query interfaces to image scanner and processor - move result filtering into image scanner (from user) - abort output blockers when window closed --- ChangeLog | 3 +++ include/zbar.h | 25 +++++++++++++++++-- include/zbar/ImageScanner.h | 10 ++++++++ include/zbar/Processor.h | 7 ++++++ perl/ZBar.xs | 15 ++++++++++++ python/imagescanner.c | 14 +++++++++++ python/processor.c | 10 ++++++++ zbar/img_scanner.c | 44 +++++++++++++++++++++++++++------- zbar/img_scanner.h | 4 ++-- zbar/processor.c | 48 ++++++++++++++++++++++++++++++------- zbar/processor.h | 4 ++++ zbar/processor/lock.c | 12 ++++++---- zbar/qrcode/qrdectxt.c | 3 +-- zbar/symbol.c | 15 ++++++++---- zbar/symbol.h | 3 ++- 15 files changed, 183 insertions(+), 34 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2bf034a..ae5bb74 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,7 @@ current: + * add result query interfaces to image scanner and processor + - move result filtering into image scanner (from user) + - abort output blockers when window closed * Windows updates - update installer and README for distribution of dependency libraries - fix applications to use binary output for xml and raw modes diff --git a/include/zbar.h b/include/zbar.h index 4e857cc..0ab1d62 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -221,7 +221,7 @@ typedef struct zbar_symbol_set_s zbar_symbol_set_t; * destroyed or reused. * @since 0.9 */ -extern void zbar_symbol_ref(zbar_symbol_t *symbol, +extern void zbar_symbol_ref(const zbar_symbol_t *symbol, int refs); /** retrieve type of decoded symbol. @@ -340,7 +340,7 @@ extern char *zbar_symbol_xml(const zbar_symbol_t *symbol, * the object any longer once references have been released. * @since 0.10 */ -extern void zbar_symbol_set_ref(zbar_symbol_set_t *symbols, +extern void zbar_symbol_set_ref(const zbar_symbol_set_t *symbols, int refs); /** retrieve set size. @@ -713,6 +713,16 @@ extern int zbar_processor_set_visible(zbar_processor_t *processor, extern int zbar_processor_set_active(zbar_processor_t *processor, int active); +/** retrieve decode results for last scanned image/frame. + * @returns the symbol set result container or NULL if no results are + * available + * @note the returned symbol set has its reference count incremented; + * ensure that the count is decremented after use + * @since 0.10 + */ +extern const zbar_symbol_set_t* +zbar_processor_get_results(const zbar_processor_t *processor); + /** wait for input to the display window from the user * (via mouse or keyboard). * @returns >0 when input is received, 0 if timeout ms expired @@ -1065,6 +1075,17 @@ extern void zbar_image_scanner_enable_cache(zbar_image_scanner_t *scanner, extern void zbar_image_scanner_recycle_image(zbar_image_scanner_t *scanner, zbar_image_t *image); +/** retrieve decode results for last scanned image. + * @returns the symbol set result container or NULL if no results are + * available + * @note the symbol set does not have its reference count adjusted; + * ensure that the count is incremented if the results may be kept + * after the next image is scanned + * @since 0.10 + */ +extern const zbar_symbol_set_t* +zbar_image_scanner_get_results(const zbar_image_scanner_t *scanner); + /** scan for symbols in provided image. The image format must be * "Y800" or "GRAY". * @returns >0 if symbols were successfully decoded from the image, diff --git a/include/zbar/ImageScanner.h b/include/zbar/ImageScanner.h index 2e7ebf4..bda8433 100644 --- a/include/zbar/ImageScanner.h +++ b/include/zbar/ImageScanner.h @@ -91,11 +91,21 @@ class ImageScanner { zbar_image_scanner_enable_cache(_scanner, enable); } + /// remove previous results from scanner and image. + /// @see zbar_image_scanner_recycle_image() + /// @since 0.10 void recycle_image (Image &image) { zbar_image_scanner_recycle_image(_scanner, image); } + /// retrieve decode results for last scanned image. + /// @see zbar_image_scanner_get_results() + /// @since 0.10 + const SymbolSet get_results () const { + return(SymbolSet(zbar_image_scanner_get_results(_scanner))); + } + /// scan for symbols in provided image. /// see zbar_scan_image() int scan (Image& image) diff --git a/include/zbar/Processor.h b/include/zbar/Processor.h index d89f9c7..51b0e1c 100644 --- a/include/zbar/Processor.h +++ b/include/zbar/Processor.h @@ -127,6 +127,13 @@ class Processor { throw_exception(_processor); } + /// retrieve decode results for last scanned image. + /// @see zbar_processor_get_results() + /// @since 0.10 + const SymbolSet get_results () const { + return(SymbolSet(zbar_processor_get_results(_processor))); + } + /// wait for input to the display window from the user. /// see zbar_processor_user_wait() int user_wait (int timeout = FOREVER) diff --git a/perl/ZBar.xs b/perl/ZBar.xs index 208a799..c23de52 100644 --- a/perl/ZBar.xs +++ b/perl/ZBar.xs @@ -537,6 +537,14 @@ zbar_processor_set_active(processor, active=1) check_error(zbar_processor_set_active(processor, active), processor); +SV * +get_results(processor) + Barcode::ZBar::Processor processor + PPCODE: + zbar_symbol_set_t *syms = zbar_processor_get_results(processor); + PUSH_SYMS(zbar_symbol_set_first_symbol(syms)); + zbar_symbol_set_ref(syms, -1); + int zbar_processor_user_wait(processor, timeout=-1) Barcode::ZBar::Processor processor @@ -620,6 +628,13 @@ zbar_image_scanner_recycle_image(scanner, image) Barcode::ZBar::ImageScanner scanner Barcode::ZBar::Image image +SV * +get_results(scanner) + Barcode::ZBar::ImageScanner scanner + PPCODE: + zbar_symbol_set_t *syms = zbar_image_scanner_get_results(scanner); + PUSH_SYMS(zbar_symbol_set_first_symbol(syms)); + int scan_image(scanner, image) Barcode::ZBar::ImageScanner scanner diff --git a/python/imagescanner.c b/python/imagescanner.c index 2f0f995..e7f7f09 100644 --- a/python/imagescanner.c +++ b/python/imagescanner.c @@ -57,6 +57,19 @@ imagescanner_dealloc (zbarImageScanner *self) ((PyObject*)self)->ob_type->tp_free((PyObject*)self); } +static zbarSymbolSet* +imagescanner_get_results (zbarImageScanner *self, + void *closure) +{ + const zbar_symbol_set_t *zsyms = + zbar_image_scanner_get_results(self->zscn); + return(zbarSymbolSet_FromSymbolSet(zsyms)); +} + +static PyGetSetDef imagescanner_getset[] = { + { "results", (getter)imagescanner_get_results, }, +}; + static PyObject* imagescanner_set_config (zbarImageScanner *self, PyObject *args, @@ -169,5 +182,6 @@ PyTypeObject zbarImageScanner_Type = { .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .tp_new = (newfunc)imagescanner_new, .tp_dealloc = (destructor)imagescanner_dealloc, + .tp_getset = imagescanner_getset, .tp_methods = imagescanner_methods, }; diff --git a/python/processor.c b/python/processor.c index 06543f6..c42d918 100644 --- a/python/processor.c +++ b/python/processor.c @@ -129,11 +129,21 @@ processor_set_bool (zbarProcessor *self, return(0); } +static zbarSymbolSet* +processor_get_results (zbarProcessor *self, + void *closure) +{ + const zbar_symbol_set_t *zsyms = + zbar_processor_get_results(self->zproc); + return(zbarSymbolSet_FromSymbolSet(zsyms)); +} + static PyGetSetDef processor_getset[] = { { "visible", (getter)processor_get_bool, (setter)processor_set_bool, NULL, (void*)0 }, { "active", NULL, (setter)processor_set_bool, NULL, (void*)1 }, + { "results", (getter)processor_get_results, }, { NULL, }, }; diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index df5d471..bf80772 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -176,7 +176,7 @@ static inline int recycle_syms (zbar_image_scanner_t *iscn, return(1); _zbar_image_scanner_recycle_syms(iscn, syms->head); - syms->head = NULL; + syms->head = syms->tail = NULL; syms->nsyms = 0; return(0); } @@ -291,8 +291,8 @@ static inline zbar_symbol_t *cache_lookup (zbar_image_scanner_t *iscn, return(*entry); } -inline void _zbar_image_scanner_cache_sym (zbar_image_scanner_t *iscn, - zbar_symbol_t *sym) +static inline void cache_sym (zbar_image_scanner_t *iscn, + zbar_symbol_t *sym) { if(iscn->enable_cache) { zbar_symbol_t *entry = cache_lookup(iscn, sym); @@ -325,6 +325,29 @@ inline void _zbar_image_scanner_cache_sym (zbar_image_scanner_t *iscn, sym->cache_count = 0; } +void _zbar_image_scanner_add_sym(zbar_image_scanner_t *iscn, + zbar_symbol_t *sym) +{ + cache_sym(iscn, sym); + + zbar_symbol_set_t *syms = iscn->syms; + if(sym->cache_count || !syms->tail) { + sym->next = syms->head; + syms->head = sym; + } + else { + sym->next = syms->tail->next; + syms->tail->next = sym; + } + + if(!sym->cache_count) + syms->nsyms++; + else if(!syms->tail) + syms->tail = sym; + + _zbar_symbol_refcnt(sym, 1); +} + #ifdef ENABLE_QRCODE extern qr_finder_line *_zbar_decoder_get_qr_finder_line(zbar_decoder_t*); @@ -420,9 +443,7 @@ static void symbol_handler (zbar_decoder_t *dcode) if(TEST_CFG(iscn, ZBAR_CFG_POSITION)) sym_add_point(sym, x, y); - /* add to current result set */ - _zbar_symbol_set_add(iscn->syms, sym); - _zbar_image_scanner_cache_sym(iscn, sym); + _zbar_image_scanner_add_sym(iscn, sym); } zbar_image_scanner_t *zbar_image_scanner_create () @@ -541,8 +562,8 @@ int zbar_image_scanner_set_config (zbar_image_scanner_t *iscn, return(0); } -void zbar_image_scanner_enable_cache(zbar_image_scanner_t *iscn, - int enable) +void zbar_image_scanner_enable_cache (zbar_image_scanner_t *iscn, + int enable) { if(iscn->cache) { /* recycle all cached syms */ @@ -552,6 +573,12 @@ void zbar_image_scanner_enable_cache(zbar_image_scanner_t *iscn, iscn->enable_cache = (enable) ? 1 : 0; } +const zbar_symbol_set_t * +zbar_image_scanner_get_results (const zbar_image_scanner_t *iscn) +{ + return(iscn->syms); +} + static inline void quiet_border (zbar_image_scanner_t *iscn) { /* flush scanner pipeline */ @@ -743,7 +770,6 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, } } - /* FIXME option to only report count == 0 */ if(syms->nsyms && iscn->handler) iscn->handler(img, iscn->userdata); diff --git a/zbar/img_scanner.h b/zbar/img_scanner.h index a1fc24a..8138b1b 100644 --- a/zbar/img_scanner.h +++ b/zbar/img_scanner.h @@ -30,8 +30,8 @@ extern zbar_symbol_t *_zbar_image_scanner_alloc_sym(zbar_image_scanner_t*, zbar_symbol_type_t, int); -extern void _zbar_image_scanner_cache_sym(zbar_image_scanner_t*, - zbar_symbol_t*); +extern void _zbar_image_scanner_add_sym(zbar_image_scanner_t*, + zbar_symbol_t*); extern void _zbar_image_scanner_recycle_syms(zbar_image_scanner_t*, zbar_symbol_t*); diff --git a/zbar/processor.c b/zbar/processor.c index bb53048..c64cca3 100644 --- a/zbar/processor.c +++ b/zbar/processor.c @@ -73,6 +73,10 @@ int _zbar_process_image (zbar_processor_t *proc, if(!tmp) goto error; + if(proc->syms) { + zbar_symbol_set_ref(proc->syms, -1); + proc->syms = NULL; + } zbar_image_scanner_recycle_image(proc->scanner, img); int nsyms = zbar_scan_image(proc->scanner, tmp); _zbar_image_swap_symbols(img, tmp); @@ -82,6 +86,10 @@ int _zbar_process_image (zbar_processor_t *proc, if(nsyms < 0) goto error; + proc->syms = zbar_image_scanner_get_results(proc->scanner); + if(proc->syms) + zbar_symbol_set_ref(proc->syms, 1); + if(_zbar_verbosity >= 8) { const zbar_symbol_t *sym = zbar_image_first_symbol(img); while(sym) { @@ -138,8 +146,10 @@ int _zbar_process_image (zbar_processor_t *proc, int _zbar_processor_handle_input (zbar_processor_t *proc, int input) { + int event = EVENT_INPUT; switch(input) { case -1: + event |= EVENT_CANCELED; _zbar_processor_set_visible(proc, 0); err_capture(proc, SEV_WARNING, ZBAR_ERR_CLOSED, __func__, "user closed display window"); @@ -167,7 +177,10 @@ int _zbar_processor_handle_input (zbar_processor_t *proc, _zbar_mutex_lock(&proc->mutex); proc->input = input; - _zbar_processor_notify(proc, EVENT_INPUT); + if(input == -1 && proc->visible && proc->streaming) + /* also cancel outstanding output waiters */ + event |= EVENT_OUTPUT; + _zbar_processor_notify(proc, event); _zbar_mutex_unlock(&proc->mutex); return(input); } @@ -442,9 +455,10 @@ void zbar_processor_set_userdata (zbar_processor_t *proc, void *zbar_processor_get_userdata (const zbar_processor_t *proc) { - _zbar_mutex_lock(&((zbar_processor_t*)proc)->mutex); + zbar_processor_t *ncproc = (zbar_processor_t*)proc; + _zbar_mutex_lock(&ncproc->mutex); void *userdata = (void*)proc->userdata; - _zbar_mutex_unlock(&((zbar_processor_t*)proc)->mutex); + _zbar_mutex_unlock(&ncproc->mutex); return(userdata); } @@ -534,6 +548,18 @@ int zbar_processor_set_visible (zbar_processor_t *proc, return(rc); } +const zbar_symbol_set_t* +zbar_processor_get_results (const zbar_processor_t *proc) +{ + zbar_processor_t *ncproc = (zbar_processor_t*)proc; + proc_enter(ncproc); + const zbar_symbol_set_t *syms = proc->syms; + if(syms) + zbar_symbol_set_ref(syms, 1); + proc_leave(ncproc); + return(syms); +} + int zbar_processor_user_wait (zbar_processor_t *proc, int timeout) { @@ -546,13 +572,14 @@ int zbar_processor_user_wait (zbar_processor_t *proc, rc = _zbar_processor_wait(proc, EVENT_INPUT, _zbar_timer_init(&timer, timeout)); } - if(rc > 0) - rc = proc->input; if(!proc->visible) rc = err_capture(proc, SEV_WARNING, ZBAR_ERR_CLOSED, __func__, "display window not available for input"); + if(rc > 0) + rc = proc->input; + _zbar_mutex_lock(&proc->mutex); proc_leave(proc); return(rc); @@ -602,6 +629,7 @@ int zbar_process_one (zbar_processor_t *proc, int timeout) { proc_enter(proc); + int streaming = proc->streaming; _zbar_mutex_unlock(&proc->mutex); int rc = 0; @@ -611,15 +639,17 @@ int zbar_process_one (zbar_processor_t *proc, goto done; } - rc = zbar_processor_set_active(proc, 1); - if(rc) - goto done; + if(!streaming) { + rc = zbar_processor_set_active(proc, 1); + if(rc) + goto done; + } zbar_timer_t timer; rc = _zbar_processor_wait(proc, EVENT_OUTPUT, _zbar_timer_init(&timer, timeout)); - if(zbar_processor_set_active(proc, 0)) + if(!streaming && zbar_processor_set_active(proc, 0)) rc = -1; done: diff --git a/zbar/processor.h b/zbar/processor.h index 9a9f659..5dcd05a 100644 --- a/zbar/processor.h +++ b/zbar/processor.h @@ -56,6 +56,8 @@ typedef struct proc_waiter_s { /* high-level API events */ #define EVENT_INPUT 0x01 /* user input */ #define EVENT_OUTPUT 0x02 /* decoded output data available */ +#define EVENT_CANCELED 0x80 /* cancelation flag */ +#define EVENTS_PENDING (EVENT_INPUT | EVENT_OUTPUT) struct zbar_processor_s { errinfo_t err; /* error reporting */ @@ -86,6 +88,8 @@ struct zbar_processor_s { zbar_thread_t input_thread; /* video input handler */ zbar_thread_t video_thread; /* window event handler */ + const zbar_symbol_set_t *syms; /* previous decode results */ + zbar_mutex_t mutex; /* shared data mutex */ /* API serialization lock */ diff --git a/zbar/processor/lock.c b/zbar/processor/lock.c index d1d80bc..478af5d 100644 --- a/zbar/processor/lock.c +++ b/zbar/processor/lock.c @@ -67,7 +67,7 @@ static inline proc_waiter_t *proc_waiter_dequeue (zbar_processor_t *proc) waiter = prev->next; else waiter = proc->wait_head; - while(waiter && waiter->events) { + while(waiter && (waiter->events & EVENTS_PENDING)) { prev = waiter; proc->wait_next = waiter; waiter = waiter->next; @@ -145,7 +145,8 @@ void _zbar_processor_notify (zbar_processor_t *proc, proc->wait_next = NULL; proc_waiter_t *waiter; for(waiter = proc->wait_head; waiter; waiter = waiter->next) - waiter->events &= ~events; + waiter->events = ((waiter->events & ~events) | + (events & EVENT_CANCELED)); if(!proc->lock_level) { waiter = proc_waiter_dequeue(proc); @@ -162,7 +163,7 @@ static inline int proc_wait_unthreaded (zbar_processor_t *proc, _zbar_mutex_unlock(&proc->mutex); int rc = 1; - while(rc > 0 && waiter->events) { + while(rc > 0 && (waiter->events & EVENTS_PENDING)) { /* FIXME lax w/the locking (though shouldn't matter...) */ if(blocking) { zbar_image_t *img = zbar_video_next_image(proc->video); @@ -193,7 +194,7 @@ int _zbar_processor_wait (zbar_processor_t *proc, _zbar_mutex_lock(&proc->mutex); int save_level = proc->lock_level; proc_waiter_t *waiter = proc_waiter_queue(proc); - waiter->events = events; + waiter->events = events & EVENTS_PENDING; _zbar_processor_unlock(proc, 1); int rc; @@ -205,6 +206,7 @@ int _zbar_processor_wait (zbar_processor_t *proc, if(rc <= 0 || !proc->threaded) { /* reacquire api lock */ waiter->events = 0; + proc->wait_next = NULL; if(!proc->lock_level) { proc_waiter_t *w = proc_waiter_dequeue(proc); assert(w == waiter); @@ -212,6 +214,8 @@ int _zbar_processor_wait (zbar_processor_t *proc, else _zbar_event_wait(&waiter->notify, &proc->mutex, NULL); } + if(rc > 0 && (waiter->events & EVENT_CANCELED)) + rc = -1; assert(proc->lock_level == 1); assert(_zbar_thread_is_self(proc->lock_owner)); diff --git a/zbar/qrcode/qrdectxt.c b/zbar/qrcode/qrdectxt.c index a748f56..8a82ea1 100644 --- a/zbar/qrcode/qrdectxt.c +++ b/zbar/qrcode/qrdectxt.c @@ -379,8 +379,7 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, sa_sym->data_alloc = sa_ntext; sa_sym->datalen = sa_ntext - 1; - _zbar_symbol_set_add(img->syms, sa_sym); - _zbar_image_scanner_cache_sym(iscn, sa_sym); + _zbar_image_scanner_add_sym(iscn, sa_sym); } else { _zbar_image_scanner_recycle_syms(iscn, syms); diff --git a/zbar/symbol.c b/zbar/symbol.c index 4eb54ef..37e86a2 100644 --- a/zbar/symbol.c +++ b/zbar/symbol.c @@ -70,10 +70,11 @@ void _zbar_symbol_free (zbar_symbol_t *sym) free(sym); } -void zbar_symbol_ref (zbar_symbol_t *sym, +void zbar_symbol_ref (const zbar_symbol_t *sym, int refs) { - _zbar_symbol_refcnt(sym, refs); + zbar_symbol_t *ncsym = (zbar_symbol_t*)sym; + _zbar_symbol_refcnt(ncsym, refs); } zbar_symbol_type_t zbar_symbol_get_type (const zbar_symbol_t *sym) @@ -220,11 +221,12 @@ inline void _zbar_symbol_set_free (zbar_symbol_set_t *syms) free(syms); } -void zbar_symbol_set_ref (zbar_symbol_set_t *syms, +void zbar_symbol_set_ref (const zbar_symbol_set_t *syms, int delta) { - if(!_zbar_refcnt(&syms->refcnt, delta) && delta <= 0) - _zbar_symbol_set_free(syms); + zbar_symbol_set_t *ncsyms = (zbar_symbol_set_t*)syms; + if(!_zbar_refcnt(&ncsyms->refcnt, delta) && delta <= 0) + _zbar_symbol_set_free(ncsyms); } int zbar_symbol_set_get_size (const zbar_symbol_set_t *syms) @@ -235,5 +237,8 @@ int zbar_symbol_set_get_size (const zbar_symbol_set_t *syms) const zbar_symbol_t* zbar_symbol_set_first_symbol (const zbar_symbol_set_t *syms) { + zbar_symbol_t *sym = syms->tail; + if(sym) + return(sym->next); return(syms->head); } diff --git a/zbar/symbol.h b/zbar/symbol.h index 4ec5357..7b256ed 100644 --- a/zbar/symbol.h +++ b/zbar/symbol.h @@ -33,8 +33,9 @@ typedef struct point_s { struct zbar_symbol_set_s { refcnt_t refcnt; - int nsyms; /* number of valid symbols */ + int nsyms; /* number of filtered symbols */ zbar_symbol_t *head; /* first of decoded symbol results */ + zbar_symbol_t *tail; /* last of unfiltered symbol results */ }; struct zbar_symbol_s { From 3a57b6e23aa4dc2de132f2320e0a777d12febab3 Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 21 Oct 2009 13:01:02 -0400 Subject: [PATCH 154/328] fix window closed notification during events - add read_one example, fix xs compiler warnings, update perl docs --- ChangeLog | 2 ++ examples/processor.pl | 7 ++++--- examples/processor.py | 8 ++++---- examples/read_one.pl | 29 +++++++++++++++++++++++++++++ examples/read_one.py | 29 +++++++++++++++++++++++++++++ perl/ZBar.xs | 8 ++++++-- perl/ZBar/ImageScanner.pod | 5 +++++ perl/ZBar/Processor.pod | 5 +++++ zbar/processor/lock.c | 2 +- 9 files changed, 85 insertions(+), 10 deletions(-) create mode 100755 examples/read_one.pl create mode 100755 examples/read_one.py diff --git a/ChangeLog b/ChangeLog index ae5bb74..80c4c8d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * fix window closed notification during events + - add read_one example, fix xs compiler warnings, update perl docs * add result query interfaces to image scanner and processor - move result filtering into image scanner (from user) - abort output blockers when window closed diff --git a/examples/processor.pl b/examples/processor.pl index e14a4a3..d2d1e91 100755 --- a/examples/processor.pl +++ b/examples/processor.pl @@ -17,11 +17,10 @@ sub my_handler { my ($proc, $image, $closure) = @_; # extract results - foreach my $symbol ($image->get_symbols()) { + foreach my $symbol ($proc->get_results()) { # do something useful with results print('decoded ' . $symbol->get_type() . - ' symbol "' . $symbol->get_data() . "\"\n") - if(!$symbol->get_count()); + ' symbol "' . $symbol->get_data() . "\"\n"); } } $proc->set_data_handler(\&my_handler); @@ -31,4 +30,6 @@ sub my_handler { # initiate scanning $proc->set_active(); + +# keep scanning until user provides key/mouse input $proc->user_wait(); diff --git a/examples/processor.py b/examples/processor.py index e565164..52996d1 100755 --- a/examples/processor.py +++ b/examples/processor.py @@ -17,10 +17,9 @@ # setup a callback def my_handler(proc, image, closure): # extract results - for symbol in image: - if not symbol.count: - # do something useful with results - print 'decoded', symbol.type, 'symbol', '"%s"' % symbol.data + for symbol in image.symbols: + # do something useful with results + print 'decoded', symbol.type, 'symbol', '"%s"' % symbol.data proc.set_data_handler(my_handler) @@ -30,6 +29,7 @@ def my_handler(proc, image, closure): # initiate scanning proc.active = True try: + # keep scanning until user provides key/mouse input proc.user_wait() except zbar.WindowClosed, e: pass diff --git a/examples/read_one.pl b/examples/read_one.pl new file mode 100755 index 0000000..d64860c --- /dev/null +++ b/examples/read_one.pl @@ -0,0 +1,29 @@ +#!/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"); +} diff --git a/examples/read_one.py b/examples/read_one.py new file mode 100755 index 0000000..426b999 --- /dev/null +++ b/examples/read_one.py @@ -0,0 +1,29 @@ +#!/usr/bin/python +from sys import argv +import zbar + +# create a Processor +proc = zbar.Processor() + +# configure the Processor +proc.parse_config('enable') + +# initialize the Processor +device = '/dev/video0' +if len(argv) > 1: + device = argv[1] +proc.init(device) + +# enable the preview window +proc.visible = True + +# read at least one barcode (or until window closed) +proc.process_one() + +# hide the preview window +proc.visible = False + +# extract results +for symbol in proc.results: + # do something useful with results + print 'decoded', symbol.type, 'symbol', '"%s"' % symbol.data diff --git a/perl/ZBar.xs b/perl/ZBar.xs index c23de52..ad6fc56 100644 --- a/perl/ZBar.xs +++ b/perl/ZBar.xs @@ -540,8 +540,10 @@ zbar_processor_set_active(processor, active=1) SV * get_results(processor) Barcode::ZBar::Processor processor + PREINIT: + const zbar_symbol_set_t *syms; PPCODE: - zbar_symbol_set_t *syms = zbar_processor_get_results(processor); + syms = zbar_processor_get_results(processor); PUSH_SYMS(zbar_symbol_set_first_symbol(syms)); zbar_symbol_set_ref(syms, -1); @@ -631,8 +633,10 @@ zbar_image_scanner_recycle_image(scanner, image) SV * get_results(scanner) Barcode::ZBar::ImageScanner scanner + PREINIT: + const zbar_symbol_set_t *syms; PPCODE: - zbar_symbol_set_t *syms = zbar_image_scanner_get_results(scanner); + syms = zbar_image_scanner_get_results(scanner); PUSH_SYMS(zbar_symbol_set_first_symbol(syms)); int diff --git a/perl/ZBar/ImageScanner.pod b/perl/ZBar/ImageScanner.pod index b42ebf0..6028dbd 100644 --- a/perl/ZBar/ImageScanner.pod +++ b/perl/ZBar/ImageScanner.pod @@ -50,6 +50,11 @@ Barcode::ZBar::Image. Create a new bar code image scanner instance. +=item get_results() + +Return a list of Barcode::ZBar::Symbol results from the last scanned +image. + =item scan_image([I]) Scan a Barcode::ZBar::Image for bar codes. diff --git a/perl/ZBar/Processor.pod b/perl/ZBar/Processor.pod index 0db7b74..55c8783 100644 --- a/perl/ZBar/Processor.pod +++ b/perl/ZBar/Processor.pod @@ -91,6 +91,11 @@ Test/set visibility of the output window. Enable/disable video streaming and scanning for bar codes. +=item get_results() + +Return a list of Barcode::ZBar::Symbol results from the last scanned +image or video frame. + =item user_wait([I]) Wait for the user to press a key/button or close the window. Bar diff --git a/zbar/processor/lock.c b/zbar/processor/lock.c index 478af5d..1b3766e 100644 --- a/zbar/processor/lock.c +++ b/zbar/processor/lock.c @@ -205,7 +205,7 @@ int _zbar_processor_wait (zbar_processor_t *proc, if(rc <= 0 || !proc->threaded) { /* reacquire api lock */ - waiter->events = 0; + waiter->events &= EVENT_CANCELED; proc->wait_next = NULL; if(!proc->lock_level) { proc_waiter_t *w = proc_waiter_dequeue(proc); From e5cc3b5711a82e6252f74ac73f59e78ac3a321c4 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 22 Oct 2009 15:18:13 -0400 Subject: [PATCH 155/328] release updates - fix perl Processor init without video --- ChangeLog | 4 ++- Makefile.am | 3 ++- NEWS | 12 +++++++++ README | 25 +++++++++-------- configure.ac | 10 +++---- examples/scan_image.pl | 2 +- perl/MANIFEST | 4 +++ perl/ZBar.pm | 2 +- perl/ZBar/ImageScanner.pod | 4 ++- perl/examples/processor.pl | 7 ++--- perl/examples/read_one.pl | 29 ++++++++++++++++++++ perl/examples/scan_image.pl | 2 +- perl/t/Processor.t | 2 +- perl/t/pod.t | 2 +- perl/typemap | 2 ++ zbar.nsi | 3 ++- zbar/window.h | 5 ++-- zbar/window/null.c | 54 +++++++++++++++++++++++++++++++------ 18 files changed, 133 insertions(+), 39 deletions(-) create mode 100755 perl/examples/read_one.pl diff --git a/ChangeLog b/ChangeLog index 80c4c8d..32a419b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ -current: +version 0.10: + * release updates + - fix perl Processor init without video * fix window closed notification during events - add read_one example, fix xs compiler warnings, update perl docs * add result query interfaces to image scanner and processor diff --git a/Makefile.am b/Makefile.am index 0c3fdf6..e0737ad 100644 --- a/Makefile.am +++ b/Makefile.am @@ -49,6 +49,7 @@ 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 @@ -57,7 +58,7 @@ EXTRA_DIST += perl/MANIFEST perl/README perl/Changes perl/COPYING.LIB \ perl/ZBar.pm perl/inc/Devel/CheckLib.pm perl/ZBar/Image.pod \ perl/ZBar/ImageScanner.pod perl/ZBar/Processor.pod perl/ZBar/Symbol.pod \ perl/examples/paginate.pl perl/examples/processor.pl \ - perl/examples/scan_image.pl \ + perl/examples/read_one.pl perl/examples/scan_image.pl \ perl/t/barcode.png perl/t/ZBar.t perl/t/Decoder.t perl/t/Image.t \ perl/t/Processor.t perl/t/Scanner.t perl/t/pod.t perl/t/pod-coverage.t diff --git a/NEWS b/NEWS index 0d3fe33..9d9905a 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,17 @@ ZBar Barcode Reader +version 0.10 (2009-10-23): + ZBar goes 2D! This release introduces support for QR Code, developed + by our new project member, Timothy Terriberry. Timothy is an image + processing master, providing this sophisticated functionality using + only integer arithmetic and maintaining an extremely small image + size. Feel free to drop in on #zbar over at freenode to welcome + Timothy (aka derf) to the project and congratulate him on his awesome + work. + + Several bugs fixes and enhancements are also found in this release; + existing users are encouraged to upgrade. + version 0.9 (2009-08-31): Introducing ZBar for Windows! So far we only have straight ports of the command line applications, but work on a cross-platform GUI has diff --git a/README b/README index 933e4a0..30b8955 100644 --- a/README +++ b/README @@ -37,27 +37,30 @@ pkg-config may be obtained from The zbarimg program uses ImageMagick to read image files in many different formats. You will need at least ImageMagick version 6.2.6 -and the Magick++ development interface to ImageMagick if you want to -scan image files. ImageMagick may be obtained from +if you want to scan image files. ImageMagick may be obtained from http://www.imagemagick.org/ The Qt widget requires Qt4. You will need Qt4 if you would like to -develop a Qt GUI application with an integrated bar code scanning -widget. Qt4 may be obtained from - http://www.qtsoftware.com/products +use or develop a Qt GUI application with an integrated bar code +scanning widget. Qt4 may be obtained from + http://qt.nokia.com/products The GTK+ widget requires GTK+-2.x. You will need GTK+ if you would -like to develop a GTK+ GUI application with an integrated bar code -scanning widget. GTK+ may be obtained from +like to use or develop a GTK+ GUI application with an integrated bar +code scanning widget. GTK+ may be obtained from http://www.gtk.org/ The PyGTK wrapper for the GTK+ widget requires Python and PyGTK. You -will need both if you would like to develop a PyGTK GUI application -with an integrated bar code scanning widget. Python and PyGTK may -respectively be obtained from - http://python.org/ +will need both if you would like to use or develop a PyGTK GUI +application with an integrated bar code scanning widget. PyGTK may be +obtained from http://www.pygtk.org/ +The Python bindings require Python (version?). You will need Python +if you would like to scan images or video directly using Python. +Python is available from + http://python.org/ + The Perl bindings require Perl (version?). You will need Perl if you would like to scan images or video directly using Perl. Perl is available from diff --git a/configure.ac b/configure.ac index a499664..56d3dd0 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ([2.61]) -AC_INIT([zbar], [0.9], [spadix@users.sourceforge.net]) +AC_INIT([zbar], [0.10], [spadix@users.sourceforge.net]) AC_CONFIG_AUX_DIR(config) AC_CONFIG_MACRO_DIR(config) AM_INIT_AUTOMAKE([1.10 -Wall -Werror foreign subdir-objects std-options dist-bzip2]) @@ -21,13 +21,13 @@ dnl - If any interfaces have been added since the last public release, dnl then increment age. dnl - If any interfaces have been removed since the last public release, dnl then set age to 0. -AC_SUBST([LIB_VERSION], [1:0:1]) -AC_SUBST([RELDATE], [2009-08-31]) +AC_SUBST([LIB_VERSION], [2:0:2]) +AC_SUBST([RELDATE], [2009-10-23]) dnl widget libraries use their own versioning. dnl NB pygtk wrapper is *unversioned* -AC_SUBST([ZGTK_LIB_VERSION], [0:1:0]) -AC_SUBST([ZQT_LIB_VERSION], [0:1:0]) +AC_SUBST([ZGTK_LIB_VERSION], [0:2:0]) +AC_SUBST([ZQT_LIB_VERSION], [0:2:0]) AC_DEFINE_UNQUOTED([ZBAR_VERSION_MAJOR], [[`echo "$PACKAGE_VERSION" | sed -e 's/\..*$//'`]], diff --git a/examples/scan_image.pl b/examples/scan_image.pl index 3734d19..39d460e 100755 --- a/examples/scan_image.pl +++ b/examples/scan_image.pl @@ -15,7 +15,7 @@ # obtain image data my $magick = Image::Magick->new(); $magick->Read($ARGV[0]) && die; -my $raw = $magick->ImageToBlob(magick => 'GRAY'); +my $raw = $magick->ImageToBlob(magick => 'GRAY', depth => 8); # wrap image data my $image = Barcode::ZBar::Image->new(); diff --git a/perl/MANIFEST b/perl/MANIFEST index 8d98fa5..c2412a0 100644 --- a/perl/MANIFEST +++ b/perl/MANIFEST @@ -20,3 +20,7 @@ t/ZBar.t t/pod.t t/pod-coverage.t inc/Devel/CheckLib.pm +examples/paginate.pl +examples/processor.pl +examples/read_one.pl +examples/scan_image.pl diff --git a/perl/ZBar.pm b/perl/ZBar.pm index f289c01..47cefa6 100644 --- a/perl/ZBar.pm +++ b/perl/ZBar.pm @@ -32,7 +32,7 @@ our @ISA = qw(Exporter); our @EXPORT_OK = qw(SPACE BAR version increase_verbosity set_verbosity); -our $VERSION = '0.03'; +our $VERSION = '0.04'; require XSLoader; XSLoader::load('Barcode::ZBar', $VERSION); diff --git a/perl/ZBar/ImageScanner.pod b/perl/ZBar/ImageScanner.pod index 6028dbd..94f32e3 100644 --- a/perl/ZBar/ImageScanner.pod +++ b/perl/ZBar/ImageScanner.pod @@ -57,7 +57,9 @@ image. =item scan_image([I]) -Scan a Barcode::ZBar::Image for bar codes. +Scan a Barcode::ZBar::Image for bar codes. The image must be in the +"Y800" format. If necessary, use C<< I<$image>->convert("Y800") >> to +convert from other supported formats to Y800 before scanning. =item enable_cache([I]) diff --git a/perl/examples/processor.pl b/perl/examples/processor.pl index e14a4a3..d2d1e91 100755 --- a/perl/examples/processor.pl +++ b/perl/examples/processor.pl @@ -17,11 +17,10 @@ sub my_handler { my ($proc, $image, $closure) = @_; # extract results - foreach my $symbol ($image->get_symbols()) { + foreach my $symbol ($proc->get_results()) { # do something useful with results print('decoded ' . $symbol->get_type() . - ' symbol "' . $symbol->get_data() . "\"\n") - if(!$symbol->get_count()); + ' symbol "' . $symbol->get_data() . "\"\n"); } } $proc->set_data_handler(\&my_handler); @@ -31,4 +30,6 @@ sub my_handler { # initiate scanning $proc->set_active(); + +# keep scanning until user provides key/mouse input $proc->user_wait(); diff --git a/perl/examples/read_one.pl b/perl/examples/read_one.pl new file mode 100755 index 0000000..d64860c --- /dev/null +++ b/perl/examples/read_one.pl @@ -0,0 +1,29 @@ +#!/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"); +} diff --git a/perl/examples/scan_image.pl b/perl/examples/scan_image.pl index 3734d19..39d460e 100755 --- a/perl/examples/scan_image.pl +++ b/perl/examples/scan_image.pl @@ -15,7 +15,7 @@ # obtain image data my $magick = Image::Magick->new(); $magick->Read($ARGV[0]) && die; -my $raw = $magick->ImageToBlob(magick => 'GRAY'); +my $raw = $magick->ImageToBlob(magick => 'GRAY', depth => 8); # wrap image data my $image = Barcode::ZBar::Image->new(); diff --git a/perl/t/Processor.t b/perl/t/Processor.t index aa6734c..21a4a67 100755 --- a/perl/t/Processor.t +++ b/perl/t/Processor.t @@ -77,7 +77,7 @@ $proc->set_data_handler(sub { ######################### -$proc->init($ENV{VIDEO_DEVICE} || '/dev/video0'); +$proc->init($ENV{VIDEO_DEVICE}); ok(!$proc->is_visible(), 'initial visibility'); ######################### diff --git a/perl/t/pod.t b/perl/t/pod.t index a83ee7d..bc0af34 100644 --- a/perl/t/pod.t +++ b/perl/t/pod.t @@ -5,7 +5,7 @@ use warnings; use strict; use Test::More; -eval { use Test::Pod 1.00 }; +eval "use Test::Pod 1.00"; plan skip_all => "Test::Pod 1.00 required for testing POD" if $@; diff --git a/perl/typemap b/perl/typemap index 4cad035..2d6ef6b 100644 --- a/perl/typemap +++ b/perl/typemap @@ -45,6 +45,8 @@ T_FOURCC T_TIMEOUT if(($var = ($type)(SvNV($arg) * 1000.)) < 0) $var = -1; +T_PV + $var = SvOK($arg) ? SvPV_nolen($arg) : NULL; OUTPUT diff --git a/zbar.nsi b/zbar.nsi index fbe11c2..640d4e6 100644 --- a/zbar.nsi +++ b/zbar.nsi @@ -259,7 +259,8 @@ Section Uninstall Delete $INSTDIR\README.windows Delete $INSTDIR\NEWS Delete $INSTDIR\TODO - Delete $INSTDIR\COPYING.LIB + Delete $INSTDIR\COPYING + Delete $INSTDIR\LICENSE Delete $INSTDIR\zbarvars.bat Delete $INSTDIR\uninstall.exe RMDir $INSTDIR diff --git a/zbar/window.h b/zbar/window.h index bba52cf..0db7a2a 100644 --- a/zbar/window.h +++ b/zbar/window.h @@ -134,12 +134,11 @@ extern int _zbar_window_resize(zbar_window_t*); extern int _zbar_window_clear(zbar_window_t*); extern int _zbar_window_begin(zbar_window_t*); extern int _zbar_window_end(zbar_window_t*); -extern int _zbar_window_draw_logo(zbar_window_t*); extern int _zbar_window_draw_marker(zbar_window_t*, uint32_t, point_t); extern int _zbar_window_draw_polygon(zbar_window_t*, uint32_t, const point_t*, int); extern int _zbar_window_draw_text(zbar_window_t*, uint32_t, point_t, const char*); -extern int _zbar_window_fill_rect(zbar_window_t*, uint32_t, - point_t, const point_t); +extern int _zbar_window_fill_rect(zbar_window_t*, uint32_t, point_t, point_t); +extern int _zbar_window_draw_logo(zbar_window_t*); #endif diff --git a/zbar/window/null.c b/zbar/window/null.c index 9588747..df9a8fd 100644 --- a/zbar/window/null.c +++ b/zbar/window/null.c @@ -30,31 +30,69 @@ static inline int null_error (void *m, "not compiled with output window support")); } +int _zbar_window_attach (zbar_window_t *w, + void *display, + unsigned long win) +{ + return(null_error(w, __func__)); +} + +int _zbar_window_expose (zbar_window_t *w, + int x, + int y, + int width, + int height) +{ + return(null_error(w, __func__)); +} + int _zbar_window_resize (zbar_window_t *w) { return(0); } -int _zbar_window_attach (zbar_window_t *w, - void *display, - unsigned long win) +int _zbar_window_clear (zbar_window_t *w) { return(null_error(w, __func__)); } -int _zbar_window_flush (zbar_window_t *w) +int _zbar_window_begin (zbar_window_t *w) { return(null_error(w, __func__)); } -int _zbar_window_clear (zbar_window_t *w) +int _zbar_window_end (zbar_window_t *w) +{ + return(null_error(w, __func__)); +} + +int _zbar_window_draw_marker (zbar_window_t *w, + uint32_t rgb, + point_t p) +{ + return(null_error(w, __func__)); +} + +int _zbar_window_draw_polygon (zbar_window_t *w, + uint32_t rgb, + const point_t *pts, + int npts) +{ + return(null_error(w, __func__)); +} + +int _zbar_window_draw_text (zbar_window_t *w, + uint32_t rgb, + point_t p, + const char *text) { return(null_error(w, __func__)); } -int _zbar_window_draw_marker(zbar_window_t *w, - uint32_t rgb, - const point_t *p) +int _zbar_window_fill_rect (zbar_window_t *w, + uint32_t rgb, + point_t org, + point_t size) { return(null_error(w, __func__)); } From 44220c8e1a58ca54b0cd768548a08f6210fed842 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 22 Oct 2009 16:37:44 -0400 Subject: [PATCH 156/328] attempt fix for Qt4 < 4.4 --- ChangeLog | 1 + perl/t/Processor.t | 2 +- qt/QZBar.cpp | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 32a419b..3453d71 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ version 0.10: + * attempt fix for Qt4 < 4.4 * release updates - fix perl Processor init without video * fix window closed notification during events diff --git a/perl/t/Processor.t b/perl/t/Processor.t index 21a4a67..db45817 100755 --- a/perl/t/Processor.t +++ b/perl/t/Processor.t @@ -94,7 +94,7 @@ ok($proc->user_wait(1.1) >= 0, 'wait w/timeout'); SKIP: { # FIXME factor out image read utility eval { require Image::Magick }; - skip "Image::Magick not installed", 8 if $@; + skip "Image::Magick not installed", 11 if $@; my $im = Image::Magick->new(); my $err = $im->Read('t/barcode.png'); die($err) if($err); diff --git a/qt/QZBar.cpp b/qt/QZBar.cpp index bff10ea..e1001b0 100644 --- a/qt/QZBar.cpp +++ b/qt/QZBar.cpp @@ -38,8 +38,10 @@ QZBar::QZBar (QWidget *parent) { setAttribute(Qt::WA_OpaquePaintEvent); setAttribute(Qt::WA_PaintOnScreen); +#if QT_VERSION >= 0x040400 setAttribute(Qt::WA_NativeWindow); setAttribute(Qt::WA_DontCreateNativeAncestors); +#endif QSizePolicy sizing(QSizePolicy::Preferred, QSizePolicy::Preferred); sizing.setHeightForWidth(true); From 97bc84f72b380f159458c596018458d98d6472bc Mon Sep 17 00:00:00 2001 From: tterribe Date: Thu, 22 Oct 2009 16:59:27 -0400 Subject: [PATCH 157/328] Fix Xv detection allocations to use the correct type size. This avoids segfaults on 64-bit systems. --- zbar/window/xv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zbar/window/xv.c b/zbar/window/xv.c index 855ffe1..361c1b8 100644 --- a/zbar/window/xv.c +++ b/zbar/window/xv.c @@ -122,7 +122,7 @@ static inline int xv_add_format (zbar_window_t *w, window_state_t *x = w->state; if(!w->formats[i + 1]) - x->xv_ports = realloc(x->xv_ports, (i + 1) * sizeof(uint32_t)); + x->xv_ports = realloc(x->xv_ports, (i + 1) * sizeof(*x->xv_ports)); /* FIXME could prioritize by something (rate? size?) */ x->xv_ports[i] = port; @@ -205,7 +205,7 @@ int _zbar_window_probe_xv (zbar_window_t *w) window_state_t *x = w->state; x->num_xv_adaptors = 0; - x->xv_adaptors = calloc(n, sizeof(int)); + x->xv_adaptors = calloc(n, sizeof(*x->xv_adaptors)); int i; for(i = 0; i < n; i++) { XvAdaptorInfo *adapt = &adaptors[i]; From 8da64bb27855e65208c6c0ee9dbf391dcf000626 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 22 Oct 2009 17:50:38 -0400 Subject: [PATCH 158/328] test script print from present --- test/barcodetest.py | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/test/barcodetest.py b/test/barcodetest.py index 798a166..9881c8c 100755 --- a/test/barcodetest.py +++ b/test/barcodetest.py @@ -1,7 +1,5 @@ #!/usr/bin/env python -from __future__ import print_function - import sys, re, unittest as UT, xml.etree.ElementTree as ET from os import path, getcwd from errno import EISDIR, EINVAL, EACCES @@ -45,15 +43,15 @@ def toxml(node): return s.getvalue() def hexdump(data): - print(data) + print data for i, c in enumerate(data): if i & 0x7 == 0: - print('[%04x]' % i, end='') - print(' %04x' % ord(c), end='') + print '[%04x]' % i, + print ' %04x' % ord(c), if i & 0x7 == 0x7: - print() + print if len(c) & 0x7 != 0x7: - print('\n') + print '\n' # search for a file in the distribution @@ -98,9 +96,9 @@ def find_zbarimg(): # fall back to PATH zbarimg = 'zbarimg' if debug: - print('using zbarimg from PATH') + print 'using zbarimg from PATH' elif debug: - print('using:', zbarimg) + print 'using:', zbarimg def run_zbarimg(images): @@ -112,7 +110,7 @@ def run_zbarimg(images): args.extend(zbarimg_args) args.extend(images) if debug: - print("running:", ' '.join(args)) + print 'running:', ' '.join(args) # FIXME should be able to pipe (feed) parser straight from output child = Popen(args, stdout = PIPE, stderr = PIPE) @@ -120,7 +118,7 @@ def run_zbarimg(images): rc = child.returncode if debug: - print("zbarimg returned", rc) + print 'zbarimg returned', rc # FIXME trim usage from error msg assert rc in (0, 4), \ @@ -198,9 +196,9 @@ def compare_maps(expect, actual, compare_func): errors.append('missing expected result:\n' + toxml(iexp)) if len(notes) == 1: - print("(TODO)", end='', file=sys.stderr) + print >>sys.stderr, '(TODO)', elif notes: - print("(%d TODO)" % len(notes), end='', file=sys.stderr) + print >>sys.stderr, '(%d TODO)' % len(notes), assert not errors, '\n'.join(errors) @@ -270,7 +268,7 @@ class TestLoader: def __init__(self): self.cwd = urlunparse(('file', '', getcwd() + '/', '', '', '')) if debug: - print('cwd =', self.cwd) + print 'cwd =', self.cwd def loadTestsFromModule(self, module): return self.suiteClass([BuiltinTestCase()]) @@ -281,7 +279,7 @@ def loadTestsFromNames(self, names, module=None): def loadTestsFromURL(self, url=None, file=None): if debug: - print('loading url:', url) + print 'loading url:', url target = None if not file: @@ -294,7 +292,7 @@ def loadTestsFromURL(self, url=None, file=None): try: if debug: - print('trying:', url) + print 'trying:', url file = urlopen(url) content = file.info().get('Content-Type') except HTTPError, e: @@ -312,7 +310,7 @@ def loadTestsFromURL(self, url=None, file=None): try: tmp = urljoin(url + '/', 'index.xml') if debug: - print('trying index:', tmp) + print 'trying index:', tmp file = urlopen(tmp) content = file.info().get('Content-Type') url = tmp @@ -320,7 +318,7 @@ def loadTestsFromURL(self, url=None, file=None): raise IOError('no test index found at: %s' % url) if debug: - print('\tContent-Type:', content) + print '\tContent-Type:', content if content not in ('application/xml', 'text/xml'): # assume url is image to test, try containing index @@ -329,11 +327,11 @@ def loadTestsFromURL(self, url=None, file=None): target = url.rsplit('/', 1)[1] index = urljoin(url, 'index.xml') if debug: - print('trying index:', index) + print 'trying index:', index file = urlopen(index) content = file.info().get('Content-Type') if debug: - print('\tContent-Type:', content) + print '\tContent-Type:', content assert content in ('application/xml', 'text/xml') url = index except IOError: From 27429960db78d00247ce02adf4d5ba812ce6f9d3 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 22 Oct 2009 18:01:09 -0400 Subject: [PATCH 159/328] more python test compatibility updates --- test/barcodetest.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/barcodetest.py b/test/barcodetest.py index 9881c8c..6219a5d 100755 --- a/test/barcodetest.py +++ b/test/barcodetest.py @@ -64,13 +64,13 @@ def distdir_search(subdir, base, suffixes=('',)): # finally, attempt to follow VPATH if present try: import re - with open('Makefile') as makefile: - for line in makefile: - if re.match('^VPATH\s*=', line): - vpath = line.split('=', 1)[1].strip() - if vpath and vpath != rundir: - search.append(vpath) - break + makefile = open('Makefile') + for line in makefile: + if re.match('^VPATH\s*=', line): + vpath = line.split('=', 1)[1].strip() + if vpath and vpath != rundir: + search.append(vpath) + break except: pass From 088fbe5d62f8b6261fae8256cec231d311548fb6 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 22 Oct 2009 22:36:02 -0400 Subject: [PATCH 160/328] Windows updates --- include/zbar/Symbol.h | 2 +- zbar/window/win.c | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/include/zbar/Symbol.h b/include/zbar/Symbol.h index 61cbe38..b47732a 100644 --- a/include/zbar/Symbol.h +++ b/include/zbar/Symbol.h @@ -423,7 +423,7 @@ class SymbolIterator } private: - const SymbolSet _syms; + SymbolSet _syms; Symbol _sym; }; diff --git a/zbar/window/win.c b/zbar/window/win.c index f6288e9..b949f65 100644 --- a/zbar/window/win.c +++ b/zbar/window/win.c @@ -193,15 +193,13 @@ int _zbar_window_draw_polygon (zbar_window_t *w, HDC hdc = w->state->hdc; win_set_rgb(hdc, rgb); + point_t org = w->scaled_offset; POINT gdipts[npts + 1]; int i; for(i = 0; i < npts; i++) { - gdipts[i].x = pts[i].x; - if(w->width != w->image->width) - gdipts[i].x = gdipts[i].x * w->width / w->image->width; - gdipts[i].y = pts[i].y; - if(w->height != w->image->height) - gdipts[i].y = gdipts[i].y * w->height / w->image->height; + point_t p = window_scale_pt(w, pts[i]); + gdipts[i].x = p.x + org.x; + gdipts[i].y = p.y + org.y; } gdipts[npts] = gdipts[0]; From abc2c8c8c47c9f0debf6d6c17fc8db6f954dfa1a Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 23 Oct 2009 09:18:20 -0400 Subject: [PATCH 161/328] release updates --- Makefile.am | 2 +- zbar/processor.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index e0737ad..9608be6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ AM_CPPFLAGS = -I$(srcdir)/include -AM_CFLAGS = -Wall -Werror -Wno-parentheses +AM_CFLAGS = -Wall -Wno-parentheses AM_CXXFLAGS = $(AM_CFLAGS) ACLOCAL_AMFLAGS = -I config bin_PROGRAMS = diff --git a/zbar/processor.c b/zbar/processor.c index c64cca3..a160552 100644 --- a/zbar/processor.c +++ b/zbar/processor.c @@ -457,7 +457,7 @@ void *zbar_processor_get_userdata (const zbar_processor_t *proc) { zbar_processor_t *ncproc = (zbar_processor_t*)proc; _zbar_mutex_lock(&ncproc->mutex); - void *userdata = (void*)proc->userdata; + void *userdata = (void*)ncproc->userdata; _zbar_mutex_unlock(&ncproc->mutex); return(userdata); } From 27182a19e57d0dd0076f84b36783b0d9810636f0 Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 23 Oct 2009 14:16:11 -0400 Subject: [PATCH 162/328] Added tag 0.10 for changeset f3670ba47f2e From 325ccbb2d6e73e372fc40a96d606d6ed62f9aee8 Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 27 Oct 2009 11:25:59 -0400 Subject: [PATCH 163/328] hotfix add MinGW import lib to Windows installer --- ChangeLog | 1 + zbar.nsi | 1 + 2 files changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index 3453d71..e1a1f99 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ version 0.10: + * hotfix add MinGW import lib to Windows installer * attempt fix for Qt4 < 4.4 * release updates - fix perl Processor init without video diff --git a/zbar.nsi b/zbar.nsi index 640d4e6..e15718b 100644 --- a/zbar.nsi +++ b/zbar.nsi @@ -212,6 +212,7 @@ Section "Development Headers and Libraries" SecDevel SetOutPath $INSTDIR\lib File lib\libzbar-0.def File lib\libzbar-0.lib + File lib\libzbar.dll.a SetOutPath $INSTDIR\examples File share\zbar\scan_image.cpp From 48af0df8a5fd1b70c43aa0e96be20c5b22941e76 Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 27 Oct 2009 11:26:14 -0400 Subject: [PATCH 164/328] Added tag 0.10 for changeset 563557a923d0 From 8e7f24d18d7677c06cd6106251a1c57835b8827c Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 3 Nov 2009 09:22:26 -0500 Subject: [PATCH 165/328] first pass working iPhone "widget" --- ChangeLog | 3 + include/zbar/ZBarReaderController.h | 64 ++++++ include/zbar/ZBarSymbol.h | 41 ++++ iphone/ZBarHelpController.h | 37 ++++ iphone/ZBarHelpController.m | 258 ++++++++++++++++++++++ iphone/ZBarReaderController.m | 326 ++++++++++++++++++++++++++++ iphone/ZBarSymbol.m | 70 ++++++ iphone/res/buttondown.svg | 57 +++++ iphone/res/buttonmask.svg | 26 +++ iphone/res/buttonup.svg | 57 +++++ iphone/res/lightbulb.svg | 108 +++++++++ iphone/res/shakyhand.svg | 108 +++++++++ iphone/res/stopwatch.svg | 88 ++++++++ iphone/res/zbar-button.png | Bin 0 -> 2536 bytes iphone/res/zbar-helpicons.png | Bin 0 -> 14506 bytes 15 files changed, 1243 insertions(+) create mode 100644 include/zbar/ZBarReaderController.h create mode 100644 include/zbar/ZBarSymbol.h create mode 100644 iphone/ZBarHelpController.h create mode 100644 iphone/ZBarHelpController.m create mode 100644 iphone/ZBarReaderController.m create mode 100644 iphone/ZBarSymbol.m create mode 100644 iphone/res/buttondown.svg create mode 100644 iphone/res/buttonmask.svg create mode 100644 iphone/res/buttonup.svg create mode 100644 iphone/res/lightbulb.svg create mode 100644 iphone/res/shakyhand.svg create mode 100644 iphone/res/stopwatch.svg create mode 100644 iphone/res/zbar-button.png create mode 100644 iphone/res/zbar-helpicons.png diff --git a/ChangeLog b/ChangeLog index 3453d71..44f3609 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +current: + * first pass working iPhone "widget" + version 0.10: * attempt fix for Qt4 < 4.4 * release updates diff --git a/include/zbar/ZBarReaderController.h b/include/zbar/ZBarReaderController.h new file mode 100644 index 0000000..576ad8b --- /dev/null +++ b/include/zbar/ZBarReaderController.h @@ -0,0 +1,64 @@ +//------------------------------------------------------------------------ +// Copyright 2009 (c) Jeff Brown +// +// 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 +#import +#import +#import + +@protocol ZBarReaderDelegate +@end + +@interface ZBarReaderController : UIImagePickerController + < UINavigationControllerDelegate, + UIImagePickerControllerDelegate, + UIActionSheetDelegate > +{ + zbar_image_scanner_t *scanner; + UIViewController *picker; + UIView *overlay; + + id readerDelegate; + BOOL showsZBarControls, showsHelpOnFail; +} + +@property (nonatomic, assign) id readerDelegate; + +// whether to use alternate control set +@property (nonatomic) BOOL showsZBarControls; + +// whether to display helpful information when decoding fails +@property (nonatomic) BOOL showsHelpOnFail; + +// decoder configuration +- (void) parseConfig: (NSString*) configStr; +- (void) setSymbology: (zbar_symbol_type_t) symbology + config: (zbar_config_t) config + to: (int) value; + +// direct scanner interface +- (id ) scanImage: (UIImage*) img; + +@end + +extern NSString* const ZBarReaderControllerResults; diff --git a/include/zbar/ZBarSymbol.h b/include/zbar/ZBarSymbol.h new file mode 100644 index 0000000..af49281 --- /dev/null +++ b/include/zbar/ZBarSymbol.h @@ -0,0 +1,41 @@ +//------------------------------------------------------------------------ +// Copyright 2009 (c) Jeff Brown +// +// 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 +#import + +// Obj-C wrapper for ZBar result type + +@interface ZBarSymbol : NSObject +{ + const zbar_symbol_t *symbol; +} + +@property (readonly, nonatomic) zbar_symbol_type_t type; +@property (readonly, nonatomic) NSString *typeName; +@property (readonly, nonatomic) NSString *data; +@property (readonly, nonatomic) int quality; + +- (id) initWithSymbol: (const zbar_symbol_t*) symbol; + +@end diff --git a/iphone/ZBarHelpController.h b/iphone/ZBarHelpController.h new file mode 100644 index 0000000..da02d10 --- /dev/null +++ b/iphone/ZBarHelpController.h @@ -0,0 +1,37 @@ +//------------------------------------------------------------------------ +// Copyright 2009 (c) Jeff Brown +// +// 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 + +// failure dialog w/a few useful tips + +@interface ZBarHelpController : UIViewController +{ + id delegate; +} + +@property (nonatomic, assign) id delegate; + +extern UIButton *_ZBarButton (CGFloat size, CGFloat r, CGFloat g, CGFloat b); + +@end diff --git a/iphone/ZBarHelpController.m b/iphone/ZBarHelpController.m new file mode 100644 index 0000000..e0cd370 --- /dev/null +++ b/iphone/ZBarHelpController.m @@ -0,0 +1,258 @@ +//------------------------------------------------------------------------ +// Copyright 2009 (c) Jeff Brown +// +// 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 "ZBarHelpController.h" + +enum { BTN_GIVEUP, BTN_TRYAGAIN }; + +UIButton *_ZBarButton (CGFloat size, + CGFloat red, + CGFloat green, + CGFloat blue) +{ + UIButton *btn = [UIButton buttonWithType: UIButtonTypeCustom]; + UILabel *label = btn.titleLabel; + label.shadowColor = [UIColor lightGrayColor]; + label.shadowOffset = CGSizeMake(-1,1); + label.font = [UIFont boldSystemFontOfSize: size * 5 / 12]; + + CGRect r = CGRectMake(0, 0, 48, 48); + CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB(); + CGContextRef ctx = + CGBitmapContextCreate(NULL, r.size.width, r.size.height, + 8, r.size.width * 4, cs, + kCGBitmapByteOrderDefault | + kCGImageAlphaPremultipliedFirst); + CGColorSpaceRelease(cs); + + CGContextSetRGBFillColor(ctx, red, green, blue, 1); + + UIImage *buttonset = [UIImage imageNamed: @"zbar-button.png"]; + CGImageRef setimg = buttonset.CGImage; + CGImageRef up = CGImageCreateWithImageInRect(setimg, r); + r.origin.x = 48; + CGImageRef down = CGImageCreateWithImageInRect(setimg, r); + r.origin.x = 96; + CGImageRef mask = CGImageCreateWithImageInRect(setimg, r); + + r.origin.x = 0; + CGContextClipToMask(ctx, r, mask); + CGImageRelease(mask); + + CGContextFillRect(ctx, r); + CGContextDrawImage(ctx, r, up); + CGImageRelease(up); + + CGImageRef img = CGBitmapContextCreateImage(ctx); + [btn setBackgroundImage: + [[UIImage imageWithCGImage: img] + stretchableImageWithLeftCapWidth: 24 + topCapHeight: 24] + forState: UIControlStateNormal]; + CGImageRelease(img); + + CGContextFillRect(ctx, r); + CGContextDrawImage(ctx, r, down); + CGImageRelease(down); + + img = CGBitmapContextCreateImage(ctx); + [btn setBackgroundImage: + [[UIImage imageWithCGImage: img] + stretchableImageWithLeftCapWidth: 24 + topCapHeight: 24] + forState: UIControlStateHighlighted]; + CGImageRelease(img); + + CGContextRelease(ctx); + return(btn); +} + +@implementation ZBarHelpController + +@synthesize delegate; + +- (UILabel*) addLabelAt: (CGRect) frame + withText: (NSString*) text + font: (UIFont*) font +{ + UILabel *label = [[[UILabel alloc] initWithFrame: frame] autorelease]; + label.autoresizingMask = (UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight); + label.backgroundColor = [UIColor clearColor]; + label.textColor = [UIColor whiteColor]; + label.font = font; + label.text = text; + [self.view addSubview: label]; + return(label); +} + +- (void) viewDidLoad +{ + [super viewDidLoad]; + + UIView *view = self.view; + view.backgroundColor = [UIColor colorWithWhite: .125f + alpha: 1 ]; + + CGSize size = view.bounds.size; + CGRect r; + r.origin.x = 0; + r.origin.y = 0; + r.size.width = size.width; + r.size.height = size.height * 19 / 115; + UILabel *label = + [self addLabelAt: r + withText: @"No Barcode Found" + font: [UIFont boldSystemFontOfSize: size.height * 12 / 115]]; + label.textAlignment = UITextAlignmentCenter; + label.adjustsFontSizeToFitWidth = YES; + label.minimumFontSize = size.height * 5 / 115; + label.textColor = [UIColor colorWithRed: 1.0f green: 0.4f blue: 0.4f + alpha: 1.0f]; + label.shadowColor = [UIColor colorWithRed: 0.5f green: 0.2f blue: 0.2f + alpha: 1.0f]; + label.shadowOffset = CGSizeMake(-1.5,1.5); + + UIFont *bigFont = [UIFont boldSystemFontOfSize: size.height * 7 / 115]; + UIFont *smallFont = [UIFont systemFontOfSize: size.height * 4 / 115]; + + r.origin.x = size.width * .05f; + r.size.width = size.width * 0.9f; + + r.origin.y = r.size.height; + r.size.height = size.height * 8 / 115; + [self addLabelAt: r + withText: @"Hints for successful scanning:" + font: smallFont] + .textAlignment = UITextAlignmentCenter; + + r.origin.x = r.size.width * 7 / 20; + r.size.width = r.size.width * 13 / 20; + + r.origin.y = size.height * 31 / 115; + r.size.height = size.height * 6 / 115; + [self addLabelAt: r + withText: @"ensure there is plenty of" + font: smallFont]; + + r.origin.y = size.height * 39 / 115; + r.size.height = size.height * 8 / 115; + [self addLabelAt: r + withText: @"Light" + font: bigFont] + .textColor = [UIColor colorWithRed: 1.0f green: 1.0f blue: 0.333f + alpha: 1]; + + r.origin.y = size.height * 55 / 115; + r.size.height = size.height * 8 / 115; + [self addLabelAt: r + withText: @"Wait" + font: bigFont] + .textColor = [UIColor colorWithRed: 0.5f green: 1.0f blue: 0.5f + alpha: 1]; + + r.origin.y = size.height * 65 / 115; + r.size.height = size.height * 6 / 115; + [self addLabelAt: r + withText: @"for the camera to focus" + font: smallFont]; + + r.origin.y = size.height * 79 / 115; + r.size.height = size.height * 8 / 115; + [self addLabelAt: r + withText: @"Hold Still" + font: bigFont] + .textColor = [UIColor colorWithRed: 0.583f green: 0.583f blue: 1.0f + alpha: 1]; + + r.origin.y = size.height * 89 / 115; + r.size.height = size.height * 6 / 115; + [self addLabelAt: r + withText: @"while taking the picture" + font: smallFont]; + + r.origin.x = size.width / 20; + r.size.width = r.size.height = size.height * 16 / 115; + + UIImage *iconset = [UIImage imageNamed: @"zbar-helpicons.png"]; + CGImageRef setimg = iconset.CGImage; + + r.origin.y = size.height * 31 / 115; + UIImageView *icon = [[UIImageView alloc] initWithFrame: r]; + CGImageRef img = + CGImageCreateWithImageInRect(setimg, CGRectMake(0, 0, 64, 64)); + icon.image = [UIImage imageWithCGImage: img]; + CGImageRelease(img); + [view addSubview: icon]; + + r.origin.y = size.height * 55 / 115; + icon = [[UIImageView alloc] initWithFrame: r]; + img = CGImageCreateWithImageInRect(setimg, CGRectMake(64, 0, 64, 64)); + icon.image = [UIImage imageWithCGImage: img]; + CGImageRelease(img); + [view addSubview: icon]; + + r.origin.y = size.height * 79 / 115; + icon = [[UIImageView alloc] initWithFrame: r]; + img = CGImageCreateWithImageInRect(setimg, CGRectMake(128, 0, 64, 64)); + icon.image = [UIImage imageWithCGImage: img]; + CGImageRelease(img); + [view addSubview: icon]; + + r.origin.x = size.width / 40; + r.origin.y = size.height * 103 / 115; + r.size.width = size.width * 9 / 20; + r.size.height = size.height * 12 / 115; + + UIButton *btn = _ZBarButton(48, .85, .15, .15); + btn.frame = r; + btn.tag = BTN_GIVEUP; + [btn addTarget: self + action: @selector(buttonPressed:) + forControlEvents: UIControlEventTouchUpInside]; + [btn setTitle: @"Give Up" + forState: UIControlStateNormal]; + [view addSubview: btn]; + + btn = _ZBarButton(48, .1, .7, .1); + r.origin.x = size.width * 21 / 40; + btn.frame = r; + btn.tag = BTN_TRYAGAIN; + [btn addTarget: self + action: @selector(buttonPressed:) + forControlEvents: UIControlEventTouchUpInside]; + [btn setTitle: @"Try Again" + forState: UIControlStateNormal]; + [view addSubview: btn]; +} + +- (void) buttonPressed: (UIButton*) button +{ + int idx = button.tag; + [delegate actionSheet: (UIActionSheet*)self + clickedButtonAtIndex: idx]; + if(idx) + [self dismissModalViewControllerAnimated: YES]; +} + +@end diff --git a/iphone/ZBarReaderController.m b/iphone/ZBarReaderController.m new file mode 100644 index 0000000..352145f --- /dev/null +++ b/iphone/ZBarReaderController.m @@ -0,0 +1,326 @@ +//------------------------------------------------------------------------ +// Copyright 2009 (c) Jeff Brown +// +// 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 +#import + +#import +#import "ZBarHelpController.h" + +#define MIN_QUALITY 10 +#ifdef ZRC_DEBUG +# define zlog(fmt, ...) \ + NSLog(@"ZBarReaderController: " fmt , ##__VA_ARGS__) + +static inline long timer_now () +{ + struct tms now; + times(&now); + return(now.tms_utime + now.tms_stime); +} + +static inline double timer_elapsed (long start, long end) +{ + double clk_tck = sysconf(_SC_CLK_TCK); + if(!clk_tck) + return(-1); + return((end - start) / clk_tck); +} + +#else +# define zlog(...) +#endif + +NSString* const ZBarReaderControllerResults = @"ZBarReaderControllerResults"; + + +@implementation ZBarReaderController + +@synthesize readerDelegate, showsZBarControls, showsHelpOnFail; + +- (id) init +{ + if(self = [super init]) { + scanner = zbar_image_scanner_create(); + showsHelpOnFail = YES; + if([UIImagePickerController + isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]) + self.sourceType = UIImagePickerControllerSourceTypeCamera; + } + return(self); +} + +- (void) initOverlay +{ + CGRect r = self.view.bounds; + overlay = [[UIView new] initWithFrame: r]; + overlay.backgroundColor = [UIColor clearColor]; + + UIToolbar *toolbar = [UIToolbar new]; + toolbar.barStyle = UIBarStyleBlackOpaque; + [toolbar sizeToFit]; + r.origin.y = r.size.height - 56; + r.size.height = 56; + toolbar.frame = r; + [overlay addSubview: toolbar]; + [toolbar release]; + + UIButton *btn = _ZBarButton(48, .1, .7, .1); + btn.frame = CGRectMake(r.size.width / 4 + 4, r.origin.y + 4, + r.size.width / 2 - 8, 48); + [btn addTarget: self + action: @selector(takePicture) + forControlEvents: UIControlEventTouchDown]; + [btn setTitle: @"Scan!" + forState: UIControlStateNormal]; + [overlay addSubview: btn]; + + btn = _ZBarButton(40, .85, .15, .15); + btn.frame = CGRectMake(4, r.origin.y + 4, + r.size.width / 4 - 8, 48); + [btn addTarget: self + action: @selector(cancel) + forControlEvents: UIControlEventTouchUpInside]; + [btn setTitle: @"done" + forState: UIControlStateNormal]; + [overlay addSubview: btn]; +} + +- (void) viewDidLoad +{ + [super viewDidLoad]; + [super setDelegate: self]; + [self initOverlay]; +} + +- (void) cleanup +{ + [overlay release]; + overlay = nil; +} + +- (void) viewDidUnload +{ + [self cleanup]; + [super viewDidUnload]; +} + +- (void) dealloc +{ + [self cleanup]; + if(scanner) { + zbar_image_scanner_destroy(scanner); + scanner = NULL; + } + [super dealloc]; +} + +- (void) cancel +{ + [self performSelector: @selector(imagePickerControllerDidCancel:) + withObject: self + afterDelay: 0]; +} + +- (void) viewWillAppear: (BOOL) animated +{ + if(self.sourceType == UIImagePickerControllerSourceTypeCamera && + showsZBarControls) { + self.showsCameraControls = NO; + self.cameraOverlayView = overlay; + } + [super viewWillAppear: animated]; +} + +- (void) setDelegate: (id ) delegate +{ + // FIXME raise + assert(0); +} + +// image scanner config wrappers +- (void) parseConfig: (NSString*) cfg +{ + const char *str = [cfg UTF8String]; + zbar_image_scanner_parse_config(scanner, str); + // 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 +} + + +// scan UIImage and return something enumerable +- (id ) scanImage: (UIImage*) img +{ +#ifdef ZRC_DEBUG + long t_start = timer_now(); + zlog(@"captured image %gx%g\n", img.size.width, img.size.height); +#endif + + int w = img.size.width; + int h = img.size.height; + if(w > 1280 || h > 1280) { + w /= 2; + h /= 2; + } + long datalen = w * h; + uint8_t *raw = malloc(datalen); + // FIXME handle OOM + assert(raw); + + zbar_image_t *zimg = zbar_image_create(); + zbar_image_set_data(zimg, raw, datalen, zbar_image_free_data); + zbar_image_set_format(zimg, *(int*)"Y800"); + zbar_image_set_size(zimg, w, h); + + // generate grayscale image data + CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray(); + CGContextRef ctx = + CGBitmapContextCreate(raw, w, h, 8, w, cs, kCGImageAlphaNone); + CGColorSpaceRelease(cs); + CGContextSetAllowsAntialiasing(ctx, 0); + CGRect bbox = CGRectMake(0, 0, w, h); + CGContextDrawImage(ctx, bbox, img.CGImage); + CGContextRelease(ctx); + +#ifdef ZRC_DEBUG + long t_convert = timer_now(); + zlog(@" converted to %dx%d Y800 in +%gs\n", + w, h, timer_elapsed(t_start, t_convert)); +#endif + + // limit the maximum number of scan passes + int density; + if(w > 480) + density = (w / 240 + 1) / 2; + else + density = 1; + zbar_image_scanner_set_config(scanner, 0, ZBAR_CFG_X_DENSITY, density); + + if(h > 480) + density = (h / 240 + 1) / 2; + else + density = 1; + zbar_image_scanner_set_config(scanner, 0, ZBAR_CFG_Y_DENSITY, density); + + int nsyms = zbar_scan_image(scanner, zimg); + +#ifdef ZRC_DEBUG + long t_scan = timer_now(); + zlog(@" scanned %d raw symbols in +%gs\n", + nsyms, timer_elapsed(t_convert, t_scan)); +#endif + + NSMutableArray *syms = nil; + if(nsyms) { + // quality/type filtering + int max_quality = MIN_QUALITY; + const zbar_symbol_t *zsym = zbar_image_first_symbol(zimg); + assert(zsym); + for(; zsym; zsym = zbar_symbol_next(zsym)) { + if(zbar_symbol_get_count(zsym)) + continue; + + zbar_symbol_type_t type = zbar_symbol_get_type(zsym); + int quality; + if(type == ZBAR_QRCODE) + quality = INT_MAX; + else + quality = zbar_symbol_get_quality(zsym); + + 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]; + + ZBarSymbol *sym = [[ZBarSymbol alloc] initWithSymbol: zsym]; + [syms addObject: sym]; + [sym release]; + } + } + zbar_image_destroy(zimg); + +#ifdef ZRC_DEBUG + long t_end = timer_now(); + zlog(@"read %d filtered symbols in %gs total\n", + (!syms) ? 0 : [syms count], timer_elapsed(t_start, t_end)); +#endif + return(syms); +} + +- (void) imagePickerController: (UIImagePickerController*) picker + didFinishPickingMediaWithInfo: (NSDictionary*) info +{ + UIImage *img = [info objectForKey: UIImagePickerControllerOriginalImage]; + + id results = [self scanImage: img]; + if(results) { + NSMutableDictionary *newinfo = [info mutableCopy]; + [newinfo setObject: results + forKey: ZBarReaderControllerResults]; + [readerDelegate imagePickerController: self + didFinishPickingMediaWithInfo: newinfo]; + return; + } + + if(showsHelpOnFail) { + ZBarHelpController *help = [ZBarHelpController new]; + help.delegate = self; + [self presentModalViewController: help + animated: YES]; + [help release]; + } + + //[readerDelegate zbarReaderControllerDidFailToRead: self]; +} + +- (void) imagePickerControllerDidCancel: (UIImagePickerController*) picker +{ + [readerDelegate imagePickerControllerDidCancel: self]; +} + +- (void) actionSheet: (UIActionSheet*) sheet + clickedButtonAtIndex: (NSInteger) idx +{ + if(!idx) + [readerDelegate imagePickerControllerDidCancel: self]; +} + +@end diff --git a/iphone/ZBarSymbol.m b/iphone/ZBarSymbol.m new file mode 100644 index 0000000..af08f0e --- /dev/null +++ b/iphone/ZBarSymbol.m @@ -0,0 +1,70 @@ +//------------------------------------------------------------------------ +// Copyright 2009 (c) Jeff Brown +// +// 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 +#import + +@implementation ZBarSymbol + +@dynamic type, typeName, data, quality; + +- (id) initWithSymbol: (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 +{ + zbar_symbol_type_t type = zbar_symbol_get_type(symbol); + return([NSString stringWithUTF8String: zbar_get_symbol_name(type)]); +} + +- (NSString*) data +{ + return([NSString stringWithUTF8String: zbar_symbol_get_data(symbol)]); +} + +- (int) quality +{ + return(zbar_symbol_get_quality(symbol)); +} + +@end diff --git a/iphone/res/buttondown.svg b/iphone/res/buttondown.svg new file mode 100644 index 0000000..799d5fc --- /dev/null +++ b/iphone/res/buttondown.svg @@ -0,0 +1,57 @@ + + + + + + + + rounded button overlay + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iphone/res/buttonmask.svg b/iphone/res/buttonmask.svg new file mode 100644 index 0000000..55f0e29 --- /dev/null +++ b/iphone/res/buttonmask.svg @@ -0,0 +1,26 @@ + + + + + + + + mask for button overlays + + + + + + + diff --git a/iphone/res/buttonup.svg b/iphone/res/buttonup.svg new file mode 100644 index 0000000..861ca9a --- /dev/null +++ b/iphone/res/buttonup.svg @@ -0,0 +1,57 @@ + + + + + + + + rounded button overlay + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iphone/res/lightbulb.svg b/iphone/res/lightbulb.svg new file mode 100644 index 0000000..1f8628c --- /dev/null +++ b/iphone/res/lightbulb.svg @@ -0,0 +1,108 @@ + + + + + + + + lit light bulb icon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iphone/res/shakyhand.svg b/iphone/res/shakyhand.svg new file mode 100644 index 0000000..273efd0 --- /dev/null +++ b/iphone/res/shakyhand.svg @@ -0,0 +1,108 @@ + + + + + + + + unstable hand icon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iphone/res/stopwatch.svg b/iphone/res/stopwatch.svg new file mode 100644 index 0000000..186f2e9 --- /dev/null +++ b/iphone/res/stopwatch.svg @@ -0,0 +1,88 @@ + + + + + + + + stopwatch icon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iphone/res/zbar-button.png b/iphone/res/zbar-button.png new file mode 100644 index 0000000000000000000000000000000000000000..82311746eea90359fbc7addb29aeed006fc075dc GIT binary patch literal 2536 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 Date: Thu, 5 Nov 2009 12:49:17 -0500 Subject: [PATCH 166/328] iphone cleanup and add project --- .hgignore | 2 + include/zbar/ZBarReaderController.h | 20 +- iphone/ZBarHelpController.h | 8 +- iphone/ZBarHelpController.m | 40 ++- iphone/ZBarReaderController.m | 150 +++++---- iphone/prefix.pch | 5 + iphone/zbar.xcodeproj/project.pbxproj | 422 ++++++++++++++++++++++++++ 7 files changed, 561 insertions(+), 86 deletions(-) create mode 100644 iphone/prefix.pch create mode 100644 iphone/zbar.xcodeproj/project.pbxproj diff --git a/.hgignore b/.hgignore index b00bc3c..1771017 100644 --- a/.hgignore +++ b/.hgignore @@ -19,3 +19,5 @@ libtool ltmain.sh autom4te.cache missing +iphone/build +.DS_Store diff --git a/include/zbar/ZBarReaderController.h b/include/zbar/ZBarReaderController.h index 576ad8b..46d0dea 100644 --- a/include/zbar/ZBarReaderController.h +++ b/include/zbar/ZBarReaderController.h @@ -23,28 +23,34 @@ #import #import -#import #import +@class ZBarReaderController, ZBarHelpController; + @protocol ZBarReaderDelegate + +@optional +- (void) zbarReaderControllerDidFailToRead: (ZBarReaderController*) reader; + @end + @interface ZBarReaderController : UIImagePickerController < UINavigationControllerDelegate, - UIImagePickerControllerDelegate, - UIActionSheetDelegate > + UIImagePickerControllerDelegate > { zbar_image_scanner_t *scanner; - UIViewController *picker; - UIView *overlay; + ZBarHelpController *help; + UIView *overlay, *controls; id readerDelegate; BOOL showsZBarControls, showsHelpOnFail; } +// barcode result recipient @property (nonatomic, assign) id readerDelegate; -// whether to use alternate control set +// whether to use alternate control set (FIXME broken for NO) @property (nonatomic) BOOL showsZBarControls; // whether to display helpful information when decoding fails @@ -56,7 +62,7 @@ config: (zbar_config_t) config to: (int) value; -// direct scanner interface +// direct scanner interface - scan UIImage and return something enumerable - (id ) scanImage: (UIImage*) img; @end diff --git a/iphone/ZBarHelpController.h b/iphone/ZBarHelpController.h index da02d10..12f8d9b 100644 --- a/iphone/ZBarHelpController.h +++ b/iphone/ZBarHelpController.h @@ -27,11 +27,11 @@ @interface ZBarHelpController : UIViewController { - id delegate; + id delegate; } -@property (nonatomic, assign) id delegate; - -extern UIButton *_ZBarButton (CGFloat size, CGFloat r, CGFloat g, CGFloat b); +@property (nonatomic, assign) id delegate; @end + +extern UIButton *_ZBarButton (CGFloat size, CGFloat r, CGFloat g, CGFloat b); diff --git a/iphone/ZBarHelpController.m b/iphone/ZBarHelpController.m index e0cd370..137b44d 100644 --- a/iphone/ZBarHelpController.m +++ b/iphone/ZBarHelpController.m @@ -23,7 +23,15 @@ #import "ZBarHelpController.h" -enum { BTN_GIVEUP, BTN_TRYAGAIN }; +@interface NSObject (ZBarHelpControllerDelegate) + +- (void) helpController: (ZBarHelpController*) help + clickedButtonAtIndex: (NSInteger) index; + +@end + + +enum { BTN_TRYAGAIN = 1 }; UIButton *_ZBarButton (CGFloat size, CGFloat red, @@ -192,7 +200,7 @@ - (void) viewDidLoad font: smallFont]; r.origin.x = size.width / 20; - r.size.width = r.size.height = size.height * 16 / 115; + r.size.width = r.size.height = 64; UIImage *iconset = [UIImage imageNamed: @"zbar-helpicons.png"]; CGImageRef setimg = iconset.CGImage; @@ -204,6 +212,7 @@ - (void) viewDidLoad icon.image = [UIImage imageWithCGImage: img]; CGImageRelease(img); [view addSubview: icon]; + [icon release]; r.origin.y = size.height * 55 / 115; icon = [[UIImageView alloc] initWithFrame: r]; @@ -211,6 +220,7 @@ - (void) viewDidLoad icon.image = [UIImage imageWithCGImage: img]; CGImageRelease(img); [view addSubview: icon]; + [icon release]; r.origin.y = size.height * 79 / 115; icon = [[UIImageView alloc] initWithFrame: r]; @@ -218,25 +228,11 @@ - (void) viewDidLoad icon.image = [UIImage imageWithCGImage: img]; CGImageRelease(img); [view addSubview: icon]; + [icon release]; - r.origin.x = size.width / 40; - r.origin.y = size.height * 103 / 115; - r.size.width = size.width * 9 / 20; - r.size.height = size.height * 12 / 115; - - UIButton *btn = _ZBarButton(48, .85, .15, .15); - btn.frame = r; - btn.tag = BTN_GIVEUP; - [btn addTarget: self - action: @selector(buttonPressed:) - forControlEvents: UIControlEventTouchUpInside]; - [btn setTitle: @"Give Up" - forState: UIControlStateNormal]; - [view addSubview: btn]; - - btn = _ZBarButton(48, .1, .7, .1); - r.origin.x = size.width * 21 / 40; - btn.frame = r; + UIButton *btn = _ZBarButton(48, .1, .7, .1); + btn.frame = CGRectMake(size.width / 4 + 4, size.height - 52, + size.width / 2 - 8, 48); btn.tag = BTN_TRYAGAIN; [btn addTarget: self action: @selector(buttonPressed:) @@ -249,10 +245,8 @@ - (void) viewDidLoad - (void) buttonPressed: (UIButton*) button { int idx = button.tag; - [delegate actionSheet: (UIActionSheet*)self + [delegate helpController: self clickedButtonAtIndex: idx]; - if(idx) - [self dismissModalViewControllerAnimated: YES]; } @end diff --git a/iphone/ZBarReaderController.m b/iphone/ZBarReaderController.m index 352145f..7c376a0 100644 --- a/iphone/ZBarReaderController.m +++ b/iphone/ZBarReaderController.m @@ -63,6 +63,7 @@ - (id) init if(self = [super init]) { scanner = zbar_image_scanner_create(); showsHelpOnFail = YES; + showsZBarControls = YES; if([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]) self.sourceType = UIImagePickerControllerSourceTypeCamera; @@ -73,37 +74,43 @@ - (id) init - (void) initOverlay { CGRect r = self.view.bounds; - overlay = [[UIView new] initWithFrame: r]; + overlay = [[UIView alloc] initWithFrame: r]; overlay.backgroundColor = [UIColor clearColor]; + controls = [UIView new]; + UIToolbar *toolbar = [UIToolbar new]; toolbar.barStyle = UIBarStyleBlackOpaque; [toolbar sizeToFit]; r.origin.y = r.size.height - 56; r.size.height = 56; + controls.frame = r; + r.origin.y = r.origin.x = 0; toolbar.frame = r; - [overlay addSubview: toolbar]; + [controls addSubview: toolbar]; [toolbar release]; UIButton *btn = _ZBarButton(48, .1, .7, .1); - btn.frame = CGRectMake(r.size.width / 4 + 4, r.origin.y + 4, + btn.frame = CGRectMake(r.size.width / 4 + 4, 4, r.size.width / 2 - 8, 48); [btn addTarget: self action: @selector(takePicture) forControlEvents: UIControlEventTouchDown]; [btn setTitle: @"Scan!" forState: UIControlStateNormal]; - [overlay addSubview: btn]; + [controls addSubview: btn]; btn = _ZBarButton(40, .85, .15, .15); - btn.frame = CGRectMake(4, r.origin.y + 4, - r.size.width / 4 - 8, 48); + btn.frame = CGRectMake(4, 4, r.size.width / 4 - 8, 48); [btn addTarget: self action: @selector(cancel) forControlEvents: UIControlEventTouchUpInside]; [btn setTitle: @"done" forState: UIControlStateNormal]; - [overlay addSubview: btn]; + [controls addSubview: btn]; + + controls.hidden = YES; + [overlay addSubview: controls]; } - (void) viewDidLoad @@ -117,6 +124,10 @@ - (void) cleanup { [overlay release]; overlay = nil; + [controls release]; + controls = nil; + [help release]; + help = nil; } - (void) viewDidUnload @@ -139,24 +150,97 @@ - (void) cancel { [self performSelector: @selector(imagePickerControllerDidCancel:) withObject: self - afterDelay: 0]; + afterDelay: 0.1]; } - (void) viewWillAppear: (BOOL) animated { - if(self.sourceType == UIImagePickerControllerSourceTypeCamera && - showsZBarControls) { - self.showsCameraControls = NO; - self.cameraOverlayView = overlay; + if(help) { + [help.view removeFromSuperview]; + [help release]; + help = nil; + } + + if(self.sourceType == UIImagePickerControllerSourceTypeCamera) { + if(showsZBarControls || !self.cameraOverlayView) + self.cameraOverlayView = overlay; + self.showsCameraControls = !showsZBarControls; + controls.hidden = !showsZBarControls; } [super viewWillAppear: animated]; } +- (void) imagePickerController: (UIImagePickerController*) picker + didFinishPickingMediaWithInfo: (NSDictionary*) info +{ + UIImage *img = [info objectForKey: UIImagePickerControllerOriginalImage]; + + id results = [self scanImage: img]; + 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; + } + + if(showsHelpOnFail) { + help = [ZBarHelpController new]; + help.delegate = self; + + if(self.sourceType == UIImagePickerControllerSourceTypeCamera) { + help.wantsFullScreenLayout = YES; + help.view.alpha = 0; + [self.cameraOverlayView addSubview: help.view]; + [UIView beginAnimations: @"ZBarHelp" + context: nil]; + help.view.alpha = 1; + [UIView commitAnimations]; + } + else + [self presentModalViewController: help + animated: YES]; + } + + SEL cb = @selector(zbarReaderControllerDidFailToRead:); + if([readerDelegate respondsToSelector: cb]) + [readerDelegate zbarReaderControllerDidFailToRead: self]; +} + +- (void) imagePickerControllerDidCancel: (UIImagePickerController*) picker +{ + SEL cb = @selector(imagePickerControllerDidCancel:); + if([readerDelegate respondsToSelector: cb]) + [readerDelegate imagePickerControllerDidCancel: self]; + else + [self dismissModalViewControllerAnimated: YES]; +} + +- (void) helpController: (ZBarHelpController*) hlp + clickedButtonAtIndex: (NSInteger) idx +{ + if(self.sourceType == UIImagePickerControllerSourceTypeCamera) { + [UIView beginAnimations: @"ZBarHelp" + context: nil]; + hlp.view.alpha = 0; + [UIView commitAnimations]; + } + else + [hlp dismissModalViewControllerAnimated: YES]; +} + +// intercept delegate as readerDelegate + - (void) setDelegate: (id ) delegate { - // FIXME raise - assert(0); + self.readerDelegate = (id )delegate; } // image scanner config wrappers @@ -285,42 +369,4 @@ - (void) setSymbology: (zbar_symbol_type_t) sym return(syms); } -- (void) imagePickerController: (UIImagePickerController*) picker - didFinishPickingMediaWithInfo: (NSDictionary*) info -{ - UIImage *img = [info objectForKey: UIImagePickerControllerOriginalImage]; - - id results = [self scanImage: img]; - if(results) { - NSMutableDictionary *newinfo = [info mutableCopy]; - [newinfo setObject: results - forKey: ZBarReaderControllerResults]; - [readerDelegate imagePickerController: self - didFinishPickingMediaWithInfo: newinfo]; - return; - } - - if(showsHelpOnFail) { - ZBarHelpController *help = [ZBarHelpController new]; - help.delegate = self; - [self presentModalViewController: help - animated: YES]; - [help release]; - } - - //[readerDelegate zbarReaderControllerDidFailToRead: self]; -} - -- (void) imagePickerControllerDidCancel: (UIImagePickerController*) picker -{ - [readerDelegate imagePickerControllerDidCancel: self]; -} - -- (void) actionSheet: (UIActionSheet*) sheet - clickedButtonAtIndex: (NSInteger) idx -{ - if(!idx) - [readerDelegate imagePickerControllerDidCancel: self]; -} - @end diff --git a/iphone/prefix.pch b/iphone/prefix.pch new file mode 100644 index 0000000..bb09ddd --- /dev/null +++ b/iphone/prefix.pch @@ -0,0 +1,5 @@ +#ifdef __OBJC__ +# import +# import +# import +#endif diff --git a/iphone/zbar.xcodeproj/project.pbxproj b/iphone/zbar.xcodeproj/project.pbxproj new file mode 100644 index 0000000..7eb13d9 --- /dev/null +++ b/iphone/zbar.xcodeproj/project.pbxproj @@ -0,0 +1,422 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 45; + objects = { + +/* Begin PBXBuildFile section */ + AA747D9F0F9514B9006C5449 /* prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = AA747D9E0F9514B9006C5449 /* prefix.pch */; }; + DC67C11210A079E40033B702 /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C11110A079E40033B702 /* config.h */; }; + DC67C11810A07A810033B702 /* zbar.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C11710A07A810033B702 /* zbar.h */; }; + DC67C11B10A07A950033B702 /* ZBarReaderController.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C11910A07A950033B702 /* ZBarReaderController.h */; }; + DC67C11C10A07A950033B702 /* ZBarSymbol.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C11A10A07A950033B702 /* ZBarSymbol.h */; }; + DC67C17110A07AD30033B702 /* config.c in Sources */ = {isa = PBXBuildFile; fileRef = DC67C11F10A07AD30033B702 /* config.c */; }; + DC67C17310A07AD30033B702 /* debug.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C12110A07AD30033B702 /* debug.h */; }; + DC67C17410A07AD30033B702 /* code128.c in Sources */ = {isa = PBXBuildFile; fileRef = DC67C12310A07AD30033B702 /* code128.c */; }; + DC67C17510A07AD30033B702 /* code128.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C12410A07AD30033B702 /* code128.h */; }; + DC67C17610A07AD30033B702 /* code39.c in Sources */ = {isa = PBXBuildFile; fileRef = DC67C12510A07AD30033B702 /* code39.c */; }; + DC67C17710A07AD30033B702 /* code39.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C12610A07AD30033B702 /* code39.h */; }; + DC67C17810A07AD30033B702 /* ean.c in Sources */ = {isa = PBXBuildFile; fileRef = DC67C12710A07AD30033B702 /* ean.c */; }; + DC67C17910A07AD30033B702 /* ean.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C12810A07AD30033B702 /* ean.h */; }; + DC67C17A10A07AD30033B702 /* i25.c in Sources */ = {isa = PBXBuildFile; fileRef = DC67C12910A07AD30033B702 /* i25.c */; }; + DC67C17B10A07AD30033B702 /* i25.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C12A10A07AD30033B702 /* i25.h */; }; + DC67C17F10A07AD30033B702 /* qr_finder.c in Sources */ = {isa = PBXBuildFile; fileRef = DC67C12E10A07AD30033B702 /* qr_finder.c */; }; + DC67C18010A07AD30033B702 /* qr_finder.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C12F10A07AD30033B702 /* qr_finder.h */; }; + DC67C18110A07AD30033B702 /* decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = DC67C13010A07AD30033B702 /* decoder.c */; }; + DC67C18210A07AD30033B702 /* decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C13110A07AD30033B702 /* decoder.h */; }; + DC67C18310A07AD30033B702 /* error.c in Sources */ = {isa = PBXBuildFile; fileRef = DC67C13210A07AD30033B702 /* error.c */; }; + DC67C18410A07AD30033B702 /* error.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C13310A07AD30033B702 /* error.h */; }; + DC67C18610A07AD30033B702 /* image.c in Sources */ = {isa = PBXBuildFile; fileRef = DC67C13510A07AD30033B702 /* image.c */; }; + DC67C18710A07AD30033B702 /* image.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C13610A07AD30033B702 /* image.h */; }; + DC67C18810A07AD30033B702 /* img_scanner.c in Sources */ = {isa = PBXBuildFile; fileRef = DC67C13710A07AD30033B702 /* img_scanner.c */; }; + DC67C18910A07AD30033B702 /* img_scanner.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C13810A07AD30033B702 /* img_scanner.h */; }; + DC67C19510A07AD30033B702 /* bch15_5.c in Sources */ = {isa = PBXBuildFile; fileRef = DC67C14710A07AD30033B702 /* bch15_5.c */; }; + DC67C19610A07AD30033B702 /* bch15_5.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C14810A07AD30033B702 /* bch15_5.h */; }; + DC67C19710A07AD30033B702 /* binarize.c in Sources */ = {isa = PBXBuildFile; fileRef = DC67C14910A07AD30033B702 /* binarize.c */; }; + DC67C19810A07AD30033B702 /* binarize.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C14A10A07AD30033B702 /* binarize.h */; }; + DC67C19910A07AD30033B702 /* isaac.c in Sources */ = {isa = PBXBuildFile; fileRef = DC67C14B10A07AD30033B702 /* isaac.c */; }; + DC67C19A10A07AD30033B702 /* isaac.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C14C10A07AD30033B702 /* isaac.h */; }; + DC67C19B10A07AD30033B702 /* qrdec.c in Sources */ = {isa = PBXBuildFile; fileRef = DC67C14D10A07AD30033B702 /* qrdec.c */; }; + DC67C19C10A07AD30033B702 /* qrdec.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C14E10A07AD30033B702 /* qrdec.h */; }; + DC67C19D10A07AD30033B702 /* qrdectxt.c in Sources */ = {isa = PBXBuildFile; fileRef = DC67C14F10A07AD30033B702 /* qrdectxt.c */; }; + DC67C19E10A07AD30033B702 /* rs.c in Sources */ = {isa = PBXBuildFile; fileRef = DC67C15010A07AD30033B702 /* rs.c */; }; + DC67C19F10A07AD30033B702 /* rs.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C15110A07AD30033B702 /* rs.h */; }; + DC67C1A010A07AD30033B702 /* util.c in Sources */ = {isa = PBXBuildFile; fileRef = DC67C15210A07AD30033B702 /* util.c */; }; + DC67C1A110A07AD30033B702 /* util.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C15310A07AD30033B702 /* util.h */; }; + DC67C1A210A07AD30033B702 /* qrcode.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C15410A07AD30033B702 /* qrcode.h */; }; + DC67C1A310A07AD30033B702 /* refcnt.c in Sources */ = {isa = PBXBuildFile; fileRef = DC67C15510A07AD30033B702 /* refcnt.c */; }; + DC67C1A410A07AD30033B702 /* refcnt.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C15610A07AD30033B702 /* refcnt.h */; }; + DC67C1A510A07AD30033B702 /* scanner.c in Sources */ = {isa = PBXBuildFile; fileRef = DC67C15710A07AD30033B702 /* scanner.c */; }; + DC67C1A810A07AD30033B702 /* symbol.c in Sources */ = {isa = PBXBuildFile; fileRef = DC67C15A10A07AD30033B702 /* symbol.c */; }; + DC67C1A910A07AD30033B702 /* symbol.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C15B10A07AD30033B702 /* symbol.h */; }; + DC67C1C110A07B6B0033B702 /* ZBarHelpController.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C1BD10A07B6B0033B702 /* ZBarHelpController.h */; }; + DC67C1C210A07B6B0033B702 /* ZBarHelpController.m in Sources */ = {isa = PBXBuildFile; fileRef = DC67C1BE10A07B6B0033B702 /* ZBarHelpController.m */; }; + DC67C1C310A07B6B0033B702 /* ZBarReaderController.m in Sources */ = {isa = PBXBuildFile; fileRef = DC67C1BF10A07B6B0033B702 /* ZBarReaderController.m */; }; + DC67C1C410A07B6B0033B702 /* ZBarSymbol.m in Sources */ = {isa = PBXBuildFile; fileRef = DC67C1C010A07B6B0033B702 /* ZBarSymbol.m */; }; + DC67C1CC10A07BEE0033B702 /* svg.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C1CB10A07BEE0033B702 /* svg.h */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + AA747D9E0F9514B9006C5449 /* prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = prefix.pch; sourceTree = ""; }; + AACBBE490F95108600F1A2B1 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + D2AAC07E0554694100DB518D /* libzbar.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libzbar.a; sourceTree = BUILT_PRODUCTS_DIR; }; + DC67C08210A079BE0033B702 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + DC67C11110A079E40033B702 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = ""; }; + DC67C11710A07A810033B702 /* zbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = zbar.h; path = ../include/zbar.h; sourceTree = SOURCE_ROOT; }; + DC67C11910A07A950033B702 /* ZBarReaderController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ZBarReaderController.h; path = ../include/zbar/ZBarReaderController.h; sourceTree = SOURCE_ROOT; }; + DC67C11A10A07A950033B702 /* ZBarSymbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ZBarSymbol.h; path = ../include/zbar/ZBarSymbol.h; sourceTree = SOURCE_ROOT; }; + DC67C11F10A07AD30033B702 /* config.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = config.c; sourceTree = ""; }; + DC67C12110A07AD30033B702 /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = ""; }; + DC67C12310A07AD30033B702 /* code128.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = code128.c; sourceTree = ""; }; + DC67C12410A07AD30033B702 /* code128.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = code128.h; sourceTree = ""; }; + DC67C12510A07AD30033B702 /* code39.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = code39.c; sourceTree = ""; }; + DC67C12610A07AD30033B702 /* code39.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = code39.h; sourceTree = ""; }; + DC67C12710A07AD30033B702 /* ean.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ean.c; sourceTree = ""; }; + DC67C12810A07AD30033B702 /* ean.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ean.h; sourceTree = ""; }; + DC67C12910A07AD30033B702 /* i25.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = i25.c; sourceTree = ""; }; + DC67C12A10A07AD30033B702 /* i25.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = i25.h; sourceTree = ""; }; + DC67C12E10A07AD30033B702 /* qr_finder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = qr_finder.c; sourceTree = ""; }; + DC67C12F10A07AD30033B702 /* qr_finder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = qr_finder.h; sourceTree = ""; }; + DC67C13010A07AD30033B702 /* decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = decoder.c; sourceTree = ""; }; + DC67C13110A07AD30033B702 /* decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = decoder.h; sourceTree = ""; }; + DC67C13210A07AD30033B702 /* error.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = error.c; sourceTree = ""; }; + DC67C13310A07AD30033B702 /* error.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = error.h; sourceTree = ""; }; + DC67C13510A07AD30033B702 /* image.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = image.c; sourceTree = ""; }; + DC67C13610A07AD30033B702 /* image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = image.h; sourceTree = ""; }; + DC67C13710A07AD30033B702 /* img_scanner.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = img_scanner.c; sourceTree = ""; }; + DC67C13810A07AD30033B702 /* img_scanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = img_scanner.h; sourceTree = ""; }; + DC67C14710A07AD30033B702 /* bch15_5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bch15_5.c; sourceTree = ""; }; + DC67C14810A07AD30033B702 /* bch15_5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bch15_5.h; sourceTree = ""; }; + DC67C14910A07AD30033B702 /* binarize.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = binarize.c; sourceTree = ""; }; + DC67C14A10A07AD30033B702 /* binarize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = binarize.h; sourceTree = ""; }; + DC67C14B10A07AD30033B702 /* isaac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = isaac.c; sourceTree = ""; }; + DC67C14C10A07AD30033B702 /* isaac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = isaac.h; sourceTree = ""; }; + DC67C14D10A07AD30033B702 /* qrdec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = qrdec.c; sourceTree = ""; }; + DC67C14E10A07AD30033B702 /* qrdec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = qrdec.h; sourceTree = ""; }; + DC67C14F10A07AD30033B702 /* qrdectxt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = qrdectxt.c; sourceTree = ""; }; + DC67C15010A07AD30033B702 /* rs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rs.c; sourceTree = ""; }; + DC67C15110A07AD30033B702 /* rs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rs.h; sourceTree = ""; }; + DC67C15210A07AD30033B702 /* util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = util.c; sourceTree = ""; }; + DC67C15310A07AD30033B702 /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = util.h; sourceTree = ""; }; + DC67C15410A07AD30033B702 /* qrcode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = qrcode.h; sourceTree = ""; }; + DC67C15510A07AD30033B702 /* refcnt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = refcnt.c; sourceTree = ""; }; + DC67C15610A07AD30033B702 /* refcnt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = refcnt.h; sourceTree = ""; }; + DC67C15710A07AD30033B702 /* scanner.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scanner.c; sourceTree = ""; }; + DC67C15A10A07AD30033B702 /* symbol.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = symbol.c; sourceTree = ""; }; + DC67C15B10A07AD30033B702 /* symbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = symbol.h; sourceTree = ""; }; + DC67C1BD10A07B6B0033B702 /* ZBarHelpController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarHelpController.h; sourceTree = ""; }; + DC67C1BE10A07B6B0033B702 /* ZBarHelpController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarHelpController.m; sourceTree = ""; }; + DC67C1BF10A07B6B0033B702 /* ZBarReaderController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarReaderController.m; sourceTree = ""; }; + DC67C1C010A07B6B0033B702 /* ZBarSymbol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarSymbol.m; sourceTree = ""; }; + DC67C1CB10A07BEE0033B702 /* svg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = svg.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + D2AAC07C0554694100DB518D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 034768DFFF38A50411DB9C8B /* Products */ = { + isa = PBXGroup; + children = ( + D2AAC07E0554694100DB518D /* libzbar.a */, + ); + name = Products; + sourceTree = ""; + }; + 0867D691FE84028FC02AAC07 /* zbar */ = { + isa = PBXGroup; + children = ( + DC67C1BD10A07B6B0033B702 /* ZBarHelpController.h */, + DC67C1BE10A07B6B0033B702 /* ZBarHelpController.m */, + DC67C1BF10A07B6B0033B702 /* ZBarReaderController.m */, + DC67C1C010A07B6B0033B702 /* ZBarSymbol.m */, + DC67C11610A07A670033B702 /* include */, + DC67C11E10A07AD30033B702 /* zbar */, + 0867D69AFE84028FC02AAC07 /* Frameworks */, + 034768DFFF38A50411DB9C8B /* Products */, + ); + name = zbar; + sourceTree = ""; + }; + 0867D69AFE84028FC02AAC07 /* Frameworks */ = { + isa = PBXGroup; + children = ( + AACBBE490F95108600F1A2B1 /* Foundation.framework */, + DC67C08210A079BE0033B702 /* UIKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + DC67C11610A07A670033B702 /* include */ = { + isa = PBXGroup; + children = ( + AA747D9E0F9514B9006C5449 /* prefix.pch */, + DC67C11110A079E40033B702 /* config.h */, + DC67C11710A07A810033B702 /* zbar.h */, + DC67C11A10A07A950033B702 /* ZBarSymbol.h */, + DC67C11910A07A950033B702 /* ZBarReaderController.h */, + ); + name = include; + sourceTree = ""; + }; + DC67C11E10A07AD30033B702 /* zbar */ = { + isa = PBXGroup; + children = ( + DC67C11F10A07AD30033B702 /* config.c */, + DC67C12110A07AD30033B702 /* debug.h */, + DC67C12210A07AD30033B702 /* decoder */, + DC67C13010A07AD30033B702 /* decoder.c */, + DC67C13110A07AD30033B702 /* decoder.h */, + DC67C13210A07AD30033B702 /* error.c */, + DC67C13310A07AD30033B702 /* error.h */, + DC67C13510A07AD30033B702 /* image.c */, + DC67C13610A07AD30033B702 /* image.h */, + DC67C13710A07AD30033B702 /* img_scanner.c */, + DC67C13810A07AD30033B702 /* img_scanner.h */, + DC67C14610A07AD30033B702 /* qrcode */, + DC67C15410A07AD30033B702 /* qrcode.h */, + DC67C15510A07AD30033B702 /* refcnt.c */, + DC67C15610A07AD30033B702 /* refcnt.h */, + DC67C15710A07AD30033B702 /* scanner.c */, + DC67C1CB10A07BEE0033B702 /* svg.h */, + DC67C15A10A07AD30033B702 /* symbol.c */, + DC67C15B10A07AD30033B702 /* symbol.h */, + ); + name = zbar; + path = ../zbar; + sourceTree = SOURCE_ROOT; + }; + DC67C12210A07AD30033B702 /* decoder */ = { + isa = PBXGroup; + children = ( + DC67C12310A07AD30033B702 /* code128.c */, + DC67C12410A07AD30033B702 /* code128.h */, + DC67C12510A07AD30033B702 /* code39.c */, + DC67C12610A07AD30033B702 /* code39.h */, + DC67C12710A07AD30033B702 /* ean.c */, + DC67C12810A07AD30033B702 /* ean.h */, + DC67C12910A07AD30033B702 /* i25.c */, + DC67C12A10A07AD30033B702 /* i25.h */, + DC67C12E10A07AD30033B702 /* qr_finder.c */, + DC67C12F10A07AD30033B702 /* qr_finder.h */, + ); + path = decoder; + sourceTree = ""; + }; + DC67C14610A07AD30033B702 /* qrcode */ = { + isa = PBXGroup; + children = ( + DC67C14710A07AD30033B702 /* bch15_5.c */, + DC67C14810A07AD30033B702 /* bch15_5.h */, + DC67C14910A07AD30033B702 /* binarize.c */, + DC67C14A10A07AD30033B702 /* binarize.h */, + DC67C14B10A07AD30033B702 /* isaac.c */, + DC67C14C10A07AD30033B702 /* isaac.h */, + DC67C14D10A07AD30033B702 /* qrdec.c */, + DC67C14E10A07AD30033B702 /* qrdec.h */, + DC67C14F10A07AD30033B702 /* qrdectxt.c */, + DC67C15010A07AD30033B702 /* rs.c */, + DC67C15110A07AD30033B702 /* rs.h */, + DC67C15210A07AD30033B702 /* util.c */, + DC67C15310A07AD30033B702 /* util.h */, + ); + path = qrcode; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + D2AAC07A0554694100DB518D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + AA747D9F0F9514B9006C5449 /* prefix.pch in Headers */, + DC67C11210A079E40033B702 /* config.h in Headers */, + DC67C11810A07A810033B702 /* zbar.h in Headers */, + DC67C11B10A07A950033B702 /* ZBarReaderController.h in Headers */, + DC67C11C10A07A950033B702 /* ZBarSymbol.h in Headers */, + DC67C17310A07AD30033B702 /* debug.h in Headers */, + DC67C17510A07AD30033B702 /* code128.h in Headers */, + DC67C17710A07AD30033B702 /* code39.h in Headers */, + DC67C17910A07AD30033B702 /* ean.h in Headers */, + DC67C17B10A07AD30033B702 /* i25.h in Headers */, + DC67C18010A07AD30033B702 /* qr_finder.h in Headers */, + DC67C18210A07AD30033B702 /* decoder.h in Headers */, + DC67C18410A07AD30033B702 /* error.h in Headers */, + DC67C18710A07AD30033B702 /* image.h in Headers */, + DC67C18910A07AD30033B702 /* img_scanner.h in Headers */, + DC67C19610A07AD30033B702 /* bch15_5.h in Headers */, + DC67C19810A07AD30033B702 /* binarize.h in Headers */, + DC67C19A10A07AD30033B702 /* isaac.h in Headers */, + DC67C19C10A07AD30033B702 /* qrdec.h in Headers */, + DC67C19F10A07AD30033B702 /* rs.h in Headers */, + DC67C1A110A07AD30033B702 /* util.h in Headers */, + DC67C1A210A07AD30033B702 /* qrcode.h in Headers */, + DC67C1A410A07AD30033B702 /* refcnt.h in Headers */, + DC67C1A910A07AD30033B702 /* symbol.h in Headers */, + DC67C1C110A07B6B0033B702 /* ZBarHelpController.h in Headers */, + DC67C1CC10A07BEE0033B702 /* svg.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + D2AAC07D0554694100DB518D /* zbar */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB921E08733DC00010E9CD /* Build configuration list for PBXNativeTarget "zbar" */; + buildPhases = ( + D2AAC07A0554694100DB518D /* Headers */, + D2AAC07B0554694100DB518D /* Sources */, + D2AAC07C0554694100DB518D /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = zbar; + productName = zbar; + productReference = D2AAC07E0554694100DB518D /* libzbar.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 0867D690FE84028FC02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "zbar" */; + compatibilityVersion = "Xcode 3.1"; + hasScannedForEncodings = 1; + mainGroup = 0867D691FE84028FC02AAC07 /* zbar */; + productRefGroup = 034768DFFF38A50411DB9C8B /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + D2AAC07D0554694100DB518D /* zbar */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + D2AAC07B0554694100DB518D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DC67C17110A07AD30033B702 /* config.c in Sources */, + DC67C17410A07AD30033B702 /* code128.c in Sources */, + DC67C17610A07AD30033B702 /* code39.c in Sources */, + DC67C17810A07AD30033B702 /* ean.c in Sources */, + DC67C17A10A07AD30033B702 /* i25.c in Sources */, + DC67C17F10A07AD30033B702 /* qr_finder.c in Sources */, + DC67C18110A07AD30033B702 /* decoder.c in Sources */, + DC67C18310A07AD30033B702 /* error.c in Sources */, + DC67C18610A07AD30033B702 /* image.c in Sources */, + DC67C18810A07AD30033B702 /* img_scanner.c in Sources */, + DC67C19510A07AD30033B702 /* bch15_5.c in Sources */, + DC67C19710A07AD30033B702 /* binarize.c in Sources */, + DC67C19910A07AD30033B702 /* isaac.c in Sources */, + DC67C19B10A07AD30033B702 /* qrdec.c in Sources */, + DC67C19D10A07AD30033B702 /* qrdectxt.c in Sources */, + DC67C19E10A07AD30033B702 /* rs.c in Sources */, + DC67C1A010A07AD30033B702 /* util.c in Sources */, + DC67C1A310A07AD30033B702 /* refcnt.c in Sources */, + DC67C1A510A07AD30033B702 /* scanner.c in Sources */, + DC67C1A810A07AD30033B702 /* symbol.c in Sources */, + DC67C1C210A07B6B0033B702 /* ZBarHelpController.m in Sources */, + DC67C1C310A07B6B0033B702 /* ZBarReaderController.m in Sources */, + DC67C1C410A07B6B0033B702 /* ZBarSymbol.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1DEB921F08733DC00010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = prefix.pch; + PRODUCT_NAME = zbar; + }; + name = Debug; + }; + 1DEB922008733DC00010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = prefix.pch; + PRODUCT_NAME = zbar; + }; + name = Release; + }; + 1DEB922308733DC00010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_LDFLAGS = "-ObjC"; + PREBINDING = NO; + SDKROOT = iphoneos3.1.2; + }; + name = Debug; + }; + 1DEB922408733DC00010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_LDFLAGS = "-ObjC"; + PREBINDING = NO; + SDKROOT = iphoneos3.1.2; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB921E08733DC00010E9CD /* Build configuration list for PBXNativeTarget "zbar" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB921F08733DC00010E9CD /* Debug */, + 1DEB922008733DC00010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "zbar" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB922308733DC00010E9CD /* Debug */, + 1DEB922408733DC00010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 0867D690FE84028FC02AAC07 /* Project object */; +} From 716538f0b48f14843b2c97ba96b6567b176dcdb7 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 5 Nov 2009 12:52:30 -0500 Subject: [PATCH 167/328] add missing iphone/config.h --- .hgignore | 2 +- iphone/config.h | 225 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 226 insertions(+), 1 deletion(-) create mode 100644 iphone/config.h diff --git a/.hgignore b/.hgignore index 1771017..538ef02 100644 --- a/.hgignore +++ b/.hgignore @@ -7,7 +7,7 @@ aclocal.m4 configure config config.guess -config.h +config/config.h config.h.in config.log config.status diff --git a/iphone/config.h b/iphone/config.h new file mode 100644 index 0000000..e3242f5 --- /dev/null +++ b/iphone/config.h @@ -0,0 +1,225 @@ +/* include/config.h.in. Generated from configure.ac by autoheader. */ + +/* whether to build support for Code 128 symbology */ +#define ENABLE_CODE128 1 + +/* whether to build support for Code 39 symbology */ +#define ENABLE_CODE39 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 header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the 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 header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the 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 header file. */ +#undef HAVE_LINUX_VIDEODEV2_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_VIDEODEV_H + +/* Define to 1 if you have the 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 header file. */ +#undef HAVE_POLL_H + +/* Define to 1 if you have the 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 header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_IPC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MMAN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SHM_H + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIMES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the 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 header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the header file. */ +#undef HAVE_VFW_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_X11_EXTENSIONS_XSHM_H + +/* Define to 1 if you have the 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 */ +#undef PACKAGE "zbar" + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT "spadix@users.sourceforge.net" + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME "zbar" + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING "zbar 0.10" + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME "zbar" + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION "0.10" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#undef 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 , + , or 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 , + , or 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 + From 46c22d0cbea0e7089ab508601dad600d8e674603 Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 9 Nov 2009 18:44:31 -0500 Subject: [PATCH 168/328] add python distutils build infrastructure --- .hgignore | 1 + ChangeLog | 1 + examples/paginate.pl | 71 --------------------- examples/processor.pl | 35 ---------- examples/read_one.pl | 29 --------- examples/scan_image.pl | 37 ----------- python/MANIFEST.in | 2 + python/README | 40 ++++++++++++ {examples => python/examples}/processor.py | 0 {examples => python/examples}/read_one.py | 0 {examples => python/examples}/scan_image.py | 0 python/setup.py | 44 +++++++++++++ 12 files changed, 88 insertions(+), 172 deletions(-) delete mode 100755 examples/paginate.pl delete mode 100755 examples/processor.pl delete mode 100755 examples/read_one.pl delete mode 100755 examples/scan_image.pl create mode 100644 python/MANIFEST.in create mode 100644 python/README rename {examples => python/examples}/processor.py (100%) rename {examples => python/examples}/read_one.py (100%) rename {examples => python/examples}/scan_image.py (100%) create mode 100755 python/setup.py diff --git a/.hgignore b/.hgignore index 538ef02..64e80d1 100644 --- a/.hgignore +++ b/.hgignore @@ -19,5 +19,6 @@ libtool ltmain.sh autom4te.cache missing +python/MANIFEST iphone/build .DS_Store diff --git a/ChangeLog b/ChangeLog index 0092f7b..95403d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * add python distutils build infrastructure * first pass working iPhone "widget" version 0.10: diff --git a/examples/paginate.pl b/examples/paginate.pl deleted file mode 100755 index 68ffe50..0000000 --- a/examples/paginate.pl +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/perl -#------------------------------------------------------------------------ -# Copyright 2009 (c) Jeff Brown -# -# 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); -} diff --git a/examples/processor.pl b/examples/processor.pl deleted file mode 100755 index d2d1e91..0000000 --- a/examples/processor.pl +++ /dev/null @@ -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(); diff --git a/examples/read_one.pl b/examples/read_one.pl deleted file mode 100755 index d64860c..0000000 --- a/examples/read_one.pl +++ /dev/null @@ -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"); -} diff --git a/examples/scan_image.pl b/examples/scan_image.pl deleted file mode 100755 index 39d460e..0000000 --- a/examples/scan_image.pl +++ /dev/null @@ -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); diff --git a/python/MANIFEST.in b/python/MANIFEST.in new file mode 100644 index 0000000..93acc53 --- /dev/null +++ b/python/MANIFEST.in @@ -0,0 +1,2 @@ +include MANIFEST MANIFEST.in zbarmodule.h test/barcode.png +recursive-include examples *.py diff --git a/python/README b/python/README new file mode 100644 index 0000000..97480e4 --- /dev/null +++ b/python/README @@ -0,0 +1,40 @@ +========================================== +ZBar -- read barcodes from images or video +========================================== + +The ZBar Bar Code Reader is a library for scanning and decoding bar +codes from various sources such as video streams, image files or raw +intensity sensors. It supports EAN, UPC, Code 128, Code 39 and +Interleaved 2 of 5. These are the Python bindings for the library. + +Check the ZBar project home page for the latest release, mailing +lists, etc. + http://zbar.sourceforge.net/ + + +Installation +------------ + +To install this module type the following: + + ptython setup.py install + +Dependencies +------------ + +This module requires the ZBar Bar Code Reader, which may be obtained +from: + http://zbar.sourceforge.net/ + +Examples +-------- + +TBD + +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-2009 (c) Jeff Brown diff --git a/examples/processor.py b/python/examples/processor.py similarity index 100% rename from examples/processor.py rename to python/examples/processor.py diff --git a/examples/read_one.py b/python/examples/read_one.py similarity index 100% rename from examples/read_one.py rename to python/examples/read_one.py diff --git a/examples/scan_image.py b/python/examples/scan_image.py similarity index 100% rename from examples/scan_image.py rename to python/examples/scan_image.py diff --git a/python/setup.py b/python/setup.py new file mode 100755 index 0000000..f7639c5 --- /dev/null +++ b/python/setup.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python +from distutils.core import setup, Extension + +setup( + name = 'zbar', + version = '0.10', + author = 'Jeff Brown', + author_email = 'spadix@users.sourceforge.net', + url = 'http://zbar.sourceforge.net', + description = 'read barcodes from images or video', + license = 'LGPL', + long_description = open('README').read(), + classifiers = [ + 'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)', + 'Development Status :: 4 - Beta', + 'Intended Audience :: Developers', + 'Environment :: Console', + 'Environment :: X11 Applications', + 'Environment :: Win32 (MS Windows)', + 'Operating System :: POSIX', + 'Operating System :: Unix', + 'Operating System :: Microsoft :: Windows', + 'Topic :: Communications', + 'Topic :: Multimedia :: Graphics', + 'Topic :: Software Development :: Libraries', + ], + ext_modules = [ + Extension('zbar', [ + 'zbarmodule.c', + 'enum.c', + 'exception.c', + 'symbol.c', + 'symbolset.c', + 'symboliter.c', + 'image.c', + 'processor.c', + 'imagescanner.c', + 'decoder.c', + 'scanner.c', + ], + libraries = [ 'zbar' ], + ), + ], +) From dc84a46c60dd660763ac8c03b2c820e37d5183d3 Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 10 Nov 2009 12:17:27 -0500 Subject: [PATCH 169/328] update python/perl README --- perl/README | 9 +++++---- python/README | 20 +++++++++++--------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/perl/README b/perl/README index 1824af5..e4b1811 100644 --- a/perl/README +++ b/perl/README @@ -1,10 +1,11 @@ Barcode::ZBar Perl module ========================= -The ZBar Bar Code Reader is a library for scanning and decoding bar -codes from various sources such as video streams, image files or raw -intensity sensors. It supports EAN, UPC, Code 128, Code 39 and -Interleaved 2 of 5. These are the Perl bindings for the library. +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. These are the Perl bindings +for the library. Check the ZBar project home page for the latest release, mailing lists, etc. diff --git a/python/README b/python/README index 97480e4..881ae38 100644 --- a/python/README +++ b/python/README @@ -1,30 +1,32 @@ ========================================== -ZBar -- read barcodes from images or video +zbar -- read barcodes from images or video ========================================== -The ZBar Bar Code Reader is a library for scanning and decoding bar -codes from various sources such as video streams, image files or raw -intensity sensors. It supports EAN, UPC, Code 128, Code 39 and -Interleaved 2 of 5. These are the Python bindings for the library. +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. These are the Python +bindings for the library. Check the ZBar project home page for the latest release, mailing lists, etc. - http://zbar.sourceforge.net/ +* http://zbar.sourceforge.net/ Installation ------------ -To install this module type the following: +To install this module type the following:: - ptython setup.py install + python setup.py install Dependencies ------------ This module requires the ZBar Bar Code Reader, which may be obtained from: - http://zbar.sourceforge.net/ + +* http://zbar.sourceforge.net/ Examples -------- From fd54c0eca9b706d8751ab4a54ccb81e60f491f94 Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 10 Nov 2009 15:16:51 -0500 Subject: [PATCH 170/328] add Obj-C wrapper --- ChangeLog | 1 + include/zbar/ZBarImage.h | 62 ++++++++ include/zbar/ZBarImageScanner.h | 50 +++++++ include/zbar/ZBarReaderController.h | 19 +-- include/zbar/ZBarSymbol.h | 24 +++- iphone/ZBarImage.m | 197 ++++++++++++++++++++++++++ iphone/ZBarImageScanner.m | 92 ++++++++++++ iphone/ZBarReaderController.m | 124 +++------------- iphone/ZBarSymbol.m | 76 +++++++++- iphone/debug.h | 53 +++++++ iphone/zbar.xcodeproj/project.pbxproj | 19 ++- 11 files changed, 601 insertions(+), 116 deletions(-) create mode 100644 include/zbar/ZBarImage.h create mode 100644 include/zbar/ZBarImageScanner.h create mode 100644 iphone/ZBarImage.m create mode 100644 iphone/ZBarImageScanner.m create mode 100644 iphone/debug.h diff --git a/ChangeLog b/ChangeLog index 44f3609..70c2205 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * add Obj-C wrapper * first pass working iPhone "widget" version 0.10: diff --git a/include/zbar/ZBarImage.h b/include/zbar/ZBarImage.h new file mode 100644 index 0000000..08cb651 --- /dev/null +++ b/include/zbar/ZBarImage.h @@ -0,0 +1,62 @@ +//------------------------------------------------------------------------ +// Copyright 2009 (c) Jeff Brown +// +// 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 +#import +#import + +#ifdef __cplusplus +using namespace zbar; +#endif + +// Obj-C wrapper for ZBar image + +@interface ZBarImage : NSObject +{ + zbar_image_t *zimg; +} + +@property (nonatomic) unsigned long format; +@property (nonatomic) unsigned sequence; +@property (nonatomic) CGSize size; +@property (readonly, nonatomic) const void *data; +@property (readonly, nonatomic) unsigned long dataLength; +@property (readonly, nonatomic) ZBarSymbolSet *symbols; +@property (readonly, nonatomic) zbar_image_t *zbarImage; + +- initWithImage: (zbar_image_t*) image; +- initWithUIImage: (UIImage*) image; +- initWithUIImage: (UIImage*) image + size: (CGSize) size; + +- (void) setData: (const void*) data + withLength: (unsigned long) length; +- (void) cleanup; + ++ (unsigned long) fourcc: (NSString*) format; + +#if 0 +- convertToFormat: (unsigned long) format; +#endif + +@end diff --git a/include/zbar/ZBarImageScanner.h b/include/zbar/ZBarImageScanner.h new file mode 100644 index 0000000..ca85d56 --- /dev/null +++ b/include/zbar/ZBarImageScanner.h @@ -0,0 +1,50 @@ +//------------------------------------------------------------------------ +// Copyright 2009 (c) Jeff Brown +// +// 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 +#import + +#ifdef __cplusplus +using namespace zbar; +#endif + +// Obj-C wrapper for ZBar image scanner + +@interface ZBarImageScanner : NSObject +{ + zbar_image_scanner_t *scanner; +} + +@property (nonatomic) BOOL enableCache; +@property (readonly, nonatomic) ZBarSymbolSet *results; + +// decoder configuration +- (void) parseConfig: (NSString*) configStr; +- (void) setSymbology: (zbar_symbol_type_t) symbology + config: (zbar_config_t) config + to: (int) value; + +// image scanning interface +- (NSInteger) scanImage: (ZBarImage*) image; + +@end diff --git a/include/zbar/ZBarReaderController.h b/include/zbar/ZBarReaderController.h index 46d0dea..4d1ad22 100644 --- a/include/zbar/ZBarReaderController.h +++ b/include/zbar/ZBarReaderController.h @@ -23,7 +23,11 @@ #import #import -#import +#import + +#ifdef __cplusplus +using namespace zbar; +#endif @class ZBarReaderController, ZBarHelpController; @@ -39,7 +43,7 @@ < UINavigationControllerDelegate, UIImagePickerControllerDelegate > { - zbar_image_scanner_t *scanner; + ZBarImageScanner *scanner; ZBarHelpController *help; UIView *overlay, *controls; @@ -47,6 +51,9 @@ BOOL showsZBarControls, showsHelpOnFail; } +// access to configure image scanner +@property (readonly, nonatomic) ZBarImageScanner *scanner; + // barcode result recipient @property (nonatomic, assign) id readerDelegate; @@ -56,14 +63,8 @@ // whether to display helpful information when decoding fails @property (nonatomic) BOOL showsHelpOnFail; -// decoder configuration -- (void) parseConfig: (NSString*) configStr; -- (void) setSymbology: (zbar_symbol_type_t) symbology - config: (zbar_config_t) config - to: (int) value; - // direct scanner interface - scan UIImage and return something enumerable -- (id ) scanImage: (UIImage*) img; +- (id ) scanImage: (UIImage*) image; @end diff --git a/include/zbar/ZBarSymbol.h b/include/zbar/ZBarSymbol.h index af49281..0cc70fb 100644 --- a/include/zbar/ZBarSymbol.h +++ b/include/zbar/ZBarSymbol.h @@ -22,9 +22,26 @@ //------------------------------------------------------------------------ #import -#import +#import + +#ifdef __cplusplus +using namespace zbar; +#endif + +// Obj-C wrapper for ZBar result types + +@interface ZBarSymbolSet : NSObject +{ + const zbar_symbol_set_t *set; +} + +@property (readonly, nonatomic) int count; +@property (readonly, nonatomic) const zbar_symbol_set_t *zbarSymbolSet; + +- (id) initWithSymbolSet: (const zbar_symbol_set_t*) set; + +@end -// Obj-C wrapper for ZBar result type @interface ZBarSymbol : NSObject { @@ -35,6 +52,9 @@ @property (readonly, nonatomic) NSString *typeName; @property (readonly, nonatomic) NSString *data; @property (readonly, nonatomic) int quality; +@property (readonly, nonatomic) int count; +@property (readonly, nonatomic) ZBarSymbolSet *components; +@property (readonly, nonatomic) const zbar_symbol_t *zbarSymbol; - (id) initWithSymbol: (const zbar_symbol_t*) symbol; diff --git a/iphone/ZBarImage.m b/iphone/ZBarImage.m new file mode 100644 index 0000000..193fe6e --- /dev/null +++ b/iphone/ZBarImage.m @@ -0,0 +1,197 @@ +//------------------------------------------------------------------------ +// Copyright 2009 (c) Jeff Brown +// +// 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 +#import +#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, data, dataLength, zbarImage; + ++ (unsigned long) fourcc: (NSString*) format +{ + return(*(uint32_t*)[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) initWithUIImage: (UIImage*) image + size: (CGSize) size +{ + if(!(self = [self init])) + return(nil); + + timer_start; + + unsigned int w = size.width + 0.5; + unsigned int h = size.height + 0.5; + + unsigned long datalen = w * h; + uint8_t *raw = malloc(datalen); + // FIXME handle OOM + assert(raw); + + zbar_image_set_data(zimg, raw, datalen, zbar_image_free_data); + zbar_image_set_format(zimg, *(int*)"Y800"); + zbar_image_set_size(zimg, w, h); + + // generate grayscale image data + CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray(); + CGContextRef ctx = + CGBitmapContextCreate(raw, w, h, 8, w, cs, kCGImageAlphaNone); + CGColorSpaceRelease(cs); + CGContextSetAllowsAntialiasing(ctx, 0); + CGContextDrawImage(ctx, CGRectMake(0, 0, w, h), image.CGImage); + CGContextRelease(ctx); + + zlog(@"ZBarImage: converted UIImage %dx%d to %dx%d Y800 in %gs\n", + w, h, timer_elapsed(t_start, timer_now())); + + return(self); +} + +- (id) initWithUIImage: (UIImage*) image +{ + return([self initWithUIImage: image + size: image.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 +{ + return(CGSizeMake(zbar_image_get_width(zimg), + zbar_image_get_height(zimg))); +} + +- (void) setSize: (CGSize) size +{ + zbar_image_set_size(zimg, size.width + .5, 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); +} + +- (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 diff --git a/iphone/ZBarImageScanner.m b/iphone/ZBarImageScanner.m new file mode 100644 index 0000000..192e797 --- /dev/null +++ b/iphone/ZBarImageScanner.m @@ -0,0 +1,92 @@ +//------------------------------------------------------------------------ +// Copyright 2009 (c) Jeff Brown +// +// 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 +#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 +{ + timer_start; + + int nsyms = zbar_scan_image(scanner, image.zbarImage); + + zlog(@"ZBarImageScanner: scanned %d symbols in %gs\n", + nsyms, timer_elapsed(t_start, timer_now())); + + return(nsyms); +} + +@end diff --git a/iphone/ZBarReaderController.m b/iphone/ZBarReaderController.m index 7c376a0..fbb59b7 100644 --- a/iphone/ZBarReaderController.m +++ b/iphone/ZBarReaderController.m @@ -26,44 +26,23 @@ #import #import "ZBarHelpController.h" +#import "debug.h" #define MIN_QUALITY 10 -#ifdef ZRC_DEBUG -# define zlog(fmt, ...) \ - NSLog(@"ZBarReaderController: " fmt , ##__VA_ARGS__) - -static inline long timer_now () -{ - struct tms now; - times(&now); - return(now.tms_utime + now.tms_stime); -} - -static inline double timer_elapsed (long start, long end) -{ - double clk_tck = sysconf(_SC_CLK_TCK); - if(!clk_tck) - return(-1); - return((end - start) / clk_tck); -} - -#else -# define zlog(...) -#endif NSString* const ZBarReaderControllerResults = @"ZBarReaderControllerResults"; @implementation ZBarReaderController -@synthesize readerDelegate, showsZBarControls, showsHelpOnFail; +@synthesize scanner, readerDelegate, showsZBarControls, showsHelpOnFail; - (id) init { if(self = [super init]) { - scanner = zbar_image_scanner_create(); showsHelpOnFail = YES; showsZBarControls = YES; + scanner = [ZBarImageScanner new]; if([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]) self.sourceType = UIImagePickerControllerSourceTypeCamera; @@ -139,10 +118,8 @@ - (void) viewDidUnload - (void) dealloc { [self cleanup]; - if(scanner) { - zbar_image_scanner_destroy(scanner); - scanner = NULL; - } + [scanner release]; + scanner = nil; [super dealloc]; } @@ -243,62 +220,16 @@ - (void) setDelegate: (id )delegate; } -// image scanner config wrappers -- (void) parseConfig: (NSString*) cfg -{ - const char *str = [cfg UTF8String]; - zbar_image_scanner_parse_config(scanner, str); - // FIXME throw errors -} - -- (void) setSymbology: (zbar_symbol_type_t) sym - config: (zbar_config_t) cfg - to: (int) val +- (id ) scanImage: (UIImage*) image { - zbar_image_scanner_set_config(scanner, sym, cfg, val); - // FIXME throw errors -} + timer_start; - -// scan UIImage and return something enumerable -- (id ) scanImage: (UIImage*) img -{ -#ifdef ZRC_DEBUG - long t_start = timer_now(); - zlog(@"captured image %gx%g\n", img.size.width, img.size.height); -#endif - - int w = img.size.width; - int h = img.size.height; + int w = image.size.width; + int h = image.size.height; if(w > 1280 || h > 1280) { w /= 2; h /= 2; } - long datalen = w * h; - uint8_t *raw = malloc(datalen); - // FIXME handle OOM - assert(raw); - - zbar_image_t *zimg = zbar_image_create(); - zbar_image_set_data(zimg, raw, datalen, zbar_image_free_data); - zbar_image_set_format(zimg, *(int*)"Y800"); - zbar_image_set_size(zimg, w, h); - - // generate grayscale image data - CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray(); - CGContextRef ctx = - CGBitmapContextCreate(raw, w, h, 8, w, cs, kCGImageAlphaNone); - CGColorSpaceRelease(cs); - CGContextSetAllowsAntialiasing(ctx, 0); - CGRect bbox = CGRectMake(0, 0, w, h); - CGContextDrawImage(ctx, bbox, img.CGImage); - CGContextRelease(ctx); - -#ifdef ZRC_DEBUG - long t_convert = timer_now(); - zlog(@" converted to %dx%d Y800 in +%gs\n", - w, h, timer_elapsed(t_start, t_convert)); -#endif // limit the maximum number of scan passes int density; @@ -306,38 +237,33 @@ - (void) setSymbology: (zbar_symbol_type_t) sym density = (w / 240 + 1) / 2; else density = 1; - zbar_image_scanner_set_config(scanner, 0, ZBAR_CFG_X_DENSITY, density); + [scanner setSymbology: 0 + config: ZBAR_CFG_X_DENSITY + to: density]; if(h > 480) density = (h / 240 + 1) / 2; else density = 1; - zbar_image_scanner_set_config(scanner, 0, ZBAR_CFG_Y_DENSITY, density); - - int nsyms = zbar_scan_image(scanner, zimg); + [scanner setSymbology: 0 + config: ZBAR_CFG_Y_DENSITY + to: density]; -#ifdef ZRC_DEBUG - long t_scan = timer_now(); - zlog(@" scanned %d raw symbols in +%gs\n", - nsyms, timer_elapsed(t_convert, t_scan)); -#endif + ZBarImage *zimg = [[ZBarImage alloc] initWithUIImage: image]; + int nsyms = [scanner scanImage: zimg]; + [zimg release]; NSMutableArray *syms = nil; if(nsyms) { // quality/type filtering int max_quality = MIN_QUALITY; - const zbar_symbol_t *zsym = zbar_image_first_symbol(zimg); - assert(zsym); - for(; zsym; zsym = zbar_symbol_next(zsym)) { - if(zbar_symbol_get_count(zsym)) - continue; - - zbar_symbol_type_t type = zbar_symbol_get_type(zsym); + for(ZBarSymbol *sym in scanner.results) { + zbar_symbol_type_t type = sym.type; int quality; if(type == ZBAR_QRCODE) quality = INT_MAX; else - quality = zbar_symbol_get_quality(zsym); + quality = sym.quality; if(quality < max_quality) { zlog(@" type=%d quality=%d < %d\n", @@ -354,18 +280,12 @@ - (void) setSymbology: (zbar_symbol_type_t) sym if(!syms) syms = [NSMutableArray arrayWithCapacity: 1]; - ZBarSymbol *sym = [[ZBarSymbol alloc] initWithSymbol: zsym]; [syms addObject: sym]; - [sym release]; } } - zbar_image_destroy(zimg); -#ifdef ZRC_DEBUG - long t_end = timer_now(); zlog(@"read %d filtered symbols in %gs total\n", - (!syms) ? 0 : [syms count], timer_elapsed(t_start, t_end)); -#endif + (!syms) ? 0 : [syms count], timer_elapsed(t_start, timer_now())); return(syms); } diff --git a/iphone/ZBarSymbol.m b/iphone/ZBarSymbol.m index af08f0e..9f514f5 100644 --- a/iphone/ZBarSymbol.m +++ b/iphone/ZBarSymbol.m @@ -21,12 +21,11 @@ // http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#import #import @implementation ZBarSymbol -@dynamic type, typeName, data, quality; +@dynamic type, typeName, data, quality, count, zbarSymbol; - (id) initWithSymbol: (zbar_symbol_t*) sym { @@ -67,4 +66,77 @@ - (int) quality return(zbar_symbol_get_quality(symbol)); } +- (int) count +{ + return(zbar_symbol_get_count(symbol)); +} + +- (const zbar_symbol_t*) zbarSymbol +{ + return(symbol); +} + +- (ZBarSymbolSet*) components +{ + return([[[ZBarSymbolSet alloc] + initWithSymbolSet: zbar_symbol_get_components(symbol)] + autorelease]); +} + +@end + + +@implementation ZBarSymbolSet + +@dynamic count, zbarSymbolSet; + +- (id) initWithSymbolSet: (const zbar_symbol_set_t*) s +{ + if(self = [super init]) { + set = s; + zbar_symbol_set_ref(s, 1); + } + return(self); +} + +- (void) dealloc +{ + if(set) { + zbar_symbol_set_ref(set, -1); + set = NULL; + } + [super dealloc]; +} + +- (int) count +{ + return(zbar_symbol_set_get_size(set)); +} + +- (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) + sym = zbar_symbol_set_first_symbol(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 diff --git a/iphone/debug.h b/iphone/debug.h new file mode 100644 index 0000000..6d0ee00 --- /dev/null +++ b/iphone/debug.h @@ -0,0 +1,53 @@ +//------------------------------------------------------------------------ +// Copyright 2009 (c) Jeff Brown +// +// 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 + +#ifdef DEBUG_OBJC +# define zlog(fmt, ...) \ + NSLog(@"ZBarReaderController: " fmt , ##__VA_ARGS__) + +#define timer_start \ + long t_start = timer_now(); + +static inline long timer_now () +{ + struct tms now; + times(&now); + return(now.tms_utime + now.tms_stime); +} + +static inline double timer_elapsed (long start, long end) +{ + double clk_tck = sysconf(_SC_CLK_TCK); + if(!clk_tck) + return(-1); + return((end - start) / clk_tck); +} + +#else +# define zlog(...) +# define timer_start +# define timer_now(...) 0 +# define timer_elapsed(...) 0 +#endif diff --git a/iphone/zbar.xcodeproj/project.pbxproj b/iphone/zbar.xcodeproj/project.pbxproj index 7eb13d9..3246ddf 100644 --- a/iphone/zbar.xcodeproj/project.pbxproj +++ b/iphone/zbar.xcodeproj/project.pbxproj @@ -8,6 +8,10 @@ /* Begin PBXBuildFile section */ AA747D9F0F9514B9006C5449 /* prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = AA747D9E0F9514B9006C5449 /* prefix.pch */; }; + DC4920EE10A70475000E4D43 /* ZBarImage.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4920EC10A70475000E4D43 /* ZBarImage.m */; }; + DC4920EF10A70475000E4D43 /* ZBarImageScanner.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4920ED10A70475000E4D43 /* ZBarImageScanner.m */; }; + DC4920F210A7048C000E4D43 /* ZBarImage.h in Headers */ = {isa = PBXBuildFile; fileRef = DC4920F010A7048C000E4D43 /* ZBarImage.h */; }; + DC4920F310A7048C000E4D43 /* ZBarImageScanner.h in Headers */ = {isa = PBXBuildFile; fileRef = DC4920F110A7048C000E4D43 /* ZBarImageScanner.h */; }; DC67C11210A079E40033B702 /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C11110A079E40033B702 /* config.h */; }; DC67C11810A07A810033B702 /* zbar.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C11710A07A810033B702 /* zbar.h */; }; DC67C11B10A07A950033B702 /* ZBarReaderController.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C11910A07A950033B702 /* ZBarReaderController.h */; }; @@ -62,6 +66,10 @@ AA747D9E0F9514B9006C5449 /* prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = prefix.pch; sourceTree = ""; }; AACBBE490F95108600F1A2B1 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; D2AAC07E0554694100DB518D /* libzbar.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libzbar.a; sourceTree = BUILT_PRODUCTS_DIR; }; + DC4920EC10A70475000E4D43 /* ZBarImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarImage.m; sourceTree = ""; }; + DC4920ED10A70475000E4D43 /* ZBarImageScanner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarImageScanner.m; sourceTree = ""; }; + DC4920F010A7048C000E4D43 /* ZBarImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ZBarImage.h; path = ../include/zbar/ZBarImage.h; sourceTree = SOURCE_ROOT; }; + DC4920F110A7048C000E4D43 /* ZBarImageScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ZBarImageScanner.h; path = ../include/zbar/ZBarImageScanner.h; sourceTree = SOURCE_ROOT; }; DC67C08210A079BE0033B702 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; DC67C11110A079E40033B702 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = ""; }; DC67C11710A07A810033B702 /* zbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = zbar.h; path = ../include/zbar.h; sourceTree = SOURCE_ROOT; }; @@ -135,10 +143,12 @@ 0867D691FE84028FC02AAC07 /* zbar */ = { isa = PBXGroup; children = ( + DC67C1C010A07B6B0033B702 /* ZBarSymbol.m */, + DC4920EC10A70475000E4D43 /* ZBarImage.m */, + DC4920ED10A70475000E4D43 /* ZBarImageScanner.m */, DC67C1BD10A07B6B0033B702 /* ZBarHelpController.h */, DC67C1BE10A07B6B0033B702 /* ZBarHelpController.m */, DC67C1BF10A07B6B0033B702 /* ZBarReaderController.m */, - DC67C1C010A07B6B0033B702 /* ZBarSymbol.m */, DC67C11610A07A670033B702 /* include */, DC67C11E10A07AD30033B702 /* zbar */, 0867D69AFE84028FC02AAC07 /* Frameworks */, @@ -163,6 +173,8 @@ DC67C11110A079E40033B702 /* config.h */, DC67C11710A07A810033B702 /* zbar.h */, DC67C11A10A07A950033B702 /* ZBarSymbol.h */, + DC4920F010A7048C000E4D43 /* ZBarImage.h */, + DC4920F110A7048C000E4D43 /* ZBarImageScanner.h */, DC67C11910A07A950033B702 /* ZBarReaderController.h */, ); name = include; @@ -265,6 +277,8 @@ DC67C1A910A07AD30033B702 /* symbol.h in Headers */, DC67C1C110A07B6B0033B702 /* ZBarHelpController.h in Headers */, DC67C1CC10A07BEE0033B702 /* svg.h in Headers */, + DC4920F210A7048C000E4D43 /* ZBarImage.h in Headers */, + DC4920F310A7048C000E4D43 /* ZBarImageScanner.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -334,6 +348,8 @@ DC67C1C210A07B6B0033B702 /* ZBarHelpController.m in Sources */, DC67C1C310A07B6B0033B702 /* ZBarReaderController.m in Sources */, DC67C1C410A07B6B0033B702 /* ZBarSymbol.m in Sources */, + DC4920EE10A70475000E4D43 /* ZBarImage.m in Sources */, + DC4920EF10A70475000E4D43 /* ZBarImageScanner.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -374,6 +390,7 @@ ARCHS = "$(ARCHS_STANDARD_32_BIT)"; GCC_C_LANGUAGE_STANDARD = c99; GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = "DEBUG_OBJC=1"; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; OTHER_LDFLAGS = "-ObjC"; From 25c88647bb5a46db9dd3a567fc85b9c94dc28864 Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 14 Nov 2009 00:25:53 -0500 Subject: [PATCH 171/328] improve iphone reader reliability --- .hgignore | 2 ++ iphone/ZBarReaderController.m | 42 +++++++++++++++++++++++++---------- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/.hgignore b/.hgignore index 64e80d1..c43649f 100644 --- a/.hgignore +++ b/.hgignore @@ -21,4 +21,6 @@ autom4te.cache missing python/MANIFEST iphone/build +iphone/*.xcodeproj/*.mode1v3 +iphone/*.xcodeproj/*.pbxuser .DS_Store diff --git a/iphone/ZBarReaderController.m b/iphone/ZBarReaderController.m index fbb59b7..b0c064b 100644 --- a/iphone/ZBarReaderController.m +++ b/iphone/ZBarReaderController.m @@ -221,35 +221,31 @@ - (void) setDelegate: (id ) scanImage: (UIImage*) image + size: (CGSize) size { timer_start; - int w = image.size.width; - int h = image.size.height; - if(w > 1280 || h > 1280) { - w /= 2; - h /= 2; - } - // limit the maximum number of scan passes int density; - if(w > 480) - density = (w / 240 + 1) / 2; + if(size.width > 480) + density = (size.width / 240 + 1) / 2; else density = 1; [scanner setSymbology: 0 config: ZBAR_CFG_X_DENSITY to: density]; - if(h > 480) - density = (h / 240 + 1) / 2; + if(size.height > 480) + density = (size.height / 240 + 1) / 2; else density = 1; [scanner setSymbology: 0 config: ZBAR_CFG_Y_DENSITY to: density]; - ZBarImage *zimg = [[ZBarImage alloc] initWithUIImage: image]; + ZBarImage *zimg = [[ZBarImage alloc] + initWithUIImage: image + size: size]; int nsyms = [scanner scanImage: zimg]; [zimg release]; @@ -289,4 +285,26 @@ - (void) setDelegate: (id ) scanImage: (UIImage*) image +{ + CGSize size = image.size; + if(size.width > 1280 || size.height > 1280) { + size.width /= 2; + size.height /= 2; + } + + id syms = + [self scanImage: image + size: size]; + if(!syms) { + // make one more attempt for close up, grainy images + size.width /= 2; + size.height /= 2; + syms = [self scanImage: image + size: size]; + } + + return(syms); +} + @end From ea5ccf1b8eaa26400eef8970f79aa5dcaab1397c Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 16 Nov 2009 13:17:28 -0500 Subject: [PATCH 172/328] iphone widget back compat updates, add basic test app --- ChangeLog | 1 + include/zbar/ZBarReaderController.h | 9 +- iphone/ZBarImage.m | 5 +- iphone/ZBarReaderController.m | 55 ++- test/iphone/prefix.pch | 5 + test/iphone/readertest.m | 360 ++++++++++++++++++ test/iphone/readertest.plist | 28 ++ .../readertest.xcodeproj/project.pbxproj | 273 +++++++++++++ 8 files changed, 719 insertions(+), 17 deletions(-) create mode 100644 test/iphone/prefix.pch create mode 100644 test/iphone/readertest.m create mode 100644 test/iphone/readertest.plist create mode 100755 test/iphone/readertest.xcodeproj/project.pbxproj diff --git a/ChangeLog b/ChangeLog index cc14ca5..cd48610 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * iphone widget back compat updates, add basic test app * add python distutils build infrastructure * add Obj-C wrapper * first pass working iPhone "widget" diff --git a/include/zbar/ZBarReaderController.h b/include/zbar/ZBarReaderController.h index 4d1ad22..30d32d4 100644 --- a/include/zbar/ZBarReaderController.h +++ b/include/zbar/ZBarReaderController.h @@ -32,9 +32,12 @@ using namespace zbar; @class ZBarReaderController, ZBarHelpController; @protocol ZBarReaderDelegate - @optional -- (void) zbarReaderControllerDidFailToRead: (ZBarReaderController*) reader; + +// called when no barcode is found in an image selected by the user. +// if retry is NO, the delegate *must* dismiss the controller +- (void) readerControllerDidFailToRead: (ZBarReaderController*) reader + withRetry: (BOOL) retry; @end @@ -48,7 +51,7 @@ using namespace zbar; UIView *overlay, *controls; id readerDelegate; - BOOL showsZBarControls, showsHelpOnFail; + BOOL hasOverlay, showsZBarControls, showsHelpOnFail; } // access to configure image scanner diff --git a/iphone/ZBarImage.m b/iphone/ZBarImage.m index 193fe6e..c94d01b 100644 --- a/iphone/ZBarImage.m +++ b/iphone/ZBarImage.m @@ -100,8 +100,9 @@ - (id) initWithUIImage: (UIImage*) image CGContextDrawImage(ctx, CGRectMake(0, 0, w, h), image.CGImage); CGContextRelease(ctx); - zlog(@"ZBarImage: converted UIImage %dx%d to %dx%d Y800 in %gs\n", - w, h, timer_elapsed(t_start, timer_now())); + zlog(@"ZBarImage: converted UIImage %gx%g to %dx%d Y800 in %gs\n", + image.size.width, image.size.height, w, h, + timer_elapsed(t_start, timer_now())); return(self); } diff --git a/iphone/ZBarReaderController.m b/iphone/ZBarReaderController.m index b0c064b..a853327 100644 --- a/iphone/ZBarReaderController.m +++ b/iphone/ZBarReaderController.m @@ -35,13 +35,15 @@ @implementation ZBarReaderController -@synthesize scanner, readerDelegate, showsZBarControls, showsHelpOnFail; +@synthesize scanner, readerDelegate, showsHelpOnFail; +@dynamic showsZBarControls; - (id) init { if(self = [super init]) { showsHelpOnFail = YES; - showsZBarControls = YES; + hasOverlay = showsZBarControls = + [self respondsToSelector: @selector(cameraOverlayView)]; scanner = [ZBarImageScanner new]; if([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]) @@ -96,7 +98,8 @@ - (void) viewDidLoad { [super viewDidLoad]; [super setDelegate: self]; - [self initOverlay]; + if(hasOverlay) + [self initOverlay]; } - (void) cleanup @@ -138,10 +141,16 @@ - (void) viewWillAppear: (BOOL) animated help = nil; } - if(self.sourceType == UIImagePickerControllerSourceTypeCamera) { - if(showsZBarControls || !self.cameraOverlayView) - self.cameraOverlayView = overlay; - self.showsCameraControls = !showsZBarControls; + if(hasOverlay && + self.sourceType == UIImagePickerControllerSourceTypeCamera) { + if(showsZBarControls || ![self cameraOverlayView]) + [self setCameraOverlayView: overlay]; + + if(showsZBarControls) + [self setShowsCameraControls: NO]; + else if([self cameraOverlayView] == overlay) + [self setShowsCameraControls: YES]; + controls.hidden = !showsZBarControls; } [super viewWillAppear: animated]; @@ -153,6 +162,7 @@ - (void) imagePickerController: (UIImagePickerController*) picker UIImage *img = [info objectForKey: UIImagePickerControllerOriginalImage]; id results = [self scanImage: img]; + if(results) { NSMutableDictionary *newinfo = [info mutableCopy]; [newinfo setObject: results @@ -167,14 +177,16 @@ - (void) imagePickerController: (UIImagePickerController*) picker return; } - if(showsHelpOnFail) { + BOOL camera = (self.sourceType == UIImagePickerControllerSourceTypeCamera); + BOOL retry = !camera || (hasOverlay && ![self showsCameraControls]); + if(showsHelpOnFail && retry) { help = [ZBarHelpController new]; help.delegate = self; - if(self.sourceType == UIImagePickerControllerSourceTypeCamera) { + if(camera) { help.wantsFullScreenLayout = YES; help.view.alpha = 0; - [self.cameraOverlayView addSubview: help.view]; + [[self cameraOverlayView] addSubview: help.view]; [UIView beginAnimations: @"ZBarHelp" context: nil]; help.view.alpha = 1; @@ -185,9 +197,14 @@ - (void) imagePickerController: (UIImagePickerController*) picker animated: YES]; } - SEL cb = @selector(zbarReaderControllerDidFailToRead:); + SEL cb = @selector(readerControllerDidFailToRead:withRetry:); if([readerDelegate respondsToSelector: cb]) - [readerDelegate zbarReaderControllerDidFailToRead: self]; + // 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 @@ -212,6 +229,20 @@ - (void) helpController: (ZBarHelpController*) hlp [hlp dismissModalViewControllerAnimated: YES]; } +- (BOOL) showsZBarControls +{ + return(showsZBarControls); +} + +- (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 +# import +# import +#endif diff --git a/test/iphone/readertest.m b/test/iphone/readertest.m new file mode 100644 index 0000000..bb0a751 --- /dev/null +++ b/test/iphone/readertest.m @@ -0,0 +1,360 @@ +#import + +#if 0 +# define VALGRIND "/usr/local/bin/valgrind" +#endif + +enum { + SOURCE_SECTION = 0, + CONFIG_SECTION, + RESULT_SECTION, + NUM_SECTIONS +}; + +@interface AppDelegate : UITableViewController + < UIApplicationDelegate, + UINavigationControllerDelegate, + UITableViewDelegate, + UITableViewDataSource, + ZBarReaderDelegate > +{ + UIWindow *window; + UINavigationController *nav; + + NSArray *sections; + + BOOL found; + NSInteger dataHeight; + UILabel *typeLabel, *dataLabel; + UIImageView *imageView; + + ZBarReaderController *reader; +} + +@end + + +@implementation AppDelegate + +- (id) init +{ + return([super initWithStyle: UITableViewStyleGrouped]); +} + +- (void) applicationDidFinishLaunching: (UIApplication*) application +{ + self.title = @"ZBar Reader Test"; + + nav = [[UINavigationController alloc] + initWithRootViewController: self]; + nav.delegate = self; + + window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]]; + [window addSubview: nav.view]; + [window makeKeyAndVisible]; + + reader = [ZBarReaderController new]; + reader.readerDelegate = self; +} + +- (void) viewDidLoad +{ + [super viewDidLoad]; + + UITableView *view = self.tableView; + view.delegate = self; + view.dataSource = self; + + // NB don't need SourceTypeSavedPhotosAlbum + static NSString* const sourceNames[] = { + @"Library", @"Camera", @"Album" + }; + NSMutableArray *sources = [NSMutableArray arrayWithCapacity: 3]; + for(int i = 0; i < 3; i++) { + UITableViewCell *cell = [UITableViewCell new]; + if([ZBarReaderController isSourceTypeAvailable: i]) { + cell.textLabel.text = sourceNames[i]; + cell.tag = i; + if(reader.sourceType == i) + cell.accessoryType = UITableViewCellAccessoryCheckmark; + [sources addObject: cell]; + [cell release]; + } + } + + static NSString* const configNames[] = { + @"showsHelpOnFail", @"showsZBarControls" + }; + NSMutableArray *configs = [NSMutableArray arrayWithCapacity: 2]; + for(int i = 0; i < 2; i++) { + UITableViewCell *cell = [UITableViewCell new]; + cell.textLabel.text = configNames[i]; + if([reader performSelector: NSSelectorFromString(configNames[i])]) + cell.accessoryType = UITableViewCellAccessoryCheckmark; + [configs addObject: cell]; + [cell release]; + } + + UITableViewCell *typeCell = [UITableViewCell new]; + typeLabel = typeCell.textLabel; + UITableViewCell *dataCell = [UITableViewCell new]; + dataLabel = dataCell.textLabel; + dataLabel.numberOfLines = 0; + dataLabel.lineBreakMode = UILineBreakModeCharacterWrap; + UITableViewCell *imageCell = [UITableViewCell new]; + imageView = [UIImageView new]; + imageView.contentMode = UIViewContentModeScaleAspectFit; + imageView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight); + UIView *content = imageCell.contentView; + imageView.frame = content.bounds; + [content addSubview: imageView]; + [imageView release]; + NSArray *results = + [NSArray arrayWithObjects: typeCell, dataCell, imageCell, nil]; + + sections = + [[NSArray arrayWithObjects: sources, configs, results, nil] retain]; +} + +- (void) viewDidUnload +{ + [sections release]; + sections = nil; + typeLabel = nil; + dataLabel = nil; + imageView = nil; + + [super viewDidUnload]; +} + +- (void) dealloc +{ + [reader release]; + [nav release]; + [window release]; + [super dealloc]; +} + +- (void) scan +{ + found = NO; + imageView.image = nil; + typeLabel.text = nil; + dataLabel.text = nil; + [self.tableView reloadData]; + [self presentModalViewController: reader + animated: YES]; +} + +- (void) setCheck: (BOOL) state + forCell: (UITableViewCell*) cell +{ + cell.accessoryType = + ((state) + ? UITableViewCellAccessoryCheckmark + : UITableViewCellAccessoryNone); +} + +- (void) setSource: (int) state +{ + NSArray *sources = [sections objectAtIndex: 0]; + for(UITableViewCell *cell in sources) + [self setCheck: (cell.tag == state) + forCell: cell]; +} + +// UINavigationControllerDelegate + +- (void) navigationController: (UINavigationController*) _nav + willShowViewController: (UIViewController*) vc + animated: (BOOL) animated +{ + self.navigationItem.rightBarButtonItem = + [[[UIBarButtonItem alloc] + initWithTitle: @"Scan!" + style: UIBarButtonItemStyleDone + target: self + action: @selector(scan)] + autorelease]; +} + +// UITableViewDataSource + +- (NSInteger) numberOfSectionsInTableView: (UITableView*) view +{ + return(sections.count - !found); +} + +- (NSInteger) tableView: (UITableView*) view + numberOfRowsInSection: (NSInteger) idx +{ + NSArray *section = [sections objectAtIndex: idx]; + return(section.count); +} + +- (UITableViewCell*) tableView: (UITableView*) view + cellForRowAtIndexPath: (NSIndexPath*) path +{ + return([[sections objectAtIndex: path.section] + objectAtIndex: path.row]); +} + +- (NSString*) tableView: (UITableView*) view + titleForHeaderInSection: (NSInteger) idx +{ + static NSString * const titles[] = { + @"SourceType", + @"Reader Configuration", + @"Decode Results", + }; + assert(idx < NUM_SECTIONS); + return(titles[idx]); +} + +// UITableViewDelegate + +- (NSIndexPath*) tableView: (UITableView*) view + willSelectRowAtIndexPath: (NSIndexPath*) path +{ + if(path.section == RESULT_SECTION) + return(nil); + return(path); +} + +- (void) tableView: (UITableView*) view + didSelectRowAtIndexPath: (NSIndexPath*) path +{ + [view deselectRowAtIndexPath: path + animated: YES]; + + UITableViewCell *cell = [view cellForRowAtIndexPath: path]; + + switch(path.section) { + case SOURCE_SECTION: + [self setSource: reader.sourceType = cell.tag]; + break; + case CONFIG_SECTION: { + BOOL state; + switch(path.row) { + case 0: + reader.showsHelpOnFail = !reader.showsHelpOnFail; + state = reader.showsHelpOnFail; + break; + case 1: + @try { + reader.showsZBarControls = !reader.showsZBarControls; + } + @catch (...) { + UIAlertView *alert = + [[UIAlertView alloc] + initWithTitle: @"Unsupported" + message: @"Not available for iPhone OS < 3.1" + delegate: nil + cancelButtonTitle: @"Cancel" + otherButtonTitles: nil]; + [alert show]; + [alert release]; + } + state = reader.showsZBarControls; + break; + default: + assert(0); + } + [self setCheck: state + forCell: cell]; + break; + } + case RESULT_SECTION: + break; + default: + assert(0); + } +} + +- (CGFloat) tableView: (UITableView*) view + heightForRowAtIndexPath: (NSIndexPath*) path +{ + if(path.section < RESULT_SECTION) + return(44); + + switch(path.row) { + case 0: return(44); + case 1: return(dataHeight); + case 2: return(300); + default: assert(0); + } +} + +// ZBarReaderDelegate + +- (void) imagePickerController: (UIImagePickerController*) picker + didFinishPickingMediaWithInfo: (NSDictionary*) info +{ + found = YES; + id results = + [info objectForKey: ZBarReaderControllerResults]; + assert(results); + + NSLog(@"imagePickerController:didFinishPickingMediaWithInfo:\n"); + UIImage *image = [info objectForKey: UIImagePickerControllerOriginalImage]; + assert(image); + imageView.image = image; + + int quality = 0, n = 0; + for(ZBarSymbol *sym in results) { + NSLog(@" [%d] type=%@ data=%@\n", n, sym.typeName, sym.data); + + if(sym.quality > quality) { + typeLabel.text = sym.typeName; + NSString *data = sym.data; + dataLabel.text = data; + + CGSize size = [data sizeWithFont: [UIFont systemFontOfSize: 17] + constrainedToSize: CGSizeMake(288, 2000) + lineBreakMode: UILineBreakModeCharacterWrap]; + dataHeight = size.height + 26; + if(dataHeight > 2000) + dataHeight = 2000; + } + n++; + } + assert(n); + + [picker dismissModalViewControllerAnimated: YES]; + [self.tableView reloadData]; +} + +- (void) imagePickerControllerDidCancel: (UIImagePickerController*) picker +{ + NSLog(@"imagePickerControllerDidCancel:\n"); + [picker dismissModalViewControllerAnimated: YES]; +} + +- (void) readerControllerDidFailToRead: (ZBarReaderController*) _reader + withRetry: (BOOL) retry +{ + NSLog(@"readerControllerDidFailToRead: retry=%s\n", + (retry) ? "YES" : "NO"); + if(!retry) + [_reader dismissModalViewControllerAnimated: YES]; +} + +@end + + +int main (int argc, char *argv[]) +{ +#ifdef VALGRIND + if(argc < 2 || (argc >= 2 && strcmp(argv[1], "-valgrind"))) + execl(VALGRIND, VALGRIND, + "--log-file=/tmp/memcheck.log", "--leak-check=full", + argv[0], "-valgrind", + NULL); +#endif + + NSAutoreleasePool *pool = [NSAutoreleasePool new]; + int rc = UIApplicationMain(argc, argv, nil, @"AppDelegate"); + [pool release]; + return(rc); +} diff --git a/test/iphone/readertest.plist b/test/iphone/readertest.plist new file mode 100644 index 0000000..62a8126 --- /dev/null +++ b/test/iphone/readertest.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + net.sourceforge.zbar.test.readertest + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + + diff --git a/test/iphone/readertest.xcodeproj/project.pbxproj b/test/iphone/readertest.xcodeproj/project.pbxproj new file mode 100755 index 0000000..027d1df --- /dev/null +++ b/test/iphone/readertest.xcodeproj/project.pbxproj @@ -0,0 +1,273 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 45; + objects = { + +/* Begin PBXBuildFile section */ + 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; + 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; + 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; }; + DC0BB57C10B124EB000448CB /* zbar-button.png in Resources */ = {isa = PBXBuildFile; fileRef = DC0BB57A10B124EB000448CB /* zbar-button.png */; }; + DC0BB57D10B124EB000448CB /* zbar-helpicons.png in Resources */ = {isa = PBXBuildFile; fileRef = DC0BB57B10B124EB000448CB /* zbar-helpicons.png */; }; + DCD6E0D010B0AD41002005CD /* readertest.m in Sources */ = {isa = PBXBuildFile; fileRef = DCD6E0CF10B0AD41002005CD /* readertest.m */; }; + DCD6E13C10B0AFD4002005CD /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD6E13B10B0AFD4002005CD /* libiconv.dylib */; }; + DCD6E13D10B0AFDE002005CD /* libzbar.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD6E0E610B0AE16002005CD /* libzbar.a */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + DCD6E0E510B0AE16002005CD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DCD6E0DE10B0AE16002005CD /* zbar.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D2AAC07E0554694100DB518D; + remoteInfo = zbar; + }; + DCD6E11810B0AE7B002005CD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DCD6E0DE10B0AE16002005CD /* zbar.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = D2AAC07D0554694100DB518D; + remoteInfo = zbar; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 1D6058910D05DD3D006BFB54 /* readertest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = readertest.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 288765FC0DF74451002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + DC0BB57A10B124EB000448CB /* zbar-button.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "zbar-button.png"; path = "../../iphone/res/zbar-button.png"; sourceTree = SOURCE_ROOT; }; + DC0BB57B10B124EB000448CB /* zbar-helpicons.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "zbar-helpicons.png"; path = "../../iphone/res/zbar-helpicons.png"; sourceTree = SOURCE_ROOT; }; + DCD6E0CE10B0AD41002005CD /* prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = prefix.pch; sourceTree = ""; }; + DCD6E0CF10B0AD41002005CD /* readertest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = readertest.m; sourceTree = ""; }; + DCD6E0D810B0AD55002005CD /* readertest.plist */ = {isa = PBXFileReference; explicitFileType = text.plist.info; fileEncoding = 4; path = readertest.plist; sourceTree = ""; }; + DCD6E0DE10B0AE16002005CD /* zbar.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = zbar.xcodeproj; path = ../../iphone/zbar.xcodeproj; sourceTree = SOURCE_ROOT; }; + DCD6E13B10B0AFD4002005CD /* libiconv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libiconv.dylib; path = usr/lib/libiconv.dylib; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, + 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, + 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */, + DCD6E13C10B0AFD4002005CD /* libiconv.dylib in Frameworks */, + DCD6E13D10B0AFDE002005CD /* libzbar.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 19C28FACFE9D520D11CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 1D6058910D05DD3D006BFB54 /* readertest.app */, + ); + name = Products; + sourceTree = ""; + }; + 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { + isa = PBXGroup; + children = ( + DCD6E0CF10B0AD41002005CD /* readertest.m */, + DCD6E0CE10B0AD41002005CD /* prefix.pch */, + DCD6E0D810B0AD55002005CD /* readertest.plist */, + DC0BB57A10B124EB000448CB /* zbar-button.png */, + DC0BB57B10B124EB000448CB /* zbar-helpicons.png */, + DCD6E0DE10B0AE16002005CD /* zbar.xcodeproj */, + 29B97323FDCFA39411CA2CEA /* Frameworks */, + 19C28FACFE9D520D11CA2CBB /* Products */, + DCD6E13B10B0AFD4002005CD /* libiconv.dylib */, + ); + name = CustomTemplate; + sourceTree = ""; + }; + 29B97323FDCFA39411CA2CEA /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, + 1D30AB110D05D00D00671497 /* Foundation.framework */, + 288765FC0DF74451002DB57D /* CoreGraphics.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + DCD6E0DF10B0AE16002005CD /* Products */ = { + isa = PBXGroup; + children = ( + DCD6E0E610B0AE16002005CD /* libzbar.a */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1D6058900D05DD3D006BFB54 /* readertest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "readertest" */; + buildPhases = ( + 1D60588D0D05DD3D006BFB54 /* Resources */, + 1D60588E0D05DD3D006BFB54 /* Sources */, + 1D60588F0D05DD3D006BFB54 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + DCD6E11910B0AE7B002005CD /* PBXTargetDependency */, + ); + name = readertest; + productName = readertest; + productReference = 1D6058910D05DD3D006BFB54 /* readertest.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29B97313FDCFA39411CA2CEA /* Project object */ = { + isa = PBXProject; + buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "readertest" */; + compatibilityVersion = "Xcode 3.1"; + hasScannedForEncodings = 1; + mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = DCD6E0DF10B0AE16002005CD /* Products */; + ProjectRef = DCD6E0DE10B0AE16002005CD /* zbar.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 1D6058900D05DD3D006BFB54 /* readertest */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + DCD6E0E610B0AE16002005CD /* libzbar.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libzbar.a; + remoteRef = DCD6E0E510B0AE16002005CD /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + 1D60588D0D05DD3D006BFB54 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DC0BB57C10B124EB000448CB /* zbar-button.png in Resources */, + DC0BB57D10B124EB000448CB /* zbar-helpicons.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1D60588E0D05DD3D006BFB54 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DCD6E0D010B0AD41002005CD /* readertest.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + DCD6E11910B0AE7B002005CD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = zbar; + targetProxy = DCD6E11810B0AE7B002005CD /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 1D6058940D05DD3E006BFB54 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = prefix.pch; + INFOPLIST_FILE = readertest.plist; + PRODUCT_NAME = readertest; + }; + name = Debug; + }; + 1D6058950D05DD3E006BFB54 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = prefix.pch; + INFOPLIST_FILE = readertest.plist; + PRODUCT_NAME = readertest; + }; + name = Release; + }; + C01FCF4F08A954540054247B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ../../include; + PREBINDING = NO; + SDKROOT = iphoneos3.0; + }; + name = Debug; + }; + C01FCF5008A954540054247B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ../../include; + PREBINDING = NO; + SDKROOT = iphoneos3.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "readertest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1D6058940D05DD3E006BFB54 /* Debug */, + 1D6058950D05DD3E006BFB54 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C01FCF4E08A954540054247B /* Build configuration list for PBXProject "readertest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C01FCF4F08A954540054247B /* Debug */, + C01FCF5008A954540054247B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; +} From 94e2775d1c9cd73371f38c7e857820f8f1abe6a2 Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 22 Nov 2009 10:36:59 -0500 Subject: [PATCH 173/328] add symbol class type name interface --- include/zbar/ZBarSymbol.h | 2 ++ iphone/ZBarSymbol.m | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/include/zbar/ZBarSymbol.h b/include/zbar/ZBarSymbol.h index 0cc70fb..c94f3b2 100644 --- a/include/zbar/ZBarSymbol.h +++ b/include/zbar/ZBarSymbol.h @@ -58,4 +58,6 @@ using namespace zbar; - (id) initWithSymbol: (const zbar_symbol_t*) symbol; ++ (NSString*) nameForType: (zbar_symbol_type_t) type; + @end diff --git a/iphone/ZBarSymbol.m b/iphone/ZBarSymbol.m index 9f514f5..2a9a9d5 100644 --- a/iphone/ZBarSymbol.m +++ b/iphone/ZBarSymbol.m @@ -27,6 +27,11 @@ @implementation ZBarSymbol @dynamic type, typeName, data, quality, count, zbarSymbol; ++ (NSString*) nameForType: (zbar_symbol_type_t) type +{ + return([NSString stringWithUTF8String: zbar_get_symbol_name(type)]); +} + - (id) initWithSymbol: (zbar_symbol_t*) sym { if(self = [super init]) { @@ -52,8 +57,7 @@ - (zbar_symbol_type_t) type - (NSString*) typeName { - zbar_symbol_type_t type = zbar_symbol_get_type(symbol); - return([NSString stringWithUTF8String: zbar_get_symbol_name(type)]); + return([[self class] nameForType: zbar_symbol_get_type(symbol)]); } - (NSString*) data From adec1e9be22ef554713675ca61fdf1d24e79e0e7 Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 25 Nov 2009 16:54:52 -0500 Subject: [PATCH 174/328] 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 --- ChangeLog | 5 + include/zbar.h | 8 + include/zbar/ZBarImage.h | 12 +- include/zbar/ZBarReaderController.h | 33 +- include/zbar/ZBarSymbol.h | 3 + iphone/ZBarImage.m | 43 ++- iphone/ZBarImageScanner.m | 9 +- iphone/ZBarReaderController.m | 341 +++++++++++++++--- iphone/ZBarSymbol.m | 26 +- iphone/debug.h | 31 +- iphone/prefix.pch | 1 + test/iphone/readertest.m | 44 ++- .../readertest.xcodeproj/project.pbxproj | 14 +- zbar/symbol.c | 6 + 14 files changed, 469 insertions(+), 107 deletions(-) diff --git a/ChangeLog b/ChangeLog index cd48610..89c7550 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,9 @@ current: + * 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 python distutils build infrastructure * add Obj-C wrapper diff --git a/include/zbar.h b/include/zbar.h index 0ab1d62..362a37d 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -357,6 +357,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); + /*@}*/ /*------------------------------------------------------------*/ diff --git a/include/zbar/ZBarImage.h b/include/zbar/ZBarImage.h index 08cb651..bf74f6c 100644 --- a/include/zbar/ZBarImage.h +++ b/include/zbar/ZBarImage.h @@ -34,6 +34,7 @@ using namespace zbar; @interface ZBarImage : NSObject { zbar_image_t *zimg; + double t_convert; } @property (nonatomic) unsigned long format; @@ -44,10 +45,13 @@ using namespace zbar; @property (readonly, nonatomic) ZBarSymbolSet *symbols; @property (readonly, nonatomic) zbar_image_t *zbarImage; -- initWithImage: (zbar_image_t*) image; -- initWithUIImage: (UIImage*) image; -- initWithUIImage: (UIImage*) image - size: (CGSize) size; +- (id) initWithImage: (zbar_image_t*) image; +- (id) initWithCGImage: (CGImageRef) image; +- (id) initWithCGImage: (CGImageRef) image + size: (CGSize) size; +- (id) initWithCGImage: (CGImageRef) image + crop: (CGRect) crop + size: (CGSize) size; - (void) setData: (const void*) data withLength: (unsigned long) length; diff --git a/include/zbar/ZBarReaderController.h b/include/zbar/ZBarReaderController.h index 30d32d4..af9f318 100644 --- a/include/zbar/ZBarReaderController.h +++ b/include/zbar/ZBarReaderController.h @@ -29,6 +29,11 @@ using namespace zbar; #endif +typedef enum { + ZBarReaderControllerCameraModeDefault = 0, + ZBarReaderControllerCameraModeSampling, +} ZBarReaderControllerCameraMode; + @class ZBarReaderController, ZBarHelpController; @protocol ZBarReaderDelegate @@ -48,26 +53,44 @@ using namespace zbar; { ZBarImageScanner *scanner; ZBarHelpController *help; - UIView *overlay, *controls; + UIView *overlay, *boxView; + CALayer *boxLayer; + + UIToolbar *toolbar; + UIBarButtonItem *cancelBtn, *scanBtn, *space[3]; id readerDelegate; - BOOL hasOverlay, showsZBarControls, showsHelpOnFail; + BOOL showsZBarControls, showsHelpOnFail, takesPicture; + ZBarReaderControllerCameraMode cameraMode; + + BOOL hasOverlay, sampling; + uint64_t t_frame; + double dt_frame; + + ZBarSymbol *symbol; } // access to configure image scanner @property (readonly, nonatomic) ZBarImageScanner *scanner; -// barcode result recipient +// barcode result recipient (NB don't use delegate) @property (nonatomic, assign) id readerDelegate; -// whether to use alternate control set (FIXME broken for NO) +// whether to use alternate control set @property (nonatomic) BOOL showsZBarControls; // whether to display helpful information when decoding fails @property (nonatomic) BOOL showsHelpOnFail; +// how to use the camera (when sourceType == ...Camera) +@property (nonatomic) ZBarReaderControllerCameraMode cameraMode; + +// whether to automatically take a full picture when a barcode is detected +// (when cameraMode != ...Default) +@property (nonatomic) BOOL takesPicture; + // direct scanner interface - scan UIImage and return something enumerable -- (id ) scanImage: (UIImage*) image; +- (id ) scanImage: (CGImageRef) image; @end diff --git a/include/zbar/ZBarSymbol.h b/include/zbar/ZBarSymbol.h index c94f3b2..071f8b5 100644 --- a/include/zbar/ZBarSymbol.h +++ b/include/zbar/ZBarSymbol.h @@ -33,10 +33,12 @@ using namespace zbar; @interface ZBarSymbolSet : NSObject { const zbar_symbol_set_t *set; + BOOL filterSymbols; } @property (readonly, nonatomic) int count; @property (readonly, nonatomic) const zbar_symbol_set_t *zbarSymbolSet; +@property (nonatomic) BOOL filterSymbols; - (id) initWithSymbolSet: (const zbar_symbol_set_t*) set; @@ -55,6 +57,7 @@ using namespace zbar; @property (readonly, nonatomic) int count; @property (readonly, nonatomic) ZBarSymbolSet *components; @property (readonly, nonatomic) const zbar_symbol_t *zbarSymbol; +@property (readonly, nonatomic) CGRect bounds; - (id) initWithSymbol: (const zbar_symbol_t*) symbol; diff --git a/iphone/ZBarImage.m b/iphone/ZBarImage.m index c94d01b..526ddcc 100644 --- a/iphone/ZBarImage.m +++ b/iphone/ZBarImage.m @@ -71,12 +71,12 @@ - (void) dealloc [super dealloc]; } -- (id) initWithUIImage: (UIImage*) image +- (id) initWithCGImage: (CGImageRef) image + crop: (CGRect) crop size: (CGSize) size { if(!(self = [self init])) return(nil); - timer_start; unsigned int w = size.width + 0.5; @@ -91,26 +91,49 @@ - (id) initWithUIImage: (UIImage*) image zbar_image_set_format(zimg, *(int*)"Y800"); 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; + crop.origin.y *= -scale; + crop.size.height = scale * (CGFloat)CGImageGetHeight(image); + // compensate for wacky origin + crop.origin.y += size.height - crop.size.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, CGRectMake(0, 0, w, h), image.CGImage); - CGContextRelease(ctx); - zlog(@"ZBarImage: converted UIImage %gx%g to %dx%d Y800 in %gs\n", - image.size.width, image.size.height, w, h, - timer_elapsed(t_start, timer_now())); + CGContextDrawImage(ctx, crop, image); + CGContextRelease(ctx); + t_convert = timer_elapsed(t_start, timer_now()); return(self); } -- (id) initWithUIImage: (UIImage*) image +- (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 { - return([self initWithUIImage: image - size: image.size]); + CGRect crop = CGRectMake(0, 0, + CGImageGetWidth(image), + CGImageGetHeight(image)); + return([self initWithCGImage: image + crop: crop + size: crop.size]); } - (zbar_image_t*) image diff --git a/iphone/ZBarImageScanner.m b/iphone/ZBarImageScanner.m index 192e797..3c5fa48 100644 --- a/iphone/ZBarImageScanner.m +++ b/iphone/ZBarImageScanner.m @@ -79,14 +79,7 @@ - (void) setSymbology: (zbar_symbol_type_t) sym - (NSInteger) scanImage: (ZBarImage*) image { - timer_start; - - int nsyms = zbar_scan_image(scanner, image.zbarImage); - - zlog(@"ZBarImageScanner: scanned %d symbols in %gs\n", - nsyms, timer_elapsed(t_start, timer_now())); - - return(nsyms); + return(zbar_scan_image(scanner, image.zbarImage)); } @end diff --git a/iphone/ZBarReaderController.m b/iphone/ZBarReaderController.m index a853327..9bfefa3 100644 --- a/iphone/ZBarReaderController.m +++ b/iphone/ZBarReaderController.m @@ -21,9 +21,6 @@ // http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#import -#import - #import #import "ZBarHelpController.h" #import "debug.h" @@ -32,10 +29,12 @@ NSString* const ZBarReaderControllerResults = @"ZBarReaderControllerResults"; +// expose undocumented API +CGImageRef UIGetScreenImage(void); @implementation ZBarReaderController -@synthesize scanner, readerDelegate, showsHelpOnFail; +@synthesize scanner, readerDelegate, showsHelpOnFail, takesPicture, cameraMode; @dynamic showsZBarControls; - (id) init @@ -48,50 +47,59 @@ - (id) init if([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]) self.sourceType = UIImagePickerControllerSourceTypeCamera; + cameraMode = ZBarReaderControllerCameraModeSampling; } return(self); } - (void) initOverlay { - CGRect r = self.view.bounds; - overlay = [[UIView alloc] initWithFrame: r]; + CGRect bounds = self.view.bounds; + overlay = [[UIView alloc] initWithFrame: bounds]; overlay.backgroundColor = [UIColor clearColor]; - controls = [UIView new]; + 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]; - UIToolbar *toolbar = [UIToolbar new]; + toolbar = [UIToolbar new]; toolbar.barStyle = UIBarStyleBlackOpaque; - [toolbar sizeToFit]; - r.origin.y = r.size.height - 56; - r.size.height = 56; - controls.frame = r; - r.origin.y = r.origin.x = 0; + r.origin.y = r.size.height; + r.size.height = 54; toolbar.frame = r; - [controls addSubview: toolbar]; - [toolbar release]; - UIButton *btn = _ZBarButton(48, .1, .7, .1); - btn.frame = CGRectMake(r.size.width / 4 + 4, 4, - r.size.width / 2 - 8, 48); - [btn addTarget: self - action: @selector(takePicture) - forControlEvents: UIControlEventTouchDown]; - [btn setTitle: @"Scan!" - forState: UIControlStateNormal]; - [controls addSubview: btn]; - - btn = _ZBarButton(40, .85, .15, .15); - btn.frame = CGRectMake(4, 4, r.size.width / 4 - 8, 48); - [btn addTarget: self - action: @selector(cancel) - forControlEvents: UIControlEventTouchUpInside]; - [btn setTitle: @"done" - forState: UIControlStateNormal]; - [controls addSubview: btn]; - - controls.hidden = YES; - [overlay addSubview: controls]; + 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; } - (void) viewDidLoad @@ -106,8 +114,20 @@ - (void) cleanup { [overlay release]; overlay = nil; - [controls release]; - controls = 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; + } [help release]; help = nil; } @@ -126,6 +146,13 @@ - (void) dealloc [super dealloc]; } +- (void) scan +{ + scanBtn.enabled = NO; + self.view.userInteractionEnabled = NO; + [self takePicture]; +} + - (void) cancel { [self performSelector: @selector(imagePickerControllerDidCancel:) @@ -133,6 +160,12 @@ - (void) cancel afterDelay: 0.1]; } +- (void) reenable +{ + scanBtn.enabled = YES; + self.view.userInteractionEnabled = YES; +} + - (void) viewWillAppear: (BOOL) animated { if(help) { @@ -146,22 +179,234 @@ - (void) viewWillAppear: (BOOL) animated if(showsZBarControls || ![self cameraOverlayView]) [self setCameraOverlayView: overlay]; - if(showsZBarControls) + UIView *activeOverlay = [self cameraOverlayView]; + + if(showsZBarControls) { + if(!toolbar.superview) + [overlay addSubview: toolbar]; [self setShowsCameraControls: NO]; - else if([self cameraOverlayView] == overlay) - [self setShowsCameraControls: YES]; + } + else { + [toolbar removeFromSuperview]; + if(activeOverlay == overlay) + [self setShowsCameraControls: YES]; + } - controls.hidden = !showsZBarControls; + self.view.userInteractionEnabled = YES; + if(cameraMode == ZBarReaderControllerCameraModeSampling) + toolbar.items = [NSArray arrayWithObjects: + cancelBtn, space[0], nil]; + 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]; + } + + if(cameraMode == ZBarReaderControllerCameraModeSampling) { + t_frame = timer_now(); + dt_frame = 0; + sampling = YES; + boxLayer.opacity = 0; + if(boxView.superview != activeOverlay) + [boxView removeFromSuperview]; + if(!boxView.superview) + [activeOverlay addSubview: boxView]; + + [scanner setSymbology: 0 + config: ZBAR_CFG_X_DENSITY + to: 2]; + [scanner setSymbology: 0 + config: ZBAR_CFG_Y_DENSITY + to: 2]; + scanner.enableCache = YES; + + [self performSelector: @selector(scanScreen) + withObject: nil + afterDelay: 1]; +#ifndef NDEBUG + [self performSelector: @selector(dumpFPS) + withObject: nil + afterDelay: 4]; +#endif + } + else { + sampling = NO; + [boxView removeFromSuperview]; + } } + [super viewWillAppear: animated]; } +- (void) viewWillDisappear: (BOOL) animated +{ + sampling = NO; + scanner.enableCache = NO; + [super viewWillDisappear: animated]; +} + +- (void) scanScreen +{ + if(!sampling) + return; + + 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; + + // FIXME ugly hack: use private API to sample screen + CGImageRef image = UIGetScreenImage(); + + CGRect crop = CGRectMake(0, 0, + CGImageGetWidth(image), CGImageGetHeight(image)); + if(crop.size.width > crop.size.height) + crop.size.width -= 54; + else + crop.size.height -= 54; + + ZBarImage *zimg = [[ZBarImage alloc] + initWithCGImage: image + crop: crop + size: crop.size]; + CGImageRelease(image); + + [scanner scanImage: zimg]; + [zimg release]; + + ZBarSymbol *sym = nil; + ZBarSymbolSet *results = scanner.results; + results.filterSymbols = NO; + for(ZBarSymbol *s in results) + if(!sym || sym.quality < s.quality) + sym = s; + + 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]; + + [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 = 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 > 0) + boxLayer.opacity = 0; + } + [CATransaction commit]; +} + +- (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]; +} + +#ifndef NDEBUG +- (void) dumpFPS +{ + if(!sampling) + return; + [self performSelector: @selector(dumpFPS) + withObject: nil + afterDelay: 2]; + zlog(@"fps=%g", 1 / dt_frame); +} +#endif + - (void) imagePickerController: (UIImagePickerController*) picker didFinishPickingMediaWithInfo: (NSDictionary*) info { UIImage *img = [info objectForKey: UIImagePickerControllerOriginalImage]; - id results = [self scanImage: img]; + id results = nil; + if(sampling) { + results = [NSArray arrayWithObject: symbol]; + [symbol release]; + symbol = nil; + } + else + results = [self scanImage: img.CGImage]; + + [self performSelector: @selector(reenable) + withObject: nil + afterDelay: .25]; if(results) { NSMutableDictionary *newinfo = [info mutableCopy]; @@ -251,7 +496,7 @@ - (void) setDelegate: (id )delegate; } -- (id ) scanImage: (UIImage*) image +- (id ) scanImage: (CGImageRef) image size: (CGSize) size { timer_start; @@ -275,7 +520,7 @@ - (void) setDelegate: (id ) scanImage: (UIImage*) image +- (id ) scanImage: (CGImageRef) image { - CGSize size = image.size; + CGSize size = CGSizeMake(CGImageGetWidth(image), + CGImageGetHeight(image)); if(size.width > 1280 || size.height > 1280) { size.width /= 2; size.height /= 2; @@ -327,6 +573,7 @@ - (void) setDelegate: (id syms = [self scanImage: image size: size]; + if(!syms) { // make one more attempt for close up, grainy images size.width /= 2; diff --git a/iphone/ZBarSymbol.m b/iphone/ZBarSymbol.m index 2a9a9d5..c021050 100644 --- a/iphone/ZBarSymbol.m +++ b/iphone/ZBarSymbol.m @@ -87,18 +87,40 @@ - (ZBarSymbolSet*) components 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(self = [super init]) { set = s; zbar_symbol_set_ref(s, 1); + filterSymbols = YES; } return(self); } @@ -129,8 +151,10 @@ - (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState*) state const zbar_symbol_t *sym = (void*)state->state; // FIXME if(sym) sym = zbar_symbol_next(sym); - else if(set) + 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] diff --git a/iphone/debug.h b/iphone/debug.h index 6d0ee00..76a4382 100644 --- a/iphone/debug.h +++ b/iphone/debug.h @@ -21,33 +21,28 @@ // http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#include +#include #ifdef DEBUG_OBJC # define zlog(fmt, ...) \ NSLog(@"ZBarReaderController: " fmt , ##__VA_ARGS__) #define timer_start \ - long t_start = timer_now(); + uint64_t t_start = timer_now(); -static inline long timer_now () +#else +# define zlog(...) +# define timer_start +#endif + +static inline uint64_t timer_now () { - struct tms now; - times(&now); - return(now.tms_utime + now.tms_stime); + return(mach_absolute_time()); } -static inline double timer_elapsed (long start, long end) +static inline double timer_elapsed (uint64_t start, uint64_t end) { - double clk_tck = sysconf(_SC_CLK_TCK); - if(!clk_tck) - return(-1); - return((end - start) / clk_tck); + mach_timebase_info_data_t info; + mach_timebase_info(&info); + return((double)(end - start) * info.numer / (info.denom * 1000000000.)); } - -#else -# define zlog(...) -# define timer_start -# define timer_now(...) 0 -# define timer_elapsed(...) 0 -#endif diff --git a/iphone/prefix.pch b/iphone/prefix.pch index bb09ddd..aaf5d7d 100644 --- a/iphone/prefix.pch +++ b/iphone/prefix.pch @@ -2,4 +2,5 @@ # import # import # import +# import #endif diff --git a/test/iphone/readertest.m b/test/iphone/readertest.m index bb0a751..0c43e34 100644 --- a/test/iphone/readertest.m +++ b/test/iphone/readertest.m @@ -6,6 +6,7 @@ enum { SOURCE_SECTION = 0, + CAMODE_SECTION, CONFIG_SECTION, RESULT_SECTION, NUM_SECTIONS @@ -82,11 +83,25 @@ - (void) viewDidLoad } } - static NSString* const configNames[] = { - @"showsHelpOnFail", @"showsZBarControls" + static NSString* const modeNames[] = { + @"Default", @"Sampling" }; - NSMutableArray *configs = [NSMutableArray arrayWithCapacity: 2]; + NSMutableArray *modes = [NSMutableArray arrayWithCapacity: 2]; for(int i = 0; i < 2; i++) { + UITableViewCell *cell = [UITableViewCell new]; + cell.textLabel.text = modeNames[i]; + cell.tag = i; + if(reader.cameraMode == i) + cell.accessoryType = UITableViewCellAccessoryCheckmark; + [modes addObject: cell]; + [cell release]; + } + + static NSString* const configNames[] = { + @"showsHelpOnFail", @"showsZBarControls", @"takesPicture", + }; + NSMutableArray *configs = [NSMutableArray arrayWithCapacity: 3]; + for(int i = 0; i < 3; i++) { UITableViewCell *cell = [UITableViewCell new]; cell.textLabel.text = configNames[i]; if([reader performSelector: NSSelectorFromString(configNames[i])]) @@ -114,7 +129,8 @@ - (void) viewDidLoad [NSArray arrayWithObjects: typeCell, dataCell, imageCell, nil]; sections = - [[NSArray arrayWithObjects: sources, configs, results, nil] retain]; + [[NSArray arrayWithObjects: sources, modes, configs, results, nil] + retain]; } - (void) viewDidUnload @@ -156,11 +172,11 @@ - (void) setCheck: (BOOL) state : UITableViewCellAccessoryNone); } -- (void) setSource: (int) state +- (void) setCheckForTag: (int) tag + inSection: (int) section { - NSArray *sources = [sections objectAtIndex: 0]; - for(UITableViewCell *cell in sources) - [self setCheck: (cell.tag == state) + for(UITableViewCell *cell in [sections objectAtIndex: section]) + [self setCheck: (cell.tag == tag) forCell: cell]; } @@ -205,6 +221,7 @@ - (NSString*) tableView: (UITableView*) view { static NSString * const titles[] = { @"SourceType", + @"CameraMode", @"Reader Configuration", @"Decode Results", }; @@ -232,7 +249,12 @@ - (void) tableView: (UITableView*) view switch(path.section) { case SOURCE_SECTION: - [self setSource: reader.sourceType = cell.tag]; + [self setCheckForTag: reader.sourceType = cell.tag + inSection: SOURCE_SECTION]; + break; + case CAMODE_SECTION: + [self setCheckForTag: reader.cameraMode = cell.tag + inSection: CAMODE_SECTION]; break; case CONFIG_SECTION: { BOOL state; @@ -258,6 +280,10 @@ - (void) tableView: (UITableView*) view } state = reader.showsZBarControls; break; + case 2: + reader.takesPicture = !reader.takesPicture; + state = reader.takesPicture; + break; default: assert(0); } diff --git a/test/iphone/readertest.xcodeproj/project.pbxproj b/test/iphone/readertest.xcodeproj/project.pbxproj index 027d1df..16afe96 100755 --- a/test/iphone/readertest.xcodeproj/project.pbxproj +++ b/test/iphone/readertest.xcodeproj/project.pbxproj @@ -12,9 +12,10 @@ 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; }; DC0BB57C10B124EB000448CB /* zbar-button.png in Resources */ = {isa = PBXBuildFile; fileRef = DC0BB57A10B124EB000448CB /* zbar-button.png */; }; DC0BB57D10B124EB000448CB /* zbar-helpicons.png in Resources */ = {isa = PBXBuildFile; fileRef = DC0BB57B10B124EB000448CB /* zbar-helpicons.png */; }; + DCB9118510BC5DA200B907F0 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCB9118410BC5DA200B907F0 /* QuartzCore.framework */; }; + DCB9118810BC5DB500B907F0 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD6E13B10B0AFD4002005CD /* libiconv.dylib */; }; + DCB9119B10BC5DCB00B907F0 /* libzbar.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD6E0E610B0AE16002005CD /* libzbar.a */; }; DCD6E0D010B0AD41002005CD /* readertest.m in Sources */ = {isa = PBXBuildFile; fileRef = DCD6E0CF10B0AD41002005CD /* readertest.m */; }; - DCD6E13C10B0AFD4002005CD /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD6E13B10B0AFD4002005CD /* libiconv.dylib */; }; - DCD6E13D10B0AFDE002005CD /* libzbar.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD6E0E610B0AE16002005CD /* libzbar.a */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -41,6 +42,7 @@ 288765FC0DF74451002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; DC0BB57A10B124EB000448CB /* zbar-button.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "zbar-button.png"; path = "../../iphone/res/zbar-button.png"; sourceTree = SOURCE_ROOT; }; DC0BB57B10B124EB000448CB /* zbar-helpicons.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "zbar-helpicons.png"; path = "../../iphone/res/zbar-helpicons.png"; sourceTree = SOURCE_ROOT; }; + DCB9118410BC5DA200B907F0 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; DCD6E0CE10B0AD41002005CD /* prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = prefix.pch; sourceTree = ""; }; DCD6E0CF10B0AD41002005CD /* readertest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = readertest.m; sourceTree = ""; }; DCD6E0D810B0AD55002005CD /* readertest.plist */ = {isa = PBXFileReference; explicitFileType = text.plist.info; fileEncoding = 4; path = readertest.plist; sourceTree = ""; }; @@ -56,8 +58,9 @@ 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */, - DCD6E13C10B0AFD4002005CD /* libiconv.dylib in Frameworks */, - DCD6E13D10B0AFDE002005CD /* libzbar.a in Frameworks */, + DCB9118510BC5DA200B907F0 /* QuartzCore.framework in Frameworks */, + DCB9118810BC5DB500B907F0 /* libiconv.dylib in Frameworks */, + DCB9119B10BC5DCB00B907F0 /* libzbar.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -83,7 +86,6 @@ DCD6E0DE10B0AE16002005CD /* zbar.xcodeproj */, 29B97323FDCFA39411CA2CEA /* Frameworks */, 19C28FACFE9D520D11CA2CBB /* Products */, - DCD6E13B10B0AFD4002005CD /* libiconv.dylib */, ); name = CustomTemplate; sourceTree = ""; @@ -94,6 +96,8 @@ 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, 1D30AB110D05D00D00671497 /* Foundation.framework */, 288765FC0DF74451002DB57D /* CoreGraphics.framework */, + DCB9118410BC5DA200B907F0 /* QuartzCore.framework */, + DCD6E13B10B0AFD4002005CD /* libiconv.dylib */, ); name = Frameworks; sourceTree = ""; diff --git a/zbar/symbol.c b/zbar/symbol.c index 37e86a2..abcebd3 100644 --- a/zbar/symbol.c +++ b/zbar/symbol.c @@ -242,3 +242,9 @@ zbar_symbol_set_first_symbol (const zbar_symbol_set_t *syms) return(sym->next); return(syms->head); } + +const zbar_symbol_t* +zbar_symbol_set_first_unfiltered (const zbar_symbol_set_t *syms) +{ + return(syms->head); +} From 9f7b0415e2400e98f5145a0a90bf21e1731dbad6 Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 30 Nov 2009 18:46:50 -0500 Subject: [PATCH 175/328] iphone: add help via info button for realtime scanning --- include/zbar/ZBarReaderController.h | 1 + iphone/ZBarHelpController.h | 3 ++ iphone/ZBarHelpController.m | 16 +++++++++- iphone/ZBarImage.m | 2 +- iphone/ZBarReaderController.m | 46 +++++++++++++++++++++-------- 5 files changed, 54 insertions(+), 14 deletions(-) diff --git a/include/zbar/ZBarReaderController.h b/include/zbar/ZBarReaderController.h index af9f318..323b2dd 100644 --- a/include/zbar/ZBarReaderController.h +++ b/include/zbar/ZBarReaderController.h @@ -58,6 +58,7 @@ typedef enum { UIToolbar *toolbar; UIBarButtonItem *cancelBtn, *scanBtn, *space[3]; + UIButton *infoBtn; id readerDelegate; BOOL showsZBarControls, showsHelpOnFail, takesPicture; diff --git a/iphone/ZBarHelpController.h b/iphone/ZBarHelpController.h index 12f8d9b..a3f1e76 100644 --- a/iphone/ZBarHelpController.h +++ b/iphone/ZBarHelpController.h @@ -27,11 +27,14 @@ @interface ZBarHelpController : UIViewController { + NSString *title; id delegate; } @property (nonatomic, assign) id delegate; +- (id) initWithTitle: (NSString*) title; + @end extern UIButton *_ZBarButton (CGFloat size, CGFloat r, CGFloat g, CGFloat b); diff --git a/iphone/ZBarHelpController.m b/iphone/ZBarHelpController.m index 137b44d..0cd1f27 100644 --- a/iphone/ZBarHelpController.m +++ b/iphone/ZBarHelpController.m @@ -99,6 +99,20 @@ @implementation ZBarHelpController @synthesize delegate; +- (id) initWithTitle: (NSString*) t +{ + if(self = [super init]) + title = [t retain]; + return(self); +} + +- (void) dealloc +{ + [title release]; + title = nil; + [super dealloc]; +} + - (UILabel*) addLabelAt: (CGRect) frame withText: (NSString*) text font: (UIFont*) font @@ -130,7 +144,7 @@ - (void) viewDidLoad r.size.height = size.height * 19 / 115; UILabel *label = [self addLabelAt: r - withText: @"No Barcode Found" + withText: title font: [UIFont boldSystemFontOfSize: size.height * 12 / 115]]; label.textAlignment = UITextAlignmentCenter; label.adjustsFontSizeToFitWidth = YES; diff --git a/iphone/ZBarImage.m b/iphone/ZBarImage.m index 526ddcc..4ec63de 100644 --- a/iphone/ZBarImage.m +++ b/iphone/ZBarImage.m @@ -77,7 +77,7 @@ - (id) initWithCGImage: (CGImageRef) image { if(!(self = [self init])) return(nil); - timer_start; + uint64_t t_start = timer_now(); unsigned int w = size.width + 0.5; unsigned int h = size.height + 0.5; diff --git a/iphone/ZBarReaderController.m b/iphone/ZBarReaderController.m index 9bfefa3..5da8a78 100644 --- a/iphone/ZBarReaderController.m +++ b/iphone/ZBarReaderController.m @@ -52,6 +52,22 @@ - (id) init return(self); } +- (void) showHelpOverlay +{ + if(!help) { + help = [[ZBarHelpController alloc] + initWithTitle: @"Barcode Reader"]; + help.delegate = self; + } + help.wantsFullScreenLayout = YES; + help.view.alpha = 0; + [[self cameraOverlayView] addSubview: help.view]; + [UIView beginAnimations: @"ZBarHelp" + context: nil]; + help.view.alpha = 1; + [UIView commitAnimations]; +} + - (void) initOverlay { CGRect bounds = self.view.bounds; @@ -100,6 +116,14 @@ - (void) initOverlay 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(showHelpOverlay) + forControlEvents: UIControlEventTouchUpInside]; } - (void) viewDidLoad @@ -128,6 +152,8 @@ - (void) cleanup [space[i] release]; space[i] = nil; } + [infoBtn release]; + infoBtn = nil; [help release]; help = nil; } @@ -182,12 +208,15 @@ - (void) viewWillAppear: (BOOL) animated UIView *activeOverlay = [self cameraOverlayView]; if(showsZBarControls) { - if(!toolbar.superview) + if(!toolbar.superview) { [overlay addSubview: toolbar]; + [overlay addSubview: infoBtn]; + } [self setShowsCameraControls: NO]; } else { [toolbar removeFromSuperview]; + [infoBtn removeFromSuperview]; if(activeOverlay == overlay) [self setShowsCameraControls: YES]; } @@ -425,18 +454,11 @@ - (void) imagePickerController: (UIImagePickerController*) picker BOOL camera = (self.sourceType == UIImagePickerControllerSourceTypeCamera); BOOL retry = !camera || (hasOverlay && ![self showsCameraControls]); if(showsHelpOnFail && retry) { - help = [ZBarHelpController new]; + help = [[ZBarHelpController alloc] + initWithTitle: @"No Barcode Found"]; help.delegate = self; - - if(camera) { - help.wantsFullScreenLayout = YES; - help.view.alpha = 0; - [[self cameraOverlayView] addSubview: help.view]; - [UIView beginAnimations: @"ZBarHelp" - context: nil]; - help.view.alpha = 1; - [UIView commitAnimations]; - } + if(camera) + [self showHelpOverlay]; else [self presentModalViewController: help animated: YES]; From b58d99733999223292751bde7c31d5dbeb957715 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 3 Dec 2009 07:51:19 -0500 Subject: [PATCH 176/328] report QR immediately for video (no inter-frame consistency check) --- ChangeLog | 1 + zbar/img_scanner.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 89c7550..35b63d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * report QR immediately for video (no inter-frame consistency check) * realtime scanning for iphone widget - uses UIGetScreenImage() (NB private) - ZBarImage from CGImage (instead of UIImage) diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index bf80772..0db1a1c 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -295,6 +295,7 @@ static inline void cache_sym (zbar_image_scanner_t *iscn, zbar_symbol_t *sym) { if(iscn->enable_cache) { + char qr = (sym->type == ZBAR_QRCODE); zbar_symbol_t *entry = cache_lookup(iscn, sym); if(!entry) { /* FIXME reuse sym */ @@ -302,7 +303,7 @@ static inline void cache_sym (zbar_image_scanner_t *iscn, sym->datalen + 1); memcpy(entry->data, sym->data, sym->datalen); entry->time = sym->time - CACHE_HYSTERESIS; - entry->cache_count = -CACHE_CONSISTENCY; + entry->cache_count = (qr) ? 0 : -CACHE_CONSISTENCY; /* add to cache */ entry->next = iscn->cache; iscn->cache = entry; @@ -315,7 +316,7 @@ static inline void cache_sym (zbar_image_scanner_t *iscn, int far_thresh = (age >= CACHE_HYSTERESIS); int dup = (entry->cache_count >= 0); if((!dup && !near_thresh) || far_thresh) - entry->cache_count = -CACHE_CONSISTENCY; + entry->cache_count = (qr) ? 0 : -CACHE_CONSISTENCY; else if(dup || near_thresh) entry->cache_count++; From 19f30298b4a3f0b509c30e055162690a05d6fc1b Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 3 Dec 2009 07:56:22 -0500 Subject: [PATCH 177/328] report QR immediately for video (no inter-frame consistency check) --- ChangeLog | 1 + zbar/img_scanner.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index cd48610..3890d1f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * report QR immediately for video (no inter-frame consistency check) * iphone widget back compat updates, add basic test app * add python distutils build infrastructure * add Obj-C wrapper diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index bf80772..0db1a1c 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -295,6 +295,7 @@ static inline void cache_sym (zbar_image_scanner_t *iscn, zbar_symbol_t *sym) { if(iscn->enable_cache) { + char qr = (sym->type == ZBAR_QRCODE); zbar_symbol_t *entry = cache_lookup(iscn, sym); if(!entry) { /* FIXME reuse sym */ @@ -302,7 +303,7 @@ static inline void cache_sym (zbar_image_scanner_t *iscn, sym->datalen + 1); memcpy(entry->data, sym->data, sym->datalen); entry->time = sym->time - CACHE_HYSTERESIS; - entry->cache_count = -CACHE_CONSISTENCY; + entry->cache_count = (qr) ? 0 : -CACHE_CONSISTENCY; /* add to cache */ entry->next = iscn->cache; iscn->cache = entry; @@ -315,7 +316,7 @@ static inline void cache_sym (zbar_image_scanner_t *iscn, int far_thresh = (age >= CACHE_HYSTERESIS); int dup = (entry->cache_count >= 0); if((!dup && !near_thresh) || far_thresh) - entry->cache_count = -CACHE_CONSISTENCY; + entry->cache_count = (qr) ? 0 : -CACHE_CONSISTENCY; else if(dup || near_thresh) entry->cache_count++; From d571fa47eb4a6c2f61dc8c2f3ac6bacdddc62097 Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 18 Dec 2009 10:26:48 -0500 Subject: [PATCH 178/328] 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) --- ChangeLog | 7 + include/zbar/ZBarReaderController.h | 41 +- iphone/ZBarImage.m | 21 +- iphone/ZBarReaderController.m | 381 +++++++++++------- test/iphone/entitlements.plist | 8 + test/iphone/readertest.m | 16 +- .../readertest.xcodeproj/project.pbxproj | 35 ++ 7 files changed, 350 insertions(+), 159 deletions(-) create mode 100644 test/iphone/entitlements.plist diff --git a/ChangeLog b/ChangeLog index 35b63d7..875ba04 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,11 @@ current: + * 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) * report QR immediately for video (no inter-frame consistency check) * realtime scanning for iphone widget - uses UIGetScreenImage() (NB private) diff --git a/include/zbar/ZBarReaderController.h b/include/zbar/ZBarReaderController.h index 323b2dd..e4564cd 100644 --- a/include/zbar/ZBarReaderController.h +++ b/include/zbar/ZBarReaderController.h @@ -30,10 +30,24 @@ using namespace zbar; #endif typedef enum { + // default interface provided by UIImagePickerController - user manually + // captures an image by pressing a button ZBarReaderControllerCameraModeDefault = 0, + + // automatically scan by taking screenshots with UIGetScreenImage(). + // resolution is limited by the screen, so this is inappropriate for + // longer codes ZBarReaderControllerCameraModeSampling, + + // automatically scan by rapidly taking pictures with takePicture. + // tradeoff resolution with frame rate by adjusting the crop, and size + // properties of the reader along with the density configs of the image + // scanner + ZBarReaderControllerCameraModeSequence, + } ZBarReaderControllerCameraMode; + @class ZBarReaderController, ZBarHelpController; @protocol ZBarReaderDelegate @@ -61,8 +75,10 @@ typedef enum { UIButton *infoBtn; id readerDelegate; - BOOL showsZBarControls, showsHelpOnFail, takesPicture; + BOOL showsZBarControls, showsHelpOnFail, takesPicture, enableCache; ZBarReaderControllerCameraMode cameraMode; + CGRect scanCrop; + NSInteger maxScanDimension; BOOL hasOverlay, sampling; uint64_t t_frame; @@ -83,13 +99,32 @@ typedef enum { // whether to display helpful information when decoding fails @property (nonatomic) BOOL showsHelpOnFail; -// how to use the camera (when sourceType == ...Camera) +// how to use the camera (when sourceType == Camera) @property (nonatomic) ZBarReaderControllerCameraMode cameraMode; // whether to automatically take a full picture when a barcode is detected -// (when cameraMode != ...Default) +// (when cameraMode == Sampling) @property (nonatomic) BOOL takesPicture; +// whether to use the "cache" for realtime modes (default YES). this can be +// used to safely disable the inter-frame consistency and duplicate checks, +// speeding up recognition, iff: +// 1. the controller is dismissed when a barcode is read and +// 2. unreliable symbologies are disabled (all EAN/UPC variants and I2/5) +@property (nonatomic) BOOL enableCache; + +// crop images for scanning. the original image will be cropped to this +// rectangle before scanning. the rectangle is normalized to the image size +// and aspect ratio; useful values will place the rectangle between 0 and 1 +// on each axis, where the x-axis corresponds to the image major axis. +// defaults to the full image (0, 0, 1, 1). +@property (nonatomic) CGRect scanCrop; + +// 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. +@property (nonatomic) NSInteger maxScanDimension; + // direct scanner interface - scan UIImage and return something enumerable - (id ) scanImage: (CGImageRef) image; diff --git a/iphone/ZBarImage.m b/iphone/ZBarImage.m index 4ec63de..67cc4ff 100644 --- a/iphone/ZBarImage.m +++ b/iphone/ZBarImage.m @@ -96,10 +96,11 @@ - (id) initWithCGImage: (CGImageRef) image crop.origin.x *= -scale; crop.size.width = scale * (CGFloat)CGImageGetWidth(image); scale = size.height / crop.size.height; - crop.origin.y *= -scale; - crop.size.height = scale * (CGFloat)CGImageGetHeight(image); + CGFloat height = CGImageGetHeight(image); // compensate for wacky origin - crop.origin.y += size.height - crop.size.height; + 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(); @@ -109,6 +110,20 @@ - (id) initWithCGImage: (CGImageRef) image 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()); diff --git a/iphone/ZBarReaderController.m b/iphone/ZBarReaderController.m index 5da8a78..4202592 100644 --- a/iphone/ZBarReaderController.m +++ b/iphone/ZBarReaderController.m @@ -25,7 +25,9 @@ #import "ZBarHelpController.h" #import "debug.h" -#define MIN_QUALITY 10 +#ifndef MIN_QUALITY +# define MIN_QUALITY 10 +#endif NSString* const ZBarReaderControllerResults = @"ZBarReaderControllerResults"; @@ -34,7 +36,8 @@ @implementation ZBarReaderController -@synthesize scanner, readerDelegate, showsHelpOnFail, takesPicture, cameraMode; +@synthesize scanner, readerDelegate, cameraMode, scanCrop, maxScanDimension, + showsHelpOnFail, takesPicture, enableCache; @dynamic showsZBarControls; - (id) init @@ -43,7 +46,18 @@ - (id) init showsHelpOnFail = YES; hasOverlay = showsZBarControls = [self respondsToSelector: @selector(cameraOverlayView)]; + enableCache = 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; @@ -222,48 +236,52 @@ - (void) viewWillAppear: (BOOL) animated } self.view.userInteractionEnabled = YES; - if(cameraMode == ZBarReaderControllerCameraModeSampling) - toolbar.items = [NSArray arrayWithObjects: - cancelBtn, space[0], nil]; - 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]; - } + sampling = (cameraMode == ZBarReaderControllerCameraModeSampling || + cameraMode == ZBarReaderControllerCameraModeSequence); + + if(sampling) { + toolbar.items = [NSArray arrayWithObjects: + cancelBtn, space[0], nil]; - if(cameraMode == ZBarReaderControllerCameraModeSampling) { t_frame = timer_now(); dt_frame = 0; - sampling = YES; boxLayer.opacity = 0; if(boxView.superview != activeOverlay) [boxView removeFromSuperview]; if(!boxView.superview) [activeOverlay addSubview: boxView]; + scanner.enableCache = enableCache; - [scanner setSymbology: 0 - config: ZBAR_CFG_X_DENSITY - to: 2]; - [scanner setSymbology: 0 - config: ZBAR_CFG_Y_DENSITY - to: 2]; - scanner.enableCache = YES; + 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; - [self performSelector: @selector(scanScreen) + meth = @selector(scanScreen); + } + else + meth = @selector(takePicture); + + [self performSelector: meth withObject: nil - afterDelay: 1]; -#ifndef NDEBUG + afterDelay: 2]; +#ifdef DEBUG_OBJC [self performSelector: @selector(dumpFPS) withObject: nil afterDelay: 4]; #endif } else { - sampling = NO; + 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]; } } @@ -278,11 +296,45 @@ - (void) viewWillDisappear: (BOOL) animated [super viewWillDisappear: animated]; } -- (void) scanScreen + +- (BOOL) showsZBarControls +{ + return(showsZBarControls); +} + +- (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 ) delegate +{ + self.readerDelegate = (id )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; @@ -290,60 +342,76 @@ - (void) scanScreen dt_frame = timer_elapsed(t_frame, now); t_frame = now; - // FIXME ugly hack: use private API to sample screen - CGImageRef image = UIGetScreenImage(); - - CGRect crop = CGRectMake(0, 0, - CGImageGetWidth(image), CGImageGetHeight(image)); - if(crop.size.width > crop.size.height) - crop.size.width -= 54; + 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 - crop.size.height -= 54; + 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: crop.size]; - CGImageRelease(image); - - [scanner scanImage: zimg]; + size: size]; + int nsyms = [scanner scanImage: zimg]; [zimg release]; + return(nsyms); +} + +- (ZBarSymbol*) extractBestResult: (BOOL) filter +{ ZBarSymbol *sym = nil; ZBarSymbolSet *results = scanner.results; - results.filterSymbols = NO; + results.filterSymbols = filter; for(ZBarSymbol *s in results) if(!sym || sym.quality < s.quality) sym = s; + return(sym); +} - 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]; - +- (void) updateBox: (ZBarSymbol*) sym +{ [CATransaction begin]; [CATransaction setAnimationDuration: .3]; [CATransaction setAnimationTimingFunction: @@ -353,6 +421,8 @@ - (void) scanScreen CGFloat alpha = boxLayer.opacity; if(sym) { CGRect r = sym.bounds; + // FIXME reverse image scaling + //r = crop.origin + ; if(r.size.width > 16 && r.size.height > 16) { r = CGRectInset(r, -16, -16); if(alpha > .25) { @@ -369,12 +439,59 @@ - (void) scanScreen else { if(alpha > .1) boxLayer.opacity = alpha / 2; - else if(alpha > 0) + else if(alpha) boxLayer.opacity = 0; } [CATransaction commit]; } +- (void) scanScreen +{ + if(!sampling) + return; + + // FIXME ugly hack: use private API to sample screen + CGImageRef image = UIGetScreenImage(); + + int nsyms = [self scanImage: image + withScaling: 0]; + CGImageRelease(image); + + ZBarSymbol *sym = nil; + if(nsyms) + 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]; + + [self updateBox: sym]; +} + - (void) captureScreen { CGImageRef screen = UIGetScreenImage(); @@ -407,17 +524,40 @@ - (void) captureScreen afterDelay: 0.001]; } -#ifndef NDEBUG -- (void) dumpFPS +- (void) scanSequence: (UIImage*) image { - if(!sampling) + if(!sampling) { + [image release]; return; - [self performSelector: @selector(dumpFPS) + } + + int nsyms = [self scanImage: image.CGImage + withScaling: 0]; + + ZBarSymbol *sym = nil; + if(nsyms) + sym = [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]]; + [image release]; + + // reschedule + [self performSelector: @selector(takePicture) withObject: nil - afterDelay: 2]; - zlog(@"fps=%g", 1 / dt_frame); + afterDelay: 0.001]; + + [self updateBox: sym]; } -#endif - (void) imagePickerController: (UIImagePickerController*) picker didFinishPickingMediaWithInfo: (NSDictionary*) info @@ -425,13 +565,19 @@ - (void) imagePickerController: (UIImagePickerController*) picker UIImage *img = [info objectForKey: UIImagePickerControllerOriginalImage]; id results = nil; - if(sampling) { + if(!sampling) + results = [self scanImage: img.CGImage]; + else if(cameraMode == ZBarReaderControllerCameraModeSampling) { results = [NSArray arrayWithObject: symbol]; [symbol release]; symbol = nil; } - else - results = [self scanImage: img.CGImage]; + else { + [self performSelector: @selector(scanSequence:) + withObject: [img retain] + afterDelay: 0.001]; + return; + } [self performSelector: @selector(reenable) withObject: nil @@ -496,56 +642,19 @@ - (void) helpController: (ZBarHelpController*) hlp [hlp dismissModalViewControllerAnimated: YES]; } -- (BOOL) showsZBarControls -{ - return(showsZBarControls); -} - -- (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 ) delegate -{ - self.readerDelegate = (id )delegate; -} - - (id ) scanImage: (CGImageRef) image - size: (CGSize) size { timer_start; - // limit the maximum number of scan passes - int density; - if(size.width > 480) - density = (size.width / 240 + 1) / 2; - else - density = 1; - [scanner setSymbology: 0 - config: ZBAR_CFG_X_DENSITY - to: density]; + int nsyms = [self scanImage: image + withScaling: 0]; - if(size.height > 480) - 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 - size: size]; - int nsyms = [scanner scanImage: zimg]; - [zimg release]; + 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) { @@ -583,28 +692,4 @@ - (void) setDelegate: (id ) scanImage: (CGImageRef) image -{ - CGSize size = CGSizeMake(CGImageGetWidth(image), - CGImageGetHeight(image)); - if(size.width > 1280 || size.height > 1280) { - size.width /= 2; - size.height /= 2; - } - - id syms = - [self scanImage: image - size: size]; - - if(!syms) { - // make one more attempt for close up, grainy images - size.width /= 2; - size.height /= 2; - syms = [self scanImage: image - size: size]; - } - - return(syms); -} - @end diff --git a/test/iphone/entitlements.plist b/test/iphone/entitlements.plist new file mode 100644 index 0000000..ce373e1 --- /dev/null +++ b/test/iphone/entitlements.plist @@ -0,0 +1,8 @@ + + + + + get-task-allow + + + diff --git a/test/iphone/readertest.m b/test/iphone/readertest.m index 0c43e34..7d56781 100644 --- a/test/iphone/readertest.m +++ b/test/iphone/readertest.m @@ -84,10 +84,10 @@ - (void) viewDidLoad } static NSString* const modeNames[] = { - @"Default", @"Sampling" + @"Default", @"Sampling", @"Sequence" }; - NSMutableArray *modes = [NSMutableArray arrayWithCapacity: 2]; - for(int i = 0; i < 2; i++) { + NSMutableArray *modes = [NSMutableArray arrayWithCapacity: 3]; + for(int i = 0; i < 3; i++) { UITableViewCell *cell = [UITableViewCell new]; cell.textLabel.text = modeNames[i]; cell.tag = i; @@ -99,9 +99,10 @@ - (void) viewDidLoad static NSString* const configNames[] = { @"showsHelpOnFail", @"showsZBarControls", @"takesPicture", + @"enableCache" }; - NSMutableArray *configs = [NSMutableArray arrayWithCapacity: 3]; - for(int i = 0; i < 3; i++) { + NSMutableArray *configs = [NSMutableArray arrayWithCapacity: 4]; + for(int i = 0; i < 4; i++) { UITableViewCell *cell = [UITableViewCell new]; cell.textLabel.text = configNames[i]; if([reader performSelector: NSSelectorFromString(configNames[i])]) @@ -284,6 +285,10 @@ - (void) tableView: (UITableView*) view reader.takesPicture = !reader.takesPicture; state = reader.takesPicture; break; + case 3: + reader.enableCache = !reader.enableCache; + state = reader.enableCache; + break; default: assert(0); } @@ -310,6 +315,7 @@ - (CGFloat) tableView: (UITableView*) view case 2: return(300); default: assert(0); } + return(44); } // ZBarReaderDelegate diff --git a/test/iphone/readertest.xcodeproj/project.pbxproj b/test/iphone/readertest.xcodeproj/project.pbxproj index 16afe96..c57a86b 100755 --- a/test/iphone/readertest.xcodeproj/project.pbxproj +++ b/test/iphone/readertest.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; }; DC0BB57C10B124EB000448CB /* zbar-button.png in Resources */ = {isa = PBXBuildFile; fileRef = DC0BB57A10B124EB000448CB /* zbar-button.png */; }; DC0BB57D10B124EB000448CB /* zbar-helpicons.png in Resources */ = {isa = PBXBuildFile; fileRef = DC0BB57B10B124EB000448CB /* zbar-helpicons.png */; }; + DC1C8DED10DAAEBA004C0F9E /* entitlements.plist in Resources */ = {isa = PBXBuildFile; fileRef = DC1C8DEC10DAAEBA004C0F9E /* entitlements.plist */; }; DCB9118510BC5DA200B907F0 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCB9118410BC5DA200B907F0 /* QuartzCore.framework */; }; DCB9118810BC5DB500B907F0 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD6E13B10B0AFD4002005CD /* libiconv.dylib */; }; DCB9119B10BC5DCB00B907F0 /* libzbar.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD6E0E610B0AE16002005CD /* libzbar.a */; }; @@ -42,6 +43,7 @@ 288765FC0DF74451002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; DC0BB57A10B124EB000448CB /* zbar-button.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "zbar-button.png"; path = "../../iphone/res/zbar-button.png"; sourceTree = SOURCE_ROOT; }; DC0BB57B10B124EB000448CB /* zbar-helpicons.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "zbar-helpicons.png"; path = "../../iphone/res/zbar-helpicons.png"; sourceTree = SOURCE_ROOT; }; + DC1C8DEC10DAAEBA004C0F9E /* entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = entitlements.plist; sourceTree = ""; }; DCB9118410BC5DA200B907F0 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; DCD6E0CE10B0AD41002005CD /* prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = prefix.pch; sourceTree = ""; }; DCD6E0CF10B0AD41002005CD /* readertest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = readertest.m; sourceTree = ""; }; @@ -78,6 +80,7 @@ 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { isa = PBXGroup; children = ( + DC1C8DEC10DAAEBA004C0F9E /* entitlements.plist */, DCD6E0CF10B0AD41002005CD /* readertest.m */, DCD6E0CE10B0AD41002005CD /* prefix.pch */, DCD6E0D810B0AD55002005CD /* readertest.plist */, @@ -171,6 +174,7 @@ files = ( DC0BB57C10B124EB000448CB /* zbar-button.png in Resources */, DC0BB57D10B124EB000448CB /* zbar-helpicons.png in Resources */, + DC1C8DED10DAAEBA004C0F9E /* entitlements.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -250,6 +254,35 @@ }; name = Release; }; + DC1C8DF010DAAED5004C0F9E /* AdHoc */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1"; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ../../include; + PREBINDING = NO; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + SDKROOT = iphoneos3.0; + }; + name = AdHoc; + }; + DC1C8DF110DAAED5004C0F9E /* AdHoc */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CODE_SIGN_ENTITLEMENTS = entitlements.plist; + COPY_PHASE_STRIP = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = prefix.pch; + INFOPLIST_FILE = readertest.plist; + PRODUCT_NAME = readertest; + }; + name = AdHoc; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -258,6 +291,7 @@ buildConfigurations = ( 1D6058940D05DD3E006BFB54 /* Debug */, 1D6058950D05DD3E006BFB54 /* Release */, + DC1C8DF110DAAED5004C0F9E /* AdHoc */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -267,6 +301,7 @@ buildConfigurations = ( C01FCF4F08A954540054247B /* Debug */, C01FCF5008A954540054247B /* Release */, + DC1C8DF010DAAED5004C0F9E /* AdHoc */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; From e91244777223290299e1ef190074ec57e61a7127 Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 5 Jan 2010 10:48:35 -0500 Subject: [PATCH 179/328] fix inconsistent fourcc endian handling bugs (bug #2918994) - thanks to jdccdevel for a patch! - add fourcc conversion and parse interfaces to zbar.h --- ChangeLog | 3 +++ Makefile.am | 2 +- examples/scan_image.c | 2 +- gtk/zbargtk.c | 17 ++++++----------- include/zbar.h | 22 ++++++++++++++++++++++ include/zbar/Image.h | 7 +------ include/zbar/Processor.h | 4 ++-- include/zbar/QZBarImage.h | 2 +- include/zbar/Video.h | 2 +- iphone/ZBarImage.m | 4 ++-- perl/typemap | 10 ++-------- python/image.c | 9 ++++----- test/test_images.h | 5 +---- zbar/image.c | 2 +- zbar/image.h | 5 +---- zbarimg/zbarimg.c | 2 +- 16 files changed, 50 insertions(+), 48 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3890d1f..16c878b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,7 @@ current: + * 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) * iphone widget back compat updates, add basic test app * add python distutils build infrastructure diff --git a/Makefile.am b/Makefile.am index 9608be6..6906d22 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ AM_CPPFLAGS = -I$(srcdir)/include -AM_CFLAGS = -Wall -Wno-parentheses +AM_CFLAGS = -Wall -Wno-parentheses -Werror AM_CXXFLAGS = $(AM_CFLAGS) ACLOCAL_AMFLAGS = -I config bin_PROGRAMS = diff --git a/examples/scan_image.c b/examples/scan_image.c index 52db035..40009ba 100644 --- a/examples/scan_image.c +++ b/examples/scan_image.c @@ -65,7 +65,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); diff --git a/gtk/zbargtk.c b/gtk/zbargtk.c index eb03227..46ed13f 100644 --- a/gtk/zbargtk.c +++ b/gtk/zbargtk.c @@ -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); @@ -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); diff --git a/include/zbar.h b/include/zbar.h index 0ab1d62..5ac5682 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -184,6 +184,28 @@ 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) + */ +#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. + */ +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); diff --git a/include/zbar/Image.h b/include/zbar/Image.h index e1d9644..1b4120d 100644 --- a/include/zbar/Image.h +++ b/include/zbar/Image.h @@ -143,12 +143,7 @@ class Image { /// 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); } diff --git a/include/zbar/Processor.h b/include/zbar/Processor.h index 51b0e1c..4652b11 100644 --- a/include/zbar/Processor.h +++ b/include/zbar/Processor.h @@ -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); } diff --git a/include/zbar/QZBarImage.h b/include/zbar/QZBarImage.h index ce98401..610b2da 100644 --- a/include/zbar/QZBarImage.h +++ b/include/zbar/QZBarImage.h @@ -53,7 +53,7 @@ class QZBarImage 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); diff --git a/include/zbar/Video.h b/include/zbar/Video.h index 2787d86..83733ef 100644 --- a/include/zbar/Video.h +++ b/include/zbar/Video.h @@ -92,7 +92,7 @@ class Video { /// 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); } diff --git a/iphone/ZBarImage.m b/iphone/ZBarImage.m index c94d01b..e591524 100644 --- a/iphone/ZBarImage.m +++ b/iphone/ZBarImage.m @@ -37,7 +37,7 @@ @implementation ZBarImage + (unsigned long) fourcc: (NSString*) format { - return(*(uint32_t*)[format UTF8String]); + return(zbar_fourcc_parse([format UTF8String])); } - (id) initWithImage: (zbar_image_t*) image @@ -88,7 +88,7 @@ - (id) initWithUIImage: (UIImage*) image assert(raw); zbar_image_set_data(zimg, raw, datalen, zbar_image_free_data); - zbar_image_set_format(zimg, *(int*)"Y800"); + zbar_image_set_format(zimg, zbar_fourcc('Y','8','0','0')); zbar_image_set_size(zimg, w, h); // generate grayscale image data diff --git a/perl/typemap b/perl/typemap index 2d6ef6b..6de93e5 100644 --- a/perl/typemap +++ b/perl/typemap @@ -30,14 +30,8 @@ T_ENUM T_FOURCC { if(SvPOK($arg)) { - STRLEN len; - char *str = SvPV($arg, len); - if(len != 4) - croak(\"invalid fourcc: \%s\", str); - $var = ((unsigned long)str[0] | - ((unsigned long)str[1] << 8) | - ((unsigned long)str[2] << 16) | - ((unsigned long)str[3] << 24)); + char *str = SvPV_nolen($arg); + $var = zbar_fourcc_parse(str); } else $var = SvUV($arg); diff --git a/python/image.c b/python/image.c index d0d778d..baa49a9 100644 --- a/python/image.c +++ b/python/image.c @@ -148,7 +148,7 @@ image_set_format (zbarImage *self, format); return(-1); } - zbar_image_set_format(self->zimg,*((unsigned long*)format)); + zbar_image_set_format(self->zimg, zbar_fourcc_parse(format)); return(0); } @@ -359,6 +359,7 @@ image_convert (zbarImage *self, format); return(NULL); } + unsigned long fourcc = zbar_fourcc_parse(format); zbarImage *img = PyObject_GC_New(zbarImage, &zbarImage_Type); if(!img) @@ -366,11 +367,9 @@ image_convert (zbarImage *self, img->data = NULL; if(width > 0 && height > 0) img->zimg = - zbar_image_convert_resize(self->zimg, - *((unsigned long*)format), - width, height); + zbar_image_convert_resize(self->zimg, fourcc, width, height); else - img->zimg = zbar_image_convert(self->zimg, *((unsigned long*)format)); + img->zimg = zbar_image_convert(self->zimg, fourcc); if(!img->zimg) { /* FIXME propagate exception */ diff --git a/test/test_images.h b/test/test_images.h index c1bc379..c507516 100644 --- a/test/test_images.h +++ b/test/test_images.h @@ -23,10 +23,7 @@ #ifndef _TEST_IMAGES_H_ #define _TEST_IMAGES_H_ -/* adapted from v4l2 spec */ -#define fourcc(a, b, c, d) \ - ((uint32_t)(a) | ((uint32_t)(b) << 8) | \ - ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24)) +#define fourcc zbar_fourcc int test_image_check_cleanup(void); int test_image_bars(zbar_image_t*); diff --git a/zbar/image.c b/zbar/image.c index 04f681d..e928d4f 100644 --- a/zbar/image.c +++ b/zbar/image.c @@ -205,7 +205,7 @@ int zbar_image_write (const zbar_image_t *img, char filename[len]; strcpy(filename, filebase); int n = 0; - if(*(char*)&img->format >= ' ') + if(img->format & 0xff >= ' ') n = snprintf(filename, len, "%s.%.4s.zimg", filebase, (char*)&img->format); else diff --git a/zbar/image.h b/zbar/image.h index 8886ead..fe9af25 100644 --- a/zbar/image.h +++ b/zbar/image.h @@ -35,10 +35,7 @@ #include "symbol.h" #include "refcnt.h" -/* adapted from v4l2 spec */ -#define fourcc(a, b, c, d) \ - ((uint32_t)(a) | ((uint32_t)(b) << 8) | \ - ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24)) +#define fourcc zbar_fourcc /* unpack size/location of component */ #define RGB_SIZE(c) ((c) >> 5) diff --git a/zbarimg/zbarimg.c b/zbarimg/zbarimg.c index 5d2db34..17228f2 100644 --- a/zbarimg/zbarimg.c +++ b/zbarimg/zbarimg.c @@ -137,7 +137,7 @@ static int scan_image (const char *filename) zbar_image_t *zimage = zbar_image_create(); assert(zimage); - zbar_image_set_format(zimage, *(unsigned long*)"Y800"); + zbar_image_set_format(zimage, zbar_fourcc('Y','8','0','0')); int width = MagickGetImageWidth(images); int height = MagickGetImageHeight(images); From 4a11525556e0680e038bc533fa0405228f8c49f4 Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 6 Jan 2010 13:31:57 -0500 Subject: [PATCH 180/328] 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 --- ChangeLog | 5 +++ include/zbar.h | 36 ++++++++++++++- include/zbar/Decoder.h | 10 ++++- include/zbar/Symbol.h | 9 +++- include/zbar/ZBarSymbol.h | 3 +- iphone/ZBarSymbol.m | 7 ++- perl/Changes | 12 +++++ perl/ZBar.pm | 44 ++++++++++++++++++- perl/ZBar.xs | 26 ++++++++++- perl/ZBar/Symbol.pod | 8 +++- perl/t/Decoder.t | 12 ++++- perl/t/Image.t | 9 +++- perl/t/ZBar.t | 40 ++++++++++++++++- perl/typemap | 1 + python/decoder.c | 16 +++++-- python/enum.c | 15 ++++++- python/symbol.c | 11 ++++- python/test/test_zbar.py | 31 ++++++++++--- python/zbarmodule.c | 92 ++++++++++++++++++++++++++------------- python/zbarmodule.h | 5 ++- test/barcodetest.py | 8 ++-- zbar/decoder.c | 7 ++- zbar/decoder.h | 3 +- zbar/decoder/code128.c | 3 +- zbar/decoder/code39.c | 8 ++-- zbar/decoder/ean.c | 12 ++++- zbar/decoder/ean.h | 6 ++- zbar/decoder/i25.c | 3 +- zbar/decoder/pdf417.c | 3 +- zbar/decoder/qr_finder.c | 25 +++++++++++ zbar/img_scanner.c | 7 ++- zbar/processor.c | 5 ++- zbar/qrcode/qrdectxt.c | 12 ++++- zbar/symbol.c | 22 ++++++++-- zbar/symbol.h | 3 +- 35 files changed, 437 insertions(+), 82 deletions(-) diff --git a/ChangeLog b/ChangeLog index 16c878b..a0c644c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,9 @@ current: + * 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 diff --git a/include/zbar.h b/include/zbar.h index 5ac5682..5f4167a 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown + * Copyright 2007-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -103,6 +103,17 @@ typedef enum zbar_symbol_type_e { ZBAR_ADDON = 0x0700, /**< add-on flag mask */ } 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 */ @@ -171,6 +182,14 @@ extern const char *zbar_get_symbol_name(zbar_symbol_type_t sym); */ extern const char *zbar_get_addon_name(zbar_symbol_type_t sym); +/** 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. @@ -306,6 +325,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 @@ -1217,6 +1244,13 @@ 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 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. diff --git a/include/zbar/Decoder.h b/include/zbar/Decoder.h index 3e65d5e..b0c6764 100644 --- a/include/zbar/Decoder.h +++ b/include/zbar/Decoder.h @@ -1,5 +1,5 @@ //------------------------------------------------------------------------ -// Copyright 2007-2009 (c) Jeff Brown +// Copyright 2007-2010 (c) Jeff Brown // // This file is part of the ZBar Bar Code Reader. // @@ -149,6 +149,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) { diff --git a/include/zbar/Symbol.h b/include/zbar/Symbol.h index b47732a..018eac5 100644 --- a/include/zbar/Symbol.h +++ b/include/zbar/Symbol.h @@ -1,5 +1,5 @@ //------------------------------------------------------------------------ -// Copyright 2007-2009 (c) Jeff Brown +// Copyright 2007-2010 (c) Jeff Brown // // This file is part of the ZBar Bar Code Reader. // @@ -311,6 +311,13 @@ class Symbol { 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 { diff --git a/include/zbar/ZBarSymbol.h b/include/zbar/ZBarSymbol.h index c94f3b2..40b762e 100644 --- a/include/zbar/ZBarSymbol.h +++ b/include/zbar/ZBarSymbol.h @@ -1,5 +1,5 @@ //------------------------------------------------------------------------ -// Copyright 2009 (c) Jeff Brown +// Copyright 2009-2010 (c) Jeff Brown // // This file is part of the ZBar Bar Code Reader. // @@ -53,6 +53,7 @@ using namespace zbar; @property (readonly, nonatomic) NSString *data; @property (readonly, nonatomic) int quality; @property (readonly, nonatomic) int count; +@property (readonly, nonatomic) zbar_orientation_t orientation; @property (readonly, nonatomic) ZBarSymbolSet *components; @property (readonly, nonatomic) const zbar_symbol_t *zbarSymbol; diff --git a/iphone/ZBarSymbol.m b/iphone/ZBarSymbol.m index 2a9a9d5..9a3eb2e 100644 --- a/iphone/ZBarSymbol.m +++ b/iphone/ZBarSymbol.m @@ -1,5 +1,5 @@ //------------------------------------------------------------------------ -// Copyright 2009 (c) Jeff Brown +// Copyright 2009-2010 (c) Jeff Brown // // This file is part of the ZBar Bar Code Reader. // @@ -75,6 +75,11 @@ - (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); diff --git a/perl/Changes b/perl/Changes index 2bba2b3..26191a9 100644 --- a/perl/Changes +++ b/perl/Changes @@ -1,5 +1,17 @@ Revision history for Perl extension Barcode::ZBar. +current spadix + * add Symbol orientation and Decoder direction interfaces + +0.04 2009-10-23 spadix + * add result query interfaces to ImageScanner and Processor + +0.03 2009-09-24 spadix + * add support for binary symbol data + * fix symbol leaks + * add symbol quality metric + * add support for QR Code + 0.02 2009-04-16 spadix * project name change: package becomes Barcode::ZBar diff --git a/perl/ZBar.pm b/perl/ZBar.pm index 47cefa6..460c439 100644 --- a/perl/ZBar.pm +++ b/perl/ZBar.pm @@ -1,5 +1,5 @@ #------------------------------------------------------------------------ -# Copyright 2008-2009 (c) Jeff Brown +# Copyright 2008-2010 (c) Jeff Brown # # This file is part of the ZBar Bar Code Reader. # @@ -137,6 +137,46 @@ Dark area or colored bar segment. =back +Decoder configuration constants: + +=over 4 + +=item Config::ENABLE + +=item Config::ADD_CHECK + +=item Config::EMIT_CHECK + +=item Config::ASCII + +=item Config::MIN_LEN + +=item Config::MAX_LEN + +=item Config::POSITION + +=item Config::X_DENSITY + +=item Config::Y_DENSITY + +=back + +Symbol orientation constants: + +=over 4 + +=item Orient::UNKNOWN + +=item Orient::UP + +=item Orient::RIGHT + +=item Orient::DOWN + +=item Orient::LEFT + +=back + =head1 SEE ALSO @@ -156,7 +196,7 @@ Jeff Brown, Espadix@users.sourceforge.netE =head1 COPYRIGHT AND LICENSE -Copyright 2008-2009 (c) Jeff Brown Espadix@users.sourceforge.netE +Copyright 2008-2010 (c) Jeff Brown Espadix@users.sourceforge.netE 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 diff --git a/perl/ZBar.xs b/perl/ZBar.xs index ad6fc56..1eaad02 100644 --- a/perl/ZBar.xs +++ b/perl/ZBar.xs @@ -1,5 +1,5 @@ //------------------------------------------------------------------------ -// Copyright 2008-2009 (c) Jeff Brown +// Copyright 2008-2010 (c) Jeff Brown // // This file is part of the ZBar Bar Code Reader. // @@ -53,6 +53,7 @@ static AV *LOOKUP_zbar_color_t = NULL; static AV *LOOKUP_zbar_symbol_type_t = NULL; static AV *LOOKUP_zbar_error_t = NULL; static AV *LOOKUP_zbar_config_t = NULL; +static AV *LOOKUP_zbar_orientation_t = NULL; #define CONSTANT(typ, prefix, sym, name) \ do { \ @@ -283,6 +284,21 @@ BOOT: } +MODULE = Barcode::ZBar PACKAGE = Barcode::ZBar::Orient PREFIX = zbar_orientation_ + +BOOT: + { + HV *stash = gv_stashpv("Barcode::ZBar::Orient", TRUE); + + LOOKUP_zbar_orientation_t = newAV(); + CONSTANT(orientation, ORIENT_, UNKNOWN, "UNKNOWN"); + CONSTANT(orientation, ORIENT_, UP, "UP"); + CONSTANT(orientation, ORIENT_, RIGHT, "RIGHT"); + CONSTANT(orientation, ORIENT_, DOWN, "DOWN"); + CONSTANT(orientation, ORIENT_, LEFT, "LEFT"); + } + + MODULE = Barcode::ZBar PACKAGE = Barcode::ZBar::Symbol PREFIX = zbar_symbol_ BOOT: @@ -347,6 +363,10 @@ zbar_symbol_get_loc(symbol) av_push(pt, newSVuv(zbar_symbol_get_loc_y(symbol, i))); } +zbar_orientation_t +zbar_symbol_get_orientation(symbol) + Barcode::ZBar::Symbol symbol + SV * get_components(symbol) Barcode::ZBar::Symbol symbol @@ -712,6 +732,10 @@ zbar_symbol_type_t zbar_decoder_get_type(decoder) Barcode::ZBar::Decoder decoder +int +zbar_decoder_get_direction(decoder) + Barcode::ZBar::Decoder decoder + void zbar_decoder_set_handler(decoder, handler = 0, closure = 0) Barcode::ZBar::Decoder decoder diff --git a/perl/ZBar/Symbol.pod b/perl/ZBar/Symbol.pod index 4ccd9b5..e0f2188 100644 --- a/perl/ZBar/Symbol.pod +++ b/perl/ZBar/Symbol.pod @@ -1,5 +1,5 @@ #------------------------------------------------------------------------ -# Copyright 2008-2009 (c) Jeff Brown +# Copyright 2008-2010 (c) Jeff Brown # # This file is part of the ZBar Bar Code Reader. # @@ -72,6 +72,12 @@ Current cache count of the symbol. This integer value provides inter-scan reliability and redundancy information if enabled at the Barcode::ZBar::ImageScanner. +=item get_orientation() + +General orientation of decoded symbol. This returns one of the +Barcode::ZBar::Orient constants, which provide a coarse, axis-aligned +indication of symbol orientation. + =item get_components() Components of a composite result. This yields an array of physical diff --git a/perl/t/Decoder.t b/perl/t/Decoder.t index f7e16f4..07244cc 100755 --- a/perl/t/Decoder.t +++ b/perl/t/Decoder.t @@ -3,7 +3,7 @@ use warnings; use strict; -use Test::More tests => 13; +use Test::More tests => 15; ######################### @@ -19,7 +19,7 @@ $decoder->parse_config('enable'); ######################### can_ok($decoder, qw(set_config parse_config reset new_scan decode_width - get_color get_data get_type set_handler)); + get_color get_direction get_data get_type set_handler)); ######################### @@ -58,6 +58,10 @@ is($decoder->get_color(), Barcode::ZBar::SPACE, 'reset color'); ######################### +is($decoder->get_direction(), 0, 'reset direction'); + +######################### + $decoder->set_config(Barcode::ZBar::Symbol::QRCODE, Barcode::ZBar::Config::ENABLE, 0); @@ -82,6 +86,10 @@ is($decoder->get_color(), Barcode::ZBar::BAR, 'post-scan color'); ######################### +is($decoder->get_direction(), 1, 'decode direction'); + +######################### + is($handler_type, Barcode::ZBar::Symbol::EAN13, 'handler type'); ######################### diff --git a/perl/t/Image.t b/perl/t/Image.t index 7df06e9..a8ce007 100755 --- a/perl/t/Image.t +++ b/perl/t/Image.t @@ -3,7 +3,7 @@ use warnings; use strict; -use Test::More tests => 22; +use Test::More tests => 23; ######################### @@ -94,7 +94,8 @@ SKIP: { ######################### - can_ok($sym, qw(get_type get_data get_quality get_count get_loc)); + can_ok($sym, qw(get_type get_data get_quality get_count get_loc + get_orientation)); ######################### @@ -133,6 +134,10 @@ SKIP: { ######################### + is($sym->get_orientation(), Barcode::ZBar::Orient::UP, 'orientation'); + + ######################### + my @comps = $sym->get_components(); is(scalar(@comps), 0, 'components size'); diff --git a/perl/t/ZBar.t b/perl/t/ZBar.t index f9a7e8e..64d1f02 100755 --- a/perl/t/ZBar.t +++ b/perl/t/ZBar.t @@ -3,7 +3,7 @@ use warnings; use strict; -use Test::More tests => 3; +use Test::More tests => 31; ######################### @@ -20,3 +20,41 @@ Barcode::ZBar::increase_verbosity(); pass('verbosity'); ######################### + +# performs (2 * n) tests +sub test_enum { + my $name = shift; + foreach my $test (@_) { + my $enum = $test->[0]; + + is($enum, $test->[1], "$name enum/string compare"); + + ######################### + + ok($enum == $test->[2], "$name enum/numeric compare"); + } +} + +test_enum('config', + [Barcode::ZBar::Config::ENABLE, 'enable', 0], + [Barcode::ZBar::Config::ADD_CHECK, 'add-check', 1], + [Barcode::ZBar::Config::EMIT_CHECK, 'emit-check', 2], + [Barcode::ZBar::Config::ASCII, 'ascii', 3], + [Barcode::ZBar::Config::MIN_LEN, 'min-length', 32], + [Barcode::ZBar::Config::MAX_LEN, 'max-length', 33], + [Barcode::ZBar::Config::POSITION, 'position', 128], + [Barcode::ZBar::Config::X_DENSITY, 'x-density', 256], + [Barcode::ZBar::Config::Y_DENSITY, 'y-density', 257], +); + +######################### + +test_enum('orientation', + [Barcode::ZBar::Orient::UNKNOWN, 'UNKNOWN', -1], + [Barcode::ZBar::Orient::UP, 'UP', 0], + [Barcode::ZBar::Orient::RIGHT, 'RIGHT', 1], + [Barcode::ZBar::Orient::DOWN, 'DOWN', 2], + [Barcode::ZBar::Orient::LEFT, 'LEFT', 3], +); + +######################### diff --git a/perl/typemap b/perl/typemap index 6de93e5..e088fe2 100644 --- a/perl/typemap +++ b/perl/typemap @@ -14,6 +14,7 @@ zbar_color_t T_ENUM zbar_error_t T_ENUM zbar_symbol_type_t T_ENUM zbar_config_t T_ENUM +zbar_orientation_t T_ENUM # special scalars fourcc_t T_FOURCC diff --git a/python/decoder.c b/python/decoder.c index 26cb8a8..f8ef7b8 100644 --- a/python/decoder.c +++ b/python/decoder.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2009 (c) Jeff Brown + * Copyright 2009-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -111,10 +111,18 @@ decoder_get_data (zbarDecoder *self, zbar_decoder_get_data_length(self->zdcode))); } +static PyObject* +decoder_get_direction (zbarDecoder *self, + void *closure) +{ + return(PyInt_FromLong(zbar_decoder_get_direction(self->zdcode))); +} + static PyGetSetDef decoder_getset[] = { - { "color", (getter)decoder_get_color, }, - { "type", (getter)decoder_get_type, }, - { "data", (getter)decoder_get_data, }, + { "color", (getter)decoder_get_color, }, + { "type", (getter)decoder_get_type, }, + { "data", (getter)decoder_get_data, }, + { "direction", (getter)decoder_get_direction }, { NULL, }, }; diff --git a/python/enum.c b/python/enum.c index 8a51532..f875287 100644 --- a/python/enum.c +++ b/python/enum.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2009 (c) Jeff Brown + * Copyright 2009-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -192,3 +192,16 @@ zbarEnum_Add (zbarEnum *self, return(-1); return(0); } + +zbarEnumItem* +zbarEnum_LookupValue (zbarEnum *self, + int val) +{ + PyObject *key = PyInt_FromLong(val); + zbarEnumItem *e = (zbarEnumItem*)PyDict_GetItem(self->byvalue, key); + if(!e) + return((zbarEnumItem*)key); + Py_INCREF((PyObject*)e); + Py_DECREF(key); + return(e); +} diff --git a/python/symbol.c b/python/symbol.c index 6c91274..80ba99c 100644 --- a/python/symbol.c +++ b/python/symbol.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2009 (c) Jeff Brown + * Copyright 2009-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -128,12 +128,21 @@ symbol_get_location (zbarSymbol *self, return(self->loc); } +static zbarEnumItem* +symbol_get_orientation (zbarSymbol *self, + void *closure) +{ + return(zbarEnum_LookupValue(orient_enum, + zbar_symbol_get_orientation(self->zsym))); +} + static PyGetSetDef symbol_getset[] = { { "type", (getter)symbol_get_type, }, { "quality", (getter)symbol_get_long, NULL, NULL, (void*)0 }, { "count", (getter)symbol_get_long, NULL, NULL, (void*)1 }, { "data", (getter)symbol_get_data, }, { "location", (getter)symbol_get_location, }, + { "orientation",(getter)symbol_get_orientation, }, { "components", (getter)symbol_get_components, }, { NULL, }, }; diff --git a/python/test/test_zbar.py b/python/test/test_zbar.py index 2772152..9a27f3c 100755 --- a/python/test/test_zbar.py +++ b/python/test/test_zbar.py @@ -84,6 +84,16 @@ def test_symbologies(self): self.assert_(int(sym) >= 0) self.assert_(is_identifier.match(str(sym))) + def test_orientations(self): + for orient in (zbar.Orient.UNKNOWN, + zbar.Orient.UP, + zbar.Orient.RIGHT, + zbar.Orient.DOWN, + zbar.Orient.LEFT): + self.assert_(isinstance(orient, zbar.EnumItem)) + self.assert_(-1 <= int(orient) <= 3) + self.assert_(is_identifier.match(str(orient))) + class TestScanner(ut.TestCase): def setUp(self): self.scn = zbar.Scanner() @@ -135,6 +145,9 @@ def set_data(data): self.dcode.data = data self.assertRaises(AttributeError, set_data, 'yomama') + self.assertRaises(AttributeError, + self.dcode.__setattr__, 'direction', -1) + def test_width(self): sym = self.dcode.decode_width(5) self.assert_(sym is zbar.Symbol.NONE) @@ -150,6 +163,7 @@ def test_reset(self): self.assert_(self.dcode.color is zbar.BAR) self.dcode.reset() self.assert_(self.dcode.color is zbar.SPACE) + self.assertEqual(self.dcode.direction, 0) def test_decode(self): inline_sym = [ -1 ] @@ -174,6 +188,7 @@ def handler(dcode, closure): self.assertEqual(self.dcode.data, '6268964977804') self.assert_(self.dcode.color is zbar.BAR) + self.assertEqual(self.dcode.direction, 1) self.assert_(sym is zbar.Symbol.EAN13) self.assert_(inline_sym[0] is zbar.Symbol.EAN13) self.assertEqual(explicit_closure, [ 2 ]) @@ -310,6 +325,7 @@ def test_scan(self): self.assertEqual(len(pt), 2) # FIXME test values (API currently in flux) + self.assert_(sym.orientation is zbar.Orient.UP) self.assert_(data is sym.data) self.assert_(loc is sym.location) @@ -370,13 +386,14 @@ def data_handler(proc, image, closure): symiter = iter(image) self.assert_(isinstance(symiter, zbar.SymbolIter)) - symbols = tuple(image) - self.assertEqual(len(symbols), 1) - for symbol in symbols: - self.assert_(isinstance(symbol, zbar.Symbol)) - self.assert_(symbol.type is zbar.Symbol.EAN13) - self.assertEqual(symbol.data, '9876543210128') - self.assert_(symbol.quality > 0) + syms = tuple(image) + self.assertEqual(len(syms), 1) + for sym in syms: + self.assert_(isinstance(sym, zbar.Symbol)) + self.assert_(sym.type is zbar.Symbol.EAN13) + self.assertEqual(sym.data, '9876543210128') + self.assert_(sym.quality > 0) + self.assert_(sym.orientation is zbar.Orient.UP) closure[0] += 1 explicit_closure = [ 0 ] diff --git a/python/zbarmodule.c b/python/zbarmodule.c index 27cce34..bffe2ed 100644 --- a/python/zbarmodule.c +++ b/python/zbarmodule.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2009 (c) Jeff Brown + * Copyright 2009-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -23,6 +23,11 @@ #include "zbarmodule.h" +typedef struct enumdef { + const char *strval; + int intval; +} enumdef; + static char *exc_names[] = { "zbar.Exception", NULL, @@ -38,6 +43,45 @@ static char *exc_names[] = { "zbar.WinAPIError", }; +static const enumdef symbol_defs[] = { + { "NONE", ZBAR_NONE }, + { "PARTIAL", ZBAR_PARTIAL }, + { "EAN8", ZBAR_EAN8 }, + { "UPCE", ZBAR_UPCE }, + { "ISBN10", ZBAR_ISBN10 }, + { "UPCA", ZBAR_UPCA }, + { "EAN13", ZBAR_EAN13 }, + { "ISBN13", ZBAR_ISBN13 }, + { "I25", ZBAR_I25 }, + { "CODE39", ZBAR_CODE39 }, + { "PDF417", ZBAR_PDF417 }, + { "QRCODE", ZBAR_QRCODE }, + { "CODE128", ZBAR_CODE128 }, + { NULL, } +}; + +static const enumdef config_defs[] = { + { "ENABLE", ZBAR_CFG_ENABLE }, + { "ADD_CHECK", ZBAR_CFG_ADD_CHECK }, + { "EMIT_CHECK", ZBAR_CFG_EMIT_CHECK }, + { "ASCII", ZBAR_CFG_ASCII }, + { "MIN_LEN", ZBAR_CFG_MIN_LEN }, + { "MAX_LEN", ZBAR_CFG_MAX_LEN }, + { "POSITION", ZBAR_CFG_POSITION }, + { "X_DENSITY", ZBAR_CFG_X_DENSITY }, + { "Y_DENSITY", ZBAR_CFG_Y_DENSITY }, + { NULL, } +}; + +static const enumdef orient_defs[] = { + { "UNKNOWN", ZBAR_ORIENT_UNKNOWN }, + { "UP", ZBAR_ORIENT_UP }, + { "RIGHT", ZBAR_ORIENT_RIGHT }, + { "DOWN", ZBAR_ORIENT_DOWN }, + { "LEFT", ZBAR_ORIENT_LEFT }, + { NULL, } +}; + int object_to_bool (PyObject *obj, int *val) @@ -54,6 +98,7 @@ zbarEnumItem *color_enum[2]; zbarEnum *config_enum; PyObject *symbol_enum; zbarEnumItem *symbol_NONE; +zbarEnum *orient_enum; static PyObject* version (PyObject *self, @@ -105,12 +150,6 @@ static PyMethodDef zbar_functions[] = { PyMODINIT_FUNC initzbar (void) { - /* initialize constant containers */ - config_enum = zbarEnum_New(); - symbol_enum = PyDict_New(); - if(!config_enum || !symbol_enum) - return; - /* initialize types */ zbarEnumItem_Type.tp_base = &PyInt_Type; zbarException_Type.tp_base = (PyTypeObject*)PyExc_Exception; @@ -128,6 +167,13 @@ initzbar (void) PyType_Ready(&zbarScanner_Type) < 0) return; + /* initialize constant containers */ + config_enum = zbarEnum_New(); + symbol_enum = PyDict_New(); + orient_enum = zbarEnum_New(); + if(!config_enum || !symbol_enum || !orient_enum) + return; + zbar_exc[0] = (PyObject*)&zbarException_Type; zbar_exc[ZBAR_ERR_NOMEM] = NULL; zbar_error_t ei; @@ -151,6 +197,7 @@ initzbar (void) PyModule_AddObject(mod, "EnumItem", (PyObject*)&zbarEnumItem_Type); PyModule_AddObject(mod, "Image", (PyObject*)&zbarImage_Type); PyModule_AddObject(mod, "Config", (PyObject*)config_enum); + PyModule_AddObject(mod, "Orient", (PyObject*)orient_enum); PyModule_AddObject(mod, "Symbol", (PyObject*)&zbarSymbol_Type); PyModule_AddObject(mod, "SymbolSet", (PyObject*)&zbarSymbolSet_Type); PyModule_AddObject(mod, "SymbolIter", (PyObject*)&zbarSymbolIter_Type); @@ -170,29 +217,14 @@ initzbar (void) color_enum[ZBAR_BAR] = zbarEnumItem_New(dict, NULL, ZBAR_BAR, "BAR"); - zbarEnum_Add(config_enum, ZBAR_CFG_ENABLE, "ENABLE"); - zbarEnum_Add(config_enum, ZBAR_CFG_ADD_CHECK, "ADD_CHECK"); - zbarEnum_Add(config_enum, ZBAR_CFG_EMIT_CHECK, "EMIT_CHECK"); - zbarEnum_Add(config_enum, ZBAR_CFG_ASCII, "ASCII"); - zbarEnum_Add(config_enum, ZBAR_CFG_MIN_LEN, "MIN_LEN"); - zbarEnum_Add(config_enum, ZBAR_CFG_MAX_LEN, "MAX_LEN"); - zbarEnum_Add(config_enum, ZBAR_CFG_X_DENSITY, "POSITION"); - zbarEnum_Add(config_enum, ZBAR_CFG_X_DENSITY, "X_DENSITY"); - zbarEnum_Add(config_enum, ZBAR_CFG_Y_DENSITY, "Y_DENSITY"); + const enumdef *item; + for(item = config_defs; item->strval; item++) + zbarEnum_Add(config_enum, item->intval, item->strval); + for(item = orient_defs; item->strval; item++) + zbarEnum_Add(orient_enum, item->intval, item->strval); PyObject *tp_dict = zbarSymbol_Type.tp_dict; - symbol_NONE = - zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_NONE, "NONE"); - zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_PARTIAL, "PARTIAL"); - zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_EAN8, "EAN8"); - zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_UPCE, "UPCE"); - zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_ISBN10, "ISBN10"); - zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_UPCA, "UPCA"); - zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_EAN13, "EAN13"); - zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_ISBN13, "ISBN13"); - zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_I25, "I25"); - zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_CODE39, "CODE39"); - zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_PDF417, "PDF417"); - zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_QRCODE, "QRCODE"); - zbarEnumItem_New(tp_dict, symbol_enum, ZBAR_CODE128, "CODE128"); + for(item = symbol_defs; item->strval; item++) + zbarEnumItem_New(tp_dict, symbol_enum, item->intval, item->strval); + symbol_NONE = zbarSymbol_LookupEnum(ZBAR_NONE); } diff --git a/python/zbarmodule.h b/python/zbarmodule.h index b6b660f..f2252ec 100644 --- a/python/zbarmodule.h +++ b/python/zbarmodule.h @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2009 (c) Jeff Brown + * Copyright 2009-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -61,6 +61,8 @@ extern zbarEnum *zbarEnum_New(void); extern int zbarEnum_Add(zbarEnum *self, int val, const char *name); +extern zbarEnumItem *zbarEnum_LookupValue(zbarEnum *self, + int val); typedef struct { PyObject_HEAD @@ -146,6 +148,7 @@ extern zbarEnumItem *color_enum[2]; extern zbarEnum *config_enum; extern PyObject *symbol_enum; extern zbarEnumItem *symbol_NONE; +extern zbarEnum *orient_enum; int object_to_bool(PyObject *obj, int *val); diff --git a/test/barcodetest.py b/test/barcodetest.py index 6219a5d..15400da 100755 --- a/test/barcodetest.py +++ b/test/barcodetest.py @@ -167,7 +167,8 @@ def __init__(self, methodName='runTest'): href = 'http://zbar.sf.net/test/barcode.png' self.source = src = ET.Element(ET.QName(BC, 'source'), href=href) - sym = ET.SubElement(src, ET.QName(BC, 'symbol'), type='EAN-13') + sym = ET.SubElement(src, ET.QName(BC, 'symbol'), type='EAN-13', + orientation='UP') data = ET.SubElement(sym, ET.QName(BC, 'data')) data.text = '9876543210128' @@ -258,8 +259,9 @@ def map_index(idx): def compare_symbols(expect, actual): - pass - + orient = expect.get('orientation') + if orient: + assert actual.get('orientation') == orient # override unittest.TestLoader to populate tests from xml description class TestLoader: diff --git a/zbar/decoder.c b/zbar/decoder.c index 07a6262..f1a0c9c 100644 --- a/zbar/decoder.c +++ b/zbar/decoder.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown + * Copyright 2007-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -149,6 +149,11 @@ unsigned int zbar_decoder_get_data_length (const zbar_decoder_t *dcode) return(dcode->buflen); } +int zbar_decoder_get_direction (const zbar_decoder_t *dcode) +{ + return(dcode->direction); +} + zbar_decoder_handler_t * zbar_decoder_set_handler (zbar_decoder_t *dcode, zbar_decoder_handler_t handler) diff --git a/zbar/decoder.h b/zbar/decoder.h index 10c9357..c5132f9 100644 --- a/zbar/decoder.h +++ b/zbar/decoder.h @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown + * Copyright 2007-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -80,6 +80,7 @@ struct zbar_decoder_s { unsigned w[DECODE_WINDOW]; /* window of last N bar widths */ zbar_symbol_type_t type; /* type of last decoded data */ zbar_symbol_type_t lock; /* buffer lock */ + int direction; /* direction of last decoded data */ /* everything above here is automatically reset */ unsigned buf_alloc; /* dynamic buffer allocation */ diff --git a/zbar/decoder/code128.c b/zbar/decoder/code128.c index 8674854..b505f3a 100644 --- a/zbar/decoder/code128.c +++ b/zbar/decoder/code128.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown + * Copyright 2007-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -321,6 +321,7 @@ static inline unsigned char postprocess (zbar_decoder_t *dcode) dprintf(2, "\n postproc len=%d", dcode128->character); unsigned i, j; unsigned char code = 0; + dcode->direction = 1 - 2 * dcode128->direction; if(dcode128->direction) { /* reverse buffer */ dprintf(2, " (rev)"); diff --git a/zbar/decoder/code39.c b/zbar/decoder/code39.c index da60db8..4a53019 100644 --- a/zbar/decoder/code39.c +++ b/zbar/decoder/code39.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2008-2009 (c) Jeff Brown + * Copyright 2008-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -194,12 +194,11 @@ static inline signed char code39_decode_start (zbar_decoder_t *dcode) code39_decoder_t *dcode39 = &dcode->code39; signed char c = code39_decode9(dcode); - if(c == 0x19) - dcode39->direction ^= 1; - else if(c != 0x2b) { + if(c != 0x19 && c != 0x2b) { dprintf(2, "\n"); return(ZBAR_NONE); } + dcode39->direction = (c == 0x19); /* check leading quiet zone - spec is 10x */ unsigned quiet = get_width(dcode, 9); @@ -217,6 +216,7 @@ static inline signed char code39_decode_start (zbar_decoder_t *dcode) static inline void code39_postprocess (zbar_decoder_t *dcode) { code39_decoder_t *dcode39 = &dcode->code39; + dcode->direction = 1 - 2 * dcode39->direction; int i; if(dcode39->direction) { /* reverse buffer */ diff --git a/zbar/decoder/ean.c b/zbar/decoder/ean.c index dee0523..93d46bd 100644 --- a/zbar/decoder/ean.c +++ b/zbar/decoder/ean.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown + * Copyright 2007-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -243,6 +243,7 @@ static inline zbar_symbol_type_t ean_part_end4 (ean_pass_t *pass, return(ZBAR_NONE); if(!par == fwd) { + pass->state |= STATE_REV; /* reverse sampled digits */ unsigned char tmp = pass->raw[1]; pass->raw[1] = pass->raw[4]; @@ -292,6 +293,7 @@ static inline zbar_symbol_type_t ean_part_end7 (ean_decoder_t *ean, return(ZBAR_NONE); if(!par == fwd) { + pass->state |= STATE_REV; /* reverse sampled digits */ unsigned char i; for(i = 1; i < 4; i++) { @@ -334,6 +336,8 @@ static inline zbar_symbol_type_t decode_pass (zbar_decoder_t *dcode, !aux_end(dcode, fwd)) { dprintf(2, " fwd=%x", fwd); zbar_symbol_type_t part = ean_part_end4(pass, fwd); + if(part) + dcode->ean.direction = (pass->state & STATE_REV) != 0; pass->state = -1; return(part); } @@ -369,6 +373,8 @@ static inline zbar_symbol_type_t decode_pass (zbar_decoder_t *dcode, dprintf(2, " fwd=%x", fwd); if(!aux_end(dcode, fwd)) part = ean_part_end7(&dcode->ean, pass, fwd); + if(part) + dcode->ean.direction = (pass->state & STATE_REV) != 0; pass->state = -1; return(part); } @@ -556,7 +562,8 @@ static inline zbar_symbol_type_t integrate_partial (ean_decoder_t *ean, if(part > ZBAR_PARTIAL) part |= ean->addon; - dprintf(2, " %x/%x=%x", ean->left, ean->right, part); + dprintf(2, " dir=%d %x/%x=%x", + ean->direction, ean->left, ean->right, part); return(part); } @@ -596,6 +603,7 @@ static inline void postprocess (zbar_decoder_t *dcode, dcode->buf[j] = ean->buf[i] + '0'; dcode->buflen = j; dcode->buf[j] = '\0'; + dcode->direction = 1 - 2 * ean->direction; } zbar_symbol_type_t _zbar_decode_ean (zbar_decoder_t *dcode) diff --git a/zbar/decoder/ean.h b/zbar/decoder/ean.h index 183b841..8ab895f 100644 --- a/zbar/decoder/ean.h +++ b/zbar/decoder/ean.h @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown + * Copyright 2007-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -26,6 +26,7 @@ /* state of each parallel decode attempt */ typedef struct ean_pass_s { signed char state; /* module position of w[idx] in symbol */ +#define STATE_REV 0x80 /* scan direction reversed */ #define STATE_ADDON 0x40 /* scanning add-on */ #define STATE_IDX 0x1f /* element offset into symbol */ unsigned char raw[7]; /* decode in process */ @@ -34,9 +35,10 @@ typedef struct ean_pass_s { /* EAN/UPC specific decode state */ typedef struct ean_decoder_s { ean_pass_t pass[4]; /* state of each parallel decode attempt */ - zbar_symbol_type_t left; /* current holding buffer contents */ + zbar_symbol_type_t left; /* current holding buffer contents */ zbar_symbol_type_t right; zbar_symbol_type_t addon; + int direction; /* scan direction */ unsigned s4; /* character width */ signed char buf[18]; /* holding buffer */ diff --git a/zbar/decoder/i25.c b/zbar/decoder/i25.c index 903eb9d..75a0a28 100644 --- a/zbar/decoder/i25.c +++ b/zbar/decoder/i25.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2008-2009 (c) Jeff Brown + * Copyright 2008-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -145,6 +145,7 @@ static inline signed char i25_decode_end (zbar_decoder_t *dcode) decode_e(get_width(dcode, 4), dcode25->width, 45) > 2)) return(ZBAR_NONE); + dcode->direction = 1 - 2 * dcode25->direction; if(dcode25->direction) { /* reverse buffer */ dprintf(2, " (rev)"); diff --git a/zbar/decoder/pdf417.c b/zbar/decoder/pdf417.c index ac948e9..167a2f3 100644 --- a/zbar/decoder/pdf417.c +++ b/zbar/decoder/pdf417.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2008-2009 (c) Jeff Brown + * Copyright 2008-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -213,6 +213,7 @@ zbar_symbol_type_t _zbar_decode_pdf417 (zbar_decoder_t *dcode) if(c == PDF417_STOP) { dprintf(1, " [valid stop]"); /* FIXME check trailing bar and qz */ + dcode->direction = 1 - 2 * dcode417->direction; dcode->lock = 0; dcode417->character = -1; } diff --git a/zbar/decoder/qr_finder.c b/zbar/decoder/qr_finder.c index 27bf185..8caeec7 100644 --- a/zbar/decoder/qr_finder.c +++ b/zbar/decoder/qr_finder.c @@ -1,3 +1,26 @@ +/*------------------------------------------------------------------------ + * Copyright 2009-2010 (c) Jeff Brown + * + * 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 #include @@ -67,6 +90,8 @@ zbar_symbol_type_t _zbar_find_qr (zbar_decoder_t *dcode) qrf->line.boffs, qrf->line.pos[0], qrf->line.len, qrf->line.eoffs); + dcode->direction = 0; + dcode->buflen = 0; return(ZBAR_QRCODE); invalid: diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 0db1a1c..4551548 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown + * Copyright 2007-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -246,6 +246,7 @@ _zbar_image_scanner_alloc_sym (zbar_image_scanner_t *iscn, sym->type = type; sym->quality = 1; sym->npts = 0; + sym->orient = ZBAR_ORIENT_UNKNOWN; sym->cache_count = 0; sym->time = iscn->time; assert(!sym->syms); @@ -444,6 +445,10 @@ static void symbol_handler (zbar_decoder_t *dcode) if(TEST_CFG(iscn, ZBAR_CFG_POSITION)) sym_add_point(sym, x, y); + int dir = zbar_decoder_get_direction(dcode); + if(dir) + sym->orient = (iscn->dy != 0) + ((iscn->du ^ dir) & 2); + _zbar_image_scanner_add_sym(iscn, sym); } diff --git a/zbar/processor.c b/zbar/processor.c index a160552..3bd57a3 100644 --- a/zbar/processor.c +++ b/zbar/processor.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown + * Copyright 2007-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -95,11 +95,12 @@ int _zbar_process_image (zbar_processor_t *proc, while(sym) { zbar_symbol_type_t type = zbar_symbol_get_type(sym); int count = zbar_symbol_get_count(sym); - zprintf(8, "%s%s: %s (%d pts) (q=%d) (%s)\n", + zprintf(8, "%s%s: %s (%d pts) (dir=%d) (q=%d) (%s)\n", zbar_get_symbol_name(type), zbar_get_addon_name(type), zbar_symbol_get_data(sym), zbar_symbol_get_loc_size(sym), + zbar_symbol_get_orientation(sym), zbar_symbol_get_quality(sym), (count < 0) ? "uncertain" : (count > 0) ? "duplicate" : "new"); diff --git a/zbar/qrcode/qrdectxt.c b/zbar/qrcode/qrdectxt.c index 8a82ea1..7646bc7 100644 --- a/zbar/qrcode/qrdectxt.c +++ b/zbar/qrcode/qrdectxt.c @@ -1,4 +1,4 @@ -/*Copyright (C) 2008-2009 Timothy B. Terriberry (tterribe@xiph.org) +/*Copyright (C) 2008-2010 Timothy B. Terriberry (tterribe@xiph.org) You can redistribute this library and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later @@ -167,6 +167,16 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, sym_add_point(*sym, qrdataj->bbox[3][0], qrdataj->bbox[3][1]); sym_add_point(*sym, qrdataj->bbox[1][0], qrdataj->bbox[1][1]); + /* approx symbol "up" direction */ + qr_point dir = { + qrdataj->bbox[0][0] - qrdataj->bbox[2][0] + + qrdataj->bbox[1][0] - qrdataj->bbox[3][0], + qrdataj->bbox[2][1] - qrdataj->bbox[0][1] + + qrdataj->bbox[3][1] - qrdataj->bbox[1][1], + }; + int horiz = abs(dir[0]) > abs(dir[1]); + (*sym)->orient = horiz + 2 * (dir[1 - horiz] < 0); + for(k=0;knentries&&!err;k++){ size_t inleft; size_t outleft; diff --git a/zbar/symbol.c b/zbar/symbol.c index 37e86a2..590b340 100644 --- a/zbar/symbol.c +++ b/zbar/symbol.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown + * Copyright 2007-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -56,6 +56,16 @@ const char *zbar_get_addon_name (zbar_symbol_type_t sym) } } +const char *zbar_get_orientation_name (zbar_orientation_t orient) +{ + switch(orient) { + case ZBAR_ORIENT_UP: return("UP"); + case ZBAR_ORIENT_RIGHT: return("RIGHT"); + case ZBAR_ORIENT_DOWN: return("DOWN"); + case ZBAR_ORIENT_LEFT: return("LEFT"); + default: return("UNKNOWN"); + } +} void _zbar_symbol_free (zbar_symbol_t *sym) { @@ -125,6 +135,11 @@ int zbar_symbol_get_loc_y (const zbar_symbol_t *sym, return(-1); } +zbar_orientation_t zbar_symbol_get_orientation (const zbar_symbol_t *sym) +{ + return(sym->orient); +} + const zbar_symbol_t *zbar_symbol_next (const zbar_symbol_t *sym) { return((sym) ? sym->next : NULL); @@ -143,7 +158,7 @@ const zbar_symbol_t *zbar_symbol_first_component (const zbar_symbol_t *sym) static const char *xmlfmt[] = { - "", @@ -170,7 +185,8 @@ char *zbar_symbol_xml (const zbar_symbol_t *sym, *len = maxlen; } - int n = snprintf(*buf, maxlen, xmlfmt[0], type, sym->quality); + int n = snprintf(*buf, maxlen, xmlfmt[0], type, sym->quality, + zbar_get_orientation_name(sym->orient)); assert(n > 0); assert(n <= maxlen); diff --git a/zbar/symbol.h b/zbar/symbol.h index 7b256ed..626076c 100644 --- a/zbar/symbol.h +++ b/zbar/symbol.h @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown + * Copyright 2007-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -47,6 +47,7 @@ struct zbar_symbol_s { unsigned pts_alloc; /* allocation size of pts */ unsigned npts; /* number of points in location polygon */ point_t *pts; /* list of points in location polygon */ + zbar_orientation_t orient; /* coarse orientation */ refcnt_t refcnt; /* reference count */ zbar_symbol_t *next; /* linked list of results (or siblings) */ From ea1e5b6a630002bf3638123dd0747716773ba1fd Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 6 Jan 2010 13:37:17 -0500 Subject: [PATCH 181/328] documentation fixes for rev 9d22936617de --- gtk/zbargtk.c | 2 +- include/zbar.h | 2 ++ include/zbar/Image.h | 2 +- include/zbar/Processor.h | 2 +- include/zbar/QZBarImage.h | 2 +- include/zbar/Video.h | 2 +- iphone/ZBarImage.m | 2 +- python/image.c | 2 +- test/test_images.h | 2 +- zbar/image.c | 2 +- zbar/image.h | 2 +- zbarimg/zbarimg.c | 2 +- 12 files changed, 13 insertions(+), 11 deletions(-) diff --git a/gtk/zbargtk.c b/gtk/zbargtk.c index 46ed13f..a67c6ff 100644 --- a/gtk/zbargtk.c +++ b/gtk/zbargtk.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2008-2009 (c) Jeff Brown + * Copyright 2008-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * diff --git a/include/zbar.h b/include/zbar.h index 5f4167a..5f5b8e8 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -205,6 +205,7 @@ extern int zbar_parse_config(const char *config_string, /** consistently compute fourcc values across architectures * (adapted from v4l2 specification) + * @since 0.11 */ #define zbar_fourcc(a, b, c, d) \ ((unsigned long)(a) | \ @@ -213,6 +214,7 @@ extern int zbar_parse_config(const char *config_string, ((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) { diff --git a/include/zbar/Image.h b/include/zbar/Image.h index 1b4120d..9d518ce 100644 --- a/include/zbar/Image.h +++ b/include/zbar/Image.h @@ -1,5 +1,5 @@ //------------------------------------------------------------------------ -// Copyright 2007-2009 (c) Jeff Brown +// Copyright 2007-2010 (c) Jeff Brown // // This file is part of the ZBar Bar Code Reader. // diff --git a/include/zbar/Processor.h b/include/zbar/Processor.h index 4652b11..2622ee8 100644 --- a/include/zbar/Processor.h +++ b/include/zbar/Processor.h @@ -1,5 +1,5 @@ //------------------------------------------------------------------------ -// Copyright 2007-2009 (c) Jeff Brown +// Copyright 2007-2010 (c) Jeff Brown // // This file is part of the ZBar Bar Code Reader. // diff --git a/include/zbar/QZBarImage.h b/include/zbar/QZBarImage.h index 610b2da..1505177 100644 --- a/include/zbar/QZBarImage.h +++ b/include/zbar/QZBarImage.h @@ -1,5 +1,5 @@ //------------------------------------------------------------------------ -// Copyright 2008-2009 (c) Jeff Brown +// Copyright 2008-2010 (c) Jeff Brown // // This file is part of the ZBar Bar Code Reader. // diff --git a/include/zbar/Video.h b/include/zbar/Video.h index 83733ef..61a49f1 100644 --- a/include/zbar/Video.h +++ b/include/zbar/Video.h @@ -1,5 +1,5 @@ //------------------------------------------------------------------------ -// Copyright 2007-2009 (c) Jeff Brown +// Copyright 2007-2010 (c) Jeff Brown // // This file is part of the ZBar Bar Code Reader. // diff --git a/iphone/ZBarImage.m b/iphone/ZBarImage.m index e591524..2913768 100644 --- a/iphone/ZBarImage.m +++ b/iphone/ZBarImage.m @@ -1,5 +1,5 @@ //------------------------------------------------------------------------ -// Copyright 2009 (c) Jeff Brown +// Copyright 2009-2010 (c) Jeff Brown // // This file is part of the ZBar Bar Code Reader. // diff --git a/python/image.c b/python/image.c index baa49a9..2d44055 100644 --- a/python/image.c +++ b/python/image.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2009 (c) Jeff Brown + * Copyright 2009-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * diff --git a/test/test_images.h b/test/test_images.h index c507516..84e163b 100644 --- a/test/test_images.h +++ b/test/test_images.h @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown + * Copyright 2007-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * diff --git a/zbar/image.c b/zbar/image.c index e928d4f..81ba349 100644 --- a/zbar/image.c +++ b/zbar/image.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown + * Copyright 2007-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * diff --git a/zbar/image.h b/zbar/image.h index fe9af25..3e2adf5 100644 --- a/zbar/image.h +++ b/zbar/image.h @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown + * Copyright 2007-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * diff --git a/zbarimg/zbarimg.c b/zbarimg/zbarimg.c index 17228f2..1c01efd 100644 --- a/zbarimg/zbarimg.c +++ b/zbarimg/zbarimg.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown + * Copyright 2007-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * From ce79383c669d09577f90724b53a4f67b1bf15212 Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 23 Jan 2010 15:11:38 -0500 Subject: [PATCH 182/328] fix output of binary data in zbarimg and zbarcam - thanks to fukuchi for a patch! - add base64 format for binary xml output --- ChangeLog | 3 ++ zbar/symbol.c | 110 +++++++++++++++++++++++++++++++++++----------- zbarcam/zbarcam.c | 18 +++++--- zbarimg/zbarimg.c | 18 +++++--- 4 files changed, 110 insertions(+), 39 deletions(-) diff --git a/ChangeLog b/ChangeLog index a0c644c..196e2ec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,7 @@ current: + * 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 diff --git a/zbar/symbol.c b/zbar/symbol.c index 590b340..38c48ae 100644 --- a/zbar/symbol.c +++ b/zbar/symbol.c @@ -157,26 +157,88 @@ const zbar_symbol_t *zbar_symbol_first_component (const zbar_symbol_t *sym) } +unsigned base64_encode (char *dst, + const char *src, + unsigned srclen) +{ + static const char alphabet[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + char *start = dst; + int nline = 19; + for(; srclen; srclen -= 3) { + unsigned int buf = *(src++) << 16; + if(srclen > 1) buf |= *(src++) << 8; + if(srclen > 2) buf |= *(src++); + *(dst++) = alphabet[(buf >> 18) & 0x3f]; + *(dst++) = alphabet[(buf >> 12) & 0x3f]; + *(dst++) = (srclen > 1) ? alphabet[(buf >> 6) & 0x3f] : '='; + *(dst++) = (srclen > 2) ? alphabet[buf & 0x3f] : '='; + if(srclen < 3) break; + if(!--nline) { *(dst++) = '\n'; nline = 19; } + } + *(dst++) = '\n'; + *(dst++) = '\0'; + return(dst - start - 1); +} + static const char *xmlfmt[] = { "", }; /* FIXME suspect... */ #define MAX_INT_DIGITS 10 +#define TMPL_COPY(t) do { \ + i = strlen(xmlfmt[(t)]); \ + memcpy(*buf + n, xmlfmt[(t)], i + 1); \ + n += i; \ + assert(n <= maxlen); \ + } while(0) + +#define TMPL_FMT(t, ...) do { \ + i = snprintf(*buf + n, maxlen - n, xmlfmt[(t)], __VA_ARGS__); \ + assert(i > 0); \ + n += i; \ + assert(n <= maxlen); \ + } while(0) + char *zbar_symbol_xml (const zbar_symbol_t *sym, char **buf, unsigned *len) { const char *type = zbar_get_symbol_name(sym->type); - /* FIXME binary data */ + const char *orient = zbar_get_orientation_name(sym->orient); + + /* check for binary data */ + char binary = ((sym->data[0] == 0xff && sym->data[1] == 0xfe) || + (sym->data[0] == 0xfe && sym->data[1] == 0xff) || + !strncmp(sym->data, "datalen; i++) { + char c = sym->data[i]; + binary = ((c < 0x20 && ((~0x00002600 >> c) & 1)) || + (c == ']' && i + 2 < sym->datalen && + sym->data[i + 1] == ']' && + sym->data[i + 2] == '>')); + } + unsigned datalen = strlen(sym->data); + if(binary) + datalen = (sym->datalen + 2) / 3 * 4 + sym->datalen / 57 + 3; + unsigned maxlen = (strlen(xmlfmt[0]) + strlen(xmlfmt[1]) + - strlen(xmlfmt[2]) + strlen(xmlfmt[3]) + - strlen(type) + datalen + MAX_INT_DIGITS + 1); + strlen(xmlfmt[2]) + strlen(xmlfmt[4]) + + strlen(xmlfmt[6]) + strlen(type) + strlen(orient) + + datalen + MAX_INT_DIGITS + 1); + if(binary) + maxlen += (strlen(xmlfmt[3]) + strlen(xmlfmt[5]) + MAX_INT_DIGITS); + if(!*buf || (*len < maxlen)) { if(*buf) free(*buf); @@ -185,34 +247,30 @@ char *zbar_symbol_xml (const zbar_symbol_t *sym, *len = maxlen; } - int n = snprintf(*buf, maxlen, xmlfmt[0], type, sym->quality, - zbar_get_orientation_name(sym->orient)); - assert(n > 0); - assert(n <= maxlen); + int n = 0; - if(sym->cache_count) { - int i = snprintf(*buf + n, maxlen - n, xmlfmt[1], sym->cache_count); - assert(i > 0); - n += i; - assert(n <= maxlen); - } + TMPL_FMT(0, type, sym->quality, orient); - int i = strlen(xmlfmt[2]); - memcpy(*buf + n, xmlfmt[2], i + 1); - n += i; - assert(n <= maxlen); + if(sym->cache_count) + TMPL_FMT(1, sym->cache_count); - /* FIXME binary data */ - /* FIXME handle "]]>" */ - strncpy(*buf + n, sym->data, datalen + 1); - n += datalen; - assert(n <= maxlen); + TMPL_COPY(2); + if(binary) + TMPL_FMT(3, sym->datalen); + TMPL_COPY(4); - i = strlen(xmlfmt[3]); - memcpy(*buf + n, xmlfmt[3], i + 1); - n += i; + if(!binary) { + memcpy(*buf + n, sym->data, sym->datalen + 1); + n += sym->datalen; + } + else { + TMPL_COPY(5); + n += base64_encode(*buf + n, sym->data, sym->datalen); + } assert(n <= maxlen); + TMPL_COPY(6); + *len = n; return(*buf); } diff --git a/zbarcam/zbarcam.c b/zbarcam/zbarcam.c index 56536b3..f1f3233 100644 --- a/zbarcam/zbarcam.c +++ b/zbarcam/zbarcam.c @@ -105,17 +105,23 @@ static void data_handler (zbar_image_t *img, const void *userdata) if(type == ZBAR_PARTIAL) continue; - if(!format) - printf("%s%s:%s\n", - zbar_get_symbol_name(type), zbar_get_addon_name(type), - zbar_symbol_get_data(sym)); + if(!format) { + printf("%s:", zbar_get_symbol_name(type)); + fwrite(zbar_symbol_get_data(sym), + zbar_symbol_get_data_length(sym), + 1, stdout); + } else if(format == RAW) - printf("%s\n", zbar_symbol_get_data(sym)); + fwrite(zbar_symbol_get_data(sym), + zbar_symbol_get_data_length(sym), + 1, stdout); else if(format == XML) { if(!n) printf("\n", zbar_image_get_sequence(img)); - printf("%s\n", zbar_symbol_xml(sym, &xml_buf, &xml_len)); + zbar_symbol_xml(sym, &xml_buf, &xml_len); + fwrite(xml_buf, xml_len, 1, stdout); } + printf("\n"); n++; } diff --git a/zbarimg/zbarimg.c b/zbarimg/zbarimg.c index 1c01efd..9376a49 100644 --- a/zbarimg/zbarimg.c +++ b/zbarimg/zbarimg.c @@ -167,21 +167,25 @@ static int scan_image (const char *filename) zbar_symbol_type_t typ = zbar_symbol_get_type(sym); if(typ == ZBAR_PARTIAL) continue; - else if(!xmllvl) - printf("%s%s:%s\n", - zbar_get_symbol_name(typ), - zbar_get_addon_name(typ), - zbar_symbol_get_data(sym)); + else if(!xmllvl) { + printf("%s:", zbar_get_symbol_name(typ)); + fwrite(zbar_symbol_get_data(sym), + zbar_symbol_get_data_length(sym), + 1, stdout); + } else if(xmllvl < 0) - printf("%s\n", zbar_symbol_get_data(sym)); + fwrite(zbar_symbol_get_data(sym), + zbar_symbol_get_data_length(sym), + 1, stdout); else { if(xmllvl < 3) { xmllvl++; printf("\n", seq); } zbar_symbol_xml(sym, &xmlbuf, &xmlbuflen); - printf("%s\n", xmlbuf); + fwrite(xmlbuf, xmlbuflen, 1, stdout); } + printf("\n"); found++; num_symbols++; } From f6c68420ebb6f1729b6ab0363b08221c1c9bc0e2 Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 26 Feb 2010 09:42:58 -0500 Subject: [PATCH 183/328] fix iphone custom overlay response (bug #2959617) - thanks to an anonymous user for the patch! --- ChangeLog | 2 ++ iphone/ZBarReaderController.m | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 35b63d7..86a0c21 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * fix iphone custom overlay response (bug #2959617) + - thanks to an anonymous user for the patch! * report QR immediately for video (no inter-frame consistency check) * realtime scanning for iphone widget - uses UIGetScreenImage() (NB private) diff --git a/iphone/ZBarReaderController.m b/iphone/ZBarReaderController.m index 5da8a78..9ba3802 100644 --- a/iphone/ZBarReaderController.m +++ b/iphone/ZBarReaderController.m @@ -243,7 +243,7 @@ - (void) viewWillAppear: (BOOL) animated if(boxView.superview != activeOverlay) [boxView removeFromSuperview]; if(!boxView.superview) - [activeOverlay addSubview: boxView]; + [activeOverlay insertSubview: boxView atIndex:0]; [scanner setSymbology: 0 config: ZBAR_CFG_X_DENSITY From 392609f4fb27008d961959b1fcc134d772d04b97 Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 28 Feb 2010 21:19:05 -0500 Subject: [PATCH 184/328] add Java interface to library via JNI - add Java tools and JNI build tests to configure - fix compiler warnings from binary output changes --- ChangeLog | 3 + Makefile.am | 8 +- configure.ac | 63 +- doc/Makefile.am.inc | 1 + java/Makefile.am | 40 ++ java/net/sourceforge/zbar/Config.java | 53 ++ java/net/sourceforge/zbar/Image.java | 148 +++++ java/net/sourceforge/zbar/ImageScanner.java | 98 +++ java/net/sourceforge/zbar/Orientation.java | 42 ++ java/net/sourceforge/zbar/Symbol.java | 182 ++++++ java/net/sourceforge/zbar/SymbolIterator.java | 70 +++ java/net/sourceforge/zbar/SymbolSet.java | 82 +++ java/test/TestImage.java | 140 +++++ java/test/TestImageScanner.java | 53 ++ java/test/TestScanImage.java | 183 ++++++ java/zbarjni.c | 583 ++++++++++++++++++ zbarcam/zbarcam.c | 20 +- zbarimg/zbarimg.c | 26 +- 18 files changed, 1774 insertions(+), 21 deletions(-) create mode 100644 java/Makefile.am create mode 100644 java/net/sourceforge/zbar/Config.java create mode 100644 java/net/sourceforge/zbar/Image.java create mode 100644 java/net/sourceforge/zbar/ImageScanner.java create mode 100644 java/net/sourceforge/zbar/Orientation.java create mode 100644 java/net/sourceforge/zbar/Symbol.java create mode 100644 java/net/sourceforge/zbar/SymbolIterator.java create mode 100644 java/net/sourceforge/zbar/SymbolSet.java create mode 100644 java/test/TestImage.java create mode 100644 java/test/TestImageScanner.java create mode 100644 java/test/TestScanImage.java create mode 100644 java/zbarjni.c diff --git a/ChangeLog b/ChangeLog index 196e2ec..246a908 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,7 @@ current: + * 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 diff --git a/Makefile.am b/Makefile.am index 6906d22..d7fbd0e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,3 @@ -AM_CPPFLAGS = -I$(srcdir)/include -AM_CFLAGS = -Wall -Wno-parentheses -Werror -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 diff --git a/configure.ac b/configure.ac index 56d3dd0..938b29e 100644 --- a/configure.ac +++ b/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,6 +80,29 @@ 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], @@ -255,7 +285,7 @@ AM_CONDITIONAL([HAVE_JPEG], [test "x$with_jpeg" = "xyes"]) dnl ImageMagick 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"]) @@ -296,7 +326,7 @@ AM_CONDITIONAL([HAVE_MAGICK], [test "x$with_imagemagick" = "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"]) @@ -383,6 +413,31 @@ 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 @@ -428,6 +483,7 @@ AC_CONFIG_COMMANDS([doc/reldate.xml], AC_CONFIG_FILES([ Makefile +java/Makefile zbar.pc zbar-gtk.pc zbar-qt.pc @@ -460,6 +516,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"]) diff --git a/doc/Makefile.am.inc b/doc/Makefile.am.inc index 55ae5b6..2923adc 100644 --- a/doc/Makefile.am.inc +++ b/doc/Makefile.am.inc @@ -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 = diff --git a/java/Makefile.am b/java/Makefile.am new file mode 100644 index 0000000..eadb638 --- /dev/null +++ b/java/Makefile.am @@ -0,0 +1,40 @@ +javadir = $(pkgdatadir)/lib + +PKG = net/sourceforge/zbar +java_DATA = zbar.jar + +java_LTLIBRARIES = libzbarjni.la +libzbarjni_la_CPPFLAGS = $(JAVA_CFLAGS) $(AM_CPPFLAGS) +libzbarjni_la_LIBADD = $(abs_top_builddir)/zbar/libzbar.la + +libzbarjni_la_SOURCES = zbarjni.c zbarjni.h +BUILT_SOURCES = zbarjni.h +MAINTAINERCLEANFILES = zbarjni.h + +zbar_jar_SRCS = \ + $(PKG)/Config.java $(PKG)/Orientation.java \ + $(PKG)/Symbol.java $(PKG)/SymbolIterator.java $(PKG)/SymbolSet.java \ + $(PKG)/Image.java $(PKG)/ImageScanner.java + +zbar_jar_CLASSES = $(zbar_jar_SRCS:.java=.class) \ + $(PKG)/Symbol\$$Rect.class + +test_SRCS = test/TestImage.java test/TestImageScanner.java \ + test/TestScanImage.java +test_CLASSES = TestImage TestImageScanner TestScanImage + +CLEANFILES = zbar.jar $(zbar_jar_CLASSES) $(test_CLASSES:=.class) + +zbarjni.h: $(zbar_jar_SRCS) + $(MAKE) $(AM_MAKEFLAGS) zbar.jar + classes=`echo $(zbar_jar_CLASSES:.class=) | tr / .` ; \ + $(JAVAH) -o $@ $$classes + +zbar.jar: $(zbar_jar_SRCS) + cd $(abs_srcdir); $(JAVAC) -d $(abs_builddir) $(zbar_jar_SRCS) + $(JAR) cf $@ $(zbar_jar_CLASSES) || $(RM) $@ + +check-local: + echo "making check in java" + cd $(abs_srcdir); $(JAVAC) -classpath $(CLASSPATH):$(abs_builddir)/zbar.jar -d $(abs_builddir) $(test_SRCS) + $(top_builddir)/libtool -dlopen libzbarjni.la --mode=execute $(JAVA) -classpath zbar.jar:$(CLASSPATH):. -Xcheck:jni org.junit.runner.JUnitCore $(test_CLASSES) diff --git a/java/net/sourceforge/zbar/Config.java b/java/net/sourceforge/zbar/Config.java new file mode 100644 index 0000000..164c7e1 --- /dev/null +++ b/java/net/sourceforge/zbar/Config.java @@ -0,0 +1,53 @@ +/*------------------------------------------------------------------------ + * Config + * + * Copyright 2010 (c) Jeff Brown + * + * This file is part of the ZBar Bar Code Reader. + * + * The ZBar Bar Code Reader is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * The ZBar Bar Code Reader is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with the ZBar Bar Code Reader; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zbar + *------------------------------------------------------------------------*/ + +package net.sourceforge.zbar; + +/** Decoder configuration options. + */ +public class Config +{ + /** Enable symbology/feature. */ + public static final int ENABLE = 0; + /** Enable check digit when optional. */ + public static final int ADD_CHECK = 1; + /** Return check digit when present. */ + public static final int EMIT_CHECK = 2; + /** Enable full ASCII character set. */ + public static final int ASCII = 3; + + /** Minimum data length for valid decode. */ + public static final int MIN_LEN = 0x20; + /** Maximum data length for valid decode. */ + public static final int MAX_LEN = 0x21; + + /** Enable scanner to collect position data. */ + public static final int POSITION = 0x80; + + /** Image scanner vertical scan density. */ + public static final int X_DENSITY = 0x100; + /** Image scanner horizontal scan density. */ + public static final int Y_DENSITY = 0x101; +} diff --git a/java/net/sourceforge/zbar/Image.java b/java/net/sourceforge/zbar/Image.java new file mode 100644 index 0000000..9b93c40 --- /dev/null +++ b/java/net/sourceforge/zbar/Image.java @@ -0,0 +1,148 @@ +/*------------------------------------------------------------------------ + * Image + * + * Copyright 2007-2010 (c) Jeff Brown + * + * This file is part of the ZBar Bar Code Reader. + * + * The ZBar Bar Code Reader is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * The ZBar Bar Code Reader is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with the ZBar Bar Code Reader; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zbar + *------------------------------------------------------------------------*/ + +package net.sourceforge.zbar; + +/** stores image data samples along with associated format and size + * metadata. + */ +public class Image +{ + /** C pointer to a zbar_symbol_t. */ + private long peer; + private Object data; + + static + { + System.loadLibrary("zbarjni"); + init(); + } + private static native void init(); + + public Image () + { + peer = create(); + } + + public Image (int width, int height) + { + this(); + setSize(width, height); + } + + public Image (int width, int height, String format) + { + this(); + setSize(width, height); + setFormat(format); + } + + public Image (String format) + { + this(); + setFormat(format); + } + + Image (long peer) + { + this.peer = peer; + } + + /** Create an associated peer instance. */ + private native long create(); + + protected void finalize () + { + destroy(); + } + + /** Clean up native data associated with an instance. */ + public synchronized void destroy () + { + if(peer != 0) { + destroy(peer); + peer = 0; + } + } + + /** Destroy the associated peer instance. */ + private native void destroy(long peer); + + /** Image format conversion. + * @returns a @em new image with the sample data from the original + * image converted to the requested format fourcc. the original + * image is unaffected. + */ + public Image convert (String format) + { + long newpeer = convert(peer, format); + if(newpeer == 0) + return(null); + return(new Image(newpeer)); + } + + private native long convert(long peer, String format); + + /** Retrieve the image format fourcc. */ + public native String getFormat(); + + /** Specify the fourcc image format code for image sample data. */ + public native void setFormat(String format); + + /** Retrieve a "sequence" (page/frame) number associated with this + * image. + */ + public native int getSequence(); + + /** Associate a "sequence" (page/frame) number with this image. */ + public native void setSequence(int seq); + + /** Retrieve the width of the image. */ + public native int getWidth(); + + /** Retrieve the height of the image. */ + public native int getHeight(); + + /** Specify the pixel size of the image. */ + public native void setSize(int width, int height); + + /** Retrieve the image sample data. */ + public native byte[] getData(); + + /** Specify image sample data. */ + public native void setData(byte[] data); + + /** Specify image sample data. */ + public native void setData(int[] data); + + /** Retrieve the decoded results associated with this image. */ + public SymbolSet getSymbols () + { + return(new SymbolSet(getSymbols(peer))); + } + + private native long getSymbols(long peer); + +} diff --git a/java/net/sourceforge/zbar/ImageScanner.java b/java/net/sourceforge/zbar/ImageScanner.java new file mode 100644 index 0000000..02a2a1d --- /dev/null +++ b/java/net/sourceforge/zbar/ImageScanner.java @@ -0,0 +1,98 @@ +/*------------------------------------------------------------------------ + * ImageScanner + * + * Copyright 2007-2010 (c) Jeff Brown + * + * This file is part of the ZBar Bar Code Reader. + * + * The ZBar Bar Code Reader is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * The ZBar Bar Code Reader is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with the ZBar Bar Code Reader; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zbar + *------------------------------------------------------------------------*/ + +package net.sourceforge.zbar; + +/** Read barcodes from 2-D images. + */ +public class ImageScanner +{ + /** C pointer to a zbar_image_scanner_t. */ + private long peer; + + static + { + System.loadLibrary("zbarjni"); + init(); + } + private static native void init(); + + public ImageScanner () + { + peer = create(); + } + + /** Create an associated peer instance. */ + private native long create(); + + protected void finalize () + { + destroy(); + } + + /** Clean up native data associated with an instance. */ + public synchronized void destroy () + { + if(peer != 0) { + destroy(peer); + peer = 0; + } + } + + /** Destroy the associated peer instance. */ + private native void destroy(long peer); + + /** Set config for indicated symbology (0 for all) to specified value. + */ + public native void setConfig(int symbology, int config, int value) + throws IllegalArgumentException; + + /** Parse configuration string and apply to image scanner. */ + public native void parseConfig(String config); + + /** Enable or disable the inter-image result cache (default disabled). + * Mostly useful for scanning video frames, the cache filters duplicate + * results from consecutive images, while adding some consistency + * checking and hysteresis to the results. Invoking this method also + * clears the cache. + */ + public native void enableCache(boolean enable); + + /** Retrieve decode results for last scanned image. + * @returns the SymbolSet result container + */ + public SymbolSet getResults () + { + return(new SymbolSet(getResults(peer))); + } + + private native long getResults(long peer); + + /** Scan for symbols in provided Image. + * The image format must currently be "Y800" or "GRAY". + * @returns the number of symbols successfully decoded from the image. + */ + public native int scanImage(Image image); +} diff --git a/java/net/sourceforge/zbar/Orientation.java b/java/net/sourceforge/zbar/Orientation.java new file mode 100644 index 0000000..6643695 --- /dev/null +++ b/java/net/sourceforge/zbar/Orientation.java @@ -0,0 +1,42 @@ +/*------------------------------------------------------------------------ + * Orientation + * + * Copyright 2010 (c) Jeff Brown + * + * This file is part of the ZBar Bar Code Reader. + * + * The ZBar Bar Code Reader is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * The ZBar Bar Code Reader is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with the ZBar Bar Code Reader; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zbar + *------------------------------------------------------------------------*/ + +package net.sourceforge.zbar; + +/** Decoded symbol coarse orientation. + */ +public class Orientation +{ + /** Unable to determine orientation. */ + public static final int UNKNOWN = -1; + /** Upright, read left to right. */ + public static final int UP = 0; + /** sideways, read top to bottom */ + public static final int RIGHT = 1; + /** upside-down, read right to left */ + public static final int DOWN = 2; + /** sideways, read bottom to top */ + public static final int LEFT = 3; +} diff --git a/java/net/sourceforge/zbar/Symbol.java b/java/net/sourceforge/zbar/Symbol.java new file mode 100644 index 0000000..d5d2b83 --- /dev/null +++ b/java/net/sourceforge/zbar/Symbol.java @@ -0,0 +1,182 @@ +/*------------------------------------------------------------------------ + * Symbol + * + * Copyright 2007-2010 (c) Jeff Brown + * + * This file is part of the ZBar Bar Code Reader. + * + * The ZBar Bar Code Reader is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * The ZBar Bar Code Reader is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with the ZBar Bar Code Reader; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zbar + *------------------------------------------------------------------------*/ + +package net.sourceforge.zbar; + +/** Immutable container for decoded result symbols associated with an image + * or a composite symbol. + */ +public class Symbol +{ + public class Rect + { + public int x, y, width, height; + }; + + /** No symbol decoded. */ + public static final int NONE = 0; + /** Symbol detected but not decoded. */ + public static final int PARTIAL = 1; + + /** EAN-8. */ + public static final int EAN8 = 8; + /** UPC-E. */ + public static final int UPCE = 9; + /** ISBN-10 (from EAN-13). */ + public static final int ISBN10 = 10; + /** UPC-A. */ + public static final int UPCA = 12; + /** EAN-13. */ + public static final int EAN13 = 13; + /** ISBN-13 (from EAN-13). */ + public static final int ISBN13 = 14; + /** Interleaved 2 of 5. */ + public static final int I25 = 25; + /** Code 39. */ + public static final int CODE39 = 39; + /** PDF417. */ + public static final int PDF417 = 57; + /** QR Code. */ + public static final int QRCODE = 64; + /** Code 128. */ + public static final int CODE128 = 128; + + /** C pointer to a zbar_symbol_t. */ + private long peer; + + /** Cached attributes. */ + private int type; + + static + { + System.loadLibrary("zbarjni"); + init(); + } + private static native void init(); + + /** Symbols are only created by other package methods. */ + Symbol (long peer) + { + this.peer = peer; + } + + protected void finalize () + { + destroy(); + } + + /** Clean up native data associated with an instance. */ + public synchronized void destroy () + { + if(peer != 0) { + destroy(peer); + peer = 0; + } + } + + /** Release the associated peer instance. */ + private native void destroy(long peer); + + /** Retrieve type of decoded symbol. */ + public int getType () + { + if(type == 0) + type = getType(peer); + return(type); + } + + private native int getType(long peer); + + /** Retrieve data decoded from symbol as a String. */ + public native String getData(); + + /** Retrieve raw data bytes decoded from symbol. */ + public native byte[] getDataBytes(); + + /** Retrieve a symbol confidence metric. Quality is an unscaled, + * relative quantity: larger values are better than smaller + * values, where "large" and "small" are application dependent. + */ + public native int getQuality(); + + /** Retrieve current cache count. When the cache is enabled for + * the image_scanner this provides inter-frame reliability and + * redundancy information for video streams. + * @returns < 0 if symbol is still uncertain + * @returns 0 if symbol is newly verified + * @returns > 0 for duplicate symbols + */ + public native int getCount(); + + /** Retrieve an approximate, axis-aligned bounding box for the + * symbol. + */ + public Rect getBounds () + { + int n = getLocationSize(peer); + if(n <= 0) + return(null); + + Rect bounds = new Rect(); + int xmin = Integer.MAX_VALUE; + int xmax = Integer.MIN_VALUE; + int ymin = Integer.MAX_VALUE; + int ymax = Integer.MIN_VALUE; + + for(int i = 0; i < n; i++) { + int x = getLocationX(peer, i); + if(xmin > x) xmin = x; + if(xmax < x) xmax = x; + + int y = getLocationY(peer, i); + if(ymin > y) ymin = y; + if(ymax < y) ymax = y; + } + bounds.x = xmin; + bounds.y = ymin; + bounds.width = xmax - xmin; + bounds.height = ymax - ymin; + return(bounds); + } + + private native int getLocationSize(long peer); + private native int getLocationX(long peer, int idx); + private native int getLocationY(long peer, int idx); + + /** Retrieve general axis-aligned, orientation of decoded + * symbol. + */ + public native int getOrientation(); + + /** Retrieve components of a composite result. */ + public SymbolSet getComponents () + { + return(new SymbolSet(getComponents(peer))); + } + + private native long getComponents(long peer); + + native long next(); +} diff --git a/java/net/sourceforge/zbar/SymbolIterator.java b/java/net/sourceforge/zbar/SymbolIterator.java new file mode 100644 index 0000000..954a5aa --- /dev/null +++ b/java/net/sourceforge/zbar/SymbolIterator.java @@ -0,0 +1,70 @@ +/*------------------------------------------------------------------------ + * SymbolIterator + * + * Copyright 2007-2010 (c) Jeff Brown + * + * This file is part of the ZBar Bar Code Reader. + * + * The ZBar Bar Code Reader is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * The ZBar Bar Code Reader is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with the ZBar Bar Code Reader; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zbar + *------------------------------------------------------------------------*/ + +package net.sourceforge.zbar; + +/** Iterator over a SymbolSet. + */ +public class SymbolIterator + implements java.util.Iterator +{ + /** Next symbol to be returned by the iterator. */ + private Symbol current; + + /** SymbolIterators are only created by internal interface methods. */ + SymbolIterator (Symbol first) + { + current = first; + } + + /** Returns true if the iteration has more elements. */ + public boolean hasNext () + { + return(current != null); + } + + /** Retrieves the next element in the iteration. */ + public Symbol next () + { + if(current == null) + throw(new java.util.NoSuchElementException + ("access past end of SymbolIterator")); + + Symbol result = current; + long sym = current.next(); + if(sym != 0) + current = new Symbol(sym); + else + current = null; + return(result); + } + + /** Raises UnsupportedOperationException. */ + public void remove () + { + throw(new UnsupportedOperationException + ("SymbolIterator is immutable")); + } +} diff --git a/java/net/sourceforge/zbar/SymbolSet.java b/java/net/sourceforge/zbar/SymbolSet.java new file mode 100644 index 0000000..1c9110a --- /dev/null +++ b/java/net/sourceforge/zbar/SymbolSet.java @@ -0,0 +1,82 @@ +/*------------------------------------------------------------------------ + * SymbolSet + * + * Copyright 2007-2010 (c) Jeff Brown + * + * This file is part of the ZBar Bar Code Reader. + * + * The ZBar Bar Code Reader is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * The ZBar Bar Code Reader is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with the ZBar Bar Code Reader; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zbar + *------------------------------------------------------------------------*/ + +package net.sourceforge.zbar; + +/** Immutable container for decoded result symbols associated with an image + * or a composite symbol. + */ +public class SymbolSet + extends java.util.AbstractCollection +{ + /** C pointer to a zbar_symbol_set_t. */ + private long peer; + + static + { + System.loadLibrary("zbarjni"); + init(); + } + private static native void init(); + + /** SymbolSets are only created by other package methods. */ + SymbolSet (long peer) + { + this.peer = peer; + } + + protected void finalize () + { + destroy(); + } + + /** Clean up native data associated with an instance. */ + public synchronized void destroy () + { + if(peer != 0) { + destroy(peer); + peer = 0; + } + } + + /** Release the associated peer instance. */ + private native void destroy(long peer); + + /** Retrieve an iterator over the Symbol elements in this collection. */ + public java.util.Iterator iterator () + { + long sym = firstSymbol(peer); + if(sym == 0) + return(new SymbolIterator(null)); + + return(new SymbolIterator(new Symbol(sym))); + } + + /** Retrieve the number of elements in the collection. */ + public native int size(); + + /** Retrieve C pointer to first symbol in the set. */ + private native long firstSymbol(long peer); +} diff --git a/java/test/TestImage.java b/java/test/TestImage.java new file mode 100644 index 0000000..136d953 --- /dev/null +++ b/java/test/TestImage.java @@ -0,0 +1,140 @@ + +import org.junit.Test; +import org.junit.Before; +import org.junit.After; +import static org.junit.Assert.*; + +import net.sourceforge.zbar.Image; + +public class TestImage +{ + protected Image image; + + @Before public void setUp () + { + image = new Image(); + } + + @After public void tearDown () + { + image.destroy(); + image = null; + } + + + @Test public void creation () + { + Image img0 = new Image(123, 456); + Image img1 = new Image("BGR3"); + Image img2 = new Image(987, 654, "UYVY"); + + assertEquals(123, img0.getWidth()); + assertEquals(456, img0.getHeight()); + assertEquals(null, img0.getFormat()); + + assertEquals(0, img1.getWidth()); + assertEquals(0, img1.getHeight()); + assertEquals("BGR3", img1.getFormat()); + + assertEquals(987, img2.getWidth()); + assertEquals(654, img2.getHeight()); + assertEquals("UYVY", img2.getFormat()); + } + + @Test public void sequence () + { + assertEquals(0, image.getSequence()); + image.setSequence(42); + assertEquals(42, image.getSequence()); + } + + @Test public void size () + { + assertEquals(0, image.getWidth()); + assertEquals(0, image.getHeight()); + image.setSize(640, 480); + assertEquals(640, image.getWidth()); + assertEquals(480, image.getHeight()); + } + + @Test public void format () + { + assertNull(image.getFormat()); + image.setFormat("Y800"); + assertEquals("Y800", image.getFormat()); + boolean gotException = false; + try { + image.setFormat("[]"); + } + catch(IllegalArgumentException e) { + // expected + gotException = true; + } + assertTrue("Expected exception", gotException); + assertEquals("Y800", image.getFormat()); + } + + @Test(expected=IllegalArgumentException.class) + public void setFormatInvalid0 () + { + image.setFormat(null); + } + + @Test(expected=IllegalArgumentException.class) + public void setFormatInvalid1 () + { + image.setFormat(""); + } + + @Test(expected=IllegalArgumentException.class) + public void setFormatInvalid2 () + { + image.setFormat("YOMAMA"); + } + + @Test(expected=IllegalArgumentException.class) + public void setFormatInvalid3 () + { + image.setFormat("foo"); + } + + @Test public void data () + { + assertNull(image.getData()); + + int[] ints = new int[24]; + image.setData(ints); + assertSame(ints, image.getData()); + + byte[] bytes = new byte[280]; + image.setData(bytes); + assertSame(bytes, image.getData()); + + image.setData((byte[])null); + assertNull(image.getData()); + } + + @Test public void convert () + { + image.setSize(4, 4); + image.setFormat("RGB4"); + int[] rgb4 = new int[16]; + byte[] exp = new byte[16]; + for(int i = 0; i < 16; i++) { + int c = i * 15; + rgb4[i] = c | (c << 8) | (c << 16) | (c << 24); + exp[i] = (byte)c; + } + image.setData(rgb4); + + Image gray = image.convert("Y800"); + assertEquals(4, gray.getWidth()); + assertEquals(4, gray.getHeight()); + assertEquals("Y800", gray.getFormat()); + + byte[] y800 = gray.getData(); + assertEquals(16, y800.length); + + assertArrayEquals(exp, y800); + } +} diff --git a/java/test/TestImageScanner.java b/java/test/TestImageScanner.java new file mode 100644 index 0000000..0d8eccc --- /dev/null +++ b/java/test/TestImageScanner.java @@ -0,0 +1,53 @@ + +import org.junit.Test; +import org.junit.Before; +import org.junit.After; +import org.junit.Assert.*; + +import net.sourceforge.zbar.ImageScanner; +import net.sourceforge.zbar.Config; + +public class TestImageScanner +{ + protected ImageScanner scanner; + + @Before public void setUp () + { + scanner = new ImageScanner(); + } + + @After public void tearDown () + { + scanner.destroy(); + scanner = null; + } + + + @Test public void creation () + { + // create/destroy + } + + @Test public void callSetConfig () + { + scanner.setConfig(0, Config.X_DENSITY, 2); + scanner.setConfig(0, Config.Y_DENSITY, 4); + } + + @Test public void callParseConfig () + { + scanner.parseConfig("disable"); + } + + @Test(expected=IllegalArgumentException.class) + public void callParseConfigInvalid () + { + scanner.parseConfig("yomama"); + } + + @Test public void callEnableCache () + { + scanner.enableCache(true); + scanner.enableCache(false); + } +} diff --git a/java/test/TestScanImage.java b/java/test/TestScanImage.java new file mode 100644 index 0000000..d27c04c --- /dev/null +++ b/java/test/TestScanImage.java @@ -0,0 +1,183 @@ + +import org.junit.Test; +import org.junit.Before; +import org.junit.After; +import static org.junit.Assert.*; + +import net.sourceforge.zbar.*; + +import java.text.CharacterIterator; +import java.text.StringCharacterIterator; +import java.util.Iterator; + +public class TestScanImage +{ + protected ImageScanner scanner; + protected Image image; + + @Before public void setUp () + { + scanner = new ImageScanner(); + image = new Image(); + } + + @After public void tearDown () + { + image = null; + scanner = null; + System.gc(); + } + + public static final String encoded_widths = + "9 111 212241113121211311141132 11111 311213121312121332111132 111 9"; + + protected void generateY800 () + { + int width = 114, height = 85; + image.setSize(width, height); + image.setFormat("Y800"); + int datalen = width * height; + byte[] data = new byte[datalen]; + + int y = 0; + int p = 0; + for(; y < 10 && y < height; y++) + for(int x = 0; x < width; x++) + data[p++] = -1; + + for(; y < height - 10; y++) { + int x = 0; + byte color = -1; + CharacterIterator it = new StringCharacterIterator(encoded_widths); + for(char c = it.first(); + c != CharacterIterator.DONE; + c = it.next()) + { + if(c == ' ') + continue; + for(int dx = (int)c - 0x30; dx > 0; dx--) { + data[p++] = color; + x++; + } + color = (byte)~color; + } + for(; x < width; x++) + data[p++] = (byte)~color; + } + + for(; y < height; y++) + for(int x = 0; x < width; x++) + data[p++] = -1; + assert(p == datalen); + + image.setData(data); + } + + protected void checkResults (SymbolSet syms) + { + assertNotNull(syms); + assert(syms.size() == 1); + Iterator it = syms.iterator(); + assertTrue(it.hasNext()); + Symbol sym = it.next(); + assertNotNull(sym); + assertFalse(it.hasNext()); + + assertEquals(Symbol.EAN13, sym.getType()); + assertEquals(sym.EAN13, sym.getType()); // cached + + assertTrue(sym.getQuality() > 1); + assertEquals(0, sym.getCount()); + + SymbolSet comps = sym.getComponents(); + assertNotNull(comps); + assertEquals(0, comps.size()); + it = comps.iterator(); + assertNotNull(it); + assertFalse(it.hasNext()); + + String data = sym.getData(); + assertEquals("6268964977804", data); + + byte[] bytes = sym.getDataBytes(); + byte[] exp = { '6','2','6','8','9','6','4','9','7','7','8','0','4' }; + assertArrayEquals(exp, bytes); + + Symbol.Rect r = sym.getBounds(); + assertTrue(r.x > 6); + assertTrue(r.y > 6); + assertTrue(r.width < 102); + assertTrue(r.height < 73); + + assertEquals(Orientation.UP, sym.getOrientation()); + } + + @Test public void generated () + { + generateY800(); + int n = scanner.scanImage(image); + assertEquals(1, n); + + checkResults(image.getSymbols()); + checkResults(scanner.getResults()); + } + + @Test public void config () + { + generateY800(); + scanner.setConfig(Symbol.EAN13, Config.ENABLE, 0); + int n = scanner.scanImage(image); + assertEquals(0, n); + } + + @Test public void cache () + { + generateY800(); + scanner.enableCache(true); + + int n = 0; + for(int i = 0; i < 10; i++) { + n = scanner.scanImage(image); + if(n > 0) { + assertTrue(i > 1); + break; + } + } + + assertEquals(1, n); + checkResults(scanner.getResults()); + } + + @Test public void orientation() + { + generateY800(); + + // flip the image + int width = image.getWidth(); + int height = image.getHeight(); + byte[] data = image.getData(); + int p = 0; + for(int y = 0; y < height; y++) { + for(int x0 = 0; x0 < width / 2; x0++) { + int x1 = width - x0 - 1; + assert(x0 < x1); + byte b = data[p + x0]; + data[p + x0] = data[p + x1]; + data[p + x1] = b; + } + p += width; + } + image.setData(data); + + int n = scanner.scanImage(image); + assertEquals(1, n); + + SymbolSet syms = scanner.getResults(); + assert(syms.size() == 1); + for(Symbol sym : syms) { + assertEquals(Symbol.EAN13, sym.getType()); + assertEquals("6268964977804", sym.getData()); + assertEquals(Orientation.DOWN, sym.getOrientation()); + } + } +} diff --git a/java/zbarjni.c b/java/zbarjni.c new file mode 100644 index 0000000..3da4e4d --- /dev/null +++ b/java/zbarjni.c @@ -0,0 +1,583 @@ +#include +#include +#include +#include + +static jfieldID SymbolSet_peer; +static jfieldID Symbol_peer; +static jfieldID Image_peer, Image_data; +static jfieldID ImageScanner_peer; + +static struct { + int SymbolSet_create, SymbolSet_destroy; + int Symbol_create, Symbol_destroy; + int Image_create, Image_destroy; + int ImageScanner_create, ImageScanner_destroy; +} stats; + + +#define PEER_CAST(l) \ + ((void*)(uintptr_t)(l)) + +#define GET_PEER(c, o) \ + PEER_CAST((*env)->GetLongField(env, (o), c ## _peer)) + + +static inline void +throw_exc(JNIEnv *env, + const char *name, + const char *msg) +{ + jclass cls = (*env)->FindClass(env, name); + if(cls) + (*env)->ThrowNew(env, cls, msg); + (*env)->DeleteLocalRef(env, cls); +} + +static inline uint32_t +format_to_fourcc(JNIEnv *env, + jstring format) +{ + if(!format) + goto invalid; + + int n = (*env)->GetStringLength(env, format); + if(0 >= n || n > 4) + goto invalid; + + char fmtstr[8]; + (*env)->GetStringUTFRegion(env, format, 0, n, fmtstr); + + uint32_t fourcc = 0; + int i; + for(i = 0; i < n; i++) { + if(fmtstr[i] < ' ' || 'Z' < fmtstr[i] || + ('9' < fmtstr[i] && fmtstr[i] < 'A') || + (' ' < fmtstr[i] && fmtstr[i] < '0')) + goto invalid; + fourcc |= ((uint32_t)fmtstr[i]) << (8 * i); + } + return(fourcc); + +invalid: + throw_exc(env, "java/lang/IllegalArgumentException", + "invalid format fourcc"); + return(0); +} + +static JavaVM *jvm = NULL; + +JNIEXPORT jint JNICALL +JNI_OnLoad (JavaVM *_jvm, + void *reserved) +{ + jvm = _jvm; + return(JNI_VERSION_1_2); +} + +JNIEXPORT void JNICALL +JNI_OnUnload (JavaVM *_jvm, + void *reserved) +{ + assert(stats.SymbolSet_create == stats.SymbolSet_destroy); + assert(stats.Symbol_create == stats.Symbol_destroy); + assert(stats.Image_create == stats.Image_destroy); + assert(stats.ImageScanner_create == stats.ImageScanner_destroy); +} + + +JNIEXPORT void JNICALL +Java_net_sourceforge_zbar_SymbolSet_init (JNIEnv *env, + jclass cls) +{ + SymbolSet_peer = (*env)->GetFieldID(env, cls, "peer", "J"); +} + +JNIEXPORT void JNICALL +Java_net_sourceforge_zbar_SymbolSet_destroy (JNIEnv *env, + jobject obj, + jlong peer) +{ + zbar_symbol_set_ref(PEER_CAST(peer), -1); + stats.SymbolSet_destroy++; +} + +JNIEXPORT jint JNICALL +Java_net_sourceforge_zbar_SymbolSet_size (JNIEnv *env, + jobject obj) +{ + zbar_symbol_set_t *zsyms = GET_PEER(SymbolSet, obj); + if(!zsyms) + return(0); + return(zbar_symbol_set_get_size(zsyms)); +} + +JNIEXPORT jlong JNICALL +Java_net_sourceforge_zbar_SymbolSet_firstSymbol (JNIEnv *env, + jobject obj, + jlong peer) +{ + if(!peer) + return(0); + const zbar_symbol_t *zsym = zbar_symbol_set_first_symbol(PEER_CAST(peer)); + if(zsym) { + zbar_symbol_ref(zsym, 1); + stats.Symbol_create++; + } + return((intptr_t)zsym); +} + + + +JNIEXPORT void JNICALL +Java_net_sourceforge_zbar_Symbol_init (JNIEnv *env, + jclass cls) +{ + Symbol_peer = (*env)->GetFieldID(env, cls, "peer", "J"); +} + +JNIEXPORT void JNICALL +Java_net_sourceforge_zbar_Symbol_destroy (JNIEnv *env, + jobject obj, + jlong peer) +{ + zbar_symbol_ref(PEER_CAST(peer), -1); + stats.Symbol_destroy++; +} + +JNIEXPORT jint JNICALL +Java_net_sourceforge_zbar_Symbol_getType (JNIEnv *env, + jobject obj, + jlong peer) +{ + return(zbar_symbol_get_type(PEER_CAST(peer))); +} + +JNIEXPORT jstring JNICALL +Java_net_sourceforge_zbar_Symbol_getData (JNIEnv *env, + jobject obj) +{ + const char *data = zbar_symbol_get_data(GET_PEER(Symbol, obj)); + return((*env)->NewStringUTF(env, data)); +} + +JNIEXPORT jstring JNICALL +Java_net_sourceforge_zbar_Symbol_getDataBytes (JNIEnv *env, + jobject obj) +{ + const zbar_symbol_t *zsym = GET_PEER(Symbol, obj); + const void *data = zbar_symbol_get_data(zsym); + unsigned long datalen = zbar_symbol_get_data_length(zsym); + if(!data || !datalen) + return(NULL); + + jbyteArray bytes = (*env)->NewByteArray(env, datalen); + if(!bytes) + return(NULL); + + (*env)->SetByteArrayRegion(env, bytes, 0, datalen, data); + return(bytes); +} + +JNIEXPORT jint JNICALL +Java_net_sourceforge_zbar_Symbol_getQuality (JNIEnv *env, + jobject obj) +{ + return(zbar_symbol_get_quality(GET_PEER(Symbol, obj))); +} + +JNIEXPORT jint JNICALL +Java_net_sourceforge_zbar_Symbol_getCount (JNIEnv *env, + jobject obj) +{ + return(zbar_symbol_get_count(GET_PEER(Symbol, obj))); +} + +JNIEXPORT jint JNICALL +Java_net_sourceforge_zbar_Symbol_getLocationSize (JNIEnv *env, + jobject obj, + jlong peer) +{ + return(zbar_symbol_get_loc_size(PEER_CAST(peer))); +} + +JNIEXPORT jint JNICALL +Java_net_sourceforge_zbar_Symbol_getLocationX (JNIEnv *env, + jobject obj, + jlong peer, + jint idx) +{ + return(zbar_symbol_get_loc_x(PEER_CAST(peer), idx)); +} + +JNIEXPORT jint JNICALL +Java_net_sourceforge_zbar_Symbol_getLocationY (JNIEnv *env, + jobject obj, + jlong peer, + jint idx) +{ + return(zbar_symbol_get_loc_y(PEER_CAST(peer), idx)); +} + +JNIEXPORT jint JNICALL +Java_net_sourceforge_zbar_Symbol_getOrientation (JNIEnv *env, + jobject obj) +{ + return(zbar_symbol_get_orientation(GET_PEER(Symbol, obj))); +} + +JNIEXPORT jlong JNICALL +Java_net_sourceforge_zbar_Symbol_getComponents (JNIEnv *env, + jobject obj, + jlong peer) +{ + const zbar_symbol_set_t *zsyms = + zbar_symbol_get_components(PEER_CAST(peer)); + if(zsyms) { + zbar_symbol_set_ref(zsyms, 1); + stats.SymbolSet_create++; + } + return((intptr_t)zsyms); +} + +JNIEXPORT jlong JNICALL +Java_net_sourceforge_zbar_Symbol_next (JNIEnv *env, + jobject obj) +{ + const zbar_symbol_t *zsym = zbar_symbol_next(GET_PEER(Symbol, obj)); + if(zsym) { + zbar_symbol_ref(zsym, 1); + stats.Symbol_create++; + } + return((intptr_t)zsym); +} + + + +static void +Image_cleanupByteArray (zbar_image_t *zimg) +{ + jobject data = zbar_image_get_userdata(zimg); + assert(data); + + JNIEnv *env = NULL; + if((*jvm)->AttachCurrentThread(jvm, (void**)&env, NULL)) + return; + assert(env); + if(env && data) { + void *raw = (void*)zbar_image_get_data(zimg); + assert(raw); + /* const image data is unchanged - abort copy back */ + (*env)->ReleaseByteArrayElements(env, data, raw, JNI_ABORT); + (*env)->DeleteGlobalRef(env, data); + zbar_image_set_userdata(zimg, NULL); + } +} + +static void +Image_cleanupIntArray (zbar_image_t *zimg) +{ + jobject data = zbar_image_get_userdata(zimg); + assert(data); + + JNIEnv *env = NULL; + if((*jvm)->AttachCurrentThread(jvm, (void**)&env, NULL)) + return; + assert(env); + if(env && data) { + void *raw = (void*)zbar_image_get_data(zimg); + assert(raw); + /* const image data is unchanged - abort copy back */ + (*env)->ReleaseIntArrayElements(env, data, raw, JNI_ABORT); + (*env)->DeleteGlobalRef(env, data); + zbar_image_set_userdata(zimg, NULL); + } +} + + +JNIEXPORT void JNICALL +Java_net_sourceforge_zbar_Image_init (JNIEnv *env, + jclass cls) +{ + Image_peer = (*env)->GetFieldID(env, cls, "peer", "J"); + Image_data = (*env)->GetFieldID(env, cls, "data", "Ljava/lang/Object;"); +} + +JNIEXPORT jlong JNICALL +Java_net_sourceforge_zbar_Image_create (JNIEnv *env, + jobject obj) +{ + zbar_image_t *zimg = zbar_image_create(); + if(!zimg) { + throw_exc(env, "java/lang/OutOfMemoryError", NULL); + return(0); + } + stats.Image_create++; + return((intptr_t)zimg); +} + +JNIEXPORT void JNICALL +Java_net_sourceforge_zbar_Image_destroy (JNIEnv *env, + jobject obj, + jlong peer) +{ + zbar_image_ref(PEER_CAST(peer), -1); + stats.Image_destroy++; +} + +JNIEXPORT jlong JNICALL +Java_net_sourceforge_zbar_Image_convert (JNIEnv *env, + jobject obj, + jlong peer, + jstring format) +{ + uint32_t fourcc = format_to_fourcc(env, format); + if(!fourcc) + return(0); + zbar_image_t *zimg = zbar_image_convert(PEER_CAST(peer), fourcc); + if(!zimg) + throw_exc(env, "java/lang/UnsupportedOperationException", + "unsupported image format"); + else + stats.Image_create++; + return((intptr_t)zimg); +} + +JNIEXPORT jstring JNICALL +Java_net_sourceforge_zbar_Image_getFormat (JNIEnv *env, + jobject obj) +{ + uint32_t fourcc = zbar_image_get_format(GET_PEER(Image, obj)); + if(!fourcc) + return(NULL); + char fmtstr[5] = { fourcc, fourcc >> 8, fourcc >> 16, fourcc >> 24, 0 }; + return((*env)->NewStringUTF(env, fmtstr)); +} + +JNIEXPORT void JNICALL +Java_net_sourceforge_zbar_Image_setFormat (JNIEnv *env, + jobject obj, + jstring format) +{ + uint32_t fourcc = format_to_fourcc(env, format); + if(!fourcc) + return; + zbar_image_set_format(GET_PEER(Image, obj), fourcc); +} + +JNIEXPORT jint JNICALL +Java_net_sourceforge_zbar_Image_getSequence (JNIEnv *env, + jobject obj) +{ + return(zbar_image_get_sequence(GET_PEER(Image, obj))); +} + +JNIEXPORT void JNICALL +Java_net_sourceforge_zbar_Image_setSequence (JNIEnv *env, + jobject obj, + jint seq) +{ + zbar_image_set_sequence(GET_PEER(Image, obj), seq); +} + +JNIEXPORT jint JNICALL +Java_net_sourceforge_zbar_Image_getWidth (JNIEnv *env, + jobject obj) +{ + return(zbar_image_get_width(GET_PEER(Image, obj))); +} + +JNIEXPORT jint JNICALL +Java_net_sourceforge_zbar_Image_getHeight (JNIEnv *env, + jobject obj) +{ + return(zbar_image_get_height(GET_PEER(Image, obj))); +} + +JNIEXPORT void JNICALL +Java_net_sourceforge_zbar_Image_setSize (JNIEnv *env, + jobject obj, + jint width, + jint height) +{ + zbar_image_set_size(GET_PEER(Image, obj), width, height); +} + +JNIEXPORT jobject JNICALL +Java_net_sourceforge_zbar_Image_getData (JNIEnv *env, + jobject obj) +{ + jobject data = (*env)->GetObjectField(env, obj, Image_data); + if(data) + return(data); + + zbar_image_t *zimg = GET_PEER(Image, obj); + data = zbar_image_get_userdata(zimg); + if(data) + return(data); + + unsigned long rawlen = zbar_image_get_data_length(zimg); + const void *raw = zbar_image_get_data(zimg); + if(!rawlen || !raw) + return(NULL); + + data = (*env)->NewByteArray(env, rawlen); + if(!data) + return(NULL); + + (*env)->SetByteArrayRegion(env, data, 0, rawlen, raw); + (*env)->SetObjectField(env, obj, Image_data, data); + return(data); +} + +static inline void +Image_setData (JNIEnv *env, + jobject obj, + jbyteArray data, + void *raw, + unsigned long rawlen, + zbar_image_cleanup_handler_t *cleanup) +{ + if(!data) + cleanup = NULL; + (*env)->SetObjectField(env, obj, Image_data, data); + zbar_image_t *zimg = GET_PEER(Image, obj); + zbar_image_set_data(zimg, raw, rawlen, cleanup); + zbar_image_set_userdata(zimg, (*env)->NewGlobalRef(env, data)); +} + +JNIEXPORT void JNICALL +Java_net_sourceforge_zbar_Image_setData___3B (JNIEnv *env, + jobject obj, + jbyteArray data) +{ + jbyte *raw = NULL; + unsigned long rawlen = 0; + if(data) { + raw = (*env)->GetByteArrayElements(env, data, NULL); + if(!raw) + return; + rawlen = (*env)->GetArrayLength(env, data); + } + Image_setData(env, obj, data, raw, rawlen, Image_cleanupByteArray); +} + +JNIEXPORT void JNICALL +Java_net_sourceforge_zbar_Image_setData___3I (JNIEnv *env, + jobject obj, + jintArray data) +{ + jint *raw = NULL; + unsigned long rawlen = 0; + if(data) { + raw = (*env)->GetIntArrayElements(env, data, NULL); + if(!raw) + return; + rawlen = (*env)->GetArrayLength(env, data) * sizeof(*raw); + } + Image_setData(env, obj, data, raw, rawlen, Image_cleanupIntArray); +} + +JNIEXPORT jlong JNICALL +Java_net_sourceforge_zbar_Image_getSymbols (JNIEnv *env, + jobject obj, + jlong peer) +{ + const zbar_symbol_set_t *zsyms = zbar_image_get_symbols(PEER_CAST(peer)); + if(zsyms) { + zbar_symbol_set_ref(zsyms, 1); + stats.SymbolSet_create++; + } + return((intptr_t)zsyms); +} + + +JNIEXPORT void JNICALL +Java_net_sourceforge_zbar_ImageScanner_init (JNIEnv *env, + jclass cls) +{ + ImageScanner_peer = (*env)->GetFieldID(env, cls, "peer", "J"); +} + +JNIEXPORT jlong JNICALL +Java_net_sourceforge_zbar_ImageScanner_create (JNIEnv *env, + jobject obj) +{ + zbar_image_scanner_t *zscn = zbar_image_scanner_create(); + if(!zscn) { + throw_exc(env, "java/lang/OutOfMemoryError", NULL); + return(0); + } + stats.ImageScanner_create++; + return((intptr_t)zscn); +} + +JNIEXPORT void JNICALL +Java_net_sourceforge_zbar_ImageScanner_destroy (JNIEnv *env, + jobject obj, + jlong peer) +{ + zbar_image_scanner_destroy(PEER_CAST(peer)); + stats.ImageScanner_destroy++; +} + +JNIEXPORT void JNICALL +Java_net_sourceforge_zbar_ImageScanner_setConfig (JNIEnv *env, + jobject obj, + jint symbology, + jint config, + jint value) +{ + zbar_image_scanner_set_config(GET_PEER(ImageScanner, obj), + symbology, config, value); +} + +JNIEXPORT void JNICALL +Java_net_sourceforge_zbar_ImageScanner_parseConfig (JNIEnv *env, + jobject obj, + jstring cfg) +{ + const char *cfgstr = (*env)->GetStringUTFChars(env, cfg, NULL); + if(!cfgstr) + return; + if(zbar_image_scanner_parse_config(GET_PEER(ImageScanner, obj), cfgstr)) + throw_exc(env, "java/lang/IllegalArgumentException", + "unknown configuration"); +} + +JNIEXPORT void JNICALL +Java_net_sourceforge_zbar_ImageScanner_enableCache (JNIEnv *env, + jobject obj, + jboolean enable) +{ + zbar_image_scanner_enable_cache(GET_PEER(ImageScanner, obj), enable); +} + +JNIEXPORT jlong JNICALL +Java_net_sourceforge_zbar_ImageScanner_getResults (JNIEnv *env, + jobject obj, + jlong peer) +{ + const zbar_symbol_set_t *zsyms = + zbar_image_scanner_get_results(PEER_CAST(peer)); + if(zsyms) { + zbar_symbol_set_ref(zsyms, 1); + stats.SymbolSet_create++; + } + return((intptr_t)zsyms); +} + +JNIEXPORT jint JNICALL +Java_net_sourceforge_zbar_ImageScanner_scanImage (JNIEnv *env, + jobject obj, + jobject image) +{ + zbar_image_scanner_t *zscn = GET_PEER(ImageScanner, obj); + zbar_image_t *zimg = GET_PEER(Image, image); + + int n = zbar_scan_image(zscn, zimg); + if(n < 0) + throw_exc(env, "java/lang/UnsupportedOperationException", + "unsupported image format"); + return(n); +} diff --git a/zbarcam/zbarcam.c b/zbarcam/zbarcam.c index f1f3233..8f8fadf 100644 --- a/zbarcam/zbarcam.c +++ b/zbarcam/zbarcam.c @@ -107,19 +107,23 @@ static void data_handler (zbar_image_t *img, const void *userdata) if(!format) { printf("%s:", zbar_get_symbol_name(type)); - fwrite(zbar_symbol_get_data(sym), - zbar_symbol_get_data_length(sym), - 1, stdout); + if(fwrite(zbar_symbol_get_data(sym), + zbar_symbol_get_data_length(sym), + 1, stdout) != 1) + continue; + } + else if(format == RAW) { + if(fwrite(zbar_symbol_get_data(sym), + zbar_symbol_get_data_length(sym), + 1, stdout) != 1) + continue; } - else if(format == RAW) - fwrite(zbar_symbol_get_data(sym), - zbar_symbol_get_data_length(sym), - 1, stdout); else if(format == XML) { if(!n) printf("\n", zbar_image_get_sequence(img)); zbar_symbol_xml(sym, &xml_buf, &xml_len); - fwrite(xml_buf, xml_len, 1, stdout); + if(fwrite(xml_buf, xml_len, 1, stdout) != 1) + continue; } printf("\n"); n++; diff --git a/zbarimg/zbarimg.c b/zbarimg/zbarimg.c index 9376a49..3467a83 100644 --- a/zbarimg/zbarimg.c +++ b/zbarimg/zbarimg.c @@ -169,21 +169,31 @@ static int scan_image (const char *filename) continue; else if(!xmllvl) { printf("%s:", zbar_get_symbol_name(typ)); - fwrite(zbar_symbol_get_data(sym), - zbar_symbol_get_data_length(sym), - 1, stdout); + if(fwrite(zbar_symbol_get_data(sym), + zbar_symbol_get_data_length(sym), + 1, stdout) != 1) { + exit_code = 1; + return(-1); + } + } + else if(xmllvl < 0) { + if(fwrite(zbar_symbol_get_data(sym), + zbar_symbol_get_data_length(sym), + 1, stdout) != 1) { + exit_code = 1; + return(-1); + } } - else if(xmllvl < 0) - fwrite(zbar_symbol_get_data(sym), - zbar_symbol_get_data_length(sym), - 1, stdout); else { if(xmllvl < 3) { xmllvl++; printf("\n", seq); } zbar_symbol_xml(sym, &xmlbuf, &xmlbuflen); - fwrite(xmlbuf, xmlbuflen, 1, stdout); + if(fwrite(xmlbuf, xmlbuflen, 1, stdout) != 1) { + exit_code = 1; + return(-1); + } } printf("\n"); found++; From 539442d1976277ef09647d083bf4076a3f494dbd Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 4 Mar 2010 13:06:59 -0500 Subject: [PATCH 185/328] 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 --- ChangeLog | 7 + iphone/ZBarHelpController.h | 12 +- iphone/ZBarHelpController.m | 366 ++++++++---------- iphone/ZBarReaderController.m | 22 +- iphone/res/back.png | Bin 0 -> 319 bytes iphone/res/back.svg | 31 ++ iphone/res/shakyhand.svg | 2 +- iphone/res/shakyphone.svg | 51 +++ iphone/res/zbar-help.html | 83 ++++ iphone/res/zbar-helpicons.png | Bin 14506 -> 18350 bytes iphone/res/zbar-samples.png | Bin 0 -> 1181 bytes .../readertest.xcodeproj/project.pbxproj | 16 +- 12 files changed, 377 insertions(+), 213 deletions(-) create mode 100644 iphone/res/back.png create mode 100644 iphone/res/back.svg create mode 100644 iphone/res/shakyphone.svg create mode 100644 iphone/res/zbar-help.html create mode 100644 iphone/res/zbar-samples.png diff --git a/ChangeLog b/ChangeLog index 002ab55..3b6805f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,11 @@ current: + * 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 diff --git a/iphone/ZBarHelpController.h b/iphone/ZBarHelpController.h index a3f1e76..2f2d12e 100644 --- a/iphone/ZBarHelpController.h +++ b/iphone/ZBarHelpController.h @@ -26,15 +26,19 @@ // failure dialog w/a few useful tips @interface ZBarHelpController : UIViewController + < UIWebViewDelegate, + UIAlertViewDelegate > { - NSString *title; + NSString *reason; id delegate; + UIWebView *webView; + UIToolbar *toolbar; + UIBarButtonItem *doneBtn, *backBtn, *space[2]; + NSURL *linkURL; } @property (nonatomic, assign) id delegate; -- (id) initWithTitle: (NSString*) title; +- (id) initWithReason: (NSString*) reason; @end - -extern UIButton *_ZBarButton (CGFloat size, CGFloat r, CGFloat g, CGFloat b); diff --git a/iphone/ZBarHelpController.m b/iphone/ZBarHelpController.m index 0cd1f27..90c1116 100644 --- a/iphone/ZBarHelpController.m +++ b/iphone/ZBarHelpController.m @@ -33,99 +33,49 @@ - (void) helpController: (ZBarHelpController*) help enum { BTN_TRYAGAIN = 1 }; -UIButton *_ZBarButton (CGFloat size, - CGFloat red, - CGFloat green, - CGFloat blue) -{ - UIButton *btn = [UIButton buttonWithType: UIButtonTypeCustom]; - UILabel *label = btn.titleLabel; - label.shadowColor = [UIColor lightGrayColor]; - label.shadowOffset = CGSizeMake(-1,1); - label.font = [UIFont boldSystemFontOfSize: size * 5 / 12]; - - CGRect r = CGRectMake(0, 0, 48, 48); - CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB(); - CGContextRef ctx = - CGBitmapContextCreate(NULL, r.size.width, r.size.height, - 8, r.size.width * 4, cs, - kCGBitmapByteOrderDefault | - kCGImageAlphaPremultipliedFirst); - CGColorSpaceRelease(cs); - - CGContextSetRGBFillColor(ctx, red, green, blue, 1); - - UIImage *buttonset = [UIImage imageNamed: @"zbar-button.png"]; - CGImageRef setimg = buttonset.CGImage; - CGImageRef up = CGImageCreateWithImageInRect(setimg, r); - r.origin.x = 48; - CGImageRef down = CGImageCreateWithImageInRect(setimg, r); - r.origin.x = 96; - CGImageRef mask = CGImageCreateWithImageInRect(setimg, r); - - r.origin.x = 0; - CGContextClipToMask(ctx, r, mask); - CGImageRelease(mask); - - CGContextFillRect(ctx, r); - CGContextDrawImage(ctx, r, up); - CGImageRelease(up); - - CGImageRef img = CGBitmapContextCreateImage(ctx); - [btn setBackgroundImage: - [[UIImage imageWithCGImage: img] - stretchableImageWithLeftCapWidth: 24 - topCapHeight: 24] - forState: UIControlStateNormal]; - CGImageRelease(img); - - CGContextFillRect(ctx, r); - CGContextDrawImage(ctx, r, down); - CGImageRelease(down); - - img = CGBitmapContextCreateImage(ctx); - [btn setBackgroundImage: - [[UIImage imageWithCGImage: img] - stretchableImageWithLeftCapWidth: 24 - topCapHeight: 24] - forState: UIControlStateHighlighted]; - CGImageRelease(img); - - CGContextRelease(ctx); - return(btn); -} - @implementation ZBarHelpController @synthesize delegate; -- (id) initWithTitle: (NSString*) t +- (id) initWithReason: (NSString*) _reason { - if(self = [super init]) - title = [t retain]; + if(self = [super init]) { + if(!_reason) + _reason = @"HELP"; + reason = [_reason retain]; + } return(self); } -- (void) dealloc +- (id) init { - [title release]; - title = nil; - [super dealloc]; + return([self initWithReason: nil]); +} + +- (void) cleanup +{ + [toolbar release]; + toolbar = nil; + [webView release]; + webView = nil; + [doneBtn release]; + doneBtn = nil; + [backBtn release]; + backBtn = nil; + [space[0] release]; + space[0] = nil; + [space[1] release]; + space[1] = nil; } -- (UILabel*) addLabelAt: (CGRect) frame - withText: (NSString*) text - font: (UIFont*) font +- (void) dealloc { - UILabel *label = [[[UILabel alloc] initWithFrame: frame] autorelease]; - label.autoresizingMask = (UIViewAutoresizingFlexibleWidth | - UIViewAutoresizingFlexibleHeight); - label.backgroundColor = [UIColor clearColor]; - label.textColor = [UIColor whiteColor]; - label.font = font; - label.text = text; - [self.view addSubview: label]; - return(label); + [self cleanup]; + [reason release]; + reason = nil; + [linkURL release]; + linkURL = nil; + [super dealloc]; } - (void) viewDidLoad @@ -136,131 +86,147 @@ - (void) viewDidLoad view.backgroundColor = [UIColor colorWithWhite: .125f alpha: 1 ]; - CGSize size = view.bounds.size; - CGRect r; - r.origin.x = 0; - r.origin.y = 0; - r.size.width = size.width; - r.size.height = size.height * 19 / 115; - UILabel *label = - [self addLabelAt: r - withText: title - font: [UIFont boldSystemFontOfSize: size.height * 12 / 115]]; - label.textAlignment = UITextAlignmentCenter; - label.adjustsFontSizeToFitWidth = YES; - label.minimumFontSize = size.height * 5 / 115; - label.textColor = [UIColor colorWithRed: 1.0f green: 0.4f blue: 0.4f - alpha: 1.0f]; - label.shadowColor = [UIColor colorWithRed: 0.5f green: 0.2f blue: 0.2f - alpha: 1.0f]; - label.shadowOffset = CGSizeMake(-1.5,1.5); - - UIFont *bigFont = [UIFont boldSystemFontOfSize: size.height * 7 / 115]; - UIFont *smallFont = [UIFont systemFontOfSize: size.height * 4 / 115]; - - r.origin.x = size.width * .05f; - r.size.width = size.width * 0.9f; + CGRect r = view.bounds; + r.size.height -= 54; + webView = [[UIWebView alloc] + initWithFrame: r]; + webView.delegate = self; + webView.backgroundColor = [UIColor colorWithWhite: .125f + alpha: 1 ]; + toolbar = [UIToolbar new]; + toolbar.barStyle = UIBarStyleBlackOpaque; r.origin.y = r.size.height; - r.size.height = size.height * 8 / 115; - [self addLabelAt: r - withText: @"Hints for successful scanning:" - font: smallFont] - .textAlignment = UITextAlignmentCenter; - - r.origin.x = r.size.width * 7 / 20; - r.size.width = r.size.width * 13 / 20; - - r.origin.y = size.height * 31 / 115; - r.size.height = size.height * 6 / 115; - [self addLabelAt: r - withText: @"ensure there is plenty of" - font: smallFont]; - - r.origin.y = size.height * 39 / 115; - r.size.height = size.height * 8 / 115; - [self addLabelAt: r - withText: @"Light" - font: bigFont] - .textColor = [UIColor colorWithRed: 1.0f green: 1.0f blue: 0.333f - alpha: 1]; - - r.origin.y = size.height * 55 / 115; - r.size.height = size.height * 8 / 115; - [self addLabelAt: r - withText: @"Wait" - font: bigFont] - .textColor = [UIColor colorWithRed: 0.5f green: 1.0f blue: 0.5f - alpha: 1]; - - r.origin.y = size.height * 65 / 115; - r.size.height = size.height * 6 / 115; - [self addLabelAt: r - withText: @"for the camera to focus" - font: smallFont]; - - r.origin.y = size.height * 79 / 115; - r.size.height = size.height * 8 / 115; - [self addLabelAt: r - withText: @"Hold Still" - font: bigFont] - .textColor = [UIColor colorWithRed: 0.583f green: 0.583f blue: 1.0f - alpha: 1]; - - r.origin.y = size.height * 89 / 115; - r.size.height = size.height * 6 / 115; - [self addLabelAt: r - withText: @"while taking the picture" - font: smallFont]; - - r.origin.x = size.width / 20; - r.size.width = r.size.height = 64; - - UIImage *iconset = [UIImage imageNamed: @"zbar-helpicons.png"]; - CGImageRef setimg = iconset.CGImage; - - r.origin.y = size.height * 31 / 115; - UIImageView *icon = [[UIImageView alloc] initWithFrame: r]; - CGImageRef img = - CGImageCreateWithImageInRect(setimg, CGRectMake(0, 0, 64, 64)); - icon.image = [UIImage imageWithCGImage: img]; - CGImageRelease(img); - [view addSubview: icon]; - [icon release]; - - r.origin.y = size.height * 55 / 115; - icon = [[UIImageView alloc] initWithFrame: r]; - img = CGImageCreateWithImageInRect(setimg, CGRectMake(64, 0, 64, 64)); - icon.image = [UIImage imageWithCGImage: img]; - CGImageRelease(img); - [view addSubview: icon]; - [icon release]; - - r.origin.y = size.height * 79 / 115; - icon = [[UIImageView alloc] initWithFrame: r]; - img = CGImageCreateWithImageInRect(setimg, CGRectMake(128, 0, 64, 64)); - icon.image = [UIImage imageWithCGImage: img]; - CGImageRelease(img); - [view addSubview: icon]; - [icon release]; - - UIButton *btn = _ZBarButton(48, .1, .7, .1); - btn.frame = CGRectMake(size.width / 4 + 4, size.height - 52, - size.width / 2 - 8, 48); - btn.tag = BTN_TRYAGAIN; - [btn addTarget: self - action: @selector(buttonPressed:) - forControlEvents: UIControlEventTouchUpInside]; - [btn setTitle: @"Try Again" - forState: UIControlStateNormal]; - [view addSubview: btn]; + r.size.height = 54; + toolbar.frame = r; + + doneBtn = [[UIBarButtonItem alloc] + initWithBarButtonSystemItem: UIBarButtonSystemItemCamera + target: self + action: @selector(dismiss)]; + doneBtn.width = 32; + + backBtn = [[UIBarButtonItem alloc] + initWithImage: [UIImage imageNamed: @"back.png"] + style: UIBarButtonItemStylePlain + target: webView + action: @selector(goBack)]; + + space[0] = [[UIBarButtonItem alloc] + initWithBarButtonSystemItem: + UIBarButtonSystemItemFlexibleSpace + target: nil + action: nil]; + space[1] = [[UIBarButtonItem alloc] + initWithBarButtonSystemItem: + UIBarButtonSystemItemFixedSpace + target: nil + action: nil]; + space[1].width = r.size.width / 2 - 17; + + toolbar.items = [NSArray arrayWithObjects: + space[0], doneBtn, space[1], 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 removeFromSuperview]; + [super viewWillAppear: animated]; } -- (void) buttonPressed: (UIButton*) button +- (void) viewWillDisappear: (BOOL) animated +{ + [webView stopLoading]; + webView.delegate = nil; + [super viewWillDisappear: animated]; +} + +- (void) dismiss { - int idx = button.tag; [delegate helpController: self - clickedButtonAtIndex: idx]; + clickedButtonAtIndex: BTN_TRYAGAIN]; +} + +- (void) webViewDidFinishLoad: (UIWebView*) view +{ + if(!view.superview) { + [view stringByEvaluatingJavaScriptFromString: + [NSString stringWithFormat: + @"onZBarHelp({reason:\"%@\"});", reason]]; + [UIView beginAnimations: @"ZBarHelp" + context: nil]; + [self.view addSubview: webView]; + [UIView commitAnimations]; + } + + BOOL canGoBack = [view canGoBack]; + NSArray *items = toolbar.items; + if(canGoBack != ([items objectAtIndex: 0] == backBtn)) { + if(canGoBack) + items = [NSArray arrayWithObjects: + backBtn, space[0], doneBtn, space[1], nil]; + else + items = [NSArray arrayWithObjects: + space[0], doneBtn, space[1], 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 diff --git a/iphone/ZBarReaderController.m b/iphone/ZBarReaderController.m index 2a23e6e..94e3d60 100644 --- a/iphone/ZBarReaderController.m +++ b/iphone/ZBarReaderController.m @@ -68,9 +68,10 @@ - (id) init - (void) showHelpOverlay { + sampling = NO; + scanner.enableCache = NO; if(!help) { - help = [[ZBarHelpController alloc] - initWithTitle: @"Barcode Reader"]; + help = [ZBarHelpController new]; help.delegate = self; } help.wantsFullScreenLayout = YES; @@ -206,7 +207,7 @@ - (void) reenable self.view.userInteractionEnabled = YES; } -- (void) viewWillAppear: (BOOL) animated +- (void) initScanning { if(help) { [help.view removeFromSuperview]; @@ -285,7 +286,11 @@ - (void) viewWillAppear: (BOOL) animated [boxView removeFromSuperview]; } } +} +- (void) viewWillAppear: (BOOL) animated +{ + [self initScanning]; [super viewWillAppear: animated]; } @@ -598,8 +603,13 @@ - (void) imagePickerController: (UIImagePickerController*) picker BOOL camera = (self.sourceType == UIImagePickerControllerSourceTypeCamera); BOOL retry = !camera || (hasOverlay && ![self showsCameraControls]); if(showsHelpOnFail && retry) { + assert(!help); + if(help) { + [help.view removeFromSuperview]; + [help release]; + } help = [[ZBarHelpController alloc] - initWithTitle: @"No Barcode Found"]; + initWithReason: @"FAIL"]; help.delegate = self; if(camera) [self showHelpOverlay]; @@ -634,10 +644,14 @@ - (void) helpController: (ZBarHelpController*) hlp [UIView beginAnimations: @"ZBarHelp" context: nil]; hlp.view.alpha = 0; + [help.view removeFromSuperview]; [UIView commitAnimations]; + [self initScanning]; } else [hlp dismissModalViewControllerAnimated: YES]; + [help release]; + help = nil; } - (id ) scanImage: (CGImageRef) image diff --git a/iphone/res/back.png b/iphone/res/back.png new file mode 100644 index 0000000000000000000000000000000000000000..6a0681d0deeaa2cfbeffa620ea31a3cc279fd0da GIT binary patch literal 319 zcmeAS@N?(olHy`uVBq!ia0vp^vOp}s!VDz86uj;SQVPi)LB0$ORcZ_j4J`}|zkosw zFBlj~4Hy_+B``2p&0t^U81Og;E^i1;U|nHU!NqnWASUVLMz)S! z-~H2eht1Qf`Mvy%oX@3K + + + + + + + left pointing arrow toolbar icon + + + + + + + + + + + diff --git a/iphone/res/shakyhand.svg b/iphone/res/shakyhand.svg index 273efd0..66a2eec 100644 --- a/iphone/res/shakyhand.svg +++ b/iphone/res/shakyhand.svg @@ -22,7 +22,7 @@ #hand-outline { stroke: #a76; stroke-width: .75; stroke-opacity: 1 } #skin-base { fill: #db9 } #skin circle { fill: url(#skin-grad);/* stroke: red; stroke-width: .01*/ } - #shakes { stroke: #f43; stroke-width: .03125 } + #shakes { stroke: #d5f; stroke-width: .03125 } /* #f43 */ ]]> diff --git a/iphone/res/shakyphone.svg b/iphone/res/shakyphone.svg new file mode 100644 index 0000000..96db019 --- /dev/null +++ b/iphone/res/shakyphone.svg @@ -0,0 +1,51 @@ + + + + + + + + iPhone shake gesture icon + + + + + + + + + + + + + + + + + + + + + + diff --git a/iphone/res/zbar-help.html b/iphone/res/zbar-help.html new file mode 100644 index 0000000..0ec90f1 --- /dev/null +++ b/iphone/res/zbar-help.html @@ -0,0 +1,83 @@ + + + + + +Barcode Reader Help + + + +

Barcode Reader Help

+
+

Recognized barcodes should look like

+ +
+ +

QR Codes

+
+

Also Code 128 and Code 39 (not shown)

+
+

Hints for successful scanning

+
+
+

Ensure there is plenty of

+

Light

+
+
+
4"
+

Distance

+

should be about 3 to 5 inches

+
+
+
+

Shake

+

to force the camera to focus

+
+
+
+

Wait

+

for the autofocus to finish

+
+
+
+

Hold Still

+

while the barcode is scanned

+
+ + + diff --git a/iphone/res/zbar-helpicons.png b/iphone/res/zbar-helpicons.png index 37d42f0d7596e9576596b36b019d3d238c924bba..2a07e7c44478cd30a1e297395de2f25c8a7bb52a 100644 GIT binary patch literal 18350 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 JPDHLkV1mE0dd2_% literal 14506 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 literal 0 HcmV?d00001 diff --git a/test/iphone/readertest.xcodeproj/project.pbxproj b/test/iphone/readertest.xcodeproj/project.pbxproj index dfa3eb9..c00af7a 100755 --- a/test/iphone/readertest.xcodeproj/project.pbxproj +++ b/test/iphone/readertest.xcodeproj/project.pbxproj @@ -10,9 +10,11 @@ 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; }; - DC0BB57C10B124EB000448CB /* zbar-button.png in Resources */ = {isa = PBXBuildFile; fileRef = DC0BB57A10B124EB000448CB /* zbar-button.png */; }; DC0BB57D10B124EB000448CB /* zbar-helpicons.png in Resources */ = {isa = PBXBuildFile; fileRef = DC0BB57B10B124EB000448CB /* zbar-helpicons.png */; }; DC1C8DED10DAAEBA004C0F9E /* entitlements.plist in Resources */ = {isa = PBXBuildFile; fileRef = DC1C8DEC10DAAEBA004C0F9E /* entitlements.plist */; }; + DC7E3325113DA00200E67FB8 /* zbar-help.html in Resources */ = {isa = PBXBuildFile; fileRef = DC7E3324113DA00200E67FB8 /* zbar-help.html */; }; + DC7E3337113DAEE700E67FB8 /* back.png in Resources */ = {isa = PBXBuildFile; fileRef = DC7E3336113DAEE700E67FB8 /* back.png */; }; + DC7E33EA113EA95800E67FB8 /* zbar-samples.png in Resources */ = {isa = PBXBuildFile; fileRef = DC7E33E9113EA95800E67FB8 /* zbar-samples.png */; }; DCB9118510BC5DA200B907F0 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCB9118410BC5DA200B907F0 /* QuartzCore.framework */; }; DCB9118810BC5DB500B907F0 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD6E13B10B0AFD4002005CD /* libiconv.dylib */; }; DCB9119B10BC5DCB00B907F0 /* libzbar.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD6E0E610B0AE16002005CD /* libzbar.a */; }; @@ -41,9 +43,11 @@ 1D6058910D05DD3D006BFB54 /* readertest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = readertest.app; sourceTree = BUILT_PRODUCTS_DIR; }; 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 288765FC0DF74451002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - DC0BB57A10B124EB000448CB /* zbar-button.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "zbar-button.png"; path = "../../iphone/res/zbar-button.png"; sourceTree = SOURCE_ROOT; }; DC0BB57B10B124EB000448CB /* zbar-helpicons.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "zbar-helpicons.png"; path = "../../iphone/res/zbar-helpicons.png"; sourceTree = SOURCE_ROOT; }; DC1C8DEC10DAAEBA004C0F9E /* entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = entitlements.plist; sourceTree = ""; }; + DC7E3324113DA00200E67FB8 /* zbar-help.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = "zbar-help.html"; path = "../../iphone/res/zbar-help.html"; sourceTree = SOURCE_ROOT; }; + DC7E3336113DAEE700E67FB8 /* back.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = back.png; path = ../../iphone/res/back.png; sourceTree = SOURCE_ROOT; }; + DC7E33E9113EA95800E67FB8 /* zbar-samples.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "zbar-samples.png"; path = "../../iphone/res/zbar-samples.png"; sourceTree = SOURCE_ROOT; }; DCB9118410BC5DA200B907F0 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; DCD6E0CE10B0AD41002005CD /* prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = prefix.pch; sourceTree = ""; }; DCD6E0CF10B0AD41002005CD /* readertest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = readertest.m; sourceTree = ""; }; @@ -84,8 +88,10 @@ DCD6E0CF10B0AD41002005CD /* readertest.m */, DCD6E0CE10B0AD41002005CD /* prefix.pch */, DCD6E0D810B0AD55002005CD /* readertest.plist */, - DC0BB57A10B124EB000448CB /* zbar-button.png */, + DC7E3324113DA00200E67FB8 /* zbar-help.html */, DC0BB57B10B124EB000448CB /* zbar-helpicons.png */, + DC7E33E9113EA95800E67FB8 /* zbar-samples.png */, + DC7E3336113DAEE700E67FB8 /* back.png */, DCD6E0DE10B0AE16002005CD /* zbar.xcodeproj */, 29B97323FDCFA39411CA2CEA /* Frameworks */, 19C28FACFE9D520D11CA2CBB /* Products */, @@ -172,9 +178,11 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - DC0BB57C10B124EB000448CB /* zbar-button.png in Resources */, DC0BB57D10B124EB000448CB /* zbar-helpicons.png in Resources */, DC1C8DED10DAAEBA004C0F9E /* entitlements.plist in Resources */, + DC7E3325113DA00200E67FB8 /* zbar-help.html in Resources */, + DC7E3337113DAEE700E67FB8 /* back.png in Resources */, + DC7E33EA113EA95800E67FB8 /* zbar-samples.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; From 57338812a995b41776e29408e9b60660e08a928c Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 5 Mar 2010 15:08:44 -0500 Subject: [PATCH 186/328] fixes to new iphone help display --- ChangeLog | 1 + iphone/ZBarHelpController.h | 2 +- iphone/ZBarHelpController.m | 36 ++++++------------ iphone/ZBarReaderController.m | 72 ++++++++++++++++++----------------- 4 files changed, 51 insertions(+), 60 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3b6805f..4c75785 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * 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 diff --git a/iphone/ZBarHelpController.h b/iphone/ZBarHelpController.h index 2f2d12e..051b14c 100644 --- a/iphone/ZBarHelpController.h +++ b/iphone/ZBarHelpController.h @@ -33,7 +33,7 @@ id delegate; UIWebView *webView; UIToolbar *toolbar; - UIBarButtonItem *doneBtn, *backBtn, *space[2]; + UIBarButtonItem *doneBtn, *backBtn, *space; NSURL *linkURL; } diff --git a/iphone/ZBarHelpController.m b/iphone/ZBarHelpController.m index 90c1116..306a10e 100644 --- a/iphone/ZBarHelpController.m +++ b/iphone/ZBarHelpController.m @@ -62,10 +62,8 @@ - (void) cleanup doneBtn = nil; [backBtn release]; backBtn = nil; - [space[0] release]; - space[0] = nil; - [space[1] release]; - space[1] = nil; + [space release]; + space = nil; } - (void) dealloc @@ -101,10 +99,9 @@ - (void) viewDidLoad toolbar.frame = r; doneBtn = [[UIBarButtonItem alloc] - initWithBarButtonSystemItem: UIBarButtonSystemItemCamera + initWithBarButtonSystemItem: UIBarButtonSystemItemDone target: self action: @selector(dismiss)]; - doneBtn.width = 32; backBtn = [[UIBarButtonItem alloc] initWithImage: [UIImage imageNamed: @"back.png"] @@ -112,20 +109,13 @@ - (void) viewDidLoad target: webView action: @selector(goBack)]; - space[0] = [[UIBarButtonItem alloc] - initWithBarButtonSystemItem: - UIBarButtonSystemItemFlexibleSpace - target: nil - action: nil]; - space[1] = [[UIBarButtonItem alloc] - initWithBarButtonSystemItem: - UIBarButtonSystemItemFixedSpace - target: nil - action: nil]; - space[1].width = r.size.width / 2 - 17; - - toolbar.items = [NSArray arrayWithObjects: - space[0], doneBtn, space[1], nil]; + space = [[UIBarButtonItem alloc] + initWithBarButtonSystemItem: + UIBarButtonSystemItemFlexibleSpace + target: nil + action: nil]; + + toolbar.items = [NSArray arrayWithObjects: space, doneBtn, nil]; [view addSubview: toolbar]; @@ -189,11 +179,9 @@ - (void) webViewDidFinishLoad: (UIWebView*) view NSArray *items = toolbar.items; if(canGoBack != ([items objectAtIndex: 0] == backBtn)) { if(canGoBack) - items = [NSArray arrayWithObjects: - backBtn, space[0], doneBtn, space[1], nil]; + items = [NSArray arrayWithObjects: backBtn, space, doneBtn, nil]; else - items = [NSArray arrayWithObjects: - space[0], doneBtn, space[1], nil]; + items = [NSArray arrayWithObjects: space, doneBtn, nil]; [toolbar setItems: items animated: YES]; } diff --git a/iphone/ZBarReaderController.m b/iphone/ZBarReaderController.m index 94e3d60..aa480ec 100644 --- a/iphone/ZBarReaderController.m +++ b/iphone/ZBarReaderController.m @@ -66,23 +66,6 @@ - (id) init return(self); } -- (void) showHelpOverlay -{ - sampling = NO; - scanner.enableCache = NO; - if(!help) { - help = [ZBarHelpController new]; - help.delegate = self; - } - help.wantsFullScreenLayout = YES; - help.view.alpha = 0; - [[self cameraOverlayView] addSubview: help.view]; - [UIView beginAnimations: @"ZBarHelp" - context: nil]; - help.view.alpha = 1; - [UIView commitAnimations]; -} - - (void) initOverlay { CGRect bounds = self.view.bounds; @@ -137,7 +120,7 @@ - (void) initOverlay r.size.width = 54; infoBtn.frame = r; [infoBtn addTarget: self - action: @selector(showHelpOverlay) + action: @selector(info) forControlEvents: UIControlEventTouchUpInside]; } @@ -209,12 +192,6 @@ - (void) reenable - (void) initScanning { - if(help) { - [help.view removeFromSuperview]; - [help release]; - help = nil; - } - if(hasOverlay && self.sourceType == UIImagePickerControllerSourceTypeCamera) { if(showsZBarControls || ![self cameraOverlayView]) @@ -296,6 +273,11 @@ - (void) viewWillAppear: (BOOL) animated - (void) viewWillDisappear: (BOOL) animated { + if(help) { + [help.view removeFromSuperview]; + [help release]; + help = nil; + } sampling = NO; scanner.enableCache = NO; [super viewWillDisappear: animated]; @@ -562,6 +544,36 @@ - (void) scanSequence: (UIImage*) image [self updateBox: sym]; } +- (void) initHelpWithReason: (NSString*) reason +{ + if(help) { + [help.view removeFromSuperview]; + [help release]; + } + help = [[ZBarHelpController alloc] + initWithReason: reason]; + help.delegate = self; +} + +- (void) showHelpOverlay +{ + sampling = NO; + scanner.enableCache = NO; + help.wantsFullScreenLayout = YES; + help.view.alpha = 0; + [[self cameraOverlayView] addSubview: help.view]; + [UIView beginAnimations: @"ZBarHelp" + context: nil]; + help.view.alpha = 1; + [UIView commitAnimations]; +} + +- (void) info +{ + [self initHelpWithReason: @"HELP"]; + [self showHelpOverlay]; +} + - (void) imagePickerController: (UIImagePickerController*) picker didFinishPickingMediaWithInfo: (NSDictionary*) info { @@ -603,14 +615,7 @@ - (void) imagePickerController: (UIImagePickerController*) picker BOOL camera = (self.sourceType == UIImagePickerControllerSourceTypeCamera); BOOL retry = !camera || (hasOverlay && ![self showsCameraControls]); if(showsHelpOnFail && retry) { - assert(!help); - if(help) { - [help.view removeFromSuperview]; - [help release]; - } - help = [[ZBarHelpController alloc] - initWithReason: @"FAIL"]; - help.delegate = self; + [self initHelpWithReason: @"FAIL"]; if(camera) [self showHelpOverlay]; else @@ -644,14 +649,11 @@ - (void) helpController: (ZBarHelpController*) hlp [UIView beginAnimations: @"ZBarHelp" context: nil]; hlp.view.alpha = 0; - [help.view removeFromSuperview]; [UIView commitAnimations]; [self initScanning]; } else [hlp dismissModalViewControllerAnimated: YES]; - [help release]; - help = nil; } - (id ) scanImage: (CGImageRef) image From 6f92eb5b0ac069739b458fea32457b5bc7e7dce1 Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 6 Mar 2010 10:10:46 -0500 Subject: [PATCH 187/328] cleanup and expose iphone help display API --- ChangeLog | 1 + include/zbar/ZBarReaderController.h | 6 ++++ iphone/ZBarHelpController.m | 2 +- iphone/ZBarReaderController.m | 49 +++++++++++++---------------- iphone/res/zbar-help.html | 2 +- 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4c75785..763b526 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * 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 diff --git a/include/zbar/ZBarReaderController.h b/include/zbar/ZBarReaderController.h index e4564cd..9dfacc5 100644 --- a/include/zbar/ZBarReaderController.h +++ b/include/zbar/ZBarReaderController.h @@ -125,6 +125,12 @@ typedef enum { // defaults to 640. @property (nonatomic) NSInteger maxScanDimension; +// display the built-in help browser. for use with custom overlays if +// you don't also want to create your own help view. only send this +// message when the reader is displayed. the argument will be passed +// to the onZBarHelp() javascript function. +- (void) showHelpWithReason: (NSString*) reason; + // direct scanner interface - scan UIImage and return something enumerable - (id ) scanImage: (CGImageRef) image; diff --git a/iphone/ZBarHelpController.m b/iphone/ZBarHelpController.m index 306a10e..7c54817 100644 --- a/iphone/ZBarHelpController.m +++ b/iphone/ZBarHelpController.m @@ -41,7 +41,7 @@ - (id) initWithReason: (NSString*) _reason { if(self = [super init]) { if(!_reason) - _reason = @"HELP"; + _reason = @"INFO"; reason = [_reason retain]; } return(self); diff --git a/iphone/ZBarReaderController.m b/iphone/ZBarReaderController.m index aa480ec..51bdda2 100644 --- a/iphone/ZBarReaderController.m +++ b/iphone/ZBarReaderController.m @@ -273,17 +273,11 @@ - (void) viewWillAppear: (BOOL) animated - (void) viewWillDisappear: (BOOL) animated { - if(help) { - [help.view removeFromSuperview]; - [help release]; - help = nil; - } sampling = NO; scanner.enableCache = NO; [super viewWillDisappear: animated]; } - - (BOOL) showsZBarControls { return(showsZBarControls); @@ -544,7 +538,7 @@ - (void) scanSequence: (UIImage*) image [self updateBox: sym]; } -- (void) initHelpWithReason: (NSString*) reason +- (void) showHelpWithReason: (NSString*) reason { if(help) { [help.view removeFromSuperview]; @@ -553,10 +547,14 @@ - (void) initHelpWithReason: (NSString*) reason help = [[ZBarHelpController alloc] initWithReason: reason]; help.delegate = self; -} -- (void) showHelpOverlay -{ + 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; @@ -570,8 +568,7 @@ - (void) showHelpOverlay - (void) info { - [self initHelpWithReason: @"HELP"]; - [self showHelpOverlay]; + [self showHelpWithReason: @"INFO"]; } - (void) imagePickerController: (UIImagePickerController*) picker @@ -580,19 +577,21 @@ - (void) imagePickerController: (UIImagePickerController*) picker UIImage *img = [info objectForKey: UIImagePickerControllerOriginalImage]; id results = nil; - if(!sampling) + 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 if(cameraMode == ZBarReaderControllerCameraModeSampling) { + else { results = [NSArray arrayWithObject: symbol]; [symbol release]; symbol = nil; } - else { - [self performSelector: @selector(scanSequence:) - withObject: [img retain] - afterDelay: 0.001]; - return; - } [self performSelector: @selector(reenable) withObject: nil @@ -614,14 +613,8 @@ - (void) imagePickerController: (UIImagePickerController*) picker BOOL camera = (self.sourceType == UIImagePickerControllerSourceTypeCamera); BOOL retry = !camera || (hasOverlay && ![self showsCameraControls]); - if(showsHelpOnFail && retry) { - [self initHelpWithReason: @"FAIL"]; - if(camera) - [self showHelpOverlay]; - else - [self presentModalViewController: help - animated: YES]; - } + if(showsHelpOnFail && retry) + [self showHelpWithReason: @"FAIL"]; SEL cb = @selector(readerControllerDidFailToRead:withRetry:); if([readerDelegate respondsToSelector: cb]) diff --git a/iphone/res/zbar-help.html b/iphone/res/zbar-help.html index 0ec90f1..a5d17b3 100644 --- a/iphone/res/zbar-help.html +++ b/iphone/res/zbar-help.html @@ -73,7 +73,7 @@

Hold Still

function onZBarHelp(argv) { var title; switch(argv.reason) { -case "HELP": break; +case "INFO": break; case "FAIL": title = "No Barcode Detected"; break; } if(title) document.getElementById('title').textContent = title; From 0195c362ad0bb9a3a6aec593e908217dae2a7a3b Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 12 Mar 2010 12:27:59 -0500 Subject: [PATCH 188/328] cleanup decoder assertions and locking --- ChangeLog | 1 + test/barcodetest.py | 2 ++ zbar/config.c | 1 - zbar/decoder.c | 43 ++++++++++++++++++++-------------------- zbar/decoder.h | 18 ++++++++++++++--- zbar/decoder/code128.c | 9 ++++----- zbar/decoder/code39.c | 13 ++++++------ zbar/decoder/ean.c | 4 ++-- zbar/decoder/i25.c | 10 +++++----- zbar/decoder/pdf417.c | 14 ++++++------- zbar/decoder/qr_finder.c | 2 +- 11 files changed, 66 insertions(+), 51 deletions(-) diff --git a/ChangeLog b/ChangeLog index 763b526..a61edff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * cleanup decoder assertions and locking * cleanup and expose iphone help display API * fixes to new iphone help display * migrate iphone help display to integrated web page (NB resource updates!) diff --git a/test/barcodetest.py b/test/barcodetest.py index 15400da..47406f4 100755 --- a/test/barcodetest.py +++ b/test/barcodetest.py @@ -124,6 +124,8 @@ def run_zbarimg(images): assert rc in (0, 4), \ 'zbarimg returned error status (%d)\n' % rc + err + assert not err, err + result = ET.XML(xml) assert result.tag == ET.QName(BC, 'barcodes') return result diff --git a/zbar/config.c b/zbar/config.c index f8b4f00..92b78e5 100644 --- a/zbar/config.c +++ b/zbar/config.c @@ -25,7 +25,6 @@ #include /* strtol */ #include /* strchr, strncmp, strlen */ #include -#include #include diff --git a/zbar/decoder.c b/zbar/decoder.c index f1a0c9c..066d793 100644 --- a/zbar/decoder.c +++ b/zbar/decoder.c @@ -27,7 +27,6 @@ #include /* memset, strlen */ #include -#include "decoder.h" #if defined(DEBUG_DECODER) || defined(DEBUG_EAN) || \ defined(DEBUG_CODE39) || defined(DEBUG_I25) || \ @@ -36,6 +35,7 @@ # define DEBUG_LEVEL 1 #endif #include "debug.h" +#include "decoder.h" zbar_decoder_t *zbar_decoder_create () { @@ -186,47 +186,48 @@ zbar_symbol_type_t zbar_decode_width (zbar_decoder_t *dcode, dprintf(1, " decode[%x]: w=%d (%g)\n", dcode->idx, w, (w / 32.)); /* each decoder processes width stream in parallel */ - zbar_symbol_type_t sym = dcode->type = ZBAR_NONE; + zbar_symbol_type_t tmp, sym = ZBAR_NONE; #ifdef ENABLE_EAN if((dcode->ean.enable) && - (sym = _zbar_decode_ean(dcode))) - dcode->type = sym; + (tmp = _zbar_decode_ean(dcode))) + sym = tmp; +#endif +#ifdef ENABLE_QRCODE + if(TEST_CFG(dcode->qrf.config, ZBAR_CFG_ENABLE) && + (tmp = _zbar_find_qr(dcode)) > ZBAR_PARTIAL) + sym = tmp; #endif #ifdef ENABLE_CODE39 if(TEST_CFG(dcode->code39.config, ZBAR_CFG_ENABLE) && - (sym = _zbar_decode_code39(dcode)) > ZBAR_PARTIAL) - dcode->type = sym; + (tmp = _zbar_decode_code39(dcode)) > ZBAR_PARTIAL) + sym = tmp; #endif #ifdef ENABLE_CODE128 if(TEST_CFG(dcode->code128.config, ZBAR_CFG_ENABLE) && - (sym = _zbar_decode_code128(dcode)) > ZBAR_PARTIAL) - dcode->type = sym; + (tmp = _zbar_decode_code128(dcode)) > ZBAR_PARTIAL) + sym = tmp; #endif #ifdef ENABLE_I25 if(TEST_CFG(dcode->i25.config, ZBAR_CFG_ENABLE) && - (sym = _zbar_decode_i25(dcode)) > ZBAR_PARTIAL) - dcode->type = sym; + (tmp = _zbar_decode_i25(dcode)) > ZBAR_PARTIAL) + sym = tmp; #endif #ifdef ENABLE_PDF417 if(TEST_CFG(dcode->pdf417.config, ZBAR_CFG_ENABLE) && - (sym = _zbar_decode_pdf417(dcode)) > ZBAR_PARTIAL) - dcode->type = sym; -#endif -#ifdef ENABLE_QRCODE - if(TEST_CFG(dcode->qrf.config, ZBAR_CFG_ENABLE) && - (sym = _zbar_find_qr(dcode)) > ZBAR_PARTIAL) - dcode->type = sym; + (tmp = _zbar_decode_pdf417(dcode)) > ZBAR_PARTIAL) + sym = tmp; #endif dcode->idx++; - if(dcode->type) { + dcode->type = sym; + if(sym) { + if(dcode->lock && sym > ZBAR_PARTIAL && sym != ZBAR_QRCODE) + release_lock(dcode, sym); if(dcode->handler) dcode->handler(dcode); - if(dcode->lock && dcode->type > ZBAR_PARTIAL) - dcode->lock = 0; } - return(dcode->type); + return(sym); } static inline int decoder_set_config_bool (zbar_decoder_t *dcode, diff --git a/zbar/decoder.h b/zbar/decoder.h index c5132f9..2022dce 100644 --- a/zbar/decoder.h +++ b/zbar/decoder.h @@ -169,15 +169,27 @@ static inline int decode_e (unsigned e, } /* acquire shared state lock */ -static inline char get_lock (zbar_decoder_t *dcode, - zbar_symbol_type_t req) +static inline char acquire_lock (zbar_decoder_t *dcode, + zbar_symbol_type_t req) { - if(dcode->lock) + if(dcode->lock) { + dprintf(2, " [locked %d]\n", dcode->lock); return(1); + } dcode->lock = req; return(0); } +/* check and release shared state lock */ +static inline char release_lock (zbar_decoder_t *dcode, + zbar_symbol_type_t req) +{ + zassert(dcode->lock == req, 1, "lock=%d req=%d\n", + dcode->lock, req); + dcode->lock = 0; + return(0); +} + /* ensure output buffer has sufficient allocation for request */ static inline char size_buf (zbar_decoder_t *dcode, unsigned len) diff --git a/zbar/decoder/code128.c b/zbar/decoder/code128.c index b505f3a..d79bbad 100644 --- a/zbar/decoder/code128.c +++ b/zbar/decoder/code128.c @@ -25,12 +25,12 @@ #include /* memmove */ #include -#include "decoder.h" #ifdef DEBUG_CODE128 # define DEBUG_LEVEL (DEBUG_CODE128) #endif #include "debug.h" +#include "decoder.h" #define NUM_CHARS 108 /* total number of character codes */ @@ -457,8 +457,7 @@ zbar_symbol_type_t _zbar_decode_code128 (zbar_decoder_t *dcode) return(0); } /* lock shared resources */ - if(get_lock(dcode, ZBAR_CODE128)) { - dprintf(2, " [locked %d]\n", dcode->lock); + if(acquire_lock(dcode, ZBAR_CODE128)) { dcode128->character = -1; return(0); } @@ -477,7 +476,7 @@ zbar_symbol_type_t _zbar_decode_code128 (zbar_decoder_t *dcode) ((dcode128->character >= BUFFER_MIN) && size_buf(dcode, dcode128->character + 1))) { dprintf(1, (c < 0) ? " [aborted]\n" : " [overflow]\n"); - dcode->lock = 0; + release_lock(dcode, ZBAR_CODE128); dcode128->character = -1; return(0); } @@ -507,7 +506,7 @@ zbar_symbol_type_t _zbar_decode_code128 (zbar_decoder_t *dcode) dprintf(2, " [valid end]\n"); dcode128->character = -1; if(!sym) - dcode->lock = 0; + release_lock(dcode, ZBAR_CODE128); return(sym); } diff --git a/zbar/decoder/code39.c b/zbar/decoder/code39.c index 4a53019..0d8a133 100644 --- a/zbar/decoder/code39.c +++ b/zbar/decoder/code39.c @@ -25,12 +25,12 @@ #include /* memmove */ #include -#include "decoder.h" #ifdef DEBUG_CODE39 # define DEBUG_LEVEL (DEBUG_CODE39) #endif #include "debug.h" +#include "decoder.h" #define NUM_CHARS (0x2c) @@ -284,14 +284,15 @@ zbar_symbol_type_t _zbar_decode_code39 (zbar_decoder_t *dcode) } dcode39->character = -1; if(!sym) - dcode->lock = 0; + release_lock(dcode, ZBAR_CODE39); return(sym); } if(space > dcode39->width / 2) { /* inter-character space check failure */ - dcode->lock = 0; - dcode39->character = -1; dprintf(2, " ics>%d [invalid ics]", dcode39->width); + if(dcode39->character) + release_lock(dcode, ZBAR_CODE39); + dcode39->character = -1; } dcode39->element = 0; dprintf(2, "\n"); @@ -302,7 +303,7 @@ zbar_symbol_type_t _zbar_decode_code39 (zbar_decoder_t *dcode) dprintf(2, " c=%d", c); /* lock shared resources */ - if(!dcode39->character && get_lock(dcode, ZBAR_CODE39)) { + if(!dcode39->character && acquire_lock(dcode, ZBAR_CODE39)) { dcode39->character = -1; dprintf(1, " [locked %d]\n", dcode->lock); return(ZBAR_PARTIAL); @@ -312,7 +313,7 @@ zbar_symbol_type_t _zbar_decode_code39 (zbar_decoder_t *dcode) ((dcode39->character >= BUFFER_MIN) && size_buf(dcode, dcode39->character + 1))) { dprintf(1, (c < 0) ? " [aborted]\n" : " [overflow]\n"); - dcode->lock = 0; + release_lock(dcode, ZBAR_CODE39); dcode39->character = -1; return(ZBAR_NONE); } diff --git a/zbar/decoder/ean.c b/zbar/decoder/ean.c index 93d46bd..874bca7 100644 --- a/zbar/decoder/ean.c +++ b/zbar/decoder/ean.c @@ -23,12 +23,12 @@ #include #include -#include "decoder.h" #ifdef DEBUG_EAN # define DEBUG_LEVEL (DEBUG_EAN) #endif #include "debug.h" +#include "decoder.h" /* partial decode symbol location */ typedef enum symbol_partial_e { @@ -634,7 +634,7 @@ zbar_symbol_type_t _zbar_decode_ean (zbar_decoder_t *dcode) dcode->ean.pass[0].state = dcode->ean.pass[1].state = -1; dcode->ean.pass[2].state = dcode->ean.pass[3].state = -1; if(sym > ZBAR_PARTIAL) { - if(!get_lock(dcode, ZBAR_EAN13)) + if(!acquire_lock(dcode, sym)) postprocess(dcode, sym); else { dprintf(1, " [locked %d]", dcode->lock); diff --git a/zbar/decoder/i25.c b/zbar/decoder/i25.c index 75a0a28..0cb5148 100644 --- a/zbar/decoder/i25.c +++ b/zbar/decoder/i25.c @@ -25,12 +25,12 @@ #include /* memmove */ #include -#include "decoder.h" #ifdef DEBUG_I25 # define DEBUG_LEVEL (DEBUG_I25) #endif #include "debug.h" +#include "decoder.h" static inline unsigned char i25_decode1 (unsigned char enc, unsigned e, @@ -162,7 +162,7 @@ static inline signed char i25_decode_end (zbar_decoder_t *dcode) (CFG(*dcode25, ZBAR_CFG_MAX_LEN) > 0 && dcode25->character > CFG(*dcode25, ZBAR_CFG_MAX_LEN))) { dprintf(2, " [invalid len]\n"); - dcode->lock = 0; + release_lock(dcode, ZBAR_I25); dcode25->character = -1; return(ZBAR_NONE); } @@ -199,7 +199,7 @@ zbar_symbol_type_t _zbar_decode_i25 (zbar_decoder_t *dcode) dcode25->character, dcode25->element); /* lock shared resources */ - if(!dcode25->character && get_lock(dcode, ZBAR_I25)) { + if(!dcode25->character && acquire_lock(dcode, ZBAR_I25)) { dcode25->character = -1; dprintf(2, " [locked %d]\n", dcode->lock); return(ZBAR_PARTIAL); @@ -212,7 +212,7 @@ zbar_symbol_type_t _zbar_decode_i25 (zbar_decoder_t *dcode) ((dcode25->character >= BUFFER_MIN) && size_buf(dcode, dcode25->character + 2))) { dprintf(2, (c > 9) ? " [aborted]\n" : " [overflow]\n"); - dcode->lock = 0; + release_lock(dcode, ZBAR_I25); dcode25->character = -1; return(ZBAR_NONE); } @@ -222,7 +222,7 @@ zbar_symbol_type_t _zbar_decode_i25 (zbar_decoder_t *dcode) dprintf(2, " c=%x", c); if(c > 9) { dprintf(2, " [aborted]\n"); - dcode->lock = 0; + release_lock(dcode, ZBAR_I25); dcode25->character = -1; return(ZBAR_NONE); } diff --git a/zbar/decoder/pdf417.c b/zbar/decoder/pdf417.c index 167a2f3..e2c4161 100644 --- a/zbar/decoder/pdf417.c +++ b/zbar/decoder/pdf417.c @@ -24,14 +24,14 @@ #include #include -#include "decoder.h" - -#include "pdf417_hash.h" #ifdef DEBUG_PDF417 # define DEBUG_LEVEL (DEBUG_PDF417) #endif #include "debug.h" +#include "decoder.h" + +#include "pdf417_hash.h" #define PDF417_STOP 0xbff @@ -152,7 +152,7 @@ static inline signed char pdf417_decode_start(zbar_decoder_t *dcode) } /* lock shared resources */ - if(get_lock(dcode, ZBAR_PDF417)) { + if(acquire_lock(dcode, ZBAR_PDF417)) { dprintf(2, " [locked %d]\n", dcode->lock); return(0); } @@ -190,7 +190,7 @@ zbar_symbol_type_t _zbar_decode_pdf417 (zbar_decoder_t *dcode) if(get_color(dcode) != dcode417->direction) { int c = dcode417->character; - dcode->lock = 0; + release_lock(dcode, ZBAR_PDF417); dcode417->character = -1; zassert(get_color(dcode) == dcode417->direction, ZBAR_NONE, "color=%x dir=%x char=%d elem=0 %s\n", @@ -203,7 +203,7 @@ zbar_symbol_type_t _zbar_decode_pdf417 (zbar_decoder_t *dcode) ((dcode417->character >= BUFFER_MIN) && size_buf(dcode, dcode417->character + 1))) { dprintf(1, (c < 0) ? " [aborted]\n" : " [overflow]\n"); - dcode->lock = 0; + release_lock(dcode, ZBAR_PDF417); dcode417->character = -1; return(0); } @@ -214,7 +214,7 @@ zbar_symbol_type_t _zbar_decode_pdf417 (zbar_decoder_t *dcode) dprintf(1, " [valid stop]"); /* FIXME check trailing bar and qz */ dcode->direction = 1 - 2 * dcode417->direction; - dcode->lock = 0; + release_lock(dcode, ZBAR_PDF417); dcode417->character = -1; } diff --git a/zbar/decoder/qr_finder.c b/zbar/decoder/qr_finder.c index 8caeec7..9f7691f 100644 --- a/zbar/decoder/qr_finder.c +++ b/zbar/decoder/qr_finder.c @@ -25,12 +25,12 @@ #include #include -#include "decoder.h" #ifdef DEBUG_QR_FINDER # define DEBUG_LEVEL (DEBUG_QR_FINDER) #endif #include "debug.h" +#include "decoder.h" /* at this point lengths are all decode unit offsets from the decode edge * NB owned by finder From d54d7681aeae906fe854b3c292b03f2613854497 Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 13 Mar 2010 09:54:20 -0500 Subject: [PATCH 189/328] fix QR Code missing from man pages (bug #2969857) --- COPYING | 2 +- ChangeLog | 3 ++- doc/api/footer.html | 2 +- doc/manual.xml | 1 + doc/ref/commonoptions.xml | 3 ++- doc/ref/zbarcam.xml | 6 +++--- doc/ref/zbarimg.xml | 6 +++--- include/zbar/ZBarReaderController.h | 2 +- iphone/ZBarHelpController.h | 2 +- iphone/ZBarHelpController.m | 2 +- iphone/ZBarReaderController.m | 2 +- iphone/res/back.svg | 2 +- iphone/res/shakyhand.svg | 2 +- perl/README | 2 +- perl/ZBar/Image.pod | 2 +- perl/ZBar/ImageScanner.pod | 2 +- perl/ZBar/Processor.pod | 2 +- perl/ZBar/Symbol.pod | 2 +- python/README | 2 +- zbar/config.c | 2 +- zbarcam/zbarcam.rc | 2 +- zbarimg/zbarimg.rc | 2 +- 22 files changed, 28 insertions(+), 25 deletions(-) diff --git a/COPYING b/COPYING index 6a9d036..d0b0654 100644 --- a/COPYING +++ b/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-2010 Jeff Brown The QR Code reader is Copyright (C) 1999-2009 Timothy B. Terriberry diff --git a/ChangeLog b/ChangeLog index a61edff..d0b2b19 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ current: - * cleanup decoder assertions and locking + * fix QR Code missing from man pages (bug #2969857) + * cleanup decoder assertions and locking (bug #2966916) * cleanup and expose iphone help display API * fixes to new iphone help display * migrate iphone help display to integrated web page (NB resource updates!) diff --git a/doc/api/footer.html b/doc/api/footer.html index d9529a3..1e506c4 100644 --- a/doc/api/footer.html +++ b/doc/api/footer.html @@ -9,7 +9,7 @@
spadix@users.sourceforge.net
-

Copyright 2008-2009 (c) Jeff Brown - All Rights Reserved.

+

Copyright 2008-2010 (c) Jeff Brown - All Rights Reserved.

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.

diff --git a/doc/manual.xml b/doc/manual.xml index 6a000d3..98b185f 100644 --- a/doc/manual.xml +++ b/doc/manual.xml @@ -29,6 +29,7 @@ 2007 2008 2009 + 2010 Jeff Brown
All Rights Reserved diff --git a/doc/ref/commonoptions.xml b/doc/ref/commonoptions.xml index 8ea3ea1..8b77bb6 100644 --- a/doc/ref/commonoptions.xml +++ b/doc/ref/commonoptions.xml @@ -48,7 +48,8 @@ , , , , , , - or the special value . + , + or the special value . If symbology is omitted or , the config will be set for all diff --git a/doc/ref/zbarcam.xml b/doc/ref/zbarcam.xml index 4121a98..f84c81b 100644 --- a/doc/ref/zbarcam.xml +++ b/doc/ref/zbarcam.xml @@ -60,9 +60,9 @@ /dev/video0 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. + UPC and ISBN subsets), EAN-8, Code 128, Code 39, Interleaved 2 of + 5 and QR Code symbologies. The specific type of each detected + symbol is printed with the decoded data. diff --git a/doc/ref/zbarimg.xml b/doc/ref/zbarimg.xml index 520ddd6..8fd0f72 100644 --- a/doc/ref/zbarimg.xml +++ b/doc/ref/zbarimg.xml @@ -59,9 +59,9 @@ displayed to the screen. 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. + UPC and ISBN subsets), EAN-8, Code 128, Code 39, Interleaved 2 of + 5 and QR Code symbologies. The specific type of each detected + symbol is printed with the decoded data. Note that "image" diff --git a/include/zbar/ZBarReaderController.h b/include/zbar/ZBarReaderController.h index 9dfacc5..855a676 100644 --- a/include/zbar/ZBarReaderController.h +++ b/include/zbar/ZBarReaderController.h @@ -1,5 +1,5 @@ //------------------------------------------------------------------------ -// Copyright 2009 (c) Jeff Brown +// Copyright 2009-2010 (c) Jeff Brown // // This file is part of the ZBar Bar Code Reader. // diff --git a/iphone/ZBarHelpController.h b/iphone/ZBarHelpController.h index 051b14c..dd9d683 100644 --- a/iphone/ZBarHelpController.h +++ b/iphone/ZBarHelpController.h @@ -1,5 +1,5 @@ //------------------------------------------------------------------------ -// Copyright 2009 (c) Jeff Brown +// Copyright 2009-2010 (c) Jeff Brown // // This file is part of the ZBar Bar Code Reader. // diff --git a/iphone/ZBarHelpController.m b/iphone/ZBarHelpController.m index 7c54817..717e6c2 100644 --- a/iphone/ZBarHelpController.m +++ b/iphone/ZBarHelpController.m @@ -1,5 +1,5 @@ //------------------------------------------------------------------------ -// Copyright 2009 (c) Jeff Brown +// Copyright 2009-2010 (c) Jeff Brown // // This file is part of the ZBar Bar Code Reader. // diff --git a/iphone/ZBarReaderController.m b/iphone/ZBarReaderController.m index 51bdda2..4e26a59 100644 --- a/iphone/ZBarReaderController.m +++ b/iphone/ZBarReaderController.m @@ -1,5 +1,5 @@ //------------------------------------------------------------------------ -// Copyright 2009 (c) Jeff Brown +// Copyright 2009-2010 (c) Jeff Brown // // This file is part of the ZBar Bar Code Reader. // diff --git a/iphone/res/back.svg b/iphone/res/back.svg index 6b64ea9..64f1aba 100644 --- a/iphone/res/back.svg +++ b/iphone/res/back.svg @@ -3,7 +3,7 @@ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> diff --git a/iphone/res/shakyhand.svg b/iphone/res/shakyhand.svg index 66a2eec..2e3c594 100644 --- a/iphone/res/shakyhand.svg +++ b/iphone/res/shakyhand.svg @@ -3,7 +3,7 @@ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> diff --git a/perl/README b/perl/README index e4b1811..f6c4e82 100644 --- a/perl/README +++ b/perl/README @@ -35,4 +35,4 @@ COPYRIGHT AND LICENCE Licensed under the GNU Lesser General Public License, version 2.1. http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt -Copyright 2008-2009 (c) Jeff Brown +Copyright 2008-2010 (c) Jeff Brown diff --git a/perl/ZBar/Image.pod b/perl/ZBar/Image.pod index 6b3fc31..92ed7e7 100644 --- a/perl/ZBar/Image.pod +++ b/perl/ZBar/Image.pod @@ -132,7 +132,7 @@ Jeff Brown, Espadix@users.sourceforge.netE =head1 COPYRIGHT AND LICENSE -Copyright 2008-2009 (c) Jeff Brown Espadix@users.sourceforge.netE +Copyright 2008-2010 (c) Jeff Brown Espadix@users.sourceforge.netE 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 diff --git a/perl/ZBar/ImageScanner.pod b/perl/ZBar/ImageScanner.pod index 94f32e3..14600ed 100644 --- a/perl/ZBar/ImageScanner.pod +++ b/perl/ZBar/ImageScanner.pod @@ -89,7 +89,7 @@ Jeff Brown, Espadix@users.sourceforge.netE =head1 COPYRIGHT AND LICENSE -Copyright 2008-2009 (c) Jeff Brown Espadix@users.sourceforge.netE +Copyright 2008-2010 (c) Jeff Brown Espadix@users.sourceforge.netE 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 diff --git a/perl/ZBar/Processor.pod b/perl/ZBar/Processor.pod index 55c8783..94cbb44 100644 --- a/perl/ZBar/Processor.pod +++ b/perl/ZBar/Processor.pod @@ -137,7 +137,7 @@ Jeff Brown, Espadix@users.sourceforge.netE =head1 COPYRIGHT AND LICENSE -Copyright 2008-2009 (c) Jeff Brown Espadix@users.sourceforge.netE +Copyright 2008-2010 (c) Jeff Brown Espadix@users.sourceforge.netE 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 diff --git a/perl/ZBar/Symbol.pod b/perl/ZBar/Symbol.pod index e0f2188..7e37f5c 100644 --- a/perl/ZBar/Symbol.pod +++ b/perl/ZBar/Symbol.pod @@ -150,7 +150,7 @@ Jeff Brown, Espadix@users.sourceforge.netE =head1 COPYRIGHT AND LICENSE -Copyright 2008-2009 (c) Jeff Brown Espadix@users.sourceforge.netE +Copyright 2008-2010 (c) Jeff Brown Espadix@users.sourceforge.netE 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 diff --git a/python/README b/python/README index 881ae38..1d0f281 100644 --- a/python/README +++ b/python/README @@ -39,4 +39,4 @@ 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-2009 (c) Jeff Brown +Copyright 2008-2010 (c) Jeff Brown diff --git a/zbar/config.c b/zbar/config.c index 92b78e5..05e9ae8 100644 --- a/zbar/config.c +++ b/zbar/config.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2008-2009 (c) Jeff Brown + * Copyright 2008-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * diff --git a/zbarcam/zbarcam.rc b/zbarcam/zbarcam.rc index 3877915..89e5aff 100644 --- a/zbarcam/zbarcam.rc +++ b/zbarcam/zbarcam.rc @@ -19,7 +19,7 @@ VS_VERSION_INFO VERSIONINFO VALUE "FileDescription", "Scan bar codes from video devices" - VALUE "LegalCopyright", "Copyright 2007-2009 (c) Jeff Brown " + VALUE "LegalCopyright", "Copyright 2007-2010 (c) Jeff Brown " } } BLOCK "VarFileInfo" { diff --git a/zbarimg/zbarimg.rc b/zbarimg/zbarimg.rc index ba70033..cb9bbde 100644 --- a/zbarimg/zbarimg.rc +++ b/zbarimg/zbarimg.rc @@ -19,7 +19,7 @@ VS_VERSION_INFO VERSIONINFO VALUE "FileDescription", "Scan bar codes from image files" - VALUE "LegalCopyright", "Copyright 2007-2009 (c) Jeff Brown " + VALUE "LegalCopyright", "Copyright 2007-2010 (c) Jeff Brown " } } BLOCK "VarFileInfo" { From 69263591aaa61c67ece4d80e9a3abe7c945d7c77 Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 20 Mar 2010 18:48:39 -0400 Subject: [PATCH 190/328] adjust Python module README (add examples and note DLL in path) --- ChangeLog | 1 + python/README | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index d0b2b19..657b6a1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * 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) * cleanup and expose iphone help display API diff --git a/python/README b/python/README index 1d0f281..ba36228 100644 --- a/python/README +++ b/python/README @@ -28,10 +28,27 @@ from: * http://zbar.sourceforge.net/ +Windows users please note: the module *will NOT load* unless the ZBar +library DLL (currently libzbar-0.dll) is available in your PATH! + Examples -------- -TBD +To scan an image, wrap the raw image data in a ``zbar.Image`` and feed +it to a ``zbar.ImageScanner``:: + + import zbar + scanner = zbar.ImageScanner() + image = zbar.Image(width, height, 'Y800', raw_data) + scanner.scan(image) + for symbol in image: + print 'decoded', symbol.type, 'symbol', '"%s"' % symbol.data + +Complete, runnable examples may be found in the source distribution, +under the ``examples/`` directory. A couple of HOWTOs_ that cover +programming with the library may be found on the project wiki. + +.. _HOWTOs: http://sourceforge.net/apps/mediawiki/zbar/index.php?title=Category:HOWTOs Copyright and License --------------------- From 0369b1520120edee4302583ab0f9aebc84cae509 Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 7 Apr 2010 08:47:14 -0400 Subject: [PATCH 191/328] core library portability improvements - remove some unnecessary C99 syntax - add configure checks for errno - enhance C++ Symbol interface --- ChangeLog | 4 + configure.ac | 4 +- include/zbar/Symbol.h | 102 +++++++++++--- zbar/config.c | 19 ++- zbar/convert.c | 297 ++++++++++++++++++++++----------------- zbar/decoder.c | 12 +- zbar/decoder.h | 3 +- zbar/decoder/code128.c | 57 +++++--- zbar/decoder/ean.c | 52 ++++--- zbar/decoder/qr_finder.c | 10 +- zbar/error.c | 20 +-- zbar/error.h | 10 +- zbar/image.c | 37 +++-- zbar/img_scanner.c | 92 ++++++------ zbar/qrcode/qrdec.c | 7 +- zbar/qrcode/qrdectxt.c | 31 ++-- zbar/refcnt.h | 4 +- zbar/scanner.c | 40 +++--- zbar/symbol.c | 16 +-- zbar/timer.h | 40 ++++-- zbar/video.c | 31 ++-- zbar/window.c | 35 +++-- 22 files changed, 571 insertions(+), 352 deletions(-) diff --git a/ChangeLog b/ChangeLog index 657b6a1..02558ea 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,8 @@ current: + * 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) diff --git a/configure.ac b/configure.ac index 938b29e..60defca 100644 --- a/configure.ac +++ b/configure.ac @@ -443,8 +443,8 @@ 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/ioctl.h sys/time.h sys/times.h sys/ipc.h sys/shm.h sys/mman.h]) dnl types diff --git a/include/zbar/Symbol.h b/include/zbar/Symbol.h index 018eac5..afe26f1 100644 --- a/include/zbar/Symbol.h +++ b/include/zbar/Symbol.h @@ -64,6 +64,21 @@ class SymbolSet { 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 @@ class SymbolSet { return(_syms); } - int get_size () + int get_size () const { return((_syms) ? zbar_symbol_set_get_size(_syms) : 0); } @@ -112,9 +127,16 @@ class Symbol { /// 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); } }; @@ -135,7 +157,7 @@ class Symbol { _index = -1; } - /// constructor. + /// copy constructor. PointIterator (const PointIterator& iter) : _sym(iter._sym), _index(iter._index) @@ -149,6 +171,21 @@ class Symbol { _sym->ref(-1); } + /// assignment. + PointIterator& operator= (const PointIterator& iter) + { + iter._sym->ref(); + _sym->ref(-1); + _sym = iter._sym; + _index = iter._index; + } + + /// truth testing. + bool operator! () const + { + return(!_sym || _index < 0); + } + /// advance iterator to next Point. PointIterator& operator++ () { @@ -161,7 +198,9 @@ class Symbol { /// 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 +252,31 @@ class Symbol { 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); + } + + /// truth testing. + bool operator! () const + { + return(!_sym); + } + void ref (int delta = 1) const { if(_sym) @@ -327,9 +391,6 @@ class Symbol { } protected: - - friend class SymbolIterator; - /// (re)initialize Symbol from C symbol object. void init (const zbar_symbol_t *sym = NULL) { @@ -368,7 +429,7 @@ class SymbolIterator { 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. @@ -377,25 +438,32 @@ class SymbolIterator { 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; + } + + 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); } diff --git a/zbar/config.c b/zbar/config.c index 05e9ae8..5fbbfe7 100644 --- a/zbar/config.c +++ b/zbar/config.c @@ -24,7 +24,9 @@ #include #include /* strtol */ #include /* strchr, strncmp, strlen */ -#include +#ifdef HAVE_ERRNO_H +# include +#endif #include @@ -33,10 +35,13 @@ int zbar_parse_config (const char *cfgstr, zbar_config_t *cfg, int *val) { + const char *dot, *eq; + int len; + char negate; if(!cfgstr) return(1); - const char *dot = strchr(cfgstr, '.'); + dot = strchr(cfgstr, '.'); if(dot) { int len = dot - cfgstr; if(!len || (len == 1 && !strncmp(cfgstr, "*", len))) @@ -89,13 +94,13 @@ int zbar_parse_config (const char *cfgstr, else *sym = 0; - int len = strlen(cfgstr); - const char *eq = strchr(cfgstr, '='); + len = strlen(cfgstr); + eq = strchr(cfgstr, '='); if(eq) len = eq - cfgstr; else *val = 1; /* handle this here so we can override later */ - char negate = 0; + negate = 0; if(len > 3 && !strncmp(cfgstr, "no-", 3)) { negate = 1; @@ -135,10 +140,14 @@ int zbar_parse_config (const char *cfgstr, return(1); if(eq) { +#ifdef HAVE_ERRNO_H errno = 0; +#endif *val = strtol(eq + 1, NULL, 0); +#ifdef HAVE_ERRNO_H if(errno) return(1); +#endif } if(negate) *val = !*val; diff --git a/zbar/convert.c b/zbar/convert.c index 1a90381..b3c4832 100644 --- a/zbar/convert.c +++ b/zbar/convert.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown + * Copyright 2007-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -236,12 +236,13 @@ static inline void uv_round (zbar_image_t *img, static inline void uv_roundup (zbar_image_t *img, const zbar_format_def_t *fmt) { + unsigned xmask, ymask; if(fmt->group == ZBAR_FMT_GRAY) return; - unsigned xmask = (1 << fmt->p.yuv.xsub2) - 1; + xmask = (1 << fmt->p.yuv.xsub2) - 1; if(img->width & xmask) img->width = (img->width + xmask) & ~xmask; - unsigned ymask = (1 << fmt->p.yuv.ysub2) - 1; + ymask = (1 << fmt->p.yuv.ysub2) - 1; if(img->height & ymask) img->height = (img->height + ymask) & ~ymask; } @@ -306,16 +307,18 @@ static inline void convert_y_resize (zbar_image_t *dst, const zbar_format_def_t *srcfmt, size_t n) { + uint8_t *psrc, *pdst; + unsigned width, height, xpad, y; + if(dst->width == src->width && dst->height == src->height) { memcpy((void*)dst->data, src->data, n); return; } - uint8_t *psrc = (void*)src->data; - uint8_t *pdst = (void*)dst->data; - unsigned width = (dst->width > src->width) ? src->width : dst->width; - unsigned xpad = (dst->width > src->width) ? dst->width - src->width : 0; - unsigned height = (dst->height > src->height) ? src->height : dst->height; - unsigned y; + psrc = (void*)src->data; + pdst = (void*)dst->data; + width = (dst->width > src->width) ? src->width : dst->width; + xpad = (dst->width > src->width) ? dst->width - src->width : 0; + height = (dst->height > src->height) ? src->height : dst->height; for(y = 0; y < height; y++) { memcpy(pdst, psrc, width); pdst += width; @@ -344,10 +347,10 @@ static void convert_copy (zbar_image_t *dst, { if(src->width == dst->width && src->height == dst->height) { + zbar_image_t *s = (zbar_image_t*)src; dst->data = src->data; dst->datalen = src->datalen; dst->cleanup = cleanup_ref; - zbar_image_t *s = (zbar_image_t*)src; dst->next = s; _zbar_image_refcnt(s, 1); } @@ -362,9 +365,10 @@ static void convert_uvp_append (zbar_image_t *dst, const zbar_image_t *src, const zbar_format_def_t *srcfmt) { + unsigned long n; uv_roundup(dst, dstfmt); dst->datalen = uvp_size(dst, dstfmt) * 2; - unsigned long n = dst->width * dst->height; + n = dst->width * dst->height; dst->datalen += n; assert(src->datalen >= src->width * src->height); zprintf(24, "dst=%dx%d (%lx) %lx src=%dx%d %lx\n", @@ -373,7 +377,7 @@ static void convert_uvp_append (zbar_image_t *dst, dst->data = malloc(dst->datalen); if(!dst->data) return; convert_y_resize(dst, dstfmt, src, srcfmt, n); - memset((void*)dst->data + n, 0x80, dst->datalen - n); + memset((uint8_t*)dst->data + n, 0x80, dst->datalen - n); } /* interleave YUV planes into packed YUV */ @@ -382,32 +386,35 @@ static void convert_yuv_pack (zbar_image_t *dst, const zbar_image_t *src, const zbar_format_def_t *srcfmt) { + unsigned long srcm, srcn; + uint8_t flags, *srcy, *dstp; + const uint8_t *srcu, *srcv; + unsigned srcl, xmask, ymask, x, y; + uint8_t y0 = 0, y1 = 0, u = 0x80, v = 0x80; + uv_roundup(dst, dstfmt); dst->datalen = dst->width * dst->height + uvp_size(dst, dstfmt) * 2; dst->data = malloc(dst->datalen); if(!dst->data) return; - uint8_t *dstp = (void*)dst->data; + dstp = (void*)dst->data; - unsigned long srcm = uvp_size(src, srcfmt); - unsigned long srcn = src->width * src->height; + srcm = uvp_size(src, srcfmt); + srcn = src->width * src->height; assert(src->datalen >= srcn + 2 * srcn); - uint8_t flags = dstfmt->p.yuv.packorder ^ srcfmt->p.yuv.packorder; - uint8_t *srcy = (void*)src->data; - const uint8_t *srcu, *srcv; + flags = dstfmt->p.yuv.packorder ^ srcfmt->p.yuv.packorder; + srcy = (void*)src->data; if(flags & 1) { - srcv = src->data + srcn; + srcv = (uint8_t*)src->data + srcn; srcu = srcv + srcm; } else { - srcu = src->data + srcn; + srcu = (uint8_t*)src->data + srcn; srcv = srcu + srcm; } flags = dstfmt->p.yuv.packorder & 2; - unsigned srcl = src->width >> srcfmt->p.yuv.xsub2; - unsigned xmask = (1 << srcfmt->p.yuv.xsub2) - 1; - unsigned ymask = (1 << srcfmt->p.yuv.ysub2) - 1; - unsigned x, y; - uint8_t y0 = 0, y1 = 0, u = 0x80, v = 0x80; + srcl = src->width >> srcfmt->p.yuv.xsub2; + xmask = (1 << srcfmt->p.yuv.xsub2) - 1; + ymask = (1 << srcfmt->p.yuv.ysub2) - 1; for(y = 0; y < dst->height; y++) { if(y >= src->height) { srcy -= src->width; @@ -448,25 +455,29 @@ static void convert_yuv_unpack (zbar_image_t *dst, const zbar_image_t *src, const zbar_format_def_t *srcfmt) { + unsigned long dstn, dstm2; + uint8_t *dsty, flags; + const uint8_t *srcp; + unsigned srcl, x, y; + uint8_t y0 = 0, y1 = 0; + uv_roundup(dst, dstfmt); - unsigned long dstn = dst->width * dst->height; - unsigned long dstm2 = uvp_size(dst, dstfmt) * 2; + dstn = dst->width * dst->height; + dstm2 = uvp_size(dst, dstfmt) * 2; dst->datalen = dstn + dstm2; dst->data = malloc(dst->datalen); if(!dst->data) return; if(dstm2) - memset((void*)dst->data + dstn, 0x80, dstm2); - uint8_t *dsty = (void*)dst->data; + memset((uint8_t*)dst->data + dstn, 0x80, dstm2); + dsty = (uint8_t*)dst->data; - uint8_t flags = srcfmt->p.yuv.packorder ^ dstfmt->p.yuv.packorder; + flags = srcfmt->p.yuv.packorder ^ dstfmt->p.yuv.packorder; flags &= 2; - const uint8_t *srcp = src->data; + srcp = src->data; if(flags) srcp++; - unsigned srcl = src->width + (src->width >> srcfmt->p.yuv.xsub2); - unsigned x, y; - uint8_t y0 = 0, y1 = 0; + srcl = src->width + (src->width >> srcfmt->p.yuv.xsub2); for(y = 0; y < dst->height; y++) { if(y >= src->height) srcp -= srcl; @@ -491,15 +502,16 @@ static void convert_uvp_resample (zbar_image_t *dst, const zbar_image_t *src, const zbar_format_def_t *srcfmt) { + unsigned long dstn, dstm2; uv_roundup(dst, dstfmt); - unsigned long dstn = dst->width * dst->height; - unsigned long dstm2 = uvp_size(dst, dstfmt) * 2; + dstn = dst->width * dst->height; + dstm2 = uvp_size(dst, dstfmt) * 2; dst->datalen = dstn + dstm2; dst->data = malloc(dst->datalen); if(!dst->data) return; convert_y_resize(dst, dstfmt, src, srcfmt, dstn); if(dstm2) - memset((void*)dst->data + dstn, 0x80, dstm2); + memset((uint8_t*)dst->data + dstn, 0x80, dstm2); } /* rearrange interleaved UV componets */ @@ -508,19 +520,23 @@ static void convert_uv_resample (zbar_image_t *dst, const zbar_image_t *src, const zbar_format_def_t *srcfmt) { + unsigned long dstn; + uint8_t *dstp, flags; + const uint8_t *srcp; + unsigned srcl, x, y; + uint8_t y0 = 0, y1 = 0, u = 0x80, v = 0x80; + uv_roundup(dst, dstfmt); - unsigned long dstn = dst->width * dst->height; + dstn = dst->width * dst->height; dst->datalen = dstn + uvp_size(dst, dstfmt) * 2; dst->data = malloc(dst->datalen); if(!dst->data) return; - uint8_t *dstp = (void*)dst->data; + dstp = (void*)dst->data; - uint8_t flags = (srcfmt->p.yuv.packorder ^ dstfmt->p.yuv.packorder) & 1; - const uint8_t *srcp = src->data; + flags = (srcfmt->p.yuv.packorder ^ dstfmt->p.yuv.packorder) & 1; + srcp = src->data; - unsigned srcl = src->width + (src->width >> srcfmt->p.yuv.xsub2); - unsigned x, y; - uint8_t y0 = 0, y1 = 0, u = 0x80, v = 0x80; + srcl = src->width + (src->width >> srcfmt->p.yuv.xsub2); for(y = 0; y < dst->height; y++) { if(y >= src->height) srcp -= srcl; @@ -560,25 +576,29 @@ static void convert_yuvp_to_rgb (zbar_image_t *dst, const zbar_image_t *src, const zbar_format_def_t *srcfmt) { + uint8_t *dstp, *srcy; + int drbits, drbit0, dgbits, dgbit0, dbbits, dbbit0; + unsigned long srcm, srcn; + unsigned x, y; + uint32_t p = 0; + dst->datalen = dst->width * dst->height * dstfmt->p.rgb.bpp; dst->data = malloc(dst->datalen); if(!dst->data) return; - uint8_t *dstp = (void*)dst->data; + dstp = (void*)dst->data; - int drbits = RGB_SIZE(dstfmt->p.rgb.red); - int drbit0 = RGB_OFFSET(dstfmt->p.rgb.red); - int dgbits = RGB_SIZE(dstfmt->p.rgb.green); - int dgbit0 = RGB_OFFSET(dstfmt->p.rgb.green); - int dbbits = RGB_SIZE(dstfmt->p.rgb.blue); - int dbbit0 = RGB_OFFSET(dstfmt->p.rgb.blue); + drbits = RGB_SIZE(dstfmt->p.rgb.red); + drbit0 = RGB_OFFSET(dstfmt->p.rgb.red); + dgbits = RGB_SIZE(dstfmt->p.rgb.green); + dgbit0 = RGB_OFFSET(dstfmt->p.rgb.green); + dbbits = RGB_SIZE(dstfmt->p.rgb.blue); + dbbit0 = RGB_OFFSET(dstfmt->p.rgb.blue); - unsigned long srcm = uvp_size(src, srcfmt); - unsigned long srcn = src->width * src->height; + srcm = uvp_size(src, srcfmt); + srcn = src->width * src->height; assert(src->datalen >= srcn + 2 * srcm); - uint8_t *srcy = (void*)src->data; + srcy = (void*)src->data; - unsigned x, y; - uint32_t p = 0; for(y = 0; y < dst->height; y++) { if(y >= src->height) srcy -= src->width; @@ -606,29 +626,34 @@ static void convert_rgb_to_yuvp (zbar_image_t *dst, const zbar_image_t *src, const zbar_format_def_t *srcfmt) { + unsigned long dstn, dstm2; + uint8_t *dsty; + const uint8_t *srcp; + int rbits, rbit0, gbits, gbit0, bbits, bbit0; + unsigned srcl, x, y; + uint16_t y0 = 0; + uv_roundup(dst, dstfmt); - unsigned long dstn = dst->width * dst->height; - unsigned long dstm2 = uvp_size(dst, dstfmt) * 2; + dstn = dst->width * dst->height; + dstm2 = uvp_size(dst, dstfmt) * 2; dst->datalen = dstn + dstm2; dst->data = malloc(dst->datalen); if(!dst->data) return; if(dstm2) - memset((void*)dst->data + dstn, 0x80, dstm2); - uint8_t *dsty = (void*)dst->data; + memset((uint8_t*)dst->data + dstn, 0x80, dstm2); + dsty = (void*)dst->data; assert(src->datalen >= (src->width * src->height * srcfmt->p.rgb.bpp)); - const uint8_t *srcp = src->data; + srcp = src->data; - int rbits = RGB_SIZE(srcfmt->p.rgb.red); - int rbit0 = RGB_OFFSET(srcfmt->p.rgb.red); - int gbits = RGB_SIZE(srcfmt->p.rgb.green); - int gbit0 = RGB_OFFSET(srcfmt->p.rgb.green); - int bbits = RGB_SIZE(srcfmt->p.rgb.blue); - int bbit0 = RGB_OFFSET(srcfmt->p.rgb.blue); + rbits = RGB_SIZE(srcfmt->p.rgb.red); + rbit0 = RGB_OFFSET(srcfmt->p.rgb.red); + gbits = RGB_SIZE(srcfmt->p.rgb.green); + gbit0 = RGB_OFFSET(srcfmt->p.rgb.green); + bbits = RGB_SIZE(srcfmt->p.rgb.blue); + bbit0 = RGB_OFFSET(srcfmt->p.rgb.blue); - unsigned srcl = src->width * srcfmt->p.rgb.bpp; - unsigned x, y; - uint16_t y0 = 0; + srcl = src->width * srcfmt->p.rgb.bpp; for(y = 0; y < dst->height; y++) { if(y >= src->height) srcp -= srcl; @@ -659,29 +684,33 @@ static void convert_yuv_to_rgb (zbar_image_t *dst, const zbar_image_t *src, const zbar_format_def_t *srcfmt) { + uint8_t *dstp; unsigned long dstn = dst->width * dst->height; + int drbits, drbit0, dgbits, dgbit0, dbbits, dbbit0; + const uint8_t *srcp; + unsigned srcl, x, y; + uint32_t p = 0; + dst->datalen = dstn * dstfmt->p.rgb.bpp; dst->data = malloc(dst->datalen); if(!dst->data) return; - uint8_t *dstp = (void*)dst->data; + dstp = (void*)dst->data; - int drbits = RGB_SIZE(dstfmt->p.rgb.red); - int drbit0 = RGB_OFFSET(dstfmt->p.rgb.red); - int dgbits = RGB_SIZE(dstfmt->p.rgb.green); - int dgbit0 = RGB_OFFSET(dstfmt->p.rgb.green); - int dbbits = RGB_SIZE(dstfmt->p.rgb.blue); - int dbbit0 = RGB_OFFSET(dstfmt->p.rgb.blue); + drbits = RGB_SIZE(dstfmt->p.rgb.red); + drbit0 = RGB_OFFSET(dstfmt->p.rgb.red); + dgbits = RGB_SIZE(dstfmt->p.rgb.green); + dgbit0 = RGB_OFFSET(dstfmt->p.rgb.green); + dbbits = RGB_SIZE(dstfmt->p.rgb.blue); + dbbit0 = RGB_OFFSET(dstfmt->p.rgb.blue); assert(src->datalen >= (src->width * src->height + uvp_size(src, srcfmt) * 2)); - const uint8_t *srcp = src->data; + srcp = src->data; if(srcfmt->p.yuv.packorder & 2) srcp++; assert(srcfmt->p.yuv.xsub2 == 1); - unsigned srcl = src->width + (src->width >> 1); - unsigned x, y; - uint32_t p = 0; + srcl = src->width + (src->width >> 1); for(y = 0; y < dst->height; y++) { if(y >= src->height) srcp -= srcl; @@ -717,26 +746,30 @@ static void convert_rgb_to_yuv (zbar_image_t *dst, const zbar_image_t *src, const zbar_format_def_t *srcfmt) { + uint8_t *dstp, flags; + const uint8_t *srcp; + int rbits, rbit0, gbits, gbit0, bbits, bbit0; + unsigned srcl, x, y; + uint16_t y0 = 0; + uv_roundup(dst, dstfmt); dst->datalen = dst->width * dst->height + uvp_size(dst, dstfmt) * 2; dst->data = malloc(dst->datalen); if(!dst->data) return; - uint8_t *dstp = (void*)dst->data; - uint8_t flags = dstfmt->p.yuv.packorder & 2; + dstp = (void*)dst->data; + flags = dstfmt->p.yuv.packorder & 2; assert(src->datalen >= (src->width * src->height * srcfmt->p.rgb.bpp)); - const uint8_t *srcp = src->data; + srcp = src->data; - int rbits = RGB_SIZE(srcfmt->p.rgb.red); - int rbit0 = RGB_OFFSET(srcfmt->p.rgb.red); - int gbits = RGB_SIZE(srcfmt->p.rgb.green); - int gbit0 = RGB_OFFSET(srcfmt->p.rgb.green); - int bbits = RGB_SIZE(srcfmt->p.rgb.blue); - int bbit0 = RGB_OFFSET(srcfmt->p.rgb.blue); + rbits = RGB_SIZE(srcfmt->p.rgb.red); + rbit0 = RGB_OFFSET(srcfmt->p.rgb.red); + gbits = RGB_SIZE(srcfmt->p.rgb.green); + gbit0 = RGB_OFFSET(srcfmt->p.rgb.green); + bbits = RGB_SIZE(srcfmt->p.rgb.blue); + bbit0 = RGB_OFFSET(srcfmt->p.rgb.blue); - unsigned srcl = src->width * srcfmt->p.rgb.bpp; - unsigned x, y; - uint16_t y0 = 0; + srcl = src->width * srcfmt->p.rgb.bpp; for(y = 0; y < dst->height; y++) { if(y >= src->height) srcp -= srcl; @@ -773,31 +806,36 @@ static void convert_rgb_resample (zbar_image_t *dst, const zbar_format_def_t *srcfmt) { unsigned long dstn = dst->width * dst->height; + uint8_t *dstp; + int drbits, drbit0, dgbits, dgbit0, dbbits, dbbit0; + int srbits, srbit0, sgbits, sgbit0, sbbits, sbbit0; + const uint8_t *srcp; + unsigned srcl, x, y; + uint32_t p = 0; + dst->datalen = dstn * dstfmt->p.rgb.bpp; dst->data = malloc(dst->datalen); if(!dst->data) return; - uint8_t *dstp = (void*)dst->data; + dstp = (void*)dst->data; - int drbits = RGB_SIZE(dstfmt->p.rgb.red); - int drbit0 = RGB_OFFSET(dstfmt->p.rgb.red); - int dgbits = RGB_SIZE(dstfmt->p.rgb.green); - int dgbit0 = RGB_OFFSET(dstfmt->p.rgb.green); - int dbbits = RGB_SIZE(dstfmt->p.rgb.blue); - int dbbit0 = RGB_OFFSET(dstfmt->p.rgb.blue); + drbits = RGB_SIZE(dstfmt->p.rgb.red); + drbit0 = RGB_OFFSET(dstfmt->p.rgb.red); + dgbits = RGB_SIZE(dstfmt->p.rgb.green); + dgbit0 = RGB_OFFSET(dstfmt->p.rgb.green); + dbbits = RGB_SIZE(dstfmt->p.rgb.blue); + dbbit0 = RGB_OFFSET(dstfmt->p.rgb.blue); assert(src->datalen >= (src->width * src->height * srcfmt->p.rgb.bpp)); - const uint8_t *srcp = src->data; + srcp = src->data; - int srbits = RGB_SIZE(srcfmt->p.rgb.red); - int srbit0 = RGB_OFFSET(srcfmt->p.rgb.red); - int sgbits = RGB_SIZE(srcfmt->p.rgb.green); - int sgbit0 = RGB_OFFSET(srcfmt->p.rgb.green); - int sbbits = RGB_SIZE(srcfmt->p.rgb.blue); - int sbbit0 = RGB_OFFSET(srcfmt->p.rgb.blue); + srbits = RGB_SIZE(srcfmt->p.rgb.red); + srbit0 = RGB_OFFSET(srcfmt->p.rgb.red); + sgbits = RGB_SIZE(srcfmt->p.rgb.green); + sgbit0 = RGB_OFFSET(srcfmt->p.rgb.green); + sbbits = RGB_SIZE(srcfmt->p.rgb.blue); + sbbit0 = RGB_OFFSET(srcfmt->p.rgb.blue); - unsigned srcl = src->width * srcfmt->p.rgb.bpp; - unsigned x, y; - uint32_t p = 0; + srcl = src->width * srcfmt->p.rgb.bpp; for(y = 0; y < dst->height; y++) { if(y >= src->height) y -= srcl; @@ -963,6 +1001,8 @@ zbar_image_t *zbar_image_convert_resize (const zbar_image_t *src, unsigned width, unsigned height) { + const zbar_format_def_t *srcfmt, *dstfmt; + conversion_handler_t *func; zbar_image_t *dst = zbar_image_create(); dst->format = fmt; dst->width = width; @@ -974,8 +1014,8 @@ zbar_image_t *zbar_image_convert_resize (const zbar_image_t *src, return(dst); } - const zbar_format_def_t *srcfmt = _zbar_format_lookup(src->format); - const zbar_format_def_t *dstfmt = _zbar_format_lookup(dst->format); + srcfmt = _zbar_format_lookup(src->format); + dstfmt = _zbar_format_lookup(dst->format); if(!srcfmt || !dstfmt) /* FIXME free dst */ return(NULL); @@ -988,8 +1028,7 @@ zbar_image_t *zbar_image_convert_resize (const zbar_image_t *src, return(dst); } - conversion_handler_t *func = - conversions[srcfmt->group][dstfmt->group].func; + func = conversions[srcfmt->group][dstfmt->group].func; dst->cleanup = zbar_image_free_data; func(dst, dstfmt, src, srcfmt); @@ -1021,6 +1060,9 @@ int _zbar_best_format (uint32_t src, uint32_t *dst, const uint32_t *dsts) { + const zbar_format_def_t *srcfmt; + unsigned min_cost = -1; + if(dst) *dst = 0; if(!dsts) @@ -1031,17 +1073,16 @@ int _zbar_best_format (uint32_t src, *dst = src; return(0); } - const zbar_format_def_t *srcfmt = _zbar_format_lookup(src); + srcfmt = _zbar_format_lookup(src); if(!srcfmt) return(-1); zprintf(8, "from %.4s(%08" PRIx32 ") to", (char*)&src, src); - unsigned min_cost = -1; for(; *dsts; dsts++) { const zbar_format_def_t *dstfmt = _zbar_format_lookup(*dsts); + int cost; if(!dstfmt) continue; - int cost; if(srcfmt->group == dstfmt->group && srcfmt->p.cmp == dstfmt->p.cmp) cost = 0; @@ -1065,13 +1106,20 @@ int _zbar_best_format (uint32_t src, int zbar_negotiate_format (zbar_video_t *vdo, zbar_window_t *win) { + static const uint32_t y800[2] = { fourcc('Y','8','0','0'), 0 }; + errinfo_t *errdst; + const uint32_t *srcs, *dsts; + unsigned min_cost = -1; + uint32_t min_fmt = 0; + const uint32_t *fmt; + if(!vdo && !win) return(0); if(win) (void)window_lock(win); - errinfo_t *errdst = (vdo) ? &vdo->err : &win->err; + errdst = (vdo) ? &vdo->err : &win->err; if(verify_format_sort()) { if(win) (void)window_unlock(win); @@ -1086,19 +1134,16 @@ int zbar_negotiate_format (zbar_video_t *vdo, "no input or output formats available")); } - static const uint32_t y800[2] = { fourcc('Y','8','0','0'), 0 }; - const uint32_t *srcs = (vdo) ? vdo->formats : y800; - const uint32_t *dsts = (win) ? win->formats : y800; + srcs = (vdo) ? vdo->formats : y800; + dsts = (win) ? win->formats : y800; - unsigned min_cost = -1; - uint32_t min_fmt = 0; - const uint32_t *fmt; for(fmt = _zbar_formats; *fmt; fmt++) { /* only consider formats supported by video device */ + uint32_t win_fmt = 0; + int cost; if(!has_format(*fmt, srcs)) continue; - uint32_t win_fmt = 0; - int cost = _zbar_best_format(*fmt, &win_fmt, dsts); + cost = _zbar_best_format(*fmt, &win_fmt, dsts); if(cost < 0) { zprintf(4, "%.4s(%08" PRIx32 ") -> ? (unsupported)\n", (char*)fmt, *fmt); diff --git a/zbar/decoder.c b/zbar/decoder.c index 066d793..c1330e9 100644 --- a/zbar/decoder.c +++ b/zbar/decoder.c @@ -156,7 +156,7 @@ int zbar_decoder_get_direction (const zbar_decoder_t *dcode) zbar_decoder_handler_t * zbar_decoder_set_handler (zbar_decoder_t *dcode, - zbar_decoder_handler_t handler) + zbar_decoder_handler_t *handler) { zbar_decoder_handler_t *result = dcode->handler; dcode->handler = handler; @@ -182,12 +182,12 @@ zbar_symbol_type_t zbar_decoder_get_type (const zbar_decoder_t *dcode) zbar_symbol_type_t zbar_decode_width (zbar_decoder_t *dcode, unsigned w) { + zbar_symbol_type_t tmp, sym = ZBAR_NONE; + dcode->w[dcode->idx & (DECODE_WINDOW - 1)] = w; dprintf(1, " decode[%x]: w=%d (%g)\n", dcode->idx, w, (w / 32.)); /* each decoder processes width stream in parallel */ - zbar_symbol_type_t tmp, sym = ZBAR_NONE; - #ifdef ENABLE_EAN if((dcode->ean.enable) && (tmp = _zbar_decode_ean(dcode))) @@ -391,16 +391,18 @@ const char *_zbar_decoder_buf_dump (unsigned char *buf, unsigned int buflen) { int dumplen = (buflen * 3) + 12; + char *p; + int i; + if(!decoder_dump || dumplen > decoder_dumplen) { if(decoder_dump) free(decoder_dump); decoder_dump = malloc(dumplen); decoder_dumplen = dumplen; } - char *p = decoder_dump + + p = decoder_dump + snprintf(decoder_dump, 12, "buf[%04x]=", (buflen > 0xffff) ? 0xffff : buflen); - int i; for(i = 0; i < buflen; i++) p += snprintf(p, 4, "%s%02x", (i) ? " " : "", buf[i]); return(decoder_dump); diff --git a/zbar/decoder.h b/zbar/decoder.h index 2022dce..7bffdba 100644 --- a/zbar/decoder.h +++ b/zbar/decoder.h @@ -194,6 +194,7 @@ static inline char release_lock (zbar_decoder_t *dcode, static inline char size_buf (zbar_decoder_t *dcode, unsigned len) { + unsigned char *buf; if(len < dcode->buf_alloc) /* FIXME size reduction heuristic? */ return(0); @@ -204,7 +205,7 @@ static inline char size_buf (zbar_decoder_t *dcode, if(len > BUFFER_MAX) len = BUFFER_MAX; } - unsigned char *buf = realloc(dcode->buf, len); + buf = realloc(dcode->buf, len); if(!buf) return(1); dcode->buf = buf; diff --git a/zbar/decoder/code128.c b/zbar/decoder/code128.c index d79bbad..689e20e 100644 --- a/zbar/decoder/code128.c +++ b/zbar/decoder/code128.c @@ -120,6 +120,8 @@ static inline signed char decode_lo (int sig) ((sig >> 5) & 0x18) | ((sig >> 7) & 0x60)); unsigned char idx = lo_offset[offset]; + unsigned char base, c; + if(sig & 1) idx &= 0xf; else @@ -127,14 +129,14 @@ static inline signed char decode_lo (int sig) if(idx == 0xf) return(-1); - unsigned char base = (sig >> 11) | ((sig >> 9) & 1); + base = (sig >> 11) | ((sig >> 9) & 1); zassert(base < 8, -1, "sig=%x offset=%x idx=%x base=%x\n", sig, offset, idx, base); idx += lo_base[base]; zassert(idx <= 0x50, -1, "sig=%x offset=%x base=%x idx=%x\n", sig, offset, base, idx); - unsigned char c = characters[idx]; + c = characters[idx]; dprintf(2, " %02x(%x(%02x)/%x(%02x)) => %02x", idx, base, lo_base[base], offset, lo_offset[offset], (unsigned char)c); @@ -144,6 +146,7 @@ static inline signed char decode_lo (int sig) static inline signed char decode_hi (int sig) { unsigned char rev = (sig & 0x4400) != 0; + unsigned char idx, c; if(rev) sig = (((sig >> 12) & 0x000f) | ((sig >> 4) & 0x00f0) | @@ -151,7 +154,6 @@ static inline signed char decode_hi (int sig) ((sig << 12) & 0xf000)); dprintf(2, " rev=%x", rev != 0); - unsigned char idx; switch(sig) { case 0x0014: idx = 0x0; break; case 0x0025: idx = 0x1; break; @@ -171,7 +173,7 @@ static inline signed char decode_hi (int sig) } if(rev) idx += 0xe; - unsigned char c = characters[0x51 + idx]; + c = characters[0x51 + idx]; dprintf(2, " %02x => %02x", idx, c); return(c); } @@ -190,13 +192,18 @@ static inline unsigned char calc_check (unsigned char c) static inline signed char decode6 (zbar_decoder_t *dcode) { + int sig; + signed char c, chk; + unsigned bars; + /* build edge signature of character */ unsigned s = dcode->code128.s6; + dprintf(2, " s=%d", s); if(s < 5) return(-1); /* calculate similar edge measurements */ - int sig = (get_color(dcode) == ZBAR_BAR) + sig = (get_color(dcode) == ZBAR_BAR) ? ((decode_e(get_width(dcode, 0) + get_width(dcode, 1), s, 11) << 12) | (decode_e(get_width(dcode, 1) + get_width(dcode, 2), s, 11) << 8) | (decode_e(get_width(dcode, 2) + get_width(dcode, 3), s, 11) << 4) | @@ -209,16 +216,16 @@ static inline signed char decode6 (zbar_decoder_t *dcode) return(-1); dprintf(2, " sig=%04x", sig); /* lookup edge signature */ - signed char c = (sig & 0x4444) ? decode_hi(sig) : decode_lo(sig); + c = (sig & 0x4444) ? decode_hi(sig) : decode_lo(sig); if(c == -1) return(-1); /* character validation */ - unsigned bars = (get_color(dcode) == ZBAR_BAR) + bars = (get_color(dcode) == ZBAR_BAR) ? (get_width(dcode, 0) + get_width(dcode, 2) + get_width(dcode, 4)) : (get_width(dcode, 1) + get_width(dcode, 3) + get_width(dcode, 5)); bars = bars * 11 * 4 / s; - unsigned char chk = calc_check(c); + chk = calc_check(c); dprintf(2, " bars=%d chk=%d", bars, chk); if(chk - 7 > bars || bars > chk + 7) return(-1); @@ -228,18 +235,20 @@ static inline signed char decode6 (zbar_decoder_t *dcode) static inline unsigned char validate_checksum (zbar_decoder_t *dcode) { + unsigned idx, sum, i, acc = 0; + unsigned char check, err; + code128_decoder_t *dcode128 = &dcode->code128; if(dcode128->character < 3) return(1); /* add in irregularly weighted start character */ - unsigned idx = (dcode128->direction) ? dcode128->character - 1 : 0; - unsigned sum = dcode->buf[idx]; + idx = (dcode128->direction) ? dcode128->character - 1 : 0; + sum = dcode->buf[idx]; if(sum >= 103) sum -= 103; /* calculate sum in reverse to avoid multiply operations */ - unsigned i, acc = 0; for(i = dcode128->character - 3; i; i--) { zassert(sum < 103, -1, "dir=%x i=%x sum=%x acc=%x %s\n", dcode128->direction, i, sum, acc, @@ -258,9 +267,9 @@ static inline unsigned char validate_checksum (zbar_decoder_t *dcode) /* and compare to check character */ idx = (dcode128->direction) ? 1 : dcode128->character - 2; - unsigned char check = dcode->buf[idx]; + check = dcode->buf[idx]; dprintf(2, " chk=%02x(%02x)", sum, check); - unsigned char err = (sum != check); + err = (sum != check); if(err) dprintf(1, " [checksum error]\n"); return(err); @@ -272,6 +281,8 @@ static inline unsigned postprocess_c (zbar_decoder_t *dcode, unsigned end, unsigned dst) { + unsigned i, j; + /* expand buffer to accomodate 2x set C characters (2 digits per-char) */ unsigned delta = end - start; unsigned newlen = dcode->code128.character + delta; @@ -282,7 +293,6 @@ static inline unsigned postprocess_c (zbar_decoder_t *dcode, dcode->code128.character - start); dcode->code128.character = newlen; - unsigned i, j; for(i = 0, j = dst; i < delta; i++, j += 2) { /* convert each set C character into two ASCII digits */ unsigned char code = dcode->buf[start + delta + i]; @@ -317,10 +327,10 @@ static inline unsigned postprocess_c (zbar_decoder_t *dcode, /* resolve scan direction and convert to ASCII */ static inline unsigned char postprocess (zbar_decoder_t *dcode) { + unsigned i, j, cexp; + unsigned char code = 0, charset; code128_decoder_t *dcode128 = &dcode->code128; dprintf(2, "\n postproc len=%d", dcode128->character); - unsigned i, j; - unsigned char code = 0; dcode->direction = 1 - 2 * dcode128->direction; if(dcode128->direction) { /* reverse buffer */ @@ -344,8 +354,8 @@ static inline unsigned char postprocess (zbar_decoder_t *dcode) zassert(code >= START_A && code <= START_C, 1, "%s\n", _zbar_decoder_buf_dump(dcode->buf, dcode->code128.character)); - unsigned char charset = code - START_A; - unsigned cexp = (code == START_C) ? 1 : 0; + charset = code - START_A; + cexp = (code == START_C) ? 1 : 0; dprintf(2, " start=%c", 'A' + charset); for(i = 1, j = 0; i < dcode128->character - 2; i++) { @@ -371,12 +381,13 @@ static inline unsigned char postprocess (zbar_decoder_t *dcode) else { dprintf(2, " %02x", code); if(charset & 0x2) { + unsigned delta; /* expand character set C to ASCII */ zassert(cexp, 1, "i=%x j=%x code=%02x charset=%x cexp=%x %s\n", i, j, code, charset, cexp, _zbar_decoder_buf_dump(dcode->buf, dcode->code128.character)); - unsigned delta = postprocess_c(dcode, cexp, i, j); + delta = postprocess_c(dcode, cexp, i, j); i += delta; j += delta * 2; cexp = 0; @@ -396,12 +407,12 @@ static inline unsigned char postprocess (zbar_decoder_t *dcode) return(1); } else { + unsigned char newset = CODE_A - code; zassert(code >= CODE_C && code <= CODE_A, 1, "i=%x j=%x code=%02x charset=%x cexp=%x %s\n", i, j, code, charset, cexp, _zbar_decoder_buf_dump(dcode->buf, dcode->code128.character)); - unsigned char newset = CODE_A - code; if(newset != charset) charset = newset; else @@ -427,6 +438,7 @@ static inline unsigned char postprocess (zbar_decoder_t *dcode) zbar_symbol_type_t _zbar_decode_code128 (zbar_decoder_t *dcode) { code128_decoder_t *dcode128 = &dcode->code128; + signed char c; /* update latest character width */ dcode128->s6 -= get_width(dcode, 6); @@ -444,14 +456,15 @@ zbar_symbol_type_t _zbar_decode_code128 (zbar_decoder_t *dcode) (dcode128->direction) ? '<' : '>', dcode128->character, dcode128->element); - signed char c = decode6(dcode); + c = decode6(dcode); if(dcode128->character < 0) { + unsigned qz; dprintf(2, " c=%02x", c); if(c < START_A || c > STOP_REV || c == STOP_FWD) { dprintf(2, " [invalid]\n"); return(0); } - unsigned qz = get_width(dcode, 6); + qz = get_width(dcode, 6); if(qz && qz < (dcode->code128.s6 * 3) / 4) { dprintf(2, " [invalid qz %d]\n", qz); return(0); diff --git a/zbar/decoder/ean.c b/zbar/decoder/ean.c index 874bca7..bb9c501 100644 --- a/zbar/decoder/ean.c +++ b/zbar/decoder/ean.c @@ -115,6 +115,8 @@ static inline const unsigned char *dsprintbuf(ean_decoder_t *ean) static inline signed char aux_end (zbar_decoder_t *dcode, unsigned char fwd) { + signed char code, i; + /* reference width from previous character */ unsigned s = calc_s(dcode, 4 + fwd, 4); @@ -126,8 +128,7 @@ static inline signed char aux_end (zbar_decoder_t *dcode, } dprintf(2, " ("); - signed char code = 0; - unsigned char i; + code = 0; for(i = 1 - fwd; i < 3 + fwd; i++) { unsigned e = get_width(dcode, i) + get_width(dcode, i + 1); dprintf(2, " %d", e); @@ -147,14 +148,15 @@ static inline signed char aux_end (zbar_decoder_t *dcode, static inline signed char aux_start (zbar_decoder_t *dcode) { /* FIXME NB add-on has no guard in reverse */ - unsigned e2 = get_width(dcode, 5) + get_width(dcode, 6); + unsigned e1, e2 = get_width(dcode, 5) + get_width(dcode, 6); + unsigned char E1; if(decode_e(e2, dcode->ean.s4, 7)) { dprintf(2, " [invalid any]"); return(/*FIXME (get_color(dcode) == ZBAR_SPACE) ? STATE_ADDON : */-1); } - unsigned e1 = get_width(dcode, 4) + get_width(dcode, 5); - unsigned char E1 = decode_e(e1, dcode->ean.s4, 7); + e1 = get_width(dcode, 4) + get_width(dcode, 5); + E1 = decode_e(e1, dcode->ean.s4, 7); if(get_color(dcode) == ZBAR_BAR) { /* check for quiet-zone */ @@ -188,6 +190,8 @@ static inline signed char aux_start (zbar_decoder_t *dcode) /* attempt to decode previous 4 widths (2 bars and 2 spaces) as a character */ static inline signed char decode4 (zbar_decoder_t *dcode) { + signed char code; + /* calculate similar edge measurements */ unsigned e1 = ((get_color(dcode) == ZBAR_BAR) ? get_width(dcode, 0) + get_width(dcode, 1) @@ -196,8 +200,8 @@ static inline signed char decode4 (zbar_decoder_t *dcode) dprintf(2, "\n e1=%d e2=%d", e1, e2); /* create compacted encoding for direct lookup */ - signed char code = ((decode_e(e1, dcode->ean.s4, 7) << 2) | - decode_e(e2, dcode->ean.s4, 7)); + code = ((decode_e(e1, dcode->ean.s4, 7) << 2) | + decode_e(e2, dcode->ean.s4, 7)); if(code < 0) return(-1); dprintf(2, " code=%x", code); @@ -209,15 +213,16 @@ static inline signed char decode4 (zbar_decoder_t *dcode) E1E2 == 44 (1010) */ if((1 << code) & 0x0660) { + unsigned char mid, alt; /* use sum of bar widths */ unsigned d2 = ((get_color(dcode) == ZBAR_BAR) ? get_width(dcode, 0) + get_width(dcode, 2) : get_width(dcode, 1) + get_width(dcode, 3)); d2 *= 7; - unsigned char mid = (((1 << code) & 0x0420) + mid = (((1 << code) & 0x0420) ? 3 /* E1E2 in 33,44 */ : 4); /* E1E2 in 34,43 */ - unsigned char alt = d2 > (mid * dcode->ean.s4); + alt = d2 > (mid * dcode->ean.s4); if(alt) code = ((code >> 1) & 3) | 0x10; /* compress code space */ dprintf(2, " (d2=%d(%d) alt=%d)", d2, mid * dcode->ean.s4, alt); @@ -243,9 +248,9 @@ static inline zbar_symbol_type_t ean_part_end4 (ean_pass_t *pass, return(ZBAR_NONE); if(!par == fwd) { - pass->state |= STATE_REV; /* reverse sampled digits */ unsigned char tmp = pass->raw[1]; + pass->state |= STATE_REV; pass->raw[1] = pass->raw[4]; pass->raw[4] = tmp; tmp = pass->raw[2]; @@ -293,9 +298,9 @@ static inline zbar_symbol_type_t ean_part_end7 (ean_decoder_t *ean, return(ZBAR_NONE); if(!par == fwd) { + unsigned char i; pass->state |= STATE_REV; /* reverse sampled digits */ - unsigned char i; for(i = 1; i < 4; i++) { unsigned char tmp = pass->raw[i]; pass->raw[i] = pass->raw[7 - i]; @@ -326,16 +331,18 @@ static inline zbar_symbol_type_t ean_part_end7 (ean_decoder_t *ean, static inline zbar_symbol_type_t decode_pass (zbar_decoder_t *dcode, ean_pass_t *pass) { + unsigned char idx, fwd; pass->state++; - unsigned char idx = pass->state & STATE_IDX; - unsigned char fwd = pass->state & 1; + idx = pass->state & STATE_IDX; + fwd = pass->state & 1; if(get_color(dcode) == ZBAR_SPACE && (idx == 0x10 || idx == 0x11) && TEST_CFG(dcode->ean.ean8_config, ZBAR_CFG_ENABLE) && !aux_end(dcode, fwd)) { + zbar_symbol_type_t part; dprintf(2, " fwd=%x", fwd); - zbar_symbol_type_t part = ean_part_end4(pass, fwd); + part = ean_part_end4(pass, fwd); if(part) dcode->ean.direction = (pass->state & STATE_REV) != 0; pass->state = -1; @@ -343,6 +350,7 @@ static inline zbar_symbol_type_t decode_pass (zbar_decoder_t *dcode, } if(!(idx & 0x03) && idx <= 0x14) { + signed char code; if(!dcode->ean.s4) return(0); /* validate guard bars before decoding first char of symbol */ @@ -352,7 +360,7 @@ static inline zbar_symbol_type_t decode_pass (zbar_decoder_t *dcode, return(0); idx = pass->state & STATE_IDX; } - signed char code = decode4(dcode); + code = decode4(dcode); if(code < 0) pass->state = -1; else { @@ -385,7 +393,7 @@ static inline signed char ean_verify_checksum (ean_decoder_t *ean, int n) { unsigned char chk = 0; - unsigned char i; + unsigned char i, d; for(i = 0; i < n; i++) { unsigned char d = ean->buf[i]; zassert(d < 10, -1, "i=%x d=%x chk=%x %s\n", i, d, chk, @@ -403,7 +411,7 @@ static inline signed char ean_verify_checksum (ean_decoder_t *ean, _zbar_decoder_buf_dump((void*)ean->buf, 18)); if(chk) chk = 10 - chk; - unsigned char d = ean->buf[n]; + d = ean->buf[n]; zassert(d < 10, -1, "n=%x d=%x chk=%x %s\n", n, d, chk, _zbar_decoder_buf_dump((void*)ean->buf, 18)); if(chk != d) { @@ -437,10 +445,11 @@ static inline void ean_expand_upce (ean_decoder_t *ean, ean_pass_t *pass) { int i = 0; + unsigned char decode; /* parity encoded digit is checksum */ ean->buf[12] = pass->raw[i++]; - unsigned char decode = pass->raw[6] & 0xf; + decode = pass->raw[6] & 0xf; ean->buf[0] = 0; ean->buf[1] = 0; ean->buf[2] = pass->raw[i++] & 0xf; @@ -459,10 +468,10 @@ static inline zbar_symbol_type_t integrate_partial (ean_decoder_t *ean, ean_pass_t *pass, zbar_symbol_type_t part) { + signed char i, j; /* copy raw data into holding buffer */ /* if same partial is not consistent, reset others */ dprintf(2, " integrate part=%x (%s)", part, dsprintbuf(ean)); - signed char i, j; if(part & ZBAR_ADDON) { /* FIXME TBD */ for(i = (part == ZBAR_ADDON5) ? 4 : 1; i >= 0; i--) { @@ -611,20 +620,21 @@ zbar_symbol_type_t _zbar_decode_ean (zbar_decoder_t *dcode) /* process upto 4 separate passes */ zbar_symbol_type_t sym = ZBAR_NONE; unsigned char pass_idx = dcode->idx & 3; + unsigned char i; /* update latest character width */ dcode->ean.s4 -= get_width(dcode, 4); dcode->ean.s4 += get_width(dcode, 0); - unsigned char i; for(i = 0; i < 4; i++) { ean_pass_t *pass = &dcode->ean.pass[i]; if(pass->state >= 0 || i == pass_idx) { + zbar_symbol_type_t part; dprintf(2, " ean[%x/%x]: idx=%x st=%d s=%d", pass_idx, i, dcode->idx, pass->state, dcode->ean.s4); - zbar_symbol_type_t part = decode_pass(dcode, pass); + part = decode_pass(dcode, pass); if(part) { /* update accumulated data from new partial decode */ sym = integrate_partial(&dcode->ean, pass, part); diff --git a/zbar/decoder/qr_finder.c b/zbar/decoder/qr_finder.c index 9f7691f..f6c0819 100644 --- a/zbar/decoder/qr_finder.c +++ b/zbar/decoder/qr_finder.c @@ -43,18 +43,20 @@ qr_finder_line *_zbar_decoder_get_qr_finder_line (zbar_decoder_t *dcode) zbar_symbol_type_t _zbar_find_qr (zbar_decoder_t *dcode) { qr_finder_t *qrf = &dcode->qrf; + unsigned s, qz, w; + int ei; /* update latest finder pattern width */ qrf->s5 -= get_width(dcode, 6); qrf->s5 += get_width(dcode, 1); - unsigned s = qrf->s5; + s = qrf->s5; if(get_color(dcode) != ZBAR_SPACE || s < 7) return(0); dprintf(2, " qrf: s=%d", s); - int ei = decode_e(pair_width(dcode, 1), s, 7); + ei = decode_e(pair_width(dcode, 1), s, 7); dprintf(2, " %d", ei); if(ei) goto invalid; @@ -77,8 +79,8 @@ zbar_symbol_type_t _zbar_find_qr (zbar_decoder_t *dcode) /* valid QR finder symbol * mark positions needed by decoder */ - unsigned qz = get_width(dcode, 0); - unsigned w = get_width(dcode, 1); + qz = get_width(dcode, 0); + w = get_width(dcode, 1); qrf->line.eoffs = qz + (w + 1) / 2; qrf->line.len = qz + w + get_width(dcode, 2); qrf->line.pos[0] = qrf->line.len + get_width(dcode, 3); diff --git a/zbar/error.c b/zbar/error.c index 7bd3caf..27b0a82 100644 --- a/zbar/error.c +++ b/zbar/error.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown + * Copyright 2007-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -36,7 +36,7 @@ static const char * const mod_str[] = { }; #define MOD_MAX (strlen(mod_str[ZBAR_MOD_IMAGE_SCANNER])) -static const char const * err_str[] = { +static const char * const err_str[] = { "no error", /* OK */ "out of memory", /* NOMEM */ "internal library error", /* INTERNAL */ @@ -99,32 +99,32 @@ zbar_error_t _zbar_get_error_code (const void *container) const char *_zbar_error_string (const void *container, int verbosity) { + static const char basefmt[] = "%s: zbar %s in %s():\n %s: "; errinfo_t *err = (errinfo_t*)container; + const char *sev, *mod, *func, *type; + int len; + assert(err->magic == ERRINFO_MAGIC); - const char *sev; if(err->sev >= SEV_FATAL && err->sev <= SEV_NOTE) sev = sev_str[err->sev + 2]; else sev = sev_str[1]; - const char *mod; if(err->module >= ZBAR_MOD_PROCESSOR && err->module < ZBAR_MOD_UNKNOWN) mod = mod_str[err->module]; else mod = mod_str[ZBAR_MOD_UNKNOWN]; - const char *func = (err->func) ? err->func : ""; + func = (err->func) ? err->func : ""; - const char *type; if(err->type >= 0 && err->type < ZBAR_ERR_NUM) type = err_str[err->type]; else type = err_str[ZBAR_ERR_NUM]; - char basefmt[] = "%s: zbar %s in %s():\n %s: "; - int len = SEV_MAX + MOD_MAX + ERR_MAX + strlen(func) + sizeof(basefmt); + len = SEV_MAX + MOD_MAX + ERR_MAX + strlen(func) + sizeof(basefmt); err->buf = realloc(err->buf, len); len = sprintf(err->buf, basefmt, sev, mod, func, type); if(len <= 0) @@ -150,12 +150,14 @@ const char *_zbar_error_string (const void *container, return(""); } +#ifdef HAVE_ERRNO_H if(err->type == ZBAR_ERR_SYSTEM) { - char sysfmt[] = ": %s (%d)\n"; + static const char sysfmt[] = ": %s (%d)\n"; const char *syserr = strerror(err->errnum); err->buf = realloc(err->buf, len + strlen(sysfmt) + strlen(syserr)); len += sprintf(err->buf + len, sysfmt, syserr, err->errnum); } +#endif #ifdef _WIN32 else if(err->type == ZBAR_ERR_WINAPI) { char *syserr = NULL; diff --git a/zbar/error.h b/zbar/error.h index 1ab9068..523c391 100644 --- a/zbar/error.h +++ b/zbar/error.h @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown + * Copyright 2007-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -30,7 +30,9 @@ #include #include #include -#include +#ifdef HAVE_ERRNO_H +# include +#endif #include #include @@ -146,10 +148,12 @@ static inline int err_capture (const void *container, { errinfo_t *err = (errinfo_t*)container; assert(err->magic == ERRINFO_MAGIC); +#ifdef HAVE_ERRNO_H if(type == ZBAR_ERR_SYSTEM) err->errnum = errno; +#endif #ifdef _WIN32 - else if(type == ZBAR_ERR_WINAPI) + if(type == ZBAR_ERR_WINAPI) err->errnum = GetLastError(); #endif err->sev = sev; diff --git a/zbar/image.c b/zbar/image.c index 81ba349..4bcb2a3 100644 --- a/zbar/image.c +++ b/zbar/image.c @@ -109,9 +109,10 @@ inline void zbar_image_free_data (zbar_image_t *img) if(!img) return; if(img->src) { + zbar_image_t *newimg; /* replace video image w/new copy */ assert(img->refcnt); /* FIXME needs lock */ - zbar_image_t *newimg = zbar_image_create(); + newimg = zbar_image_create(); memcpy(newimg, img, sizeof(zbar_image_t)); /* recycle video image */ newimg->cleanup(newimg); @@ -202,10 +203,12 @@ int zbar_image_write (const zbar_image_t *img, const char *filebase) { int len = strlen(filebase) + 16; - char filename[len]; + char *filename = malloc(len); + int n = 0, rc = 0; + FILE *f; + zimg_hdr_t hdr; strcpy(filename, filebase); - int n = 0; - if(img->format & 0xff >= ' ') + if((img->format & 0xff) >= ' ') n = snprintf(filename, len, "%s.%.4s.zimg", filebase, (char*)&img->format); else @@ -217,14 +220,17 @@ int zbar_image_write (const zbar_image_t *img, zprintf(1, "dumping %.4s(%08" PRIx32 ") image to %s\n", (char*)&img->format, img->format, filename); - FILE *f = fopen(filename, "w"); + f = fopen(filename, "w"); if(!f) { - int rc = errno; +#ifdef HAVE_ERRNO_H + rc = errno; zprintf(1, "ERROR opening %s: %s\n", filename, strerror(rc)); - return(rc); +#else + rc = 1; +#endif + goto error; } - zimg_hdr_t hdr; hdr.magic = 0x676d697a; hdr.format = img->format; hdr.width = img->width; @@ -233,12 +239,21 @@ int zbar_image_write (const zbar_image_t *img, if(fwrite(&hdr, sizeof(hdr), 1, f) != 1 || fwrite(img->data, 1, img->datalen, f) != img->datalen) { - int rc = errno; +#ifdef HAVE_ERRNO_H + rc = errno; zprintf(1, "ERROR writing %s: %s\n", filename, strerror(rc)); +#else + rc = 1; +#endif fclose(f); - return(rc); + goto error; } - return(fclose(f)); + + rc = fclose(f); + +error: + free(filename); + return(rc); } #ifdef DEBUG_SVG diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 4551548..89a711b 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -22,19 +22,20 @@ *------------------------------------------------------------------------*/ #include -#include +#ifdef HAVE_UNISTD_H +# include +#endif #ifdef HAVE_INTTYPES_H # include #endif #include /* malloc, free */ -#include /* clock_gettime */ -#include /* gettimeofday */ #include /* memcmp, memset, memcpy */ #include #include #include "error.h" #include "image.h" +#include "timer.h" #ifdef ENABLE_QRCODE # include "qrcode.h" #endif @@ -136,6 +137,8 @@ void _zbar_image_scanner_recycle_syms (zbar_image_scanner_t *iscn, sym->next = NULL; } else { + int i; + recycle_bucket_t *bucket; /* recycle unreferenced symbol */ if(!sym->data_alloc) { sym->data = NULL; @@ -149,7 +152,6 @@ void _zbar_image_scanner_recycle_syms (zbar_image_scanner_t *iscn, _zbar_symbol_set_free(sym->syms); sym->syms = NULL; } - int i; for(i = 0; i < RECYCLE_BUCKETS; i++) if(sym->data_alloc < 1 << (i * 2)) break; @@ -160,7 +162,7 @@ void _zbar_image_scanner_recycle_syms (zbar_image_scanner_t *iscn, sym->data_alloc = 0; i = 0; } - recycle_bucket_t *bucket = &iscn->recycle[i]; + bucket = &iscn->recycle[i]; /* FIXME cap bucket fill */ bucket->nsyms++; sym->next = bucket->head; @@ -219,12 +221,12 @@ _zbar_image_scanner_alloc_sym (zbar_image_scanner_t *iscn, int datalen) { /* recycle old or alloc new symbol */ + zbar_symbol_t *sym = NULL; int i; for(i = 0; i < RECYCLE_BUCKETS - 1; i++) if(datalen <= 1 << (i * 2)) break; - zbar_symbol_t *sym = NULL; for(; i > 0; i--) if((sym = iscn->recycle[i].head)) { STAT(sym_recycle[i]); @@ -295,6 +297,7 @@ static inline zbar_symbol_t *cache_lookup (zbar_image_scanner_t *iscn, static inline void cache_sym (zbar_image_scanner_t *iscn, zbar_symbol_t *sym) { + uint32_t age, near_thresh, far_thresh, dup; if(iscn->enable_cache) { char qr = (sym->type == ZBAR_QRCODE); zbar_symbol_t *entry = cache_lookup(iscn, sym); @@ -311,11 +314,11 @@ static inline void cache_sym (zbar_image_scanner_t *iscn, } /* consistency check and hysteresis */ - uint32_t age = sym->time - entry->time; + age = sym->time - entry->time; entry->time = sym->time; - int near_thresh = (age < CACHE_PROXIMITY); - int far_thresh = (age >= CACHE_HYSTERESIS); - int dup = (entry->cache_count >= 0); + near_thresh = (age < CACHE_PROXIMITY); + far_thresh = (age >= CACHE_HYSTERESIS); + dup = (entry->cache_count >= 0); if((!dup && !near_thresh) || far_thresh) entry->cache_count = (qr) ? 0 : -CACHE_CONSISTENCY; else if(dup || near_thresh) @@ -330,9 +333,10 @@ static inline void cache_sym (zbar_image_scanner_t *iscn, void _zbar_image_scanner_add_sym(zbar_image_scanner_t *iscn, zbar_symbol_t *sym) { + zbar_symbol_set_t *syms; cache_sym(iscn, sym); - zbar_symbol_set_t *syms = iscn->syms; + syms = iscn->syms; if(sym->cache_count || !syms->tail) { sym->next = syms->head; syms->head = sym; @@ -360,10 +364,12 @@ extern qr_finder_line *_zbar_decoder_get_qr_finder_line(zbar_decoder_t*); static inline void qr_handler (zbar_image_scanner_t *iscn) { + unsigned u; + int vert; qr_finder_line *line = _zbar_decoder_get_qr_finder_line(iscn->dcode); assert(line); - unsigned u = zbar_scanner_get_edge(iscn->scn, line->pos[0], - QR_FINDER_SUBPREC); + u = zbar_scanner_get_edge(iscn->scn, line->pos[0], + QR_FINDER_SUBPREC); line->boffs = u - zbar_scanner_get_edge(iscn->scn, line->boffs, QR_FINDER_SUBPREC); line->len = zbar_scanner_get_edge(iscn->scn, line->len, @@ -374,12 +380,12 @@ static inline void qr_handler (zbar_image_scanner_t *iscn) u = QR_FIXED(iscn->umin, 0) + iscn->du * u; if(iscn->du < 0) { - u -= line->len; int tmp = line->boffs; line->boffs = line->eoffs; line->eoffs = tmp; + u -= line->len; } - int vert = !iscn->dx; + vert = !iscn->dx; line->pos[vert] = u; line->pos[!vert] = QR_FIXED(iscn->v, 1); @@ -391,6 +397,11 @@ static void symbol_handler (zbar_decoder_t *dcode) { zbar_image_scanner_t *iscn = zbar_decoder_get_userdata(dcode); zbar_symbol_type_t type = zbar_decoder_get_type(dcode); + int x = 0, y = 0, dir; + const char *data; + unsigned datalen; + zbar_symbol_t *sym; + /* FIXME assert(type == ZBAR_PARTIAL) */ /* FIXME debug flag to save/display all PARTIALs */ if(type <= ZBAR_PARTIAL) @@ -405,10 +416,9 @@ static void symbol_handler (zbar_decoder_t *dcode) assert(type != ZBAR_QRCODE); #endif - const char *data = zbar_decoder_get_data(dcode); - unsigned datalen = zbar_decoder_get_data_length(dcode); + data = zbar_decoder_get_data(dcode); + datalen = zbar_decoder_get_data_length(dcode); - int x = 0, y = 0; if(TEST_CFG(iscn, ZBAR_CFG_POSITION)) { /* tmp position fixup */ int w = zbar_scanner_get_width(iscn->scn); @@ -424,7 +434,6 @@ static void symbol_handler (zbar_decoder_t *dcode) } /* FIXME need better symbol matching */ - zbar_symbol_t *sym; for(sym = iscn->syms->head; sym; sym = sym->next) if(sym->type == type && sym->datalen == datalen && @@ -445,7 +454,7 @@ static void symbol_handler (zbar_decoder_t *dcode) if(TEST_CFG(iscn, ZBAR_CFG_POSITION)) sym_add_point(sym, x, y); - int dir = zbar_decoder_get_direction(dcode); + dir = zbar_decoder_get_direction(dcode); if(dir) sym->orient = (iscn->dy != 0) + ((iscn->du ^ dir) & 2); @@ -480,13 +489,13 @@ zbar_image_scanner_t *zbar_image_scanner_create () #ifndef NO_STATS static inline void dump_stats (const zbar_image_scanner_t *iscn) { + int i; zprintf(1, "symbol sets allocated = %-4d\n", iscn->stat_syms_new); zprintf(1, " scanner syms in use = %-4d\trecycled = %-4d\n", iscn->stat_iscn_syms_inuse, iscn->stat_iscn_syms_recycle); zprintf(1, " image syms in use = %-4d\trecycled = %-4d\n", iscn->stat_img_syms_inuse, iscn->stat_img_syms_recycle); zprintf(1, "symbols allocated = %-4d\n", iscn->stat_sym_new); - int i; for(i = 0; i < RECYCLE_BUCKETS; i++) zprintf(1, " recycled[%d] = %-4d\n", i, iscn->stat_sym_recycle[i]); @@ -495,6 +504,7 @@ static inline void dump_stats (const zbar_image_scanner_t *iscn) void zbar_image_scanner_destroy (zbar_image_scanner_t *iscn) { + int i; dump_stats(iscn); if(iscn->syms) { if(iscn->syms->refcnt) @@ -509,7 +519,6 @@ void zbar_image_scanner_destroy (zbar_image_scanner_t *iscn) if(iscn->dcode) zbar_decoder_destroy(iscn->dcode); iscn->dcode = NULL; - int i; for(i = 0; i < RECYCLE_BUCKETS; i++) { zbar_symbol_t *sym, *next; for(sym = iscn->recycle[i].head; sym; sym = next) { @@ -597,30 +606,28 @@ static inline void quiet_border (zbar_image_scanner_t *iscn) #define movedelta(dx, dy) do { \ x += (dx); \ y += (dy); \ - p += (dx) + ((intptr_t)(dy) * w); \ + p += (dx) + ((uintptr_t)(dy) * w); \ } while(0); int zbar_scan_image (zbar_image_scanner_t *iscn, zbar_image_t *img) { + zbar_symbol_set_t *syms; + const uint8_t *data; + zbar_scanner_t *scn = iscn->scn; + unsigned w, h; + int density; + /* timestamp image * FIXME prefer video timestamp */ -#if _POSIX_TIMERS > 0 - struct timespec abstime; - clock_gettime(CLOCK_REALTIME, &abstime); - iscn->time = (abstime.tv_sec * 1000) + ((abstime.tv_nsec / 500000) + 1) / 2; -#else - struct timeval abstime; - gettimeofday(&abstime, NULL); - iscn->time = (abstime.tv_sec * 1000) + ((abstime.tv_usec / 500) + 1) / 2; -#endif + iscn->time = _zbar_timer_now(); #ifdef ENABLE_QRCODE _zbar_qr_reset(iscn->qr); #endif - /* get grayscale image, convert if necessary */ + /* image must be in grayscale format */ if(img->format != fourcc('Y','8','0','0') && img->format != fourcc('G','R','E','Y')) return(-1); @@ -628,7 +635,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, /* recycle previous scanner and image results */ zbar_image_scanner_recycle_image(iscn, img); - zbar_symbol_set_t *syms = iscn->syms; + syms = iscn->syms; if(!syms) { syms = iscn->syms = _zbar_symbol_set_create(); STAT(syms_new); @@ -638,26 +645,25 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, zbar_symbol_set_ref(syms, 2); img->syms = syms; - unsigned w = img->width; - unsigned h = img->height; - const uint8_t *data = img->data; + w = img->width; + h = img->height; + data = img->data; zbar_image_write_png(img, "debug.png"); svg_open("debug.svg", 0, 0, w, h); svg_image("debug.png", w, h); - zbar_scanner_t *scn = iscn->scn; - - int density = CFG(iscn, ZBAR_CFG_Y_DENSITY); + density = CFG(iscn, ZBAR_CFG_Y_DENSITY); if(density > 0) { - svg_group_start("scanner", 0, 1, 1, 0, 0); const uint8_t *p = data; int x = 0, y = 0; - iscn->dy = 0; int border = (((h - 1) % density) + 1) / 2; if(border > h / 2) border = h / 2; + svg_group_start("scanner", 0, 1, 1, 0, 0); + iscn->dy = 0; + movedelta(0, border); iscn->v = y; @@ -704,13 +710,13 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, density = CFG(iscn, ZBAR_CFG_X_DENSITY); if(density > 0) { - svg_group_start("scanner", 90, 1, -1, 0, 0); const uint8_t *p = data; int x = 0, y = 0; int border = (((w - 1) % density) + 1) / 2; if(border > w / 2) border = w / 2; + svg_group_start("scanner", 90, 1, -1, 0, 0); movedelta(border, 0); iscn->v = x; diff --git a/zbar/qrcode/qrdec.c b/zbar/qrcode/qrdec.c index 3349380..7e60f15 100644 --- a/zbar/qrcode/qrdec.c +++ b/zbar/qrcode/qrdec.c @@ -3,6 +3,7 @@ GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.*/ +#include #include #include #include @@ -2577,8 +2578,8 @@ static inline void qr_svg_points(const char *cls, qr_point *p, int n) { - svg_path_start(cls, 1, 0, 0); int i; + svg_path_start(cls, 1, 0, 0); for(i = 0; i < n; i++, p++) svg_path_moveto(SVG_ABS, p[0][0], p[0][1]); svg_path_end(); @@ -3913,7 +3914,7 @@ int _zbar_qr_decode (qr_reader *reader, zbar_image_scanner_t *iscn, zbar_image_t *img) { - int nqrdata = 0; + int nqrdata = 0, ncenters; qr_finder_edge_pt *edge_pts = NULL; qr_finder_center *centers = NULL; @@ -3923,7 +3924,7 @@ int _zbar_qr_decode (qr_reader *reader, svg_group_start("finder", 0, 1. / (1 << QR_FINDER_SUBPREC), 0, 0, 0); - int ncenters = qr_finder_centers_locate(¢ers, &edge_pts, reader, 0, 0); + ncenters = qr_finder_centers_locate(¢ers, &edge_pts, reader, 0, 0); zprintf(14, "%dx%d finders, %d centers:\n", reader->finder_lines[0].nlines, diff --git a/zbar/qrcode/qrdectxt.c b/zbar/qrcode/qrdectxt.c index 7646bc7..fdbae89 100644 --- a/zbar/qrcode/qrdectxt.c +++ b/zbar/qrcode/qrdectxt.c @@ -3,6 +3,7 @@ GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.*/ +#include #include #include #include @@ -79,6 +80,10 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, int err; int j; int k; + zbar_symbol_t *syms = NULL, **sym = &syms; + qr_point dir; + int horiz; + /*Step 0: Collect the other QR codes belonging to this S-A group.*/ if(qrdata[i].sa_size){ unsigned sa_parity; @@ -138,7 +143,6 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, enc_list[2]=utf8_cd; eci_cd=(iconv_t)-1; err=0; - zbar_symbol_t *syms = NULL, **sym = &syms; for(j = 0; j < sa_size && !err; j++, sym = &(*sym)->next) { *sym = _zbar_image_scanner_alloc_sym(iscn, ZBAR_QRCODE, 0); (*sym)->datalen = sa_ntext; @@ -168,13 +172,11 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, sym_add_point(*sym, qrdataj->bbox[1][0], qrdataj->bbox[1][1]); /* approx symbol "up" direction */ - qr_point dir = { - qrdataj->bbox[0][0] - qrdataj->bbox[2][0] + - qrdataj->bbox[1][0] - qrdataj->bbox[3][0], - qrdataj->bbox[2][1] - qrdataj->bbox[0][1] + - qrdataj->bbox[3][1] - qrdataj->bbox[1][1], - }; - int horiz = abs(dir[0]) > abs(dir[1]); + dir[0] = (qrdataj->bbox[0][0] - qrdataj->bbox[2][0] + + qrdataj->bbox[1][0] - qrdataj->bbox[3][0]); + dir[1] = (qrdataj->bbox[2][1] - qrdataj->bbox[0][1] + + qrdataj->bbox[3][1] - qrdataj->bbox[1][1]); + horiz = abs(dir[0]) > abs(dir[1]); (*sym)->orient = horiz + 2 * (dir[1 - horiz] < 0); for(k=0;knentries&&!err;k++){ @@ -341,26 +343,27 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, } if(eci_cd!=(iconv_t)-1)iconv_close(eci_cd); if(!err){ + zbar_symbol_t *sa_sym; sa_text[sa_ntext++]='\0'; if(sa_ctext+1>sa_ntext){ sa_text=(char *)realloc(sa_text,sa_ntext*sizeof(*sa_text)); } - zbar_symbol_t *sa_sym; if(sa_size == 1) sa_sym = syms; else { + /* cheap out w/axis aligned bbox for now */ + int xmin = img->width, xmax = -2; + int ymin = img->height, ymax = -2; + /* create "virtual" container symbol for composite result */ sa_sym = _zbar_image_scanner_alloc_sym(iscn, ZBAR_QRCODE, 0); sa_sym->syms = _zbar_symbol_set_create(); sa_sym->syms->head = syms; - /* cheap out w/axis aligned bbox for now */ - int xmin = img->width, xmax = -2; - int ymin = img->height, ymax = -2; - /* fixup data references */ for(; syms; syms = syms->next) { + int next; _zbar_symbol_refcnt(syms, 1); if(syms->type == ZBAR_PARTIAL) sa_sym->type = ZBAR_PARTIAL; @@ -374,7 +377,7 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, if(ymax <= u) ymax = u + 1; } syms->data = sa_text + syms->datalen; - int next = (syms->next) ? syms->next->datalen : sa_ntext; + next = (syms->next) ? syms->next->datalen : sa_ntext; assert(next > syms->datalen); syms->datalen = next - syms->datalen - 1; } diff --git a/zbar/refcnt.h b/zbar/refcnt.h index 4f809af..d7fe912 100644 --- a/zbar/refcnt.h +++ b/zbar/refcnt.h @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown + * Copyright 2007-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -29,7 +29,7 @@ #if defined(_WIN32) # include -typedef volatile LONG refcnt_t; /* FIXME where did volatile come from? */ +typedef LONG refcnt_t; static inline int _zbar_refcnt (refcnt_t *cnt, int delta) diff --git a/zbar/scanner.c b/zbar/scanner.c index 3e932ce..d8b16c2 100644 --- a/zbar/scanner.c +++ b/zbar/scanner.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown + * Copyright 2007-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -23,6 +23,7 @@ #include #include /* malloc, free, abs */ +#include #include /* memset */ #include @@ -91,7 +92,7 @@ void zbar_scanner_destroy (zbar_scanner_t *scn) zbar_symbol_type_t zbar_scanner_reset (zbar_scanner_t *scn) { - memset(&scn->x, 0, sizeof(zbar_scanner_t) + (void*)scn - (void*)&scn->x); + memset(&scn->x, 0, sizeof(zbar_scanner_t) - offsetof(zbar_scanner_t, x)); scn->y1_thresh = scn->y1_min_thresh; if(scn->decoder) zbar_decoder_reset(scn->decoder); @@ -125,14 +126,15 @@ zbar_color_t zbar_scanner_get_color (const zbar_scanner_t *scn) static inline unsigned calc_thresh (zbar_scanner_t *scn) { /* threshold 1st to improve noise rejection */ - unsigned thresh = scn->y1_thresh; + unsigned dx, thresh = scn->y1_thresh; + unsigned long t; if((thresh <= scn->y1_min_thresh) || !scn->width) { dprintf(1, " tmin=%d", scn->y1_min_thresh); return(scn->y1_min_thresh); } /* slowly return threshold to min */ - unsigned dx = (scn->x << ZBAR_FIXED) - scn->last_edge; - unsigned long t = thresh * dx; + dx = (scn->x << ZBAR_FIXED) - scn->last_edge; + t = thresh * dx; t /= scn->width; t /= ZBAR_SCANNER_THRESH_FADE; dprintf(1, " thr=%d t=%ld x=%d last=%d.%d (%d)", @@ -174,14 +176,15 @@ static inline zbar_symbol_type_t process_edge (zbar_scanner_t *scn, inline zbar_symbol_type_t zbar_scanner_flush (zbar_scanner_t *scn) { + unsigned x; if(!scn->y1_sign) return(ZBAR_NONE); - unsigned x = (scn->x << ZBAR_FIXED) + ROUND; + x = (scn->x << ZBAR_FIXED) + ROUND; if(scn->cur_edge != x || scn->y1_sign > 0) { - dprintf(1, "flush0:"); zbar_symbol_type_t edge = process_edge(scn, -scn->y1_sign); + dprintf(1, "flush0:"); scn->cur_edge = x; scn->y1_sign = -scn->y1_sign; return(edge); @@ -203,7 +206,7 @@ zbar_symbol_type_t zbar_scanner_new_scan (zbar_scanner_t *scn) } /* reset scanner and associated decoder */ - memset(&scn->x, 0, sizeof(zbar_scanner_t) + (void*)scn - (void*)&scn->x); + memset(&scn->x, 0, sizeof(zbar_scanner_t) - offsetof(zbar_scanner_t, x)); scn->y1_thresh = scn->y1_min_thresh; if(scn->decoder) zbar_decoder_new_scan(scn->decoder); @@ -218,6 +221,8 @@ zbar_symbol_type_t zbar_scan_y (zbar_scanner_t *scn, register int x = scn->x; register int y0_1 = scn->y0[(x - 1) & 3]; register int y0_0 = y0_1; + register int y0_2, y0_3, y1_1, y2_1, y2_2; + zbar_symbol_type_t edge; if(x) { /* update weighted moving average */ y0_0 += ((int)((y - y0_1) * EWMA_WEIGHT)) >> ZBAR_FIXED; @@ -225,10 +230,10 @@ zbar_symbol_type_t zbar_scan_y (zbar_scanner_t *scn, } else y0_0 = y0_1 = scn->y0[0] = scn->y0[1] = scn->y0[2] = scn->y0[3] = y; - register int y0_2 = scn->y0[(x - 2) & 3]; - register int y0_3 = scn->y0[(x - 3) & 3]; + y0_2 = scn->y0[(x - 2) & 3]; + y0_3 = scn->y0[(x - 3) & 3]; /* 1st differential @ x-1 */ - register int y1_1 = y0_1 - y0_2; + y1_1 = y0_1 - y0_2; { register int y1_2 = y0_2 - y0_3; if((abs(y1_1) < abs(y1_2)) && @@ -237,13 +242,13 @@ zbar_symbol_type_t zbar_scan_y (zbar_scanner_t *scn, } /* 2nd differentials @ x-1 & x-2 */ - register int y2_1 = y0_0 - (y0_1 * 2) + y0_2; - register int y2_2 = y0_1 - (y0_2 * 2) + y0_3; + y2_1 = y0_0 - (y0_1 * 2) + y0_2; + y2_2 = y0_1 - (y0_2 * 2) + y0_3; dprintf(1, "scan: x=%d y=%d y0=%d y1=%d y2=%d", x, y, y0_1, y1_1, y2_1); - zbar_symbol_type_t edge = ZBAR_NONE; + edge = ZBAR_NONE; /* 2nd zero-crossing is 1st local min/max - could be edge */ if((!y2_1 || ((y2_1 > 0) ? y2_2 < 0 : y2_2 > 0)) && @@ -256,6 +261,7 @@ zbar_symbol_type_t zbar_scan_y (zbar_scanner_t *scn, edge = process_edge(scn, y1_1); if(y1_rev || (abs(scn->y1_sign) < abs(y1_1))) { + int d; scn->y1_sign = y1_1; /* adaptive thresholding */ @@ -266,7 +272,7 @@ zbar_symbol_type_t zbar_scan_y (zbar_scanner_t *scn, scn->y1_thresh = scn->y1_min_thresh; /* update current edge */ - int d = y2_1 - y2_2; + d = y2_1 - y2_2; scn->cur_edge = 1 << ZBAR_FIXED; if(!d) scn->cur_edge >>= 1; @@ -298,14 +304,14 @@ void zbar_scanner_get_state (const zbar_scanner_t *scn, register int y0_0 = scn->y0[(scn->x - 1) & 3]; register int y0_1 = scn->y0[(scn->x - 2) & 3]; register int y0_2 = scn->y0[(scn->x - 3) & 3]; + zbar_scanner_t *mut_scn; if(x) *x = scn->x - 1; - if(cur_edge) *cur_edge = scn->cur_edge; if(last_edge) *last_edge = scn->last_edge; if(y0) *y0 = y0_1; if(y1) *y1 = y0_1 - y0_2; if(y2) *y2 = y0_0 - (y0_1 * 2) + y0_2; /* NB not quite accurate (uses updated x) */ - zbar_scanner_t *mut_scn = (zbar_scanner_t*)scn; + mut_scn = (zbar_scanner_t*)scn; if(y1_thresh) *y1_thresh = calc_thresh(mut_scn); dprintf(1, "\n"); } diff --git a/zbar/symbol.c b/zbar/symbol.c index b54360e..da87595 100644 --- a/zbar/symbol.c +++ b/zbar/symbol.c @@ -212,6 +212,9 @@ char *zbar_symbol_xml (const zbar_symbol_t *sym, char **buf, unsigned *len) { + unsigned int datalen, maxlen; + int i, n = 0; + const char *type = zbar_get_symbol_name(sym->type); const char *orient = zbar_get_orientation_name(sym->orient); @@ -220,7 +223,6 @@ char *zbar_symbol_xml (const zbar_symbol_t *sym, char binary = ((data[0] == 0xff && data[1] == 0xfe) || (data[0] == 0xfe && data[1] == 0xff) || !strncmp(sym->data, "datalen; i++) { char c = sym->data[i]; binary = ((c < 0x20 && ((~0x00002600 >> c) & 1)) || @@ -229,14 +231,14 @@ char *zbar_symbol_xml (const zbar_symbol_t *sym, sym->data[i + 2] == '>')); } - unsigned datalen = strlen(sym->data); + datalen = strlen(sym->data); if(binary) datalen = (sym->datalen + 2) / 3 * 4 + sym->datalen / 57 + 3; - unsigned maxlen = (strlen(xmlfmt[0]) + strlen(xmlfmt[1]) + - strlen(xmlfmt[2]) + strlen(xmlfmt[4]) + - strlen(xmlfmt[6]) + strlen(type) + strlen(orient) + - datalen + MAX_INT_DIGITS + 1); + maxlen = (strlen(xmlfmt[0]) + strlen(xmlfmt[1]) + + strlen(xmlfmt[2]) + strlen(xmlfmt[4]) + + strlen(xmlfmt[6]) + strlen(type) + strlen(orient) + + datalen + MAX_INT_DIGITS + 1); if(binary) maxlen += (strlen(xmlfmt[3]) + strlen(xmlfmt[5]) + MAX_INT_DIGITS); @@ -248,8 +250,6 @@ char *zbar_symbol_xml (const zbar_symbol_t *sym, *len = maxlen; } - int n = 0; - TMPL_FMT(0, type, sym->quality, orient); if(sym->cache_count) diff --git a/zbar/timer.h b/zbar/timer.h index 3f33f29..ea4df85 100644 --- a/zbar/timer.h +++ b/zbar/timer.h @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown + * Copyright 2007-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -24,7 +24,9 @@ #define _ZBAR_TIMER_H_ #include -#include /* gettimeofday */ +#ifdef HAVE_SYS_TIME_H +# include /* gettimeofday */ +#endif /* platform timer abstraction * @@ -41,6 +43,12 @@ typedef struct timespec zbar_timer_t; +static inline int _zbar_timer_now () +{ + clock_gettime(CLOCK_REALTIME, timer); + return(now.tv_sec * 1000 + now.tv_nsec / 1000000); +} + static inline zbar_timer_t *_zbar_timer_init (zbar_timer_t *timer, int delay) { @@ -56,13 +64,14 @@ static inline zbar_timer_t *_zbar_timer_init (zbar_timer_t *timer, static inline int _zbar_timer_check (zbar_timer_t *timer) { + struct timespec now; + int delay; if(!timer) return(-1); - struct timespec now; clock_gettime(CLOCK_REALTIME, &now); - int delay = ((timer->tv_sec - now.tv_sec) * 1000 + - (timer->tv_nsec - now.tv_nsec) / 1000000); + delay = ((timer->tv_sec - now.tv_sec) * 1000 + + (timer->tv_nsec - now.tv_nsec) / 1000000); return((delay >= 0) ? delay : 0); } @@ -73,6 +82,11 @@ static inline int _zbar_timer_check (zbar_timer_t *timer) typedef DWORD zbar_timer_t; +static inline int _zbar_timer_now () +{ + return(timeGetTime()); +} + static inline zbar_timer_t *_zbar_timer_init (zbar_timer_t *timer, int delay) { @@ -85,18 +99,26 @@ static inline zbar_timer_t *_zbar_timer_init (zbar_timer_t *timer, static inline int _zbar_timer_check (zbar_timer_t *timer) { + int delay; if(!timer) return(INFINITE); - int delay = *timer - timeGetTime(); + delay = *timer - timeGetTime(); return((delay >= 0) ? delay : 0); } -#else +#elif defined(HAVE_SYS_TIME_H) typedef struct timeval zbar_timer_t; +static inline int _zbar_timer_now () +{ + struct timeval now; + gettimeofday(&now, NULL); + return(now.tv_sec * 1000 + now.tv_usec / 1000); +} + static inline zbar_timer_t *_zbar_timer_init (zbar_timer_t *timer, int delay) { @@ -112,15 +134,17 @@ static inline zbar_timer_t *_zbar_timer_init (zbar_timer_t *timer, static inline int _zbar_timer_check (zbar_timer_t *timer) { + struct timeval now; if(!timer) return(-1); - struct timeval now; gettimeofday(&now, NULL); return((timer->tv_sec - now.tv_sec) * 1000 + (timer->tv_usec - now.tv_usec) / 1000); } +#else +# error "unable to find a timer interface" #endif #endif diff --git a/zbar/video.c b/zbar/video.c index 01afb26..9077071 100644 --- a/zbar/video.c +++ b/zbar/video.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown + * Copyright 2007-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -58,6 +58,7 @@ static void _zbar_video_recycle_shadow (zbar_image_t *img) zbar_video_t *zbar_video_create () { zbar_video_t *vdo = calloc(1, sizeof(zbar_video_t)); + int i; if(!vdo) return(NULL); err_init(&vdo->err, ZBAR_MOD_VIDEO); @@ -73,7 +74,6 @@ zbar_video_t *zbar_video_create () return(NULL); } - int i; for(i = 0; i < ZBAR_VIDEO_IMAGES_MAX; i++) { zbar_image_t *img = vdo->images[i] = zbar_image_create(); if(!img) { @@ -130,6 +130,8 @@ void zbar_video_destroy (zbar_video_t *vdo) int zbar_video_open (zbar_video_t *vdo, const char *dev) { + char *ldev = NULL; + int rc; zbar_video_enable(vdo, 0); video_lock(vdo); if(vdo->intf != VIDEO_INVALID) { @@ -145,7 +147,6 @@ int zbar_video_open (zbar_video_t *vdo, if(!dev) return(0); - char *ldev = NULL; if((unsigned char)dev[0] < 0x10) { /* default linux device, overloaded for other platforms */ int id = dev[0]; @@ -153,7 +154,7 @@ int zbar_video_open (zbar_video_t *vdo, ldev[10] = '0' + id; } - int rc = _zbar_video_open(vdo, dev); + rc = _zbar_video_open(vdo, dev); if(ldev) free(ldev); @@ -227,7 +228,7 @@ uint32_t zbar_video_get_format (const zbar_video_t *vdo) static inline int video_init_images (zbar_video_t *vdo) { - + int i; assert(vdo->datalen); if(vdo->iomode != VIDEO_MMAP) { assert(!vdo->buf); @@ -240,16 +241,15 @@ static inline int video_init_images (zbar_video_t *vdo) (vdo->iomode == VIDEO_READWRITE) ? "READ" : "USERPTR", vdo->buflen); } - int i; for(i = 0; i < vdo->num_images; i++) { zbar_image_t *img = vdo->images[i]; img->format = vdo->format; img->width = vdo->width; img->height = vdo->height; if(vdo->iomode != VIDEO_MMAP) { - img->datalen = vdo->datalen; unsigned long offset = i * vdo->datalen; - img->data = vdo->buf + offset; + img->datalen = vdo->datalen; + img->data = (uint8_t*)vdo->buf + offset; zprintf(2, " [%02d] @%08lx\n", i, offset); } } @@ -259,6 +259,9 @@ static inline int video_init_images (zbar_video_t *vdo) int zbar_video_init (zbar_video_t *vdo, unsigned long fmt) { +#ifdef HAVE_LIBJPEG + const zbar_format_def_t *vidfmt; +#endif if(vdo->initialized) /* FIXME re-init different format? */ return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, @@ -270,8 +273,9 @@ int zbar_video_init (zbar_video_t *vdo, if(video_init_images(vdo)) return(-1); #ifdef HAVE_LIBJPEG - const zbar_format_def_t *vidfmt = _zbar_format_lookup(fmt); + vidfmt = _zbar_format_lookup(fmt); if(vidfmt && vidfmt->group == ZBAR_FMT_JPEG) { + zbar_image_t *img; /* prepare for decoding */ if(!vdo->jpeg) vdo->jpeg = _zbar_jpeg_decomp_create(); @@ -279,7 +283,7 @@ int zbar_video_init (zbar_video_t *vdo, zbar_image_destroy(vdo->jpeg_img); /* create intermediate image for decoder to use*/ - zbar_image_t *img = vdo->jpeg_img = zbar_image_create(); + img = vdo->jpeg_img = zbar_image_create(); img->format = fourcc('Y','8','0','0'); img->width = vdo->width; img->height = vdo->height; @@ -333,6 +337,9 @@ int zbar_video_enable (zbar_video_t *vdo, zbar_image_t *zbar_video_next_image (zbar_video_t *vdo) { + unsigned frame; + zbar_image_t *img; + if(video_lock(vdo)) return(NULL); if(!vdo->active) { @@ -340,8 +347,8 @@ zbar_image_t *zbar_video_next_image (zbar_video_t *vdo) return(NULL); } - unsigned frame = vdo->frame++; - zbar_image_t *img = vdo->dq(vdo); + frame = vdo->frame++; + img = vdo->dq(vdo); if(img) { img->seq = frame; if(vdo->num_images < 2) { diff --git a/zbar/window.c b/zbar/window.c index e01077d..c2cac51 100644 --- a/zbar/window.c +++ b/zbar/window.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown + * Copyright 2007-2010 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -23,8 +23,11 @@ #include "window.h" #include "image.h" +#include "timer.h" #include /* clock_gettime */ -#include /* gettimeofday */ +#ifdef HAVE_SYS_TIME_H +# include /* gettimeofday */ +#endif zbar_window_t *zbar_window_create () { @@ -117,20 +120,11 @@ static inline int window_draw_overlay (zbar_window_t *w) if(w->overlay >= 2) { /* calculate/display frame rate */ - unsigned long time; -#if _POSIX_TIMERS > 0 - struct timespec abstime; - clock_gettime(CLOCK_REALTIME, &abstime); - time = (abstime.tv_sec * 1000) + ((abstime.tv_nsec / 500000) + 1) / 2; -#else - struct timeval abstime; - gettimeofday(&abstime, NULL); - time = (abstime.tv_sec * 1000) + ((abstime.tv_usec / 500) + 1) / 2; -#endif - point_t p = { -8, -1 }; - char text[32]; + unsigned long time = _zbar_timer_now(); if(w->time) { int avg = w->time_avg = (w->time_avg + time - w->time) / 2; + point_t p = { -8, -1 }; + char text[32]; sprintf(text, "%d.%01d fps", 1000 / avg, (10000 / avg) % 10); _zbar_window_draw_text(w, 3, p, text); } @@ -141,6 +135,8 @@ static inline int window_draw_overlay (zbar_window_t *w) inline int zbar_window_redraw (zbar_window_t *w) { + int rc = 0; + zbar_image_t *img; if(window_lock(w)) return(-1); if(!w->display || _zbar_window_begin(w)) { @@ -148,8 +144,7 @@ inline int zbar_window_redraw (zbar_window_t *w) return(-1); } - int rc = 0; - zbar_image_t *img = w->image; + img = w->image; if(w->init && w->draw_image && img) { int format_change = (w->src_format != img->format && w->format != img->format); @@ -163,6 +158,7 @@ inline int zbar_window_redraw (zbar_window_t *w) } if(!rc && (format_change || !w->scaled_size.x || !w->dst_width)) { + point_t size = { w->width, w->height }; zprintf(24, "init: src=%.4s(%08x) %dx%d dst=%.4s(%08x) %dx%d\n", (char*)&w->src_format, w->src_format, w->src_width, w->src_height, @@ -173,7 +169,6 @@ inline int zbar_window_redraw (zbar_window_t *w) w->src_height = img->height; } - point_t size = { w->width, w->height }; if(size.x > w->max_width) size.x = w->max_width; if(size.y > w->max_height) @@ -226,9 +221,10 @@ inline int zbar_window_redraw (zbar_window_t *w) } if(!rc) { + point_t org; rc = w->draw_image(w, img); - point_t org = w->scaled_offset; + org = w->scaled_offset; if(org.x > 0) { point_t p = { 0, org.y }; point_t s = { org.x, w->scaled_size.y }; @@ -300,9 +296,10 @@ void zbar_window_set_overlay (zbar_window_t *w, int zbar_window_get_overlay (const zbar_window_t *w) { zbar_window_t *ncw = (zbar_window_t*)w; + int lvl; if(window_lock(ncw)) return(-1); - int lvl = w->overlay; + lvl = w->overlay; (void)window_unlock(ncw); return(lvl); } From 87d022de9d7d91170fc9d997a658309df3959948 Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 7 Apr 2010 08:57:57 -0400 Subject: [PATCH 192/328] fix compile errors --- include/zbar/Symbol.h | 3 +++ zbar/timer.h | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/zbar/Symbol.h b/include/zbar/Symbol.h index afe26f1..cd881f4 100644 --- a/include/zbar/Symbol.h +++ b/include/zbar/Symbol.h @@ -178,6 +178,7 @@ class Symbol { _sym->ref(-1); _sym = iter._sym; _index = iter._index; + return(*this); } /// truth testing. @@ -269,6 +270,7 @@ class Symbol { zbar_symbol_ref(sym, 1); ref(-1); init(sym); + return(*this); } /// truth testing. @@ -450,6 +452,7 @@ class SymbolIterator { _syms = iter._syms; _sym = iter._sym; + return(*this); } bool operator! () const diff --git a/zbar/timer.h b/zbar/timer.h index ea4df85..d465926 100644 --- a/zbar/timer.h +++ b/zbar/timer.h @@ -45,7 +45,8 @@ typedef struct timespec zbar_timer_t; static inline int _zbar_timer_now () { - clock_gettime(CLOCK_REALTIME, timer); + struct timespec now; + clock_gettime(CLOCK_REALTIME, &now); return(now.tv_sec * 1000 + now.tv_nsec / 1000000); } From 6627d89ebb15c75c133c157a682163ee4f96ed9f Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 10 May 2010 16:49:01 -0400 Subject: [PATCH 193/328] relax Code 39 width ratio checks --- ChangeLog | 1 + zbar/decoder/code39.c | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 02558ea..607e14d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * relax Code 39 width ratio checks * core library portability improvements - remove some unnecessary C99 syntax - add configure checks for errno diff --git a/zbar/decoder/code39.c b/zbar/decoder/code39.c index 0d8a133..74f961e 100644 --- a/zbar/decoder/code39.c +++ b/zbar/decoder/code39.c @@ -130,11 +130,11 @@ static inline unsigned char code39_decode1 (unsigned char enc, unsigned e, unsigned s) { - unsigned char E = decode_e(e, s, 36); - if(E > 7) + unsigned char E = decode_e(e, s, 72); + if(E > 18) return(0xff); enc <<= 1; - if(E > 2) { + if(E > 6) { enc |= 1; dprintf(2, "1"); } From b7c6240d77a7ec4a2bcbf7fda8ee6cd0a4512216 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 20 May 2010 10:02:36 -0400 Subject: [PATCH 194/328] remove doc hints about GFDL --- ChangeLog | 1 + doc/manual.xml | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 607e14d..292e4b6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * remove doc hints about GFDL * relax Code 39 width ratio checks * core library portability improvements - remove some unnecessary C99 syntax diff --git a/doc/manual.xml b/doc/manual.xml index 98b185f..549d42c 100644 --- a/doc/manual.xml +++ b/doc/manual.xml @@ -33,7 +33,6 @@ Jeff Brown All Rights Reserved - @@ -48,7 +47,4 @@ &refzbarimg; - - - From 9584483e6f941ac26299d156375819bc871027d0 Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 24 May 2010 18:55:06 -0400 Subject: [PATCH 195/328] apply LGPL to API docs --- doc/api/footer.html | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/doc/api/footer.html b/doc/api/footer.html index d9529a3..2eefbb2 100644 --- a/doc/api/footer.html +++ b/doc/api/footer.html @@ -9,9 +9,12 @@
spadix@users.sourceforge.net
-

Copyright 2008-2009 (c) Jeff Brown - All Rights Reserved.

-

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.

+

Copyright 2008-2010 (c) Jeff Brown

+

This documentation is part of the ZBar Barcode Reader; you can +redistribute it and/or modify it under the terms of the +GNU +Lesser General Public License as published by the Free Software +Foundation; either version 2.1 of the License, or (at your option) any +later version.

From 2b2c10cb992e695c4df97ae9ceb2340bb297b9e8 Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 28 May 2010 13:54:07 -0400 Subject: [PATCH 196/328] fix couple of leaks --- ChangeLog | 1 + zbar/img_scanner.c | 4 ++-- zbar/processor.c | 4 ++++ zbar/qrcode/qrdectxt.c | 2 -- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index e0d1ce6..c9df860 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * fix couple of leaks * remove doc hints about GFDL (bug #3004411) - apply LGPL to API docs * relax Code 39 width ratio checks diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 89a711b..c7cff4e 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -653,6 +653,8 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, svg_open("debug.svg", 0, 0, w, h); svg_image("debug.png", w, h); + zbar_scanner_new_scan(scn); + density = CFG(iscn, ZBAR_CFG_Y_DENSITY); if(density > 0) { const uint8_t *p = data; @@ -667,8 +669,6 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, movedelta(0, border); iscn->v = y; - zbar_scanner_new_scan(scn); - while(y < h) { zprintf(128, "img_x+: %04d,%04d @%p\n", x, y, p); svg_path_start("vedge", 1. / 32, 0, y + 0.5); diff --git a/zbar/processor.c b/zbar/processor.c index 3bd57a3..9801e56 100644 --- a/zbar/processor.c +++ b/zbar/processor.c @@ -289,6 +289,10 @@ void zbar_processor_destroy (zbar_processor_t *proc) { zbar_processor_init(proc, NULL, 0); + if(proc->syms) { + zbar_symbol_set_ref(proc->syms, -1); + proc->syms = NULL; + } if(proc->scanner) { zbar_image_scanner_destroy(proc->scanner); proc->scanner = NULL; diff --git a/zbar/qrcode/qrdectxt.c b/zbar/qrcode/qrdectxt.c index fdbae89..c6d400e 100644 --- a/zbar/qrcode/qrdectxt.c +++ b/zbar/qrcode/qrdectxt.c @@ -51,12 +51,10 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, const qr_code_data *qrdata; int nqrdata; unsigned char *mark; - char **text; int ntext; int i; qrdata=_qrlist->qrdata; nqrdata=_qrlist->nqrdata; - text=(char **)malloc(nqrdata*sizeof(*text)); mark=(unsigned char *)calloc(nqrdata,sizeof(*mark)); ntext=0; /*This is the encoding the standard says is the default.*/ From 001c8ed4ac97be411aa72fa7e48e10f77ef803f8 Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 4 Jun 2010 16:55:39 -0400 Subject: [PATCH 197/328] add support for scanning partial images (cropping) - update c++, python, perl, java bindings and tests --- ChangeLog | 2 + include/zbar.h | 31 +++++++++ include/zbar/Image.h | 29 +++++++++ java/Makefile.am | 3 +- java/net/sourceforge/zbar/Image.java | 15 +++++ java/net/sourceforge/zbar/Symbol.java | 25 ++++---- java/test/TestImage.java | 39 +++++++++++- java/test/TestScanImage.java | 10 +-- java/zbarjni.c | 90 +++++++++++++++++++++++++-- perl/ZBar.xs | 25 +++++++- perl/t/Image.t | 22 ++++++- python/image.c | 86 +++++++++++++++++++------ python/test/test_zbar.py | 34 ++++++++++ zbar/convert.c | 14 +++++ zbar/image.c | 48 +++++++++++++- zbar/image.h | 2 + zbar/img_scanner.c | 46 +++++++++----- 17 files changed, 457 insertions(+), 64 deletions(-) diff --git a/ChangeLog b/ChangeLog index c9df860..988c521 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * 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 diff --git a/include/zbar.h b/include/zbar.h index a10157f..9e26eb4 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -515,6 +515,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 */ @@ -564,12 +583,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) diff --git a/include/zbar/Image.h b/include/zbar/Image.h index 9d518ce..1ff9289 100644 --- a/include/zbar/Image.h +++ b/include/zbar/Image.h @@ -178,6 +178,15 @@ class Image { 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, @@ -186,6 +195,26 @@ class Image { 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 diff --git a/java/Makefile.am b/java/Makefile.am index eadb638..8943917 100644 --- a/java/Makefile.am +++ b/java/Makefile.am @@ -16,8 +16,7 @@ zbar_jar_SRCS = \ $(PKG)/Symbol.java $(PKG)/SymbolIterator.java $(PKG)/SymbolSet.java \ $(PKG)/Image.java $(PKG)/ImageScanner.java -zbar_jar_CLASSES = $(zbar_jar_SRCS:.java=.class) \ - $(PKG)/Symbol\$$Rect.class +zbar_jar_CLASSES = $(zbar_jar_SRCS:.java=.class) test_SRCS = test/TestImage.java test/TestImageScanner.java \ test/TestScanImage.java diff --git a/java/net/sourceforge/zbar/Image.java b/java/net/sourceforge/zbar/Image.java index 9b93c40..8227a4f 100644 --- a/java/net/sourceforge/zbar/Image.java +++ b/java/net/sourceforge/zbar/Image.java @@ -125,9 +125,24 @@ public Image convert (String format) /** Retrieve the height of the image. */ public native int getHeight(); + /** Retrieve the size of the image. */ + public native int[] getSize(); + /** Specify the pixel size of the image. */ public native void setSize(int width, int height); + /** Specify the pixel size of the image. */ + public native void setSize(int[] size); + + /** Retrieve the crop region of the image. */ + public native int[] getCrop(); + + /** Specify the crop region of the image. */ + public native void setCrop(int x, int y, int width, int height); + + /** Specify the crop region of the image. */ + public native void setCrop(int[] crop); + /** Retrieve the image sample data. */ public native byte[] getData(); diff --git a/java/net/sourceforge/zbar/Symbol.java b/java/net/sourceforge/zbar/Symbol.java index d5d2b83..185c13f 100644 --- a/java/net/sourceforge/zbar/Symbol.java +++ b/java/net/sourceforge/zbar/Symbol.java @@ -30,11 +30,6 @@ */ public class Symbol { - public class Rect - { - public int x, y, width, height; - }; - /** No symbol decoded. */ public static final int NONE = 0; /** Symbol detected but not decoded. */ @@ -133,13 +128,13 @@ public int getType () /** Retrieve an approximate, axis-aligned bounding box for the * symbol. */ - public Rect getBounds () + public int[] getBounds () { int n = getLocationSize(peer); if(n <= 0) return(null); - Rect bounds = new Rect(); + int[] bounds = new int[4]; int xmin = Integer.MAX_VALUE; int xmax = Integer.MIN_VALUE; int ymin = Integer.MAX_VALUE; @@ -154,10 +149,10 @@ public Rect getBounds () if(ymin > y) ymin = y; if(ymax < y) ymax = y; } - bounds.x = xmin; - bounds.y = ymin; - bounds.width = xmax - xmin; - bounds.height = ymax - ymin; + bounds[0] = xmin; + bounds[1] = ymin; + bounds[2] = xmax - xmin; + bounds[3] = ymax - ymin; return(bounds); } @@ -165,6 +160,14 @@ public Rect getBounds () private native int getLocationX(long peer, int idx); private native int getLocationY(long peer, int idx); + public int[] getLocationPoint (int idx) + { + int[] p = new int[2]; + p[0] = getLocationX(peer, idx); + p[1] = getLocationY(peer, idx); + return(p); + } + /** Retrieve general axis-aligned, orientation of decoded * symbol. */ diff --git a/java/test/TestImage.java b/java/test/TestImage.java index 136d953..9666f2b 100644 --- a/java/test/TestImage.java +++ b/java/test/TestImage.java @@ -52,9 +52,44 @@ public class TestImage { assertEquals(0, image.getWidth()); assertEquals(0, image.getHeight()); + image.setSize(640, 480); - assertEquals(640, image.getWidth()); - assertEquals(480, image.getHeight()); + int[] size0 = { 640, 480 }; + assertArrayEquals(size0, image.getSize()); + + int[] size1 = { 320, 240 }; + image.setSize(size1); + assertEquals(320, image.getWidth()); + assertEquals(240, image.getHeight()); + } + + @Test public void crop () + { + int[] zeros = { 0, 0, 0, 0 }; + assertArrayEquals(zeros, image.getCrop()); + + image.setSize(123, 456); + int[] crop0 = { 0, 0, 123, 456 }; + assertArrayEquals(crop0, image.getCrop()); + + image.setCrop(1, 2, 34, 56); + int[] crop1 = { 1, 2, 34, 56 }; + assertArrayEquals(crop1, image.getCrop()); + + image.setCrop(-20, -20, 200, 500); + assertArrayEquals(crop0, image.getCrop()); + + int[] crop2 = { 7, 8, 90, 12}; + image.setCrop(crop2); + assertArrayEquals(crop2, image.getCrop()); + + image.setSize(654, 321); + int[] crop3 = { 0, 0, 654, 321 }; + assertArrayEquals(crop3, image.getCrop()); + + int[] crop4 = { -10, -10, 700, 400 }; + image.setCrop(crop4); + assertArrayEquals(crop3, image.getCrop()); } @Test public void format () diff --git a/java/test/TestScanImage.java b/java/test/TestScanImage.java index d27c04c..86ed024 100644 --- a/java/test/TestScanImage.java +++ b/java/test/TestScanImage.java @@ -103,11 +103,11 @@ protected void checkResults (SymbolSet syms) byte[] exp = { '6','2','6','8','9','6','4','9','7','7','8','0','4' }; assertArrayEquals(exp, bytes); - Symbol.Rect r = sym.getBounds(); - assertTrue(r.x > 6); - assertTrue(r.y > 6); - assertTrue(r.width < 102); - assertTrue(r.height < 73); + int[] r = sym.getBounds(); + assertTrue(r[0] > 6); + assertTrue(r[1] > 6); + assertTrue(r[2] < 102); + assertTrue(r[3] < 73); assertEquals(Orientation.UP, sym.getOrientation()); } diff --git a/java/zbarjni.c b/java/zbarjni.c index 3da4e4d..e61e666 100644 --- a/java/zbarjni.c +++ b/java/zbarjni.c @@ -394,15 +394,97 @@ Java_net_sourceforge_zbar_Image_getHeight (JNIEnv *env, return(zbar_image_get_height(GET_PEER(Image, obj))); } +JNIEXPORT jobject JNICALL +Java_net_sourceforge_zbar_Image_getSize (JNIEnv *env, + jobject obj) +{ + jintArray size = (*env)->NewIntArray(env, 2); + if(!size) + return(NULL); + + unsigned dims[2]; + zbar_image_get_size(GET_PEER(Image, obj), dims, dims + 1); + jint jdims[2] = { dims[0], dims[1] }; + (*env)->SetIntArrayRegion(env, size, 0, 2, jdims); + return(size); +} + JNIEXPORT void JNICALL -Java_net_sourceforge_zbar_Image_setSize (JNIEnv *env, - jobject obj, - jint width, - jint height) +Java_net_sourceforge_zbar_Image_setSize__II (JNIEnv *env, + jobject obj, + jint width, + jint height) { + if(width < 0) width = 0; + if(height < 0) height = 0; zbar_image_set_size(GET_PEER(Image, obj), width, height); } +JNIEXPORT void JNICALL +Java_net_sourceforge_zbar_Image_setSize___3I (JNIEnv *env, + jobject obj, + jintArray size) +{ + if((*env)->GetArrayLength(env, size) != 2) + throw_exc(env, "java/lang/IllegalArgumentException", + "size must be an array of two ints"); + jint dims[2]; + (*env)->GetIntArrayRegion(env, size, 0, 2, dims); + if(dims[0] < 0) dims[0] = 0; + if(dims[1] < 0) dims[1] = 0; + zbar_image_set_size(GET_PEER(Image, obj), dims[0], dims[1]); +} + +JNIEXPORT jobject JNICALL +Java_net_sourceforge_zbar_Image_getCrop (JNIEnv *env, + jobject obj) +{ + jintArray crop = (*env)->NewIntArray(env, 4); + if(!crop) + return(NULL); + + unsigned dims[4]; + zbar_image_get_crop(GET_PEER(Image, obj), dims, dims + 1, + dims + 2, dims + 3); + jint jdims[4] = { dims[0], dims[1], dims[2], dims[3] }; + (*env)->SetIntArrayRegion(env, crop, 0, 4, jdims); + return(crop); +} + +#define VALIDATE_CROP(u, m) \ + if((u) < 0) { \ + (m) += (u); \ + (u) = 0; \ + } + +JNIEXPORT void JNICALL +Java_net_sourceforge_zbar_Image_setCrop__IIII (JNIEnv *env, + jobject obj, + jint x, jint y, + jint w, jint h) +{ + VALIDATE_CROP(x, w); + VALIDATE_CROP(y, h); + zbar_image_set_crop(GET_PEER(Image, obj), x, y, w, h); +} + +JNIEXPORT void JNICALL +Java_net_sourceforge_zbar_Image_setCrop___3I (JNIEnv *env, + jobject obj, + jintArray crop) +{ + if((*env)->GetArrayLength(env, crop) != 4) + throw_exc(env, "java/lang/IllegalArgumentException", + "crop must be an array of four ints"); + jint dims[4]; + (*env)->GetIntArrayRegion(env, crop, 0, 4, dims); + VALIDATE_CROP(dims[0], dims[2]); + VALIDATE_CROP(dims[1], dims[3]); + zbar_image_set_crop(GET_PEER(Image, obj), + dims[0], dims[1], dims[2], dims[3]); +} +#undef VALIDATE_CROP + JNIEXPORT jobject JNICALL Java_net_sourceforge_zbar_Image_getData (JNIEnv *env, jobject obj) diff --git a/perl/ZBar.xs b/perl/ZBar.xs index 1eaad02..adad6bd 100644 --- a/perl/ZBar.xs +++ b/perl/ZBar.xs @@ -418,6 +418,19 @@ get_size(image) mPUSHu(zbar_image_get_width(image)); mPUSHu(zbar_image_get_height(image)); +void +get_crop(image) + Barcode::ZBar::Image image + PREINIT: + unsigned x, y, w, h; + PPCODE: + zbar_image_get_crop(image, &x, &y, &w, &h); + EXTEND(SP, 4); + mPUSHu(x); + mPUSHu(y); + mPUSHu(w); + mPUSHu(h); + SV * zbar_image_get_data(image) Barcode::ZBar::Image image @@ -446,8 +459,16 @@ zbar_image_set_sequence(image, seq_num) void zbar_image_set_size(image, width, height) Barcode::ZBar::Image image - unsigned width - unsigned height + int width + if(width < 0) width = 0; + int height + if(height < 0) height = 0; + +void +zbar_image_set_crop(image, x, y, width, height) + Barcode::ZBar::Image image + int x + if(x < 0) { width += x; x = 0; } + int y + if(y < 0) { height += y; y = 0; } + int width + int height void zbar_image_set_data(image, data) diff --git a/perl/t/Image.t b/perl/t/Image.t index a8ce007..7876f72 100755 --- a/perl/t/Image.t +++ b/perl/t/Image.t @@ -3,7 +3,7 @@ use warnings; use strict; -use Test::More tests => 23; +use Test::More tests => 27; ######################### @@ -48,6 +48,26 @@ is_deeply([$image->get_size()], [114, 80], 'size accessors'); ######################### +$image->set_crop(20, 20, 74, 40); +is_deeply([$image->get_crop()], [20, 20, 74, 40], 'crop accessors'); + +######################### + +$image->set_crop(-57, -40, 228, 160); +is_deeply([$image->get_crop()], [0, 0, 114, 80], 'crop clipping'); + +######################### + +$image->set_crop(10, 10, 94, 60); +is_deeply([$image->get_crop()], [10, 10, 94, 60], 'crop accessors'); + +######################### + +$image->set_size(114, 80); +is_deeply([$image->get_crop()], [0, 0, 114, 80], 'crop reset'); + +######################### + # FIXME avoid skipping these (eg embed image vs ImageMagick) SKIP: { eval { require Image::Magick }; diff --git a/python/image.c b/python/image.c index 2d44055..a617d4f 100644 --- a/python/image.c +++ b/python/image.c @@ -156,9 +156,9 @@ static PyObject* image_get_size (zbarImage *self, void *closure) { - unsigned int width = zbar_image_get_width(self->zimg); - unsigned int height = zbar_image_get_height(self->zimg); - return(PyTuple_Pack(2, PyInt_FromLong(width), PyInt_FromLong(height))); + unsigned int w, h; + zbar_image_get_size(self->zimg, &w, &h); + return(PyTuple_Pack(2, PyInt_FromLong(w), PyInt_FromLong(h))); } static int @@ -170,33 +170,82 @@ image_set_size (zbarImage *self, PyErr_SetString(PyExc_TypeError, "cannot delete size attribute"); return(-1); } - int rc = -1; - PyObject *wobj = NULL, *hobj = NULL; + int rc = -1, i, dims[2]; if(!PySequence_Check(value) || PySequence_Size(value) != 2) goto error; - wobj = PySequence_GetItem(value, 0); - hobj = PySequence_GetItem(value, 1); - if(!wobj || !hobj) - goto error; + for(i = 0; i < 2; i++) { + PyObject *dim = PySequence_GetItem(value, i); + if(!dim) + goto error; + dims[i] = PyInt_AsSsize_t(dim); + Py_DECREF(dim); + if(dims[i] < 0) + goto error; + } - int width = PyInt_AsSsize_t(wobj); - if(width == -1 && PyErr_Occurred()) - goto error; + zbar_image_set_size(self->zimg, dims[0], dims[1]); + rc = 0; + +error: + if(rc) + PyErr_SetString(PyExc_ValueError, + "size must be a sequence of two positive ints"); + return(rc); +} - int height = PyInt_AsSsize_t(hobj); - if(height == -1 && PyErr_Occurred()) +static PyObject* +image_get_crop (zbarImage *self, + void *closure) +{ + unsigned int x, y, w, h; + zbar_image_get_crop(self->zimg, &x, &y, &w, &h); + return(PyTuple_Pack(4, PyInt_FromLong(x), PyInt_FromLong(y), + PyInt_FromLong(w), PyInt_FromLong(h))); +} + +static int +image_set_crop (zbarImage *self, + PyObject *value, + void *closure) +{ + unsigned w, h; + zbar_image_get_size(self->zimg, &w, &h); + if(!value) { + zbar_image_set_crop(self->zimg, 0, 0, w, h); + return(0); + } + int rc = -1, i, dims[4]; + if(!PySequence_Check(value) || + PySequence_Size(value) != 4) + goto error; + for(i = 0; i < 4; i++) { + PyObject *dim = PySequence_GetItem(value, i); + if(!dim) + goto error; + dims[i] = PyInt_AsSsize_t(dim); + Py_DECREF(dim); + if(dims[i] == -1 && PyErr_Occurred()) + goto error; + } + if(dims[2] < 0 || dims[3] < 0) goto error; + if(dims[0] < 0) { + dims[2] += dims[0]; + dims[0] = 0; + } + if(dims[1] < 0) { + dims[3] += dims[1]; + dims[1] = 0; + } - zbar_image_set_size(self->zimg, width, height); + zbar_image_set_crop(self->zimg, dims[0], dims[1], dims[2], dims[3]); rc = 0; error: - Py_XDECREF(wobj); - Py_XDECREF(hobj); if(rc) PyErr_SetString(PyExc_ValueError, - "size must be a sequence of two ints"); + "crop must be a sequence of four positive ints"); return(rc); } @@ -308,6 +357,7 @@ image_set_data (zbarImage *self, static PyGetSetDef image_getset[] = { { "format", (getter)image_get_format, (setter)image_set_format, }, { "size", (getter)image_get_size, (setter)image_set_size, }, + { "crop", (getter)image_get_crop, (setter)image_set_crop, }, { "width", (getter)image_get_int, (setter)image_set_int, NULL, (void*)0 }, { "height", (getter)image_get_int, (setter)image_set_int, diff --git a/python/test/test_zbar.py b/python/test/test_zbar.py index 9a27f3c..58f3e73 100755 --- a/python/test/test_zbar.py +++ b/python/test/test_zbar.py @@ -209,11 +209,13 @@ def test_type(self): def test_new(self): self.assertEqual(self.image.format, 'Y800') self.assertEqual(self.image.size, (123, 456)) + self.assertEqual(self.image.crop, (0, 0, 123, 456)) image = zbar.Image() self.assert_(isinstance(image, zbar.Image)) self.assertEqual(image.format, '\0\0\0\0') self.assertEqual(image.size, (0, 0)) + self.assertEqual(image.crop, (0, 0, 0, 0)) def test_format(self): def set_format(fmt): @@ -246,6 +248,23 @@ def set_size(sz): self.assertEqual(self.image.width, 81) self.assertEqual(self.image.height, 64) + def test_crop(self): + def set_crop(crp): + self.image.crop = crp + self.assertRaises(ValueError, set_crop, (1,)) + self.assertRaises(ValueError, set_crop, 1) + self.image.crop = (1, 2, 100, 200) + self.assertRaises(ValueError, set_crop, (1, 2, 3, 4, 5)) + self.assertEqual(self.image.crop, (1, 2, 100, 200)) + self.assertRaises(ValueError, set_crop, "foo") + self.assertEqual(self.image.crop, (1, 2, 100, 200)) + self.image.crop = (-100, -100, 400, 700) + self.assertEqual(self.image.crop, (0, 0, 123, 456)) + self.image.crop = (40, 50, 60, 70) + self.assertEqual(self.image.crop, (40, 50, 60, 70)) + self.image.size = (82, 65) + self.assertEqual(self.image.crop, (0, 0, 82, 65)) + class TestImageScanner(ut.TestCase): def setUp(self): self.scn = zbar.ImageScanner() @@ -336,6 +355,21 @@ def set_symbols(syms): self.scn.recycle(self.image) self.assertEqual(len(self.image.symbols), 0) + def test_scan_crop(self): + self.image.crop = (0, 71, 114, 9) + self.assertEqual(self.image.crop, (0, 71, 114, 9)) + n = self.scn.scan(self.image) + self.assertEqual(n, 0) + + self.image.crop = (12, 24, 90, 12) + self.assertEqual(self.image.crop, (12, 24, 90, 12)) + n = self.scn.scan(self.image) + self.assertEqual(n, 0) + + self.image.crop = (9, 24, 96, 12) + self.assertEqual(self.image.crop, (9, 24, 96, 12)) + self.test_scan() + def test_scan_again(self): self.test_scan() diff --git a/zbar/convert.c b/zbar/convert.c index b3c4832..f328b29 100644 --- a/zbar/convert.c +++ b/zbar/convert.c @@ -968,12 +968,20 @@ static void convert_jpeg (zbar_image_t *dst, tmp->format = fourcc('Y','8','0','0'); tmp->width = dst->width; tmp->height = dst->height; + tmp->crop_x = dst->crop_x; + tmp->crop_y = dst->crop_y; + tmp->crop_w = dst->crop_w; + tmp->crop_h = dst->crop_h; } else { tmp = src->src->jpeg_img; assert(tmp); dst->width = tmp->width; dst->height = tmp->height; + dst->crop_x = tmp->crop_x; + dst->crop_y = tmp->crop_y; + dst->crop_w = tmp->crop_w; + dst->crop_h = tmp->crop_h; } const zbar_format_def_t *tmpfmt = _zbar_format_lookup(tmp->format); @@ -985,6 +993,10 @@ static void convert_jpeg (zbar_image_t *dst, /* now convert to dst */ dst->width = tmp->width; dst->height = tmp->height; + dst->crop_x = tmp->crop_x; + dst->crop_y = tmp->crop_y; + dst->crop_w = tmp->crop_w; + dst->crop_h = tmp->crop_h; conversion_handler_t *func = conversions[tmpfmt->group][dstfmt->group].func; @@ -1007,6 +1019,8 @@ zbar_image_t *zbar_image_convert_resize (const zbar_image_t *src, dst->format = fmt; dst->width = width; dst->height = height; + zbar_image_set_crop(dst, src->crop_x, src->crop_y, + src->crop_w, src->crop_h); if(src->format == fmt && src->width == width && src->height == height) { diff --git a/zbar/image.c b/zbar/image.c index 4bcb2a3..99e1303 100644 --- a/zbar/image.c +++ b/zbar/image.c @@ -74,6 +74,26 @@ unsigned zbar_image_get_height (const zbar_image_t *img) return(img->height); } +void zbar_image_get_size (const zbar_image_t *img, + unsigned *w, + unsigned *h) +{ + if(w) *w = img->width; + if(h) *h = img->height; +} + +void zbar_image_get_crop (const zbar_image_t *img, + unsigned *x, + unsigned *y, + unsigned *w, + unsigned *h) +{ + if(x) *x = img->crop_x; + if(y) *y = img->crop_y; + if(w) *w = img->crop_w; + if(h) *h = img->crop_h; +} + const void *zbar_image_get_data (const zbar_image_t *img) { return(img->data); @@ -100,8 +120,28 @@ void zbar_image_set_size (zbar_image_t *img, unsigned w, unsigned h) { - img->width = w; - img->height = h; + img->crop_x = img->crop_y = 0; + img->width = img->crop_w = w; + img->height = img->crop_h = h; +} + +void zbar_image_set_crop (zbar_image_t *img, + unsigned x, + unsigned y, + unsigned w, + unsigned h) +{ + unsigned img_w = img->width; + if(x > img_w) x = img_w; + if(x + w > img_w) w = img_w - x; + img->crop_x = x; + img->crop_w = w; + + unsigned img_h = img->height; + if(y > img_h) y = img_h; + if(y + h > img_h) h = img_h - y; + img->crop_y = y; + img->crop_h = h; } inline void zbar_image_free_data (zbar_image_t *img) @@ -165,6 +205,10 @@ zbar_image_t *zbar_image_copy (const zbar_image_t *src) dst->format = src->format; dst->width = src->width; dst->height = src->height; + dst->crop_x = src->crop_x; + dst->crop_y = src->crop_y; + dst->crop_w = src->crop_w; + dst->crop_h = src->crop_h; dst->datalen = src->datalen; dst->data = malloc(src->datalen); assert(dst->data); diff --git a/zbar/image.h b/zbar/image.h index 3e2adf5..a3ea15d 100644 --- a/zbar/image.h +++ b/zbar/image.h @@ -62,6 +62,8 @@ struct zbar_image_s { unsigned width, height; /* image size */ const void *data; /* image sample data */ unsigned long datalen; /* allocated/mapped size of data */ + unsigned crop_x, crop_y; /* crop rectangle */ + unsigned crop_w, crop_h; void *userdata; /* user specified data associated w/image */ /* cleanup handler */ diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index c7cff4e..79820a2 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -615,7 +615,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, zbar_symbol_set_t *syms; const uint8_t *data; zbar_scanner_t *scn = iscn->scn; - unsigned w, h; + unsigned w, h, cx1, cy1; int density; /* timestamp image @@ -647,6 +647,10 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, w = img->width; h = img->height; + cx1 = img->crop_x + img->crop_w; + assert(cx1 <= w); + cy1 = img->crop_y + img->crop_h; + assert(cy1 <= h); data = img->data; zbar_image_write_png(img, "debug.png"); @@ -660,21 +664,24 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, const uint8_t *p = data; int x = 0, y = 0; - int border = (((h - 1) % density) + 1) / 2; - if(border > h / 2) - border = h / 2; + int border = (((img->crop_h - 1) % density) + 1) / 2; + if(border > img->crop_h / 2) + border = img->crop_h / 2; + border += img->crop_y; + assert(border <= h); svg_group_start("scanner", 0, 1, 1, 0, 0); iscn->dy = 0; - movedelta(0, border); + movedelta(img->crop_x, border); iscn->v = y; - while(y < h) { + while(y < cy1) { + int cx0; zprintf(128, "img_x+: %04d,%04d @%p\n", x, y, p); svg_path_start("vedge", 1. / 32, 0, y + 0.5); iscn->dx = iscn->du = 1; iscn->umin = 0; - while(x < w) { + while(x < cx1) { uint8_t d = *p; movedelta(1, 0); zbar_scan_y(scn, d); @@ -685,14 +692,15 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, movedelta(-1, density); iscn->v = y; - if(y >= h) + if(y >= cy1) break; zprintf(128, "img_x-: %04d,%04d @%p\n", x, y, p); svg_path_start("vedge", -1. / 32, w, y + 0.5); iscn->dx = iscn->du = -1; iscn->umin = w; - while(x >= 0) { + cx0 = img->crop_x; + while(x >= cx0) { uint8_t d = *p; movedelta(-1, 0); zbar_scan_y(scn, d); @@ -713,19 +721,22 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, const uint8_t *p = data; int x = 0, y = 0; - int border = (((w - 1) % density) + 1) / 2; - if(border > w / 2) - border = w / 2; + int border = (((img->crop_w - 1) % density) + 1) / 2; + if(border > img->crop_w / 2) + border = img->crop_w / 2; + border += img->crop_x; + assert(border <= w); svg_group_start("scanner", 90, 1, -1, 0, 0); - movedelta(border, 0); + movedelta(border, img->crop_y); iscn->v = x; - while(x < w) { + while(x < cx1) { + int cy0; zprintf(128, "img_y+: %04d,%04d @%p\n", x, y, p); svg_path_start("vedge", 1. / 32, 0, x + 0.5); iscn->dy = iscn->du = 1; iscn->umin = 0; - while(y < h) { + while(y < cy1) { uint8_t d = *p; movedelta(0, 1); zbar_scan_y(scn, d); @@ -736,14 +747,15 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, movedelta(density, -1); iscn->v = x; - if(x >= w) + if(x >= cx1) break; zprintf(128, "img_y-: %04d,%04d @%p\n", x, y, p); svg_path_start("vedge", -1. / 32, h, x + 0.5); iscn->dy = iscn->du = -1; iscn->umin = h; - while(y >= 0) { + cy0 = img->crop_y; + while(y >= cy0) { uint8_t d = *p; movedelta(0, -1); zbar_scan_y(scn, d); From c552e7bcecc815f7a69a21c29f397d0d208f07a5 Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 5 Jun 2010 15:50:45 -0400 Subject: [PATCH 198/328] 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 --- ChangeLog | 5 + include/zbar/ZBarCaptureReader.h | 89 ++++ include/zbar/ZBarImage.h | 4 +- include/zbar/ZBarReaderView.h | 96 ++++ include/zbar/ZBarReaderViewController.h | 90 ++++ iphone/ZBarCVImage.h | 44 ++ iphone/ZBarCVImage.m | 178 +++++++ iphone/ZBarCaptureReader.m | 278 ++++++++++ iphone/ZBarImage.m | 53 +- iphone/ZBarReaderController.m | 1 + iphone/ZBarReaderView.m | 458 +++++++++++++++++ iphone/ZBarReaderViewController.m | 354 +++++++++++++ iphone/ZBarSymbol.m | 10 +- iphone/debug.h | 7 +- iphone/zbar.xcodeproj/project.pbxproj | 45 +- test/iphone/readertest.m | 486 +++++++++++++----- .../readertest.xcodeproj/project.pbxproj | 20 +- zbar/refcnt.c | 2 +- zbar/refcnt.h | 12 + 19 files changed, 2081 insertions(+), 151 deletions(-) create mode 100644 include/zbar/ZBarCaptureReader.h create mode 100644 include/zbar/ZBarReaderView.h create mode 100644 include/zbar/ZBarReaderViewController.h create mode 100644 iphone/ZBarCVImage.h create mode 100644 iphone/ZBarCVImage.m create mode 100644 iphone/ZBarCaptureReader.m create mode 100644 iphone/ZBarReaderView.m create mode 100644 iphone/ZBarReaderViewController.m diff --git a/ChangeLog b/ChangeLog index c9df860..556007b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,9 @@ current: + * 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 * fix couple of leaks * remove doc hints about GFDL (bug #3004411) - apply LGPL to API docs diff --git a/include/zbar/ZBarCaptureReader.h b/include/zbar/ZBarCaptureReader.h new file mode 100644 index 0000000..836363f --- /dev/null +++ b/include/zbar/ZBarCaptureReader.h @@ -0,0 +1,89 @@ +//------------------------------------------------------------------------ +// Copyright 2010 (c) Jeff Brown +// +// 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 + +@class ZBarCaptureReader, ZBarImageScanner, ZBarImage, ZBarCVImage, + ZBarSymbolSet; + +@protocol ZBarCaptureDelegate + +// called when a new barcode is detected. the image refers to the +// video buffer and must not be retained for long +- (void) captureReader: (ZBarCaptureReader*) captureReader + didReadNewSymbolsFromImage: (ZBarImage*) image; + +@optional +// called when a potential/uncertain barcode is detected. will also +// be called *after* captureReader:didReadNewSymbolsFromImage: +// when good barcodes are detected +- (void) captureReader: (ZBarCaptureReader*) captureReader + didTrackSymbols: (ZBarSymbolSet*) symbols; + +@end + +@interface ZBarCaptureReader + : NSObject +{ + AVCaptureVideoDataOutput *captureOutput; + id captureDelegate; + ZBarImageScanner *scanner; + CGRect scanCrop; + CGFloat framesPerSecond; + + dispatch_queue_t queue; + ZBarImage *image; + ZBarCVImage *result; + int32_t running; + int framecnt; + uint64_t t_frame, t_fps, t_scan; + CGFloat dt_frame; +} + +// supply a pre-configured image scanner +- (id) initWithImageScanner: (ZBarImageScanner*) imageScanner; + +// this must be called before the session is started +- (void) willStartRunning; + +// this must be called *before* the session is stopped +- (void) willStopRunning; + +// the capture output. add this to an instance of AVCaptureSession +@property (nonatomic, readonly) AVCaptureOutput *captureOutput; + +// delegate is notified of decode results and symbol tracking. +@property (assign) id captureDelegate; + +// access to image scanner for configuration. +@property (readonly) ZBarImageScanner *scanner; + +// region of image to scan in normalized coordinates. +// NB horizontal crop currently ignored... +@property (assign) CGRect scanCrop; + +// current frame rate (for debug/optimization). +// only valid when running +@property (nonatomic, readonly) CGFloat framesPerSecond; + +@end diff --git a/include/zbar/ZBarImage.h b/include/zbar/ZBarImage.h index bf74f6c..2d091ac 100644 --- a/include/zbar/ZBarImage.h +++ b/include/zbar/ZBarImage.h @@ -42,8 +42,9 @@ using namespace zbar; @property (nonatomic) CGSize size; @property (readonly, nonatomic) const void *data; @property (readonly, nonatomic) unsigned long dataLength; -@property (readonly, nonatomic) ZBarSymbolSet *symbols; +@property (copy, nonatomic) ZBarSymbolSet *symbols; @property (readonly, nonatomic) zbar_image_t *zbarImage; +@property (readonly, nonatomic) UIImage *UIImage; - (id) initWithImage: (zbar_image_t*) image; - (id) initWithCGImage: (CGImageRef) image; @@ -55,6 +56,7 @@ using namespace zbar; - (void) setData: (const void*) data withLength: (unsigned long) length; +- (UIImage*) UIImageWithOrientation: (UIImageOrientation) imageOrientation; - (void) cleanup; + (unsigned long) fourcc: (NSString*) format; diff --git a/include/zbar/ZBarReaderView.h b/include/zbar/ZBarReaderView.h new file mode 100644 index 0000000..8ab96c5 --- /dev/null +++ b/include/zbar/ZBarReaderView.h @@ -0,0 +1,96 @@ +//------------------------------------------------------------------------ +// Copyright 2010 (c) Jeff Brown +// +// 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 +#import + +@class AVCaptureSession, AVCaptureDevice, AVCaptureInput; +@class AVCaptureVideoPreviewLayer; +@class CALayer; +@class ZBarReaderView, ZBarCaptureReader; + +// delegate is notified of decode results. + +@protocol ZBarReaderViewDelegate < NSObject > + +- (void) readerView: (ZBarReaderView*) readerView + didReadSymbols: (ZBarSymbolSet*) symbols + fromImage: (UIImage*) image; + +@end + +// read barcodes from the displayed video preview. the view maintains +// a complete video capture session feeding a ZBarCaptureReader and +// presents the associated preview with symbol tracking annotations. + +@interface ZBarReaderView + : UIView +{ + id readerDelegate; + AVCaptureSession *session; + AVCaptureDevice *device; + BOOL tracksSymbols, showsFPS; + + AVCaptureInput *input; + ZBarCaptureReader *captureReader; + AVCaptureVideoPreviewLayer *preview; + CALayer *tracking; + UIView *fpsView; + UILabel *fpsLabel; + BOOL started, running; +} + +// supply a pre-configured image scanner. +- (id) initWithImageScanner: (ZBarImageScanner*) imageScanner; + +// start the video stream and barcode reader. +- (void) start; + +// stop the video stream and barcode reader. +- (void) stop; + +// delegate is notified of decode results. +@property (nonatomic, assign) id readerDelegate; + +// access to image scanner for configuration. +@property (nonatomic, readonly) ZBarImageScanner *scanner; + +// whether to display the tracking annotation for uncertain barcodes +// (default YES). +@property (nonatomic) BOOL tracksSymbols; + +// whether to display the frame rate for debug/configuration +// (default NO). +@property (nonatomic) BOOL showsFPS; + +// the region of the image that will be scanned. normalized coordinates. +@property (nonatomic) CGRect scanCrop; + +// specify an alternate capture device. +@property (nonatomic, retain) AVCaptureDevice *device; + +// direct access to the capture session. warranty void if opened... +@property (nonatomic, readonly) AVCaptureSession *session; +@property (nonatomic, readonly) ZBarCaptureReader *captureReader; + +@end diff --git a/include/zbar/ZBarReaderViewController.h b/include/zbar/ZBarReaderViewController.h new file mode 100644 index 0000000..6f96e5a --- /dev/null +++ b/include/zbar/ZBarReaderViewController.h @@ -0,0 +1,90 @@ +//------------------------------------------------------------------------ +// Copyright 2010 (c) Jeff Brown +// +// 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 + +@class ZBarReaderView; + +// drop in video scanning replacement for ZBarReaderController. +// this is a thin controller around a ZBarReaderView that adds the UI +// controls and select functionality offered by ZBarReaderController. +// Automatically falls back to a ZBarReaderController if video APIs +// are unavailable (eg for OS < 4.0) + +@interface ZBarReaderViewController + : UIViewController +{ + ZBarImageScanner *scanner; + id readerDelegate; + ZBarReaderView *readerView; + UIView *cameraOverlayView; + CGRect scanCrop; + BOOL showsZBarControls; + + UIView *controls; + BOOL statusBarHidden; +} + +// access to configure image scanner +@property (nonatomic, readonly) ZBarImageScanner *scanner; + +// barcode result recipient +@property (nonatomic, assign) id readerDelegate; + +// whether to use alternate control set +@property (nonatomic) BOOL showsZBarControls; + +// crop images for scanning. the image will be cropped to this +// rectangle before scanning. the rectangle is normalized to the +// image size and aspect ratio; useful values will place the rectangle +// between 0 and 1 on each axis, where the x-axis corresponds to the +// image major axis. defaults to the full image (0, 0, 1, 1). FIXME +// currently only works for the minor axis +@property (nonatomic) CGRect scanCrop; + +// provide a custom overlay. note that this can be used with +// showsZBarControls enabled (but not if you want backward compatibility) +@property (nonatomic, retain) UIView *cameraOverlayView; + +// display the built-in help browser. the argument will be passed to +// the onZBarHelp() javascript function. +- (void) showHelpWithReason: (NSString*) reason; + +// direct access to the ZBarReaderView +@property (nonatomic, readonly) ZBarReaderView *readerView; + +// these are present only for backward compatibility. +// they will error if inappropriate/unsupported values are set +@property (nonatomic) UIImagePickerControllerSourceType sourceType; // Camera +@property (nonatomic) BOOL allowsEditing; // NO +@property (nonatomic) BOOL allowsImageEditing; // NO +@property (nonatomic) BOOL showsCameraControls; // NO +@property (nonatomic) BOOL showsHelpOnFail; // NO +@property (nonatomic) ZBarReaderControllerCameraMode cameraMode; // Sampling +@property (nonatomic) BOOL takesPicture; // NO +@property (nonatomic) BOOL enableCache; // ignored +@property (nonatomic) NSInteger maxScanDimension; // ignored + ++ (BOOL) isSourceTypeAvailable: (UIImagePickerControllerSourceType) sourceType; + +@end diff --git a/iphone/ZBarCVImage.h b/iphone/ZBarCVImage.h new file mode 100644 index 0000000..b1bb75a --- /dev/null +++ b/iphone/ZBarCVImage.h @@ -0,0 +1,44 @@ +//------------------------------------------------------------------------ +// Copyright 2010 (c) Jeff Brown +// +// 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 +#import + +// ZBarImage referring to a CVPixelBuffer. used internally to handle +// asynchronous conversion to UIImage + +@interface ZBarCVImage + : ZBarImage +{ + CVPixelBufferRef pixelBuffer; + void *rgbBuffer; + NSInvocationOperation *conversion; +} + +@property (nonatomic) CVPixelBufferRef pixelBuffer; +@property (nonatomic, readonly) void *rgbBuffer; +@property (nonatomic, readonly) NSOperation *conversion; + +- (void) convertCVtoRGB; + +@end diff --git a/iphone/ZBarCVImage.m b/iphone/ZBarCVImage.m new file mode 100644 index 0000000..ab363cf --- /dev/null +++ b/iphone/ZBarCVImage.m @@ -0,0 +1,178 @@ +//------------------------------------------------------------------------ +// Copyright 2010 (c) Jeff Brown +// +// 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); + NSOperation *op = image.conversion; + // operation will at least have been queued already + assert(op); + if(!op) + return(NULL); + if(![op isFinished]) + [op waitUntilFinished]; + assert(image.rgbBuffer); + return(image.rgbBuffer); +} + +static const CGDataProviderDirectCallbacks asyncProvider = { + .version = 0, + .getBytePointer = asyncProvider_getBytePointer, + .releaseBytePointer = NULL, + .getBytesAtPosition = NULL, + .releaseInfo = (void*)CFRelease, +}; + +@implementation ZBarCVImage + +@synthesize pixelBuffer, rgbBuffer, conversion; + +- (void) dealloc +{ + self.pixelBuffer = nil; + 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); +} + +- (UIImage*) UIImageWithOrientation: (UIImageOrientation) orient +{ + NSOperationQueue *queue = conversionQueue; + if(!queue) + queue = conversionQueue = [NSOperationQueue new]; + + // start format conversion in separate thread + conversion = [[NSInvocationOperation alloc] + initWithTarget: self + selector: @selector(convertCVtoRGB) + object: nil]; + [queue addOperation: conversion]; + + // create UIImage with before converted data is available + CGSize size = self.size; + int w = size.width; + int h = size.height; + + CGDataProviderRef datasrc = + CGDataProviderCreateDirect(self, 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; + uint8_t *pdst = rgbBuffer = malloc(datalen); + 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; +} + +@end diff --git a/iphone/ZBarCaptureReader.m b/iphone/ZBarCaptureReader.m new file mode 100644 index 0000000..3d4b06e --- /dev/null +++ b/iphone/ZBarCaptureReader.m @@ -0,0 +1,278 @@ +//------------------------------------------------------------------------ +// Copyright 2010 (c) Jeff Brown +// +// 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 +#import +#import +#import "ZBarCVImage.h" + +#define MODULE ZBarCaptureReader +#import "debug.h" + +@implementation ZBarCaptureReader + +@synthesize captureOutput, captureDelegate, scanner, scanCrop, framesPerSecond; + +- (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(); + + 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; + captureOutput.videoSettings = + [NSDictionary + dictionaryWithObject: + [NSNumber numberWithInt: + kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange] + forKey: (NSString*)kCVPixelBufferPixelFormatTypeKey]; + + queue = dispatch_queue_create("ZBarCaptureReader", NULL); + [captureOutput setSampleBufferDelegate: + (id)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]; +} + +- (void) willStartRunning +{ + if(!OSAtomicCompareAndSwap32Barrier(0, 1, &running)) + return; + @synchronized(scanner) { + scanner.enableCache = YES; + } +} + +- (void) willStopRunning +{ + if(!OSAtomicAnd32OrigBarrier(0, (void*)&running)) + return; +} + +- (void) didTrackSymbols: (ZBarSymbolSet*) syms +{ + [captureDelegate + captureReader: self + didTrackSymbols: syms]; +} + +- (void) didReadNewSymbolsFromImage: (ZBarImage*) img +{ + timer_start; + [captureDelegate + captureReader: self + didReadNewSymbolsFromImage: img]; + OSAtomicCompareAndSwap32Barrier(2, 1, &running); + 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) setFPS: (NSNumber*) val +{ + [self setFramesPerSecond: val.doubleValue]; +} + +- (void) captureOutput: (AVCaptureOutput*) output + didOutputSampleBuffer: (CMSampleBufferRef) samp + fromConnection: (AVCaptureConnection*) conn +{ + // queue is apparently not flushed when stopping; + // only process when running + if(!OSAtomicCompareAndSwap32Barrier(1, 1, &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(setFPS:) + 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) { + int yc = h * scanCrop.origin.y + .5; + if(yc < 0) + yc = 0; + if(yc >= h) + yc = h - 1; + int hc = h * scanCrop.size.height + .5; + if(hc <= 0) + hc = 1; + if(yc + hc > h) + hc = h - yc; + image.size = CGSizeMake(w, hc); + [image setData: data + w * yc + withLength: w * hc]; + + int ngood = 0; + ZBarSymbolSet *syms = nil; + @synchronized(scanner) { + ngood = [scanner scanImage: image]; + syms = scanner.results; + } + now = timer_now(); + + if(ngood >= 0) { + // return unfiltered results for tracking feedback + syms.filterSymbols = NO; + int nraw = syms.count; + if(nraw > 0) + zlog(@"scan image: %dx%d ngood=%d nraw=%d", + w, hc, ngood, nraw); + + SEL cb = @selector(captureReader:didReadNewSymbolsFromImage:); + if(ngood && [captureDelegate respondsToSelector: cb]) { + // copy image data so we can release the buffer + result.size = CGSizeMake(w, h); + result.pixelBuffer = buf; + result.symbols = syms; + t_scan = now; + OSAtomicCompareAndSwap32Barrier(1, 2, &running); + [self performSelectorOnMainThread: + @selector(didReadNewSymbolsFromImage:) + withObject: result + waitUntilDone: NO]; + [self initResult]; + } + + cb = @selector(captureReader:didTrackSymbols:); + if(nraw && [captureDelegate respondsToSelector: cb]) + [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 diff --git a/iphone/ZBarImage.m b/iphone/ZBarImage.m index 526715e..ddf3a71 100644 --- a/iphone/ZBarImage.m +++ b/iphone/ZBarImage.m @@ -33,7 +33,7 @@ static void image_cleanup(zbar_image_t *zimg) @implementation ZBarImage -@dynamic format, sequence, size, data, dataLength, zbarImage; +@dynamic format, sequence, size, data, dataLength, symbols, zbarImage, UIImage; + (unsigned long) fourcc: (NSString*) format { @@ -220,6 +220,57 @@ - (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: + 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 { } diff --git a/iphone/ZBarReaderController.m b/iphone/ZBarReaderController.m index 4e26a59..007d06b 100644 --- a/iphone/ZBarReaderController.m +++ b/iphone/ZBarReaderController.m @@ -32,6 +32,7 @@ NSString* const ZBarReaderControllerResults = @"ZBarReaderControllerResults"; // expose undocumented API +CF_RETURNS_RETAINED CGImageRef UIGetScreenImage(void); @implementation ZBarReaderController diff --git a/iphone/ZBarReaderView.m b/iphone/ZBarReaderView.m new file mode 100644 index 0000000..e78e0c7 --- /dev/null +++ b/iphone/ZBarReaderView.m @@ -0,0 +1,458 @@ +//------------------------------------------------------------------------ +// Copyright 2010 (c) Jeff Brown +// +// 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 +#import + +#define MODULE ZBarReaderView +#import "debug.h" + +@implementation ZBarReaderView + +@synthesize readerDelegate, showsFPS, tracksSymbols, session, captureReader; +@dynamic scanner, scanCrop, device; + +- (id) initWithImageScanner: (ZBarImageScanner*) _scanner +{ + self = [super initWithFrame: CGRectMake(0, 0, 320, 426)]; + if(!self) + return(nil); + + self.backgroundColor = [UIColor blackColor]; + self.contentMode = UIViewContentModeScaleAspectFill; + self.autoresizingMask = + UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight; + + tracksSymbols = YES; + 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)self; + [session addOutput: captureReader.captureOutput]; + + preview = [[AVCaptureVideoPreviewLayer + layerWithSession: session] + retain]; + preview.frame = self.bounds; + [self.layer addSublayer: preview]; + + CGRect r = self.bounds; + tracking = [CALayer new]; + tracking.frame = r; + tracking.opacity = 0; + tracking.borderWidth = 1; + tracking.backgroundColor = [UIColor clearColor].CGColor; + tracking.borderColor = [UIColor greenColor].CGColor; + [self.layer addSublayer: tracking]; + + r.origin.x = 3 * r.size.width / 4; + r.origin.y = r.size.height - 32; + r.size.width = r.size.width - r.origin.x + 12; + r.size.height = 32 + 12; + fpsView = [[UIView alloc] + initWithFrame: r]; + fpsView.backgroundColor = [UIColor colorWithWhite: 0 + alpha: .333]; + fpsView.layer.cornerRadius = 12; + fpsView.hidden = YES; + [self addSubview: fpsView]; + + fpsLabel = [[UILabel alloc] + initWithFrame: CGRectMake(0, 0, + r.size.width - 12, + r.size.height - 12)]; + 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]; + + 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); +} + +- (void) dealloc +{ + [[NSNotificationCenter defaultCenter] + removeObserver: self]; + if(showsFPS) { + @try { + [captureReader removeObserver: self + forKeyPath: @"framesPerSecond"]; + } + @catch(...) { } + } + [fpsLabel release]; + fpsLabel = nil; + [fpsView release]; + fpsView = nil; + captureReader.captureDelegate = nil; + [captureReader release]; + captureReader = nil; + [device release]; + device = nil; + [input release]; + input = nil; + [preview removeFromSuperlayer]; + [preview release]; + preview = nil; + [session release]; + session = nil; + [tracking release]; + tracking = nil; + [super dealloc]; +} + +- (ZBarImageScanner*) scanner +{ + return(captureReader.scanner); +} + +- (CGRect) scanCrop +{ + return(captureReader.scanCrop); +} + +- (void) setScanCrop: (CGRect) r +{ + captureReader.scanCrop = r; +} + +- (AVCaptureDevice*) device +{ + return(device); +} + +- (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: input]; + if(input) + [session addInput: input]; + [session commitConfiguration]; + + [olddev release]; + [oldinput release]; +} + +- (void) setTracksSymbols: (BOOL) track +{ + if(track == tracksSymbols) + return; + + tracksSymbols = track; + tracking.opacity = 0; + tracking.frame = self.bounds; +} + +- (void) setShowsFPS: (BOOL) show +{ + if(show == showsFPS) + return; + fpsView.hidden = !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; + started = YES; + + [[UIDevice currentDevice] + beginGeneratingDeviceOrientationNotifications]; + + tracking.frame = self.bounds; + tracking.opacity = 0; + fpsLabel.text = @""; + + [captureReader willStartRunning]; + [session startRunning]; +} + +- (void) stop +{ + if(!started) + return; + + [captureReader willStopRunning]; + [session stopRunning]; + + [[UIDevice currentDevice] + endGeneratingDeviceOrientationNotifications]; + started = NO; +} + +- (void) onVideoStart: (NSNotification*) note +{ + zlog(@"onVideoStart: running=%d %@", running, note); + if(running) + return; + running = YES; + + // lock device and set focus mode + NSError *error = nil; + if([device lockForConfiguration: &error]) + device.focusMode = AVCaptureFocusModeContinuousAutoFocus; + else + zlog(@"failed to lock device: %@", error); +} + +- (void) onVideoStop: (NSNotification*) note +{ + zlog(@"onVideoStop: %@", note); + if(!running) + return; + + [device unlockForConfiguration]; + running = NO; +} + +- (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]; + NSLog(@"ZBarReaderView: ERROR during capture: %@: %@", + [err localizedDescription], + [err localizedFailureReason]); +} + +- (void) observeValueForKeyPath: (NSString*) path + ofObject: (id) obj + change: (NSDictionary*) info + context: (void*) ctx +{ + if(obj == captureReader && + [path isEqualToString: @"framesPerSecond"]) + fpsLabel.text = [NSString stringWithFormat: @"%.2ffps ", + captureReader.framesPerSecond]; +} + +- (void) updateTracking: (CALayer*) trk + withSymbol: (ZBarSymbol*) sym +{ + if(!sym) + return; + + CGRect b = sym.bounds; + CGPoint c = CGPointMake(CGRectGetMidX(b), CGRectGetMidY(b)); + CGSize size = preview.bounds.size; + CGPoint p = CGPointMake((480 - c.y) * size.width / 480, + c.x * size.height / 640); + CGRect r = CGRectMake(0, 0, + b.size.height * size.width / 480, + b.size.width * size.height / 640); + if(r.size.width <= 24 && r.size.height <= 24) + return; + r = CGRectInset(r, -16, -16); + + CALayer *current = trk.presentationLayer; + CGPoint cp = current.position; + 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 = .3; + 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 = .3; + 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 = .3; + on.timingFunction = linear; + on.fillMode = kCAFillModeForwards; + on.removedOnCompletion = NO; + + CABasicAnimation *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; + [trk addAnimation: group + forKey: @"tracking"]; +} + +- (void) captureReader: (ZBarCaptureReader*) reader + 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]; +} + +- (void) captureReader: (ZBarCaptureReader*) reader + didReadNewSymbolsFromImage: (ZBarImage*) zimg +{ + zlog(@"scanned %d symbols: %@", zimg.symbols.count, zimg); + if(!readerDelegate) + return; + + UIImageOrientation orient; + switch([UIDevice currentDevice].orientation) + { + 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 diff --git a/iphone/ZBarReaderViewController.m b/iphone/ZBarReaderViewController.m new file mode 100644 index 0000000..593d11f --- /dev/null +++ b/iphone/ZBarReaderViewController.m @@ -0,0 +1,354 @@ +//------------------------------------------------------------------------ +// Copyright 2010 (c) Jeff Brown +// +// 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 +#import +#import "ZBarHelpController.h" + +#define MODULE ZBarReaderViewController +#import "debug.h" + +@implementation ZBarReaderViewController + +@synthesize scanner, readerDelegate, showsZBarControls, cameraOverlayView, + readerView, scanCrop; +@dynamic sourceType, allowsEditing, allowsImageEditing, showsCameraControls, + showsHelpOnFail, cameraMode, takesPicture, maxScanDimension; + ++ (BOOL) isSourceTypeAvailable: (UIImagePickerControllerSourceType) sourceType +{ + if(sourceType != UIImagePickerControllerSourceTypeCamera) + return(NO); + return([UIImagePickerController isSourceTypeAvailable: sourceType]); +} + +- (id) init +{ + if(!NSClassFromString(@"AVCaptureSession")) { + // fallback to old interface + [self release]; + return([ZBarReaderController new]); + } + + self = [super init]; + if(!self) + return(nil); + + self.wantsFullScreenLayout = YES; + + showsZBarControls = YES; + scanCrop = CGRectMake(0, 0, 1, 1); + + // 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]; + + return(self); +} + +- (void) cleanup +{ + readerView.readerDelegate = nil; + [readerView release]; + readerView = nil; + [controls release]; + controls = 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 || controls) + return; + + UIView *view = self.view; + CGRect r = view.bounds; + r.origin.y = r.size.height - 54; + r.size.height = 54; + controls = [[UIView alloc] + initWithFrame: r]; + controls.backgroundColor = [UIColor blackColor]; + + UIToolbar *toolbar = + [UIToolbar new]; + r.origin.y = 0; + toolbar.frame = r; + toolbar.barStyle = UIBarStyleBlackOpaque; + + toolbar.items = + [NSArray arrayWithObjects: + [[[UIBarButtonItem alloc] + initWithBarButtonSystemItem: UIBarButtonSystemItemCancel + target: self + action: @selector(cancel)] + autorelease], + [[[UIBarButtonItem alloc] + initWithBarButtonSystemItem: UIBarButtonSystemItemFlexibleSpace + target: nil + action: nil] + autorelease], + nil]; + [controls addSubview: toolbar]; + [toolbar release]; + + UIButton *info = + [UIButton buttonWithType: UIButtonTypeInfoLight]; + r.origin.x = r.size.width - 54; + r.size.width = 54; + info.frame = r; + [info addTarget: self + action: @selector(info) + forControlEvents: UIControlEventTouchUpInside]; + [controls addSubview: info]; + + [self.view addSubview: controls]; +} + +- (void) loadView +{ + self.view = [[UIView alloc] + initWithFrame: CGRectMake(0, 0, 320, 480)]; +} + +- (void) viewDidLoad +{ + [super viewDidLoad]; + UIView *view = self.view; + view.backgroundColor = [UIColor blackColor]; + + readerView = [[ZBarReaderView alloc] + initWithImageScanner: scanner]; + readerView.readerDelegate = (id)self; + readerView.scanCrop = scanCrop; + [view addSubview: readerView]; + + [self initControls]; + + if(cameraOverlayView) { + assert(!cameraOverlayView.superview); + [cameraOverlayView removeFromSuperview]; + [self.view addSubview: cameraOverlayView]; + } +} + +- (void) viewDidUnload +{ + [cameraOverlayView removeFromSuperview]; + [self cleanup]; + [super viewDidUnload]; +} + +- (void) viewWillAppear: (BOOL) animated +{ + [self initControls]; + [super viewWillAppear: animated]; + + [readerView start]; + + UIApplication *app = [UIApplication sharedApplication]; + statusBarHidden = app.statusBarHidden; + if(self.wantsFullScreenLayout) + [app setStatusBarHidden: YES + withAnimation: UIStatusBarAnimationFade]; +} + +- (void) viewWillDisappear: (BOOL) animated +{ + [readerView stop]; + [[UIApplication sharedApplication] + setStatusBarHidden: statusBarHidden + withAnimation: UIStatusBarAnimationFade]; + + [super viewWillDisappear: animated]; +} + +- (void) viewDidDisappear: (BOOL) animated +{ + [super viewDidDisappear: animated]; + + // workaround for rdar://8034533 + // force view to unload so session is recreated and restarts correctly + self.view = nil; + [self viewDidUnload]; +} + +- (BOOL) enableCache +{ + return(NO); +} + +- (void) setEnableCache: (BOOL) enable +{ + // NB ignoring deprecated property +} + +- (ZBarReaderView*) readerView +{ + self.view; + assert(readerView); + return(readerView); +} + +- (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]; +} + +#if 0 +- (CGAffineTransform) cameraViewTransform +{ + // FIXME TBD + return(CGAffineTransformIdentity); +} + +- (void) setCameraViewTransform +{ + // FIXME TBD +} +#endif + +- (void) cancel +{ + if(!readerDelegate) + return; + [readerDelegate + imagePickerControllerDidCancel: (UIImagePickerController*)self]; +} + +- (void) info +{ + [self showHelpWithReason: @"INFO"]; +} + +- (void) showHelpWithReason: (NSString*) reason +{ + ZBarHelpController *help = + [[ZBarHelpController alloc] + initWithReason: reason]; + help.delegate = self; + help.wantsFullScreenLayout = YES; + UIView *helpView = help.view; + helpView.alpha = 0; + [self.view addSubview: helpView]; + [UIView beginAnimations: @"ZBarHelp" + context: nil]; + help.view.alpha = 1; + [UIView commitAnimations]; +} + +// ZBarHelpControllerDelegate (informal) + +- (void) helpController: (ZBarHelpController*) help + clickedButtonAtIndex: (NSInteger) idx +{ + [UIView beginAnimations: @"ZBarHelp" + context: help]; + [UIView setAnimationDelegate: self]; + [UIView setAnimationDidStopSelector: @selector(removeHelp:done:context:)]; + help.view.alpha = 0; + [UIView commitAnimations]; +} + +- (void) removeHelp: (NSString*) id + done: (NSNumber*) done + context: (void*) ctx +{ + if([id isEqualToString: @"ZBarHelp"]) { + ZBarHelpController *help = ctx; + [help.view removeFromSuperview]; + [help release]; + } +} + +// ZBarReaderViewDelegate + +- (void) readerView: (ZBarReaderView*) view + didReadSymbols: (ZBarSymbolSet*) syms + fromImage: (UIImage*) image +{ + [readerDelegate + imagePickerController: (UIImagePickerController*)self + didFinishPickingMediaWithInfo: + [NSDictionary dictionaryWithObjectsAndKeys: + image, UIImagePickerControllerOriginalImage, + syms, ZBarReaderControllerResults, + nil]]; +} + +// "deprecated" properties + +#define DEPRECATED_PROPERTY(getter, setter, type, val) \ + - (type) getter \ + { \ + return(val); \ + } \ + - (void) setter: (type) v \ + { \ + NSAssert2(v == val, @"attempt to set unsupported value (%d)" \ + @" for %@ property", val, @#getter); \ + } + +DEPRECATED_PROPERTY(sourceType, setSourceType, UIImagePickerControllerSourceType, UIImagePickerControllerSourceTypeCamera) +DEPRECATED_PROPERTY(allowsEditing, setAllowsEditing, BOOL, NO) +DEPRECATED_PROPERTY(allowsImageEditing, setAllowsImageEditing, BOOL, NO) +DEPRECATED_PROPERTY(showsCameraControls, setShowsCameraControls, BOOL, NO) +DEPRECATED_PROPERTY(showsHelpOnFail, setShowsHelpOnFail, BOOL, NO) +DEPRECATED_PROPERTY(cameraMode, setCameraMode, ZBarReaderControllerCameraMode, ZBarReaderControllerCameraModeSampling) +DEPRECATED_PROPERTY(takesPicture, setTakesPicture, BOOL, NO) +DEPRECATED_PROPERTY(maxScanDimension, setMaxScanDimension, NSInteger, 640) + +@end diff --git a/iphone/ZBarSymbol.m b/iphone/ZBarSymbol.m index 1e5151f..135cdb2 100644 --- a/iphone/ZBarSymbol.m +++ b/iphone/ZBarSymbol.m @@ -21,6 +21,7 @@ // http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ +#import #import @implementation ZBarSymbol @@ -141,7 +142,14 @@ - (void) dealloc - (int) count { - return(zbar_symbol_set_get_size(set)); + 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 diff --git a/iphone/debug.h b/iphone/debug.h index 76a4382..3244b48 100644 --- a/iphone/debug.h +++ b/iphone/debug.h @@ -22,10 +22,15 @@ //------------------------------------------------------------------------ #include +#define xNSSTR(s) @#s +#define NSSTR(s) xNSSTR(s) #ifdef DEBUG_OBJC +# ifndef MODULE +# define MODULE ZBarReaderController +# endif # define zlog(fmt, ...) \ - NSLog(@"ZBarReaderController: " fmt , ##__VA_ARGS__) + NSLog(NSSTR(MODULE) @": " fmt , ##__VA_ARGS__) #define timer_start \ uint64_t t_start = timer_now(); diff --git a/iphone/zbar.xcodeproj/project.pbxproj b/iphone/zbar.xcodeproj/project.pbxproj index 3246ddf..3951dc3 100644 --- a/iphone/zbar.xcodeproj/project.pbxproj +++ b/iphone/zbar.xcodeproj/project.pbxproj @@ -8,6 +8,11 @@ /* Begin PBXBuildFile section */ AA747D9F0F9514B9006C5449 /* prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = AA747D9E0F9514B9006C5449 /* prefix.pch */; }; + DC26004C118631C200FA987B /* ZBarCaptureReader.m in Sources */ = {isa = PBXBuildFile; fileRef = DC26004B118631C200FA987B /* ZBarCaptureReader.m */; }; + DC26004F118631E000FA987B /* ZBarCaptureReader.h in Headers */ = {isa = PBXBuildFile; fileRef = DC26004D118631E000FA987B /* ZBarCaptureReader.h */; }; + DC3AAB4E11B71A040021C7B1 /* ZBarCVImage.h in Headers */ = {isa = PBXBuildFile; fileRef = DC3AAB4C11B71A040021C7B1 /* ZBarCVImage.h */; }; + DC3AAB4F11B71A040021C7B1 /* ZBarCVImage.m in Sources */ = {isa = PBXBuildFile; fileRef = DC3AAB4D11B71A040021C7B1 /* ZBarCVImage.m */; }; + DC3EBB2D119DDB2100107EE9 /* ZBarReaderViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DC3EBB2C119DDB2100107EE9 /* ZBarReaderViewController.m */; }; DC4920EE10A70475000E4D43 /* ZBarImage.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4920EC10A70475000E4D43 /* ZBarImage.m */; }; DC4920EF10A70475000E4D43 /* ZBarImageScanner.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4920ED10A70475000E4D43 /* ZBarImageScanner.m */; }; DC4920F210A7048C000E4D43 /* ZBarImage.h in Headers */ = {isa = PBXBuildFile; fileRef = DC4920F010A7048C000E4D43 /* ZBarImage.h */; }; @@ -60,12 +65,20 @@ DC67C1C310A07B6B0033B702 /* ZBarReaderController.m in Sources */ = {isa = PBXBuildFile; fileRef = DC67C1BF10A07B6B0033B702 /* ZBarReaderController.m */; }; DC67C1C410A07B6B0033B702 /* ZBarSymbol.m in Sources */ = {isa = PBXBuildFile; fileRef = DC67C1C010A07B6B0033B702 /* ZBarSymbol.m */; }; DC67C1CC10A07BEE0033B702 /* svg.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C1CB10A07BEE0033B702 /* svg.h */; }; + DCDC6E3011ADCA8E00021380 /* ZBarReaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = DCDC6E2F11ADCA8E00021380 /* ZBarReaderView.m */; }; + DCDC6E3911ADCB7700021380 /* ZBarReaderView.h in Headers */ = {isa = PBXBuildFile; fileRef = DCDC6E3811ADCB7700021380 /* ZBarReaderView.h */; }; + DCDC713711B1628200021380 /* ZBarReaderViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = DCDC713611B1628200021380 /* ZBarReaderViewController.h */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ AA747D9E0F9514B9006C5449 /* prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = prefix.pch; sourceTree = ""; }; AACBBE490F95108600F1A2B1 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; D2AAC07E0554694100DB518D /* libzbar.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libzbar.a; sourceTree = BUILT_PRODUCTS_DIR; }; + DC26004B118631C200FA987B /* ZBarCaptureReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarCaptureReader.m; sourceTree = ""; }; + DC26004D118631E000FA987B /* ZBarCaptureReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ZBarCaptureReader.h; path = ../include/zbar/ZBarCaptureReader.h; sourceTree = SOURCE_ROOT; }; + DC3AAB4C11B71A040021C7B1 /* ZBarCVImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarCVImage.h; sourceTree = ""; }; + DC3AAB4D11B71A040021C7B1 /* ZBarCVImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarCVImage.m; sourceTree = ""; }; + DC3EBB2C119DDB2100107EE9 /* ZBarReaderViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarReaderViewController.m; sourceTree = ""; }; DC4920EC10A70475000E4D43 /* ZBarImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarImage.m; sourceTree = ""; }; DC4920ED10A70475000E4D43 /* ZBarImageScanner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarImageScanner.m; sourceTree = ""; }; DC4920F010A7048C000E4D43 /* ZBarImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ZBarImage.h; path = ../include/zbar/ZBarImage.h; sourceTree = SOURCE_ROOT; }; @@ -119,6 +132,9 @@ DC67C1BF10A07B6B0033B702 /* ZBarReaderController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarReaderController.m; sourceTree = ""; }; DC67C1C010A07B6B0033B702 /* ZBarSymbol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarSymbol.m; sourceTree = ""; }; DC67C1CB10A07BEE0033B702 /* svg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = svg.h; sourceTree = ""; }; + DCDC6E2F11ADCA8E00021380 /* ZBarReaderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarReaderView.m; sourceTree = ""; }; + DCDC6E3811ADCB7700021380 /* ZBarReaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ZBarReaderView.h; path = ../include/zbar/ZBarReaderView.h; sourceTree = SOURCE_ROOT; }; + DCDC713611B1628200021380 /* ZBarReaderViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ZBarReaderViewController.h; path = ../include/zbar/ZBarReaderViewController.h; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -143,11 +159,18 @@ 0867D691FE84028FC02AAC07 /* zbar */ = { isa = PBXGroup; children = ( + AA747D9E0F9514B9006C5449 /* prefix.pch */, + DC67C11110A079E40033B702 /* config.h */, + DC3AAB4C11B71A040021C7B1 /* ZBarCVImage.h */, + DC67C1BD10A07B6B0033B702 /* ZBarHelpController.h */, DC67C1C010A07B6B0033B702 /* ZBarSymbol.m */, DC4920EC10A70475000E4D43 /* ZBarImage.m */, DC4920ED10A70475000E4D43 /* ZBarImageScanner.m */, - DC67C1BD10A07B6B0033B702 /* ZBarHelpController.h */, + DC3AAB4D11B71A040021C7B1 /* ZBarCVImage.m */, + DC26004B118631C200FA987B /* ZBarCaptureReader.m */, + DCDC6E2F11ADCA8E00021380 /* ZBarReaderView.m */, DC67C1BE10A07B6B0033B702 /* ZBarHelpController.m */, + DC3EBB2C119DDB2100107EE9 /* ZBarReaderViewController.m */, DC67C1BF10A07B6B0033B702 /* ZBarReaderController.m */, DC67C11610A07A670033B702 /* include */, DC67C11E10A07AD30033B702 /* zbar */, @@ -169,12 +192,13 @@ DC67C11610A07A670033B702 /* include */ = { isa = PBXGroup; children = ( - AA747D9E0F9514B9006C5449 /* prefix.pch */, - DC67C11110A079E40033B702 /* config.h */, DC67C11710A07A810033B702 /* zbar.h */, DC67C11A10A07A950033B702 /* ZBarSymbol.h */, DC4920F010A7048C000E4D43 /* ZBarImage.h */, DC4920F110A7048C000E4D43 /* ZBarImageScanner.h */, + DC26004D118631E000FA987B /* ZBarCaptureReader.h */, + DCDC6E3811ADCB7700021380 /* ZBarReaderView.h */, + DCDC713611B1628200021380 /* ZBarReaderViewController.h */, DC67C11910A07A950033B702 /* ZBarReaderController.h */, ); name = include; @@ -279,6 +303,10 @@ DC67C1CC10A07BEE0033B702 /* svg.h in Headers */, DC4920F210A7048C000E4D43 /* ZBarImage.h in Headers */, DC4920F310A7048C000E4D43 /* ZBarImageScanner.h in Headers */, + DC26004F118631E000FA987B /* ZBarCaptureReader.h in Headers */, + DCDC6E3911ADCB7700021380 /* ZBarReaderView.h in Headers */, + DCDC713711B1628200021380 /* ZBarReaderViewController.h in Headers */, + DC3AAB4E11B71A040021C7B1 /* ZBarCVImage.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -350,6 +378,10 @@ DC67C1C410A07B6B0033B702 /* ZBarSymbol.m in Sources */, DC4920EE10A70475000E4D43 /* ZBarImage.m in Sources */, DC4920EF10A70475000E4D43 /* ZBarImageScanner.m in Sources */, + DC26004C118631C200FA987B /* ZBarCaptureReader.m in Sources */, + DC3EBB2D119DDB2100107EE9 /* ZBarReaderViewController.m in Sources */, + DCDC6E3011ADCA8E00021380 /* ZBarReaderView.m in Sources */, + DC3AAB4F11B71A040021C7B1 /* ZBarCVImage.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -393,9 +425,11 @@ GCC_PREPROCESSOR_DEFINITIONS = "DEBUG_OBJC=1"; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 3.1.2; OTHER_LDFLAGS = "-ObjC"; PREBINDING = NO; - SDKROOT = iphoneos3.1.2; + RUN_CLANG_STATIC_ANALYZER = NO; + SDKROOT = iphoneos4.0; }; name = Debug; }; @@ -408,7 +442,8 @@ GCC_WARN_UNUSED_VARIABLE = YES; OTHER_LDFLAGS = "-ObjC"; PREBINDING = NO; - SDKROOT = iphoneos3.1.2; + RUN_CLANG_STATIC_ANALYZER = NO; + SDKROOT = iphoneos4.0; }; name = Release; }; diff --git a/test/iphone/readertest.m b/test/iphone/readertest.m index 7d56781..4845701 100644 --- a/test/iphone/readertest.m +++ b/test/iphone/readertest.m @@ -1,35 +1,50 @@ -#import +#import +#import #if 0 # define VALGRIND "/usr/local/bin/valgrind" #endif enum { - SOURCE_SECTION = 0, + CLASS_SECTION = 0, + SOURCE_SECTION, CAMODE_SECTION, CONFIG_SECTION, + SYMBOL_SECTION, RESULT_SECTION, NUM_SECTIONS }; -@interface AppDelegate : UITableViewController - < UIApplicationDelegate, - UINavigationControllerDelegate, - UITableViewDelegate, - UITableViewDataSource, - ZBarReaderDelegate > +static NSString* const section_titles[] = { + @"Classes", + @"SourceType", + @"CameraMode", + @"Reader Configuration", + @"Enabled Symbologies", + @"Decode Results", +}; + +@interface AppDelegate + : UITableViewController + < UIApplicationDelegate, + UINavigationControllerDelegate, + UITableViewDelegate, + UITableViewDataSource, + ZBarReaderDelegate > { UIWindow *window; UINavigationController *nav; - NSArray *sections; + NSMutableArray *sections, *symbolEnables; - BOOL found; + BOOL found, paused; NSInteger dataHeight; UILabel *typeLabel, *dataLabel; UIImageView *imageView; - ZBarReaderController *reader; + ZBarReaderViewController *reader; + UIView *overlay; + NSArray *masks; } @end @@ -39,9 +54,112 @@ @implementation AppDelegate - (id) init { + // force these classes to load + [ZBarReaderViewController class]; + [ZBarReaderController class]; + return([super initWithStyle: UITableViewStyleGrouped]); } +- (void) initReader: (NSString*) clsName +{ + [reader release]; + reader = [NSClassFromString(clsName) new]; + reader.readerDelegate = self; +} + +- (void) initOverlay +{ + overlay = [[UIView alloc] + initWithFrame: CGRectMake(0, 0, 320, 480)]; + overlay.backgroundColor = [UIColor clearColor]; + + masks = [[NSArray alloc] + initWithObjects: + [[[UIView alloc] + initWithFrame: CGRectMake(0, 0, 320, 0)] + autorelease], + [[[UIView alloc] + initWithFrame: CGRectMake(0, 0, 0, 426)] + autorelease], + [[[UIView alloc] + initWithFrame: CGRectMake(0, 426, 320, 0)] + autorelease], + [[[UIView alloc] + initWithFrame: CGRectMake(320, 0, 0, 426)] + autorelease], + nil]; + for(UIView *mask in masks) { + mask.backgroundColor = [UIColor colorWithWhite: 0 + alpha: .5]; + [overlay addSubview: mask]; + } + + UILabel *label = + [[UILabel alloc] + initWithFrame: CGRectMake(0, 0, 320, 48)]; + label.backgroundColor = [UIColor clearColor]; + label.textColor = [UIColor whiteColor]; + label.font = [UIFont boldSystemFontOfSize: 24]; + label.text = @"Custom Overlay"; + [overlay addSubview: label]; + [label release]; + + UIToolbar *toolbar = + [[UIToolbar alloc] + initWithFrame: CGRectMake(0, 426, 320, 54)]; + toolbar.tintColor = [UIColor colorWithRed: .5 + green: 0 + blue: 0 + alpha: 1]; + toolbar.items = + [NSArray arrayWithObjects: + [[[UIBarButtonItem alloc] + initWithTitle: @"X" + style: UIBarButtonItemStylePlain + target: self + action: @selector(imagePickerControllerDidCancel:)] + autorelease], + [[[UIBarButtonItem alloc] + initWithBarButtonSystemItem: UIBarButtonSystemItemFlexibleSpace + target: nil + action: nil] + autorelease], + [[[UIBarButtonItem alloc] + initWithBarButtonSystemItem: UIBarButtonSystemItemPause + target: self + action: @selector(pause)] + autorelease], + nil]; + [overlay addSubview: toolbar]; + [toolbar release]; +} + +- (void) setCheck: (BOOL) state + forCell: (UITableViewCell*) cell +{ + cell.accessoryType = + ((state) + ? UITableViewCellAccessoryCheckmark + : UITableViewCellAccessoryNone); +} + +- (void) setCheckForTag: (int) tag + inSection: (int) section +{ + for(UITableViewCell *cell in [sections objectAtIndex: section]) + [self setCheck: (cell.tag == tag) + forCell: cell]; +} + +- (void) setCheckForName: (NSString*) name + inSection: (int) section +{ + for(UITableViewCell *cell in [sections objectAtIndex: section]) + [self setCheck: [name isEqualToString: cell.textLabel.text] + forCell: cell]; +} + - (void) applicationDidFinishLaunching: (UIApplication*) application { self.title = @"ZBar Reader Test"; @@ -54,62 +172,117 @@ - (void) applicationDidFinishLaunching: (UIApplication*) application [window addSubview: nav.view]; [window makeKeyAndVisible]; - reader = [ZBarReaderController new]; - reader.readerDelegate = self; + [self initReader: @"ZBarReaderViewController"]; } -- (void) viewDidLoad +- (UITableViewCell*) cellWithTitle: (NSString*) title + tag: (NSInteger) tag + checked: (BOOL) checked { - [super viewDidLoad]; - - UITableView *view = self.tableView; - view.delegate = self; - view.dataSource = self; + UITableViewCell *cell = [UITableViewCell new]; + cell.textLabel.text = title; + cell.tag = tag; + [self setCheck: checked + forCell: cell]; + return([cell autorelease]); +} +- (void) initControlCells +{ // NB don't need SourceTypeSavedPhotosAlbum static NSString* const sourceNames[] = { - @"Library", @"Camera", @"Album" + @"Library", @"Camera", @"Album", nil }; - NSMutableArray *sources = [NSMutableArray arrayWithCapacity: 3]; - for(int i = 0; i < 3; i++) { - UITableViewCell *cell = [UITableViewCell new]; - if([ZBarReaderController isSourceTypeAvailable: i]) { - cell.textLabel.text = sourceNames[i]; - cell.tag = i; - if(reader.sourceType == i) - cell.accessoryType = UITableViewCellAccessoryCheckmark; - [sources addObject: cell]; - [cell release]; - } - } + NSMutableArray *sources = [NSMutableArray array]; + for(int i = 0; sourceNames[i]; i++) + if([[reader class] isSourceTypeAvailable: i]) + [sources addObject: + [self cellWithTitle: sourceNames[i] + tag: i + checked: (reader.sourceType == i)]]; + [sections replaceObjectAtIndex: SOURCE_SECTION + withObject: sources]; static NSString* const modeNames[] = { - @"Default", @"Sampling", @"Sequence" + @"Default", @"Sampling", @"Sequence", nil }; - NSMutableArray *modes = [NSMutableArray arrayWithCapacity: 3]; - for(int i = 0; i < 3; i++) { - UITableViewCell *cell = [UITableViewCell new]; - cell.textLabel.text = modeNames[i]; - cell.tag = i; - if(reader.cameraMode == i) - cell.accessoryType = UITableViewCellAccessoryCheckmark; - [modes addObject: cell]; - [cell release]; - } + NSMutableArray *modes = [NSMutableArray array]; + for(int i = 0; modeNames[i]; i++) + [modes addObject: + [self cellWithTitle: modeNames[i] + tag: i + checked: (reader.cameraMode == i)]]; + [sections replaceObjectAtIndex: CAMODE_SECTION + withObject: modes]; static NSString* const configNames[] = { - @"showsHelpOnFail", @"showsZBarControls", @"takesPicture", - @"enableCache" + @"showsZBarControls", @"enableCache", + @"showsHelpOnFail", @"takesPicture", + nil + }; + NSMutableArray *configs = [NSMutableArray array]; + for(int i = 0; configNames[i]; i++) + [configs addObject: + [self cellWithTitle: configNames[i] + tag: i + checked: [[reader valueForKey: configNames[i]] boolValue]]]; + [sections replaceObjectAtIndex: CONFIG_SECTION + withObject: configs]; + + static const int symbolValues[] = { + ZBAR_QRCODE, ZBAR_CODE128, ZBAR_CODE39, ZBAR_I25, ZBAR_EAN13, ZBAR_EAN8, + ZBAR_UPCA, ZBAR_UPCE, ZBAR_ISBN13, ZBAR_ISBN10, + 0 + }; + static NSString* const symbolNames[] = { + @"QRCODE", @"CODE128", @"CODE39", @"I25", @"EAN13", @"EAN8", + @"UPCA", @"UPCE", @"ISBN13", @"ISBN10", + nil }; - NSMutableArray *configs = [NSMutableArray arrayWithCapacity: 4]; - for(int i = 0; i < 4; i++) { - UITableViewCell *cell = [UITableViewCell new]; - cell.textLabel.text = configNames[i]; - if([reader performSelector: NSSelectorFromString(configNames[i])]) - cell.accessoryType = UITableViewCellAccessoryCheckmark; - [configs addObject: cell]; - [cell release]; + NSMutableArray *symbols = [NSMutableArray array]; + [symbolEnables release]; + symbolEnables = [[NSMutableArray alloc] init]; + BOOL en = YES; + for(int i = 0; symbolValues[i]; i++) { + en = en && (symbolValues[i] != ZBAR_UPCA); + [symbols addObject: + [self cellWithTitle: symbolNames[i] + tag: symbolValues[i] + checked: en]]; + [symbolEnables addObject: [NSNumber numberWithBool: en]]; } + [sections replaceObjectAtIndex: SYMBOL_SECTION + withObject: symbols]; + + [self.tableView reloadData]; +} + +- (void) viewDidLoad +{ + [super viewDidLoad]; + + UITableView *view = self.tableView; + view.delegate = self; + view.dataSource = self; + + [self initOverlay]; + + sections = [[NSMutableArray alloc] + initWithCapacity: NUM_SECTIONS]; + for(int i = 0; i < NUM_SECTIONS; i++) + [sections addObject: [NSNull null]]; + + NSArray *classes = + [NSArray arrayWithObjects: + [self cellWithTitle: @"ZBarReaderViewController" + tag: 0 + checked: YES], + [self cellWithTitle: @"ZBarReaderController" + tag: 1 + checked: NO], + nil]; + [sections replaceObjectAtIndex: CLASS_SECTION + withObject: classes]; UITableViewCell *typeCell = [UITableViewCell new]; typeLabel = typeCell.textLabel; @@ -128,57 +301,64 @@ - (void) viewDidLoad [imageView release]; NSArray *results = [NSArray arrayWithObjects: typeCell, dataCell, imageCell, nil]; + [sections replaceObjectAtIndex: RESULT_SECTION + withObject: results]; - sections = - [[NSArray arrayWithObjects: sources, modes, configs, results, nil] - retain]; + [self initControlCells]; } - (void) viewDidUnload { [sections release]; sections = nil; + [symbolEnables release]; + symbolEnables = nil; + [typeLabel release]; typeLabel = nil; + [dataLabel release]; dataLabel = nil; + [imageView release]; imageView = nil; - + [overlay release]; + overlay = nil; + [masks release]; + masks = nil; [super viewDidUnload]; } - (void) dealloc { [reader release]; + reader = nil; [nav release]; + nav = nil; [window release]; + window = nil; [super dealloc]; } - (void) scan { - found = NO; + found = paused = NO; imageView.image = nil; typeLabel.text = nil; dataLabel.text = nil; [self.tableView reloadData]; + if([reader respondsToSelector: @selector(readerView)]) + reader.readerView.showsFPS = YES; [self presentModalViewController: reader animated: YES]; } -- (void) setCheck: (BOOL) state - forCell: (UITableViewCell*) cell -{ - cell.accessoryType = - ((state) - ? UITableViewCellAccessoryCheckmark - : UITableViewCellAccessoryNone); -} - -- (void) setCheckForTag: (int) tag - inSection: (int) section +- (void) pause { - for(UITableViewCell *cell in [sections objectAtIndex: section]) - [self setCheck: (cell.tag == tag) - forCell: cell]; + if(![reader respondsToSelector: @selector(readerView)]) + return; + paused = !paused; + if(paused) + [reader.readerView stop]; + else + [reader.readerView start]; } // UINavigationControllerDelegate @@ -220,14 +400,8 @@ - (UITableViewCell*) tableView: (UITableView*) view - (NSString*) tableView: (UITableView*) view titleForHeaderInSection: (NSInteger) idx { - static NSString * const titles[] = { - @"SourceType", - @"CameraMode", - @"Reader Configuration", - @"Decode Results", - }; assert(idx < NUM_SECTIONS); - return(titles[idx]); + return(section_titles[idx]); } // UITableViewDelegate @@ -240,6 +414,20 @@ - (NSIndexPath*) tableView: (UITableView*) view return(path); } +- (void) alertUnsupported +{ + UIAlertView *alert = + [[UIAlertView alloc] + initWithTitle: @"Unsupported" + message: @"Setting not available for this reader" + @" (or with this OS on this device)" + delegate: nil + cancelButtonTitle: @"Cancel" + otherButtonTitles: nil]; + [alert show]; + [alert release]; +} + - (void) tableView: (UITableView*) view didSelectRowAtIndexPath: (NSIndexPath*) path { @@ -248,50 +436,59 @@ - (void) tableView: (UITableView*) view UITableViewCell *cell = [view cellForRowAtIndexPath: path]; - switch(path.section) { + switch(path.section) + { + case CLASS_SECTION: { + NSString *name = cell.textLabel.text; + [self initReader: name]; + [self initControlCells]; + [self setCheckForName: name + inSection: CLASS_SECTION]; + break; + } case SOURCE_SECTION: [self setCheckForTag: reader.sourceType = cell.tag inSection: SOURCE_SECTION]; break; case CAMODE_SECTION: - [self setCheckForTag: reader.cameraMode = cell.tag + @try { + reader.cameraMode = cell.tag; + } + @catch (...) { + [self alertUnsupported]; + } + [self setCheckForTag: reader.cameraMode inSection: CAMODE_SECTION]; break; case CONFIG_SECTION: { BOOL state; - switch(path.row) { - case 0: - reader.showsHelpOnFail = !reader.showsHelpOnFail; - state = reader.showsHelpOnFail; - break; - case 1: - @try { - reader.showsZBarControls = !reader.showsZBarControls; - } - @catch (...) { - UIAlertView *alert = - [[UIAlertView alloc] - initWithTitle: @"Unsupported" - message: @"Not available for iPhone OS < 3.1" - delegate: nil - cancelButtonTitle: @"Cancel" - otherButtonTitles: nil]; - [alert show]; - [alert release]; - } - state = reader.showsZBarControls; - break; - case 2: - reader.takesPicture = !reader.takesPicture; - state = reader.takesPicture; - break; - case 3: - reader.enableCache = !reader.enableCache; - state = reader.enableCache; - break; - default: - assert(0); + NSString *key = cell.textLabel.text; + state = ![[reader valueForKey: key] boolValue]; + @try { + [reader setValue: [NSNumber numberWithBool: state] + forKey: key]; } + @catch (...) { + [self alertUnsupported]; + } + + // read back and update current state + state = [[reader valueForKey: key] boolValue]; + [self setCheck: state + forCell: cell]; + + if([key isEqualToString: @"showsZBarControls"] && + reader.sourceType == UIImagePickerControllerSourceTypeCamera) + reader.cameraOverlayView = (state) ? nil : overlay; + break; + } + case SYMBOL_SECTION: { + BOOL state = ![[symbolEnables objectAtIndex: path.row] boolValue]; + [symbolEnables replaceObjectAtIndex: path.row + withObject: [NSNumber numberWithBool: state]]; + [reader.scanner setSymbology: cell.tag + config: ZBAR_CFG_ENABLE + to: state]; [self setCheck: state forCell: cell]; break; @@ -323,44 +520,57 @@ - (CGFloat) tableView: (UITableView*) view - (void) imagePickerController: (UIImagePickerController*) picker didFinishPickingMediaWithInfo: (NSDictionary*) info { - found = YES; id results = [info objectForKey: ZBarReaderControllerResults]; assert(results); - NSLog(@"imagePickerController:didFinishPickingMediaWithInfo:\n"); UIImage *image = [info objectForKey: UIImagePickerControllerOriginalImage]; assert(image); - imageView.image = image; - - int quality = 0, n = 0; - for(ZBarSymbol *sym in results) { - NSLog(@" [%d] type=%@ data=%@\n", n, sym.typeName, sym.data); - - if(sym.quality > quality) { - typeLabel.text = sym.typeName; - NSString *data = sym.data; - dataLabel.text = data; - - CGSize size = [data sizeWithFont: [UIFont systemFontOfSize: 17] - constrainedToSize: CGSizeMake(288, 2000) - lineBreakMode: UILineBreakModeCharacterWrap]; - dataHeight = size.height + 26; - if(dataHeight > 2000) - dataHeight = 2000; - } - n++; - } - assert(n); - + if(image) + imageView.image = image; + + int quality = 0; + ZBarSymbol *bestResult = nil; + for(ZBarSymbol *sym in results) + if(sym.quality > quality) + bestResult = sym; + assert(!!bestResult); + + [self performSelector: @selector(presentResult:) + withObject: bestResult + afterDelay: .001]; [picker dismissModalViewControllerAnimated: YES]; +} + +- (void) presentResult: (ZBarSymbol*) sym +{ + found = !!sym; + typeLabel.text = sym.typeName; + NSString *data = sym.data; + dataLabel.text = data; + + NSLog(@"imagePickerController:didFinishPickingMediaWithInfo:\n"); + NSLog(@" type=%@ data=%@\n", sym.typeName, data); + + CGSize size = [data sizeWithFont: [UIFont systemFontOfSize: 17] + constrainedToSize: CGSizeMake(288, 2000) + lineBreakMode: UILineBreakModeCharacterWrap]; + dataHeight = size.height + 26; + if(dataHeight > 2000) + dataHeight = 2000; + [self.tableView reloadData]; + [self.tableView scrollToRowAtIndexPath: + [NSIndexPath indexPathForRow: 0 + inSection: RESULT_SECTION] + atScrollPosition:UITableViewScrollPositionTop + animated: NO]; } - (void) imagePickerControllerDidCancel: (UIImagePickerController*) picker { NSLog(@"imagePickerControllerDidCancel:\n"); - [picker dismissModalViewControllerAnimated: YES]; + [reader dismissModalViewControllerAnimated: YES]; } - (void) readerControllerDidFailToRead: (ZBarReaderController*) _reader diff --git a/test/iphone/readertest.xcodeproj/project.pbxproj b/test/iphone/readertest.xcodeproj/project.pbxproj index c00af7a..68522d3 100755 --- a/test/iphone/readertest.xcodeproj/project.pbxproj +++ b/test/iphone/readertest.xcodeproj/project.pbxproj @@ -19,6 +19,9 @@ DCB9118810BC5DB500B907F0 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD6E13B10B0AFD4002005CD /* libiconv.dylib */; }; DCB9119B10BC5DCB00B907F0 /* libzbar.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD6E0E610B0AE16002005CD /* libzbar.a */; }; DCD6E0D010B0AD41002005CD /* readertest.m in Sources */ = {isa = PBXBuildFile; fileRef = DCD6E0CF10B0AD41002005CD /* readertest.m */; }; + DCDC6D9B11ACA23000021380 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCDC6D9A11ACA23000021380 /* CoreVideo.framework */; }; + DCDC6D9F11ACA23900021380 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCDC6D9E11ACA23900021380 /* CoreMedia.framework */; }; + DCDC6DEC11ACA5B400021380 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCDC6DEB11ACA5B400021380 /* AVFoundation.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -54,6 +57,9 @@ DCD6E0D810B0AD55002005CD /* readertest.plist */ = {isa = PBXFileReference; explicitFileType = text.plist.info; fileEncoding = 4; path = readertest.plist; sourceTree = ""; }; DCD6E0DE10B0AE16002005CD /* zbar.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = zbar.xcodeproj; path = ../../iphone/zbar.xcodeproj; sourceTree = SOURCE_ROOT; }; DCD6E13B10B0AFD4002005CD /* libiconv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libiconv.dylib; path = usr/lib/libiconv.dylib; sourceTree = SDKROOT; }; + DCDC6D9A11ACA23000021380 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; }; + DCDC6D9E11ACA23900021380 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; }; + DCDC6DEB11ACA5B400021380 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -67,6 +73,9 @@ DCB9118510BC5DA200B907F0 /* QuartzCore.framework in Frameworks */, DCB9118810BC5DB500B907F0 /* libiconv.dylib in Frameworks */, DCB9119B10BC5DCB00B907F0 /* libzbar.a in Frameworks */, + DCDC6D9B11ACA23000021380 /* CoreVideo.framework in Frameworks */, + DCDC6D9F11ACA23900021380 /* CoreMedia.framework in Frameworks */, + DCDC6DEC11ACA5B400021380 /* AVFoundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -106,6 +115,9 @@ 1D30AB110D05D00D00671497 /* Foundation.framework */, 288765FC0DF74451002DB57D /* CoreGraphics.framework */, DCB9118410BC5DA200B907F0 /* QuartzCore.framework */, + DCDC6DEB11ACA5B400021380 /* AVFoundation.framework */, + DCDC6D9A11ACA23000021380 /* CoreVideo.framework */, + DCDC6D9E11ACA23900021380 /* CoreMedia.framework */, DCD6E13B10B0AFD4002005CD /* libiconv.dylib */, ); name = Frameworks; @@ -243,8 +255,10 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ../../include; + IPHONEOS_DEPLOYMENT_TARGET = 3.1.2; PREBINDING = NO; - SDKROOT = iphoneos3.1.3; + RUN_CLANG_STATIC_ANALYZER = YES; + SDKROOT = iphoneos4.0; }; name = Debug; }; @@ -258,7 +272,7 @@ GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ../../include; PREBINDING = NO; - SDKROOT = iphoneos3.1.3; + SDKROOT = iphoneos4.0; }; name = Release; }; @@ -274,7 +288,7 @@ HEADER_SEARCH_PATHS = ../../include; PREBINDING = NO; "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; - SDKROOT = iphoneos3.1.3; + SDKROOT = iphoneos4.0; }; name = AdHoc; }; diff --git a/zbar/refcnt.c b/zbar/refcnt.c index 592fc12..657d061 100644 --- a/zbar/refcnt.c +++ b/zbar/refcnt.c @@ -23,7 +23,7 @@ #include "refcnt.h" -#ifdef HAVE_LIBPTHREAD +#if !defined(_WIN32) && !defined(TARGET_OS_MAC) && defined(HAVE_LIBPTHREAD) pthread_once_t initialized = PTHREAD_ONCE_INIT; pthread_mutex_t _zbar_reflock; diff --git a/zbar/refcnt.h b/zbar/refcnt.h index d7fe912..34727e3 100644 --- a/zbar/refcnt.h +++ b/zbar/refcnt.h @@ -45,6 +45,18 @@ static inline int _zbar_refcnt (refcnt_t *cnt, return(rc); } +#elif defined(TARGET_OS_MAC) +# include + +typedef int32_t refcnt_t; + +static inline int _zbar_refcnt (refcnt_t *cnt, + int delta) +{ + int rc = OSAtomicAdd32Barrier(delta, cnt); + assert(rc >= 0); + return(rc); +} #elif defined(HAVE_LIBPTHREAD) # include From 8ea95e5f8c452e74bd8cffbc1f923208de04f57a Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 5 Jun 2010 20:11:48 -0400 Subject: [PATCH 199/328] fix crop position info --- zbar/img_scanner.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 79820a2..98449cc 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -676,11 +676,11 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, iscn->v = y; while(y < cy1) { - int cx0; + int cx0 = img->crop_x;; zprintf(128, "img_x+: %04d,%04d @%p\n", x, y, p); svg_path_start("vedge", 1. / 32, 0, y + 0.5); iscn->dx = iscn->du = 1; - iscn->umin = 0; + iscn->umin = cx0; while(x < cx1) { uint8_t d = *p; movedelta(1, 0); @@ -698,8 +698,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, zprintf(128, "img_x-: %04d,%04d @%p\n", x, y, p); svg_path_start("vedge", -1. / 32, w, y + 0.5); iscn->dx = iscn->du = -1; - iscn->umin = w; - cx0 = img->crop_x; + iscn->umin = cx1; while(x >= cx0) { uint8_t d = *p; movedelta(-1, 0); @@ -731,11 +730,11 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, iscn->v = x; while(x < cx1) { - int cy0; + int cy0 = img->crop_y; zprintf(128, "img_y+: %04d,%04d @%p\n", x, y, p); svg_path_start("vedge", 1. / 32, 0, x + 0.5); iscn->dy = iscn->du = 1; - iscn->umin = 0; + iscn->umin = cy0; while(y < cy1) { uint8_t d = *p; movedelta(0, 1); @@ -753,8 +752,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, zprintf(128, "img_y-: %04d,%04d @%p\n", x, y, p); svg_path_start("vedge", -1. / 32, h, x + 0.5); iscn->dy = iscn->du = -1; - iscn->umin = h; - cy0 = img->crop_y; + iscn->umin = cy1; while(y >= cy0) { uint8_t d = *p; movedelta(0, -1); From 7fba8d829be0842dc954eee30398cdb361c65186 Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 6 Jun 2010 11:15:51 -0400 Subject: [PATCH 200/328] add iPhone zoom support, integrate with crop --- ChangeLog | 1 + include/zbar/ZBarCaptureReader.h | 10 +- include/zbar/ZBarImage.h | 1 + include/zbar/ZBarReaderView.h | 17 +++ include/zbar/ZBarReaderViewController.h | 6 +- iphone/ZBarCaptureReader.m | 68 ++++++++---- iphone/ZBarImage.m | 21 +++- iphone/ZBarReaderView.m | 140 ++++++++++++++++++++---- iphone/ZBarReaderViewController.m | 50 ++++----- zbar/img_scanner.c | 14 +-- 10 files changed, 243 insertions(+), 85 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8bf4a2f..031a22b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * 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 diff --git a/include/zbar/ZBarCaptureReader.h b/include/zbar/ZBarCaptureReader.h index 836363f..97853e0 100644 --- a/include/zbar/ZBarCaptureReader.h +++ b/include/zbar/ZBarCaptureReader.h @@ -56,6 +56,7 @@ ZBarCVImage *result; int32_t running; int framecnt; + unsigned width, height; uint64_t t_frame, t_fps, t_scan; CGFloat dt_frame; } @@ -73,14 +74,17 @@ @property (nonatomic, readonly) AVCaptureOutput *captureOutput; // delegate is notified of decode results and symbol tracking. -@property (assign) id captureDelegate; +@property (nonatomic, assign) id captureDelegate; // access to image scanner for configuration. -@property (readonly) ZBarImageScanner *scanner; +@property (nonatomic, readonly) ZBarImageScanner *scanner; // region of image to scan in normalized coordinates. // NB horizontal crop currently ignored... -@property (assign) CGRect scanCrop; +@property (nonatomic, assign) CGRect scanCrop; + +// size of video frames. +@property (nonatomic, readonly) CGSize size; // current frame rate (for debug/optimization). // only valid when running diff --git a/include/zbar/ZBarImage.h b/include/zbar/ZBarImage.h index 2d091ac..dcb8644 100644 --- a/include/zbar/ZBarImage.h +++ b/include/zbar/ZBarImage.h @@ -40,6 +40,7 @@ using namespace zbar; @property (nonatomic) unsigned long format; @property (nonatomic) unsigned sequence; @property (nonatomic) CGSize size; +@property (nonatomic) CGRect crop; @property (readonly, nonatomic) const void *data; @property (readonly, nonatomic) unsigned long dataLength; @property (copy, nonatomic) ZBarSymbolSet *symbols; diff --git a/include/zbar/ZBarReaderView.h b/include/zbar/ZBarReaderView.h index 8ab96c5..0c7baf0 100644 --- a/include/zbar/ZBarReaderView.h +++ b/include/zbar/ZBarReaderView.h @@ -49,6 +49,9 @@ id readerDelegate; AVCaptureSession *session; AVCaptureDevice *device; + CGRect scanCrop; + CGAffineTransform previewTransform; + CGFloat zoom, zoom0; BOOL tracksSymbols, showsFPS; AVCaptureInput *input; @@ -57,6 +60,7 @@ CALayer *tracking; UIView *fpsView; UILabel *fpsLabel; + UIPinchGestureRecognizer *pinch; BOOL started, running; } @@ -79,13 +83,26 @@ // (default YES). @property (nonatomic) BOOL tracksSymbols; +// enable pinch gesture recognition for zooming the preview/decode +// (default YES). +@property (nonatomic) BOOL allowsPinchZoom; + // whether to display the frame rate for debug/configuration // (default NO). @property (nonatomic) BOOL showsFPS; +// zoom scale factor applied to video preview *and* scanCrop. +// also updated by pinch-zoom gesture. clipped to range [1,2], +// defaults to 1.25 +@property (nonatomic) CGFloat zoom; + // the region of the image that will be scanned. normalized coordinates. @property (nonatomic) CGRect scanCrop; +// additional transform applied to video preview. +// (NB *not* applied to scan crop) +@property (nonatomic) CGAffineTransform previewTransform; + // specify an alternate capture device. @property (nonatomic, retain) AVCaptureDevice *device; diff --git a/include/zbar/ZBarReaderViewController.h b/include/zbar/ZBarReaderViewController.h index 6f96e5a..ad70b0e 100644 --- a/include/zbar/ZBarReaderViewController.h +++ b/include/zbar/ZBarReaderViewController.h @@ -38,6 +38,7 @@ id readerDelegate; ZBarReaderView *readerView; UIView *cameraOverlayView; + CGAffineTransform cameraViewTransform; CGRect scanCrop; BOOL showsZBarControls; @@ -66,6 +67,9 @@ // showsZBarControls enabled (but not if you want backward compatibility) @property (nonatomic, retain) UIView *cameraOverlayView; +// transform applied to the preview image. +@property (nonatomic) CGAffineTransform cameraViewTransform; + // display the built-in help browser. the argument will be passed to // the onZBarHelp() javascript function. - (void) showHelpWithReason: (NSString*) reason; @@ -79,7 +83,7 @@ @property (nonatomic) BOOL allowsEditing; // NO @property (nonatomic) BOOL allowsImageEditing; // NO @property (nonatomic) BOOL showsCameraControls; // NO -@property (nonatomic) BOOL showsHelpOnFail; // NO +@property (nonatomic) BOOL showsHelpOnFail; // ignored @property (nonatomic) ZBarReaderControllerCameraMode cameraMode; // Sampling @property (nonatomic) BOOL takesPicture; // NO @property (nonatomic) BOOL enableCache; // ignored diff --git a/iphone/ZBarCaptureReader.m b/iphone/ZBarCaptureReader.m index 3d4b06e..1651366 100644 --- a/iphone/ZBarCaptureReader.m +++ b/iphone/ZBarCaptureReader.m @@ -32,6 +32,7 @@ @implementation ZBarCaptureReader @synthesize captureOutput, captureDelegate, scanner, scanCrop, framesPerSecond; +@dynamic size; - (void) initResult { @@ -125,6 +126,38 @@ - (void) willStopRunning return; } +- (void) setCaptureDelegate: (id) delegate +{ + @synchronized(scanner) { + captureDelegate = delegate; + } +} + +- (CGSize) size +{ + @synchronized(scanner) { + return(CGSizeMake(width, height)); + } +} + +- (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 @@ -212,25 +245,24 @@ - (void) captureOutput: (AVCaptureOutput*) output void *data = CVPixelBufferGetBaseAddressOfPlane(buf, 0); if(data) { - int yc = h * scanCrop.origin.y + .5; - if(yc < 0) - yc = 0; - if(yc >= h) - yc = h - 1; - int hc = h * scanCrop.size.height + .5; - if(hc <= 0) - hc = 1; - if(yc + hc > h) - hc = h - yc; - image.size = CGSizeMake(w, hc); - [image setData: data + w * yc - withLength: w * hc]; + [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; + image.size = CGSizeMake(w, h); + [self cropUpdate]; + } + ngood = [scanner scanImage: image]; syms = scanner.results; + doTrack = [captureDelegate respondsToSelector: + @selector(captureReader:didTrackSymbols:)]; } now = timer_now(); @@ -239,11 +271,10 @@ - (void) captureOutput: (AVCaptureOutput*) output syms.filterSymbols = NO; int nraw = syms.count; if(nraw > 0) - zlog(@"scan image: %dx%d ngood=%d nraw=%d", - w, hc, ngood, nraw); + zlog(@"scan image: %dx%d crop=%@ ngood=%d nraw=%d", + w, h, NSStringFromCGRect(image.crop), ngood, nraw); - SEL cb = @selector(captureReader:didReadNewSymbolsFromImage:); - if(ngood && [captureDelegate respondsToSelector: cb]) { + if(ngood) { // copy image data so we can release the buffer result.size = CGSizeMake(w, h); result.pixelBuffer = buf; @@ -257,8 +288,7 @@ - (void) captureOutput: (AVCaptureOutput*) output [self initResult]; } - cb = @selector(captureReader:didTrackSymbols:); - if(nraw && [captureDelegate respondsToSelector: cb]) + if(nraw && doTrack) [self performSelectorOnMainThread: @selector(didTrackSymbols:) withObject: syms diff --git a/iphone/ZBarImage.m b/iphone/ZBarImage.m index ddf3a71..c32080c 100644 --- a/iphone/ZBarImage.m +++ b/iphone/ZBarImage.m @@ -33,7 +33,8 @@ static void image_cleanup(zbar_image_t *zimg) @implementation ZBarImage -@dynamic format, sequence, size, data, dataLength, symbols, zbarImage, UIImage; +@dynamic format, sequence, size, crop, data, dataLength, symbols, zbarImage, + UIImage; + (unsigned long) fourcc: (NSString*) format { @@ -178,8 +179,9 @@ - (void) setSequence: (unsigned) seq - (CGSize) size { - return(CGSizeMake(zbar_image_get_width(zimg), - zbar_image_get_height(zimg))); + unsigned w, h; + zbar_image_get_size(zimg, &w, &h); + return(CGSizeMake(w, h)); } - (void) setSize: (CGSize) size @@ -187,6 +189,19 @@ - (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] diff --git a/iphone/ZBarReaderView.m b/iphone/ZBarReaderView.m index e78e0c7..5f7c28f 100644 --- a/iphone/ZBarReaderView.m +++ b/iphone/ZBarReaderView.m @@ -29,8 +29,9 @@ @implementation ZBarReaderView -@synthesize readerDelegate, showsFPS, tracksSymbols, session, captureReader; -@dynamic scanner, scanCrop, device; +@synthesize readerDelegate, tracksSymbols, showsFPS, zoom, scanCrop, + previewTransform, session, captureReader; +@dynamic scanner, allowsPinchZoom, device; - (id) initWithImageScanner: (ZBarImageScanner*) _scanner { @@ -45,6 +46,9 @@ - (id) initWithImageScanner: (ZBarImageScanner*) _scanner UIViewAutoresizingFlexibleHeight; tracksSymbols = YES; + scanCrop = CGRectMake(0, 0, 1, 1); + previewTransform = CGAffineTransformIdentity; + session = [AVCaptureSession new]; NSNotificationCenter *notify = [NSNotificationCenter defaultCenter]; @@ -81,16 +85,17 @@ - (id) initWithImageScanner: (ZBarImageScanner*) _scanner layerWithSession: session] retain]; preview.frame = self.bounds; + preview.videoGravity = AVLayerVideoGravityResizeAspectFill; [self.layer addSublayer: preview]; - CGRect r = self.bounds; + CGRect r = preview.bounds; tracking = [CALayer new]; tracking.frame = r; tracking.opacity = 0; tracking.borderWidth = 1; tracking.backgroundColor = [UIColor clearColor].CGColor; tracking.borderColor = [UIColor greenColor].CGColor; - [self.layer addSublayer: tracking]; + [preview addSublayer: tracking]; r.origin.x = 3 * r.size.width / 4; r.origin.y = r.size.height - 32; @@ -117,6 +122,13 @@ - (id) initWithImageScanner: (ZBarImageScanner*) _scanner fpsLabel.textAlignment = UITextAlignmentRight; [fpsView addSubview: fpsLabel]; + pinch = [[UIPinchGestureRecognizer alloc] + initWithTarget: self + action: @selector(handlePinch)]; + [self addGestureRecognizer: pinch]; + + self.zoom = 1.25; + return(self); } @@ -167,6 +179,8 @@ - (void) dealloc session = nil; [tracking release]; tracking = nil; + [pinch release]; + pinch = nil; [super dealloc]; } @@ -175,14 +189,34 @@ - (ZBarImageScanner*) scanner return(captureReader.scanner); } -- (CGRect) scanCrop +- (void) resetTracking { - return(captureReader.scanCrop); + tracking.opacity = 0; + CGSize size = preview.bounds.size; + CGRect crop = captureReader.scanCrop; + tracking.frame = CGRectMake(crop.origin.y * size.width, + crop.origin.x * size.height, + crop.size.height * size.width, + crop.size.width * size.height); +} + +- (void) cropUpdate +{ + CGAffineTransform xfrm = + CGAffineTransformMakeTranslation(.5, .5); + CGFloat z = 1 / zoom; + xfrm = CGAffineTransformScale(xfrm, z, z); + xfrm = CGAffineTransformTranslate(xfrm, -.5, -.5); + captureReader.scanCrop = CGRectApplyAffineTransform(scanCrop, xfrm); + [self resetTracking]; } - (void) setScanCrop: (CGRect) r { - captureReader.scanCrop = r; + if(CGRectEqualToRect(scanCrop, r)) + return; + scanCrop = r; + [self cropUpdate]; } - (AVCaptureDevice*) device @@ -223,10 +257,18 @@ - (void) setTracksSymbols: (BOOL) track { if(track == tracksSymbols) return; - tracksSymbols = track; - tracking.opacity = 0; - tracking.frame = self.bounds; + [self resetTracking]; +} + +- (BOOL) allowsPinchZoom +{ + return(pinch.enabled); +} + +- (void) setAllowsPinchZoom: (BOOL) enabled +{ + pinch.enabled = enabled; } - (void) setShowsFPS: (BOOL) show @@ -247,6 +289,35 @@ - (void) setShowsFPS: (BOOL) show @catch(...) { } } +- (void) setZoom: (CGFloat) z +{ + if(z < 1.0) + z = 1.0; + if(z > 2.0) + z = 2.0; + if(z == zoom) + return; + zoom = z; + + [CATransaction begin]; + [CATransaction setAnimationDuration: .1]; + [CATransaction setAnimationTimingFunction: + [CAMediaTimingFunction functionWithName: + kCAMediaTimingFunctionLinear]]; + [preview setAffineTransform: + CGAffineTransformScale(previewTransform, z, z)]; + [CATransaction commit]; + + [self cropUpdate]; +} + +- (void) setPreviewTransform: (CGAffineTransform) xfrm +{ + previewTransform = xfrm; + [preview setAffineTransform: + CGAffineTransformScale(previewTransform, zoom, zoom)]; +} + - (void) start { if(started) @@ -256,8 +327,7 @@ - (void) start [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; - tracking.frame = self.bounds; - tracking.opacity = 0; + [self resetTracking]; fpsLabel.text = @""; [captureReader willStartRunning]; @@ -277,6 +347,8 @@ - (void) stop started = NO; } +// AVCaptureSession notifications + - (void) onVideoStart: (NSNotification*) note { zlog(@"onVideoStart: running=%d %@", running, note); @@ -317,6 +389,31 @@ - (void) onVideoError: (NSNotification*) note [err localizedFailureReason]); } +// UIGestureRecognizer callback + +- (void) handlePinch +{ + if(pinch.state == UIGestureRecognizerStateBegan) + zoom0 = zoom; + CGFloat z = zoom0 * pinch.scale; + self.zoom = z; + + if((zoom < 1.5) != (z < 1.5)) { + int d = (z < 1.5) ? 3 : 2; + ZBarImageScanner *scanner = captureReader.scanner; + @synchronized(scanner) { + [scanner setSymbology: 0 + config: ZBAR_CFG_X_DENSITY + to: d]; + [scanner setSymbology: 0 + config: ZBAR_CFG_Y_DENSITY + to: d]; + } + } +} + +// NSKeyValueObserving + - (void) observeValueForKeyPath: (NSString*) path ofObject: (id) obj change: (NSDictionary*) info @@ -328,6 +425,8 @@ - (void) observeValueForKeyPath: (NSString*) path captureReader.framesPerSecond]; } +// ZBarCaptureDelegate + - (void) updateTracking: (CALayer*) trk withSymbol: (ZBarSymbol*) sym { @@ -336,12 +435,13 @@ - (void) updateTracking: (CALayer*) trk CGRect b = sym.bounds; CGPoint c = CGPointMake(CGRectGetMidX(b), CGRectGetMidY(b)); - CGSize size = preview.bounds.size; - CGPoint p = CGPointMake((480 - c.y) * size.width / 480, - c.x * size.height / 640); + CGSize isize = captureReader.size; + CGSize psize = preview.bounds.size; + CGPoint p = CGPointMake((isize.height - c.y) * psize.width / isize.height, + c.x * psize.height / isize.width); CGRect r = CGRectMake(0, 0, - b.size.height * size.width / 480, - b.size.width * size.height / 640); + b.size.height * psize.width / isize.height, + b.size.width * psize.height / isize.width); if(r.size.width <= 24 && r.size.height <= 24) return; r = CGRectInset(r, -16, -16); @@ -363,7 +463,7 @@ - (void) updateTracking: (CALayer*) trk [CABasicAnimation animationWithKeyPath: @"bounds"]; resize.fromValue = [NSValue valueWithCGRect: cr]; resize.toValue = [NSValue valueWithCGRect: r]; - resize.duration = .3; + resize.duration = .2; resize.timingFunction = linear; resize.fillMode = kCAFillModeForwards; resize.removedOnCompletion = NO; @@ -372,7 +472,7 @@ - (void) updateTracking: (CALayer*) trk [CABasicAnimation animationWithKeyPath: @"position"]; move.fromValue = [NSValue valueWithCGPoint: cp]; move.toValue = [NSValue valueWithCGPoint: p]; - move.duration = .3; + move.duration = .2; move.timingFunction = linear; move.fillMode = kCAFillModeForwards; move.removedOnCompletion = NO; @@ -381,7 +481,7 @@ - (void) updateTracking: (CALayer*) trk [CABasicAnimation animationWithKeyPath: @"opacity"]; on.fromValue = [NSNumber numberWithDouble: current.opacity]; on.toValue = [NSNumber numberWithDouble: 1]; - on.duration = .3; + on.duration = .2; on.timingFunction = linear; on.fillMode = kCAFillModeForwards; on.removedOnCompletion = NO; diff --git a/iphone/ZBarReaderViewController.m b/iphone/ZBarReaderViewController.m index 593d11f..393e51c 100644 --- a/iphone/ZBarReaderViewController.m +++ b/iphone/ZBarReaderViewController.m @@ -31,7 +31,7 @@ @implementation ZBarReaderViewController @synthesize scanner, readerDelegate, showsZBarControls, cameraOverlayView, - readerView, scanCrop; + cameraViewTransform, readerView, scanCrop; @dynamic sourceType, allowsEditing, allowsImageEditing, showsCameraControls, showsHelpOnFail, cameraMode, takesPicture, maxScanDimension; @@ -58,6 +58,7 @@ - (id) init showsZBarControls = YES; scanCrop = CGRectMake(0, 0, 1, 1); + cameraViewTransform = CGAffineTransformIdentity; // create our own scanner to store configuration, // independent of whether view is loaded @@ -160,6 +161,7 @@ - (void) viewDidLoad initWithImageScanner: scanner]; readerView.readerDelegate = (id)self; readerView.scanCrop = scanCrop; + readerView.previewTransform = cameraViewTransform; [view addSubview: readerView]; [self initControls]; @@ -212,16 +214,6 @@ - (void) viewDidDisappear: (BOOL) animated [self viewDidUnload]; } -- (BOOL) enableCache -{ - return(NO); -} - -- (void) setEnableCache: (BOOL) enable -{ - // NB ignoring deprecated property -} - - (ZBarReaderView*) readerView { self.view; @@ -248,18 +240,12 @@ - (void) setCameraOverlayView: (UIView*) newview [oldview release]; } -#if 0 -- (CGAffineTransform) cameraViewTransform +- (void) setCameraViewTransform: (CGAffineTransform) xfrm { - // FIXME TBD - return(CGAffineTransformIdentity); -} - -- (void) setCameraViewTransform -{ - // FIXME TBD + cameraViewTransform = xfrm; + if(readerView) + readerView.previewTransform = xfrm; } -#endif - (void) cancel { @@ -331,24 +317,26 @@ - (void) readerView: (ZBarReaderView*) view // "deprecated" properties -#define DEPRECATED_PROPERTY(getter, setter, type, val) \ +#define DEPRECATED_PROPERTY(getter, setter, type, val, ignore) \ - (type) getter \ { \ return(val); \ } \ - (void) setter: (type) v \ { \ - NSAssert2(v == val, @"attempt to set unsupported value (%d)" \ + NSAssert2(ignore || v == val, \ + @"attempt to set unsupported value (%d)" \ @" for %@ property", val, @#getter); \ } -DEPRECATED_PROPERTY(sourceType, setSourceType, UIImagePickerControllerSourceType, UIImagePickerControllerSourceTypeCamera) -DEPRECATED_PROPERTY(allowsEditing, setAllowsEditing, BOOL, NO) -DEPRECATED_PROPERTY(allowsImageEditing, setAllowsImageEditing, BOOL, NO) -DEPRECATED_PROPERTY(showsCameraControls, setShowsCameraControls, BOOL, NO) -DEPRECATED_PROPERTY(showsHelpOnFail, setShowsHelpOnFail, BOOL, NO) -DEPRECATED_PROPERTY(cameraMode, setCameraMode, ZBarReaderControllerCameraMode, ZBarReaderControllerCameraModeSampling) -DEPRECATED_PROPERTY(takesPicture, setTakesPicture, BOOL, NO) -DEPRECATED_PROPERTY(maxScanDimension, setMaxScanDimension, NSInteger, 640) +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(enableCache, setEnableCache, BOOL, YES, YES) +DEPRECATED_PROPERTY(maxScanDimension, setMaxScanDimension, NSInteger, 640, YES) @end diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 79820a2..b704fd5 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -676,11 +676,11 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, iscn->v = y; while(y < cy1) { - int cx0; + int cx0 = img->crop_x;; zprintf(128, "img_x+: %04d,%04d @%p\n", x, y, p); svg_path_start("vedge", 1. / 32, 0, y + 0.5); iscn->dx = iscn->du = 1; - iscn->umin = 0; + iscn->umin = cx0; while(x < cx1) { uint8_t d = *p; movedelta(1, 0); @@ -698,8 +698,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, zprintf(128, "img_x-: %04d,%04d @%p\n", x, y, p); svg_path_start("vedge", -1. / 32, w, y + 0.5); iscn->dx = iscn->du = -1; - iscn->umin = w; - cx0 = img->crop_x; + iscn->umin = cx1; while(x >= cx0) { uint8_t d = *p; movedelta(-1, 0); @@ -731,11 +730,11 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, iscn->v = x; while(x < cx1) { - int cy0; + int cy0 = img->crop_y;; zprintf(128, "img_y+: %04d,%04d @%p\n", x, y, p); svg_path_start("vedge", 1. / 32, 0, x + 0.5); iscn->dy = iscn->du = 1; - iscn->umin = 0; + iscn->umin = cy0; while(y < cy1) { uint8_t d = *p; movedelta(0, 1); @@ -753,8 +752,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, zprintf(128, "img_y-: %04d,%04d @%p\n", x, y, p); svg_path_start("vedge", -1. / 32, h, x + 0.5); iscn->dy = iscn->du = -1; - iscn->umin = h; - cy0 = img->crop_y; + iscn->umin = cy1; while(y >= cy0) { uint8_t d = *p; movedelta(0, -1); From 7f3693c87ea621c86201ac5dcfe7c6f026b054a0 Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 7 Jun 2010 09:00:35 -0400 Subject: [PATCH 201/328] 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 --- ChangeLog | 4 ++++ include/zbar.h | 2 ++ zbar/convert.c | 21 +++------------------ zbar/image.c | 7 +------ zbar/image.h | 11 +++++++++++ zbar/img_scanner.c | 39 ++++++++++++++++++++++++++++----------- zbar/jpeg.c | 10 ++++++++-- zbar/video.c | 9 +++------ 8 files changed, 60 insertions(+), 43 deletions(-) diff --git a/ChangeLog b/ChangeLog index 988c521..e530ce8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,8 @@ current: + * 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 diff --git a/include/zbar.h b/include/zbar.h index 9e26eb4..399dd91 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -144,6 +144,8 @@ 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 */ diff --git a/zbar/convert.c b/zbar/convert.c index f328b29..b0da7ca 100644 --- a/zbar/convert.c +++ b/zbar/convert.c @@ -966,22 +966,12 @@ static void convert_jpeg (zbar_image_t *dst, if(!src->src) { tmp = zbar_image_create(); tmp->format = fourcc('Y','8','0','0'); - tmp->width = dst->width; - tmp->height = dst->height; - tmp->crop_x = dst->crop_x; - tmp->crop_y = dst->crop_y; - tmp->crop_w = dst->crop_w; - tmp->crop_h = dst->crop_h; + _zbar_image_copy_size(tmp, dst); } else { tmp = src->src->jpeg_img; assert(tmp); - dst->width = tmp->width; - dst->height = tmp->height; - dst->crop_x = tmp->crop_x; - dst->crop_y = tmp->crop_y; - dst->crop_w = tmp->crop_w; - dst->crop_h = tmp->crop_h; + _zbar_image_copy_size(dst, tmp); } const zbar_format_def_t *tmpfmt = _zbar_format_lookup(tmp->format); @@ -991,12 +981,7 @@ static void convert_jpeg (zbar_image_t *dst, _zbar_convert_jpeg_to_y(tmp, tmpfmt, src, srcfmt); /* now convert to dst */ - dst->width = tmp->width; - dst->height = tmp->height; - dst->crop_x = tmp->crop_x; - dst->crop_y = tmp->crop_y; - dst->crop_w = tmp->crop_w; - dst->crop_h = tmp->crop_h; + _zbar_image_copy_size(dst, tmp); conversion_handler_t *func = conversions[tmpfmt->group][dstfmt->group].func; diff --git a/zbar/image.c b/zbar/image.c index 99e1303..2dd47a7 100644 --- a/zbar/image.c +++ b/zbar/image.c @@ -203,12 +203,7 @@ zbar_image_t *zbar_image_copy (const zbar_image_t *src) { zbar_image_t *dst = zbar_image_create(); dst->format = src->format; - dst->width = src->width; - dst->height = src->height; - dst->crop_x = src->crop_x; - dst->crop_y = src->crop_y; - dst->crop_w = src->crop_w; - dst->crop_h = src->crop_h; + _zbar_image_copy_size(dst, src); dst->datalen = src->datalen; dst->data = malloc(src->datalen); assert(dst->data); diff --git a/zbar/image.h b/zbar/image.h index a3ea15d..0a8ba2c 100644 --- a/zbar/image.h +++ b/zbar/image.h @@ -128,4 +128,15 @@ static inline void _zbar_image_swap_symbols (zbar_image_t *a, b->syms = tmp; } +static inline void _zbar_image_copy_size (zbar_image_t *dst, + const zbar_image_t *src) +{ + dst->width = src->width; + dst->height = src->height; + dst->crop_x = src->crop_x; + dst->crop_y = src->crop_y; + dst->crop_w = src->crop_w; + dst->crop_h = src->crop_h; +} + #endif diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 98449cc..2749d4a 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -51,11 +51,6 @@ /* FIXME cache setting configurability */ -/* number of times the same result must be detected - * in "nearby" images before being reported - */ -#define CACHE_CONSISTENCY 3 /* images */ - /* time interval for which two images are considered "nearby" */ #define CACHE_PROXIMITY 1000 /* ms */ @@ -113,6 +108,7 @@ struct zbar_image_scanner_s { /* configuration settings */ unsigned config; /* config flags */ int configs[NUM_SCN_CFGS]; /* int valued configurations */ + int sym_configs[1][16]; /* per-symbology configurations */ #ifndef NO_STATS int stat_syms_new; @@ -297,9 +293,8 @@ static inline zbar_symbol_t *cache_lookup (zbar_image_scanner_t *iscn, static inline void cache_sym (zbar_image_scanner_t *iscn, zbar_symbol_t *sym) { - uint32_t age, near_thresh, far_thresh, dup; if(iscn->enable_cache) { - char qr = (sym->type == ZBAR_QRCODE); + uint32_t age, near_thresh, far_thresh, dup; zbar_symbol_t *entry = cache_lookup(iscn, sym); if(!entry) { /* FIXME reuse sym */ @@ -307,7 +302,7 @@ static inline void cache_sym (zbar_image_scanner_t *iscn, sym->datalen + 1); memcpy(entry->data, sym->data, sym->datalen); entry->time = sym->time - CACHE_HYSTERESIS; - entry->cache_count = (qr) ? 0 : -CACHE_CONSISTENCY; + entry->cache_count = 0; /* add to cache */ entry->next = iscn->cache; iscn->cache = entry; @@ -319,8 +314,11 @@ static inline void cache_sym (zbar_image_scanner_t *iscn, near_thresh = (age < CACHE_PROXIMITY); far_thresh = (age >= CACHE_HYSTERESIS); dup = (entry->cache_count >= 0); - if((!dup && !near_thresh) || far_thresh) - entry->cache_count = (qr) ? 0 : -CACHE_CONSISTENCY; + if((!dup && !near_thresh) || far_thresh) { + int type = sym->type; + int h = ((type - (type >> 3)) ^ (type >> 5)) & 0xf; + entry->cache_count = -iscn->sym_configs[0][h]; + } else if(dup || near_thresh) entry->cache_count++; @@ -483,6 +481,10 @@ zbar_image_scanner_t *zbar_image_scanner_create () CFG(iscn, ZBAR_CFG_X_DENSITY) = 1; CFG(iscn, ZBAR_CFG_Y_DENSITY) = 1; zbar_image_scanner_set_config(iscn, 0, ZBAR_CFG_POSITION, 1); + zbar_image_scanner_set_config(iscn, 0, ZBAR_CFG_UNCERTAINTY, 2); + zbar_image_scanner_set_config(iscn, ZBAR_QRCODE, ZBAR_CFG_UNCERTAINTY, 0); + zbar_image_scanner_set_config(iscn, ZBAR_CODE128, ZBAR_CFG_UNCERTAINTY, 0); + zbar_image_scanner_set_config(iscn, ZBAR_CODE39, ZBAR_CFG_UNCERTAINTY, 0); return(iscn); } @@ -551,9 +553,24 @@ int zbar_image_scanner_set_config (zbar_image_scanner_t *iscn, zbar_config_t cfg, int val) { - if(cfg < ZBAR_CFG_POSITION) + if(cfg < ZBAR_CFG_UNCERTAINTY) return(zbar_decoder_set_config(iscn->dcode, sym, cfg, val)); + if(cfg < ZBAR_CFG_POSITION) { + int c, i; + if(cfg > ZBAR_CFG_UNCERTAINTY) + return(1); + c = cfg - ZBAR_CFG_UNCERTAINTY; + if(sym > ZBAR_PARTIAL) { + i = ((sym - (sym >> 3)) ^ (sym >> 5)) & 0xf; + iscn->sym_configs[c][i] = val; + } + else + for(i = 0; i < 16; i++) + iscn->sym_configs[c][i] = val; + return(0); + } + if(sym > ZBAR_PARTIAL) return(1); diff --git a/zbar/jpeg.c b/zbar/jpeg.c index fb566f4..6351731 100644 --- a/zbar/jpeg.c +++ b/zbar/jpeg.c @@ -195,10 +195,16 @@ void _zbar_convert_jpeg_to_y (zbar_image_t *dst, jpeg_start_decompress(cinfo); /* adjust dst image parameters to match(?) decompressor */ - if(dst->width < cinfo->output_width) + if(dst->width < cinfo->output_width) { dst->width = cinfo->output_width; - if(dst->height < cinfo->output_height) + if(dst->crop_x + dst->crop_w > dst->width) + dst->crop_w = dst->width - dst->crop_x; + } + if(dst->height < cinfo->output_height) { dst->height = cinfo->output_height; + if(dst->crop_y + dst->crop_h > dst->height) + dst->crop_h = dst->height - dst->crop_y; + } unsigned long datalen = (cinfo->output_width * cinfo->output_height * cinfo->out_color_components); diff --git a/zbar/video.c b/zbar/video.c index 9077071..ef58717 100644 --- a/zbar/video.c +++ b/zbar/video.c @@ -244,8 +244,7 @@ static inline int video_init_images (zbar_video_t *vdo) for(i = 0; i < vdo->num_images; i++) { zbar_image_t *img = vdo->images[i]; img->format = vdo->format; - img->width = vdo->width; - img->height = vdo->height; + zbar_image_set_size(img, vdo->width, vdo->height); if(vdo->iomode != VIDEO_MMAP) { unsigned long offset = i * vdo->datalen; img->datalen = vdo->datalen; @@ -285,8 +284,7 @@ int zbar_video_init (zbar_video_t *vdo, /* create intermediate image for decoder to use*/ img = vdo->jpeg_img = zbar_image_create(); img->format = fourcc('Y','8','0','0'); - img->width = vdo->width; - img->height = vdo->height; + zbar_image_set_size(img, vdo->width, vdo->height); img->datalen = vdo->width * vdo->height; } #endif @@ -369,8 +367,7 @@ zbar_image_t *zbar_video_next_image (zbar_video_t *vdo) /* recycle the shadow images */ img->format = vdo->format; - img->width = vdo->width; - img->height = vdo->height; + zbar_image_set_size(img, vdo->width, vdo->height); img->datalen = vdo->datalen; img->data = malloc(vdo->datalen); } From 6076e277c8abedd262388b4cb79450ab36dc7106 Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 7 Jun 2010 09:21:13 -0400 Subject: [PATCH 202/328] fix C++ video callback bug - add C++ processor example --- ChangeLog | 2 ++ examples/processor.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++ include/zbar/Image.h | 7 ++++++- 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 examples/processor.cpp diff --git a/ChangeLog b/ChangeLog index e530ce8..ffde5cb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * fix C++ video callback bug + - add C++ processor example * add per-symbology cache consistency - reliable symbologies decode immediately by default - no more need to disable cache with video diff --git a/examples/processor.cpp b/examples/processor.cpp new file mode 100644 index 0000000..4d03b6c --- /dev/null +++ b/examples/processor.cpp @@ -0,0 +1,45 @@ +#include +#include + +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); +} diff --git a/include/zbar/Image.h b/include/zbar/Image.h index 1ff9289..830953d 100644 --- a/include/zbar/Image.h +++ b/include/zbar/Image.h @@ -67,7 +67,12 @@ class Image { { 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); + } } } }; From a72196655519cbe5f696096c90a603061b124fc8 Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 7 Jun 2010 10:06:04 -0400 Subject: [PATCH 203/328] add c processor example --- examples/processor.c | 47 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 examples/processor.c diff --git a/examples/processor.c b/examples/processor.c new file mode 100644 index 0000000..fd2fbfb --- /dev/null +++ b/examples/processor.c @@ -0,0 +1,47 @@ +#include +#include + +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); +} From cb02bbe7998a2bd7f25b1c36bf32906356281995 Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 8 Jun 2010 09:53:39 -0400 Subject: [PATCH 204/328] fix C++ Image wrapper bug --- include/zbar/Image.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/zbar/Image.h b/include/zbar/Image.h index 830953d..a482b91 100644 --- a/include/zbar/Image.h +++ b/include/zbar/Image.h @@ -115,6 +115,7 @@ class Image { ~Image () { + zbar_image_set_userdata(_img, NULL); zbar_image_ref(_img, -1); } From 3e4874bd92873eb94da628a734dcc81277da6286 Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 8 Jun 2010 15:57:06 -0400 Subject: [PATCH 205/328] enhance iPhone readertest w/more options --- ChangeLog | 1 + include/zbar/ZBarReaderViewController.h | 3 +- iphone/ZBarReaderController.m | 13 +- iphone/ZBarReaderViewController.m | 10 -- test/iphone/readertest.m | 164 +++++++++++++++++++++++- 5 files changed, 169 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index 006ead4..6422fd4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * enhance iPhone readertest w/more options * fix C++ video callback bug - add C and C++ processor examples * add per-symbology cache consistency diff --git a/include/zbar/ZBarReaderViewController.h b/include/zbar/ZBarReaderViewController.h index ad70b0e..2c285a9 100644 --- a/include/zbar/ZBarReaderViewController.h +++ b/include/zbar/ZBarReaderViewController.h @@ -59,8 +59,7 @@ // rectangle before scanning. the rectangle is normalized to the // image size and aspect ratio; useful values will place the rectangle // between 0 and 1 on each axis, where the x-axis corresponds to the -// image major axis. defaults to the full image (0, 0, 1, 1). FIXME -// currently only works for the minor axis +// image major axis. defaults to the full image (0, 0, 1, 1). @property (nonatomic) CGRect scanCrop; // provide a custom overlay. note that this can be used with diff --git a/iphone/ZBarReaderController.m b/iphone/ZBarReaderController.m index 007d06b..5b261f4 100644 --- a/iphone/ZBarReaderController.m +++ b/iphone/ZBarReaderController.m @@ -393,6 +393,7 @@ - (ZBarSymbol*) extractBestResult: (BOOL) filter } - (void) updateBox: (ZBarSymbol*) sym + imageSize: (CGSize) size { [CATransaction begin]; [CATransaction setAnimationDuration: .3]; @@ -403,9 +404,9 @@ - (void) updateBox: (ZBarSymbol*) sym CGFloat alpha = boxLayer.opacity; if(sym) { CGRect r = sym.bounds; - // FIXME reverse image scaling - //r = crop.origin + ; 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; @@ -437,6 +438,7 @@ - (void) scanScreen [self scanImage: image withScaling: 0]; + CGSize size = CGSizeMake(CGImageGetWidth(image), CGImageGetHeight(image)); CGImageRelease(image); ZBarSymbol *sym = [self extractBestResult: NO]; @@ -469,7 +471,8 @@ - (void) scanScreen withObject: nil afterDelay: 0.001]; - [self updateBox: sym]; + [self updateBox: sym + imageSize: size]; } - (void) captureScreen @@ -529,6 +532,7 @@ - (void) scanSequence: (UIImage*) image [NSArray arrayWithObject: sym], ZBarReaderControllerResults, nil]]; + CGSize size = image.size; [image release]; // reschedule @@ -536,7 +540,8 @@ - (void) scanSequence: (UIImage*) image withObject: nil afterDelay: 0.001]; - [self updateBox: sym]; + [self updateBox: sym + imageSize: size]; } - (void) showHelpWithReason: (NSString*) reason diff --git a/iphone/ZBarReaderViewController.m b/iphone/ZBarReaderViewController.m index 393e51c..97a9b43 100644 --- a/iphone/ZBarReaderViewController.m +++ b/iphone/ZBarReaderViewController.m @@ -204,16 +204,6 @@ - (void) viewWillDisappear: (BOOL) animated [super viewWillDisappear: animated]; } -- (void) viewDidDisappear: (BOOL) animated -{ - [super viewDidDisappear: animated]; - - // workaround for rdar://8034533 - // force view to unload so session is recreated and restarts correctly - self.view = nil; - [self viewDidUnload]; -} - - (ZBarReaderView*) readerView { self.view; diff --git a/test/iphone/readertest.m b/test/iphone/readertest.m index 4845701..f8bcadd 100644 --- a/test/iphone/readertest.m +++ b/test/iphone/readertest.m @@ -10,6 +10,7 @@ SOURCE_SECTION, CAMODE_SECTION, CONFIG_SECTION, + CUSTOM_SECTION, SYMBOL_SECTION, RESULT_SECTION, NUM_SECTIONS @@ -20,10 +21,22 @@ @"SourceType", @"CameraMode", @"Reader Configuration", + nil, @"Enabled Symbologies", @"Decode Results", }; +static const CGRect const crop_choices[] = { + { { 0, 0 }, { 1, 1 } }, + { { .25, 0 }, { .5, 1 } }, + { { 0, .3 }, { 1, .4 } }, + { { 0, 0 }, { 0, 0 } } +}; + +static const NSInteger const density_choices[] = { + 3, 2, 1, 0, 4, -1 +}; + @interface AppDelegate : UITableViewController < UIApplicationDelegate, @@ -37,13 +50,14 @@ @interface AppDelegate NSMutableArray *sections, *symbolEnables; - BOOL found, paused; + BOOL found, paused, continuous; NSInteger dataHeight; UILabel *typeLabel, *dataLabel; UIImageView *imageView; ZBarReaderViewController *reader; UIView *overlay; + UILabel *typeOvl, *dataOvl; NSArray *masks; } @@ -105,6 +119,21 @@ - (void) initOverlay [overlay addSubview: label]; [label release]; + typeOvl = [[UILabel alloc] + initWithFrame: CGRectMake(0, 48, 80, 24)]; + typeOvl.backgroundColor = [UIColor clearColor]; + typeOvl.textColor = [UIColor whiteColor]; + typeOvl.font = [UIFont systemFontOfSize: 16]; + typeOvl.textAlignment = UITextAlignmentCenter; + [overlay addSubview: typeOvl]; + + dataOvl = [[UILabel alloc] + initWithFrame: CGRectMake(96, 48, 224, 24)]; + dataOvl.backgroundColor = [UIColor clearColor]; + dataOvl.textColor = [UIColor whiteColor]; + dataOvl.font = [UIFont systemFontOfSize: 16]; + [overlay addSubview: dataOvl]; + UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame: CGRectMake(0, 426, 320, 54)]; @@ -216,7 +245,7 @@ - (void) initControlCells withObject: modes]; static NSString* const configNames[] = { - @"showsZBarControls", @"enableCache", + @"showsCameraControls", @"showsZBarControls", @"enableCache", @"showsHelpOnFail", @"takesPicture", nil }; @@ -229,6 +258,44 @@ - (void) initControlCells [sections replaceObjectAtIndex: CONFIG_SECTION withObject: configs]; + UITableViewCell *cropCell = + [[[UITableViewCell alloc] + initWithStyle: UITableViewCellStyleValue1 + reuseIdentifier: nil] + autorelease]; + cropCell.textLabel.text = @"scanCrop"; + cropCell.detailTextLabel.text = NSStringFromCGRect(crop_choices[0]); + + UITableViewCell *xDensityCell = + [[[UITableViewCell alloc] + initWithStyle: UITableViewCellStyleValue1 + reuseIdentifier: nil] + autorelease]; + xDensityCell.textLabel.text = @"CFG_X_DENSITY"; + xDensityCell.detailTextLabel.tag = ZBAR_CFG_X_DENSITY; + xDensityCell.detailTextLabel.text = + [NSString stringWithFormat: @"%d", density_choices[0]]; + + UITableViewCell *yDensityCell = + [[[UITableViewCell alloc] + initWithStyle: UITableViewCellStyleValue1 + reuseIdentifier: nil] + autorelease]; + yDensityCell.textLabel.text = @"CFG_Y_DENSITY"; + yDensityCell.detailTextLabel.tag = ZBAR_CFG_Y_DENSITY; + yDensityCell.detailTextLabel.text = + [NSString stringWithFormat: @"%d", density_choices[0]]; + + [sections replaceObjectAtIndex: CUSTOM_SECTION + withObject: [NSArray arrayWithObjects: + xDensityCell, + yDensityCell, + cropCell, + [self cellWithTitle: @"continuous" + tag: 1 + checked: NO], + nil]]; + static const int symbolValues[] = { ZBAR_QRCODE, ZBAR_CODE128, ZBAR_CODE39, ZBAR_I25, ZBAR_EAN13, ZBAR_EAN8, ZBAR_UPCA, ZBAR_UPCE, ZBAR_ISBN13, ZBAR_ISBN10, @@ -285,9 +352,9 @@ - (void) viewDidLoad withObject: classes]; UITableViewCell *typeCell = [UITableViewCell new]; - typeLabel = typeCell.textLabel; + typeLabel = [typeCell.textLabel retain]; UITableViewCell *dataCell = [UITableViewCell new]; - dataLabel = dataCell.textLabel; + dataLabel = [dataCell.textLabel retain]; dataLabel.numberOfLines = 0; dataLabel.lineBreakMode = UILineBreakModeCharacterWrap; UITableViewCell *imageCell = [UITableViewCell new]; @@ -319,6 +386,10 @@ - (void) viewDidUnload dataLabel = nil; [imageView release]; imageView = nil; + [typeOvl release]; + typeOvl = nil; + [dataOvl release]; + dataOvl = nil; [overlay release]; overlay = nil; [masks release]; @@ -343,6 +414,8 @@ - (void) scan imageView.image = nil; typeLabel.text = nil; dataLabel.text = nil; + typeOvl.text = nil; + dataOvl.text = nil; [self.tableView reloadData]; if([reader respondsToSelector: @selector(readerView)]) reader.readerView.showsFPS = YES; @@ -428,6 +501,55 @@ - (void) alertUnsupported [alert release]; } +- (void) advanceCrop: (UILabel*) label +{ + CGRect r = CGRectFromString(label.text); + int i; + for(i = 0; crop_choices[i].size.width;) + if(CGRectEqualToRect(r, crop_choices[i++])) + break; + if(!crop_choices[i].size.width) + i = 0; + r = crop_choices[i]; + reader.scanCrop = r; + label.text = NSStringFromCGRect(r); + + r.origin.x *= 426; + r.origin.y *= 320; + r.size.width *= 426; + r.size.height *= 320; + UIView *mask = [masks objectAtIndex: 0]; + mask.frame = CGRectMake(0, 0, 320, r.origin.x); + mask = [masks objectAtIndex: 1]; + mask.frame = CGRectMake(0, r.origin.x, r.origin.y, r.size.width); + + r.origin.y += r.size.height; + mask = [masks objectAtIndex: 2]; + mask.frame = CGRectMake(r.origin.y, r.origin.x, + 320 - r.origin.y, r.size.width); + + r.origin.x += r.size.width; + mask = [masks objectAtIndex: 3]; + mask.frame = CGRectMake(0, r.origin.x, 320, 426 - r.origin.x); +} + +- (void) advanceDensity: (UILabel*) label +{ + NSInteger d = [label.text integerValue]; + int i; + for(i = 0; density_choices[i] >= 0;) + if(d == density_choices[i++]) + break; + if(density_choices[i] < 0) + i = 0; + d = density_choices[i]; + assert(d >= 0); + [reader.scanner setSymbology: 0 + config: label.tag + to: d]; + label.text = [NSString stringWithFormat: @"%d", d]; +} + - (void) tableView: (UITableView*) view didSelectRowAtIndexPath: (NSIndexPath*) path { @@ -446,10 +568,12 @@ - (void) tableView: (UITableView*) view inSection: CLASS_SECTION]; break; } + case SOURCE_SECTION: [self setCheckForTag: reader.sourceType = cell.tag inSection: SOURCE_SECTION]; break; + case CAMODE_SECTION: @try { reader.cameraMode = cell.tag; @@ -460,6 +584,7 @@ - (void) tableView: (UITableView*) view [self setCheckForTag: reader.cameraMode inSection: CAMODE_SECTION]; break; + case CONFIG_SECTION: { BOOL state; NSString *key = cell.textLabel.text; @@ -482,6 +607,26 @@ - (void) tableView: (UITableView*) view reader.cameraOverlayView = (state) ? nil : overlay; break; } + + case CUSTOM_SECTION: + switch(path.row) + { + case 0: + case 1: + [self advanceDensity: cell.detailTextLabel]; + break; + case 2: + [self advanceCrop: cell.detailTextLabel]; + break; + case 3: + [self setCheck: continuous = !continuous + forCell: cell]; + break; + default: + assert(0); + } + break; + case SYMBOL_SECTION: { BOOL state = ![[symbolEnables objectAtIndex: path.row] boolValue]; [symbolEnables replaceObjectAtIndex: path.row @@ -539,16 +684,23 @@ - (void) imagePickerController: (UIImagePickerController*) picker [self performSelector: @selector(presentResult:) withObject: bestResult afterDelay: .001]; - [picker dismissModalViewControllerAnimated: YES]; + if(!continuous) + [picker dismissModalViewControllerAnimated: YES]; } - (void) presentResult: (ZBarSymbol*) sym { found = !!sym; - typeLabel.text = sym.typeName; + NSString *typeName = sym.typeName; + typeLabel.text = typeName; NSString *data = sym.data; dataLabel.text = data; + if(continuous) { + typeOvl.text = typeName; + dataOvl.text = data; + } + NSLog(@"imagePickerController:didFinishPickingMediaWithInfo:\n"); NSLog(@" type=%@ data=%@\n", sym.typeName, data); From 436b192a89e132101250b137767b8445b9a2fa92 Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 11 Jun 2010 09:35:03 -0400 Subject: [PATCH 206/328] fix iPhone async ref bug --- ChangeLog | 1 + include/zbar/ZBarCaptureReader.h | 3 +++ include/zbar/ZBarReaderController.h | 3 +++ include/zbar/ZBarReaderView.h | 3 +++ include/zbar/ZBarReaderViewController.h | 10 +++++++-- iphone/ZBarCVImage.h | 2 -- iphone/ZBarCVImage.m | 29 +++++++++++++------------ iphone/ZBarCaptureReader.m | 6 +++-- iphone/ZBarReaderController.m | 14 +++++++----- iphone/ZBarReaderView.m | 12 +++++++++- iphone/ZBarReaderViewController.m | 23 ++++++++++++++++---- test/iphone/readertest.m | 4 ++-- 12 files changed, 77 insertions(+), 33 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6422fd4..f2b320f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * fix iPhone async ref bug * enhance iPhone readertest w/more options * fix C++ video callback bug - add C and C++ processor examples diff --git a/include/zbar/ZBarCaptureReader.h b/include/zbar/ZBarCaptureReader.h index 97853e0..dbeae18 100644 --- a/include/zbar/ZBarCaptureReader.h +++ b/include/zbar/ZBarCaptureReader.h @@ -50,6 +50,7 @@ ZBarImageScanner *scanner; CGRect scanCrop; CGFloat framesPerSecond; + BOOL enableCache; dispatch_queue_t queue; ZBarImage *image; @@ -90,4 +91,6 @@ // only valid when running @property (nonatomic, readonly) CGFloat framesPerSecond; +@property (nonatomic) BOOL enableCache; + @end diff --git a/include/zbar/ZBarReaderController.h b/include/zbar/ZBarReaderController.h index 855a676..f0dd4f0 100644 --- a/include/zbar/ZBarReaderController.h +++ b/include/zbar/ZBarReaderController.h @@ -102,6 +102,9 @@ typedef enum { // how to use the camera (when sourceType == Camera) @property (nonatomic) ZBarReaderControllerCameraMode cameraMode; +// whether to outline symbols with the green tracking box. +@property (nonatomic) BOOL tracksSymbols; + // whether to automatically take a full picture when a barcode is detected // (when cameraMode == Sampling) @property (nonatomic) BOOL takesPicture; diff --git a/include/zbar/ZBarReaderView.h b/include/zbar/ZBarReaderView.h index 0c7baf0..7826f3e 100644 --- a/include/zbar/ZBarReaderView.h +++ b/include/zbar/ZBarReaderView.h @@ -110,4 +110,7 @@ @property (nonatomic, readonly) AVCaptureSession *session; @property (nonatomic, readonly) ZBarCaptureReader *captureReader; +// this flag still works, but its use is deprecated +@property (nonatomic) BOOL enableCache; + @end diff --git a/include/zbar/ZBarReaderViewController.h b/include/zbar/ZBarReaderViewController.h index 2c285a9..8ef0ced 100644 --- a/include/zbar/ZBarReaderViewController.h +++ b/include/zbar/ZBarReaderViewController.h @@ -40,7 +40,7 @@ UIView *cameraOverlayView; CGAffineTransform cameraViewTransform; CGRect scanCrop; - BOOL showsZBarControls; + BOOL showsZBarControls, tracksSymbols, enableCache; UIView *controls; BOOL statusBarHidden; @@ -55,6 +55,10 @@ // whether to use alternate control set @property (nonatomic) BOOL showsZBarControls; +// whether to show the green tracking box. note that, even when +// enabled, the box will only be visible when scanning EAN and I2/5. +@property (nonatomic) BOOL tracksSymbols; + // crop images for scanning. the image will be cropped to this // rectangle before scanning. the rectangle is normalized to the // image size and aspect ratio; useful values will place the rectangle @@ -76,6 +80,9 @@ // direct access to the ZBarReaderView @property (nonatomic, readonly) ZBarReaderView *readerView; +// this flag still works, but its use is deprecated +@property (nonatomic) BOOL enableCache; + // these are present only for backward compatibility. // they will error if inappropriate/unsupported values are set @property (nonatomic) UIImagePickerControllerSourceType sourceType; // Camera @@ -85,7 +92,6 @@ @property (nonatomic) BOOL showsHelpOnFail; // ignored @property (nonatomic) ZBarReaderControllerCameraMode cameraMode; // Sampling @property (nonatomic) BOOL takesPicture; // NO -@property (nonatomic) BOOL enableCache; // ignored @property (nonatomic) NSInteger maxScanDimension; // ignored + (BOOL) isSourceTypeAvailable: (UIImagePickerControllerSourceType) sourceType; diff --git a/iphone/ZBarCVImage.h b/iphone/ZBarCVImage.h index b1bb75a..aba60d4 100644 --- a/iphone/ZBarCVImage.h +++ b/iphone/ZBarCVImage.h @@ -39,6 +39,4 @@ @property (nonatomic, readonly) void *rgbBuffer; @property (nonatomic, readonly) NSOperation *conversion; -- (void) convertCVtoRGB; - @end diff --git a/iphone/ZBarCVImage.m b/iphone/ZBarCVImage.m index ab363cf..1e88bd8 100644 --- a/iphone/ZBarCVImage.m +++ b/iphone/ZBarCVImage.m @@ -80,24 +80,13 @@ - (void) setPixelBuffer: (CVPixelBufferRef) newbuf - (UIImage*) UIImageWithOrientation: (UIImageOrientation) orient { - NSOperationQueue *queue = conversionQueue; - if(!queue) - queue = conversionQueue = [NSOperationQueue new]; - - // start format conversion in separate thread - conversion = [[NSInvocationOperation alloc] - initWithTarget: self - selector: @selector(convertCVtoRGB) - object: nil]; - [queue addOperation: conversion]; - - // create UIImage with before converted data is available + // create UIImage before converted data is available CGSize size = self.size; int w = size.width; int h = size.height; CGDataProviderRef datasrc = - CGDataProviderCreateDirect(self, 3 * w * h, &asyncProvider); + CGDataProviderCreateDirect([self retain], 3 * w * h, &asyncProvider); CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB(); CGImageRef cgimg = CGImageCreate(w, h, 8, 24, 3 * w, cs, @@ -111,12 +100,24 @@ - (UIImage*) UIImageWithOrientation: (UIImageOrientation) orient scale: 1 orientation: orient]; CGImageRelease(cgimg); + + NSOperationQueue *queue = conversionQueue; + if(!queue) + queue = conversionQueue = [NSOperationQueue new]; + + // start format conversion in separate thread + conversion = [[NSInvocationOperation alloc] + initWithTarget: self + selector: @selector(convertCVtoRGB:) + object: uiimg]; + [queue addOperation: conversion]; + return(uiimg); } // convert video frame to a CGImage compatible RGB format // FIXME this is temporary until we can find the native way... -- (void) convertCVtoRGB +- (void) convertCVtoRGB: (UIImage*) uiimg { timer_start; unsigned long format = self.format; diff --git a/iphone/ZBarCaptureReader.m b/iphone/ZBarCaptureReader.m index 1651366..8134310 100644 --- a/iphone/ZBarCaptureReader.m +++ b/iphone/ZBarCaptureReader.m @@ -31,7 +31,8 @@ @implementation ZBarCaptureReader -@synthesize captureOutput, captureDelegate, scanner, scanCrop, framesPerSecond; +@synthesize captureOutput, captureDelegate, scanner, scanCrop, framesPerSecond, + enableCache; @dynamic size; - (void) initResult @@ -48,6 +49,7 @@ - (id) initWithImageScanner: (ZBarImageScanner*) _scanner return(nil); t_fps = t_frame = timer_now(); + enableCache = YES; scanner = [_scanner retain]; scanCrop = CGRectMake(0, 0, 1, 1); @@ -116,7 +118,7 @@ - (void) willStartRunning if(!OSAtomicCompareAndSwap32Barrier(0, 1, &running)) return; @synchronized(scanner) { - scanner.enableCache = YES; + scanner.enableCache = enableCache; } } diff --git a/iphone/ZBarReaderController.m b/iphone/ZBarReaderController.m index 5b261f4..bca1b90 100644 --- a/iphone/ZBarReaderController.m +++ b/iphone/ZBarReaderController.m @@ -38,7 +38,7 @@ @implementation ZBarReaderController @synthesize scanner, readerDelegate, cameraMode, scanCrop, maxScanDimension, - showsHelpOnFail, takesPicture, enableCache; + showsHelpOnFail, takesPicture, enableCache, tracksSymbols; @dynamic showsZBarControls; - (id) init @@ -47,7 +47,7 @@ - (id) init showsHelpOnFail = YES; hasOverlay = showsZBarControls = [self respondsToSelector: @selector(cameraOverlayView)]; - enableCache = YES; + enableCache = tracksSymbols = YES; scanCrop = CGRectMake(0, 0, 1, 1); maxScanDimension = 640; @@ -471,8 +471,9 @@ - (void) scanScreen withObject: nil afterDelay: 0.001]; - [self updateBox: sym - imageSize: size]; + if(tracksSymbols) + [self updateBox: sym + imageSize: size]; } - (void) captureScreen @@ -540,8 +541,9 @@ - (void) scanSequence: (UIImage*) image withObject: nil afterDelay: 0.001]; - [self updateBox: sym - imageSize: size]; + if(tracksSymbols) + [self updateBox: sym + imageSize: size]; } - (void) showHelpWithReason: (NSString*) reason diff --git a/iphone/ZBarReaderView.m b/iphone/ZBarReaderView.m index 5f7c28f..ab91dd7 100644 --- a/iphone/ZBarReaderView.m +++ b/iphone/ZBarReaderView.m @@ -31,7 +31,7 @@ @implementation ZBarReaderView @synthesize readerDelegate, tracksSymbols, showsFPS, zoom, scanCrop, previewTransform, session, captureReader; -@dynamic scanner, allowsPinchZoom, device; +@dynamic scanner, allowsPinchZoom, enableCache, device; - (id) initWithImageScanner: (ZBarImageScanner*) _scanner { @@ -266,6 +266,16 @@ - (BOOL) allowsPinchZoom return(pinch.enabled); } +- (BOOL) enableCache +{ + return(captureReader.enableCache); +} + +- (void) setEnableCache: (BOOL) enable +{ + captureReader.enableCache = enable; +} + - (void) setAllowsPinchZoom: (BOOL) enabled { pinch.enabled = enabled; diff --git a/iphone/ZBarReaderViewController.m b/iphone/ZBarReaderViewController.m index 97a9b43..8c199bd 100644 --- a/iphone/ZBarReaderViewController.m +++ b/iphone/ZBarReaderViewController.m @@ -30,8 +30,8 @@ @implementation ZBarReaderViewController -@synthesize scanner, readerDelegate, showsZBarControls, cameraOverlayView, - cameraViewTransform, readerView, scanCrop; +@synthesize scanner, readerDelegate, showsZBarControls, tracksSymbols, + enableCache, cameraOverlayView, cameraViewTransform, readerView, scanCrop; @dynamic sourceType, allowsEditing, allowsImageEditing, showsCameraControls, showsHelpOnFail, cameraMode, takesPicture, maxScanDimension; @@ -56,7 +56,7 @@ - (id) init self.wantsFullScreenLayout = YES; - showsZBarControls = YES; + showsZBarControls = tracksSymbols = enableCache = YES; scanCrop = CGRectMake(0, 0, 1, 1); cameraViewTransform = CGAffineTransformIdentity; @@ -162,6 +162,8 @@ - (void) viewDidLoad readerView.readerDelegate = (id)self; readerView.scanCrop = scanCrop; readerView.previewTransform = cameraViewTransform; + readerView.tracksSymbols = tracksSymbols; + readerView.enableCache = enableCache; [view addSubview: readerView]; [self initControls]; @@ -211,6 +213,20 @@ - (ZBarReaderView*) 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; @@ -326,7 +342,6 @@ - (void) setter: (type) v \ DEPRECATED_PROPERTY(showsHelpOnFail, setShowsHelpOnFail, BOOL, NO, YES) DEPRECATED_PROPERTY(cameraMode, setCameraMode, ZBarReaderControllerCameraMode, ZBarReaderControllerCameraModeSampling, NO) DEPRECATED_PROPERTY(takesPicture, setTakesPicture, BOOL, NO, NO) -DEPRECATED_PROPERTY(enableCache, setEnableCache, BOOL, YES, YES) DEPRECATED_PROPERTY(maxScanDimension, setMaxScanDimension, NSInteger, 640, YES) @end diff --git a/test/iphone/readertest.m b/test/iphone/readertest.m index f8bcadd..0ea0491 100644 --- a/test/iphone/readertest.m +++ b/test/iphone/readertest.m @@ -245,8 +245,8 @@ - (void) initControlCells withObject: modes]; static NSString* const configNames[] = { - @"showsCameraControls", @"showsZBarControls", @"enableCache", - @"showsHelpOnFail", @"takesPicture", + @"showsCameraControls", @"showsZBarControls", @"tracksSymbols", + @"enableCache", @"showsHelpOnFail", @"takesPicture", nil }; NSMutableArray *configs = [NSMutableArray array]; From f78bca6e6526fa243aab60374ec490ea95102207 Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 12 Jun 2010 09:14:00 -0400 Subject: [PATCH 207/328] add iPhone cache flush, change new libs to weak refs --- ChangeLog | 1 + include/zbar/ZBarCaptureReader.h | 3 +++ include/zbar/ZBarReaderView.h | 3 +++ iphone/ZBarCaptureReader.m | 7 +++++++ iphone/ZBarReaderView.m | 5 +++++ test/iphone/readertest.xcodeproj/project.pbxproj | 6 +++--- 6 files changed, 22 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index f2b320f..626a4ff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * add iPhone cache flush, change new libs to weak refs * fix iPhone async ref bug * enhance iPhone readertest w/more options * fix C++ video callback bug diff --git a/include/zbar/ZBarCaptureReader.h b/include/zbar/ZBarCaptureReader.h index dbeae18..5aada67 100644 --- a/include/zbar/ZBarCaptureReader.h +++ b/include/zbar/ZBarCaptureReader.h @@ -71,6 +71,9 @@ // this must be called *before* the session is stopped - (void) willStopRunning; +// clear the internal result cache +- (void) flushCache; + // the capture output. add this to an instance of AVCaptureSession @property (nonatomic, readonly) AVCaptureOutput *captureOutput; diff --git a/include/zbar/ZBarReaderView.h b/include/zbar/ZBarReaderView.h index 7826f3e..13cce5d 100644 --- a/include/zbar/ZBarReaderView.h +++ b/include/zbar/ZBarReaderView.h @@ -73,6 +73,9 @@ // stop the video stream and barcode reader. - (void) stop; +// clear the internal result cache +- (void) flushCache; + // delegate is notified of decode results. @property (nonatomic, assign) id readerDelegate; diff --git a/iphone/ZBarCaptureReader.m b/iphone/ZBarCaptureReader.m index 8134310..09a6355 100644 --- a/iphone/ZBarCaptureReader.m +++ b/iphone/ZBarCaptureReader.m @@ -128,6 +128,13 @@ - (void) willStopRunning return; } +- (void) flushCache +{ + @synchronized(scanner) { + scanner.enableCache = enableCache; + } +} + - (void) setCaptureDelegate: (id) delegate { @synchronized(scanner) { diff --git a/iphone/ZBarReaderView.m b/iphone/ZBarReaderView.m index ab91dd7..c2da778 100644 --- a/iphone/ZBarReaderView.m +++ b/iphone/ZBarReaderView.m @@ -357,6 +357,11 @@ - (void) stop started = NO; } +- (void) flushCache +{ + [captureReader flushCache]; +} + // AVCaptureSession notifications - (void) onVideoStart: (NSNotification*) note diff --git a/test/iphone/readertest.xcodeproj/project.pbxproj b/test/iphone/readertest.xcodeproj/project.pbxproj index 68522d3..130e1ff 100755 --- a/test/iphone/readertest.xcodeproj/project.pbxproj +++ b/test/iphone/readertest.xcodeproj/project.pbxproj @@ -19,9 +19,9 @@ DCB9118810BC5DB500B907F0 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD6E13B10B0AFD4002005CD /* libiconv.dylib */; }; DCB9119B10BC5DCB00B907F0 /* libzbar.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD6E0E610B0AE16002005CD /* libzbar.a */; }; DCD6E0D010B0AD41002005CD /* readertest.m in Sources */ = {isa = PBXBuildFile; fileRef = DCD6E0CF10B0AD41002005CD /* readertest.m */; }; - DCDC6D9B11ACA23000021380 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCDC6D9A11ACA23000021380 /* CoreVideo.framework */; }; - DCDC6D9F11ACA23900021380 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCDC6D9E11ACA23900021380 /* CoreMedia.framework */; }; - DCDC6DEC11ACA5B400021380 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCDC6DEB11ACA5B400021380 /* AVFoundation.framework */; }; + DCDC6D9B11ACA23000021380 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCDC6D9A11ACA23000021380 /* CoreVideo.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + DCDC6D9F11ACA23900021380 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCDC6D9E11ACA23900021380 /* CoreMedia.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + DCDC6DEC11ACA5B400021380 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCDC6DEB11ACA5B400021380 /* AVFoundation.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ From 60c7961ea88bbb86065093d23bdb2db3d3433a96 Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 16 Jun 2010 10:27:14 -0400 Subject: [PATCH 208/328] fix iPhone circular ref bug --- ChangeLog | 1 + iphone/ZBarCVImage.h | 3 ++- iphone/ZBarCVImage.m | 55 +++++++++++++++++++++++++++----------------- 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index 626a4ff..905a674 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * 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 diff --git a/iphone/ZBarCVImage.h b/iphone/ZBarCVImage.h index aba60d4..80d1e0c 100644 --- a/iphone/ZBarCVImage.h +++ b/iphone/ZBarCVImage.h @@ -35,8 +35,9 @@ NSInvocationOperation *conversion; } +- (void) waitUntilConverted; + @property (nonatomic) CVPixelBufferRef pixelBuffer; @property (nonatomic, readonly) void *rgbBuffer; -@property (nonatomic, readonly) NSOperation *conversion; @end diff --git a/iphone/ZBarCVImage.m b/iphone/ZBarCVImage.m index 1e88bd8..4c90913 100644 --- a/iphone/ZBarCVImage.m +++ b/iphone/ZBarCVImage.m @@ -33,13 +33,7 @@ // block until data is available ZBarCVImage *image = info; assert(image); - NSOperation *op = image.conversion; - // operation will at least have been queued already - assert(op); - if(!op) - return(NULL); - if(![op isFinished]) - [op waitUntilFinished]; + [image waitUntilConverted]; assert(image.rgbBuffer); return(image.rgbBuffer); } @@ -54,11 +48,11 @@ @implementation ZBarCVImage -@synthesize pixelBuffer, rgbBuffer, conversion; +@synthesize pixelBuffer, rgbBuffer; - (void) dealloc { - self.pixelBuffer = nil; + self.pixelBuffer = NULL; if(rgbBuffer) { free(rgbBuffer); rgbBuffer = NULL; @@ -78,8 +72,36 @@ - (void) setPixelBuffer: (CVPixelBufferRef) newbuf 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; @@ -101,23 +123,12 @@ - (UIImage*) UIImageWithOrientation: (UIImageOrientation) orient orientation: orient]; CGImageRelease(cgimg); - NSOperationQueue *queue = conversionQueue; - if(!queue) - queue = conversionQueue = [NSOperationQueue new]; - - // start format conversion in separate thread - conversion = [[NSInvocationOperation alloc] - initWithTarget: self - selector: @selector(convertCVtoRGB:) - object: uiimg]; - [queue addOperation: conversion]; - return(uiimg); } // convert video frame to a CGImage compatible RGB format // FIXME this is temporary until we can find the native way... -- (void) convertCVtoRGB: (UIImage*) uiimg +- (void) convertCVtoRGB { timer_start; unsigned long format = self.format; @@ -174,6 +185,8 @@ - (void) convertCVtoRGB: (UIImage*) uiimg // release buffer as soon as conversion is complete self.pixelBuffer = NULL; + + conversion = nil; } @end From 65b05536e2ef6275910c949cc421ee66799c6a3b Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 17 Jun 2010 11:51:08 -0400 Subject: [PATCH 209/328] fix documentation of command exit codes (bug #3017322) --- ChangeLog | 1 + doc/ref/zbarcam.xml | 31 +++++++++++++++++++++++++++ doc/ref/zbarimg.xml | 50 ++++++++++++++++++++++++++++++++++++++++++++ include/zbar/Image.h | 1 + 4 files changed, 83 insertions(+) diff --git a/ChangeLog b/ChangeLog index ffde5cb..dcda6c0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * fix documentation of command exit codes (bug #3017322) * fix C++ video callback bug - add C++ processor example * add per-symbology cache consistency diff --git a/doc/ref/zbarcam.xml b/doc/ref/zbarcam.xml index f84c81b..0293a02 100644 --- a/doc/ref/zbarcam.xml +++ b/doc/ref/zbarcam.xml @@ -159,6 +159,37 @@
+ + Exit Status + + zbarcam returns an exit code to indicate the + status of the program execution. Current exit codes are: + + + + 0 + + Successful program completion. + + + + + 1 + + An error occurred. This includes bad arguments and I/O + errors. + + + + + 2 + + A fatal error occurred. + + + + + See Also diff --git a/doc/ref/zbarimg.xml b/doc/ref/zbarimg.xml index 8fd0f72..e7766b1 100644 --- a/doc/ref/zbarimg.xml +++ b/doc/ref/zbarimg.xml @@ -165,6 +165,56 @@ + + Exit Status + + zbarimg returns an exit code to indicate the + status of the program execution. Current exit codes are: + + + + 0 + + Barcodes successfully detected in all images. Warnings may + have been generated, but no errors. + + + + + 1 + + An error occurred while processing some image(s). This + includes bad arguments, I/O errors and image handling errors from + ImageMagick. + + + + + 2 + + ImageMagick fatal error. + + + + + 3 + + The user quit the program before all images were scanned. + Only applies when running in interactive mode + (with ) + + + + + 4 + + No barcode was detected in one or more of the images. No + other errors occurred. + + + + + See Also diff --git a/include/zbar/Image.h b/include/zbar/Image.h index a482b91..1a2af46 100644 --- a/include/zbar/Image.h +++ b/include/zbar/Image.h @@ -115,6 +115,7 @@ class Image { ~Image () { + set_data(NULL, 0); zbar_image_set_userdata(_img, NULL); zbar_image_ref(_img, -1); } From e7e19044476f254cd0b4bf3e14000fd16db7086d Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 26 Jun 2010 20:45:53 -0400 Subject: [PATCH 210/328] fix ObjC sym constness inconsistency (bug #3021801) - random SA cleanup --- iphone/ZBarReaderViewController.m | 1 + iphone/ZBarSymbol.m | 2 +- zbar/decoder/ean.c | 2 +- zbar/decoder/i25.c | 2 +- zbar/img_scanner.c | 8 ++------ 5 files changed, 6 insertions(+), 9 deletions(-) diff --git a/iphone/ZBarReaderViewController.m b/iphone/ZBarReaderViewController.m index 8c199bd..51120a5 100644 --- a/iphone/ZBarReaderViewController.m +++ b/iphone/ZBarReaderViewController.m @@ -208,6 +208,7 @@ - (void) viewWillDisappear: (BOOL) animated - (ZBarReaderView*) readerView { + // force view to load self.view; assert(readerView); return(readerView); diff --git a/iphone/ZBarSymbol.m b/iphone/ZBarSymbol.m index 135cdb2..e7e7a1f 100644 --- a/iphone/ZBarSymbol.m +++ b/iphone/ZBarSymbol.m @@ -33,7 +33,7 @@ + (NSString*) nameForType: (zbar_symbol_type_t) type return([NSString stringWithUTF8String: zbar_get_symbol_name(type)]); } -- (id) initWithSymbol: (zbar_symbol_t*) sym +- (id) initWithSymbol: (const zbar_symbol_t*) sym { if(self = [super init]) { symbol = sym; diff --git a/zbar/decoder/ean.c b/zbar/decoder/ean.c index bb9c501..2c30128 100644 --- a/zbar/decoder/ean.c +++ b/zbar/decoder/ean.c @@ -461,7 +461,7 @@ static inline void ean_expand_upce (ean_decoder_t *ean, ean->buf[8] = 0; ean->buf[9] = (decode < 3) ? pass->raw[i++] & 0xf : 0; ean->buf[10] = (decode < 4) ? pass->raw[i++] & 0xf : 0; - ean->buf[11] = (decode < 5) ? pass->raw[i++] & 0xf : decode; + ean->buf[11] = (decode < 5) ? pass->raw[i] & 0xf : decode; } static inline zbar_symbol_type_t integrate_partial (ean_decoder_t *ean, diff --git a/zbar/decoder/i25.c b/zbar/decoder/i25.c index 0cb5148..56e6501 100644 --- a/zbar/decoder/i25.c +++ b/zbar/decoder/i25.c @@ -111,7 +111,7 @@ static inline signed char i25_decode_start (zbar_decoder_t *dcode) * we require 5.25n for w=2n to 6.75n for w=3n * (FIXME should really factor in w:n ratio) */ - unsigned quiet = get_width(dcode, i++); + unsigned quiet = get_width(dcode, i); if(quiet && quiet < dcode25->s10 * 3 / 8) { dprintf(3, " i25: s=%d enc=%x q=%d [invalid qz]\n", dcode25->s10, enc, quiet); diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 2749d4a..e19c279 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -194,18 +194,14 @@ inline void zbar_image_scanner_recycle_image (zbar_image_scanner_t *iscn, syms = img->syms; img->syms = NULL; - if(syms && recycle_syms(iscn, syms)) { + if(syms && recycle_syms(iscn, syms)) STAT(img_syms_inuse); - syms = iscn->syms; - } else if(syms) { STAT(img_syms_recycle); /* select one set to resurrect, destroy the other */ - if(iscn->syms) { + if(iscn->syms) _zbar_symbol_set_free(syms); - syms = iscn->syms; - } else iscn->syms = syms; } From d3e07ddb9ab3af34e8387e94dff19d5653fe7d85 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 1 Jul 2010 16:41:26 -0400 Subject: [PATCH 211/328] enhance decoder reliability (EAN, Code 39, Code 128) - enhance decoder test --- ChangeLog | 2 + test/Makefile.am.inc | 11 ++ test/test_decode.c | 383 ++++++++++++++++++++++++++++------------ zbar/decoder/code128.c | 28 ++- zbar/decoder/code128.h | 1 + zbar/decoder/code39.c | 2 +- zbar/decoder/ean.c | 32 +++- zbar/image.c | 4 +- zbar/img_scanner.c | 2 +- zbarimg/Makefile.am.inc | 4 +- 10 files changed, 338 insertions(+), 131 deletions(-) diff --git a/ChangeLog b/ChangeLog index 601b4a2..1098204 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * enhance decoder reliability (EAN, Code 39, Code 128) + - enhance decoder test * fix documentation of command exit codes (bug #3017322) * fix iPhone circular ref bug * add iPhone cache flush, change new libs to weak refs diff --git a/test/Makefile.am.inc b/test/Makefile.am.inc index 82291ed..a9f45a9 100644 --- a/test/Makefile.am.inc +++ b/test/Makefile.am.inc @@ -67,3 +67,14 @@ EXTRA_DIST += test/test_pygtk.py test/test_perl.pl CLEANFILES += test/.libs/test_decode test/.libs/test_proc \ test/.libs/test_convert test/.libs/test_window \ test/.libs/test_video test/.libs/dbg_scan test/.libs/test_gtk + +check-decoder: + test/test_decode -q + +regress-decoder: + test/test_decode -n 100000 + +check-local: check-decoder check-images +regress: regress-decoder regress-images + +.PHONY: check-decoder check-images regress-decoder regress-images regress diff --git a/test/test_decode.c b/test/test_decode.c index 0881ac5..54335ee 100644 --- a/test/test_decode.c +++ b/test/test_decode.c @@ -22,33 +22,79 @@ *------------------------------------------------------------------------*/ #include +#include #include #include #include +#include +#include #include #include zbar_decoder_t *decoder; +zbar_symbol_type_t expect_sym; +char *expect_data = NULL; + +unsigned seed = 0; +int verbosity = 1; +int rnd_size = 9; /* NB should be odd */ +int iter = 0; /* test iteration */ + +#define zprintf(level, format, ...) do { \ + if(verbosity >= (level)) { \ + fprintf((level) ? stdout : stderr, format , ##__VA_ARGS__); \ + } \ + } while(0) + static void symbol_handler (zbar_decoder_t *decoder) { zbar_symbol_type_t sym = zbar_decoder_get_type(decoder); - if(sym <= ZBAR_PARTIAL) + if(sym <= ZBAR_PARTIAL || sym == ZBAR_QRCODE) return; - printf("%s%s:%s\n", - zbar_get_symbol_name(sym), - zbar_get_addon_name(sym), - zbar_decoder_get_data(decoder)); - /* FIXME add check! */ + const char *data = zbar_decoder_get_data(decoder); + + int pass = (sym == expect_sym) && !strcmp(data, expect_data); + pass *= 3; + + zprintf(pass, "decode %s:%s\n", zbar_get_symbol_name(sym), data); + + if(!expect_sym) + zprintf(0, "UNEXPECTED!\n"); + else + zprintf(pass, "expect %s:%s\n", zbar_get_symbol_name(expect_sym), + expect_data); + if(!pass) { + zprintf(0, "SEED=%d\n", seed); + abort(); + } + + expect_sym = ZBAR_NONE; + free(expect_data); + expect_data = NULL; +} + +static void expect (zbar_symbol_type_t sym, + const char *data) +{ + if(expect_sym) { + zprintf(0, "MISSING %s:%s\n" + "SEED=%d\n", + zbar_get_symbol_name(expect_sym), expect_data, seed); + abort(); + } + expect_sym = sym; + expect_data = (data) ? strdup(data) : NULL; } static void encode_junk (int n) { - printf("encode random junk...\n"); + if(n > 1) + zprintf(3, "encode random junk...\n"); int i; for(i = 0; i < n; i++) - zbar_decode_width(decoder, 10. * (rand() / (RAND_MAX + 1.))); + zbar_decode_width(decoder, 20. * (rand() / (RAND_MAX + 1.)) + 1); } #define FWD 1 @@ -57,8 +103,8 @@ static void encode_junk (int n) static void encode (uint64_t units, int fwd) { - printf(" raw=%x%x%c\n", (unsigned)(units >> 32), - (unsigned)(units & 0xffffffff), (fwd) ? '<' : '>'); + zprintf(3, " raw=%x%x%c\n", (unsigned)(units >> 32), + (unsigned)(units & 0xffffffff), (fwd) ? '<' : '>'); if(!fwd) while(units && !(units >> 0x3c)) units <<= 4; @@ -122,47 +168,49 @@ static const unsigned int code128[107] = { 0x2331112a, /* STOP (6a) */ }; -static void encode_code128b (unsigned char *data) +static void encode_code128b (char *data) { - printf("------------------------------------------------------------\n" - "encode CODE-128(B): %s\n" - " encode START_B: %02x", data, START_B); + assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); + zprintf(3, "----------------------------------------------------------\n"); + zprintf(2, "CODE-128(B): %s\n", data); + zprintf(3, " encode START_B: %02x", START_B); encode(code128[START_B], 0); int i, chk = START_B; for(i = 0; data[i]; i++) { - printf(" encode '%c': %02x", data[i], data[i] - 0x20); + zprintf(3, " encode '%c': %02x", data[i], data[i] - 0x20); encode(code128[data[i] - 0x20], 0); chk += (i + 1) * (data[i] - 0x20); } chk %= 103; - printf(" encode checksum: %02x", chk); + zprintf(3, " encode checksum: %02x", chk); encode(code128[chk], 0); - printf(" encode STOP: %02x", STOP); + zprintf(3, " encode STOP: %02x", STOP); encode(code128[STOP], 0); - printf("------------------------------------------------------------\n"); + zprintf(3, "----------------------------------------------------------\n"); } -static void encode_code128c (unsigned char *data) +static void encode_code128c (char *data) { - printf("------------------------------------------------------------\n" - "encode CODE-128(C): %s\n" - " encode START_C: %02x", data, START_C); + assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); + zprintf(3, "----------------------------------------------------------\n"); + zprintf(2, "CODE-128(C): %s\n", data); + zprintf(3, " encode START_C: %02x", START_C); encode(code128[START_C], 0); int i, chk = START_C; for(i = 0; data[i]; i += 2) { assert(data[i] >= '0'); assert(data[i + 1] >= '0'); unsigned char c = (data[i] - '0') * 10 + (data[i + 1] - '0'); - printf(" encode '%c%c': %02d", data[i], data[i + 1], c); + zprintf(3, " encode '%c%c': %02d", data[i], data[i + 1], c); encode(code128[c], 0); chk += (i / 2 + 1) * c; } chk %= 103; - printf(" encode checksum: %02x", chk); + zprintf(3, " encode checksum: %02x", chk); encode(code128[chk], 0); - printf(" encode STOP: %02x", STOP); + zprintf(3, " encode STOP: %02x", STOP); encode(code128[STOP], 0); - printf("------------------------------------------------------------\n"); + zprintf(3, "----------------------------------------------------------\n"); } /*------------------------------------------------------------*/ @@ -182,14 +230,29 @@ static const unsigned int code39[91-32] = { /* FIXME configurable/randomized ratio, ics */ /* FIXME check digit option, ASCII escapes */ +static void convert_code39 (char *data) +{ + char *src, *dst; + for(src = data, dst = data; *src; src++) { + char c = *src; + if(c >= 'a' && c <= 'z') + *(dst++) = c - ('a' - 'A'); + else if(c == ' ' || + c == '$' || c == '%' || + c == '+' || c == '-' || + (c >= '.' && c <= '9') || + (c >= 'A' && c <= 'Z')) + *(dst++) = c; + else + /* skip (FIXME) */; + } + *dst = 0; +} + static void encode_char39 (unsigned char c, unsigned ics) { - if(c >= 'a' && c <= 'z') - c -= 'a' - 'A'; - else if(c < 0x20 || c > 0x5a) - return; /* skip (FIXME) */ - + assert(0x20 <= c && c <= 0x5a); unsigned int raw = code39[c - 0x20]; if(!raw) return; /* skip (FIXME) */ @@ -201,15 +264,16 @@ static void encode_char39 (unsigned char c, raw <<= 1; } enc = (enc << 4) | ics; - printf(" encode '%c': %02x%08x: ", c, - (unsigned)(enc >> 32), (unsigned)(enc & 0xffffffff)); + zprintf(3, " encode '%c': %02x%08x: ", c, + (unsigned)(enc >> 32), (unsigned)(enc & 0xffffffff)); encode(enc, REV); } -static void encode_code39 (unsigned char *data) +static void encode_code39 (char *data) { - printf("------------------------------------------------------------\n" - "encode CODE-39: %s\n", data); + assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); + zprintf(3, "----------------------------------------------------------\n"); + zprintf(2, "CODE-39: %s\n", data); encode(0xa, 0); /* leading quiet */ encode_char39('*', 1); int i; @@ -217,10 +281,10 @@ static void encode_code39 (unsigned char *data) if(data[i] != '*') /* skip (FIXME) */ encode_char39(data[i], 1); encode_char39('*', 0xa); /* w/trailing quiet */ - printf("------------------------------------------------------------\n"); + zprintf(3, "----------------------------------------------------------\n"); } - +#if 0 /*------------------------------------------------------------*/ /* PDF417 encoding */ @@ -258,32 +322,33 @@ static void encode_row417 (int r, { int k = r % 3; - printf(" [%d] encode %s:", r, (dir) ? "stop" : "start"); + zprintf(3, " [%d] encode %s:", r, (dir) ? "stop" : "start"); encode((dir) ? PDF417_STOP : PDF417_START, dir); int cw = calc_ind417(k + !dir, r, cols); - printf(" [%d,%c] encode %03d(%d): ", r, (dir) ? 'R' : 'L', cw, k); + zprintf(3, " [%d,%c] encode %03d(%d): ", r, (dir) ? 'R' : 'L', cw, k); encode(pdf417_encode[cw][k], dir); int c; for(c = 0; c < cols; c++) { cw = cws[c]; - printf(" [%d,%d] encode %03d(%d): ", r, c, cw, k); + zprintf(3, " [%d,%d] encode %03d(%d): ", r, c, cw, k); encode(pdf417_encode[cw][k], dir); } cw = calc_ind417(k + dir, r, cols); - printf(" [%d,%c] encode %03d(%d): ", r, (dir) ? 'L' : 'R', cw, k); + zprintf(3, " [%d,%c] encode %03d(%d): ", r, (dir) ? 'L' : 'R', cw, k); encode(pdf417_encode[cw][k], dir); - printf(" [%d] encode %s:", r, (dir) ? "start" : "stop"); + zprintf(3, " [%d] encode %s:", r, (dir) ? "start" : "stop"); encode((dir) ? PDF417_START : PDF417_STOP, dir); } -static void encode_pdf417 (unsigned char *data) +static void encode_pdf417 (char *data) { - printf("------------------------------------------------------------\n" - "encode PDF417: hello world\n"); + assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); + zprintf(3, "----------------------------------------------------------\n"); + zprintf(2, "PDF417: hello world\n"); encode(0xa, 0); int r; @@ -292,9 +357,9 @@ static void encode_pdf417 (unsigned char *data) encode(0xa, 0); } - printf("------------------------------------------------------------\n"); + zprintf(3, "----------------------------------------------------------\n"); } - +#endif /*------------------------------------------------------------*/ /* Interleaved 2 of 5 encoding */ @@ -303,21 +368,22 @@ static const unsigned char i25[10] = { 0x06, 0x11, 0x09, 0x18, 0x05, 0x14, 0x0c, 0x03, 0x12, 0x0a, }; -static void encode_i25 (unsigned char *data, +static void encode_i25 (char *data, int dir) { - printf("------------------------------------------------------------\n" - "encode Interleaved 2 of 5: %s\n" - " encode start:", data); + assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); + zprintf(3, "----------------------------------------------------------\n"); + zprintf(2, "Interleaved 2 of 5: %s\n", data); + zprintf(3, " encode start:"); encode((dir) ? 0xa1111 : 0xa112, 0); /* FIXME rev case data reversal */ int i; - for(i = (strlen((char*)data) & 1) ? -1 : 0; i < 0 || data[i]; i += 2) { + for(i = (strlen(data) & 1) ? -1 : 0; i < 0 || data[i]; i += 2) { /* encode 2 digits */ unsigned char c0 = (i < 0) ? 0 : data[i] - '0'; unsigned char c1 = data[i + 1] - '0'; - printf(" encode '%d%d':", c0, c1); + zprintf(3, " encode '%d%d':", c0, c1); assert(c0 < 10); assert(c1 < 10); @@ -337,9 +403,9 @@ static void encode_i25 (unsigned char *data, encode(enc, dir); } - printf(" encode end:"); + zprintf(3, " encode end:"); encode((dir) ? 0x211a : 0x1111a, 0); - printf("------------------------------------------------------------\n"); + zprintf(3, "----------------------------------------------------------\n"); } /*------------------------------------------------------------*/ @@ -372,7 +438,7 @@ static const unsigned char ean_parity_encode[] = { 0x25, /* ABBABA = 9 */ }; -static void calc_ean_parity (unsigned char *data, +static void calc_ean_parity (char *data, int n) { int i, chk = 0; @@ -387,119 +453,216 @@ static void calc_ean_parity (unsigned char *data, data[i] = 0; } -static void encode_ean13 (unsigned char *data) +static void encode_ean13 (char *data) { int i; unsigned char par = ean_parity_encode[data[0] - '0']; + assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); - printf("------------------------------------------------------------\n" - "encode EAN-13: %s (%02x)\n" - " encode start guard:", - data, par); + zprintf(3, "----------------------------------------------------------\n"); + zprintf(2, "EAN-13: %s (%02x)\n", data, par); + zprintf(3, " encode start guard:"); encode(ean_guard[3], FWD); for(i = 1; i < 7; i++, par <<= 1) { - printf(" encode %x%c:", (par >> 5) & 1, data[i]); - encode(ean_digits[data[i] - '0'], REV ^ ((par >> 5) & 1)); + zprintf(3, " encode %x%c:", (par >> 5) & 1, data[i]); + encode(ean_digits[data[i] - '0'], (par >> 5) & 1); } - printf(" encode center guard:"); + zprintf(3, " encode center guard:"); encode(ean_guard[5], FWD); for(; i < 13; i++) { - printf(" encode %x%c:", 0, data[i]); + zprintf(3, " encode %x%c:", 0, data[i]); encode(ean_digits[data[i] - '0'], FWD); } - printf(" encode end guard:"); + zprintf(3, " encode end guard:"); encode(ean_guard[3], REV); - printf("------------------------------------------------------------\n"); + zprintf(3, "----------------------------------------------------------\n"); } -static void encode_ean8 (unsigned char *data) +static void encode_ean8 (char *data) { int i; - printf("------------------------------------------------------------\n" - "encode EAN-8: %s\n" - " encode start guard:", - data); + assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); + zprintf(3, "----------------------------------------------------------\n"); + zprintf(2, "EAN-8: %s\n", data); + zprintf(3, " encode start guard:"); encode(ean_guard[3], FWD); for(i = 0; i < 4; i++) { - printf(" encode %c:", data[i]); + zprintf(3, " encode %c:", data[i]); encode(ean_digits[data[i] - '0'], FWD); } - printf(" encode center guard:"); + zprintf(3, " encode center guard:"); encode(ean_guard[5], FWD); for(; i < 8; i++) { - printf(" encode %c:", data[i]); + zprintf(3, " encode %c:", data[i]); encode(ean_digits[data[i] - '0'], FWD); } - printf(" encode end guard:"); + zprintf(3, " encode end guard:"); encode(ean_guard[3], REV); - printf("------------------------------------------------------------\n"); + zprintf(3, "----------------------------------------------------------\n"); } /*------------------------------------------------------------*/ /* main test flow */ -int main (int argc, char **argv) +int test_numeric (char *data) { - int i; - int rnd_size = 9; /* should be odd */ - srand(0xbabeface); - - /* FIXME TBD: - * - random module width (!= 1.0) - * - simulate scan speed variance - * - simulate dark "swelling" and light "blooming" - * - inject parity errors - */ - decoder = zbar_decoder_create(); - zbar_decoder_set_handler(decoder, symbol_handler); - zbar_decoder_set_config(decoder, 0, ZBAR_CFG_MIN_LEN, 0); - - encode_junk(rnd_size + 1); - - unsigned char data[32] = { 0 }; - for(i = 0; i < 12; i++) - data[i] = (rand() % 10) + '0'; - - calc_ean_parity(data, 12); - encode_ean13(data); - - encode_junk(rnd_size); - - data[i] = 0; + data[strlen(data) & ~1] = 0; + expect(ZBAR_CODE128, data); encode_code128c(data); encode_junk(rnd_size); + expect(ZBAR_I25, data); encode_i25(data, FWD); encode_junk(rnd_size); +#if 0 /* FIXME encoding broken */ encode_i25(data, REV); encode_junk(rnd_size); +#endif - calc_ean_parity(data, 7); - encode_ean8(data); + calc_ean_parity(data + 2, 12); + expect(ZBAR_EAN13, data + 2); + encode_ean13(data + 2); encode_junk(rnd_size); - for(i = 0; i < 10; i++) - data[i] = (rand() % 0x5f) + 0x20; - data[i] = 0; + calc_ean_parity(data + 7, 7); + expect(ZBAR_EAN8, data + 7); + encode_ean8(data + 7); + encode_junk(rnd_size); + + expect(ZBAR_NONE, NULL); + return(0); +} + +int test_alpha (char *data) +{ + expect(ZBAR_CODE128, data); encode_code128b(data); encode_junk(rnd_size); /*encode_code39("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%");*/ + convert_code39(data); + expect(ZBAR_CODE39, data); encode_code39(data); encode_junk(rnd_size); +#if 0 /* FIXME decoder unfinished */ encode_pdf417(data); encode_junk(rnd_size); +#endif + + expect(ZBAR_NONE, NULL); + return(0); +} + +int test1 () +{ + zprintf(2, "----------------------------------------------------------\n"); + if(!seed) + seed = 0xbabeface; + zprintf(1, "[%d] SEED=%d\n", iter++, seed); + srand(seed); + + int i; + char data[32] = { 0, }; + for(i = 0; i < 14; i++) + data[i] = (rand() % 10) + '0'; + + test_numeric(data); + + for(i = 0; i < 10; i++) + data[i] = (rand() % 0x5f) + 0x20; + data[i] = 0; + + test_alpha(data); + return(0); +} + +/* FIXME TBD: + * - random module width (!= 1.0) + * - simulate scan speed variance + * - simulate dark "swelling" and light "blooming" + * - inject parity errors + */ + +int main (int argc, char **argv) +{ + int n, i, j; + char *end; + + decoder = zbar_decoder_create(); + zbar_decoder_set_handler(decoder, symbol_handler); + zbar_decoder_set_config(decoder, 0, ZBAR_CFG_MIN_LEN, 0); + + encode_junk(rnd_size + 1); + + for(i = 1; i < argc; i++) { + if(argv[i][0] != '-') { + fprintf(stderr, "ERROR: unknown argument: %s\n", argv[i]); + return(2); + } + for(j = 1; argv[i][j]; j++) { + switch(argv[i][j]) + { + case 'q': verbosity = 0; break; + case 'v': verbosity++; break; + case 'r': + seed = time(NULL); + srand(seed); + seed = (rand() << 8) ^ rand(); + zprintf(0, "-r SEED=%d\n", seed); + break; + + case 's': + if(!argv[i][++j] && !(j = 0) && ++i >= argc) { + fprintf(stderr, "ERROR: -s needs argument\n"); + return(2); + } + seed = strtol(argv[i] + j, &end, 0); + if((!isdigit(argv[i][j]) && argv[i][j] != '-') || + !seed || seed == LONG_MAX || seed == LONG_MIN) { + fprintf(stderr, "ERROR: invalid : \"%s\"\n", + argv[i] + j); + return(2); + } + j = end - argv[i] - 1; + break; + + case 'n': + if(!argv[i][++j] && !(j = 0) && ++i >= argc) { + fprintf(stderr, "ERROR: -n needs argument\n"); + return(2); + } + n = strtol(argv[i] + j, &end, 0); + if(!isdigit(argv[i][j]) || !n) { + fprintf(stderr, "ERROR: invalid : \"%s\"\n", + argv[i] + j); + return(2); + } + j = end - argv[i] - 1; + + while(n--) { + test1(); + seed = (rand() << 8) ^ rand(); + } + break; + } + } + } + + if(!iter) + test1(); + + /* FIXME "Ran %d iterations in %gs\n\nOK\n" */ zbar_decoder_destroy(decoder); return(0); diff --git a/zbar/decoder/code128.c b/zbar/decoder/code128.c index 689e20e..0702b79 100644 --- a/zbar/decoder/code128.c +++ b/zbar/decoder/code128.c @@ -444,11 +444,12 @@ zbar_symbol_type_t _zbar_decode_code128 (zbar_decoder_t *dcode) dcode128->s6 -= get_width(dcode, 6); dcode128->s6 += get_width(dcode, 0); - if(/* process every 6th element of active symbol */ - (dcode128->character >= 0 && - (++dcode128->element) != 6) || - /* decode color based on direction */ - (get_color(dcode) != dcode128->direction)) + if((dcode128->character < 0) + ? get_color(dcode) != ZBAR_SPACE + : (/* process every 6th element of active symbol */ + ++dcode128->element != 6 || + /* decode color based on direction */ + get_color(dcode) != dcode128->direction)) return(0); dcode128->element = 0; @@ -465,7 +466,7 @@ zbar_symbol_type_t _zbar_decode_code128 (zbar_decoder_t *dcode) return(0); } qz = get_width(dcode, 6); - if(qz && qz < (dcode->code128.s6 * 3) / 4) { + if(qz && qz < (dcode128->s6 * 3) / 4) { dprintf(2, " [invalid qz %d]\n", qz); return(0); } @@ -493,6 +494,20 @@ zbar_symbol_type_t _zbar_decode_code128 (zbar_decoder_t *dcode) dcode128->character = -1; return(0); } + else { + unsigned dw; + if(dcode128->width > dcode128->s6) + dw = dcode128->width - dcode128->s6; + else + dw = dcode128->s6 - dcode128->width; + dw *= 4; + if(dw > dcode128->width) { + dprintf(1, " [width var]\n"); + release_lock(dcode, ZBAR_CODE128); + dcode128->character = -1; + return(0); + } + } zassert(dcode->buf_alloc > dcode128->character, 0, "alloc=%x idx=%x c=%02x %s\n", @@ -500,6 +515,7 @@ zbar_symbol_type_t _zbar_decode_code128 (zbar_decoder_t *dcode) _zbar_decoder_buf_dump(dcode->buf, dcode->buf_alloc)); dcode->buf[dcode128->character++] = c; + dcode128->width = dcode128->s6; if(dcode128->character > 2 && ((dcode128->direction) diff --git a/zbar/decoder/code128.h b/zbar/decoder/code128.h index 6e5153a..40db777 100644 --- a/zbar/decoder/code128.h +++ b/zbar/decoder/code128.h @@ -29,6 +29,7 @@ typedef struct code128_decoder_s { unsigned element : 3; /* element offset 0-5 */ int character : 12; /* character position in symbol */ unsigned s6; /* character width */ + unsigned width; /* last character width */ unsigned config; int configs[NUM_CFGS]; /* int valued configurations */ diff --git a/zbar/decoder/code39.c b/zbar/decoder/code39.c index 74f961e..89bfd43 100644 --- a/zbar/decoder/code39.c +++ b/zbar/decoder/code39.c @@ -198,7 +198,7 @@ static inline signed char code39_decode_start (zbar_decoder_t *dcode) dprintf(2, "\n"); return(ZBAR_NONE); } - dcode39->direction = (c == 0x19); + dcode39->direction ^= (c == 0x19); /* check leading quiet zone - spec is 10x */ unsigned quiet = get_width(dcode, 9); diff --git a/zbar/decoder/ean.c b/zbar/decoder/ean.c index 2c30128..93d82b2 100644 --- a/zbar/decoder/ean.c +++ b/zbar/decoder/ean.c @@ -122,7 +122,7 @@ static inline signed char aux_end (zbar_decoder_t *dcode, /* check quiet zone */ unsigned qz = get_width(dcode, 0); - if(!fwd && qz && qz < s * 3 / 4) { + if(!fwd && qz && qz <= s * 3 / 4) { dprintf(2, " [invalid quiet]"); return(-1); } @@ -161,15 +161,17 @@ static inline signed char aux_start (zbar_decoder_t *dcode) if(get_color(dcode) == ZBAR_BAR) { /* check for quiet-zone */ unsigned qz = get_width(dcode, 7); - if(!qz || qz >= dcode->ean.s4 * 3 / 4) { + if(!qz || qz > dcode->ean.s4 * 3 / 4) { if(!E1) { dprintf(2, " [valid normal]"); return(0); /* normal symbol start */ } +#if 0 else if(E1 == 1) { dprintf(2, " [valid add-on]"); return(STATE_ADDON); /* add-on symbol start */ } +#endif } dprintf(2, " [invalid start]"); return(-1); @@ -178,7 +180,9 @@ static inline signed char aux_start (zbar_decoder_t *dcode) if(!E1) { /* attempting decode from SPACE => validate center guard */ unsigned e3 = get_width(dcode, 6) + get_width(dcode, 7); - if(!decode_e(e3, dcode->ean.s4, 7)) { + unsigned e4 = get_width(dcode, 7) + get_width(dcode, 8); + if(!decode_e(e3, dcode->ean.s4, 7) && + !decode_e(e4, dcode->ean.s4, 7)) { dprintf(2, " [valid center]"); return(0); /* start after center guard */ } @@ -199,6 +203,9 @@ static inline signed char decode4 (zbar_decoder_t *dcode) unsigned e2 = get_width(dcode, 1) + get_width(dcode, 2); dprintf(2, "\n e1=%d e2=%d", e1, e2); + if(dcode->ean.s4 < 6) + return(-1); + /* create compacted encoding for direct lookup */ code = ((decode_e(e1, dcode->ean.s4, 7) << 2) | decode_e(e2, dcode->ean.s4, 7)); @@ -361,8 +368,10 @@ static inline zbar_symbol_type_t decode_pass (zbar_decoder_t *dcode, idx = pass->state & STATE_IDX; } code = decode4(dcode); - if(code < 0) + if(code < 0 && idx != 0x10) pass->state = -1; + else if(code < 0) + pass->raw[5] = 0xff; else { dprintf(2, "\n raw[%x]=%02x =>", idx >> 2, digits[(unsigned char)code]); @@ -379,7 +388,7 @@ static inline zbar_symbol_type_t decode_pass (zbar_decoder_t *dcode, (idx == 0x18 || idx == 0x19)) { zbar_symbol_type_t part = ZBAR_NONE; dprintf(2, " fwd=%x", fwd); - if(!aux_end(dcode, fwd)) + if(!aux_end(dcode, fwd) && pass->raw[5] != 0xff) part = ean_part_end7(&dcode->ean, pass, fwd); if(part) dcode->ean.direction = (pass->state & STATE_REV) != 0; @@ -468,7 +477,7 @@ static inline zbar_symbol_type_t integrate_partial (ean_decoder_t *ean, ean_pass_t *pass, zbar_symbol_type_t part) { - signed char i, j; + signed char i, j, right = !!(part & EAN_RIGHT); /* copy raw data into holding buffer */ /* if same partial is not consistent, reset others */ dprintf(2, " integrate part=%x (%s)", part, dsprintbuf(ean)); @@ -492,7 +501,7 @@ static inline zbar_symbol_type_t integrate_partial (ean_decoder_t *ean, ean->left = ean->right = ean->addon = ZBAR_NONE; } - if(part & EAN_RIGHT) { + if(right) { part &= ZBAR_SYMBOL; j = (part == ZBAR_EAN13) ? 12 : 7; for(i = (part == ZBAR_EAN13) ? 6 : 4; i; i--, j--) { @@ -531,9 +540,14 @@ static inline zbar_symbol_type_t integrate_partial (ean_decoder_t *ean, if(((part == ZBAR_EAN13 || part == ZBAR_UPCE) && ean_verify_checksum(ean, 12)) || - (part == ZBAR_EAN8 && ean_verify_checksum(ean, 7))) - /* invalid parity */ + (part == ZBAR_EAN8 && ean_verify_checksum(ean, 7))) { + /* invalid checksum */ + if(right) + ean->left = ZBAR_NONE; + else + ean->right = ZBAR_NONE; part = ZBAR_NONE; + } if(part == ZBAR_EAN13) { /* special case EAN-13 subsets */ diff --git a/zbar/image.c b/zbar/image.c index 2dd47a7..aa56a5f 100644 --- a/zbar/image.c +++ b/zbar/image.c @@ -253,8 +253,8 @@ int zbar_image_write (const zbar_image_t *img, else n = snprintf(filename, len, "%s.%08" PRIx32 ".zimg", filebase, img->format); - assert(n < len); - filename[len] = '\0'; + assert(n < len - 1); + filename[len - 1] = '\0'; zprintf(1, "dumping %.4s(%08" PRIx32 ") image to %s\n", (char*)&img->format, img->format, filename); diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index e19c279..0ac0f47 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -793,7 +793,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, zbar_symbol_t **symp = &syms->head, *sym; while((sym = *symp)) { if(sym->type < ZBAR_I25 && sym->type > ZBAR_PARTIAL && - sym->quality < 3) { + sym->quality < 4) { /* recycle */ *symp = sym->next; syms->nsyms--; diff --git a/zbarimg/Makefile.am.inc b/zbarimg/Makefile.am.inc index de66019..2ba65f6 100644 --- a/zbarimg/Makefile.am.inc +++ b/zbarimg/Makefile.am.inc @@ -12,10 +12,10 @@ endif EXTRA_DIST += test/barcodetest.py -check-local: +check-images: $(PYTHON) $(srcdir)/test/barcodetest.py -regress: +regress-images: suite='$(ZBAR_TESTS)'; \ if test "x$$suite" = "x"; then suite='http://zbar.sf.net/test'; fi ; \ $(PYTHON) $(srcdir)/test/barcodetest.py $$suite From 93b85992de33765f4437f6f273271bdc03d000d8 Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 9 Jul 2010 09:16:57 -0400 Subject: [PATCH 212/328] enable torch for iPhone 4 --- ChangeLog | 1 + include/zbar/ZBarReaderView.h | 4 ++++ iphone/ZBarReaderView.m | 11 ++++++++--- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1098204..6dbcdf8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * enable torch for iPhone 4 * enhance decoder reliability (EAN, Code 39, Code 128) - enhance decoder test * fix documentation of command exit codes (bug #3017322) diff --git a/include/zbar/ZBarReaderView.h b/include/zbar/ZBarReaderView.h index 13cce5d..e763e12 100644 --- a/include/zbar/ZBarReaderView.h +++ b/include/zbar/ZBarReaderView.h @@ -53,6 +53,7 @@ CGAffineTransform previewTransform; CGFloat zoom, zoom0; BOOL tracksSymbols, showsFPS; + NSInteger torchMode; AVCaptureInput *input; ZBarCaptureReader *captureReader; @@ -90,6 +91,9 @@ // (default YES). @property (nonatomic) BOOL allowsPinchZoom; +// torch mode to set automatically (default On). +@property (nonatomic) NSInteger torchMode; + // whether to display the frame rate for debug/configuration // (default NO). @property (nonatomic) BOOL showsFPS; diff --git a/iphone/ZBarReaderView.m b/iphone/ZBarReaderView.m index c2da778..fc49b8e 100644 --- a/iphone/ZBarReaderView.m +++ b/iphone/ZBarReaderView.m @@ -29,7 +29,7 @@ @implementation ZBarReaderView -@synthesize readerDelegate, tracksSymbols, showsFPS, zoom, scanCrop, +@synthesize readerDelegate, tracksSymbols, torchMode, showsFPS, zoom, scanCrop, previewTransform, session, captureReader; @dynamic scanner, allowsPinchZoom, enableCache, device; @@ -46,6 +46,7 @@ - (id) initWithImageScanner: (ZBarImageScanner*) _scanner UIViewAutoresizingFlexibleHeight; tracksSymbols = YES; + torchMode = AVCaptureTorchModeOn; scanCrop = CGRectMake(0, 0, 1, 1); previewTransform = CGAffineTransformIdentity; @@ -373,8 +374,12 @@ - (void) onVideoStart: (NSNotification*) note // lock device and set focus mode NSError *error = nil; - if([device lockForConfiguration: &error]) - device.focusMode = AVCaptureFocusModeContinuousAutoFocus; + if([device lockForConfiguration: &error]) { + if([device isFocusModeSupported: AVCaptureFocusModeContinuousAutoFocus]) + device.focusMode = AVCaptureFocusModeContinuousAutoFocus; + if([device isTorchModeSupported: torchMode]) + device.torchMode = torchMode; + } else zlog(@"failed to lock device: %@", error); } From 97d68dd54cd3de65226334a4cabf163eaff0333b Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 10 Jul 2010 10:53:32 -0400 Subject: [PATCH 213/328] fix iPhone torch - default to Auto - support for dynamic updates (while running) --- iphone/ZBarReaderView.m | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/iphone/ZBarReaderView.m b/iphone/ZBarReaderView.m index fc49b8e..1b82e03 100644 --- a/iphone/ZBarReaderView.m +++ b/iphone/ZBarReaderView.m @@ -46,7 +46,7 @@ - (id) initWithImageScanner: (ZBarImageScanner*) _scanner UIViewAutoresizingFlexibleHeight; tracksSymbols = YES; - torchMode = AVCaptureTorchModeOn; + torchMode = AVCaptureTorchModeAuto; scanCrop = CGRectMake(0, 0, 1, 1); previewTransform = CGAffineTransformIdentity; @@ -262,11 +262,6 @@ - (void) setTracksSymbols: (BOOL) track [self resetTracking]; } -- (BOOL) allowsPinchZoom -{ - return(pinch.enabled); -} - - (BOOL) enableCache { return(captureReader.enableCache); @@ -277,11 +272,26 @@ - (void) setEnableCache: (BOOL) enable captureReader.enableCache = enable; } +- (BOOL) allowsPinchZoom +{ + return(pinch.enabled); +} + - (void) setAllowsPinchZoom: (BOOL) enabled { pinch.enabled = enabled; } +- (void) setTorchMode: (NSInteger) mode +{ + torchMode = mode; + if(running && [device isTorchModeSupported: mode]) + @try { + device.torchMode = mode; + } + @catch(...) { } +} + - (void) setShowsFPS: (BOOL) show { if(show == showsFPS) From ae6840b781dd1ab9101ea66753b2f2596bcad883 Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 10 Jul 2010 12:28:30 -0400 Subject: [PATCH 214/328] fixes for new iPhone reader - don't require delegate to define imagePickerControllerDidCancel: - adjust timing of status bar changes to workaround broken views --- include/zbar/ZBarReaderViewController.h | 2 +- iphone/ZBarReaderViewController.m | 35 ++++++++++++++++++++----- test/iphone/readertest.m | 19 ++++++++++++++ 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/include/zbar/ZBarReaderViewController.h b/include/zbar/ZBarReaderViewController.h index 8ef0ced..763c889 100644 --- a/include/zbar/ZBarReaderViewController.h +++ b/include/zbar/ZBarReaderViewController.h @@ -43,7 +43,7 @@ BOOL showsZBarControls, tracksSymbols, enableCache; UIView *controls; - BOOL statusBarHidden; + BOOL didHideStatusBar; } // access to configure image scanner diff --git a/iphone/ZBarReaderViewController.m b/iphone/ZBarReaderViewController.m index 51120a5..9c19bc0 100644 --- a/iphone/ZBarReaderViewController.m +++ b/iphone/ZBarReaderViewController.m @@ -190,18 +190,35 @@ - (void) viewWillAppear: (BOOL) animated [readerView start]; UIApplication *app = [UIApplication sharedApplication]; - statusBarHidden = app.statusBarHidden; - if(self.wantsFullScreenLayout) + 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 stop]; - [[UIApplication sharedApplication] - setStatusBarHidden: statusBarHidden - withAnimation: UIStatusBarAnimationFade]; + + if(didHideStatusBar) { + [[UIApplication sharedApplication] + setStatusBarHidden: NO + withAnimation: UIStatusBarAnimationFade]; + didHideStatusBar = NO; + } [super viewWillDisappear: animated]; } @@ -258,8 +275,12 @@ - (void) cancel { if(!readerDelegate) return; - [readerDelegate - imagePickerControllerDidCancel: (UIImagePickerController*)self]; + SEL cb = @selector(imagePickerControllerDidCancel:); + if([readerDelegate respondsToSelector: cb]) + [readerDelegate + imagePickerControllerDidCancel: (UIImagePickerController*)self]; + else + [self dismissModalViewControllerAnimated: YES]; } - (void) info diff --git a/test/iphone/readertest.m b/test/iphone/readertest.m index 0ea0491..a3c3dbd 100644 --- a/test/iphone/readertest.m +++ b/test/iphone/readertest.m @@ -159,9 +159,23 @@ - (void) initOverlay target: self action: @selector(pause)] autorelease], + [[[UIBarButtonItem alloc] + initWithBarButtonSystemItem: UIBarButtonSystemItemFlexibleSpace + target: nil + action: nil] + autorelease], nil]; [overlay addSubview: toolbar]; [toolbar release]; + + + UIButton *info = + [UIButton buttonWithType: UIButtonTypeInfoLight]; + info.frame = CGRectMake(266, 426, 54, 54); + [info addTarget: self + action: @selector(info) + forControlEvents: UIControlEventTouchUpInside]; + [overlay addSubview: info]; } - (void) setCheck: (BOOL) state @@ -734,6 +748,11 @@ - (void) readerControllerDidFailToRead: (ZBarReaderController*) _reader [_reader dismissModalViewControllerAnimated: YES]; } +- (void) info +{ + [reader showHelpWithReason: @"INFO"]; +} + @end From 7d736730d4fb91d8c0d6283c8ff5734bc48001e0 Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 11 Jul 2010 14:47:17 -0400 Subject: [PATCH 215/328] add preliminary support for GS1 DataBar (RSS-14) symbology --- ChangeLog | 1 + configure.ac | 7 +- doc/ref/zbarcam.xml | 6 +- doc/ref/zbarimg.xml | 6 +- include/zbar.h | 1 + iphone/config.h | 5 +- iphone/zbar.xcodeproj/project.pbxproj | 8 + test/Makefile.am.inc | 4 +- test/iphone/readertest.m | 8 +- test/test_decode.c | 296 ++++++++++- zbar/Makefile.am.inc | 3 + zbar/config.c | 2 + zbar/decoder.c | 30 +- zbar/decoder.h | 6 + zbar/decoder/code128.c | 29 +- zbar/decoder/code128.h | 1 + zbar/decoder/code39.c | 22 +- zbar/decoder/databar.c | 709 ++++++++++++++++++++++++++ zbar/decoder/databar.h | 79 +++ zbar/decoder/ean.c | 38 +- zbar/decoder/ean.h | 3 +- zbar/decoder/i25.c | 63 ++- zbar/decoder/i25.h | 1 + zbar/img_scanner.c | 27 +- zbar/symbol.c | 1 + zbarimg/Makefile.am.inc | 4 +- zbarimg/zbarimg.c | 2 +- 27 files changed, 1295 insertions(+), 67 deletions(-) create mode 100644 zbar/decoder/databar.c create mode 100644 zbar/decoder/databar.h diff --git a/ChangeLog b/ChangeLog index 1098204..1ed903f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * 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) diff --git a/configure.ac b/configure.ac index 60defca..2be845f 100644 --- a/configure.ac +++ b/configure.ac @@ -107,9 +107,9 @@ 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,code39,i25,qrcode]])], [], - [enable_codes="ean,code39,code128,i25,qrcode"]) dnl pdf417 + [enable_codes="ean,databar,code128,code39,i25,qrcode"]) AC_DEFUN([ZBAR_CHK_CODE], [ AC_MSG_CHECKING([whether to build $2]) @@ -127,11 +127,12 @@ 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([code39], [Code 39 symbology]) -ZBAR_CHK_CODE([pdf417], [PDF417 symbology]) ZBAR_CHK_CODE([i25], [Interleaved 2 of 5 symbology]) ZBAR_CHK_CODE([qrcode], [QR Code]) +ZBAR_CHK_CODE([pdf417], [PDF417 symbology]) dnl libraries diff --git a/doc/ref/zbarcam.xml b/doc/ref/zbarcam.xml index 0293a02..cb21b8f 100644 --- a/doc/ref/zbarcam.xml +++ b/doc/ref/zbarcam.xml @@ -60,9 +60,9 @@ /dev/video0 The underlying library currently supports EAN-13 (including - UPC and ISBN subsets), EAN-8, Code 128, Code 39, Interleaved 2 of - 5 and QR Code symbologies. The specific type of each detected - symbol is printed with the decoded data. + UPC and ISBN subsets), EAN-8, DataBar, Code 128, Code 39, + Interleaved 2 of 5 and QR Code symbologies. The specific type of + each detected symbol is printed with the decoded data. diff --git a/doc/ref/zbarimg.xml b/doc/ref/zbarimg.xml index e7766b1..86b90e0 100644 --- a/doc/ref/zbarimg.xml +++ b/doc/ref/zbarimg.xml @@ -59,9 +59,9 @@ displayed to the screen. The underlying library currently supports EAN-13 (including - UPC and ISBN subsets), EAN-8, Code 128, Code 39, Interleaved 2 of - 5 and QR Code symbologies. The specific type of each detected - symbol is printed with the decoded data. + UPC and ISBN subsets), EAN-8, DataBar, Code 128, Code 39, + Interleaved 2 of 5 and QR Code symbologies. The specific type of + each detected symbol is printed with the decoded data. Note that "image" diff --git a/include/zbar.h b/include/zbar.h index 399dd91..9cde3f8 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -93,6 +93,7 @@ typedef enum zbar_symbol_type_e { ZBAR_EAN13 = 13, /**< EAN-13 */ ZBAR_ISBN13 = 14, /**< ISBN-13 (from EAN-13). @since 0.4 */ ZBAR_I25 = 25, /**< Interleaved 2 of 5. @since 0.4 */ + ZBAR_DATABAR = 34, /**< GS1 DataBar (RSS). @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 */ diff --git a/iphone/config.h b/iphone/config.h index 8ad6dc2..181c971 100644 --- a/iphone/config.h +++ b/iphone/config.h @@ -1,4 +1,4 @@ -/* include/config.h.in. Generated from configure.ac by autoheader. */ +/* manually customized for iPhone platform */ /* whether to build support for Code 128 symbology */ #define ENABLE_CODE128 1 @@ -6,6 +6,9 @@ /* whether to build support for Code 39 symbology */ #define ENABLE_CODE39 1 +/* whether to build support for DataBar symbology */ +#define ENABLE_DATABAR 1 + /* whether to build support for EAN symbologies */ #define ENABLE_EAN 1 diff --git a/iphone/zbar.xcodeproj/project.pbxproj b/iphone/zbar.xcodeproj/project.pbxproj index 3951dc3..de3d185 100644 --- a/iphone/zbar.xcodeproj/project.pbxproj +++ b/iphone/zbar.xcodeproj/project.pbxproj @@ -68,6 +68,8 @@ DCDC6E3011ADCA8E00021380 /* ZBarReaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = DCDC6E2F11ADCA8E00021380 /* ZBarReaderView.m */; }; DCDC6E3911ADCB7700021380 /* ZBarReaderView.h in Headers */ = {isa = PBXBuildFile; fileRef = DCDC6E3811ADCB7700021380 /* ZBarReaderView.h */; }; DCDC713711B1628200021380 /* ZBarReaderViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = DCDC713611B1628200021380 /* ZBarReaderViewController.h */; }; + DCF5C9AD11EA3AD100E7DC21 /* databar.c in Sources */ = {isa = PBXBuildFile; fileRef = DCF5C9AB11EA3AD100E7DC21 /* databar.c */; }; + DCF5C9AE11EA3AD100E7DC21 /* databar.h in Headers */ = {isa = PBXBuildFile; fileRef = DCF5C9AC11EA3AD100E7DC21 /* databar.h */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -135,6 +137,8 @@ DCDC6E2F11ADCA8E00021380 /* ZBarReaderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarReaderView.m; sourceTree = ""; }; DCDC6E3811ADCB7700021380 /* ZBarReaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ZBarReaderView.h; path = ../include/zbar/ZBarReaderView.h; sourceTree = SOURCE_ROOT; }; DCDC713611B1628200021380 /* ZBarReaderViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ZBarReaderViewController.h; path = ../include/zbar/ZBarReaderViewController.h; sourceTree = SOURCE_ROOT; }; + DCF5C9AB11EA3AD100E7DC21 /* databar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = databar.c; sourceTree = ""; }; + DCF5C9AC11EA3AD100E7DC21 /* databar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = databar.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -234,6 +238,8 @@ DC67C12210A07AD30033B702 /* decoder */ = { isa = PBXGroup; children = ( + DCF5C9AB11EA3AD100E7DC21 /* databar.c */, + DCF5C9AC11EA3AD100E7DC21 /* databar.h */, DC67C12310A07AD30033B702 /* code128.c */, DC67C12410A07AD30033B702 /* code128.h */, DC67C12510A07AD30033B702 /* code39.c */, @@ -307,6 +313,7 @@ DCDC6E3911ADCB7700021380 /* ZBarReaderView.h in Headers */, DCDC713711B1628200021380 /* ZBarReaderViewController.h in Headers */, DC3AAB4E11B71A040021C7B1 /* ZBarCVImage.h in Headers */, + DCF5C9AE11EA3AD100E7DC21 /* databar.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -382,6 +389,7 @@ DC3EBB2D119DDB2100107EE9 /* ZBarReaderViewController.m in Sources */, DCDC6E3011ADCA8E00021380 /* ZBarReaderView.m in Sources */, DC3AAB4F11B71A040021C7B1 /* ZBarCVImage.m in Sources */, + DCF5C9AD11EA3AD100E7DC21 /* databar.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/test/Makefile.am.inc b/test/Makefile.am.inc index a9f45a9..a7672dc 100644 --- a/test/Makefile.am.inc +++ b/test/Makefile.am.inc @@ -68,10 +68,10 @@ CLEANFILES += test/.libs/test_decode test/.libs/test_proc \ test/.libs/test_convert test/.libs/test_window \ test/.libs/test_video test/.libs/dbg_scan test/.libs/test_gtk -check-decoder: +check-decoder: test/test_decode test/test_decode -q -regress-decoder: +regress-decoder: test/test_decode test/test_decode -n 100000 check-local: check-decoder check-images diff --git a/test/iphone/readertest.m b/test/iphone/readertest.m index 0ea0491..e41db48 100644 --- a/test/iphone/readertest.m +++ b/test/iphone/readertest.m @@ -297,13 +297,13 @@ - (void) initControlCells nil]]; static const int symbolValues[] = { - ZBAR_QRCODE, ZBAR_CODE128, ZBAR_CODE39, ZBAR_I25, ZBAR_EAN13, ZBAR_EAN8, - ZBAR_UPCA, ZBAR_UPCE, ZBAR_ISBN13, ZBAR_ISBN10, + ZBAR_QRCODE, ZBAR_CODE128, ZBAR_CODE39, ZBAR_I25, ZBAR_DATABAR, + ZBAR_EAN13, ZBAR_EAN8, ZBAR_UPCA, ZBAR_UPCE, ZBAR_ISBN13, ZBAR_ISBN10, 0 }; static NSString* const symbolNames[] = { - @"QRCODE", @"CODE128", @"CODE39", @"I25", @"EAN13", @"EAN8", - @"UPCA", @"UPCE", @"ISBN13", @"ISBN10", + @"QRCODE", @"CODE128", @"CODE39", @"I25", @"DataBar", + @"EAN13", @"EAN8", @"UPCA", @"UPCE", @"ISBN13", @"ISBN10", nil }; NSMutableArray *symbols = [NSMutableArray array]; diff --git a/test/test_decode.c b/test/test_decode.c index 54335ee..c62cb9a 100644 --- a/test/test_decode.c +++ b/test/test_decode.c @@ -44,7 +44,7 @@ int iter = 0; /* test iteration */ #define zprintf(level, format, ...) do { \ if(verbosity >= (level)) { \ - fprintf((level) ? stdout : stderr, format , ##__VA_ARGS__); \ + fprintf(stderr, format , ##__VA_ARGS__); \ } \ } while(0) @@ -408,6 +408,246 @@ static void encode_i25 (char *data, zprintf(3, "----------------------------------------------------------\n"); } +/*------------------------------------------------------------*/ +/* DataBar encoding */ + + +/* character encoder reference algorithm from ISO/IEC 24724:2009 */ + +struct rss_group { + int T_odd, T_even, n_odd, w_max; +}; + +static const struct rss_group databar_groups_outside[] = { + { 161, 1, 12, 8 }, + { 80, 10, 10, 6 }, + { 31, 34, 8, 4 }, + { 10, 70, 6, 3 }, + { 1, 126, 4, 1 }, + { 0, } +}; + +static const struct rss_group databar_groups_inside[] = { + { 4, 84, 5, 2 }, + { 20, 35, 7, 4 }, + { 48, 10, 9, 6 }, + { 81, 1, 11, 8 }, + { 0, } +}; + +static const uint32_t databar_finders[9] = { + 0x38211, 0x35511, 0x33711, 0x31911, 0x27411, + 0x25611, 0x23811, 0x15711, 0x13911, +}; + +int combins (int n, + int r) +{ + int i, j; + int maxDenom, minDenom; + int val; + if(n-r > r) { + minDenom = r; + maxDenom = n-r; + } + else { + minDenom = n-r; + maxDenom = r; + } + val = 1; + j = 1; + for(i = n; i > maxDenom; i--) { + val *= i; + if(j <= minDenom) { + val /= j; + j++; + } + } + for(; j <= minDenom; j++) + val /= j; + return(val); +} + +void getRSSWidths (int val, + int n, + int elements, + int maxWidth, + int noNarrow, + int *widths) +{ + int narrowMask = 0; + int bar; + for(bar = 0; bar < elements - 1; bar++) { + int elmWidth, subVal; + for(elmWidth = 1, narrowMask |= (1<= elements-bar-1)) + subVal -= combins(n-elmWidth-(elements-bar), elements-bar-2); + if(elements-bar-1 > 1) { + int mxwElement, lessVal = 0; + for (mxwElement = n-elmWidth-(elements-bar-2); + mxwElement > maxWidth; + mxwElement--) + lessVal += combins(n-elmWidth-mxwElement-1, elements-bar-3); + subVal -= lessVal * (elements-1-bar); + } + else if (n-elmWidth > maxWidth) + subVal--; + val -= subVal; + if(val < 0) + break; + } + val += subVal; + n -= elmWidth; + widths[bar] = elmWidth; + } + widths[bar] = n; +} + +static uint64_t encode_databar_char (unsigned val, + const struct rss_group *grp, + int nmodules, + int nelems, + int dir) +{ + int G_sum = 0; + while(1) { + assert(grp->T_odd); + int sum = G_sum + grp->T_odd * grp->T_even; + if(val >= sum) + G_sum = sum; + else + break; + grp++; + } + + zprintf(3, "char=%d", val); + + int V_grp = val - G_sum; + int V_odd, V_even; + if(!dir) { + V_odd = V_grp / grp->T_even; + V_even = V_grp % grp->T_even; + } + else { + V_even = V_grp / grp->T_odd; + V_odd = V_grp % grp->T_odd; + } + + zprintf(3, " G_sum=%d T_odd=%d T_even=%d n_odd=%d w_max=%d V_grp=%d\n", + G_sum, grp->T_odd, grp->T_even, grp->n_odd, grp->w_max, V_grp); + + int odd[16]; + getRSSWidths(V_odd, grp->n_odd, nelems, grp->w_max, !dir, odd); + zprintf(3, " V_odd=%d odd=%d%d%d%d", + V_odd, odd[0], odd[1], odd[2], odd[3]); + + int even[16]; + getRSSWidths(V_even, nmodules - grp->n_odd, nelems, 9 - grp->w_max, + dir, even); + zprintf(3, " V_even=%d even=%d%d%d%d", + V_even, even[0], even[1], even[2], even[3]); + + uint64_t units = 0; + int i; + for(i = 0; i < nelems; i++) + units = (units << 8) | (odd[i] << 4) | even[i]; + + zprintf(3, " raw=%"PRIx64"\n", units); + return(units); +} + +#define SWAP(a, b) do { \ + uint32_t tmp = (a); \ + (a) = (b); \ + (b) = tmp; \ + } while(0); + +static void encode_databar (char *data, + int dir) +{ + assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); + + zprintf(3, "----------------------------------------------------------\n"); + zprintf(2, "DataBar: %s\n", data); + + uint32_t v[4] = { 0, }; + int i, j; + for(i = 0; i < 14; i++) { + for(j = 0; j < 4; j++) + v[j] *= 10; + assert(data[i]); + v[0] += data[i] - '0'; + v[1] += v[0] / 1597; + v[0] %= 1597; + v[2] += v[1] / 2841; + v[1] %= 2841; + v[3] += v[2] / 1597; + v[2] %= 1597; + /*printf(" [%d] %c (%d,%d,%d,%d)\n", + i, data[i], v[0], v[1], v[2], v[3]);*/ + } + zprintf(3, "chars=(%d,%d,%d,%d)\n", v[3], v[2], v[1], v[0]); + + uint32_t c[4] = { + encode_databar_char(v[3], databar_groups_outside, 16, 4, 0), + encode_databar_char(v[2], databar_groups_inside, 15, 4, 1), + encode_databar_char(v[1], databar_groups_outside, 16, 4, 0), + encode_databar_char(v[0], databar_groups_inside, 15, 4, 1), + }; + + int chk = 0, w = 1; + for(i = 0; i < 4; i++, chk %= 79, w %= 79) + for(j = 0; j < 8; j++, w *= 3) + chk += ((c[i] >> (28 - j * 4)) & 0xf) * w; + zprintf(3, "chk=%d\n", chk); + + if(chk >= 8) chk++; + if(chk >= 72) chk++; + int C_left = chk / 9; + int C_right = chk % 9; + + if(dir == REV) { + SWAP(C_left, C_right); + SWAP(c[0], c[2]); + SWAP(c[1], c[3]); + SWAP(v[0], v[2]); + SWAP(v[1], v[3]); + } + + zprintf(3, " encode start guard:"); + encode_junk(dir); + encode(0x1, FWD); + + zprintf(3, "encode char[0]=%d", v[3]); + encode(c[0], REV); + + zprintf(3, "encode left finder=%d", C_left); + encode(databar_finders[C_left], REV); + + zprintf(3, "encode char[1]=%d", v[2]); + encode(c[1], FWD); + + zprintf(3, "encode char[3]=%d", v[0]); + encode(c[3], REV); + + zprintf(3, "encode right finder=%d", C_right); + encode(databar_finders[C_right], FWD); + + zprintf(3, "encode char[2]=%d", v[1]); + encode(c[2], FWD); + + zprintf(3, " encode end guard:"); + encode(0x1, FWD); + encode_junk(!dir); + zprintf(3, "----------------------------------------------------------\n"); +} + + /*------------------------------------------------------------*/ /* EAN/UPC encoding */ @@ -505,8 +745,56 @@ static void encode_ean8 (char *data) /*------------------------------------------------------------*/ /* main test flow */ +int test_databar_F_1 () +{ + expect(ZBAR_DATABAR, "24012345678905"); + assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); + encode(0x11, 0); + encode(0x31111333, 0); + encode(0x13911, 0); + encode(0x31131231, 0); + encode(0x11214222, 0); + encode(0x11553, 0); + encode(0x21231313, 0); + encode(0x1, 0); + encode_junk(rnd_size); + return(0); +} + +int test_orange () +{ + char data[32] = "000845963000052"; + expect(ZBAR_DATABAR, data + 1); + encode_databar(data, FWD); + encode_junk(rnd_size); + + expect(ZBAR_DATABAR, data + 1); + assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); + encode(0x1, 0); + encode(0x23212321, 0); // data[0] + encode(0x31911, 0); // finder[?] = 3 + encode(0x21121215, 1); // data[1] + encode(0x41111133, 0); // data[3] + encode(0x23811, 1); // finder[?] = 6 + encode(0x11215141, 1); // data[2] + encode(0x11, 0); + encode_junk(rnd_size); + + return(0); +} + int test_numeric (char *data) { + char tmp = data[0]; + data[0] &= '1'; + calc_ean_parity(data + 1, 13); + expect(ZBAR_DATABAR, data + 1); + encode_databar(data, (rand() >> 8) & 1); + + encode_junk(rnd_size); + + data[0] = tmp; + data[strlen(data) & ~1] = 0; expect(ZBAR_CODE128, data); encode_code128c(data); @@ -601,7 +889,6 @@ int main (int argc, char **argv) decoder = zbar_decoder_create(); zbar_decoder_set_handler(decoder, symbol_handler); - zbar_decoder_set_config(decoder, 0, ZBAR_CFG_MIN_LEN, 0); encode_junk(rnd_size + 1); @@ -659,8 +946,11 @@ int main (int argc, char **argv) } } - if(!iter) + if(!iter) { + test_databar_F_1(); + test_orange(); test1(); + } /* FIXME "Ran %d iterations in %gs\n\nOK\n" */ diff --git a/zbar/Makefile.am.inc b/zbar/Makefile.am.inc index 8d38484..badb03e 100644 --- a/zbar/Makefile.am.inc +++ b/zbar/Makefile.am.inc @@ -19,6 +19,9 @@ EXTRA_zbar_libzbar_la_SOURCES = zbar/svg.h zbar/svg.c if ENABLE_EAN zbar_libzbar_la_SOURCES += zbar/decoder/ean.h zbar/decoder/ean.c endif +if ENABLE_DATABAR +zbar_libzbar_la_SOURCES += zbar/decoder/databar.h zbar/decoder/databar.c +endif if ENABLE_CODE128 zbar_libzbar_la_SOURCES += zbar/decoder/code128.h zbar/decoder/code128.c endif diff --git a/zbar/config.c b/zbar/config.c index 5fbbfe7..115c3a3 100644 --- a/zbar/config.c +++ b/zbar/config.c @@ -87,6 +87,8 @@ int zbar_parse_config (const char *cfgstr, return(1); else if(!strncmp(cfgstr, "code128", len)) *sym = ZBAR_CODE128; + else if(!strncmp(cfgstr, "databar", len)) + *sym = ZBAR_DATABAR; else return(1); cfgstr = dot + 1; diff --git a/zbar/decoder.c b/zbar/decoder.c index c1330e9..2581ea0 100644 --- a/zbar/decoder.c +++ b/zbar/decoder.c @@ -29,7 +29,7 @@ #include #if defined(DEBUG_DECODER) || defined(DEBUG_EAN) || \ - defined(DEBUG_CODE39) || defined(DEBUG_I25) || \ + defined(DEBUG_CODE39) || defined(DEBUG_I25) || defined(DEBUG_DATABAR) || \ defined(DEBUG_CODE128) || defined(DEBUG_QR_FINDER) || \ (defined(DEBUG_PDF417) && (DEBUG_PDF417 >= 4)) # define DEBUG_LEVEL 1 @@ -59,6 +59,12 @@ zbar_decoder_t *zbar_decoder_create () dcode->i25.config = 1 << ZBAR_CFG_ENABLE; CFG(dcode->i25, ZBAR_CFG_MIN_LEN) = 6; #endif +#ifdef ENABLE_DATABAR + dcode->databar.config = ((1 << ZBAR_CFG_ENABLE) | + (1 << ZBAR_CFG_EMIT_CHECK)); + dcode->databar.csegs = 4; + dcode->databar.segs = calloc(4, sizeof(*dcode->databar.segs)); +#endif #ifdef ENABLE_CODE39 dcode->code39.config = 1 << ZBAR_CFG_ENABLE; CFG(dcode->code39, ZBAR_CFG_MIN_LEN) = 1; @@ -79,6 +85,10 @@ zbar_decoder_t *zbar_decoder_create () void zbar_decoder_destroy (zbar_decoder_t *dcode) { +#ifdef ENABLE_DATABAR + if(dcode->databar.segs) + free(dcode->databar.segs); +#endif if(dcode->buf) free(dcode->buf); free(dcode); @@ -93,6 +103,9 @@ void zbar_decoder_reset (zbar_decoder_t *dcode) #ifdef ENABLE_I25 i25_reset(&dcode->i25); #endif +#ifdef ENABLE_DATABAR + databar_reset(&dcode->databar); +#endif #ifdef ENABLE_CODE39 code39_reset(&dcode->code39); #endif @@ -119,6 +132,9 @@ void zbar_decoder_new_scan (zbar_decoder_t *dcode) #ifdef ENABLE_I25 i25_reset(&dcode->i25); #endif +#ifdef ENABLE_DATABAR + databar_new_scan(&dcode->databar); +#endif #ifdef ENABLE_CODE39 code39_reset(&dcode->code39); #endif @@ -208,6 +224,11 @@ zbar_symbol_type_t zbar_decode_width (zbar_decoder_t *dcode, (tmp = _zbar_decode_code128(dcode)) > ZBAR_PARTIAL) sym = tmp; #endif +#ifdef ENABLE_DATABAR + if(TEST_CFG(dcode->databar.config, ZBAR_CFG_ENABLE) && + (tmp = _zbar_decode_databar(dcode)) > ZBAR_PARTIAL) + sym = tmp; +#endif #ifdef ENABLE_I25 if(TEST_CFG(dcode->i25.config, ZBAR_CFG_ENABLE) && (tmp = _zbar_decode_i25(dcode)) > ZBAR_PARTIAL) @@ -269,6 +290,12 @@ static inline int decoder_set_config_bool (zbar_decoder_t *dcode, break; #endif +#ifdef ENABLE_DATABAR + case ZBAR_DATABAR: + config = &dcode->databar.config; + break; +#endif + #ifdef ENABLE_CODE39 case ZBAR_CODE39: config = &dcode->code39.config; @@ -368,6 +395,7 @@ int zbar_decoder_set_config (zbar_decoder_t *dcode, zbar_decoder_set_config(dcode, ZBAR_ISBN10, cfg, val); zbar_decoder_set_config(dcode, ZBAR_ISBN13, cfg, val); zbar_decoder_set_config(dcode, ZBAR_I25, cfg, val); + zbar_decoder_set_config(dcode, ZBAR_DATABAR, cfg, val); zbar_decoder_set_config(dcode, ZBAR_CODE39, cfg, val); zbar_decoder_set_config(dcode, ZBAR_CODE128, cfg, val); zbar_decoder_set_config(dcode, ZBAR_PDF417, cfg, val); diff --git a/zbar/decoder.h b/zbar/decoder.h index 7bffdba..1d2cc9e 100644 --- a/zbar/decoder.h +++ b/zbar/decoder.h @@ -36,6 +36,9 @@ #ifdef ENABLE_I25 # include "decoder/i25.h" #endif +#ifdef ENABLE_DATABAR +# include "decoder/databar.h" +#endif #ifdef ENABLE_CODE39 # include "decoder/code39.h" #endif @@ -96,6 +99,9 @@ struct zbar_decoder_s { #ifdef ENABLE_I25 i25_decoder_t i25; /* Interleaved 2 of 5 decode state */ #endif +#ifdef ENABLE_DATABAR + databar_decoder_t databar; /* DataBar decode state */ +#endif #ifdef ENABLE_CODE39 code39_decoder_t code39; /* Code 39 decode state */ #endif diff --git a/zbar/decoder/code128.c b/zbar/decoder/code128.c index 0702b79..4af9939 100644 --- a/zbar/decoder/code128.c +++ b/zbar/decoder/code128.c @@ -470,27 +470,26 @@ zbar_symbol_type_t _zbar_decode_code128 (zbar_decoder_t *dcode) dprintf(2, " [invalid qz %d]\n", qz); return(0); } - /* lock shared resources */ - if(acquire_lock(dcode, ZBAR_CODE128)) { - dcode128->character = -1; - return(0); - } /* decoded valid start/stop */ /* initialize state */ - dcode128->character = 0; + dcode128->character = 1; if(c == STOP_REV) { dcode128->direction = ZBAR_BAR; dcode128->element = 7; } else dcode128->direction = ZBAR_SPACE; - dprintf(2, " dir=%x [valid start]", dcode128->direction); + dcode128->start = c; + dcode128->width = dcode128->s6; + dprintf(2, " dir=%x [valid start]\n", dcode128->direction); + return(0); } else if((c < 0) || ((dcode128->character >= BUFFER_MIN) && size_buf(dcode, dcode128->character + 1))) { dprintf(1, (c < 0) ? " [aborted]\n" : " [overflow]\n"); - release_lock(dcode, ZBAR_CODE128); + if(dcode128->character > 1) + release_lock(dcode, ZBAR_CODE128); dcode128->character = -1; return(0); } @@ -503,19 +502,29 @@ zbar_symbol_type_t _zbar_decode_code128 (zbar_decoder_t *dcode) dw *= 4; if(dw > dcode128->width) { dprintf(1, " [width var]\n"); - release_lock(dcode, ZBAR_CODE128); + if(dcode128->character > 1) + release_lock(dcode, ZBAR_CODE128); dcode128->character = -1; return(0); } } + dcode128->width = dcode128->s6; zassert(dcode->buf_alloc > dcode128->character, 0, "alloc=%x idx=%x c=%02x %s\n", dcode->buf_alloc, dcode128->character, c, _zbar_decoder_buf_dump(dcode->buf, dcode->buf_alloc)); + if(dcode128->character == 1) { + /* lock shared resources */ + if(acquire_lock(dcode, ZBAR_CODE128)) { + dcode128->character = -1; + return(0); + } + dcode->buf[0] = dcode128->start; + } + dcode->buf[dcode128->character++] = c; - dcode128->width = dcode128->s6; if(dcode128->character > 2 && ((dcode128->direction) diff --git a/zbar/decoder/code128.h b/zbar/decoder/code128.h index 40db777..2cc1d4a 100644 --- a/zbar/decoder/code128.h +++ b/zbar/decoder/code128.h @@ -28,6 +28,7 @@ typedef struct code128_decoder_s { unsigned direction : 1; /* scan direction: 0=fwd/space, 1=rev/bar */ unsigned element : 3; /* element offset 0-5 */ int character : 12; /* character position in symbol */ + unsigned char start; /* start character */ unsigned s6; /* character width */ unsigned width; /* last character width */ diff --git a/zbar/decoder/code39.c b/zbar/decoder/code39.c index 89bfd43..35bbf0f 100644 --- a/zbar/decoder/code39.c +++ b/zbar/decoder/code39.c @@ -147,7 +147,6 @@ static inline signed char code39_decode9 (zbar_decoder_t *dcode) { code39_decoder_t *dcode39 = &dcode->code39; - dprintf(2, " s=%d ", dcode39->s9); if(dcode39->s9 < 9) return(-1); @@ -192,6 +191,7 @@ static inline signed char code39_decode9 (zbar_decoder_t *dcode) static inline signed char code39_decode_start (zbar_decoder_t *dcode) { code39_decoder_t *dcode39 = &dcode->code39; + dprintf(2, " s=%d ", dcode39->s9); signed char c = code39_decode9(dcode); if(c != 0x19 && c != 0x2b) { @@ -236,6 +236,16 @@ static inline void code39_postprocess (zbar_decoder_t *dcode) dcode->buf[i] = '\0'; } +static inline int +check_width (unsigned ref, + unsigned w) +{ + unsigned dref = ref; + ref *= 4; + w *= 4; + return(ref - dref <= w && w <= ref + dref); +} + zbar_symbol_type_t _zbar_decode_code39 (zbar_decoder_t *dcode) { code39_decoder_t *dcode39 = &dcode->code39; @@ -299,13 +309,21 @@ zbar_symbol_type_t _zbar_decode_code39 (zbar_decoder_t *dcode) return(ZBAR_NONE); } + dprintf(2, " s=%d ", dcode39->s9); + if(!check_width(dcode39->width, dcode39->s9)) { + dprintf(2, " [width]\n"); + if(dcode39->character) + release_lock(dcode, ZBAR_CODE39); + dcode39->character = -1; + return(ZBAR_NONE); + } + signed char c = code39_decode9(dcode); dprintf(2, " c=%d", c); /* lock shared resources */ if(!dcode39->character && acquire_lock(dcode, ZBAR_CODE39)) { dcode39->character = -1; - dprintf(1, " [locked %d]\n", dcode->lock); return(ZBAR_PARTIAL); } diff --git a/zbar/decoder/databar.c b/zbar/decoder/databar.c new file mode 100644 index 0000000..96ddbcd --- /dev/null +++ b/zbar/decoder/databar.c @@ -0,0 +1,709 @@ +/*------------------------------------------------------------------------ + * Copyright 2010 (c) Jeff Brown + * + * 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 +#include + +#ifdef DEBUG_DATABAR +# define DEBUG_LEVEL (DEBUG_DATABAR) +#endif +#include "debug.h" +#include "decoder.h" + +static const signed char finder_hash[0x20] = { + 0x16, 0x1f, 0x02, 0x00, 0x03, 0x00, 0x06, 0x0b, + 0x1f, 0x0e, 0x17, 0x0c, 0x0b, 0x14, 0x11, 0x0c, + 0x1f, 0x03, 0x13, 0x08, 0x00, 0x0a, -1, 0x16, + 0x0c, 0x09, -1, 0x1a, 0x1f, 0x1c, 0x00, -1, +}; + +/* DataBar character encoding groups */ +struct group_s { + unsigned short sum; + unsigned char wmax; + unsigned char todd; + unsigned char teven; +} groups[] = { + /* (17,4) DataBar Expanded character groups */ + { 0, 7, 87, 4 }, + { 348, 5, 52, 20 }, + { 1388, 4, 30, 52 }, + { 2948, 3, 10, 104 }, + { 3988, 1, 1, 204 }, + + /* (16,4) DataBar outer character groups */ + { 0, 8, 161, 1 }, + { 161, 6, 80, 10 }, + { 961, 4, 31, 34 }, + { 2015, 3, 10, 70 }, + { 2715, 1, 1, 126 }, + + /* (15,4) DataBar inner character groups */ + { 1516, 8, 81, 1 }, + { 1036, 6, 48, 10 }, + { 336, 4, 20, 35 }, + { 0, 2, 4, 84 }, +}; + +/* convert from heterogeneous base {1597,2841} + * to base 10 character representation + */ +static inline void +databar_postprocess (zbar_decoder_t *dcode, + unsigned d[4]) +{ + databar_decoder_t *db = &dcode->databar; + int i; + unsigned c, chk; + unsigned char *buf = dcode->buf + 15; + *--buf = '\0'; + *--buf = '\0'; + + dprintf(2, "\n d={%d,%d,%d,%d}", d[0], d[1], d[2], d[3]); + unsigned long r = d[0] * 1597 + d[1]; + d[1] = r / 10000; + r %= 10000; + r = r * 2841 + d[2]; + d[2] = r / 10000; + r %= 10000; + r = r * 1597 + d[3]; + d[3] = r / 10000; + dprintf(2, " r=%ld", r); + + for(i = 4; --i >= 0; ) { + c = r % 10; + chk += c; + if(i & 1) + chk += c << 1; + *--buf = c + '0'; + if(i) + r /= 10; + } + + dprintf(2, "\n d={%d,%d,%d}", d[1], d[2], d[3]); + r = d[1] * 2841 + d[2]; + d[2] = r / 10000; + r %= 10000; + r = r * 1597 + d[3]; + d[3] = r / 10000; + dprintf(2, " r=%ld", r); + + for(i = 4; --i >= 0; ) { + c = r % 10; + chk += c; + if(i & 1) + chk += c << 1; + *--buf = c + '0'; + if(i) + r /= 10; + } + + r = d[2] * 1597 + d[3]; + dprintf(2, "\n d={%d,%d} r=%ld", d[2], d[3], r); + + for(i = 5; --i >= 0; ) { + c = r % 10; + chk += c; + if(!(i & 1)) + chk += c << 1; + *--buf = c + '0'; + if(i) + r /= 10; + } + + /* NB linkage flag not supported */ + if(TEST_CFG(db->config, ZBAR_CFG_EMIT_CHECK)) { + chk %= 10; + if(chk) + chk = 10 - chk; + dcode->buf[13] = chk + '0'; + dcode->buflen = 14; + } + else + dcode->buflen = 13; + + dprintf(2, "\n %s", _zbar_decoder_buf_dump(dcode->buf, 16)); +} + +static inline int +check_width (unsigned wf, + unsigned wd, + unsigned n) +{ + unsigned dwf = wf * 3; + wd *= 14; + wf *= n; + return(wf - dwf <= wd && wd <= wf + dwf); +} + +static inline void +merge_segment (databar_decoder_t *db, + databar_segment_t *seg) +{ + unsigned csegs = db->csegs; + int i; + for(i = 0; i < csegs; i++) { + databar_segment_t *s = db->segs + i; + if(s != seg && s->finder == seg->finder && s->ext == seg->ext && + s->color == seg->color && s->side == seg->side && + s->data == seg->data && s->check == seg->check && + check_width(seg->width, s->width, 14)) { + /* merge with existing segment */ + unsigned cnt = s->count; + if(cnt < 0x7f) + cnt++; + seg->count = cnt; + seg->partial &= s->partial; + seg->width = (3 * seg->width + s->width + 2) / 4; + s->finder = -1; + dprintf(2, " dup@%d", i); + } + else if(s->finder >= 0) { + unsigned age = (db->epoch - s->epoch) & 0xff; + if(age >= 248 || (age >= 128 && s->count < 2)) + s->finder = -1; + } + } +} + +static inline zbar_symbol_type_t +match_segment (zbar_decoder_t *dcode, + databar_segment_t *seg) +{ + databar_decoder_t *db = &dcode->databar; + unsigned csegs = db->csegs, maxage = 0xfff; + int i0, i1, i2, maxcnt = 0; + databar_segment_t *smax[3] = { NULL, }; + + if(seg->partial && seg->count < 4) + return(ZBAR_PARTIAL); + + for(i0 = 0; i0 < csegs; i0++) { + databar_segment_t *s0 = db->segs + i0; + if(s0 == seg || s0->finder != seg->finder || s0->ext || + s0->color != seg->color || s0->side == seg->side || + (s0->partial && s0->count < 4) || + !check_width(seg->width, s0->width, 14)) + continue; + + for(i1 = 0; i1 < csegs; i1++) { + databar_segment_t *s1 = db->segs + i1; + int chkf, chks, chk; + unsigned age1; + if(i1 == i0 || s1->finder < 0 || s1->ext || + s1->color == seg->color || + (s1->partial && s1->count < 4) || + !check_width(seg->width, s1->width, 14)) + continue; + dprintf(2, "\n\t[%d,%d] f=%d(0%xx)/%d(%x%x%x)", + i0, i1, seg->finder, seg->color, + s1->finder, s1->ext, s1->color, s1->side); + + if(seg->color) + chkf = seg->finder + s1->finder * 9; + else + chkf = s1->finder + seg->finder * 9; + if(chkf > 72) + chkf--; + if(chkf > 8) + chkf--; + + chks = (seg->check + s0->check + s1->check) % 79; + + if(chkf >= chks) + chk = chkf - chks; + else + chk = 79 + chkf - chks; + + dprintf(2, " chk=(%d,%d) => %d", chkf, chks, chk); + age1 = ((db->epoch - s0->epoch) & 0xff + + (db->epoch - s1->epoch) & 0xff); + + for(i2 = i1 + 1; i2 < csegs; i2++) { + databar_segment_t *s2 = db->segs + i2; + unsigned cnt, age2, age; + if(i2 == i0 || s2->finder != s1->finder || s2->ext || + s2->color != s1->color || s2->side == s1->side || + s2->check != chk || + (s2->partial && s2->count < 4) || + !check_width(seg->width, s2->width, 14)) + continue; + age2 = (db->epoch - s2->epoch) & 0xff; + age = age1 + age2; + cnt = s0->count + s1->count + s2->count; + dprintf(2, " [%d] MATCH cnt=%d age=%d", i2, cnt, age); + if(maxcnt < cnt || + (maxcnt == cnt && maxage > age)) { + maxcnt = cnt; + maxage = age; + smax[0] = s0; + smax[1] = s1; + smax[2] = s2; + } + } + } + } + + if(!smax[0]) + return(ZBAR_PARTIAL); + + unsigned d[4]; + d[(seg->color << 1) | seg->side] = seg->data; + for(i0 = 0; i0 < 3; i0++) { + d[(smax[i0]->color << 1) | smax[i0]->side] = smax[i0]->data; + if(!--(smax[i0]->count)) + smax[i0]->finder = -1; + } + seg->finder = -1; + + if(acquire_lock(dcode, ZBAR_DATABAR)) + return(ZBAR_PARTIAL); + + databar_postprocess(dcode, d); + dcode->direction = 1 - 2 * (seg->side ^ seg->color ^ 1); + return(ZBAR_DATABAR); +} + +static inline zbar_symbol_type_t +match_segment_ext (zbar_decoder_t *dcode, + databar_segment_t *seg) +{ + /* FIXME TBD */ + seg->finder = -1; + return(ZBAR_NONE); +} + +static inline unsigned +calc_check (unsigned sig0, + unsigned sig1, + unsigned side, + unsigned mod) +{ + unsigned chk = 0; + int i; + for(i = 4; --i >= 0; ) { + chk = (chk * 3 + (sig1 & 0xf) + 1) * 3 + (sig0 & 0xf) + 1; + sig1 >>= 4; + sig0 >>= 4; + if(!(i & 1)) + chk %= mod; + } + dprintf(2, " chk=%d", chk); + + if(side) + chk = (chk * (6561 % mod)) % mod; + return(chk); +} + +static inline int +calc_value4 (unsigned sig, + unsigned n, + unsigned wmax, + unsigned nonarrow) +{ + unsigned v = 0; + n--; + + unsigned w0 = (sig >> 12) & 0xf; + if(w0 > 1) { + if(w0 > wmax) + return(-1); + unsigned n0 = n - w0; + unsigned sk20 = (n - 1) * n * (2 * n - 1); + unsigned sk21 = n0 * (n0 + 1) * (2 * n0 + 1); + v = sk20 - sk21 - 3 * (w0 - 1) * (2 * n - w0); + + if(!nonarrow && w0 > 2 && n > 4) { + unsigned k = (n - 2) * (n - 1) * (2 * n - 3) - sk21; + k -= 3 * (w0 - 2) * (14 * n - 7 * w0 - 31); + v -= k; + } + + if(n - 2 > wmax) { + unsigned wm20 = 2 * wmax * (wmax + 1); + unsigned wm21 = (2 * wmax + 1); + unsigned k = sk20; + if(n0 > wmax) { + k -= sk21; + k += 3 * (w0 - 1) * (wm20 - wm21 * (2 * n - w0)); + } + else { + k -= (wmax + 1) * (wmax + 2) * (2 * wmax + 3); + k += 3 * (n - wmax - 2) * (wm20 - wm21 * (n + wmax + 1)); + } + k *= 3; + v -= k; + } + v /= 12; + } + else + nonarrow = 1; + n -= w0; + + unsigned w1 = (sig >> 8) & 0xf; + if(w1 > 1) { + if(w1 > wmax) + return(-1); + v += (2 * n - w1) * (w1 - 1) / 2; + if(!nonarrow && w1 > 2 && n > 3) + v -= (2 * n - w1 - 5) * (w1 - 2) / 2; + if(n - 1 > wmax) { + if(n - w1 > wmax) + v -= (w1 - 1) * (2 * n - w1 - 2 * wmax); + else + v -= (n - wmax) * (n - wmax - 1); + } + } + else + nonarrow = 1; + n -= w1; + + unsigned w2 = (sig >> 4) & 0xf; + if(w2 > 1) { + if(w2 > wmax) + return(-1); + v += w2 - 1; + if(!nonarrow && w2 > 2 && n > 2) + v -= n - 2; + if(n > wmax) + v -= n - wmax; + } + else + nonarrow = 1; + + unsigned w3 = sig & 0xf; + if(w3 == 1) + nonarrow = 1; + else if(w3 > wmax) + return(-1); + + if(!nonarrow) + return(-1); + + return(v); +} + +static inline zbar_symbol_type_t +decode_char (zbar_decoder_t *dcode, + databar_segment_t *seg, + int off, + int dir) +{ + databar_decoder_t *db = &dcode->databar; + unsigned s = calc_s(dcode, (dir > 0) ? off : off - 6, 8); + int n, i, emin[2] = { 0, }, sum = 0; + unsigned sig0 = 0, sig1 = 0; + + if(seg->ext) + n = 17; + else if(seg->side) + n = 15; + else + n = 16; + emin[1] = -n; + + dprintf(2, " char: d=%d off=%d n=%d s=%d w=%d sig=", + dir, off, n, s, seg->width); + if(s < 13 || !check_width(seg->width, s, n)) + return(ZBAR_NONE); + + for(i = 4; --i >= 0; ) { + int e = decode_e(pair_width(dcode, off), s, n); + if(e < 0) + return(ZBAR_NONE); + dprintf(2, "%d", e); + sum = e - sum; + off += dir; + sig1 <<= 4; + if(emin[1] < -sum) + emin[1] = -sum; + sig1 += sum; + if(!i) + break; + + e = decode_e(pair_width(dcode, off), s, n); + if(e < 0) + return(ZBAR_NONE); + dprintf(2, "%d", e); + sum = e - sum; + off += dir; + sig0 <<= 4; + if(emin[0] > sum) + emin[0] = sum; + sig0 += sum; + } + + int diff = emin[~n & 1]; + diff = diff + (diff << 4); + diff = diff + (diff << 8); + + sig0 -= diff; + sig1 += diff; + + dprintf(2, " emin=%d,%d el=%04x/%04x", emin[0], emin[1], sig0, sig1); + + unsigned sum0 = sig0 + (sig0 >> 8); + unsigned sum1 = sig1 + (sig1 >> 8); + sum0 += sum0 >> 4; + sum1 += sum1 >> 4; + sum0 &= 0xf; + sum1 &= 0xf; + + dprintf(2, " sum=%d/%d", sum0, sum1); + + if(sum0 + sum1 + 8 != n) { + dprintf(2, " [SUM]"); + return(ZBAR_NONE); + } + + if(((sum0 ^ (n >> 1)) | (sum1 ^ (n >> 1) ^ n)) & 1) { + dprintf(2, " [ODD]"); + return(ZBAR_NONE); + } + + i = ((n & 0x3) ^ 1) * 5 + (sum1 >> 1); + zassert(i < sizeof(groups) / sizeof(*groups), -1, + "n=%d sum=%d/%d sig=%04x/%04x g=%d", + n, sum0, sum1, sig0, sig1, i); + struct group_s *g = groups + i; + dprintf(2, "\n g=%d(%d,%d,%d/%d)", + i, g->sum, g->wmax, g->todd, g->teven); + + int vodd = calc_value4(sig0 + 0x1111, sum0 + 4, g->wmax, ~n & 1); + dprintf(2, " v=%d", vodd); + if(vodd < 0 || vodd > g->todd) + return(ZBAR_NONE); + + int veven = calc_value4(sig1 + 0x1111, sum1 + 4, 9 - g->wmax, n & 1); + dprintf(2, "/%d", veven); + if(veven < 0 || veven > g->teven) + return(ZBAR_NONE); + + int v = g->sum; + if(n & 2) + v += vodd + veven * g->todd; + else + v += veven + vodd * g->teven; + + dprintf(2, " f=%d(%x%x%x)", seg->finder, seg->ext, seg->color, seg->side); + + unsigned chk = 0; + if(seg->ext) { + /* FIXME skip A1 */ + chk = calc_check(sig0, sig1, seg->side, 211); + if(seg->color) + chk = (chk * 189) % 211; + } + else { + chk = calc_check(sig0, sig1, seg->side, 79); + if(seg->color) + chk = (chk * 16) % 79; + } + dprintf(2, " => %d val=%d", chk, v); + + seg->epoch = db->epoch++; + seg->check = chk; + seg->data = v; + + merge_segment(db, seg); + + return(ZBAR_PARTIAL); +} + +static inline int +alloc_segment (databar_decoder_t *db) +{ + unsigned maxage = 0, csegs = db->csegs; + int i, old = -1; + for(i = 0; i < csegs; i++) { + databar_segment_t *seg = db->segs + i; + unsigned age; + if(seg->finder < 0) { + dprintf(2, " free@%d", i); + return(i); + } + age = (db->epoch - seg->epoch) & 0xff; + if(age >= 128 && seg->count < 2) { + seg->finder = -1; + dprintf(2, " stale@%d (%d - %d = %d)", + i, db->epoch, seg->epoch, age); + return(i); + } + + /* score based on both age and count */ + if(age > seg->count) + age = age - seg->count + 1; + else + age = 1; + + if(maxage < age) { + maxage = age; + old = i; + dprintf(2, " old@%d(%u)", i, age); + } + } + + if(csegs < DATABAR_MAX_SEGMENTS) { + dprintf(2, " new@%d", i); + i = csegs; + csegs *= 2; + if(csegs > DATABAR_MAX_SEGMENTS) + csegs = DATABAR_MAX_SEGMENTS; + if(csegs != db->csegs) { + db->segs = realloc(db->segs, csegs * sizeof(*db->segs)); + db->csegs = csegs; + while(--csegs >= i) + db->segs[csegs].finder = -1; + return(i); + } + } + zassert(old >= 0, -1, "\n"); + + db->segs[old].finder = -1; + return(old); +} + +static inline zbar_symbol_type_t +decode_finder (zbar_decoder_t *dcode) +{ + databar_decoder_t *db = &dcode->databar; + databar_segment_t *seg; + unsigned e0 = pair_width(dcode, 1); + unsigned e2 = pair_width(dcode, 3); + unsigned e1, e3, s, finder, dir; + int sig, iseg; + dprintf(2, " databar: e0=%d e2=%d", e0, e2); + if(e0 < e2) { + unsigned e = e2 * 4; + if(e < 15 * e0 || e > 34 * e0) + return(ZBAR_NONE); + dir = 0; + e3 = pair_width(dcode, 4); + } + else { + unsigned e = e0 * 4; + if(e < 15 * e2 || e > 34 * e2) + return(ZBAR_NONE); + dir = 1; + e2 = e0; + e3 = pair_width(dcode, 0); + } + e1 = pair_width(dcode, 2); + + s = e1 + e3; + dprintf(2, " e1=%d e3=%d dir=%d s=%d", e1, e3, dir, s); + if(s < 12) + return(ZBAR_NONE); + + sig = ((decode_e(e3, s, 14) << 8) | (decode_e(e2, s, 14) << 4) | + decode_e(e1, s, 14)); + dprintf(2, " sig=%04x", sig & 0xfff); + if(sig < 0 || + ((sig >> 4) & 0xf) < 8 || + ((sig >> 4) & 0xf) > 10 || + (sig & 0xf) >= 10 || + ((sig >> 8) & 0xf) >= 10) + return(ZBAR_NONE); + + finder = (finder_hash[(sig - (sig >> 5)) & 0x1f] + + finder_hash[(sig >> 1) & 0x1f]) & 0x1f; + dprintf(2, " finder=%d", finder); + if(finder == 0x1f) + return(ZBAR_NONE); + + iseg = alloc_segment(db); + if(iseg < 0) + return(ZBAR_NONE); + dprintf(2, " i=%d\n", iseg); + + seg = db->segs + iseg; + seg->finder = (finder >= 9) ? finder - 9 : finder; + seg->ext = (finder >= 9); + seg->color = get_color(dcode) ^ dir ^ 1; + seg->side = dir; + seg->partial = 0; + seg->count = 1; + seg->width = s; + + int rc = decode_char(dcode, seg, 12 - dir, -1); + if(!rc) + seg->partial = 1; + + int i = (dcode->idx + 8 + dir) & 0xf; + zassert(db->chars[i] == -1, ZBAR_NONE, "\n"); + db->chars[i] = iseg; + return(rc); +} + +zbar_symbol_type_t +_zbar_decode_databar (zbar_decoder_t *dcode) +{ + databar_decoder_t *db = &dcode->databar; + databar_segment_t *seg, *pair; + zbar_symbol_type_t sym; + int iseg, i = dcode->idx & 0xf; + sym = decode_finder(dcode); + dprintf(2, "\n"); + + iseg = db->chars[i]; + if(iseg < 0) + return(sym); + + db->chars[i] = -1; + seg = db->segs + iseg; + dprintf(2, " databar: i=%d part=%d", iseg, seg->partial); + + if(seg->partial) { + pair = NULL; + seg->side = !seg->side; + } + else { + int jseg = alloc_segment(db); + pair = db->segs + iseg; + seg = db->segs + jseg; + seg->finder = pair->finder; + seg->ext = pair->ext; + seg->color = pair->color; + seg->side = !pair->side; + seg->partial = 0; + seg->count = 1; + seg->width = pair->width; + } + dprintf(2, "\n"); + + sym = decode_char(dcode, seg, 1, 1); + if(sym) { + if(seg->ext) + sym = match_segment_ext(dcode, seg); + else + sym = match_segment(dcode, seg); + } + else { + seg->finder = -1; + if(pair) + pair->partial = 1; + } + + dprintf(2, "\n"); + return(sym); +} diff --git a/zbar/decoder/databar.h b/zbar/decoder/databar.h new file mode 100644 index 0000000..5c98fd3 --- /dev/null +++ b/zbar/decoder/databar.h @@ -0,0 +1,79 @@ +/*------------------------------------------------------------------------ + * Copyright 2010 (c) Jeff Brown + * + * 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 + *------------------------------------------------------------------------*/ +#ifndef _DATABAR_H_ +#define _DATABAR_H_ + +#define DATABAR_MAX_SEGMENTS 32 + +/* active DataBar (partial) segment entry */ +typedef struct databar_segment_s { + signed finder : 5; /* finder pattern */ + unsigned ext : 1; /* DataBar extended finder */ + unsigned color : 1; /* finder coloring */ + unsigned side : 1; /* data character side of finder */ + + unsigned partial : 1; /* unpaired partial segment */ + unsigned count : 7; /* times encountered */ + unsigned epoch : 8; /* age, in characters scanned */ + unsigned check : 8; /* bar checksum */ + signed short data; /* decoded character data */ + unsigned short width; /* measured width of finder (14 modules) */ +} databar_segment_t; + +/* DataBar specific decode state */ +typedef struct databar_decoder_s { + unsigned config; /* decoder configuration flags */ + + unsigned csegs : 8; /* allocated segments */ + unsigned epoch : 8; /* current scan */ + + databar_segment_t *segs; /* active segment list */ + signed char chars[16]; /* outstanding character indices */ +} databar_decoder_t; + +/* reset DataBar segment decode state */ +static inline void databar_new_scan (databar_decoder_t *db) +{ + int i; + for(i = 0; i < 16; i++) + if(db->chars[i] >= 0) { + databar_segment_t *seg = db->segs + db->chars[i]; + if(seg->partial) + seg->finder = -1; + db->chars[i] = -1; + } +} + +/* reset DataBar accumulated segments */ +static inline void databar_reset (databar_decoder_t *db) +{ + int i, n = db->csegs; + databar_new_scan(db); + for(i = 0; i < n; i++) + db->segs[i].finder = -1; +} + +/* decode DataBar symbols */ +zbar_symbol_type_t _zbar_decode_databar(zbar_decoder_t *dcode); + +#endif diff --git a/zbar/decoder/ean.c b/zbar/decoder/ean.c index 93d82b2..67fdd73 100644 --- a/zbar/decoder/ean.c +++ b/zbar/decoder/ean.c @@ -109,6 +109,15 @@ static inline const unsigned char *dsprintbuf(ean_decoder_t *ean) } #endif +static inline int check_width (unsigned w0, + unsigned w1) +{ + unsigned dw0 = w0; + w0 *= 8; + w1 *= 8; + return(w0 - dw0 <= w1 && w1 <= w0 + dw0); +} + /* evaluate previous N (>= 2) widths as auxiliary pattern, * using preceding 4 as character width */ @@ -150,6 +159,8 @@ static inline signed char aux_start (zbar_decoder_t *dcode) /* FIXME NB add-on has no guard in reverse */ unsigned e1, e2 = get_width(dcode, 5) + get_width(dcode, 6); unsigned char E1; + if(dcode->ean.s4 < 6) + return(-1); if(decode_e(e2, dcode->ean.s4, 7)) { dprintf(2, " [invalid any]"); return(/*FIXME (get_color(dcode) == ZBAR_SPACE) ? STATE_ADDON : */-1); @@ -357,17 +368,29 @@ static inline zbar_symbol_type_t decode_pass (zbar_decoder_t *dcode, } if(!(idx & 0x03) && idx <= 0x14) { - signed char code; + signed char code = -1; + unsigned w = pass->width; if(!dcode->ean.s4) return(0); /* validate guard bars before decoding first char of symbol */ if(!pass->state) { pass->state = aux_start(dcode); + pass->width = dcode->ean.s4; if(pass->state < 0) return(0); idx = pass->state & STATE_IDX; } - code = decode4(dcode); + else { + w = check_width(w, dcode->ean.s4); + if(w) + pass->width = (pass->width + dcode->ean.s4 * 3) / 4; + } + + if(w) + code = decode4(dcode); + else + dprintf(2, " [bad width]"); + if(code < 0 && idx != 0x10) pass->state = -1; else if(code < 0) @@ -480,7 +503,9 @@ static inline zbar_symbol_type_t integrate_partial (ean_decoder_t *ean, signed char i, j, right = !!(part & EAN_RIGHT); /* copy raw data into holding buffer */ /* if same partial is not consistent, reset others */ - dprintf(2, " integrate part=%x (%s)", part, dsprintbuf(ean)); + dprintf(2, " integrate part=%x (%s) w=%d=>%d", + part, dsprintbuf(ean), ean->width, pass->width); + if(part & ZBAR_ADDON) { /* FIXME TBD */ for(i = (part == ZBAR_ADDON5) ? 4 : 1; i >= 0; i--) { @@ -501,6 +526,12 @@ static inline zbar_symbol_type_t integrate_partial (ean_decoder_t *ean, ean->left = ean->right = ean->addon = ZBAR_NONE; } + if((ean->left || ean->right || ean->addon) && + !check_width(ean->width, pass->width)) { + dprintf(2, " rst(width %d)", pass->width); + ean->left = ean->right = ean->addon = ZBAR_NONE; + } + if(right) { part &= ZBAR_SYMBOL; j = (part == ZBAR_EAN13) ? 12 : 7; @@ -531,6 +562,7 @@ static inline zbar_symbol_type_t integrate_partial (ean_decoder_t *ean, else /* ZBAR_UPCE */ ean_expand_upce(ean, pass); } + ean->width = pass->width; if((part & ZBAR_SYMBOL) != ZBAR_UPCE) { part = (ean->left & ean->right); diff --git a/zbar/decoder/ean.h b/zbar/decoder/ean.h index 8ab895f..a1b09f9 100644 --- a/zbar/decoder/ean.h +++ b/zbar/decoder/ean.h @@ -29,6 +29,7 @@ typedef struct ean_pass_s { #define STATE_REV 0x80 /* scan direction reversed */ #define STATE_ADDON 0x40 /* scanning add-on */ #define STATE_IDX 0x1f /* element offset into symbol */ + unsigned width; /* width of last character */ unsigned char raw[7]; /* decode in process */ } ean_pass_t; @@ -39,7 +40,7 @@ typedef struct ean_decoder_s { zbar_symbol_type_t right; zbar_symbol_type_t addon; int direction; /* scan direction */ - unsigned s4; /* character width */ + unsigned s4, width; /* character width */ signed char buf[18]; /* holding buffer */ signed char enable; diff --git a/zbar/decoder/i25.c b/zbar/decoder/i25.c index 56e6501..7d3d3af 100644 --- a/zbar/decoder/i25.c +++ b/zbar/decoder/i25.c @@ -124,6 +124,21 @@ static inline signed char i25_decode_start (zbar_decoder_t *dcode) return(ZBAR_PARTIAL); } +static inline int i25_acquire_lock (zbar_decoder_t *dcode) +{ + int i; + /* lock shared resources */ + if(acquire_lock(dcode, ZBAR_I25)) { + dcode->i25.character = -1; + return(1); + } + + /* copy holding buffer */ + for(i = 4; --i >= 0; ) + dcode->buf[i] = dcode->i25.buf[i]; + return(0); +} + static inline signed char i25_decode_end (zbar_decoder_t *dcode) { i25_decoder_t *dcode25 = &dcode->i25; @@ -133,7 +148,8 @@ static inline signed char i25_decode_end (zbar_decoder_t *dcode) if((quiet && quiet < dcode25->width * 3 / 8) || decode_e(get_width(dcode, 1), dcode25->width, 45) > 2 || decode_e(get_width(dcode, 2), dcode25->width, 45) > 2) { - dprintf(3, " s=%d q=%d [invalid qz]\n", dcode25->width, quiet); + dprintf(3, " i25: s=%d q=%d [invalid qz]\n", + dcode25->width, quiet); return(ZBAR_NONE); } @@ -145,6 +161,10 @@ static inline signed char i25_decode_end (zbar_decoder_t *dcode) decode_e(get_width(dcode, 4), dcode25->width, 45) > 2)) return(ZBAR_NONE); + if(dcode25->character <= 4 && + i25_acquire_lock(dcode)) + return(ZBAR_PARTIAL); + dcode->direction = 1 - 2 * dcode25->direction; if(dcode25->direction) { /* reverse buffer */ @@ -198,38 +218,45 @@ zbar_symbol_type_t _zbar_decode_i25 (zbar_decoder_t *dcode) (dcode25->direction) ? '<' : '>', dcode25->character, dcode25->element); - /* lock shared resources */ - if(!dcode25->character && acquire_lock(dcode, ZBAR_I25)) { - dcode25->character = -1; - dprintf(2, " [locked %d]\n", dcode->lock); + if(dcode25->character == 4 && i25_acquire_lock(dcode)) return(ZBAR_PARTIAL); - } unsigned char c = i25_decode10(dcode, 1); dprintf(2, " c=%x", c); + if(c > 9) { + dprintf(2, " [aborted]\n"); + goto reset; + } - if(c > 9 || - ((dcode25->character >= BUFFER_MIN) && - size_buf(dcode, dcode25->character + 2))) { - dprintf(2, (c > 9) ? " [aborted]\n" : " [overflow]\n"); - release_lock(dcode, ZBAR_I25); - dcode25->character = -1; - return(ZBAR_NONE); + if((dcode25->character >= BUFFER_MIN) && + size_buf(dcode, dcode25->character + 2)) { + dprintf(2, " [overflow]\n"); + goto reset; } - dcode->buf[dcode25->character++] = c + '0'; + + unsigned char *buf; + if(dcode25->character >= 4) + buf = dcode->buf; + else + buf = dcode25->buf; + buf[dcode25->character++] = c + '0'; c = i25_decode10(dcode, 0); dprintf(2, " c=%x", c); if(c > 9) { dprintf(2, " [aborted]\n"); - release_lock(dcode, ZBAR_I25); - dcode25->character = -1; - return(ZBAR_NONE); + goto reset; } else dprintf(2, "\n"); - dcode->buf[dcode25->character++] = c + '0'; + buf[dcode25->character++] = c + '0'; dcode25->element = 10; return((dcode25->character == 2) ? ZBAR_PARTIAL : ZBAR_NONE); + +reset: + if(dcode25->character >= 4) + release_lock(dcode, ZBAR_I25); + dcode25->character = -1; + return(ZBAR_NONE); } diff --git a/zbar/decoder/i25.h b/zbar/decoder/i25.h index 4f4bee0..bd61975 100644 --- a/zbar/decoder/i25.h +++ b/zbar/decoder/i25.h @@ -30,6 +30,7 @@ typedef struct i25_decoder_s { int character : 12; /* character position in symbol */ unsigned s10; /* current character width */ unsigned width; /* last character width */ + unsigned char buf[4]; /* initial scan buffer */ unsigned config; int configs[NUM_CFGS]; /* int valued configurations */ diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 0ac0f47..c271710 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -396,11 +396,6 @@ static void symbol_handler (zbar_decoder_t *dcode) unsigned datalen; zbar_symbol_t *sym; - /* FIXME assert(type == ZBAR_PARTIAL) */ - /* FIXME debug flag to save/display all PARTIALs */ - if(type <= ZBAR_PARTIAL) - return; - #ifdef ENABLE_QRCODE if(type == ZBAR_QRCODE) { qr_handler(iscn); @@ -410,9 +405,6 @@ static void symbol_handler (zbar_decoder_t *dcode) assert(type != ZBAR_QRCODE); #endif - data = zbar_decoder_get_data(dcode); - datalen = zbar_decoder_get_data_length(dcode); - if(TEST_CFG(iscn, ZBAR_CFG_POSITION)) { /* tmp position fixup */ int w = zbar_scanner_get_width(iscn->scn); @@ -427,12 +419,23 @@ static void symbol_handler (zbar_decoder_t *dcode) } } + /* FIXME debug flag to save/display all PARTIALs */ + if(type <= ZBAR_PARTIAL) { + zprintf(256, "partial symbol @(%d,%d)\n", x, y); + return; + } + + data = zbar_decoder_get_data(dcode); + datalen = zbar_decoder_get_data_length(dcode); + /* FIXME need better symbol matching */ for(sym = iscn->syms->head; sym; sym = sym->next) if(sym->type == type && sym->datalen == datalen && !memcmp(sym->data, data, datalen)) { sym->quality++; + zprintf(224, "dup symbol @(%d,%d): dup %s: %.20s\n", + x, y, zbar_get_symbol_name(type), data); if(TEST_CFG(iscn, ZBAR_CFG_POSITION)) /* add new point to existing set */ /* FIXME should be polygon */ @@ -445,8 +448,11 @@ static void symbol_handler (zbar_decoder_t *dcode) memcpy(sym->data, data, datalen + 1); /* initialize first point */ - if(TEST_CFG(iscn, ZBAR_CFG_POSITION)) + if(TEST_CFG(iscn, ZBAR_CFG_POSITION)) { + zprintf(192, "new symbol @(%d,%d): %s: %.20s\n", + x, y, zbar_get_symbol_name(type), data); sym_add_point(sym, x, y); + } dir = zbar_decoder_get_direction(dcode); if(dir) @@ -792,7 +798,8 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, (density == 1 || CFG(iscn, ZBAR_CFG_Y_DENSITY) == 1)) { zbar_symbol_t **symp = &syms->head, *sym; while((sym = *symp)) { - if(sym->type < ZBAR_I25 && sym->type > ZBAR_PARTIAL && + if(((sym->type < ZBAR_I25 && sym->type > ZBAR_PARTIAL) || + sym->type == ZBAR_DATABAR) && sym->quality < 4) { /* recycle */ *symp = sym->next; diff --git a/zbar/symbol.c b/zbar/symbol.c index da87595..86971d9 100644 --- a/zbar/symbol.c +++ b/zbar/symbol.c @@ -39,6 +39,7 @@ const char *zbar_get_symbol_name (zbar_symbol_type_t sym) case ZBAR_EAN13: return("EAN-13"); case ZBAR_ISBN13: return("ISBN-13"); case ZBAR_I25: return("I2/5"); + case ZBAR_DATABAR: return("DataBar"); case ZBAR_CODE39: return("CODE-39"); case ZBAR_CODE128: return("CODE-128"); case ZBAR_PDF417: return("PDF417"); diff --git a/zbarimg/Makefile.am.inc b/zbarimg/Makefile.am.inc index 2ba65f6..1008c94 100644 --- a/zbarimg/Makefile.am.inc +++ b/zbarimg/Makefile.am.inc @@ -12,10 +12,10 @@ endif EXTRA_DIST += test/barcodetest.py -check-images: +check-images: zbarimg/zbarimg $(PYTHON) $(srcdir)/test/barcodetest.py -regress-images: +regress-images: zbarimg/zbarimg suite='$(ZBAR_TESTS)'; \ if test "x$$suite" = "x"; then suite='http://zbar.sf.net/test'; fi ; \ $(PYTHON) $(srcdir)/test/barcodetest.py $$suite diff --git a/zbarimg/zbarimg.c b/zbarimg/zbarimg.c index 3467a83..751fe37 100644 --- a/zbarimg/zbarimg.c +++ b/zbarimg/zbarimg.c @@ -77,7 +77,7 @@ static const char *warning_not_found = " - is the barcode type supported?" " currently supported symbologies are:\n" " EAN/UPC (EAN-13, EAN-8, UPC-A, UPC-E, ISBN-10, ISBN-13),\n" - " Code 128, Code 39 and Interleaved 2 of 5\n" + " Code 128, Code 39, DataBar and Interleaved 2 of 5\n" " - is the barcode large enough in the image?\n" " - is the barcode mostly in focus?\n" " - is there sufficient contrast/illumination?\n" From b464a83da3e184f5069397ba3bf75fe282a0bbf3 Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 12 Jul 2010 14:12:51 -0400 Subject: [PATCH 216/328] add language bindings for DataBar --- ChangeLog | 1 + java/net/sourceforge/zbar/Config.java | 3 +++ java/net/sourceforge/zbar/Symbol.java | 2 ++ perl/ZBar.xs | 2 ++ perl/t/ZBar.t | 21 +++++++++++---------- python/test/test_zbar.py | 19 +++++++++++++++++++ python/zbarmodule.c | 20 +++++++++++--------- zbar/decoder/databar.c | 16 +++++++++++++--- zbar/image.c | 4 ++-- zbar/video.c | 4 ++-- 10 files changed, 66 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index b46f582..c6f09e3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * add language bindings for DataBar * add preliminary support for GS1 DataBar (RSS-14) symbology * enable torch for iPhone 4 * enhance decoder reliability (EAN, Code 39, Code 128) diff --git a/java/net/sourceforge/zbar/Config.java b/java/net/sourceforge/zbar/Config.java index 164c7e1..019ea6c 100644 --- a/java/net/sourceforge/zbar/Config.java +++ b/java/net/sourceforge/zbar/Config.java @@ -43,6 +43,9 @@ public class Config /** Maximum data length for valid decode. */ public static final int MAX_LEN = 0x21; + /** Required video consistency frames. */ + public static final int UNCERTAINTY = 0x40; + /** Enable scanner to collect position data. */ public static final int POSITION = 0x80; diff --git a/java/net/sourceforge/zbar/Symbol.java b/java/net/sourceforge/zbar/Symbol.java index 185c13f..9b239a3 100644 --- a/java/net/sourceforge/zbar/Symbol.java +++ b/java/net/sourceforge/zbar/Symbol.java @@ -49,6 +49,8 @@ public class Symbol public static final int ISBN13 = 14; /** Interleaved 2 of 5. */ public static final int I25 = 25; + /** DataBar. */ + public static final int DATABAR = 34; /** Code 39. */ public static final int CODE39 = 39; /** PDF417. */ diff --git a/perl/ZBar.xs b/perl/ZBar.xs index adad6bd..e0a792a 100644 --- a/perl/ZBar.xs +++ b/perl/ZBar.xs @@ -278,6 +278,7 @@ BOOT: CONSTANT(config, CFG_, ASCII, "ascii"); CONSTANT(config, CFG_, MIN_LEN, "min-length"); CONSTANT(config, CFG_, MAX_LEN, "max-length"); + CONSTANT(config, CFG_, UNCERTAINTY, "uncertainty"); CONSTANT(config, CFG_, POSITION, "position"); CONSTANT(config, CFG_, X_DENSITY, "x-density"); CONSTANT(config, CFG_, Y_DENSITY, "y-density"); @@ -314,6 +315,7 @@ BOOT: CONSTANT(symbol_type, , UPCA, zbar_get_symbol_name(ZBAR_UPCA)); CONSTANT(symbol_type, , EAN13, zbar_get_symbol_name(ZBAR_EAN13)); CONSTANT(symbol_type, , ISBN13, zbar_get_symbol_name(ZBAR_ISBN13)); + CONSTANT(symbol_type, , DATABAR, zbar_get_symbol_name(ZBAR_DATABAR)); CONSTANT(symbol_type, , I25, zbar_get_symbol_name(ZBAR_I25)); CONSTANT(symbol_type, , CODE39, zbar_get_symbol_name(ZBAR_CODE39)); CONSTANT(symbol_type, , PDF417, zbar_get_symbol_name(ZBAR_PDF417)); diff --git a/perl/t/ZBar.t b/perl/t/ZBar.t index 64d1f02..4e4489b 100755 --- a/perl/t/ZBar.t +++ b/perl/t/ZBar.t @@ -3,7 +3,7 @@ use warnings; use strict; -use Test::More tests => 31; +use Test::More tests => 33; ######################### @@ -36,15 +36,16 @@ sub test_enum { } test_enum('config', - [Barcode::ZBar::Config::ENABLE, 'enable', 0], - [Barcode::ZBar::Config::ADD_CHECK, 'add-check', 1], - [Barcode::ZBar::Config::EMIT_CHECK, 'emit-check', 2], - [Barcode::ZBar::Config::ASCII, 'ascii', 3], - [Barcode::ZBar::Config::MIN_LEN, 'min-length', 32], - [Barcode::ZBar::Config::MAX_LEN, 'max-length', 33], - [Barcode::ZBar::Config::POSITION, 'position', 128], - [Barcode::ZBar::Config::X_DENSITY, 'x-density', 256], - [Barcode::ZBar::Config::Y_DENSITY, 'y-density', 257], + [Barcode::ZBar::Config::ENABLE, 'enable', 0], + [Barcode::ZBar::Config::ADD_CHECK, 'add-check', 1], + [Barcode::ZBar::Config::EMIT_CHECK, 'emit-check', 2], + [Barcode::ZBar::Config::ASCII, 'ascii', 3], + [Barcode::ZBar::Config::MIN_LEN, 'min-length', 32], + [Barcode::ZBar::Config::MAX_LEN, 'max-length', 33], + [Barcode::ZBar::Config::UNCERTAINTY, 'uncertainty', 64], + [Barcode::ZBar::Config::POSITION, 'position', 128], + [Barcode::ZBar::Config::X_DENSITY, 'x-density', 256], + [Barcode::ZBar::Config::Y_DENSITY, 'y-density', 257], ); ######################### diff --git a/python/test/test_zbar.py b/python/test/test_zbar.py index 58f3e73..1c1aa02 100755 --- a/python/test/test_zbar.py +++ b/python/test/test_zbar.py @@ -20,6 +20,9 @@ def load_image(): encoded_widths = \ '9 111 212241113121211311141132 11111 311213121312121332111132 111 9' +databar_widths = \ + '11 31111333 13911 31131231 11214222 11553 21231313 1' + VIDEO_DEVICE = None if 'VIDEO_DEVICE' in os.environ: VIDEO_DEVICE = os.environ['VIDEO_DEVICE'] @@ -59,6 +62,7 @@ def test_configs(self): zbar.Config.ASCII, zbar.Config.MIN_LEN, zbar.Config.MAX_LEN, + zbar.Config.UNCERTAINTY, zbar.Config.POSITION, zbar.Config.X_DENSITY, zbar.Config.Y_DENSITY): @@ -75,6 +79,7 @@ def test_symbologies(self): zbar.Symbol.UPCA, zbar.Symbol.EAN13, zbar.Symbol.ISBN13, + zbar.Symbol.DATABAR, zbar.Symbol.I25, zbar.Symbol.CODE39, zbar.Symbol.PDF417, @@ -193,6 +198,20 @@ def handler(dcode, closure): self.assert_(inline_sym[0] is zbar.Symbol.EAN13) self.assertEqual(explicit_closure, [ 2 ]) + def test_databar(self): + self.dcode.set_config(zbar.Symbol.QRCODE, zbar.Config.ENABLE, 0) + for (i, width) in enumerate(databar_widths): + if width == ' ': continue + sym = self.dcode.decode_width(int(width)) + if i < len(databar_widths) - 1: + self.assert_(sym is zbar.Symbol.NONE or + sym is zbar.Symbol.PARTIAL) + + self.assert_(sym is zbar.Symbol.DATABAR) + self.assertEqual(self.dcode.data, '24012345678905') + self.assert_(self.dcode.color is zbar.BAR) + self.assertEqual(self.dcode.direction, 1) + # FIXME test exception during callback class TestImage(ut.TestCase): diff --git a/python/zbarmodule.c b/python/zbarmodule.c index bffe2ed..f179d23 100644 --- a/python/zbarmodule.c +++ b/python/zbarmodule.c @@ -52,6 +52,7 @@ static const enumdef symbol_defs[] = { { "UPCA", ZBAR_UPCA }, { "EAN13", ZBAR_EAN13 }, { "ISBN13", ZBAR_ISBN13 }, + { "DATABAR", ZBAR_DATABAR }, { "I25", ZBAR_I25 }, { "CODE39", ZBAR_CODE39 }, { "PDF417", ZBAR_PDF417 }, @@ -61,15 +62,16 @@ static const enumdef symbol_defs[] = { }; static const enumdef config_defs[] = { - { "ENABLE", ZBAR_CFG_ENABLE }, - { "ADD_CHECK", ZBAR_CFG_ADD_CHECK }, - { "EMIT_CHECK", ZBAR_CFG_EMIT_CHECK }, - { "ASCII", ZBAR_CFG_ASCII }, - { "MIN_LEN", ZBAR_CFG_MIN_LEN }, - { "MAX_LEN", ZBAR_CFG_MAX_LEN }, - { "POSITION", ZBAR_CFG_POSITION }, - { "X_DENSITY", ZBAR_CFG_X_DENSITY }, - { "Y_DENSITY", ZBAR_CFG_Y_DENSITY }, + { "ENABLE", ZBAR_CFG_ENABLE }, + { "ADD_CHECK", ZBAR_CFG_ADD_CHECK }, + { "EMIT_CHECK", ZBAR_CFG_EMIT_CHECK }, + { "ASCII", ZBAR_CFG_ASCII }, + { "MIN_LEN", ZBAR_CFG_MIN_LEN }, + { "MAX_LEN", ZBAR_CFG_MAX_LEN }, + { "UNCERTAINTY", ZBAR_CFG_UNCERTAINTY }, + { "POSITION", ZBAR_CFG_POSITION }, + { "X_DENSITY", ZBAR_CFG_X_DENSITY }, + { "Y_DENSITY", ZBAR_CFG_Y_DENSITY }, { NULL, } }; diff --git a/zbar/decoder/databar.c b/zbar/decoder/databar.c index 96ddbcd..5f2e47d 100644 --- a/zbar/decoder/databar.c +++ b/zbar/decoder/databar.c @@ -74,7 +74,7 @@ databar_postprocess (zbar_decoder_t *dcode, { databar_decoder_t *db = &dcode->databar; int i; - unsigned c, chk; + unsigned c, chk = 0; unsigned char *buf = dcode->buf + 15; *--buf = '\0'; *--buf = '\0'; @@ -570,10 +570,20 @@ alloc_segment (databar_decoder_t *db) if(csegs > DATABAR_MAX_SEGMENTS) csegs = DATABAR_MAX_SEGMENTS; if(csegs != db->csegs) { + databar_segment_t *seg; db->segs = realloc(db->segs, csegs * sizeof(*db->segs)); db->csegs = csegs; - while(--csegs >= i) - db->segs[csegs].finder = -1; + seg = db->segs + csegs; + while(--seg, --csegs >= i) { + seg->finder = -1; + seg->ext = 0; + seg->color = 0; + seg->side = 0; + seg->partial = 0; + seg->count = 0; + seg->epoch = 0; + seg->check = 0; + } return(i); } } diff --git a/zbar/image.c b/zbar/image.c index aa56a5f..359c837 100644 --- a/zbar/image.c +++ b/zbar/image.c @@ -220,11 +220,11 @@ const zbar_symbol_set_t *zbar_image_get_symbols (const zbar_image_t *img) void zbar_image_set_symbols (zbar_image_t *img, const zbar_symbol_set_t *syms) { + if(syms) + zbar_symbol_set_ref(syms, 1); if(img->syms) zbar_symbol_set_ref(img->syms, -1); img->syms = (zbar_symbol_set_t*)syms; - if(syms) - zbar_symbol_set_ref(img->syms, 1); } const zbar_symbol_t *zbar_image_first_symbol (const zbar_image_t *img) diff --git a/zbar/video.c b/zbar/video.c index ef58717..f4efde2 100644 --- a/zbar/video.c +++ b/zbar/video.c @@ -97,7 +97,7 @@ void zbar_video_destroy (zbar_video_t *vdo) int i; for(i = 0; i < ZBAR_VIDEO_IMAGES_MAX; i++) if(vdo->images[i]) - free(vdo->images[i]); + _zbar_image_free(vdo->images[i]); free(vdo->images); } while(vdo->shadow_image) { @@ -233,7 +233,7 @@ static inline int video_init_images (zbar_video_t *vdo) if(vdo->iomode != VIDEO_MMAP) { assert(!vdo->buf); vdo->buflen = vdo->num_images * vdo->datalen; - vdo->buf = malloc(vdo->buflen); + vdo->buf = calloc(1, vdo->buflen); if(!vdo->buf) return(err_capture(vdo, SEV_FATAL, ZBAR_ERR_NOMEM, __func__, "unable to allocate image buffers")); From ab716bf93cfe3d8e1937ee012f9d24b4fcc2f47d Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 13 Jul 2010 09:46:18 -0400 Subject: [PATCH 217/328] fix for poor iPhone 4 performance --- ChangeLog | 1 + iphone/ZBarReaderView.m | 3 +++ 2 files changed, 4 insertions(+) diff --git a/ChangeLog b/ChangeLog index c6f09e3..f61cca7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * fix for poor iPhone 4 performance * add language bindings for DataBar * add preliminary support for GS1 DataBar (RSS-14) symbology * enable torch for iPhone 4 diff --git a/iphone/ZBarReaderView.m b/iphone/ZBarReaderView.m index 1b82e03..18694e5 100644 --- a/iphone/ZBarReaderView.m +++ b/iphone/ZBarReaderView.m @@ -82,6 +82,9 @@ - (id) initWithImageScanner: (ZBarImageScanner*) _scanner captureReader.captureDelegate = (id)self; [session addOutput: captureReader.captureOutput]; + if([session canSetSessionPreset: AVCaptureSessionPreset640x480]) + session.sessionPreset = AVCaptureSessionPreset640x480; + preview = [[AVCaptureVideoPreviewLayer layerWithSession: session] retain]; From 86d7511fed993835d26958bc9dd34579a9c4b590 Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 16 Jul 2010 10:17:54 -0400 Subject: [PATCH 218/328] add iPhone compile option to remove UIGetScreenImage() --- iphone/ZBarReaderController.m | 31 +++++++++++++++++++++++++++ iphone/zbar.xcodeproj/project.pbxproj | 1 + 2 files changed, 32 insertions(+) diff --git a/iphone/ZBarReaderController.m b/iphone/ZBarReaderController.m index bca1b90..9fe0f95 100644 --- a/iphone/ZBarReaderController.m +++ b/iphone/ZBarReaderController.m @@ -25,15 +25,25 @@ #import "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 1 +#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 @@ -62,7 +72,12 @@ - (id) init if([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]) self.sourceType = UIImagePickerControllerSourceTypeCamera; + +#if USE_PRIVATE_APIS cameraMode = ZBarReaderControllerCameraModeSampling; +#else + cameraMode = ZBarReaderControllerCameraModeDefault; +#endif } return(self); } @@ -284,6 +299,17 @@ - (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) @@ -428,6 +454,8 @@ - (void) updateBox: (ZBarSymbol*) sym [CATransaction commit]; } +#if USE_PRIVATE_APIS + - (void) scanScreen { if(!sampling) @@ -479,6 +507,7 @@ - (void) scanScreen - (void) captureScreen { CGImageRef screen = UIGetScreenImage(); + CGRect r = CGRectMake(0, 0, CGImageGetWidth(screen), CGImageGetHeight(screen)); if(r.size.width > r.size.height) @@ -508,6 +537,8 @@ - (void) captureScreen afterDelay: 0.001]; } +#endif /* USE_PRIVATE_APIS */ + - (void) scanSequence: (UIImage*) image { if(!sampling) { diff --git a/iphone/zbar.xcodeproj/project.pbxproj b/iphone/zbar.xcodeproj/project.pbxproj index de3d185..1d25fe5 100644 --- a/iphone/zbar.xcodeproj/project.pbxproj +++ b/iphone/zbar.xcodeproj/project.pbxproj @@ -446,6 +446,7 @@ buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT)"; GCC_C_LANGUAGE_STANDARD = c99; + GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1"; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; OTHER_LDFLAGS = "-ObjC"; From 551517745e3064b267b1fe503ebb19c6fc9eaf95 Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 18 Jul 2010 10:57:48 -0400 Subject: [PATCH 219/328] add support for GS1 DataBar Expanded (RSS Expanded) symbology --- ChangeLog | 1 + doc/ref/zbarcam.xml | 7 +- doc/ref/zbarimg.xml | 7 +- include/zbar.h | 1 + java/net/sourceforge/zbar/Symbol.java | 4 +- perl/ZBar.xs | 2 + python/test/test_zbar.py | 3 +- python/zbarmodule.c | 59 +-- test/iphone/readertest.m | 10 +- test/test_decode.c | 46 +- zbar/config.c | 14 +- zbar/decoder.c | 9 +- zbar/decoder/databar.c | 634 ++++++++++++++++++++++++-- zbar/decoder/databar.h | 3 +- zbar/img_scanner.c | 2 +- zbar/symbol.c | 1 + zbarimg/zbarimg.c | 2 +- 17 files changed, 697 insertions(+), 108 deletions(-) diff --git a/ChangeLog b/ChangeLog index f61cca7..0184abd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * add support for GS1 DataBar Expanded (RSS Expanded) symbology * fix for poor iPhone 4 performance * add language bindings for DataBar * add preliminary support for GS1 DataBar (RSS-14) symbology diff --git a/doc/ref/zbarcam.xml b/doc/ref/zbarcam.xml index cb21b8f..69f5ff2 100644 --- a/doc/ref/zbarcam.xml +++ b/doc/ref/zbarcam.xml @@ -60,9 +60,10 @@ /dev/video0 The underlying library currently supports EAN-13 (including - UPC and ISBN subsets), EAN-8, DataBar, Code 128, Code 39, - Interleaved 2 of 5 and QR Code symbologies. The specific type of - each detected symbol is printed with the decoded data. + UPC and ISBN subsets), EAN-8, DataBar, DataBar Expanded, Code 128, + Code 39, Interleaved 2 of 5 and QR Code symbologies. The specific + type of each detected symbol is printed with the decoded + data. diff --git a/doc/ref/zbarimg.xml b/doc/ref/zbarimg.xml index 86b90e0..d1c664f 100644 --- a/doc/ref/zbarimg.xml +++ b/doc/ref/zbarimg.xml @@ -59,9 +59,10 @@ displayed to the screen. The underlying library currently supports EAN-13 (including - UPC and ISBN subsets), EAN-8, DataBar, Code 128, Code 39, - Interleaved 2 of 5 and QR Code symbologies. The specific type of - each detected symbol is printed with the decoded data. + UPC and ISBN subsets), EAN-8, DataBar, DataBar Expanded, Code 128, + Code 39, Interleaved 2 of 5 and QR Code symbologies. The specific + type of each detected symbol is printed with the decoded + data. Note that "image" diff --git a/include/zbar.h b/include/zbar.h index 9cde3f8..c71327f 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -94,6 +94,7 @@ typedef enum zbar_symbol_type_e { ZBAR_ISBN13 = 14, /**< ISBN-13 (from EAN-13). @since 0.4 */ 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_CODE39 = 39, /**< Code 39. @since 0.4 */ ZBAR_PDF417 = 57, /**< PDF417. @since 0.6 */ ZBAR_QRCODE = 64, /**< QR Code. @since 0.10 */ diff --git a/java/net/sourceforge/zbar/Symbol.java b/java/net/sourceforge/zbar/Symbol.java index 9b239a3..19d349e 100644 --- a/java/net/sourceforge/zbar/Symbol.java +++ b/java/net/sourceforge/zbar/Symbol.java @@ -49,8 +49,10 @@ public class Symbol public static final int ISBN13 = 14; /** Interleaved 2 of 5. */ public static final int I25 = 25; - /** DataBar. */ + /** DataBar (RSS-14). */ public static final int DATABAR = 34; + /** DataBar Expanded. */ + public static final int DATABAR_EXP = 35; /** Code 39. */ public static final int CODE39 = 39; /** PDF417. */ diff --git a/perl/ZBar.xs b/perl/ZBar.xs index e0a792a..6040fe6 100644 --- a/perl/ZBar.xs +++ b/perl/ZBar.xs @@ -316,6 +316,8 @@ BOOT: CONSTANT(symbol_type, , EAN13, zbar_get_symbol_name(ZBAR_EAN13)); CONSTANT(symbol_type, , ISBN13, zbar_get_symbol_name(ZBAR_ISBN13)); CONSTANT(symbol_type, , DATABAR, zbar_get_symbol_name(ZBAR_DATABAR)); + CONSTANT(symbol_type, , DATABAR_EXP, + zbar_get_symbol_name(ZBAR_DATABAR_EXP)); CONSTANT(symbol_type, , I25, zbar_get_symbol_name(ZBAR_I25)); CONSTANT(symbol_type, , CODE39, zbar_get_symbol_name(ZBAR_CODE39)); CONSTANT(symbol_type, , PDF417, zbar_get_symbol_name(ZBAR_PDF417)); diff --git a/python/test/test_zbar.py b/python/test/test_zbar.py index 1c1aa02..bee44fb 100755 --- a/python/test/test_zbar.py +++ b/python/test/test_zbar.py @@ -80,6 +80,7 @@ def test_symbologies(self): zbar.Symbol.EAN13, zbar.Symbol.ISBN13, zbar.Symbol.DATABAR, + zbar.Symbol.DATABAR_EXP, zbar.Symbol.I25, zbar.Symbol.CODE39, zbar.Symbol.PDF417, @@ -208,7 +209,7 @@ def test_databar(self): sym is zbar.Symbol.PARTIAL) self.assert_(sym is zbar.Symbol.DATABAR) - self.assertEqual(self.dcode.data, '24012345678905') + self.assertEqual(self.dcode.data, '0124012345678905') self.assert_(self.dcode.color is zbar.BAR) self.assertEqual(self.dcode.direction, 1) diff --git a/python/zbarmodule.c b/python/zbarmodule.c index f179d23..cebacf9 100644 --- a/python/zbarmodule.c +++ b/python/zbarmodule.c @@ -44,43 +44,44 @@ static char *exc_names[] = { }; static const enumdef symbol_defs[] = { - { "NONE", ZBAR_NONE }, - { "PARTIAL", ZBAR_PARTIAL }, - { "EAN8", ZBAR_EAN8 }, - { "UPCE", ZBAR_UPCE }, - { "ISBN10", ZBAR_ISBN10 }, - { "UPCA", ZBAR_UPCA }, - { "EAN13", ZBAR_EAN13 }, - { "ISBN13", ZBAR_ISBN13 }, - { "DATABAR", ZBAR_DATABAR }, - { "I25", ZBAR_I25 }, - { "CODE39", ZBAR_CODE39 }, - { "PDF417", ZBAR_PDF417 }, - { "QRCODE", ZBAR_QRCODE }, - { "CODE128", ZBAR_CODE128 }, + { "NONE", ZBAR_NONE }, + { "PARTIAL", ZBAR_PARTIAL }, + { "EAN8", ZBAR_EAN8 }, + { "UPCE", ZBAR_UPCE }, + { "ISBN10", ZBAR_ISBN10 }, + { "UPCA", ZBAR_UPCA }, + { "EAN13", ZBAR_EAN13 }, + { "ISBN13", ZBAR_ISBN13 }, + { "DATABAR", ZBAR_DATABAR }, + { "DATABAR_EXP", ZBAR_DATABAR_EXP }, + { "I25", ZBAR_I25 }, + { "CODE39", ZBAR_CODE39 }, + { "PDF417", ZBAR_PDF417 }, + { "QRCODE", ZBAR_QRCODE }, + { "CODE128", ZBAR_CODE128 }, { NULL, } }; static const enumdef config_defs[] = { - { "ENABLE", ZBAR_CFG_ENABLE }, - { "ADD_CHECK", ZBAR_CFG_ADD_CHECK }, - { "EMIT_CHECK", ZBAR_CFG_EMIT_CHECK }, - { "ASCII", ZBAR_CFG_ASCII }, - { "MIN_LEN", ZBAR_CFG_MIN_LEN }, - { "MAX_LEN", ZBAR_CFG_MAX_LEN }, - { "UNCERTAINTY", ZBAR_CFG_UNCERTAINTY }, - { "POSITION", ZBAR_CFG_POSITION }, - { "X_DENSITY", ZBAR_CFG_X_DENSITY }, - { "Y_DENSITY", ZBAR_CFG_Y_DENSITY }, + { "ENABLE", ZBAR_CFG_ENABLE }, + { "ADD_CHECK", ZBAR_CFG_ADD_CHECK }, + { "EMIT_CHECK", ZBAR_CFG_EMIT_CHECK }, + { "ASCII", ZBAR_CFG_ASCII }, + { "MIN_LEN", ZBAR_CFG_MIN_LEN }, + { "MAX_LEN", ZBAR_CFG_MAX_LEN }, + { "UNCERTAINTY", ZBAR_CFG_UNCERTAINTY }, + { "POSITION", ZBAR_CFG_POSITION }, + { "X_DENSITY", ZBAR_CFG_X_DENSITY }, + { "Y_DENSITY", ZBAR_CFG_Y_DENSITY }, { NULL, } }; static const enumdef orient_defs[] = { - { "UNKNOWN", ZBAR_ORIENT_UNKNOWN }, - { "UP", ZBAR_ORIENT_UP }, - { "RIGHT", ZBAR_ORIENT_RIGHT }, - { "DOWN", ZBAR_ORIENT_DOWN }, - { "LEFT", ZBAR_ORIENT_LEFT }, + { "UNKNOWN", ZBAR_ORIENT_UNKNOWN }, + { "UP", ZBAR_ORIENT_UP }, + { "RIGHT", ZBAR_ORIENT_RIGHT }, + { "DOWN", ZBAR_ORIENT_DOWN }, + { "LEFT", ZBAR_ORIENT_LEFT }, { NULL, } }; diff --git a/test/iphone/readertest.m b/test/iphone/readertest.m index 99d6261..256cd93 100644 --- a/test/iphone/readertest.m +++ b/test/iphone/readertest.m @@ -311,15 +311,11 @@ - (void) initControlCells nil]]; static const int symbolValues[] = { - ZBAR_QRCODE, ZBAR_CODE128, ZBAR_CODE39, ZBAR_I25, ZBAR_DATABAR, + ZBAR_QRCODE, ZBAR_CODE128, ZBAR_CODE39, ZBAR_I25, + ZBAR_DATABAR, ZBAR_DATABAR_EXP, ZBAR_EAN13, ZBAR_EAN8, ZBAR_UPCA, ZBAR_UPCE, ZBAR_ISBN13, ZBAR_ISBN10, 0 }; - static NSString* const symbolNames[] = { - @"QRCODE", @"CODE128", @"CODE39", @"I25", @"DataBar", - @"EAN13", @"EAN8", @"UPCA", @"UPCE", @"ISBN13", @"ISBN10", - nil - }; NSMutableArray *symbols = [NSMutableArray array]; [symbolEnables release]; symbolEnables = [[NSMutableArray alloc] init]; @@ -327,7 +323,7 @@ - (void) initControlCells for(int i = 0; symbolValues[i]; i++) { en = en && (symbolValues[i] != ZBAR_UPCA); [symbols addObject: - [self cellWithTitle: symbolNames[i] + [self cellWithTitle: [ZBarSymbol nameForType: symbolValues[i]] tag: symbolValues[i] checked: en]]; [symbolEnables addObject: [NSNumber numberWithBool: en]]; diff --git a/test/test_decode.c b/test/test_decode.c index c62cb9a..a887cc7 100644 --- a/test/test_decode.c +++ b/test/test_decode.c @@ -55,7 +55,8 @@ static void symbol_handler (zbar_decoder_t *decoder) return; const char *data = zbar_decoder_get_data(decoder); - int pass = (sym == expect_sym) && !strcmp(data, expect_data); + int pass = (sym == expect_sym) && !strcmp(data, expect_data) && + zbar_decoder_get_data_length(decoder) == strlen(data); pass *= 3; zprintf(pass, "decode %s:%s\n", zbar_get_symbol_name(sym), data); @@ -747,7 +748,7 @@ static void encode_ean8 (char *data) int test_databar_F_1 () { - expect(ZBAR_DATABAR, "24012345678905"); + expect(ZBAR_DATABAR, "0124012345678905"); assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); encode(0x11, 0); encode(0x31111333, 0); @@ -761,14 +762,26 @@ int test_databar_F_1 () return(0); } -int test_orange () +int test_databar_F_3 () { - char data[32] = "000845963000052"; - expect(ZBAR_DATABAR, data + 1); - encode_databar(data, FWD); + expect(ZBAR_DATABAR_EXP, "1012A"); + assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); + encode(0x11, 0); + encode(0x11521151, 0); + encode(0x18411, 0); + encode(0x13171121, 0); + encode(0x11521232, 0); + encode(0x11481, 0); + encode(0x23171111, 0); + encode(0x1, 0); encode_junk(rnd_size); + return(0); +} - expect(ZBAR_DATABAR, data + 1); +int test_orange () +{ + char data[32] = "0100845963000052"; + expect(ZBAR_DATABAR, data); assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); encode(0x1, 0); encode(0x23212321, 0); // data[0] @@ -780,20 +793,24 @@ int test_orange () encode(0x11, 0); encode_junk(rnd_size); + expect(ZBAR_DATABAR, data); + data[1] = '0'; + encode_databar(data + 1, FWD); + encode_junk(rnd_size); return(0); } int test_numeric (char *data) { - char tmp = data[0]; - data[0] &= '1'; - calc_ean_parity(data + 1, 13); - expect(ZBAR_DATABAR, data + 1); - encode_databar(data, (rand() >> 8) & 1); + char tmp[32] = "01"; + strncpy(tmp + 2, data + 1, 13); + calc_ean_parity(tmp + 2, 13); + expect(ZBAR_DATABAR, tmp); - encode_junk(rnd_size); + tmp[1] = data[0] & '1'; + encode_databar(tmp + 1, (rand() >> 8) & 1); - data[0] = tmp; + encode_junk(rnd_size); data[strlen(data) & ~1] = 0; expect(ZBAR_CODE128, data); @@ -948,6 +965,7 @@ int main (int argc, char **argv) if(!iter) { test_databar_F_1(); + test_databar_F_3(); test_orange(); test1(); } diff --git a/zbar/config.c b/zbar/config.c index 115c3a3..fa80c52 100644 --- a/zbar/config.c +++ b/zbar/config.c @@ -31,9 +31,9 @@ #include int zbar_parse_config (const char *cfgstr, - zbar_symbol_type_t *sym, - zbar_config_t *cfg, - int *val) + zbar_symbol_type_t *sym, + zbar_config_t *cfg, + int *val) { const char *dot, *eq; int len; @@ -50,6 +50,8 @@ int zbar_parse_config (const char *cfgstr, return(1); else if(!strncmp(cfgstr, "qrcode", len)) *sym = ZBAR_QRCODE; + else if(!strncmp(cfgstr, "db", len)) + *sym = ZBAR_DATABAR; else if(len < 3) return(1); else if(!strncmp(cfgstr, "upca", len)) @@ -70,6 +72,8 @@ int zbar_parse_config (const char *cfgstr, *sym = ZBAR_ISBN13; else if(!strncmp(cfgstr, "isbn10", len)) *sym = ZBAR_ISBN10; + else if(!strncmp(cfgstr, "db-exp", len)) + *sym = ZBAR_DATABAR_EXP; #if 0 /* FIXME addons are configured per-main symbol type */ else if(!strncmp(cfgstr, "addon2", len)) @@ -89,6 +93,8 @@ int zbar_parse_config (const char *cfgstr, *sym = ZBAR_CODE128; else if(!strncmp(cfgstr, "databar", len)) *sym = ZBAR_DATABAR; + else if(!strncmp(cfgstr, "databar-exp", len)) + *sym = ZBAR_DATABAR_EXP; else return(1); cfgstr = dot + 1; @@ -136,6 +142,8 @@ int zbar_parse_config (const char *cfgstr, *cfg = ZBAR_CFG_ADD_CHECK; else if(!strncmp(cfgstr, "emit-check", len)) *cfg = ZBAR_CFG_EMIT_CHECK; + else if(!strncmp(cfgstr, "uncertainty", len)) + *cfg = ZBAR_CFG_UNCERTAINTY; else if(!strncmp(cfgstr, "position", len)) *cfg = ZBAR_CFG_POSITION; else diff --git a/zbar/decoder.c b/zbar/decoder.c index 2581ea0..aa04797 100644 --- a/zbar/decoder.c +++ b/zbar/decoder.c @@ -62,6 +62,8 @@ zbar_decoder_t *zbar_decoder_create () #ifdef ENABLE_DATABAR dcode->databar.config = ((1 << ZBAR_CFG_ENABLE) | (1 << ZBAR_CFG_EMIT_CHECK)); + dcode->databar.config_exp = ((1 << ZBAR_CFG_ENABLE) | + (1 << ZBAR_CFG_EMIT_CHECK)); dcode->databar.csegs = 4; dcode->databar.segs = calloc(4, sizeof(*dcode->databar.segs)); #endif @@ -225,7 +227,8 @@ zbar_symbol_type_t zbar_decode_width (zbar_decoder_t *dcode, sym = tmp; #endif #ifdef ENABLE_DATABAR - if(TEST_CFG(dcode->databar.config, ZBAR_CFG_ENABLE) && + if(TEST_CFG(dcode->databar.config | dcode->databar.config_exp, + ZBAR_CFG_ENABLE) && (tmp = _zbar_decode_databar(dcode)) > ZBAR_PARTIAL) sym = tmp; #endif @@ -294,6 +297,9 @@ static inline int decoder_set_config_bool (zbar_decoder_t *dcode, case ZBAR_DATABAR: config = &dcode->databar.config; break; + case ZBAR_DATABAR_EXP: + config = &dcode->databar.config_exp; + break; #endif #ifdef ENABLE_CODE39 @@ -396,6 +402,7 @@ int zbar_decoder_set_config (zbar_decoder_t *dcode, zbar_decoder_set_config(dcode, ZBAR_ISBN13, cfg, val); zbar_decoder_set_config(dcode, ZBAR_I25, cfg, val); zbar_decoder_set_config(dcode, ZBAR_DATABAR, cfg, val); + zbar_decoder_set_config(dcode, ZBAR_DATABAR_EXP, cfg, val); zbar_decoder_set_config(dcode, ZBAR_CODE39, cfg, val); zbar_decoder_set_config(dcode, ZBAR_CODE128, cfg, val); zbar_decoder_set_config(dcode, ZBAR_PDF417, cfg, val); diff --git a/zbar/decoder/databar.c b/zbar/decoder/databar.c index 5f2e47d..eb46af4 100644 --- a/zbar/decoder/databar.c +++ b/zbar/decoder/databar.c @@ -30,6 +30,10 @@ #include "debug.h" #include "decoder.h" +#define GS ('\035') + +enum { SCH_NUM, SCH_ALNUM, SCH_ISO646 }; + static const signed char finder_hash[0x20] = { 0x16, 0x1f, 0x02, 0x00, 0x03, 0x00, 0x06, 0x0b, 0x1f, 0x0e, 0x17, 0x0c, 0x0b, 0x14, 0x11, 0x0c, @@ -65,6 +69,362 @@ struct group_s { { 0, 2, 4, 84 }, }; +static const unsigned char exp_sequences[] = { + /* sequence Group 1 */ + 0x01, + 0x23, + 0x25, 0x07, + 0x29, 0x47, + 0x29, 0x67, 0x0b, + 0x29, 0x87, 0xab, + /* sequence Group 2 */ + 0x21, 0x43, 0x65, 0x07, + 0x21, 0x43, 0x65, 0x89, + 0x21, 0x43, 0x65, 0xa9, 0x0b, + 0x21, 0x43, 0x67, 0x89, 0xab +}; + +/* DataBar expanded checksum multipliers */ +static const unsigned char exp_checksums[] = { + 1, 189, 62, 113, 46, 43, 109, 134, 6, 79, 161, 45 +}; + +static inline void +append_check14 (unsigned char *buf) +{ + unsigned char chk = 0, d; + int i; + for(i = 13; --i >= 0; ) { + d = *(buf++) - '0'; + chk += d; + if(!(i & 1)) + chk += d << 1; + } + chk %= 10; + if(chk) + chk = 10 - chk; + *buf = chk + '0'; +} + +static inline void +decode10 (unsigned char *buf, + unsigned long n, + int i) +{ + buf += i; + while(--i >= 0) { + unsigned char d = n % 10; + n /= 10; + *--buf = '0' + d; + } +} + +#define FEED_BITS(b) \ + while(i < (b) && len) { \ + d = (d << 12) | (*(data++) & 0xfff); \ + i += 12; \ + len--; \ + dprintf(2, " %03lx", d & 0xfff); \ + } + +#define PUSH_CHAR(c) \ + *(buf++) = (c) + +#define PUSH_CHAR4(c0, c1, c2, c3) do { \ + PUSH_CHAR(c0); \ + PUSH_CHAR(c1); \ + PUSH_CHAR(c2); \ + PUSH_CHAR(c3); \ + } while(0); + +static inline int +databar_postprocess_exp (zbar_decoder_t *dcode, + int *data) +{ + int i = 0, enc; + unsigned n; + unsigned char *buf; + unsigned long d = *(data++); + int len = d / 211 + 4; + + /* grok encodation method */ + d = *(data++); + dprintf(2, "\n len=%d %03lx", len, d & 0xfff); + n = (d >> 4) & 0x7f; + if(n >= 0x40) { + i = 10; + enc = 1; + } + else if(n >= 0x38) { + i = 4; + enc = 6 + (n & 7); + } + else if(n >= 0x30) { + i = 6; + enc = 2 + ((n >> 2) & 1); + } + else if(n >= 0x20) { + i = 7; + enc = 4 + ((n >> 3) & 1); + } + else { + i = 9; + enc = 0; + } + dprintf(2, " enc=%d", enc); + + if(enc < 4) { + /* grok variable length symbol bit field */ + if((len ^ (d >> (--i))) & 1) + /* even/odd length mismatch */ + return(-1); + if((d >> (--i)) & 1 != (len > 14)) + /* size group mismatch */ + return(-1); + } + len -= 2; + dprintf(2, " [%d+%d]", i, len); + + if(size_buf(dcode, ((i + len * 12) * 2 + 6) / 7 + 8)) + return(-1); + buf = dcode->buf; + + /* handle compressed fields */ + if(enc) { + PUSH_CHAR('0'); + PUSH_CHAR('1'); + } + + if(enc == 1) { + i -= 4; + n = (d >> i) & 0xf; + if(i >= 10) + return(-1); + PUSH_CHAR('0' + n); + } + else if(enc) + PUSH_CHAR('9'); + + if(enc) { + int j; + for(j = 0; j < 4; j++) { + FEED_BITS(10); + i -= 10; + n = (d >> i) & 0x3ff; + if(n >= 1000) + return(-1); + decode10(buf, n, 3); + buf += 3; + } + append_check14(buf - 13); + buf++; + } + + switch(enc) + { + case 2: /* 01100: AI 392x */ + FEED_BITS(2); + i -= 2; + n = (d >> i) & 0x3; + PUSH_CHAR4('3', '9', '2', '0' + n); + break; + + case 3: /* 01101: AI 393x */ + FEED_BITS(12); + i -= 2; + n = (d >> i) & 0x3; + PUSH_CHAR4('3', '9', '3', '0' + n); + i -= 10; + n = (d >> i) & 0x3ff; + if(n >= 1000) + return(-1); + decode10(buf, n, 3); + buf += 3; + break; + + case 4: /* 0100: AI 3103 */ + FEED_BITS(15); + i -= 15; + n = (d >> i) & 0x7fff; + PUSH_CHAR4('3', '1', '0', '3'); + decode10(buf, n, 6); + buf += 6; + break; + + case 5: /* 0101: AI 3202/3203 */ + FEED_BITS(15); + i -= 15; + n = (d >> i) & 0x7fff; + dprintf(2, " v=%d", n); + PUSH_CHAR4('3', '2', '0', (n >= 10000) ? '3' : '2' ); + if(n >= 10000) + n -= 10000; + decode10(buf, n, 6); + buf += 6; + break; + } + if(enc >= 6) { + /* 0111000 - 0111111: AI 310x/320x + AI 11/13/15/17 */ + PUSH_CHAR4('3', '1' + (enc & 1), '0', 'x'); + FEED_BITS(20); + i -= 20; + n = (d >> i) & 0xfffff; + dprintf(2, " [%d+%d] %d", i, len, n); + if(n >= 1000000) + return(-1); + decode10(buf, n, 6); + *(buf - 1) = *buf; + *buf = '0'; + buf += 6; + + FEED_BITS(16); + i -= 16; + n = (d >> i) & 0xffff; + if(n < 38400) { + int dd, mm, yy; + dd = n % 32; + n /= 32; + mm = n % 12 + 1; + n /= 12; + yy = n; + PUSH_CHAR('1'); + PUSH_CHAR('0' + (enc - 6) | 1); + decode10(buf, yy, 2); + buf += 2; + decode10(buf, mm, 2); + buf += 2; + decode10(buf, dd, 2); + buf += 2; + } + else if(n > 38400) + return(-1); + } + + if(enc < 4) { + /* remainder is general-purpose data compaction */ + int scheme = SCH_NUM; + while(i > 0 || len > 0) { + FEED_BITS(8); + dprintf(2, " [%d+%d]", i, len); + + if(scheme == SCH_NUM) { + int n1; + i -= 4; + if(i < 0) + break; + if(!((d >> i) & 0xf)) { + scheme = SCH_ALNUM; + dprintf(2, ">A"); + continue; + } + if(!len && i < 3) { + /* special case last digit */ + n = ((d >> i) & 0xf) - 1; + if(n > 9) + return(-1); + *(buf++) = '0' + n; + break; + } + i -= 3; + zassert(i >= 0, -1, "\n"); + n = ((d >> i) & 0x7f) - 8; + n1 = n % 11; + n = n / 11; + dprintf(2, "N%d%d", n, n1); + *(buf++) = (n < 10) ? '0' + n : GS; + *(buf++) = (n1 < 10) ? '0' + n1 : GS; + } + else { + unsigned c = 0; + i -= 3; + if(i < 0) + break; + if(!((d >> i) & 0x7)) { + scheme = SCH_NUM; + continue; + } + i -= 2; + if(i < 0) + break; + n = (d >> i) & 0x1f; + if(n == 0x04) { + scheme ^= 0x3; + dprintf(2, ">%d", scheme); + } + else if(n == 0x0f) + c = GS; + else if(n < 0x0f) + c = 43 + n; + else if(scheme == SCH_ALNUM) { + i--; + if(i < 0) + return(-1); + n = (d >> i) & 0x1f; + if(n < 0x1a) + c = 'A' + n; + else if(n == 0x1a) + c = '*'; + else if(n < 0x1f) + c = ',' + n - 0x1b; + else + return(-1); + } + else if(scheme == SCH_ISO646 && n < 0x1d) { + i -= 2; + if(i < 0) + return(-1); + n = (d >> i) & 0x3f; + if(n < 0x1a) + c = 'A' + n; + else if(n < 0x34) + c = 'a' + n - 0x1a; + else + return(-1); + } + else if(scheme == SCH_ISO646) { + i -= 3; + if(i < 0) + return(-1); + n = ((d >> i) & 0x1f); + dprintf(2, "(%02x)", n); + if(n < 0xa) + c = '!' + n - 8; + else if(n < 0x15) + c = '%' + n - 0xa; + else if(n < 0x1b) + c = ':' + n - 0x15; + else if(n == 0x1b) + c = '_'; + else if(n == 0x1c) + c = ' '; + else + return(-1); + } + else + return(-1); + + if(c) { + dprintf(2, "%d%c", scheme, c); + *(buf++) = c; + } + } + } + /* FIXME check pad? */ + } + + *buf = 0; + i = buf - dcode->buf; + dcode->buflen = i; + if(i && *--buf == GS) { + *buf = 0; + dcode->buflen--; + } + + dprintf(2, "\n %s", _zbar_decoder_buf_dump(dcode->buf, dcode->buflen)); + return(0); +} +#undef FEED_BITS + /* convert from heterogeneous base {1597,2841} * to base 10 character representation */ @@ -75,7 +435,10 @@ databar_postprocess (zbar_decoder_t *dcode, databar_decoder_t *db = &dcode->databar; int i; unsigned c, chk = 0; - unsigned char *buf = dcode->buf + 15; + unsigned char *buf = dcode->buf; + *(buf++) = '0'; + *(buf++) = '1'; + buf += 15; *--buf = '\0'; *--buf = '\0'; @@ -100,7 +463,7 @@ databar_postprocess (zbar_decoder_t *dcode, r /= 10; } - dprintf(2, "\n d={%d,%d,%d}", d[1], d[2], d[3]); + dprintf(2, " d={%d,%d,%d}", d[1], d[2], d[3]); r = d[1] * 2841 + d[2]; d[2] = r / 10000; r %= 10000; @@ -119,7 +482,7 @@ databar_postprocess (zbar_decoder_t *dcode, } r = d[2] * 1597 + d[3]; - dprintf(2, "\n d={%d,%d} r=%ld", d[2], d[3], r); + dprintf(2, " d={%d,%d} r=%ld", d[2], d[3], r); for(i = 5; --i >= 0; ) { c = r % 10; @@ -136,11 +499,11 @@ databar_postprocess (zbar_decoder_t *dcode, chk %= 10; if(chk) chk = 10 - chk; - dcode->buf[13] = chk + '0'; - dcode->buflen = 14; + buf[13] = chk + '0'; + dcode->buflen = buf - dcode->buf + 14; } else - dcode->buflen = 13; + dcode->buflen = buf - dcode->buf + 13; dprintf(2, "\n %s", _zbar_decoder_buf_dump(dcode->buf, 16)); } @@ -164,7 +527,7 @@ merge_segment (databar_decoder_t *db, int i; for(i = 0; i < csegs; i++) { databar_segment_t *s = db->segs + i; - if(s != seg && s->finder == seg->finder && s->ext == seg->ext && + if(s != seg && s->finder == seg->finder && s->exp == seg->exp && s->color == seg->color && s->side == seg->side && s->data == seg->data && s->check == seg->check && check_width(seg->width, s->width, 14)) { @@ -176,7 +539,8 @@ merge_segment (databar_decoder_t *db, seg->partial &= s->partial; seg->width = (3 * seg->width + s->width + 2) / 4; s->finder = -1; - dprintf(2, " dup@%d", i); + dprintf(2, " dup@%d(%d,%d)", + i, cnt, (db->epoch - seg->epoch) & 0xff); } else if(s->finder >= 0) { unsigned age = (db->epoch - s->epoch) & 0xff; @@ -200,7 +564,7 @@ match_segment (zbar_decoder_t *dcode, for(i0 = 0; i0 < csegs; i0++) { databar_segment_t *s0 = db->segs + i0; - if(s0 == seg || s0->finder != seg->finder || s0->ext || + if(s0 == seg || s0->finder != seg->finder || s0->exp || s0->color != seg->color || s0->side == seg->side || (s0->partial && s0->count < 4) || !check_width(seg->width, s0->width, 14)) @@ -210,14 +574,14 @@ match_segment (zbar_decoder_t *dcode, databar_segment_t *s1 = db->segs + i1; int chkf, chks, chk; unsigned age1; - if(i1 == i0 || s1->finder < 0 || s1->ext || + if(i1 == i0 || s1->finder < 0 || s1->exp || s1->color == seg->color || (s1->partial && s1->count < 4) || !check_width(seg->width, s1->width, 14)) continue; dprintf(2, "\n\t[%d,%d] f=%d(0%xx)/%d(%x%x%x)", i0, i1, seg->finder, seg->color, - s1->finder, s1->ext, s1->color, s1->side); + s1->finder, s1->exp, s1->color, s1->side); if(seg->color) chkf = seg->finder + s1->finder * 9; @@ -242,7 +606,7 @@ match_segment (zbar_decoder_t *dcode, for(i2 = i1 + 1; i2 < csegs; i2++) { databar_segment_t *s2 = db->segs + i2; unsigned cnt, age2, age; - if(i2 == i0 || s2->finder != s1->finder || s2->ext || + if(i2 == i0 || s2->finder != s1->finder || s2->exp || s2->color != s1->color || s2->side == s1->side || s2->check != chk || (s2->partial && s2->count < 4) || @@ -276,6 +640,9 @@ match_segment (zbar_decoder_t *dcode, } seg->finder = -1; + if(size_buf(dcode, 18)) + return(ZBAR_PARTIAL); + if(acquire_lock(dcode, ZBAR_DATABAR)) return(ZBAR_PARTIAL); @@ -284,14 +651,173 @@ match_segment (zbar_decoder_t *dcode, return(ZBAR_DATABAR); } +static inline unsigned +lookup_sequence (databar_segment_t *seg, + int fixed, + int seq[22]) +{ + unsigned n = seg->data / 211, i; + const unsigned char *p; + i = (n + 1) / 2 + 1; + n += 4; + i = (i * i) / 4; + dprintf(2, " {%d,%d:", i, n); + p = exp_sequences + i; + + fixed >>= 1; + seq[0] = 0; + seq[1] = 1; + for(i = 2; i < n; ) { + int s = *p; + if(!(i & 2)) { + p++; + s >>= 4; + } + else + s &= 0xf; + if(s == fixed) + fixed = -1; + s <<= 1; + dprintf(2, "%x", s); + seq[i++] = s++; + seq[i++] = s; + } + dprintf(2, "}"); + seq[n] = -1; + return(fixed < 1); +} + +#define IDX(s) \ + (((s)->finder << 2) | ((s)->color << 1) | ((s)->color ^ (s)->side)) + static inline zbar_symbol_type_t -match_segment_ext (zbar_decoder_t *dcode, - databar_segment_t *seg) +match_segment_exp (zbar_decoder_t *dcode, + databar_segment_t *seg, + int dir) { - /* FIXME TBD */ - seg->finder = -1; - return(ZBAR_NONE); + databar_decoder_t *db = &dcode->databar; + int bestsegs[22], i = 0, segs[22], seq[22]; + int ifixed = seg - db->segs, fixed = IDX(seg), maxcnt = 0; + int iseg[DATABAR_MAX_SEGMENTS]; + unsigned csegs = db->csegs, width = seg->width, maxage = 0x7fff; + + bestsegs[0] = segs[0] = seq[1] = -1; + seq[0] = 0; + + dprintf(2, "\n fixed=%d@%d: ", fixed, ifixed); + for(i = csegs, seg = db->segs + csegs - 1; --i >= 0; seg--) { + if(seg->exp && seg->finder >= 0 && + (!seg->partial || seg->count >= 4)) + iseg[i] = IDX(seg); + else + iseg[i] = -1; + dprintf(2, " %d", iseg[i]); + } + + for(i = 0; ; i--) { + if(!i) + dprintf(2, "\n "); + for(; i >= 0 && seq[i] >= 0; i--) { + int j; + dprintf(2, " [%d]%d", i, seq[i]); + + if(seq[i] == fixed) { + seg = db->segs + ifixed; + if(segs[i] < 0 && check_width(width, seg->width, 14)) { + dprintf(2, "*"); + j = ifixed; + } + else + continue; + } + else { + for(j = segs[i] + 1; j < csegs; j++) { + if(iseg[j] == seq[i] && + (!i || check_width(width, db->segs[j].width, 14))) { + seg = db->segs + j; + break; + } + } + if(j == csegs) + continue; + } + + if(!i) { + if(!lookup_sequence(seg, fixed, seq)) { + dprintf(2, "[nf]"); + continue; + } + width = seg->width; + dprintf(2, " A00@%d", j); + } + else { + width = (width + seg->width) / 2; + dprintf(2, " %c%x%x@%d", + 'A' + seg->finder, seg->color, seg->side, j); + } + segs[i++] = j; + segs[i++] = -1; + } + if(i < 0) + break; + + seg = db->segs + segs[0]; + unsigned cnt = 0, chk = 0, age = (db->epoch - seg->epoch) & 0xff; + for(i = 1; segs[i] >= 0; i++) { + seg = db->segs + segs[i]; + chk += seg->check; + cnt += seg->count; + age += (db->epoch - seg->epoch) & 0xff; + } + + unsigned data0 = db->segs[segs[0]].data; + unsigned chk0 = data0 % 211; + chk %= 211; + + dprintf(2, " chk=%d ?= %d", chk, chk0); + if(chk != chk0) + continue; + + dprintf(2, " cnt=%d age=%d", cnt, age); + if(maxcnt > cnt || (maxcnt == cnt && maxage <= age)) + continue; + + dprintf(2, " !"); + maxcnt = cnt; + maxage = age; + for(i = 0; segs[i] >= 0; i++) + bestsegs[i] = segs[i]; + bestsegs[i] = -1; + } + + if(bestsegs[0] < 0) + return(ZBAR_PARTIAL); + + if(acquire_lock(dcode, ZBAR_DATABAR_EXP)) + return(ZBAR_PARTIAL); + + for(i = 0; bestsegs[i] >= 0; i++) + segs[i] = db->segs[bestsegs[i]].data; + + if(databar_postprocess_exp(dcode, segs)) { + release_lock(dcode, ZBAR_DATABAR_EXP); + return(ZBAR_PARTIAL); + } + + for(i = 0; bestsegs[i] >= 0; i++) + if(bestsegs[i] != ifixed) { + seg = db->segs + bestsegs[i]; + if(!--seg->count) + seg->finder = -1; + } + + /* FIXME stacked rows are frequently reversed, + * so direction is impossible to determine at this level + */ + dcode->direction = (1 - 2 * (seg->side ^ seg->color)) * dir; + return(ZBAR_DATABAR_EXP); } +#undef IDX static inline unsigned calc_check (unsigned sig0, @@ -414,7 +940,7 @@ decode_char (zbar_decoder_t *dcode, int n, i, emin[2] = { 0, }, sum = 0; unsigned sig0 = 0, sig1 = 0; - if(seg->ext) + if(seg->exp) n = 17; else if(seg->side) n = 15; @@ -422,8 +948,8 @@ decode_char (zbar_decoder_t *dcode, n = 16; emin[1] = -n; - dprintf(2, " char: d=%d off=%d n=%d s=%d w=%d sig=", - dir, off, n, s, seg->width); + dprintf(2, "\n char[%c%d]: n=%d s=%d w=%d sig=", + (dir < 0) ? '>' : '<', off, n, s, seg->width); if(s < 13 || !check_width(seg->width, s, n)) return(ZBAR_NONE); @@ -505,14 +1031,26 @@ decode_char (zbar_decoder_t *dcode, else v += veven + vodd * g->teven; - dprintf(2, " f=%d(%x%x%x)", seg->finder, seg->ext, seg->color, seg->side); + dprintf(2, " f=%d(%x%x%x)", seg->finder, seg->exp, seg->color, seg->side); unsigned chk = 0; - if(seg->ext) { - /* FIXME skip A1 */ - chk = calc_check(sig0, sig1, seg->side, 211); - if(seg->color) - chk = (chk * 189) % 211; + if(seg->exp) { + unsigned side = seg->color ^ seg->side ^ 1; + if(v >= 4096) + return(ZBAR_NONE); + /* skip A1 left */ + chk = calc_check(sig0, sig1, side, 211); + if(seg->finder || seg->color || seg->side) { + i = (seg->finder << 1) - side + seg->color; + zassert(i >= 0 && i < 12, ZBAR_NONE, + "f=%d(%x%x%x) side=%d i=%d\n", + seg->finder, seg->exp, seg->color, seg->side, side, i); + chk = (chk * exp_checksums[i]) % 211; + } + else if(v >= 4009) + return(ZBAR_NONE); + else + chk = 0; } else { chk = calc_check(sig0, sig1, seg->side, 79); @@ -521,12 +1059,15 @@ decode_char (zbar_decoder_t *dcode, } dprintf(2, " => %d val=%d", chk, v); - seg->epoch = db->epoch++; seg->check = chk; seg->data = v; merge_segment(db, seg); + if(seg->exp) + return(match_segment_exp(dcode, seg, dir)); + else if(dir > 0) + return(match_segment(dcode, seg)); return(ZBAR_PARTIAL); } @@ -576,7 +1117,7 @@ alloc_segment (databar_decoder_t *db) seg = db->segs + csegs; while(--seg, --csegs >= i) { seg->finder = -1; - seg->ext = 0; + seg->exp = 0; seg->color = 0; seg->side = 0; seg->partial = 0; @@ -632,32 +1173,39 @@ decode_finder (zbar_decoder_t *dcode) ((sig >> 4) & 0xf) < 8 || ((sig >> 4) & 0xf) > 10 || (sig & 0xf) >= 10 || - ((sig >> 8) & 0xf) >= 10) + ((sig >> 8) & 0xf) >= 10 || + (((sig >> 8) + sig) & 0xf) != 10) return(ZBAR_NONE); finder = (finder_hash[(sig - (sig >> 5)) & 0x1f] + finder_hash[(sig >> 1) & 0x1f]) & 0x1f; dprintf(2, " finder=%d", finder); - if(finder == 0x1f) + if(finder == 0x1f || + !TEST_CFG((finder < 9) ? db->config : db->config_exp, ZBAR_CFG_ENABLE)) return(ZBAR_NONE); + zassert(finder >= 0, ZBAR_NONE, "dir=%d sig=%04x f=%d\n", + dir, sig & 0xfff, finder); + iseg = alloc_segment(db); if(iseg < 0) return(ZBAR_NONE); - dprintf(2, " i=%d\n", iseg); seg = db->segs + iseg; seg->finder = (finder >= 9) ? finder - 9 : finder; - seg->ext = (finder >= 9); + seg->exp = (finder >= 9); seg->color = get_color(dcode) ^ dir ^ 1; seg->side = dir; seg->partial = 0; seg->count = 1; seg->width = s; + seg->epoch = db->epoch; int rc = decode_char(dcode, seg, 12 - dir, -1); if(!rc) seg->partial = 1; + else + db->epoch++; int i = (dcode->idx + 8 + dir) & 0xf; zassert(db->chars[i] == -1, ZBAR_NONE, "\n"); @@ -672,6 +1220,7 @@ _zbar_decode_databar (zbar_decoder_t *dcode) databar_segment_t *seg, *pair; zbar_symbol_type_t sym; int iseg, i = dcode->idx & 0xf; + sym = decode_finder(dcode); dprintf(2, "\n"); @@ -681,7 +1230,10 @@ _zbar_decode_databar (zbar_decoder_t *dcode) db->chars[i] = -1; seg = db->segs + iseg; - dprintf(2, " databar: i=%d part=%d", iseg, seg->partial); + dprintf(2, " databar: i=%d part=%d f=%d(%x%x%x)", + iseg, seg->partial, seg->finder, seg->exp, seg->color, seg->side); + zassert(seg->finder >= 0, ZBAR_NONE, "i=%d f=%d(%x%x%x) part=%x\n", + iseg, seg->finder, seg->exp, seg->color, seg->side, seg->partial); if(seg->partial) { pair = NULL; @@ -692,28 +1244,24 @@ _zbar_decode_databar (zbar_decoder_t *dcode) pair = db->segs + iseg; seg = db->segs + jseg; seg->finder = pair->finder; - seg->ext = pair->ext; + seg->exp = pair->exp; seg->color = pair->color; seg->side = !pair->side; seg->partial = 0; seg->count = 1; seg->width = pair->width; + seg->epoch = db->epoch; } - dprintf(2, "\n"); sym = decode_char(dcode, seg, 1, 1); - if(sym) { - if(seg->ext) - sym = match_segment_ext(dcode, seg); - else - sym = match_segment(dcode, seg); - } - else { + if(!sym) { seg->finder = -1; if(pair) pair->partial = 1; } - + else + db->epoch++; dprintf(2, "\n"); + return(sym); } diff --git a/zbar/decoder/databar.h b/zbar/decoder/databar.h index 5c98fd3..693cf2e 100644 --- a/zbar/decoder/databar.h +++ b/zbar/decoder/databar.h @@ -28,7 +28,7 @@ /* active DataBar (partial) segment entry */ typedef struct databar_segment_s { signed finder : 5; /* finder pattern */ - unsigned ext : 1; /* DataBar extended finder */ + unsigned exp : 1; /* DataBar expanded finder */ unsigned color : 1; /* finder coloring */ unsigned side : 1; /* data character side of finder */ @@ -43,6 +43,7 @@ typedef struct databar_segment_s { /* DataBar specific decode state */ typedef struct databar_decoder_s { unsigned config; /* decoder configuration flags */ + unsigned config_exp; unsigned csegs : 8; /* allocated segments */ unsigned epoch : 8; /* current scan */ diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index c271710..d5456d6 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -799,7 +799,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, zbar_symbol_t **symp = &syms->head, *sym; while((sym = *symp)) { if(((sym->type < ZBAR_I25 && sym->type > ZBAR_PARTIAL) || - sym->type == ZBAR_DATABAR) && + sym->type == ZBAR_DATABAR || sym->type == ZBAR_DATABAR_EXP) && sym->quality < 4) { /* recycle */ *symp = sym->next; diff --git a/zbar/symbol.c b/zbar/symbol.c index 86971d9..4f8bf93 100644 --- a/zbar/symbol.c +++ b/zbar/symbol.c @@ -40,6 +40,7 @@ const char *zbar_get_symbol_name (zbar_symbol_type_t sym) case ZBAR_ISBN13: return("ISBN-13"); case ZBAR_I25: return("I2/5"); case ZBAR_DATABAR: return("DataBar"); + case ZBAR_DATABAR_EXP: return("DataBar-Exp"); case ZBAR_CODE39: return("CODE-39"); case ZBAR_CODE128: return("CODE-128"); case ZBAR_PDF417: return("PDF417"); diff --git a/zbarimg/zbarimg.c b/zbarimg/zbarimg.c index 751fe37..26cbfef 100644 --- a/zbarimg/zbarimg.c +++ b/zbarimg/zbarimg.c @@ -77,7 +77,7 @@ static const char *warning_not_found = " - is the barcode type supported?" " currently supported symbologies are:\n" " EAN/UPC (EAN-13, EAN-8, UPC-A, UPC-E, ISBN-10, ISBN-13),\n" - " Code 128, Code 39, DataBar and Interleaved 2 of 5\n" + " Code 128, Code 39, DataBar, DataBar Expanded, and Interleaved 2 of 5\n" " - is the barcode large enough in the image?\n" " - is the barcode mostly in focus?\n" " - is there sufficient contrast/illumination?\n" From 4093322e1f10f906de3fa3db3b7d14f471915e92 Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 18 Jul 2010 20:54:45 -0400 Subject: [PATCH 220/328] fix DataBar Expanded buffer overrun --- zbar/decoder/databar.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/zbar/decoder/databar.c b/zbar/decoder/databar.c index eb46af4..61510b5 100644 --- a/zbar/decoder/databar.c +++ b/zbar/decoder/databar.c @@ -119,6 +119,8 @@ decode10 (unsigned char *buf, } } +#define VAR_MAX(l, i) ((((l) * 12 + (i)) * 2 + 6) / 7) + #define FEED_BITS(b) \ while(i < (b) && len) { \ d = (d << 12) | (*(data++) & 0xfff); \ @@ -145,7 +147,7 @@ databar_postprocess_exp (zbar_decoder_t *dcode, unsigned n; unsigned char *buf; unsigned long d = *(data++); - int len = d / 211 + 4; + int len = d / 211 + 4, buflen; /* grok encodation method */ d = *(data++); @@ -154,24 +156,30 @@ databar_postprocess_exp (zbar_decoder_t *dcode, if(n >= 0x40) { i = 10; enc = 1; + buflen = 2 + 14 + VAR_MAX(len, 10 - 2 - 44 + 6) + 2; } else if(n >= 0x38) { i = 4; enc = 6 + (n & 7); + buflen = 2 + 14 + 4 + 6 + 2 + 6 + 2; } else if(n >= 0x30) { i = 6; enc = 2 + ((n >> 2) & 1); + buflen = 2 + 14 + 4 + 3 + VAR_MAX(len, 6 - 2 - 44 - 2 - 10) + 2; } else if(n >= 0x20) { i = 7; enc = 4 + ((n >> 3) & 1); + buflen = 2 + 14 + 4 + 6; } else { i = 9; enc = 0; + buflen = VAR_MAX(len, 9 - 2) + 2; } - dprintf(2, " enc=%d", enc); + dprintf(2, " buflen=%d enc=%d", buflen, enc); + zassert(buflen > 2, -1, "buflen=%d\n", buflen); if(enc < 4) { /* grok variable length symbol bit field */ @@ -185,7 +193,7 @@ databar_postprocess_exp (zbar_decoder_t *dcode, len -= 2; dprintf(2, " [%d+%d]", i, len); - if(size_buf(dcode, ((i + len * 12) * 2 + 6) / 7 + 8)) + if(size_buf(dcode, buflen)) return(-1); buf = dcode->buf; From d7ad65dfc2b5a422b637243e9e2244d0dbaf1b8e Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 25 Jul 2010 17:02:00 -0400 Subject: [PATCH 221/328] workaround for iPhone simulator builds - refactor ZBarReaderView for capture/simulator specific implementations - fix tracking calculations - fix captured video frame color conversion --- ChangeLog | 4 + include/zbar/ZBarCaptureReader.h | 1 + include/zbar/ZBarReaderView.h | 13 +- iphone/ZBarCVImage.m | 2 +- iphone/ZBarCaptureReader.m | 39 ++- iphone/ZBarImage.m | 8 +- iphone/ZBarReaderController.m | 7 +- iphone/ZBarReaderView.m | 381 +++++++------------------- iphone/ZBarReaderViewController.m | 13 +- iphone/ZBarReaderViewImpl_Capture.m | 336 +++++++++++++++++++++++ iphone/ZBarReaderViewImpl_Simulator.m | 189 +++++++++++++ iphone/ZBarSymbol.m | 4 + iphone/zbar.xcodeproj/project.pbxproj | 20 ++ test/iphone/readertest.m | 94 +++++-- 14 files changed, 774 insertions(+), 337 deletions(-) create mode 100644 iphone/ZBarReaderViewImpl_Capture.m create mode 100644 iphone/ZBarReaderViewImpl_Simulator.m diff --git a/ChangeLog b/ChangeLog index 0184abd..9c3767d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,8 @@ current: + * workaround for iPhone simulator builds + - refactor ZBarReaderView for capture/simulator specific implementations + - fix tracking calculations + - fix captured video frame color conversion * add support for GS1 DataBar Expanded (RSS Expanded) symbology * fix for poor iPhone 4 performance * add language bindings for DataBar diff --git a/include/zbar/ZBarCaptureReader.h b/include/zbar/ZBarCaptureReader.h index 5aada67..1d28243 100644 --- a/include/zbar/ZBarCaptureReader.h +++ b/include/zbar/ZBarCaptureReader.h @@ -49,6 +49,7 @@ id captureDelegate; ZBarImageScanner *scanner; CGRect scanCrop; + CGSize size; CGFloat framesPerSecond; BOOL enableCache; diff --git a/include/zbar/ZBarReaderView.h b/include/zbar/ZBarReaderView.h index e763e12..0365724 100644 --- a/include/zbar/ZBarReaderView.h +++ b/include/zbar/ZBarReaderView.h @@ -24,8 +24,7 @@ #import #import -@class AVCaptureSession, AVCaptureDevice, AVCaptureInput; -@class AVCaptureVideoPreviewLayer; +@class AVCaptureSession, AVCaptureDevice; @class CALayer; @class ZBarReaderView, ZBarCaptureReader; @@ -47,21 +46,17 @@ : UIView { id readerDelegate; - AVCaptureSession *session; - AVCaptureDevice *device; - CGRect scanCrop; + CGRect scanCrop, zoomCrop; CGAffineTransform previewTransform; CGFloat zoom, zoom0; BOOL tracksSymbols, showsFPS; NSInteger torchMode; - AVCaptureInput *input; - ZBarCaptureReader *captureReader; - AVCaptureVideoPreviewLayer *preview; - CALayer *tracking; + CALayer *preview, *overlay, *tracking; UIView *fpsView; UILabel *fpsLabel; UIPinchGestureRecognizer *pinch; + CGFloat imageScale; BOOL started, running; } diff --git a/iphone/ZBarCVImage.m b/iphone/ZBarCVImage.m index 4c90913..86c1a75 100644 --- a/iphone/ZBarCVImage.m +++ b/iphone/ZBarCVImage.m @@ -163,7 +163,7 @@ - (void) convertCVtoRGB Y1 *= 4769; quv += (x & 1) << 1; int r = (Y1 + 6537 * Cr + 2048) / 4096; - int g = (Y1 + 1604 * Cb + 3329 * 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); diff --git a/iphone/ZBarCaptureReader.m b/iphone/ZBarCaptureReader.m index 09a6355..7a42e99 100644 --- a/iphone/ZBarCaptureReader.m +++ b/iphone/ZBarCaptureReader.m @@ -31,9 +31,8 @@ @implementation ZBarCaptureReader -@synthesize captureOutput, captureDelegate, scanner, scanCrop, framesPerSecond, - enableCache; -@dynamic size; +@synthesize captureOutput, captureDelegate, scanner, scanCrop, size, + framesPerSecond, enableCache; - (void) initResult { @@ -142,13 +141,6 @@ - (void) setCaptureDelegate: (id) delegate } } -- (CGSize) size -{ - @synchronized(scanner) { - return(CGSizeMake(width, height)); - } -} - - (void) cropUpdate { @synchronized(scanner) { @@ -191,11 +183,23 @@ - (void) setFramesPerSecond: (CGFloat) fps framesPerSecond = fps; } -- (void) setFPS: (NSNumber*) val +- (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 @@ -219,7 +223,7 @@ - (void) captureOutput: (AVCaptureOutput*) output dt_frame = dt; dt_frame = (dt_frame + dt) / 2; if(timer_elapsed(t_fps, now) >= 1) { - [self performSelectorOnMainThread: @selector(setFPS:) + [self performSelectorOnMainThread: @selector(updateFPS:) withObject: [NSNumber numberWithDouble: 1 / dt_frame] waitUntilDone: NO]; t_fps = now; @@ -264,7 +268,16 @@ - (void) captureOutput: (AVCaptureOutput*) output if(width != w || height != h) { width = w; height = h; - image.size = CGSizeMake(w, 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]; } diff --git a/iphone/ZBarImage.m b/iphone/ZBarImage.m index c32080c..cf7f20f 100644 --- a/iphone/ZBarImage.m +++ b/iphone/ZBarImage.m @@ -85,8 +85,10 @@ - (id) initWithCGImage: (CGImageRef) image unsigned long datalen = w * h; uint8_t *raw = malloc(datalen); - // FIXME handle OOM - assert(raw); + 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')); @@ -254,6 +256,8 @@ case zbar_fourcc('R','G','B','Q'): bpp = 16; break; default: + NSLog(@"ERROR: format %.4s(%08x) is unsupported", + (char*)&format, format); assert(0); return(nil); }; diff --git a/iphone/ZBarReaderController.m b/iphone/ZBarReaderController.m index 9fe0f95..4c9d3af 100644 --- a/iphone/ZBarReaderController.m +++ b/iphone/ZBarReaderController.m @@ -598,7 +598,12 @@ - (void) showHelpWithReason: (NSString*) reason scanner.enableCache = NO; help.wantsFullScreenLayout = YES; help.view.alpha = 0; - [[self cameraOverlayView] addSubview: help.view]; + + 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; diff --git a/iphone/ZBarReaderView.m b/iphone/ZBarReaderView.m index 18694e5..5cb22ee 100644 --- a/iphone/ZBarReaderView.m +++ b/iphone/ZBarReaderView.m @@ -22,84 +22,47 @@ //------------------------------------------------------------------------ #import -#import #define MODULE ZBarReaderView #import "debug.h" +// silence warning +@interface ZBarReaderViewImpl : NSObject +@end + @implementation ZBarReaderView @synthesize readerDelegate, tracksSymbols, torchMode, showsFPS, zoom, scanCrop, - previewTransform, session, captureReader; -@dynamic scanner, allowsPinchZoom, enableCache, device; + previewTransform; +@dynamic scanner, allowsPinchZoom, enableCache, device, session, captureReader; -- (id) initWithImageScanner: (ZBarImageScanner*) _scanner ++ (id) alloc { - self = [super initWithFrame: CGRectMake(0, 0, 320, 426)]; - if(!self) - return(nil); - - self.backgroundColor = [UIColor blackColor]; - self.contentMode = UIViewContentModeScaleAspectFill; - self.autoresizingMask = - UIViewAutoresizingFlexibleWidth | - UIViewAutoresizingFlexibleHeight; - - tracksSymbols = YES; - torchMode = AVCaptureTorchModeAuto; - scanCrop = CGRectMake(0, 0, 1, 1); - previewTransform = CGAffineTransformIdentity; + if(self == [ZBarReaderView class]) { + // this is an abstract wrapper for implementation selected + // at compile time. replace with concrete subclass. + return([ZBarReaderViewImpl alloc]); + } + return([super alloc]); +} - 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)self; - [session addOutput: captureReader.captureOutput]; - - if([session canSetSessionPreset: AVCaptureSessionPreset640x480]) - session.sessionPreset = AVCaptureSessionPreset640x480; - - preview = [[AVCaptureVideoPreviewLayer - layerWithSession: session] - retain]; - preview.frame = self.bounds; - preview.videoGravity = AVLayerVideoGravityResizeAspectFill; - [self.layer addSublayer: preview]; +- (void) initSubviews +{ + assert(preview); CGRect r = preview.bounds; + overlay = [CALayer new]; + overlay.frame = r; + overlay.backgroundColor = [UIColor clearColor].CGColor; + [preview addSublayer: overlay]; + tracking = [CALayer new]; tracking.frame = r; tracking.opacity = 0; tracking.borderWidth = 1; tracking.backgroundColor = [UIColor clearColor].CGColor; tracking.borderColor = [UIColor greenColor].CGColor; - [preview addSublayer: tracking]; + [overlay addSublayer: tracking]; r.origin.x = 3 * r.size.width / 4; r.origin.y = r.size.height - 32; @@ -125,6 +88,25 @@ - (id) initWithImageScanner: (ZBarImageScanner*) _scanner fpsLabel.font = [UIFont systemFontOfSize: 18]; fpsLabel.textAlignment = UITextAlignmentRight; [fpsView addSubview: fpsLabel]; +} + +- (id) initWithImageScanner: (ZBarImageScanner*) scanner +{ + self = [super initWithFrame: CGRectMake(0, 0, 320, 426)]; + if(!self) + return(nil); + + self.backgroundColor = [UIColor blackColor]; + self.contentMode = UIViewContentModeScaleAspectFill; + self.autoresizingMask = + UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight; + + tracksSymbols = YES; + torchMode = 2; // AVCaptureTorchModeAuto + scanCrop = zoomCrop = CGRectMake(0, 0, 1, 1); + imageScale = 1; + previewTransform = CGAffineTransformIdentity; pinch = [[UIPinchGestureRecognizer alloc] initWithTarget: self @@ -132,7 +114,6 @@ - (id) initWithImageScanner: (ZBarImageScanner*) _scanner [self addGestureRecognizer: pinch]; self.zoom = 1.25; - return(self); } @@ -156,52 +137,50 @@ - (id) init - (void) dealloc { - [[NSNotificationCenter defaultCenter] - removeObserver: self]; - if(showsFPS) { - @try { - [captureReader removeObserver: self - forKeyPath: @"framesPerSecond"]; - } - @catch(...) { } - } - [fpsLabel release]; - fpsLabel = nil; - [fpsView release]; - fpsView = nil; - captureReader.captureDelegate = nil; - [captureReader release]; - captureReader = nil; - [device release]; - device = nil; - [input release]; - input = nil; [preview removeFromSuperlayer]; [preview release]; preview = nil; - [session release]; - session = nil; + [overlay release]; + overlay = nil; [tracking release]; tracking = nil; + [fpsLabel release]; + fpsLabel = nil; + [fpsView release]; + fpsView = nil; [pinch release]; pinch = nil; [super dealloc]; } -- (ZBarImageScanner*) scanner +- (void) resetTracking { - return(captureReader.scanner); + [tracking removeAllAnimations]; + [CATransaction begin]; + [CATransaction setDisableActions: YES]; + CGSize size = overlay.bounds.size; + CGRect crop = zoomCrop; + tracking.frame = CGRectMake(crop.origin.x * size.width, + crop.origin.y * size.width, + crop.size.width * size.width, + crop.size.height * size.height); + tracking.opacity = 0; + [CATransaction commit]; } -- (void) resetTracking +- (void) setImageSize: (CGSize) size { - tracking.opacity = 0; - CGSize size = preview.bounds.size; - CGRect crop = captureReader.scanCrop; - tracking.frame = CGRectMake(crop.origin.y * size.width, - crop.origin.x * size.height, - crop.size.height * size.width, - crop.size.width * size.height); + CGSize psize = preview.bounds.size; + CGFloat scalex = size.width / psize.width; + CGFloat scaley = size.height / psize.height; + imageScale = (scalex > scaley) ? scalex : scaley; + + tracking.borderWidth = imageScale / zoom; + + zlog(@"scaling: layer=%@ image=%@ scale=%g %c %g = 1/%g", + NSStringFromCGSize(psize), NSStringFromCGSize(size), + scalex, (scalex > scaley) ? '>' : '<', scaley, 1 / imageScale); + [self resetTracking]; } - (void) cropUpdate @@ -211,7 +190,7 @@ - (void) cropUpdate CGFloat z = 1 / zoom; xfrm = CGAffineTransformScale(xfrm, z, z); xfrm = CGAffineTransformTranslate(xfrm, -.5, -.5); - captureReader.scanCrop = CGRectApplyAffineTransform(scanCrop, xfrm); + zoomCrop = CGRectApplyAffineTransform(scanCrop, xfrm); [self resetTracking]; } @@ -223,40 +202,6 @@ - (void) setScanCrop: (CGRect) r [self cropUpdate]; } -- (AVCaptureDevice*) device -{ - return(device); -} - -- (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: input]; - if(input) - [session addInput: input]; - [session commitConfiguration]; - - [olddev release]; - [oldinput release]; -} - - (void) setTracksSymbols: (BOOL) track { if(track == tracksSymbols) @@ -265,16 +210,6 @@ - (void) setTracksSymbols: (BOOL) track [self resetTracking]; } -- (BOOL) enableCache -{ - return(captureReader.enableCache); -} - -- (void) setEnableCache: (BOOL) enable -{ - captureReader.enableCache = enable; -} - - (BOOL) allowsPinchZoom { return(pinch.enabled); @@ -285,32 +220,11 @@ - (void) setAllowsPinchZoom: (BOOL) enabled pinch.enabled = enabled; } -- (void) setTorchMode: (NSInteger) mode -{ - torchMode = mode; - if(running && [device isTorchModeSupported: mode]) - @try { - device.torchMode = mode; - } - @catch(...) { } -} - - (void) setShowsFPS: (BOOL) show { if(show == showsFPS) return; fpsView.hidden = !show; - @try { - if(show) - [captureReader addObserver: self - forKeyPath: @"framesPerSecond" - options: 0 - context: NULL]; - else - [captureReader removeObserver: self - forKeyPath: @"framesPerSecond"]; - } - @catch(...) { } } - (void) setZoom: (CGFloat) z @@ -330,6 +244,7 @@ - (void) setZoom: (CGFloat) z kCAMediaTimingFunctionLinear]]; [preview setAffineTransform: CGAffineTransformScale(previewTransform, z, z)]; + tracking.borderWidth = imageScale / zoom; [CATransaction commit]; [self cropUpdate]; @@ -348,78 +263,25 @@ - (void) start return; started = YES; - [[UIDevice currentDevice] - beginGeneratingDeviceOrientationNotifications]; - [self resetTracking]; - fpsLabel.text = @""; + fpsLabel.text = @"--- fps "; - [captureReader willStartRunning]; - [session startRunning]; + [[UIDevice currentDevice] + beginGeneratingDeviceOrientationNotifications]; } - (void) stop { if(!started) return; - - [captureReader willStopRunning]; - [session stopRunning]; + started = NO; [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications]; - started = NO; } - (void) flushCache { - [captureReader flushCache]; -} - -// AVCaptureSession notifications - -- (void) onVideoStart: (NSNotification*) note -{ - zlog(@"onVideoStart: running=%d %@", running, note); - if(running) - return; - running = YES; - - // lock device and set focus mode - NSError *error = nil; - if([device lockForConfiguration: &error]) { - if([device isFocusModeSupported: AVCaptureFocusModeContinuousAutoFocus]) - device.focusMode = AVCaptureFocusModeContinuousAutoFocus; - if([device isTorchModeSupported: torchMode]) - device.torchMode = torchMode; - } - else - zlog(@"failed to lock device: %@", error); -} - -- (void) onVideoStop: (NSNotification*) note -{ - zlog(@"onVideoStop: %@", note); - if(!running) - return; - - [device unlockForConfiguration]; - running = NO; -} - -- (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]; - NSLog(@"ZBarReaderView: ERROR during capture: %@: %@", - [err localizedDescription], - [err localizedFailureReason]); } // UIGestureRecognizer callback @@ -433,7 +295,7 @@ - (void) handlePinch if((zoom < 1.5) != (z < 1.5)) { int d = (z < 1.5) ? 3 : 2; - ZBarImageScanner *scanner = captureReader.scanner; + ZBarImageScanner *scanner = self.scanner; @synchronized(scanner) { [scanner setSymbology: 0 config: ZBAR_CFG_X_DENSITY @@ -445,44 +307,21 @@ - (void) handlePinch } } -// NSKeyValueObserving - -- (void) observeValueForKeyPath: (NSString*) path - ofObject: (id) obj - change: (NSDictionary*) info - context: (void*) ctx -{ - if(obj == captureReader && - [path isEqualToString: @"framesPerSecond"]) - fpsLabel.text = [NSString stringWithFormat: @"%.2ffps ", - captureReader.framesPerSecond]; -} - -// ZBarCaptureDelegate - - (void) updateTracking: (CALayer*) trk withSymbol: (ZBarSymbol*) sym { if(!sym) return; - CGRect b = sym.bounds; - CGPoint c = CGPointMake(CGRectGetMidX(b), CGRectGetMidY(b)); - CGSize isize = captureReader.size; - CGSize psize = preview.bounds.size; - CGPoint p = CGPointMake((isize.height - c.y) * psize.width / isize.height, - c.x * psize.height / isize.width); - CGRect r = CGRectMake(0, 0, - b.size.height * psize.width / isize.height, - b.size.width * psize.height / isize.width); - if(r.size.width <= 24 && r.size.height <= 24) + CGRect r = sym.bounds; + if(r.size.width <= 32 && r.size.height <= 32) return; - r = CGRectInset(r, -16, -16); + r = CGRectInset(r, -24, -24); CALayer *current = trk.presentationLayer; CGPoint cp = current.position; - p = CGPointMake((p.x * 3 + cp.x) / 4, - (p.y * 3 + cp.y) / 4); + 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; @@ -519,23 +358,26 @@ - (void) updateTracking: (CALayer*) trk on.fillMode = kCAFillModeForwards; on.removedOnCompletion = NO; - CABasicAnimation *off = - [CABasicAnimation animationWithKeyPath: @"opacity"]; - off.fromValue = [NSNumber numberWithDouble: 1]; - off.toValue = [NSNumber numberWithDouble: 0]; - off.beginTime = .5; - off.duration = .5; - off.timingFunction = linear; + 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) captureReader: (ZBarCaptureReader*) reader - didTrackSymbols: (ZBarSymbolSet*) syms +- (void) didTrackSymbols: (ZBarSymbolSet*) syms { if(!tracksSymbols) return; @@ -557,35 +399,4 @@ - (void) captureReader: (ZBarCaptureReader*) reader withSymbol: sym]; } -- (void) captureReader: (ZBarCaptureReader*) reader - didReadNewSymbolsFromImage: (ZBarImage*) zimg -{ - zlog(@"scanned %d symbols: %@", zimg.symbols.count, zimg); - if(!readerDelegate) - return; - - UIImageOrientation orient; - switch([UIDevice currentDevice].orientation) - { - 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 diff --git a/iphone/ZBarReaderViewController.m b/iphone/ZBarReaderViewController.m index 9c19bc0..b29b3c9 100644 --- a/iphone/ZBarReaderViewController.m +++ b/iphone/ZBarReaderViewController.m @@ -39,13 +39,16 @@ + (BOOL) isSourceTypeAvailable: (UIImagePickerControllerSourceType) sourceType { if(sourceType != UIImagePickerControllerSourceTypeCamera) return(NO); - return([UIImagePickerController isSourceTypeAvailable: sourceType]); + return(TARGET_IPHONE_SIMULATOR || + [UIImagePickerController isSourceTypeAvailable: sourceType]); } - (id) init { - if(!NSClassFromString(@"AVCaptureSession")) { + if(!TARGET_IPHONE_SIMULATOR && + !NSClassFromString(@"AVCaptureSession")) { // fallback to old interface + zlog(@"Falling back to ZBarReaderController"); [self release]; return([ZBarReaderController new]); } @@ -145,6 +148,11 @@ - (void) initControls [self.view addSubview: controls]; } +- (void) initSimulator +{ + // simulator specific hooks +} + - (void) loadView { self.view = [[UIView alloc] @@ -167,6 +175,7 @@ - (void) viewDidLoad [view addSubview: readerView]; [self initControls]; + [self initSimulator]; if(cameraOverlayView) { assert(!cameraOverlayView.superview); diff --git a/iphone/ZBarReaderViewImpl_Capture.m b/iphone/ZBarReaderViewImpl_Capture.m new file mode 100644 index 0000000..e3f5c93 --- /dev/null +++ b/iphone/ZBarReaderViewImpl_Capture.m @@ -0,0 +1,336 @@ +#import +#import + +#define MODULE ZBarReaderView +#import "debug.h" + +// protected APIs +@interface ZBarReaderView() +- (void) initSubviews; +- (void) cropUpdate; +- (void) setImageSize: (CGSize) size; +- (void) didTrackSymbols: (ZBarSymbolSet*) syms; +@end + +@interface ZBarReaderViewImpl + : ZBarReaderView +{ + AVCaptureSession *session; + AVCaptureDevice *device; + AVCaptureInput *input; + ZBarCaptureReader *captureReader; +} + +@end + +@implementation ZBarReaderViewImpl + +@synthesize device, session, captureReader; + +- (id) initWithImageScanner: (ZBarImageScanner*) scanner +{ + self = [super initWithImageScanner: scanner]; + if(!self) + return(nil); + + 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)self; + [session addOutput: captureReader.captureOutput]; + + if([session canSetSessionPreset: AVCaptureSessionPreset640x480]) + session.sessionPreset = AVCaptureSessionPreset640x480; + + [captureReader addObserver: self + forKeyPath: @"size" + options: 0 + context: NULL]; + + [self initSubviews]; + return(self); +} + +- (void) initSubviews +{ + AVCaptureVideoPreviewLayer *videoPreview = + [[AVCaptureVideoPreviewLayer + layerWithSession: session] + retain]; + videoPreview.videoGravity = AVLayerVideoGravityResizeAspectFill; + preview = videoPreview; + preview.frame = self.bounds; + [self.layer addSublayer: preview]; + + [super initSubviews]; + + // camera image is rotated + overlay.transform = CATransform3DMakeRotation(M_PI / 2, 0, 0, 1); +} + +- (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) cropUpdate +{ + [super cropUpdate]; + captureReader.scanCrop = zoomCrop; +} + +- (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: input]; + 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]; + + [captureReader willStartRunning]; + [session startRunning]; +} + +- (void) stop +{ + if(!started) + return; + [super stop]; + + [captureReader willStopRunning]; + [session stopRunning]; +} + +- (void) flushCache +{ + [captureReader flushCache]; +} + +// AVCaptureSession notifications + +- (void) onVideoStart: (NSNotification*) note +{ + zlog(@"onVideoStart: running=%d %@", running, note); + if(running) + return; + running = YES; + + // lock device and set focus mode + NSError *error = nil; + if([device lockForConfiguration: &error]) { + if([device isFocusModeSupported: AVCaptureFocusModeContinuousAutoFocus]) + device.focusMode = AVCaptureFocusModeContinuousAutoFocus; + if([device isTorchModeSupported: torchMode]) + device.torchMode = torchMode; + } + else + zlog(@"failed to lock device: %@", error); +} + +- (void) onVideoStop: (NSNotification*) note +{ + zlog(@"onVideoStop: %@", note); + if(!running) + return; + + [device unlockForConfiguration]; + running = NO; +} + +- (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]; + 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 tracking overlay to match image size + CGSize size = captureReader.size; + overlay.bounds = CGRectMake(0, 0, size.width, size.height); + + CGSize rsize = CGSizeMake(size.height, size.width); + [self setImageSize: rsize]; + CGFloat scale = 1 / imageScale; + CATransform3D xform = CATransform3DMakeRotation(M_PI / 2, 0, 0, 1); + overlay.transform = CATransform3DScale(xform, scale, scale, 1); + } + 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; + switch([UIDevice currentDevice].orientation) + { + 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 diff --git a/iphone/ZBarReaderViewImpl_Simulator.m b/iphone/ZBarReaderViewImpl_Simulator.m new file mode 100644 index 0000000..bd1bf34 --- /dev/null +++ b/iphone/ZBarReaderViewImpl_Simulator.m @@ -0,0 +1,189 @@ +#import +#import + +#define MODULE ZBarReaderView +#import "debug.h" + +// hack around missing simulator support for AVCapture interfaces + +@interface ZBarReaderViewController(Simulator) +@end + +@implementation ZBarReaderViewController(Simulator) + +- (void) initSimulator +{ + UILongPressGestureRecognizer *press = + [[UILongPressGestureRecognizer alloc] + initWithTarget: self + action: @selector(takePicture)]; + [self.view addGestureRecognizer: press]; + press.numberOfTouchesRequired = 2; + [press release]; +} + +- (void) takePicture +{ + UIImagePickerController *picker = + [UIImagePickerController new]; + picker.delegate = (id)self; + [self presentModalViewController: picker + animated: YES]; + [picker release]; +} + +- (void) imagePickerController: (UIImagePickerController*) picker + didFinishPickingMediaWithInfo: (NSDictionary*) info +{ + UIImage *image = [info objectForKey: UIImagePickerControllerOriginalImage]; + [picker dismissModalViewControllerAnimated: YES]; + [readerView performSelector: @selector(scanImage:) + withObject: image + afterDelay: .1]; +} + +- (void) imagePickerControllerDidCancel: (UIImagePickerController*) picker +{ + [picker dismissModalViewControllerAnimated: YES]; +} + +@end + +// protected APIs +@interface ZBarReaderView() +- (void) initSubviews; +- (void) setImageSize: (CGSize) size; +- (void) didTrackSymbols: (ZBarSymbolSet*) syms; +@end + +@interface ZBarReaderViewImpl + : ZBarReaderView +{ + ZBarImageScanner *scanner; + UIImage *scanImage; + BOOL enableCache; +} +@end + +@implementation ZBarReaderViewImpl + +@synthesize scanner, enableCache; + +- (id) initWithImageScanner: (ZBarImageScanner*) _scanner +{ + self = [super initWithImageScanner: _scanner]; + if(!self) + return(nil); + + scanner = [_scanner retain]; + + [self initSubviews]; + return(self); +} + +- (void) initSubviews +{ + UILabel *label = + [[UILabel alloc] + initWithFrame: CGRectMake(16, 165, 288, 96)]; + label.backgroundColor = [UIColor clearColor]; + label.textColor = [UIColor whiteColor]; + label.font = [UIFont boldSystemFontOfSize: 20]; + label.numberOfLines = 4; + label.textAlignment = UITextAlignmentCenter; + label.text = @"Camera Simulation\n\n" + @"Tap and hold with two \"fingers\" to select image"; + [self addSubview: label]; + [label release]; + + preview = [CALayer new]; + preview.frame = self.bounds; + [self.layer addSublayer: preview]; + + [super initSubviews]; +} + +- (void) dealloc +{ + [scanner release]; + scanner = nil; + [super dealloc]; +} + +- (void) start +{ + if(started) + return; + [super start]; + running = YES; +} + +- (void) stop +{ + if(!started) + return; + [super stop]; + running = NO; +} + +- (void) scanImage: (UIImage*) image +{ + // strip EXIF info + CGImageRef cgimage = image.CGImage; + image = [[UIImage alloc] + initWithCGImage: cgimage + scale: 1.0 + orientation: UIImageOrientationUp]; + + CGSize size = image.size; + overlay.bounds = CGRectMake(0, 0, size.width, size.height); + [self setImageSize: size]; + + preview.contentsScale = imageScale; + preview.contentsGravity = kCAGravityCenter; + preview.contents = (id)cgimage; + + // match overlay to image + CGFloat scale = 1 / imageScale; + overlay.transform = CATransform3DMakeScale(scale, scale, 1); + + ZBarImage *zimg = + [[ZBarImage alloc] + initWithCGImage: cgimage]; + + size = zimg.size; + zimg.crop = CGRectMake(zoomCrop.origin.y * size.width, + zoomCrop.origin.x * size.height, + zoomCrop.size.height * size.width, + zoomCrop.size.width * 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; +} + +@end diff --git a/iphone/ZBarSymbol.m b/iphone/ZBarSymbol.m index e7e7a1f..5dba311 100644 --- a/iphone/ZBarSymbol.m +++ b/iphone/ZBarSymbol.m @@ -123,6 +123,10 @@ @implementation ZBarSymbolSet - (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); diff --git a/iphone/zbar.xcodeproj/project.pbxproj b/iphone/zbar.xcodeproj/project.pbxproj index 1d25fe5..5bd4660 100644 --- a/iphone/zbar.xcodeproj/project.pbxproj +++ b/iphone/zbar.xcodeproj/project.pbxproj @@ -12,6 +12,8 @@ DC26004F118631E000FA987B /* ZBarCaptureReader.h in Headers */ = {isa = PBXBuildFile; fileRef = DC26004D118631E000FA987B /* ZBarCaptureReader.h */; }; DC3AAB4E11B71A040021C7B1 /* ZBarCVImage.h in Headers */ = {isa = PBXBuildFile; fileRef = DC3AAB4C11B71A040021C7B1 /* ZBarCVImage.h */; }; DC3AAB4F11B71A040021C7B1 /* ZBarCVImage.m in Sources */ = {isa = PBXBuildFile; fileRef = DC3AAB4D11B71A040021C7B1 /* ZBarCVImage.m */; }; + DC3CE47811FA1622008FAF88 /* ZBarReaderViewImpl_Capture.m in Sources */ = {isa = PBXBuildFile; fileRef = DC3CE47611FA1622008FAF88 /* ZBarReaderViewImpl_Capture.m */; }; + DC3CE47911FA1622008FAF88 /* ZBarReaderViewImpl_Simulator.m in Sources */ = {isa = PBXBuildFile; fileRef = DC3CE47711FA1622008FAF88 /* ZBarReaderViewImpl_Simulator.m */; }; DC3EBB2D119DDB2100107EE9 /* ZBarReaderViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DC3EBB2C119DDB2100107EE9 /* ZBarReaderViewController.m */; }; DC4920EE10A70475000E4D43 /* ZBarImage.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4920EC10A70475000E4D43 /* ZBarImage.m */; }; DC4920EF10A70475000E4D43 /* ZBarImageScanner.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4920ED10A70475000E4D43 /* ZBarImageScanner.m */; }; @@ -80,6 +82,8 @@ DC26004D118631E000FA987B /* ZBarCaptureReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ZBarCaptureReader.h; path = ../include/zbar/ZBarCaptureReader.h; sourceTree = SOURCE_ROOT; }; DC3AAB4C11B71A040021C7B1 /* ZBarCVImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarCVImage.h; sourceTree = ""; }; DC3AAB4D11B71A040021C7B1 /* ZBarCVImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarCVImage.m; sourceTree = ""; }; + DC3CE47611FA1622008FAF88 /* ZBarReaderViewImpl_Capture.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarReaderViewImpl_Capture.m; sourceTree = ""; }; + DC3CE47711FA1622008FAF88 /* ZBarReaderViewImpl_Simulator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarReaderViewImpl_Simulator.m; sourceTree = ""; }; DC3EBB2C119DDB2100107EE9 /* ZBarReaderViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarReaderViewController.m; sourceTree = ""; }; DC4920EC10A70475000E4D43 /* ZBarImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarImage.m; sourceTree = ""; }; DC4920ED10A70475000E4D43 /* ZBarImageScanner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarImageScanner.m; sourceTree = ""; }; @@ -173,6 +177,8 @@ DC3AAB4D11B71A040021C7B1 /* ZBarCVImage.m */, DC26004B118631C200FA987B /* ZBarCaptureReader.m */, DCDC6E2F11ADCA8E00021380 /* ZBarReaderView.m */, + DC3CE47611FA1622008FAF88 /* ZBarReaderViewImpl_Capture.m */, + DC3CE47711FA1622008FAF88 /* ZBarReaderViewImpl_Simulator.m */, DC67C1BE10A07B6B0033B702 /* ZBarHelpController.m */, DC3EBB2C119DDB2100107EE9 /* ZBarReaderViewController.m */, DC67C1BF10A07B6B0033B702 /* ZBarReaderController.m */, @@ -390,6 +396,8 @@ DCDC6E3011ADCA8E00021380 /* ZBarReaderView.m in Sources */, DC3AAB4F11B71A040021C7B1 /* ZBarCVImage.m in Sources */, DCF5C9AD11EA3AD100E7DC21 /* databar.c in Sources */, + DC3CE47811FA1622008FAF88 /* ZBarReaderViewImpl_Capture.m in Sources */, + DC3CE47911FA1622008FAF88 /* ZBarReaderViewImpl_Simulator.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -428,6 +436,12 @@ isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + EXCLUDED_SOURCE_FILE_NAMES = ""; + "EXCLUDED_SOURCE_FILE_NAMES[sdk=iphoneos*][arch=*]" = ZBarReaderViewImpl_Simulator.m; + "EXCLUDED_SOURCE_FILE_NAMES[sdk=iphonesimulator*][arch=*]" = ( + ZBarReaderViewImpl_Capture.m, + ZBarCaptureReader.m, + ); GCC_C_LANGUAGE_STANDARD = c99; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = "DEBUG_OBJC=1"; @@ -445,6 +459,12 @@ isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + EXCLUDED_SOURCE_FILE_NAMES = ""; + "EXCLUDED_SOURCE_FILE_NAMES[sdk=iphoneos*][arch=*]" = ZBarReaderViewImpl_Simulator.m; + "EXCLUDED_SOURCE_FILE_NAMES[sdk=iphonesimulator*][arch=*]" = ( + ZBarReaderViewImpl_Capture.m, + ZBarCaptureReader.m, + ); GCC_C_LANGUAGE_STANDARD = c99; GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1"; GCC_WARN_ABOUT_RETURN_TYPE = YES; diff --git a/test/iphone/readertest.m b/test/iphone/readertest.m index 256cd93..75d3bb8 100644 --- a/test/iphone/readertest.m +++ b/test/iphone/readertest.m @@ -43,6 +43,7 @@ @interface AppDelegate UINavigationControllerDelegate, UITableViewDelegate, UITableViewDataSource, + UIActionSheetDelegate, ZBarReaderDelegate > { UIWindow *window; @@ -57,6 +58,7 @@ @interface AppDelegate ZBarReaderViewController *reader; UIView *overlay; + UIBarButtonItem *manualBtn; UILabel *typeOvl, *dataOvl; NSArray *masks; } @@ -85,22 +87,22 @@ - (void) initReader: (NSString*) clsName - (void) initOverlay { overlay = [[UIView alloc] - initWithFrame: CGRectMake(0, 0, 320, 480)]; + initWithFrame: CGRectMake(0, 426, 320, 54)]; overlay.backgroundColor = [UIColor clearColor]; masks = [[NSArray alloc] initWithObjects: [[[UIView alloc] - initWithFrame: CGRectMake(0, 0, 320, 0)] + initWithFrame: CGRectMake(0, -426, 320, 0)] autorelease], [[[UIView alloc] - initWithFrame: CGRectMake(0, 0, 0, 426)] + initWithFrame: CGRectMake(0, -426, 0, 426)] autorelease], [[[UIView alloc] - initWithFrame: CGRectMake(0, 426, 320, 0)] + initWithFrame: CGRectMake(0, 0, 320, 0)] autorelease], [[[UIView alloc] - initWithFrame: CGRectMake(320, 0, 0, 426)] + initWithFrame: CGRectMake(320, -426, 0, 426)] autorelease], nil]; for(UIView *mask in masks) { @@ -111,7 +113,7 @@ - (void) initOverlay UILabel *label = [[UILabel alloc] - initWithFrame: CGRectMake(0, 0, 320, 48)]; + initWithFrame: CGRectMake(0, -426, 320, 48)]; label.backgroundColor = [UIColor clearColor]; label.textColor = [UIColor whiteColor]; label.font = [UIFont boldSystemFontOfSize: 24]; @@ -120,7 +122,7 @@ - (void) initOverlay [label release]; typeOvl = [[UILabel alloc] - initWithFrame: CGRectMake(0, 48, 80, 24)]; + initWithFrame: CGRectMake(0, -378, 80, 24)]; typeOvl.backgroundColor = [UIColor clearColor]; typeOvl.textColor = [UIColor whiteColor]; typeOvl.font = [UIFont systemFontOfSize: 16]; @@ -128,7 +130,7 @@ - (void) initOverlay [overlay addSubview: typeOvl]; dataOvl = [[UILabel alloc] - initWithFrame: CGRectMake(96, 48, 224, 24)]; + initWithFrame: CGRectMake(96, -378, 224, 24)]; dataOvl.backgroundColor = [UIColor clearColor]; dataOvl.textColor = [UIColor whiteColor]; dataOvl.font = [UIFont systemFontOfSize: 16]; @@ -136,11 +138,17 @@ - (void) initOverlay UIToolbar *toolbar = [[UIToolbar alloc] - initWithFrame: CGRectMake(0, 426, 320, 54)]; + initWithFrame: CGRectMake(0, 0, 320, 54)]; toolbar.tintColor = [UIColor colorWithRed: .5 green: 0 blue: 0 alpha: 1]; + [manualBtn release]; + manualBtn = [[UIBarButtonItem alloc] + initWithBarButtonSystemItem: UIBarButtonSystemItemCamera + target: self + action: @selector(manualCapture)]; + toolbar.items = [NSArray arrayWithObjects: [[[UIBarButtonItem alloc] @@ -149,6 +157,12 @@ - (void) initOverlay target: self action: @selector(imagePickerControllerDidCancel:)] autorelease], + [[[UIBarButtonItem alloc] + initWithBarButtonSystemItem: UIBarButtonSystemItemFlexibleSpace + target: nil + action: nil] + autorelease], + manualBtn, [[[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemFlexibleSpace target: nil @@ -171,7 +185,7 @@ - (void) initOverlay UIButton *info = [UIButton buttonWithType: UIButtonTypeInfoLight]; - info.frame = CGRectMake(266, 426, 54, 54); + info.frame = CGRectMake(266, 0, 54, 54); [info addTarget: self action: @selector(info) forControlEvents: UIControlEventTouchUpInside]; @@ -265,10 +279,14 @@ - (void) initControlCells }; NSMutableArray *configs = [NSMutableArray array]; for(int i = 0; configNames[i]; i++) - [configs addObject: - [self cellWithTitle: configNames[i] - tag: i - checked: [[reader valueForKey: configNames[i]] boolValue]]]; + @try { + BOOL checked = [[reader valueForKey: configNames[i]] boolValue]; + [configs addObject: + [self cellWithTitle: configNames[i] + tag: i + checked: checked]]; + } + @catch(...) { } [sections replaceObjectAtIndex: CONFIG_SECTION withObject: configs]; @@ -307,7 +325,7 @@ - (void) initControlCells cropCell, [self cellWithTitle: @"continuous" tag: 1 - checked: NO], + checked: continuous], nil]]; static const int symbolValues[] = { @@ -390,6 +408,8 @@ - (void) viewDidUnload sections = nil; [symbolEnables release]; symbolEnables = nil; + [manualBtn release]; + manualBtn = nil; [typeLabel release]; typeLabel = nil; [dataLabel release]; @@ -429,6 +449,10 @@ - (void) scan [self.tableView reloadData]; if([reader respondsToSelector: @selector(readerView)]) reader.readerView.showsFPS = YES; + if(reader.sourceType == UIImagePickerControllerSourceTypeCamera) + reader.cameraOverlayView = (reader.showsZBarControls) ? nil : overlay; + manualBtn.enabled = TARGET_IPHONE_SIMULATOR || + (reader.cameraMode == ZBarReaderControllerCameraModeDefault); [self presentModalViewController: reader animated: YES]; } @@ -444,6 +468,11 @@ - (void) pause [reader.readerView start]; } +- (void) manualCapture +{ + [(UIImagePickerController*)reader takePicture]; +} + // UINavigationControllerDelegate - (void) navigationController: (UINavigationController*) _nav @@ -492,7 +521,7 @@ - (NSString*) tableView: (UITableView*) view - (NSIndexPath*) tableView: (UITableView*) view willSelectRowAtIndexPath: (NSIndexPath*) path { - if(path.section == RESULT_SECTION) + if(path.section == RESULT_SECTION && path.row != 2) return(nil); return(path); } @@ -529,18 +558,18 @@ - (void) advanceCrop: (UILabel*) label r.size.width *= 426; r.size.height *= 320; UIView *mask = [masks objectAtIndex: 0]; - mask.frame = CGRectMake(0, 0, 320, r.origin.x); + mask.frame = CGRectMake(0, -426, 320, r.origin.x); mask = [masks objectAtIndex: 1]; - mask.frame = CGRectMake(0, r.origin.x, r.origin.y, r.size.width); + mask.frame = CGRectMake(0, r.origin.x - 426, r.origin.y, r.size.width); r.origin.y += r.size.height; mask = [masks objectAtIndex: 2]; - mask.frame = CGRectMake(r.origin.y, r.origin.x, + mask.frame = CGRectMake(r.origin.y, r.origin.x - 426, 320 - r.origin.y, r.size.width); r.origin.x += r.size.width; mask = [masks objectAtIndex: 3]; - mask.frame = CGRectMake(0, r.origin.x, 320, 426 - r.origin.x); + mask.frame = CGRectMake(0, r.origin.x - 426, 320, 426 - r.origin.x); } - (void) advanceDensity: (UILabel*) label @@ -611,10 +640,6 @@ - (void) tableView: (UITableView*) view state = [[reader valueForKey: key] boolValue]; [self setCheck: state forCell: cell]; - - if([key isEqualToString: @"showsZBarControls"] && - reader.sourceType == UIImagePickerControllerSourceTypeCamera) - reader.cameraOverlayView = (state) ? nil : overlay; break; } @@ -649,6 +674,15 @@ - (void) tableView: (UITableView*) view break; } case RESULT_SECTION: + if(path.row == 2) + [[[[UIActionSheet alloc] + initWithTitle: nil + delegate: self + cancelButtonTitle: @"Cancel" + destructiveButtonTitle: nil + otherButtonTitles: @"Save Image", nil] + autorelease] + showInView: self.view]; break; default: assert(0); @@ -670,6 +704,18 @@ - (CGFloat) tableView: (UITableView*) view return(44); } +// UIActionSheetDelegate + +- (void) actionSheet: (UIActionSheet*) sheet + clickedButtonAtIndex: (NSInteger) idx +{ + if(idx == sheet.cancelButtonIndex) + return; + idx -= sheet.firstOtherButtonIndex; + if(!idx) + UIImageWriteToSavedPhotosAlbum(imageView.image, nil, NULL, NULL); +} + // ZBarReaderDelegate - (void) imagePickerController: (UIImagePickerController*) picker From 0c6bf0d4ef2c93f32caae1a5e5a8583468e47108 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 29 Jul 2010 11:22:39 -0400 Subject: [PATCH 222/328] add video size request to (Py)GTK widget (req #3034522) - thanks to Jerome Charaoui for the patch! --- ChangeLog | 2 ++ gtk/zbargtk.c | 25 +++++++++++++++++++------ gtk/zbargtkprivate.h | 1 + include/zbar/zbargtk.h | 14 ++++++++++++-- 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0184abd..5296c4e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * 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 * fix for poor iPhone 4 performance * add language bindings for DataBar diff --git a/gtk/zbargtk.c b/gtk/zbargtk.c index a67c6ff..4865014 100644 --- a/gtk/zbargtk.c +++ b/gtk/zbargtk.c @@ -137,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"); @@ -179,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) { @@ -555,6 +555,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, @@ -608,8 +621,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(); diff --git a/gtk/zbargtkprivate.h b/gtk/zbargtkprivate.h index 9cd0525..214a529 100644 --- a/gtk/zbargtkprivate.h +++ b/gtk/zbargtkprivate.h @@ -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. diff --git a/include/zbar/zbargtk.h b/include/zbar/zbargtk.h index 02b3662..ce068f2 100644 --- a/include/zbar/zbargtk.h +++ b/include/zbar/zbargtk.h @@ -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 From e7292deb8089fc6a4a375db00e56f930863c8c5c Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 30 Jul 2010 10:06:20 -0400 Subject: [PATCH 223/328] change default to *not* use private iPhone APIs --- iphone/ZBarReaderController.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iphone/ZBarReaderController.m b/iphone/ZBarReaderController.m index 4c9d3af..b8f7761 100644 --- a/iphone/ZBarReaderController.m +++ b/iphone/ZBarReaderController.m @@ -30,7 +30,7 @@ * and fall back to cameraMode=Default (manual capture) */ #ifndef USE_PRIVATE_APIS -# define USE_PRIVATE_APIS 1 +# define USE_PRIVATE_APIS 0 #endif #ifndef MIN_QUALITY From 031dc21e49ffd3ae44dffba0d602e1f0ab93635a Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 31 Jul 2010 20:34:40 -0400 Subject: [PATCH 224/328] fix example links to upcdatabase.com RPC --- examples/upcrpc.pl | 2 +- examples/upcrpc.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/upcrpc.pl b/examples/upcrpc.pl index adc4595..5b0e10e 100755 --- a/examples/upcrpc.pl +++ b/examples/upcrpc.pl @@ -3,7 +3,7 @@ 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 diff --git a/examples/upcrpc.py b/examples/upcrpc.py index 5d6fbed..2e2a668 100755 --- a/examples/upcrpc.py +++ b/examples/upcrpc.py @@ -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): From b9c2632201a6e7c2e3b30480bc772a764e6aeca7 Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 18 Aug 2010 15:40:22 -0400 Subject: [PATCH 225/328] migrate to binary iPhone SDK distribution (NB backward incompatibilities!) - restructure headers --- .hgignore | 6 +- ChangeLog | 42 - iphone/ChangeLog | 47 ++ iphone/README | 59 ++ iphone/ZBarCVImage.h | 2 +- iphone/ZBarCaptureReader.m | 7 +- iphone/ZBarHelpController.m | 2 +- iphone/ZBarImage.m | 2 +- iphone/ZBarImageScanner.m | 2 +- iphone/ZBarReaderController.m | 2 +- iphone/ZBarReaderView.m | 2 +- iphone/ZBarReaderViewController.m | 4 +- iphone/ZBarReaderViewImpl_Capture.m | 30 +- iphone/ZBarReaderViewImpl_Simulator.m | 27 +- iphone/ZBarSymbol.m | 3 +- iphone/bin/BuildUniversal.sh | 23 + iphone/bin/CreateDMG.sh | 35 + iphone/bin/CreateDSStore.pl | 72 ++ iphone/bin/Mac/Finder/AliasRecord.pm | 169 ++++ iphone/doc/Documentation.html | 11 + iphone/doc/ReaderSample.png | Bin 0 -> 131381 bytes iphone/doc/ZBarImage.rst | 150 ++++ iphone/doc/ZBarImageScanner.rst | 99 +++ iphone/doc/ZBarReaderController.rst | 156 ++++ iphone/doc/ZBarReaderDelegate.rst | 70 ++ iphone/doc/ZBarReaderView.rst | 104 +++ iphone/doc/ZBarReaderViewController.rst | 128 +++ iphone/doc/ZBarReaderViewDelegate.rst | 26 + iphone/doc/ZBarSymbol.rst | 158 ++++ iphone/doc/ZBarSymbolSet.rst | 43 + iphone/doc/apiref.rst | 16 + iphone/doc/camera.rst | 129 +++ iphone/doc/compat.rst | 183 +++++ iphone/doc/conf.py | 77 ++ iphone/doc/custom.rst | 72 ++ iphone/doc/devguide.rst | 13 + iphone/doc/faq.rst | 113 +++ iphone/doc/getstarted.rst | 12 + iphone/doc/index.rst | 20 + iphone/doc/install.rst | 131 +++ iphone/doc/licensing.rst | 187 +++++ iphone/doc/optimizing.rst | 344 ++++++++ iphone/doc/picker.rst | 104 +++ iphone/doc/static/style.css | 36 + iphone/doc/support.rst | 19 + iphone/doc/tutorial.rst | 216 +++++ .../Classes/ReaderSampleAppDelegate.h | 21 + .../Classes/ReaderSampleAppDelegate.m | 86 ++ .../Classes/ReaderSampleViewController.h | 21 + .../Classes/ReaderSampleViewController.m | 68 ++ iphone/examples/ReaderSample/MainWindow.xib | 444 ++++++++++ .../ReaderSample/ReaderSample-Info.plist | 30 + .../ReaderSample.xcodeproj/project.pbxproj | 377 +++++++++ .../ReaderSampleViewController.xib | 521 ++++++++++++ .../ReaderSample/ReaderSample_Prefix.pch | 11 + iphone/examples/ReaderSample/ZBarSDK | 1 + iphone/examples/ReaderSample/build | 1 + iphone/examples/ReaderSample/main.m | 15 + iphone/examples/readertest/ZBarSDK | 1 + iphone/examples/readertest/build | 1 + .../examples/readertest}/entitlements.plist | 0 iphone/examples/readertest/prefix.pch | 11 + .../examples/readertest}/readertest.m | 3 - .../examples/readertest}/readertest.plist | 0 .../readertest.xcodeproj/project.pbxproj | 232 +++--- .../include/ZBarSDK}/ZBarCaptureReader.h | 7 +- .../include/ZBarSDK}/ZBarImage.h | 4 +- .../include/ZBarSDK}/ZBarImageScanner.h | 5 +- .../include/ZBarSDK}/ZBarReaderController.h | 10 +- .../include/ZBarSDK}/ZBarReaderView.h | 6 +- .../ZBarSDK}/ZBarReaderViewController.h | 3 +- iphone/include/ZBarSDK/ZBarSDK.h | 32 + .../include/ZBarSDK}/ZBarSymbol.h | 5 +- iphone/{ => include}/config.h | 0 iphone/include/prefix.pch | 10 + iphone/prefix.pch | 6 - iphone/res/ZBarSDK-Info.plist | 16 + iphone/res/ZBarSDK-bg.png | Bin 0 -> 23569 bytes iphone/res/ZBarSDK-bg.svg | 78 ++ iphone/res/ZBarSDK.DS_Store | Bin 0 -> 8196 bytes iphone/res/{back.png => zbar-back.png} | Bin iphone/res/{back.svg => zbar-back.svg} | 0 iphone/res/zbar-button.png | Bin 2536 -> 0 bytes iphone/zbar.xcodeproj/project.pbxproj | 771 ++++++++++++++---- test/iphone/prefix.pch | 5 - 85 files changed, 5601 insertions(+), 354 deletions(-) create mode 100644 iphone/ChangeLog create mode 100644 iphone/README create mode 100755 iphone/bin/BuildUniversal.sh create mode 100755 iphone/bin/CreateDMG.sh create mode 100755 iphone/bin/CreateDSStore.pl create mode 100644 iphone/bin/Mac/Finder/AliasRecord.pm create mode 100644 iphone/doc/Documentation.html create mode 100644 iphone/doc/ReaderSample.png create mode 100644 iphone/doc/ZBarImage.rst create mode 100644 iphone/doc/ZBarImageScanner.rst create mode 100644 iphone/doc/ZBarReaderController.rst create mode 100644 iphone/doc/ZBarReaderDelegate.rst create mode 100644 iphone/doc/ZBarReaderView.rst create mode 100644 iphone/doc/ZBarReaderViewController.rst create mode 100644 iphone/doc/ZBarReaderViewDelegate.rst create mode 100644 iphone/doc/ZBarSymbol.rst create mode 100644 iphone/doc/ZBarSymbolSet.rst create mode 100644 iphone/doc/apiref.rst create mode 100644 iphone/doc/camera.rst create mode 100644 iphone/doc/compat.rst create mode 100644 iphone/doc/conf.py create mode 100644 iphone/doc/custom.rst create mode 100644 iphone/doc/devguide.rst create mode 100644 iphone/doc/faq.rst create mode 100644 iphone/doc/getstarted.rst create mode 100644 iphone/doc/index.rst create mode 100644 iphone/doc/install.rst create mode 100644 iphone/doc/licensing.rst create mode 100644 iphone/doc/optimizing.rst create mode 100644 iphone/doc/picker.rst create mode 100644 iphone/doc/static/style.css create mode 100644 iphone/doc/support.rst create mode 100644 iphone/doc/tutorial.rst create mode 100644 iphone/examples/ReaderSample/Classes/ReaderSampleAppDelegate.h create mode 100644 iphone/examples/ReaderSample/Classes/ReaderSampleAppDelegate.m create mode 100644 iphone/examples/ReaderSample/Classes/ReaderSampleViewController.h create mode 100644 iphone/examples/ReaderSample/Classes/ReaderSampleViewController.m create mode 100644 iphone/examples/ReaderSample/MainWindow.xib create mode 100644 iphone/examples/ReaderSample/ReaderSample-Info.plist create mode 100755 iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj create mode 100644 iphone/examples/ReaderSample/ReaderSampleViewController.xib create mode 100644 iphone/examples/ReaderSample/ReaderSample_Prefix.pch create mode 120000 iphone/examples/ReaderSample/ZBarSDK create mode 120000 iphone/examples/ReaderSample/build create mode 100644 iphone/examples/ReaderSample/main.m create mode 120000 iphone/examples/readertest/ZBarSDK create mode 120000 iphone/examples/readertest/build rename {test/iphone => iphone/examples/readertest}/entitlements.plist (100%) create mode 100644 iphone/examples/readertest/prefix.pch rename {test/iphone => iphone/examples/readertest}/readertest.m (99%) rename {test/iphone => iphone/examples/readertest}/readertest.plist (100%) rename {test/iphone => iphone/examples/readertest}/readertest.xcodeproj/project.pbxproj (58%) rename {include/zbar => iphone/include/ZBarSDK}/ZBarCaptureReader.h (95%) rename {include/zbar => iphone/include/ZBarSDK}/ZBarImage.h (98%) rename {include/zbar => iphone/include/ZBarSDK}/ZBarImageScanner.h (95%) rename {include/zbar => iphone/include/ZBarSDK}/ZBarReaderController.h (95%) rename {include/zbar => iphone/include/ZBarSDK}/ZBarReaderView.h (96%) rename {include/zbar => iphone/include/ZBarSDK}/ZBarReaderViewController.h (98%) create mode 100644 iphone/include/ZBarSDK/ZBarSDK.h rename {include/zbar => iphone/include/ZBarSDK}/ZBarSymbol.h (96%) rename iphone/{ => include}/config.h (100%) create mode 100644 iphone/include/prefix.pch delete mode 100644 iphone/prefix.pch create mode 100644 iphone/res/ZBarSDK-Info.plist create mode 100644 iphone/res/ZBarSDK-bg.png create mode 100644 iphone/res/ZBarSDK-bg.svg create mode 100644 iphone/res/ZBarSDK.DS_Store rename iphone/res/{back.png => zbar-back.png} (100%) rename iphone/res/{back.svg => zbar-back.svg} (100%) delete mode 100644 iphone/res/zbar-button.png delete mode 100644 test/iphone/prefix.pch diff --git a/.hgignore b/.hgignore index c43649f..4ec021d 100644 --- a/.hgignore +++ b/.hgignore @@ -20,7 +20,7 @@ ltmain.sh autom4te.cache missing python/MANIFEST -iphone/build -iphone/*.xcodeproj/*.mode1v3 -iphone/*.xcodeproj/*.pbxuser +build +*.xcodeproj/*.mode1v3 +*.xcodeproj/*.pbxuser .DS_Store diff --git a/ChangeLog b/ChangeLog index 9c3767d..1033482 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,34 +1,18 @@ current: - * workaround for iPhone simulator builds - - refactor ZBarReaderView for capture/simulator specific implementations - - fix tracking calculations - - fix captured video frame color conversion * add support for GS1 DataBar Expanded (RSS Expanded) symbology - * fix for poor iPhone 4 performance * add language bindings for DataBar * add preliminary support for GS1 DataBar (RSS-14) symbology - * enable torch for iPhone 4 * enhance decoder reliability (EAN, Code 39, Code 128) - enhance decoder test * fix documentation of command exit codes (bug #3017322) - * 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 * 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 iPhone zoom support, integrate with crop * add support for scanning partial images (cropping) - update c++, python, perl, java bindings and tests - * 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 * fix couple of leaks * remove doc hints about GFDL (bug #3004411) - apply LGPL to API docs @@ -40,29 +24,6 @@ current: * 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) - * 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 * add Java interface to library via JNI - add Java tools and JNI build tests to configure - fix compiler warnings from binary output changes @@ -78,10 +39,7 @@ current: - 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) - * iphone widget back compat updates, add basic test app * add python distutils build infrastructure - * add Obj-C wrapper - * first pass working iPhone "widget" version 0.10: * hotfix add MinGW import lib to Windows installer diff --git a/iphone/ChangeLog b/iphone/ChangeLog new file mode 100644 index 0000000..49f4a13 --- /dev/null +++ b/iphone/ChangeLog @@ -0,0 +1,47 @@ +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" diff --git a/iphone/README b/iphone/README new file mode 100644 index 0000000..29c7e31 --- /dev/null +++ b/iphone/README @@ -0,0 +1,59 @@ +ZBar iPhone 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 39, Interleaved 2 of 5 and QR Code. These are the +Objective C wrappers and integrated widget for developing with the +library on the iPhone 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 +-------- + +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. + +You should be able to open and build the examples directly from the +disk image. If not, please copy them to your local drive and build +from there. + +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-2010 © Jeff Brown et al + +See the included files COPYING and LICENSE for details diff --git a/iphone/ZBarCVImage.h b/iphone/ZBarCVImage.h index 80d1e0c..b0e18a9 100644 --- a/iphone/ZBarCVImage.h +++ b/iphone/ZBarCVImage.h @@ -21,7 +21,7 @@ // http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#import +#import #import // ZBarImage referring to a CVPixelBuffer. used internally to handle diff --git a/iphone/ZBarCaptureReader.m b/iphone/ZBarCaptureReader.m index 7a42e99..513f5e9 100644 --- a/iphone/ZBarCaptureReader.m +++ b/iphone/ZBarCaptureReader.m @@ -22,8 +22,11 @@ //------------------------------------------------------------------------ #import -#import -#import +#import +#import +#import +#import +#import #import "ZBarCVImage.h" #define MODULE ZBarCaptureReader diff --git a/iphone/ZBarHelpController.m b/iphone/ZBarHelpController.m index 717e6c2..3ac6c47 100644 --- a/iphone/ZBarHelpController.m +++ b/iphone/ZBarHelpController.m @@ -104,7 +104,7 @@ - (void) viewDidLoad action: @selector(dismiss)]; backBtn = [[UIBarButtonItem alloc] - initWithImage: [UIImage imageNamed: @"back.png"] + initWithImage: [UIImage imageNamed: @"zbar-back.png"] style: UIBarButtonItemStylePlain target: webView action: @selector(goBack)]; diff --git a/iphone/ZBarImage.m b/iphone/ZBarImage.m index cf7f20f..db50e97 100644 --- a/iphone/ZBarImage.m +++ b/iphone/ZBarImage.m @@ -21,8 +21,8 @@ // http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#import #import +#import #import "debug.h" static void image_cleanup(zbar_image_t *zimg) diff --git a/iphone/ZBarImageScanner.m b/iphone/ZBarImageScanner.m index 3c5fa48..cdc4ea4 100644 --- a/iphone/ZBarImageScanner.m +++ b/iphone/ZBarImageScanner.m @@ -21,7 +21,7 @@ // http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#import +#import #import "debug.h" @implementation ZBarImageScanner diff --git a/iphone/ZBarReaderController.m b/iphone/ZBarReaderController.m index 4c9d3af..3da71a6 100644 --- a/iphone/ZBarReaderController.m +++ b/iphone/ZBarReaderController.m @@ -21,7 +21,7 @@ // http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#import +#import #import "ZBarHelpController.h" #import "debug.h" diff --git a/iphone/ZBarReaderView.m b/iphone/ZBarReaderView.m index 5cb22ee..dba6fc5 100644 --- a/iphone/ZBarReaderView.m +++ b/iphone/ZBarReaderView.m @@ -21,7 +21,7 @@ // http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#import +#import #define MODULE ZBarReaderView #import "debug.h" diff --git a/iphone/ZBarReaderViewController.m b/iphone/ZBarReaderViewController.m index b29b3c9..67be8b4 100644 --- a/iphone/ZBarReaderViewController.m +++ b/iphone/ZBarReaderViewController.m @@ -21,8 +21,8 @@ // http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#import -#import +#import +#import #import "ZBarHelpController.h" #define MODULE ZBarReaderViewController diff --git a/iphone/ZBarReaderViewImpl_Capture.m b/iphone/ZBarReaderViewImpl_Capture.m index e3f5c93..168596e 100644 --- a/iphone/ZBarReaderViewImpl_Capture.m +++ b/iphone/ZBarReaderViewImpl_Capture.m @@ -1,5 +1,31 @@ -#import -#import +//------------------------------------------------------------------------ +// Copyright 2010 (c) Jeff Brown +// +// 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 +#import +#import +#import +#import #define MODULE ZBarReaderView #import "debug.h" diff --git a/iphone/ZBarReaderViewImpl_Simulator.m b/iphone/ZBarReaderViewImpl_Simulator.m index bd1bf34..3768e98 100644 --- a/iphone/ZBarReaderViewImpl_Simulator.m +++ b/iphone/ZBarReaderViewImpl_Simulator.m @@ -1,5 +1,28 @@ -#import -#import +//------------------------------------------------------------------------ +// Copyright 2010 (c) Jeff Brown +// +// 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 +#import #define MODULE ZBarReaderView #import "debug.h" diff --git a/iphone/ZBarSymbol.m b/iphone/ZBarSymbol.m index 5dba311..15f9d9a 100644 --- a/iphone/ZBarSymbol.m +++ b/iphone/ZBarSymbol.m @@ -21,8 +21,7 @@ // http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#import -#import +#import @implementation ZBarSymbol diff --git a/iphone/bin/BuildUniversal.sh b/iphone/bin/BuildUniversal.sh new file mode 100755 index 0000000..1c00589 --- /dev/null +++ b/iphone/bin/BuildUniversal.sh @@ -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 \ + || exit 1 +xcodebuild -target $SUBTARGET -configuration $CONFIGURATION -sdk iphonesimulator \ + || 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_DIR/$CONFIGURATION-iphoneos/$SUBTARGET.a \ + $BUILD_DIR/$CONFIGURATION-iphonesimulator/$SUBTARGET.a \ + -output $OUTDIR/$SUBTARGET.a \ + || exit 1 diff --git a/iphone/bin/CreateDMG.sh b/iphone/bin/CreateDMG.sh new file mode 100755 index 0000000..a13c141 --- /dev/null +++ b/iphone/bin/CreateDMG.sh @@ -0,0 +1,35 @@ +#!/bin/sh +set -ux +VOLNAME=${1:?} +shift +RES=$SOURCE_ROOT/res +BUDDY=$(xcrun -find PlistBuddy) \ + || exit 1 +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) +do + rm -rf $example/{*.xcodeproj/*.{mode1v3,pbxuser},ZBarSDK} + cp -af $BUILT_PRODUCTS_DIR/ZBarSDK $example/ +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 diff --git a/iphone/bin/CreateDSStore.pl b/iphone/bin/CreateDSStore.pl new file mode 100755 index 0000000..d4ec627 --- /dev/null +++ b/iphone/bin/CreateDSStore.pl @@ -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 => [true => 1], + 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 ]), +); diff --git a/iphone/bin/Mac/Finder/AliasRecord.pm b/iphone/bin/Mac/Finder/AliasRecord.pm new file mode 100644 index 0000000..06f68f6 --- /dev/null +++ b/iphone/bin/Mac/Finder/AliasRecord.pm @@ -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; diff --git a/iphone/doc/Documentation.html b/iphone/doc/Documentation.html new file mode 100644 index 0000000..c6a532a --- /dev/null +++ b/iphone/doc/Documentation.html @@ -0,0 +1,11 @@ + + + + + + + +

redirecting to Documentation/index.html

+ + diff --git a/iphone/doc/ReaderSample.png b/iphone/doc/ReaderSample.png new file mode 100644 index 0000000000000000000000000000000000000000..a71b5a4af2dbf6a6122b24e085b868d07b5ec8bb GIT binary patch literal 131381 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 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 ) 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:`` diff --git a/iphone/doc/ZBarReaderDelegate.rst b/iphone/doc/ZBarReaderDelegate.rst new file mode 100644 index 0000000..34b52c7 --- /dev/null +++ b/iphone/doc/ZBarReaderDelegate.rst @@ -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. diff --git a/iphone/doc/ZBarReaderView.rst b/iphone/doc/ZBarReaderView.rst new file mode 100644 index 0000000..0a46e1b --- /dev/null +++ b/iphone/doc/ZBarReaderView.rst @@ -0,0 +1,104 @@ +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 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:: 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,2]. (default 1.25) + + .. 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. diff --git a/iphone/doc/ZBarReaderViewController.rst b/iphone/doc/ZBarReaderViewController.rst new file mode 100644 index 0000000..787a86b --- /dev/null +++ b/iphone/doc/ZBarReaderViewController.rst @@ -0,0 +1,128 @@ +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 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:: 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:: 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:: 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``. + +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. diff --git a/iphone/doc/ZBarReaderViewDelegate.rst b/iphone/doc/ZBarReaderViewDelegate.rst new file mode 100644 index 0000000..e6730cb --- /dev/null +++ b/iphone/doc/ZBarReaderViewDelegate.rst @@ -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. diff --git a/iphone/doc/ZBarSymbol.rst b/iphone/doc/ZBarSymbol.rst new file mode 100644 index 0000000..2027e6a --- /dev/null +++ b/iphone/doc/ZBarSymbol.rst @@ -0,0 +1,158 @@ +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:: 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_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 diff --git a/iphone/doc/ZBarSymbolSet.rst b/iphone/doc/ZBarSymbolSet.rst new file mode 100644 index 0000000..7983869 --- /dev/null +++ b/iphone/doc/ZBarSymbolSet.rst @@ -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. diff --git a/iphone/doc/apiref.rst b/iphone/doc/apiref.rst new file mode 100644 index 0000000..92920c0 --- /dev/null +++ b/iphone/doc/apiref.rst @@ -0,0 +1,16 @@ +******************* + API Reference +******************* + +.. toctree:: + :maxdepth: 1 + + ZBarImage + ZBarImageScanner + ZBarReaderController + ZBarReaderDelegate + ZBarReaderView + ZBarReaderViewController + ZBarReaderViewDelegate + ZBarSymbol + ZBarSymbolSet diff --git a/iphone/doc/camera.rst b/iphone/doc/camera.rst new file mode 100644 index 0000000..a04a1c6 --- /dev/null +++ b/iphone/doc/camera.rst @@ -0,0 +1,129 @@ +Scanning From the Camera Feed +============================= + +Many iPhone 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 is not recommended, it + does not give you much more flexibility than using the full controller. +* 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. It is also the only way to support :doc:`automatic fallback +for iOS 3.1 `. 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 new]; + +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:: + + [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, although the new controller + does not require it (note that modal presentation is the only option if you + want to support :doc:`iOS 3.1 fallback `):: + + [self presentModalViewController: reader + animated: YES]; + +5. Process the results. + + The controller will call the + :member:`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 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. You will +lose the automatic fallback for iOS 3.1 and some of the simulator hooks, so +this approach is not currently recommended (or well tested). + + +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 :) diff --git a/iphone/doc/compat.rst b/iphone/doc/compat.rst new file mode 100644 index 0000000..038e614 --- /dev/null +++ b/iphone/doc/compat.rst @@ -0,0 +1,183 @@ +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. + + +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: + UIImagePickerControllerSoureTypeCamera]) { + // 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 = UIImagePickerControllerSoureTypeCamera; + 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. diff --git a/iphone/doc/conf.py b/iphone/doc/conf.py new file mode 100644 index 0000000..cfc9b5d --- /dev/null +++ b/iphone/doc/conf.py @@ -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, 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 diff --git a/iphone/doc/custom.rst b/iphone/doc/custom.rst new file mode 100644 index 0000000..9e0b207 --- /dev/null +++ b/iphone/doc/custom.rst @@ -0,0 +1,72 @@ +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`, are *only* planning to +support iOS 4 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`, still need the +iOS 3.1 fallback 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`. + +See :doc:`compat` for more information about iOS 3.1 fallbacks. + +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:``. diff --git a/iphone/doc/devguide.rst b/iphone/doc/devguide.rst new file mode 100644 index 0000000..d794e2f --- /dev/null +++ b/iphone/doc/devguide.rst @@ -0,0 +1,13 @@ +*********************** + Developer's Guide +*********************** + +.. toctree:: + :maxdepth: 2 + + camera + picker + custom + optimizing + compat + licensing diff --git a/iphone/doc/faq.rst b/iphone/doc/faq.rst new file mode 100644 index 0000000..78b2ec1 --- /dev/null +++ b/iphone/doc/faq.rst @@ -0,0 +1,113 @@ +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 the iPhone 3GS and iPhone 4. + +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 is 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 for reading barcodes. + + iOS 3.1 is also supported, but you will have to resort to manual capture if + you intend to distribute on the App Store. + + The library should work all the way back to iOS 3.0, although we no longer + test with it. For most cases we recommend you use at least iOS 3.1, which + introduced several must-have enhancements for the UIImagePickerController + (ie, :member:`~ZBarReaderController::cameraOverlayView` and ``takePicture``) + + In all cases you will need at least a 4.0 SDK to build. + + See :doc:`compat` for details about iOS version fallbacks. + +Are any private APIs in use? + No - the binary release of the SDK does not use any private APIs. + + OTOH, if you do not care about private APIs (for instance, you are + targeting AdHoc or enterprise distribution) and you want to enable + automatic capture with iOS 3.1, you can build a version that uses + UIGetScreenImage (which is again a private API). + + See :doc:`compat` for details. + +Does this support "automatic" barcode capture? + Yes - if you use iOS 4, the default configuration will capture barcodes + automatically from the video stream. + + Again, automatic capture is no longer supported with iOS 3.1 for apps + distributed on the App Store. + + +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#Zero-compressed_UPC-E diff --git a/iphone/doc/getstarted.rst b/iphone/doc/getstarted.rst new file mode 100644 index 0000000..29cf9e4 --- /dev/null +++ b/iphone/doc/getstarted.rst @@ -0,0 +1,12 @@ +********************* + Getting Started +********************* + +.. toctree:: + :maxdepth: 2 + :numbered: + + install + tutorial + faq + support diff --git a/iphone/doc/index.rst b/iphone/doc/index.rst new file mode 100644 index 0000000..24c70fc --- /dev/null +++ b/iphone/doc/index.rst @@ -0,0 +1,20 @@ +################### + ZBar iPhone SDK +################### + +Welcome to the ZBar SDK for iPhone! + +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 diff --git a/iphone/doc/install.rst b/iphone/doc/install.rst new file mode 100644 index 0000000..2b18ecc --- /dev/null +++ b/iphone/doc/install.rst @@ -0,0 +1,131 @@ +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 >= 3.2.3 +* iPhone SDK >= 4.0 +* An iPhone 3GS or iPhone 4 +* iOS >= 3.1 running on the device (>= 4.0 is preferred) + +.. warning:: + + *Only* the iPhone 3GS and iPhone 4 are supported, as they have a camera + with auto-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. + +4. 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.1: + + * AVFoundation.framework (weak) + * CoreMedia.framework (weak) + * CoreVideo.framework (weak) + * QuartzCore.framework + * libiconv.dylib + +5. 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 you 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" diff --git a/iphone/doc/licensing.rst b/iphone/doc/licensing.rst new file mode 100644 index 0000000..a281e81 --- /dev/null +++ b/iphone/doc/licensing.rst @@ -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 ;) diff --git a/iphone/doc/optimizing.rst b/iphone/doc/optimizing.rst new file mode 100644 index 0000000..c85b9c1 --- /dev/null +++ b/iphone/doc/optimizing.rst @@ -0,0 +1,344 @@ +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 12-15fps. + +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). You 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 from optimal, 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, 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. You can change this using the capture +:member:`~ZBarReaderView::session` preset. + +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 there just isn't much we can +do about that. + +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 the iPhone 4 device, 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 `_. 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 +-------- + +You can try these examples yourself using the readertest. For each example, +start with the default settings (by tapping the ZBarReaderViewController +class) and enable the custom overlay and continuous mode. + +Frame rates are approximate, measured on an iPhone 3GS running iOS 4.0.1 in a +room with "average" light level (whatever that means). Two measurements are +taken for each case: the rate with the camera pointed at a blank white page +such that it fills the image, and the rate while decoding the provided +example. + +For reference, the base frame rates with default settings are ?/? for [this +linear symbol] and ?/? for [this QR symbol]. + +Long Linear Symbols +^^^^^^^^^^^^^^^^^^^ + +To scan the longest symbol possible, we want to maximize resolution and scan +the longest image axis. [Here is a barcode] you can use for testing. + +We can compensate for the reduction this causes in the frame rate by: + +* cropping the image to a long, skinny rectangle +* disabling scans across the short image axis +* reducing the density + +High Density QR Symbols +^^^^^^^^^^^^^^^^^^^^^^^ + +In this case we also want to maximize the resolution. + +* crop to square +* reduce density + +Small DataBar Symbols +^^^^^^^^^^^^^^^^^^^^^ + +Again we want high resolution scans, but this time we also want high density +passes in both directions. + +* zoom/crop, also helps user see barcode diff --git a/iphone/doc/picker.rst b/iphone/doc/picker.rst new file mode 100644 index 0000000..35335af --- /dev/null +++ b/iphone/doc/picker.rst @@ -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 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 new]; + +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: + UIImagePickerControllerSoureTypeCamera]) + reader.sourceType = UIImagePickerControllerSoureTypeCamera; + [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 + :member:`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 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. diff --git a/iphone/doc/static/style.css b/iphone/doc/static/style.css new file mode 100644 index 0000000..721b5fb --- /dev/null +++ b/iphone/doc/static/style.css @@ -0,0 +1,36 @@ +@import url("default.css"); + +h1, h2, h3, h4, h5, h6 { + clear: both; +} + +img.logo { + vertical-align: middle; +} + +img.floatright { + float: right; + clear: both; + margin-left: 2em; + margin-right: 2em; +} + +dl.docutils dt { + font-weight: bold; +} +dl.docutils dd { + margin-top: 1em; + margin-bottom: 1em; +} + +table.docutils { + margin-left: auto; + margin-right: auto; +} +table.docutils th, table.docutils td { + padding: .25em .5em; +} + +table.docutils.field-list { + margin-left: 0; +} diff --git a/iphone/doc/support.rst b/iphone/doc/support.rst new file mode 100644 index 0000000..7cf8b55 --- /dev/null +++ b/iphone/doc/support.rst @@ -0,0 +1,19 @@ +Obtaining Support +================= + +If this documentation does not address your question/problem and you need +support, please feel free to post in our `iPhone Developers Forum`_. + +.. _`iPhone Developers Forum`: + http://sourceforge.net/projects/zbar/forums/forum/1072195 + +When posting, please: + +* Check the :doc:`faq` and the rest of this documentation first. +* Start a new thread for a new question - do not "hijack" an unrelated thread. +* Post complete details of your problem - complete error messages as well as + relevant source code and images. +* Log-in to receive email, or check back within a day or so - you will almost + always get a response. + +For the latest support information, please see http://zbar.sf.net/iphone diff --git a/iphone/doc/tutorial.rst b/iphone/doc/tutorial.rst new file mode 100644 index 0000000..c7e3989 --- /dev/null +++ b/iphone/doc/tutorial.rst @@ -0,0 +1,216 @@ +ZBar SDK Integration Tutorial +============================= + +.. image:: ReaderSample.png + :alt: Screenshot of the ReaderSample app + :width: 414 + :height: 770 + :scale: 40 + :class: floatright + +This tutorial will quickly get you up and running with the ZBar iPhone SDK. + +We will develop a very simple app that presents a button the user can tap to +invoke the barcode reader and then displays the results. Interface Builder +will be used to create the interface. + +The completed project is also available with the distributed SDK under +:file:`Examples/ReaderSample`. + + +Create the App +-------------- + +1. Open Xcode; you must have version 3.2.3 or later. + +2. Create a new project using the "View-based Application" template. Name the + project "ReaderSample". Save it wherever you like. + +3. Open :file:`ReaderSampleViewController.xib` + +4. Drag a Round Rect Button onto the view and title it "Scan". Customize the + placement and appearance as you like. + +5. Drag an Image View onto the view. Size it to fill about half of the + remaining space. Change the view mode to Aspect Fit. + +6. Drag a Text View onto the view and size it to fill the remaining space. + Change the default text to "No barcode scanned" or something. De-select + "Editable" + +7. Add connections to the interface elements in the code; open + :file:`ReaderSampleViewController.h` and change the interface to:: + + @interface ReaderSampleViewController : UIViewController + { + UIImageView *resultImage; + UITextView *resultText; + } + @property (nonatomic, retain) IBOutlet UIImageView *resultImage; + @property (nonatomic, retain) IBOutlet UITextView *resultText; + - (IBAction) scanButtonTapped; + @end + +8. Now we can finish the interface connections - open + :file:`ReaderSampleViewController.xib` and make these connections: + + * Connect ReaderSampleViewController ``resultImage`` outlet to the + ImageView. + * Connect ReaderSampleViewController ``resultText`` outlet to the TextView. + * Connect ReaderSampleViewController ``scanButtonTapped`` action to the + RoundedRectButton(Scan) event ``TouchUpInside``. + + Consult the Xcode documentation if you need help making these connections. + Make sure you save the XIB once they are finished. + +9. Finish the implementation in :file:`ReaderSampleViewController.m`:: + + @synthesize resultImage, resultText; + + - (IBAction) scanButtonTapped + { + NSLog(@"TBD: scan barcode here..."); + } + + - (void) dealloc { + self.resultImage = nil; + self.resultText = nil; + [super dealloc]; + } + + This stub for scanButtonTapped is temporary, we'll fix it in a minute... + +Although it doesn't do much yet, you should now have a working skeleton app +that you can build and run. + + +Integrate the Reader +-------------------- + +Now for the exciting part - let's add a barcode reader! + +1. If you have not done so already, download the latest SDK from + http://zbar.sourceforge.net/iphone + +2. Double-click the disk image, ZBarSDK-|version|.dmg in the Finder to open it. + +3. Drag the :file:`ZBarSDK` folder into your Xcode project. Make sure that + the "Copy Items into destination group's folder" checkbox is checked. + +4. Right-click the ``Frameworks`` group in your project. Select + ``Add -> Existing Frameworks...`` Make sure "All" are listed and add each + of these from the ``Device`` list (NB hold down command for multiple + selection): + + * AVFoundation.framework + * CoreMedia.framework + * CoreVideo.framework + * QuartzCore.framework + * libiconv.dylib + +5. Import the SDK header. You will usually want to prefix it, so add it to + :file:`ReaderSample_prefix.pch`:: + + // ADD: import barcode reader APIs + #import "ZBarSDK.h" + +6. Declare support for the delegate protocol in + :file:`ReaderSampleViewController.h`:: + + @interface ReaderSampleViewController : UIViewController + // ADD: delegate protocol + < ZBarReaderDelegate > + { + ... + +7. Re-implement scanButtonTapped to present a barcode reader when the user + taps the Scan button. In :file:`ReaderSampleViewController.m`:: + + - (IBAction) scanButtonTapped + { + // ADD: present a barcode reader that scans from the camera feed + ZBarReaderViewController *reader = [ZBarReaderViewController new]; + reader.readerDelegate = self; + + ZBarImageScanner *scanner = reader.scanner; + // TODO: (optional) additional reader configuration here + + // EXAMPLE: disable rarely used I2/5 to improve performance + [scanner setSymbology: ZBAR_I25 + config: ZBAR_CFG_ENABLE + to: 0]; + + // present and release the controller + [self presentModalViewController: reader + animated: YES]; + [reader release]; + } + +8. Finally, implement the delegate method to do something useful with the + results. Still in :file:`ReaderSampleViewController.m`:: + + - (void) imagePickerController: (UIImagePickerController*) reader + didFinishPickingMediaWithInfo: (NSDictionary*) info + { + // ADD: get the decode results + id results = + [info objectForKey: ZBarReaderControllerResults]; + ZBarSymbol *symbol = nil; + for(symbol in results) + // EXAMPLE: just grab the first barcode + break; + + // EXAMPLE: do something useful with the barcode data + resultText.text = symbol.data; + + // EXAMPLE: do something useful with the barcode image + resultImage.image = + [info objectForKey: UIImagePickerControllerOriginalImage]; + + // ADD: dismiss the controller (NB dismiss from the *reader*!) + [reader dismissModalViewControllerAnimated: YES]; + } + +And that's it! + + +Testing +------- + +1. Save everything (don't forget to save MyAppViewController.xib). + +2. Select "Build and Run". + +3. Tap the Scan button. + +4. Aim at barcode. + +5. Enjoy the sweet fruits of your minimal labor + + +Where to go from here +--------------------- + +You can learn more about using the reader APIs to scan barcodes from +:doc:`camera` or :doc:`picker`. Use the :doc:`apiref` to find details about a +particular interface. + + +Troubleshooting +--------------- + +We take great care to ensure this tutorial is working as described. However, +if you do have a problem + +1. Make sure you followed the instructions exactly - every detail is + important. +2. Start from scratch with a new project and follow the instructions + *exactly*. +3. Try the ReaderSample distributed with the SDK and compare your work with + that. +4. If you are unable to get things working, you may post your frustrations in + the project `iPhone Developers Forum`_. Please be very specific about your + problem, post the complete text of any errors, etc. + +.. _`iPhone Developers Forum`: + http://sourceforge.net/projects/zbar/forums/forum/1072195 diff --git a/iphone/examples/ReaderSample/Classes/ReaderSampleAppDelegate.h b/iphone/examples/ReaderSample/Classes/ReaderSampleAppDelegate.h new file mode 100644 index 0000000..7fe8eec --- /dev/null +++ b/iphone/examples/ReaderSample/Classes/ReaderSampleAppDelegate.h @@ -0,0 +1,21 @@ +// +// ReaderSampleAppDelegate.h +// ReaderSample +// +// Created by spadix on 8/4/10. +// + +#import + +@class ReaderSampleViewController; + +@interface ReaderSampleAppDelegate : NSObject { + UIWindow *window; + ReaderSampleViewController *viewController; +} + +@property (nonatomic, retain) IBOutlet UIWindow *window; +@property (nonatomic, retain) IBOutlet ReaderSampleViewController *viewController; + +@end + diff --git a/iphone/examples/ReaderSample/Classes/ReaderSampleAppDelegate.m b/iphone/examples/ReaderSample/Classes/ReaderSampleAppDelegate.m new file mode 100644 index 0000000..cdf4456 --- /dev/null +++ b/iphone/examples/ReaderSample/Classes/ReaderSampleAppDelegate.m @@ -0,0 +1,86 @@ +// +// ReaderSampleAppDelegate.m +// ReaderSample +// +// Created by spadix on 8/4/10. +// + +#import "ReaderSampleAppDelegate.h" +#import "ReaderSampleViewController.h" + +@implementation ReaderSampleAppDelegate + +@synthesize window; +@synthesize viewController; + + +#pragma mark - +#pragma mark Application lifecycle + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + + // Add the view controller's view to the window and display. + [window addSubview:viewController.view]; + [window makeKeyAndVisible]; + + return YES; +} + + +- (void)applicationWillResignActive:(UIApplication *)application { + /* + Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. + */ +} + + +- (void)applicationDidEnterBackground:(UIApplication *)application { + /* + Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + If your application supports background execution, called instead of applicationWillTerminate: when the user quits. + */ +} + + +- (void)applicationWillEnterForeground:(UIApplication *)application { + /* + Called as part of transition from the background to the inactive state: here you can undo many of the changes made on entering the background. + */ +} + + +- (void)applicationDidBecomeActive:(UIApplication *)application { + /* + Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + */ +} + + +- (void)applicationWillTerminate:(UIApplication *)application { + /* + Called when the application is about to terminate. + See also applicationDidEnterBackground:. + */ +} + + +#pragma mark - +#pragma mark Memory management + +- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { + /* + Free up as much memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later. + */ +} + + +- (void)dealloc { + [viewController release]; + [window release]; + [super dealloc]; +} + + +@end diff --git a/iphone/examples/ReaderSample/Classes/ReaderSampleViewController.h b/iphone/examples/ReaderSample/Classes/ReaderSampleViewController.h new file mode 100644 index 0000000..e9763cf --- /dev/null +++ b/iphone/examples/ReaderSample/Classes/ReaderSampleViewController.h @@ -0,0 +1,21 @@ +// +// ReaderSampleViewController.h +// ReaderSample +// +// Created by spadix on 8/4/10. +// + +#import + +@interface ReaderSampleViewController + : UIViewController + // ADD: delegate protocol + < ZBarReaderDelegate > +{ + UIImageView *resultImage; + UITextView *resultText; +} +@property (nonatomic, retain) IBOutlet UIImageView *resultImage; +@property (nonatomic, retain) IBOutlet UITextView *resultText; +- (IBAction) scanButtonTapped; +@end diff --git a/iphone/examples/ReaderSample/Classes/ReaderSampleViewController.m b/iphone/examples/ReaderSample/Classes/ReaderSampleViewController.m new file mode 100644 index 0000000..0e412ac --- /dev/null +++ b/iphone/examples/ReaderSample/Classes/ReaderSampleViewController.m @@ -0,0 +1,68 @@ +// +// ReaderSampleViewController.m +// ReaderSample +// +// Created by spadix on 8/4/10. +// + +#import "ReaderSampleViewController.h" + +@implementation ReaderSampleViewController + +@synthesize resultImage, resultText; + +- (IBAction) scanButtonTapped +{ + // ADD: present a barcode reader that scans from the camera feed + ZBarReaderViewController *reader = [ZBarReaderViewController new]; + reader.readerDelegate = self; + + ZBarImageScanner *scanner = reader.scanner; + // TODO: (optional) additional reader configuration here + + // EXAMPLE: disable rarely used I2/5 to improve performance + [scanner setSymbology: ZBAR_I25 + config: ZBAR_CFG_ENABLE + to: 0]; + + // present and release the controller + [self presentModalViewController: reader + animated: YES]; + [reader release]; +} + +- (void) imagePickerController: (UIImagePickerController*) reader + didFinishPickingMediaWithInfo: (NSDictionary*) info +{ + // ADD: get the decode results + id results = + [info objectForKey: ZBarReaderControllerResults]; + ZBarSymbol *symbol = nil; + for(symbol in results) + // EXAMPLE: just grab the first barcode + break; + + // EXAMPLE: do something useful with the barcode data + resultText.text = symbol.data; + + // EXAMPLE: do something useful with the barcode image + resultImage.image = + [info objectForKey: UIImagePickerControllerOriginalImage]; + + // ADD: dismiss the controller (NB dismiss from the *reader*!) + [reader dismissModalViewControllerAnimated: YES]; +} + +- (void)didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + // Release any cached data, images, etc that aren't in use. +} + +- (void)dealloc { + self.resultImage = nil; + self.resultText = nil; + [super dealloc]; +} + +@end diff --git a/iphone/examples/ReaderSample/MainWindow.xib b/iphone/examples/ReaderSample/MainWindow.xib new file mode 100644 index 0000000..eda55c2 --- /dev/null +++ b/iphone/examples/ReaderSample/MainWindow.xib @@ -0,0 +1,444 @@ + + + + 1024 + 10D571 + 786 + 1038.29 + 460.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 112 + + + YES + + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + YES + + + + YES + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + IBCocoaTouchFramework + + + ReaderSampleViewController + + + 1 + + IBCocoaTouchFramework + NO + + + + 292 + {320, 480} + + 1 + MSAxIDEAA + + NO + NO + + IBCocoaTouchFramework + YES + + + + + YES + + + delegate + + + + 4 + + + + viewController + + + + 11 + + + + window + + + + 14 + + + + + YES + + 0 + + + + + + -1 + + + File's Owner + + + 3 + + + ReaderSample App Delegate + + + -2 + + + + + 10 + + + + + 12 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 10.CustomClassName + 10.IBEditorWindowLastContentRect + 10.IBPluginDependency + 12.IBEditorWindowLastContentRect + 12.IBPluginDependency + 3.CustomClassName + 3.IBPluginDependency + + + YES + UIApplication + UIResponder + ReaderSampleViewController + {{234, 376}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + {{525, 346}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + ReaderSampleAppDelegate + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + YES + + + + + YES + + + YES + + + + 15 + + + + YES + + UIWindow + UIView + + IBUserSource + + + + + ReaderSampleAppDelegate + NSObject + + YES + + YES + viewController + window + + + YES + ReaderSampleViewController + UIWindow + + + + YES + + YES + viewController + window + + + YES + + viewController + ReaderSampleViewController + + + window + UIWindow + + + + + IBProjectSource + Classes/ReaderSampleAppDelegate.h + + + + ReaderSampleAppDelegate + NSObject + + IBUserSource + + + + + ReaderSampleViewController + UIViewController + + IBProjectSource + Classes/ReaderSampleViewController.h + + + + + YES + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIAccessibility.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UINibLoading.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIResponder.h + + + + UIApplication + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIApplication.h + + + + UIResponder + NSObject + + + + UISearchBar + UIView + + IBFrameworkSource + UIKit.framework/Headers/UISearchBar.h + + + + UISearchDisplayController + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UISearchDisplayController.h + + + + UIView + + IBFrameworkSource + UIKit.framework/Headers/UITextField.h + + + + UIView + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIView.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UINavigationController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UIPopoverController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UISplitViewController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UITabBarController.h + + + + UIViewController + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIViewController.h + + + + UIWindow + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIWindow.h + + + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + ReaderSample.xcodeproj + 3 + 112 + + diff --git a/iphone/examples/ReaderSample/ReaderSample-Info.plist b/iphone/examples/ReaderSample/ReaderSample-Info.plist new file mode 100644 index 0000000..3289444 --- /dev/null +++ b/iphone/examples/ReaderSample/ReaderSample-Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.yourcompany.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + NSMainNibFile + MainWindow + + diff --git a/iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj b/iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj new file mode 100755 index 0000000..9408de4 --- /dev/null +++ b/iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj @@ -0,0 +1,377 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 45; + objects = { + +/* Begin PBXBuildFile section */ + 1D3623260D0F684500981E51 /* ReaderSampleAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* ReaderSampleAppDelegate.m */; }; + 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; + 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; + 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; + 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765A40DF7441C002DB57D /* CoreGraphics.framework */; }; + 2899E5220DE3E06400AC0155 /* ReaderSampleViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2899E5210DE3E06400AC0155 /* ReaderSampleViewController.xib */; }; + 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; + 28D7ACF80DDB3853001CB0EB /* ReaderSampleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28D7ACF70DDB3853001CB0EB /* ReaderSampleViewController.m */; }; + DC3CEC791209F83E00D7A786 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC3CEC781209F83E00D7A786 /* AVFoundation.framework */; }; + DC3CEC7B1209F83E00D7A786 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC3CEC7A1209F83E00D7A786 /* CoreMedia.framework */; }; + DC3CEC7D1209F83E00D7A786 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC3CEC7C1209F83E00D7A786 /* CoreVideo.framework */; }; + DC3CEC7F1209F83E00D7A786 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC3CEC7E1209F83E00D7A786 /* QuartzCore.framework */; }; + DC3CEC811209F83E00D7A786 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DC3CEC801209F83E00D7A786 /* libiconv.dylib */; }; + DC48C40C1219E1A20047193B /* libzbar.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC48C4061219E1A20047193B /* libzbar.a */; }; + DC48C40D1219E1A20047193B /* zbar-back.png in Resources */ = {isa = PBXBuildFile; fileRef = DC48C4081219E1A20047193B /* zbar-back.png */; }; + DC48C40E1219E1A20047193B /* zbar-help.html in Resources */ = {isa = PBXBuildFile; fileRef = DC48C4091219E1A20047193B /* zbar-help.html */; }; + DC48C40F1219E1A20047193B /* zbar-helpicons.png in Resources */ = {isa = PBXBuildFile; fileRef = DC48C40A1219E1A20047193B /* zbar-helpicons.png */; }; + DC48C4101219E1A20047193B /* zbar-samples.png in Resources */ = {isa = PBXBuildFile; fileRef = DC48C40B1219E1A20047193B /* zbar-samples.png */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 1D3623240D0F684500981E51 /* ReaderSampleAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReaderSampleAppDelegate.h; sourceTree = ""; }; + 1D3623250D0F684500981E51 /* ReaderSampleAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ReaderSampleAppDelegate.m; sourceTree = ""; }; + 1D6058910D05DD3D006BFB54 /* ReaderSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ReaderSample.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 288765A40DF7441C002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 2899E5210DE3E06400AC0155 /* ReaderSampleViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ReaderSampleViewController.xib; sourceTree = ""; }; + 28AD733E0D9D9553002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; + 28D7ACF60DDB3853001CB0EB /* ReaderSampleViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReaderSampleViewController.h; sourceTree = ""; }; + 28D7ACF70DDB3853001CB0EB /* ReaderSampleViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ReaderSampleViewController.m; sourceTree = ""; }; + 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 32CA4F630368D1EE00C91783 /* ReaderSample_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReaderSample_Prefix.pch; sourceTree = ""; }; + 8D1107310486CEB800E47090 /* ReaderSample-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "ReaderSample-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = ""; }; + DC3CEC781209F83E00D7A786 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; + DC3CEC7A1209F83E00D7A786 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; }; + DC3CEC7C1209F83E00D7A786 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; }; + DC3CEC7E1209F83E00D7A786 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; + DC3CEC801209F83E00D7A786 /* libiconv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libiconv.dylib; path = usr/lib/libiconv.dylib; sourceTree = SDKROOT; }; + DC48C3F41219E1A20047193B /* Decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Decoder.h; sourceTree = ""; }; + DC48C3F51219E1A20047193B /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = ""; }; + DC48C3F61219E1A20047193B /* Image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Image.h; sourceTree = ""; }; + DC48C3F71219E1A20047193B /* ImageScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageScanner.h; sourceTree = ""; }; + DC48C3F81219E1A20047193B /* Processor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Processor.h; sourceTree = ""; }; + DC48C3F91219E1A20047193B /* Scanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Scanner.h; sourceTree = ""; }; + DC48C3FA1219E1A20047193B /* Symbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Symbol.h; sourceTree = ""; }; + DC48C3FB1219E1A20047193B /* Video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Video.h; sourceTree = ""; }; + DC48C3FC1219E1A20047193B /* Window.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Window.h; sourceTree = ""; }; + DC48C3FD1219E1A20047193B /* zbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zbar.h; sourceTree = ""; }; + DC48C3FE1219E1A20047193B /* ZBarCaptureReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarCaptureReader.h; sourceTree = ""; }; + DC48C3FF1219E1A20047193B /* ZBarImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarImage.h; sourceTree = ""; }; + DC48C4001219E1A20047193B /* ZBarImageScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarImageScanner.h; sourceTree = ""; }; + DC48C4011219E1A20047193B /* ZBarReaderController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarReaderController.h; sourceTree = ""; }; + DC48C4021219E1A20047193B /* ZBarReaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarReaderView.h; sourceTree = ""; }; + DC48C4031219E1A20047193B /* ZBarReaderViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarReaderViewController.h; sourceTree = ""; }; + DC48C4041219E1A20047193B /* ZBarSDK.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarSDK.h; sourceTree = ""; }; + DC48C4051219E1A20047193B /* ZBarSymbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarSymbol.h; sourceTree = ""; }; + DC48C4061219E1A20047193B /* libzbar.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libzbar.a; sourceTree = ""; }; + DC48C4081219E1A20047193B /* zbar-back.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "zbar-back.png"; sourceTree = ""; }; + DC48C4091219E1A20047193B /* zbar-help.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "zbar-help.html"; sourceTree = ""; }; + DC48C40A1219E1A20047193B /* zbar-helpicons.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "zbar-helpicons.png"; sourceTree = ""; }; + DC48C40B1219E1A20047193B /* zbar-samples.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "zbar-samples.png"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, + 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */, + 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, + DC3CEC791209F83E00D7A786 /* AVFoundation.framework in Frameworks */, + DC3CEC7B1209F83E00D7A786 /* CoreMedia.framework in Frameworks */, + DC3CEC7D1209F83E00D7A786 /* CoreVideo.framework in Frameworks */, + DC3CEC7F1209F83E00D7A786 /* QuartzCore.framework in Frameworks */, + DC3CEC811209F83E00D7A786 /* libiconv.dylib in Frameworks */, + DC48C40C1219E1A20047193B /* libzbar.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 080E96DDFE201D6D7F000001 /* Classes */ = { + isa = PBXGroup; + children = ( + 1D3623240D0F684500981E51 /* ReaderSampleAppDelegate.h */, + 1D3623250D0F684500981E51 /* ReaderSampleAppDelegate.m */, + 28D7ACF60DDB3853001CB0EB /* ReaderSampleViewController.h */, + 28D7ACF70DDB3853001CB0EB /* ReaderSampleViewController.m */, + ); + path = Classes; + sourceTree = ""; + }; + 19C28FACFE9D520D11CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 1D6058910D05DD3D006BFB54 /* ReaderSample.app */, + ); + name = Products; + sourceTree = ""; + }; + 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { + isa = PBXGroup; + children = ( + 080E96DDFE201D6D7F000001 /* Classes */, + 29B97315FDCFA39411CA2CEA /* Other Sources */, + 29B97317FDCFA39411CA2CEA /* Resources */, + DC48C3F01219E1A20047193B /* ZBarSDK */, + 29B97323FDCFA39411CA2CEA /* Frameworks */, + 19C28FACFE9D520D11CA2CBB /* Products */, + ); + name = CustomTemplate; + sourceTree = ""; + }; + 29B97315FDCFA39411CA2CEA /* Other Sources */ = { + isa = PBXGroup; + children = ( + 32CA4F630368D1EE00C91783 /* ReaderSample_Prefix.pch */, + 29B97316FDCFA39411CA2CEA /* main.m */, + ); + name = "Other Sources"; + sourceTree = ""; + }; + 29B97317FDCFA39411CA2CEA /* Resources */ = { + isa = PBXGroup; + children = ( + 2899E5210DE3E06400AC0155 /* ReaderSampleViewController.xib */, + 28AD733E0D9D9553002E5188 /* MainWindow.xib */, + 8D1107310486CEB800E47090 /* ReaderSample-Info.plist */, + ); + name = Resources; + sourceTree = ""; + }; + 29B97323FDCFA39411CA2CEA /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1D30AB110D05D00D00671497 /* Foundation.framework */, + 288765A40DF7441C002DB57D /* CoreGraphics.framework */, + 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, + DC3CEC7E1209F83E00D7A786 /* QuartzCore.framework */, + DC3CEC781209F83E00D7A786 /* AVFoundation.framework */, + DC3CEC7A1209F83E00D7A786 /* CoreMedia.framework */, + DC3CEC7C1209F83E00D7A786 /* CoreVideo.framework */, + DC3CEC801209F83E00D7A786 /* libiconv.dylib */, + ); + name = Frameworks; + sourceTree = ""; + }; + DC48C3F01219E1A20047193B /* ZBarSDK */ = { + isa = PBXGroup; + children = ( + DC48C3F11219E1A20047193B /* Headers */, + DC48C4061219E1A20047193B /* libzbar.a */, + DC48C4071219E1A20047193B /* Resources */, + ); + path = ZBarSDK; + sourceTree = ""; + }; + DC48C3F11219E1A20047193B /* Headers */ = { + isa = PBXGroup; + children = ( + DC48C3F21219E1A20047193B /* ZBarSDK */, + ); + path = Headers; + sourceTree = ""; + }; + DC48C3F21219E1A20047193B /* ZBarSDK */ = { + isa = PBXGroup; + children = ( + DC48C3F31219E1A20047193B /* zbar */, + DC48C3FD1219E1A20047193B /* zbar.h */, + DC48C3FE1219E1A20047193B /* ZBarCaptureReader.h */, + DC48C3FF1219E1A20047193B /* ZBarImage.h */, + DC48C4001219E1A20047193B /* ZBarImageScanner.h */, + DC48C4011219E1A20047193B /* ZBarReaderController.h */, + DC48C4021219E1A20047193B /* ZBarReaderView.h */, + DC48C4031219E1A20047193B /* ZBarReaderViewController.h */, + DC48C4041219E1A20047193B /* ZBarSDK.h */, + DC48C4051219E1A20047193B /* ZBarSymbol.h */, + ); + path = ZBarSDK; + sourceTree = ""; + }; + DC48C3F31219E1A20047193B /* zbar */ = { + isa = PBXGroup; + children = ( + DC48C3F41219E1A20047193B /* Decoder.h */, + DC48C3F51219E1A20047193B /* Exception.h */, + DC48C3F61219E1A20047193B /* Image.h */, + DC48C3F71219E1A20047193B /* ImageScanner.h */, + DC48C3F81219E1A20047193B /* Processor.h */, + DC48C3F91219E1A20047193B /* Scanner.h */, + DC48C3FA1219E1A20047193B /* Symbol.h */, + DC48C3FB1219E1A20047193B /* Video.h */, + DC48C3FC1219E1A20047193B /* Window.h */, + ); + path = zbar; + sourceTree = ""; + }; + DC48C4071219E1A20047193B /* Resources */ = { + isa = PBXGroup; + children = ( + DC48C4081219E1A20047193B /* zbar-back.png */, + DC48C4091219E1A20047193B /* zbar-help.html */, + DC48C40A1219E1A20047193B /* zbar-helpicons.png */, + DC48C40B1219E1A20047193B /* zbar-samples.png */, + ); + path = Resources; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1D6058900D05DD3D006BFB54 /* ReaderSample */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "ReaderSample" */; + buildPhases = ( + 1D60588D0D05DD3D006BFB54 /* Resources */, + 1D60588E0D05DD3D006BFB54 /* Sources */, + 1D60588F0D05DD3D006BFB54 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ReaderSample; + productName = ReaderSample; + productReference = 1D6058910D05DD3D006BFB54 /* ReaderSample.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29B97313FDCFA39411CA2CEA /* Project object */ = { + isa = PBXProject; + buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ReaderSample" */; + compatibilityVersion = "Xcode 3.1"; + hasScannedForEncodings = 1; + mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 1D6058900D05DD3D006BFB54 /* ReaderSample */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1D60588D0D05DD3D006BFB54 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */, + 2899E5220DE3E06400AC0155 /* ReaderSampleViewController.xib in Resources */, + DC48C40D1219E1A20047193B /* zbar-back.png in Resources */, + DC48C40E1219E1A20047193B /* zbar-help.html in Resources */, + DC48C40F1219E1A20047193B /* zbar-helpicons.png in Resources */, + DC48C4101219E1A20047193B /* zbar-samples.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1D60588E0D05DD3D006BFB54 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1D60589B0D05DD56006BFB54 /* main.m in Sources */, + 1D3623260D0F684500981E51 /* ReaderSampleAppDelegate.m in Sources */, + 28D7ACF80DDB3853001CB0EB /* ReaderSampleViewController.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1D6058940D05DD3E006BFB54 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = ReaderSample_Prefix.pch; + INFOPLIST_FILE = "ReaderSample-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/ZBarSDK\"", + ); + PRODUCT_NAME = ReaderSample; + SYMROOT = /tmp/ReaderSample.build; + }; + name = Debug; + }; + 1D6058950D05DD3E006BFB54 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = ReaderSample_Prefix.pch; + INFOPLIST_FILE = "ReaderSample-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/ZBarSDK\"", + ); + PRODUCT_NAME = ReaderSample; + SYMROOT = /tmp/ReaderSample.build; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + C01FCF4F08A954540054247B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = iphoneos4.0; + }; + name = Debug; + }; + C01FCF5008A954540054247B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; + PREBINDING = NO; + SDKROOT = iphoneos4.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "ReaderSample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1D6058940D05DD3E006BFB54 /* Debug */, + 1D6058950D05DD3E006BFB54 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ReaderSample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C01FCF4F08A954540054247B /* Debug */, + C01FCF5008A954540054247B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; +} diff --git a/iphone/examples/ReaderSample/ReaderSampleViewController.xib b/iphone/examples/ReaderSample/ReaderSampleViewController.xib new file mode 100644 index 0000000..5f522f4 --- /dev/null +++ b/iphone/examples/ReaderSample/ReaderSampleViewController.xib @@ -0,0 +1,521 @@ + + + + 1024 + 10F569 + 788 + 1038.29 + 461.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 117 + + + YES + + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + YES + + + + YES + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + + 274 + + YES + + + 292 + {{20, 392}, {280, 48}} + + NO + IBCocoaTouchFramework + 0 + 0 + + Helvetica-Bold + 18 + 16 + + 1 + Scan + + 3 + MQA + + + 1 + MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + + + 3 + MC41AA + + + + + 292 + {{20, 20}, {280, 210}} + + 1 + NO + IBCocoaTouchFramework + + + + 292 + {{20, 238}, {280, 146}} + + + 3 + MCAwAA + + NO + YES + YES + IBCocoaTouchFramework + NO + No barcode scanned + + 2 + IBCocoaTouchFramework + + + + {320, 460} + + + 3 + MC43NQA + + 2 + + + NO + + IBCocoaTouchFramework + + + + + YES + + + view + + + + 7 + + + + resultImage + + + + 11 + + + + resultText + + + + 12 + + + + scanButtonTapped + + + 7 + + 13 + + + + + YES + + 0 + + + + + + -1 + + + File's Owner + + + -2 + + + + + 6 + + + YES + + + + + + + + 8 + + + + + 9 + + + + + 10 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 10.IBPluginDependency + 6.IBEditorWindowLastContentRect + 6.IBPluginDependency + 8.IBPluginDependency + 9.IBPluginDependency + + + YES + ReaderSampleViewController + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + {{239, 276}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + YES + + + + + YES + + + YES + + + + 13 + + + + YES + + ReaderSampleViewController + UIViewController + + scanButtonTapped + id + + + scanButtonTapped + + scanButtonTapped + id + + + + YES + + YES + resultImage + resultText + + + YES + UIImageView + UITextView + + + + YES + + YES + resultImage + resultText + + + YES + + resultImage + UIImageView + + + resultText + UITextView + + + + + IBProjectSource + Classes/ReaderSampleViewController.h + + + + + YES + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIAccessibility.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UINibLoading.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIResponder.h + + + + UIButton + UIControl + + IBFrameworkSource + UIKit.framework/Headers/UIButton.h + + + + UIControl + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIControl.h + + + + UIImageView + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIImageView.h + + + + UIResponder + NSObject + + + + UIScrollView + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIScrollView.h + + + + UISearchBar + UIView + + IBFrameworkSource + UIKit.framework/Headers/UISearchBar.h + + + + UISearchDisplayController + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UISearchDisplayController.h + + + + UITextView + UIScrollView + + IBFrameworkSource + UIKit.framework/Headers/UITextView.h + + + + UIView + + IBFrameworkSource + UIKit.framework/Headers/UITextField.h + + + + UIView + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIView.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UINavigationController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UIPopoverController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UISplitViewController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UITabBarController.h + + + + UIViewController + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIViewController.h + + + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + ReaderSample.xcodeproj + 3 + 117 + + diff --git a/iphone/examples/ReaderSample/ReaderSample_Prefix.pch b/iphone/examples/ReaderSample/ReaderSample_Prefix.pch new file mode 100644 index 0000000..66bf51a --- /dev/null +++ b/iphone/examples/ReaderSample/ReaderSample_Prefix.pch @@ -0,0 +1,11 @@ +// +// Prefix header for all source files of the 'ReaderSample' target in the 'ReaderSample' project +// + +#ifdef __OBJC__ +# import +# import + +// ADD: barcode reader APIs +# import "ZBarSDK.h" +#endif diff --git a/iphone/examples/ReaderSample/ZBarSDK b/iphone/examples/ReaderSample/ZBarSDK new file mode 120000 index 0000000..b8e7666 --- /dev/null +++ b/iphone/examples/ReaderSample/ZBarSDK @@ -0,0 +1 @@ +../../build/Release-iphoneos/ZBarSDK \ No newline at end of file diff --git a/iphone/examples/ReaderSample/build b/iphone/examples/ReaderSample/build new file mode 120000 index 0000000..1e5c306 --- /dev/null +++ b/iphone/examples/ReaderSample/build @@ -0,0 +1 @@ +/tmp/ReaderSample.build \ No newline at end of file diff --git a/iphone/examples/ReaderSample/main.m b/iphone/examples/ReaderSample/main.m new file mode 100644 index 0000000..843293a --- /dev/null +++ b/iphone/examples/ReaderSample/main.m @@ -0,0 +1,15 @@ +// +// main.m +// ReaderSample +// +// Created by spadix on 8/4/10. +// + +#import + +int main(int argc, char *argv[]) { + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + int retVal = UIApplicationMain(argc, argv, nil, nil); + [pool release]; + return retVal; +} diff --git a/iphone/examples/readertest/ZBarSDK b/iphone/examples/readertest/ZBarSDK new file mode 120000 index 0000000..b8e7666 --- /dev/null +++ b/iphone/examples/readertest/ZBarSDK @@ -0,0 +1 @@ +../../build/Release-iphoneos/ZBarSDK \ No newline at end of file diff --git a/iphone/examples/readertest/build b/iphone/examples/readertest/build new file mode 120000 index 0000000..bd23a51 --- /dev/null +++ b/iphone/examples/readertest/build @@ -0,0 +1 @@ +/tmp/readertest.build \ No newline at end of file diff --git a/test/iphone/entitlements.plist b/iphone/examples/readertest/entitlements.plist similarity index 100% rename from test/iphone/entitlements.plist rename to iphone/examples/readertest/entitlements.plist diff --git a/iphone/examples/readertest/prefix.pch b/iphone/examples/readertest/prefix.pch new file mode 100644 index 0000000..9efda98 --- /dev/null +++ b/iphone/examples/readertest/prefix.pch @@ -0,0 +1,11 @@ +#ifdef __OBJC__ +# import +# import +# import +# import +# import +# import +# import +# import +# import "ZBarSDK.h" +#endif diff --git a/test/iphone/readertest.m b/iphone/examples/readertest/readertest.m similarity index 99% rename from test/iphone/readertest.m rename to iphone/examples/readertest/readertest.m index 75d3bb8..3ef6ee4 100644 --- a/test/iphone/readertest.m +++ b/iphone/examples/readertest/readertest.m @@ -1,6 +1,3 @@ -#import -#import - #if 0 # define VALGRIND "/usr/local/bin/valgrind" #endif diff --git a/test/iphone/readertest.plist b/iphone/examples/readertest/readertest.plist similarity index 100% rename from test/iphone/readertest.plist rename to iphone/examples/readertest/readertest.plist diff --git a/test/iphone/readertest.xcodeproj/project.pbxproj b/iphone/examples/readertest/readertest.xcodeproj/project.pbxproj similarity index 58% rename from test/iphone/readertest.xcodeproj/project.pbxproj rename to iphone/examples/readertest/readertest.xcodeproj/project.pbxproj index 130e1ff..9f0ad29 100755 --- a/test/iphone/readertest.xcodeproj/project.pbxproj +++ b/iphone/examples/readertest/readertest.xcodeproj/project.pbxproj @@ -10,52 +10,51 @@ 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; }; - DC0BB57D10B124EB000448CB /* zbar-helpicons.png in Resources */ = {isa = PBXBuildFile; fileRef = DC0BB57B10B124EB000448CB /* zbar-helpicons.png */; }; - DC1C8DED10DAAEBA004C0F9E /* entitlements.plist in Resources */ = {isa = PBXBuildFile; fileRef = DC1C8DEC10DAAEBA004C0F9E /* entitlements.plist */; }; - DC7E3325113DA00200E67FB8 /* zbar-help.html in Resources */ = {isa = PBXBuildFile; fileRef = DC7E3324113DA00200E67FB8 /* zbar-help.html */; }; - DC7E3337113DAEE700E67FB8 /* back.png in Resources */ = {isa = PBXBuildFile; fileRef = DC7E3336113DAEE700E67FB8 /* back.png */; }; - DC7E33EA113EA95800E67FB8 /* zbar-samples.png in Resources */ = {isa = PBXBuildFile; fileRef = DC7E33E9113EA95800E67FB8 /* zbar-samples.png */; }; + DC48C4D61219E5F70047193B /* libzbar.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC48C4D01219E5F70047193B /* libzbar.a */; }; + DC48C4D71219E5F70047193B /* zbar-back.png in Resources */ = {isa = PBXBuildFile; fileRef = DC48C4D21219E5F70047193B /* zbar-back.png */; }; + DC48C4D81219E5F70047193B /* zbar-help.html in Resources */ = {isa = PBXBuildFile; fileRef = DC48C4D31219E5F70047193B /* zbar-help.html */; }; + DC48C4D91219E5F70047193B /* zbar-helpicons.png in Resources */ = {isa = PBXBuildFile; fileRef = DC48C4D41219E5F70047193B /* zbar-helpicons.png */; }; + DC48C4DA1219E5F70047193B /* zbar-samples.png in Resources */ = {isa = PBXBuildFile; fileRef = DC48C4D51219E5F70047193B /* zbar-samples.png */; }; DCB9118510BC5DA200B907F0 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCB9118410BC5DA200B907F0 /* QuartzCore.framework */; }; DCB9118810BC5DB500B907F0 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD6E13B10B0AFD4002005CD /* libiconv.dylib */; }; - DCB9119B10BC5DCB00B907F0 /* libzbar.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD6E0E610B0AE16002005CD /* libzbar.a */; }; DCD6E0D010B0AD41002005CD /* readertest.m in Sources */ = {isa = PBXBuildFile; fileRef = DCD6E0CF10B0AD41002005CD /* readertest.m */; }; DCDC6D9B11ACA23000021380 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCDC6D9A11ACA23000021380 /* CoreVideo.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; DCDC6D9F11ACA23900021380 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCDC6D9E11ACA23900021380 /* CoreMedia.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; DCDC6DEC11ACA5B400021380 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCDC6DEB11ACA5B400021380 /* AVFoundation.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; /* End PBXBuildFile section */ -/* Begin PBXContainerItemProxy section */ - DCD6E0E510B0AE16002005CD /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = DCD6E0DE10B0AE16002005CD /* zbar.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = D2AAC07E0554694100DB518D; - remoteInfo = zbar; - }; - DCD6E11810B0AE7B002005CD /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = DCD6E0DE10B0AE16002005CD /* zbar.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = D2AAC07D0554694100DB518D; - remoteInfo = zbar; - }; -/* End PBXContainerItemProxy section */ - /* Begin PBXFileReference section */ 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 1D6058910D05DD3D006BFB54 /* readertest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = readertest.app; sourceTree = BUILT_PRODUCTS_DIR; }; 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 288765FC0DF74451002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - DC0BB57B10B124EB000448CB /* zbar-helpicons.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "zbar-helpicons.png"; path = "../../iphone/res/zbar-helpicons.png"; sourceTree = SOURCE_ROOT; }; - DC1C8DEC10DAAEBA004C0F9E /* entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = entitlements.plist; sourceTree = ""; }; - DC7E3324113DA00200E67FB8 /* zbar-help.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = "zbar-help.html"; path = "../../iphone/res/zbar-help.html"; sourceTree = SOURCE_ROOT; }; - DC7E3336113DAEE700E67FB8 /* back.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = back.png; path = ../../iphone/res/back.png; sourceTree = SOURCE_ROOT; }; - DC7E33E9113EA95800E67FB8 /* zbar-samples.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "zbar-samples.png"; path = "../../iphone/res/zbar-samples.png"; sourceTree = SOURCE_ROOT; }; + DC48C4BE1219E5F70047193B /* Decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Decoder.h; sourceTree = ""; }; + DC48C4BF1219E5F70047193B /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = ""; }; + DC48C4C01219E5F70047193B /* Image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Image.h; sourceTree = ""; }; + DC48C4C11219E5F70047193B /* ImageScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageScanner.h; sourceTree = ""; }; + DC48C4C21219E5F70047193B /* Processor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Processor.h; sourceTree = ""; }; + DC48C4C31219E5F70047193B /* Scanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Scanner.h; sourceTree = ""; }; + DC48C4C41219E5F70047193B /* Symbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Symbol.h; sourceTree = ""; }; + DC48C4C51219E5F70047193B /* Video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Video.h; sourceTree = ""; }; + DC48C4C61219E5F70047193B /* Window.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Window.h; sourceTree = ""; }; + DC48C4C71219E5F70047193B /* zbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zbar.h; sourceTree = ""; }; + DC48C4C81219E5F70047193B /* ZBarCaptureReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarCaptureReader.h; sourceTree = ""; }; + DC48C4C91219E5F70047193B /* ZBarImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarImage.h; sourceTree = ""; }; + DC48C4CA1219E5F70047193B /* ZBarImageScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarImageScanner.h; sourceTree = ""; }; + DC48C4CB1219E5F70047193B /* ZBarReaderController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarReaderController.h; sourceTree = ""; }; + DC48C4CC1219E5F70047193B /* ZBarReaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarReaderView.h; sourceTree = ""; }; + DC48C4CD1219E5F70047193B /* ZBarReaderViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarReaderViewController.h; sourceTree = ""; }; + DC48C4CE1219E5F70047193B /* ZBarSDK.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarSDK.h; sourceTree = ""; }; + DC48C4CF1219E5F70047193B /* ZBarSymbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarSymbol.h; sourceTree = ""; }; + DC48C4D01219E5F70047193B /* libzbar.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libzbar.a; sourceTree = ""; }; + DC48C4D21219E5F70047193B /* zbar-back.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "zbar-back.png"; sourceTree = ""; }; + DC48C4D31219E5F70047193B /* zbar-help.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "zbar-help.html"; sourceTree = ""; }; + DC48C4D41219E5F70047193B /* zbar-helpicons.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "zbar-helpicons.png"; sourceTree = ""; }; + DC48C4D51219E5F70047193B /* zbar-samples.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "zbar-samples.png"; sourceTree = ""; }; DCB9118410BC5DA200B907F0 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; DCD6E0CE10B0AD41002005CD /* prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = prefix.pch; sourceTree = ""; }; DCD6E0CF10B0AD41002005CD /* readertest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = readertest.m; sourceTree = ""; }; DCD6E0D810B0AD55002005CD /* readertest.plist */ = {isa = PBXFileReference; explicitFileType = text.plist.info; fileEncoding = 4; path = readertest.plist; sourceTree = ""; }; - DCD6E0DE10B0AE16002005CD /* zbar.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = zbar.xcodeproj; path = ../../iphone/zbar.xcodeproj; sourceTree = SOURCE_ROOT; }; DCD6E13B10B0AFD4002005CD /* libiconv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libiconv.dylib; path = usr/lib/libiconv.dylib; sourceTree = SDKROOT; }; DCDC6D9A11ACA23000021380 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; }; DCDC6D9E11ACA23900021380 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; }; @@ -68,14 +67,14 @@ buildActionMask = 2147483647; files = ( 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, - 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */, + 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, DCB9118510BC5DA200B907F0 /* QuartzCore.framework in Frameworks */, - DCB9118810BC5DB500B907F0 /* libiconv.dylib in Frameworks */, - DCB9119B10BC5DCB00B907F0 /* libzbar.a in Frameworks */, - DCDC6D9B11ACA23000021380 /* CoreVideo.framework in Frameworks */, - DCDC6D9F11ACA23900021380 /* CoreMedia.framework in Frameworks */, DCDC6DEC11ACA5B400021380 /* AVFoundation.framework in Frameworks */, + DCDC6D9F11ACA23900021380 /* CoreMedia.framework in Frameworks */, + DCDC6D9B11ACA23000021380 /* CoreVideo.framework in Frameworks */, + DCB9118810BC5DB500B907F0 /* libiconv.dylib in Frameworks */, + DC48C4D61219E5F70047193B /* libzbar.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -93,15 +92,10 @@ 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { isa = PBXGroup; children = ( - DC1C8DEC10DAAEBA004C0F9E /* entitlements.plist */, - DCD6E0CF10B0AD41002005CD /* readertest.m */, DCD6E0CE10B0AD41002005CD /* prefix.pch */, - DCD6E0D810B0AD55002005CD /* readertest.plist */, - DC7E3324113DA00200E67FB8 /* zbar-help.html */, - DC0BB57B10B124EB000448CB /* zbar-helpicons.png */, - DC7E33E9113EA95800E67FB8 /* zbar-samples.png */, - DC7E3336113DAEE700E67FB8 /* back.png */, - DCD6E0DE10B0AE16002005CD /* zbar.xcodeproj */, + DCD6E0CF10B0AD41002005CD /* readertest.m */, + DC48C4BA1219E5F70047193B /* ZBarSDK */, + DC3CEAC61209C07400D7A786 /* Resources */, 29B97323FDCFA39411CA2CEA /* Frameworks */, 19C28FACFE9D520D11CA2CBB /* Products */, ); @@ -111,9 +105,9 @@ 29B97323FDCFA39411CA2CEA /* Frameworks */ = { isa = PBXGroup; children = ( - 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, 1D30AB110D05D00D00671497 /* Foundation.framework */, 288765FC0DF74451002DB57D /* CoreGraphics.framework */, + 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, DCB9118410BC5DA200B907F0 /* QuartzCore.framework */, DCDC6DEB11ACA5B400021380 /* AVFoundation.framework */, DCDC6D9A11ACA23000021380 /* CoreVideo.framework */, @@ -123,12 +117,74 @@ name = Frameworks; sourceTree = ""; }; - DCD6E0DF10B0AE16002005CD /* Products */ = { + DC3CEAC61209C07400D7A786 /* Resources */ = { + isa = PBXGroup; + children = ( + DCD6E0D810B0AD55002005CD /* readertest.plist */, + ); + name = Resources; + sourceTree = ""; + }; + DC48C4BA1219E5F70047193B /* ZBarSDK */ = { isa = PBXGroup; children = ( - DCD6E0E610B0AE16002005CD /* libzbar.a */, + DC48C4BB1219E5F70047193B /* Headers */, + DC48C4D01219E5F70047193B /* libzbar.a */, + DC48C4D11219E5F70047193B /* Resources */, ); - name = Products; + path = ZBarSDK; + sourceTree = ""; + }; + DC48C4BB1219E5F70047193B /* Headers */ = { + isa = PBXGroup; + children = ( + DC48C4BC1219E5F70047193B /* ZBarSDK */, + ); + path = Headers; + sourceTree = ""; + }; + DC48C4BC1219E5F70047193B /* ZBarSDK */ = { + isa = PBXGroup; + children = ( + DC48C4BD1219E5F70047193B /* zbar */, + DC48C4C71219E5F70047193B /* zbar.h */, + DC48C4C81219E5F70047193B /* ZBarCaptureReader.h */, + DC48C4C91219E5F70047193B /* ZBarImage.h */, + DC48C4CA1219E5F70047193B /* ZBarImageScanner.h */, + DC48C4CB1219E5F70047193B /* ZBarReaderController.h */, + DC48C4CC1219E5F70047193B /* ZBarReaderView.h */, + DC48C4CD1219E5F70047193B /* ZBarReaderViewController.h */, + DC48C4CE1219E5F70047193B /* ZBarSDK.h */, + DC48C4CF1219E5F70047193B /* ZBarSymbol.h */, + ); + path = ZBarSDK; + sourceTree = ""; + }; + DC48C4BD1219E5F70047193B /* zbar */ = { + isa = PBXGroup; + children = ( + DC48C4BE1219E5F70047193B /* Decoder.h */, + DC48C4BF1219E5F70047193B /* Exception.h */, + DC48C4C01219E5F70047193B /* Image.h */, + DC48C4C11219E5F70047193B /* ImageScanner.h */, + DC48C4C21219E5F70047193B /* Processor.h */, + DC48C4C31219E5F70047193B /* Scanner.h */, + DC48C4C41219E5F70047193B /* Symbol.h */, + DC48C4C51219E5F70047193B /* Video.h */, + DC48C4C61219E5F70047193B /* Window.h */, + ); + path = zbar; + sourceTree = ""; + }; + DC48C4D11219E5F70047193B /* Resources */ = { + isa = PBXGroup; + children = ( + DC48C4D21219E5F70047193B /* zbar-back.png */, + DC48C4D31219E5F70047193B /* zbar-help.html */, + DC48C4D41219E5F70047193B /* zbar-helpicons.png */, + DC48C4D51219E5F70047193B /* zbar-samples.png */, + ); + path = Resources; sourceTree = ""; }; /* End PBXGroup section */ @@ -145,7 +201,6 @@ buildRules = ( ); dependencies = ( - DCD6E11910B0AE7B002005CD /* PBXTargetDependency */, ); name = readertest; productName = readertest; @@ -162,12 +217,6 @@ hasScannedForEncodings = 1; mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; projectDirPath = ""; - projectReferences = ( - { - ProductGroup = DCD6E0DF10B0AE16002005CD /* Products */; - ProjectRef = DCD6E0DE10B0AE16002005CD /* zbar.xcodeproj */; - }, - ); projectRoot = ""; targets = ( 1D6058900D05DD3D006BFB54 /* readertest */, @@ -175,26 +224,15 @@ }; /* End PBXProject section */ -/* Begin PBXReferenceProxy section */ - DCD6E0E610B0AE16002005CD /* libzbar.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libzbar.a; - remoteRef = DCD6E0E510B0AE16002005CD /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - /* Begin PBXResourcesBuildPhase section */ 1D60588D0D05DD3D006BFB54 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - DC0BB57D10B124EB000448CB /* zbar-helpicons.png in Resources */, - DC1C8DED10DAAEBA004C0F9E /* entitlements.plist in Resources */, - DC7E3325113DA00200E67FB8 /* zbar-help.html in Resources */, - DC7E3337113DAEE700E67FB8 /* back.png in Resources */, - DC7E33EA113EA95800E67FB8 /* zbar-samples.png in Resources */, + DC48C4D71219E5F70047193B /* zbar-back.png in Resources */, + DC48C4D81219E5F70047193B /* zbar-help.html in Resources */, + DC48C4D91219E5F70047193B /* zbar-helpicons.png in Resources */, + DC48C4DA1219E5F70047193B /* zbar-samples.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -211,25 +249,19 @@ }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXTargetDependency section */ - DCD6E11910B0AE7B002005CD /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = zbar; - targetProxy = DCD6E11810B0AE7B002005CD /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - /* Begin XCBuildConfiguration section */ 1D6058940D05DD3E006BFB54 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = prefix.pch; INFOPLIST_FILE = readertest.plist; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/ZBarSDK\"", + ); PRODUCT_NAME = readertest; }; name = Debug; @@ -237,11 +269,14 @@ 1D6058950D05DD3E006BFB54 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = prefix.pch; INFOPLIST_FILE = readertest.plist; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/ZBarSDK\"", + ); PRODUCT_NAME = readertest; }; name = Release; @@ -254,11 +289,10 @@ GCC_C_LANGUAGE_STANDARD = c99; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ../../include; - IPHONEOS_DEPLOYMENT_TARGET = 3.1.2; + IPHONEOS_DEPLOYMENT_TARGET = 3.1; PREBINDING = NO; - RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = iphoneos4.0; + SYMROOT = /tmp/readertest.build; }; name = Debug; }; @@ -270,41 +304,13 @@ GCC_C_LANGUAGE_STANDARD = c99; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ../../include; + IPHONEOS_DEPLOYMENT_TARGET = 3.1; PREBINDING = NO; SDKROOT = iphoneos4.0; + SYMROOT = /tmp/readertest.build; }; name = Release; }; - DC1C8DF010DAAED5004C0F9E /* AdHoc */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1"; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ../../include; - PREBINDING = NO; - "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; - SDKROOT = iphoneos4.0; - }; - name = AdHoc; - }; - DC1C8DF110DAAED5004C0F9E /* AdHoc */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CODE_SIGN_ENTITLEMENTS = entitlements.plist; - COPY_PHASE_STRIP = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = prefix.pch; - INFOPLIST_FILE = readertest.plist; - PRODUCT_NAME = readertest; - }; - name = AdHoc; - }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -313,7 +319,6 @@ buildConfigurations = ( 1D6058940D05DD3E006BFB54 /* Debug */, 1D6058950D05DD3E006BFB54 /* Release */, - DC1C8DF110DAAED5004C0F9E /* AdHoc */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -323,7 +328,6 @@ buildConfigurations = ( C01FCF4F08A954540054247B /* Debug */, C01FCF5008A954540054247B /* Release */, - DC1C8DF010DAAED5004C0F9E /* AdHoc */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/include/zbar/ZBarCaptureReader.h b/iphone/include/ZBarSDK/ZBarCaptureReader.h similarity index 95% rename from include/zbar/ZBarCaptureReader.h rename to iphone/include/ZBarSDK/ZBarCaptureReader.h index 1d28243..038b902 100644 --- a/include/zbar/ZBarCaptureReader.h +++ b/iphone/include/ZBarSDK/ZBarCaptureReader.h @@ -21,10 +21,11 @@ // http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#import +#import +#import "ZBarImageScanner.h" -@class ZBarCaptureReader, ZBarImageScanner, ZBarImage, ZBarCVImage, - ZBarSymbolSet; +@class AVCaptureVideoDataOutput, AVCaptureOutput; +@class ZBarCaptureReader, ZBarCVImage; @protocol ZBarCaptureDelegate diff --git a/include/zbar/ZBarImage.h b/iphone/include/ZBarSDK/ZBarImage.h similarity index 98% rename from include/zbar/ZBarImage.h rename to iphone/include/ZBarSDK/ZBarImage.h index dcb8644..2e6ec8e 100644 --- a/include/zbar/ZBarImage.h +++ b/iphone/include/ZBarSDK/ZBarImage.h @@ -21,9 +21,9 @@ // http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#import -#import #import +#import "zbar.h" +#import "ZBarSymbol.h" #ifdef __cplusplus using namespace zbar; diff --git a/include/zbar/ZBarImageScanner.h b/iphone/include/ZBarSDK/ZBarImageScanner.h similarity index 95% rename from include/zbar/ZBarImageScanner.h rename to iphone/include/ZBarSDK/ZBarImageScanner.h index ca85d56..c01b047 100644 --- a/include/zbar/ZBarImageScanner.h +++ b/iphone/include/ZBarSDK/ZBarImageScanner.h @@ -21,8 +21,9 @@ // http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#import -#import +#import +#import "zbar.h" +#import "ZBarImage.h" #ifdef __cplusplus using namespace zbar; diff --git a/include/zbar/ZBarReaderController.h b/iphone/include/ZBarSDK/ZBarReaderController.h similarity index 95% rename from include/zbar/ZBarReaderController.h rename to iphone/include/ZBarSDK/ZBarReaderController.h index f0dd4f0..9121971 100644 --- a/include/zbar/ZBarReaderController.h +++ b/iphone/include/ZBarSDK/ZBarReaderController.h @@ -21,9 +21,8 @@ // http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#import #import -#import +#import "ZBarImageScanner.h" #ifdef __cplusplus using namespace zbar; @@ -61,9 +60,10 @@ typedef enum { @end -@interface ZBarReaderController : UIImagePickerController - < UINavigationControllerDelegate, - UIImagePickerControllerDelegate > +@interface ZBarReaderController + : UIImagePickerController + < UINavigationControllerDelegate, + UIImagePickerControllerDelegate > { ZBarImageScanner *scanner; ZBarHelpController *help; diff --git a/include/zbar/ZBarReaderView.h b/iphone/include/ZBarSDK/ZBarReaderView.h similarity index 96% rename from include/zbar/ZBarReaderView.h rename to iphone/include/ZBarSDK/ZBarReaderView.h index 0365724..78a4169 100644 --- a/include/zbar/ZBarReaderView.h +++ b/iphone/include/ZBarSDK/ZBarReaderView.h @@ -22,11 +22,11 @@ //------------------------------------------------------------------------ #import -#import +#import "ZBarImageScanner.h" @class AVCaptureSession, AVCaptureDevice; @class CALayer; -@class ZBarReaderView, ZBarCaptureReader; +@class ZBarImageScanner, ZBarCaptureReader, ZBarReaderView; // delegate is notified of decode results. @@ -86,7 +86,7 @@ // (default YES). @property (nonatomic) BOOL allowsPinchZoom; -// torch mode to set automatically (default On). +// torch mode to set automatically (default Auto). @property (nonatomic) NSInteger torchMode; // whether to display the frame rate for debug/configuration diff --git a/include/zbar/ZBarReaderViewController.h b/iphone/include/ZBarSDK/ZBarReaderViewController.h similarity index 98% rename from include/zbar/ZBarReaderViewController.h rename to iphone/include/ZBarSDK/ZBarReaderViewController.h index 763c889..cd65a6e 100644 --- a/include/zbar/ZBarReaderViewController.h +++ b/iphone/include/ZBarSDK/ZBarReaderViewController.h @@ -21,7 +21,8 @@ // http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#import +#import +#import "ZBarReaderController.h" @class ZBarReaderView; diff --git a/iphone/include/ZBarSDK/ZBarSDK.h b/iphone/include/ZBarSDK/ZBarSDK.h new file mode 100644 index 0000000..11243b7 --- /dev/null +++ b/iphone/include/ZBarSDK/ZBarSDK.h @@ -0,0 +1,32 @@ +/*------------------------------------------------------------------------ + * Copyright 2010 (c) Jeff Brown + * + * 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 "zbar.h" + +#import "ZBarSymbol.h" +#import "ZBarImage.h" +#import "ZBarImageScanner.h" +#import "ZBarReaderView.h" +#import "ZBarReaderViewController.h" +#import "ZBarReaderController.h" +#import "ZBarCaptureReader.h" diff --git a/include/zbar/ZBarSymbol.h b/iphone/include/ZBarSDK/ZBarSymbol.h similarity index 96% rename from include/zbar/ZBarSymbol.h rename to iphone/include/ZBarSDK/ZBarSymbol.h index cc28ab9..470ce4a 100644 --- a/include/zbar/ZBarSymbol.h +++ b/iphone/include/ZBarSDK/ZBarSymbol.h @@ -21,8 +21,8 @@ // http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#import #import +#import "zbar.h" #ifdef __cplusplus using namespace zbar; @@ -30,7 +30,8 @@ using namespace zbar; // Obj-C wrapper for ZBar result types -@interface ZBarSymbolSet : NSObject +@interface ZBarSymbolSet + : NSObject { const zbar_symbol_set_t *set; BOOL filterSymbols; diff --git a/iphone/config.h b/iphone/include/config.h similarity index 100% rename from iphone/config.h rename to iphone/include/config.h diff --git a/iphone/include/prefix.pch b/iphone/include/prefix.pch new file mode 100644 index 0000000..a7bdae5 --- /dev/null +++ b/iphone/include/prefix.pch @@ -0,0 +1,10 @@ +#ifdef __OBJC__ +# import +# import +# import +# import +# import +# import +# import +# import +#endif diff --git a/iphone/prefix.pch b/iphone/prefix.pch deleted file mode 100644 index aaf5d7d..0000000 --- a/iphone/prefix.pch +++ /dev/null @@ -1,6 +0,0 @@ -#ifdef __OBJC__ -# import -# import -# import -# import -#endif diff --git a/iphone/res/ZBarSDK-Info.plist b/iphone/res/ZBarSDK-Info.plist new file mode 100644 index 0000000..79507be --- /dev/null +++ b/iphone/res/ZBarSDK-Info.plist @@ -0,0 +1,16 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleName + ZBarSDK + CFBundleVersion + 0.1.1 + CFBundleSignature + ???? + NSHumanReadableCopyright + Copyright 2010 © Jeff Brown et al + + diff --git a/iphone/res/ZBarSDK-bg.png b/iphone/res/ZBarSDK-bg.png new file mode 100644 index 0000000000000000000000000000000000000000..5c633ace7cfc63684aed03aa53c71c7b752eb317 GIT binary patch literal 23569 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 j3) + + + + + + + ZBar iPhone SDK DMG Folder Background Image + + + + + + + + + + + + + + + + + + + + + + + Read this first + + + Then drag this + into your + Xcode project + + + + + + diff --git a/iphone/res/ZBarSDK.DS_Store b/iphone/res/ZBarSDK.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..058443cff3c1f22a4f0ae256f1d00e3cbced2a65 GIT binary patch literal 8196 zcmeHKO>YxN7=CA+VuwJygpWcaRaOHC2{1{jRuqIVP7tvYu!SRVXlS%+Pu8ohcdXrY z!iORvap;x5(F0em{Q*6<$F@JAQq^<&%+4gSH{#G+5%WsBPu`jLYo2+%lOZBj9dzc1 z3Uu(;$DsT`RGI)vu@sQh8Ii431BL;^fMLKeU>GnAe83FkRP6h5^IC z$Hf2}TWl^?v1a^}|6Y-E6+9Am6{hBRrS}Bj7>4%+dPyq4ipE`q7=bW-y;=a-R;ZncHDOZ;lkiY zw;%X%GCRBe*bh5myDA1@C*H8nzI^%B-29c&-2C;OD<$>!*I&-=?5sEa4tJgCvENC$ zHhtUdifuhqNR?F~0?a>6ClV(a#8oFsXBtk@#mui{jUCAsSnd-@;q>gS+siAh%}7gvZez5+5T`|T}Vy7lv3=^J)2MisTT2pbXK^7;1ohJDI)+TVMTT+V_BM079W zJe<+NXgzgEc&`?2io$mXwyV$k+_qW?f0i`;7ks92Nx6&!to0m^-wAvtuAg8Rr2*df zLgk-esm;aZy)0Q=x~x8bliKd8>y`VVmo@v(`ah6EP8NNk)7&T@tnWr9brB!nJUyW* zITTTo7HOF#>2o}zV^_%~kIK}i5I9BC*M@>#%LGL&6GPJ^t84k#9z|(G)w*GyJg6(( zqiQhVGq?ZPo1T(eS??#l2;)aQih*c2FY-I}&CQr6Yfl5mU_UnJw4R!ERn3q)K0a^=al3%56N_x1kg;Zdgs zt)a39bnmdWg}vCfK91cMsD3~_#1AP!u7rGyg`=Jfc}6^^-tUPX=^{#xf=mpQJ5p^8Tc0fXG{J7 literal 0 HcmV?d00001 diff --git a/iphone/res/back.png b/iphone/res/zbar-back.png similarity index 100% rename from iphone/res/back.png rename to iphone/res/zbar-back.png diff --git a/iphone/res/back.svg b/iphone/res/zbar-back.svg similarity index 100% rename from iphone/res/back.svg rename to iphone/res/zbar-back.svg diff --git a/iphone/res/zbar-button.png b/iphone/res/zbar-button.png deleted file mode 100644 index 82311746eea90359fbc7addb29aeed006fc075dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2536 zcmVP)A)WY?l1RuHKODm6_@fwYje zqK#EZV&`Gs$M=|-!{Yny_4O<9O>*0+&dkD}{XIPMn{(!zGjm2zR*GkVc`iiDku%NT z2e*aw#UOx?Ni2~_?04jQI{WikwIdI0^x~vS$_bv}%N$__JLbEAtGvyhc!5(Cqs?Cd zw7?n8(Zdl4qG)|vH|S;kyTxKL5=%>BlbF;dahSfm|NQ;^-J1Xs1cPA4M5jPN2~C66 z7vb}KkH?t1sUcAoc#)s;`ry9|0C~=GnnemK9F7pF#i;;cT}xt8L5Y-2GMvUtav;X6>c4*gm3Ue4&5S2Jjajt4dn_T&l{X# zi5`7QDx3*-gt$SY>i|W=UJHgq63Ha9SrjL6BAL%ztGDCd4=p~Rb_9?mB_kmw!eVX! zP{8A;D9I`CBllvy&r?j@LS^mpV}42r5ddd7#br8l=uuGOTA{6}rWhcsk=aP>Nbf9G zQb|n~WpSL?)aBi*TTtyi-A}vsk380*O^cL-sF9)ZRIHXCM@d11p+AD?o3|JbOz{I2 z_;n3vfzvF};VK=v^eJPvH|%2<j_{mekscj7EYYD)vCn;$ zyUlK!nYs@mBY=j#4G>w0Z5Aiis0-cle6^g1s;8IC(t@7hOSRCEkqu>Npk(6$suirj zpv`p!Bz%X%6S0Yh_%7dySYV!#oIc%J$&%t|IAQNec9|5Zg=R=(^;M0_m^e<_(h6~3 zE>(Fc+I0)E9Q%xU7MfW-X%Mx@8YR0iKqUs6s~Cs!2#-z7ZTKpWM9kBpq97-yPmf+y z9MJodd*T@zC1PZaxo#LWHVgr=HZwbDSJEwgKkeoIykCrci;5oeBi1V=B_k!h2|%@3 zttg0z5R}Kcb7Fw*(bGUZ%t)op3B`PuVVjV1W)6IDZX5 zqw-ZpliLW83|9=zrYjJ#2G=LA7;cx_fNlf24d`PDXhFxFc6ECJ`U8u@C77)hx4q2# z2RyIKa(Ikr&}rCCfMA}JdXRhMFv%9wCuo;#1_IwavrBJ#x_QjIzYU1>H~t&-DO-QfcNrmzCA^Lj^RtUuCc;9?0 zmY2+b=!n{pFRg%XYFqcqUD3`o%OuLR>-xdzwS`U)30j8O7j!}uMt0l=ko-h<#(YFP z1T)wau2aiooH6>|n9MGDt57DCQdJk{b>*hKPh@_?>$HeHsXOy!HFSy?U43lT4>J zQ5z#wjMEh&4ImvAry5WyNzUQ1A& z1(Y_JA|mbt6d$`o{?mH5?6te2)PnQQB`#D}*D9FET8RoOzE!o|RB1|IP&P>xgBG5g zD4>%O2ly8;X_MgO0ZV+tfKuAD8cZ>54#2EV`@`Wt*sXKAQ(MmDzVgABzVJQ_t+&XU zpH2F)q6Dv{$!$*2BybiZxvszC$%$nMUEqa?IS#N$MvJn+lZ=edcz|M3T1+$5WRe|V z4qlT#>V=>hhb**;sN;%~zVEqyRfI6iMqZW4h9E;xQc7PqSA>F+l7c=tIVBYeyuyn- zIUzv5=amS{QRXSBhIs1h@c~(45?V|#%`|OhIf{jY`nbHwq833*dd_>vwdZ@jABx~r zo6LmKc}G^IA}N&?&N(Tg%9l;LU`|f$7?u2zuS_IM@qK7uzEdhq`5(S8l~9Uc54XXny0N~ yB}$Vf&(-<(T48<43BJaoH*p;5B+sut4)uR}aFtHNr&qNA0000 -# import -# import -#endif From 4ea3377dfaa5d3d175e18fce7f1e9bb9ca941827 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 19 Aug 2010 11:31:56 -0400 Subject: [PATCH 226/328] Added tag iPhoneSDK-0.1 for changeset b21098d27ff8 From 39cb37fa69204990ea16eeb40166de426a668bff Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 19 Aug 2010 11:41:56 -0400 Subject: [PATCH 227/328] Added tag iPhoneSDK-0.1.1 for changeset b0bda6247b2f From 225d242fbd236d4e6bdb34d833d68caeb127cbbf Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 24 Aug 2010 12:50:30 -0400 Subject: [PATCH 228/328] workaround iPhone quartz access past image data --- iphone/ZBarCVImage.m | 9 ++++++--- iphone/ZBarReaderView.m | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/iphone/ZBarCVImage.m b/iphone/ZBarCVImage.m index 86c1a75..63065dd 100644 --- a/iphone/ZBarCVImage.m +++ b/iphone/ZBarCVImage.m @@ -34,8 +34,9 @@ ZBarCVImage *image = info; assert(image); [image waitUntilConverted]; - assert(image.rgbBuffer); - return(image.rgbBuffer); + void *buf = image.rgbBuffer; + assert(buf); + return(buf); } static const CGDataProviderDirectCallbacks asyncProvider = { @@ -147,7 +148,9 @@ - (void) convertCVtoRGB goto error; int datalen = 3 * w * h; - uint8_t *pdst = rgbBuffer = malloc(datalen); + // 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 diff --git a/iphone/ZBarReaderView.m b/iphone/ZBarReaderView.m index 5cb22ee..680af6b 100644 --- a/iphone/ZBarReaderView.m +++ b/iphone/ZBarReaderView.m @@ -161,7 +161,7 @@ - (void) resetTracking CGSize size = overlay.bounds.size; CGRect crop = zoomCrop; tracking.frame = CGRectMake(crop.origin.x * size.width, - crop.origin.y * size.width, + crop.origin.y * size.height, crop.size.width * size.width, crop.size.height * size.height); tracking.opacity = 0; From 22551f8fd3926e1dc4b26153dd0ccc7c90929c94 Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 25 Aug 2010 21:17:39 -0400 Subject: [PATCH 229/328] iPhone: fix initial zoom crop (performance bug) --- iphone/ZBarReaderViewImpl_Capture.m | 1 + 1 file changed, 1 insertion(+) diff --git a/iphone/ZBarReaderViewImpl_Capture.m b/iphone/ZBarReaderViewImpl_Capture.m index e3f5c93..47a3097 100644 --- a/iphone/ZBarReaderViewImpl_Capture.m +++ b/iphone/ZBarReaderViewImpl_Capture.m @@ -74,6 +74,7 @@ - (id) initWithImageScanner: (ZBarImageScanner*) scanner context: NULL]; [self initSubviews]; + [self cropUpdate]; return(self); } From c8cbdb36c69835453636a266546bcc26b6643eb0 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 26 Aug 2010 08:34:45 -0400 Subject: [PATCH 230/328] iPhone: force controls to front when showsZBarControls is enabled --- iphone/ChangeLog | 1 + iphone/ZBarReaderViewController.m | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index d45c015..0e552bc 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,5 @@ current: + * force controls to front when showsZBarControls is enabled * fix initial zoom crop (performance bug) * workaround iPhone quartz access past image data diff --git a/iphone/ZBarReaderViewController.m b/iphone/ZBarReaderViewController.m index 67be8b4..756f9fc 100644 --- a/iphone/ZBarReaderViewController.m +++ b/iphone/ZBarReaderViewController.m @@ -102,10 +102,16 @@ - (void) initControls [controls release]; controls = nil; } - if(!showsZBarControls || controls) + 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; @@ -145,7 +151,7 @@ - (void) initControls forControlEvents: UIControlEventTouchUpInside]; [controls addSubview: info]; - [self.view addSubview: controls]; + [view addSubview: controls]; } - (void) initSimulator @@ -174,14 +180,14 @@ - (void) viewDidLoad readerView.enableCache = enableCache; [view addSubview: readerView]; - [self initControls]; - [self initSimulator]; - if(cameraOverlayView) { assert(!cameraOverlayView.superview); [cameraOverlayView removeFromSuperview]; - [self.view addSubview: cameraOverlayView]; + [view addSubview: cameraOverlayView]; } + + [self initControls]; + [self initSimulator]; } - (void) viewDidUnload From 6c61c4ecf1b6818684361d73b0e9c03946d31992 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 26 Aug 2010 18:23:59 -0400 Subject: [PATCH 231/328] doc enhancements --- iphone/ChangeLog | 1 + iphone/doc/install.rst | 16 ++- iphone/doc/optimizing.rst | 153 +++++++++++++++++++----- iphone/examples/readertest/readertest.m | 2 +- 4 files changed, 135 insertions(+), 37 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 0e552bc..3fb99ea 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,5 @@ current: + * doc enhancements * force controls to front when showsZBarControls is enabled * fix initial zoom crop (performance bug) * workaround iPhone quartz access past image data diff --git a/iphone/doc/install.rst b/iphone/doc/install.rst index 2b18ecc..582878c 100644 --- a/iphone/doc/install.rst +++ b/iphone/doc/install.rst @@ -45,18 +45,22 @@ Xcode project: 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. + checking the box. The target that you want to link with the library should + also be selected in the target list. 4. 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.1: - * AVFoundation.framework (weak) - * CoreMedia.framework (weak) - * CoreVideo.framework (weak) - * QuartzCore.framework - * libiconv.dylib + * :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 along with :file:`libzbar.a`. 5. Import the SDK header from your prefix header to make the barcode reader APIs available:: diff --git a/iphone/doc/optimizing.rst b/iphone/doc/optimizing.rst index c85b9c1..934e80a 100644 --- a/iphone/doc/optimizing.rst +++ b/iphone/doc/optimizing.rst @@ -75,7 +75,8 @@ 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 12-15fps. +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 @@ -109,19 +110,20 @@ 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 from optimal, 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, noise can interfere with the edge detection and images will take -longer to process. +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. You can change this using the capture -:member:`~ZBarReaderView::session` preset. +for most applications. On the iPhone 4, you can increase this using a capture +:member:`~ZBarReaderView::session` preset. The iPhone 3GS does not have a +higher resolution option available. For scanning images, you can use :member:`~ZBarReaderController::maxScanDimension` to control the scaled size @@ -302,43 +304,134 @@ scanning context, etc... Examples -------- -You can try these examples yourself using the readertest. For each example, -start with the default settings (by tapping the ZBarReaderViewController -class) and enable the custom overlay and continuous mode. +These examples demonstrate several scenarios for scanning from the camera with +automatic capture using iOS 4. 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 -room with "average" light level (whatever that means). Two measurements are -taken for each case: the rate with the camera pointed at a blank white page -such that it fills the image, and the rate while decoding the provided -example. +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 ?/? for [this -linear symbol] and ?/? for [this QR symbol]. +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 ^^^^^^^^^^^^^^^^^^^ -To scan the longest symbol possible, we want to maximize resolution and scan -the longest image axis. [Here is a barcode] you can use for testing. +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. -We can compensate for the reduction this causes in the frame rate by: +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. -* cropping the image to a long, skinny rectangle -* disabling scans across the short image axis -* reducing the density +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 an iPhone 4, you may also try increasing the resolution to support +even longer symbols (NB there is no readertest setting for resolution). You +may have to compensate elsewhere to bring the frame rate back to a reasonable +level. High Density QR Symbols ^^^^^^^^^^^^^^^^^^^^^^^ -In this case we also want to maximize the resolution. +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 -* crop to square -* reduce density +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 (NB there is no readertest setting for resolution). +You may have to compensate elsewhere to bring the frame rate back to a +reasonable level. Small DataBar Symbols ^^^^^^^^^^^^^^^^^^^^^ -Again we want high resolution scans, but this time we also want high density -passes in both directions. +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) -* zoom/crop, also helps user see barcode +The reader should now be very sensitive to DataBar, even when scanned at an +angle. diff --git a/iphone/examples/readertest/readertest.m b/iphone/examples/readertest/readertest.m index 3ef6ee4..a697cf9 100644 --- a/iphone/examples/readertest/readertest.m +++ b/iphone/examples/readertest/readertest.m @@ -25,7 +25,7 @@ static const CGRect const crop_choices[] = { { { 0, 0 }, { 1, 1 } }, - { { .25, 0 }, { .5, 1 } }, + { { .125, 0 }, { .75, 1 } }, { { 0, .3 }, { 1, .4 } }, { { 0, 0 }, { 0, 0 } } }; From 59cdd3e211305ba55a7c4e7caf3a4872d016f68f Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 26 Aug 2010 18:28:48 -0400 Subject: [PATCH 232/328] iPhone: fix missing header dependency --- iphone/ChangeLog | 1 + iphone/include/ZBarSDK/ZBarSymbol.h | 1 + 2 files changed, 2 insertions(+) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 3fb99ea..d204c0e 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,5 @@ current: + * fix missing header dependency * doc enhancements * force controls to front when showsZBarControls is enabled * fix initial zoom crop (performance bug) diff --git a/iphone/include/ZBarSDK/ZBarSymbol.h b/iphone/include/ZBarSDK/ZBarSymbol.h index 470ce4a..900312d 100644 --- a/iphone/include/ZBarSDK/ZBarSymbol.h +++ b/iphone/include/ZBarSDK/ZBarSymbol.h @@ -22,6 +22,7 @@ //------------------------------------------------------------------------ #import +#import #import "zbar.h" #ifdef __cplusplus From 16821b9570b58d1e8d0e714d413c25f9fd022d64 Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 28 Aug 2010 11:26:36 -0400 Subject: [PATCH 233/328] iPhone: bump SDK version --- iphone/ChangeLog | 2 +- iphone/bin/CreateDSStore.pl | 2 +- iphone/res/ZBarSDK-Info.plist | 2 +- iphone/res/ZBarSDK.DS_Store | Bin 8196 -> 8196 bytes 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index d204c0e..7c6d7fd 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,4 @@ -current: +version 0.1.2: * fix missing header dependency * doc enhancements * force controls to front when showsZBarControls is enabled diff --git a/iphone/bin/CreateDSStore.pl b/iphone/bin/CreateDSStore.pl index d4ec627..7e52fd4 100755 --- a/iphone/bin/CreateDSStore.pl +++ b/iphone/bin/CreateDSStore.pl @@ -46,7 +46,7 @@ BEGIN gridOffsetX => [real => 0], gridOffsetY => [real => 0], showItemInfo => [false => 0], - showIconPreview => [true => 1], + showIconPreview => [false => 0], backgroundType => [integer => 2], backgroundColorRed => [real => 0], backgroundColorGreen => [real => 0], diff --git a/iphone/res/ZBarSDK-Info.plist b/iphone/res/ZBarSDK-Info.plist index 79507be..726d35d 100644 --- a/iphone/res/ZBarSDK-Info.plist +++ b/iphone/res/ZBarSDK-Info.plist @@ -7,7 +7,7 @@ CFBundleName ZBarSDK CFBundleVersion - 0.1.1 + 0.1.2 CFBundleSignature ???? NSHumanReadableCopyright diff --git a/iphone/res/ZBarSDK.DS_Store b/iphone/res/ZBarSDK.DS_Store index 058443cff3c1f22a4f0ae256f1d00e3cbced2a65..6e71b2f4e8aa91b36e4a25535611f49c4e466a9a 100644 GIT binary patch delta 97 zcmV-n0G|JZK!iZB^AG_Dlk^ZRvmz130Rah<=n_jq1qTTW4G$3#6c!g50RsUB2nq}i z5Canx0~iAU2ml%Y8vrr@I{-)kR{&W6VgPFZf&r`nwE?~X)B)WA@&WV$00IuPb`y>a D|B@8C delta 97 zcmV-n0G|JZK!iZB^AG_Elk^ZR0SL1p5yka D_Zk%c From eecf6bba001c521b01c057d7894ed11cb28e071f Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 28 Aug 2010 11:27:03 -0400 Subject: [PATCH 234/328] Added tag iPhoneSDK-0.1.2 for changeset d1655a680c3d From ef091d96547c72612ba59950ff55b7be1404948b Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 30 Aug 2010 11:49:51 -0400 Subject: [PATCH 235/328] iPhone: fix camera simulation gesture --- iphone/ChangeLog | 3 +++ iphone/ZBarReaderViewImpl_Simulator.m | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 7c6d7fd..e5abb08 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,3 +1,6 @@ +current: + * fix camera simulation gesture + version 0.1.2: * fix missing header dependency * doc enhancements diff --git a/iphone/ZBarReaderViewImpl_Simulator.m b/iphone/ZBarReaderViewImpl_Simulator.m index 3768e98..2fc7607 100644 --- a/iphone/ZBarReaderViewImpl_Simulator.m +++ b/iphone/ZBarReaderViewImpl_Simulator.m @@ -39,7 +39,7 @@ - (void) initSimulator UILongPressGestureRecognizer *press = [[UILongPressGestureRecognizer alloc] initWithTarget: self - action: @selector(takePicture)]; + action: @selector(didLongPress:)]; [self.view addGestureRecognizer: press]; press.numberOfTouchesRequired = 2; [press release]; @@ -56,6 +56,12 @@ - (void) takePicture [picker release]; } +- (void) didLongPress: (UIGestureRecognizer*) press +{ + if(press.state == UIGestureRecognizerStateBegan) + [self takePicture]; +} + - (void) imagePickerController: (UIImagePickerController*) picker didFinishPickingMediaWithInfo: (NSDictionary*) info { From 907aa816b25ccf8a711541b2f8f85cb28954771f Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 31 Aug 2010 15:52:49 -0400 Subject: [PATCH 236/328] update zbarimg MagickExportImagePixels workaround --- zbarimg/zbarimg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zbarimg/zbarimg.c b/zbarimg/zbarimg.c index 26cbfef..9b2e320 100644 --- a/zbarimg/zbarimg.c +++ b/zbarimg/zbarimg.c @@ -45,7 +45,7 @@ * how does MagickGetAuthenticImagePixels fit in?) * ref http://bugs.gentoo.org/247292 */ -#if MagickLibVersion < 0x645 +#if MagickLibVersion <= 0x645 # define MagickExportImagePixels MagickGetImagePixels #endif From 10ed72d84009de19c451d60736c97e7f0408e68c Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 19 Sep 2010 12:54:08 -0400 Subject: [PATCH 237/328] add support for Code 93 symbology --- ChangeLog | 1 + Makefile.am | 7 +- README.windows | 2 +- configure.ac | 5 +- doc/ref/commonoptions.xml | 2 +- doc/ref/zbarcam.xml | 4 +- doc/ref/zbarimg.xml | 4 +- include/zbar.h | 1 + iphone/config.h | 3 + iphone/res/zbar-help.html | 2 +- iphone/zbar.xcodeproj/project.pbxproj | 8 + java/net/sourceforge/zbar/Symbol.java | 2 + perl/README | 4 +- perl/ZBar.xs | 1 + perl/ZBar/Symbol.pod | 2 + python/Makefile.am.inc | 3 +- python/README | 4 +- python/test/test_zbar.py | 1 + python/zbarmodule.c | 1 + test/iphone/readertest.m | 2 +- test/test_decode.c | 189 ++++++++++-- zbar.spec.in | 28 +- zbar/Makefile.am.inc | 3 + zbar/config.c | 2 + zbar/decoder.c | 33 ++- zbar/decoder.h | 7 + zbar/decoder/code93.c | 397 ++++++++++++++++++++++++++ zbar/decoder/code93.h | 49 ++++ zbar/img_scanner.c | 9 +- zbar/symbol.c | 20 +- zbar/symbol.h | 4 + zbarimg/zbarimg.c | 23 +- 32 files changed, 751 insertions(+), 72 deletions(-) create mode 100644 zbar/decoder/code93.c create mode 100644 zbar/decoder/code93.h diff --git a/ChangeLog b/ChangeLog index 392cb81..fbb092f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * add support for Code 93 symbology * add video size request to (Py)GTK widget (req #3034522) - thanks to Jerome Charaoui for the patch! * workaround for iPhone simulator builds diff --git a/Makefile.am b/Makefile.am index d7fbd0e..e18499a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -49,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 \ diff --git a/README.windows b/README.windows index e7c547b..2dc4381 100644 --- a/README.windows +++ b/README.windows @@ -3,7 +3,7 @@ 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, +sensors. It supports EAN-13/UPC-A, UPC-E, EAN-8, Code 128, Code 93, 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 developers, language diff --git a/configure.ac b/configure.ac index 2be845f..4407935 100644 --- a/configure.ac +++ b/configure.ac @@ -107,9 +107,9 @@ dnl symbologies AC_ARG_ENABLE([codes], [AS_HELP_STRING([--enable-codes=SYMS], - [select symbologies to compile [default=ean,databar,code128,code39,i25,qrcode]])], + [select symbologies to compile [default=ean,databar,code128,code93,code39,i25,qrcode]])], [], - [enable_codes="ean,databar,code128,code39,i25,qrcode"]) + [enable_codes="ean,databar,code128,code93,code39,i25,qrcode"]) AC_DEFUN([ZBAR_CHK_CODE], [ AC_MSG_CHECKING([whether to build $2]) @@ -129,6 +129,7 @@ AC_DEFUN([ZBAR_CHK_CODE], [ 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([i25], [Interleaved 2 of 5 symbology]) ZBAR_CHK_CODE([qrcode], [QR Code]) diff --git a/doc/ref/commonoptions.xml b/doc/ref/commonoptions.xml index 8b77bb6..749abcb 100644 --- a/doc/ref/commonoptions.xml +++ b/doc/ref/commonoptions.xml @@ -47,7 +47,7 @@ , , , , , , - , , + , , , , or the special value . If symbology is diff --git a/doc/ref/zbarcam.xml b/doc/ref/zbarcam.xml index 69f5ff2..439aeb1 100644 --- a/doc/ref/zbarcam.xml +++ b/doc/ref/zbarcam.xml @@ -61,8 +61,8 @@ The underlying library currently supports EAN-13 (including UPC and ISBN subsets), EAN-8, DataBar, DataBar Expanded, Code 128, - Code 39, Interleaved 2 of 5 and QR Code symbologies. The specific - type of each detected symbol is printed with the decoded + Code 93, Code 39, Interleaved 2 of 5 and QR Code symbologies. The + specific type of each detected symbol is printed with the decoded data. diff --git a/doc/ref/zbarimg.xml b/doc/ref/zbarimg.xml index d1c664f..ccc5d0e 100644 --- a/doc/ref/zbarimg.xml +++ b/doc/ref/zbarimg.xml @@ -60,8 +60,8 @@ The underlying library currently supports EAN-13 (including UPC and ISBN subsets), EAN-8, DataBar, DataBar Expanded, Code 128, - Code 39, Interleaved 2 of 5 and QR Code symbologies. The specific - type of each detected symbol is printed with the decoded + Code 93, Code 39, Interleaved 2 of 5 and QR Code symbologies. The + specific type of each detected symbol is printed with the decoded data. Note that "image" diff --git a/include/zbar.h b/include/zbar.h index c71327f..84c5faa 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -98,6 +98,7 @@ typedef enum zbar_symbol_type_e { 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 */ diff --git a/iphone/config.h b/iphone/config.h index 181c971..2b337f5 100644 --- a/iphone/config.h +++ b/iphone/config.h @@ -3,6 +3,9 @@ /* 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 diff --git a/iphone/res/zbar-help.html b/iphone/res/zbar-help.html index a5d17b3..6c0e9f7 100644 --- a/iphone/res/zbar-help.html +++ b/iphone/res/zbar-help.html @@ -41,7 +41,7 @@

Barcode Reader Help

QR Codes

-

Also Code 128 and Code 39 (not shown)

+

Also recognized, but not shown: Code 128, Code 93 and Code 39


Hints for successful scanning

diff --git a/iphone/zbar.xcodeproj/project.pbxproj b/iphone/zbar.xcodeproj/project.pbxproj index 5bd4660..75ce9e4 100644 --- a/iphone/zbar.xcodeproj/project.pbxproj +++ b/iphone/zbar.xcodeproj/project.pbxproj @@ -67,6 +67,8 @@ DC67C1C310A07B6B0033B702 /* ZBarReaderController.m in Sources */ = {isa = PBXBuildFile; fileRef = DC67C1BF10A07B6B0033B702 /* ZBarReaderController.m */; }; DC67C1C410A07B6B0033B702 /* ZBarSymbol.m in Sources */ = {isa = PBXBuildFile; fileRef = DC67C1C010A07B6B0033B702 /* ZBarSymbol.m */; }; DC67C1CC10A07BEE0033B702 /* svg.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67C1CB10A07BEE0033B702 /* svg.h */; }; + DCC097631242BFE000C9FAEB /* code93.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC097611242BFE000C9FAEB /* code93.c */; }; + DCC097641242BFE000C9FAEB /* code93.h in Headers */ = {isa = PBXBuildFile; fileRef = DCC097621242BFE000C9FAEB /* code93.h */; }; DCDC6E3011ADCA8E00021380 /* ZBarReaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = DCDC6E2F11ADCA8E00021380 /* ZBarReaderView.m */; }; DCDC6E3911ADCB7700021380 /* ZBarReaderView.h in Headers */ = {isa = PBXBuildFile; fileRef = DCDC6E3811ADCB7700021380 /* ZBarReaderView.h */; }; DCDC713711B1628200021380 /* ZBarReaderViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = DCDC713611B1628200021380 /* ZBarReaderViewController.h */; }; @@ -138,6 +140,8 @@ DC67C1BF10A07B6B0033B702 /* ZBarReaderController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarReaderController.m; sourceTree = ""; }; DC67C1C010A07B6B0033B702 /* ZBarSymbol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarSymbol.m; sourceTree = ""; }; DC67C1CB10A07BEE0033B702 /* svg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = svg.h; sourceTree = ""; }; + DCC097611242BFE000C9FAEB /* code93.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = code93.c; sourceTree = ""; }; + DCC097621242BFE000C9FAEB /* code93.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = code93.h; sourceTree = ""; }; DCDC6E2F11ADCA8E00021380 /* ZBarReaderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarReaderView.m; sourceTree = ""; }; DCDC6E3811ADCB7700021380 /* ZBarReaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ZBarReaderView.h; path = ../include/zbar/ZBarReaderView.h; sourceTree = SOURCE_ROOT; }; DCDC713611B1628200021380 /* ZBarReaderViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ZBarReaderViewController.h; path = ../include/zbar/ZBarReaderViewController.h; sourceTree = SOURCE_ROOT; }; @@ -248,6 +252,8 @@ DCF5C9AC11EA3AD100E7DC21 /* databar.h */, DC67C12310A07AD30033B702 /* code128.c */, DC67C12410A07AD30033B702 /* code128.h */, + DCC097611242BFE000C9FAEB /* code93.c */, + DCC097621242BFE000C9FAEB /* code93.h */, DC67C12510A07AD30033B702 /* code39.c */, DC67C12610A07AD30033B702 /* code39.h */, DC67C12710A07AD30033B702 /* ean.c */, @@ -320,6 +326,7 @@ DCDC713711B1628200021380 /* ZBarReaderViewController.h in Headers */, DC3AAB4E11B71A040021C7B1 /* ZBarCVImage.h in Headers */, DCF5C9AE11EA3AD100E7DC21 /* databar.h in Headers */, + DCC097641242BFE000C9FAEB /* code93.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -398,6 +405,7 @@ DCF5C9AD11EA3AD100E7DC21 /* databar.c in Sources */, DC3CE47811FA1622008FAF88 /* ZBarReaderViewImpl_Capture.m in Sources */, DC3CE47911FA1622008FAF88 /* ZBarReaderViewImpl_Simulator.m in Sources */, + DCC097631242BFE000C9FAEB /* code93.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/java/net/sourceforge/zbar/Symbol.java b/java/net/sourceforge/zbar/Symbol.java index 19d349e..8445a84 100644 --- a/java/net/sourceforge/zbar/Symbol.java +++ b/java/net/sourceforge/zbar/Symbol.java @@ -53,6 +53,8 @@ public class Symbol public static final int DATABAR = 34; /** DataBar Expanded. */ public static final int DATABAR_EXP = 35; + /** Code 93. */ + public static final int CODE93 = 93; /** Code 39. */ public static final int CODE39 = 39; /** PDF417. */ diff --git a/perl/README b/perl/README index f6c4e82..c5a3427 100644 --- a/perl/README +++ b/perl/README @@ -4,8 +4,8 @@ Barcode::ZBar Perl module 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. These are the Perl bindings -for the library. +Code 93, Code 39, Interleaved 2 of 5 and QR Code. These are the Perl +bindings for the library. Check the ZBar project home page for the latest release, mailing lists, etc. diff --git a/perl/ZBar.xs b/perl/ZBar.xs index 6040fe6..8a537ba 100644 --- a/perl/ZBar.xs +++ b/perl/ZBar.xs @@ -322,6 +322,7 @@ BOOT: CONSTANT(symbol_type, , CODE39, zbar_get_symbol_name(ZBAR_CODE39)); CONSTANT(symbol_type, , PDF417, zbar_get_symbol_name(ZBAR_PDF417)); CONSTANT(symbol_type, , QRCODE, zbar_get_symbol_name(ZBAR_QRCODE)); + CONSTANT(symbol_type, , CODE93, zbar_get_symbol_name(ZBAR_CODE93)); CONSTANT(symbol_type, , CODE128, zbar_get_symbol_name(ZBAR_CODE128)); } diff --git a/perl/ZBar/Symbol.pod b/perl/ZBar/Symbol.pod index 7e37f5c..6a0eec3 100644 --- a/perl/ZBar/Symbol.pod +++ b/perl/ZBar/Symbol.pod @@ -128,6 +128,8 @@ Bar code type "symbology" constants: =item CODE39 +=item CODE93 + =item CODE128 =item QRCODE diff --git a/python/Makefile.am.inc b/python/Makefile.am.inc index ac12c03..e5ca123 100644 --- a/python/Makefile.am.inc +++ b/python/Makefile.am.inc @@ -9,4 +9,5 @@ python_zbar_la_SOURCES = python/zbarmodule.c python/zbarmodule.h \ python/symboliter.c python/image.c \ python/processor.c python/imagescanner.c python/decoder.c python/scanner.c -EXTRA_DIST += python/test/barcode.png python/test/test_zbar.py +EXTRA_DIST += python/test/barcode.png python/test/test_zbar.py \ + python/examples/processor.py python/examples/read_one.py diff --git a/python/README b/python/README index ba36228..62313f4 100644 --- a/python/README +++ b/python/README @@ -5,8 +5,8 @@ zbar -- read barcodes from images or video 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. These are the Python -bindings for the library. +Code 93, Code 39, Interleaved 2 of 5 and QR Code. These are the +Python bindings for the library. Check the ZBar project home page for the latest release, mailing lists, etc. diff --git a/python/test/test_zbar.py b/python/test/test_zbar.py index bee44fb..42dddbd 100755 --- a/python/test/test_zbar.py +++ b/python/test/test_zbar.py @@ -85,6 +85,7 @@ def test_symbologies(self): zbar.Symbol.CODE39, zbar.Symbol.PDF417, zbar.Symbol.QRCODE, + zbar.Symbol.CODE93, zbar.Symbol.CODE128): self.assert_(isinstance(sym, zbar.EnumItem)) self.assert_(int(sym) >= 0) diff --git a/python/zbarmodule.c b/python/zbarmodule.c index cebacf9..d3ac2b1 100644 --- a/python/zbarmodule.c +++ b/python/zbarmodule.c @@ -58,6 +58,7 @@ static const enumdef symbol_defs[] = { { "CODE39", ZBAR_CODE39 }, { "PDF417", ZBAR_PDF417 }, { "QRCODE", ZBAR_QRCODE }, + { "CODE93", ZBAR_CODE93 }, { "CODE128", ZBAR_CODE128 }, { NULL, } }; diff --git a/test/iphone/readertest.m b/test/iphone/readertest.m index 75d3bb8..7f0ab7b 100644 --- a/test/iphone/readertest.m +++ b/test/iphone/readertest.m @@ -329,7 +329,7 @@ - (void) initControlCells nil]]; static const int symbolValues[] = { - ZBAR_QRCODE, ZBAR_CODE128, ZBAR_CODE39, ZBAR_I25, + ZBAR_QRCODE, ZBAR_CODE128, ZBAR_CODE93, ZBAR_CODE39, ZBAR_I25, ZBAR_DATABAR, ZBAR_DATABAR_EXP, ZBAR_EAN13, ZBAR_EAN8, ZBAR_UPCA, ZBAR_UPCE, ZBAR_ISBN13, ZBAR_ISBN10, 0 diff --git a/test/test_decode.c b/test/test_decode.c index a887cc7..d660860 100644 --- a/test/test_decode.c +++ b/test/test_decode.c @@ -48,6 +48,12 @@ int iter = 0; /* test iteration */ } \ } while(0) +static inline void print_sep (int level) +{ + zprintf(level, + "----------------------------------------------------------\n"); +} + static void symbol_handler (zbar_decoder_t *decoder) { zbar_symbol_type_t sym = zbar_decoder_get_type(decoder); @@ -172,7 +178,7 @@ static const unsigned int code128[107] = { static void encode_code128b (char *data) { assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); - zprintf(3, "----------------------------------------------------------\n"); + print_sep(3); zprintf(2, "CODE-128(B): %s\n", data); zprintf(3, " encode START_B: %02x", START_B); encode(code128[START_B], 0); @@ -187,13 +193,13 @@ static void encode_code128b (char *data) encode(code128[chk], 0); zprintf(3, " encode STOP: %02x", STOP); encode(code128[STOP], 0); - zprintf(3, "----------------------------------------------------------\n"); + print_sep(3); } static void encode_code128c (char *data) { assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); - zprintf(3, "----------------------------------------------------------\n"); + print_sep(3); zprintf(2, "CODE-128(C): %s\n", data); zprintf(3, " encode START_C: %02x", START_C); encode(code128[START_C], 0); @@ -211,7 +217,146 @@ static void encode_code128c (char *data) encode(code128[chk], 0); zprintf(3, " encode STOP: %02x", STOP); encode(code128[STOP], 0); - zprintf(3, "----------------------------------------------------------\n"); + print_sep(3); +} + +/*------------------------------------------------------------*/ +/* Code 93 encoding */ + +#define CODE93_START_STOP 0x2f + +static const unsigned int code93[47 + 1] = { + 0x131112, 0x111213, 0x111312, 0x111411, /* 00 */ + 0x121113, 0x121212, 0x121311, 0x111114, + 0x131211, 0x141111, 0x211113, 0x211212, /* 08 */ + 0x211311, 0x221112, 0x221211, 0x231111, + 0x112113, 0x112212, 0x112311, 0x122112, /* 10 */ + 0x132111, 0x111123, 0x111222, 0x111321, + 0x121122, 0x131121, 0x212112, 0x212211, /* 18 */ + 0x211122, 0x211221, 0x221121, 0x222111, + 0x112122, 0x112221, 0x122121, 0x123111, /* 20 */ + 0x121131, 0x311112, 0x311211, 0x321111, + 0x112131, 0x113121, 0x211131, 0x121221, /* 28 */ + 0x312111, 0x311121, 0x122211, + 0x111141, /* START/STOP (2f) */ +}; + +#define S1 0x2b00| +#define S2 0x2c00| +#define S3 0x2d00| +#define S4 0x2e00| + +static const unsigned short code93_ext[0x80] = { + S2'U', S1'A', S1'B', S1'C', S1'D', S1'E', S1'F', S1'G', + S1'H', S1'I', S1'J', S1'K', S1'L', S1'M', S1'N', S1'O', + S1'P', S1'Q', S1'R', S1'S', S1'T', S1'U', S1'V', S1'W', + S1'X', S1'Y', S1'Z', S2'A', S2'B', S2'C', S2'D', S2'E', + 0x26, S3'A', S3'B', S3'C', 0x27, 0x2a, S3'F', S3'G', + S3'H', S3'I', S3'J', 0x29, S3'L', 0x24, 0x25, 0x28, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, S3'Z', S2'F', S2'G', S2'H', S2'I', S2'J', + S2'V', 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, S2'K', S2'L', S2'M', S2'N', S2'O', + S2'W', S4'A', S4'B', S4'C', S4'D', S4'E', S4'F', S4'G', + S4'H', S4'I', S4'J', S4'K', S4'L', S4'M', S4'N', S4'O', + S4'P', S4'Q', S4'R', S4'S', S4'T', S4'U', S4'V', S4'W', + S4'X', S4'Y', S4'Z', S2'P', S2'Q', S2'R', S2'S', S2'T', +}; + +#undef S1 +#undef S2 +#undef S3 +#undef S4 + +static void encode_char93 (unsigned char c, + int dir) +{ + unsigned ext = code93_ext[c]; + unsigned shift = ext >> 8; + assert(shift < 0x30); + c = ext & 0xff; + if(shift) { + assert(c < 0x80); + c = code93_ext[c]; + } + assert(c < 0x30); + + if(shift) { + encode(code93[(dir) ? shift : c], dir ^ 1); + encode(code93[(dir) ? c : shift], dir ^ 1); + } + else + encode(code93[c], dir ^ 1); +} + +static void encode_code93 (char *data, + int dir) +{ + assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); + print_sep(3); + + /* calculate checksums */ + int i, j, chk_c = 0, chk_k = 0, n = 0; + for(i = 0; data[i]; i++, n++) { + unsigned c = data[i], ext; + assert(c < 0x80); + ext = code93_ext[c]; + n += ext >> 13; + } + + for(i = 0, j = 0; data[i]; i++, j++) { + unsigned ext = code93_ext[(unsigned)data[i]]; + unsigned shift = ext >> 8; + unsigned c = ext & 0xff; + if(shift) { + chk_c += shift * (((n - 1 - j) % 20) + 1); + chk_k += shift * (((n - j) % 15) + 1); + j++; + c = code93_ext[c]; + } + chk_c += c * (((n - 1 - j) % 20) + 1); + chk_k += c * (((n - j) % 15) + 1); + } + chk_c %= 47; + chk_k += chk_c; + chk_k %= 47; + + zprintf(2, "CODE-93: %s (n=%x C=%02x K=%02x)\n", data, n, chk_c, chk_k); + encode(0xa, 0); /* leading quiet */ + + zprintf(3, " encode %s:", (dir) ? "START" : "STOP"); + if(!dir) + encode(0x1, REV); + encode(code93[CODE93_START_STOP], dir ^ 1); + if(!dir) { + zprintf(3, " encode checksum (K): %02x", chk_k); + encode(code93[chk_k], REV ^ 1); + zprintf(3, " encode checksum (C): %02x", chk_c); + encode(code93[chk_c], REV ^ 1); + } + + n = strlen(data); + for(i = 0; i < n; i++) { + unsigned char c = data[(dir) ? i : (n - i - 1)]; + zprintf(3, " encode '%c':", c); + encode_char93(c, dir); + } + + if(dir) { + zprintf(3, " encode checksum (C): %02x", chk_c); + encode(code93[chk_c], FWD ^ 1); + zprintf(3, " encode checksum (K): %02x", chk_k); + encode(code93[chk_k], FWD ^ 1); + } + zprintf(3, " encode %s:", (dir) ? "STOP" : "START"); + encode(code93[CODE93_START_STOP], dir ^ 1); + if(dir) + encode(0x1, FWD); + + encode(0xa, 0); /* trailing quiet */ + print_sep(3); } /*------------------------------------------------------------*/ @@ -273,7 +418,7 @@ static void encode_char39 (unsigned char c, static void encode_code39 (char *data) { assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); - zprintf(3, "----------------------------------------------------------\n"); + print_sep(3); zprintf(2, "CODE-39: %s\n", data); encode(0xa, 0); /* leading quiet */ encode_char39('*', 1); @@ -282,7 +427,7 @@ static void encode_code39 (char *data) if(data[i] != '*') /* skip (FIXME) */ encode_char39(data[i], 1); encode_char39('*', 0xa); /* w/trailing quiet */ - zprintf(3, "----------------------------------------------------------\n"); + print_sep(3); } #if 0 @@ -348,7 +493,7 @@ static void encode_row417 (int r, static void encode_pdf417 (char *data) { assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); - zprintf(3, "----------------------------------------------------------\n"); + print_sep(3); zprintf(2, "PDF417: hello world\n"); encode(0xa, 0); @@ -358,7 +503,7 @@ static void encode_pdf417 (char *data) encode(0xa, 0); } - zprintf(3, "----------------------------------------------------------\n"); + print_sep(3); } #endif @@ -373,7 +518,7 @@ static void encode_i25 (char *data, int dir) { assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); - zprintf(3, "----------------------------------------------------------\n"); + print_sep(3); zprintf(2, "Interleaved 2 of 5: %s\n", data); zprintf(3, " encode start:"); encode((dir) ? 0xa1111 : 0xa112, 0); @@ -406,7 +551,7 @@ static void encode_i25 (char *data, zprintf(3, " encode end:"); encode((dir) ? 0x211a : 0x1111a, 0); - zprintf(3, "----------------------------------------------------------\n"); + print_sep(3); } /*------------------------------------------------------------*/ @@ -573,7 +718,7 @@ static void encode_databar (char *data, { assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); - zprintf(3, "----------------------------------------------------------\n"); + print_sep(3); zprintf(2, "DataBar: %s\n", data); uint32_t v[4] = { 0, }; @@ -645,7 +790,7 @@ static void encode_databar (char *data, zprintf(3, " encode end guard:"); encode(0x1, FWD); encode_junk(!dir); - zprintf(3, "----------------------------------------------------------\n"); + print_sep(3); } @@ -700,7 +845,7 @@ static void encode_ean13 (char *data) unsigned char par = ean_parity_encode[data[0] - '0']; assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); - zprintf(3, "----------------------------------------------------------\n"); + print_sep(3); zprintf(2, "EAN-13: %s (%02x)\n", data, par); zprintf(3, " encode start guard:"); encode(ean_guard[3], FWD); @@ -716,14 +861,14 @@ static void encode_ean13 (char *data) } zprintf(3, " encode end guard:"); encode(ean_guard[3], REV); - zprintf(3, "----------------------------------------------------------\n"); + print_sep(3); } static void encode_ean8 (char *data) { int i; assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); - zprintf(3, "----------------------------------------------------------\n"); + print_sep(3); zprintf(2, "EAN-8: %s\n", data); zprintf(3, " encode start guard:"); encode(ean_guard[3], FWD); @@ -739,7 +884,7 @@ static void encode_ean8 (char *data) } zprintf(3, " encode end guard:"); encode(ean_guard[3], REV); - zprintf(3, "----------------------------------------------------------\n"); + print_sep(3); } @@ -852,6 +997,16 @@ int test_alpha (char *data) encode_junk(rnd_size); + expect(ZBAR_CODE93, data); + encode_code93(data, FWD); + + encode_junk(rnd_size); + + expect(ZBAR_CODE93, data); + encode_code93(data, REV); + + encode_junk(rnd_size); + /*encode_code39("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%");*/ convert_code39(data); expect(ZBAR_CODE39, data); @@ -871,7 +1026,7 @@ int test_alpha (char *data) int test1 () { - zprintf(2, "----------------------------------------------------------\n"); + print_sep(2); if(!seed) seed = 0xbabeface; zprintf(1, "[%d] SEED=%d\n", iter++, seed); diff --git a/zbar.spec.in b/zbar.spec.in index d846d84..0c247c1 100644 --- a/zbar.spec.in +++ b/zbar.spec.in @@ -15,8 +15,8 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root %description The ZBar Bar Code Reader is a library for scanning and decoding bar codes from various sources such as video streams, image files or raw -intensity sensors. It supports EAN, UPC, Code 128, Code 39 and -Interleaved 2 of 5. The flexible, layered architecture features a +intensity sensors. It supports EAN, UPC, Code 128, Code 93, Code 39 +and Interleaved 2 of 5. The flexible, layered architecture features a fast, streaming interface with a minimal memory footprint. %package devel @@ -27,8 +27,8 @@ Requires: %{name} = %{version} %description devel The ZBar Bar Code Reader is a library for scanning and decoding bar codes from various sources such as video streams, image files or raw -intensity sensors. It supports EAN, UPC, Code 128, Code 39 and -Interleaved 2 of 5. The flexible, layered architecture features a +intensity sensors. It supports EAN, UPC, Code 128, Code 93, Code 39 +and Interleaved 2 of 5. The flexible, layered architecture features a fast, streaming interface with a minimal memory footprint. This package contains header files and additional libraries used for @@ -42,8 +42,8 @@ Requires: %{name} = %{version}, gtk2 %description gtk The ZBar Bar Code Reader is a library for scanning and decoding bar codes from various sources such as video streams, image files or raw -intensity sensors. It supports EAN, UPC, Code 128, Code 39 and -Interleaved 2 of 5. The flexible, layered architecture features a +intensity sensors. It supports EAN, UPC, Code 128, Code 93, Code 39 +and Interleaved 2 of 5. The flexible, layered architecture features a fast, streaming interface with a minimal memory footprint. This package contains a bar code scanning widget for use with GUI @@ -57,8 +57,8 @@ Requires: %{name}-gtk = %{version}, %{name}-devel = %{version}, gtk2-devel %description gtk-devel The ZBar Bar Code Reader is a library for scanning and decoding bar codes from various sources such as video streams, image files or raw -intensity sensors. It supports EAN, UPC, Code 128, Code 39 and -Interleaved 2 of 5. The flexible, layered architecture features a +intensity sensors. It supports EAN, UPC, Code 128, Code 93, Code 39 +and Interleaved 2 of 5. The flexible, layered architecture features a fast, streaming interface with a minimal memory footprint. This package contains header files and additional libraries used for @@ -73,8 +73,8 @@ Requires: %{name} = %{version}, pygtk2 %description pygtk The ZBar Bar Code Reader is a library for scanning and decoding bar codes from various sources such as video streams, image files or raw -intensity sensors. It supports EAN, UPC, Code 128, Code 39 and -Interleaved 2 of 5. The flexible, layered architecture features a +intensity sensors. It supports EAN, UPC, Code 128, Code 93, Code 39 +and Interleaved 2 of 5. The flexible, layered architecture features a fast, streaming interface with a minimal memory footprint. This package contains a bar code scanning widget for use in GUI @@ -88,8 +88,8 @@ Requires: %{name} = %{version}, qt >= 4 %description qt The ZBar Bar Code Reader is a library for scanning and decoding bar codes from various sources such as video streams, image files or raw -intensity sensors. It supports EAN, UPC, Code 128, Code 39 and -Interleaved 2 of 5. The flexible, layered architecture features a +intensity sensors. It supports EAN, UPC, Code 128, Code 93, Code 39 +and Interleaved 2 of 5. The flexible, layered architecture features a fast, streaming interface with a minimal memory footprint. This package contains a bar code scanning widget for use with GUI @@ -103,8 +103,8 @@ Requires: %{name}-qt = %{version}, %{name}-devel = %{version}, qt-devel >= 4 %description qt-devel The ZBar Bar Code Reader is a library for scanning and decoding bar codes from various sources such as video streams, image files or raw -intensity sensors. It supports EAN, UPC, Code 128, Code 39 and -Interleaved 2 of 5. The flexible, layered architecture features a +intensity sensors. It supports EAN, UPC, Code 128, Code 93, Code 39 +and Interleaved 2 of 5. The flexible, layered architecture features a fast, streaming interface with a minimal memory footprint. This package contains header files and additional libraries used for diff --git a/zbar/Makefile.am.inc b/zbar/Makefile.am.inc index badb03e..3d52077 100644 --- a/zbar/Makefile.am.inc +++ b/zbar/Makefile.am.inc @@ -25,6 +25,9 @@ endif if ENABLE_CODE128 zbar_libzbar_la_SOURCES += zbar/decoder/code128.h zbar/decoder/code128.c endif +if ENABLE_CODE93 +zbar_libzbar_la_SOURCES += zbar/decoder/code93.h zbar/decoder/code93.c +endif if ENABLE_CODE39 zbar_libzbar_la_SOURCES += zbar/decoder/code39.h zbar/decoder/code39.c endif diff --git a/zbar/config.c b/zbar/config.c index fa80c52..0a830bc 100644 --- a/zbar/config.c +++ b/zbar/config.c @@ -83,6 +83,8 @@ int zbar_parse_config (const char *cfgstr, #endif else if(len < 6) return(1); + else if(!strncmp(cfgstr, "code93", len)) + *sym = ZBAR_CODE93; else if(!strncmp(cfgstr, "code39", len)) *sym = ZBAR_CODE39; else if(!strncmp(cfgstr, "pdf417", len)) diff --git a/zbar/decoder.c b/zbar/decoder.c index aa04797..e244555 100644 --- a/zbar/decoder.c +++ b/zbar/decoder.c @@ -28,7 +28,7 @@ #include -#if defined(DEBUG_DECODER) || defined(DEBUG_EAN) || \ +#if defined(DEBUG_DECODER) || defined(DEBUG_EAN) || defined(DEBUG_CODE93) || \ defined(DEBUG_CODE39) || defined(DEBUG_I25) || defined(DEBUG_DATABAR) || \ defined(DEBUG_CODE128) || defined(DEBUG_QR_FINDER) || \ (defined(DEBUG_PDF417) && (DEBUG_PDF417 >= 4)) @@ -71,6 +71,9 @@ zbar_decoder_t *zbar_decoder_create () dcode->code39.config = 1 << ZBAR_CFG_ENABLE; CFG(dcode->code39, ZBAR_CFG_MIN_LEN) = 1; #endif +#ifdef ENABLE_CODE93 + dcode->code93.config = 1 << ZBAR_CFG_ENABLE; +#endif #ifdef ENABLE_CODE128 dcode->code128.config = 1 << ZBAR_CFG_ENABLE; #endif @@ -111,6 +114,9 @@ void zbar_decoder_reset (zbar_decoder_t *dcode) #ifdef ENABLE_CODE39 code39_reset(&dcode->code39); #endif +#ifdef ENABLE_CODE93 + code93_reset(&dcode->code93); +#endif #ifdef ENABLE_CODE128 code128_reset(&dcode->code128); #endif @@ -128,6 +134,7 @@ void zbar_decoder_new_scan (zbar_decoder_t *dcode) memset(dcode->w, 0, sizeof(dcode->w)); dcode->lock = 0; dcode->idx = 0; + dcode->s6 = 0; #ifdef ENABLE_EAN ean_new_scan(&dcode->ean); #endif @@ -140,6 +147,9 @@ void zbar_decoder_new_scan (zbar_decoder_t *dcode) #ifdef ENABLE_CODE39 code39_reset(&dcode->code39); #endif +#ifdef ENABLE_CODE93 + code93_reset(&dcode->code93); +#endif #ifdef ENABLE_CODE128 code128_reset(&dcode->code128); #endif @@ -205,6 +215,10 @@ zbar_symbol_type_t zbar_decode_width (zbar_decoder_t *dcode, dcode->w[dcode->idx & (DECODE_WINDOW - 1)] = w; dprintf(1, " decode[%x]: w=%d (%g)\n", dcode->idx, w, (w / 32.)); + /* update shared character width */ + dcode->s6 -= get_width(dcode, 7); + dcode->s6 += get_width(dcode, 1); + /* each decoder processes width stream in parallel */ #ifdef ENABLE_EAN if((dcode->ean.enable) && @@ -221,6 +235,11 @@ zbar_symbol_type_t zbar_decode_width (zbar_decoder_t *dcode, (tmp = _zbar_decode_code39(dcode)) > ZBAR_PARTIAL) sym = tmp; #endif +#ifdef ENABLE_CODE93 + if(TEST_CFG(dcode->code93.config, ZBAR_CFG_ENABLE) && + (tmp = _zbar_decode_code93(dcode)) > ZBAR_PARTIAL) + sym = tmp; +#endif #ifdef ENABLE_CODE128 if(TEST_CFG(dcode->code128.config, ZBAR_CFG_ENABLE) && (tmp = _zbar_decode_code128(dcode)) > ZBAR_PARTIAL) @@ -308,6 +327,12 @@ static inline int decoder_set_config_bool (zbar_decoder_t *dcode, break; #endif +#ifdef ENABLE_CODE93 + case ZBAR_CODE93: + config = &dcode->code93.config; + break; +#endif + #ifdef ENABLE_CODE128 case ZBAR_CODE128: config = &dcode->code128.config; @@ -371,6 +396,11 @@ static inline int decoder_set_config_int (zbar_decoder_t *dcode, CFG(dcode->code39, cfg) = val; break; #endif +#ifdef ENABLE_CODE93 + case ZBAR_CODE93: + CFG(dcode->code93, cfg) = val; + break; +#endif #ifdef ENABLE_CODE128 case ZBAR_CODE128: CFG(dcode->code128, cfg) = val; @@ -404,6 +434,7 @@ int zbar_decoder_set_config (zbar_decoder_t *dcode, zbar_decoder_set_config(dcode, ZBAR_DATABAR, cfg, val); zbar_decoder_set_config(dcode, ZBAR_DATABAR_EXP, cfg, val); zbar_decoder_set_config(dcode, ZBAR_CODE39, cfg, val); + zbar_decoder_set_config(dcode, ZBAR_CODE93, cfg, val); zbar_decoder_set_config(dcode, ZBAR_CODE128, cfg, val); zbar_decoder_set_config(dcode, ZBAR_PDF417, cfg, val); zbar_decoder_set_config(dcode, ZBAR_QRCODE, cfg, val); diff --git a/zbar/decoder.h b/zbar/decoder.h index 1d2cc9e..53ab151 100644 --- a/zbar/decoder.h +++ b/zbar/decoder.h @@ -42,6 +42,9 @@ #ifdef ENABLE_CODE39 # include "decoder/code39.h" #endif +#ifdef ENABLE_CODE93 +# include "decoder/code93.h" +#endif #ifdef ENABLE_CODE128 # include "decoder/code128.h" #endif @@ -84,6 +87,7 @@ struct zbar_decoder_s { zbar_symbol_type_t type; /* type of last decoded data */ zbar_symbol_type_t lock; /* buffer lock */ int direction; /* direction of last decoded data */ + unsigned s6; /* 6-element character width */ /* everything above here is automatically reset */ unsigned buf_alloc; /* dynamic buffer allocation */ @@ -105,6 +109,9 @@ struct zbar_decoder_s { #ifdef ENABLE_CODE39 code39_decoder_t code39; /* Code 39 decode state */ #endif +#ifdef ENABLE_CODE93 + code93_decoder_t code93; /* Code 93 decode state */ +#endif #ifdef ENABLE_CODE128 code128_decoder_t code128; /* Code 128 decode state */ #endif diff --git a/zbar/decoder/code93.c b/zbar/decoder/code93.c new file mode 100644 index 0000000..ce83da4 --- /dev/null +++ b/zbar/decoder/code93.c @@ -0,0 +1,397 @@ +/*------------------------------------------------------------------------ + * Copyright 2010 (c) Jeff Brown + * + * 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 +#include + +#ifdef DEBUG_CODE93 +# define DEBUG_LEVEL (DEBUG_CODE93) +#endif +#include "debug.h" +#include "decoder.h" + +static const signed char code93_hash[0x40] = { + 0x0f, 0x2b, 0x30, 0x38, 0x13, 0x1b, 0x11, 0x2a, + 0x0a, -1, 0x2f, 0x0f, 0x38, 0x38, 0x2f, 0x37, + 0x24, 0x3a, 0x1b, 0x36, 0x18, 0x26, 0x02, 0x2c, + 0x2b, 0x05, 0x21, 0x3b, 0x04, 0x15, 0x12, 0x0c, + 0x00, 0x26, 0x23, 0x00, -1, 0x2e, 0x3f, 0x13, + 0x2e, 0x36, -1, 0x08, 0x09, -1, 0x15, 0x14, + -1, 0x00, 0x21, 0x3b, -1, 0x33, 0x00, -1, + 0x2d, 0x0c, 0x1b, 0x0a, 0x3f, 0x3f, 0x29, 0x1c, +}; + +static inline int +check_width (unsigned cur, + unsigned prev) +{ + unsigned dw; + if(prev > cur) + dw = prev - cur; + else + dw = cur - prev; + dw *= 4; + return(dw > prev); +} + +static inline int +encode6 (zbar_decoder_t *dcode) +{ + /* build edge signature of character */ + unsigned s = dcode->s6; + int sig = 0, i; + + dprintf(2, " s=%d ", s); + if(s < 9) + return(-1); + + for(i = 6; --i > 0; ) { + unsigned c = decode_e(pair_width(dcode, i), s, 9); + if(c > 3) + return(-1); + sig = (sig << 2) | c; + dprintf(2, "%d", c); + } + dprintf(2, " sig=%03x", sig); + + return(sig); +} + +static inline int +validate_sig (int sig) +{ + int i, sum = 0, emin = 0, sig0 = 0, sig1 = 0; + dprintf(3, " sum=0"); + for(i = 3; --i >= 0; ) { + int e = sig & 3; + sig >>= 2; + sum = e - sum; + sig1 <<= 4; + sig1 += sum; + dprintf(3, "%d", sum); + if(!i) + break; + + e = sig & 3; + sig >>= 2; + sum = e - sum; + sig0 <<= 4; + if(emin > sum) + emin = sum; + sig0 += sum; + dprintf(3, "%d", sum); + } + + dprintf(3, " emin=%d sig=%03x/%03x", emin, sig1 & 0xfff, sig0 & 0xfff); + + emin = emin + (emin << 4) + (emin << 8); + sig0 -= emin; + sig1 += emin; + + dprintf(3, "=%03x/%03x", sig1 & 0xfff, sig0 & 0xfff); + return((sig0 | sig1) & 0x888); +} + +static inline int +decode6 (zbar_decoder_t *dcode) +{ + int sig = encode6(dcode); + int g0, g1, c; + if(sig < 0 || + (sig & 0x3) + ((sig >> 4) & 0x3) + ((sig >> 8) & 0x3) != 3 || + validate_sig(sig)) + return(-1); + + if(dcode->code93.direction) { + /* reverse signature */ + unsigned tmp = sig & 0x030; + sig = ((sig & 0x3c0) >> 6) | ((sig & 0x00f) << 6); + sig = ((sig & 0x30c) >> 2) | ((sig & 0x0c3) << 2) | tmp; + } + + g0 = code93_hash[(sig - (sig >> 4)) & 0x3f]; + g1 = code93_hash[((sig >> 2) - (sig >> 7)) & 0x3f]; + zassert(g0 >= 0 && g1 >= 0, -1, + "dir=%x sig=%03x g0=%03x g1=%03x %s\n", + dcode->code93.direction, sig, g0, g1, + _zbar_decoder_buf_dump(dcode->buf, dcode->code93.character)); + + c = (g0 + g1) & 0x3f; + dprintf(2, " g0=%x g1=%x c=%02x", g0, g1, c); + return(c); +} + +static inline zbar_symbol_type_t +decode_start (zbar_decoder_t *dcode) +{ + code93_decoder_t *dcode93 = &dcode->code93; + unsigned dir, qz, s = dcode->s6; + int c; + + dprintf(2, " code93:"); + c = encode6(dcode); + if(c < 0 || (c != 0x00f && c != 0x0f0)) + return(ZBAR_NONE); + + dir = (c >> 7); + + if(dir) { + if(decode_e(pair_width(dcode, 0), s, 9)) + return(ZBAR_NONE); + qz = get_width(dcode, 8); + } + + qz = get_width(dcode, 7); + if(qz && qz < (s * 3) / 4) { + dprintf(2, " [invalid qz %d]", qz); + return(ZBAR_NONE); + } + + /* decoded valid start/stop - initialize state */ + dcode93->direction = dir; + dcode93->element = (!dir) ? 0 : 7; + dcode93->character = 0; + dcode93->width = s; + + dprintf(2, " dir=%x [valid start]", dir); + return(ZBAR_PARTIAL); +} + +static inline zbar_symbol_type_t +decode_abort (zbar_decoder_t *dcode, + const char *reason) +{ + code93_decoder_t *dcode93 = &dcode->code93; + if(dcode93->character > 1) + release_lock(dcode, ZBAR_CODE93); + dcode93->character = -1; + if(reason) + dprintf(1, " [%s]\n", reason); + return(ZBAR_NONE); +} + +static inline zbar_symbol_type_t +check_stop (zbar_decoder_t *dcode) +{ + code93_decoder_t *dcode93 = &dcode->code93; + unsigned n = dcode93->character, s = dcode->s6; + int max_len = CFG(*dcode93, ZBAR_CFG_MAX_LEN); + if(n < 2 || + n < CFG(*dcode93, ZBAR_CFG_MIN_LEN) || + (max_len && n > max_len)) + return(decode_abort(dcode, "invalid len")); + + if(dcode93->direction) { + unsigned qz = get_width(dcode, 0); + if(qz && qz < (s * 3) / 4) + return(decode_abort(dcode, "invalid qz")); + } + else if(decode_e(pair_width(dcode, 0), s, 9)) + /* FIXME forward-trailing QZ check */ + return(decode_abort(dcode, "invalid stop")); + + return(ZBAR_CODE93); +} + +#define CHKMOD (47) + +static inline int +plusmod47 (int acc, + int add) +{ + acc += add; + if(acc >= CHKMOD) + acc -= CHKMOD; + return(acc); +} + +static inline int +validate_checksums (zbar_decoder_t *dcode) +{ + code93_decoder_t *dcode93 = &dcode->code93; + unsigned d, i, n = dcode93->character; + unsigned sum_c = 0, acc_c = 0, i_c = (n - 2) % 20; + unsigned sum_k = 0, acc_k = 0, i_k = (n - 1) % 15; + + for(i = 0; i < n - 2; i++) { + d = dcode->buf[(dcode93->direction) ? n - 1 - i : i]; + + if(!i_c--) { + acc_c = 0; + i_c = 19; + } + acc_c = plusmod47(acc_c, d); + sum_c = plusmod47(sum_c, acc_c); + + if(!i_k--) { + acc_k = 0; + i_k = 14; + } + acc_k = plusmod47(acc_k, d); + sum_k = plusmod47(sum_k, acc_k); + } + + d = dcode->buf[(dcode93->direction) ? 1 : n - 2]; + dprintf(2, " C=%02x?=%02x", d, sum_c); + if(d != sum_c) + return(1); + + acc_k = plusmod47(acc_k, sum_c); + sum_k = plusmod47(sum_k, acc_k); + d = dcode->buf[(dcode93->direction) ? 0 : n - 1]; + dprintf(2, " K=%02x?=%02x", d, sum_k); + if(d != sum_k) + return(1); + + return(0); +} + +/* resolve scan direction and convert to ASCII */ +static inline int +postprocess (zbar_decoder_t *dcode) +{ + code93_decoder_t *dcode93 = &dcode->code93; + unsigned i, j, n = dcode93->character; + static const unsigned char code93_graph[] = "-. $/+%"; + static const unsigned char code93_s2[] = + "\x1b\x1c\x1d\x1e\x1f;<=>?[\\]^_{|}~\x7f\x00\x40`\x7f\x7f\x7f"; + + dprintf(2, "\n postproc len=%d", n); + dcode->direction = 1 - 2 * dcode93->direction; + if(dcode93->direction) { + /* reverse buffer */ + dprintf(2, " (rev)"); + for(i = 0; i < n / 2; i++) { + unsigned j = n - 1 - i; + unsigned char d = dcode->buf[i]; + dcode->buf[i] = dcode->buf[j]; + dcode->buf[j] = d; + } + } + + n -= 2; + for(i = 0, j = 0; i < n; ) { + unsigned char d = dcode->buf[i++]; + if(d < 0xa) + d = '0' + d; + else if(d < 0x24) + d = 'A' + d - 0xa; + else if(d < 0x2b) + d = code93_graph[d - 0x24]; + else { + unsigned shift = d; + zassert(shift < 0x2f, -1, "%s\n", + _zbar_decoder_buf_dump(dcode->buf, dcode93->character)); + d = dcode->buf[i++]; + if(d < 0xa || d >= 0x24) + return(1); + d -= 0xa; + switch(shift) + { + case 0x2b: d++; break; + case 0x2c: d = code93_s2[d]; break; + case 0x2d: d += 0x21; break; + case 0x2e: d += 0x61; break; + default: return(1); + } + } + dcode->buf[j++] = d; + } + + dcode->buflen = j; + dcode->buf[j] = '\0'; + return(0); +} + +zbar_symbol_type_t +_zbar_decode_code93 (zbar_decoder_t *dcode) +{ + code93_decoder_t *dcode93 = &dcode->code93; + int c; + + if(dcode93->character < 0) { + zbar_symbol_type_t sym; + if(get_color(dcode) != ZBAR_BAR) + return(ZBAR_NONE); + sym = decode_start(dcode); + dprintf(2, "\n"); + return(sym); + } + + if(/* process every 6th element of active symbol */ + ++dcode93->element != 6 || + /* decode color based on direction */ + get_color(dcode) == dcode93->direction) + return(ZBAR_NONE); + + dcode93->element = 0; + + dprintf(2, " code93[%c%02d+%x]:", + (dcode93->direction) ? '<' : '>', + dcode93->character, dcode93->element); + + if(check_width(dcode->s6, dcode93->width)) + return(decode_abort(dcode, "width var")); + + c = decode6(dcode); + if(c < 0) + return(decode_abort(dcode, "aborted")); + + if(c == 0x2f) { + if(!check_stop(dcode)) + return(ZBAR_NONE); + if(validate_checksums(dcode)) + return(decode_abort(dcode, "checksum error")); + if(postprocess(dcode)) + return(decode_abort(dcode, "invalid encoding")); + + dprintf(2, " [valid end]\n"); + dprintf(3, " %s\n", + _zbar_decoder_buf_dump(dcode->buf, dcode93->character)); + + dcode93->character = -1; + return(ZBAR_CODE93); + } + + if(dcode93->character >= BUFFER_MIN && + size_buf(dcode, dcode93->character + 1)) + return(decode_abort(dcode, "overflow")); + + dcode93->width = dcode->s6; + + if(dcode93->character == 1) { + /* lock shared resources */ + if(acquire_lock(dcode, ZBAR_CODE93)) + return(decode_abort(dcode, NULL)); + dcode->buf[0] = dcode93->buf; + } + + if(!dcode93->character) + dcode93->buf = c; + else + dcode->buf[dcode93->character] = c; + dcode93->character++; + + dprintf(2, "\n"); + return(ZBAR_NONE); +} diff --git a/zbar/decoder/code93.h b/zbar/decoder/code93.h new file mode 100644 index 0000000..5716ccf --- /dev/null +++ b/zbar/decoder/code93.h @@ -0,0 +1,49 @@ +/*------------------------------------------------------------------------ + * Copyright 2010 (c) Jeff Brown + * + * 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 + *------------------------------------------------------------------------*/ +#ifndef _CODE93_H_ +#define _CODE93_H_ + +/* Code 93 specific decode state */ +typedef struct code93_decoder_s { + unsigned direction : 1; /* scan direction: 0=fwd/space, 1=rev/bar */ + unsigned element : 3; /* element offset 0-5 */ + int character : 12; /* character position in symbol */ + unsigned width; /* last character width */ + unsigned char buf; /* first character */ + + unsigned config; + int configs[NUM_CFGS]; /* int valued configurations */ +} code93_decoder_t; + +/* reset Code 93 specific state */ +static inline void code93_reset (code93_decoder_t *dcode93) +{ + dcode93->direction = 0; + dcode93->element = 0; + dcode93->character = -1; +} + +/* decode Code 93 symbols */ +zbar_symbol_type_t _zbar_decode_code93(zbar_decoder_t *dcode); + +#endif diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index d5456d6..8598643 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -108,7 +108,7 @@ struct zbar_image_scanner_s { /* configuration settings */ unsigned config; /* config flags */ int configs[NUM_SCN_CFGS]; /* int valued configurations */ - int sym_configs[1][16]; /* per-symbology configurations */ + int sym_configs[1][NUM_SYMS]; /* per-symbology configurations */ #ifndef NO_STATS int stat_syms_new; @@ -312,7 +312,7 @@ static inline void cache_sym (zbar_image_scanner_t *iscn, dup = (entry->cache_count >= 0); if((!dup && !near_thresh) || far_thresh) { int type = sym->type; - int h = ((type - (type >> 3)) ^ (type >> 5)) & 0xf; + int h = _zbar_get_symbol_hash(type); entry->cache_count = -iscn->sym_configs[0][h]; } else if(dup || near_thresh) @@ -486,6 +486,7 @@ zbar_image_scanner_t *zbar_image_scanner_create () zbar_image_scanner_set_config(iscn, 0, ZBAR_CFG_UNCERTAINTY, 2); zbar_image_scanner_set_config(iscn, ZBAR_QRCODE, ZBAR_CFG_UNCERTAINTY, 0); zbar_image_scanner_set_config(iscn, ZBAR_CODE128, ZBAR_CFG_UNCERTAINTY, 0); + zbar_image_scanner_set_config(iscn, ZBAR_CODE93, ZBAR_CFG_UNCERTAINTY, 0); zbar_image_scanner_set_config(iscn, ZBAR_CODE39, ZBAR_CFG_UNCERTAINTY, 0); return(iscn); } @@ -564,11 +565,11 @@ int zbar_image_scanner_set_config (zbar_image_scanner_t *iscn, return(1); c = cfg - ZBAR_CFG_UNCERTAINTY; if(sym > ZBAR_PARTIAL) { - i = ((sym - (sym >> 3)) ^ (sym >> 5)) & 0xf; + i = _zbar_get_symbol_hash(sym); iscn->sym_configs[c][i] = val; } else - for(i = 0; i < 16; i++) + for(i = 0; i < NUM_SYMS; i++) iscn->sym_configs[c][i] = val; return(0); } diff --git a/zbar/symbol.c b/zbar/symbol.c index 4f8bf93..ec21693 100644 --- a/zbar/symbol.c +++ b/zbar/symbol.c @@ -42,6 +42,7 @@ const char *zbar_get_symbol_name (zbar_symbol_type_t sym) case ZBAR_DATABAR: return("DataBar"); case ZBAR_DATABAR_EXP: return("DataBar-Exp"); case ZBAR_CODE39: return("CODE-39"); + case ZBAR_CODE93: return("CODE-93"); case ZBAR_CODE128: return("CODE-128"); case ZBAR_PDF417: return("PDF417"); case ZBAR_QRCODE: return("QR-Code"); @@ -69,6 +70,22 @@ const char *zbar_get_orientation_name (zbar_orientation_t orient) } } +int _zbar_get_symbol_hash (zbar_symbol_type_t sym) +{ + static const signed char hash[0x20] = { + 0x00, 0x01, 0x0d, 0x0e, -1, -1, -1, 0x09, + 0x05, 0x06, 0x08, -1, 0x04, 0x03, 0x07, -1, + -1, -1, -1, -1, -1, -1, -1, 0x02, + -1, 0x00, 0x0f, 0x0c, 0x0b, 0x00, 0x0a, 0x00, + }; + int g0 = hash[sym & 0x1f]; + int g1 = hash[~(sym >> 4) & 0x1f]; + assert(g0 >= 0 && g1 >= 0); + if(g0 < 0 || g1 < 0) + return(0); + return((g0 + g1) & 0x1f); +} + void _zbar_symbol_free (zbar_symbol_t *sym) { if(sym->syms) { @@ -226,8 +243,9 @@ char *zbar_symbol_xml (const zbar_symbol_t *sym, (data[0] == 0xfe && data[1] == 0xff) || !strncmp(sym->data, "datalen; i++) { - char c = sym->data[i]; + unsigned char c = sym->data[i]; binary = ((c < 0x20 && ((~0x00002600 >> c) & 1)) || + (c >= 0x7f && c < 0xa0) || (c == ']' && i + 2 < sym->datalen && sym->data[i + 1] == ']' && sym->data[i + 2] == '>')); diff --git a/zbar/symbol.h b/zbar/symbol.h index 626076c..99972d1 100644 --- a/zbar/symbol.h +++ b/zbar/symbol.h @@ -27,6 +27,8 @@ #include #include "refcnt.h" +#define NUM_SYMS 16 + typedef struct point_s { int x, y; } point_t; @@ -57,6 +59,8 @@ struct zbar_symbol_s { int quality; /* relative symbol reliability metric */ }; +extern int _zbar_get_symbol_hash(zbar_symbol_type_t); + extern void _zbar_symbol_free(zbar_symbol_t*); extern zbar_symbol_set_t *_zbar_symbol_set_create(void); diff --git a/zbarimg/zbarimg.c b/zbarimg/zbarimg.c index 9b2e320..38ba737 100644 --- a/zbarimg/zbarimg.c +++ b/zbarimg/zbarimg.c @@ -76,8 +76,8 @@ static const char *warning_not_found = " things to check:\n" " - is the barcode type supported?" " currently supported symbologies are:\n" - " EAN/UPC (EAN-13, EAN-8, UPC-A, UPC-E, ISBN-10, ISBN-13),\n" - " Code 128, Code 39, DataBar, DataBar Expanded, and Interleaved 2 of 5\n" + " EAN/UPC (EAN-13, EAN-8, UPC-A, UPC-E, ISBN-10, ISBN-13), Code 128,\n" + " Code 93, Code 39, DataBar, DataBar Expanded, and Interleaved 2 of 5\n" " - is the barcode large enough in the image?\n" " - is the barcode mostly in focus?\n" " - is there sufficient contrast/illumination?\n" @@ -165,21 +165,14 @@ static int scan_image (const char *filename) const zbar_symbol_t *sym = zbar_image_first_symbol(zimage); for(; sym; sym = zbar_symbol_next(sym)) { zbar_symbol_type_t typ = zbar_symbol_get_type(sym); + unsigned len = zbar_symbol_get_data_length(sym); if(typ == ZBAR_PARTIAL) continue; - else if(!xmllvl) { - printf("%s:", zbar_get_symbol_name(typ)); - if(fwrite(zbar_symbol_get_data(sym), - zbar_symbol_get_data_length(sym), - 1, stdout) != 1) { - exit_code = 1; - return(-1); - } - } - else if(xmllvl < 0) { - if(fwrite(zbar_symbol_get_data(sym), - zbar_symbol_get_data_length(sym), - 1, stdout) != 1) { + else if(xmllvl <= 0) { + if(!xmllvl) + printf("%s:", zbar_get_symbol_name(typ)); + if(len && + fwrite(zbar_symbol_get_data(sym), len, 1, stdout) != 1) { exit_code = 1; return(-1); } From 23c7c13235eb866c77340294f27e1e51962cf333 Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 20 Sep 2010 13:00:57 -0400 Subject: [PATCH 238/328] iPhone: update to SDK 4.1, clean out LLVM warnings --- iphone/ChangeLog | 1 + iphone/ZBarImage.m | 2 +- iphone/ZBarReaderViewController.m | 2 +- iphone/debug.h | 2 +- .../ReaderSample.xcodeproj/project.pbxproj | 13 ++++++++++-- .../readertest.xcodeproj/project.pbxproj | 11 ++++++++-- iphone/include/config.h | 14 ++++++------- iphone/zbar.xcodeproj/project.pbxproj | 13 ++++++++---- zbar/debug.h | 18 +++++++++-------- zbar/decoder/code128.c | 20 +++++++++++-------- zbar/decoder/databar.c | 2 +- 11 files changed, 63 insertions(+), 35 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index e5abb08..b55e4a7 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,5 @@ current: + * update to SDK 4.1, clean out LLVM warnings * fix camera simulation gesture version 0.1.2: diff --git a/iphone/ZBarImage.m b/iphone/ZBarImage.m index db50e97..f723e7a 100644 --- a/iphone/ZBarImage.m +++ b/iphone/ZBarImage.m @@ -256,7 +256,7 @@ case zbar_fourcc('R','G','B','Q'): bpp = 16; break; default: - NSLog(@"ERROR: format %.4s(%08x) is unsupported", + NSLog(@"ERROR: format %.4s(%08lx) is unsupported", (char*)&format, format); assert(0); return(nil); diff --git a/iphone/ZBarReaderViewController.m b/iphone/ZBarReaderViewController.m index 756f9fc..c9220a6 100644 --- a/iphone/ZBarReaderViewController.m +++ b/iphone/ZBarReaderViewController.m @@ -241,7 +241,7 @@ - (void) viewWillDisappear: (BOOL) animated - (ZBarReaderView*) readerView { // force view to load - self.view; + (void)self.view; assert(readerView); return(readerView); } diff --git a/iphone/debug.h b/iphone/debug.h index 3244b48..97ff64e 100644 --- a/iphone/debug.h +++ b/iphone/debug.h @@ -36,7 +36,7 @@ uint64_t t_start = timer_now(); #else -# define zlog(...) +# define zlog(...) while(0) # define timer_start #endif diff --git a/iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj b/iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj index 9408de4..75cca99 100755 --- a/iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj +++ b/iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj @@ -246,7 +246,14 @@ isa = PBXProject; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ReaderSample" */; compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; projectDirPath = ""; projectRoot = ""; @@ -331,8 +338,9 @@ GCC_C_LANGUAGE_STANDARD = c99; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 4.0; PREBINDING = NO; - SDKROOT = iphoneos4.0; + SDKROOT = iphoneos4.1; }; name = Debug; }; @@ -344,9 +352,10 @@ GCC_C_LANGUAGE_STANDARD = c99; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 4.0; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; PREBINDING = NO; - SDKROOT = iphoneos4.0; + SDKROOT = iphoneos4.1; }; name = Release; }; diff --git a/iphone/examples/readertest/readertest.xcodeproj/project.pbxproj b/iphone/examples/readertest/readertest.xcodeproj/project.pbxproj index 9f0ad29..b43397f 100755 --- a/iphone/examples/readertest/readertest.xcodeproj/project.pbxproj +++ b/iphone/examples/readertest/readertest.xcodeproj/project.pbxproj @@ -214,7 +214,14 @@ isa = PBXProject; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "readertest" */; compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; projectDirPath = ""; projectRoot = ""; @@ -291,7 +298,7 @@ GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 3.1; PREBINDING = NO; - SDKROOT = iphoneos4.0; + SDKROOT = iphoneos4.1; SYMROOT = /tmp/readertest.build; }; name = Debug; @@ -306,7 +313,7 @@ GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 3.1; PREBINDING = NO; - SDKROOT = iphoneos4.0; + SDKROOT = iphoneos4.1; SYMROOT = /tmp/readertest.build; }; name = Release; diff --git a/iphone/include/config.h b/iphone/include/config.h index 181c971..11ea39d 100644 --- a/iphone/include/config.h +++ b/iphone/include/config.h @@ -149,28 +149,28 @@ #undef NO_MINUS_C_MINUS_O /* Name of package */ -#undef PACKAGE "zbar" +#define PACKAGE "zbar" /* Define to the address where bug reports for this package should be sent. */ -#undef PACKAGE_BUGREPORT "spadix@users.sourceforge.net" +#define PACKAGE_BUGREPORT "spadix@users.sourceforge.net" /* Define to the full name of this package. */ -#undef PACKAGE_NAME "zbar" +#define PACKAGE_NAME "zbar" /* Define to the full name and version of this package. */ -#undef PACKAGE_STRING "zbar 0.10" +#define PACKAGE_STRING "zbar 0.10" /* Define to the one symbol short name of this package. */ -#undef PACKAGE_TARNAME "zbar" +#define PACKAGE_TARNAME "zbar" /* Define to the version of this package. */ -#undef PACKAGE_VERSION "0.10" +#define PACKAGE_VERSION "0.10" /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Version number of package */ -#undef VERSION "0.10" +#define VERSION "0.10" /* Define to 1 if the X Window System is missing or not being used. */ #define X_DISPLAY_MISSING 1 diff --git a/iphone/zbar.xcodeproj/project.pbxproj b/iphone/zbar.xcodeproj/project.pbxproj index 464c889..6a70faa 100644 --- a/iphone/zbar.xcodeproj/project.pbxproj +++ b/iphone/zbar.xcodeproj/project.pbxproj @@ -596,7 +596,14 @@ isa = PBXProject; buildConfigurationList = 1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "zbar" */; compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); mainGroup = 0867D691FE84028FC02AAC07 /* zbar */; productRefGroup = 034768DFFF38A50411DB9C8B /* Products */; projectDirPath = ""; @@ -800,7 +807,7 @@ OTHER_LDFLAGS = "-ObjC"; PREBINDING = NO; RUN_CLANG_STATIC_ANALYZER = NO; - SDKROOT = iphoneos4.0; + SDKROOT = iphoneos4.1; USE_HEADERMAP = NO; }; name = Debug; @@ -823,7 +830,7 @@ OTHER_LDFLAGS = "-ObjC"; PREBINDING = NO; RUN_CLANG_STATIC_ANALYZER = NO; - SDKROOT = iphoneos4.0; + SDKROOT = iphoneos4.1; USE_HEADERMAP = NO; }; name = Release; @@ -870,7 +877,6 @@ ); PREBINDING = NO; PRODUCT_NAME = readertest; - SDKROOT = iphoneos4.0; }; name = Debug; }; @@ -898,7 +904,6 @@ ); PREBINDING = NO; PRODUCT_NAME = readertest; - SDKROOT = iphoneos4.0; ZERO_LINK = NO; }; name = Release; diff --git a/zbar/debug.h b/zbar/debug.h index 482ca8d..138ab0f 100644 --- a/zbar/debug.h +++ b/zbar/debug.h @@ -27,10 +27,10 @@ # ifdef __GNUC__ /* older versions of gcc (< 2.95) require a named varargs parameter */ -# define dprintf(args...) +# define dprintf(args...) while(0) # else /* unfortunately named vararg parameter is a gcc-specific extension */ -# define dprintf(...) +# define dprintf(...) while(0) # endif #else @@ -38,13 +38,15 @@ # include # ifdef __GNUC__ -# define dprintf(level, args...) \ - if((level) <= DEBUG_LEVEL) \ - fprintf(stderr, args) +# define dprintf(level, args...) do { \ + if((level) <= DEBUG_LEVEL) \ + fprintf(stderr, args); \ + } while(0) # else -# define dprintf(level, ...) \ - if((level) <= DEBUG_LEVEL) \ - fprintf(stderr, __VA_ARGS__) +# define dprintf(level, ...) do { \ + if((level) <= DEBUG_LEVEL) \ + fprintf(stderr, __VA_ARGS__); \ + } while(0) # endif #endif /* DEBUG_LEVEL */ diff --git a/zbar/decoder/code128.c b/zbar/decoder/code128.c index 4af9939..78ec23a 100644 --- a/zbar/decoder/code128.c +++ b/zbar/decoder/code128.c @@ -395,13 +395,16 @@ static inline unsigned char postprocess (zbar_decoder_t *dcode) if(code < CODE_C) { if(code == SHIFT) charset |= 0x80; - else if(code == FNC2) - /* FIXME FNC2 - message append */; - else if(code == FNC3) - /* FIXME FNC3 - initialize */; + else if(code == FNC2) { + /* FIXME FNC2 - message append */ + } + else if(code == FNC3) { + /* FIXME FNC3 - initialize */ + } + } + else if(code == FNC1) { + /* FIXME FNC1 - Code 128 subsets or ASCII 0x1d */ } - else if(code == FNC1) - /* FIXME FNC1 - Code 128 subsets or ASCII 0x1d */; else if(code >= START_A) { dprintf(1, " [truncated]\n"); return(1); @@ -415,8 +418,9 @@ static inline unsigned char postprocess (zbar_decoder_t *dcode) dcode->code128.character)); if(newset != charset) charset = newset; - else - /* FIXME FNC4 - extended ASCII */; + else { + /* FIXME FNC4 - extended ASCII */ + } } if(charset & 0x2) cexp = i + 1; diff --git a/zbar/decoder/databar.c b/zbar/decoder/databar.c index 61510b5..bd3b91a 100644 --- a/zbar/decoder/databar.c +++ b/zbar/decoder/databar.c @@ -186,7 +186,7 @@ databar_postprocess_exp (zbar_decoder_t *dcode, if((len ^ (d >> (--i))) & 1) /* even/odd length mismatch */ return(-1); - if((d >> (--i)) & 1 != (len > 14)) + if(((d >> (--i)) & 1) != (len > 14)) /* size group mismatch */ return(-1); } From cae8c4950128d5011046e10bb05c01efffd0a1ba Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 20 Sep 2010 13:25:40 -0400 Subject: [PATCH 239/328] iPhone: bump SDK version to 1.0 --- iphone/ChangeLog | 2 +- iphone/res/ZBarSDK-Info.plist | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index b55e4a7..793b5d8 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,4 @@ -current: +version 1.0: * update to SDK 4.1, clean out LLVM warnings * fix camera simulation gesture diff --git a/iphone/res/ZBarSDK-Info.plist b/iphone/res/ZBarSDK-Info.plist index 726d35d..901bcf9 100644 --- a/iphone/res/ZBarSDK-Info.plist +++ b/iphone/res/ZBarSDK-Info.plist @@ -7,7 +7,7 @@ CFBundleName ZBarSDK CFBundleVersion - 0.1.2 + 1.0 CFBundleSignature ???? NSHumanReadableCopyright From fbdf3575ab96e6ac37840f9a747ca806af3ec0bc Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 20 Sep 2010 13:26:45 -0400 Subject: [PATCH 240/328] Added tag iPhoneSDK-1.0 for changeset 4556c996acaa From 9583e93e4a01d1bb2ff40dea5923ee2150770897 Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 23 Nov 2010 18:39:20 -0800 Subject: [PATCH 241/328] iPhone: workaround iOS 4.2 hang - update to use latest SDK --- iphone/ChangeLog | 4 ++++ iphone/ZBarCaptureReader.m | 11 +++++++++++ iphone/zbar.xcodeproj/project.pbxproj | 4 ++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 793b5d8..2b97e77 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,3 +1,7 @@ +current: + * workaround iOS 4.2 hang + - update to use latest SDK + version 1.0: * update to SDK 4.1, clean out LLVM warnings * fix camera simulation gesture diff --git a/iphone/ZBarCaptureReader.m b/iphone/ZBarCaptureReader.m index 513f5e9..db4f12e 100644 --- a/iphone/ZBarCaptureReader.m +++ b/iphone/ZBarCaptureReader.m @@ -61,12 +61,23 @@ - (id) initWithImageScanner: (ZBarImageScanner*) _scanner 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: diff --git a/iphone/zbar.xcodeproj/project.pbxproj b/iphone/zbar.xcodeproj/project.pbxproj index cfc629c..4cdf04f 100644 --- a/iphone/zbar.xcodeproj/project.pbxproj +++ b/iphone/zbar.xcodeproj/project.pbxproj @@ -813,7 +813,7 @@ OTHER_LDFLAGS = "-ObjC"; PREBINDING = NO; RUN_CLANG_STATIC_ANALYZER = NO; - SDKROOT = iphoneos4.1; + SDKROOT = iphoneos; USE_HEADERMAP = NO; }; name = Debug; @@ -836,7 +836,7 @@ OTHER_LDFLAGS = "-ObjC"; PREBINDING = NO; RUN_CLANG_STATIC_ANALYZER = NO; - SDKROOT = iphoneos4.1; + SDKROOT = iphoneos; USE_HEADERMAP = NO; }; name = Release; From f579e5f43771773960fe4bd2e7d654a379f3083f Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 23 Nov 2010 19:07:24 -0800 Subject: [PATCH 242/328] expose enable for reader capture processing --- iphone/ChangeLog | 1 + iphone/ZBarCaptureReader.m | 25 ++++++++++++++++------ iphone/ZBarReaderViewImpl_Capture.m | 4 ++-- iphone/include/ZBarSDK/ZBarCaptureReader.h | 4 ++++ 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 2b97e77..3e6f783 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,5 @@ current: + * expose enable for reader capture processing * workaround iOS 4.2 hang - update to use latest SDK diff --git a/iphone/ZBarCaptureReader.m b/iphone/ZBarCaptureReader.m index db4f12e..a5723df 100644 --- a/iphone/ZBarCaptureReader.m +++ b/iphone/ZBarCaptureReader.m @@ -36,6 +36,7 @@ @implementation ZBarCaptureReader @synthesize captureOutput, captureDelegate, scanner, scanCrop, size, framesPerSecond, enableCache; +@dynamic enableReader; - (void) initResult { @@ -126,19 +127,29 @@ - (void) dealloc [super dealloc]; } +- (BOOL) enableReader +{ + return(!OSAtomicCompareAndSwap32Barrier(0, 0, &running)); +} + +- (void) setEnableReader: (BOOL) enable +{ + if(!enable) + OSAtomicAnd32OrigBarrier(0, (void*)&running); + else if(OSAtomicCompareAndSwap32Barrier(0, 1, &running)) + @synchronized(scanner) { + scanner.enableCache = enableCache; + } +} + - (void) willStartRunning { - if(!OSAtomicCompareAndSwap32Barrier(0, 1, &running)) - return; - @synchronized(scanner) { - scanner.enableCache = enableCache; - } + self.enableReader = YES; } - (void) willStopRunning { - if(!OSAtomicAnd32OrigBarrier(0, (void*)&running)) - return; + self.enableReader = NO; } - (void) flushCache diff --git a/iphone/ZBarReaderViewImpl_Capture.m b/iphone/ZBarReaderViewImpl_Capture.m index 07aae3d..41879d6 100644 --- a/iphone/ZBarReaderViewImpl_Capture.m +++ b/iphone/ZBarReaderViewImpl_Capture.m @@ -231,8 +231,8 @@ - (void) start return; [super start]; - [captureReader willStartRunning]; [session startRunning]; + captureReader.enableReader = YES; } - (void) stop @@ -241,7 +241,7 @@ - (void) stop return; [super stop]; - [captureReader willStopRunning]; + captureReader.enableReader = NO; [session stopRunning]; } diff --git a/iphone/include/ZBarSDK/ZBarCaptureReader.h b/iphone/include/ZBarSDK/ZBarCaptureReader.h index 038b902..310dd31 100644 --- a/iphone/include/ZBarSDK/ZBarCaptureReader.h +++ b/iphone/include/ZBarSDK/ZBarCaptureReader.h @@ -92,6 +92,10 @@ // size of video frames. @property (nonatomic, readonly) CGSize size; +// (quickly) gate the reader function without interrupting the video +// stream. also flushes the cache when enabled. defaults to *NO* +@property (nonatomic) BOOL enableReader; + // current frame rate (for debug/optimization). // only valid when running @property (nonatomic, readonly) CGFloat framesPerSecond; From 1fc7635a1153751daa8fe6b7e6bb2de8b8bd8b5b Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 24 Nov 2010 10:19:00 -0800 Subject: [PATCH 243/328] cleanup and expose ZBarHelpController --- iphone/ChangeLog | 2 + iphone/ZBarHelpController.m | 111 +++++++++++++----- iphone/ZBarReaderController.m | 9 +- iphone/ZBarReaderViewController.m | 9 +- iphone/examples/readertest/readertest.m | 27 ++++- .../ZBarSDK}/ZBarHelpController.h | 18 ++- iphone/include/ZBarSDK/ZBarSDK.h | 1 + 7 files changed, 132 insertions(+), 45 deletions(-) rename iphone/{ => include/ZBarSDK}/ZBarHelpController.h (76%) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 3e6f783..1ed6cdf 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,7 +1,9 @@ current: + * 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 diff --git a/iphone/ZBarHelpController.m b/iphone/ZBarHelpController.m index 3ac6c47..c07fea1 100644 --- a/iphone/ZBarHelpController.m +++ b/iphone/ZBarHelpController.m @@ -21,17 +21,7 @@ // http://sourceforge.net/projects/zbar //------------------------------------------------------------------------ -#import "ZBarHelpController.h" - -@interface NSObject (ZBarHelpControllerDelegate) - -- (void) helpController: (ZBarHelpController*) help - clickedButtonAtIndex: (NSInteger) index; - -@end - - -enum { BTN_TRYAGAIN = 1 }; +#import @implementation ZBarHelpController @@ -39,11 +29,18 @@ @implementation ZBarHelpController - (id) initWithReason: (NSString*) _reason { - if(self = [super init]) { - if(!_reason) - _reason = @"INFO"; - reason = [_reason retain]; - } + self = [super init]; + if(!self) + return(nil); + + if(!_reason) + _reason = @"INFO"; + reason = [_reason retain]; + orientations = ((1 << UIInterfaceOrientationPortrait) | + (1 << UIInterfaceOrientationPortraitUpsideDown) | + (1 << UIInterfaceOrientationLandscapeLeft) | + (1 << UIInterfaceOrientationLandscapeRight)); + return(self); } @@ -76,27 +73,38 @@ - (void) dealloc [super dealloc]; } +- (void) layoutSubviewsForOrientation: (UIInterfaceOrientation) orient +{ + CGFloat h; + if(orient == UIInterfaceOrientationPortrait || + orient == UIInterfaceOrientationPortraitUpsideDown) + h = 44; + else + h = 32; + CGRect r = self.view.bounds; + r.origin.y += r.size.height - h; + r.size.height = h; + toolbar.frame = r; + + r = self.view.bounds; + r.size.height -= h; + webView.frame = r; +} + - (void) viewDidLoad { [super viewDidLoad]; UIView *view = self.view; view.backgroundColor = [UIColor colorWithWhite: .125f - alpha: 1 ]; - - CGRect r = view.bounds; - r.size.height -= 54; - webView = [[UIWebView alloc] - initWithFrame: r]; - webView.delegate = self; - webView.backgroundColor = [UIColor colorWithWhite: .125f - alpha: 1 ]; + alpha: 1]; + view.autoresizingMask = (UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight); toolbar = [UIToolbar new]; toolbar.barStyle = UIBarStyleBlackOpaque; - r.origin.y = r.size.height; - r.size.height = 54; - toolbar.frame = r; + toolbar.autoresizingMask = (UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleTopMargin); doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemDone @@ -119,6 +127,20 @@ - (void) viewDidLoad [view addSubview: toolbar]; + webView = [UIWebView new]; + webView.delegate = self; + webView.backgroundColor = [UIColor colorWithWhite: .125f + alpha: 1 ]; + webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight); + + UIInterfaceOrientation orient = self.interfaceOrientation; + if(!((orientations >> orient) & 1)) + for(orient = UIInterfaceOrientationPortrait; + (orientations >> orient) && !((orientations >> orient) & 1); + orient++); + [self layoutSubviewsForOrientation: orient]; + NSString *path = [[NSBundle mainBundle] pathForResource: @"zbar-help" ofType: @"html"]; @@ -157,10 +179,39 @@ - (void) viewWillDisappear: (BOOL) animated [super viewWillDisappear: animated]; } +- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) orient +{ + return([self isInterfaceOrientationSupported: orient]); +} + +- (void) willAnimateRotationToInterfaceOrientation: (UIInterfaceOrientation) orient + duration: (NSTimeInterval) duration +{ + [self layoutSubviewsForOrientation: orient]; + [webView reload]; +} + +- (BOOL) isInterfaceOrientationSupported: (UIInterfaceOrientation) 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 { - [delegate helpController: self - clickedButtonAtIndex: BTN_TRYAGAIN]; + if([delegate respondsToSelector: @selector(helpControllerDidFinish:)]) + [delegate helpControllerDidFinish: self]; + else + [self dismissModalViewControllerAnimated: YES]; } - (void) webViewDidFinishLoad: (UIWebView*) view diff --git a/iphone/ZBarReaderController.m b/iphone/ZBarReaderController.m index 5b439c7..6b3d18e 100644 --- a/iphone/ZBarReaderController.m +++ b/iphone/ZBarReaderController.m @@ -22,7 +22,7 @@ //------------------------------------------------------------------------ #import -#import "ZBarHelpController.h" +#import #import "debug.h" /* the use of UIGetScreenImage() may no longer be sanctioned, even @@ -585,7 +585,7 @@ - (void) showHelpWithReason: (NSString*) reason } help = [[ZBarHelpController alloc] initWithReason: reason]; - help.delegate = self; + help.delegate = (id)self; if(self.sourceType != UIImagePickerControllerSourceTypeCamera) { [self presentModalViewController: help @@ -679,8 +679,9 @@ - (void) imagePickerControllerDidCancel: (UIImagePickerController*) picker [self dismissModalViewControllerAnimated: YES]; } -- (void) helpController: (ZBarHelpController*) hlp - clickedButtonAtIndex: (NSInteger) idx +// ZBarHelpDelegate + +- (void) helpControllerDidFinish: (ZBarHelpController*) hlp { if(self.sourceType == UIImagePickerControllerSourceTypeCamera) { [UIView beginAnimations: @"ZBarHelp" diff --git a/iphone/ZBarReaderViewController.m b/iphone/ZBarReaderViewController.m index c9220a6..0b37852 100644 --- a/iphone/ZBarReaderViewController.m +++ b/iphone/ZBarReaderViewController.m @@ -23,7 +23,7 @@ #import #import -#import "ZBarHelpController.h" +#import #define MODULE ZBarReaderViewController #import "debug.h" @@ -308,7 +308,7 @@ - (void) showHelpWithReason: (NSString*) reason ZBarHelpController *help = [[ZBarHelpController alloc] initWithReason: reason]; - help.delegate = self; + help.delegate = (id)self; help.wantsFullScreenLayout = YES; UIView *helpView = help.view; helpView.alpha = 0; @@ -319,10 +319,9 @@ - (void) showHelpWithReason: (NSString*) reason [UIView commitAnimations]; } -// ZBarHelpControllerDelegate (informal) +// ZBarHelpDelegate -- (void) helpController: (ZBarHelpController*) help - clickedButtonAtIndex: (NSInteger) idx +- (void) helpControllerDidFinish: (ZBarHelpController*) help { [UIView beginAnimations: @"ZBarHelp" context: help]; diff --git a/iphone/examples/readertest/readertest.m b/iphone/examples/readertest/readertest.m index 42ceb9a..20e346c 100644 --- a/iphone/examples/readertest/readertest.m +++ b/iphone/examples/readertest/readertest.m @@ -454,6 +454,21 @@ - (void) scan animated: YES]; } +- (void) help +{ + ZBarHelpController *help = + [[ZBarHelpController alloc] + initWithReason: @"TEST"]; + [self presentModalViewController: help + animated: YES]; + [help release]; +} + +- (void) info +{ + [reader showHelpWithReason: @"INFO"]; +} + - (void) pause { if(![reader respondsToSelector: @selector(readerView)]) @@ -476,6 +491,13 @@ - (void) navigationController: (UINavigationController*) _nav willShowViewController: (UIViewController*) vc animated: (BOOL) animated { + self.navigationItem.leftBarButtonItem = + [[[UIBarButtonItem alloc] + initWithTitle: @"Help" + style: UIBarButtonItemStyleDone + target: self + action: @selector(help)] + autorelease]; self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle: @"Scan!" @@ -787,11 +809,6 @@ - (void) readerControllerDidFailToRead: (ZBarReaderController*) _reader [_reader dismissModalViewControllerAnimated: YES]; } -- (void) info -{ - [reader showHelpWithReason: @"INFO"]; -} - @end diff --git a/iphone/ZBarHelpController.h b/iphone/include/ZBarSDK/ZBarHelpController.h similarity index 76% rename from iphone/ZBarHelpController.h rename to iphone/include/ZBarSDK/ZBarHelpController.h index dd9d683..37639dd 100644 --- a/iphone/ZBarHelpController.h +++ b/iphone/include/ZBarSDK/ZBarHelpController.h @@ -23,6 +23,16 @@ #import +@class ZBarHelpController; + +@protocol ZBarHelpDelegate +@optional + +- (void) helpControllerDidFinish: (ZBarHelpController*) help; + +@end + + // failure dialog w/a few useful tips @interface ZBarHelpController : UIViewController @@ -35,10 +45,16 @@ UIToolbar *toolbar; UIBarButtonItem *doneBtn, *backBtn, *space; NSURL *linkURL; + NSUInteger orientations; } -@property (nonatomic, assign) id delegate; +@property (nonatomic, assign) id delegate; +// designated initializer - (id) initWithReason: (NSString*) reason; +- (BOOL) isInterfaceOrientationSupported: (UIInterfaceOrientation) orientation; +- (void) setInterfaceOrientation: (UIInterfaceOrientation) orientation + supported: (BOOL) supported; + @end diff --git a/iphone/include/ZBarSDK/ZBarSDK.h b/iphone/include/ZBarSDK/ZBarSDK.h index 11243b7..e7d5c0f 100644 --- a/iphone/include/ZBarSDK/ZBarSDK.h +++ b/iphone/include/ZBarSDK/ZBarSDK.h @@ -30,3 +30,4 @@ #import "ZBarReaderViewController.h" #import "ZBarReaderController.h" #import "ZBarCaptureReader.h" +#import "ZBarHelpController.h" From 4275006ad8d8946f8725b148bed28a1e41dc108b Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 24 Nov 2010 12:33:47 -0800 Subject: [PATCH 244/328] fix simulated camera image orientation/scaling --- iphone/ChangeLog | 1 + iphone/ZBarReaderView.m | 14 ++++++++--- iphone/ZBarReaderViewImpl_Capture.m | 14 +++-------- iphone/ZBarReaderViewImpl_Simulator.m | 35 +++++++++++++++------------ 4 files changed, 34 insertions(+), 30 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 1ed6cdf..60d6ef1 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,5 @@ current: + * fix simulated camera image orientation/scaling * cleanup and expose ZBarHelpController * expose enable for reader capture processing * workaround iOS 4.2 hang diff --git a/iphone/ZBarReaderView.m b/iphone/ZBarReaderView.m index b8c2228..343c955 100644 --- a/iphone/ZBarReaderView.m +++ b/iphone/ZBarReaderView.m @@ -88,6 +88,8 @@ - (void) initSubviews fpsLabel.font = [UIFont systemFontOfSize: 18]; fpsLabel.textAlignment = UITextAlignmentRight; [fpsView addSubview: fpsLabel]; + + self.zoom = 1.25; } - (id) initWithImageScanner: (ZBarImageScanner*) scanner @@ -113,7 +115,6 @@ - (id) initWithImageScanner: (ZBarImageScanner*) scanner action: @selector(handlePinch)]; [self addGestureRecognizer: pinch]; - self.zoom = 1.25; return(self); } @@ -171,15 +172,20 @@ - (void) resetTracking - (void) setImageSize: (CGSize) size { CGSize psize = preview.bounds.size; - CGFloat scalex = size.width / psize.width; - CGFloat scaley = size.height / psize.height; + CGFloat scalex = size.width / psize.height; + CGFloat scaley = size.height / psize.width; imageScale = (scalex > scaley) ? scalex : scaley; + // match overlay to preview image + overlay.bounds = CGRectMake(0, 0, size.width, size.height); + CGFloat scale = 1 / imageScale; + CATransform3D xform = CATransform3DMakeRotation(M_PI / 2, 0, 0, 1); + overlay.transform = CATransform3DScale(xform, scale, scale, 1); tracking.borderWidth = imageScale / zoom; zlog(@"scaling: layer=%@ image=%@ scale=%g %c %g = 1/%g", NSStringFromCGSize(psize), NSStringFromCGSize(size), - scalex, (scalex > scaley) ? '>' : '<', scaley, 1 / imageScale); + scalex, (scalex > scaley) ? '>' : '<', scaley, scale); [self resetTracking]; } diff --git a/iphone/ZBarReaderViewImpl_Capture.m b/iphone/ZBarReaderViewImpl_Capture.m index 41879d6..438de7c 100644 --- a/iphone/ZBarReaderViewImpl_Capture.m +++ b/iphone/ZBarReaderViewImpl_Capture.m @@ -304,17 +304,9 @@ - (void) observeValueForKeyPath: (NSString*) path context: (void*) ctx { if(obj == captureReader && - [path isEqualToString: @"size"]) { - // adjust tracking overlay to match image size - CGSize size = captureReader.size; - overlay.bounds = CGRectMake(0, 0, size.width, size.height); - - CGSize rsize = CGSizeMake(size.height, size.width); - [self setImageSize: rsize]; - CGFloat scale = 1 / imageScale; - CATransform3D xform = CATransform3DMakeRotation(M_PI / 2, 0, 0, 1); - overlay.transform = CATransform3DScale(xform, scale, scale, 1); - } + [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 ", diff --git a/iphone/ZBarReaderViewImpl_Simulator.m b/iphone/ZBarReaderViewImpl_Simulator.m index 2fc7607..430a72a 100644 --- a/iphone/ZBarReaderViewImpl_Simulator.m +++ b/iphone/ZBarReaderViewImpl_Simulator.m @@ -91,6 +91,7 @@ @interface ZBarReaderViewImpl { ZBarImageScanner *scanner; UIImage *scanImage; + CALayer *previewImage; BOOL enableCache; } @end @@ -130,6 +131,10 @@ - (void) initSubviews preview.frame = self.bounds; [self.layer addSublayer: preview]; + previewImage = [CALayer new]; + previewImage.frame = self.bounds; + [preview addSublayer: previewImage]; + [super initSubviews]; } @@ -137,6 +142,8 @@ - (void) dealloc { [scanner release]; scanner = nil; + [previewImage release]; + previewImage = nil; [super dealloc]; } @@ -165,27 +172,25 @@ - (void) scanImage: (UIImage*) image scale: 1.0 orientation: UIImageOrientationUp]; - CGSize size = image.size; - overlay.bounds = CGRectMake(0, 0, size.width, size.height); - [self setImageSize: size]; - - preview.contentsScale = imageScale; - preview.contentsGravity = kCAGravityCenter; - preview.contents = (id)cgimage; + [self setImageSize: image.size]; - // match overlay to image - CGFloat scale = 1 / imageScale; - overlay.transform = CATransform3DMakeScale(scale, scale, 1); + [CATransaction begin]; + [CATransaction setDisableActions: YES]; + previewImage.contentsScale = imageScale; + previewImage.contentsGravity = kCAGravityCenter; + previewImage.transform = CATransform3DMakeRotation(M_PI_2, 0, 0, 1); + previewImage.contents = (id)cgimage; + [CATransaction commit]; ZBarImage *zimg = [[ZBarImage alloc] initWithCGImage: cgimage]; - size = zimg.size; - zimg.crop = CGRectMake(zoomCrop.origin.y * size.width, - zoomCrop.origin.x * size.height, - zoomCrop.size.height * size.width, - zoomCrop.size.width * size.height); + CGSize size = zimg.size; + zimg.crop = CGRectMake(zoomCrop.origin.x * size.width, + zoomCrop.origin.y * size.height, + zoomCrop.size.width * size.width, + zoomCrop.size.height * size.height); int nsyms = [scanner scanImage: zimg]; zlog(@"scan image: %@ crop=%@ nsyms=%d", From 2d51182c01782b33c7de24d4ef34a672fe6c8075 Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 28 Nov 2010 19:13:52 -0800 Subject: [PATCH 245/328] 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 --- ChangeLog | 5 + include/zbar.h | 62 ++++++++++++ iphone/ZBarSymbol.m | 13 ++- iphone/include/ZBarSDK/ZBarSymbol.h | 2 + java/Makefile.am | 6 +- java/net/sourceforge/zbar/Modifier.java | 42 ++++++++ java/net/sourceforge/zbar/Symbol.java | 6 ++ java/zbarjni.c | 36 +++++++ perl/ZBar.pm | 10 ++ perl/ZBar.xs | 49 +++++++++- perl/t/Decoder.t | 16 ++- perl/t/Image.t | 17 +++- perl/t/ZBar.t | 9 +- perl/typemap | 1 + python/decoder.c | 38 +++++++ python/enum.c | 15 +++ python/image.c | 4 +- python/symbol.c | 18 ++++ python/test/test_zbar.py | 27 +++++ python/zbarmodule.c | 13 ++- python/zbarmodule.h | 3 + zbar/decoder.c | 34 +++++-- zbar/decoder.h | 4 +- zbar/decoder/code128.c | 10 +- zbar/decoder/code39.c | 1 + zbar/decoder/code93.c | 1 + zbar/decoder/databar.c | 2 + zbar/decoder/ean.c | 1 + zbar/decoder/i25.c | 1 + zbar/decoder/pdf417.c | 1 + zbar/img_scanner.c | 4 + zbar/symbol.c | 125 ++++++++++++++++++------ zbar/symbol.h | 2 + 33 files changed, 528 insertions(+), 50 deletions(-) create mode 100644 java/net/sourceforge/zbar/Modifier.java diff --git a/ChangeLog b/ChangeLog index e2c8ab0..e3a48f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,9 @@ current: + * 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! diff --git a/include/zbar.h b/include/zbar.h index 84c5faa..1e02537 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -155,6 +155,25 @@ typedef enum zbar_config_e { 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) @@ -187,6 +206,20 @@ extern const char *zbar_get_symbol_name(zbar_symbol_type_t sym); */ 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, @@ -277,6 +310,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 */ @@ -1243,6 +1290,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 */ @@ -1290,6 +1345,13 @@ 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 diff --git a/iphone/ZBarSymbol.m b/iphone/ZBarSymbol.m index 15f9d9a..3131205 100644 --- a/iphone/ZBarSymbol.m +++ b/iphone/ZBarSymbol.m @@ -25,7 +25,8 @@ @implementation ZBarSymbol -@dynamic type, typeName, data, quality, count, zbarSymbol; +@dynamic type, typeName, configMask, modifierMask, data, quality, count, + zbarSymbol; + (NSString*) nameForType: (zbar_symbol_type_t) type { @@ -60,6 +61,16 @@ - (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)]); diff --git a/iphone/include/ZBarSDK/ZBarSymbol.h b/iphone/include/ZBarSDK/ZBarSymbol.h index 900312d..c8a8574 100644 --- a/iphone/include/ZBarSDK/ZBarSymbol.h +++ b/iphone/include/ZBarSDK/ZBarSymbol.h @@ -54,6 +54,8 @@ using namespace zbar; @property (readonly, nonatomic) zbar_symbol_type_t type; @property (readonly, nonatomic) NSString *typeName; +@property (readonly, nonatomic) NSUInteger configMask; +@property (readonly, nonatomic) NSUInteger modifierMask; @property (readonly, nonatomic) NSString *data; @property (readonly, nonatomic) int quality; @property (readonly, nonatomic) int count; diff --git a/java/Makefile.am b/java/Makefile.am index 8943917..beef4de 100644 --- a/java/Makefile.am +++ b/java/Makefile.am @@ -12,7 +12,7 @@ BUILT_SOURCES = zbarjni.h MAINTAINERCLEANFILES = zbarjni.h zbar_jar_SRCS = \ - $(PKG)/Config.java $(PKG)/Orientation.java \ + $(PKG)/Config.java $(PKG)/Modifier.java $(PKG)/Orientation.java \ $(PKG)/Symbol.java $(PKG)/SymbolIterator.java $(PKG)/SymbolSet.java \ $(PKG)/Image.java $(PKG)/ImageScanner.java @@ -35,5 +35,5 @@ zbar.jar: $(zbar_jar_SRCS) check-local: echo "making check in java" - cd $(abs_srcdir); $(JAVAC) -classpath $(CLASSPATH):$(abs_builddir)/zbar.jar -d $(abs_builddir) $(test_SRCS) - $(top_builddir)/libtool -dlopen libzbarjni.la --mode=execute $(JAVA) -classpath zbar.jar:$(CLASSPATH):. -Xcheck:jni org.junit.runner.JUnitCore $(test_CLASSES) + cd $(abs_srcdir); $(JAVAC) -classpath $(abs_builddir)/zbar.jar:.:$(CLASSPATH) -d $(abs_builddir) $(test_SRCS) + $(top_builddir)/libtool -dlopen $(top_builddir)/zbar/libzbar.la -dlopen libzbarjni.la --mode=execute $(JAVA) -Xcheck:jni -classpath zbar.jar:.:$(CLASSPATH) org.junit.runner.JUnitCore $(test_CLASSES) diff --git a/java/net/sourceforge/zbar/Modifier.java b/java/net/sourceforge/zbar/Modifier.java new file mode 100644 index 0000000..451bb2e --- /dev/null +++ b/java/net/sourceforge/zbar/Modifier.java @@ -0,0 +1,42 @@ +/*------------------------------------------------------------------------ + * Modifier + * + * Copyright 2010 (c) Jeff Brown + * + * This file is part of the ZBar Bar Code Reader. + * + * The ZBar Bar Code Reader is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * The ZBar Bar Code Reader is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with the ZBar Bar Code Reader; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zbar + *------------------------------------------------------------------------*/ + +package net.sourceforge.zbar; + +/** Decoder symbology modifiers. + */ +public class Modifier +{ + /** barcode tagged as GS1 (EAN.UCC) reserved + * (eg, FNC1 before first data character). + * data may be parsed as a sequence of GS1 AIs + */ + public static final int GS1 = 0; + + /** barcode tagged as AIM reserved + * (eg, FNC1 after first character or digit pair) + */ + public static final int AIM = 1; +} diff --git a/java/net/sourceforge/zbar/Symbol.java b/java/net/sourceforge/zbar/Symbol.java index 8445a84..43ea6d4 100644 --- a/java/net/sourceforge/zbar/Symbol.java +++ b/java/net/sourceforge/zbar/Symbol.java @@ -110,6 +110,12 @@ public int getType () private native int getType(long peer); + /** Retrieve symbology boolean configs settings used during decode. */ + public native int getConfigMask(); + + /** Retrieve symbology characteristics detected during decode. */ + public native int getModifierMask(); + /** Retrieve data decoded from symbol as a String. */ public native String getData(); diff --git a/java/zbarjni.c b/java/zbarjni.c index e61e666..584a9d0 100644 --- a/java/zbarjni.c +++ b/java/zbarjni.c @@ -1,3 +1,25 @@ +/*------------------------------------------------------------------------ + * Copyright 2010 (c) Jeff Brown + * + * 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 #include #include @@ -153,6 +175,20 @@ Java_net_sourceforge_zbar_Symbol_getType (JNIEnv *env, return(zbar_symbol_get_type(PEER_CAST(peer))); } +JNIEXPORT jint JNICALL +Java_net_sourceforge_zbar_Symbol_getConfigMask (JNIEnv *env, + jobject obj) +{ + return(zbar_symbol_get_configs(GET_PEER(Symbol, obj))); +} + +JNIEXPORT jint JNICALL +Java_net_sourceforge_zbar_Symbol_getModifierMask (JNIEnv *env, + jobject obj) +{ + return(zbar_symbol_get_modifiers(GET_PEER(Symbol, obj))); +} + JNIEXPORT jstring JNICALL Java_net_sourceforge_zbar_Symbol_getData (JNIEnv *env, jobject obj) diff --git a/perl/ZBar.pm b/perl/ZBar.pm index 460c439..ce77931 100644 --- a/perl/ZBar.pm +++ b/perl/ZBar.pm @@ -161,6 +161,16 @@ Decoder configuration constants: =back +Symbology modifier constants: + +=over 4 + +=item Modifier::GS1 + +=item Modifier::AIM + +=back + Symbol orientation constants: =over 4 diff --git a/perl/ZBar.xs b/perl/ZBar.xs index 8a537ba..77db677 100644 --- a/perl/ZBar.xs +++ b/perl/ZBar.xs @@ -53,6 +53,7 @@ static AV *LOOKUP_zbar_color_t = NULL; static AV *LOOKUP_zbar_symbol_type_t = NULL; static AV *LOOKUP_zbar_error_t = NULL; static AV *LOOKUP_zbar_config_t = NULL; +static AV *LOOKUP_zbar_modifier_t = NULL; static AV *LOOKUP_zbar_orientation_t = NULL; #define CONSTANT(typ, prefix, sym, name) \ @@ -94,6 +95,15 @@ static inline void check_error (int rc, void *obj) } \ } while(0); +#define PUSH_ENUM_MASK(typ, TYP, val) \ + do { \ + unsigned mask = (val); \ + int i; \ + for(i = 0; i < ZBAR_ ## TYP ## _NUM; i++, mask >>= 1) \ + if(mask & 1) \ + XPUSHs(LOOKUP_ENUM(typ, i)); \ + } while(0); + static void image_cleanup_handler (zbar_image_t *image) { SV *data = zbar_image_get_userdata(image); @@ -152,7 +162,7 @@ static inline void activate_handler (handler_wrapper_t *wrap, SAVETMPS; PUSHMARK(SP); - EXTEND(SP, 2); + EXTEND(SP, 3); PUSHs(sv_mortalcopy(wrap->instance)); if(param) PUSHs(param); @@ -284,6 +294,16 @@ BOOT: CONSTANT(config, CFG_, Y_DENSITY, "y-density"); } +MODULE = Barcode::ZBar PACKAGE = Barcode::ZBar::Modifier PREFIX = zbar_mod_ + +BOOT: + { + HV *stash = gv_stashpv("Barcode::ZBar::Modifier", TRUE); + + LOOKUP_zbar_modifier_t = newAV(); + CONSTANT(modifier, MOD_, GS1, "GS1"); + CONSTANT(modifier, MOD_, AIM, "AIM"); + } MODULE = Barcode::ZBar PACKAGE = Barcode::ZBar::Orient PREFIX = zbar_orientation_ @@ -336,6 +356,18 @@ zbar_symbol_type_t zbar_symbol_get_type(symbol) Barcode::ZBar::Symbol symbol +SV * +zbar_symbol_get_configs(symbol) + Barcode::ZBar::Symbol symbol + PPCODE: + PUSH_ENUM_MASK(config, CFG, zbar_symbol_get_configs(symbol)); + +SV * +zbar_symbol_get_modifiers(symbol) + Barcode::ZBar::Symbol symbol + PPCODE: + PUSH_ENUM_MASK(modifier, MOD, zbar_symbol_get_modifiers(symbol)); + SV * zbar_symbol_get_data(symbol) Barcode::ZBar::Symbol symbol @@ -758,6 +790,21 @@ zbar_symbol_type_t zbar_decoder_get_type(decoder) Barcode::ZBar::Decoder decoder +SV * +zbar_decoder_get_configs(decoder, symbology) + Barcode::ZBar::Decoder decoder + zbar_symbol_type_t symbology + PPCODE: + if(symbology == ZBAR_NONE) + symbology = zbar_decoder_get_type(decoder) + PUSH_ENUM_MASK(config, CFG, zbar_decoder_get_configs(decoder, symbology)); + +SV * +zbar_decoder_get_modifiers(decoder) + Barcode::ZBar::Decoder decoder + PPCODE: + PUSH_ENUM_MASK(modifier, MOD, zbar_decoder_get_modifiers(decoder)); + int zbar_decoder_get_direction(decoder) Barcode::ZBar::Decoder decoder diff --git a/perl/t/Decoder.t b/perl/t/Decoder.t index 07244cc..12ba86f 100755 --- a/perl/t/Decoder.t +++ b/perl/t/Decoder.t @@ -3,7 +3,7 @@ use warnings; use strict; -use Test::More tests => 15; +use Test::More tests => 17; ######################### @@ -19,7 +19,8 @@ $decoder->parse_config('enable'); ######################### can_ok($decoder, qw(set_config parse_config reset new_scan decode_width - get_color get_direction get_data get_type set_handler)); + get_color get_configs get_direction get_data get_modifiers + get_type set_handler)); ######################### @@ -78,6 +79,17 @@ is($sym, Barcode::ZBar::Symbol::EAN13, 'EAN-13 type'); ######################### +is_deeply([$decoder->get_configs($sym)], + [Barcode::ZBar::Config::ENABLE, + Barcode::ZBar::Config::EMIT_CHECK], + 'read configs'); + +######################### + +is_deeply([$decoder->get_modifiers()], [], 'read modifiers'); + +######################### + is($decoder->get_data(), '6268964977804', 'EAN-13 data'); ######################### diff --git a/perl/t/Image.t b/perl/t/Image.t index 7876f72..d7ef6c1 100755 --- a/perl/t/Image.t +++ b/perl/t/Image.t @@ -3,7 +3,7 @@ use warnings; use strict; -use Test::More tests => 27; +use Test::More tests => 29; ######################### @@ -114,8 +114,8 @@ SKIP: { ######################### - can_ok($sym, qw(get_type get_data get_quality get_count get_loc - get_orientation)); + can_ok($sym, qw(get_type get_configs get_modifiers get_data get_quality + get_count get_loc get_orientation)); ######################### @@ -123,6 +123,17 @@ SKIP: { ######################### + is_deeply([$sym->get_configs()], + [Barcode::ZBar::Config::ENABLE, + Barcode::ZBar::Config::EMIT_CHECK], + 'result configs'); + + ######################### + + is_deeply([$sym->get_modifiers()], [], 'result modifiers'); + + ######################### + is($sym->get_data(), '9876543210128', 'result data'); ######################### diff --git a/perl/t/ZBar.t b/perl/t/ZBar.t index 4e4489b..0e3a867 100755 --- a/perl/t/ZBar.t +++ b/perl/t/ZBar.t @@ -3,7 +3,7 @@ use warnings; use strict; -use Test::More tests => 33; +use Test::More tests => 37; ######################### @@ -50,6 +50,13 @@ test_enum('config', ######################### +test_enum('modifier', + [Barcode::ZBar::Modifier::GS1, 'GS1', 0], + [Barcode::ZBar::Modifier::AIM, 'AIM', 1], +); + +######################### + test_enum('orientation', [Barcode::ZBar::Orient::UNKNOWN, 'UNKNOWN', -1], [Barcode::ZBar::Orient::UP, 'UP', 0], diff --git a/perl/typemap b/perl/typemap index e088fe2..dda1979 100644 --- a/perl/typemap +++ b/perl/typemap @@ -14,6 +14,7 @@ zbar_color_t T_ENUM zbar_error_t T_ENUM zbar_symbol_type_t T_ENUM zbar_config_t T_ENUM +zbar_modifier_t T_ENUM zbar_orientation_t T_ENUM # special scalars diff --git a/python/decoder.c b/python/decoder.c index f8ef7b8..5698094 100644 --- a/python/decoder.c +++ b/python/decoder.c @@ -103,6 +103,23 @@ decoder_get_type (zbarDecoder *self, return(zbarSymbol_LookupEnum(sym)); } +static PyObject* +decoder_get_configs (zbarDecoder *self, + void *closure) +{ + unsigned int sym = zbar_decoder_get_type(self->zdcode); + unsigned int mask = zbar_decoder_get_configs(self->zdcode, sym); + return(zbarEnum_SetFromMask(config_enum, mask)); +} + +static PyObject* +decoder_get_modifiers (zbarDecoder *self, + void *closure) +{ + unsigned int mask = zbar_decoder_get_modifiers(self->zdcode); + return(zbarEnum_SetFromMask(modifier_enum, mask)); +} + static PyObject* decoder_get_data (zbarDecoder *self, void *closure) @@ -121,6 +138,8 @@ decoder_get_direction (zbarDecoder *self, static PyGetSetDef decoder_getset[] = { { "color", (getter)decoder_get_color, }, { "type", (getter)decoder_get_type, }, + { "configs", (getter)decoder_get_configs, }, + { "modifiers", (getter)decoder_get_modifiers, }, { "data", (getter)decoder_get_data, }, { "direction", (getter)decoder_get_direction }, { NULL, }, @@ -146,6 +165,23 @@ decoder_set_config (zbarDecoder *self, Py_RETURN_NONE; } +static PyObject* +decoder_get_configs_meth (zbarDecoder *self, + PyObject *args, + PyObject *kwds) +{ + zbar_symbol_type_t sym = ZBAR_NONE; + static char *kwlist[] = { "symbology", NULL }; + if(!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &sym)) + return(NULL); + + if(sym == ZBAR_NONE) + sym = zbar_decoder_get_type(self->zdcode); + + unsigned int mask = zbar_decoder_get_configs(self->zdcode, sym); + return(zbarEnum_SetFromMask(config_enum, mask)); +} + static PyObject* decoder_parse_config (zbarDecoder *self, PyObject *args, @@ -270,6 +306,8 @@ decoder_decode_width (zbarDecoder *self, static PyMethodDef decoder_methods[] = { { "set_config", (PyCFunction)decoder_set_config, METH_VARARGS | METH_KEYWORDS, }, + { "get_configs", (PyCFunction)decoder_get_configs_meth, + METH_VARARGS | METH_KEYWORDS, }, { "parse_config", (PyCFunction)decoder_parse_config, METH_VARARGS | METH_KEYWORDS, }, { "reset", (PyCFunction)decoder_reset, diff --git a/python/enum.c b/python/enum.c index f875287..5f83fc6 100644 --- a/python/enum.c +++ b/python/enum.c @@ -205,3 +205,18 @@ zbarEnum_LookupValue (zbarEnum *self, Py_DECREF(key); return(e); } + +PyObject* +zbarEnum_SetFromMask (zbarEnum *self, + unsigned int mask) +{ + PyObject *result = PySet_New(NULL); + PyObject *key, *item; + Py_ssize_t i = 0; + while(PyDict_Next(self->byvalue, &i, &key, &item)) { + int val = PyInt_AsLong(item); + if(val < sizeof(mask) * 8 && ((mask >> val) & 1)) + PySet_Add(result, item); + } + return(result); +} diff --git a/python/image.c b/python/image.c index a617d4f..760d13a 100644 --- a/python/image.c +++ b/python/image.c @@ -139,10 +139,12 @@ image_set_format (zbarImage *self, PyErr_SetString(PyExc_TypeError, "cannot delete format attribute"); return(-1); } - char *format; + char *format = NULL; Py_ssize_t len; if(PyString_AsStringAndSize(value, &format, &len) || !format || len != 4) { + if(!format) + format = "(nil)"; PyErr_Format(PyExc_ValueError, "format '%.50s' is not a valid four character code", format); diff --git a/python/symbol.c b/python/symbol.c index 80ba99c..a3eb9f6 100644 --- a/python/symbol.c +++ b/python/symbol.c @@ -80,6 +80,22 @@ symbol_get_type (zbarSymbol *self, return(zbarSymbol_LookupEnum(zbar_symbol_get_type(self->zsym))); } +static PyObject* +symbol_get_configs (zbarSymbol *self, + void *closure) +{ + unsigned int mask = zbar_symbol_get_configs(self->zsym); + return(zbarEnum_SetFromMask(config_enum, mask)); +} + +static PyObject* +symbol_get_modifiers (zbarSymbol *self, + void *closure) +{ + unsigned int mask = zbar_symbol_get_modifiers(self->zsym); + return(zbarEnum_SetFromMask(modifier_enum, mask)); +} + static PyObject* symbol_get_long (zbarSymbol *self, void *closure) @@ -138,6 +154,8 @@ symbol_get_orientation (zbarSymbol *self, static PyGetSetDef symbol_getset[] = { { "type", (getter)symbol_get_type, }, + { "configs", (getter)symbol_get_configs, }, + { "modifiers", (getter)symbol_get_modifiers, }, { "quality", (getter)symbol_get_long, NULL, NULL, (void*)0 }, { "count", (getter)symbol_get_long, NULL, NULL, (void*)1 }, { "data", (getter)symbol_get_data, }, diff --git a/python/test/test_zbar.py b/python/test/test_zbar.py index 42dddbd..bb186ce 100755 --- a/python/test/test_zbar.py +++ b/python/test/test_zbar.py @@ -70,6 +70,13 @@ def test_configs(self): self.assert_(int(cfg) >= 0) self.assert_(is_identifier.match(str(cfg))) + def test_modifiers(self): + for mod in (zbar.Modifier.GS1, + zbar.Modifier.AIM): + self.assert_(isinstance(mod, zbar.EnumItem)) + self.assert_(int(mod) >= 0) + self.assert_(is_identifier.match(str(mod))) + def test_symbologies(self): for sym in (zbar.Symbol.NONE, zbar.Symbol.PARTIAL, @@ -193,6 +200,9 @@ def handler(dcode, closure): else: self.assert_(sym is zbar.Symbol.EAN13) + self.assertEqual(self.dcode.configs, + set((zbar.Config.ENABLE, zbar.Config.EMIT_CHECK))) + self.assertEqual(self.dcode.modifiers, set()) self.assertEqual(self.dcode.data, '6268964977804') self.assert_(self.dcode.color is zbar.BAR) self.assertEqual(self.dcode.direction, 1) @@ -210,6 +220,9 @@ def test_databar(self): sym is zbar.Symbol.PARTIAL) self.assert_(sym is zbar.Symbol.DATABAR) + self.assertEqual(self.dcode.get_configs(zbar.Symbol.EAN13), + set((zbar.Config.ENABLE, zbar.Config.EMIT_CHECK))) + self.assertEqual(self.dcode.modifiers, set((zbar.Modifier.GS1,))) self.assertEqual(self.dcode.data, '0124012345678905') self.assert_(self.dcode.color is zbar.BAR) self.assertEqual(self.dcode.direction, 1) @@ -344,6 +357,20 @@ def test_scan(self): self.assert_(sym.type is zbar.Symbol.EAN13) self.assert_(sym.type is sym.EAN13) self.assertEqual(str(sym.type), 'EAN13') + + cfgs = sym.configs + self.assert_(isinstance(cfgs, set)) + for cfg in cfgs: + self.assert_(isinstance(cfg, zbar.EnumItem)) + self.assertEqual(cfgs, + set((zbar.Config.ENABLE, zbar.Config.EMIT_CHECK))) + + mods = sym.modifiers + self.assert_(isinstance(mods, set)) + for mod in mods: + self.assert_(isinstance(mod, zbar.EnumItem)) + self.assertEqual(mods, set()) + self.assert_(sym.quality > 0) self.assertEqual(sym.count, 0) diff --git a/python/zbarmodule.c b/python/zbarmodule.c index d3ac2b1..0900bdd 100644 --- a/python/zbarmodule.c +++ b/python/zbarmodule.c @@ -77,6 +77,12 @@ static const enumdef config_defs[] = { { NULL, } }; +static const enumdef modifier_defs[] = { + { "GS1", ZBAR_MOD_GS1 }, + { "AIM", ZBAR_MOD_AIM }, + { NULL, } +}; + static const enumdef orient_defs[] = { { "UNKNOWN", ZBAR_ORIENT_UNKNOWN }, { "UP", ZBAR_ORIENT_UP }, @@ -100,6 +106,7 @@ object_to_bool (PyObject *obj, PyObject *zbar_exc[ZBAR_ERR_NUM]; zbarEnumItem *color_enum[2]; zbarEnum *config_enum; +zbarEnum *modifier_enum; PyObject *symbol_enum; zbarEnumItem *symbol_NONE; zbarEnum *orient_enum; @@ -173,9 +180,10 @@ initzbar (void) /* initialize constant containers */ config_enum = zbarEnum_New(); + modifier_enum = zbarEnum_New(); symbol_enum = PyDict_New(); orient_enum = zbarEnum_New(); - if(!config_enum || !symbol_enum || !orient_enum) + if(!config_enum || !modifier_enum || !symbol_enum || !orient_enum) return; zbar_exc[0] = (PyObject*)&zbarException_Type; @@ -201,6 +209,7 @@ initzbar (void) PyModule_AddObject(mod, "EnumItem", (PyObject*)&zbarEnumItem_Type); PyModule_AddObject(mod, "Image", (PyObject*)&zbarImage_Type); PyModule_AddObject(mod, "Config", (PyObject*)config_enum); + PyModule_AddObject(mod, "Modifier", (PyObject*)modifier_enum); PyModule_AddObject(mod, "Orient", (PyObject*)orient_enum); PyModule_AddObject(mod, "Symbol", (PyObject*)&zbarSymbol_Type); PyModule_AddObject(mod, "SymbolSet", (PyObject*)&zbarSymbolSet_Type); @@ -224,6 +233,8 @@ initzbar (void) const enumdef *item; for(item = config_defs; item->strval; item++) zbarEnum_Add(config_enum, item->intval, item->strval); + for(item = modifier_defs; item->strval; item++) + zbarEnum_Add(modifier_enum, item->intval, item->strval); for(item = orient_defs; item->strval; item++) zbarEnum_Add(orient_enum, item->intval, item->strval); diff --git a/python/zbarmodule.h b/python/zbarmodule.h index f2252ec..938aa4f 100644 --- a/python/zbarmodule.h +++ b/python/zbarmodule.h @@ -63,6 +63,8 @@ extern int zbarEnum_Add(zbarEnum *self, const char *name); extern zbarEnumItem *zbarEnum_LookupValue(zbarEnum *self, int val); +extern PyObject *zbarEnum_SetFromMask(zbarEnum *self, + unsigned int mask); typedef struct { PyObject_HEAD @@ -146,6 +148,7 @@ extern PyTypeObject zbarScanner_Type; extern zbarEnumItem *color_enum[2]; extern zbarEnum *config_enum; +extern zbarEnum *modifier_enum; extern PyObject *symbol_enum; extern zbarEnumItem *symbol_NONE; extern zbarEnum *orient_enum; diff --git a/zbar/decoder.c b/zbar/decoder.c index e244555..c7ac934 100644 --- a/zbar/decoder.c +++ b/zbar/decoder.c @@ -207,6 +207,11 @@ zbar_symbol_type_t zbar_decoder_get_type (const zbar_decoder_t *dcode) return(dcode->type); } +unsigned int zbar_decoder_get_modifiers (const zbar_decoder_t *dcode) +{ + return(dcode->modifiers); +} + zbar_symbol_type_t zbar_decode_width (zbar_decoder_t *dcode, unsigned w) { @@ -273,12 +278,11 @@ zbar_symbol_type_t zbar_decode_width (zbar_decoder_t *dcode, return(sym); } -static inline int decoder_set_config_bool (zbar_decoder_t *dcode, - zbar_symbol_type_t sym, - zbar_config_t cfg, - int val) +static inline const unsigned int* +decoder_get_configp (const zbar_decoder_t *dcode, + zbar_symbol_type_t sym) { - unsigned *config = NULL; + const unsigned int *config; switch(sym) { #ifdef ENABLE_EAN case ZBAR_EAN13: @@ -354,8 +358,26 @@ static inline int decoder_set_config_bool (zbar_decoder_t *dcode, /* FIXME handle addons */ default: - return(1); + config = NULL; } + return(config); +} + +unsigned int zbar_decoder_get_configs (const zbar_decoder_t *dcode, + zbar_symbol_type_t sym) +{ + const unsigned *config = decoder_get_configp(dcode, sym); + if(!config) + return(0); + return(*config); +} + +static inline int decoder_set_config_bool (zbar_decoder_t *dcode, + zbar_symbol_type_t sym, + zbar_config_t cfg, + int val) +{ + unsigned *config = (void*)decoder_get_configp(dcode, sym); if(!config || cfg >= ZBAR_CFG_NUM) return(1); diff --git a/zbar/decoder.h b/zbar/decoder.h index 53ab151..17c3599 100644 --- a/zbar/decoder.h +++ b/zbar/decoder.h @@ -79,6 +79,7 @@ #define CFG(dcode, cfg) ((dcode).configs[(cfg) - ZBAR_CFG_MIN_LEN]) #define TEST_CFG(config, cfg) (((config) >> (cfg)) & 1) +#define MOD(mod) (1 << (mod)) /* symbology independent decoder state */ struct zbar_decoder_s { @@ -86,6 +87,7 @@ struct zbar_decoder_s { unsigned w[DECODE_WINDOW]; /* window of last N bar widths */ zbar_symbol_type_t type; /* type of last decoded data */ zbar_symbol_type_t lock; /* buffer lock */ + unsigned modifiers; /* symbology modifier */ int direction; /* direction of last decoded data */ unsigned s6; /* 6-element character width */ @@ -227,6 +229,6 @@ static inline char size_buf (zbar_decoder_t *dcode, } extern const char *_zbar_decoder_buf_dump (unsigned char *buf, - unsigned int buflen); + unsigned int buflen); #endif diff --git a/zbar/decoder/code128.c b/zbar/decoder/code128.c index 78ec23a..e3a8b4c 100644 --- a/zbar/decoder/code128.c +++ b/zbar/decoder/code128.c @@ -331,6 +331,7 @@ static inline unsigned char postprocess (zbar_decoder_t *dcode) unsigned char code = 0, charset; code128_decoder_t *dcode128 = &dcode->code128; dprintf(2, "\n postproc len=%d", dcode128->character); + dcode->modifiers = 0; dcode->direction = 1 - 2 * dcode128->direction; if(dcode128->direction) { /* reverse buffer */ @@ -403,7 +404,14 @@ static inline unsigned char postprocess (zbar_decoder_t *dcode) } } else if(code == FNC1) { - /* FIXME FNC1 - Code 128 subsets or ASCII 0x1d */ + /* FNC1 - Code 128 subsets or ASCII 0x1d */ + if(i == 1) + dcode->modifiers |= MOD(ZBAR_MOD_GS1); + else if(i == 2) + dcode->modifiers |= MOD(ZBAR_MOD_AIM); + else if(i < dcode->code128.character - 3) + dcode->buf[j++] = 0x1d; + /*else drop trailing FNC1 */ } else if(code >= START_A) { dprintf(1, " [truncated]\n"); diff --git a/zbar/decoder/code39.c b/zbar/decoder/code39.c index 35bbf0f..bceeba6 100644 --- a/zbar/decoder/code39.c +++ b/zbar/decoder/code39.c @@ -234,6 +234,7 @@ static inline void code39_postprocess (zbar_decoder_t *dcode) : '?'); dcode->buflen = i; dcode->buf[i] = '\0'; + dcode->modifiers = 0; } static inline int diff --git a/zbar/decoder/code93.c b/zbar/decoder/code93.c index ce83da4..6d5dee0 100644 --- a/zbar/decoder/code93.c +++ b/zbar/decoder/code93.c @@ -320,6 +320,7 @@ postprocess (zbar_decoder_t *dcode) dcode->buflen = j; dcode->buf[j] = '\0'; + dcode->modifiers = 0; return(0); } diff --git a/zbar/decoder/databar.c b/zbar/decoder/databar.c index bd3b91a..9f4bef6 100644 --- a/zbar/decoder/databar.c +++ b/zbar/decoder/databar.c @@ -655,6 +655,7 @@ match_segment (zbar_decoder_t *dcode, return(ZBAR_PARTIAL); databar_postprocess(dcode, d); + dcode->modifiers = MOD(ZBAR_MOD_GS1); dcode->direction = 1 - 2 * (seg->side ^ seg->color ^ 1); return(ZBAR_DATABAR); } @@ -823,6 +824,7 @@ match_segment_exp (zbar_decoder_t *dcode, * so direction is impossible to determine at this level */ dcode->direction = (1 - 2 * (seg->side ^ seg->color)) * dir; + dcode->modifiers = MOD(ZBAR_MOD_GS1); return(ZBAR_DATABAR_EXP); } #undef IDX diff --git a/zbar/decoder/ean.c b/zbar/decoder/ean.c index 67fdd73..e3aa62e 100644 --- a/zbar/decoder/ean.c +++ b/zbar/decoder/ean.c @@ -659,6 +659,7 @@ static inline void postprocess (zbar_decoder_t *dcode, dcode->buflen = j; dcode->buf[j] = '\0'; dcode->direction = 1 - 2 * ean->direction; + dcode->modifiers = 0; } zbar_symbol_type_t _zbar_decode_ean (zbar_decoder_t *dcode) diff --git a/zbar/decoder/i25.c b/zbar/decoder/i25.c index 7d3d3af..58e66d5 100644 --- a/zbar/decoder/i25.c +++ b/zbar/decoder/i25.c @@ -189,6 +189,7 @@ static inline signed char i25_decode_end (zbar_decoder_t *dcode) dcode->buflen = dcode25->character; dcode->buf[dcode25->character] = '\0'; + dcode->modifiers = 0; dprintf(2, " [valid end]\n"); dcode25->character = -1; return(ZBAR_I25); diff --git a/zbar/decoder/pdf417.c b/zbar/decoder/pdf417.c index e2c4161..ed01de7 100644 --- a/zbar/decoder/pdf417.c +++ b/zbar/decoder/pdf417.c @@ -214,6 +214,7 @@ zbar_symbol_type_t _zbar_decode_pdf417 (zbar_decoder_t *dcode) dprintf(1, " [valid stop]"); /* FIXME check trailing bar and qz */ dcode->direction = 1 - 2 * dcode417->direction; + dcode->modifiers = 0; release_lock(dcode, ZBAR_PDF417); dcode417->character = -1; } diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 8598643..e1ff946 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -296,6 +296,8 @@ static inline void cache_sym (zbar_image_scanner_t *iscn, /* FIXME reuse sym */ entry = _zbar_image_scanner_alloc_sym(iscn, sym->type, sym->datalen + 1); + entry->configs = sym->configs; + entry->modifiers = sym->modifiers; memcpy(entry->data, sym->data, sym->datalen); entry->time = sym->time - CACHE_HYSTERESIS; entry->cache_count = 0; @@ -444,6 +446,8 @@ static void symbol_handler (zbar_decoder_t *dcode) } sym = _zbar_image_scanner_alloc_sym(iscn, type, datalen + 1); + sym->configs = zbar_decoder_get_configs(dcode, type); + sym->modifiers = zbar_decoder_get_modifiers(dcode); /* FIXME grab decoder buffer */ memcpy(sym->data, data, datalen + 1); diff --git a/zbar/symbol.c b/zbar/symbol.c index ec21693..a0b308a 100644 --- a/zbar/symbol.c +++ b/zbar/symbol.c @@ -59,6 +59,32 @@ const char *zbar_get_addon_name (zbar_symbol_type_t sym) } } +const char *zbar_get_config_name (zbar_config_t cfg) +{ + switch(cfg) { + case ZBAR_CFG_ENABLE: return("ENABLE"); + case ZBAR_CFG_ADD_CHECK: return("ADD_CHECK"); + case ZBAR_CFG_EMIT_CHECK: return("EMIT_CHECK"); + case ZBAR_CFG_ASCII: return("ASCII"); + case ZBAR_CFG_MIN_LEN: return("MIN_LEN"); + case ZBAR_CFG_MAX_LEN: return("MAX_LEN"); + case ZBAR_CFG_UNCERTAINTY: return("UNCERTAINTY"); + case ZBAR_CFG_POSITION: return("POSITION"); + case ZBAR_CFG_X_DENSITY: return("X_DENSITY"); + case ZBAR_CFG_Y_DENSITY: return("Y_DENSITY"); + default: return(""); + } +} + +const char *zbar_get_modifier_name (zbar_modifier_t mod) +{ + switch(mod) { + case ZBAR_MOD_GS1: return("GS1"); + case ZBAR_MOD_AIM: return("AIM"); + default: return(""); + } +} + const char *zbar_get_orientation_name (zbar_orientation_t orient) { switch(orient) { @@ -111,6 +137,16 @@ zbar_symbol_type_t zbar_symbol_get_type (const zbar_symbol_t *sym) return(sym->type); } +unsigned int zbar_symbol_get_configs (const zbar_symbol_t *sym) +{ + return(sym->configs); +} + +unsigned int zbar_symbol_get_modifiers (const zbar_symbol_t *sym) +{ + return(sym->modifiers); +} + const char *zbar_symbol_get_data (const zbar_symbol_t *sym) { return(sym->data); @@ -200,31 +236,35 @@ unsigned base64_encode (char *dst, return(dst - start - 1); } -static const char *xmlfmt[] = { - "", +enum { + TMPL_START, + TMPL_MOD_START, TMPL_MOD_ITEM, TMPL_MOD_END, + TMPL_COUNT, + TMPL_DATA_START, TMPL_FORMAT, TMPL_CDATA, + TMPL_NL, + TMPL_END, }; /* FIXME suspect... */ +#define MAX_STATIC 256 +#define MAX_MOD (5 * ZBAR_MOD_NUM) +#define MAX_CFG (10 * ZBAR_CFG_NUM) #define MAX_INT_DIGITS 10 -#define TMPL_COPY(t) do { \ - i = strlen(xmlfmt[(t)]); \ - memcpy(*buf + n, xmlfmt[(t)], i + 1); \ - n += i; \ - assert(n <= maxlen); \ +#define TMPL_COPY(t) do { \ + static const char *_st = (t); \ + i = strlen(_st); \ + memcpy(*buf + n, _st, i + 1); \ + n += i; \ + assert(n <= maxlen); \ } while(0) -#define TMPL_FMT(t, ...) do { \ - i = snprintf(*buf + n, maxlen - n, xmlfmt[(t)], __VA_ARGS__); \ - assert(i > 0); \ - n += i; \ - assert(n <= maxlen); \ +#define TMPL_FMT(t, ...) do { \ + static const char *_st = (t); \ + i = snprintf(*buf + n, maxlen - n, _st, __VA_ARGS__); \ + assert(i > 0); \ + n += i; \ + assert(n <= maxlen); \ } while(0) char *zbar_symbol_xml (const zbar_symbol_t *sym, @@ -255,12 +295,16 @@ char *zbar_symbol_xml (const zbar_symbol_t *sym, if(binary) datalen = (sym->datalen + 2) / 3 * 4 + sym->datalen / 57 + 3; - maxlen = (strlen(xmlfmt[0]) + strlen(xmlfmt[1]) + - strlen(xmlfmt[2]) + strlen(xmlfmt[4]) + - strlen(xmlfmt[6]) + strlen(type) + strlen(orient) + + maxlen = (MAX_STATIC + strlen(type) + strlen(orient) + datalen + MAX_INT_DIGITS + 1); + unsigned int mods = sym->modifiers; + if(mods) + maxlen += MAX_MOD; + unsigned int cfgs = sym->configs & ~(1 << ZBAR_CFG_ENABLE); + if(cfgs) + maxlen += MAX_CFG; if(binary) - maxlen += (strlen(xmlfmt[3]) + strlen(xmlfmt[5]) + MAX_INT_DIGITS); + maxlen += MAX_INT_DIGITS; if(!*buf || (*len < maxlen)) { if(*buf) @@ -270,27 +314,50 @@ char *zbar_symbol_xml (const zbar_symbol_t *sym, *len = maxlen; } - TMPL_FMT(0, type, sym->quality, orient); + TMPL_FMT("quality, orient); + + if(mods) { + int j; + TMPL_COPY(" modifiers='"); + for(j = 0; mods && j < ZBAR_MOD_NUM; j++, mods >>= 1) + if(mods & 1) + TMPL_FMT("%s ", zbar_get_modifier_name(j)); + /* cleanup trailing space */ + n--; + TMPL_COPY("'"); + } + + if(cfgs) { + int j; + TMPL_COPY(" configs='"); + for(j = 0; cfgs && j < ZBAR_CFG_NUM; j++, cfgs >>= 1) + if(cfgs & 1) + TMPL_FMT("%s ", zbar_get_config_name(j)); + /* cleanup trailing space */ + n--; + TMPL_COPY("'"); + } if(sym->cache_count) - TMPL_FMT(1, sym->cache_count); + TMPL_FMT(" count='%d'", sym->cache_count); - TMPL_COPY(2); + TMPL_COPY(">datalen); - TMPL_COPY(4); + TMPL_FMT(" format='base64' length='%d'", sym->datalen); + TMPL_COPY(">data, sym->datalen + 1); n += sym->datalen; } else { - TMPL_COPY(5); + TMPL_COPY("\n"); n += base64_encode(*buf + n, sym->data, sym->datalen); } assert(n <= maxlen); - TMPL_COPY(6); + TMPL_COPY("]]>"); *len = n; return(*buf); diff --git a/zbar/symbol.h b/zbar/symbol.h index 99972d1..c2ddef4 100644 --- a/zbar/symbol.h +++ b/zbar/symbol.h @@ -42,6 +42,8 @@ struct zbar_symbol_set_s { struct zbar_symbol_s { zbar_symbol_type_t type; /* symbol type */ + unsigned int configs; /* symbology boolean config bitmask */ + unsigned int modifiers; /* symbology modifier bitmask */ unsigned int data_alloc; /* allocation size of data */ unsigned int datalen; /* length of binary symbol data */ char *data; /* symbol data */ From d03c4a3a61ae5f61617e7d331522e4e59fdf0c22 Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 29 Nov 2010 12:25:17 -0800 Subject: [PATCH 246/328] release updates - update docs --- iphone/ChangeLog | 5 ++++- iphone/README | 4 ++-- iphone/doc/ZBarSymbol.rst | 8 ++++++++ .../ReaderSample/ReaderSample.xcodeproj/project.pbxproj | 4 ++-- .../readertest/readertest.xcodeproj/project.pbxproj | 4 ++-- iphone/res/ZBarSDK-Info.plist | 2 +- iphone/res/zbar-help.html | 7 ++++++- iphone/zbar.xcodeproj/project.pbxproj | 6 ++++-- 8 files changed, 29 insertions(+), 11 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 60d6ef1..698b33c 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,7 @@ -current: +version 1.0.1: + * 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 diff --git a/iphone/README b/iphone/README index 29c7e31..25acea8 100644 --- a/iphone/README +++ b/iphone/README @@ -4,8 +4,8 @@ ZBar iPhone 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 39, Interleaved 2 of 5 and QR Code. These are the -Objective C wrappers and integrated widget for developing with the +Code 128, Code 93, Code 39, Interleaved 2 of 5 and QR Code. These are +the Objective C wrappers and integrated widget for developing with the library on the iPhone platform. Check the ZBar project home page for the latest release, forums, etc. diff --git a/iphone/doc/ZBarSymbol.rst b/iphone/doc/ZBarSymbol.rst index 2027e6a..6cf9705 100644 --- a/iphone/doc/ZBarSymbol.rst +++ b/iphone/doc/ZBarSymbol.rst @@ -25,6 +25,14 @@ Properties 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. + .. member:: NSString *data The raw decoded barcode data. (read-only) diff --git a/iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj b/iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj index 75cca99..f7b2a2d 100755 --- a/iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj +++ b/iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj @@ -340,7 +340,7 @@ GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 4.0; PREBINDING = NO; - SDKROOT = iphoneos4.1; + SDKROOT = iphoneos; }; name = Debug; }; @@ -355,7 +355,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 4.0; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; PREBINDING = NO; - SDKROOT = iphoneos4.1; + SDKROOT = iphoneos; }; name = Release; }; diff --git a/iphone/examples/readertest/readertest.xcodeproj/project.pbxproj b/iphone/examples/readertest/readertest.xcodeproj/project.pbxproj index b43397f..df4d499 100755 --- a/iphone/examples/readertest/readertest.xcodeproj/project.pbxproj +++ b/iphone/examples/readertest/readertest.xcodeproj/project.pbxproj @@ -298,7 +298,7 @@ GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 3.1; PREBINDING = NO; - SDKROOT = iphoneos4.1; + SDKROOT = iphoneos; SYMROOT = /tmp/readertest.build; }; name = Debug; @@ -313,7 +313,7 @@ GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 3.1; PREBINDING = NO; - SDKROOT = iphoneos4.1; + SDKROOT = iphoneos; SYMROOT = /tmp/readertest.build; }; name = Release; diff --git a/iphone/res/ZBarSDK-Info.plist b/iphone/res/ZBarSDK-Info.plist index 901bcf9..a785148 100644 --- a/iphone/res/ZBarSDK-Info.plist +++ b/iphone/res/ZBarSDK-Info.plist @@ -7,7 +7,7 @@ CFBundleName ZBarSDK CFBundleVersion - 1.0 + 1.0.1 CFBundleSignature ???? NSHumanReadableCopyright diff --git a/iphone/res/zbar-help.html b/iphone/res/zbar-help.html index 6c0e9f7..72d209c 100644 --- a/iphone/res/zbar-help.html +++ b/iphone/res/zbar-help.html @@ -41,7 +41,12 @@

Barcode Reader Help

QR Codes

-

Also recognized, but not shown: Code 128, Code 93 and Code 39

+

Also recognized, but not shown: +Code 128, +DataBar (RSS), +Code 93, +Code 39 and +Interleaved 2 of 5


Hints for successful scanning

diff --git a/iphone/zbar.xcodeproj/project.pbxproj b/iphone/zbar.xcodeproj/project.pbxproj index 4cdf04f..cb13f3d 100644 --- a/iphone/zbar.xcodeproj/project.pbxproj +++ b/iphone/zbar.xcodeproj/project.pbxproj @@ -114,6 +114,7 @@ DC67C1C210A07B6B0033B702 /* ZBarHelpController.m in Sources */ = {isa = PBXBuildFile; fileRef = DC67C1BE10A07B6B0033B702 /* ZBarHelpController.m */; }; DC67C1C310A07B6B0033B702 /* ZBarReaderController.m in Sources */ = {isa = PBXBuildFile; fileRef = DC67C1BF10A07B6B0033B702 /* ZBarReaderController.m */; }; DC67C1C410A07B6B0033B702 /* ZBarSymbol.m in Sources */ = {isa = PBXBuildFile; fileRef = DC67C1C010A07B6B0033B702 /* ZBarSymbol.m */; }; + DCB3789B12A43CAC0059B07B /* ZBarHelpController.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = DCB3789A12A43C7E0059B07B /* ZBarHelpController.h */; }; DCDC6E3011ADCA8E00021380 /* ZBarReaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = DCDC6E2F11ADCA8E00021380 /* ZBarReaderView.m */; }; DCE9900D129719F100D2655C /* code93.c in Sources */ = {isa = PBXBuildFile; fileRef = DCE9900B129719F100D2655C /* code93.c */; }; DCF5C9AD11EA3AD100E7DC21 /* databar.c in Sources */ = {isa = PBXBuildFile; fileRef = DCF5C9AB11EA3AD100E7DC21 /* databar.c */; }; @@ -151,6 +152,7 @@ dstSubfolderSpec = 1; files = ( DC3CEFB51216349700D7A786 /* ZBarCaptureReader.h in Copy Headers */, + DCB3789B12A43CAC0059B07B /* ZBarHelpController.h in Copy Headers */, DC3CEFB61216349700D7A786 /* ZBarImage.h in Copy Headers */, DC3CEFB71216349700D7A786 /* ZBarImageScanner.h in Copy Headers */, DC3CEFB81216349700D7A786 /* ZBarReaderController.h in Copy Headers */, @@ -317,11 +319,11 @@ DC67C15710A07AD30033B702 /* scanner.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scanner.c; sourceTree = ""; usesTabs = 0; }; DC67C15A10A07AD30033B702 /* symbol.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = symbol.c; sourceTree = ""; usesTabs = 0; }; DC67C15B10A07AD30033B702 /* symbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = symbol.h; sourceTree = ""; usesTabs = 0; }; - DC67C1BD10A07B6B0033B702 /* ZBarHelpController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarHelpController.h; sourceTree = ""; usesTabs = 0; }; DC67C1BE10A07B6B0033B702 /* ZBarHelpController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarHelpController.m; sourceTree = ""; usesTabs = 0; }; DC67C1BF10A07B6B0033B702 /* ZBarReaderController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarReaderController.m; sourceTree = ""; usesTabs = 0; }; DC67C1C010A07B6B0033B702 /* ZBarSymbol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarSymbol.m; sourceTree = ""; usesTabs = 0; }; DC67C1CB10A07BEE0033B702 /* svg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = svg.h; sourceTree = ""; usesTabs = 0; }; + DCB3789A12A43C7E0059B07B /* ZBarHelpController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ZBarHelpController.h; path = include/ZBarSDK/ZBarHelpController.h; sourceTree = ""; }; DCDC6E2F11ADCA8E00021380 /* ZBarReaderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarReaderView.m; sourceTree = ""; usesTabs = 0; }; DCE9900B129719F100D2655C /* code93.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = code93.c; sourceTree = ""; }; DCE9900C129719F100D2655C /* code93.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = code93.h; sourceTree = ""; }; @@ -409,6 +411,7 @@ isa = PBXGroup; children = ( DC3CEFA51216347100D7A786 /* ZBarCaptureReader.h */, + DCB3789A12A43C7E0059B07B /* ZBarHelpController.h */, DC3CEFA61216347100D7A786 /* ZBarImage.h */, DC3CEFA71216347100D7A786 /* ZBarImageScanner.h */, DC3CEFA81216347100D7A786 /* ZBarReaderController.h */, @@ -480,7 +483,6 @@ DC299BEC1208FE40006A023C /* prefix.pch */, DC299AF51208B7BD006A023C /* config.h */, DC3AAB4C11B71A040021C7B1 /* ZBarCVImage.h */, - DC67C1BD10A07B6B0033B702 /* ZBarHelpController.h */, DC299BE41208FE09006A023C /* ZBarSDK */, ); name = include; From 3d129863e003481412c28f84989d2a61938d386b Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 29 Nov 2010 12:26:36 -0800 Subject: [PATCH 247/328] Added tag iPhoneSDK-1.0.1 for changeset 12de07e51dce From 986945ec50dca4ff2ec78ecad3b0d076c87f0d83 Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 29 Nov 2010 14:48:08 -0800 Subject: [PATCH 248/328] hotfix broken ZBarHelpController back button --- iphone/ChangeLog | 1 + iphone/ZBarHelpController.m | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 698b33c..b68fbb3 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,5 @@ version 1.0.1: + * hotfix broken ZBarHelpController back button * release updates - update docs * fix support for GS1 AIs diff --git a/iphone/ZBarHelpController.m b/iphone/ZBarHelpController.m index c07fea1..e4211db 100644 --- a/iphone/ZBarHelpController.m +++ b/iphone/ZBarHelpController.m @@ -101,6 +101,13 @@ - (void) viewDidLoad view.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); + webView = [UIWebView new]; + webView.delegate = self; + webView.backgroundColor = [UIColor colorWithWhite: .125f + alpha: 1 ]; + webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight); + toolbar = [UIToolbar new]; toolbar.barStyle = UIBarStyleBlackOpaque; toolbar.autoresizingMask = (UIViewAutoresizingFlexibleWidth | @@ -127,13 +134,6 @@ - (void) viewDidLoad [view addSubview: toolbar]; - webView = [UIWebView new]; - webView.delegate = self; - webView.backgroundColor = [UIColor colorWithWhite: .125f - alpha: 1 ]; - webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | - UIViewAutoresizingFlexibleHeight); - UIInterfaceOrientation orient = self.interfaceOrientation; if(!((orientations >> orient) & 1)) for(orient = UIInterfaceOrientationPortrait; From 5553919cdf4ea750c87ce2b63e5eee4b7ca08a00 Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 29 Nov 2010 14:48:55 -0800 Subject: [PATCH 249/328] Added tag iPhoneSDK-1.0.1 for changeset 2541a66ae7d6 From 66ab786c0c7c0b95d50d57de5e32b0c69bf97810 Mon Sep 17 00:00:00 2001 From: tterribe Date: Thu, 9 Dec 2010 12:17:27 -0800 Subject: [PATCH 250/328] Increase precision of the inverse affine transform in the QR decoder. For large images, the coefficients of the inverse affine transform did not have many significant bits, resulting in unprojected points that were too far left and up. This interacted badly with the code that tries to follow the right and bottom edges to locate the lower-right corner of the code area (where there is no finder pattern). This change just performs the intermediate calculations in the unprojection with more significant bits; overflow could be a problem for very skewed images, but these are unlikely to decode correctly anyway. Fixes issue 3131834: http://sourceforge.net/tracker/?func=detail&atid=928516&aid=3131834&group_id=189236 --- zbar/qrcode/qrdec.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/zbar/qrcode/qrdec.c b/zbar/qrcode/qrdec.c index 7e60f15..6a57465 100644 --- a/zbar/qrcode/qrdec.c +++ b/zbar/qrcode/qrdec.c @@ -630,11 +630,12 @@ struct qr_aff{ int x0; int y0; int res; + int ires; }; static void qr_aff_init(qr_aff *_aff, - const qr_point _p0,const qr_point _p1,const qr_point _p2,int _res){ + const qr_point _p0,const qr_point _p1,const qr_point _p2,int _res,int _ires){ int det; int dx1; int dy1; @@ -650,20 +651,23 @@ static void qr_aff_init(qr_aff *_aff, _aff->fwd[0][1]=dx2; _aff->fwd[1][0]=dy1; _aff->fwd[1][1]=dy2; - _aff->inv[0][0]=QR_DIVROUND(dy2<<_res,det); - _aff->inv[0][1]=QR_DIVROUND(-dx2<<_res,det); - _aff->inv[1][0]=QR_DIVROUND(-dy1<<_res,det); - _aff->inv[1][1]=QR_DIVROUND(dx1<<_res,det); + _aff->inv[0][0]=QR_DIVROUND(dy2<<_res,det>>_ires); + _aff->inv[0][1]=QR_DIVROUND(-dx2<<_res,det>>_ires); + _aff->inv[1][0]=QR_DIVROUND(-dy1<<_res,det>>_ires); + _aff->inv[1][1]=QR_DIVROUND(dx1<<_res,det>>_ires); _aff->x0=_p0[0]; _aff->y0=_p0[1]; _aff->res=_res; + _aff->ires=_ires; } /*Map from the image (at subpel resolution) into the square domain.*/ static void qr_aff_unproject(qr_point _q,const qr_aff *_aff, int _x,int _y){ - _q[0]=_aff->inv[0][0]*(_x-_aff->x0)+_aff->inv[0][1]*(_y-_aff->y0); - _q[1]=_aff->inv[1][0]*(_x-_aff->x0)+_aff->inv[1][1]*(_y-_aff->y0); + _q[0]=_aff->inv[0][0]*(_x-_aff->x0)+_aff->inv[0][1]*(_y-_aff->y0) + +(1<<_aff->ires-1)>>_aff->ires; + _q[1]=_aff->inv[1][0]*(_x-_aff->x0)+_aff->inv[1][1]*(_y-_aff->y0) + +(1<<_aff->ires-1)>>_aff->ires; } /*Map from the square domain into the image (at subpel resolution).*/ @@ -1894,10 +1898,10 @@ static int qr_alignment_pattern_search(qr_point _p,const qr_hom_cell *_cell, if(nc[0]){ dx=QR_DIVROUND(c[0][0],nc[0]); dy=QR_DIVROUND(c[0][1],nc[0]); - /*But only if it doesn't make things worse.*/ + /*But only if it doesn't make things too much worse.*/ match=qr_alignment_pattern_fetch(p,bestx+dx,besty+dy,_img,_width,_height); dist=qr_hamming_dist(match,0x1F8D63F,best_dist+1); - if(dist<=best_dist){ + if(dist<=best_dist+1){ bestx+=dx; besty+=dy; } @@ -3629,6 +3633,7 @@ static int qr_reader_try_configuration(qr_reader *_reader, qr_finder ur; qr_finder dl; int res; + int ires; int ur_version; int dl_version; int fmt_info; @@ -3641,8 +3646,10 @@ static int qr_reader_try_configuration(qr_reader *_reader, estimate it there. Although it should be the same along both axes, we keep separate estimates to account for any remaining projective distortion.*/ - res=QR_INT_BITS-2-QR_FINDER_SUBPREC-qr_ilog(QR_MAXI(_width,_height)-1); - qr_aff_init(&aff,ul.c->pos,ur.c->pos,dl.c->pos,res); + ires=qr_ilog(QR_MAXI(_width,_height)-1)+QR_FINDER_SUBPREC; + res=QR_INT_BITS-2-ires; + ires-=2; + qr_aff_init(&aff,ul.c->pos,ur.c->pos,dl.c->pos,res,ires); qr_aff_unproject(ur.o,&aff,ur.c->pos[0],ur.c->pos[1]); qr_finder_edge_pts_aff_classify(&ur,&aff); if(qr_finder_estimate_module_size_and_version(&ur,1< Date: Thu, 9 Dec 2010 12:40:16 -0800 Subject: [PATCH 251/328] Avoid dprintf conflict. dprintf is part of XPG7 (X/Open 2008), but zbar #defines a conflicting one to use for debug printing. This just makes sure is included before the macro is defined, so that the declaration in that header is processed before zbar's macro. Fixes issue 3122916: http://sourceforge.net/tracker/?func=detail&atid=928516&aid=3122916&group_id=189236 --- zbar/debug.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zbar/debug.h b/zbar/debug.h index 138ab0f..468996f 100644 --- a/zbar/debug.h +++ b/zbar/debug.h @@ -23,6 +23,8 @@ /* varargs variations on compile time debug spew */ +# include + #ifndef DEBUG_LEVEL # ifdef __GNUC__ @@ -35,8 +37,6 @@ #else -# include - # ifdef __GNUC__ # define dprintf(level, args...) do { \ if((level) <= DEBUG_LEVEL) \ From fa1d075e67ca19fd0bbbc729a677079bbd744943 Mon Sep 17 00:00:00 2001 From: tterribe Date: Fri, 10 Dec 2010 06:49:44 -0800 Subject: [PATCH 252/328] More fixes for issue 3131834. I'm not sure how my fixes managed to successfully decode the image in question yesterday, but they don't today. There was also an overflow in the code to project the lower-right alignment pattern out to the exterior corner when fitting the initial homography. When computing w for large versions, dim could use 8 bits, and the product of two image coordinates was using 12 each, overflowing a signed 32-bit number. These calculations have been expanded to 64-bit. This patch also fixes a potential divide-by-zero when the determinant in the affine transformation is small. The new strategy for picking ires should avoid this and avoid any potential overflow in the unprojection calculations. --- configure.ac | 4 ++-- zbar/qrcode/qrdec.c | 40 ++++++++++++++++++++-------------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/configure.ac b/configure.ac index 4407935..329a630 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.61]) AC_INIT([zbar], [0.10], [spadix@users.sourceforge.net]) AC_CONFIG_AUX_DIR(config) AC_CONFIG_MACRO_DIR(config) -AM_INIT_AUTOMAKE([1.10 -Wall -Werror foreign subdir-objects std-options dist-bzip2]) +AM_INIT_AUTOMAKE([1.10 -Wall foreign subdir-objects std-options dist-bzip2]) AC_CONFIG_HEADERS([include/config.h]) AC_CONFIG_SRCDIR(zbar/scanner.c) LT_PREREQ([2.2]) @@ -47,7 +47,7 @@ AC_DEFINE_UNQUOTED([LIB_VERSION_REVISION], [Library revision]) AM_CPPFLAGS="-I$srcdir/include" -AM_CFLAGS="-Wall -Wno-parentheses -Werror" +AM_CFLAGS="-Wall -Wno-parentheses" AM_CXXFLAGS="$AM_CFLAGS" AC_SUBST([AM_CPPFLAGS]) AC_SUBST([AM_CFLAGS]) diff --git a/zbar/qrcode/qrdec.c b/zbar/qrcode/qrdec.c index 6a57465..bd27538 100644 --- a/zbar/qrcode/qrdec.c +++ b/zbar/qrcode/qrdec.c @@ -635,30 +635,32 @@ struct qr_aff{ static void qr_aff_init(qr_aff *_aff, - const qr_point _p0,const qr_point _p1,const qr_point _p2,int _res,int _ires){ + const qr_point _p0,const qr_point _p1,const qr_point _p2,int _res){ int det; + int ires; int dx1; int dy1; int dx2; int dy2; /*det is ensured to be positive by our caller.*/ - det=qr_point_ccw(_p0,_p1,_p2); dx1=_p1[0]-_p0[0]; dx2=_p2[0]-_p0[0]; dy1=_p1[1]-_p0[1]; dy2=_p2[1]-_p0[1]; + det=dx1*dy2-dy1*dx2; + ires=QR_MAXI((qr_ilog(abs(det))>>1)-2,0); _aff->fwd[0][0]=dx1; _aff->fwd[0][1]=dx2; _aff->fwd[1][0]=dy1; _aff->fwd[1][1]=dy2; - _aff->inv[0][0]=QR_DIVROUND(dy2<<_res,det>>_ires); - _aff->inv[0][1]=QR_DIVROUND(-dx2<<_res,det>>_ires); - _aff->inv[1][0]=QR_DIVROUND(-dy1<<_res,det>>_ires); - _aff->inv[1][1]=QR_DIVROUND(dx1<<_res,det>>_ires); + _aff->inv[0][0]=QR_DIVROUND(dy2<<_res,det>>ires); + _aff->inv[0][1]=QR_DIVROUND(-dx2<<_res,det>>ires); + _aff->inv[1][0]=QR_DIVROUND(-dy1<<_res,det>>ires); + _aff->inv[1][1]=QR_DIVROUND(dx1<<_res,det>>ires); _aff->x0=_p0[0]; _aff->y0=_p0[1]; _aff->res=_res; - _aff->ires=_ires; + _aff->ires=ires; } /*Map from the image (at subpel resolution) into the square domain.*/ @@ -2222,11 +2224,11 @@ static int qr_hom_fit(qr_hom *_hom,qr_finder *_ul,qr_finder *_ur, _p[2][0],_p[2][1],_p[3][0],_p[3][1]); if(qr_alignment_pattern_search(p3,&cell,dim-7,dim-7,4, _img,_width,_height)>=0){ - int c21; - int dx21; - int dy21; - int mask; - int w; + long long w; + long long mask; + int c21; + int dx21; + int dy21; /*There's no real need to update the bounding box corner, and in fact we actively perform worse if we do. Clearly it was good enough for us to find this alignment pattern, so @@ -2242,10 +2244,11 @@ static int qr_hom_fit(qr_hom *_hom,qr_finder *_ul,qr_finder *_ur, c21=_p[2][0]*_p[1][1]-_p[2][1]*_p[1][0]; dx21=_p[2][0]-_p[1][0]; dy21=_p[2][1]-_p[1][1]; - w=(dim-7)*c21 - +(dim-13)*(_p[0][0]*dy21-_p[0][1]*dx21)+6*(p3[0]*dy21-p3[1]*dx21); + w=QR_EXTMUL(dim-7,c21, + QR_EXTMUL(dim-13,_p[0][0]*dy21-_p[0][1]*dx21, + QR_EXTMUL(6,p3[0]*dy21-p3[1]*dx21,0))); mask=QR_SIGNMASK(w); - w=abs(w); + w=w+mask^mask; brx=(int)QR_DIVROUND(QR_EXTMUL((dim-7)*_p[0][0],p3[0]*dy21, QR_EXTMUL((dim-13)*p3[0],c21-_p[0][1]*dx21, QR_EXTMUL(6*_p[0][0],c21-p3[1]*dx21,0)))+mask^mask,w); @@ -3633,7 +3636,6 @@ static int qr_reader_try_configuration(qr_reader *_reader, qr_finder ur; qr_finder dl; int res; - int ires; int ur_version; int dl_version; int fmt_info; @@ -3646,10 +3648,8 @@ static int qr_reader_try_configuration(qr_reader *_reader, estimate it there. Although it should be the same along both axes, we keep separate estimates to account for any remaining projective distortion.*/ - ires=qr_ilog(QR_MAXI(_width,_height)-1)+QR_FINDER_SUBPREC; - res=QR_INT_BITS-2-ires; - ires-=2; - qr_aff_init(&aff,ul.c->pos,ur.c->pos,dl.c->pos,res,ires); + res=QR_INT_BITS-2-QR_FINDER_SUBPREC-qr_ilog(QR_MAXI(_width,_height)-1); + qr_aff_init(&aff,ul.c->pos,ur.c->pos,dl.c->pos,res); qr_aff_unproject(ur.o,&aff,ur.c->pos[0],ur.c->pos[1]); qr_finder_edge_pts_aff_classify(&ur,&aff); if(qr_finder_estimate_module_size_and_version(&ur,1< Date: Fri, 10 Dec 2010 07:24:17 -0800 Subject: [PATCH 253/328] Fix ires rounding in qr_aff_unproject(). With the last commit, ires can now be zero, and so shifting by ires-1 was undefined. This also backs out the accidental removal of -Werror from configure.ac. --- configure.ac | 4 ++-- zbar/qrcode/qrdec.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 329a630..4407935 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.61]) AC_INIT([zbar], [0.10], [spadix@users.sourceforge.net]) AC_CONFIG_AUX_DIR(config) AC_CONFIG_MACRO_DIR(config) -AM_INIT_AUTOMAKE([1.10 -Wall foreign subdir-objects std-options dist-bzip2]) +AM_INIT_AUTOMAKE([1.10 -Wall -Werror foreign subdir-objects std-options dist-bzip2]) AC_CONFIG_HEADERS([include/config.h]) AC_CONFIG_SRCDIR(zbar/scanner.c) LT_PREREQ([2.2]) @@ -47,7 +47,7 @@ AC_DEFINE_UNQUOTED([LIB_VERSION_REVISION], [Library revision]) AM_CPPFLAGS="-I$srcdir/include" -AM_CFLAGS="-Wall -Wno-parentheses" +AM_CFLAGS="-Wall -Wno-parentheses -Werror" AM_CXXFLAGS="$AM_CFLAGS" AC_SUBST([AM_CPPFLAGS]) AC_SUBST([AM_CFLAGS]) diff --git a/zbar/qrcode/qrdec.c b/zbar/qrcode/qrdec.c index bd27538..4df1d32 100644 --- a/zbar/qrcode/qrdec.c +++ b/zbar/qrcode/qrdec.c @@ -667,9 +667,9 @@ static void qr_aff_init(qr_aff *_aff, static void qr_aff_unproject(qr_point _q,const qr_aff *_aff, int _x,int _y){ _q[0]=_aff->inv[0][0]*(_x-_aff->x0)+_aff->inv[0][1]*(_y-_aff->y0) - +(1<<_aff->ires-1)>>_aff->ires; + +(1<<_aff->ires>>1)>>_aff->ires; _q[1]=_aff->inv[1][0]*(_x-_aff->x0)+_aff->inv[1][1]*(_y-_aff->y0) - +(1<<_aff->ires-1)>>_aff->ires; + +(1<<_aff->ires>>1)>>_aff->ires; } /*Map from the square domain into the image (at subpel resolution).*/ From 954f611f70bef7f3ca317332074808fee1d3e703 Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 11 Dec 2010 19:02:17 -0800 Subject: [PATCH 254/328] add support for EAN/UPC 2 and 5 digit add-on symbols (draft) - deprecate original, unfinished add-on APIs - add self-checking to test_decode --- ChangeLog | 3 + TODO | 1 - gtk/zbargtk.c | 1 - include/zbar.h | 31 +++++- include/zbar/Decoder.h | 1 + include/zbar/Symbol.h | 5 +- qt/QZBarThread.cpp | 3 +- test/test_decode.c | 162 ++++++++++++++++++++++++---- test/test_gtk.c | 1 - zbar/config.c | 13 ++- zbar/decoder.c | 34 +++--- zbar/decoder/code39.c | 2 +- zbar/decoder/ean.c | 238 +++++++++++++++++++++++++++-------------- zbar/decoder/ean.h | 17 +-- zbar/decoder/i25.c | 24 +++-- zbar/decoder/i25.h | 1 + zbar/img_scanner.c | 78 +++++++++++--- zbar/processor.c | 3 +- zbar/symbol.c | 9 +- 19 files changed, 453 insertions(+), 174 deletions(-) diff --git a/ChangeLog b/ChangeLog index a0c644c..19d0680 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,7 @@ current: + * add support for EAN/UPC 2 and 5 digit add-on symbols + - deprecate original, unfinished add-on APIs + - add self-checking to test_decode * add coarse symbol orientation information (patch #2913094) - thanks to Anssi for a patch! - add decode direction feedback to decoder diff --git a/TODO b/TODO index 2eaff8a..1344993 100644 --- a/TODO +++ b/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) diff --git a/gtk/zbargtk.c b/gtk/zbargtk.c index a67c6ff..529610e 100644 --- a/gtk/zbargtk.c +++ b/gtk/zbargtk.c @@ -231,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); diff --git a/include/zbar.h b/include/zbar.h index 5f5b8e8..fbb3420 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -86,21 +86,41 @@ 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_EANUPC = 15, /**< EAN/UPC composite */ ZBAR_I25 = 25, /**< Interleaved 2 of 5. @since 0.4 */ ZBAR_CODE39 = 39, /**< Code 39. @since 0.4 */ ZBAR_PDF417 = 57, /**< PDF417. @since 0.6 */ ZBAR_QRCODE = 64, /**< QR Code. @since 0.10 */ 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_EANUPC; add-on components use ::ZBAR_EAN2 + * or ::ZBAR_EAN5 + */ + ZBAR_ADDON = 0x0700, } zbar_symbol_type_t; /** decoded symbol coarse orientation. @@ -179,6 +199,7 @@ 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); @@ -329,7 +350,7 @@ extern int zbar_symbol_get_loc_y(const zbar_symbol_t *symbol, /** retrieve general orientation of decoded symbol. * @returns a coarse, axis-aligned indication of symbol orientation or - * ZBAR_ORIENT_UNKNOWN if unknown + * ::ZBAR_ORIENT_UNKNOWN if unknown * @since 0.11 */ extern zbar_orientation_t diff --git a/include/zbar/Decoder.h b/include/zbar/Decoder.h index b0c6764..27e78d8 100644 --- a/include/zbar/Decoder.h +++ b/include/zbar/Decoder.h @@ -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))); diff --git a/include/zbar/Symbol.h b/include/zbar/Symbol.h index 018eac5..04a4af2 100644 --- a/include/zbar/Symbol.h +++ b/include/zbar/Symbol.h @@ -250,6 +250,7 @@ class Symbol { } /// retrieve the string name for any addon. + /// @deprecated in 0.11 const std::string get_addon_name () const { return(zbar_get_addon_name(_type)); @@ -447,9 +448,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); } diff --git a/qt/QZBarThread.cpp b/qt/QZBarThread.cpp index e392674..b080c7b 100644 --- a/qt/QZBarThread.cpp +++ b/qt/QZBarThread.cpp @@ -26,7 +26,7 @@ using namespace zbar; -static const QString textFormat("%1%2:%3"); +static const QString textFormat("%1:%2"); QZBarThread::QZBarThread () : _videoOpened(false), @@ -52,7 +52,6 @@ void QZBarThread::image_callback (Image &image) emit decodedText(textFormat.arg( QString::fromStdString(sym->get_type_name()), - QString::fromStdString(sym->get_addon_name()), data)); } } diff --git a/test/test_decode.c b/test/test_decode.c index 0881ac5..d8690ba 100644 --- a/test/test_decode.c +++ b/test/test_decode.c @@ -31,16 +31,40 @@ zbar_decoder_t *decoder; +zbar_symbol_type_t expect_sym; +char *expect_data = NULL; + static void symbol_handler (zbar_decoder_t *decoder) { zbar_symbol_type_t sym = zbar_decoder_get_type(decoder); - if(sym <= ZBAR_PARTIAL) + if(sym <= ZBAR_PARTIAL || sym == ZBAR_QRCODE) return; - printf("%s%s:%s\n", - zbar_get_symbol_name(sym), - zbar_get_addon_name(sym), - zbar_decoder_get_data(decoder)); - /* FIXME add check! */ + const char *data = zbar_decoder_get_data(decoder); + printf("decode %s:%s\n", zbar_get_symbol_name(sym), data); + + if(!expect_sym) { + printf("UNEXPECTED!\n"); + abort(); + } + printf("expect %s:%s\n", zbar_get_symbol_name(expect_sym), expect_data); + if(sym != expect_sym || strcmp(data, expect_data)) + abort(); + + expect_sym = ZBAR_NONE; + free(expect_data); + expect_data = NULL; +} + +static void expect (zbar_symbol_type_t sym, + const char *data) +{ + if(expect_sym) { + printf("MISSING %s:%s\n", + zbar_get_symbol_name(expect_sym), expect_data); + abort(); + } + expect_sym = sym; + expect_data = (data) ? strdup(data) : NULL; } static void encode_junk (int n) @@ -122,8 +146,9 @@ static const unsigned int code128[107] = { 0x2331112a, /* STOP (6a) */ }; -static void encode_code128b (unsigned char *data) +static void encode_code128b (char *data) { + assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); printf("------------------------------------------------------------\n" "encode CODE-128(B): %s\n" " encode START_B: %02x", data, START_B); @@ -142,8 +167,9 @@ static void encode_code128b (unsigned char *data) printf("------------------------------------------------------------\n"); } -static void encode_code128c (unsigned char *data) +static void encode_code128c (char *data) { + assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); printf("------------------------------------------------------------\n" "encode CODE-128(C): %s\n" " encode START_C: %02x", data, START_C); @@ -182,14 +208,29 @@ static const unsigned int code39[91-32] = { /* FIXME configurable/randomized ratio, ics */ /* FIXME check digit option, ASCII escapes */ +static void convert_code39 (char *data) +{ + char *src, *dst; + for(src = data, dst = data; *src; src++) { + char c = *src; + if(c >= 'a' && c <= 'z') + *(dst++) = c - ('a' - 'A'); + else if(c == ' ' || + c == '$' || c == '%' || + c == '+' || c == '-' || + (c >= '.' && c <= '9') || + (c >= 'A' && c <= 'Z')) + *(dst++) = c; + else + /* skip (FIXME) */; + } + *dst = 0; +} + static void encode_char39 (unsigned char c, unsigned ics) { - if(c >= 'a' && c <= 'z') - c -= 'a' - 'A'; - else if(c < 0x20 || c > 0x5a) - return; /* skip (FIXME) */ - + assert(0x20 <= c && c <= 0x5a); unsigned int raw = code39[c - 0x20]; if(!raw) return; /* skip (FIXME) */ @@ -206,8 +247,9 @@ static void encode_char39 (unsigned char c, encode(enc, REV); } -static void encode_code39 (unsigned char *data) +static void encode_code39 (char *data) { + assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); printf("------------------------------------------------------------\n" "encode CODE-39: %s\n", data); encode(0xa, 0); /* leading quiet */ @@ -280,8 +322,9 @@ static void encode_row417 (int r, encode((dir) ? PDF417_START : PDF417_STOP, dir); } -static void encode_pdf417 (unsigned char *data) +static void encode_pdf417 (char *data) { + assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); printf("------------------------------------------------------------\n" "encode PDF417: hello world\n"); encode(0xa, 0); @@ -303,9 +346,10 @@ static const unsigned char i25[10] = { 0x06, 0x11, 0x09, 0x18, 0x05, 0x14, 0x0c, 0x03, 0x12, 0x0a, }; -static void encode_i25 (unsigned char *data, +static void encode_i25 (char *data, int dir) { + assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); printf("------------------------------------------------------------\n" "encode Interleaved 2 of 5: %s\n" " encode start:", data); @@ -313,7 +357,7 @@ static void encode_i25 (unsigned char *data, /* FIXME rev case data reversal */ int i; - for(i = (strlen((char*)data) & 1) ? -1 : 0; i < 0 || data[i]; i += 2) { + for(i = (strlen(data) & 1) ? -1 : 0; i < 0 || data[i]; i += 2) { /* encode 2 digits */ unsigned char c0 = (i < 0) ? 0 : data[i] - '0'; unsigned char c1 = data[i + 1] - '0'; @@ -372,7 +416,20 @@ static const unsigned char ean_parity_encode[] = { 0x25, /* ABBABA = 9 */ }; -static void calc_ean_parity (unsigned char *data, +static const unsigned char addon_parity_encode[] = { + 0x07, /* BBAAA = 0 */ + 0x0b, /* BABAA = 1 */ + 0x0d, /* BAABA = 2 */ + 0x0e, /* BAAAB = 3 */ + 0x13, /* ABBAA = 4 */ + 0x19, /* AABBA = 5 */ + 0x1c, /* AAABB = 6 */ + 0x15, /* ABABA = 7 */ + 0x16, /* ABAAB = 8 */ + 0x1a, /* AABAB = 9 */ +}; + +static void calc_ean_parity (char *data, int n) { int i, chk = 0; @@ -387,8 +444,9 @@ static void calc_ean_parity (unsigned char *data, data[i] = 0; } -static void encode_ean13 (unsigned char *data) +static void encode_ean13 (char *data) { + assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); int i; unsigned char par = ean_parity_encode[data[0] - '0']; @@ -399,7 +457,7 @@ static void encode_ean13 (unsigned char *data) encode(ean_guard[3], FWD); for(i = 1; i < 7; i++, par <<= 1) { printf(" encode %x%c:", (par >> 5) & 1, data[i]); - encode(ean_digits[data[i] - '0'], REV ^ ((par >> 5) & 1)); + encode(ean_digits[data[i] - '0'], (par >> 5) & 1); } printf(" encode center guard:"); encode(ean_guard[5], FWD); @@ -412,8 +470,9 @@ static void encode_ean13 (unsigned char *data) printf("------------------------------------------------------------\n"); } -static void encode_ean8 (unsigned char *data) +static void encode_ean8 (char *data) { + assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); int i; printf("------------------------------------------------------------\n" "encode EAN-8: %s\n" @@ -435,6 +494,43 @@ static void encode_ean8 (unsigned char *data) printf("------------------------------------------------------------\n"); } +static void encode_addon (char *data, + unsigned par, + int n) +{ + assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); + printf("------------------------------------------------------------\n" + "encode EAN-%d: %s (par=%02x)\n" + " encode start guard:", + n, data, par); + encode(ean_guard[4], FWD); + int i; + for(i = 0; i < n; i++, par <<= 1) { + printf(" encode %x%c:", (par >> (n - 1)) & 1, data[i]); + encode(ean_digits[data[i] - '0'], (par >> (n - 1)) & 1); + if(i < n - 1) { + printf(" encode delineator:"); + encode(ean_guard[2], FWD); + } + } + printf(" encode trailing qz:"); + encode(0x7, FWD); + printf("------------------------------------------------------------\n"); +} + +static void encode_ean5 (char *data) +{ + unsigned chk = ((data[0] - '0' + data[2] - '0' + data[4] - '0') * 3 + + (data[1] - '0' + data[3] - '0') * 9) % 10; + encode_addon(data, addon_parity_encode[chk], 5); +} + +static void encode_ean2 (char *data) +{ + unsigned par = (~(10 * (data[0] - '0') + data[1] - '0')) & 3; + encode_addon(data, par, 2); +} + /*------------------------------------------------------------*/ /* main test flow */ @@ -457,46 +553,68 @@ int main (int argc, char **argv) encode_junk(rnd_size + 1); - unsigned char data[32] = { 0 }; + char data[32] = { 0 }; for(i = 0; i < 12; i++) data[i] = (rand() % 10) + '0'; calc_ean_parity(data, 12); + expect(ZBAR_EAN13, data); encode_ean13(data); encode_junk(rnd_size); data[i] = 0; + expect(ZBAR_CODE128, data); encode_code128c(data); encode_junk(rnd_size); + expect(ZBAR_I25, data); encode_i25(data, FWD); encode_junk(rnd_size); +#if 0 /* FIXME encoding broken*/ encode_i25(data, REV); encode_junk(rnd_size); +#endif calc_ean_parity(data, 7); + expect(ZBAR_EAN8, data); encode_ean8(data); encode_junk(rnd_size); + data[5] = 0; + expect(ZBAR_EAN5, data); + encode_ean5(data); + + encode_junk(rnd_size); + + data[2] = 0; + expect(ZBAR_EAN2, data); + encode_ean2(data); + + encode_junk(rnd_size); + for(i = 0; i < 10; i++) data[i] = (rand() % 0x5f) + 0x20; data[i] = 0; + expect(ZBAR_CODE128, data); encode_code128b(data); encode_junk(rnd_size); /*encode_code39("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%");*/ + convert_code39(data); + expect(ZBAR_CODE39, data); encode_code39(data); encode_junk(rnd_size); + expect(ZBAR_NONE, NULL); encode_pdf417(data); encode_junk(rnd_size); diff --git a/test/test_gtk.c b/test/test_gtk.c index eef9121..7d13cd5 100644 --- a/test/test_gtk.c +++ b/test/test_gtk.c @@ -45,7 +45,6 @@ static void decoded (GtkWidget *widget, GtkTextIter end; gtk_text_buffer_get_end_iter(resultbuf, &end); gtk_text_buffer_insert(resultbuf, &end, zbar_get_symbol_name(symbol), -1); - gtk_text_buffer_insert(resultbuf, &end, zbar_get_addon_name(symbol), -1); gtk_text_buffer_insert(resultbuf, &end, ":", -1); gtk_text_buffer_insert(resultbuf, &end, result, -1); gtk_text_buffer_insert(resultbuf, &end, "\n", -1); diff --git a/zbar/config.c b/zbar/config.c index f8b4f00..693e4cf 100644 --- a/zbar/config.c +++ b/zbar/config.c @@ -56,6 +56,12 @@ int zbar_parse_config (const char *cfgstr, *sym = ZBAR_EAN13; else if(!strncmp(cfgstr, "ean8", len)) *sym = ZBAR_EAN8; + else if(!strncmp(cfgstr, "ean5", len)) + *sym = ZBAR_EAN5; + else if(!strncmp(cfgstr, "ean2", len)) + *sym = ZBAR_EAN2; + else if(!strncmp(cfgstr, "eanupc", len)) + *sym = ZBAR_EANUPC; else if(!strncmp(cfgstr, "i25", len)) *sym = ZBAR_I25; else if(len < 4) @@ -66,13 +72,6 @@ int zbar_parse_config (const char *cfgstr, *sym = ZBAR_ISBN13; else if(!strncmp(cfgstr, "isbn10", len)) *sym = ZBAR_ISBN10; -#if 0 - /* FIXME addons are configured per-main symbol type */ - else if(!strncmp(cfgstr, "addon2", len)) - *sym = ZBAR_ADDON2; - else if(!strncmp(cfgstr, "addon5", len)) - *sym = ZBAR_ADDON5; -#endif else if(len < 6) return(1); else if(!strncmp(cfgstr, "code39", len)) diff --git a/zbar/decoder.c b/zbar/decoder.c index f1a0c9c..7220ab7 100644 --- a/zbar/decoder.c +++ b/zbar/decoder.c @@ -54,6 +54,8 @@ zbar_decoder_t *zbar_decoder_create () dcode->ean.upce_config = 1 << ZBAR_CFG_EMIT_CHECK; dcode->ean.isbn10_config = 1 << ZBAR_CFG_EMIT_CHECK; dcode->ean.isbn13_config = 1 << ZBAR_CFG_EMIT_CHECK; + dcode->ean.ean2_config = 1 << ZBAR_CFG_ENABLE; + dcode->ean.ean5_config = 1 << ZBAR_CFG_ENABLE; #endif #ifdef ENABLE_I25 dcode->i25.config = 1 << ZBAR_CFG_ENABLE; @@ -241,6 +243,14 @@ static inline int decoder_set_config_bool (zbar_decoder_t *dcode, config = &dcode->ean.ean13_config; break; + case ZBAR_EAN2: + config = &dcode->ean.ean2_config; + break; + + case ZBAR_EAN5: + config = &dcode->ean.ean5_config; + break; + case ZBAR_EAN8: config = &dcode->ean.ean8_config; break; @@ -292,8 +302,6 @@ static inline int decoder_set_config_bool (zbar_decoder_t *dcode, break; #endif - /* FIXME handle addons */ - default: return(1); } @@ -309,6 +317,8 @@ static inline int decoder_set_config_bool (zbar_decoder_t *dcode, #ifdef ENABLE_EAN dcode->ean.enable = TEST_CFG(dcode->ean.ean13_config | + dcode->ean.ean2_config | + dcode->ean.ean5_config | dcode->ean.ean8_config | dcode->ean.upca_config | dcode->ean.upce_config | @@ -360,17 +370,15 @@ int zbar_decoder_set_config (zbar_decoder_t *dcode, int val) { if(sym == ZBAR_NONE) { - zbar_decoder_set_config(dcode, ZBAR_EAN13, cfg, val); - zbar_decoder_set_config(dcode, ZBAR_EAN8, cfg, val); - zbar_decoder_set_config(dcode, ZBAR_UPCA, cfg, val); - zbar_decoder_set_config(dcode, ZBAR_UPCE, cfg, val); - zbar_decoder_set_config(dcode, ZBAR_ISBN10, cfg, val); - zbar_decoder_set_config(dcode, ZBAR_ISBN13, cfg, val); - zbar_decoder_set_config(dcode, ZBAR_I25, cfg, val); - zbar_decoder_set_config(dcode, ZBAR_CODE39, cfg, val); - zbar_decoder_set_config(dcode, ZBAR_CODE128, cfg, val); - zbar_decoder_set_config(dcode, ZBAR_PDF417, cfg, val); - zbar_decoder_set_config(dcode, ZBAR_QRCODE, cfg, val); + static const zbar_symbol_type_t all[] = { + ZBAR_EAN13, ZBAR_EAN2, ZBAR_EAN5, ZBAR_EAN8, + ZBAR_UPCA, ZBAR_UPCE, ZBAR_ISBN10, ZBAR_ISBN13, + ZBAR_I25, ZBAR_CODE39, ZBAR_CODE128, ZBAR_QRCODE, ZBAR_PDF417, + 0 + }; + const zbar_symbol_type_t *symp; + for(symp = all; *symp; symp++) + zbar_decoder_set_config(dcode, *symp, cfg, val); return(0); } diff --git a/zbar/decoder/code39.c b/zbar/decoder/code39.c index 4a53019..8a7fc62 100644 --- a/zbar/decoder/code39.c +++ b/zbar/decoder/code39.c @@ -198,7 +198,7 @@ static inline signed char code39_decode_start (zbar_decoder_t *dcode) dprintf(2, "\n"); return(ZBAR_NONE); } - dcode39->direction = (c == 0x19); + dcode39->direction ^= (c == 0x19); /* check leading quiet zone - spec is 10x */ unsigned quiet = get_width(dcode, 9); diff --git a/zbar/decoder/ean.c b/zbar/decoder/ean.c index 93d46bd..b5754cc 100644 --- a/zbar/decoder/ean.c +++ b/zbar/decoder/ean.c @@ -146,11 +146,13 @@ static inline signed char aux_end (zbar_decoder_t *dcode, */ static inline signed char aux_start (zbar_decoder_t *dcode) { - /* FIXME NB add-on has no guard in reverse */ + /* FIXME add-on has no guard in reverse, + * currently we only decode them forward + */ unsigned e2 = get_width(dcode, 5) + get_width(dcode, 6); if(decode_e(e2, dcode->ean.s4, 7)) { dprintf(2, " [invalid any]"); - return(/*FIXME (get_color(dcode) == ZBAR_SPACE) ? STATE_ADDON : */-1); + return(-1); } unsigned e1 = get_width(dcode, 4) + get_width(dcode, 5); @@ -182,7 +184,15 @@ static inline signed char aux_start (zbar_decoder_t *dcode) } } dprintf(2, " [invalid center]"); - return(/*STATE_ADDON*/-1); + return(-1); +} + +/* check addon delimiter using current 4 as character + */ +static inline signed char aux_mid (zbar_decoder_t *dcode) +{ + unsigned e = get_width(dcode, 4) + get_width(dcode, 5); + return(decode_e(e, dcode->ean.s4, 7)); } /* attempt to decode previous 4 widths (2 bars and 2 spaces) as a character */ @@ -228,6 +238,24 @@ static inline signed char decode4 (zbar_decoder_t *dcode) return(code); } +static inline char ean_part_end2 (ean_pass_t *pass) +{ + /* extract parity bits */ + unsigned char par = ((pass->raw[1] & 0x10) >> 3 | + (pass->raw[2] & 0x10) >> 4); + /* calculate "checksum" */ + unsigned char chk = ~((pass->raw[1] & 0xf) + + (pass->raw[2] & 0xf) * 10) & 0x3; + dprintf(2, " par=%x chk=%x", par, chk); + if(par != chk) + return(ZBAR_NONE); + + dprintf(2, "\n"); + dprintf(1, "decode2=%x%x\n", + pass->raw[1] & 0xf, pass->raw[2] & 0xf); + return(ZBAR_EAN2); +} + static inline zbar_symbol_type_t ean_part_end4 (ean_pass_t *pass, unsigned char fwd) { @@ -262,6 +290,38 @@ static inline zbar_symbol_type_t ean_part_end4 (ean_pass_t *pass, return(ZBAR_EAN8 | EAN_LEFT); } +static inline char ean_part_end5 (ean_pass_t *pass) +{ + /* extract parity bits */ + unsigned char par = ((pass->raw[1] & 0x10) | + (pass->raw[2] & 0x10) >> 1 | + (pass->raw[3] & 0x10) >> 2 | + (pass->raw[4] & 0x10) >> 3 | + (pass->raw[5] & 0x10) >> 4); + /* calculate checksum */ + unsigned char chk = (((pass->raw[1] & 0x0f) + + (pass->raw[2] & 0x0f) * 3 + + (pass->raw[3] & 0x0f) + + (pass->raw[4] & 0x0f) * 3 + + (pass->raw[5] & 0x0f)) * 3) % 10; + + unsigned char parchk = parity_decode[par >> 1]; + if(par & 1) + parchk >>= 4; + parchk &= 0xf; + dprintf(2, " par=%x(%d) chk=%d", par, parchk, chk); + if(parchk != chk) + return(ZBAR_NONE); + + dprintf(2, "\n"); + dprintf(1, "decode5=%x%x%x%x%x\n", + pass->raw[1] & 0xf, pass->raw[2] & 0xf, + pass->raw[3] & 0xf, pass->raw[4] & 0xf, + pass->raw[5] & 0xf); + + return(ZBAR_EAN5); +} + static inline zbar_symbol_type_t ean_part_end7 (ean_decoder_t *ean, ean_pass_t *pass, unsigned char fwd) @@ -330,18 +390,55 @@ static inline zbar_symbol_type_t decode_pass (zbar_decoder_t *dcode, unsigned char idx = pass->state & STATE_IDX; unsigned char fwd = pass->state & 1; - if(get_color(dcode) == ZBAR_SPACE && - (idx == 0x10 || idx == 0x11) && - TEST_CFG(dcode->ean.ean8_config, ZBAR_CFG_ENABLE) && - !aux_end(dcode, fwd)) { - dprintf(2, " fwd=%x", fwd); - zbar_symbol_type_t part = ean_part_end4(pass, fwd); - if(part) - dcode->ean.direction = (pass->state & STATE_REV) != 0; - pass->state = -1; - return(part); + if(get_color(dcode) == ZBAR_SPACE) { + if(pass->state & STATE_ADDON) { + dprintf(2, " i=%d", idx); + if(idx == 0x09 || idx == 0x21) { + unsigned qz = get_width(dcode, 0); + unsigned s = calc_s(dcode, 1, 4); + zbar_symbol_type_t part = !qz || (qz >= s * 3 / 4); + if(part && idx == 0x09) + part = ean_part_end2(pass); + else if(part) + part = ean_part_end5(pass); + + if(part || idx == 0x21) { + dcode->ean.direction = 0; + pass->state = -1; + return(part); + } + } + if((idx & 7) == 1) { + dprintf(2, " +"); + pass->state += 2; + idx += 2; + } + } + else if((idx == 0x10 || idx == 0x11) && + TEST_CFG(dcode->ean.ean8_config, ZBAR_CFG_ENABLE) && + !aux_end(dcode, fwd)) { + dprintf(2, " fwd=%x", fwd); + zbar_symbol_type_t part = ean_part_end4(pass, fwd); + if(part) + dcode->ean.direction = (pass->state & STATE_REV) != 0; + pass->state = -1; + return(part); + } + else if((idx == 0x18 || idx == 0x19)) { + zbar_symbol_type_t part = ZBAR_NONE; + dprintf(2, " fwd=%x", fwd); + if(!aux_end(dcode, fwd)) + part = ean_part_end7(&dcode->ean, pass, fwd); + if(part) + dcode->ean.direction = (pass->state & STATE_REV) != 0; + pass->state = -1; + return(part); + } } + if(pass->state & STATE_ADDON) + idx >>= 1; + if(!(idx & 0x03) && idx <= 0x14) { if(!dcode->ean.s4) return(0); @@ -353,7 +450,8 @@ static inline zbar_symbol_type_t decode_pass (zbar_decoder_t *dcode, idx = pass->state & STATE_IDX; } signed char code = decode4(dcode); - if(code < 0) + if(code < 0 || + (idx > 0 && (pass->state & STATE_ADDON) && aux_mid(dcode))) pass->state = -1; else { dprintf(2, "\n raw[%x]=%02x =>", idx >> 2, @@ -366,18 +464,6 @@ static inline zbar_symbol_type_t decode_pass (zbar_decoder_t *dcode, pass->raw[6] & 0xf); } } - - if(get_color(dcode) == ZBAR_SPACE && - (idx == 0x18 || idx == 0x19)) { - zbar_symbol_type_t part = ZBAR_NONE; - dprintf(2, " fwd=%x", fwd); - if(!aux_end(dcode, fwd)) - part = ean_part_end7(&dcode->ean, pass, fwd); - if(part) - dcode->ean.direction = (pass->state & STATE_REV) != 0; - pass->state = -1; - return(part); - } return(0); } @@ -463,62 +549,52 @@ static inline zbar_symbol_type_t integrate_partial (ean_decoder_t *ean, /* if same partial is not consistent, reset others */ dprintf(2, " integrate part=%x (%s)", part, dsprintbuf(ean)); signed char i, j; - if(part & ZBAR_ADDON) { - /* FIXME TBD */ - for(i = (part == ZBAR_ADDON5) ? 4 : 1; i >= 0; i--) { + if((ean->left && ((part & ZBAR_SYMBOL) != ean->left)) || + (ean->right && ((part & ZBAR_SYMBOL) != ean->right))) { + /* partial mismatch - reset collected parts */ + dprintf(2, " rst(type %x %x)", ean->left, ean->right); + ean->left = ean->right = ZBAR_NONE; + } + + if(part & EAN_RIGHT) { + part &= ZBAR_SYMBOL; + j = part - 1; + for(i = part >> 1; i; i--, j--) { unsigned char digit = pass->raw[i] & 0xf; - if(ean->addon && ean->buf[i + 13] != digit) { + if(ean->right && ean->buf[j] != digit) { /* partial mismatch - reset collected parts */ - ean->left = ean->right = ean->addon = ZBAR_NONE; + dprintf(2, " rst(right)"); + ean->left = ean->right = ZBAR_NONE; } - ean->buf[i + 13] = digit; + ean->buf[j] = digit; } - ean->addon = part; + ean->right = part; + part &= ean->left; /* FIXME!? */ } - else { - if((ean->left && ((part & ZBAR_SYMBOL) != ean->left)) || - (ean->right && ((part & ZBAR_SYMBOL) != ean->right))) { - /* partial mismatch - reset collected parts */ - dprintf(2, " rst(type %x %x)", ean->left, ean->right); - ean->left = ean->right = ean->addon = ZBAR_NONE; - } - - if(part & EAN_RIGHT) { - part &= ZBAR_SYMBOL; - j = (part == ZBAR_EAN13) ? 12 : 7; - for(i = (part == ZBAR_EAN13) ? 6 : 4; i; i--, j--) { - unsigned char digit = pass->raw[i] & 0xf; - if(ean->right && ean->buf[j] != digit) { - /* partial mismatch - reset collected parts */ - dprintf(2, " rst(right)"); - ean->left = ean->right = ean->addon = ZBAR_NONE; - } - ean->buf[j] = digit; - } - ean->right = part; - } - else if(part != ZBAR_UPCE) /* EAN_LEFT */ { - j = (part == ZBAR_EAN13) ? 6 : 3; - for(i = (part == ZBAR_EAN13) ? 6 : 4; j >= 0; i--, j--) { - unsigned char digit = pass->raw[i] & 0xf; - if(ean->left && ean->buf[j] != digit) { - /* partial mismatch - reset collected parts */ - dprintf(2, " rst(left)"); - ean->left = ean->right = ean->addon = ZBAR_NONE; - } - ean->buf[j] = digit; + else if(part == ZBAR_EAN13 || part == ZBAR_EAN8) /* EAN_LEFT */ { + j = (part - 1) >> 1; + for(i = part >> 1; j >= 0; i--, j--) { + unsigned char digit = pass->raw[i] & 0xf; + if(ean->left && ean->buf[j] != digit) { + /* partial mismatch - reset collected parts */ + dprintf(2, " rst(left)"); + ean->left = ean->right = ZBAR_NONE; } - ean->left = part; + ean->buf[j] = digit; } - else /* ZBAR_UPCE */ - ean_expand_upce(ean, pass); + ean->left = part; + part &= ean->right; /* FIXME!? */ } - - if((part & ZBAR_SYMBOL) != ZBAR_UPCE) { - part = (ean->left & ean->right); - if(!part) - part = ZBAR_PARTIAL; + else if(part != ZBAR_UPCE) /* add-ons */ { + for(i = part; i > 0; i--) + ean->buf[i - 1] = pass->raw[i] & 0xf; + ean->left = part; } + else + ean_expand_upce(ean, pass); + + if(!part) + part = ZBAR_PARTIAL; if(((part == ZBAR_EAN13 || part == ZBAR_UPCE) && ean_verify_checksum(ean, 12)) || @@ -559,9 +635,6 @@ static inline zbar_symbol_type_t integrate_partial (ean_decoder_t *ean, part = ZBAR_NONE; } - if(part > ZBAR_PARTIAL) - part |= ean->addon; - dprintf(2, " dir=%d %x/%x=%x", ean->direction, ean->left, ean->right, part); return(part); @@ -572,7 +645,7 @@ static inline void postprocess (zbar_decoder_t *dcode, zbar_symbol_type_t sym) { ean_decoder_t *ean = &dcode->ean; - zbar_symbol_type_t base = sym & ZBAR_SYMBOL; + zbar_symbol_type_t base = sym; int i = 0, j = 0; if(base > ZBAR_PARTIAL) { if(base == ZBAR_UPCA) @@ -587,23 +660,22 @@ static inline void postprocess (zbar_decoder_t *dcode, i = 3; if(base == ZBAR_ISBN10 || - !TEST_CFG(ean_get_config(ean, sym), ZBAR_CFG_EMIT_CHECK)) + (base > ZBAR_EAN5 && + !TEST_CFG(ean_get_config(ean, sym), ZBAR_CFG_EMIT_CHECK))) base--; for(; j < base && ean->buf[i] >= 0; i++, j++) dcode->buf[j] = ean->buf[i] + '0'; - if((sym & ZBAR_SYMBOL) == ZBAR_ISBN10 && j == 9 && + if(sym == ZBAR_ISBN10 && j == 9 && TEST_CFG(ean->isbn10_config, ZBAR_CFG_EMIT_CHECK)) /* recalculate ISBN-10 check digit */ dcode->buf[j++] = isbn10_calc_checksum(ean); } - if(sym & ZBAR_ADDON) - for(i = 13; ean->buf[i] >= 0; i++, j++) - dcode->buf[j] = ean->buf[i] + '0'; dcode->buflen = j; dcode->buf[j] = '\0'; dcode->direction = 1 - 2 * ean->direction; + dprintf(2, " base=%d j=%d (%s)", base, j, dcode->buf); } zbar_symbol_type_t _zbar_decode_ean (zbar_decoder_t *dcode) @@ -623,7 +695,7 @@ zbar_symbol_type_t _zbar_decode_ean (zbar_decoder_t *dcode) i == pass_idx) { dprintf(2, " ean[%x/%x]: idx=%x st=%d s=%d", - pass_idx, i, dcode->idx, pass->state, dcode->ean.s4); + i, pass_idx, dcode->idx, pass->state, dcode->ean.s4); zbar_symbol_type_t part = decode_pass(dcode, pass); if(part) { /* update accumulated data from new partial decode */ diff --git a/zbar/decoder/ean.h b/zbar/decoder/ean.h index 8ab895f..e634fc5 100644 --- a/zbar/decoder/ean.h +++ b/zbar/decoder/ean.h @@ -28,7 +28,7 @@ typedef struct ean_pass_s { signed char state; /* module position of w[idx] in symbol */ #define STATE_REV 0x80 /* scan direction reversed */ #define STATE_ADDON 0x40 /* scanning add-on */ -#define STATE_IDX 0x1f /* element offset into symbol */ +#define STATE_IDX 0x3f /* element offset into symbol */ unsigned char raw[7]; /* decode in process */ } ean_pass_t; @@ -37,7 +37,6 @@ typedef struct ean_decoder_s { ean_pass_t pass[4]; /* state of each parallel decode attempt */ zbar_symbol_type_t left; /* current holding buffer contents */ zbar_symbol_type_t right; - zbar_symbol_type_t addon; int direction; /* scan direction */ unsigned s4; /* character width */ signed char buf[18]; /* holding buffer */ @@ -49,6 +48,8 @@ typedef struct ean_decoder_s { unsigned upce_config; unsigned isbn10_config; unsigned isbn13_config; + unsigned ean5_config; + unsigned ean2_config; } ean_decoder_t; /* reset EAN/UPC pass specific state */ @@ -63,20 +64,22 @@ static inline void ean_new_scan (ean_decoder_t *ean) static inline void ean_reset (ean_decoder_t *ean) { ean_new_scan(ean); - ean->left = ean->right = ean->addon = ZBAR_NONE; + ean->left = ean->right = ZBAR_NONE; } static inline unsigned ean_get_config (ean_decoder_t *ean, zbar_symbol_type_t sym) { - switch(sym & ZBAR_SYMBOL) { - case ZBAR_EAN13: return(ean->ean13_config); + switch(sym) { + case ZBAR_EAN2: return(ean->ean2_config); + case ZBAR_EAN5: return(ean->ean5_config); case ZBAR_EAN8: return(ean->ean8_config); - case ZBAR_UPCA: return(ean->upca_config); case ZBAR_UPCE: return(ean->upce_config); case ZBAR_ISBN10: return(ean->isbn10_config); + case ZBAR_UPCA: return(ean->upca_config); + case ZBAR_EAN13: return(ean->ean13_config); case ZBAR_ISBN13: return(ean->isbn13_config); - default: return(0); + default: return(0); } } diff --git a/zbar/decoder/i25.c b/zbar/decoder/i25.c index 75a0a28..1e85979 100644 --- a/zbar/decoder/i25.c +++ b/zbar/decoder/i25.c @@ -145,6 +145,9 @@ static inline signed char i25_decode_end (zbar_decoder_t *dcode) decode_e(get_width(dcode, 4), dcode25->width, 45) > 2)) return(ZBAR_NONE); + dcode->buf[0] = dcode25->buf[0]; + dcode->buf[1] = dcode25->buf[1]; + dcode->direction = 1 - 2 * dcode25->direction; if(dcode25->direction) { /* reverse buffer */ @@ -198,11 +201,17 @@ zbar_symbol_type_t _zbar_decode_i25 (zbar_decoder_t *dcode) (dcode25->direction) ? '<' : '>', dcode25->character, dcode25->element); - /* lock shared resources */ - if(!dcode25->character && get_lock(dcode, ZBAR_I25)) { - dcode25->character = -1; - dprintf(2, " [locked %d]\n", dcode->lock); - return(ZBAR_PARTIAL); + unsigned char *buf; + if(!dcode25->character) + buf = dcode25->buf; + else { + /* lock shared resources */ + if(dcode25->character == 2 && get_lock(dcode, ZBAR_I25)) { + dcode25->character = -1; + dprintf(2, " [locked %d]\n", dcode->lock); + return(ZBAR_PARTIAL); + } + buf = dcode->buf + dcode25->character; } unsigned char c = i25_decode10(dcode, 1); @@ -216,7 +225,7 @@ zbar_symbol_type_t _zbar_decode_i25 (zbar_decoder_t *dcode) dcode25->character = -1; return(ZBAR_NONE); } - dcode->buf[dcode25->character++] = c + '0'; + *(buf++) = c + '0'; c = i25_decode10(dcode, 0); dprintf(2, " c=%x", c); @@ -228,8 +237,9 @@ zbar_symbol_type_t _zbar_decode_i25 (zbar_decoder_t *dcode) } else dprintf(2, "\n"); + *buf = c + '0'; - dcode->buf[dcode25->character++] = c + '0'; dcode25->element = 10; + dcode25->character += 2; return((dcode25->character == 2) ? ZBAR_PARTIAL : ZBAR_NONE); } diff --git a/zbar/decoder/i25.h b/zbar/decoder/i25.h index 4f4bee0..ba48b31 100644 --- a/zbar/decoder/i25.h +++ b/zbar/decoder/i25.h @@ -30,6 +30,7 @@ typedef struct i25_decoder_s { int character : 12; /* character position in symbol */ unsigned s10; /* current character width */ unsigned width; /* last character width */ + unsigned char buf[2]; /* initial decode */ unsigned config; int configs[NUM_CFGS]; /* int valued configurations */ diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 4551548..3bd3e31 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -111,6 +111,7 @@ struct zbar_image_scanner_s { /* configuration settings */ unsigned config; /* config flags */ + unsigned ean_config; int configs[NUM_SCN_CFGS]; /* int valued configurations */ #ifndef NO_STATS @@ -542,6 +543,12 @@ int zbar_image_scanner_set_config (zbar_image_scanner_t *iscn, zbar_config_t cfg, int val) { + if((sym == 0 || sym == ZBAR_EANUPC) && cfg == ZBAR_CFG_ENABLE) { + iscn->ean_config = !!val; + if(sym) + return(0); + } + if(cfg < ZBAR_CFG_POSITION) return(zbar_decoder_set_config(iscn->dcode, sym, cfg, val)); @@ -549,7 +556,6 @@ int zbar_image_scanner_set_config (zbar_image_scanner_t *iscn, return(1); if(cfg >= ZBAR_CFG_X_DENSITY && cfg <= ZBAR_CFG_Y_DENSITY) { - CFG(iscn, cfg) = val; return(0); } @@ -759,20 +765,64 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, #endif /* FIXME tmp hack to filter bad EAN results */ - if(syms->nsyms && !iscn->enable_cache && - (density == 1 || CFG(iscn, ZBAR_CFG_Y_DENSITY) == 1)) { - zbar_symbol_t **symp = &syms->head, *sym; - while((sym = *symp)) { - if(sym->type < ZBAR_I25 && sym->type > ZBAR_PARTIAL && - sym->quality < 3) { - /* recycle */ - *symp = sym->next; - syms->nsyms--; - sym->next = NULL; - _zbar_image_scanner_recycle_syms(iscn, sym); + /* FIXME tmp hack to merge simple case EAN add-ons */ + char filter = (!iscn->enable_cache && + (density == 1 || CFG(iscn, ZBAR_CFG_Y_DENSITY) == 1)); + int nean = 0, naddon = 0; + if(syms->nsyms) { + zbar_symbol_t **symp; + for(symp = &syms->head; *symp; ) { + zbar_symbol_t *sym = *symp; + if(sym->type < ZBAR_EANUPC && sym->type > ZBAR_PARTIAL) { + if(filter && sym->quality < 3) { + /* recycle */ + *symp = sym->next; + syms->nsyms--; + sym->next = NULL; + _zbar_image_scanner_recycle_syms(iscn, sym); + continue; + } + else if(sym->type > ZBAR_EAN5) + nean++; + else + naddon++; + } + symp = &sym->next; + } + + if(nean == 1 && naddon == 1 && iscn->ean_config) { + /* create container symbol for composite result */ + zbar_symbol_t *ean = NULL, *addon = NULL; + for(symp = &syms->head; *symp; ) { + zbar_symbol_t *sym = *symp; + if(sym->type < ZBAR_EANUPC && sym->type > ZBAR_PARTIAL) { + /* move to composite */ + *symp = sym->next; + syms->nsyms--; + sym->next = NULL; + if(sym->type <= ZBAR_EAN5) + addon = sym; + else + ean = sym; + } + else + symp = &sym->next; } - else - symp = &sym->next; + assert(ean); + assert(addon); + + int datalen = ean->datalen + addon->datalen + 1; + zbar_symbol_t *ean_sym = + _zbar_image_scanner_alloc_sym(iscn, ZBAR_EANUPC, datalen); + ean_sym->orient = ean->orient; + ean_sym->syms = _zbar_symbol_set_create(); + memcpy(ean_sym->data, ean->data, ean->datalen); + memcpy(ean_sym->data + ean->datalen, + addon->data, addon->datalen + 1); + ean_sym->syms->head = ean; + ean->next = addon; + ean_sym->syms->nsyms = 2; + _zbar_image_scanner_add_sym(iscn, ean_sym); } } diff --git a/zbar/processor.c b/zbar/processor.c index 3bd57a3..dcc0507 100644 --- a/zbar/processor.c +++ b/zbar/processor.c @@ -95,9 +95,8 @@ int _zbar_process_image (zbar_processor_t *proc, while(sym) { zbar_symbol_type_t type = zbar_symbol_get_type(sym); int count = zbar_symbol_get_count(sym); - zprintf(8, "%s%s: %s (%d pts) (dir=%d) (q=%d) (%s)\n", + zprintf(8, "%s: %s (%d pts) (dir=%d) (q=%d) (%s)\n", zbar_get_symbol_name(type), - zbar_get_addon_name(type), zbar_symbol_get_data(sym), zbar_symbol_get_loc_size(sym), zbar_symbol_get_orientation(sym), diff --git a/zbar/symbol.c b/zbar/symbol.c index 590b340..5be9a4a 100644 --- a/zbar/symbol.c +++ b/zbar/symbol.c @@ -32,12 +32,15 @@ const char *zbar_get_symbol_name (zbar_symbol_type_t sym) { switch(sym & ZBAR_SYMBOL) { + case ZBAR_EAN2: return("EAN-2"); + case ZBAR_EAN5: return("EAN-5"); case ZBAR_EAN8: return("EAN-8"); case ZBAR_UPCE: return("UPC-E"); case ZBAR_ISBN10: return("ISBN-10"); case ZBAR_UPCA: return("UPC-A"); case ZBAR_EAN13: return("EAN-13"); case ZBAR_ISBN13: return("ISBN-13"); + case ZBAR_EANUPC: return("EAN/UPC"); case ZBAR_I25: return("I2/5"); case ZBAR_CODE39: return("CODE-39"); case ZBAR_CODE128: return("CODE-128"); @@ -49,11 +52,7 @@ const char *zbar_get_symbol_name (zbar_symbol_type_t sym) const char *zbar_get_addon_name (zbar_symbol_type_t sym) { - switch(sym & ZBAR_ADDON) { - case ZBAR_ADDON2: return("+2"); - case ZBAR_ADDON5: return("+5"); - default: return(""); - } + return(""); } const char *zbar_get_orientation_name (zbar_orientation_t orient) From a0a78ab84ff5c270c4d5fa2e0c3cbb3ffe0a99dd Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 20 Dec 2010 09:09:21 -0800 Subject: [PATCH 255/328] iPhone: fix doc typo (bug #3139087) - add modifier bit docs --- iphone/ChangeLog | 4 ++++ iphone/doc/ZBarSymbol.rst | 19 ++++++++++++++++++- iphone/doc/compat.rst | 4 ++-- iphone/doc/picker.rst | 4 ++-- python/README | 3 ++- 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index b68fbb3..75df57f 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,3 +1,7 @@ +current: + * fix doc typo (bug #3139087) + - add modifier bit docs + version 1.0.1: * hotfix broken ZBarHelpController back button * release updates diff --git a/iphone/doc/ZBarSymbol.rst b/iphone/doc/ZBarSymbol.rst index 6cf9705..0fbcda5 100644 --- a/iphone/doc/ZBarSymbol.rst +++ b/iphone/doc/ZBarSymbol.rst @@ -31,7 +31,8 @@ Properties .. member:: NSUInteger modifierMask - Bitmask of symbology characteristics detected during decode. + Bitmask of symbology characteristics detected during decode. See + :type:`zbar_modifier_t` for the currently defined modifier bits. .. member:: NSString *data @@ -164,3 +165,19 @@ Constants 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. diff --git a/iphone/doc/compat.rst b/iphone/doc/compat.rst index 038e614..027b49f 100644 --- a/iphone/doc/compat.rst +++ b/iphone/doc/compat.rst @@ -153,7 +153,7 @@ 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: - UIImagePickerControllerSoureTypeCamera]) { + UIImagePickerControllerSourceTypeCamera]) { // camera unavailable: display warning and abort // or resort to keypad entry, etc... return; @@ -164,7 +164,7 @@ depending on whether the library was compiled to use private APIs:: // or a ZBarReaderViewController for iOS 4 reader.readerDelegate = self; - reader.sourceType = UIImagePickerControllerSoureTypeCamera; + reader.sourceType = UIImagePickerControllerSourceTypeCamera; reader.showsZBarControls = YES; if(reader.cameraMode == ZBarReaderControllerCameraModeSampling) { diff --git a/iphone/doc/picker.rst b/iphone/doc/picker.rst index 35335af..26a0e53 100644 --- a/iphone/doc/picker.rst +++ b/iphone/doc/picker.rst @@ -28,8 +28,8 @@ documentation for :class:`UIImagePickerController` for more detais. property:: if([ZBarReaderController isSourceTypeAvailable: - UIImagePickerControllerSoureTypeCamera]) - reader.sourceType = UIImagePickerControllerSoureTypeCamera; + UIImagePickerControllerSourceTypeCamera]) + reader.sourceType = UIImagePickerControllerSourceTypeCamera; [reader.scanner setSymbology: ZBAR_I25 config: ZBAR_CFG_ENABLE to: 0]; diff --git a/python/README b/python/README index 62313f4..3698d7c 100644 --- a/python/README +++ b/python/README @@ -29,7 +29,8 @@ from: * http://zbar.sourceforge.net/ Windows users please note: the module *will NOT load* unless the ZBar -library DLL (currently libzbar-0.dll) is available in your PATH! +library DLL (currently libzbar-0.dll) is available in your Windows system +PATH! Examples -------- From 3c68e1ec7c37874311ee66ca276c8e3c04b12548 Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 28 Dec 2010 13:26:36 -0800 Subject: [PATCH 256/328] iPhone: fix doc typo (bug #3139087) - add modifier bit docs --- iphone/ChangeLog | 4 ++++ iphone/doc/ZBarSymbol.rst | 19 ++++++++++++++++++- iphone/doc/compat.rst | 4 ++-- iphone/doc/picker.rst | 4 ++-- python/README | 3 ++- 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index b68fbb3..75df57f 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,3 +1,7 @@ +current: + * fix doc typo (bug #3139087) + - add modifier bit docs + version 1.0.1: * hotfix broken ZBarHelpController back button * release updates diff --git a/iphone/doc/ZBarSymbol.rst b/iphone/doc/ZBarSymbol.rst index 6cf9705..0fbcda5 100644 --- a/iphone/doc/ZBarSymbol.rst +++ b/iphone/doc/ZBarSymbol.rst @@ -31,7 +31,8 @@ Properties .. member:: NSUInteger modifierMask - Bitmask of symbology characteristics detected during decode. + Bitmask of symbology characteristics detected during decode. See + :type:`zbar_modifier_t` for the currently defined modifier bits. .. member:: NSString *data @@ -164,3 +165,19 @@ Constants 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. diff --git a/iphone/doc/compat.rst b/iphone/doc/compat.rst index 038e614..027b49f 100644 --- a/iphone/doc/compat.rst +++ b/iphone/doc/compat.rst @@ -153,7 +153,7 @@ 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: - UIImagePickerControllerSoureTypeCamera]) { + UIImagePickerControllerSourceTypeCamera]) { // camera unavailable: display warning and abort // or resort to keypad entry, etc... return; @@ -164,7 +164,7 @@ depending on whether the library was compiled to use private APIs:: // or a ZBarReaderViewController for iOS 4 reader.readerDelegate = self; - reader.sourceType = UIImagePickerControllerSoureTypeCamera; + reader.sourceType = UIImagePickerControllerSourceTypeCamera; reader.showsZBarControls = YES; if(reader.cameraMode == ZBarReaderControllerCameraModeSampling) { diff --git a/iphone/doc/picker.rst b/iphone/doc/picker.rst index 35335af..26a0e53 100644 --- a/iphone/doc/picker.rst +++ b/iphone/doc/picker.rst @@ -28,8 +28,8 @@ documentation for :class:`UIImagePickerController` for more detais. property:: if([ZBarReaderController isSourceTypeAvailable: - UIImagePickerControllerSoureTypeCamera]) - reader.sourceType = UIImagePickerControllerSoureTypeCamera; + UIImagePickerControllerSourceTypeCamera]) + reader.sourceType = UIImagePickerControllerSourceTypeCamera; [reader.scanner setSymbology: ZBAR_I25 config: ZBAR_CFG_ENABLE to: 0]; diff --git a/python/README b/python/README index 62313f4..3698d7c 100644 --- a/python/README +++ b/python/README @@ -29,7 +29,8 @@ from: * http://zbar.sourceforge.net/ Windows users please note: the module *will NOT load* unless the ZBar -library DLL (currently libzbar-0.dll) is available in your PATH! +library DLL (currently libzbar-0.dll) is available in your Windows system +PATH! Examples -------- From 2d8d3e98b12ddb1674480d978a711f2a4057d8eb Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 28 Dec 2010 13:42:43 -0800 Subject: [PATCH 257/328] iPhone: release updates --- iphone/ChangeLog | 2 +- iphone/res/ZBarSDK-Info.plist | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 75df57f..f785546 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,4 @@ -current: +version 1.1: * fix doc typo (bug #3139087) - add modifier bit docs diff --git a/iphone/res/ZBarSDK-Info.plist b/iphone/res/ZBarSDK-Info.plist index a785148..3ce3bf0 100644 --- a/iphone/res/ZBarSDK-Info.plist +++ b/iphone/res/ZBarSDK-Info.plist @@ -7,7 +7,7 @@ CFBundleName ZBarSDK CFBundleVersion - 1.0.1 + 1.1 CFBundleSignature ???? NSHumanReadableCopyright From bf031dae923257467b2d180c89ae6ce7f0149c9b Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 28 Dec 2010 13:43:27 -0800 Subject: [PATCH 258/328] Added tag iPhoneSDK-1.1 for changeset 5e5060b563a1 From 512f009055b7b017bc8eca0af74b5b1ba79fafe2 Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 16 Jan 2011 11:46:28 -0800 Subject: [PATCH 259/328] rename dprintf macro to avoid conflicts (patch #3128538) - thanks to maurochehab for the patch! --- ChangeLog | 2 + zbar/debug.h | 8 +-- zbar/decoder.c | 2 +- zbar/decoder.h | 2 +- zbar/decoder/code128.c | 54 +++++++-------- zbar/decoder/code39.c | 44 ++++++------- zbar/decoder/code93.c | 50 +++++++------- zbar/decoder/databar.c | 138 +++++++++++++++++++-------------------- zbar/decoder/ean.c | 128 ++++++++++++++++++------------------ zbar/decoder/i25.c | 44 ++++++------- zbar/decoder/pdf417.c | 34 +++++----- zbar/decoder/qr_finder.c | 18 ++--- zbar/scanner.c | 30 ++++----- 13 files changed, 278 insertions(+), 276 deletions(-) diff --git a/ChangeLog b/ChangeLog index cc40cf9..3d5916d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * 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 diff --git a/zbar/debug.h b/zbar/debug.h index 468996f..9c41075 100644 --- a/zbar/debug.h +++ b/zbar/debug.h @@ -29,21 +29,21 @@ # ifdef __GNUC__ /* older versions of gcc (< 2.95) require a named varargs parameter */ -# define dprintf(args...) while(0) +# define dbprintf(args...) while(0) # else /* unfortunately named vararg parameter is a gcc-specific extension */ -# define dprintf(...) while(0) +# define dbprintf(...) while(0) # endif #else # ifdef __GNUC__ -# define dprintf(level, args...) do { \ +# define dbprintf(level, args...) do { \ if((level) <= DEBUG_LEVEL) \ fprintf(stderr, args); \ } while(0) # else -# define dprintf(level, ...) do { \ +# define dbprintf(level, ...) do { \ if((level) <= DEBUG_LEVEL) \ fprintf(stderr, __VA_ARGS__); \ } while(0) diff --git a/zbar/decoder.c b/zbar/decoder.c index fe53565..4d2dc25 100644 --- a/zbar/decoder.c +++ b/zbar/decoder.c @@ -220,7 +220,7 @@ zbar_symbol_type_t zbar_decode_width (zbar_decoder_t *dcode, zbar_symbol_type_t tmp, sym = ZBAR_NONE; dcode->w[dcode->idx & (DECODE_WINDOW - 1)] = w; - dprintf(1, " decode[%x]: w=%d (%g)\n", dcode->idx, w, (w / 32.)); + dbprintf(1, " decode[%x]: w=%d (%g)\n", dcode->idx, w, (w / 32.)); /* update shared character width */ dcode->s6 -= get_width(dcode, 7); diff --git a/zbar/decoder.h b/zbar/decoder.h index 17c3599..4603d0a 100644 --- a/zbar/decoder.h +++ b/zbar/decoder.h @@ -188,7 +188,7 @@ static inline char acquire_lock (zbar_decoder_t *dcode, zbar_symbol_type_t req) { if(dcode->lock) { - dprintf(2, " [locked %d]\n", dcode->lock); + dbprintf(2, " [locked %d]\n", dcode->lock); return(1); } dcode->lock = req; diff --git a/zbar/decoder/code128.c b/zbar/decoder/code128.c index e3a8b4c..3e5ef0b 100644 --- a/zbar/decoder/code128.c +++ b/zbar/decoder/code128.c @@ -137,9 +137,9 @@ static inline signed char decode_lo (int sig) zassert(idx <= 0x50, -1, "sig=%x offset=%x base=%x idx=%x\n", sig, offset, base, idx); c = characters[idx]; - dprintf(2, " %02x(%x(%02x)/%x(%02x)) => %02x", - idx, base, lo_base[base], offset, lo_offset[offset], - (unsigned char)c); + dbprintf(2, " %02x(%x(%02x)/%x(%02x)) => %02x", + idx, base, lo_base[base], offset, lo_offset[offset], + (unsigned char)c); return(c); } @@ -152,7 +152,7 @@ static inline signed char decode_hi (int sig) ((sig >> 4) & 0x00f0) | ((sig << 4) & 0x0f00) | ((sig << 12) & 0xf000)); - dprintf(2, " rev=%x", rev != 0); + dbprintf(2, " rev=%x", rev != 0); switch(sig) { case 0x0014: idx = 0x0; break; @@ -174,7 +174,7 @@ static inline signed char decode_hi (int sig) if(rev) idx += 0xe; c = characters[0x51 + idx]; - dprintf(2, " %02x => %02x", idx, c); + dbprintf(2, " %02x => %02x", idx, c); return(c); } @@ -199,7 +199,7 @@ static inline signed char decode6 (zbar_decoder_t *dcode) /* build edge signature of character */ unsigned s = dcode->code128.s6; - dprintf(2, " s=%d", s); + dbprintf(2, " s=%d", s); if(s < 5) return(-1); /* calculate similar edge measurements */ @@ -214,7 +214,7 @@ static inline signed char decode6 (zbar_decoder_t *dcode) (decode_e(get_width(dcode, 2) + get_width(dcode, 1), s, 11))); if(sig < 0) return(-1); - dprintf(2, " sig=%04x", sig); + dbprintf(2, " sig=%04x", sig); /* lookup edge signature */ c = (sig & 0x4444) ? decode_hi(sig) : decode_lo(sig); if(c == -1) @@ -226,7 +226,7 @@ static inline signed char decode6 (zbar_decoder_t *dcode) : (get_width(dcode, 1) + get_width(dcode, 3) + get_width(dcode, 5)); bars = bars * 11 * 4 / s; chk = calc_check(c); - dprintf(2, " bars=%d chk=%d", bars, chk); + dbprintf(2, " bars=%d chk=%d", bars, chk); if(chk - 7 > bars || bars > chk + 7) return(-1); @@ -268,10 +268,10 @@ static inline unsigned char validate_checksum (zbar_decoder_t *dcode) /* and compare to check character */ idx = (dcode128->direction) ? 1 : dcode128->character - 2; check = dcode->buf[idx]; - dprintf(2, " chk=%02x(%02x)", sum, check); + dbprintf(2, " chk=%02x(%02x)", sum, check); err = (sum != check); if(err) - dprintf(1, " [checksum error]\n"); + dbprintf(1, " [checksum error]\n"); return(err); } @@ -330,12 +330,12 @@ static inline unsigned char postprocess (zbar_decoder_t *dcode) unsigned i, j, cexp; unsigned char code = 0, charset; code128_decoder_t *dcode128 = &dcode->code128; - dprintf(2, "\n postproc len=%d", dcode128->character); + dbprintf(2, "\n postproc len=%d", dcode128->character); dcode->modifiers = 0; dcode->direction = 1 - 2 * dcode128->direction; if(dcode128->direction) { /* reverse buffer */ - dprintf(2, " (rev)"); + dbprintf(2, " (rev)"); for(i = 0; i < dcode128->character / 2; i++) { unsigned j = dcode128->character - 1 - i; code = dcode->buf[i]; @@ -357,7 +357,7 @@ static inline unsigned char postprocess (zbar_decoder_t *dcode) charset = code - START_A; cexp = (code == START_C) ? 1 : 0; - dprintf(2, " start=%c", 'A' + charset); + dbprintf(2, " start=%c", 'A' + charset); for(i = 1, j = 0; i < dcode128->character - 2; i++) { unsigned char code = dcode->buf[i]; @@ -380,7 +380,7 @@ static inline unsigned char postprocess (zbar_decoder_t *dcode) charset &= 0x7f; } else { - dprintf(2, " %02x", code); + dbprintf(2, " %02x", code); if(charset & 0x2) { unsigned delta; /* expand character set C to ASCII */ @@ -414,7 +414,7 @@ static inline unsigned char postprocess (zbar_decoder_t *dcode) /*else drop trailing FNC1 */ } else if(code >= START_A) { - dprintf(1, " [truncated]\n"); + dbprintf(1, " [truncated]\n"); return(1); } else { @@ -465,21 +465,21 @@ zbar_symbol_type_t _zbar_decode_code128 (zbar_decoder_t *dcode) return(0); dcode128->element = 0; - dprintf(2, " code128[%c%02d+%x]:", - (dcode128->direction) ? '<' : '>', - dcode128->character, dcode128->element); + dbprintf(2, " code128[%c%02d+%x]:", + (dcode128->direction) ? '<' : '>', + dcode128->character, dcode128->element); c = decode6(dcode); if(dcode128->character < 0) { unsigned qz; - dprintf(2, " c=%02x", c); + dbprintf(2, " c=%02x", c); if(c < START_A || c > STOP_REV || c == STOP_FWD) { - dprintf(2, " [invalid]\n"); + dbprintf(2, " [invalid]\n"); return(0); } qz = get_width(dcode, 6); if(qz && qz < (dcode128->s6 * 3) / 4) { - dprintf(2, " [invalid qz %d]\n", qz); + dbprintf(2, " [invalid qz %d]\n", qz); return(0); } /* decoded valid start/stop */ @@ -493,13 +493,13 @@ zbar_symbol_type_t _zbar_decode_code128 (zbar_decoder_t *dcode) dcode128->direction = ZBAR_SPACE; dcode128->start = c; dcode128->width = dcode128->s6; - dprintf(2, " dir=%x [valid start]\n", dcode128->direction); + dbprintf(2, " dir=%x [valid start]\n", dcode128->direction); return(0); } else if((c < 0) || ((dcode128->character >= BUFFER_MIN) && size_buf(dcode, dcode128->character + 1))) { - dprintf(1, (c < 0) ? " [aborted]\n" : " [overflow]\n"); + dbprintf(1, (c < 0) ? " [aborted]\n" : " [overflow]\n"); if(dcode128->character > 1) release_lock(dcode, ZBAR_CODE128); dcode128->character = -1; @@ -513,7 +513,7 @@ zbar_symbol_type_t _zbar_decode_code128 (zbar_decoder_t *dcode) dw = dcode128->s6 - dcode128->width; dw *= 4; if(dw > dcode128->width) { - dprintf(1, " [width var]\n"); + dbprintf(1, " [width var]\n"); if(dcode128->character > 1) release_lock(dcode, ZBAR_CODE128); dcode128->character = -1; @@ -549,17 +549,17 @@ zbar_symbol_type_t _zbar_decode_code128 (zbar_decoder_t *dcode) else if(dcode128->character < CFG(*dcode128, ZBAR_CFG_MIN_LEN) || (CFG(*dcode128, ZBAR_CFG_MAX_LEN) > 0 && dcode128->character > CFG(*dcode128, ZBAR_CFG_MAX_LEN))) { - dprintf(2, " [invalid len]\n"); + dbprintf(2, " [invalid len]\n"); sym = ZBAR_NONE; } else - dprintf(2, " [valid end]\n"); + dbprintf(2, " [valid end]\n"); dcode128->character = -1; if(!sym) release_lock(dcode, ZBAR_CODE128); return(sym); } - dprintf(2, "\n"); + dbprintf(2, "\n"); return(0); } diff --git a/zbar/decoder/code39.c b/zbar/decoder/code39.c index bceeba6..9cbaec9 100644 --- a/zbar/decoder/code39.c +++ b/zbar/decoder/code39.c @@ -136,10 +136,10 @@ static inline unsigned char code39_decode1 (unsigned char enc, enc <<= 1; if(E > 6) { enc |= 1; - dprintf(2, "1"); + dbprintf(2, "1"); } else - dprintf(2, "0"); + dbprintf(2, "0"); return(enc); } @@ -180,7 +180,7 @@ static inline signed char code39_decode9 (zbar_decoder_t *dcode) zassert(idx < 0x2c, -1, " idx=%x enc=%x s9=%x\n", idx, enc, dcode39->s9); const char39_t *c = &code39_encodings[idx]; - dprintf(2, " i=%02x chk=%02x c=%02x/%02x", idx, c->chk, c->fwd, c->rev); + dbprintf(2, " i=%02x chk=%02x c=%02x/%02x", idx, c->chk, c->fwd, c->rev); if(enc != c->chk) return(-1); @@ -191,11 +191,11 @@ static inline signed char code39_decode9 (zbar_decoder_t *dcode) static inline signed char code39_decode_start (zbar_decoder_t *dcode) { code39_decoder_t *dcode39 = &dcode->code39; - dprintf(2, " s=%d ", dcode39->s9); + dbprintf(2, " s=%d ", dcode39->s9); signed char c = code39_decode9(dcode); if(c != 0x19 && c != 0x2b) { - dprintf(2, "\n"); + dbprintf(2, "\n"); return(ZBAR_NONE); } dcode39->direction ^= (c == 0x19); @@ -203,13 +203,13 @@ static inline signed char code39_decode_start (zbar_decoder_t *dcode) /* check leading quiet zone - spec is 10x */ unsigned quiet = get_width(dcode, 9); if(quiet && quiet < dcode39->s9 / 2) { - dprintf(2, " [invalid quiet]\n"); + dbprintf(2, " [invalid quiet]\n"); return(ZBAR_NONE); } dcode39->element = 9; dcode39->character = 0; - dprintf(1, " dir=%x [valid start]\n", dcode39->direction); + dbprintf(1, " dir=%x [valid start]\n", dcode39->direction); return(ZBAR_PARTIAL); } @@ -220,7 +220,7 @@ static inline void code39_postprocess (zbar_decoder_t *dcode) int i; if(dcode39->direction) { /* reverse buffer */ - dprintf(2, " (rev)"); + dbprintf(2, " (rev)"); for(i = 0; i < dcode39->character / 2; i++) { unsigned j = dcode39->character - 1 - i; char code = dcode->buf[i]; @@ -258,16 +258,16 @@ zbar_symbol_type_t _zbar_decode_code39 (zbar_decoder_t *dcode) if(dcode39->character < 0) { if(get_color(dcode) != ZBAR_BAR) return(ZBAR_NONE); - dprintf(2, " code39:"); + dbprintf(2, " code39:"); return(code39_decode_start(dcode)); } if(++dcode39->element < 9) return(ZBAR_NONE); - dprintf(2, " code39[%c%02d+%x]", - (dcode39->direction) ? '<' : '>', - dcode39->character, dcode39->element); + dbprintf(2, " code39[%c%02d+%x]", + (dcode39->direction) ? '<' : '>', + dcode39->character, dcode39->element); if(dcode39->element == 10) { unsigned space = get_width(dcode, 0); @@ -279,19 +279,19 @@ zbar_symbol_type_t _zbar_decode_code39 (zbar_decoder_t *dcode) /* trailing quiet zone check */ if(space && space < dcode39->width / 2) { - dprintf(2, " [invalid qz]\n"); + dbprintf(2, " [invalid qz]\n"); sym = ZBAR_NONE; } else if(dcode39->character < CFG(*dcode39, ZBAR_CFG_MIN_LEN) || (CFG(*dcode39, ZBAR_CFG_MAX_LEN) > 0 && dcode39->character > CFG(*dcode39, ZBAR_CFG_MAX_LEN))) { - dprintf(2, " [invalid len]\n"); + dbprintf(2, " [invalid len]\n"); sym = ZBAR_NONE; } else { /* FIXME checksum (needs config enable) */ code39_postprocess(dcode); - dprintf(2, " [valid end]\n"); + dbprintf(2, " [valid end]\n"); } dcode39->character = -1; if(!sym) @@ -300,19 +300,19 @@ zbar_symbol_type_t _zbar_decode_code39 (zbar_decoder_t *dcode) } if(space > dcode39->width / 2) { /* inter-character space check failure */ - dprintf(2, " ics>%d [invalid ics]", dcode39->width); + dbprintf(2, " ics>%d [invalid ics]", dcode39->width); if(dcode39->character) release_lock(dcode, ZBAR_CODE39); dcode39->character = -1; } dcode39->element = 0; - dprintf(2, "\n"); + dbprintf(2, "\n"); return(ZBAR_NONE); } - dprintf(2, " s=%d ", dcode39->s9); + dbprintf(2, " s=%d ", dcode39->s9); if(!check_width(dcode39->width, dcode39->s9)) { - dprintf(2, " [width]\n"); + dbprintf(2, " [width]\n"); if(dcode39->character) release_lock(dcode, ZBAR_CODE39); dcode39->character = -1; @@ -320,7 +320,7 @@ zbar_symbol_type_t _zbar_decode_code39 (zbar_decoder_t *dcode) } signed char c = code39_decode9(dcode); - dprintf(2, " c=%d", c); + dbprintf(2, " c=%d", c); /* lock shared resources */ if(!dcode39->character && acquire_lock(dcode, ZBAR_CODE39)) { @@ -331,14 +331,14 @@ zbar_symbol_type_t _zbar_decode_code39 (zbar_decoder_t *dcode) if(c < 0 || ((dcode39->character >= BUFFER_MIN) && size_buf(dcode, dcode39->character + 1))) { - dprintf(1, (c < 0) ? " [aborted]\n" : " [overflow]\n"); + dbprintf(1, (c < 0) ? " [aborted]\n" : " [overflow]\n"); release_lock(dcode, ZBAR_CODE39); dcode39->character = -1; return(ZBAR_NONE); } else { zassert(c < 0x2c, ZBAR_NONE, "c=%02x s9=%x\n", c, dcode39->s9); - dprintf(2, "\n"); + dbprintf(2, "\n"); } dcode->buf[dcode39->character++] = c; diff --git a/zbar/decoder/code93.c b/zbar/decoder/code93.c index 6d5dee0..23d79c5 100644 --- a/zbar/decoder/code93.c +++ b/zbar/decoder/code93.c @@ -61,7 +61,7 @@ encode6 (zbar_decoder_t *dcode) unsigned s = dcode->s6; int sig = 0, i; - dprintf(2, " s=%d ", s); + dbprintf(2, " s=%d ", s); if(s < 9) return(-1); @@ -70,9 +70,9 @@ encode6 (zbar_decoder_t *dcode) if(c > 3) return(-1); sig = (sig << 2) | c; - dprintf(2, "%d", c); + dbprintf(2, "%d", c); } - dprintf(2, " sig=%03x", sig); + dbprintf(2, " sig=%03x", sig); return(sig); } @@ -81,14 +81,14 @@ static inline int validate_sig (int sig) { int i, sum = 0, emin = 0, sig0 = 0, sig1 = 0; - dprintf(3, " sum=0"); + dbprintf(3, " sum=0"); for(i = 3; --i >= 0; ) { int e = sig & 3; sig >>= 2; sum = e - sum; sig1 <<= 4; sig1 += sum; - dprintf(3, "%d", sum); + dbprintf(3, "%d", sum); if(!i) break; @@ -99,16 +99,16 @@ validate_sig (int sig) if(emin > sum) emin = sum; sig0 += sum; - dprintf(3, "%d", sum); + dbprintf(3, "%d", sum); } - dprintf(3, " emin=%d sig=%03x/%03x", emin, sig1 & 0xfff, sig0 & 0xfff); + dbprintf(3, " emin=%d sig=%03x/%03x", emin, sig1 & 0xfff, sig0 & 0xfff); emin = emin + (emin << 4) + (emin << 8); sig0 -= emin; sig1 += emin; - dprintf(3, "=%03x/%03x", sig1 & 0xfff, sig0 & 0xfff); + dbprintf(3, "=%03x/%03x", sig1 & 0xfff, sig0 & 0xfff); return((sig0 | sig1) & 0x888); } @@ -137,7 +137,7 @@ decode6 (zbar_decoder_t *dcode) _zbar_decoder_buf_dump(dcode->buf, dcode->code93.character)); c = (g0 + g1) & 0x3f; - dprintf(2, " g0=%x g1=%x c=%02x", g0, g1, c); + dbprintf(2, " g0=%x g1=%x c=%02x", g0, g1, c); return(c); } @@ -148,7 +148,7 @@ decode_start (zbar_decoder_t *dcode) unsigned dir, qz, s = dcode->s6; int c; - dprintf(2, " code93:"); + dbprintf(2, " code93:"); c = encode6(dcode); if(c < 0 || (c != 0x00f && c != 0x0f0)) return(ZBAR_NONE); @@ -163,7 +163,7 @@ decode_start (zbar_decoder_t *dcode) qz = get_width(dcode, 7); if(qz && qz < (s * 3) / 4) { - dprintf(2, " [invalid qz %d]", qz); + dbprintf(2, " [invalid qz %d]", qz); return(ZBAR_NONE); } @@ -173,7 +173,7 @@ decode_start (zbar_decoder_t *dcode) dcode93->character = 0; dcode93->width = s; - dprintf(2, " dir=%x [valid start]", dir); + dbprintf(2, " dir=%x [valid start]", dir); return(ZBAR_PARTIAL); } @@ -186,7 +186,7 @@ decode_abort (zbar_decoder_t *dcode, release_lock(dcode, ZBAR_CODE93); dcode93->character = -1; if(reason) - dprintf(1, " [%s]\n", reason); + dbprintf(1, " [%s]\n", reason); return(ZBAR_NONE); } @@ -252,14 +252,14 @@ validate_checksums (zbar_decoder_t *dcode) } d = dcode->buf[(dcode93->direction) ? 1 : n - 2]; - dprintf(2, " C=%02x?=%02x", d, sum_c); + dbprintf(2, " C=%02x?=%02x", d, sum_c); if(d != sum_c) return(1); acc_k = plusmod47(acc_k, sum_c); sum_k = plusmod47(sum_k, acc_k); d = dcode->buf[(dcode93->direction) ? 0 : n - 1]; - dprintf(2, " K=%02x?=%02x", d, sum_k); + dbprintf(2, " K=%02x?=%02x", d, sum_k); if(d != sum_k) return(1); @@ -276,11 +276,11 @@ postprocess (zbar_decoder_t *dcode) static const unsigned char code93_s2[] = "\x1b\x1c\x1d\x1e\x1f;<=>?[\\]^_{|}~\x7f\x00\x40`\x7f\x7f\x7f"; - dprintf(2, "\n postproc len=%d", n); + dbprintf(2, "\n postproc len=%d", n); dcode->direction = 1 - 2 * dcode93->direction; if(dcode93->direction) { /* reverse buffer */ - dprintf(2, " (rev)"); + dbprintf(2, " (rev)"); for(i = 0; i < n / 2; i++) { unsigned j = n - 1 - i; unsigned char d = dcode->buf[i]; @@ -335,7 +335,7 @@ _zbar_decode_code93 (zbar_decoder_t *dcode) if(get_color(dcode) != ZBAR_BAR) return(ZBAR_NONE); sym = decode_start(dcode); - dprintf(2, "\n"); + dbprintf(2, "\n"); return(sym); } @@ -347,9 +347,9 @@ _zbar_decode_code93 (zbar_decoder_t *dcode) dcode93->element = 0; - dprintf(2, " code93[%c%02d+%x]:", - (dcode93->direction) ? '<' : '>', - dcode93->character, dcode93->element); + dbprintf(2, " code93[%c%02d+%x]:", + (dcode93->direction) ? '<' : '>', + dcode93->character, dcode93->element); if(check_width(dcode->s6, dcode93->width)) return(decode_abort(dcode, "width var")); @@ -366,9 +366,9 @@ _zbar_decode_code93 (zbar_decoder_t *dcode) if(postprocess(dcode)) return(decode_abort(dcode, "invalid encoding")); - dprintf(2, " [valid end]\n"); - dprintf(3, " %s\n", - _zbar_decoder_buf_dump(dcode->buf, dcode93->character)); + dbprintf(2, " [valid end]\n"); + dbprintf(3, " %s\n", + _zbar_decoder_buf_dump(dcode->buf, dcode93->character)); dcode93->character = -1; return(ZBAR_CODE93); @@ -393,6 +393,6 @@ _zbar_decode_code93 (zbar_decoder_t *dcode) dcode->buf[dcode93->character] = c; dcode93->character++; - dprintf(2, "\n"); + dbprintf(2, "\n"); return(ZBAR_NONE); } diff --git a/zbar/decoder/databar.c b/zbar/decoder/databar.c index 9f4bef6..da472b4 100644 --- a/zbar/decoder/databar.c +++ b/zbar/decoder/databar.c @@ -126,7 +126,7 @@ decode10 (unsigned char *buf, d = (d << 12) | (*(data++) & 0xfff); \ i += 12; \ len--; \ - dprintf(2, " %03lx", d & 0xfff); \ + dbprintf(2, " %03lx", d & 0xfff); \ } #define PUSH_CHAR(c) \ @@ -151,7 +151,7 @@ databar_postprocess_exp (zbar_decoder_t *dcode, /* grok encodation method */ d = *(data++); - dprintf(2, "\n len=%d %03lx", len, d & 0xfff); + dbprintf(2, "\n len=%d %03lx", len, d & 0xfff); n = (d >> 4) & 0x7f; if(n >= 0x40) { i = 10; @@ -178,7 +178,7 @@ databar_postprocess_exp (zbar_decoder_t *dcode, enc = 0; buflen = VAR_MAX(len, 9 - 2) + 2; } - dprintf(2, " buflen=%d enc=%d", buflen, enc); + dbprintf(2, " buflen=%d enc=%d", buflen, enc); zassert(buflen > 2, -1, "buflen=%d\n", buflen); if(enc < 4) { @@ -191,7 +191,7 @@ databar_postprocess_exp (zbar_decoder_t *dcode, return(-1); } len -= 2; - dprintf(2, " [%d+%d]", i, len); + dbprintf(2, " [%d+%d]", i, len); if(size_buf(dcode, buflen)) return(-1); @@ -263,7 +263,7 @@ databar_postprocess_exp (zbar_decoder_t *dcode, FEED_BITS(15); i -= 15; n = (d >> i) & 0x7fff; - dprintf(2, " v=%d", n); + dbprintf(2, " v=%d", n); PUSH_CHAR4('3', '2', '0', (n >= 10000) ? '3' : '2' ); if(n >= 10000) n -= 10000; @@ -277,7 +277,7 @@ databar_postprocess_exp (zbar_decoder_t *dcode, FEED_BITS(20); i -= 20; n = (d >> i) & 0xfffff; - dprintf(2, " [%d+%d] %d", i, len, n); + dbprintf(2, " [%d+%d] %d", i, len, n); if(n >= 1000000) return(-1); decode10(buf, n, 6); @@ -313,7 +313,7 @@ databar_postprocess_exp (zbar_decoder_t *dcode, int scheme = SCH_NUM; while(i > 0 || len > 0) { FEED_BITS(8); - dprintf(2, " [%d+%d]", i, len); + dbprintf(2, " [%d+%d]", i, len); if(scheme == SCH_NUM) { int n1; @@ -322,7 +322,7 @@ databar_postprocess_exp (zbar_decoder_t *dcode, break; if(!((d >> i) & 0xf)) { scheme = SCH_ALNUM; - dprintf(2, ">A"); + dbprintf(2, ">A"); continue; } if(!len && i < 3) { @@ -338,7 +338,7 @@ databar_postprocess_exp (zbar_decoder_t *dcode, n = ((d >> i) & 0x7f) - 8; n1 = n % 11; n = n / 11; - dprintf(2, "N%d%d", n, n1); + dbprintf(2, "N%d%d", n, n1); *(buf++) = (n < 10) ? '0' + n : GS; *(buf++) = (n1 < 10) ? '0' + n1 : GS; } @@ -357,7 +357,7 @@ databar_postprocess_exp (zbar_decoder_t *dcode, n = (d >> i) & 0x1f; if(n == 0x04) { scheme ^= 0x3; - dprintf(2, ">%d", scheme); + dbprintf(2, ">%d", scheme); } else if(n == 0x0f) c = GS; @@ -394,7 +394,7 @@ databar_postprocess_exp (zbar_decoder_t *dcode, if(i < 0) return(-1); n = ((d >> i) & 0x1f); - dprintf(2, "(%02x)", n); + dbprintf(2, "(%02x)", n); if(n < 0xa) c = '!' + n - 8; else if(n < 0x15) @@ -412,7 +412,7 @@ databar_postprocess_exp (zbar_decoder_t *dcode, return(-1); if(c) { - dprintf(2, "%d%c", scheme, c); + dbprintf(2, "%d%c", scheme, c); *(buf++) = c; } } @@ -428,7 +428,7 @@ databar_postprocess_exp (zbar_decoder_t *dcode, dcode->buflen--; } - dprintf(2, "\n %s", _zbar_decoder_buf_dump(dcode->buf, dcode->buflen)); + dbprintf(2, "\n %s", _zbar_decoder_buf_dump(dcode->buf, dcode->buflen)); return(0); } #undef FEED_BITS @@ -450,7 +450,7 @@ databar_postprocess (zbar_decoder_t *dcode, *--buf = '\0'; *--buf = '\0'; - dprintf(2, "\n d={%d,%d,%d,%d}", d[0], d[1], d[2], d[3]); + dbprintf(2, "\n d={%d,%d,%d,%d}", d[0], d[1], d[2], d[3]); unsigned long r = d[0] * 1597 + d[1]; d[1] = r / 10000; r %= 10000; @@ -459,7 +459,7 @@ databar_postprocess (zbar_decoder_t *dcode, r %= 10000; r = r * 1597 + d[3]; d[3] = r / 10000; - dprintf(2, " r=%ld", r); + dbprintf(2, " r=%ld", r); for(i = 4; --i >= 0; ) { c = r % 10; @@ -471,13 +471,13 @@ databar_postprocess (zbar_decoder_t *dcode, r /= 10; } - dprintf(2, " d={%d,%d,%d}", d[1], d[2], d[3]); + dbprintf(2, " d={%d,%d,%d}", d[1], d[2], d[3]); r = d[1] * 2841 + d[2]; d[2] = r / 10000; r %= 10000; r = r * 1597 + d[3]; d[3] = r / 10000; - dprintf(2, " r=%ld", r); + dbprintf(2, " r=%ld", r); for(i = 4; --i >= 0; ) { c = r % 10; @@ -490,7 +490,7 @@ databar_postprocess (zbar_decoder_t *dcode, } r = d[2] * 1597 + d[3]; - dprintf(2, " d={%d,%d} r=%ld", d[2], d[3], r); + dbprintf(2, " d={%d,%d} r=%ld", d[2], d[3], r); for(i = 5; --i >= 0; ) { c = r % 10; @@ -513,7 +513,7 @@ databar_postprocess (zbar_decoder_t *dcode, else dcode->buflen = buf - dcode->buf + 13; - dprintf(2, "\n %s", _zbar_decoder_buf_dump(dcode->buf, 16)); + dbprintf(2, "\n %s", _zbar_decoder_buf_dump(dcode->buf, 16)); } static inline int @@ -547,8 +547,8 @@ merge_segment (databar_decoder_t *db, seg->partial &= s->partial; seg->width = (3 * seg->width + s->width + 2) / 4; s->finder = -1; - dprintf(2, " dup@%d(%d,%d)", - i, cnt, (db->epoch - seg->epoch) & 0xff); + dbprintf(2, " dup@%d(%d,%d)", + i, cnt, (db->epoch - seg->epoch) & 0xff); } else if(s->finder >= 0) { unsigned age = (db->epoch - s->epoch) & 0xff; @@ -587,9 +587,9 @@ match_segment (zbar_decoder_t *dcode, (s1->partial && s1->count < 4) || !check_width(seg->width, s1->width, 14)) continue; - dprintf(2, "\n\t[%d,%d] f=%d(0%xx)/%d(%x%x%x)", - i0, i1, seg->finder, seg->color, - s1->finder, s1->exp, s1->color, s1->side); + dbprintf(2, "\n\t[%d,%d] f=%d(0%xx)/%d(%x%x%x)", + i0, i1, seg->finder, seg->color, + s1->finder, s1->exp, s1->color, s1->side); if(seg->color) chkf = seg->finder + s1->finder * 9; @@ -607,7 +607,7 @@ match_segment (zbar_decoder_t *dcode, else chk = 79 + chkf - chks; - dprintf(2, " chk=(%d,%d) => %d", chkf, chks, chk); + dbprintf(2, " chk=(%d,%d) => %d", chkf, chks, chk); age1 = ((db->epoch - s0->epoch) & 0xff + (db->epoch - s1->epoch) & 0xff); @@ -623,7 +623,7 @@ match_segment (zbar_decoder_t *dcode, age2 = (db->epoch - s2->epoch) & 0xff; age = age1 + age2; cnt = s0->count + s1->count + s2->count; - dprintf(2, " [%d] MATCH cnt=%d age=%d", i2, cnt, age); + dbprintf(2, " [%d] MATCH cnt=%d age=%d", i2, cnt, age); if(maxcnt < cnt || (maxcnt == cnt && maxage > age)) { maxcnt = cnt; @@ -670,7 +670,7 @@ lookup_sequence (databar_segment_t *seg, i = (n + 1) / 2 + 1; n += 4; i = (i * i) / 4; - dprintf(2, " {%d,%d:", i, n); + dbprintf(2, " {%d,%d:", i, n); p = exp_sequences + i; fixed >>= 1; @@ -687,11 +687,11 @@ lookup_sequence (databar_segment_t *seg, if(s == fixed) fixed = -1; s <<= 1; - dprintf(2, "%x", s); + dbprintf(2, "%x", s); seq[i++] = s++; seq[i++] = s; } - dprintf(2, "}"); + dbprintf(2, "}"); seq[n] = -1; return(fixed < 1); } @@ -713,27 +713,27 @@ match_segment_exp (zbar_decoder_t *dcode, bestsegs[0] = segs[0] = seq[1] = -1; seq[0] = 0; - dprintf(2, "\n fixed=%d@%d: ", fixed, ifixed); + dbprintf(2, "\n fixed=%d@%d: ", fixed, ifixed); for(i = csegs, seg = db->segs + csegs - 1; --i >= 0; seg--) { if(seg->exp && seg->finder >= 0 && (!seg->partial || seg->count >= 4)) iseg[i] = IDX(seg); else iseg[i] = -1; - dprintf(2, " %d", iseg[i]); + dbprintf(2, " %d", iseg[i]); } for(i = 0; ; i--) { if(!i) - dprintf(2, "\n "); + dbprintf(2, "\n "); for(; i >= 0 && seq[i] >= 0; i--) { int j; - dprintf(2, " [%d]%d", i, seq[i]); + dbprintf(2, " [%d]%d", i, seq[i]); if(seq[i] == fixed) { seg = db->segs + ifixed; if(segs[i] < 0 && check_width(width, seg->width, 14)) { - dprintf(2, "*"); + dbprintf(2, "*"); j = ifixed; } else @@ -753,16 +753,16 @@ match_segment_exp (zbar_decoder_t *dcode, if(!i) { if(!lookup_sequence(seg, fixed, seq)) { - dprintf(2, "[nf]"); + dbprintf(2, "[nf]"); continue; } width = seg->width; - dprintf(2, " A00@%d", j); + dbprintf(2, " A00@%d", j); } else { width = (width + seg->width) / 2; - dprintf(2, " %c%x%x@%d", - 'A' + seg->finder, seg->color, seg->side, j); + dbprintf(2, " %c%x%x@%d", + 'A' + seg->finder, seg->color, seg->side, j); } segs[i++] = j; segs[i++] = -1; @@ -783,15 +783,15 @@ match_segment_exp (zbar_decoder_t *dcode, unsigned chk0 = data0 % 211; chk %= 211; - dprintf(2, " chk=%d ?= %d", chk, chk0); + dbprintf(2, " chk=%d ?= %d", chk, chk0); if(chk != chk0) continue; - dprintf(2, " cnt=%d age=%d", cnt, age); + dbprintf(2, " cnt=%d age=%d", cnt, age); if(maxcnt > cnt || (maxcnt == cnt && maxage <= age)) continue; - dprintf(2, " !"); + dbprintf(2, " !"); maxcnt = cnt; maxage = age; for(i = 0; segs[i] >= 0; i++) @@ -844,7 +844,7 @@ calc_check (unsigned sig0, if(!(i & 1)) chk %= mod; } - dprintf(2, " chk=%d", chk); + dbprintf(2, " chk=%d", chk); if(side) chk = (chk * (6561 % mod)) % mod; @@ -958,8 +958,8 @@ decode_char (zbar_decoder_t *dcode, n = 16; emin[1] = -n; - dprintf(2, "\n char[%c%d]: n=%d s=%d w=%d sig=", - (dir < 0) ? '>' : '<', off, n, s, seg->width); + dbprintf(2, "\n char[%c%d]: n=%d s=%d w=%d sig=", + (dir < 0) ? '>' : '<', off, n, s, seg->width); if(s < 13 || !check_width(seg->width, s, n)) return(ZBAR_NONE); @@ -967,7 +967,7 @@ decode_char (zbar_decoder_t *dcode, int e = decode_e(pair_width(dcode, off), s, n); if(e < 0) return(ZBAR_NONE); - dprintf(2, "%d", e); + dbprintf(2, "%d", e); sum = e - sum; off += dir; sig1 <<= 4; @@ -980,7 +980,7 @@ decode_char (zbar_decoder_t *dcode, e = decode_e(pair_width(dcode, off), s, n); if(e < 0) return(ZBAR_NONE); - dprintf(2, "%d", e); + dbprintf(2, "%d", e); sum = e - sum; off += dir; sig0 <<= 4; @@ -996,7 +996,7 @@ decode_char (zbar_decoder_t *dcode, sig0 -= diff; sig1 += diff; - dprintf(2, " emin=%d,%d el=%04x/%04x", emin[0], emin[1], sig0, sig1); + dbprintf(2, " emin=%d,%d el=%04x/%04x", emin[0], emin[1], sig0, sig1); unsigned sum0 = sig0 + (sig0 >> 8); unsigned sum1 = sig1 + (sig1 >> 8); @@ -1005,15 +1005,15 @@ decode_char (zbar_decoder_t *dcode, sum0 &= 0xf; sum1 &= 0xf; - dprintf(2, " sum=%d/%d", sum0, sum1); + dbprintf(2, " sum=%d/%d", sum0, sum1); if(sum0 + sum1 + 8 != n) { - dprintf(2, " [SUM]"); + dbprintf(2, " [SUM]"); return(ZBAR_NONE); } if(((sum0 ^ (n >> 1)) | (sum1 ^ (n >> 1) ^ n)) & 1) { - dprintf(2, " [ODD]"); + dbprintf(2, " [ODD]"); return(ZBAR_NONE); } @@ -1022,16 +1022,16 @@ decode_char (zbar_decoder_t *dcode, "n=%d sum=%d/%d sig=%04x/%04x g=%d", n, sum0, sum1, sig0, sig1, i); struct group_s *g = groups + i; - dprintf(2, "\n g=%d(%d,%d,%d/%d)", - i, g->sum, g->wmax, g->todd, g->teven); + dbprintf(2, "\n g=%d(%d,%d,%d/%d)", + i, g->sum, g->wmax, g->todd, g->teven); int vodd = calc_value4(sig0 + 0x1111, sum0 + 4, g->wmax, ~n & 1); - dprintf(2, " v=%d", vodd); + dbprintf(2, " v=%d", vodd); if(vodd < 0 || vodd > g->todd) return(ZBAR_NONE); int veven = calc_value4(sig1 + 0x1111, sum1 + 4, 9 - g->wmax, n & 1); - dprintf(2, "/%d", veven); + dbprintf(2, "/%d", veven); if(veven < 0 || veven > g->teven) return(ZBAR_NONE); @@ -1041,7 +1041,7 @@ decode_char (zbar_decoder_t *dcode, else v += veven + vodd * g->teven; - dprintf(2, " f=%d(%x%x%x)", seg->finder, seg->exp, seg->color, seg->side); + dbprintf(2, " f=%d(%x%x%x)", seg->finder, seg->exp, seg->color, seg->side); unsigned chk = 0; if(seg->exp) { @@ -1067,7 +1067,7 @@ decode_char (zbar_decoder_t *dcode, if(seg->color) chk = (chk * 16) % 79; } - dprintf(2, " => %d val=%d", chk, v); + dbprintf(2, " => %d val=%d", chk, v); seg->check = chk; seg->data = v; @@ -1090,14 +1090,14 @@ alloc_segment (databar_decoder_t *db) databar_segment_t *seg = db->segs + i; unsigned age; if(seg->finder < 0) { - dprintf(2, " free@%d", i); + dbprintf(2, " free@%d", i); return(i); } age = (db->epoch - seg->epoch) & 0xff; if(age >= 128 && seg->count < 2) { seg->finder = -1; - dprintf(2, " stale@%d (%d - %d = %d)", - i, db->epoch, seg->epoch, age); + dbprintf(2, " stale@%d (%d - %d = %d)", + i, db->epoch, seg->epoch, age); return(i); } @@ -1110,12 +1110,12 @@ alloc_segment (databar_decoder_t *db) if(maxage < age) { maxage = age; old = i; - dprintf(2, " old@%d(%u)", i, age); + dbprintf(2, " old@%d(%u)", i, age); } } if(csegs < DATABAR_MAX_SEGMENTS) { - dprintf(2, " new@%d", i); + dbprintf(2, " new@%d", i); i = csegs; csegs *= 2; if(csegs > DATABAR_MAX_SEGMENTS) @@ -1153,7 +1153,7 @@ decode_finder (zbar_decoder_t *dcode) unsigned e2 = pair_width(dcode, 3); unsigned e1, e3, s, finder, dir; int sig, iseg; - dprintf(2, " databar: e0=%d e2=%d", e0, e2); + dbprintf(2, " databar: e0=%d e2=%d", e0, e2); if(e0 < e2) { unsigned e = e2 * 4; if(e < 15 * e0 || e > 34 * e0) @@ -1172,13 +1172,13 @@ decode_finder (zbar_decoder_t *dcode) e1 = pair_width(dcode, 2); s = e1 + e3; - dprintf(2, " e1=%d e3=%d dir=%d s=%d", e1, e3, dir, s); + dbprintf(2, " e1=%d e3=%d dir=%d s=%d", e1, e3, dir, s); if(s < 12) return(ZBAR_NONE); sig = ((decode_e(e3, s, 14) << 8) | (decode_e(e2, s, 14) << 4) | decode_e(e1, s, 14)); - dprintf(2, " sig=%04x", sig & 0xfff); + dbprintf(2, " sig=%04x", sig & 0xfff); if(sig < 0 || ((sig >> 4) & 0xf) < 8 || ((sig >> 4) & 0xf) > 10 || @@ -1189,7 +1189,7 @@ decode_finder (zbar_decoder_t *dcode) finder = (finder_hash[(sig - (sig >> 5)) & 0x1f] + finder_hash[(sig >> 1) & 0x1f]) & 0x1f; - dprintf(2, " finder=%d", finder); + dbprintf(2, " finder=%d", finder); if(finder == 0x1f || !TEST_CFG((finder < 9) ? db->config : db->config_exp, ZBAR_CFG_ENABLE)) return(ZBAR_NONE); @@ -1232,7 +1232,7 @@ _zbar_decode_databar (zbar_decoder_t *dcode) int iseg, i = dcode->idx & 0xf; sym = decode_finder(dcode); - dprintf(2, "\n"); + dbprintf(2, "\n"); iseg = db->chars[i]; if(iseg < 0) @@ -1240,8 +1240,8 @@ _zbar_decode_databar (zbar_decoder_t *dcode) db->chars[i] = -1; seg = db->segs + iseg; - dprintf(2, " databar: i=%d part=%d f=%d(%x%x%x)", - iseg, seg->partial, seg->finder, seg->exp, seg->color, seg->side); + dbprintf(2, " databar: i=%d part=%d f=%d(%x%x%x)", + iseg, seg->partial, seg->finder, seg->exp, seg->color, seg->side); zassert(seg->finder >= 0, ZBAR_NONE, "i=%d f=%d(%x%x%x) part=%x\n", iseg, seg->finder, seg->exp, seg->color, seg->side, seg->partial); @@ -1271,7 +1271,7 @@ _zbar_decode_databar (zbar_decoder_t *dcode) } else db->epoch++; - dprintf(2, "\n"); + dbprintf(2, "\n"); return(sym); } diff --git a/zbar/decoder/ean.c b/zbar/decoder/ean.c index 9c671a6..270c48b 100644 --- a/zbar/decoder/ean.c +++ b/zbar/decoder/ean.c @@ -132,22 +132,22 @@ static inline signed char aux_end (zbar_decoder_t *dcode, /* check quiet zone */ unsigned qz = get_width(dcode, 0); if(!fwd && qz && qz <= s * 3 / 4) { - dprintf(2, " [invalid quiet]"); + dbprintf(2, " [invalid quiet]"); return(-1); } - dprintf(2, " ("); + dbprintf(2, " ("); code = 0; for(i = 1 - fwd; i < 3 + fwd; i++) { unsigned e = get_width(dcode, i) + get_width(dcode, i + 1); - dprintf(2, " %d", e); + dbprintf(2, " %d", e); code = (code << 2) | decode_e(e, s, 7); if(code < 0) { - dprintf(2, " [invalid end guard]"); + dbprintf(2, " [invalid end guard]"); return(-1); } } - dprintf(2, ") s=%d aux=%x", s, code); + dbprintf(2, ") s=%d aux=%x", s, code); return(code); } @@ -163,7 +163,7 @@ static inline signed char aux_start (zbar_decoder_t *dcode) return(-1); if(decode_e(e2, dcode->ean.s4, 7)) { - dprintf(2, " [invalid any]"); + dbprintf(2, " [invalid any]"); return(-1); } @@ -175,15 +175,15 @@ static inline signed char aux_start (zbar_decoder_t *dcode) unsigned qz = get_width(dcode, 7); if(!qz || qz > dcode->ean.s4 * 3 / 4) { if(!E1) { - dprintf(2, " [valid normal]"); + dbprintf(2, " [valid normal]"); return(0); /* normal symbol start */ } else if(E1 == 1) { - dprintf(2, " [valid add-on]"); + dbprintf(2, " [valid add-on]"); return(STATE_ADDON); /* add-on symbol start */ } } - dprintf(2, " [invalid start]"); + dbprintf(2, " [invalid start]"); return(-1); } @@ -193,11 +193,11 @@ static inline signed char aux_start (zbar_decoder_t *dcode) unsigned e4 = get_width(dcode, 7) + get_width(dcode, 8); if(!decode_e(e3, dcode->ean.s4, 7) && !decode_e(e4, dcode->ean.s4, 7)) { - dprintf(2, " [valid center]"); + dbprintf(2, " [valid center]"); return(0); /* start after center guard */ } } - dprintf(2, " [invalid center]"); + dbprintf(2, " [invalid center]"); return(-1); } @@ -219,7 +219,7 @@ static inline signed char decode4 (zbar_decoder_t *dcode) ? get_width(dcode, 0) + get_width(dcode, 1) : get_width(dcode, 2) + get_width(dcode, 3)); unsigned e2 = get_width(dcode, 1) + get_width(dcode, 2); - dprintf(2, "\n e1=%d e2=%d", e1, e2); + dbprintf(2, "\n e1=%d e2=%d", e1, e2); if(dcode->ean.s4 < 6) return(-1); @@ -229,7 +229,7 @@ static inline signed char decode4 (zbar_decoder_t *dcode) decode_e(e2, dcode->ean.s4, 7)); if(code < 0) return(-1); - dprintf(2, " code=%x", code); + dbprintf(2, " code=%x", code); /* 4 combinations require additional determinant (D2) E1E2 == 34 (0110) @@ -250,9 +250,9 @@ static inline signed char decode4 (zbar_decoder_t *dcode) alt = d2 > (mid * dcode->ean.s4); if(alt) code = ((code >> 1) & 3) | 0x10; /* compress code space */ - dprintf(2, " (d2=%d(%d) alt=%d)", d2, mid * dcode->ean.s4, alt); + dbprintf(2, " (d2=%d(%d) alt=%d)", d2, mid * dcode->ean.s4, alt); } - dprintf(2, " char=%02x", digits[(unsigned char)code]); + dbprintf(2, " char=%02x", digits[(unsigned char)code]); zassert(code < 0x14, -1, "code=%02x e1=%x e2=%x s4=%x color=%x\n", code, e1, e2, dcode->ean.s4, get_color(dcode)); return(code); @@ -266,13 +266,13 @@ static inline char ean_part_end2 (ean_pass_t *pass) /* calculate "checksum" */ unsigned char chk = ~((pass->raw[1] & 0xf) * 10 + (pass->raw[2] & 0xf)) & 0x3; - dprintf(2, " par=%x chk=%x", par, chk); + dbprintf(2, " par=%x chk=%x", par, chk); if(par != chk) return(ZBAR_NONE); - dprintf(2, "\n"); - dprintf(1, "decode2=%x%x\n", - pass->raw[1] & 0xf, pass->raw[2] & 0xf); + dbprintf(2, "\n"); + dbprintf(1, "decode2=%x%x\n", + pass->raw[1] & 0xf, pass->raw[2] & 0xf); return(ZBAR_EAN2); } @@ -285,7 +285,7 @@ static inline zbar_symbol_type_t ean_part_end4 (ean_pass_t *pass, (pass->raw[3] & 0x10) >> 3 | (pass->raw[4] & 0x10) >> 4); - dprintf(2, " par=%x", par); + dbprintf(2, " par=%x", par); if(par && par != 0xf) /* invalid parity combination */ return(ZBAR_NONE); @@ -301,10 +301,10 @@ static inline zbar_symbol_type_t ean_part_end4 (ean_pass_t *pass, pass->raw[3] = tmp; } - dprintf(2, "\n"); - dprintf(1, "decode4=%x%x%x%x\n", - pass->raw[1] & 0xf, pass->raw[2] & 0xf, - pass->raw[3] & 0xf, pass->raw[4] & 0xf); + dbprintf(2, "\n"); + dbprintf(1, "decode4=%x%x%x%x\n", + pass->raw[1] & 0xf, pass->raw[2] & 0xf, + pass->raw[3] & 0xf, pass->raw[4] & 0xf); if(!par) return(ZBAR_EAN8 | EAN_RIGHT); return(ZBAR_EAN8 | EAN_LEFT); @@ -329,15 +329,15 @@ static inline char ean_part_end5 (ean_pass_t *pass) if(par & 1) parchk >>= 4; parchk &= 0xf; - dprintf(2, " par=%x(%d) chk=%d", par, parchk, chk); + dbprintf(2, " par=%x(%d) chk=%d", par, parchk, chk); if(parchk != chk) return(ZBAR_NONE); - dprintf(2, "\n"); - dprintf(1, "decode5=%x%x%x%x%x\n", - pass->raw[1] & 0xf, pass->raw[2] & 0xf, - pass->raw[3] & 0xf, pass->raw[4] & 0xf, - pass->raw[5] & 0xf); + dbprintf(2, "\n"); + dbprintf(1, "decode5=%x%x%x%x%x\n", + pass->raw[1] & 0xf, pass->raw[2] & 0xf, + pass->raw[3] & 0xf, pass->raw[4] & 0xf, + pass->raw[5] & 0xf); return(ZBAR_EAN5); } @@ -366,7 +366,7 @@ static inline zbar_symbol_type_t ean_part_end7 (ean_decoder_t *ean, if(par & 1) pass->raw[0] >>= 4; pass->raw[0] &= 0xf; - dprintf(2, " par=%02x(%x)", par, pass->raw[0]); + dbprintf(2, " par=%02x(%x)", par, pass->raw[0]); if(pass->raw[0] == 0xf) /* invalid parity combination */ @@ -383,12 +383,12 @@ static inline zbar_symbol_type_t ean_part_end7 (ean_decoder_t *ean, } } - dprintf(2, "\n"); - dprintf(1, "decode=%x%x%x%x%x%x%x(%02x)\n", - pass->raw[0] & 0xf, pass->raw[1] & 0xf, - pass->raw[2] & 0xf, pass->raw[3] & 0xf, - pass->raw[4] & 0xf, pass->raw[5] & 0xf, - pass->raw[6] & 0xf, par); + dbprintf(2, "\n"); + dbprintf(1, "decode=%x%x%x%x%x%x%x(%02x)\n", + pass->raw[0] & 0xf, pass->raw[1] & 0xf, + pass->raw[2] & 0xf, pass->raw[3] & 0xf, + pass->raw[4] & 0xf, pass->raw[5] & 0xf, + pass->raw[6] & 0xf, par); if(TEST_CFG(ean->ean13_config, ZBAR_CFG_ENABLE)) { if(!par) @@ -413,7 +413,7 @@ static inline zbar_symbol_type_t decode_pass (zbar_decoder_t *dcode, if(get_color(dcode) == ZBAR_SPACE) { if(pass->state & STATE_ADDON) { - dprintf(2, " i=%d", idx); + dbprintf(2, " i=%d", idx); if(idx == 0x09 || idx == 0x21) { unsigned qz = get_width(dcode, 0); unsigned s = calc_s(dcode, 1, 4); @@ -430,7 +430,7 @@ static inline zbar_symbol_type_t decode_pass (zbar_decoder_t *dcode, } } if((idx & 7) == 1) { - dprintf(2, " +"); + dbprintf(2, " +"); pass->state += 2; idx += 2; } @@ -438,7 +438,7 @@ static inline zbar_symbol_type_t decode_pass (zbar_decoder_t *dcode, else if((idx == 0x10 || idx == 0x11) && TEST_CFG(dcode->ean.ean8_config, ZBAR_CFG_ENABLE) && !aux_end(dcode, fwd)) { - dprintf(2, " fwd=%x", fwd); + dbprintf(2, " fwd=%x", fwd); zbar_symbol_type_t part = ean_part_end4(pass, fwd); if(part) dcode->ean.direction = (pass->state & STATE_REV) != 0; @@ -447,7 +447,7 @@ static inline zbar_symbol_type_t decode_pass (zbar_decoder_t *dcode, } else if((idx == 0x18 || idx == 0x19)) { zbar_symbol_type_t part = ZBAR_NONE; - dprintf(2, " fwd=%x", fwd); + dbprintf(2, " fwd=%x", fwd); if(!aux_end(dcode, fwd) && pass->raw[5] != 0xff) part = ean_part_end7(&dcode->ean, pass, fwd); if(part) @@ -482,7 +482,7 @@ static inline zbar_symbol_type_t decode_pass (zbar_decoder_t *dcode, if(w) code = decode4(dcode); else - dprintf(2, " [bad width]"); + dbprintf(2, " [bad width]"); if((code < 0 && idx != 0x10) || (idx > 0 && (pass->state & STATE_ADDON) && aux_mid(dcode))) @@ -490,14 +490,14 @@ static inline zbar_symbol_type_t decode_pass (zbar_decoder_t *dcode, else if(code < 0) pass->raw[5] = 0xff; else { - dprintf(2, "\n raw[%x]=%02x =>", idx >> 2, - digits[(unsigned char)code]); + dbprintf(2, "\n raw[%x]=%02x =>", idx >> 2, + digits[(unsigned char)code]); pass->raw[(idx >> 2) + 1] = digits[(unsigned char)code]; - dprintf(2, " raw=%d%d%d%d%d%d%d", - pass->raw[0] & 0xf, pass->raw[1] & 0xf, - pass->raw[2] & 0xf, pass->raw[3] & 0xf, - pass->raw[4] & 0xf, pass->raw[5] & 0xf, - pass->raw[6] & 0xf); + dbprintf(2, " raw=%d%d%d%d%d%d%d", + pass->raw[0] & 0xf, pass->raw[1] & 0xf, + pass->raw[2] & 0xf, pass->raw[3] & 0xf, + pass->raw[4] & 0xf, pass->raw[5] & 0xf, + pass->raw[6] & 0xf); } } return(0); @@ -529,8 +529,8 @@ static inline signed char ean_verify_checksum (ean_decoder_t *ean, zassert(d < 10, -1, "n=%x d=%x chk=%x %s\n", n, d, chk, _zbar_decoder_buf_dump((void*)ean->buf, 18)); if(chk != d) { - dprintf(1, "\nchecksum mismatch %d != %d (%s)\n", - chk, d, dsprintbuf(ean)); + dbprintf(1, "\nchecksum mismatch %d != %d (%s)\n", + chk, d, dsprintbuf(ean)); return(-1); } return(0); @@ -584,19 +584,19 @@ static inline zbar_symbol_type_t integrate_partial (ean_decoder_t *ean, { /* copy raw data into holding buffer */ /* if same partial is not consistent, reset others */ - dprintf(2, " integrate part=%x (%s)", part, dsprintbuf(ean)); + dbprintf(2, " integrate part=%x (%s)", part, dsprintbuf(ean)); signed char i, j; if((ean->left && ((part & ZBAR_SYMBOL) != ean->left)) || (ean->right && ((part & ZBAR_SYMBOL) != ean->right))) { /* partial mismatch - reset collected parts */ - dprintf(2, " rst(type %x %x)", ean->left, ean->right); + dbprintf(2, " rst(type %x %x)", ean->left, ean->right); ean->left = ean->right = ZBAR_NONE; } if((ean->left || ean->right) && !check_width(ean->width, pass->width)) { - dprintf(2, " rst(width %d)", pass->width); + dbprintf(2, " rst(width %d)", pass->width); ean->left = ean->right = ZBAR_NONE; } @@ -608,7 +608,7 @@ static inline zbar_symbol_type_t integrate_partial (ean_decoder_t *ean, unsigned char digit = pass->raw[i] & 0xf; if(ean->right && ean->buf[j] != digit) { /* partial mismatch - reset collected parts */ - dprintf(2, " rst(right)"); + dbprintf(2, " rst(right)"); ean->left = ean->right = ZBAR_NONE; } ean->buf[j] = digit; @@ -622,7 +622,7 @@ static inline zbar_symbol_type_t integrate_partial (ean_decoder_t *ean, unsigned char digit = pass->raw[i] & 0xf; if(ean->left && ean->buf[j] != digit) { /* partial mismatch - reset collected parts */ - dprintf(2, " rst(left)"); + dbprintf(2, " rst(left)"); ean->left = ean->right = ZBAR_NONE; } ean->buf[j] = digit; @@ -687,8 +687,8 @@ static inline zbar_symbol_type_t integrate_partial (ean_decoder_t *ean, part = ZBAR_NONE; } - dprintf(2, " dir=%d %x/%x=%x", - ean->direction, ean->left, ean->right, part); + dbprintf(2, " dir=%d %x/%x=%x", + ean->direction, ean->left, ean->right, part); return(part); } @@ -728,7 +728,7 @@ static inline void postprocess (zbar_decoder_t *dcode, dcode->buf[j] = '\0'; dcode->direction = 1 - 2 * ean->direction; dcode->modifiers = 0; - dprintf(2, " base=%d j=%d (%s)", base, j, dcode->buf); + dbprintf(2, " base=%d j=%d (%s)", base, j, dcode->buf); } zbar_symbol_type_t _zbar_decode_ean (zbar_decoder_t *dcode) @@ -748,28 +748,28 @@ zbar_symbol_type_t _zbar_decode_ean (zbar_decoder_t *dcode) i == pass_idx) { zbar_symbol_type_t part; - dprintf(2, " ean[%x/%x]: idx=%x st=%d s=%d", - i, pass_idx, dcode->idx, pass->state, dcode->ean.s4); + dbprintf(2, " ean[%x/%x]: idx=%x st=%d s=%d", + i, pass_idx, dcode->idx, pass->state, dcode->ean.s4); part = decode_pass(dcode, pass); if(part) { /* update accumulated data from new partial decode */ sym = integrate_partial(&dcode->ean, pass, part); if(sym) { /* this pass valid => _reset_ all passes */ - dprintf(2, " sym=%x", sym); + dbprintf(2, " sym=%x", sym); dcode->ean.pass[0].state = dcode->ean.pass[1].state = -1; dcode->ean.pass[2].state = dcode->ean.pass[3].state = -1; if(sym > ZBAR_PARTIAL) { if(!acquire_lock(dcode, sym)) postprocess(dcode, sym); else { - dprintf(1, " [locked %d]", dcode->lock); + dbprintf(1, " [locked %d]", dcode->lock); sym = ZBAR_PARTIAL; } } } } - dprintf(2, "\n"); + dbprintf(2, "\n"); } } return(sym); diff --git a/zbar/decoder/i25.c b/zbar/decoder/i25.c index 58e66d5..a93f3bf 100644 --- a/zbar/decoder/i25.c +++ b/zbar/decoder/i25.c @@ -49,7 +49,7 @@ static inline unsigned char i25_decode10 (zbar_decoder_t *dcode, unsigned char offset) { i25_decoder_t *dcode25 = &dcode->i25; - dprintf(2, " s=%d", dcode25->s10); + dbprintf(2, " s=%d", dcode25->s10); if(dcode25->s10 < 10) return(0xff); @@ -65,11 +65,11 @@ static inline unsigned char i25_decode10 (zbar_decoder_t *dcode, par++; } - dprintf(2, " enc=%02x par=%x", enc, par); + dbprintf(2, " enc=%02x par=%x", enc, par); /* parity check */ if(par != 2) { - dprintf(2, " [bad parity]"); + dbprintf(2, " [bad parity]"); return(0xff); } @@ -79,12 +79,12 @@ static inline unsigned char i25_decode10 (zbar_decoder_t *dcode, if(enc == 12) enc = 0; else if(--enc > 9) { - dprintf(2, " [invalid encoding]"); + dbprintf(2, " [invalid encoding]"); return(0xff); } } - dprintf(2, " => %x", enc); + dbprintf(2, " => %x", enc); return(enc); } @@ -103,7 +103,7 @@ static inline signed char i25_decode_start (zbar_decoder_t *dcode) if((get_color(dcode) == ZBAR_BAR) ? enc != 4 : (enc = i25_decode1(enc, get_width(dcode, i++), dcode25->s10))) { - dprintf(4, " i25: s=%d enc=%x [invalid]\n", dcode25->s10, enc); + dbprintf(4, " i25: s=%d enc=%x [invalid]\n", dcode25->s10, enc); return(ZBAR_NONE); } @@ -113,8 +113,8 @@ static inline signed char i25_decode_start (zbar_decoder_t *dcode) */ unsigned quiet = get_width(dcode, i); if(quiet && quiet < dcode25->s10 * 3 / 8) { - dprintf(3, " i25: s=%d enc=%x q=%d [invalid qz]\n", - dcode25->s10, enc, quiet); + dbprintf(3, " i25: s=%d enc=%x q=%d [invalid qz]\n", + dcode25->s10, enc, quiet); return(ZBAR_NONE); } @@ -148,8 +148,8 @@ static inline signed char i25_decode_end (zbar_decoder_t *dcode) if((quiet && quiet < dcode25->width * 3 / 8) || decode_e(get_width(dcode, 1), dcode25->width, 45) > 2 || decode_e(get_width(dcode, 2), dcode25->width, 45) > 2) { - dprintf(3, " i25: s=%d q=%d [invalid qz]\n", - dcode25->width, quiet); + dbprintf(3, " i25: s=%d q=%d [invalid qz]\n", + dcode25->width, quiet); return(ZBAR_NONE); } @@ -168,7 +168,7 @@ static inline signed char i25_decode_end (zbar_decoder_t *dcode) dcode->direction = 1 - 2 * dcode25->direction; if(dcode25->direction) { /* reverse buffer */ - dprintf(2, " (rev)"); + dbprintf(2, " (rev)"); int i; for(i = 0; i < dcode25->character / 2; i++) { unsigned j = dcode25->character - 1 - i; @@ -181,7 +181,7 @@ static inline signed char i25_decode_end (zbar_decoder_t *dcode) if(dcode25->character < CFG(*dcode25, ZBAR_CFG_MIN_LEN) || (CFG(*dcode25, ZBAR_CFG_MAX_LEN) > 0 && dcode25->character > CFG(*dcode25, ZBAR_CFG_MAX_LEN))) { - dprintf(2, " [invalid len]\n"); + dbprintf(2, " [invalid len]\n"); release_lock(dcode, ZBAR_I25); dcode25->character = -1; return(ZBAR_NONE); @@ -190,7 +190,7 @@ static inline signed char i25_decode_end (zbar_decoder_t *dcode) dcode->buflen = dcode25->character; dcode->buf[dcode25->character] = '\0'; dcode->modifiers = 0; - dprintf(2, " [valid end]\n"); + dbprintf(2, " [valid end]\n"); dcode25->character = -1; return(ZBAR_I25); } @@ -215,23 +215,23 @@ zbar_symbol_type_t _zbar_decode_i25 (zbar_decoder_t *dcode) /* FIXME check current character width against previous */ dcode25->width = dcode25->s10; - dprintf(2, " i25[%c%02d+%x]", - (dcode25->direction) ? '<' : '>', - dcode25->character, dcode25->element); + dbprintf(2, " i25[%c%02d+%x]", + (dcode25->direction) ? '<' : '>', + dcode25->character, dcode25->element); if(dcode25->character == 4 && i25_acquire_lock(dcode)) return(ZBAR_PARTIAL); unsigned char c = i25_decode10(dcode, 1); - dprintf(2, " c=%x", c); + dbprintf(2, " c=%x", c); if(c > 9) { - dprintf(2, " [aborted]\n"); + dbprintf(2, " [aborted]\n"); goto reset; } if((dcode25->character >= BUFFER_MIN) && size_buf(dcode, dcode25->character + 2)) { - dprintf(2, " [overflow]\n"); + dbprintf(2, " [overflow]\n"); goto reset; } @@ -243,13 +243,13 @@ zbar_symbol_type_t _zbar_decode_i25 (zbar_decoder_t *dcode) buf[dcode25->character++] = c + '0'; c = i25_decode10(dcode, 0); - dprintf(2, " c=%x", c); + dbprintf(2, " c=%x", c); if(c > 9) { - dprintf(2, " [aborted]\n"); + dbprintf(2, " [aborted]\n"); goto reset; } else - dprintf(2, "\n"); + dbprintf(2, "\n"); buf[dcode25->character++] = c + '0'; dcode25->element = 10; diff --git a/zbar/decoder/pdf417.c b/zbar/decoder/pdf417.c index ed01de7..80c7a94 100644 --- a/zbar/decoder/pdf417.c +++ b/zbar/decoder/pdf417.c @@ -41,7 +41,7 @@ static inline signed short pdf417_decode8 (zbar_decoder_t *dcode) * from similar edge measurements */ unsigned s = dcode->pdf417.s8; - dprintf(2, " s=%d ", s); + dbprintf(2, " s=%d ", s); if(s < 8) return(-1); @@ -55,19 +55,19 @@ static inline signed short pdf417_decode8 (zbar_decoder_t *dcode) else e = decode_e(get_width(dcode, 7 - i) + get_width(dcode, 6 - i), s, 17); - dprintf(4, "%x", e); + dbprintf(4, "%x", e); if(e < 0 || e > 8) return(-1); sig = (sig << 3) ^ e; } - dprintf(2, " sig=%06lx", sig); + dbprintf(2, " sig=%06lx", sig); /* determine cluster number */ int clst = ((sig & 7) - ((sig >> 3) & 7) + ((sig >> 12) & 7) - ((sig >> 15) & 7)); if(clst < 0) clst += 9; - dprintf(2, " k=%d", clst); + dbprintf(2, " k=%d", clst); zassert(clst >= 0 && clst < 9, -1, "dir=%x sig=%lx k=%x %s\n", dcode->pdf417.direction, sig, clst, _zbar_decoder_buf_dump(dcode->buf, dcode->pdf417.character)); @@ -89,8 +89,8 @@ static inline signed short pdf417_decode8 (zbar_decoder_t *dcode) _zbar_decoder_buf_dump(dcode->buf, dcode->pdf417.character)); unsigned short c = (g[0] + g[1] + g[2]) & PDF417_HASH_MASK; - dprintf(2, " g0=%x g1=%x g2=%x c=%03d(%d)", - g[0], g[1], g[2], c & 0x3ff, c >> 10); + dbprintf(2, " g0=%x g1=%x g2=%x c=%03d(%d)", + g[0], g[1], g[2], c & 0x3ff, c >> 10); return(c); } @@ -142,18 +142,18 @@ static inline signed char pdf417_decode_start(zbar_decoder_t *dcode) ei = decode_e(get_width(dcode, 8) + get_width(dcode, 9), s, 17); } - dprintf(2, " pdf417[%c]: s=%d", - (get_color(dcode)) ? '<' : '>', s); + dbprintf(2, " pdf417[%c]: s=%d", + (get_color(dcode)) ? '<' : '>', s); /* check quiet zone */ if(ei >= 0 && ei < ex) { - dprintf(2, " [invalid quiet]\n"); + dbprintf(2, " [invalid quiet]\n"); return(0); } /* lock shared resources */ if(acquire_lock(dcode, ZBAR_PDF417)) { - dprintf(2, " [locked %d]\n", dcode->lock); + dbprintf(2, " [locked %d]\n", dcode->lock); return(0); } @@ -162,7 +162,7 @@ static inline signed char pdf417_decode_start(zbar_decoder_t *dcode) dcode417->element = 0; dcode417->character = 0; - dprintf(2, " [valid start]\n"); + dbprintf(2, " [valid start]\n"); return(ZBAR_PARTIAL); } @@ -176,7 +176,7 @@ zbar_symbol_type_t _zbar_decode_pdf417 (zbar_decoder_t *dcode) if(dcode417->character < 0) { pdf417_decode_start(dcode); - dprintf(4, "\n"); + dbprintf(4, "\n"); return(0); } @@ -185,8 +185,8 @@ zbar_symbol_type_t _zbar_decode_pdf417 (zbar_decoder_t *dcode) return(0); dcode417->element = 0; - dprintf(2, " pdf417[%c%02d]:", - (dcode417->direction) ? '<' : '>', dcode417->character); + dbprintf(2, " pdf417[%c%02d]:", + (dcode417->direction) ? '<' : '>', dcode417->character); if(get_color(dcode) != dcode417->direction) { int c = dcode417->character; @@ -202,7 +202,7 @@ zbar_symbol_type_t _zbar_decode_pdf417 (zbar_decoder_t *dcode) if((c < 0) || ((dcode417->character >= BUFFER_MIN) && size_buf(dcode, dcode417->character + 1))) { - dprintf(1, (c < 0) ? " [aborted]\n" : " [overflow]\n"); + dbprintf(1, (c < 0) ? " [aborted]\n" : " [overflow]\n"); release_lock(dcode, ZBAR_PDF417); dcode417->character = -1; return(0); @@ -211,7 +211,7 @@ zbar_symbol_type_t _zbar_decode_pdf417 (zbar_decoder_t *dcode) /* FIXME TBD infer dimensions, save codewords */ if(c == PDF417_STOP) { - dprintf(1, " [valid stop]"); + dbprintf(1, " [valid stop]"); /* FIXME check trailing bar and qz */ dcode->direction = 1 - 2 * dcode417->direction; dcode->modifiers = 0; @@ -219,6 +219,6 @@ zbar_symbol_type_t _zbar_decode_pdf417 (zbar_decoder_t *dcode) dcode417->character = -1; } - dprintf(2, "\n"); + dbprintf(2, "\n"); return(0); } diff --git a/zbar/decoder/qr_finder.c b/zbar/decoder/qr_finder.c index f6c0819..d187d76 100644 --- a/zbar/decoder/qr_finder.c +++ b/zbar/decoder/qr_finder.c @@ -54,25 +54,25 @@ zbar_symbol_type_t _zbar_find_qr (zbar_decoder_t *dcode) if(get_color(dcode) != ZBAR_SPACE || s < 7) return(0); - dprintf(2, " qrf: s=%d", s); + dbprintf(2, " qrf: s=%d", s); ei = decode_e(pair_width(dcode, 1), s, 7); - dprintf(2, " %d", ei); + dbprintf(2, " %d", ei); if(ei) goto invalid; ei = decode_e(pair_width(dcode, 2), s, 7); - dprintf(2, "%d", ei); + dbprintf(2, "%d", ei); if(ei != 2) goto invalid; ei = decode_e(pair_width(dcode, 3), s, 7); - dprintf(2, "%d", ei); + dbprintf(2, "%d", ei); if(ei != 2) goto invalid; ei = decode_e(pair_width(dcode, 4), s, 7); - dprintf(2, "%d", ei); + dbprintf(2, "%d", ei); if(ei) goto invalid; @@ -88,15 +88,15 @@ zbar_symbol_type_t _zbar_find_qr (zbar_decoder_t *dcode) w = get_width(dcode, 5); qrf->line.boffs = qrf->line.pos[0] + get_width(dcode, 4) + (w + 1) / 2; - dprintf(2, " boff=%d pos=%d len=%d eoff=%d [valid]\n", - qrf->line.boffs, qrf->line.pos[0], qrf->line.len, - qrf->line.eoffs); + dbprintf(2, " boff=%d pos=%d len=%d eoff=%d [valid]\n", + qrf->line.boffs, qrf->line.pos[0], qrf->line.len, + qrf->line.eoffs); dcode->direction = 0; dcode->buflen = 0; return(ZBAR_QRCODE); invalid: - dprintf(2, " [invalid]\n"); + dbprintf(2, " [invalid]\n"); return(0); } diff --git a/zbar/scanner.c b/zbar/scanner.c index d8b16c2..79d6906 100644 --- a/zbar/scanner.c +++ b/zbar/scanner.c @@ -129,7 +129,7 @@ static inline unsigned calc_thresh (zbar_scanner_t *scn) unsigned dx, thresh = scn->y1_thresh; unsigned long t; if((thresh <= scn->y1_min_thresh) || !scn->width) { - dprintf(1, " tmin=%d", scn->y1_min_thresh); + dbprintf(1, " tmin=%d", scn->y1_min_thresh); return(scn->y1_min_thresh); } /* slowly return threshold to min */ @@ -137,9 +137,9 @@ static inline unsigned calc_thresh (zbar_scanner_t *scn) t = thresh * dx; t /= scn->width; t /= ZBAR_SCANNER_THRESH_FADE; - dprintf(1, " thr=%d t=%ld x=%d last=%d.%d (%d)", - thresh, t, scn->x, scn->last_edge >> ZBAR_FIXED, - scn->last_edge & ((1 << ZBAR_FIXED) - 1), dx); + dbprintf(1, " thr=%d t=%ld x=%d last=%d.%d (%d)", + thresh, t, scn->x, scn->last_edge >> ZBAR_FIXED, + scn->last_edge & ((1 << ZBAR_FIXED) - 1), dx); if(thresh > t) { thresh -= t; if(thresh > scn->y1_min_thresh) @@ -158,10 +158,10 @@ static inline zbar_symbol_type_t process_edge (zbar_scanner_t *scn, scn->last_edge = scn->cur_edge; scn->width = scn->cur_edge - scn->last_edge; - dprintf(1, " sgn=%d cur=%d.%d w=%d (%s)\n", - scn->y1_sign, scn->cur_edge >> ZBAR_FIXED, - scn->cur_edge & ((1 << ZBAR_FIXED) - 1), scn->width, - ((y1 > 0) ? "SPACE" : "BAR")); + dbprintf(1, " sgn=%d cur=%d.%d w=%d (%s)\n", + scn->y1_sign, scn->cur_edge >> ZBAR_FIXED, + scn->cur_edge & ((1 << ZBAR_FIXED) - 1), scn->width, + ((y1 > 0) ? "SPACE" : "BAR")); scn->last_edge = scn->cur_edge; #if DEBUG_SVG > 1 @@ -184,7 +184,7 @@ inline zbar_symbol_type_t zbar_scanner_flush (zbar_scanner_t *scn) if(scn->cur_edge != x || scn->y1_sign > 0) { zbar_symbol_type_t edge = process_edge(scn, -scn->y1_sign); - dprintf(1, "flush0:"); + dbprintf(1, "flush0:"); scn->cur_edge = x; scn->y1_sign = -scn->y1_sign; return(edge); @@ -245,8 +245,8 @@ zbar_symbol_type_t zbar_scan_y (zbar_scanner_t *scn, y2_1 = y0_0 - (y0_1 * 2) + y0_2; y2_2 = y0_1 - (y0_2 * 2) + y0_3; - dprintf(1, "scan: x=%d y=%d y0=%d y1=%d y2=%d", - x, y, y0_1, y1_1, y2_1); + dbprintf(1, "scan: x=%d y=%d y0=%d y1=%d y2=%d", + x, y, y0_1, y1_1, y2_1); edge = ZBAR_NONE; /* 2nd zero-crossing is 1st local min/max - could be edge */ @@ -267,7 +267,7 @@ zbar_symbol_type_t zbar_scan_y (zbar_scanner_t *scn, /* adaptive thresholding */ /* start at multiple of new min/max */ scn->y1_thresh = (abs(y1_1) * THRESH_INIT + ROUND) >> ZBAR_FIXED; - dprintf(1, "\tthr=%d", scn->y1_thresh); + dbprintf(1, "\tthr=%d", scn->y1_thresh); if(scn->y1_thresh < scn->y1_min_thresh) scn->y1_thresh = scn->y1_min_thresh; @@ -280,11 +280,11 @@ zbar_symbol_type_t zbar_scan_y (zbar_scanner_t *scn, /* interpolate zero crossing */ scn->cur_edge -= ((y2_1 << ZBAR_FIXED) + 1) / d; scn->cur_edge += x << ZBAR_FIXED; - dprintf(1, "\n"); + dbprintf(1, "\n"); } } else - dprintf(1, "\n"); + dbprintf(1, "\n"); /* FIXME add fall-thru pass to decoder after heuristic "idle" period (eg, 6-8 * last width) */ scn->x = x + 1; @@ -313,5 +313,5 @@ void zbar_scanner_get_state (const zbar_scanner_t *scn, /* NB not quite accurate (uses updated x) */ mut_scn = (zbar_scanner_t*)scn; if(y1_thresh) *y1_thresh = calc_thresh(mut_scn); - dprintf(1, "\n"); + dbprintf(1, "\n"); } From 12cb7a89a9fe0ab5d49eb99b6181f969b0e66658 Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 16 Jan 2011 14:48:39 -0800 Subject: [PATCH 260/328] iPhone: expose tracking box color --- iphone/ChangeLog | 3 +++ iphone/ZBarReaderView.m | 21 ++++++++++++++++++--- iphone/doc/ZBarReaderView.rst | 4 ++++ iphone/include/ZBarSDK/ZBarReaderView.h | 4 ++++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index f785546..e5c4b33 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,3 +1,6 @@ +current: + * expose tracking box color + version 1.1: * fix doc typo (bug #3139087) - add modifier bit docs diff --git a/iphone/ZBarReaderView.m b/iphone/ZBarReaderView.m index 343c955..d4ff0cf 100644 --- a/iphone/ZBarReaderView.m +++ b/iphone/ZBarReaderView.m @@ -32,8 +32,8 @@ @interface ZBarReaderViewImpl : NSObject @implementation ZBarReaderView -@synthesize readerDelegate, tracksSymbols, torchMode, showsFPS, zoom, scanCrop, - previewTransform; +@synthesize readerDelegate, tracksSymbols, trackingColor, torchMode, showsFPS, + zoom, scanCrop, previewTransform; @dynamic scanner, allowsPinchZoom, enableCache, device, session, captureReader; + (id) alloc @@ -61,9 +61,12 @@ - (void) initSubviews tracking.opacity = 0; tracking.borderWidth = 1; tracking.backgroundColor = [UIColor clearColor].CGColor; - tracking.borderColor = [UIColor greenColor].CGColor; [overlay addSublayer: tracking]; + trackingColor = [[UIColor greenColor] + retain]; + tracking.borderColor = trackingColor.CGColor; + r.origin.x = 3 * r.size.width / 4; r.origin.y = r.size.height - 32; r.size.width = r.size.width - r.origin.x + 12; @@ -145,6 +148,8 @@ - (void) dealloc overlay = nil; [tracking release]; tracking = nil; + [trackingColor release]; + trackingColor = nil; [fpsLabel release]; fpsLabel = nil; [fpsView release]; @@ -226,6 +231,16 @@ - (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) diff --git a/iphone/doc/ZBarReaderView.rst b/iphone/doc/ZBarReaderView.rst index 0a46e1b..2652a8e 100644 --- a/iphone/doc/ZBarReaderView.rst +++ b/iphone/doc/ZBarReaderView.rst @@ -27,6 +27,10 @@ Properties 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 diff --git a/iphone/include/ZBarSDK/ZBarReaderView.h b/iphone/include/ZBarSDK/ZBarReaderView.h index 78a4169..b06dd04 100644 --- a/iphone/include/ZBarSDK/ZBarReaderView.h +++ b/iphone/include/ZBarSDK/ZBarReaderView.h @@ -49,6 +49,7 @@ CGRect scanCrop, zoomCrop; CGAffineTransform previewTransform; CGFloat zoom, zoom0; + UIColor *trackingColor; BOOL tracksSymbols, showsFPS; NSInteger torchMode; @@ -82,6 +83,9 @@ // (default YES). @property (nonatomic) BOOL tracksSymbols; +// color of the tracking box (default green) +@property (nonatomic, retain) UIColor *trackingColor; + // enable pinch gesture recognition for zooming the preview/decode // (default YES). @property (nonatomic) BOOL allowsPinchZoom; From c1505d744a8943ded69df022761271a76d94278b Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 16 Jan 2011 17:05:29 -0800 Subject: [PATCH 261/328] fix jpeg decoder skip handling - thanks to jarekczek for the patch! --- ChangeLog | 2 ++ zbar/jpeg.c | 11 +++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3d5916d..e96ecc5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * 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 diff --git a/zbar/jpeg.c b/zbar/jpeg.c index 6351731..972bfea 100644 --- a/zbar/jpeg.c +++ b/zbar/jpeg.c @@ -79,8 +79,15 @@ int fill_input_buffer (j_decompress_ptr cinfo) void skip_input_data (j_decompress_ptr cinfo, long num_bytes) { - cinfo->src->next_input_byte = NULL; - cinfo->src->bytes_in_buffer = 0; + if(num_bytes > 0) { + if (num_bytes < cinfo->src->bytes_in_buffer) { + cinfo->src->next_input_byte += num_bytes; + cinfo->src->bytes_in_buffer -= num_bytes; + } + else { + fill_input_buffer(cinfo); + } + } } void term_source (j_decompress_ptr cinfo) From 79714979263c26c64508b1ec695ad55c2f0c5cad Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 21 Jan 2011 12:05:36 -0800 Subject: [PATCH 262/328] update HACKING - thanks to jarekczek for the patch! --- HACKING | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/HACKING b/HACKING index d73943d..b7da6e1 100644 --- a/HACKING +++ b/HACKING @@ -13,6 +13,11 @@ 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 +all above mentioned tools 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: From 0154a0a9674cb3a3089bba55d2ecad1bfe9560b6 Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 12 Feb 2011 19:28:53 -0800 Subject: [PATCH 263/328] fix Python Processor support for GIL, allowing asynchronous scanning --- ChangeLog | 1 + python/processor.c | 49 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index e96ecc5..17776d8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * 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) diff --git a/python/processor.c b/python/processor.c index c42d918..5c3c462 100644 --- a/python/processor.c +++ b/python/processor.c @@ -36,15 +36,24 @@ processor_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { - static char *kwlist[] = { NULL }; - if(!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist)) + static char *kwlist[] = { "enable_threads", NULL }; + int threaded = -1; + if(!PyArg_ParseTupleAndKeywords(args, kwds, "|O&", kwlist, + object_to_bool, &threaded)) + return(NULL); + +#ifndef WITH_THREAD + if(threaded > 0 && + PyErr_WarnEx(NULL, "threading requested but not available", 1)) return(NULL); + threaded = 0; +#endif zbarProcessor *self = (zbarProcessor*)type->tp_alloc(type, 0); if(!self) return(NULL); - self->zproc = zbar_processor_create(0/*FIXME*/); + self->zproc = zbar_processor_create(threaded); zbar_processor_set_userdata(self->zproc, self); if(!self->zproc) { Py_DECREF(self); @@ -228,7 +237,11 @@ processor_user_wait (zbarProcessor *self, object_to_timeout, &timeout)) return(NULL); - int rc = zbar_processor_user_wait(self->zproc, timeout); + int rc = -1; + Py_BEGIN_ALLOW_THREADS + rc = zbar_processor_user_wait(self->zproc, timeout); + Py_END_ALLOW_THREADS + if(rc < 0) return(zbarErr_Set((PyObject*)self)); return(PyInt_FromLong(rc)); @@ -245,7 +258,11 @@ processor_process_one (zbarProcessor *self, object_to_timeout, &timeout)) return(NULL); - int rc = zbar_process_one(self->zproc, timeout); + int rc = -1; + Py_BEGIN_ALLOW_THREADS + rc = zbar_process_one(self->zproc, timeout); + Py_END_ALLOW_THREADS + if(rc < 0) return(zbarErr_Set((PyObject*)self)); return(PyInt_FromLong(rc)); @@ -265,7 +282,11 @@ processor_process_image (zbarProcessor *self, if(zbarImage_validate(img)) return(NULL); - int n = zbar_process_image(self->zproc, img->zimg); + int n = -1; + Py_BEGIN_ALLOW_THREADS + n = zbar_process_image(self->zproc, img->zimg); + Py_END_ALLOW_THREADS + if(n < 0) return(zbarErr_Set((PyObject*)self)); return(PyInt_FromLong(n)); @@ -275,6 +296,9 @@ void process_handler (zbar_image_t *zimg, const void *userdata) { + PyGILState_STATE gstate; + gstate = PyGILState_Ensure(); + zbarProcessor *self = (zbarProcessor*)userdata; assert(self); assert(self->handler); @@ -285,7 +309,7 @@ process_handler (zbar_image_t *zimg, img = zbarImage_FromImage(zimg); if(!img) { PyErr_NoMemory(); - return; + goto done; } } else @@ -299,8 +323,17 @@ process_handler (zbar_image_t *zimg, PyTuple_SET_ITEM(args, 2, self->closure); PyObject *junk = PyObject_Call(self->handler, args, NULL); - Py_XDECREF(junk); + if(junk) + Py_DECREF(junk); + else { + PySys_WriteStderr("in ZBar Processor data_handler:\n"); + assert(PyErr_Occurred()); + PyErr_Print(); + } Py_DECREF(args); + +done: + PyGILState_Release(gstate); } static PyObject* From 304e2f3951fdd02fb02b8229477f60bd6bae3f0b Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 13 Feb 2011 09:55:56 -0800 Subject: [PATCH 264/328] add Python Processor support for request_size interface --- ChangeLog | 1 + python/image.c | 57 ++++++++++++---------------------------- python/processor.c | 23 ++++++++++++++++ python/test/test_zbar.py | 9 +++++++ python/zbarmodule.c | 22 ++++++++++++++++ python/zbarmodule.h | 7 +++-- 6 files changed, 77 insertions(+), 42 deletions(-) diff --git a/ChangeLog b/ChangeLog index 17776d8..aef33bc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * 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! diff --git a/python/image.c b/python/image.c index 760d13a..418bf21 100644 --- a/python/image.c +++ b/python/image.c @@ -172,28 +172,17 @@ image_set_size (zbarImage *self, PyErr_SetString(PyExc_TypeError, "cannot delete size attribute"); return(-1); } - int rc = -1, i, dims[2]; - if(!PySequence_Check(value) || - PySequence_Size(value) != 2) - goto error; - for(i = 0; i < 2; i++) { - PyObject *dim = PySequence_GetItem(value, i); - if(!dim) - goto error; - dims[i] = PyInt_AsSsize_t(dim); - Py_DECREF(dim); - if(dims[i] < 0) - goto error; - } - - zbar_image_set_size(self->zimg, dims[0], dims[1]); - rc = 0; -error: - if(rc) + int dims[2]; + if(parse_dimensions(value, dims, 2) || + dims[0] < 0 || dims[1] < 0) { PyErr_SetString(PyExc_ValueError, "size must be a sequence of two positive ints"); - return(rc); + return(-1); + } + + zbar_image_set_size(self->zimg, dims[0], dims[1]); + return(0); } static PyObject* @@ -217,21 +206,15 @@ image_set_crop (zbarImage *self, zbar_image_set_crop(self->zimg, 0, 0, w, h); return(0); } - int rc = -1, i, dims[4]; - if(!PySequence_Check(value) || - PySequence_Size(value) != 4) - goto error; - for(i = 0; i < 4; i++) { - PyObject *dim = PySequence_GetItem(value, i); - if(!dim) - goto error; - dims[i] = PyInt_AsSsize_t(dim); - Py_DECREF(dim); - if(dims[i] == -1 && PyErr_Occurred()) - goto error; + + int dims[4]; + if(parse_dimensions(value, dims, 4) || + dims[2] < 0 || dims[3] < 0) { + PyErr_SetString(PyExc_ValueError, + "crop must be a sequence of four positive ints"); + return(-1); } - if(dims[2] < 0 || dims[3] < 0) - goto error; + if(dims[0] < 0) { dims[2] += dims[0]; dims[0] = 0; @@ -242,13 +225,7 @@ image_set_crop (zbarImage *self, } zbar_image_set_crop(self->zimg, dims[0], dims[1], dims[2], dims[3]); - rc = 0; - -error: - if(rc) - PyErr_SetString(PyExc_ValueError, - "crop must be a sequence of four positive ints"); - return(rc); + return(0); } static PyObject* diff --git a/python/processor.c b/python/processor.c index 5c3c462..6af01f2 100644 --- a/python/processor.c +++ b/python/processor.c @@ -147,12 +147,35 @@ processor_get_results (zbarProcessor *self, return(zbarSymbolSet_FromSymbolSet(zsyms)); } +static int +processor_set_request_size (zbarProcessor *self, + PyObject *value, + void *closure) +{ + if(!value) { + zbar_processor_request_size(self->zproc, 0, 0); + return(0); + } + + int dims[2]; + if(parse_dimensions(value, dims, 2) || + dims[0] < 0 || dims[1] < 0) { + PyErr_SetString(PyExc_ValueError, + "request_size must be a sequence of two positive ints"); + return(-1); + } + + zbar_processor_request_size(self->zproc, dims[0], dims[1]); + return(0); +} + static PyGetSetDef processor_getset[] = { { "visible", (getter)processor_get_bool, (setter)processor_set_bool, NULL, (void*)0 }, { "active", NULL, (setter)processor_set_bool, NULL, (void*)1 }, { "results", (getter)processor_get_results, }, + { "request_size", NULL, (setter)processor_set_request_size, }, { NULL, }, }; diff --git a/python/test/test_zbar.py b/python/test/test_zbar.py index bb186ce..38aba3f 100755 --- a/python/test/test_zbar.py +++ b/python/test/test_zbar.py @@ -449,6 +449,15 @@ def test_parse_config(self): self.assertRaises(ValueError, self.proc.set_config, -1) self.proc.set_config() + def test_request_size(self): + def set_size(sz): + self.proc.request_size = sz + self.assertRaises(ValueError, set_size, (1,)) + self.assertRaises(ValueError, set_size, 1) + self.proc.request_size = (12, 6) + self.assertRaises(ValueError, set_size, (1, 2, 3)) + self.assertRaises(ValueError, set_size, "foo") + def test_processing(self): self.proc.init(VIDEO_DEVICE) self.assert_(self.proc.visible is False) diff --git a/python/zbarmodule.c b/python/zbarmodule.c index 0900bdd..979f0a5 100644 --- a/python/zbarmodule.c +++ b/python/zbarmodule.c @@ -103,6 +103,28 @@ object_to_bool (PyObject *obj, return(1); } +int +parse_dimensions (PyObject *seq, + int *dims, + int n) +{ + if(!PySequence_Check(seq) || + PySequence_Size(seq) != n) + return(-1); + + int i; + for(i = 0; i < n; i++, dims++) { + PyObject *dim = PySequence_GetItem(seq, i); + if(!dim) + return(-1); + *dims = PyInt_AsSsize_t(dim); + Py_DECREF(dim); + if(*dims == -1 && PyErr_Occurred()) + return(-1); + } + return(0); +} + PyObject *zbar_exc[ZBAR_ERR_NUM]; zbarEnumItem *color_enum[2]; zbarEnum *config_enum; diff --git a/python/zbarmodule.h b/python/zbarmodule.h index 938aa4f..9e01585 100644 --- a/python/zbarmodule.h +++ b/python/zbarmodule.h @@ -153,7 +153,10 @@ extern PyObject *symbol_enum; extern zbarEnumItem *symbol_NONE; extern zbarEnum *orient_enum; -int object_to_bool(PyObject *obj, - int *val); +extern int object_to_bool(PyObject *obj, + int *val); +extern int parse_dimensions(PyObject *seq, + int *dims, + int n); #endif From 05398a8851bdcce3b0abf143745ca32735b3479b Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 13 Feb 2011 10:18:06 -0800 Subject: [PATCH 265/328] fix Qt 4.6.3 compilation error (patch #3178244) - thanks to hrhristov for the patch! --- ChangeLog | 2 ++ qt/QZBarThread.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index aef33bc..6b59cba 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * 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 diff --git a/qt/QZBarThread.cpp b/qt/QZBarThread.cpp index b080c7b..69ce2c0 100644 --- a/qt/QZBarThread.cpp +++ b/qt/QZBarThread.cpp @@ -167,7 +167,7 @@ void QZBarThread::scanImageEvent (ScanImageEvent *e) bool QZBarThread::event (QEvent *e) { - switch(e->type()) { + switch((EventType)e->type()) { case VideoDevice: videoDeviceEvent((VideoDeviceEvent*)e); break; From 3ad01bae3fc3922b708d4062e40acfeeb06d199b Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 13 Feb 2011 17:14:29 -0800 Subject: [PATCH 266/328] fix zbarimg to accept autodetected stdin (lone dash) --- ChangeLog | 1 + zbarimg/zbarimg.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6b59cba..09f53f6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * 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 diff --git a/zbarimg/zbarimg.c b/zbarimg/zbarimg.c index a8b3bb2..4ffc3d4 100644 --- a/zbarimg/zbarimg.c +++ b/zbarimg/zbarimg.c @@ -255,7 +255,7 @@ int main (int argc, const char *argv[]) int i, j; for(i = 1; i < argc; i++) { const char *arg = argv[i]; - if(arg[0] != '-') + if(arg[0] != '-' || !arg[1]) // first pass, skip images num_images++; else if(arg[1] != '-') @@ -326,7 +326,7 @@ int main (int argc, const char *argv[]) if(!arg) continue; - if(arg[0] != '-') { + if(arg[0] != '-' || !arg[1]) { if(scan_image(arg)) return(exit_code); } From 0a141de20a852d1a1840ed4fc3bfa51e5a2ee065 Mon Sep 17 00:00:00 2001 From: lisah000 Date: Sun, 27 Feb 2011 02:17:22 -0500 Subject: [PATCH 267/328] fix EAN addon enables --- ChangeLog | 1 + zbar/decoder/ean.c | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 09f53f6..4f30320 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * 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! diff --git a/zbar/decoder/ean.c b/zbar/decoder/ean.c index 270c48b..c20f538 100644 --- a/zbar/decoder/ean.c +++ b/zbar/decoder/ean.c @@ -258,8 +258,12 @@ static inline signed char decode4 (zbar_decoder_t *dcode) return(code); } -static inline char ean_part_end2 (ean_pass_t *pass) +static inline char ean_part_end2 (ean_decoder_t *ean, + ean_pass_t *pass) { + if(!TEST_CFG(ean->ean2_config, ZBAR_CFG_ENABLE)) + return(ZBAR_NONE); + /* extract parity bits */ unsigned char par = ((pass->raw[1] & 0x10) >> 3 | (pass->raw[2] & 0x10) >> 4); @@ -310,8 +314,12 @@ static inline zbar_symbol_type_t ean_part_end4 (ean_pass_t *pass, return(ZBAR_EAN8 | EAN_LEFT); } -static inline char ean_part_end5 (ean_pass_t *pass) +static inline char ean_part_end5 (ean_decoder_t *ean, + ean_pass_t *pass) { + if(!TEST_CFG(ean->ean5_config, ZBAR_CFG_ENABLE)) + return(ZBAR_NONE); + /* extract parity bits */ unsigned char par = ((pass->raw[1] & 0x10) | (pass->raw[2] & 0x10) >> 1 | @@ -419,9 +427,9 @@ static inline zbar_symbol_type_t decode_pass (zbar_decoder_t *dcode, unsigned s = calc_s(dcode, 1, 4); zbar_symbol_type_t part = !qz || (qz >= s * 3 / 4); if(part && idx == 0x09) - part = ean_part_end2(pass); + part = ean_part_end2(&dcode->ean, pass); else if(part) - part = ean_part_end5(pass); + part = ean_part_end5(&dcode->ean, pass); if(part || idx == 0x21) { dcode->ean.direction = 0; From 8d3ee695e34cd789f0a39435eb63102fcc899701 Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 9 Apr 2011 18:31:42 -0700 Subject: [PATCH 268/328] add core support for Codabar symbology - TBD: python, perl, java and iPhone interfaces --- ChangeLog | 2 + README | 6 +- README.windows | 2 +- configure.ac | 5 +- doc/ref/commonoptions.xml | 17 +- doc/ref/zbarcam.xml | 4 +- doc/ref/zbarimg.xml | 4 +- include/zbar.h | 1 + test/test_decode.c | 134 ++++++++++++- zbar/Makefile.am.inc | 3 + zbar/config.c | 2 + zbar/decoder.c | 34 +++- zbar/decoder.h | 58 ++++++ zbar/decoder/codabar.c | 382 ++++++++++++++++++++++++++++++++++++++ zbar/decoder/codabar.h | 51 +++++ zbar/decoder/databar.c | 6 +- zbar/img_scanner.c | 2 +- zbar/symbol.c | 3 +- zbar/symbol.h | 2 +- zbarimg/zbarimg.c | 4 +- 20 files changed, 688 insertions(+), 34 deletions(-) create mode 100644 zbar/decoder/codabar.c create mode 100644 zbar/decoder/codabar.h diff --git a/ChangeLog b/ChangeLog index 4f30320..b2ee443 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * add core support for Codabar symbology + - TBD: python, perl, java and iPhone interfaces * fix EAN addon enables * fix zbarimg to accept autodetected stdin (lone dash) * fix Qt 4.6.3 compilation error (patch #3178244) diff --git a/README b/README index 30b8955..d484441 100644 --- a/README +++ b/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. diff --git a/README.windows b/README.windows index 2dc4381..688d893 100644 --- a/README.windows +++ b/README.windows @@ -4,7 +4,7 @@ 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 93, Code 39, -Interleaved 2 of 5 and QR Code. Included with the library are basic +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 diff --git a/configure.ac b/configure.ac index 4407935..de07420 100644 --- a/configure.ac +++ b/configure.ac @@ -107,9 +107,9 @@ dnl symbologies AC_ARG_ENABLE([codes], [AS_HELP_STRING([--enable-codes=SYMS], - [select symbologies to compile [default=ean,databar,code128,code93,code39,i25,qrcode]])], + [select symbologies to compile [default=ean,databar,code128,code93,code39,codabar,i25,qrcode]])], [], - [enable_codes="ean,databar,code128,code93,code39,i25,qrcode"]) + [enable_codes="ean,databar,code128,code93,code39,codabar,i25,qrcode"]) AC_DEFUN([ZBAR_CHK_CODE], [ AC_MSG_CHECKING([whether to build $2]) @@ -131,6 +131,7 @@ 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([codabar], [Codabar symbology]) ZBAR_CHK_CODE([i25], [Interleaved 2 of 5 symbology]) ZBAR_CHK_CODE([qrcode], [QR Code]) ZBAR_CHK_CODE([pdf417], [PDF417 symbology]) diff --git a/doc/ref/commonoptions.xml b/doc/ref/commonoptions.xml index 749abcb..ca68465 100644 --- a/doc/ref/commonoptions.xml +++ b/doc/ref/commonoptions.xml @@ -47,9 +47,9 @@ , , , , , , - , , , - , - or the special value . + , , , + , , + or the special value . If symbology is omitted or , the config will be set for all @@ -129,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: , , - and . - defaults to 6 for - and 1 for (per Code 39 autodiscrimination - recommendation); all others default to 0 + symbologies: , , + , and + . defaults to 6 + for and 1 for (per Code + 39 autodiscrimination recommendation); all others default to + 0 diff --git a/doc/ref/zbarcam.xml b/doc/ref/zbarcam.xml index 439aeb1..69ad593 100644 --- a/doc/ref/zbarcam.xml +++ b/doc/ref/zbarcam.xml @@ -61,8 +61,8 @@ The underlying library currently supports EAN-13 (including UPC and ISBN subsets), EAN-8, DataBar, DataBar Expanded, Code 128, - Code 93, Code 39, Interleaved 2 of 5 and QR Code symbologies. The - specific type of each detected symbol is printed with the decoded + 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. diff --git a/doc/ref/zbarimg.xml b/doc/ref/zbarimg.xml index ccc5d0e..98963e0 100644 --- a/doc/ref/zbarimg.xml +++ b/doc/ref/zbarimg.xml @@ -60,8 +60,8 @@ The underlying library currently supports EAN-13 (including UPC and ISBN subsets), EAN-8, DataBar, DataBar Expanded, Code 128, - Code 93, Code 39, Interleaved 2 of 5 and QR Code symbologies. The - specific type of each detected symbol is printed with the decoded + 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. Note that "image" diff --git a/include/zbar.h b/include/zbar.h index 49aaea6..6927113 100644 --- a/include/zbar.h +++ b/include/zbar.h @@ -98,6 +98,7 @@ typedef enum zbar_symbol_type_e { 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 */ diff --git a/test/test_decode.c b/test/test_decode.c index d783c71..4fd6d6e 100644 --- a/test/test_decode.c +++ b/test/test_decode.c @@ -507,6 +507,105 @@ static void encode_pdf417 (char *data) } #endif +/*------------------------------------------------------------*/ +/* Codabar encoding */ + +static const unsigned int codabar[20] = { + 0x03, 0x06, 0x09, 0x60, 0x12, 0x42, 0x21, 0x24, + 0x30, 0x48, 0x0c, 0x18, 0x45, 0x51, 0x54, 0x15, + 0x1a, 0x29, 0x0b, 0x0e, +}; + +static const char codabar_char[0x14] = + "0123456789-$:/.+ABCD"; + +/* FIXME configurable/randomized ratio, ics */ +/* FIXME check digit option */ + +static char *convert_codabar (char *src) +{ + unsigned len = strlen(src); + char tmp[4] = { 0, }; + if(len < 2) { + unsigned delim = rand() >> 8; + tmp[0] = delim & 3; + if(len) + tmp[1] = src[0]; + tmp[len + 1] = (delim >> 2) & 3; + len += 2; + src = tmp; + } + + char *result = malloc(len + 1); + char *dst = result; + *(dst++) = ((*(src++) - 1) & 0x3) + 'A'; + for(len--; len > 1; len--) { + char c = *(src++); + if(c >= '0' && c <= '9') + *(dst++) = c; + else if(c == '-' || c == '$' || c == ':' || c == '/' || + c == '.' || c == '+') + *(dst++) = c; + else + *(dst++) = codabar_char[c % 0x10]; + } + *(dst++) = ((*(src++) - 1) & 0x3) + 'A'; + *dst = 0; + return(result); +} + +static void encode_codachar (unsigned char c, + unsigned ics, + int dir) +{ + unsigned int idx; + if(c >= '0' && c <= '9') + idx = c - '0'; + else if(c >= 'A' && c <= 'D') + idx = c - 'A' + 0x10; + else + switch(c) + { + case '-': idx = 0xa; break; + case '$': idx = 0xb; break; + case ':': idx = 0xc; break; + case '/': idx = 0xd; break; + case '.': idx = 0xe; break; + case '+': idx = 0xf; break; + default: + assert(0); + } + + assert(idx < 0x14); + unsigned int raw = codabar[idx]; + + uint32_t enc = 0; + int j; + for(j = 0; j < 7; j++, raw <<= 1) + enc = (enc << 4) | ((raw & 0x40) ? 3 : 1); + zprintf(3, " encode '%c': %07x: ", c, enc); + if(dir) + enc = (enc << 4) | ics; + else + enc |= ics << 28; + encode(enc, 1 - dir); +} + +static void encode_codabar (char *data, + int dir) +{ + assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE); + print_sep(3); + zprintf(2, "CODABAR: %s\n", data); + encode(0xa, 0); /* leading quiet */ + int i, n = strlen(data); + for(i = 0; i < n; i++) { + int j = (dir) ? i : n - i - 1; + encode_codachar(data[j], (i < n - 1) ? 1 : 0xa, dir); + } + print_sep(3); +} + /*------------------------------------------------------------*/ /* Interleaved 2 of 5 encoding */ @@ -1017,13 +1116,22 @@ int test_numeric (char *data) encode_i25(data, FWD); encode_junk(rnd_size); - #if 0 /* FIXME encoding broken */ encode_i25(data, REV); encode_junk(rnd_size); #endif + char *cdb = convert_codabar(data); + expect(ZBAR_CODABAR, cdb); + encode_codabar(cdb, FWD); + encode_junk(rnd_size); + + expect(ZBAR_CODABAR, cdb); + encode_codabar(cdb, REV); + encode_junk(rnd_size); + free(cdb); + calc_ean_parity(data + 2, 12); expect(ZBAR_EAN13, data + 2); encode_ean13(data + 2); @@ -1067,7 +1175,16 @@ int test_alpha (char *data) encode_junk(rnd_size); - /*encode_code39("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%");*/ + char *cdb = convert_codabar(data); + expect(ZBAR_CODABAR, cdb); + encode_codabar(cdb, FWD); + encode_junk(rnd_size); + + expect(ZBAR_CODABAR, cdb); + encode_codabar(cdb, REV); + encode_junk(rnd_size); + free(cdb); + convert_code39(data); expect(ZBAR_CODE39, data); encode_code39(data); @@ -1091,6 +1208,14 @@ int test1 () seed = 0xbabeface; zprintf(1, "[%d] SEED=%d\n", iter++, seed); srand(seed); + if(/* EAN-2 within DataBar (020596539169270) + * (FIXME require COMPOSITE for addons) + */ + seed == -862734747) + { + zprintf(2, " FIXME known failure\n"); + return(2); + } int i; char data[32] = { 0, }; @@ -1148,9 +1273,10 @@ int main (int argc, char **argv) fprintf(stderr, "ERROR: -s needs argument\n"); return(2); } - seed = strtol(argv[i] + j, &end, 0); + long s = strtol(argv[i] + j, &end, 0); + seed = s; if((!isdigit(argv[i][j]) && argv[i][j] != '-') || - !seed || seed == LONG_MAX || seed == LONG_MIN) { + !s || s == LONG_MAX || s == LONG_MIN) { fprintf(stderr, "ERROR: invalid : \"%s\"\n", argv[i] + j); return(2); diff --git a/zbar/Makefile.am.inc b/zbar/Makefile.am.inc index 3d52077..375c577 100644 --- a/zbar/Makefile.am.inc +++ b/zbar/Makefile.am.inc @@ -31,6 +31,9 @@ endif if ENABLE_CODE39 zbar_libzbar_la_SOURCES += zbar/decoder/code39.h zbar/decoder/code39.c endif +if ENABLE_CODABAR +zbar_libzbar_la_SOURCES += zbar/decoder/codabar.h zbar/decoder/codabar.c +endif if ENABLE_I25 zbar_libzbar_la_SOURCES += zbar/decoder/i25.h zbar/decoder/i25.c endif diff --git a/zbar/config.c b/zbar/config.c index 0921637..2b784b4 100644 --- a/zbar/config.c +++ b/zbar/config.c @@ -80,6 +80,8 @@ int zbar_parse_config (const char *cfgstr, *sym = ZBAR_ISBN10; else if(!strncmp(cfgstr, "db-exp", len)) *sym = ZBAR_DATABAR_EXP; + else if(!strncmp(cfgstr, "codabar", len)) + *sym = ZBAR_CODABAR; else if(len < 6) return(1); else if(!strncmp(cfgstr, "code93", len)) diff --git a/zbar/decoder.c b/zbar/decoder.c index 4d2dc25..24ef25b 100644 --- a/zbar/decoder.c +++ b/zbar/decoder.c @@ -29,9 +29,9 @@ #include #if defined(DEBUG_DECODER) || defined(DEBUG_EAN) || defined(DEBUG_CODE93) || \ - defined(DEBUG_CODE39) || defined(DEBUG_I25) || defined(DEBUG_DATABAR) || \ - defined(DEBUG_CODE128) || defined(DEBUG_QR_FINDER) || \ - (defined(DEBUG_PDF417) && (DEBUG_PDF417 >= 4)) + defined(DEBUG_CODE39) || defined(DEBUG_CODABAR) || defined(DEBUG_I25) || \ + defined(DEBUG_DATABAR) || defined(DEBUG_CODE128) || \ + defined(DEBUG_QR_FINDER) || (defined(DEBUG_PDF417) && (DEBUG_PDF417 >= 4)) # define DEBUG_LEVEL 1 #endif #include "debug.h" @@ -69,6 +69,10 @@ zbar_decoder_t *zbar_decoder_create () dcode->databar.csegs = 4; dcode->databar.segs = calloc(4, sizeof(*dcode->databar.segs)); #endif +#ifdef ENABLE_CODABAR + dcode->codabar.config = 1 << ZBAR_CFG_ENABLE; + CFG(dcode->codabar, ZBAR_CFG_MIN_LEN) = 4; +#endif #ifdef ENABLE_CODE39 dcode->code39.config = 1 << ZBAR_CFG_ENABLE; CFG(dcode->code39, ZBAR_CFG_MIN_LEN) = 1; @@ -113,6 +117,9 @@ void zbar_decoder_reset (zbar_decoder_t *dcode) #ifdef ENABLE_DATABAR databar_reset(&dcode->databar); #endif +#ifdef ENABLE_CODABAR + codabar_reset(&dcode->codabar); +#endif #ifdef ENABLE_CODE39 code39_reset(&dcode->code39); #endif @@ -146,6 +153,9 @@ void zbar_decoder_new_scan (zbar_decoder_t *dcode) #ifdef ENABLE_DATABAR databar_new_scan(&dcode->databar); #endif +#ifdef ENABLE_CODABAR + codabar_reset(&dcode->codabar); +#endif #ifdef ENABLE_CODE39 code39_reset(&dcode->code39); #endif @@ -258,6 +268,11 @@ zbar_symbol_type_t zbar_decode_width (zbar_decoder_t *dcode, (tmp = _zbar_decode_databar(dcode)) > ZBAR_PARTIAL) sym = tmp; #endif +#ifdef ENABLE_CODABAR + if(TEST_CFG(dcode->codabar.config, ZBAR_CFG_ENABLE) && + (tmp = _zbar_decode_codabar(dcode)) > ZBAR_PARTIAL) + sym = tmp; +#endif #ifdef ENABLE_I25 if(TEST_CFG(dcode->i25.config, ZBAR_CFG_ENABLE) && (tmp = _zbar_decode_i25(dcode)) > ZBAR_PARTIAL) @@ -335,6 +350,12 @@ decoder_get_configp (const zbar_decoder_t *dcode, break; #endif +#ifdef ENABLE_CODABAR + case ZBAR_CODABAR: + config = &dcode->codabar.config; + break; +#endif + #ifdef ENABLE_CODE39 case ZBAR_CODE39: config = &dcode->code39.config; @@ -423,6 +444,11 @@ static inline int decoder_set_config_int (zbar_decoder_t *dcode, CFG(dcode->i25, cfg) = val; break; #endif +#ifdef ENABLE_CODABAR + case ZBAR_CODABAR: + CFG(dcode->codabar, cfg) = val; + break; +#endif #ifdef ENABLE_CODE39 case ZBAR_CODE39: CFG(dcode->code39, cfg) = val; @@ -459,7 +485,7 @@ int zbar_decoder_set_config (zbar_decoder_t *dcode, static const zbar_symbol_type_t all[] = { ZBAR_EAN13, ZBAR_EAN2, ZBAR_EAN5, ZBAR_EAN8, ZBAR_UPCA, ZBAR_UPCE, ZBAR_ISBN10, ZBAR_ISBN13, - ZBAR_I25, ZBAR_DATABAR, ZBAR_DATABAR_EXP, + ZBAR_I25, ZBAR_DATABAR, ZBAR_DATABAR_EXP, ZBAR_CODABAR, ZBAR_CODE39, ZBAR_CODE93, ZBAR_CODE128, ZBAR_QRCODE, ZBAR_PDF417, 0 }; diff --git a/zbar/decoder.h b/zbar/decoder.h index 4603d0a..33177d4 100644 --- a/zbar/decoder.h +++ b/zbar/decoder.h @@ -25,6 +25,7 @@ #include #include /* realloc */ +#include #include @@ -39,6 +40,9 @@ #ifdef ENABLE_DATABAR # include "decoder/databar.h" #endif +#ifdef ENABLE_CODABAR +# include "decoder/codabar.h" +#endif #ifdef ENABLE_CODE39 # include "decoder/code39.h" #endif @@ -108,6 +112,9 @@ struct zbar_decoder_s { #ifdef ENABLE_DATABAR databar_decoder_t databar; /* DataBar decode state */ #endif +#ifdef ENABLE_CODABAR + codabar_decoder_t codabar; /* Codabar decode state */ +#endif #ifdef ENABLE_CODE39 code39_decoder_t code39; /* Code 39 decode state */ #endif @@ -183,6 +190,57 @@ static inline int decode_e (unsigned e, return((E >= n - 3) ? -1 : E); } +/* sort three like-colored elements and return ordering + */ +static inline unsigned decode_sort3 (zbar_decoder_t *dcode, + int i0) +{ + unsigned w0 = get_width(dcode, i0); + unsigned w2 = get_width(dcode, i0 + 2); + unsigned w4 = get_width(dcode, i0 + 4); + if(w0 < w2) { + if(w2 < w4) + return((i0 << 8) | ((i0 + 2) << 4) | (i0 + 4)); + if(w0 < w4) + return((i0 << 8) | ((i0 + 4) << 4) | (i0 + 2)); + return(((i0 + 4) << 8) | (i0 << 4) | (i0 + 2)); + } + if(w4 < w2) + return(((i0 + 4) << 8) | ((i0 + 2) << 4) | i0); + if(w0 < w4) + return(((i0 + 2) << 8) | (i0 << 4) | (i0 + 4)); + return(((i0 + 2) << 8) | ((i0 + 4) << 4) | i0); +} + +/* sort N like-colored elements and return ordering + */ +static inline unsigned decode_sortn (zbar_decoder_t *dcode, + int n, + int i0) +{ + unsigned mask = 0, sort = 0; + int i; + for(i = n - 1; i >= 0; i--) { + unsigned wmin = UINT_MAX; + int jmin = -1, j; + for(j = n - 1; j >= 0; j--) { + if((mask >> j) & 1) + continue; + unsigned w = get_width(dcode, i0 + j * 2); + if(wmin >= w) { + wmin = w; + jmin = j; + } + } + zassert(jmin >= 0, 0, "sortn(%d,%d) jmin=%d", + n, i0, jmin); + sort <<= 4; + mask |= 1 << jmin; + sort |= i0 + jmin * 2; + } + return(sort); +} + /* acquire shared state lock */ static inline char acquire_lock (zbar_decoder_t *dcode, zbar_symbol_type_t req) diff --git a/zbar/decoder/codabar.c b/zbar/decoder/codabar.c new file mode 100644 index 0000000..fd2a76a --- /dev/null +++ b/zbar/decoder/codabar.c @@ -0,0 +1,382 @@ +/*------------------------------------------------------------------------ + * Copyright 2011 (c) Jeff Brown + * + * 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 +#include /* memmove */ + +#include + +#ifdef DEBUG_CODABAR +# define DEBUG_LEVEL (DEBUG_CODABAR) +#endif +#include "debug.h" +#include "decoder.h" + +#define NIBUF 6 /* initial scan buffer size */ + +static const signed char codabar_lo[12] = { + 0x0, 0x1, 0x4, 0x5, 0x2, 0xa, 0xb, 0x9, + 0x6, 0x7, 0x8, 0x3 +}; + +static const unsigned char codabar_hi[8] = { + 0x1, 0x4, 0x7, 0x6, 0x2, 0x3, 0x0, 0x5 +}; + +static const unsigned char codabar_characters[20] = + "0123456789-$:/.+ABCD"; + +static inline int +check_width (unsigned ref, + unsigned w) +{ + unsigned dref = ref; + ref *= 4; + w *= 4; + return(ref - dref <= w && w <= ref + dref); +} + +static inline signed char +codabar_decode7 (zbar_decoder_t *dcode) +{ + codabar_decoder_t *codabar = &dcode->codabar; + unsigned s = codabar->s7; + dbprintf(2, " s=%d", s); + if(s < 7) + return(-1); + + /* check width */ + if(!check_width(codabar->width, s)) { + dbprintf(2, " [width]"); + return(-1); + } + + /* extract min/max bar */ + unsigned ibar = decode_sortn(dcode, 4, 1); + dbprintf(2, " bar=%04x", ibar); + + unsigned wbmax = get_width(dcode, ibar & 0xf); + unsigned wbmin = get_width(dcode, ibar >> 12); + if(8 * wbmin < wbmax || + 8 * wbmin > 5 * wbmax) + { + dbprintf(2, " [bar ratio]"); + return(-1); + } + + if(8 * get_width(dcode, (ibar >> 4) & 0xf) < 5 * wbmax) + // single wide bar combinations + ibar = (ibar >> 1) & 0x3; + else if(8 * get_width(dcode, (ibar >> 8) & 0xf) >= 5 * wbmax) + // three wide bars, no wide spaces + ibar = (ibar >> 13) + 4; + else { + dbprintf(2, " [bar comb]"); + return(-1); + } + + unsigned ispc = decode_sort3(dcode, 2); + dbprintf(2, "(%x) spc=%03x", ibar, ispc); + + unsigned wsmax = get_width(dcode, ispc & 0xf); + unsigned wsmid = get_width(dcode, (ispc >> 4) & 0xf); + unsigned wsmin = get_width(dcode, (ispc >> 8) & 0xf); + if(ibar >> 2) { + // verify no wide spaces + if(wsmin * 8 < wsmax * 3) { + dbprintf(2, " [space comb0]"); + return(-1); + } + ibar &= 0x3; + if(codabar->direction) + ibar = 3 - ibar; + int c = (0xfcde >> (ibar << 2)) & 0xf; + dbprintf(2, " ex[%d]=%x", ibar, c); + return(c); + } + else if(8 * wsmin > 5 * wsmax) { + dbprintf(2, " [space comb1]"); + return(-1); + } + else if(8 * wsmid < 5 * wsmax) { + // single wide space + ispc = ((ispc & 0xf) >> 1) - 1; + unsigned ic = (ispc << 2) | ibar; + if(codabar->direction) + ic = 11 - ic; + int c = codabar_lo[ic]; + dbprintf(2, "(%d) lo[%d]=%x", ispc, ic, c); + return(c); + } + else if(8 * wsmin < 5 * wsmid) { + // two wide spaces, check start/stop + ispc >>= 10; + dbprintf(2, "(%d)", ispc); + unsigned ic = ispc * 4 + ibar; + zassert(ic < 8, -1, "ic=%d ispc=%d ibar=%d", ic, ispc, ibar); + unsigned char c = codabar_hi[ic]; + if(c >> 2 != codabar->direction) { + dbprintf(2, " [invalid stop]"); + return(-1); + } + c = (c & 0x3) | 0x10; + dbprintf(2, " hi[%d]=%x", ic, c); + return(c); + } + else { + dbprintf(2, " [space ratio]"); + return(-1); + } +} + +static inline signed char +codabar_decode_start (zbar_decoder_t *dcode) +{ + codabar_decoder_t *codabar = &dcode->codabar; + unsigned s = codabar->s7; + if(s < 8) + return(ZBAR_NONE); + dbprintf(2, " codabar: s=%d", s); + + /* check leading quiet zone - spec is 10x */ + unsigned qz = get_width(dcode, 8); + if((qz && qz * 2 < s) || + 4 * get_width(dcode, 0) > 3 * s) + { + dbprintf(2, " [invalid qz/ics]\n"); + return(ZBAR_NONE); + } + + /* check space ratios first */ + unsigned ispc = decode_sort3(dcode, 2); + dbprintf(2, " spc=%03x", ispc); + if((ispc >> 8) == 4) { + dbprintf(2, " [space comb]\n"); + return(ZBAR_NONE); + } + + /* require 2 wide and 1 narrow spaces */ + unsigned wsmax = get_width(dcode, ispc & 0xf); + unsigned wsmid = get_width(dcode, (ispc >> 4) & 0xf); + unsigned wsmin = get_width(dcode, ispc >> 8); + if(8 * wsmin < wsmax || + 8 * wsmin > 5 * wsmax || + 8 * wsmid < 5 * wsmax) + { + dbprintf(2, " [space ratio]\n"); + return(ZBAR_NONE); + } + ispc >>= 10; + dbprintf(2, "(%d)", ispc); + + /* check bar ratios */ + unsigned ibar = decode_sortn(dcode, 4, 1); + dbprintf(2, " bar=%04x", ibar); + + /* require 1 wide & 3 narrow bars */ + unsigned wbmax = get_width(dcode, ibar & 0xf); + unsigned wbmin = get_width(dcode, ibar >> 12); + if(8 * wbmin < wbmax || + 8 * wbmin > 5 * wbmax) + { + dbprintf(2, " [bar0 ratio]\n"); + return(ZBAR_NONE); + } + unsigned wbmid = get_width(dcode, (ibar >> 4) & 0xf); + if(8 * wbmid > 5 * wbmax) { + dbprintf(2, " [bar2 ratio]\n"); + return(ZBAR_NONE); + } + ibar = ((ibar & 0xf) - 1) >> 1; + dbprintf(2, "(%d)", ibar); + + /* decode combination */ + int ic = ispc * 4 + ibar; + zassert(ic < 8, ZBAR_NONE, "ic=%d ispc=%d ibar=%d", ic, ispc, ibar); + int c = codabar_hi[ic]; + codabar->buf[0] = (c & 0x3) | 0x10; + + /* set character direction */ + codabar->direction = c >> 2; + + codabar->element = 4; + codabar->character = 1; + codabar->width = codabar->s7; + dbprintf(1, " start=%c dir=%x [valid start]\n", + codabar->buf[0] + 0x31, codabar->direction); + return(ZBAR_PARTIAL); +} + +static inline int +codabar_checksum (zbar_decoder_t *dcode, + unsigned n) +{ + unsigned chk = 0; + unsigned char *buf = dcode->buf; + while(n--) + chk += *(buf++); + return(!!(chk & 0xf)); +} + +static inline zbar_symbol_type_t +codabar_postprocess (zbar_decoder_t *dcode) +{ + codabar_decoder_t *codabar = &dcode->codabar; + int dir = codabar->direction; + dcode->direction = 1 - 2 * dir; + int i, n = codabar->character; + for(i = 0; i < NIBUF; i++) + dcode->buf[i] = codabar->buf[i]; + if(dir) + /* reverse buffer */ + for(i = 0; i < n / 2; i++) { + unsigned j = n - 1 - i; + char code = dcode->buf[i]; + dcode->buf[i] = dcode->buf[j]; + dcode->buf[j] = code; + } + + if(TEST_CFG(codabar->config, ZBAR_CFG_ADD_CHECK)) { + /* validate checksum */ + if(codabar_checksum(dcode, n)) + return(ZBAR_NONE); + if(!TEST_CFG(codabar->config, ZBAR_CFG_EMIT_CHECK)) { + dcode->buf[n - 2] = dcode->buf[n - 1]; + n--; + } + } + + for(i = 0; i < n; i++) { + unsigned c = dcode->buf[i]; + dcode->buf[i] = ((c < 0x14) + ? codabar_characters[c] + : '?'); + } + dcode->buflen = i; + dcode->buf[i] = '\0'; + dcode->modifiers = 0; + + codabar->character = -1; + return(ZBAR_CODABAR); +} + +zbar_symbol_type_t +_zbar_decode_codabar (zbar_decoder_t *dcode) +{ + codabar_decoder_t *codabar = &dcode->codabar; + + /* update latest character width */ + codabar->s7 -= get_width(dcode, 8); + codabar->s7 += get_width(dcode, 1); + + if(get_color(dcode) != ZBAR_SPACE) + return(ZBAR_NONE); + if(codabar->character < 0) + return(codabar_decode_start(dcode)); + if(codabar->character < 2 && + codabar_decode_start(dcode)) + return(ZBAR_PARTIAL); + if(--codabar->element) + return(ZBAR_NONE); + codabar->element = 4; + + dbprintf(1, " codabar[%c%02d+%x]", + (codabar->direction) ? '<' : '>', + codabar->character, codabar->element); + + signed char c = codabar_decode7(dcode); + dbprintf(1, " %d", c); + if(c < 0) { + dbprintf(1, " [aborted]\n"); + goto reset; + } + + unsigned char *buf; + if(codabar->character < NIBUF) + buf = codabar->buf; + else { + if(codabar->character >= BUFFER_MIN && + size_buf(dcode, codabar->character + 1)) + { + dbprintf(1, " [overflow]\n"); + goto reset; + } + buf = dcode->buf; + } + buf[codabar->character++] = c; + + /* lock shared resources */ + if(codabar->character == NIBUF && + acquire_lock(dcode, ZBAR_CODABAR)) + { + codabar->character = -1; + return(ZBAR_PARTIAL); + } + + unsigned s = codabar->s7; + if(c & 0x10) { + unsigned qz = get_width(dcode, 0); + if(qz && qz * 2 < s) { + dbprintf(2, " [invalid qz]\n"); + goto reset; + } + unsigned n = codabar->character; + if(n < CFG(*codabar, ZBAR_CFG_MIN_LEN) || + (CFG(*codabar, ZBAR_CFG_MAX_LEN) > 0 && + n > CFG(*codabar, ZBAR_CFG_MAX_LEN))) + { + dbprintf(2, " [invalid len]\n"); + goto reset; + } + if(codabar->character < NIBUF && + acquire_lock(dcode, ZBAR_CODABAR)) + { + codabar->character = -1; + return(ZBAR_PARTIAL); + } + dbprintf(2, " stop=%c", c + 0x31); + + zbar_symbol_type_t sym = codabar_postprocess(dcode); + if(sym > ZBAR_PARTIAL) + dbprintf(2, " [valid stop]"); + else { + release_lock(dcode, ZBAR_CODABAR); + codabar->character = -1; + } + dbprintf(2, "\n"); + return(sym); + } + else if(4 * get_width(dcode, 0) > 3 * s) { + dbprintf(2, " [ics]\n"); + goto reset; + } + + dbprintf(2, "\n"); + return(ZBAR_NONE); + +reset: + if(codabar->character >= NIBUF) + release_lock(dcode, ZBAR_CODABAR); + codabar->character = -1; + return(ZBAR_NONE); +} diff --git a/zbar/decoder/codabar.h b/zbar/decoder/codabar.h new file mode 100644 index 0000000..85ec198 --- /dev/null +++ b/zbar/decoder/codabar.h @@ -0,0 +1,51 @@ +/*------------------------------------------------------------------------ + * Copyright 2011 (c) Jeff Brown + * + * 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 + *------------------------------------------------------------------------*/ +#ifndef _CODABAR_H_ +#define _CODABAR_H_ + +/* Codabar specific decode state */ +typedef struct codabar_decoder_s { + unsigned direction : 1; /* scan direction: 0=fwd, 1=rev */ + unsigned element : 4; /* element offset 0-7 */ + int character : 12; /* character position in symbol */ + unsigned s7; /* current character width */ + unsigned width; /* last character width */ + unsigned char buf[6]; /* initial scan buffer */ + + unsigned config; + int configs[NUM_CFGS]; /* int valued configurations */ +} codabar_decoder_t; + +/* reset Codabar specific state */ +static inline void codabar_reset (codabar_decoder_t *codabar) +{ + codabar->direction = 0; + codabar->element = 0; + codabar->character = -1; + codabar->s7 = 0; +} + +/* decode Codabar symbols */ +zbar_symbol_type_t _zbar_decode_codabar(zbar_decoder_t *dcode); + +#endif diff --git a/zbar/decoder/databar.c b/zbar/decoder/databar.c index da472b4..79fb4a6 100644 --- a/zbar/decoder/databar.c +++ b/zbar/decoder/databar.c @@ -296,7 +296,7 @@ databar_postprocess_exp (zbar_decoder_t *dcode, n /= 12; yy = n; PUSH_CHAR('1'); - PUSH_CHAR('0' + (enc - 6) | 1); + PUSH_CHAR('0' + ((enc - 6) | 1)); decode10(buf, yy, 2); buf += 2; decode10(buf, mm, 2); @@ -608,8 +608,8 @@ match_segment (zbar_decoder_t *dcode, chk = 79 + chkf - chks; dbprintf(2, " chk=(%d,%d) => %d", chkf, chks, chk); - age1 = ((db->epoch - s0->epoch) & 0xff + - (db->epoch - s1->epoch) & 0xff); + age1 = (((db->epoch - s0->epoch) & 0xff) + + ((db->epoch - s1->epoch) & 0xff)); for(i2 = i1 + 1; i2 < csegs; i2++) { databar_segment_t *s2 = db->segs + i2; diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 8474248..bbe6d8d 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -493,7 +493,7 @@ zbar_image_scanner_t *zbar_image_scanner_create () zbar_image_scanner_set_config(iscn, ZBAR_CODE128, ZBAR_CFG_UNCERTAINTY, 0); zbar_image_scanner_set_config(iscn, ZBAR_CODE93, ZBAR_CFG_UNCERTAINTY, 0); zbar_image_scanner_set_config(iscn, ZBAR_CODE39, ZBAR_CFG_UNCERTAINTY, 0); - + zbar_image_scanner_set_config(iscn, ZBAR_CODABAR, ZBAR_CFG_UNCERTAINTY, 1); zbar_image_scanner_set_config(iscn, ZBAR_COMPOSITE, ZBAR_CFG_UNCERTAINTY, 0); return(iscn); } diff --git a/zbar/symbol.c b/zbar/symbol.c index 4e118b9..e35df30 100644 --- a/zbar/symbol.c +++ b/zbar/symbol.c @@ -44,6 +44,7 @@ const char *zbar_get_symbol_name (zbar_symbol_type_t sym) case ZBAR_I25: return("I2/5"); case ZBAR_DATABAR: return("DataBar"); case ZBAR_DATABAR_EXP: return("DataBar-Exp"); + case ZBAR_CODABAR: return("Codabar"); case ZBAR_CODE39: return("CODE-39"); case ZBAR_CODE93: return("CODE-93"); case ZBAR_CODE128: return("CODE-128"); @@ -98,7 +99,7 @@ const char *zbar_get_orientation_name (zbar_orientation_t orient) int _zbar_get_symbol_hash (zbar_symbol_type_t sym) { static const signed char hash[0x20] = { - 0x00, 0x01, 0x10, 0x11, -1, 0x11, -1, 0x0c, + 0x00, 0x01, 0x10, 0x11, -1, 0x11, 0x16, 0x0c, 0x05, 0x06, 0x08, -1, 0x04, 0x03, 0x07, 0x12, -1, -1, -1, -1, -1, -1, -1, 0x02, -1, 0x00, 0x12, 0x0c, 0x0b, 0x1d, 0x0a, 0x00, diff --git a/zbar/symbol.h b/zbar/symbol.h index 59b7374..81f0e86 100644 --- a/zbar/symbol.h +++ b/zbar/symbol.h @@ -27,7 +27,7 @@ #include #include "refcnt.h" -#define NUM_SYMS 19 +#define NUM_SYMS 20 typedef struct point_s { int x, y; diff --git a/zbarimg/zbarimg.c b/zbarimg/zbarimg.c index 4ffc3d4..7220523 100644 --- a/zbarimg/zbarimg.c +++ b/zbarimg/zbarimg.c @@ -77,8 +77,8 @@ static const char *warning_not_found = " - is the barcode type supported?" " currently supported symbologies are:\n" " EAN/UPC (EAN-13, EAN-8, EAN-2, EAN-5, UPC-A, UPC-E,\n" - " ISBN-10, ISBN-13), Code 128, Code 93, Code 39, DataBar,\n" - " DataBar Expanded, and Interleaved 2 of 5\n" + " ISBN-10, ISBN-13), Code 128, Code 93, Code 39, Codabar,\n" + " DataBar, DataBar Expanded, and Interleaved 2 of 5\n" " - is the barcode large enough in the image?\n" " - is the barcode mostly in focus?\n" " - is there sufficient contrast/illumination?\n" From 69945d9a83c1549a45dc48859664afa80f6ede3f Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 10 Apr 2011 10:29:10 -0700 Subject: [PATCH 269/328] finish Codabar support for python, perl, java and iPhone interfaces - reduce Codabar uncertainty to minimum --- ChangeLog | 2 ++ iphone/README | 6 +++--- iphone/doc/ZBarSymbol.rst | 3 +++ iphone/examples/readertest/readertest.m | 4 ++-- iphone/include/config.h | 3 +++ iphone/res/zbar-help.html | 1 + iphone/zbar.xcodeproj/project.pbxproj | 6 ++++++ java/net/sourceforge/zbar/Symbol.java | 6 ++++-- perl/README | 4 ++-- perl/ZBar.pm | 4 ++-- perl/ZBar.xs | 3 ++- perl/ZBar/Symbol.pod | 2 ++ python/README | 4 ++-- python/test/test_zbar.py | 1 + python/zbarmodule.c | 1 + zbar/img_scanner.c | 2 +- 16 files changed, 37 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index b2ee443..868249f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * 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 EAN addon enables diff --git a/iphone/README b/iphone/README index 25acea8..7c889b5 100644 --- a/iphone/README +++ b/iphone/README @@ -4,9 +4,9 @@ ZBar iPhone 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, Interleaved 2 of 5 and QR Code. These are -the Objective C wrappers and integrated widget for developing with the -library on the iPhone platform. +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 iPhone platform. Check the ZBar project home page for the latest release, forums, etc. diff --git a/iphone/doc/ZBarSymbol.rst b/iphone/doc/ZBarSymbol.rst index 0fbcda5..058a7b1 100644 --- a/iphone/doc/ZBarSymbol.rst +++ b/iphone/doc/ZBarSymbol.rst @@ -132,6 +132,9 @@ Constants ZBAR_DATABAR_EXP GS1 DataBar Expanded + ZBAR_CODABAR + Codabar + ZBAR_CODE39 Code 39 (3 of 9) diff --git a/iphone/examples/readertest/readertest.m b/iphone/examples/readertest/readertest.m index 7bbe1b0..3f6cda9 100644 --- a/iphone/examples/readertest/readertest.m +++ b/iphone/examples/readertest/readertest.m @@ -326,8 +326,8 @@ - (void) initControlCells nil]]; static const int symbolValues[] = { - ZBAR_QRCODE, ZBAR_CODE128, ZBAR_CODE93, ZBAR_CODE39, ZBAR_I25, - ZBAR_DATABAR, ZBAR_DATABAR_EXP, + ZBAR_QRCODE, ZBAR_CODE128, ZBAR_CODE93, ZBAR_CODE39, ZBAR_CODABAR, + ZBAR_I25, ZBAR_DATABAR, ZBAR_DATABAR_EXP, ZBAR_EAN13, ZBAR_EAN8, ZBAR_EAN2, ZBAR_EAN5, ZBAR_COMPOSITE, ZBAR_UPCA, ZBAR_UPCE, diff --git a/iphone/include/config.h b/iphone/include/config.h index efd4f3e..113982d 100644 --- a/iphone/include/config.h +++ b/iphone/include/config.h @@ -9,6 +9,9 @@ /* 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 diff --git a/iphone/res/zbar-help.html b/iphone/res/zbar-help.html index 72d209c..620ba78 100644 --- a/iphone/res/zbar-help.html +++ b/iphone/res/zbar-help.html @@ -46,6 +46,7 @@

Barcode Reader Help

DataBar (RSS), Code 93, Code 39 and +Codabar and Interleaved 2 of 5


Hints for successful scanning

diff --git a/iphone/zbar.xcodeproj/project.pbxproj b/iphone/zbar.xcodeproj/project.pbxproj index 600b5f1..fd335e9 100644 --- a/iphone/zbar.xcodeproj/project.pbxproj +++ b/iphone/zbar.xcodeproj/project.pbxproj @@ -41,6 +41,7 @@ /* Begin PBXBuildFile section */ DC26004C118631C200FA987B /* ZBarCaptureReader.m in Sources */ = {isa = PBXBuildFile; fileRef = DC26004B118631C200FA987B /* ZBarCaptureReader.m */; }; + DC290E281351496400A9B857 /* codabar.c in Sources */ = {isa = PBXBuildFile; fileRef = DC290E261351496400A9B857 /* codabar.c */; }; DC299A9D1208B5E8006A023C /* libzbar.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D2AAC07E0554694100DB518D /* libzbar.a */; }; DC299AA01208B61C006A023C /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC50453D1203396B009FF359 /* AVFoundation.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; DC299AA11208B61C006A023C /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC50453F1203396B009FF359 /* CoreMedia.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; @@ -236,6 +237,8 @@ DC1A49A411FF33B300BCDA30 /* zbar-samples.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "zbar-samples.png"; path = "res/zbar-samples.png"; sourceTree = ""; }; DC1A49C111FF537000BCDA30 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; DC26004B118631C200FA987B /* ZBarCaptureReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarCaptureReader.m; sourceTree = ""; usesTabs = 0; }; + DC290E261351496400A9B857 /* codabar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = codabar.c; sourceTree = ""; }; + DC290E271351496400A9B857 /* codabar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = codabar.h; sourceTree = ""; }; DC299AF51208B7BD006A023C /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = config.h; path = include/config.h; sourceTree = ""; }; DC299B051208FC11006A023C /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; DC299BEC1208FE40006A023C /* prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = prefix.pch; path = include/prefix.pch; sourceTree = ""; }; @@ -530,6 +533,8 @@ DC67C12610A07AD30033B702 /* code39.h */, DC67C12710A07AD30033B702 /* ean.c */, DC67C12810A07AD30033B702 /* ean.h */, + DC290E261351496400A9B857 /* codabar.c */, + DC290E271351496400A9B857 /* codabar.h */, DC67C12910A07AD30033B702 /* i25.c */, DC67C12A10A07AD30033B702 /* i25.h */, DC67C12E10A07AD30033B702 /* qr_finder.c */, @@ -724,6 +729,7 @@ DC3CE47811FA1622008FAF88 /* ZBarReaderViewImpl_Capture.m in Sources */, DC3CE47911FA1622008FAF88 /* ZBarReaderViewImpl_Simulator.m in Sources */, DCE9900D129719F100D2655C /* code93.c in Sources */, + DC290E281351496400A9B857 /* codabar.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/java/net/sourceforge/zbar/Symbol.java b/java/net/sourceforge/zbar/Symbol.java index 43ea6d4..54f40f5 100644 --- a/java/net/sourceforge/zbar/Symbol.java +++ b/java/net/sourceforge/zbar/Symbol.java @@ -53,14 +53,16 @@ public class Symbol public static final int DATABAR = 34; /** DataBar Expanded. */ public static final int DATABAR_EXP = 35; - /** Code 93. */ - public static final int CODE93 = 93; + /** Codabar. */ + public static final int CODABAR = 38; /** Code 39. */ public static final int CODE39 = 39; /** PDF417. */ public static final int PDF417 = 57; /** QR Code. */ public static final int QRCODE = 64; + /** Code 93. */ + public static final int CODE93 = 93; /** Code 128. */ public static final int CODE128 = 128; diff --git a/perl/README b/perl/README index c5a3427..fc25456 100644 --- a/perl/README +++ b/perl/README @@ -4,8 +4,8 @@ Barcode::ZBar Perl module 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, Interleaved 2 of 5 and QR Code. These are the Perl -bindings for the library. +Code 93, Code 39, Codabar, Interleaved 2 of 5 and QR Code. These are +the Perl bindings for the library. Check the ZBar project home page for the latest release, mailing lists, etc. diff --git a/perl/ZBar.pm b/perl/ZBar.pm index ce77931..de2fa44 100644 --- a/perl/ZBar.pm +++ b/perl/ZBar.pm @@ -86,8 +86,8 @@ collect results: The ZBar Bar Code Reader is a library for scanning and decoding bar codes from various sources such as video streams, image files or raw -intensity sensors. It supports EAN, UPC, Code 128, Code 39 and -Interleaved 2 of 5. +intensity 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. These are the bindings for interacting directly with the library from Perl. diff --git a/perl/ZBar.xs b/perl/ZBar.xs index 77db677..ced1f7d 100644 --- a/perl/ZBar.xs +++ b/perl/ZBar.xs @@ -339,6 +339,7 @@ BOOT: CONSTANT(symbol_type, , DATABAR_EXP, zbar_get_symbol_name(ZBAR_DATABAR_EXP)); CONSTANT(symbol_type, , I25, zbar_get_symbol_name(ZBAR_I25)); + CONSTANT(symbol_type, , CODABAR, zbar_get_symbol_name(ZBAR_CODABAR)); CONSTANT(symbol_type, , CODE39, zbar_get_symbol_name(ZBAR_CODE39)); CONSTANT(symbol_type, , PDF417, zbar_get_symbol_name(ZBAR_PDF417)); CONSTANT(symbol_type, , QRCODE, zbar_get_symbol_name(ZBAR_QRCODE)); @@ -796,7 +797,7 @@ zbar_decoder_get_configs(decoder, symbology) zbar_symbol_type_t symbology PPCODE: if(symbology == ZBAR_NONE) - symbology = zbar_decoder_get_type(decoder) + symbology = zbar_decoder_get_type(decoder); PUSH_ENUM_MASK(config, CFG, zbar_decoder_get_configs(decoder, symbology)); SV * diff --git a/perl/ZBar/Symbol.pod b/perl/ZBar/Symbol.pod index 6a0eec3..77118eb 100644 --- a/perl/ZBar/Symbol.pod +++ b/perl/ZBar/Symbol.pod @@ -126,6 +126,8 @@ Bar code type "symbology" constants: =item I25 +=item CODABAR + =item CODE39 =item CODE93 diff --git a/python/README b/python/README index 3698d7c..3117615 100644 --- a/python/README +++ b/python/README @@ -5,8 +5,8 @@ zbar -- read barcodes from images or video 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, Interleaved 2 of 5 and QR Code. These are the -Python bindings for the library. +Code 93, Code 39, Codabar, Interleaved 2 of 5 and QR Code. These are +the Python bindings for the library. Check the ZBar project home page for the latest release, mailing lists, etc. diff --git a/python/test/test_zbar.py b/python/test/test_zbar.py index 38aba3f..dbe1803 100755 --- a/python/test/test_zbar.py +++ b/python/test/test_zbar.py @@ -89,6 +89,7 @@ def test_symbologies(self): zbar.Symbol.DATABAR, zbar.Symbol.DATABAR_EXP, zbar.Symbol.I25, + zbar.Symbol.CODABAR, zbar.Symbol.CODE39, zbar.Symbol.PDF417, zbar.Symbol.QRCODE, diff --git a/python/zbarmodule.c b/python/zbarmodule.c index 979f0a5..a5895d7 100644 --- a/python/zbarmodule.c +++ b/python/zbarmodule.c @@ -55,6 +55,7 @@ static const enumdef symbol_defs[] = { { "DATABAR", ZBAR_DATABAR }, { "DATABAR_EXP", ZBAR_DATABAR_EXP }, { "I25", ZBAR_I25 }, + { "CODABAR", ZBAR_CODABAR }, { "CODE39", ZBAR_CODE39 }, { "PDF417", ZBAR_PDF417 }, { "QRCODE", ZBAR_QRCODE }, diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index bbe6d8d..2267c97 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -493,7 +493,7 @@ zbar_image_scanner_t *zbar_image_scanner_create () zbar_image_scanner_set_config(iscn, ZBAR_CODE128, ZBAR_CFG_UNCERTAINTY, 0); zbar_image_scanner_set_config(iscn, ZBAR_CODE93, ZBAR_CFG_UNCERTAINTY, 0); zbar_image_scanner_set_config(iscn, ZBAR_CODE39, ZBAR_CFG_UNCERTAINTY, 0); - zbar_image_scanner_set_config(iscn, ZBAR_CODABAR, ZBAR_CFG_UNCERTAINTY, 1); + zbar_image_scanner_set_config(iscn, ZBAR_CODABAR, ZBAR_CFG_UNCERTAINTY, 0); zbar_image_scanner_set_config(iscn, ZBAR_COMPOSITE, ZBAR_CFG_UNCERTAINTY, 0); return(iscn); } From 03bd189ff7f8e9a60a1c3c02400dea052e003b7d Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 13 Apr 2011 14:42:08 -0700 Subject: [PATCH 270/328] tweak Codabar bar/space ratio validation --- ChangeLog | 1 + zbar/decoder/codabar.c | 103 ++++++++++++++++++++++++++++++----------- 2 files changed, 78 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index 868249f..27dc7bb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * 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 diff --git a/zbar/decoder/codabar.c b/zbar/decoder/codabar.c index fd2a76a..f05e9ab 100644 --- a/zbar/decoder/codabar.c +++ b/zbar/decoder/codabar.c @@ -78,20 +78,42 @@ codabar_decode7 (zbar_decoder_t *dcode) unsigned wbmax = get_width(dcode, ibar & 0xf); unsigned wbmin = get_width(dcode, ibar >> 12); if(8 * wbmin < wbmax || - 8 * wbmin > 5 * wbmax) + 3 * wbmin > 2 * wbmax) { - dbprintf(2, " [bar ratio]"); + dbprintf(2, " [bar outer ratio]"); return(-1); } - if(8 * get_width(dcode, (ibar >> 4) & 0xf) < 5 * wbmax) - // single wide bar combinations + unsigned wb1 = get_width(dcode, (ibar >> 8) & 0xf); + unsigned wb2 = get_width(dcode, (ibar >> 4) & 0xf); + unsigned long b0b3 = wbmin * wbmax; + unsigned long b1b2 = wb1 * wb2; + if(b1b2 + b1b2 / 8 < b0b3) { + /* single wide bar combinations */ + if(8 * wbmin < 5 * wb1 || + 8 * wb1 < 5 * wb2 || + 4 * wb2 > 3 * wbmax || + wb2 * wb2 >= wb1 * wbmax) + { + dbprintf(2, " [1bar inner ratios]"); + return(-1); + } ibar = (ibar >> 1) & 0x3; - else if(8 * get_width(dcode, (ibar >> 8) & 0xf) >= 5 * wbmax) - // three wide bars, no wide spaces + } + else if(b1b2 > b0b3 + b0b3 / 8) { + /* three wide bars, no wide spaces */ + if(4 * wbmin > 3 * wb1 || + 8 * wb1 < 5 * wb2 || + 8 * wb2 < 5 * wbmax || + wbmin * wb2 >= wb1 * wb1) + { + dbprintf(2, " [3bar inner ratios]"); + return(-1); + } ibar = (ibar >> 13) + 4; + } else { - dbprintf(2, " [bar comb]"); + dbprintf(2, " [bar inner ratios]"); return(-1); } @@ -102,9 +124,12 @@ codabar_decode7 (zbar_decoder_t *dcode) unsigned wsmid = get_width(dcode, (ispc >> 4) & 0xf); unsigned wsmin = get_width(dcode, (ispc >> 8) & 0xf); if(ibar >> 2) { - // verify no wide spaces - if(wsmin * 8 < wsmax * 3) { - dbprintf(2, " [space comb0]"); + /* verify no wide spaces */ + if(8 * wsmin < wsmax || + 8 * wsmin < 5 * wsmid || + 8 * wsmid < 5 * wsmax) + { + dbprintf(2, " [0space inner ratios]"); return(-1); } ibar &= 0x3; @@ -114,12 +139,23 @@ codabar_decode7 (zbar_decoder_t *dcode) dbprintf(2, " ex[%d]=%x", ibar, c); return(c); } - else if(8 * wsmin > 5 * wsmax) { - dbprintf(2, " [space comb1]"); + else if(8 * wsmin < wsmax || + 3 * wsmin > 2 * wsmax) + { + dbprintf(2, " [space outer ratio]"); return(-1); } - else if(8 * wsmid < 5 * wsmax) { - // single wide space + + unsigned long s0s2 = wsmin * wsmax; + unsigned long s1s1 = wsmid * wsmid; + if(s1s1 + s1s1 / 8 < s0s2) { + /* single wide space */ + if(8 * wsmin < 5 * wsmid || + 4 * wsmid > 3 * wsmax) + { + dbprintf(2, " [1space inner ratios]"); + return(-1); + } ispc = ((ispc & 0xf) >> 1) - 1; unsigned ic = (ispc << 2) | ibar; if(codabar->direction) @@ -128,8 +164,14 @@ codabar_decode7 (zbar_decoder_t *dcode) dbprintf(2, "(%d) lo[%d]=%x", ispc, ic, c); return(c); } - else if(8 * wsmin < 5 * wsmid) { - // two wide spaces, check start/stop + else if(s1s1 > s0s2 + s0s2 / 8) { + /* two wide spaces, check start/stop */ + if(4 * wsmin > 3 * wsmid || + 8 * wsmid < 5 * wsmax) + { + dbprintf(2, " [2space inner ratios]"); + return(-1); + } ispc >>= 10; dbprintf(2, "(%d)", ispc); unsigned ic = ispc * 4 + ibar; @@ -144,7 +186,7 @@ codabar_decode7 (zbar_decoder_t *dcode) return(c); } else { - dbprintf(2, " [space ratio]"); + dbprintf(2, " [space inner ratios]"); return(-1); } } @@ -177,11 +219,13 @@ codabar_decode_start (zbar_decoder_t *dcode) /* require 2 wide and 1 narrow spaces */ unsigned wsmax = get_width(dcode, ispc & 0xf); - unsigned wsmid = get_width(dcode, (ispc >> 4) & 0xf); unsigned wsmin = get_width(dcode, ispc >> 8); + unsigned wsmid = get_width(dcode, (ispc >> 4) & 0xf); if(8 * wsmin < wsmax || - 8 * wsmin > 5 * wsmax || - 8 * wsmid < 5 * wsmax) + 3 * wsmin > 2 * wsmax || + 4 * wsmin > 3 * wsmid || + 8 * wsmid < 5 * wsmax || + wsmid * wsmid <= wsmax * wsmin) { dbprintf(2, " [space ratio]\n"); return(ZBAR_NONE); @@ -193,18 +237,25 @@ codabar_decode_start (zbar_decoder_t *dcode) unsigned ibar = decode_sortn(dcode, 4, 1); dbprintf(2, " bar=%04x", ibar); - /* require 1 wide & 3 narrow bars */ unsigned wbmax = get_width(dcode, ibar & 0xf); unsigned wbmin = get_width(dcode, ibar >> 12); if(8 * wbmin < wbmax || - 8 * wbmin > 5 * wbmax) + 3 * wbmin > 2 * wbmax) { - dbprintf(2, " [bar0 ratio]\n"); + dbprintf(2, " [bar outer ratio]\n"); return(ZBAR_NONE); } - unsigned wbmid = get_width(dcode, (ibar >> 4) & 0xf); - if(8 * wbmid > 5 * wbmax) { - dbprintf(2, " [bar2 ratio]\n"); + + /* require 1 wide & 3 narrow bars */ + unsigned wb1 = get_width(dcode, (ibar >> 8) & 0xf); + unsigned wb2 = get_width(dcode, (ibar >> 4) & 0xf); + if(8 * wbmin < 5 * wb1 || + 8 * wb1 < 5 * wb2 || + 4 * wb2 > 3 * wbmax || + wb1 * wb2 >= wbmin * wbmax || + wb2 * wb2 >= wb1 * wbmax) + { + dbprintf(2, " [bar inner ratios]\n"); return(ZBAR_NONE); } ibar = ((ibar & 0xf) - 1) >> 1; From b66529ec9947aaaeab8a53bead992548aa41e165 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 14 Apr 2011 15:14:56 -0700 Subject: [PATCH 271/328] iPhone: updates for Xcode 4 --- .hgignore | 2 + iphone/ChangeLog | 1 + iphone/doc/tutorial.rst | 9 +- .../ReaderSample.xcodeproj/project.pbxproj | 467 ++++++++-------- .../ReaderSample-Info.plist | 10 +- .../ReaderSample/ReaderSample-Prefix.pch | 16 + .../ReaderSampleAppDelegate.h | 7 +- .../ReaderSampleAppDelegate.m | 64 +-- .../ReaderSampleViewController.h | 2 +- .../ReaderSampleViewController.m | 20 +- .../ReaderSample/en.lproj/InfoPlist.strings | 2 + .../en.lproj}/MainWindow.xib | 4 +- .../en.lproj/ReaderSampleViewController.xib | 320 +++++++++++ .../ReaderSample/{ => ReaderSample}/main.m | 7 +- .../ReaderSampleViewController.xib | 521 ------------------ .../ReaderSample/ReaderSample_Prefix.pch | 11 - .../xcschemes/readertest.xcscheme | 76 +++ iphone/res/ZBarSDK-Info.plist | 2 +- .../xcschemes/ZBarSDK.dmg.xcscheme | 58 ++ .../xcshareddata/xcschemes/ZBarSDK.xcscheme | 58 ++ .../xcshareddata/xcschemes/libzbar.xcscheme | 58 ++ .../xcschemes/readertest.xcscheme | 76 +++ 22 files changed, 971 insertions(+), 820 deletions(-) mode change 100755 => 100644 iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj rename iphone/examples/ReaderSample/{ => ReaderSample}/ReaderSample-Info.plist (74%) create mode 100644 iphone/examples/ReaderSample/ReaderSample/ReaderSample-Prefix.pch rename iphone/examples/ReaderSample/{Classes => ReaderSample}/ReaderSampleAppDelegate.h (76%) rename iphone/examples/ReaderSample/{Classes => ReaderSample}/ReaderSampleAppDelegate.m (59%) rename iphone/examples/ReaderSample/{Classes => ReaderSample}/ReaderSampleViewController.h (92%) rename iphone/examples/ReaderSample/{Classes => ReaderSample}/ReaderSampleViewController.m (75%) create mode 100644 iphone/examples/ReaderSample/ReaderSample/en.lproj/InfoPlist.strings rename iphone/examples/ReaderSample/{ => ReaderSample/en.lproj}/MainWindow.xib (99%) create mode 100644 iphone/examples/ReaderSample/ReaderSample/en.lproj/ReaderSampleViewController.xib rename iphone/examples/ReaderSample/{ => ReaderSample}/main.m (54%) delete mode 100644 iphone/examples/ReaderSample/ReaderSampleViewController.xib delete mode 100644 iphone/examples/ReaderSample/ReaderSample_Prefix.pch create mode 100644 iphone/examples/readertest/readertest.xcodeproj/xcshareddata/xcschemes/readertest.xcscheme create mode 100644 iphone/zbar.xcodeproj/xcshareddata/xcschemes/ZBarSDK.dmg.xcscheme create mode 100644 iphone/zbar.xcodeproj/xcshareddata/xcschemes/ZBarSDK.xcscheme create mode 100644 iphone/zbar.xcodeproj/xcshareddata/xcschemes/libzbar.xcscheme create mode 100644 iphone/zbar.xcodeproj/xcshareddata/xcschemes/readertest.xcscheme diff --git a/.hgignore b/.hgignore index 4ec021d..1b450ef 100644 --- a/.hgignore +++ b/.hgignore @@ -23,4 +23,6 @@ python/MANIFEST build *.xcodeproj/*.mode1v3 *.xcodeproj/*.pbxuser +xcuserdata +contents.xcworkspacedata .DS_Store diff --git a/iphone/ChangeLog b/iphone/ChangeLog index e5c4b33..3008050 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,5 @@ current: + * updates for Xcode 4 * expose tracking box color version 1.1: diff --git a/iphone/doc/tutorial.rst b/iphone/doc/tutorial.rst index c7e3989..b54b459 100644 --- a/iphone/doc/tutorial.rst +++ b/iphone/doc/tutorial.rst @@ -97,9 +97,8 @@ Now for the exciting part - let's add a barcode reader! 3. Drag the :file:`ZBarSDK` folder into your Xcode project. Make sure that the "Copy Items into destination group's folder" checkbox is checked. -4. Right-click the ``Frameworks`` group in your project. Select - ``Add -> Existing Frameworks...`` Make sure "All" are listed and add each - of these from the ``Device`` list (NB hold down command for multiple +4. Open the target build settings and find ``Link Binary With Libraries``. + Click the ``+`` and add each of these (NB hold down command for multiple selection): * AVFoundation.framework @@ -109,7 +108,7 @@ Now for the exciting part - let's add a barcode reader! * libiconv.dylib 5. Import the SDK header. You will usually want to prefix it, so add it to - :file:`ReaderSample_prefix.pch`:: + :file:`ReaderSample-prefix.pch`:: // ADD: import barcode reader APIs #import "ZBarSDK.h" @@ -179,7 +178,7 @@ Testing 1. Save everything (don't forget to save MyAppViewController.xib). -2. Select "Build and Run". +2. Build and Run the project. 3. Tap the Scan button. diff --git a/iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj b/iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj old mode 100755 new mode 100644 index f7b2a2d..49708a3 --- a/iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj +++ b/iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj @@ -3,218 +3,215 @@ archiveVersion = 1; classes = { }; - objectVersion = 45; + objectVersion = 46; objects = { /* Begin PBXBuildFile section */ - 1D3623260D0F684500981E51 /* ReaderSampleAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* ReaderSampleAppDelegate.m */; }; - 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; - 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; - 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; - 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765A40DF7441C002DB57D /* CoreGraphics.framework */; }; - 2899E5220DE3E06400AC0155 /* ReaderSampleViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2899E5210DE3E06400AC0155 /* ReaderSampleViewController.xib */; }; - 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; - 28D7ACF80DDB3853001CB0EB /* ReaderSampleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28D7ACF70DDB3853001CB0EB /* ReaderSampleViewController.m */; }; - DC3CEC791209F83E00D7A786 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC3CEC781209F83E00D7A786 /* AVFoundation.framework */; }; - DC3CEC7B1209F83E00D7A786 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC3CEC7A1209F83E00D7A786 /* CoreMedia.framework */; }; - DC3CEC7D1209F83E00D7A786 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC3CEC7C1209F83E00D7A786 /* CoreVideo.framework */; }; - DC3CEC7F1209F83E00D7A786 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC3CEC7E1209F83E00D7A786 /* QuartzCore.framework */; }; - DC3CEC811209F83E00D7A786 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DC3CEC801209F83E00D7A786 /* libiconv.dylib */; }; - DC48C40C1219E1A20047193B /* libzbar.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC48C4061219E1A20047193B /* libzbar.a */; }; - DC48C40D1219E1A20047193B /* zbar-back.png in Resources */ = {isa = PBXBuildFile; fileRef = DC48C4081219E1A20047193B /* zbar-back.png */; }; - DC48C40E1219E1A20047193B /* zbar-help.html in Resources */ = {isa = PBXBuildFile; fileRef = DC48C4091219E1A20047193B /* zbar-help.html */; }; - DC48C40F1219E1A20047193B /* zbar-helpicons.png in Resources */ = {isa = PBXBuildFile; fileRef = DC48C40A1219E1A20047193B /* zbar-helpicons.png */; }; - DC48C4101219E1A20047193B /* zbar-samples.png in Resources */ = {isa = PBXBuildFile; fileRef = DC48C40B1219E1A20047193B /* zbar-samples.png */; }; + DC8F289413579EFF005B8862 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC8F289313579EFF005B8862 /* UIKit.framework */; }; + DC8F289613579EFF005B8862 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC8F289513579EFF005B8862 /* Foundation.framework */; }; + DC8F289813579EFF005B8862 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC8F289713579EFF005B8862 /* CoreGraphics.framework */; }; + DC8F289E13579EFF005B8862 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DC8F289C13579EFF005B8862 /* InfoPlist.strings */; }; + DC8F28A113579EFF005B8862 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DC8F28A013579EFF005B8862 /* main.m */; }; + DC8F28A413579EFF005B8862 /* ReaderSampleAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DC8F28A313579EFF005B8862 /* ReaderSampleAppDelegate.m */; }; + DC8F28A713579EFF005B8862 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = DC8F28A513579EFF005B8862 /* MainWindow.xib */; }; + DC8F28AA13579EFF005B8862 /* ReaderSampleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DC8F28A913579EFF005B8862 /* ReaderSampleViewController.m */; }; + DC8F28AD13579F00005B8862 /* ReaderSampleViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = DC8F28AB13579EFF005B8862 /* ReaderSampleViewController.xib */; }; + DC8F28D01357A29D005B8862 /* libzbar.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC8F28CA1357A29D005B8862 /* libzbar.a */; }; + DC8F28D11357A29D005B8862 /* zbar-back.png in Resources */ = {isa = PBXBuildFile; fileRef = DC8F28CC1357A29D005B8862 /* zbar-back.png */; }; + DC8F28D21357A29D005B8862 /* zbar-help.html in Resources */ = {isa = PBXBuildFile; fileRef = DC8F28CD1357A29D005B8862 /* zbar-help.html */; }; + DC8F28D31357A29D005B8862 /* zbar-helpicons.png in Resources */ = {isa = PBXBuildFile; fileRef = DC8F28CE1357A29D005B8862 /* zbar-helpicons.png */; }; + DC8F28D41357A29D005B8862 /* zbar-samples.png in Resources */ = {isa = PBXBuildFile; fileRef = DC8F28CF1357A29D005B8862 /* zbar-samples.png */; }; + DC8F28DA1357A42E005B8862 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC8F28D51357A42E005B8862 /* AVFoundation.framework */; }; + DC8F28DB1357A42E005B8862 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC8F28D61357A42E005B8862 /* CoreMedia.framework */; }; + DC8F28DC1357A42E005B8862 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC8F28D71357A42E005B8862 /* CoreVideo.framework */; }; + DC8F28DD1357A42E005B8862 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DC8F28D81357A42E005B8862 /* libiconv.dylib */; }; + DC8F28DE1357A42E005B8862 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC8F28D91357A42E005B8862 /* QuartzCore.framework */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 1D3623240D0F684500981E51 /* ReaderSampleAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReaderSampleAppDelegate.h; sourceTree = ""; }; - 1D3623250D0F684500981E51 /* ReaderSampleAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ReaderSampleAppDelegate.m; sourceTree = ""; }; - 1D6058910D05DD3D006BFB54 /* ReaderSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ReaderSample.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 288765A40DF7441C002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - 2899E5210DE3E06400AC0155 /* ReaderSampleViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ReaderSampleViewController.xib; sourceTree = ""; }; - 28AD733E0D9D9553002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; - 28D7ACF60DDB3853001CB0EB /* ReaderSampleViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReaderSampleViewController.h; sourceTree = ""; }; - 28D7ACF70DDB3853001CB0EB /* ReaderSampleViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ReaderSampleViewController.m; sourceTree = ""; }; - 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 32CA4F630368D1EE00C91783 /* ReaderSample_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReaderSample_Prefix.pch; sourceTree = ""; }; - 8D1107310486CEB800E47090 /* ReaderSample-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "ReaderSample-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = ""; }; - DC3CEC781209F83E00D7A786 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; - DC3CEC7A1209F83E00D7A786 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; }; - DC3CEC7C1209F83E00D7A786 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; }; - DC3CEC7E1209F83E00D7A786 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; - DC3CEC801209F83E00D7A786 /* libiconv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libiconv.dylib; path = usr/lib/libiconv.dylib; sourceTree = SDKROOT; }; - DC48C3F41219E1A20047193B /* Decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Decoder.h; sourceTree = ""; }; - DC48C3F51219E1A20047193B /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = ""; }; - DC48C3F61219E1A20047193B /* Image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Image.h; sourceTree = ""; }; - DC48C3F71219E1A20047193B /* ImageScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageScanner.h; sourceTree = ""; }; - DC48C3F81219E1A20047193B /* Processor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Processor.h; sourceTree = ""; }; - DC48C3F91219E1A20047193B /* Scanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Scanner.h; sourceTree = ""; }; - DC48C3FA1219E1A20047193B /* Symbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Symbol.h; sourceTree = ""; }; - DC48C3FB1219E1A20047193B /* Video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Video.h; sourceTree = ""; }; - DC48C3FC1219E1A20047193B /* Window.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Window.h; sourceTree = ""; }; - DC48C3FD1219E1A20047193B /* zbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zbar.h; sourceTree = ""; }; - DC48C3FE1219E1A20047193B /* ZBarCaptureReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarCaptureReader.h; sourceTree = ""; }; - DC48C3FF1219E1A20047193B /* ZBarImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarImage.h; sourceTree = ""; }; - DC48C4001219E1A20047193B /* ZBarImageScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarImageScanner.h; sourceTree = ""; }; - DC48C4011219E1A20047193B /* ZBarReaderController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarReaderController.h; sourceTree = ""; }; - DC48C4021219E1A20047193B /* ZBarReaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarReaderView.h; sourceTree = ""; }; - DC48C4031219E1A20047193B /* ZBarReaderViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarReaderViewController.h; sourceTree = ""; }; - DC48C4041219E1A20047193B /* ZBarSDK.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarSDK.h; sourceTree = ""; }; - DC48C4051219E1A20047193B /* ZBarSymbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarSymbol.h; sourceTree = ""; }; - DC48C4061219E1A20047193B /* libzbar.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libzbar.a; sourceTree = ""; }; - DC48C4081219E1A20047193B /* zbar-back.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "zbar-back.png"; sourceTree = ""; }; - DC48C4091219E1A20047193B /* zbar-help.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "zbar-help.html"; sourceTree = ""; }; - DC48C40A1219E1A20047193B /* zbar-helpicons.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "zbar-helpicons.png"; sourceTree = ""; }; - DC48C40B1219E1A20047193B /* zbar-samples.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "zbar-samples.png"; sourceTree = ""; }; + DC8F288F13579EFF005B8862 /* ReaderSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ReaderSample.app; sourceTree = BUILT_PRODUCTS_DIR; }; + DC8F289313579EFF005B8862 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + DC8F289513579EFF005B8862 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + DC8F289713579EFF005B8862 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + DC8F289B13579EFF005B8862 /* ReaderSample-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ReaderSample-Info.plist"; sourceTree = ""; }; + DC8F289D13579EFF005B8862 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + DC8F289F13579EFF005B8862 /* ReaderSample-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ReaderSample-Prefix.pch"; sourceTree = ""; }; + DC8F28A013579EFF005B8862 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + DC8F28A213579EFF005B8862 /* ReaderSampleAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReaderSampleAppDelegate.h; sourceTree = ""; }; + DC8F28A313579EFF005B8862 /* ReaderSampleAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ReaderSampleAppDelegate.m; sourceTree = ""; }; + DC8F28A613579EFF005B8862 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainWindow.xib; sourceTree = ""; }; + DC8F28A813579EFF005B8862 /* ReaderSampleViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReaderSampleViewController.h; sourceTree = ""; }; + DC8F28A913579EFF005B8862 /* ReaderSampleViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ReaderSampleViewController.m; sourceTree = ""; }; + DC8F28AC13579F00005B8862 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/ReaderSampleViewController.xib; sourceTree = ""; }; + DC8F28B71357A29D005B8862 /* Decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Decoder.h; sourceTree = ""; }; + DC8F28B81357A29D005B8862 /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = ""; }; + DC8F28B91357A29D005B8862 /* Image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Image.h; sourceTree = ""; }; + DC8F28BA1357A29D005B8862 /* ImageScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageScanner.h; sourceTree = ""; }; + DC8F28BB1357A29D005B8862 /* Processor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Processor.h; sourceTree = ""; }; + DC8F28BC1357A29D005B8862 /* Scanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Scanner.h; sourceTree = ""; }; + DC8F28BD1357A29D005B8862 /* Symbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Symbol.h; sourceTree = ""; }; + DC8F28BE1357A29D005B8862 /* Video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Video.h; sourceTree = ""; }; + DC8F28BF1357A29D005B8862 /* Window.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Window.h; sourceTree = ""; }; + DC8F28C01357A29D005B8862 /* zbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zbar.h; sourceTree = ""; }; + DC8F28C11357A29D005B8862 /* ZBarCaptureReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarCaptureReader.h; sourceTree = ""; }; + DC8F28C21357A29D005B8862 /* ZBarHelpController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarHelpController.h; sourceTree = ""; }; + DC8F28C31357A29D005B8862 /* ZBarImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarImage.h; sourceTree = ""; }; + DC8F28C41357A29D005B8862 /* ZBarImageScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarImageScanner.h; sourceTree = ""; }; + DC8F28C51357A29D005B8862 /* ZBarReaderController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarReaderController.h; sourceTree = ""; }; + DC8F28C61357A29D005B8862 /* ZBarReaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarReaderView.h; sourceTree = ""; }; + DC8F28C71357A29D005B8862 /* ZBarReaderViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarReaderViewController.h; sourceTree = ""; }; + DC8F28C81357A29D005B8862 /* ZBarSDK.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarSDK.h; sourceTree = ""; }; + DC8F28C91357A29D005B8862 /* ZBarSymbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarSymbol.h; sourceTree = ""; }; + DC8F28CA1357A29D005B8862 /* libzbar.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libzbar.a; sourceTree = ""; }; + DC8F28CC1357A29D005B8862 /* zbar-back.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "zbar-back.png"; sourceTree = ""; }; + DC8F28CD1357A29D005B8862 /* zbar-help.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "zbar-help.html"; sourceTree = ""; }; + DC8F28CE1357A29D005B8862 /* zbar-helpicons.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "zbar-helpicons.png"; sourceTree = ""; }; + DC8F28CF1357A29D005B8862 /* zbar-samples.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "zbar-samples.png"; sourceTree = ""; }; + DC8F28D51357A42E005B8862 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; + DC8F28D61357A42E005B8862 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; }; + DC8F28D71357A42E005B8862 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; }; + DC8F28D81357A42E005B8862 /* libiconv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libiconv.dylib; path = usr/lib/libiconv.dylib; sourceTree = SDKROOT; }; + DC8F28D91357A42E005B8862 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { + DC8F288C13579EFF005B8862 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, - 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */, - 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, - DC3CEC791209F83E00D7A786 /* AVFoundation.framework in Frameworks */, - DC3CEC7B1209F83E00D7A786 /* CoreMedia.framework in Frameworks */, - DC3CEC7D1209F83E00D7A786 /* CoreVideo.framework in Frameworks */, - DC3CEC7F1209F83E00D7A786 /* QuartzCore.framework in Frameworks */, - DC3CEC811209F83E00D7A786 /* libiconv.dylib in Frameworks */, - DC48C40C1219E1A20047193B /* libzbar.a in Frameworks */, + DC8F28DA1357A42E005B8862 /* AVFoundation.framework in Frameworks */, + DC8F28DB1357A42E005B8862 /* CoreMedia.framework in Frameworks */, + DC8F28DC1357A42E005B8862 /* CoreVideo.framework in Frameworks */, + DC8F28DD1357A42E005B8862 /* libiconv.dylib in Frameworks */, + DC8F28DE1357A42E005B8862 /* QuartzCore.framework in Frameworks */, + DC8F289413579EFF005B8862 /* UIKit.framework in Frameworks */, + DC8F289613579EFF005B8862 /* Foundation.framework in Frameworks */, + DC8F289813579EFF005B8862 /* CoreGraphics.framework in Frameworks */, + DC8F28D01357A29D005B8862 /* libzbar.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 080E96DDFE201D6D7F000001 /* Classes */ = { + DC8F288413579EFF005B8862 = { isa = PBXGroup; children = ( - 1D3623240D0F684500981E51 /* ReaderSampleAppDelegate.h */, - 1D3623250D0F684500981E51 /* ReaderSampleAppDelegate.m */, - 28D7ACF60DDB3853001CB0EB /* ReaderSampleViewController.h */, - 28D7ACF70DDB3853001CB0EB /* ReaderSampleViewController.m */, + DC8F289913579EFF005B8862 /* ReaderSample */, + DC8F289213579EFF005B8862 /* Frameworks */, + DC8F289013579EFF005B8862 /* Products */, ); - path = Classes; sourceTree = ""; }; - 19C28FACFE9D520D11CA2CBB /* Products */ = { + DC8F289013579EFF005B8862 /* Products */ = { isa = PBXGroup; children = ( - 1D6058910D05DD3D006BFB54 /* ReaderSample.app */, + DC8F288F13579EFF005B8862 /* ReaderSample.app */, ); name = Products; sourceTree = ""; }; - 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { + DC8F289213579EFF005B8862 /* Frameworks */ = { isa = PBXGroup; children = ( - 080E96DDFE201D6D7F000001 /* Classes */, - 29B97315FDCFA39411CA2CEA /* Other Sources */, - 29B97317FDCFA39411CA2CEA /* Resources */, - DC48C3F01219E1A20047193B /* ZBarSDK */, - 29B97323FDCFA39411CA2CEA /* Frameworks */, - 19C28FACFE9D520D11CA2CBB /* Products */, + DC8F289313579EFF005B8862 /* UIKit.framework */, + DC8F289513579EFF005B8862 /* Foundation.framework */, + DC8F289713579EFF005B8862 /* CoreGraphics.framework */, + DC8F28D91357A42E005B8862 /* QuartzCore.framework */, + DC8F28D61357A42E005B8862 /* CoreMedia.framework */, + DC8F28D71357A42E005B8862 /* CoreVideo.framework */, + DC8F28D51357A42E005B8862 /* AVFoundation.framework */, + DC8F28D81357A42E005B8862 /* libiconv.dylib */, ); - name = CustomTemplate; - sourceTree = ""; - }; - 29B97315FDCFA39411CA2CEA /* Other Sources */ = { - isa = PBXGroup; - children = ( - 32CA4F630368D1EE00C91783 /* ReaderSample_Prefix.pch */, - 29B97316FDCFA39411CA2CEA /* main.m */, - ); - name = "Other Sources"; + name = Frameworks; sourceTree = ""; }; - 29B97317FDCFA39411CA2CEA /* Resources */ = { + DC8F289913579EFF005B8862 /* ReaderSample */ = { isa = PBXGroup; children = ( - 2899E5210DE3E06400AC0155 /* ReaderSampleViewController.xib */, - 28AD733E0D9D9553002E5188 /* MainWindow.xib */, - 8D1107310486CEB800E47090 /* ReaderSample-Info.plist */, + DC8F28A213579EFF005B8862 /* ReaderSampleAppDelegate.h */, + DC8F28A313579EFF005B8862 /* ReaderSampleAppDelegate.m */, + DC8F28A513579EFF005B8862 /* MainWindow.xib */, + DC8F28A813579EFF005B8862 /* ReaderSampleViewController.h */, + DC8F28A913579EFF005B8862 /* ReaderSampleViewController.m */, + DC8F28AB13579EFF005B8862 /* ReaderSampleViewController.xib */, + DC8F289A13579EFF005B8862 /* Supporting Files */, + DC8F28B31357A29D005B8862 /* ZBarSDK */, ); - name = Resources; + path = ReaderSample; sourceTree = ""; }; - 29B97323FDCFA39411CA2CEA /* Frameworks */ = { + DC8F289A13579EFF005B8862 /* Supporting Files */ = { isa = PBXGroup; children = ( - 1D30AB110D05D00D00671497 /* Foundation.framework */, - 288765A40DF7441C002DB57D /* CoreGraphics.framework */, - 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, - DC3CEC7E1209F83E00D7A786 /* QuartzCore.framework */, - DC3CEC781209F83E00D7A786 /* AVFoundation.framework */, - DC3CEC7A1209F83E00D7A786 /* CoreMedia.framework */, - DC3CEC7C1209F83E00D7A786 /* CoreVideo.framework */, - DC3CEC801209F83E00D7A786 /* libiconv.dylib */, + DC8F289B13579EFF005B8862 /* ReaderSample-Info.plist */, + DC8F289C13579EFF005B8862 /* InfoPlist.strings */, + DC8F289F13579EFF005B8862 /* ReaderSample-Prefix.pch */, + DC8F28A013579EFF005B8862 /* main.m */, ); - name = Frameworks; + name = "Supporting Files"; sourceTree = ""; }; - DC48C3F01219E1A20047193B /* ZBarSDK */ = { + DC8F28B31357A29D005B8862 /* ZBarSDK */ = { isa = PBXGroup; children = ( - DC48C3F11219E1A20047193B /* Headers */, - DC48C4061219E1A20047193B /* libzbar.a */, - DC48C4071219E1A20047193B /* Resources */, + DC8F28B41357A29D005B8862 /* Headers */, + DC8F28CA1357A29D005B8862 /* libzbar.a */, + DC8F28CB1357A29D005B8862 /* Resources */, ); - path = ZBarSDK; + name = ZBarSDK; + path = "../../../build/Release-iphoneos/ZBarSDK"; sourceTree = ""; }; - DC48C3F11219E1A20047193B /* Headers */ = { + DC8F28B41357A29D005B8862 /* Headers */ = { isa = PBXGroup; children = ( - DC48C3F21219E1A20047193B /* ZBarSDK */, + DC8F28B51357A29D005B8862 /* ZBarSDK */, ); path = Headers; sourceTree = ""; }; - DC48C3F21219E1A20047193B /* ZBarSDK */ = { + DC8F28B51357A29D005B8862 /* ZBarSDK */ = { isa = PBXGroup; children = ( - DC48C3F31219E1A20047193B /* zbar */, - DC48C3FD1219E1A20047193B /* zbar.h */, - DC48C3FE1219E1A20047193B /* ZBarCaptureReader.h */, - DC48C3FF1219E1A20047193B /* ZBarImage.h */, - DC48C4001219E1A20047193B /* ZBarImageScanner.h */, - DC48C4011219E1A20047193B /* ZBarReaderController.h */, - DC48C4021219E1A20047193B /* ZBarReaderView.h */, - DC48C4031219E1A20047193B /* ZBarReaderViewController.h */, - DC48C4041219E1A20047193B /* ZBarSDK.h */, - DC48C4051219E1A20047193B /* ZBarSymbol.h */, + DC8F28B61357A29D005B8862 /* zbar */, + DC8F28C01357A29D005B8862 /* zbar.h */, + DC8F28C11357A29D005B8862 /* ZBarCaptureReader.h */, + DC8F28C21357A29D005B8862 /* ZBarHelpController.h */, + DC8F28C31357A29D005B8862 /* ZBarImage.h */, + DC8F28C41357A29D005B8862 /* ZBarImageScanner.h */, + DC8F28C51357A29D005B8862 /* ZBarReaderController.h */, + DC8F28C61357A29D005B8862 /* ZBarReaderView.h */, + DC8F28C71357A29D005B8862 /* ZBarReaderViewController.h */, + DC8F28C81357A29D005B8862 /* ZBarSDK.h */, + DC8F28C91357A29D005B8862 /* ZBarSymbol.h */, ); path = ZBarSDK; sourceTree = ""; }; - DC48C3F31219E1A20047193B /* zbar */ = { + DC8F28B61357A29D005B8862 /* zbar */ = { isa = PBXGroup; children = ( - DC48C3F41219E1A20047193B /* Decoder.h */, - DC48C3F51219E1A20047193B /* Exception.h */, - DC48C3F61219E1A20047193B /* Image.h */, - DC48C3F71219E1A20047193B /* ImageScanner.h */, - DC48C3F81219E1A20047193B /* Processor.h */, - DC48C3F91219E1A20047193B /* Scanner.h */, - DC48C3FA1219E1A20047193B /* Symbol.h */, - DC48C3FB1219E1A20047193B /* Video.h */, - DC48C3FC1219E1A20047193B /* Window.h */, + DC8F28B71357A29D005B8862 /* Decoder.h */, + DC8F28B81357A29D005B8862 /* Exception.h */, + DC8F28B91357A29D005B8862 /* Image.h */, + DC8F28BA1357A29D005B8862 /* ImageScanner.h */, + DC8F28BB1357A29D005B8862 /* Processor.h */, + DC8F28BC1357A29D005B8862 /* Scanner.h */, + DC8F28BD1357A29D005B8862 /* Symbol.h */, + DC8F28BE1357A29D005B8862 /* Video.h */, + DC8F28BF1357A29D005B8862 /* Window.h */, ); path = zbar; sourceTree = ""; }; - DC48C4071219E1A20047193B /* Resources */ = { + DC8F28CB1357A29D005B8862 /* Resources */ = { isa = PBXGroup; children = ( - DC48C4081219E1A20047193B /* zbar-back.png */, - DC48C4091219E1A20047193B /* zbar-help.html */, - DC48C40A1219E1A20047193B /* zbar-helpicons.png */, - DC48C40B1219E1A20047193B /* zbar-samples.png */, + DC8F28CC1357A29D005B8862 /* zbar-back.png */, + DC8F28CD1357A29D005B8862 /* zbar-help.html */, + DC8F28CE1357A29D005B8862 /* zbar-helpicons.png */, + DC8F28CF1357A29D005B8862 /* zbar-samples.png */, ); path = Resources; sourceTree = ""; @@ -222,13 +219,13 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 1D6058900D05DD3D006BFB54 /* ReaderSample */ = { + DC8F288E13579EFF005B8862 /* ReaderSample */ = { isa = PBXNativeTarget; - buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "ReaderSample" */; + buildConfigurationList = DC8F28B013579F00005B8862 /* Build configuration list for PBXNativeTarget "ReaderSample" */; buildPhases = ( - 1D60588D0D05DD3D006BFB54 /* Resources */, - 1D60588E0D05DD3D006BFB54 /* Sources */, - 1D60588F0D05DD3D006BFB54 /* Frameworks */, + DC8F288B13579EFF005B8862 /* Sources */, + DC8F288C13579EFF005B8862 /* Frameworks */, + DC8F288D13579EFF005B8862 /* Resources */, ); buildRules = ( ); @@ -236,151 +233,181 @@ ); name = ReaderSample; productName = ReaderSample; - productReference = 1D6058910D05DD3D006BFB54 /* ReaderSample.app */; + productReference = DC8F288F13579EFF005B8862 /* ReaderSample.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - 29B97313FDCFA39411CA2CEA /* Project object */ = { + DC8F288613579EFF005B8862 /* Project object */ = { isa = PBXProject; - buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ReaderSample" */; - compatibilityVersion = "Xcode 3.1"; + attributes = { + ORGANIZATIONNAME = "ZBar Consulting Services"; + }; + buildConfigurationList = DC8F288913579EFF005B8862 /* Build configuration list for PBXProject "ReaderSample" */; + compatibilityVersion = "Xcode 3.2"; developmentRegion = English; - hasScannedForEncodings = 1; + hasScannedForEncodings = 0; knownRegions = ( - English, - Japanese, - French, - German, + en, ); - mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; + mainGroup = DC8F288413579EFF005B8862; + productRefGroup = DC8F289013579EFF005B8862 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - 1D6058900D05DD3D006BFB54 /* ReaderSample */, + DC8F288E13579EFF005B8862 /* ReaderSample */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 1D60588D0D05DD3D006BFB54 /* Resources */ = { + DC8F288D13579EFF005B8862 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */, - 2899E5220DE3E06400AC0155 /* ReaderSampleViewController.xib in Resources */, - DC48C40D1219E1A20047193B /* zbar-back.png in Resources */, - DC48C40E1219E1A20047193B /* zbar-help.html in Resources */, - DC48C40F1219E1A20047193B /* zbar-helpicons.png in Resources */, - DC48C4101219E1A20047193B /* zbar-samples.png in Resources */, + DC8F289E13579EFF005B8862 /* InfoPlist.strings in Resources */, + DC8F28A713579EFF005B8862 /* MainWindow.xib in Resources */, + DC8F28AD13579F00005B8862 /* ReaderSampleViewController.xib in Resources */, + DC8F28D11357A29D005B8862 /* zbar-back.png in Resources */, + DC8F28D21357A29D005B8862 /* zbar-help.html in Resources */, + DC8F28D31357A29D005B8862 /* zbar-helpicons.png in Resources */, + DC8F28D41357A29D005B8862 /* zbar-samples.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 1D60588E0D05DD3D006BFB54 /* Sources */ = { + DC8F288B13579EFF005B8862 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 1D60589B0D05DD56006BFB54 /* main.m in Sources */, - 1D3623260D0F684500981E51 /* ReaderSampleAppDelegate.m in Sources */, - 28D7ACF80DDB3853001CB0EB /* ReaderSampleViewController.m in Sources */, + DC8F28A113579EFF005B8862 /* main.m in Sources */, + DC8F28A413579EFF005B8862 /* ReaderSampleAppDelegate.m in Sources */, + DC8F28AA13579EFF005B8862 /* ReaderSampleViewController.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ -/* Begin XCBuildConfiguration section */ - 1D6058940D05DD3E006BFB54 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = ReaderSample_Prefix.pch; - INFOPLIST_FILE = "ReaderSample-Info.plist"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/ZBarSDK\"", - ); - PRODUCT_NAME = ReaderSample; - SYMROOT = /tmp/ReaderSample.build; - }; - name = Debug; +/* Begin PBXVariantGroup section */ + DC8F289C13579EFF005B8862 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + DC8F289D13579EFF005B8862 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; }; - 1D6058950D05DD3E006BFB54 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = ReaderSample_Prefix.pch; - INFOPLIST_FILE = "ReaderSample-Info.plist"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/ZBarSDK\"", - ); - PRODUCT_NAME = ReaderSample; - SYMROOT = /tmp/ReaderSample.build; - VALIDATE_PRODUCT = YES; - }; - name = Release; + DC8F28A513579EFF005B8862 /* MainWindow.xib */ = { + isa = PBXVariantGroup; + children = ( + DC8F28A613579EFF005B8862 /* en */, + ); + name = MainWindow.xib; + sourceTree = ""; }; - C01FCF4F08A954540054247B /* Debug */ = { + DC8F28AB13579EFF005B8862 /* ReaderSampleViewController.xib */ = { + isa = PBXVariantGroup; + children = ( + DC8F28AC13579F00005B8862 /* en */, + ); + name = ReaderSampleViewController.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + DC8F28AE13579F00005B8862 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT)"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_C_LANGUAGE_STANDARD = c99; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = DEBUG; + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvmgcc42; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 4.0; - PREBINDING = NO; SDKROOT = iphoneos; }; name = Debug; }; - C01FCF5008A954540054247B /* Release */ = { + DC8F28AF13579F00005B8862 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT)"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_C_LANGUAGE_STANDARD = c99; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_VERSION = com.apple.compilers.llvmgcc42; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 4.0; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; - PREBINDING = NO; SDKROOT = iphoneos; }; name = Release; }; + DC8F28B113579F00005B8862 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "ReaderSample/ReaderSample-Prefix.pch"; + INFOPLIST_FILE = "ReaderSample/ReaderSample-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/../../build/Release-iphoneos/ZBarSDK\"", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + DC8F28B213579F00005B8862 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "ReaderSample/ReaderSample-Prefix.pch"; + INFOPLIST_FILE = "ReaderSample/ReaderSample-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/../../build/Release-iphoneos/ZBarSDK\"", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + VALIDATE_PRODUCT = YES; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "ReaderSample" */ = { + DC8F288913579EFF005B8862 /* Build configuration list for PBXProject "ReaderSample" */ = { isa = XCConfigurationList; buildConfigurations = ( - 1D6058940D05DD3E006BFB54 /* Debug */, - 1D6058950D05DD3E006BFB54 /* Release */, + DC8F28AE13579F00005B8862 /* Debug */, + DC8F28AF13579F00005B8862 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ReaderSample" */ = { + DC8F28B013579F00005B8862 /* Build configuration list for PBXNativeTarget "ReaderSample" */ = { isa = XCConfigurationList; buildConfigurations = ( - C01FCF4F08A954540054247B /* Debug */, - C01FCF5008A954540054247B /* Release */, + DC8F28B113579F00005B8862 /* Debug */, + DC8F28B213579F00005B8862 /* Release */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; - rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; + rootObject = DC8F288613579EFF005B8862 /* Project object */; } diff --git a/iphone/examples/ReaderSample/ReaderSample-Info.plist b/iphone/examples/ReaderSample/ReaderSample/ReaderSample-Info.plist similarity index 74% rename from iphone/examples/ReaderSample/ReaderSample-Info.plist rename to iphone/examples/ReaderSample/ReaderSample/ReaderSample-Info.plist index 3289444..4ceba32 100644 --- a/iphone/examples/ReaderSample/ReaderSample-Info.plist +++ b/iphone/examples/ReaderSample/ReaderSample/ReaderSample-Info.plist @@ -3,7 +3,7 @@ CFBundleDevelopmentRegion - English + en CFBundleDisplayName ${PRODUCT_NAME} CFBundleExecutable @@ -18,6 +18,8 @@ ${PRODUCT_NAME} CFBundlePackageType APPL + CFBundleShortVersionString + 1.0 CFBundleSignature ???? CFBundleVersion @@ -26,5 +28,11 @@ NSMainNibFile MainWindow + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + diff --git a/iphone/examples/ReaderSample/ReaderSample/ReaderSample-Prefix.pch b/iphone/examples/ReaderSample/ReaderSample/ReaderSample-Prefix.pch new file mode 100644 index 0000000..2b3e510 --- /dev/null +++ b/iphone/examples/ReaderSample/ReaderSample/ReaderSample-Prefix.pch @@ -0,0 +1,16 @@ +// +// Prefix header for all source files of the 'ReaderSample' target in the 'ReaderSample' project +// + +#import + +#ifndef __IPHONE_3_0 +#warning "This project uses features only available in iPhone SDK 3.0 and later." +#endif + +#ifdef __OBJC__ + #import + #import + // ADD: import barcode reader APIs + #import "ZBarSDK.h" +#endif diff --git a/iphone/examples/ReaderSample/Classes/ReaderSampleAppDelegate.h b/iphone/examples/ReaderSample/ReaderSample/ReaderSampleAppDelegate.h similarity index 76% rename from iphone/examples/ReaderSample/Classes/ReaderSampleAppDelegate.h rename to iphone/examples/ReaderSample/ReaderSample/ReaderSampleAppDelegate.h index 7fe8eec..44fc3e7 100644 --- a/iphone/examples/ReaderSample/Classes/ReaderSampleAppDelegate.h +++ b/iphone/examples/ReaderSample/ReaderSample/ReaderSampleAppDelegate.h @@ -2,7 +2,7 @@ // ReaderSampleAppDelegate.h // ReaderSample // -// Created by spadix on 8/4/10. +// Created by spadix on 4/14/11. // #import @@ -10,12 +10,11 @@ @class ReaderSampleViewController; @interface ReaderSampleAppDelegate : NSObject { - UIWindow *window; - ReaderSampleViewController *viewController; + } @property (nonatomic, retain) IBOutlet UIWindow *window; + @property (nonatomic, retain) IBOutlet ReaderSampleViewController *viewController; @end - diff --git a/iphone/examples/ReaderSample/Classes/ReaderSampleAppDelegate.m b/iphone/examples/ReaderSample/ReaderSample/ReaderSampleAppDelegate.m similarity index 59% rename from iphone/examples/ReaderSample/Classes/ReaderSampleAppDelegate.m rename to iphone/examples/ReaderSample/ReaderSample/ReaderSampleAppDelegate.m index cdf4456..e765ec5 100644 --- a/iphone/examples/ReaderSample/Classes/ReaderSampleAppDelegate.m +++ b/iphone/examples/ReaderSample/ReaderSample/ReaderSampleAppDelegate.m @@ -2,85 +2,73 @@ // ReaderSampleAppDelegate.m // ReaderSample // -// Created by spadix on 8/4/10. +// Created by spadix on 4/14/11. // #import "ReaderSampleAppDelegate.h" + #import "ReaderSampleViewController.h" @implementation ReaderSampleAppDelegate -@synthesize window; -@synthesize viewController; +@synthesize window=_window; -#pragma mark - -#pragma mark Application lifecycle +@synthesize viewController=_viewController; -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ // Override point for customization after application launch. - - // Add the view controller's view to the window and display. - [window addSubview:viewController.view]; - [window makeKeyAndVisible]; - + + self.window.rootViewController = self.viewController; + [self.window makeKeyAndVisible]; return YES; } - -- (void)applicationWillResignActive:(UIApplication *)application { +- (void)applicationWillResignActive:(UIApplication *)application +{ /* Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. */ } - -- (void)applicationDidEnterBackground:(UIApplication *)application { +- (void)applicationDidEnterBackground:(UIApplication *)application +{ /* Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - If your application supports background execution, called instead of applicationWillTerminate: when the user quits. + If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. */ } - -- (void)applicationWillEnterForeground:(UIApplication *)application { +- (void)applicationWillEnterForeground:(UIApplication *)application +{ /* - Called as part of transition from the background to the inactive state: here you can undo many of the changes made on entering the background. + Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. */ } - -- (void)applicationDidBecomeActive:(UIApplication *)application { +- (void)applicationDidBecomeActive:(UIApplication *)application +{ /* Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. */ } - -- (void)applicationWillTerminate:(UIApplication *)application { +- (void)applicationWillTerminate:(UIApplication *)application +{ /* Called when the application is about to terminate. + Save data if appropriate. See also applicationDidEnterBackground:. */ } - -#pragma mark - -#pragma mark Memory management - -- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { - /* - Free up as much memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later. - */ -} - - -- (void)dealloc { - [viewController release]; - [window release]; +- (void)dealloc +{ + [_window release]; + [_viewController release]; [super dealloc]; } - @end diff --git a/iphone/examples/ReaderSample/Classes/ReaderSampleViewController.h b/iphone/examples/ReaderSample/ReaderSample/ReaderSampleViewController.h similarity index 92% rename from iphone/examples/ReaderSample/Classes/ReaderSampleViewController.h rename to iphone/examples/ReaderSample/ReaderSample/ReaderSampleViewController.h index e9763cf..504180a 100644 --- a/iphone/examples/ReaderSample/Classes/ReaderSampleViewController.h +++ b/iphone/examples/ReaderSample/ReaderSample/ReaderSampleViewController.h @@ -2,7 +2,7 @@ // ReaderSampleViewController.h // ReaderSample // -// Created by spadix on 8/4/10. +// Created by spadix on 4/14/11. // #import diff --git a/iphone/examples/ReaderSample/Classes/ReaderSampleViewController.m b/iphone/examples/ReaderSample/ReaderSample/ReaderSampleViewController.m similarity index 75% rename from iphone/examples/ReaderSample/Classes/ReaderSampleViewController.m rename to iphone/examples/ReaderSample/ReaderSample/ReaderSampleViewController.m index 0e412ac..8007684 100644 --- a/iphone/examples/ReaderSample/Classes/ReaderSampleViewController.m +++ b/iphone/examples/ReaderSample/ReaderSample/ReaderSampleViewController.m @@ -2,7 +2,7 @@ // ReaderSampleViewController.m // ReaderSample // -// Created by spadix on 8/4/10. +// Created by spadix on 4/14/11. // #import "ReaderSampleViewController.h" @@ -22,12 +22,12 @@ - (IBAction) scanButtonTapped // EXAMPLE: disable rarely used I2/5 to improve performance [scanner setSymbology: ZBAR_I25 - config: ZBAR_CFG_ENABLE - to: 0]; + config: ZBAR_CFG_ENABLE + to: 0]; // present and release the controller [self presentModalViewController: reader - animated: YES]; + animated: YES]; [reader release]; } @@ -36,7 +36,7 @@ - (void) imagePickerController: (UIImagePickerController*) reader { // ADD: get the decode results id results = - [info objectForKey: ZBarReaderControllerResults]; + [info objectForKey: ZBarReaderControllerResults]; ZBarSymbol *symbol = nil; for(symbol in results) // EXAMPLE: just grab the first barcode @@ -47,19 +47,13 @@ - (void) imagePickerController: (UIImagePickerController*) reader // EXAMPLE: do something useful with the barcode image resultImage.image = - [info objectForKey: UIImagePickerControllerOriginalImage]; + [info objectForKey: UIImagePickerControllerOriginalImage]; // ADD: dismiss the controller (NB dismiss from the *reader*!) [reader dismissModalViewControllerAnimated: YES]; } -- (void)didReceiveMemoryWarning { - // Releases the view if it doesn't have a superview. - [super didReceiveMemoryWarning]; - // Release any cached data, images, etc that aren't in use. -} - -- (void)dealloc { +- (void) dealloc { self.resultImage = nil; self.resultText = nil; [super dealloc]; diff --git a/iphone/examples/ReaderSample/ReaderSample/en.lproj/InfoPlist.strings b/iphone/examples/ReaderSample/ReaderSample/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..477b28f --- /dev/null +++ b/iphone/examples/ReaderSample/ReaderSample/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/iphone/examples/ReaderSample/MainWindow.xib b/iphone/examples/ReaderSample/ReaderSample/en.lproj/MainWindow.xib similarity index 99% rename from iphone/examples/ReaderSample/MainWindow.xib rename to iphone/examples/ReaderSample/ReaderSample/en.lproj/MainWindow.xib index eda55c2..3b45763 100644 --- a/iphone/examples/ReaderSample/MainWindow.xib +++ b/iphone/examples/ReaderSample/ReaderSample/en.lproj/MainWindow.xib @@ -223,7 +223,7 @@
IBProjectSource - Classes/ReaderSampleAppDelegate.h + ReaderSampleAppDelegate.h
@@ -239,7 +239,7 @@ UIViewController IBProjectSource - Classes/ReaderSampleViewController.h + ReaderSampleViewController.h
diff --git a/iphone/examples/ReaderSample/ReaderSample/en.lproj/ReaderSampleViewController.xib b/iphone/examples/ReaderSample/ReaderSample/en.lproj/ReaderSampleViewController.xib new file mode 100644 index 0000000..846d96f --- /dev/null +++ b/iphone/examples/ReaderSample/ReaderSample/en.lproj/ReaderSampleViewController.xib @@ -0,0 +1,320 @@ + + + + 1056 + 10J869 + 1306 + 1038.35 + 461.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 301 + + + YES + IBUITextView + IBUIButton + IBUIImageView + IBUIView + IBProxyObject + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + + + YES + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + + 274 + + YES + + + 292 + {{20, 396}, {280, 44}} + + + + NO + IBCocoaTouchFramework + 0 + 0 + + Helvetica-Bold + 19 + 16 + + 1 + Scan + + 3 + MQA + + + 1 + MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + + + 3 + MC41AA + + + + + 292 + {{20, 20}, {280, 210}} + + + + 1 + NO + IBCocoaTouchFramework + + + + 292 + {{20, 238}, {280, 150}} + + + + + 3 + MCAwAA + + YES + YES + IBCocoaTouchFramework + NO + No barcode scanned... + + Helvetica + 17 + 16 + + + 2 + IBCocoaTouchFramework + + + + {{0, 20}, {320, 460}} + + + + + 3 + MC43NQA + + 2 + + + NO + + IBCocoaTouchFramework + + + + + YES + + + view + + + + 7 + + + + resultImage + + + + 11 + + + + resultText + + + + 12 + + + + scanButtonTapped + + + 7 + + 13 + + + + + YES + + 0 + + + + + + -1 + + + File's Owner + + + -2 + + + + + 6 + + + YES + + + + + + + + 8 + + + + + 9 + + + + + 10 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 10.IBPluginDependency + 6.IBEditorWindowLastContentRect + 6.IBPluginDependency + 8.IBPluginDependency + 9.IBPluginDependency + + + YES + ReaderSampleViewController + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + {{239, 654}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + + + + YES + + + + + 13 + + + + YES + + ReaderSampleViewController + UIViewController + + scanButtonTapped + id + + + scanButtonTapped + + scanButtonTapped + id + + + + YES + + YES + resultImage + resultText + + + YES + UIImageView + UITextView + + + + YES + + YES + resultImage + resultText + + + YES + + resultImage + UIImageView + + + resultText + UITextView + + + + + IBProjectSource + ./Classes/ReaderSampleViewController.h + + + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + 3 + 301 + + diff --git a/iphone/examples/ReaderSample/main.m b/iphone/examples/ReaderSample/ReaderSample/main.m similarity index 54% rename from iphone/examples/ReaderSample/main.m rename to iphone/examples/ReaderSample/ReaderSample/main.m index 843293a..4a373e4 100644 --- a/iphone/examples/ReaderSample/main.m +++ b/iphone/examples/ReaderSample/ReaderSample/main.m @@ -2,13 +2,14 @@ // main.m // ReaderSample // -// Created by spadix on 8/4/10. +// Created by spadix on 4/14/11. // #import -int main(int argc, char *argv[]) { - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; +int main(int argc, char *argv[]) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; int retVal = UIApplicationMain(argc, argv, nil, nil); [pool release]; return retVal; diff --git a/iphone/examples/ReaderSample/ReaderSampleViewController.xib b/iphone/examples/ReaderSample/ReaderSampleViewController.xib deleted file mode 100644 index 5f522f4..0000000 --- a/iphone/examples/ReaderSample/ReaderSampleViewController.xib +++ /dev/null @@ -1,521 +0,0 @@ - - - - 1024 - 10F569 - 788 - 1038.29 - 461.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 117 - - - YES - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - YES - - - YES - - - - YES - - IBFilesOwner - IBCocoaTouchFramework - - - IBFirstResponder - IBCocoaTouchFramework - - - - 274 - - YES - - - 292 - {{20, 392}, {280, 48}} - - NO - IBCocoaTouchFramework - 0 - 0 - - Helvetica-Bold - 18 - 16 - - 1 - Scan - - 3 - MQA - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - 3 - MC41AA - - - - - 292 - {{20, 20}, {280, 210}} - - 1 - NO - IBCocoaTouchFramework - - - - 292 - {{20, 238}, {280, 146}} - - - 3 - MCAwAA - - NO - YES - YES - IBCocoaTouchFramework - NO - No barcode scanned - - 2 - IBCocoaTouchFramework - - - - {320, 460} - - - 3 - MC43NQA - - 2 - - - NO - - IBCocoaTouchFramework - - - - - YES - - - view - - - - 7 - - - - resultImage - - - - 11 - - - - resultText - - - - 12 - - - - scanButtonTapped - - - 7 - - 13 - - - - - YES - - 0 - - - - - - -1 - - - File's Owner - - - -2 - - - - - 6 - - - YES - - - - - - - - 8 - - - - - 9 - - - - - 10 - - - - - - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 10.IBPluginDependency - 6.IBEditorWindowLastContentRect - 6.IBPluginDependency - 8.IBPluginDependency - 9.IBPluginDependency - - - YES - ReaderSampleViewController - UIResponder - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - {{239, 276}, {320, 480}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - - YES - - - - - YES - - - YES - - - - 13 - - - - YES - - ReaderSampleViewController - UIViewController - - scanButtonTapped - id - - - scanButtonTapped - - scanButtonTapped - id - - - - YES - - YES - resultImage - resultText - - - YES - UIImageView - UITextView - - - - YES - - YES - resultImage - resultText - - - YES - - resultImage - UIImageView - - - resultText - UITextView - - - - - IBProjectSource - Classes/ReaderSampleViewController.h - - - - - YES - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIAccessibility.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UINibLoading.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIResponder.h - - - - UIButton - UIControl - - IBFrameworkSource - UIKit.framework/Headers/UIButton.h - - - - UIControl - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIControl.h - - - - UIImageView - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIImageView.h - - - - UIResponder - NSObject - - - - UIScrollView - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIScrollView.h - - - - UISearchBar - UIView - - IBFrameworkSource - UIKit.framework/Headers/UISearchBar.h - - - - UISearchDisplayController - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UISearchDisplayController.h - - - - UITextView - UIScrollView - - IBFrameworkSource - UIKit.framework/Headers/UITextView.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UITextField.h - - - - UIView - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIView.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UINavigationController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UIPopoverController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UISplitViewController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UITabBarController.h - - - - UIViewController - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIViewController.h - - - - - 0 - IBCocoaTouchFramework - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - - - YES - ReaderSample.xcodeproj - 3 - 117 - - diff --git a/iphone/examples/ReaderSample/ReaderSample_Prefix.pch b/iphone/examples/ReaderSample/ReaderSample_Prefix.pch deleted file mode 100644 index 66bf51a..0000000 --- a/iphone/examples/ReaderSample/ReaderSample_Prefix.pch +++ /dev/null @@ -1,11 +0,0 @@ -// -// Prefix header for all source files of the 'ReaderSample' target in the 'ReaderSample' project -// - -#ifdef __OBJC__ -# import -# import - -// ADD: barcode reader APIs -# import "ZBarSDK.h" -#endif diff --git a/iphone/examples/readertest/readertest.xcodeproj/xcshareddata/xcschemes/readertest.xcscheme b/iphone/examples/readertest/readertest.xcodeproj/xcshareddata/xcschemes/readertest.xcscheme new file mode 100644 index 0000000..9264466 --- /dev/null +++ b/iphone/examples/readertest/readertest.xcodeproj/xcshareddata/xcschemes/readertest.xcscheme @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iphone/res/ZBarSDK-Info.plist b/iphone/res/ZBarSDK-Info.plist index 3ce3bf0..bcfbde8 100644 --- a/iphone/res/ZBarSDK-Info.plist +++ b/iphone/res/ZBarSDK-Info.plist @@ -7,7 +7,7 @@ CFBundleName ZBarSDK CFBundleVersion - 1.1 + 1.1.1 CFBundleSignature ???? NSHumanReadableCopyright diff --git a/iphone/zbar.xcodeproj/xcshareddata/xcschemes/ZBarSDK.dmg.xcscheme b/iphone/zbar.xcodeproj/xcshareddata/xcschemes/ZBarSDK.dmg.xcscheme new file mode 100644 index 0000000..6266dd1 --- /dev/null +++ b/iphone/zbar.xcodeproj/xcshareddata/xcschemes/ZBarSDK.dmg.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iphone/zbar.xcodeproj/xcshareddata/xcschemes/ZBarSDK.xcscheme b/iphone/zbar.xcodeproj/xcshareddata/xcschemes/ZBarSDK.xcscheme new file mode 100644 index 0000000..55974d5 --- /dev/null +++ b/iphone/zbar.xcodeproj/xcshareddata/xcschemes/ZBarSDK.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iphone/zbar.xcodeproj/xcshareddata/xcschemes/libzbar.xcscheme b/iphone/zbar.xcodeproj/xcshareddata/xcschemes/libzbar.xcscheme new file mode 100644 index 0000000..07cb0e8 --- /dev/null +++ b/iphone/zbar.xcodeproj/xcshareddata/xcschemes/libzbar.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iphone/zbar.xcodeproj/xcshareddata/xcschemes/readertest.xcscheme b/iphone/zbar.xcodeproj/xcshareddata/xcschemes/readertest.xcscheme new file mode 100644 index 0000000..256e1b5 --- /dev/null +++ b/iphone/zbar.xcodeproj/xcshareddata/xcschemes/readertest.xcscheme @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 1bdf60b373d943734a9f44833f1e1757df6695e5 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 14 Apr 2011 17:09:57 -0700 Subject: [PATCH 272/328] iPhone: enhance readertest to support default/demo pre-config and distribution --- iphone/ChangeLog | 1 + iphone/examples/readertest/readertest.m | 146 ++++++++++++------ .../readertest.xcodeproj/project.pbxproj | 2 + iphone/zbar.xcodeproj/project.pbxproj | 123 ++++++++++++--- .../xcschemes/readertest.xcscheme | 9 +- 5 files changed, 208 insertions(+), 73 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 3008050..7631dc6 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,5 @@ current: + * enhance readertest to support default/demo pre-config and distribution * updates for Xcode 4 * expose tracking box color diff --git a/iphone/examples/readertest/readertest.m b/iphone/examples/readertest/readertest.m index 7bbe1b0..0373a23 100644 --- a/iphone/examples/readertest/readertest.m +++ b/iphone/examples/readertest/readertest.m @@ -1,7 +1,3 @@ -#if 0 -# define VALGRIND "/usr/local/bin/valgrind" -#endif - enum { CLASS_SECTION = 0, SOURCE_SECTION, @@ -46,7 +42,11 @@ @interface AppDelegate UIWindow *window; UINavigationController *nav; + NSSet *defaultSymbologies; + CGFloat defaultZoom; + NSMutableArray *sections, *symbolEnables; + NSInteger xDensity, yDensity; BOOL found, paused, continuous; NSInteger dataHeight; @@ -67,18 +67,49 @@ @implementation AppDelegate - (id) init { - // force these classes to load - [ZBarReaderViewController class]; - [ZBarReaderController class]; - return([super initWithStyle: UITableViewStyleGrouped]); } - (void) initReader: (NSString*) clsName { [reader release]; - reader = [NSClassFromString(clsName) new]; + Class cls = [[NSBundle mainBundle] + classNamed: clsName]; + assert(cls); + reader = [cls new]; + assert(reader); reader.readerDelegate = self; + xDensity = yDensity = 3; + +#if 0 + // apply defaults for demo + ZBarImageScanner *scanner = reader.scanner; + continuous = NO; + defaultZoom = 1; + reader.showsZBarControls = NO; + reader.scanCrop = CGRectMake(0, .35, 1, .3); + + [defaultSymbologies release]; + defaultSymbologies = + [[NSSet alloc] + initWithObjects: + [NSNumber numberWithInteger: ZBAR_CODE128], + nil]; + [scanner setSymbology: 0 + config: ZBAR_CFG_ENABLE + to: 0]; + for(NSNumber *sym in defaultSymbologies) + [scanner setSymbology: sym.integerValue + config: ZBAR_CFG_ENABLE + to: 1]; + + [scanner setSymbology: 0 + config: ZBAR_CFG_X_DENSITY + to: (xDensity = 0)]; + [scanner setSymbology: 0 + config: ZBAR_CFG_Y_DENSITY + to: (yDensity = 1)]; +#endif } - (void) initOverlay @@ -189,6 +220,28 @@ - (void) initOverlay [overlay addSubview: info]; } +- (void) updateCropMask +{ + CGRect r = reader.scanCrop; + r.origin.x *= 426; + r.origin.y *= 320; + r.size.width *= 426; + r.size.height *= 320; + UIView *mask = [masks objectAtIndex: 0]; + mask.frame = CGRectMake(0, -426, 320, r.origin.x); + mask = [masks objectAtIndex: 1]; + mask.frame = CGRectMake(0, r.origin.x - 426, r.origin.y, r.size.width); + + r.origin.y += r.size.height; + mask = [masks objectAtIndex: 2]; + mask.frame = CGRectMake(r.origin.y, r.origin.x - 426, + 320 - r.origin.y, r.size.width); + + r.origin.x += r.size.width; + mask = [masks objectAtIndex: 3]; + mask.frame = CGRectMake(0, r.origin.x - 426, 320, 426 - r.origin.x); +} + - (void) setCheck: (BOOL) state forCell: (UITableViewCell*) cell { @@ -293,7 +346,7 @@ - (void) initControlCells reuseIdentifier: nil] autorelease]; cropCell.textLabel.text = @"scanCrop"; - cropCell.detailTextLabel.text = NSStringFromCGRect(crop_choices[0]); + cropCell.detailTextLabel.text = NSStringFromCGRect(reader.scanCrop); UITableViewCell *xDensityCell = [[[UITableViewCell alloc] @@ -303,7 +356,7 @@ - (void) initControlCells xDensityCell.textLabel.text = @"CFG_X_DENSITY"; xDensityCell.detailTextLabel.tag = ZBAR_CFG_X_DENSITY; xDensityCell.detailTextLabel.text = - [NSString stringWithFormat: @"%d", density_choices[0]]; + [NSString stringWithFormat: @"%d", xDensity]; UITableViewCell *yDensityCell = [[[UITableViewCell alloc] @@ -313,7 +366,7 @@ - (void) initControlCells yDensityCell.textLabel.text = @"CFG_Y_DENSITY"; yDensityCell.detailTextLabel.tag = ZBAR_CFG_Y_DENSITY; yDensityCell.detailTextLabel.text = - [NSString stringWithFormat: @"%d", density_choices[0]]; + [NSString stringWithFormat: @"%d", yDensity]; [sections replaceObjectAtIndex: CUSTOM_SECTION withObject: [NSArray arrayWithObjects: @@ -325,25 +378,30 @@ - (void) initControlCells checked: continuous], nil]]; - static const int symbolValues[] = { + static const zbar_symbol_type_t allSymbologies[] = { ZBAR_QRCODE, ZBAR_CODE128, ZBAR_CODE93, ZBAR_CODE39, ZBAR_I25, ZBAR_DATABAR, ZBAR_DATABAR_EXP, ZBAR_EAN13, ZBAR_EAN8, - ZBAR_EAN2, ZBAR_EAN5, ZBAR_COMPOSITE, - ZBAR_UPCA, ZBAR_UPCE, - ZBAR_ISBN13, ZBAR_ISBN10, + ZBAR_EAN2, ZBAR_EAN5, ZBAR_COMPOSITE, + ZBAR_UPCA, ZBAR_UPCE, + ZBAR_ISBN13, ZBAR_ISBN10, 0 }; NSMutableArray *symbols = [NSMutableArray array]; [symbolEnables release]; - symbolEnables = [[NSMutableArray alloc] init]; + symbolEnables = [NSMutableArray new]; BOOL en = YES; - for(int i = 0; symbolValues[i]; i++) { - /* symbologies after ZBAR_EAN5 are disabled by default */ - en = en && (symbolValues[i] != ZBAR_COMPOSITE); + for(int i = 0; allSymbologies[i]; i++) { + zbar_symbol_type_t sym = allSymbologies[i]; + if(defaultSymbologies) + en = !![defaultSymbologies member: + [NSNumber numberWithInteger: sym]]; + else + /* symbologies after ZBAR_EAN5 are disabled by default */ + en = en && (sym != ZBAR_COMPOSITE); [symbols addObject: - [self cellWithTitle: [ZBarSymbol nameForType: symbolValues[i]] - tag: symbolValues[i] + [self cellWithTitle: [ZBarSymbol nameForType: sym] + tag: sym checked: en]]; [symbolEnables addObject: [NSNumber numberWithBool: en]]; } @@ -362,6 +420,7 @@ - (void) viewDidLoad view.dataSource = self; [self initOverlay]; + [self updateCropMask]; sections = [[NSMutableArray alloc] initWithCapacity: NUM_SECTIONS]; @@ -448,8 +507,11 @@ - (void) scan typeOvl.text = nil; dataOvl.text = nil; [self.tableView reloadData]; - if([reader respondsToSelector: @selector(readerView)]) + if([reader respondsToSelector: @selector(readerView)]) { reader.readerView.showsFPS = YES; + if(defaultZoom) + reader.readerView.zoom = defaultZoom; + } if(reader.sourceType == UIImagePickerControllerSourceTypeCamera) reader.cameraOverlayView = (reader.showsZBarControls) ? nil : overlay; manualBtn.enabled = TARGET_IPHONE_SIMULATOR || @@ -576,35 +638,20 @@ - (void) advanceCrop: (UILabel*) label reader.scanCrop = r; label.text = NSStringFromCGRect(r); - r.origin.x *= 426; - r.origin.y *= 320; - r.size.width *= 426; - r.size.height *= 320; - UIView *mask = [masks objectAtIndex: 0]; - mask.frame = CGRectMake(0, -426, 320, r.origin.x); - mask = [masks objectAtIndex: 1]; - mask.frame = CGRectMake(0, r.origin.x - 426, r.origin.y, r.size.width); - - r.origin.y += r.size.height; - mask = [masks objectAtIndex: 2]; - mask.frame = CGRectMake(r.origin.y, r.origin.x - 426, - 320 - r.origin.y, r.size.width); - - r.origin.x += r.size.width; - mask = [masks objectAtIndex: 3]; - mask.frame = CGRectMake(0, r.origin.x - 426, 320, 426 - r.origin.x); + [self updateCropMask]; } - (void) advanceDensity: (UILabel*) label + value: (NSInteger*) value { - NSInteger d = [label.text integerValue]; + NSInteger d = *value; int i; for(i = 0; density_choices[i] >= 0;) if(d == density_choices[i++]) break; if(density_choices[i] < 0) i = 0; - d = density_choices[i]; + *value = d = density_choices[i]; assert(d >= 0); [reader.scanner setSymbology: 0 config: label.tag @@ -625,6 +672,7 @@ - (void) tableView: (UITableView*) view case CLASS_SECTION: { NSString *name = cell.textLabel.text; [self initReader: name]; + [self updateCropMask]; [self initControlCells]; [self setCheckForName: name inSection: CLASS_SECTION]; @@ -670,8 +718,12 @@ - (void) tableView: (UITableView*) view switch(path.row) { case 0: + [self advanceDensity: cell.detailTextLabel + value: &xDensity]; + break; case 1: - [self advanceDensity: cell.detailTextLabel]; + [self advanceDensity: cell.detailTextLabel + value: &yDensity]; break; case 2: [self advanceCrop: cell.detailTextLabel]; @@ -818,14 +870,6 @@ - (void) readerControllerDidFailToRead: (ZBarReaderController*) _reader int main (int argc, char *argv[]) { -#ifdef VALGRIND - if(argc < 2 || (argc >= 2 && strcmp(argv[1], "-valgrind"))) - execl(VALGRIND, VALGRIND, - "--log-file=/tmp/memcheck.log", "--leak-check=full", - argv[0], "-valgrind", - NULL); -#endif - NSAutoreleasePool *pool = [NSAutoreleasePool new]; int rc = UIApplicationMain(argc, argv, nil, @"AppDelegate"); [pool release]; diff --git a/iphone/examples/readertest/readertest.xcodeproj/project.pbxproj b/iphone/examples/readertest/readertest.xcodeproj/project.pbxproj index df4d499..09a55b4 100755 --- a/iphone/examples/readertest/readertest.xcodeproj/project.pbxproj +++ b/iphone/examples/readertest/readertest.xcodeproj/project.pbxproj @@ -297,6 +297,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 3.1; + OTHER_LDFLAGS = "-all_load"; PREBINDING = NO; SDKROOT = iphoneos; SYMROOT = /tmp/readertest.build; @@ -312,6 +313,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 3.1; + OTHER_LDFLAGS = "-all_load"; PREBINDING = NO; SDKROOT = iphoneos; SYMROOT = /tmp/readertest.build; diff --git a/iphone/zbar.xcodeproj/project.pbxproj b/iphone/zbar.xcodeproj/project.pbxproj index 600b5f1..0616793 100644 --- a/iphone/zbar.xcodeproj/project.pbxproj +++ b/iphone/zbar.xcodeproj/project.pbxproj @@ -775,6 +775,7 @@ ); OTHER_LDFLAGS = ""; PRODUCT_NAME = zbar; + SKIP_INSTALL = YES; }; name = Debug; }; @@ -793,6 +794,7 @@ ); OTHER_LDFLAGS = ""; PRODUCT_NAME = zbar; + SKIP_INSTALL = YES; }; name = Release; }; @@ -813,7 +815,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 3.0; - OTHER_LDFLAGS = "-ObjC"; + OTHER_LDFLAGS = "-all_load"; PREBINDING = NO; PROVISIONING_PROFILE = ""; RUN_CLANG_STATIC_ANALYZER = NO; @@ -826,6 +828,7 @@ isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CODE_SIGN_IDENTITY = "iPhone Developer"; EXCLUDED_SOURCE_FILE_NAMES = ""; "EXCLUDED_SOURCE_FILE_NAMES[sdk=iphoneos*][arch=*]" = ZBarReaderViewImpl_Simulator.m; "EXCLUDED_SOURCE_FILE_NAMES[sdk=iphonesimulator*][arch=*]" = ( @@ -837,8 +840,9 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 3.0; - OTHER_LDFLAGS = "-ObjC"; + OTHER_LDFLAGS = "-all_load"; PREBINDING = NO; + PROVISIONING_PROFILE = ""; RUN_CLANG_STATIC_ANALYZER = NO; SDKROOT = iphoneos; USE_HEADERMAP = NO; @@ -867,7 +871,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CODE_SIGN_IDENTITY = "iPhone Developer"; COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -879,12 +882,6 @@ ); INFOPLIST_FILE = examples/readertest/readertest.plist; INSTALL_PATH = "$(HOME)/Applications"; - OTHER_LDFLAGS = ( - "-framework", - Foundation, - "-framework", - UIKit, - ); PREBINDING = NO; PRODUCT_NAME = readertest; }; @@ -894,7 +891,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CODE_SIGN_IDENTITY = "iPhone Developer"; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_ENABLE_FIX_AND_CONTINUE = NO; @@ -906,18 +902,98 @@ ); INFOPLIST_FILE = examples/readertest/readertest.plist; INSTALL_PATH = "$(HOME)/Applications"; - OTHER_LDFLAGS = ( - "-framework", - Foundation, - "-framework", - UIKit, - ); PREBINDING = NO; PRODUCT_NAME = readertest; ZERO_LINK = NO; }; name = Release; }; + DC3748D71357BC69004E69D6 /* Distribution */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + EXCLUDED_SOURCE_FILE_NAMES = ""; + "EXCLUDED_SOURCE_FILE_NAMES[sdk=iphoneos*][arch=*]" = ZBarReaderViewImpl_Simulator.m; + "EXCLUDED_SOURCE_FILE_NAMES[sdk=iphonesimulator*][arch=*]" = ( + ZBarReaderViewImpl_Capture.m, + ZBarCaptureReader.m, + ); + GCC_C_LANGUAGE_STANDARD = c99; + GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1"; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 3.0; + OTHER_LDFLAGS = "-all_load"; + PREBINDING = NO; + PROVISIONING_PROFILE = ""; + RUN_CLANG_STATIC_ANALYZER = NO; + SDKROOT = iphoneos; + USE_HEADERMAP = NO; + }; + name = Distribution; + }; + DC3748D81357BC69004E69D6 /* Distribution */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = include/prefix.pch; + HEADER_SEARCH_PATHS = ( + include, + ../include, + ../zbar, + ); + OTHER_LDFLAGS = ""; + PRODUCT_NAME = zbar; + SKIP_INSTALL = YES; + }; + name = Distribution; + }; + DC3748D91357BC69004E69D6 /* Distribution */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + PRODUCT_NAME = ZBarSDK; + TARGET_BUILD_DIR = "$(TARGET_BUILD_DIR)/$(PRODUCT_NAME)"; + ZERO_LINK = NO; + }; + name = Distribution; + }; + DC3748DA1357BC69004E69D6 /* Distribution */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + PRODUCT_NAME = ZBarSDK.dmg; + TARGET_BUILD_DIR = "$(TARGET_BUILD_DIR)/$(PRODUCT_NAME)"; + }; + name = Distribution; + }; + DC3748DB1357BC69004E69D6 /* Distribution */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = examples/readertest/prefix.pch; + HEADER_SEARCH_PATHS = ( + include/ZBarSDK, + ../include, + ); + INFOPLIST_FILE = examples/readertest/readertest.plist; + INSTALL_PATH = "$(HOME)/Applications"; + PREBINDING = NO; + PRODUCT_NAME = readertest; + ZERO_LINK = NO; + }; + name = Distribution; + }; DC3CEE831215C7EF00D7A786 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -949,45 +1025,50 @@ buildConfigurations = ( 1DEB921F08733DC00010E9CD /* Debug */, 1DEB922008733DC00010E9CD /* Release */, + DC3748D81357BC69004E69D6 /* Distribution */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; + defaultConfigurationName = Distribution; }; 1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "zbar" */ = { isa = XCConfigurationList; buildConfigurations = ( 1DEB922308733DC00010E9CD /* Debug */, 1DEB922408733DC00010E9CD /* Release */, + DC3748D71357BC69004E69D6 /* Distribution */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; + defaultConfigurationName = Distribution; }; DC1A4A5311FF5D3D00BCDA30 /* Build configuration list for PBXAggregateTarget "ZBarSDK.dmg" */ = { isa = XCConfigurationList; buildConfigurations = ( DC1A4A4F11FF5D0500BCDA30 /* Debug */, DC1A4A5011FF5D0500BCDA30 /* Release */, + DC3748DA1357BC69004E69D6 /* Distribution */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; + defaultConfigurationName = Distribution; }; DC299A9A1208B5D5006A023C /* Build configuration list for PBXNativeTarget "readertest" */ = { isa = XCConfigurationList; buildConfigurations = ( DC299A981208B5D5006A023C /* Debug */, DC299A991208B5D5006A023C /* Release */, + DC3748DB1357BC69004E69D6 /* Distribution */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; + defaultConfigurationName = Distribution; }; DC3CEE851215C83500D7A786 /* Build configuration list for PBXAggregateTarget "ZBarSDK" */ = { isa = XCConfigurationList; buildConfigurations = ( DC3CEE831215C7EF00D7A786 /* Debug */, DC3CEE841215C7EF00D7A786 /* Release */, + DC3748D91357BC69004E69D6 /* Distribution */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; + defaultConfigurationName = Distribution; }; /* End XCConfigurationList section */ }; diff --git a/iphone/zbar.xcodeproj/xcshareddata/xcschemes/readertest.xcscheme b/iphone/zbar.xcodeproj/xcshareddata/xcschemes/readertest.xcscheme index 256e1b5..e50c0e3 100644 --- a/iphone/zbar.xcodeproj/xcshareddata/xcschemes/readertest.xcscheme +++ b/iphone/zbar.xcodeproj/xcshareddata/xcschemes/readertest.xcscheme @@ -46,6 +46,13 @@ ReferencedContainer = "container:zbar.xcodeproj"> + + + + @@ -70,7 +77,7 @@ buildConfiguration = "Debug"> From edb0e67940c30796c1561ff9524e0076f32f72f5 Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 17 Apr 2011 20:02:05 -0700 Subject: [PATCH 273/328] Codabar reliability enhancements - fix missing check - require minimum quality - bump default uncertainty --- ChangeLog | 4 ++++ zbar/decoder/codabar.c | 4 ++++ zbar/img_scanner.c | 19 ++++++++++++------- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 27dc7bb..3153467 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,8 @@ 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 diff --git a/zbar/decoder/codabar.c b/zbar/decoder/codabar.c index f05e9ab..40b2064 100644 --- a/zbar/decoder/codabar.c +++ b/zbar/decoder/codabar.c @@ -172,6 +172,10 @@ codabar_decode7 (zbar_decoder_t *dcode) dbprintf(2, " [2space inner ratios]"); return(-1); } + if((ispc >> 8) == 4) { + dbprintf(2, " [space comb]"); + return(-1); + } ispc >>= 10; dbprintf(2, "(%d)", ispc); unsigned ic = ispc * 4 + ibar; diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 2267c97..398671f 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -493,7 +493,7 @@ zbar_image_scanner_t *zbar_image_scanner_create () zbar_image_scanner_set_config(iscn, ZBAR_CODE128, ZBAR_CFG_UNCERTAINTY, 0); zbar_image_scanner_set_config(iscn, ZBAR_CODE93, ZBAR_CFG_UNCERTAINTY, 0); zbar_image_scanner_set_config(iscn, ZBAR_CODE39, ZBAR_CFG_UNCERTAINTY, 0); - zbar_image_scanner_set_config(iscn, ZBAR_CODABAR, ZBAR_CFG_UNCERTAINTY, 0); + zbar_image_scanner_set_config(iscn, ZBAR_CODABAR, ZBAR_CFG_UNCERTAINTY, 1); zbar_image_scanner_set_config(iscn, ZBAR_COMPOSITE, ZBAR_CFG_UNCERTAINTY, 0); return(iscn); } @@ -816,8 +816,11 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, for(symp = &syms->head; *symp; ) { zbar_symbol_t *sym = *symp; if((sym->type < ZBAR_COMPOSITE && sym->type > ZBAR_PARTIAL) || - (sym->type == ZBAR_DATABAR || sym->type == ZBAR_DATABAR_EXP)) { - if(filter && sym->quality < 4) { + sym->type == ZBAR_DATABAR || + sym->type == ZBAR_DATABAR_EXP || + sym->type == ZBAR_CODABAR) + { + if((sym->type == ZBAR_CODABAR || filter) && sym->quality < 4) { /* recycle */ *symp = sym->next; syms->nsyms--; @@ -825,10 +828,12 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, _zbar_image_scanner_recycle_syms(iscn, sym); continue; } - else if(sym->type > ZBAR_EAN5) - nean++; - else - naddon++; + else if(sym->type < ZBAR_COMPOSITE) { + if(sym->type > ZBAR_EAN5) + nean++; + else + naddon++; + } } symp = &sym->next; } From ed12f60639d110bb3f45c82a710345af0830dc75 Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 20 Apr 2011 18:36:36 -0700 Subject: [PATCH 274/328] fix image scanner min quality filtering --- ChangeLog | 1 + zbar/img_scanner.c | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 3153467..7dcbe4f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * fix image scanner min quality filtering * Codabar reliability enhancements - fix missing check - require minimum quality diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 398671f..a788666 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -815,12 +815,22 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, zbar_symbol_t **symp; for(symp = &syms->head; *symp; ) { zbar_symbol_t *sym = *symp; - if((sym->type < ZBAR_COMPOSITE && sym->type > ZBAR_PARTIAL) || + if(sym->cache_count <= 0 && + (sym->type < ZBAR_COMPOSITE && sym->type > ZBAR_PARTIAL) || sym->type == ZBAR_DATABAR || sym->type == ZBAR_DATABAR_EXP || sym->type == ZBAR_CODABAR) { if((sym->type == ZBAR_CODABAR || filter) && sym->quality < 4) { + if(iscn->enable_cache) { + /* revert cache update */ + zbar_symbol_t *entry = cache_lookup(iscn, sym); + if(entry) + entry->cache_count--; + else + assert(0); + } + /* recycle */ *symp = sym->next; syms->nsyms--; From b6abb87fa5781a12b4058ea6478578379c750af0 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 21 Apr 2011 14:44:36 -0700 Subject: [PATCH 275/328] iPhone: add manual frame capture - readertest save as PNG --- iphone/ChangeLog | 2 + iphone/ZBarCaptureReader.m | 35 ++++++++++----- iphone/ZBarReaderViewController.m | 26 ++++++----- iphone/examples/readertest/readertest.m | 43 +++++++++++-------- iphone/include/ZBarSDK/ZBarCaptureReader.h | 6 ++- .../ZBarSDK/ZBarReaderViewController.h | 3 ++ 6 files changed, 77 insertions(+), 38 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 7631dc6..94dbab4 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,6 @@ current: + * 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 diff --git a/iphone/ZBarCaptureReader.m b/iphone/ZBarCaptureReader.m index a5723df..b3dd65c 100644 --- a/iphone/ZBarCaptureReader.m +++ b/iphone/ZBarCaptureReader.m @@ -32,6 +32,13 @@ #define MODULE ZBarCaptureReader #import "debug.h" +enum { + STOPPED = 0, + RUNNING = 1, + PAUSED = 2, + CAPTURE = 4, +}; + @implementation ZBarCaptureReader @synthesize captureOutput, captureDelegate, scanner, scanCrop, size, @@ -129,17 +136,19 @@ - (void) dealloc - (BOOL) enableReader { - return(!OSAtomicCompareAndSwap32Barrier(0, 0, &running)); + return(OSAtomicOr32Barrier(0, &state) & RUNNING); } - (void) setEnableReader: (BOOL) enable { if(!enable) - OSAtomicAnd32OrigBarrier(0, (void*)&running); - else if(OSAtomicCompareAndSwap32Barrier(0, 1, &running)) + OSAtomicAnd32Barrier(STOPPED, &state); + else if(!(OSAtomicOr32OrigBarrier(RUNNING, &state) & RUNNING)) { + OSAtomicAnd32Barrier(~PAUSED, &state); @synchronized(scanner) { scanner.enableCache = enableCache; } + } } - (void) willStartRunning @@ -159,6 +168,11 @@ - (void) flushCache } } +- (void) captureFrame +{ + OSAtomicOr32(CAPTURE, &state); +} + - (void) setCaptureDelegate: (id) delegate { @synchronized(scanner) { @@ -197,7 +211,7 @@ - (void) didReadNewSymbolsFromImage: (ZBarImage*) img [captureDelegate captureReader: self didReadNewSymbolsFromImage: img]; - OSAtomicCompareAndSwap32Barrier(2, 1, &running); + OSAtomicAnd32Barrier(~PAUSED, &state); zlog(@"latency: delegate=%gs total=%gs", timer_elapsed(t_start, timer_now()), timer_elapsed(t_scan, timer_now())); @@ -231,7 +245,8 @@ - (void) captureOutput: (AVCaptureOutput*) output { // queue is apparently not flushed when stopping; // only process when running - if(!OSAtomicCompareAndSwap32Barrier(1, 1, &running)) + uint32_t _state = OSAtomicOr32Barrier(0, &state); + if((_state & (PAUSED | RUNNING)) != RUNNING) return; NSAutoreleasePool *pool = [NSAutoreleasePool new]; @@ -317,17 +332,17 @@ - (void) captureOutput: (AVCaptureOutput*) output // return unfiltered results for tracking feedback syms.filterSymbols = NO; int nraw = syms.count; - if(nraw > 0) - zlog(@"scan image: %dx%d crop=%@ ngood=%d nraw=%d", - w, h, NSStringFromCGRect(image.crop), ngood, nraw); + 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) { + 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; - OSAtomicCompareAndSwap32Barrier(1, 2, &running); + OSAtomicXor32Barrier((_state & CAPTURE) | PAUSED, &state); [self performSelectorOnMainThread: @selector(didReadNewSymbolsFromImage:) withObject: result diff --git a/iphone/ZBarReaderViewController.m b/iphone/ZBarReaderViewController.m index 0b37852..dac8e33 100644 --- a/iphone/ZBarReaderViewController.m +++ b/iphone/ZBarReaderViewController.m @@ -23,6 +23,7 @@ #import #import +#import #import #define MODULE ZBarReaderViewController @@ -125,6 +126,12 @@ - (void) initControls toolbar.frame = r; toolbar.barStyle = UIBarStyleBlackOpaque; + UIButton *info = + [UIButton buttonWithType: UIButtonTypeInfoLight]; + [info addTarget: self + action: @selector(info) + forControlEvents: UIControlEventTouchUpInside]; + toolbar.items = [NSArray arrayWithObjects: [[[UIBarButtonItem alloc] @@ -137,20 +144,13 @@ - (void) initControls target: nil action: nil] autorelease], + [[[UIBarButtonItem alloc] + initWithCustomView: info] + autorelease], nil]; [controls addSubview: toolbar]; [toolbar release]; - UIButton *info = - [UIButton buttonWithType: UIButtonTypeInfoLight]; - r.origin.x = r.size.width - 54; - r.size.width = 54; - info.frame = r; - [info addTarget: self - action: @selector(info) - forControlEvents: UIControlEventTouchUpInside]; - [controls addSubview: info]; - [view addSubview: controls]; } @@ -319,6 +319,12 @@ - (void) showHelpWithReason: (NSString*) reason [UIView commitAnimations]; } +- (void) takePicture +{ + if(readerView) + [readerView.captureReader captureFrame]; +} + // ZBarHelpDelegate - (void) helpControllerDidFinish: (ZBarHelpController*) help diff --git a/iphone/examples/readertest/readertest.m b/iphone/examples/readertest/readertest.m index 0373a23..af3435e 100644 --- a/iphone/examples/readertest/readertest.m +++ b/iphone/examples/readertest/readertest.m @@ -177,6 +177,13 @@ - (void) initOverlay target: self action: @selector(manualCapture)]; + + UIButton *info = + [UIButton buttonWithType: UIButtonTypeInfoLight]; + [info addTarget: self + action: @selector(info) + forControlEvents: UIControlEventTouchUpInside]; + toolbar.items = [NSArray arrayWithObjects: [[[UIBarButtonItem alloc] @@ -206,18 +213,12 @@ - (void) initOverlay target: nil action: nil] autorelease], + [[[UIBarButtonItem alloc] + initWithCustomView: info] + autorelease], nil]; [overlay addSubview: toolbar]; [toolbar release]; - - - UIButton *info = - [UIButton buttonWithType: UIButtonTypeInfoLight]; - info.frame = CGRectMake(266, 0, 54, 54); - [info addTarget: self - action: @selector(info) - forControlEvents: UIControlEventTouchUpInside]; - [overlay addSubview: info]; } - (void) updateCropMask @@ -515,7 +516,8 @@ - (void) scan if(reader.sourceType == UIImagePickerControllerSourceTypeCamera) reader.cameraOverlayView = (reader.showsZBarControls) ? nil : overlay; manualBtn.enabled = TARGET_IPHONE_SIMULATOR || - (reader.cameraMode == ZBarReaderControllerCameraModeDefault); + (reader.cameraMode == ZBarReaderControllerCameraModeDefault) || + [reader isKindOfClass: [ZBarReaderViewController class]]; [self presentModalViewController: reader animated: YES]; } @@ -787,8 +789,12 @@ - (void) actionSheet: (UIActionSheet*) sheet if(idx == sheet.cancelButtonIndex) return; idx -= sheet.firstOtherButtonIndex; - if(!idx) - UIImageWriteToSavedPhotosAlbum(imageView.image, nil, NULL, NULL); + if(!idx) { + UIImage *img = + [UIImage imageWithData: + UIImagePNGRepresentation(imageView.image)]; + UIImageWriteToSavedPhotosAlbum(img, nil, NULL, NULL); + } } // ZBarReaderDelegate @@ -810,7 +816,6 @@ - (void) imagePickerController: (UIImagePickerController*) picker for(ZBarSymbol *sym in results) if(sym.quality > quality) bestResult = sym; - assert(!!bestResult); [self performSelector: @selector(presentResult:) withObject: bestResult @@ -821,10 +826,14 @@ - (void) imagePickerController: (UIImagePickerController*) picker - (void) presentResult: (ZBarSymbol*) sym { - found = !!sym; - NSString *typeName = sym.typeName; + found = sym || imageView.image; + NSString *typeName = @"NONE"; + NSString *data = @""; + if(sym) { + typeName = sym.typeName; + data = sym.data; + } typeLabel.text = typeName; - NSString *data = sym.data; dataLabel.text = data; if(continuous) { @@ -833,7 +842,7 @@ - (void) presentResult: (ZBarSymbol*) sym } NSLog(@"imagePickerController:didFinishPickingMediaWithInfo:\n"); - NSLog(@" type=%@ data=%@\n", sym.typeName, data); + NSLog(@" type=%@ data=%@\n", typeName, data); CGSize size = [data sizeWithFont: [UIFont systemFontOfSize: 17] constrainedToSize: CGSizeMake(288, 2000) diff --git a/iphone/include/ZBarSDK/ZBarCaptureReader.h b/iphone/include/ZBarSDK/ZBarCaptureReader.h index 310dd31..903c838 100644 --- a/iphone/include/ZBarSDK/ZBarCaptureReader.h +++ b/iphone/include/ZBarSDK/ZBarCaptureReader.h @@ -57,7 +57,7 @@ dispatch_queue_t queue; ZBarImage *image; ZBarCVImage *result; - int32_t running; + volatile uint32_t state; int framecnt; unsigned width, height; uint64_t t_frame, t_fps, t_scan; @@ -76,6 +76,10 @@ // clear the internal result cache - (void) flushCache; +// capture the next frame after processing. the captured image will +// follow the same delegate path as an image with decoded symbols. +- (void) captureFrame; + // the capture output. add this to an instance of AVCaptureSession @property (nonatomic, readonly) AVCaptureOutput *captureOutput; diff --git a/iphone/include/ZBarSDK/ZBarReaderViewController.h b/iphone/include/ZBarSDK/ZBarReaderViewController.h index cd65a6e..f1403da 100644 --- a/iphone/include/ZBarSDK/ZBarReaderViewController.h +++ b/iphone/include/ZBarSDK/ZBarReaderViewController.h @@ -78,6 +78,9 @@ // the onZBarHelp() javascript function. - (void) showHelpWithReason: (NSString*) reason; +// capture the next frame and send it over the usual delegate path. +- (void) takePicture; + // direct access to the ZBarReaderView @property (nonatomic, readonly) ZBarReaderView *readerView; From 07980c91ce6ca46cf06cf4d33fa9f82c989c5583 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 21 Apr 2011 15:31:54 -0700 Subject: [PATCH 276/328] iPhone: add readertest fixed zoom stops --- iphone/ChangeLog | 1 + iphone/examples/readertest/readertest.m | 54 +++++++++++++++++++------ 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 94dbab4..c988e88 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,5 @@ current: + * add readertest fixed zoom stops * add manual frame capture - readertest save as PNG * enhance readertest to support default/demo pre-config and distribution diff --git a/iphone/examples/readertest/readertest.m b/iphone/examples/readertest/readertest.m index af3435e..8325f72 100644 --- a/iphone/examples/readertest/readertest.m +++ b/iphone/examples/readertest/readertest.m @@ -30,6 +30,10 @@ 3, 2, 1, 0, 4, -1 }; +static const CGFloat const zoom_choices[] = { + 1, 10/9., 10/8., 8/6., 10/7., 9/6., 10/6., 7/4., 2, 0, -1 +}; + @interface AppDelegate : UITableViewController < UIApplicationDelegate, @@ -43,7 +47,7 @@ @interface AppDelegate UINavigationController *nav; NSSet *defaultSymbologies; - CGFloat defaultZoom; + CGFloat zoom; NSMutableArray *sections, *symbolEnables; NSInteger xDensity, yDensity; @@ -85,7 +89,7 @@ - (void) initReader: (NSString*) clsName // apply defaults for demo ZBarImageScanner *scanner = reader.scanner; continuous = NO; - defaultZoom = 1; + zoom = 1; reader.showsZBarControls = NO; reader.scanCrop = CGRectMake(0, .35, 1, .3); @@ -341,14 +345,6 @@ - (void) initControlCells [sections replaceObjectAtIndex: CONFIG_SECTION withObject: configs]; - UITableViewCell *cropCell = - [[[UITableViewCell alloc] - initWithStyle: UITableViewCellStyleValue1 - reuseIdentifier: nil] - autorelease]; - cropCell.textLabel.text = @"scanCrop"; - cropCell.detailTextLabel.text = NSStringFromCGRect(reader.scanCrop); - UITableViewCell *xDensityCell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleValue1 @@ -369,11 +365,29 @@ - (void) initControlCells yDensityCell.detailTextLabel.text = [NSString stringWithFormat: @"%d", yDensity]; + UITableViewCell *cropCell = + [[[UITableViewCell alloc] + initWithStyle: UITableViewCellStyleValue1 + reuseIdentifier: nil] + autorelease]; + cropCell.textLabel.text = @"scanCrop"; + cropCell.detailTextLabel.text = NSStringFromCGRect(reader.scanCrop); + + UITableViewCell *zoomCell = + [[[UITableViewCell alloc] + initWithStyle: UITableViewCellStyleValue1 + reuseIdentifier: nil] + autorelease]; + zoomCell.textLabel.text = @"zoom"; + zoomCell.detailTextLabel.text = + [NSString stringWithFormat: @"%g", zoom]; + [sections replaceObjectAtIndex: CUSTOM_SECTION withObject: [NSArray arrayWithObjects: xDensityCell, yDensityCell, cropCell, + zoomCell, [self cellWithTitle: @"continuous" tag: 1 checked: continuous], @@ -510,8 +524,8 @@ - (void) scan [self.tableView reloadData]; if([reader respondsToSelector: @selector(readerView)]) { reader.readerView.showsFPS = YES; - if(defaultZoom) - reader.readerView.zoom = defaultZoom; + if(zoom) + reader.readerView.zoom = zoom; } if(reader.sourceType == UIImagePickerControllerSourceTypeCamera) reader.cameraOverlayView = (reader.showsZBarControls) ? nil : overlay; @@ -643,6 +657,19 @@ - (void) advanceCrop: (UILabel*) label [self updateCropMask]; } +- (void) advanceZoom: (UILabel*) label +{ + int i; + for(i = 0; zoom_choices[i] >= 0;) + if(zoom == zoom_choices[i++]) + break; + if(zoom_choices[i] < 0) + i = 0; + zoom = zoom_choices[i]; + assert(zoom >= 0); + label.text = [NSString stringWithFormat: @"%g", zoom]; +} + - (void) advanceDensity: (UILabel*) label value: (NSInteger*) value { @@ -731,6 +758,9 @@ - (void) tableView: (UITableView*) view [self advanceCrop: cell.detailTextLabel]; break; case 3: + [self advanceZoom: cell.detailTextLabel]; + break; + case 4: [self setCheck: continuous = !continuous forCell: cell]; break; From 7e7349009f838795fe8c41eaa35561b8d91077e0 Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 27 Apr 2011 12:48:35 -0700 Subject: [PATCH 277/328] fix i25 buffer overrun corner case --- ChangeLog | 1 + zbar/decoder.h | 2 ++ zbar/decoder/code128.c | 6 +++--- zbar/decoder/code39.c | 25 +++++++++++-------------- zbar/decoder/code93.c | 6 ++++-- zbar/decoder/databar.c | 5 ++++- zbar/decoder/i25.c | 6 ++++-- zbar/decoder/pdf417.c | 4 +--- 8 files changed, 30 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4f30320..078b456 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * 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) diff --git a/zbar/decoder.h b/zbar/decoder.h index 4603d0a..51358a0 100644 --- a/zbar/decoder.h +++ b/zbar/decoder.h @@ -210,6 +210,8 @@ static inline char size_buf (zbar_decoder_t *dcode, unsigned len) { unsigned char *buf; + if(len <= BUFFER_MIN) + return(0); if(len < dcode->buf_alloc) /* FIXME size reduction heuristic? */ return(0); diff --git a/zbar/decoder/code128.c b/zbar/decoder/code128.c index 3e5ef0b..4c3d91c 100644 --- a/zbar/decoder/code128.c +++ b/zbar/decoder/code128.c @@ -441,6 +441,8 @@ static inline unsigned char postprocess (zbar_decoder_t *dcode) dcode->code128.character)); j += postprocess_c(dcode, cexp, i, j) * 2; } + zassert(j < dcode->buf_alloc, 1, "j=%02x %s\n", j, + _zbar_decoder_buf_dump(dcode->buf, dcode->code128.character)); dcode->buflen = j; dcode->buf[j] = '\0'; dcode->code128.character = j; @@ -496,9 +498,7 @@ zbar_symbol_type_t _zbar_decode_code128 (zbar_decoder_t *dcode) dbprintf(2, " dir=%x [valid start]\n", dcode128->direction); return(0); } - else if((c < 0) || - ((dcode128->character >= BUFFER_MIN) && - size_buf(dcode, dcode128->character + 1))) { + else if(c < 0 || size_buf(dcode, dcode128->character + 1)) { dbprintf(1, (c < 0) ? " [aborted]\n" : " [overflow]\n"); if(dcode128->character > 1) release_lock(dcode, ZBAR_CODE128); diff --git a/zbar/decoder/code39.c b/zbar/decoder/code39.c index 9cbaec9..2fb4012 100644 --- a/zbar/decoder/code39.c +++ b/zbar/decoder/code39.c @@ -213,7 +213,7 @@ static inline signed char code39_decode_start (zbar_decoder_t *dcode) return(ZBAR_PARTIAL); } -static inline void code39_postprocess (zbar_decoder_t *dcode) +static inline int code39_postprocess (zbar_decoder_t *dcode) { code39_decoder_t *dcode39 = &dcode->code39; dcode->direction = 1 - 2 * dcode39->direction; @@ -232,9 +232,12 @@ static inline void code39_postprocess (zbar_decoder_t *dcode) dcode->buf[i] = ((dcode->buf[i] < 0x2b) ? code39_characters[(unsigned)dcode->buf[i]] : '?'); + zassert(i < dcode->buf_alloc, -1, "i=%02x %s\n", i, + _zbar_decoder_buf_dump(dcode->buf, dcode39->character)); dcode->buflen = i; dcode->buf[i] = '\0'; dcode->modifiers = 0; + return(0); } static inline int @@ -275,23 +278,19 @@ zbar_symbol_type_t _zbar_decode_code39 (zbar_decoder_t *dcode) dcode->buf[dcode39->character - 1] == 0x2b) { /* STOP */ /* trim STOP character */ dcode39->character--; - zbar_symbol_type_t sym = ZBAR_CODE39; + zbar_symbol_type_t sym = ZBAR_NONE; /* trailing quiet zone check */ - if(space && space < dcode39->width / 2) { + if(space && space < dcode39->width / 2) dbprintf(2, " [invalid qz]\n"); - sym = ZBAR_NONE; - } else if(dcode39->character < CFG(*dcode39, ZBAR_CFG_MIN_LEN) || (CFG(*dcode39, ZBAR_CFG_MAX_LEN) > 0 && - dcode39->character > CFG(*dcode39, ZBAR_CFG_MAX_LEN))) { + dcode39->character > CFG(*dcode39, ZBAR_CFG_MAX_LEN))) dbprintf(2, " [invalid len]\n"); - sym = ZBAR_NONE; - } - else { - /* FIXME checksum (needs config enable) */ - code39_postprocess(dcode); + else if(!code39_postprocess(dcode)) { + /* FIXME checksum */ dbprintf(2, " [valid end]\n"); + sym = ZBAR_CODE39; } dcode39->character = -1; if(!sym) @@ -328,9 +327,7 @@ zbar_symbol_type_t _zbar_decode_code39 (zbar_decoder_t *dcode) return(ZBAR_PARTIAL); } - if(c < 0 || - ((dcode39->character >= BUFFER_MIN) && - size_buf(dcode, dcode39->character + 1))) { + if(c < 0 || size_buf(dcode, dcode39->character + 1)) { dbprintf(1, (c < 0) ? " [aborted]\n" : " [overflow]\n"); release_lock(dcode, ZBAR_CODE39); dcode39->character = -1; diff --git a/zbar/decoder/code93.c b/zbar/decoder/code93.c index 23d79c5..43b8ed7 100644 --- a/zbar/decoder/code93.c +++ b/zbar/decoder/code93.c @@ -318,6 +318,9 @@ postprocess (zbar_decoder_t *dcode) dcode->buf[j++] = d; } + zassert(j < dcode->buf_alloc, 1, + "j=%02x %s\n", j, + _zbar_decoder_buf_dump(dcode->buf, dcode->code93.character)); dcode->buflen = j; dcode->buf[j] = '\0'; dcode->modifiers = 0; @@ -374,8 +377,7 @@ _zbar_decode_code93 (zbar_decoder_t *dcode) return(ZBAR_CODE93); } - if(dcode93->character >= BUFFER_MIN && - size_buf(dcode, dcode93->character + 1)) + if(size_buf(dcode, dcode93->character + 1)) return(decode_abort(dcode, "overflow")); dcode93->width = dcode->s6; diff --git a/zbar/decoder/databar.c b/zbar/decoder/databar.c index da472b4..b6d9a70 100644 --- a/zbar/decoder/databar.c +++ b/zbar/decoder/databar.c @@ -420,8 +420,11 @@ databar_postprocess_exp (zbar_decoder_t *dcode, /* FIXME check pad? */ } - *buf = 0; i = buf - dcode->buf; + zassert(i < dcode->buf_alloc, -1, "i=%02x %s\n", i, + _zbar_decoder_buf_dump(dcode->buf, i)); + + *buf = 0; dcode->buflen = i; if(i && *--buf == GS) { *buf = 0; diff --git a/zbar/decoder/i25.c b/zbar/decoder/i25.c index a93f3bf..b2740a4 100644 --- a/zbar/decoder/i25.c +++ b/zbar/decoder/i25.c @@ -187,6 +187,9 @@ static inline signed char i25_decode_end (zbar_decoder_t *dcode) return(ZBAR_NONE); } + zassert(dcode25->character < dcode->buf_alloc, ZBAR_NONE, "i=%02x %s\n", + dcode25->character, + _zbar_decoder_buf_dump(dcode->buf, dcode25->character)); dcode->buflen = dcode25->character; dcode->buf[dcode25->character] = '\0'; dcode->modifiers = 0; @@ -229,8 +232,7 @@ zbar_symbol_type_t _zbar_decode_i25 (zbar_decoder_t *dcode) goto reset; } - if((dcode25->character >= BUFFER_MIN) && - size_buf(dcode, dcode25->character + 2)) { + if(size_buf(dcode, dcode25->character + 3)) { dbprintf(2, " [overflow]\n"); goto reset; } diff --git a/zbar/decoder/pdf417.c b/zbar/decoder/pdf417.c index 80c7a94..738e58f 100644 --- a/zbar/decoder/pdf417.c +++ b/zbar/decoder/pdf417.c @@ -199,9 +199,7 @@ zbar_symbol_type_t _zbar_decode_pdf417 (zbar_decoder_t *dcode) } signed short c = pdf417_decode8(dcode); - if((c < 0) || - ((dcode417->character >= BUFFER_MIN) && - size_buf(dcode, dcode417->character + 1))) { + if(c < 0 || size_buf(dcode, dcode417->character + 1)) { dbprintf(1, (c < 0) ? " [aborted]\n" : " [overflow]\n"); release_lock(dcode, ZBAR_PDF417); dcode417->character = -1; From 97611dce69bf6f538d91f42101c2512d5496401f Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 2 May 2011 15:09:59 -0700 Subject: [PATCH 278/328] improve support for resizing, rotating and embedding the reader --- iphone/ChangeLog | 1 + iphone/ZBarHelpController.m | 74 +++-- iphone/ZBarReaderView.m | 270 ++++++++++++++---- iphone/ZBarReaderViewController.m | 77 ++++- iphone/ZBarReaderViewImpl_Capture.m | 22 +- iphone/ZBarReaderViewImpl_Simulator.m | 86 ++++-- iphone/examples/readertest/readertest.m | 1 + iphone/include/ZBarSDK/ZBarCaptureReader.h | 2 + iphone/include/ZBarSDK/ZBarReaderView.h | 13 +- .../ZBarSDK/ZBarReaderViewController.h | 15 + iphone/zbar.xcodeproj/project.pbxproj | 6 + 11 files changed, 413 insertions(+), 154 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index c988e88..f2736e1 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,5 @@ current: + * improve support for resizing, rotating and embedding the reader * add readertest fixed zoom stops * add manual frame capture - readertest save as PNG diff --git a/iphone/ZBarHelpController.m b/iphone/ZBarHelpController.m index e4211db..531f40e 100644 --- a/iphone/ZBarHelpController.m +++ b/iphone/ZBarHelpController.m @@ -23,6 +23,9 @@ #import +#define MODULE ZBarHelpController +#import "debug.h" + @implementation ZBarHelpController @synthesize delegate; @@ -36,11 +39,6 @@ - (id) initWithReason: (NSString*) _reason if(!_reason) _reason = @"INFO"; reason = [_reason retain]; - orientations = ((1 << UIInterfaceOrientationPortrait) | - (1 << UIInterfaceOrientationPortraitUpsideDown) | - (1 << UIInterfaceOrientationLandscapeLeft) | - (1 << UIInterfaceOrientationLandscapeRight)); - return(self); } @@ -73,44 +71,38 @@ - (void) dealloc [super dealloc]; } -- (void) layoutSubviewsForOrientation: (UIInterfaceOrientation) orient -{ - CGFloat h; - if(orient == UIInterfaceOrientationPortrait || - orient == UIInterfaceOrientationPortraitUpsideDown) - h = 44; - else - h = 32; - CGRect r = self.view.bounds; - r.origin.y += r.size.height - h; - r.size.height = h; - toolbar.frame = r; - - r = self.view.bounds; - r.size.height -= h; - webView.frame = r; -} - - (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 new]; + webView = [[UIWebView alloc] + initWithFrame: CGRectMake(0, 0, + bounds.size.width, + bounds.size.height - 44)]; webView.delegate = self; webView.backgroundColor = [UIColor colorWithWhite: .125f - alpha: 1 ]; + alpha: 1]; webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | - UIViewAutoresizingFlexibleHeight); - - toolbar = [UIToolbar new]; + 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] @@ -134,13 +126,6 @@ - (void) viewDidLoad [view addSubview: toolbar]; - UIInterfaceOrientation orient = self.interfaceOrientation; - if(!((orientations >> orient) & 1)) - for(orient = UIInterfaceOrientationPortrait; - (orientations >> orient) && !((orientations >> orient) & 1); - orient++); - [self layoutSubviewsForOrientation: orient]; - NSString *path = [[NSBundle mainBundle] pathForResource: @"zbar-help" ofType: @"html"]; @@ -168,7 +153,8 @@ - (void) viewWillAppear: (BOOL) animated { assert(webView); if(webView.loading) - [webView removeFromSuperview]; + webView.hidden = YES; + webView.delegate = self; [super viewWillAppear: animated]; } @@ -187,12 +173,22 @@ - (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) orient - (void) willAnimateRotationToInterfaceOrientation: (UIInterfaceOrientation) orient duration: (NSTimeInterval) duration { - [self layoutSubviewsForOrientation: orient]; [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); } @@ -216,13 +212,13 @@ - (void) dismiss - (void) webViewDidFinishLoad: (UIWebView*) view { - if(!view.superview) { + if(view.hidden) { [view stringByEvaluatingJavaScriptFromString: [NSString stringWithFormat: @"onZBarHelp({reason:\"%@\"});", reason]]; [UIView beginAnimations: @"ZBarHelp" context: nil]; - [self.view addSubview: webView]; + view.hidden = NO; [UIView commitAnimations]; } diff --git a/iphone/ZBarReaderView.m b/iphone/ZBarReaderView.m index d4ff0cf..f065811 100644 --- a/iphone/ZBarReaderView.m +++ b/iphone/ZBarReaderView.m @@ -50,14 +50,27 @@ - (void) initSubviews { assert(preview); - CGRect r = preview.bounds; overlay = [CALayer new]; - overlay.frame = r; 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.frame = r; tracking.opacity = 0; tracking.borderWidth = 1; tracking.backgroundColor = [UIColor clearColor].CGColor; @@ -67,12 +80,7 @@ - (void) initSubviews retain]; tracking.borderColor = trackingColor.CGColor; - r.origin.x = 3 * r.size.width / 4; - r.origin.y = r.size.height - 32; - r.size.width = r.size.width - r.origin.x + 12; - r.size.height = 32 + 12; - fpsView = [[UIView alloc] - initWithFrame: r]; + fpsView = [UIView new]; fpsView.backgroundColor = [UIColor colorWithWhite: 0 alpha: .333]; fpsView.layer.cornerRadius = 12; @@ -80,9 +88,7 @@ - (void) initSubviews [self addSubview: fpsView]; fpsLabel = [[UILabel alloc] - initWithFrame: CGRectMake(0, 0, - r.size.width - 12, - r.size.height - 12)]; + initWithFrame: CGRectMake(0, 0, 80, 32)]; fpsLabel.backgroundColor = [UIColor clearColor]; fpsLabel.textColor = [UIColor colorWithRed: .333 green: .666 @@ -95,21 +101,14 @@ - (void) initSubviews self.zoom = 1.25; } -- (id) initWithImageScanner: (ZBarImageScanner*) scanner +- (void) _initWithImageScanner: (ZBarImageScanner*) scanner { - self = [super initWithFrame: CGRectMake(0, 0, 320, 426)]; - if(!self) - return(nil); - - self.backgroundColor = [UIColor blackColor]; - self.contentMode = UIViewContentModeScaleAspectFill; - self.autoresizingMask = - UIViewAutoresizingFlexibleWidth | - UIViewAutoresizingFlexibleHeight; + assert(scanner); tracksSymbols = YES; + interfaceOrientation = UIInterfaceOrientationPortrait; torchMode = 2; // AVCaptureTorchModeAuto - scanCrop = zoomCrop = CGRectMake(0, 0, 1, 1); + scanCrop = effectiveCrop = CGRectMake(0, 0, 1, 1); imageScale = 1; previewTransform = CGAffineTransformIdentity; @@ -117,7 +116,22 @@ - (id) initWithImageScanner: (ZBarImageScanner*) scanner 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); } @@ -139,6 +153,25 @@ - (id) init 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]; @@ -146,6 +179,8 @@ - (void) dealloc preview = nil; [overlay release]; overlay = nil; + [cropLayer release]; + cropLayer = nil; [tracking release]; tracking = nil; [trackingColor release]; @@ -165,7 +200,7 @@ - (void) resetTracking [CATransaction begin]; [CATransaction setDisableActions: YES]; CGSize size = overlay.bounds.size; - CGRect crop = zoomCrop; + CGRect crop = effectiveCrop; tracking.frame = CGRectMake(crop.origin.x * size.width, crop.origin.y * size.height, crop.size.width * size.width, @@ -174,35 +209,154 @@ - (void) resetTracking [CATransaction commit]; } -- (void) setImageSize: (CGSize) size +- (void) updateCrop { - CGSize psize = preview.bounds.size; - CGFloat scalex = size.width / psize.height; - CGFloat scaley = size.height / psize.width; - imageScale = (scalex > scaley) ? scalex : scaley; - - // match overlay to preview image - overlay.bounds = CGRectMake(0, 0, size.width, size.height); - CGFloat scale = 1 / imageScale; - CATransform3D xform = CATransform3DMakeRotation(M_PI / 2, 0, 0, 1); - overlay.transform = CATransform3DScale(xform, scale, scale, 1); - tracking.borderWidth = imageScale / zoom; - - zlog(@"scaling: layer=%@ image=%@ scale=%g %c %g = 1/%g", - NSStringFromCGSize(psize), NSStringFromCGSize(size), - scalex, (scalex > scaley) ? '>' : '<', scaley, scale); - [self resetTracking]; } -- (void) cropUpdate +static inline CGFloat rotationForInterfaceOrientation (int orient) { - CGAffineTransform xfrm = - CGAffineTransformMakeTranslation(.5, .5); + // 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 +{ + if(animationDuration) { + [CATransaction begin]; + [CATransaction setAnimationDuration: animationDuration]; + [CATransaction setAnimationTimingFunction: + [CAMediaTimingFunction functionWithName: + kCAMediaTimingFunctionEaseInEaseOut]]; + } + [super layoutSubviews]; + CGRect bounds = self.bounds; + fpsView.frame = CGRectMake(bounds.size.width - 80, bounds.size.height - 32, + 80 + 12, 32 + 12); + if(!bounds.size.width || !bounds.size.height) + return; + + // 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; - xfrm = CGAffineTransformScale(xfrm, z, z); - xfrm = CGAffineTransformTranslate(xfrm, -.5, -.5); - zoomCrop = CGRectApplyAffineTransform(scanCrop, xfrm); + 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 + 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]; + + if(animationDuration) { + [CATransaction commit]; + animationDuration = 0; + } +} + +- (void) setImageSize: (CGSize) size +{ + imageSize = size; + [self setNeedsLayout]; +} + +- (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) orient + duration: (NSTimeInterval) duration +{ + zlog(@"orient=%d", orient); + interfaceOrientation = orient; + animationDuration = duration; } - (void) setScanCrop: (CGRect) r @@ -210,7 +364,7 @@ - (void) setScanCrop: (CGRect) r if(CGRectEqualToRect(scanCrop, r)) return; scanCrop = r; - [self cropUpdate]; + [self setNeedsLayout]; } - (void) setTracksSymbols: (BOOL) track @@ -258,24 +412,27 @@ - (void) setZoom: (CGFloat) z return; zoom = z; + [self setNeedsLayout]; +} + +- (void) setZoom: (CGFloat) z + animated: (BOOL) animated +{ [CATransaction begin]; [CATransaction setAnimationDuration: .1]; [CATransaction setAnimationTimingFunction: [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionLinear]]; - [preview setAffineTransform: - CGAffineTransformScale(previewTransform, z, z)]; - tracking.borderWidth = imageScale / zoom; + // FIXME animate from current value + self.zoom = z; + [self layoutIfNeeded]; [CATransaction commit]; - - [self cropUpdate]; } - (void) setPreviewTransform: (CGAffineTransform) xfrm { previewTransform = xfrm; - [preview setAffineTransform: - CGAffineTransformScale(previewTransform, zoom, zoom)]; + [self setNeedsLayout]; } - (void) start @@ -312,7 +469,8 @@ - (void) handlePinch if(pinch.state == UIGestureRecognizerStateBegan) zoom0 = zoom; CGFloat z = zoom0 * pinch.scale; - self.zoom = z; + [self setZoom: z + animated: YES]; if((zoom < 1.5) != (z < 1.5)) { int d = (z < 1.5) ? 3 : 2; diff --git a/iphone/ZBarReaderViewController.m b/iphone/ZBarReaderViewController.m index dac8e33..1936edd 100644 --- a/iphone/ZBarReaderViewController.m +++ b/iphone/ZBarReaderViewController.m @@ -31,8 +31,9 @@ @implementation ZBarReaderViewController -@synthesize scanner, readerDelegate, showsZBarControls, tracksSymbols, - enableCache, cameraOverlayView, cameraViewTransform, readerView, scanCrop; +@synthesize scanner, readerDelegate, showsZBarControls, + supportedOrientationsMask, tracksSymbols, enableCache, cameraOverlayView, + cameraViewTransform, readerView, scanCrop; @dynamic sourceType, allowsEditing, allowsImageEditing, showsCameraControls, showsHelpOnFail, cameraMode, takesPicture, maxScanDimension; @@ -60,6 +61,8 @@ - (id) init self.wantsFullScreenLayout = YES; + supportedOrientationsMask = + ZBarOrientationMask(UIInterfaceOrientationPortrait); showsZBarControls = tracksSymbols = enableCache = YES; scanCrop = CGRectMake(0, 0, 1, 1); cameraViewTransform = CGAffineTransformIdentity; @@ -118,6 +121,10 @@ - (void) initControls r.size.height = 54; controls = [[UIView alloc] initWithFrame: r]; + controls.autoresizingMask = + UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight | + UIViewAutoresizingFlexibleTopMargin; controls.backgroundColor = [UIColor blackColor]; UIToolbar *toolbar = @@ -125,6 +132,9 @@ - (void) initControls r.origin.y = 0; toolbar.frame = r; toolbar.barStyle = UIBarStyleBlackOpaque; + toolbar.autoresizingMask = + UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight; UIButton *info = [UIButton buttonWithType: UIButtonTypeInfoLight]; @@ -170,9 +180,20 @@ - (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; + readerView.frame = CGRectMake(0, 0, + bounds.size.width, + bounds.size.height - 54); + readerView.autoresizingMask = + UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight | + UIViewAutoresizingFlexibleBottomMargin; readerView.readerDelegate = (id)self; readerView.scanCrop = scanCrop; readerView.previewTransform = cameraViewTransform; @@ -183,6 +204,7 @@ - (void) viewDidLoad if(cameraOverlayView) { assert(!cameraOverlayView.superview); [cameraOverlayView removeFromSuperview]; + cameraOverlayView.frame = readerView.frame; [view addSubview: cameraOverlayView]; } @@ -238,6 +260,26 @@ - (void) viewWillDisappear: (BOOL) animated [super viewWillDisappear: animated]; } +- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) orient +{ + return((supportedOrientationsMask >> orient) & 1); +} + +- (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) orient + duration: (NSTimeInterval) duration +{ + [readerView willRotateToInterfaceOrientation: orient + duration: duration]; +} + +- (void) willAnimateRotationToInterfaceOrientation: (UIInterfaceOrientation) orient + duration: (NSTimeInterval) duration +{ + if(helpController) + [helpController willAnimateRotationToInterfaceOrientation: orient + duration: duration]; +} + - (ZBarReaderView*) readerView { // force view to load @@ -305,17 +347,20 @@ - (void) info - (void) showHelpWithReason: (NSString*) reason { - ZBarHelpController *help = - [[ZBarHelpController alloc] - initWithReason: reason]; - help.delegate = (id)self; - help.wantsFullScreenLayout = YES; - UIView *helpView = help.view; + if(helpController) + return; + helpController = [[ZBarHelpController alloc] + initWithReason: reason]; + helpController.delegate = (id)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]; - help.view.alpha = 1; + helpController.view.alpha = 1; [UIView commitAnimations]; } @@ -329,22 +374,24 @@ - (void) takePicture - (void) helpControllerDidFinish: (ZBarHelpController*) help { + assert(help == helpController); + [help viewWillDisappear: YES]; [UIView beginAnimations: @"ZBarHelp" - context: help]; + context: NULL]; [UIView setAnimationDelegate: self]; [UIView setAnimationDidStopSelector: @selector(removeHelp:done:context:)]; help.view.alpha = 0; [UIView commitAnimations]; } -- (void) removeHelp: (NSString*) id +- (void) removeHelp: (NSString*) tag done: (NSNumber*) done context: (void*) ctx { - if([id isEqualToString: @"ZBarHelp"]) { - ZBarHelpController *help = ctx; - [help.view removeFromSuperview]; - [help release]; + if([tag isEqualToString: @"ZBarHelp"] && helpController) { + [helpController.view removeFromSuperview]; + [helpController release]; + helpController = nil; } } diff --git a/iphone/ZBarReaderViewImpl_Capture.m b/iphone/ZBarReaderViewImpl_Capture.m index 438de7c..8b7c782 100644 --- a/iphone/ZBarReaderViewImpl_Capture.m +++ b/iphone/ZBarReaderViewImpl_Capture.m @@ -32,8 +32,9 @@ // protected APIs @interface ZBarReaderView() +- (void) _initWithImageScanner: (ZBarImageScanner*) _scanner; - (void) initSubviews; -- (void) cropUpdate; +- (void) updateCrop; - (void) setImageSize: (CGSize) size; - (void) didTrackSymbols: (ZBarSymbolSet*) syms; @end @@ -53,11 +54,9 @@ @implementation ZBarReaderViewImpl @synthesize device, session, captureReader; -- (id) initWithImageScanner: (ZBarImageScanner*) scanner +- (void) _initWithImageScanner: (ZBarImageScanner*) scanner { - self = [super initWithImageScanner: scanner]; - if(!self) - return(nil); + [super _initWithImageScanner: scanner]; session = [AVCaptureSession new]; NSNotificationCenter *notify = @@ -100,8 +99,6 @@ - (id) initWithImageScanner: (ZBarImageScanner*) scanner context: NULL]; [self initSubviews]; - [self cropUpdate]; - return(self); } - (void) initSubviews @@ -116,9 +113,6 @@ - (void) initSubviews [self.layer addSublayer: preview]; [super initSubviews]; - - // camera image is rotated - overlay.transform = CATransform3DMakeRotation(M_PI / 2, 0, 0, 1); } - (void) dealloc @@ -149,10 +143,10 @@ - (void) dealloc [super dealloc]; } -- (void) cropUpdate +- (void) updateCrop { - [super cropUpdate]; - captureReader.scanCrop = zoomCrop; + [super updateCrop]; + captureReader.scanCrop = effectiveCrop; } - (ZBarImageScanner*) scanner @@ -180,7 +174,7 @@ - (void) setDevice: (AVCaptureDevice*) newdev [session beginConfiguration]; if(oldinput) - [session removeInput: input]; + [session removeInput: oldinput]; if(input) [session addInput: input]; [session commitConfiguration]; diff --git a/iphone/ZBarReaderViewImpl_Simulator.m b/iphone/ZBarReaderViewImpl_Simulator.m index 430a72a..cc426cc 100644 --- a/iphone/ZBarReaderViewImpl_Simulator.m +++ b/iphone/ZBarReaderViewImpl_Simulator.m @@ -51,8 +51,17 @@ - (void) takePicture [UIImagePickerController new]; picker.delegate = (id)self; - [self presentModalViewController: picker - animated: YES]; + if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { + simPopover = [[UIPopoverController alloc] + initWithContentViewController: picker]; + [simPopover presentPopoverFromRect: CGRectZero + inView: self.view + permittedArrowDirections: UIPopoverArrowDirectionAny + animated: YES]; + } + else + [self presentModalViewController: picker + animated: YES]; [picker release]; } @@ -66,7 +75,15 @@ - (void) imagePickerController: (UIImagePickerController*) picker didFinishPickingMediaWithInfo: (NSDictionary*) info { UIImage *image = [info objectForKey: UIImagePickerControllerOriginalImage]; - [picker dismissModalViewControllerAnimated: YES]; + + if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { + [simPopover dismissPopoverAnimated: YES]; + [simPopover release]; + simPopover = nil; + } + else + [picker dismissModalViewControllerAnimated: YES]; + [readerView performSelector: @selector(scanImage:) withObject: image afterDelay: .1]; @@ -77,10 +94,17 @@ - (void) imagePickerControllerDidCancel: (UIImagePickerController*) picker [picker dismissModalViewControllerAnimated: YES]; } +- (void) popoverControllerDidDismissPopover: (UIPopoverController*) popover +{ + [simPopover release]; + simPopover = nil; +} + @end // protected APIs @interface ZBarReaderView() +- (void) _initWithImageScanner: (ZBarImageScanner*) _scanner; - (void) initSubviews; - (void) setImageSize: (CGSize) size; - (void) didTrackSymbols: (ZBarSymbolSet*) syms; @@ -90,6 +114,7 @@ @interface ZBarReaderViewImpl : ZBarReaderView { ZBarImageScanner *scanner; + UILabel *simLabel; UIImage *scanImage; CALayer *previewImage; BOOL enableCache; @@ -100,39 +125,33 @@ @implementation ZBarReaderViewImpl @synthesize scanner, enableCache; -- (id) initWithImageScanner: (ZBarImageScanner*) _scanner +- (void) _initWithImageScanner: (ZBarImageScanner*) _scanner { - self = [super initWithImageScanner: _scanner]; - if(!self) - return(nil); - + [super _initWithImageScanner: _scanner]; scanner = [_scanner retain]; [self initSubviews]; - return(self); } - (void) initSubviews { - UILabel *label = - [[UILabel alloc] - initWithFrame: CGRectMake(16, 165, 288, 96)]; - label.backgroundColor = [UIColor clearColor]; - label.textColor = [UIColor whiteColor]; - label.font = [UIFont boldSystemFontOfSize: 20]; - label.numberOfLines = 4; - label.textAlignment = UITextAlignmentCenter; - label.text = @"Camera Simulation\n\n" + 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"; - [self addSubview: label]; - [label release]; + simLabel.autoresizingMask = + UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight; + [self addSubview: simLabel]; preview = [CALayer new]; - preview.frame = self.bounds; [self.layer addSublayer: preview]; previewImage = [CALayer new]; - previewImage.frame = self.bounds; [preview addSublayer: previewImage]; [super initSubviews]; @@ -142,11 +161,22 @@ - (void) dealloc { [scanner release]; scanner = nil; + [simLabel release]; + simLabel = nil; [previewImage release]; previewImage = nil; [super dealloc]; } +- (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) @@ -173,11 +203,11 @@ - (void) scanImage: (UIImage*) image orientation: UIImageOrientationUp]; [self setImageSize: image.size]; + [self layoutIfNeeded]; [CATransaction begin]; [CATransaction setDisableActions: YES]; - previewImage.contentsScale = imageScale; - previewImage.contentsGravity = kCAGravityCenter; + previewImage.contentsGravity = kCAGravityResizeAspectFill; previewImage.transform = CATransform3DMakeRotation(M_PI_2, 0, 0, 1); previewImage.contents = (id)cgimage; [CATransaction commit]; @@ -187,10 +217,10 @@ - (void) scanImage: (UIImage*) image initWithCGImage: cgimage]; CGSize size = zimg.size; - zimg.crop = CGRectMake(zoomCrop.origin.x * size.width, - zoomCrop.origin.y * size.height, - zoomCrop.size.width * size.width, - zoomCrop.size.height * size.height); + 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", diff --git a/iphone/examples/readertest/readertest.m b/iphone/examples/readertest/readertest.m index 8325f72..b748de5 100644 --- a/iphone/examples/readertest/readertest.m +++ b/iphone/examples/readertest/readertest.m @@ -84,6 +84,7 @@ - (void) initReader: (NSString*) clsName assert(reader); reader.readerDelegate = self; xDensity = yDensity = 3; + reader.supportedOrientationsMask = ZBarOrientationMaskAll; #if 0 // apply defaults for demo diff --git a/iphone/include/ZBarSDK/ZBarCaptureReader.h b/iphone/include/ZBarSDK/ZBarCaptureReader.h index 903c838..e466130 100644 --- a/iphone/include/ZBarSDK/ZBarCaptureReader.h +++ b/iphone/include/ZBarSDK/ZBarCaptureReader.h @@ -46,6 +46,7 @@ @interface ZBarCaptureReader : NSObject { +#if !TARGET_IPHONE_SIMULATOR AVCaptureVideoDataOutput *captureOutput; id captureDelegate; ZBarImageScanner *scanner; @@ -62,6 +63,7 @@ unsigned width, height; uint64_t t_frame, t_fps, t_scan; CGFloat dt_frame; +#endif } // supply a pre-configured image scanner diff --git a/iphone/include/ZBarSDK/ZBarReaderView.h b/iphone/include/ZBarSDK/ZBarReaderView.h index b06dd04..83aa831 100644 --- a/iphone/include/ZBarSDK/ZBarReaderView.h +++ b/iphone/include/ZBarSDK/ZBarReaderView.h @@ -46,18 +46,21 @@ : UIView { id readerDelegate; - CGRect scanCrop, zoomCrop; + CGRect scanCrop, effectiveCrop; CGAffineTransform previewTransform; CGFloat zoom, zoom0; UIColor *trackingColor; BOOL tracksSymbols, showsFPS; NSInteger torchMode; + UIInterfaceOrientation interfaceOrientation; + NSTimeInterval animationDuration; - CALayer *preview, *overlay, *tracking; + CALayer *preview, *overlay, *tracking, *cropLayer; UIView *fpsView; UILabel *fpsLabel; UIPinchGestureRecognizer *pinch; CGFloat imageScale; + CGSize imageSize; BOOL started, running; } @@ -73,6 +76,10 @@ // clear the internal result cache - (void) flushCache; +// compensate for device/camera/interface orientation +- (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) orient + duration: (NSTimeInterval) duration; + // delegate is notified of decode results. @property (nonatomic, assign) id readerDelegate; @@ -101,6 +108,8 @@ // also updated by pinch-zoom gesture. clipped to range [1,2], // defaults to 1.25 @property (nonatomic) CGFloat zoom; +- (void) setZoom: (CGFloat) zoom + animated: (BOOL) animated; // the region of the image that will be scanned. normalized coordinates. @property (nonatomic) CGRect scanCrop; diff --git a/iphone/include/ZBarSDK/ZBarReaderViewController.h b/iphone/include/ZBarSDK/ZBarReaderViewController.h index f1403da..3bc1bd9 100644 --- a/iphone/include/ZBarSDK/ZBarReaderViewController.h +++ b/iphone/include/ZBarSDK/ZBarReaderViewController.h @@ -24,6 +24,14 @@ #import #import "ZBarReaderController.h" +// orientation set support +#define ZBarOrientationMask(orient) (1 << orient) +#define ZBarOrientationMaskAll \ + (ZBarOrientationMask(UIInterfaceOrientationPortrait) | \ + ZBarOrientationMask(UIInterfaceOrientationPortraitUpsideDown) | \ + ZBarOrientationMask(UIInterfaceOrientationLandscapeLeft) | \ + ZBarOrientationMask(UIInterfaceOrientationLandscapeRight)) + @class ZBarReaderView; // drop in video scanning replacement for ZBarReaderController. @@ -41,10 +49,13 @@ UIView *cameraOverlayView; CGAffineTransform cameraViewTransform; CGRect scanCrop; + NSUInteger supportedOrientationsMask; BOOL showsZBarControls, tracksSymbols, enableCache; + ZBarHelpController *helpController; UIView *controls; BOOL didHideStatusBar; + UIPopoverController *simPopover; } // access to configure image scanner @@ -60,6 +71,10 @@ // enabled, the box will only be visible when scanning EAN and I2/5. @property (nonatomic) BOOL tracksSymbols; +// interface orientation support. bit-mask of accepted orientations. +// see eg ZBarOrientationMask() and ZBarOrientationMaskAll +@property (nonatomic) NSUInteger supportedOrientationsMask; + // crop images for scanning. the image will be cropped to this // rectangle before scanning. the rectangle is normalized to the // image size and aspect ratio; useful values will place the rectangle diff --git a/iphone/zbar.xcodeproj/project.pbxproj b/iphone/zbar.xcodeproj/project.pbxproj index 0616793..2a87ec1 100644 --- a/iphone/zbar.xcodeproj/project.pbxproj +++ b/iphone/zbar.xcodeproj/project.pbxproj @@ -882,8 +882,10 @@ ); INFOPLIST_FILE = examples/readertest/readertest.plist; INSTALL_PATH = "$(HOME)/Applications"; + IPHONEOS_DEPLOYMENT_TARGET = 4.0; PREBINDING = NO; PRODUCT_NAME = readertest; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; @@ -902,8 +904,10 @@ ); INFOPLIST_FILE = examples/readertest/readertest.plist; INSTALL_PATH = "$(HOME)/Applications"; + IPHONEOS_DEPLOYMENT_TARGET = 4.0; PREBINDING = NO; PRODUCT_NAME = readertest; + TARGETED_DEVICE_FAMILY = "1,2"; ZERO_LINK = NO; }; name = Release; @@ -988,8 +992,10 @@ ); INFOPLIST_FILE = examples/readertest/readertest.plist; INSTALL_PATH = "$(HOME)/Applications"; + IPHONEOS_DEPLOYMENT_TARGET = 4.0; PREBINDING = NO; PRODUCT_NAME = readertest; + TARGETED_DEVICE_FAMILY = "1,2"; ZERO_LINK = NO; }; name = Distribution; From 7245e9266eb4503115494d327054392f60856c8a Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 2 May 2011 15:32:28 -0700 Subject: [PATCH 279/328] fix image scanner min quality filtering --- ChangeLog | 1 + zbar/img_scanner.c | 22 +++++++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 078b456..ab335f4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * fix image scanner min quality filtering * fix i25 buffer overrun corner case * fix EAN addon enables * fix zbarimg to accept autodetected stdin (lone dash) diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 8474248..7f2add1 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -815,9 +815,19 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, zbar_symbol_t **symp; for(symp = &syms->head; *symp; ) { zbar_symbol_t *sym = *symp; - if((sym->type < ZBAR_COMPOSITE && sym->type > ZBAR_PARTIAL) || + if(sym->cache_count <= 0 && + (sym->type < ZBAR_COMPOSITE && sym->type > ZBAR_PARTIAL) || (sym->type == ZBAR_DATABAR || sym->type == ZBAR_DATABAR_EXP)) { if(filter && sym->quality < 4) { + if(iscn->enable_cache) { + /* revert cache update */ + zbar_symbol_t *entry = cache_lookup(iscn, sym); + if(entry) + entry->cache_count--; + else + assert(0); + } + /* recycle */ *symp = sym->next; syms->nsyms--; @@ -825,10 +835,12 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, _zbar_image_scanner_recycle_syms(iscn, sym); continue; } - else if(sym->type > ZBAR_EAN5) - nean++; - else - naddon++; + else if(sym->type < ZBAR_COMPOSITE) { + if(sym->type > ZBAR_EAN5) + nean++; + else + naddon++; + } } symp = &sym->next; } From 77da4e74749939ba9ee88ea52da6e20dfac5aa2b Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 2 May 2011 15:48:06 -0700 Subject: [PATCH 280/328] iPhone: fix readertest max quality result filtering - thanks to John Boydon for finding this! --- iphone/ChangeLog | 2 ++ iphone/examples/readertest/readertest.m | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index f2736e1..fa50e5f 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,6 @@ current: + * 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 diff --git a/iphone/examples/readertest/readertest.m b/iphone/examples/readertest/readertest.m index b748de5..bd1dfc5 100644 --- a/iphone/examples/readertest/readertest.m +++ b/iphone/examples/readertest/readertest.m @@ -844,9 +844,13 @@ - (void) imagePickerController: (UIImagePickerController*) picker int quality = 0; ZBarSymbol *bestResult = nil; - for(ZBarSymbol *sym in results) - if(sym.quality > quality) + for(ZBarSymbol *sym in results) { + int q = sym.quality; + if(quality < q) { + quality = q; bestResult = sym; + } + } [self performSelector: @selector(presentResult:) withObject: bestResult From f7a2db22590798eb85965857152fb523aabb10d6 Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 3 May 2011 08:33:37 -0700 Subject: [PATCH 281/328] iPhone: add embedded reader sample - factor out camera simulation logic --- iphone/ChangeLog | 2 + iphone/ZBarCameraSimulator.m | 114 +++++ iphone/ZBarReaderViewController.m | 22 +- iphone/ZBarReaderViewImpl_Capture.m | 1 + iphone/ZBarReaderViewImpl_Simulator.m | 73 --- iphone/bin/CreateDMG.sh | 2 +- .../EmbedReader.xcodeproj/project.pbxproj | 411 ++++++++++++++++ .../EmbedReader/EmbedReader-Info.plist | 38 ++ .../EmbedReader/EmbedReader-Prefix.pch | 11 + .../EmbedReader/EmbedReaderAppDelegate.h | 21 + .../EmbedReader/EmbedReaderAppDelegate.m | 34 ++ .../EmbedReader/EmbedReaderViewController.h | 22 + .../EmbedReader/EmbedReaderViewController.m | 88 ++++ .../en.lproj/EmbedReaderViewController.xib | 336 +++++++++++++ .../EmbedReader/en.lproj/InfoPlist.strings | 2 + .../EmbedReader/en.lproj/MainWindow.xib | 444 ++++++++++++++++++ .../examples/EmbedReader/EmbedReader/main.m | 16 + iphone/examples/EmbedReader/ZBarSDK | 1 + iphone/include/ZBarSDK/ZBarCameraSimulator.h | 45 ++ .../ZBarSDK/ZBarReaderViewController.h | 4 +- iphone/include/ZBarSDK/ZBarSDK.h | 1 + iphone/zbar.xcodeproj/project.pbxproj | 8 + 22 files changed, 1613 insertions(+), 83 deletions(-) create mode 100644 iphone/ZBarCameraSimulator.m create mode 100644 iphone/examples/EmbedReader/EmbedReader.xcodeproj/project.pbxproj create mode 100644 iphone/examples/EmbedReader/EmbedReader/EmbedReader-Info.plist create mode 100644 iphone/examples/EmbedReader/EmbedReader/EmbedReader-Prefix.pch create mode 100644 iphone/examples/EmbedReader/EmbedReader/EmbedReaderAppDelegate.h create mode 100644 iphone/examples/EmbedReader/EmbedReader/EmbedReaderAppDelegate.m create mode 100644 iphone/examples/EmbedReader/EmbedReader/EmbedReaderViewController.h create mode 100644 iphone/examples/EmbedReader/EmbedReader/EmbedReaderViewController.m create mode 100644 iphone/examples/EmbedReader/EmbedReader/en.lproj/EmbedReaderViewController.xib create mode 100644 iphone/examples/EmbedReader/EmbedReader/en.lproj/InfoPlist.strings create mode 100644 iphone/examples/EmbedReader/EmbedReader/en.lproj/MainWindow.xib create mode 100644 iphone/examples/EmbedReader/EmbedReader/main.m create mode 120000 iphone/examples/EmbedReader/ZBarSDK create mode 100644 iphone/include/ZBarSDK/ZBarCameraSimulator.h diff --git a/iphone/ChangeLog b/iphone/ChangeLog index fa50e5f..333f094 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,6 @@ current: + * 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 diff --git a/iphone/ZBarCameraSimulator.m b/iphone/ZBarCameraSimulator.m new file mode 100644 index 0000000..2ed4839 --- /dev/null +++ b/iphone/ZBarCameraSimulator.m @@ -0,0 +1,114 @@ +//------------------------------------------------------------------------ +// Copyright 2010-2011 (c) Jeff Brown +// +// 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 +#import + +// 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(takePicture)]; + gesture.numberOfTouchesRequired = 2; + [view addGestureRecognizer: gesture]; + [gesture release]; +} + +- (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 diff --git a/iphone/ZBarReaderViewController.m b/iphone/ZBarReaderViewController.m index 1936edd..bf5143f 100644 --- a/iphone/ZBarReaderViewController.m +++ b/iphone/ZBarReaderViewController.m @@ -25,6 +25,7 @@ #import #import #import +#import #define MODULE ZBarReaderViewController #import "debug.h" @@ -82,6 +83,9 @@ - (id) init - (void) cleanup { + cameraSim.readerView = nil; + [cameraSim release]; + cameraSim = nil; readerView.readerDelegate = nil; [readerView release]; readerView = nil; @@ -164,11 +168,6 @@ - (void) initControls [view addSubview: controls]; } -- (void) initSimulator -{ - // simulator specific hooks -} - - (void) loadView { self.view = [[UIView alloc] @@ -209,7 +208,12 @@ - (void) viewDidLoad } [self initControls]; - [self initSimulator]; + + if(TARGET_IPHONE_SIMULATOR) { + cameraSim = [[ZBarCameraSimulator alloc] + initWithViewController: self]; + cameraSim.readerView = readerView; + } } - (void) viewDidUnload @@ -366,7 +370,11 @@ - (void) showHelpWithReason: (NSString*) reason - (void) takePicture { - if(readerView) + if(TARGET_IPHONE_SIMULATOR) { + [cameraSim takePicture]; + // FIXME return selected image + } + else if(readerView) [readerView.captureReader captureFrame]; } diff --git a/iphone/ZBarReaderViewImpl_Capture.m b/iphone/ZBarReaderViewImpl_Capture.m index 8b7c782..7d6774c 100644 --- a/iphone/ZBarReaderViewImpl_Capture.m +++ b/iphone/ZBarReaderViewImpl_Capture.m @@ -244,6 +244,7 @@ - (void) flushCache [captureReader flushCache]; } + // AVCaptureSession notifications - (void) onVideoStart: (NSNotification*) note diff --git a/iphone/ZBarReaderViewImpl_Simulator.m b/iphone/ZBarReaderViewImpl_Simulator.m index cc426cc..ee808ba 100644 --- a/iphone/ZBarReaderViewImpl_Simulator.m +++ b/iphone/ZBarReaderViewImpl_Simulator.m @@ -29,79 +29,6 @@ // hack around missing simulator support for AVCapture interfaces -@interface ZBarReaderViewController(Simulator) -@end - -@implementation ZBarReaderViewController(Simulator) - -- (void) initSimulator -{ - UILongPressGestureRecognizer *press = - [[UILongPressGestureRecognizer alloc] - initWithTarget: self - action: @selector(didLongPress:)]; - [self.view addGestureRecognizer: press]; - press.numberOfTouchesRequired = 2; - [press release]; -} - -- (void) takePicture -{ - UIImagePickerController *picker = - [UIImagePickerController new]; - picker.delegate = (id)self; - if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - simPopover = [[UIPopoverController alloc] - initWithContentViewController: picker]; - [simPopover presentPopoverFromRect: CGRectZero - inView: self.view - permittedArrowDirections: UIPopoverArrowDirectionAny - animated: YES]; - } - else - [self presentModalViewController: picker - animated: YES]; - [picker release]; -} - -- (void) didLongPress: (UIGestureRecognizer*) press -{ - if(press.state == UIGestureRecognizerStateBegan) - [self takePicture]; -} - -- (void) imagePickerController: (UIImagePickerController*) picker - didFinishPickingMediaWithInfo: (NSDictionary*) info -{ - UIImage *image = [info objectForKey: UIImagePickerControllerOriginalImage]; - - if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - [simPopover dismissPopoverAnimated: YES]; - [simPopover release]; - simPopover = nil; - } - else - [picker dismissModalViewControllerAnimated: YES]; - - [readerView performSelector: @selector(scanImage:) - withObject: image - afterDelay: .1]; -} - -- (void) imagePickerControllerDidCancel: (UIImagePickerController*) picker -{ - [picker dismissModalViewControllerAnimated: YES]; -} - -- (void) popoverControllerDidDismissPopover: (UIPopoverController*) popover -{ - [simPopover release]; - simPopover = nil; -} - -@end - // protected APIs @interface ZBarReaderView() - (void) _initWithImageScanner: (ZBarImageScanner*) _scanner; diff --git a/iphone/bin/CreateDMG.sh b/iphone/bin/CreateDMG.sh index a13c141..22c3c78 100755 --- a/iphone/bin/CreateDMG.sh +++ b/iphone/bin/CreateDMG.sh @@ -24,7 +24,7 @@ done # prepare examples for distribution for example in $(find $TARGET_BUILD_DIR/Examples -depth 1) do - rm -rf $example/{*.xcodeproj/*.{mode1v3,pbxuser},ZBarSDK} + rm -rf $example/{build,*.xcodeproj/{*.{mode1v3,pbxuser},project.xcworkspace,xcuserdata},ZBarSDK} cp -af $BUILT_PRODUCTS_DIR/ZBarSDK $example/ done diff --git a/iphone/examples/EmbedReader/EmbedReader.xcodeproj/project.pbxproj b/iphone/examples/EmbedReader/EmbedReader.xcodeproj/project.pbxproj new file mode 100644 index 0000000..3e519c1 --- /dev/null +++ b/iphone/examples/EmbedReader/EmbedReader.xcodeproj/project.pbxproj @@ -0,0 +1,411 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + DCFB4494136F7202004B3EE0 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCFB4493136F7202004B3EE0 /* UIKit.framework */; }; + DCFB4496136F7202004B3EE0 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCFB4495136F7202004B3EE0 /* Foundation.framework */; }; + DCFB4498136F7202004B3EE0 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCFB4497136F7202004B3EE0 /* CoreGraphics.framework */; }; + DCFB449E136F7203004B3EE0 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DCFB449C136F7203004B3EE0 /* InfoPlist.strings */; }; + DCFB44A1136F7203004B3EE0 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DCFB44A0136F7203004B3EE0 /* main.m */; }; + DCFB44A4136F7203004B3EE0 /* EmbedReaderAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DCFB44A3136F7203004B3EE0 /* EmbedReaderAppDelegate.m */; }; + DCFB44A7136F7203004B3EE0 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = DCFB44A5136F7203004B3EE0 /* MainWindow.xib */; }; + DCFB44AA136F7203004B3EE0 /* EmbedReaderViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DCFB44A9136F7203004B3EE0 /* EmbedReaderViewController.m */; }; + DCFB44AD136F7203004B3EE0 /* EmbedReaderViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = DCFB44AB136F7203004B3EE0 /* EmbedReaderViewController.xib */; }; + DCFB44D0136F722A004B3EE0 /* libzbar.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCFB44CA136F722A004B3EE0 /* libzbar.a */; }; + DCFB44D1136F722A004B3EE0 /* zbar-back.png in Resources */ = {isa = PBXBuildFile; fileRef = DCFB44CC136F722A004B3EE0 /* zbar-back.png */; }; + DCFB44D2136F722A004B3EE0 /* zbar-help.html in Resources */ = {isa = PBXBuildFile; fileRef = DCFB44CD136F722A004B3EE0 /* zbar-help.html */; }; + DCFB44D3136F722A004B3EE0 /* zbar-helpicons.png in Resources */ = {isa = PBXBuildFile; fileRef = DCFB44CE136F722A004B3EE0 /* zbar-helpicons.png */; }; + DCFB44D4136F722A004B3EE0 /* zbar-samples.png in Resources */ = {isa = PBXBuildFile; fileRef = DCFB44CF136F722A004B3EE0 /* zbar-samples.png */; }; + DCFB44DA136F72D3004B3EE0 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCFB44D5136F72D3004B3EE0 /* AVFoundation.framework */; }; + DCFB44DB136F72D3004B3EE0 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCFB44D6136F72D3004B3EE0 /* CoreMedia.framework */; }; + DCFB44DC136F72D3004B3EE0 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCFB44D7136F72D3004B3EE0 /* CoreVideo.framework */; }; + DCFB44DD136F72D3004B3EE0 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DCFB44D8136F72D3004B3EE0 /* libiconv.dylib */; }; + DCFB44DE136F72D3004B3EE0 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCFB44D9136F72D3004B3EE0 /* QuartzCore.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + DCFB448F136F7202004B3EE0 /* EmbedReader.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EmbedReader.app; sourceTree = BUILT_PRODUCTS_DIR; }; + DCFB4493136F7202004B3EE0 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + DCFB4495136F7202004B3EE0 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + DCFB4497136F7202004B3EE0 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + DCFB449B136F7202004B3EE0 /* EmbedReader-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "EmbedReader-Info.plist"; sourceTree = ""; }; + DCFB449D136F7203004B3EE0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + DCFB449F136F7203004B3EE0 /* EmbedReader-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "EmbedReader-Prefix.pch"; sourceTree = ""; }; + DCFB44A0136F7203004B3EE0 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + DCFB44A2136F7203004B3EE0 /* EmbedReaderAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EmbedReaderAppDelegate.h; sourceTree = ""; }; + DCFB44A3136F7203004B3EE0 /* EmbedReaderAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EmbedReaderAppDelegate.m; sourceTree = ""; }; + DCFB44A6136F7203004B3EE0 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainWindow.xib; sourceTree = ""; }; + DCFB44A8136F7203004B3EE0 /* EmbedReaderViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EmbedReaderViewController.h; sourceTree = ""; }; + DCFB44A9136F7203004B3EE0 /* EmbedReaderViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EmbedReaderViewController.m; sourceTree = ""; }; + DCFB44AC136F7203004B3EE0 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/EmbedReaderViewController.xib; sourceTree = ""; }; + DCFB44B7136F722A004B3EE0 /* Decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Decoder.h; sourceTree = ""; }; + DCFB44B8136F722A004B3EE0 /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = ""; }; + DCFB44B9136F722A004B3EE0 /* Image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Image.h; sourceTree = ""; }; + DCFB44BA136F722A004B3EE0 /* ImageScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageScanner.h; sourceTree = ""; }; + DCFB44BB136F722A004B3EE0 /* Processor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Processor.h; sourceTree = ""; }; + DCFB44BC136F722A004B3EE0 /* Scanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Scanner.h; sourceTree = ""; }; + DCFB44BD136F722A004B3EE0 /* Symbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Symbol.h; sourceTree = ""; }; + DCFB44BE136F722A004B3EE0 /* Video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Video.h; sourceTree = ""; }; + DCFB44BF136F722A004B3EE0 /* Window.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Window.h; sourceTree = ""; }; + DCFB44C0136F722A004B3EE0 /* zbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zbar.h; sourceTree = ""; }; + DCFB44C1136F722A004B3EE0 /* ZBarCaptureReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarCaptureReader.h; sourceTree = ""; }; + DCFB44C2136F722A004B3EE0 /* ZBarHelpController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarHelpController.h; sourceTree = ""; }; + DCFB44C3136F722A004B3EE0 /* ZBarImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarImage.h; sourceTree = ""; }; + DCFB44C4136F722A004B3EE0 /* ZBarImageScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarImageScanner.h; sourceTree = ""; }; + DCFB44C5136F722A004B3EE0 /* ZBarReaderController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarReaderController.h; sourceTree = ""; }; + DCFB44C6136F722A004B3EE0 /* ZBarReaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarReaderView.h; sourceTree = ""; }; + DCFB44C7136F722A004B3EE0 /* ZBarReaderViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarReaderViewController.h; sourceTree = ""; }; + DCFB44C8136F722A004B3EE0 /* ZBarSDK.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarSDK.h; sourceTree = ""; }; + DCFB44C9136F722A004B3EE0 /* ZBarSymbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarSymbol.h; sourceTree = ""; }; + DCFB44CA136F722A004B3EE0 /* libzbar.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libzbar.a; sourceTree = ""; }; + DCFB44CC136F722A004B3EE0 /* zbar-back.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "zbar-back.png"; sourceTree = ""; }; + DCFB44CD136F722A004B3EE0 /* zbar-help.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "zbar-help.html"; sourceTree = ""; }; + DCFB44CE136F722A004B3EE0 /* zbar-helpicons.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "zbar-helpicons.png"; sourceTree = ""; }; + DCFB44CF136F722A004B3EE0 /* zbar-samples.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "zbar-samples.png"; sourceTree = ""; }; + DCFB44D5136F72D3004B3EE0 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; + DCFB44D6136F72D3004B3EE0 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; }; + DCFB44D7136F72D3004B3EE0 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; }; + DCFB44D8136F72D3004B3EE0 /* libiconv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libiconv.dylib; path = usr/lib/libiconv.dylib; sourceTree = SDKROOT; }; + DCFB44D9136F72D3004B3EE0 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + DCFB448C136F7202004B3EE0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DCFB4494136F7202004B3EE0 /* UIKit.framework in Frameworks */, + DCFB4496136F7202004B3EE0 /* Foundation.framework in Frameworks */, + DCFB4498136F7202004B3EE0 /* CoreGraphics.framework in Frameworks */, + DCFB44DE136F72D3004B3EE0 /* QuartzCore.framework in Frameworks */, + DCFB44DB136F72D3004B3EE0 /* CoreMedia.framework in Frameworks */, + DCFB44DC136F72D3004B3EE0 /* CoreVideo.framework in Frameworks */, + DCFB44DA136F72D3004B3EE0 /* AVFoundation.framework in Frameworks */, + DCFB44DD136F72D3004B3EE0 /* libiconv.dylib in Frameworks */, + DCFB44D0136F722A004B3EE0 /* libzbar.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + DCFB4484136F7202004B3EE0 = { + isa = PBXGroup; + children = ( + DCFB4499136F7202004B3EE0 /* EmbedReader */, + DCFB44B3136F722A004B3EE0 /* ZBarSDK */, + DCFB4492136F7202004B3EE0 /* Frameworks */, + DCFB4490136F7202004B3EE0 /* Products */, + ); + sourceTree = ""; + }; + DCFB4490136F7202004B3EE0 /* Products */ = { + isa = PBXGroup; + children = ( + DCFB448F136F7202004B3EE0 /* EmbedReader.app */, + ); + name = Products; + sourceTree = ""; + }; + DCFB4492136F7202004B3EE0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + DCFB4493136F7202004B3EE0 /* UIKit.framework */, + DCFB4495136F7202004B3EE0 /* Foundation.framework */, + DCFB4497136F7202004B3EE0 /* CoreGraphics.framework */, + DCFB44D9136F72D3004B3EE0 /* QuartzCore.framework */, + DCFB44D6136F72D3004B3EE0 /* CoreMedia.framework */, + DCFB44D7136F72D3004B3EE0 /* CoreVideo.framework */, + DCFB44D5136F72D3004B3EE0 /* AVFoundation.framework */, + DCFB44D8136F72D3004B3EE0 /* libiconv.dylib */, + ); + name = Frameworks; + sourceTree = ""; + }; + DCFB4499136F7202004B3EE0 /* EmbedReader */ = { + isa = PBXGroup; + children = ( + DCFB44A2136F7203004B3EE0 /* EmbedReaderAppDelegate.h */, + DCFB44A3136F7203004B3EE0 /* EmbedReaderAppDelegate.m */, + DCFB44A5136F7203004B3EE0 /* MainWindow.xib */, + DCFB44A8136F7203004B3EE0 /* EmbedReaderViewController.h */, + DCFB44A9136F7203004B3EE0 /* EmbedReaderViewController.m */, + DCFB44AB136F7203004B3EE0 /* EmbedReaderViewController.xib */, + DCFB449A136F7202004B3EE0 /* Supporting Files */, + ); + path = EmbedReader; + sourceTree = ""; + }; + DCFB449A136F7202004B3EE0 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + DCFB449B136F7202004B3EE0 /* EmbedReader-Info.plist */, + DCFB449C136F7203004B3EE0 /* InfoPlist.strings */, + DCFB449F136F7203004B3EE0 /* EmbedReader-Prefix.pch */, + DCFB44A0136F7203004B3EE0 /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + DCFB44B3136F722A004B3EE0 /* ZBarSDK */ = { + isa = PBXGroup; + children = ( + DCFB44B4136F722A004B3EE0 /* Headers */, + DCFB44CA136F722A004B3EE0 /* libzbar.a */, + DCFB44CB136F722A004B3EE0 /* Resources */, + ); + path = ZBarSDK; + sourceTree = ""; + }; + DCFB44B4136F722A004B3EE0 /* Headers */ = { + isa = PBXGroup; + children = ( + DCFB44B5136F722A004B3EE0 /* ZBarSDK */, + ); + path = Headers; + sourceTree = ""; + }; + DCFB44B5136F722A004B3EE0 /* ZBarSDK */ = { + isa = PBXGroup; + children = ( + DCFB44B6136F722A004B3EE0 /* zbar */, + DCFB44C0136F722A004B3EE0 /* zbar.h */, + DCFB44C1136F722A004B3EE0 /* ZBarCaptureReader.h */, + DCFB44C2136F722A004B3EE0 /* ZBarHelpController.h */, + DCFB44C3136F722A004B3EE0 /* ZBarImage.h */, + DCFB44C4136F722A004B3EE0 /* ZBarImageScanner.h */, + DCFB44C5136F722A004B3EE0 /* ZBarReaderController.h */, + DCFB44C6136F722A004B3EE0 /* ZBarReaderView.h */, + DCFB44C7136F722A004B3EE0 /* ZBarReaderViewController.h */, + DCFB44C8136F722A004B3EE0 /* ZBarSDK.h */, + DCFB44C9136F722A004B3EE0 /* ZBarSymbol.h */, + ); + path = ZBarSDK; + sourceTree = ""; + }; + DCFB44B6136F722A004B3EE0 /* zbar */ = { + isa = PBXGroup; + children = ( + DCFB44B7136F722A004B3EE0 /* Decoder.h */, + DCFB44B8136F722A004B3EE0 /* Exception.h */, + DCFB44B9136F722A004B3EE0 /* Image.h */, + DCFB44BA136F722A004B3EE0 /* ImageScanner.h */, + DCFB44BB136F722A004B3EE0 /* Processor.h */, + DCFB44BC136F722A004B3EE0 /* Scanner.h */, + DCFB44BD136F722A004B3EE0 /* Symbol.h */, + DCFB44BE136F722A004B3EE0 /* Video.h */, + DCFB44BF136F722A004B3EE0 /* Window.h */, + ); + path = zbar; + sourceTree = ""; + }; + DCFB44CB136F722A004B3EE0 /* Resources */ = { + isa = PBXGroup; + children = ( + DCFB44CC136F722A004B3EE0 /* zbar-back.png */, + DCFB44CD136F722A004B3EE0 /* zbar-help.html */, + DCFB44CE136F722A004B3EE0 /* zbar-helpicons.png */, + DCFB44CF136F722A004B3EE0 /* zbar-samples.png */, + ); + path = Resources; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + DCFB448E136F7202004B3EE0 /* EmbedReader */ = { + isa = PBXNativeTarget; + buildConfigurationList = DCFB44B0136F7203004B3EE0 /* Build configuration list for PBXNativeTarget "EmbedReader" */; + buildPhases = ( + DCFB448B136F7202004B3EE0 /* Sources */, + DCFB448C136F7202004B3EE0 /* Frameworks */, + DCFB448D136F7202004B3EE0 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = EmbedReader; + productName = EmbedReader; + productReference = DCFB448F136F7202004B3EE0 /* EmbedReader.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + DCFB4486136F7202004B3EE0 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = DCFB4489136F7202004B3EE0 /* Build configuration list for PBXProject "EmbedReader" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = DCFB4484136F7202004B3EE0; + productRefGroup = DCFB4490136F7202004B3EE0 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + DCFB448E136F7202004B3EE0 /* EmbedReader */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + DCFB448D136F7202004B3EE0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DCFB449E136F7203004B3EE0 /* InfoPlist.strings in Resources */, + DCFB44A7136F7203004B3EE0 /* MainWindow.xib in Resources */, + DCFB44AD136F7203004B3EE0 /* EmbedReaderViewController.xib in Resources */, + DCFB44D1136F722A004B3EE0 /* zbar-back.png in Resources */, + DCFB44D2136F722A004B3EE0 /* zbar-help.html in Resources */, + DCFB44D3136F722A004B3EE0 /* zbar-helpicons.png in Resources */, + DCFB44D4136F722A004B3EE0 /* zbar-samples.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + DCFB448B136F7202004B3EE0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DCFB44A1136F7203004B3EE0 /* main.m in Sources */, + DCFB44A4136F7203004B3EE0 /* EmbedReaderAppDelegate.m in Sources */, + DCFB44AA136F7203004B3EE0 /* EmbedReaderViewController.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + DCFB449C136F7203004B3EE0 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + DCFB449D136F7203004B3EE0 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + DCFB44A5136F7203004B3EE0 /* MainWindow.xib */ = { + isa = PBXVariantGroup; + children = ( + DCFB44A6136F7203004B3EE0 /* en */, + ); + name = MainWindow.xib; + sourceTree = ""; + }; + DCFB44AB136F7203004B3EE0 /* EmbedReaderViewController.xib */ = { + isa = PBXVariantGroup; + children = ( + DCFB44AC136F7203004B3EE0 /* en */, + ); + name = EmbedReaderViewController.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + DCFB44AE136F7203004B3EE0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = DEBUG; + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvmgcc42; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 4.0; + SDKROOT = iphoneos; + }; + name = Debug; + }; + DCFB44AF136F7203004B3EE0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_VERSION = com.apple.compilers.llvmgcc42; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 4.0; + OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; + SDKROOT = iphoneos; + }; + name = Release; + }; + DCFB44B1136F7203004B3EE0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "EmbedReader/EmbedReader-Prefix.pch"; + INFOPLIST_FILE = "EmbedReader/EmbedReader-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/ZBarSDK\"", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + DCFB44B2136F7203004B3EE0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "EmbedReader/EmbedReader-Prefix.pch"; + INFOPLIST_FILE = "EmbedReader/EmbedReader-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/ZBarSDK\"", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + DCFB4489136F7202004B3EE0 /* Build configuration list for PBXProject "EmbedReader" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DCFB44AE136F7203004B3EE0 /* Debug */, + DCFB44AF136F7203004B3EE0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DCFB44B0136F7203004B3EE0 /* Build configuration list for PBXNativeTarget "EmbedReader" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DCFB44B1136F7203004B3EE0 /* Debug */, + DCFB44B2136F7203004B3EE0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = DCFB4486136F7202004B3EE0 /* Project object */; +} diff --git a/iphone/examples/EmbedReader/EmbedReader/EmbedReader-Info.plist b/iphone/examples/EmbedReader/EmbedReader/EmbedReader-Info.plist new file mode 100644 index 0000000..1e72cf2 --- /dev/null +++ b/iphone/examples/EmbedReader/EmbedReader/EmbedReader-Info.plist @@ -0,0 +1,38 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + net.sourceforge.zbar.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + NSMainNibFile + MainWindow + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/iphone/examples/EmbedReader/EmbedReader/EmbedReader-Prefix.pch b/iphone/examples/EmbedReader/EmbedReader/EmbedReader-Prefix.pch new file mode 100644 index 0000000..ed6587b --- /dev/null +++ b/iphone/examples/EmbedReader/EmbedReader/EmbedReader-Prefix.pch @@ -0,0 +1,11 @@ +#import + +#ifndef __IPHONE_3_0 +#warning "This project uses features only available in iPhone SDK 3.0 and later." +#endif + +#ifdef __OBJC__ +# import +# import +# import "ZBarSDK.h" +#endif diff --git a/iphone/examples/EmbedReader/EmbedReader/EmbedReaderAppDelegate.h b/iphone/examples/EmbedReader/EmbedReader/EmbedReaderAppDelegate.h new file mode 100644 index 0000000..8a11091 --- /dev/null +++ b/iphone/examples/EmbedReader/EmbedReader/EmbedReaderAppDelegate.h @@ -0,0 +1,21 @@ +// +// EmbedReaderAppDelegate.h +// EmbedReader +// +// Created by spadix on 5/2/11. +// + +#import + +@class EmbedReaderViewController; + +@interface EmbedReaderAppDelegate + : NSObject + < UIApplicationDelegate > +{ +} + +@property (nonatomic, retain) IBOutlet UIWindow *window; +@property (nonatomic, retain) IBOutlet EmbedReaderViewController *viewController; + +@end diff --git a/iphone/examples/EmbedReader/EmbedReader/EmbedReaderAppDelegate.m b/iphone/examples/EmbedReader/EmbedReader/EmbedReaderAppDelegate.m new file mode 100644 index 0000000..5db5649 --- /dev/null +++ b/iphone/examples/EmbedReader/EmbedReader/EmbedReaderAppDelegate.m @@ -0,0 +1,34 @@ +// +// EmbedReaderAppDelegate.m +// EmbedReader +// +// Created by spadix on 5/2/11. +// + +#import "EmbedReaderAppDelegate.h" +#import "EmbedReaderViewController.h" + +@implementation EmbedReaderAppDelegate +@synthesize window=_window; +@synthesize viewController=_viewController; + +- (BOOL) application: (UIApplication*) application + didFinishLaunchingWithOptions: (NSDictionary*) launchOptions +{ + self.window.rootViewController = self.viewController; + [self.window makeKeyAndVisible]; + + // force view class to load so it may be referenced directly from NIB + [ZBarReaderView class]; + + return(YES); +} + +- (void) dealloc +{ + [_window release]; + [_viewController release]; + [super dealloc]; +} + +@end diff --git a/iphone/examples/EmbedReader/EmbedReader/EmbedReaderViewController.h b/iphone/examples/EmbedReader/EmbedReader/EmbedReaderViewController.h new file mode 100644 index 0000000..672dd29 --- /dev/null +++ b/iphone/examples/EmbedReader/EmbedReader/EmbedReaderViewController.h @@ -0,0 +1,22 @@ +// +// EmbedReaderViewController.h +// EmbedReader +// +// Created by spadix on 5/2/11. +// + +#import + +@interface EmbedReaderViewController + : UIViewController + < ZBarReaderViewDelegate > +{ + ZBarReaderView *readerView; + UITextView *resultText; + ZBarCameraSimulator *cameraSim; +} + +@property (nonatomic, retain) IBOutlet ZBarReaderView *readerView; +@property (nonatomic, retain) IBOutlet UITextView *resultText; + +@end diff --git a/iphone/examples/EmbedReader/EmbedReader/EmbedReaderViewController.m b/iphone/examples/EmbedReader/EmbedReader/EmbedReaderViewController.m new file mode 100644 index 0000000..7a3a025 --- /dev/null +++ b/iphone/examples/EmbedReader/EmbedReader/EmbedReaderViewController.m @@ -0,0 +1,88 @@ +// +// EmbedReaderViewController.m +// EmbedReader +// +// Created by spadix on 5/2/11. +// + +#import "EmbedReaderViewController.h" + +@implementation EmbedReaderViewController + +@synthesize readerView, resultText; + +- (void) cleanup +{ + [cameraSim release]; + cameraSim = nil; + readerView.readerDelegate = nil; + [readerView release]; + readerView = nil; + [resultText release]; + resultText = nil; +} + +- (void) dealloc +{ + [self cleanup]; + [super dealloc]; +} + +- (void) viewDidLoad +{ + [super viewDidLoad]; + + // the delegate receives decode results + readerView.readerDelegate = self; + + // you can use this to support the simulator + if(TARGET_IPHONE_SIMULATOR) { + cameraSim = [[ZBarCameraSimulator alloc] + initWithViewController: self]; + cameraSim.readerView = readerView; + } +} + +- (void) viewDidUnload +{ + [self cleanup]; + [super viewDidUnload]; +} + +- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) orient +{ + // auto-rotation is supported + return(YES); +} + +- (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) orient + duration: (NSTimeInterval) duration +{ + // compensate for view rotation so camera preview is not rotated + [readerView willRotateToInterfaceOrientation: orient + duration: duration]; +} + +- (void) viewDidAppear: (BOOL) animated +{ + // run the reader when the view is visible + [readerView start]; +} + +- (void) viewWillDisappear: (BOOL) animated +{ + [readerView stop]; +} + +- (void) readerView: (ZBarReaderView*) view + didReadSymbols: (ZBarSymbolSet*) syms + fromImage: (UIImage*) img +{ + // do something useful with results + for(ZBarSymbol *sym in syms) { + resultText.text = sym.data; + break; + } +} + +@end diff --git a/iphone/examples/EmbedReader/EmbedReader/en.lproj/EmbedReaderViewController.xib b/iphone/examples/EmbedReader/EmbedReader/en.lproj/EmbedReaderViewController.xib new file mode 100644 index 0000000..8f4e9dc --- /dev/null +++ b/iphone/examples/EmbedReader/EmbedReader/en.lproj/EmbedReaderViewController.xib @@ -0,0 +1,336 @@ + + + + 1056 + 10J869 + 1306 + 1038.35 + 461.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 301 + + + YES + IBUINavigationItem + IBUIToolbar + IBUITextView + IBUIView + IBUINavigationBar + IBProxyObject + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + + + YES + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + + 274 + + YES + + + 306 + {{8, 52}, {304, 228}} + + + + + 3 + MAA + + YES + YES + IBCocoaTouchFramework + + + + 290 + {320, 44} + + + + IBCocoaTouchFramework + + YES + + + EmbedReader + IBCocoaTouchFramework + + + + + + 266 + {{0, 416}, {320, 44}} + + + + NO + NO + IBCocoaTouchFramework + + YES + + + + + 314 + {{8, 300}, {304, 94}} + + + + + 3 + MCAwAA + + YES + YES + IBCocoaTouchFramework + NO + No barcode scanned... + + Helvetica + 17 + 16 + + + IBCocoaTouchFramework + + + + {{0, 20}, {320, 460}} + + + + + 3 + MC43NQA + + 2 + + + NO + + IBCocoaTouchFramework + + + + + YES + + + view + + + + 7 + + + + readerView + + + + 16 + + + + resultText + + + + 17 + + + + + YES + + 0 + + + + + + -1 + + + File's Owner + + + -2 + + + + + 6 + + + YES + + + + + + + + + 8 + + + + + 11 + + + YES + + + + + + 12 + + + + + 13 + + + YES + + + + + 15 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 11.IBPluginDependency + 12.IBPluginDependency + 13.IBPluginDependency + 15.IBPluginDependency + 6.IBEditorWindowLastContentRect + 6.IBPluginDependency + 8.CustomClassName + 8.IBPluginDependency + + + YES + EmbedReaderViewController + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + {{239, 654}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + ZBarReaderView + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + + + + YES + + + + + 18 + + + + YES + + EmbedReaderViewController + UIViewController + + YES + + YES + readerView + resultText + + + YES + ZBarReaderView + UITextView + + + + YES + + YES + readerView + resultText + + + YES + + readerView + ZBarReaderView + + + resultText + UITextView + + + + + IBProjectSource + ./Classes/EmbedReaderViewController.h + + + + ZBarReaderView + UIView + + IBProjectSource + ./Classes/ZBarReaderView.h + + + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + 3 + 301 + + diff --git a/iphone/examples/EmbedReader/EmbedReader/en.lproj/InfoPlist.strings b/iphone/examples/EmbedReader/EmbedReader/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..477b28f --- /dev/null +++ b/iphone/examples/EmbedReader/EmbedReader/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/iphone/examples/EmbedReader/EmbedReader/en.lproj/MainWindow.xib b/iphone/examples/EmbedReader/EmbedReader/en.lproj/MainWindow.xib new file mode 100644 index 0000000..dea1ac4 --- /dev/null +++ b/iphone/examples/EmbedReader/EmbedReader/en.lproj/MainWindow.xib @@ -0,0 +1,444 @@ + + + + 1024 + 10D571 + 786 + 1038.29 + 460.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 112 + + + YES + + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + YES + + + + YES + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + IBCocoaTouchFramework + + + EmbedReaderViewController + + + 1 + + IBCocoaTouchFramework + NO + + + + 292 + {320, 480} + + 1 + MSAxIDEAA + + NO + NO + + IBCocoaTouchFramework + YES + + + + + YES + + + delegate + + + + 4 + + + + viewController + + + + 11 + + + + window + + + + 14 + + + + + YES + + 0 + + + + + + -1 + + + File's Owner + + + 3 + + + EmbedReader App Delegate + + + -2 + + + + + 10 + + + + + 12 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 10.CustomClassName + 10.IBEditorWindowLastContentRect + 10.IBPluginDependency + 12.IBEditorWindowLastContentRect + 12.IBPluginDependency + 3.CustomClassName + 3.IBPluginDependency + + + YES + UIApplication + UIResponder + EmbedReaderViewController + {{234, 376}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + {{525, 346}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + EmbedReaderAppDelegate + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + YES + + + + + YES + + + YES + + + + 15 + + + + YES + + UIWindow + UIView + + IBUserSource + + + + + EmbedReaderAppDelegate + NSObject + + YES + + YES + viewController + window + + + YES + EmbedReaderViewController + UIWindow + + + + YES + + YES + viewController + window + + + YES + + viewController + EmbedReaderViewController + + + window + UIWindow + + + + + IBProjectSource + EmbedReaderAppDelegate.h + + + + EmbedReaderAppDelegate + NSObject + + IBUserSource + + + + + EmbedReaderViewController + UIViewController + + IBProjectSource + EmbedReaderViewController.h + + + + + YES + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIAccessibility.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UINibLoading.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIResponder.h + + + + UIApplication + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIApplication.h + + + + UIResponder + NSObject + + + + UISearchBar + UIView + + IBFrameworkSource + UIKit.framework/Headers/UISearchBar.h + + + + UISearchDisplayController + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UISearchDisplayController.h + + + + UIView + + IBFrameworkSource + UIKit.framework/Headers/UITextField.h + + + + UIView + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIView.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UINavigationController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UIPopoverController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UISplitViewController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UITabBarController.h + + + + UIViewController + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIViewController.h + + + + UIWindow + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIWindow.h + + + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + EmbedReader.xcodeproj + 3 + 112 + + diff --git a/iphone/examples/EmbedReader/EmbedReader/main.m b/iphone/examples/EmbedReader/EmbedReader/main.m new file mode 100644 index 0000000..e91e4ba --- /dev/null +++ b/iphone/examples/EmbedReader/EmbedReader/main.m @@ -0,0 +1,16 @@ +// +// main.m +// EmbedReader +// +// Created by spadix on 5/2/11. +// + +#import + +int main(int argc, char *argv[]) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + int retVal = UIApplicationMain(argc, argv, nil, nil); + [pool release]; + return retVal; +} diff --git a/iphone/examples/EmbedReader/ZBarSDK b/iphone/examples/EmbedReader/ZBarSDK new file mode 120000 index 0000000..b8e7666 --- /dev/null +++ b/iphone/examples/EmbedReader/ZBarSDK @@ -0,0 +1 @@ +../../build/Release-iphoneos/ZBarSDK \ No newline at end of file diff --git a/iphone/include/ZBarSDK/ZBarCameraSimulator.h b/iphone/include/ZBarSDK/ZBarCameraSimulator.h new file mode 100644 index 0000000..61bb07f --- /dev/null +++ b/iphone/include/ZBarSDK/ZBarCameraSimulator.h @@ -0,0 +1,45 @@ +//------------------------------------------------------------------------ +// Copyright 2010-2011 (c) Jeff Brown +// +// 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 +//------------------------------------------------------------------------ + +@class ZBarReaderView; + +// hack around missing simulator support for AVCapture interfaces + +@interface ZBarCameraSimulator + : NSObject + < UINavigationControllerDelegate, + UIImagePickerControllerDelegate, + UIPopoverControllerDelegate > +{ + UIViewController *viewController; + ZBarReaderView *readerView; + UIImagePickerController *picker; + UIPopoverController *pickerPopover; +} + +- (id) initWithViewController: (UIViewController*) viewController; +- (void) takePicture; + +@property (nonatomic, assign) ZBarReaderView *readerView; + +@end diff --git a/iphone/include/ZBarSDK/ZBarReaderViewController.h b/iphone/include/ZBarSDK/ZBarReaderViewController.h index 3bc1bd9..21d2ec4 100644 --- a/iphone/include/ZBarSDK/ZBarReaderViewController.h +++ b/iphone/include/ZBarSDK/ZBarReaderViewController.h @@ -32,7 +32,7 @@ ZBarOrientationMask(UIInterfaceOrientationLandscapeLeft) | \ ZBarOrientationMask(UIInterfaceOrientationLandscapeRight)) -@class ZBarReaderView; +@class ZBarReaderView, ZBarCameraSimulator; // drop in video scanning replacement for ZBarReaderController. // this is a thin controller around a ZBarReaderView that adds the UI @@ -55,7 +55,7 @@ ZBarHelpController *helpController; UIView *controls; BOOL didHideStatusBar; - UIPopoverController *simPopover; + ZBarCameraSimulator *cameraSim; } // access to configure image scanner diff --git a/iphone/include/ZBarSDK/ZBarSDK.h b/iphone/include/ZBarSDK/ZBarSDK.h index e7d5c0f..b7cd52d 100644 --- a/iphone/include/ZBarSDK/ZBarSDK.h +++ b/iphone/include/ZBarSDK/ZBarSDK.h @@ -31,3 +31,4 @@ #import "ZBarReaderController.h" #import "ZBarCaptureReader.h" #import "ZBarHelpController.h" +#import "ZBarCameraSimulator.h" diff --git a/iphone/zbar.xcodeproj/project.pbxproj b/iphone/zbar.xcodeproj/project.pbxproj index 2a87ec1..a654cc0 100644 --- a/iphone/zbar.xcodeproj/project.pbxproj +++ b/iphone/zbar.xcodeproj/project.pbxproj @@ -91,6 +91,8 @@ DC48C5A8121B1F910047193B /* Documentation.html in Copy SDK */ = {isa = PBXBuildFile; fileRef = DC48C5A7121B1F840047193B /* Documentation.html */; }; DC4920EE10A70475000E4D43 /* ZBarImage.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4920EC10A70475000E4D43 /* ZBarImage.m */; }; DC4920EF10A70475000E4D43 /* ZBarImageScanner.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4920ED10A70475000E4D43 /* ZBarImageScanner.m */; }; + DC5D76C3136FA8C40069AEF5 /* ZBarCameraSimulator.m in Sources */ = {isa = PBXBuildFile; fileRef = DC5D76C2136FA8C40069AEF5 /* ZBarCameraSimulator.m */; }; + DC5D76C6136FA94B0069AEF5 /* ZBarCameraSimulator.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = DC5D76C5136FA8F20069AEF5 /* ZBarCameraSimulator.h */; }; DC67C17110A07AD30033B702 /* config.c in Sources */ = {isa = PBXBuildFile; fileRef = DC67C11F10A07AD30033B702 /* config.c */; }; DC67C17410A07AD30033B702 /* code128.c in Sources */ = {isa = PBXBuildFile; fileRef = DC67C12310A07AD30033B702 /* code128.c */; }; DC67C17610A07AD30033B702 /* code39.c in Sources */ = {isa = PBXBuildFile; fileRef = DC67C12510A07AD30033B702 /* code39.c */; }; @@ -151,6 +153,7 @@ dstPath = Headers/ZBarSDK; dstSubfolderSpec = 1; files = ( + DC5D76C6136FA94B0069AEF5 /* ZBarCameraSimulator.h in Copy Headers */, DC3CEFB51216349700D7A786 /* ZBarCaptureReader.h in Copy Headers */, DCB3789B12A43CAC0059B07B /* ZBarHelpController.h in Copy Headers */, DC3CEFB61216349700D7A786 /* ZBarImage.h in Copy Headers */, @@ -278,6 +281,8 @@ DC50467B12034D60009FF359 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; DC50467C12034D71009FF359 /* COPYING */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = COPYING; path = ../COPYING; sourceTree = SOURCE_ROOT; }; DC50467D12034D71009FF359 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = SOURCE_ROOT; }; + DC5D76C2136FA8C40069AEF5 /* ZBarCameraSimulator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarCameraSimulator.m; sourceTree = ""; }; + DC5D76C5136FA8F20069AEF5 /* ZBarCameraSimulator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ZBarCameraSimulator.h; path = include/ZBarSDK/ZBarCameraSimulator.h; sourceTree = ""; }; DC67C08210A079BE0033B702 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; DC67C11710A07A810033B702 /* zbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = zbar.h; path = ../include/zbar.h; sourceTree = SOURCE_ROOT; usesTabs = 0; }; DC67C11F10A07AD30033B702 /* config.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = config.c; sourceTree = ""; usesTabs = 0; }; @@ -410,6 +415,7 @@ DC299BE41208FE09006A023C /* ZBarSDK */ = { isa = PBXGroup; children = ( + DC5D76C5136FA8F20069AEF5 /* ZBarCameraSimulator.h */, DC3CEFA51216347100D7A786 /* ZBarCaptureReader.h */, DCB3789A12A43C7E0059B07B /* ZBarHelpController.h */, DC3CEFA61216347100D7A786 /* ZBarImage.h */, @@ -436,6 +442,7 @@ DCDC6E2F11ADCA8E00021380 /* ZBarReaderView.m */, DC3CE47611FA1622008FAF88 /* ZBarReaderViewImpl_Capture.m */, DC3CE47711FA1622008FAF88 /* ZBarReaderViewImpl_Simulator.m */, + DC5D76C2136FA8C40069AEF5 /* ZBarCameraSimulator.m */, DC67C1BE10A07B6B0033B702 /* ZBarHelpController.m */, DC3EBB2C119DDB2100107EE9 /* ZBarReaderViewController.m */, DC67C1BF10A07B6B0033B702 /* ZBarReaderController.m */, @@ -724,6 +731,7 @@ DC3CE47811FA1622008FAF88 /* ZBarReaderViewImpl_Capture.m in Sources */, DC3CE47911FA1622008FAF88 /* ZBarReaderViewImpl_Simulator.m in Sources */, DCE9900D129719F100D2655C /* code93.c in Sources */, + DC5D76C3136FA8C40069AEF5 /* ZBarCameraSimulator.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; From 1b99bc7a4ae33fe8cf31c26d1c749a3d5030b490 Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 3 May 2011 19:14:50 -0700 Subject: [PATCH 282/328] iPhone: disable readertest custom overlay rotation until fixed --- iphone/examples/readertest/readertest.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/iphone/examples/readertest/readertest.m b/iphone/examples/readertest/readertest.m index bd1dfc5..58e94af 100644 --- a/iphone/examples/readertest/readertest.m +++ b/iphone/examples/readertest/readertest.m @@ -84,7 +84,6 @@ - (void) initReader: (NSString*) clsName assert(reader); reader.readerDelegate = self; xDensity = yDensity = 3; - reader.supportedOrientationsMask = ZBarOrientationMaskAll; #if 0 // apply defaults for demo @@ -533,6 +532,9 @@ - (void) scan manualBtn.enabled = TARGET_IPHONE_SIMULATOR || (reader.cameraMode == ZBarReaderControllerCameraModeDefault) || [reader isKindOfClass: [ZBarReaderViewController class]]; + reader.supportedOrientationsMask = (reader.showsZBarControls) + ? ZBarOrientationMaskAll + : ZBarOrientationMask(UIInterfaceOrientationPortrait); // tmp disable [self presentModalViewController: reader animated: YES]; } From 470342b3737676e2cc247010a8b3ffeab386584e Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 11 May 2011 16:01:56 -0700 Subject: [PATCH 283/328] iPhone: add IB support to ZBarReaderViewController - add tabbed reader sample --- iphone/ChangeLog | 2 + iphone/ZBarReaderViewController.m | 62 ++- .../xcschemes/EmbedReader.xcscheme | 76 ++++ iphone/examples/EmbedReader/build | 1 + .../TabReader.xcodeproj/project.pbxproj | 416 ++++++++++++++++++ .../xcshareddata/xcschemes/TabReader.xcscheme | 76 ++++ .../TabReader/ResultsViewController.h | 18 + .../TabReader/ResultsViewController.m | 20 + .../TabReader/TabReader/TabReader-Info.plist | 38 ++ .../TabReader/TabReader/TabReader-Prefix.pch | 15 + .../TabReader/TabReaderAppDelegate.h | 21 + .../TabReader/TabReaderAppDelegate.m | 61 +++ .../TabReader/en.lproj/InfoPlist.strings | 2 + .../TabReader/en.lproj/MainWindow.xib | 411 +++++++++++++++++ .../TabReader/en.lproj/ResultsView.xib | 303 +++++++++++++ iphone/examples/TabReader/TabReader/main.m | 16 + iphone/examples/TabReader/ZBarSDK | 1 + iphone/examples/TabReader/build | 1 + 18 files changed, 1519 insertions(+), 21 deletions(-) create mode 100644 iphone/examples/EmbedReader/EmbedReader.xcodeproj/xcshareddata/xcschemes/EmbedReader.xcscheme create mode 120000 iphone/examples/EmbedReader/build create mode 100644 iphone/examples/TabReader/TabReader.xcodeproj/project.pbxproj create mode 100644 iphone/examples/TabReader/TabReader.xcodeproj/xcshareddata/xcschemes/TabReader.xcscheme create mode 100644 iphone/examples/TabReader/TabReader/ResultsViewController.h create mode 100644 iphone/examples/TabReader/TabReader/ResultsViewController.m create mode 100644 iphone/examples/TabReader/TabReader/TabReader-Info.plist create mode 100644 iphone/examples/TabReader/TabReader/TabReader-Prefix.pch create mode 100644 iphone/examples/TabReader/TabReader/TabReaderAppDelegate.h create mode 100644 iphone/examples/TabReader/TabReader/TabReaderAppDelegate.m create mode 100644 iphone/examples/TabReader/TabReader/en.lproj/InfoPlist.strings create mode 100644 iphone/examples/TabReader/TabReader/en.lproj/MainWindow.xib create mode 100644 iphone/examples/TabReader/TabReader/en.lproj/ResultsView.xib create mode 100644 iphone/examples/TabReader/TabReader/main.m create mode 120000 iphone/examples/TabReader/ZBarSDK create mode 120000 iphone/examples/TabReader/build diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 333f094..c5579e0 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,6 @@ current: + * add IB support to ZBarReaderViewController + - add tabbed reader sample * add embedded reader sample - factor out camera simulation logic * fix readertest max quality result filtering diff --git a/iphone/ZBarReaderViewController.m b/iphone/ZBarReaderViewController.m index bf5143f..21f222f 100644 --- a/iphone/ZBarReaderViewController.m +++ b/iphone/ZBarReaderViewController.m @@ -46,22 +46,8 @@ + (BOOL) isSourceTypeAvailable: (UIImagePickerControllerSourceType) sourceType [UIImagePickerController isSourceTypeAvailable: sourceType]); } -- (id) init +- (void) _init { - if(!TARGET_IPHONE_SIMULATOR && - !NSClassFromString(@"AVCaptureSession")) { - // fallback to old interface - zlog(@"Falling back to ZBarReaderController"); - [self release]; - return([ZBarReaderController new]); - } - - self = [super init]; - if(!self) - return(nil); - - self.wantsFullScreenLayout = YES; - supportedOrientationsMask = ZBarOrientationMask(UIInterfaceOrientationPortrait); showsZBarControls = tracksSymbols = enableCache = YES; @@ -77,7 +63,34 @@ - (id) init [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([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); } @@ -186,13 +199,20 @@ - (void) viewDidLoad readerView = [[ZBarReaderView alloc] initWithImageScanner: scanner]; CGRect bounds = view.bounds; - readerView.frame = CGRectMake(0, 0, - bounds.size.width, - bounds.size.height - 54); - readerView.autoresizingMask = + CGRect r = bounds; + NSUInteger autoresize = UIViewAutoresizingFlexibleWidth | - UIViewAutoresizingFlexibleHeight | - UIViewAutoresizingFlexibleBottomMargin; + UIViewAutoresizingFlexibleHeight; + + if(!showsZBarControls && + self.parentViewController.modalViewController != self) + { + autoresize |= UIViewAutoresizingFlexibleBottomMargin; + bounds.size.height -= 54; + } + readerView.frame = r; + readerView.autoresizingMask = autoresize; + readerView.readerDelegate = (id)self; readerView.scanCrop = scanCrop; readerView.previewTransform = cameraViewTransform; diff --git a/iphone/examples/EmbedReader/EmbedReader.xcodeproj/xcshareddata/xcschemes/EmbedReader.xcscheme b/iphone/examples/EmbedReader/EmbedReader.xcodeproj/xcshareddata/xcschemes/EmbedReader.xcscheme new file mode 100644 index 0000000..7f08e65 --- /dev/null +++ b/iphone/examples/EmbedReader/EmbedReader.xcodeproj/xcshareddata/xcschemes/EmbedReader.xcscheme @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iphone/examples/EmbedReader/build b/iphone/examples/EmbedReader/build new file mode 120000 index 0000000..534f8d4 --- /dev/null +++ b/iphone/examples/EmbedReader/build @@ -0,0 +1 @@ +/tmp/EmbedReader.build \ No newline at end of file diff --git a/iphone/examples/TabReader/TabReader.xcodeproj/project.pbxproj b/iphone/examples/TabReader/TabReader.xcodeproj/project.pbxproj new file mode 100644 index 0000000..003167c --- /dev/null +++ b/iphone/examples/TabReader/TabReader.xcodeproj/project.pbxproj @@ -0,0 +1,416 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + DC52DED31370F5340048DADA /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52DECE1370F5340048DADA /* AVFoundation.framework */; }; + DC52DED41370F5340048DADA /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52DECF1370F5340048DADA /* CoreMedia.framework */; }; + DC52DED51370F5340048DADA /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52DED01370F5340048DADA /* CoreVideo.framework */; }; + DC52DED61370F5340048DADA /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52DED11370F5340048DADA /* libiconv.dylib */; }; + DC52DED71370F5340048DADA /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52DED21370F5340048DADA /* QuartzCore.framework */; }; + DC5D76D71370EE8F0069AEF5 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC5D76D61370EE8F0069AEF5 /* UIKit.framework */; }; + DC5D76D91370EE8F0069AEF5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC5D76D81370EE8F0069AEF5 /* Foundation.framework */; }; + DC5D76DB1370EE8F0069AEF5 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC5D76DA1370EE8F0069AEF5 /* CoreGraphics.framework */; }; + DC5D76E11370EE8F0069AEF5 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DC5D76DF1370EE8F0069AEF5 /* InfoPlist.strings */; }; + DC5D76E41370EE8F0069AEF5 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DC5D76E31370EE8F0069AEF5 /* main.m */; }; + DC5D76E71370EE8F0069AEF5 /* TabReaderAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DC5D76E61370EE8F0069AEF5 /* TabReaderAppDelegate.m */; }; + DC5D76EA1370EE8F0069AEF5 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = DC5D76E81370EE8F0069AEF5 /* MainWindow.xib */; }; + DC5D76F01370EE8F0069AEF5 /* ResultsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DC5D76EF1370EE8F0069AEF5 /* ResultsViewController.m */; }; + DC5D76F61370EE8F0069AEF5 /* ResultsView.xib in Resources */ = {isa = PBXBuildFile; fileRef = DC5D76F41370EE8F0069AEF5 /* ResultsView.xib */; }; + DC5D771A1370F0E30069AEF5 /* libzbar.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC5D77141370F0E30069AEF5 /* libzbar.a */; }; + DC5D771B1370F0E30069AEF5 /* zbar-back.png in Resources */ = {isa = PBXBuildFile; fileRef = DC5D77161370F0E30069AEF5 /* zbar-back.png */; }; + DC5D771C1370F0E30069AEF5 /* zbar-help.html in Resources */ = {isa = PBXBuildFile; fileRef = DC5D77171370F0E30069AEF5 /* zbar-help.html */; }; + DC5D771D1370F0E30069AEF5 /* zbar-helpicons.png in Resources */ = {isa = PBXBuildFile; fileRef = DC5D77181370F0E30069AEF5 /* zbar-helpicons.png */; }; + DC5D771E1370F0E30069AEF5 /* zbar-samples.png in Resources */ = {isa = PBXBuildFile; fileRef = DC5D77191370F0E30069AEF5 /* zbar-samples.png */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + DC52DECE1370F5340048DADA /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; + DC52DECF1370F5340048DADA /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; }; + DC52DED01370F5340048DADA /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; }; + DC52DED11370F5340048DADA /* libiconv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libiconv.dylib; path = usr/lib/libiconv.dylib; sourceTree = SDKROOT; }; + DC52DED21370F5340048DADA /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; + DC5D76D21370EE8F0069AEF5 /* TabReader.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TabReader.app; sourceTree = BUILT_PRODUCTS_DIR; }; + DC5D76D61370EE8F0069AEF5 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + DC5D76D81370EE8F0069AEF5 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + DC5D76DA1370EE8F0069AEF5 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + DC5D76DE1370EE8F0069AEF5 /* TabReader-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "TabReader-Info.plist"; sourceTree = ""; }; + DC5D76E01370EE8F0069AEF5 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + DC5D76E21370EE8F0069AEF5 /* TabReader-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TabReader-Prefix.pch"; sourceTree = ""; }; + DC5D76E31370EE8F0069AEF5 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + DC5D76E51370EE8F0069AEF5 /* TabReaderAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TabReaderAppDelegate.h; sourceTree = ""; }; + DC5D76E61370EE8F0069AEF5 /* TabReaderAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TabReaderAppDelegate.m; sourceTree = ""; }; + DC5D76E91370EE8F0069AEF5 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainWindow.xib; sourceTree = ""; }; + DC5D76EE1370EE8F0069AEF5 /* ResultsViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ResultsViewController.h; sourceTree = ""; }; + DC5D76EF1370EE8F0069AEF5 /* ResultsViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ResultsViewController.m; sourceTree = ""; }; + DC5D76F51370EE8F0069AEF5 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/ResultsView.xib; sourceTree = ""; }; + DC5D77001370F0E30069AEF5 /* Decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Decoder.h; sourceTree = ""; }; + DC5D77011370F0E30069AEF5 /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = ""; }; + DC5D77021370F0E30069AEF5 /* Image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Image.h; sourceTree = ""; }; + DC5D77031370F0E30069AEF5 /* ImageScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageScanner.h; sourceTree = ""; }; + DC5D77041370F0E30069AEF5 /* Processor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Processor.h; sourceTree = ""; }; + DC5D77051370F0E30069AEF5 /* Scanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Scanner.h; sourceTree = ""; }; + DC5D77061370F0E30069AEF5 /* Symbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Symbol.h; sourceTree = ""; }; + DC5D77071370F0E30069AEF5 /* Video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Video.h; sourceTree = ""; }; + DC5D77081370F0E30069AEF5 /* Window.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Window.h; sourceTree = ""; }; + DC5D77091370F0E30069AEF5 /* zbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zbar.h; sourceTree = ""; }; + DC5D770A1370F0E30069AEF5 /* ZBarCameraSimulator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarCameraSimulator.h; sourceTree = ""; }; + DC5D770B1370F0E30069AEF5 /* ZBarCaptureReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarCaptureReader.h; sourceTree = ""; }; + DC5D770C1370F0E30069AEF5 /* ZBarHelpController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarHelpController.h; sourceTree = ""; }; + DC5D770D1370F0E30069AEF5 /* ZBarImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarImage.h; sourceTree = ""; }; + DC5D770E1370F0E30069AEF5 /* ZBarImageScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarImageScanner.h; sourceTree = ""; }; + DC5D770F1370F0E30069AEF5 /* ZBarReaderController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarReaderController.h; sourceTree = ""; }; + DC5D77101370F0E30069AEF5 /* ZBarReaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarReaderView.h; sourceTree = ""; }; + DC5D77111370F0E30069AEF5 /* ZBarReaderViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarReaderViewController.h; sourceTree = ""; }; + DC5D77121370F0E30069AEF5 /* ZBarSDK.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarSDK.h; sourceTree = ""; }; + DC5D77131370F0E30069AEF5 /* ZBarSymbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBarSymbol.h; sourceTree = ""; }; + DC5D77141370F0E30069AEF5 /* libzbar.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libzbar.a; sourceTree = ""; }; + DC5D77161370F0E30069AEF5 /* zbar-back.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "zbar-back.png"; sourceTree = ""; }; + DC5D77171370F0E30069AEF5 /* zbar-help.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "zbar-help.html"; sourceTree = ""; }; + DC5D77181370F0E30069AEF5 /* zbar-helpicons.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "zbar-helpicons.png"; sourceTree = ""; }; + DC5D77191370F0E30069AEF5 /* zbar-samples.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "zbar-samples.png"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + DC5D76CF1370EE8F0069AEF5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DC52DED31370F5340048DADA /* AVFoundation.framework in Frameworks */, + DC52DED41370F5340048DADA /* CoreMedia.framework in Frameworks */, + DC52DED51370F5340048DADA /* CoreVideo.framework in Frameworks */, + DC52DED61370F5340048DADA /* libiconv.dylib in Frameworks */, + DC52DED71370F5340048DADA /* QuartzCore.framework in Frameworks */, + DC5D76D71370EE8F0069AEF5 /* UIKit.framework in Frameworks */, + DC5D76D91370EE8F0069AEF5 /* Foundation.framework in Frameworks */, + DC5D76DB1370EE8F0069AEF5 /* CoreGraphics.framework in Frameworks */, + DC5D771A1370F0E30069AEF5 /* libzbar.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + DC5D76C71370EE8D0069AEF5 = { + isa = PBXGroup; + children = ( + DC5D76DC1370EE8F0069AEF5 /* TabReader */, + DC5D76FC1370F0E30069AEF5 /* ZBarSDK */, + DC5D76D51370EE8F0069AEF5 /* Frameworks */, + DC5D76D31370EE8F0069AEF5 /* Products */, + ); + sourceTree = ""; + }; + DC5D76D31370EE8F0069AEF5 /* Products */ = { + isa = PBXGroup; + children = ( + DC5D76D21370EE8F0069AEF5 /* TabReader.app */, + ); + name = Products; + sourceTree = ""; + }; + DC5D76D51370EE8F0069AEF5 /* Frameworks */ = { + isa = PBXGroup; + children = ( + DC5D76D61370EE8F0069AEF5 /* UIKit.framework */, + DC5D76D81370EE8F0069AEF5 /* Foundation.framework */, + DC5D76DA1370EE8F0069AEF5 /* CoreGraphics.framework */, + DC52DECE1370F5340048DADA /* AVFoundation.framework */, + DC52DECF1370F5340048DADA /* CoreMedia.framework */, + DC52DED01370F5340048DADA /* CoreVideo.framework */, + DC52DED11370F5340048DADA /* libiconv.dylib */, + DC52DED21370F5340048DADA /* QuartzCore.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + DC5D76DC1370EE8F0069AEF5 /* TabReader */ = { + isa = PBXGroup; + children = ( + DC5D76E51370EE8F0069AEF5 /* TabReaderAppDelegate.h */, + DC5D76E61370EE8F0069AEF5 /* TabReaderAppDelegate.m */, + DC5D76E81370EE8F0069AEF5 /* MainWindow.xib */, + DC5D76EE1370EE8F0069AEF5 /* ResultsViewController.h */, + DC5D76EF1370EE8F0069AEF5 /* ResultsViewController.m */, + DC5D76F41370EE8F0069AEF5 /* ResultsView.xib */, + DC5D76DD1370EE8F0069AEF5 /* Supporting Files */, + ); + path = TabReader; + sourceTree = ""; + }; + DC5D76DD1370EE8F0069AEF5 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + DC5D76DE1370EE8F0069AEF5 /* TabReader-Info.plist */, + DC5D76DF1370EE8F0069AEF5 /* InfoPlist.strings */, + DC5D76E21370EE8F0069AEF5 /* TabReader-Prefix.pch */, + DC5D76E31370EE8F0069AEF5 /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + DC5D76FC1370F0E30069AEF5 /* ZBarSDK */ = { + isa = PBXGroup; + children = ( + DC5D76FD1370F0E30069AEF5 /* Headers */, + DC5D77141370F0E30069AEF5 /* libzbar.a */, + DC5D77151370F0E30069AEF5 /* Resources */, + ); + path = ZBarSDK; + sourceTree = ""; + }; + DC5D76FD1370F0E30069AEF5 /* Headers */ = { + isa = PBXGroup; + children = ( + DC5D76FE1370F0E30069AEF5 /* ZBarSDK */, + ); + path = Headers; + sourceTree = ""; + }; + DC5D76FE1370F0E30069AEF5 /* ZBarSDK */ = { + isa = PBXGroup; + children = ( + DC5D76FF1370F0E30069AEF5 /* zbar */, + DC5D77091370F0E30069AEF5 /* zbar.h */, + DC5D770A1370F0E30069AEF5 /* ZBarCameraSimulator.h */, + DC5D770B1370F0E30069AEF5 /* ZBarCaptureReader.h */, + DC5D770C1370F0E30069AEF5 /* ZBarHelpController.h */, + DC5D770D1370F0E30069AEF5 /* ZBarImage.h */, + DC5D770E1370F0E30069AEF5 /* ZBarImageScanner.h */, + DC5D770F1370F0E30069AEF5 /* ZBarReaderController.h */, + DC5D77101370F0E30069AEF5 /* ZBarReaderView.h */, + DC5D77111370F0E30069AEF5 /* ZBarReaderViewController.h */, + DC5D77121370F0E30069AEF5 /* ZBarSDK.h */, + DC5D77131370F0E30069AEF5 /* ZBarSymbol.h */, + ); + path = ZBarSDK; + sourceTree = ""; + }; + DC5D76FF1370F0E30069AEF5 /* zbar */ = { + isa = PBXGroup; + children = ( + DC5D77001370F0E30069AEF5 /* Decoder.h */, + DC5D77011370F0E30069AEF5 /* Exception.h */, + DC5D77021370F0E30069AEF5 /* Image.h */, + DC5D77031370F0E30069AEF5 /* ImageScanner.h */, + DC5D77041370F0E30069AEF5 /* Processor.h */, + DC5D77051370F0E30069AEF5 /* Scanner.h */, + DC5D77061370F0E30069AEF5 /* Symbol.h */, + DC5D77071370F0E30069AEF5 /* Video.h */, + DC5D77081370F0E30069AEF5 /* Window.h */, + ); + path = zbar; + sourceTree = ""; + }; + DC5D77151370F0E30069AEF5 /* Resources */ = { + isa = PBXGroup; + children = ( + DC5D77161370F0E30069AEF5 /* zbar-back.png */, + DC5D77171370F0E30069AEF5 /* zbar-help.html */, + DC5D77181370F0E30069AEF5 /* zbar-helpicons.png */, + DC5D77191370F0E30069AEF5 /* zbar-samples.png */, + ); + path = Resources; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + DC5D76D11370EE8F0069AEF5 /* TabReader */ = { + isa = PBXNativeTarget; + buildConfigurationList = DC5D76F91370EE900069AEF5 /* Build configuration list for PBXNativeTarget "TabReader" */; + buildPhases = ( + DC5D76CE1370EE8F0069AEF5 /* Sources */, + DC5D76CF1370EE8F0069AEF5 /* Frameworks */, + DC5D76D01370EE8F0069AEF5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = TabReader; + productName = TabReader; + productReference = DC5D76D21370EE8F0069AEF5 /* TabReader.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + DC5D76C91370EE8D0069AEF5 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = DC5D76CC1370EE8D0069AEF5 /* Build configuration list for PBXProject "TabReader" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = DC5D76C71370EE8D0069AEF5; + productRefGroup = DC5D76D31370EE8F0069AEF5 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + DC5D76D11370EE8F0069AEF5 /* TabReader */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + DC5D76D01370EE8F0069AEF5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DC5D76E11370EE8F0069AEF5 /* InfoPlist.strings in Resources */, + DC5D76EA1370EE8F0069AEF5 /* MainWindow.xib in Resources */, + DC5D76F61370EE8F0069AEF5 /* ResultsView.xib in Resources */, + DC5D771B1370F0E30069AEF5 /* zbar-back.png in Resources */, + DC5D771C1370F0E30069AEF5 /* zbar-help.html in Resources */, + DC5D771D1370F0E30069AEF5 /* zbar-helpicons.png in Resources */, + DC5D771E1370F0E30069AEF5 /* zbar-samples.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + DC5D76CE1370EE8F0069AEF5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DC5D76E41370EE8F0069AEF5 /* main.m in Sources */, + DC5D76E71370EE8F0069AEF5 /* TabReaderAppDelegate.m in Sources */, + DC5D76F01370EE8F0069AEF5 /* ResultsViewController.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + DC5D76DF1370EE8F0069AEF5 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + DC5D76E01370EE8F0069AEF5 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + DC5D76E81370EE8F0069AEF5 /* MainWindow.xib */ = { + isa = PBXVariantGroup; + children = ( + DC5D76E91370EE8F0069AEF5 /* en */, + ); + name = MainWindow.xib; + sourceTree = ""; + }; + DC5D76F41370EE8F0069AEF5 /* ResultsView.xib */ = { + isa = PBXVariantGroup; + children = ( + DC5D76F51370EE8F0069AEF5 /* en */, + ); + name = ResultsView.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + DC5D76F71370EE900069AEF5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = DEBUG; + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvmgcc42; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 4.3; + SDKROOT = iphoneos; + }; + name = Debug; + }; + DC5D76F81370EE900069AEF5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_VERSION = com.apple.compilers.llvmgcc42; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 4.3; + OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; + SDKROOT = iphoneos; + }; + name = Release; + }; + DC5D76FA1370EE900069AEF5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "TabReader/TabReader-Prefix.pch"; + INFOPLIST_FILE = "TabReader/TabReader-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 4.0; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/ZBarSDK\"", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + DC5D76FB1370EE900069AEF5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "TabReader/TabReader-Prefix.pch"; + INFOPLIST_FILE = "TabReader/TabReader-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 4.0; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/ZBarSDK\"", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + DC5D76CC1370EE8D0069AEF5 /* Build configuration list for PBXProject "TabReader" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DC5D76F71370EE900069AEF5 /* Debug */, + DC5D76F81370EE900069AEF5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DC5D76F91370EE900069AEF5 /* Build configuration list for PBXNativeTarget "TabReader" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DC5D76FA1370EE900069AEF5 /* Debug */, + DC5D76FB1370EE900069AEF5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = DC5D76C91370EE8D0069AEF5 /* Project object */; +} diff --git a/iphone/examples/TabReader/TabReader.xcodeproj/xcshareddata/xcschemes/TabReader.xcscheme b/iphone/examples/TabReader/TabReader.xcodeproj/xcshareddata/xcschemes/TabReader.xcscheme new file mode 100644 index 0000000..fd10597 --- /dev/null +++ b/iphone/examples/TabReader/TabReader.xcodeproj/xcshareddata/xcschemes/TabReader.xcscheme @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iphone/examples/TabReader/TabReader/ResultsViewController.h b/iphone/examples/TabReader/TabReader/ResultsViewController.h new file mode 100644 index 0000000..3032f57 --- /dev/null +++ b/iphone/examples/TabReader/TabReader/ResultsViewController.h @@ -0,0 +1,18 @@ +// +// SecondViewController.h +// TabReader +// +// Created by spadix on 5/3/11. +// + +#import + +@interface ResultsViewController + : UIViewController +{ +} + +@property (nonatomic, retain) IBOutlet UIImageView *resultImage; +@property (nonatomic, retain) IBOutlet UITextView *resultText; + +@end diff --git a/iphone/examples/TabReader/TabReader/ResultsViewController.m b/iphone/examples/TabReader/TabReader/ResultsViewController.m new file mode 100644 index 0000000..e1ee41f --- /dev/null +++ b/iphone/examples/TabReader/TabReader/ResultsViewController.m @@ -0,0 +1,20 @@ +// +// SecondViewController.m +// TabReader +// +// Created by spadix on 5/3/11. +// + +#import "ResultsViewController.h" + + +@implementation ResultsViewController + +@synthesize resultImage, resultText; + +- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) orient +{ + return(YES); +} + +@end diff --git a/iphone/examples/TabReader/TabReader/TabReader-Info.plist b/iphone/examples/TabReader/TabReader/TabReader-Info.plist new file mode 100644 index 0000000..1e72cf2 --- /dev/null +++ b/iphone/examples/TabReader/TabReader/TabReader-Info.plist @@ -0,0 +1,38 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + net.sourceforge.zbar.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + NSMainNibFile + MainWindow + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/iphone/examples/TabReader/TabReader/TabReader-Prefix.pch b/iphone/examples/TabReader/TabReader/TabReader-Prefix.pch new file mode 100644 index 0000000..701a5b1 --- /dev/null +++ b/iphone/examples/TabReader/TabReader/TabReader-Prefix.pch @@ -0,0 +1,15 @@ +// +// Prefix header for all source files of the 'TabReader' target in the 'TabReader' project +// + +#import + +#ifndef __IPHONE_3_0 +#warning "This project uses features only available in iPhone SDK 3.0 and later." +#endif + +#ifdef __OBJC__ +# import +# import +# import "ZBarSDK.h" +#endif diff --git a/iphone/examples/TabReader/TabReader/TabReaderAppDelegate.h b/iphone/examples/TabReader/TabReader/TabReaderAppDelegate.h new file mode 100644 index 0000000..d04b967 --- /dev/null +++ b/iphone/examples/TabReader/TabReader/TabReaderAppDelegate.h @@ -0,0 +1,21 @@ +// +// TabReaderAppDelegate.h +// TabReader +// +// Created by spadix on 5/3/11. +// + +#import + +@interface TabReaderAppDelegate + : NSObject + < UIApplicationDelegate, + UITabBarControllerDelegate, + ZBarReaderDelegate > +{ +} + +@property (nonatomic, retain) IBOutlet UIWindow *window; +@property (nonatomic, retain) IBOutlet UITabBarController *tabBarController; + +@end diff --git a/iphone/examples/TabReader/TabReader/TabReaderAppDelegate.m b/iphone/examples/TabReader/TabReader/TabReaderAppDelegate.m new file mode 100644 index 0000000..2d1ec43 --- /dev/null +++ b/iphone/examples/TabReader/TabReader/TabReaderAppDelegate.m @@ -0,0 +1,61 @@ +// +// TabReaderAppDelegate.m +// TabReader +// +// Created by spadix on 5/3/11. +// + +#import "TabReaderAppDelegate.h" +#import "ResultsViewController.h" + +@implementation TabReaderAppDelegate + +@synthesize window=_window; +@synthesize tabBarController=_tabBarController; + +- (BOOL) application: (UIApplication*) application + didFinishLaunchingWithOptions: (NSDictionary*) options +{ + self.window.rootViewController = self.tabBarController; + [self.window makeKeyAndVisible]; + + // force class to load so it may be referenced directly from nib + [ZBarReaderViewController class]; + + ZBarReaderViewController *reader = + [self.tabBarController.viewControllers objectAtIndex: 0]; + reader.readerDelegate = self; + reader.showsZBarControls = NO; + + return(YES); +} + +- (void) dealloc +{ + [_window release]; + [_tabBarController release]; + [super dealloc]; +} + + +// ZBarReaderDelegate + +- (void) imagePickerController: (UIImagePickerController*) picker + didFinishPickingMediaWithInfo: (NSDictionary*) info +{ + // do something useful with results + UITabBarController *tabs = self.tabBarController; + tabs.selectedIndex = 1; + ResultsViewController *results = [tabs.viewControllers objectAtIndex: 1]; + UIImage *image = [info objectForKey: UIImagePickerControllerOriginalImage]; + results.resultImage.image = image; + + id syms = + [info objectForKey: ZBarReaderControllerResults]; + for(ZBarSymbol *sym in syms) { + results.resultText.text = sym.data; + break; + } +} + +@end diff --git a/iphone/examples/TabReader/TabReader/en.lproj/InfoPlist.strings b/iphone/examples/TabReader/TabReader/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..477b28f --- /dev/null +++ b/iphone/examples/TabReader/TabReader/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/iphone/examples/TabReader/TabReader/en.lproj/MainWindow.xib b/iphone/examples/TabReader/TabReader/en.lproj/MainWindow.xib new file mode 100644 index 0000000..4875de8 --- /dev/null +++ b/iphone/examples/TabReader/TabReader/en.lproj/MainWindow.xib @@ -0,0 +1,411 @@ + + + + 1024 + 10J869 + 1306 + 1038.35 + 461.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 301 + + + YES + IBProxyObject + IBUITabBarItem + IBUIViewController + IBUICustomObject + IBUITabBarController + IBUIWindow + IBUITabBar + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + + + YES + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + IBCocoaTouchFramework + + + + 1316 + + {320, 480} + + + + 1 + MSAxIDEAA + + NO + NO + + IBCocoaTouchFramework + YES + + + + + + 1 + 1 + + IBCocoaTouchFramework + NO + + + Scan + IBCocoaTouchFramework + + + + + + 1 + 1 + + IBCocoaTouchFramework + NO + + + YES + + + + Results + IBCocoaTouchFramework + + + + ResultsView + + 1 + 1 + + IBCocoaTouchFramework + NO + + + + + 266 + {{0, 431}, {320, 49}} + + + + 3 + MCAwAA + + NO + IBCocoaTouchFramework + + YES + + + + + + + + + + YES + + + window + + + + 9 + + + + delegate + + + + 99 + + + + tabBarController + + + + 113 + + + + delegate + + + + 127 + + + + + YES + + 0 + + + + + + 2 + + + YES + + + + + -1 + + + File's Owner + + + 3 + + + + + 106 + + + YES + + + + + + + + 107 + + + + + -2 + + + + + 125 + + + YES + + + + Barcode Reader Controller + + + 126 + + + + + 109 + + + YES + + + + Barcode Results Controller + + + 110 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 106.IBEditorWindowLastContentRect + 106.IBPluginDependency + 107.IBPluginDependency + 109.CustomClassName + 109.IBPluginDependency + 110.IBPluginDependency + 125.CustomClassName + 125.IBPluginDependency + 126.IBPluginDependency + 2.IBAttributePlaceholdersKey + 2.IBEditorWindowLastContentRect + 2.IBPluginDependency + 3.CustomClassName + 3.IBPluginDependency + + + YES + UIApplication + UIResponder + {{1323, 676}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + ResultsViewController + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + ZBarReaderViewController + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + YES + + + + {{229, 373}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + TabReaderAppDelegate + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + + + + YES + + + + + 127 + + + + YES + + ResultsViewController + UIViewController + + YES + + YES + resultImage + resultText + + + YES + UIImageView + UITextView + + + + YES + + YES + resultImage + resultText + + + YES + + resultImage + UIImageView + + + resultText + UITextView + + + + + IBProjectSource + ./Classes/ResultsViewController.h + + + + TabReaderAppDelegate + NSObject + + YES + + YES + tabBarController + window + + + YES + UITabBarController + UIWindow + + + + YES + + YES + tabBarController + window + + + YES + + tabBarController + UITabBarController + + + window + UIWindow + + + + + IBProjectSource + ./Classes/TabReaderAppDelegate.h + + + + ZBarReaderViewController + UIViewController + + IBProjectSource + ./Classes/ZBarReaderViewController.h + + + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + 3 + 301 + + diff --git a/iphone/examples/TabReader/TabReader/en.lproj/ResultsView.xib b/iphone/examples/TabReader/TabReader/en.lproj/ResultsView.xib new file mode 100644 index 0000000..c9c77bc --- /dev/null +++ b/iphone/examples/TabReader/TabReader/en.lproj/ResultsView.xib @@ -0,0 +1,303 @@ + + + + 1024 + 10J869 + 1306 + 1038.35 + 461.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 301 + + + YES + IBUITextView + IBUIImageView + IBUIView + IBUILabel + IBProxyObject + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + + + YES + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + + 274 + + YES + + + 306 + {{20, 20}, {280, 28}} + + + + + 3 + MQA + + 2 + + + NO + YES + NO + IBCocoaTouchFramework + Results Tab + + Helvetica + 24 + 16 + + + 1 + MCAwIDAAA + + + 1 + 10 + 1 + + + + 282 + {{20, 274}, {280, 117}} + + + NO + YES + YES + NO + IBCocoaTouchFramework + NO + NO + NO + 0.0 + 0.0 + NO + NO + No barcode scanned. + + IBCocoaTouchFramework + + + + + 306 + {{20, 56}, {280, 210}} + + + 1 + NO + IBCocoaTouchFramework + + + {{0, 20}, {320, 411}} + + + + + 3 + MQA + + + + IBCocoaTouchFramework + + + + + YES + + + view + + + + 3 + + + + resultImage + + + + 9 + + + + resultText + + + + 10 + + + + + YES + + 0 + + + + + + 1 + + + YES + + + + + + + + -1 + + + File's Owner + + + -2 + + + + + 5 + + + + + 7 + + + + + 8 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 1.IBEditorWindowLastContentRect + 1.IBPluginDependency + 5.IBPluginDependency + 7.IBPluginDependency + 7.IBViewBoundsToFrameTransform + 8.IBPluginDependency + + + YES + ResultsViewController + UIResponder + {{187, 376}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABA4AAAw7GAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + + + + YES + + + + + 10 + + + + YES + + ResultsViewController + UIViewController + + YES + + YES + resultImage + resultText + + + YES + UIImageView + UITextView + + + + YES + + YES + resultImage + resultText + + + YES + + resultImage + UIImageView + + + resultText + UITextView + + + + + IBProjectSource + ./Classes/ResultsViewController.h + + + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + 3 + 301 + + diff --git a/iphone/examples/TabReader/TabReader/main.m b/iphone/examples/TabReader/TabReader/main.m new file mode 100644 index 0000000..5505e3a --- /dev/null +++ b/iphone/examples/TabReader/TabReader/main.m @@ -0,0 +1,16 @@ +// +// main.m +// TabReader +// +// Created by spadix on 5/3/11. +// + +#import + +int main(int argc, char *argv[]) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + int retVal = UIApplicationMain(argc, argv, nil, nil); + [pool release]; + return retVal; +} diff --git a/iphone/examples/TabReader/ZBarSDK b/iphone/examples/TabReader/ZBarSDK new file mode 120000 index 0000000..b8e7666 --- /dev/null +++ b/iphone/examples/TabReader/ZBarSDK @@ -0,0 +1 @@ +../../build/Release-iphoneos/ZBarSDK \ No newline at end of file diff --git a/iphone/examples/TabReader/build b/iphone/examples/TabReader/build new file mode 120000 index 0000000..fc13333 --- /dev/null +++ b/iphone/examples/TabReader/build @@ -0,0 +1 @@ +/tmp/TabReader.build \ No newline at end of file From 52e81e26719c8820bc839b4f35969697024d1ae0 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 12 May 2011 15:25:39 -0700 Subject: [PATCH 284/328] iPhone: add missing references to new samples --- iphone/ChangeLog | 1 + iphone/zbar.xcodeproj/project.pbxproj | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index c5579e0..a4dfb1f 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,5 @@ current: + * add missing references to new samples * add IB support to ZBarReaderViewController - add tabbed reader sample * add embedded reader sample diff --git a/iphone/zbar.xcodeproj/project.pbxproj b/iphone/zbar.xcodeproj/project.pbxproj index a654cc0..cc28953 100644 --- a/iphone/zbar.xcodeproj/project.pbxproj +++ b/iphone/zbar.xcodeproj/project.pbxproj @@ -117,6 +117,8 @@ DC67C1C310A07B6B0033B702 /* ZBarReaderController.m in Sources */ = {isa = PBXBuildFile; fileRef = DC67C1BF10A07B6B0033B702 /* ZBarReaderController.m */; }; DC67C1C410A07B6B0033B702 /* ZBarSymbol.m in Sources */ = {isa = PBXBuildFile; fileRef = DC67C1C010A07B6B0033B702 /* ZBarSymbol.m */; }; DCB3789B12A43CAC0059B07B /* ZBarHelpController.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = DCB3789A12A43C7E0059B07B /* ZBarHelpController.h */; }; + DCC93259137B50CB0040A82D /* EmbedReader in Copy Examples */ = {isa = PBXBuildFile; fileRef = DCC9324E137B509B0040A82D /* EmbedReader */; }; + DCC9325A137B50CB0040A82D /* TabReader in Copy Examples */ = {isa = PBXBuildFile; fileRef = DCC9324F137B509B0040A82D /* TabReader */; }; DCDC6E3011ADCA8E00021380 /* ZBarReaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = DCDC6E2F11ADCA8E00021380 /* ZBarReaderView.m */; }; DCE9900D129719F100D2655C /* code93.c in Sources */ = {isa = PBXBuildFile; fileRef = DCE9900B129719F100D2655C /* code93.c */; }; DCF5C9AD11EA3AD100E7DC21 /* databar.c in Sources */ = {isa = PBXBuildFile; fileRef = DCF5C9AB11EA3AD100E7DC21 /* databar.c */; }; @@ -209,6 +211,8 @@ files = ( DC3CF29A1218359400D7A786 /* ReaderSample in Copy Examples */, DC3CF29B1218359400D7A786 /* readertest in Copy Examples */, + DCC93259137B50CB0040A82D /* EmbedReader in Copy Examples */, + DCC9325A137B50CB0040A82D /* TabReader in Copy Examples */, ); name = "Copy Examples"; runOnlyForDeploymentPostprocessing = 0; @@ -329,6 +333,8 @@ DC67C1C010A07B6B0033B702 /* ZBarSymbol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarSymbol.m; sourceTree = ""; usesTabs = 0; }; DC67C1CB10A07BEE0033B702 /* svg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = svg.h; sourceTree = ""; usesTabs = 0; }; DCB3789A12A43C7E0059B07B /* ZBarHelpController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ZBarHelpController.h; path = include/ZBarSDK/ZBarHelpController.h; sourceTree = ""; }; + DCC9324E137B509B0040A82D /* EmbedReader */ = {isa = PBXFileReference; lastKnownFileType = folder; name = EmbedReader; path = examples/EmbedReader; sourceTree = ""; }; + DCC9324F137B509B0040A82D /* TabReader */ = {isa = PBXFileReference; lastKnownFileType = folder; name = TabReader; path = examples/TabReader; sourceTree = ""; }; DCDC6E2F11ADCA8E00021380 /* ZBarReaderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBarReaderView.m; sourceTree = ""; usesTabs = 0; }; DCE9900B129719F100D2655C /* code93.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = code93.c; sourceTree = ""; }; DCE9900C129719F100D2655C /* code93.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = code93.h; sourceTree = ""; }; @@ -456,6 +462,8 @@ children = ( DC3CF2081218358C00D7A786 /* ReaderSample */, DC3CF2651218358C00D7A786 /* readertest */, + DCC9324E137B509B0040A82D /* EmbedReader */, + DCC9324F137B509B0040A82D /* TabReader */, ); name = Examples; sourceTree = ""; From f07e9561e419120ae3ed538adfc1247e3e7615cc Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 12 May 2011 16:27:35 -0700 Subject: [PATCH 285/328] iPhone: update docs to note possible link order dependency --- iphone/ChangeLog | 1 + iphone/doc/install.rst | 13 +++++++++---- iphone/doc/tutorial.rst | 6 ++++++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index a4dfb1f..ecbf203 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,5 @@ current: + * update docs to note possible link order dependency * add missing references to new samples * add IB support to ZBarReaderViewController - add tabbed reader sample diff --git a/iphone/doc/install.rst b/iphone/doc/install.rst index 582878c..231fd77 100644 --- a/iphone/doc/install.rst +++ b/iphone/doc/install.rst @@ -48,10 +48,10 @@ Xcode project: checking the box. The target that you want to link with the library should also be selected in the target list. -4. Link the following additional frameworks to any targets that link with the +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.1: + iOS 3: * :file:`AVFoundation.framework` (weak) * :file:`CoreMedia.framework` (weak) @@ -60,9 +60,14 @@ Xcode project: * :file:`libiconv.dylib` If you check "Link Binary With Libraries" for the target(s), you should see - all of these frameworks along with :file:`libzbar.a`. + all of these frameworks followed by :file:`libzbar.a`. -5. Import the SDK header from your prefix header to make the barcode reader + .. 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" diff --git a/iphone/doc/tutorial.rst b/iphone/doc/tutorial.rst index b54b459..4a6eec9 100644 --- a/iphone/doc/tutorial.rst +++ b/iphone/doc/tutorial.rst @@ -107,6 +107,12 @@ Now for the exciting part - let's add a barcode reader! * QuartzCore.framework * libiconv.dylib + .. warning:: + + Link order may be important for some versions of Xcode; the libraries + referenced above should be listed *before* :file:`libzbar.a` in the + link order. + 5. Import the SDK header. You will usually want to prefix it, so add it to :file:`ReaderSample-prefix.pch`:: From 1d74433f7a208922a8def5d3eab14afc82dbd165 Mon Sep 17 00:00:00 2001 From: spadix Date: Fri, 13 May 2011 07:44:10 -0700 Subject: [PATCH 286/328] iPhone: fix camera preview stale rotation corner - fix ZBarReaderViewController toolbar layout accomodation - switch pre-release samples to use debug library --- iphone/ChangeLog | 3 +++ iphone/ZBarReaderViewController.m | 21 ++++++++++++++----- iphone/examples/EmbedReader/ZBarSDK | 2 +- iphone/examples/TabReader/ZBarSDK | 2 +- iphone/examples/readertest/readertest.m | 11 +++++++--- .../xcshareddata/xcschemes/ZBarSDK.xcscheme | 2 +- 6 files changed, 30 insertions(+), 11 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index ecbf203..a9f3761 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,7 @@ current: + * 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 diff --git a/iphone/ZBarReaderViewController.m b/iphone/ZBarReaderViewController.m index 21f222f..09b1d87 100644 --- a/iphone/ZBarReaderViewController.m +++ b/iphone/ZBarReaderViewController.m @@ -204,11 +204,11 @@ - (void) viewDidLoad UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - if(!showsZBarControls && - self.parentViewController.modalViewController != self) + if(showsZBarControls || + self.parentViewController.modalViewController == self) { autoresize |= UIViewAutoresizingFlexibleBottomMargin; - bounds.size.height -= 54; + r.size.height -= 54; } readerView.frame = r; readerView.autoresizingMask = autoresize; @@ -245,6 +245,7 @@ - (void) viewDidUnload - (void) viewWillAppear: (BOOL) animated { + zlog(@"willAppear: anim=%d", animated); [self initControls]; [super viewWillAppear: animated]; @@ -292,16 +293,26 @@ - (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) orient - (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) orient duration: (NSTimeInterval) duration { - [readerView willRotateToInterfaceOrientation: orient - duration: duration]; + zlog(@"willRotate: orient=%d #%g", orient, duration); + 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: orient=%d", orient); } - (ZBarReaderView*) readerView diff --git a/iphone/examples/EmbedReader/ZBarSDK b/iphone/examples/EmbedReader/ZBarSDK index b8e7666..7a373ea 120000 --- a/iphone/examples/EmbedReader/ZBarSDK +++ b/iphone/examples/EmbedReader/ZBarSDK @@ -1 +1 @@ -../../build/Release-iphoneos/ZBarSDK \ No newline at end of file +../../build/Debug-iphoneos/ZBarSDK \ No newline at end of file diff --git a/iphone/examples/TabReader/ZBarSDK b/iphone/examples/TabReader/ZBarSDK index b8e7666..7a373ea 120000 --- a/iphone/examples/TabReader/ZBarSDK +++ b/iphone/examples/TabReader/ZBarSDK @@ -1 +1 @@ -../../build/Release-iphoneos/ZBarSDK \ No newline at end of file +../../build/Debug-iphoneos/ZBarSDK \ No newline at end of file diff --git a/iphone/examples/readertest/readertest.m b/iphone/examples/readertest/readertest.m index 58e94af..d0cc5b9 100644 --- a/iphone/examples/readertest/readertest.m +++ b/iphone/examples/readertest/readertest.m @@ -513,6 +513,11 @@ - (void) dealloc [super dealloc]; } +- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) orient +{ + return(YES); +} + - (void) scan { found = paused = NO; @@ -526,15 +531,15 @@ - (void) scan reader.readerView.showsFPS = YES; if(zoom) reader.readerView.zoom = zoom; + reader.supportedOrientationsMask = (reader.showsZBarControls) + ? ZBarOrientationMaskAll + : ZBarOrientationMask(UIInterfaceOrientationPortrait); // tmp disable } if(reader.sourceType == UIImagePickerControllerSourceTypeCamera) reader.cameraOverlayView = (reader.showsZBarControls) ? nil : overlay; manualBtn.enabled = TARGET_IPHONE_SIMULATOR || (reader.cameraMode == ZBarReaderControllerCameraModeDefault) || [reader isKindOfClass: [ZBarReaderViewController class]]; - reader.supportedOrientationsMask = (reader.showsZBarControls) - ? ZBarOrientationMaskAll - : ZBarOrientationMask(UIInterfaceOrientationPortrait); // tmp disable [self presentModalViewController: reader animated: YES]; } diff --git a/iphone/zbar.xcodeproj/xcshareddata/xcschemes/ZBarSDK.xcscheme b/iphone/zbar.xcodeproj/xcshareddata/xcschemes/ZBarSDK.xcscheme index 55974d5..1d6023c 100644 --- a/iphone/zbar.xcodeproj/xcshareddata/xcschemes/ZBarSDK.xcscheme +++ b/iphone/zbar.xcodeproj/xcshareddata/xcschemes/ZBarSDK.xcscheme @@ -36,7 +36,7 @@ displayScale = "1.00" launchStyle = "0" useCustomWorkingDirectory = "NO" - buildConfiguration = "Release"> + buildConfiguration = "Debug"> From ace7deb445694433dd5fcc5a674dd1e901fef37c Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 15 May 2011 10:46:36 -0700 Subject: [PATCH 287/328] iPhone: fix captureReader not exposed to simulator --- iphone/ChangeLog | 1 + iphone/ZBarReaderView.m | 4 ++-- iphone/ZBarReaderViewImpl_Capture.m | 3 +-- iphone/include/ZBarSDK/ZBarReaderView.h | 1 + 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index a9f3761..048cd80 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,5 @@ current: + * 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 diff --git a/iphone/ZBarReaderView.m b/iphone/ZBarReaderView.m index f065811..40a484a 100644 --- a/iphone/ZBarReaderView.m +++ b/iphone/ZBarReaderView.m @@ -33,8 +33,8 @@ @interface ZBarReaderViewImpl : NSObject @implementation ZBarReaderView @synthesize readerDelegate, tracksSymbols, trackingColor, torchMode, showsFPS, - zoom, scanCrop, previewTransform; -@dynamic scanner, allowsPinchZoom, enableCache, device, session, captureReader; + zoom, scanCrop, previewTransform, captureReader; +@dynamic scanner, allowsPinchZoom, enableCache, device, session; + (id) alloc { diff --git a/iphone/ZBarReaderViewImpl_Capture.m b/iphone/ZBarReaderViewImpl_Capture.m index 7d6774c..110fa65 100644 --- a/iphone/ZBarReaderViewImpl_Capture.m +++ b/iphone/ZBarReaderViewImpl_Capture.m @@ -45,14 +45,13 @@ @interface ZBarReaderViewImpl AVCaptureSession *session; AVCaptureDevice *device; AVCaptureInput *input; - ZBarCaptureReader *captureReader; } @end @implementation ZBarReaderViewImpl -@synthesize device, session, captureReader; +@synthesize device, session; - (void) _initWithImageScanner: (ZBarImageScanner*) scanner { diff --git a/iphone/include/ZBarSDK/ZBarReaderView.h b/iphone/include/ZBarSDK/ZBarReaderView.h index 83aa831..270be19 100644 --- a/iphone/include/ZBarSDK/ZBarReaderView.h +++ b/iphone/include/ZBarSDK/ZBarReaderView.h @@ -46,6 +46,7 @@ : UIView { id readerDelegate; + ZBarCaptureReader *captureReader; CGRect scanCrop, effectiveCrop; CGAffineTransform previewTransform; CGFloat zoom, zoom0; From 6c782deb799d288f2570f91ab6c66016cd3d87d7 Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 16 May 2011 09:38:58 -0700 Subject: [PATCH 288/328] fix image scanner min quality filtering --- iphone/ChangeLog | 1 + iphone/ZBarReaderViewImpl_Capture.m | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 048cd80..2191712 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,5 @@ current: + * add orientation detection fall back * fix captureReader not exposed to simulator * fix camera preview stale rotation corner - fix ZBarReaderViewController toolbar layout accomodation diff --git a/iphone/ZBarReaderViewImpl_Capture.m b/iphone/ZBarReaderViewImpl_Capture.m index 110fa65..71914fc 100644 --- a/iphone/ZBarReaderViewImpl_Capture.m +++ b/iphone/ZBarReaderViewImpl_Capture.m @@ -322,8 +322,15 @@ - (void) captureReader: (ZBarCaptureReader*) reader if(!readerDelegate) return; - UIImageOrientation orient; - switch([UIDevice currentDevice].orientation) + 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; From a6b6c8b94f486c26c05ed37b5569dd6589dd93fd Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 9 Jun 2011 15:55:32 -0700 Subject: [PATCH 289/328] iPhone: workaround orientation bugs in parent controllers - enable orientation and iPad support for all examples --- iphone/ChangeLog | 2 ++ iphone/ZBarReaderViewController.m | 11 ++++++++++- .../ReaderSample.xcodeproj/project.pbxproj | 3 +++ .../ReaderSample/ReaderSampleViewController.m | 6 ++++++ .../en.lproj/ReaderSampleViewController.xib | 7 +++---- .../TabReader/TabReader/TabReaderAppDelegate.m | 1 + iphone/include/ZBarSDK/ZBarReaderViewController.h | 2 +- 7 files changed, 26 insertions(+), 6 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 2191712..d24b987 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,6 @@ current: + * 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 diff --git a/iphone/ZBarReaderViewController.m b/iphone/ZBarReaderViewController.m index 09b1d87..2669584 100644 --- a/iphone/ZBarReaderViewController.m +++ b/iphone/ZBarReaderViewController.m @@ -294,6 +294,7 @@ - (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) orient duration: (NSTimeInterval) duration { zlog(@"willRotate: orient=%d #%g", orient, duration); + rotating = YES; if(readerView) [readerView willRotateToInterfaceOrientation: orient duration: duration]; @@ -312,7 +313,15 @@ - (void) willAnimateRotationToInterfaceOrientation: (UIInterfaceOrientation) ori - (void) didRotateFromInterfaceOrientation: (UIInterfaceOrientation) orient { - zlog(@"didRotate: orient=%d", 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 diff --git a/iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj b/iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj index 49708a3..d5dde31 100644 --- a/iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj +++ b/iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj @@ -365,6 +365,7 @@ "\"$(SRCROOT)/../../build/Release-iphoneos/ZBarSDK\"", ); PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; WRAPPER_EXTENSION = app; }; name = Debug; @@ -382,6 +383,7 @@ "\"$(SRCROOT)/../../build/Release-iphoneos/ZBarSDK\"", ); PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; WRAPPER_EXTENSION = app; }; @@ -406,6 +408,7 @@ DC8F28B213579F00005B8862 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/iphone/examples/ReaderSample/ReaderSample/ReaderSampleViewController.m b/iphone/examples/ReaderSample/ReaderSample/ReaderSampleViewController.m index 8007684..6a12b42 100644 --- a/iphone/examples/ReaderSample/ReaderSample/ReaderSampleViewController.m +++ b/iphone/examples/ReaderSample/ReaderSample/ReaderSampleViewController.m @@ -16,6 +16,7 @@ - (IBAction) scanButtonTapped // ADD: present a barcode reader that scans from the camera feed ZBarReaderViewController *reader = [ZBarReaderViewController new]; reader.readerDelegate = self; + reader.supportedOrientationsMask = ZBarOrientationMaskAll; ZBarImageScanner *scanner = reader.scanner; // TODO: (optional) additional reader configuration here @@ -53,6 +54,11 @@ - (void) imagePickerController: (UIImagePickerController*) reader [reader dismissModalViewControllerAnimated: YES]; } +- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) orient +{ + return(YES); +} + - (void) dealloc { self.resultImage = nil; self.resultText = nil; diff --git a/iphone/examples/ReaderSample/ReaderSample/en.lproj/ReaderSampleViewController.xib b/iphone/examples/ReaderSample/ReaderSample/en.lproj/ReaderSampleViewController.xib index 846d96f..16d9167 100644 --- a/iphone/examples/ReaderSample/ReaderSample/en.lproj/ReaderSampleViewController.xib +++ b/iphone/examples/ReaderSample/ReaderSample/en.lproj/ReaderSampleViewController.xib @@ -46,11 +46,10 @@ YES - 292 + 282 {{20, 396}, {280, 44}} - NO IBCocoaTouchFramework 0 @@ -77,7 +76,7 @@ - 292 + 311 {{20, 20}, {280, 210}} @@ -88,7 +87,7 @@ - 292 + 282 {{20, 238}, {280, 150}} diff --git a/iphone/examples/TabReader/TabReader/TabReaderAppDelegate.m b/iphone/examples/TabReader/TabReader/TabReaderAppDelegate.m index 2d1ec43..29d9e5e 100644 --- a/iphone/examples/TabReader/TabReader/TabReaderAppDelegate.m +++ b/iphone/examples/TabReader/TabReader/TabReaderAppDelegate.m @@ -26,6 +26,7 @@ - (BOOL) application: (UIApplication*) application [self.tabBarController.viewControllers objectAtIndex: 0]; reader.readerDelegate = self; reader.showsZBarControls = NO; + reader.supportedOrientationsMask = ZBarOrientationMaskAll; return(YES); } diff --git a/iphone/include/ZBarSDK/ZBarReaderViewController.h b/iphone/include/ZBarSDK/ZBarReaderViewController.h index 21d2ec4..b91dbe4 100644 --- a/iphone/include/ZBarSDK/ZBarReaderViewController.h +++ b/iphone/include/ZBarSDK/ZBarReaderViewController.h @@ -54,7 +54,7 @@ ZBarHelpController *helpController; UIView *controls; - BOOL didHideStatusBar; + BOOL didHideStatusBar, rotating; ZBarCameraSimulator *cameraSim; } From 19d01efcb886f21e4f8793f1b984f43fc07a8409 Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 15 Jun 2011 12:40:42 -0700 Subject: [PATCH 290/328] iPhone: add emulation for UI camera device and flash mode properties --- iphone/ChangeLog | 1 + iphone/ZBarReaderViewController.m | 124 +++++++++++++++++- iphone/examples/readertest/readertest.m | 43 ++++++ .../ZBarSDK/ZBarReaderViewController.h | 10 ++ 4 files changed, 177 insertions(+), 1 deletion(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index d24b987..735f053 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,5 @@ current: + * 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 diff --git a/iphone/ZBarReaderViewController.m b/iphone/ZBarReaderViewController.m index 2669584..b7c60c1 100644 --- a/iphone/ZBarReaderViewController.m +++ b/iphone/ZBarReaderViewController.m @@ -30,11 +30,67 @@ #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); + + 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); + return(nil); +} + +static inline AVCaptureTorchMode +AVTorchModeForUIFlashMode (UIImagePickerControllerCameraFlashMode mode) +{ + switch(mode) + { + case UIImagePickerControllerCameraFlashModeAuto: + return(AVCaptureTorchModeAuto); + case UIImagePickerControllerCameraFlashModeOn: + return(AVCaptureTorchModeOn); + //case UIImagePickerControllerCameraFlashModeOff: + } + return(AVCaptureTorchModeOff); +} + + @implementation ZBarReaderViewController @synthesize scanner, readerDelegate, showsZBarControls, supportedOrientationsMask, tracksSymbols, enableCache, cameraOverlayView, - cameraViewTransform, readerView, scanCrop; + cameraViewTransform, cameraDevice, cameraFlashMode, readerView, scanCrop; @dynamic sourceType, allowsEditing, allowsImageEditing, showsCameraControls, showsHelpOnFail, cameraMode, takesPicture, maxScanDimension; @@ -46,6 +102,29 @@ + (BOOL) isSourceTypeAvailable: (UIImagePickerControllerSourceType) sourceType [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 = @@ -54,6 +133,14 @@ - (void) _init scanCrop = CGRectMake(0, 0, 1, 1); cameraViewTransform = CGAffineTransformIdentity; + cameraFlashMode = UIImagePickerControllerCameraFlashModeAuto; + AVCaptureDevice *device = + [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo]; + 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]; @@ -212,6 +299,10 @@ - (void) viewDidLoad } readerView.frame = r; readerView.autoresizingMask = autoresize; + AVCaptureDevice *device = AVDeviceForUICamera(cameraDevice); + if(device && device != readerView.device) + readerView.device = device; + readerView.torchMode = AVTorchModeForUIFlashMode(cameraFlashMode); readerView.readerDelegate = (id)self; readerView.scanCrop = scanCrop; @@ -418,6 +509,36 @@ - (void) takePicture [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"); +} + + // ZBarHelpDelegate - (void) helpControllerDidFinish: (ZBarHelpController*) help @@ -443,6 +564,7 @@ - (void) removeHelp: (NSString*) tag } } + // ZBarReaderViewDelegate - (void) readerView: (ZBarReaderView*) view diff --git a/iphone/examples/readertest/readertest.m b/iphone/examples/readertest/readertest.m index d0cc5b9..2647ab7 100644 --- a/iphone/examples/readertest/readertest.m +++ b/iphone/examples/readertest/readertest.m @@ -2,6 +2,8 @@ CLASS_SECTION = 0, SOURCE_SECTION, CAMODE_SECTION, + DEVICE_SECTION, + FLASH_SECTION, CONFIG_SECTION, CUSTOM_SECTION, SYMBOL_SECTION, @@ -13,6 +15,8 @@ @"Classes", @"SourceType", @"CameraMode", + @"CaptureDevice", + @"CameraFlashMode", @"Reader Configuration", nil, @"Enabled Symbologies", @@ -327,6 +331,33 @@ - (void) initControlCells [sections replaceObjectAtIndex: CAMODE_SECTION withObject: modes]; + static NSString *const deviceNames[] = { + @"Rear", @"Front", nil + }; + NSMutableArray *devices = [NSMutableArray array]; + for(int i = 0; deviceNames[i]; i++) + if([[reader class] + isCameraDeviceAvailable: i]) + [devices addObject: + [self cellWithTitle: deviceNames[i] + tag: i + checked: (reader.cameraDevice == i)]]; + assert(devices.count); + [sections replaceObjectAtIndex: DEVICE_SECTION + withObject: devices]; + + static NSString *const flashNames[] = { + @"Off", @"Auto", @"On", nil + }; + NSMutableArray *flashModes = [NSMutableArray array]; + for(int i = 0; flashNames[i]; i++) + [flashModes addObject: + [self cellWithTitle: flashNames[i] + tag: i - 1 + checked: (reader.cameraFlashMode == i - 1)]]; + [sections replaceObjectAtIndex: FLASH_SECTION + withObject: flashModes]; + static NSString* const configNames[] = { @"showsCameraControls", @"showsZBarControls", @"tracksSymbols", @"enableCache", @"showsHelpOnFail", @"takesPicture", @@ -732,6 +763,18 @@ - (void) tableView: (UITableView*) view inSection: CAMODE_SECTION]; break; + case DEVICE_SECTION: + reader.cameraDevice = cell.tag; + [self setCheckForTag: reader.cameraDevice + inSection: DEVICE_SECTION]; + break; + + case FLASH_SECTION: + reader.cameraFlashMode = cell.tag; + [self setCheckForTag: reader.cameraFlashMode + inSection: FLASH_SECTION]; + break; + case CONFIG_SECTION: { BOOL state; NSString *key = cell.textLabel.text; diff --git a/iphone/include/ZBarSDK/ZBarReaderViewController.h b/iphone/include/ZBarSDK/ZBarReaderViewController.h index b91dbe4..cbf4d09 100644 --- a/iphone/include/ZBarSDK/ZBarReaderViewController.h +++ b/iphone/include/ZBarSDK/ZBarReaderViewController.h @@ -50,6 +50,8 @@ CGAffineTransform cameraViewTransform; CGRect scanCrop; NSUInteger supportedOrientationsMask; + UIImagePickerControllerCameraDevice cameraDevice; + UIImagePickerControllerCameraFlashMode cameraFlashMode; BOOL showsZBarControls, tracksSymbols, enableCache; ZBarHelpController *helpController; @@ -96,6 +98,14 @@ // capture the next frame and send it over the usual delegate path. - (void) takePicture; +// these attempt to emulate UIImagePickerController ++ (BOOL) isCameraDeviceAvailable: (UIImagePickerControllerCameraDevice) cameraDevice; ++ (BOOL) isFlashAvailableForCameraDevice: (UIImagePickerControllerCameraDevice) cameraDevice; ++ (NSArray*) availableCaptureModesForCameraDevice: (UIImagePickerControllerCameraDevice) cameraDevice; +@property(nonatomic) UIImagePickerControllerCameraDevice cameraDevice; +@property(nonatomic) UIImagePickerControllerCameraFlashMode cameraFlashMode; +@property(nonatomic) UIImagePickerControllerCameraCaptureMode cameraCaptureMode; + // direct access to the ZBarReaderView @property (nonatomic, readonly) ZBarReaderView *readerView; From 66228092c5b96ded01b16de7eba98d400dfaf35c Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 16 Jun 2011 11:38:14 -0700 Subject: [PATCH 291/328] documentation updates --- iphone/ChangeLog | 3 +- iphone/doc/ZBarReaderView.rst | 13 ++++++ iphone/doc/ZBarReaderViewController.rst | 56 +++++++++++++++++++++++++ iphone/doc/camera.rst | 12 +++--- iphone/doc/tutorial.rst | 9 +++- 5 files changed, 86 insertions(+), 7 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 735f053..11656f5 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,5 @@ -current: +version 1.1.1: + * 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 diff --git a/iphone/doc/ZBarReaderView.rst b/iphone/doc/ZBarReaderView.rst index 2652a8e..de16173 100644 --- a/iphone/doc/ZBarReaderView.rst +++ b/iphone/doc/ZBarReaderView.rst @@ -106,3 +106,16 @@ Instance Methods 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. diff --git a/iphone/doc/ZBarReaderViewController.rst b/iphone/doc/ZBarReaderViewController.rst index 787a86b..bd9bb1f 100644 --- a/iphone/doc/ZBarReaderViewController.rst +++ b/iphone/doc/ZBarReaderViewController.rst @@ -32,6 +32,12 @@ Properties 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 @@ -47,6 +53,15 @@ Properties A transform to apply to the camera preview. Ignored by the reader. + .. member:: UIImagePickerControllerCameraDevice cameraDevice + + The camera device to use for scanning. + + .. member:: UIImagePickerControllerCameraFlashMode cameraFlashMode + + The "flash" (aka torch) mode to use while scanning. Defaults to + UIImagePickerControllerCameraFlashModeAuto. + .. member:: ZBarReaderView *readerView View that presents the camera preview and performs the scanning. This @@ -73,6 +88,11 @@ Properties ``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. @@ -114,6 +134,21 @@ Class Methods :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 ---------------- @@ -126,3 +161,24 @@ Instance Methods 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) diff --git a/iphone/doc/camera.rst b/iphone/doc/camera.rst index a04a1c6..ea446a5 100644 --- a/iphone/doc/camera.rst +++ b/iphone/doc/camera.rst @@ -9,8 +9,8 @@ There are three levels that you may choose to integrate at, from least complex * 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 is not recommended, it - does not give you much more flexibility than using the full controller. +* 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. @@ -111,9 +111,11 @@ Using a ZBarReaderView ---------------------- :class:`ZBarReaderViewController` is a relatively thin wrapper around a -:class:`ZBarReaderView`; it is possible to use the view directly. You will -lose the automatic fallback for iOS 3.1 and some of the simulator hooks, so -this approach is not currently recommended (or well tested). +:class:`ZBarReaderView`; it is possible to use the view directly, even from +Interface Builder. You will lose the automatic fallback for iOS 3.1 and 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 diff --git a/iphone/doc/tutorial.rst b/iphone/doc/tutorial.rst index 4a6eec9..19be979 100644 --- a/iphone/doc/tutorial.rst +++ b/iphone/doc/tutorial.rst @@ -72,11 +72,17 @@ Create the App NSLog(@"TBD: scan barcode here..."); } - - (void) dealloc { + - (void) dealloc + { self.resultImage = nil; self.resultText = nil; [super dealloc]; } + + - (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation + { + return(YES); + } This stub for scanButtonTapped is temporary, we'll fix it in a minute... @@ -136,6 +142,7 @@ Now for the exciting part - let's add a barcode reader! // ADD: present a barcode reader that scans from the camera feed ZBarReaderViewController *reader = [ZBarReaderViewController new]; reader.readerDelegate = self; + reader.supportedOrientationsMask = ZBarOrientationMaskAll; ZBarImageScanner *scanner = reader.scanner; // TODO: (optional) additional reader configuration here From 6c0d5efcc56c93c2481f63eb7e80553cd8128701 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 16 Jun 2011 12:18:15 -0700 Subject: [PATCH 292/328] disable addons by default until synchronization with main symbol is working --- ChangeLog | 1 + iphone/examples/readertest/readertest.m | 2 +- zbar/decoder.c | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index ab335f4..fa23afe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * 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 diff --git a/iphone/examples/readertest/readertest.m b/iphone/examples/readertest/readertest.m index 2647ab7..cf18421 100644 --- a/iphone/examples/readertest/readertest.m +++ b/iphone/examples/readertest/readertest.m @@ -444,7 +444,7 @@ - (void) initControlCells [NSNumber numberWithInteger: sym]]; else /* symbologies after ZBAR_EAN5 are disabled by default */ - en = en && (sym != ZBAR_COMPOSITE); + en = en && (sym != ZBAR_EAN2); [symbols addObject: [self cellWithTitle: [ZBarSymbol nameForType: sym] tag: sym diff --git a/zbar/decoder.c b/zbar/decoder.c index 4d2dc25..3114765 100644 --- a/zbar/decoder.c +++ b/zbar/decoder.c @@ -54,8 +54,10 @@ zbar_decoder_t *zbar_decoder_create () dcode->ean.upce_config = 1 << ZBAR_CFG_EMIT_CHECK; dcode->ean.isbn10_config = 1 << ZBAR_CFG_EMIT_CHECK; dcode->ean.isbn13_config = 1 << ZBAR_CFG_EMIT_CHECK; +# ifdef FIXME_ADDON_SYNC dcode->ean.ean2_config = 1 << ZBAR_CFG_ENABLE; dcode->ean.ean5_config = 1 << ZBAR_CFG_ENABLE; +# endif #endif #ifdef ENABLE_I25 dcode->i25.config = 1 << ZBAR_CFG_ENABLE; From d08189db4c4f86d1e0addd51db3142ec5b40f98c Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 16 Jun 2011 13:24:26 -0700 Subject: [PATCH 293/328] iPhone: README document new examples - make ReaderSample scheme public --- COPYING | 2 +- iphone/ChangeLog | 2 + iphone/README | 15 +++- iphone/doc/install.rst | 8 +- .../xcschemes/ReaderSample.xcscheme | 76 +++++++++++++++++++ 5 files changed, 94 insertions(+), 9 deletions(-) create mode 100644 iphone/examples/ReaderSample/ReaderSample.xcodeproj/xcshareddata/xcschemes/ReaderSample.xcscheme diff --git a/COPYING b/COPYING index d0b0654..15fe8ed 100644 --- a/COPYING +++ b/COPYING @@ -1,4 +1,4 @@ -The ZBar Bar Code Reader is Copyright (C) 2007-2010 Jeff Brown +The ZBar Bar Code Reader is Copyright (C) 2007-2011 Jeff Brown The QR Code reader is Copyright (C) 1999-2009 Timothy B. Terriberry diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 11656f5..9a1f218 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,6 @@ version 1.1.1: + * 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 diff --git a/iphone/README b/iphone/README index 25acea8..d631ba0 100644 --- a/iphone/README +++ b/iphone/README @@ -37,6 +37,11 @@ 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. @@ -44,9 +49,11 @@ resulting Xcode project at Examples/ReaderSample. Examples/readertest demonstrates most of the configuration options available for the reader. -You should be able to open and build the examples directly from the -disk image. If not, please copy them to your local drive and build -from there. +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 --------------------- @@ -54,6 +61,6 @@ 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-2010 © Jeff Brown et al +Copyright 2008-2011 © Jeff Brown et al See the included files COPYING and LICENSE for details diff --git a/iphone/doc/install.rst b/iphone/doc/install.rst index 231fd77..dca9d2e 100644 --- a/iphone/doc/install.rst +++ b/iphone/doc/install.rst @@ -93,10 +93,10 @@ 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 you source stays -the same, you just need to update how the library is included in the project -and how the headers are imported. +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 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/iphone/examples/ReaderSample/ReaderSample.xcodeproj/xcshareddata/xcschemes/ReaderSample.xcscheme b/iphone/examples/ReaderSample/ReaderSample.xcodeproj/xcshareddata/xcschemes/ReaderSample.xcscheme new file mode 100644 index 0000000..12fb1da --- /dev/null +++ b/iphone/examples/ReaderSample/ReaderSample.xcodeproj/xcshareddata/xcschemes/ReaderSample.xcscheme @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From b9f882344b4c723a6a938f23e9301ebaaf264f44 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 16 Jun 2011 13:59:48 -0700 Subject: [PATCH 294/328] iPhone: fix ReaderSample project path to ZBarSDK --- iphone/ChangeLog | 1 + .../ReaderSample/ReaderSample.xcodeproj/project.pbxproj | 9 ++++----- iphone/examples/ReaderSample/ZBarSDK | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 9a1f218..3eb236b 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,5 @@ version 1.1.1: + * fix ReaderSample project path to ZBarSDK * README document new examples - make ReaderSample scheme public * documentation updates diff --git a/iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj b/iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj index d5dde31..79a4af4 100644 --- a/iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj +++ b/iphone/examples/ReaderSample/ReaderSample.xcodeproj/project.pbxproj @@ -98,6 +98,7 @@ isa = PBXGroup; children = ( DC8F289913579EFF005B8862 /* ReaderSample */, + DC8F28B31357A29D005B8862 /* ZBarSDK */, DC8F289213579EFF005B8862 /* Frameworks */, DC8F289013579EFF005B8862 /* Products */, ); @@ -136,7 +137,6 @@ DC8F28A913579EFF005B8862 /* ReaderSampleViewController.m */, DC8F28AB13579EFF005B8862 /* ReaderSampleViewController.xib */, DC8F289A13579EFF005B8862 /* Supporting Files */, - DC8F28B31357A29D005B8862 /* ZBarSDK */, ); path = ReaderSample; sourceTree = ""; @@ -159,8 +159,7 @@ DC8F28CA1357A29D005B8862 /* libzbar.a */, DC8F28CB1357A29D005B8862 /* Resources */, ); - name = ZBarSDK; - path = "../../../build/Release-iphoneos/ZBarSDK"; + path = ZBarSDK; sourceTree = ""; }; DC8F28B41357A29D005B8862 /* Headers */ = { @@ -362,7 +361,7 @@ INFOPLIST_FILE = "ReaderSample/ReaderSample-Info.plist"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "\"$(SRCROOT)/../../build/Release-iphoneos/ZBarSDK\"", + "\"$(SRCROOT)/ZBarSDK\"", ); PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = "1,2"; @@ -380,7 +379,7 @@ INFOPLIST_FILE = "ReaderSample/ReaderSample-Info.plist"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "\"$(SRCROOT)/../../build/Release-iphoneos/ZBarSDK\"", + "\"$(SRCROOT)/ZBarSDK\"", ); PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/iphone/examples/ReaderSample/ZBarSDK b/iphone/examples/ReaderSample/ZBarSDK index b8e7666..7a373ea 120000 --- a/iphone/examples/ReaderSample/ZBarSDK +++ b/iphone/examples/ReaderSample/ZBarSDK @@ -1 +1 @@ -../../build/Release-iphoneos/ZBarSDK \ No newline at end of file +../../build/Debug-iphoneos/ZBarSDK \ No newline at end of file From 7ad0b306f7daa44b9063776b524c4b9941879b29 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 16 Jun 2011 14:07:59 -0700 Subject: [PATCH 295/328] Added tag iPhoneSDK-1.1.1 for changeset f9e46865dbce From 48d7bc1aefa34ac69721329f00df374e95cd4ae3 Mon Sep 17 00:00:00 2001 From: spadix Date: Wed, 22 Jun 2011 17:34:58 -0700 Subject: [PATCH 296/328] iPhone: fix several simulator-related bugs - fix device property missing from simulated ZBarReaderView - fix AVCaptureDevice referenced from ZBarReaderViewController - fix simulated camera gesture multiple recognition --- iphone/ChangeLog | 6 ++++++ iphone/ZBarCameraSimulator.m | 8 +++++++- iphone/ZBarReaderViewController.m | 8 ++++++-- iphone/ZBarReaderViewImpl_Simulator.m | 10 ++++++++++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 3eb236b..96c4435 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,3 +1,9 @@ +version 1.1.2: + * 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 diff --git a/iphone/ZBarCameraSimulator.m b/iphone/ZBarCameraSimulator.m index 2ed4839..96fd753 100644 --- a/iphone/ZBarCameraSimulator.m +++ b/iphone/ZBarCameraSimulator.m @@ -65,12 +65,18 @@ - (void) setReaderView: (ZBarReaderView*) view UILongPressGestureRecognizer *gesture = [[UILongPressGestureRecognizer alloc] initWithTarget: self - action: @selector(takePicture)]; + 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) { diff --git a/iphone/ZBarReaderViewController.m b/iphone/ZBarReaderViewController.m index b7c60c1..0aced30 100644 --- a/iphone/ZBarReaderViewController.m +++ b/iphone/ZBarReaderViewController.m @@ -62,12 +62,14 @@ 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); } @@ -134,8 +136,10 @@ - (void) _init cameraViewTransform = CGAffineTransformIdentity; cameraFlashMode = UIImagePickerControllerCameraFlashModeAuto; - AVCaptureDevice *device = - [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo]; + AVCaptureDevice *device = nil; +#if !TARGET_IPHONE_SIMULATOR + device = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo]; +#endif if(device) cameraDevice = UICameraForAVPosition(device.position); else diff --git a/iphone/ZBarReaderViewImpl_Simulator.m b/iphone/ZBarReaderViewImpl_Simulator.m index ee808ba..238efff 100644 --- a/iphone/ZBarReaderViewImpl_Simulator.m +++ b/iphone/ZBarReaderViewImpl_Simulator.m @@ -95,6 +95,16 @@ - (void) dealloc [super dealloc]; } +- (AVCaptureDevice*) device +{ + return(nil); +} + +- (void) setDevice: (AVCaptureDevice*) device +{ + // simulated camera does nothing with this +} + - (void) updateCrop { previewImage.frame = preview.bounds; From e26195a345a30a94ef0b794e8252996bf9071f4c Mon Sep 17 00:00:00 2001 From: tterribe Date: Wed, 29 Jun 2011 23:18:43 -0700 Subject: [PATCH 297/328] Various QR decoder fixes to bring it more in-line with the spec. - Support mirror-image reversals. We still don't support reflectance-reversals. - Properly compute the self-parity of each symbol in an S-A group. We still don't use it to validate the parity of the entire group. - Properly decode the Application Indicator for FNC1 in the 2nd position, and prepend its textual representation to the output. - Only use the first S-A header, instead of the last, as this is supposed to be the very first entry in the stream. - Only use the first FNC1 marker, instead of the last, as this is supposed to appear once, before any data entries (after S-A and ECI). - Properly reserve some of the parity bytes for small codes (versions 1, 2-L, and 3-L) for error detection instead of correction, as the spec requires. This causes zxing-4/43.png to fail where it succeeded before. - Add support for the UTF-8 ECI marker (000026). - Treat data encoded in kanji mode as part of the ECI-specified character set, if any, instead of always treating it as SJIS. Also, assorted bug fixes: - Properly reset the "empty" count after finding an isolated module while scanning the right edge during homography estimation. - Avoid division by zero when projecting the lower-right alignment pattern out to the corner during homography estimation. - Limit the number of consecutive invalid configurations we'll try, to avoid long delays in images with lots of finder-pattern-like features. - Properly report the FNC1 markers back to zbar via the modifiers field. --- zbar/decoder.h | 2 + zbar/decoder/qr_finder.c | 4 + zbar/qrcode/qrdec.c | 199 +++++++++++++++++++++++++++------------ zbar/qrcode/qrdec.h | 6 +- zbar/qrcode/qrdectxt.c | 72 +++++++++----- zbar/qrcode/util.h | 8 ++ 6 files changed, 208 insertions(+), 83 deletions(-) diff --git a/zbar/decoder.h b/zbar/decoder.h index 51358a0..aedfa1e 100644 --- a/zbar/decoder.h +++ b/zbar/decoder.h @@ -28,6 +28,8 @@ #include +#include "debug.h" + #define NUM_CFGS (ZBAR_CFG_MAX_LEN - ZBAR_CFG_MIN_LEN + 1) #ifdef ENABLE_EAN diff --git a/zbar/decoder/qr_finder.c b/zbar/decoder/qr_finder.c index d187d76..7a55733 100644 --- a/zbar/decoder/qr_finder.c +++ b/zbar/decoder/qr_finder.c @@ -51,6 +51,10 @@ zbar_symbol_type_t _zbar_find_qr (zbar_decoder_t *dcode) qrf->s5 += get_width(dcode, 1); s = qrf->s5; + /*TODO: The 2005 standard allows reflectance-reversed codes (light on dark + instead of dark on light). + If we find finder patterns with the opposite polarity, we should invert + the final binarized image and use them to search for QR codes in that.*/ if(get_color(dcode) != ZBAR_SPACE || s < 7) return(0); diff --git a/zbar/qrcode/qrdec.c b/zbar/qrcode/qrdec.c index 4df1d32..d8fa802 100644 --- a/zbar/qrcode/qrdec.c +++ b/zbar/qrcode/qrdec.c @@ -2103,7 +2103,7 @@ static int qr_hom_fit(qr_hom *_hom,qr_finder *_ul,qr_finder *_ur, rlastfit=nr; } } - else nrempty=0; + nrempty=0; } else nrempty++; ru+=dru; @@ -2247,6 +2247,8 @@ static int qr_hom_fit(qr_hom *_hom,qr_finder *_ul,qr_finder *_ur, w=QR_EXTMUL(dim-7,c21, QR_EXTMUL(dim-13,_p[0][0]*dy21-_p[0][1]*dx21, QR_EXTMUL(6,p3[0]*dy21-p3[1]*dx21,0))); + /*The projection failed: invalid geometry.*/ + if(w==0)return -1; mask=QR_SIGNMASK(w); w=w+mask^mask; brx=(int)QR_DIVROUND(QR_EXTMUL((dim-7)*_p[0][0],p3[0]*dy21, @@ -2364,11 +2366,10 @@ static int qr_finder_version_decode(qr_finder *_f,const qr_hom *_hom, w0+=dwi; } ret=bch18_6_correct(&v); - /*TODO: I'd certainly hope the order the version bits is accessed in is - well-defined, but I seem to have images for two different codes with the - same version using two different orders? - Maybe the other one is a model 1 code? - Even if I parse the version here, I can't decode the rest of the code. + /*TODO: I seem to have an image with the version bits in a different order + (the transpose of the standard order). + Even if I change the order here so I can parse the version on this image, + I can't decode the rest of the code. If this is really needed, we should just re-order the bits.*/ #if 0 if(ret<0){ @@ -2486,16 +2487,9 @@ static int qr_finder_fmt_info_decode(qr_finder *_ul,qr_finder *_ur, y+=dy; w+=dw; } - /*For the 8th bit we have 3 samples... use the majority value. - TODO: The DL bit appears to be wrong as much as right? Guess it's not - really a third copy after all, but doesn't appear to be used for data. - i=((lo[0]>>7&1)+(lo[1]>>7&1)+(hi[1]>>7&1)>>1)<<7; - lo[0]=lo[0]&~0x80|i; - lo[1]=lo[1]&~0x80|i; - hi[1]&=~0x80;*/ - /*For the remaining bits we have two samples... try them in all - combinations and pick the most popular valid code, breaking ties using - the number of bit errors.*/ + /*For each group of bits we have two samples... try them in all combinations + and pick the most popular valid code, breaking ties using the number of + bit errors.*/ imax=2<<(hi[0]!=hi[1]); di=1+(lo[0]==lo[1]); nfmt_info=0; @@ -3192,6 +3186,7 @@ static const unsigned char QR_ALNUM_TABLE[45]={ static int qr_code_data_parse(qr_code_data *_qrdata,int _version, const unsigned char *_data,int _ndata){ qr_pack_buf qpb; + unsigned self_parity; int centries; int len_bits_idx; /*Entries are stored directly in the struct during parsing. @@ -3199,6 +3194,7 @@ static int qr_code_data_parse(qr_code_data *_qrdata,int _version, _qrdata->entries=NULL; _qrdata->nentries=0; _qrdata->sa_size=0; + self_parity=0; centries=0; /*The versions are divided into 3 ranges that each use a different number of bits for length fields.*/ @@ -3217,9 +3213,10 @@ static int qr_code_data_parse(qr_code_data *_qrdata,int _version, centries*sizeof(*_qrdata->entries)); } entry=_qrdata->entries+_qrdata->nentries++; - /*Set the mode to an invalid value until we allocate a buffer for it. - This ensures we don't try to free it on clean-up until then.*/ - entry->mode=-1; + entry->mode=mode; + /*Set the buffer to NULL, because if parsing fails, we might try to free it + on clean-up.*/ + entry->payload.data.buf=NULL; switch(mode){ /*The number of bits used to encode the character count for each version range and each data mode.*/ @@ -3231,6 +3228,7 @@ static int qr_code_data_parse(qr_code_data *_qrdata,int _version, case QR_MODE_NUM:{ unsigned char *buf; unsigned bits; + unsigned c; int len; int count; int rem; @@ -3241,35 +3239,47 @@ static int qr_code_data_parse(qr_code_data *_qrdata,int _version, count=len/3; rem=len%3; if(qr_pack_buf_avail(&qpb)<10*count+7*(rem>>1&1)+4*(rem&1))return -1; - entry->mode=mode; entry->payload.data.buf=buf=(unsigned char *)malloc(len*sizeof(*buf)); entry->payload.data.len=len; /*Read groups of 3 digits encoded in 10 bits.*/ while(count-->0){ bits=qr_pack_buf_read(&qpb,10); if(bits>=1000)return -1; - *buf++=(unsigned char)('0'+bits/100); + c='0'+bits/100; + self_parity^=c; + *buf++=(unsigned char)c; bits%=100; - *buf++=(unsigned char)('0'+bits/10); - *buf++=(unsigned char)('0'+bits%10); + c='0'+bits/10; + self_parity^=c; + *buf++=(unsigned char)c; + c='0'+bits%10; + self_parity^=c; + *buf++=(unsigned char)c; } /*Read the last two digits encoded in 7 bits.*/ if(rem>1){ bits=qr_pack_buf_read(&qpb,7); if(bits>=100)return -1; - *buf++=(unsigned char)('0'+bits/10); - *buf++=(unsigned char)('0'+bits%10); + c='0'+bits/10; + self_parity^=c; + *buf++=(unsigned char)c; + c='0'+bits%10; + self_parity^=c; + *buf++=(unsigned char)c; } /*Or the last one digit encoded in 4 bits.*/ else if(rem){ bits=qr_pack_buf_read(&qpb,4); if(bits>=10)return -1; - *buf++=(unsigned char)('0'+bits); + c='0'+bits; + self_parity^=c; + *buf++=(unsigned char)c; } }break; case QR_MODE_ALNUM:{ unsigned char *buf; unsigned bits; + unsigned c; int len; int count; int rem; @@ -3280,56 +3290,67 @@ static int qr_code_data_parse(qr_code_data *_qrdata,int _version, count=len>>1; rem=len&1; if(qr_pack_buf_avail(&qpb)<11*count+6*rem)return -1; - entry->mode=mode; entry->payload.data.buf=buf=(unsigned char *)malloc(len*sizeof(*buf)); entry->payload.data.len=len; /*Read groups of two characters encoded in 11 bits.*/ while(count-->0){ bits=qr_pack_buf_read(&qpb,11); if(bits>=2025)return -1; - *buf++=QR_ALNUM_TABLE[bits/45]; - *buf++=QR_ALNUM_TABLE[bits%45]; + c=QR_ALNUM_TABLE[bits/45]; + self_parity^=c; + *buf++=(unsigned char)c; + c=QR_ALNUM_TABLE[bits%45]; + self_parity^=c; + *buf++=(unsigned char)c; len-=2; } /*Read the last character encoded in 6 bits.*/ if(rem){ bits=qr_pack_buf_read(&qpb,6); if(bits>=45)return -1; - *buf++=QR_ALNUM_TABLE[bits]; + c=QR_ALNUM_TABLE[bits]; + self_parity^=c; + *buf++=(unsigned char)c; } }break; /*Structured-append header.*/ case QR_MODE_STRUCT:{ int bits; - entry->mode=mode; bits=qr_pack_buf_read(&qpb,16); if(bits<0)return -1; - /*We also save a copy of the data in _qrdata for easy reference when + /*We save a copy of the data in _qrdata for easy reference when grouping structured-append codes. - If for some reason the code has multiple S-A headers, last one wins - (TODO: should we return an error instead?).*/ - _qrdata->sa_index=entry->payload.sa.sa_index= - (unsigned char)(bits>>12&0xF); - _qrdata->sa_size=entry->payload.sa.sa_size= - (unsigned char)((bits>>8&0xF)+1); - _qrdata->sa_parity=entry->payload.sa.sa_parity= - (unsigned char)(bits&0xFF); + If for some reason the code has multiple S-A headers, first one wins, + since it is supposed to come before everything else (TODO: should we + return an error instead?).*/ + if(_qrdata->sa_size==0){ + _qrdata->sa_index=entry->payload.sa.sa_index= + (unsigned char)(bits>>12&0xF); + _qrdata->sa_size=entry->payload.sa.sa_size= + (unsigned char)((bits>>8&0xF)+1); + _qrdata->sa_parity=entry->payload.sa.sa_parity= + (unsigned char)(bits&0xFF); + } }break; case QR_MODE_BYTE:{ unsigned char *buf; + unsigned c; int len; len=qr_pack_buf_read(&qpb,LEN_BITS[len_bits_idx][2]); if(len<0)return -1; /*Check to see if there are enough bits left now, so we don't have to in the decode loop.*/ if(qr_pack_buf_avail(&qpb)mode=mode; entry->payload.data.buf=buf=(unsigned char *)malloc(len*sizeof(*buf)); entry->payload.data.len=len; - while(len-->0)*buf++=(unsigned char)qr_pack_buf_read(&qpb,8); + while(len-->0){ + c=qr_pack_buf_read(&qpb,8); + self_parity^=c; + *buf++=(unsigned char)c; + } }break; /*FNC1 first position marker.*/ - case QR_MODE_FNC1_1ST:entry->mode=mode;break; + case QR_MODE_FNC1_1ST:break; /*Extended Channel Interpretation data.*/ case QR_MODE_ECI:{ unsigned val; @@ -3357,7 +3378,6 @@ static int qr_code_data_parse(qr_code_data *_qrdata,int _version, } /*Invalid lead byte.*/ else return -1; - entry->mode=mode; entry->payload.eci=val; }break; case QR_MODE_KANJI:{ @@ -3369,7 +3389,6 @@ static int qr_code_data_parse(qr_code_data *_qrdata,int _version, /*Check to see if there are enough bits left now, so we don't have to in the decode loop.*/ if(qr_pack_buf_avail(&qpb)<13*len)return -1; - entry->mode=mode; entry->payload.data.buf=buf=(unsigned char *)malloc(2*len*sizeof(*buf)); entry->payload.data.len=2*len; /*Decode 2-byte SJIS characters encoded in 13 bits.*/ @@ -3377,14 +3396,28 @@ static int qr_code_data_parse(qr_code_data *_qrdata,int _version, bits=qr_pack_buf_read(&qpb,13); bits=(bits/0xC0<<8|bits%0xC0)+0x8140; if(bits>=0xA000)bits+=0x4000; - /*Are values 0xXX7F, 0xXXFD...0xXXFF always invalid? + /*TODO: Are values 0xXX7F, 0xXXFD...0xXXFF always invalid? Should we reject them here?*/ + self_parity^=bits; *buf++=(unsigned char)(bits>>8); *buf++=(unsigned char)(bits&0xFF); } }break; /*FNC1 second position marker.*/ - case QR_MODE_FNC1_2ND:entry->mode=mode;break; + case QR_MODE_FNC1_2ND:{ + int bits; + /*FNC1 in the 2nd position encodes an Application Indicator in one + byte, which is either a letter (A...Z or a...z) or a 2-digit number. + The letters are encoded with their ASCII value plus 100, the numbers + are encoded directly with their numeric value. + Values 100...164, 191...196, and 223...255 are invalid, so we reject + them here.*/ + bits=qr_pack_buf_read(&qpb,8); + if(!(bits>=0&&bits<100||bits>=165&&bits<191||bits>=197&&bits<223)){ + return -1; + } + entry->payload.ai=bits; + }break; /*Unknown mode number:*/ default:{ /*Unfortunately, because we have to understand the format of a mode to @@ -3394,9 +3427,11 @@ static int qr_code_data_parse(qr_code_data *_qrdata,int _version, }break; } } - /*TODO: If there was a S-A header, we should compute the parity of this - code; how are non-data modes handled (ECI, FNC1)?*/ - _qrdata->self_parity=0; + /*Store the parity of the data from this code, for S-A. + The final parity is the 8-bit XOR of all the decoded bytes of literal data. + We don't combine the 2-byte kanji codes into one byte in the loops above, + because we can just do it here instead.*/ + _qrdata->self_parity=((self_parity>>8)^self_parity)&0xFF; /*Success.*/ _qrdata->entries=(qr_code_data_entry *)realloc(_qrdata->entries, _qrdata->nentries*sizeof(*_qrdata->entries)); @@ -3573,7 +3608,17 @@ static int qr_code_decode(qr_code_data *_qrdata,const rs_gf256 *_gf, int block_szi; int ndatai; block_szi=block_sz+(i>=nshort_blocks); - if(rs_correct(_gf,QR_M0,block_data+ncodewords,block_szi,npar,NULL,0)<0){ + ret=rs_correct(_gf,QR_M0,block_data+ncodewords,block_szi,npar,NULL,0); + /*For version 1 symbols and version 2-L and 3-L symbols, we aren't allowed + to use all the parity bytes for correction. + They are instead used to improve detection. + Version 1-L reserves 3 parity bytes for detection. + Versions 1-M and 2-L reserve 2 parity bytes for detection. + Versions 1-Q, 1-H, and 3-L reserve 1 parity byte for detection. + We can ignore the version 3-L restriction because it has an odd number of + parity bytes, and we don't support erasure detection.*/ + if(ret<0||_version==1&&ret>ecc_level+1<<1|| + _version==2&&ecc_level==0&&ret>4){ ret=-1; break; } @@ -3635,6 +3680,7 @@ static int qr_reader_try_configuration(qr_reader *_reader, qr_finder ul; qr_finder ur; qr_finder dl; + qr_point bbox[4]; int res; int ur_version; int dl_version; @@ -3671,10 +3717,11 @@ static int qr_reader_try_configuration(qr_reader *_reader, #endif /*If we made it this far, upgrade the affine homography to a full homography.*/ - if(qr_hom_fit(&hom,&ul,&ur,&dl,_qrdata->bbox,&aff, + if(qr_hom_fit(&hom,&ul,&ur,&dl,bbox,&aff, &_reader->isaac,_img,_width,_height)<0){ continue; } + memcpy(_qrdata->bbox,bbox,sizeof(bbox)); qr_hom_unproject(ul.o,&hom,ul.c->pos[0],ul.c->pos[1]); qr_hom_unproject(ur.o,&hom,ur.c->pos[0],ur.c->pos[1]); qr_hom_unproject(dl.o,&hom,dl.c->pos[0],dl.c->pos[1]); @@ -3797,14 +3844,37 @@ static int qr_reader_try_configuration(qr_reader *_reader, continue; } fmt_info=qr_finder_fmt_info_decode(&ul,&ur,&dl,&hom,_img,_width,_height); - if(fmt_info<0)continue; - if(qr_code_decode(_qrdata,&_reader->gf,ul.c->pos,ur.c->pos,dl.c->pos, + if(fmt_info<0|| + qr_code_decode(_qrdata,&_reader->gf,ul.c->pos,ur.c->pos,dl.c->pos, ur_version,fmt_info,_img,_width,_height)<0){ - /*TODO: Maybe somebody flipped the code? - We'd still get a valid version, and probably valid (but incorrect) - format info. - After we've come this far, it should be a simple matter to check.*/ - continue; + /*The code may be flipped. + Try again, swapping the UR and DL centers. + We should get a valid version either way, so it's relatively cheap to + check this, as we've already filtered out a lot of invalid + configurations.*/ + QR_SWAP2I(hom.inv[0][0],hom.inv[1][0]); + QR_SWAP2I(hom.inv[0][1],hom.inv[1][1]); + QR_SWAP2I(hom.fwd[0][0],hom.fwd[0][1]); + QR_SWAP2I(hom.fwd[1][0],hom.fwd[1][1]); + QR_SWAP2I(hom.fwd[2][0],hom.fwd[2][1]); + QR_SWAP2I(ul.o[0],ul.o[1]); + QR_SWAP2I(ul.size[0],ul.size[1]); + QR_SWAP2I(ur.o[0],ur.o[1]); + QR_SWAP2I(ur.size[0],ur.size[1]); + QR_SWAP2I(dl.o[0],dl.o[1]); + QR_SWAP2I(dl.size[0],dl.size[1]); +#if defined(QR_DEBUG) + qr_finder_dump_hom_undistorted(&ul,&dl,&ur,&hom,_img,_width,_height); +#endif + fmt_info=qr_finder_fmt_info_decode(&ul,&dl,&ur,&hom,_img,_width,_height); + if(fmt_info<0)continue; + QR_SWAP2I(bbox[1][0],bbox[2][0]); + QR_SWAP2I(bbox[1][1],bbox[2][1]); + memcpy(_qrdata->bbox,bbox,sizeof(bbox)); + if(qr_code_decode(_qrdata,&_reader->gf,ul.c->pos,dl.c->pos,ur.c->pos, + ur_version,fmt_info,_img,_width,_height)<0){ + continue; + } } return ur_version; } @@ -3817,10 +3887,14 @@ void qr_reader_match_centers(qr_reader *_reader,qr_code_data_list *_qrlist, /*The number of centers should be small, so an O(n^3) exhaustive search of which ones go together should be reasonable.*/ unsigned char *mark; + int nfailures_max; + int nfailures; int i; int j; int k; mark=(unsigned char *)calloc(_ncenters,sizeof(*mark)); + nfailures_max=QR_MAXI(8192,_width*_height>>9); + nfailures=0; for(i=0;i<_ncenters;i++){ /*TODO: We might be able to accelerate this step significantly by considering the remaining finder centers in a more intelligent order, @@ -3873,6 +3947,13 @@ void qr_reader_match_centers(qr_reader *_reader,qr_code_data_list *_qrlist, } /*Mark _all_ such centers used: codes cannot partially overlap.*/ for(l=0;l<_ncenters;l++)if(mark[l]==2)mark[l]=1; + nfailures=0; + } + else if(++nfailures>nfailures_max){ + /*Give up. + We're unlikely to find a valid code in all this clutter, and we + could spent quite a lot of time trying.*/ + i=j=k=_ncenters; } } } diff --git a/zbar/qrcode/qrdec.h b/zbar/qrcode/qrdec.h index 2074e68..3d3d0de 100644 --- a/zbar/qrcode/qrdec.h +++ b/zbar/qrcode/qrdec.h @@ -85,7 +85,9 @@ typedef enum qr_eci_encoding{ QR_ECI_ISO8859_16, /*ECI 000019 is reserved?*/ /*Shift-JIS.*/ - QR_ECI_SJIS=20 + QR_ECI_SJIS=20, + /*UTF-8.*/ + QR_ECI_UTF8=26 }qr_eci_encoding; @@ -101,6 +103,8 @@ struct qr_code_data_entry{ }data; /*Decoded "Extended Channel Interpretation" data.*/ unsigned eci; + /*Decoded "Application Indicator" for FNC1 in 2nd position.*/ + int ai; /*Structured-append header data.*/ struct{ unsigned char sa_index; diff --git a/zbar/qrcode/qrdectxt.c b/zbar/qrcode/qrdectxt.c index c6d400e..e54fa69 100644 --- a/zbar/qrcode/qrdectxt.c +++ b/zbar/qrcode/qrdectxt.c @@ -12,6 +12,7 @@ #include "qrdec.h" #include "util.h" #include "image.h" +#include "decoder.h" #include "error.h" #include "img_scanner.h" @@ -74,6 +75,8 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, size_t sa_ntext; size_t sa_ctext; int fnc1; + int fnc1_2ai; + int has_kanji; int eci; int err; int j; @@ -106,6 +109,8 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, sa_ctext=0; fnc1=0; + fnc1_2ai=0; + has_kanji=0; /*Step 1: Detect FNC1 markers and estimate the required buffer size.*/ for(j=0;j=0){ qrdataj=qrdata+sa[j]; @@ -115,13 +120,20 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, shift=0; switch(entry->mode){ /*FNC1 applies to the entire code and ignores subsequent markers.*/ - case QR_MODE_FNC1_1ST: - case QR_MODE_FNC1_2ND:fnc1=1;break; - /*2 SJIS bytes will be at most 4 UTF-8 bytes.*/ - case QR_MODE_KANJI:shift++; + case QR_MODE_FNC1_1ST:{ + if(!fnc1)fnc1=MOD(ZBAR_MOD_GS1); + }break; + case QR_MODE_FNC1_2ND:{ + if(!fnc1){ + fnc1=MOD(ZBAR_MOD_AIM); + fnc1_2ai=entry->payload.ai; + sa_ctext+=2; + } + }break; /*We assume at most 4 UTF-8 bytes per input byte. I believe this is true for all the encodings we actually use.*/ - case QR_MODE_BYTE:shift++; + case QR_MODE_KANJI:has_kanji=1; + case QR_MODE_BYTE:shift=2; default:{ /*The remaining two modes are already valid UTF-8.*/ if(QR_MODE_HAS_DATA(entry->mode)){ @@ -135,6 +147,18 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, /*Step 2: Convert the entries.*/ sa_text=(char *)malloc((sa_ctext+1)*sizeof(*sa_text)); sa_ntext=0; + /*Add the encoded Application Indicator for FNC1 in the second position.*/ + if(fnc1==MOD(ZBAR_MOD_AIM)){ + if(fnc1_2ai<100){ + /*The Application Indicator is a 2-digit number.*/ + sa_text[sa_ntext++]='0'+fnc1_2ai/10; + sa_text[sa_ntext++]='0'+fnc1_2ai%10; + } + /*The Application Indicator is a single letter. + We already checked that it lies in one of the ranges A...Z, a...z + when we decoded it.*/ + else sa_text[sa_ntext++]=(char)(fnc1_2ai-100); + } eci=-1; enc_list[0]=sjis_cd; enc_list[1]=latin1_cd; @@ -230,7 +254,8 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, Does such a thing occur? Is it allowed? It requires copying buffers around to handle correctly.*/ - case QR_MODE_BYTE:{ + case QR_MODE_BYTE: + case QR_MODE_KANJI:{ in=(char *)entry->payload.data.buf; inleft=entry->payload.data.len; out=sa_text+sa_ntext; @@ -238,8 +263,12 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, /*If we have no specified encoding, attempt to auto-detect it.*/ if(eci<0){ int ei; - /*First check for the UTF-8 BOM.*/ - if(inleft>=3&& + /*If there was data encoded in kanji mode, assume it's SJIS.*/ + if(has_kanji)enc_list_mtf(enc_list,sjis_cd); + /*Otherwise check for the UTF-8 BOM. + There's no way to specify UTF-8 using ECI, so this is the + only way for encoders to reliably indicate it.*/ + else if(inleft>=3&& in[0]==(char)0xEF&&in[1]==(char)0xBB&&in[2]==(char)0xBF){ in+=3; inleft-=3; @@ -256,15 +285,17 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, out=sa_text+sa_ntext; outleft=sa_ctext-sa_ntext; } - /*If the text is 8-bit clean, prefer UTF-8 over SJIS, since SJIS - will corrupt the backslashes used for DoCoMo formats.*/ + /*If the text is 8-bit clean, prefer UTF-8 over SJIS, since + SJIS will corrupt the backslashes used for DoCoMo formats.*/ else if(text_is_ascii((unsigned char *)in,inleft)){ enc_list_mtf(enc_list,utf8_cd); } /*Try our list of encodings.*/ for(ei=0;ei<3;ei++)if(enc_list[ei]!=(iconv_t)-1){ - /*According to the standard, ISO/IEC 8859-1 (one hyphen) is - supposed to be used, but reality is not always so. + /*According to the 2005 version of the standard, + ISO/IEC 8859-1 (one hyphen) is supposed to be used, but + reality is not always so (and in the 2000 version of the + standard, it was JIS8/SJIS that was the default). It's got an invalid range that is used often with SJIS and UTF-8, though, which makes detection easier. However, iconv() does not properly reject characters in @@ -290,23 +321,16 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, outleft=sa_ctext-sa_ntext; } } - /*We were actually given a character set; use it.*/ + /*We were actually given a character set; use it. + The spec says that in this case, data should be treated as if it + came from the given character set even when encoded in kanji + mode.*/ else{ err=eci_cd==(iconv_t)-1|| iconv(eci_cd,&in,&inleft,&out,&outleft)==(size_t)-1; if(!err)sa_ntext=out-sa_text; } }break; - /*Kanji mode always uses SJIS.*/ - case QR_MODE_KANJI:{ - in=(char *)entry->payload.data.buf; - inleft=entry->payload.data.len; - out=sa_text+sa_ntext; - outleft=sa_ctext-sa_ntext; - err=sjis_cd==(iconv_t)-1|| - iconv(sjis_cd,&in,&inleft,&out,&outleft)==(size_t)-1; - if(!err)sa_ntext=out-sa_text; - }break; /*Check to see if a character set was specified.*/ case QR_MODE_ECI:{ const char *enc; @@ -323,6 +347,7 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, else enc="CP437"; } else if(cur_eci==QR_ECI_SJIS)enc="SJIS"; + else if(cur_eci==QR_ECI_UTF8)enc="UTF-8"; /*Don't know what this ECI code specifies, but not an encoding that we recognize.*/ else continue; @@ -389,6 +414,7 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, sa_sym->data = sa_text; sa_sym->data_alloc = sa_ntext; sa_sym->datalen = sa_ntext - 1; + sa_sym->modifiers = fnc1; _zbar_image_scanner_add_sym(iscn, sa_sym); } diff --git a/zbar/qrcode/util.h b/zbar/qrcode/util.h index cb89d96..94a74a3 100644 --- a/zbar/qrcode/util.h +++ b/zbar/qrcode/util.h @@ -17,6 +17,14 @@ #define QR_DIVROUND(_x,_y) (((_x)+QR_FLIPSIGNI(_y>>1,_x))/(_y)) #define QR_CLAMPI(_a,_b,_c) (QR_MAXI(_a,QR_MINI(_b,_c))) #define QR_CLAMP255(_x) ((unsigned char)((((_x)<0)-1)&((_x)|-((_x)>255)))) +#define QR_SWAP2I(_a,_b) \ + do{ \ + int t__; \ + t__=(_a); \ + (_a)=(_b); \ + (_b)=t__; \ + } \ + while(0) /*Swaps two integers _a and _b if _a>_b.*/ #define QR_SORT2I(_a,_b) \ do{ \ From c391064b193d5f389fb250b1bc9da148cbd4e501 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 30 Jun 2011 11:15:20 -0700 Subject: [PATCH 298/328] iPhone: add emulation for UI videoQuality to adjust camera resolution --- iphone/ChangeLog | 1 + iphone/ZBarReaderViewController.m | 48 ++++++++++++++++++- iphone/ZBarReaderViewImpl_Simulator.m | 5 ++ iphone/doc/ZBarReaderViewController.rst | 8 +++- iphone/examples/readertest/readertest.m | 20 ++++++++ .../ZBarSDK/ZBarReaderViewController.h | 2 + 6 files changed, 82 insertions(+), 2 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 96c4435..e613f6a 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,5 @@ version 1.1.2: + * 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 diff --git a/iphone/ZBarReaderViewController.m b/iphone/ZBarReaderViewController.m index 0aced30..aa9bbe9 100644 --- a/iphone/ZBarReaderViewController.m +++ b/iphone/ZBarReaderViewController.m @@ -87,12 +87,32 @@ 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); + } +#endif + return(nil); +} + @implementation ZBarReaderViewController @synthesize scanner, readerDelegate, showsZBarControls, supportedOrientationsMask, tracksSymbols, enableCache, cameraOverlayView, - cameraViewTransform, cameraDevice, cameraFlashMode, readerView, scanCrop; + cameraViewTransform, cameraDevice, cameraFlashMode, videoQuality, + readerView, scanCrop; @dynamic sourceType, allowsEditing, allowsImageEditing, showsCameraControls, showsHelpOnFail, cameraMode, takesPicture, maxScanDimension; @@ -136,6 +156,7 @@ - (void) _init cameraViewTransform = CGAffineTransformIdentity; cameraFlashMode = UIImagePickerControllerCameraFlashModeAuto; + videoQuality = UIImagePickerControllerQualityType640x480; AVCaptureDevice *device = nil; #if !TARGET_IPHONE_SIMULATOR device = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo]; @@ -272,6 +293,23 @@ - (void) initControls [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] @@ -307,6 +345,7 @@ - (void) viewDidLoad if(device && device != readerView.device) readerView.device = device; readerView.torchMode = AVTorchModeForUIFlashMode(cameraFlashMode); + [self initVideoQuality]; readerView.readerDelegate = (id)self; readerView.scanCrop = scanCrop; @@ -542,6 +581,13 @@ - (void) setCameraCaptureMode: (UIImagePickerControllerCameraCaptureMode) mode @" for %@ property", mode, @"cameraCaptureMode"); } +- (void) setVideoQuality: (UIImagePickerControllerQualityType) quality +{ + videoQuality = quality; + if(readerView) + [self initVideoQuality]; +} + // ZBarHelpDelegate diff --git a/iphone/ZBarReaderViewImpl_Simulator.m b/iphone/ZBarReaderViewImpl_Simulator.m index 238efff..2e9c1f8 100644 --- a/iphone/ZBarReaderViewImpl_Simulator.m +++ b/iphone/ZBarReaderViewImpl_Simulator.m @@ -105,6 +105,11 @@ - (void) setDevice: (AVCaptureDevice*) device // simulated camera does nothing with this } +- (AVCaptureSession*) session +{ + return(nil); +} + - (void) updateCrop { previewImage.frame = preview.bounds; diff --git a/iphone/doc/ZBarReaderViewController.rst b/iphone/doc/ZBarReaderViewController.rst index bd9bb1f..6eee7d3 100644 --- a/iphone/doc/ZBarReaderViewController.rst +++ b/iphone/doc/ZBarReaderViewController.rst @@ -55,13 +55,19 @@ Properties .. member:: UIImagePickerControllerCameraDevice cameraDevice - The camera device to use for scanning. + 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 diff --git a/iphone/examples/readertest/readertest.m b/iphone/examples/readertest/readertest.m index cf18421..d0c87ff 100644 --- a/iphone/examples/readertest/readertest.m +++ b/iphone/examples/readertest/readertest.m @@ -4,6 +4,7 @@ CAMODE_SECTION, DEVICE_SECTION, FLASH_SECTION, + QUALITY_SECTION, CONFIG_SECTION, CUSTOM_SECTION, SYMBOL_SECTION, @@ -17,6 +18,7 @@ @"CameraMode", @"CaptureDevice", @"CameraFlashMode", + @"VideoQuality", @"Reader Configuration", nil, @"Enabled Symbologies", @@ -358,6 +360,18 @@ - (void) initControlCells [sections replaceObjectAtIndex: FLASH_SECTION withObject: flashModes]; + static NSString *const qualityNames[] = { + @"High", @"Medium", @"Low", @"640x480", nil + }; + NSMutableArray *qualities = [NSMutableArray array]; + for(int i = 0; qualityNames[i]; i++) + [qualities addObject: + [self cellWithTitle: qualityNames[i] + tag: i + checked: (reader.videoQuality == i)]]; + [sections replaceObjectAtIndex: QUALITY_SECTION + withObject: qualities]; + static NSString* const configNames[] = { @"showsCameraControls", @"showsZBarControls", @"tracksSymbols", @"enableCache", @"showsHelpOnFail", @"takesPicture", @@ -775,6 +789,12 @@ - (void) tableView: (UITableView*) view inSection: FLASH_SECTION]; break; + case QUALITY_SECTION: + reader.videoQuality = cell.tag; + [self setCheckForTag: reader.videoQuality + inSection: QUALITY_SECTION]; + break; + case CONFIG_SECTION: { BOOL state; NSString *key = cell.textLabel.text; diff --git a/iphone/include/ZBarSDK/ZBarReaderViewController.h b/iphone/include/ZBarSDK/ZBarReaderViewController.h index cbf4d09..be2bf21 100644 --- a/iphone/include/ZBarSDK/ZBarReaderViewController.h +++ b/iphone/include/ZBarSDK/ZBarReaderViewController.h @@ -52,6 +52,7 @@ NSUInteger supportedOrientationsMask; UIImagePickerControllerCameraDevice cameraDevice; UIImagePickerControllerCameraFlashMode cameraFlashMode; + UIImagePickerControllerQualityType videoQuality; BOOL showsZBarControls, tracksSymbols, enableCache; ZBarHelpController *helpController; @@ -105,6 +106,7 @@ @property(nonatomic) UIImagePickerControllerCameraDevice cameraDevice; @property(nonatomic) UIImagePickerControllerCameraFlashMode cameraFlashMode; @property(nonatomic) UIImagePickerControllerCameraCaptureMode cameraCaptureMode; +@property(nonatomic) UIImagePickerControllerQualityType videoQuality; // direct access to the ZBarReaderView @property (nonatomic, readonly) ZBarReaderView *readerView; From 3e9e65a115e3ee8732a7799537af76edd5d7478b Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 30 Jun 2011 15:08:46 -0700 Subject: [PATCH 299/328] iPhone: add maxZoom for increasing zoom range - workaround camera preview initial location/size bug --- iphone/ChangeLog | 2 ++ iphone/ZBarReaderView.m | 43 ++++++++++++++++--------- iphone/ZBarReaderViewImpl_Capture.m | 8 +++-- iphone/doc/ZBarReaderView.rst | 7 +++- iphone/include/ZBarSDK/ZBarReaderView.h | 7 ++-- 5 files changed, 47 insertions(+), 20 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index e613f6a..43f53de 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,4 +1,6 @@ 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 diff --git a/iphone/ZBarReaderView.m b/iphone/ZBarReaderView.m index 40a484a..a5245a5 100644 --- a/iphone/ZBarReaderView.m +++ b/iphone/ZBarReaderView.m @@ -33,7 +33,7 @@ @interface ZBarReaderViewImpl : NSObject @implementation ZBarReaderView @synthesize readerDelegate, tracksSymbols, trackingColor, torchMode, showsFPS, - zoom, scanCrop, previewTransform, captureReader; + zoom, maxZoom, scanCrop, previewTransform, captureReader; @dynamic scanner, allowsPinchZoom, enableCache, device, session; + (id) alloc @@ -111,6 +111,7 @@ - (void) _initWithImageScanner: (ZBarImageScanner*) scanner scanCrop = effectiveCrop = CGRectMake(0, 0, 1, 1); imageScale = 1; previewTransform = CGAffineTransformIdentity; + maxZoom = 2; pinch = [[UIPinchGestureRecognizer alloc] initWithTarget: self @@ -232,19 +233,23 @@ static inline CGFloat rotationForInterfaceOrientation (int orient) - (void) layoutSubviews { + CGRect bounds = self.bounds; + if(!bounds.size.width || !bounds.size.height) + return; + + [CATransaction begin]; if(animationDuration) { - [CATransaction begin]; [CATransaction setAnimationDuration: animationDuration]; [CATransaction setAnimationTimingFunction: [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut]]; } + else + [CATransaction setDisableActions: YES]; + [super layoutSubviews]; - CGRect bounds = self.bounds; fpsView.frame = CGRectMake(bounds.size.width - 80, bounds.size.height - 32, 80 + 12, 32 + 12); - if(!bounds.size.width || !bounds.size.height) - return; // orient view bounds to match camera image CGSize psize; @@ -320,6 +325,7 @@ - (void) layoutSubviews 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, @@ -339,15 +345,18 @@ - (void) layoutSubviews [self resetTracking]; [self updateCrop]; - if(animationDuration) { - [CATransaction commit]; - animationDuration = 0; - } + [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]; } @@ -406,8 +415,8 @@ - (void) setZoom: (CGFloat) z { if(z < 1.0) z = 1.0; - if(z > 2.0) - z = 2.0; + if(z > maxZoom) + z = maxZoom; if(z == zoom) return; zoom = z; @@ -419,10 +428,14 @@ - (void) setZoom: (CGFloat) z animated: (BOOL) animated { [CATransaction begin]; - [CATransaction setAnimationDuration: .1]; - [CATransaction setAnimationTimingFunction: - [CAMediaTimingFunction functionWithName: - kCAMediaTimingFunctionLinear]]; + if(animated) { + [CATransaction setAnimationDuration: .1]; + [CATransaction setAnimationTimingFunction: + [CAMediaTimingFunction functionWithName: + kCAMediaTimingFunctionLinear]]; + } + else + [CATransaction setDisableActions: YES]; // FIXME animate from current value self.zoom = z; [self layoutIfNeeded]; diff --git a/iphone/ZBarReaderViewImpl_Capture.m b/iphone/ZBarReaderViewImpl_Capture.m index 71914fc..482c472 100644 --- a/iphone/ZBarReaderViewImpl_Capture.m +++ b/iphone/ZBarReaderViewImpl_Capture.m @@ -106,9 +106,13 @@ - (void) initSubviews [[AVCaptureVideoPreviewLayer layerWithSession: session] retain]; - videoPreview.videoGravity = AVLayerVideoGravityResizeAspectFill; preview = videoPreview; - preview.frame = self.bounds; + 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]; diff --git a/iphone/doc/ZBarReaderView.rst b/iphone/doc/ZBarReaderView.rst index de16173..d434215 100644 --- a/iphone/doc/ZBarReaderView.rst +++ b/iphone/doc/ZBarReaderView.rst @@ -51,7 +51,12 @@ Properties 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,2]. (default 1.25) + 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 diff --git a/iphone/include/ZBarSDK/ZBarReaderView.h b/iphone/include/ZBarSDK/ZBarReaderView.h index 270be19..bc75c9d 100644 --- a/iphone/include/ZBarSDK/ZBarReaderView.h +++ b/iphone/include/ZBarSDK/ZBarReaderView.h @@ -49,7 +49,7 @@ ZBarCaptureReader *captureReader; CGRect scanCrop, effectiveCrop; CGAffineTransform previewTransform; - CGFloat zoom, zoom0; + CGFloat zoom, zoom0, maxZoom; UIColor *trackingColor; BOOL tracksSymbols, showsFPS; NSInteger torchMode; @@ -106,12 +106,15 @@ @property (nonatomic) BOOL showsFPS; // zoom scale factor applied to video preview *and* scanCrop. -// also updated by pinch-zoom gesture. clipped to range [1,2], +// also updated by pinch-zoom gesture. clipped to range [1,maxZoom], // defaults to 1.25 @property (nonatomic) CGFloat zoom; - (void) setZoom: (CGFloat) zoom animated: (BOOL) animated; +// maximum settable zoom factor. +@property (nonatomic) CGFloat maxZoom; + // the region of the image that will be scanned. normalized coordinates. @property (nonatomic) CGRect scanCrop; From be3d45d1a0f95f4b6173ee34e677af904e1e24f8 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 30 Jun 2011 15:23:52 -0700 Subject: [PATCH 300/328] iPhone: release updates --- iphone/res/ZBarSDK-Info.plist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iphone/res/ZBarSDK-Info.plist b/iphone/res/ZBarSDK-Info.plist index bcfbde8..cabd2ab 100644 --- a/iphone/res/ZBarSDK-Info.plist +++ b/iphone/res/ZBarSDK-Info.plist @@ -7,7 +7,7 @@ CFBundleName ZBarSDK CFBundleVersion - 1.1.1 + 1.1.2 CFBundleSignature ???? NSHumanReadableCopyright From 4cb6647cea3d69dbebe3bf15e7f802111a066d66 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 30 Jun 2011 15:40:13 -0700 Subject: [PATCH 301/328] Added tag iPhoneSDK-1.1.2 for changeset 801318a61950 From af857f4ff6415e838ac3116e328fea8b64c606b9 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 28 Jul 2011 19:48:15 -0700 Subject: [PATCH 302/328] iPhone: fix UITabViewController rotation interaction --- iphone/ChangeLog | 3 +++ iphone/ZBarReaderView.m | 8 +++++--- iphone/ZBarReaderViewController.m | 5 ++++- iphone/examples/readertest/ZBarSDK | 2 +- iphone/res/ZBarSDK-Info.plist | 2 +- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 43f53de..0fe308c 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,3 +1,6 @@ +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 diff --git a/iphone/ZBarReaderView.m b/iphone/ZBarReaderView.m index a5245a5..cbb2256 100644 --- a/iphone/ZBarReaderView.m +++ b/iphone/ZBarReaderView.m @@ -363,9 +363,11 @@ - (void) setImageSize: (CGSize) size - (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) orient duration: (NSTimeInterval) duration { - zlog(@"orient=%d", orient); - interfaceOrientation = orient; - animationDuration = duration; + if(interfaceOrientation != orient) { + zlog(@"orient=%d #%g", orient, duration); + interfaceOrientation = orient; + animationDuration = duration; + } } - (void) setScanCrop: (CGRect) r diff --git a/iphone/ZBarReaderViewController.m b/iphone/ZBarReaderViewController.m index aa9bbe9..a3e9caa 100644 --- a/iphone/ZBarReaderViewController.m +++ b/iphone/ZBarReaderViewController.m @@ -379,10 +379,13 @@ - (void) viewDidUnload - (void) viewWillAppear: (BOOL) animated { - zlog(@"willAppear: anim=%d", animated); + zlog(@"willAppear: anim=%d orient=%d", + animated, self.interfaceOrientation); [self initControls]; [super viewWillAppear: animated]; + [readerView willRotateToInterfaceOrientation: self.interfaceOrientation + duration: 0]; [readerView start]; UIApplication *app = [UIApplication sharedApplication]; diff --git a/iphone/examples/readertest/ZBarSDK b/iphone/examples/readertest/ZBarSDK index b8e7666..7a373ea 120000 --- a/iphone/examples/readertest/ZBarSDK +++ b/iphone/examples/readertest/ZBarSDK @@ -1 +1 @@ -../../build/Release-iphoneos/ZBarSDK \ No newline at end of file +../../build/Debug-iphoneos/ZBarSDK \ No newline at end of file diff --git a/iphone/res/ZBarSDK-Info.plist b/iphone/res/ZBarSDK-Info.plist index cabd2ab..d3aa694 100644 --- a/iphone/res/ZBarSDK-Info.plist +++ b/iphone/res/ZBarSDK-Info.plist @@ -7,7 +7,7 @@ CFBundleName ZBarSDK CFBundleVersion - 1.1.2 + 1.1.3 CFBundleSignature ???? NSHumanReadableCopyright From 11b5dc0ab4953d7e3ed5621e9e83d078ed243aff Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 28 Jul 2011 20:16:50 -0700 Subject: [PATCH 303/328] Added tag iPhoneSDK-1.1.3 for changeset 4bbb4e2bdba8 From 7ae75028c312d48fc01b2b93c7b8ac2a4d5d36d9 Mon Sep 17 00:00:00 2001 From: spadix Date: Thu, 4 Aug 2011 11:38:17 -0700 Subject: [PATCH 304/328] mention xmlto in HACKING (patch #3297039) - thanks to jarekczek for the patch! --- ChangeLog | 2 ++ HACKING | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index fa23afe..34e24fd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * 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 diff --git a/HACKING b/HACKING index b7da6e1..5df4d9e 100644 --- a/HACKING +++ b/HACKING @@ -15,9 +15,10 @@ be fine): GNU libtool 2.2.6 GNU gettext 0.18.1.1 GNU pkg-config 0.25 -all above mentioned tools must be installed in the same prefix. -mixing prefixes (i.g. /usr/bin and /usr/local/bin) may lead to errors in -configuration stages + 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: From 8674cb467c6697283069570fc7cbfb8005bba0a5 Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 6 Aug 2011 21:08:20 -0700 Subject: [PATCH 305/328] add support for GraphicsMagick as ImageMagick alternative --- ChangeLog | 1 + configure.ac | 110 +++++++++++++++++++++++++++++++++----------- test/barcodetest.py | 7 ++- test/test_decode.c | 3 ++ zbarimg/zbarimg.c | 30 ++++++++---- 5 files changed, 114 insertions(+), 37 deletions(-) diff --git a/ChangeLog b/ChangeLog index 34e24fd..42ca28a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * 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 diff --git a/configure.ac b/configure.ac index 4407935..5300713 100644 --- a/configure.ac +++ b/configure.ac @@ -284,46 +284,100 @@ 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 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]) - -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"]) +* 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. +])]) -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], @@ -506,8 +560,10 @@ AS_IF([test "x$enable_video" != "xyes"], 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" diff --git a/test/barcodetest.py b/test/barcodetest.py index 47406f4..e271f06 100755 --- a/test/barcodetest.py +++ b/test/barcodetest.py @@ -66,7 +66,7 @@ def distdir_search(subdir, base, suffixes=('',)): import re makefile = open('Makefile') for line in makefile: - if re.match('^VPATH\s*=', line): + if re.match(r'^VPATH\s*=', line): vpath = line.split('=', 1)[1].strip() if vpath and vpath != rundir: search.append(vpath) @@ -352,7 +352,10 @@ def loadTestsFromURL(self, url=None, file=None): continue if src.tag == ET.QName(BC, 'source'): test = TestCase() - src.set('href', urljoin(url, href)) + # convert file URLs to filesystem paths + href = urljoin(url, href) + href = re.sub(r'^file://', '', href) + src.set('href', href) test.source = src suite.addTest(test) elif src.tag == ET.QName(TS, 'index'): diff --git a/test/test_decode.c b/test/test_decode.c index d783c71..f5fac17 100644 --- a/test/test_decode.c +++ b/test/test_decode.c @@ -1122,6 +1122,9 @@ int main (int argc, char **argv) decoder = zbar_decoder_create(); /* allow empty CODE39 symbologies */ zbar_decoder_set_config(decoder, ZBAR_CODE39, ZBAR_CFG_MIN_LEN, 0); + /* enable addons */ + zbar_decoder_set_config(decoder, ZBAR_EAN2, ZBAR_CFG_ENABLE, 1); + zbar_decoder_set_config(decoder, ZBAR_EAN5, ZBAR_CFG_ENABLE, 1); zbar_decoder_set_handler(decoder, symbol_handler); encode_junk(rnd_size + 1); diff --git a/zbarimg/zbarimg.c b/zbarimg/zbarimg.c index 4ffc3d4..0ddca1a 100644 --- a/zbarimg/zbarimg.c +++ b/zbarimg/zbarimg.c @@ -38,15 +38,29 @@ #include #include -#include + +#ifdef HAVE_GRAPHICSMAGICK +# include +#endif + +#ifdef HAVE_IMAGEMAGICK +# include + +/* ImageMagick frequently changes API names - just use the original + * (more stable?) names to match GraphicsMagick + */ +# define InitializeMagick(f) MagickWandGenesis() +# define DestroyMagick MagickWandTerminus +# define MagickSetImageIndex MagickSetIteratorIndex /* in 6.4.5.4 MagickGetImagePixels changed to MagickExportImagePixels. * (still not sure this check is quite right... * how does MagickGetAuthenticImagePixels fit in?) * ref http://bugs.gentoo.org/247292 */ -#if MagickLibVersion <= 0x645 -# define MagickExportImagePixels MagickGetImagePixels +# if MagickLibVersion > 0x645 +# define MagickGetImagePixels MagickExportImagePixels +# endif #endif static const char *note_usage = @@ -133,7 +147,7 @@ static int scan_image (const char *filename) if(exit_code == 3) return(-1); - if(!MagickSetIteratorIndex(images, seq) && dump_error(images)) + if(!MagickSetImageIndex(images, seq) && dump_error(images)) return(-1); zbar_image_t *zimage = zbar_image_create(); @@ -151,8 +165,8 @@ static int scan_image (const char *filename) unsigned char *blob = malloc(bloblen); zbar_image_set_data(zimage, blob, bloblen, zbar_image_free_data); - if(!MagickExportImagePixels(images, 0, 0, width, height, - "I", CharPixel, blob)) + if(!MagickGetImagePixels(images, 0, 0, width, height, + "I", CharPixel, blob)) return(-1); if(xmllvl == 1) { @@ -312,7 +326,7 @@ int main (int argc, const char *argv[]) return(usage(1, "ERROR: specify image file(s) to scan", NULL)); num_images = 0; - MagickWandGenesis(); + InitializeMagick("zbarimg"); processor = zbar_processor_create(0); assert(processor); @@ -425,6 +439,6 @@ int main (int argc, const char *argv[]) exit_code = 4; zbar_processor_destroy(processor); - MagickWandTerminus(); + DestroyMagick(); return(exit_code); } From d7a6b7907d3b477ebe32d040acdad9127fc1f4fe Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 8 Aug 2011 10:15:29 -0700 Subject: [PATCH 306/328] fix avoid compositing ISBN10 data --- ChangeLog | 1 + zbar/img_scanner.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 42ca28a..79c74c5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ current: + * fix avoid compositing ISBN10 data * add support for GraphicsMagick as ImageMagick alternative * mention xmlto in HACKING (patch #3297039) - thanks to jarekczek for the patch! diff --git a/zbar/img_scanner.c b/zbar/img_scanner.c index 7f2add1..c3a2811 100644 --- a/zbar/img_scanner.c +++ b/zbar/img_scanner.c @@ -835,7 +835,9 @@ int zbar_scan_image (zbar_image_scanner_t *iscn, _zbar_image_scanner_recycle_syms(iscn, sym); continue; } - else if(sym->type < ZBAR_COMPOSITE) { + else if(sym->type < ZBAR_COMPOSITE && + sym->type != ZBAR_ISBN10) + { if(sym->type > ZBAR_EAN5) nean++; else From 7ffee230316351a3d7415f0942ea550a5110d3ef Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 8 Aug 2011 13:25:23 -0700 Subject: [PATCH 307/328] iPhone: release updates --- iphone/ChangeLog | 3 +++ iphone/res/ZBarSDK-Info.plist | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 0fe308c..3be923d 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,3 +1,6 @@ +version 1.2: + * release updates + version 1.1.3: * fix UITabViewController rotation interaction diff --git a/iphone/res/ZBarSDK-Info.plist b/iphone/res/ZBarSDK-Info.plist index d3aa694..1f3fea5 100644 --- a/iphone/res/ZBarSDK-Info.plist +++ b/iphone/res/ZBarSDK-Info.plist @@ -7,7 +7,7 @@ CFBundleName ZBarSDK CFBundleVersion - 1.1.3 + 1.2 CFBundleSignature ???? NSHumanReadableCopyright From 00c74de3d00f972448447d962e6efaef30c4d254 Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 8 Aug 2011 13:27:03 -0700 Subject: [PATCH 308/328] Added tag iPhoneSDK-1.2 for changeset 1ad84c3c0325 From 39d8e1f49d7fee7db21d87dd7868d0215c022d89 Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 20 Aug 2011 19:22:34 -0700 Subject: [PATCH 309/328] iPhone: fix overlay resizing bug --- iphone/ChangeLog | 3 +++ iphone/ZBarReaderViewController.m | 2 +- iphone/examples/readertest/readertest.m | 4 ++-- iphone/res/ZBarSDK-Info.plist | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 3be923d..92d7f82 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,3 +1,6 @@ +version 1.2.1: + * fix overlay resizing bug + version 1.2: * release updates diff --git a/iphone/ZBarReaderViewController.m b/iphone/ZBarReaderViewController.m index a3e9caa..14c6814 100644 --- a/iphone/ZBarReaderViewController.m +++ b/iphone/ZBarReaderViewController.m @@ -208,6 +208,7 @@ - (id) initWithCoder: (NSCoder*) decoder - (void) cleanup { + [cameraOverlayView removeFromSuperview]; cameraSim.readerView = nil; [cameraSim release]; cameraSim = nil; @@ -357,7 +358,6 @@ - (void) viewDidLoad if(cameraOverlayView) { assert(!cameraOverlayView.superview); [cameraOverlayView removeFromSuperview]; - cameraOverlayView.frame = readerView.frame; [view addSubview: cameraOverlayView]; } diff --git a/iphone/examples/readertest/readertest.m b/iphone/examples/readertest/readertest.m index d0c87ff..7140a42 100644 --- a/iphone/examples/readertest/readertest.m +++ b/iphone/examples/readertest/readertest.m @@ -572,6 +572,8 @@ - (void) scan typeOvl.text = nil; dataOvl.text = nil; [self.tableView reloadData]; + if(reader.sourceType == UIImagePickerControllerSourceTypeCamera) + reader.cameraOverlayView = (reader.showsZBarControls) ? nil : overlay; if([reader respondsToSelector: @selector(readerView)]) { reader.readerView.showsFPS = YES; if(zoom) @@ -580,8 +582,6 @@ - (void) scan ? ZBarOrientationMaskAll : ZBarOrientationMask(UIInterfaceOrientationPortrait); // tmp disable } - if(reader.sourceType == UIImagePickerControllerSourceTypeCamera) - reader.cameraOverlayView = (reader.showsZBarControls) ? nil : overlay; manualBtn.enabled = TARGET_IPHONE_SIMULATOR || (reader.cameraMode == ZBarReaderControllerCameraModeDefault) || [reader isKindOfClass: [ZBarReaderViewController class]]; diff --git a/iphone/res/ZBarSDK-Info.plist b/iphone/res/ZBarSDK-Info.plist index 1f3fea5..d223eb0 100644 --- a/iphone/res/ZBarSDK-Info.plist +++ b/iphone/res/ZBarSDK-Info.plist @@ -7,7 +7,7 @@ CFBundleName ZBarSDK CFBundleVersion - 1.2 + 1.2.1 CFBundleSignature ???? NSHumanReadableCopyright From 98fe10d620d9c2f3407a0bd4382e714eb0d42276 Mon Sep 17 00:00:00 2001 From: spadix Date: Sat, 20 Aug 2011 19:59:51 -0700 Subject: [PATCH 310/328] Added tag iPhoneSDK-1.2.1 for changeset 9e7bad13ae6a From 93560e82ea6bbaf239b808481f1f818ca39a0ee8 Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 22 Aug 2011 16:10:39 -0700 Subject: [PATCH 311/328] iPhone: reduce controller present and dismiss latency - add simple shutter to mask video start --- iphone/ChangeLog | 4 ++ iphone/ZBarReaderViewController.m | 41 +++++++++++++++++-- iphone/ZBarReaderViewImpl_Capture.m | 20 +++++++-- iphone/ZBarReaderViewImpl_Simulator.m | 24 +++++++++++ iphone/include/ZBarSDK/ZBarReaderView.h | 5 +++ .../ZBarSDK/ZBarReaderViewController.h | 2 +- iphone/res/ZBarSDK-Info.plist | 2 +- 7 files changed, 90 insertions(+), 8 deletions(-) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 92d7f82..6ba59ab 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,3 +1,7 @@ +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 diff --git a/iphone/ZBarReaderViewController.m b/iphone/ZBarReaderViewController.m index 14c6814..9ce889a 100644 --- a/iphone/ZBarReaderViewController.m +++ b/iphone/ZBarReaderViewController.m @@ -217,6 +217,8 @@ - (void) cleanup readerView = nil; [controls release]; controls = nil; + [shutter release]; + shutter = nil; } - (void) dealloc @@ -355,6 +357,15 @@ - (void) viewDidLoad 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]; @@ -386,7 +397,11 @@ - (void) viewWillAppear: (BOOL) animated [readerView willRotateToInterfaceOrientation: self.interfaceOrientation duration: 0]; - [readerView start]; + [readerView performSelector: @selector(start) + withObject: nil + afterDelay: .001]; + shutter.alpha = 1; + shutter.hidden = NO; UIApplication *app = [UIApplication sharedApplication]; BOOL willHideStatusBar = @@ -410,7 +425,7 @@ - (void) dismissModalViewControllerAnimated: (BOOL) animated - (void) viewWillDisappear: (BOOL) animated { - [readerView stop]; + readerView.captureReader.enableReader = NO; if(didHideStatusBar) { [[UIApplication sharedApplication] @@ -422,6 +437,13 @@ - (void) viewWillDisappear: (BOOL) animated [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); @@ -620,7 +642,7 @@ - (void) removeHelp: (NSString*) tag // ZBarReaderViewDelegate -- (void) readerView: (ZBarReaderView*) view +- (void) readerView: (ZBarReaderView*) readerView didReadSymbols: (ZBarSymbolSet*) syms fromImage: (UIImage*) image { @@ -633,6 +655,19 @@ - (void) readerView: (ZBarReaderView*) view 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) \ diff --git a/iphone/ZBarReaderViewImpl_Capture.m b/iphone/ZBarReaderViewImpl_Capture.m index 482c472..9b81a3f 100644 --- a/iphone/ZBarReaderViewImpl_Capture.m +++ b/iphone/ZBarReaderViewImpl_Capture.m @@ -267,6 +267,9 @@ - (void) onVideoStart: (NSNotification*) note } else zlog(@"failed to lock device: %@", error); + + if([readerDelegate respondsToSelector: @selector(readerViewDidStart:)]) + [readerDelegate readerViewDidStart: self]; } - (void) onVideoStop: (NSNotification*) note @@ -277,6 +280,11 @@ - (void) onVideoStop: (NSNotification*) note [device unlockForConfiguration]; running = NO; + + if([readerDelegate respondsToSelector: + @selector(readerView:didStopWithError:)]) + [readerDelegate readerView: self + didStopWithError: nil]; } - (void) onVideoError: (NSNotification*) note @@ -289,9 +297,15 @@ - (void) onVideoError: (NSNotification*) note } NSError *err = [note.userInfo objectForKey: AVCaptureSessionErrorKey]; - NSLog(@"ZBarReaderView: ERROR during capture: %@: %@", - [err localizedDescription], - [err localizedFailureReason]); + + if([readerDelegate respondsToSelector: + @selector(readerView:didStopWithError:)]) + [readerDelegate readerView: self + didStopWithError: err]; + else + NSLog(@"ZBarReaderView: ERROR during capture: %@: %@", + [err localizedDescription], + [err localizedFailureReason]); } // NSKeyValueObserving diff --git a/iphone/ZBarReaderViewImpl_Simulator.m b/iphone/ZBarReaderViewImpl_Simulator.m index 2e9c1f8..328a59e 100644 --- a/iphone/ZBarReaderViewImpl_Simulator.m +++ b/iphone/ZBarReaderViewImpl_Simulator.m @@ -125,6 +125,10 @@ - (void) start return; [super start]; running = YES; + + [self performSelector: @selector(onVideoStart) + withObject: nil + afterDelay: 0.5]; } - (void) stop @@ -133,6 +137,10 @@ - (void) stop return; [super stop]; running = NO; + + [self performSelector: @selector(onVideoStop) + withObject: nil + afterDelay: 0.5]; } - (void) scanImage: (UIImage*) image @@ -192,4 +200,20 @@ - (void) didReadSymbols: (ZBarSymbolSet*) syms 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 diff --git a/iphone/include/ZBarSDK/ZBarReaderView.h b/iphone/include/ZBarSDK/ZBarReaderView.h index bc75c9d..71aa685 100644 --- a/iphone/include/ZBarSDK/ZBarReaderView.h +++ b/iphone/include/ZBarSDK/ZBarReaderView.h @@ -36,6 +36,11 @@ didReadSymbols: (ZBarSymbolSet*) symbols fromImage: (UIImage*) image; +@optional +- (void) readerViewDidStart: (ZBarReaderView*) readerView; +- (void) readerView: (ZBarReaderView*) readerView + didStopWithError: (NSError*) error; + @end // read barcodes from the displayed video preview. the view maintains diff --git a/iphone/include/ZBarSDK/ZBarReaderViewController.h b/iphone/include/ZBarSDK/ZBarReaderViewController.h index be2bf21..20fb7e9 100644 --- a/iphone/include/ZBarSDK/ZBarReaderViewController.h +++ b/iphone/include/ZBarSDK/ZBarReaderViewController.h @@ -56,7 +56,7 @@ BOOL showsZBarControls, tracksSymbols, enableCache; ZBarHelpController *helpController; - UIView *controls; + UIView *controls, *shutter; BOOL didHideStatusBar, rotating; ZBarCameraSimulator *cameraSim; } diff --git a/iphone/res/ZBarSDK-Info.plist b/iphone/res/ZBarSDK-Info.plist index d223eb0..afbcb64 100644 --- a/iphone/res/ZBarSDK-Info.plist +++ b/iphone/res/ZBarSDK-Info.plist @@ -7,7 +7,7 @@ CFBundleName ZBarSDK CFBundleVersion - 1.2.1 + 1.2.2 CFBundleSignature ???? NSHumanReadableCopyright From cb7bb2978e4a63271d078338ee056573cb8a84f5 Mon Sep 17 00:00:00 2001 From: spadix Date: Tue, 23 Aug 2011 12:17:23 -0700 Subject: [PATCH 312/328] Added tag iPhoneSDK-1.2.2 for changeset 146b857ff41a From 051ebcb629929c8ebf2bec430b2459a6020c14d3 Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 18 Sep 2011 11:38:54 -0700 Subject: [PATCH 313/328] fix C++ wrapper bugs (bug #3396068) - thanks to anotheruser1 for reporting this! - add new C++ wrapper test --- ChangeLog | 3 + include/zbar/Image.h | 13 ++- include/zbar/Symbol.h | 17 +-- test/Makefile.am.inc | 9 +- test/test_cpp_img.cpp | 234 ++++++++++++++++++++++++++++++++++++++++++ test/test_images.c | 205 ++++++++++++++++++++++++++++-------- test/test_images.h | 15 +++ 7 files changed, 444 insertions(+), 52 deletions(-) create mode 100644 test/test_cpp_img.cpp diff --git a/ChangeLog b/ChangeLog index 79c74c5..2177cba 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,7 @@ current: + * 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) diff --git a/include/zbar/Image.h b/include/zbar/Image.h index 1a2af46..4205ecb 100644 --- a/include/zbar/Image.h +++ b/include/zbar/Image.h @@ -115,8 +115,8 @@ class Image { ~Image () { - set_data(NULL, 0); - zbar_image_set_userdata(_img, NULL); + if(zbar_image_get_userdata(_img) == this) + zbar_image_set_userdata(_img, NULL); zbar_image_ref(_img, -1); } @@ -255,6 +255,14 @@ class Image { throw FormatError(); } + /// image format conversion. + /// see zbar_image_convert() + 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 @@ -309,7 +317,6 @@ class Image { { // by default nothing is cleaned assert(img); - assert(zbar_image_get_userdata(img)); } private: diff --git a/include/zbar/Symbol.h b/include/zbar/Symbol.h index a094222..fa10ea1 100644 --- a/include/zbar/Symbol.h +++ b/include/zbar/Symbol.h @@ -151,7 +151,8 @@ class Symbol { : _sym(sym), _index(index) { - sym->ref(1); + if(sym) + sym->ref(1); if(!sym || (unsigned)_index >= zbar_symbol_get_loc_size(*_sym)) _index = -1; @@ -162,20 +163,24 @@ class Symbol { : _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) { - iter._sym->ref(); - _sym->ref(-1); + if(iter._sym) + iter._sym->ref(); + if(_sym) + _sym->ref(-1); _sym = iter._sym; _index = iter._index; return(*this); @@ -191,7 +196,7 @@ class Symbol { 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); } diff --git a/test/Makefile.am.inc b/test/Makefile.am.inc index a7672dc..776b0ec 100644 --- a/test/Makefile.am.inc +++ b/test/Makefile.am.inc @@ -28,6 +28,10 @@ check_PROGRAMS += test/test_cpp test_test_cpp_SOURCES = test/test_cpp.cpp test_test_cpp_LDADD = zbar/libzbar.la $(AM_LDADD) +check_PROGRAMS += test/test_cpp_img +test_test_cpp_img_SOURCES = test/test_cpp_img.cpp $(TEST_IMAGE_SOURCES) +test_test_cpp_img_LDADD = zbar/libzbar.la $(AM_LDADD) + if HAVE_JPEG check_PROGRAMS += test/test_jpeg test_test_jpeg_SOURCES = test/test_jpeg.c @@ -68,13 +72,16 @@ CLEANFILES += test/.libs/test_decode test/.libs/test_proc \ test/.libs/test_convert test/.libs/test_window \ test/.libs/test_video test/.libs/dbg_scan test/.libs/test_gtk +check-cpp: test/test_cpp_img + test/test_cpp_img + check-decoder: test/test_decode test/test_decode -q regress-decoder: test/test_decode test/test_decode -n 100000 -check-local: check-decoder check-images +check-local: check-cpp check-decoder check-images regress: regress-decoder regress-images .PHONY: check-decoder check-images regress-decoder regress-images regress diff --git a/test/test_cpp_img.cpp b/test/test_cpp_img.cpp new file mode 100644 index 0000000..0015065 --- /dev/null +++ b/test/test_cpp_img.cpp @@ -0,0 +1,234 @@ +//------------------------------------------------------------------------ +// Copyright 2007-2009 (c) Jeff Brown +// +// 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 +//------------------------------------------------------------------------ + +// NB do not put anything before this header +// it's here to check that we didn't omit any dependencies +#include + +#include +#include +#include +#include "test_images.h" + +bool debug = false; +bool verbose = false; +int errors = 0; +zbar::zbar_symbol_type_t expect_type = zbar::ZBAR_NONE; +std::string expect_data; + +template +inline std::string to_string (const T& t) +{ + std::stringstream ss; + ss << t; + return ss.str(); +} + +static inline int +error (const std::string &msg) +{ + errors++; + std::cerr << "ERROR: " << msg << std::endl; + if(debug) + abort(); + return(-1); +} + +static inline int +check_loc (const zbar::Image &img, + const zbar::Symbol &sym) +{ + int n = 0; + int w = img.get_width(); + int h = img.get_height(); + for(zbar::Symbol::PointIterator p(sym.point_begin()); + p != sym.point_end(); + ++p, n++) + { + zbar::Symbol::Point q(*p); + if(q.x < 0 || q.x >= w || + q.y < 0 || q.y >= h) + error("location point out of range"); + } + return(!n); +} + +static inline int +check_symbol (const zbar::Image &img, + const zbar::Symbol &sym) +{ + zbar::zbar_symbol_type_t type(sym.get_type()); + std::string data(sym.get_data()); + + bool pass = + expect_type && + type == expect_type && + data == expect_data && + sym.get_data_length() == expect_data.length(); + if(pass) + pass = !check_loc(img, sym); + + if(verbose || !pass) + std::cerr << "decode Symbol: " << sym << std::endl; + + if(!expect_type) + error("unexpected"); + else if(!pass) + error(std::string("expected: ") + + zbar::zbar_get_symbol_name(expect_type) + + " " + expect_data); + + expect_type = zbar::ZBAR_NONE; + expect_data = ""; + return(!pass); +} + +static inline int +check_image (const zbar::Image &img) +{ + zbar::SymbolSet syms(img.get_symbols()); + int setn = syms.get_size(), countn = 0; + + int rc = 0; + for(zbar::SymbolIterator sym(syms.symbol_begin()); + sym != syms.symbol_end(); + ++sym, ++countn) + rc |= check_symbol(img, *sym); + + if(countn != setn) + rc |= error("SymbolSet size mismatch: exp=" + to_string(setn) + + " act=" + to_string(countn)); + return(rc); +} + +static inline void +expect (zbar::zbar_symbol_type_t type, + std::string data) +{ + if(expect_type) + error(std::string("missing: ") + zbar_get_symbol_name(expect_type) + + " " + expect_data); + expect_type = type; + expect_data = data; +} + +class Handler : public zbar::Image::Handler { + void image_callback(zbar::Image &img); +}; + +void +Handler::image_callback (zbar::Image &img) +{ + bool unexpected = !expect_type; + if(unexpected) + error("unexpected image callback"); + check_image(img); +} + +static inline int +test_processor () +{ + // create processor w/no video and no window + zbar::Processor proc(debug, NULL); + Handler handler; + proc.set_handler(handler); + if(debug) { + proc.set_visible(); + proc.user_wait(); + } + + // generate barcode test image + zbar::Image rgb3(0, 0, "RGB3"); + + // test cast to C image + if(test_image_ean13(rgb3)) + error("failed to generate image"); + + // test decode + expect(zbar::ZBAR_EAN13, test_image_ean13_data); + proc.process_image(rgb3); + if(debug) + proc.user_wait(); + + expect(zbar::ZBAR_EAN13, test_image_ean13_data); + check_image(rgb3); + + if(rgb3.get_format() != zbar_fourcc('R','G','B','3')) + error("image format mismatch"); + + expect(zbar::ZBAR_NONE, ""); + proc.set_config(zbar::ZBAR_EAN13, + zbar::ZBAR_CFG_ENABLE, + false); + proc.process_image(rgb3); + check_image(rgb3); + if(debug) + proc.user_wait(); + + proc.set_config("ean13.en"); + expect(zbar::ZBAR_EAN13, test_image_ean13_data); + proc << rgb3; + expect(zbar::ZBAR_EAN13, test_image_ean13_data); + check_image(rgb3); + if(debug) + proc.user_wait(); + + { + zbar::Image grey(rgb3.convert(zbar_fourcc('G','R','E','Y'))); + expect(zbar::ZBAR_EAN13, test_image_ean13_data); + proc << grey; + + zbar::Image y800 = grey.convert("Y800"); + expect(zbar::ZBAR_EAN13, test_image_ean13_data); + proc << y800; + } + if(debug) + // check image data retention + proc.user_wait(); + + expect(zbar::ZBAR_NONE, ""); + return(0); +} + +int main (int argc, char **argv) +{ + debug = (argc > 1 && std::string(argv[1]) == "-d"); + verbose = (debug || (argc > 1 && std::string(argv[1]) == "-v")); + + if(test_processor()) { + error("ERROR: Processor test FAILED"); + return(2); + } + + if(test_image_check_cleanup()) + error("cleanup failed"); + + if(errors) { + std::cout << "FAIL" << std::endl; + return(2); + } + else { + std::cout << "OK" << std::endl; + return(0); + } +} diff --git a/test/test_images.c b/test/test_images.c index eb20536..c752586 100644 --- a/test/test_images.c +++ b/test/test_images.c @@ -96,30 +96,74 @@ static const format_def_t formats[] = { { 0 } }; +static const char *encoded_widths = + "9 111 212241113121211311141132 11111 311213121312121332111132 111 9"; +const char *test_image_ean13_data = "6268964977804"; + static int allocated_images = 0; -int test_image_check_cleanup () +int +test_image_check_cleanup () { if(allocated_images) fprintf(stderr, "ERROR: %d image data buffers still allocated\n", allocated_images); - else - fprintf(stderr, "all image data buffers freed\n"); + /*else + fprintf(stderr, "all image data buffers freed\n");*/ return(allocated_images); } -static void test_cleanup_handler (zbar_image_t *img) +static void +test_cleanup_handler (zbar_image_t *img) { void *data = (void*)zbar_image_get_data(img); - fprintf(stderr, "cleanup image data @%p\n", data); + /*fprintf(stderr, "cleanup image data @%p\n", data);*/ free(data); allocated_images--; } +static inline const format_def_t* +lookup_format (zbar_image_t *img) +{ + uint32_t ifmt = zbar_image_get_format(img); + const format_def_t *fmt; + for(fmt = formats; fmt->format; fmt++) + if(fmt->format == ifmt) + break; + if(!fmt->format) { + fprintf(stderr, "ERROR: no %.4s (%08"PRIx32") format\n", + (char*)&ifmt, ifmt); + return(NULL); + } + return(fmt); +} + +static inline const format_def_t* +alloc_data (zbar_image_t *img) +{ + allocated_images++; + const format_def_t *fmt = lookup_format(img); + if(!fmt) + return(NULL); + + unsigned w = zbar_image_get_width(img); + unsigned h = zbar_image_get_height(img); + unsigned long planelen = w * h; + unsigned long datalen = planelen * fmt->bpp / 8; + uint8_t *data = malloc(datalen); + + zbar_image_set_data(img, data, datalen, test_cleanup_handler); + + /*fprintf(stderr, "create %.4s(%08"PRIx32") image data %lx bytes @%p\n", + (char*)&fmt->format, fmt->format, datalen, data);*/ + return(fmt); +} + /* write intensity plane */ -static inline uint8_t *fill_bars_y (uint8_t *p, - unsigned w, - unsigned h) +static inline uint8_t* +fill_bars_y (uint8_t *p, + unsigned w, + unsigned h) { unsigned x, y, i; unsigned y0 = (h + 31) / 30; @@ -145,10 +189,11 @@ static inline uint8_t *fill_bars_y (uint8_t *p, } /* write Cb (U) or Cr (V) plane */ -static inline uint8_t *fill_bars_uv (uint8_t *p, - unsigned w, - unsigned h, - const uint8_t *C) +static inline uint8_t* +fill_bars_uv (uint8_t *p, + unsigned w, + unsigned h, + const uint8_t *C) { unsigned x, y, i; unsigned y0 = (h + 31) / 30; @@ -174,10 +219,11 @@ static inline uint8_t *fill_bars_uv (uint8_t *p, } /* write packed CbCr plane */ -static inline uint8_t *fill_bars_nv (uint8_t *p, - unsigned w, - unsigned h, - format_type_t order) +static inline uint8_t* +fill_bars_nv (uint8_t *p, + unsigned w, + unsigned h, + format_type_t order) { unsigned x, y, i; unsigned y0 = (h + 31) / 30; @@ -208,10 +254,11 @@ static inline uint8_t *fill_bars_nv (uint8_t *p, } /* write packed YCbCr plane */ -static inline uint8_t *fill_bars_yuv (uint8_t *p, - unsigned w, - unsigned h, - format_type_t order) +static inline uint8_t* +fill_bars_yuv (uint8_t *p, + unsigned w, + unsigned h, + format_type_t order) { unsigned x, y, i; unsigned y0 = (h + 31) / 30; @@ -253,11 +300,12 @@ static inline uint8_t *fill_bars_yuv (uint8_t *p, return((uint8_t*)q); } -static inline uint8_t *fill_bars_rgb (uint8_t *p, - unsigned w, - unsigned h, - format_type_t order, - int bpp) +static inline uint8_t* +fill_bars_rgb (uint8_t *p, + unsigned w, + unsigned h, + format_type_t order, + int bpp) { unsigned x, y, i; unsigned y0 = (h + 31) / 30; @@ -336,26 +384,17 @@ static inline uint8_t *fill_bars_rgb (uint8_t *p, return(((uint8_t*)q) + headlen); } -int test_image_bars (zbar_image_t *img) +int +test_image_bars (zbar_image_t *img) { - allocated_images++; - unsigned w = zbar_image_get_width(img); - unsigned h = zbar_image_get_height(img); - - const format_def_t *fmt; - for(fmt = formats; fmt->format; fmt++) - if(fmt->format == zbar_image_get_format(img)) - break; - if(!fmt->format) + const format_def_t *fmt = alloc_data(img); + if(!fmt) return(-1); - unsigned long planelen = w * h; - unsigned long datalen = planelen * fmt->bpp / 8; - uint8_t *data = malloc(datalen); - zbar_image_set_data(img, data, datalen, test_cleanup_handler); - fprintf(stderr, "create %.4s(%08" PRIx32 ") image data %lx bytes @%p\n", - (char*)&fmt->format, fmt->format, datalen, data); - + unsigned w = zbar_image_get_width(img); + unsigned h = zbar_image_get_height(img); + uint8_t *data = (void*)zbar_image_get_data(img); + assert(data); uint8_t *p = data; switch(fmt->type) { case GRAY: @@ -390,6 +429,88 @@ int test_image_bars (zbar_image_t *img) break; } + assert(p == data + zbar_image_get_data_length(img)); + return(0); +} + +int +test_image_ean13 (zbar_image_t *img) +{ + unsigned w = 114, h = 85; + zbar_image_set_size(img, w, h); + + const format_def_t *fmt = alloc_data(img); + if(!fmt) + return(-1); + + uint8_t *data = (void*)zbar_image_get_data(img); + unsigned int datalen = zbar_image_get_data_length(img); + assert(data && datalen); + + uint8_t *p = data; + /* FIXME randomize? */ + memset(data, 0x80, datalen); + + int nrep = 1, nskip = 0; + switch(fmt->type) + { + case YUVP: /* planar YUV */ + case YVUP: + case GRAY: + break; + + case UYVY: /* packed YUV */ + p++; + case YUYV: + case YVYU: + nskip = 1; + break; + + default: /* RGB */ + nrep = fmt->bpp / 8; + } + + int y = 0, x, i; + for(; y < 10 && y < h; y++) + for(x = 0; x < w; x++) { + for(i = 0; i < nrep; i++) + *p++ = 0xff; + p += nskip; + } + + for(; y < h - 10; y++) { + uint8_t color = 0xff; + const char *c; + for(x = 0, c = encoded_widths; *c; c++) { + int dx; + if(*c == ' ') + continue; + for(dx = *c - '0'; dx > 0; dx--) { + for(i = 0; i < nrep; i++) + *p++ = color; + p += nskip; + x++; + } + color = ~color; + } + assert(!color); + for(; x < w; x++) { + for(i = 0; i < nrep; i++) + *p++ = 0xff; + p += nskip; + } + assert(x == w); + } + + for(; y < h; y++) + for(x = 0; x < w; x++) { + for(i = 0; i < nrep; i++) + *p++ = 0xff; + p += nskip; + } + + if(fmt->type == UYVY) + p--; assert(p == data + datalen); return(0); } diff --git a/test/test_images.h b/test/test_images.h index 84e163b..1957757 100644 --- a/test/test_images.h +++ b/test/test_images.h @@ -25,7 +25,22 @@ #define fourcc zbar_fourcc +#ifdef __cplusplus + +extern "C" { + int test_image_check_cleanup(void); + int test_image_bars(zbar::zbar_image_t*); + int test_image_ean13(zbar::zbar_image_t*); +} + +#else + int test_image_check_cleanup(void); int test_image_bars(zbar_image_t*); +int test_image_ean13(zbar_image_t*); + +#endif + +extern const char *test_image_ean13_data; #endif From 6e9910afc0ee5badc3f1e7f51af1a9bbc6887130 Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 18 Sep 2011 11:52:51 -0700 Subject: [PATCH 314/328] fix C++ wrapper missing Symbol.quality (bug #3076524) - thanks to Rudy Melli for pointing this out! --- ChangeLog | 2 ++ include/zbar/Image.h | 1 + include/zbar/Symbol.h | 10 +++++++++- test/test_cpp_img.cpp | 3 ++- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2177cba..32772de 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * 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 diff --git a/include/zbar/Image.h b/include/zbar/Image.h index 4205ecb..713b1f9 100644 --- a/include/zbar/Image.h +++ b/include/zbar/Image.h @@ -257,6 +257,7 @@ class Image { /// 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()); diff --git a/include/zbar/Symbol.h b/include/zbar/Symbol.h index fa10ea1..d3061be 100644 --- a/include/zbar/Symbol.h +++ b/include/zbar/Symbol.h @@ -341,12 +341,20 @@ class Symbol { /// 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)); diff --git a/test/test_cpp_img.cpp b/test/test_cpp_img.cpp index 0015065..837ab42 100644 --- a/test/test_cpp_img.cpp +++ b/test/test_cpp_img.cpp @@ -84,7 +84,8 @@ check_symbol (const zbar::Image &img, expect_type && type == expect_type && data == expect_data && - sym.get_data_length() == expect_data.length(); + sym.get_data_length() == expect_data.length() && + sym.get_quality() > 4; if(pass) pass = !check_loc(img, sym); From 0accb61e3d5953d72be81cab85a3afa2dc96545f Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 18 Sep 2011 16:59:52 -0700 Subject: [PATCH 315/328] fix C example libpng usage - thanks to nickmeinhold for finding and reporting the fix! --- examples/scan_image.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/examples/scan_image.c b/examples/scan_image.c index 40009ba..c278bf3 100644 --- a/examples/scan_image.c +++ b/examples/scan_image.c @@ -3,6 +3,20 @@ #include #include +#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) From ed26d79be822ce51934df7e3148f20df2745c826 Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 18 Sep 2011 18:33:24 -0700 Subject: [PATCH 316/328] fix missing configure check for Python.h (bug #3092663) - thanks to Zoltan Kovacs for reporting this problem! --- ChangeLog | 2 ++ configure.ac | 11 ++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 32772de..7293926 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * 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) diff --git a/configure.ac b/configure.ac index 5300713..e8f1868 100644 --- a/configure.ac +++ b/configure.ac @@ -436,7 +436,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 compiles + +dnl check that #include 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]) From 79fcd53436929c6b331c9cc3049820fa884daf59 Mon Sep 17 00:00:00 2001 From: spadix Date: Sun, 18 Sep 2011 18:44:38 -0700 Subject: [PATCH 317/328] fix missing python thread initialization (bug #3349199) - thanks to jarekczek for reporting this problem! --- ChangeLog | 2 ++ python/processor.c | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 7293926..46b29bb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ current: + * 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) diff --git a/python/processor.c b/python/processor.c index 6af01f2..d77d4ae 100644 --- a/python/processor.c +++ b/python/processor.c @@ -42,7 +42,13 @@ processor_new (PyTypeObject *type, object_to_bool, &threaded)) return(NULL); -#ifndef WITH_THREAD +#ifdef WITH_THREAD + /* the processor creates a thread that calls back into python, + * so we must ensure that threads are initialized before attempting + * to manipulate the GIL (bug #3349199) + */ + PyEval_InitThreads(); +#else if(threaded > 0 && PyErr_WarnEx(NULL, "threading requested but not available", 1)) return(NULL); From c4ab2015e6bc3fc5cbf2709f7c2712710f296976 Mon Sep 17 00:00:00 2001 From: spadix Date: Mon, 19 Sep 2011 10:36:29 -0700 Subject: [PATCH 318/328] fix v4l config and build variations (bug #3348888) - thanks to jarekczek for reporting this! - NB v4l1 removed from kernel as of 2.6.38 --- ChangeLog | 3 ++ configure.ac | 36 +++++++++++++----------- test/Makefile.am.inc | 2 +- zbar/Makefile.am.inc | 9 ++++-- zbar/video/v4l.c | 67 ++++++++++++++++++++++++++++++++++++++++++++ zbar/video/v4l1.c | 32 ++------------------- 6 files changed, 99 insertions(+), 50 deletions(-) create mode 100644 zbar/video/v4l.c diff --git a/ChangeLog b/ChangeLog index 46b29bb..70fd282 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,7 @@ current: + * 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) diff --git a/configure.ac b/configure.ac index e8f1868..7c116a5 100644 --- a/configure.ac +++ b/configure.ac @@ -176,23 +176,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_HEADERS([linux/videodev.h], [with_video="v4l1"], - [AC_MSG_FAILURE([test for video support failed! +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.])]) - AC_CHECK_HEADERS([linux/videodev2.h], [with_video="v4l2"], - [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.])])]) -]) +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$with_video" = "xv4l1" || test "x$with_video" = "xv4l2"]) -AM_CONDITIONAL([HAVE_V4L2], [test "x$with_video" = "xv4l2"]) +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]) @@ -509,7 +512,8 @@ dnl header files dnl FIXME switches for shm, mmap AC_HEADER_ASSERT AC_CHECK_HEADERS([errno.h 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]) + 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 diff --git a/test/Makefile.am.inc b/test/Makefile.am.inc index 776b0ec..7340a7f 100644 --- a/test/Makefile.am.inc +++ b/test/Makefile.am.inc @@ -84,4 +84,4 @@ regress-decoder: test/test_decode check-local: check-cpp check-decoder check-images regress: regress-decoder regress-images -.PHONY: check-decoder check-images regress-decoder regress-images regress +.PHONY: check-cpp check-decoder check-images regress-decoder regress-images regress diff --git a/zbar/Makefile.am.inc b/zbar/Makefile.am.inc index 3d52077..83e63cc 100644 --- a/zbar/Makefile.am.inc +++ b/zbar/Makefile.am.inc @@ -59,11 +59,14 @@ else zbar_libzbar_la_SOURCES += zbar/processor/posix.h zbar/processor/posix.c endif -if HAVE_V4L1 -zbar_libzbar_la_SOURCES += zbar/video/v4l1.c if HAVE_V4L2 -zbar_libzbar_la_SOURCES += zbar/video/v4l2.c +zbar_libzbar_la_SOURCES += zbar/video/v4l.c zbar/video/v4l2.c endif +if HAVE_V4L1 +if !HAVE_V4L2 +zbar_libzbar_la_SOURCES += zbar/video/v4l.c +endif +zbar_libzbar_la_SOURCES += zbar/video/v4l1.c endif if WIN32 if HAVE_VIDEO diff --git a/zbar/video/v4l.c b/zbar/video/v4l.c new file mode 100644 index 0000000..4bbc10f --- /dev/null +++ b/zbar/video/v4l.c @@ -0,0 +1,67 @@ +/*------------------------------------------------------------------------ + * Copyright 2007-2011 (c) Jeff Brown + * + * 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 +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef HAVE_FCNTL_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif + +#include "video.h" + +extern int _zbar_v4l1_probe(zbar_video_t*); +extern int _zbar_v4l2_probe(zbar_video_t*); + +int _zbar_video_open (zbar_video_t *vdo, + const char *dev) +{ + vdo->fd = open(dev, O_RDWR); + if(vdo->fd < 0) + return(err_capture_str(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, + "opening video device '%s'", dev)); + zprintf(1, "opened camera device %s (fd=%d)\n", dev, vdo->fd); + + int rc = -1; +#ifdef HAVE_LINUX_VIDEODEV2_H + if(vdo->intf != VIDEO_V4L1) + rc = _zbar_v4l2_probe(vdo); +#endif +#ifdef HAVE_LINUX_VIDEODEV_H + if(rc && vdo->intf != VIDEO_V4L2) + rc = _zbar_v4l1_probe(vdo); +#endif + + if(rc && vdo->fd >= 0) { + close(vdo->fd); + vdo->fd = -1; + } + return(rc); +} diff --git a/zbar/video/v4l1.c b/zbar/video/v4l1.c index 89b1da2..da5d608 100644 --- a/zbar/video/v4l1.c +++ b/zbar/video/v4l1.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown + * Copyright 2007-2011 (c) Jeff Brown * * This file is part of the ZBar Bar Code Reader. * @@ -46,8 +46,6 @@ #include "video.h" #include "image.h" -extern int _zbar_v4l2_probe(zbar_video_t*); - typedef struct v4l1_format_s { uint32_t format; uint8_t bpp; @@ -371,7 +369,7 @@ static inline int v4l1_init_window (zbar_video_t *vdo) return(0); } -static int _zbar_v4l1_probe (zbar_video_t *vdo) +int _zbar_v4l1_probe (zbar_video_t *vdo) { /* check capabilities */ struct video_capability vcap; @@ -407,29 +405,3 @@ static int _zbar_v4l1_probe (zbar_video_t *vdo) vdo->dq = v4l1_dq; return(0); } - -int _zbar_video_open (zbar_video_t *vdo, - const char *dev) -{ - vdo->fd = open(dev, O_RDWR); - if(vdo->fd < 0) - return(err_capture_str(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, - "opening video device '%s'", dev)); - zprintf(1, "opened camera device %s (fd=%d)\n", dev, vdo->fd); - - int rc = -1; -#ifdef HAVE_LINUX_VIDEODEV2_H - if(vdo->intf != VIDEO_V4L1) - rc = _zbar_v4l2_probe(vdo); - if(rc) -#else - zprintf(1, "WARNING: not compiled with v4l2 support, trying v4l1\n"); -#endif - rc = _zbar_v4l1_probe(vdo); - - if(rc && vdo->fd >= 0) { - close(vdo->fd); - vdo->fd = -1; - } - return(rc); -} From 926d2634d7f062428b074159da6a8433eb18fa11 Mon Sep 17 00:00:00 2001 From: tterribe Date: Fri, 2 Dec 2011 02:04:40 -0800 Subject: [PATCH 319/328] Small comment fix in the QR decoder. --- zbar/qrcode/qrdectxt.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/zbar/qrcode/qrdectxt.c b/zbar/qrcode/qrdectxt.c index e54fa69..e4f1864 100644 --- a/zbar/qrcode/qrdectxt.c +++ b/zbar/qrcode/qrdectxt.c @@ -266,8 +266,9 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist, /*If there was data encoded in kanji mode, assume it's SJIS.*/ if(has_kanji)enc_list_mtf(enc_list,sjis_cd); /*Otherwise check for the UTF-8 BOM. - There's no way to specify UTF-8 using ECI, so this is the - only way for encoders to reliably indicate it.*/ + UTF-8 is rarely specified with ECI, and few decoders + currently support doing so, so this is the best way for + encoders to reliably indicate it.*/ else if(inleft>=3&& in[0]==(char)0xEF&&in[1]==(char)0xBB&&in[2]==(char)0xBF){ in+=3; From 8edfa5f8c4d11a5452c2f24730a8a729dea5cbe6 Mon Sep 17 00:00:00 2001 From: lisah0 Date: Wed, 22 Feb 2012 19:06:14 -0800 Subject: [PATCH 320/328] Fix EmbedReader example rotation interaction --- iphone/ChangeLog | 3 +++ .../EmbedReader/EmbedReader/EmbedReaderViewController.m | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/iphone/ChangeLog b/iphone/ChangeLog index 6ba59ab..90a7d7f 100644 --- a/iphone/ChangeLog +++ b/iphone/ChangeLog @@ -1,3 +1,6 @@ +current: + * Fix EmbedReader example rotation interaction + version 1.2.2: * reduce controller present and dismiss latency - add simple shutter to mask video start diff --git a/iphone/examples/EmbedReader/EmbedReader/EmbedReaderViewController.m b/iphone/examples/EmbedReader/EmbedReader/EmbedReaderViewController.m index 7a3a025..68a6934 100644 --- a/iphone/examples/EmbedReader/EmbedReader/EmbedReaderViewController.m +++ b/iphone/examples/EmbedReader/EmbedReader/EmbedReaderViewController.m @@ -63,6 +63,14 @@ - (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) orient duration: duration]; } +- (void) willAnimateRotationToInterfaceOrientation: (UIInterfaceOrientation) orient + duration: (NSTimeInterval) duration +{ + // perform rotation in animation loop so camera preview does not move + // wrt device orientation + [readerView setNeedsLayout]; +} + - (void) viewDidAppear: (BOOL) animated { // run the reader when the view is visible From 6ed227f4d59fb6e0f5be173997c46941e93a1e7d Mon Sep 17 00:00:00 2001 From: lisah0 Date: Sun, 11 Mar 2012 14:22:42 -0700 Subject: [PATCH 321/328] Android: Add initial support for Android platform --- .hgignore | 8 + android/AndroidManifest.xml | 15 ++ android/ChangeLog | 2 + android/README | 112 +++++++++ android/ant.properties | 17 ++ android/build-ndk.xml | 66 +++++ android/build.xml | 86 +++++++ .../examples/CameraTest/AndroidManifest.xml | 19 ++ android/examples/CameraTest/ant.properties | 17 ++ android/examples/CameraTest/build.xml | 85 +++++++ android/examples/CameraTest/proguard.cfg | 40 +++ .../examples/CameraTest/project.properties | 11 + .../examples/CameraTest/res/layout/main.xml | 28 +++ .../CameraTest/res/values/strings.xml | 4 + .../android/CameraTest/CameraPreview.java | 108 ++++++++ .../CameraTest/CameraTestActivity.java | 155 ++++++++++++ android/jni/Android.mk | 75 ++++++ android/jni/Application.mk | 1 + android/jni/config.h | 233 ++++++++++++++++++ android/proguard.cfg | 40 +++ android/project.properties | 12 + android/res/layout/main.xml | 13 + android/res/values/strings.xml | 4 + java/zbarjni.c | 4 +- 24 files changed, 1153 insertions(+), 2 deletions(-) create mode 100644 android/AndroidManifest.xml create mode 100644 android/ChangeLog create mode 100644 android/README create mode 100644 android/ant.properties create mode 100644 android/build-ndk.xml create mode 100644 android/build.xml create mode 100644 android/examples/CameraTest/AndroidManifest.xml create mode 100644 android/examples/CameraTest/ant.properties create mode 100644 android/examples/CameraTest/build.xml create mode 100644 android/examples/CameraTest/proguard.cfg create mode 100644 android/examples/CameraTest/project.properties create mode 100644 android/examples/CameraTest/res/layout/main.xml create mode 100644 android/examples/CameraTest/res/values/strings.xml create mode 100644 android/examples/CameraTest/src/net/sourceforge/zbar/android/CameraTest/CameraPreview.java create mode 100644 android/examples/CameraTest/src/net/sourceforge/zbar/android/CameraTest/CameraTestActivity.java create mode 100644 android/jni/Android.mk create mode 100644 android/jni/Application.mk create mode 100644 android/jni/config.h create mode 100644 android/proguard.cfg create mode 100644 android/project.properties create mode 100644 android/res/layout/main.xml create mode 100644 android/res/values/strings.xml diff --git a/.hgignore b/.hgignore index 1b450ef..f8b9026 100644 --- a/.hgignore +++ b/.hgignore @@ -26,3 +26,11 @@ build xcuserdata contents.xcworkspacedata .DS_Store +android/obj +*.class +*.dex +android/libs +android/examples/*/libs +android/*.zip +android/local.properties +android/examples/*/local.properties diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml new file mode 100644 index 0000000..a6d44d4 --- /dev/null +++ b/android/AndroidManifest.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/android/ChangeLog b/android/ChangeLog new file mode 100644 index 0000000..25ef5c5 --- /dev/null +++ b/android/ChangeLog @@ -0,0 +1,2 @@ +version 0.1: + * Add initial support for Android platform diff --git a/android/README b/android/README new file mode 100644 index 0000000..b8521de --- /dev/null +++ b/android/README @@ -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 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-.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 + cp -r ZBar-Android-SDK-/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-/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 /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 /android + 2) android update project --path . + 3) ant -Dndk.dir= -Diconv.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= zbar-clean + +See build-ndk.xml for additional target options. + + diff --git a/android/ant.properties b/android/ant.properties new file mode 100644 index 0000000..ee52d86 --- /dev/null +++ b/android/ant.properties @@ -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. + diff --git a/android/build-ndk.xml b/android/build-ndk.xml new file mode 100644 index 0000000..2328d0f --- /dev/null +++ b/android/build-ndk.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/build.xml b/android/build.xml new file mode 100644 index 0000000..e7b93ac --- /dev/null +++ b/android/build.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/examples/CameraTest/AndroidManifest.xml b/android/examples/CameraTest/AndroidManifest.xml new file mode 100644 index 0000000..1e99cbc --- /dev/null +++ b/android/examples/CameraTest/AndroidManifest.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + diff --git a/android/examples/CameraTest/ant.properties b/android/examples/CameraTest/ant.properties new file mode 100644 index 0000000..ee52d86 --- /dev/null +++ b/android/examples/CameraTest/ant.properties @@ -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. + diff --git a/android/examples/CameraTest/build.xml b/android/examples/CameraTest/build.xml new file mode 100644 index 0000000..df1f293 --- /dev/null +++ b/android/examples/CameraTest/build.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/examples/CameraTest/proguard.cfg b/android/examples/CameraTest/proguard.cfg new file mode 100644 index 0000000..b1cdf17 --- /dev/null +++ b/android/examples/CameraTest/proguard.cfg @@ -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 ; +} + +-keepclasseswithmembers class * { + public (android.content.Context, android.util.AttributeSet); +} + +-keepclasseswithmembers class * { + public (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 *; +} diff --git a/android/examples/CameraTest/project.properties b/android/examples/CameraTest/project.properties new file mode 100644 index 0000000..8da376a --- /dev/null +++ b/android/examples/CameraTest/project.properties @@ -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 diff --git a/android/examples/CameraTest/res/layout/main.xml b/android/examples/CameraTest/res/layout/main.xml new file mode 100644 index 0000000..f6164f1 --- /dev/null +++ b/android/examples/CameraTest/res/layout/main.xml @@ -0,0 +1,28 @@ + + + + + + + +