0

I am trying to change the saturation of an image by a certain amount but I am getting some strange results. I am using the following code

// shiftAmount should be a float value between -1 and 1
public static int[] saturation( int[] pixels, float shiftAmount )
{
        int[] newPixels = new int[ pixels.length ];

        for( int i = 0; i < pixels.length; i++ )
        {
            // get HSB color values
            Color rgb = new Color( pixels[ i ] );
            float[] hsb = Color.RGBtoHSB( rgb.getRed(), rgb.getGreen(), rgb.getBlue(), null );
            float hue =        hsb[ 0 ];
            float saturation = hsb[ 1 ];
            float brightness = hsb[ 2 ];

            // shift
            saturation += shiftAmount;
            if( saturation > 1f )
                saturation = 1f;
            else if( saturation < 0f )
                saturation = 0f;

            // convert HSB color back
            newPixels[ i ] = Color.HSBtoRGB( hue, saturation, brightness );
        }

        return newPixels;
}

Below is an example of 80% saturation shift in another image editing software (Aseprite) and one where I did it with my own code (using 0.8f).

Original image

What it looks like when I use Aseprite

What it looks like using my own code

As you can see, in the last image the colors are very distorted. Does anyone know how to solve this?

Luc Drenth
  • 3
  • 1
  • 4
  • What happens if you "shift" the saturation by, say, 0.01? 0.8 seems a very large value in a range 0-1, particularly when your base image seems highly saturated to start with. – Kevin Boone Sep 22 '20 at 11:26
  • When I shift by a small amount like 0.01 nothing really happens. When I start to up the value to around 3.0 the distortion starts getting seeable. – Luc Drenth Sep 22 '20 at 11:41
  • Are you certain that the pixel values you supply are in the correct format to start with? Because you convert from integers to floats and then back to integers, it's possible that your input data could be completely scrambled, and you wouldn't notice until you tried to do math on it. I believe that the integer inputs have to have RGB values in the range 0-255 packed in a specific order into the bottom 24 bits. Is that what you have? – Kevin Boone Sep 22 '20 at 11:57
  • The integer values are hexadecimal values. For example 0xff_80bbc0. I just found out the problem though. What Aseprite was doing for calculating the new saturation is `saturation += ( saturation * shiftAmount );`. That way, for example the white colors that have low saturation stay low and white. – Luc Drenth Sep 22 '20 at 12:08

0 Answers0