Skip to content

Commit 296d1e9

Browse files
authored
Merge pull request #4 from Lyams/add-rubocop
Add rubocop linter and fix styles
2 parents 287941e + 032d085 commit 296d1e9

File tree

9 files changed

+220
-148
lines changed

9 files changed

+220
-148
lines changed

.github/workflows/test.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,6 @@ jobs:
3939

4040
- name: Test
4141
run: bundle exec rspec
42+
43+
- name: Run Rubocop linter
44+
run: bundle exec rubocop

.rubocop.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# .rubocop.yml
2+
3+
AllCops:
4+
NewCops: enable
5+
6+
Naming/MethodParameterName:
7+
Enabled: false
8+
9+
Metrics/ParameterLists:
10+
Enabled: false
11+
12+
Metrics/PerceivedComplexity:
13+
Enabled: false
14+
15+
Metrics/AbcSize:
16+
Enabled: false
17+
18+
Style/OptionalBooleanParameter:
19+
Enabled: false
20+
21+
Metrics/BlockLength:
22+
Enabled: false
23+
24+
Metrics/ClassLength:
25+
Enabled: false
26+
27+
Metrics/CyclomaticComplexity:
28+
Enabled: false
29+
30+
Metrics/MethodLength:
31+
Enabled: false
32+
33+
Naming/VariableNumber:
34+
Enabled: false
35+
36+
Gemspec/DevelopmentDependencies:
37+
EnforcedStyle: gemspec

Gemfile

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
source "https://rubygems.org"
2-
git_source(:github) { |repo| "https://github.com/butteff/is_dark_ruby_gem.git" }
1+
# frozen_string_literal: true
32

4-
gem "rmagick"
3+
source 'https://rubygems.org'
4+
git_source(:github) { |_repo| 'https://github.com/butteff/is_dark_ruby_gem.git' }
55

6-
group :development, :test do
7-
gem "rspec"
8-
gem "minitest"
9-
end
6+
# Specify your gem's dependencies in scenic.gemspec
7+
gemspec

Rakefile

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
require "rake/testtask"
1+
# frozen_string_literal: true
2+
3+
require 'rake/testtask'
24

35
Rake::TestTask.new do |t|
4-
t.libs << "test"
6+
t.libs << 'test'
57
end
68

7-
desc "Run tests"
8-
task default: :test
9+
desc 'Run tests'
10+
task default: :test

