Skip to content

Commit

Permalink
Add option to change error correction level in MultiFormatWriter
Browse files Browse the repository at this point in the history
  • Loading branch information
huycn committed Jan 7, 2019
1 parent 46ed7a5 commit ee8b405
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 26 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ emmake make

See usage example of exported functions from a demo here: https://nu-book.github.io/zxing-cpp/demo.html.

By default, both encoder and decoder are included. If you don't plan to use either of them, you can disable it to reduce generated code size. To do so, in the line `emconfigure cmake ...` above, pass `-ENABLE_ENCODERS=0` to disable encoders or `-ENABLE_DECODERS=0` to disable decoders.

### For other platforms
Wrappers are provided as convenient way to work with native image format. You still can use the library without a wrapper.

Expand Down
45 changes: 38 additions & 7 deletions core/src/MultiFormatWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "datamatrix/DMWriter.h"
#include "pdf417/PDFWriter.h"
#include "qrcode/QRWriter.h"
#include "qrcode/QRErrorCorrectionLevel.h"
#include "oned/ODCodabarWriter.h"
#include "oned/ODCode39Writer.h"
#include "oned/ODCode93Writer.h"
Expand All @@ -34,12 +35,14 @@ namespace ZXing {

namespace {

template <typename Writer>
Writer CreateWriter(CharacterSet encoding)
template <typename Writer, typename EccConverter>
Writer CreateWriter(CharacterSet encoding, int eccLevel)
{
Writer writer;
if (encoding != CharacterSet::Unknown)
writer.setEncoding(encoding);
if (eccLevel >= 0 && eccLevel <= 8)
writer.setEccPercent(EccConverter()(eccLevel));
return writer;
}

Expand All @@ -52,17 +55,45 @@ namespace {
return writer;
}

template <typename Writer>
Writer CreateWriter(CharacterSet encoding, int margin)
template <typename Writer, typename EccConverter>
Writer CreateWriter(CharacterSet encoding, int margin, int eccLevel)
{
Writer writer;
if (encoding != CharacterSet::Unknown)
writer.setEncoding(encoding);
if (margin >= 0)
writer.setMargin(margin);
if (eccLevel >= 0 && eccLevel <= 8)
writer.setErrorCorrectionLevel(EccConverter()(eccLevel));
return writer;
}

struct AztecEccConverter {
int operator()(int eccLevel) const {
// Aztec supports levels 0 to 100 in percentage
return eccLevel * 100 / 8;
}
};

struct Pdf417EccConverter {
int operator()(int eccLevel) const {
return eccLevel;
}
};

struct QRCodeEccConverter {
QRCode::ErrorCorrectionLevel operator()(int eccPercent) const {
if (eccPercent <= 1)
return QRCode::ErrorCorrectionLevel::Low;
else if (eccPercent <= 4)
return QRCode::ErrorCorrectionLevel::Medium;
else if (eccPercent <= 6)
return QRCode::ErrorCorrectionLevel::Quality;
else
return QRCode::ErrorCorrectionLevel::High;
}
};

} // anonymous

BitMatrix
Expand All @@ -71,13 +102,13 @@ MultiFormatWriter::encode(const std::wstring& contents, int width, int height) c
switch (_format)
{
case BarcodeFormat::AZTEC:
return CreateWriter<Aztec::Writer>(_encoding).encode(contents, width, height);
return CreateWriter<Aztec::Writer, AztecEccConverter>(_encoding, _eccLevel).encode(contents, width, height);
case BarcodeFormat::DATA_MATRIX:
return DataMatrix::Writer().encode(contents, width, height);
case BarcodeFormat::PDF_417:
return CreateWriter<Pdf417::Writer>(_encoding, _margin).encode(contents, width, height);
return CreateWriter<Pdf417::Writer, Pdf417EccConverter>(_encoding, _margin, _eccLevel).encode(contents, width, height);
case BarcodeFormat::QR_CODE:
return CreateWriter<QRCode::Writer>(_encoding, _margin).encode(contents, width, height);
return CreateWriter<QRCode::Writer, QRCodeEccConverter>(_encoding, _margin, _eccLevel).encode(contents, width, height);
case BarcodeFormat::CODABAR:
return CreateWriter<OneD::CodabarWriter>(_margin).encode(contents, width, height);
case BarcodeFormat::CODE_39:
Expand Down
9 changes: 9 additions & 0 deletions core/src/MultiFormatWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ class MultiFormatWriter
return *this;
}

/**
* Used for Aztec, PDF417, and QRCode only, [0-8].
*/
MultiFormatWriter& setEccLevel(int level) {
_eccLevel = level;
return *this;
}

/**
* Used for all 1D formats, PDF417, and QRCode only.
*/
Expand All @@ -54,6 +62,7 @@ class MultiFormatWriter
BarcodeFormat _format;
CharacterSet _encoding = CharacterSet::Unknown;
int _margin = -1;
int _eccLevel = -1;
};

} // ZXing
19 changes: 16 additions & 3 deletions example/generate_png.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@ using namespace ZXing;

