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. * 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 * 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. * 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 ## 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 .. automodule:: suou.codecs
@ -16,6 +16,7 @@ suou.codecs
b64encode b64encode
cb32decode cb32decode
cb32encode cb32encode
cb32lencode
jsonencode jsonencode
quote_css_string quote_css_string
rb64decode rb64decode

View file

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

View file

@ -1,18 +1,6 @@
suou.flask\_sqlalchemy suou.flask\_sqlalchemy
====================== ======================
.. automodule:: 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 .. 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 .. automodule:: suou.strtools
@ -9,4 +9,5 @@ suou.strtools
.. autosummary:: .. autosummary::
PrefixIdentifier PrefixIdentifier
SpitText

View file

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

View file

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

View file

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

View file

@ -22,6 +22,8 @@ from __future__ import annotations
from collections import namedtuple from collections import namedtuple
from functools import lru_cache from functools import lru_cache
from suou.mat import Matrix
class Chalk: class Chalk:
""" """
@ -143,15 +145,26 @@ class RGBColor(namedtuple('_WebColor', 'red green blue')):
*New in 0.12.0* *New in 0.12.0*
""" """
return SRGBColor(*( return SRGBColor(*(
(i / 12.92 if abs(c) <= 0.04045 else (i / 12.92 if abs(i) <= 0.04045 else
(-1 if i < 0 else 1) * (((abs(c) + 0.55)) / 1.055) ** 2.4) for i in self (-1 if i < 0 else 1) * (((abs(i) + 0.55)) / 1.055) ** 2.4) for i in self
)) ))
__add__ = blend_with __add__ = blend_with
def __str__(self): def __str__(self):
return f"rgb({self.red}, {self.green}, {self.blue})" 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 WebColor = RGBColor
@ -160,15 +173,43 @@ WebColor = RGBColor
class SRGBColor(namedtuple('_SRGBColor', 'red green blue')): 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* *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): def to_rgb(self):
return RGBColor(*( return RGBColor(*(
((-1 if i < 0 else 1) * (1.055 * (abs(i) ** (1/2.4)) - 0.055) ((-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)) 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) [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', ) __all__ = ('Matrix', )