is_dark.gemspec

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,27 @@
1+
# frozen_string_literal: true
2+
13
Gem::Specification.new do |s|
2-
s.name = "is_dark"
3-
s.version = "0.1.7"
4-
s.summary = "Detects a dark background under an area or by a color code"
5-
s.description = "Detects a dark color based on luminance W3 standarts ( https://www.w3.org/TR/WCAG20/#relativeluminancedef ). \n\n It has these options: \n * is a hex color dark \n * is an Imagick pixel dark \n * is an Imagick pixel from a blob dark \n * is an area in a blob over a dark background (uses Imagick for it too). \n\n An example practical aspect: it can be useful to understand will a black colored text be visible or not over an area."
6-
s.authors = ["Sergei Illarionov", "Liamshin Ilia"]
7-
s.email = "butteff.ru@gmail.com"
8-
s.files = ["lib/is_dark.rb"]
9-
s.homepage = "https://butteff.ru/en/"
10-
s.post_install_message = "You can find docs about is_dark gem on https://butteff.ru/en/extensions or on https://github.com/butteff/is_dark_ruby_gem"
11-
s.license = "MIT"
12-
s.metadata = { "source_code_uri" => "https://github.com/butteff/is_dark_ruby_gem" }
4+
s.name = 'is_dark'
5+
s.version = '0.1.7'
6+
s.summary = 'Detects a dark background under an area or by a color code'
7+
s.description = 'Detects a dark color based on luminance W3 standarts ' \
8+
"( https://www.w3.org/TR/WCAG20/#relativeluminancedef ). \n\n " \
9+
"It has these options: \n * is a hex color dark \n * is an Imagick " \
10+
"pixel dark \n * is an Imagick pixel from a blob dark \n * is an area " \
11+
"in a blob over a dark background (uses Imagick for it too). \n\n " \
12+
'An example practical aspect: it can be useful to understand will ' \
13+
'a black colored text be visible or not over an area.'
14+
s.authors = ['Sergei Illarionov', 'Liamshin Ilia']
15+
s.email = 'butteff.ru@gmail.com'
16+
s.files = ['lib/is_dark.rb']
17+
s.homepage = 'https://butteff.ru/en/'
18+
s.post_install_message = 'You can find docs about is_dark gem on https://butteff.ru/en/extensions or on https://github.com/butteff/is_dark_ruby_gem'
19+
s.license = 'MIT'
20+
s.metadata = { 'source_code_uri' => 'https://github.com/butteff/is_dark_ruby_gem',
21+
'rubygems_mfa_required' => 'true' }
1322
s.required_ruby_version = '>= 2.7.0'
1423
s.add_dependency 'rmagick', '~> 5.2'
15-
s.add_development_dependency 'rspec', "~> 3.13"
16-
s.add_development_dependency 'minitest', "~> 5.16"
24+
s.add_development_dependency 'minitest', '~> 5.16'
25+
s.add_development_dependency 'rspec', '~> 3.13'
26+
s.add_development_dependency 'rubocop', '~> 1.69'
1727
end

lib/is_dark.rb

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
# frozen_string_literal: true
22

