Class: Barcode1DTools::EAN8
- Defined in:
- lib/barcode1dtools/ean8.rb
Overview
Barcode1DTools::EAN_8 - Create pattern for EAN-8 barcodes. The value encoded is a 7-digit number, and a checksum digit will be added. You can add the option # :checksum_included => true when initializing to specify that you have already included a checksum.
Example
num = '96385074'
bc = Barcode1DTools::EAN8.new(num)
pattern = bc.
rle_pattern = bc.rle
width = bc.width
check_digit = Barcode1DTools::EAN83.generate_check_digit_for(num)
Other Information
The object created is immutable.
Formats
There are two formats for the returned pattern (wn format is not available):
bars - 1s and 0s specifying black lines and white spaces. Actual characters can be changed from “1” and 0“ with options :line_character and :space_character.
rle - Run-length-encoded version of the pattern. The first number is always a black line, with subsequent digits alternating between spaces and lines. The digits specify the width of each line or space.
The “width” method will tell you the total end-to-end width, in units, of the entire barcode.
Unlike some of the other barcodes, e.g. Code 3 of 9, there is no “wnstr” for EAN & UPC style barcodes because the bars and spaces are variable width from 1 to 4 units.
An EAN-8 barcode has 3 elements:
-
A 2 or 3 digit “number system” designation
-
A 4 or 5 digit manufacturer’s code
-
A single digit checksum
Note than an EAN-8 is not analogous to a UPC-E. In particular, there is no way to create an EAN-13 from and EAN-8 and vice versa. The numbers are assigned within EAN-8 by a central authority.
The bar patterns are the same as EAN-13, with nothing encoded in the parity. All bars on the left use the “odd” parity set.
Rendering
When rendered, two sets of four digits are shown at the bottom of the code, aligned with the bottom of the code, and with the middle guard pattern bars extending down between them. A supplemental 2 or 5 may be used.
Constant Summary collapse
- LEFT_PATTERNS =
Left patterns from EAN-13
EAN13::LEFT_PATTERNS
- LEFT_PATTERNS_RLE =
Left rle patterns from EAN-13
EAN13::LEFT_PATTERNS_RLE
- RIGHT_PATTERNS =
Right patterns from EAN-13
EAN13::RIGHT_PATTERNS
- RIGHT_PATTERNS_RLE =
Right rle patterns from EAN-13
EAN13::RIGHT_PATTERNS_RLE
- SIDE_GUARD_PATTERN =
Guard pattern from EAN-13
EAN13::SIDE_GUARD_PATTERN
- MIDDLE_GUARD_PATTERN =
Middle Guard pattern from EAN-13
EAN13::MIDDLE_GUARD_PATTERN
- SIDE_GUARD_PATTERN_RLE =
Guard pattern from EAN-13 as an rle
EAN13::SIDE_GUARD_PATTERN_RLE
- MIDDLE_GUARD_PATTERN_RLE =
Middle Guard pattern from EAN-13 as an rle
EAN13::MIDDLE_GUARD_PATTERN_RLE
- DEFAULT_OPTIONS =
{ :line_character => '1', :space_character => '0' }
Instance Attribute Summary collapse
-
#number_system ⇒ Object
readonly
Specific for EAN-8 - the number system part of the payload.
-
#product_code ⇒ Object
readonly
Specific for EAN-8 - the product code part of the payload.
Attributes inherited from Barcode1D
#check_digit, #encoded_string, #options, #value
Class Method Summary collapse
-
.can_encode?(value, options = nil) ⇒ Boolean
Returns true if value can be encoded in EAN-8 - must be 7-8 digits.
-
.decode(str) ⇒ Object
Decode a string representing an rle or bar pattern EAN-13.
-
.generate_check_digit_for(value) ⇒ Object
Generates check digit given a string to encode.
-
.validate_check_digit_for(value) ⇒ Object
Validates the check digit given a string - assumes check digit is last digit of string.
Instance Method Summary collapse
-
#bars ⇒ Object
Returns 1s and 0s (for “black” and “white”).
-
#initialize(value, options = {}) ⇒ EAN8
constructor
Create an EAN8 object with a given value.
-
#rle ⇒ Object
returns a run-length-encoded string representation.
-
#width ⇒ Object
Returns the total unit width of the bar code.
-
#wn ⇒ Object
EAN-based codes cannot create a w/n string, so this will raise an error.
Methods inherited from Barcode1D
bar_pair, bars_to_rle, rle_to_bars, rle_to_wn, wn_pair, wn_to_rle
Constructor Details
#initialize(value, options = {}) ⇒ EAN8
Create an EAN8 object with a given value. Options are :line_character, :space_character, and :checksum_included.
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/barcode1dtools/ean8.rb', line 208 def initialize(value, = {}) @options = DEFAULT_OPTIONS.merge() # Can we encode this value? raise UnencodableCharactersError unless self.class.can_encode?(value, @options) if @options[:checksum_included] @encoded_string = sprintf('%08d', value.to_i) raise ChecksumError unless self.class.validate_check_digit_for(@encoded_string) md = @encoded_string.match(/^(\d+?)(\d)$/) @value, @check_digit = md[1], md[2].to_i else # need to add a checksum @value = sprintf('%07d', value.to_i) @check_digit = self.class.generate_check_digit_for(@value) @encoded_string = "#{@value}#{@check_digit}" end md = @value.match(/^(\d{3})(\d{4})/) @number_system, @product_code = md[1], md[2] end |
Instance Attribute Details
#number_system ⇒ Object (readonly)
Specific for EAN-8 - the number system part of the payload
95 96 97 |
# File 'lib/barcode1dtools/ean8.rb', line 95 def number_system @number_system end |
#product_code ⇒ Object (readonly)
Specific for EAN-8 - the product code part of the payload
97 98 99 |
# File 'lib/barcode1dtools/ean8.rb', line 97 def product_code @product_code end |
Class Method Details
.can_encode?(value, options = nil) ⇒ Boolean
Returns true if value can be encoded in EAN-8 - must be 7-8 digits.
101 102 103 104 105 106 107 108 109 |
# File 'lib/barcode1dtools/ean8.rb', line 101 def can_encode?(value, = nil) if ! value.to_s =~ /^\d{7,8}$/ elsif ([:checksum_included]) value.to_s =~ /^\d{8}$/ else value.to_s =~ /^\d{7}$/ end end |
.decode(str) ⇒ Object
Decode a string representing an rle or bar pattern EAN-13. Note that the string might be backward or forward. This will return an EAN8 object.
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/barcode1dtools/ean8.rb', line 131 def decode(str) if str.length == 67 # bar pattern str = (str) elsif str.length == 43 # rle else raise UnencodableCharactersError, "Pattern must be 67 unit bar pattern or 43 character rle." end # Check the guard patterns unless str[0..2] == SIDE_GUARD_PATTERN_RLE && str[40..42] == SIDE_GUARD_PATTERN_RLE && str[19..23] == MIDDLE_GUARD_PATTERN_RLE raise UnencodableCharactersError, "Missing or incorrect guard patterns" end # Now I have an rle pattern, simply need to decode # according to the LEFT_PATTERNS_RLE, keeping track # of the parity for each position. # Set up the decoder left_parity_sequence = '' left_digits = '' right_parity_sequence = '' right_digits = '' left_initial_offset = SIDE_GUARD_PATTERN_RLE.length right_initial_offset = SIDE_GUARD_PATTERN_RLE.length + (4*4) + MIDDLE_GUARD_PATTERN_RLE.length # Decode the left side (0..3).each do |left_offset| found = false digit_rle = str[(left_initial_offset + left_offset*4),4] ['o','e'].each do |parity| ('0'..'9').each do |digit| if LEFT_PATTERNS_RLE[digit][parity] == digit_rle left_parity_sequence += parity left_digits += digit found = true break end end end raise UndecodableCharactersError, "Invalid sequence: #{digit_rle}" unless found end # Decode the right side (0..3).each do |right_offset| found = false digit_rle = str[(right_initial_offset + right_offset*4),4] ['o','e'].each do |parity| ('0'..'9').each do |digit| if LEFT_PATTERNS_RLE[digit][parity] == digit_rle right_parity_sequence += parity right_digits += digit found = true break end end end raise UndecodableCharactersError, "Invalid sequence: #{digit_rle}" unless found end # If left parity sequence is 'eeee', the string is reversed if left_parity_sequence == 'eeee' left_digits, right_digits, left_parity_sequence = right_digits.reverse, left_digits.reverse, right_parity_sequence.reverse.tr('eo','oe') end # Debugging #puts "Left digits: #{left_digits} Left parity: #{left_parity_sequence}" #puts "Right digits: #{right_digits} Right parity: #{right_parity_sequence}" EAN8.new(left_digits + right_digits, :checksum_included => true) end |
.generate_check_digit_for(value) ⇒ Object
Generates check digit given a string to encode. It assumes there is no check digit on the “value”.
113 114 115 116 117 118 |
# File 'lib/barcode1dtools/ean8.rb', line 113 def generate_check_digit_for(value) raise UnencodableCharactersError unless self.can_encode?(value, :checksum_included => false) mult = 1 value = value.split('').inject(0) { |a,c| mult = 4 - mult ; a + c.to_i * mult } (10 - (value % 10)) % 10 end |
.validate_check_digit_for(value) ⇒ Object
Validates the check digit given a string - assumes check digit is last digit of string.
122 123 124 125 126 |
# File 'lib/barcode1dtools/ean8.rb', line 122 def validate_check_digit_for(value) raise UnencodableCharactersError unless self.can_encode?(value, :checksum_included => true) md = value.match(/^(\d{7})(\d)$/) self.generate_check_digit_for(md[1]) == md[2].to_i end |
Instance Method Details
#bars ⇒ Object
Returns 1s and 0s (for “black” and “white”)
248 249 250 |
# File 'lib/barcode1dtools/ean8.rb', line 248 def @bars ||= self.class.(self.rle, @options) end |
#rle ⇒ Object
returns a run-length-encoded string representation.
238 239 240 241 242 243 244 245 |
# File 'lib/barcode1dtools/ean8.rb', line 238 def rle if @rle @rle else md = @encoded_string.match(/^(\d{4})(\d{4})/) @rle = gen_rle(md[1], md[2]) end end |
#width ⇒ Object
Returns the total unit width of the bar code.
253 254 255 |
# File 'lib/barcode1dtools/ean8.rb', line 253 def width @width ||= rle.split('').inject(0) { |a,c| a + c.to_i } end |
#wn ⇒ Object
EAN-based codes cannot create a w/n string, so this will raise an error.
233 234 235 |
# File 'lib/barcode1dtools/ean8.rb', line 233 def wn raise NotImplementedError end |