IMGKit 1.3 Released!

I‘ve released a new version of the IMGKit gem that incorporates some enhancements that while alone may not warrant discussion, taken together add some well-tested new functionality.

Moar Formats

I‘d always felt a shortcoming of the gem was that it artificially restricted results to the JPG format. Although this format makes sense for the majority of cases, I had some requests for supporting the other formats.

It turned out that passing the --format flag was always a possiblity, but I wanted something more ruby-like. Specificially, I created a group of #to_<format> methods for jpgs, pngs, and tiffs.

Encodings? Oh my!

A big part of adding the to_format methods was how I was going to be able to test it. I opted to write a matcher that uses the magic number (first 4 bytes) of the data to determine its format. This way, I can test the generated data itself and not just that all the right method calls happened.

module MagicNumber
  extend self
  JPG  = "\xFF\xD8\xFF\xE0"
  JPEG = JPG
  PNG  = "\x89\x50\x4e\x47"
  TIFF = "\x49\x49\x2a\x00"
  TIF  = TIFF
  GIF  = "\x47\x49\x46\x38"


  if "".respond_to?(:force_encoding) 
    constants.each { |c| const_get(c).force_encoding("ASCII-8BIT")  }
  end

  def read(string)
    string[0,4]
  end
end

RSpec::Matchers.define :be_a do |expected|
  match do |actual|
    @expected = MagicNumber.const_get(expected.to_s.upcase)
    MagicNumber.read(actual) == @expected
  end

  failure_message_for_should do |actual|
    actual = MagicNumber.read(actual)
    "expctected #{actual.inspect},#{actual.encoding} to equal #{@expected.inspect},#{@expected.encoding}"
  end
end

I can then use these in a test as:

  IMGKit.new("Hello, world").to_img.should be_a(:jpg)

Things were looking pretty good until I ran the actual tests under Ruby 1.9. In MRI Ruby 1.9, the string encoding was causing the string comparison in the matcher to fail! The strings in the MagicNumber class were being treated as ASCII-8BIT, whereas the strings representing the image data were UTF-8.

At first, I coded a solution that allowed the image‘s binary data to get coerced into a UTF-8 string. However, this is not the type of data that is being represented. Encoding the binary string returned by #to_img as UTF-8 is the wrong fit and only creates the kind of weird equality bug I was seeing. ASCII-8BIT is the encoding type for binary data, so I explicity coerce to and test for this encoding.

Moar Compatibility

However, the string coercision code could possibly introduce compatibilities with other rubies. RVM to the rescue!

RVM has a feature that allows you to run specs under multiple different versions of Ruby:

specs - runs 'rake spec' across selected ruby versions

so with the following runner:

rvm 1.9.2\@imgkit_devel,1.8.7\@imgkit specs

I can ensure compatibility with earlier Ruby!

Real Error Messages

Lastly, I got a useful commit from @kouldelka that actually raises an error if the wkhtmltoimage command fails.

Conclusion

I hope these changes make using IMGKit more fun and reliable!

c2

Fork me on GitHub