lib/capybara/screenshot/diff/image_compare.rb in capybara-screenshot-diff-1.6.3 vs lib/capybara/screenshot/diff/image_compare.rb in capybara-screenshot-diff-1.7.0
- old
+ new
@@ -10,13 +10,12 @@
class ImageCompare < SimpleDelegator
TMP_FILE_SUFFIX = "~"
attr_reader :driver, :driver_options
- attr_reader :annotated_new_file_name, :annotated_old_file_name, :area_size_limit,
- :color_distance_limit, :new_file_name, :old_file_name, :shift_distance_limit,
- :skip_area
+ attr_reader :annotated_new_file_name, :annotated_old_file_name, :new_file_name, :old_file_name, :skip_area
+ attr_accessor :shift_distance_limit, :area_size_limit, :color_distance_limit
def initialize(new_file_name, old_file_name = nil, options = {})
options = old_file_name if old_file_name.is_a?(Hash)
@new_file_name = new_file_name
@@ -38,104 +37,87 @@
@driver = driver_klass.new(@new_file_name, @old_file_name, **@driver_options)
super(@driver)
end
+ def skip_area=(new_skip_area)
+ @skip_area = new_skip_area
+ driver.skip_area = @skip_area
+ end
+
# Compare the two image files and return `true` or `false` as quickly as possible.
- # Return falsish if the old file does not exist or the image dimensions do not match.
+ # Return falsely if the old file does not exist or the image dimensions do not match.
def quick_equal?
return false unless old_file_exists?
return true if new_file_size == old_file_size
- # old_bytes, new_bytes = load_image_files(@old_file_name, @new_file_name)
- # return true if old_bytes == new_bytes
-
images = driver.load_images(@old_file_name, @new_file_name)
old_image, new_image = preprocess_images(images, driver)
return false if driver.dimension_changed?(old_image, new_image)
- region, meta = driver.find_difference_region(
+ self.difference_region, meta = driver.find_difference_region(
new_image,
old_image,
@color_distance_limit,
@shift_distance_limit,
@area_size_limit,
fast_fail: true
)
- self.difference_region = region
-
- return true if difference_region_empty?(new_image, region)
-
- return true if @area_size_limit && driver.size(region) <= @area_size_limit
-
- return true if @tolerance && @tolerance >= driver.difference_level(meta, old_image, region)
-
+ return true if difference_region_area_size.zero? || difference_region_empty?(new_image, difference_region)
+ return true if @area_size_limit && difference_region_area_size <= @area_size_limit
+ return true if @tolerance && @tolerance >= driver.difference_level(meta, old_image, difference_region)
# TODO: Remove this or find similar solution for vips
return true if @shift_distance_limit && driver.shift_distance_equal?
false
end
# Compare the two images referenced by this object, and return `true` if they are different,
# and `false` if they are the same.
- # Return `nil` if the old file does not exist or if the image dimensions do not match.
def different?
- return nil unless old_file_exists?
+ return false unless old_file_exists?
images = driver.load_images(@old_file_name, @new_file_name)
-
old_image, new_image = preprocess_images(images, driver)
if driver.dimension_changed?(old_image, new_image)
- save(new_image, old_image, @annotated_new_file_name, @annotated_old_file_name)
+ self.difference_region = Region.from_edge_coordinates(
+ 0,
+ 0,
+ [driver.width_for(old_image), driver.width_for(new_image)].min,
+ [driver.height_for(old_image), driver.height_for(new_image)].min
+ )
- self.difference_region = 0, 0, driver.width_for(old_image), driver.height_for(old_image)
-
- return true
+ return different(*images)
end
- region, meta = driver.find_difference_region(
+ self.difference_region, meta = driver.find_difference_region(
new_image,
old_image,
@color_distance_limit,
@shift_distance_limit,
@area_size_limit
)
- self.difference_region = region
- return not_different if difference_region_empty?(old_image, region)
- return not_different if @area_size_limit && driver.size(region) <= @area_size_limit
- return not_different if @tolerance && @tolerance > driver.difference_level(meta, old_image, region)
-
+ return not_different if difference_region_area_size.zero? || difference_region_empty?(old_image, difference_region)
+ return not_different if @area_size_limit && difference_region_area_size <= @area_size_limit
+ return not_different if @tolerance && @tolerance > driver.difference_level(meta, old_image, difference_region)
# TODO: Remove this or find similar solution for vips
return not_different if @shift_distance_limit && !driver.shift_distance_different?
- annotate_and_save(images, region)
-
- true
+ different(*images)
end
def clean_tmp_files
FileUtils.cp @old_file_name, @new_file_name if old_file_exists?
File.delete(@old_file_name) if old_file_exists?
File.delete(@annotated_old_file_name) if File.exist?(@annotated_old_file_name)
File.delete(@annotated_new_file_name) if File.exist?(@annotated_new_file_name)
end
- DIFF_COLOR = [255, 0, 0, 255].freeze
- SKIP_COLOR = [255, 192, 0, 255].freeze
-
- def annotate_and_save(images, region = difference_region)
- annotated_images = driver.draw_rectangles(images, region, DIFF_COLOR)
- @skip_area.to_a.flatten.each_slice(4) do |region|
- annotated_images = driver.draw_rectangles(annotated_images, region, SKIP_COLOR)
- end
- save(*annotated_images, @annotated_old_file_name, @annotated_new_file_name)
- end
-
def save(old_img, new_img, annotated_old_file_name, annotated_new_file_name)
driver.save_image_to(old_img, annotated_old_file_name)
driver.save_image_to(new_img, annotated_new_file_name)
end
@@ -146,29 +128,47 @@
def reset
self.difference_region = nil
driver.reset
end
+ NEW_LINE = "\n"
+
def error_message
result = {
- area_size: driver.size(difference_region),
- region: difference_region
+ area_size: difference_region_area_size,
+ region: difference_coordinates
}
driver.adds_error_details_to(result)
- ["(#{result.to_json})", new_file_name, annotated_old_file_name, annotated_new_file_name].join("\n")
+ [
+ "(#{result.to_json})",
+ new_file_name,
+ annotated_old_file_name,
+ annotated_new_file_name
+ ].join(NEW_LINE)
end
- def difference_region
- return nil unless @left || @top || @right || @bottom
+ def difference_coordinates
+ difference_region&.to_edge_coordinates
+ end
- [@left, @top, @right, @bottom]
+ def difference_region_area_size
+ return 0 unless difference_region
+
+ difference_region.size
end
private
+ attr_accessor :difference_region
+
+ def different(old_image, new_image)
+ annotate_and_save([old_image, new_image], difference_region)
+ true
+ end
+
def find_driver_class_for(driver)
driver = AVAILABLE_DRIVERS.first if driver == :auto
LOADED_DRIVERS[driver] ||=
case driver
@@ -181,27 +181,10 @@
else
fail "Wrong adapter #{driver.inspect}. Available adapters: #{AVAILABLE_DRIVERS.inspect}"
end
end
- def old_file_size
- @old_file_size ||= old_file_exists? && File.size(@old_file_name)
- end
-
- def new_file_size
- File.size(@new_file_name)
- end
-
- def not_different
- clean_tmp_files
- false
- end
-
- def load_images(old_file_name, new_file_name, driver = self)
- [driver.from_file(old_file_name), driver.from_file(new_file_name)]
- end
-
def preprocess_images(images, driver = self)
old_img = preprocess_image(images.first, driver)
new_img = preprocess_image(images.last, driver)
[old_img, new_img]
@@ -223,21 +206,51 @@
end
result
end
- def difference_region=(region)
- @left, @top, @right, @bottom = region
+ def old_file_size
+ @old_file_size ||= old_file_exists? && File.size(@old_file_name)
end
+ def new_file_size
+ File.size(@new_file_name)
+ end
+
+ def not_different
+ clean_tmp_files
+ false
+ end
+
def difference_region_empty?(new_image, region)
region.nil? ||
(
- region[1] == height_for(new_image) &&
- region[0] == width_for(new_image) &&
- region[2].zero? &&
- region[3].zero?
+ region.height == height_for(new_image) &&
+ region.width == width_for(new_image) &&
+ region.x.zero? &&
+ region.y.zero?
)
+ end
+
+ def annotate_and_save(images, region)
+ annotated_images = annotate_difference(images, region)
+ annotated_images = annotate_skip_areas(annotated_images, @skip_area) if @skip_area
+
+ save(*annotated_images, @annotated_old_file_name, @annotated_new_file_name)
+ end
+
+ DIFF_COLOR = [255, 0, 0, 255].freeze
+
+ def annotate_difference(images, region)
+ driver.draw_rectangles(images, region, DIFF_COLOR)
+ end
+
+ SKIP_COLOR = [255, 192, 0, 255].freeze
+
+ def annotate_skip_areas(annotated_images, skip_areas)
+ skip_areas.reduce(annotated_images) do |annotated_images, region|
+ driver.draw_rectangles(annotated_images, region, SKIP_COLOR)
+ end
end
end
end
end
end