class Blufin::Image
Constants
- VALID_SIDES
Public Class Methods
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
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
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
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
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
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
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
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
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