You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

216 lines
6.3 KiB

/*
* Copyright 2016 Nu-book Inc.
*/
// SPDX-License-Identifier: Apache-2.0
#if (_MSC_VER >= 1915)
#define no_init_all deprecated
#pragma warning(disable : 4996)
#endif
#include "BarcodeReader.h"
#include "BarcodeFormat.h"
#include "ReaderOptions.h"
#include "ReadBarcode.h"
#include "ReadResult.h"
#include "Utf.h"
#include <algorithm>
#include <MemoryBuffer.h>
#include <stdexcept>
#include <wrl.h>
using namespace Microsoft::WRL;
using namespace Windows::Foundation;
using namespace Windows::Graphics::Imaging;
namespace ZXing {
BarcodeReader::BarcodeReader(bool tryHarder, bool tryRotate, const Platform::Array<BarcodeType>^ types)
{
init(tryHarder, tryRotate, types);
}
BarcodeReader::BarcodeReader(bool tryHarder, bool tryRotate)
{
init(tryHarder, tryRotate, nullptr);
}
BarcodeReader::BarcodeReader(bool tryHarder)
{
init(tryHarder, tryHarder, nullptr);
}
void
BarcodeReader::init(bool tryHarder, bool tryRotate, const Platform::Array<BarcodeType>^ types)
{
m_opts.reset(new ReaderOptions());
m_opts->setTryHarder(tryHarder);
m_opts->setTryRotate(tryRotate);
m_opts->setTryInvert(tryHarder);
if (types != nullptr && types->Length > 0) {
BarcodeFormats barcodeFormats;
for (BarcodeType type : types) {
barcodeFormats |= BarcodeReader::ConvertRuntimeToNative(type);
}
m_opts->setFormats(barcodeFormats);
}
}
BarcodeReader::~BarcodeReader()
{
}
BarcodeFormat BarcodeReader::ConvertRuntimeToNative(BarcodeType type)
{
switch (type) {
case BarcodeType::AZTEC:
return BarcodeFormat::Aztec;
case BarcodeType::CODABAR:
return BarcodeFormat::Codabar;
case BarcodeType::CODE_128:
return BarcodeFormat::Code128;
case BarcodeType::CODE_39:
return BarcodeFormat::Code39;
case BarcodeType::CODE_93:
return BarcodeFormat::Code93;
case BarcodeType::DATA_MATRIX:
return BarcodeFormat::DataMatrix;
case BarcodeType::EAN_13:
return BarcodeFormat::EAN13;
case BarcodeType::EAN_8:
return BarcodeFormat::EAN8;
case BarcodeType::ITF:
return BarcodeFormat::ITF;
case BarcodeType::MAXICODE:
return BarcodeFormat::MaxiCode;
case BarcodeType::PDF_417:
return BarcodeFormat::PDF417;
case BarcodeType::QR_CODE:
return BarcodeFormat::QRCode;
case BarcodeType::MICRO_QR_CODE:
return BarcodeFormat::MicroQRCode;
case BarcodeType::RMQR_CODE:
return BarcodeFormat::RMQRCode;
case BarcodeType::RSS_14:
return BarcodeFormat::DataBar;
case BarcodeType::RSS_EXPANDED:
return BarcodeFormat::DataBarExpanded;
case BarcodeType::DATA_BAR_LIMITED:
return BarcodeFormat::DataBarLimited;
case BarcodeType::DX_FILM_EDGE:
return BarcodeFormat::DXFilmEdge;
case BarcodeType::UPC_A:
return BarcodeFormat::UPCA;
case BarcodeType::UPC_E:
return BarcodeFormat::UPCE;
default:
std::wstring typeAsString = type.ToString()->Begin();
throw std::invalid_argument("Unknown Barcode Type: " + ToUtf8(typeAsString));
}
}
BarcodeType BarcodeReader::ConvertNativeToRuntime(BarcodeFormat format)
{
switch (format) {
case BarcodeFormat::Aztec:
return BarcodeType::AZTEC;
case BarcodeFormat::Codabar:
return BarcodeType::CODABAR;
case BarcodeFormat::Code128:
return BarcodeType::CODE_128;
case BarcodeFormat::Code39:
return BarcodeType::CODE_39;
case BarcodeFormat::Code93:
return BarcodeType::CODE_93;
case BarcodeFormat::DataMatrix:
return BarcodeType::DATA_MATRIX;
case BarcodeFormat::EAN13:
return BarcodeType::EAN_13;
case BarcodeFormat::EAN8:
return BarcodeType::EAN_8;
case BarcodeFormat::ITF:
return BarcodeType::ITF;
case BarcodeFormat::MaxiCode:
return BarcodeType::MAXICODE;
case BarcodeFormat::PDF417:
return BarcodeType::PDF_417;
case BarcodeFormat::QRCode:
return BarcodeType::QR_CODE;
case BarcodeFormat::MicroQRCode:
return BarcodeType::MICRO_QR_CODE;
case BarcodeFormat::RMQRCode:
return BarcodeType::RMQR_CODE;
case BarcodeFormat::DataBar:
return BarcodeType::RSS_14;
case BarcodeFormat::DataBarExpanded:
return BarcodeType::RSS_EXPANDED;
case BarcodeFormat::DataBarLimited:
return BarcodeType::DATA_BAR_LIMITED;
case BarcodeFormat::DXFilmEdge:
return BarcodeType::DX_FILM_EDGE;
case BarcodeFormat::UPCA:
return BarcodeType::UPC_A;
case BarcodeFormat::UPCE:
return BarcodeType::UPC_E;
default:
throw std::invalid_argument("Unknown Barcode Format ");
}
}
static Platform::String^ ToPlatformString(const std::string& str)
{
std::wstring wstr = FromUtf8(str);
return ref new Platform::String(wstr.c_str(), (unsigned)wstr.length());
}
ReadResult^
BarcodeReader::Read(SoftwareBitmap^ bitmap, int cropWidth, int cropHeight)
{
try {
cropWidth = cropWidth <= 0 ? bitmap->PixelWidth : std::min(bitmap->PixelWidth, cropWidth);
cropHeight = cropHeight <= 0 ? bitmap->PixelHeight : std::min(bitmap->PixelHeight, cropHeight);
int cropLeft = (bitmap->PixelWidth - cropWidth) / 2;
int cropTop = (bitmap->PixelHeight - cropHeight) / 2;
auto inBuffer = bitmap->LockBuffer(BitmapBufferAccessMode::Read);
auto inMemRef = inBuffer->CreateReference();
ComPtr<IMemoryBufferByteAccess> inBufferAccess;
if (SUCCEEDED(ComPtr<IUnknown>(reinterpret_cast<IUnknown*>(inMemRef)).As(&inBufferAccess))) {
BYTE* inBytes = nullptr;
UINT32 inCapacity = 0;
inBufferAccess->GetBuffer(&inBytes, &inCapacity);
ImageFormat fmt = ImageFormat::None;
switch (bitmap->BitmapPixelFormat)
{
case BitmapPixelFormat::Gray8: fmt = ImageFormat::Lum; break;
case BitmapPixelFormat::Bgra8: fmt = ImageFormat::BGRA; break;
case BitmapPixelFormat::Rgba8: fmt = ImageFormat::RGBA; break;
default:
throw std::runtime_error("Unsupported BitmapPixelFormat");
}
auto img = ImageView(inBytes, bitmap->PixelWidth, bitmap->PixelHeight, fmt, inBuffer->GetPlaneDescription(0).Stride)
.cropped(cropLeft, cropTop, cropWidth, cropHeight);
auto barcode = ReadBarcode(img, *m_opts);
if (barcode.isValid()) {
return ref new ReadResult(ToPlatformString(ZXing::ToString(barcode.format())), ToPlatformString(barcode.text()), ConvertNativeToRuntime(barcode.format()));
}
} else {
throw std::runtime_error("Failed to read bitmap's data");
}
}
catch (const std::exception& e) {
OutputDebugStringA(e.what());
}
catch (...) {
}
return nullptr;
}
} // ZXing