/* * Copyright 2016 Huy Cuong Nguyen * Copyright 2016 ZXing authors */ // SPDX-License-Identifier: Apache-2.0 #include "PDFWriter.h" #include "PDFEncoder.h" #include "BitMatrix.h" #include "Utf.h" #include namespace ZXing { namespace Pdf417 { /** * default white space (margin) around the code */ static const int WHITE_SPACE = 30; /** * default error correction level */ static const int DEFAULT_ERROR_CORRECTION_LEVEL = 2; /** * Takes and rotates the it 90 degrees */ static void RotateArray(const std::vector>& input, std::vector>& output) { size_t height = input.size(); size_t width = input[0].size(); output.resize(width); for (size_t i = 0; i < width; ++i) { output[i].resize(height); } for (size_t ii = 0; ii < height; ++ii) { // This makes the direction consistent on screen when rotating the screen size_t inverseii = height - ii - 1; for (size_t jj = 0; jj < width; ++jj) { output[jj][inverseii] = input[ii][jj]; } } } /** * This takes an array holding the values of the PDF 417 * * @param input a byte array of information with 0 is black, and 1 is white * @param margin border around the barcode * @return BitMatrix of the input */ static BitMatrix BitMatrixFromBitArray(const std::vector>& input, int margin) { // Creates the bitmatrix with extra space for whitespace int width = Size(input[0]); int height = Size(input); BitMatrix result(width + 2 * margin, height + 2 * margin); for (int y = 0, yOutput = static_cast(result.height()) - margin - 1; y < height; y++, yOutput--) { for (int x = 0; x < width; ++x) { // Zero is white in the bytematrix if (input[y][x]) { result.set(x + margin, yOutput); } } } return result; } BitMatrix Writer::encode(const std::wstring& contents, int width, int height) const { int margin = _margin >= 0 ? _margin : WHITE_SPACE; int ecLevel = _ecLevel >= 0 ? _ecLevel : DEFAULT_ERROR_CORRECTION_LEVEL; BarcodeMatrix resultMatrix = _encoder->generateBarcodeLogic(contents, ecLevel); int aspectRatio = 4; // keep in sync with MODULE_RATIO in PDFEncoder.cpp std::vector> originalScale; resultMatrix.getScaledMatrix(1, aspectRatio, originalScale); bool rotated = false; if ((height > width) != (originalScale[0].size() < originalScale.size())) { std::vector> temp; RotateArray(originalScale, temp); originalScale = temp; rotated = true; } int scaleX = width / Size(originalScale[0]); int scaleY = height / Size(originalScale); int scale; if (scaleX < scaleY) { scale = scaleX; } else { scale = scaleY; } if (scale > 1) { std::vector> scaledMatrix; resultMatrix.getScaledMatrix(scale, scale * aspectRatio, scaledMatrix); if (rotated) { std::vector> temp; RotateArray(scaledMatrix, temp); scaledMatrix = temp; } return BitMatrixFromBitArray(scaledMatrix, margin); } else { return BitMatrixFromBitArray(originalScale, margin); } } BitMatrix Writer::encode(const std::string& contents, int width, int height) const { return encode(FromUtf8(contents), width, height); } Writer::Writer() { _encoder.reset(new Encoder); } Writer::Writer(Writer &&other) noexcept: _margin(other._margin), _ecLevel(other._ecLevel), _encoder(std::move(other._encoder)) { } Writer::~Writer() { } Writer& Writer::setDimensions(int minCols, int maxCols, int minRows, int maxRows) { _encoder->setDimensions(minCols, maxCols, minRows, maxRows); return *this; } Writer& Writer::setCompaction(Compaction compaction) { _encoder->setCompaction(compaction); return *this; } /** * @param compact if true, enables compaction */ Writer& Writer::setCompact(bool compact) { _encoder->setCompact(compact); return *this; } /** * @param encoding sets character encoding to use */ Writer& Writer::setEncoding(CharacterSet encoding) { _encoder->setEncoding(encoding); return *this; } } // Pdf417 } // ZXing