Class: IsDark
- Inherits:
-
Object
- Object
- IsDark
- Defined in:
- lib/is_dark.rb
Overview
The ‘Is Dark` class is designed to determine whether a given color or pixel is dark based on luminance standards defined by the W3C. It utilizes the `rmagick` library to handle image processing tasks. The class includes methods to analyze colors from hexadecimal values, individual pixels, and areas within images blobs. It also supports debugging features to visualize the analysis process.
Key features include:
-
**Color Analysis**: Determines if a color is dark based on its luminance.
-
**- **Pixel Analysis**: Analysis individual pixels from an image.
-
**Area Analysis**: Evaluates the darkness of a specified area within an image blob.
-
Debugging: Provides options to enable debugging information and visualize the analysis on a PDF file.
Constant Summary collapse
- BLUE_LUMINANCE_COEFFICIENT =
0.0722
- GREEN_LUMINANCE_COEFFICIENT =
0.7152
- HIGH_LUMINANCE_DIVIDER =
1.055- HIGH_LUMINANCE_POWER =
2.4- LOW_LUMINANCE_DIVIDER =
12.92- LUMINANCE_THRESHOLD =
0.05
- MAXIMUM_COLOR_DEPTH =
255- MAX_COLOR_VALUE_MULTIPLIER =
655- MAX_COLOR_VALUE =
MAX_COLOR_VALUE_MULTIPLIER * MAXIMUM_COLOR_DEPTH
- LINEAR_LUMINANCE_THRESHOLD =
(1 / (LOW_LUMINANCE_DIVIDER * 100.0)) * MAXIMUM_COLOR_DEPTH
- 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'
Instance Method Summary collapse
- #color(hex) ⇒ Object
- #configure(settings = {}) ⇒ Object
-
#dark?(x = nil, y = nil) ⇒ Boolean
detects a dark color based on luminance W3 standarts ( www.w3.org/TR/WCAG20/#relativeluminancedef ).
- #draw_debug_files(image, x, y, old_x, old_y) ⇒ Object
-
#initialize(settings = {}) ⇒ IsDark
constructor
A new instance of IsDark.
-
#magick_area_from_blob(x, y, blob, height, width) ⇒ Object
(x, y) is the left corner of an element over a blob, height and width is the element’s size.
- #magick_pixel(pix, x = nil, y = nil) ⇒ Object
- #magick_pixel_from_blob(x, y, blob) ⇒ Object
Constructor Details
#initialize(settings = {}) ⇒ IsDark
Returns a new instance of IsDark.
45 46 47 |
# File 'lib/is_dark.rb', line 45 def initialize(settings = {}) configure(settings) end |
Instance Method Details
#color(hex) ⇒ Object
59 60 61 62 63 |
# File 'lib/is_dark.rb', line 59 def color(hex) @r, @g, @b = hex.match(/^#(..)(..)(..)$/).captures.map(&:hex) @colorset = MAXIMUM_COLOR_DEPTH dark? end |
#configure(settings = {}) ⇒ Object
49 50 51 52 53 54 55 56 57 |
# File 'lib/is_dark.rb', line 49 def configure(settings = {}) @percent = settings[:percent] || DEFAULT_PERCENT_OF_DOTS @matrix = settings[:matrix] || DEFAULT_MATRIX_RANGE @luminance = settings[:luminance] || LUMINANCE_THRESHOLD @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 |
#dark?(x = nil, y = nil) ⇒ Boolean
detects a dark color based on luminance W3 standarts ( www.w3.org/TR/WCAG20/#relativeluminancedef )
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/is_dark.rb', line 135 def 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 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 calculated = [] pixel.each do |color| color /= @colorset if color <= LINEAR_LUMINANCE_THRESHOLD color /= LOW_LUMINANCE_DIVIDER else color = ((color + NONLINEAR_TRANSFORM_OFFSET) / NONLINEAR_TRANSFORM_DIVIDER)**HIGH_LUMINANCE_POWER end calculated << color end l = (RED_LUMINANCE_COEFFICIENT * calculated[0]) + (GREEN_LUMINANCE_COEFFICIENT * calculated[1]) + (BLUE_LUMINANCE_COEFFICIENT * calculated[2]) dark = true if l <= @luminance if @with_debug debug = { X: x, Y: y, R: @r, G: @g, B: @b, 'luminance value': l, dark?: dark, 'inverted to white': inverted } p debug end dark end |
#draw_debug_files(image, x, y, old_x, old_y) ⇒ Object
124 125 126 127 128 129 130 131 132 |
# File 'lib/is_dark.rb', line 124 def draw_debug_files(image, x, y, old_x, old_y) return unless old_x && old_y gc = Magick::Draw.new gc.line(x, y, old_x, old_y) gc.stroke('black') gc.draw(image) image.write(@debug_file_path) end |
#magick_area_from_blob(x, y, blob, height, width) ⇒ Object
(x, y) is the left corner of an element over a blob, height and width is the element’s size
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/is_dark.rb', line 80 def magick_area_from_blob(x, y, blob, height, width) image = Magick::Image.read(blob).first dark = false dots = [] @matrix.each do |xx| @matrix.each do |yy| dots << { x: (x + (width * xx / @matrix.count)).to_i, y: (y + (height * yy / @matrix.count)).to_i } end end points = 0 if @with_debug_file old_x = false old_y = false end 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) points += 1 if l next unless @with_debug_file 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 if @with_debug percent_calculated = points/(dots.length / 100) p '==================================================================================' p "Total Points: #{dots.length}, dark points amount:#{points}" p "Is \"invert to white not detectd pixels\" option enabled?:#{@with_not_detected_as_white}" p "Percent of dark dots in the matrix: #{percent_calculated}%" p "Percent to consider as a dark area from settings: #{@percent}%" p "Luminance value is: #{@luminance}" p "Is Area Dark?: #{dark}" p "have a look on #{@debug_file_path} file to see your tested area of a blob" if @with_debug_file p '==================================================================================' end dark end |
#magick_pixel(pix, x = nil, y = nil) ⇒ Object
65 66 67 68 69 70 71 |
# File 'lib/is_dark.rb', line 65 def 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) end |
#magick_pixel_from_blob(x, y, blob) ⇒ Object
73 74 75 76 77 |
# File 'lib/is_dark.rb', line 73 def 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 |