class FlickrCollage::Image

Class for Image. Create collage and crop images @attr_reader [String] img_path Path for saving images @attr_reader [Number] img_width Width for images crop @attr_reader [Number] img_height Height for images crop @attr_reader [String] collage_file Collage file name @attr_reader [Boolean] clear_tmp Delete all downloaded images

Constants

IMG_HEIGHT
IMG_WIDTH

Attributes

clear_tmp[RW]
collage_file[RW]
img_height[RW]
img_path[RW]
img_width[RW]

Public Class Methods

new(opts = {}) click to toggle source
# File lib/FlickrCollage.rb, line 151
def initialize(opts = {})
  opts[:img_path]     ||= IMG_PATH
  opts[:img_width]    ||= IMG_WIDTH
  opts[:img_height]   ||= IMG_HEIGHT
  opts[:collage_file] ||= COLLAGE_FILE

  @img_path           = opts[:img_path]
  @img_width          = opts[:img_width]
  @img_height         = opts[:img_height]
  @collage_file       = opts[:collage_file]
  @clear_tmp          = opts[:clear_tmp]
end
valid?(file) click to toggle source

Validates downloaded image

@param [String] file file path for downloaded image

@return [true] image is valid @return [false] image is not valid

# File lib/FlickrCollage.rb, line 170
def self.valid?(file)
  return false if file.nil?
  begin
    image = MiniMagick::Image.open(file)
  rescue StandardError => e
    warn "Image.valid: caught exception #{e}"
    raise e if RAISE_ERROR
  end
  image.valid?
end

Public Instance Methods

collage(opts = {}) click to toggle source

Creates collage from 10 images

@param [Hash] opts @option opts [Array<String>] :files file paths for collage images

@return [true] collage created successfully @return [false] something went wrong

# File lib/FlickrCollage.rb, line 214
def collage(opts = {})
  unless opts[:files].size == IMG_COUNT
    info "Not enough images for collage"
    return false
  end

  begin
    (1..4).each do |row|
      montage = MiniMagick::Tool::Montage.new
      files = montage_resize(files: opts[:files], row: row)
      files.each do |file|
        montage << file
      end
      montage << "-mode"
      montage << "Concatenate"
      montage << "-background"
      montage << "none"
      montage << "-geometry"
      montage << montage_geometry(row: row)
      montage << "-tile"
      montage << montage_tile(row: row)
      montage << montage_img_path(row: row)
      montage.call
    end
  rescue StandardError => e
    warn "Image.collage: caught exception #{e}"
    raise e if RAISE_ERROR
  end
  FileUtils.rm_rf("#{@img_path}tmp") if @clear_tmp
  true
end
collage_simple(opts = {}) click to toggle source

Creates simple collage 5x2 from 10 images

@param [Hash] opts @option opts [Array<String>] :files file paths for collage images

@return [true] collage created successfully @return [false] something went wrong @deprecated First collage implementation

# File lib/FlickrCollage.rb, line 285
def collage_simple(opts = {})
  unless opts[:files].size == IMG_COUNT
    info "No images for collage"
    return false
  end

  begin
    montage = MiniMagick::Tool::Montage.new
    opts[:files].each do |file|
      montage << resize(file: file)
    end
    montage << "-mode"
    montage << "Concatenate"
    montage << "-background"
    montage << "none"
    montage << "-geometry"
    montage << "#{@img_width}x#{@img_height}+0+0"
    montage << "-tile"
    montage << "5x2"
    montage << "#{@img_path}#{@collage_file}.jpg"
    puts montage.inspect.to_s
    montage.call
  rescue StandardError => e
    warn "Image.collage: caught exception #{e}"
    raise e if RAISE_ERROR
  end
  true
end
resize(opts = {}) click to toggle source

Resize image

@param [Hash] opts @option opts [String] :file file path for image @option opts [Number] :width (@img_width) image new width @option opts [Number] :height (@img_height) image new height

@return [String] file path for resized image

