Java изменяет насыщенность, давая искаженные цвета

#java #awt #hsb

#java #awt #hsb

Вопрос:

Я пытаюсь изменить насыщенность изображения на определенную величину, но получаю некоторые странные результаты. Я использую следующий код

 // 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;
}
  

Ниже приведен пример 80%-ного сдвига насыщенности в другом программном обеспечении для редактирования изображений (Aseprite), в котором я сделал это с помощью собственного кода (используя 0.8f).

Исходное изображение

Как это выглядит, когда я использую Aseprite

Как это выглядит с использованием моего собственного кода

Как вы можете видеть, на последнем изображении цвета сильно искажены. Кто-нибудь знает, как это решить?

Комментарии:

1. Что произойдет, если вы «сдвинете» насыщенность, скажем, на 0,01? 0,8 кажется очень большим значением в диапазоне 0-1, особенно когда ваше базовое изображение с самого начала кажется очень насыщенным.

2. Когда я сдвигаюсь на небольшую величину, например, на 0,01, на самом деле ничего не происходит. Когда я начинаю увеличивать значение примерно до 3.0, искажение начинает становиться заметным.

3. Вы уверены, что значения пикселей, которые вы предоставляете, находятся в правильном формате для начала? Поскольку вы преобразуете целые числа в числа с плавающей запятой, а затем обратно в целые числа, возможно, что ваши входные данные могут быть полностью зашифрованы, и вы не заметите, пока не попытаетесь выполнить математическую обработку. Я считаю, что целочисленные входные данные должны иметь значения RGB в диапазоне 0-255, упакованные в определенном порядке в нижние 24 бита. Это то, что у вас есть?

4. Целочисленные значения являются шестнадцатеричными значениями. Например, 0xff_80bbc0. Я только что обнаружил проблему. Что Aseprite делал для вычисления новой насыщенности, так это saturation = ( saturation * shiftAmount ); . Таким образом, например, белые цвета с низкой насыщенностью остаются низкими и белыми.