Class: MiniMagick::Image

Inherits:
Object
  • Object
show all
Defined in:
lib/mini_magick.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(input_path, tempfile = nil) ⇒ Image

Instance Methods




50
51
52
53
54
55
56
# File 'lib/mini_magick.rb', line 50

def initialize(input_path, tempfile=nil)
  @path = input_path
  @tempfile = tempfile # ensures that the tempfile will stick around until this image is garbage collected.

  # Ensure that the file is an image
  run_command("identify", @path)
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 morgrify program Look here to find all the commands (www.imagemagick.org/script/mogrify.php)



139
140
141
142
143
# File 'lib/mini_magick.rb', line 139

def method_missing(symbol, *args)
  args.push(@path) # push the path onto the end
  run_command("mogrify", "-#{symbol}", *args)
  self
end

Instance Attribute Details

#outputObject (readonly)

Returns the value of attribute output.



22
23
24
# File 'lib/mini_magick.rb', line 22

def output
  @output
end

#pathObject (readonly)

Returns the value of attribute path.



20
21
22
# File 'lib/mini_magick.rb', line 20

def path
  @path
end

#tempfileObject (readonly)

Returns the value of attribute tempfile.



21
22
23
# File 'lib/mini_magick.rb', line 21

def tempfile
  @tempfile
end

Class Method Details

.from_blob(blob, ext = nil) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
# File 'lib/mini_magick.rb', line 27

def from_blob(blob, ext = nil)
  begin
    tempfile = Tempfile.new(['mini_magick', ext.to_s])
    tempfile.binmode
    tempfile.write(blob)
  ensure
    tempfile.close if tempfile
  end

  return self.new(tempfile.path, tempfile)
end

.open(image_path) ⇒ Object Also known as: from_file

Use this if you don’t want to overwrite the image file



40
41
42
43
44
# File 'lib/mini_magick.rb', line 40

def open(image_path)
  File.open(image_path, "rb") do |f|
    self.from_blob(f.read, File.extname(image_path))
  end
end

Instance Method Details

#<<(*args) ⇒ Object

Sends raw commands to imagemagick’s mogrify command. The image path is automatically appended to the command



88
89
90
# File 'lib/mini_magick.rb', line 88

def <<(*args)
  run_command("mogrify", *args << @path)
end

#[](value) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/mini_magick.rb', line 59

def [](value)
  # Why do I go to the trouble of putting in newlines? Because otherwise animated gifs screw everything up
  case value.to_s
  when "format"
    run_command("identify", "-format", format_option("%m"), @path).split("\n")[0]
  when "height"
    run_command("identify", "-format", format_option("%h"), @path).split("\n")[0].to_i
  when "width"
    run_command("identify", "-format", format_option("%w"), @path).split("\n")[0].to_i
  when "dimensions"
    run_command("identify", "-format", format_option("%w %h"), @path).split("\n")[0].split.map{|v|v.to_i}
  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).chop
    if result.include?(",")
      read_character_data(result)
    else
      result
    end
  else
    run_command('identify', '-format', "\"#{value}\"", @path).split("\n")[0]
  end
end

#collapse!Object

Collapse images with sequences to the first frame (ie. animated gifs) and preserve quality



118
119
120
# File 'lib/mini_magick.rb', line 118

def collapse!
  run_command("mogrify", "-quality", "100", "#{path}[0]")
end

#combine_options(&block) ⇒ Object

You can use multiple commands together using this method



146
147
148
149
150
# File 'lib/mini_magick.rb', line 146

def combine_options(&block)
  c = CommandBuilder.new
  block.call c
  run_command("mogrify", *c.args << @path)
end

#destroy!Object



198
199
200
201
202
# File 'lib/mini_magick.rb', line 198

def destroy!
  return if tempfile.nil?
  File.unlink(tempfile.path)
  @tempfile = nil
end

#format(format, page = 0) ⇒ Object

This is a ‘special’ command because it needs to change @path to reflect the new extension 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.



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/mini_magick.rb', line 96

def format(format, page=0)
  run_command("mogrify", "-format", format, @path)

  old_path = @path.dup
  @path.sub!(/(\.\w*)?$/, ".#{format}")
  File.delete(old_path) unless old_path == @path

  unless File.exists?(@path)
    begin
      FileUtils.copy_file(@path.sub(".#{format}", "-#{page}.#{format}"), @path)
    rescue => ex
      raise MiniMagickError, "Unable to format to #{format}; #{ex}" unless File.exist?(@path)
    end
  end
ensure
  Dir[@path.sub(/(\.\w+)?$/, "-[0-9]*.#{format}")].each do |fname|
    File.unlink(fname)
  end
end

#format_option(format) ⇒ Object

Outputs a carriage-return delimited format string for Unix and Windows



158
159
160
# File 'lib/mini_magick.rb', line 158

def format_option(format)
  windows? ? "#{format}\\n" : "#{format}\\\\n"
end

#run_command(command, *args) ⇒ Object



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
192
193
194
195
196
# File 'lib/mini_magick.rb', line 162

def run_command(command, *args)
  args.collect! do |arg|        
    # args can contain characters like '>' so we must escape them, but don't quote switches
    if arg !~ /^[\+\-]/
      "\"#{arg}\""
    else
      arg.to_s
    end
  end

  command = "#{MiniMagick.processor} #{command} #{args.join(' ')}".strip

  if ::MiniMagick.use_subexec
    sub = Subexec.run(command, :timeout => MiniMagick.timeout)
    exit_status = sub.exitstatus
    output = sub.output
  else
    output = `#{command} 2>&1`
    exit_status = $?.exitstatus
  end
  
  if exit_status != 0
    # Clean up after ourselves in case of an error
    destroy!
    
    # Raise the appropriate error
    if output =~ /no decode delegate/i || output =~ /did not return an image/i
      raise Invalid, output
    else
      raise Error, "Command (#{command.inspect}) failed: #{{:status_code => exit_status, :output => output}.inspect}"
    end
  else
    output
  end
end

#to_blobObject

Give you raw data back



129
130
131
132
133
134
135
# File 'lib/mini_magick.rb', line 129

def to_blob
  f = File.new @path
  f.binmode
  f.read
ensure
  f.close if f
end

#windows?Boolean

Check to see if we are running on win32 – we need to escape things differently

Returns:

  • (Boolean)


153
154
155
# File 'lib/mini_magick.rb', line 153

def windows?
  !(RUBY_PLATFORM =~ /win32/).nil?
end

#write(output_path) ⇒ Object

Writes the temporary image that we are using for processing to the output path



123
124
125
126
# File 'lib/mini_magick.rb', line 123

def write(output_path)
  FileUtils.copy_file @path, output_path
  run_command "identify", output_path # Verify that we have a good image
end