Photoshop 中的色相/饱和度调整图层算法

发布于 2024-10-07 06:12:35 字数 184 浏览 9 评论 0原文

有谁知道 Photoshop 中的调整图层是如何工作的?我需要生成一个结果图像,其中包含来自色相/饱和度调整图层的源图像和 HSL 值。转换为 RGB 然后与源颜色相乘不起作用。

或者是否可以用正常图层替换色相/饱和度调整图层并适当设置混合模式(多重,屏幕,色相,饱和度,颜色,亮度,...)? 如果是这样那怎么办?

谢谢

Does anyone know how adjustment layers work in Photoshop? I need to generate a result image having a source image and HSL values from Hue/Saturation adjustment layer. Conversion to RGB and then multiplication with the source color does not work.

Or is it possible to replace Hue/Saturation Adjustment Layer with normal layers with appropriately set blending modes (Mulitiply, Screen, Hue, Saturation, Color, Luminocity,...)?
If so then how?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

甜嗑 2024-10-14 06:12:35

我已经对选中“着色”复选框时的计算进行了逆向工程。下面的所有代码都是伪代码

输入为:

  • hueRGB,它是 HSV(photoshop_hue, 100, 100).ToRGB()
  • 饱和度<的 RGB 颜色 /em>,即 photoshop_saturation / 100.0(即 0..1)
  • 亮度,即 photoshop_lightness / 100.0(即 -1..1) 1)
  • value,即 pixel.ToHSV().Value,缩放至 0..1 范围。

对单个像素着色的方法:

color = blend2(rgb(128, 128, 128), hueRGB, saturation);

if (lightness <= -1)
    return black;
else if (lightness >= 1)
    return white;

else if (lightness >= 0)
    return blend3(black, color, white, 2 * (1 - lightness) * (value - 1) + 1)
else
    return blend3(black, color, white, 2 * (1 + lightness) * (value) - 1)

其中 blend2blend3 是:

blend2(left, right, pos):
    return rgb(left.R * (1-pos) + right.R * pos, same for green, same for blue)

blend3(left, main, right, pos):
    if (pos < 0)
        return blend2(left, main, pos + 1)
    else if (pos > 0)
        return blend2(main, right, pos)
    else
        return main

I've reverse-engineered the computation for when the "Colorize" checkbox is checked. All of the code below is pseudo-code.

The inputs are:

  • hueRGB, which is an RGB color for HSV(photoshop_hue, 100, 100).ToRGB()
  • saturation, which is photoshop_saturation / 100.0 (i.e. 0..1)
  • lightness, which is photoshop_lightness / 100.0 (i.e. -1..1)
  • value, which is the pixel.ToHSV().Value, scaled into 0..1 range.

The method to colorize a single pixel:

color = blend2(rgb(128, 128, 128), hueRGB, saturation);

if (lightness <= -1)
    return black;
else if (lightness >= 1)
    return white;

else if (lightness >= 0)
    return blend3(black, color, white, 2 * (1 - lightness) * (value - 1) + 1)
else
    return blend3(black, color, white, 2 * (1 + lightness) * (value) - 1)

Where blend2 and blend3 are:

blend2(left, right, pos):
    return rgb(left.R * (1-pos) + right.R * pos, same for green, same for blue)

blend3(left, main, right, pos):
    if (pos < 0)
        return blend2(left, main, pos + 1)
    else if (pos > 0)
        return blend2(main, right, pos)
    else
        return main
绮烟 2024-10-14 06:12:35

我已经弄清楚了Lightness是如何工作的。

输入参数亮度b在[0, 2]中,输出为c(颜色通道)。

if(b<1) c = b * c;
else    c = c + (b-1) * (1-c);

一些测试:

b = 0  >>>  c = 0  // black
b = 1  >>>  c = c  // same color
b = 2  >>>  c = 1  // white

但是,如果您选择某个间隔(例如红色而不是主色),亮度的表现完全不同,更像饱和度。

I have figured out how Lightness works.

The input parameter brightness b is in [0, 2], Output is c (color channel).

if(b<1) c = b * c;
else    c = c + (b-1) * (1-c);

Some tests:

b = 0  >>>  c = 0  // black
b = 1  >>>  c = c  // same color
b = 2  >>>  c = 1  // white

However, if you choose some interval (e.g. Reds instead of Master), Lightness behaves completely differently, more like Saturation.

假装不在乎 2024-10-14 06:12:35

Photoshop,不知道。但理论通常是:通过特定层的内部方法将RGB图像转换为HSL/HSV;然后根据指定的参数修改每个像素的 HSL,并将所得结果以 RGB 形式返回(用于显示)。

