Creating images from pixel data (RMagick?)

Paul,

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?!" :slight_smile:

Cheers,

Tim.

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 = Magick::Image.new(@width, @height)
    @pixels =
  end
  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 << Magick::Pixel.new(col[0], col[1], col[2], 0)
  end
  def finalize (type="gif")
    @canvas.store_pixels(0, 0, @width, @height, @pixels)
    @canvas.write("#{@job_id}.#{type}")
  end
end

x = 512
y = 384
colours = ["ff0000", "00ff00", "0000ff"]
img = RippedImage.new(1, x, y)
(x*y).times do
  img.draw(colours[rand(colours.length)])
end
img.finalize

···

--
-------------------------------------------------------
TB: http://tim.bla.ir/ Tech: http://tech.badpen.com/
-------------------------------------------------------
     RAWNET LTD - independent digital media agency
     "We are big, we are funny and we are clever!"
                http://www.rawnet.com/
-------------------------------------------------------
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.
-------------------------------------------------------

Hi Tim,

See the thread starting at
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/153656 -
it talks about ImageMagick/RMagick specifically, and using mmap and
NArray to quickly create large images from pixel data.

- Dimitri

are you really limited to using string pixel values? if not i would say you
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 : false
     BIG_ENDIAN = ! LITTLE_ENDIAN
     MAP = BIG_ENDIAN ? 'ARGB' : 'BGRA'
     def initialize width, height
       @width = Integer width
       @height = Integer height
       @pixels =
     end
     def << c
       @pixels << c.hex
       self
     end
     def draw path
       img = Magick::Image.new @width, @height
       img.import_pixels 0, 0, @width, @height, MAP, @pixels.pack('i*'), Magick::CharPixel
       img.opacity = 255 # because the pack leaves it 0 - totally transparent
       img.write path
     end
   end

   x = 512
   y = 384
   colours = ["ff0000", "00ff00", "0000ff"]
   img = RippedImage.new 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 reasonable
number too.

kind regards.

-a

···

On Thu, 6 Apr 2006, Tim Blair wrote:

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 = Magick::Image.new(@width, @height)
   @pixels =
end
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 << Magick::Pixel.new(col[0], col[1], col[2], 0)
end
def finalize (type="gif")
   @canvas.store_pixels(0, 0, @width, @height, @pixels)
   @canvas.write("#{@job_id}.#{type}")
end
end

x = 512
y = 384
colours = ["ff0000", "00ff00", "0000ff"]
img = RippedImage.new(1, x, y)
(x*y).times do
img.draw(colours[rand(colours.length)])
end
img.finalize

--
be kind whenever possible... it is always possible.
- h.h. the 14th dali lama