Generating dynamic QR codes in Rails using Rjb

When I started looking for gems which generate QR code in ruby I found “rqrcode” which generates only HTML code which was not useful to me. I wanted the QR code image so I looked at “qr4r” but here we can not customize the color, background color etc,  so I decided to write my own code to generate the QR codes where I can have customized data, color, background color (transparent) and last but not the least, it should be fast!!

After looking at various libraries I found this much interesting.

http://mvnrepository.com/artifact/com.google.zxing/core. See demo.

You can download the jar file from here. As it is a jar file we need a bridge between Ruby and JVM. Here the Rjb gem comes into picture. Follow the instructions and install the Rjb gem. Ensure you have openjdk installed before installing Rjb gem. Also make sure you add the code below on top of your Gemfile to avoid the errors at the time of deployment.

java_home = '/usr/lib/jvm/java-7-openjdk-amd64'
ENV['JAVA_HOME'] = java_home if Dir.exist?(java_home)
#zxing.rb

require 'rjb'
require 'RMagick'
require 'rvg/rvg'
require 'color'

module Zxing
 class Zxing
   include Magick

   def initialize
     Rjb::load('.')
     Rjb::add_jar(Rails.root.join('lib/core.jar').to_s)
   end

   def encode(content, output_path, color='#000000', size=300, background = '#FFFFFF')
     @content = content
     @output_path = output_path
     @color = color
     @size = size
     @background_color = background
     encode!
   end

   def encode!
     qrcoder = Rjb::import('com.google.zxing.MultiFormatWriter').new
     barcode_format = Rjb::import("com.google.zxing.BarcodeFormat")
     format = barcode_format.valueOf("QR_CODE")
     hint_type = Rjb::import("com.google.zxing.EncodeHintType")
     hints = Rjb::import("java.util.HashMap").new
     hints.put(hint_type.MARGIN, 0)
     result = qrcoder.encode(@content, format, @size, @size, hints)
     generate_image(result)
   end

   def generate_image(result)
     arr = []
     red, green, blue = set_image_color
     for i in 0...@size
       for j in 0...@size
         if result.get(j, i)
           arr.push(red, green, blue)
         else
           arr.push(65535, 65535, 65535)
         end
       end
     end
     image = Magick::Image.constitute(@size, @size, "RGB", arr.flatten)
     image.write(@output_path)
     system("convert #{@output_path} -fill '#{@background_color}' -opaque white #{@output_path}")
   end

   def set_image_color
     c = ::Color::RGB.from_html(@color)
     [(c.red * 257).to_i, (c.green * 257).to_i, (c.blue * 257).to_i]
   end
  end
end

Here hints are used to reduce the margins from the QR code image. If you want margins then you can remove the hints option.

result = qrcoder.encode(@content, format, @size, @size, hints)

Above code will return an array of qr code elements with ‘0’s & ‘1’s. ‘1’ stands for qr code position. The ‘generate_image’ method will loop through the result set and wherever it finds ‘1’ it will replace it with RGB colors.  Here we have used ‘color gem‘ which returns the RGB codes from the given Hex color.  Also you will notice that each RGB color code is multiplied with ‘257’ because we want 16-bit colors to generate the image. There is a method in jar library that will generate the QR code image but it is very slow. So to make the QR code generation faster we will write our own method ‘generate_image’ which generates the image using Rmagick

def generate_QR
  zxing = Zxing::Zxing.new
  zxing.encode(
   email_content("qr@example.com", "Testing", "QR code works"),
   Rails.root.join("public/qr.png")
  )
end

def email_content(email, subject, body)
  "mailto:#{email}?subject=#{subject}&body=#{body}"
end

In the above code, “email_content” method will have the QR code specific content. We can have similar methods to generate different types of QR codes like SMS, Vcards, Youtube links, Bookmarks, website url etc.

Refer qrgenius.net for more qr code details.

The QR code image will be generated at the given output path, which you can use to display on HTML page.

Advertisements
This entry was posted in Ruby, Ruby on Rails and tagged , , , , , . Bookmark the permalink.

2 Responses to Generating dynamic QR codes in Rails using Rjb

  1. Martin says:

    rqrcode does render png and svg since 2012, but readme was only updated 2015.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s