2009-03-20 16 views
5

Chcę zmienić kolor Jasny Zielony na Ciemnoczerwony w czasie (240 godzin). Najlepszym sposobem, jaki widzę, jest zmiana kombinacji heksadecymalnej z 00FF00 na FF0000.Pytanie algorytmu: Należy dynamicznie INCREMENT od 00FF00 do FF0000 przez TIME, C#/Java

Nie wiem, jak dynamicznie liczyć do FF0000 z 00FF00 na całe życie. Rozglądam się przez okres 10 dni, więc najprawdopodobniej ponad 240 godzin na przyrost.

Czy ktoś może mi pomóc?

Nigdy nie brałem lekcji algorytmów, więc myślę, że może to mieć coś wspólnego z tym problemem.

Jeśli masz lepszy sposób na zrobienie tego, daj mi znać.

Szukam tutaj jakiegoś kodu. Dzięki chłopaki. Może być w dowolnym języku, ale nieuchronnie zostanie przekonwertowany na język C#.

Odpowiedz

8

Pomyśl o tym w kategoriach komponentów. Mimo że wygląda na jedną dużą liczbę heksadecymalną, to w rzeczywistości trzy obok siebie.

Na początku, czerwony jest 0, zielony jest 255 (FF), niebieski jest 0.
Na koniec, czerwony 255, zielony jest 0, niebieski jest 0.

Więc każdy (kwota czasu trzeba/255), przyrost red od 1 do dekrementu zielonego o 1.

+0

Twoje obie poprawne, co jest do bani. Chciałbym dać odpowiedź obu wam. –

+0

Cóż, Scott dokonał dobrego wyboru, ponieważ Chad Birch jest znacznie łatwiejszy niż odpowiedź Pete'a Kirkhama. –

3

TIME_REMAINING (wartość w przedziale od 0 do 239)

zielony = 255 * (TIME_REMAINING/239)
czerwony = 255 - zielony
niebieski = 0

color = (czerwony, zielony, niebieski)

+0

Twoje obie poprawne, co jest do bani. Chciałbym dać odpowiedź obu wam. –

29

Jeśli idziesz z jasnym kolorem na jasny kolor jako wartości hex zasugerować, to może chcesz interpolacji w HSV space zamiast przestrzeni RGB. Przestrzeń HSV jest zbliżona do tego, jak myślimy o kolorze - odcień, nasycenie i wartość. Przestrzeń RGB przybliża sposób działania wrażliwych na światło komórek w naszych oczach.

Górny gradient to liniowa interpolacja RGB od FF0000 do 00FF00. Jego średnia wartość to 7f7f00, błotnisty brąz.

Środkowy gradient to interpolacja liniowa w przestrzeni HSV. Ponieważ zarówno FF0000, jak i 00FF00 są w pełni nasycone i mają tę samą wartość (jasność), interpolacja zachowuje tę samą jasność i nasycenie w całym tekście, więc wartość środkowa jest jasnożółta ffff00.

Trzecią alternatywą byłaby rotacja wektora w przestrzeni RGB, co oznaczałoby, że wartość środkowa to B4B400, (B4 hex = 180 dec = 255/sqrt (2)), która znajduje się gdzieś pomiędzy dwoma efektami. Odbywa się to poprzez obliczenie wielkości każdego punktu końcowego, a następnie skalowanie wyniku interpolacji liniowej RGB, tak aby była ona tej samej wielkości, skutecznie przesuwając wektor w łuku w płaszczyźnie dwóch kolorów i punktu początkowego. Ponieważ tak naprawdę nie ważymy różnych kolorów równomiernie dla jasności, ani nie widzimy liniowo, nie jest to dokładne, ale ma dość równomierną intensywność w całym cyklu, podczas gdy HSV jest nieco lżejsze w środku, ponieważ ma dwie wartości na 100%.

usuwa martwy link Imageshack


W Javie, gdzie masz wsparcie HSB algorytm jest prosty - dostać HSB wartości końcowych, liniowa interpolacja je podobnie jak w innych odpowiedzi RGB, a następnie konwertować utworzyć kolor z h, s, V wartości:

