From 9a61da4663a8a2f247fdb40f386f166257c4d0c2 Mon Sep 17 00:00:00 2001 From: Sergei Illarionov Date: Mon, 30 Dec 2024 17:14:17 +0300 Subject: [PATCH] refactoring to have settings --- README.md | 32 +++++++++--------- is_dark.gemspec | 2 +- lib/is_dark.rb | 71 +++++++++++++++++++++------------------- spec/lib/is_dark_spec.rb | 36 +++++++++----------- 4 files changed, 71 insertions(+), 70 deletions(-) diff --git a/README.md b/README.md index 7ec1a8a..0e28995 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # is_dark Ruby Gem Ruby Gem to detect a dark color over an area from a blob of a file or by a color hex code based on [luminance w3 standarts]( https://www.w3.org/TR/WCAG20/#relativeluminancedef "luminance w3 standarts") -https://github.com/user-attachments/assets/b5c46ae5-b608-4588-a497-b3bd3eb690ef +https://github.com/user-attachments/assets/430cd789-1b5d-42a0-ae6e-c8b5f1da694b #### Can detect: * is a hex color dark @@ -14,7 +14,7 @@ An example practical aspect: it can be useful to understand will a black colored #### How to Install: Gemfile: -`gem 'is_dark', '~> 0.1.7'` +`gem 'is_dark', '~> 0.1.8'` Install: `gem install is_dark` @@ -35,19 +35,21 @@ Install: 5. is Imagick area from a blob dark (by coordinates of a dot + width and height from the dot): `IsDark.magick_area_from_blob(x, y, blob, height, width)` #standart default settings -#### More examples: -It also has kind of a development mode, when you can generate a debug outputs of all the generated dots based on provided coordinates. It can draw a test area over the file if you want, so you always can be sure, that you have valid coordinates on your tests. -- `IsDark.set_debug_data(true, false)` #with debug info outputs in logs - -- `IsDark.set_debug_data(true, '/var/www/project/is_dark_debug_output.pdf')` #with a generated debug pdf file (has displayed area of the analytics). You can use other file formats for the info (jpg, png, gif) - -- `IsDark.magick_area_from_blob(x, y, blob, height, width)` #standart default settings - -- ` IsDark.magick_area_from_blob(x, y, blob, cf_height, cf_width, 60, (1..10))` #additional settings (percent of dark dots amount to mark an area as a dark, range of matrix to build dots 1..10 - means 10x10; 0..10 - will have 121 dots for the analytics) - -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 at the end of the method: - -- ` IsDark.magick_area_from_blob(x, y, blob, cf_height, cf_width, 60, (1..10), false)` #detection "as white" is disabled) +#### Settings: +It also has kind of a development mode, when you can generate a debug outputs of all the generated dots based on provided coordinates. It can draw a test area over the file if you want, so you always can be sure, that you have valid coordinates on your tests. You can also set some other values and calibrate results as you need. + +```ruby +IsDark.configure({ + percent: 70, #percent of dark dots under an area to mark all the area as dark + matrix: (0..10), #range of dots to analyse. (0..10) means matrix 10x10 or 100 dots to analyse + with_not_detected_as_white: true, # 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_debug: true, #show debug output + with_debug_file: true, #draw a tested area in a copy of your blob file + debug_file_path: debug_file_path #path of the file with a drawn area +}) +``` +You can use these settings and test it after with this command: +`IsDark.magick_area_from_blob(x, y, blob, height, width)`, so it will show a debug info with a generated file #### Unit Tests: diff --git a/is_dark.gemspec b/is_dark.gemspec index 2dca80c..5b3c683 100644 --- a/is_dark.gemspec +++ b/is_dark.gemspec @@ -2,7 +2,7 @@ Gem::Specification.new do |s| s.name = 'is_dark' - s.version = '0.1.7' + s.version = '0.1.8' s.summary = 'Detects a dark background under an area or by a color code' s.description = 'Detects a dark color based on luminance W3 standarts ' \ "( https://www.w3.org/TR/WCAG20/#relativeluminancedef ). \n\n " \ diff --git a/lib/is_dark.rb b/lib/is_dark.rb index 0e9a81c..1118780 100644 --- a/lib/is_dark.rb +++ b/lib/is_dark.rb @@ -26,14 +26,29 @@ 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 self.configure(settings) + @percent = settings[:percent] || DEFAULT_PERCENT_OF_DOTS + @matrix = settings[:matrix] || DEFAULT_MATRIX_RANGE + @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] || DEFAULT_DEBUG_FILE_PATH + end def self.color(hex) @r, @g, @b = hex.match(/^#(..)(..)(..)$/).captures.map(&:hex) @@ -41,58 +56,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 +112,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