Class: Barcode1DTools::UPC_E
- Defined in:
- lib/barcode1dtools/upc_e.rb
Overview
Barcode1DTools::UPC_E - Create pattern for UPC-E barcodes. The value encoded is an 6-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 = '394932'
bc = Barcode1DTools::UPC_E.new(num)
pattern = bc.
rle_pattern = bc.rle
width = bc.width
check_digit = Barcode1DTools::UPC_E.generate_check_digit_for(num)
Other Information
A UPC-E barcode is an abbreviated form of UPC-A, but can encode only a few codes. The checksum is derived from the full UPC-A digit sequence rather than the 6 digits of the UPC-E. The checksum is encoded as the parity, with the bar patterns the same as the left side of a standard UPC-A.
The last digit of the UPC-E determines the pattern used to convert to a UPC-A.
UPC-E UPC-A equivalent
2 digits for manufacturer code (plus last digit), 3 digits for product
XXNNN0 0XX000-00NNN
XXNNN1 0XX100-00NNN
XXNNN2 0XX200-00NNN
3 digits for manufacturer code, 2 digits for product
XXXNN3 0XXX00-000NN
4 digits for manufacturer code, 1 digit for product
XXXXN4 0XXXX0-0000N
5 digits for manufacturer code, 1 digit for product (5-9)
XXXXX5 0XXXXX-00005
XXXXX6 0XXXXX-00006
XXXXX7 0XXXXX-00007
XXXXX8 0XXXXX-00008
XXXXX9 0XXXXX-00009
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 UPC-E is made for smaller items. Generally, they are rendered with the number system digit (0) on the left of the bars and the checksum on the right. The 6-digit payload is shown below the bars with the end guard bars extending half-way down the digits. The number system and check digit might be rendered in a slightly smaller font size. The UPC-E uses the same bar patterns as the left half of a regular UPC-A, but there is no middle pattern and the right guard pattern has an extra line/space pair.
Constant Summary collapse
- LEFT_PATTERNS =
Using the left patterns from UPC-A
UPC_A::LEFT_PATTERNS
- LEFT_PATTERNS_RLE =
Using the left patterns from UPC-A
UPC_A::LEFT_PATTERNS_RLE
- PARITY_PATTERNS =
UPC-E uses a different set of parity patterns to encode the check digit.
{ '0' => 'eeeooo', '1' => 'eeoeoo', '2' => 'eeooeo', '3' => 'eeoooe', '4' => 'eoeeoo', '5' => 'eooeeo', '6' => 'eoooee', '7' => 'eoeoeo', '8' => 'eoeooe', '9' => 'eooeoe', }
- LEFT_GUARD_PATTERN =
Left guard pattern
'101'
- RIGHT_GUARD_PATTERN =
Right guard pattern
'010101'
- LEFT_GUARD_PATTERN_RLE =
Left guard pattern as RLE
'111'
- RIGHT_GUARD_PATTERN_RLE =
Right guard pattern as RLE
'111111'
- DEFAULT_OPTIONS =
{ :line_character => '1', :space_character => '0' }
Instance Attribute Summary collapse
-
#manufacturers_code ⇒ Object
readonly
For UPC-E - the manufacturer’s code part of the item number.
-
#number_system ⇒ Object
readonly
For UPC-E - the number system part of the item number.
-
#product_code ⇒ Object
readonly
For UPC-E - the product code part of the item number.
-
#upca_value ⇒ Object
readonly
For UPC-E - the UPC-A value for this UPC-E value.
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 6-8 digits.
-
.decode(str) ⇒ Object
Decodes a bar pattern or rle string that represents a UPC-E.
-
.generate_check_digit_for(value) ⇒ Object
Generates check digit given a string to encode.
-
.upca_value_to_upce_value(value, options = {}) ⇒ Object
Converts the given UPC-A value to a UPC-E value.
-
.upce_value_to_upca_value(value, options = {}) ⇒ Object
Converts the given UPC-E value to a UPC-A value.
-
.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_E
constructor
Create a new UPC-E object for a given value.
-
#rle ⇒ Object
Returns a run-length-encoded string representation.
-
#to_upc_a ⇒ Object
Returns a UPC_A object with the same value.
-
#width ⇒ Object
Returns the total unit width of the bar code.
-
#wn ⇒ Object
W/N strings 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_E
Create a new UPC-E object for a given value. Options are :line_character, :space_character, and :checksum_included.
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 |
# File 'lib/barcode1dtools/upc_e.rb', line 254 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], md[2].to_i else # need to add a checksum @value = value.to_s @check_digit = self.class.generate_check_digit_for(@value) @encoded_string = "#{@value}#{@check_digit}" end @upca_value = self.class.upce_value_to_upca_value(@value) md = @upca_value.match(/^(\d)(\d{5})(\d{5})/) @number_system, @manufacturers_code, @product_code = md[1], md[2], md[3] end |
Instance Attribute Details
#manufacturers_code ⇒ Object (readonly)
For UPC-E - the manufacturer’s code part of the item number
121 122 123 |
# File 'lib/barcode1dtools/upc_e.rb', line 121 def manufacturers_code @manufacturers_code end |
#number_system ⇒ Object (readonly)
For UPC-E - the number system part of the item number
119 120 121 |
# File 'lib/barcode1dtools/upc_e.rb', line 119 def number_system @number_system end |
#product_code ⇒ Object (readonly)
For UPC-E - the product code part of the item number
123 124 125 |
# File 'lib/barcode1dtools/upc_e.rb', line 123 def product_code @product_code end |
#upca_value ⇒ Object (readonly)
For UPC-E - the UPC-A value for this UPC-E value
125 126 127 |
# File 'lib/barcode1dtools/upc_e.rb', line 125 def upca_value @upca_value end |
Class Method Details
.can_encode?(value, options = nil) ⇒ Boolean
Returns true or false - must be 6-8 digits. This also handles the case where the leading 0 is added.
130 131 132 133 134 135 136 137 138 |
# File 'lib/barcode1dtools/upc_e.rb', line 130 def can_encode?(value, = nil) if ! value.to_s =~ /^0?[0-9]{6,7}$/ elsif ([:checksum_included]) value.to_s =~ /^0?[0-9]{7}$/ else value.to_s =~ /^0?[0-9]{6}$/ end end |
.decode(str) ⇒ Object
Decodes a bar pattern or rle string that represents a UPC-E. Returns a UPC_E object.
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 203 204 205 206 207 208 209 |
# File 'lib/barcode1dtools/upc_e.rb', line 156 def decode(str) if str.length == 51 # bar pattern str = (str) elsif str.length == 33 && str =~ /^[1-9]+$/ # rle else raise UnencodableCharactersError, "Pattern must be 51 unit bar pattern or 33 character rle." end # See if the string is reversed if str[0..5] == RIGHT_GUARD_PATTERN_RLE && str[30..32] == LEFT_GUARD_PATTERN_RLE str.reverse! end # Check the guard patterns unless (str[0..2] == LEFT_GUARD_PATTERN_RLE && str[27..32] == RIGHT_GUARD_PATTERN_RLE) raise UnencodableCharactersError, "Missing or incorrect guard patterns" end parity_sequence = '' digits = '' initial_offset = LEFT_GUARD_PATTERN_RLE.length # Decode (0..5).each do |offset| found = false digit_rle = str[(initial_offset + offset*4),4] ['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'..'9').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_E.new('0' + 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”.
142 143 144 |
# File 'lib/barcode1dtools/upc_e.rb', line 142 def generate_check_digit_for(value) UPC_A.generate_check_digit_for(self.upce_value_to_upca_value(value)) end |
.upca_value_to_upce_value(value, options = {}) ⇒ Object
Converts the given UPC-A value to a UPC-E value.
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 |
# File 'lib/barcode1dtools/upc_e.rb', line 232 def upca_value_to_upce_value(value, = {}) raise UnencodableCharactersError unless UPC_A.can_encode?(value, ) value = value % 10 if [:checksum_included] value = sprintf('%011d', value.to_i) if value =~ /^0(\d\d\d\d[1-9])0000([5-9])/ upce_value = "0#{$1}#{$2}" elsif value =~ /^0(\d\d\d[1-9])00000(\d)/ upce_value = "0#{$1}#{$2}4" elsif value =~ /^0(\d\d)([012])0000(\d\d\d)/ upce_value = "0#{$1}#{$3}#{$2}" elsif value =~ /^0(\d\d[3-9])00000(\d\d)/ upce_value = "0#{$1}#{$2}3" else raise UnencodableCharactersError, "Cannot change UPC-A #{value} to UPC-E" end upce_value end |
.upce_value_to_upca_value(value, options = {}) ⇒ Object
Converts the given UPC-E value to a UPC-A value.
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/barcode1dtools/upc_e.rb', line 212 def upce_value_to_upca_value(value, = {}) raise UnencodableCharactersError unless self.can_encode?(value, ) # remove the check digit if it was included value = value.to_i % 10 if [:checksum_included] value = sprintf('%06d', value.to_i) if value =~ /(\d\d)(\d\d\d)([012])/ upca_value = "0#{$1}#{$3}0000#{$2}" elsif value =~ /(\d\d\d)(\d\d)(3)/ upca_value = "0#{$1}00000#{$2}" elsif value =~ /(\d\d\d\d)(\d)(4)/ upca_value = "0#{$1}00000#{$2}" elsif value =~ /(\d\d\d\d\d)([5-9])/ upca_value = "0#{$1}0000#{$2}" else raise UnencodableCharactersError, "Cannot change UPC-E #{value} to UPC-A" end upca_value end |
.validate_check_digit_for(value) ⇒ Object
Validates the check digit given a string - assumes check digit is last digit of string.
148 149 150 151 152 |
# File 'lib/barcode1dtools/upc_e.rb', line 148 def validate_check_digit_for(value) raise UnencodableCharactersError unless self.can_encode?(value, :checksum_included => true) md = value.match(/^(0?\d{6})(\d)$/) self.generate_check_digit_for(md[1]) == md[2].to_i end |
Instance Method Details
#bars ⇒ Object
Returns a bar pattern.
294 295 296 |
# File 'lib/barcode1dtools/upc_e.rb', line 294 def @bars ||= self.class.(self.rle, @options) end |
#rle ⇒ Object
Returns a run-length-encoded string representation.
284 285 286 287 288 289 290 291 |
# File 'lib/barcode1dtools/upc_e.rb', line 284 def rle if @rle @rle else md = @encoded_string.match(/(\d{6})(\d)$/) @rle = gen_rle(md[1], md[2]) end end |
#to_upc_a ⇒ Object
Returns a UPC_A object with the same value.
304 305 306 |
# File 'lib/barcode1dtools/upc_e.rb', line 304 def to_upc_a UPC_A.new(self.class.upce_value_to_upca_value(@value), .merge(:checksum_included => false)) end |
#width ⇒ Object
Returns the total unit width of the bar code.
299 300 301 |
# File 'lib/barcode1dtools/upc_e.rb', line 299 def width @width ||= rle.split('').inject(0) { |a,c| a + c.to_i } end |
#wn ⇒ Object
W/N strings are not usable with EAN-style codes.
279 280 281 |
# File 'lib/barcode1dtools/upc_e.rb', line 279 def wn raise NotImplementedError end |