UPC 码(Universal Product Code,通用产品代码)是一种广泛使用的条形码系统,主要用于零售商品的标识和追踪。有两种主要格式:UPC-A 和 UPC-E。
UPC-A
- 长度12位数字。
- 适用于大型商品
UPC-E
- 长度8位数字。
- UPC-E是UPC-A的压缩版本,适用于小型商品。
校验码计算:
UPC-A跟UPC-E的算法一样,从右往左将奇数位数据值3跟偶数位的值相加,10减去得到的值的个位数即为校验码值(如果值为10则校验码为0)。
例如UPC-A码校验码计算:12345678901
奇数位的加权和为:13+93+73+53+33+1*3 = 78
偶数位的和为:0+8+6+4+2=20
总和为:98
校验码为:10 - 98%10 = 2
例如UPC-E码校验码计算:1234567
奇数位的加权和:73+53+33+13=48
偶数位的加权和:6+4+2=12
总和为:60
校验码:10 - 60%10=10 校验码为0
下边我们分别看看UPC-A跟UPC-E码的生成代码:
UPC-A:
std::string strContent = "12345678901";
CRect rcCode(0,0,200,50);
struct zint_symbol* symbol;
symbol = ZBarcode_Create();
symbol->symbology = BARCODE_UPCA;
symbol->input_mode = DATA_MODE; //数据编码格式
int nRet = ZBarcode_Encode_and_Buffer_Vector(symbol, (unsigned char*)strContent.c_str(), strContent.size(), 0);
if (nRet == 0)
{
ZBarcode_Print(symbol, 0);
//拿到绘制的所有黑色条
int nMinLen = 500;
int nMaxLen = 0;
std::vector<CRect> vecBlackRect;
if (symbol->vector)
{
struct zint_vector_rect* rect = symbol->vector->rectangles;
while (rect)
{
CRect rcTmp;
rcTmp.left = rect->x;
rcTmp.top = rect->y;
rcTmp.right = rcTmp.left + rect->width;
rcTmp.bottom = rcTmp.top + rect->height;
vecBlackRect.push_back(rcTmp);
if (rect->height > nMaxLen) nMaxLen = rect->height;
if (rect->height < nMinLen) nMinLen = rect->height;
rect = rect->next;
}
}
//计算在rcCode中绘制每个单位的宽跟标准的宽,主要绘制的时间用
double nDrawUint = (double)rcCode.Width() / symbol->width;
double nUint = (double)symbol->bitmap_width / symbol->width;
std::vector<CRect> vecDrawBlack; //绘制条码条的真实区域
for (int i = 0; i < vecBlackRect.size(); i++)
{
//分出那些是绘制长条,那些绘制短条
CRect rcTmp(vecBlackRect[i]);
rcTmp.left = rcTmp.left / nUint * nDrawUint;
rcTmp.right = rcTmp.right / nUint * nDrawUint;
if (rcTmp.Height() == nMaxLen)
{
//长条
//实际绘制的rc的top跟bottom即为rcCode的top跟bottom
}
else
{
//短条
//此处如果要区分文本位置则需要特殊处理
//如果文本在上边则绘制的rc的top为rcCode的top加上文本高度或者自定义的一个高度。rc的bottom为rcCode的bottom
//如果文本在下边则绘制的rc的top为rcCode的top。rc的bottom为rcCode的bottom减去文本高度或者自定义的一个高度
}
}
//拿到计算出的真实绘制区域然后再进行单个绘制或者以路径的方式绘制
//TODO:
//文本的绘制
//UPC-A码的文本分成了4部分,在绘制时分别绘制即可
//TODO:
UPC-E:
std::string strContent = "1234567";
CRect rcCode(0,0,200,50);
struct zint_symbol* symbol;
symbol = ZBarcode_Create();
symbol->symbology = BARCODE_UPCE;
symbol->input_mode = DATA_MODE; //数据编码格式
int nRet = ZBarcode_Encode_and_Buffer_Vector(symbol, (unsigned char*)strContent.c_str(), strContent.size(), 0);
if (nRet == 0)
{
ZBarcode_Print(symbol, 0);
//拿到绘制的所有黑色条
int nMinLen = 500;
int nMaxLen = 0;
std::vector<CRect> vecBlackRect;
if (symbol->vector)
{
struct zint_vector_rect* rect = symbol->vector->rectangles;
while (rect)
{
CRect rcTmp;
rcTmp.left = rect->x;
rcTmp.top = rect->y;
rcTmp.right = rcTmp.left + rect->width;
rcTmp.bottom = rcTmp.top + rect->height;
vecBlackRect.push_back(rcTmp);
if (rect->height > nMaxLen) nMaxLen = rect->height;
if (rect->height < nMinLen) nMinLen = rect->height;
rect = rect->next;
}
}
//计算在rcCode中绘制每个单位的宽跟标准的宽,主要绘制的时间用
double nDrawUint = (double)rcCode.Width() / symbol->width;
double nUint = (double)symbol->bitmap_width / symbol->width;
std::vector<CRect> vecDrawBlack; //绘制条码条的真实区域
for (int i = 0; i < vecBlackRect.size(); i++)
{
//分出那些是绘制长条,那些绘制短条
CRect rcTmp(vecBlackRect[i]);
rcTmp.left = rcTmp.left / nUint * nDrawUint;
rcTmp.right = rcTmp.right / nUint * nDrawUint;
if (rcTmp.Height() == nMaxLen)
{
//长条
//实际绘制的rc的top跟bottom即为rcCode的top跟bottom
}
else
{
//短条
//此处如果要区分文本位置则需要特殊处理
//如果文本在上边则绘制的rc的top为rcCode的top加上文本高度或者自定义的一个高度。rc的bottom为rcCode的bottom
//如果文本在下边则绘制的rc的top为rcCode的top。rc的bottom为rcCode的bottom减去文本高度或者自定义的一个高度
}
}
//拿到计算出的真实绘制区域然后再进行单个绘制或者以路径的方式绘制
//TODO:
//文本的绘制
//UPC-E码的文本分成了3部分,在绘制时分别绘制即可
//TODO:
}
具体绘制可参考128码的绘制。
4074

被折叠的 条评论
为什么被折叠?



