First, the origin of commodity bar code

Domestic commodity barcode generally adopts EAN-13 coding method, EAN-13 is European Article Number (European Article Number). It uses a total of 13 bits of coding method applied to the general end product bar code protocol and standards, mainly used in supermarkets and other retail scenarios.

Two, domestic product bar code range

Nationally available country codes are 690-699, of which 696-699 is not yet in use. The most common country code in life is 690-693. Among them:

  1. If it starts with 690 or 691, the vendor identification code is four digits and the item code is five digits.
  2. When starting with 692, 693, the vendor identification code is five digits and the item code is four digits.

Eg: Take 6902538004045 as an example. 690 [Manufacturing Code] 2538 [Manufacturer code] 00404 [Product identification code] 5 [Verification code]

Iii. Introduction to coding rules [1]

  • Left blank area: the area on the left of the bar code symbol with the same reflectivity as the empty area, and its minimum width is 11 modules wide.
  • Start symbol: a special symbol at the right of the left blank area of the bar code symbol, indicating the beginning of information. It consists of three modules.
  • Left-hand data character: A group of bar code characters to the right of the start character representing 6-digit information, consisting of 42 modules.
  • Middle separator: Located to the right of the left datagram, it is a special symbol that bisects barcode characters and consists of five modules.
  • Right data character: A group of 35 bar code characters representing 5-digit information to the right of the middle separator.
  • Parity symbol: the barcode character of the parity code located on the right of the data symbol. It consists of seven modules.
  • Terminator: a special symbol that indicates the end of information on the right side of the bar code check symbol. It consists of three modules.
  • Right-side blank: the area at the far right of the bar code symbol with the same reflectivity as the empty area, with a minimum width of 7 modules wide. To protect the width of the blank area on the right, you can add “>” in the lower right corner of the bar code symbol.
  • For people to read characters and pre-code: located below the bar code symbol, it is 13 digits corresponding to the barcode characters for people to identify, the most left one is called pre-code, now with implicit representation (in fact, has been hidden in the bar code). The OCR-B character set is preferred for human recognition characters, and the minimum distance between the top of the character and the bottom of the bar code is 0.5 module width. The leading code in the standard version of the bar code for commodities is printed on the left side of the start character of the bar code symbol.

Character set

  1. The barcode for a commodity can contain 10 digits: 0 to 9.
  2. Each bar code data character is composed of two bars and two blanks (two black and white). Each bar code data character is composed of 1 to 4 modules. The total number of modules for each bar code character is 7.
  3. Binary “1” represents the bar module, binary “0” represents the empty module;
  4. The specific rules for transcoding each digit are shown in the following table:
Numeric characters A subset of A subset of B C subset
0 0001101 0100111 1110010
1 0011001 0110011 1100110
2 0010011 0011011 1101100
3 0111101 0100001 1000010
4 0100011 0011101 1011100
5 0110001 0111001 1001110
6 0101111 0000101 1010000
7 0111011 0010001 1000100
8 0110111 0001001 1001000
9 0001011 0010111 1110100

The number of modules of bar (1) contained in the bar code characters in the subset A is odd, which is called odd arrangement. The number of modules of bar (1) contained in bar code characters in subsets B and C is even, which is called even permutation.

  1. The pre-code is determined by negotiation between countries. The default domestic pre-code is 6.
  2. The left-hand datagram is determined by the leading code as follows (the first digit must be sorted anyway) :
The front yard The left one The left 2 The left 3 Left 4 Left 5 The left 6
0 A A A A A A
1 A A B A B B
2 A A B B A B
3 A A B B B A
4 A B A A B B
5 A B B A A B
6 A B B B A A
7 A B A B A B
8 A B A B B A
9 A B B A B A

Eg: Take 6902538004045 as an example, front code: 6 left data character: 902538 Left data character: ABBBAA sequence to select the left data table code 9: A odd 0001011 white white black black black 0: B even 0100111 white black white black black black 2: B accidentally 0011011 white black black black black 5: B accidentally 0111001 white black black black black white black 3: A strange 0111101 white black black black black black black black black 8: A strange 0110111 white black black black black black black black black black

  1. All data characters on the right are coded by C subset.

