Skip to content

Commit

Permalink
Instance way of a gem use + docs
Browse files Browse the repository at this point in the history
  • Loading branch information
butteff committed Dec 30, 2024
1 parent 01d718a commit ff2ac00
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 112 deletions.
37 changes: 26 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.9'`
`gem 'is_dark', '~> 0.2.0'`

Install:
`gem install is_dark`
Expand All @@ -23,36 +23,51 @@ Install:
1. Declare a lib:
`require 'is_dark'`

2. Make an instance:
`is_dark = IsDark.new`

2. Is Hex color dark:
`IsDark.color('#ffffff') => false`
`is_dark.color('#ffffff') => false`

3. is Imagick pixel dark:
`IsDark.magick_pixel(pix)`
`is_dark.magick_pixel(pix)`

4. is Imagick pixel from a blob dark by coordinates:
`IsDark.magick_pixel_from_blob(x, y, blob)`
`is_dark.magick_pixel_from_blob(x, y, blob)`

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
`is_dark.magick_area_from_blob(x, y, blob, height, width)` #standart default settings

#### 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.
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 during your tests. You can also set some other values and calibrate results as you need. You can just initialize an instance with these settings or update an existed one:

```ruby
IsDark.configure({
params = {
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
})
debug_file_path: debug_file_path, #path of the file with a drawn area
luminance: 0.05 # all pixels are dark if their luminance is lower, that this value
}
is_dark = IsDark.new(params) #to generate new Instance
#or
is_dark.configure(params) #to update existed instance

```

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
`is_dark.magick_area_from_blob(x, y, blob, height, width)`, so it will show a debug info with a generated file like in the video at the top of this documentation.

###### Deep Settings:

You can calibrate it more deep, change constants for it inside lib/is_dark.rb file, but the most powerful parameter to calibrate in case of a not valid dark area detection is about luminance value, it is open to change this value from settings params, it is already described in the message above.

#### Unit Tests:

- `rspec` #rspec tests with a generated debug file

- `rake test` #minitest based unit tests (low amount of tests)
#### Old versions:

