BarcodeReader.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. * Copyright 2016 Nu-book Inc.
  3. */
  4. // SPDX-License-Identifier: Apache-2.0
  5. #if (_MSC_VER >= 1915)
  6. #define no_init_all deprecated
  7. #pragma warning(disable : 4996)
  8. #endif
  9. #include "BarcodeReader.h"
  10. #include "BarcodeFormat.h"
  11. #include "ReaderOptions.h"
  12. #include "ReadBarcode.h"
  13. #include "ReadResult.h"
  14. #include "Utf.h"
  15. #include <algorithm>
  16. #include <MemoryBuffer.h>
  17. #include <stdexcept>
  18. #include <wrl.h>
  19. using namespace Microsoft::WRL;
  20. using namespace Windows::Foundation;
  21. using namespace Windows::Graphics::Imaging;
  22. namespace ZXing {
  23. BarcodeReader::BarcodeReader(bool tryHarder, bool tryRotate, const Platform::Array<BarcodeType>^ types)
  24. {
  25. init(tryHarder, tryRotate, types);
  26. }
  27. BarcodeReader::BarcodeReader(bool tryHarder, bool tryRotate)
  28. {
  29. init(tryHarder, tryRotate, nullptr);
  30. }
  31. BarcodeReader::BarcodeReader(bool tryHarder)
  32. {
  33. init(tryHarder, tryHarder, nullptr);
  34. }
  35. void
  36. BarcodeReader::init(bool tryHarder, bool tryRotate, const Platform::Array<BarcodeType>^ types)
  37. {
  38. m_opts.reset(new ReaderOptions());
  39. m_opts->setTryHarder(tryHarder);
  40. m_opts->setTryRotate(tryRotate);
  41. m_opts->setTryInvert(tryHarder);
  42. if (types != nullptr && types->Length > 0) {
  43. BarcodeFormats barcodeFormats;
  44. for (BarcodeType type : types) {
  45. barcodeFormats |= BarcodeReader::ConvertRuntimeToNative(type);
  46. }
  47. m_opts->setFormats(barcodeFormats);
  48. }
  49. }
  50. BarcodeReader::~BarcodeReader()
  51. {
  52. }
  53. BarcodeFormat BarcodeReader::ConvertRuntimeToNative(BarcodeType type)
  54. {
  55. switch (type) {
  56. case BarcodeType::AZTEC:
  57. return BarcodeFormat::Aztec;
  58. case BarcodeType::CODABAR:
  59. return BarcodeFormat::Codabar;
  60. case BarcodeType::CODE_128:
  61. return BarcodeFormat::Code128;
  62. case BarcodeType::CODE_39:
  63. return BarcodeFormat::Code39;
  64. case BarcodeType::CODE_93:
  65. return BarcodeFormat::Code93;
  66. case BarcodeType::DATA_MATRIX:
  67. return BarcodeFormat::DataMatrix;
  68. case BarcodeType::EAN_13:
  69. return BarcodeFormat::EAN13;
  70. case BarcodeType::EAN_8:
  71. return BarcodeFormat::EAN8;
  72. case BarcodeType::ITF:
  73. return BarcodeFormat::ITF;
  74. case BarcodeType::MAXICODE:
  75. return BarcodeFormat::MaxiCode;
  76. case BarcodeType::PDF_417:
  77. return BarcodeFormat::PDF417;
  78. case BarcodeType::QR_CODE:
  79. return BarcodeFormat::QRCode;
  80. case BarcodeType::MICRO_QR_CODE:
  81. return BarcodeFormat::MicroQRCode;
  82. case BarcodeType::RMQR_CODE:
  83. return BarcodeFormat::RMQRCode;
  84. case BarcodeType::RSS_14:
  85. return BarcodeFormat::DataBar;
  86. case BarcodeType::RSS_EXPANDED:
  87. return BarcodeFormat::DataBarExpanded;
  88. case BarcodeType::DATA_BAR_LIMITED:
  89. return BarcodeFormat::DataBarLimited;
  90. case BarcodeType::DX_FILM_EDGE:
  91. return BarcodeFormat::DXFilmEdge;
  92. case BarcodeType::UPC_A:
  93. return BarcodeFormat::UPCA;
  94. case BarcodeType::UPC_E:
  95. return BarcodeFormat::UPCE;
  96. default:
  97. std::wstring typeAsString = type.ToString()->Begin();
  98. throw std::invalid_argument("Unknown Barcode Type: " + ToUtf8(typeAsString));
  99. }
  100. }
  101. BarcodeType BarcodeReader::ConvertNativeToRuntime(BarcodeFormat format)
  102. {
  103. switch (format) {
  104. case BarcodeFormat::Aztec:
  105. return BarcodeType::AZTEC;
  106. case BarcodeFormat::Codabar:
  107. return BarcodeType::CODABAR;
  108. case BarcodeFormat::Code128:
  109. return BarcodeType::CODE_128;
  110. case BarcodeFormat::Code39:
  111. return BarcodeType::CODE_39;
  112. case BarcodeFormat::Code93:
  113. return BarcodeType::CODE_93;
  114. case BarcodeFormat::DataMatrix:
  115. return BarcodeType::DATA_MATRIX;
  116. case BarcodeFormat::EAN13:
  117. return BarcodeType::EAN_13;
  118. case BarcodeFormat::EAN8:
  119. return BarcodeType::EAN_8;
  120. case BarcodeFormat::ITF:
  121. return BarcodeType::ITF;
  122. case BarcodeFormat::MaxiCode:
  123. return BarcodeType::MAXICODE;
  124. case BarcodeFormat::PDF417:
  125. return BarcodeType::PDF_417;
  126. case BarcodeFormat::QRCode:
  127. return BarcodeType::QR_CODE;
  128. case BarcodeFormat::MicroQRCode:
  129. return BarcodeType::MICRO_QR_CODE;
  130. case BarcodeFormat::RMQRCode:
  131. return BarcodeType::RMQR_CODE;
  132. case BarcodeFormat::DataBar:
  133. return BarcodeType::RSS_14;
  134. case BarcodeFormat::DataBarExpanded:
  135. return BarcodeType::RSS_EXPANDED;
  136. case BarcodeFormat::DataBarLimited:
  137. return BarcodeType::DATA_BAR_LIMITED;
  138. case BarcodeFormat::DXFilmEdge:
  139. return BarcodeType::DX_FILM_EDGE;
  140. case BarcodeFormat::UPCA:
  141. return BarcodeType::UPC_A;
  142. case BarcodeFormat::UPCE:
  143. return BarcodeType::UPC_E;
  144. default:
  145. throw std::invalid_argument("Unknown Barcode Format ");
  146. }
  147. }
  148. static Platform::String^ ToPlatformString(const std::string& str)
  149. {
  150. std::wstring wstr = FromUtf8(str);
  151. return ref new Platform::String(wstr.c_str(), (unsigned)wstr.length());
  152. }
  153. ReadResult^
  154. BarcodeReader::Read(SoftwareBitmap^ bitmap, int cropWidth, int cropHeight)
  155. {
  156. try {
  157. cropWidth = cropWidth <= 0 ? bitmap->PixelWidth : std::min(bitmap->PixelWidth, cropWidth);
  158. cropHeight = cropHeight <= 0 ? bitmap->PixelHeight : std::min(bitmap->PixelHeight, cropHeight);
  159. int cropLeft = (bitmap->PixelWidth - cropWidth) / 2;
  160. int cropTop = (bitmap->PixelHeight - cropHeight) / 2;
  161. auto inBuffer = bitmap->LockBuffer(BitmapBufferAccessMode::Read);
  162. auto inMemRef = inBuffer->CreateReference();
  163. ComPtr<IMemoryBufferByteAccess> inBufferAccess;
  164. if (SUCCEEDED(ComPtr<IUnknown>(reinterpret_cast<IUnknown*>(inMemRef)).As(&inBufferAccess))) {
  165. BYTE* inBytes = nullptr;
  166. UINT32 inCapacity = 0;
  167. inBufferAccess->GetBuffer(&inBytes, &inCapacity);
  168. ImageFormat fmt = ImageFormat::None;
  169. switch (bitmap->BitmapPixelFormat)
  170. {
  171. case BitmapPixelFormat::Gray8: fmt = ImageFormat::Lum; break;
  172. case BitmapPixelFormat::Bgra8: fmt = ImageFormat::BGRA; break;
  173. case BitmapPixelFormat::Rgba8: fmt = ImageFormat::RGBA; break;
  174. default:
  175. throw std::runtime_error("Unsupported BitmapPixelFormat");
  176. }
  177. auto img = ImageView(inBytes, bitmap->PixelWidth, bitmap->PixelHeight, fmt, inBuffer->GetPlaneDescription(0).Stride)
  178. .cropped(cropLeft, cropTop, cropWidth, cropHeight);
  179. auto barcode = ReadBarcode(img, *m_opts);
  180. if (barcode.isValid()) {
  181. return ref new ReadResult(ToPlatformString(ZXing::ToString(barcode.format())), ToPlatformString(barcode.text()), ConvertNativeToRuntime(barcode.format()));
  182. }
  183. } else {
  184. throw std::runtime_error("Failed to read bitmap's data");
  185. }
  186. }
  187. catch (const std::exception& e) {
  188. OutputDebugStringA(e.what());
  189. }
  190. catch (...) {
  191. }
  192. return nullptr;
  193. }
  194. } // ZXing