0.12.0a4 add XYZ color

This commit is contained in:
Yusur 2025-12-20 07:50:43 +01:00
parent e6ee355f2e
commit ef645bd4da
17 changed files with 132 additions and 29 deletions

View file

@ -5,7 +5,7 @@
* All `AuthSrc()` derivatives, deprecated and never used, have been removed.
* New module `mat` adds a shallow reimplementation of `Matrix()` in order to implement matrix multiplication
* Removed obsolete `configparse` implementation that has been around since 0.3 and shelved since 0.4.
* `color`: added support for conversion from RGB to sRGB
* `color`: added support for conversion from RGB to sRGB, XYZ
## 0.11.2

19
docs/color.rst Normal file
View file

@ -0,0 +1,19 @@
Color
=====
.. currentmodule:: suou.color
...
Web colors
----------
.. autoclass:: RGBColor
.. autoclass:: WebColor
.. autoclass:: XYZColor

View file

@ -1,4 +1,4 @@
suou.codecs
suou.codecs
===========
.. automodule:: suou.codecs
@ -16,6 +16,7 @@ suou.codecs
b64encode
cb32decode
cb32encode
cb32lencode
jsonencode
quote_css_string
rb64decode

View file

@ -1,4 +1,4 @@
suou.color
suou.color
==========
.. automodule:: suou.color
@ -9,5 +9,7 @@ suou.color
.. autosummary::
Chalk
RGBColor
SRGBColor
WebColor

View file

@ -1,18 +1,6 @@
suou.flask\_sqlalchemy
suou.flask\_sqlalchemy
======================
.. automodule:: suou.flask_sqlalchemy
.. rubric:: Functions
.. autosummary::
require_auth
.. rubric:: Classes
.. autosummary::
FlaskAuthSrc

View file

@ -1,6 +1,12 @@
suou.legal
suou.legal
==========
.. automodule:: suou.legal
.. rubric:: Classes
.. autosummary::
Lawyer

View file

@ -0,0 +1,23 @@
suou.peewee
===========
.. automodule:: suou.peewee
.. rubric:: Functions
.. autosummary::
connect_reconnect
.. rubric:: Classes
.. autosummary::
ConnectToDatabase
PeeweeConnectionState
ReconnectMysqlDatabase
RegexCharField
SiqField
SnowflakeField

View file

@ -1,4 +1,4 @@
suou.strtools
suou.strtools
=============
.. automodule:: suou.strtools
@ -9,4 +9,5 @@ suou.strtools
.. autosummary::
PrefixIdentifier
SpitText

View file

@ -1,4 +1,4 @@
suou.validators
suou.validators
===============
.. automodule:: suou.validators
@ -12,4 +12,5 @@ suou.validators
must_be
not_greater_than
not_less_than
yesno

View file

@ -16,4 +16,5 @@ ease programmer's QoL and write shorter and cleaner code that works.
sqlalchemy
iding
validators
color
api

View file

@ -38,13 +38,14 @@ from .http import WantsContentType
from .color import chalk, WebColor
from .mat import Matrix
__version__ = "0.12.0a3"
__version__ = "0.12.0a4"
__all__ = (
'ConfigOptions', 'ConfigParserConfigSource', 'ConfigSource', 'ConfigValue',
'DictConfigSource', 'EnvConfigSource', 'I18n', 'Incomplete', 'JsonI18n',
'Matrix',
'MissingConfigError', 'MissingConfigWarning', 'PrefixIdentifier',
'RGBColor', 'SRGBColor',
'Siq', 'SiqCache', 'SiqGen', 'SiqType', 'Snowflake', 'SnowflakeGen',
'StringCase', 'TimedDict', 'TomlI18n', 'UserSigner', 'Wanted', 'WantsContentType',
'WebColor',

View file

@ -22,6 +22,8 @@ from __future__ import annotations
from collections import namedtuple
from functools import lru_cache
from suou.mat import Matrix
class Chalk:
"""
@ -143,15 +145,26 @@ class RGBColor(namedtuple('_WebColor', 'red green blue')):
*New in 0.12.0*
"""
return SRGBColor(*(
(i / 12.92 if abs(c) <= 0.04045 else
(-1 if i < 0 else 1) * (((abs(c) + 0.55)) / 1.055) ** 2.4) for i in self
(i / 12.92 if abs(i) <= 0.04045 else
(-1 if i < 0 else 1) * (((abs(i) + 0.55)) / 1.055) ** 2.4) for i in self
))
__add__ = blend_with
def __str__(self):
return f"rgb({self.red}, {self.green}, {self.blue})"
RGB_TO_XYZ = Matrix([
[0.41239079926595934, 0.357584339383878, 0.1804807884018343],
[0.21263900587151027, 0.715168678767756, 0.07219231536073371],
[0.01933081871559182, 0.11919477979462598, 0.9505321522496607]
])
def to_xyz(self):
return XYZColor(*(self.RGB_TO_XYZ @ Matrix.as_column(self)).get_column())
WebColor = RGBColor
@ -160,15 +173,43 @@ WebColor = RGBColor
class SRGBColor(namedtuple('_SRGBColor', 'red green blue')):
"""
Represent a color in the sRGB-Linear space.
Represent a color in the sRGB space.
*New in 0.12.0*
"""
red: float
green: float
blue: float
def __str__(self):
return f"srgb({self.red}, {self.green}, {self.blue})"
def to_rgb(self):
return RGBColor(*(
((-1 if i < 0 else 1) * (1.055 * (abs(i) ** (1/2.4)) - 0.055)
if abs(i) > 0.0031308 else 12.92 * i) for i in self))
def to_xyz(self):
return self.to_rgb().to_xyz()
__all__ = ('chalk', 'WebColor')
class XYZColor(namedtuple('_XYZColor', 'x y z')):
"""
Represent a color in the XYZ color space.
"""
XYZ_TO_RGB = Matrix([
[ 3.2409699419045226, -1.537383177570094, -0.4986107602930034],
[-0.9692436362808796, 1.8759675015077202, 0.04155505740717559],
[ 0.05563007969699366, -0.20397695888897652, 1.0569715142428786]
])
def to_rgb(self):
return RGBColor(*(self.XYZ_TO_RGB @ Matrix.as_column(self)).get_column())
__all__ = ('chalk', 'WebColor', "RGBColor", 'SRGBColor')

View file

@ -116,6 +116,25 @@ class Matrix(Collection[_T]):
[self[j, i] for j in range(sx)] for i in range(sy)
)
@classmethod
def as_row(cls, iterable: Iterable):
return cls([[*iterable]])
@classmethod
def as_column(cls, iterable: Iterable):
return cls([[x] for x in iterable])
def get_column(self, idx = 0):
sx, _ = self.shape()
return [
self[j, idx] for j in range(sx)
]
def get_row(self, idx = 0):
_, sy = self.shape()
return [
self[idx, j] for j in range(sy)
]
__all__ = ('Matrix', )