Class: SmartImage

Inherits:
Object
  • Object
show all
Defined in:
lib/smart_image.rb,
lib/smart_image/base_canvas.rb,
lib/smart_image/java_canvas.rb,
lib/smart_image/rmagick_canvas.rb,
lib/smart_image/ratio_calculator.rb

Overview

SmartImage: it’s like a Swiss Army Knife for images, but one of those tiny ones you can keep on your keychain.

Defined Under Namespace

Classes: BaseCanvas, DeadCanvas, FormatError, Info, JavaCanvas, NotImplementedError, RMagickCanvas, RatioCalculator

Constant Summary collapse

Canvas =

RMagick is our Canvas on everything besides JRuby. Hope it works for you!

RMagickCanvas

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(width, height) {|_self| ... } ⇒ SmartImage

Create a new SmartImage of the given width and height. Always takes a block… no exceptions! Returns a destroyed SmartImage object.

SmartImage.new(400, 300) do |compositor|
  compositor.image "foo/bar.jpg", :x => 10, :y => 10
  compositor.text  "Hello, world!", :x => 20, :y => 20
  compositor.write "baz/qux.jpg"
end

When used with a block, all images are automatically freed from memory

Yields:

  • (_self)

Yield Parameters:

  • _self (SmartImage)

    the object that the method was called on

Raises:

  • (ArgumentError)


112
113
114
115
116
117
118
119
120
121
# File 'lib/smart_image.rb', line 112

def initialize(width, height, &block)
  raise ArgumentError, "give me a block, pretty please" unless block_given?
  
  @width, @height = Integer(width), Integer(height)
  @canvas = SmartImage::Canvas.new @width, @height
  
  yield self
  @canvas.destroy
  @canvas = DeadCanvas.new
end

Class Method Details

.calculate_aspect_ratio(info, options) ⇒ Object

Solve aspect ratio constraints based on source image info and a given options hash. This is mostly an internal method but if you find it useful knock yourself out.



86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/smart_image.rb', line 86

def calculate_aspect_ratio(info, options)
  if options[:preserve_aspect_ratio]
    composited_size = SmartImage::RatioCalculator.new(
      :source_width  => info.width,
      :source_height => info.height,
      :dest_width  => Integer(options[:width]), 
      :dest_height => Integer(options[:height])
    ).size

    return composited_size.width, composited_size.height
  else
    return options[:width], options[:height]
  end
end

.file_info(path) ⇒ Object

Obtain information about a file Returns a SmartImage::Info object



32
33
34
# File 'lib/smart_image.rb', line 32

def file_info(path)
  info File.read(path)
end

.info(data) ⇒ Object

Obtain basic information about the given image data Returns a SmartImage::Info object

Raises:



23
24
25
26
27
28
# File 'lib/smart_image.rb', line 23

def info(data)
  img = ImageSize.new data
  raise FormatError, "invalid image" if img.get_type == "OTHER"

  Info.new(img.width, img.height, img.get_type.downcase.to_sym)
end

.thumbnail(data, options = {}) ⇒ Object

Generate a thumbnail from the given image data Options:

  • width: max width of the image, or explicit width if not preserving aspect ratio

  • height: ditto, except for height of course

  • preserve_aspect_ratio: if true, ensure image fits within the given width/height restraints.

  • format: file extension you’d ordinarily apply to an output file of the type you desire. Supported formats are :jpg, :png, and :gif (default :png)



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/smart_image.rb', line 46

def thumbnail(data, options = {})
  source_info = info data
  
  opts = {
    :width  => source_info.width,
    :height => source_info.height,
    :preserve_aspect_ratio => true,
    :format => :png
  }.merge(options)
  
  width, height = calculate_aspect_ratio source_info, opts
  
  # Set res so we can assign it within the SmartImage.new block
  res = nil
  
  SmartImage.new(width, height) do |image|
    image.composite data, :width  => width,
                          :height => height,
                          :preserve_aspect_ratio => false
                          
    res = image.encode opts[:format]
  end
  
  res
end

.thumbnail_file(input_path, output_path, options = {}) ⇒ Object

Generate a thumbnail file from a given input file Accepts the same options as SmartImage.thumbnail



74
75
76
77
78
79
80
81
# File 'lib/smart_image.rb', line 74

def thumbnail_file(input_path, output_path, options = {})
  opts = {
    :format => File.extname(output_path).sub(/^\./, '')
  }.merge(options)
  
  data = SmartImage.thumbnail File.read(input_path), opts
  File.open(output_path, 'w') { |file| file << data }
end

Instance Method Details

#alpha_mask(data, options = {}) ⇒ Object

Apply an alpha mask from the given image data. Doesn’t accept any options right now, sorry. It’s just another useless dangling options hash.



167
168
169
# File 'lib/smart_image.rb', line 167

def alpha_mask(data, options = {})
  @canvas.alpha_mask data
end

#alpha_mask_file(file, options = {}) ⇒ Object

Apply an alpha mask from the given file. Accepts the same options as the alpha_mask method.



173
174
175
# File 'lib/smart_image.rb', line 173

def alpha_mask_file(file, options = {})
  alpha_mask File.read(file), options
end

#composite(data, options = {}) ⇒ Object

Composite the given image data onto the SmartImage

Accepts the following options:

  • x: coordinate of the upper left corner of the image (default 0)

  • y: ditto, it’s the y coordinate

  • width: an alternate width

  • height: alternate height

  • preserve_aspect_ratio: should the aspect ratio be preserved? (default: true)



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/smart_image.rb', line 140

def composite(data, options = {})
  info = self.class.info data
  
  opts = {
    :x => 0,
    :y => 0,
    :width  => info.width,
    :height => info.height,
    :preserve_aspect_ratio => true
  }.merge(options)

  dest_width, dest_height = self.class.calculate_aspect_ratio info, opts

  @canvas.composite data, :width  => Integer(dest_width),
                          :height => Integer(dest_height),
                          :x      => opts[:x], 
                          :y      => opts[:y]
end

#composite_file(file, options = {}) ⇒ Object

Composite a given image file onto the SmartImage. Accepts the same options as the composite method



161
162
163
# File 'lib/smart_image.rb', line 161

def composite_file(file, options = {})
  composite File.read(file), options
end

#encode(format, options = {}) ⇒ Object

Encode the image with the given format (a file extension) and return it as a string. Doesn’t accept any options at present. The options hash is just there to annoy you and make you wish it had more options.

Raises:

  • (ArgumentError)


180
181
182
183
184
185
186
187
188
# File 'lib/smart_image.rb', line 180

def encode(format, options = {})
  # Sorry .jpeg lovers, I'm one of you too but the standard is jpg
  format = 'jpg' if format.to_s == 'jpeg'
  format = format.to_s
  
  raise ArgumentError, "invalid format: #{format}" unless %w(jpg png gif).include?(format)
  
  @canvas.encode format, options
end

#write(path, options = {}) ⇒ Object

Write the resulting image out to disk. Picks format based on filename. Takes the same options as encode



192
193
194
195
# File 'lib/smart_image.rb', line 192

def write(path, options = {})    
  format = File.extname(path).sub(/^\./, '')
  File.open(path, 'w') { |file| file << encode(format, options) }
end