Domanda sull'algoritmo:È necessario INCREMENTARE dinamicamente da 00FF00 a FF0000 nel tempo, C#/Java

StackOverflow https://stackoverflow.com/questions/668263

  •  21-08-2019
  •  | 
  •  

Domanda

Voglio cambiare il colore da verde brillante a rosso scuro nel tempo (240 ore).Il modo migliore che posso vedere è cambiare la combinazione esadecimale da 00FF00 a FF0000.

Non so come contare dinamicamente fino a FF0000 da 00FF00 per tutta la mia vita.Sto esaminando un periodo di 10 giorni, quindi molto probabilmente più di 240 ore per incrementare.

Qualcuno mi può aiutare?

Non ho mai seguito un corso di algoritmi, quindi penso che potrebbe avere qualcosa a che fare con questo problema.

Se hai un modo migliore per farlo, fammi sapere.

Sto cercando una sorta di codice qui.Grazie ragazzi.Può essere in qualsiasi linguaggio ma verrà inevitabilmente convertito in C#.

È stato utile?

Soluzione

Basti pensare che in termini di componenti. Anche se sembra un grande numero esadecimale, in realtà è di tre side-by-side.

Al via, il rosso è 0, verde è 255 (FF), il blu è 0.
Alla fine, il rosso è 255, il verde è 0, il blu è 0.

Così, ogni (quantità di tempo che hai / 255), incrementa rosso da 1 e decremento verde di 1.

Altri suggerimenti

Se stai passando da un colore brillante a un colore brillante come suggeriscono i valori esadecimali, allora potresti voler eseguire l'interpolazione Spazio HSV, piuttosto che lo spazio RGB.Lo spazio HSV si avvicina al modo in cui pensiamo al colore: tonalità, saturazione e valore.Lo spazio RGB si avvicina al modo in cui funzionano le cellule sensibili alla luce nei nostri occhi.

Il gradiente superiore è un'interpolazione RGB lineare da FF0000 a 00FF00.Il suo valore medio è 7f7f00, un marrone fangoso.

Il gradiente medio è un'interpolazione lineare nello spazio HSV.Poiché sia ​​FF0000 che 00FF00 sono completamente saturi e hanno lo stesso valore (luminosità), l'interpolazione mantiene la stessa luminosità e saturazione ovunque, quindi il valore centrale è giallo brillante ffff00.

La terza alternativa sarebbe una rotazione vettoriale nello spazio RGB, il che significherebbe che il valore medio è B4B400, ( B4 hex = 180 dec = 255 / sqrt(2) ), che è da qualche parte tra i due effetti.Questo viene fatto calcolando la grandezza di ciascun punto finale, quindi ridimensionando il risultato dell'interpolazione lineare RGB in modo che abbia la stessa grandezza, descrivendo effettivamente il vettore in un arco nel piano dei due colori e nell'origine.Dato che in realtà non pesiamo equamente i diversi colori in termini di luminosità, o vediamo in modo lineare, non è esatto, ma ha un'intensità abbastanza uniforme lungo tutta la sua scansione, mentre quello HSV è un po' più leggero al centro, poiché ha due valori al 100%.

rimosso il collegamento Imageshack morto


In Java, dove hai il supporto HSB, l'algoritmo è semplice: ottieni l'HSB dei valori finali, interpolali linearmente come nelle altre risposte RGB, quindi converti crea un colore con i valori h,s,v:

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

Non credo che C# abbia le conversioni integrate, quindi il codice non è molto utile.

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

Probabilmente vorrai trovare l'intersezione del vettore con il bordo del cubo RGB piuttosto che semplicemente fissarlo, ma in questo caso non ha importanza in ogni caso.


In aggiunta, vale la pena considerare anche lo spazio HSY, che è più vicino alla luminosità percepita, come illustrato da L'elica del cubo di Dave Green interpolazioni di colore.

time_remaining (valore varia da 0 a 239)

verde = 255 * (/ 239 TIME_REMAINING)
rosso = 255 -
verde blu = 0

color = (rosso, verde, blu)

ecco una risposta Java Quick da rosso a verde (OFC si può cambiare) il valore è il value corrente nel tempo e all è la somma del tempo ...

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)));

}

Ecco il codice Java di Pete tradotta in C # nel caso qualcuno era alla ricerca di questo. E le grandi opere per i miei scopi (da nero a rosso scuro e viceversa).

    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;
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top