33
require 'rmagick'
4+
5+
# The `Is Dark` class is designed to determine whether a given color or pixel is dark based on luminance
6+
# standards defined by the W3C. It utilizes the `rmagick` library to handle image processing tasks.
7+
# The class includes methods to analyze colors from hexadecimal values, individual pixels,
8+
# and areas within images blobs. It also supports debugging features to visualize the analysis process.
9+
#
10+
# Key features include:
11+
# - **Color Analysis**: Determines if a color is dark based on its luminance.
12+
# - **- **Pixel Analysis**: Analysis individual pixels from an image.
13+
# - **Area Analysis**: Evaluates the darkness of a specified area within an image blob.
14+
# - **Debugging**: Provides options to enable debugging information and visualize the analysis on a PDF file.
415
class IsDark
516
BLUE_LUMINANCE_COEFFICIENT = 0.0722
617
GREEN_LUMINANCE_COEFFICIENT = 0.7152
@@ -27,15 +38,15 @@ class IsDark
2738
def self.color(hex)
2839
@r, @g, @b = hex.match(/^#(..)(..)(..)$/).captures.map(&:hex)
2940
@colorset = MAXIMUM_COLOR_DEPTH
30-
is_dark
41+
dark?
3142
end
3243

3344
def self.magick_pixel(pix, x = nil, y = nil, set_not_detected_light = true)
3445
@r = pix.red.to_f
3546
@g = pix.green.to_f
3647
@b = pix.blue.to_f
3748
@colorset = MAX_COLOR_VALUE
38-
is_dark(x, y, set_not_detected_light)
49+
dark?(x, y, set_not_detected_light)
3950
end
4051

4152
def self.magick_pixel_from_blob(x, y, blob, _set_not_detected_light = true)
@@ -45,14 +56,16 @@ def self.magick_pixel_from_blob(x, y, blob, _set_not_detected_light = true)
4556
end
4657

4758
# (x, y) is the left corner of an element over a blob, height and width is the element's size
48-
def self.magick_area_from_blob(x, y, blob, height, width, percent = 80, range = (0..10), set_not_detected_light = true)
59+
def self.magick_area_from_blob(
60+
x, y, blob, height, width, percent = 80, range = (0..10), set_not_detected_light = true
61+
)
4962
@set_not_detected_light = set_not_detected_light
5063
image = Magick::Image.read(blob).first
5164
dark = false
5265
dots = []
5366
range.each do |xx|
5467
range.each do |yy|
55-
dots << { 'x': (x + width * xx / 10).to_i, 'y': (y + height * yy / 10).to_i }
68+
dots << { x: (x + (width * xx / 10)).to_i, y: (y + (height * yy / 10)).to_i }
5669
end
5770
end
5871

@@ -106,11 +119,12 @@ def self.draw_debug_files(image, x, y, oldx, oldy)
106119
end
107120

108121
# detects a dark color based on luminance W3 standarts ( https://www.w3.org/TR/WCAG20/#relativeluminancedef )
109-
def self.is_dark(x = nil, y = nil, set_not_detected_light = true)
122+
def self.dark?(x = nil, y = nil, set_not_detected_light = true)
110123
dark = false
111124
inverted = false
112125
pixel = [@r.to_f, @g.to_f, @b.to_f]
113-
return true if pixel == [0.00, 0.00, 0.00] #hardcoded exception
126+
return true if pixel == [0.00, 0.00, 0.00] # hardcoded exception
127+
114128
# probably not detected pixel color by Imagick, will be considered as "white" if "set_not_detected_light = true"
115129
if set_not_detected_light && pixel[0] == 0.0 && pixel[1] == 0.0 && pixel[2] == 0.0
116130
pixel = [MAXIMUM_COLOR_DEPTH, MAXIMUM_COLOR_DEPTH, MAXIMUM_COLOR_DEPTH]
@@ -126,12 +140,12 @@ def self.is_dark(x = nil, y = nil, set_not_detected_light = true)
126140
end
127141
calculated << color
128142
end
129-
l = RED_LUMINANCE_COEFFICIENT * calculated[0] +
130-
GREEN_LUMINANCE_COEFFICIENT * calculated[1] +
131-
BLUE_LUMINANCE_COEFFICIENT * calculated[2]
143+
l = (RED_LUMINANCE_COEFFICIENT * calculated[0]) +
144+
(GREEN_LUMINANCE_COEFFICIENT * calculated[1]) +
145+
(BLUE_LUMINANCE_COEFFICIENT * calculated[2])
132146
dark = true if l <= LUMINANCE_THRESHOLD
133147
if @with_debug
134-
debug = { 'X': x, 'Y': y, 'R': @r, 'G': @g, 'B': @b, 'luminance value': l, 'is_dark': dark,
148+
debug = { X: x, Y: y, R: @r, G: @g, B: @b, 'luminance value': l, dark?: dark,
135149
'inverted to white': inverted }
136150
p debug
137151
end

spec/lib/is_dark_spec.rb

Lines changed: 64 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,125 +1,134 @@
1-
require "rmagick"
1+
# frozen_string_literal: true
2+
3+
require 'rmagick'
24
require 'spec_helper'
35
require_relative '../../lib/is_dark'
46

57
TEST_FILE_PATH = 'color_card.pdf'
68

79
describe IsDark do
8-
9-
describe ".color" do
10-
context "dark colors tests" do
11-
it "this color #000000 is dark, returns true" do
10+
describe '.color' do
11+
context 'dark colors tests' do
12+
it 'this color #000000 is dark, returns true' do
1213
expect(IsDark.color('#000000')).to eq(true)
1314
end
1415

15-
it "this color #111111 is dark, returns true" do
16+
it 'this color #111111 is dark, returns true' do
1617
expect(IsDark.color('#111111')).to eq(true)
1718
end
1819

19-
it "this color #102694 is dark, returns true" do
20+
it 'this color #102694 is dark, returns true' do
2021
expect(IsDark.color('#102694')).to eq(true)
2122
end
2223

23-
it "this color #ff2e17 is dark, returns true" do
24+
it 'this color #ff2e17 is dark, returns true' do
2425
expect(IsDark.color('#800f03')).to eq(true)
2526
end
2627
end
2728

28-
context "not dark colors tests" do
29-
it "this color is not dark, returns false" do
29+
context 'not dark colors tests' do
30+
it 'this color is not dark, returns false' do
3031
expect(IsDark.color('#444444')).to eq(false)
3132
end
3233

33-
it "this color is not dark, returns false" do
34+
it 'this color is not dark, returns false' do
3435
expect(IsDark.color('#888888')).to eq(false)
3536
end
3637

37-
it "this color is not dark, returns false" do
38+
it 'this color is not dark, returns false' do
3839
expect(IsDark.color('#ffffff')).to eq(false)
3940
end
4041

41-
it "this color is not dark, returns false" do
42+
it 'this color is not dark, returns false' do
4243
expect(IsDark.color('#fff6b2')).to eq(false)
4344
end
4445
end
4546
end
4647

47-
describe ".magick_pixel_from_blob" do
48-
context "test dark pixel" do
49-
it "this pixel is dark, returns true" do
48+
describe '.magick_pixel_from_blob' do
49+
context 'test dark pixel' do
50+
it 'this pixel is dark, returns true' do
5051
x = 120
5152
y = 120
5253
expect(IsDark.magick_pixel_from_blob(x, y, TEST_FILE_PATH)).to eq(true)
5354
end
5455
end
5556

56-
context "test not dark pixel" do
57-
it "this pixel is not dark, returns false" do
57+
context 'test not dark pixel' do
58+
it 'this pixel is not dark, returns false' do
5859
x = 720
5960
y = 120
6061
expect(IsDark.magick_pixel_from_blob(x, y, TEST_FILE_PATH)).to eq(false)
6162
end
6263
end
6364
end
6465

65-
describe ".magick_pixel" do
66-
context "test dark pixel" do
67-
it "this pixel is dark, returns true" do
66+
describe '.magick_pixel' do
67+
context 'test dark pixel' do
68+
it 'this pixel is dark, returns true' do
6869
image = Magick::Image.read(TEST_FILE_PATH).first
6970
pix = image.pixel_color(80, 320)
7071
expect(IsDark.magick_pixel(pix)).to eq(true)
7172
end
7273
end
7374

74-
context "test not dark pixel" do
75-
it "this pixel is not dark, returns false" do
75+
context 'test not dark pixel' do
76+
it 'this pixel is not dark, returns false' do
7677
image = Magick::Image.read(TEST_FILE_PATH).first
7778
pix = image.pixel_color(720, 120)
7879
expect(IsDark.magick_pixel(pix)).to eq(false)
7980
end
8081
end
8182
end
8283

83-
describe ".magick_area_from_blob" do
84-
context "test dark area" do
85-
it "this area is dark, returns true" do
86-
x = 120 #coordinate of a left corner of the area's rectangle X
87-
y = 120 #coordinate of a left corner of the area's rectangle Y
88-
cf_height = 64 #height of the area's rectangle
89-
cf_width = 128 #height of the area's rectangle
90-
percent = 70 #percent of detected dark pixels to invert
91-
matrix = (1..10) #matrix of dots. Range of matrix to build dots 1..10 - means 10x10
92-
with_not_detected = false #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
93-
expect(IsDark.magick_area_from_blob(x, y, TEST_FILE_PATH, cf_height, cf_width, percent, matrix, with_not_detected)).to eq(false)
84+
describe '.magick_area_from_blob' do
85+
context 'test dark area' do
86+
it 'this area is dark, returns true' do
87+
x = 120 # coordinate of a left corner of the area's rectangle X
88+
y = 120 # coordinate of a left corner of the area's rectangle Y
89+
cf_height = 64 # height of the area's rectangle
90+
cf_width = 128 # height of the area's rectangle
91+
percent = 70 # percent of detected dark pixels to invert
92+
matrix = (1..10) # matrix of dots. Range of matrix to build dots 1..10 - means 10x10
93+
# 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
94+
# option to consider pixels like this as "white", but if you need to disable this option add true or false.
95+
with_not_detected = false
96+
expect(IsDark.magick_area_from_blob(x, y, TEST_FILE_PATH, cf_height, cf_width, percent, matrix,
97+
with_not_detected)).to eq(false)
9498
end
9599
end
96100

97-
context "test bright area" do
98-
it "this area is not dark, returns false" do
99-
x = 720 #coordinate of a left corner of the area's rectangle X
100-
y = 120 #coordinate of a left corner of the area's rectangle Y
101-
cf_height = 64 #height of the area's rectangle
102-
cf_width = 128 #height of the area's rectangle
103-
percent = 70 #percent of detected dark pixels to invert
104-
matrix = (1..10) #matrix of dots. Range of matrix to build dots 1..10 - means 10x10
105-
with_not_detected = false #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
106-
expect(IsDark.magick_area_from_blob(x, y, TEST_FILE_PATH, cf_height, cf_width, percent, matrix, with_not_detected)).to eq(false)
101+
context 'test bright area' do
102+
it 'this area is not dark, returns false' do
103+
x = 720 # coordinate of a left corner of the area's rectangle X
104+
y = 120 # coordinate of a left corner of the area's rectangle Y
105+
cf_height = 64 # height of the area's rectangle
106+
cf_width = 128 # height of the area's rectangle
107+
percent = 70 # percent of detected dark pixels to invert
108+
matrix = (1..10) # matrix of dots. Range of matrix to build dots 1..10 - means 10x10
109+
# Sometimes Imagick can't detect a pixel or it has no color, so it detects it as (RGB: 0,0,0), the gem has
110+
# an option to consider pixels like this as "white", but if you need to disable this option add true or false.
111+
with_not_detected = false
112+
expect(IsDark.magick_area_from_blob(x, y, TEST_FILE_PATH, cf_height, cf_width, percent, matrix,
113+
with_not_detected)).to eq(false)
107114
end
108115
end
109116

110-
context "test debug output" do
111-
it "test area with logs and debug file" do
112-
x = 120 #coordinate of a left corner of the area's rectangle X
113-
y = 120 #coordinate of a left corner of the area's rectangle Y
114-
cf_height = 64 #height of the area's rectangle
115-
cf_width = 128 #height of the area's rectangle
116-
percent = 70 #percent of detected dark pixels to invert
117-
matrix = (1..10) #matrix of dots. Range of matrix to build dots 1..10 - means 10x10
118-
with_not_detected = false #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
117+
context 'test debug output' do
118+
it 'test area with logs and debug file' do
119+
x = 120 # coordinate of a left corner of the area's rectangle X
120+
y = 120 # coordinate of a left corner of the area's rectangle Y
121+
cf_height = 64 # height of the area's rectangle
122+
cf_width = 128 # height of the area's rectangle
123+
percent = 70 # percent of detected dark pixels to invert
124+
matrix = (1..10) # matrix of dots. Range of matrix to build dots 1..10 - means 10x10
125+
# Sometimes Imagick can't detect a pixel or it has no color, so it detects it as (RGB: 0,0,0), the gem has
126+
# an option to consider pixels like this as "white", but if you need to disable this option add true or false.
127+
with_not_detected = false
119128
IsDark.set_debug_data(true, './is_dark_debug_output.pdf')
120-
expect(IsDark.magick_area_from_blob(x, y, TEST_FILE_PATH, cf_height, cf_width, percent, matrix, with_not_detected)).to eq(false)
129+
expect(IsDark.magick_area_from_blob(x, y, TEST_FILE_PATH, cf_height, cf_width, percent, matrix,
130+
with_not_detected)).to eq(false)
121131
end
122132
end
123133
end
124-
125134
end

0 commit comments

Comments
 (0)