📄 sgxbarcode.cpp
字号:
SFXAnsiStringConstRef SGXBarCode::Read(SFBBitmapSmpConstRef bitmap, UInt16 y) static_throws
{
Clear();
_result.Clear();
static_throw(SFERR_NO_ERROR);
CreateGrayScale(bitmap, y);
CreateBarBit();
if (static_catch() == SFERR_NO_ERROR) {
switch (_barcodeType) {
case BARCODE_JAN8:
ProcessJAN8();
break;
case BARCODE_JAN13:
ProcessJAN13();
break;
}
}
Clear();
return _result;
}
Void SGXBarCode::CreateGrayScale(SFBBitmapSmpConstRef bitmap, UInt16 y) static_throws
{
if (static_catch() != SFERR_NO_ERROR) {
return;
}
SGXBitmap myBitmap;
if (myBitmap.Create(bitmap) != SFERR_NO_ERROR) {
static_throw(SFERR_NO_MEMORY);
return;
}
SInt32Const bmpWidth(myBitmap.GetWidth()), bmpHeight(myBitmap.GetHeight());
if (y >= bmpHeight) {
y = 0;
}
_grayscaleWidth = bmpWidth;
_grayscaleHeight = bmpHeight - y;
if (_grayscaleHeight > _height) {
_grayscaleHeight = _height;
}
_grayscale = new UInt08[_grayscaleWidth * _grayscaleHeight];
if (!_grayscale) {
static_throw(SFERR_NO_MEMORY);
return;
}
// 僇儔乕夋憸偺偆偪昁梫側晹暘傪僌儗僀丒僗働乕儖偵曄姺
SInt32 i, j, red, green, blue, gray;
SFXRGBColor rgb;
for (j = 0; j < _grayscaleHeight; ++j) {
for (i = 0; i < _grayscaleWidth; ++i) {
rgb = myBitmap.GetPixel(static_cast<SInt16>(i), static_cast<SInt16>(j + y));
red = rgb.GetRed();
green = rgb.GetGreen();
blue = rgb.GetBlue();
gray = (299 * red + 587 * green + 114 * blue) / 1000;
_grayscale[ToIndex(i, j)] = static_cast<UInt08>(gray);
}
}
}
Void SGXBarCode::CreateBarBit(Void) static_throws
{
if (static_catch() != SFERR_NO_ERROR) {
return;
}
SInt32 i, j, k, barLeft, barRight, barLength;
SGXBARCODE_FLOAT ratio, kd;
SInt32Ptr bar_t(null), bar_tc(null);
UInt08Ptr grayBar(null);
if (!SearchLeftRight(&barLeft, &barRight)) {
static_throw(ERR_INVALID_BARCODE);
return;
}
switch (_barcodeType) {
case BARCODE_JAN8:
barLength = BARLENGTH_JAN8;
break;
case BARCODE_JAN13:
barLength = BARLENGTH_JAN13;
break;
default:
barLength = 0;
}
ratio = static_cast<SGXBARCODE_FLOAT>(barLength) / static_cast<SGXBARCODE_FLOAT>(barRight - barLeft + 1);
bar_t = new SInt32[barLength];
bar_tc = new SInt32[barLength];
grayBar = new UInt08[barLength];
if (!bar_t || !bar_tc || !grayBar) {
if (bar_t) {
delete [] bar_t;
}
if (bar_tc) {
delete [] bar_tc;
}
if (grayBar) {
delete [] grayBar;
}
static_throw(SFERR_NO_MEMORY);
return;
}
SFXHelper::memset(bar_t, 0, sizeof(SInt32) * barLength);
SFXHelper::memset(bar_tc, 0, sizeof(SInt32) * barLength);
for (i = barLeft; i <= barRight; ++i) {
kd = static_cast<SGXBARCODE_FLOAT>(i - barLeft) * ratio;
k = static_cast<SInt32>(kd);
for (j = 0; j < _grayscaleHeight; ++j) {
bar_t[k] += _grayscale[ToIndex(i, j)];
++bar_tc[k];
}
}
for (i = 0; i < barLength; ++i) {
if (bar_tc[i] != 0) {
grayBar[i] = static_cast<UInt08>(bar_t[i] / bar_tc[i]); // 僲僀僘懳嶔傕寭偹傞
}
else {
grayBar[i] = UINT08_MAXIMUM;
}
}
UInt08Const threshold(GetThreshold(grayBar, barLength));
_barBit = new Bool[barLength];
if (_barBit) {
_barBitSize = static_cast<SInt16>(barLength);
for (i = 0; i < barLength; ++i) {
_barBit[i] = (grayBar[i] < threshold);
}
}
else {
static_throw(SFERR_NO_MEMORY);
}
delete [] bar_t;
delete [] bar_tc;
delete [] grayBar;
delete [] _grayscale;
_grayscale = null;
_grayscaleWidth = _grayscaleHeight = 0;
}
UInt08 SGXBarCode::GetThreshold(UInt08ConstPtr pGray, SInt32 size)
{
SInt32 i;
UInt08 min, max;
min = UINT08_MAXIMUM;
max = 0;
for (i = 0; i < size; i++) {
if (pGray[i] < min) {
min = pGray[i];
} else if (pGray[i] > max) {
max = pGray[i];
}
}
// DBGPRINTF("%d %d", (min + max) >> 1, result);
return (UInt08)((min + max) >> 1);
}
/*
// 敾暿暘愅朄偵傛傞鑷抣偺専弌
UInt08 SGXBarCode::GetThreshold(UInt08ConstPtr pGray, SInt32 size)
{
SInt32Const brightnessMax(UINT08_MAXIMUM + 1);
SInt32 i, j, n1, n2, temp(0);
SGXBARCODE_FLOAT mu1, mu2, mu(0.0), sigma1, sigma2, sigma_w, sigma_b, w, w_max(-1.0);
UInt08 histo[brightnessMax], result(0);
// 僸僗僩僌儔儉偺嶌惉
SFXHelper::memset(histo, 0, sizeof(histo));
for (i = 0; i < size; ++i) {
++histo[pGray[i]];
temp += pGray[i];
}
// 鑷抣偺寁嶼
mu = static_cast<SGXBARCODE_FLOAT>(temp) / static_cast<SGXBARCODE_FLOAT>(size);
for (i = 0; i < brightnessMax; ++i) {
n1 = n2 = 0;
sigma1 = sigma2 = 0.0;
temp = 0;
for (j = 0; j < i; ++j) {
n1 += histo[j];
temp += (j * histo[j]);
}
mu1 = static_cast<SGXBARCODE_FLOAT>(temp) / static_cast<SGXBARCODE_FLOAT>(n1);
for (j = 0; j < i; ++j) {
sigma1 += (static_cast<SGXBARCODE_FLOAT>(histo[j]) * Sqr(static_cast<SGXBARCODE_FLOAT>(j) - mu1));
}
sigma1 /= static_cast<SGXBARCODE_FLOAT>(n1);
temp = 0;
for (j = i; j < brightnessMax; ++j) {
n2 += histo[j];
temp += (j * histo[j]);
}
mu2 = static_cast<SGXBARCODE_FLOAT>(temp) / static_cast<SGXBARCODE_FLOAT>(n2);
for (j = i; j < brightnessMax; ++j) {
sigma2 += (static_cast<SGXBARCODE_FLOAT>(histo[j]) * Sqr(static_cast<SGXBARCODE_FLOAT>(j) - mu2));
}
sigma2 /= static_cast<SGXBARCODE_FLOAT>(n2);
sigma_w = static_cast<SGXBARCODE_FLOAT>(n1) * sigma1 + static_cast<SGXBARCODE_FLOAT>(n2) * sigma2;
sigma_b = static_cast<SGXBARCODE_FLOAT>(n1) * Sqr(mu1 - mu) + static_cast<SGXBARCODE_FLOAT>(n2) * Sqr(mu2 - mu);
w = sigma_b / sigma_w;
if (w > w_max) {
result = static_cast<UInt08>(i);
w_max = w;
}
}
if (result < 1) {
result = 1;
}
return result;
}
*/
/*
// 僶乕偺嵍塃偺奐巒埵抲傪扵偡 (JAN-8 / JAN-13 埲奜偼曄峏偑昁梫)
Bool SGXBarCode::SearchLeftRight(SInt32Ptr pLeft, SInt32Ptr pRight) const
{
SInt32 left(_grayscaleWidth), right(0);
UInt08Const threshold(GetThreshold(_grayscale, _grayscaleWidth * _grayscaleHeight));
SInt32 i, j;
for (j = 0; j < _grayscaleHeight; ++j) {
for (i = 0; i < _grayscaleWidth; ++i) {
if (_grayscale[ToIndex(i, j)] < threshold && i < left) {
left = i;
break;
}
}
for (i = _grayscaleWidth - 1; i >= 0; --i) {
if (_grayscale[ToIndex(i, j)] < threshold && i > right) {
right = i;
break;
}
}
}
if (left < right) {
*pLeft = left;
*pRight = right;
return true;
}
else {
*pLeft = 0;
*pRight = _grayscaleWidth - 1;
return false;
}
}
*/
// 僶乕偺嵍塃偺奐巒埵抲傪扵偡 (JAN-8 / JAN-13 埲奜偼曄峏偑昁梫)
Bool SGXBarCode::SearchLeftRight(SInt32Ptr pLeft, SInt32Ptr pRight) const
{
UInt08Const threshold(GetThreshold(_grayscale, _grayscaleWidth * _grayscaleHeight));
Bool result(false);
SInt32 i, tleft, tright, left(_grayscaleWidth), right(0);
for (i = 0; i < _grayscaleHeight; ++i) {
if (SearchLeftRightJAN(_grayscale + i * _grayscaleWidth, _grayscaleWidth, threshold, &tleft, &tright)) {
if (tleft < left) {
left = tleft;
}
if (tright > right) {
right = tright;
}
result = true;
}
}
if (result) {
*pLeft = left;
*pRight = right;
}
else {
*pLeft = 0;
*pRight = _grayscaleWidth - 1;
}
return result;
}
// JAN-8 / JAN-13 偺僶乕僐乕僪偺椉抂傪専弌偡傞
Bool SGXBarCode::SearchLeftRightJAN(UInt08ConstPtr pGray, SInt32 width, UInt08 threshold, SInt32Ptr pLeft, SInt32Ptr pRight)
{
TYPE_STRUCT_BAR *bars = NULL;
SInt32 i, barCount(0), len, len1, len2, minLen, maxLen;
Bool result1(false), result2(false), white;
bars = new TYPE_STRUCT_BAR[width];
if (!bars) {
return false;
}
bars[0].isWhite = (pGray[0] >= threshold);
bars[0].barLeft = 0;
bars[0].barRight = 0;
// 僶乕偺宍忬傪挷傋傞
for (i = 1; i < width; ++i) {
white = (pGray[i] >= threshold);
if (bars[barCount].isWhite == white) {
bars[barCount].barRight = i;
}
else {
++barCount;
bars[barCount].isWhite = white;
bars[barCount].barLeft = i;
bars[barCount].barRight = i;
}
}
++barCount;
SInt32Const loopMax(barCount - 2);
for (i = 0; i < loopMax; ++i) {
if (bars[i].isWhite) {
continue;
}
len = bars[i].barRight - bars[i].barLeft + 1;
len1 = bars[i + 1].barRight - bars[i + 1].barLeft + 1;
len2 = bars[i + 2].barRight - bars[i + 2].barLeft + 1;
minLen = len - BAR_LENGTH_ERROR;
if (minLen < 1) {
minLen = 1;
}
maxLen = len + BAR_LENGTH_ERROR;
if (len1 >= minLen && len1 <= maxLen && len2 >= minLen && len2 <= maxLen) {
*pLeft = bars[i].barLeft;
result1 = true;
break;
}
}
for (i = barCount - 1; i >= 2; --i) {
if (bars[i].isWhite) {
continue;
}
len = bars[i].barRight - bars[i].barLeft + 1;
len1 = bars[i - 1].barRight - bars[i - 1].barLeft + 1;
len2 = bars[i - 2].barRight - bars[i - 2].barLeft + 1;
minLen = len - BAR_LENGTH_ERROR;
if (minLen < 1) {
minLen = 1;
}
maxLen = len + BAR_LENGTH_ERROR;
if (len1 >= minLen && len1 <= maxLen && len2 >= minLen && len2 <= maxLen) {
*pRight = bars[i].barRight;
result2 = true;
break;
}
}
delete [] bars;
if (!result1 || !result2) {
*pLeft = 0;
*pRight = width - 1;
return false;
}
else {
return true;
}
}
SFXAnsiStringConstRef SGXBarCode::GetResult(Void) const
{
return _result;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -