File indexing completed on 2024-05-12 05:17:29

0001 /*
0002     SPDX-FileCopyrightText: 2018 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include <KItinerary/BarcodeDecoder>
0008 
0009 #include <QImage>
0010 #include <QObject>
0011 #include <QTest>
0012 
0013 Q_DECLARE_METATYPE(KItinerary::BarcodeDecoder::BarcodeType)
0014 
0015 using namespace KItinerary;
0016 
0017 class BarcodeDecoderTest : public QObject
0018 {
0019     Q_OBJECT
0020 private Q_SLOTS:
0021     void testPDF417_data()
0022     {
0023         QTest::addColumn<QString>("fileName");
0024 
0025         QTest::newRow("1bit") << QStringLiteral("pdf417_1bit.png");
0026         QTest::newRow("8bit") << QStringLiteral("pdf417_8bit.png");
0027         QTest::newRow("24bit") << QStringLiteral("pdf417_24bit.png");
0028         QTest::newRow("32bit") << QStringLiteral("pdf417_32bit.png");
0029         QTest::newRow("cropped") << QStringLiteral("pdf417_cropped.png");
0030         QTest::newRow("rot90") << QStringLiteral("pdf417_rot90.png");
0031         QTest::newRow("rot180") << QStringLiteral("pdf417_rot180.png");
0032         QTest::newRow("rot270") << QStringLiteral("pdf417_rot270.png");
0033         QTest::newRow("flipped") << QStringLiteral("pdf417_flipped.png");
0034         QTest::newRow("partial cropped") << QStringLiteral("pdf417_partial_cropped.png");
0035     }
0036 
0037     void testPDF417()
0038     {
0039         QFETCH(QString, fileName);
0040 
0041         QImage img(QStringLiteral(SOURCE_DIR "/barcodes/") + fileName);
0042         QVERIFY(!img.isNull());
0043 
0044         BarcodeDecoder decoder;
0045         QVERIFY(BarcodeDecoder::maybeBarcode(img.width(), img.height(), BarcodeDecoder::Any) & BarcodeDecoder::PDF417);
0046         QCOMPARE(decoder.decode(img, BarcodeDecoder::PDF417).toString(), QStringLiteral("PDF417 is a stacked linear barcode symbol format used in a variety of applications, primarily transport, identification cards, and inventory management."));
0047     }
0048 
0049     void testAztec()
0050     {
0051         QImage img(QStringLiteral(SOURCE_DIR "/barcodes/aztec.png"));
0052         QVERIFY(!img.isNull());
0053         BarcodeDecoder decoder;
0054         QVERIFY(BarcodeDecoder::maybeBarcode(img.width(), img.height(), BarcodeDecoder::Any) & BarcodeDecoder::Aztec);
0055         QCOMPARE(decoder.decode(img, BarcodeDecoder::Aztec).toString(), QStringLiteral("This is an example Aztec symbol for Wikipedia."));
0056         img.load(QStringLiteral(SOURCE_DIR "/barcodes/aztec-partial-quiet-zone.png"));
0057         QVERIFY(!img.isNull());
0058         QVERIFY(BarcodeDecoder::maybeBarcode(img.width(), img.height(), BarcodeDecoder::Any) & BarcodeDecoder::Aztec);
0059         QCOMPARE(decoder.decode(img, BarcodeDecoder::Aztec).toString(), QStringLiteral("KF5::Prison - The KDE barcode generation framework."));
0060 
0061         img.load(QStringLiteral(SOURCE_DIR "/barcodes/uic918-3star.png"));
0062         QVERIFY(!img.isNull());
0063         QVERIFY(BarcodeDecoder::maybeBarcode(img.width(), img.height(), BarcodeDecoder::Any) & BarcodeDecoder::Aztec);
0064         const auto b = decoder.decode(img, BarcodeDecoder::Aztec).toByteArray();
0065         QCOMPARE(b.size(), 351);
0066         QVERIFY(b.startsWith("OTI010080000020"));
0067     }
0068 
0069     void testQRCode_data()
0070     {
0071             QTest::addColumn<QString>("fileName");
0072             QTest::addColumn<QString>("result");
0073 
0074             QTest::newRow("1") << QStringLiteral("qrcode1.png") << QStringLiteral("M$K0YGV0G");
0075             QTest::newRow("2") << QStringLiteral("qrcode2.png") << QStringLiteral("KZEXO4HRE");
0076             // individual lines have non-square features (found e.g. in Renfe tickets)
0077             QTest::newRow("3") << QStringLiteral("qrcode-scale-artifacts.png") << QStringLiteral("M$K0YGV0G");
0078     }
0079 
0080     void testQRCode()
0081     {
0082         QFETCH(QString, fileName);
0083         QFETCH(QString, result);
0084 
0085         QImage img(QStringLiteral(SOURCE_DIR "/barcodes/") + fileName);
0086         QVERIFY(!img.isNull());
0087 
0088         BarcodeDecoder decoder;
0089         QVERIFY(BarcodeDecoder::maybeBarcode(img.width(), img.height(), BarcodeDecoder::Any) & BarcodeDecoder::QRCode);
0090         QCOMPARE(decoder.decode(img, BarcodeDecoder::QRCode).toString(), result);
0091     }
0092 
0093     void testPlausibilityCheck()
0094     {
0095         QCOMPARE(BarcodeDecoder::maybeBarcode(10, 10, BarcodeDecoder::Any), BarcodeDecoder::None);
0096         QCOMPARE(BarcodeDecoder::maybeBarcode(100, 100, BarcodeDecoder::Any), BarcodeDecoder::AnySquare);
0097         QCOMPARE(BarcodeDecoder::maybeBarcode(100, 100, BarcodeDecoder::PDF417), BarcodeDecoder::None);
0098         QCOMPARE(BarcodeDecoder::maybeBarcode(100, 100, BarcodeDecoder::Aztec), BarcodeDecoder::Aztec);
0099         QCOMPARE(BarcodeDecoder::maybeBarcode(100, 100, BarcodeDecoder::AnySquare), BarcodeDecoder::AnySquare);
0100         QCOMPARE(BarcodeDecoder::maybeBarcode(100, 180, BarcodeDecoder::PDF417), BarcodeDecoder::PDF417);
0101         QCOMPARE(BarcodeDecoder::maybeBarcode(180, 100, BarcodeDecoder::PDF417), BarcodeDecoder::PDF417);
0102         QCOMPARE(BarcodeDecoder::maybeBarcode(180, 100, BarcodeDecoder::AnySquare), BarcodeDecoder::None);
0103     }
0104 
0105     void testNoCode()
0106     {
0107         BarcodeDecoder decoder;
0108         QCOMPARE(decoder.decode({}, BarcodeDecoder::Any).contentType, BarcodeDecoder::None);
0109         QCOMPARE(decoder.decode({}, BarcodeDecoder::Any).toByteArray(), QByteArray());
0110         QCOMPARE(decoder.decode({}, BarcodeDecoder::Any).toString(), QString());
0111 
0112         QImage img(10, 10, QImage::Format_ARGB32);
0113         img.fill(Qt::black);
0114         QCOMPARE(decoder.decode(img, BarcodeDecoder::Any).contentType, BarcodeDecoder::None);
0115         QCOMPARE(decoder.decode(img, BarcodeDecoder::Any).toByteArray(), QByteArray());
0116         QCOMPARE(decoder.decode(img, BarcodeDecoder::Any).toString(), QString());
0117 
0118         img = QImage(200, 200, QImage::Format_ARGB32);
0119         img.fill(Qt::red);
0120         img.fill(Qt::black);
0121         QCOMPARE(decoder.decode(img, BarcodeDecoder::Any).contentType, BarcodeDecoder::None);
0122         QCOMPARE(decoder.decode(img, BarcodeDecoder::Any).toByteArray(), QByteArray());
0123         QCOMPARE(decoder.decode(img, BarcodeDecoder::Any).toString(), QString());
0124     }
0125 
0126     void testDecoderHints()
0127     {
0128         BarcodeDecoder decoder;
0129         QImage img(QStringLiteral(SOURCE_DIR "/barcodes/aztec.png"));
0130         QCOMPARE(decoder.decode(img, BarcodeDecoder::PDF417).toString(), QString());
0131         QCOMPARE(decoder.decode(img, BarcodeDecoder::AnySquare).toString(), QStringLiteral("This is an example Aztec symbol for Wikipedia."));
0132         QCOMPARE(decoder.decode(img, BarcodeDecoder::Any).toString(), QStringLiteral("This is an example Aztec symbol for Wikipedia."));
0133         QCOMPARE(decoder.decode(img, BarcodeDecoder::Aztec).toString(), QStringLiteral("This is an example Aztec symbol for Wikipedia."));
0134         QCOMPARE(decoder.decode(img, BarcodeDecoder::QRCode).toString(), QString());
0135 
0136         decoder.clearCache();
0137         QCOMPARE(decoder.decode(img, BarcodeDecoder::Any).toString(), QStringLiteral("This is an example Aztec symbol for Wikipedia."));
0138         QCOMPARE(decoder.decode(img, BarcodeDecoder::PDF417).toString(), QString());
0139         QCOMPARE(decoder.decode(img, BarcodeDecoder::QRCode).toString(), QString());
0140         QCOMPARE(decoder.decode(img, BarcodeDecoder::Aztec).toString(), QStringLiteral("This is an example Aztec symbol for Wikipedia."));
0141         QCOMPARE(decoder.decode(img, BarcodeDecoder::AnySquare).toString(), QStringLiteral("This is an example Aztec symbol for Wikipedia."));
0142     }
0143 
0144     void testContentTypeDetection()
0145     {
0146         BarcodeDecoder decoder;
0147         QImage img(QStringLiteral(SOURCE_DIR "/barcodes/aztec.png"));
0148         QCOMPARE(decoder.decode(img, BarcodeDecoder::Any).toString(), QStringLiteral("This is an example Aztec symbol for Wikipedia."));
0149         QCOMPARE(decoder.decode(img, BarcodeDecoder::Any).toByteArray(), QByteArray("This is an example Aztec symbol for Wikipedia."));
0150 
0151         img.load(QStringLiteral(SOURCE_DIR "/barcodes/uic918-3star.png"));
0152         QCOMPARE(decoder.decode(img, BarcodeDecoder::Any).toString(), QString());
0153         const auto ba = decoder.decode(img, BarcodeDecoder::Any).toByteArray();
0154         QCOMPARE(ba.size(), 351);
0155         QVERIFY(ba.startsWith("OTI010080000020"));
0156     }
0157 
0158     void test1D_data()
0159     {
0160         QTest::addColumn<QString>("filename");
0161         QTest::addColumn<BarcodeDecoder::BarcodeType>("type");
0162 
0163         QTest::newRow("code39") << QStringLiteral("code39.png") << BarcodeDecoder::Code39;
0164         QTest::newRow("code93") << QStringLiteral("code93.png") << BarcodeDecoder::Code93;
0165         QTest::newRow("code128") << QStringLiteral("code128.png") << BarcodeDecoder::Code128;
0166     }
0167 
0168     void test1D()
0169     {
0170         QFETCH(QString, filename);
0171         QFETCH(BarcodeDecoder::BarcodeType, type);
0172 
0173         QImage img(QLatin1StringView(SOURCE_DIR "/barcodes/") + filename);
0174         QVERIFY(!img.isNull());
0175 
0176         BarcodeDecoder decoder;
0177         QCOMPARE(decoder.decode(img, BarcodeDecoder::Any2D).toString(), QString());
0178         QCOMPARE(decoder.decode(img, type).toString(),
0179                  QLatin1StringView("123456789"));
0180         QCOMPARE(decoder.decode(img, BarcodeDecoder::Any1D).toString(),
0181                  QLatin1StringView("123456789"));
0182         QCOMPARE(decoder.decode(img, BarcodeDecoder::Any).toString(),
0183                  QLatin1StringView("123456789"));
0184     }
0185 };
0186 
0187 QTEST_APPLESS_MAIN(BarcodeDecoderTest)
0188 
0189 #include "barcodedecodertest.moc"