PaintShopPro7 用于以 30° (IIRC) 的离散增量分割 H 空间(假设范围为 0..360),因此如果仅碰撞“黄色”,即仅 H 分量值为 45-75 的像素,被考虑进行操纵。

红色 345..15、橙色 15..45、黄色 45..75、黄绿色 75..105、绿色 105..135 等。

if (h >= 45 && h < 75)
        s += s * yellow_percent;

还有其他可能性,例如应用衰减滤镜,如下所示:

/* For h=60, let m=1... and linearly fall off to h=75 m=0. */
m = 1 - abs(h - 60) / 15;
if (m < 0)
        m = 0;
s += s * yellow_percent * d;

Photoshop, dunno. But the theory is usually: The RGB image is converted to HSL/HSV by the particular layer's internal methods; each pixel's HSL is then modified according to the specified parameters, and the so-obtained result is being provided back (for displaying) in RGB.

PaintShopPro7 used to split up the H space (assuming a range of 0..360) in discrete increments of 30° (IIRC), so if you bumped only the "yellows", i.e. only pixels whose H component was valued 45-75 would be considered for manipulation.

reds 345..15, oranges 15..45, yellows 45..75, yellowgreen 75..105, greens 105..135, etc.

if (h >= 45 && h < 75)
        s += s * yellow_percent;

There are alternative possibilities, such as applying a falloff filter, as in:

/* For h=60, let m=1... and linearly fall off to h=75 m=0. */
m = 1 - abs(h - 60) / 15;
if (m < 0)
        m = 0;
s += s * yellow_percent * d;
救赎№ 2024-10-14 06:12:35

你好,我写了着色着色器,我的方程如下

inputRGB 是源图像,应该是单色

(r+g+b) * 0.333

colorRGB 是你的目标颜色
FinalRGB是结果

伪代码:

finalRGB = inputRGB * (colorRGB + inputRGB * 0.5);

我认为它快速高效

Hello I wrote colorize shader and my equation is as folows

inputRGB is the source image which should be in monochrome

(r+g+b) * 0.333

colorRGB is your destination color
finalRGB is the result

pseudo code:

finalRGB = inputRGB * (colorRGB + inputRGB * 0.5);

I think it's fast and efficient

诗化ㄋ丶相逢 2024-10-14 06:12:35

如果有人需要的话,我确实将@Roman Starkov解决方案翻译成java,但由于某种原因它效果不太好,然后我开始阅读一点,发现解决方案非常简单,有两件事必须完成:

  1. < p>当更改色调或饱和度时,仅替换原始图像的色调和饱和度,而亮度保持原始图像中的原样,这种混合方法称为 10.2.4。亮度混合模式:
    https://www.w3.org/TR/compositing-1/#backdrop< /a>

  2. 在 Photoshop 中更改亮度时,滑块会指示我们需要在原始亮度上添加或减去多少百分比,才能在 HSL 中获得白色或黑色。

例如 :
如果原始像素亮度为 0.7,亮度滑块 = 20
所以我们需要更多的 0.3 亮度才能达到 1,

所以我们需要添加到原始像素亮度:0.7 + 0.2*0.3;
这将是新像素的新混合亮度值。

@Roman Starkov解决方案Java实现:

//newHue, which is photoshop_hue (i.e. 0..360)
//newSaturation, which is photoshop_saturation / 100.0 (i.e. 0..1)
//newLightness, which is photoshop_lightness / 100.0 (i.e. -1..1)

//returns rgb int array of new color
private static int[] colorizeSinglePixel(int originlPixel,int newHue,float newSaturation,float newLightness)
{
    float[] originalPixelHSV = new float[3];
    Color.colorToHSV(originlPixel,originalPixelHSV);
    float originalPixelLightness = originalPixelHSV[2];

    float[] hueRGB_HSV = {newHue,100.0f,100.0f};
    int[] hueRGB = {Color.red(Color.HSVToColor(hueRGB_HSV)),Color.green(Color.HSVToColor(hueRGB_HSV)),Color.blue(Color.HSVToColor(hueRGB_HSV))};


    int color[] = blend2(new int[]{128,128,128},hueRGB,newSaturation);
    int blackColor[] = new int[]{Color.red(Color.BLACK),Color.green(Color.BLACK),Color.blue(Color.BLACK)};
    int whileColor[] = new int[]{Color.red(Color.WHITE),Color.green(Color.WHITE),Color.blue(Color.WHITE)};

    if(newLightness <= -1)
    {
        return blackColor;
    }
    else if(newLightness >=1)
    {
        return whileColor;
    }
    else if(newLightness >=0)
    {
        return blend3(blackColor,color,whileColor, (int) (2*(1-newLightness)*(originalPixelLightness-1) + 1));
    }
    else
    {
        return blend3(blackColor,color,whileColor, (int) ((1+newLightness)*(originalPixelLightness) - 1));
    }
}

