├── .github └── workflows │ └── build-and-test.yml ├── .gitignore ├── AUTHORS ├── CMakeLists.txt ├── ChangeLog ├── KNOWNBUG ├── LICENSE ├── Makefile.am ├── NEWS ├── README ├── README.cygwin ├── README.freebsd ├── README.linux ├── README.mingw ├── README.osx ├── README.unix ├── TODO ├── autogen.sh ├── configure.ac ├── dmtx.c ├── dmtx.h ├── dmtxbytelist.c ├── dmtxdecode.c ├── dmtxdecodescheme.c ├── dmtxencode.c ├── dmtxencodeascii.c ├── dmtxencodebase256.c ├── dmtxencodec40textx12.c ├── dmtxencodeedifact.c ├── dmtxencodeoptimize.c ├── dmtxencodescheme.c ├── dmtxencodestream.c ├── dmtximage.c ├── dmtxmatrix3.c ├── dmtxmessage.c ├── dmtxplacemod.c ├── dmtxreedsol.c ├── dmtxregion.c ├── dmtxscangrid.c ├── dmtxstatic.h ├── dmtxsymbol.c ├── dmtxtime.c ├── dmtxvector2.c ├── libdmtx.pc.in ├── man └── libdmtx.3 ├── script ├── check_all.sh ├── check_comments.sh ├── check_copyright.sh ├── check_headers.pl ├── check_license.sh ├── check_spacing.sh ├── check_splint.sh ├── check_todo.sh ├── check_whitespace.sh └── common_tasks.txt └── test ├── CMakeLists.txt ├── Makefile.am ├── compare_test ├── Makefile ├── TODO ├── compare_confirmed.sh ├── compare_confirmed │ ├── barcode_004_a.png │ ├── barcode_014_c.png │ └── barcode_060_e.png ├── compare_generated.sh ├── compare_siemens.sh ├── compare_siemens │ ├── siemens_000_8.png │ ├── siemens_000_a.png │ ├── siemens_000_c.png │ ├── siemens_000_f.png │ ├── siemens_000_t.png │ ├── siemens_001_8.png │ ├── siemens_001_a.png │ ├── siemens_001_c.png │ ├── siemens_001_f.png │ ├── siemens_001_t.png │ ├── siemens_002_8.png │ ├── siemens_002_a.png │ ├── siemens_002_c.png │ ├── siemens_002_f.png │ ├── siemens_002_t.png │ ├── siemens_003_8.png │ ├── siemens_003_a.png │ ├── siemens_003_c.png │ ├── siemens_003_f.png │ ├── siemens_003_t.png │ ├── siemens_004_8.png │ ├── siemens_004_a.png │ ├── siemens_004_c.png │ ├── siemens_004_f.png │ ├── siemens_004_t.png │ ├── siemens_005_8.png │ ├── siemens_005_a.png │ ├── siemens_005_c.png │ ├── siemens_005_f.png │ ├── siemens_005_t.png │ ├── siemens_006_8.png │ ├── siemens_006_a.png │ ├── siemens_006_c.png │ ├── siemens_006_f.png │ ├── siemens_006_t.png │ ├── siemens_007_8.png │ ├── siemens_007_a.png │ ├── siemens_007_c.png │ ├── siemens_007_f.png │ ├── siemens_007_t.png │ ├── siemens_008_8.png │ ├── siemens_008_a.png │ ├── siemens_008_c.png │ ├── siemens_008_f.png │ ├── siemens_008_t.png │ ├── siemens_009_8.png │ ├── siemens_009_a.png │ ├── siemens_009_c.png │ ├── siemens_009_f.png │ ├── siemens_009_t.png │ ├── siemens_010_8.png │ ├── siemens_010_a.png │ ├── siemens_010_c.png │ ├── siemens_010_f.png │ ├── siemens_010_t.png │ ├── siemens_011_8.png │ ├── siemens_011_a.png │ ├── siemens_011_c.png │ ├── siemens_011_f.png │ ├── siemens_011_t.png │ ├── siemens_012_8.png │ ├── siemens_012_a.png │ ├── siemens_012_c.png │ ├── siemens_012_f.png │ ├── siemens_012_t.png │ ├── siemens_013_8.png │ ├── siemens_013_a.png │ ├── siemens_013_c.png │ ├── siemens_013_f.png │ └── siemens_013_t.png └── input_messages │ ├── message_000.dat │ ├── message_001.dat │ ├── message_002.dat │ ├── message_003.dat │ ├── message_004.dat │ ├── message_005.dat │ ├── message_006.dat │ ├── message_007.dat │ ├── message_008.dat │ ├── message_009.dat │ ├── message_010.dat │ ├── message_011.dat │ ├── message_012.dat │ ├── message_013.dat │ ├── message_014.dat │ ├── message_015.dat │ ├── message_016.dat │ ├── message_017.dat │ ├── message_018.dat │ ├── message_019.dat │ ├── message_020.dat │ ├── message_021.dat │ ├── message_022.dat │ ├── message_023.dat │ ├── message_024.dat │ ├── message_025.dat │ ├── message_026.dat │ ├── message_027.dat │ ├── message_028.dat │ ├── message_029.dat │ ├── message_030.dat │ ├── message_031.dat │ ├── message_032.dat │ ├── message_033.dat │ ├── message_034.dat │ ├── message_035.dat │ ├── message_036.dat │ ├── message_037.dat │ ├── message_038.dat │ ├── message_039.dat │ ├── message_040.dat │ ├── message_041.dat │ ├── message_042.dat │ ├── message_043.dat │ ├── message_044.dat │ ├── message_045.dat │ ├── message_046.dat │ ├── message_047.dat │ ├── message_048.dat │ ├── message_049.dat │ ├── message_050.dat │ ├── message_051.dat │ ├── message_052.dat │ ├── message_053.dat │ ├── message_054.dat │ ├── message_055.dat │ ├── message_056.dat │ ├── message_057.dat │ ├── message_058.dat │ ├── message_059.dat │ └── message_060.dat ├── multi_test ├── Makefile.am ├── _kiss_fft_guts.h ├── dmtx.c ├── dmtxaccel.c ├── dmtxdecode2.c ├── dmtxhough.c ├── dmtxregion2.c ├── dmtxsobel.c ├── dmtxvaluegrid.c ├── kiss_fft.c ├── kiss_fft.h ├── kiss_fftr.c ├── kiss_fftr.h ├── multi_test.c ├── multi_test.h └── visualize.c ├── rotate_test ├── Makefile.am ├── README ├── callback.c ├── callback.h ├── display.c ├── display.h ├── dmtx.c ├── image.c ├── image.h ├── images │ ├── test_image01.png │ ├── test_image02.png │ ├── test_image03.png │ ├── test_image04.png │ ├── test_image05.png │ ├── test_image06.png │ ├── test_image07.png │ ├── test_image08.png │ ├── test_image09.png │ ├── test_image10.png │ ├── test_image11.png │ ├── test_image12.png │ ├── test_image13.png │ ├── test_image14.png │ ├── test_image15.png │ ├── test_image16.png │ ├── test_image17.png │ └── test_image18.png ├── rotate_test.c └── rotate_test.h ├── simple_test ├── Makefile.am └── simple_test.c └── unit_test ├── Makefile.am └── unit_test.c /.github/workflows/build-and-test.yml: -------------------------------------------------------------------------------- 1 | # libdmtx - Data Matrix Encoding/Decoding Library 2 | # 3 | # Copyright 2008, 2009 Mike Laughton. All rights reserved. 4 | # Copyright 2012-2025 Vadim A. Misbakh-Soloviov. All rights reserved. 5 | # Copyright 2016 Tim Zaman. All rights reserved. 6 | # 7 | # See LICENSE file in the main project directory for full 8 | # terms of use and distribution. 9 | # 10 | # Contact: 11 | # Vadim A. Misbakh-Soloviov 12 | # Mike Laughton 13 | 14 | name: Check that project builds and tests are passing 15 | 16 | "on": 17 | push: 18 | branches: [master, main] 19 | pull_request: 20 | branches: [master, main] 21 | 22 | workflow_dispatch: 23 | 24 | 25 | jobs: 26 | autotools_standard: 27 | name: Checking autotools build (default) 28 | 29 | strategy: 30 | matrix: 31 | os: [ubuntu-latest] 32 | 33 | runs-on: ${{ matrix.os }} 34 | 35 | steps: 36 | - uses: actions/checkout@v3 37 | - name: Run autogen 38 | run: ./autogen.sh 39 | - name: Run Configure 40 | run: ./configure --enable-static=yes --enable-shared=yes 41 | - name: Build 42 | run: make 43 | - name: Build and run tests 44 | run: | 45 | make check 46 | cd test/simple_test 47 | ./simple_test 48 | 49 | autotools_with_reader_prog: 50 | name: Checking autotools build (with 'Reader Programming' feature) 51 | 52 | strategy: 53 | matrix: 54 | os: [ubuntu-latest] 55 | 56 | runs-on: ${{ matrix.os }} 57 | 58 | steps: 59 | - uses: actions/checkout@v3 60 | - name: Run autogen 61 | run: ./autogen.sh 62 | - name: Run Configure 63 | run: ./configure --enable-static=yes --enable-shared=yes --enable-reader-programming 64 | - name: Build and run tests 65 | run: | 66 | make check 67 | cd test/simple_test 68 | ./simple_test 69 | 70 | cmake_standard: 71 | name: Checking CMake build (default) 72 | 73 | strategy: 74 | matrix: 75 | os: [ubuntu-latest] 76 | 77 | runs-on: ${{ matrix.os }} 78 | 79 | steps: 80 | - uses: actions/checkout@v3 81 | - name: Create build directory 82 | run: mkdir build 83 | - name: Configure 84 | working-directory: build 85 | run: cmake -DDMTX_SHARED=ON -DDMTX_STATIC=ON -DBUILD_TESTING=ON .. 86 | - name: Build 87 | working-directory: build 88 | run: cmake --build . --verbose 89 | # - name: Run Unit Test 90 | # working-directory: build/test 91 | # run: ./test_unit 92 | - name: Run Simple Test 93 | working-directory: build/test 94 | run: ./test_simple 95 | 96 | 97 | cmake_with_reader_prog: 98 | name: Checking CMake build (with 'Reader Programming' feature) 99 | 100 | strategy: 101 | matrix: 102 | os: [ubuntu-latest] 103 | 104 | runs-on: ${{ matrix.os }} 105 | 106 | steps: 107 | - uses: actions/checkout@v3 108 | - name: Create build directory 109 | run: mkdir build 110 | - name: Configure 111 | working-directory: build 112 | run: cmake -DDMTX_READER_PROGRAMMING=ON -DDMTX_SHARED=ON -DDMTX_STATIC=ON -DBUILD_TESTING=ON .. 113 | - name: Build 114 | working-directory: build 115 | run: cmake --build . --verbose 116 | # - name: Run Unit Test 117 | # working-directory: build/test 118 | # run: ./test_unit 119 | - name: Run Simple Test 120 | working-directory: build/test 121 | run: ./test_simple 122 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Mike Laughton 2 | Mackenzie Straight 3 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(DMTX VERSION 0.7.9 LANGUAGES C) 3 | 4 | set(DEFAULT_SHARED_LIBS "ON") 5 | if(DEFINED BUILD_SHARED_LIBS AND NOT BUILD_SHARED_LIBS STREQUAL "") 6 | set(DEFAULT_SHARED_LIBS "${BUILD_SHARED_LIBS}") 7 | endif() 8 | option(DMTX_SHARED "Build DMTX as shared library" "${DEFAULT_SHARED_LIBS}") 9 | if(DMTX_SHARED) 10 | add_library(dmtx_shared SHARED "dmtx.c") 11 | if (MSVC) 12 | set_target_properties(dmtx_shared PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON) 13 | else() 14 | set_target_properties(dmtx_shared PROPERTIES 15 | VERSION ${PROJECT_VERSION} 16 | SOVERSION ${PROJECT_VERSION_MAJOR} 17 | ) 18 | target_link_libraries(dmtx_shared PUBLIC m) 19 | endif() 20 | set_target_properties(dmtx_shared PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/dmtx.h" OUTPUT_NAME "dmtx") 21 | install(TARGETS dmtx_shared LIBRARY ARCHIVE RUNTIME PUBLIC_HEADER) 22 | endif() 23 | 24 | set(DEFAULT_STATIC_LIBS "ON") # XXX: ON for now, will default to OFF someday later (maybe on 0.7.9/0.8) 25 | if(DEFINED BUILD_STATIC_LIBS AND NOT BUILD_STATIC_LIBS STREQUAL "") 26 | set(DEFAULT_STATIC_LIBS "${BUILD_STATIC_LIBS}") 27 | endif() 28 | option(DMTX_STATIC "Build DMTX as static library" "${DEFAULT_STATIC_LIBS}") 29 | if(DMTX_STATIC) 30 | add_library(dmtx_static STATIC "dmtx.c") 31 | if (MSVC) 32 | set_target_properties(dmtx_static PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON) 33 | else() 34 | target_link_libraries(dmtx_static PUBLIC m) 35 | endif() 36 | set_target_properties(dmtx_static PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/dmtx.h" OUTPUT_NAME "dmtx") 37 | install(TARGETS dmtx_static LIBRARY ARCHIVE RUNTIME PUBLIC_HEADER) 38 | endif() 39 | 40 | option(DMTX_READER_PROGRAMMING "Enable reader programming feature (adds breaking changes to API)" OFF) 41 | if(DMTX_READER_PROGRAMMING) 42 | add_compile_definitions(HAVE_READER_PROGRAMMING) 43 | endif() 44 | 45 | add_compile_definitions(VERSION="${PROJECT_VERSION}") 46 | 47 | # Add support for tests if DMTX is the main project 48 | if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) 49 | option(BUILD_TESTING "Build tests" OFF) 50 | if(BUILD_TESTING) 51 | add_subdirectory("test") 52 | endif() 53 | include(CTest) 54 | endif() 55 | 56 | # vim: ft=cmake ts=2 sw=2 sts=2 et 57 | -------------------------------------------------------------------------------- /KNOWNBUG: -------------------------------------------------------------------------------- 1 | Bugs in libdmtx 2 | ----------------------------------------------------------------- 3 | 4 | 1. libdmtx - Core Library 5 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 6 | 7 | While regular encoder works fine, the optimizer feature (--best) 8 | still occasionally generates codeword sequences that are not 100% 9 | legal according to the ISO specification. Everything still 10 | appears to decode properly, but until I have time to go through 11 | every corner case and validate the behavior this will be treated 12 | as an experimental feature. For now dmtxwrite will encode using 13 | a straight ASCII scheme by default. 14 | 15 | Data Mosaic encoding doesn't produce output for certain sizes: 16 | 17 | $ echo -n foo | dmtxwrite -M <-- works 18 | $ echo -n fooo | dmtxwrite -M <-- doesn't work 19 | $ echo -n foooo | dmtxwrite -M <-- works 20 | 21 | 22 | 2. Test Programs 23 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 24 | 25 | multi_test: 26 | * No known issues (not included in general download) 27 | 28 | rotate_test: 29 | * No known issues (not included in general download) 30 | 31 | simple_test: 32 | * No known issues 33 | 34 | unit_test: 35 | * Missing files (not included in general download) 36 | 37 | 38 | 3. Scripts in the script directory 39 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 40 | 41 | The check_headers.pl script verifies that every function has 42 | a correctly-formed header comment. But the test condition is 43 | currently pretty simple, and does not test the first function 44 | appearing in each file. 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2005-2016 Mike Laughton, Vadim A. Misbakh-Soloviov and others. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | The views and conclusions contained in the software and documentation are those 26 | of the authors and should not be interpreted as representing official policies, 27 | either expressed or implied, of the libdmtx project. 28 | 29 | -------------------------------------------------------------------------------- 30 | 31 | ALTERNATE TERMS 32 | 33 | Redistributions in binary form, with or without modification, are permitted 34 | without including the above copyright notice, list of conditions, and disclaimer 35 | if express written permission has been obtained from Dragonfly Logic, Inc. 36 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | # Packaging commands (all run from libdmtx root): 2 | # $ make distclean 3 | # $ make dist-bzip2 4 | # $ make dist-gzip 5 | 6 | AUTOMAKE_OPTIONS = foreign 7 | 8 | ACLOCAL_AMFLAGS = -I m4 9 | AM_CPPFLAGS = -Wshadow -Wall -pedantic -std=c99 10 | 11 | lib_LTLIBRARIES = libdmtx.la 12 | libdmtx_la_SOURCES = dmtx.c 13 | libdmtx_la_CFLAGS = -Wall -pedantic 14 | 15 | EXTRA_libdmtx_la_SOURCES = dmtxencode.c dmtxencodestream.c dmtxencodescheme.c \ 16 | dmtxencodeoptimize.c dmtxencodeascii.c dmtxencodec40textx12.c \ 17 | dmtxencodeedifact.c dmtxencodebase256.c dmtxdecode.c dmtxdecodescheme.c \ 18 | dmtxmessage.c dmtxregion.c dmtxsymbol.c dmtxplacemod.c dmtxreedsol.c \ 19 | dmtxscangrid.c dmtximage.c dmtxbytelist.c dmtxtime.c dmtxvector2.c \ 20 | dmtxmatrix3.c dmtxstatic.h 21 | 22 | include_HEADERS = dmtx.h 23 | 24 | SUBDIRS = . test 25 | 26 | dist_man_MANS = man/libdmtx.3 27 | 28 | EXTRA_DIST = KNOWNBUG \ 29 | LICENSE \ 30 | README.cygwin \ 31 | README.freebsd \ 32 | README.linux \ 33 | README.mingw \ 34 | README.osx \ 35 | README.unix \ 36 | m4 \ 37 | script/check_all.sh \ 38 | script/check_comments.sh \ 39 | script/check_copyright.sh \ 40 | script/check_headers.pl \ 41 | script/check_license.sh \ 42 | script/check_spacing.sh \ 43 | script/check_splint.sh \ 44 | script/check_todo.sh \ 45 | script/check_whitespace.sh 46 | 47 | pkgconfigdir = $(libdir)/pkgconfig 48 | pkgconfig_DATA = libdmtx.pc 49 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | 26-May-2011: New official download page available 2 | 17-Mar-2011: Core library relicensed to Simplified BSD with waiver option 3 | 03-Mar-2011: libdmtx code now in SourceForge GIT repositories 4 | 29-Nov-2010: libdmtx binaries now available as official Fedora package 5 | 18-Nov-2009: Mikko Koppanen released improved PHP bindings for libdmtx 6 | 05-Nov-2009: "Onion" released a Gstreamer element using libdmtx 7 | 04-Sep-2009: New release: libdmtx-0.7.2 (Release Notes) 8 | 06-Aug-2009: Simon Wood released pyDataMatrixScanner at SourceForge 9 | 03-Aug-2009: Evan Nemerson added Vala support with a new wrapper 10 | 31-Jul-2009: libdmtx Documentation wiki moved to libdmtx.wikidot.com 11 | 19-May-2009: libdmtx project discussed in Linux Journal (March 2009) 12 | 12-Mar-2009: Python wrapper supports multi-barcode scans (thanks Simon!) 13 | 02-Mar-2009: New release: libdmtx-0.7.0 (Release Notes) 14 | 31-Jan-2009: Experimental libdmtx Windows binaries now available 15 | 23-Nov-2008: New release: libdmtx-0.6.0 (Release Notes) 16 | 08-Oct-2008: Olivier Guilyardi added support for all major image formats! (SVN) 17 | 04-Sep-2008: New release: libdmtx-0.5.2 (README) 18 | 20-Aug-2008: Significant performance gains available in SVN (latest tarball) 19 | 01-Jul-2008: New release: libdmtx-0.5.1 (README) 20 | 29-Jun-2008: libdmtx.org now hosted on a super efficient fit-PC 21 | 03-Jun-2008: New iPhone reader by Stefan Hafeneger (no jailbreak required) 22 | 31-May-2008: New libdmtx mailing lists replace forums 23 | 30-May-2008: GeoWeb does it again: CameraDMTX for Nokia N60 24 | 27-May-2008: Et tu, Cognex? 25 | 22-May-2008: Congratulations Cognex! Good guys 2, patent trolls 0 26 | 16-Apr-2008: New documentation wiki. Everyone can contribute! 27 | 13-Apr-2008: 5th release: libdmtx-0.5.0 (README) 28 | 22-Feb-2008: New phone video, this time on Symbian S60 29 | 15-Jan-2008: Unofficial .debs now available (thanks pcitizen!) 30 | 21-Dec-2007: Check out Martin's iDMTX video! 31 | 07-Dec-2007: 4th release: libdmtx-0.4.0 (README) 32 | 02-Dec-2007: Good news: Project is ACTIVE - new release soon 33 | 16-Aug-2007: Added new screenshots to show progress during freeze 34 | 30-Nov-2006: Bad news: Downloads have been halted (explanation) 35 | 15-Oct-2006: 3rd release: libdmtx-0.3.0 (README) 36 | 13-Sep-2006: Unstable version now available from CVS (instructions) 37 | 07-Sep-2006: Now taking feature requests for next release 38 | 11-Jun-2006: 2nd release: libdmtx-0.2.0 (view README file before using) 39 | 22-Apr-2006: 1st release: libdmtx-0.1.0 (view README file before using) 40 | 12-Mar-2006: Project home page changed hosting 41 | 24-Jan-2006: ISO/IEC 16022:2000 specification arrived in the mail 42 | 25-Nov-2005: Project home page libdmtx.sourceforge.net created 43 | 22-Nov-2005: SourceForge project created 44 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | ================================================================= 2 | libdmtx - Open Source Data Matrix Software 3 | ================================================================= 4 | 5 | libdmtx README file (all platforms) 6 | 7 | This summary of the libdmtx package applies generally to all 8 | platforms. For instructions regarding your specific platform, 9 | also see the README.xxx file in this directory that matches your 10 | system (e.g., README.linux, README.osx, etc...). 11 | 12 | 13 | 1. Introduction 14 | ----------------------------------------------------------------- 15 | 16 | libdmtx is a software library that enables programs to read and 17 | write Data Matrix barcodes of the modern ECC200 variety. The 18 | library runs natively on several platforms and can be accessed by 19 | multiple languages using the libdmtx language wrappers. The 20 | utility programs dmtxread and dmtxwrite also provide a command 21 | line interface for libdmtx, and serve as a good reference for 22 | developers writing their own libdmtx-enabled programs. 23 | 24 | This package (libdmtx) contains only the core library, and is 25 | distributed under a Simplified BSD license with an alternate 26 | waiver option. See the LICENSE file in the main project directory 27 | for full terms of use and distribution. 28 | 29 | The non-library components related to libdmtx are available as 30 | separate downloads, and are distributed under a different license 31 | (typically LGPLv2). Please contact support@dragonflylogic.com if 32 | you require clarification on licensing. It's not complicated, but 33 | it's important to us that all license terms are respected (not 34 | just ours). 35 | 36 | 37 | 2. Project Components 38 | ----------------------------------------------------------------- 39 | 40 | The libdmtx project serves a diverse audience and contains many 41 | components -- some of which may not be useful to you. Components 42 | fall into one of four categories: 43 | 44 | Description Package Audience 45 | ----------------- ------------- ---------------------- 46 | Core library libdmtx libdmtx programs 47 | Test programs libdmtx libdmtx developers 48 | Utility programs dmtx-utils Shell and command line 49 | Language Wrappers dmtx-wrappers Non-C/C++ developers 50 | 51 | 52 | 3. Installation 53 | ----------------------------------------------------------------- 54 | 55 | libdmtx uses GNU Autotools so installation should be familiar to 56 | free software veterans. If your platform cannot easily run the 57 | Autotools scripts, refer to the appropriate platform-specific 58 | README.xxx located in this directory for alternate instructions. 59 | 60 | In theory the following 3 steps would build and install libdmtx 61 | on your system: 62 | 63 | $ ./configure 64 | $ make 65 | $ sudo make install 66 | 67 | However, you may need to install additional software or make 68 | other changes for these steps to work properly. The details below 69 | will help to address errors and/or customize beyond the defaults. 70 | 71 | Problems with "configure" step 72 | ---------------------------------------- 73 | If you obtained libdmtx from Git you may have received an error 74 | like "./configure: No such file or directory". Run this command 75 | before trying again: 76 | 77 | $ ./autogen.sh 78 | 79 | The autogen.sh command requires autoconf, automake, libtool, and 80 | pkgconfig to be installed on your system. 81 | 82 | The configure script also offers many options for customizing the 83 | build process, described in detail by running: 84 | 85 | $ ./configure --help 86 | 87 | Problems with "make" step 88 | ---------------------------------------- 89 | Errors encountered during the "make" step are often a result of 90 | missing software dependencies. Install any missing software 91 | mentioned in the error message(s) and try again. 92 | 93 | Problems with "sudo make install" step 94 | ---------------------------------------- 95 | If the 'sudo' command is not configured on your system, you can 96 | alternatively yell "Yeeehaww!" as you log in as root and run it 97 | like this: 98 | 99 | # make install 100 | 101 | And finally... 102 | ---------------------------------------- 103 | If you want to verify that everything is working properly you can 104 | optionally build the test programs: 105 | 106 | $ make check 107 | 108 | This command will not perform any tests, but will build the 109 | programs that contain test logic: multi_test, rotate_test, 110 | simple_test, and unit_test. 111 | 112 | Note: multi_test and rotate_test contain extra dependencies due 113 | to their graphical nature, and are not terribly useful unless you 114 | need to test the library's internals. 115 | 116 | 117 | 5. Contact 118 | ----------------------------------------------------------------- 119 | 120 | Documentation wiki: libdmtx.wikidot.com 121 | GitHub page: github.com/dmtx/libdmtx 122 | OhLoh.net page: www.ohloh.net/projects/libdmtx 123 | Open mailing list: libdmtx-open_discussion@lists.sourceforge.net 124 | 125 | 126 | 6. This Document 127 | ----------------------------------------------------------------- 128 | 129 | This document is derived from the wiki page located at: 130 | 131 | http://libdmtx.wikidot.com/general-instructions 132 | 133 | If you find an error or have additional helpful information, 134 | please edit the wiki directly with your updates. 135 | -------------------------------------------------------------------------------- /README.cygwin: -------------------------------------------------------------------------------- 1 | ================================================================= 2 | libdmtx - Open Source Data Matrix Software 3 | ================================================================= 4 | 5 | libdmtx README file (Cygwin) 6 | 7 | This README.cygwin file contains information on installing and 8 | using libdmtx on Windows in a Cygwin environment. The general 9 | README file, also found in this directory, contains a high level 10 | summary of libdmtx and its components. 11 | 12 | 13 | 1. Installing libdmtx on Windows using Cygwin 14 | ----------------------------------------------------------------- 15 | 16 | libdmtx can be installed on Cygwin using the instructions 17 | provided in the general README file. However, please see below 18 | for additional details that might benefit users on this platform. 19 | 20 | 21 | 2. Dependencies 22 | ----------------------------------------------------------------- 23 | 24 | The following packages must be installed to compile libdmtx on 25 | Cygwin: 26 | 27 | * gcc 28 | * make 29 | * automake 30 | * pkg-config 31 | 32 | Also, if libdmtx was obtained from Git: 33 | 34 | * autoconf 35 | * libtool 36 | 37 | 38 | 3. This Document 39 | ----------------------------------------------------------------- 40 | 41 | This document is derived from the wiki page located at: 42 | 43 | http://libdmtx.wikidot.com/libdmtx-on-windows-using-cygwin 44 | 45 | If you find an error or have additional helpful information, 46 | please edit the wiki directly with your updates. 47 | -------------------------------------------------------------------------------- /README.freebsd: -------------------------------------------------------------------------------- 1 | ================================================================= 2 | libdmtx - Open Source Data Matrix Software 3 | ================================================================= 4 | 5 | libdmtx README file (FreeBSD) 6 | 7 | This README.freebsd file contains information on installing and 8 | using libdmtx on FreeBSD. The general README file, also found in 9 | this directory, contains a high level summary of libdmtx and its 10 | components. 11 | 12 | 13 | 1. Installing libdmtx on FreeBSD 14 | ----------------------------------------------------------------- 15 | 16 | libdmtx can be installed on FreeBSD using the instructions 17 | provided in the general README file. However, please read below 18 | for additional details that might benefit users on this platform. 19 | 20 | 21 | 2. Running configure 22 | ----------------------------------------------------------------- 23 | 24 | FreeBSD users may need to export the CPPFLAGS and LDFLAGS 25 | variables as follows before running configure: 26 | 27 | $ export CPPFLAGS=-I/usr/local/include 28 | $ export LDFLAGS=-L/usr/local/lib 29 | $ ./configure 30 | $ make 31 | $ sudo make install 32 | 33 | 34 | 3. This Document 35 | ----------------------------------------------------------------- 36 | 37 | This document is derived from the wiki page located at: 38 | 39 | http://libdmtx.wikidot.com/libdmtx-on-freebsd 40 | 41 | If you find an error or have additional helpful information, 42 | please edit the wiki directly with your updates. 43 | -------------------------------------------------------------------------------- /README.linux: -------------------------------------------------------------------------------- 1 | ================================================================= 2 | libdmtx - Open Source Data Matrix Software 3 | ================================================================= 4 | 5 | libdmtx README file (GNU/Linux) 6 | 7 | This README.linux file contains information on installing and 8 | using libdmtx on GNU/Linux. The general README file, also found 9 | in this directory, contains a high level summary of libdmtx and 10 | its components. 11 | 12 | 13 | 1. Installing libdmtx on GNU/Linux 14 | ----------------------------------------------------------------- 15 | 16 | libdmtx can be installed on Linux using the instructions provided 17 | in the general README file. However, please see below for 18 | additional details that might benefit users on this platform. 19 | 20 | 21 | 2. Pre-Compiled Binaries 22 | ----------------------------------------------------------------- 23 | 24 | Many Linux distributions offer pre-compiled libdmtx binaries in 25 | their package repositories. This can be a real time saver if you 26 | aren't required to build from source for other reasons. 27 | 28 | 29 | 3. This Document 30 | ----------------------------------------------------------------- 31 | 32 | This document is derived from the wiki page located at: 33 | 34 | http://libdmtx.wikidot.com/libdmtx-on-gnu-linux 35 | 36 | If you find an error or have additional helpful information, 37 | please edit the wiki directly with your updates. 38 | -------------------------------------------------------------------------------- /README.mingw: -------------------------------------------------------------------------------- 1 | ================================================================= 2 | libdmtx - Open Source Data Matrix Software 3 | ================================================================= 4 | 5 | libdmtx README file (MinGW) 6 | 7 | This README.mingw file contains information on installing and 8 | using libdmtx using MinGW. The general README file, also found in 9 | this directory, contains a high level summary of libdmtx and its 10 | components. 11 | 12 | 13 | 1. Installing libdmtx on Windows using MinGW and MSYS 14 | ----------------------------------------------------------------- 15 | 16 | libdmtx can be installed on MinGW using the instructions provided 17 | in the general README file. However, please see below for 18 | additional details that might benefit users on this platform. 19 | 20 | 21 | 2. Installing MinGW and MSYS 22 | ----------------------------------------------------------------- 23 | 24 | If you haven't done so already, first install MinGW, MSYS, and 25 | all recommended updates to your Windows system. Instructions for 26 | doing this are provided here: 27 | 28 | http://www.mingw.org/wiki/msys 29 | 30 | 31 | 3. Building and installing the core library 32 | ----------------------------------------------------------------- 33 | 34 | To install libdmtx, download and unpack the libdmtx source to 35 | your MSYS folder. If you accepted the installation defaults this 36 | will be C:\msys\1.0. 37 | 38 | Open the MSYS shell and run the following: 39 | 40 | $ ./configure 41 | $ make 42 | $ sudo make install 43 | 44 | Go to folder .libs: 45 | 46 | $ cd .libs 47 | $ ls 48 | 49 | Now you should see following output: 50 | 51 | libdmtx.a libdmtx.la libdmtx.lai libdmtx_la-dmtx.o 52 | 53 | Finally run: 54 | 55 | $ gcc -shared -o dmtx.dll libdmtx_la-dmtx.o -Wl,--out-implib,libdmtx.a 56 | 57 | Now you should have working dmtx.dll in the folder .libs. 58 | 59 | 60 | 3.1. Building and installing the core library from different folder 61 | ------------------------------------------------------------------- 62 | 63 | Recent MSYS2 installation uses C:\msys64 root folder, To build libdmtx: 64 | 65 | 1. install the MSYS2 packages: 66 | 67 | $ pacman -S --needed base-devel mingw-w64-x86_64-toolchain autoconf automake make libtool 68 | 69 | Details on how to install and setup MSYS2 environment on Windows can be found `here `_ 70 | and `here `_ . 71 | 72 | 2. clone git repository 73 | 3. open msys2 console and add msys' mingw64 bin folder to path environment variable 74 | 75 | $ export PATH=$PATH:/c/msys64/mingw64/bin 76 | 77 | 4. to create configure script, run 78 | $ ./autogen.sh 79 | 80 | 5. open the configure file and put as very first instruction the following one 81 | LDFLAGS="-Wl,-no-undefined" 82 | 83 | 6. from within the libdmtx folder, run 84 | 85 | $ ./configure 86 | $ make 87 | 88 | Now, into .libs subfolder, you should find following files: 89 | 90 | libdmtx.a libdmtx.la libdmtx.lai libdmtx_la-dmtx.o 91 | 92 | Then finally run: 93 | 94 | $ gcc -shared -o dmtx.dll libdmtx_la-dmtx.o -Wl,--out-implib,libdmtx.a 95 | 96 | Now you should have working dmtx.dll in the folder .libs. 97 | 98 | 99 | 4. This Document 100 | ----------------------------------------------------------------- 101 | 102 | This document is derived from the wiki page located at: 103 | 104 | http://libdmtx.wikidot.com/libdmtx-on-windows-using-mingw 105 | 106 | If you find an error or have additional helpful information, 107 | please edit the wiki directly with your updates. 108 | -------------------------------------------------------------------------------- /README.osx: -------------------------------------------------------------------------------- 1 | ================================================================= 2 | libdmtx - Open Source Data Matrix Software 3 | ================================================================= 4 | 5 | libdmtx README file (Mac OS X) 6 | 7 | This README.osx file contains information on installing and using 8 | libdmtx on Mac OS X. The general README file, also found in this 9 | directory, contains a high level summary of libdmtx and its 10 | components. 11 | 12 | 13 | 1. Installing libdmtx on Mac OS X 14 | ----------------------------------------------------------------- 15 | 16 | libdmtx can be installed on OS X using the instructions provided 17 | in the general README file. However, please see below for 18 | additional details that might benefit users on this platform. 19 | 20 | 21 | 2. Universal Binaries 22 | ----------------------------------------------------------------- 23 | 24 | You can tweak configure's parameters to build an Universal Binary 25 | version of the library. Recommendations are provided at: 26 | 27 | http://developer.apple.com/technotes/tn2005/tn2137.html 28 | 29 | 30 | 3. Dependencies 31 | ----------------------------------------------------------------- 32 | 33 | Compiling from Git requires a working autoconf/pkg-config setup: 34 | 35 | * autoconf, automake, libtool, and pkgconfig are required to 36 | generate the configure script. These packages are available 37 | from MacPorts. 38 | 39 | * You may run into issues if you mix the autotools packages in 40 | MacPorts with the ones installed from Xcode Tools. Make sure 41 | /opt/local/bin appears before /usr/bin in your $PATH. 42 | 43 | 44 | 4. This Document 45 | ----------------------------------------------------------------- 46 | 47 | This document is derived from the wiki page located at: 48 | 49 | http://libdmtx.wikidot.com/libdmtx-on-mac-os-x 50 | 51 | If you find an error or have additional helpful information, 52 | please edit the wiki directly with your updates. 53 | -------------------------------------------------------------------------------- /README.unix: -------------------------------------------------------------------------------- 1 | ================================================================= 2 | libdmtx - Open Source Data Matrix Software 3 | ================================================================= 4 | 5 | libdmtx README file (Unix) 6 | 7 | This README.unix file contains information on installing and 8 | using libdmtx on Unix. The general README file, also found in 9 | this directory, contains a high level summary of libdmtx and its 10 | components. 11 | 12 | 13 | 1. Installing libdmtx on Unix 14 | ----------------------------------------------------------------- 15 | 16 | libdmtx can be installed on Unix using the instructions provided 17 | in the general README file. However, please see below for 18 | additional details that might benefit users on this platform. 19 | 20 | 21 | 2. Known Issues 22 | ----------------------------------------------------------------- 23 | 24 | libdmtx is known to work on the following commercial Unix 25 | versions: 26 | 27 | * AIX 28 | * HP-UX 29 | * Solaris 30 | 31 | However, building libdmtx from source on these operating systems 32 | can be tricky due to their non-GNU conventions. 33 | 34 | 35 | 3. This Document 36 | ----------------------------------------------------------------- 37 | 38 | This document is derived from the wiki page located at: 39 | 40 | http://libdmtx.wikidot.com/libdmtx-on-unix 41 | 42 | If you find an error or have additional helpful information, 43 | please edit the wiki directly with your updates. 44 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Create empty m4 directory if missing 4 | if [ ! -d "m4" ]; then 5 | echo "autogen.sh: creating empty m4 directory" 6 | mkdir m4 7 | fi 8 | 9 | echo "autogen.sh: running autoreconf" 10 | autoreconf --force --install 11 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT([libdmtx], [0.7.9], [https://github.com/dmtx/libdmtx/issues], [libdmtx], [https://github.com/dmtx/libdmtx]) 2 | AM_INIT_AUTOMAKE([-Wall -Werror]) 3 | 4 | AC_CONFIG_MACRO_DIR([m4]) 5 | AC_CONFIG_HEADERS([config.h]) 6 | AC_CONFIG_FILES([ 7 | Makefile 8 | libdmtx.pc 9 | test/Makefile 10 | test/simple_test/Makefile 11 | ]) 12 | 13 | AC_PROG_CC 14 | AC_PROG_LIBTOOL 15 | AM_PROG_CC_C_O 16 | 17 | 18 | AC_ARG_ENABLE([reader_programming], [AS_HELP_STRING([--enable-reader-programming], [Enable Reader Programming breaking feature.])], [], [enable_reader_programming=no] ) 19 | AS_IF([test "x$enable_reader_programming" = "xyes"], [ 20 | AC_DEFINE([HAVE_READER_PROGRAMMING], [1], [Reader Programming breaking feature.]) 21 | ]) 22 | 23 | 24 | AC_SEARCH_LIBS([sin], [m] ,[], AC_MSG_ERROR([libdmtx requires libm])) 25 | AC_SEARCH_LIBS([cos], [m] ,[], AC_MSG_ERROR([libdmtx requires libm])) 26 | AC_SEARCH_LIBS([atan2], [m] ,[], AC_MSG_ERROR([libdmtx requires libm])) 27 | 28 | AC_CHECK_HEADERS([sys/time.h]) 29 | AC_CHECK_FUNCS([gettimeofday]) 30 | 31 | case $target_os in 32 | cygwin*) 33 | ARCH=cygwin ;; 34 | darwin*) 35 | ARCH=macosx ;; 36 | freebsd*) 37 | ARCH=freebsd ;; 38 | linux-gnu*) 39 | ARCH=linux-gnu ;; 40 | mingw32*) 41 | ARCH=mingw32 ;; 42 | esac 43 | AM_CONDITIONAL([TARGET_MACOSX], [test x$ARCH = xmacosx]) 44 | 45 | AC_OUTPUT 46 | -------------------------------------------------------------------------------- /dmtx.c: -------------------------------------------------------------------------------- 1 | /** 2 | * libdmtx - Data Matrix Encoding/Decoding Library 3 | * Copyright 2008, 2009 Mike Laughton. All rights reserved. 4 | * Copyright 2012-2016 Vadim A. Misbakh-Soloviov. All rights reserved. 5 | * 6 | * See LICENSE file in the main project directory for full 7 | * terms of use and distribution. 8 | * 9 | * Contact: 10 | * Vadim A. Misbakh-Soloviov 11 | * Mike Laughton 12 | * 13 | * \file dmtx.c 14 | * \brief Main libdmtx source file 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #ifdef HAVE_CONFIG_H 29 | #include "config.h" 30 | #endif 31 | 32 | #include "dmtx.h" 33 | #include "dmtxstatic.h" 34 | 35 | #ifndef CALLBACK_POINT_PLOT 36 | #define CALLBACK_POINT_PLOT(a,b,c,d) 37 | #endif 38 | 39 | #ifndef CALLBACK_POINT_XFRM 40 | #define CALLBACK_POINT_XFRM(a,b,c,d) 41 | #endif 42 | 43 | #ifndef CALLBACK_MODULE 44 | #define CALLBACK_MODULE(a,b,c,d,e) 45 | #endif 46 | 47 | #ifndef CALLBACK_MATRIX 48 | #define CALLBACK_MATRIX(a) 49 | #endif 50 | 51 | #ifndef CALLBACK_FINAL 52 | #define CALLBACK_FINAL(a,b) 53 | #endif 54 | 55 | /** 56 | * Use #include to merge the individual .c source files into a single combined 57 | * file during preprocessing. This allows the project to be organized in files 58 | * of like-functionality while still keeping a clean namespace. Specifically, 59 | * internal functions can be static without losing the ability to access them 60 | * "externally" from the other source files in this list. 61 | */ 62 | 63 | #include "dmtxencode.c" 64 | #include "dmtxencodestream.c" 65 | #include "dmtxencodescheme.c" 66 | #include "dmtxencodeoptimize.c" 67 | #include "dmtxencodeascii.c" 68 | #include "dmtxencodec40textx12.c" 69 | #include "dmtxencodeedifact.c" 70 | #include "dmtxencodebase256.c" 71 | 72 | #include "dmtxdecode.c" 73 | #include "dmtxdecodescheme.c" 74 | 75 | #include "dmtxmessage.c" 76 | #include "dmtxregion.c" 77 | #include "dmtxsymbol.c" 78 | #include "dmtxplacemod.c" 79 | #include "dmtxreedsol.c" 80 | #include "dmtxscangrid.c" 81 | 82 | #include "dmtximage.c" 83 | #include "dmtxbytelist.c" 84 | #include "dmtxtime.c" 85 | #include "dmtxvector2.c" 86 | #include "dmtxmatrix3.c" 87 | 88 | extern char * 89 | dmtxVersion(void) 90 | { 91 | return DmtxVersion; 92 | } 93 | 94 | extern DmtxBoolean 95 | dmtxHasReaderProgramming(void) 96 | { 97 | #ifdef HAVE_READER_PROGRAMMING 98 | return DmtxTrue; 99 | #else 100 | return DmtxFalse; 101 | #endif 102 | } 103 | -------------------------------------------------------------------------------- /dmtxbytelist.c: -------------------------------------------------------------------------------- 1 | /** 2 | * libdmtx - Data Matrix Encoding/Decoding Library 3 | * Copyright 2010 Mike Laughton. All rights reserved. 4 | * Copyright 2012-2016 Vadim A. Misbakh-Soloviov. All rights reserved. 5 | * 6 | * See LICENSE file in the main project directory for full 7 | * terms of use and distribution. 8 | * 9 | * Contact: 10 | * Vadim A. Misbakh-Soloviov 11 | * Mike Laughton 12 | * 13 | * \file file.c 14 | */ 15 | 16 | /** 17 | * 18 | * 19 | */ 20 | extern DmtxByteList 21 | dmtxByteListBuild(DmtxByte *storage, int capacity) 22 | { 23 | DmtxByteList list; 24 | 25 | list.b = storage; 26 | list.capacity = capacity; 27 | list.length = 0; 28 | 29 | return list; 30 | } 31 | 32 | /** 33 | * 34 | * 35 | */ 36 | extern void 37 | dmtxByteListInit(DmtxByteList *list, int length, DmtxByte value, DmtxPassFail *passFail) 38 | { 39 | if(length > list->capacity) 40 | { 41 | *passFail = DmtxFail; 42 | } 43 | else 44 | { 45 | list->length = length; 46 | memset(list->b, value, sizeof(DmtxByte) * list->capacity); 47 | *passFail = DmtxPass; 48 | } 49 | } 50 | 51 | /** 52 | * 53 | * 54 | */ 55 | extern void 56 | dmtxByteListClear(DmtxByteList *list) 57 | { 58 | memset(list->b, 0x00, sizeof(DmtxByte) * list->capacity); 59 | list->length = 0; 60 | } 61 | 62 | /** 63 | * 64 | * 65 | */ 66 | extern DmtxBoolean 67 | dmtxByteListHasCapacity(DmtxByteList *list) 68 | { 69 | return (list->length < list->capacity) ? DmtxTrue : DmtxFalse; 70 | } 71 | 72 | /** 73 | * 74 | * 75 | */ 76 | extern void 77 | dmtxByteListCopy(DmtxByteList *dst, const DmtxByteList *src, DmtxPassFail *passFail) 78 | { 79 | int length; 80 | 81 | if(dst->capacity < src->length) 82 | { 83 | *passFail = DmtxFail; /* dst must be large enough to hold src data */ 84 | } 85 | else 86 | { 87 | /* Copy as many bytes as dst can hold or src can provide (smaller of two) */ 88 | length = (dst->capacity < src->capacity) ? dst->capacity : src->capacity; 89 | 90 | dst->length = src->length; 91 | memcpy(dst->b, src->b, sizeof(unsigned char) * length); 92 | *passFail = DmtxPass; 93 | } 94 | } 95 | 96 | /** 97 | * 98 | * 99 | */ 100 | extern void 101 | dmtxByteListPush(DmtxByteList *list, DmtxByte value, DmtxPassFail *passFail) 102 | { 103 | if(list->length >= list->capacity) 104 | { 105 | *passFail = DmtxFail; 106 | } 107 | else 108 | { 109 | list->b[list->length++] = value; 110 | *passFail = DmtxPass; 111 | } 112 | } 113 | 114 | /** 115 | * 116 | * 117 | */ 118 | extern DmtxByte 119 | dmtxByteListPop(DmtxByteList *list, DmtxPassFail *passFail) 120 | { 121 | *passFail = (list->length > 0) ? DmtxPass : DmtxFail; 122 | 123 | return list->b[--(list->length)]; 124 | } 125 | 126 | /** 127 | * 128 | * 129 | */ 130 | extern void 131 | dmtxByteListPrint(DmtxByteList *list, char *prefix) 132 | { 133 | int i; 134 | 135 | if(prefix != NULL) 136 | fprintf(stdout, "%s", prefix); 137 | 138 | for(i = 0; i < list->length; i++) 139 | fprintf(stdout, " %d", list->b[i]); 140 | 141 | fputc('\n', stdout); 142 | } 143 | -------------------------------------------------------------------------------- /dmtxencodeascii.c: -------------------------------------------------------------------------------- 1 | /** 2 | * libdmtx - Data Matrix Encoding/Decoding Library 3 | * Copyright 2011 Mike Laughton. All rights reserved. 4 | * Copyright 2012-2016 Vadim A. Misbakh-Soloviov. All rights reserved. 5 | * 6 | * See LICENSE file in the main project directory for full 7 | * terms of use and distribution. 8 | * 9 | * Contact: 10 | * Vadim A. Misbakh-Soloviov 11 | * Mike Laughton 12 | * 13 | * \file dmtxencodeascii.c 14 | * \brief ASCII encoding rules 15 | */ 16 | 17 | /** 18 | * Simple single scheme encoding uses "Normal" 19 | * The optimizer needs to track "Expanded" and "Compact" streams separately, so they 20 | * are called explicitly. 21 | * 22 | * Normal: Automatically collapses 2 consecutive digits into one codeword 23 | * Expanded: Uses a whole codeword to represent a digit (never collapses) 24 | * Compact: Collapses 2 digits into a single codeword or marks the stream 25 | * invalid if either values are not digits 26 | * 27 | * \param stream 28 | * \param option [Expanded|Compact|Normal] 29 | */ 30 | static void 31 | EncodeNextChunkAscii(DmtxEncodeStream *stream, int option) 32 | { 33 | DmtxByte v0, v1; 34 | DmtxBoolean compactDigits; 35 | 36 | if(StreamInputHasNext(stream)) 37 | { 38 | v0 = StreamInputAdvanceNext(stream); CHKERR; 39 | 40 | if((option == DmtxEncodeCompact || option == DmtxEncodeNormal) && 41 | StreamInputHasNext(stream)) 42 | { 43 | v1 = StreamInputPeekNext(stream); CHKERR; 44 | 45 | /* Check for FNC1 character */ 46 | if(stream->fnc1 != DmtxUndefined && (int)v1 == stream->fnc1) 47 | { 48 | v1 = 0; 49 | compactDigits = DmtxFalse; 50 | } 51 | else 52 | compactDigits = (ISDIGIT(v0) && ISDIGIT(v1)) ? DmtxTrue : DmtxFalse; 53 | } 54 | else /* option == DmtxEncodeFull */ 55 | { 56 | v1 = 0; 57 | compactDigits = DmtxFalse; 58 | } 59 | 60 | if(compactDigits == DmtxTrue) 61 | { 62 | /* Two adjacent digit chars: Make peek progress official and encode */ 63 | StreamInputAdvanceNext(stream); CHKERR; 64 | AppendValueAscii(stream, 10 * (v0-'0') + (v1-'0') + 130); CHKERR; 65 | } 66 | else if(option == DmtxEncodeCompact) 67 | { 68 | /* Can't compact non-digits */ 69 | StreamMarkInvalid(stream, DmtxErrorCantCompactNonDigits); 70 | } 71 | else 72 | { 73 | /* Encode single ASCII value */ 74 | if(stream->fnc1 != DmtxUndefined && (int)v0 == stream->fnc1) 75 | { 76 | /* FNC1 */ 77 | AppendValueAscii(stream, DmtxValueFNC1); CHKERR; 78 | } 79 | else if(v0 < 128) 80 | { 81 | /* Regular ASCII */ 82 | AppendValueAscii(stream, v0 + 1); CHKERR; 83 | } 84 | else 85 | { 86 | /* Extended ASCII */ 87 | AppendValueAscii(stream, DmtxValueAsciiUpperShift); CHKERR; 88 | AppendValueAscii(stream, v0 - 127); CHKERR; 89 | } 90 | } 91 | } 92 | } 93 | 94 | /** 95 | * this code is separated from EncodeNextChunkAscii() because it needs to be 96 | * called directly elsewhere 97 | */ 98 | static void 99 | AppendValueAscii(DmtxEncodeStream *stream, DmtxByte value) 100 | { 101 | CHKSCHEME(DmtxSchemeAscii); 102 | 103 | StreamOutputChainAppend(stream, value); CHKERR; 104 | stream->outputChainValueCount++; 105 | } 106 | 107 | /** 108 | * 109 | * 110 | */ 111 | static void 112 | CompleteIfDoneAscii(DmtxEncodeStream *stream, int sizeIdxRequest) 113 | { 114 | int sizeIdx; 115 | 116 | if(stream->status == DmtxStatusComplete) 117 | return; 118 | 119 | if(!StreamInputHasNext(stream)) 120 | { 121 | sizeIdx = FindSymbolSize(stream->output->length, sizeIdxRequest); CHKSIZE; 122 | PadRemainingInAscii(stream, sizeIdx); CHKERR; 123 | StreamMarkComplete(stream, sizeIdx); 124 | } 125 | } 126 | 127 | /** 128 | * Can we just receive a length to pad here? I don't like receiving 129 | * sizeIdxRequest (or sizeIdx) this late in the game 130 | */ 131 | static void 132 | PadRemainingInAscii(DmtxEncodeStream *stream, int sizeIdx) 133 | { 134 | int symbolRemaining; 135 | DmtxByte padValue; 136 | 137 | CHKSCHEME(DmtxSchemeAscii); 138 | CHKSIZE; 139 | 140 | symbolRemaining = GetRemainingSymbolCapacity(stream->output->length, sizeIdx); 141 | 142 | /* First pad character is not randomized */ 143 | if(symbolRemaining > 0) 144 | { 145 | padValue = DmtxValueAsciiPad; 146 | StreamOutputChainAppend(stream, padValue); CHKERR; 147 | symbolRemaining--; 148 | } 149 | 150 | /* All remaining pad characters are randomized based on character position */ 151 | while(symbolRemaining > 0) 152 | { 153 | padValue = Randomize253State(DmtxValueAsciiPad, stream->output->length + 1); 154 | StreamOutputChainAppend(stream, padValue); CHKERR; 155 | symbolRemaining--; 156 | } 157 | } 158 | 159 | /** 160 | * consider receiving instantiated DmtxByteList instead of the output components 161 | */ 162 | static DmtxByteList 163 | EncodeTmpRemainingInAscii(DmtxEncodeStream *stream, DmtxByte *storage, 164 | int capacity, DmtxPassFail *passFail) 165 | { 166 | DmtxEncodeStream streamAscii; 167 | DmtxByteList output = dmtxByteListBuild(storage, capacity); 168 | 169 | /* Create temporary copy of stream that writes to storage */ 170 | streamAscii = *stream; 171 | streamAscii.currentScheme = DmtxSchemeAscii; 172 | streamAscii.outputChainValueCount = 0; 173 | streamAscii.outputChainWordCount = 0; 174 | streamAscii.reason = NULL; 175 | streamAscii.sizeIdx = DmtxUndefined; 176 | streamAscii.status = DmtxStatusEncoding; 177 | streamAscii.output = &output; 178 | 179 | while(dmtxByteListHasCapacity(streamAscii.output)) 180 | { 181 | if(StreamInputHasNext(&streamAscii)) 182 | EncodeNextChunkAscii(&streamAscii, DmtxEncodeNormal); /* No CHKERR */ 183 | else 184 | break; 185 | } 186 | 187 | /* 188 | * We stopped encoding before attempting to write beyond output boundary so 189 | * any stream errors are truly unexpected. The passFail status indicates 190 | * whether output.length can be trusted by the calling function. 191 | */ 192 | 193 | if(streamAscii.status == DmtxStatusInvalid || streamAscii.status == DmtxStatusFatal) 194 | *passFail = DmtxFail; 195 | else 196 | *passFail = DmtxPass; 197 | 198 | return output; 199 | } 200 | 201 | /** 202 | * \brief Randomize 253 state 203 | * \param codewordValue 204 | * \param codewordPosition 205 | * \return Randomized value 206 | */ 207 | static DmtxByte 208 | Randomize253State(DmtxByte cwValue, int cwPosition) 209 | { 210 | int pseudoRandom, tmp; 211 | 212 | pseudoRandom = ((149 * cwPosition) % 253) + 1; 213 | tmp = cwValue + pseudoRandom; 214 | if(tmp > 254) 215 | tmp -= 254; 216 | 217 | assert(tmp >= 0 && tmp < 256); 218 | 219 | return (DmtxByte)tmp; 220 | } 221 | -------------------------------------------------------------------------------- /dmtxencodeedifact.c: -------------------------------------------------------------------------------- 1 | /** 2 | * libdmtx - Data Matrix Encoding/Decoding Library 3 | * Copyright 2011 Mike Laughton. All rights reserved. 4 | * Copyright 2012-2016 Vadim A. Misbakh-Soloviov. All rights reserved. 5 | * 6 | * See LICENSE file in the main project directory for full 7 | * terms of use and distribution. 8 | * 9 | * Contact: 10 | * Vadim A. Misbakh-Soloviov 11 | * Mike Laughton 12 | * 13 | * \file dmtxencodeedifact.c 14 | * \brief Edifact encoding rules 15 | */ 16 | 17 | /** 18 | * 19 | * 20 | */ 21 | static void 22 | EncodeNextChunkEdifact(DmtxEncodeStream *stream) 23 | { 24 | DmtxByte value; 25 | 26 | if(StreamInputHasNext(stream)) 27 | { 28 | /* Check for FNC1 character, which needs to be sent in ASCII */ 29 | value = StreamInputPeekNext(stream); CHKERR; 30 | 31 | if((value < 32 || value > 94)) { 32 | StreamMarkInvalid(stream, DmtxChannelUnsupportedChar); 33 | return; 34 | } 35 | 36 | if (stream->fnc1 != DmtxUndefined && (int)value == stream->fnc1) { 37 | EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchExplicit); CHKERR; 38 | 39 | StreamInputAdvanceNext(stream); CHKERR; 40 | AppendValueAscii(stream, DmtxValueFNC1); CHKERR; 41 | return; 42 | } 43 | 44 | value = StreamInputAdvanceNext(stream); CHKERR; 45 | AppendValueEdifact(stream, value); CHKERR; 46 | } 47 | } 48 | 49 | /** 50 | * 51 | * 52 | */ 53 | static void 54 | AppendValueEdifact(DmtxEncodeStream *stream, DmtxByte value) 55 | { 56 | DmtxByte edifactValue, previousOutput; 57 | 58 | CHKSCHEME(DmtxSchemeEdifact); 59 | 60 | /* 61 | * TODO: KECA -> korean, circles 62 | * TODO: UNOX -> ISO-2022-JP 63 | * TODO: and so on 64 | */ 65 | if(value < 31 || value > 94) 66 | { 67 | StreamMarkInvalid(stream, DmtxChannelUnsupportedChar); 68 | return; 69 | } 70 | 71 | edifactValue = (value & 0x3f) << 2; 72 | 73 | switch(stream->outputChainValueCount % 4) 74 | { 75 | case 0: 76 | StreamOutputChainAppend(stream, edifactValue); CHKERR; 77 | break; 78 | case 1: 79 | previousOutput = StreamOutputChainRemoveLast(stream); CHKERR; 80 | StreamOutputChainAppend(stream, previousOutput | (edifactValue >> 6)); CHKERR; 81 | StreamOutputChainAppend(stream, edifactValue << 2); CHKERR; 82 | break; 83 | case 2: 84 | previousOutput = StreamOutputChainRemoveLast(stream); CHKERR; 85 | StreamOutputChainAppend(stream, previousOutput | (edifactValue >> 4)); CHKERR; 86 | StreamOutputChainAppend(stream, edifactValue << 4); CHKERR; 87 | break; 88 | case 3: 89 | previousOutput = StreamOutputChainRemoveLast(stream); CHKERR; 90 | StreamOutputChainAppend(stream, previousOutput | (edifactValue >> 2)); CHKERR; 91 | break; 92 | } 93 | 94 | stream->outputChainValueCount++; 95 | } 96 | 97 | /** 98 | * Complete EDIFACT encoding if it matches a known end-of-symbol condition. 99 | * 100 | * Term Clean Symbol ASCII Codeword 101 | * Cond Bound Remain Remain Sequence 102 | * ---- ----- ------ ------ ----------- 103 | * (a) Y 0 0 [none] 104 | * (b) Y 1 0 PAD 105 | * (c) Y 1 1 ASCII 106 | * (d) Y 2 0 PAD PAD 107 | * (e) Y 2 1 ASCII PAD 108 | * (f) Y 2 2 ASCII ASCII 109 | * - - 0 UNLATCH 110 | * 111 | * If not matching any of the above, continue without doing anything. 112 | */ 113 | static void 114 | CompleteIfDoneEdifact(DmtxEncodeStream *stream, int sizeIdxRequest) 115 | { 116 | int i; 117 | int sizeIdx; 118 | int symbolRemaining; 119 | DmtxBoolean cleanBoundary; 120 | DmtxPassFail passFail; 121 | DmtxByte outputTmpStorage[3]; 122 | DmtxByteList outputTmp; 123 | 124 | if(stream->status == DmtxStatusComplete) 125 | return; 126 | 127 | /* 128 | * If we just completed a triplet (cleanBoundary), 1 or 2 symbol codewords 129 | * remain, and our remaining inputs (if any) represented in ASCII would fit 130 | * in the remaining space, encode them in ASCII with an implicit unlatch. 131 | */ 132 | 133 | cleanBoundary = (stream->outputChainValueCount % 4 == 0) ? DmtxTrue : DmtxFalse; 134 | 135 | if(cleanBoundary == DmtxTrue) 136 | { 137 | /* Encode up to 3 codewords to a temporary stream */ 138 | outputTmp = EncodeTmpRemainingInAscii(stream, outputTmpStorage, 139 | sizeof(outputTmpStorage), &passFail); 140 | 141 | if(passFail == DmtxFail) 142 | { 143 | StreamMarkFatal(stream, DmtxErrorUnknown); 144 | return; 145 | } 146 | 147 | if(outputTmp.length < 3) 148 | { 149 | /* Find minimum symbol size for projected length */ 150 | sizeIdx = FindSymbolSize(stream->output->length + outputTmp.length, sizeIdxRequest); CHKSIZE; 151 | 152 | /* Find remaining capacity over current length */ 153 | symbolRemaining = GetRemainingSymbolCapacity(stream->output->length, sizeIdx); CHKERR; 154 | 155 | if(symbolRemaining < 3 && outputTmp.length <= symbolRemaining) 156 | { 157 | EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchImplicit); CHKERR; 158 | 159 | for(i = 0; i < outputTmp.length; i++) 160 | { 161 | AppendValueAscii(stream, outputTmp.b[i]); CHKERR; 162 | } 163 | 164 | /* Register progress since encoding happened outside normal path */ 165 | stream->inputNext = stream->input->length; 166 | 167 | /* Pad remaining if necessary */ 168 | PadRemainingInAscii(stream, sizeIdx); CHKERR; 169 | StreamMarkComplete(stream, sizeIdx); 170 | return; 171 | } 172 | } 173 | } 174 | 175 | if(!StreamInputHasNext(stream)) 176 | { 177 | sizeIdx = FindSymbolSize(stream->output->length, sizeIdxRequest); CHKSIZE; 178 | symbolRemaining = GetRemainingSymbolCapacity(stream->output->length, sizeIdx); CHKERR; 179 | 180 | /* Explicit unlatch required unless on clean boundary and full symbol */ 181 | if(cleanBoundary == DmtxFalse || symbolRemaining > 0) 182 | { 183 | EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchExplicit); CHKERR; 184 | sizeIdx = FindSymbolSize(stream->output->length, sizeIdxRequest); CHKSIZE; 185 | PadRemainingInAscii(stream, sizeIdx); CHKERR; 186 | } 187 | 188 | StreamMarkComplete(stream, sizeIdx); 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /dmtxencodestream.c: -------------------------------------------------------------------------------- 1 | /** 2 | * libdmtx - Data Matrix Encoding/Decoding Library 3 | * Copyright 2011 Mike Laughton. All rights reserved. 4 | * Copyright 2012-2016 Vadim A. Misbakh-Soloviov. All rights reserved. 5 | * 6 | * See LICENSE file in the main project directory for full 7 | * terms of use and distribution. 8 | * 9 | * Contact: 10 | * Vadim A. Misbakh-Soloviov 11 | * Mike Laughton 12 | * 13 | * \file dmtxencodestream.c 14 | * \brief DmtxEncodeStream implementation 15 | */ 16 | 17 | /** 18 | * 19 | * 20 | */ 21 | static DmtxEncodeStream 22 | StreamInit(DmtxByteList *input, DmtxByteList *output) 23 | { 24 | DmtxEncodeStream stream; 25 | 26 | stream.input = input; 27 | stream.output = output; 28 | 29 | stream.currentScheme = DmtxSchemeAscii; 30 | stream.inputNext = 0; 31 | stream.outputChainValueCount = 0; 32 | stream.outputChainWordCount = 0; 33 | stream.reason = NULL; 34 | stream.sizeIdx = DmtxUndefined; 35 | stream.status = DmtxStatusEncoding; 36 | 37 | return stream; 38 | } 39 | 40 | /** 41 | * 42 | * 43 | */ 44 | static void 45 | StreamCopy(DmtxEncodeStream *dst, DmtxEncodeStream *src) 46 | { 47 | DmtxPassFail passFail; 48 | 49 | dst->currentScheme = src->currentScheme; 50 | dst->inputNext = src->inputNext; 51 | dst->outputChainValueCount = src->outputChainValueCount; 52 | dst->outputChainWordCount = src->outputChainWordCount; 53 | dst->reason = src->reason; 54 | dst->sizeIdx = src->sizeIdx; 55 | dst->status = src->status; 56 | dst->input = src->input; 57 | dst->fnc1 = src->fnc1; 58 | 59 | dmtxByteListCopy(dst->output, src->output, &passFail); 60 | } 61 | 62 | /** 63 | * 64 | * 65 | */ 66 | static void 67 | StreamMarkComplete(DmtxEncodeStream *stream, int sizeIdx) 68 | { 69 | if(stream->status == DmtxStatusEncoding) 70 | { 71 | stream->sizeIdx = sizeIdx; 72 | stream->status = DmtxStatusComplete; 73 | assert(stream->reason == NULL); 74 | } 75 | } 76 | 77 | /** 78 | * 79 | * 80 | */ 81 | static void 82 | StreamMarkInvalid(DmtxEncodeStream *stream, int reasonIdx) 83 | { 84 | stream->status = DmtxStatusInvalid; 85 | stream->reason = dmtxErrorMessage[reasonIdx]; 86 | } 87 | 88 | /** 89 | * 90 | * 91 | */ 92 | static void 93 | StreamMarkFatal(DmtxEncodeStream *stream, int reasonIdx) 94 | { 95 | stream->status = DmtxStatusFatal; 96 | stream->reason = dmtxErrorMessage[reasonIdx]; 97 | } 98 | 99 | /** 100 | * push on newest/last append 101 | * used for encoding each output cw 102 | */ 103 | static void 104 | StreamOutputChainAppend(DmtxEncodeStream *stream, DmtxByte value) 105 | { 106 | DmtxPassFail passFail; 107 | 108 | dmtxByteListPush(stream->output, value, &passFail); 109 | 110 | if(passFail == DmtxPass) 111 | stream->outputChainWordCount++; 112 | else 113 | StreamMarkFatal(stream, DmtxErrorOutOfBounds); 114 | } 115 | 116 | /** 117 | * pop off newest/last 118 | * used for edifact 119 | */ 120 | static DmtxByte 121 | StreamOutputChainRemoveLast(DmtxEncodeStream *stream) 122 | { 123 | DmtxByte value; 124 | DmtxPassFail passFail; 125 | 126 | if(stream->outputChainWordCount > 0) 127 | { 128 | value = dmtxByteListPop(stream->output, &passFail); 129 | stream->outputChainWordCount--; 130 | } 131 | else 132 | { 133 | value = 0; 134 | StreamMarkFatal(stream, DmtxErrorEmptyList); 135 | } 136 | 137 | return value; 138 | } 139 | 140 | /** 141 | * overwrite arbitrary element 142 | * used for binary length changes 143 | */ 144 | static void 145 | StreamOutputSet(DmtxEncodeStream *stream, int index, DmtxByte value) 146 | { 147 | if(index < 0 || index >= stream->output->length) 148 | StreamMarkFatal(stream, DmtxErrorOutOfBounds); 149 | else 150 | stream->output->b[index] = value; 151 | } 152 | 153 | /** 154 | * 155 | * 156 | */ 157 | static DmtxBoolean 158 | StreamInputHasNext(DmtxEncodeStream *stream) 159 | { 160 | return (stream->inputNext < stream->input->length) ? DmtxTrue : DmtxFalse; 161 | } 162 | 163 | /** 164 | * peek at first/oldest 165 | * used for ascii double digit 166 | */ 167 | static DmtxByte 168 | StreamInputPeekNext(DmtxEncodeStream *stream) 169 | { 170 | DmtxByte value = 0; 171 | 172 | if(StreamInputHasNext(stream)) 173 | value = stream->input->b[stream->inputNext]; 174 | else 175 | StreamMarkFatal(stream, DmtxErrorOutOfBounds); 176 | 177 | return value; 178 | } 179 | 180 | /** 181 | * used as each input cw is processed 182 | * 183 | * \param value Value to populate, can be null (for blind dequeues) 184 | * \param stream 185 | */ 186 | static DmtxByte 187 | StreamInputAdvanceNext(DmtxEncodeStream *stream) 188 | { 189 | DmtxByte value; 190 | 191 | value = StreamInputPeekNext(stream); 192 | 193 | if(stream->status == DmtxStatusEncoding) 194 | stream->inputNext++; /* XXX is this what we really mean here? */ 195 | 196 | return value; 197 | } 198 | 199 | /** 200 | * used as each input cw is processed 201 | * 202 | * \param value Value to populate, can be null (for blind dequeues) 203 | * \param stream 204 | */ 205 | static void 206 | StreamInputAdvancePrev(DmtxEncodeStream *stream) 207 | { 208 | if(stream->inputNext > 0) 209 | stream->inputNext--; 210 | else 211 | StreamMarkFatal(stream, DmtxErrorOutOfBounds); 212 | } 213 | -------------------------------------------------------------------------------- /dmtxmessage.c: -------------------------------------------------------------------------------- 1 | /** 2 | * libdmtx - Data Matrix Encoding/Decoding Library 3 | * Copyright 2008, 2009 Mike Laughton. All rights reserved. 4 | * Copyright 2012-2016 Vadim A. Misbakh-Soloviov. All rights reserved. 5 | * 6 | * See LICENSE file in the main project directory for full 7 | * terms of use and distribution. 8 | * 9 | * Contact: 10 | * Vadim A. Misbakh-Soloviov 11 | * Mike Laughton 12 | * 13 | * \file dmtxmessage.c 14 | * \brief Data message handling 15 | */ 16 | 17 | /** 18 | * \brief Allocate memory for message 19 | * \param sizeIdx 20 | * \param symbolFormat DmtxFormatMatrix | DmtxFormatMosaic 21 | * \return Address of allocated memory 22 | */ 23 | extern DmtxMessage * 24 | dmtxMessageCreate(int sizeIdx, int symbolFormat) 25 | { 26 | DmtxMessage *message; 27 | int mappingRows, mappingCols; 28 | 29 | assert(symbolFormat == DmtxFormatMatrix || symbolFormat == DmtxFormatMosaic); 30 | 31 | mappingRows = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixRows, sizeIdx); 32 | mappingCols = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixCols, sizeIdx); 33 | 34 | message = (DmtxMessage *)calloc(1, sizeof(DmtxMessage)); 35 | if(message == NULL) 36 | return NULL; 37 | 38 | message->arraySize = sizeof(unsigned char) * mappingRows * mappingCols; 39 | 40 | message->array = (unsigned char *)calloc(1, message->arraySize); 41 | if(message->array == NULL) { 42 | perror("Calloc failed"); 43 | dmtxMessageDestroy(&message); 44 | return NULL; 45 | } 46 | 47 | message->codeSize = sizeof(unsigned char) * 48 | dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx) + 49 | dmtxGetSymbolAttribute(DmtxSymAttribSymbolErrorWords, sizeIdx); 50 | 51 | if(symbolFormat == DmtxFormatMosaic) 52 | message->codeSize *= 3; 53 | 54 | message->code = (unsigned char *)calloc(message->codeSize, sizeof(unsigned char)); 55 | if(message->code == NULL) { 56 | perror("Calloc failed"); 57 | dmtxMessageDestroy(&message); 58 | return NULL; 59 | } 60 | 61 | /* XXX not sure if this is the right place or even the right approach. 62 | Trying to allocate memory for the decoded data stream and will 63 | initially assume that decoded data will not be larger than 2x encoded data */ 64 | message->outputSize = sizeof(unsigned char) * message->codeSize * 10; 65 | message->output = (unsigned char *)calloc(message->outputSize, sizeof(unsigned char)); 66 | if(message->output == NULL) { 67 | perror("Calloc failed"); 68 | dmtxMessageDestroy(&message); 69 | return NULL; 70 | } 71 | 72 | return message; 73 | } 74 | 75 | /** 76 | * \brief Free memory previously allocated for message 77 | * \param message 78 | * \return void 79 | */ 80 | extern DmtxPassFail 81 | dmtxMessageDestroy(DmtxMessage **msg) 82 | { 83 | if(msg == NULL || *msg == NULL) 84 | return DmtxFail; 85 | 86 | if((*msg)->array != NULL) 87 | free((*msg)->array); 88 | 89 | if((*msg)->code != NULL) 90 | free((*msg)->code); 91 | 92 | if((*msg)->output != NULL) 93 | free((*msg)->output); 94 | 95 | free(*msg); 96 | 97 | *msg = NULL; 98 | 99 | return DmtxPass; 100 | } 101 | -------------------------------------------------------------------------------- /dmtxscangrid.c: -------------------------------------------------------------------------------- 1 | /** 2 | * libdmtx - Data Matrix Encoding/Decoding Library 3 | * Copyright 2008, 2009 Mike Laughton. All rights reserved. 4 | * Copyright 2012-2016 Vadim A. Misbakh-Soloviov. All rights reserved. 5 | * 6 | * See LICENSE file in the main project directory for full 7 | * terms of use and distribution. 8 | * 9 | * Contact: 10 | * Vadim A. Misbakh-Soloviov 11 | * Mike Laughton 12 | * 13 | * \file dmtxscangrid.c 14 | * \brief Scan grid tracking 15 | */ 16 | 17 | /** 18 | * \brief Initialize scan grid pattern 19 | * \param dec 20 | * \return Initialized grid 21 | */ 22 | static DmtxScanGrid 23 | InitScanGrid(DmtxDecode *dec) 24 | { 25 | int scale, smallestFeature; 26 | int xExtent, yExtent, maxExtent; 27 | int extent; 28 | DmtxScanGrid grid; 29 | 30 | memset(&grid, 0x00, sizeof(DmtxScanGrid)); 31 | 32 | scale = dmtxDecodeGetProp(dec, DmtxPropScale); 33 | smallestFeature = dmtxDecodeGetProp(dec, DmtxPropScanGap) / scale; 34 | 35 | grid.xMin = dmtxDecodeGetProp(dec, DmtxPropXmin); 36 | grid.xMax = dmtxDecodeGetProp(dec, DmtxPropXmax); 37 | grid.yMin = dmtxDecodeGetProp(dec, DmtxPropYmin); 38 | grid.yMax = dmtxDecodeGetProp(dec, DmtxPropYmax); 39 | 40 | /* Values that get set once */ 41 | xExtent = grid.xMax - grid.xMin; 42 | yExtent = grid.yMax - grid.yMin; 43 | maxExtent = (xExtent > yExtent) ? xExtent : yExtent; 44 | 45 | assert(maxExtent > 1); 46 | 47 | for(extent = 1; extent < maxExtent; extent = ((extent + 1) * 2) - 1) 48 | if(extent <= smallestFeature) 49 | grid.minExtent = extent; 50 | 51 | grid.maxExtent = extent; 52 | 53 | grid.xOffset = (grid.xMin + grid.xMax - grid.maxExtent) / 2; 54 | grid.yOffset = (grid.yMin + grid.yMax - grid.maxExtent) / 2; 55 | 56 | /* Values that get reset for every level */ 57 | grid.total = 1; 58 | grid.extent = grid.maxExtent; 59 | 60 | SetDerivedFields(&grid); 61 | 62 | return grid; 63 | } 64 | 65 | /** 66 | * \brief Return the next good location (which may be the current location), 67 | * and advance grid progress one position beyond that. If no good 68 | * locations remain then return DmtxRangeEnd. 69 | * \param grid 70 | * \return void 71 | */ 72 | static int 73 | PopGridLocation(DmtxScanGrid *grid, DmtxPixelLoc *locPtr) 74 | { 75 | int locStatus; 76 | 77 | do { 78 | locStatus = GetGridCoordinates(grid, locPtr); 79 | 80 | /* Always leave grid pointing at next available location */ 81 | grid->pixelCount++; 82 | 83 | } while(locStatus == DmtxRangeBad); 84 | 85 | return locStatus; 86 | } 87 | 88 | /** 89 | * \brief Extract current grid position in pixel coordinates and return 90 | * whether location is good, bad, or end 91 | * \param grid 92 | * \return Pixel location 93 | */ 94 | static int 95 | GetGridCoordinates(DmtxScanGrid *grid, DmtxPixelLoc *locPtr) 96 | { 97 | int count, half, quarter; 98 | DmtxPixelLoc loc; 99 | 100 | /* Initially pixelCount may fall beyond acceptable limits. Update grid 101 | * state before testing coordinates */ 102 | 103 | /* Jump to next cross pattern horizontally if current column is done */ 104 | if(grid->pixelCount >= grid->pixelTotal) { 105 | grid->pixelCount = 0; 106 | grid->xCenter += grid->jumpSize; 107 | } 108 | 109 | /* Jump to next cross pattern vertically if current row is done */ 110 | if(grid->xCenter > grid->maxExtent) { 111 | grid->xCenter = grid->startPos; 112 | grid->yCenter += grid->jumpSize; 113 | } 114 | 115 | /* Increment level when vertical step goes too far */ 116 | if(grid->yCenter > grid->maxExtent) { 117 | grid->total *= 4; 118 | grid->extent /= 2; 119 | SetDerivedFields(grid); 120 | } 121 | 122 | if(grid->extent == 0 || grid->extent < grid->minExtent) { 123 | locPtr->X = locPtr->Y = -1; 124 | return DmtxRangeEnd; 125 | } 126 | 127 | count = grid->pixelCount; 128 | 129 | assert(count < grid->pixelTotal); 130 | 131 | if(count == grid->pixelTotal - 1) { 132 | /* center pixel */ 133 | loc.X = grid->xCenter; 134 | loc.Y = grid->yCenter; 135 | } 136 | else { 137 | half = grid->pixelTotal / 2; 138 | quarter = half / 2; 139 | 140 | /* horizontal portion */ 141 | if(count < half) { 142 | loc.X = grid->xCenter + ((count < quarter) ? (count - quarter) : (half - count)); 143 | loc.Y = grid->yCenter; 144 | } 145 | /* vertical portion */ 146 | else { 147 | count -= half; 148 | loc.X = grid->xCenter; 149 | loc.Y = grid->yCenter + ((count < quarter) ? (count - quarter) : (half - count)); 150 | } 151 | } 152 | 153 | loc.X += grid->xOffset; 154 | loc.Y += grid->yOffset; 155 | 156 | *locPtr = loc; 157 | 158 | if(loc.X < grid->xMin || loc.X > grid->xMax || 159 | loc.Y < grid->yMin || loc.Y > grid->yMax) 160 | return DmtxRangeBad; 161 | 162 | return DmtxRangeGood; 163 | } 164 | 165 | /** 166 | * \brief Update derived fields based on current state 167 | * \param grid 168 | * \return void 169 | */ 170 | static void 171 | SetDerivedFields(DmtxScanGrid *grid) 172 | { 173 | grid->jumpSize = grid->extent + 1; 174 | grid->pixelTotal = 2 * grid->extent - 1; 175 | grid->startPos = grid->extent / 2; 176 | grid->pixelCount = 0; 177 | grid->xCenter = grid->yCenter = grid->startPos; 178 | } 179 | -------------------------------------------------------------------------------- /dmtxsymbol.c: -------------------------------------------------------------------------------- 1 | /** 2 | * libdmtx - Data Matrix Encoding/Decoding Library 3 | * Copyright 2008, 2009 Mike Laughton. All rights reserved. 4 | * Copyright 2012-2016 Vadim A. Misbakh-Soloviov. All rights reserved. 5 | * Copyright 2016 Tim Zaman. All rights reserved. 6 | * 7 | * See LICENSE file in the main project directory for full 8 | * terms of use and distribution. 9 | * 10 | * Contact: 11 | * Vadim A. Misbakh-Soloviov 12 | * Mike Laughton 13 | * 14 | * \file dmtxsymbol.c 15 | * \brief Data Matrix symbol attributes 16 | */ 17 | 18 | 19 | /** 20 | * \brief Retrieve symbol index from rows and columns 21 | * \param rows 22 | * \param cols 23 | * \return sizeIdx value 24 | */ 25 | extern int 26 | getSizeIdxFromSymbolDimension(int rows, int cols) 27 | { 28 | int symbolRows, symbolCols, i; 29 | for (i=0; i<30; i++){ 30 | symbolRows = dmtxGetSymbolAttribute(DmtxSymAttribSymbolRows, i); 31 | symbolCols = dmtxGetSymbolAttribute(DmtxSymAttribSymbolCols, i); 32 | if (rows==symbolRows && cols==symbolCols){ 33 | return i; 34 | } 35 | } 36 | return -1; 37 | } 38 | 39 | 40 | /** 41 | * \brief Retrieve property based on symbol size 42 | * \param attribute 43 | * \param sizeIdx 44 | * \return Attribute value 45 | */ 46 | extern int 47 | dmtxGetSymbolAttribute(int attribute, int sizeIdx) 48 | { 49 | static const int symbolRows[] = { 10, 12, 14, 16, 18, 20, 22, 24, 26, 50 | 32, 36, 40, 44, 48, 52, 51 | 64, 72, 80, 88, 96, 104, 52 | 120, 132, 144, 53 | 8, 8, 12, 12, 16, 16 }; 54 | 55 | static const int symbolCols[] = { 10, 12, 14, 16, 18, 20, 22, 24, 26, 56 | 32, 36, 40, 44, 48, 52, 57 | 64, 72, 80, 88, 96, 104, 58 | 120, 132, 144, 59 | 18, 32, 26, 36, 36, 48 }; 60 | 61 | static const int dataRegionRows[] = { 8, 10, 12, 14, 16, 18, 20, 22, 24, 62 | 14, 16, 18, 20, 22, 24, 63 | 14, 16, 18, 20, 22, 24, 64 | 18, 20, 22, 65 | 6, 6, 10, 10, 14, 14 }; 66 | 67 | static const int dataRegionCols[] = { 8, 10, 12, 14, 16, 18, 20, 22, 24, 68 | 14, 16, 18, 20, 22, 24, 69 | 14, 16, 18, 20, 22, 24, 70 | 18, 20, 22, 71 | 16, 14, 24, 16, 16, 22 }; 72 | 73 | static const int horizDataRegions[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 74 | 2, 2, 2, 2, 2, 2, 75 | 4, 4, 4, 4, 4, 4, 76 | 6, 6, 6, 77 | 1, 2, 1, 2, 2, 2 }; 78 | 79 | static const int interleavedBlocks[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 80 | 1, 1, 1, 1, 1, 2, 81 | 2, 4, 4, 4, 4, 6, 82 | 6, 8, 10, 83 | 1, 1, 1, 1, 1, 1 }; 84 | 85 | static const int symbolDataWords[] = { 3, 5, 8, 12, 18, 22, 30, 36, 44, 86 | 62, 86, 114, 144, 174, 204, 87 | 280, 368, 456, 576, 696, 816, 88 | 1050, 1304, 1558, 89 | 5, 10, 16, 22, 32, 49 }; 90 | 91 | static const int blockErrorWords[] = { 5, 7, 10, 12, 14, 18, 20, 24, 28, 92 | 36, 42, 48, 56, 68, 42, 93 | 56, 36, 48, 56, 68, 56, 94 | 68, 62, 62, 95 | 7, 11, 14, 18, 24, 28 }; 96 | 97 | static const int blockMaxCorrectable[] = { 2, 3, 5, 6, 7, 9, 10, 12, 14, 98 | 18, 21, 24, 28, 34, 21, 99 | 28, 18, 24, 28, 34, 28, 100 | 34, 31, 31, 101 | 3, 5, 7, 9, 12, 14 }; 102 | 103 | if(sizeIdx < 0 || sizeIdx >= DmtxSymbolSquareCount + DmtxSymbolRectCount) 104 | return DmtxUndefined; 105 | 106 | switch(attribute) { 107 | case DmtxSymAttribSymbolRows: 108 | return symbolRows[sizeIdx]; 109 | case DmtxSymAttribSymbolCols: 110 | return symbolCols[sizeIdx]; 111 | case DmtxSymAttribDataRegionRows: 112 | return dataRegionRows[sizeIdx]; 113 | case DmtxSymAttribDataRegionCols: 114 | return dataRegionCols[sizeIdx]; 115 | case DmtxSymAttribHorizDataRegions: 116 | return horizDataRegions[sizeIdx]; 117 | case DmtxSymAttribVertDataRegions: 118 | return (sizeIdx < DmtxSymbolSquareCount) ? horizDataRegions[sizeIdx] : 1; 119 | case DmtxSymAttribMappingMatrixRows: 120 | return dataRegionRows[sizeIdx] * 121 | dmtxGetSymbolAttribute(DmtxSymAttribVertDataRegions, sizeIdx); 122 | case DmtxSymAttribMappingMatrixCols: 123 | return dataRegionCols[sizeIdx] * horizDataRegions[sizeIdx]; 124 | case DmtxSymAttribInterleavedBlocks: 125 | return interleavedBlocks[sizeIdx]; 126 | case DmtxSymAttribBlockErrorWords: 127 | return blockErrorWords[sizeIdx]; 128 | case DmtxSymAttribBlockMaxCorrectable: 129 | return blockMaxCorrectable[sizeIdx]; 130 | case DmtxSymAttribSymbolDataWords: 131 | return symbolDataWords[sizeIdx]; 132 | case DmtxSymAttribSymbolErrorWords: 133 | return blockErrorWords[sizeIdx] * interleavedBlocks[sizeIdx]; 134 | case DmtxSymAttribSymbolMaxCorrectable: 135 | return blockMaxCorrectable[sizeIdx] * interleavedBlocks[sizeIdx]; 136 | } 137 | 138 | return DmtxUndefined; 139 | } 140 | 141 | /** 142 | * \brief Retrieve data size for a specific symbol size and block number 143 | * \param sizeIdx 144 | * \param blockIdx 145 | * \return Attribute value 146 | */ 147 | extern int 148 | dmtxGetBlockDataSize(int sizeIdx, int blockIdx) 149 | { 150 | int symbolDataWords; 151 | int interleavedBlocks; 152 | int count; 153 | 154 | symbolDataWords = dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx); 155 | interleavedBlocks = dmtxGetSymbolAttribute(DmtxSymAttribInterleavedBlocks, sizeIdx); 156 | 157 | if(symbolDataWords < 1 || interleavedBlocks < 1) 158 | return DmtxUndefined; 159 | 160 | count = (int)(symbolDataWords/interleavedBlocks); 161 | 162 | return (sizeIdx == DmtxSymbol144x144 && blockIdx < 8) ? count + 1 : count; 163 | } 164 | 165 | /** 166 | * \brief Determine symbol size based on data size and requested properties 167 | * \param dataWords 168 | * \param sizeIdxRequest 169 | * \return Symbol size index (or DmtxUndefined if none) 170 | */ 171 | static int 172 | FindSymbolSize(int dataWords, int sizeIdxRequest) 173 | { 174 | int sizeIdx; 175 | int idxBeg, idxEnd; 176 | 177 | if(dataWords <= 0) 178 | return DmtxUndefined; 179 | 180 | if(sizeIdxRequest == DmtxSymbolSquareAuto || sizeIdxRequest == DmtxSymbolRectAuto) { 181 | 182 | if(sizeIdxRequest == DmtxSymbolSquareAuto) { 183 | idxBeg = 0; 184 | idxEnd = DmtxSymbolSquareCount; 185 | } 186 | else { 187 | idxBeg = DmtxSymbolSquareCount; 188 | idxEnd = DmtxSymbolSquareCount + DmtxSymbolRectCount; 189 | } 190 | 191 | for(sizeIdx = idxBeg; sizeIdx < idxEnd; sizeIdx++) { 192 | if(dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx) >= dataWords) 193 | break; 194 | } 195 | 196 | if(sizeIdx == idxEnd) 197 | return DmtxUndefined; 198 | } 199 | else { 200 | sizeIdx = sizeIdxRequest; 201 | } 202 | 203 | if(dataWords > dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx)) 204 | return DmtxUndefined; 205 | 206 | return sizeIdx; 207 | } 208 | -------------------------------------------------------------------------------- /dmtxtime.c: -------------------------------------------------------------------------------- 1 | /** 2 | * libdmtx - Data Matrix Encoding/Decoding Library 3 | * Copyright 2008, 2009 Mike Laughton. All rights reserved. 4 | * Copyright 2012-2016 Vadim A. Misbakh-Soloviov. All rights reserved. 5 | * 6 | * See LICENSE file in the main project directory for full 7 | * terms of use and distribution. 8 | * 9 | * Contact: 10 | * Vadim A. Misbakh-Soloviov 11 | * Mike Laughton 12 | * 13 | * \file dmtxtime.c 14 | * \brief Time handling 15 | */ 16 | 17 | #define DMTX_USEC_PER_SEC 1000000 18 | 19 | #if defined(HAVE_SYS_TIME_H) && defined(HAVE_GETTIMEOFDAY) 20 | 21 | #include 22 | #include 23 | #define DMTX_TIME_PREC_USEC 1 24 | 25 | /** 26 | * \brief GETTIMEOFDAY version 27 | * \return Time now 28 | */ 29 | extern DmtxTime 30 | dmtxTimeNow(void) 31 | { 32 | DmtxPassFail err; 33 | struct timeval tv; 34 | DmtxTime tNow; 35 | 36 | err = gettimeofday(&tv, NULL); 37 | if(err != 0) 38 | ; /* XXX handle error better here */ 39 | 40 | tNow.sec = tv.tv_sec; 41 | tNow.usec = tv.tv_usec; 42 | 43 | return tNow; 44 | } 45 | 46 | #elif defined(_MSC_VER) 47 | 48 | #include 49 | #define DMTX_TIME_PREC_USEC 1 50 | 51 | /** 52 | * \brief MICROSOFT VC++ version 53 | * \return Time now 54 | */ 55 | extern DmtxTime 56 | dmtxTimeNow(void) 57 | { 58 | FILETIME ft; 59 | unsigned __int64 tm; 60 | DmtxTime tNow; 61 | 62 | GetSystemTimeAsFileTime(&ft); 63 | 64 | tm = ft.dwHighDateTime; 65 | tm <<= 32; 66 | tm |= ft.dwLowDateTime; 67 | tm /= 10; 68 | 69 | tNow.sec = tm / 1000000UL; 70 | tNow.usec = tm % 1000000UL; 71 | 72 | return tNow; 73 | } 74 | 75 | #else 76 | 77 | #include 78 | #define DMTX_TIME_PREC_USEC 1000000 79 | 80 | /** 81 | * \brief Generic 1 second resolution version 82 | * \return Time now 83 | */ 84 | extern DmtxTime 85 | dmtxTimeNow(void) 86 | { 87 | time_t s; 88 | DmtxTime tNow; 89 | 90 | s = time(NULL); 91 | if(errno != 0) 92 | ; /* XXX handle error better here */ 93 | 94 | tNow.sec = s; 95 | tNow.usec = 0; 96 | 97 | return tNow; 98 | } 99 | 100 | #endif 101 | 102 | /** 103 | * \brief Add milliseconds to time t 104 | * \param t 105 | * \param msec 106 | * \return Adjusted time 107 | */ 108 | extern DmtxTime 109 | dmtxTimeAdd(DmtxTime t, long msec) 110 | { 111 | int usec; 112 | 113 | usec = msec * 1000; 114 | 115 | /* Ensure that time difference will register on local system */ 116 | if(usec > 0 && usec < DMTX_TIME_PREC_USEC) 117 | usec = DMTX_TIME_PREC_USEC; 118 | 119 | /* Add time */ 120 | t.sec += usec/DMTX_USEC_PER_SEC; 121 | t.usec += usec%DMTX_USEC_PER_SEC; 122 | 123 | /* Roll extra usecs into secs */ 124 | while(t.usec >= DMTX_USEC_PER_SEC) { 125 | t.sec++; 126 | t.usec -= DMTX_USEC_PER_SEC; 127 | } 128 | 129 | return t; 130 | } 131 | 132 | /** 133 | * \brief Determine whether the received timeout has been exceeded 134 | * \param timeout 135 | * \return 1 (true) | 0 (false) 136 | */ 137 | extern int 138 | dmtxTimeExceeded(DmtxTime timeout) 139 | { 140 | DmtxTime now; 141 | 142 | now = dmtxTimeNow(); 143 | 144 | return (now.sec > timeout.sec || (now.sec == timeout.sec && now.usec > timeout.usec)); 145 | } 146 | 147 | #undef DMTX_TIME_PREC_USEC 148 | #undef DMTX_USEC_PER_SEC 149 | -------------------------------------------------------------------------------- /dmtxvector2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * libdmtx - Data Matrix Encoding/Decoding Library 3 | * Copyright 2008, 2009 Mike Laughton. All rights reserved. 4 | * Copyright 2012-2016 Vadim A. Misbakh-Soloviov. All rights reserved. 5 | * 6 | * See LICENSE file in the main project directory for full 7 | * terms of use and distribution. 8 | * 9 | * Contact: 10 | * Vadim A. Misbakh-Soloviov 11 | * Mike Laughton 12 | * 13 | * \file dmtxvector2.c 14 | * \brief 2D Vector math 15 | */ 16 | 17 | /** 18 | * 19 | * 20 | */ 21 | extern DmtxVector2 * 22 | dmtxVector2AddTo(DmtxVector2 *v1, const DmtxVector2 *v2) 23 | { 24 | v1->X += v2->X; 25 | v1->Y += v2->Y; 26 | 27 | return v1; 28 | } 29 | 30 | /** 31 | * 32 | * 33 | */ 34 | extern DmtxVector2 * 35 | dmtxVector2Add(DmtxVector2 *vOut, const DmtxVector2 *v1, const DmtxVector2 *v2) 36 | { 37 | *vOut = *v1; 38 | 39 | return dmtxVector2AddTo(vOut, v2); 40 | } 41 | 42 | /** 43 | * 44 | * 45 | */ 46 | extern DmtxVector2 * 47 | dmtxVector2SubFrom(DmtxVector2 *v1, const DmtxVector2 *v2) 48 | { 49 | v1->X -= v2->X; 50 | v1->Y -= v2->Y; 51 | 52 | return v1; 53 | } 54 | 55 | /** 56 | * 57 | * 58 | */ 59 | extern DmtxVector2 * 60 | dmtxVector2Sub(DmtxVector2 *vOut, const DmtxVector2 *v1, const DmtxVector2 *v2) 61 | { 62 | *vOut = *v1; 63 | 64 | return dmtxVector2SubFrom(vOut, v2); 65 | } 66 | 67 | /** 68 | * 69 | * 70 | */ 71 | extern DmtxVector2 * 72 | dmtxVector2ScaleBy(DmtxVector2 *v, double s) 73 | { 74 | v->X *= s; 75 | v->Y *= s; 76 | 77 | return v; 78 | } 79 | 80 | /** 81 | * 82 | * 83 | */ 84 | extern DmtxVector2 * 85 | dmtxVector2Scale(DmtxVector2 *vOut, const DmtxVector2 *v, double s) 86 | { 87 | *vOut = *v; 88 | 89 | return dmtxVector2ScaleBy(vOut, s); 90 | } 91 | 92 | /** 93 | * 94 | * 95 | */ 96 | extern double 97 | dmtxVector2Cross(const DmtxVector2 *v1, const DmtxVector2 *v2) 98 | { 99 | return (v1->X * v2->Y) - (v1->Y * v2->X); 100 | } 101 | 102 | /** 103 | * 104 | * 105 | */ 106 | extern double 107 | dmtxVector2Norm(DmtxVector2 *v) 108 | { 109 | double mag; 110 | 111 | mag = dmtxVector2Mag(v); 112 | 113 | if(mag <= DmtxAlmostZero) 114 | return -1.0; /* XXX this doesn't look clean */ 115 | 116 | dmtxVector2ScaleBy(v, 1/mag); 117 | 118 | return mag; 119 | } 120 | 121 | /** 122 | * 123 | * 124 | */ 125 | extern double 126 | dmtxVector2Dot(const DmtxVector2 *v1, const DmtxVector2 *v2) 127 | { 128 | return (v1->X * v2->X) + (v1->Y * v2->Y); 129 | } 130 | 131 | /** 132 | * 133 | * 134 | */ 135 | extern double 136 | dmtxVector2Mag(const DmtxVector2 *v) 137 | { 138 | return sqrt(v->X * v->X + v->Y * v->Y); 139 | } 140 | 141 | /** 142 | * 143 | * 144 | */ 145 | extern double 146 | dmtxDistanceFromRay2(const DmtxRay2 *r, const DmtxVector2 *q) 147 | { 148 | DmtxVector2 vSubTmp; 149 | 150 | /* Assumes that v is a unit vector */ 151 | assert(fabs(1.0 - dmtxVector2Mag(&(r->v))) <= DmtxAlmostZero); 152 | 153 | return dmtxVector2Cross(&(r->v), dmtxVector2Sub(&vSubTmp, q, &(r->p))); 154 | } 155 | 156 | /** 157 | * 158 | * 159 | */ 160 | extern double 161 | dmtxDistanceAlongRay2(const DmtxRay2 *r, const DmtxVector2 *q) 162 | { 163 | DmtxVector2 vSubTmp; 164 | 165 | #ifdef DEBUG 166 | /* Assumes that v is a unit vector */ 167 | if(fabs(1.0 - dmtxVector2Mag(&(r->v))) > DmtxAlmostZero) { 168 | ; /* XXX big error goes here */ 169 | } 170 | #endif 171 | 172 | return dmtxVector2Dot(dmtxVector2Sub(&vSubTmp, q, &(r->p)), &(r->v)); 173 | } 174 | 175 | /** 176 | * 177 | * 178 | */ 179 | extern DmtxPassFail 180 | dmtxRay2Intersect(DmtxVector2 *point, const DmtxRay2 *p0, const DmtxRay2 *p1) 181 | { 182 | double numer, denom; 183 | DmtxVector2 w; 184 | 185 | denom = dmtxVector2Cross(&(p1->v), &(p0->v)); 186 | if(fabs(denom) <= DmtxAlmostZero) 187 | return DmtxFail; 188 | 189 | dmtxVector2Sub(&w, &(p1->p), &(p0->p)); 190 | numer = dmtxVector2Cross(&(p1->v), &w); 191 | 192 | return dmtxPointAlongRay2(point, p0, numer/denom); 193 | } 194 | 195 | /** 196 | * 197 | * 198 | */ 199 | extern DmtxPassFail 200 | dmtxPointAlongRay2(DmtxVector2 *point, const DmtxRay2 *r, double t) 201 | { 202 | DmtxVector2 vTmp; 203 | 204 | /* Ray should always have unit length of 1 */ 205 | assert(fabs(1.0 - dmtxVector2Mag(&(r->v))) <= DmtxAlmostZero); 206 | 207 | dmtxVector2Scale(&vTmp, &(r->v), t); 208 | dmtxVector2Add(point, &(r->p), &vTmp); 209 | 210 | return DmtxPass; 211 | } 212 | -------------------------------------------------------------------------------- /libdmtx.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: libdmtx 7 | URL: http://www.libdmtx.org/ 8 | Description: Library for reading and writing Data Matrix barcodes 9 | Version: @PACKAGE_VERSION@ 10 | Libs: -L${libdir} -ldmtx 11 | Cflags: -I${includedir} 12 | -------------------------------------------------------------------------------- /man/libdmtx.3: -------------------------------------------------------------------------------- 1 | .\" Man page for the libdmtx project. 2 | .\" 3 | .\" To view: $ groff -man -T ascii libdmtx.3 | less 4 | .\" To text: $ groff -man -T ascii libdmtx.3 | col -b | expand 5 | .\" 6 | .TH LIBDMTX 3 "June 2, 2011" 7 | .SH NAME 8 | libdmtx \- Data Matrix Encoding & Decoding Library 9 | .SH SYNOPSIS 10 | \fB#include \fP 11 | 12 | cc file.c -ldmtx 13 | 14 | .SH DESCRIPTION 15 | \fIlibdmtx\fP is a software library that enables programs to read and write Data Matrix barcodes of the modern ECC200 variety. The library runs natively on several platforms, and can be accessed by multiple languages using the libdmtx language wrappers. The utility programs \fIdmtxread\fP and \fIdmtxwrite\fP provide a command line interface for libdmtx, and serve as a good reference for developers writing their own libdmtx-enabled programs. 16 | 17 | Data Matrix barcodes store data as a pattern of ON and OFF modules (often black on white) in a grid pattern that resembles a checkerboard. Like other 2D symbologies, Data Matrix barcodes have a large data capacity compared to their traditional 1D cousins, and employ sophisticated error correction techniques. Data Matrix barcodes can be square or rectangle in shape, and offer several encodation schemes for optimized storage of text and/or binary data. The Data Matrix symbology was invented and released into the public domain by RVSI Acuity CiMatrix. 18 | 19 | .SH ENCODING - Generating Data Matrix Barcodes 20 | C/C++ programs can generate a barcode with just a few basic calls to libdmtx: 21 | 22 | 1. Call \fBdmtxEncodeCreate()\fP 23 | 24 | Creates a new \fBDmtxEncode\fP structure and initializes the encoding process. This function must be called before using the other encoding functions. 25 | 26 | 2. Call \fBdmtxEncodeSetProp()\fP [optional] 27 | 28 | Allows you to control specific aspects of the encoding behavior. If this function is not called, libdmtx will use the defaults set by \fBdmtxEncodeCreate()\fP above. The complementary function, \fBdmtxEncodeGetProp()\fP, allows you to detect the current settings. 29 | 30 | 3. Call either \fBdmtxEncodeDataMatrix()\fP or \fBdmtxEncodeDataMosaic()\fP 31 | 32 | Call one of these functions to generate an image of the desired barcode type. Your program is responsible for dispatching the resulting output to its destination, whether that means displaying it on a screen, writing an image file, copying it elsewhere, etc... 33 | 34 | 4. Call \fBdmtxEncodeDestroy()\fP 35 | 36 | Releases memory allocated during the encoding process. 37 | 38 | .SH DECODING - Reading Data Matrix Barcodes 39 | Barcode reading takes more steps than barcode generation, mainly because libdmtx must find a barcode region before it can decode the message. However, this too is a relatively simple process that uses 4 main structures: 40 | 41 | \fBDmtxImage\fP holds image properties and a pointer to pixel data held by the calling program. 42 | 43 | \fBDmtxDecode\fP holds values for controlling decode behavior and tracking scan progress. When scanning a new image, calling programs should always create a new \fBDmtxDecode\fP structure instead of reusing an old one. 44 | 45 | \fBDmtxRegion\fP defines a 4-sided region in pixel coordinates. Regions may be found in almost any orientation, and their corners won't necessarily form right angles. libdmtx uses this structure to store the location of potential barcodes, which are then returned to the calling program one-at-a-time. 46 | 47 | \fBDmtxMessage\fP holds the decoded message after being extracted from the barcode region. A successfully decoded region will produce exactly one message. 48 | 49 | Use the following functions to find and decode Data Matrix barcodes: 50 | 51 | 1. Call \fBdmtxImageCreate()\fP 52 | 53 | Creates and initializes a new \fBDmtxImage\fP structure using pixel data provided by the calling application. Parameters include a pointer to the existing pixel array, image width, height, and the pixel packing format. 54 | 55 | 2. Call \fBdmtxImageSetProp()\fP [optional] 56 | 57 | Sets image properties to control the pixel mapping logic. These settings allow libdmtx to understand many native in-memory image layouts, thus preventing the extra work of transforming and copying data to a one-size-fits-all format. A \fBdmtxDecodeGetProp()\fP function is also available for detecting the current image properties. 58 | 59 | 3. Call \fBdmtxDecodeCreate()\fP 60 | 61 | Creates and initializes a new \fBDmtxDecode\fP struct, which designates the image to be scanned and initializes the scan grid pattern. This function must be called before any other scanning functions. 62 | 63 | 4. Call \fBdmtxDecodeSetProp()\fP [optional] 64 | 65 | Sets internal properties to control decoding behavior. This feature allows you to optimize performance and accuracy for specific image conditions. A \fBdmtxDecodeGetProp()\fP function is also available. 66 | 67 | 5. Call \fBdmtxRegionFindNext()\fP 68 | 69 | Searches every pixel location in a grid pattern looking for potential barcode regions. A \fBDmtxRegion\fP is returned whenever a potential barcode region is found, or if the final pixel location has been scanned. Subsequent calls to this function will resume the search where the previous call left off. 70 | 71 | 6. Call either \fBdmtxDecodeMatrixRegion()\fP or \fBdmtxDecodeMosaicRegion()\fP 72 | 73 | Extracts raw data from the barcode region and decodes the underlying message. 74 | 75 | 7. Call \fBdmtxMessageDestroy()\fP 76 | 77 | Releases memory held by a \fBDmtxMessage\fP struct. The complementary function, \fBdmtxMessageCreate()\fP, is automatically called by \fBdmtxDecodeMatrixRegion()\fP and therefore is not normally used by the calling program. 78 | 79 | 8. Call \fBdmtxRegionDestroy()\fP 80 | 81 | Releases memory held by a \fBDmtxRegion\fP struct. The complementary function, \fBdmtxRegionCreate()\fP, is automatically called by \fBdmtxRegionFindNext()\fP (actually \fBdmtxRegionScanPixel()\fP) and therefore is not normally used by the calling program. 82 | 83 | 9. Call \fBdmtxDecodeDestroy()\fP 84 | 85 | Releases memory held by a \fBDmtxDecode\fP struct. This is the complementary function to \fBdmtxDecodeCreate()\fP. 86 | 87 | 10. Call \fBdmtxImageDestroy()\fP 88 | 89 | Releases memory held by a \fBDmtxImage\fP struct, excluding the pixel array passed to \fBdmtxImageCreate()\fP. The calling program is responsible for releasing the pixel array memory, if required. 90 | 91 | .SH EXAMPLE PROGRAM 92 | 93 | This example program (available as simple_test.c in the source package) demonstrates \fIlibdmtx\fP functionality in both directions: encoding and decoding. It creates a Data Matrix barcode in memory, reads it back, and prints the decoded message. The final output message should match the original input string. 94 | 95 | #include 96 | #include 97 | #include 98 | #include 99 | #include 100 | 101 | int 102 | main(int argc, char *argv[]) 103 | { 104 | size_t width, height, bytesPerPixel; 105 | unsigned char str[] = "30Q324343430794image, DmtxPropWidth); 124 | height = dmtxImageGetProp(enc->image, DmtxPropHeight); 125 | bytesPerPixel = dmtxImageGetProp(enc->image, DmtxPropBytesPerPixel); 126 | 127 | pxl = (unsigned char *)malloc(width * height * bytesPerPixel); 128 | assert(pxl != NULL); 129 | memcpy(pxl, enc->image->pxl, width * height * bytesPerPixel); 130 | 131 | dmtxEncodeDestroy(&enc); 132 | 133 | /* 3) DECODE the Data Matrix barcode from the copied image */ 134 | 135 | img = dmtxImageCreate(pxl, width, height, DmtxPack24bppRGB); 136 | assert(img != NULL); 137 | 138 | dec = dmtxDecodeCreate(img, 1); 139 | assert(dec != NULL); 140 | 141 | reg = dmtxRegionFindNext(dec, NULL); 142 | if(reg != NULL) { 143 | msg = dmtxDecodeMatrixRegion(dec, reg, DmtxUndefined); 144 | if(msg != NULL) { 145 | fputs("output: \\"", stdout); 146 | fwrite(msg->output, sizeof(unsigned char), msg->outputIdx, stdout); 147 | fputs("\\"\\n", stdout); 148 | dmtxMessageDestroy(&msg); 149 | } 150 | dmtxRegionDestroy(®); 151 | } 152 | 153 | dmtxDecodeDestroy(&dec); 154 | dmtxImageDestroy(&img); 155 | free(pxl); 156 | 157 | exit(0); 158 | } 159 | 160 | .SH "SEE ALSO" 161 | \fIdmtxread\fP(1), \fIdmtxwrite\fP(1), \fIdmtxquery\fP(1) 162 | .SH STANDARDS 163 | ISO/IEC 16022:2000 164 | .PP 165 | ANSI/AIM BC11 ISS 166 | .SH BUGS 167 | Post bug reports on GitHub issue tracker or email them to dmtx-bug@mva.name 168 | .SH AUTHOR 169 | Copyright (C) 2008, 2009 Mike Laughton 170 | Copyright (C) 2012-2025 Vadim A. Misbakh-Soloviov 171 | .\" end of man page 172 | -------------------------------------------------------------------------------- /script/check_all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | function RunTest() 4 | { 5 | SCRIPT="$1" 6 | SCRIPT_TYPE=$(echo "$SCRIPT" | awk -F'.' '{print $NF}') 7 | 8 | echo " $SCRIPT" 9 | 10 | ERRORS=0 11 | for dir in $(find "$LIBDMTX" -type d); do 12 | 13 | if [[ "$dir" != "$LIBDMTX" && 14 | "$dir" != "$LIBDMTX/test/simple_test" ]]; then 15 | continue 16 | fi 17 | 18 | for file in $(find $dir -maxdepth 1); do 19 | 20 | EXT=$(echo $file | awk -F'.' '{print $NF}') 21 | if [[ "$EXT" != "c" && "$EXT" != "h" && "$EXT" != "sh" && \ 22 | "$EXT" != "py" && "$EXT" != "pl" ]]; then 23 | continue 24 | fi 25 | 26 | if [[ "$(basename $file)" = "config.h" || 27 | "$(basename $file)" = "ltmain.sh" ]]; then 28 | continue 29 | fi 30 | 31 | if [[ $(cat $file | wc -l) -le 10 ]]; then 32 | #echo " skipping \"$file\" (trivial file)" 33 | continue 34 | fi 35 | 36 | if [[ "$SCRIPT_TYPE" = "sh" ]]; then 37 | $LIBDMTX/script/$SCRIPT $file 38 | ERRORS=$(( ERRORS + $? )) 39 | elif [[ "$SCRIPT_TYPE" = "pl" ]]; then 40 | PERL=$(which perl) 41 | if [[ $? -ne 0 ]]; then 42 | echo "No perl interpreter found. Skipping $SCRIPT test." 43 | else 44 | $PERL $LIBDMTX/script/$SCRIPT $file 45 | ERRORS=$(( ERRORS + $? )) 46 | fi 47 | fi 48 | done 49 | done 50 | 51 | return $ERRORS 52 | } 53 | 54 | LIBDMTX="$1" 55 | if [[ -z "$LIBDMTX" || ! -d "$LIBDMTX/script" ]]; then 56 | echo "Must provide valid LIBDMTX directory" 57 | exit 1 58 | fi 59 | 60 | RunTest check_comments.sh 61 | RunTest check_copyright.sh 62 | RunTest check_license.sh 63 | RunTest check_spacing.sh 64 | RunTest check_whitespace.sh 65 | RunTest check_headers.pl 66 | RunTest check_todo.sh 67 | 68 | exit 0 69 | -------------------------------------------------------------------------------- /script/check_comments.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | FILE="$1" 4 | 5 | LINE=$(grep -n "\*\{10\}" $FILE) 6 | if [[ $? -eq 0 ]]; then 7 | echo -e "Bad comment style found in $FILE on line(s):\n$LINE" 8 | exit 1 9 | fi 10 | 11 | LINE=$(sed -n -e '1 =' -e '2,$ p' $FILE | grep -n "^\/\*\$") 12 | if [[ $? -eq 0 ]]; then 13 | echo -e "Bad comment style found in $FILE on line(s):\n$LINE" 14 | exit 2 15 | fi 16 | 17 | exit 0 18 | -------------------------------------------------------------------------------- /script/check_copyright.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | FILE="$1" 4 | 5 | # Every nontrivial source file must include a copyright line 6 | COPYRIGHT=$(grep "Copyright 2[[:digit:]]\{3\}" $FILE) 7 | if [[ $? -ne 0 ]]; then 8 | echo "Missing copyright text in $FILE" 9 | exit 1 10 | fi 11 | 12 | exit 0 13 | -------------------------------------------------------------------------------- /script/check_headers.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | use strict; 4 | use File::Basename; 5 | 6 | # TODO: Test still misses first function of each file 7 | 8 | my $errorCount = 0; 9 | undef my $closeLineNbr; 10 | undef my $lineNbrs; 11 | 12 | while(<>) { 13 | chomp; 14 | 15 | if(m/^}$/) { 16 | $closeLineNbr = $.; 17 | } 18 | elsif(!defined($closeLineNbr) || m/^$/ || m/^\*/ || m/^#/) { 19 | next; 20 | } 21 | elsif(m/^\/\*\*$/) { 22 | undef $closeLineNbr; 23 | } 24 | else { 25 | $lineNbrs = (defined $lineNbrs) ? "$lineNbrs, $." : $.; 26 | $errorCount++; 27 | undef $closeLineNbr; 28 | } 29 | } 30 | 31 | if($errorCount > 0) { 32 | print "Missing header comment in file \"" . basename($ARGV) . 33 | "\" at line(s) $lineNbrs\n"; 34 | exit(1); 35 | } 36 | 37 | exit(0); 38 | -------------------------------------------------------------------------------- /script/check_license.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | FILE="$1" 4 | 5 | TEST1="^ \* libdmtx - Data Matrix Encoding/Decoding Library\$" 6 | TEST2="^ \* See LICENSE file in the main project directory for full\$" 7 | TEST3="^ \* terms of use and distribution.\$" 8 | TEST4="^ \* Vadim A. Misbakh-Soloviov\$" 9 | 10 | COUNT=0 11 | 12 | grep --silent "$TEST1" $FILE 13 | COUNT=$(( COUNT + $? )) 14 | 15 | grep --silent "$TEST2" $FILE 16 | COUNT=$(( COUNT + $? )) 17 | 18 | grep --silent "$TEST3" $FILE 19 | COUNT=$(( COUNT + $? )) 20 | 21 | grep --silent "$TEST4" $FILE 22 | COUNT=$(( COUNT + $? )) 23 | 24 | if [[ "$COUNT" -gt 0 ]]; then 25 | echo "Missing license text in $FILE" 26 | exit 1 27 | fi 28 | 29 | exit 0 30 | -------------------------------------------------------------------------------- /script/check_spacing.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -u 4 | 5 | FILE=$1 6 | 7 | PATTERN="XXC_XX_X_XXX" 8 | COPYRIGHT=0 9 | 10 | for i in $(seq 1 12); do 11 | LINE_TYPE=$(echo $PATTERN | cut -c$i) 12 | LINE_NBR=$((i + COPYRIGHT)) 13 | if [[ "$LINE_TYPE" = "C" ]]; then 14 | while true; do 15 | sed -n "${LINE_NBR}p" $FILE | grep --silent "^ \* Copyright" 16 | if [[ $? -eq 0 ]]; then 17 | COPYRIGHT=$((COPYRIGHT+1)) 18 | LINE_NBR=$((i + COPYRIGHT)) 19 | else 20 | COPYRIGHT=$((COPYRIGHT-1)) 21 | break 22 | fi 23 | done 24 | elif [[ "$LINE_TYPE" = "X" ]]; then 25 | sed -n "$LINE_NBR p" $FILE | grep --silent "^..*$" 26 | if [[ $? -ne 0 ]]; then 27 | echo "Expected line $LINE_NBR to be non-empty in $FILE" 28 | exit 1 29 | fi 30 | else 31 | sed -n "$LINE_NBR p" $FILE | grep --silent "^[\/ ]\*$" 32 | if [[ $? -ne 0 ]]; then 33 | echo "Expected line $LINE_NBR to be empty in $FILE" 34 | exit 1 35 | fi 36 | fi 37 | done 38 | 39 | exit 0 40 | -------------------------------------------------------------------------------- /script/check_splint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #splint -linelen 999 -Disgreater -Disless dmtx.c 4 | splint -linelen 999 dmtx.c 5 | 6 | exit $? 7 | -------------------------------------------------------------------------------- /script/check_todo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | FILE="$1" 4 | 5 | COUNT=$(grep -i -e "XXX" -e "TODO" -e "FIXME" $FILE | wc -l) 6 | if [[ "$COUNT" -gt 0 ]]; then 7 | printf "%4d TODO(s) remain in $FILE\n" $COUNT 8 | exit 1 9 | fi 10 | 11 | exit 0 12 | -------------------------------------------------------------------------------- /script/check_whitespace.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | FILE="$1" 4 | 5 | LINE=$(grep -n " $" $FILE) 6 | if [[ $? -eq 0 ]]; then 7 | echo -e "Trailing whitespace found in $FILE on line(s):\n$LINE" 8 | exit 1 9 | fi 10 | 11 | exit 0 12 | -------------------------------------------------------------------------------- /script/common_tasks.txt: -------------------------------------------------------------------------------- 1 | #!/make/me/a/sandwich 2 | 3 | Common Tasks 4 | ----------------------------------------------------------------- 5 | 6 | Generate splint warnings 7 | $ splint -posix-strict-lib dmtx.c 8 | 9 | 10 | Release Checklist 11 | ----------------------------------------------------------------- 12 | 13 | 1) o Include newly added files in lists below if appropriate 14 | 15 | 2) o Create copy of this file as living checklist 16 | 17 | 3) o Test for common style and formatting issues 18 | 19 | o $ script/check_all.sh . 20 | 21 | 4) o Review and close applicable bugs and feature requests 22 | 23 | 5) o Write and finalize release documentation 24 | 25 | o ReleaseNotes.txt (not in Git or source distribution) 26 | 27 | o ChangeLog 28 | o LICENSE o KNOWNBUG 29 | o NEWS o TODO 30 | 31 | o README 32 | o README.freebsd o README.cygwin 33 | o README.mingw o README.linux 34 | o README.unix o README.osx 35 | 36 | o man/libdmtx.3 37 | 38 | 6) o Update version number in appropriate files 39 | 40 | o configure.ac 41 | o dmtx.h 42 | o man/libdmtx.3 43 | 44 | 7) o Update release date in appropriate files 45 | 46 | o TODO 47 | o man/libdmtx.3 (be sure to sync w/ simple_test.c) 48 | 49 | 8) o Perform final test build 50 | 51 | o $ git status # no staged commits 52 | o $ git pull # get any pending updates 53 | o # final commit 54 | o $ sudo make uninstall && make clean && make distclean 55 | o $ ./autogen.sh && ./configure && make && make check && sudo make install 56 | o # Run tests and confirm it works. Start step over if changes are needed. 57 | 58 | 9) o Build and test tarballs 59 | 60 | o $ cd .. 61 | o $ git clone git://libdmtx.git.sourceforge.net/gitroot/libdmtx/libdmtx release 62 | o $ cd release 63 | o $ rm -Rf .git 64 | o $ find . -type d -name ".git" 65 | o $ ./autogen.sh && ./configure # don't build though 66 | o $ make dist-gzip 67 | o $ make dist-bzip2 68 | o $ make dist-zip 69 | o Verify no extraneous files made their way into the 70 | distribution (especially in the wrapper directories) 71 | o $ md5sum libdmtx-0.8.0.* > MD5SUM.txt 72 | 73 | 10) o SourceForge release administration 74 | 75 | o Upload files to SourceForge 76 | o Publish news item 77 | 78 | 11) o Tag final release in Git (do this only after uploading to 79 | SourceForge in case something changes at the last minute) 80 | 81 | o $ git tag -a -m "Tagged v0.7.4" v0.7.4 82 | o $ git push origin --tags 83 | 84 | 12) o Update minor number in unstable trunk (e.g., 0.8.0 -> 0.8.1) 85 | 86 | o Use file list from step 6 above 87 | o $ ./autogen.sh 88 | o $ ./configure 89 | o $ git commit -a 90 | o $ git push 91 | 92 | 13) o Check out tagged version so dmtx-utils and dmtx-wrapper 93 | builds will inherit correct version numbers 94 | 95 | o $ git checkout v0.7.4 96 | o $ ./autogen.sh 97 | o $ ./configure 98 | o $ make clean 99 | o $ make 100 | o # sudo make install 101 | 102 | 13) o Update libdmtx.org with news item, download entry, and new 103 | project status 104 | 105 | 14) o Send message to libdmtx-announcements@lists.sourceforge.net 106 | with subject "libdmtx: 0.8.0 Released" and ReleaseNotes.txt 107 | as message body 108 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12) 2 | 3 | enable_testing() 4 | 5 | link_directories(../build) 6 | 7 | add_executable(test_simple 8 | "simple_test/simple_test.c") 9 | target_link_libraries(test_simple PRIVATE dmtx m) 10 | add_test(NAME test_simple COMMAND $) 11 | 12 | add_executable(test_unit 13 | "unit_test/unit_test.c") 14 | target_link_libraries(test_unit PRIVATE dmtx m) 15 | add_test(NAME test_unit COMMAND $) 16 | -------------------------------------------------------------------------------- /test/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = simple_test 2 | #SUBDIRS = multi_test rotate_test simple_test unit_test 3 | -------------------------------------------------------------------------------- /test/compare_test/Makefile: -------------------------------------------------------------------------------- 1 | test: 2 | @./compare_generated.sh 3 | @./compare_confirmed.sh 4 | @./compare_siemens.sh 5 | 6 | clean: 7 | rm -f compare_generated/barcode_*_?.pnm 8 | rm -f compare_confirmed/barcode_*_?.pnm 9 | rm -f compare_siemens/siemens_*_?.pnm 10 | 11 | .PHONY: test clean 12 | -------------------------------------------------------------------------------- /test/compare_test/TODO: -------------------------------------------------------------------------------- 1 | o Test that "best" option is always as good or better than others 2 | o Measure how often "best" gives exact results as a straight option 3 | o Count how often "best" beats "fast" (and visa versa) 4 | -------------------------------------------------------------------------------- /test/compare_test/compare_confirmed.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ERROR_COUNT=0 4 | 5 | echo "Comparing generated barcodes against confirmed results" 6 | echo "-----------------------------------------------------------------" 7 | 8 | for CONFIRMED in compare_confirmed/barcode_*_?.png; do 9 | 10 | GENERATED="compare_generated/$(basename $CONFIRMED | sed -e 's/^confirmed_/barcode_/')" 11 | if [[ ! -s "$GENERATED" ]]; then 12 | echo "FILE MISSING: Please run compare_generated.sh first." 13 | exit 1 14 | fi 15 | 16 | GENERATED_MD5SUM=$(convert -depth 8 -type TrueColor $GENERATED pnm: | md5sum) 17 | GENERATED_ERROR=$? 18 | 19 | CONFIRMED_MD5SUM=$(convert -depth 8 -type TrueColor $CONFIRMED pnm: | md5sum) 20 | CONFIRMED_ERROR=$? 21 | 22 | if [[ "$GENERATED_ERROR" -ne 0 || "$CONFIRMED_ERROR" -ne 0 ]]; then 23 | echo "Error: convert failed" 24 | exit 1 25 | fi 26 | 27 | if [[ "$GENERATED_MD5SUM" == "$CONFIRMED_MD5SUM" ]]; then 28 | echo "SUCCESS: $(basename $CONFIRMED)" 29 | else 30 | echo "FAILURE: $(basename $GENERATED)" 31 | ERROR_COUNT=$[$ERROR_COUNT + 1] 32 | fi 33 | 34 | done 35 | 36 | echo "$ERROR_COUNT difference(s) found" 37 | echo "" 38 | 39 | exit 0 40 | -------------------------------------------------------------------------------- /test/compare_test/compare_confirmed/barcode_004_a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_confirmed/barcode_004_a.png -------------------------------------------------------------------------------- /test/compare_test/compare_confirmed/barcode_014_c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_confirmed/barcode_014_c.png -------------------------------------------------------------------------------- /test/compare_test/compare_confirmed/barcode_060_e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_confirmed/barcode_060_e.png -------------------------------------------------------------------------------- /test/compare_test/compare_generated.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #SCHEMES="b f a c t x e 8" 4 | SCHEMES="b a c t x e 8" 5 | DMTXWRITE="$(which dmtxwrite)" 6 | DMTXREAD="$(which dmtxread)" 7 | MOGRIFY=$(which mogrify) 8 | COMPARE_DIR="compare_generated" 9 | 10 | if [[ ! -x "$DMTXWRITE" ]]; then 11 | echo "Unable to execute \"$DMTXWRITE\"" 12 | exit 1 13 | fi 14 | 15 | if [[ ! -x "$DMTXREAD" ]]; then 16 | echo "Unable to execute \"$DMTXREAD\"" 17 | exit 1 18 | fi 19 | 20 | if [[ ! -x "$MOGRIFY" ]]; then 21 | echo "Unable to find or execute mogrify" 22 | exit 1 23 | fi 24 | 25 | if [[ ! -d "$COMPARE_DIR" ]]; then 26 | $(which mkdir) "$COMPARE_DIR" 27 | fi 28 | 29 | ERROR_COUNT=0 30 | 31 | echo "Generating and reading back barcodes from input messages" 32 | echo "-----------------------------------------------------------------" 33 | 34 | for file in input_messages/message_*.dat; do 35 | 36 | ENCODE=$(cat $file) 37 | MESSAGE=$(basename $file .dat | cut -d'_' -f2) 38 | 39 | for scheme in $SCHEMES; do 40 | 41 | OUTPUT="${COMPARE_DIR}/barcode_${MESSAGE}_${scheme}" 42 | $DMTXWRITE -e$scheme -o ${OUTPUT}.png $file 1>/dev/null 2>&1 43 | ERROR=$? 44 | if [[ "$ERROR" -eq 70 ]]; then 45 | # XXX revisit this to use more specific error code when available 46 | echo " SKIP: message $MESSAGE scheme ${scheme} (unsupported character)" 47 | continue; 48 | elif [[ "$ERROR" -ne 0 && "$ERROR" -ne 70 ]]; then 49 | echo " ERROR: dmtxwrite failed" 50 | exit "$ERROR"; 51 | fi 52 | 53 | $MOGRIFY -depth 8 -type TrueColor ${OUTPUT}.png 54 | ERROR=$? 55 | if [[ $? -ne 0 ]]; then 56 | echo " ERROR: mogrify failed" 57 | exit "$ERROR"; 58 | fi 59 | 60 | DECODE=$($DMTXREAD ${OUTPUT}.png) 61 | ERROR=$? 62 | if [[ $? -ne 0 ]]; then 63 | echo " ERROR: dmtxread failed" 64 | exit "$ERROR"; 65 | fi 66 | 67 | if [[ "$ENCODE" == "$DECODE" ]]; then 68 | echo "SUCCESS: message $MESSAGE scheme ${scheme}" 69 | else 70 | echo "FAILURE: message $MESSAGE scheme ${scheme}" 71 | ERROR_COUNT=$[$ERROR_COUNT + 1] 72 | fi 73 | 74 | done 75 | done 76 | 77 | echo "$ERROR_COUNT error(s) encountered" 78 | echo "" 79 | 80 | exit 0 81 | -------------------------------------------------------------------------------- /test/compare_test/compare_siemens.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ERROR_COUNT=0 4 | 5 | for PNG_BARCODE in compare_siemens/siemens_*_?.png; do 6 | PNM_BARCODE=$(echo $PNG_BARCODE | sed -e 's/\.png$/.pnm/') 7 | convert -depth 8 -type TrueColor $PNG_BARCODE $PNM_BARCODE 8 | done 9 | 10 | echo "Comparing generated barcodes against Seimens results" 11 | echo "-----------------------------------------------------------------" 12 | 13 | for file in compare_siemens/siemens_*_?.pnm; do 14 | 15 | TEST_BARCODE=compare_generated/$(basename $file | sed -e 's/^siemens_/barcode_/') 16 | if [[ ! -r "$TEST_BARCODE" ]]; then 17 | continue 18 | fi 19 | 20 | cmp $file $TEST_BARCODE 21 | if [[ $? -ne 0 ]]; then 22 | ERROR_COUNT=$[$ERROR_COUNT + 1] 23 | fi 24 | 25 | done 26 | 27 | echo "$ERROR_COUNT difference(s) found" 28 | echo "" 29 | 30 | exit 0 31 | -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_000_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_000_8.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_000_a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_000_a.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_000_c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_000_c.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_000_f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_000_f.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_000_t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_000_t.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_001_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_001_8.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_001_a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_001_a.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_001_c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_001_c.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_001_f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_001_f.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_001_t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_001_t.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_002_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_002_8.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_002_a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_002_a.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_002_c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_002_c.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_002_f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_002_f.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_002_t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_002_t.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_003_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_003_8.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_003_a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_003_a.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_003_c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_003_c.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_003_f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_003_f.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_003_t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_003_t.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_004_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_004_8.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_004_a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_004_a.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_004_c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_004_c.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_004_f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_004_f.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_004_t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_004_t.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_005_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_005_8.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_005_a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_005_a.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_005_c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_005_c.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_005_f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_005_f.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_005_t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_005_t.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_006_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_006_8.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_006_a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_006_a.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_006_c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_006_c.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_006_f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_006_f.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_006_t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_006_t.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_007_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_007_8.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_007_a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_007_a.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_007_c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_007_c.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_007_f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_007_f.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_007_t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_007_t.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_008_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_008_8.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_008_a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_008_a.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_008_c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_008_c.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_008_f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_008_f.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_008_t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_008_t.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_009_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_009_8.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_009_a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_009_a.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_009_c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_009_c.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_009_f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_009_f.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_009_t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_009_t.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_010_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_010_8.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_010_a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_010_a.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_010_c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_010_c.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_010_f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_010_f.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_010_t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_010_t.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_011_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_011_8.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_011_a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_011_a.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_011_c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_011_c.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_011_f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_011_f.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_011_t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_011_t.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_012_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_012_8.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_012_a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_012_a.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_012_c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_012_c.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_012_f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_012_f.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_012_t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_012_t.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_013_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_013_8.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_013_a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_013_a.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_013_c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_013_c.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_013_f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_013_f.png -------------------------------------------------------------------------------- /test/compare_test/compare_siemens/siemens_013_t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/compare_test/compare_siemens/siemens_013_t.png -------------------------------------------------------------------------------- /test/compare_test/input_messages/message_000.dat: -------------------------------------------------------------------------------- 1 | abcdefghijklmnopqrsABCDEFGHIJKLMNOPQRS -------------------------------------------------------------------------------- /test/compare_test/input_messages/message_001.dat: -------------------------------------------------------------------------------- 1 | abcdefghijklmABCDEFGHIJKLM0123456789 -------------------------------------------------------------------------------- /test/compare_test/input_messages/message_002.dat: -------------------------------------------------------------------------------- 1 | libdmtx is a shared library for Linux that can be used to read (scan & decode) and write (encode & print) 2D Data Matrix barcode symbols. It is released under the LGPL and can be used and distributed freely under these terms. 2 | Data Matrix barcodes are two-dimensional symbols that hold a dense pattern of data with built-in error correction. The Data Matrix symbology (sometimes referred to as DataMatrix) was invented and released into the public domain by RVSI Acuity CiMatrix. Wikipedia has a good article on the symbology and its characteristics. -------------------------------------------------------------------------------- /test/compare_test/input_messages/message_003.dat: -------------------------------------------------------------------------------- 1 | This test case contains newline charactes, 2 | including in the middle and at the end of 3 | the message. 4 | -------------------------------------------------------------------------------- /test/compare_test/input_messages/message_004.dat: -------------------------------------------------------------------------------- 1 | 123456 -------------------------------------------------------------------------------- /test/compare_test/input_messages/message_005.dat: -------------------------------------------------------------------------------- 1 | 123456789012345678901234567890123456789012345678901234567890 -------------------------------------------------------------------------------- /test/compare_test/input_messages/message_006.dat: -------------------------------------------------------------------------------- 1 | 30Q324343430794 21 | 22 | #define MAXFACTORS 32 23 | /* e.g. an fft of length 128 has 4 factors 24 | as far as kissfft is concerned 25 | 4*4*4*2 26 | */ 27 | 28 | struct kiss_fft_state{ 29 | int nfft; 30 | int inverse; 31 | int factors[2*MAXFACTORS]; 32 | kiss_fft_cpx twiddles[1]; 33 | }; 34 | 35 | /* 36 | Explanation of macros dealing with complex math: 37 | 38 | C_MUL(m,a,b) : m = a*b 39 | C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise 40 | C_SUB( res, a,b) : res = a - b 41 | C_SUBFROM( res , a) : res -= a 42 | C_ADDTO( res , a) : res += a 43 | * */ 44 | #ifdef FIXED_POINT 45 | #if (FIXED_POINT==32) 46 | # define FRACBITS 31 47 | # define SAMPPROD int64_t 48 | #define SAMP_MAX 2147483647 49 | #else 50 | # define FRACBITS 15 51 | # define SAMPPROD int32_t 52 | #define SAMP_MAX 32767 53 | #endif 54 | 55 | #define SAMP_MIN -SAMP_MAX 56 | 57 | #if defined(CHECK_OVERFLOW) 58 | # define CHECK_OVERFLOW_OP(a,op,b) \ 59 | if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \ 60 | fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) ); } 61 | #endif 62 | 63 | 64 | # define smul(a,b) ( (SAMPPROD)(a)*(b) ) 65 | # define sround( x ) (kiss_fft_scalar)( ( (x) + (1<<(FRACBITS-1)) ) >> FRACBITS ) 66 | 67 | # define S_MUL(a,b) sround( smul(a,b) ) 68 | 69 | # define C_MUL(m,a,b) \ 70 | do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \ 71 | (m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0) 72 | 73 | # define DIVSCALAR(x,k) \ 74 | (x) = sround( smul( x, SAMP_MAX/k ) ) 75 | 76 | # define C_FIXDIV(c,div) \ 77 | do { DIVSCALAR( (c).r , div); \ 78 | DIVSCALAR( (c).i , div); }while (0) 79 | 80 | # define C_MULBYSCALAR( c, s ) \ 81 | do{ (c).r = sround( smul( (c).r , s ) ) ;\ 82 | (c).i = sround( smul( (c).i , s ) ) ; }while(0) 83 | 84 | #else /* not FIXED_POINT*/ 85 | 86 | # define S_MUL(a,b) ( (a)*(b) ) 87 | #define C_MUL(m,a,b) \ 88 | do{ (m).r = (a).r*(b).r - (a).i*(b).i;\ 89 | (m).i = (a).r*(b).i + (a).i*(b).r; }while(0) 90 | # define C_FIXDIV(c,div) /* NOOP */ 91 | # define C_MULBYSCALAR( c, s ) \ 92 | do{ (c).r *= (s);\ 93 | (c).i *= (s); }while(0) 94 | #endif 95 | 96 | #ifndef CHECK_OVERFLOW_OP 97 | # define CHECK_OVERFLOW_OP(a,op,b) /* noop */ 98 | #endif 99 | 100 | #define C_ADD( res, a,b)\ 101 | do { \ 102 | CHECK_OVERFLOW_OP((a).r,+,(b).r)\ 103 | CHECK_OVERFLOW_OP((a).i,+,(b).i)\ 104 | (res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \ 105 | }while(0) 106 | #define C_SUB( res, a,b)\ 107 | do { \ 108 | CHECK_OVERFLOW_OP((a).r,-,(b).r)\ 109 | CHECK_OVERFLOW_OP((a).i,-,(b).i)\ 110 | (res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \ 111 | }while(0) 112 | #define C_ADDTO( res , a)\ 113 | do { \ 114 | CHECK_OVERFLOW_OP((res).r,+,(a).r)\ 115 | CHECK_OVERFLOW_OP((res).i,+,(a).i)\ 116 | (res).r += (a).r; (res).i += (a).i;\ 117 | }while(0) 118 | 119 | #define C_SUBFROM( res , a)\ 120 | do {\ 121 | CHECK_OVERFLOW_OP((res).r,-,(a).r)\ 122 | CHECK_OVERFLOW_OP((res).i,-,(a).i)\ 123 | (res).r -= (a).r; (res).i -= (a).i; \ 124 | }while(0) 125 | 126 | 127 | #ifdef FIXED_POINT 128 | # define KISS_FFT_COS(phase) floor(.5+SAMP_MAX * cos (phase)) 129 | # define KISS_FFT_SIN(phase) floor(.5+SAMP_MAX * sin (phase)) 130 | # define HALF_OF(x) ((x)>>1) 131 | #elif defined(USE_SIMD) 132 | # define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) ) 133 | # define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) ) 134 | # define HALF_OF(x) ((x)*_mm_set1_ps(.5)) 135 | #else 136 | # define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase) 137 | # define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase) 138 | # define HALF_OF(x) ((x)*.5) 139 | #endif 140 | 141 | #define kf_cexp(x,phase) \ 142 | do{ \ 143 | (x)->r = KISS_FFT_COS(phase);\ 144 | (x)->i = KISS_FFT_SIN(phase);\ 145 | }while(0) 146 | 147 | 148 | /* a debugging function */ 149 | #define pcpx(c)\ 150 | fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) ) 151 | 152 | 153 | #ifdef KISS_FFT_USE_ALLOCA 154 | // define this to allow use of alloca instead of malloc for temporary buffers 155 | // Temporary buffers are used in two case: 156 | // 1. FFT sizes that have "bad" factors. i.e. not 2,3 and 5 157 | // 2. "in-place" FFTs. Notice the quotes, since kissfft does not really do an in-place transform. 158 | #include 159 | #define KISS_FFT_TMP_ALLOC(nbytes) alloca(nbytes) 160 | #define KISS_FFT_TMP_FREE(ptr) 161 | #else 162 | #define KISS_FFT_TMP_ALLOC(nbytes) KISS_FFT_MALLOC(nbytes) 163 | #define KISS_FFT_TMP_FREE(ptr) KISS_FFT_FREE(ptr) 164 | #endif 165 | -------------------------------------------------------------------------------- /test/multi_test/dmtx.c: -------------------------------------------------------------------------------- 1 | #include "../../dmtx.c" 2 | -------------------------------------------------------------------------------- /test/multi_test/dmtxaccel.c: -------------------------------------------------------------------------------- 1 | /** 2 | * libdmtx - Data Matrix Encoding/Decoding Library 3 | * Copyright 2010 Mike Laughton. All rights reserved. 4 | * 5 | * See LICENSE file in the main project directory for full 6 | * terms of use and distribution. 7 | * 8 | * Contact: Mike Laughton 9 | * 10 | * \file dmtxaccel.c 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include "../../dmtx.h" 17 | #include "multi_test.h" 18 | 19 | /** 20 | * 21 | * 22 | */ 23 | DmtxAccel * 24 | AccelCreate(DmtxSobel *sobel) 25 | { 26 | int sWidth, sHeight; 27 | int vWidth, vHeight; 28 | int hWidth, hHeight; 29 | DmtxAccel *accel; 30 | 31 | accel = (DmtxAccel *)calloc(1, sizeof(DmtxAccel)); 32 | if(accel == NULL) 33 | return NULL; 34 | 35 | sWidth = dmtxValueGridGetWidth(sobel->v); 36 | sHeight = dmtxValueGridGetHeight(sobel->v); 37 | 38 | vWidth = sWidth - 1; 39 | vHeight = sHeight; 40 | 41 | hWidth = sWidth; 42 | hHeight = sHeight - 1; 43 | 44 | accel->vv = dmtxValueGridCreate(vWidth, vHeight, DmtxEdgeVertical, sobel->v); 45 | accel->vb = dmtxValueGridCreate(vWidth, vHeight, DmtxEdgeVertical, sobel->b); 46 | accel->vs = dmtxValueGridCreate(vWidth, vHeight, DmtxEdgeVertical, sobel->s); 47 | accel->hb = dmtxValueGridCreate(hWidth, hHeight, DmtxEdgeHorizontal, sobel->b); 48 | accel->hh = dmtxValueGridCreate(hWidth, hHeight, DmtxEdgeHorizontal, sobel->h); 49 | accel->hs = dmtxValueGridCreate(hWidth, hHeight, DmtxEdgeHorizontal, sobel->s); 50 | 51 | if(accel->vv == NULL || accel->vb == NULL || accel->vs == NULL || 52 | accel->hb == NULL || accel->hh == NULL || accel->hs == NULL) 53 | { 54 | AccelDestroy(&accel); 55 | return NULL; 56 | } 57 | 58 | return accel; 59 | } 60 | 61 | /** 62 | * 63 | * 64 | */ 65 | DmtxPassFail 66 | AccelDestroy(DmtxAccel **accel) 67 | { 68 | if(accel == NULL || *accel == NULL) 69 | return DmtxFail; 70 | 71 | dmtxValueGridDestroy(&((*accel)->vs)); 72 | dmtxValueGridDestroy(&((*accel)->hs)); 73 | dmtxValueGridDestroy(&((*accel)->hh)); 74 | dmtxValueGridDestroy(&((*accel)->hb)); 75 | dmtxValueGridDestroy(&((*accel)->vb)); 76 | dmtxValueGridDestroy(&((*accel)->vv)); 77 | 78 | free(*accel); 79 | *accel = NULL; 80 | 81 | return DmtxPass; 82 | } 83 | 84 | #define RETURN_FAIL_IF(c) if(c) { return DmtxFail; } 85 | 86 | /** 87 | * 88 | * 89 | */ 90 | DmtxPassFail 91 | AccelPopulate(DmtxDecode2 *dec) 92 | { 93 | DmtxAccel *accel; 94 | 95 | assert(dec != NULL && dec->accel != NULL); 96 | 97 | accel = dec->accel; 98 | 99 | RETURN_FAIL_IF(AccelPopulateLocal(accel->vv) == DmtxFail); 100 | RETURN_FAIL_IF(AccelPopulateLocal(accel->vb) == DmtxFail); 101 | RETURN_FAIL_IF(AccelPopulateLocal(accel->hb) == DmtxFail); 102 | RETURN_FAIL_IF(AccelPopulateLocal(accel->hh) == DmtxFail); 103 | RETURN_FAIL_IF(AccelPopulateLocal(accel->hs) == DmtxFail); 104 | RETURN_FAIL_IF(AccelPopulateLocal(accel->vs) == DmtxFail); 105 | 106 | dec->fn.dmtxValueGridCallback(accel->vv, 4); 107 | dec->fn.dmtxValueGridCallback(accel->vb, 5); 108 | dec->fn.dmtxValueGridCallback(accel->hb, 7); 109 | dec->fn.dmtxValueGridCallback(accel->hh, 8); 110 | dec->fn.dmtxValueGridCallback(accel->hs, 9); 111 | dec->fn.dmtxValueGridCallback(accel->vs, 6); 112 | 113 | return DmtxPass; 114 | } 115 | 116 | #undef RETURN_FAIL_IF 117 | 118 | /** 119 | * 120 | * 121 | */ 122 | DmtxPassFail 123 | AccelPopulateLocal(DmtxValueGrid *acc) 124 | { 125 | int sWidth, sHeight; 126 | int aWidth, aHeight; 127 | int sIdx, sIdxNext, sInc, aIdx; 128 | int x, y; 129 | DmtxValueGrid *sob; 130 | 131 | sob = acc->ref; 132 | 133 | sWidth = dmtxValueGridGetWidth(sob); 134 | sHeight = dmtxValueGridGetHeight(sob); 135 | 136 | switch(acc->type) { 137 | case DmtxEdgeVertical: 138 | aWidth = sWidth - 1; 139 | aHeight = sHeight; 140 | sInc = 1; 141 | break; 142 | 143 | case DmtxEdgeHorizontal: 144 | aWidth = sWidth; 145 | aHeight = sHeight - 1; 146 | sInc = sWidth; 147 | break; 148 | 149 | default: 150 | return DmtxFail; 151 | } 152 | 153 | for(y = 0; y < aHeight; y++) 154 | { 155 | sIdx = y * sWidth; 156 | aIdx = y * aWidth; 157 | 158 | for(x = 0; x < aWidth; x++) 159 | { 160 | sIdxNext = sIdx + sInc; 161 | acc->value[aIdx] = sob->value[sIdxNext] - sob->value[sIdx]; 162 | aIdx++; 163 | sIdx++; 164 | } 165 | } 166 | 167 | return DmtxPass; 168 | } 169 | -------------------------------------------------------------------------------- /test/multi_test/dmtxdecode2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * libdmtx - Data Matrix Encoding/Decoding Library 3 | * Copyright 2010 Mike Laughton. All rights reserved. 4 | * 5 | * See LICENSE file in the main project directory for full 6 | * terms of use and distribution. 7 | * 8 | * Contact: Mike Laughton 9 | * 10 | * \file dmtxdecode2.c 11 | */ 12 | 13 | #include 14 | #include 15 | #include "../../dmtx.h" 16 | #include "multi_test.h" 17 | 18 | /** 19 | * 20 | * 21 | */ 22 | DmtxDecode2 * 23 | dmtxDecode2Create(DmtxImage *img) 24 | { 25 | DmtxDecode2 *dec; 26 | 27 | dec = (DmtxDecode2 *)calloc(1, sizeof(DmtxDecode2)); 28 | if(dec == NULL) 29 | return NULL; 30 | 31 | PopulateVanishBounds(dec); 32 | 33 | return dec; 34 | } 35 | 36 | /** 37 | * 38 | * 39 | */ 40 | DmtxPassFail 41 | dmtxDecode2Destroy(DmtxDecode2 **dec) 42 | { 43 | if(dec == NULL || *dec == NULL) 44 | return DmtxFail; 45 | 46 | decode2ReleaseCacheMemory(*dec); 47 | 48 | free(*dec); 49 | *dec = NULL; 50 | 51 | return DmtxPass; 52 | } 53 | 54 | #define RETURN_FAIL_IF(c) \ 55 | if(c) { \ 56 | decode2ReleaseCacheMemory(dec); \ 57 | return DmtxFail; \ 58 | } 59 | 60 | /** 61 | * 62 | * 63 | */ 64 | void 65 | PopulateVanishBounds(DmtxDecode2 *dec) 66 | { 67 | int d, phi; 68 | 69 | for(phi = 0; phi < 128; phi++) 70 | for(d = 0; d < 64; d++) 71 | dec->corners[d][phi] = GetVanishCorners(d, phi); 72 | } 73 | 74 | /** 75 | * 76 | * 77 | */ 78 | DmtxVanishCorners 79 | GetVanishCorners(int d, int phi) 80 | { 81 | DmtxVanishCorners vBound; 82 | DmtxVectorPair locs, dirs; 83 | int zone; 84 | int dFull, phiFull; 85 | double l, phiRad, bucketRad; 86 | DmtxVector2 v; 87 | 88 | dFull = d - 32; 89 | phiFull = (dFull < 0) ? phi + 128 : phi; 90 | assert(phiFull >= 0 && phiFull < 256); 91 | phiRad = phi * (M_PI/128.0); 92 | 93 | /* Infinity */ 94 | if(dFull == 0) 95 | { 96 | zone = GetZone(phiFull, NULL); 97 | locs = GetZoneCornerLocs(zone); 98 | 99 | dirs.a.X = dirs.b.X = cos(phiRad); /* XXX does phiRad point in this direction, or right angle? */ 100 | dirs.a.Y = dirs.b.Y = sin(phiRad); 101 | } 102 | else 103 | { 104 | bucketRad = abs(dFull) * (M_PI/96.0); 105 | l = 32/tan(bucketRad); 106 | zone = GetZone(phiFull, &l); 107 | locs = GetZoneCornerLocs(zone); 108 | 109 | v.X = l * cos(phiRad); 110 | v.Y = l * sin(phiRad); /* XXX remember phiRad may not point in direction you think */ 111 | 112 | dmtxVector2Sub(&dirs.a, &v, &locs.a); 113 | dmtxVector2Sub(&dirs.b, &v, &locs.b); 114 | 115 | dmtxVector2Norm(&dirs.a); /* I think this is necessary */ 116 | dmtxVector2Norm(&dirs.b); 117 | } 118 | 119 | vBound.zone = zone; 120 | vBound.lineA.p = locs.a; 121 | vBound.lineA.v = dirs.a; 122 | vBound.lineB.p = locs.b; 123 | vBound.lineB.v = dirs.b; 124 | 125 | return vBound; 126 | } 127 | 128 | /** 129 | * 130 | * 131 | */ 132 | int 133 | GetZone(int phiFull, double *distance) 134 | { 135 | int zone0 = 0; 136 | int zone1, zone2; 137 | double phiRad, xComp, yComp; 138 | 139 | if(phiFull < 32 || phiFull >= 224) 140 | zone1 = DmtxOctantTop; 141 | else if(phiFull < 96) 142 | zone1 = DmtxOctantLeft; 143 | else if(phiFull < 160) 144 | zone1 = DmtxOctantBottom; 145 | else 146 | zone1 = DmtxOctantRight; 147 | 148 | /* Orthagonal directions */ 149 | if(phiFull == 0 || phiFull == 64 || phiFull == 128 || phiFull == 196) 150 | return (distance != NULL && *distance < 32.0) ? zone0 : zone1; 151 | 152 | if(phiFull < 64) 153 | zone2 = DmtxOctantTopLeft; 154 | else if(phiFull < 128) 155 | zone2 = DmtxOctantBottomLeft; 156 | else if(phiFull < 192) 157 | zone2 = DmtxOctantBottomRight; 158 | else 159 | zone2 = DmtxOctantTopRight; 160 | 161 | /* Non-orthagonal vanishing point at infinity */ 162 | if(distance == NULL) 163 | return zone2; 164 | 165 | /* Must be a finite non-orthagonal vanishing point */ 166 | phiRad = phiFull * (M_PI/128.0); 167 | xComp = fabs(32.0/cos(phiRad)); /* remember phiRad may not point in direction you think */ 168 | yComp = fabs(32.0/sin(phiRad)); 169 | 170 | if(*distance > max(xComp,yComp)) 171 | return zone2; 172 | else if(*distance > min(xComp,yComp)) 173 | return zone1; 174 | 175 | return zone0; 176 | } 177 | 178 | /** 179 | * 180 | * 181 | */ 182 | DmtxVectorPair 183 | GetZoneCornerLocs(DmtxOctantType zone) 184 | { 185 | const DmtxVector2 p00 = { 0.0, 0.0 }; /* should be { -32.0, -32.0 } ? */ 186 | const DmtxVector2 p10 = { 1.0, 0.0 }; 187 | const DmtxVector2 p11 = { 1.0, 1.0 }; 188 | const DmtxVector2 p01 = { 0.0, 1.0 }; 189 | DmtxVectorPair locs; 190 | 191 | switch(zone) 192 | { 193 | case DmtxOctantTop: 194 | locs.a = p11; 195 | locs.b = p01; 196 | break; 197 | case DmtxOctantLeft: 198 | locs.a = p01; 199 | locs.b = p00; 200 | break; 201 | case DmtxOctantBottom: 202 | locs.a = p00; 203 | locs.b = p10; 204 | break; 205 | case DmtxOctantRight: 206 | locs.a = p10; 207 | locs.b = p11; 208 | break; 209 | case DmtxOctantTopLeft: 210 | case DmtxOctantBottomRight: 211 | locs.a = p00; 212 | locs.b = p11; 213 | break; 214 | case DmtxOctantBottomLeft: 215 | case DmtxOctantTopRight: 216 | default: /* XXX this feels wrong */ 217 | locs.a = p10; 218 | locs.b = p01; 219 | break; 220 | } 221 | 222 | return locs; 223 | } 224 | 225 | /** 226 | * 227 | * 228 | */ 229 | DmtxPassFail 230 | dmtxDecode2SetImage(DmtxDecode2 *dec, DmtxImage *img) 231 | { 232 | if(dec == NULL) 233 | return DmtxFail; 234 | 235 | dec->image = img; 236 | 237 | /* XXX decide here how big and how small to scale the image, and what level to go to */ 238 | /* store it in the decode struct */ 239 | 240 | /* Free existing buffers if sized incorrectly */ 241 | /* if(buffers are allocated but sized incorrectly) */ 242 | RETURN_FAIL_IF(decode2ReleaseCacheMemory(dec) == DmtxFail); 243 | 244 | /* Allocate new buffers if necessary */ 245 | /* if(buffers are not allocated) */ 246 | dec->sobel = SobelCreate(dec->image); 247 | RETURN_FAIL_IF(dec->sobel == NULL); 248 | 249 | dec->accel = AccelCreate(dec->sobel); 250 | RETURN_FAIL_IF(dec->accel == NULL); 251 | 252 | dec->hough = HoughCreate(1,1); 253 | RETURN_FAIL_IF(dec->hough == NULL); 254 | 255 | /* Necessary to zero out buffers? */ 256 | 257 | RETURN_FAIL_IF(SobelPopulate(dec) == DmtxFail); 258 | RETURN_FAIL_IF(AccelPopulate(dec) == DmtxFail); 259 | RETURN_FAIL_IF(HoughPopulate(dec) == DmtxFail); 260 | 261 | return DmtxPass; 262 | } 263 | 264 | #undef RETURN_FAIL_IF 265 | 266 | /** 267 | * 268 | * 269 | */ 270 | DmtxPassFail 271 | decode2ReleaseCacheMemory(DmtxDecode2 *dec) 272 | { 273 | if(dec == NULL) 274 | return DmtxFail; 275 | 276 | HoughDestroy(&(dec->hough)); 277 | AccelDestroy(&(dec->accel)); 278 | SobelDestroy(&(dec->sobel)); 279 | 280 | return DmtxPass; 281 | } 282 | -------------------------------------------------------------------------------- /test/multi_test/dmtxsobel.c: -------------------------------------------------------------------------------- 1 | /** 2 | * libdmtx - Data Matrix Encoding/Decoding Library 3 | * Copyright 2010 Mike Laughton. All rights reserved. 4 | * 5 | * See LICENSE file in the main project directory for full 6 | * terms of use and distribution. 7 | * 8 | * Contact: Mike Laughton 9 | * 10 | * \file dmtxsobel.c 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include "../../dmtx.h" 17 | #include "multi_test.h" 18 | 19 | /** 20 | * 21 | * 22 | */ 23 | DmtxSobel * 24 | SobelCreate(DmtxImage *img) 25 | { 26 | int sWidth, sHeight; 27 | DmtxSobel *sobel; 28 | 29 | sobel = (DmtxSobel *)calloc(1, sizeof(DmtxSobel)); 30 | if(sobel == NULL) 31 | return NULL; 32 | 33 | sWidth = dmtxImageGetProp(img, DmtxPropWidth) - 2; 34 | sHeight = dmtxImageGetProp(img, DmtxPropHeight) - 2; 35 | 36 | sobel->v = dmtxValueGridCreate(sWidth, sHeight, DmtxEdgeVertical, NULL); 37 | sobel->b = dmtxValueGridCreate(sWidth, sHeight, DmtxEdgeBackslash, NULL); 38 | sobel->h = dmtxValueGridCreate(sWidth, sHeight, DmtxEdgeHorizontal, NULL); 39 | sobel->s = dmtxValueGridCreate(sWidth, sHeight, DmtxEdgeSlash, NULL); 40 | 41 | if(sobel->v == NULL || sobel->b == NULL || sobel->h == NULL || sobel->s == NULL) 42 | { 43 | SobelDestroy(&sobel); 44 | return NULL; 45 | } 46 | 47 | return sobel; 48 | } 49 | 50 | /** 51 | * 52 | * 53 | */ 54 | DmtxPassFail 55 | SobelDestroy(DmtxSobel **sobel) 56 | { 57 | if(sobel == NULL || *sobel == NULL) 58 | return DmtxFail; 59 | 60 | dmtxValueGridDestroy(&((*sobel)->s)); 61 | dmtxValueGridDestroy(&((*sobel)->h)); 62 | dmtxValueGridDestroy(&((*sobel)->b)); 63 | dmtxValueGridDestroy(&((*sobel)->v)); 64 | 65 | free(*sobel); 66 | *sobel = NULL; 67 | 68 | return DmtxPass; 69 | } 70 | 71 | /** 72 | * 3x3 Sobel Kernel 73 | * 74 | */ 75 | DmtxPassFail 76 | SobelPopulate(DmtxDecode2 *dec) 77 | { 78 | int bytesPerPixel, rowSizeBytes, colorPlane; 79 | int sx, sy; 80 | int py, pOffset; 81 | int vMag, bMag, hMag, sMag; 82 | int colorLoLf, colorLoMd, colorLoRt; 83 | int colorMdRt, colorHiRt, colorHiMd; 84 | int colorHiLf, colorMdLf, colorMdMd; 85 | int idx; 86 | int sWidth, sHeight; 87 | DmtxSobel *sobel = dec->sobel; 88 | DmtxImage *img = dec->image; 89 | 90 | assert(dec != NULL); 91 | 92 | sobel = dec->sobel; 93 | img = dec->image; 94 | 95 | assert(sobel != NULL && img != NULL); 96 | 97 | sWidth = dmtxImageGetProp(img, DmtxPropWidth) - 2; 98 | sHeight = dmtxImageGetProp(img, DmtxPropHeight) - 2; 99 | 100 | rowSizeBytes = dmtxImageGetProp(img, DmtxPropRowSizeBytes); 101 | bytesPerPixel = dmtxImageGetProp(img, DmtxPropBytesPerPixel); 102 | colorPlane = 1; /* XXX need to make some decisions here */ 103 | 104 | for(sy = 0; sy < sHeight; sy++) 105 | { 106 | py = sHeight - sy; 107 | 108 | pOffset = py * rowSizeBytes + colorPlane; 109 | colorHiLf = img->pxl[pOffset - rowSizeBytes]; 110 | colorMdLf = img->pxl[pOffset]; 111 | colorLoLf = img->pxl[pOffset + rowSizeBytes]; 112 | 113 | pOffset += bytesPerPixel; 114 | colorHiMd = img->pxl[pOffset - rowSizeBytes]; 115 | colorMdMd = img->pxl[pOffset]; 116 | colorLoMd = img->pxl[pOffset + rowSizeBytes]; 117 | 118 | pOffset += bytesPerPixel; 119 | colorHiRt = img->pxl[pOffset - rowSizeBytes]; 120 | colorMdRt = img->pxl[pOffset]; 121 | colorLoRt = img->pxl[pOffset + rowSizeBytes]; 122 | 123 | for(sx = 0; sx < sWidth; sx++) 124 | { 125 | /** 126 | * -1 0 1 127 | * -2 0 2 128 | * -1 0 1 129 | */ 130 | vMag = colorHiRt; 131 | vMag += colorMdRt * 2; 132 | vMag += colorLoRt; 133 | vMag -= colorHiLf; 134 | vMag -= colorMdLf * 2; 135 | vMag -= colorLoLf; 136 | 137 | /** 138 | * 0 1 2 139 | * -1 0 1 140 | * -2 -1 0 141 | */ 142 | bMag = colorMdLf; 143 | bMag += colorLoLf * 2; 144 | bMag += colorLoMd; 145 | bMag -= colorMdRt; 146 | bMag -= colorHiRt * 2; 147 | bMag -= colorHiMd; 148 | 149 | /** 150 | * 1 2 1 151 | * 0 0 0 152 | * -1 -2 -1 153 | */ 154 | hMag = colorHiLf; 155 | hMag += colorHiMd * 2; 156 | hMag += colorHiRt; 157 | hMag -= colorLoLf; 158 | hMag -= colorLoMd * 2; 159 | hMag -= colorLoRt; 160 | 161 | /** 162 | * -2 -1 0 163 | * -1 0 1 164 | * 0 1 2 165 | */ 166 | sMag = colorLoMd; 167 | sMag += colorLoRt * 2; 168 | sMag += colorMdRt; 169 | sMag -= colorHiMd; 170 | sMag -= colorHiLf * 2; 171 | sMag -= colorMdLf; 172 | 173 | /** 174 | * If implementing these operations using MMX, can load 2 175 | * registers with 4 doubleword values and subtract (PSUBD). 176 | */ 177 | 178 | idx = sy * sWidth + sx; 179 | sobel->v->value[idx] = vMag; 180 | sobel->b->value[idx] = bMag; 181 | sobel->h->value[idx] = hMag; 182 | sobel->s->value[idx] = sMag; 183 | 184 | colorHiLf = colorHiMd; 185 | colorMdLf = colorMdMd; 186 | colorLoLf = colorLoMd; 187 | 188 | colorHiMd = colorHiRt; 189 | colorMdMd = colorMdRt; 190 | colorLoMd = colorLoRt; 191 | 192 | pOffset += bytesPerPixel; 193 | colorHiRt = img->pxl[pOffset - rowSizeBytes]; 194 | colorMdRt = img->pxl[pOffset]; 195 | colorLoRt = img->pxl[pOffset + rowSizeBytes]; 196 | } 197 | } 198 | 199 | dec->fn.dmtxValueGridCallback(sobel->v, 0); 200 | dec->fn.dmtxValueGridCallback(sobel->b, 1); 201 | dec->fn.dmtxValueGridCallback(sobel->h, 2); 202 | dec->fn.dmtxValueGridCallback(sobel->s, 3); 203 | 204 | return DmtxPass; 205 | } 206 | -------------------------------------------------------------------------------- /test/multi_test/dmtxvaluegrid.c: -------------------------------------------------------------------------------- 1 | /** 2 | * libdmtx - Data Matrix Encoding/Decoding Library 3 | * Copyright 2010 Mike Laughton. All rights reserved. 4 | * 5 | * See LICENSE file in the main project directory for full 6 | * terms of use and distribution. 7 | * 8 | * Contact: Mike Laughton 9 | * 10 | * \file dmtxvaluegrid.c 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include "../../dmtx.h" 17 | #include "multi_test.h" 18 | 19 | /** 20 | * 21 | * 22 | */ 23 | DmtxValueGrid * 24 | dmtxValueGridCreate(int width, int height, int type, DmtxValueGrid *ref) 25 | { 26 | DmtxValueGrid *valueGrid; 27 | 28 | valueGrid = (DmtxValueGrid *)calloc(1, sizeof(DmtxValueGrid)); 29 | if(valueGrid == NULL) 30 | return NULL; 31 | 32 | valueGrid->width = width; 33 | valueGrid->height = height; 34 | valueGrid->type = type; 35 | valueGrid->ref = ref; 36 | 37 | valueGrid->value = (int *)malloc(width * height * sizeof(int)); 38 | if(valueGrid->value == NULL) 39 | { 40 | dmtxValueGridDestroy(&valueGrid); 41 | return NULL; 42 | } 43 | 44 | return valueGrid; 45 | } 46 | 47 | /** 48 | * 49 | * 50 | */ 51 | DmtxPassFail 52 | dmtxValueGridDestroy(DmtxValueGrid **valueGrid) 53 | { 54 | if(valueGrid == NULL || *valueGrid == NULL) 55 | return DmtxFail; 56 | 57 | if((*valueGrid)->value != NULL) 58 | free((*valueGrid)->value); 59 | 60 | free(*valueGrid); 61 | *valueGrid = NULL; 62 | 63 | return DmtxPass; 64 | } 65 | 66 | /** 67 | * 68 | * 69 | */ 70 | int 71 | dmtxValueGridGetWidth(DmtxValueGrid *valueGrid) 72 | { 73 | if(valueGrid == NULL) 74 | return DmtxUndefined; 75 | 76 | return valueGrid->width; 77 | } 78 | 79 | /** 80 | * 81 | * 82 | */ 83 | int 84 | dmtxValueGridGetHeight(DmtxValueGrid *valueGrid) 85 | { 86 | if(valueGrid == NULL) 87 | return DmtxUndefined; 88 | 89 | return valueGrid->height; 90 | } 91 | 92 | /** 93 | * 94 | * 95 | */ 96 | int 97 | dmtxValueGridGetValue(DmtxValueGrid *valueGrid, int x, int y) 98 | { 99 | int idx; 100 | 101 | if(valueGrid == NULL) 102 | return DmtxUndefined; 103 | 104 | if(x < 0 || x >= valueGrid->width || y < 0 || y >= valueGrid->height) 105 | return 0; 106 | 107 | idx = y * valueGrid->width + x; 108 | 109 | return valueGrid->value[idx]; 110 | } 111 | -------------------------------------------------------------------------------- /test/multi_test/kiss_fft.h: -------------------------------------------------------------------------------- 1 | #ifndef KISS_FFT_H 2 | #define KISS_FFT_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /* 15 | ATTENTION! 16 | If you would like a : 17 | -- a utility that will handle the caching of fft objects 18 | -- real-only (no imaginary time component ) FFT 19 | -- a multi-dimensional FFT 20 | -- a command-line utility to perform ffts 21 | -- a command-line utility to perform fast-convolution filtering 22 | 23 | Then see kfc.h kiss_fftr.h kiss_fftnd.h fftutil.c kiss_fastfir.c 24 | in the tools/ directory. 25 | */ 26 | 27 | #ifdef USE_SIMD 28 | # include 29 | # define kiss_fft_scalar __m128 30 | #define KISS_FFT_MALLOC(nbytes) _mm_malloc(nbytes,16) 31 | #define KISS_FFT_FREE _mm_free 32 | #else 33 | #define KISS_FFT_MALLOC malloc 34 | #define KISS_FFT_FREE free 35 | #endif 36 | 37 | 38 | #ifdef FIXED_POINT 39 | #include 40 | # if (FIXED_POINT == 32) 41 | # define kiss_fft_scalar int32_t 42 | # else 43 | # define kiss_fft_scalar int16_t 44 | # endif 45 | #else 46 | # ifndef kiss_fft_scalar 47 | /* default is float */ 48 | # define kiss_fft_scalar float 49 | # endif 50 | #endif 51 | 52 | typedef struct { 53 | kiss_fft_scalar r; 54 | kiss_fft_scalar i; 55 | }kiss_fft_cpx; 56 | 57 | typedef struct kiss_fft_state* kiss_fft_cfg; 58 | 59 | /* 60 | * kiss_fft_alloc 61 | * 62 | * Initialize a FFT (or IFFT) algorithm's cfg/state buffer. 63 | * 64 | * typical usage: kiss_fft_cfg mycfg=kiss_fft_alloc(1024,0,NULL,NULL); 65 | * 66 | * The return value from fft_alloc is a cfg buffer used internally 67 | * by the fft routine or NULL. 68 | * 69 | * If lenmem is NULL, then kiss_fft_alloc will allocate a cfg buffer using malloc. 70 | * The returned value should be free()d when done to avoid memory leaks. 71 | * 72 | * The state can be placed in a user supplied buffer 'mem': 73 | * If lenmem is not NULL and mem is not NULL and *lenmem is large enough, 74 | * then the function places the cfg in mem and the size used in *lenmem 75 | * and returns mem. 76 | * 77 | * If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough), 78 | * then the function returns NULL and places the minimum cfg 79 | * buffer size in *lenmem. 80 | * */ 81 | 82 | kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem); 83 | 84 | /* 85 | * kiss_fft(cfg,in_out_buf) 86 | * 87 | * Perform an FFT on a complex input buffer. 88 | * for a forward FFT, 89 | * fin should be f[0] , f[1] , ... ,f[nfft-1] 90 | * fout will be F[0] , F[1] , ... ,F[nfft-1] 91 | * Note that each element is complex and can be accessed like 92 | f[k].r and f[k].i 93 | * */ 94 | void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout); 95 | 96 | /* 97 | A more generic version of the above function. It reads its input from every Nth sample. 98 | * */ 99 | void kiss_fft_stride(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int fin_stride); 100 | 101 | /* If kiss_fft_alloc allocated a buffer, it is one contiguous 102 | buffer and can be simply free()d when no longer needed*/ 103 | #define kiss_fft_free free 104 | 105 | /* 106 | Cleans up some memory that gets managed internally. Not necessary to call, but it might clean up 107 | your compiler output to call this before you exit. 108 | */ 109 | void kiss_fft_cleanup(void); 110 | 111 | 112 | /* 113 | * Returns the smallest integer k, such that k>=n and k has only "fast" factors (2,3,5) 114 | */ 115 | int kiss_fft_next_fast_size(int n); 116 | 117 | /* for real ffts, we need an even size */ 118 | #define kiss_fftr_next_fast_size_real(n) \ 119 | (kiss_fft_next_fast_size( ((n)+1)>>1)<<1) 120 | 121 | #ifdef __cplusplus 122 | } 123 | #endif 124 | 125 | #endif 126 | -------------------------------------------------------------------------------- /test/multi_test/kiss_fftr.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2004, Mark Borgerding 3 | 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 13 | */ 14 | 15 | #include "kiss_fftr.h" 16 | #include "_kiss_fft_guts.h" 17 | 18 | struct kiss_fftr_state{ 19 | kiss_fft_cfg substate; 20 | kiss_fft_cpx * tmpbuf; 21 | kiss_fft_cpx * super_twiddles; 22 | #ifdef USE_SIMD 23 | void * pad; 24 | #endif 25 | }; 26 | 27 | kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem) 28 | { 29 | int i; 30 | kiss_fftr_cfg st = NULL; 31 | size_t subsize, memneeded; 32 | 33 | if (nfft & 1) { 34 | fprintf(stderr,"Real FFT optimization must be even.\n"); 35 | return NULL; 36 | } 37 | nfft >>= 1; 38 | 39 | kiss_fft_alloc (nfft, inverse_fft, NULL, &subsize); 40 | memneeded = sizeof(struct kiss_fftr_state) + subsize + sizeof(kiss_fft_cpx) * ( nfft * 3 / 2); 41 | 42 | if (lenmem == NULL) { 43 | st = (kiss_fftr_cfg) KISS_FFT_MALLOC (memneeded); 44 | } else { 45 | if (*lenmem >= memneeded) 46 | st = (kiss_fftr_cfg) mem; 47 | *lenmem = memneeded; 48 | } 49 | if (!st) 50 | return NULL; 51 | 52 | st->substate = (kiss_fft_cfg) (st + 1); /*just beyond kiss_fftr_state struct */ 53 | st->tmpbuf = (kiss_fft_cpx *) (((char *) st->substate) + subsize); 54 | st->super_twiddles = st->tmpbuf + nfft; 55 | kiss_fft_alloc(nfft, inverse_fft, st->substate, &subsize); 56 | 57 | for (i = 0; i < nfft/2; ++i) { 58 | double phase = 59 | -3.14159265358979323846264338327 * ((double) (i+1) / nfft + .5); 60 | if (inverse_fft) 61 | phase *= -1; 62 | kf_cexp (st->super_twiddles+i,phase); 63 | } 64 | return st; 65 | } 66 | 67 | void kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata) 68 | { 69 | /* input buffer timedata is stored row-wise */ 70 | int k,ncfft; 71 | kiss_fft_cpx fpnk,fpk,f1k,f2k,tw,tdc; 72 | 73 | if ( st->substate->inverse) { 74 | fprintf(stderr,"kiss fft usage error: improper alloc\n"); 75 | exit(1); 76 | } 77 | 78 | ncfft = st->substate->nfft; 79 | 80 | /*perform the parallel fft of two real signals packed in real,imag*/ 81 | kiss_fft( st->substate , (const kiss_fft_cpx*)timedata, st->tmpbuf ); 82 | /* The real part of the DC element of the frequency spectrum in st->tmpbuf 83 | * contains the sum of the even-numbered elements of the input time sequence 84 | * The imag part is the sum of the odd-numbered elements 85 | * 86 | * The sum of tdc.r and tdc.i is the sum of the input time sequence. 87 | * yielding DC of input time sequence 88 | * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1... 89 | * yielding Nyquist bin of input time sequence 90 | */ 91 | 92 | tdc.r = st->tmpbuf[0].r; 93 | tdc.i = st->tmpbuf[0].i; 94 | C_FIXDIV(tdc,2); 95 | CHECK_OVERFLOW_OP(tdc.r ,+, tdc.i); 96 | CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i); 97 | freqdata[0].r = tdc.r + tdc.i; 98 | freqdata[ncfft].r = tdc.r - tdc.i; 99 | #ifdef USE_SIMD 100 | freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps(0); 101 | #else 102 | freqdata[ncfft].i = freqdata[0].i = 0; 103 | #endif 104 | 105 | for ( k=1;k <= ncfft/2 ; ++k ) { 106 | fpk = st->tmpbuf[k]; 107 | fpnk.r = st->tmpbuf[ncfft-k].r; 108 | fpnk.i = - st->tmpbuf[ncfft-k].i; 109 | C_FIXDIV(fpk,2); 110 | C_FIXDIV(fpnk,2); 111 | 112 | C_ADD( f1k, fpk , fpnk ); 113 | C_SUB( f2k, fpk , fpnk ); 114 | C_MUL( tw , f2k , st->super_twiddles[k-1]); 115 | 116 | freqdata[k].r = HALF_OF(f1k.r + tw.r); 117 | freqdata[k].i = HALF_OF(f1k.i + tw.i); 118 | freqdata[ncfft-k].r = HALF_OF(f1k.r - tw.r); 119 | freqdata[ncfft-k].i = HALF_OF(tw.i - f1k.i); 120 | } 121 | } 122 | 123 | void kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata) 124 | { 125 | /* input buffer timedata is stored row-wise */ 126 | int k, ncfft; 127 | 128 | if (st->substate->inverse == 0) { 129 | fprintf (stderr, "kiss fft usage error: improper alloc\n"); 130 | exit (1); 131 | } 132 | 133 | ncfft = st->substate->nfft; 134 | 135 | st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r; 136 | st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r; 137 | C_FIXDIV(st->tmpbuf[0],2); 138 | 139 | for (k = 1; k <= ncfft / 2; ++k) { 140 | kiss_fft_cpx fk, fnkc, fek, fok, tmp; 141 | fk = freqdata[k]; 142 | fnkc.r = freqdata[ncfft - k].r; 143 | fnkc.i = -freqdata[ncfft - k].i; 144 | C_FIXDIV( fk , 2 ); 145 | C_FIXDIV( fnkc , 2 ); 146 | 147 | C_ADD (fek, fk, fnkc); 148 | C_SUB (tmp, fk, fnkc); 149 | C_MUL (fok, tmp, st->super_twiddles[k-1]); 150 | C_ADD (st->tmpbuf[k], fek, fok); 151 | C_SUB (st->tmpbuf[ncfft - k], fek, fok); 152 | #ifdef USE_SIMD 153 | st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0); 154 | #else 155 | st->tmpbuf[ncfft - k].i *= -1; 156 | #endif 157 | } 158 | kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata); 159 | } 160 | -------------------------------------------------------------------------------- /test/multi_test/kiss_fftr.h: -------------------------------------------------------------------------------- 1 | #ifndef KISS_FTR_H 2 | #define KISS_FTR_H 3 | 4 | #include "kiss_fft.h" 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | 10 | /* 11 | 12 | Real optimized version can save about 45% cpu time vs. complex fft of a real seq. 13 | 14 | 15 | 16 | */ 17 | 18 | typedef struct kiss_fftr_state *kiss_fftr_cfg; 19 | 20 | 21 | kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem, size_t * lenmem); 22 | /* 23 | nfft must be even 24 | 25 | If you don't care to allocate space, use mem = lenmem = NULL 26 | */ 27 | 28 | 29 | void kiss_fftr(kiss_fftr_cfg cfg,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata); 30 | /* 31 | input timedata has nfft scalar points 32 | output freqdata has nfft/2+1 complex points 33 | */ 34 | 35 | void kiss_fftri(kiss_fftr_cfg cfg,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata); 36 | /* 37 | input freqdata has nfft/2+1 complex points 38 | output timedata has nfft scalar points 39 | */ 40 | 41 | #define kiss_fftr_free free 42 | 43 | #ifdef __cplusplus 44 | } 45 | #endif 46 | #endif 47 | -------------------------------------------------------------------------------- /test/rotate_test/Makefile.am: -------------------------------------------------------------------------------- 1 | AM_CPPFLAGS = -Wshadow -Wall -pedantic -std=c99 2 | 3 | check_PROGRAMS = rotate_test 4 | 5 | rotate_test_SOURCES = rotate_test.c callback.c display.c image.c dmtx.c 6 | 7 | EXTRA_rotate_test_SOURCES = callback.h display.h rotate_test.h image.h 8 | 9 | if TARGET_MACOSX 10 | rotate_test_LDFLAGS = -lm -lpng -framework OpenGL -lSDL -lSDLmain -framework Cocoa -lpthread 11 | else 12 | rotate_test_LDFLAGS = -lm -lpng -lGL -lGLU -lSDL -lpthread 13 | endif 14 | -------------------------------------------------------------------------------- /test/rotate_test/README: -------------------------------------------------------------------------------- 1 | This test program uses OpenGL (Mesa) to simulate camera input, 2 | and writes decoded Data Matrix streams to STDOUT. 3 | 4 | Right-click on the window to cycle through the test images. To 5 | add your own images for testing, just overwrite any image in the 6 | "rotate_test/images" directory with another 256x256 PNG file. If 7 | you want to add brand new images then you will have to update the 8 | gFilename[] and gFileCount variables at the top of rotate_test.c 9 | to include them. 10 | -------------------------------------------------------------------------------- /test/rotate_test/callback.h: -------------------------------------------------------------------------------- 1 | /** 2 | * libdmtx - Data Matrix Encoding/Decoding Library 3 | * Copyright 2007, 2008, 2009 Mike Laughton. All rights reserved. 4 | * 5 | * See LICENSE file in the main project directory for full 6 | * terms of use and distribution. 7 | * 8 | * Contact: Mike Laughton 9 | * 10 | * \file callback.h 11 | */ 12 | 13 | #ifndef __CALLBACK_H__ 14 | #define __CALLBACK_H__ 15 | 16 | void BuildMatrixCallback2(DmtxRegion *region); 17 | void BuildMatrixCallback3(DmtxMatrix3 region); 18 | void BuildMatrixCallback4(DmtxMatrix3 region); 19 | void PlotPointCallback(DmtxPixelLoc loc, int colorInt, int paneNbr, int dispType); 20 | void XfrmPlotPointCallback(DmtxVector2 point, DmtxMatrix3 xfrm, int paneNbr, int dispType); 21 | void FinalCallback(DmtxDecode *decode, DmtxRegion *region); 22 | /*void PlotModuleCallback(DmtxDecode *info, DmtxRegion *region, int row, int col, DmtxColor3 color);*/ 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /test/rotate_test/display.c: -------------------------------------------------------------------------------- 1 | /** 2 | * libdmtx - Data Matrix Encoding/Decoding Library 3 | * Copyright 2007, 2008, 2009 Mike Laughton. All rights reserved. 4 | * 5 | * See LICENSE file in the main project directory for full 6 | * terms of use and distribution. 7 | * 8 | * Contact: Mike Laughton 9 | * 10 | * \file display.c 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include "dmtx.h" 19 | #include "rotate_test.h" 20 | #include "display.h" 21 | 22 | /** 23 | * 24 | * 25 | */ 26 | SDL_Surface *initDisplay(void) 27 | { 28 | SDL_Surface *screen; 29 | 30 | SDL_Init(SDL_INIT_VIDEO); 31 | 32 | screen = SDL_SetVideoMode(968, 646, 16, SDL_OPENGL | SDL_RESIZABLE); 33 | if(!screen) { 34 | fprintf(stderr, "Couldn't set 968x646 GL video mode: %s\n", SDL_GetError()); 35 | SDL_Quit(); 36 | exit(2); 37 | } 38 | SDL_WM_SetCaption("GL Test", "GL Test"); 39 | 40 | glClearColor(0.0, 0.0, 0.3, 1.0); 41 | 42 | return screen; 43 | } 44 | 45 | /** 46 | * 47 | * 48 | */ 49 | void DrawBarCode(void) 50 | { 51 | glColor3f(0.95, 0.95, 0.95); 52 | glBegin(GL_QUADS); 53 | glTexCoord2d(0.0, 0.0); glVertex3f(-2.0, -2.0, 0.0); 54 | glTexCoord2d(1.0, 0.0); glVertex3f( 2.0, -2.0, 0.0); 55 | glTexCoord2d(1.0, 1.0); glVertex3f( 2.0, 2.0, 0.0); 56 | glTexCoord2d(0.0, 1.0); glVertex3f(-2.0, 2.0, 0.0); 57 | glEnd(); 58 | } 59 | 60 | /** 61 | * 62 | * 63 | */ 64 | void ReshapeWindow(int width, int height) 65 | { 66 | glViewport(2, 324, (GLint)320, (GLint)320); 67 | glMatrixMode(GL_PROJECTION); 68 | glLoadIdentity(); 69 | glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 50.0); 70 | glMatrixMode(GL_MODELVIEW); 71 | glLoadIdentity(); 72 | } 73 | 74 | /** 75 | * 76 | * 77 | */ 78 | void DrawBorders(SDL_Surface *screen) 79 | { 80 | /* window and pane borders */ 81 | DrawPaneBorder( 0, 0, 646, 968); 82 | 83 | DrawPaneBorder( 1, 1, 322, 322); 84 | DrawPaneBorder(323, 1, 322, 322); 85 | DrawPaneBorder(645, 1, 322, 322); 86 | 87 | DrawPaneBorder( 1, 323, 322, 322); 88 | DrawPaneBorder(323, 323, 322, 322); 89 | DrawPaneBorder(645, 323, 322, 322); 90 | } 91 | 92 | /** 93 | * 94 | * 95 | */ 96 | void DrawGeneratedImage(SDL_Surface *screen) 97 | { 98 | /* rotate barcode surface */ 99 | glViewport(2, 324, (GLint)320, (GLint)320); 100 | glMatrixMode(GL_PROJECTION); 101 | glLoadIdentity(); 102 | glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 50.0); 103 | glMatrixMode(GL_MODELVIEW); 104 | glLoadIdentity(); 105 | glTranslatef(0.0, 0.0, -10.0); 106 | glPolygonMode(GL_FRONT, GL_FILL); 107 | glPolygonMode(GL_BACK, GL_LINE); 108 | glEnable(GL_TEXTURE_2D); 109 | 110 | glPushMatrix(); 111 | glRotatef(view_rotx, 1.0, 0.0, 0.0); 112 | glRotatef(view_roty, 0.0, 1.0, 0.0); 113 | glRotatef(view_rotz, 0.0, 0.0, 1.0); 114 | glRotatef(angle, 0.0, 0.0, 1.0); 115 | glCallList(barcodeList); 116 | glPopMatrix(); 117 | } 118 | 119 | /** 120 | * 121 | * 122 | */ 123 | void DrawPane2(SDL_Surface *screen, unsigned char *pxl) 124 | { 125 | DrawPaneBorder(323, 323, 322, 322); /* XXX drawn twice */ 126 | glRasterPos2i(1, 1); 127 | glDrawPixels(320, 320, GL_RGB, GL_UNSIGNED_BYTE, pxl); 128 | } 129 | 130 | /** 131 | * 132 | * 133 | */ 134 | void DrawPane3(SDL_Surface *screen, unsigned char *pxl) 135 | { 136 | DrawPaneBorder(645, 323, 322, 322); /* XXX drawn twice */ 137 | glRasterPos2i(1, 1); 138 | glDrawPixels(320, 320, GL_RGB, GL_UNSIGNED_BYTE, pxl); 139 | } 140 | 141 | /** 142 | * 143 | * 144 | */ 145 | void DrawPane4(SDL_Surface *screen, unsigned char *pxl) 146 | { 147 | DrawPaneBorder(1, 1, 322, 322); /* XXX drawn twice */ 148 | glRasterPos2i(1, 1); 149 | glDrawPixels(320, 320, GL_RGB, GL_UNSIGNED_BYTE, pxl); 150 | } 151 | 152 | /** 153 | * 154 | * 155 | */ 156 | void DrawPane5(SDL_Surface *screen, unsigned char *pxl) 157 | { 158 | DrawPaneBorder(323, 1, 322, 322); /* XXX drawn twice */ 159 | glRasterPos2i(1, 1); 160 | glDrawPixels(320, 320, GL_RGB, GL_UNSIGNED_BYTE, pxl); 161 | } 162 | 163 | /** 164 | * 165 | * 166 | */ 167 | void DrawPane6(SDL_Surface *screen, unsigned char *pxl) 168 | { 169 | DrawPaneBorder(645, 1, 322, 322); /* XXX drawn twice */ 170 | glRasterPos2i(1, 1); 171 | 172 | if(pxl != NULL) 173 | glDrawPixels(320, 320, GL_RGB, GL_UNSIGNED_BYTE, pxl); 174 | } 175 | 176 | /** 177 | * 178 | * 179 | */ 180 | void DrawPaneBorder(GLint x, GLint y, GLint h, GLint w) 181 | { 182 | glDisable(GL_TEXTURE_2D); 183 | glColor3f(0.6, 0.6, 1.0); 184 | glPolygonMode(GL_FRONT, GL_LINE); 185 | glViewport(x, y, w, w); 186 | glMatrixMode(GL_PROJECTION); 187 | glLoadIdentity(); 188 | glOrtho(-0.5, w-0.5, -0.5, w-0.5, -1.0, 10.0); 189 | glMatrixMode(GL_MODELVIEW); 190 | glLoadIdentity(); 191 | 192 | glBegin(GL_QUADS); 193 | glVertex2f(0, 0); 194 | glVertex2f(w-1, 0); 195 | glVertex2f(w-1, h-1); 196 | glVertex2f(0, h-1); 197 | glEnd(); 198 | } 199 | 200 | /** 201 | * 202 | * 203 | */ 204 | int HandleEvent(SDL_Event *event, SDL_Surface *screen) 205 | { 206 | int width, height; 207 | 208 | switch(event->type) { 209 | case SDL_VIDEORESIZE: 210 | screen = SDL_SetVideoMode(event->resize.w, event->resize.h, 16, 211 | SDL_OPENGL | SDL_RESIZABLE); 212 | if(screen) { 213 | ReshapeWindow(screen->w, screen->h); 214 | } 215 | else { 216 | /* Uh oh, we couldn't set the new video mode? */; 217 | return(1); 218 | } 219 | break; 220 | 221 | case SDL_QUIT: 222 | return(1); 223 | break; 224 | 225 | case SDL_MOUSEMOTION: 226 | view_rotx = ((event->motion.y-160)/2.0); 227 | view_roty = ((event->motion.x-160)/2.0); 228 | break; 229 | 230 | case SDL_KEYDOWN: 231 | switch(event->key.keysym.sym) { 232 | case SDLK_ESCAPE: 233 | return(1); 234 | break; 235 | default: 236 | break; 237 | } 238 | break; 239 | 240 | case SDL_MOUSEBUTTONDOWN: 241 | switch(event->button.button) { 242 | case SDL_BUTTON_RIGHT: 243 | free(texturePxl); 244 | texturePxl = (unsigned char *)loadTextureImage(&width, &height); 245 | break; 246 | case SDL_BUTTON_LEFT: 247 | fprintf(stdout, "left click\n"); 248 | break; 249 | default: 250 | break; 251 | } 252 | break; 253 | } 254 | 255 | return(0); 256 | } 257 | -------------------------------------------------------------------------------- /test/rotate_test/display.h: -------------------------------------------------------------------------------- 1 | /** 2 | * libdmtx - Data Matrix Encoding/Decoding Library 3 | * Copyright 2007, 2008, 2009 Mike Laughton. All rights reserved. 4 | * 5 | * See LICENSE file in the main project directory for full 6 | * terms of use and distribution. 7 | * 8 | * Contact: Mike Laughton 9 | * 10 | * \file display.h 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | GLfloat view_rotx, view_roty, view_rotz; 18 | GLfloat angle; 19 | 20 | GLuint barcodeTexture; 21 | GLint barcodeList; 22 | 23 | SDL_Surface *initDisplay(void); 24 | void DrawBarCode(void); 25 | void ReshapeWindow(int width, int height); 26 | void DrawGeneratedImage(SDL_Surface *screen); 27 | void DrawBorders(SDL_Surface *screen); 28 | void DrawPane2(SDL_Surface *screen, unsigned char *pxl); 29 | void DrawPane3(SDL_Surface *screen, unsigned char *pxl); 30 | void DrawPane4(SDL_Surface *screen, unsigned char *pxl); 31 | void DrawPane5(SDL_Surface *screen, unsigned char *pxl); 32 | void DrawPane6(SDL_Surface *screen, unsigned char *pxl); 33 | int HandleEvent(SDL_Event *event, SDL_Surface *screen); 34 | void DrawPaneBorder(GLint x, GLint y, GLint h, GLint w); 35 | -------------------------------------------------------------------------------- /test/rotate_test/dmtx.c: -------------------------------------------------------------------------------- 1 | #define CALLBACK_POINT_PLOT(a,b,c,d) PlotPointCallback(a,b,c,d) 2 | #define CALLBACK_POINT_XFRM(a,b,c,d) XfrmPlotPointCallback(a,b,c,d) 3 | #define CALLBACK_MODULE(a,b,c,d,e) PlotModuleCallback(a,b,c,d,e) 4 | #define CALLBACK_MATRIX(a) BuildMatrixCallback2(a) 5 | #define CALLBACK_FINAL(a,b) FinalCallback(a,b) 6 | 7 | #include "../../dmtx.c" 8 | -------------------------------------------------------------------------------- /test/rotate_test/image.c: -------------------------------------------------------------------------------- 1 | /** 2 | * libdmtx - Data Matrix Encoding/Decoding Library 3 | * Copyright 2007, 2008, 2009 Mike Laughton. All rights reserved. 4 | * 5 | * See LICENSE file in the main project directory for full 6 | * terms of use and distribution. 7 | * 8 | * Contact: Mike Laughton 9 | * 10 | * \file image.c 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include "dmtx.h" 21 | #include "rotate_test.h" 22 | #include "image.h" 23 | 24 | /** 25 | * 26 | * 27 | */ 28 | unsigned char * 29 | loadTextureImage(int *width, int *height) 30 | { 31 | unsigned char *pxl; 32 | int error; 33 | char filepath[128]; 34 | 35 | strcpy(filepath, "images/"); 36 | strcat(filepath, gFilename[gFileIdx]); 37 | fprintf(stdout, "Opening %s\n", filepath); 38 | 39 | pxl = loadPng(filepath, width, height); 40 | assert(pxl != NULL); 41 | 42 | gFileIdx++; 43 | if(gFileIdx == gFileCount) 44 | gFileIdx = 0; 45 | 46 | /* Set up texture */ 47 | glGenTextures(1, &barcodeTexture); 48 | glBindTexture(GL_TEXTURE_2D, barcodeTexture); 49 | glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 50 | 51 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 52 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR); 53 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 54 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 55 | 56 | /* Read barcode image */ 57 | gluBuild2DMipmaps(GL_TEXTURE_2D, 3, *width, *height, GL_RGB, GL_UNSIGNED_BYTE, pxl); 58 | 59 | /* Create the barcode list */ 60 | barcodeList = glGenLists(1); 61 | glNewList(barcodeList, GL_COMPILE); 62 | DrawBarCode(); 63 | glEndList(); 64 | 65 | return pxl; 66 | } 67 | 68 | /** 69 | * 70 | * 71 | */ 72 | unsigned char * 73 | loadPng(char *filename, int *width, int *height) 74 | { 75 | png_byte pngHeader[8]; 76 | FILE *fp; 77 | int headerTestSize = sizeof(pngHeader); 78 | int isPng; 79 | int bitDepth, color_type, interlace_type, compression_type, filter_method; 80 | int row; 81 | png_uint_32 png_width, png_height; 82 | png_structp png_ptr; 83 | png_infop info_ptr; 84 | png_infop end_info; 85 | png_bytepp row_pointers; 86 | unsigned char *pxl = NULL; 87 | 88 | fp = fopen(filename, "rb"); 89 | if(!fp) 90 | return NULL; 91 | 92 | fread(pngHeader, 1, headerTestSize, fp); 93 | isPng = !png_sig_cmp(pngHeader, 0, headerTestSize); 94 | if(!isPng) 95 | return NULL; 96 | 97 | png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 98 | 99 | if(!png_ptr) 100 | return NULL; 101 | 102 | info_ptr = png_create_info_struct(png_ptr); 103 | if(!info_ptr) { 104 | png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); 105 | return NULL; 106 | } 107 | 108 | end_info = png_create_info_struct(png_ptr); 109 | if(!end_info) { 110 | png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); 111 | return NULL; 112 | } 113 | 114 | if(setjmp(png_jmpbuf(png_ptr))) { 115 | png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); 116 | fclose(fp); 117 | return NULL; 118 | } 119 | 120 | png_init_io(png_ptr, fp); 121 | png_set_sig_bytes(png_ptr, headerTestSize); 122 | 123 | png_read_info(png_ptr, info_ptr); 124 | png_get_IHDR(png_ptr, info_ptr, &png_width, &png_height, &bitDepth, 125 | &color_type, &interlace_type, &compression_type, &filter_method); 126 | 127 | png_set_strip_16(png_ptr); 128 | png_set_strip_alpha(png_ptr); 129 | png_set_packswap(png_ptr); 130 | 131 | if(color_type == PNG_COLOR_TYPE_PALETTE) 132 | png_set_palette_to_rgb(png_ptr); 133 | 134 | if (color_type == PNG_COLOR_TYPE_GRAY || PNG_COLOR_TYPE_GRAY_ALPHA) 135 | png_set_gray_to_rgb(png_ptr); 136 | 137 | png_read_update_info(png_ptr, info_ptr); 138 | png_get_IHDR(png_ptr, info_ptr, &png_width, &png_height, &bitDepth, 139 | &color_type, &interlace_type, &compression_type, &filter_method); 140 | 141 | *width = (int)png_width; 142 | *height = (int)png_height; 143 | 144 | row_pointers = (png_bytepp)png_malloc(png_ptr, sizeof(png_bytep) * png_height); 145 | if(row_pointers == NULL) { 146 | fprintf(stdout, "Fatal error!\n"); fflush(stdout); /* XXX finish later */ 147 | ; /* FatalError(1, "Error while during malloc for row_pointers"); */ 148 | } 149 | 150 | for(row = 0; row < *height; row++) { 151 | row_pointers[row] = (png_bytep)png_malloc(png_ptr, 152 | png_get_rowbytes(png_ptr, info_ptr)); 153 | } 154 | 155 | png_read_image(png_ptr, row_pointers); 156 | png_read_end(png_ptr, info_ptr); 157 | 158 | png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); 159 | 160 | pxl = (unsigned char *)malloc((*width) * (*height) * 3); 161 | assert(pxl != NULL); 162 | 163 | for(row = 0; row < *height; row++) { 164 | memcpy(pxl + (row * (*width) * 3), row_pointers[(*height) - row - 1], (*width) * 3); 165 | } 166 | 167 | for(row = 0; row < (*height); row++) { 168 | png_free(png_ptr, row_pointers[row]); 169 | } 170 | png_free(png_ptr, row_pointers); 171 | 172 | fclose(fp); 173 | 174 | return pxl; 175 | } 176 | 177 | /** 178 | * 179 | * 180 | */ 181 | void plotPoint(DmtxImage *img, float rowFloat, float colFloat, int targetColor) 182 | { 183 | int i, row, col; 184 | float xFloat, yFloat; 185 | int offset[4]; 186 | int color[4]; 187 | 188 | row = (int)rowFloat; 189 | col = (int)colFloat; 190 | 191 | xFloat = colFloat - col; 192 | yFloat = rowFloat - row; 193 | 194 | offset[0] = row * img->width + col; 195 | offset[1] = row * img->width + (col + 1); 196 | offset[2] = (row + 1) * img->width + col; 197 | offset[3] = (row + 1) * img->width + (col + 1); 198 | 199 | color[0] = clampRGB(255.0 * ((1.0 - xFloat) * (1.0 - yFloat))); 200 | color[1] = clampRGB(255.0 * (xFloat * (1.0 - yFloat))); 201 | color[2] = clampRGB(255.0 * ((1.0 - xFloat) * yFloat)); 202 | color[3] = clampRGB(255.0 * (xFloat * yFloat)); 203 | 204 | for(i = 0; i < 4; i++) { 205 | if((i == 1 || i== 3) && col + 1 > 319) 206 | continue; 207 | else if((i == 2 || i== 3) && row + 1 > 319) 208 | continue; 209 | 210 | if(targetColor & (ColorWhite | ColorRed | ColorYellow)) 211 | img->pxl[offset[i]*3+0] = max(img->pxl[offset[i]*3+0], color[i]); 212 | 213 | if(targetColor & (ColorWhite | ColorGreen | ColorYellow)) 214 | img->pxl[offset[i]*3+1] = max(img->pxl[offset[i]*3+1], color[i]); 215 | 216 | if(targetColor & (ColorWhite | ColorBlue)) 217 | img->pxl[offset[i]*3+2] = max(img->pxl[offset[i]*3+2], color[i]); 218 | } 219 | } 220 | 221 | /** 222 | * 223 | * 224 | */ 225 | int clampRGB(float color) 226 | { 227 | if(color < 0.0) 228 | return 0; 229 | else if(color > 255.0) 230 | return 255; 231 | else 232 | return (int)(color + 0.5); 233 | } 234 | -------------------------------------------------------------------------------- /test/rotate_test/image.h: -------------------------------------------------------------------------------- 1 | /** 2 | * libdmtx - Data Matrix Encoding/Decoding Library 3 | * Copyright 2007, 2008, 2009 Mike Laughton. All rights reserved. 4 | * 5 | * See LICENSE file in the main project directory for full 6 | * terms of use and distribution. 7 | * 8 | * Contact: Mike Laughton 9 | * 10 | * \file image.h 11 | */ 12 | 13 | #ifndef __IMAGE_H__ 14 | #define __IMAGE_H__ 15 | 16 | #define IMAGE_NO_ERROR 0 17 | #define IMAGE_ERROR 1 18 | #define IMAGE_NOT_PNG 2 19 | 20 | typedef enum { 21 | ColorWhite = 0x01 << 0, 22 | ColorRed = 0x01 << 1, 23 | ColorGreen = 0x01 << 2, 24 | ColorBlue = 0x01 << 3, 25 | ColorYellow = 0x01 << 4 26 | } ColorEnum; 27 | 28 | /*void captureImage(DmtxImage *img, DmtxImage *imgTmp);*/ 29 | unsigned char *loadTextureImage(int *width, int *height); 30 | unsigned char *loadPng(char *filename, int *width, int *height); 31 | void plotPoint(DmtxImage *img, float rowFloat, float colFloat, int targetColor); 32 | int clampRGB(float color); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /test/rotate_test/images/test_image01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/rotate_test/images/test_image01.png -------------------------------------------------------------------------------- /test/rotate_test/images/test_image02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/rotate_test/images/test_image02.png -------------------------------------------------------------------------------- /test/rotate_test/images/test_image03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/rotate_test/images/test_image03.png -------------------------------------------------------------------------------- /test/rotate_test/images/test_image04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/rotate_test/images/test_image04.png -------------------------------------------------------------------------------- /test/rotate_test/images/test_image05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/rotate_test/images/test_image05.png -------------------------------------------------------------------------------- /test/rotate_test/images/test_image06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/rotate_test/images/test_image06.png -------------------------------------------------------------------------------- /test/rotate_test/images/test_image07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/rotate_test/images/test_image07.png -------------------------------------------------------------------------------- /test/rotate_test/images/test_image08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/rotate_test/images/test_image08.png -------------------------------------------------------------------------------- /test/rotate_test/images/test_image09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/rotate_test/images/test_image09.png -------------------------------------------------------------------------------- /test/rotate_test/images/test_image10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/rotate_test/images/test_image10.png -------------------------------------------------------------------------------- /test/rotate_test/images/test_image11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/rotate_test/images/test_image11.png -------------------------------------------------------------------------------- /test/rotate_test/images/test_image12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/rotate_test/images/test_image12.png -------------------------------------------------------------------------------- /test/rotate_test/images/test_image13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/rotate_test/images/test_image13.png -------------------------------------------------------------------------------- /test/rotate_test/images/test_image14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/rotate_test/images/test_image14.png -------------------------------------------------------------------------------- /test/rotate_test/images/test_image15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/rotate_test/images/test_image15.png -------------------------------------------------------------------------------- /test/rotate_test/images/test_image16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/rotate_test/images/test_image16.png -------------------------------------------------------------------------------- /test/rotate_test/images/test_image17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/rotate_test/images/test_image17.png -------------------------------------------------------------------------------- /test/rotate_test/images/test_image18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmtx/libdmtx/62e3621a88922dce0ee45c5ab529262c9e174e84/test/rotate_test/images/test_image18.png -------------------------------------------------------------------------------- /test/rotate_test/rotate_test.c: -------------------------------------------------------------------------------- 1 | /** 2 | * libdmtx - Data Matrix Encoding/Decoding Library 3 | * Copyright 2007, 2008, 2009 Mike Laughton. All rights reserved. 4 | * 5 | * See LICENSE file in the main project directory for full 6 | * terms of use and distribution. 7 | * 8 | * Contact: Mike Laughton 9 | * 10 | * \file rotate_test.c 11 | */ 12 | 13 | #include "rotate_test.h" 14 | 15 | #define MIN(x,y) ((x < y) ? x : y) 16 | #define MAX(x,y) ((x > y) ? x : y) 17 | 18 | GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0; 19 | GLfloat angle = 0.0; 20 | 21 | GLuint barcodeTexture; 22 | GLint barcodeList; 23 | 24 | DmtxImage *gImage = NULL; 25 | unsigned char *capturePxl = NULL; 26 | unsigned char *texturePxl = NULL; 27 | unsigned char *passOnePxl = NULL; 28 | unsigned char *passTwoPxl = NULL; 29 | 30 | char *gFilename[] = { "test_image18.png" 31 | , "test_image16.png" 32 | , "test_image17.png" 33 | , "test_image01.png" 34 | , "test_image05.png" 35 | , "test_image06.png" 36 | , "test_image07.png" 37 | , "test_image12.png" 38 | , "test_image13.png" 39 | , "test_image08.png" 40 | , "test_image09.png" 41 | , "test_image10.png" 42 | , "test_image04.png" 43 | , "test_image11.png" 44 | , "test_image02.png" 45 | , "test_image03.png" 46 | , "test_image14.png" 47 | , "test_image15.png" }; 48 | int gFileIdx = 0; 49 | int gFileCount = 18; 50 | 51 | /** 52 | * 53 | * 54 | */ 55 | int main(int argc, char *argv[]) 56 | { 57 | int i; 58 | int count; 59 | int done; 60 | int width, height; 61 | SDL_Event event; 62 | SDL_Surface *screen; 63 | unsigned char outputString[1024]; 64 | DmtxDecode *dec; 65 | DmtxRegion *reg; 66 | DmtxMessage *msg; 67 | DmtxTime timeout; 68 | 69 | /* Initialize display window */ 70 | screen = initDisplay(); 71 | 72 | /* Load input image to DmtxImage */ 73 | texturePxl = loadTextureImage(&width, &height); 74 | assert(texturePxl != NULL); 75 | 76 | capturePxl = (unsigned char *)malloc(width * height * 3); 77 | assert(capturePxl != NULL); 78 | 79 | passOnePxl = (unsigned char *)malloc(width * height * 3); 80 | assert(passOnePxl != NULL); 81 | 82 | passTwoPxl = (unsigned char *)malloc(width * height * 3); 83 | assert(passTwoPxl != NULL); 84 | 85 | done = 0; 86 | while(!done) { 87 | 88 | SDL_Delay(50); 89 | 90 | while(SDL_PollEvent(&event)) 91 | done = HandleEvent(&event, screen); 92 | 93 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 94 | DrawGeneratedImage(screen); 95 | 96 | memset(passOnePxl, 0x00, width * height * 3); 97 | memset(passTwoPxl, 0x00, width * height * 3); 98 | 99 | /* Capture screenshot of generated image */ 100 | glReadPixels(2, 324, width, height, GL_RGB, GL_UNSIGNED_BYTE, capturePxl); 101 | gImage = dmtxImageCreate(capturePxl, width, height, DmtxPack24bppRGB); 102 | assert(gImage != NULL); 103 | 104 | /* Pixels from glReadPixels are Y-flipped according to libdmtx */ 105 | dmtxImageSetProp(gImage, DmtxPropImageFlip, DmtxFlipY); 106 | 107 | /* Start fresh scan */ 108 | dec = dmtxDecodeCreate(gImage, 1); 109 | assert(dec != NULL); 110 | 111 | for(;;) { 112 | timeout = dmtxTimeAdd(dmtxTimeNow(), 500); 113 | 114 | reg = dmtxRegionFindNext(dec, &timeout); 115 | if(reg != NULL) { 116 | msg = dmtxDecodeMatrixRegion(dec, reg, DmtxUndefined); 117 | if(msg != NULL) { 118 | fwrite(msg->output, sizeof(unsigned char), msg->outputIdx, stdout); 119 | fputc('\n', stdout); 120 | dmtxMessageDestroy(&msg); 121 | } 122 | dmtxRegionDestroy(®); 123 | } 124 | break; 125 | } 126 | 127 | dmtxDecodeDestroy(&dec); 128 | dmtxImageDestroy(&gImage); 129 | 130 | DrawBorders(screen); 131 | /* DrawPane2(screen, passOnePxl); */ 132 | /* DrawPane4(screen, passTwoPxl); */ 133 | 134 | SDL_GL_SwapBuffers(); 135 | } 136 | 137 | free(passTwoPxl); 138 | free(passOnePxl); 139 | free(capturePxl); 140 | free(texturePxl); 141 | 142 | exit(0); 143 | } 144 | -------------------------------------------------------------------------------- /test/rotate_test/rotate_test.h: -------------------------------------------------------------------------------- 1 | /** 2 | * libdmtx - Data Matrix Encoding/Decoding Library 3 | * Copyright 2007, 2008, 2009 Mike Laughton. All rights reserved. 4 | * 5 | * See LICENSE file in the main project directory for full 6 | * terms of use and distribution. 7 | * 8 | * Contact: Mike Laughton 9 | * 10 | * \file rotate_test.h 11 | */ 12 | 13 | #ifndef __SCANDEMO_H__ 14 | #define __SCANDEMO_H__ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include "../../dmtx.h" 23 | #include "image.h" 24 | #include "display.h" 25 | #include "callback.h" 26 | 27 | #define max(X,Y) (X > Y) ? X : Y 28 | #define min(X,Y) (X < Y) ? X : Y 29 | 30 | extern GLfloat view_rotx; 31 | extern GLfloat view_roty; 32 | extern GLfloat view_rotz; 33 | extern GLfloat angle; 34 | 35 | extern GLuint barcodeTexture; 36 | extern GLint barcodeList; 37 | 38 | extern DmtxImage *gImage; 39 | extern unsigned char *capturePxl; 40 | extern unsigned char *texturePxl; 41 | extern unsigned char *passOnePxl; 42 | extern unsigned char *passTwoPxl; 43 | 44 | extern char *gFilename[]; 45 | extern int gFileIdx; 46 | extern int gFileCount; 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /test/simple_test/Makefile.am: -------------------------------------------------------------------------------- 1 | AM_CPPFLAGS = -Wshadow -Wall -pedantic -std=c99 2 | 3 | check_PROGRAMS = simple_test 4 | 5 | simple_test_SOURCES = simple_test.c 6 | simple_test_LDFLAGS = -lm 7 | 8 | LDADD = ../../libdmtx.la 9 | -------------------------------------------------------------------------------- /test/simple_test/simple_test.c: -------------------------------------------------------------------------------- 1 | /** 2 | * libdmtx - Data Matrix Encoding/Decoding Library 3 | * Copyright 2008, 2009 Mike Laughton. All rights reserved. 4 | * Copyright 2010-2016 Vadim A. Misbakh-Soloviov. All rights reserved. 5 | * Copyright 2016 Tim Zaman. All rights reserved. 6 | * 7 | * See LICENSE file in the main project directory for full 8 | * terms of use and distribution. 9 | * 10 | * Contact: 11 | * Vadim A. Misbakh-Soloviov 12 | * Mike Laughton 13 | * 14 | * \file simple_test.c 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include "../../dmtx.h" 23 | 24 | int 25 | main(int argc, char *argv[]) 26 | { 27 | size_t width, height, bytesPerPixel; 28 | unsigned char str[] = "30Q324343430794image, DmtxPropWidth); 59 | height = dmtxImageGetProp(enc->image, DmtxPropHeight); 60 | bytesPerPixel = dmtxImageGetProp(enc->image, DmtxPropBytesPerPixel); 61 | 62 | pxl = (unsigned char *)malloc(width * height * bytesPerPixel); 63 | assert(pxl != NULL); 64 | memcpy(pxl, enc->image->pxl, width * height * bytesPerPixel); 65 | 66 | dmtxEncodeDestroy(&enc); 67 | 68 | fprintf(stdout, "width: \"%zd\"\n", width); 69 | fprintf(stdout, "height: \"%zd\"\n", height); 70 | fprintf(stdout, "bpp: \"%zd\"\n", bytesPerPixel); 71 | 72 | for (int i=0; iarraySize : \"%zd\"\n", msg->arraySize ); 92 | fprintf(stdout, "msg->codeSize : \"%zd\"\n", msg->codeSize ); 93 | fprintf(stdout, "msg->outputSize: \"%zd\"\n", msg->outputSize); 94 | int oned = sqrt(msg->arraySize); 95 | for (int i=0; iarraySize; i++){ 96 | fprintf(stdout, " %c.", msg->array[i]); 97 | if (i%oned==oned-1){ 98 | fprintf(stdout, "\n"); 99 | } 100 | } 101 | fprintf(stdout, "\n\n"); 102 | for (int j=0; jcodeSize; j++){ 103 | fprintf(stdout, " %c.", msg->code[j]); 104 | } 105 | fprintf(stdout, "\n\n"); 106 | for (int k=0; koutputSize; k++){ 107 | fprintf(stdout, " %c.", msg->output[k]); 108 | } 109 | fprintf(stdout, "\n\n"); 110 | 111 | if(msg != NULL) { 112 | fputs("output: \"", stdout); 113 | fwrite(msg->output, sizeof(unsigned char), msg->outputIdx, stdout); 114 | fputs("\"\n", stdout); 115 | dmtxMessageDestroy(&msg); 116 | } 117 | dmtxRegionDestroy(®); 118 | } 119 | 120 | dmtxDecodeDestroy(&dec); 121 | dmtxImageDestroy(&img); 122 | free(pxl); 123 | 124 | fprintf(stdout, "%d\n", getSizeIdxFromSymbolDimension(12, 12)); 125 | 126 | exit(0); 127 | } 128 | -------------------------------------------------------------------------------- /test/unit_test/Makefile.am: -------------------------------------------------------------------------------- 1 | AM_CPPFLAGS = -Wshadow -Wall -pedantic -std=c99 2 | 3 | check_PROGRAMS = unit_test 4 | 5 | unit_test_SOURCES = unit_test.c ../../util/common/dmtxutil.c ../../util/common/dmtxutil.h 6 | unit_test_LDFLAGS = -lm 7 | 8 | LDADD = ../../libdmtx.la 9 | -------------------------------------------------------------------------------- /test/unit_test/unit_test.c: -------------------------------------------------------------------------------- 1 | /** 2 | * libdmtx - Data Matrix Encoding/Decoding Library 3 | * Copyright 2007, 2008, 2009 Mike Laughton. All rights reserved. 4 | * 5 | * See LICENSE file in the main project directory for full 6 | * terms of use and distribution. 7 | * 8 | * Contact: Mike Laughton 9 | * 10 | * \file unit_test.c 11 | */ 12 | 13 | #ifdef HAVE_UNISTD_H 14 | #include 15 | #endif 16 | 17 | #include 18 | #include 19 | #include 20 | #include "../../dmtx.h" 21 | 22 | char *programName; 23 | 24 | static void FatalError(int idx, char* msg) 25 | { 26 | fprintf(stdout, "FAIL: (%d) %s\n", idx, msg); 27 | exit(1); 28 | } 29 | 30 | static void timeAddTest(void); 31 | static void timePrint(DmtxTime t); 32 | 33 | int 34 | main(int argc, char *argv[]) 35 | { 36 | programName = argv[0]; 37 | 38 | timeAddTest(); 39 | 40 | exit(0); 41 | } 42 | 43 | /** 44 | * 45 | * 46 | */ 47 | static void 48 | timePrint(DmtxTime t) 49 | { 50 | #ifdef _MSC_VER 51 | fprintf(stdout, "t.sec: %llu\n", t.sec); 52 | #else 53 | fprintf(stdout, "t.sec: %lu\n", t.sec); 54 | #endif 55 | 56 | fprintf(stdout, "t.usec: %lu\n", t.usec); 57 | } 58 | 59 | /** 60 | * 61 | * 62 | */ 63 | static void 64 | timeAddTest(void) 65 | { 66 | DmtxTime t0, t1; 67 | 68 | t0 = dmtxTimeNow(); 69 | t0.usec = 999000; 70 | 71 | t1 = dmtxTimeAdd(t0, 0); 72 | if(memcmp(&t0, &t1, sizeof(DmtxTime)) != 0) 73 | FatalError(1, "timeAddTest\n"); 74 | 75 | t1 = dmtxTimeAdd(t0, 1); 76 | if(memcmp(&t0, &t1, sizeof(DmtxTime)) == 0) 77 | FatalError(2, "timeAddTest\n"); 78 | 79 | t1 = dmtxTimeAdd(t0, 1); 80 | if(t1.sec != t0.sec + 1 || t1.usec != 0) { 81 | timePrint(t0); 82 | timePrint(t1); 83 | FatalError(3, "timeAddTest\n"); 84 | } 85 | 86 | t1 = dmtxTimeAdd(t0, 1001); 87 | if(t1.sec != t0.sec + 2 || t1.usec != 0) { 88 | timePrint(t0); 89 | timePrint(t1); 90 | FatalError(4, "timeAddTest\n"); 91 | } 92 | 93 | t1 = dmtxTimeAdd(t0, 2002); 94 | if(t1.sec != t0.sec + 3 || t1.usec != 1000) { 95 | timePrint(t0); 96 | timePrint(t1); 97 | FatalError(5, "timeAddTest\n"); 98 | } 99 | } 100 | 101 | /** 102 | * 103 | * 104 | */ 105 | /** 106 | static void 107 | TestRGB(void) 108 | { 109 | unsigned char *pxl; 110 | FILE *fp; 111 | 112 | pxl = (unsigned char *)malloc(320 * 240 * 3); 113 | assert(pxl != NULL); 114 | 115 | fp = fopen("fruit_matrix.rgb", "rb"); 116 | assert(fp != NULL); 117 | 118 | fread(ptr, 3, 320 * 240, fp); 119 | fclose(fp); 120 | 121 | dmtxImageCreate(ptr, 320, 240, DmtxPack24bppRGB); 122 | } 123 | */ 124 | --------------------------------------------------------------------------------