forked from zxing-cpp/zxing-cpp
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Writer: implement new experimental API (Create + Write)
This adds two new operations 'create' and 'write' next to the existing 'read'. Each new operation is accompanied by an Options class: * ReadBarcodes(..., ReaderOptions) * CreateBarcodeFromText(..., CreatorOptions) * WriteBarcodeToImage(..., WriterOptions) Background info can be found here: * zxing-cpp#724 * zxing-cpp#739
- Loading branch information
Showing
8 changed files
with
381 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
/* | ||
* Copyright 2024 Axel Waggershauser | ||
*/ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
#ifdef ZXING_BUILD_EXPERIMENTAL_API | ||
|
||
#include "WriteBarcode.h" | ||
|
||
struct zint_symbol {}; | ||
|
||
namespace ZXing { | ||
|
||
struct CreatorOptions::Data | ||
{ | ||
BarcodeFormat format; | ||
bool readerInit = false; | ||
bool forceSquareDataMatrix = false; | ||
std::string ecLevel; | ||
|
||
// symbol size (qrcode, datamatrix, etc), map from I, 'WxH' | ||
// structured_append (idx, cnt, ID) | ||
|
||
mutable std::unique_ptr<zint_symbol> zint; | ||
}; | ||
|
||
#define ZX_PROPERTY(TYPE, NAME) \ | ||
TYPE CreatorOptions::NAME() const noexcept { return d->NAME; } \ | ||
CreatorOptions& CreatorOptions::NAME(TYPE v)& { return d->NAME = std::move(v), *this; } \ | ||
CreatorOptions&& CreatorOptions::NAME(TYPE v)&& { return d->NAME = std::move(v), std::move(*this); } | ||
|
||
ZX_PROPERTY(BarcodeFormat, format) | ||
ZX_PROPERTY(bool, readerInit) | ||
ZX_PROPERTY(bool, forceSquareDataMatrix) | ||
ZX_PROPERTY(std::string, ecLevel) | ||
|
||
#undef ZX_PROPERTY | ||
|
||
CreatorOptions::CreatorOptions(BarcodeFormat format) : d(std::make_unique<Data>(format)) {} | ||
CreatorOptions::~CreatorOptions() = default; | ||
CreatorOptions::CreatorOptions(CreatorOptions&&) = default; | ||
CreatorOptions& CreatorOptions::operator=(CreatorOptions&&) = default; | ||
|
||
|
||
struct WriterOptions::Data | ||
{ | ||
int scale = 0; | ||
int sizeHint = 0; | ||
int rotate = 0; | ||
bool withHRT = false; | ||
bool withQuietZones = true; | ||
}; | ||
|
||
#define ZX_PROPERTY(TYPE, NAME) \ | ||
TYPE WriterOptions::NAME() const noexcept { return d->NAME; } \ | ||
WriterOptions& WriterOptions::NAME(TYPE v)& { return d->NAME = std::move(v), *this; } \ | ||
WriterOptions&& WriterOptions::NAME(TYPE v)&& { return d->NAME = std::move(v), std::move(*this); } | ||
|
||
ZX_PROPERTY(int, scale) | ||
ZX_PROPERTY(int, sizeHint) | ||
ZX_PROPERTY(int, rotate) | ||
ZX_PROPERTY(bool, withHRT) | ||
ZX_PROPERTY(bool, withQuietZones) | ||
|
||
#undef ZX_PROPERTY | ||
|
||
WriterOptions::WriterOptions() : d(std::make_unique<Data>()) {} | ||
WriterOptions::~WriterOptions() = default; | ||
WriterOptions::WriterOptions(WriterOptions&&) = default; | ||
WriterOptions& WriterOptions::operator=(WriterOptions&&) = default; | ||
|
||
} // namespace ZXing | ||
|
||
|
||
#include "BitMatrix.h" | ||
#include "MultiFormatWriter.h" | ||
#include "ReadBarcode.h" | ||
|
||
namespace ZXing { | ||
|
||
static Barcode CreateBarcode(BitMatrix&& bits, const CreatorOptions& opts) | ||
{ | ||
auto img = ToMatrix<uint8_t>(bits); | ||
|
||
auto res = ReadBarcode({img.data(), img.width(), img.height(), ImageFormat::Lum}, | ||
ReaderOptions().setFormats(opts.format()).setIsPure(true).setBinarizer(Binarizer::BoolCast)); | ||
res.symbol(std::move(bits)); | ||
return res; | ||
} | ||
|
||
static bool IsLinearCode(BarcodeFormat format) | ||
{ | ||
return BarcodeFormats(BarcodeFormat::LinearCodes).testFlag(format); | ||
} | ||
|
||
Barcode CreateBarcodeFromText(std::string_view contents, const CreatorOptions& opts) | ||
{ | ||
auto writer = MultiFormatWriter(opts.format()).setMargin(0); | ||
if (!opts.ecLevel().empty()) | ||
writer.setEccLevel(std::stoi(opts.ecLevel())); | ||
|
||
return CreateBarcode(writer.encode(std::string(contents), 0, IsLinearCode(opts.format()) ? 50 : 0), opts); | ||
} | ||
|
||
Barcode CreateBarcodeFromText(std::u8string_view contents, const CreatorOptions& opts) | ||
{ | ||
return CreateBarcodeFromText({reinterpret_cast<const char*>(contents.data()), contents.size()}, opts); | ||
} | ||
|
||
Barcode CreateBarcodeFromBytes(const void* data, int size, const CreatorOptions& opts) | ||
{ | ||
std::wstring bytes; | ||
for (uint8_t c : std::basic_string_view<uint8_t>((uint8_t*)data, size)) | ||
bytes.push_back(c); | ||
|
||
auto writer = MultiFormatWriter(opts.format()).setMargin(0); | ||
if (!opts.ecLevel().empty()) | ||
writer.setEccLevel(std::stoi(opts.ecLevel())); | ||
writer.setEncoding(CharacterSet::BINARY); | ||
|
||
return CreateBarcode(writer.encode(bytes, 0, IsLinearCode(opts.format()) ? 50 : 0), opts); | ||
} | ||
|
||
std::string WriteBarcodeToSVG(const Barcode& barcode, [[maybe_unused]] const WriterOptions& opts) | ||
{ | ||
return ToSVG(barcode.symbol()); | ||
} | ||
|
||
Image WriteBarcodeToImage(const Barcode& barcode, [[maybe_unused]] const WriterOptions& opts) | ||
{ | ||
auto symbol = Inflate(barcode.symbol().copy(), opts.sizeHint(), | ||
IsLinearCode(barcode.format()) ? std::clamp(opts.sizeHint() / 2, 50, 300) : opts.sizeHint(), | ||
opts.withQuietZones() ? 10 : 0); | ||
auto bitmap = ToMatrix<uint8_t>(symbol); | ||
auto iv = Image(symbol.width(), symbol.height()); | ||
std::memcpy(const_cast<uint8_t*>(iv.data()), bitmap.data(), iv.width() * iv.height()); | ||
return iv; | ||
} | ||
|
||
} // namespace ZXing | ||
|
||
#endif // ZXING_BUILD_EXPERIMENTAL_API |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
/* | ||
* Copyright 2022 Axel Waggershauser | ||
*/ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
#pragma once | ||
|
||
#ifdef ZXING_BUILD_EXPERIMENTAL_API | ||
|
||
#include "Barcode.h" | ||
#include "ImageView.h" | ||
|
||
#include <memory> | ||
#include <string_view> | ||
|
||
extern "C" struct zint_symbol; | ||
|
||
namespace ZXing { | ||
|
||
class CreatorOptions | ||
{ | ||
struct Data; | ||
|
||
std::unique_ptr<Data> d; | ||
|
||
friend Barcode CreateBarcode(const void* data, int size, int mode, const CreatorOptions& options); | ||
|
||
public: | ||
CreatorOptions(BarcodeFormat format); | ||
|
||
~CreatorOptions(); | ||
CreatorOptions(CreatorOptions&&); | ||
CreatorOptions& operator=(CreatorOptions&&); | ||
|
||
zint_symbol* zint() const; | ||
|
||
#define ZX_PROPERTY(TYPE, NAME) \ | ||
TYPE NAME() const noexcept; \ | ||
CreatorOptions& NAME(TYPE v)&; \ | ||
CreatorOptions&& NAME(TYPE v)&&; | ||
|
||
ZX_PROPERTY(BarcodeFormat, format) | ||
ZX_PROPERTY(bool, readerInit) | ||
ZX_PROPERTY(bool, forceSquareDataMatrix) | ||
ZX_PROPERTY(std::string, ecLevel) | ||
|
||
#undef ZX_PROPERTY | ||
}; | ||
|
||
/** | ||
* Generate barcode from unicode text | ||
* | ||
* @param contents UTF-8 string to encode into a barcode | ||
* @param options CreatorOptions (including BarcodeFormat) | ||
* @return #Barcode generated barcode | ||
*/ | ||
Barcode CreateBarcodeFromText(std::string_view contents, const CreatorOptions& options); | ||
|
||
/** | ||
* Generate barcode from raw binary data | ||
* | ||
* @param data array of bytes to encode into a barcode | ||
* @param size size of byte array | ||
* @param options CreatorOptions (including BarcodeFormat) | ||
* @return #Barcode generated barcode | ||
*/ | ||
Barcode CreateBarcodeFromBytes(const void* data, int size, const CreatorOptions& options); | ||
|
||
#if __cplusplus > 201703L | ||
Barcode CreateBarcodeFromText(std::u8string_view contents, const CreatorOptions& options); | ||
|
||
template <typename R> | ||
requires std::ranges::contiguous_range<R> && std::ranges::sized_range<R> && (sizeof(std::ranges::range_value_t<R>) == 1) | ||
Barcode CreateBarcodeFromBytes(const R& contents, const CreatorOptions& options) | ||
{ | ||
return CreateBarcodeFromBytes(std::ranges::data(contents), std::ranges::size(contents), options); | ||
} | ||
#endif | ||
|
||
// ================================================================================= | ||
|
||
class WriterOptions | ||
{ | ||
struct Data; | ||
|
||
std::unique_ptr<Data> d; | ||
|
||
public: | ||
WriterOptions(); | ||
~WriterOptions(); | ||
WriterOptions(WriterOptions&&); | ||
WriterOptions& operator=(WriterOptions&&); | ||
|
||
#define ZX_PROPERTY(TYPE, NAME) \ | ||
TYPE NAME() const noexcept; \ | ||
WriterOptions& NAME(TYPE v)&; \ | ||
WriterOptions&& NAME(TYPE v)&&; | ||
|
||
ZX_PROPERTY(int, scale) | ||
ZX_PROPERTY(int, sizeHint) | ||
ZX_PROPERTY(int, rotate) | ||
ZX_PROPERTY(bool, withHRT) | ||
ZX_PROPERTY(bool, withQuietZones) | ||
|
||
#undef ZX_PROPERTY | ||
}; | ||
|
||
|
||
/** | ||
* Write barcode symbol to SVG | ||
* | ||
* @param barcode Barcode to write | ||
* @param options WriterOptions to parameterize rendering | ||
* @return std::string SVG representation of barcode symbol | ||
*/ | ||
std::string WriteBarcodeToSVG(const Barcode& barcode, const WriterOptions& options = {}); | ||
|
||
/** | ||
* Write barcode symbol to Image (Bitmap) | ||
* | ||
* @param barcode Barcode to write | ||
* @param options WriterOptions to parameterize rendering | ||
* @return Image Bitmap reprentation of barcode symbol | ||
*/ | ||
Image WriteBarcodeToImage(const Barcode& barcode, const WriterOptions& options = {}); | ||
|
||
} // ZXing | ||
|
||
#endif // ZXING_BUILD_EXPERIMENTAL_API |
Oops, something went wrong.