class Giftrim::Image

Attributes

path[RW]

@return [String] The location of the current working file

Public Class Methods

create(ext = nil, validate = true, &block) click to toggle source

Modified from MiniMagick, see License_MiniMagick 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!

@param ext [String] Specify the extension you want to read it as @param validate [Boolean] If false, skips validation of the created image. Defaults to true. @yield [IOStream] You can write bits to this object to create the new Image @return [Image] The created image

# File lib/giftrim.rb, line 92
def create(ext = nil, validate = true, &block)
  begin
    tempfile = Tempfile.new(['giftrim_', ext.to_s.downcase])
    tempfile.binmode
    block.call(tempfile)
    tempfile.close

    image = self.new(tempfile.path, tempfile)

    if validate and !image.valid?
      raise Giftrim::Invalid
    end
    return image
  ensure
    tempfile.close if tempfile
  end
end
new(input_path, tempfile = nil) click to toggle source

Modified from MiniMagick, see License_MiniMagick 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!

@param input_path [String] The location of an image file @todo Allow this to accept a block that can pass off to Image#combine_options

# File lib/giftrim.rb, line 121
def initialize(input_path, tempfile = nil)
  @path = input_path
  @tempfile = tempfile # ensures that the tempfile will stick around until this image is garbage collected.
end
open(file_or_url, ext = nil) click to toggle source

Modified from MiniMagick, see License_MiniMagick 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.

@param file_or_url [String] Either a local file path or a URL that open-uri can read @param ext [String] Specify the extension you want to read it as @return [Image] The loaded image

# File lib/giftrim.rb, line 68
def open(file_or_url, ext = nil)
  file_or_url = file_or_url.to_s # Force it to be a String... hell or highwater
  if file_or_url.include?("://")
    require 'open-uri'
    ext ||= File.extname(URI.parse(file_or_url).path)
    self.read(Kernel::open(file_or_url), ext)
  else
    ext ||= File.extname(file_or_url)
    File.open(file_or_url, "rb") do |f|
      self.read(f, ext)
    end
  end
end
read(stream, ext = nil) click to toggle source

Modified from MiniMagick, see License_MiniMagick 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.

@param stream [IOStream, String] Some kind of stream object that needs to be read or is a binary String blob! @param ext [String] A manual extension to use for reading the file. Not required, but if you are having issues, give this a try. @return [Image]

# File lib/giftrim.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

Public Instance Methods

number_of_frames() click to toggle source
# File lib/giftrim.rb, line 163
def number_of_frames
  command = "#{Giftrim.processor} --info #{@path}"
  output = run_command command
  if output
    first_line = output.lines.first
    number_of_frames = first_line.scan(/\d+[ \t]*images/).first.to_i
  end
  number_of_frames
end
run_command(command) click to toggle source
# File lib/giftrim.rb, line 132
def run_command command
  sub = Subexec.run(command, :timeout => Giftrim.timeout)
  if sub.exitstatus == 0
    sub.output
  else
    raise Error, "Command (#{command.inspect.gsub("\\", "")}) failed: #{{:status_code => sub.exitstatus, :output => sub.output}.inspect}"
  end
end
trim() click to toggle source
# File lib/giftrim.rb, line 173
def trim
  @outfile = Tempfile.new('giftrim_')
  @outfile.binmode
  @outfile.close

  frames = Giftrim::frame_number_wanted self.number_of_frames, 10
  frames_formatted = frames.map{|frame| "\"##{frame}\""}.join " "
  command = "#{Giftrim.processor} --unoptimize -O2 --no-comments --no-names --delay 20 --same-loopcount --no-warnings --resize-fit '300x300' #{@path} #{frames_formatted} > #{@outfile.path}"
  trim_run_command command
end
trim_with_target_frame_number(frame_number) click to toggle source
# File lib/giftrim.rb, line 184
def trim_with_target_frame_number frame_number
  @outfile = Tempfile.new('giftrim_')
  @outfile.binmode
  @outfile.close

  frames = Giftrim::frame_number_wanted self.number_of_frames, 10
  frames_formatted = frames.map{|frame| "\"##{frame}\""}.join " "
  command = "#{Giftrim.processor} --unoptimize -O2 --no-comments --no-names --delay 20 --same-loopcount --no-warnings #{@path} #{frames_formatted} > #{@outfile.path}"
  trim_run_command command
end
valid?() click to toggle source

@return [Boolean]

# File lib/giftrim.rb, line 127
def valid?
  # TODO
  true
end
write(output_to) click to toggle source

Modified from MiniMagick, see License_MiniMagick 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

@param output_to [IOStream, String] Some kind of stream object that needs to be read or a file path as a String @return [IOStream, Boolean] If you pass in a file location [String] then you get a success boolean. If its a stream, you get it back. Writes the temporary image that we are using for processing to the output path

# File lib/giftrim.rb, line 148
def write(output_to)
  if output_to.kind_of?(String) || !output_to.respond_to?(:write)
    FileUtils.copy_file @path, output_to
    run_command "identify #{output_to}" # Verify that we have a good image
  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

Private Instance Methods

trim_run_command(command) click to toggle source
# File lib/giftrim.rb, line 196
def trim_run_command command

  output = run_command command
  if output
    @tempfile = @outfile
    @path = @tempfile.path
    @outfile = nil
  end
  output
end