2

I've been making an image editor in my free time and tried to use the HSL to RGB conversion formula here: HSL to RGB color conversion however I have come across an error.

Whenever I got to run my program the conversion does not work as it should, leaving the rgb with an unexpected grey colour. Here's some sample output data:

HSL: 0.0, 0.0, 1.0
RGB: 255.0, 255.0, 255.0
HSL: 214.0, 0.73, 0.5
RGB: 128.0, 128.0, 128.0
HSL: 214.0, 0.74, 0.5
RGB: 128.0, 128.0, 128.0
HSL: 214.0, 0.75, 0.5
RGB: 128.0, 128.0, 128.0
HSL: 214.0, 0.76, 0.5
RGB: 128.0, 128.0, 128.0
HSL: 214.0, 0.76, 0.5
RGB: 128.0, 128.0, 128.0

And below is my code. It's all written in Java.

public double[] hslToRgb(double h, double s, double l){

    System.out.println("HSL: " + h + ", " + s + ", " + l);

    double r = -1;
    double b = -1;
    double g = -1;

    if(s == 0){

        r = l;
        b = l;
        g = l;

    }else{

        double q = 1 < 0.5 ? l * (1 + s) : l + s - 1 * s;
        double p = 2 * l - q;

        r = hueToRgb(p, q, h + (1 / 3));
        g = hueToRgb(p, q, h);
        b = hueToRgb(p, q, h - (1/ 3));
    }

    r = Math.round(r * 255);
    b = Math.round(b * 255);
    g = Math.round(g * 255);

    System.out.println("RGB: " + r + ", " + g + ", " + b);
    double[] rgb = {r, g, b};

    return rgb;
}

private double hueToRgb(double p, double q, double t){

    if(t < 0){

        t++;
    }

    if(t > 1){

        t--;
    }

    if(t < 1 / 6){

        return p + (q - p) * 6 * t;
    }

    if(t < 1 / 2){

        return q;
    }

    if(t < 2 / 3){

        return p + (q - p) * ((2 / 3) - t) * 6;
    }

    return p;
}

Can anybody give me some insight as to what might be causing this? I feel like it's a minor error in my code but I can't find it anywhere.

Community
  • 1
  • 1
user438766
  • 21
  • 1

1 Answers1

2

Firstly, in the line double q = 1 < 0.5 ..., it's supposed to be the letter EL l, not the number 1 in two places.

double q = 1 < 0.5 ? l * (1 + s) : l + s - 1 * s;
           ^ ----- change from 1 to l ---- ^

Secondly, you have to be very careful about arithmetic which works differently in Java than JavaScript. When you have code like 1 / 3, since both are integers, the result will be an integer which means you get 0 rather than 0.3333.... In order to prevent using integer division, all of your divisions need to use at least one floating-point type:

if(t < 1.0 / 6){
       ^^^ change from 1 to 1.0
    return p + (q - p) * 6 * t;
}

if(t < 1.0 / 2){
       ^^^ change from 1 to 1.0
    return q;
}

if(t < 2.0 / 3){
       ^^^ change from 2 to 2.0
    return p + (q - p) * ((2.0 / 3) - t) * 6;
                           ^^^ change from 2 to 2.0
}

Also:

    r = hueToRgb(p, q, h + (1.0 / 3));
                            ^^^ change from 1 to 1.0
    g = hueToRgb(p, q, h);
    b = hueToRgb(p, q, h - (1.0 / 3));
                            ^^^ change from 1 to 1.0

Finally, in the code you copied from, the values for h, s, and l are all supposed to be between 0 and 1. So an H of 214 is not valid in your examples - you need to divide it by 360 first.

Here is a working code sample with the changes applied: http://ideone.com/QbXyYi

Input: 240.0 / 360.0, 1.0, 0.5

Output: [0, 0, 255.0]

mellamokb
  • 56,094
  • 12
  • 110
  • 136
  • 1
    I think you have found all the errors, so upvoted. But I'd also suggest to the OP avoid using those manifest constants altogether, and instead of trying to translate JavaScript to Java, understand the algorithm and re implement OP's own Java program. – paisanco Aug 12 '15 at 04:32