class Capybara::Screenshot::Diff::ImageCompare

Compare two image and determine if they are equal, different, or within some comparison range considering color values and difference area size.

Constants

TOLERABLE_OPTIONS

Attributes

base_image_path[R]
difference[R]
driver[R]
driver_options[R]
error_message[R]
image_path[R]

Public Class Methods

new(image_path, base_image_path, options = {}) click to toggle source
# File lib/capybara/screenshot/diff/image_compare.rb, line 19
def initialize(image_path, base_image_path, options = {})
  @image_path = Pathname.new(image_path)
  @base_image_path = Pathname.new(base_image_path)

  @driver_options = options.dup

  @driver = Drivers.for(@driver_options)
end

Public Instance Methods

different?() click to toggle source

Compare the two image referenced by this object, and return ‘true` if they are different, and `false` if they are the same.

# File lib/capybara/screenshot/diff/image_compare.rb, line 58
def different?
  processed.difference.different?
end
processed() click to toggle source
# File lib/capybara/screenshot/diff/image_compare.rb, line 73
def processed
  self.difference = find_difference unless processed?
  @error_message ||= reporter.generate
  self
end
processed?() click to toggle source
# File lib/capybara/screenshot/diff/image_compare.rb, line 69
def processed?
  !!difference
end
quick_equal?() click to toggle source

Compare the two image files and return ‘true` or `false` as quickly as possible. Return falsely if the old file does not exist or the image dimensions do not match.

# File lib/capybara/screenshot/diff/image_compare.rb, line 30
def quick_equal?
  require_images_exists!

  # NOTE: This is very fuzzy logic, but so far it's helps to support current performance.
  return true if new_file_size == old_file_size

  comparison = load_and_process_images

  unless driver.same_dimension?(comparison)
    self.difference = build_failed_difference(comparison, {different_dimensions: true})
    return false
  end

  if driver.same_pixels?(comparison)
    self.difference = build_no_difference(comparison)
    return true
  end

  # NOTE: Could not make any difference to be tolerable, so skip and return as not equal.
  return false if without_tolerable_options?

  self.difference = driver.find_difference_region(comparison)

  !difference.different?
end
reporter() click to toggle source
# File lib/capybara/screenshot/diff/image_compare.rb, line 62
def reporter
  @reporter ||= begin
    current_difference = difference || build_no_difference(nil)
    Capybara::Screenshot::Diff::Reporters::Default.new(current_difference)
  end
end

Private Instance Methods

blur_image_by(image, size) click to toggle source
# File lib/capybara/screenshot/diff/image_compare.rb, line 164
def blur_image_by(image, size)
  driver.filter_image_with_median(image, size)
end
build_comparison() click to toggle source
# File lib/capybara/screenshot/diff/image_compare.rb, line 188
def build_comparison
  Capybara::Screenshot::Diff::Comparison.new(nil, nil, driver_options, driver, image_path, base_image_path).freeze
end
build_failed_difference(comparison, failed_by) click to toggle source
# File lib/capybara/screenshot/diff/image_compare.rb, line 116
def build_failed_difference(comparison, failed_by)
  Difference.new(
    nil,
    {difference_level: nil, max_color_distance: 0},
    comparison,
    failed_by
  )
end
build_no_difference(comparison = nil) click to toggle source
# File lib/capybara/screenshot/diff/image_compare.rb, line 180
def build_no_difference(comparison = nil)
  Difference.new(
    nil,
    {difference_level: nil, max_color_distance: 0},
    comparison || build_comparison
  ).freeze
end
difference=(new_difference) click to toggle source
# File lib/capybara/screenshot/diff/image_compare.rb, line 102
def difference=(new_difference)
  @error_message = nil
  @reporter = nil
  @difference = new_difference
end
find_difference() click to toggle source
# File lib/capybara/screenshot/diff/image_compare.rb, line 81
def find_difference
  require_images_exists!

  comparison = load_and_process_images

  unless driver.same_dimension?(comparison)
    return build_failed_difference(comparison, {different_dimensions: true})
  end

  if driver.same_pixels?(comparison)
    build_no_difference(comparison)
  else
    driver.find_difference_region(comparison)
  end
end
ignore_skipped_area(image) click to toggle source
# File lib/capybara/screenshot/diff/image_compare.rb, line 168
def ignore_skipped_area(image)
  skip_area&.reduce(image) { |memo, region| driver.add_black_box(memo, region) }
end
image_files_exist?() click to toggle source
# File lib/capybara/screenshot/diff/image_compare.rb, line 108
def image_files_exist?
  @base_image_path.exist? && @image_path.exist?
end
load_and_process_images() click to toggle source
# File lib/capybara/screenshot/diff/image_compare.rb, line 125
def load_and_process_images
  images = driver.load_images(base_image_path, image_path)
  base_image, new_image = preprocess_images(images)
  Comparison.new(new_image, base_image, @driver_options, driver, image_path, base_image_path)
end
median_filter_window_size() click to toggle source
# File lib/capybara/screenshot/diff/image_compare.rb, line 135
def median_filter_window_size
  @driver_options[:median_filter_window_size]
end
new_file_size() click to toggle source
# File lib/capybara/screenshot/diff/image_compare.rb, line 176
def new_file_size
  image_path.size
end
old_file_size() click to toggle source
# File lib/capybara/screenshot/diff/image_compare.rb, line 172
def old_file_size
  base_image_path.size
end
preprocess_image(image) click to toggle source
# File lib/capybara/screenshot/diff/image_compare.rb, line 143
def preprocess_image(image)
  result = image

  if skip_area
    result = ignore_skipped_area(result)
  end

  if median_filter_window_size
    if driver.is_a?(Drivers::VipsDriver)
      result = blur_image_by(image, median_filter_window_size)
    else
      warn(
        "[capybara-screenshot-diff] Median filter has been skipped for #{image_path} " \
          "because it is not supported by #{driver.class.name}"
      )
    end
  end

  result
end
preprocess_images(images) click to toggle source
# File lib/capybara/screenshot/diff/image_compare.rb, line 139
def preprocess_images(images)
  images.map { |image| preprocess_image(image) }
end
require_images_exists!() click to toggle source
# File lib/capybara/screenshot/diff/image_compare.rb, line 97
def require_images_exists!
  raise ArgumentError, "There is no original (base) screenshot version to compare, located: #{base_image_path}" unless base_image_path.exist?
  raise ArgumentError, "There is no new screenshot version to compare, located: #{image_path}" unless image_path.exist?
end
skip_area() click to toggle source
# File lib/capybara/screenshot/diff/image_compare.rb, line 131
def skip_area
  @driver_options[:skip_area]
end
without_tolerable_options?() click to toggle source
# File lib/capybara/screenshot/diff/image_compare.rb, line 112
def without_tolerable_options?
  (@driver_options.keys & TOLERABLE_OPTIONS).empty?
end