Eg: Take 6902538004045 as an example on the right side of the data character: 004045 0: C couple 1110010 black black black white white black 0: C couple 1110010 black black black white white black 4: C couple 1011100 black black black black black white 0: C couple 1110010 black black black white white 4: C couple 1011100 black black black black white 5: C couple 1001110 black white black black black black black black

  1. The precode is hidden, usually allocated;
  2. The default start and end characters are 101, that is, black and white.
  3. The default middle separator is 01010, that is, white, black and white

5. Check character

Most coding protocols have a check bit, and EAN-13 is no exception. The function of the checksum is to check whether the first 12 digits are correct. When the barcode machine reads data, it will calculate the checksum of the data symbol and compare it with the checksum. Among them, the preposition codes are arranged in A subset by default [1].

  1. Generate check code
  • Add all the odd digits of the 12 data characters (check characters are generated later) from the left to get a number A
  • Add up all the even digits to get a number b
  • You multiply b by 3 and add it to A to get c
  • Mod C divided by 10
  • The remainder is the check code

Eg: Take 6920 [Manufacturing code] 15246 [Manufacturer code] 1023 [commodity identification code] as an example. Lead code: 6 Left data character: ABBBAA sequence is used to select table coding for data on the left. Right data service: 9 2 0 1 5 2 4 6 1 0 2 A B B B A A CCCCC C A = 6 + 9 + 5 + 2 = 22 B = 2 + 0 + 1 + 4 + 6 + 1 + 0 + 2 C = b * 3 + A = 16 * 3 + 22 = 60 check mark = C % 10 = 0

  1. Verify bar code
  • Sort the 13 characters in order from right to left.
  • Add the numbers in the second, fourth, sixth, eighth, tenth, and twelfth even digits and multiply the result by three to get P.
  • Add the odd bits of data such as 3, 5, 7, 9, 11 and 13, and wait for N.
  • N + P M
  • Divide M by 10 and take the remainder. Find the complement C with a remainder modulo 10.
  • If C is the same as the parity code, the decoding is correct.

Eg: P = (2 + 1 + 4 + 5 + 0 + 9) * 3 = 63 N = 0 + 6 + 2 + 1 + 2 + 6 = 17 N + P = 80 80% 10 = 0 ≠ 3 There is a problem with the barcode of this product!

Use Canvas to generate EAN-13 bar code

Once you understand the process, it shouldn’t be too much trouble to implement it. Some of the concepts mentioned above will be annotated to help you read. First, prepare the canvas canvas


      
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>EAN-13</title>
</head>
<style>
@font-face {
  font-family: "ocr-b-10bt";
  src: url("./src/static/font/OCRB10N.ttf");
}
</style>
<body>
<! -- Sand Sea rain digging gold anti-malicious crawler logo -->
<canvas id="canvas" style="width: 920px; height: 320px; font-family: 'ocr-b-10bt">
  <p>Your browser does not support Canvas!</p>
</canvas>
<script type="text/javascript" src="./src/ean_13/index.js"></script>
</body>
</html>

Copy the code

Character set:

const codeGroup = {
  '0': {
    A: '0001101'.B: '0100111'.C: '1110010'
  },
  '1': {
    A: '0011001'.B: '0110011'.C: '1100110'
  },
  '2': {
    A: '0010011'.B: '0011011'.C: '1101100'
  },
  '3': {
    A: '0111101'.B: '0100001'.C: '1000010'
  },
  '4': {
    A: '0100011'.B: '0011101'.C: '1011100'
  },
  '5': {
    A: '0110001'.B: '0111001'.C: '1001110'
  },
  '6': {
    A: '0101111'.B: '0000101'.C: '1010000'
  },
  '7': {
    A: '0111011'.B: '0010001'.C: '1000100'
  },
  '8': {
    A: '0110111'.B: '0001001'.C: '1001000'
  },
  '9': {
    A: '0001011'.B: '0010111'.C: '1110100'}}Copy the code

Pre-code transformation rule set:

