/* * The MIT License (MIT) * * Copyright (c) 2016 B. Stultiens * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #include "hsv2rgb.h" void hsv2rgb_8b(int16_t h, uint8_t s, uint8_t v, uint8_t *r, uint8_t *g , uint8_t *b) { uint8_t sextant; uint8_t bb; uint16_t ww; uint8_t h_fraction; if (!(s)) { *(r) = *(g) = *(b) = (v); return; } sextant = h >> 8; HSV_SEXTANT_TEST(sextant); // Optional: Limit hue sextants to defined space HSV_POINTER_SWAP(sextant, r, g, b); // Swap pointers depending which sextant we are in *g = v; // Top level // Perform actual calculations /* * Bottom level: v * (1.0 - s) * --> (v * (255 - s) + error_corr) / 256 */ bb = ~s; ww = v * bb; ww += 1; // Error correction ww += ww >> 8; // Error correction *b = ww >> 8; h_fraction = h & 0xff; // 0...255 if(!(sextant & 1)) { // *r = ...slope_up...; /* * Slope up: v * (1.0 - s * (1.0 - h)) * --> (v * (255 - (s * (256 - h) + error_corr1) / 256) + error_corr2) / 256 */ ww = !h_fraction ? ((uint16_t)s << 8) : (s * (uint8_t)(-h_fraction)); ww += ww >> 8; // Error correction 1 bb = ww >> 8; bb = ~bb; ww = v * bb; ww += v >> 1; // Error correction 2 *r = ww >> 8; } else { // *r = ...slope_down...; /* * Slope down: v * (1.0 - s * h) * --> (v * (255 - (s * h + error_corr1) / 256) + error_corr2) / 256 */ ww = s * h_fraction; ww += ww >> 8; // Error correction 1 bb = ww >> 8; bb = ~bb; ww = v * bb; ww += v >> 1; // Error correction 2 *r = ww >> 8; /* * A perfect match for h_fraction == 0 implies: * *r = (ww >> 8) + (h_fraction ? 0 : 1) * However, this is an extra calculation that may not be required. */ } }