class Blufin::Image

Constants

VALID_SIDES

Public Class Methods

add_text(src, target, text, x = 35, y = 60, bg = 'black', fg = 'white', point_size = 22, stroke_width = 1) click to toggle source

Adds text/caption to image. @return void

# File lib/core/image.rb, line 85
def self.add_text(src, target, text, x = 35, y = 60, bg = 'black', fg = 'white', point_size = 22, stroke_width = 1)
    raise RuntimeError, "File not found: #{src}" unless Blufin::Files::file_exists(src)
    raise RuntimeError, "Expected integer (for x), instead got: #{x}" unless x.to_s =~ /^\d+$/
    raise RuntimeError, "Expected integer (for y), instead got: #{y}" unless y.to_s =~ /^\d+$/
    raise RuntimeError, "Expected integer (for point_size), instead got: #{point_size}" unless point_size.to_s =~ /^\d+$/
    raise RuntimeError, "Expected integer (for stroke_width), instead got: #{stroke_width}" unless stroke_width.to_s =~ /^\d+$/
    Blufin::Terminal::execute("convert #{src} -undercolor #{bg} -stroke #{fg} -pointsize #{point_size} -strokewidth #{stroke_width} -draw \"text #{x},#{y} '#{text}'\" #{target}")
end
calc_aspect_ratio(width, height) click to toggle source

Calculates the aspect ration (IE: 16:9) from a set of given dimensions. @return string

# File lib/core/image.rb, line 96
def self.calc_aspect_ratio(width, height)
    gcd = gcd(width, height)
    "#{(width / gcd).to_i}:#{(height / gcd).to_i}"
end
calc_file_name(prefix, ext, side, length, ratio) click to toggle source

Standardizes the way output files are named. @return string

# File lib/core/image.rb, line 133
def self.calc_file_name(prefix, ext, side, length, ratio)
    raise RuntimeError, "Expected integer, instead got: #{length}" unless length.to_s =~ /^\d+$/
    raise RuntimeError, "Expected one of: #{VALID_SIDES.inspect}, instead got: #{side}" unless VALID_SIDES.include?(side)
    raise RuntimeError, "Unexpected ratio #{Blufin::Terminal::format_highlight(ratio)}, expected something like: 16:9" unless ratio =~ /\d{1,2}:\d{1,2}/
    x = side == 'width' ? length : calc_width_from_ratio(ratio, length)
    y = side == 'width' ? calc_height_from_ratio(ratio, length) : length
    "#{prefix}-#{x}x#{y}.#{ext.downcase}"
end
calc_height_from_ratio(ratio, width) click to toggle source

Calculates height from aspect ratio and width: IE: 16:9 and 1920 returns -> 1080. @return int

# File lib/core/image.rb, line 114
def self.calc_height_from_ratio(ratio, width)
    raise RuntimeError, "Unexpected ratio #{Blufin::Terminal::format_highlight(ratio)}, expected something like: 16:9" unless ratio =~ /\d{1,2}:\d{1,2}/
    raise RuntimeError, "Expected integer, instead got: #{width}" unless width.to_s =~ /^\d+$/
    rs = ratio.split(':')
    ((width.to_i / rs[0].to_i) * rs[1].to_i).to_i
end
calc_width_from_ratio(ratio, height) click to toggle source

Calculates width from aspect ratio and height: IE: 16:9 and 1080 returns -> 1920. @return int

# File lib/core/image.rb, line 104
def self.calc_width_from_ratio(ratio, height)
    raise RuntimeError, "Unexpected ratio #{Blufin::Terminal::format_highlight(ratio)}, expected something like: 16:9" unless ratio =~ /\d{1,2}:\d{1,2}/
    raise RuntimeError, "Expected integer, instead got: #{height}" unless height.to_s =~ /^\d+$/
    rs = ratio.split(':')
    ((height.to_i / rs[1].to_i) * rs[0].to_i).to_i
end
crop_to_length_and_ratio(src, target, side, length, ratio, quality = 100) click to toggle source

This command crops an image based on a give size and a ration (using ImageMagick). If dimensions don't match ratio, adjusts accordingly and crops from center. Must specify if you want @side to be width or height, where your chosen side will match @length and the other gets altered as needed. @src - path/file to source image. @target - path/file to target image. side - the side for which you want to apply the length to (other side will get adjusted accordingly) length - the length that you want applied ratio - the ratio you want (16:9 and 9:16 will produce different results) quality - the higher the quality, the bigger the image. @return void

