by mars on 2006-07-16
filed in Work with tags , , ,

Mogrify is ImageMagick's command-line utility to transform images. I'm using it within MiniMagick, a Rails plugin that allows image manipulation with minimum memory usage compared to the more ruby-like RMagick bindings.

So the point of this post... Do you get errors like "mogrify: unable to open module file" when it's looking for a coder?

The whole error is like:

mogrify: unable to open module file 
`/usr/local/lib/ImageMagick-6.2.8/modules-Q8/coders/1.la': 
No such file or directory.

The problem is that Ruby's Tempfile naming scheme uses a numeric filename extension, for example "tempfile666.1" instead of a more meaningful "tempfile666.jpg". Mogrify understands an image file without a filename extension, but apparently an erroneous file extension overrides that magic mechanism.

So, we need to change the behavior of the Tempfile class to avoid that problematic extension. In the ruby code, before loading images with MiniMagick, open up that Tempfile class and redefine #make_tmpname to use a hyphen instead of a period.

Before *(lifted from /usr/local/lib/ruby/1.8/tempfile.rb)*:

1
2
3
4
5
    class Tempfile
      def make_tmpname(basename, n)
        sprintf('%s%d.%d', basename, $$, n)
      end
    end

After *(when defining your MiniMagick-implementing class)*:

1
2
3
4
5
6
    # fix Tempfile to work with mogrify by removing filename extension
    class Tempfile
      def make_tmpname(basename, n)
        sprintf('%s%d-%d', basename, $$, n)
      end
    end

7 Responses to “of Mogrify, Ruby Tempfile & Dynamic Class Definitions”

mzpn commented
2007-07-15 at 10:48 AM
fun
Steve commented
2007-07-15 at 10:48 AM
I had the same exact problem and extended your idea a little. This modification to make_tmpname allows you to create temp files with whatever extension you like (but if you don't specify an extension, it works like normal):
Module MiniMagick
  class ImgTempFile < Tempfile
    def make_tmpname(basename, n)
      # force tempfile to use basename's extension if provided
      ext = File::extname(basename)
      # force hyphens instead of periods in name
      sprintf('%s%d-%d%s', File::basename(basename, ext), $$, n, ext)
    end
  end # class
end # module
Also, I chose to subclass Tempfile rather than overwrite, which required a small alteration to mini_magick.rb:
          tmp = ImgTempFile.new("minimagic")
Finally, here's a short test that shows it's working (put it in any convenient test file that gets run on related stuff):
  def test_image_temp_file
    tmp = MiniMagick::ImgTempFile.new('test')
    assert_match %r{^test}, File::basename(tmp.path)
    tmp = MiniMagick::ImgTempFile.new('test.jpg')
    assert_match %r{^test}, File::basename(tmp.path)
    assert_match %r{\.jpg$}, File::basename(tmp.path)
  end
Matt commented
2008-04-28 at 09:57 AM

Do you know if the newest version fixes this? == 1.2.2 / 2007-06-01

silverdr commented
2009-08-08 at 11:21 AM

Steve - thanks. Simple solution to my problem.

Shyam Khadka commented
2010-10-04 at 11:38 PM

Looks great!! But in my case, ext = File::extname(basename) doesn't return anything.

So that I am not able to get extension of temp file using file_field of rails. Any suggestions are highly welcomed!!

Michael MacDonald commented
2011-01-05 at 08:43 PM

When I upgraded to Ruby 1.9.2 I got the following error with this patch:

can't convert nil into Integer

To solve this, I used the same trick as the paperclip folks used:

sprintf('%s%d-%d%s', File::basename(basename, ext), $$, n.to_i, ext)

Notice the addition of n.to_i.

Fred Liang commented
2011-10-08 at 08:28 PM

Why you didn't pass params like this Tempfile.new ['filenane', '.stuffix']

Comments are closed for this article.



Everything is here.