Class: ImageProc
- Inherits:
-
Object
- Object
- ImageProc
- Defined in:
- lib/image_proc.rb
Overview
A simplistic interface to shell-based image processing. Pluggable, compact and WIN32-incompatible by design. Sort of like the Processors in attachment_fu but less. Less.
width, height = ImageProc.get_bounds("image.png")
destination_path = ImageProc.resize("image.png", "thumb.png", :width => 50. :height => 50)
The whole idea is: a backend does not have to support cropping (we don’t do it), it has only to be able to resize, and a backend should have 2 public methods. That’s the game.
Defined Under Namespace
Classes: DestinationLocked, Error, FormatUnsupported, InvalidOptions, MissingInput, MissingOutput, NoDestinationDir, NoOverwrites
Constant Summary collapse
- VERSION =
'2.1.0'
- HARMLESS =
[]
Class Method Summary collapse
-
.detect_engine ⇒ Object
Tries to detect the best engine available.
-
.engine ⇒ Object
Get the processor class currently assigned.
-
.engine=(kls) ⇒ Object
Assign a specific processor class.
-
.get_bounds(of) ⇒ Object
Qukckly get bounds of an image ImageProc.get_bounds(“/tmp/upload.tif”) #=> [100, 120].
-
.keep_quiet ⇒ Object
Run a block without warnings.
-
.method_missing(*args) ⇒ Object
:nodoc:.
Instance Method Summary collapse
-
#fit_sizes(bounds, opts) ⇒ Object
Will fit the passed array of [input_width, input_heitght] proportionally and return an array of [recommended_width, recommended_height] honoring the following parameters:.
-
#fit_sizes_with_crop(bounds, opts) ⇒ Object
Will fit the passed array of [input_width, input_heitght] to fill the whole rect and return an array of [recommended_width, recommended_height] honoring the following parameters:.
-
#resize(from_path, to_path, opts = {}) ⇒ Object
Resizes with specific options passed as a hash.
-
#resize_exact(from_path, to_path, to_width, to_height) ⇒ Object
Resize an image fitting the boundary exactly.
-
#resize_fit_both(from_path, to_path, to_width, to_height) ⇒ Object
(also: #resize_fit)
Resize an image fitting it into a rect.
-
#resize_fit_fill(from_path, to_path, width, height) ⇒ Object
Will resize the image so that it’s part always fills the rect of
width
andheight
It’s recommended to then simply use CSS overflow to crop off the edges which are not necessary. -
#resize_fit_height(from_path, to_path, height) ⇒ Object
Same as resize_fit_width.
-
#resize_fit_square(from_path, to_path, square_side) ⇒ Object
Resize an image fitting the biggest side of it to the side of a square.
-
#resize_fit_width(from_path, to_path, width) ⇒ Object
Resize an image fitting the biggest side of it to the side of a square.
-
#resize_with_geom_string(from_path, to_path, geom_str) ⇒ Object
:nodoc:.
Class Method Details
.detect_engine ⇒ Object
Tries to detect the best engine available
44 45 46 47 48 49 50 51 52 |
# File 'lib/image_proc.rb', line 44 def detect_engine if ImageProcConvert.available? ImageProcConvert elsif RUBY_PLATFORM =~ /darwin/i ImageProcSips else raise "This system has no image processing facitilites that we can use. Time to compile RMagick or install a decent OS." end end |
.engine ⇒ Object
Get the processor class currently assigned
41 |
# File 'lib/image_proc.rb', line 41 def engine; @@engine ||= detect_engine; @@engine; end |
.engine=(kls) ⇒ Object
Assign a specific processor class
38 |
# File 'lib/image_proc.rb', line 38 def engine=(kls); @@engine = kls; end |
.get_bounds(of) ⇒ Object
Qukckly get bounds of an image
ImageProc.get_bounds("/tmp/upload.tif") #=> [100, 120]
56 57 58 |
# File 'lib/image_proc.rb', line 56 def get_bounds(of) engine.new.get_bounds(File.(of)) end |
.keep_quiet ⇒ Object
Run a block without warnings
27 28 29 30 31 32 33 34 35 |
# File 'lib/image_proc.rb', line 27 def keep_quiet o = $VERBOSE begin $VERBOSE = nil yield ensure $VERBOSE = o end end |
.method_missing(*args) ⇒ Object
:nodoc:
60 61 62 |
# File 'lib/image_proc.rb', line 60 def method_missing(*args) #:nodoc: engine.new.send(*args) end |
Instance Method Details
#fit_sizes(bounds, opts) ⇒ Object
Will fit the passed array of [input_width, input_heitght] proportionally and return an array of
- recommended_width, recommended_height
-
honoring the following parameters:
:width - maximum width of the bounding rect :height - maximum height of the bounding rect
If you pass both the bounds will be fit into the rect having the :width and :height proportionally, downsizing the bounds if necessary. Useful for calculating needed size before resizing.
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/image_proc.rb', line 160 def fit_sizes(bounds, opts) disallow_nil_values_in(opts) integerize_values_of(opts) ratio = bounds[0].to_f / bounds[1].to_f floats = case (opts.keys & [:height, :width]) when [] raise "The options #{opts.inspect} do not contain proper bounds" when [:width] desired_w = opts[:width] [desired_w, desired_w / ratio] when [:height] desired_h = opts[:height] [desired_h * ratio, desired_h] else # both, use reduction smallest_side = [opts[:width], opts[:height]].sort.shift if bounds[0] > bounds[1] # horizontal fit_sizes bounds, :width => smallest_side else fit_sizes bounds, :height => smallest_side end end # Prevent zero results prevent_zeroes_in(floats) # Nudge output values to pixels so that we fit exactly floats[0] = opts[:width] if (opts[:width] && floats[0] > opts[:width]) floats[1] = opts[:height] if (opts[:height] && floats[1] > opts[:height]) floats end |
#fit_sizes_with_crop(bounds, opts) ⇒ Object
Will fit the passed array of [input_width, input_heitght] to fill the whole rect and return an array of
- recommended_width, recommended_height
-
honoring the following parameters:
:width - maximum width of the bounding rect :height - maximum height of the bounding rect
In contrast to fit_sizes it requires BOTH.
It’s recommended to clip the image which will be created with these bounds using CSS, as not all resizers support cropping - and besides it’s just too many vars.
203 204 205 206 207 208 |
# File 'lib/image_proc.rb', line 203 def fit_sizes_with_crop(bounds, opts) force_keys!(opts, :width, :height) scale = [opts[:width].to_f / bounds[0], opts[:height].to_f / bounds[1]].sort.pop result = [bounds[0] * scale, bounds[1] * scale] result.map{|e| e.round} end |
#resize(from_path, to_path, opts = {}) ⇒ Object
Resizes with specific options passed as a hash. It returns the destination path to the resized image. If you need to know the resulting size of the image just call a ImageProc.get_bounds on the result path
ImageProc.resize "/tmp/foo.jpg", "bla.jpg", :width => 120, :height => 30
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/image_proc.rb', line 77 def resize(from_path, to_path, opts = {}) if opts.is_a?(String) STDERR.puts "String argument to resize() is really deprecated" resize_with_geom_string(from_path, to_path, opts) end remove_nil_values!(opts) raise InvalidOptions, "The only allowed options are :width, :height and :fill" if (opts.keys - [:width, :height, :fill]).any? if opts[:width] && opts[:height] && opts[:fill] resize_fit_fill(from_path, to_path, opts[:width], opts[:height]) elsif opts[:width] && opts[:height] resize_fit_both(from_path, to_path, opts[:width], opts[:height]) elsif opts[:width] resize_fit_width(from_path, to_path, opts[:width]) elsif opts[:height] resize_fit_height(from_path, to_path, opts[:height]) else raise InvalidOptions, "Pass width, height or both" end raise MissingOutput unless File.exist?(to_path) return to_path end |
#resize_exact(from_path, to_path, to_width, to_height) ⇒ Object
Resize an image fitting the boundary exactly. Will stretch and squash.
109 110 111 112 113 114 |
# File 'lib/image_proc.rb', line 109 def resize_exact(from_path, to_path, to_width, to_height) validate_input_output_files(from_path, to_path) @target_w, @target_h = to_width, to_height resetting_state_afterwards { process_exact } to_path end |
#resize_fit_both(from_path, to_path, to_width, to_height) ⇒ Object Also known as: resize_fit
Resize an image fitting it into a rect.
117 118 119 120 121 122 |
# File 'lib/image_proc.rb', line 117 def resize_fit_both(from_path, to_path, to_width, to_height) validate_input_output_files(from_path, to_path) @target_w, @target_h = fit_sizes(get_bounds(from_path), :width => to_width, :height => to_height) resetting_state_afterwards { process_exact } to_path end |
#resize_fit_fill(from_path, to_path, width, height) ⇒ Object
Will resize the image so that it’s part always fills the rect of width
and height
It’s recommended to then simply use CSS overflow to crop off the edges which are not necessary. If you want more involved processing calculate the geometry directly.
145 146 147 148 149 150 |
# File 'lib/image_proc.rb', line 145 def resize_fit_fill(from_path, to_path, width, height) validate_input_output_files(from_path, to_path) @target_w, @target_h = fit_sizes_with_crop get_bounds(from_path), :height => height, :width => width resetting_state_afterwards { process_exact } to_path end |
#resize_fit_height(from_path, to_path, height) ⇒ Object
Same as resize_fit_width
135 136 137 138 139 140 |
# File 'lib/image_proc.rb', line 135 def resize_fit_height(from_path, to_path, height) validate_input_output_files(from_path, to_path) @target_w, @target_h = fit_sizes(get_bounds(from_path), :height => height) resetting_state_afterwards { process_exact } to_path end |
#resize_fit_square(from_path, to_path, square_side) ⇒ Object
Resize an image fitting the biggest side of it to the side of a square. A must for thumbs.
104 105 106 |
# File 'lib/image_proc.rb', line 104 def resize_fit_square(from_path, to_path, square_side) resize_fit_both(from_path, to_path, square_side, square_side) end |
#resize_fit_width(from_path, to_path, width) ⇒ Object
Resize an image fitting the biggest side of it to the side of a square. A must for thumbs.
126 127 128 129 130 131 132 |
# File 'lib/image_proc.rb', line 126 def resize_fit_width(from_path, to_path, width) validate_input_output_files(from_path, to_path) @target_w, @target_h = fit_sizes get_bounds(from_path), :width => width resetting_state_afterwards { process_exact } to_path end |
#resize_with_geom_string(from_path, to_path, geom_str) ⇒ Object
:nodoc:
65 66 67 68 69 70 |
# File 'lib/image_proc.rb', line 65 def resize_with_geom_string(from_path, to_path, geom_str) #:nodoc: w, h = geom_str.scan(/^(\d+)x(\d+)$/).to_a.flatten.map{|e| e.to_i } resize(from_path, to_path, :width => w, :height => h) result_w, result_h = get_bounds(to_path) [to_path, result_w, result_h] end |