├── .github └── workflows │ ├── cmake-windows.yml │ ├── cmake.yml │ └── configure.yml ├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── COPYING ├── ChangeLog ├── Doxyfile ├── Makefile.am ├── NEWS ├── README.md ├── TODO ├── acinclude.m4 ├── autogen.sh ├── bitstream.c ├── bitstream.h ├── cmake └── FindIconv.cmake ├── configure.ac ├── libqrencode.pc.in ├── makeREADME.sh ├── mask.c ├── mask.h ├── mmask.c ├── mmask.h ├── mqrspec.c ├── mqrspec.h ├── qrenc.c ├── qrencode.1.in ├── qrencode.c ├── qrencode.h ├── qrencode_inner.h ├── qrinput.c ├── qrinput.h ├── qrspec.c ├── qrspec.h ├── rsecc.c ├── rsecc.h ├── split.c ├── split.h ├── tests ├── CMakeLists.txt ├── Makefile.am ├── URI_testset.inc ├── common.c ├── common.h ├── create_frame_pattern.c ├── create_mqr_frame_pattern.c ├── datachunk.c ├── datachunk.h ├── decoder.c ├── decoder.h ├── frame ├── prof_qrencode.c ├── pthread_qrencode.c ├── rscode.c ├── rscode.h ├── rsecc_decoder.c ├── rsecc_decoder.h ├── test_all.sh ├── test_basic.sh ├── test_bitstream.c ├── test_configure.sh ├── test_estimatebit.c ├── test_mask.c ├── test_mmask.c ├── test_monkey.c ├── test_mqrspec.c ├── test_qrenc.sh ├── test_qrencode.c ├── test_qrinput.c ├── test_qrspec.c ├── test_rs.c ├── test_split.c ├── test_split_urls.c └── view_qrcode.c └── use └── config.rpath /.github/workflows/cmake-windows.yml: -------------------------------------------------------------------------------- 1 | name: CMake 2 | 3 | on: [push, pull_request] 4 | 5 | env: 6 | # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) 7 | BUILD_TYPE: Release 8 | 9 | jobs: 10 | build: 11 | # The CMake configure and build commands are platform agnostic and should work equally 12 | # well on Windows or Mac. You can convert this to a matrix build if you need 13 | # cross-platform coverage. 14 | # See: https://docs.github.com/en/actions/configuring-and-managing-workflows/configuring-a-workflow#configuring-a-build-matrix 15 | runs-on: windows-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | 20 | - name: run vcpkg 21 | uses: lukka/run-vcpkg@v3 22 | with: 23 | vcpkgArguments: getopt:x64-windows libiconv:x64-windows libpng:x64-windows 24 | vcpkgDirectory: '${{ github.workspace }}/vcpkg' 25 | vcpkgGitCommitId: 'fca18ba3572f8aebe3b8158c359db62a7e26134e' 26 | 27 | - name: Create Build Environment 28 | # Some projects don't allow in-source building, so create a separate build directory 29 | # We'll use this as our working directory for all subsequent commands 30 | run: cmake -E make_directory ${{runner.workspace}}/build 31 | 32 | - name: Configure CMake 33 | # Use a bash shell so we can use the same syntax for environment variable 34 | # access regardless of the host operating system 35 | shell: bash 36 | working-directory: ${{runner.workspace}}/build 37 | # Note the current convention is to use the -S and -B options here to specify source 38 | # and build directories, but this is only available with CMake 3.13 and higher. 39 | # The CMake binaries on the Github Actions machines are (as of this writing) 3.12 40 | run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake -DWITH_TESTS=yes 41 | 42 | - name: Build 43 | working-directory: ${{runner.workspace}}/build 44 | shell: bash 45 | # Execute the build. You can specify a specific target with "--target " 46 | run: cmake --build . --config $BUILD_TYPE 47 | 48 | - name: Test 49 | working-directory: ${{runner.workspace}}/build 50 | shell: bash 51 | # Execute tests defined by the CMake configuration. 52 | # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail 53 | run: ctest -C $BUILD_TYPE 54 | -------------------------------------------------------------------------------- /.github/workflows/cmake.yml: -------------------------------------------------------------------------------- 1 | name: CMake 2 | 3 | on: [push] 4 | 5 | env: 6 | # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) 7 | BUILD_TYPE: Release 8 | 9 | jobs: 10 | build: 11 | # The CMake configure and build commands are platform agnostic and should work equally 12 | # well on Windows or Mac. You can convert this to a matrix build if you need 13 | # cross-platform coverage. 14 | # See: https://docs.github.com/en/actions/configuring-and-managing-workflows/configuring-a-workflow#configuring-a-build-matrix 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | 20 | - name: Create Build Environment 21 | # Some projects don't allow in-source building, so create a separate build directory 22 | # We'll use this as our working directory for all subsequent commands 23 | run: cmake -E make_directory ${{runner.workspace}}/build 24 | 25 | - name: Configure CMake 26 | # Use a bash shell so we can use the same syntax for environment variable 27 | # access regardless of the host operating system 28 | shell: bash 29 | working-directory: ${{runner.workspace}}/build 30 | # Note the current convention is to use the -S and -B options here to specify source 31 | # and build directories, but this is only available with CMake 3.13 and higher. 32 | # The CMake binaries on the Github Actions machines are (as of this writing) 3.12 33 | run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DWITH_TESTS=yes -DBUILD_SHARED_LIBS=on 34 | 35 | - name: Build 36 | working-directory: ${{runner.workspace}}/build 37 | shell: bash 38 | # Execute the build. You can specify a specific target with "--target " 39 | run: cmake --build . --config $BUILD_TYPE 40 | 41 | - name: Test 42 | working-directory: ${{runner.workspace}}/build 43 | shell: bash 44 | # Execute tests defined by the CMake configuration. 45 | # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail 46 | run: ctest -C $BUILD_TYPE 47 | -------------------------------------------------------------------------------- /.github/workflows/configure.yml: -------------------------------------------------------------------------------- 1 | name: configure CI 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v2 12 | - name: generate configure script 13 | run: ./autogen.sh 14 | - name: configure 15 | run: ./configure --with-tests 16 | - name: make 17 | run: make 18 | - name: make check 19 | run: make check 20 | - name: make distcheck 21 | run: make distcheck 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.[oa] 2 | *.lo 3 | *.la 4 | *.gcno 5 | *.gcov 6 | *.gcda 7 | .deps/ 8 | .libs/ 9 | autom4te.cache/ 10 | m4/ 11 | CMakeLists.txt.user 12 | CMakeCache.txt 13 | CTestTestfile.cmake 14 | CMakeFiles/ 15 | cmake_install.cmake 16 | Makefile 17 | Makefile.in 18 | README 19 | build 20 | config.log 21 | configure 22 | config.status 23 | config.h 24 | config.h.in 25 | aclocal.m4 26 | libtool 27 | stamp-h1 28 | qrencode 29 | qrencode.1 30 | libqrencode.pc 31 | tests/create_frame_pattern 32 | tests/create_mqr_frame_pattern 33 | tests/pthread_qrencode 34 | tests/prof_qrencode 35 | tests/test_bitstream 36 | tests/test_estimatebit 37 | tests/test_mask 38 | tests/test_mmask 39 | tests/test_monkey 40 | tests/test_mqrspec 41 | tests/test_qrencode 42 | tests/test_qrinput 43 | tests/test_qrspec 44 | tests/test_rs 45 | tests/test_split 46 | tests/test_split_urls 47 | tests/view_qrcode 48 | use/compile 49 | use/config.guess 50 | use/config.sub 51 | use/depcomp 52 | use/install-sh 53 | use/ltmain.sh 54 | use/missing 55 | use/test-driver 56 | html/ 57 | massif.out.* 58 | gmon.out 59 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | sudo: required 3 | language: c 4 | 5 | compiler: 6 | - gcc 7 | 8 | before_install: 9 | - sudo apt-get update 10 | - sudo apt-get install libpng12-dev 11 | 12 | install: 13 | - ./autogen.sh 14 | - ./configure --with-tests && make 15 | - sudo make install 16 | - mkdir build && cd build 17 | - cmake .. -DWITH_TESTS=yes -DBUILD_SHARED_LIBS=on && make 18 | - DESTDIR=$PWD/install make install 19 | 20 | script: 21 | - cd $TRAVIS_BUILD_DIR/tests 22 | - ./test_all.sh 23 | - cd $TRAVIS_BUILD_DIR/build/tests 24 | - cp $TRAVIS_BUILD_DIR/tests/frame ./ 25 | - make test 26 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1.0) 2 | 3 | project(QRencode VERSION 4.1.1 LANGUAGES C) 4 | 5 | option(WITH_TOOLS "Build utility tools" YES ) 6 | option(WITH_TESTS "Build tests" NO ) 7 | option(WITHOUT_PNG "Disable PNG support" NO) 8 | option(GPROF "Generate extra code to write profile information" OFF) 9 | option(COVERAGE "Generate extra code to write coverage information" OFF) 10 | option(ASAN "Use AddressSanitizer" OFF) 11 | option(BUILD_SHARED_LIBS "Enable build of shared libraries" NO) 12 | 13 | if(BUILD_TESTING) 14 | set(WITH_TESTS ON) 15 | message(DEPRECATION "use WITH_TESTS option instead BUILD_TESTING") 16 | endif() 17 | 18 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") 19 | 20 | set(CMAKE_THREAD_PREFER_PTHREAD ON) 21 | find_package(Threads) 22 | find_package(PNG) 23 | find_package(Iconv) 24 | 25 | if(CMAKE_USE_PTHREADS_INIT) 26 | add_definitions(-DHAVE_LIBPTHREAD=1) 27 | # for libqrencode.pc 28 | set(LIBPTHREAD ${CMAKE_THREAD_LIBS_INIT}) 29 | endif() 30 | 31 | ## Check for system include files 32 | include(CheckIncludeFile) 33 | include(CheckFunctionExists) 34 | 35 | check_include_file(dlfcn.h HAVE_DLFCN_H ) 36 | check_include_file(inttypes.h HAVE_INTTYPES_H) 37 | check_include_file(memory.h HAVE_MEMORY_H ) 38 | check_include_file(stdint.h HAVE_STDINT_H ) 39 | check_include_file(stdlib.h HAVE_STDLIB_H ) 40 | check_include_file(strings.h HAVE_STRINGS_H ) 41 | check_include_file(string.h HAVE_STRING_H ) 42 | check_include_file(getopt.h HAVE_GETOPT_H ) 43 | check_include_file(sys/time.h HAVE_SYS_TIME_H) 44 | check_include_file(time.h HAVE_TIME_H ) 45 | check_include_file(pthread.h HAVE_PTHREAD_H ) 46 | 47 | check_function_exists(strdup HAVE_STRDUP) 48 | 49 | if(HAVE_STRDUP) 50 | add_definitions(-DHAVE_STRDUP=1) 51 | endif() 52 | 53 | if(CMAKE_COMPILER_IS_GNUCXX) 54 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") 55 | endif() 56 | 57 | if(GPROF) 58 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pg") 59 | endif() 60 | 61 | if(COVERAGE) 62 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage") 63 | endif() 64 | 65 | if(ASAN) 66 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls") 67 | endif() 68 | 69 | add_definitions(-DMAJOR_VERSION=${PROJECT_VERSION_MAJOR}) 70 | add_definitions(-DMINOR_VERSION=${PROJECT_VERSION_MINOR}) 71 | add_definitions(-DMICRO_VERSION=${PROJECT_VERSION_PATCH}) 72 | add_definitions(-DVERSION="${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") 73 | add_definitions(-DHAVE_SDL=0) 74 | 75 | if(MSVC) 76 | set(CMAKE_DEBUG_POSTFIX "d") 77 | 78 | add_definitions(-Dstrcasecmp=_stricmp) 79 | add_definitions(-Dstrncasecmp=_strnicmp) 80 | add_definitions(-D_CRT_SECURE_NO_WARNINGS) 81 | add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE) 82 | 83 | if(WITH_TOOLS) 84 | find_path(GETOPT_INCLUDE_DIR getopt.h PATH_SUFFIXES include) 85 | find_library(GETOPT_LIBRARIES getopt PATH_SUFFIXES lib) 86 | include_directories(${GETOPT_INCLUDE_DIR}) 87 | endif(WITH_TOOLS) 88 | endif(MSVC) 89 | 90 | set(QRENCODE_SRCS qrencode.c 91 | qrinput.c 92 | bitstream.c 93 | qrspec.c 94 | rsecc.c 95 | split.c 96 | mask.c 97 | mqrspec.c 98 | mmask.c) 99 | 100 | set(QRENCODE_HDRS qrencode_inner.h 101 | qrinput.h 102 | bitstream.h 103 | qrspec.h 104 | rsecc.h 105 | split.h 106 | mask.h 107 | mqrspec.h 108 | mmask.h) 109 | 110 | if(BUILD_SHARED_LIBS) 111 | if(MSVC) 112 | set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) 113 | endif() 114 | add_library(qrencode SHARED ${QRENCODE_SRCS} ${QRENCODE_HDRS}) 115 | set_target_properties(qrencode PROPERTIES VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH} SOVERSION ${PROJECT_VERSION_MAJOR}) 116 | else() 117 | add_library(qrencode ${QRENCODE_SRCS} ${QRENCODE_HDRS}) 118 | endif() 119 | if(CMAKE_USE_PTHREADS_INIT) 120 | target_link_libraries(qrencode Threads::Threads) 121 | endif() 122 | 123 | include(GNUInstallDirs) 124 | set(prefix "${CMAKE_INSTALL_PREFIX}") 125 | set(exec_prefix "${CMAKE_INSTALL_FULL_BINDIR}") 126 | set(libdir "${CMAKE_INSTALL_FULL_LIBDIR}") 127 | set(includedir "${CMAKE_INSTALL_FULL_INCLUDEDIR}") 128 | set(VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") 129 | 130 | configure_file(qrencode.1.in qrencode.1 @ONLY) 131 | configure_file(libqrencode.pc.in libqrencode.pc @ONLY) 132 | 133 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qrencode.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) 134 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libqrencode.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) 135 | install(FILES qrencode.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) 136 | install(TARGETS qrencode DESTINATION ${CMAKE_INSTALL_LIBDIR}) 137 | 138 | ## Build utility tools 139 | if(WITH_TOOLS) 140 | if(NOT WITHOUT_PNG) 141 | add_definitions(-DHAVE_PNG=1) 142 | endif() 143 | add_executable(qrenc qrenc.c) 144 | set_target_properties(qrenc PROPERTIES OUTPUT_NAME qrencode) 145 | 146 | if(NOT WITHOUT_PNG) 147 | target_link_libraries(qrenc qrencode PNG::PNG) 148 | else() 149 | target_link_libraries(qrenc qrencode) 150 | endif() 151 | 152 | if(MSVC) 153 | target_link_libraries(qrenc ${GETOPT_LIBRARIES}) 154 | endif(MSVC) 155 | 156 | install(TARGETS qrenc DESTINATION ${CMAKE_INSTALL_BINDIR}) 157 | endif() 158 | 159 | if(WITH_TESTS) 160 | enable_testing() 161 | add_definitions(-DWITH_TESTS=) 162 | add_definitions(-DSTATIC_IN_RELEASE=) 163 | add_subdirectory(tests) 164 | else() 165 | add_definitions(-DSTATIC_IN_RELEASE=static) 166 | endif() 167 | 168 | ## ============================================================================== 169 | ## 170 | ## Configuration summary 171 | ## 172 | ## ============================================================================== 173 | 174 | message(STATUS "------------------------------------------------------------" ) 175 | message(STATUS "[QRencode] Configuration summary." ) 176 | message(STATUS "------------------------------------------------------------ ") 177 | message(STATUS " System configuration:" ) 178 | message(STATUS " .. Processor type .............. = ${CMAKE_SYSTEM_PROCESSOR}") 179 | message(STATUS " .. CMake executable ............ = ${CMAKE_COMMAND}" ) 180 | message(STATUS " .. CMake version ............... = ${CMAKE_VERSION}" ) 181 | message(STATUS " .. System name ................. = ${CMAKE_SYSTEM}" ) 182 | message(STATUS " .. C++ compiler ................ = ${CMAKE_CXX_COMPILER}" ) 183 | message(STATUS " .. C compiler .................. = ${CMAKE_C_COMPILER}" ) 184 | message(STATUS " .. size(void*) ................. = ${CMAKE_SIZEOF_VOID_P}" ) 185 | message(STATUS " Dependencies:" ) 186 | #message(STATUS " .. Doxygen ..................... = ${DOXYGEN_EXECUTABLE}" ) 187 | message(STATUS " .. Thread library of the system = ${CMAKE_THREAD_LIBS_INIT}") 188 | message(STATUS " .. Iconv ....................... = ${ICONV_FOUND}" ) 189 | message(STATUS " .... Iconv includes ............ = ${ICONV_INCLUDE_DIR}" ) 190 | message(STATUS " .... Iconv library ............. = ${ICONV_LIBRARIES}" ) 191 | message(STATUS " .. ZLIB ........................ = ${ZLIB_FOUND}" ) 192 | message(STATUS " .. PNG ......................... = ${PNG_FOUND}" ) 193 | message(STATUS " .... PNG includes .............. = ${PNG_INCLUDE_DIR}" ) 194 | message(STATUS " .... PNG library ............... = ${PNG_LIBRARIES}" ) 195 | #message(STATUS " .. Memory checker .............. = ${MEMORYCHECK_COMMAND}" ) 196 | message(STATUS " Project configuration:" ) 197 | message(STATUS " .. Build test programs ........ = ${WITH_TESTS}" ) 198 | message(STATUS " .. Build utility tools ........ = ${WITH_TOOLS}" ) 199 | message(STATUS " .. Disable PNG support ........ = ${WITHOUT_PNG}" ) 200 | message(STATUS " .. Installation prefix ......... = ${CMAKE_INSTALL_PREFIX}" ) 201 | message(STATUS "------------------------------------------------------------ ") 202 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS = foreign 2 | ACLOCAL_AMFLAGS=-I m4 3 | 4 | SUBDIRS = . 5 | 6 | if BUILD_TESTS 7 | SUBDIRS += tests 8 | endif 9 | 10 | lib_LTLIBRARIES = libqrencode.la 11 | 12 | libqrencode_la_SOURCES = qrencode.c qrencode_inner.h \ 13 | qrinput.c qrinput.h \ 14 | bitstream.c bitstream.h \ 15 | qrspec.c qrspec.h \ 16 | rsecc.c rsecc.h \ 17 | split.c split.h \ 18 | mask.c mask.h \ 19 | mqrspec.c mqrspec.h \ 20 | mmask.c mmask.h 21 | 22 | libqrencode_la_LDFLAGS = -version-number $(MAJOR_VERSION):$(MINOR_VERSION):$(MICRO_VERSION) 23 | 24 | include_HEADERS = qrencode.h 25 | 26 | pkgconfigdir = $(libdir)/pkgconfig 27 | pkgconfig_DATA = libqrencode.pc 28 | noinst_DATA = README 29 | README_markdown_optional := $(wildcard README.md) 30 | README: $(README_markdown_optional) 31 | $(if $(README_markdown_optional), ./makeREADME.sh) 32 | 33 | EXTRA_DIST = libqrencode.pc.in autogen.sh configure.ac acinclude.m4 \ 34 | Makefile.am tests/Makefile.am \ 35 | qrencode.1.in Doxyfile \ 36 | CMakeLists.txt cmake/FindIconv.cmake 37 | 38 | if BUILD_TOOLS 39 | bin_PROGRAMS = qrencode 40 | qrencode_SOURCES = qrenc.c 41 | qrencode_CFLAGS = $(png_CFLAGS) 42 | qrencode_LDADD = libqrencode.la $(png_LIBS) 43 | man1_MANS = qrencode.1 44 | endif 45 | 46 | if MINGW 47 | libqrencode_la_LDFLAGS += -no-undefined -avoid-version -Wl,--nxcompat -Wl,--dynamicbase 48 | endif 49 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | libqrencode NEWS - Overview of changes 2 | ====================================== 3 | 4 | Version 4.1.1 (2020.9.28) 5 | ------------------------- 6 | * Some minor bugs in Micro QR Code generation have been fixed. 7 | * The data capacity calculations are now correct. These bugs probably did not 8 | affect the Micro QR Code generation. 9 | 10 | Version 4.1.0 (2020.8.29) 11 | ------------------------- 12 | * Command line tool "qrencode" has been improved: 13 | * New option "--inline" has been added. (Thanks to @jp-bennett) 14 | * New option "--strict-version" has been added. 15 | * UTF8 mode now supports ANSI256 color. (Thanks to András Veres- 16 | Szentkirályi) 17 | * Micro QR Code no longer requires to specify the version number. 18 | * 'make check' allows to run the test programs. (Thanks to Jan Tojnar) 19 | * Some compile time warnings have been fixed. 20 | * Various CMake support improvements. (Thanks to @mgorny and @sdf5) 21 | * Some minor bug fixes. (Thanks to Lonnie Abelbeck and Frédéric Wang) 22 | * Some documentation/manpage improvements. (Thanks to Dan Jacobson) 23 | * Some performance improvements. (Thanks to @4061N and Mika Lindqvist) 24 | 25 | Release Note: 26 | The internal representation of the output code has been slightly changed - 27 | the second bit from LSB side now represents; 1:ECC bit / 0:data bit. 28 | This change is only for debug purposes and does not affect user applications. 29 | 30 | 31 | Version 4.0.2 (2018.6.6) 32 | ------------------------ 33 | * Build script fixes. (Thanks to @mgorny) 34 | 35 | 36 | Version 4.0.1 (2018.6.4) 37 | ------------------------ 38 | * CMake support improved. 39 | * New test scripts have been added. 40 | * Some compile time warnings have been fixed. 41 | 42 | 43 | Version 4.0.0 (2017.9.21) 44 | ------------------------- 45 | * Memory efficiency has been improved. 46 | * QRcode_clearCache() has been deprecated. 47 | * Error correction code generating functions have been improved. 48 | * Command line tool "qrencode" has been improved: 49 | * XPM support. (Thanks to Tobias Klauser) 50 | * PNG32 (direct color mode) support. (Thanks to Greg Hart) 51 | * EPS output now supports foreground and background color. 52 | * New options "-r" and "--svg-path" have been added. 53 | (Thanks to Robert Petersen and @Oblomov) 54 | * CMake support has been added. (optional) (Thanks to @misery) 55 | * Various bug fixes. 56 | * Various performance improvements. 57 | 58 | Release Note: 59 | While the API has not been changed since the previous major release, we 60 | incremented the major version number of libqrencode to 4 because the 61 | implementation of the library has been largely changed. 62 | 63 | This release improves the performance and memory footprints of code generation. 64 | 65 | Now you can build libqrencode with CMake. 66 | 67 | If you build the test programs, please note that the required SDL version has 68 | been changed from 1.2 to 2.0. 69 | 70 | 71 | Version 3.4.4 (2014.7.24) 72 | ------------------------- 73 | * Bug fix release. (Thanks to Yoshimichi Inoue) 74 | * New option "--verbose" has been added to the command line tool. 75 | 76 | Release Note: 77 | When only one symbol is generated in structured-append mode, the library had 78 | inserted unnecessary chunk to the symbol and some QR Code readers fail to read 79 | it. Now the library omits the chunk and generate a symbol identical to non- 80 | structured symbol. 81 | 82 | Version 3.4.3 (2013.8.12) 83 | ------------------------- 84 | * New option "--rle" has been added to the command line tool (Thanks to Daniel 85 | Dörrhöfer) 86 | * Bug fixes. (Thanks to Hassan Hajji, Emmanuel Blot, and ßlúèÇhîp) 87 | 88 | Release Note: 89 | This release contains a couple of bug fixes and a new minor feature of the 90 | command line tool. Some minor bugs in the library have been fixed. 91 | 92 | Run Length Encoding (RLE) for SVG output decreases the size of the output file, 93 | but it makes complicated to edit the image by SVG editors. A newly introduced 94 | command line option "--rle" enables RLE. RLE will not be applied if it is not 95 | given. 96 | 97 | Version 3.4.2 (2013.3.1) 98 | ------------------------ 99 | * Bug fix release. (Thanks to chisj, vlad417, Petr and Viona) 100 | 101 | Release Note: 102 | Micro QR Code encoder had a bug that caused incorrect output (issue #25). Now 103 | the bug has been fixed. Memory leak bug (#24) and insufficient string splitting 104 | bug have been fixed. 105 | 106 | Version 3.4.1 (2012.10.17) 107 | -------------------------- 108 | * Bug fix release. 109 | 110 | Release Note: 111 | Mutual exclusion did not work correctly since 3.3.1. If your application uses 112 | libqrencode in multithreaded environment, it is strongly recommended to update 113 | it. 114 | 115 | Version 3.4.0 (2012.10.15) 116 | -------------------------- 117 | * SVG, UTF8, and ANSIUTF8 output supports have been added to the command line 118 | tool. (Thanks to Dan Storm, David Dahl, and Lennart Poettering) 119 | * Colored QR Code support. 120 | * Bug fixes. (Thanks to Terry Burton, Fred Steinhaeuser, and Yann Droneaud) 121 | 122 | Release Note: 123 | Three new output format, SVG, UTF8, and ANSIUTF8 have been added to the command 124 | line tool. UTF8 and ANSIUTF8 are another text art mode, using Unicode block 125 | elements for high-resolution text output. Long-awaited colored QR code has been 126 | introduced. Try "--foreground" and "--background" options to set the colors. 127 | Currently PNG and SVG supports colored output. 128 | 129 | Version 3.3.1 (2012.4.18) 130 | ------------------------- 131 | * Bugs in command line tool, manual, configure script, and libtool files have 132 | been fixed. (Thanks to Yutaka Niibe and Rob Ryan) 133 | 134 | Version 3.3.0 (2012.4.1) 135 | ------------------------- 136 | * EPS, ANSI, and ASCII text output supports have been added. 137 | (Thanks to Zapster, Colin, and Ralf) 138 | * QRcode_APIVersion() and QRcode_APIVersionString() have been added. 139 | 140 | Release Note: 141 | Three new output format, EPS, ANSI, and ASCII text, have been added to the 142 | command line tool. ANSI and ASCII mode ignore "-size" option. Give "-t ASCIIi" 143 | to get an ASCII-mode symbol in inverted color. 144 | 145 | QRcode_APIVersion() is requested by Matthew Baker for better support of Python 146 | ctypes binding. Check them out at https://code.google.com/p/libqrencode-ctypes/ 147 | 148 | Version 3.2.1 (2012.4.1) 149 | ------------------------ 150 | * Bugs in configure script and libtool file has been fixed. (Thanks to Yutaka 151 | Niibe) 152 | 153 | Version 3.2.0 (2011.11.26) 154 | -------------------------- 155 | * "--dpi" (or "-d") option has been added to qrencode. This option set DPI 156 | information in an output PNG image. (Thanks to David Dahl) 157 | * New option "--enable-thread-safety" has been added to the configure script 158 | that makes the library thread-safe. It is enabled by default. 159 | * QRcode_encodeData(), QRcode_encodeDataMQR, QRcode_encodeDataStructured() have 160 | been added for binary data encoding including '\0'. 161 | * Typo and bug fixes. 162 | * Experimental Micro QR Code support has been added. 163 | * "--micro" (or "-M") option for Micro QR Code has been added to qrencode. 164 | (experimental) 165 | 166 | Release Note: 167 | Binary data including '\0' is now supported. To encode a binary data, give "-8" 168 | option to qrencode, and let qrencode obtain data via standard input like 169 | "qrencode -8 -o output.png < binary". "--dpi" and "-d" are also added to embed 170 | DPI information to PNG file. 171 | 172 | A bug in the mask pattern evaluation routine has been fixed. In some cases, 173 | libqrencode may generate a different symbol from the one that was generated by 174 | the prior libqrencode because of this bug fix, but the embedded data are not 175 | affected. The symbols generated by the old libqrencode are valid. 176 | 177 | Experimental support of Micro QR Code encoder has been added. Some functions 178 | (QRcode_*MQR()) have been added to the library. The command line tool generates 179 | Micro QR Code when "--micro" or "-M" is given. 180 | 181 | Version 3.1.1 (2010.2.3) 182 | ------------------------ 183 | * A bug in the library has been fixed. 184 | 185 | Release Note: 186 | Libqrecode had generated incorrect QR Code in some cases. Symbols larger than 187 | version 5 (error correction level Q and H) were affected. In many cases this 188 | bug did not cause serious damage thanks to the error correction mechanism, but 189 | we highly recommend you to encode symbols again using this release. 190 | 191 | Version 3.1.0 (2009.6.6) 192 | ------------------------ 193 | * Various code cleanups and performance improves. 194 | * Strict internal error checks have been added. 195 | * "--without-tests" has become default setting. Specify "--with-tests" to 196 | compile test programs. 197 | * Some memory leak bugs have been fixed. 198 | 199 | Release Note: 200 | This release focuses on the code cleanup and performance improve. Encoding time 201 | has been improved, drastically in large symbols. Basically this update only 202 | changes its internal code. The API is not changed, no need to recompile user 203 | applications that includes only qrencode.h. If your application refers the 204 | internal data representation (not recommended), see ChangeLog for further 205 | information. 206 | 207 | Version 3.0.3 (2008.6.1) 208 | ------------------------ 209 | * Portability enhancement. (Thanks to Gavan Fantom) 210 | * The command line tool "qrencode" now accepts long options. See the man page 211 | for the detailed instruction. 212 | 213 | Release Note: 214 | This release improves the portability of our command line tool "qrencode". 215 | The library is not changed so that any applications using libqrencode are not 216 | affected. 217 | 218 | From this release, qrencode accepts "long" options, such as "--help". See the 219 | manpage for the detailed instructions. 220 | 221 | Qrencode now uses getopt_long() instead of getopt_long_only() which is not 222 | available in some operating systems. If the getopt_long() is not provided or 223 | the implementation of it is not compatible with GNU's one, please try 224 | qrencode-3.0.3-gnulib, that contains the source code of the getopt_long(). 225 | Gnulib version is a test release. If you feel happy with it, please let us know 226 | and the future releases will include gnulib. 227 | 228 | Version 3.0.2 (2008.5.18) 229 | ------------------------- 230 | * Some compile-time warnings/errors with g++ have been fixed. 231 | (Thanks to wangsai) 232 | * The bit order of "Version information" has been corrected. 233 | Symbols greater than version 6 were affected. (Thanks to Paul Janssesn) 234 | * The "--without-tests" option has been added to the configure script. 235 | 236 | Version 3.0.1 (2008.5.9) 237 | ------------------------ 238 | * A bug fix for non-POSIX platform. (Thanks to Paul Janssens) 239 | * The RPM spec file now packages the man page correctly. 240 | 241 | Version 3.0.0 (2008.4.30) 242 | ------------------------- 243 | * The interface of QRencode_encodeInput() has been changed. User applications 244 | using it must be modified. 245 | * Structured append support has been added. (patches from Yusuke Mihara) 246 | * The "-S" option for structured append has been added to qrencode and 247 | view_qrcode. 248 | * Some functions now set errno to indicate errors. 249 | * Some bug fixes. 250 | 251 | Release Note: 252 | Now libqrencode supports "structured-append" of symbols. A large data set can 253 | be split into multiple QR code symbols. The basic usage of structured-append 254 | is not so different from the single symbol encoding: just call 255 | QRcode_encodeStringStructured() or QRcode_encodeString8bitStructured() and 256 | they return a list of symbols. Instead of giving a string, you can encode 257 | an explicitly typed data. See the manual generated by Doxygen for the detailed 258 | usage. 259 | 260 | Many thanks to Yusuke Mihara, who contributed a patch to add support of 261 | structured-append to version 1.0.2. 262 | 263 | API changes: 264 | 265 | * Incompatible API changes: 266 | - QRencode_encodeInput 267 | * New types: 268 | - QRinput_Struct 269 | - QRcode_List 270 | * New functions: 271 | - QRinput_new2 272 | - QRinput_Struct_new 273 | - QRinput_Struct_setParity 274 | - QRinput_Struct_appendInput 275 | - QRinput_Struct_free 276 | - QRinput_Struct_insertStructuredAppendHeaders 277 | - QRinput_splitQRinputToStruct 278 | - QRcode_encodeStructuredInput 279 | - QRcode_encodeStringStructured 280 | - QRcode_encodeString8bitStructured 281 | - QRcode_List_size 282 | - QRcode_List_free 283 | * Declarations moved to qrencode.h: 284 | - QRinput_getErrorCorrectionLevel 285 | - QRinput_setErrorCorrectionLevel 286 | - QRinput_getVersion 287 | - QRinput_setVersion 288 | 289 | Version 2.0.0 (2008.1.24) 290 | ------------------------- 291 | * "-i" option to ignore case distinctions has been added to qrencode and 292 | view_qrcode. 293 | * "-c" option (case-sensitive mode) of qrencode is now enabled by default and 294 | has been improved. See details in Release Note section. 295 | * "-8" option has been added to qrencode to encode whole data in 8-bit mode. 296 | * tests/view_qrcode now accepts various options like qrencode. 297 | * Man page has been added. 298 | * Code cleanup. 299 | * The mask evaluation bug has been fixed. (Philippe Delcroix) 300 | 301 | * API changes 302 | - QRcode_encodeString() now receives case-sensitive flag. 303 | - QRcode_encodeStringCase() has been removed. 304 | - QRcode_encodeString8bit() has been added. 305 | 306 | Release Note: 307 | Previously libqrencode encodes lower-case alphabet characters in Alphabet- 308 | Numeric mode (upper-case alphabet and numeric) by default. According to the 309 | specification of QR code, however, it is clearly claimed that Alphabet-Numeric 310 | mode provides only upper-case alphabet (+ numeric and some symbol) characters. 311 | Since this version, libqrencode distinguishes lower-case and upper-case of 312 | alphabet characters by default. Because of that, "-c" option of qrencode 313 | is now deprecated, and "-i" option has been added. By giving "-i", qrencode 314 | converts lower-case characters to upper-case if possible, then encode a QR code 315 | symbol. Please read qrencode.h for the details about API changes if you are 316 | going to use this library. 317 | 318 | Many thanks to NANKI Haruo for his suggestions. 319 | 320 | Version 1.0.2 (2007.03.24) 321 | -------------------------- 322 | * A small bug fix. (Thanks to NANKI Haruo) 323 | * 'extern "C"' barrier has been added to qrencode.h. 324 | 325 | Version 1.0.1 (2006.12.27) 326 | -------------------------- 327 | * Added "force 8-bit encoding mode". 328 | * Configure script finds libpng's header correctly. 329 | 330 | Version 1.0.0 (2006.12.12) 331 | -------------------------- 332 | * The first public release. 333 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # libqrencode - a fast and compact QR Code encoding library [![Build Status](https://travis-ci.org/fukuchi/libqrencode.png?branch=master)](https://travis-ci.org/fukuchi/libqrencode) 2 | 3 | **Attention:** This repository contains the development version of libqrencode. See for the official stable releases. At this moment, the latest stable release is version 4.1.1. 4 | 5 | GENERAL INFORMATION 6 | =================== 7 | Libqrencode is a fast and compact library for encoding data in a QR Code, 8 | a 2D symbology that can be scanned by handy terminals such as a smartphone. 9 | The capacity of QR Code is up to 7000 digits or 4000 characters and has high 10 | robustness. 11 | 12 | Libqrencode accepts a string or a list of data chunks then encodes in a QR Code 13 | symbol as a bitmap array. While other QR Code applications generate an image 14 | file, using libqrencode allows applications to render QR Code symbols from raw 15 | bitmap data directly. This library also contains a command-line utility outputs 16 | QR Code images in various formats. 17 | 18 | 19 | SPECIFICATION 20 | ============= 21 | Libqrencode supports QR Code model 2, described in JIS (Japanese Industrial 22 | Standards) X0510:2004 or ISO/IEC 18004. Most of features in the specification 23 | are implemented such as: 24 | 25 | - Numeric, alphabet, Japanese kanji (Shift-JIS) or any 8 bit code can be 26 | embedded 27 | - Optimized encoding of a string 28 | - Structured-append of symbols 29 | - Micro QR Code (experimental) 30 | 31 | Currently the following features are not supported: 32 | 33 | - ECI and FNC1 mode 34 | - QR Code model 1 (deprecated) 35 | 36 | 37 | INSTALL 38 | ======= 39 | 40 | Requirements 41 | ------------ 42 | While the command-line utility and some test programs use libpng or SDL 2.0, 43 | the libqrencode library itself has no dependencies. You can skip compiling 44 | tests and/or tools if you want not to install programs using SDL or PNG. 45 | 46 | Compile & install 47 | ----------------- 48 | If there is no "configure" script in the source code directory, run 49 | "autogen.sh" at first to generate it - this is mandatory if you downloaded the 50 | source from GitHub. Some additional software is needed to complete this 51 | process. For example, in Ubuntu, the following packages are needed: 52 | 53 | - autoconf 54 | - automake 55 | - autotools-dev 56 | - libtool 57 | - pkg-config 58 | - libpng12-dev 59 | 60 | You can skip this process if you have "configure" script already (typically 61 | when you downloaded the source tarball from fukuchi.org.) 62 | 63 | Now you are ready to compile the library and tool. Type the following commands: 64 | 65 | ``` 66 | ./configure 67 | make 68 | sudo make install 69 | sudo ldconfig 70 | ``` 71 | 72 | This compiles and installs the library and header file to the appropriate 73 | directories: by default, /usr/local/lib and /usr/local/include. You can change 74 | the destination directory by passing some options to the configure script. 75 | Run "./configure --help" to see the list of options. 76 | 77 | It also installs a command line tool "qrencode" to /usr/local/bin. If you want 78 | not to build it, give "--without-tools" option to the configure script. 79 | 80 | If the configure script does not work well, try to use CMake. 81 | 82 | ``` 83 | cmake . 84 | make 85 | ``` 86 | 87 | When you want to build the test programs, give "--with-tests" option to 88 | configure, or "-DWITH\_TESTS=YES" to cmake. 89 | 90 | ### Building libqrencode with vcpkg 91 | 92 | You can download and install libqrencode using the 93 | [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager: 94 | 95 | ``` 96 | git clone https://github.com/Microsoft/vcpkg.git 97 | cd vcpkg 98 | ./bootstrap-vcpkg.sh 99 | ./vcpkg integrate install 100 | ./vcpkg install libqrencode 101 | ``` 102 | 103 | The libqrencode port in vcpkg is kept up to date by Microsoft team members and 104 | community contributors. If the version is out of date, please 105 | [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the 106 | vcpkg repository. 107 | 108 | 109 | USAGE 110 | ===== 111 | Basic usages of this library are written in the header file (qrencode.h). 112 | You can generate a manual of the library by using Doxygen, or see 113 | 114 | https://fukuchi.org/works/qrencode/manual/index.html 115 | 116 | 117 | WARNINGS 118 | ======== 119 | The library is distributed WITHOUT ANY WARRANTY. 120 | 121 | Micro QR Code support is EXPERIMENTAL. 122 | 123 | Be careful to use the command line tool (qrencode) if it is used by a web 124 | application (e.g. CGI script). For example, giving "-s" option with a large 125 | number to qrencode may cause DoS. The parameters should be checked by the 126 | application. 127 | 128 | 129 | LICENSING INFORMATION 130 | ===================== 131 | Copyright (C) 2006-2018 Kentaro Fukuchi 132 | 133 | This library is free software; you can redistribute it and/or modify it under 134 | the terms of the GNU Lesser General Public License as published by the Free 135 | Software Foundation; either version 2.1 of the License, or any later version. 136 | 137 | This library is distributed in the hope that it will be useful, but WITHOUT ANY 138 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 139 | PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 140 | 141 | You should have received a copy of the GNU Lesser General Public License along 142 | with this library; if not, write to the Free Software Foundation, Inc., 51 143 | Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 144 | 145 | 146 | CONTACT 147 | ======= 148 | Visit the homepage at: 149 | 150 | https://fukuchi.org/works/qrencode/ 151 | 152 | for new releases. The git repository is available at: 153 | 154 | https://github.com/fukuchi/libqrencode 155 | 156 | Please mail any bug reports, suggestions, comments, and questions to: 157 | 158 | Kentaro Fukuchi 159 | 160 | or submit issues to: 161 | 162 | https://github.com/fukuchi/libqrencode/issues 163 | 164 | 165 | ACKNOWLEDGMENTS 166 | =============== 167 | QR Code is registered trademarks of DENSO WAVE INCORPORATED in JAPAN and other 168 | countries. 169 | 170 | Reed-Solomon encoder included in this library is originally taken from FEC 171 | library developed by Phil Karn (KA9Q) and distributed under the terms of the 172 | GNU LGPL, then rewritten by Kentaro Fukuchi. 173 | Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q 174 | 175 | * NANKI Haruo - improved lower-case characters encoding 176 | * Katsumi Saito - SPEC file 177 | * Philippe Delcroix - improved mask evaluation 178 | * Yusuke Mihara - structured-append support 179 | * David Dahl - DPI and SVG support patch 180 | * Adam Shepherd - bug fix patch of the mask evaluation 181 | * Josef Eisl (@zapster) - EPS support patch 182 | * Colin (@moshen) - ANSI support patch 183 | * Ralf Ertzinger - ASCII support patch 184 | * Yutaka Niibe (@gniibe)- various bug fix patches 185 | * Dan Storm (@Repox) - SVG support patch 186 | * Lennart Poettering (@mezcalero) 187 | - improved text art patch 188 | * Yann Droneaud - improved input validation patch 189 | * Viona - bug fix patch for string splitting 190 | * Daniel Dörrhöfer (@d4ndo) 191 | - RLE option, some bug fixes, Travis configuration 192 | * Greg Hart - PNG32 support patch 193 | * @siggi-heltau - bug fix patch 194 | * Tobias Klauser (@tklauser) 195 | - bug fix patch, XPM support patch 196 | * Robert Petersen (@ripetersen) 197 | - added ability to read input data from a file 198 | * @Oblomov - improved SVG support patch 199 | * Michał Górny (@mgorny) 200 | - reverse mappings of UTF8 and ANSIUTF8, build script 201 | fixes 202 | * @EckoEdc - MinGW support patch 203 | * Sebastian Buchwald (@UniQP) 204 | - Various code cleanups 205 | * André Klitzing (@misery) 206 | - CMake support 207 | * Alexey Nikolaev (@aleksey-nikolaev) 208 | - improved CMake support 209 | * Vilppu Vuorinen (@vilppuvuorinen) 210 | - improved CMake support 211 | * @vanillahsu - bug fix patch 212 | * @Ation - bug fix patch 213 | * Jonathan Bennett - Added "--inline" option to qrencode 214 | * András Veres-Szentkirályi 215 | - ANSI256UTF8 support 216 | * @sdf5 - improved CMake support 217 | * Lonnie Abelbeck (@abelbeck) 218 | - bug fix patch 219 | * @4061N - performance improvement patch 220 | * Rosen Penev (@neheb) - CMake bug fix patch 221 | * Mika Lindqvist (@mtl1979) 222 | - replacement for gettimeofday() for Windows. 223 | * Shigeyuki Hirai, Paul Janssens, wangsai, Gavan Fantom, Matthew Baker, 224 | Rob Ryan, Fred Steinhaeuser, Terry Burton, @chisj, @vlad417, Petr, 225 | Hassan Hajji, Emmanuel Blot, ßlúèÇhîp, Heiko Becker, Gavin Andresen, 226 | David Binderman, @ralgozino, Sean McMurray, Vlad Bespalov (@win32asm), 227 | Antenore Gatta, Yoshimichi Inoue, Sunil Maganally, Norman Gray, 228 | Danomi Manchego, @minus7, Ian Sweet, @qianchenglenger, Ronald Michaels, 229 | Yuji Ueno, Jakub Wilk, @KangLin, @c-273, @thebunnyrules, @NancyLi1013, 230 | Frédéric Wang, Dan Jacobson, Jan Tojnar, @xiaoyur347, @charmander 231 | - bug report / suggestion / typo fixes 232 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | Micro QR code encoding is not tested well. 2 | 3 | Documents (not only the README, but also the manual of the library) needs 4 | revision of grammar, spelling or to resolve ambiguity or incomplete descriptions. 5 | Feel really free to send us your revision. 6 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | if [ `uname -s` = Darwin ]; then 6 | LIBTOOLIZE=glibtoolize 7 | else 8 | LIBTOOLIZE=libtoolize 9 | fi 10 | 11 | ACLOCAL_OPT="" 12 | if [ -d /usr/local/share/aclocal ]; then 13 | ACLOCAL_OPT="-I /usr/local/share/aclocal" 14 | elif [ -d /opt/local/share/aclocal ]; then 15 | ACLOCAL_OPT="-I /opt/local/share/aclocal" 16 | elif [ -d /usr/share/aclocal ]; then 17 | ACLOCAL_OPT="-I /usr/share/aclocal" 18 | fi 19 | 20 | if [ ! -d use ]; then 21 | mkdir use 22 | fi 23 | 24 | if [ ! -d m4 ]; then 25 | mkdir m4 26 | fi 27 | 28 | autoheader 29 | 30 | aclocal $ACLOCAL_OPT 31 | 32 | $LIBTOOLIZE --automake --copy 33 | automake --add-missing --copy 34 | 35 | autoconf 36 | -------------------------------------------------------------------------------- /bitstream.c: -------------------------------------------------------------------------------- 1 | /* 2 | * qrencode - QR Code encoder 3 | * 4 | * Binary sequence class. 5 | * Copyright (C) 2006-2017 Kentaro Fukuchi 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #if HAVE_CONFIG_H 23 | # include "config.h" 24 | #endif 25 | #include 26 | #include 27 | #include 28 | 29 | #include "bitstream.h" 30 | 31 | #define DEFAULT_BUFSIZE (128) 32 | 33 | BitStream *BitStream_new(void) 34 | { 35 | BitStream *bstream; 36 | 37 | bstream = (BitStream *)malloc(sizeof(BitStream)); 38 | if(bstream == NULL) return NULL; 39 | 40 | bstream->length = 0; 41 | bstream->data = (unsigned char *)malloc(DEFAULT_BUFSIZE); 42 | if(bstream->data == NULL) { 43 | free(bstream); 44 | return NULL; 45 | } 46 | bstream->datasize = DEFAULT_BUFSIZE; 47 | 48 | return bstream; 49 | } 50 | 51 | #ifdef WITH_TESTS 52 | BitStream *BitStream_newWithBits(size_t size, unsigned char *bits) 53 | { 54 | BitStream *bstream; 55 | 56 | if(size == 0) return BitStream_new(); 57 | 58 | bstream = (BitStream *)malloc(sizeof(BitStream)); 59 | if(bstream == NULL) return NULL; 60 | 61 | bstream->data = (unsigned char *)malloc(size); 62 | if(bstream->data == NULL) { 63 | free(bstream); 64 | return NULL; 65 | } 66 | 67 | bstream->length = size; 68 | bstream->datasize = size; 69 | memcpy(bstream->data, bits, size); 70 | 71 | return bstream; 72 | } 73 | #endif 74 | 75 | static int BitStream_expand(BitStream *bstream) 76 | { 77 | unsigned char *data; 78 | 79 | data = (unsigned char *)realloc(bstream->data, bstream->datasize * 2); 80 | if(data == NULL) { 81 | return -1; 82 | } 83 | 84 | bstream->data = data; 85 | bstream->datasize *= 2; 86 | 87 | return 0; 88 | } 89 | 90 | static void BitStream_writeNum(unsigned char *dest, size_t bits, unsigned int num) 91 | { 92 | unsigned int mask; 93 | size_t i; 94 | unsigned char *p; 95 | 96 | p = dest; 97 | mask = 1U << (bits - 1); 98 | for(i = 0; i < bits; i++) { 99 | if(num & mask) { 100 | *p = 1; 101 | } else { 102 | *p = 0; 103 | } 104 | p++; 105 | mask = mask >> 1; 106 | } 107 | } 108 | 109 | static void BitStream_writeBytes(unsigned char *dest, size_t size, unsigned char *data) 110 | { 111 | unsigned char mask; 112 | size_t i, j; 113 | unsigned char *p; 114 | 115 | p = dest; 116 | for(i = 0; i < size; i++) { 117 | mask = 0x80; 118 | for(j = 0; j < 8; j++) { 119 | if(data[i] & mask) { 120 | *p = 1; 121 | } else { 122 | *p = 0; 123 | } 124 | p++; 125 | mask = mask >> 1; 126 | } 127 | } 128 | } 129 | 130 | int BitStream_append(BitStream *bstream, BitStream *arg) 131 | { 132 | int ret; 133 | 134 | if(arg == NULL) { 135 | return -1; 136 | } 137 | if(arg->length == 0) { 138 | return 0; 139 | } 140 | 141 | while(bstream->length + arg->length > bstream->datasize) { 142 | ret = BitStream_expand(bstream); 143 | if(ret < 0) return ret; 144 | } 145 | 146 | memcpy(bstream->data + bstream->length, arg->data, arg->length); 147 | bstream->length += arg->length; 148 | 149 | return 0; 150 | } 151 | 152 | int BitStream_appendNum(BitStream *bstream, size_t bits, unsigned int num) 153 | { 154 | int ret; 155 | 156 | if(bits == 0) return 0; 157 | 158 | while(bstream->datasize - bstream->length < bits) { 159 | ret = BitStream_expand(bstream); 160 | if(ret < 0) return ret; 161 | } 162 | BitStream_writeNum(bstream->data + bstream->length, bits, num); 163 | bstream->length += bits; 164 | 165 | return 0; 166 | } 167 | 168 | int BitStream_appendBytes(BitStream *bstream, size_t size, unsigned char *data) 169 | { 170 | int ret; 171 | 172 | if(size == 0) return 0; 173 | 174 | while(bstream->datasize - bstream->length < size * 8) { 175 | ret = BitStream_expand(bstream); 176 | if(ret < 0) return ret; 177 | } 178 | BitStream_writeBytes(bstream->data + bstream->length, size, data); 179 | bstream->length += size * 8; 180 | 181 | return 0; 182 | } 183 | 184 | unsigned char *BitStream_toByte(BitStream *bstream) 185 | { 186 | size_t i, j, size, bytes, oddbits; 187 | unsigned char *data, v; 188 | unsigned char *p; 189 | 190 | size = BitStream_size(bstream); 191 | if(size == 0) { 192 | return NULL; 193 | } 194 | data = (unsigned char *)malloc((size + 7) / 8); 195 | if(data == NULL) { 196 | return NULL; 197 | } 198 | 199 | bytes = size / 8; 200 | 201 | p = bstream->data; 202 | for(i = 0; i < bytes; i++) { 203 | v = 0; 204 | for(j = 0; j < 8; j++) { 205 | v = (unsigned char)(v << 1); 206 | v |= *p; 207 | p++; 208 | } 209 | data[i] = v; 210 | } 211 | oddbits = size & 7; 212 | if(oddbits > 0) { 213 | v = 0; 214 | for(j = 0; j < oddbits; j++) { 215 | v = (unsigned char)(v << 1); 216 | v |= *p; 217 | p++; 218 | } 219 | data[bytes] = (unsigned char)(v << (8 - oddbits)); 220 | } 221 | 222 | return data; 223 | } 224 | 225 | void BitStream_free(BitStream *bstream) 226 | { 227 | if(bstream != NULL) { 228 | free(bstream->data); 229 | free(bstream); 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /bitstream.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qrencode - QR Code encoder 3 | * 4 | * Binary sequence class. 5 | * Copyright (C) 2006-2017 Kentaro Fukuchi 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #ifndef BITSTREAM_H 23 | #define BITSTREAM_H 24 | 25 | typedef struct { 26 | size_t length; 27 | size_t datasize; 28 | unsigned char *data; 29 | } BitStream; 30 | 31 | extern BitStream *BitStream_new(void); 32 | #ifdef WITH_TESTS 33 | extern BitStream *BitStream_newWithBits(size_t size, unsigned char *bits); 34 | #endif 35 | extern int BitStream_append(BitStream *bstream, BitStream *arg); 36 | extern int BitStream_appendNum(BitStream *bstream, size_t bits, unsigned int num); 37 | extern int BitStream_appendBytes(BitStream *bstream, size_t size, unsigned char *data); 38 | #define BitStream_size(__bstream__) (__bstream__->length) 39 | #define BitStream_reset(__bstream__) (__bstream__->length = 0) 40 | extern unsigned char *BitStream_toByte(BitStream *bstream); 41 | extern void BitStream_free(BitStream *bstream); 42 | 43 | #endif /* BITSTREAM_H */ 44 | -------------------------------------------------------------------------------- /cmake/FindIconv.cmake: -------------------------------------------------------------------------------- 1 | include(CheckFunctionExists) 2 | 3 | set(_ICONV_SEARCHES) 4 | 5 | # Search ICONV_DIR first if it is set. 6 | if(NOT ICONV_DIR AND ENV{ICONV_DIR}) 7 | set(ICONV_DIR $ENV{ICONV_DIR}) 8 | endif() 9 | 10 | if(ICONV_DIR) 11 | set(_ICONV_DIR_SEARCH PATHS ${ICONV_DIR} NO_DEFAULT_PATH) 12 | list(APPEND _ICONV_SEARCHES _ICONV_DIR_SEARCH) 13 | endif() 14 | 15 | # Normal search. 16 | set(_ICONV_SEARCH_NORMAL 17 | PATHS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\Iconv;InstallPath]" 18 | "$ENV{PROGRAMFILES}/iconv" 19 | ENV CPATH 20 | ENV C_INCLUDE_PATH 21 | ENV CPLUS_INCLUDE_PATH 22 | ENV LIBRARY_PATH) 23 | list(APPEND _ICONV_SEARCHES _ICONV_SEARCH_NORMAL) 24 | 25 | set(ICONV_NAMES iconv iconv2 libiconv iconv64) 26 | set(ICONV_NAMES_DEBUG iconvd iconv64d) 27 | 28 | # Try each search configuration. 29 | foreach(search ${_ICONV_SEARCHES}) 30 | find_path(ICONV_INCLUDE_DIR NAMES iconv.h ${${search}} PATH_SUFFIXES include) 31 | endforeach() 32 | 33 | # Allow ICONV_LIBRARY to be set manually, as the location of the iconv library 34 | if(NOT ICONV_LIBRARY) 35 | foreach(search ${_ICONV_SEARCHES}) 36 | find_library(ICONV_LIBRARY_RELEASE NAMES ${ICONV_NAMES} ${${search}} PATH_SUFFIXES lib) 37 | find_library(ICONV_LIBRARY_DEBUG NAMES ${ICONV_NAMES_DEBUG} ${${search}} PATH_SUFFIXES lib) 38 | endforeach() 39 | 40 | include(SelectLibraryConfigurations) 41 | select_library_configurations(ICONV) 42 | endif() 43 | 44 | unset(ICONV_NAMES) 45 | unset(ICONV_NAMES_DEBUG) 46 | 47 | if(ICONV_INCLUDE_DIR AND EXISTS "${ICONV_INCLUDE_DIR}/iconv.h") 48 | file(STRINGS "${ICONV_INCLUDE_DIR}/iconv.h" ICONV_H REGEX "^#define _LIBICONV_VERSION 0x([0-9]+)") 49 | string(REGEX MATCH "q#define _LIBICONV_VERSION 0x([0-9][0-9])([0-9][0-9])?([0-9][0-9])?.*" temp_match "${ICONV_H}") 50 | unset(temp_match) 51 | if(CMAKE_MATCH_0) 52 | set(ICONV_VERSION_MAJOR "${CMAKE_MATCH_1}") 53 | set(ICONV_VERSION_MINOR "${CMAKE_MATCH_2}") 54 | set(ICONV_VERSION_PATCH "${CMAKE_MATCH_3}") 55 | string(REGEX REPLACE "0*([1-9][0-9]*).*" "\\1" ICONV_VERSION_MAJOR "${ICONV_VERSION_MAJOR}") 56 | string(REGEX REPLACE "0*([1-9][0-9]*).*" "\\1" ICONV_VERSION_MINOR "${ICONV_VERSION_MINOR}") 57 | string(REGEX REPLACE "0*([1-9][0-9]*).*" "\\1" ICONV_VERSION_PATCH "${ICONV_VERSION_PATCH}") 58 | 59 | set(ICONV_VERSION_STRING "${ICONV_VERSION_MAJOR}.${ICONV_VERSION_MINOR}") 60 | if(ICONV_VERSION_PATCH) 61 | set(ICONV_VERSION_STRING "${ICONV_VERSION_STRING}.${ICONV_VERSION_PATCH}") 62 | endif() 63 | endif() 64 | endif() 65 | 66 | check_function_exists(iconv_open ICONV_IN_GLIBC) 67 | 68 | set(ICONV_FOUND_ANY FALSE) 69 | if(ICONV_IN_GLIBC OR ICONV_LIBRARY) 70 | set(ICONV_FOUND_ANY TRUE) 71 | endif() 72 | 73 | # handle the QUIETLY and REQUIRED arguments and set ICONV_FOUND to TRUE if 74 | # all listed variables are TRUE 75 | include(FindPackageHandleStandardArgs) 76 | find_package_handle_standard_args(ICONV 77 | REQUIRED_VARS ICONV_FOUND_ANY ICONV_INCLUDE_DIR 78 | VERSION_VAR ICONV_VERSION_STRING) 79 | 80 | mark_as_advanced(ICONV_LIBRARY ICONV_INCLUDE_DIR) 81 | 82 | if(NOT ICONV_FOUND) 83 | return() 84 | endif() 85 | 86 | set(ICONV_INCLUDE_DIRS ${ICONV_INCLUDE_DIR}) 87 | 88 | if(NOT ICONV_LIBRARIES) 89 | set(ICONV_LIBRARIES ${ICONV_LIBRARY}) 90 | endif() 91 | 92 | if(ICONV_LIBRARY AND NOT TARGET ICONV::ICONV) 93 | add_library(ICONV::ICONV UNKNOWN IMPORTED) 94 | set_target_properties(ICONV::ICONV PROPERTIES 95 | INTERFACE_INCLUDE_DIRECTORIES "${ICONV_INCLUDE_DIRS}" 96 | IMPORTED_LOCATION "${ICONV_LIBRARY}") 97 | 98 | if(ICONV_LIBRARY_RELEASE) 99 | set_property(TARGET ICONV::ICONV APPEND PROPERTY 100 | IMPORTED_CONFIGURATIONS RELEASE) 101 | set_target_properties(ICONV::ICONV PROPERTIES 102 | IMPORTED_LOCATION_RELEASE "${ICONV_LIBRARY_RELEASE}") 103 | endif() 104 | 105 | if(ICONV_LIBRARY_DEBUG) 106 | set_property(TARGET ICONV::ICONV APPEND PROPERTY 107 | IMPORTED_CONFIGURATIONS DEBUG) 108 | set_target_properties(ICONV::ICONV PROPERTIES 109 | IMPORTED_LOCATION_DEBUG "${ICONV_LIBRARY_DEBUG}") 110 | endif() 111 | elseif(NOT TARGET ICONV::ICONV) 112 | add_library(ICONV::ICONV INTERFACE IMPORTED) 113 | set_target_properties(ICONV::ICONV PROPERTIES 114 | INTERFACE_INCLUDE_DIRECTORIES "${ICONV_INCLUDE_DIRS}") 115 | endif() 116 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | m4_define([__MAJOR_VERSION], [4])dnl 2 | m4_define([__MINOR_VERSION], [1])dnl 3 | m4_define([__MICRO_VERSION], [1])dnl 4 | m4_define([__VERSION], [__MAJOR_VERSION.__MINOR_VERSION.__MICRO_VERSION])dnl 5 | AC_INIT(QRencode, __VERSION) 6 | 7 | MAJOR_VERSION=__MAJOR_VERSION 8 | MINOR_VERSION=__MINOR_VERSION 9 | MICRO_VERSION=__MICRO_VERSION 10 | AC_SUBST(MAJOR_VERSION) 11 | AC_SUBST(MINOR_VERSION) 12 | AC_SUBST(MICRO_VERSION) 13 | AC_DEFINE_UNQUOTED([MAJOR_VERSION], [$MAJOR_VERSION], [Major version number]) 14 | AC_DEFINE_UNQUOTED([MINOR_VERSION], [$MINOR_VERSION], [Minor version number]) 15 | AC_DEFINE_UNQUOTED([MICRO_VERSION], [$MICRO_VERSION], [Micro version number]) 16 | 17 | AC_CONFIG_SRCDIR([qrencode.c]) 18 | AC_CONFIG_HEADERS([config.h]) 19 | AC_CONFIG_AUX_DIR(use) 20 | AC_CONFIG_MACRO_DIR([m4]) 21 | AC_CANONICAL_HOST 22 | AC_CANONICAL_TARGET 23 | 24 | AM_INIT_AUTOMAKE 25 | 26 | AC_DISABLE_STATIC 27 | AC_C_CONST 28 | AC_C_INLINE 29 | AC_HEADER_STDC 30 | AC_CHECK_HEADERS(sys/time.h) 31 | 32 | LT_INIT 33 | AC_PROG_CC 34 | AM_PROG_CC_C_O 35 | AC_PROG_INSTALL 36 | AC_PROG_LIBTOOL 37 | PKG_PROG_PKG_CONFIG 38 | 39 | case "${target}" in 40 | *-*-mingw*) 41 | mingw=yes 42 | esac 43 | AM_CONDITIONAL(MINGW, [test "x$mingw" = "xyes" ]) 44 | 45 | AC_CONFIG_FILES([Makefile libqrencode.pc tests/Makefile qrencode.1]) 46 | 47 | AC_CHECK_FUNCS([strdup]) 48 | 49 | dnl --enable-thread-safety 50 | AC_ARG_ENABLE([thread-safety], [AS_HELP_STRING([--enable-thread-safety], [make the library thread-safe. [default=yes]])], 51 | [], [enable_thread_safety=yes]) 52 | 53 | if test x$enable_thread_safety = xyes; then 54 | AC_CHECK_LIB([pthread], [pthread_mutex_init], [AC_SUBST([LIBPTHREAD], [-lpthread])]) 55 | fi 56 | AM_CONDITIONAL([HAVE_LIBPTHREAD], [test "x$ac_cv_lib_pthread_pthread_mutex_init" = "xyes" ]) 57 | # FIXME: isn't it able to integrate the followings to AC_CHECK_LIB? 58 | if test x$ac_cv_lib_pthread_pthread_mutex_init = xyes ; then 59 | AC_DEFINE([HAVE_LIBPTHREAD], [1], [Define to 1 if using pthread is enabled.]) 60 | CFLAGS="$CFLAGS -pthread" 61 | fi 62 | 63 | AC_ARG_WITH(png, 64 | [AC_HELP_STRING([--without-png], 65 | [disable PNG support])], 66 | [with_png=$withval], [with_png=yes]) 67 | 68 | dnl --with-tools 69 | AC_ARG_WITH([tools], [AS_HELP_STRING([--with-tools], [build utility tools [default=yes]])], 70 | [build_tools=$withval], [build_tools=yes]) 71 | 72 | AM_CONDITIONAL(BUILD_TOOLS, [test "x$build_tools" = "xyes" ]) 73 | if test x$build_tools = xyes && test x$with_png = xyes ; then 74 | PKG_CHECK_MODULES(png, "libpng", [AC_DEFINE([HAVE_PNG], [1], [Define to 1 if using libpng is enabled.])], [AC_DEFINE([HAVE_PNG], [0])]) 75 | if test "x$png_CFLAGS" = "x" && test x$with_png = xyes ; then 76 | echo " 77 | !!!!!!!!!! 78 | LIBPNG is required to build the utility tools. Temporarily disabled. 79 | !!!!!!!!!! 80 | " 81 | fi 82 | fi 83 | AM_CONDITIONAL(HAVE_PNG, [test "x$png_CFLAGS" != "x" ]) 84 | 85 | dnl --with-tests 86 | AC_ARG_WITH([tests], [AS_HELP_STRING([--with-tests], [build tests [default=no]])], 87 | [build_tests=$withval], [build_tests=no]) 88 | 89 | AM_CONDITIONAL(BUILD_TESTS, [test "x$build_tests" = "xyes" ]) 90 | AH_VERBATIM([tests], 91 | [/* Define to 'static' if no test programs will be compiled. */ 92 | #define STATIC_IN_RELEASE static 93 | #undef WITH_TESTS 94 | ]) 95 | if test x$build_tests = xyes ; then 96 | echo "#define STATIC_IN_RELEASE" >>confdefs.h 97 | echo "#define WITH_TESTS 1" >>confdefs.h 98 | else 99 | echo "#define STATIC_IN_RELEASE static" >>confdefs.h 100 | echo "/* #undef WITH_TESTS */" >>confdefs.h 101 | fi 102 | 103 | if test x$build_tests = xyes ; then 104 | SDL_REQUIRED_VERSION=2.0.0 105 | PKG_CHECK_MODULES(SDL, [sdl2 >= $SDL_REQUIRED_VERSION], [AC_DEFINE([HAVE_SDL], [1], [Define to 1 if using SDL is enabled.])], [AC_DEFINE([HAVE_SDL], [0])]) 106 | AM_ICONV_LINK 107 | fi 108 | AM_CONDITIONAL(HAVE_SDL, [test "x$SDL_CFLAGS" != "x" ]) 109 | 110 | 111 | dnl --enable-gprof 112 | AC_ARG_ENABLE([gprof], [AS_HELP_STRING([--enable-gprof], [generate extra code to write profile information suitable for gprof [default=no]])], 113 | [], [enable_gprof=no]) 114 | 115 | if test x$enable_gprof = xyes; then 116 | CFLAGS="$CFLAGS -g -pg" 117 | fi 118 | 119 | 120 | dnl --enable-gcov 121 | AC_ARG_ENABLE([gcov], [AS_HELP_STRING([--enable-gcov], [generate extra code to write coverage information suitable for gcov [default=no]])], 122 | [], [enable_gcov=no]) 123 | 124 | if test x$enable_gcov = xyes; then 125 | CFLAGS="$CFLAGS --coverage" 126 | fi 127 | 128 | 129 | dnl --enable-mudflap 130 | AC_ARG_ENABLE([mudflap], [AS_HELP_STRING([--enable-mudflap], [generate extra code to check memory leaks [default=no]])], 131 | [], [enable_mudflap=no]) 132 | 133 | if test x$enable_mudflap = xyes; then 134 | if test x$enable_thread_safety = xyes; then 135 | CFLAGS="$CFLAGS -fmudflapth" 136 | LDFLAGS="$LDFLAGS -lmudflapth" 137 | else 138 | CFLAGS="$CFLAGS -fmudflap" 139 | LDFLAGS="$LDFLAGS -lmudflap" 140 | fi 141 | fi 142 | 143 | dnl --enable-asan 144 | AC_ARG_ENABLE([asan], [AS_HELP_STRING([--enable-asan], [use AddressSanitizer [default=no]])], 145 | [], [enable_asan=no]) 146 | 147 | if test x$enable_asan = xyes; then 148 | CFLAGS="$CFLAGS -fsanitize=address -fno-omit-frame-pointer" 149 | LDFLAGS="$LDFLAGS -fsanitize=address" 150 | fi 151 | 152 | 153 | dnl set CFLAGS 154 | CFLAGS="-Wall $CFLAGS" 155 | 156 | 157 | AC_OUTPUT 158 | 159 | echo "" 160 | echo "Options used to compile and link:" 161 | echo " CC = $CC" 162 | echo " CFLAGS = $CFLAGS" 163 | echo " CPPFLAGS = $CPPFLAGS" 164 | echo " CXX = $CXX" 165 | echo " CXXFLAGS = $CXXFLAGS" 166 | echo " LDFLAGS = $LDFLAGS" 167 | echo "" 168 | -------------------------------------------------------------------------------- /libqrencode.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: libqrencode 7 | Description: A QR Code encoding library 8 | Version: @VERSION@ 9 | Libs: -L${libdir} -lqrencode 10 | Libs.private: @LIBPTHREAD@ 11 | Cflags: -I${includedir} 12 | -------------------------------------------------------------------------------- /makeREADME.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | sed '/^```$/d 4 | /^\*\*Attention/d 5 | s/DWITH\\_TESTS/DWITH_TESTS/ 6 | 1 { 7 | s/^# // 8 | s/encoding library.*/encoding library/ 9 | } 10 | ' README.md > README 11 | -------------------------------------------------------------------------------- /mask.c: -------------------------------------------------------------------------------- 1 | /* 2 | * qrencode - QR Code encoder 3 | * 4 | * Masking. 5 | * Copyright (C) 2006-2017 Kentaro Fukuchi 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #if HAVE_CONFIG_H 23 | # include "config.h" 24 | #endif 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "qrencode.h" 31 | #include "qrspec.h" 32 | #include "mask.h" 33 | 34 | STATIC_IN_RELEASE int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level) 35 | { 36 | unsigned int format; 37 | unsigned char v; 38 | int i; 39 | int blacks = 0; 40 | 41 | format = QRspec_getFormatInfo(mask, level); 42 | 43 | for(i = 0; i < 8; i++) { 44 | if(format & 1) { 45 | blacks += 2; 46 | v = 0x85; 47 | } else { 48 | v = 0x84; 49 | } 50 | frame[width * 8 + width - 1 - i] = v; 51 | if(i < 6) { 52 | frame[width * i + 8] = v; 53 | } else { 54 | frame[width * (i + 1) + 8] = v; 55 | } 56 | format= format >> 1; 57 | } 58 | for(i = 0; i < 7; i++) { 59 | if(format & 1) { 60 | blacks += 2; 61 | v = 0x85; 62 | } else { 63 | v = 0x84; 64 | } 65 | frame[width * (width - 7 + i) + 8] = v; 66 | if(i == 0) { 67 | frame[width * 8 + 7] = v; 68 | } else { 69 | frame[width * 8 + 6 - i] = v; 70 | } 71 | format= format >> 1; 72 | } 73 | 74 | return blacks; 75 | } 76 | 77 | /** 78 | * Demerit coefficients. 79 | * See Section 8.8.2, pp.45, JIS X0510:2004. 80 | */ 81 | #define N1 (3) 82 | #define N2 (3) 83 | #define N3 (40) 84 | #define N4 (10) 85 | 86 | #define MASKMAKER(__exp__) \ 87 | int x, y;\ 88 | int b = 0;\ 89 | \ 90 | for(y = 0; y < width; y++) {\ 91 | for(x = 0; x < width; x++) {\ 92 | if(*s & 0x80) {\ 93 | *d = *s;\ 94 | } else {\ 95 | *d = *s ^ ((__exp__) == 0);\ 96 | }\ 97 | b += (int)(*d & 1);\ 98 | s++; d++;\ 99 | }\ 100 | }\ 101 | return b; 102 | 103 | static int Mask_mask0(int width, const unsigned char *s, unsigned char *d) 104 | { 105 | MASKMAKER((x+y)&1) 106 | } 107 | 108 | static int Mask_mask1(int width, const unsigned char *s, unsigned char *d) 109 | { 110 | MASKMAKER(y&1) 111 | } 112 | 113 | static int Mask_mask2(int width, const unsigned char *s, unsigned char *d) 114 | { 115 | MASKMAKER(x%3) 116 | } 117 | 118 | static int Mask_mask3(int width, const unsigned char *s, unsigned char *d) 119 | { 120 | MASKMAKER((x+y)%3) 121 | } 122 | 123 | static int Mask_mask4(int width, const unsigned char *s, unsigned char *d) 124 | { 125 | MASKMAKER(((y/2)+(x/3))&1) 126 | } 127 | 128 | static int Mask_mask5(int width, const unsigned char *s, unsigned char *d) 129 | { 130 | MASKMAKER(((x*y)&1)+(x*y)%3) 131 | } 132 | 133 | static int Mask_mask6(int width, const unsigned char *s, unsigned char *d) 134 | { 135 | MASKMAKER((((x*y)&1)+(x*y)%3)&1) 136 | } 137 | 138 | static int Mask_mask7(int width, const unsigned char *s, unsigned char *d) 139 | { 140 | MASKMAKER((((x*y)%3)+((x+y)&1))&1) 141 | } 142 | 143 | #define maskNum (8) 144 | typedef int MaskMaker(int, const unsigned char *, unsigned char *); 145 | static MaskMaker *maskMakers[maskNum] = { 146 | Mask_mask0, Mask_mask1, Mask_mask2, Mask_mask3, 147 | Mask_mask4, Mask_mask5, Mask_mask6, Mask_mask7 148 | }; 149 | 150 | #ifdef WITH_TESTS 151 | unsigned char *Mask_makeMaskedFrame(int width, unsigned char *frame, int mask) 152 | { 153 | unsigned char *masked; 154 | 155 | masked = (unsigned char *)malloc((size_t)(width * width)); 156 | if(masked == NULL) return NULL; 157 | 158 | maskMakers[mask](width, frame, masked); 159 | 160 | return masked; 161 | } 162 | #endif 163 | 164 | unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level) 165 | { 166 | unsigned char *masked; 167 | 168 | if(mask < 0 || mask >= maskNum) { 169 | errno = EINVAL; 170 | return NULL; 171 | } 172 | 173 | masked = (unsigned char *)malloc((size_t)(width * width)); 174 | if(masked == NULL) return NULL; 175 | 176 | maskMakers[mask](width, frame, masked); 177 | Mask_writeFormatInformation(width, masked, mask, level); 178 | 179 | return masked; 180 | } 181 | 182 | 183 | //static int n1; 184 | //static int n2; 185 | //static int n3; 186 | //static int n4; 187 | 188 | STATIC_IN_RELEASE int Mask_calcN1N3(int length, int *runLength) 189 | { 190 | int i; 191 | int demerit = 0; 192 | int fact; 193 | 194 | for(i = 0; i < length; i++) { 195 | if(runLength[i] >= 5) { 196 | demerit += N1 + (runLength[i] - 5); 197 | //n1 += N1 + (runLength[i] - 5); 198 | } 199 | if((i & 1)) { 200 | if(i >= 3 && i < length-2 && (runLength[i] % 3) == 0) { 201 | fact = runLength[i] / 3; 202 | if(runLength[i-2] == fact && 203 | runLength[i-1] == fact && 204 | runLength[i+1] == fact && 205 | runLength[i+2] == fact) { 206 | if(i == 3 || runLength[i-3] >= 4 * fact) { 207 | demerit += N3; 208 | //n3 += N3; 209 | } else if(i+4 >= length || runLength[i+3] >= 4 * fact) { 210 | demerit += N3; 211 | //n3 += N3; 212 | } 213 | } 214 | } 215 | } 216 | } 217 | 218 | return demerit; 219 | } 220 | 221 | STATIC_IN_RELEASE int Mask_calcN2(int width, unsigned char *frame) 222 | { 223 | int x, y; 224 | unsigned char *p; 225 | unsigned char b22, w22; 226 | int demerit = 0; 227 | 228 | p = frame + width + 1; 229 | for(y = 1; y < width; y++) { 230 | for(x = 1; x < width; x++) { 231 | b22 = p[0] & p[-1] & p[-width] & p [-width-1]; 232 | w22 = p[0] | p[-1] | p[-width] | p [-width-1]; 233 | if((b22 | (w22 ^ 1))&1) { 234 | demerit += N2; 235 | } 236 | p++; 237 | } 238 | p++; 239 | } 240 | 241 | return demerit; 242 | } 243 | 244 | STATIC_IN_RELEASE int Mask_calcRunLengthH(int width, unsigned char *frame, int *runLength) 245 | { 246 | int head; 247 | int i; 248 | unsigned char prev; 249 | 250 | if(frame[0] & 1) { 251 | runLength[0] = -1; 252 | head = 1; 253 | } else { 254 | head = 0; 255 | } 256 | runLength[head] = 1; 257 | prev = frame[0]; 258 | 259 | for(i = 1; i < width; i++) { 260 | if((frame[i] ^ prev) & 1) { 261 | head++; 262 | runLength[head] = 1; 263 | prev = frame[i]; 264 | } else { 265 | runLength[head]++; 266 | } 267 | } 268 | 269 | return head + 1; 270 | } 271 | 272 | STATIC_IN_RELEASE int Mask_calcRunLengthV(int width, unsigned char *frame, int *runLength) 273 | { 274 | int head; 275 | int i; 276 | unsigned char prev; 277 | 278 | if(frame[0] & 1) { 279 | runLength[0] = -1; 280 | head = 1; 281 | } else { 282 | head = 0; 283 | } 284 | runLength[head] = 1; 285 | prev = frame[0]; 286 | 287 | for(i = 1; i < width; i++) { 288 | if((frame[i * width] ^ prev) & 1) { 289 | head++; 290 | runLength[head] = 1; 291 | prev = frame[i * width]; 292 | } else { 293 | runLength[head]++; 294 | } 295 | } 296 | 297 | return head + 1; 298 | } 299 | 300 | STATIC_IN_RELEASE int Mask_evaluateSymbol(int width, unsigned char *frame) 301 | { 302 | int x, y; 303 | int demerit = 0; 304 | int runLength[QRSPEC_WIDTH_MAX + 1]; 305 | int length; 306 | 307 | demerit += Mask_calcN2(width, frame); 308 | 309 | for(y = 0; y < width; y++) { 310 | length = Mask_calcRunLengthH(width, frame + y * width, runLength); 311 | demerit += Mask_calcN1N3(length, runLength); 312 | } 313 | 314 | for(x = 0; x < width; x++) { 315 | length = Mask_calcRunLengthV(width, frame + x, runLength); 316 | demerit += Mask_calcN1N3(length, runLength); 317 | } 318 | 319 | return demerit; 320 | } 321 | 322 | unsigned char *Mask_mask(int width, unsigned char *frame, QRecLevel level) 323 | { 324 | int i; 325 | unsigned char *mask, *bestMask; 326 | int minDemerit = INT_MAX; 327 | int blacks; 328 | int bratio; 329 | int demerit; 330 | int w2 = width * width; 331 | 332 | mask = (unsigned char *)malloc((size_t)w2); 333 | if(mask == NULL) return NULL; 334 | bestMask = (unsigned char *)malloc((size_t)w2); 335 | if(bestMask == NULL) { 336 | free(mask); 337 | return NULL; 338 | } 339 | 340 | for(i = 0; i < maskNum; i++) { 341 | // n1 = n2 = n3 = n4 = 0; 342 | demerit = 0; 343 | blacks = maskMakers[i](width, frame, mask); 344 | blacks += Mask_writeFormatInformation(width, mask, i, level); 345 | bratio = (200 * blacks + w2) / w2 / 2; /* (int)(100*blacks/w2+0.5) */ 346 | demerit = (abs(bratio - 50) / 5) * N4; 347 | // n4 = demerit; 348 | demerit += Mask_evaluateSymbol(width, mask); 349 | // printf("(%d,%d,%d,%d)=%d\n", n1, n2, n3 ,n4, demerit); 350 | if(demerit < minDemerit) { 351 | minDemerit = demerit; 352 | memcpy(bestMask, mask, (size_t)w2); 353 | } 354 | } 355 | free(mask); 356 | return bestMask; 357 | } 358 | -------------------------------------------------------------------------------- /mask.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qrencode - QR Code encoder 3 | * 4 | * Masking. 5 | * Copyright (C) 2006-2017 Kentaro Fukuchi 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #ifndef MASK_H 23 | #define MASK_H 24 | 25 | extern unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level); 26 | extern unsigned char *Mask_mask(int width, unsigned char *frame, QRecLevel level); 27 | 28 | #ifdef WITH_TESTS 29 | extern int Mask_calcN2(int width, unsigned char *frame); 30 | extern int Mask_calcN1N3(int length, int *runLength); 31 | extern int Mask_calcRunLengthH(int width, unsigned char *frame, int *runLength); 32 | extern int Mask_calcRunLengthV(int width, unsigned char *frame, int *runLength); 33 | extern int Mask_evaluateSymbol(int width, unsigned char *frame); 34 | extern int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level); 35 | extern unsigned char *Mask_makeMaskedFrame(int width, unsigned char *frame, int mask); 36 | #endif 37 | 38 | #endif /* MASK_H */ 39 | -------------------------------------------------------------------------------- /mmask.c: -------------------------------------------------------------------------------- 1 | /* 2 | * qrencode - QR Code encoder 3 | * 4 | * Masking for Micro QR Code. 5 | * Copyright (C) 2006-2017 Kentaro Fukuchi 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #if HAVE_CONFIG_H 23 | # include "config.h" 24 | #endif 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "qrencode.h" 31 | #include "mqrspec.h" 32 | #include "mmask.h" 33 | 34 | STATIC_IN_RELEASE void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level) 35 | { 36 | unsigned int format; 37 | unsigned char v; 38 | int i; 39 | 40 | format = MQRspec_getFormatInfo(mask, version, level); 41 | 42 | for(i = 0; i < 8; i++) { 43 | v = 0x84 | (format & 1); 44 | frame[width * (i + 1) + 8] = v; 45 | format = format >> 1; 46 | } 47 | for(i = 0; i < 7; i++) { 48 | v = 0x84 | (format & 1); 49 | frame[width * 8 + 7 - i] = v; 50 | format = format >> 1; 51 | } 52 | } 53 | 54 | #define MASKMAKER(__exp__) \ 55 | int x, y;\ 56 | \ 57 | for(y = 0; y < width; y++) {\ 58 | for(x = 0; x < width; x++) {\ 59 | if(*s & 0x80) {\ 60 | *d = *s;\ 61 | } else {\ 62 | *d = *s ^ ((__exp__) == 0);\ 63 | }\ 64 | s++; d++;\ 65 | }\ 66 | } 67 | 68 | static void Mask_mask0(int width, const unsigned char *s, unsigned char *d) 69 | { 70 | MASKMAKER(y&1) 71 | } 72 | 73 | static void Mask_mask1(int width, const unsigned char *s, unsigned char *d) 74 | { 75 | MASKMAKER(((y/2)+(x/3))&1) 76 | } 77 | 78 | static void Mask_mask2(int width, const unsigned char *s, unsigned char *d) 79 | { 80 | MASKMAKER((((x*y)&1)+(x*y)%3)&1) 81 | } 82 | 83 | static void Mask_mask3(int width, const unsigned char *s, unsigned char *d) 84 | { 85 | MASKMAKER((((x+y)&1)+((x*y)%3))&1) 86 | } 87 | 88 | #define maskNum (4) 89 | typedef void MaskMaker(int, const unsigned char *, unsigned char *); 90 | static MaskMaker *maskMakers[maskNum] = { 91 | Mask_mask0, Mask_mask1, Mask_mask2, Mask_mask3 92 | }; 93 | 94 | #ifdef WITH_TESTS 95 | unsigned char *MMask_makeMaskedFrame(int width, unsigned char *frame, int mask) 96 | { 97 | unsigned char *masked; 98 | 99 | masked = (unsigned char *)malloc((size_t)(width * width)); 100 | if(masked == NULL) return NULL; 101 | 102 | maskMakers[mask](width, frame, masked); 103 | 104 | return masked; 105 | } 106 | #endif 107 | 108 | unsigned char *MMask_makeMask(int version, unsigned char *frame, int mask, QRecLevel level) 109 | { 110 | unsigned char *masked; 111 | int width; 112 | 113 | if(mask < 0 || mask >= maskNum) { 114 | errno = EINVAL; 115 | return NULL; 116 | } 117 | 118 | width = MQRspec_getWidth(version); 119 | masked = (unsigned char *)malloc((size_t)(width * width)); 120 | if(masked == NULL) return NULL; 121 | 122 | maskMakers[mask](width, frame, masked); 123 | MMask_writeFormatInformation(version, width, masked, mask, level); 124 | 125 | return masked; 126 | } 127 | 128 | STATIC_IN_RELEASE int MMask_evaluateSymbol(int width, unsigned char *frame) 129 | { 130 | int x, y; 131 | unsigned char *p; 132 | int sum1 = 0, sum2 = 0; 133 | 134 | p = frame + width * (width - 1); 135 | for(x = 1; x < width; x++) { 136 | sum1 += (p[x] & 1); 137 | } 138 | 139 | p = frame + width * 2 - 1; 140 | for(y = 1; y < width; y++) { 141 | sum2 += (*p & 1); 142 | p += width; 143 | } 144 | 145 | return (sum1 <= sum2)?(sum1 * 16 + sum2):(sum2 * 16 + sum1); 146 | } 147 | 148 | unsigned char *MMask_mask(int version, unsigned char *frame, QRecLevel level) 149 | { 150 | int i; 151 | unsigned char *mask, *bestMask; 152 | int maxScore = 0; 153 | int score; 154 | int width; 155 | 156 | width = MQRspec_getWidth(version); 157 | 158 | mask = (unsigned char *)malloc((size_t)(width * width)); 159 | if(mask == NULL) return NULL; 160 | bestMask = NULL; 161 | 162 | for(i = 0; i < maskNum; i++) { 163 | score = 0; 164 | maskMakers[i](width, frame, mask); 165 | MMask_writeFormatInformation(version, width, mask, i, level); 166 | score = MMask_evaluateSymbol(width, mask); 167 | if(score > maxScore) { 168 | maxScore = score; 169 | free(bestMask); 170 | bestMask = mask; 171 | mask = (unsigned char *)malloc((size_t)(width * width)); 172 | if(mask == NULL) break; 173 | } 174 | } 175 | free(mask); 176 | return bestMask; 177 | } 178 | -------------------------------------------------------------------------------- /mmask.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qrencode - QR Code encoder 3 | * 4 | * Masking for Micro QR Code. 5 | * Copyright (C) 2006-2017 Kentaro Fukuchi 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #ifndef MMASK_H 23 | #define MMASK_H 24 | 25 | extern unsigned char *MMask_makeMask(int version, unsigned char *frame, int mask, QRecLevel level); 26 | extern unsigned char *MMask_mask(int version, unsigned char *frame, QRecLevel level); 27 | 28 | #ifdef WITH_TESTS 29 | extern int MMask_evaluateSymbol(int width, unsigned char *frame); 30 | extern void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level); 31 | extern unsigned char *MMask_makeMaskedFrame(int width, unsigned char *frame, int mask); 32 | #endif 33 | 34 | #endif /* MMASK_H */ 35 | -------------------------------------------------------------------------------- /mqrspec.c: -------------------------------------------------------------------------------- 1 | /* 2 | * qrencode - QR Code encoder 3 | * 4 | * Micro QR Code specification in convenient format. 5 | * Copyright (C) 2006-2017 Kentaro Fukuchi 6 | * 7 | * The following data / specifications are taken from 8 | * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) 9 | * or 10 | * "Automatic identification and data capture techniques -- 11 | * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) 12 | * 13 | * This library is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Lesser General Public 15 | * License as published by the Free Software Foundation; either 16 | * version 2.1 of the License, or any later version. 17 | * 18 | * This library is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 | * Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public 24 | * License along with this library; if not, write to the Free Software 25 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 26 | */ 27 | 28 | #if HAVE_CONFIG_H 29 | # include "config.h" 30 | #endif 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include "mqrspec.h" 37 | 38 | /****************************************************************************** 39 | * Version and capacity 40 | *****************************************************************************/ 41 | 42 | typedef struct { 43 | int width; ///< Edge length of the symbol 44 | int ec[4]; ///< Number of ECC code (bytes) 45 | } MQRspec_Capacity; 46 | 47 | /** 48 | * Table of the capacity of symbols 49 | * See Table 1 (pp.106) and Table 8 (pp.113) of Appendix 1, JIS X0510:2004. 50 | */ 51 | static const MQRspec_Capacity mqrspecCapacity[MQRSPEC_VERSION_MAX + 1] = { 52 | { 0, {0, 0, 0, 0}}, 53 | { 11, {2, 0, 0, 0}}, 54 | { 13, {5, 6, 0, 0}}, 55 | { 15, {6, 8, 0, 0}}, 56 | { 17, {8, 10, 14, 0}} 57 | }; 58 | 59 | int MQRspec_getDataLengthBit(int version, QRecLevel level) 60 | { 61 | int w; 62 | int ecc; 63 | 64 | w = mqrspecCapacity[version].width - 1; 65 | ecc = mqrspecCapacity[version].ec[level]; 66 | if(ecc == 0) return 0; 67 | return w * w - 64 - ecc * 8; 68 | } 69 | 70 | int MQRspec_getDataLength(int version, QRecLevel level) 71 | { 72 | return (MQRspec_getDataLengthBit(version, level) + 4) / 8; 73 | } 74 | 75 | int MQRspec_getECCLength(int version, QRecLevel level) 76 | { 77 | return mqrspecCapacity[version].ec[level]; 78 | } 79 | 80 | int MQRspec_getWidth(int version) 81 | { 82 | return mqrspecCapacity[version].width; 83 | } 84 | 85 | /****************************************************************************** 86 | * Length indicator 87 | *****************************************************************************/ 88 | 89 | /** 90 | * See Table 3 (pp.107) of Appendix 1, JIS X0510:2004. 91 | */ 92 | static const int lengthTableBits[4][4] = { 93 | { 3, 4, 5, 6}, 94 | { 0, 3, 4, 5}, 95 | { 0, 0, 4, 5}, 96 | { 0, 0, 3, 4} 97 | }; 98 | 99 | int MQRspec_lengthIndicator(QRencodeMode mode, int version) 100 | { 101 | return lengthTableBits[mode][version - 1]; 102 | } 103 | 104 | int MQRspec_maximumWords(QRencodeMode mode, int version) 105 | { 106 | int bits; 107 | int words; 108 | 109 | bits = lengthTableBits[mode][version - 1]; 110 | words = (1 << bits) - 1; 111 | if(mode == QR_MODE_KANJI) { 112 | words *= 2; // the number of bytes is required 113 | } 114 | 115 | return words; 116 | } 117 | 118 | /****************************************************************************** 119 | * Format information 120 | *****************************************************************************/ 121 | 122 | /* See calcFormatInfo in tests/test_mqrspec.c */ 123 | static const unsigned int formatInfo[4][8] = { 124 | {0x4445, 0x55ae, 0x6793, 0x7678, 0x06de, 0x1735, 0x2508, 0x34e3}, 125 | {0x4172, 0x5099, 0x62a4, 0x734f, 0x03e9, 0x1202, 0x203f, 0x31d4}, 126 | {0x4e2b, 0x5fc0, 0x6dfd, 0x7c16, 0x0cb0, 0x1d5b, 0x2f66, 0x3e8d}, 127 | {0x4b1c, 0x5af7, 0x68ca, 0x7921, 0x0987, 0x186c, 0x2a51, 0x3bba} 128 | }; 129 | 130 | /* See Table 10 of Appendix 1. (pp.115) */ 131 | static const int typeTable[MQRSPEC_VERSION_MAX + 1][3] = { 132 | {-1, -1, -1}, 133 | { 0, -1, -1}, 134 | { 1, 2, -1}, 135 | { 3, 4, -1}, 136 | { 5, 6, 7} 137 | }; 138 | 139 | unsigned int MQRspec_getFormatInfo(int mask, int version, QRecLevel level) 140 | { 141 | int type; 142 | 143 | if(mask < 0 || mask > 3) return 0; 144 | if(version <= 0 || version > MQRSPEC_VERSION_MAX) return 0; 145 | if(level == QR_ECLEVEL_H) return 0; 146 | type = typeTable[version][level]; 147 | if(type < 0) return 0; 148 | 149 | return formatInfo[mask][type]; 150 | } 151 | 152 | /****************************************************************************** 153 | * Frame 154 | *****************************************************************************/ 155 | 156 | /** 157 | * Put a finder pattern. 158 | * @param frame 159 | * @param width 160 | * @param ox,oy upper-left coordinate of the pattern 161 | */ 162 | static void putFinderPattern(unsigned char *frame, int width, int ox, int oy) 163 | { 164 | static const unsigned char finder[] = { 165 | 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 166 | 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 167 | 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 168 | 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 169 | 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 170 | 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 171 | 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 172 | }; 173 | int x, y; 174 | const unsigned char *s; 175 | 176 | frame += oy * width + ox; 177 | s = finder; 178 | for(y = 0; y < 7; y++) { 179 | for(x = 0; x < 7; x++) { 180 | frame[x] = s[x]; 181 | } 182 | frame += width; 183 | s += 7; 184 | } 185 | } 186 | 187 | static unsigned char *MQRspec_createFrame(int version) 188 | { 189 | unsigned char *frame, *p, *q; 190 | int width; 191 | int x, y; 192 | 193 | width = mqrspecCapacity[version].width; 194 | frame = (unsigned char *)malloc((size_t)(width * width)); 195 | if(frame == NULL) return NULL; 196 | 197 | memset(frame, 0, (size_t)(width * width)); 198 | /* Finder pattern */ 199 | putFinderPattern(frame, width, 0, 0); 200 | /* Separator */ 201 | p = frame; 202 | for(y = 0; y < 7; y++) { 203 | p[7] = 0xc0; 204 | p += width; 205 | } 206 | memset(frame + width * 7, 0xc0, 8); 207 | /* Mask format information area */ 208 | memset(frame + width * 8 + 1, 0x84, 8); 209 | p = frame + width + 8; 210 | for(y = 0; y < 7; y++) { 211 | *p = 0x84; 212 | p += width; 213 | } 214 | /* Timing pattern */ 215 | p = frame + 8; 216 | q = frame + width * 8; 217 | for(x = 1; x < width-7; x++) { 218 | *p = 0x90 | (x & 1); 219 | *q = 0x90 | (x & 1); 220 | p++; 221 | q += width; 222 | } 223 | 224 | return frame; 225 | } 226 | 227 | unsigned char *MQRspec_newFrame(int version) 228 | { 229 | if(version < 1 || version > MQRSPEC_VERSION_MAX) return NULL; 230 | 231 | return MQRspec_createFrame(version); 232 | } 233 | -------------------------------------------------------------------------------- /mqrspec.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qrencode - QR Code encoder 3 | * 4 | * Micro QR Code specification in convenient format. 5 | * Copyright (C) 2006-2017 Kentaro Fukuchi 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #ifndef MQRSPEC_H 23 | #define MQRSPEC_H 24 | 25 | #include "qrencode.h" 26 | 27 | /****************************************************************************** 28 | * Version and capacity 29 | *****************************************************************************/ 30 | 31 | /** 32 | * Maximum width of a symbol 33 | */ 34 | #define MQRSPEC_WIDTH_MAX 17 35 | 36 | /** 37 | * Return maximum data code length (bits) for the version. 38 | * @param version version of the symbol 39 | * @param level error correction level 40 | * @return maximum size (bits) 41 | */ 42 | extern int MQRspec_getDataLengthBit(int version, QRecLevel level); 43 | 44 | /** 45 | * Return maximum data code length (bytes) for the version. 46 | * @param version version of the symbol 47 | * @param level error correction level 48 | * @return maximum size (bytes) 49 | */ 50 | extern int MQRspec_getDataLength(int version, QRecLevel level); 51 | 52 | /** 53 | * Return maximum error correction code length (bytes) for the version. 54 | * @param version version of the symbol 55 | * @param level error correction level 56 | * @return ECC size (bytes) 57 | */ 58 | extern int MQRspec_getECCLength(int version, QRecLevel level); 59 | 60 | /** 61 | * Return a version number that satisfies the input code length. 62 | * @param size input code length (byte) 63 | * @param level error correction level 64 | * @return version number 65 | */ 66 | extern int MQRspec_getMinimumVersion(int size, QRecLevel level); 67 | 68 | /** 69 | * Return the width of the symbol for the version. 70 | * @param version version of the symbol 71 | * @return width 72 | */ 73 | extern int MQRspec_getWidth(int version); 74 | 75 | /** 76 | * Return the numer of remainder bits. 77 | * @param version version of the symbol 78 | * @return number of remainder bits 79 | */ 80 | extern int MQRspec_getRemainder(int version); 81 | 82 | /****************************************************************************** 83 | * Length indicator 84 | *****************************************************************************/ 85 | 86 | /** 87 | * Return the size of length indicator for the mode and version. 88 | * @param mode encode mode 89 | * @param version vesion of the symbol 90 | * @return the size of the appropriate length indicator (bits). 91 | */ 92 | extern int MQRspec_lengthIndicator(QRencodeMode mode, int version); 93 | 94 | /** 95 | * Return the maximum length for the mode and version. 96 | * @param mode encode mode 97 | * @param version vesion of the symbol 98 | * @return the maximum length (bytes) 99 | */ 100 | extern int MQRspec_maximumWords(QRencodeMode mode, int version); 101 | 102 | /****************************************************************************** 103 | * Version information pattern 104 | *****************************************************************************/ 105 | 106 | /** 107 | * Return BCH encoded version information pattern that is used for the symbol 108 | * of version 7 or greater. Use lower 18 bits. 109 | * @param version vesion of the symbol 110 | * @return BCH encoded version information pattern 111 | */ 112 | extern unsigned int MQRspec_getVersionPattern(int version); 113 | 114 | /****************************************************************************** 115 | * Format information 116 | *****************************************************************************/ 117 | 118 | /** 119 | * Return BCH encoded format information pattern. 120 | * @param mask mask number 121 | * @param version version of the symbol 122 | * @param level error correction level 123 | * @return BCH encoded format information pattern 124 | */ 125 | extern unsigned int MQRspec_getFormatInfo(int mask, int version, QRecLevel level); 126 | 127 | /****************************************************************************** 128 | * Frame 129 | *****************************************************************************/ 130 | 131 | /** 132 | * Return a copy of initialized frame. 133 | * @param version version of the symbol 134 | * @return Array of unsigned char. You can free it by free(). 135 | */ 136 | extern unsigned char *MQRspec_newFrame(int version); 137 | 138 | /****************************************************************************** 139 | * Mode indicator 140 | *****************************************************************************/ 141 | 142 | /** 143 | * Mode indicator. See Table 2 in Appendix 1 of JIS X0510:2004, pp.107. 144 | */ 145 | #define MQRSPEC_MODEID_NUM 0 146 | #define MQRSPEC_MODEID_AN 1 147 | #define MQRSPEC_MODEID_8 2 148 | #define MQRSPEC_MODEID_KANJI 3 149 | 150 | #endif /* MQRSPEC_H */ 151 | -------------------------------------------------------------------------------- /qrencode.1.in: -------------------------------------------------------------------------------- 1 | .TH QRENCODE 1 "Aug. 28, 2020" "qrencode @VERSION@" 2 | .SH NAME 3 | qrencode \- Encode input data in a QR Code and save as a PNG or EPS image. 4 | .SH SYNOPSIS 5 | .B "qrencode" 6 | [-o FILENAME] 7 | [OPTION]... 8 | [STRING] 9 | 10 | .SH DESCRIPTION 11 | Libqrencode is a library for encoding data in a QR Code symbol, a kind of 2D 12 | symbology that can be scanned by handy terminals such as a mobile phone with 13 | CCD. The capacity of QR Code is up to 7000 digits or 4000 characters, and has 14 | high robustness. 15 | 16 | Qrencode is a utility software using libqrencode to encode string data in 17 | a QR Code and save as a PNG or EPS image. 18 | 19 | .SH OPTIONS 20 | .TP 21 | .B \-h, \-\-help 22 | display help message. 23 | .TP 24 | .B \-o FILENAME, \-\-output=FILENAME 25 | write image to FILENAME. If '\-' is specified, the result will be output to standard output. If \-S is given, structured symbols are written to FILENAME-01.png, FILENAME-02.png, ... (suffix is removed from FILENAME, if specified) 26 | .TP 27 | .B \-r FILENAME, \-\-read\-from=FILENAME 28 | read input data from FILENAME. 29 | .TP 30 | .B \-s NUMBER, \-\-size=NUMBER 31 | specify the size of dot (pixel). (default=3) 32 | .TP 33 | .B \-l {LMQH}, \-\-level={LMQH} 34 | specify error correction level from L (lowest) to H (highest). (default=L) 35 | .TP 36 | .B \-v NUMBER, \-\-symversion=NUMBER 37 | specify the minimum version of the symbol. See SYMBOL VERSIONS for more information. (default=auto) 38 | .TP 39 | .B \-m NUMBER, \-\-margin=NUMBER 40 | specify the width of margin. (default=4) 41 | .TP 42 | .B \-d NUMBER, \-\-dpi=NUMBER 43 | specify the DPI of the generated PNG. (default=72) 44 | .TP 45 | .PD 0 46 | .B \-t {PNG,PNG32,EPS,SVG,XPM,ANSI,ANSI256,ASCII,ASCIIi,UTF8,UTF8i,ANSIUTF8,ANSIUTF8i,ANSI256UTF8} 47 | .TP 48 | .PD 49 | .B \-\-type={PNG,PNG32,EPS,SVG,XPM,ANSI,ANSI256,ASCII,ASCIIi,UTF8,UTF8i,ANSIUTF8,ANSIUTF8i,ANSI256UTF8} 50 | specify the type of the generated image. (default=PNG) 51 | .TP 52 | .B \-S, \-\-structured 53 | make structured symbols. Version number must be specified with '-v'. 54 | .TP 55 | .B \-k, \-\-kanji 56 | assume that the input text contains kanji (shift-jis). 57 | .TP 58 | .B \-c, \-\-casesensitive 59 | encode lower-case alphabet characters in 8-bit mode. (default) 60 | .TP 61 | .B \-i, \-\-ignorecase 62 | ignore case distinctions and use only upper-case characters. 63 | .TP 64 | .B \-8, \-\-8bit 65 | encode entire data in 8-bit mode. \-k, \-c and \-i will be ignored. 66 | .TP 67 | .B \-M, \-\-micro 68 | encode in a Micro QR Code. See MICRO QR CODE for more information. 69 | .TP 70 | .B \-\-rle 71 | enable run-length encoding for SVG. 72 | .TP 73 | .B \-\-svg-path 74 | use single path to draw modules for SVG. 75 | .TP 76 | .B \-\-inline 77 | only useful for SVG output, generates an SVG without the XML tag. 78 | .TP 79 | .PD 0 80 | .B \-\-foreground=RRGGBB[AA] 81 | .TP 82 | .PD 83 | .B \-\-background=RRGGBB[AA] 84 | specify foreground/background color in hexadecimal notation. 85 | 6-digit (RGB) or 8-digit (RGBA) form are supported. 86 | Color output support available only in PNG, EPS and SVG. 87 | .TP 88 | .B \-\-strict\-version 89 | disable automatic version number adjustment. If the input data is 90 | too large for the specified version, the program exits with the 91 | code of 1. 92 | .TP 93 | .B \-V, \-\-version 94 | display the version number and copyrights of the qrencode. 95 | .TP 96 | .B \-\-verbose 97 | display verbose information to stderr. 98 | .TP 99 | .B [STRING] 100 | input data. If it is not specified, data will be taken from standard input. 101 | 102 | .SH SYMBOL VERSIONS 103 | The symbol versions of QR Code range from Version 1 to Version 40. 104 | Each version has a different module configuration or number of modules, 105 | ranging from Version 1 (21 x 21 modules) up to Version 40 (177 x 177 modules). 106 | Each higher version number comprises 4 additional modules per side by default. 107 | See http://www.qrcode.com/en/about/version.html for a detailed version list. 108 | 109 | .SH MICRO QR CODE 110 | With Micro QR Code, You can embed data in a smaller area than with QR Code, 111 | but the data capacity is strongly limited. The symbol versions range from 112 | Version 1 to 4. 113 | 114 | .SH EXAMPLES 115 | .TP 116 | .B qrencode \-l L \-v 1 \-o output.png 'Hello, world!' 117 | encode into a symbol version 1, level L. 118 | .TP 119 | .B qrencode \-iSv 1 \-\-output=output.png 120 | read standard input and encode it into a structured-appended symbols in 121 | case-insensitive mode. 122 | .TP 123 | .B qrencode \-S \-v 40 \-l L \-r bigfile.txt \-o output.png 124 | read input data from bigfile.txt and encode into a symbol version 40, level L. 125 | 126 | .SH AUTHOR 127 | Written by Kentaro Fukuchi. 128 | 129 | .SH RESOURCES 130 | .TP 131 | Main Web Site: https://fukuchi.org/works/qrencode/ 132 | .TP 133 | Source code repository: https://github.com/fukuchi/libqrencode/ 134 | 135 | .SH COPYRIGHT 136 | Copyright (C) 2006-2018 Kentaro Fukuchi. 137 | -------------------------------------------------------------------------------- /qrencode_inner.h: -------------------------------------------------------------------------------- 1 | /** 2 | * qrencode - QR Code encoder 3 | * 4 | * Header for test use 5 | * Copyright (C) 2006-2017 Kentaro Fukuchi 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #ifndef QRENCODE_INNER_H 23 | #define QRENCODE_INNER_H 24 | 25 | /** 26 | * This header file includes definitions for test use. 27 | */ 28 | 29 | /****************************************************************************** 30 | * Raw code 31 | *****************************************************************************/ 32 | 33 | typedef struct { 34 | int dataLength; 35 | int eccLength; 36 | unsigned char *data; 37 | unsigned char *ecc; 38 | } RSblock; 39 | 40 | typedef struct { 41 | int version; 42 | int dataLength; 43 | int eccLength; 44 | unsigned char *datacode; 45 | unsigned char *ecccode; 46 | int b1; 47 | int blocks; 48 | RSblock *rsblock; 49 | int count; 50 | } QRRawCode; 51 | 52 | extern QRRawCode *QRraw_new(QRinput *input); 53 | extern unsigned char QRraw_getCode(QRRawCode *raw); 54 | extern void QRraw_free(QRRawCode *raw); 55 | 56 | /****************************************************************************** 57 | * Raw code for Micro QR Code 58 | *****************************************************************************/ 59 | 60 | typedef struct { 61 | int version; 62 | int dataLength; 63 | int eccLength; 64 | unsigned char *datacode; 65 | unsigned char *ecccode; 66 | RSblock *rsblock; 67 | int oddbits; 68 | int count; 69 | } MQRRawCode; 70 | 71 | extern MQRRawCode *MQRraw_new(QRinput *input); 72 | extern unsigned char MQRraw_getCode(MQRRawCode *raw); 73 | extern void MQRraw_free(MQRRawCode *raw); 74 | 75 | /****************************************************************************** 76 | * Frame filling 77 | *****************************************************************************/ 78 | extern unsigned char *FrameFiller_test(int version); 79 | extern unsigned char *FrameFiller_testMQR(int version); 80 | 81 | /****************************************************************************** 82 | * QR-code encoding 83 | *****************************************************************************/ 84 | extern QRcode *QRcode_encodeMask(QRinput *input, int mask); 85 | extern QRcode *QRcode_encodeMaskMQR(QRinput *input, int mask); 86 | extern QRcode *QRcode_new(int version, int width, unsigned char *data); 87 | 88 | #endif /* QRENCODE_INNER_H */ 89 | -------------------------------------------------------------------------------- /qrinput.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qrencode - QR Code encoder 3 | * 4 | * Input data chunk class 5 | * Copyright (C) 2006-2017 Kentaro Fukuchi 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #ifndef QRINPUT_H 23 | #define QRINPUT_H 24 | 25 | #include "qrencode.h" 26 | #include "bitstream.h" 27 | 28 | int QRinput_isSplittableMode(QRencodeMode mode); 29 | 30 | /****************************************************************************** 31 | * Entry of input data 32 | *****************************************************************************/ 33 | typedef struct _QRinput_List QRinput_List; 34 | 35 | struct _QRinput_List { 36 | QRencodeMode mode; 37 | int size; ///< Size of data chunk (byte). 38 | unsigned char *data; ///< Data chunk. 39 | BitStream *bstream; 40 | QRinput_List *next; 41 | }; 42 | 43 | /****************************************************************************** 44 | * Input Data 45 | *****************************************************************************/ 46 | struct _QRinput { 47 | int version; 48 | QRecLevel level; 49 | QRinput_List *head; 50 | QRinput_List *tail; 51 | int mqr; 52 | int fnc1; 53 | unsigned char appid; 54 | }; 55 | 56 | /****************************************************************************** 57 | * Structured append input data 58 | *****************************************************************************/ 59 | typedef struct _QRinput_InputList QRinput_InputList; 60 | 61 | struct _QRinput_InputList { 62 | QRinput *input; 63 | QRinput_InputList *next; 64 | }; 65 | 66 | struct _QRinput_Struct { 67 | int size; ///< number of structured symbols 68 | int parity; 69 | QRinput_InputList *head; 70 | QRinput_InputList *tail; 71 | }; 72 | 73 | /** 74 | * Pack all bit streams padding bits into a byte array. 75 | * @param input input data. 76 | * @return padded merged byte stream 77 | */ 78 | extern unsigned char *QRinput_getByteStream(QRinput *input); 79 | 80 | 81 | extern int QRinput_estimateBitsModeNum(int size); 82 | extern int QRinput_estimateBitsModeAn(int size); 83 | extern int QRinput_estimateBitsMode8(int size); 84 | extern int QRinput_estimateBitsModeKanji(int size); 85 | 86 | extern QRinput *QRinput_dup(QRinput *input); 87 | 88 | extern const signed char QRinput_anTable[128]; 89 | 90 | /** 91 | * Look up the alphabet-numeric convesion table (see JIS X0510:2004, pp.19). 92 | * @param __c__ character 93 | * @return value 94 | */ 95 | #define QRinput_lookAnTable(__c__) \ 96 | ((__c__ & 0x80)?-1:QRinput_anTable[(int)__c__]) 97 | 98 | /** 99 | * Length of a standard mode indicator in bits. 100 | */ 101 | 102 | #define MODE_INDICATOR_SIZE 4 103 | 104 | /** 105 | * Length of a segment of structured-append header. 106 | */ 107 | #define STRUCTURE_HEADER_SIZE 20 108 | 109 | /** 110 | * Maximum number of symbols in a set of structured-appended symbols. 111 | */ 112 | #define MAX_STRUCTURED_SYMBOLS 16 113 | 114 | #ifdef WITH_TESTS 115 | extern int QRinput_mergeBitStream(QRinput *input, BitStream *bstream); 116 | extern int QRinput_getBitStream(QRinput *input, BitStream *bstream); 117 | extern int QRinput_estimateBitStreamSize(QRinput *input, int version); 118 | extern int QRinput_splitEntry(QRinput_List *entry, int bytes); 119 | extern int QRinput_estimateVersion(QRinput *input); 120 | extern int QRinput_lengthOfCode(QRencodeMode mode, int version, int bits); 121 | extern int QRinput_insertStructuredAppendHeader(QRinput *input, int size, int index, unsigned char parity); 122 | #endif 123 | 124 | #endif /* QRINPUT_H */ 125 | -------------------------------------------------------------------------------- /qrspec.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qrencode - QR Code encoder 3 | * 4 | * QR Code specification in convenient format. 5 | * Copyright (C) 2006-2017 Kentaro Fukuchi 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #ifndef QRSPEC_H 23 | #define QRSPEC_H 24 | 25 | #include "qrencode.h" 26 | 27 | /****************************************************************************** 28 | * Version and capacity 29 | *****************************************************************************/ 30 | 31 | /** 32 | * Maximum width of a symbol 33 | */ 34 | #define QRSPEC_WIDTH_MAX 177 35 | 36 | /** 37 | * Return maximum data code length (bytes) for the version. 38 | * @param version version of the symbol 39 | * @param level error correction level 40 | * @return maximum size (bytes) 41 | */ 42 | extern int QRspec_getDataLength(int version, QRecLevel level); 43 | 44 | /** 45 | * Return maximum error correction code length (bytes) for the version. 46 | * @param version version of the symbol 47 | * @param level error correction level 48 | * @return ECC size (bytes) 49 | */ 50 | extern int QRspec_getECCLength(int version, QRecLevel level); 51 | 52 | /** 53 | * Return a version number that satisfies the input code length. 54 | * @param size input code length (byte) 55 | * @param level error correction level 56 | * @return version number 57 | */ 58 | extern int QRspec_getMinimumVersion(int size, QRecLevel level); 59 | 60 | /** 61 | * Return the width of the symbol for the version. 62 | * @param version vesion of the symbol 63 | * @return width of the symbol 64 | */ 65 | extern int QRspec_getWidth(int version); 66 | 67 | /** 68 | * Return the numer of remainder bits. 69 | * @param version vesion of the symbol 70 | * @return number of remainder bits 71 | */ 72 | extern int QRspec_getRemainder(int version); 73 | 74 | /****************************************************************************** 75 | * Length indicator 76 | *****************************************************************************/ 77 | 78 | /** 79 | * Return the size of length indicator for the mode and version. 80 | * @param mode encode mode 81 | * @param version vesion of the symbol 82 | * @return the size of the appropriate length indicator (bits). 83 | */ 84 | extern int QRspec_lengthIndicator(QRencodeMode mode, int version); 85 | 86 | /** 87 | * Return the maximum length for the mode and version. 88 | * @param mode encode mode 89 | * @param version vesion of the symbol 90 | * @return the maximum length (bytes) 91 | */ 92 | extern int QRspec_maximumWords(QRencodeMode mode, int version); 93 | 94 | /****************************************************************************** 95 | * Error correction code 96 | *****************************************************************************/ 97 | 98 | /** 99 | * Return an array of ECC specification. 100 | * @param version version of the symbol 101 | * @param level error correction level 102 | * @param spec an array of ECC specification contains as following: 103 | * {# of type1 blocks, # of data code, # of ecc code, 104 | * # of type2 blocks, # of data code} 105 | */ 106 | void QRspec_getEccSpec(int version, QRecLevel level, int spec[5]); 107 | 108 | #define QRspec_rsBlockNum(__spec__) (__spec__[0] + __spec__[3]) 109 | #define QRspec_rsBlockNum1(__spec__) (__spec__[0]) 110 | #define QRspec_rsDataCodes1(__spec__) (__spec__[1]) 111 | #define QRspec_rsEccCodes1(__spec__) (__spec__[2]) 112 | #define QRspec_rsBlockNum2(__spec__) (__spec__[3]) 113 | #define QRspec_rsDataCodes2(__spec__) (__spec__[4]) 114 | #define QRspec_rsEccCodes2(__spec__) (__spec__[2]) 115 | 116 | #define QRspec_rsDataLength(__spec__) \ 117 | ((QRspec_rsBlockNum1(__spec__) * QRspec_rsDataCodes1(__spec__)) + \ 118 | (QRspec_rsBlockNum2(__spec__) * QRspec_rsDataCodes2(__spec__))) 119 | #define QRspec_rsEccLength(__spec__) \ 120 | (QRspec_rsBlockNum(__spec__) * QRspec_rsEccCodes1(__spec__)) 121 | 122 | /****************************************************************************** 123 | * Version information pattern 124 | *****************************************************************************/ 125 | 126 | /** 127 | * Return BCH encoded version information pattern that is used for the symbol 128 | * of version 7 or greater. Use lower 18 bits. 129 | * @param version version of the symbol 130 | * @return BCH encoded version information pattern 131 | */ 132 | extern unsigned int QRspec_getVersionPattern(int version); 133 | 134 | /****************************************************************************** 135 | * Format information 136 | *****************************************************************************/ 137 | 138 | /** 139 | * Return BCH encoded format information pattern. 140 | * @param mask mask number 141 | * @param level error correction level 142 | * @return BCH encoded format information pattern 143 | */ 144 | extern unsigned int QRspec_getFormatInfo(int mask, QRecLevel level); 145 | 146 | /****************************************************************************** 147 | * Frame 148 | *****************************************************************************/ 149 | 150 | /** 151 | * Return a copy of initialized frame. 152 | * @param version version of the symbol 153 | * @return Array of unsigned char. You can free it by free(). 154 | */ 155 | extern unsigned char *QRspec_newFrame(int version); 156 | 157 | /****************************************************************************** 158 | * Mode indicator 159 | *****************************************************************************/ 160 | 161 | /** 162 | * Mode indicator. See Table 2 of JIS X0510:2004, pp.16. 163 | */ 164 | #define QRSPEC_MODEID_ECI 7 165 | #define QRSPEC_MODEID_NUM 1 166 | #define QRSPEC_MODEID_AN 2 167 | #define QRSPEC_MODEID_8 4 168 | #define QRSPEC_MODEID_KANJI 8 169 | #define QRSPEC_MODEID_FNC1FIRST 5 170 | #define QRSPEC_MODEID_FNC1SECOND 9 171 | #define QRSPEC_MODEID_STRUCTURE 3 172 | #define QRSPEC_MODEID_TERMINATOR 0 173 | 174 | #endif /* QRSPEC_H */ 175 | -------------------------------------------------------------------------------- /rsecc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * qrencode - QR Code encoder 3 | * 4 | * Reed solomon error correction code encoder specialized for QR code. 5 | * This code is rewritten by Kentaro Fukuchi, referring to the FEC library 6 | * developed by Phil Karn (KA9Q). 7 | * 8 | * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q 9 | * Copyright (C) 2014-2017 Kentaro Fukuchi 10 | * 11 | * This library is free software; you can redistribute it and/or 12 | * modify it under the terms of the GNU Lesser General Public 13 | * License as published by the Free Software Foundation; either 14 | * version 2.1 of the License, or any later version. 15 | * 16 | * This library is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | * Lesser General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU Lesser General Public 22 | * License along with this library; if not, write to the Free Software 23 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | */ 25 | 26 | #if HAVE_CONFIG_H 27 | # include "config.h" 28 | #endif 29 | #include 30 | #include 31 | #if HAVE_LIBPTHREAD 32 | #include 33 | #endif 34 | 35 | #include "rsecc.h" 36 | 37 | #if HAVE_LIBPTHREAD 38 | static pthread_mutex_t RSECC_mutex = PTHREAD_MUTEX_INITIALIZER; 39 | #endif 40 | 41 | static int initialized = 0; 42 | 43 | #define SYMBOL_SIZE (8) 44 | #define symbols ((1U << SYMBOL_SIZE) - 1) 45 | static const unsigned int proot = 0x11d; /* stands for x^8+x^4+x^3+x^2+1 (see pp.37 of JIS X0510:2004) */ 46 | 47 | /* min/max codeword length of ECC, calculated from the specification. */ 48 | #define min_length (2) 49 | #define max_length (30) 50 | #define max_generatorSize (max_length) 51 | 52 | static unsigned char alpha[symbols + 1]; 53 | static unsigned char aindex[symbols + 1]; 54 | static unsigned char generator[max_length - min_length + 1][max_generatorSize + 1]; 55 | static unsigned char generatorInitialized[max_length - min_length + 1]; 56 | 57 | static void RSECC_initLookupTable(void) 58 | { 59 | unsigned int i, b; 60 | 61 | alpha[symbols] = 0; 62 | aindex[0] = symbols; 63 | 64 | b = 1; 65 | for(i = 0; i < symbols; i++) { 66 | alpha[i] = b; 67 | aindex[b] = i; 68 | b <<= 1; 69 | if(b & (symbols + 1)) { 70 | b ^= proot; 71 | } 72 | b &= symbols; 73 | } 74 | } 75 | 76 | static void RSECC_init(void) 77 | { 78 | RSECC_initLookupTable(); 79 | memset(generatorInitialized, 0, (max_length - min_length + 1)); 80 | initialized = 1; 81 | } 82 | 83 | static void generator_init(size_t length) 84 | { 85 | size_t i, j; 86 | int g[max_generatorSize + 1]; 87 | 88 | g[0] = 1; 89 | for(i = 0; i < length; i++) { 90 | g[i + 1] = 1; 91 | /* Because g[0] never be zero, skipped some conditional checks. */ 92 | for(j = i; j > 0; j--) { 93 | g[j] = g[j - 1] ^ alpha[(aindex[g[j]] + i) % symbols]; 94 | } 95 | g[0] = alpha[(aindex[g[0]] + i) % symbols]; 96 | } 97 | 98 | for(i = 0; i <= length; i++) { 99 | generator[length - min_length][i] = aindex[g[i]]; 100 | } 101 | 102 | generatorInitialized[length - min_length] = 1; 103 | } 104 | 105 | int RSECC_encode(size_t data_length, size_t ecc_length, const unsigned char *data, unsigned char *ecc) 106 | { 107 | size_t i, j; 108 | unsigned char feedback; 109 | unsigned char *gen; 110 | 111 | #if HAVE_LIBPTHREAD 112 | pthread_mutex_lock(&RSECC_mutex); 113 | #endif 114 | if(!initialized) { 115 | RSECC_init(); 116 | } 117 | #if HAVE_LIBPTHREAD 118 | pthread_mutex_unlock(&RSECC_mutex); 119 | #endif 120 | 121 | if(ecc_length > max_length) return -1; 122 | 123 | memset(ecc, 0, ecc_length); 124 | #if HAVE_LIBPTHREAD 125 | pthread_mutex_lock(&RSECC_mutex); 126 | #endif 127 | if(!generatorInitialized[ecc_length - min_length]) generator_init(ecc_length); 128 | #if HAVE_LIBPTHREAD 129 | pthread_mutex_unlock(&RSECC_mutex); 130 | #endif 131 | gen = generator[ecc_length - min_length]; 132 | 133 | for(i = 0; i < data_length; i++) { 134 | feedback = aindex[data[i] ^ ecc[0]]; 135 | if(feedback != symbols) { 136 | for(j = 1; j < ecc_length; j++) { 137 | ecc[j] ^= alpha[(unsigned int)(feedback + gen[ecc_length - j]) % symbols]; 138 | } 139 | } 140 | memmove(&ecc[0], &ecc[1], ecc_length - 1); 141 | if(feedback != symbols) { 142 | ecc[ecc_length - 1] = alpha[(unsigned int)(feedback + gen[0]) % symbols]; 143 | } else { 144 | ecc[ecc_length - 1] = 0; 145 | } 146 | } 147 | 148 | return 0; 149 | } 150 | -------------------------------------------------------------------------------- /rsecc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qrencode - QR Code encoder 3 | * 4 | * Reed solomon error correction code encoder specialized for QR code. 5 | * This code is rewritten by Kentaro Fukuchi, referring to the FEC library 6 | * developed by Phil Karn (KA9Q). 7 | * 8 | * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q 9 | * Copyright (C) 2014-2017 Kentaro Fukuchi 10 | * 11 | * This library is free software; you can redistribute it and/or 12 | * modify it under the terms of the GNU Lesser General Public 13 | * License as published by the Free Software Foundation; either 14 | * version 2.1 of the License, or any later version. 15 | * 16 | * This library is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | * Lesser General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU Lesser General Public 22 | * License along with this library; if not, write to the Free Software 23 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | */ 25 | 26 | #ifndef RSECC_H 27 | #define RSECC_H 28 | 29 | extern int RSECC_encode(size_t data_length, size_t ecc_length, const unsigned char *data, unsigned char *ecc); 30 | 31 | #endif /* RSECC_H */ 32 | -------------------------------------------------------------------------------- /split.c: -------------------------------------------------------------------------------- 1 | /* 2 | * qrencode - QR Code encoder 3 | * 4 | * Input data splitter. 5 | * Copyright (C) 2006-2017 Kentaro Fukuchi 6 | * 7 | * The following data / specifications are taken from 8 | * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) 9 | * or 10 | * "Automatic identification and data capture techniques -- 11 | * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) 12 | * 13 | * This library is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Lesser General Public 15 | * License as published by the Free Software Foundation; either 16 | * version 2.1 of the License, or any later version. 17 | * 18 | * This library is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 | * Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public 24 | * License along with this library; if not, write to the Free Software 25 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 26 | */ 27 | 28 | #if HAVE_CONFIG_H 29 | # include "config.h" 30 | #endif 31 | #include 32 | #include 33 | #include 34 | #include "qrencode.h" 35 | #include "qrinput.h" 36 | #include "qrspec.h" 37 | #include "split.h" 38 | 39 | #define isdigit(__c__) ((unsigned char)((signed char)(__c__) - '0') < 10) 40 | #define isalnum(__c__) (QRinput_lookAnTable(__c__) >= 0) 41 | 42 | #if !HAVE_STRDUP 43 | #undef strdup 44 | char *strdup(const char *s) 45 | { 46 | size_t len = strlen(s) + 1; 47 | void *newstring = malloc(len); 48 | if(newstring == NULL) return NULL; 49 | return (char *)memcpy(newstring, s, len); 50 | } 51 | #endif 52 | 53 | static QRencodeMode Split_identifyMode(const char *string, QRencodeMode hint) 54 | { 55 | unsigned char c, d; 56 | unsigned int word; 57 | 58 | c = (unsigned char)string[0]; 59 | 60 | if(c == '\0') return QR_MODE_NUL; 61 | if(isdigit(c)) { 62 | return QR_MODE_NUM; 63 | } else if(isalnum(c)) { 64 | return QR_MODE_AN; 65 | } else if(hint == QR_MODE_KANJI) { 66 | d = (unsigned char)string[1]; 67 | if(d != '\0') { 68 | word = ((unsigned int)c << 8) | d; 69 | if((word >= 0x8140 && word <= 0x9ffc) || (word >= 0xe040 && word <= 0xebbf)) { 70 | return QR_MODE_KANJI; 71 | } 72 | } 73 | } 74 | 75 | return QR_MODE_8; 76 | } 77 | 78 | static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint); 79 | static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint); 80 | 81 | static int Split_eatNum(const char *string, QRinput *input,QRencodeMode hint) 82 | { 83 | const char *p; 84 | int ret; 85 | int run; 86 | int dif; 87 | int ln; 88 | QRencodeMode mode; 89 | 90 | ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version); 91 | 92 | p = string; 93 | while(isdigit(*p)) { 94 | p++; 95 | } 96 | run = (int)(p - string); 97 | mode = Split_identifyMode(p, hint); 98 | if(mode == QR_MODE_8) { 99 | dif = QRinput_estimateBitsModeNum(run) + 4 + ln 100 | + QRinput_estimateBitsMode8(1) /* + 4 + l8 */ 101 | - QRinput_estimateBitsMode8(run + 1) /* - 4 - l8 */; 102 | if(dif > 0) { 103 | return Split_eat8(string, input, hint); 104 | } 105 | } 106 | if(mode == QR_MODE_AN) { 107 | dif = QRinput_estimateBitsModeNum(run) + 4 + ln 108 | + QRinput_estimateBitsModeAn(1) /* + 4 + la */ 109 | - QRinput_estimateBitsModeAn(run + 1) /* - 4 - la */; 110 | if(dif > 0) { 111 | return Split_eatAn(string, input, hint); 112 | } 113 | } 114 | 115 | ret = QRinput_append(input, QR_MODE_NUM, run, (unsigned char *)string); 116 | if(ret < 0) return -1; 117 | 118 | return run; 119 | } 120 | 121 | static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint) 122 | { 123 | const char *p, *q; 124 | int ret; 125 | int run; 126 | int dif; 127 | int la, ln; 128 | 129 | la = QRspec_lengthIndicator(QR_MODE_AN, input->version); 130 | ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version); 131 | 132 | p = string; 133 | while(isalnum(*p)) { 134 | if(isdigit(*p)) { 135 | q = p; 136 | while(isdigit(*q)) { 137 | q++; 138 | } 139 | dif = QRinput_estimateBitsModeAn((int)(p - string)) /* + 4 + la */ 140 | + QRinput_estimateBitsModeNum((int)(q - p)) + 4 + ln 141 | + (isalnum(*q)?(4 + ln):0) 142 | - QRinput_estimateBitsModeAn((int)(q - string)) /* - 4 - la */; 143 | if(dif < 0) { 144 | break; 145 | } 146 | p = q; 147 | } else { 148 | p++; 149 | } 150 | } 151 | 152 | run = (int)(p - string); 153 | 154 | if(*p && !isalnum(*p)) { 155 | dif = QRinput_estimateBitsModeAn(run) + 4 + la 156 | + QRinput_estimateBitsMode8(1) /* + 4 + l8 */ 157 | - QRinput_estimateBitsMode8(run + 1) /* - 4 - l8 */; 158 | if(dif > 0) { 159 | return Split_eat8(string, input, hint); 160 | } 161 | } 162 | 163 | ret = QRinput_append(input, QR_MODE_AN, run, (unsigned char *)string); 164 | if(ret < 0) return -1; 165 | 166 | return run; 167 | } 168 | 169 | static int Split_eatKanji(const char *string, QRinput *input, QRencodeMode hint) 170 | { 171 | const char *p; 172 | int ret; 173 | int run; 174 | 175 | p = string; 176 | while(Split_identifyMode(p, hint) == QR_MODE_KANJI) { 177 | p += 2; 178 | } 179 | run = (int)(p - string); 180 | ret = QRinput_append(input, QR_MODE_KANJI, run, (unsigned char *)string); 181 | if(ret < 0) return -1; 182 | 183 | return run; 184 | } 185 | 186 | static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint) 187 | { 188 | const char *p, *q; 189 | QRencodeMode mode; 190 | int ret; 191 | int run; 192 | int dif; 193 | int la, ln, l8; 194 | int swcost; 195 | 196 | la = QRspec_lengthIndicator(QR_MODE_AN, input->version); 197 | ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version); 198 | l8 = QRspec_lengthIndicator(QR_MODE_8, input->version); 199 | 200 | p = string + 1; 201 | while(*p != '\0') { 202 | mode = Split_identifyMode(p, hint); 203 | if(mode == QR_MODE_KANJI) { 204 | break; 205 | } 206 | if(mode == QR_MODE_NUM) { 207 | q = p; 208 | while(isdigit(*q)) { 209 | q++; 210 | } 211 | if(Split_identifyMode(q, hint) == QR_MODE_8) { 212 | swcost = 4 + l8; 213 | } else { 214 | swcost = 0; 215 | } 216 | dif = QRinput_estimateBitsMode8((int)(p - string)) /* + 4 + l8 */ 217 | + QRinput_estimateBitsModeNum((int)(q - p)) + 4 + ln 218 | + swcost 219 | - QRinput_estimateBitsMode8((int)(q - string)) /* - 4 - l8 */; 220 | if(dif < 0) { 221 | break; 222 | } 223 | p = q; 224 | } else if(mode == QR_MODE_AN) { 225 | q = p; 226 | while(isalnum(*q)) { 227 | q++; 228 | } 229 | if(Split_identifyMode(q, hint) == QR_MODE_8) { 230 | swcost = 4 + l8; 231 | } else { 232 | swcost = 0; 233 | } 234 | dif = QRinput_estimateBitsMode8((int)(p - string)) /* + 4 + l8 */ 235 | + QRinput_estimateBitsModeAn((int)(q - p)) + 4 + la 236 | + swcost 237 | - QRinput_estimateBitsMode8((int)(q - string)) /* - 4 - l8 */; 238 | if(dif < 0) { 239 | break; 240 | } 241 | p = q; 242 | } else { 243 | p++; 244 | } 245 | } 246 | 247 | run = (int)(p - string); 248 | ret = QRinput_append(input, QR_MODE_8, run, (unsigned char *)string); 249 | if(ret < 0) return -1; 250 | 251 | return run; 252 | } 253 | 254 | static int Split_splitString(const char *string, QRinput *input, 255 | QRencodeMode hint) 256 | { 257 | int length; 258 | QRencodeMode mode; 259 | 260 | while(*string != '\0') { 261 | mode = Split_identifyMode(string, hint); 262 | if(mode == QR_MODE_NUM) { 263 | length = Split_eatNum(string, input, hint); 264 | } else if(mode == QR_MODE_AN) { 265 | length = Split_eatAn(string, input, hint); 266 | } else if(mode == QR_MODE_KANJI && hint == QR_MODE_KANJI) { 267 | length = Split_eatKanji(string, input, hint); 268 | } else { 269 | length = Split_eat8(string, input, hint); 270 | } 271 | if(length == 0) break; 272 | if(length < 0) return -1; 273 | string += length; 274 | } 275 | 276 | return 0; 277 | } 278 | 279 | static char *dupAndToUpper(const char *str, QRencodeMode hint) 280 | { 281 | char *newstr, *p; 282 | QRencodeMode mode; 283 | 284 | newstr = strdup(str); 285 | if(newstr == NULL) return NULL; 286 | 287 | p = newstr; 288 | while(*p != '\0') { 289 | mode = Split_identifyMode(p, hint); 290 | if(mode == QR_MODE_KANJI) { 291 | p += 2; 292 | } else { 293 | if (*p >= 'a' && *p <= 'z') { 294 | *p = (char)((int)*p - 32); 295 | } 296 | p++; 297 | } 298 | } 299 | 300 | return newstr; 301 | } 302 | 303 | int Split_splitStringToQRinput(const char *string, QRinput *input, 304 | QRencodeMode hint, int casesensitive) 305 | { 306 | char *newstr; 307 | int ret; 308 | 309 | if(string == NULL || *string == '\0') { 310 | errno = EINVAL; 311 | return -1; 312 | } 313 | if(!casesensitive) { 314 | newstr = dupAndToUpper(string, hint); 315 | if(newstr == NULL) return -1; 316 | ret = Split_splitString(newstr, input, hint); 317 | free(newstr); 318 | } else { 319 | ret = Split_splitString(string, input, hint); 320 | } 321 | 322 | return ret; 323 | } 324 | -------------------------------------------------------------------------------- /split.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qrencode - QR Code encoder 3 | * 4 | * Input data splitter. 5 | * Copyright (C) 2006-2017 Kentaro Fukuchi 6 | * 7 | * The following data / specifications are taken from 8 | * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) 9 | * or 10 | * "Automatic identification and data capture techniques -- 11 | * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) 12 | * 13 | * This library is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Lesser General Public 15 | * License as published by the Free Software Foundation; either 16 | * version 2.1 of the License, or any later version. 17 | * 18 | * This library is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 | * Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public 24 | * License along with this library; if not, write to the Free Software 25 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 26 | */ 27 | 28 | #ifndef SPLIT_H 29 | #define SPLIT_H 30 | 31 | #include "qrencode.h" 32 | 33 | /** 34 | * Split the input string (null terminated) into QRinput. 35 | * @param string input string 36 | * @param hint give QR_MODE_KANJI if the input string contains Kanji character encoded in Shift-JIS. If not, give QR_MODE_8. 37 | * @param casesensitive 0 for case-insensitive encoding (all alphabet characters are replaced to UPPER-CASE CHARACTERS. 38 | * @retval 0 success. 39 | * @retval -1 an error occurred. errno is set to indicate the error. See 40 | * Exceptions for the details. 41 | * @throw EINVAL invalid input object. 42 | * @throw ENOMEM unable to allocate memory for input objects. 43 | */ 44 | extern int Split_splitStringToQRinput(const char *string, QRinput *input, 45 | QRencodeMode hint, int casesensitive); 46 | 47 | #endif /* SPLIT_H */ 48 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(common 2 | common.c common.h) 3 | target_link_libraries(common qrencode) 4 | 5 | add_library(rscode 6 | rscode.c rscode.h) 7 | target_link_libraries(rscode common) 8 | 9 | macro(MAKE_TEST test_name) 10 | set(ADDITIONAL_LIBS "${ARGN}") 11 | add_executable(${test_name} ${test_name}.c) 12 | target_link_libraries(${test_name} common ${ADDITIONAL_LIBS}) 13 | add_test(${test_name} ${test_name}) 14 | endmacro(MAKE_TEST) 15 | 16 | if(TARGET PNG::PNG) 17 | add_executable(create_frame_pattern create_frame_pattern.c) 18 | target_link_libraries(create_frame_pattern common PNG::PNG) 19 | 20 | add_executable(create_mqr_frame_pattern create_mqr_frame_pattern.c) 21 | target_link_libraries(create_mqr_frame_pattern common PNG::PNG) 22 | endif() 23 | 24 | if(HAVE_SDL) 25 | add_executable(view_qrcode view_qrcode.c) 26 | target_link_libraries(view_qrcode common) 27 | endif(HAVE_SDL) 28 | 29 | if(TARGET Threads::Threads) 30 | if(HAVE_SYS_TIME_H) 31 | add_definitions(-DHAVE_SYS_TIME_H) 32 | endif() 33 | 34 | if(HAVE_TIME_H) 35 | add_definitions(-DHAVE_TIME_H) 36 | endif() 37 | 38 | add_executable(prof_qrencode prof_qrencode.c) 39 | target_link_libraries(prof_qrencode common Threads::Threads) 40 | 41 | if(HAVE_PTHREAD_H) 42 | add_executable(pthread_qrencode pthread_qrencode.c) 43 | target_link_libraries(pthread_qrencode common Threads::Threads) 44 | endif() 45 | endif() 46 | 47 | MAKE_TEST(test_bitstream) 48 | MAKE_TEST(test_estimatebit) 49 | MAKE_TEST(test_split) 50 | 51 | if(TARGET ICONV::ICONV) 52 | add_library(decoder STATIC 53 | decoder.c decoder.h 54 | datachunk.c datachunk.h 55 | rsecc_decoder.c rsecc_decoder.h) 56 | target_link_libraries(decoder ICONV::ICONV) 57 | 58 | MAKE_TEST(test_qrinput decoder) 59 | MAKE_TEST(test_qrspec decoder) 60 | target_compile_definitions(test_qrspec PRIVATE -DSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}/") 61 | MAKE_TEST(test_mqrspec decoder) 62 | MAKE_TEST(test_qrencode decoder) 63 | MAKE_TEST(test_split_urls decoder) 64 | MAKE_TEST(test_monkey decoder) 65 | 66 | include(CheckCSourceCompiles) 67 | check_c_source_compiles( 68 | "int main(){ 69 | const int w = 1; 70 | char buf[w]; 71 | return 0; 72 | }" 73 | FIXED_SIZE_BUFFER_INITIALIZATION) 74 | 75 | if(FIXED_SIZE_BUFFER_INITIALIZATION) 76 | MAKE_TEST(test_mask decoder) 77 | MAKE_TEST(test_mmask decoder) 78 | MAKE_TEST(test_rs rscode decoder) 79 | endif() 80 | endif() 81 | 82 | -------------------------------------------------------------------------------- /tests/Makefile.am: -------------------------------------------------------------------------------- 1 | AM_CFLAGS = 2 | AM_LDFLAGS = 3 | 4 | if HAVE_SDL 5 | sdlPROGRAMS = view_qrcode 6 | AM_CFLAGS += $(SDL_CFLAGS) 7 | AM_LDFLAGS += $(SDL_LIBS) 8 | endif 9 | 10 | if HAVE_PNG 11 | pngPROGRAMS = create_frame_pattern create_mqr_frame_pattern 12 | endif 13 | 14 | check_PROGRAMS = test_qrinput test_bitstream test_estimatebit test_qrspec \ 15 | test_rs test_qrencode test_mqrspec test_split test_mask \ 16 | test_mmask test_split_urls test_monkey 17 | noinst_PROGRAMS = $(pngPROGRAMS) $(sdlPROGRAMS) $(check_PROGRAMS) prof_qrencode 18 | noinst_LIBRARIES = libdecoder.a 19 | DECODER_LIBS = libdecoder.a $(LIBICONV) 20 | noinst_HEADERS = common.h rscode.h 21 | if HAVE_LIBPTHREAD 22 | noinst_PROGRAMS += pthread_qrencode 23 | endif 24 | 25 | TESTS = $(check_PROGRAMS) 26 | EXTRA_DIST = test_all.sh test_basic.sh test_configure.sh frame URI_testset.inc CMakeLists.txt 27 | 28 | libdecoder_a_SOURCES = decoder.c decoder.h datachunk.c datachunk.h rsecc_decoder.c rsecc_decoder.h 29 | 30 | test_qrinput_SOURCES = test_qrinput.c common.c 31 | test_qrinput_LDADD = $(DECODER_LIBS) ../libqrencode.la 32 | 33 | test_bitstream_SOURCES = test_bitstream.c common.c 34 | test_bitstream_LDADD = ../libqrencode.la 35 | 36 | test_estimatebit_SOURCES = test_estimatebit.c common.c 37 | test_estimatebit_LDADD = ../libqrencode.la 38 | 39 | test_qrspec_SOURCES = test_qrspec.c common.c 40 | test_qrspec_CPPFLAGS = -DSRCDIR=\"$(srcdir)/\" 41 | test_qrspec_LDADD = $(DECODER_LIBS) ../libqrencode.la 42 | 43 | test_mqrspec_SOURCES = test_mqrspec.c common.c 44 | test_mqrspec_LDADD = $(DECODER_LIBS) ../libqrencode.la 45 | 46 | test_rs_SOURCES = test_rs.c rscode.c common.c 47 | test_rs_LDADD = $(DECODER_LIBS) ../libqrencode.la 48 | 49 | test_qrencode_SOURCES = test_qrencode.c common.c 50 | test_qrencode_LDADD = $(DECODER_LIBS) ../libqrencode.la 51 | 52 | test_split_SOURCES = test_split.c common.c 53 | test_split_LDADD = ../libqrencode.la 54 | 55 | test_split_urls_SOURCES = test_split_urls.c common.c 56 | test_split_urls_LDADD = $(DECODER_LIBS) ../libqrencode.la 57 | 58 | test_monkey_SOURCES = test_monkey.c common.c 59 | test_monkey_LDADD = $(DECODER_LIBS) ../libqrencode.la 60 | 61 | test_mask_SOURCES = test_mask.c common.c 62 | test_mask_LDADD = $(DECODER_LIBS) ../libqrencode.la 63 | 64 | test_mmask_SOURCES = test_mmask.c common.c 65 | test_mmask_LDADD = $(DECODER_LIBS) ../libqrencode.la 66 | 67 | prof_qrencode_SOURCES = prof_qrencode.c common.c 68 | prof_qrencode_LDADD = ../libqrencode.la 69 | 70 | pthread_qrencode_SOURCES = pthread_qrencode.c common.c 71 | pthread_qrencode_LDADD = ../libqrencode.la 72 | 73 | if HAVE_PNG 74 | create_frame_pattern_SOURCES = create_frame_pattern.c common.c 75 | create_frame_pattern_CFLAGS = $(png_CFLAGS) $(AM_CFLAGS) 76 | create_frame_pattern_LDADD = ../libqrencode.la $(png_LIBS) 77 | 78 | create_mqr_frame_pattern_SOURCES = create_mqr_frame_pattern.c common.c 79 | create_mqr_frame_pattern_CFLAGS = $(png_CFLAGS) $(AM_CFLAGS) 80 | create_mqr_frame_pattern_LDADD = ../libqrencode.la $(png_LIBS) 81 | endif 82 | 83 | if HAVE_SDL 84 | view_qrcode_SOURCES = view_qrcode.c common.c 85 | view_qrcode_LDADD = ../libqrencode.la 86 | endif 87 | -------------------------------------------------------------------------------- /tests/common.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "common.h" 4 | 5 | static int tests = 0; 6 | static int failed = 0; 7 | int assertionFailed = 0; 8 | int assertionNum = 0; 9 | static const char *testName = NULL; 10 | static const char *testFunc = NULL; 11 | 12 | const char levelChar[4] = {'L', 'M', 'Q', 'H'}; 13 | const char *modeStr[5] = {"nm", "an", "8", "kj", "st"}; 14 | 15 | int ncmpBin(char *correct, BitStream *bstream, size_t len) 16 | { 17 | int bit; 18 | size_t i; 19 | char *p; 20 | 21 | if(len != BitStream_size(bstream)) { 22 | printf("Length is not match: %zu, %zu expected.\n", BitStream_size(bstream), len); 23 | return -1; 24 | } 25 | 26 | p = correct; 27 | i = 0; 28 | while(*p != '\0') { 29 | while(*p == ' ') { 30 | p++; 31 | } 32 | bit = (*p == '1')?1:0; 33 | if(bstream->data[i] != bit) return -1; 34 | i++; 35 | p++; 36 | if(i == len) break; 37 | } 38 | 39 | return 0; 40 | } 41 | 42 | int cmpBin(char *correct, BitStream *bstream) 43 | { 44 | size_t len = 0; 45 | char *p; 46 | 47 | 48 | for(p = correct; *p != '\0'; p++) { 49 | if(*p != ' ') len++; 50 | } 51 | return ncmpBin(correct, bstream, len); 52 | } 53 | 54 | void testInit(int tests) 55 | { 56 | printf("1..%d\n", tests); 57 | } 58 | 59 | void testStartReal(const char *func, const char *name) 60 | { 61 | tests++; 62 | testName = name; 63 | testFunc = func; 64 | assertionFailed = 0; 65 | assertionNum = 0; 66 | //printf("_____%d: %s: %s...\n", tests, func, name); 67 | } 68 | 69 | void testEnd(int result) 70 | { 71 | if(result) { 72 | printf("not ok %d %s: %s\n", tests, testFunc, testName); 73 | failed++; 74 | } else { 75 | printf("ok %d %s: %s\n", tests, testFunc, testName); 76 | } 77 | } 78 | 79 | void testFinish(void) 80 | { 81 | if(assertionFailed) { 82 | printf("not ok %d %s: %s (%d assertions failed.)\n", tests, testFunc, testName, assertionFailed); 83 | failed++; 84 | } else { 85 | printf("ok %d %s: %s (%d assertions passed.)\n", tests, testFunc, testName, assertionNum); 86 | } 87 | } 88 | 89 | void testReport(int expectedTests) 90 | { 91 | printf("Total %d tests, %d fails.\n", tests, failed); 92 | if(failed) exit(-1); 93 | if(expectedTests != tests) { 94 | printf("WARNING: the number of the executed tests (%d) is not equal to the expecetd (%d).\n", tests, expectedTests); 95 | } 96 | } 97 | 98 | int testNum(void) 99 | { 100 | return tests; 101 | } 102 | 103 | void printBinary(unsigned char *data, int length) 104 | { 105 | int i; 106 | 107 | for(i=0; idata, BitStream_size(bstream)); 116 | } 117 | 118 | void printQRinput(QRinput *input) 119 | { 120 | QRinput_List *list; 121 | int i; 122 | 123 | list = input->head; 124 | while(list != NULL) { 125 | for(i=0; isize; i++) { 126 | printf("0x%02x,", list->data[i]); 127 | } 128 | list = list->next; 129 | } 130 | printf("\n"); 131 | } 132 | 133 | void printQRinputInfo(QRinput *input) 134 | { 135 | QRinput_List *list; 136 | BitStream *b; 137 | int i, ret; 138 | 139 | printf("QRinput info:\n"); 140 | printf(" version: %d\n", input->version); 141 | printf(" level : %c\n", levelChar[input->level]); 142 | list = input->head; 143 | i = 0; 144 | while(list != NULL) { 145 | i++; 146 | list = list->next; 147 | } 148 | printf(" chunks: %d\n", i); 149 | b = BitStream_new(); 150 | ret = QRinput_mergeBitStream(input, b); 151 | if(ret == 0) { 152 | printf(" bitstream-size: %zu\n", BitStream_size(b)); 153 | BitStream_free(b); 154 | } 155 | 156 | list = input->head; 157 | i = 0; 158 | while(list != NULL) { 159 | printf("\t#%d: mode = %s, size = %d\n", i, modeStr[list->mode], list->size); 160 | i++; 161 | list = list->next; 162 | } 163 | } 164 | 165 | void printQRinputStruct(QRinput_Struct *s) 166 | { 167 | QRinput_InputList *list; 168 | int i = 1; 169 | 170 | printf("Struct size: %d\n", s->size); 171 | printf("Struct parity: %08x\n", s->parity); 172 | for(list = s->head; list != NULL; list = list->next) { 173 | printf("Symbol %d - ", i); 174 | printQRinputInfo(list->input); 175 | i++; 176 | } 177 | } 178 | 179 | void printFrame(int width, unsigned char *frame) 180 | { 181 | int x, y; 182 | 183 | for(y=0; ywidth, code->data); 194 | } 195 | 196 | void printQRRawCodeFromQRinput(QRinput *input) 197 | { 198 | QRRawCode *raw; 199 | int i; 200 | 201 | puts("QRRawCode dump image:"); 202 | raw = QRraw_new(input); 203 | if(raw == NULL) { 204 | puts("Failed to generate QRRawCode from this input.\n"); 205 | return; 206 | } 207 | for(i=0; idataLength; i++) { 208 | printf(" %02x", raw->datacode[i]); 209 | } 210 | for(i=0; ieccLength; i++) { 211 | printf(" %02x", raw->ecccode[i]); 212 | } 213 | printf("\n"); 214 | QRraw_free(raw); 215 | } 216 | 217 | #if HAVE_SDL 218 | /* Experimental debug function */ 219 | /* You can call show_QRcode(QRcode *code) to display the QR Code from anywhere 220 | * in test code using SDL. */ 221 | #include 222 | 223 | static void draw_QRcode(QRcode *qrcode, int ox, int oy, int margin, int size, SDL_Surface *surface) 224 | { 225 | int x, y, width; 226 | unsigned char *p; 227 | SDL_Rect rect; 228 | Uint32 color[2]; 229 | 230 | color[0] = SDL_MapRGBA(surface->format, 255, 255, 255, 255); 231 | color[1] = SDL_MapRGBA(surface->format, 0, 0, 0, 255); 232 | SDL_FillRect(surface, NULL, color[0]); 233 | 234 | ox += margin * size; 235 | oy += margin * size; 236 | width = qrcode->width; 237 | p = qrcode->data; 238 | for(y=0; ywidth + 4 * 2) * 4; //maring = 4, size = 4 263 | SDL_CreateWindowAndRenderer(width, width, SDL_WINDOW_SHOWN, &window, &renderer); 264 | SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); 265 | SDL_RenderClear(renderer); 266 | surface = SDL_CreateRGBSurface(0, width, width, 32, 0, 0, 0, 0); 267 | 268 | draw_QRcode(qrcode, 0, 0, 4, 4, surface); 269 | 270 | texture = SDL_CreateTextureFromSurface(renderer, surface); 271 | SDL_RenderCopy(renderer, texture, NULL, NULL); 272 | SDL_RenderPresent(renderer); 273 | fprintf(stderr, "Press any key on the QR Code window to proceed.\n"); 274 | 275 | int loop = 1; 276 | while(loop) { 277 | SDL_WaitEvent(&event); 278 | if(event.type == SDL_KEYDOWN) { 279 | loop = 0; 280 | } 281 | } 282 | 283 | SDL_FreeSurface(surface); 284 | SDL_DestroyTexture(texture); 285 | SDL_DestroyRenderer(renderer); 286 | } 287 | #else 288 | void show_QRcode(QRcode *qrcode) { 289 | } 290 | #endif 291 | -------------------------------------------------------------------------------- /tests/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * common part of test units. 3 | */ 4 | 5 | #ifndef COMMON_H__ 6 | #define COMMON_H__ 7 | 8 | #include 9 | #if HAVE_CONFIG_H 10 | #include "../config.h" 11 | #endif 12 | #include "../qrencode.h" 13 | #include "../qrinput.h" 14 | #include "../bitstream.h" 15 | #include "../qrencode_inner.h" 16 | 17 | extern int assertionFailed; 18 | extern int assertionNum; 19 | extern const char levelChar[4]; 20 | extern const char *modeStr[5]; 21 | 22 | void testInit(int tests); 23 | #define testStart(__arg__) (testStartReal(__func__, __arg__)) 24 | #define testEndExp(__arg__) (testEnd(!(__arg__))) 25 | void testStartReal(const char *func, const char *name); 26 | void testEnd(int result); 27 | void testFinish(void); 28 | void testReport(int tests); 29 | 30 | #define assert_exp(__exp__, ...) \ 31 | {assertionNum++;if(!(__exp__)) {assertionFailed++; printf(__VA_ARGS__);}} 32 | 33 | #define assert_zero(__exp__, ...) assert_exp((__exp__) == 0, __VA_ARGS__) 34 | #define assert_nonzero(__exp__, ...) assert_exp((__exp__) != 0, __VA_ARGS__) 35 | #define assert_null(__ptr__, ...) assert_exp((__ptr__) == NULL, __VA_ARGS__) 36 | #define assert_nonnull(__ptr__, ...) assert_exp((__ptr__) != NULL, __VA_ARGS__) 37 | #define assert_equal(__e1__, __e2__, ...) assert_exp((__e1__) == (__e2__), __VA_ARGS__) 38 | #define assert_notequal(__e1__, __e2__, ...) assert_exp((__e1__) != (__e2__), __VA_ARGS__) 39 | #define assert_nothing(__exp__, ...) {printf(__VA_ARGS__); __exp__;} 40 | 41 | int ncmpBin(char *correct, BitStream *bstream, size_t len); 42 | int cmpBin(char *correct, BitStream *bstream); 43 | 44 | void printFrame(int width, unsigned char *frame); 45 | void printQRcode(QRcode *code); 46 | void printQRRawCodeFromQRinput(QRinput *input); 47 | void printQRinput(QRinput *input); 48 | void printQRinputInfo(QRinput *input); 49 | void printQRinputStruct(QRinput_Struct *s); 50 | 51 | void printBinary(unsigned char *data, int length); 52 | void printBstream(BitStream *bstream); 53 | 54 | void show_QRcode(QRcode *qrcode); 55 | 56 | #endif /* COMMON_H__ */ 57 | -------------------------------------------------------------------------------- /tests/create_frame_pattern.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This tool creates a frame pattern data for debug purpose used by 3 | * test_qrspec. test_qrspec and create_frame_pattern uses the same function 4 | * of libqrencode. This means the test is meaningless if test_qrspec is run 5 | * with a pattern data created by create_frame_pattern of the same version. 6 | * In order to test it correctly, create a pattern data by the tool of the 7 | * previous version, or use the frame data attached to the package. 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include "common.h" 14 | #include "../qrspec.h" 15 | 16 | void append_pattern(int version, FILE *fp) 17 | { 18 | int width; 19 | unsigned char *frame; 20 | 21 | frame = QRspec_newFrame(version); 22 | width = QRspec_getWidth(version); 23 | fwrite(frame, 1, width * width, fp); 24 | free(frame); 25 | } 26 | 27 | static int writePNG(unsigned char *frame, int width, const char *outfile) 28 | { 29 | static FILE *fp; 30 | png_structp png_ptr; 31 | png_infop info_ptr; 32 | unsigned char *row, *p, *q; 33 | int x, y, xx, yy, bit; 34 | int realwidth; 35 | const int margin = 0; 36 | const int size = 1; 37 | 38 | realwidth = (width + margin * 2) * size; 39 | row = (unsigned char *)malloc((realwidth + 7) / 8); 40 | if(row == NULL) { 41 | fprintf(stderr, "Failed to allocate memory.\n"); 42 | exit(EXIT_FAILURE); 43 | } 44 | 45 | if(outfile[0] == '-' && outfile[1] == '\0') { 46 | fp = stdout; 47 | } else { 48 | fp = fopen(outfile, "wb"); 49 | if(fp == NULL) { 50 | fprintf(stderr, "Failed to create file: %s\n", outfile); 51 | perror(NULL); 52 | exit(EXIT_FAILURE); 53 | } 54 | } 55 | 56 | png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 57 | if(png_ptr == NULL) { 58 | fclose(fp); 59 | fprintf(stderr, "Failed to initialize PNG writer.\n"); 60 | exit(EXIT_FAILURE); 61 | } 62 | 63 | info_ptr = png_create_info_struct(png_ptr); 64 | if(info_ptr == NULL) { 65 | fclose(fp); 66 | fprintf(stderr, "Failed to initialize PNG write.\n"); 67 | exit(EXIT_FAILURE); 68 | } 69 | 70 | if(setjmp(png_jmpbuf(png_ptr))) { 71 | png_destroy_write_struct(&png_ptr, &info_ptr); 72 | fclose(fp); 73 | fprintf(stderr, "Failed to write PNG image.\n"); 74 | exit(EXIT_FAILURE); 75 | } 76 | 77 | png_init_io(png_ptr, fp); 78 | png_set_IHDR(png_ptr, info_ptr, 79 | realwidth, realwidth, 80 | 1, 81 | PNG_COLOR_TYPE_GRAY, 82 | PNG_INTERLACE_NONE, 83 | PNG_COMPRESSION_TYPE_DEFAULT, 84 | PNG_FILTER_TYPE_DEFAULT); 85 | png_write_info(png_ptr, info_ptr); 86 | 87 | /* top margin */ 88 | memset(row, 0xff, (realwidth + 7) / 8); 89 | for(y=0; y 11 | #include 12 | #include 13 | #include "common.h" 14 | #include "../mqrspec.h" 15 | 16 | void append_pattern(int version, FILE *fp) 17 | { 18 | int width; 19 | unsigned char *frame; 20 | 21 | frame = MQRspec_newFrame(version); 22 | width = MQRspec_getWidth(version); 23 | fwrite(frame, 1, width * width, fp); 24 | free(frame); 25 | } 26 | 27 | static int writePNG(unsigned char *frame, int width, const char *outfile) 28 | { 29 | static FILE *fp; 30 | png_structp png_ptr; 31 | png_infop info_ptr; 32 | unsigned char *row, *p, *q; 33 | int x, y, xx, yy, bit; 34 | int realwidth; 35 | const int margin = 0; 36 | const int size = 1; 37 | 38 | realwidth = (width + margin * 2) * size; 39 | row = (unsigned char *)malloc((realwidth + 7) / 8); 40 | if(row == NULL) { 41 | fprintf(stderr, "Failed to allocate memory.\n"); 42 | exit(EXIT_FAILURE); 43 | } 44 | 45 | if(outfile[0] == '-' && outfile[1] == '\0') { 46 | fp = stdout; 47 | } else { 48 | fp = fopen(outfile, "wb"); 49 | if(fp == NULL) { 50 | fprintf(stderr, "Failed to create file: %s\n", outfile); 51 | perror(NULL); 52 | exit(EXIT_FAILURE); 53 | } 54 | } 55 | 56 | png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 57 | if(png_ptr == NULL) { 58 | fclose(fp); 59 | fprintf(stderr, "Failed to initialize PNG writer.\n"); 60 | exit(EXIT_FAILURE); 61 | } 62 | 63 | info_ptr = png_create_info_struct(png_ptr); 64 | if(info_ptr == NULL) { 65 | fclose(fp); 66 | fprintf(stderr, "Failed to initialize PNG write.\n"); 67 | exit(EXIT_FAILURE); 68 | } 69 | 70 | if(setjmp(png_jmpbuf(png_ptr))) { 71 | png_destroy_write_struct(&png_ptr, &info_ptr); 72 | fclose(fp); 73 | fprintf(stderr, "Failed to write PNG image.\n"); 74 | exit(EXIT_FAILURE); 75 | } 76 | 77 | png_init_io(png_ptr, fp); 78 | png_set_IHDR(png_ptr, info_ptr, 79 | realwidth, realwidth, 80 | 1, 81 | PNG_COLOR_TYPE_GRAY, 82 | PNG_INTERLACE_NONE, 83 | PNG_COMPRESSION_TYPE_DEFAULT, 84 | PNG_FILTER_TYPE_DEFAULT); 85 | png_write_info(png_ptr, info_ptr); 86 | 87 | /* top margin */ 88 | memset(row, 0xff, (realwidth + 7) / 8); 89 | for(y=0; y 2 | #include 3 | #include 4 | #include 5 | #include "datachunk.h" 6 | 7 | DataChunk *DataChunk_new(QRencodeMode mode) 8 | { 9 | DataChunk *chunk; 10 | 11 | chunk = (DataChunk *)calloc(1, sizeof(DataChunk)); 12 | if(chunk == NULL) return NULL; 13 | 14 | chunk->mode = mode; 15 | 16 | return chunk; 17 | } 18 | 19 | void DataChunk_free(DataChunk *chunk) 20 | { 21 | if(chunk) { 22 | if(chunk->data) free(chunk->data); 23 | free(chunk); 24 | } 25 | } 26 | 27 | void DataChunk_freeList(DataChunk *list) 28 | { 29 | DataChunk *next; 30 | 31 | while(list != NULL) { 32 | next = list->next; 33 | DataChunk_free(list); 34 | list = next; 35 | } 36 | } 37 | 38 | static void dumpNum(DataChunk *chunk) 39 | { 40 | printf("%s\n", chunk->data); 41 | } 42 | 43 | static void dumpAn(DataChunk *chunk) 44 | { 45 | printf("%s\n", chunk->data); 46 | } 47 | 48 | static void dump8(DataChunk *chunk) 49 | { 50 | int i, j; 51 | unsigned char c; 52 | int count = 0; 53 | unsigned char buf[16]; 54 | 55 | for(i=0; isize; i++) { 56 | buf[count] = chunk->data[i]; 57 | c = chunk->data[i]; 58 | if(c >= ' ' && c <= '~') { 59 | putchar(c); 60 | } else { 61 | putchar('.'); 62 | } 63 | count++; 64 | 65 | if(count >= 16) { 66 | putchar(' '); 67 | for(j=0; j<16; j++) { 68 | printf(" %02x", buf[j]); 69 | } 70 | count = 0; 71 | putchar('\n'); 72 | } 73 | } 74 | if(count > 0) { 75 | for(i=0; i<16 - count; i++) { 76 | putchar(' '); 77 | } 78 | putchar(' '); 79 | for(j=0; jsize; 95 | inbuf = (char *)chunk->data; 96 | outbytes = inbytes * 4 + 1; 97 | outbuf = (char *)malloc(inbytes * 4 + 1); 98 | outp = outbuf; 99 | ret = iconv(conv, &inbuf, &inbytes, &outp, &outbytes); 100 | if(ret == (size_t) -1) { perror(NULL); } 101 | *outp = '\0'; 102 | 103 | printf("%s\n", outbuf); 104 | 105 | iconv_close(conv); 106 | free(outbuf); 107 | } 108 | 109 | static void dumpChunk(DataChunk *chunk) 110 | { 111 | switch(chunk->mode) { 112 | case QR_MODE_NUM: 113 | printf("Numeric: %d bytes\n", chunk->size); 114 | dumpNum(chunk); 115 | break; 116 | case QR_MODE_AN: 117 | printf("AlphaNumeric: %d bytes\n", chunk->size); 118 | dumpAn(chunk); 119 | break; 120 | case QR_MODE_8: 121 | printf("8-bit data: %d bytes\n", chunk->size); 122 | dump8(chunk); 123 | break; 124 | case QR_MODE_KANJI: 125 | printf("Kanji: %d bytes\n", chunk->size); 126 | dumpKanji(chunk); 127 | break; 128 | default: 129 | printf("Invalid or reserved: %d bytes\n", chunk->size); 130 | dump8(chunk); 131 | break; 132 | } 133 | } 134 | 135 | void DataChunk_dumpChunkList(DataChunk *list) 136 | { 137 | while(list != NULL) { 138 | dumpChunk(list); 139 | list = list->next; 140 | } 141 | } 142 | 143 | int DataChunk_totalSize(DataChunk *list) 144 | { 145 | int size = 0; 146 | 147 | while(list != NULL) { 148 | size += list->size; 149 | list = list->next; 150 | } 151 | 152 | return size; 153 | } 154 | 155 | unsigned char *DataChunk_concatChunkList(DataChunk *list, int *retsize) 156 | { 157 | int size, idx; 158 | unsigned char *data; 159 | 160 | size = DataChunk_totalSize(list); 161 | if(size <= 0) return NULL; 162 | 163 | data = (unsigned char *)malloc(size + 1); 164 | idx = 0; 165 | while(list != NULL) { 166 | memcpy(&data[idx], list->data, list->size); 167 | idx += list->size; 168 | list = list->next; 169 | } 170 | data[size] = '\0'; 171 | 172 | *retsize = size; 173 | return data; 174 | } 175 | -------------------------------------------------------------------------------- /tests/datachunk.h: -------------------------------------------------------------------------------- 1 | #ifndef DATACHUNK_H 2 | #define DATACHUNK_H 3 | 4 | #include "../qrencode.h" 5 | 6 | typedef struct _DataChunk { 7 | QRencodeMode mode; 8 | int size; 9 | int bits; 10 | unsigned char *data; 11 | struct _DataChunk *next; 12 | } DataChunk; 13 | 14 | DataChunk *DataChunk_new(QRencodeMode mode); 15 | void DataChunk_free(DataChunk *chunk); 16 | void DataChunk_freeList(DataChunk *list); 17 | void DataChunk_dumpChunkList(DataChunk *list); 18 | int DataChunk_totalSize(DataChunk *list); 19 | unsigned char *DataChunk_concatChunkList(DataChunk *list, int *retsize); 20 | 21 | #endif /* DATACHUNK_H */ 22 | -------------------------------------------------------------------------------- /tests/decoder.h: -------------------------------------------------------------------------------- 1 | #ifndef DECODER_H 2 | #define DECODER_H 3 | 4 | #include "../qrencode.h" 5 | #include "datachunk.h" 6 | 7 | typedef struct { 8 | unsigned char *data; 9 | int size; 10 | int mqr; 11 | int version; 12 | QRecLevel level; 13 | DataChunk *chunks, *last; 14 | int eccResult; 15 | } QRdata; 16 | 17 | struct FormatInfo { 18 | int version; 19 | QRecLevel level; 20 | }; 21 | 22 | extern struct FormatInfo MQRformat[]; 23 | 24 | QRdata *QRdata_new(void); 25 | QRdata *QRdata_newMQR(void); 26 | int QRdata_decodeBitStream(QRdata *qrdata, BitStream *bstream); 27 | void QRdata_dump(QRdata *data); 28 | void QRdata_free(QRdata *data); 29 | 30 | int QRcode_decodeVersion(QRcode *code); 31 | int QRcode_decodeFormat(QRcode *code, QRecLevel *level, int *mask); 32 | unsigned char *QRcode_unmask(QRcode *code); 33 | BitStream *QRcode_extractBits(QRcode *code, int *dataLength, int *eccLength); 34 | QRdata *QRcode_decodeBits(QRcode *code); 35 | QRdata *QRcode_decode(QRcode *code); 36 | 37 | int QRcode_decodeFormatMQR(QRcode *code, int *vesion, QRecLevel *level, int *mask); 38 | unsigned char *QRcode_unmaskMQR(QRcode *code); 39 | BitStream *QRcode_extractBitsMQR(QRcode *code, int *dataLength, int *eccLength, int *version, QRecLevel *level); 40 | QRdata *QRcode_decodeBitsMQR(QRcode *code); 41 | QRdata *QRcode_decodeMQR(QRcode *code); 42 | 43 | #endif /* DECODER_H */ 44 | -------------------------------------------------------------------------------- /tests/frame: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fukuchi/libqrencode/715e29fd4cd71b6e452ae0f4e36d917b43122ce8/tests/frame -------------------------------------------------------------------------------- /tests/prof_qrencode.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #if HAVE_CONFIG_H 4 | #include "../config.h" 5 | #endif 6 | #ifdef HAVE_SYS_TIME_H 7 | #include 8 | #endif 9 | #include 10 | #include "../qrencode.h" 11 | 12 | #ifdef _MSC_VER 13 | #define WIN32_LEAN_AND_MEAN 14 | #include 15 | static LARGE_INTEGER startTime; 16 | static LARGE_INTEGER frequency = { .QuadPart = 0 }; 17 | #else 18 | static struct timeval tv; 19 | #endif 20 | 21 | static void timerStart(const char *str) 22 | { 23 | printf("%s: START\n", str); 24 | #ifdef _MSC_VER 25 | (void) QueryPerformanceCounter(&startTime); 26 | #else 27 | gettimeofday(&tv, NULL); 28 | #endif 29 | } 30 | 31 | static void timerStop(void) 32 | { 33 | #ifdef _MSC_VER 34 | LARGE_INTEGER endTime, elapsed; 35 | (void) QueryPerformanceCounter(&endTime); 36 | if (frequency.QuadPart == 0) { 37 | (void) QueryPerformanceFrequency(&frequency); 38 | } 39 | 40 | elapsed.QuadPart = endTime.QuadPart - startTime.QuadPart; 41 | elapsed.QuadPart *= 1000; 42 | elapsed.QuadPart /= frequency.QuadPart; 43 | 44 | printf("STOP: %lld msec\n", elapsed.QuadPart); 45 | #else 46 | struct timeval tc; 47 | 48 | gettimeofday(&tc, NULL); 49 | printf("STOP: %ld msec\n", (tc.tv_sec - tv.tv_sec) * 1000 50 | + (tc.tv_usec - tv.tv_usec) / 1000); 51 | #endif 52 | } 53 | 54 | static void prof_ver1to10(void) 55 | { 56 | QRcode *code; 57 | int i; 58 | int version; 59 | static const char *data = "This is test."; 60 | 61 | timerStart("Version 1 - 10 (500 symbols for each)"); 62 | for(i=0; i<500; i++) { 63 | for(version = 0; version < 11; version++) { 64 | code = QRcode_encodeString(data, version, QR_ECLEVEL_L, QR_MODE_8, 0); 65 | if(code == NULL) { 66 | perror("Failed to encode:"); 67 | } else { 68 | QRcode_free(code); 69 | } 70 | } 71 | } 72 | timerStop(); 73 | } 74 | 75 | static void prof_ver31to40(void) 76 | { 77 | QRcode *code; 78 | int i; 79 | int version; 80 | static const char *data = "This is test."; 81 | 82 | timerStart("Version 31 - 40 (50 symbols for each)"); 83 | for(i=0; i<50; i++) { 84 | for(version = 31; version < 41; version++) { 85 | code = QRcode_encodeString(data, version, QR_ECLEVEL_L, QR_MODE_8, 0); 86 | if(code == NULL) { 87 | perror("Failed to encode:"); 88 | } else { 89 | QRcode_free(code); 90 | } 91 | } 92 | } 93 | timerStop(); 94 | } 95 | 96 | int main() 97 | { 98 | prof_ver1to10(); 99 | prof_ver31to40(); 100 | 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /tests/pthread_qrencode.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #if HAVE_CONFIG_H 4 | #include "../config.h" 5 | #endif 6 | #ifdef HAVE_SYS_TIME_H 7 | #include 8 | #endif 9 | #include 10 | #include 11 | #include "../qrencode.h" 12 | 13 | #define THREADS (10) 14 | 15 | static pthread_t threads[THREADS]; 16 | 17 | #ifdef _MSC_VER 18 | #define WIN32_LEAN_AND_MEAN 19 | #include 20 | static LARGE_INTEGER startTime; 21 | static LARGE_INTEGER frequency = { .QuadPart = 0 }; 22 | #else 23 | static struct timeval tv; 24 | #endif 25 | 26 | static void timerStart(const char *str) 27 | { 28 | printf("%s: START\n", str); 29 | #ifdef _MSC_VER 30 | (void) QueryPerformanceCounter(&startTime); 31 | #else 32 | gettimeofday(&tv, NULL); 33 | #endif 34 | } 35 | 36 | static void timerStop(void) 37 | { 38 | #ifdef _MSC_VER 39 | LARGE_INTEGER endTime, elapsed; 40 | (void) QueryPerformanceCounter(&endTime); 41 | if (frequency.QuadPart == 0) { 42 | (void) QueryPerformanceFrequency(&frequency); 43 | } 44 | 45 | elapsed.QuadPart = endTime.QuadPart - startTime.QuadPart; 46 | elapsed.QuadPart *= 1000; 47 | elapsed.QuadPart /= frequency.QuadPart; 48 | 49 | printf("STOP: %lld msec\n", elapsed.QuadPart); 50 | #else 51 | struct timeval tc; 52 | 53 | gettimeofday(&tc, NULL); 54 | printf("STOP: %ld msec\n", (tc.tv_sec - tv.tv_sec) * 1000 55 | + (tc.tv_usec - tv.tv_usec) / 1000); 56 | #endif 57 | } 58 | 59 | static void *encode_ver1to10(void *arg) 60 | { 61 | QRcode *code; 62 | int i; 63 | int version; 64 | static const char *data = "This is test."; 65 | 66 | for(i=0; i<500; i++) { 67 | for(version = 0; version < 11; version++) { 68 | code = QRcode_encodeString(data, version, QR_ECLEVEL_L, QR_MODE_8, 0); 69 | if(code == NULL) { 70 | perror("Failed to encode:"); 71 | } else { 72 | QRcode_free(code); 73 | } 74 | } 75 | } 76 | 77 | return NULL; 78 | } 79 | 80 | static void prof_ver1to10(void) 81 | { 82 | int i; 83 | 84 | timerStart("Version 1 - 10 (500 symbols for each)"); 85 | for(i=0; i 11 | * 12 | * This library is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU Lesser General Public 14 | * License as published by the Free Software Foundation; either 15 | * version 2.1 of the License, or any later version. 16 | * 17 | * This library is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | * Lesser General Public License for more details. 21 | * 22 | * You should have received a copy of the GNU Lesser General Public 23 | * License along with this library; if not, write to the Free Software 24 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 25 | */ 26 | 27 | #if HAVE_CONFIG_H 28 | # include "config.h" 29 | #endif 30 | #include 31 | #include 32 | 33 | #include "rscode.h" 34 | 35 | /* Stuff specific to the 8-bit symbol version of the general purpose RS codecs 36 | * 37 | */ 38 | typedef unsigned char data_t; 39 | 40 | 41 | /** 42 | * Reed-Solomon codec control block 43 | */ 44 | struct _RS { 45 | int mm; /* Bits per symbol */ 46 | int nn; /* Symbols per block (= (1<= rs->nn) { 60 | x -= rs->nn; 61 | x = (x >> rs->mm) + (x & rs->nn); 62 | } 63 | return x; 64 | } 65 | 66 | 67 | #define MODNN(x) modnn(rs,x) 68 | 69 | #define MM (rs->mm) 70 | #define NN (rs->nn) 71 | #define ALPHA_TO (rs->alpha_to) 72 | #define INDEX_OF (rs->index_of) 73 | #define GENPOLY (rs->genpoly) 74 | #define NROOTS (rs->nroots) 75 | #define FCR (rs->fcr) 76 | #define PRIM (rs->prim) 77 | #define IPRIM (rs->iprim) 78 | #define PAD (rs->pad) 79 | #define A0 (NN) 80 | 81 | 82 | /* Initialize a Reed-Solomon codec 83 | * symsize = symbol size, bits 84 | * gfpoly = Field generator polynomial coefficients 85 | * fcr = first root of RS code generator polynomial, index form 86 | * prim = primitive element to generate polynomial roots 87 | * nroots = RS code generator polynomial degree (number of roots) 88 | * pad = padding bytes at front of shortened block 89 | */ 90 | static RS *init_rs_char(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad) 91 | { 92 | RS *rs; 93 | 94 | 95 | /* Common code for intializing a Reed-Solomon control block (char or int symbols) 96 | * Copyright 2004 Phil Karn, KA9Q 97 | * May be used under the terms of the GNU Lesser General Public License (LGPL) 98 | */ 99 | //#undef NULL 100 | //#define NULL ((void *)0) 101 | 102 | int i, j, sr,root,iprim; 103 | 104 | rs = NULL; 105 | /* Check parameter ranges */ 106 | if(symsize < 0 || symsize > (int)(8*sizeof(data_t))){ 107 | goto done; 108 | } 109 | 110 | if(fcr < 0 || fcr >= (1<= (1<= (1<= ((1<mm = symsize; 124 | rs->nn = (1<pad = pad; 126 | 127 | rs->alpha_to = (data_t *)malloc(sizeof(data_t)*(rs->nn+1)); 128 | if(rs->alpha_to == NULL){ 129 | free(rs); 130 | rs = NULL; 131 | goto done; 132 | } 133 | rs->index_of = (data_t *)malloc(sizeof(data_t)*(rs->nn+1)); 134 | if(rs->index_of == NULL){ 135 | free(rs->alpha_to); 136 | free(rs); 137 | rs = NULL; 138 | goto done; 139 | } 140 | 141 | /* Generate Galois field lookup tables */ 142 | rs->index_of[0] = A0; /* log(zero) = -inf */ 143 | rs->alpha_to[A0] = 0; /* alpha**-inf = 0 */ 144 | sr = 1; 145 | for(i=0;inn;i++){ 146 | rs->index_of[sr] = i; 147 | rs->alpha_to[i] = sr; 148 | sr <<= 1; 149 | if(sr & (1<nn; 152 | } 153 | if(sr != 1){ 154 | /* field generator polynomial is not primitive! */ 155 | free(rs->alpha_to); 156 | free(rs->index_of); 157 | free(rs); 158 | rs = NULL; 159 | goto done; 160 | } 161 | 162 | /* Form RS code generator polynomial from its roots */ 163 | rs->genpoly = (data_t *)malloc(sizeof(data_t)*(nroots+1)); 164 | if(rs->genpoly == NULL){ 165 | free(rs->alpha_to); 166 | free(rs->index_of); 167 | free(rs); 168 | rs = NULL; 169 | goto done; 170 | } 171 | rs->fcr = fcr; 172 | rs->prim = prim; 173 | rs->nroots = nroots; 174 | rs->gfpoly = gfpoly; 175 | 176 | /* Find prim-th root of 1, used in decoding */ 177 | for(iprim=1;(iprim % prim) != 0;iprim += rs->nn) 178 | ; 179 | rs->iprim = iprim / prim; 180 | 181 | rs->genpoly[0] = 1; 182 | for (i = 0,root=fcr*prim; i < nroots; i++,root += prim) { 183 | rs->genpoly[i+1] = 1; 184 | 185 | /* Multiply rs->genpoly[] by @**(root + x) */ 186 | for (j = i; j > 0; j--){ 187 | if (rs->genpoly[j] != 0) 188 | rs->genpoly[j] = rs->genpoly[j-1] ^ rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[j]] + root)]; 189 | else 190 | rs->genpoly[j] = rs->genpoly[j-1]; 191 | } 192 | /* rs->genpoly[0] can never be zero */ 193 | rs->genpoly[0] = rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[0]] + root)]; 194 | } 195 | /* convert rs->genpoly[] to index form for quicker encoding */ 196 | for (i = 0; i <= nroots; i++) 197 | rs->genpoly[i] = rs->index_of[rs->genpoly[i]]; 198 | done:; 199 | 200 | return rs; 201 | } 202 | 203 | RS *init_rs(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad) 204 | { 205 | return init_rs_char(symsize, gfpoly, fcr, prim, nroots, pad); 206 | } 207 | 208 | 209 | void free_rs_char(RS *rs) 210 | { 211 | free(rs->alpha_to); 212 | free(rs->index_of); 213 | free(rs->genpoly); 214 | free(rs); 215 | } 216 | 217 | /* The guts of the Reed-Solomon encoder, meant to be #included 218 | * into a function body with the following typedefs, macros and variables supplied 219 | * according to the code parameters: 220 | 221 | * data_t - a typedef for the data symbol 222 | * data_t data[] - array of NN-NROOTS-PAD and type data_t to be encoded 223 | * data_t parity[] - an array of NROOTS and type data_t to be written with parity symbols 224 | * NROOTS - the number of roots in the RS code generator polynomial, 225 | * which is the same as the number of parity symbols in a block. 226 | Integer variable or literal. 227 | * 228 | * NN - the total number of symbols in a RS block. Integer variable or literal. 229 | * PAD - the number of pad symbols in a block. Integer variable or literal. 230 | * ALPHA_TO - The address of an array of NN elements to convert Galois field 231 | * elements in index (log) form to polynomial form. Read only. 232 | * INDEX_OF - The address of an array of NN elements to convert Galois field 233 | * elements in polynomial form to index (log) form. Read only. 234 | * MODNN - a function to reduce its argument modulo NN. May be inline or a macro. 235 | * GENPOLY - an array of NROOTS+1 elements containing the generator polynomial in index form 236 | 237 | * The memset() and memmove() functions are used. The appropriate header 238 | * file declaring these functions (usually ) must be included by the calling 239 | * program. 240 | 241 | * Copyright 2004, Phil Karn, KA9Q 242 | * May be used under the terms of the GNU Lesser General Public License (LGPL) 243 | */ 244 | 245 | #undef A0 246 | #define A0 (NN) /* Special reserved value encoding zero in index form */ 247 | 248 | void encode_rs_char(RS *rs, const data_t *data, data_t *parity) 249 | { 250 | int i, j; 251 | data_t feedback; 252 | 253 | memset(parity,0,NROOTS*sizeof(data_t)); 254 | 255 | for(i=0;i 11 | * 12 | * This library is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU Lesser General Public 14 | * License as published by the Free Software Foundation; either 15 | * version 2.1 of the License, or any later version. 16 | * 17 | * This library is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | * Lesser General Public License for more details. 21 | * 22 | * You should have received a copy of the GNU Lesser General Public 23 | * License along with this library; if not, write to the Free Software 24 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 25 | */ 26 | 27 | #ifndef RSCODE_H 28 | #define RSCODE_H 29 | 30 | /* 31 | * General purpose RS codec, 8-bit symbols. 32 | */ 33 | 34 | typedef struct _RS RS; 35 | 36 | extern RS *init_rs(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad); 37 | extern void encode_rs_char(RS *rs, const unsigned char *data, unsigned char *parity); 38 | extern void free_rs_char(RS *rs); 39 | 40 | #endif /* RSCODE_H */ 41 | -------------------------------------------------------------------------------- /tests/rsecc_decoder.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../qrspec.h" 5 | #include "rsecc_decoder.h" 6 | 7 | #define SYMBOL_SIZE (8) 8 | #define symbols ((1 << SYMBOL_SIZE) - 1) 9 | static const int proot = 0x11d; /* stands for x^8+x^4+x^3+x^2+1 (see pp.37 of JIS X0510:2004) */ 10 | 11 | /* min/max codeword length of ECC, calculated from the specification. */ 12 | #define min_length (2) 13 | #define max_length (30) 14 | #define max_generatorSize (max_length) 15 | 16 | static unsigned char alpha[symbols + 1]; 17 | static unsigned char aindex[symbols + 1]; 18 | 19 | void RSECC_decoder_init() { 20 | int i, b; 21 | 22 | alpha[symbols] = 0; 23 | aindex[0] = symbols; 24 | 25 | b = 1; 26 | for(i = 0; i < symbols; i++) { 27 | alpha[i] = b; 28 | aindex[b] = i; 29 | b <<= 1; 30 | if(b & (symbols + 1)) { 31 | b ^= proot; 32 | } 33 | b &= symbols; 34 | } 35 | } 36 | 37 | int RSECC_decoder_checkSyndrome(int dl, unsigned char *data, int el, unsigned char *ecc) 38 | { 39 | int i, j; 40 | int s; 41 | 42 | for(i=0; i 2 | #include 3 | #include "common.h" 4 | #include "../bitstream.h" 5 | 6 | static void test_null(void) 7 | { 8 | BitStream *bstream; 9 | 10 | testStart("Empty stream"); 11 | bstream = BitStream_new(); 12 | assert_zero(BitStream_size(bstream), "Size of empty BitStream is not 0.\n"); 13 | assert_null(BitStream_toByte(bstream), "BitStream_toByte returned non-NULL.\n"); 14 | assert_nothing(BitStream_free(NULL), "Checking BitStream_free(NULL).\n"); 15 | testFinish(); 16 | 17 | BitStream_free(bstream); 18 | } 19 | 20 | static void test_num(void) 21 | { 22 | BitStream *bstream; 23 | unsigned int data = 0x13579bdf; 24 | char correct[] = "0010011010101111001101111011111"; 25 | 26 | testStart("New from num"); 27 | bstream = BitStream_new(); 28 | BitStream_appendNum(bstream, 31, data); 29 | testEnd(cmpBin(correct, bstream)); 30 | 31 | BitStream_free(bstream); 32 | } 33 | 34 | static void test_bytes(void) 35 | { 36 | BitStream *bstream; 37 | unsigned char data[1] = {0x3a}; 38 | char correct[] = "00111010"; 39 | 40 | testStart("New from bytes"); 41 | bstream = BitStream_new(); 42 | BitStream_appendBytes(bstream, 1, data); 43 | testEnd(cmpBin(correct, bstream)); 44 | BitStream_free(bstream); 45 | } 46 | 47 | static void test_appendNum(void) 48 | { 49 | BitStream *bstream; 50 | char correct[] = "10001010 11111111 11111111 00010010001101000101011001111000"; 51 | 52 | testStart("Append Num"); 53 | bstream = BitStream_new(); 54 | 55 | BitStream_appendNum(bstream, 8, 0x0000008a); 56 | assert_zero(ncmpBin(correct, bstream, 8), "Internal data is incorrect.\n"); 57 | 58 | BitStream_appendNum(bstream, 16, 0x0000ffff); 59 | assert_zero(ncmpBin(correct, bstream, 24), "Internal data is incorrect.\n"); 60 | 61 | BitStream_appendNum(bstream, 32, 0x12345678); 62 | 63 | assert_zero(cmpBin(correct, bstream), "Internal data is incorrect.\n"); 64 | testFinish(); 65 | 66 | BitStream_free(bstream); 67 | } 68 | 69 | static void test_appendBytes(void) 70 | { 71 | BitStream *bstream; 72 | unsigned char data[8]; 73 | char correct[] = "10001010111111111111111100010010001101000101011001111000"; 74 | 75 | testStart("Append Bytes"); 76 | bstream = BitStream_new(); 77 | 78 | data[0] = 0x8a; 79 | BitStream_appendBytes(bstream, 1, data); 80 | assert_zero(ncmpBin(correct, bstream, 8), "Internal data is incorrect."); 81 | 82 | data[0] = 0xff; 83 | data[1] = 0xff; 84 | BitStream_appendBytes(bstream, 2, data); 85 | assert_zero(ncmpBin(correct, bstream, 24), "Internal data is incorrect.\n"); 86 | 87 | data[0] = 0x12; 88 | data[1] = 0x34; 89 | data[2] = 0x56; 90 | data[3] = 0x78; 91 | BitStream_appendBytes(bstream, 4, data); 92 | 93 | assert_zero(cmpBin(correct, bstream), "Internal data is incorrect.\n"); 94 | testFinish(); 95 | 96 | BitStream_free(bstream); 97 | } 98 | 99 | static void test_toByte(void) 100 | { 101 | BitStream *bstream; 102 | unsigned char correct[] = { 103 | 0x8a, 0xff, 0xff, 0x12, 0x34, 0x56, 0x78 104 | }; 105 | unsigned char *result; 106 | 107 | testStart("Convert to a byte array"); 108 | bstream = BitStream_new(); 109 | 110 | BitStream_appendBytes(bstream, 1, &correct[0]); 111 | BitStream_appendBytes(bstream, 2, &correct[1]); 112 | BitStream_appendBytes(bstream, 4, &correct[3]); 113 | 114 | result = BitStream_toByte(bstream); 115 | testEnd(memcmp(correct, result, 7)); 116 | 117 | BitStream_free(bstream); 118 | free(result); 119 | } 120 | 121 | static void test_toByte_4bitpadding(void) 122 | { 123 | BitStream *bstream; 124 | unsigned char *result; 125 | 126 | testStart("Convert to a byte array"); 127 | 128 | bstream = BitStream_new(); 129 | BitStream_appendNum(bstream, 4, 0xb); 130 | result = BitStream_toByte(bstream); 131 | assert_equal(result[0], 0xb0, "incorrect paddings\n"); 132 | BitStream_free(bstream); 133 | free(result); 134 | 135 | bstream = BitStream_new(); 136 | BitStream_appendNum(bstream, 12, 0x335); 137 | result = BitStream_toByte(bstream); 138 | assert_equal(result[0], 0x33, "incorrect paddings\n"); 139 | assert_equal(result[1], 0x50, "incorrect paddings\n"); 140 | BitStream_free(bstream); 141 | free(result); 142 | 143 | testFinish(); 144 | 145 | } 146 | 147 | static void test_size(void) 148 | { 149 | BitStream *bstream; 150 | 151 | testStart("size check"); 152 | bstream = BitStream_new(); 153 | assert_equal(BitStream_size(bstream), 0, "Initialized BitStream is not 0 length"); 154 | BitStream_appendNum(bstream, 1, 0); 155 | assert_equal(BitStream_size(bstream), 1, "Size incorrect. (first append)"); 156 | BitStream_appendNum(bstream, 2, 0); 157 | assert_equal(BitStream_size(bstream), 3, "Size incorrect. (second append)"); 158 | testFinish(); 159 | 160 | BitStream_free(bstream); 161 | } 162 | 163 | static void test_append(void) 164 | { 165 | BitStream *bs1, *bs2; 166 | char c1[] = "00"; 167 | char c2[] = "0011"; 168 | char c3[] = "01111111111111111"; 169 | char c4[] = "001101111111111111111"; 170 | char c5[] = "0011011111111111111111111111111111"; 171 | int ret; 172 | 173 | testStart("Append two BitStreams"); 174 | 175 | bs1 = BitStream_new(); 176 | bs2 = BitStream_new(); 177 | ret = BitStream_appendNum(bs1, 1, 0); 178 | ret = BitStream_appendNum(bs2, 1, 0); 179 | 180 | ret = BitStream_append(bs1, bs2); 181 | assert_zero(ret, "Failed to append."); 182 | assert_zero(cmpBin(c1, bs1), "Internal data is incorrect."); 183 | 184 | ret = BitStream_appendNum(bs1, 2, 3); 185 | assert_zero(ret, "Failed to append."); 186 | assert_zero(cmpBin(c2, bs1), "Internal data is incorrect."); 187 | 188 | ret = BitStream_appendNum(bs2, 16, 65535); 189 | assert_zero(ret, "Failed to append."); 190 | assert_zero(cmpBin(c3, bs2), "Internal data is incorrect."); 191 | 192 | ret = BitStream_append(bs1, bs2); 193 | assert_zero(ret, "Failed to append."); 194 | assert_zero(cmpBin(c4, bs1), "Internal data is incorrect."); 195 | 196 | ret = BitStream_appendNum(bs1, 13, 16383); 197 | assert_zero(ret, "Failed to append."); 198 | assert_zero(cmpBin(c5, bs1), "Internal data is incorrect."); 199 | 200 | testFinish(); 201 | 202 | BitStream_free(bs1); 203 | BitStream_free(bs2); 204 | } 205 | 206 | static void test_newWithBits(void) 207 | { 208 | BitStream *bstream; 209 | unsigned char data[4] = {0, 1, 0, 1}; 210 | 211 | testStart("New with bits"); 212 | 213 | bstream = BitStream_newWithBits(4, data); 214 | assert_equal(bstream->length, 4, "Internal bit length is incorrect.\n"); 215 | assert_equal(bstream->datasize, 4, "Internal buffer size is incorrect.\n"); 216 | assert_zero(cmpBin("0101", bstream), "Internal data is incorrect.\n"); 217 | 218 | testFinish(); 219 | 220 | BitStream_free(bstream); 221 | } 222 | 223 | static void test_newWithBits_size0(void) 224 | { 225 | BitStream *bstream; 226 | 227 | testStart("New with bits (size = 0)"); 228 | 229 | bstream = BitStream_newWithBits(0, NULL); 230 | assert_equal(bstream->length, 0, "Internal bit length is incorrect.\n"); 231 | assert_nonzero(bstream->datasize, "Internal buffer size is incorrect.\n"); 232 | assert_nonnull(bstream->data, "Internal buffer not allocated.\n"); 233 | 234 | testFinish(); 235 | 236 | BitStream_free(bstream); 237 | } 238 | 239 | int main() 240 | { 241 | int tests = 11; 242 | testInit(tests); 243 | test_null(); 244 | test_num(); 245 | test_bytes(); 246 | test_appendNum(); 247 | test_appendBytes(); 248 | test_toByte(); 249 | test_toByte_4bitpadding(); 250 | test_size(); 251 | test_append(); 252 | test_newWithBits(); 253 | test_newWithBits_size0(); 254 | testReport(tests); 255 | 256 | return 0; 257 | } 258 | -------------------------------------------------------------------------------- /tests/test_configure.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | BASEDIR=.. 4 | 5 | CONFIG_H_IN="$BASEDIR/config.h.in" 6 | CONFIG_H="$BASEDIR/config.h" 7 | LIBQRENCODE_PC_IN="$BASEDIR/libqrencode.pc.in" 8 | LIBQRENCODE_PC="$BASEDIR/libqrencode.pc" 9 | 10 | echo "Testing configure scripts..." 11 | 12 | (cd $BASEDIR; ./autogen.sh) 13 | 14 | # test config.h.in 15 | grep "#undef HAVE_LIBPTHREAD" $CONFIG_H_IN > /dev/null 16 | if test ! $? -eq 0; then 17 | echo "HAVE_LIBPTHREAD undefined in config.h.in." 18 | exit 1 19 | fi 20 | 21 | # test libqrencode.pc.in 22 | grep "Libs.private: @LIBPTHREAD@" $LIBQRENCODE_PC_IN > /dev/null 23 | if test ! $? -eq 0; then 24 | echo "Pthread is not handled in libqrencode.pc.in." 25 | exit 1 26 | fi 27 | 28 | # test pthread checks in configure 29 | (cd $BASEDIR; ./configure --with-tests --enable-thread-safety > /dev/null) 30 | grep "#define HAVE_LIBPTHREAD 1" $CONFIG_H > /dev/null 31 | if test ! $? -eq 0; then 32 | echo "HAVE_LIBPTHREAD undefined in config.h." 33 | exit 1 34 | fi 35 | 36 | grep "Libs.private: -lpthread" $LIBQRENCODE_PC > /dev/null 37 | if test ! $? -eq 0; then 38 | echo "Pthread is not handled in libqrencode.pc." 39 | exit 1 40 | fi 41 | 42 | (cd $BASEDIR; ./configure --with-tests --disable-thread-safety > /dev/null) 43 | grep "#define HAVE_LIBPTHREAD 1" $CONFIG_H > /dev/null 44 | if test ! $? -eq 1; then 45 | echo "HAVE_LIBPTHREAD incorrectly defined in config.h." 46 | exit 1 47 | fi 48 | 49 | grep "Libs.private: -lpthread" $LIBQRENCODE_PC > /dev/null 50 | if test ! $? -eq 1; then 51 | echo "Pthread is incorrectly handled in libqrencode.pc." 52 | exit 1 53 | fi 54 | 55 | echo "All tests of configure script passed. Now reconfiguring..." 56 | 57 | (cd $BASEDIR; ./configure --with-tests > /dev/null) 58 | 59 | echo "Done." 60 | 61 | exit 0 62 | -------------------------------------------------------------------------------- /tests/test_estimatebit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "common.h" 5 | #include "../qrinput.h" 6 | 7 | static QRinput *gstream; 8 | 9 | static void test_numbit(void) 10 | { 11 | QRinput *stream; 12 | char num[9]="01234567"; 13 | int bits; 14 | 15 | testStart("Estimation of Numeric stream (8 digits)"); 16 | stream = QRinput_new(); 17 | QRinput_append(stream, QR_MODE_NUM, 8, (unsigned char *)num); 18 | bits = QRinput_estimateBitStreamSize(stream, 0); 19 | testEndExp(bits == 41); 20 | 21 | QRinput_append(gstream, QR_MODE_NUM, 8, (unsigned char *)num); 22 | QRinput_free(stream); 23 | } 24 | 25 | static void test_numbit2(void) 26 | { 27 | QRinput *stream; 28 | char num[17]="0123456789012345"; 29 | int bits; 30 | 31 | testStart("Estimation of Numeric stream (16 digits)"); 32 | stream = QRinput_new(); 33 | QRinput_append(stream, QR_MODE_NUM, 16, (unsigned char *)num); 34 | bits = QRinput_estimateBitStreamSize(stream, 0); 35 | testEndExp(bits == 68); 36 | 37 | QRinput_append(gstream, QR_MODE_NUM, 16, (unsigned char *)num); 38 | QRinput_free(stream); 39 | } 40 | 41 | static void test_numbit3(void) 42 | { 43 | QRinput *stream; 44 | char *num; 45 | int bits; 46 | 47 | testStart("Estimation of Numeric stream (400 digits)"); 48 | stream = QRinput_new(); 49 | num = (char *)malloc(401); 50 | memset(num, '1', 400); 51 | num[400] = '\0'; 52 | QRinput_append(stream, QR_MODE_NUM, 400, (unsigned char *)num); 53 | bits = QRinput_estimateBitStreamSize(stream, 0); 54 | /* 4 + 10 + 133*10 + 4 = 1348 */ 55 | testEndExp(bits == 1348); 56 | 57 | QRinput_append(gstream, QR_MODE_NUM, 400, (unsigned char *)num); 58 | QRinput_free(stream); 59 | free(num); 60 | } 61 | 62 | static void test_an(void) 63 | { 64 | QRinput *stream; 65 | char str[6]="AC-42"; 66 | int bits; 67 | 68 | testStart("Estimation of Alphabet-Numeric stream (5 chars)"); 69 | stream = QRinput_new(); 70 | QRinput_append(stream, QR_MODE_AN, 5, (unsigned char *)str); 71 | bits = QRinput_estimateBitStreamSize(stream, 0); 72 | testEndExp(bits == 41); 73 | 74 | QRinput_append(gstream, QR_MODE_AN, 5, (unsigned char *)str); 75 | QRinput_free(stream); 76 | } 77 | 78 | static void test_8(void) 79 | { 80 | QRinput *stream; 81 | char str[9]="12345678"; 82 | int bits; 83 | 84 | testStart("Estimation of 8 bit data stream (8 bytes)"); 85 | stream = QRinput_new(); 86 | QRinput_append(stream, QR_MODE_8, 8, (unsigned char *)str); 87 | bits = QRinput_estimateBitStreamSize(stream, 0); 88 | testEndExp(bits == 76); 89 | 90 | QRinput_append(gstream, QR_MODE_8, 8, (unsigned char *)str); 91 | QRinput_free(stream); 92 | } 93 | 94 | static void test_structure(void) 95 | { 96 | QRinput *stream; 97 | int bits; 98 | 99 | testStart("Estimation of a structure-append header"); 100 | stream = QRinput_new(); 101 | QRinput_insertStructuredAppendHeader(stream, 10, 1, 0); 102 | bits = QRinput_estimateBitStreamSize(stream, 1); 103 | testEndExp(bits == 20); 104 | 105 | QRinput_insertStructuredAppendHeader(gstream, 10, 1, 0); 106 | QRinput_free(stream); 107 | } 108 | 109 | static void test_kanji(void) 110 | { 111 | int res; 112 | 113 | QRinput *stream; 114 | unsigned char str[4]= {0x93, 0x5f,0xe4, 0xaa}; 115 | int bits; 116 | 117 | testStart("Estimation of Kanji stream (2 chars)"); 118 | stream = QRinput_new(); 119 | res = QRinput_append(stream, QR_MODE_KANJI, 4, (unsigned char *)str); 120 | if(res < 0) { 121 | printf("Failed to add.\n"); 122 | testEnd(1); 123 | } else { 124 | bits = QRinput_estimateBitStreamSize(stream, 0); 125 | testEndExp(bits == 38); 126 | QRinput_append(gstream, QR_MODE_KANJI, 4, (unsigned char *)str); 127 | } 128 | 129 | QRinput_free(stream); 130 | } 131 | 132 | static void test_mix(void) 133 | { 134 | int bits; 135 | 136 | testStart("Estimation of Mixed stream"); 137 | bits = QRinput_estimateBitStreamSize(gstream, 0); 138 | testEndExp(bits == (41 + 68 + 1348 + 41 + 76 + 38 + 20)); 139 | QRinput_free(gstream); 140 | } 141 | 142 | /* Taken from JISX 0510:2018, p.23 */ 143 | static void test_numbit1_mqr(void) 144 | { 145 | QRinput *stream; 146 | char *str = "0123456789012345"; 147 | int bits; 148 | 149 | testStart("Estimation of Numeric stream for Micro QR Code (16 digits)"); 150 | stream = QRinput_newMQR(3, QR_ECLEVEL_M); 151 | QRinput_append(stream, QR_MODE_NUM, 16, (const unsigned char *)str); 152 | bits = QRinput_estimateBitStreamSize(stream, QRinput_getVersion(stream)); 153 | assert_equal(bits, 61, "Estimated bit length is wrong: %d, expected: %d.\n", bits, 61); 154 | QRinput_free(stream); 155 | 156 | stream = QRinput_newMQR(4, QR_ECLEVEL_M); 157 | QRinput_append(stream, QR_MODE_NUM, 16, (const unsigned char *)str); 158 | bits = QRinput_estimateBitStreamSize(stream, QRinput_getVersion(stream)); 159 | assert_equal(bits, 63, "Estimated bit length is wrong: %d, expected: %d.\n", bits, 63); 160 | QRinput_free(stream); 161 | 162 | testFinish(); 163 | } 164 | 165 | int main() 166 | { 167 | gstream = QRinput_new(); 168 | 169 | int tests = 9; 170 | testInit(tests); 171 | test_numbit(); 172 | test_numbit2(); 173 | test_numbit3(); 174 | test_an(); 175 | test_8(); 176 | test_kanji(); 177 | test_structure(); 178 | test_mix(); 179 | test_numbit1_mqr(); 180 | testReport(tests); 181 | 182 | return 0; 183 | } 184 | -------------------------------------------------------------------------------- /tests/test_mask.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "common.h" 4 | #include "../mask.h" 5 | #include "../qrspec.h" 6 | #include "decoder.h" 7 | 8 | static char dot[2] = {'_', '#'}; 9 | static char *maskPatterns[8] = { 10 | /* (i + j) mod 2 = 0 */ 11 | "#_#_#_" 12 | "_#_#_#" 13 | "#_#_#_" 14 | "_#_#_#" 15 | "#_#_#_" 16 | "_#_#_#", 17 | /* i mod 2 = 0 */ 18 | "######" 19 | "______" 20 | "######" 21 | "______" 22 | "######" 23 | "______", 24 | /* j mod 3 = 0 */ 25 | "#__#__" 26 | "#__#__" 27 | "#__#__" 28 | "#__#__" 29 | "#__#__" 30 | "#__#__", 31 | /* (i + j) mod 3 = 0 */ 32 | "#__#__" 33 | "__#__#" 34 | "_#__#_" 35 | "#__#__" 36 | "__#__#" 37 | "_#__#_", 38 | /* ((i div 2) + (j div 3)) mod 2 = 0 */ 39 | "###___" 40 | "###___" 41 | "___###" 42 | "___###" 43 | "###___" 44 | "###___", 45 | /* (ij) mod 2 + (ij) mod 3 = 0 */ 46 | "######" 47 | "#_____" 48 | "#__#__" 49 | "#_#_#_" 50 | "#__#__" 51 | "#_____", 52 | /* ((ij) mod 2 + (ij) mod 3) mod 2 = 0 */ 53 | "######" 54 | "###___" 55 | "##_##_" 56 | "#_#_#_" 57 | "#_##_#" 58 | "#___##", 59 | /* ((ij) mod 3 + (i+j) mod 2) mod 2 = 0 */ 60 | "#_#_#_" 61 | "___###" 62 | "#___##" 63 | "_#_#_#" 64 | "###___" 65 | "_###__" 66 | }; 67 | 68 | static void print_mask(int mask) 69 | { 70 | const unsigned int w = 6; 71 | unsigned char frame[w * w], *masked, *p; 72 | int x, y; 73 | 74 | memset(frame, 0, w * w); 75 | masked = Mask_makeMaskedFrame(w, frame, mask); 76 | p = masked; 77 | for(y=0; y> 1; 213 | } 214 | } 215 | demerit = Mask_calcN2(width, frame); 216 | assert_equal(demerit, N2 * 4, "Calculation of N2 demerit is wrong: %d, expected %d", demerit, N2 * 4); 217 | 218 | width = 4; 219 | for(y = 0; y < width; y++) { 220 | for(x = 0; x < width; x++) { 221 | frame[y * width + x] = (((x + 1) & 2) ^ (y & 2)) >> 1; 222 | } 223 | } 224 | demerit = Mask_calcN2(width, frame); 225 | assert_equal(demerit, N2 * 2, "Calculation of N2 demerit is wrong: %d, expected %d", demerit, N2 * 2); 226 | 227 | width = 6; 228 | for(y = 0; y < width; y++) { 229 | for(x = 0; x < width; x++) { 230 | frame[y * width + x] = (x / 3) ^ (y / 3); 231 | } 232 | } 233 | demerit = Mask_calcN2(width, frame); 234 | assert_equal(demerit, N2 * 16, "Calculation of N2 demerit is wrong: %d, expected %d", demerit, N2 * 16); 235 | 236 | testFinish(); 237 | } 238 | 239 | static void test_eval3(void) 240 | { 241 | unsigned char *frame; 242 | int w = 15; 243 | int demerit; 244 | int x, y; 245 | static unsigned char pattern[7][15] = { 246 | {0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0}, // N3x1 247 | {1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1}, // N3x1 248 | {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1}, // N3x1 249 | {1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0}, // 0 250 | {1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1}, // N3x2 251 | {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0}, // N3 + (N1+1) 252 | {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1} // (N1+1) 253 | }; 254 | 255 | frame = (unsigned char *)malloc(w * w); 256 | 257 | testStart("Test mask evaluation (1:1:3:1:1 check)"); 258 | 259 | for(y=0; y<5; y++) { 260 | for(x=0; x 1) { 407 | print_masks(); 408 | } 409 | 410 | return 0; 411 | } 412 | -------------------------------------------------------------------------------- /tests/test_mmask.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "common.h" 4 | #include "../mmask.h" 5 | #include "../mqrspec.h" 6 | 7 | static char dot[2] = {'_', '#'}; 8 | static char *maskPatterns[4] = { 9 | /* i mod 2 = 0 */ 10 | "######" 11 | "______" 12 | "######" 13 | "______" 14 | "######" 15 | "______", 16 | /* ((i div 2) + (j div 3)) mod 2 = 0 */ 17 | "###___" 18 | "###___" 19 | "___###" 20 | "___###" 21 | "###___" 22 | "###___", 23 | /* ((ij) mod 2 + (ij) mod 3) mod 2 = 0 */ 24 | "######" 25 | "###___" 26 | "##_##_" 27 | "#_#_#_" 28 | "#_##_#" 29 | "#___##", 30 | /* ((ij) mod 3 + (i+j) mod 2) mod 2 = 0 */ 31 | "#_#_#_" 32 | "___###" 33 | "#___##" 34 | "_#_#_#" 35 | "###___" 36 | "_###__" 37 | }; 38 | 39 | static void print_mask(int mask) 40 | { 41 | const int w = 6; 42 | unsigned char frame[w * w], *masked, *p; 43 | int x, y; 44 | 45 | memset(frame, 0, w * w); 46 | masked = MMask_makeMaskedFrame(w, frame, mask); 47 | p = masked; 48 | for(y=0; y 1) { 151 | print_masks(); 152 | } 153 | 154 | return 0; 155 | } 156 | -------------------------------------------------------------------------------- /tests/test_mqrspec.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "common.h" 4 | #include "../mqrspec.h" 5 | 6 | static unsigned char v4frame[] = { 7 | 0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc0,0x91,0x90,0x91,0x90,0x91,0x90,0x91,0x90,0x91, 8 | 0xc1,0xc0,0xc0,0xc0,0xc0,0xc0,0xc1,0xc0,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9 | 0xc1,0xc0,0xc1,0xc1,0xc1,0xc0,0xc1,0xc0,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10 | 0xc1,0xc0,0xc1,0xc1,0xc1,0xc0,0xc1,0xc0,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11 | 0xc1,0xc0,0xc1,0xc1,0xc1,0xc0,0xc1,0xc0,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 12 | 0xc1,0xc0,0xc0,0xc0,0xc0,0xc0,0xc1,0xc0,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 13 | 0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc0,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 14 | 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 15 | 0x91,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 16 | 0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 17 | 0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 18 | 0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 19 | 0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 20 | 0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 21 | 0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 22 | 0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 23 | 0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 24 | }; 25 | 26 | static void test_newFrame(void) 27 | { 28 | int width, i, y; 29 | unsigned char *frame; 30 | 31 | testStart("Test empty frames"); 32 | for(i=1; i> 1; 67 | } 68 | c = 4 - i; 69 | code = 0x537 << c ; //10100110111 70 | b = 1 << (10 + c); 71 | for(i=0; i<=c; i++) { 72 | if(b & ecc) { 73 | ecc ^= code; 74 | } 75 | code = code >> 1; 76 | b = b >> 1; 77 | } 78 | 79 | return (data | ecc) ^ 0x4445; 80 | } 81 | 82 | /* See Table 10 of Appendix 1. (pp.115) */ 83 | static const int typeTable[4][3] = { 84 | { 0, -1, -1}, 85 | { 1, 2, -1}, 86 | { 3, 4, -1}, 87 | { 5, 6, 7} 88 | }; 89 | 90 | static void test_format(void) 91 | { 92 | unsigned int format; 93 | int version, l, mask; 94 | int type; 95 | int err = 0; 96 | 97 | testStart("Format info test"); 98 | for(version=1; version<=MQRSPEC_VERSION_MAX; version++) { 99 | for(l=QR_ECLEVEL_L; l<=QR_ECLEVEL_Q; l++) { 100 | for(mask=0; mask<4; mask++) { 101 | format = MQRspec_getFormatInfo(mask, version, (QRecLevel)l); 102 | type = typeTable[version - 1][l]; 103 | if(type == -1) { 104 | if(format != 0) { 105 | printf("Error in version %d, level %d, mask %d\n", 106 | version, l, mask); 107 | err++; 108 | } 109 | } else { 110 | if(format != calcFormatInfo(type, mask)) { 111 | printf("Error in version %d, level %d, mask %d\n", 112 | version, l, mask); 113 | err++; 114 | } 115 | } 116 | } 117 | } 118 | } 119 | testEnd(err); 120 | } 121 | 122 | static void print_format(void) 123 | { 124 | unsigned int format; 125 | int i, j; 126 | 127 | puts("\nPrinting hex strings of format information."); 128 | for(i=0; i<4; i++) { 129 | for(j=0; j<8; j++) { 130 | format = calcFormatInfo(j, i); 131 | printf("0x%04x, ", format); 132 | } 133 | printf("\n"); 134 | } 135 | } 136 | 137 | /** 138 | * See Table 7 of Appendix 1. 139 | */ 140 | static int datalen[4][3] = { 141 | { 20, 0, 0}, 142 | { 40, 32, 0}, 143 | { 84, 68, 0}, 144 | {128, 112, 80}, 145 | }; 146 | 147 | static void test_dataLength(void) 148 | { 149 | int v, l; 150 | int bits; 151 | int err = 0; 152 | 153 | testStart("Test dataLength"); 154 | for(v=0; v<4; v++) { 155 | for(l=0; l<3; l++) { 156 | bits = MQRspec_getDataLengthBit(v+1, (QRecLevel)l); 157 | if(bits != datalen[v][l]) { 158 | printf("Error in version %d, level %d.\n", v, l); 159 | err++; 160 | } 161 | } 162 | } 163 | testEnd(err); 164 | } 165 | 166 | int main(int argc, char **argv) 167 | { 168 | int tests = 4; 169 | testInit(tests); 170 | test_newFrame(); 171 | test_newframe_invalid(); 172 | test_format(); 173 | test_dataLength(); 174 | testReport(tests); 175 | 176 | if(argc > 1) { 177 | print_format(); 178 | } 179 | 180 | return 0; 181 | } 182 | -------------------------------------------------------------------------------- /tests/test_qrenc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | COMMAND=../qrencode 4 | TARGET_DIR="test_images" 5 | VALGRIND_COMMAND="libtool --mode=execute valgrind" 6 | VALGRIND_OPTIONS="--leak-check=full --show-reachable=yes" 7 | 8 | if [ "x$1" = 'xvalgrind' ]; then 9 | COMMAND="$VALGRIND_COMMAND $VALGRIND_OPTIONS $COMMAND" 10 | fi 11 | 12 | repeatchar() 13 | { 14 | printf %${2}s | tr ' ' ${1} 15 | } 16 | 17 | test_command_success() 18 | { 19 | repeatchar ${1} ${2} | $COMMAND -o - -l L ${3} > /dev/null 20 | if [ $? -ne 0 ]; then 21 | echo "Failed to encode $fn.txt" 22 | exit 1 23 | fi 24 | } 25 | 26 | test_command_fail() 27 | { 28 | repeatchar ${1} ${2} | $COMMAND -o - -l L ${3} > /dev/null 29 | if [ $? -eq 0 ]; then 30 | echo "Unexpectedly successed to encode '${1}'x'${2}' with '${3}'." 31 | exit 1 32 | else 33 | echo "^^^this is the expected error. Everything OK." 34 | fi 35 | } 36 | 37 | mkdir -p $TARGET_DIR 38 | 39 | test_command_success '1' 7089 40 | test_command_success 'A' 4296 41 | test_command_success 'a' 2953 42 | test_command_success '\211' 3634 '-k' 43 | 44 | test_command_fail '1' 7090 45 | test_command_fail 'A' 4297 46 | test_command_fail 'a' 2954 47 | test_command_fail '\211' 3636 '-k' 48 | test_command_fail '1' 15000 49 | -------------------------------------------------------------------------------- /tests/test_qrspec.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "common.h" 4 | #include "../qrspec.h" 5 | #include "../qrencode_inner.h" 6 | #include "decoder.h" 7 | 8 | #ifndef SRCDIR 9 | # define SRCDIR 10 | #endif 11 | 12 | static void print_eccTable(void) 13 | { 14 | int i, j; 15 | int ecc; 16 | int data; 17 | int spec[5]; 18 | 19 | puts("\nPrinting ECC table.\n"); 20 | for(i=1; i<=QRSPEC_VERSION_MAX; i++) { 21 | printf("Version %2d\n", i); 22 | for(j=0; j<4; j++) { 23 | QRspec_getEccSpec(i, (QRecLevel)j, spec); 24 | data = QRspec_rsBlockNum1(spec) * QRspec_rsDataCodes1(spec) 25 | + QRspec_rsBlockNum2(spec) * QRspec_rsDataCodes2(spec); 26 | ecc = QRspec_rsBlockNum1(spec) * QRspec_rsEccCodes1(spec) 27 | + QRspec_rsBlockNum2(spec) * QRspec_rsEccCodes2(spec); 28 | printf("%3d\t", data); 29 | printf("%3d\t", ecc); 30 | printf("%2d\t", QRspec_rsBlockNum1(spec)); 31 | printf("(%3d, %3d, %3d)\n", 32 | QRspec_rsDataCodes1(spec) + QRspec_rsEccCodes1(spec), 33 | QRspec_rsDataCodes1(spec), 34 | QRspec_rsEccCodes1(spec)); 35 | if(QRspec_rsBlockNum2(spec) > 0) { 36 | printf("\t%2d\t", QRspec_rsBlockNum2(spec)); 37 | printf("(%3d, %3d, %3d)\n", 38 | QRspec_rsDataCodes2(spec) + QRspec_rsEccCodes2(spec), 39 | QRspec_rsDataCodes2(spec), 40 | QRspec_rsEccCodes2(spec)); 41 | } 42 | } 43 | } 44 | } 45 | 46 | static void test_eccTable(void) 47 | { 48 | int i, j; 49 | int ecc; 50 | int data; 51 | int err = 0; 52 | int spec[5]; 53 | 54 | testStart("Checking ECC table."); 55 | for(i=1; i<=QRSPEC_VERSION_MAX; i++) { 56 | for(j=0; j<4; j++) { 57 | QRspec_getEccSpec(i, (QRecLevel)j, spec); 58 | data = QRspec_rsBlockNum1(spec) * QRspec_rsDataCodes1(spec) 59 | + QRspec_rsBlockNum2(spec) * QRspec_rsDataCodes2(spec); 60 | ecc = QRspec_rsBlockNum1(spec) * QRspec_rsEccCodes1(spec) 61 | + QRspec_rsBlockNum2(spec) * QRspec_rsEccCodes2(spec); 62 | if(data + ecc != QRspec_getDataLength(i, (QRecLevel)j) + QRspec_getECCLength(i, (QRecLevel)j)) { 63 | printf("Error in version %d, level %d: invalid size\n", i, j); 64 | printf("%d %d %d %d %d %d\n", spec[0], spec[1], spec[2], spec[3], spec[4], spec[2]); 65 | err++; 66 | } 67 | if(ecc != QRspec_getECCLength(i, (QRecLevel)j)) { 68 | printf("Error in version %d, level %d: invalid data\n", i, j); 69 | printf("%d %d %d %d %d %d\n", spec[0], spec[1], spec[2], spec[3], spec[4], spec[2]); 70 | err++; 71 | } 72 | } 73 | } 74 | testEnd(err); 75 | } 76 | 77 | static void test_eccTable2(void) 78 | { 79 | int i; 80 | int spec[5]; 81 | 82 | const int correct[7][6] = { 83 | { 8, 1, 0, 2, 60, 38}, 84 | { 8, 1, 1, 2, 61, 39}, 85 | {24, 2, 0, 11, 54, 24}, 86 | {24, 2, 1, 16, 55, 25}, 87 | {32, 0, 0, 17, 145, 115}, 88 | {40, 3, 0, 20, 45, 15}, 89 | {40, 3, 1, 61, 46, 16}, 90 | }; 91 | 92 | testStart("Checking ECC table(2)"); 93 | for(i=0; i<7; i++) { 94 | QRspec_getEccSpec(correct[i][0], (QRecLevel)correct[i][1], spec); 95 | if(correct[i][2] == 0) { 96 | assert_equal(QRspec_rsBlockNum1(spec), correct[i][3], 97 | "Error in version %d, level %d. rsBlockNum1 was %d, expected %d.\n", 98 | correct[i][0], correct[i][1], 99 | QRspec_rsBlockNum1(spec), correct[i][3]); 100 | assert_equal(QRspec_rsDataCodes1(spec) + QRspec_rsEccCodes1(spec), correct[i][4], 101 | "Error in version %d, level %d. rsDataCodes1 + rsEccCodes1 was %d, expected %d.\n", 102 | correct[i][0], correct[i][1], 103 | QRspec_rsDataCodes1(spec) + QRspec_rsEccCodes1(spec), correct[i][4]); 104 | assert_equal(QRspec_rsDataCodes1(spec), correct[i][5], 105 | "Error in version %d, level %d. rsDataCodes1 was %d, expected %d.\n", 106 | correct[i][0], correct[i][1], 107 | QRspec_rsDataCodes1(spec), correct[i][5]); 108 | } else { 109 | assert_equal(QRspec_rsBlockNum2(spec), correct[i][3], 110 | "Error in version %d, level %d. rsBlockNum2 was %d, expected %d.\n", 111 | correct[i][0], correct[i][1], 112 | QRspec_rsBlockNum2(spec), correct[i][3]); 113 | assert_equal(QRspec_rsDataCodes2(spec) + QRspec_rsEccCodes2(spec), correct[i][4], 114 | "Error in version %d, level %d. rsDataCodes2 + rsEccCodes2 was %d, expected %d.\n", 115 | correct[i][0], correct[i][1], 116 | QRspec_rsDataCodes2(spec) + QRspec_rsEccCodes2(spec), correct[i][4]); 117 | assert_equal(QRspec_rsDataCodes2(spec), correct[i][5], 118 | "Error in version %d, level %d. rsDataCodes2 was %d, expected %d.\n", 119 | correct[i][0], correct[i][1], 120 | QRspec_rsDataCodes2(spec), correct[i][5]); 121 | } 122 | } 123 | testFinish(); 124 | } 125 | 126 | static void test_newframe(void) 127 | { 128 | unsigned char buf[QRSPEC_WIDTH_MAX * QRSPEC_WIDTH_MAX]; 129 | int i, width; 130 | size_t len; 131 | FILE *fp; 132 | unsigned char *frame; 133 | QRcode *qrcode; 134 | int version; 135 | 136 | testStart("Checking newly created frame."); 137 | fp = fopen(SRCDIR "frame", "rb"); 138 | if(fp == NULL) { 139 | perror("Failed to open \"" SRCDIR "frame\":"); 140 | abort(); 141 | } 142 | for(i=1; i<=QRSPEC_VERSION_MAX; i++) { 143 | frame = QRspec_newFrame(i); 144 | width = QRspec_getWidth(i); 145 | len = fread(buf, 1, width * width, fp); 146 | if((int)len != width * width) { 147 | perror("Failed to read the pattern file:"); 148 | abort(); 149 | } 150 | assert_zero(memcmp(frame, buf, len), "frame pattern mismatch (version %d)\n", i); 151 | qrcode = QRcode_new(i, width, frame); 152 | version = QRcode_decodeVersion(qrcode); 153 | assert_equal(version, i, "Decoded version number is wrong: %d, expected %d.\n", version, i); 154 | QRcode_free(qrcode); 155 | } 156 | 157 | testFinish(); 158 | fclose(fp); 159 | } 160 | 161 | static void test_newframe_invalid(void) 162 | { 163 | unsigned char *frame; 164 | 165 | testStart("Checking QRspec_newFrame with invalid version."); 166 | frame = QRspec_newFrame(0); 167 | assert_null(frame, "QRspec_newFrame(0) returns non-NULL."); 168 | frame = QRspec_newFrame(QRSPEC_VERSION_MAX+1); 169 | assert_null(frame, "QRspec_newFrame(0) returns non-NULL."); 170 | testFinish(); 171 | } 172 | 173 | #if 0 174 | /* This test is used to check positions of alignment pattern. See Appendix E 175 | * (p.71) of JIS X0510:2004 and compare to the output. Before comment out 176 | * this test, change the value of the pattern marker's center dot from 0xa1 177 | * to 0xb1 (QRspec_putAlignmentMarker() : finder). 178 | */ 179 | static void test_alignment(void) 180 | { 181 | unsigned char *frame; 182 | int i, x, y, width, c; 183 | 184 | testStart("Checking alignment pattern."); 185 | for(i=2; i<=QRSPEC_VERSION_MAX; i++) { 186 | printf("%2d", i); 187 | frame = QRspec_newFrame(i); 188 | width = QRspec_getWidth(i); 189 | c = 0; 190 | for(x=0; x> 12) != (unsigned int)version) { 223 | printf("Error in version %d.\n", version); 224 | err++; 225 | continue; 226 | } 227 | mask = 0x40; 228 | for(i=0; mask != 0; i++) { 229 | if(version & mask) break; 230 | mask = mask >> 1; 231 | } 232 | c = 6 - i; 233 | data = version << 12; 234 | code = 0x1f25 << c; 235 | mask = 0x40000 >> (6 - c); 236 | for(i=0; i<=c; i++) { 237 | if(mask & data) { 238 | data ^= code; 239 | } 240 | code = code >> 1; 241 | mask = mask >> 1; 242 | } 243 | data = (version << 12) | (data & 0xfff); 244 | if(data != pattern) { 245 | printf("Error in version %d\n", version); 246 | err++; 247 | } 248 | } 249 | testEnd(err); 250 | } 251 | 252 | /* See Table 22 (p.45) and Appendix C (p. 65) of JIS X0510:2004 */ 253 | static unsigned int levelIndicator[4] = {1, 0, 3, 2}; 254 | static unsigned int calcFormatInfo(int mask, QRecLevel level) 255 | { 256 | unsigned int data, ecc, b, code; 257 | int i, c; 258 | 259 | data = (levelIndicator[level] << 13) | (mask << 10); 260 | ecc = data; 261 | b = 1 << 14; 262 | for(i=0; b != 0; i++) { 263 | if(ecc & b) break; 264 | b = b >> 1; 265 | } 266 | c = 4 - i; 267 | code = 0x537 << c ; //10100110111 268 | b = 1 << (10 + c); 269 | for(i=0; i<=c; i++) { 270 | if(b & ecc) { 271 | ecc ^= code; 272 | } 273 | code = code >> 1; 274 | b = b >> 1; 275 | } 276 | 277 | return (data | ecc) ^ 0x5412; 278 | } 279 | 280 | static void test_format(void) 281 | { 282 | unsigned int format; 283 | int i, j; 284 | int err = 0; 285 | 286 | testStart("Format info test"); 287 | for(i=0; i<4; i++) { 288 | for(j=0; j<8; j++) { 289 | format = calcFormatInfo(j, (QRecLevel)i); 290 | // printf("0x%04x, ", format); 291 | if(format != QRspec_getFormatInfo(j, (QRecLevel)i)) { 292 | printf("Level %d, mask %x\n", i, j); 293 | err++; 294 | } 295 | } 296 | // printf("\n"); 297 | } 298 | testEnd(err); 299 | } 300 | 301 | int main(int argc, char **argv) 302 | { 303 | int tests = 6; 304 | testInit(tests); 305 | test_eccTable(); 306 | test_eccTable2(); 307 | test_newframe(); 308 | test_newframe_invalid(); 309 | //test_alignment(); 310 | test_verpat(); 311 | test_format(); 312 | testReport(tests); 313 | 314 | if(argc > 1) { 315 | print_eccTable(); 316 | } 317 | 318 | return 0; 319 | } 320 | -------------------------------------------------------------------------------- /tests/test_rs.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "common.h" 4 | #include "../qrencode_inner.h" 5 | #include "../qrspec.h" 6 | #include "../mqrspec.h" 7 | #include "../qrinput.h" 8 | #include "../rsecc.h" 9 | #include "decoder.h" 10 | #include "rsecc_decoder.h" 11 | #include "rscode.h" 12 | 13 | /* See pp. 73 of JIS X0510:2004 */ 14 | void test_rscodeexample(void) 15 | { 16 | QRinput *stream; 17 | QRRawCode *code; 18 | static const char str[9] = "01234567"; 19 | static unsigned char correct[26] = { 20 | 0x10, 0x20, 0x0c, 0x56, 0x61, 0x80, 0xec, 0x11, 0xec, 0x11, 0xec, 0x11, 21 | 0xec, 0x11, 0xec, 0x11, 0xa5, 0x24, 0xd4, 0xc1, 0xed, 0x36, 0xc7, 0x87, 22 | 0x2c, 0x55}; 23 | 24 | testStart("RS ecc test"); 25 | stream = QRinput_new(); 26 | QRinput_append(stream, QR_MODE_NUM, 8, (unsigned char *)str); 27 | QRinput_setErrorCorrectionLevel(stream, QR_ECLEVEL_M); 28 | code = QRraw_new(stream); 29 | 30 | testEnd(memcmp(correct + 16, code->rsblock[0].ecc, 10)); 31 | QRinput_free(stream); 32 | QRraw_free(code); 33 | } 34 | 35 | static void compareRS(unsigned char data[]) 36 | { 37 | int i, j; 38 | RS *rs; 39 | int spec[5]; 40 | int dl, el; 41 | unsigned char ecc_expected[256], ecc_rscodec[256]; 42 | 43 | for(i = 1; i <= QRSPEC_VERSION_MAX; i++) { 44 | for(j = QR_ECLEVEL_L; j <= QR_ECLEVEL_H; j++) { 45 | QRspec_getEccSpec(i, (QRecLevel)j, spec); 46 | dl = QRspec_rsDataCodes1(spec); 47 | el = QRspec_rsEccCodes1(spec); 48 | rs = init_rs(8, 0x11d, 0, 1, el, 255 - dl - el); 49 | RSECC_encode(dl, el, data, ecc_rscodec); 50 | encode_rs_char(rs, data, ecc_expected); 51 | assert_zero(memcmp(ecc_expected, ecc_rscodec, el), "Invalid ECC found: length %d.\n", el); 52 | assert_zero(RSECC_decoder_checkSyndrome(dl, data, el, ecc_rscodec), "ECC error found."); 53 | free_rs_char(rs); 54 | 55 | 56 | dl = QRspec_rsDataCodes2(spec); 57 | el = QRspec_rsEccCodes2(spec); 58 | if(dl != 0) { 59 | rs = init_rs(8, 0x11d, 0, 1, el, 255 - dl - el); 60 | RSECC_encode(dl, el, data, ecc_rscodec); 61 | encode_rs_char(rs, data, ecc_expected); 62 | assert_zero(memcmp(ecc_expected, ecc_rscodec, el), "Invalid ECC found: length %d.\n", el); 63 | assert_zero(RSECC_decoder_checkSyndrome(dl, data, el, ecc_rscodec), "ECC error found."); 64 | free_rs_char(rs); 65 | } 66 | } 67 | } 68 | } 69 | 70 | static void compareRSMQR(unsigned char data[]) 71 | { 72 | int i, j; 73 | RS *rs; 74 | int dl, el; 75 | unsigned char ecc_expected[256], ecc_rscodec[256]; 76 | 77 | for(i = 1; i <= MQRSPEC_VERSION_MAX; i++) { 78 | for(j = QR_ECLEVEL_L; j <= QR_ECLEVEL_Q; j++) { 79 | dl = MQRspec_getDataLength(i, (QRecLevel)j); 80 | el = MQRspec_getECCLength(i, (QRecLevel)j); 81 | if(dl != 0) { 82 | rs = init_rs(8, 0x11d, 0, 1, el, 255 - dl - el); 83 | RSECC_encode(dl, el, data, ecc_rscodec); 84 | encode_rs_char(rs, data, ecc_expected); 85 | assert_zero(memcmp(ecc_expected, ecc_rscodec, el), "Invalid ECC found: length %d.\n", el); 86 | assert_zero(RSECC_decoder_checkSyndrome(dl, data, el, ecc_rscodec), "ECC error found."); 87 | free_rs_char(rs); 88 | } 89 | } 90 | } 91 | } 92 | 93 | void test_allQRSizeAndECCLevel(void) 94 | { 95 | int i; 96 | unsigned char data[256]; 97 | 98 | testStart("Comparing with KA9Q's code: all QR Code sizes and ECC levels"); 99 | memset(data, 0, 256); 100 | compareRS(data); 101 | compareRSMQR(data); 102 | memset(data, 0xaa, 256); 103 | compareRS(data); 104 | compareRSMQR(data); 105 | memset(data, 0xff, 256); 106 | compareRS(data); 107 | compareRSMQR(data); 108 | for(i=0; i<256; i++) { 109 | data[i] = i; 110 | } 111 | compareRS(data); 112 | compareRSMQR(data); 113 | testFinish(); 114 | } 115 | 116 | int main() 117 | { 118 | RSECC_decoder_init(); 119 | int tests = 2; 120 | testInit(tests); 121 | test_rscodeexample(); 122 | test_allQRSizeAndECCLevel(); 123 | testReport(tests); 124 | 125 | return 0; 126 | } 127 | -------------------------------------------------------------------------------- /tests/test_split_urls.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "common.h" 5 | #include "../qrinput.h" 6 | #include "../qrencode_inner.h" 7 | #include "../split.h" 8 | #include "decoder.h" 9 | 10 | #include "URI_testset.inc" 11 | 12 | #if 0 13 | static void encodeURLandPrint(char *url) { 14 | QRinput *input; 15 | BitStream *bstream; 16 | 17 | input = QRinput_new2(0, QR_ECLEVEL_L); 18 | Split_splitStringToQRinput(url, input, QR_MODE_8, 1); 19 | bstream = BitStream_new(); 20 | QRinput_mergeBitStream(input, bstream); 21 | 22 | printf("{%zu,\"%s\"},\n", BitStream_size(bstream), url); 23 | 24 | QRinput_free(input); 25 | BitStream_free(bstream); 26 | } 27 | 28 | static void print_currentBitLength() { 29 | struct TestSet *ts = testset; 30 | 31 | puts("struct TestSet {\n\tint expected_length;\n\tchar *url;\n};"); 32 | puts("\nstruct TestSet testset[] = {"); 33 | 34 | while(ts->url != NULL) { 35 | encodeURLandPrint(ts->url); 36 | ts++; 37 | } 38 | 39 | puts("{0,NULL}\n};"); 40 | } 41 | #endif 42 | 43 | static int encodeURLandCompare(char *url, size_t expected_length) { 44 | QRinput *input; 45 | BitStream *bstream; 46 | int ret = 0; 47 | 48 | input = QRinput_new2(0, QR_ECLEVEL_L); 49 | Split_splitStringToQRinput(url, input, QR_MODE_8, 1); 50 | bstream = BitStream_new(); 51 | QRinput_mergeBitStream(input, bstream); 52 | 53 | size_t length = BitStream_size(bstream); 54 | if(length > expected_length) { 55 | printf("The length of the encode stream is longer than expected: %zu over %zu\n", length, expected_length); 56 | printQRinput(input); 57 | 58 | ret = 1; 59 | } else if(length < expected_length) { 60 | printf("The length of the encode stream is shorter than expected: %zu under %zu\n", length, expected_length); 61 | printQRinput(input); 62 | 63 | ret = 1; 64 | } 65 | 66 | QRinput_free(input); 67 | BitStream_free(bstream); 68 | 69 | return ret; 70 | } 71 | 72 | static void test_bitstream_length() { 73 | struct TestSet *ts = testset; 74 | int err = 0; 75 | 76 | testStart("Split_URL test: compare bitstream length"); 77 | while(ts->url != NULL) { 78 | err += encodeURLandCompare(ts->url, ts->expected_length); 79 | ts++; 80 | } 81 | testEnd(err); 82 | } 83 | 84 | int main() 85 | { 86 | int tests = 1; 87 | testInit(tests); 88 | test_bitstream_length(); 89 | testReport(tests); 90 | 91 | return 0; 92 | } 93 | --------------------------------------------------------------------------------