Main > Software

« Analog Hole to be Sewn Shut? | Main | A Fishy Transaction »

December 31, 2005

Progress Bars with GD2 and Ruby

Just in time for the new year...

I went milling about for source for progress bars that would be suitably embedded within a Ruby on Rails application I'm working on and came up with nada. Sure, sure there are lots of bars that have to do with live uploading and whatnot (see: here); but nothing that grabbed me with the interface I was looking for (call function, return data).

Like cheating on a lover, I went looking into PHP territory and found a really quite wonderful and straightforward example here by Bård (Bob) Johannessen.

It only took about 20 minutes to adapt to a halfway decent ruby class and now I'm rollin'. Here are some output examples:

OSX-ish:
rpb-output1.png

WinXp-ish:
rpb-output1.png

Generic LED-ish:
rpb-output1.png

Solaris-ish:
rpb-output1.png

You can download a tarball of my musings: ruby_progressbar.tar.gz.

Here's the source:

#!/bin/env ruby18
# copyright 2005, Jordan Husney <jordan@husney.com>
# (http://jordan.husney.com/main.html)
#
# derived directly from the following source and protected under
# the GNU GENERAL PUBLIC LICENSE, Version 2, June 1991
#
# http://db.org/demo/2003/02/17/progress-bar/?view=source
#
# php+gd dynamic progress bar image script.
# copyright 2003, B. Johannessen <bob@db.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version, and provided that the above
# copyright and permission notice is included with all distributed
# copies of this or derived software.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# A copy of the GNU General Public License is available from the GNU
# website at the following URL: http://www.gnu.org/licenses/gpl.txt


require 'rubygems'
require 'gd2'

class RubyProgressbar
  include GD2

  IMAGE_DIR = "./images/"
  IMAGE_STYLES = [ 'winxp', 'osx', 'led', 'solaris' ]

  public

  def initialize
    @image = nil
  end

  def create(style, width, completed, total)
    # Check arugments:
    raise ArgumentError, "style '#{style}' unknown" if
      not IMAGE_STYLES.include?(style)
    raise ArgumentError, "width must be between 64 and 1280 pixels" if
      width < 64 || width > 1280
    raise ArgumentError,
      "completed must be greater than 0 and less than total" if
        completed < 0 || completed > total
    raise ArgumentError, "total must be greater than 0" if
      total < 1

    # Open images according to defined style:
    begin
      bg        = Image.import(IMAGE_DIR + style + '-bg.png')
      fill      = Image.import(IMAGE_DIR + style + '-fill.png')
      bg_cap    = Image.import(IMAGE_DIR + style + '-bg-cap.png')
      fill_cap  = Image.import(IMAGE_DIR + style + '-fill-cap.png')
    rescue Exception => e
      raise "Unable to load required images for style #{style}!"
    end

    # calculate the fill width:
    fill_width = (((width - bg_cap.width) * completed) / total).round -
                  fill_cap.width

    # create the new image, and copy the fragments into it:
    image = Image::TrueColor.new(width, bg.height)
    image.copy_from(bg, 0, 0, 0, 0, bg.w, (width - bg_cap.w))
    image.copy_from(bg_cap, (width - bg_cap.w), 0, 0, 0, bg_cap.w, bg_cap.h)
    image.copy_from(fill, 0, 0, 0, 0, fill_width, fill.h)
    image.copy_from(fill_cap, fill_width, 0, 0, 0, fill_cap.w, fill_cap.h)

    @image = image

    # return success
    return true
  end

  def destroy
    @image = nil
  end

  def gif()
    raise Exception, "image not created" if @image.nil?
    return @image.gif()
  end

  def jpeg(compression = nil)
    raise Exception, "image not created" if @image.nil?
    return @image.jpeg(compression)
  end

  def png(compression = nil)
    raise Exception, "image not created" if @image.nil?
    return @image.png(compression)
  end

end

It can be used thusly:

require 'ruby_progressbar'

bar = RubyProgressbar.new
# OSX style, 320px wide, 3 of 10 units completed on the bar:
bar.create("osx", 320, 3, 10)
f = File.new("output.png", "w")
f.write(bar.png)
f.close

Please let me know if you've got any feedback or make any extensions!

Update, 2006-Jun-28: fixed recollation typographic error and added syntax highlighting.

Posted by jordanh at December 31, 2005 5:43 PM |

Trackback Pings

TrackBack URL for this entry:
http://jordan.husney.com/mt/mt-tb.cgi/221.

Comments

When I run ruby_progressbar.rb on my computer the following error occur:
$ ruby ruby_progressbar.rb
/usr/local/lib/ruby/gems/1.8/gems/gd2-1.1.1/lib/gd2.rb:58:in `initialize': No such file or directory (RuntimeError)
from /usr/local/lib/ruby/gems/1.8/gems/gd2-1.1.1/lib/gd2.rb:58:in `dlopen'
from /usr/local/lib/ruby/gems/1.8/gems/gd2-1.1.1/lib/gd2.rb:58
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:32:in `gem_original_require'
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:32:in `require'
from ruby_progressbar.rb:31

my ruby version is 1.8.6
my gd2 version is 1.1.1
I run at on Cygwin

What's the problem?

Posted by: Anonymous at June 12, 2007 2:27 AM

I have the same problem as above.. I'm running on windows as well, so it sounds like this might be a problem with the gd2 gem on windows? If anybody has any ideas or experience please share!

Thanks

Posted by: Jeremy at July 31, 2007 11:52 AM

I've experienced the same issue on a MacBook Pro, so it doesn't seem to be a Windows only problem.

Posted by: Grant at September 2, 2007 5:07 AM

Same problem here in Windows XP!

Any ideas?

Posted by: Peter at September 5, 2007 8:09 PM

we are geeting the error "no such file to load -- gd2 "

from where i can get the gd2 plugin

Posted by: mahesh at September 28, 2007 1:33 AM

I've the same problem with WinXP. I found the localisation of the problem but I don't know how to resolve it. First the gem seems to be not instaleld because I was obliged to import the files gd2.rb (gd/canvas.rb...) to my space working
Then in the file gd2.rb there's a line
LIB = DL.dlopen('libgd.so.2')
this library is available under Linux so we must replace it with libgd.dll or bgd.dll (downloaded from the Web) and change the path LIB = DL.dlopen('path/libgd.dl'). This solution seems to be good but I'm not sure!!

Posted by: Abir at September 28, 2007 7:48 AM

Posted by: pdr at September 12, 2008 3:33 AM

A very well written / explained tutorial.

Posted by: ComputerTutorials at November 24, 2010 9:19 AM

Well, this is a great read for me.. I found this blog is very useful for me in my work. Nicely presented information in this post, I prefer to read this kind of stuff. The quality of content is fine and the conclusion is good. Thanks for the post

Posted by: domain and hosting services india at February 29, 2012 3:33 AM

Post a comment




Remember Me?