2009-07-22 5 views
28

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

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

const int RGBMAX = 255; 

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

Фактически, это * есть способ, которым обычно определяется инвертирование цвета ... что вы ищете вместо этого? –

+0

Что делать, если мой цвет был 127, 127, 127, проходя через мою функцию, не инвертировал бы его. – ThePower

+1

Возможно, вам нужно сгенерировать цвет фона, на котором будет отображаться данный цвет? –

ответ

41

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

Ваш код обеспечивает «негативный» цвет.

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

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

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

+0

yup, наконец, содержательный ответ. +1 – jalf

+1

+1 для фактического ответа на мой вопрос с правильным решением (вместо того, чтобы предоставить альтернативу коду, который я опубликовал) – ThePower

+0

Смешивание этого в сочетании с http://stackoverflow.com/questions/2942/hsl-in-net/2504318 # 2504318 - это именно то, с чем я пошел. Благодаря! – Yoopergeek

10

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

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

все сделано таким же образом в C#. Синтаксис точно такой же. 0xFFFFFFFF^цвет –

+0

Почти идентичный. :) Я просто сделал небольшие изменения, чтобы превратить его в C#. – Noldorin

+3

Это то же самое, что и код в вопросе – Eyal

4

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

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

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

+0

Это генерирует исключение (ArgumentException "Значение '-129' недопустимо для 'red'") – ThePower

+0

Да, пропустил тот, исправленный ответ. –

+0

Теперь это было отредактировано, что лучше, хотя он по-прежнему делает то же самое, что и моя функция в отношении того, чтобы быть отрицательным, а не инвертированным. спасибо за ответ в любом случае :-) – ThePower

4

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

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

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

+1

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

14

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

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

Это будет инвертировать MyColor.

+6

Итак, что делает это до серого? 127, 127, 127? – ThePower

+1

Он дает немного светлее серый: 128, 128, 128 – Jerther

+1

Я думаю, что это очень хороший ответ для многих случаев. Например, красный цвет будет преобразован в голубой. является эквивалентом vbnet кода Remy: 'MyColor = Color.FromArgb (MyColor.ToArgb() Xor & Hffffff)' – Alex

3

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

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

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

Код для сдвига на 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); 
    } 
} 
1

Самый простой и ленивый, как я сделал это, чтобы работать с наличием не только тройной 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 или близко к нему значение цвета.