BarcodeReader.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*
  2. * Copyright 2016 Nu-book Inc.
  3. * Copyright 2023 Axel Waggershauser
  4. */
  5. // SPDX-License-Identifier: Apache-2.0
  6. #include "ReadBarcode.h"
  7. #include <emscripten/bind.h>
  8. #include <emscripten/val.h>
  9. #include <memory>
  10. #include <stdexcept>
  11. #include <string>
  12. #define STB_IMAGE_IMPLEMENTATION
  13. #include <stb_image.h>
  14. using namespace ZXing;
  15. struct ReadResult
  16. {
  17. std::string format{};
  18. std::string text{};
  19. emscripten::val bytes;
  20. std::string error{};
  21. Position position{};
  22. std::string symbologyIdentifier{};
  23. };
  24. std::vector<ReadResult> readBarcodes(ImageView iv, bool tryHarder, const std::string& format, int maxSymbols)
  25. {
  26. try {
  27. ReaderOptions opts;
  28. opts.setTryHarder(tryHarder);
  29. opts.setTryRotate(tryHarder);
  30. opts.setTryInvert(tryHarder);
  31. opts.setTryDownscale(tryHarder);
  32. opts.setFormats(BarcodeFormatsFromString(format));
  33. opts.setMaxNumberOfSymbols(maxSymbols);
  34. // opts.setReturnErrors(maxSymbols > 1);
  35. auto barcodes = ReadBarcodes(iv, opts);
  36. std::vector<ReadResult> readResults{};
  37. readResults.reserve(barcodes.size());
  38. thread_local const emscripten::val Uint8Array = emscripten::val::global("Uint8Array");
  39. for (auto&& barcode : barcodes) {
  40. const ByteArray& bytes = barcode.bytes();
  41. readResults.push_back({
  42. ToString(barcode.format()),
  43. barcode.text(),
  44. Uint8Array.new_(emscripten::typed_memory_view(bytes.size(), bytes.data())),
  45. ToString(barcode.error()),
  46. barcode.position(),
  47. barcode.symbologyIdentifier()
  48. });
  49. }
  50. return readResults;
  51. } catch (const std::exception& e) {
  52. return {{"", "", {}, e.what()}};
  53. } catch (...) {
  54. return {{"", "", {}, "Unknown error"}};
  55. }
  56. return {};
  57. }
  58. std::vector<ReadResult> readBarcodesFromImage(int bufferPtr, int bufferLength, bool tryHarder, std::string format, int maxSymbols)
  59. {
  60. int width, height, channels;
  61. std::unique_ptr<stbi_uc, void (*)(void*)> buffer(
  62. stbi_load_from_memory(reinterpret_cast<const unsigned char*>(bufferPtr), bufferLength, &width, &height, &channels, 1),
  63. stbi_image_free);
  64. if (buffer == nullptr)
  65. return {{"", "", {}, "Error loading image"}};
  66. return readBarcodes({buffer.get(), width, height, ImageFormat::Lum}, tryHarder, format, maxSymbols);
  67. }
  68. ReadResult readBarcodeFromImage(int bufferPtr, int bufferLength, bool tryHarder, std::string format)
  69. {
  70. return FirstOrDefault(readBarcodesFromImage(bufferPtr, bufferLength, tryHarder, format, 1));
  71. }
  72. std::vector<ReadResult> readBarcodesFromPixmap(int bufferPtr, int imgWidth, int imgHeight, bool tryHarder, std::string format, int maxSymbols)
  73. {
  74. return readBarcodes({reinterpret_cast<uint8_t*>(bufferPtr), imgWidth, imgHeight, ImageFormat::RGBA}, tryHarder, format, maxSymbols);
  75. }
  76. ReadResult readBarcodeFromPixmap(int bufferPtr, int imgWidth, int imgHeight, bool tryHarder, std::string format)
  77. {
  78. return FirstOrDefault(readBarcodesFromPixmap(bufferPtr, imgWidth, imgHeight, tryHarder, format, 1));
  79. }
  80. EMSCRIPTEN_BINDINGS(BarcodeReader)
  81. {
  82. using namespace emscripten;
  83. value_object<ReadResult>("ReadResult")
  84. .field("format", &ReadResult::format)
  85. .field("text", &ReadResult::text)
  86. .field("bytes", &ReadResult::bytes)
  87. .field("error", &ReadResult::error)
  88. .field("position", &ReadResult::position)
  89. .field("symbologyIdentifier", &ReadResult::symbologyIdentifier);
  90. value_object<ZXing::PointI>("Point").field("x", &ZXing::PointI::x).field("y", &ZXing::PointI::y);
  91. value_object<ZXing::Position>("Position")
  92. .field("topLeft", emscripten::index<0>())
  93. .field("topRight", emscripten::index<1>())
  94. .field("bottomRight", emscripten::index<2>())
  95. .field("bottomLeft", emscripten::index<3>());
  96. register_vector<ReadResult>("vector<ReadResult>");
  97. function("readBarcodeFromImage", &readBarcodeFromImage);
  98. function("readBarcodeFromPixmap", &readBarcodeFromPixmap);
  99. function("readBarcodesFromImage", &readBarcodesFromImage);
  100. function("readBarcodesFromPixmap", &readBarcodesFromPixmap);
  101. };