const encodeGroup = {
  '0': 'AAAAAA'.'1': 'AABABB'.'2': 'AABBAB'.'3': 'AABBBA'.'4': 'ABAABB'.'5': 'ABBAAB'.'6': 'ABBBAA'.'7': 'ABABAB'.'8': 'ABABBA'.'9': 'ABBABA'
}
// "//
Copy the code

Canvas preparatory work

// Get the canvas element
let canvas = document.getElementById('canvas')
// Get the canvas element box width and height
let cw = canvas.offsetWidth
let ch = canvas.offsetHeight
// Sets the width and height of the actual canvas element
canvas.width = cw
canvas.height = ch
// "//
// Instantiate the environment for drawing on the canvas
let ctx = canvas.getContext('2d')
// The bar code is filled with white background
ctx.fillStyle = 'white'
ctx.fillRect(0.0, cw, ch)
// Calculate the width of a module
let unit = parseInt(cw / 115)
PS: the minimum width of the left blank area is 11 modules wide
let begin = 11 * unit
Copy the code

Starting identifier:

for (let i = 0; i < 3; i++) {
    if (i % 2= = =0) {
      ctx.fillStyle = 'black'
    } else {
      ctx.fillStyle = 'white'
    }
    ctx.fillRect(begin + i * unit, 0, unit, ch - 5)}Copy the code

Middle separator:

for (let i = 0; i < 5; i++) {
  if (i % 2= = =0) {
    ctx.fillStyle = 'white'
  } else {
    ctx.fillStyle = 'black'
  }
  ctx.fillRect(begin + unit * (3 + 6 * 7 + i), 0, unit, ch - 5)}// Stop malicious crawlers from digging gold
Copy the code

Termination:

for (let i = 0; i < 3; i++) {
  if (i % 2= = =0) {
    ctx.fillStyle = 'black'
  } else {
    ctx.fillStyle = 'white'
  }
  ctx.fillRect(begin + (3 + 6 * 7 * 2 + 5 + i) * unit, 0, unit, ch - 5)}// Dig gold sand sea to listen to rain to prevent malicious reptile mark
Copy the code

Left and right data characters:

// Select the left data character encoding rule according to the leading code
let selectEncodeRule = encodeGroup[code[0]]
// Draw the position of the left datagram
let _begin = begin + 3 * unit
for (let i = 1; i < 7; i++) {
  // Dig gold sand sea to listen to rain to prevent malicious reptile mark
  // Retrieve the corresponding encoding of the number
  let _encode = codeGroup[code[i]][selectEncodeRule[i - 1]]
  for (let j = 0; j < _encode.length; j++) {
    if (_encode[j] === '0') {
      ctx.fillStyle = 'white'
    } else {
      ctx.fillStyle = 'black'
    }
    ctx.fillRect(_begin + unit * j, 0, unit, ch - 80)
  }
  _begin += 7 * unit
}
// Move the position to the right of the middle delimiter
_begin += 5 * unit
for (let i = 7; i < 13; i++) {
  // Retrieve the corresponding encoding of the number
  let _encode = codeGroup[code[i]]['C']
  for (let j = 0; j < _encode.length; j++) {
    if (_encode[j] === '0') {
      ctx.fillStyle = 'white'
    } else {
      ctx.fillStyle = 'black'
    }
    ctx.fillRect(_begin + unit * j, 0, unit, ch - 80)
  }
  _begin += 7 * unit
}
Copy the code

Draw human-readable characters (using OCR-B-10BT font)

// Set the font
ctx.font = 'Normal 80px ocr-b-10bt'
// Set the alignment
ctx.textAlign = 'left'
// Set the fill color
ctx.fillStyle = '# 000'
/ / front yards
ctx.fillText(code[0].10, ch - 5)
// "//
for (let i = 1; i < 7; i++) {
  ctx.fillText(code[i], 125 + 53 * (i - 1), ch - 5)}for (let i = 7; i < 13; i++) {
  ctx.fillText(code[i], 175 + 53 * (i - 1), ch - 5)}Copy the code