static Color hsvInterpolate (float mix, Color c0, Color c1) { 
    float[] hsv0 = new float[3]; 
    float[] hsv1 = new float[3]; 

    float alt = 1.0f - mix; 

    Color.RGBtoHSB(c0.getRed(), c0.getGreen(), c0.getBlue(), hsv0); 
    Color.RGBtoHSB(c1.getRed(), c1.getGreen(), c1.getBlue(), hsv1); 

    float h = mix * hsv0 [ 0 ] + alt * hsv1 [ 0 ]; 
    float s = mix * hsv0 [ 1 ] + alt * hsv1 [ 1 ]; 
    float v = mix * hsv0 [ 2 ] + alt * hsv1 [ 2 ]; 

    return Color.getHSBColor (h, s, v); 
} 

nie wierzę, C# ma konwersji wbudowane, więc kod nie jest dużo używać naprawdę.

static Color vectorInterpolate (float mix, Color c0, Color c1) { 
    float alt = 1.0f - mix; 

    double x0 = c0.getRed(); 
    double y0 = c0.getGreen(); 
    double z0 = c0.getBlue(); 

    double x1 = c1.getRed(); 
    double y1 = c1.getGreen(); 
    double z1 = c1.getBlue(); 

    double mag0 = sqrt(x0*x0 + y0*y0 + z0*z0); 
    double mag1 = sqrt(x1*x1 + y1*y1 + z1*z1); 

    double x = mix * x0 + alt * x1; 
    double y = mix * y0 + alt * y1; 
    double z = mix * z0 + alt * z1; 

    double mag = mix * mag0 + alt * mag1; 
    double scale = mag/sqrt(x*x + y*y + z*z); 

    return new Color ( 
     clamp (x * scale), 
     clamp (y * scale), 
     clamp (z * scale)); 
} 

static int clamp (double value) { 
    int x = (int) round (value); 

    if (x > 255) return 255; 
    if (x < 0) return 0; 
    return x; 
} 

Prawdopodobnie chcesz znaleźć przecięcie wektora z krawędzi sześcianu RGB zamiast po prostu go zaciskania, ale w tym przypadku nie ma znaczenia, tak czy inaczej.


jako dodatek, to również warto zastanowić HSY przestrzeń, która jest bliżej postrzeganej jasności, co ilustruje Dave Green's cube helix interpolacji kolorów.

+0

przykład tego, jak to zrobić, byłoby jednak miłe =) – Svish

+0

Fajna odpowiedź! Artykuł Wikipedii ma nawet matematykę konwersji między rgb i hsv, więc implementacja w języku C# powinna być możliwa, ponieważ myślę, że nie ma bezpośredniego wsparcia dla kolorów wyrażonych w HSV ...? – flq

+0

+1 za nauczanie mnie czegoś nowego – Nifle

0

oto szybkie java odpowiedź z czerwonego na zielony (ofc można to zmienić) wartość jest obecny value w czasie i all jest sumą czasu ...

public static String progressiveColor(int value, int all){ 

    int red = 255 - (int)((float)(value*255)/(float)all); 
    int green = (int)((float)(value*255)/(float)all); 
    return String.format("#%06X", (0xFFFFFF & Color.argb(255, red, green, 0))); 

} 
0

Oto kod Pete'a Java przetłumaczone na C# na wypadek, gdyby ktoś tego szukał. Działa doskonale do moich celów (od czarnych do ciemnoczerwonych iz powrotem).

static Color VectorInterpolate(float mix, Color c0, Color c1) 
    { 
     float alt = 1.0f - mix; 

     double x0 = c0.R; 
     double y0 = c0.G; 
     double z0 = c0.B; 

     double x1 = c1.R; 
     double y1 = c1.G; 
     double z1 = c1.B; 

     double mag0 = Math.Sqrt(x0 * x0 + y0 * y0 + z0 * z0); 
     double mag1 = Math.Sqrt(x1 * x1 + y1 * y1 + z1 * z1); 

     double x = mix * x0 + alt * x1; 
     double y = mix * y0 + alt * y1; 
     double z = mix * z0 + alt * z1; 

     double mag = mix * mag0 + alt * mag1; 
     double scale = mag/Math.Sqrt(x * x + y * y + z * z); 

     return Color.FromRgb(Clamp(x * scale), Clamp(y * scale), Clamp(z * scale)); 
    } 

    static byte Clamp(double value) 
    { 
     var x = (int)Math.Round(value); 

     if (x > 255) return 255; 
     if (x < 0) return 0; 
     return (byte) x; 
    }