JoshSmith/kaleidoscope

View on GitHub
lib/kaleidoscope/instance_methods.rb

Summary

Maintainability
A
0 mins
Test Coverage
require 'kaleidoscope/errors/no_colors_configured'
require 'kaleidoscope/color_set'

module Kaleidoscope
  module InstanceMethods
    def colors_for
    end

    def generate_colors
      if has_colors_configured?
        Kaleidoscope.log("Generating colors for #{self.class.model_name}.")

        histogram = generate_histogram_for(magick_image)

        frequency_total = 0.0 # needs to be float

        array_of_pixels = []

        histogram.each do |h|
          # where h => [#<Magick::Pixel:0x007f948a736768>, 74558]
          # and h[0] is the Magick::Pixel
          # and h[1] is the histogram count
          # see, e.g. http://stackoverflow.com/questions/11282856/rmagicks-color-histogram-results-in-something-unlike-a-hash
          pixel = h[0]
          histogram_count = h[1]
          matched_pixel = compare_pixel_to_colors(pixel)
          array_of_pixels << { original_hex: hex_from_pixel(pixel), histogram_count: histogram_count, matched_hex: matched_pixel.to_hex, distance: distance_between(pixel: pixel, match: matched_pixel) }
          frequency_total += histogram_count
        end

        pixels_by_frequency = array_of_pixels.sort { |a, b| b[1] <=> a[1] }

        pixels_by_frequency.each do |pixel|
          frequency_percentage = histogram_count_to_percentage(pixel[:histogram_count], frequency_total)
          original_hex = sanitize_hex(pixel[:original_hex])
          matched_hex = sanitize_hex(pixel[:matched_hex])
          color_class.create(photo_id: self.id, original_color: original_hex, reference_color: matched_hex, frequency: frequency_percentage, distance: pixel[:distance])
        end

      else
        Kaleidoscope.log("Kaleidoscope::NoColorsConfiguredError: No colors are configured in your Kaleidoscope initializer.")
        raise NoColorsConfiguredError
      end
    end

    def destroy_colors
      Kaleidoscope.log("Deleting colors for #{self.class.model_name}.")
    end

    private

    def kaleidoscope_config
      Kaleidoscope.configuration
    end

    def available_colors
      kaleidoscope_config.colors
    end

    def has_colors_configured?
      has_kaleidoscope_config? && has_available_colors?
    end

    def has_kaleidoscope_config?
      !kaleidoscope_config.nil?
    end

    def has_available_colors?
      !available_colors.nil? && !available_colors.empty?
    end

    # Possibly extract out these methods
    def read_image_into_imagemagick(image_url)
      Magick::Image.read(image_url).first
    end

    def generate_histogram_for(magick_image)
      magick_image.quantize(number_of_colors).color_histogram
    end

    def number_of_colors
      kaleidoscope_config.number_of_colors
    end

    def compare_pixel_to_colors(pixel)
      pixel_color = color_from(pixel)
      match_color = color_set.find_closest_to(pixel_color)
    end

    def color_from(pixel)
      Kaleidoscope::Color.from_pixel(pixel)
    end

    def color_set
      @color_set ||= Kaleidoscope::ColorSet.new(kaleidoscope_config.colors)
    end

    def histogram_count_to_percentage(histogram_count, frequency_total)
      percentage_of_histogram = histogram_count / frequency_total
      (percentage_of_histogram * 100.0).round(1)
    end

    def color_class
      Object.const_get("#{self.class.name}Color")
    end

    def magick_image
      @magick_image ||= read_image_into_imagemagick(self.image.url)
    end

    def distance_between(pixel: pixel, match: match)
      pixel_color = color_from(pixel)
      pixel_color.distance_from(match)     
    end

    def hex_from_pixel(pixel)
      pixel.to_color(Magick::AllCompliance,false,8)
    end

    def sanitize_hex(hex)
      hex.delete('#').downcase
    end
  end
end