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

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Aade3c292661517519f48c1f47325aa0?d=identicon&s=25 Tim Blair (Guest)
on 2006-04-05 17:38
(Received via mailing list)
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.
Ff260830c27224f0e15f37362a6256d0?d=identicon&s=25 Paul Duncan (Guest)
on 2006-04-05 21:34
(Received via mailing list)
* Tim Blair (tblair@rawnet.com) wrote:
[snipped]
> 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)
This topic is locked and can not be replied to.