当前位置: 首页 > 知识库问答 >
问题:

为什么180度和-180度的色调旋转不能产生原始颜色?

阳文轩
2023-03-14

通过阅读HSL / HSV色彩理论,我得到的印象是色调分量是一个周期性属性,每360度重复一次,可以独立于饱和度和亮度/值而改变。如果我错了,请纠正我,但这些陈述在逻辑上遵循前面的定义:

    < li >将色调旋转360度会产生相同的颜色 < li >将色调旋转180度两次会产生原始颜色 < li >将色调旋转180度,然后旋转-180度,产生原始颜色

但是,只有选项 1 是正确的。将色调旋转 4 倍 90 度,产生的颜色甚至与原始颜色相差不远。

此外,使用-webkit过滤器和SVG

<filter><feColorMatrix in="SourceGraphic" type="hueRotate" values="..." /></filter>

对于相同的旋转,不要产生相同的结果。另一方面,SVG过滤器生成的颜色在浏览器之间是一致的。

有没有色相旋转的“隐藏”属性,让操作不联想?

webkit过滤器和SVG的例子可以在这里找到:http://jsfiddle.net/maros_urbanec/ARsjb/5/

共有3个答案

百里锋
2023-03-14

TL;将颜色从floats(过滤器内部)转换为bytes(其他地方)时出现dr错误。

所以它比这更复杂一点,规范为色调旋转矩阵提供了一个很好的公式,例如180度的公式是(不包括α和移位):

-0.5747  1.4304   0.1444
 0.4252  0.4304   0.1444
 0.4252  1.4304  -0.8556

注意,如果你把它本身乘以,你会得到(到小数点后四位):

 0.9999  0.0001   0.0000
 0.0000  1.0      0.0
 0.0000  0.0000   1.0

这非常接近于单位矩阵或空变换。

这将是完美的,除了浏览器在每个过滤器之间转换回RGB。看看当我们旋转鲜红色时会发生什么:

-0.5747  1.4304   0.1444     1     -0.5747
 0.4252  0.4304   0.1444  *  0  =   0.4252
 0.4252  1.4304  -0.8556     0      0.4252

我们得到了一种无法用0到255之间的值表示的RGB颜色。因此,在RGB转换过程中,它被绑定并四舍五入为0 0.4235 0.4235,当它再次旋转时,我们得到的是深色的去饱和红色,0.6667 0.2431 0.2431。

邴星洲
2023-03-14

迈克尔的回答太棒了,我真希望我以前看到过;但是,由于我不仅需要理解它们的怪异之处,还需要理解它们的怪异之处(我想绕过它们的逻辑,所以我需要数学知识),我用Javascript编写了一个< code>hue-rotate实现(主要来自于阅读Firefox的源代码),它模拟了Webkit/Blink/Gecko使用的< code>hue-rotate。

再次强调,这里的重点只是了解它产生了什么结果。

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;
}
<p>
    This algorithm emulates the wierd, nonsensical and completely 
    idiotic <code>hue-rotate</code> 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.
</p>
<span>#</span>
<input type="text" id="color" placeholder="RRGGBB">
<input type="text" id="angle" placeholder="degrees">
<button onclick="calculate()">Calculate</button>
<p id="result"></p>
端木皓君
2023-03-14

在CSS和SVG滤镜中,没有到HSV或HSL的转换-色调旋转快捷键使用RGB空间中的线性矩阵近似来执行色调旋转。正如你所看到的,对于小旋转和高饱和度的颜色,这不能很好地保持饱和度或亮度。

真正的色调旋转,将首先将输入的RGB颜色转换为HSL,调整H,然后转换回RGB。过滤器不这样做。这种转换不能用线性矩阵精确逼近,所以当色调被精确改变(大部分)时,饱和度和亮度会到处都是。这些效果是非线性的,所以将较小的操作加在一起会产生不同的颜色,而不是做一个大的操作。

(SVG和CSS过滤器中的颜色差异可能是由于使用了不同的颜色空间(sRGB与linearRGB)-这些应该是相同的。)

更新:我有足够的兴趣去做一个手动比较。如您所见,滤镜在0到180度范围内旋转纯色的色调方面做得很糟糕。此图比较了通过手动插入 hsl 颜色(外环)完成的手动色调旋转与基色(内环)上的滤镜色调旋转

如果你想玩代码链接:http://codepen.io/mullany/pen/fwHrd

 类似资料:
  • 我写了一个C#代码,在下载时合并两个pdf文件,但是它将一些(不是全部)文档旋转了180度。我已经附上了我上传的样本文件。 请帮助我。 示例文件

  • 我希望我的移动菜单上的向下箭头旋转180度,并在点击时朝上。我还想动画旋转平稳过渡。我使用Javascript切换一个". js-Rotate"类在我的". fa-角-向下"字体-真棒类。 JS函数中的最后一行控制此行为: 我尝试添加一个“transition:transform1s到“.fa角度向下”,但我没有运气。 CSS可通过以下链接的sass/组件/_navigation.scss获得:h

  • 问题内容: 是否有一个Java库,用于以90度为增量旋转JPEG文件,而不会导致图像质量下降? 问题答案: 我发现了这一点:http : //mediachest.sourceforge.net/mediautil/ API:http : //mediachest.sourceforge.net/mediautil/javadocs/mediautil/image/jpeg/LLJTran.htm

  • 我有两个NetCDF文件,每个文件都有不同的年份,我想将它们连接起来。它们似乎有相同的结构,时间是无限的维度,除了一个文件的经度是0:360,另一个文件的经度是-180:180。 这个问题解决了如何使用 R 中的栅格包来处理这个问题,但我想使用 nco。 我已经找到了转换的说明(提供如下)-180:180- 关于我的NetCDF文件的详细信息: 这是我在手册中找到的将-180:180转换为0:36

  • 我有麻烦弄清楚什么应该是一个简单的任务,但似乎不能旋转这个雪佛龙180度点击。我们的RTE将标记转换为,我们使用的是jQuery的旧版本(1.12.4),但我不认为这些会导致问题。我已经尝试了多种脚本,到目前为止已经登陆了。有谁能看出我缺了什么吗?: null null 演示:https://jsfidle.net/codewalker/5su8029z/4/

  • 我实际上是在打印这个图案:https://imgur.com/a/ObixO5I 我得到的输出是: