I got a Tera 1D Barcode scanner at work. What I want to use it for is to be able to scan a barcode on a circuit board and then print out more labels with barcodes to stick on the boxes that we’ll be shipping them in. I also have an old iMac that I’m going to use for this project, along with a Brother QL 550 label printer.

When I plug the barcode scanner in, the mac recognizes it as an input device and prompts you to push a certain key on the keyboard. Since there is only the trigger on the barcode scanner, I can just close that prompt. To test it out, I just opened textedit and scanned a barcode. The text from the barcode shows up in the editor. So the barcode scanner worked fine with the mac (and any other computer I tried it on).

The next key is to write a script that will generate and print a new barcode label. I used ruby for this because that’s the language I’m most familiar with. I don’t need rails right now, but if I decide to do more with this setup, I may use it in the future.

There is a gem for ruby called barby that generates barcodes. This gem also requires the chunky_png gem.

A simple program that will read a barcode and generate a new one is:

require 'barby'
require 'barby/barcode/code_128'
require 'barby/outputter/png_outputter'
puts "Scan barcode"
string = gets.chomp
barcode = Barby::Code128B.new(string).to_png
File.open('barcode.png', 'wb'){ |f| f.write barcode }

The resulting barcode looks like this. sample barcode

That’s fine. However, I’d also like the text encoded in the barcode to show beneath the barcode. Unfortunately, barby doesn’t offer a way to add this text. So I’m going to use ImageMagick to do this. Basically, I’m going to make a blank png file the size to fit my labels. Then I’m going to place the barcode I made with barby in that image. After that I’m going to place the image with the text encoded in the barcode on top of that. I feel like there should be a way to do this in one step, but I haven’t been able to figure this out. Fortunately, we’re only going to be working on one board at a time, so if it takes a minute to make these labels, that’s ok.

Here’s the final code.

#!/usr/local/bin/ruby

require 'barby'
require 'barby/barcode/code_128'
require 'barby/outputter/png_outputter'
require 'RMagick'

# This is for the 1 1/7" x 3.5" labels (output needs to be smaller than 252x82)
textsize = 18
ysize = 80
xsize = 250

blank_label = Magick::Image.new(xsize, ysize) do |lbl|
    lbl.background_color = "white"
end
blank_label.write("blank_label.png")

# Scan the barcode
puts "Scan barcode"
string = gets.chomp

# Make barcode image
barcode = Barby::Code128B.new(string).to_png
File.open('tmp.png', 'wb'){ |f| f.write barcode }

# Make text image
annotation = Magick::Draw.new do |text|
    text.gravity = Magick::CenterGravity
    text.pointsize = textsize
    text.undercolor = "white"
    text.fill = "black"
end
image = Magick::Image.new(xsize, ysize/4) do |i|
    i.background_color = "white"
    i.gravity = Magick::SouthGravity
end
image = image.annotate(annotation, 0,0,0,0, "#{string}")
image.write("text.png")

# Drop the barcode image and the text image into the blank label
`composite -gravity center tmp.png blank_label.png output.png`
`composite -gravity south text.png output.png #{string}.png`

# Print a number of labels
3.times do 
    `lpr -P Brother_QL_550 #{string}.png`
end

The final output is a label named with the same name as the string that’s encoded. So it would be pretty easy for us to print out more if we need them. I’m still working through the process of how we’re labelling and packaging the boards for shipment. But this, should be a pretty easy way for us to just scan the boards so that we don’t make the mistake of typing in a wrong character from the long string that we’re encoding.

Here’s what the final image looks like. sample barcode with text

I thought about trying to write this so that we could print out different sized labels. But that’s trying to solve a problem that we don’t have. Once we get started, we’ll just be doing around 1000 boards all of the same label.