Old versions of the gem are about static methods only, you can find old documentation about it all in [README_old.md file]( https://github.com/butteff/is_dark_ruby_gem/blob/main/README_old.md "README_old.md file")
58 changes: 58 additions & 0 deletions README_old.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# 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/430cd789-1b5d-42a0-ae6e-c8b5f1da694b

#### Can detect:
* is a hex color dark
* is an Imagick pixel dark
* is an Imagick pixel from a blob dark
* is an area in a blob over a dark background (uses Imagick for it too).
.
An example practical aspect: it can be useful to understand will a black colored text be visible or not over an area.

#### How to Install:

Gemfile:
`gem 'is_dark', '~> 0.1.9'`

Install:
`gem install is_dark`

#### How to use:
1. Declare a lib:
`require 'is_dark'`

2. Is Hex color dark:
`IsDark.color('#ffffff') => false`

3. is Imagick pixel dark:
`IsDark.magick_pixel(pix)`

4. is Imagick pixel from a blob dark by coordinates:
`IsDark.magick_pixel_from_blob(x, y, blob)`

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

#### 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:

- `rspec` #rspec tests with a generated debug file

- `rake test` #minitest based unit tests (low amount of tests)
10 changes: 0 additions & 10 deletions Rakefile

This file was deleted.

2 changes: 1 addition & 1 deletion is_dark.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Gem::Specification.new do |s|
s.name = 'is_dark'
s.version = '0.1.9'
s.version = '0.2.0'
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 " \
Expand Down
27 changes: 17 additions & 10 deletions lib/is_dark.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,42 +36,48 @@ class IsDark
@colorset = MAXIMUM_COLOR_DEPTH
@percent = DEFAULT_PERCENT_OF_DOTS
@matrix = DEFAULT_MATRIX_RANGE
@luminance = LUMINANCE_THRESHOLD
@with_not_detected_as_white = true
@with_debug = false
@with_debug_file = false
@debug_file_path = DEFAULT_DEBUG_FILE_PATH

def self.configure(settings)
def initialize(settings = {})
configure(settings)
end

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

def self.color(hex)
def color(hex)
@r, @g, @b = hex.match(/^#(..)(..)(..)$/).captures.map(&:hex)
@colorset = MAXIMUM_COLOR_DEPTH
dark?
end

def self.magick_pixel(pix, x = nil, y = nil)
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

def self.magick_pixel_from_blob(x, y, blob)
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

# (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)
def magick_area_from_blob(x, y, blob, height, width)
image = Magick::Image.read(blob).first
dark = false
dots = []
Expand Down Expand Up @@ -104,15 +110,16 @@ def self.magick_area_from_blob(x, y, blob, height, width)
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 "Signature will be inverted if #{@percent}% of dots will be dark"
p "Is inverted?: #{dark}"
p "Percent of dark dots in the matrix: #{@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"
p '=================================================================================='
end
dark
end

def self.draw_debug_files(image, x, y, old_x, old_y)
def draw_debug_files(image, x, y, old_x, old_y)
return unless old_x && old_y

gc = Magick::Draw.new
Expand All @@ -123,7 +130,7 @@ def self.draw_debug_files(image, x, y, old_x, old_y)
end

# detects a dark color based on luminance W3 standarts ( https://www.w3.org/TR/WCAG20/#relativeluminancedef )
def self.dark?(x = nil, y = nil)
def dark?(x = nil, y = nil)
dark = false
inverted = false
pixel = [@r.to_f, @g.to_f, @b.to_f]
Expand All @@ -146,7 +153,7 @@ def self.dark?(x = nil, y = nil)
l = (RED_LUMINANCE_COEFFICIENT * calculated[0]) +
(GREEN_LUMINANCE_COEFFICIENT * calculated[1]) +
(BLUE_LUMINANCE_COEFFICIENT * calculated[2])
dark = true if l <= LUMINANCE_THRESHOLD
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 }
Expand Down
68 changes: 38 additions & 30 deletions spec/lib/is_dark_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,37 +10,45 @@
describe '.color' do
context 'dark colors tests' do
it 'this color #000000 is dark, returns true' do
expect(IsDark.color('#000000')).to eq(true)
is_dark = IsDark.new
expect(is_dark.color('#000000')).to eq(true)
end

it 'this color #111111 is dark, returns true' do
expect(IsDark.color('#111111')).to eq(true)
is_dark = IsDark.new
expect(is_dark.color('#111111')).to eq(true)
end

it 'this color #102694 is dark, returns true' do
expect(IsDark.color('#102694')).to eq(true)
is_dark = IsDark.new
expect(is_dark.color('#102694')).to eq(true)
end

it 'this color #ff2e17 is dark, returns true' do
expect(IsDark.color('#800f03')).to eq(true)
is_dark = IsDark.new
expect(is_dark.color('#800f03')).to eq(true)
end
end

context 'not dark colors tests' do
it 'this color is not dark, returns false' do
expect(IsDark.color('#444444')).to eq(false)
is_dark = IsDark.new
expect(is_dark.color('#444444')).to eq(false)
end

it 'this color is not dark, returns false' do
expect(IsDark.color('#888888')).to eq(false)
is_dark = IsDark.new
expect(is_dark.color('#888888')).to eq(false)
end

it 'this color is not dark, returns false' do
expect(IsDark.color('#ffffff')).to eq(false)
is_dark = IsDark.new
expect(is_dark.color('#ffffff')).to eq(false)
end

it 'this color is not dark, returns false' do
expect(IsDark.color('#fff6b2')).to eq(false)
is_dark = IsDark.new
expect(is_dark.color('#fff6b2')).to eq(false)
end
end
end
Expand All @@ -50,15 +58,17 @@
it 'this pixel is dark, returns true' do
x = 120
y = 120
expect(IsDark.magick_pixel_from_blob(x, y, TEST_FILE_PATH)).to eq(true)
is_dark = IsDark.new
expect(is_dark.magick_pixel_from_blob(x, y, TEST_FILE_PATH)).to eq(true)
end
end

context 'test not dark pixel' do
it 'this pixel is not dark, returns false' do
x = 720
y = 120
expect(IsDark.magick_pixel_from_blob(x, y, TEST_FILE_PATH)).to eq(false)
is_dark = IsDark.new
expect(is_dark.magick_pixel_from_blob(x, y, TEST_FILE_PATH)).to eq(false)
end
end
end
Expand All @@ -68,15 +78,17 @@
it 'this pixel is dark, returns true' do
image = Magick::Image.read(TEST_FILE_PATH).first
pix = image.pixel_color(80, 320)
expect(IsDark.magick_pixel(pix)).to eq(true)
is_dark = IsDark.new
expect(is_dark.magick_pixel(pix)).to eq(true)
end
end

context 'test not dark pixel' do
it 'this pixel is not dark, returns false' do
image = Magick::Image.read(TEST_FILE_PATH).first
pix = image.pixel_color(720, 120)
expect(IsDark.magick_pixel(pix)).to eq(false)
is_dark = IsDark.new
expect(is_dark.magick_pixel(pix)).to eq(false)
end
end
end
Expand All @@ -88,7 +100,8 @@
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
expect(IsDark.magick_area_from_blob(x, y, TEST_FILE_PATH, cf_height, cf_width)).to eq(false)
is_dark = IsDark.new
expect(is_dark.magick_area_from_blob(x, y, TEST_FILE_PATH, cf_height, cf_width)).to eq(false)
end
end

Expand All @@ -98,7 +111,8 @@
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
expect(IsDark.magick_area_from_blob(x, y, TEST_FILE_PATH, cf_height, cf_width)).to eq(false)
is_dark = IsDark.new
expect(is_dark.magick_area_from_blob(x, y, TEST_FILE_PATH, cf_height, cf_width)).to eq(false)
end
end

Expand All @@ -108,22 +122,16 @@
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 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:
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)
params = {
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,
with_not_detected_as_white: true, # to mark not detected pixels as white
with_debug: true, # to show debug output
with_debug_file: true, # to generate debug file to show a tested area
debug_file_path: './is_dark_debug_file.pdf' # to show file path
}
is_dark = IsDark.new(params)
expect(is_dark.magick_area_from_blob(x, y, TEST_FILE_PATH, cf_height, cf_width)).to eq(false)
end
end
end
Expand Down
Loading

0 comments on commit ff2ac00

Please sign in to comment.