Another IO.popen question

Hi,

I'm wanting to create thumbnails of pdfs in png format and send them off
to be saved. I've come up with this so far:

    IO.popen("curl #{some_uri} | convert -resize 700x700 pdf:-[0]
png:-") {|f| do_something_with_this_file}

Which works a treat. (In case you didn't know, convert is a command line
tool for ImageMagick).

What I'd really like to do though is pass on a File object to convert:

file = File.open("mypdf.pdf")

    IO.popen("#{file} | convert -resize 700x700 pdf:-[0] png:-") {|f|
do_something_with_this_file}

This obviously doesn't work but I hope illustrates what I'm wanting to
acheive - namely to pass 'file' to convert it to a png which is read
back into ruby and uploaded to my file repository on S3.

By the way, this IS for a rails application, but it seems basically like
a pure ruby question to me.

Regards

Adam

···

--
Posted via http://www.ruby-forum.com/.

Adam Groves wrote:

Hi,

I'm wanting to create thumbnails of pdfs in png format and send them off to be saved. I've come up with this so far:

    IO.popen("curl #{some_uri} | convert -resize 700x700 pdf:-[0] png:-") {|f| do_something_with_this_file}

Which works a treat. (In case you didn't know, convert is a command line tool for ImageMagick).

What I'd really like to do though is pass on a File object to convert:

file = File.open("mypdf.pdf")

    IO.popen("#{file} | convert -resize 700x700 pdf:-[0] png:-") {|f| do_something_with_this_file}

would this work?

file = "mypdf.pdf"
IO.popen("cat #{file} | ...")

or simply

IO.popen("convert -resize 700x700 #{file} png:-")

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Adam Groves wrote:

Hi,

I'm wanting to create thumbnails of pdfs in png format and send them off to be saved. I've come up with this so far:

    IO.popen("curl #{some_uri} | convert -resize 700x700 pdf:-[0] png:-") {|f| do_something_with_this_file}

Which works a treat. (In case you didn't know, convert is a command line tool for ImageMagick).

What I'd really like to do though is pass on a File object to convert:

file = File.open("mypdf.pdf")

    IO.popen("#{file} | convert -resize 700x700 pdf:-[0] png:-") {|f| do_something_with_this_file}

This obviously doesn't work but I hope illustrates what I'm wanting to acheive - namely to pass 'file' to convert it to a png which is read back into ruby and uploaded to my file repository on S3.

By the way, this IS for a rails application, but it seems basically like a pure ruby question to me.

Regards

Adam

Consider RMagick: http://rmagick.rubyforge.org

The Magick::Image.read method accepts an open Ruby file object as an argument.

http://www.simplesystems.org/RMagick/doc/image1.html#read

Hi Joel,

thanks for the speedy reply! The problem is, I need to pass on a file
object (which has been uploaded from a web page form) to 'convert' and
not just a path. I should have made this clearer in my original post.

Any ideas?

···

--
Posted via http://www.ruby-forum.com/.

Timothy Hunter wrote:

Adam Groves wrote:

By the way, this IS for a rails application, but it seems basically like
a pure ruby question to me.

Regards

Adam

Consider RMagick: http://rmagick.rubyforge.org

The Magick::Image.read method accepts an open Ruby file object as an
argument.

RMagick 1.15.0: class Image (class and instance methods, part 1)

hmm.. Maybe you're right Tim. I was just wanting to drop to the command
line to do this and thought there must be a way of accomplishing this
without resorting to RMagick. Not that I have anything against it.

Is there really no other way of passing on a Ruby file object
imagemagick other than through RMagick?

···

--
Posted via http://www.ruby-forum.com/\.

yeah - that's it alright

  png = IO.popen("convert -resize 700x700 #{file} png:-"){|pipe| pipe.read}

dump it to stdout...

-a

···

On Fri, 17 Nov 2006, Joel VanderWerf wrote:

would this work?

file = "mypdf.pdf"
IO.popen("cat #{file} | ...")

or simply

IO.popen("convert -resize 700x700 #{file} png:-")

--
my religion is very simple. my religion is kindness. -- the dalai lama

Adam Groves wrote:

hmm.. Maybe you're right Tim. I was just wanting to drop to the command line to do this and thought there must be a way of accomplishing this without resorting to RMagick. Not that I have anything against it.

Is there really no other way of passing on a Ruby file object imagemagick other than through RMagick?
  

Consider that the convert command only accepts string options. It knows nothing about Ruby.

you can pass convert files on stdin. you need somthing like

   stdin = file_object.read

   cmd = " convert - png:- " # input on stdin, output to stdout

   stdout =
     IO.popen( cmd, 'r+' ) do |pipe|
       pipe.write stdin
       pipe.close_write
       pipe.read
     end

   abort "cmd <#{ cmd }> failed" unless $? == 0

   open the_png, 'w' do |f|
     f.write stdout
   end

regards.

-a

···

On Fri, 17 Nov 2006, Adam Groves wrote:

Hi Joel,

thanks for the speedy reply! The problem is, I need to pass on a file
object (which has been uploaded from a web page form) to 'convert' and
not just a path. I should have made this clearer in my original post.

Any ideas?

--
my religion is very simple. my religion is kindness. -- the dalai lama

Adam Groves wrote:

Hi Joel,

thanks for the speedy reply! The problem is, I need to pass on a file object (which has been uploaded from a web page form) to 'convert' and not just a path. I should have made this clearer in my original post.

Any ideas?

Untested, but maybe something like this?

file = File.open("mypdf.pdf")
IO.popen("convert -resize 700x700 pdf:-[0] png:-") do |f|
   while (data=file.read(N))
     f.write data
   end
end

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Joel VanderWerf wrote:

Adam Groves wrote:

Hi Joel,

thanks for the speedy reply! The problem is, I need to pass on a file object (which has been uploaded from a web page form) to 'convert' and not just a path. I should have made this clearer in my original post.

Any ideas?

Untested, but maybe something like this?

file = File.open("mypdf.pdf")
IO.popen("convert -resize 700x700 pdf:-[0] png:-") do |f|

                                              ^^^^^
...this bit is the problem. So Ara's r+ pipe would be necessary, unless you can put a filename here instead.

Also, I forgot the "w" mode.

···

  while (data=file.read(N))
    f.write data
  end
end

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

careful, if you don't read the child will block when the pipe becomes full i
think. you might need to add

   file = File.open("mypdf.pdf")

   png =
     IO.popen("convert -resize 700x700 pdf:-[0] png:-") do |f|
       while (data=file.read(N))
         f.write data
       end
       f.close_write
       f.read
     end

not sure if that was obvious or not... sorry if it was.

-a

···

On Fri, 17 Nov 2006, Joel VanderWerf wrote:

Adam Groves wrote:

Hi Joel,

thanks for the speedy reply! The problem is, I need to pass on a file object (which has been uploaded from a web page form) to 'convert' and not just a path. I should have made this clearer in my original post.

Any ideas?

Untested, but maybe something like this?

file = File.open("mypdf.pdf")
IO.popen("convert -resize 700x700 pdf:-[0] png:-") do |f|
while (data=file.read(N))
   f.write data
end
end

--
my religion is very simple. my religion is kindness. -- the dalai lama

I was confused in several respects: I was thinking of a one-way pipe (but I forgot the "w"), in which case blocking wouldn't be a problem. But the one-way pipe would only be useful if the OP could put a filename in place of the "png:-".

The one-way pipe has the advantage that you can read(N) instead of read(), and keep memory bounded. Maybe it's not an issues for the OP, though.

···

ara.t.howard@noaa.gov wrote:

On Fri, 17 Nov 2006, Joel VanderWerf wrote:

Adam Groves wrote:

Hi Joel,

thanks for the speedy reply! The problem is, I need to pass on a file object (which has been uploaded from a web page form) to 'convert' and not just a path. I should have made this clearer in my original post.

Any ideas?

Untested, but maybe something like this?

file = File.open("mypdf.pdf")
IO.popen("convert -resize 700x700 pdf:-[0] png:-") do |f|
while (data=file.read(N))
   f.write data
end
end

careful, if you don't read the child will block when the pipe becomes full i
think. you might need to add

  file = File.open("mypdf.pdf")

  png =
    IO.popen("convert -resize 700x700 pdf:-[0] png:-") do |f|
      while (data=file.read(N))
        f.write data
      end
      f.close_write
      f.read
    end

not sure if that was obvious or not... sorry if it was.

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

huh. never really thought of it that way - good reason to do

   require 'tempfile'

   t = Tempfile.new Process.pid.to_s
   t.close

   cmd = "convert ... > #{ t.path }"

   # etc

cheers.

-a

···

On Fri, 17 Nov 2006, Joel VanderWerf wrote:

I was confused in several respects: I was thinking of a one-way pipe (but I
forgot the "w"), in which case blocking wouldn't be a problem. But the
one-way pipe would only be useful if the OP could put a filename in place of
the "png:-".

The one-way pipe has the advantage that you can read(N) instead of read(), and keep memory bounded. Maybe it's not an issues for the OP, though.

--
my religion is very simple. my religion is kindness. -- the dalai lama