Creating images from pixel data (RMagick?)

Hello,

I’m currently trying to build an image file (jpg/gif) from a stream of
pixel colour values, but it’s taking a long time to build the image
pixel by pixel.

We’re trying to dynamically “screenshot” a Flash movie to create a
static JPG. The flash movie plays to the appropriate point then
effectively does a “capture” of each pixel’s colour, posting the
information directly to a ruby socket server.

From there a new RMagick::Image is created and each pixel is painted
individually on to that image (see RippedImage#draw below). While this
works, it’s very slow when we get up to the sort of image resolution
we’re looking at, taking about 40 seconds for a 512x384 image.

Does anyone have any suggestions as to how to increase this generation
speed? I’ve tried hunting through the RMagick docs for some way to
provide an array of pixel data or something similar, but nothing’s
jumped out at me. Test code below.

Thanks in advance,

Tim.

require ‘RMagick’
class RippedImage
def initialize (jobid, width, height)
@jobid = jobid.to_s;
@width = width.to_i;
@height = height.to_i;
@canvas = Magick::Image.new(@width, @height)
end
def draw (x, y, c)
Magick::Draw.new.fill(‘#’+c).point(x,y).draw(@canvas)
end
def finalize (type=“jpg”)
@canvas.write(“#{@jobid}.#{type}”)
end
end

x = 512
y = 384
colours = [“ff0000”, “00ff00”, “0000ff”]
img = RippedImage.new(1, x, y)
for x in 0…x
for y in 0…y
img.draw(x, y, colours[rand(colours.length)])
end
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.

Does anyone have any suggestions as to how to increase this generation
speed? I’ve tried hunting through the RMagick docs for some way to
provide an array of pixel data or something similar, but nothing’s
jumped out at me. Test code below.

If RMagic has support for some sort of raw format (RGBA, etc), then it
will probably be significantly faster to pack your raw pixel data (using
Array#pack) and create a new image for each “frame” that way.

If that won’t work, Imlib2-Ruby may be fast enough to do what you want,
I wrote a quick test and that loops and creates a full copy of a 32-bit
640x480 image. Note that depending on your application, this could
probably be sped up significantly (specifically, the image data could
be modified in place and wrapped using Imlib2::Image.create_using_data
instead of copied repeatedly with Image#create_using_copied_data). Here
are the machine specs:

Linux halcyon 2.6.13.1-bs-skas-skas3-v9-pre7 #5 SMP Fri Oct 21 

22:44:15
EDT 2005 i686 GNU/Linux
model name : Intel(R) Pentium(R) M processor 2.13GHz
cpu MHz : 798.213
bogomips : 1597.88

Here’s the results of 5 separate runs on the aforementioned hardware, at
1000 frames each:

              user       system     total      real
cucd (x1000)  0.980000   1.150000   2.130000 ( 19.992796)
"frames"/sec = ~50.2272937653813 fps
cucd (x1000)  0.980000   1.140000   2.120000 ( 20.160243)
"frames"/sec = ~49.7235522268876 fps
cucd (x1000)  0.970000   1.130000   2.100000 ( 26.509965)
"frames"/sec = ~38.0623666660269 fps
cucd (x1000)  0.970000   1.200000   2.170000 ( 20.236222)
"frames"/sec = ~50.6165552265999 fps
cucd (x1000)  0.960000   1.150000   2.110000 ( 18.592911)
"frames"/sec = ~54.1268296888017 fps

Which averages out to approximately 48.5 FPS. Since the tests are
measuring different things and our hardware is different, we can’t
compare times directly, but here’s the output from a couple runs of your
test code on my machine for reference:

pabs@halcyon:~/proj/imlib2-fps-test> time ruby ./rmagic_test.rb
real    0m12.247s
user    0m11.175s
sys     0m0.351s
pabs@halcyon:~/proj/imlib2-fps-test> time ruby ./rmagic_test.rb
real    0m12.014s
user    0m11.197s
sys     0m0.290s

I’ve tarred up the test scripts, image (a shot of my football-
obsessed friend’s basement), and results and posted them at the
following URL:

http://pablotron.org/files/imlib2-ruby-fps_test.tar.gz
(SHA1: d6c4f7208ce030591a064a445130e44fc0b64b0f)