Commit a1b00268 authored by Volker Krause's avatar Volker Krause
Browse files

More detailed result reporting for barcode plausibility checks

This will allow us to avoid redoing those checks several times, which can
be a problem for PDF content, as we use different sizes (source data,
output) depending on what information is available at any given point.
parent af308454
......@@ -99,14 +99,14 @@ private Q_SLOTS:
void testPlausibilityCheck()
{
QVERIFY(!BarcodeDecoder::maybeBarcode(10, 10, BarcodeDecoder::Any));
QVERIFY(BarcodeDecoder::maybeBarcode(100, 100, BarcodeDecoder::Any));
QVERIFY(!BarcodeDecoder::maybeBarcode(100, 100, BarcodeDecoder::PDF417));
QVERIFY(BarcodeDecoder::maybeBarcode(100, 100, BarcodeDecoder::Aztec));
QVERIFY(BarcodeDecoder::maybeBarcode(100, 100, BarcodeDecoder::AnySquare));
QVERIFY(BarcodeDecoder::maybeBarcode(100, 180, BarcodeDecoder::PDF417));
QVERIFY(BarcodeDecoder::maybeBarcode(180, 100, BarcodeDecoder::PDF417));
QVERIFY(!BarcodeDecoder::maybeBarcode(180, 100, BarcodeDecoder::AnySquare));
QCOMPARE(BarcodeDecoder::maybeBarcode(10, 10, BarcodeDecoder::Any), BarcodeDecoder::None);
QCOMPARE(BarcodeDecoder::maybeBarcode(100, 100, BarcodeDecoder::Any), BarcodeDecoder::AnySquare);
QCOMPARE(BarcodeDecoder::maybeBarcode(100, 100, BarcodeDecoder::PDF417), BarcodeDecoder::None);
QCOMPARE(BarcodeDecoder::maybeBarcode(100, 100, BarcodeDecoder::Aztec), BarcodeDecoder::Aztec);
QCOMPARE(BarcodeDecoder::maybeBarcode(100, 100, BarcodeDecoder::AnySquare), BarcodeDecoder::AnySquare);
QCOMPARE(BarcodeDecoder::maybeBarcode(100, 180, BarcodeDecoder::PDF417), BarcodeDecoder::PDF417);
QCOMPARE(BarcodeDecoder::maybeBarcode(180, 100, BarcodeDecoder::PDF417), BarcodeDecoder::PDF417);
QCOMPARE(BarcodeDecoder::maybeBarcode(180, 100, BarcodeDecoder::AnySquare), BarcodeDecoder::None);
}
void testNoCode()
......
......@@ -47,7 +47,7 @@ BarcodeDecoder::~BarcodeDecoder() = default;
bool BarcodeDecoder::isBarcode(const QImage &img, BarcodeDecoder::BarcodeTypes hint) const
{
if (!maybeBarcode(img.width(), img.height(), hint)) {
if (maybeBarcode(img.width(), img.height(), hint) == None) {
return false;
}
......@@ -58,7 +58,7 @@ bool BarcodeDecoder::isBarcode(const QImage &img, BarcodeDecoder::BarcodeTypes h
QByteArray BarcodeDecoder::decodeBinary(const QImage &img, BarcodeDecoder::BarcodeTypes hint) const
{
if (!maybeBarcode(img.width(), img.height(), hint)) {
if (maybeBarcode(img.width(), img.height(), hint) == None) {
return {};
}
......@@ -73,7 +73,7 @@ QByteArray BarcodeDecoder::decodeBinary(const QImage &img, BarcodeDecoder::Barco
QString BarcodeDecoder::decodeString(const QImage &img, BarcodeDecoder::BarcodeTypes hint) const
{
if (!maybeBarcode(img.width(), img.height(), hint)) {
if (maybeBarcode(img.width(), img.height(), hint) == None) {
return {};
}
......@@ -91,21 +91,24 @@ void BarcodeDecoder::clearCache()
m_cache.clear();
}
bool BarcodeDecoder::isPlausibleSize(int width, int height, BarcodeDecoder::BarcodeTypes hint)
BarcodeDecoder::BarcodeTypes BarcodeDecoder::isPlausibleSize(int width, int height, BarcodeDecoder::BarcodeTypes hint)
{
// normalize to landscape
if (height > width) {
std::swap(width, height);
}
return width > MinSourceImageWidth && height > MinSourceImageHeight
&& ((width < MaxSourceImageWidth && height < MaxSourceImageHeight) || (hint & IgnoreAspectRatio));
if (width > MinSourceImageWidth && height > MinSourceImageHeight
&& ((width < MaxSourceImageWidth && height < MaxSourceImageHeight) || (hint & IgnoreAspectRatio))) {
return hint;
}
return None;
}
bool BarcodeDecoder::isPlausibleAspectRatio(int width, int height, BarcodeDecoder::BarcodeTypes hint)
BarcodeDecoder::BarcodeTypes BarcodeDecoder::isPlausibleAspectRatio(int width, int height, BarcodeDecoder::BarcodeTypes hint)
{
if (hint & IgnoreAspectRatio) {
return true;
return hint;
}
// normalize to landscape
......@@ -116,26 +119,26 @@ bool BarcodeDecoder::isPlausibleAspectRatio(int width, int height, BarcodeDecode
const auto aspectRatio = (float)width / (float)height;
// almost square, assume Aztec or QR
if (aspectRatio < SQUARE_MAX_ASPECT && (hint & AnySquare)) {
return true;
if (aspectRatio > SQUARE_MAX_ASPECT) {
hint &= ~AnySquare;
}
// rectangular with medium aspect ratio, such as PDF 417
if (aspectRatio > PDF417_MIN_ASPECT && aspectRatio < PDF417_MAX_ASPECT && (hint & PDF417)) {
return true;
if (aspectRatio < PDF417_MIN_ASPECT || aspectRatio > PDF417_MAX_ASPECT) {
hint &= ~PDF417;
}
// 1D
if (aspectRatio > ANY1D_MIN_ASPECT && (hint & Any1D)) {
return true;
if (aspectRatio < ANY1D_MIN_ASPECT) {
hint &= ~Any1D;
}
return false;
return hint;
}
bool BarcodeDecoder::maybeBarcode(int width, int height, BarcodeDecoder::BarcodeTypes hint)
BarcodeDecoder::BarcodeTypes BarcodeDecoder::maybeBarcode(int width, int height, BarcodeDecoder::BarcodeTypes hint)
{
return isPlausibleSize(width, height, hint) && isPlausibleAspectRatio(width, height, hint);
return isPlausibleSize(width, height, hint) & isPlausibleAspectRatio(width, height, hint);
}
#if HAVE_ZXING
......
......@@ -67,15 +67,15 @@ public:
* to perform them manually if a cheaper way to obtain the image dimension exists
* that does not require a full QImage creation.
*/
static bool isPlausibleSize(int width, int height, BarcodeTypes hint);
static BarcodeTypes isPlausibleSize(int width, int height, BarcodeTypes hint);
/** Checks if the given image dimensions are a barcode of type @p hint.
* See above.
*/
static bool isPlausibleAspectRatio(int width, int height, BarcodeTypes hint);
static BarcodeTypes isPlausibleAspectRatio(int width, int height, BarcodeTypes hint);
/** The combination of the above. */
static bool maybeBarcode(int width, int height, BarcodeTypes hint);
static BarcodeTypes maybeBarcode(int width, int height, BarcodeTypes hint);
private:
struct Result {
......
......@@ -39,7 +39,7 @@ QJSValue JsApi::Barcode::decodeAztecBinary(const QVariant &img) const
{
if (img.userType() == qMetaTypeId<PdfImage>()) {
const auto pdfImg = img.value<PdfImage>();
if (!PdfBarcodeUtil::maybeBarcode(pdfImg, BarcodeDecoder::Aztec)) {
if (PdfBarcodeUtil::maybeBarcode(pdfImg, BarcodeDecoder::Aztec) == BarcodeDecoder::None) {
return {};
}
const auto content = m_decoder->decodeBinary(pdfImg.image(), BarcodeDecoder::Aztec);
......@@ -79,7 +79,7 @@ QString JsApi::Barcode::decodeBarcode(const QVariant &img, BarcodeDecoder::Barco
{
if (img.userType() == qMetaTypeId<PdfImage>()) {
const auto pdfImg = img.value<PdfImage>();
if (!PdfBarcodeUtil::maybeBarcode(pdfImg, hints)) {
if (PdfBarcodeUtil::maybeBarcode(pdfImg, hints) == BarcodeDecoder::None) {
return {};
}
return m_decoder->decodeString(pdfImg.image(), hints);
......
......@@ -14,22 +14,24 @@ enum {
MinTargetImageHeight = 28,
MinTargetImageWidth = 36,
MaxTargetImageHeight = 252,
MaxTargetImageWidth = 252,
MaxTargetImageWidth2D = 252,
};
bool PdfBarcodeUtil::maybeBarcode(const PdfImage &img, BarcodeDecoder::BarcodeTypes hint)
BarcodeDecoder::BarcodeTypes PdfBarcodeUtil::maybeBarcode(const PdfImage &img, BarcodeDecoder::BarcodeTypes hint)
{
const auto w = img.width();
const auto h = img.height();
if (!BarcodeDecoder::isPlausibleSize(img.sourceWidth(), img.sourceHeight(), hint) || !BarcodeDecoder::isPlausibleAspectRatio(w, h, hint)) {
return false;
// image target size checks
if (std::min(w, h) < MinTargetImageHeight || std::max(w, h) < MinTargetImageWidth || std::min(w, h) > MaxTargetImageHeight) {
return BarcodeDecoder::None;
}
// image target size checks
if (std::min(w, h) < MinTargetImageHeight || std::max(w, h) < MinTargetImageWidth || h > MaxTargetImageHeight || w > MaxTargetImageWidth) {
return false;
if (std::max(w, h) > MaxTargetImageWidth2D) {
hint &= ~BarcodeDecoder::Any2D;
}
return true;
hint = BarcodeDecoder::isPlausibleSize(img.sourceWidth(), img.sourceHeight(), hint);
hint = BarcodeDecoder::isPlausibleAspectRatio(w, h, hint);
return hint;
}
......@@ -16,7 +16,7 @@ class PdfImage;
namespace PdfBarcodeUtil
{
/** Quick pre-check without image decoding if @p img might be a barcode. */
bool maybeBarcode(const PdfImage &img, BarcodeDecoder::BarcodeTypes hint = BarcodeDecoder::Any2D);
BarcodeDecoder::BarcodeTypes maybeBarcode(const PdfImage &img, BarcodeDecoder::BarcodeTypes hint = BarcodeDecoder::Any2D);
}
}
......
......@@ -31,9 +31,10 @@ void ImageDocumentProcessor::expandNode(ExtractorDocumentNode &node, const Extra
// check whether we possibly have a full PDF page raster image here
const auto img = node.content<QImage>();
BarcodeDecoder::BarcodeTypes barcodeHints = BarcodeDecoder::Any2D;
if (engine->hints() & ExtractorEngine::ExtractFullPageRasterImages && !BarcodeDecoder::maybeBarcode(img.width(), img.height(), barcodeHints)) {
if (engine->hints() & ExtractorEngine::ExtractFullPageRasterImages) {
barcodeHints |= BarcodeDecoder::IgnoreAspectRatio;
}
barcodeHints = BarcodeDecoder::maybeBarcode(img.width(), img.height(), barcodeHints);
// in case the barcode raw data (string or bytearray) gets detected as a type we handle,
// we nevertheless inject a raw data node in between. This is useful in cases where the
......
......@@ -90,7 +90,7 @@ void PdfDocumentProcessor::expandNode(ExtractorDocumentNode &node, const Extract
continue;
}
if (!PdfBarcodeUtil::maybeBarcode(img)) {
if (PdfBarcodeUtil::maybeBarcode(img, BarcodeDecoder::Any2D) == BarcodeDecoder::None) {
continue;
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment