Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Image resizing without all the bloat

branch: master

Fetching latest commit…

Octocat-spinner-32-eaf2f5

Cannot retrieve the latest commit at this time

Octocat-spinner-32 lib
Octocat-spinner-32 test
Octocat-spinner-32 .gitignore
Octocat-spinner-32 .rvmrc
Octocat-spinner-32 LICENSE
Octocat-spinner-32 README.markdown
Octocat-spinner-32 imagery.gemspec
Octocat-spinner-32 imagery.gemspec.erb
README.markdown

Imagery

Image manipulation should be simple. It should be customizable. It should allow for flexibility. Imagery attempts to solve these.

Imagery favors:

  1. Simplicity and explicitness over magic DSLs.
  2. OOP principles such as inheritance and composition.
  3. Flexibility and extensibility.
  4. Not being tied to any form of ORM.

1. Simplicity and Explicitness

To get started using Imagery you only need GraphicsMagick, ruby and Imagery of course.

# on debian based systems
sudo apt-get install graphicsmagick
# or maybe using homebrew
brew install graphicsmagick
[sudo] gem install imagery

Then you may proceed using it.

require 'rubygems'
require 'imagery'

i = Imagery.new(:photo, "1001", thumb: ["48x48^", "48x48"])
i.save(File.open('/some/path/to/image.jpg'))

File.exist?('public/photo/1001/thumb.jpg')
# => true

File.exist?('public/photo/1001/original.jpg')
# => true

2. OOP Principles (that we already know)

Ohm example (See http://ohm.keyvalue.org)

class User < Ohm::Model
  include Ohm::Callbacks

  after :save, :write_avatar

  def avatar=(fp)
    @avatar_fp = fp
  end

  def avatar
    Imagery.new :avatar, id, 
      :thumb => ["48x48^", "48x48"],
      :medium => ["120x120"]
  end

protected
  def write_avatar
    avatar.save(@avatar_fp[:tempfile]) if @avatar_fp
  end
end

# Since we're using composition, we can customize the dimensions on an 
# instance level.
class Collage < Ohm::Model
  attribute :width
  attribute :height

  def photo
    Imagery.new :photo, id, :thumb => ["%sx%s" % [width, height]]
  end
end

# For cases where we want to use S3 for some and normal filesystem for others
class S3Photo < Imagery
  include Imagery::S3

  s3_bucket "my-bucket"
end

# then maybe some other files are using cloudfront
class CloudfrontPhoto < Imagery
  include Imagery::S3

  s3_bucket "my-bucket"
  s3_distribution_domain "assets.site.com"
end

# some might be using S3 EU, in which case you can specify the s3_host
class CustomS3Host < Imagery::Model
  include Imagery::S3
  s3_host "http://my.custom.host"
  s3_bucket "my-bucket-name"
end

3. Flexibility and Extensibility

Existing plugins: Faking and S3

Imagery::S3

As was shown in some examples above you can easily do S3 integration. The access credentials are assumed to be stored in

ENV["AMAZON_ACCESS_KEY_ID"]
ENV["AMAZON_SECRET_ACCESS_KEY"]

you can do this by setting it on your .bash_profile / .bashrc or just manually setting them somewhere in your appication

ENV["AMAZON_ACCESS_KEY_ID"] = "_access_key_id_"
ENV["AMAZON_SECRET_ACCESS_KEY"] = "_secret_access_key_"

Now you can just start using it:

class Imagery
  include Imagery::S3
  s3_bucket "my-bucket"
end

i = Imagery.new :photo, 1001
i.save(File.open("/some/path/to/image.jpg"))

Imagery::Faking

When doing testing, you definitely don't want to run image resizing everytime. Enter Faking.

# in your test_helper / spec_helper
Imagery::Model.send :include, Imagery::Faking
Imagery::Model.mode = :fake

# but what if we want to run it for real on a case to case basis?
# sure we can!
Imagery::Model.real {
  # do some imagery testing here
}

Imagery::Test

There is a module you can include in your test context to automate the pattern of testing / faking on an opt-in basis.

# in your test_helper / spec_helper
class Test::Unit::TestCase
  include Imagery::Test
end

# now when you do some testing... (User assumes the user example above)
imagery do |enabled|
  user = User.new(:avatar => { tempfile: File.open("avatar.jpg") })
  user.save

  if enabled
    assert File.exist?(user.avatar.root("original.jpg"))
  end
end

Running your test suite:

REAL_IMAGERY=true rake test

It's off by default though, so you don't have to do anything to make sure Imagery doesn't run.

Extending Imagery

By making use of standard Ruby idioms, we can easily do lots with it. Exensibility is addressed via Ruby modules for example:

class Imagery
  module MogileStore
    def self.included(base)
      class << base
        attr_accessor :mogile_config
      end
    end

    def save(io)
      if super
        # do some mogie FS stuff here
      end
    end

    def delete
      super
      # remove the mogile stuff here
    end
  end
end

# Now just include the module to use it.
class Imagery
  include Imagery::MogileStore
  self.mogile_config = { :foo => :bar }
end

Note on Patches/Pull Requests

  • Fork the project.
  • Make your feature addition or bug fix.
  • Add tests for it. This is important so I don't break it in a future version unintentionally.
  • Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
  • Send me a pull request. Bonus points for topic branches.

Copyright

Copyright (c) 2010 Cyril David. See LICENSE for details.

Something went wrong with that request. Please try again.