smartimage 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ README.textile
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Tony Arcieri
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,11 @@
1
+ h1. SmartImage
2
+
3
+ Hi. There will be a real README here soon, I promise.
4
+
5
+ h2. Credits
6
+
7
+ SmartImage assumes your Ruby interpreter supports the absurdly powerful RMagick
8
+ library, unless you're running JRuby, in which case it uses the absurdly
9
+ powerful Java Graphics2D library and AWT.
10
+
11
+ Mongoose courtesy Wikimedia Commons: http://en.wikipedia.org/wiki/File:Mongoose.jpg
@@ -0,0 +1,52 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "smartimage"
8
+ gem.summary = %Q{It's like a Swiss Army Knife for images, but one of those tiny ones you can keep on your keychain}
9
+ gem.description = <<-EOD
10
+ SmartImage provides a cross-platform solution for image compositing that works on both MRI and JRuby.
11
+ If using RMagick feels like swatting a fly with a nucler missile, and ImageScience just doesn't get
12
+ you there, SmartImage is hopefully at that sweet spot in the middle
13
+ EOD
14
+
15
+ gem.email = "tony@medioh.com"
16
+ gem.homepage = "http://github.com/tarcieri/smartimage"
17
+ gem.authors = ["Tony Arcieri"]
18
+ gem.add_dependency "imagesize", ">= 0.1.1"
19
+ gem.add_dependency "rmagick", ">= 2.12.2"
20
+ gem.add_development_dependency "rspec", ">= 1.2.9"
21
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
22
+ end
23
+ Jeweler::GemcutterTasks.new
24
+ rescue LoadError
25
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
26
+ end
27
+
28
+ require 'spec/rake/spectask'
29
+ Spec::Rake::SpecTask.new(:spec) do |spec|
30
+ spec.libs << 'lib' << 'spec'
31
+ spec.spec_files = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
35
+ spec.libs << 'lib' << 'spec'
36
+ spec.pattern = 'spec/**/*_spec.rb'
37
+ spec.rcov = true
38
+ end
39
+
40
+ task :spec => :check_dependencies
41
+
42
+ task :default => :spec
43
+
44
+ require 'rake/rdoctask'
45
+ Rake::RDocTask.new do |rdoc|
46
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
47
+
48
+ rdoc.rdoc_dir = 'rdoc'
49
+ rdoc.title = "smartimage #{version}"
50
+ rdoc.rdoc_files.include('README*')
51
+ rdoc.rdoc_files.include('lib/**/*.rb')
52
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
@@ -0,0 +1,137 @@
1
+ require 'image_size'
2
+ require 'smart_image/ratio_calculator'
3
+
4
+ # Load the appropriate canvas class for the current environment
5
+ if defined? JRUBY_VERSION
6
+ require 'smart_image/java_canvas'
7
+ else
8
+ require 'smart_image/rmagick_canvas'
9
+ end
10
+
11
+ # SmartImage: it's like a Swiss Army Knife for images, but one of those tiny
12
+ # ones you can keep on your keychain.
13
+ class SmartImage
14
+ # I'm sorry, I couldn't understand the data you gave me
15
+ class FormatError < ArgumentError; end
16
+
17
+ # Struct type containing information about a given image
18
+ class Info < Struct.new(:width, :height, :type); end
19
+
20
+ class << self
21
+ # Obtain basic information about the given image data
22
+ # Returns a SmartImage::Info object
23
+ def info(data)
24
+ img = ImageSize.new data
25
+ raise FormatError, "invalid image" if img.get_type == "OTHER"
26
+
27
+ Info.new(img.width, img.height, img.get_type.downcase.to_sym)
28
+ end
29
+
30
+ # Obtain information about a file
31
+ # Returns a SmartImage::Info object
32
+ def file_info(path)
33
+ info File.read(path)
34
+ end
35
+ end
36
+
37
+ # Create a new SmartImage of the given width and height. Always takes a
38
+ # block... no exceptions! Returns a destroyed SmartImage object.
39
+ #
40
+ # SmartImage.new(400, 300) do |compositor|
41
+ # compositor.image "foo/bar.jpg", :x => 10, :y => 10
42
+ # compositor.text "Hello, world!", :x => 20, :y => 20
43
+ # compositor.write "baz/qux.jpg"
44
+ # end
45
+ #
46
+ # When used with a block, all images are automatically freed from memory
47
+ def initialize(width, height, &block)
48
+ raise ArgumentError, "give me a block, pretty please" unless block_given?
49
+
50
+ @width, @height = Integer(width), Integer(height)
51
+ @canvas = SmartImage::Canvas.new @width, @height
52
+
53
+ yield self
54
+ @canvas.destroy
55
+ @canvas = DeadCanvas.new
56
+ end
57
+
58
+ class DeadCanvas
59
+ def method_missing(*args)
60
+ raise ArgumentError, "your image exists only within the SmartImage.new block"
61
+ end
62
+ end
63
+
64
+ # Composite the given image data onto the SmartImage
65
+ #
66
+ # Accepts the following options:
67
+ #
68
+ # * x: coordinate of the upper left corner of the image (default 0)
69
+ # * y: ditto, it's the y coordinate
70
+ # * width: an alternate width
71
+ # * height: alternate height
72
+ # * preserve_aspect_ratio: should the aspect ratio be preserved? (default: true)
73
+ def composite(data, options = {})
74
+ info = self.class.info data
75
+
76
+ opts = {
77
+ :x => 0,
78
+ :y => 0,
79
+ :width => info.width,
80
+ :height => info.height,
81
+ :preserve_aspect_ratio => true
82
+ }.merge(options)
83
+
84
+ if opts[:preserve_aspect_ratio]
85
+ composited_size = SmartImage::RatioCalculator.new(
86
+ :source_width => info.width,
87
+ :source_height => info.height,
88
+ :dest_width => Integer(opts[:width]),
89
+ :dest_height => Integer(opts[:height])
90
+ ).size
91
+
92
+ dest_width, dest_height = composited_size.width, composited_size.height
93
+ else
94
+ dest_width, dest_height = opts[:width], opts[:height]
95
+ end
96
+
97
+ @canvas.composite data, :width => Integer(dest_width),
98
+ :height => Integer(dest_height),
99
+ :x => opts[:x],
100
+ :y => opts[:y]
101
+ end
102
+
103
+ # Composite a given image file onto the SmartImage. Accepts the same options
104
+ # as the composite method
105
+ def composite_file(file, options = {})
106
+ composite File.read(file), options
107
+ end
108
+
109
+ # Apply an alpha mask from the given image data. Doesn't accept any options
110
+ # right now, sorry. It's just another useless dangling options hash.
111
+ def alpha_mask(data, options = {})
112
+ @canvas.alpha_mask data
113
+ end
114
+
115
+ # Apply an alpha mask from the given file. Accepts the same options as the
116
+ # alpha_mask method.
117
+ def alpha_mask_file(file, options = {})
118
+ alpha_mask File.read(file), options
119
+ end
120
+
121
+ # Encode the image with the given format (a file extension) and return it
122
+ # as a string. Doesn't accept any options at present. The options hash is
123
+ # just there to annoy you and make you wish it had more options.
124
+ def encode(format, options = {})
125
+ # Sorry .jpeg lovers, I'm one of you too but the standard is jpg
126
+ format = :jpg if format.to_s == 'jpeg'
127
+
128
+ @canvas.encode format, options
129
+ end
130
+
131
+ # Write the resulting image out to disk. Picks format based on filename.
132
+ # Takes the same options as encode
133
+ def write(path, options = {})
134
+ format = File.extname(path).sub(/^\./, '')
135
+ File.open(path, 'w') { |file| file << encode(format, options) }
136
+ end
137
+ end
@@ -0,0 +1,46 @@
1
+ class SmartImage
2
+ # Exception thrown for unimplemented features
3
+ class NotImplementedError < StandardError; end
4
+
5
+ # This class defines the set of methods all canvases are expected to implement
6
+ # It also documents the set of methods that should be available for a canvas
7
+ class BaseCanvas
8
+ # Create a new canvas object of the given width and height
9
+ def initialize(width, height)
10
+ raise NotImplementedError, "some silly person forgot to define a constructor"
11
+ end
12
+
13
+ # Destroy the canvas (if you need to)
14
+ def destroy
15
+ not_implemented :destroy
16
+ end
17
+
18
+ # Has the canvas been destroyed already?
19
+ def destroyed?
20
+ not_implemented :destroyed?
21
+ end
22
+
23
+ # Composite another image onto this canvas
24
+ def composite(image_data, width, height, options = {})
25
+ not_implemented :composite
26
+ end
27
+
28
+ # Load the given file as an alpha mask for the image
29
+ def alpha_mask(image_data, options = {})
30
+ not_implemented :alpha_mask
31
+ end
32
+
33
+ # Encode the image to the given format
34
+ def encode(format, options = {})
35
+ not_implemented :encode
36
+ end
37
+
38
+ #######
39
+ private
40
+ #######
41
+
42
+ def not_implemented(meth)
43
+ raise NotImplementedError, "#{meth} not implemented by #{self.class.inspect}"
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,74 @@
1
+ require 'smart_image/base_canvas'
2
+
3
+ class SmartImage
4
+ # Canvas object backed by Java Graphics2D
5
+ class JavaCanvas < BaseCanvas
6
+ java_import java.awt.image.BufferedImage
7
+ java_import javax.imageio.ImageIO
8
+ java_import java.io.ByteArrayInputStream
9
+ java_import java.io.ByteArrayOutputStream
10
+
11
+ def initialize(width, height)
12
+ @canvas = BufferedImage.new width, height, BufferedImage::TYPE_INT_ARGB
13
+ end
14
+
15
+ # Stub out destroy since Java actually garbage collects crap, unlike... C
16
+ def destroy
17
+ end
18
+
19
+ # Composite the given image data onto the canvas
20
+ def composite(image_data, options = {})
21
+ info = SmartImage.info image_data
22
+ opts = {
23
+ :width => info.width,
24
+ :height => info.height,
25
+ :x => 0,
26
+ :y => 0
27
+ }.merge(options)
28
+
29
+ input_stream = ByteArrayInputStream.new image_data.to_java_bytes
30
+ image = ImageIO.read input_stream
31
+ raise FormatError, "invalid image" unless image
32
+
33
+ graphics = @canvas.graphics
34
+ graphics.draw_image image, opts[:x], opts[:y], opts[:width], opts[:height], nil
35
+ end
36
+
37
+ # Load the given file as an alpha mask for the image
38
+ def alpha_mask(image_data, options = {})
39
+ input_stream = ByteArrayInputStream.new image_data.to_java_bytes
40
+ mask = ImageIO.read input_stream
41
+
42
+ width = mask.width
43
+ image_data, mask_data = Java::int[width].new, Java::int[width].new
44
+
45
+ mask.height.times do |y|
46
+ # fetch a line of data from each image
47
+ @canvas.get_rgb 0, y, width, 1, image_data, 0, 1
48
+ mask.get_rgb 0, y, width, 1, mask_data, 0, 1
49
+
50
+ width.times do |x|
51
+ # mask away the alpha
52
+ color = image_data[x] & 0x00FFFFFF
53
+
54
+ # turn red from the mask into alpha
55
+ alpha = (mask_data[x] & 0x00FF0000) << 8
56
+
57
+ image_data[x] = color | alpha
58
+ end
59
+
60
+ @canvas.set_rgb 0, y, width, 1, image_data, 0, 1
61
+ end
62
+ end
63
+
64
+ # Encode the image to the given format
65
+ def encode(format, options = {})
66
+ output_stream = ByteArrayOutputStream.new
67
+ ImageIO.write(@canvas, format.to_s, output_stream)
68
+ String.from_java_bytes output_stream.to_byte_array
69
+ end
70
+ end
71
+
72
+ # Java is our Canvas on Java, duh!
73
+ Canvas = JavaCanvas
74
+ end
@@ -0,0 +1,42 @@
1
+ class SmartImage
2
+ class RatioCalculator
3
+ # Create a new RatioCalculator object with the given options
4
+ def initialize(options = {})
5
+ @options = options
6
+ end
7
+
8
+ # Calculate the resulting size given a particular set of contraints
9
+ def size(options = {})
10
+ opts = @options.merge(options)
11
+
12
+ source = Size.new opts[:source_width], opts[:source_height]
13
+ bounds = Size.new opts[:dest_width], opts[:dest_height]
14
+
15
+ # Calculate what the width would be if we matched the dest height
16
+ naive_width = bounds.height * source.aspect_ratio
17
+
18
+ # If it fits, use it!
19
+ if naive_width <= bounds.width
20
+ width = naive_width
21
+ height = naive_width / source.aspect_ratio
22
+ # Otherwise, the height must fit
23
+ else
24
+ height = bounds.width / source.aspect_ratio
25
+ width = height * source.aspect_ratio
26
+ end
27
+
28
+ return Size.new(width, height)
29
+ end
30
+
31
+ #
32
+ # Struct to hold the resulting size and compute aspect ratios
33
+ #
34
+ class Size < Struct.new(:width, :height, :aspect_ratio)
35
+ def initialize(width, height)
36
+ width, height = Integer(width), Integer(height)
37
+ aspect_ratio = width.to_f / height
38
+ super(width, height, aspect_ratio)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,57 @@
1
+ require 'RMagick'
2
+ require 'smart_image/base_canvas'
3
+
4
+ class SmartImage
5
+ # Canvas object, backed by RMagick
6
+ class RMagickCanvas < BaseCanvas
7
+ include Magick
8
+
9
+ def initialize(width, height)
10
+ @canvas = Image.new width, height do
11
+ self.background_color = "transparent"
12
+ end
13
+ end
14
+
15
+ def destroy
16
+ @canvas.destroy!
17
+ end
18
+
19
+ def composite(image_data, options = {})
20
+ image = ImageList.new
21
+ image.from_blob image_data
22
+
23
+ opts = {
24
+ :width => image.columns,
25
+ :height => image.rows,
26
+ :x => 0,
27
+ :y => 0
28
+ }.merge(options)
29
+
30
+ image.thumbnail! opts[:width], opts[:height]
31
+ @canvas.composite! image, opts[:x], opts[:y], OverCompositeOp
32
+ ensure
33
+ image.destroy!
34
+ end
35
+
36
+ # Load the given file as an alpha mask for the image
37
+ def alpha_mask(image_data, options = {})
38
+ mask = ImageList.new
39
+ mask.from_blob image_data
40
+
41
+ # Disable this image's alpha channel to use the opacity data as a mask
42
+ mask.matte = false
43
+ @canvas.composite! mask, NorthWestGravity, CopyOpacityCompositeOp
44
+ ensure
45
+ mask.destroy!
46
+ end
47
+
48
+ # Encode this image into the given format (as a file extension)
49
+ def encode(format, options = {})
50
+ @canvas.format = format.to_s.upcase
51
+ @canvas.to_blob
52
+ end
53
+ end
54
+
55
+ # RMagick is our Canvas on everything besides JRuby. Hope it works for you!
56
+ Canvas = RMagickCanvas
57
+ end
@@ -0,0 +1,71 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{smartimage}
8
+ s.version = "0.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Tony Arcieri"]
12
+ s.date = %q{2010-03-26}
13
+ s.description = %q{ SmartImage provides a cross-platform solution for image compositing that works on both MRI and JRuby.
14
+ If using RMagick feels like swatting a fly with a nucler missile, and ImageScience just doesn't get
15
+ you there, SmartImage is hopefully at that sweet spot in the middle
16
+ }
17
+ s.email = %q{tony@medioh.com}
18
+ s.extra_rdoc_files = [
19
+ "LICENSE",
20
+ "README.textile"
21
+ ]
22
+ s.files = [
23
+ ".document",
24
+ ".gitignore",
25
+ "LICENSE",
26
+ "README.textile",
27
+ "Rakefile",
28
+ "VERSION",
29
+ "lib/smart_image.rb",
30
+ "lib/smart_image/base_canvas.rb",
31
+ "lib/smart_image/java_canvas.rb",
32
+ "lib/smart_image/ratio_calculator.rb",
33
+ "lib/smart_image/rmagick_canvas.rb",
34
+ "smartimage.gemspec",
35
+ "spec/fixtures/mask.png",
36
+ "spec/fixtures/mongoose.jpg",
37
+ "spec/smart_image_spec.rb",
38
+ "spec/spec.opts",
39
+ "spec/spec_helper.rb",
40
+ "spec/tmp/.gitignore"
41
+ ]
42
+ s.homepage = %q{http://github.com/tarcieri/smartimage}
43
+ s.rdoc_options = ["--charset=UTF-8"]
44
+ s.require_paths = ["lib"]
45
+ s.rubygems_version = %q{1.3.5}
46
+ s.summary = %q{It's like a Swiss Army Knife for images, but one of those tiny ones you can keep on your keychain}
47
+ s.test_files = [
48
+ "spec/smart_image_spec.rb",
49
+ "spec/spec_helper.rb"
50
+ ]
51
+
52
+ if s.respond_to? :specification_version then
53
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
54
+ s.specification_version = 3
55
+
56
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
57
+ s.add_runtime_dependency(%q<imagesize>, [">= 0.1.1"])
58
+ s.add_runtime_dependency(%q<rmagick>, [">= 2.12.2"])
59
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
60
+ else
61
+ s.add_dependency(%q<imagesize>, [">= 0.1.1"])
62
+ s.add_dependency(%q<rmagick>, [">= 2.12.2"])
63
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
64
+ end
65
+ else
66
+ s.add_dependency(%q<imagesize>, [">= 0.1.1"])
67
+ s.add_dependency(%q<rmagick>, [">= 2.12.2"])
68
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
69
+ end
70
+ end
71
+
Binary file
@@ -0,0 +1,44 @@
1
+ SPEC_DIR = File.dirname(__FILE__)
2
+ require SPEC_DIR + '/spec_helper'
3
+
4
+ describe SmartImage do
5
+ before :all do
6
+ @mongoose = SPEC_DIR + '/fixtures/mongoose.jpg'
7
+ @mask = SPEC_DIR + '/fixtures/mask.png'
8
+ @output_dir = SPEC_DIR + '/tmp/'
9
+ end
10
+
11
+ it "obtains image information" do
12
+ info = SmartImage.file_info(@mongoose)
13
+
14
+ info.type.should == :jpeg
15
+ info.width.should == 1327
16
+ info.height.should == 1260
17
+ end
18
+
19
+ it "composites images" do
20
+ SmartImage.new(800, 400) do |image|
21
+ image.composite_file @mongoose, :y => 15
22
+ image.write @output_dir + 'composited.png'
23
+ end
24
+ end
25
+
26
+ it "scales when compositing" do
27
+ SmartImage.new(800, 400) do |image|
28
+ image.composite_file @mongoose, :y => 15
29
+ image.composite_file @mongoose, :x => 100, :y => 30, :width => 250, :height => 100
30
+ image.write @output_dir + 'scaled.png'
31
+ end
32
+ end
33
+
34
+ it "alpha masks images" do
35
+ SmartImage.new(115, 95) do |image|
36
+ image.composite_file @mongoose, :width => 115,
37
+ :height => 95,
38
+ :preserve_aspect_ratio => false
39
+
40
+ image.alpha_mask_file @mask
41
+ image.write @output_dir + 'alpha_mask.png'
42
+ end
43
+ end
44
+ end
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,5 @@
1
+ # We depend on the ImageSize gem, at the very least
2
+ require 'rubygems'
3
+
4
+ $LOAD_PATH << File.dirname(__FILE__) + '/../lib'
5
+ require 'smart_image'
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: smartimage
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Tony Arcieri
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-03-26 00:00:00 -06:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: imagesize
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.1.1
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: rmagick
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 2.12.2
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: rspec
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.2.9
44
+ version:
45
+ description: " SmartImage provides a cross-platform solution for image compositing that works on both MRI and JRuby.\n If using RMagick feels like swatting a fly with a nucler missile, and ImageScience just doesn't get \n you there, SmartImage is hopefully at that sweet spot in the middle\n"
46
+ email: tony@medioh.com
47
+ executables: []
48
+
49
+ extensions: []
50
+
51
+ extra_rdoc_files:
52
+ - LICENSE
53
+ - README.textile
54
+ files:
55
+ - .document
56
+ - .gitignore
57
+ - LICENSE
58
+ - README.textile
59
+ - Rakefile
60
+ - VERSION
61
+ - lib/smart_image.rb
62
+ - lib/smart_image/base_canvas.rb
63
+ - lib/smart_image/java_canvas.rb
64
+ - lib/smart_image/ratio_calculator.rb
65
+ - lib/smart_image/rmagick_canvas.rb
66
+ - smartimage.gemspec
67
+ - spec/fixtures/mask.png
68
+ - spec/fixtures/mongoose.jpg
69
+ - spec/smart_image_spec.rb
70
+ - spec/spec.opts
71
+ - spec/spec_helper.rb
72
+ - spec/tmp/.gitignore
73
+ has_rdoc: true
74
+ homepage: http://github.com/tarcieri/smartimage
75
+ licenses: []
76
+
77
+ post_install_message:
78
+ rdoc_options:
79
+ - --charset=UTF-8
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: "0"
87
+ version:
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: "0"
93
+ version:
94
+ requirements: []
95
+
96
+ rubyforge_project:
97
+ rubygems_version: 1.3.5
98
+ signing_key:
99
+ specification_version: 3
100
+ summary: It's like a Swiss Army Knife for images, but one of those tiny ones you can keep on your keychain
101
+ test_files:
102
+ - spec/smart_image_spec.rb
103
+ - spec/spec_helper.rb