pax_global_header00006660000000000000000000000064132560730460014520gustar00rootroot0000000000000052 comment=2908291db4dce1d273f0a6a951ac8c074cb2fa6e dmtx-utils-0.7.6/000077500000000000000000000000001325607304600136445ustar00rootroot00000000000000dmtx-utils-0.7.6/AUTHORS000066400000000000000000000004051325607304600147130ustar00rootroot00000000000000Vadim Misbakh-Soloviov Mike Laughton Dan Watson Stefan Hafeneger Jonathan Lung Christian Hentschel Ryan Raasch Olivier Guilyardi Romain Goyet Pete Calvert Tom Vali Joseph Ferner Dikran Seropian Simon Wood Mackenzie Straight Marlon Jackson Alastair Turner Huver dmtx-utils-0.7.6/COPYING000066400000000000000000000355641325607304600147140ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 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. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, 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 or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's 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 give any other recipients of the Program a copy of this License along with the Program. 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 Program or any portion of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, 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 Program, 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 Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) 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; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, 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 executable. However, as a special exception, the source code 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. If distribution of executable or 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 counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program 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. 5. 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 Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program 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 to this License. 7. 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 Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program 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 Program. 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. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program 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. 9. The Free Software Foundation may publish revised and/or new versions of the 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 Program 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 Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, 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 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS dmtx-utils-0.7.6/COPYING.LESSER000066400000000000000000000576461325607304600157150ustar00rootroot00000000000000 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 dmtx-utils-0.7.6/ChangeLog000066400000000000000000000166461325607304600154330ustar00rootroot00000000000000Changes for dmtx-utils ----------------------------------------------------------------- Version 0.7.5 [February 2017] Some minor code fixes Compatibility fixes Compatibility with ImageMagick-7 Since now, look in git log (or github commit history) for further ChangeLog Version 0.7.4 [June 2011] dmtxwrite: Change default encoder to optimize best dmtxwrite: Fixed: Not waiting for EOF on standard input (Bug 2988977) version 0.7.2 [September 2009] Added initial macro decoding support (thanks Marlon!) Fast quad fill for dmtxDecodeMatrixRegion() (thanks Mackenzie!) Fixed capacity bug with rectangle requests New Vala wrapper (thanks Evan!) Wrapper integration in build system (thanks Evan!) Add libdmtx-X.X.X.zip as source package option Add libdmtx-win32-X.X.X.zip as binary package option Add "project" directory to EXTRA_DIST in Makefile.am version 0.7.0 [March 2009] New Java wrapper (thanks Pete and Dikran!) New .NET wrapper (thanks Vali and Joe!) Added solution and project files for MS Visual Studio 9.0 Reader support for FNC1 and upper shift (thanks Robin!) Support for byte-padded rows through dmtxImageSetProp() New no-copy image handling with configurable pixel packing Moved image scaling factors to DmtxDecode Moved scan cache from DmtxImage to DmtxDecode Eliminate types DmtxRgb, DmtxColor3, and DmtxGradient API updates for consistent naming and conventions Added dmtxEncodeSetProp() and dmtxEncodeGetProp() Option to print extended ASCII as UTF-8 (thanks Robin!) Fixed diagnostic image output Fixed misrepresented capacity in verbose mode True vector SVG output bypassing ImageMagick (thanks Richard!) Use ImageMagick to write images in major raster formats Fixed several bugs and compiler warnings version 0.6.0 [November 2008] dmtxread now scans all major image formats [Olivier] New encoding/decoding Ruby wrapper [Romain] Reduced memory footprint Will scan multiple barcodes per image Various platform-specific improvements Initial work preparing for custom pixel packing in future Begin static analysis cleanup with splint New --disable-dmtxread and --disable-dmtxwrite [Romain] Ability to specify max/min expected barcode sizes New edge neighbor tracking (Hough + 2 way edge cache) Info cache to track scan progress and avoid rescanning pixels Major reduction in floating point operations New informative return codes (found, not found, error) Read input from STDIN Diagnostic images display trail left by scanning logic Option to write output to STDOUT [Olivier] PHP wrapper now compiles with recent libdmtx Dedicated README.xxx instructions for specific platforms version 0.5.2 [September 2008] Move SetRangeLimit and SetScanRegion into library Replace DMTXUTIL_SUCCESS/ERROR with DMTX_SUCCESS/FAILURE Add edge threshold filtering Add encoding support for 144x144 barcodes Fixed encoding case when message starts with two digits Fixed bug in range limit option Add dynamic image shrinking (pixel skipping) Add step-by-step diagnostic image dump (debug build) Fixed bug in minimum scan gap setting Removed y-flip from internal pixel storage Added strict border tests to eliminate false positives Added squareness deviation filter Implement simplified Hough transform for locating first edge Several behind-the-scenes performance enhancements Python wrapper update; 15x faster (thanks Jonathan!) New PHP wrapper code added Various improvements when building for OS X and FreeBSD version 0.5.1 [July 2008] Fixed Extended ASCII encoding bug Fixed error correction bug related to multiple interleaved blocks Added timeout condition for region detection Allow partial and complete disabling of error correction Replaced DmtxPixel struct with DmtxRgb for safe pixel copies Tighter integration with libfec Conditional build logic for libtiff Added placeholder for new utility, dmtxquery Added unit test program for testing libdmtx internals Include local copies of getopt1.c, getopt.c, and getopt.h Various things to help compiling in MS VC++ Lots of holes filled in comments (Doxygen) Fixed experimental Data Mosaic decoding New Cocoa/iPhone wrapper (thanks Stefan!) version 0.5 [April 2008] Error correction using libfec (thanks Florian!) Rework encoding and decoding API for consistency and intuitiveness Handle region detection and region decoding as separate tasks Pass found regions back to calling app before attempting decode Image mask approach (for performance and multi-barcode scans) Fix TestForEndOfSymbolEdifact() to handle special cases correctly Roll scan pattern into core library (inward breadth-first cross) Replace dmtxScanLine() with dmtxScanPixel() Implement 4-direction weighted module decisions (eliminates thresholds) Add ability to scan portion of image Add --diagnose option that dumps image with embedded scan infomation Added Z rotation angle (in degrees) to verbose output Move ASCII and codeword output to separate --preview option Added -R option for setting image print resolution in dpi (PNG only) Remove gltest and simpletest from default build target Update Subversion to be keyword friendly ($Id$) Updated documentation to reflect API and option changes version 0.4 [December 2007] Remove arbitrary sz scaling (100.0) since it doesn't matter anyway Fix 4 bottom-right modules in sizes where they are not used (thanks Matthias R.!) Replace callback references with preprocessor macros Implement remaining encodation schemes for encoding (X12, Base 256, etc...) Implement remaining encodation schemes for decoding (X12, Base 256, etc...) Implement --auto-best option for best possible encoding efficiency Implement multi-region symbols Read and write rectangle barcodes Use GNU autotools (autoconf, automake, libtool) New region detection overhaul Include initial version of Python bindings from pydmtx project (thanks Dan!) Add decoding functionality through Python Add marathon images to project (thanks john@sportcam.net!) Fix dmtxread crash when same barcode is found more than 16 times Verbose messages describing traits of detected barcodes --codewords option to print codewords instead of decoded message --newline option to insert newline character at end of output Additional output formats (PNG, ASCII, codewords) 'make test' executes regression tests for encodation version 0.3 [October 2006] Several high-level changes: build process, naming consistency, file layout Added new automatic style checks in script directory ("make style") Implemented remaining encodation schemes for decode (X12, Base 256, etc...) Fixed instability/regressions that were introduced in v0.2 release Color sampling now averaged from multiple pixel locations Size calibration accuracy improved with new approach dmtxread: increased default scanline count, added multi-page TIFF format dmtxwrite: bug fixes, implemented -o option Improved documentation: deps listed in INSTALL, new man page for dmtxwrite version 0.2 [June 2006] Cleaned up program structure surrounding decoding process Improved API for real-world use (no longer just dumping results to STDOUT) Added "dmtxread" command line utility Added "dmtxwrite" command line utility Implemented Reed-Solomon error detection Created "simpletest.c" for full circle processing test Now using libpng(3) in library to read Data Matrix images Improved documentation (somewhat) version 0.1 [April 2006] Initial release dmtx-utils-0.7.6/KNOWNBUG000066400000000000000000000020271325607304600150220ustar00rootroot00000000000000Bugs in dmtx-utils ----------------------------------------------------------------- 1. dmtxread :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: The follow options are considered experimental: -M, --mosaic interpret as Data Mosaic barcodes 2. dmtxwrite :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: The follow options are considered experimental: -eb, --encodation=b best encodation (beta only) -M, --mosaic create Data Mosaic (non-standard) The follow options are not implemented yet: -ef, --encodation=f fast encodation -c, --color=COLOR barcode color -b, --bgcolor=COLOR background color -r, --rotate=DEGREES rotation angle 3. Scripts in the script directory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: The check_headers.pl script verifies that every function has a correctly-formed header comment. But the test condition is currently pretty simple, and does not test the first function appearing in each file. dmtx-utils-0.7.6/Makefile.am000066400000000000000000000014551325607304600157050ustar00rootroot00000000000000# Packaging commands (all run from dmtx-utils root): # $ make distclean # $ make dist-bzip2 # $ make dist-gzip ACLOCAL_AMFLAGS = -I m4 AM_CPPFLAGS = -Wshadow -Wall -pedantic -ansi if ENABLE_DMTXQUERY DMTXQUERY_DIR = dmtxquery endif if ENABLE_DMTXREAD DMTXREAD_DIR = dmtxread endif if ENABLE_DMTXWRITE DMTXWRITE_DIR = dmtxwrite endif SUBDIRS = . $(DMTXQUERY_DIR) $(DMTXREAD_DIR) $(DMTXWRITE_DIR) dist_man_MANS = man/dmtxread.1 man/dmtxwrite.1 man/dmtxquery.1 EXTRA_DIST = KNOWNBUG \ README.cygwin \ README.freebsd \ README.linux \ README.mingw \ README.osx \ README.unix \ m4 \ script/check_all.sh \ script/check_comments.sh \ script/check_copyright.sh \ script/check_headers.pl \ script/check_license.sh \ script/check_spacing.sh \ script/check_todo.sh \ script/check_whitespace.sh dmtx-utils-0.7.6/NEWS000066400000000000000000000000001325607304600143310ustar00rootroot00000000000000dmtx-utils-0.7.6/README000066400000000000000000000102701325607304600145240ustar00rootroot00000000000000================================================================= libdmtx - Open Source Data Matrix Software ================================================================= dmtx-utils README file (all platforms) This summary of the dmtx-utils package applies generally to all platforms. For instructions regarding your specific platform please also read the README.xxx file in this directory that matches your system (e.g., README.linux, README.cygwin, README.osx, etc...). 1. Introduction ----------------------------------------------------------------- libdmtx is a software library that enables programs to read and write Data Matrix barcodes of the modern ECC200 variety. This package, dmtx-utils, provides command line utilities that allow scripts and command line users to use libdmtx functionality. 2. Installation ----------------------------------------------------------------- In theory the following 3 steps will compile and install libdmtx on your system: $ ./configure $ make $ sudo make install However, you may need to install additional software for these steps to work properly. Details are provided below to handle error messages or if you want to customize beyond the defaults. Details on "configure" step ---------------------------------------- If you obtained libdmtx from Git you may have received an error like "./configure: No such file or directory". Run this command and try again: $ ./autogen.sh The autogen.sh command requires autoconf, automake, libtool, and pkgconfig to be installed on your system. Also, if you built and installed the libdmtx library from source it's like that configure gave you an error similar to this: configure: error: dmtxread/dmtxwrite requires libdmtx >= 0.7.0 You can fix this by telling configure where to find libdmtx.pc: $ ./configure PKG_CONFIG_PATH=/usr/local/lib/pkgconfig Note: This path may be different on your system. Details on "make" step ---------------------------------------- Errors encountered during the "make" step are often a result of missing software dependencies. Install any missing software and try again. Details on "sudo make install" step ---------------------------------------- If the 'sudo' command is not configured on your system then alternatively you can yell "Yeeehaww!" as you log in as root and run this instead: $ make install 3. Basic Usage ----------------------------------------------------------------- New users are encouraged to read the man pages for the library and command line utilities. However, here are a few simple cases to get you started: The dmtxwrite utility turns a message into a barcode image. The message is passed to dmtxwrite via file or standard input, and the output image is written to file or standard output. The following examples all produce an equivalent result: $ echo -n 123456 | dmtxwrite > image.png $ echo -n 123456 | dmtxwrite -o image.png $ echo -n 123456 > mesg.txt; dmtxwrite mesg.txt > image.png $ dmtxwrite <(echo -n 123456) -o image.png Conversely, the dmtxread utility turns barcode images back into messages. Images are passed to dmtxread via standard input or file, and the output is written to standard output. The following examples will produce an equivalent result: $ dmtxread -n image.png $ cat image.png | dmtxread -n Other typical cases: $ dmtxread -n -N1 image1.png image2.png image3.png $ dmtxread -n -N1 -m500 image.png You can even combine the utilities like this: $ echo 'Hello, world!' | dmtxwrite | dmtxread Hello, world! $ dmtxread image1.png | dmtxwrite -o image2.png Note: In this example the barcode in image2.png might appear different than the one in image1.png. Both barcodes will encode the same message, but the overall barcode shape and its internal bit pattern might be different. 4. Contact ----------------------------------------------------------------- Project website: http://www.libdmtx.org Documentation wiki: http://libdmtx.wikidot.com SourceForge.net page: http://www.sourceforge.net/projects/libdmtx OhLoh.net page: https://www.ohloh.net/projects/libdmtx Open mailing list: libdmtx-open_discussion@lists.sourceforge.net Professional support: www.dragonflylogic.com/products dmtx-utils-0.7.6/README.cygwin000066400000000000000000000022161325607304600160240ustar00rootroot00000000000000================================================================= libdmtx - Open Source Data Matrix Software ================================================================= dmtx-utils README file (Cygwin) This README.cygwin file contains information on installing and using libdmtx on Windows in a Cygwin environment. The general README file, also found in this directory, contains a high level summary of libdmtx and its components. 1. Installing dmtx-utils on Windows using Cygwin ----------------------------------------------------------------- dmtx-utils can be installed on Cygwin using the instructions provided in the general README file. However, please see below for additional details that might benefit users on this platform. 2. Dependencies ----------------------------------------------------------------- The following packages must be installed to compile libdmtx on Cygwin: * gcc * make * automake * pkg-config Also, if libdmtx was obtained from Subversion: * autoconf * libtool Also, if compiling dmtxread and/or dmtxwrite: * libSM-devel * libXt-devel * ImageMagick * libMagick-devel dmtx-utils-0.7.6/README.freebsd000066400000000000000000000020521325607304600161340ustar00rootroot00000000000000================================================================= libdmtx - Open Source Data Matrix Software ================================================================= dmtx-utils README file (FreeBSD) This README.freebsd file contains information on installing and using libdmtx on FreeBSD. The general README file, also found in this directory, contains a high level summary of libdmtx and its components. 1. Installing dmtx-utils on FreeBSD ----------------------------------------------------------------- dmtx-utils can be installed on FreeBSD using the instructions provided in the general README file. However, please read below for additional details that might benefit users on this platform. 2. Running configure ----------------------------------------------------------------- FreeBSD users may need to export the CPPFLAGS and LDFLAGS variables as follows before running configure: $ export CPPFLAGS=-I/usr/local/include $ export LDFLAGS=-L/usr/local/lib $ ./configure $ make $ sudo make install dmtx-utils-0.7.6/README.linux000066400000000000000000000021541325607304600156640ustar00rootroot00000000000000================================================================= libdmtx - Open Source Data Matrix Software ================================================================= dmtx-utils README file (GNU/Linux) This README.linux file contains information on installing and using libdmtx on GNU/Linux. The general README file, also found in this directory, contains a high level summary of libdmtx and its components. 1. Installing dmtx-utils on GNU/Linux ----------------------------------------------------------------- dmtx-utils can be installed on GNU/Linux using the instructions provided in the general README file. However, please see below for additional details that might benefit users on this platform. 2. Pre-Compiled Binaries ----------------------------------------------------------------- Many Linux distributions offer pre-compiled libdmtx binaries in their package repositories. This can be a real time saver if you aren't required to build from source for other reasons. Go to http://www.dragonflylogic.com/downloads for a list of all download options available on your system. dmtx-utils-0.7.6/README.mingw000066400000000000000000000031571325607304600156520ustar00rootroot00000000000000================================================================= libdmtx - Open Source Data Matrix Software ================================================================= dmtx-utils README file (MinGW) This README.mingw file contains information on installing and using libdmtx using MinGW. The general README file, also found in this directory, contains a high level summary of libdmtx and its components. 1. Installing dmtx-utils on Windows using MinGW and MSYS ----------------------------------------------------------------- dmtx-utils can be installed on MinGW using the instructions provided in the general README file. However, please see below for additional details that might benefit users on this platform. 2. Installing MinGW and MSYS ----------------------------------------------------------------- If you haven't done so already, first install MinGW, MSYS, and all recommended updates to your Windows system. Instructions for doing this are provided here: http://www.mingw.org/wiki/msys 3. External Dependencies ----------------------------------------------------------------- The dmtxread and dmtxwrite command line utilities require ImageMagick to be installed on your system. To satisfy this requirement you can download and install the current stable branch of ImageMagick from: https://sourceforge.net/projects/imagemagick/ After downloading, unpack the ImageMagick sources and run: $ ./configure $ make $ sudo make install Once ImageMagick is installed, change into the libdmtx directory and perform a full install: $ ./configure $ make $ sudo make install dmtx-utils-0.7.6/README.osx000066400000000000000000000041111325607304600153310ustar00rootroot00000000000000================================================================= libdmtx - Open Source Data Matrix Software ================================================================= dmtx-utils README file (Mac OS X) This README.osx file contains information on installing and using libdmtx on Mac OS X. The general README file, also found in this directory, contains a high level summary of libdmtx and its components. 1. Installing dmtx-utils on Mac OS X ----------------------------------------------------------------- dmtx-utils can be installed on OS X using the instructions provided in the general README file. However, please see below for additional details that might benefit users on this platform. 2. Universal Binaries ----------------------------------------------------------------- You can tweak configure's parameters to build an Universal Binary version of the library. Recommendations are provided at: http://developer.apple.com/technotes/tn2005/tn2137.html 3. Dependencies ----------------------------------------------------------------- Mac OS X does not have pkg-config installed by default. Even though I specified -L and -I options for ImageMagick the compiler losses this info at some point and looks to pkg-config to find it. Once pkg-config was installed it compiled perfectly. After installing pkg-config you do not need to re-install ImageMagick. The command line utilities dmtxread and dmtxwrite have a dependency on ImageMagick, which must be downloaded and built from its source distribution. After doing this, simply add the relevant "-L" and "-I" options to the CFLAGS and LDFLAGS environment variables before running the ./configure script. Compiling from Subversion requires a working autoconf/pkg-config setup: * autoconf, automake, libtool, and pkgconfig are required to generate the configure script. These packages are available from MacPorts. * You may run into issues if you mix the autotools packages in MacPorts with the ones installed from Xcode Tools. Make sure /opt/local/bin appears before /usr/bin in your $PATH. dmtx-utils-0.7.6/README.unix000066400000000000000000000021551325607304600155110ustar00rootroot00000000000000================================================================= libdmtx - Open Source Data Matrix Software ================================================================= dmtx-utils README file (Unix) This README.unix file contains information on installing and using libdmtx on Unix. The general README file, also found in this directory, contains a high level summary of libdmtx and its components. 1. Installing dmtx-utils on Unix ----------------------------------------------------------------- dmtx-utils can be installed on Unix using the instructions provided in the general README file. However, please see below for additional details that might benefit users on this platform. 2. Known Issues ----------------------------------------------------------------- dmtx-utils is known to work on the following commercial Unix versions: * AIX * HP-UX * Solaris However, building libdmtx from source on these operating systems can be tricky due to their non-GNU conventions. Users may wish to evaluate the trial binaries available at: http://www.dragonflylogic.com/downloads dmtx-utils-0.7.6/TODO000066400000000000000000000111651325607304600143400ustar00rootroot00000000000000TODO Items ----------------------------------------------------------------- version 1.0.0: (planned TBD) FOCUS: remaining gaps, testing, documentation version 0.9.0: (planned TBD) FOCUS: refactor encoding engine, FNC1, macros o dmtxread: Print character values (not just codewords) from --codewords (-c) option o dmtxread: Print out image representing "unstretched" barcode o dmtxread: Print color weights based on direction o dmtxread: Diagnostic image shows tighter-fitting outline o dmtxread: Change dmtxread to print out dump of both failed and successful barcodes if requested o dmtxread: Change dmtxread to print out mis-read modules somehow ... additive, subtractive? - Build color vector that describes jump from background to foreground color - When module is determined to be "off" then add half of color vector - When module is determined to be "on" then subtract half of color vector - resulting image should clearly show misread modules o dmtxwrite: Use MagickCommentImage() to tag images with messages o dmtxwrite: Print character values (not just codewords) from --format=c (-fc) option o dmtxwrite: Verbose messages describing encoding process version 0.8.0: (planned TBD) FOCUS: region detection refinement, multiple barcode scanning, structured append o dmtxread: Flatten deeply nested loops in main() o dmtxread: Add true scan timings that factor in linking, startup, image load o dmtxwrite: Add support for setting foreground and background colors o dmtxwrite: Consider adding "--strict" for single scheme requests (or make strict default?) o dmtxquery: Write XML for dmtxquery consumption o dmtxquery: Initial working version (parses XML) o project: Add missing getopt_long files o project: Version numbers should be maintained separate from library o project: Consider --disable-magick, while providing native PNM support to utils o project: Any way to ask Magick to filter out GS (and other) warnings? o project: Conditional use of local getopt.c version 0.7.4: (02-Jun-2011) x dmtxwrite: Change default encoder to optimize best x dmtxwrite: Fixed: Not waiting for EOF on standard input (Bug 2988977) version 0.7.2: (04-Sep-2009) version 0.7.0: (02-Mar-2009) x dmtxread: Option to print extended ASCII as UTF-8 (thanks Robin!) x dmtxread: Fix diagnostic image output x dmtxread: Fix misrepresented capacity in verbose mode x dmtxwrite: True vector SVG output bypassing ImageMagick (thanks Richard!) x dmtxwrite: Use Magick to write images of major image formats x dmtxwrite: Bad option should give short "invalid option -- N; --help for more" x dmtxwrite: Use HandleArgs() to capture requests, and process afterward x dmtxwrite: Switch to using new dmtxEncodeSetProp() approach version 0.6.0: (23-Nov-2008) x dmtxread: New informative return codes (found, not found, error) x dmtxread: Read input from STDIN x dmtxread: GraphicsMagick support for image reading [Olivier] x dmtxread: JPEG reading support [Ryan] x dmtxread: Diagnostic images display trail left by scanning logic x dmtxwrite: Option to write output to STDOUT [Olivier] version 0.5.2: (04-Sep-2008) version 0.5.1: (01-Jul-2008) x dmtxread: Conditional build logic for libtiff x dmtxquery: Start new utility to extra information from dmtxread output x project: Include local copies of getopt1.c getopt.c getopt.h version 0.5: (13-Apr-2008) x dmtxread: Add ability to scan portion of image x dmtxread: Add --diagnose option that dumps image with embedded scan infomation x dmtxread: Added Z rotation angle (in degrees) to verbose output x dmtxwrite: Move ASCII and codeword output to separate --preview option x dmtxwrite: Added -R option for setting image print resolution in dpi (PNG only) version 0.4: (07-Dec-2008) x dmtxread: Fix dmtxread crash when same barcode is found more than 16 times x dmtxread: Verbose messages describing traits of detected barcodes x dmtxread: --codewords option to print codewords instead of decoded message x dmtxread: --newline option to insert newline character at end of output x dmtxwrite: Additional output formats (PNG, ASCII, codewords) version 0.3: (15-Oct-2006) x Move PNG (and other format) logic and dependencies to dmtxread, dmtxwrite, etc... x Fix LoadPngImage() in dmtxread.c to return image count x Improved dmtxwrite (fixed bugs, implemented -o option) x Increase dmtxread default scanline count (feasible because of better stability) x Add man page for dmtxwrite version 0.2: (11-Jun-2006) x Add "dmtxread" command line utility x Add "dmtxwrite" command line utility dmtx-utils-0.7.6/autogen.sh000077500000000000000000000003271325607304600156470ustar00rootroot00000000000000#! /usr/bin/env sh # Create empty m4 directory if missing if [ ! -d "m4" ]; then echo "autogen.sh: creating empty m4 directory" mkdir m4 fi echo "autogen.sh: running autoreconf" autoreconf --force --install dmtx-utils-0.7.6/common/000077500000000000000000000000001325607304600151345ustar00rootroot00000000000000dmtx-utils-0.7.6/common/dmtxutil.c000066400000000000000000000050601325607304600171530ustar00rootroot00000000000000/* * libdmtx - Data Matrix Encoding/Decoding Library * * Copyright (C) 2011 Mike Laughton * * 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * Contact: mike@dragonflylogic.com */ #include #include #include #include #include #include #include #include #include "dmtxutil.h" #undef ISDIGIT #define ISDIGIT(n) (n > 47 && n < 58) extern char *programName; /** * @brief Display error message and exit with error status * @param errorCode error code returned to OS * @param fmt error message format for printing * @return void */ extern void FatalError(int errorCode, char *fmt, ...) { va_list va; va_start(va, fmt); fprintf(stderr, "%s: ", programName); vfprintf(stderr, fmt, va); va_end(va); fprintf(stderr, "\n\n"); fflush(stderr); exit(errorCode); } /** * @brief Convert character string to integer * @param numberInt pointer to converted integer * @param numberString string to be converted * @param terminate pointer to first invalid address * @return DmtxPass | DmtxFail */ extern DmtxPassFail StringToInt(int *numberInt, char *numberString, char **terminate) { long numberLong; if(!ISDIGIT(*numberString)) { *numberInt = DmtxUndefined; return DmtxFail; } errno = 0; numberLong = strtol(numberString, terminate, 10); while(isspace((int)**terminate)) (*terminate)++; if(errno != 0 || (**terminate != '\0' && **terminate != '%')) { *numberInt = DmtxUndefined; return DmtxFail; } *numberInt = (int)numberLong; return DmtxPass; } /** * @brief XXX * @param path * @return pointer to adjusted path string */ extern char * Basename(char *path) { assert(path); if(strrchr(path, '/')) path = strrchr(path, '/') + 1; if(strrchr(path, '\\')) path = strrchr(path, '\\') + 1; return path; } dmtx-utils-0.7.6/common/dmtxutil.h000066400000000000000000000033011325607304600171540ustar00rootroot00000000000000/* libdmtx - Data Matrix Encoding/Decoding Library Copyright (C) 2008, 2009 Mike Laughton 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 St, Fifth Floor, Boston, MA 02110-1301 USA Contact: mike@dragonflylogic.com */ #ifndef __DMTXUTIL_H__ #define __DMTXUTIL_H__ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #ifdef HAVE_SYSEXITS_H #include #else #define EX_OK 0 #define EX_USAGE 64 #define EX_DATAERR 65 #define EX_SOFTWARE 70 #define EX_OSERR 71 #define EX_CANTCREAT 73 #define EX_IOERR 74 #endif extern DmtxPassFail StringToInt(int *numberInt, char *numberString, char **terminate); extern void FatalError(int errorCode, char *fmt, ...); extern char *Basename(char *path); static char *symbolSizes[] = { "10x10", "12x12", "14x14", "16x16", "18x18", "20x20", "22x22", "24x24", "26x26", "32x32", "36x36", "40x40", "44x44", "48x48", "52x52", "64x64", "72x72", "80x80", "88x88", "96x96", "104x104", "120x120", "132x132", "144x144", "8x18", "8x32", "12x26", "12x36", "16x36", "16x48" }; #endif dmtx-utils-0.7.6/common/getopt.c000066400000000000000000001010221325607304600165760ustar00rootroot00000000000000/* Getopt for GNU. NOTE: getopt is now part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to drepper@gnu.org before changing it! Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C 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. The GNU C 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 the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ /* This tells Alpha OSF/1 not to define a getopt prototype in . Ditto for AIX 3.2 and . */ #ifndef _NO_PROTO # define _NO_PROTO #endif #ifdef HAVE_CONFIG_H # include #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 # include # if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION # define ELIDE_CODE # endif #endif #ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ # include # include #endif /* GNU C library. */ #include #ifdef VMS # include #endif #ifdef _LIBC # include #else # include "gettext.h" # define _(msgid) gettext (msgid) #endif #if defined _LIBC && defined USE_IN_LIBIO # include #endif #ifndef attribute_hidden # define attribute_hidden #endif /* This version of `getopt' appears to the caller like standard Unix `getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. Setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ #include "getopt.h" #include "getopt_int.h" /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* 1003.2 says this must be 1 before any call. */ int optind = 1; /* Callers store zero here to inhibit the error message for unrecognized options. */ int opterr = 1; /* Set to an option character which was unrecognized. This must be initialized on some systems to avoid linking in the system's own getopt implementation. */ int optopt = '?'; /* Keep a global copy of all internal members of getopt_data. */ static struct _getopt_data getopt_data; #ifndef __GNU_LIBRARY__ /* Avoid depending on library functions or files whose names are inconsistent. */ #ifndef getenv extern char *getenv (); #endif #endif /* not __GNU_LIBRARY__ */ #ifdef _LIBC /* Stored original parameters. XXX This is no good solution. We should rather copy the args so that we can compare them later. But we must not use malloc(3). */ extern int __libc_argc; extern char **__libc_argv; /* Bash 2.0 gives us an environment variable containing flags indicating ARGV elements that should not be considered arguments. */ # ifdef USE_NONOPTION_FLAGS /* Defined in getopt_init.c */ extern char *__getopt_nonoption_flags; # endif # ifdef USE_NONOPTION_FLAGS # define SWAP_FLAGS(ch1, ch2) \ if (d->__nonoption_flags_len > 0) \ { \ char __tmp = __getopt_nonoption_flags[ch1]; \ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ __getopt_nonoption_flags[ch2] = __tmp; \ } # else # define SWAP_FLAGS(ch1, ch2) # endif #else /* !_LIBC */ # define SWAP_FLAGS(ch1, ch2) #endif /* _LIBC */ /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. The other is elements [last_nonopt,optind), which contains all the options processed since those non-options were skipped. `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ static void exchange (char **argv, struct _getopt_data *d) { int bottom = d->__first_nonopt; int middle = d->__last_nonopt; int top = d->optind; char *tem; /* Exchange the shorter segment with the far end of the longer segment. That puts the shorter segment into the right place. It leaves the longer segment in the right place overall, but it consists of two parts that need to be swapped next. */ #if defined _LIBC && defined USE_NONOPTION_FLAGS /* First make sure the handling of the `__getopt_nonoption_flags' string can work normally. Our top argument must be in the range of the string. */ if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len) { /* We must extend the array. The user plays games with us and presents new arguments. */ char *new_str = malloc (top + 1); if (new_str == NULL) d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0; else { memset (__mempcpy (new_str, __getopt_nonoption_flags, d->__nonoption_flags_max_len), '\0', top + 1 - d->__nonoption_flags_max_len); d->__nonoption_flags_max_len = top + 1; __getopt_nonoption_flags = new_str; } } #endif while (top > middle && middle > bottom) { if (top - middle > middle - bottom) { /* Bottom segment is the short one. */ int len = middle - bottom; register int i; /* Swap it with the top part of the top segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[top - (middle - bottom) + i]; argv[top - (middle - bottom) + i] = tem; SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); } /* Exclude the moved bottom segment from further swapping. */ top -= len; } else { /* Top segment is the short one. */ int len = top - middle; register int i; /* Swap it with the bottom part of the bottom segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[middle + i]; argv[middle + i] = tem; SWAP_FLAGS (bottom + i, middle + i); } /* Exclude the moved top segment from further swapping. */ bottom += len; } } /* Update records for the slots the non-options now occupy. */ d->__first_nonopt += (d->optind - d->__last_nonopt); d->__last_nonopt = d->optind; } /* Initialize the internal data when the first call is made. */ static const char * _getopt_initialize (int argc, char *const *argv, const char *optstring, struct _getopt_data *d) { /* Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ d->__first_nonopt = d->__last_nonopt = d->optind; d->__nextchar = NULL; d->__posixly_correct = !!getenv ("POSIXLY_CORRECT"); /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { d->__ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { d->__ordering = REQUIRE_ORDER; ++optstring; } else if (d->__posixly_correct) d->__ordering = REQUIRE_ORDER; else d->__ordering = PERMUTE; #if defined _LIBC && defined USE_NONOPTION_FLAGS if (!d->__posixly_correct && argc == __libc_argc && argv == __libc_argv) { if (d->__nonoption_flags_max_len == 0) { if (__getopt_nonoption_flags == NULL || __getopt_nonoption_flags[0] == '\0') d->__nonoption_flags_max_len = -1; else { const char *orig_str = __getopt_nonoption_flags; int len = d->__nonoption_flags_max_len = strlen (orig_str); if (d->__nonoption_flags_max_len < argc) d->__nonoption_flags_max_len = argc; __getopt_nonoption_flags = (char *) malloc (d->__nonoption_flags_max_len); if (__getopt_nonoption_flags == NULL) d->__nonoption_flags_max_len = -1; else memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), '\0', d->__nonoption_flags_max_len - len); } } d->__nonoption_flags_len = d->__nonoption_flags_max_len; } else d->__nonoption_flags_len = 0; #endif return optstring; } /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element (aside from the initial '-') are option characters. If `getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. If `getopt' finds another option character, it returns that character, updating `optind' and `nextchar' so that the next call to `getopt' can resume the scan with the following option character or ARGV-element. If there are no more option characters, `getopt' returns -1. Then `optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, return '?' after printing an error message. If you set `opterr' to zero, the error message is suppressed but we still return '?'. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in `optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in `optarg', otherwise `optarg' is set to zero. If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated from the option name by a `=', or else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is zero. The elements of ARGV aren't really const, because we permute them. But we pretend they're const in the prototype to be compatible with other systems. LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a long-named option has been found by the most recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ int _getopt_internal_r (int argc, char *const *argv, const char *optstring, const struct option *longopts, int *longind, int long_only, struct _getopt_data *d) { int print_errors = d->opterr; if (optstring[0] == ':') print_errors = 0; if (argc < 1) return -1; d->optarg = NULL; if (d->optind == 0 || !d->__initialized) { if (d->optind == 0) d->optind = 1; /* Don't scan ARGV[0], the program name. */ optstring = _getopt_initialize (argc, argv, optstring, d); d->__initialized = 1; } /* Test whether ARGV[optind] points to a non-option argument. Either it does not have option syntax, or there is an environment flag from the shell indicating it is not an option. The later information is only used when the used in the GNU libc. */ #if defined _LIBC && defined USE_NONOPTION_FLAGS # define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \ || (d->optind < d->__nonoption_flags_len \ && __getopt_nonoption_flags[d->optind] == '1')) #else # define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0') #endif if (d->__nextchar == NULL || *d->__nextchar == '\0') { /* Advance to the next ARGV-element. */ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been moved back by the user (who may also have changed the arguments). */ if (d->__last_nonopt > d->optind) d->__last_nonopt = d->optind; if (d->__first_nonopt > d->optind) d->__first_nonopt = d->optind; if (d->__ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind) exchange ((char **) argv, d); else if (d->__last_nonopt != d->optind) d->__first_nonopt = d->optind; /* Skip any additional non-options and extend the range of non-options previously skipped. */ while (d->optind < argc && NONOPTION_P) d->optind++; d->__last_nonopt = d->optind; } /* The special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ if (d->optind != argc && !strcmp (argv[d->optind], "--")) { d->optind++; if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind) exchange ((char **) argv, d); else if (d->__first_nonopt == d->__last_nonopt) d->__first_nonopt = d->optind; d->__last_nonopt = argc; d->optind = argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ if (d->optind == argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ if (d->__first_nonopt != d->__last_nonopt) d->optind = d->__first_nonopt; return -1; } /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ if (NONOPTION_P) { if (d->__ordering == REQUIRE_ORDER) return -1; d->optarg = argv[d->optind++]; return 1; } /* We have found another option-ARGV-element. Skip the initial punctuation. */ d->__nextchar = (argv[d->optind] + 1 + (longopts != NULL && argv[d->optind][1] == '-')); } /* Decode the current option-ARGV-element. */ /* Check whether the ARGV-element is a long option. If long_only and the ARGV-element has the form "-f", where f is a valid short option, don't consider it an abbreviated form of a long option that starts with f. Otherwise there would be no way to give the -f short option. On the other hand, if there's a long option "fubar" and the ARGV-element is "-fu", do consider that an abbreviation of the long option, just like "--fu", and not "-f" with arg "u". This distinction seems to be the most useful approach. */ if (longopts != NULL && (argv[d->optind][1] == '-' || (long_only && (argv[d->optind][2] || !strchr (optstring, argv[d->optind][1]))))) { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = -1; int option_index; for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) { if ((unsigned int) (nameend - d->__nextchar) == (unsigned int) strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO char *buf; if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"), argv[0], argv[d->optind]) >= 0) { _IO_flockfile (stderr); int old_flags2 = ((_IO_FILE *) stderr)->_flags2; ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; __fxprintf (NULL, "%s", buf); ((_IO_FILE *) stderr)->_flags2 = old_flags2; _IO_funlockfile (stderr); free (buf); } #else fprintf (stderr, _("%s: option `%s' is ambiguous\n"), argv[0], argv[d->optind]); #endif } d->__nextchar += strlen (d->__nextchar); d->optind++; d->optopt = 0; return '?'; } if (pfound != NULL) { option_index = indfound; d->optind++; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) d->optarg = nameend + 1; else { if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO char *buf; int n; #endif if (argv[d->optind - 1][1] == '-') { /* --option */ #if defined _LIBC && defined USE_IN_LIBIO n = __asprintf (&buf, _("\ %s: option `--%s' doesn't allow an argument\n"), argv[0], pfound->name); #else fprintf (stderr, _("\ %s: option `--%s' doesn't allow an argument\n"), argv[0], pfound->name); #endif } else { /* +option or -option */ #if defined _LIBC && defined USE_IN_LIBIO n = __asprintf (&buf, _("\ %s: option `%c%s' doesn't allow an argument\n"), argv[0], argv[d->optind - 1][0], pfound->name); #else fprintf (stderr, _("\ %s: option `%c%s' doesn't allow an argument\n"), argv[0], argv[d->optind - 1][0], pfound->name); #endif } #if defined _LIBC && defined USE_IN_LIBIO if (n >= 0) { _IO_flockfile (stderr); int old_flags2 = ((_IO_FILE *) stderr)->_flags2; ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; __fxprintf (NULL, "%s", buf); ((_IO_FILE *) stderr)->_flags2 = old_flags2; _IO_funlockfile (stderr); free (buf); } #endif } d->__nextchar += strlen (d->__nextchar); d->optopt = pfound->val; return '?'; } } else if (pfound->has_arg == 1) { if (d->optind < argc) d->optarg = argv[d->optind++]; else { if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO char *buf; if (__asprintf (&buf, _("\ %s: option `%s' requires an argument\n"), argv[0], argv[d->optind - 1]) >= 0) { _IO_flockfile (stderr); int old_flags2 = ((_IO_FILE *) stderr)->_flags2; ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; __fxprintf (NULL, "%s", buf); ((_IO_FILE *) stderr)->_flags2 = old_flags2; _IO_funlockfile (stderr); free (buf); } #else fprintf (stderr, _("%s: option `%s' requires an argument\n"), argv[0], argv[d->optind - 1]); #endif } d->__nextchar += strlen (d->__nextchar); d->optopt = pfound->val; return optstring[0] == ':' ? ':' : '?'; } } d->__nextchar += strlen (d->__nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[d->optind][1] == '-' || strchr (optstring, *d->__nextchar) == NULL) { if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO char *buf; int n; #endif if (argv[d->optind][1] == '-') { /* --option */ #if defined _LIBC && defined USE_IN_LIBIO n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"), argv[0], d->__nextchar); #else fprintf (stderr, _("%s: unrecognized option `--%s'\n"), argv[0], d->__nextchar); #endif } else { /* +option or -option */ #if defined _LIBC && defined USE_IN_LIBIO n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"), argv[0], argv[d->optind][0], d->__nextchar); #else fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), argv[0], argv[d->optind][0], d->__nextchar); #endif } #if defined _LIBC && defined USE_IN_LIBIO if (n >= 0) { _IO_flockfile (stderr); int old_flags2 = ((_IO_FILE *) stderr)->_flags2; ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; __fxprintf (NULL, "%s", buf); ((_IO_FILE *) stderr)->_flags2 = old_flags2; _IO_funlockfile (stderr); free (buf); } #endif } d->__nextchar = (char *) ""; d->optind++; d->optopt = 0; return '?'; } } /* Look at and handle the next short option-character. */ { char c = *d->__nextchar++; char *temp = strchr (optstring, c); /* Increment `optind' when we start to process its last character. */ if (*d->__nextchar == '\0') ++d->optind; if (temp == NULL || c == ':') { if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO char *buf; int n; #endif if (d->__posixly_correct) { /* 1003.2 specifies the format of this message. */ #if defined _LIBC && defined USE_IN_LIBIO n = __asprintf (&buf, _("%s: illegal option -- %c\n"), argv[0], c); #else fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); #endif } else { #if defined _LIBC && defined USE_IN_LIBIO n = __asprintf (&buf, _("%s: invalid option -- %c\n"), argv[0], c); #else fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c); #endif } #if defined _LIBC && defined USE_IN_LIBIO if (n >= 0) { _IO_flockfile (stderr); int old_flags2 = ((_IO_FILE *) stderr)->_flags2; ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; __fxprintf (NULL, "%s", buf); ((_IO_FILE *) stderr)->_flags2 = old_flags2; _IO_funlockfile (stderr); free (buf); } #endif } d->optopt = c; return '?'; } /* Convenience. Treat POSIX -W foo same as long option --foo */ if (temp[0] == 'W' && temp[1] == ';') { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = 0; int option_index; /* This is an option that requires an argument. */ if (*d->__nextchar != '\0') { d->optarg = d->__nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ d->optind++; } else if (d->optind == argc) { if (print_errors) { /* 1003.2 specifies the format of this message. */ #if defined _LIBC && defined USE_IN_LIBIO char *buf; if (__asprintf (&buf, _("%s: option requires an argument -- %c\n"), argv[0], c) >= 0) { _IO_flockfile (stderr); int old_flags2 = ((_IO_FILE *) stderr)->_flags2; ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; __fxprintf (NULL, "%s", buf); ((_IO_FILE *) stderr)->_flags2 = old_flags2; _IO_funlockfile (stderr); free (buf); } #else fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); #endif } d->optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; return c; } else /* We already incremented `d->optind' once; increment it again when taking next ARGV-elt as argument. */ d->optarg = argv[d->optind++]; /* optarg is now the argument, see if it's in the table of longopts. */ for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) { if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO char *buf; if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"), argv[0], argv[d->optind]) >= 0) { _IO_flockfile (stderr); int old_flags2 = ((_IO_FILE *) stderr)->_flags2; ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; __fxprintf (NULL, "%s", buf); ((_IO_FILE *) stderr)->_flags2 = old_flags2; _IO_funlockfile (stderr); free (buf); } #else fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), argv[0], argv[d->optind]); #endif } d->__nextchar += strlen (d->__nextchar); d->optind++; return '?'; } if (pfound != NULL) { option_index = indfound; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) d->optarg = nameend + 1; else { if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO char *buf; if (__asprintf (&buf, _("\ %s: option `-W %s' doesn't allow an argument\n"), argv[0], pfound->name) >= 0) { _IO_flockfile (stderr); int old_flags2 = ((_IO_FILE *) stderr)->_flags2; ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; __fxprintf (NULL, "%s", buf); ((_IO_FILE *) stderr)->_flags2 = old_flags2; _IO_funlockfile (stderr); free (buf); } #else fprintf (stderr, _("\ %s: option `-W %s' doesn't allow an argument\n"), argv[0], pfound->name); #endif } d->__nextchar += strlen (d->__nextchar); return '?'; } } else if (pfound->has_arg == 1) { if (d->optind < argc) d->optarg = argv[d->optind++]; else { if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO char *buf; if (__asprintf (&buf, _("\ %s: option `%s' requires an argument\n"), argv[0], argv[d->optind - 1]) >= 0) { _IO_flockfile (stderr); int old_flags2 = ((_IO_FILE *) stderr)->_flags2; ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; __fxprintf (NULL, "%s", buf); ((_IO_FILE *) stderr)->_flags2 = old_flags2; _IO_funlockfile (stderr); free (buf); } #else fprintf (stderr, _("%s: option `%s' requires an argument\n"), argv[0], argv[d->optind - 1]); #endif } d->__nextchar += strlen (d->__nextchar); return optstring[0] == ':' ? ':' : '?'; } } d->__nextchar += strlen (d->__nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } d->__nextchar = NULL; return 'W'; /* Let the application handle it. */ } if (temp[1] == ':') { if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ if (*d->__nextchar != '\0') { d->optarg = d->__nextchar; d->optind++; } else d->optarg = NULL; d->__nextchar = NULL; } else { /* This is an option that requires an argument. */ if (*d->__nextchar != '\0') { d->optarg = d->__nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ d->optind++; } else if (d->optind == argc) { if (print_errors) { /* 1003.2 specifies the format of this message. */ #if defined _LIBC && defined USE_IN_LIBIO char *buf; if (__asprintf (&buf, _("\ %s: option requires an argument -- %c\n"), argv[0], c) >= 0) { _IO_flockfile (stderr); int old_flags2 = ((_IO_FILE *) stderr)->_flags2; ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; __fxprintf (NULL, "%s", buf); ((_IO_FILE *) stderr)->_flags2 = old_flags2; _IO_funlockfile (stderr); free (buf); } #else fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); #endif } d->optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ d->optarg = argv[d->optind++]; d->__nextchar = NULL; } } return c; } } int _getopt_internal (int argc, char *const *argv, const char *optstring, const struct option *longopts, int *longind, int long_only) { int result; getopt_data.optind = optind; getopt_data.opterr = opterr; result = _getopt_internal_r (argc, argv, optstring, longopts, longind, long_only, &getopt_data); optind = getopt_data.optind; optarg = getopt_data.optarg; optopt = getopt_data.optopt; return result; } int getopt (int argc, char *const *argv, const char *optstring) { return _getopt_internal (argc, argv, optstring, (const struct option *) 0, (int *) 0, 0); } #endif /* Not ELIDE_CODE. */ #ifdef TEST /* Compile with -DTEST to make an executable for use in testing the above definition of `getopt'. */ int main (int argc, char **argv) { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; c = getopt (argc, argv, "abc:d:0123456789"); if (c == -1) break; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ dmtx-utils-0.7.6/common/getopt.h000066400000000000000000000137551325607304600166220ustar00rootroot00000000000000/* Declarations for getopt. Copyright (C) 1989-1994,1996-1999,2001,2003,2004 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C 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. The GNU C 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 the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #ifndef _GETOPT_H #ifndef __need_getopt # define _GETOPT_H 1 #endif /* If __GNU_LIBRARY__ is not already defined, either we are being used standalone, or this is the first header included in the source file. If we are being used with glibc, we need to include , but that does not exist if we are standalone. So: if __GNU_LIBRARY__ is not defined, include , which will pull in for us if it's from glibc. (Why ctype.h? It's guaranteed to exist and it doesn't flood the namespace with stuff the way some other headers do.) */ #if !defined __GNU_LIBRARY__ # include #endif #ifndef __THROW # ifndef __GNUC_PREREQ # define __GNUC_PREREQ(maj, min) (0) # endif # if defined __cplusplus && __GNUC_PREREQ (2,8) # define __THROW throw () # else # define __THROW # endif #endif #ifdef __cplusplus extern "C" { #endif /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ extern char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ extern int optind; /* Callers store zero here to inhibit the error message `getopt' prints for unrecognized options. */ extern int opterr; /* Set to an option character which was unrecognized. */ extern int optopt; #ifndef __need_getopt /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector of `struct option' terminated by an element containing a name which is zero. The field `has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, optional_argument (or 2) if the option takes an optional argument. If the field `flag' is not NULL, it points to a variable that is set to the value given in the field `val' when the option is found, but left unchanged if the option is not found. To have a long-named option do something other than set an `int' to a compiled-in constant, such as set a value from `optarg', set the option's `flag' field to zero and its `val' field to a nonzero value (the equivalent single-letter option character, if there is one). For long options that have a zero `flag' field, `getopt' returns the contents of the `val' field. */ struct option { const char *name; /* has_arg can't be an enum because some compilers complain about type mismatches in all the code that assumes it is an int. */ int has_arg; int *flag; int val; }; /* Names for the values of the `has_arg' field of `struct option'. */ # define no_argument 0 # define required_argument 1 # define optional_argument 2 #endif /* need getopt */ /* Get definitions and prototypes for functions to process the arguments in ARGV (ARGC of them, minus the program name) for options given in OPTS. Return the option character from OPTS just read. Return -1 when there are no more options. For unrecognized options, or options missing arguments, `optopt' is set to the option letter, and '?' is returned. The OPTS string is a list of characters which are recognized option letters, optionally followed by colons, specifying that that letter takes an argument, to be placed in `optarg'. If a letter in OPTS is followed by two colons, its argument is optional. This behavior is specific to the GNU `getopt'. The argument `--' causes premature termination of argument scanning, explicitly telling `getopt' that there are no more options. If OPTS begins with `--', then non-option arguments are treated as arguments to the option '\0'. This behavior is specific to the GNU `getopt'. */ #ifdef __GNU_LIBRARY__ /* Many other libraries have conflicting prototypes for getopt, with differences in the consts, in stdlib.h. To avoid compilation errors, only prototype getopt for the GNU C library. */ extern int getopt (int ___argc, char *const *___argv, const char *__shortopts) __THROW; #else /* not __GNU_LIBRARY__ */ extern int getopt (); #endif /* __GNU_LIBRARY__ */ #ifndef __need_getopt extern int getopt_long (int ___argc, char *const *___argv, const char *__shortopts, const struct option *__longopts, int *__longind) __THROW; extern int getopt_long_only (int ___argc, char *const *___argv, const char *__shortopts, const struct option *__longopts, int *__longind) __THROW; #endif #ifdef __cplusplus } #endif /* Make sure we later can get all the definitions and declarations. */ #undef __need_getopt #endif /* getopt.h */ dmtx-utils-0.7.6/common/getopt1.c000066400000000000000000000112501325607304600166620ustar00rootroot00000000000000/* getopt_long and getopt_long_only entry points for GNU getopt. Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98,2004 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C 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. The GNU C 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 the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #ifdef HAVE_CONFIG_H #include #endif #ifdef _LIBC # include #else # include "getopt.h" #endif #include "getopt_int.h" #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 #include #if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION #define ELIDE_CODE #endif #endif #ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ #include #endif #ifndef NULL #define NULL 0 #endif int getopt_long (int argc, char *const *argv, const char *options, const struct option *long_options, int *opt_index) { return _getopt_internal (argc, argv, options, long_options, opt_index, 0); } int _getopt_long_r (int argc, char *const *argv, const char *options, const struct option *long_options, int *opt_index, struct _getopt_data *d) { return _getopt_internal_r (argc, argv, options, long_options, opt_index, 0, d); } /* Like getopt_long, but '-' as well as '--' can indicate a long option. If an option that starts with '-' (not '--') doesn't match a long option, but does match a short option, it is parsed as a short option instead. */ int getopt_long_only (int argc, char *const *argv, const char *options, const struct option *long_options, int *opt_index) { return _getopt_internal (argc, argv, options, long_options, opt_index, 1); } int _getopt_long_only_r (int argc, char *const *argv, const char *options, const struct option *long_options, int *opt_index, struct _getopt_data *d) { return _getopt_internal_r (argc, argv, options, long_options, opt_index, 1, d); } #endif /* Not ELIDE_CODE. */ #ifdef TEST #include int main (int argc, char **argv) { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"add", 1, 0, 0}, {"append", 0, 0, 0}, {"delete", 1, 0, 0}, {"verbose", 0, 0, 0}, {"create", 0, 0, 0}, {"file", 1, 0, 0}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "abc:d:0123456789", long_options, &option_index); if (c == -1) break; switch (c) { case 0: printf ("option %s", long_options[option_index].name); if (optarg) printf (" with arg %s", optarg); printf ("\n"); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case 'd': printf ("option d with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ dmtx-utils-0.7.6/common/getopt_int.h000066400000000000000000000112361325607304600174640ustar00rootroot00000000000000/* Internal declarations for getopt. Copyright (C) 1989-1994,1996-1999,2001,2003,2004 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C 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. The GNU C 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 the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #ifndef _GETOPT_INT_H #define _GETOPT_INT_H 1 extern int _getopt_internal (int ___argc, char *const *___argv, const char *__shortopts, const struct option *__longopts, int *__longind, int __long_only); /* Reentrant versions which can handle parsing multiple argument vectors at the same time. */ /* Data type for reentrant functions. */ struct _getopt_data { /* These have exactly the same meaning as the corresponding global variables, except that they are used for the reentrant versions of getopt. */ int optind; int opterr; int optopt; char *optarg; /* Internal members. */ /* True if the internal members have been initialized. */ int __initialized; /* The next char to be scanned in the option-element in which the last option character we returned was found. This allows us to pick up the scan where we left off. If this is zero, or a null string, it means resume the scan by advancing to the next ARGV-element. */ char *__nextchar; /* Describe how to deal with options that follow non-option ARGV-elements. If the caller did not specify anything, the default is REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. REQUIRE_ORDER means don't recognize them as options; stop option processing when the first non-option is seen. This is what Unix does. This mode of operation is selected by either setting the environment variable POSIXLY_CORRECT, or using `+' as the first character of the list of option characters. PERMUTE is the default. We permute the contents of ARGV as we scan, so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this. RETURN_IN_ORDER is an option available to programs that were written to expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option with character code 1. Using `-' as the first character of the list of option characters selects this mode of operation. The special argument `--' forces an end of option-scanning regardless of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return -1 with `optind' != ARGC. */ enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } __ordering; /* If the POSIXLY_CORRECT environment variable is set. */ int __posixly_correct; /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them. */ int __first_nonopt; int __last_nonopt; #if defined _LIBC && defined USE_NONOPTION_FLAGS int __nonoption_flags_max_len; int __nonoption_flags_len; # endif }; /* The initializer is necessary to set OPTIND and OPTERR to their default values and to clear the initialization flag. */ #define _GETOPT_DATA_INITIALIZER { 1, 1 } extern int _getopt_internal_r (int ___argc, char *const *___argv, const char *__shortopts, const struct option *__longopts, int *__longind, int __long_only, struct _getopt_data *__data); extern int _getopt_long_r (int ___argc, char *const *___argv, const char *__shortopts, const struct option *__longopts, int *__longind, struct _getopt_data *__data); extern int _getopt_long_only_r (int ___argc, char *const *___argv, const char *__shortopts, const struct option *__longopts, int *__longind, struct _getopt_data *__data); #endif /* getopt_int.h */ dmtx-utils-0.7.6/common/gettext.h000066400000000000000000000224211325607304600167720ustar00rootroot00000000000000/* Convenience header for conditional use of GNU . Copyright (C) 1995-1998, 2000-2002, 2004-2006 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program 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 Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _LIBGETTEXT_H #define _LIBGETTEXT_H 1 /* NLS can be disabled through the configure --disable-nls option. */ #if ENABLE_NLS /* Get declarations of GNU message catalog functions. */ # include /* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by the gettext() and ngettext() macros. This is an alternative to calling textdomain(), and is useful for libraries. */ # ifdef DEFAULT_TEXT_DOMAIN # undef gettext # define gettext(Msgid) \ dgettext (DEFAULT_TEXT_DOMAIN, Msgid) # undef ngettext # define ngettext(Msgid1, Msgid2, N) \ dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N) # endif #else /* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which chokes if dcgettext is defined as a macro. So include it now, to make later inclusions of a NOP. We don't include as well because people using "gettext.h" will not include , and also including would fail on SunOS 4, whereas is OK. */ #if defined(__sun) # include #endif /* Many header files from the libstdc++ coming with g++ 3.3 or newer include , which chokes if dcgettext is defined as a macro. So include it now, to make later inclusions of a NOP. */ #if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3) # include # if (__GLIBC__ >= 2) || _GLIBCXX_HAVE_LIBINTL_H # include # endif #endif /* Disabled NLS. The casts to 'const char *' serve the purpose of producing warnings for invalid uses of the value returned from these functions. On pre-ANSI systems without 'const', the config.h file is supposed to contain "#define const". */ # define gettext(Msgid) ((const char *) (Msgid)) # define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid)) # define dcgettext(Domainname, Msgid, Category) \ ((void) (Category), dgettext (Domainname, Msgid)) # define ngettext(Msgid1, Msgid2, N) \ ((N) == 1 \ ? ((void) (Msgid2), (const char *) (Msgid1)) \ : ((void) (Msgid1), (const char *) (Msgid2))) # define dngettext(Domainname, Msgid1, Msgid2, N) \ ((void) (Domainname), ngettext (Msgid1, Msgid2, N)) # define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ ((void) (Category), dngettext(Domainname, Msgid1, Msgid2, N)) # define textdomain(Domainname) ((const char *) (Domainname)) # define bindtextdomain(Domainname, Dirname) \ ((void) (Domainname), (const char *) (Dirname)) # define bind_textdomain_codeset(Domainname, Codeset) \ ((void) (Domainname), (const char *) (Codeset)) #endif /* A pseudo function call that serves as a marker for the automated extraction of messages, but does not call gettext(). The run-time translation is done at a different place in the code. The argument, String, should be a literal string. Concatenated strings and other string expressions won't work. The macro's expansion is not parenthesized, so that it is suitable as initializer for static 'char[]' or 'const char[]' variables. */ #define gettext_noop(String) String /* The separator between msgctxt and msgid in a .mo file. */ #define GETTEXT_CONTEXT_GLUE "\004" /* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be short and rarely need to change. The letter 'p' stands for 'particular' or 'special'. */ #ifdef DEFAULT_TEXT_DOMAIN # define pgettext(Msgctxt, Msgid) \ pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) #else # define pgettext(Msgctxt, Msgid) \ pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) #endif #define dpgettext(Domainname, Msgctxt, Msgid) \ pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) #define dcpgettext(Domainname, Msgctxt, Msgid, Category) \ pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category) #ifdef DEFAULT_TEXT_DOMAIN # define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) #else # define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) #endif #define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) #define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \ npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category) #ifdef __GNUC__ __inline #else #ifdef __cplusplus inline #endif #endif static const char * pgettext_aux (const char *domain, const char *msg_ctxt_id, const char *msgid, int category) { const char *translation = dcgettext (domain, msg_ctxt_id, category); if (translation == msg_ctxt_id) return msgid; else return translation; } #ifdef __GNUC__ __inline #else #ifdef __cplusplus inline #endif #endif static const char * npgettext_aux (const char *domain, const char *msg_ctxt_id, const char *msgid, const char *msgid_plural, unsigned long int n, int category) { const char *translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); if (translation == msg_ctxt_id || translation == msgid_plural) return (n == 1 ? msgid : msgid_plural); else return translation; } /* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID can be arbitrary expressions. But for string literals these macros are less efficient than those above. */ #include #define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \ (((__GNUC__ >= 3 || __GNUG__ >= 2) && !__STRICT_ANSI__) \ /* || __STDC_VERSION__ >= 199901L */ ) #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS #include #endif #define pgettext_expr(Msgctxt, Msgid) \ dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES) #define dpgettext_expr(Domainname, Msgctxt, Msgid) \ dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES) #ifdef __GNUC__ __inline #else #ifdef __cplusplus inline #endif #endif static const char * dcpgettext_expr (const char *domain, const char *msgctxt, const char *msgid, int category) { size_t msgctxt_len = strlen (msgctxt) + 1; size_t msgid_len = strlen (msgid) + 1; const char *translation; #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS char msg_ctxt_id[msgctxt_len + msgid_len]; #else char buf[1024]; char *msg_ctxt_id = (msgctxt_len + msgid_len <= sizeof (buf) ? buf : (char *) malloc (msgctxt_len + msgid_len)); if (msg_ctxt_id != NULL) #endif { memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); msg_ctxt_id[msgctxt_len - 1] = '\004'; memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); translation = dcgettext (domain, msg_ctxt_id, category); #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS if (msg_ctxt_id != buf) free (msg_ctxt_id); #endif if (translation != msg_ctxt_id) return translation; } return msgid; } #define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \ dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) #define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) #ifdef __GNUC__ __inline #else #ifdef __cplusplus inline #endif #endif static const char * dcnpgettext_expr (const char *domain, const char *msgctxt, const char *msgid, const char *msgid_plural, unsigned long int n, int category) { size_t msgctxt_len = strlen (msgctxt) + 1; size_t msgid_len = strlen (msgid) + 1; const char *translation; #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS char msg_ctxt_id[msgctxt_len + msgid_len]; #else char buf[1024]; char *msg_ctxt_id = (msgctxt_len + msgid_len <= sizeof (buf) ? buf : (char *) malloc (msgctxt_len + msgid_len)); if (msg_ctxt_id != NULL) #endif { memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); msg_ctxt_id[msgctxt_len - 1] = '\004'; memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS if (msg_ctxt_id != buf) free (msg_ctxt_id); #endif if (!(translation == msg_ctxt_id || translation == msgid_plural)) return translation; } return (n == 1 ? msgid : msgid_plural); } #endif /* _LIBGETTEXT_H */ dmtx-utils-0.7.6/configure.ac000066400000000000000000000042461325607304600161400ustar00rootroot00000000000000AC_INIT([dmtx-utils], [0.7.5], [https://github.com/dmtx/dmtx-utils/issues], [dmtx-utils], [https://github.com/dmtx/dmtx-utils]) AM_INIT_AUTOMAKE([-Wall -Werror gnu]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_LIBOBJ_DIR([common]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_FILES([Makefile]) AC_PATH_PROG([PKG_CONFIG], [pkg-config], [no]) AC_PROG_CC AC_PROG_LIBTOOL AM_PROG_CC_C_O ifdef([PKG_CHECK_MODULES], [], [AC_MSG_ERROR([Building dmtxread/dmtxwrite requires a working autoconf/pkg-config])]) AC_SEARCH_LIBS([atan2], [m] ,[], AC_MSG_ERROR([dmtx-utils requires libm])) PKG_CHECK_MODULES(DMTX, libdmtx >= 0.7.0, [], AC_MSG_ERROR([dmtxread/dmtxwrite requires libdmtx >= 0.7.0])) AC_SUBST(DMTX_CFLAGS) AC_SUBST(DMTX_LIBS) AC_CHECK_HEADERS([sysexits.h]) AC_CHECK_HEADERS([getopt.h]) AC_CHECK_FUNC([getopt_long], [], [ AC_LIBOBJ([getopt]) AC_LIBOBJ([getopt1]) ]) AC_ARG_ENABLE( [dmtxquery], AS_HELP_STRING([--disable-dmtxquery], [do not build the dmtxquery utility]), [dmtxquery="$enableval"], [dmtxquery="yes"] ) AC_ARG_ENABLE( [dmtxread], AS_HELP_STRING([--disable-dmtxread], [do not build the dmtxread utility]), [dmtxread="$enableval"], [dmtxread="yes"] ) AC_ARG_ENABLE( [dmtxwrite], AS_HELP_STRING([--disable-dmtxwrite], [do not build the dmtxwrite utility]), [dmtxwrite="$enableval"], [dmtxwrite="yes"] ) AM_CONDITIONAL([ENABLE_DMTXQUERY], [test x$dmtxquery = xyes]) AM_CONDITIONAL([ENABLE_DMTXREAD], [test x$dmtxread = xyes]) AM_CONDITIONAL([ENABLE_DMTXWRITE], [test x$dmtxwrite = xyes]) if test x$dmtxquery = xyes; then AC_CONFIG_FILES([dmtxquery/Makefile]) fi if test x$dmtxread = xyes; then AC_CONFIG_FILES([dmtxread/Makefile]) fi if test x$dmtxwrite = xyes; then AC_CONFIG_FILES([dmtxwrite/Makefile]) fi if test x$dmtxread = xyes -o x$dmtxwrite = xyes; then PKG_CHECK_MODULES(MAGICK, MagickWand >= 6.2.4, [], AC_MSG_ERROR([dmtxread/dmtxwrite requires MagickWand >= 6.2.4])) AH_TEMPLATE([IM_API_7], [Define to 1 if version of installed ImageMagick library is 7.x]) AS_CASE( [`${PKG_CONFIG} --modversion MagickWand`], [7.[[0-9]]*], [AC_DEFINE([IM_API_7], [1])] ) AC_SUBST(MAGICK_CFLAGS) AC_SUBST(MAGICK_LIBS) fi AC_OUTPUT dmtx-utils-0.7.6/dmtxquery/000077500000000000000000000000001325607304600157065ustar00rootroot00000000000000dmtx-utils-0.7.6/dmtxquery/Makefile.am000066400000000000000000000007111325607304600177410ustar00rootroot00000000000000AUTOMAKE_OPTIONS = subdir-objects AM_CPPFLAGS = -Wshadow -Wall -pedantic bin_PROGRAMS = dmtxquery noinst_PROGRAMS = dmtxquery.debug dmtxquery_SOURCES = dmtxquery.c dmtxquery.h ../common/dmtxutil.c ../common/dmtxutil.h dmtxquery_LDFLAGS = $(DMTX_LIBS) dmtxquery_LDADD = $(LIBOBJS) dmtxquery_debug_SOURCES = dmtxquery.c dmtxquery.h ../common/dmtxutil.c ../common/dmtxutil.h dmtxquery_debug_LDFLAGS = -static $(DMTX_LIBS) dmtxquery_debug_LDADD = $(LIBOBJS) dmtx-utils-0.7.6/dmtxquery/dmtxquery.c000066400000000000000000000115521325607304600201200ustar00rootroot00000000000000/* libdmtx - Data Matrix Encoding/Decoding Library Copyright (C) 2008, 2009 Mike Laughton 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 St, Fifth Floor, Boston, MA 02110-1301 USA Contact: mike@dragonflylogic.com */ #include #include #include #include #include #include #include "dmtxquery.h" #include "../common/dmtxutil.h" char *programName; /** * Main function for the dmtxquery Data Matrix scanning utility. * * @param argc count of arguments passed from command line * @param argv list of argument passed strings from command line * @return numeric success / failure exit code */ int main(int argc, char *argv[]) { int err; UserOptions options; SetOptionDefaults(&options); err = HandleArgs(&options, &argc, &argv); if(err) ShowUsage(err); exit(0); } /** * * */ static void SetOptionDefaults(UserOptions *options) { memset(options, 0x00, sizeof(UserOptions)); /* Set default options */ } /** * Sets and validates user-requested options from command line arguments. * * @param options runtime options from defaults or command line * @param argcp pointer to argument count * @param argvp pointer to argument list * @return DmtxPass | DmtxFail */ static DmtxPassFail HandleArgs(UserOptions *options, int *argcp, char **argvp[]) { int opt; int longIndex; struct option longOptions[] = { {"version", no_argument, NULL, 'V'}, {"help", no_argument, NULL, 0 }, {0, 0, 0, 0} }; programName = Basename((*argvp)[0]); if(*argcp == 1) /* Program called without arguments */ return DmtxFail; for(;;) { opt = getopt_long(*argcp, *argvp, "V", longOptions, &longIndex); if(opt == -1) break; switch(opt) { case 0: /* --help */ ShowUsage(0); break; case 'V': fprintf(stderr, "%s version %s\n", programName, DmtxVersion); fprintf(stderr, "libdmtx version %s\n", dmtxVersion()); exit(0); break; default: return DmtxFail; break; } } return DmtxPass; } /** * Display program usage and exit with received status. * * @param status error code returned to OS * @return void */ static void ShowUsage(int status) { if(status != 0) { fprintf(stderr, _("Usage: %s PROPERTY [OPTION]... [FILE]...\n"), programName); fprintf(stderr, _("Try `%s --help' for more information.\n"), programName); } else { fprintf(stderr, _("Usage: %s PROPERTY [OPTION]... [FILE]...\n"), programName); fprintf(stderr, _("\ Extract information from the XML output from dmtxread for individual or\n\ grouped barcode scan results.\n\ \n\ Example: dmtxread barcode.png | %s barcode.count\n\ Example: %s barcode.2.rotation scanresults.xml\n\ \n\ PROPERTY:\n"), programName, programName); fprintf(stderr, _("\ barcode.count count of all barcodes found in image\n\ barcode.N.BPROP print BPROP property of Nth barcode\n\ \n\ message.count count of all messages found in image\n\ message.N.MPROP print MPROP property of Nth message\n\ message.N.barcode.count count of all barcodes in Nth message\n\ message.N.barcode.M Mth barcode of Nth message, print all\n\ message.N.barcode.M.BPROP Mth barcode of Nth message, print BPROP\n\ \n\ BPROP barcode properties:\n\ message message_number message_position\n\ matrix_size data_codewords error_codewords\n\ rotation data_regions_count interleaved_blocks\n\ \n\ MPROP message properties:\n\ message data_codeword error_codeword\n\ \n\ OPTIONS:\n\ -V, --version print program version information\n\ --help display this help and exit\n")); fprintf(stderr, _("\nReport bugs to .\n")); fprintf(stderr, "\n\ ***************************************************************\n\ **** This program currently does nothing besides printing ****\n\ **** this help screen. This program is just a placeholder. ****\n\ ***************************************************************\n\n"); } exit(status); } dmtx-utils-0.7.6/dmtxquery/dmtxquery.h000066400000000000000000000023401325607304600201200ustar00rootroot00000000000000/* libdmtx - Data Matrix Encoding/Decoding Library Copyright (C) 2008, 2009 Mike Laughton 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 St, Fifth Floor, Boston, MA 02110-1301 USA Contact: mike@dragonflylogic.com */ #ifndef __DMTXQUERY_H__ #define __DMTXQUERY_H__ #if ENABLE_NLS # include # define _(String) gettext(String) #else # define _(String) String #endif #define N_(String) String typedef struct { int placeHolder; } UserOptions; static void SetOptionDefaults(UserOptions *options); static DmtxPassFail HandleArgs(UserOptions *options, int *argcp, char **argvp[]); static void ShowUsage(int status); #endif dmtx-utils-0.7.6/dmtxread/000077500000000000000000000000001325607304600154545ustar00rootroot00000000000000dmtx-utils-0.7.6/dmtxread/Makefile.am000066400000000000000000000011531325607304600175100ustar00rootroot00000000000000AUTOMAKE_OPTIONS = subdir-objects AM_CPPFLAGS = -Wshadow -Wall -pedantic bin_PROGRAMS = dmtxread noinst_PROGRAMS = dmtxread.debug dmtxread_SOURCES = dmtxread.c dmtxread.h ../common/dmtxutil.c ../common/dmtxutil.h dmtxread_CFLAGS = $(DMTX_CFLAGS) $(MAGICK_CFLAGS) -D_MAGICK_CONFIG_H dmtxread_LDFLAGS = $(DMTX_LIBS) $(MAGICK_LIBS) dmtxread_LDADD = $(LIBOBJS) dmtxread_debug_SOURCES = dmtxread.c dmtxread.h ../common/dmtxutil.c ../common/dmtxutil.h dmtxread_debug_CFLAGS = $(DMTX_CFLAGS) $(MAGICK_CFLAGS) -D_MAGICK_CONFIG_H dmtxread_debug_LDFLAGS = -static $(DMTX_LIBS) $(MAGICK_LIBS) dmtxread_debug_LDADD = $(LIBOBJS) dmtx-utils-0.7.6/dmtxread/dmtxread.c000066400000000000000000000646501325607304600174430ustar00rootroot00000000000000/* libdmtx - Data Matrix Encoding/Decoding Library Copyright (C) 2008, 2009 Mike Laughton Copyright (C) 2008 Ryan Raasch Copyright (C) 2008 Olivier Guilyardi 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 St, Fifth Floor, Boston, MA 02110-1301 USA Contact: mike@dragonflylogic.com */ #include "dmtxread.h" char *programName; /** * @brief Main function for the dmtxread Data Matrix scanning utility. * @param argc count of arguments passed from command line * @param argv list of argument passed strings from command line * @return Numeric exit code */ int main(int argc, char *argv[]) { char *filePath; int i; int err; int fileIndex, imgPageIndex; int fileCount; int imgScanCount, pageScanCount; int width, height; unsigned char *pxl; UserOptions opt; DmtxTime timeout; DmtxImage *img; DmtxDecode *dec; DmtxRegion *reg; DmtxMessage *msg; MagickBooleanType success; MagickWand *wand; opt = GetDefaultOptions(); err = HandleArgs(&opt, &fileIndex, &argc, &argv); if(err != DmtxPass) ShowUsage(EX_USAGE); fileCount = (argc == fileIndex) ? 1 : argc - fileIndex; MagickWandGenesis(); /* Loop once for each image named on command line */ imgScanCount = 0; for(i = 0; i < fileCount; i++) { /* Open image from file or stream (might contain multiple pages) */ filePath = (argc == fileIndex) ? "-" : argv[fileIndex++]; wand = NewMagickWand(); if(wand == NULL) { FatalError(EX_OSERR, "Magick error"); } /* XXX note this is not the same as MagickSetImageResolution() ... * need to research what this is setting. Could be dots per inch, dots * per centimeter, or even dots per "image width" */ if(opt.dpi != DmtxUndefined) { success = MagickSetResolution(wand, (double)opt.dpi, (double)opt.dpi); if(success == MagickFalse) { CleanupMagick(&wand, DmtxTrue); FatalError(EX_OSERR, "Unable to set image resolution"); } } success = MagickReadImage(wand, filePath); if(success == MagickFalse) { CleanupMagick(&wand, DmtxTrue); FatalError(EX_OSERR, "Unable to open file \"%s\" for reading", filePath); } width = MagickGetImageWidth(wand); height = MagickGetImageHeight(wand); /* Loop once for each page within image */ MagickResetIterator(wand); for(imgPageIndex = 0; MagickNextImage(wand) != MagickFalse; imgPageIndex++) { /* If requested, only scan specific page */ if(opt.page != DmtxUndefined && opt.page - 1 != imgPageIndex) continue; /* Reset timeout for each new page */ if(opt.timeoutMS != DmtxUndefined) timeout = dmtxTimeAdd(dmtxTimeNow(), opt.timeoutMS); /* Allocate memory for pixel data */ pxl = (unsigned char *)malloc(3 * width * height * sizeof(unsigned char)); if(pxl == NULL) { CleanupMagick(&wand, DmtxFalse); FatalError(EX_OSERR, "malloc() error"); } /* Copy pixels to known format */ success = MagickGetImagePixels(wand, 0, 0, width, height, "RGB", CharPixel, pxl); if(success == MagickFalse || pxl == NULL) { CleanupMagick(&wand, DmtxTrue); FatalError(EX_OSERR, "malloc() error"); } /* Initialize libdmtx image */ img = dmtxImageCreate(pxl, width, height, DmtxPack24bppRGB); if(img == NULL) { CleanupMagick(&wand, DmtxFalse); FatalError(EX_SOFTWARE, "dmtxImageCreate() error"); } dmtxImageSetProp(img, DmtxPropImageFlip, DmtxFlipNone); /* Initialize scan */ dec = dmtxDecodeCreate(img, opt.shrinkMin); if(dec == NULL) { CleanupMagick(&wand, DmtxFalse); FatalError(EX_SOFTWARE, "decode create error"); } err = SetDecodeOptions(dec, img, &opt); if(err != DmtxPass) { CleanupMagick(&wand, DmtxFalse); FatalError(EX_SOFTWARE, "decode option error"); } /* Find and decode every barcode on page */ pageScanCount = 0; for(;;) { /* Find next barcode region within image, but do not decode yet */ if(opt.timeoutMS == DmtxUndefined) reg = dmtxRegionFindNext(dec, NULL); else reg = dmtxRegionFindNext(dec, &timeout); /* Finished file or ran out of time before finding another region */ if(reg == NULL) break; /* Decode region based on requested barcode mode */ if(opt.mosaic == DmtxTrue) msg = dmtxDecodeMosaicRegion(dec, reg, opt.correctionsMax); else msg = dmtxDecodeMatrixRegion(dec, reg, opt.correctionsMax); if(msg != NULL) { PrintStats(dec, reg, msg, imgPageIndex, &opt); PrintMessage(reg, msg, &opt); pageScanCount++; imgScanCount++; dmtxMessageDestroy(&msg); } dmtxRegionDestroy(®); if(opt.stopAfter != DmtxUndefined && imgScanCount >= opt.stopAfter) break; } if(opt.diagnose == DmtxTrue) WriteDiagnosticImage(dec, "debug.pnm"); dmtxDecodeDestroy(&dec); dmtxImageDestroy(&img); free(pxl); } CleanupMagick(&wand, DmtxFalse); } MagickWandTerminus(); exit((imgScanCount > 0) ? EX_OK : 1); } /** * * */ static UserOptions GetDefaultOptions(void) { UserOptions opt; memset(&opt, 0x00, sizeof(UserOptions)); /* Default options */ opt.codewords = DmtxFalse; opt.edgeMin = DmtxUndefined; opt.edgeMax = DmtxUndefined; opt.scanGap = 2; opt.timeoutMS = DmtxUndefined; opt.newline = DmtxFalse; opt.page = DmtxUndefined; opt.squareDevn = DmtxUndefined; opt.dpi = DmtxUndefined; opt.sizeIdxExpected = DmtxSymbolShapeAuto; opt.edgeThresh = 5; opt.xMin = NULL; opt.xMax = NULL; opt.yMin = NULL; opt.yMax = NULL; opt.correctionsMax = DmtxUndefined; opt.diagnose = DmtxFalse; opt.mosaic = DmtxFalse; opt.stopAfter = DmtxUndefined; opt.pageNumbers = DmtxFalse; opt.corners = DmtxFalse; opt.shrinkMin = 1; opt.shrinkMax = 1; opt.unicode = DmtxFalse; opt.verbose = DmtxFalse; opt.gs1 = DmtxUndefined; return opt; } /** * @brief Set and validate user-requested options from command line arguments. * @param opt runtime options from defaults or command line * @param argcp pointer to argument count * @param argvp pointer to argument list * @param fileIndex pointer to index of first non-option arg (if successful) * @return DmtxPass | DmtxFail */ static DmtxPassFail HandleArgs(UserOptions *opt, int *fileIndex, int *argcp, char **argvp[]) { int i; int err; int optchr; int longIndex; char *ptr; struct option longOptions[] = { {"codewords", no_argument, NULL, 'c'}, {"minimum-edge", required_argument, NULL, 'e'}, {"maximum-edge", required_argument, NULL, 'E'}, {"gap", required_argument, NULL, 'g'}, {"list-formats", no_argument, NULL, 'l'}, {"milliseconds", required_argument, NULL, 'm'}, {"newline", no_argument, NULL, 'n'}, {"page", required_argument, NULL, 'p'}, {"square-deviation", required_argument, NULL, 'q'}, {"resolution", required_argument, NULL, 'r'}, {"symbol-size", required_argument, NULL, 's'}, {"threshold", required_argument, NULL, 't'}, {"x-range-min", required_argument, NULL, 'x'}, {"x-range-max", required_argument, NULL, 'X'}, {"y-range-min", required_argument, NULL, 'y'}, {"y-range-max", required_argument, NULL, 'Y'}, {"max-corrections", required_argument, NULL, 'C'}, {"diagnose", no_argument, NULL, 'D'}, {"mosaic", no_argument, NULL, 'M'}, {"stop-after", required_argument, NULL, 'N'}, {"page-numbers", no_argument, NULL, 'P'}, {"corners", no_argument, NULL, 'R'}, {"shrink", required_argument, NULL, 'S'}, {"unicode", no_argument, NULL, 'U'}, {"gs1", required_argument, NULL, 'G'}, {"verbose", no_argument, NULL, 'v'}, {"version", no_argument, NULL, 'V'}, {"help", no_argument, NULL, 0 }, {0, 0, 0, 0} }; programName = Basename((*argvp)[0]); *fileIndex = 0; for(;;) { optchr = getopt_long(*argcp, *argvp, "ce:E:g:lm:np:q:r:s:t:x:X:y:Y:vC:DMN:PRS:G:UV", longOptions, &longIndex); if(optchr == -1) break; switch(optchr) { case 0: /* --help */ ShowUsage(EX_OK); break; case 'l': ListImageFormats(); exit(EX_OK); break; case 'c': opt->codewords = DmtxTrue; break; case 'e': err = StringToInt(&(opt->edgeMin), optarg, &ptr); if(err != DmtxPass || opt->edgeMin <= 0 || *ptr != '\0') FatalError(EX_USAGE, _("Invalid edge length specified \"%s\""), optarg); break; case 'E': err = StringToInt(&(opt->edgeMax), optarg, &ptr); if(err != DmtxPass || opt->edgeMax <= 0 || *ptr != '\0') FatalError(EX_USAGE, _("Invalid edge length specified \"%s\""), optarg); break; case 'g': err = StringToInt(&(opt->scanGap), optarg, &ptr); if(err != DmtxPass || opt->scanGap <= 0 || *ptr != '\0') FatalError(EX_USAGE, _("Invalid gap specified \"%s\""), optarg); break; case 'm': err = StringToInt(&(opt->timeoutMS), optarg, &ptr); if(err != DmtxPass || opt->timeoutMS < 0 || *ptr != '\0') FatalError(EX_USAGE, _("Invalid timeout (in milliseconds) specified \"%s\""), optarg); break; case 'n': opt->newline = DmtxTrue; break; case 'p': err = StringToInt(&(opt->page), optarg, &ptr); if(err != DmtxPass || opt->page < 1 || *ptr != '\0') FatalError(EX_USAGE, _("Invalid page specified \"%s\""), optarg); break; case 'q': err = StringToInt(&(opt->squareDevn), optarg, &ptr); if(err != DmtxPass || *ptr != '\0' || opt->squareDevn < 0 || opt->squareDevn > 90) FatalError(EX_USAGE, _("Invalid squareness deviation specified \"%s\""), optarg); break; case 'r': err = StringToInt(&(opt->dpi), optarg, &ptr); if(err != DmtxPass || *ptr != '\0' || opt->dpi < 1) FatalError(EX_USAGE, _("Invalid resolution specified \"%s\""), optarg); break; case 's': /* Determine correct barcode size and/or shape */ if(*optarg == 'a') { opt->sizeIdxExpected = DmtxSymbolShapeAuto; } else if(*optarg == 's') { opt->sizeIdxExpected = DmtxSymbolSquareAuto; } else if(*optarg == 'r') { opt->sizeIdxExpected = DmtxSymbolRectAuto; } else { for(i = 0; i < DmtxSymbolSquareCount + DmtxSymbolRectCount; i++) { if(strncmp(optarg, symbolSizes[i], 8) == 0) { opt->sizeIdxExpected = i; break; } } if(i == DmtxSymbolSquareCount + DmtxSymbolRectCount) return DmtxFail; } break; case 't': err = StringToInt(&(opt->edgeThresh), optarg, &ptr); if(err != DmtxPass || *ptr != '\0' || opt->edgeThresh < 1 || opt->edgeThresh > 100) FatalError(EX_USAGE, _("Invalid edge threshold specified \"%s\""), optarg); break; case 'x': opt->xMin = optarg; break; case 'X': opt->xMax = optarg; break; case 'y': opt->yMin = optarg; break; case 'Y': opt->yMax = optarg; break; case 'v': opt->verbose = DmtxTrue; break; case 'C': err = StringToInt(&(opt->correctionsMax), optarg, &ptr); if(err != DmtxPass || opt->correctionsMax < 0 || *ptr != '\0') FatalError(EX_USAGE, _("Invalid max corrections specified \"%s\""), optarg); break; case 'D': opt->diagnose = DmtxTrue; break; case 'M': opt->mosaic = DmtxTrue; break; case 'N': err = StringToInt(&(opt->stopAfter), optarg, &ptr); if(err != DmtxPass || opt->stopAfter < 1 || *ptr != '\0') FatalError(EX_USAGE, _("Invalid count specified \"%s\""), optarg); break; case 'P': opt->pageNumbers = DmtxTrue; break; case 'R': opt->corners = DmtxTrue; break; case 'S': err = StringToInt(&(opt->shrinkMin), optarg, &ptr); if(err != DmtxPass || opt->shrinkMin < 1 || *ptr != '\0') FatalError(EX_USAGE, _("Invalid shrink factor specified \"%s\""), optarg); /* XXX later populate shrinkMax based on specified N-N range */ opt->shrinkMax = opt->shrinkMin; break; case 'U': opt->unicode = DmtxTrue; break; case 'G': err = StringToInt(&(opt->gs1), optarg, &ptr); if(err != DmtxPass || opt->gs1 <= 0 || opt->gs1 > 255 || *ptr != '\0') FatalError(EX_USAGE, _("Invalid gs1 character specified \"%s\""), optarg); break; case 'V': fprintf(stderr, "%s version %s\n", programName, DmtxVersion); fprintf(stderr, "libdmtx version %s\n", dmtxVersion()); exit(EX_OK); break; default: return DmtxFail; break; } } *fileIndex = optind; return DmtxPass; } /** * @brief Display program usage and exit with received status. * @param status error code returned to OS * @return void */ static void ShowUsage(int status) { if(status != 0) { fprintf(stderr, _("Usage: %s [OPTION]... [FILE]...\n"), programName); fprintf(stderr, _("Try `%s --help' for more information.\n"), programName); } else { fprintf(stderr, _("Usage: %s [OPTION]... [FILE]...\n"), programName); fprintf(stderr, _("\ Scan image FILE for Data Matrix barcodes and print decoded results to\n\ standard output. Note that %s may find multiple barcodes in one image.\n\ \n\ Example: Scan top third of IMAGE001.png and stop after first barcode is found:\n\ \n\ %s -n -Y33%% -N1 IMAGE001.png\n\ \n\ OPTIONS:\n"), programName, programName); fprintf(stderr, _("\ -c, --codewords print codewords extracted from barcode pattern\n\ -e, --minimum-edge=N pixel length of smallest expected edge in image\n\ -E, --maximum-edge=N pixel length of largest expected edge in image\n\ -g, --gap=N use scan grid with gap of N pixels between lines\n\ -l, --list-formats list supported image formats\n")); fprintf(stderr, _("\ -m, --milliseconds=N stop scan after N milliseconds (per image)\n\ -n, --newline print newline character at the end of decoded data\n\ -p, --page=N only scan Nth page of images\n\ -q, --square-deviation=N allow non-squareness of corners in degrees (0-90)\n\ -r, --resolution=N resolution for vector images (PDF, SVG, etc...)\n")); fprintf(stderr, _("\ -s, --symbol-size=[asr|RxC] only consider barcodes of specific size or shape\n\ a = All sizes [default]\n\ s = Only squares\n\ r = Only rectangles\n\ RxC = Exactly this many rows and columns (10x10, 8x18, etc...)\n")); fprintf(stderr, _("\ -t, --threshold=N ignore weak edges below threshold N (1-100)\n\ -x, --x-range-min=N[%%] do not scan pixels to the left of N (or N%%)\n\ -X, --x-range-max=N[%%] do not scan pixels to the right of N (or N%%)\n\ -y, --y-range-min=N[%%] do not scan pixels below N (or N%%)\n\ -Y, --y-range-max=N[%%] do not scan pixels above N (or N%%)\n")); fprintf(stderr, _("\ -C, --corrections-max=N correct at most N errors (0 = correction disabled)\n\ -D, --diagnose make copy of image with additional diagnostic data\n\ -M, --mosaic interpret detected regions as Data Mosaic barcodes\n\ -N, --stop-after=N stop scanning after Nth barcode is returned\n\ -P, --page-numbers prefix decoded message with fax/tiff page number\n")); fprintf(stderr, _("\ -R, --corners prefix decoded message with corner locations\n\ -S, --shrink=N internally shrink image by a factor of N\n\ -U, --unicode print Extended ASCII in Unicode (UTF-8)\n\ -G, --gs1=N enable GS1 mode and define character to represent FNC1\n\ -v, --verbose use verbose messages\n\ -V, --version print program version information\n\ --help display this help and exit\n")); fprintf(stderr, _("\nReport bugs to .\n")); } exit(status); } /** * * */ static DmtxPassFail SetDecodeOptions(DmtxDecode *dec, DmtxImage *img, UserOptions *opt) { int err; #define RETURN_IF_FAILED(e) if(e != DmtxPass) { return DmtxFail; } err = dmtxDecodeSetProp(dec, DmtxPropScanGap, opt->scanGap); RETURN_IF_FAILED(err) if(opt->gs1 != DmtxUndefined) { err = dmtxDecodeSetProp(dec, DmtxPropFnc1, opt->gs1); RETURN_IF_FAILED(err) } if(opt->edgeMin != DmtxUndefined) { err = dmtxDecodeSetProp(dec, DmtxPropEdgeMin, opt->edgeMin); RETURN_IF_FAILED(err) } if(opt->edgeMax != DmtxUndefined) { err = dmtxDecodeSetProp(dec, DmtxPropEdgeMax, opt->edgeMax); RETURN_IF_FAILED(err) } if(opt->squareDevn != DmtxUndefined) { err = dmtxDecodeSetProp(dec, DmtxPropSquareDevn, opt->squareDevn); RETURN_IF_FAILED(err) } err = dmtxDecodeSetProp(dec, DmtxPropSymbolSize, opt->sizeIdxExpected); RETURN_IF_FAILED(err) err = dmtxDecodeSetProp(dec, DmtxPropEdgeThresh, opt->edgeThresh); RETURN_IF_FAILED(err) if(opt->xMin) { err = dmtxDecodeSetProp(dec, DmtxPropXmin, ScaleNumberString(opt->xMin, img->width)); RETURN_IF_FAILED(err) } if(opt->xMax) { err = dmtxDecodeSetProp(dec, DmtxPropXmax, ScaleNumberString(opt->xMax, img->width)); RETURN_IF_FAILED(err) } if(opt->yMin) { err = dmtxDecodeSetProp(dec, DmtxPropYmin, ScaleNumberString(opt->yMin, img->height)); RETURN_IF_FAILED(err) } if(opt->yMax) { err = dmtxDecodeSetProp(dec, DmtxPropYmax, ScaleNumberString(opt->yMax, img->height)); RETURN_IF_FAILED(err) } #undef RETURN_IF_FAILED return DmtxPass; } /** * @brief Print decoded message to standard output * @param opt runtime options from defaults or command line * @param dec pointer to DmtxDecode struct * @return DmtxPass | DmtxFail */ static DmtxPassFail PrintStats(DmtxDecode *dec, DmtxRegion *reg, DmtxMessage *msg, int imgPageIndex, UserOptions *opt) { int height; int dataWordLength; int rotateInt; double rotate; DmtxVector2 p00, p10, p11, p01; height = dmtxDecodeGetProp(dec, DmtxPropHeight); p00.X = p00.Y = p10.Y = p01.X = 0.0; p10.X = p01.Y = p11.X = p11.Y = 1.0; dmtxMatrix3VMultiplyBy(&p00, reg->fit2raw); dmtxMatrix3VMultiplyBy(&p10, reg->fit2raw); dmtxMatrix3VMultiplyBy(&p11, reg->fit2raw); dmtxMatrix3VMultiplyBy(&p01, reg->fit2raw); dataWordLength = dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, reg->sizeIdx); if(opt->verbose == DmtxTrue) { /* rotate = (2 * M_PI) + (atan2(reg->fit2raw[0][1], reg->fit2raw[1][1]) - atan2(reg->fit2raw[1][0], reg->fit2raw[0][0])) / 2.0; */ rotate = (2 * M_PI) + atan2(p10.Y - p00.Y, p10.X - p00.X); rotateInt = (int)(rotate * 180/M_PI + 0.5); if(rotateInt >= 360) rotateInt -= 360; fprintf(stderr, "--------------------------------------------------\n"); fprintf(stderr, " Matrix Size: %d x %d\n", dmtxGetSymbolAttribute(DmtxSymAttribSymbolRows, reg->sizeIdx), dmtxGetSymbolAttribute(DmtxSymAttribSymbolCols, reg->sizeIdx)); fprintf(stderr, " Data Codewords: %d (capacity %d)\n", dataWordLength - msg->padCount, dataWordLength); fprintf(stderr, " Error Codewords: %d\n", dmtxGetSymbolAttribute(DmtxSymAttribSymbolErrorWords, reg->sizeIdx)); fprintf(stderr, " Data Regions: %d x %d\n", dmtxGetSymbolAttribute(DmtxSymAttribHorizDataRegions, reg->sizeIdx), dmtxGetSymbolAttribute(DmtxSymAttribVertDataRegions, reg->sizeIdx)); fprintf(stderr, "Interleaved Blocks: %d\n", dmtxGetSymbolAttribute(DmtxSymAttribInterleavedBlocks, reg->sizeIdx)); fprintf(stderr, " Rotation Angle: %d\n", rotateInt); fprintf(stderr, " Corner 0: (%0.1f, %0.1f)\n", p00.X, height - 1 - p00.Y); fprintf(stderr, " Corner 1: (%0.1f, %0.1f)\n", p10.X, height - 1 - p10.Y); fprintf(stderr, " Corner 2: (%0.1f, %0.1f)\n", p11.X, height - 1 - p11.Y); fprintf(stderr, " Corner 3: (%0.1f, %0.1f)\n", p01.X, height - 1 - p01.Y); fprintf(stderr, "--------------------------------------------------\n"); } if(opt->pageNumbers == DmtxTrue) fprintf(stderr, "%d:", imgPageIndex + 1); if(opt->corners == DmtxTrue) { fprintf(stderr, "%d,%d:", (int)(p00.X + 0.5), height - 1 - (int)(p00.Y + 0.5)); fprintf(stderr, "%d,%d:", (int)(p10.X + 0.5), height - 1 - (int)(p10.Y + 0.5)); fprintf(stderr, "%d,%d:", (int)(p11.X + 0.5), height - 1 - (int)(p11.Y + 0.5)); fprintf(stderr, "%d,%d:", (int)(p01.X + 0.5), height - 1 - (int)(p01.Y + 0.5)); } return DmtxPass; } /** * * */ static DmtxPassFail PrintMessage(DmtxRegion *reg, DmtxMessage *msg, UserOptions *opt) { int i; int remainingDataWords; int dataWordLength; if(opt->codewords == DmtxTrue) { dataWordLength = dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, reg->sizeIdx); for(i = 0; i < msg->codeSize; i++) { remainingDataWords = dataWordLength - i; if(remainingDataWords > msg->padCount) fprintf(stdout, "%c:%03d\n", 'd', msg->code[i]); else if(remainingDataWords > 0) fprintf(stdout, "%c:%03d\n", 'p', msg->code[i]); else fprintf(stdout, "%c:%03d\n", 'e', msg->code[i]); } } else { if(opt->unicode == DmtxTrue) { for(i = 0; i < msg->outputIdx; i++) { if(msg->output[i] < 128) { fputc(msg->output[i], stdout); } else if(msg->output[i] < 192) { fputc(0xc2, stdout); fputc(msg->output[i], stdout); } else { fputc(0xc3, stdout); fputc(msg->output[i] - 64, stdout); } } } else { fwrite(msg->output, sizeof(char), msg->outputIdx, stdout); } if(opt->newline) fputc('\n', stdout); } return DmtxPass; } /** * * */ static void CleanupMagick(MagickWand **wand, int magickError) { char *excMessage; ExceptionType excSeverity; if(magickError == DmtxTrue) { excMessage = MagickGetException(*wand, &excSeverity); /* fprintf(stderr, "%s %s %lu %s\n", GetMagickModule(), excMessage); */ MagickRelinquishMemory(excMessage); } if(*wand != NULL) { DestroyMagickWand(*wand); *wand = NULL; } } /** * @brief List supported input image formats on stdout * @return void */ static void ListImageFormats(void) { int i, idx; int row, rowCount; int col, colCount; unsigned long totalCount; char **list; list = MagickQueryFormats("*", &totalCount); if(list == NULL) return; fprintf(stderr, "\n"); colCount = 7; rowCount = totalCount / colCount; if(totalCount % colCount) rowCount++; for(i = 0; i < colCount * rowCount; i++) { col = i % colCount; row = i / colCount; idx = col * rowCount + row; fprintf(stderr, "%10s", (idx < totalCount) ? list[col * rowCount + row] : " "); fprintf(stderr, "%s", (col + 1 < colCount) ? " " : "\n"); } fprintf(stderr, "\n"); MagickRelinquishMemory(list); } /** * * */ static void WriteDiagnosticImage(DmtxDecode *dec, char *imagePath) { int totalBytes, headerBytes; int bytesWritten; unsigned char *pnm; FILE *fp; fp = fopen(imagePath, "wb"); if(fp == NULL) { perror(programName); FatalError(EX_CANTCREAT, _("Unable to create image \"%s\""), imagePath); } pnm = dmtxDecodeCreateDiagnostic(dec, &totalBytes, &headerBytes, 0); if(pnm == NULL) FatalError(EX_OSERR, _("Unable to create diagnostic image")); bytesWritten = fwrite(pnm, sizeof(unsigned char), totalBytes, fp); if(bytesWritten != totalBytes) FatalError(EX_IOERR, _("Unable to write diagnostic image")); free(pnm); fclose(fp); } /** * * */ static int ScaleNumberString(char *s, int extent) { int err; int numValue; int scaledValue; char *terminate; assert(s != NULL); err = StringToInt(&numValue, s, &terminate); if(err != DmtxPass) FatalError(EX_USAGE, _("Integer value required")); scaledValue = (*terminate == '%') ? (int)(0.01 * numValue * extent + 0.5) : numValue; if(scaledValue < 0) scaledValue = 0; if(scaledValue >= extent) scaledValue = extent - 1; return scaledValue; } dmtx-utils-0.7.6/dmtxread/dmtxread.h000066400000000000000000000065511325607304600174440ustar00rootroot00000000000000/* libdmtx - Data Matrix Encoding/Decoding Library Copyright (C) 2008, 2009 Mike Laughton Copyright (C) 2008 Olivier Guilyardi 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 St, Fifth Floor, Boston, MA 02110-1301 USA Contact: mike@dragonflylogic.com */ #ifndef __DMTXREAD_H__ #define __DMTXREAD_H__ #include #include #include #include #include #include #include #include #include #include #include "../common/dmtxutil.h" #ifdef IM_API_7 #include #else #include #endif #if MagickLibVersion > 0x645 #define MagickGetImagePixels MagickExportImagePixels #endif #if ENABLE_NLS # include # define _(String) gettext(String) #else # define _(String) String #endif #define N_(String) String typedef struct { int codewords; /* -c, --codewords */ int edgeMin; /* -e, --minimum-edge */ int edgeMax; /* -E, --maximum-edge */ int scanGap; /* -g, --gap */ int timeoutMS; /* -m, --milliseconds */ int newline; /* -n, --newline */ int page; /* -p, --page */ int squareDevn; /* -q, --square-deviation */ int dpi; /* -r, --resolution */ int sizeIdxExpected; /* -s, --symbol-size */ int edgeThresh; /* -t, --threshold */ char *xMin; /* -x, --x-range-min */ char *xMax; /* -X, --x-range-max */ char *yMin; /* -y, --y-range-min */ char *yMax; /* -Y, --y-range-max */ int correctionsMax; /* -C, --corrections-max */ int diagnose; /* -D, --diagnose */ int mosaic; /* -M, --mosaic */ int stopAfter; /* -N, --stop-after */ int pageNumbers; /* -P, --page-numbers */ int corners; /* -R, --corners */ int shrinkMax; /* -S, --shrink */ int shrinkMin; /* -S, --shrink (if range specified) */ int unicode; /* -U, --unicode */ int gs1; /* -G, --gs1 */ int verbose; /* -v, --verbose */ } UserOptions; /* Functions */ static UserOptions GetDefaultOptions(void); static DmtxPassFail HandleArgs(UserOptions *opt, int *fileIndex, int *argcp, char **argvp[]); static void ShowUsage(int status); static DmtxPassFail SetDecodeOptions(DmtxDecode *dec, DmtxImage *img, UserOptions *opt); static DmtxPassFail PrintStats(DmtxDecode *dec, DmtxRegion *reg, DmtxMessage *msg, int imgPageIndex, UserOptions *opt); static DmtxPassFail PrintMessage(DmtxRegion *reg, DmtxMessage *msg, UserOptions *opt); static void CleanupMagick(MagickWand **wand, int magicError); static void ListImageFormats(void); static void WriteDiagnosticImage(DmtxDecode *dec, char *imagePath); static int ScaleNumberString(char *s, int extent); #endif dmtx-utils-0.7.6/dmtxwrite/000077500000000000000000000000001325607304600156735ustar00rootroot00000000000000dmtx-utils-0.7.6/dmtxwrite/Makefile.am000066400000000000000000000011701325607304600177260ustar00rootroot00000000000000AUTOMAKE_OPTIONS = subdir-objects AM_CPPFLAGS = -Wshadow -Wall -pedantic bin_PROGRAMS = dmtxwrite noinst_PROGRAMS = dmtxwrite.debug dmtxwrite_SOURCES = dmtxwrite.c dmtxwrite.h ../common/dmtxutil.c ../common/dmtxutil.h dmtxwrite_CFLAGS = $(DMTX_CFLAGS) $(MAGICK_CFLAGS) -D_MAGICK_CONFIG_H dmtxwrite_LDFLAGS = $(DMTX_LIBS) $(MAGICK_LIBS) dmtxwrite_LDADD = $(LIBOBJS) dmtxwrite_debug_SOURCES = dmtxwrite.c dmtxwrite.h ../common/dmtxutil.c ../common/dmtxutil.h dmtxwrite_debug_CFLAGS = $(DMTX_FLAGS) $(MAGICK_CFLAGS) -D_MAGICK_CONFIG_H dmtxwrite_debug_LDFLAGS = -static $(DMTX_LIBS) $(MAGICK_LIBS) dmtxwrite_debug_LDADD = $(LIBOBJS) dmtx-utils-0.7.6/dmtxwrite/dmtxwrite.c000066400000000000000000000534301325607304600200730ustar00rootroot00000000000000/* libdmtx - Data Matrix Encoding/Decoding Library Copyright (C) 2008, 2009 Mike Laughton 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 St, Fifth Floor, Boston, MA 02110-1301 USA Contact: mike@dragonflylogic.com */ #include "dmtxwrite.h" char *programName; /** * @brief Main function for the dmtxwrite Data Matrix scanning utility. * @param argc count of arguments passed from command line * @param argv list of argument passed strings from command line * @return Numeric exit code */ int main(int argc, char *argv[]) { int err; char *format; UserOptions opt; DmtxEncode *enc; unsigned char codeBuffer[DMTXWRITE_BUFFER_SIZE]; int codeBufferSize; opt = GetDefaultOptions(); /* Override defaults with requested options */ err = HandleArgs(&opt, &argc, &argv); if(err != DmtxPass) ShowUsage(EX_USAGE); /* Create and initialize libdmtx encoding struct */ enc = dmtxEncodeCreate(); if(enc == NULL) FatalError(EX_SOFTWARE, "create error"); /* Set output image properties */ dmtxEncodeSetProp(enc, DmtxPropPixelPacking, DmtxPack24bppRGB); dmtxEncodeSetProp(enc, DmtxPropImageFlip, DmtxFlipNone); dmtxEncodeSetProp(enc, DmtxPropRowPadBytes, 0); /* Set encoding options */ dmtxEncodeSetProp(enc, DmtxPropMarginSize, opt.marginSize); dmtxEncodeSetProp(enc, DmtxPropModuleSize, opt.moduleSize); dmtxEncodeSetProp(enc, DmtxPropScheme, opt.scheme); dmtxEncodeSetProp(enc, DmtxPropSizeRequest, opt.sizeIdx); if(opt.gs1 != DmtxUndefined) { dmtxEncodeSetProp(enc, DmtxPropFnc1, opt.gs1); } /* Read input data into buffer */ codeBufferSize = ReadInputData(codeBuffer, &opt); /* Create barcode image */ if(opt.mosaic == DmtxTrue) err = dmtxEncodeDataMosaic(enc, codeBufferSize, codeBuffer); else err = dmtxEncodeDataMatrix(enc, codeBufferSize, codeBuffer); if(err == DmtxFail) FatalError(EX_SOFTWARE, _("Unable to encode message (possibly too large for requested size)")); /* Write image file, but only if preview and codewords are not used */ if(opt.preview == DmtxTrue || opt.codewords == DmtxTrue) { if(opt.preview == DmtxTrue) WriteAsciiPreview(enc); if(opt.codewords == DmtxTrue) WriteCodewordList(enc); } else { format = GetImageFormat(&opt); if(format == NULL) format = "png"; if(StrNCmpI(format, "svg", 3) == DmtxTrue) WriteSvgFile(&opt, enc, format); else WriteImageFile(&opt, enc, format); } /* Clean up */ dmtxEncodeDestroy(&enc); exit(0); } /** * * */ static UserOptions GetDefaultOptions(void) { UserOptions opt; int white[3] = { 255, 255, 255 }; int black[3] = { 0, 0, 0 }; memset(&opt, 0x00, sizeof(UserOptions)); opt.inputPath = NULL; /* default stdin */ opt.outputPath = NULL; /* default stdout */ opt.format = NULL; opt.codewords = DmtxFalse; opt.marginSize = 10; opt.moduleSize = 5; opt.scheme = DmtxSchemeAutoBest; opt.preview = DmtxFalse; opt.rotate = 0; opt.sizeIdx = DmtxSymbolSquareAuto; memcpy(opt.color, black, sizeof(int) * 3); memcpy(opt.bgColor, white, sizeof(int) * 3); opt.mosaic = DmtxFalse; opt.dpi = DmtxUndefined; opt.verbose = DmtxFalse; opt.gs1 = DmtxUndefined; return opt; } /** * @brief Set and validate user-requested options from command line arguments. * @param opt runtime options from defaults or command line * @param argcp pointer to argument count * @param argvp pointer to argument list * @return DmtxPass | DmtxFail */ static DmtxPassFail HandleArgs(UserOptions *opt, int *argcp, char **argvp[]) { int err; int i; int optchr; int longIndex; char *ptr; struct option longOptions[] = { {"codewords", no_argument, NULL, 'c'}, {"module", required_argument, NULL, 'd'}, {"margin", required_argument, NULL, 'm'}, {"encoding", required_argument, NULL, 'e'}, {"format", required_argument, NULL, 'f'}, {"list-formats", no_argument, NULL, 'l'}, {"output", required_argument, NULL, 'o'}, {"preview", no_argument, NULL, 'p'}, {"resolution", required_argument, NULL, 'r'}, {"symbol-size", required_argument, NULL, 's'}, {"color", required_argument, NULL, 'C'}, {"bg-color", required_argument, NULL, 'B'}, {"mosaic", no_argument, NULL, 'M'}, {"rotate", required_argument, NULL, 'R'}, {"gs1", required_argument, NULL, 'G'}, {"verbose", no_argument, NULL, 'v'}, {"version", no_argument, NULL, 'V'}, {"help", no_argument, NULL, 0 }, {0, 0, 0, 0} }; programName = Basename((*argvp)[0]); for(;;) { optchr = getopt_long(*argcp, *argvp, "cd:m:e:f:lo:pr:s:C:B:MR:G:vV", longOptions, &longIndex); if(optchr == -1) break; switch(optchr) { case 0: /* --help */ ShowUsage(EX_OK); break; case 'c': opt->codewords = DmtxTrue; break; case 'd': err = StringToInt(&opt->moduleSize, optarg, &ptr); if(err != DmtxPass || opt->moduleSize <= 0 || *ptr != '\0') FatalError(EX_USAGE, _("Invalid module size specified \"%s\""), optarg); break; case 'm': err = StringToInt(&opt->marginSize, optarg, &ptr); if(err != DmtxPass || opt->marginSize <= 0 || *ptr != '\0') FatalError(EX_USAGE, _("Invalid margin size specified \"%s\""), optarg); break; case 'e': if(strlen(optarg) != 1) { fprintf(stderr, "Invalid encodation scheme \"%s\"\n", optarg); return DmtxFail; } switch(*optarg) { case 'b': opt->scheme = DmtxSchemeAutoBest; break; case 'f': opt->scheme = DmtxSchemeAutoFast; fprintf(stderr, "\"Fast optimized\" not implemented\n"); return DmtxFail; case 'a': opt->scheme = DmtxSchemeAscii; break; case 'c': opt->scheme = DmtxSchemeC40; break; case 't': opt->scheme = DmtxSchemeText; break; case 'x': opt->scheme = DmtxSchemeX12; break; case 'e': opt->scheme = DmtxSchemeEdifact; break; case '8': opt->scheme = DmtxSchemeBase256; break; default: fprintf(stderr, "Invalid encodation scheme \"%s\"\n", optarg); return DmtxFail; } break; case 'f': opt->format = optarg; break; case 'l': ListImageFormats(); exit(EX_OK); break; case 'o': if(strncmp(optarg, "-", 2) == 0) opt->outputPath = NULL; else opt->outputPath = optarg; break; case 'p': opt->preview = DmtxTrue; break; case 'r': err = StringToInt(&(opt->dpi), optarg, &ptr); if(err != DmtxPass || opt->dpi <= 0 || *ptr != '\0') FatalError(EX_USAGE, _("Invalid dpi specified \"%s\""), optarg); break; case 's': /* Determine correct barcode size and/or shape */ if(*optarg == 's') { opt->sizeIdx = DmtxSymbolSquareAuto; } else if(*optarg == 'r') { opt->sizeIdx = DmtxSymbolRectAuto; } else { for(i = 0; i < DmtxSymbolSquareCount + DmtxSymbolRectCount; i++) { if(strncmp(optarg, symbolSizes[i], 8) == 0) { opt->sizeIdx = i; break; } } if(i == DmtxSymbolSquareCount + DmtxSymbolRectCount) return DmtxFail; } break; case 'C': opt->color[0] = 0; opt->color[1] = 0; opt->color[2] = 0; fprintf(stderr, "Option \"%c\" not implemented\n", optchr); break; case 'B': opt->bgColor[0] = 255; opt->bgColor[1] = 255; opt->bgColor[2] = 255; fprintf(stderr, "Option \"%c\" not implemented\n", optchr); break; case 'M': opt->mosaic = DmtxTrue; break; case 'R': err = StringToInt(&(opt->rotate), optarg, &ptr); if(err != DmtxPass || *ptr != '\0') FatalError(EX_USAGE, _("Invalid rotation angle specified \"%s\""), optarg); break; case 'v': opt->verbose = DmtxTrue; break; case 'G': err = StringToInt(&(opt->gs1), optarg, &ptr); if(err != DmtxPass || opt->gs1 <= 0 || opt->gs1 > 255 || *ptr != '\0') FatalError(EX_USAGE, _("Invalid gs1 character specified \"%s\""), optarg); break; case 'V': fprintf(stderr, "%s version %s\n", programName, DmtxVersion); fprintf(stderr, "libdmtx version %s\n", dmtxVersion()); exit(0); break; default: return DmtxFail; break; } } opt->inputPath = (*argvp)[optind]; /* XXX here test for incompatibility between options. For example you cannot specify dpi if PNM output is requested */ return DmtxPass; } /** * * */ static size_t ReadInputData(unsigned char *codeBuffer, UserOptions *opt) { int fd; ssize_t bytesRead; size_t bytesReadTotal; /* Open file or stdin for reading */ fd = (opt->inputPath == NULL) ? 0 : open(opt->inputPath, O_RDONLY); if(fd == -1) FatalError(EX_IOERR, _("Error while opening file \"%s\""), opt->inputPath); /* Read input contents into buffer */ for(bytesReadTotal = 0;; bytesReadTotal += bytesRead) { bytesRead = read(fd, codeBuffer + bytesReadTotal, DMTXWRITE_BUFFER_SIZE); if(bytesRead == 0) break; if(bytesRead == -1) FatalError(EX_IOERR, _("Message read error")); else if(bytesReadTotal == DMTXWRITE_BUFFER_SIZE) FatalError(EX_DATAERR, _("Message to be encoded is too large")); } /* Close file only if not stdin */ if(fd != 0 && close(fd) != 0) FatalError(EX_IOERR, _("Error while closing file")); return bytesReadTotal; } /** * @brief Display program usage and exit with received status. * @param status error code returned to OS * @return void */ static void ShowUsage(int status) { if(status != 0) { fprintf(stderr, _("Usage: %s [OPTION]... [FILE]\n"), programName); fprintf(stderr, _("Try `%s --help' for more information.\n"), programName); } else { fprintf(stderr, _("Usage: %s [OPTION]... [FILE]\n"), programName); fprintf(stderr, _("\ Encode FILE or standard input and write Data Matrix image\n\ \n\ Example: %s message.txt -o message.png\n\ Example: echo -n 123456 | %s -o message.png\n\ \n\ OPTIONS:\n"), programName, programName); fprintf(stderr, _("\ -c, --codewords print codeword listing\n\ -d, --module=N module size (in pixels)\n\ -m, --margin=N margin size (in pixels)\n")); fprintf(stderr, _("\ -e, --encoding=[abcet8x] primary encodation scheme\n\ a = ASCII [default] b = Best optimized [beta]\n\ c = C40 e = EDIFACT\n\ t = Text 8 = Base 256\n\ x = X12\n")); fprintf(stderr, _("\ -f, --format=FORMAT PNG [default], TIF, GIF, PDF, etc...\n\ -l, --list-formats list supported image formats\n\ -o, --output=FILE output filename\n\ -p, --preview print ASCII art preview\n\ -r, --resolution=N set image print resolution (dpi)\n")); fprintf(stderr, _("\ -s, --symbol-size=[sr|RxC] symbol size (default \"s\")\n\ Automatic size options:\n\ s = Auto square r = Auto rectangle\n")); fprintf(stderr, _("\ Manual size options for square symbols:\n\ 10x10 12x12 14x14 16x16 18x18 20x20\n\ 22x22 24x24 26x26 32x32 36x36 40x40\n\ 44x44 48x48 52x52 64x64 72x72 80x80\n\ 88x88 96x96 104x104 120x120 132x132 144x144\n")); fprintf(stderr, _("\ Manual size options for rectangle symbols:\n\ 8x18 8x32 12x26 12x36 16x36 16x48\n")); fprintf(stderr, _("\ -C, --color=COLOR barcode color (not implemented)\n\ -B, --bg-color=COLOR background color (not implemented)\n\ -M, --mosaic create Data Mosaic (non-standard)\n")); fprintf(stderr, _("\ -R, --rotate=DEGREES rotation angle (degrees)\n\ -G, --gs1=N enable GS1 mode and define character to represent FNC1\n\ -v, --verbose use verbose messages\n\ -V, --version print version information\n\ --help display this help and exit\n")); fprintf(stderr, _("\nReport bugs to .\n")); } exit(status); } /** * * */ static void CleanupMagick(MagickWand **wand, int magickError) { char *excMessage; ExceptionType excSeverity; if(magickError == DmtxTrue) { excMessage = MagickGetException(*wand, &excSeverity); fprintf(stderr, "%s %s %lu %s\n", GetMagickModule(), excMessage); MagickRelinquishMemory(excMessage); } if(*wand != NULL) { DestroyMagickWand(*wand); *wand = NULL; } } /** * @brief List supported input image formats on stdout * @return void */ static void ListImageFormats(void) { int i, idx; int row, rowCount; int col, colCount; unsigned long totalCount; char **list; list = MagickQueryFormats("*", &totalCount); if(list == NULL) return; fprintf(stderr, "\n"); colCount = 7; rowCount = totalCount / colCount; if(totalCount % colCount) rowCount++; for(i = 0; i < colCount * rowCount; i++) { col = i % colCount; row = i / colCount; idx = col * rowCount + row; fprintf(stderr, "%10s", (idx < totalCount) ? list[col * rowCount + row] : " "); fprintf(stderr, "%s", (col + 1 < colCount) ? " " : "\n"); } fprintf(stderr, "\n"); MagickRelinquishMemory(list); } /** * * * */ static char * GetImageFormat(UserOptions *opt) { char *ptr = NULL; /* Derive format from filename extension */ if(opt->outputPath != NULL) { ptr = strrchr(opt->outputPath, '.'); if(ptr != NULL) ptr++; } /* Found filename extension but format was also provided */ if(ptr != NULL && strlen(ptr) > 0 && opt->format != NULL) fprintf(stderr, "WARNING: --format (-f) argument ignored; Format taken from filename\n"); /* If still undefined then use format argument */ if(ptr == NULL || strlen(ptr) == 0) ptr = opt->format; return ptr; } /** * * */ static DmtxPassFail WriteImageFile(UserOptions *opt, DmtxEncode *enc, char *format) { MagickBooleanType successA, successB; MagickWand *wand; char *outputPath; MagickWandGenesis(); wand = NewMagickWand(); if(wand == NULL) FatalError(EX_OSERR, "Undefined error"); successA = MagickConstituteImage(wand, enc->image->width, enc->image->height, "RGB", CharPixel, enc->image->pxl); if(successA == MagickFalse) { CleanupMagick(&wand, DmtxTrue); FatalError(EX_OSERR, "Undefined error"); } if(opt->dpi != DmtxUndefined) { successA = MagickSetImageResolution(wand, (double)opt->dpi, (double)opt->dpi); successB = MagickSetImageUnits(wand, PixelsPerInchResolution); if(successA == MagickFalse || successB == MagickFalse) { CleanupMagick(&wand, DmtxFalse); FatalError(EX_OSERR, "Illegal resolution \"%d\"", opt->dpi); } } successA = MagickSetImageFormat(wand, format); if(successA == MagickFalse) { CleanupMagick(&wand, DmtxFalse); FatalError(EX_OSERR, "Illegal format \"%s\"", format); } outputPath = (opt->outputPath == NULL) ? "-" : opt->outputPath; successA = MagickWriteImage(wand, outputPath); if(successA == MagickFalse) { CleanupMagick(&wand, DmtxTrue); FatalError(EX_OSERR, "Undefined error"); } CleanupMagick(&wand, DmtxFalse); MagickWandTerminus(); return DmtxPass; } /** * * */ static DmtxPassFail WriteSvgFile(UserOptions *opt, DmtxEncode *enc, char *format) { int col, row, rowInv; int symbolCols, symbolRows; int width, height, module; int defineOnly = DmtxFalse; unsigned char mosaicRed, mosaicGrn, mosaicBlu; char *idString = NULL; char style[100]; FILE *fp; if(StrNCmpI(format, "svg:", 4) == DmtxTrue) { defineOnly = DmtxTrue; idString = &format[4]; } if(idString == NULL || strlen(idString) == 0) idString = "dmtx_0001"; if(opt->outputPath == NULL) { fp = stdout; } else { fp = fopen(opt->outputPath, "wb"); if(fp == NULL) FatalError(EX_CANTCREAT, "Unable to create output file \"%s\"", opt->outputPath); } width = 2 * enc->marginSize + (enc->region.symbolCols * enc->moduleSize); height = 2 * enc->marginSize + (enc->region.symbolRows * enc->moduleSize); symbolCols = dmtxGetSymbolAttribute(DmtxSymAttribSymbolCols, enc->region.sizeIdx); symbolRows = dmtxGetSymbolAttribute(DmtxSymAttribSymbolRows, enc->region.sizeIdx); /* Print SVG Header */ if(defineOnly == DmtxFalse) { fprintf(fp, "\ \n\ \n\ \n\ \n", width, height); } fprintf(fp, " \n", idString); fprintf(fp, " Layout:%dx%d Symbol:%dx%d Data Matrix\n", width, height, symbolCols, symbolRows); /* Write Data Matrix ON modules */ for(row = 0; row < enc->region.symbolRows; row++) { rowInv = enc->region.symbolRows - row - 1; for(col = 0; col < enc->region.symbolCols; col++) { module = dmtxSymbolModuleStatus(enc->message, enc->region.sizeIdx, row, col); if(opt->mosaic == DmtxTrue) { mosaicRed = (module & DmtxModuleOnRed) ? 0x00 : 0xff; mosaicGrn = (module & DmtxModuleOnGreen) ? 0x00 : 0xff; mosaicBlu = (module & DmtxModuleOnBlue) ? 0x00 : 0xff; snprintf(style, 100, "style=\"fill:#%02x%02x%02x;fill-opacity:1;stroke:none\" ", mosaicRed, mosaicGrn, mosaicBlu); } else { style[0] = '\0'; } if(module & DmtxModuleOn) { fprintf(fp, " \n", opt->moduleSize, opt->moduleSize, col * opt->moduleSize + opt->marginSize, rowInv * opt->moduleSize + opt->marginSize, style); } } } fprintf(fp, " \n"); /* Close SVG document */ if(defineOnly == DmtxFalse) { fprintf(fp, "\ \n\ \n\ \n\ \n\ \n", idString); } return DmtxPass; } /** * * */ static DmtxPassFail WriteAsciiPreview(DmtxEncode *enc) { int symbolRow, symbolCol; fputc('\n', stdout); /* ASCII prints from top to bottom */ for(symbolRow = enc->region.symbolRows - 1; symbolRow >= 0; symbolRow--) { fputs(" ", stdout); for(symbolCol = 0; symbolCol < enc->region.symbolCols; symbolCol++) { fputs((dmtxSymbolModuleStatus(enc->message, enc->region.sizeIdx, symbolRow, symbolCol) & DmtxModuleOnRGB) ? "XX" : " ", stdout); } fputs("\n", stdout); } fputc('\n', stdout); return DmtxPass; } /** * * */ static DmtxPassFail WriteCodewordList(DmtxEncode *enc) { int i; int dataWordLength; int remainingDataWords; dataWordLength = dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, enc->region.sizeIdx); for(i = 0; i < enc->message->codeSize; i++) { remainingDataWords = dataWordLength - i; if(remainingDataWords > enc->message->padCount) fprintf(stdout, "%c:%03d\n", 'd', enc->message->code[i]); else if(remainingDataWords > 0) fprintf(stdout, "%c:%03d\n", 'p', enc->message->code[i]); else fprintf(stdout, "%c:%03d\n", 'e', enc->message->code[i]); } return DmtxPass; } /** * * */ static DmtxBoolean StrNCmpI(const char *s1, const char *s2, size_t n) { size_t i; if(s1 == NULL || s2 == NULL || n == 0) return DmtxFalse; for(i = 0; i < n; i++) { if(tolower(s1[i]) != tolower(s2[i])) return DmtxFalse; if(s1[i] == '\0' || s2[i] == '\0') break; } return DmtxTrue; } dmtx-utils-0.7.6/dmtxwrite/dmtxwrite.h000066400000000000000000000050221325607304600200720ustar00rootroot00000000000000/* libdmtx - Data Matrix Encoding/Decoding Library Copyright (C) 2008, 2009 Mike Laughton 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 St, Fifth Floor, Boston, MA 02110-1301 USA Contact: mike@dragonflylogic.com */ #ifndef __DMTXWRITE_H__ #define __DMTXWRITE_H__ #include #include #include #include #include #include #include #include #include #include #include #include #include "../common/dmtxutil.h" #ifdef IM_API_7 #include #else #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef _VISUALC_ #include #define snprintf sprintf_s #endif #if ENABLE_NLS # include # define _(String) gettext(String) #else # define _(String) String #endif #define N_(String) String #define DMTXWRITE_BUFFER_SIZE 4096 typedef struct { char *inputPath; char *outputPath; char *format; int codewords; int marginSize; int moduleSize; int scheme; int preview; int rotate; int sizeIdx; int color[3]; int bgColor[3]; int mosaic; int dpi; int gs1; int verbose; } UserOptions; static UserOptions GetDefaultOptions(void); static DmtxPassFail HandleArgs(UserOptions *opt, int *argcp, char **argvp[]); static size_t ReadInputData(unsigned char *codeBufferSize, UserOptions *opt); static void ShowUsage(int status); static void CleanupMagick(MagickWand **wand, int magickError); static void ListImageFormats(void); static char *GetImageFormat(UserOptions *opt); static DmtxPassFail WriteImageFile(UserOptions *opt, DmtxEncode *enc, char *format); static DmtxPassFail WriteSvgFile(UserOptions *opt, DmtxEncode *enc, char *format); static DmtxPassFail WriteAsciiPreview(DmtxEncode *enc); static DmtxPassFail WriteCodewordList(DmtxEncode *enc); static DmtxBoolean StrNCmpI(const char *s1, const char *s2, size_t n); #endif dmtx-utils-0.7.6/man/000077500000000000000000000000001325607304600144175ustar00rootroot00000000000000dmtx-utils-0.7.6/man/dmtxquery.1000077500000000000000000000031451325607304600165510ustar00rootroot00000000000000.\" Man page for the dmtxquery utility (libdmtx project). .\" .\" To view: $ groff -man -T ascii dmtxquery.1 | less .\" To text: $ groff -man -T ascii dmtxquery.1 | col -b | expand .\" .TH DMTXREAD 1 "June 2, 2011" .SH NAME dmtxquery \- extract information from dmtxread output .SH SYNOPSIS .B dmtxquery \fIPROPERTY\fP [\fIOPTION\fP]... [\fIFILE\fP]... .SH DESCRIPTION dmtxquery extracts information from the XML output from dmtxread for individual or grouped barcode scan results. .SH PROPERTY .PP barcode.count count of all barcodes found in image .PP barcode.\fBN\fP.\fBBPROP\fP print BPROP property of Nth barcode .PP message.count count of all messages found in image .PP message.\fBN\fP.\fBMPROP\fP print MPROP property of Nth message .PP message.\fBN\fP.barcode.count count of all barcodes in Nth message .PP message.\fBN\fP.barcode.\fBM\fP Mth barcode of Nth message, print all .PP message.\fBN\fP.barcode.\fBM\fP.\fBBPROP\fP Mth barcode of Nth message, print BPROP .PP \fBBPROP\fP barcode properties: message message_number message_position matrix_size data_codewords error_codewords rotation data_regions_count interleaved_blocks .PP \fBMPROP\fP message properties: message data_codeword error_codeword .SH OPTIONS .TP \fB\-V\fP, \fB\-\-version\fP Print program version information. .TP \fB\-\-help\fP Display this help message and quit. .SH STANDARDS ISO/IEC 16022:2000 .PP ANSI/AIM BC11 ISS .SH BUGS Email bug reports to \fImike@dragonflylogic.com\fP .SH AUTHOR Copyright (C) 2008, 2009 Mike Laughton .\" end of man page dmtx-utils-0.7.6/man/dmtxread.1000077500000000000000000000106461325607304600163230ustar00rootroot00000000000000.\" Man page for the dmtxread utility (libdmtx project). .\" .\" To view: $ groff -man -T ascii dmtxread.1 | less .\" To text: $ groff -man -T ascii dmtxread.1 | col -b | expand .\" .TH DMTXREAD 1 "June 2, 2011" .SH NAME dmtxread \- scan Data Matrix barcodes .SH SYNOPSIS .B dmtxread [\fIoptions\fP] [\fIFILE\fP]... .SH DESCRIPTION \fBdmtxread\fP searches the named input FILEs (or standard input if no files are named or the filename "-" is given) for ECC200 Data Matrix barcodes, reads their contents, and writes the decoded messages to standard output. .SH OPTIONS .TP \fB\-c\fP, \fB\-\-codewords\fP Only print the codewords extracted from a Data Matrix, and not the actual decoded message. .TP \fB\-e\fP, \fB\-\-minimum-edge=\fIN\fP\fP Pixel length of smallest expected edge in image. .TP \fB\-E\fP, \fB\-\-maximum-edge=\fIN\fP\fP Pixel length of largest expected edge in image. .TP \fB\-g\fP, \fB\-\-gap\fP=\fIN\fP Use scan grid with gap of \fIN\fP pixels (or less) between lines. .TP \fB\-l\fP, \fB\-\-list-formats\fP List the supported input image formats. .TP \fB\-m\fP, \fB\-\-milliseconds\fP=\fIN\fP Stop scan after N milliseconds (per image). .TP \fB\-n\fP, \fB\-\-newline\fP Print a newline character at the end of decoded data. .TP \fB\-p\fP, \fB\-\-page\fP=\fIN\fP Only scan Nth page of images. .TP \fB\-q\fP, \fB\-\-square-deviation\fP=\fIN\fP Maximum deviation (degrees) from squareness between adjacent barcode sides. Default value is N=40, but N=10 is recommended for flat applications like faxes and other scanned documents. Barcode regions found with corners <(90-N) or >(90+N) will be ignored by the decoder. .TP \fB\-r\fP, \fB\-\-resolution\fP=\fIN\fP Decoding resolution in dots per inch (DPI). Only used for vectorial input images such as SVG, PDF, etc... This option accepts a single argument (eg: 300) as well as horizontal and vertical resolutions (eg: 300x150). The default resolution is 72dpi. .TP \fB\-s\fP, \fB\-\-symbol-size\fP=\fI[asr|RxC]\fP Only consider barcodes of specific size or shape. a = All sizes [default] s = Only squares r = Only rectangles RxC = Exactly this many rows and columns (10x10, 8x18, etc...) .TP \fB\-t\fP, \fB\-\-threshold\fP=\fIN\fP Set the minimum edge threshold as a percentage of maximum. For example, an edge between a pure white and pure black pixel would have an intensity of 100. Edges with intensities below the indicated threshold will be ignored by the decoding process. Lowering the threshold will increase the amount of work to be done, but may be necessary for low contrast or blurry images. .TP \fB\-x\fP, \fB\-\-x-range-min\fP=\fIN[%]\fP Do not scan pixels to the left of pixel column N (or N%). .TP \fB\-X\fP, \fB\-\-x-range-max\fP=\fIN[%]\fP Do not scan pixels to the right of pixel column N (or N%). .TP \fB\-y\fP, \fB\-\-y-range-min\fP=\fIN[%]\fP Do not scan pixels below pixel row N (or N%). .TP \fB\-Y\fP, \fB\-\-y-range-max\fP=\fIN[%]\fP Do not scan pixels above pixel row N (or N%). .TP \fB\-C\fP, \fB\-\-corrections-max\fP=\fIN\fP Correct at most N errors per image (0 = correction disabled). .TP \fB\-D\fP, \fB\-\-diagnose\fP Make copy of image with additional diagnostic data. .TP \fB\-M\fP, \fB\-\-mosaic\fP (experimental) Interpret detected regions as Data Mosaic barcodes. .TP \fB\-N\fP, \fB\-\-stop-after\fP=\fIN\fP Stop scanning after Nth barcode is returned. .TP \fB\-P\fP, \fB\-\-page\-numbers\fP Print each decoded message with its fax/tiff page number. .TP \fB\-R\fP, \fB\-\-corners\fP Prefix the decoded message with the barcode's corner locations. .TP \fB\-S\fP, \fB\-\-shrink\fP=\fIN\fP Internally shrink image by factor of N. Shrinking is accomplished by skipping N-1 pixels at a time, often producing significantly faster scan times. It also improves scan success rate for images taken with poor camera focus provided the image is sufficiently large. .TP \fB\-U\fP, \fB\-\-unicode\fP Print Extended ASCII characters in UTF-8 Unicode. .TP \fB\-v\fP, \fB\-\-verbose\fP Use verbose messages. .TP \fB\-V\fP, \fB\-\-version\fP Print program version information. .TP \fB\-\-help\fP Display this help message and quit. .SH STANDARDS ISO/IEC 16022:2000 .PP ANSI/AIM BC11 ISS .SH DIAGNOSTICS Exit status has following possible meanings: 0 At least one barcode was found and decoded 1 No barcodes were found >1 Error occurred that prevented command from executing normally .SH BUGS Email bug reports to \fImike@dragonflylogic.com\fP .SH AUTHOR Copyright (C) 2008, 2009 Mike Laughton .\" end of man page dmtx-utils-0.7.6/man/dmtxwrite.1000077500000000000000000000052561325607304600165430ustar00rootroot00000000000000.\" Man page for the dmtxwrite utility (libdmtx project). .\" .\" To view: $ groff -man -T ascii dmtxwrite.1 | less .\" To text: $ groff -man -T ascii dmtxwrite.1 | col -b | expand .\" .TH DMTXWRITE 1 "June 2, 2011" .SH NAME dmtxwrite \- create Data Matrix barcodes .SH SYNOPSIS .B dmtxwrite [\fIOPTION\fP]... [FILE] .SH DESCRIPTION \fBdmtxwrite\fP encodes data from a file or standard input, and writes the resulting ECC200 Data Matrix barcode as an image. .SH OPTIONS .TP \fB\-c\fP, \fB\-\-codewords\fP Print codeword listing instead of creating barcode. .TP \fB\-d\fP, \fB\-\-module\fP=\fIN\fP Module size in pixels. .TP \fB\-m\fP, \fB\-\-margin\fP=\fIN\fP Margin size in pixels. .TP \fB\-e\fP, \fB\-\-encoding\fP=[bfactxe8] Encodation scheme. b = Best optimized best possible optimization (beta) f = Fast optimized basic optimization (not implemented) a = ASCII [default] ASCII standard & extended c = C40 digits and uppercase t = Text digits and lowercase x = X12 ANSI X12 EDI e = EDIFACT ASCII values 32-94 8 = Base 256 all byte values 0-255 .TP \fB\-f\fP, \fB\-\-format\fP=\fIFORMAT\fP Output image format (PNG [default], TIF, GIF, PDF, etc...). .TP \fB\-l\fP, \fB\-\-list-formats\fP List available image formats. .TP \fB\-o\fP, \fB\-\-output\fP=\fIFILE\fP Barcode output filename. Default is standard output. .TP \fB\-p\fP, \fB\-\-preview\fP Print ASCII art preview to standard output. .TP \fB\-r\fP, \fB\-\-resolution\fP=\fIN\fP Set image print resolution (dpi). .TP \fB\-s\fP, \fB\-\-symbol-size\fP=[sr|RxC] (default "s") Automatic symbol size options: s = Auto square r = Auto rectangle Manual symbol size options for square symbols: 10x10 12x12 14x14 16x16 18x18 20x20 22x22 24x24 26x26 32x32 36x36 40x40 44x44 48x48 52x52 64x64 72x72 80x80 88x88 96x96 104x104 120x120 132x132 144x144 Manually symbol size options for rectangle symbols: 8x18 8x32 12x26 12x36 16x36 16x48 .TP \fB\-C\fP, \fB\-\-color\fP=\fICOLOR\fP Barcode color (not implemented). .TP \fB\-B\fP, \fB\-\-bg-color\fP=\fICOLOR\fP Background color (not implemented). .TP \fB\-M\fP, \fB\-\-mosaic\fP Create non-standard Data Mosaic barcode. .TP \fB\-R\fP, \fB\-\-rotate\fP=\fIDEGREES\fP Rotation angle in degrees (not implemented). .TP \fB\-v\fP, \fB\-\-verbose\fP Use verbose messages. .TP \fB\-V\fP, \fB\-\-version\fP Print program version information. .TP \fB\-\-help\fP Display this help message and quit. .SH STANDARDS ISO/IEC 16022:2000 .PP ANSI/AIM BC11 ISS .SH BUGS Email bug reports to \fImike@dragonflylogic.com\fP .SH AUTHOR Copyright (C) 2008, 2009 Mike Laughton .\" end of man page dmtx-utils-0.7.6/script/000077500000000000000000000000001325607304600151505ustar00rootroot00000000000000dmtx-utils-0.7.6/script/check_all.sh000077500000000000000000000034051325607304600174160ustar00rootroot00000000000000#!/bin/sh function RunTest() { SCRIPT="$1" SCRIPT_TYPE=$(echo "$SCRIPT" | awk -F'.' '{print $NF}') echo " $SCRIPT" ERRORS=0 for dir in $(find "$DMTXUTILS" -type d); do if [[ "$dir" != "$DMTXUTILS" && "$dir" != "$DMTXUTILS/dmtxread" && "$dir" != "$DMTXUTILS/dmtxwrite" && "$dir" != "$DMTXUTILS/dmtxquery" ]]; then continue fi for file in $(find $dir -maxdepth 1); do EXT=$(echo $file | awk -F'.' '{print $NF}') if [[ "$EXT" != "c" && "$EXT" != "h" && "$EXT" != "sh" && \ "$EXT" != "py" && "$EXT" != "pl" ]]; then continue fi if [[ "$(basename $file)" = "config.h" || "$(basename $file)" = "ltmain.sh" ]]; then continue fi if [[ $(cat $file | wc -l) -le 10 ]]; then #echo " skipping \"$file\" (trivial file)" continue fi if [[ "$SCRIPT_TYPE" = "sh" ]]; then $DMTXUTILS/script/$SCRIPT $file ERRORS=$(( ERRORS + $? )) elif [[ "$SCRIPT_TYPE" = "pl" ]]; then PERL=$(which perl) if [[ $? -ne 0 ]]; then echo "No perl interpreter found. Skipping $SCRIPT test." else $PERL $DMTXUTILS/script/$SCRIPT $file ERRORS=$(( ERRORS + $? )) fi fi done done return $ERRORS } DMTXUTILS="$1" if [[ -z "$DMTXUTILS" || ! -d "$DMTXUTILS/script" ]]; then echo "Must provide valid DMTXUTILS directory" exit 1 fi RunTest check_comments.sh RunTest check_copyright.sh RunTest check_keyword.sh RunTest check_license.sh RunTest check_spacing.sh RunTest check_whitespace.sh RunTest check_headers.pl RunTest check_todo.sh exit 0 dmtx-utils-0.7.6/script/check_comments.sh000077500000000000000000000005111325607304600204660ustar00rootroot00000000000000#!/bin/sh FILE="$1" LINE=$(grep -n "\*\{10\}" $FILE) if [[ $? -eq 0 ]]; then echo -e "Bad comment style found in $FILE on line(s):\n$LINE" exit 1 fi LINE=$(sed -n -e '1 =' -e '2,$ p' $FILE | grep -n "^\/\*\$") if [[ $? -eq 0 ]]; then echo -e "Bad comment style found in $FILE on line(s):\n$LINE" exit 2 fi exit 0 dmtx-utils-0.7.6/script/check_copyright.sh000077500000000000000000000006171325607304600206600ustar00rootroot00000000000000#!/bin/sh FILE="$1" # Every nontrivial source file must include a copyright line COPYRIGHT=$(grep "Copyright (C) " $FILE) if [[ $? -ne 0 ]]; then echo "Missing copyright text in $FILE" exit 1 fi # Copyright line must contain the current year echo "$COPYRIGHT" | grep --silent $(date '+%Y') if [[ $? -ne 0 ]]; then echo "Missing or incorrect copyright year in $FILE" exit 2 fi exit 0 dmtx-utils-0.7.6/script/check_headers.pl000077500000000000000000000012211325607304600202540ustar00rootroot00000000000000#!/usr/bin/perl -w use strict; use File::Basename; # TODO: Test still misses first function of each file my $errorCount = 0; undef my $closeLineNbr; undef my $lineNbrs; while(<>) { chomp; if(m/^}$/) { $closeLineNbr = $.; } elsif(!defined($closeLineNbr) || m/^$/ || m/^\*/ || m/^#/) { next; } elsif(m/^\/\*\*$/) { undef $closeLineNbr; } else { $lineNbrs = (defined $lineNbrs) ? "$lineNbrs, $." : $.; $errorCount++; undef $closeLineNbr; } } if($errorCount > 0) { print "Missing header comment in file \"" . basename($ARGV) . "\" at line(s) $lineNbrs\n"; exit(1); } exit(0); dmtx-utils-0.7.6/script/check_license.sh000077500000000000000000000007751325607304600202770ustar00rootroot00000000000000#!/bin/sh FILE="$1" TEST1="^modify it under the terms of the GNU Lesser General Public\$" TEST2="^MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\. See the GNU\$" TEST3="^You should have received a copy of the GNU Lesser General Public\$" COUNT=0 grep --silent "$TEST1" $FILE COUNT=$(( COUNT + $? )) grep --silent "$TEST2" $FILE COUNT=$(( COUNT + $? )) grep --silent "$TEST3" $FILE COUNT=$(( COUNT + $? )) if [[ "$COUNT" -gt 0 ]]; then echo "Missing license text in $FILE" exit 1 fi exit 0 dmtx-utils-0.7.6/script/check_spacing.sh000077500000000000000000000017241325607304600202740ustar00rootroot00000000000000#!/bin/sh set -u FILE=$1 if [[ "$(basename $FILE)" = "dmtxfec.c" ]]; then exit 0 fi PATTERN="XX_C_XXXX_XXXX_XXX_XX_X_X_" COPYRIGHT=0 for i in $(seq 1 25); do LINE_TYPE=$(echo $PATTERN | cut -c$i) LINE_NBR=$((i + COPYRIGHT)) if [[ "$LINE_TYPE" = "C" ]]; then while true; do sed -n "$LINE_NBR p" $FILE | grep --silent "^Copyright" if [[ $? -eq 0 ]]; then COPYRIGHT=$((COPYRIGHT+1)) LINE_NBR=$((i + COPYRIGHT)) else COPYRIGHT=$((COPYRIGHT-1)) break fi done elif [[ "$LINE_TYPE" = "X" ]]; then sed -n "$LINE_NBR p" $FILE | grep --silent "^..*$" if [[ $? -ne 0 ]]; then echo "Expected line $LINE_NBR to be non-empty in $FILE" exit 1 fi else sed -n "$LINE_NBR p" $FILE | grep --silent "^$" if [[ $? -ne 0 ]]; then echo "Expected line $LINE_NBR to be empty in $FILE" exit 1 fi fi done exit 0 dmtx-utils-0.7.6/script/check_splint.sh000077500000000000000000000001401325607304600201500ustar00rootroot00000000000000#!/bin/sh #splint -linelen 999 -Disgreater -Disless dmtx.c splint -linelen 999 dmtx.c exit $? dmtx-utils-0.7.6/script/check_todo.sh000077500000000000000000000002671325607304600176160ustar00rootroot00000000000000#!/bin/sh FILE="$1" COUNT=$(grep -i -e "XXX" -e "TODO" -e "FIXME" $FILE | wc -l) if [[ "$COUNT" -gt 0 ]]; then printf "%4d TODO(s) remain in $FILE\n" $COUNT exit 1 fi exit 0 dmtx-utils-0.7.6/script/check_whitespace.sh000077500000000000000000000002411325607304600207750ustar00rootroot00000000000000#!/bin/sh FILE="$1" LINE=$(grep -n " $" $FILE) if [[ $? -eq 0 ]]; then echo -e "Trailing whitespace found in $FILE on line(s):\n$LINE" exit 1 fi exit 0 dmtx-utils-0.7.6/script/common_tasks.txt000066400000000000000000000045351325607304600204150ustar00rootroot00000000000000#!/make/me/a/sandwich Common Tasks ----------------------------------------------------------------- Generate splint warnings $ splint -posix-strict-lib dmtx.c Release Checklist ----------------------------------------------------------------- 1) o Include newly added files in lists below if appropriate 2) o Create copy of this file as living checklist 3) o Test for common style and formatting issues o $ script/check_all.sh . 4) o Review and close applicable bugs and feature requests 5) o Write and finalize release documentation o ChangeLog o KNOWNBUG o NEWS o TODO o README o README.freebsd o README.cygwin o README.mingw o README.linux o README.unix o README.osx o man/dmtxread.1 o man/dmtxwrite.1 o man/dmtxquery.1 6) o Update version number in appropriate files o configure.ac 7) o Update release date in appropriate files o TODO o man/dmtxquery.1 o man/dmtxread.1 o man/dmtxwrite.1 8) o Perform final test build o $ git status # no staged commits o $ git pull # get any pending updates o # final commit o $ sudo make uninstall && make clean && make distclean o $ ./autogen.sh && ./configure PKG_CONFIG_PATH=/usr/local/lib/pkgconfig && \ make && make check && sudo make install o # Run tests and confirm it works. Start step over if changes are needed. 9) o Build and test tarballs o $ cd .. o $ git clone git://libdmtx.git.sourceforge.net/gitroot/libdmtx/dmtx-utils release o $ cd release o $ rm -Rf .git o $ find . -type d -name ".git" o $ ./autogen.sh && ./configure PKG_CONFIG_PATH=/usr/local/lib/pkgconfig # don't build though o $ make dist-gzip o $ make dist-bzip2 o $ make dist-zip o # Verify no extraneous files made their way into the distribution o $ md5sum libdmtx-0.8.0.* > MD5SUM.txt 10) o SourceForge release administration o Upload files to SourceForge 11) o Tag final release in Git (do this only after uploading to SourceForge in case something changes at the last minute) o $ git tag -a -m "Tagged v0.7.4" v0.7.4 o $ git push origin --tags 12) o Update minor number in unstable trunk (e.g., 0.8.0 -> 0.8.1) o Use file list from step 6 above o $ ./autogen.sh o $ ./configure o $ git commit -a o $ git push