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

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

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

const int RGBMAX = 255;

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

7 ответов


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

ваш код предоставляет "отрицательный" цвет.

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

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

EDIT: как отметил Алексей Семенюк, изменение Hue by (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) и инвертировать оттенок, но также 2) проверьте, не должен ли оттенок приближаться к середине, и если да, перейдите к либо полностью яркий, либо полностью темный.


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

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

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

код для перехода на 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);
}

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