BarcodeWriter.cpp 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /*
  2. * Copyright 2016 Nu-book Inc.
  3. */
  4. // SPDX-License-Identifier: Apache-2.0
  5. #include "BarcodeFormat.h"
  6. #include "MultiFormatWriter.h"
  7. #include "BitMatrix.h"
  8. #include "CharacterSet.h"
  9. #include <string>
  10. #include <memory>
  11. #include <exception>
  12. #include <emscripten/bind.h>
  13. #include <emscripten/val.h>
  14. #define STB_IMAGE_WRITE_IMPLEMENTATION
  15. #include <stb_image_write.h>
  16. class ImageData
  17. {
  18. public:
  19. uint8_t* const buffer;
  20. const int length;
  21. ImageData(uint8_t* buf, int len) : buffer(buf), length(len) {}
  22. ~ImageData() { STBIW_FREE(buffer); }
  23. };
  24. class WriteResult
  25. {
  26. std::shared_ptr<ImageData> _image;
  27. std::string _error;
  28. public:
  29. WriteResult(const std::shared_ptr<ImageData>& image) : _image(image) {}
  30. WriteResult(std::string error) : _error(std::move(error)) {}
  31. std::string error() const { return _error; }
  32. emscripten::val image() const
  33. {
  34. if (_image != nullptr)
  35. return emscripten::val(emscripten::typed_memory_view(_image->length, _image->buffer));
  36. else
  37. return emscripten::val::null();
  38. }
  39. };
  40. WriteResult generateBarcode(std::wstring text, std::string format, std::string encoding, int margin, int width, int height, int eccLevel)
  41. {
  42. using namespace ZXing;
  43. try {
  44. auto barcodeFormat = BarcodeFormatFromString(format);
  45. if (barcodeFormat == BarcodeFormat::None)
  46. return {"Unsupported format: " + format};
  47. MultiFormatWriter writer(barcodeFormat);
  48. if (margin >= 0)
  49. writer.setMargin(margin);
  50. CharacterSet charset = CharacterSetFromString(encoding);
  51. if (charset != CharacterSet::Unknown)
  52. writer.setEncoding(charset);
  53. if (eccLevel >= 0 && eccLevel <= 8)
  54. writer.setEccLevel(eccLevel);
  55. auto buffer = ToMatrix<uint8_t>(writer.encode(text, width, height));
  56. int len;
  57. uint8_t* bytes = stbi_write_png_to_mem(buffer.data(), 0, buffer.width(), buffer.height(), 1, &len);
  58. if (bytes == nullptr)
  59. return {"Unknown error"};
  60. return {std::make_shared<ImageData>(bytes, len)};
  61. } catch (const std::exception& e) {
  62. return {e.what()};
  63. } catch (...) {
  64. return {"Unknown error"};
  65. }
  66. }
  67. EMSCRIPTEN_BINDINGS(BarcodeWriter)
  68. {
  69. using namespace emscripten;
  70. class_<WriteResult>("WriteResult")
  71. .property("image", &WriteResult::image)
  72. .property("error", &WriteResult::error)
  73. ;
  74. function("generateBarcode", &generateBarcode);
  75. }