module Levdon

require 'filemagic' # gem install ruby-filemagic / brew install libmagick

Constants

API_URL
API_VERSION
APPLICATION_ID
ENABLE_SSL
ONTOLOGY_LIST
ONTOLOGY_REV_LIST
VERSION
VUUID

Public Class Methods

find_image(path,options={:no_check => false},&block) click to toggle source
# File lib/levdon.rb, line 338
def self.find_image(path,options={:no_check => false},&block)
  unless File.exist?(path)
    puts "Error"
    puts " File does not exist => " + path
    return
  end
  proc = lambda() {|e|
    unless File.directory?(e)
      begin
        if(options and options[:no_check] == true)
          if %w(.JPG .JPEG .GIF .PNG).member?(File.extname(e).upcase)
            obj = {}
            obj[:source_path] = e
            obj[:source_filename] = File.basename(e)
            return obj
          end
        else
          if %w(.JPG .JPEG .GIF .PNG).member?(File.extname(e).upcase)
            img = Magick::Image.from_blob( File.read(e) ).shift
            if %w(JPEG GIF PNG).member?(img.format.to_s)
              obj = {}
              obj[:source_path] = e
              obj[:source_filename] = File.basename(e)
              obj[:image] = img;
              return obj
            end
          end
        end
      rescue => e
        puts "Warning: caught a something error."
        puts e.class
        puts e.message
        puts e.backtrace
        # nothing to do
      end
    end
    return nil
  }
  unless File.directory?(path)
    obj = proc.call(path)
    block.call(obj) if(obj)
  else
    Dir.glob(path + "/" + "**/*").each{|e|
      obj = proc.call(e)
      block.call(obj) if(obj)
    }
  end
end
high_quality_resize(stream) click to toggle source
# File lib/levdon.rb, line 387
def self.high_quality_resize(stream)
  img = Magick::Image.from_blob(stream).first
  width = img.columns
  height = img.rows
  if(width > 512 and height > 512)
    img = img.resize_to_fit(512, 512)
  end
  img.to_blob {
    self.quality = 90
    self.format = "jpeg"
  }
end
identify_image(path,&block) click to toggle source
# File lib/levdon.rb, line 269
def self.identify_image(path,&block)
  proc = lambda() {|e|      
    unless File.directory?(e)
      begin
        fname = File.basename(e)
        # TODO
        if(fname.index("@STANDARDIZED@_") == 0 or fname.index("@Q@_") == 0)
          return nil
        end
        
        fsize = File.binread(e).size
        if(fsize > 1024*1024*5)
          obj = {}
          obj[:source_path] = e
          obj[:source_filename] = File.basename(e)
          obj[:error] = "Too big file :" + fsize.to_s
          return obj
        end
        if(fsize < 1024*10)
          obj = {}
          obj[:source_path] = e
          obj[:source_filename] = File.basename(e)
          obj[:error] = "Too small file :" + fsize.to_s
          return obj
        end
        
        time = Time.new
        img = Magick::Image.from_blob( File.read(e) ).shift
        #puts (Time.new - time).to_s + " : " + fsize.to_s + " : "+e
        if %w(JPEG GIF PNG).member?(img.format)
          obj = {}
          obj[:source_path] = e
          obj[:source_filename] = File.basename(e)
          obj[:image] = img;
          obj[:time] = Time.new - time
          obj[:size] = fsize
          return obj
        else
          obj = {}
          obj[:source_path] = e
          obj[:source_filename] = File.basename(e)
          obj[:image] = img;
          obj[:error] = "Unknown file"
          return obj
        end        
          
      rescue => err
        puts "Warning: cought a something error."
        obj = {}
        obj[:source_path] = e
        obj[:source_filename] = File.basename(e)
        obj[:image] = img;
        obj[:error] = err
        return obj
      end
    end
    return nil
  }
  unless File.directory?((path))
    obj = proc.call(path)
    block.call(obj) if(obj)
  else
    Dir.glob(path + "/" + "**/*").each{|e|
      obj = proc.call(e)
      block.call(obj) if(obj)
    }
  end
end
low_quality_resize(stream) click to toggle source
# File lib/levdon.rb, line 400
def self.low_quality_resize(stream)
  img = Magick::Image.from_blob(stream).first
  img = img.resize(224,224)
  img.to_blob {
    self.quality = 20
    self.format = "jpeg"
  }
