Forum: Ruby Re: Creating images from pixel data (RMagick?)

Announcement (2017-05-07): is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see and for other Rails- und Ruby-related community platforms.
Tim Blair (Guest)
on 2006-04-06 15:57
(Received via mailing list)

> If that won't work, Imlib2-Ruby may be fast enough to do
> what you want

Thanks for that.  Unfortunately we're looking for a cross-platform
solution so using imlib2 appears to be out of the running.

However, I have managed to speed up the generation a lot by using the
Rmagick Image#store_pixels method instead of Draw#fill - we now have the
512x384 image generating in <5 seconds which is OK for what we're doing
(at least at the moment!).  We're now limited by the speed at which the
flash player can glean the pixel data, rather than how fast the image
can be generated.  Code below.

Thanks again for the help.  Maybe your imlib2 will come in useful when
someone turns around and says "surely we can do that sooooo much
quicker?!" :)



require 'RMagick'
class RippedImage
  def initialize (job_id, width, height)
    @job_id = job_id.to_s;
    @width = width.to_i;
    @height = height.to_i;
    @canvas =, @height)
    @pixels = []
  def draw (c)
    # the colour is a 6 digit hex char which needs to
    # be converted to numeric values for RGB
    col = []
    c.scan(/../).each { |bit| col << bit.hex }
    @pixels <<[0], col[1], col[2], 0)
  def finalize (type="gif")
    @canvas.store_pixels(0, 0, @width, @height, @pixels)

x = 512
y = 384
colours = ["ff0000", "00ff00", "0000ff"]
img =, x, y)
(x*y).times do

 TB:  Tech:
     RAWNET LTD - independent digital media agency
     "We are big, we are funny and we are clever!"
This message may contain information which is legally
privileged and/or confidential.  If you are not the
intended recipient, you are hereby notified that any
unauthorised disclosure, copying, distribution or use
of this information is strictly prohibited. Such
notification notwithstanding, any comments, opinions,
information or conclusions expressed in this message
are those of the originator, not of rawnet limited,
unless otherwise explicitly and independently indicated
by an authorised representative of rawnet limited.
Dimitri A. (Guest)
on 2006-04-06 18:13
(Received via mailing list)
Hi Tim,

See the thread starting at -
it talks about ImageMagick/RMagick specifically, and using mmap and
NArray to quickly create large images from pixel data.

- Dimitri
unknown (Guest)
on 2006-04-06 21:46
(Received via mailing list)
On Thu, 6 Apr 2006, Tim Blair wrote:

>    # the colour is a 6 digit hex char which needs to
> x = 512
> y = 384
> colours = ["ff0000", "00ff00", "0000ff"]
> img =, x, y)
> (x*y).times do
>  img.draw(colours[rand(colours.length)])
> end
> img.finalize

are you really limited to using string pixel values?  if not i would say
should be able to generate these images in __way__ under 1s.  even if
you are,
using import_pixels will be tons faster:

your original:

     jib:~/eg/ruby > time ruby a.rb

     real    0m4.028s
     user    0m3.620s
     sys     0m0.070s

using import_pixels:

   jib:~/eg/ruby > time ruby a.rb

   real    0m0.829s
   user    0m0.810s
   sys     0m0.000s

   jib:~/eg/ruby > cat a.rb
   require 'rubygems'
   require 'RMagick'
   class RippedImage
     LITTLE_ENDIAN = [42].pack('i').unpack('c').first.nonzero? ? true :
     def initialize width, height
       @width = Integer width
       @height = Integer height
       @pixels  = []
     def << c
       @pixels << c.hex
     def draw path
       img = @width, @height
       img.import_pixels 0, 0, @width, @height, MAP, @pixels.pack('i*'),
       img.opacity = 255  # because the pack leaves it 0 - totally
       img.write path

   x = 512
   y = 384
   colours = ["ff0000", "00ff00", "0000ff"]
   img = x, y
   (x*y).times{ img << (colours[rand(colours.length)]) }
   img.draw "#{ 1 }.png"

so that's a four times speed-up right there.  i suspect 1s is a
number too.

kind regards.

This topic is locked and can not be replied to.