Why doesn't hue rotation by +180deg and -180deg yield the original color?

前端 未结 3 1299
情深已故
情深已故 2020-12-01 11:36

By reading HSL/HSV color theory, I get the impression that hue component is a cyclical attribute that repeats every 360 degrees and can be changed independently of saturatio

3条回答
  •  时光说笑
    2020-12-01 12:05

    Michael's answer is awesome, and I wish I had seen it before; but since I need to not only understand they're damn wierd but also in which way (I want to work around their logic so I need the maths), I've coded a hue-rotate implementation in Javascript (which was mostly taken from reading Firefox's source code), which emulates the hue-rotate that Webkit/Blink/Gecko use.

    Again, the whole point here is just to understand what results it produces.

    function calculate() {
        // Get the RGB and angle to work with.
        var color = document.getElementById('color').value;
        if (! /^[0-9A-F]{6}$/i.test(color)) return alert('Bad color!');
        var angle = document.getElementById('angle').value;
        if (! /^-?[0-9]+$/i.test(angle)) return alert('Bad angle!');
        var r = parseInt(color.substr(0, 2), 16);
        var g = parseInt(color.substr(2, 2), 16);
        var b = parseInt(color.substr(4, 2), 16);
        var angle = (parseInt(angle) % 360 + 360) % 360;
        
        // Hold your breath because what follows isn't flowers.
        
        var matrix = [ // Just remember this is the identity matrix for
            1, 0, 0,   // Reds
            0, 1, 0,   // Greens
            0, 0, 1    // Blues
        ];
        
        // Luminance coefficients.
        var lumR = 0.2126;
        var lumG = 0.7152;
        var lumB = 0.0722;
        
        // Hue rotate coefficients.
        var hueRotateR = 0.143;
        var hueRotateG = 0.140;
        var hueRotateB = 0.283;
        
        var cos = Math.cos(angle * Math.PI / 180);
        var sin = Math.sin(angle * Math.PI / 180);
        
        matrix[0] = lumR + (1 - lumR) * cos - lumR * sin;
        matrix[1] = lumG - lumG * cos - lumG * sin;
        matrix[2] = lumB - lumB * cos + (1 - lumB) * sin;
        
        matrix[3] = lumR - lumR * cos + hueRotateR * sin;
        matrix[4] = lumG + (1 - lumG) * cos + hueRotateG * sin;
        matrix[5] = lumB - lumB * cos - hueRotateB * sin;
        
        matrix[6] = lumR - lumR * cos - (1 - lumR) * sin;
        matrix[7] = lumG - lumG * cos + lumG * sin;
        matrix[8] = lumB + (1 - lumB) * cos + lumB * sin;
        
        function clamp(num) {
            return Math.round(Math.max(0, Math.min(255, num)));
        }
        
        var R = clamp(matrix[0] * r + matrix[1] * g + matrix[2] * b);
        var G = clamp(matrix[3] * r + matrix[4] * g + matrix[5] * b);
        var B = clamp(matrix[6] * r + matrix[7] * g + matrix[8] * b);
        
        // Output the result
        var result = 'The original color, rgb(' + [r,g,b] + '), '
                   + 'when rotated by ' + angle + ' degrees '
                   + 'by the devil\'s logic, gives you '
                   + 'rgb(' + [R,G,B] + '). If I got it right.';
        document.getElementById('result').innerText = result;
    }
    // Listen for Enter key press.
    ['color', 'angle'].forEach(function(i) {
        document.getElementById(i).onkeypress = function(event) {
            var e = event || window.event, c = e.which || e.keyCode;
            if (c == '13') return calculate();
        }
    });
    body {
        font: 14px sans-serif;
        padding: 6px 8px;
    }
    
    input {
        width: 64px;
    }

    This algorithm emulates the wierd, nonsensical and completely idiotic hue-rotate CSS filter. I wanted to know how it worked, because it is out of touch with any definition of "hue" I've ever seen; the results it produces are stupid and I believe it was coded under extreme influence of meth, alcohol and caffeine, by a scientologist listening to Death Metal.

    #

    The snippet was taken from this answer.

提交回复
热议问题