Please explain this color blending mode formula so I can replicate it in PHP/ImageMagick

后端 未结 4 448
梦如初夏
梦如初夏 2021-01-12 21:46

I\'ve been trying to use ImageMagick to replicate Photoshops Colour Blend Mode. I found the following formulas in an online guide but I don\'t know what they mean. Do I just

4条回答
  •  执念已碎
    2021-01-12 22:28

    A while ago I reversed engineered Photoshop blending modes.

    Have a look here:

    http://www.kineticsystem.org/?q=node/13

    And here below the code I use to convert between HSY (Hue, Saturation, Luminosity) to and from RGB (Red, Green, Blue). Photoshop use something called Hexacones to calculate the saturation.

    Giovanni

    /**
     * This is the formula used by Photoshop to convert a color from
     * RGB (Red, Green, Blue) to HSY (Hue, Saturation, Luminosity).
     * The hue is calculated using the exacone approximation of the saturation
     * cone.
     * @param rgb The input color RGB normalized components.
     * @param hsy The output color HSY normalized components.
     */
    public static void rgbToHsy(double rgb[], double hsy[]) {
    
        double r = Math.min(Math.max(rgb[0], 0d), 1d);
        double g = Math.min(Math.max(rgb[1], 0d), 1d);
        double b = Math.min(Math.max(rgb[2], 0d), 1d);
    
        double h;
        double s;
        double y;
    
        // For saturation equals to 0 any value of hue are valid.
        // In this case we choose 0 as a default value.
    
        if (r == g && g == b) {            // Limit case.
            s = 0d; 
            h = 0d; 
        } else if ((r >= g) && (g >= b)) { // Sector 0: 0° - 60°
            s = r - b;
            h = 60d * (g - b) / s;
        } else if ((g > r) && (r >= b)) {  // Sector 1: 60° - 120°
            s = g - b;
            h = 60d * (g - r) / s  + 60d;
        } else if ((g >= b) && (b > r)) {  // Sector 2: 120° - 180°
            s = g - r;
            h = 60d * (b - r) / s + 120d;
        } else if ((b > g) && (g > r)) {   // Sector 3: 180° - 240°
            s = b - r;
            h = 60d * (b - g) / s + 180d;
        } else if ((b > r) && (r >= g)) {  // Sector 4: 240° - 300°
            s = b - g;
            h = 60d * (r - g) / s + 240d;
        } else {                           // Sector 5: 300° - 360°
            s = r - g;
            h = 60d * (r - b) / s + 300d;
        }
    
        y = R * r + G * g + B * b;
    
        // Approximations erros can cause values to exceed bounds.
    
        hsy[0] = h % 360;
        hsy[1] = Math.min(Math.max(s, 0d), 1d);
        hsy[2] = Math.min(Math.max(y, 0d), 1d);
    }
    
    /**
     * This is the formula used by Photoshop to convert a color from
     * HSY (Hue, Saturation, Luminosity) to RGB (Red, Green, Blue).
     * The hue is calculated using the exacone approximation of the saturation
     * cone.
     * @param hsy The input color HSY normalized components.
     * @param rgb The output color RGB normalized components.
     */
    public static void hsyToRgb(double hsy[], double rgb[]) {
    
        double h = hsy[0] % 360;
        double s = Math.min(Math.max(hsy[1], 0d), 1d);
        double y = Math.min(Math.max(hsy[2], 0d), 1d);
    
        double r;
        double g;
        double b;
    
        double k; // Intermediate variable.
    
        if (h >= 0d && h < 60d) {           // Sector 0: 0° - 60°
            k = s * h / 60d;
            b = y - R * s - G * k;
            r = b + s;
            g = b + k;
        } else if (h >= 60d && h < 120d) {  // Sector 1: 60° - 120°
            k = s * (h - 60d) / 60d;
            g = y + B * s + R * k;
            b = g - s;
            r = g - k;
        } else if (h >= 120d && h < 180d) { // Sector 2: 120° - 180°
            k = s * (h - 120d) / 60d;
            r = y - G * s - B * k;
            g = r + s;
            b = r + k;
        } else if (h >= 180d && h < 240d) { // Sector 3: 180° - 240°
            k = s * (h - 180d) / 60d;
            b = y + R * s + G * k;
            r = b - s;
            g = b - k;
        } else if (h >= 240d && h < 300d) { // Sector 4: 240° - 300°
            k = s * (h - 240d) / 60d;
            g = y - B * s - R * k;
            b = g + s;
            r = g + k;
        } else {                          // Sector 5: 300° - 360°
            k = s * (h - 300d) / 60d;
            r = y + G * s + B * k;
            g = r - s;
            b = r - k;
        }
    
        // Approximations erros can cause values to exceed bounds.
    
        rgb[0] = Math.min(Math.max(r, 0d), 1d);
        rgb[1] = Math.min(Math.max(g, 0d), 1d);
        rgb[2] = Math.min(Math.max(b, 0d), 1d);
    }
    

提交回复
热议问题