Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

About this user

Adam Feuer

« Newer Snippets
Older Snippets »
Showing 1-1 of 1 total  RSS 

Produce GIF or PNG barcode images from a Ruby on Rails application using RMagick and Gbarcode

This is a Ruby on Rails controller that produces PNG barcode images using RMagick (http://rmagick.rubyforge.org/) and Gbarcode (http://gbarcode.rubyforge.org/), the Ruby Gnu Barcode ( http://www.gnu.org/software/barcode/barcode.html ) wrapper. You will need to install RMagick and Gbarcode.

On Mac OS X, you can use the Locomotive RMagick bundle (http://locomotive.raaum.org/bundles/index.html) if you install the gbarcode gem into it first, for instance:

% export GEM_HOME=/Applications/Locomotive2/Bundles/rmagickRailsMar2007_i386.locobundle/framework/lib/ruby/gems/1.8/
% gem install gbarcode


To use it, save this code as barcode_controller.rb in the apps/controllers directory of your Rails application. Generate the barcodes using a URL like this:

http://localhost:3000/barcode/get_barcode_image?string=foo

This example uses the BARCODE_128 encoding; you can use different barcode encodings by adjusting the code. To produce PNG images, make sure you have have the PNG libraries installed on your system, and that your ImageMagick is compiled with PNG support, and then change 'image/gif' to 'image/png' and im.format = "GIF" to im.format = "PNG".

# $RAILS_ROOT/apps/controllers/barcode_controller.rb
class BarcodeController < ApplicationController

  def get_barcode_image
     string_to_encode = params[:string]
     barcode_image = BarcodeGenerator.get_barcode_image(string_to_encode)
     send_data(barcode_image, :type     => 'image/gif',
                                  :disposition => 'inline')
  end
end


# $RAILS_ROOT/app/helpers/barcode_generator.rb
#
# note: this will not work without rmagick (Ruby ImageMagick interface) and gbarcode (GNU barcode) 
# gems installed. rmagick needs ImageMagick plus dependencies.

class BarcodeGenerator

  # Uses subprocesses because 
  # 1. ImageMagick/RMagick leaks memory,
  #    and doesn't work in a long-running process. The fork makes it safe.
  # 2. The output from the Gbarcode and ImageMagick is often longer than the pipe buffer,
  #    so we have to empty the buffer from another subprocess
  def BarcodeGenerator.get_barcode_image(barcode_string)
    return BarcodeGenerator.get_subprocess_output do
                   barcode_generator = BarcodeGenerator.new
                   $stdout.write(barcode_generator.get_barcode_image(barcode_string))
    end
  end

  def initialize
    # we do the imports here to protect long-running processes (like mongrel) from ImageMagick's memory leaks
    require 'RMagick'
    require 'gbarcode'
  end

  def get_barcode_image(string_to_encode)
    if string_to_encode.nil?
      string_to_encode = "No string specified"
    end
    string_to_encode = remove_rails_file_extension(string_to_encode)
    eps_barcode = get_barcode_eps(string_to_encode)
    gif_barcode = convert_eps_to_gif(eps_barcode)
    return gif_barcode
  end

  def remove_rails_file_extension(string_to_encode)
    if string_to_encode[-4..-1] == ".png"
      string_to_encode = string_to_encode[0..-5]
    end
    return string_to_encode
  end

  def get_barcode_eps(string_to_encode)
    barcode_object = Gbarcode.barcode_create(string_to_encode)
    Gbarcode.barcode_encode(barcode_object, Gbarcode::BARCODE_128)
    return BarcodeGenerator.get_subprocess_output do
        Gbarcode.barcode_print(barcode_object, $stdout, Gbarcode::BARCODE_OUT_EPS)    
    end
  end
  
  def convert_eps_to_gif(eps_image)
    base64_eps_image = Base64.encode64(eps_image)
    im = Magick::Image::read_inline(base64_eps_image).first
    im.format = "GIF"
    return BarcodeGenerator.get_subprocess_output do
       im.write($stdout) 
    end
  end

  # execute a block's code in a subprocess, returning any output
  def BarcodeGenerator.get_subprocess_output()
    data = ""
    IO.popen('-', 'r+') do |child_filehandle|
      if child_filehandle
        begin
          data = child_filehandle.read
        ensure
          child_filehandle.close_write
        end
      else
        yield
      end
    end
    return data
  end

end    
« Newer Snippets
Older Snippets »
Showing 1-1 of 1 total  RSS