end
new() click to toggle source
# File lib/levdon.rb, line 874
def self.new
  LevdonImpl.new
end
predict(access_token,target) click to toggle source
# File lib/levdon.rb, line 878
def self.predict(access_token,target)
  api = LevdonImpl.new
  state = api.start(access_token)
  if(state[:error])
    raise state[:error]
  else
    result = api.predict(target)
    if(result[:error])
      raise result[:error]
    else
      return result
    end
  end
end
prob_resize(stream) click to toggle source
# File lib/levdon.rb, line 409
def self.prob_resize(stream)
  if(Random.rand() < 0.9)
    return low_quality_resize(stream)
  end
  return high_quality_resize(stream)
end
standardize(path,options={:mode=>:delete}) click to toggle source
# File lib/levdon.rb, line 417
def self.standardize(path,options={:mode=>:delete})
  mode = options[:mode]
  dest = options[:dest]
  unless(mode)
    puts "Error"
    puts "Require parameter"
    puts " Specify a :mode => :delete or :move or :rename"
    exit(9)
  end
  unless(%w{delete delete rename}.member?(mode.to_s))
    puts "Error"
    puts "Require parameter"
    puts " Specify a :mode => :delete or :move or :rename"
    exit(9)
  end
  
  dirname = path
  unless File.directory?(path)
    dirname = File.dirname(path)
  end
  puts "Entry path : " + path
  puts "Destination : " + dirname


  identify_image(path) {|e|
    source_path     = e[:source_path]
    source_filename = e[:source_filename];
    dst_dirname     = File.dirname(source_path)
    if(e[:error])
      File.delete(source_path) if File.exist?(source_path)
      if(mode == :delete)
        File.delete(source_path) if File.exist?(source_path)
        next
      elsif(mode == :rename)
        FileUtils.mv(source_path,File.join(dst_dirname,mark+SecureRandom.uuid+"."+source_filename.split(".")[-1]))
        next
      else
        next
      end
    end
    img             = e[:image]
    width           = img.columns
    height          = img.rows
    mark            = ""
    
    # Check already standardized file or not.
    if source_filename.index("@STANDARDIZED@") == 0 or source_filename.index("@Q@") == 0
      puts "already done : " + source_path
      next
    # else
    #   puts "processing   : " + source_path
    end
    
    # Validaiton check
    if(width > 8192 or height > 8192)
      #puts "too big image: " + source_path
      mark = "@BIG@_"
    elsif(width < 300 or height < 300)
      #puts "thumb image  : " + source_path
      mark = "@THUMB@_"
    end
    
    puts e[:time].to_s + " : " + e[:size].to_s + " : "  + mark + " : " + source_path
    
    if(mark.length > 0)
      if(mode == :delete)
        File.delete(source_path) if File.exist?(source_path)
        next
      elsif(mode == :rename)
        FileUtils.mv(source_path,File.join(dst_dirname,mark+SecureRandom.uuid+"."+source_filename.split(".")[-1]))
        next
      elsif(mode == :move)
        if(dest)
          if(File.exist?(dest))
            if(File.directory?(dest))
              FileUtils.mv(source_path,File.join(dest,mark+SecureRandom.uuid+"."+source_filename.split(".")[-1]))
              next
            else
              puts "Error"
              puts "Destination is not directory.  => " + dest
              exit(9)
            end
          else
            puts "Error"
            puts "Destination path does not exist. => " + dest
            exit(9)
          end
        else
          puts "Error"
          puts "Destination path is nil."
          puts "You should specify a destination path for :move mode."
          exit(9)
        end
      end
    end
  
    # keeping ratio
    if(width > 1024 or height > 1024)
      img.resize_to_fit!(1024, 1024)
    end
    
    fname = source_filename.split(".")[0]
    img.format = 'JPEG'
    begin
      # Reformat and save
      img.write(File.join(dst_dirname,"@STANDARDIZED@_"+SecureRandom.uuid+".jpg")) { self.quality = 90 } # 1~100
      # Delete source file
      File.delete(source_path) if File.exist?(source_path)
    rescue => e
      puts "Write error"
      puts e.class
      puts e.message
      puts e.backtrace
    end
    # 10~30KB 80 : Q-TRAIN
    # 30~60KB 90 : Q-SOURCE
    # 50~200KB 100 : Q-SOURCE
  }
  puts "Done"
end