Add: q1.unit calculates why divide by 110? A1: The length of the left blank area is 11, the length of the start and end characters is 6, the length of the middle separator is 5, the length of the left and right data characters is 84, and the minimum length of the right blank area is 7(take 9 here for the convenience of rounding). 11 + 6 + 5 + 84 + 9 = 115 Q2. 125 for drawing readable characters 53 How are these constants derived? A2: It is obtained by manual debugging of canvas size and font size. The writing here is not very good. If it can be obtained dynamically, the effect will be better.

Finally, take a look at the barcode effect of the product we generated. You can use the following code to download the product

function saveFile (data, filename) {
  let saveLink = document.createElementNS('http://www.w3.org/1999/xhtml'.'a')
  saveLink.href = data
  saveLink.download = filename

  let event = document.createEvent('MouseEvents')
  event.initMouseEvent('click'.true.false.window.0.0.0.0.0.false.false.false.false.0.null)
  saveLink.dispatchEvent(event)
}
// Download the anti-malicious crawler logo
function download () {
  let canvas = document.getElementById('canvas')
  let dataURL = canvas.toDataURL('image/png')
  saveFile(dataURL, this.code)
}
Copy the code

Let’s take a look at the qr code generated for the product (you can scan it with the App to see how it looks) :

conclusion

I believe that reading this article will have more understanding of the barcode of goods, then the barcode type only EAN-13? The answer is no. The codes commonly used in the world include EAN bar Code, UPC bar Code, 25 bar Code, cross 25 bar Code, Codebar bar Code, Code 39 bar Code and Code 128 bar Code [2]. In fact, their general coding structure is similar, similar to the cognition of bar code, I believe that other bar codes you can more easily.

Q & A

Q1: The precode is hidden. How does the scanner recognize the precode? A1: It is said in the article that the left datagram is generated according to the leading code, so the A and B sequences of the left datagram can deduce what the leading code is.

Q2: What if the scanner is swept backwards? A2: This is also easy to solve. The left datagram is encoded by sequence A and B, while the right datagram is all encoded by sequence C, and the first position of the left datagram must be encoded by sequence A. If the scan gun sweeps the first C sequence then the scan gun knows it’s backwards and will reverse it.

Q3: Bar code manufacturers of various commodities have similarities and differences, and cannot guarantee that a module of all commodity codes is the same width. In such a scenario, can the scanning gun still work normally? A3: As we mentioned, the commodity bar code starts and ends with 101, which tells the scanner how wide a block should be. With reference units, it’s easy to figure out the contents of the data code.

Q4: The barcode is damaged or defaced. can it be detected by the scanning gun? A4: In this sub-scenario, if the bar code is damaged horizontally (long side), it is possible to identify it. However, if it is contaminated or the longitudinal (short side) is lost then the data bytes are lost and there is a high probability of unrecognizable problems.

Q5: Why is the code only generated and not recognized? A5: This article is a restorative writing of Shahai. Since it took 2 days from preparation to writing this article, it has not been realized yet, and will be supplemented later if there is time. Here the pure front-end identification technology design required for identification is briefly mentioned.

1. Switch on the camera of the phone at the front end of the page, take pictures and cache them to the front end. 2. The recognized image is decoded to obtain the left data character and the right data character, and the leading code 4 is obtained according to the left data character. Verification difficulties: how to identify if the picture is not clear, filter the damage and defilement of barcode, how to verify incomplete barcode, etc

About me

Sand Sea listening to rain

  1. Technology stack: big front end | | C/C + + | | embedded C # | Python | | | large data visualization
  2. Welcome to dig gold or micro blog private message to discuss a variety of technical points, front and rear end debugging ability MAX
  3. You are welcome to invite various open source authors to do some fun technology together
  4. Recently in part of the front-end source code library debugging comb, hope to have the opportunity to share a written source code reading new posture
  5. Looking forward to receiving your position invitation (Senior front-end architecture big front-end leader Base Hangzhou/Chengdu)

Above, hard reading, shun song near qi. Sand sea rain released in nuggets

reference

【1】 ean-13 Baidu encyclopedia baike.baidu.com/item/EAN-13… [2] Song Jiemin, Yuan Qiang, Chinese Medicine Commodity Science, Zhejiang Science and Technology Press,2016.06, page 23