Ask RMagick to send a direct command to ImageMagick - ruby

Some options of ImageMagick are not supported by RMagick. Also sometimes it is in fact more convenient to use ImageMagick. Is there a method (of the Image object) that allows you to send commands directly to ImageMagick using the command line interface?

Would it be ok for you to use system or system call via backticks (or similar)?
You may also extend Magick::Image to do it easier.
My example code add a method convert to call the convert-command of imagemagick for the actual image. The action to be performed must be added.
require 'rmagick'
module Magick
class Image
def convert( cmd )
`convert #{self.filename} #{cmd}`
end
end
end
picname = Dir['*.jpg'].first
img = Magick::Image.read(picname).first
img.convert('x.png')

Related

"Too many open files" error when using named pipes

I'm running 2 scripts and after a while, I'm getting Too many open files # error/blob.c/ImageToFile/1832.
Simplified version of the first scripts. It's supposed to read images written to image_pipe, process them, and write them to ocr_pipe for the OCR to read.
# creates 2 named pipes
File.mkfifo(image_pipe) rescue nil
File.mkfifo(ocr_pipe) rescue nil
while image = Image.read(image_pipe)
# do some stuff with `image`...
end
The second script is using ffmpeg to extract frames from a video, writing them to image_pipe
# image_pipe is the same as the script above.
(14..movie.duration).step(0.5) do
`/usr/local/bin/ffmpeg [some options...] #{image_pipe}`
end
I think the issue is RMagick opening too many file descriptors when reading the images in the loop of the first script, but I'm not sure how to stop that from happening. The Magick::Image class doesn't have a close method or anything, afaik.
I did not find the root cause of the issue, but ulferts helped me find a workaround that's acceptable for me.
Instead of letting RMagick open the file itself, we should handle it on our side, and then use .from_blob to create the Magick::Image instance.
while f = File.read(image_pipe)
image = Image.from_blob(f)
# ... do stuff with image.
end

Saving a GIF image with RMagick failure

I'm using ruby 2.1.0, rmagick 2.15.4, ImageMagick 6.7.7-10
I'd like to load a JPEG file and then save in the GIF format.
x = Magick::Image.read("a.jpg").first
puts "Start write..."
x.format = "GIF"
x.write("a.gif")
puts "Done."
Gives me this:
Start write...
cli.rb:104:in `exit': no implicit conversion from nil to integer (TypeError)
The stack trace includes foreman and thor gems, but no step in my code.
The filesystem has a.gif defined, but the filesize is zero.
UPDATE
I think I have a problem with ImageMagick itself. Here's what happens on the command line:
$ convert -debug a.jpg a.gif
convert.im6: unrecognized event type `a.jpg' #error/convert.c/ConvertImageCommand/1135.
It looks like this question was answered here:
JPG to PNG using RMagick
Just changing the file name will not convert he file format.
Yes it will. Something else is going on here.
"This makes it easy to convert an image file to another format. Simply write the image file using a name that has either a prefix or a suffix corresponding to the format you want."
https://rmagick.github.io/imusage.html

Imagemagick's -lat '50x50' not working in minimagick

I need to run local adaptive threshold(-lat) method in MiniMagick.
I tried with the following code:
image.lat '50x50'
Its give an error stack level too deep when image.write 'output.jpg' is run.
Can anyone suggest a way to use (-lat) method in MiniMagick.
The common approach to stack options with MiniMagick is combine_options:
image.combine_options do |c|
c.lat '50x50'
# more options
end
This should not help in your case, though. Image#write copies the file from temporary location to the local file with given name. You might want to inspect your temporary file in /var/folders/.... to see whether the threshold was applied.
It sounds like an imagemagick glitch. Did you try
$ mogrify -lat 50x50 file.jpg
Does it work?
It looks like the -lat command is not included in mogrify. I ran into the same problem and found this question, two years after the OP, using IM version 6.9.2-3 Q16 x64 on Windows 7.
There is a discussion on the ImageMagick board here.

Better ruby terminal coloring library

There are plenty of coloring libraries: colored, term-ansicolor.
But is there any which can do this:
puts "#{'hello'.red} world!".bold
And world! should be bold.
To make it clear, I want to get this:
"\e[1m\e[31mhello\e[0m\e[1m world!\e[0m"
or better even this (just shorter):
"\e[1;31mhello\e[0;1m world!\e[0m"
instead of this:
"\e[1m\e[31mhello\e[0m world!\e[0m"
As there is none, I wrote my own, with blackjack and hookers smart one — smart_colored
gem install smart_colored
and run
require 'smart_colored/extend'
# without extend you'll need to use 'string'.colored.red
puts "#{'hello'.red} world!".bold
The lib is called Highline
It has a color method: say("This should be <%= color('bold', BOLD) %>!")
Which can be easily used to implement String#bold.
In case you are using highline I made a gem that extends colors and provides helpers such as:
say_bold 'this is bold text'
https://github.com/bonzofenix/highline-color

Ruby: How to determine if file being read is binary or text

I am writing a program in Ruby which will search for strings in text files within a directory - similar to Grep.
I don't want it to attempt to search in binary files but I can't find a way in Ruby to determine whether a file is binary or text.
The program needs to work on both Windows and Linux.
If anyone could point me in the right direction that would be great.
Thanks,
Xanthalas
libmagic is a library which detects filetypes. For this solution I assume, that all mimetype's which start with text/ represent text files. Eveything else is a binary file. This assumption is not correct for all mime types (eg. application/x-latex, application/json), but libmagic detect's these as text/plain.
require "filemagic"
def binary?(filename)
begin
fm= FileMagic.new(FileMagic::MAGIC_MIME)
!(fm.file(filename)=~ /^text\//)
ensure
fm.close
end
end
gem install ptools
require 'ptools'
File.binary?(file)
An alternative to using the ruby-filemagic gem is to rely on the file command that ships with most Unix-like operating systems. I believe it uses the same libmagic library under the hood but you don't need the development files required to compile the ruby-filemagic gem. This is helpful if you're in an environment where it's a bit of work to install additional libraries (e.g. Heroku).
According to man file, text files will usually contain the word text in their description:
$ file Gemfile
Gemfile: ASCII text
You can run the file command through Ruby can capture the output:
require "open3"
def text_file?(filename)
file_type, status = Open3.capture2e("file", filename)
status.success? && file_type.include?("text")
end
Updating above answer with such example, when file name includes "text":
file /tmp/ball-texture.png
/tmp/ball-texture.png: PNG image data, 11 x 18, 8-bit/color RGBA, non-interlaced
So updated code will be like:
def text_file?(filename)
file_type, status = Open3.capture2e('file', filename)
status.success? && file_type.split(':').last.include?('text')
end

Resources