⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sgxbarcode.cpp

📁 一个基于BREW上的WEB service程序,通过扫描图书的条形码,登陆WEB站点,利用SOAP-RPC来查询图书信息.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
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 + -