Another IO.popen question ...

A

Adam Groves

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
 
J

Joel VanderWerf

Adam said:
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:-")
 
T

Timothy Hunter

Adam said:
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
 
A

Adam Groves

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?
 
A

Adam Groves

Timothy said:
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


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?
 
T

Timothy Hunter

Adam said:
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.
 
A

ara.t.howard

would this work?

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

or simply

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

yeah - that's it alright

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

dump it to stdout...

-a
 
A

ara.t.howard

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?

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
 
J

Joel VanderWerf

Adam said:
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
 
J

Joel VanderWerf

Joel said:
Adam said:
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.
 
A

ara.t.howard

Adam said:
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.

-a
 
J

Joel VanderWerf

Adam said:
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.

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.
 
A

ara.t.howard

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.

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top