Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
2
21_22-J-02
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
21_22-J-02
21_22-J-02
Commits
aa7a7fdb
Commit
aa7a7fdb
authored
Jan 04, 2022
by
Chathurdi Vibhuda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat:color detection backend files.
parent
d833a8e6
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
1939 additions
and
0 deletions
+1939
-0
BE-Aeasthatic-Quality-Check/colorcube-master/assets/js/colorcube.js
...tic-Quality-Check/colorcube-master/assets/js/colorcube.js
+347
-0
BE-Aeasthatic-Quality-Check/colorcube-master/assets/js/detection.js
...tic-Quality-Check/colorcube-master/assets/js/detection.js
+397
-0
BE-Aeasthatic-Quality-Check/colorcube-master/assets/js/tinycolor.js
...tic-Quality-Check/colorcube-master/assets/js/tinycolor.js
+1195
-0
No files found.
BE-Aeasthatic-Quality-Check/colorcube-master/assets/js/colorcube.js
0 → 100644
View file @
aa7a7fdb
const
AAANORMALRATIO
=
7.0
;
const
AANORMALRATIO
=
4.5
;
const
AALARGERATIO
=
3.0
;
var
colorArray
=
[];
// Decimal Rounding: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
(
function
()
{
/**
* Decimal adjustment of a number.
*
* @param {String} type The type of adjustment.
* @param {Number} value The number.
* @param {Integer} exp The exponent (the 10 logarithm of the adjustment base).
* @returns {Number} The adjusted value.
*/
function
decimalAdjust
(
type
,
value
,
exp
)
{
// If the exp is undefined or zero...
if
(
typeof
exp
===
'
undefined
'
||
+
exp
===
0
)
{
return
Math
[
type
](
value
);
}
value
=
+
value
;
exp
=
+
exp
;
// If the value is not a number or the exp is not an integer...
if
(
isNaN
(
value
)
||
!
(
typeof
exp
===
'
number
'
&&
exp
%
1
===
0
))
{
return
NaN
;
}
// If the value is negative...
if
(
value
<
0
)
{
return
-
decimalAdjust
(
type
,
-
value
,
exp
);
}
// Shift
value
=
value
.
toString
().
split
(
'
e
'
);
value
=
Math
[
type
](
+
(
value
[
0
]
+
'
e
'
+
(
value
[
1
]
?
(
+
value
[
1
]
-
exp
)
:
-
exp
)));
// Shift back
value
=
value
.
toString
().
split
(
'
e
'
);
return
+
(
value
[
0
]
+
'
e
'
+
(
value
[
1
]
?
(
+
value
[
1
]
+
exp
)
:
exp
));
}
// Decimal round
if
(
!
Math
.
round10
)
{
Math
.
round10
=
function
(
value
,
exp
)
{
return
decimalAdjust
(
'
round
'
,
value
,
exp
);
};
}
// Decimal floor
if
(
!
Math
.
floor10
)
{
Math
.
floor10
=
function
(
value
,
exp
)
{
return
decimalAdjust
(
'
floor
'
,
value
,
exp
);
};
}
// Decimal ceil
if
(
!
Math
.
ceil10
)
{
Math
.
ceil10
=
function
(
value
,
exp
)
{
return
decimalAdjust
(
'
ceil
'
,
value
,
exp
);
};
}
})();
function
round
(
number
)
{
return
Math
.
round
(
number
);
}
// Preserves a place after the decimal
function
round2places
(
number
)
{
return
(
Math
.
round
(
number
*
100
)
/
100
).
toFixed
(
2
);
}
function
decimalToPercent
(
number
)
{
return
Math
.
round
(
number
*
100
);
}
function
getRoundedRatio
(
color1
,
color2
)
{
var
ratio
=
tinycolor
.
readability
(
color1
,
color2
);
return
round2places
(
ratio
);
}
function
outputRatio
(
color
,
ratio
,
bg
,
target
,
editable
,
iterator
)
{
// Default values: AA normal and AAA large with failing grades
var
color
=
tinycolor
(
color
),
hex
=
color
.
toHexString
(),
background
=
tinycolor
(
bg
),
bghex
=
background
.
toHexString
(),
passfail
=
'
fail
'
,
output
=
''
,
targetclass
=
'
target-45
'
,
icontent
=
'
✘
'
,
// x mark
swatchcontent
=
'
<p class="level--AA">AA</p><span class="level--AAAplus">AAA</span> 24px
'
,
difference
=
0
;
// Check for passing grades
if
(
ratio
>=
(
target
+
0.5
)
)
{
// It passes if the ratio is greater than our constant plus 0.5 for gamma correction
passfail
=
'
pass
'
;
icontent
=
'
✔
'
;
// check mark
}
else
if
(
ratio
<=
(
target
+
0.5
)
&&
ratio
>
target
)
{
// It barely passes if the ratio is less than our constant plus 0.5 for gamma correction
// AND greater than the constant. So, within 0.5.
passfail
=
'
edge
'
;
icontent
=
'
✔
'
;
// ‼ double exclamation
}
// Check target ratios
if
(
target
==
AAANORMALRATIO
)
{
targetclass
=
'
target-7
'
swatchcontent
=
'
<p class="level--AAA">AAA</p>
'
;
}
if
(
target
==
AALARGERATIO
)
{
targetclass
=
'
target-3
'
swatchcontent
=
'
<span class="level--AAplus">AA</span> 24px
'
;
}
difference
=
round2places
(
(
ratio
-
target
),
-
1
);
if
(
editable
===
true
)
{
var
output
=
`<div class="color-ratio__wrapper
${
targetclass
}
${
passfail
}
" title="Criteria needed minimum
${
target
}
">
<p class="color-ratio__label"><strong>
${
ratio
}
</strong>: with <input class="cc__form__input adjust-custom" id="test-color-
${
iterator
}
" name="test-color-
${
iterator
}
" type="text" value="
${
hex
}
" data-target="
${
iterator
}
" data-color="
${
bghex
}
" /></p>
<div class="color-ratio__swatch color-ratio-swatch-
${
iterator
}
" style="color:
${
bghex
}
; border-color:
${
bghex
}
; background-color:
${
hex
}
;">
${
swatchcontent
}
</div>
<p class="color-ratio__results">
<span class="icon">
${
icontent
}
</span>
<span class="color-ratio__passfail">
<b>
${
passfail
}
</b>
${
difference
}
</span>
</p>
</div>`
;
}
else
{
var
output
=
`<div class="color-ratio__wrapper
${
targetclass
}
${
passfail
}
" title="Criteria needed minimum
${
target
}
">
<p class="color-ratio__label"><strong>
${
ratio
}
</strong>: with
${
bghex
}
</p>
<div class="color-ratio__swatch" style="color:
${
bghex
}
; border-color:
${
bghex
}
; background-color:
${
hex
}
;">
${
swatchcontent
}
</div>
<p class="color-ratio__results">
<span class="icon">
${
icontent
}
</span>
<span class="color-ratio__passfail">
<b>
${
passfail
}
</b>
${
difference
}
</span>
</p>
</div>`
;
}
return
output
;
}
function
outputAllRatios
(
color
,
light
,
dark
)
{
var
ratio_onlight
=
getRoundedRatio
(
color
,
light
),
ratio_ondark
=
getRoundedRatio
(
color
,
dark
),
results
=
""
;
results
=
`<div class="results__col ratios__on-light">
${
outputRatio
(
color
,
ratio_onlight
,
light
,
AAANORMALRATIO
)}
${
outputRatio
(
color
,
ratio_onlight
,
light
,
AANORMALRATIO
)}
${
outputRatio
(
color
,
ratio_onlight
,
light
,
AALARGERATIO
)}
</div>
<div class="results__col ratios__on-dark">
${
outputRatio
(
color
,
ratio_ondark
,
dark
,
AAANORMALRATIO
)}
${
outputRatio
(
color
,
ratio_ondark
,
dark
,
AANORMALRATIO
)}
${
outputRatio
(
color
,
ratio_ondark
,
dark
,
AALARGERATIO
)}
</div>`
;
return
results
;
}
function
outputCustomRatios
(
color
,
ratio
,
bg
,
iterator
)
{
var
results
=
outputRatio
(
color
,
ratio
,
bg
,
AAANORMALRATIO
,
true
,
iterator
);
results
=
results
+
outputRatio
(
color
,
ratio
,
bg
,
AANORMALRATIO
,
true
,
iterator
);
results
=
results
+
outputRatio
(
color
,
ratio
,
bg
,
AALARGERATIO
,
true
,
iterator
);
return
results
;
}
var
button
=
document
.
querySelector
(
'
#brand-color-button
'
);
button
.
onclick
=
function
(
e
)
{
e
.
preventDefault
();
var
resultsBlock
=
document
.
getElementById
(
'
results-content
'
),
results
=
document
.
getElementById
(
'
results-output
'
),
white
=
tinycolor
(
document
.
querySelector
(
'
#white-value
'
).
value
),
black
=
tinycolor
(
document
.
querySelector
(
'
#black-value
'
).
value
);
// if there are already results displayed, clear them
if
(
results
.
children
.
length
>
1
)
{
results
.
innerHTML
=
''
;
}
// Set the header row
results
.
innerHTML
=
`<div class="results__row results__row__header">
<div class="results__col ratios__original">Original</div>
<div class="results__col ratios__mod"><b>Modify</b></div>
<div class="results__col ratios__on-light">With light</div>
<div class="results__col ratios__on-dark">With dark</div>
<div class="results__col ratios__custom">Most legible or Custom</div>
</div>`
;
// var ids = ['ts0', 'ts1', 'ts2'];
// for(var i = 0; i < ids.length; i++) {
// document.getElementById(ids[i]).value = document.getElementById('merged').value;
// }
// get the colors inputted by the user
var
stringInput
=
document
.
querySelector
(
'
#txtArea
'
).
value
;
// if there's no input, get outta here
if
(
stringInput
==
''
)
{
return
;
}
// turn it into an array
colorArray
=
stringInput
.
split
(
"
\n
"
);
for
(
var
i
=
0
;
i
<
colorArray
.
length
;
i
++
)
{
// get the color's contrast ratios
var
most_legible
=
tinycolor
.
mostReadable
(
colorArray
[
i
],
colorArray
),
ratio_mostlegible
=
getRoundedRatio
(
most_legible
,
colorArray
[
i
]),
color
=
tinycolor
(
colorArray
[
i
]),
hex
=
color
.
toHex
(),
hashhex
=
color
.
toHexString
(),
hslColor
=
color
.
toHsl
();
// outputRatio( {color & border color}, ratio, {background color}, {ratio to test against} )
results
.
innerHTML
+=
`<div class="results__row">
<div class="results__col ratios__original">
<p class="original__label">
${
hashhex
}
</p>
<div class="original__hsl">
<p title="Hue"><b>H:</b>
${
round
(
hslColor
.
h
)}
</p>
<p title="Saturation"><b>S:</b>
${
decimalToPercent
(
hslColor
.
s
)}
</p>
<p title="Lightness"><b>L:</b>
${
decimalToPercent
(
hslColor
.
l
)}
</p>
</div>
<div class="original__swatch" style="background-color:
${
hashhex
}
;"></div>
</div>
<div class="results__col ratios__mod">
<p class="mod__label mod-label-
${
i
}
">
${
hashhex
}
</p>
<div class="mod__swatch mod-swatch-
${
i
}
" style="background-color:
${
hashhex
}
;"></div>
<div class="mod__controls">
<p class="mod__hue"><label for="adjust-hue-
${
i
}
">H</label><input type="number" class="cc__form__input adjust-hue" data-target="
${
i
}
" data-color="
${
hex
}
" id="adjust-hue-
${
i
}
" name="adjust-hue-
${
i
}
" value="
${
round
(
hslColor
.
h
)}
" min="0" max="360" /></p>
<p class="mod__saturation"><label for="adjust-sat-
${
i
}
">S</label><input type="number" class="cc__form__input adjust-sat" data-target="
${
i
}
" data-color="
${
hex
}
" id="adjust-sat-
${
i
}
" name="adjust-sat-
${
i
}
" value="
${
decimalToPercent
(
hslColor
.
s
)}
" min="0" max="100" /></p>
<p class="mod__lightness"><label for="adjust-lig-
${
i
}
">L</label><input type="number" class="cc__form__input adjust-lig" data-target="
${
i
}
" data-color="
${
hex
}
" id="adjust-lig-
${
i
}
" name="adjust-lig-
${
i
}
" value="
${
decimalToPercent
(
hslColor
.
l
)}
" min="0" max="100" /></p>
</div>
</div>
<div class="results__row">
<div id="row-
${
i
}
" class="results__row">
${
outputAllRatios
(
colorArray
[
i
],
white
,
black
)}
</div>
<div id="custom-pair-
${
i
}
" class="results__col ratios__custom">
${
outputCustomRatios
(
most_legible
,
ratio_mostlegible
,
colorArray
[
i
],
i
)}
</div>
</div>
</div>`
;
}
// make the results content visible
resultsBlock
.
style
.
display
=
'
block
'
;
resultsBlock
.
style
.
visibility
=
'
visible
'
;
// jump to the results
window
.
location
.
href
=
'
#results-content
'
;
}
// Adjust Hue, Saturation, or Lightness
$
(
document
).
on
(
"
change paste keyup blur
"
,
"
.adjust-hue, .adjust-sat, .adjust-lig
"
,
function
()
{
var
target
=
$
(
this
).
data
(
"
target
"
),
color
=
$
(
this
).
data
(
"
color
"
),
newValue
=
$
(
this
).
val
(),
originalColor
=
tinycolor
(
color
).
toHsl
(),
newColorHSL
=
''
;
// Adjust the color based on the class of the input
if
(
$
(
this
).
hasClass
(
'
adjust-hue
'
)
)
{
newColorHSL
=
tinycolor
(
"
hsl(
"
+
newValue
+
"
,
"
+
originalColor
.
s
+
"
,
"
+
originalColor
.
l
+
"
)
"
);
}
else
if
(
$
(
this
).
hasClass
(
'
adjust-sat
'
)
)
{
newColorHSL
=
tinycolor
(
"
hsl(
"
+
originalColor
.
h
+
"
,
"
+
newValue
+
"
,
"
+
originalColor
.
l
+
"
)
"
);
}
else
{
newColorHSL
=
tinycolor
(
"
hsl(
"
+
originalColor
.
h
+
"
,
"
+
originalColor
.
s
+
"
,
"
+
newValue
+
"
)
"
);
}
var
newColorRAW
=
newColorHSL
.
toHex
(),
newColor
=
newColorHSL
.
toHexString
(),
targetSwatch
=
$
(
'
.mod-swatch-
'
+
target
),
targetContainer
=
$
(
'
#row-
'
+
target
),
customContainer
=
$
(
'
#custom-pair-
'
+
target
),
white
=
tinycolor
(
document
.
querySelector
(
'
#white-value
'
).
value
),
black
=
tinycolor
(
document
.
querySelector
(
'
#black-value
'
).
value
),
custom
=
tinycolor
(
document
.
querySelector
(
'
#test-color-
'
+
target
).
value
),
ratio_custom
=
getRoundedRatio
(
custom
,
newColor
);
// Change the starting color on the inputs, stored in data-color
var
inputs
=
$
(
"
input[data-target=
"
+
target
+
"
]
"
);
inputs
.
each
(
function
()
{
$
(
this
).
data
(
'
color
'
,
newColorRAW
);
});
$
(
'
.mod-label-
'
+
target
).
html
(
newColor
);
// Change the swatch
targetSwatch
.
css
(
"
background-color
"
,
newColor
);
// Change the contents of the light/dark outputs
//console.log(newColor);
targetContainer
.
html
(
''
);
targetContainer
.
html
(
outputAllRatios
(
newColor
,
white
,
black
));
// Change the contents of the Custom column
customContainer
.
html
(
''
);
customContainer
.
html
(
outputCustomRatios
(
custom
,
ratio_custom
,
newColor
,
target
));
});
// If a custom color is supplied, redo the custom color test
$
(
document
).
on
(
"
blur
"
,
"
.adjust-custom
"
,
function
()
{
var
target
=
$
(
this
).
data
(
"
target
"
),
color
=
tinycolor
(
$
(
this
).
data
(
"
color
"
)),
newColor
=
tinycolor
(
$
(
this
).
val
()),
ratio_custom
=
getRoundedRatio
(
color
,
newColor
),
customContainer
=
$
(
'
#custom-pair-
'
+
target
);
// Change the contents of the Custom column
customContainer
.
html
(
''
);
customContainer
.
html
(
outputCustomRatios
(
newColor
,
ratio_custom
,
color
,
target
));
});
$
(
function
()
{
var
arrInitial
;
$
(
"
.inputField
"
).
on
(
'
focus
'
,
function
()
{
arrInitial
=
[];
$
(
"
.inputField
"
).
each
(
function
()
{
arrInitial
.
push
(
$
(
this
).
val
());
})
});
$
(
"
.inputField
"
).
on
(
'
blur
'
,
function
()
{
//If text area is blank then update all input values
if
(
$
.
trim
(
$
(
"
#txtArea
"
).
val
())
===
""
)
{
var
inputValues
=
""
;
$
(
"
.inputField
"
).
each
(
function
()
{
inputValues
+=
"
\n
"
+
$
(
this
).
val
();
})
$
(
"
#txtArea
"
).
val
(
$
.
trim
(
inputValues
));
}
else
{
//Get existing values from text area and split by " "
var
arrData
=
$
(
"
#txtArea
"
).
val
().
split
(
"
"
);
var
arr
=
arrData
.
filter
(
function
(
v
){
return
v
!==
''
});
var
arrNew
=
[];
$
(
"
.inputField
"
).
each
(
function
(
i
)
{
if
(
arr
[
i
]
===
arrInitial
[
i
])
//Check against initial values in text fields
arrNew
.
push
(
$
.
trim
(
$
(
this
).
val
()));
else
arrNew
.
push
(
arr
[
i
]);
});
$
(
"
#txtArea
"
).
val
(
arrNew
.
join
(
"
"
));
}
})
});
BE-Aeasthatic-Quality-Check/colorcube-master/assets/js/detection.js
0 → 100644
View file @
aa7a7fdb
/**
* @author Cassidy Williams
*/
/*
*
* This is for uploading files to the page, standard HTML5 jazz.
*
* */
function
handleFileSelect
(
evt
)
{
var
files
=
evt
.
target
.
files
;
// Loop through the FileList and render image files as thumbnails
for
(
var
i
=
0
,
f
;
f
=
files
[
i
];
i
++
)
{
// Only process image files
if
(
!
f
.
type
.
match
(
'
image.*
'
))
{
continue
;
}
var
reader
=
new
FileReader
();
// Capture the file info
reader
.
onload
=
(
function
(
theFile
)
{
return
function
(
e
)
{
// Render thumbnail.
var
span
=
document
.
createElement
(
'
span
'
);
span
.
innerHTML
=
[
'
<img class="thumb" onclick="javascript:analyze(this, event);" src="
'
,
e
.
target
.
result
,
'
" title="
'
,
escape
(
theFile
.
name
),
'
"/>
'
].
join
(
''
);
document
.
getElementById
(
'
list
'
).
insertBefore
(
span
,
null
);
};
})(
f
);
// Read the image file as data URL
reader
.
readAsDataURL
(
f
);
}
var
message
=
document
.
getElementById
(
'
message
'
);
message
.
innerHTML
=
'
Click any image to get theme colors!
'
;
}
/*
* This portion was created by referencing the article
* "Using python and k-means to find the dominant colors in images"
* By Charles Leifer
* */
// You can see the Python version of this in Charles Leifer's article
function
euclidean
(
point1
,
point2
)
{
var
s
=
0
;
for
(
var
i
=
0
,
l
=
point1
.
length
;
i
<
l
;
i
++
)
{
s
+=
Math
.
pow
(
point1
[
i
]
-
point2
[
i
],
2
)
}
return
Math
.
sqrt
(
s
);
}
// There are various ways to convert rgb to hex, I found this on Stack Overflow.
function
rgbToHex
(
rgb
)
{
function
toHex
(
c
)
{
var
hex
=
parseInt
(
c
).
toString
(
16
);
return
hex
.
length
==
1
?
'
0
'
+
hex
:
hex
;
}
return
'
#
'
+
toHex
(
rgb
[
0
])
+
toHex
(
rgb
[
1
])
+
toHex
(
rgb
[
2
]);
}
function
calculateCenter
(
points
,
n
)
{
var
values
=
[]
// Here we're populating the values array with 0s just so we know what size it should be (n)
for
(
var
i
=
0
;
i
<
n
;
i
++
)
{
values
.
push
(
0
);
}
var
plength
=
0
;
for
(
var
i
=
0
,
l
=
points
.
length
;
i
<
l
;
i
++
)
{
plength
++
;
for
(
var
j
=
0
;
j
<
n
;
j
++
)
{
values
[
j
]
+=
points
[
i
][
j
];
}
}
// Using the average to get the centers
for
(
var
i
=
0
;
i
<
n
;
i
++
)
{
values
[
i
]
=
values
[
i
]
/
plength
;
}
return
values
;
}
// I basically just took this from Charles Leifer.
function
k_mean
(
points
,
k
,
min_diff
)
{
plength
=
points
.
length
;
colorGroup
=
[];
seen
=
[];
while
(
colorGroup
.
length
<
k
)
{
idx
=
parseInt
(
Math
.
random
()
*
plength
);
found
=
false
;
for
(
var
i
=
0
;
i
<
seen
.
length
;
i
++
)
{
if
(
idx
===
seen
[
i
])
{
found
=
true
;
break
;
}
}
if
(
!
found
)
{
seen
.
push
(
idx
);
colorGroup
.
push
([
points
[
idx
],
[
points
[
idx
]]]);
}
}
while
(
true
)
{
plists
=
[];
for
(
var
i
=
0
;
i
<
k
;
i
++
)
{
plists
.
push
([]);
}
for
(
var
j
=
0
;
j
<
plength
;
j
++
)
{
var
p
=
points
[
j
],
smallest_distance
=
10000000
,
idx
=
0
;
for
(
var
i
=
0
;
i
<
k
;
i
++
)
{
var
distance
=
euclidean
(
p
,
colorGroup
[
i
][
0
]);
if
(
distance
<
smallest_distance
)
{
smallest_distance
=
distance
;
idx
=
i
;
}
}
plists
[
idx
].
push
(
p
);
}
var
diff
=
0
;
for
(
var
i
=
0
;
i
<
k
;
i
++
)
{
var
old
=
colorGroup
[
i
],
list
=
plists
[
i
],
center
=
calculateCenter
(
plists
[
i
],
3
),
new_cluster
=
[
center
,
(
plists
[
i
])],
dist
=
euclidean
(
old
[
0
],
center
);
colorGroup
[
i
]
=
new_cluster
diff
=
diff
>
dist
?
diff
:
dist
;
}
if
(
diff
<
min_diff
)
{
break
;
}
}
return
colorGroup
;
}
// Here's where we to actual interaction with the webpage
function
processimg
(
img
,
canvaselement
)
{
var
points
=
[];
// Drawing the given image onto a canvas 250x250 in size
canvaselement
.
drawImage
(
img
,
0
,
0
,
250
,
250
);
// Getting data from said canvas. This *DOES* get every pixel in the image.
// Luckily, it's fast.
dataCanvas
=
canvaselement
.
getImageData
(
0
,
0
,
250
,
250
).
data
;
// Populating the points array with colors from the image
for
(
var
i
=
0
,
l
=
dataCanvas
.
length
;
i
<
l
;
i
+=
4
)
{
var
r
=
dataCanvas
[
i
],
g
=
dataCanvas
[
i
+
1
],
b
=
dataCanvas
[
i
+
2
];
points
.
push
([
r
,
g
,
b
]);
}
var
totals
=
k_mean
(
points
,
3
,
1
),
hex
=
[];
// If you try and convert the RGB to Hex directly here, it takes FOREVER,
// but if you have the helper method above, it works fast. Strange.
for
(
var
i
=
0
;
i
<
totals
.
length
;
i
++
)
{
hex
.
push
(
rgbToHex
(
totals
[
i
][
0
]));
}
return
hex
;
}
function
pick
(
img
,
canvaselement
,
x
,
y
)
{
var
pickedColor
=
"
hay
"
;
xx
=
x
;
yy
=
y
;
var
imgData
=
canvaselement
.
getImageData
(
xx
,
yy
,
1
,
1
).
data
;
pickedColor
=
rgbToHex
(
imgData
);
return
pickedColor
;
}
// This is called when the user clicks an image.
function
analyze
(
img_elem
,
event
)
{
// This is getting the canvas from the page and the image in it
canvaselement
=
document
.
getElementById
(
'
canvas
'
).
getContext
(
'
2d
'
),
img
=
new
Image
();
//var coords = relMouseCoords(document.getElementById('canvas'), event);
img
.
onload
=
function
()
{
var
message
=
document
.
getElementById
(
'
message
'
);
//Hopefully we'll never see the "Loading..." message but it's here just in case
message
.
innerHTML
=
'
Loading...
'
;
var
colors
=
processimg
(
img
,
canvaselement
);
// Showing the message of processing the image to the user
message
.
innerHTML
=
'
Theme Colors
'
;
console
.
log
(
colors
.
length
,
'
length
'
);
document
.
getElementById
(
'
ts0
'
).
value
=
colors
[
0
];
document
.
getElementById
(
'
ts1
'
).
value
=
colors
[
1
];
document
.
getElementById
(
'
ts2
'
).
value
=
colors
[
2
];
document
.
getElementById
(
'
ts3
'
).
value
=
colorfun
;
document
.
getElementById
(
'
color1
'
).
style
.
backgroundColor
=
colors
[
0
];
document
.
getElementById
(
'
color1
'
).
innerHTML
=
colors
[
0
];
document
.
getElementById
(
'
color2
'
).
style
.
backgroundColor
=
colors
[
1
];
document
.
getElementById
(
'
color2
'
).
innerHTML
=
colors
[
1
];
document
.
getElementById
(
'
color3
'
).
style
.
backgroundColor
=
colors
[
2
];
document
.
getElementById
(
'
color3
'
).
innerHTML
=
colors
[
2
];
var
colorfun
=
pick
(
img
,
canvaselement
,
event
.
offsetX
,
event
.
offsetY
);
// pass in coordinates
document
.
getElementById
(
'
pickedColor
'
).
style
.
backgroundColor
=
colorfun
;
document
.
getElementById
(
'
pickedColor
'
).
innerHTML
=
colorfun
;
document
.
getElementById
(
'
scheme
'
).
style
.
display
=
"
block
"
;
createSwatches
(
colorfun
);
}
img
.
src
=
img_elem
.
src
;
}
// This is for the swatches that are generated from the picked color.
function
createSwatches
(
hex
)
{
nHex
=
hex
;
// The light and dark values could potentially be changed so colors are changed based on these hues.
// It's this way just in case we expand it to include such functionality.
var
lightRGB
=
new
Array
(
255
,
255
,
255
);
var
darkRGB
=
new
Array
(
0
,
0
,
0
);
var
colorValues
=
new
Array
();
var
swatch
=
new
Array
();
baseColor
=
hexToRGB
(
nHex
);
opArray
=
new
Array
(
1.0
,
.
75
,
.
50
,
.
25
,
.
10
,
.
85
,
.
75
,
.
50
,
.
25
,
.
10
);
for
(
i
=
0
;
i
<
10
;
i
++
)
{
nMask
=
i
<
5
?
lightRGB
:
darkRGB
;
nColor
=
setColorHue
(
baseColor
,
opArray
[
i
],
nMask
);
nHex
=
toHex
(
nColor
[
0
])
+
toHex
(
nColor
[
1
])
+
toHex
(
nColor
[
2
]);
colorValues
[
i
]
=
new
Array
();
colorValues
[
i
][
0
]
=
nHex
;
colorValues
[
i
][
1
]
=
nColor
;
// Actually putting the swatches on the page
document
.
getElementById
(
"
s
"
+
i
).
style
.
backgroundColor
=
"
#
"
+
nHex
;
}
}
// Actually crating the hues with different lightness
function
setColorHue
(
originColor
,
opacityPercent
,
maskRGB
)
{
returnColor
=
new
Array
();
for
(
w
=
0
;
w
<
originColor
.
length
;
w
++
)
returnColor
[
w
]
=
Math
.
round
(
originColor
[
w
]
*
opacityPercent
)
+
Math
.
round
(
maskRGB
[
w
]
*
(
1.0
-
opacityPercent
));
return
returnColor
;
}
// Helper method for sonverting to HEX
function
toHex
(
dec
)
{
hex
=
dec
.
toString
(
16
);
if
(
hex
.
length
==
1
)
hex
=
"
0
"
+
hex
;
if
(
hex
==
100
)
hex
=
"
FF
"
;
return
hex
.
toUpperCase
();
}
//Converting HEX to RGB
function
hexToRGB
(
hex
)
{
var
r
=
hexToR
(
hex
);
var
g
=
hexToG
(
hex
);
var
b
=
hexToB
(
hex
);
function
hexToR
(
h
)
{
return
parseInt
((
cutHex
(
h
)).
substring
(
0
,
2
),
16
)
}
function
hexToG
(
h
)
{
return
parseInt
((
cutHex
(
h
)).
substring
(
2
,
4
),
16
)
}
function
hexToB
(
h
)
{
return
parseInt
((
cutHex
(
h
)).
substring
(
4
,
6
),
16
)
}
function
cutHex
(
h
)
{
return
(
h
.
charAt
(
0
)
==
"
#
"
)
?
h
.
substring
(
1
,
7
)
:
h
}
return
new
Array
(
r
,
g
,
b
);
}
// This is currently not used. Maybe if we start playing with hues and everything, it'll be useful!
/*
function HueShift(h,s) {
h+=s;
while (h>=360.0) h-=360.0;
while (h<0.0) h+=360.0;
return h;
}
function convertToHSV(hex)
{
var r = hexToR(hex);
var g = hexToG(hex);
var b = hexToB(hex);
function hexToR(h)
{
return parseInt((cutHex(h)).substring(0, 2), 16)
}
function hexToG(h)
{
return parseInt((cutHex(h)).substring(2, 4), 16)
}
function hexToB(h)
{
return parseInt((cutHex(h)).substring(4, 6), 16)
}
function cutHex(h)
{
return (h.charAt(0) == "#") ? h.substring(1, 7) : h
}
var computedH = 0;
var computedS = 0;
var computedV = 0;
r = r / 255;
g = g / 255;
b = b / 255;
var minRGB = Math.min(r, Math.min(g, b));
var maxRGB = Math.max(r, Math.max(g, b));
// Black-gray-white
if (minRGB == maxRGB)
{
computedV = minRGB;
return [0, 0, computedV];
}
// Colors other than black-gray-white:
var d = (r == minRGB) ? g - b : ((b == minRGB) ? r - g : b - r);
var h = (r == minRGB) ? 3 : ((b == minRGB) ? 1 : 5);
computedH = 60 * (h - d / (maxRGB - minRGB));
computedS = (maxRGB - minRGB) / maxRGB;
computedV = maxRGB;
return [computedH, computedS, computedV];
}
*/
\ No newline at end of file
BE-Aeasthatic-Quality-Check/colorcube-master/assets/js/tinycolor.js
0 → 100644
View file @
aa7a7fdb
// TinyColor v1.4.1
// https://github.com/bgrins/TinyColor
// Brian Grinstead, MIT License
(
function
(
Math
)
{
var
trimLeft
=
/^
\s
+/
,
trimRight
=
/
\s
+$/
,
tinyCounter
=
0
,
mathRound
=
Math
.
round
,
mathMin
=
Math
.
min
,
mathMax
=
Math
.
max
,
mathRandom
=
Math
.
random
;
function
tinycolor
(
color
,
opts
)
{
color
=
(
color
)
?
color
:
''
;
opts
=
opts
||
{
};
// If input is already a tinycolor, return itself
if
(
color
instanceof
tinycolor
)
{
return
color
;
}
// If we are called as a function, call using new instead
if
(
!
(
this
instanceof
tinycolor
))
{
return
new
tinycolor
(
color
,
opts
);
}
var
rgb
=
inputToRGB
(
color
);
this
.
_originalInput
=
color
,
this
.
_r
=
rgb
.
r
,
this
.
_g
=
rgb
.
g
,
this
.
_b
=
rgb
.
b
,
this
.
_a
=
rgb
.
a
,
this
.
_roundA
=
mathRound
(
100
*
this
.
_a
)
/
100
,
this
.
_format
=
opts
.
format
||
rgb
.
format
;
this
.
_gradientType
=
opts
.
gradientType
;
// Don't let the range of [0,255] come back in [0,1].
// Potentially lose a little bit of precision here, but will fix issues where
// .5 gets interpreted as half of the total, instead of half of 1
// If it was supposed to be 128, this was already taken care of by `inputToRgb`
if
(
this
.
_r
<
1
)
{
this
.
_r
=
mathRound
(
this
.
_r
);
}
if
(
this
.
_g
<
1
)
{
this
.
_g
=
mathRound
(
this
.
_g
);
}
if
(
this
.
_b
<
1
)
{
this
.
_b
=
mathRound
(
this
.
_b
);
}
this
.
_ok
=
rgb
.
ok
;
this
.
_tc_id
=
tinyCounter
++
;
}
tinycolor
.
prototype
=
{
isDark
:
function
()
{
return
this
.
getBrightness
()
<
128
;
},
isLight
:
function
()
{
return
!
this
.
isDark
();
},
isValid
:
function
()
{
return
this
.
_ok
;
},
getOriginalInput
:
function
()
{
return
this
.
_originalInput
;
},
getFormat
:
function
()
{
return
this
.
_format
;
},
getAlpha
:
function
()
{
return
this
.
_a
;
},
getBrightness
:
function
()
{
//http://www.w3.org/TR/AERT#color-contrast
var
rgb
=
this
.
toRgb
();
return
(
rgb
.
r
*
299
+
rgb
.
g
*
587
+
rgb
.
b
*
114
)
/
1000
;
},
getLuminance
:
function
()
{
//http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
var
rgb
=
this
.
toRgb
();
var
RsRGB
,
GsRGB
,
BsRGB
,
R
,
G
,
B
;
RsRGB
=
rgb
.
r
/
255
;
GsRGB
=
rgb
.
g
/
255
;
BsRGB
=
rgb
.
b
/
255
;
if
(
RsRGB
<=
0.03928
)
{
R
=
RsRGB
/
12.92
;}
else
{
R
=
Math
.
pow
(((
RsRGB
+
0.055
)
/
1.055
),
2.4
);}
if
(
GsRGB
<=
0.03928
)
{
G
=
GsRGB
/
12.92
;}
else
{
G
=
Math
.
pow
(((
GsRGB
+
0.055
)
/
1.055
),
2.4
);}
if
(
BsRGB
<=
0.03928
)
{
B
=
BsRGB
/
12.92
;}
else
{
B
=
Math
.
pow
(((
BsRGB
+
0.055
)
/
1.055
),
2.4
);}
return
(
0.2126
*
R
)
+
(
0.7152
*
G
)
+
(
0.0722
*
B
);
},
setAlpha
:
function
(
value
)
{
this
.
_a
=
boundAlpha
(
value
);
this
.
_roundA
=
mathRound
(
100
*
this
.
_a
)
/
100
;
return
this
;
},
toHsv
:
function
()
{
var
hsv
=
rgbToHsv
(
this
.
_r
,
this
.
_g
,
this
.
_b
);
return
{
h
:
hsv
.
h
*
360
,
s
:
hsv
.
s
,
v
:
hsv
.
v
,
a
:
this
.
_a
};
},
toHsvString
:
function
()
{
var
hsv
=
rgbToHsv
(
this
.
_r
,
this
.
_g
,
this
.
_b
);
var
h
=
mathRound
(
hsv
.
h
*
360
),
s
=
mathRound
(
hsv
.
s
*
100
),
v
=
mathRound
(
hsv
.
v
*
100
);
return
(
this
.
_a
==
1
)
?
"
hsv(
"
+
h
+
"
,
"
+
s
+
"
%,
"
+
v
+
"
%)
"
:
"
hsva(
"
+
h
+
"
,
"
+
s
+
"
%,
"
+
v
+
"
%,
"
+
this
.
_roundA
+
"
)
"
;
},
toHsl
:
function
()
{
var
hsl
=
rgbToHsl
(
this
.
_r
,
this
.
_g
,
this
.
_b
);
return
{
h
:
hsl
.
h
*
360
,
s
:
hsl
.
s
,
l
:
hsl
.
l
,
a
:
this
.
_a
};
},
toHslString
:
function
()
{
var
hsl
=
rgbToHsl
(
this
.
_r
,
this
.
_g
,
this
.
_b
);
var
h
=
mathRound
(
hsl
.
h
*
360
),
s
=
mathRound
(
hsl
.
s
*
100
),
l
=
mathRound
(
hsl
.
l
*
100
);
return
(
this
.
_a
==
1
)
?
"
hsl(
"
+
h
+
"
,
"
+
s
+
"
%,
"
+
l
+
"
%)
"
:
"
hsla(
"
+
h
+
"
,
"
+
s
+
"
%,
"
+
l
+
"
%,
"
+
this
.
_roundA
+
"
)
"
;
},
toHex
:
function
(
allow3Char
)
{
return
rgbToHex
(
this
.
_r
,
this
.
_g
,
this
.
_b
,
allow3Char
);
},
toHexString
:
function
(
allow3Char
)
{
return
'
#
'
+
this
.
toHex
(
allow3Char
);
},
toHex8
:
function
(
allow4Char
)
{
return
rgbaToHex
(
this
.
_r
,
this
.
_g
,
this
.
_b
,
this
.
_a
,
allow4Char
);
},
toHex8String
:
function
(
allow4Char
)
{
return
'
#
'
+
this
.
toHex8
(
allow4Char
);
},
toRgb
:
function
()
{
return
{
r
:
mathRound
(
this
.
_r
),
g
:
mathRound
(
this
.
_g
),
b
:
mathRound
(
this
.
_b
),
a
:
this
.
_a
};
},
toRgbString
:
function
()
{
return
(
this
.
_a
==
1
)
?
"
rgb(
"
+
mathRound
(
this
.
_r
)
+
"
,
"
+
mathRound
(
this
.
_g
)
+
"
,
"
+
mathRound
(
this
.
_b
)
+
"
)
"
:
"
rgba(
"
+
mathRound
(
this
.
_r
)
+
"
,
"
+
mathRound
(
this
.
_g
)
+
"
,
"
+
mathRound
(
this
.
_b
)
+
"
,
"
+
this
.
_roundA
+
"
)
"
;
},
toPercentageRgb
:
function
()
{
return
{
r
:
mathRound
(
bound01
(
this
.
_r
,
255
)
*
100
)
+
"
%
"
,
g
:
mathRound
(
bound01
(
this
.
_g
,
255
)
*
100
)
+
"
%
"
,
b
:
mathRound
(
bound01
(
this
.
_b
,
255
)
*
100
)
+
"
%
"
,
a
:
this
.
_a
};
},
toPercentageRgbString
:
function
()
{
return
(
this
.
_a
==
1
)
?
"
rgb(
"
+
mathRound
(
bound01
(
this
.
_r
,
255
)
*
100
)
+
"
%,
"
+
mathRound
(
bound01
(
this
.
_g
,
255
)
*
100
)
+
"
%,
"
+
mathRound
(
bound01
(
this
.
_b
,
255
)
*
100
)
+
"
%)
"
:
"
rgba(
"
+
mathRound
(
bound01
(
this
.
_r
,
255
)
*
100
)
+
"
%,
"
+
mathRound
(
bound01
(
this
.
_g
,
255
)
*
100
)
+
"
%,
"
+
mathRound
(
bound01
(
this
.
_b
,
255
)
*
100
)
+
"
%,
"
+
this
.
_roundA
+
"
)
"
;
},
toName
:
function
()
{
if
(
this
.
_a
===
0
)
{
return
"
transparent
"
;
}
if
(
this
.
_a
<
1
)
{
return
false
;
}
return
hexNames
[
rgbToHex
(
this
.
_r
,
this
.
_g
,
this
.
_b
,
true
)]
||
false
;
},
toFilter
:
function
(
secondColor
)
{
var
hex8String
=
'
#
'
+
rgbaToArgbHex
(
this
.
_r
,
this
.
_g
,
this
.
_b
,
this
.
_a
);
var
secondHex8String
=
hex8String
;
var
gradientType
=
this
.
_gradientType
?
"
GradientType = 1,
"
:
""
;
if
(
secondColor
)
{
var
s
=
tinycolor
(
secondColor
);
secondHex8String
=
'
#
'
+
rgbaToArgbHex
(
s
.
_r
,
s
.
_g
,
s
.
_b
,
s
.
_a
);
}
return
"
progid:DXImageTransform.Microsoft.gradient(
"
+
gradientType
+
"
startColorstr=
"
+
hex8String
+
"
,endColorstr=
"
+
secondHex8String
+
"
)
"
;
},
toString
:
function
(
format
)
{
var
formatSet
=
!!
format
;
format
=
format
||
this
.
_format
;
var
formattedString
=
false
;
var
hasAlpha
=
this
.
_a
<
1
&&
this
.
_a
>=
0
;
var
needsAlphaFormat
=
!
formatSet
&&
hasAlpha
&&
(
format
===
"
hex
"
||
format
===
"
hex6
"
||
format
===
"
hex3
"
||
format
===
"
hex4
"
||
format
===
"
hex8
"
||
format
===
"
name
"
);
if
(
needsAlphaFormat
)
{
// Special case for "transparent", all other non-alpha formats
// will return rgba when there is transparency.
if
(
format
===
"
name
"
&&
this
.
_a
===
0
)
{
return
this
.
toName
();
}
return
this
.
toRgbString
();
}
if
(
format
===
"
rgb
"
)
{
formattedString
=
this
.
toRgbString
();
}
if
(
format
===
"
prgb
"
)
{
formattedString
=
this
.
toPercentageRgbString
();
}
if
(
format
===
"
hex
"
||
format
===
"
hex6
"
)
{
formattedString
=
this
.
toHexString
();
}
if
(
format
===
"
hex3
"
)
{
formattedString
=
this
.
toHexString
(
true
);
}
if
(
format
===
"
hex4
"
)
{
formattedString
=
this
.
toHex8String
(
true
);
}
if
(
format
===
"
hex8
"
)
{
formattedString
=
this
.
toHex8String
();
}
if
(
format
===
"
name
"
)
{
formattedString
=
this
.
toName
();
}
if
(
format
===
"
hsl
"
)
{
formattedString
=
this
.
toHslString
();
}
if
(
format
===
"
hsv
"
)
{
formattedString
=
this
.
toHsvString
();
}
return
formattedString
||
this
.
toHexString
();
},
clone
:
function
()
{
return
tinycolor
(
this
.
toString
());
},
_applyModification
:
function
(
fn
,
args
)
{
var
color
=
fn
.
apply
(
null
,
[
this
].
concat
([].
slice
.
call
(
args
)));
this
.
_r
=
color
.
_r
;
this
.
_g
=
color
.
_g
;
this
.
_b
=
color
.
_b
;
this
.
setAlpha
(
color
.
_a
);
return
this
;
},
lighten
:
function
()
{
return
this
.
_applyModification
(
lighten
,
arguments
);
},
brighten
:
function
()
{
return
this
.
_applyModification
(
brighten
,
arguments
);
},
darken
:
function
()
{
return
this
.
_applyModification
(
darken
,
arguments
);
},
desaturate
:
function
()
{
return
this
.
_applyModification
(
desaturate
,
arguments
);
},
saturate
:
function
()
{
return
this
.
_applyModification
(
saturate
,
arguments
);
},
greyscale
:
function
()
{
return
this
.
_applyModification
(
greyscale
,
arguments
);
},
spin
:
function
()
{
return
this
.
_applyModification
(
spin
,
arguments
);
},
_applyCombination
:
function
(
fn
,
args
)
{
return
fn
.
apply
(
null
,
[
this
].
concat
([].
slice
.
call
(
args
)));
},
analogous
:
function
()
{
return
this
.
_applyCombination
(
analogous
,
arguments
);
},
complement
:
function
()
{
return
this
.
_applyCombination
(
complement
,
arguments
);
},
monochromatic
:
function
()
{
return
this
.
_applyCombination
(
monochromatic
,
arguments
);
},
splitcomplement
:
function
()
{
return
this
.
_applyCombination
(
splitcomplement
,
arguments
);
},
triad
:
function
()
{
return
this
.
_applyCombination
(
triad
,
arguments
);
},
tetrad
:
function
()
{
return
this
.
_applyCombination
(
tetrad
,
arguments
);
}
};
// If input is an object, force 1 into "1.0" to handle ratios properly
// String input requires "1.0" as input, so 1 will be treated as 1
tinycolor
.
fromRatio
=
function
(
color
,
opts
)
{
if
(
typeof
color
==
"
object
"
)
{
var
newColor
=
{};
for
(
var
i
in
color
)
{
if
(
color
.
hasOwnProperty
(
i
))
{
if
(
i
===
"
a
"
)
{
newColor
[
i
]
=
color
[
i
];
}
else
{
newColor
[
i
]
=
convertToPercentage
(
color
[
i
]);
}
}
}
color
=
newColor
;
}
return
tinycolor
(
color
,
opts
);
};
// Given a string or object, convert that input to RGB
// Possible string inputs:
//
// "red"
// "#f00" or "f00"
// "#ff0000" or "ff0000"
// "#ff000000" or "ff000000"
// "rgb 255 0 0" or "rgb (255, 0, 0)"
// "rgb 1.0 0 0" or "rgb (1, 0, 0)"
// "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1"
// "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1"
// "hsl(0, 100%, 50%)" or "hsl 0 100% 50%"
// "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1"
// "hsv(0, 100%, 100%)" or "hsv 0 100% 100%"
//
function
inputToRGB
(
color
)
{
var
rgb
=
{
r
:
0
,
g
:
0
,
b
:
0
};
var
a
=
1
;
var
s
=
null
;
var
v
=
null
;
var
l
=
null
;
var
ok
=
false
;
var
format
=
false
;
if
(
typeof
color
==
"
string
"
)
{
color
=
stringInputToObject
(
color
);
}
if
(
typeof
color
==
"
object
"
)
{
if
(
isValidCSSUnit
(
color
.
r
)
&&
isValidCSSUnit
(
color
.
g
)
&&
isValidCSSUnit
(
color
.
b
))
{
rgb
=
rgbToRgb
(
color
.
r
,
color
.
g
,
color
.
b
);
ok
=
true
;
format
=
String
(
color
.
r
).
substr
(
-
1
)
===
"
%
"
?
"
prgb
"
:
"
rgb
"
;
}
else
if
(
isValidCSSUnit
(
color
.
h
)
&&
isValidCSSUnit
(
color
.
s
)
&&
isValidCSSUnit
(
color
.
v
))
{
s
=
convertToPercentage
(
color
.
s
);
v
=
convertToPercentage
(
color
.
v
);
rgb
=
hsvToRgb
(
color
.
h
,
s
,
v
);
ok
=
true
;
format
=
"
hsv
"
;
}
else
if
(
isValidCSSUnit
(
color
.
h
)
&&
isValidCSSUnit
(
color
.
s
)
&&
isValidCSSUnit
(
color
.
l
))
{
s
=
convertToPercentage
(
color
.
s
);
l
=
convertToPercentage
(
color
.
l
);
rgb
=
hslToRgb
(
color
.
h
,
s
,
l
);
ok
=
true
;
format
=
"
hsl
"
;
}
if
(
color
.
hasOwnProperty
(
"
a
"
))
{
a
=
color
.
a
;
}
}
a
=
boundAlpha
(
a
);
return
{
ok
:
ok
,
format
:
color
.
format
||
format
,
r
:
mathMin
(
255
,
mathMax
(
rgb
.
r
,
0
)),
g
:
mathMin
(
255
,
mathMax
(
rgb
.
g
,
0
)),
b
:
mathMin
(
255
,
mathMax
(
rgb
.
b
,
0
)),
a
:
a
};
}
// Conversion Functions
// --------------------
// `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
// <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
// `rgbToRgb`
// Handle bounds / percentage checking to conform to CSS color spec
// <http://www.w3.org/TR/css3-color/>
// *Assumes:* r, g, b in [0, 255] or [0, 1]
// *Returns:* { r, g, b } in [0, 255]
function
rgbToRgb
(
r
,
g
,
b
){
return
{
r
:
bound01
(
r
,
255
)
*
255
,
g
:
bound01
(
g
,
255
)
*
255
,
b
:
bound01
(
b
,
255
)
*
255
};
}
// `rgbToHsl`
// Converts an RGB color value to HSL.
// *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
// *Returns:* { h, s, l } in [0,1]
function
rgbToHsl
(
r
,
g
,
b
)
{
r
=
bound01
(
r
,
255
);
g
=
bound01
(
g
,
255
);
b
=
bound01
(
b
,
255
);
var
max
=
mathMax
(
r
,
g
,
b
),
min
=
mathMin
(
r
,
g
,
b
);
var
h
,
s
,
l
=
(
max
+
min
)
/
2
;
if
(
max
==
min
)
{
h
=
s
=
0
;
// achromatic
}
else
{
var
d
=
max
-
min
;
s
=
l
>
0.5
?
d
/
(
2
-
max
-
min
)
:
d
/
(
max
+
min
);
switch
(
max
)
{
case
r
:
h
=
(
g
-
b
)
/
d
+
(
g
<
b
?
6
:
0
);
break
;
case
g
:
h
=
(
b
-
r
)
/
d
+
2
;
break
;
case
b
:
h
=
(
r
-
g
)
/
d
+
4
;
break
;
}
h
/=
6
;
}
return
{
h
:
h
,
s
:
s
,
l
:
l
};
}
// `hslToRgb`
// Converts an HSL color value to RGB.
// *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
// *Returns:* { r, g, b } in the set [0, 255]
function
hslToRgb
(
h
,
s
,
l
)
{
var
r
,
g
,
b
;
h
=
bound01
(
h
,
360
);
s
=
bound01
(
s
,
100
);
l
=
bound01
(
l
,
100
);
function
hue2rgb
(
p
,
q
,
t
)
{
if
(
t
<
0
)
t
+=
1
;
if
(
t
>
1
)
t
-=
1
;
if
(
t
<
1
/
6
)
return
p
+
(
q
-
p
)
*
6
*
t
;
if
(
t
<
1
/
2
)
return
q
;
if
(
t
<
2
/
3
)
return
p
+
(
q
-
p
)
*
(
2
/
3
-
t
)
*
6
;
return
p
;
}
if
(
s
===
0
)
{
r
=
g
=
b
=
l
;
// achromatic
}
else
{
var
q
=
l
<
0.5
?
l
*
(
1
+
s
)
:
l
+
s
-
l
*
s
;
var
p
=
2
*
l
-
q
;
r
=
hue2rgb
(
p
,
q
,
h
+
1
/
3
);
g
=
hue2rgb
(
p
,
q
,
h
);
b
=
hue2rgb
(
p
,
q
,
h
-
1
/
3
);
}
return
{
r
:
r
*
255
,
g
:
g
*
255
,
b
:
b
*
255
};
}
// `rgbToHsv`
// Converts an RGB color value to HSV
// *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
// *Returns:* { h, s, v } in [0,1]
function
rgbToHsv
(
r
,
g
,
b
)
{
r
=
bound01
(
r
,
255
);
g
=
bound01
(
g
,
255
);
b
=
bound01
(
b
,
255
);
var
max
=
mathMax
(
r
,
g
,
b
),
min
=
mathMin
(
r
,
g
,
b
);
var
h
,
s
,
v
=
max
;
var
d
=
max
-
min
;
s
=
max
===
0
?
0
:
d
/
max
;
if
(
max
==
min
)
{
h
=
0
;
// achromatic
}
else
{
switch
(
max
)
{
case
r
:
h
=
(
g
-
b
)
/
d
+
(
g
<
b
?
6
:
0
);
break
;
case
g
:
h
=
(
b
-
r
)
/
d
+
2
;
break
;
case
b
:
h
=
(
r
-
g
)
/
d
+
4
;
break
;
}
h
/=
6
;
}
return
{
h
:
h
,
s
:
s
,
v
:
v
};
}
// `hsvToRgb`
// Converts an HSV color value to RGB.
// *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
// *Returns:* { r, g, b } in the set [0, 255]
function
hsvToRgb
(
h
,
s
,
v
)
{
h
=
bound01
(
h
,
360
)
*
6
;
s
=
bound01
(
s
,
100
);
v
=
bound01
(
v
,
100
);
var
i
=
Math
.
floor
(
h
),
f
=
h
-
i
,
p
=
v
*
(
1
-
s
),
q
=
v
*
(
1
-
f
*
s
),
t
=
v
*
(
1
-
(
1
-
f
)
*
s
),
mod
=
i
%
6
,
r
=
[
v
,
q
,
p
,
p
,
t
,
v
][
mod
],
g
=
[
t
,
v
,
v
,
q
,
p
,
p
][
mod
],
b
=
[
p
,
p
,
t
,
v
,
v
,
q
][
mod
];
return
{
r
:
r
*
255
,
g
:
g
*
255
,
b
:
b
*
255
};
}
// `rgbToHex`
// Converts an RGB color to hex
// Assumes r, g, and b are contained in the set [0, 255]
// Returns a 3 or 6 character hex
function
rgbToHex
(
r
,
g
,
b
,
allow3Char
)
{
var
hex
=
[
pad2
(
mathRound
(
r
).
toString
(
16
)),
pad2
(
mathRound
(
g
).
toString
(
16
)),
pad2
(
mathRound
(
b
).
toString
(
16
))
];
// Return a 3 character hex if possible
if
(
allow3Char
&&
hex
[
0
].
charAt
(
0
)
==
hex
[
0
].
charAt
(
1
)
&&
hex
[
1
].
charAt
(
0
)
==
hex
[
1
].
charAt
(
1
)
&&
hex
[
2
].
charAt
(
0
)
==
hex
[
2
].
charAt
(
1
))
{
return
hex
[
0
].
charAt
(
0
)
+
hex
[
1
].
charAt
(
0
)
+
hex
[
2
].
charAt
(
0
);
}
return
hex
.
join
(
""
);
}
// `rgbaToHex`
// Converts an RGBA color plus alpha transparency to hex
// Assumes r, g, b are contained in the set [0, 255] and
// a in [0, 1]. Returns a 4 or 8 character rgba hex
function
rgbaToHex
(
r
,
g
,
b
,
a
,
allow4Char
)
{
var
hex
=
[
pad2
(
mathRound
(
r
).
toString
(
16
)),
pad2
(
mathRound
(
g
).
toString
(
16
)),
pad2
(
mathRound
(
b
).
toString
(
16
)),
pad2
(
convertDecimalToHex
(
a
))
];
// Return a 4 character hex if possible
if
(
allow4Char
&&
hex
[
0
].
charAt
(
0
)
==
hex
[
0
].
charAt
(
1
)
&&
hex
[
1
].
charAt
(
0
)
==
hex
[
1
].
charAt
(
1
)
&&
hex
[
2
].
charAt
(
0
)
==
hex
[
2
].
charAt
(
1
)
&&
hex
[
3
].
charAt
(
0
)
==
hex
[
3
].
charAt
(
1
))
{
return
hex
[
0
].
charAt
(
0
)
+
hex
[
1
].
charAt
(
0
)
+
hex
[
2
].
charAt
(
0
)
+
hex
[
3
].
charAt
(
0
);
}
return
hex
.
join
(
""
);
}
// `rgbaToArgbHex`
// Converts an RGBA color to an ARGB Hex8 string
// Rarely used, but required for "toFilter()"
function
rgbaToArgbHex
(
r
,
g
,
b
,
a
)
{
var
hex
=
[
pad2
(
convertDecimalToHex
(
a
)),
pad2
(
mathRound
(
r
).
toString
(
16
)),
pad2
(
mathRound
(
g
).
toString
(
16
)),
pad2
(
mathRound
(
b
).
toString
(
16
))
];
return
hex
.
join
(
""
);
}
// `equals`
// Can be called with any tinycolor input
tinycolor
.
equals
=
function
(
color1
,
color2
)
{
if
(
!
color1
||
!
color2
)
{
return
false
;
}
return
tinycolor
(
color1
).
toRgbString
()
==
tinycolor
(
color2
).
toRgbString
();
};
tinycolor
.
random
=
function
()
{
return
tinycolor
.
fromRatio
({
r
:
mathRandom
(),
g
:
mathRandom
(),
b
:
mathRandom
()
});
};
// Modification Functions
// ----------------------
// Thanks to less.js for some of the basics here
// <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>
function
desaturate
(
color
,
amount
)
{
amount
=
(
amount
===
0
)
?
0
:
(
amount
||
10
);
var
hsl
=
tinycolor
(
color
).
toHsl
();
hsl
.
s
-=
amount
/
100
;
hsl
.
s
=
clamp01
(
hsl
.
s
);
return
tinycolor
(
hsl
);
}
function
saturate
(
color
,
amount
)
{
amount
=
(
amount
===
0
)
?
0
:
(
amount
||
10
);
var
hsl
=
tinycolor
(
color
).
toHsl
();
hsl
.
s
+=
amount
/
100
;
hsl
.
s
=
clamp01
(
hsl
.
s
);
return
tinycolor
(
hsl
);
}
function
greyscale
(
color
)
{
return
tinycolor
(
color
).
desaturate
(
100
);
}
function
lighten
(
color
,
amount
)
{
amount
=
(
amount
===
0
)
?
0
:
(
amount
||
10
);
var
hsl
=
tinycolor
(
color
).
toHsl
();
hsl
.
l
+=
amount
/
100
;
hsl
.
l
=
clamp01
(
hsl
.
l
);
return
tinycolor
(
hsl
);
}
function
brighten
(
color
,
amount
)
{
amount
=
(
amount
===
0
)
?
0
:
(
amount
||
10
);
var
rgb
=
tinycolor
(
color
).
toRgb
();
rgb
.
r
=
mathMax
(
0
,
mathMin
(
255
,
rgb
.
r
-
mathRound
(
255
*
-
(
amount
/
100
))));
rgb
.
g
=
mathMax
(
0
,
mathMin
(
255
,
rgb
.
g
-
mathRound
(
255
*
-
(
amount
/
100
))));
rgb
.
b
=
mathMax
(
0
,
mathMin
(
255
,
rgb
.
b
-
mathRound
(
255
*
-
(
amount
/
100
))));
return
tinycolor
(
rgb
);
}
function
darken
(
color
,
amount
)
{
amount
=
(
amount
===
0
)
?
0
:
(
amount
||
10
);
var
hsl
=
tinycolor
(
color
).
toHsl
();
hsl
.
l
-=
amount
/
100
;
hsl
.
l
=
clamp01
(
hsl
.
l
);
return
tinycolor
(
hsl
);
}
// Spin takes a positive or negative amount within [-360, 360] indicating the change of hue.
// Values outside of this range will be wrapped into this range.
function
spin
(
color
,
amount
)
{
var
hsl
=
tinycolor
(
color
).
toHsl
();
var
hue
=
(
hsl
.
h
+
amount
)
%
360
;
hsl
.
h
=
hue
<
0
?
360
+
hue
:
hue
;
return
tinycolor
(
hsl
);
}
// Combination Functions
// ---------------------
// Thanks to jQuery xColor for some of the ideas behind these
// <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>
function
complement
(
color
)
{
var
hsl
=
tinycolor
(
color
).
toHsl
();
hsl
.
h
=
(
hsl
.
h
+
180
)
%
360
;
return
tinycolor
(
hsl
);
}
function
triad
(
color
)
{
var
hsl
=
tinycolor
(
color
).
toHsl
();
var
h
=
hsl
.
h
;
return
[
tinycolor
(
color
),
tinycolor
({
h
:
(
h
+
120
)
%
360
,
s
:
hsl
.
s
,
l
:
hsl
.
l
}),
tinycolor
({
h
:
(
h
+
240
)
%
360
,
s
:
hsl
.
s
,
l
:
hsl
.
l
})
];
}
function
tetrad
(
color
)
{
var
hsl
=
tinycolor
(
color
).
toHsl
();
var
h
=
hsl
.
h
;
return
[
tinycolor
(
color
),
tinycolor
({
h
:
(
h
+
90
)
%
360
,
s
:
hsl
.
s
,
l
:
hsl
.
l
}),
tinycolor
({
h
:
(
h
+
180
)
%
360
,
s
:
hsl
.
s
,
l
:
hsl
.
l
}),
tinycolor
({
h
:
(
h
+
270
)
%
360
,
s
:
hsl
.
s
,
l
:
hsl
.
l
})
];
}
function
splitcomplement
(
color
)
{
var
hsl
=
tinycolor
(
color
).
toHsl
();
var
h
=
hsl
.
h
;
return
[
tinycolor
(
color
),
tinycolor
({
h
:
(
h
+
72
)
%
360
,
s
:
hsl
.
s
,
l
:
hsl
.
l
}),
tinycolor
({
h
:
(
h
+
216
)
%
360
,
s
:
hsl
.
s
,
l
:
hsl
.
l
})
];
}
function
analogous
(
color
,
results
,
slices
)
{
results
=
results
||
6
;
slices
=
slices
||
30
;
var
hsl
=
tinycolor
(
color
).
toHsl
();
var
part
=
360
/
slices
;
var
ret
=
[
tinycolor
(
color
)];
for
(
hsl
.
h
=
((
hsl
.
h
-
(
part
*
results
>>
1
))
+
720
)
%
360
;
--
results
;
)
{
hsl
.
h
=
(
hsl
.
h
+
part
)
%
360
;
ret
.
push
(
tinycolor
(
hsl
));
}
return
ret
;
}
function
monochromatic
(
color
,
results
)
{
results
=
results
||
6
;
var
hsv
=
tinycolor
(
color
).
toHsv
();
var
h
=
hsv
.
h
,
s
=
hsv
.
s
,
v
=
hsv
.
v
;
var
ret
=
[];
var
modification
=
1
/
results
;
while
(
results
--
)
{
ret
.
push
(
tinycolor
({
h
:
h
,
s
:
s
,
v
:
v
}));
v
=
(
v
+
modification
)
%
1
;
}
return
ret
;
}
// Utility Functions
// ---------------------
tinycolor
.
mix
=
function
(
color1
,
color2
,
amount
)
{
amount
=
(
amount
===
0
)
?
0
:
(
amount
||
50
);
var
rgb1
=
tinycolor
(
color1
).
toRgb
();
var
rgb2
=
tinycolor
(
color2
).
toRgb
();
var
p
=
amount
/
100
;
var
rgba
=
{
r
:
((
rgb2
.
r
-
rgb1
.
r
)
*
p
)
+
rgb1
.
r
,
g
:
((
rgb2
.
g
-
rgb1
.
g
)
*
p
)
+
rgb1
.
g
,
b
:
((
rgb2
.
b
-
rgb1
.
b
)
*
p
)
+
rgb1
.
b
,
a
:
((
rgb2
.
a
-
rgb1
.
a
)
*
p
)
+
rgb1
.
a
};
return
tinycolor
(
rgba
);
};
// Readability Functions
// ---------------------
// <http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef (WCAG Version 2)
// `contrast`
// Analyze the 2 colors and returns the color contrast defined by (WCAG Version 2)
tinycolor
.
readability
=
function
(
color1
,
color2
)
{
var
c1
=
tinycolor
(
color1
);
var
c2
=
tinycolor
(
color2
);
return
(
Math
.
max
(
c1
.
getLuminance
(),
c2
.
getLuminance
())
+
0.05
)
/
(
Math
.
min
(
c1
.
getLuminance
(),
c2
.
getLuminance
())
+
0.05
);
};
// `isReadable`
// Ensure that foreground and background color combinations meet WCAG2 guidelines.
// The third argument is an optional Object.
// the 'level' property states 'AA' or 'AAA' - if missing or invalid, it defaults to 'AA';
// the 'size' property states 'large' or 'small' - if missing or invalid, it defaults to 'small'.
// If the entire object is absent, isReadable defaults to {level:"AA",size:"small"}.
// *Example*
// tinycolor.isReadable("#000", "#111") => false
// tinycolor.isReadable("#000", "#111",{level:"AA",size:"large"}) => false
tinycolor
.
isReadable
=
function
(
color1
,
color2
,
wcag2
)
{
var
readability
=
tinycolor
.
readability
(
color1
,
color2
);
var
wcag2Parms
,
out
;
out
=
false
;
wcag2Parms
=
validateWCAG2Parms
(
wcag2
);
switch
(
wcag2Parms
.
level
+
wcag2Parms
.
size
)
{
case
"
AAsmall
"
:
case
"
AAAlarge
"
:
out
=
readability
>=
4.5
;
break
;
case
"
AAlarge
"
:
out
=
readability
>=
3
;
break
;
case
"
AAAsmall
"
:
out
=
readability
>=
7
;
break
;
}
return
out
;
};
// `mostReadable`
// Given a base color and a list of possible foreground or background
// colors for that base, returns the most readable color.
// Optionally returns Black or White if the most readable color is unreadable.
// *Example*
// tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:false}).toHexString(); // "#112255"
// tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:true}).toHexString(); // "#ffffff"
// tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"large"}).toHexString(); // "#faf3f3"
// tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"small"}).toHexString(); // "#ffffff"
tinycolor
.
mostReadable
=
function
(
baseColor
,
colorList
,
args
)
{
var
bestColor
=
null
;
var
bestScore
=
0
;
var
readability
;
var
includeFallbackColors
,
level
,
size
;
args
=
args
||
{};
includeFallbackColors
=
args
.
includeFallbackColors
;
level
=
args
.
level
;
size
=
args
.
size
;
for
(
var
i
=
0
;
i
<
colorList
.
length
;
i
++
)
{
readability
=
tinycolor
.
readability
(
baseColor
,
colorList
[
i
]);
if
(
readability
>
bestScore
)
{
bestScore
=
readability
;
bestColor
=
tinycolor
(
colorList
[
i
]);
}
}
if
(
tinycolor
.
isReadable
(
baseColor
,
bestColor
,
{
"
level
"
:
level
,
"
size
"
:
size
})
||
!
includeFallbackColors
)
{
return
bestColor
;
}
else
{
args
.
includeFallbackColors
=
false
;
return
tinycolor
.
mostReadable
(
baseColor
,[
"
#fff
"
,
"
#000
"
],
args
);
}
};
// Big List of Colors
// ------------------
// <http://www.w3.org/TR/css3-color/#svg-color>
var
names
=
tinycolor
.
names
=
{
aliceblue
:
"
f0f8ff
"
,
antiquewhite
:
"
faebd7
"
,
aqua
:
"
0ff
"
,
aquamarine
:
"
7fffd4
"
,
azure
:
"
f0ffff
"
,
beige
:
"
f5f5dc
"
,
bisque
:
"
ffe4c4
"
,
black
:
"
000
"
,
blanchedalmond
:
"
ffebcd
"
,
blue
:
"
00f
"
,
blueviolet
:
"
8a2be2
"
,
brown
:
"
a52a2a
"
,
burlywood
:
"
deb887
"
,
burntsienna
:
"
ea7e5d
"
,
cadetblue
:
"
5f9ea0
"
,
chartreuse
:
"
7fff00
"
,
chocolate
:
"
d2691e
"
,
coral
:
"
ff7f50
"
,
cornflowerblue
:
"
6495ed
"
,
cornsilk
:
"
fff8dc
"
,
crimson
:
"
dc143c
"
,
cyan
:
"
0ff
"
,
darkblue
:
"
00008b
"
,
darkcyan
:
"
008b8b
"
,
darkgoldenrod
:
"
b8860b
"
,
darkgray
:
"
a9a9a9
"
,
darkgreen
:
"
006400
"
,
darkgrey
:
"
a9a9a9
"
,
darkkhaki
:
"
bdb76b
"
,
darkmagenta
:
"
8b008b
"
,
darkolivegreen
:
"
556b2f
"
,
darkorange
:
"
ff8c00
"
,
darkorchid
:
"
9932cc
"
,
darkred
:
"
8b0000
"
,
darksalmon
:
"
e9967a
"
,
darkseagreen
:
"
8fbc8f
"
,
darkslateblue
:
"
483d8b
"
,
darkslategray
:
"
2f4f4f
"
,
darkslategrey
:
"
2f4f4f
"
,
darkturquoise
:
"
00ced1
"
,
darkviolet
:
"
9400d3
"
,
deeppink
:
"
ff1493
"
,
deepskyblue
:
"
00bfff
"
,
dimgray
:
"
696969
"
,
dimgrey
:
"
696969
"
,
dodgerblue
:
"
1e90ff
"
,
firebrick
:
"
b22222
"
,
floralwhite
:
"
fffaf0
"
,
forestgreen
:
"
228b22
"
,
fuchsia
:
"
f0f
"
,
gainsboro
:
"
dcdcdc
"
,
ghostwhite
:
"
f8f8ff
"
,
gold
:
"
ffd700
"
,
goldenrod
:
"
daa520
"
,
gray
:
"
808080
"
,
green
:
"
008000
"
,
greenyellow
:
"
adff2f
"
,
grey
:
"
808080
"
,
honeydew
:
"
f0fff0
"
,
hotpink
:
"
ff69b4
"
,
indianred
:
"
cd5c5c
"
,
indigo
:
"
4b0082
"
,
ivory
:
"
fffff0
"
,
khaki
:
"
f0e68c
"
,
lavender
:
"
e6e6fa
"
,
lavenderblush
:
"
fff0f5
"
,
lawngreen
:
"
7cfc00
"
,
lemonchiffon
:
"
fffacd
"
,
lightblue
:
"
add8e6
"
,
lightcoral
:
"
f08080
"
,
lightcyan
:
"
e0ffff
"
,
lightgoldenrodyellow
:
"
fafad2
"
,
lightgray
:
"
d3d3d3
"
,
lightgreen
:
"
90ee90
"
,
lightgrey
:
"
d3d3d3
"
,
lightpink
:
"
ffb6c1
"
,
lightsalmon
:
"
ffa07a
"
,
lightseagreen
:
"
20b2aa
"
,
lightskyblue
:
"
87cefa
"
,
lightslategray
:
"
789
"
,
lightslategrey
:
"
789
"
,
lightsteelblue
:
"
b0c4de
"
,
lightyellow
:
"
ffffe0
"
,
lime
:
"
0f0
"
,
limegreen
:
"
32cd32
"
,
linen
:
"
faf0e6
"
,
magenta
:
"
f0f
"
,
maroon
:
"
800000
"
,
mediumaquamarine
:
"
66cdaa
"
,
mediumblue
:
"
0000cd
"
,
mediumorchid
:
"
ba55d3
"
,
mediumpurple
:
"
9370db
"
,
mediumseagreen
:
"
3cb371
"
,
mediumslateblue
:
"
7b68ee
"
,
mediumspringgreen
:
"
00fa9a
"
,
mediumturquoise
:
"
48d1cc
"
,
mediumvioletred
:
"
c71585
"
,
midnightblue
:
"
191970
"
,
mintcream
:
"
f5fffa
"
,
mistyrose
:
"
ffe4e1
"
,
moccasin
:
"
ffe4b5
"
,
navajowhite
:
"
ffdead
"
,
navy
:
"
000080
"
,
oldlace
:
"
fdf5e6
"
,
olive
:
"
808000
"
,
olivedrab
:
"
6b8e23
"
,
orange
:
"
ffa500
"
,
orangered
:
"
ff4500
"
,
orchid
:
"
da70d6
"
,
palegoldenrod
:
"
eee8aa
"
,
palegreen
:
"
98fb98
"
,
paleturquoise
:
"
afeeee
"
,
palevioletred
:
"
db7093
"
,
papayawhip
:
"
ffefd5
"
,
peachpuff
:
"
ffdab9
"
,
peru
:
"
cd853f
"
,
pink
:
"
ffc0cb
"
,
plum
:
"
dda0dd
"
,
powderblue
:
"
b0e0e6
"
,
purple
:
"
800080
"
,
rebeccapurple
:
"
663399
"
,
red
:
"
f00
"
,
rosybrown
:
"
bc8f8f
"
,
royalblue
:
"
4169e1
"
,
saddlebrown
:
"
8b4513
"
,
salmon
:
"
fa8072
"
,
sandybrown
:
"
f4a460
"
,
seagreen
:
"
2e8b57
"
,
seashell
:
"
fff5ee
"
,
sienna
:
"
a0522d
"
,
silver
:
"
c0c0c0
"
,
skyblue
:
"
87ceeb
"
,
slateblue
:
"
6a5acd
"
,
slategray
:
"
708090
"
,
slategrey
:
"
708090
"
,
snow
:
"
fffafa
"
,
springgreen
:
"
00ff7f
"
,
steelblue
:
"
4682b4
"
,
tan
:
"
d2b48c
"
,
teal
:
"
008080
"
,
thistle
:
"
d8bfd8
"
,
tomato
:
"
ff6347
"
,
turquoise
:
"
40e0d0
"
,
violet
:
"
ee82ee
"
,
wheat
:
"
f5deb3
"
,
white
:
"
fff
"
,
whitesmoke
:
"
f5f5f5
"
,
yellow
:
"
ff0
"
,
yellowgreen
:
"
9acd32
"
};
// Make it easy to access colors via `hexNames[hex]`
var
hexNames
=
tinycolor
.
hexNames
=
flip
(
names
);
// Utilities
// ---------
// `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`
function
flip
(
o
)
{
var
flipped
=
{
};
for
(
var
i
in
o
)
{
if
(
o
.
hasOwnProperty
(
i
))
{
flipped
[
o
[
i
]]
=
i
;
}
}
return
flipped
;
}
// Return a valid alpha value [0,1] with all invalid values being set to 1
function
boundAlpha
(
a
)
{
a
=
parseFloat
(
a
);
if
(
isNaN
(
a
)
||
a
<
0
||
a
>
1
)
{
a
=
1
;
}
return
a
;
}
// Take input from [0, n] and return it as [0, 1]
function
bound01
(
n
,
max
)
{
if
(
isOnePointZero
(
n
))
{
n
=
"
100%
"
;
}
var
processPercent
=
isPercentage
(
n
);
n
=
mathMin
(
max
,
mathMax
(
0
,
parseFloat
(
n
)));
// Automatically convert percentage into number
if
(
processPercent
)
{
n
=
parseInt
(
n
*
max
,
10
)
/
100
;
}
// Handle floating point rounding errors
if
((
Math
.
abs
(
n
-
max
)
<
0.000001
))
{
return
1
;
}
// Convert into [0, 1] range if it isn't already
return
(
n
%
max
)
/
parseFloat
(
max
);
}
// Force a number between 0 and 1
function
clamp01
(
val
)
{
return
mathMin
(
1
,
mathMax
(
0
,
val
));
}
// Parse a base-16 hex value into a base-10 integer
function
parseIntFromHex
(
val
)
{
return
parseInt
(
val
,
16
);
}
// Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
// <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
function
isOnePointZero
(
n
)
{
return
typeof
n
==
"
string
"
&&
n
.
indexOf
(
'
.
'
)
!=
-
1
&&
parseFloat
(
n
)
===
1
;
}
// Check to see if string passed in is a percentage
function
isPercentage
(
n
)
{
return
typeof
n
===
"
string
"
&&
n
.
indexOf
(
'
%
'
)
!=
-
1
;
}
// Force a hex value to have 2 characters
function
pad2
(
c
)
{
return
c
.
length
==
1
?
'
0
'
+
c
:
''
+
c
;
}
// Replace a decimal with it's percentage value
function
convertToPercentage
(
n
)
{
if
(
n
<=
1
)
{
n
=
(
n
*
100
)
+
"
%
"
;
}
return
n
;
}
// Converts a decimal to a hex value
function
convertDecimalToHex
(
d
)
{
return
Math
.
round
(
parseFloat
(
d
)
*
255
).
toString
(
16
);
}
// Converts a hex value to a decimal
function
convertHexToDecimal
(
h
)
{
return
(
parseIntFromHex
(
h
)
/
255
);
}
var
matchers
=
(
function
()
{
// <http://www.w3.org/TR/css3-values/#integers>
var
CSS_INTEGER
=
"
[-
\\
+]?
\\
d+%?
"
;
// <http://www.w3.org/TR/css3-values/#number-value>
var
CSS_NUMBER
=
"
[-
\\
+]?
\\
d*
\\
.
\\
d+%?
"
;
// Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome.
var
CSS_UNIT
=
"
(?:
"
+
CSS_NUMBER
+
"
)|(?:
"
+
CSS_INTEGER
+
"
)
"
;
// Actual matching.
// Parentheses and commas are optional, but not required.
// Whitespace can take the place of commas or opening paren
var
PERMISSIVE_MATCH3
=
"
[
\\
s|
\\
(]+(
"
+
CSS_UNIT
+
"
)[,|
\\
s]+(
"
+
CSS_UNIT
+
"
)[,|
\\
s]+(
"
+
CSS_UNIT
+
"
)
\\
s*
\\
)?
"
;
var
PERMISSIVE_MATCH4
=
"
[
\\
s|
\\
(]+(
"
+
CSS_UNIT
+
"
)[,|
\\
s]+(
"
+
CSS_UNIT
+
"
)[,|
\\
s]+(
"
+
CSS_UNIT
+
"
)[,|
\\
s]+(
"
+
CSS_UNIT
+
"
)
\\
s*
\\
)?
"
;
return
{
CSS_UNIT
:
new
RegExp
(
CSS_UNIT
),
rgb
:
new
RegExp
(
"
rgb
"
+
PERMISSIVE_MATCH3
),
rgba
:
new
RegExp
(
"
rgba
"
+
PERMISSIVE_MATCH4
),
hsl
:
new
RegExp
(
"
hsl
"
+
PERMISSIVE_MATCH3
),
hsla
:
new
RegExp
(
"
hsla
"
+
PERMISSIVE_MATCH4
),
hsv
:
new
RegExp
(
"
hsv
"
+
PERMISSIVE_MATCH3
),
hsva
:
new
RegExp
(
"
hsva
"
+
PERMISSIVE_MATCH4
),
hex3
:
/^#
?([
0-9a-fA-F
]{1})([
0-9a-fA-F
]{1})([
0-9a-fA-F
]{1})
$/
,
hex6
:
/^#
?([
0-9a-fA-F
]{2})([
0-9a-fA-F
]{2})([
0-9a-fA-F
]{2})
$/
,
hex4
:
/^#
?([
0-9a-fA-F
]{1})([
0-9a-fA-F
]{1})([
0-9a-fA-F
]{1})([
0-9a-fA-F
]{1})
$/
,
hex8
:
/^#
?([
0-9a-fA-F
]{2})([
0-9a-fA-F
]{2})([
0-9a-fA-F
]{2})([
0-9a-fA-F
]{2})
$/
};
})();
// `isValidCSSUnit`
// Take in a single string / number and check to see if it looks like a CSS unit
// (see `matchers` above for definition).
function
isValidCSSUnit
(
color
)
{
return
!!
matchers
.
CSS_UNIT
.
exec
(
color
);
}
// `stringInputToObject`
// Permissive string parsing. Take in a number of formats, and output an object
// based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`
function
stringInputToObject
(
color
)
{
color
=
color
.
replace
(
trimLeft
,
''
).
replace
(
trimRight
,
''
).
toLowerCase
();
var
named
=
false
;
if
(
names
[
color
])
{
color
=
names
[
color
];
named
=
true
;
}
else
if
(
color
==
'
transparent
'
)
{
return
{
r
:
0
,
g
:
0
,
b
:
0
,
a
:
0
,
format
:
"
name
"
};
}
// Try to match string input using regular expressions.
// Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]
// Just return an object and let the conversion functions handle that.
// This way the result will be the same whether the tinycolor is initialized with string or object.
var
match
;
if
((
match
=
matchers
.
rgb
.
exec
(
color
)))
{
return
{
r
:
match
[
1
],
g
:
match
[
2
],
b
:
match
[
3
]
};
}
if
((
match
=
matchers
.
rgba
.
exec
(
color
)))
{
return
{
r
:
match
[
1
],
g
:
match
[
2
],
b
:
match
[
3
],
a
:
match
[
4
]
};
}
if
((
match
=
matchers
.
hsl
.
exec
(
color
)))
{
return
{
h
:
match
[
1
],
s
:
match
[
2
],
l
:
match
[
3
]
};
}
if
((
match
=
matchers
.
hsla
.
exec
(
color
)))
{
return
{
h
:
match
[
1
],
s
:
match
[
2
],
l
:
match
[
3
],
a
:
match
[
4
]
};
}
if
((
match
=
matchers
.
hsv
.
exec
(
color
)))
{
return
{
h
:
match
[
1
],
s
:
match
[
2
],
v
:
match
[
3
]
};
}
if
((
match
=
matchers
.
hsva
.
exec
(
color
)))
{
return
{
h
:
match
[
1
],
s
:
match
[
2
],
v
:
match
[
3
],
a
:
match
[
4
]
};
}
if
((
match
=
matchers
.
hex8
.
exec
(
color
)))
{
return
{
r
:
parseIntFromHex
(
match
[
1
]),
g
:
parseIntFromHex
(
match
[
2
]),
b
:
parseIntFromHex
(
match
[
3
]),
a
:
convertHexToDecimal
(
match
[
4
]),
format
:
named
?
"
name
"
:
"
hex8
"
};
}
if
((
match
=
matchers
.
hex6
.
exec
(
color
)))
{
return
{
r
:
parseIntFromHex
(
match
[
1
]),
g
:
parseIntFromHex
(
match
[
2
]),
b
:
parseIntFromHex
(
match
[
3
]),
format
:
named
?
"
name
"
:
"
hex
"
};
}
if
((
match
=
matchers
.
hex4
.
exec
(
color
)))
{
return
{
r
:
parseIntFromHex
(
match
[
1
]
+
''
+
match
[
1
]),
g
:
parseIntFromHex
(
match
[
2
]
+
''
+
match
[
2
]),
b
:
parseIntFromHex
(
match
[
3
]
+
''
+
match
[
3
]),
a
:
convertHexToDecimal
(
match
[
4
]
+
''
+
match
[
4
]),
format
:
named
?
"
name
"
:
"
hex8
"
};
}
if
((
match
=
matchers
.
hex3
.
exec
(
color
)))
{
return
{
r
:
parseIntFromHex
(
match
[
1
]
+
''
+
match
[
1
]),
g
:
parseIntFromHex
(
match
[
2
]
+
''
+
match
[
2
]),
b
:
parseIntFromHex
(
match
[
3
]
+
''
+
match
[
3
]),
format
:
named
?
"
name
"
:
"
hex
"
};
}
return
false
;
}
function
validateWCAG2Parms
(
parms
)
{
// return valid WCAG2 parms for isReadable.
// If input parms are invalid, return {"level":"AA", "size":"small"}
var
level
,
size
;
parms
=
parms
||
{
"
level
"
:
"
AA
"
,
"
size
"
:
"
small
"
};
level
=
(
parms
.
level
||
"
AA
"
).
toUpperCase
();
size
=
(
parms
.
size
||
"
small
"
).
toLowerCase
();
if
(
level
!==
"
AA
"
&&
level
!==
"
AAA
"
)
{
level
=
"
AA
"
;
}
if
(
size
!==
"
small
"
&&
size
!==
"
large
"
)
{
size
=
"
small
"
;
}
return
{
"
level
"
:
level
,
"
size
"
:
size
};
}
// Node: Export function
if
(
typeof
module
!==
"
undefined
"
&&
module
.
exports
)
{
module
.
exports
=
tinycolor
;
}
// AMD/requirejs: Define the module
else
if
(
typeof
define
===
'
function
'
&&
define
.
amd
)
{
define
(
function
()
{
return
tinycolor
;});
}
// Browser: Expose to window
else
{
window
.
tinycolor
=
tinycolor
;
}
})(
Math
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment