Class: Barcode1DTools::UPC_Supplemental_2
- Defined in:
- lib/barcode1dtools/upc_supplemental_2.rb
Overview
Barcode1DTools::UPC_Supplemental_2 - Create pattern for UPC Supplemental 2 barcodes. The value encoded is an 2-digit integer, 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 = '24'
bc = Barcode1DTools::UPC_Supplemental_2.new(num)
pattern = bc.
rle_pattern = bc.rle
width = bc.width
check_digit = Barcode1DTools::UPC_Supplemental_2.generate_check_digit_for(num)
Other Information
This type of barcode consists of 2 digits, and a check digit (simply a modulus 4 of the number encoded) that is encoded in the “parity” of the two barcode digits. The bar patterns are the same as the left half of a standard UPC-A.
The 2-digit supplement is generally used on periodicals as an “issue number”, so that the UPC-A code may remain the same across issues. The two are scanned together, and typically the scanner will return the two digits of the supplemental barcode immediately following the check digit from the main UPC-A. You will likely need to use the Barcode::UPC_A module in addition to this one to create the full code.
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 “w/n” format for EAN & UPC style barcodes because the bars and spaces are variable width from 1 to 4 units.
Rendering
The 2-digit supplement is positioned to the right of the main UPC code, and the human-readable digits are usually printed above the supplemental barcode. UPC-A is generally rendered at one inch across, then there’s a 1/8th inch gap, then the supplemental. A UPC-A is 95 units wide, so the gap is 24 units wide. The supplemental barcode is 20 units wide. The author hasn’t viewed the specification, but note that the UPC (and more generally EAN) barcode system never include a bar or space of more than four units width. Given that, the gap should likely be at last 10 units wide.
Constant Summary collapse
- LEFT_PATTERNS =
The bar patterns are the left bar patterns of UPC-A/EAN-13
UPC_A::LEFT_PATTERNS
- LEFT_PATTERNS_RLE =
The rle bar patterns are the left bar patterns of UPC-A/EAN-13
UPC_A::LEFT_PATTERNS_RLE
- PARITY_PATTERNS =
Parity patterns, essentially binary counting where “e” is “1” and “o” is “0”.
{ '0' => 'oo', '1' => 'oe', '2' => 'eo', '3' => 'ee', }
- LEFT_GUARD_PATTERN =
Left guard pattern
'1011'
- MIDDLE_GUARD_PATTERN =
Middle guard pattern
'01'
- LEFT_GUARD_PATTERN_RLE =
Left guard pattern as an rle
'112'
- MIDDLE_GUARD_PATTERN_RLE =
Middle guard pattern as an rle
'11'
- DEFAULT_OPTIONS =
{ :line_character => '1', :space_character => '0' }
Instance Attribute Summary
Attributes inherited from Barcode1D
#check_digit, #encoded_string, #options, #value
Class Method Summary collapse
-
.can_encode?(value, options = nil) ⇒ Boolean
Returns true or false - must be 1-3 digits.
-
.decode(str) ⇒ Object
Decodes a bar or rle pattern and returns a UPC_Supplemental_2 object.
-
.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 a bar pattern.
-
#initialize(value, options = {}) ⇒ UPC_Supplemental_2
constructor
Create a new UPC_Supplemental_2 object from 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
W/N patterns are not usable with EAN-style codes.
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 = {}) ⇒ UPC_Supplemental_2
Create a new UPC_Supplemental_2 object from a given value. Options are :line_character, :space_character, and :checksum_included.
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
# File 'lib/barcode1dtools/upc_supplemental_2.rb', line 190 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 = value.to_s raise ChecksumError unless self.class.validate_check_digit_for(@encoded_string) md = @encoded_string.match(/^(\d+?)(\d)$/) @value, @check_digit = md[1].to_i, md[2].to_i else # need to add a checksum @value = value.to_i @check_digit = self.class.generate_check_digit_for(@value) @encoded_string = sprintf('%02d%1d',@value,@check_digit) end end |
Class Method Details
.can_encode?(value, options = nil) ⇒ Boolean
Returns true or false - must be 1-3 digits. This also handles the case where the leading 0 is added.
106 107 108 109 110 111 112 113 114 |
# File 'lib/barcode1dtools/upc_supplemental_2.rb', line 106 def can_encode?(value, = nil) if ! value.to_s =~ /^\d{1,3}$/ elsif ([:checksum_included]) value.to_s =~ /^\d\d\d?$/ else value.to_s =~ /^\d\d?$/ && (0..99).include?(value.to_i) end end |
.decode(str) ⇒ Object
Decodes a bar or rle pattern and returns a UPC_Supplemental_2 object.
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 |
# File 'lib/barcode1dtools/upc_supplemental_2.rb', line 132 def decode(str) if str.length == 20 # bar pattern str = (str) elsif str.length == 13 && str =~ /^[1-9]+$/ # rle else raise UnencodableCharactersError, "Pattern must be 20 unit bar pattern or 13 character rle." end # This string is "aaabbbbccdddd" where "aaa" is the left # guard pattern, "bbbb" is the first digit, "cc" is the # intra-digit guard pattern, and "dddd" is the second # digit. # Check the guard patterns unless (str[0..2] == LEFT_GUARD_PATTERN_RLE && str[7..8] == MIDDLE_GUARD_PATTERN_RLE) raise UnencodableCharactersError, "Missing or incorrect guard patterns" end parity_sequence = '' digits = '' # Decode [str[3..6], str[9..12]].each do |digit_rle| found = false ['o','e'].each do |parity| ('0'..'9').each do |digit| if LEFT_PATTERNS_RLE[digit][parity] == digit_rle parity_sequence += parity digits += digit found = true break end end end raise UndecodableCharactersError, "Invalid sequence: #{digit_rle}" unless found end # Now, find the parity digit parity_digit = nil ('0'..'3').each do |x| if PARITY_PATTERNS[x] == parity_sequence parity_digit = x break end end raise UndecodableCharactersError, "Weird parity: #{parity_sequence}" unless parity_digit UPC_Supplemental_2.new(digits + parity_digit, :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”.
118 119 120 |
# File 'lib/barcode1dtools/upc_supplemental_2.rb', line 118 def generate_check_digit_for(value) value.to_i % 4 end |
.validate_check_digit_for(value) ⇒ Object
Validates the check digit given a string - assumes check digit is last digit of string.
124 125 126 127 128 |
# File 'lib/barcode1dtools/upc_supplemental_2.rb', line 124 def validate_check_digit_for(value) raise UnencodableCharactersError unless self.can_encode?(value, :checksum_included => true) md = value.match(/^(\d\d)(\d)$/) self.generate_check_digit_for(md[1]) == md[2].to_i end |
Instance Method Details
#bars ⇒ Object
Returns a bar pattern.
227 228 229 |
# File 'lib/barcode1dtools/upc_supplemental_2.rb', line 227 def @bars ||= self.class.(self.rle, @options) end |
#rle ⇒ Object
Returns a run-length-encoded string representation.
217 218 219 220 221 222 223 224 |
# File 'lib/barcode1dtools/upc_supplemental_2.rb', line 217 def rle if @rle @rle else md = @encoded_string.match(/(\d\d)(\d)$/) @rle = gen_rle(md[1], md[2]) end end |
#width ⇒ Object
Returns the total unit width of the bar code.
232 233 234 |
# File 'lib/barcode1dtools/upc_supplemental_2.rb', line 232 def width @width ||= rle.split('').inject(0) { |a,c| a + c.to_i } end |
#wn ⇒ Object
W/N patterns are not usable with EAN-style codes. This will raise an error.
212 213 214 |
# File 'lib/barcode1dtools/upc_supplemental_2.rb', line 212 def wn raise NotImplementedError end |