Class: Capybara::Screenshot::Diff::Drivers::ChunkyPNGDriver

Inherits:
Object
  • Object
show all
Includes:
ChunkyPNG::Color
Defined in:
lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(new_file_name, old_file_name = nil, **options) ⇒ ChunkyPNGDriver

Returns a new instance of ChunkyPNGDriver.



16
17
18
19
20
21
22
23
24
25
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 16

def initialize(new_file_name, old_file_name = nil, **options)
  @new_file_name = new_file_name
  @old_file_name = old_file_name || "#{new_file_name}~"

  @color_distance_limit = options[:color_distance_limit]
  @shift_distance_limit = options[:shift_distance_limit]
  @skip_area = options[:skip_area]

  reset
end

Instance Attribute Details

#new_file_nameObject (readonly)

Returns the value of attribute new_file_name.



14
15
16
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 14

def new_file_name
  @new_file_name
end

#old_file_nameObject (readonly)

Returns the value of attribute old_file_name.



14
15
16
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 14

def old_file_name
  @old_file_name
end

Instance Method Details

#add_black_box(image, _region) ⇒ Object



44
45
46
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 44

def add_black_box(image, _region)
  image
end

#adds_error_details_to(log) ⇒ Object



107
108
109
110
111
112
113
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 107

def adds_error_details_to(log)
  max_color_distance = self.max_color_distance.ceil(1)
  max_shift_distance = self.max_shift_distance

  log[:max_color_distance] = max_color_distance
  log.merge!(max_shift_distance: max_shift_distance) if max_shift_distance
end

#calculate_max_color_distance(new_image, old_image) ⇒ Object



139
140
141
142
143
144
145
146
147
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 139

def calculate_max_color_distance(new_image, old_image)
  pixel_pairs = old_image.pixels.zip(new_image.pixels)
  @max_color_distance = pixel_pairs.inject(0) { |max, (p1, p2)|
    next max unless p1 && p2

    d = ChunkyPNG::Color.euclidean_distance_rgba(p1, p2)
    [max, d].max
  }
end

#calculate_max_shift_limit(new_img, old_img) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 149

def calculate_max_shift_limit(new_img, old_img)
  (0...new_img.width).each do |x|
    (0...new_img.height).each do |y|
      shift_distance =
        shift_distance_at(new_img, old_img, x, y, color_distance_limit: @color_distance_limit)
      if shift_distance && (@max_shift_distance.nil? || shift_distance > @max_shift_distance)
        @max_shift_distance = shift_distance
        return if @max_shift_distance == Float::INFINITY # rubocop: disable Lint/NonLocalExitFromIterator
      end
    end
  end
end

#calculate_metricsObject

private



125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 125

def calculate_metrics
  old_file, new_file = load_image_files(@old_file_name, @new_file_name)

  if old_file == new_file
    @max_color_distance = 0
    @max_shift_distance = 0
    return
  end

  old_image, new_image = _load_images(old_file, new_file)
  calculate_max_color_distance(new_image, old_image)
  calculate_max_shift_limit(new_image, old_image)
end

#crop(dimensions, i) ⇒ Object



115
116
117
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 115

def crop(dimensions, i)
  i.crop(0, 0, *dimensions)
end

#difference_level(_diff_mask, old_img, region) ⇒ Object



48
49
50
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 48

def difference_level(_diff_mask, old_img, region)
  size(region).to_f / image_area_size(old_img)
end

#dimension_changed?(old_image, new_image) ⇒ Boolean

Returns:

  • (Boolean)


176
177
178
179
180
181
182
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 176

def dimension_changed?(old_image, new_image)
  return unless old_image.dimension != new_image.dimension

  change_msg = [old_image, new_image].map { |i| "#{i.width}x#{i.height}" }.join(" => ")
  warn "Image size has changed for #{@new_file_name}: #{change_msg}"
  true
end

#draw_rectangles(images, left, top, right, bottom, r, g, b) ⇒ Object



184
185
186
187
188
189
190
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 184

def draw_rectangles(images, (left, top, right, bottom), (r, g, b))
  images.map do |image|
    new_img = image.dup
    new_img.rect(left - 1, top - 1, right + 1, bottom + 1, ChunkyPNG::Color.rgb(r, g, b))
    new_img
  end
end

#filter_image_with_median(_image) ⇒ Object

Raises:

  • (NotImplementedError)


40
41
42
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 40

def filter_image_with_median(_image)
  raise NotImplementedError
end

#find_difference_region(new_image, old_image, color_distance_limit, shift_distance_limit, area_size_limit, fast_fail: false) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 66

def find_difference_region(new_image, old_image, color_distance_limit, shift_distance_limit, area_size_limit, fast_fail: false)
  return nil, nil if new_image.pixels == old_image.pixels

  if fast_fail && !(color_distance_limit || shift_distance_limit || area_size_limit)
    return [0, 0, width_for(new_image), height_for(new_image)], nil
  end

  region = find_top(old_image, new_image)
  region = if region.nil? || region[1].nil?
    nil
  else
    find_diff_rectangle(old_image, new_image, region)
  end

  [region, nil]
end

#from_file(filename) ⇒ Object



119
120
121
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 119

def from_file(filename)
  ChunkyPNG::Image.from_file(filename)
end

#height_for(image) ⇒ Object



83
84
85
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 83

def height_for(image)
  image.height
end

#image_area_size(old_img) ⇒ Object



52
53
54
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 52

def image_area_size(old_img)
  width_for(old_img) * height_for(old_img)
end

#load_image_files(old_file_name, file_name) ⇒ Object



170
171
172
173
174
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 170

def load_image_files(old_file_name, file_name)
  old_file = File.binread(old_file_name)
  new_file = File.binread(file_name)
  [old_file, new_file]
end

#load_images(old_file_name, new_file_name) ⇒ Object



34
35
36
37
38
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 34

def load_images(old_file_name, new_file_name)
  old_bytes, new_bytes = load_image_files(old_file_name, new_file_name)

  _load_images(old_bytes, new_bytes)
end

#max_color_distanceObject



97
98
99
100
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 97

def max_color_distance
  calculate_metrics unless @max_color_distance
  @max_color_distance
end

#max_shift_distanceObject



102
103
104
105
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 102

def max_shift_distance
  calculate_metrics unless @max_shift_distance || !@shift_distance_limit
  @max_shift_distance
end

#resetObject

Resets the calculated data about the comparison with regard to the “new_image”. Data about the original image is kept.



29
30
31
32
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 29

def reset
  @max_color_distance = @color_distance_limit ? 0 : nil
  @max_shift_distance = @shift_distance_limit ? 0 : nil
end

#resize_image_to(image, new_width, new_height) ⇒ Object



166
167
168
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 166

def resize_image_to(image, new_width, new_height)
  image.resample_bilinear(new_width, new_height)
end

#save_image_to(image, filename) ⇒ Object



162
163
164
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 162

def save_image_to(image, filename)
  image.save(filename)
end

#shift_distance_different?Boolean

Returns:

  • (Boolean)


61
62
63
64
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 61

def shift_distance_different?
  # Stub
  true
end

#shift_distance_equal?Boolean

Returns:

  • (Boolean)


56
57
58
59
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 56

def shift_distance_equal?
  # Stub
  false
end

#size(region) ⇒ Object



91
92
93
94
95
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 91

def size(region)
  return 0 unless region

  (region[2] - region[0] + 1) * (region[3] - region[1] + 1)
end

#width_for(image) ⇒ Object



87
88
89
# File 'lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb', line 87

def width_for(image)
  image.width
end