# File lib/FlickrCollage.rb, line 189
def resize(opts = {})
  return false if opts[:file].nil?

  opts[:width]    ||= @img_width
  opts[:height]   ||= @img_height
  begin
    image = MiniMagick::Image.open(opts[:file])
    resize_to_fill(opts[:width], opts[:height], image)
    file_resize = "#{@img_path}tmp/#{File.basename(opts[:file], ".jpg")}_resize.jpg"
    image.write file_resize
    debug "Resize #{opts[:file]} to #{opts[:width]}x#{opts[:height]}"
  rescue StandardError => e
    warn "Image.resize: caught exception #{e}"
    raise e if RAISE_ERROR
  end
  file_resize
end
resize_to_fill(width, height, img, gravity = "Center") click to toggle source

Smart image crop

@param [Number] width image new width @param [Number] height image new height @param [MiniMagick::Image] img image @param [String] gravity crop around

@return [MiniMagick::Image] cropped image

# File lib/FlickrCollage.rb, line 254
def resize_to_fill(width, height, img, gravity = "Center")
  cols, rows = img[:dimensions]
  img.combine_options do |cmd|
    if width != cols || height != rows
      scale_x = width / cols.to_f
      scale_y = height / rows.to_f
      if scale_x >= scale_y
        cols = (scale_x * (cols + 0.5)).round
        rows = (scale_x * (rows + 0.5)).round
        cmd.resize cols.to_s
      else
        cols = (scale_y * (cols + 0.5)).round
        rows = (scale_y * (rows + 0.5)).round
        cmd.resize "x#{rows}"
      end
    end

    cmd.gravity gravity
    cmd.background "rgba(255,255,255,0.0)"
    cmd.extent "#{width}x#{height}" if cols != width || rows != height
  end
end

Private Instance Methods

montage_geometry(opts = {}) click to toggle source

Montage Collage - setting images geometry for rows 1 row - 3 images 2 row - 4 images 3 row - 3 images

@param [Hash] opts @option opts [Number] :row collage row 1..4 (4 row - final collage from first 3 rows)

@return [String] images geometry

# File lib/FlickrCollage.rb, line 357
def montage_geometry(opts = {})
  case opts[:row]
  when 1, 3 then "#{@img_width}x#{@img_height}+0+0"
  when 2 then "#{@img_width * 0.75}x#{@img_height}+0+0"
  when 4 then "#{@img_width * 3}x#{@img_height}+0+0"
  end
end
montage_img_path(opts = {}) click to toggle source

Montage Collage - setting images paths for rows 1 row - 3 images 2 row - 4 images 3 row - 3 images

@param [Hash] opts @option opts [Number] :row collage row 1..4 (4 row - final collage from first 3 rows)

@return [String] images path

# File lib/FlickrCollage.rb, line 391
def montage_img_path(opts = {})
  case opts[:row]
  when 1..3 then "#{@img_path}tmp/#{@collage_file}-#{opts[:row]}.jpg"
  when 4 then "#{@img_path}#{@collage_file}.jpg"
  else ""
  end
end
montage_resize(opts = {}) click to toggle source

Montage Collage - resizing images for rows 1 row - 3 images 2 row - 4 images 3 row - 3 images

@param [Hash] opts @option opts [Number] :row collage row 1..4 (4 row - final collage from first 3 rows)

@return [Array<String>] Array of file paths for resized images

# File lib/FlickrCollage.rb, line 325
def montage_resize(opts = {})
  files = []
  case opts[:row]
  when 1
    (0..2).each do |i|
      files << resize(file: opts[:files][i])
    end
  when 2
    (3..6).each do |i|
      files << resize(file: opts[:files][i], width: @img_width * 0.75)
    end
  when 3
    (7..9).each do |i|
      files << resize(file: opts[:files][i])
    end
  when 4
    (1..3).each do |i|
      files << "#{@img_path}tmp/#{@collage_file}-#{i}.jpg"
    end
  end
  files
end
montage_tile(opts = {}) click to toggle source

Montage Collage - setting images tile for rows 1 row - 3 images 2 row - 4 images 3 row - 3 images

@param [Hash] opts @option opts [Number] :row collage row 1..4 (4 row - final collage from first 3 rows)

@return [String] images tile

# File lib/FlickrCollage.rb, line 374
def montage_tile(opts = {})
  case opts[:row]
  when 1, 3 then "3x1"
  when 2 then "4x1"
  when 4 then "1x3"
  end
end