{"id":15297468,"url":"https://github.com/nickythelion/ciris","last_synced_at":"2025-10-08T18:20:55.499Z","repository":{"id":62754275,"uuid":"546201591","full_name":"nickythelion/ciris","owner":"nickythelion","description":"A lightweight native Python library that makes working with color easier","archived":false,"fork":false,"pushed_at":"2022-11-12T07:25:57.000Z","size":50,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-20T19:51:51.641Z","etag":null,"topics":["color","color-processing","python","python-3","python-3-10","python-3-11","python-3-8","python-3-9","python3"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nickythelion.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-10-05T17:49:22.000Z","updated_at":"2022-11-05T20:16:16.000Z","dependencies_parsed_at":"2023-01-23T17:45:07.768Z","dependency_job_id":null,"html_url":"https://github.com/nickythelion/ciris","commit_stats":null,"previous_names":["nickythelion/iris"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nickythelion%2Fciris","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nickythelion%2Fciris/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nickythelion%2Fciris/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nickythelion%2Fciris/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nickythelion","download_url":"https://codeload.github.com/nickythelion/ciris/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245467615,"owners_count":20620216,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["color","color-processing","python","python-3","python-3-10","python-3-11","python-3-8","python-3-9","python3"],"created_at":"2024-09-30T19:17:46.244Z","updated_at":"2025-10-08T18:20:55.400Z","avatar_url":"https://github.com/nickythelion.png","language":"Python","readme":"# Ciris\n\n![GitHub](https://img.shields.io/github/license/nickythelion/ciris?style=plastic)\n![PyPI](https://img.shields.io/pypi/v/ciris)\n![PyPI - Python Version](https://img.shields.io/pypi/pyversions/ciris)\n![PyPI - Wheel](https://img.shields.io/pypi/wheel/ciris)\n\n\nCiris is a lightweight library that specializes on working with color.\nThe package does not rely on any third-party dependencies.\n\nThe name of a library is the first letter of the word \"color\" and the name of the Greek goddess of color, Iris, if you were interested :)\n\n# Color class\nCiris provides a handy Color class that provides functionality for working with color.\nThis class stores the color in HSV color space and allows the end user the greater\nflexibility while modifying the color.\n\n## Creating a Color class using HSV values\nSince the Color class uses HSV, the default constructor is set up to accept HSV values directly:\n```python\nfrom ciris import Color\n\nhue, saturation, value = 260, 90, 90\n\nc = Color(hue, saturation, value)\n```\nYou can also use the built-in function `Color.from_hsv()` to construct the Color object. \n```python\nfrom ciris import Color\n\nhue, saturation, value = 260, 90, 90\n\nc = Color.from_hsv(hue, saturation, value)\n```\nIn this case, both methods are equivalent. The latter was added for the sake of consistency with the other constructors.\n\n## Creating a Color object using RGB values\nThe Color object provides a `Color.from_rgb()` function which can be used to create Color object from RGB band values, like this:\n```python\nfrom ciris import Color\n\nr, g, b = 100, 0, 255\n\nc = Color.from_rgb(r, g, b)\n```\n\n## Creating a Color object using CMYK values\nIn case you need to create a Color object from CMYK values, you can use the `Color.from_cmyk()` method:\n```python\nfrom ciris import Color\n\nc, m, y, k = 15, 0, 45, 2\n\nc = Color.from_cmyk(c, m, y, k)\n```\nNote that CMYK values should be integers in range [0..100], not floats. For example, a CMYK color defined as (45%, 11%, 0%, 56%) should be passed as `c=45, m=11, y=0, k=56`\n\n## Creating a Color object using a hex-string\nIf you have a hex-string you can use the built-in `Color.from_hex()` method to create a Color object:\n```python\nfrom ciris import Color\n\nmy_hex_str = \"#00FF56\"\n\nc = Color.from_hex(my_hex_str)\n```\nNote that `Color.from_hex()` method only accepts a 7-symbol hex-string (a pound sign, 2 symbols for red, 2 symbols for green, 2 symbols for blue). Other variations, such as ARGB, are not yet supported.\n\n## Representing the color as HSV\nSince the HSV space is the space that the Color object uses to store data, no conversion is necessary.\nTo represent the color as HSV values, simply call the `Color.as_hsv()` method:\n```python\nfrom ciris import Color\n\nhue, saturation, value = 260, 90, 90\n\nc = Color.from_hsv(hue, saturation, value)\nhsv_tuple = c.as_hsv()\n```\nThis method returns a tuple with the signature `(hue_value, saturation_value, value_value)`\n\n## Representing the color as RGB\nTo convert the current color to RGB, simply call the `Color.as_rgb()` method:\n```python\nfrom ciris import Color\n\nhue, saturation, value = 260, 90, 90\n\nc = Color.from_hsv(hue, saturation, value)\nrgb_tuple = c.as_rgb()\n```\nThis method returns a tuple with the signature `(r_value, g_value, b_value)`.\n\n## Representing the color as CMYK\nTo convert the current color to CMYK, call the `Color.as_cmyk()` method:\n```python\nfrom ciris import Color\n\nhue, saturation, value = 260, 90, 90\n\nc = Color.from_hsv(hue, saturation, value)\ncmyk_tuple = c.as_cmyk()\n```\nThis method returns a tuple with the signature `(c_value, m_value, y_value, k_value)`. Note that these values are integers in range [0..100].\n\n## Altering the hue of the color\nTo alter the color's hue, use the `Color.hue_shift()` method. The method takes a required positional argument `amount: int`, which specifies the amount in degrees on a color wheel that the hue will be shifted by.\n\nFor example, this code will shift the color's hue by 30 degrees clockwise:\n```python\nfrom ciris import Color\n\nhue, saturation, value = 260, 90, 90\n\nc = Color.from_hsv(hue, saturation, value)\nc.hue_shift(30)\nprint(c.as_hsv()) # (290, 90, 90)\n```\nYou can also pass a negative integer into the method to shift the hue counterclockwise. For example, the code below shifts the color's hue by 60 degrees counterclockwise:\n```python\nfrom ciris import Color\n\nhue, saturation, value = 260, 90, 90\n\nc = Color.from_hsv(hue, saturation, value)\nc.hue_shift(-60)\nprint(c.as_hsv()) # (200, 90, 90)\n```\nSince the hue is always in range [0..360], the method will account for this. An example:\n```python\nfrom ciris import Color\n\nhue, saturation, value = 260, 90, 90\n\nc = Color.from_hsv(hue, saturation, value)\nc.hue_shift(120) # The shift has caused the hue to become out of acceptable range\n# The hue is a representation of a color wheel, which cannot be more than 360deg, so the method has corrected the hue\nprint(c.as_hsv()) # (20, 90, 90)\n```\nThe same logic works for negative shifts.\n\n## Altering the saturation of the color\nTo alter the color's saturation, use the `Color.adjust_saturation()` method. It takes a required positional argument `amount: int`, that indicated the amount that the saturation needs to be adjusted by.\n\nFor example, this code below raises the color's saturation by 5%:\n```python\nfrom ciris import Color\n\nhue, saturation, value = 260, 90, 90\n\nc = Color.from_hsv(hue, saturation, value)\nc.adjust_saturation(5)\nprint(c.as_hsv()) # (260, 95, 90)\n```\nYou can also pass a negative integer to lower the saturation level:\n```python\nfrom ciris import Color\n\nhue, saturation, value = 260, 90, 90\n\nc = Color.from_hsv(hue, saturation, value)\nc.adjust_saturation(-10)\nprint(c.as_hsv()) # (260, 80, 90)\n```\nSince the saturation level should always be in range [0..100], the method will cap any excessive adjustment:\n```python\nfrom ciris import Color\n\nhue, saturation, value = 260, 90, 90\n\nc = Color.from_hsv(hue, saturation, value)\nc.adjust_saturation(60000)\n# The saturation has only been raised by 10 due to it being capped\nprint(c.as_hsv()) # (260, 100, 90)\n```\n\n## Altering the color's value\nTo adjust color's value, use the `Color.lighten()` and `Color.darken()` methods to lighten and darken the color respectively:\n```python\nfrom ciris import Color\n\nhue, saturation, value = 260, 90, 90\n\nc = Color.from_hsv(hue, saturation, value)\nc.lighten(10)\nprint(c.as_hsv()) # (200, 90, 100)\n```\n```python\nfrom ciris import Color\n\nhue, saturation, value = 260, 90, 90\n\nc = Color.from_hsv(hue, saturation, value)\nc.darken(60)\nprint(c.as_hsv()) # (260, 90, 30)\n```\nThese methods do accept negative integers. In that case their functionality is reversed.\nSince the value should always be in range [0..100], the method will cap any excessive adjustment:\n```python\nfrom ciris import Color\n\nhue, saturation, value = 260, 90, 90\n\nc = Color.from_hsv(hue, saturation, value)\nc.lighten(10000)\nprint(c.as_hsv()) # (200, 90, 100)\n```\n```python\nfrom ciris import Color\n\nhue, saturation, value = 260, 90, 90\n\nc = Color.from_hsv(hue, saturation, value)\nc.darken(600000)\nprint(c.as_hsv()) # (260, 90, 0)\n```\n\n## Inverting the color\nTo invert the color, use the `Color.invert()` method:\n```python\nfrom ciris import Color\n\nhue, saturation, value = 260, 90, 90\n\nc = Color.from_hsv(hue, saturation, value)\nc.invert()\nprint(c.as_hsv()) # (80, 90, 90)\n```\n\n## Applying complementary harmony rule to the color\nTo apply the complementary rule to the current color, use `Color.harmony_complementary()` method:\n```python\nfrom ciris import Color\n\nhue, saturation, value = 260, 90, 90\n\nc = Color.from_hsv(hue, saturation, value)\nrule = c.harmony_complementary()\n```\nThis method returns a [HarmonyRule](#harmonyrule-class) object.\n\n## Applying split complementary harmony rule to the color\nTo apply the split complementary rule to the current color, use `Color.harmony_split_complementary()` method. You can also pass an optional argument `phi: int` that indicates the offset in degrees that will be used. By default it is 150deg:\n```python\nfrom ciris import Color\n\nhue, saturation, value = 260, 90, 90\n\nc = Color.from_hsv(hue, saturation, value)\nrule = c.harmony_split_complementary(phi=40) # The offset used is 40deg\n```\n\nThis method returns a [HarmonyRule](#harmonyrule-class) object.\n\n## Applying triadic harmony rule to the color\nTo apply the triadic rule to the current color, use `Color.harmony_triadic()` method.\n```python\nfrom ciris import Color\n\nhue, saturation, value = 260, 90, 90\n\nc = Color.from_hsv(hue, saturation, value)\nrule = c.harmony_triadic()\n```\n\nThis method returns a [HarmonyRule](#harmonyrule-class) object.\n\n## Applying tetradic harmony rule to the color\nTo apply the tetradic rule to the current color, use `Color.harmony_tetradic()` method.\n```python\nfrom ciris import Color\n\nhue, saturation, value = 260, 90, 90\n\nc = Color.from_hsv(hue, saturation, value)\nrule = c.harmony_tetradic()\n```\n\nThis method returns a [HarmonyRule](#harmonyrule-class) object.\n\n## Applying analogous harmony rule to the color\nTo apply the split complementary rule to the current color, use `Color.harmony_analogous()` method. You can also pass an optional argument `phi: int` that indicates the offset in degrees that will be used. By default it is 30deg:\n```python\nfrom ciris import Color\n\nhue, saturation, value = 260, 90, 90\n\nc = Color.from_hsv(hue, saturation, value)\nrule = c.harmony_split_complementary(phi=40) # The offset used is 40deg\n```\n\nThis method returns a [HarmonyRule](#harmonyrule-class) object.\n\n## Comparing the colors\nTo compare Color objects, use a simple `==` statement.\n\nFor example, the code below wil print `The colors are the same`:\n```python\nfrom ciris import Color\n\nif Color(255, 100, 100) == Color.from_hsv(255, 100, 100):\n    print(\"The colors are the same\")\n```\n\n## Looking up colors in a list\nThe Color objects are hashable, meaning that you can easily check if the color \nis already stored an a list of colors using a simple `in` statement:\n```python\nfrom ciris import Color\n\nb_and_w = [Color.from_hex(\"#FFFFFF\"), Color.from_hex(\"#000000\")]\nprint(Color.from_rgb(0, 0, 0) in b_and_w) # True\nprint(Color.from_rgb(62, 81, 22) in b_and_w) # False\n```\n\n# HarmonyRule class\nThis class is a dataclass that is used by ciris to describe any harmony rule that has been applied to the color.\n\nIt has 3 attributes:\n* `rule_type: str` - This attribute stores the type of rule that was applied. Available types are: `complementary`, `split_complementary`, `triadic`, `tetradic`, `analogous`\n* `base_color: Color` - This attribute stores the base color (the color that the rule was applied to)\n* `secondary_colors: List[Color]` - This attribute stores a list of colors that were derived from the base one according to the harmony rule\n\nAll these attributes have their appropriate getters.\n\n# Method chaining\nThe ciris' Color class supports method chaining, allowing you to write simple, concise and practical one-liners, such as:\n\n### Color conversion\n```python\nfrom ciris import Color\nc = Color.from_hsv(260, 90, 90).as_hex()\nv = Color.from_rgb(145, 90, 10).as_cmyk()\n# ...\ng = Color.from_hex(\"#ff0097\").as_hsv()\n```\n\n### Color processing\n```python\nfrom ciris import Color\nnew_color = Color.from_rgb(old.r, old.g, old.b).invert().lighten(15).hue_shift(10).as_cmyk()\n```\n\n# Color Harmony Sources\nHere you can find the source material that was used to create color harmony rules\n* https://en.wikipedia.org/wiki/Harmony_(color)\n* https://blog.thepapermillstore.com/color-theory-color-harmonies/\n* https://blog.matthewgove.com/2021/07/02/color-theory-a-simple-exercise-in-mathematics-and-graphic-design/\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnickythelion%2Fciris","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnickythelion%2Fciris","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnickythelion%2Fciris/lists"}