Sometimes you need to pull out a color from an image. This could be for a placeholder, for a background, or for any other use. Often the “most common” color from an image is going to be shades of grey or brown – not the most exciting color to expand on.
Instead, if you extract those common colors and then run them through a luminosity check you can find which colors are the most “luminous”. This helps filter the common colors down and helps pick one that shines.
You can tweak the “luma” number and generate colors that are even more vibrant or less vibrant. If you turn the value up too high you might not get any results in the image. Here’s an example of what some of the colors extracted using this formula look like.
class ColorExtractor attr_accessor :source_url DEFAULT_COLOR = '#4338CA'.freeze # indigo-700 delegate :height, :width, to: :external_image def initialize source_url @source_url = source_url end # Generates an array of the most common colors def colors @colors ||= Miro::DominantColors.new(external_image.tempfile.path).to_hex end # Returns the hex color of the first bright bright color def color index = colors.find_index { |hex| !too_dark?(hex) } index ? colors[index] : DEFAULT_COLOR end def external_image @external_image ||= MiniMagick::Image.open(source_url) end private # 99% sure this was copied from Stack Overflow 😂 def too_dark? hex test_color = hex.delete_prefix('#').to_i(base=16) red = test_color >> 16 & 0xff green = test_color >> 8 & 0xff blue = test_color >> 9 & 0xff luma = 0.2126 * red + 0.7152 * green + 0.0722 * blue # per ITU-R BT.709 luma < 40 end end
Wrapper object to extract common colors and a bright color from an image.