Files
ANSLibs/QRCode/datamatrix/DMWriter.cpp

121 lines
3.3 KiB
C++
Raw Normal View History

/*
* Copyright 2016 Huy Cuong Nguyen
* Copyright 2016 ZXing authors
*/
// SPDX-License-Identifier: Apache-2.0
#include "DMWriter.h"
#include "BitMatrix.h"
#include "ByteArray.h"
#include "CharacterSet.h"
#include "DMBitLayout.h"
#include "DMECEncoder.h"
#include "DMHighLevelEncoder.h"
#include "DMSymbolInfo.h"
#include "Utf.h"
#include <stdexcept>
#include <string>
#include <utility>
namespace ZXing::DataMatrix {
/**
* Encode the given symbol info to a bit matrix.
*
* @param placement The DataMatrix placement.
* @param symbolInfo The symbol info to encode.
* @return The bit matrix generated.
*/
static BitMatrix EncodeLowLevel(const BitMatrix& placement, const SymbolInfo& symbolInfo) {
int symbolWidth = symbolInfo.symbolDataWidth();
int symbolHeight = symbolInfo.symbolDataHeight();
BitMatrix matrix(symbolInfo.symbolWidth(), symbolInfo.symbolHeight());
int matrixY = 0;
for (int y = 0; y < symbolHeight; y++) {
// Fill the top edge with alternate 0 / 1
int matrixX;
if ((y % symbolInfo.matrixHeight()) == 0) {
matrixX = 0;
for (int x = 0; x < matrix.width(); x++) {
matrix.set(matrixX, matrixY, (x % 2) == 0);
matrixX++;
}
matrixY++;
}
matrixX = 0;
for (int x = 0; x < symbolWidth; x++) {
// Fill the right edge with full 1
if ((x % symbolInfo.matrixWidth()) == 0) {
matrix.set(matrixX, matrixY, true);
matrixX++;
}
matrix.set(matrixX, matrixY, placement.get(x, y) == 1);
matrixX++;
// Fill the right edge with alternate 0 / 1
if ((x % symbolInfo.matrixWidth()) == symbolInfo.matrixWidth() - 1) {
matrix.set(matrixX, matrixY, (y % 2) == 0);
matrixX++;
}
}
matrixY++;
// Fill the bottom edge with full 1
if ((y % symbolInfo.matrixHeight()) == symbolInfo.matrixHeight() - 1) {
matrixX = 0;
for (int x = 0; x < matrix.width(); x++) {
matrix.set(matrixX, matrixY, true);
matrixX++;
}
matrixY++;
}
}
return matrix;
}
Writer::Writer() :
_shapeHint(SymbolShape::NONE),
_encoding(CharacterSet::Unknown)
{
}
BitMatrix
Writer::encode(const std::wstring& contents, int width, int height) const
{
if (contents.empty()) {
throw std::invalid_argument("Found empty contents");
}
if (width < 0 || height < 0) {
throw std::invalid_argument("Requested dimensions are invalid");
}
//1. step: Data encodation
auto encoded = Encode(contents, _encoding, _shapeHint, _minWidth, _minHeight, _maxWidth, _maxHeight);
const SymbolInfo* symbolInfo = SymbolInfo::Lookup(Size(encoded), _shapeHint, _minWidth, _minHeight, _maxWidth, _maxHeight);
if (symbolInfo == nullptr) {
throw std::invalid_argument("Can't find a symbol arrangement that matches the message. Data codewords: " + std::to_string(encoded.size()));
}
//2. step: ECC generation
EncodeECC200(encoded, *symbolInfo);
//3. step: Module placement in Matrix
BitMatrix symbolData = BitMatrixFromCodewords(encoded, symbolInfo->symbolDataWidth(), symbolInfo->symbolDataHeight());
//4. step: low-level encoding
BitMatrix result = EncodeLowLevel(symbolData, *symbolInfo);
//5. step: scale-up to requested size, minimum required quiet zone is 1
return Inflate(std::move(result), width, height, _quietZone);
}
BitMatrix Writer::encode(const std::string& contents, int width, int height) const
{
return encode(FromUtf8(contents), width, height);
}
} // namespace ZXing::DataMatrix