Re: Creating images from pixel data (RMagick?)


#1

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 ©
# 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.


#2

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

#3

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 = RippedImage.new(1, 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
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