static void PrintUsage(const char* exePath)
{
std::cout << "Usage: " << exePath << " [-size <width>x<height>] [-margin <margin>] [-encoding <encoding>] <format> <text> <output>" << std::endl
std::cout << "Usage: " << exePath << " [-size <width>x<height>] [-margin <margin>] [-encoding <encoding>] [-ecc <level>] <format> <text> <output>" << std::endl
<< " -size Size of generated image" << std::endl
<< " -margin Margin around barcode" << std::endl
<< " -encoding Encoding used to encode input text" << std::endl
<< " -ecc Error correction level, [0-8]"
<< std::endl
<< "Supported formats are:" << std::endl
<< " AZTEC" << std::endl
Expand Down Expand Up @@ -84,7 +85,7 @@ static bool ParseSize(std::string str, int* width, int* height)
return false;
}

static bool ParseOptions(int argc, char* argv[], int* width, int* height, int* margin, std::string* format, std::string* text, std::string* filePath)
static bool ParseOptions(int argc, char* argv[], int* width, int* height, int* margin, int* eccLevel, std::string* format, std::string* text, std::string* filePath)
{
int nonOptArgCount = 0;
for (int i = 1; i < argc; ++i) {
Expand All @@ -109,6 +110,15 @@ static bool ParseOptions(int argc, char* argv[], int* width, int* height, int* m
return false;
}
}
else if (strcmp(argv[i], "-ecc") == 0) {
if (i + 1 < argc) {
++i;
*eccLevel = std::stoi(argv[i]);
}
else {
return false;
}
}
else if (nonOptArgCount == 0) {
*format = ParseFormat(argv[i]);
if (format->empty()) {
Expand Down Expand Up @@ -142,9 +152,10 @@ int main(int argc, char* argv[])

int width = 100, height = 100;
int margin = 10;
int eccLevel = -1;
std::string format, text, filePath;

if (!ParseOptions(argc, argv, &width, &height, &margin, &format, &text, &filePath)) {
if (!ParseOptions(argc, argv, &width, &height, &margin, &eccLevel, &format, &text, &filePath)) {
PrintUsage(argv[0]);
return -1;
}
Expand All @@ -157,6 +168,8 @@ int main(int argc, char* argv[])
MultiFormatWriter writer(barcodeFormat);
if (margin >= 0)
writer.setMargin(margin);
if (eccLevel >= 0)
writer.setEccLevel(eccLevel);

auto matrix = writer.encode(TextUtfEncoding::FromUtf8(text), width, height);

Expand Down
6 changes: 5 additions & 1 deletion wrappers/wasm/BarcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class WriteResult
}
};

WriteResult generateBarcode(std::wstring text, std::string format, std::string encoding, int margin, int width, int height)
WriteResult generateBarcode(std::wstring text, std::string format, std::string encoding, int margin, int width, int height, int eccLevel)
{
using namespace ZXing;
try {
Expand All @@ -63,6 +63,10 @@ WriteResult generateBarcode(std::wstring text, std::string format, std::string e
writer.setEncoding(charset);
}

if (eccLevel >= 0 && eccLevel <= 8) {
writer.setEccLevel(eccLevel);
}

auto matrix = writer.encode(text, width, height);

std::vector<unsigned char> buffer(matrix.width() * matrix.height(), '\0');
Expand Down
34 changes: 19 additions & 15 deletions wrappers/wasm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,12 @@ cmake_minimum_required (VERSION 3.1.3)

project (ZXingWasm)

set (ENABLE_ENCODERS ON CACHE INTERNAL "Check to include encoders")
set (ENABLE_DECODERS ON CACHE INTERNAL "Check to include decoders")
set (ENABLE_ENCODERS ON CACHE BOOL "Check to include encoders")
set (ENABLE_DECODERS ON CACHE BOOL "Check to include decoders")

add_definitions (-DUNICODE -D_UNICODE)

if (MSVC)
add_definitions (-D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS -DNOMINMAX)

set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Oi /GS-")
set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi /GS-")
else()
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
endif()
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")

include (CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG ("-std=c++11" COMPILER_SUPPORTS_CXX11)
Expand All @@ -27,12 +18,25 @@ endif()

add_subdirectory (${CMAKE_CURRENT_SOURCE_DIR}/../../core ${CMAKE_BINARY_DIR}/ZXingCore)

set (SOURCE_FILES lodepng.cpp)

if (ENABLE_DECODERS)
set (SOURCE_FILES ${SOURCE_FILES}
BarcodeReader.cpp
)
endif()

if (ENABLE_ENCODERS)
set (SOURCE_FILES ${SOURCE_FILES}
BarcodeWriter.cpp
)
endif()

add_executable (zxing
BarcodeReader.cpp
BarcodeWriter.cpp
${SOURCE_FILES}
lodepng.cpp
)

set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --bind -s DISABLE_EXCEPTION_CATCHING=0")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --bind -Oz -s DISABLE_EXCEPTION_CATCHING=0 -s FILESYSTEM=0")

target_link_libraries (zxing ZXingCore)

0 comments on commit ee8b405

Please sign in to comment.