Как инвертировать цвет?


Я знаю, что это не будет непосредственно инвертировать цвет, это будет просто "противостоять" ему. Мне было интересно, знает ли кто-нибудь простой способ (несколько строк кода) инвертировать цвет из любого заданного цвета?

В данный момент у меня есть это (что не совсем определение инверта, потому что если я передам ему серый / серый цвет, он вернет что-то очень похожее, например 127, 127, 127):

const int RGBMAX = 255;

Color InvertMeAColour(Color ColourToInvert)
{
    return Color.FromArgb(RGBMAX - ColourToInvert.R, 
      RGBMAX - ColourToInvert.G, RGBMAX - ColourToInvert.B);
}
7 31

7 ответов:

Это зависит от того, что вы подразумеваете под "инвертированием" цвета

Ваш код содержит "негативный" цвет.

Вы ищете трансформацию красного в голубой, зеленого в фиолетовый, синего в желтый (и так далее) ? Если это так, вам нужно преобразовать ваш цвет RGB в HSV режиме (вы найдете здесь, чтобы сделать преобразование).

Затем вам просто нужно инвертировать значение оттенка (изменить Hue на 360-Hue) и преобразовать обратно в режим RGB.

Правка: как упоминал Алексей Семенюк, изменение Hue на (Hue + 180) % 360 является лучшим решением (оно не инвертирует оттенок, но находит противоположный цвет на цветовом круге)

Вы можете использовать :

MyColor=Color.FromArgb(MyColor.ToArgb()^0xffffff);

Он перевернет MyColor.

Попробуйте это:

uint InvertColor(uint rgbaColor)
{
    return 0xFFFFFF00u ^ rgbaColor; // Assumes alpha is in the rightmost byte, change as needed
}

Инвертировать биты каждого компонента отдельно:

Color InvertMeAColour(Color ColourToInvert)
{
   return Color.FromArgb((byte)~ColourToInvert.R, (byte)~ColourToInvert.G, (byte)~ColourToInvert.B);
}

EDIT: оператор ~ не работает с байтами автоматически, требуется приведение.

То, что у вас уже есть,-это RGB-Инверт. Существуют и другие способы классификации цветов и, следовательно, другие определения для инверсии цвета.

Но это звучит так, как будто вы хотите контрастный цвет, и нет простой инверсии, которая будет работать для всех цветов, включая RGB(127, 127, 127).

Что вам нужно, так это 1) преобразование в HSV (см. ThibThibs answer) и инвертировать оттенок, но также 2) проверьте, не близок ли оттенок к середине, и если да, то перейдите к любому полностью яркий или полностью темный.

Если вы хотите изменить каждый цвет, попробуйте вращательную функцию (сдвиг или добавление), а не переворачивающую функцию (инвертирование). Другими словами, рассмотрим диапазон от 0 до 255 для каждого отдельного цвета (красный, зеленый и синий), который должен быть обернут, соединенный на концах как круг значений. Затем переместите каждый цвет вокруг круга, добавив некоторое значение и выполнив mod 256. Например, если начальное значение для red равно 255, а вы добавляете 1, то получаете 0. Если вы сдвинете все три цвета на 128, вы получите резко различаются значения для каждого оригинального цвета на картинке, даже серого. Серый 127, 127, 127 становится белым 255, 255, 255. Серый 128, 128, 128 становится черным 0, 0, 0. Существует фотографический эффект, подобный тому, что называется Соляризацией, обнаруженный случайно человеком Рэем в 1930-х годах.

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

Вы также можете выполнять вращательные операции над оттенком, смещая оттенок каждый оригинальный цвет на некоторую величину на круге оттенков, который изменяет все цвета без изменения яркости, поэтому тени все еще выглядят как тени, делая людей похожими на Симпсонов или Смурфов, например.

Код для сдвига на 128 может выглядеть следующим образом:

public static Color Invert(this Color c) => Color.FromArgb(c.R.Invert(), c.G.Invert(), c.B.Invert());

public static byte Invert(this byte b) {
    unchecked {
        return (byte)(b + 128);
    }
}

Самый простой и ленивый способ, который я сделал, чтобы работать с наличием не только тройных 12x, но и смешанных значений, это:

Color invertedColor= Color.FromArgb(fromColor.ToArgb() ^ 0xffffff);

if (invertedColor.R > 110 && invertedColor.R < 150 &&
    invertedColor.G > 110 && invertedColor.G < 150 &&
    invertedColor.B > 110 && invertedColor.B < 150)
{
    int avg = (invertedColor.R + invertedColor.G + invertedColor.B) / 3;
    avg = avg > 128 ? 200 : 60;
    invertedColor= Color.FromArgb(avg, avg, avg);
}
Теперь

Имеет другой цвет, чем исходный, даже если у нас есть 128, 128, 128 или близкое к нему цветовое значение.