128 lines
4.2 KiB
C++
128 lines
4.2 KiB
C++
// This file is part of OpenCV project.
|
|
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
|
// of this distribution and at http://opencv.org/license.html.
|
|
//
|
|
// Tencent is pleased to support the open source community by making WeChat QRCode available.
|
|
// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
|
|
#include "../../precomp.hpp"
|
|
#include "unicomblock.hpp"
|
|
|
|
namespace zxing {
|
|
short UnicomBlock::SEARCH_POS[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
|
|
UnicomBlock::UnicomBlock(int iMaxHeight, int iMaxWidth)
|
|
: m_iHeight(iMaxHeight), m_iWidth(iMaxWidth), m_bInit(false) {}
|
|
|
|
UnicomBlock::~UnicomBlock() {}
|
|
|
|
void UnicomBlock::Init() {
|
|
if (m_bInit) return;
|
|
m_vcIndex = std::vector<unsigned short>(m_iHeight * m_iWidth, 0);
|
|
m_vcCount = std::vector<unsigned short>(m_iHeight * m_iWidth, 0);
|
|
m_vcMinPnt = std::vector<int>(m_iHeight * m_iWidth, 0);
|
|
m_vcMaxPnt = std::vector<int>(m_iHeight * m_iWidth, 0);
|
|
m_vcQueue = std::vector<int>(m_iHeight * m_iWidth, 0);
|
|
m_bInit = true;
|
|
}
|
|
|
|
void UnicomBlock::Reset(Ref<BitMatrix> poImage) {
|
|
m_poImage = poImage;
|
|
memset(&m_vcIndex[0], 0, m_vcIndex.size() * sizeof(short));
|
|
m_iNowIdx = 0;
|
|
}
|
|
|
|
unsigned short UnicomBlock::GetUnicomBlockIndex(int y, int x) {
|
|
if (y >= m_iHeight || x >= m_iWidth) return 0;
|
|
if (m_vcIndex[y * m_iWidth + x]) return m_vcIndex[y * m_iWidth + x];
|
|
Bfs(y, x);
|
|
return m_vcIndex[y * m_iWidth + x];
|
|
}
|
|
|
|
int UnicomBlock::GetUnicomBlockSize(int y, int x) {
|
|
if (y >= m_iHeight || x >= m_iWidth) return 0;
|
|
if (m_vcIndex[y * m_iWidth + x]) return m_vcCount[y * m_iWidth + x];
|
|
Bfs(y, x);
|
|
return m_vcCount[y * m_iWidth + x];
|
|
}
|
|
|
|
int UnicomBlock::GetMinPoint(int y, int x, int &iMinY, int &iMinX) {
|
|
if (y >= m_iHeight || x >= m_iWidth) return -1;
|
|
if (m_vcIndex[y * m_iWidth + x]) {
|
|
iMinY = m_vcMinPnt[y * m_iWidth + x] >> 16;
|
|
iMinX = m_vcMinPnt[y * m_iWidth + x] & (0xFFFF);
|
|
return 0;
|
|
}
|
|
Bfs(y, x);
|
|
iMinY = m_vcMinPnt[y * m_iWidth + x] >> 16;
|
|
iMinX = m_vcMinPnt[y * m_iWidth + x] & (0xFFFF);
|
|
return 0;
|
|
}
|
|
|
|
int UnicomBlock::GetMaxPoint(int y, int x, int &iMaxY, int &iMaxX) {
|
|
if (y >= m_iHeight || x >= m_iWidth) return -1;
|
|
if (m_vcIndex[y * m_iWidth + x]) {
|
|
iMaxY = m_vcMaxPnt[y * m_iWidth + x] >> 16;
|
|
iMaxX = m_vcMaxPnt[y * m_iWidth + x] & (0xFFFF);
|
|
return 0;
|
|
}
|
|
Bfs(y, x);
|
|
iMaxY = m_vcMaxPnt[y * m_iWidth + x] >> 16;
|
|
iMaxX = m_vcMaxPnt[y * m_iWidth + x] & (0xFFFF);
|
|
return 0;
|
|
}
|
|
|
|
void UnicomBlock::Bfs(int y, int x) {
|
|
m_iNowIdx++;
|
|
|
|
int iFront = 0;
|
|
int iTail = 0;
|
|
int iCount = 1;
|
|
|
|
int iMaxX = x, iMaxY = y;
|
|
int iMinX = x, iMinY = y;
|
|
|
|
const bool bValue = (m_poImage->get(x, y) != (unsigned char)0);
|
|
|
|
m_vcIndex[y * m_iWidth + x] = m_iNowIdx;
|
|
m_vcQueue[iTail++] = y << 16 | x;
|
|
|
|
while (iFront < iTail) {
|
|
int iNode = m_vcQueue[iFront++];
|
|
int iX = iNode & (0xFFFF);
|
|
int iY = iNode >> 16;
|
|
iMaxX = max(iX, iMaxX);
|
|
iMaxY = max(iY, iMaxY);
|
|
iMinX = min(iX, iMinX);
|
|
iMinY = min(iY, iMinY);
|
|
|
|
iCount++;
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
const int iNextX = iX + SEARCH_POS[i][0], iNextY = iY + SEARCH_POS[i][1];
|
|
const int iPosition = iNextY * m_iWidth + iNextX;
|
|
|
|
if (iPosition >= 0 && iPosition < int(m_vcIndex.size()) && 0 == m_vcIndex[iPosition]) {
|
|
if (iNextX < 0 || iNextX >= m_poImage->getWidth() || iNextY < 0 ||
|
|
iNextY >= m_poImage->getHeight() ||
|
|
bValue != (m_poImage->get(iNextX, iNextY) != (unsigned char)0))
|
|
continue;
|
|
|
|
m_vcIndex[iPosition] = m_iNowIdx;
|
|
m_vcQueue[iTail++] = iNextY << 16 | iNextX;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (iCount >= (1 << 16) - 1) iCount = 0xFFFF;
|
|
|
|
const int iMinCombine = iMinY << 16 | iMinX;
|
|
const int iMaxCombine = iMaxY << 16 | iMaxX;
|
|
for (int i = 0; i < iTail; ++i) {
|
|
const int iPosition = (m_vcQueue[i] >> 16) * m_iWidth + (m_vcQueue[i] & (0xFFFF));
|
|
|
|
m_vcCount[iPosition] = iCount;
|
|
m_vcMinPnt[iPosition] = iMinCombine;
|
|
m_vcMaxPnt[iPosition] = iMaxCombine;
|
|
}
|
|
}
|
|
} // namespace zxing
|