private static int[] blend2(int[] left,int[] right,float pos)
{
    return new int[]{(int) (left[0]*(1-pos)+right[0]*pos),(int) (left[1]*(1-pos)+right[1]*pos),(int) (left[2]*(1-pos)+right[2]*pos)};
}

private static int[] blend3(int[] left,int[] main,int[] right,int pos)
{
    if(pos < 0)
    {
        return blend2(left,main,pos+1);
    }
    else if(pos > 0)
    {
        return blend2(main,right,pos);
    }
    else
    {
        return main;
    }

}

I did translate @Roman Starkov solution to java if any one needed, but for some reason It not worked so well, then I started read a little bit and found that the solution is very simple , there are 2 things have to be done :

  1. When changing the hue or saturation replace the original image only hue and saturation and the lightness stay as is was in the original image this blend method called 10.2.4. luminosity blend mode :
    https://www.w3.org/TR/compositing-1/#backdrop

  2. When changing the lightness in photoshop the slider indicates how much percentage we need to add or subtract to/from the original lightness in order to get to white or black color in HSL.

for example :
If the original pixel is 0.7 lightness and the lightness slider = 20
so we need more 0.3 lightness in order to get to 1

so we need to add to the original pixel lightness : 0.7 + 0.2*0.3;
this will be the new blended lightness value for the new pixel .

@Roman Starkov solution Java implementation :

//newHue, which is photoshop_hue (i.e. 0..360)
//newSaturation, which is photoshop_saturation / 100.0 (i.e. 0..1)
//newLightness, which is photoshop_lightness / 100.0 (i.e. -1..1)

//returns rgb int array of new color
private static int[] colorizeSinglePixel(int originlPixel,int newHue,float newSaturation,float newLightness)
{
    float[] originalPixelHSV = new float[3];
    Color.colorToHSV(originlPixel,originalPixelHSV);
    float originalPixelLightness = originalPixelHSV[2];

    float[] hueRGB_HSV = {newHue,100.0f,100.0f};
    int[] hueRGB = {Color.red(Color.HSVToColor(hueRGB_HSV)),Color.green(Color.HSVToColor(hueRGB_HSV)),Color.blue(Color.HSVToColor(hueRGB_HSV))};


    int color[] = blend2(new int[]{128,128,128},hueRGB,newSaturation);
    int blackColor[] = new int[]{Color.red(Color.BLACK),Color.green(Color.BLACK),Color.blue(Color.BLACK)};
    int whileColor[] = new int[]{Color.red(Color.WHITE),Color.green(Color.WHITE),Color.blue(Color.WHITE)};

    if(newLightness <= -1)
    {
        return blackColor;
    }
    else if(newLightness >=1)
    {
        return whileColor;
    }
    else if(newLightness >=0)
    {
        return blend3(blackColor,color,whileColor, (int) (2*(1-newLightness)*(originalPixelLightness-1) + 1));
    }
    else
    {
        return blend3(blackColor,color,whileColor, (int) ((1+newLightness)*(originalPixelLightness) - 1));
    }
}

private static int[] blend2(int[] left,int[] right,float pos)
{
    return new int[]{(int) (left[0]*(1-pos)+right[0]*pos),(int) (left[1]*(1-pos)+right[1]*pos),(int) (left[2]*(1-pos)+right[2]*pos)};
}

private static int[] blend3(int[] left,int[] main,int[] right,int pos)
{
    if(pos < 0)
    {
        return blend2(left,main,pos+1);
    }
    else if(pos > 0)
    {
        return blend2(main,right,pos);
    }
    else
    {
        return main;
    }

}
街角迷惘 2024-10-14 06:12:35

选中“着色”复选框后,底层的亮度将与色相和饱和度滑块的值相结合,并根据 https://en.wikipedia.org/wiki/HSL_and_HSV#From_HSL 。 (亮度滑块只是将亮度重新映射到比例的子集,正如您从直方图中看到的那样;效果非常糟糕,我不明白为什么有人会使用它。)

When the “Colorize” checkbox is checked, the lightness of the underlying layer is combined with the values of the Hue and Saturation sliders and converted from HSL to RGB according to the equations at https://en.wikipedia.org/wiki/HSL_and_HSV#From_HSL . (The Lightness slider just remaps the lightness to a subset of the scale as you can see from watching the histogram; the effect is pretty awful and I don’t see why anyone would ever use it.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文