Forum: Ruby Re: 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-06 13:57
(Received via mailing list)
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?!" :)

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.
801b207647d808477fc4514568c9d723?d=identicon&s=25 Dimitri Aivaliotis (Guest)
on 2006-04-06 16:13
(Received via mailing list)
Hi Tim,

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

- Dimitri
Cb48ca5059faf7409a5ab3745a964696?d=identicon&s=25 unknown (Guest)
on 2006-04-06 19: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 = 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
This topic is locked and can not be replied to.