Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/zxing-cpp/example/ZXingWriter.cpp @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /* | |
| 2 * Copyright 2016 Nu-book Inc. | |
| 3 */ | |
| 4 // SPDX-License-Identifier: Apache-2.0 | |
| 5 | |
| 6 #ifdef ZXING_EXPERIMENTAL_API | |
| 7 #include "WriteBarcode.h" | |
| 8 #else | |
| 9 #include "BitMatrix.h" | |
| 10 #include "BitMatrixIO.h" | |
| 11 #include "CharacterSet.h" | |
| 12 #include "MultiFormatWriter.h" | |
| 13 #endif | |
| 14 #include "Version.h" | |
| 15 | |
| 16 #include <algorithm> | |
| 17 #include <cctype> | |
| 18 #include <cstring> | |
| 19 #include <fstream> | |
| 20 #include <iostream> | |
| 21 #include <string> | |
| 22 | |
| 23 #define STB_IMAGE_WRITE_IMPLEMENTATION | |
| 24 #include <stb_image_write.h> | |
| 25 | |
| 26 using namespace ZXing; | |
| 27 | |
| 28 static void PrintUsage(const char* exePath) | |
| 29 { | |
| 30 std::cout << "Usage: " << exePath | |
| 31 << " [-size <width/height>] [-eclevel <level>] [-noqz] [-hrt] <format> <text> <output>\n" | |
| 32 << " -size Size of generated image\n" | |
| 33 // << " -margin Margin around barcode\n" | |
| 34 // << " -encoding Encoding used to encode input text\n" | |
| 35 << " -eclevel Error correction level, [0-8]\n" | |
| 36 << " -binary Interpret <text> as a file name containing binary data\n" | |
| 37 << " -noqz Print barcode witout quiet zone\n" | |
| 38 << " -hrt Print human readable text below the barcode (if supported)\n" | |
| 39 << " -help Print usage information\n" | |
| 40 << " -version Print version information\n" | |
| 41 << "\n" | |
| 42 << "Supported formats are:\n"; | |
| 43 #ifdef ZXING_EXPERIMENTAL_API | |
| 44 for (auto f : BarcodeFormats::all()) | |
| 45 #else | |
| 46 for (auto f : BarcodeFormatsFromString("Aztec Codabar Code39 Code93 Code128 DataMatrix EAN8 EAN13 ITF PDF417 QRCode UPCA UPCE")) | |
| 47 #endif | |
| 48 std::cout << " " << ToString(f) << "\n"; | |
| 49 | |
| 50 std::cout << "Format can be lowercase letters, with or without '-'.\n" | |
| 51 << "Output format is determined by file name, supported are png, jpg and svg.\n"; | |
| 52 } | |
| 53 | |
| 54 static bool ParseSize(std::string str, int* width, int* height) | |
| 55 { | |
| 56 std::transform(str.begin(), str.end(), str.begin(), [](char c) { return (char)std::tolower(c); }); | |
| 57 auto xPos = str.find('x'); | |
| 58 if (xPos != std::string::npos) { | |
| 59 *width = std::stoi(str.substr(0, xPos)); | |
| 60 *height = std::stoi(str.substr(xPos + 1)); | |
| 61 return true; | |
| 62 } | |
| 63 return false; | |
| 64 } | |
| 65 | |
| 66 struct CLI | |
| 67 { | |
| 68 BarcodeFormat format; | |
| 69 int sizeHint = 0; | |
| 70 std::string input; | |
| 71 std::string outPath; | |
| 72 std::string ecLevel; | |
| 73 bool inputIsFile = false; | |
| 74 bool withHRT = false; | |
| 75 bool withQZ = true; | |
| 76 bool verbose = false; | |
| 77 // CharacterSet encoding = CharacterSet::Unknown; | |
| 78 }; | |
| 79 | |
| 80 static bool ParseOptions(int argc, char* argv[], CLI& cli) | |
| 81 { | |
| 82 int nonOptArgCount = 0; | |
| 83 for (int i = 1; i < argc; ++i) { | |
| 84 auto is = [&](const char* str) { return strncmp(argv[i], str, strlen(argv[i])) == 0; }; | |
| 85 if (is("-size")) { | |
| 86 if (++i == argc) | |
| 87 return false; | |
| 88 cli.sizeHint = std::stoi(argv[i]); | |
| 89 } else if (is("-eclevel")) { | |
| 90 if (++i == argc) | |
| 91 return false; | |
| 92 cli.ecLevel = argv[i]; | |
| 93 // } else if (is("-margin")) { | |
| 94 // if (++i == argc) | |
| 95 // return false; | |
| 96 // cli.margin = std::stoi(argv[i]); | |
| 97 // } else if (is("-encoding")) { | |
| 98 // if (++i == argc) | |
| 99 // return false; | |
| 100 // cli.encoding = CharacterSetFromString(argv[i]); | |
| 101 } else if (is("-binary")) { | |
| 102 cli.inputIsFile = true; | |
| 103 } else if (is("-hrt")) { | |
| 104 cli.withHRT = true; | |
| 105 } else if (is("-noqz")) { | |
| 106 cli.withQZ = false; | |
| 107 } else if (is("-verbose")) { | |
| 108 cli.verbose = true; | |
| 109 } else if (is("-help") || is("--help")) { | |
| 110 PrintUsage(argv[0]); | |
| 111 exit(0); | |
| 112 } else if (is("-version") || is("--version")) { | |
| 113 std::cout << "ZXingWriter " << ZXING_VERSION_STR << "\n"; | |
| 114 exit(0); | |
| 115 } else if (nonOptArgCount == 0) { | |
| 116 cli.format = BarcodeFormatFromString(argv[i]); | |
| 117 if (cli.format == BarcodeFormat::None) { | |
| 118 std::cerr << "Unrecognized format: " << argv[i] << std::endl; | |
| 119 return false; | |
| 120 } | |
| 121 ++nonOptArgCount; | |
| 122 } else if (nonOptArgCount == 1) { | |
| 123 cli.input = argv[i]; | |
| 124 ++nonOptArgCount; | |
| 125 } else if (nonOptArgCount == 2) { | |
| 126 cli.outPath = argv[i]; | |
| 127 ++nonOptArgCount; | |
| 128 } else { | |
| 129 return false; | |
| 130 } | |
| 131 } | |
| 132 | |
| 133 return nonOptArgCount == 3; | |
| 134 } | |
| 135 | |
| 136 static std::string GetExtension(const std::string& path) | |
| 137 { | |
| 138 auto fileNameStart = path.find_last_of("/\\"); | |
| 139 auto fileName = fileNameStart == std::string::npos ? path : path.substr(fileNameStart + 1); | |
| 140 auto extStart = fileName.find_last_of('.'); | |
| 141 auto ext = extStart == std::string::npos ? "" : fileName.substr(extStart + 1); | |
| 142 std::transform(ext.begin(), ext.end(), ext.begin(), [](char c) { return std::tolower(c); }); | |
| 143 return ext; | |
| 144 } | |
| 145 | |
| 146 template <typename T = char> | |
| 147 std::vector<T> ReadFile(const std::string& fn) | |
| 148 { | |
| 149 std::basic_ifstream<T> ifs(fn, std::ios::binary); | |
| 150 if (!ifs.good()) | |
| 151 throw std::runtime_error("failed to open/read file " + fn); | |
| 152 return ifs ? std::vector(std::istreambuf_iterator<T>(ifs), std::istreambuf_iterator<T>()) : std::vector<T>(); | |
| 153 }; | |
| 154 | |
| 155 int main(int argc, char* argv[]) | |
| 156 { | |
| 157 CLI cli; | |
| 158 | |
| 159 if (!ParseOptions(argc, argv, cli)) { | |
| 160 PrintUsage(argv[0]); | |
| 161 return -1; | |
| 162 } | |
| 163 | |
| 164 try { | |
| 165 #ifdef ZXING_EXPERIMENTAL_API | |
| 166 auto cOpts = CreatorOptions(cli.format).ecLevel(cli.ecLevel); | |
| 167 auto barcode = cli.inputIsFile ? CreateBarcodeFromBytes(ReadFile(cli.input), cOpts) : CreateBarcodeFromText(cli.input, cOpts); | |
| 168 | |
| 169 auto wOpts = WriterOptions().sizeHint(cli.sizeHint).withQuietZones(cli.withQZ).withHRT(cli.withHRT).rotate(0); | |
| 170 auto bitmap = WriteBarcodeToImage(barcode, wOpts); | |
| 171 | |
| 172 if (cli.verbose) { | |
| 173 std::cout << "Text: \"" << barcode.text() << "\"\n" | |
| 174 << "Bytes: " << ToHex(barcode.bytes()) << "\n" | |
| 175 << "Format: " << ToString(barcode.format()) << "\n" | |
| 176 << "Identifier: " << barcode.symbologyIdentifier() << "\n" | |
| 177 << "Content: " << ToString(barcode.contentType()) << "\n" | |
| 178 << "HasECI: " << barcode.hasECI() << "\n" | |
| 179 << "Position: " << ToString(barcode.position()) << "\n" | |
| 180 << "Rotation: " << barcode.orientation() << " deg\n" | |
| 181 << "IsMirrored: " << barcode.isMirrored() << "\n" | |
| 182 << "IsInverted: " << barcode.isInverted() << "\n" | |
| 183 << "ecLevel: " << barcode.ecLevel() << "\n"; | |
| 184 std::cout << WriteBarcodeToUtf8(barcode); | |
| 185 } | |
| 186 #else | |
| 187 auto writer = MultiFormatWriter(cli.format).setMargin(cli.withQZ ? 10 : 0); | |
| 188 if (!cli.ecLevel.empty()) | |
| 189 writer.setEccLevel(std::stoi(cli.ecLevel)); | |
| 190 | |
| 191 BitMatrix matrix; | |
| 192 if (cli.inputIsFile) { | |
| 193 auto file = ReadFile(cli.input); | |
| 194 std::wstring bytes; | |
| 195 for (uint8_t c : file) | |
| 196 bytes.push_back(c); | |
| 197 writer.setEncoding(CharacterSet::BINARY); | |
| 198 matrix = writer.encode(bytes, cli.sizeHint, std::clamp(cli.sizeHint / 2, 50, 300)); | |
| 199 } else { | |
| 200 writer.setEncoding(CharacterSet::UTF8); | |
| 201 matrix = writer.encode(cli.input, cli.sizeHint, std::clamp(cli.sizeHint / 2, 50, 300)); | |
| 202 } | |
| 203 auto bitmap = ToMatrix<uint8_t>(matrix); | |
| 204 #endif | |
| 205 | |
| 206 auto ext = GetExtension(cli.outPath); | |
| 207 int success = 0; | |
| 208 if (ext == "" || ext == "png") { | |
| 209 success = stbi_write_png(cli.outPath.c_str(), bitmap.width(), bitmap.height(), 1, bitmap.data(), 0); | |
| 210 } else if (ext == "jpg" || ext == "jpeg") { | |
| 211 success = stbi_write_jpg(cli.outPath.c_str(), bitmap.width(), bitmap.height(), 1, bitmap.data(), 0); | |
| 212 } else if (ext == "svg") { | |
| 213 #ifdef ZXING_EXPERIMENTAL_API | |
| 214 success = (std::ofstream(cli.outPath) << WriteBarcodeToSVG(barcode, wOpts)).good(); | |
| 215 #else | |
| 216 success = (std::ofstream(cli.outPath) << ToSVG(matrix)).good(); | |
| 217 #endif | |
| 218 } | |
| 219 | |
| 220 if (!success) { | |
| 221 std::cerr << "Failed to write image: " << cli.outPath << std::endl; | |
| 222 return -1; | |
| 223 } | |
| 224 } catch (const std::exception& e) { | |
| 225 std::cerr << e.what() << std::endl; | |
| 226 return -1; | |
| 227 } | |
| 228 | |
| 229 return 0; | |
| 230 } |
