Class: MiniMagick::Image
- Inherits:
-
Object
- Object
- MiniMagick::Image
- Defined in:
- lib/mini_magick/image.rb
Instance Attribute Summary collapse
Class Method Summary collapse
-
.create(ext = nil, validate = MiniMagick.validate_on_create) {|IOStream| ... } ⇒ Image
Used to create a new Image object data-copy.
-
.from_blob(blob, ext = nil) ⇒ Object
deprecated
Deprecated.
Please use Image.read instead!
-
.from_file(file, ext = nil) ⇒ Object
deprecated
Deprecated.
Please use MiniMagick::Image.open(file_or_url) now
-
.import_pixels(blob, columns, rows, depth, map, format = 'png') ⇒ Image
Creates an image object from a binary string blob which contains raw pixel data (i.e. no header data).
-
.open(file_or_url, ext = nil) ⇒ Image
Opens a specific image file either on the local file system or at a URI.
-
.read(stream, ext = nil) ⇒ Image
This is the primary loading method used by all of the other class methods.
Instance Method Summary collapse
-
#<<(*args) ⇒ String
Sends raw commands to imagemagick’s ‘mogrify` command.
-
#[](value) ⇒ String, ...
A rather low-level way to interact with the “identify” command.
-
#collapse! ⇒ Object
Collapse images with sequences to the first frame (i.e. animated gifs) and preserve quality.
-
#combine_options {|command| ... } ⇒ Object
You can use multiple commands together using this method.
- #composite(other_image, output_extension = 'jpg', mask = nil, &block) ⇒ Object
- #destroy! ⇒ Object
-
#format(format, page = 0) {|c| ... } ⇒ nil
This is used to change the format of the image.
- #info(key) ⇒ Object
-
#initialize(input_path, tempfile = nil) ⇒ Image
constructor
Create a new MiniMagick::Image object.
-
#method_missing(symbol, *args) ⇒ Object
If an unknown method is called then it is sent through the mogrify program.
- #mime_type ⇒ Object
- #reset_queue ⇒ Object
- #run(command_builder) ⇒ Object
- #run_command(command, *args) ⇒ Object
- #run_queue ⇒ Object
-
#to_blob ⇒ String
Gives you raw image data back.
-
#valid? ⇒ Boolean
Checks to make sure that MiniMagick can read the file and understand it.
-
#write(output_to) ⇒ IOStream, Boolean
Writes the temporary file out to either a file location (by passing in a String) or by passing in a Stream that you can #write(chunk) to repeatedly.
Constructor Details
#initialize(input_path, tempfile = nil) ⇒ Image
Allow this to accept a block that can pass off to Image#combine_options
Create a new MiniMagick::Image object
DANGER: The file location passed in here is the *working copy*. That is, it gets modified. you can either copy it yourself or use the MiniMagick::Image.open(path) method which creates a temporary file for you and protects your original!
166 167 168 169 170 171 |
# File 'lib/mini_magick/image.rb', line 166 def initialize(input_path, tempfile = nil) @path = input_path @tempfile = tempfile @info = {} reset_queue end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(symbol, *args) ⇒ Object
If an unknown method is called then it is sent through the mogrify program.
372 373 374 375 |
# File 'lib/mini_magick/image.rb', line 372 def method_missing(symbol, *args) @queue.send(symbol, *args) @command_queued = true end |
Instance Attribute Details
#path ⇒ Object
11 12 13 14 |
# File 'lib/mini_magick/image.rb', line 11 def path run_queue if @command_queued MiniMagick::Utilities.path(@path) end |
Class Method Details
.create(ext = nil, validate = MiniMagick.validate_on_create) {|IOStream| ... } ⇒ Image
Used to create a new Image object data-copy. Not used to “paint” or that kind of thing.
Takes an extension in a block and can be used to build a new Image object. Used by both #open and #read to create a new object! Ensures we have a good tempfile!
141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/mini_magick/image.rb', line 141 def create(ext = nil, validate = MiniMagick.validate_on_create, &block) tempfile = Tempfile.new(['mini_magick', ext.to_s.downcase]) tempfile.binmode block.call(tempfile) tempfile.close image = new(tempfile.path, tempfile) fail MiniMagick::Invalid if validate && !image.valid? return image ensure tempfile.close if tempfile end |
.from_blob(blob, ext = nil) ⇒ Object
Please use Image.read instead!
57 58 59 60 |
# File 'lib/mini_magick/image.rb', line 57 def from_blob(blob, ext = nil) warn 'Warning: MiniMagick::Image.from_blob method is deprecated. Instead, please use Image.read' create(ext) { |f| f.write(blob) } end |
.from_file(file, ext = nil) ⇒ Object
Please use MiniMagick::Image.open(file_or_url) now
123 124 125 126 |
# File 'lib/mini_magick/image.rb', line 123 def from_file(file, ext = nil) warn 'Warning: MiniMagick::Image.from_file is now deprecated. Please use Image.open' open(file, ext) end |
.import_pixels(blob, columns, rows, depth, map, format = 'png') ⇒ Image
Creates an image object from a binary string blob which contains raw pixel data (i.e. no header data).
Defaults to ‘png’.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/mini_magick/image.rb', line 76 def import_pixels(blob, columns, rows, depth, map, format = 'png') # Create an image object with the raw pixel data string: image = create('.dat', false) { |f| f.write(blob) } # Use ImageMagick to convert the raw data file to an image file of the # desired format: converted_image_path = image.path[0..-4] + format arguments = ['-size', "#{columns}x#{rows}", '-depth', "#{depth}", "#{map}:#{image.path}", "#{converted_image_path}"] # Example: convert -size 256x256 -depth 16 gray:blob.dat blob.png cmd = CommandBuilder.new('convert', *arguments) image.run(cmd) # Update the image instance with the path of the properly formatted # image, and return: image.path = converted_image_path image end |
.open(file_or_url, ext = nil) ⇒ Image
Opens a specific image file either on the local file system or at a URI.
Use this if you don’t want to overwrite the image file.
Extension is either guessed from the path or you can specify it as a second parameter.
If you pass in what looks like a URL, we require ‘open-uri’ before opening it.
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/mini_magick/image.rb', line 106 def open(file_or_url, ext = nil) file_or_url = file_or_url.to_s # Force String... Hell or high water if file_or_url.include?('://') require 'open-uri' ext ||= File.extname(URI.parse(file_or_url).path) Kernel.open(file_or_url) do |f| read(f, ext) end else ext ||= File.extname(file_or_url) File.open(file_or_url, 'rb') do |f| read(f, ext) end end end |
.read(stream, ext = nil) ⇒ Image
This is the primary loading method used by all of the other class methods.
Use this to pass in a stream object. Must respond to Object#read(size) or be a binary string object (BLOBBBB)
As a change from the old API, please try and use IOStream objects. They are much, much better and more efficient!
Probably easier to use the #open method if you want to open a file or a URL.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/mini_magick/image.rb', line 36 def read(stream, ext = nil) if stream.is_a?(String) stream = StringIO.new(stream) elsif stream.is_a?(StringIO) # Do nothing, we want a StringIO-object elsif stream.respond_to? :path if File.respond_to?(:binread) stream = StringIO.new File.binread(stream.path.to_s) else stream = StringIO.new File.open(stream.path.to_s, 'rb') { |f| f.read } end end create(ext) do |f| while chunk = stream.read(8192) f.write(chunk) end end end |
Instance Method Details
#<<(*args) ⇒ String
Sends raw commands to imagemagick’s ‘mogrify` command. The image path is automatically appended to the command.
Remember, we are always acting on this instance of the Image when messing with this.
272 273 274 |
# File 'lib/mini_magick/image.rb', line 272 def <<(*args) run_command('mogrify', *args << path) end |
#[](value) ⇒ String, ...
A rather low-level way to interact with the “identify” command. No nice API here, just the crazy stuff you find in ImageMagick. See the examples listed!
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/mini_magick/image.rb', line 224 def [](value) retrieved = info(value) return retrieved unless retrieved.nil? # Why do I go to the trouble of putting in newlines? Because otherwise # animated gifs screw everything up retrieved = case value.to_s when 'colorspace' run_command('identify', '-format', '%r\n', path).split("\n")[0].strip when 'format' run_command('identify', '-format', '%m\n', path).split("\n")[0] when 'dimensions', 'width', 'height' width_height = run_command( 'identify', '-format', MiniMagick::Utilities.windows? ? '"%w %h\n"' : '%w %h\n', path ).split("\n")[0].split.map { |v| v.to_i } @info[:width] = width_height[0] @info[:height] = width_height[1] @info[:dimensions] = width_height @info[value.to_sym] when 'size' File.size(path) # Do this because calling identify -format "%b" on an animated gif fails! when 'original_at' # Get the EXIF original capture as a Time object Time.local(*self['EXIF:DateTimeOriginal'].split(/:|\s+/)) rescue nil when /^EXIF\:/i result = run_command('identify', '-format', "%[#{value}]", path).chomp if result.include?(',') read_character_data(result) else result end else run_command('identify', '-format', value, path).split("\n")[0] end @info[value] = retrieved unless retrieved.nil? @info[value] end |
#collapse! ⇒ Object
Collapse images with sequences to the first frame (i.e. animated gifs) and preserve quality
318 319 320 |
# File 'lib/mini_magick/image.rb', line 318 def collapse! run_command('mogrify', '-quality', '100', "#{path}[0]") end |
#combine_options {|command| ... } ⇒ Object
You can use multiple commands together using this method. Very easy to use!
388 389 390 391 392 393 |
# File 'lib/mini_magick/image.rb', line 388 def if block_given? yield @queue @command_queued = true end end |
#composite(other_image, output_extension = 'jpg', mask = nil, &block) ⇒ Object
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 |
# File 'lib/mini_magick/image.rb', line 395 def composite(other_image, output_extension = 'jpg', mask = nil, &block) run_queue if @command_queued begin second_tempfile = Tempfile.new(output_extension) second_tempfile.binmode ensure second_tempfile.close end command = CommandBuilder.new('composite') block.call(command) if block command.push(other_image.path) command.push(path) command.push(mask.path) unless mask.nil? command.push(second_tempfile.path) run(command) Image.new(second_tempfile.path, second_tempfile) end |
#destroy! ⇒ Object
448 449 450 451 452 |
# File 'lib/mini_magick/image.rb', line 448 def destroy! return if @tempfile.nil? File.unlink(@path) if File.exist?(@path) @tempfile = nil end |
#format(format, page = 0) {|c| ... } ⇒ nil
This is used to change the format of the image. That is, from “tiff to jpg” or something like that. Once you run it, the instance is pointing to a new file with a new extension!
DANGER: This renames the file that the instance is pointing to. So, if you manually opened the file with Image.new(file_path)… Then that file is DELETED! If you used Image.open(file) then you are OK. The original file will still be there. But, any changes to it might not be…
Formatting an animation into a non-animated type will result in ImageMagick creating multiple pages (starting with 0). You can choose which page you want to manipulate. We default to the first page.
If you would like to convert between animated formats, pass nil as your page and ImageMagick will copy all of the pages.
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
# File 'lib/mini_magick/image.rb', line 297 def format(format, page = 0) run_queue if @command_queued c = CommandBuilder.new('mogrify', '-format', format) yield c if block_given? c << (page ? "#{path}[#{page}]" : path) run(c) old_path = path self.path = path.sub(/(\.\w*)?$/, (page ? ".#{format}" : "-0.#{format}")) File.delete(old_path) if old_path != path unless File.exist?(path) fail MiniMagick::Error, "Unable to format to #{format}" end end |
#info(key) ⇒ Object
200 201 202 203 204 |
# File 'lib/mini_magick/image.rb', line 200 def info(key) run_queue if @command_queued @info[key] end |
#mime_type ⇒ Object
363 364 365 366 |
# File 'lib/mini_magick/image.rb', line 363 def mime_type format = self[:format] 'image/' + format.to_s.downcase end |
#reset_queue ⇒ Object
173 174 175 176 177 |
# File 'lib/mini_magick/image.rb', line 173 def reset_queue @command_queued = false @queue = MiniMagick::CommandBuilder.new('mogrify') @info.clear end |
#run(command_builder) ⇒ Object
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 |
# File 'lib/mini_magick/image.rb', line 426 def run(command_builder) command = command_builder.command sub = Subexec.run(command, :timeout => MiniMagick.timeout) if sub.exitstatus != 0 # Clean up after ourselves in case of an error destroy! # Raise the appropriate error if sub.output =~ /no decode delegate/i || sub.output =~ /did not return an image/i fail Invalid, sub.output else # TODO: should we do something different if the command times out ...? # its definitely better for logging.. Otherwise we don't really know fail Error, "Command (#{command.inspect.gsub("\\", "")}) failed: #{{ :status_code => sub.exitstatus, :output => sub.output }.inspect}" end else sub.output end end |
#run_command(command, *args) ⇒ Object
415 416 417 418 419 420 421 422 423 424 |
# File 'lib/mini_magick/image.rb', line 415 def run_command(command, *args) run_queue if @command_queued if command == 'identify' args.unshift '-ping' # -ping "efficiently determine image characteristics." args.unshift '-quiet' if MiniMagick.mogrify? && !MiniMagick.debug # graphicsmagick has no -quiet option. end run(CommandBuilder.new(command, *args)) end |
#run_queue ⇒ Object
179 180 181 182 183 184 |
# File 'lib/mini_magick/image.rb', line 179 def run_queue return nil unless @command_queued @queue << MiniMagick::Utilities.path(@path) run(@queue) reset_queue end |
#to_blob ⇒ String
Gives you raw image data back
353 354 355 356 357 358 359 360 361 |
# File 'lib/mini_magick/image.rb', line 353 def to_blob run_queue if @command_queued f = File.new path f.binmode f.read ensure f.close if f end |
#valid? ⇒ Boolean
Checks to make sure that MiniMagick can read the file and understand it.
This uses the ‘identify’ command line utility to check the file. If you are having issues with this, then please work directly with the ‘identify’ command and see if you can figure out what the issue is.
193 194 195 196 197 198 |
# File 'lib/mini_magick/image.rb', line 193 def valid? run_command('identify', path) true rescue MiniMagick::Invalid false end |
#write(output_to) ⇒ IOStream, Boolean
Writes the temporary file out to either a file location (by passing in a String) or by passing in a Stream that you can #write(chunk) to repeatedly
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 |
# File 'lib/mini_magick/image.rb', line 330 def write(output_to) run_queue if @command_queued if output_to.kind_of?(String) || output_to.kind_of?(Pathname) || !output_to.respond_to?(:write) FileUtils.copy_file path, output_to if MiniMagick.validate_on_write run_command( 'identify', MiniMagick::Utilities.path(output_to.to_s) ) # Verify that we have a good image end else # stream File.open(path, 'rb') do |f| f.binmode while chunk = f.read(8192) output_to.write(chunk) end end output_to end end |