# File lib/core/image.rb, line 40
def self.crop_to_length_and_ratio(src, target, side, length, ratio, quality = 100)
    d1 = length
    side.downcase!
    raise RuntimeError, "Expected integer, instead got: #{d1}" unless d1.to_s =~ /^\d+$/
    raise RuntimeError, "Expected one of: #{VALID_SIDES.inspect}, instead got: #{side}" unless VALID_SIDES.include?(side)
    raise RuntimeError, "Unexpected ratio #{Blufin::Terminal::format_highlight(ratio)}, expected something like: 16:9" unless ratio =~ /\d{1,2}:\d{1,2}/
    raise RuntimeError, "Expected integer between 0 - 100, instead got: #{quality}" unless quality.to_s =~ /^\d+$/ && quality.to_i >= 0 && quality.to_i <= 100
    raise RuntimeError, "File not found: #{src}" unless Blufin::Files::file_exists(src)
    # Convert the initial image to match the width.
    c1 = side == 'width' ? d1 : "x#{d1}"
    Blufin::Terminal::execute("magick #{src} -resize #{c1} -quality #{quality} #{target}")
    ac = info(target)
    d2 = side == 'width' ? calc_height_from_ratio(ratio, d1) : calc_width_from_ratio(ratio, d1)
    # If the other side is less that what's desired, convert the image using the other orientation.
    c3 = side == 'width' ? ac.height : ac.width
    if c3 < d2
        c2 = side == 'width' ? "x#{d2}" : d2
        Blufin::Terminal::execute("magick #{src} -resize #{c2} -quality #{quality} #{target}")
        ac = info(target)
    end
    ow = ac.width
    oh = ac.height
    if side == 'width'
        x  = ow > d1 ? ((ow - d1) / 2).to_i : 0
        y  = oh > d2 ? ((oh - d2) / 2).to_i : 0
        c4 = d1
        c5 = calc_height_from_ratio(ratio, d1)
    else
        x  = ow > d2 ? ((ow - d2) / 2).to_i : 0
        y  = oh > d1 ? ((oh - d1) / 2).to_i : 0
        c4 = calc_width_from_ratio(ratio, d1)
        c5 = d1
    end
    # Do the final crop.
    Blufin::Terminal::execute("convert #{target} -crop #{c4}x#{c5}+#{x}+#{y} +repage #{target}")
    # Output details about the image.
    img = info(target)
    ts  = target.split('/')
    puts
    puts "    \x1B[38;5;40m#{ts[ts.length - 1]}\x1B[38;5;240m \xe2\x80\x94 #{Filesize.from("#{img.size} B").pretty} | #{img.ratio}#{img.ratio != ratio ? ' - For this image, a perfect ratio couldn\'t be achieved :(' : nil}\x1B[0m"
    puts
end
gcd(a, b) click to toggle source

Gets the greatest-common-denominator. Used to calculate screen aspect ratio. See: stackoverflow.com/questions/14731745/what-exactly-does-do-in-javascript @return int

# File lib/core/image.rb, line 124
def self.gcd(a, b)
    a = a.to_i
    b = b.to_i
    return a if b == 0
    gcd(b, a % b)
end
info(path_and_file) click to toggle source

Uses ImageMagick to return details about an image. @return Hash

# File lib/core/image.rb, line 16
def self.info(path_and_file)
    check_image_magick_installed
    raise RuntimeError, "File not found: #{path_and_file}" unless Blufin::Files::file_exists(path_and_file)
    img                      = MiniMagick::Image.open(path_and_file)
    img_container            = ImageContainer.new
    img_container.width      = img.dimensions[0].to_i
    img_container.height     = img.dimensions[1].to_i
    img_container.size       = img.size
    img_container.size_human = img.human_size
    img_container.type       = img.type.downcase
    img_container.ratio      = calc_aspect_ratio(img.dimensions[0].to_i, img.dimensions[1].to_i)
    img_container
end

Private Class Methods

check_image_magick_installed() click to toggle source

Checks ImageMagick is installed on this system. @return void

# File lib/core/image.rb, line 146
def self.check_image_magick_installed
    Blufin::Terminal::error('ImageMagick might not be installed.', "The command: #{Blufin::Terminal::format_command('magick')} was not found on this system.", true) unless system('magick -version >/dev/null')
end