diff --git a/lib/is_dark.rb b/lib/is_dark.rb index 0e9a81c..7f97dcf 100644 --- a/lib/is_dark.rb +++ b/lib/is_dark.rb @@ -26,14 +26,33 @@ class IsDark NONLINEAR_TRANSFORM_DIVIDER = 1.055 NONLINEAR_TRANSFORM_OFFSET = 0.055 RED_LUMINANCE_COEFFICIENT = 0.2126 + DEFAULT_PERCENT_OF_DOTS = 80 + DEFAULT_MATRIX_RANGE = (0..10).freeze + DEFAULT_DEBUG_FILE_PATH = '/tmp/is_dark_debug_file.pdf' @r = 0 @g = 0 @b = 0 @colorset = MAXIMUM_COLOR_DEPTH + @percent = DEFAULT_PERCENT_OF_DOTS + @matrix = DEFAULT_MATRIX_RANGE + @with_not_detected_as_white = true @with_debug = false @with_debug_file = false - @debug_file_path = '/tmp/is_dark_debug_file.pdf' + @debug_file_path = DEFAULT_DEBUG_FILE_PATH + + def initialize(settings) + configure(settings) unless settings.nil? + end + + def self.configure(settings) + @percent = settings[:percent] || 80 + @matrix = settings[:matrix] || (0..10) + @with_not_detected_as_white = settings[:with_not_detected_as_white] || true + @with_debug = settings[:with_debug] || false + @with_debug_file = settings[:with_debug_file] || false + @debug_file_path = settings[:debug_file_path] || '/tmp/is_dark_debug_file.pdf' + end def self.color(hex) @r, @g, @b = hex.match(/^#(..)(..)(..)$/).captures.map(&:hex) @@ -41,58 +60,55 @@ def self.color(hex) dark? end - def self.magick_pixel(pix, x = nil, y = nil, set_not_detected_light = true) + def self.magick_pixel(pix, x = nil, y = nil) @r = pix.red.to_f @g = pix.green.to_f @b = pix.blue.to_f @colorset = MAX_COLOR_VALUE - dark?(x, y, set_not_detected_light) + dark?(x, y) end - def self.magick_pixel_from_blob(x, y, blob, _set_not_detected_light = true) + def self.magick_pixel_from_blob(x, y, blob) image = Magick::Image.read(blob).first pix = image.pixel_color(x, y) magick_pixel(pix, x, y) end # (x, y) is the left corner of an element over a blob, height and width is the element's size - def self.magick_area_from_blob( - x, y, blob, height, width, percent = 80, range = (0..10), set_not_detected_light = true - ) - @set_not_detected_light = set_not_detected_light + def self.magick_area_from_blob(x, y, blob, height, width) image = Magick::Image.read(blob).first dark = false dots = [] - range.each do |xx| - range.each do |yy| + @matrix.each do |xx| + @matrix.each do |yy| dots << { x: (x + (width * xx / 10)).to_i, y: (y + (height * yy / 10)).to_i } end end points = 0 if @with_debug_file - oldx = false - oldy = false + old_x = false + old_y = false end - p '====================================================================' if @with_debug + p '==================================================================================' if @with_debug dots.each do |dot| x = dot[:x].to_i y = dot[:y].to_i pix = image.pixel_color(x, y) - l = magick_pixel(pix, x, y, set_not_detected_light) + l = magick_pixel(pix, x, y) points += 1 if l next unless @with_debug_file - draw_debug_files(image, x, y, oldx, oldy) - oldy = y - oldx = x + draw_debug_files(image, x, y, old_x, old_y) + old_y = y + old_x = x end - dark = true if points >= (dots.length / 100) * percent + dark = true if points >= (dots.length / 100) * @percent if @with_debug p '==================================================================================' p "Total Points: #{dots.length}, dark points amount:#{points}" - p "Is \"invert to white not detectd pixels\" option enabled?:#{set_not_detected_light}" - p "Signature will be inverted if #{percent}% of dots will be dark" + p "Is \"invert to white not detectd pixels\" option enabled?:#{@with_not_detected_as_white}" + p "Signature will be inverted if #{@percent}% of dots will be dark" p "Is inverted?: #{dark}" p "have a look on #{@debug_file_path} file to see your tested area of a blob" p '==================================================================================' @@ -100,33 +116,24 @@ def self.magick_area_from_blob( dark end - def self.set_debug_data(show_info = false, draw_file = false) - @with_debug = show_info - return unless draw_file != false - - @with_debug_file = true - @debug_file_path = draw_file - end - - def self.draw_debug_files(image, x, y, oldx, oldy) - return unless oldx && oldy + def self.draw_debug_files(image, x, y, old_x, old_y) + return unless old_x && old_y gc = Magick::Draw.new - gc.line(x, y, oldx, oldy) + gc.line(x, y, old_x, old_y) gc.stroke('black') gc.draw(image) image.write(@debug_file_path) end # detects a dark color based on luminance W3 standarts ( https://www.w3.org/TR/WCAG20/#relativeluminancedef ) - def self.dark?(x = nil, y = nil, set_not_detected_light = true) + def self.dark?(x = nil, y = nil) dark = false inverted = false pixel = [@r.to_f, @g.to_f, @b.to_f] return true if pixel == [0.00, 0.00, 0.00] # hardcoded exception - # probably not detected pixel color by Imagick, will be considered as "white" if "set_not_detected_light = true" - if set_not_detected_light && pixel[0] == 0.0 && pixel[1] == 0.0 && pixel[2] == 0.0 + if @with_not_detected_as_white && pixel[0] == 0.0 && pixel[1] == 0.0 && pixel[2] == 0.0 pixel = [MAXIMUM_COLOR_DEPTH, MAXIMUM_COLOR_DEPTH, MAXIMUM_COLOR_DEPTH] inverted = true end diff --git a/spec/lib/is_dark_spec.rb b/spec/lib/is_dark_spec.rb index f9d8d02..c2ef0fc 100644 --- a/spec/lib/is_dark_spec.rb +++ b/spec/lib/is_dark_spec.rb @@ -88,13 +88,7 @@ y = 120 # coordinate of a left corner of the area's rectangle Y cf_height = 64 # height of the area's rectangle cf_width = 128 # height of the area's rectangle - percent = 70 # percent of detected dark pixels to invert - matrix = (1..10) # matrix of dots. Range of matrix to build dots 1..10 - means 10x10 - # Sometimes Imagick can't detect a pixel or it has no color, so it detects it as (RGB: 0,0,0), the gem has an - # option to consider pixels like this as "white", but if you need to disable this option add true or false. - with_not_detected = false - expect(IsDark.magick_area_from_blob(x, y, TEST_FILE_PATH, cf_height, cf_width, percent, matrix, - with_not_detected)).to eq(false) + expect(IsDark.magick_area_from_blob(x, y, TEST_FILE_PATH, cf_height, cf_width)).to eq(false) end end @@ -104,13 +98,7 @@ y = 120 # coordinate of a left corner of the area's rectangle Y cf_height = 64 # height of the area's rectangle cf_width = 128 # height of the area's rectangle - percent = 70 # percent of detected dark pixels to invert - matrix = (1..10) # matrix of dots. Range of matrix to build dots 1..10 - means 10x10 - # Sometimes Imagick can't detect a pixel or it has no color, so it detects it as (RGB: 0,0,0), the gem has - # an option to consider pixels like this as "white", but if you need to disable this option add true or false. - with_not_detected = false - expect(IsDark.magick_area_from_blob(x, y, TEST_FILE_PATH, cf_height, cf_width, percent, matrix, - with_not_detected)).to eq(false) + expect(IsDark.magick_area_from_blob(x, y, TEST_FILE_PATH, cf_height, cf_width)).to eq(false) end end @@ -120,14 +108,22 @@ y = 120 # coordinate of a left corner of the area's rectangle Y cf_height = 64 # height of the area's rectangle cf_width = 128 # height of the area's rectangle - percent = 70 # percent of detected dark pixels to invert + percent = 70 # percent of detected dark pixels to mark as dark matrix = (1..10) # matrix of dots. Range of matrix to build dots 1..10 - means 10x10 # Sometimes Imagick can't detect a pixel or it has no color, so it detects it as (RGB: 0,0,0), the gem has - # an option to consider pixels like this as "white", but if you need to disable this option add true or false. - with_not_detected = false - IsDark.set_debug_data(true, './is_dark_debug_output.pdf') - expect(IsDark.magick_area_from_blob(x, y, TEST_FILE_PATH, cf_height, cf_width, percent, matrix, - with_not_detected)).to eq(false) + # an option to consider pixels like this as "white", but if you need to disable this option add true or false: + not_detected = false + # generated file with lines through dots of the matrix over a tested area: + debug_file_path = './is_dark_debug_file.pdf' + IsDark.configure({ + percent: percent, + matrix: matrix, + with_not_detected_as_white: not_detected, + with_debug: true, + with_debug_file: true, + debug_file_path: debug_file_path + }) + expect(IsDark.magick_area_from_blob(x, y, TEST_FILE_PATH, cf_height, cf_width)).to eq(false) end end end