{"id":26952728,"url":"https://github.com/yoyoberenguer/saturationeffect","last_synced_at":"2025-07-03T03:05:48.485Z","repository":{"id":57463993,"uuid":"429890302","full_name":"yoyoberenguer/SaturationEffect","owner":"yoyoberenguer","description":"Image saturation algorithms for real time processing","archived":false,"fork":false,"pushed_at":"2021-12-04T11:04:06.000Z","size":19649,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-05T01:41:29.109Z","etag":null,"topics":["2d-graphics","image-processing","pygame","python","saturation","special-effects"],"latest_commit_sha":null,"homepage":"","language":"Cython","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/yoyoberenguer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-11-19T18:01:03.000Z","updated_at":"2025-03-17T14:12:48.000Z","dependencies_parsed_at":"2022-09-05T05:30:18.515Z","dependency_job_id":null,"html_url":"https://github.com/yoyoberenguer/SaturationEffect","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/yoyoberenguer/SaturationEffect","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yoyoberenguer%2FSaturationEffect","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yoyoberenguer%2FSaturationEffect/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yoyoberenguer%2FSaturationEffect/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yoyoberenguer%2FSaturationEffect/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yoyoberenguer","download_url":"https://codeload.github.com/yoyoberenguer/SaturationEffect/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yoyoberenguer%2FSaturationEffect/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263250602,"owners_count":23437288,"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":["2d-graphics","image-processing","pygame","python","saturation","special-effects"],"created_at":"2025-04-03T00:31:06.056Z","updated_at":"2025-07-03T03:05:48.454Z","avatar_url":"https://github.com/yoyoberenguer.png","language":"Cython","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Saturation Effect\r\n\r\n![alt text](https://raw.githubusercontent.com/yoyoberenguer/SaturationEffect/main/SaturationEffect/Assets/full_range_saturation.png)\r\n\r\nThis library contains fast algorithms written in `Cython` and `python` to change \r\nthe saturation level of an image or textures.\r\nThis code is using extensively the HSL (Hue, Saturation, Lightness) algorithm \r\nin order to change the saturation level. Please see also the project `HSL` and \r\n`HSV` at the following URLs if you need more details regarding those projects\r\n\r\nhttps://github.com/yoyoberenguer/HSV \r\n\r\nhttps://github.com/yoyoberenguer/HSL\r\n\r\nReal time processing\r\n\r\n![alt text](SaturationEffect/Assets/SaturationEffect1.gif)\r\n\r\nThe methods can be used with a large variety of image format such as png, jpg, \r\nbmp etc, check pygame image format compatibility for more details. \r\nThe image format can be either 24-32 bit with or without the transparency channel \r\nand works with image containing per-pixel transparency (32 bit). \r\nHowever, this library is not compatible with 8-bit format surface.\r\n\r\nThese algorithms can be used offline or real time processing for \r\nIndy Game such as pygame or Arcade game as long as the game resolution \r\ndo not exceed 1280x1024. A modern CPU with at least 8 \r\nlogical processor is required to keep the game running between 30-60 fps.\r\n   \r\nThe algorithms are written using `cython` with OPENMP capability (multi-\r\nprocessing). This library is build by default with the flag OPENMP, \r\nproviding the best performance for real time processing. \r\nYou can also turn off the multi-processing to balance evenly the \r\nCPU load between your game and the real time saturation processing. \r\nPlease refer to the section `OPENMP` for more details on how to turn\r\nthe multi-processing on/off. \r\n\r\nThe saturation effect can be used for various projects such as image \r\nprocessing, 2D light effect, spritesheet, demos and video games, video \r\nimage processing, Saturation effect for camera\r\n\r\nThe project is under the `MIT license`\r\n\r\n### Saturation effect definition (from wikipedia) :\r\nThe saturation of a color is determined by a combination of light intensity\r\nand how much it is distributed across the spectrum of different wavelengths. \r\nThe purest (most saturated) color is achieved by using just one wavelength \r\nat a high intensity, such as in laser light. If the intensity drops, then as\r\na result the saturation drops. To desaturate a color of given intensity in a\r\nsubtractive system (such as watercolor), one can add white, black, gray, or \r\nthe hue's complement.\r\n\r\nHSL and HSV\r\nSaturation is also one of three coordinates in the HSL and HSV color spaces.\r\nHowever, in the HSL color space saturation exists independently of lightness. \r\nThat is, both a very light color and a very dark color can be heavily \r\nsaturated in HSL; whereas in the previous definitions—as well as in the HSV\r\ncolor space—colors approaching white all feature low saturation.\r\n\r\nExcitation purity is the relative distance from the white point.\r\nContours of constant purity can be found by shrinking the spectral locus about the white point.\r\nThe points along the line segment have the same hue, with pe increasing from 0 to 1 between the \r\nwhite point and position on the spectral locus (position of the color on the horseshoe shape in\r\nthe diagram) or (as at the saturated end of the line shown in the diagram) position on the line\r\nof purples.\r\n\r\n![alt text](https://raw.githubusercontent.com/yoyoberenguer/SaturationEffect/main/SaturationEffect/Assets/423px-Excitation_Purity.svg.png)\r\n\r\n\r\nimage ref : By I, User:adoniscik, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=3477910\r\n\r\n\r\n## Installation \r\ncheck the link for a newest version https://test.pypi.org/project/SaturationEffect/\r\n```\r\npip install SaturationEffect \r\n# or version 1.0.2  \r\npip install SaturationEffect==1.0.2\r\n```\r\n\r\n* version installed \r\n* Imported module is case sensitive \r\n```python\r\n\u003e\u003e\u003efrom SaturationEffect.saturation import __version__\r\n\u003e\u003e\u003e__version__\r\n```\r\n\r\n## Saturation mask \r\nThe library contains 4 methods using an optional mask to determine the pixels \r\nlayer to be changed during the saturation process. \r\nThe mask is build from a pygame.Surface (image) then converted to a 2d numpy.ndarray \r\nshape (width, height) of normalized float values.\r\nThe image format used by the mask can be a JPG, PNG, BMP, 24 -32 bit with or without \r\nalpha channel. \r\nNote that the method build_mask2d_alpha using the transparency layer will require a \r\nsurface compatible 32-bit with per-pixel transparency otherwise an error message will \r\nbe raised.\r\n\r\nYou can create 3 different type of masks:\r\n*  mask build from the grayscale values of the image \r\n*  mask build from the grayscale values of the image and converted to black \u0026 white\r\n*  mask build from the alpha channel of the image \r\n\r\n\r\n```cython\r\n# Grayscale mask\r\ncpdef inline object build_mask2d_grayscale(object surface_)\r\n# Black and White mask\r\ncpdef inline object build_mask2d_bw(object surface_)\r\n# Alpha mask\r\ncpdef inline object build_mask2d_alpha(object surface_)\r\n```\r\n\r\n## Saturation method details\r\nThis version includes various methods spread into two category 24-32 bit compatible \r\nimage format and 32-bit with per-pixel transparency layer.\r\nIf you wish to process an image without the transparency layer use a method that \r\nspecify the bitsize 24 (saturation24 for example). \r\nOn the contrary, if the image contains a transparency layer, use any of method with\r\nbitsize 32 such as (saturation32)\r\n\r\nInput arguments can be a numpy.ndarray, pygame.Surface or a C -buffer data type.\r\nChoose the right method accordingly\r\n```cython\r\n# Method using a mask (input can be a surface or a numpy.array)\r\n# Compatible 24 -32 bit \r\ncpdef saturation24_mask(array_, shift_, mask_)\r\ncpdef saturation24_mask1(surface_, shift_, mask_)\r\n# Compatible with 32 bit containing transparency layer\r\ncpdef saturation32_mask(surface_, shift_, mask_)\r\ncpdef saturation32_mask1(rgb_array_, alpha_array_, shift_, mask_)\r\n\r\n# Direct saturation, no mask compatible 24 -32 bit\r\ncpdef inline object saturation24(array_, shift_)\r\ncpdef inline object saturation32(array_, alpha_, shift_)\r\n\r\n# Input argument is C-buffer data type, the mask is compulsory, omitting \r\n# the mask will raise an error \r\ncpdef saturation_buffer_mask(buffer_, shift_, mask_array, width_, height_) \r\ncpdef saturation_buffer_mask_inplace(buffer_, shift_, mask_array, width_, height_)\r\n\r\n# Inplace method, the changes are applied to the surface directly\r\ncpdef inline object saturation24_inplace(array_, shift_)\r\ncpdef inline object saturation32_inplace(array_, shift_)\r\n```\r\n\r\n## Quick example\r\n\r\n```python\r\n\u003e\u003e\u003e from SaturationEffect import example\r\n```\r\n## Building cython code\r\n\r\n#### When do you need to compile the cython code ? \r\n```\r\nEach time you are modifying any of the following files \r\nsaturation.pyx, saturation.pxd, or any external C code if applicable\r\n\r\n1) open a terminal window\r\n2) Go in the main project directory where (saturation.pyx \u0026 \r\n   saturation.pxd files are located)\r\n3) run : python setup_saturation.py build_ext --inplace --force\r\n\r\nIf you have to compile the code with a specific python \r\nversion, make sure to reference the right python version \r\nin (python38 setup_saturation.py build_ext --inplace)\r\n\r\nIf the compilation fail, refers to the requirement section and \r\nmake sure cython and a C-compiler are correctly install on your\r\n system.\r\n- A compiler such visual studio, MSVC, CGYWIN setup correctly on \r\n  your system.\r\n  - a C compiler for windows (Visual Studio, MinGW etc) install \r\n  on your system and linked to your windows environment.\r\n  Note that some adjustment might be needed once a compiler is \r\n  install on your system, refer to external documentation or \r\n  tutorial in order to setup this process.e.g https://devblogs.\r\n  microsoft.com/python/unable-to-find-vcvarsall-bat/\r\n```\r\n## OPENMP \r\nIn the main project directory, locate the file `setup_saturation.py`.\r\nThe compilation flag /openmp is used by default.\r\nTo override the OPENMP feature and disable the multi-processing remove the flag `/openmp`\r\n\r\n####\r\n`setup_saturation.py`\r\n```python\r\n\r\next_modules=cythonize([\r\n        Extension(\"SaturationEffect.saturation\", [\"SaturationEffect/saturation.pyx\"],\r\n                  extra_compile_args=[\"/openmp\", \"/Qpar\", \"/fp:fast\", \"/O2\", \"/Oy\", \"/Ot\"], language=\"c\")]),\r\n```\r\nSave the change and build the cython code with the following instruction:\r\n\r\n```python setup_saturation.py build_ext --inplace --force```\r\n\r\nIf the project build successfully, the compilation will end up with the following lines\r\n```\r\nGenerating code\r\nFinished generating code\r\n```\r\nIf you have any compilation error refer to the section `Building cython code` \r\nand make sure your system has the following program \u0026 libraries installed. \r\nCheck also that the code is not running in a different thread.  \r\n- Pygame version \u003e 3\r\n- numpy \u003e= 1.18\r\n- cython \u003e=0.29.21 (C extension for python) \r\n- A C compiler for windows (Visual Studio, MinGW etc)\r\n\r\n## Credit\r\nYoann Berenguer \r\n\r\n## Dependencies :\r\n```\r\nnumpy \u003e= 1.18\r\npygame \u003e=2.0.0\r\ncython \u003e=0.29.21\r\n```\r\n\r\n## License :\r\n\r\nMIT License\r\n\r\nCopyright (c) 2019 Yoann Berenguer\r\n\r\nPermission is hereby granted, free of charge, to any person \r\nobtaining a copy of this software and associated documentation\r\nfiles (the \"Software\"), to deal in the Software without \r\nrestriction, including without limitation the rights to use, \r\ncopy, modify, merge, publish, distribute, sublicense, and/or \r\nsell copies of the Software, and to permit persons to whom the\r\nSoftware is furnished to do so, subject to the following \r\nconditions:\r\n\r\nThe above copyright notice and this permission notice shall be\r\nincluded in all copies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\r\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \r\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \r\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \r\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \r\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\r\nOTHER DEALINGS IN THE SOFTWARE.\r\n\r\n\r\n## Testing: \r\n```python\r\n\u003e\u003e\u003eimport SaturationEffect\r\n\u003e\u003e\u003efrom SaturationEffect.tests.test_saturation import run_testsuite\r\n\u003e\u003e\u003erun_testsuite()\r\n```\r\n\r\n## Timing :\r\nIn the directory tests under the main project path\r\n\r\nC:...tests\\python profiling.py\r\n```\r\nTESTING WITH IMAGE 1280x1024 (result in ms)\r\n\r\nPerformance testing saturation24_mask with mask     per call 0.035846148 overall time 3.58461s for 100 iterations\r\nPerformance testing saturation24_mask without mask  per call 0.044081281 overall time 4.40813s for 100\r\nPerformance testing saturation32_mask with mask     per call 0.058718479 overall time 5.87185s for 100\r\nPerformance testing saturation32_mask without mask  per call 0.056563972 overall time 5.6564s  for 100\r\nPerformance testing saturation24                    per call 0.045149282 overall time 4.51493s for 100\r\nPerformance testing saturation32                    per call 0.046752571 overall time 4.67526s for 100\r\nPerformance testing saturation24_inplace            per call 0.039684722 overall time 3.96847s for 100\r\nPerformance testing saturation32_inplace            per call 0.039565034 overall time 3.9565s  for 100\r\nPerformance testing saturation_buffer_mask          per call 0.054190551 overall time 5.41906s for 100\r\nPerformance testing saturation_buffer_mask_inplace  per call 0.052289168 overall time 5.22892s for 100\r\n```\r\n\r\n### Links \r\n```\r\nWIKIPEDIA https://en.wikipedia.org/wiki/Colorfulness\r\nWIKIPEDIA https://en.wikipedia.org/wiki/HSL_and_HSV\r\n```\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyoyoberenguer%2Fsaturationeffect","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyoyoberenguer%2Fsaturationeffect","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyoyoberenguer%2Fsaturationeffect/lists"}