Files
ANSLibs/QRCode/oned/ODDataBarCommon.h

135 lines
3.4 KiB
C++

/*
* Copyright 2020 Axel Waggershauser
*/
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "ODRowReader.h"
#include "Pattern.h"
#include "Barcode.h"
#include <array>
#include <cmath>
namespace ZXing::OneD::DataBar {
inline bool IsFinder(int a, int b, int c, int d, int e)
{
// a,b,c,d,e, g | sum(a..e) = 15
// ------------
// 1,1,2
// | | |,1,1, 1
// 3,8,9
// use only pairs of bar+space to limit effect of poor threshold:
// b+c can be 10, 11 or 12 modules, d+e is always 2
int w = 2 * (b + c), n = d + e;
// the offsets (5 and 2) are there to reduce quantization effects for small module sizes
// TODO: review after switch to sub-pixel bar width calculation
bool x = (w + 5 > 9 * n) &&
(w - 5 < 13 * n) &&
// (b < 5 + 9 * d) &&
// (c < 5 + 10 * e) &&
(a < 2 + 4 * e) &&
(4 * a > n);
#if !defined(NDEBUG) && 0
printf("[");
for (bool v :
{w + 5 > 9 * n,
w - 5 < 13 * n,
// b < 5 + 9 * d,
// c < 5 + 10 * e,
a < 2 + 4 * e,
4 * a > n})
printf(" %d", v);
printf("]"); fflush(stdout);
#endif
return x;
};
inline PatternView Finder(const PatternView& view)
{
return view.subView(8, 5);
}
inline PatternView LeftChar(const PatternView& view)
{
return view.subView(0, 8);
}
inline PatternView RightChar(const PatternView& view)
{
return view.subView(13, 8);
}
inline float ModSizeFinder(const PatternView& view)
{
return Finder(view).sum() / 15.f;
}
inline bool IsGuard(int a, int b)
{
// printf(" (%d, %d)", a, b);
return a > b * 3 / 4 - 2 && a < b * 5 / 4 + 2;
}
inline bool IsCharacter(const PatternView& view, int modules, float modSizeRef)
{
float err = std::abs(float(view.sum()) / modules / modSizeRef - 1);
return err < 0.1f;
}
struct Character
{
int value = -1, checksum = 0;
operator bool() const noexcept { return value != -1; }
bool operator==(const Character& o) const noexcept { return value == o.value && checksum == o.checksum; }
bool operator!=(const Character& o) const { return !(*this == o); }
};
struct Pair
{
Character left, right;
int finder = 0, xStart = -1, xStop = 1, y = -1, count = 1;
operator bool() const noexcept { return finder != 0; }
bool operator==(const Pair& o) const noexcept { return finder == o.finder && left == o.left && right == o.right; }
bool operator!=(const Pair& o) const noexcept { return !(*this == o); }
};
struct PairHash
{
std::size_t operator()(const Pair& p) const noexcept
{
return p.left.value ^ p.left.checksum ^ p.right.value ^ p.right.checksum ^ p.finder;
}
};
constexpr int FULL_PAIR_SIZE = 8 + 5 + 8;
constexpr int HALF_PAIR_SIZE = 8 + 5 + 2; // half has to be followed by a guard pattern
template<typename T>
int ParseFinderPattern(const PatternView& view, bool reversed, T l2rPattern, T r2lPattern)
{
constexpr float MAX_AVG_VARIANCE = 0.2f;
constexpr float MAX_INDIVIDUAL_VARIANCE = 0.45f;
int i = 1 + RowReader::DecodeDigit(view, reversed ? r2lPattern : l2rPattern, MAX_AVG_VARIANCE,
MAX_INDIVIDUAL_VARIANCE, true);
return reversed ? -i : i;
}
using Array4I = std::array<int, 4>;
bool ReadDataCharacterRaw(const PatternView& view, int numModules, bool reversed, Array4I& oddPattern,
Array4I& evnPattern);
int GetValue(const Array4I& widths, int maxWidth, bool noNarrow);
Position EstimatePosition(const Pair& first, const Pair& last);
int EstimateLineCount(const Pair& first, const Pair& last);
} // namespace ZXing::OneD::DataBar