Dégradé de couleurs

Le problème exposé dans ce sujet a été résolu.

Les 6 parties sont définies par les 5 discontinuités que tu as dans ta fonction coordonnée->couleur. Si tu regarde cette image prise sur Wikipedia:

Découpage d'un dégradé RGB

Tu peux observer indépendamment les fonctions rouge, vert et bleu. Tu as des discontinuités à 60°, 120°, 180°, 240° et 300°, d'où les 6 parties du dégradée.

Ah d'accord, et dans le cas d'un dégradé blanc->noir, il n'y a qu'une seule partie puisque chaque composante R, G et B est incrémentée/décrémentée (selon le sens de colorisation du dégradé) de la même façon (elles sont égales), non ?

Je n'avais rien à faire, alors j'ai réalisé un petit algo qui donne une liste de combos RVB en fonction de la taille demandé. Je n'ai pas entièrement vérifié, mais les résultats semblent corrects. Par exemple, au début, le rouge part de 255 et diminue alors que le vert augmente en partant de 0.

Attention, âmes sensibles aux codes moches (et non commentés), s'abstenir :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
"""
RVB
100 1
110 cols/5 *1
011 cols/5 *2
001 cols/5 *3
101 cols/5 *4
100 cols/5 *5
"""

from pprint import pprint

cols = 500
sep = cols / 5
res = []

def ratio(i, min, max):
    return (i / max) * 255

def opp(i, min, max):
    return 255 - ratio(i, min, max)

for i in range(1, cols + 1):
    if i < sep:       # 100->110
        res.append((opp(i, 1, sep), ratio(i, 1, sep), 0))
    elif i < sep*2:   # 110->011
        res.append((opp(i, sep, sep*2), 255, ratio(i, sep, sep*2)))
    elif i < sep*3:   # 011->001
        res.append((0, opp(i, sep*2, sep*3), 255))
    elif i < sep*4:   # 001->101
        res.append((ratio(i, sep*3, sep*4), 0, 255))
    elif i < sep*5:   # 101->100
        res.append((255, 0, opp(i, sep*4, cols)))
    elif i == cols:   # 1OO
        res.append((255, 0, 0))
    else:
        raise Exception(str(i))

pprint(res)

C'est plutôt simple : ratio part de 0 et arrive à 255 à la fin et opp est simplement l'inverse. Le tout est séparé en 6 étapes (décrites par ρττ plus haut).

Je n'ai pas fais de rendu, tout simplement car je n'ai jamais touché à une lib adapté.

Oui, c'est ça :)

Et par rapport à ton questionnement sur la largeur des bandes de même couleur, en fait, il ne devrait pas en avoir. Si la raison pour laquelle deux colonnes peuvent avoir la même couleur, c'est parce qu'une composante est simplement un entier entre 0 et 255. Donc l'apparition de deux colonnes avec la même couleur n'est qu'un effet d'arrondis. Tu n'as pas à t'en occuper, c'est l'arrondi qui va s'en occuper tout seul.

Je n'avais rien à faire, alors j'ai réalisé un petit algo qui donne une liste de combos RVB en fonction de la taille demandé. Je n'ai pas entièrement vérifié, mais les résultats semblent corrects. Par exemple, au début, le rouge part de 255 et diminue alors que le vert augmente en partant de 0.

Attention, âmes sensibles aux codes moches (et non commentés), s'abstenir :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
"""
RVB
100 1
110 cols/5 *1
011 cols/5 *2
001 cols/5 *3
101 cols/5 *4
100 cols/5 *5
"""

from pprint import pprint

cols = 500
sep = cols / 5
res = []

def ratio(i, min, max):
    return (i / max) * 255

def opp(i, min, max):
    return 255 - ratio(i, min, max)

for i in list(range(cols + 1))[1:]:
    if i < sep:       # 100->110
        res.append((opp(i, 1, sep), ratio(i, 1, sep), 0))
    elif i < sep*2:   # 110->011
        res.append((opp(i, sep, sep*2), 255, ratio(i, sep, sep*2)))
    elif i < sep*3:   # 011->001
        res.append((0, opp(i, sep*2, sep*3), 255))
    elif i < sep*4:   # 001->101
        res.append((ratio(i, sep*3, sep*4), 0, 255))
    elif i < sep*5:   # 101->100
        res.append((255, 0, opp(i, sep*4, cols)))
    elif i == cols:   # 1OO
        res.append((255, 0, 0))
    else:
        raise Exception(str(i))

pprint(res)

C'est plutôt simple : ratio part de 0 et arrive à 255 à la fin et opp est simplement l'inverse. Le tout est séparé en 6 étapes (décrites par ρττ plus haut).

Je n'ai pas fais de rendu, tout simplement car je n'ai jamais touché à une lib adapté.

tleb

Merci beaucoup, après je préfère regarder ton code/solution quand j'aurais enfin compris ce que vous m'expliquez depuis 2H xD

Oui, c'est ça :)

Et par rapport à ton questionnement sur la largeur des bandes de même couleur, en fait, il ne devrait pas en avoir. Si la raison pour laquelle deux colonnes peuvent avoir la même couleur, c'est parce qu'une composante est simplement un entier entre 0 et 255. Donc l'apparition de deux colonnes avec la même couleur n'est qu'un effet d'arrondis. Tu n'as pas à t'en occuper, c'est l'arrondi qui va s'en occuper tout seul.

Berdes

Alors du coup d'après toi, pour un dégradé blanc vers noir, il ne faut pas décrémenter toutes les x abscisses ? :o

Non, il ne faut pas décrémenter toutes les x abscisses. En fait, il faut que tu oublies que tu dois dessiner l'image complète.

Si je te demande de quelle couleur est le 140ème pixel d'une image de largeur 180, comment tu obtiens la réponse?

Maintenant, pour dessiner l'image, tu n'as plus qu'à te reposer cette même question à chaque pixel.

Si je te demande de quelle couleur est le 140ème pixel d'une image de largeur 180, comment tu obtiens la réponse?

Avec un dégradé blanc vers noir : je fais 140/180x100 = 77.8 ce qui est davantage proche de 100 que de 0, donc du noir que du blanc ?

Après je ne comprends pas comment tu fais, dans un dégradé polychrome (mais c'est pareil avec mon dégradé monochrome blanc vers noir), pour connaître, ici, la composition RGB précise de ce pixel =/

+1 à l'explication de Berdes. Il te faut le ratio du numéro du pixel en cours de traitement sur le nombre total de pixels. Avec ce ratio, tu peux définir avec une très simple règle de trois la quantité de couleur dont tu as besoin (entre 0 et 255).

Omg j'ai l'impression de tourner à 2 à l'heure :o Je ne vois pas quelle est cette règle de trois :( C'est si simple que ça ? :o

AH SI : dans mon dégradé blanc vers noir, sachant que pour le ratio 100, la couleur est noire (donc RGB = 0), la couleur du pixel de ratio n°77.8 sera : 77.8 x 0 / 100 non ?

+0 -0
Banni

Par exemple, au début, le rouge part de 255 et diminue alors que le vert augmente en partant de 0.

tleb

Au début le rouge ne doit pas diminuer, il doit rester constant. Après je vois que tu commences par sep = cols / 5. Je n'ai pas lu la suite mais ça n'a pas l'air très bon de commencer par ça (à moins de manipuler des rationnels, mais je pense que c'est des flottants). J'ai fait tourner le code mais il ne donne pas les bons résultats.

@Lern-X : Comme exercice, tu peux essayer de calculer ce x dont tu parles. Tu peux faire comme ça, mais à mon avis ce n'est pas une bonne idée. Il se peut que ce x soit inférieur à 1, et surtout en général il ne va pas tomber rond : tu ne vas pas simplement pouvoir colorier x pixels, décrémenter, colorier x pixels, décrémenter, etc. C'est vraiment plus simple de faire comme dit Berdes.

Si je te demande de quelle couleur est le 140ème pixel d'une image de largeur 180, comment tu obtiens la réponse?

Avec un dégradé blanc vers noir : je fais 140/180x100 = 77.8 ce qui est davantage proche de 100 que de 0, donc du noir que du blanc ?

Oui, mais ce qui t'intéresse est le niveau de gris, pas si c'est plus proche de noir ou de blanc.

À propos de la règle de trois, c'est exactement ce que tu fais dans ton calcul 140/180 × 100 (pour calculer un pourcentage ici, mais ce n'est pas le pourcentage qui t'intéresse mais la composante, tu devrais pouvoir ajuster).

+0 -0

Tu sépares ton dégradé en plusieurs étapes et tu traites chaque couleur dans ton étape.

Dans la première étape, on passe (par exemple) de R à R+V, tu commences donc avec (255, 0, 0) et tu finis par (255, 255, 0). Là, c'est le V qui suit le ratio. Si une couleur passe de 255 à 0, tu inverses le ratio (255 - ratio).

En effet, j'avais mis un opp() de trop, my bad. Je ne cherchais pas vraiment à avoir le gradient recherché, juste voir une pseudo structure d'algo pour résoudre le problème.

Avec un dégradé blanc vers noir : je fais 140/180x100 = 77.8

Imagine que le blanc est 0 et le noir est 100, quel est la valeur du pixel?

Berdes

Bein la borne maximale (enfin le noir, 100) multipliée par 77.8 car ce dernier est un pourcentage, non ? :o

À propos de la règle de trois, c'est exactement ce que tu fais dans ton calcul 140/180 × 100 (pour calculer un pourcentage ici, mais ce n'est pas le pourcentage qui t'intéresse mais la composante, tu devrais pouvoir ajuster).

J'ai un peu de mal à comprendre, j'ai à peu près et sans le vouloir fait un truc qui est la réponse à ma question ? :o wtf

Tu sépares ton dégradé en plusieurs étapes et tu traites chaque couleur dans ton étape.

Dans la première étape, on passe (par exemple) de R à R+V, tu commences donc avec (255, 0, 0) et tu finis par (255, 255, 0). Là, c'est le V qui suit le ratio. Si une couleur passe de 255 à 0, tu inverses le ratio (255 - ratio).

En effet, j'avais mis un opp() de trop, my bad.

tleb

Heum attends d'abord je veux réussir mon dégradé de gris blanc vers noir parce que sinon… xD Mais merci de vouloir m'aider toi aussi, à 3 vous allez bien finir par réussir à me faire comprendre le truc :D

+0 -0

Tu peux aussi faire un tableau avec des exemples et le cas général. Par exemple, pour le dégradé noir vers blanc.

TAILLE

Couleur pour $x = 0$

Couleur pour $x$ = TAILLE

Couleur pour $x$ quelconque

255

0

255

$x$

510

0

255

$\frac{x}{2}$

$w$

0

255

$255 \times \frac{x}{w}$

EDIT : c’est bien une histoire de proportion. Il faut une fonction affine qui à 0 associe 0 et à TAILLE associe 255. Grâce à ces deux points ((0, 0) et (TAILLE, 255)), tu trouves l’équation de la droite qui correspond à la fonction qui à une abscisse associe la couleur de ses pixels.

+0 -0

Tu peux aussi faire un tableau avec des exemples et le cas général. Par exemple, pour le dégradé noir vers blanc.

TAILLE

Couleur pour $x = 0$

Couleur pour $x$ = TAILLE

Couleur pour $x$ quelconque

255

0

255

$x$

510

0

255

$\frac{x}{2}$

$w$

0

255

$255 \times \frac{x}{w}$

EDIT : c’est bien une histoire de proportion.

Karnaj

Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah bein oui :o ! Bon je vais faire ça sur mon dégradé blanc vers noir, et je verrais comment utiliser cette relation sur mon dégradé arc-en-ciel !

+0 -0

par contre ce n'est pas x/w si w est la taille, c'est pas possible ?

Oui oui c’est bien $\frac{x}{w}$. Quand $x = 0$, on trouve bien 0, et quand $x = w$, on trouve 255, et pour $0 < x < w$, on a $0 < \text{couleur} < 255$.

Je ne sais pas si tu as vu mon second EDIT, mais on aussi peut réfléchir de la façon suivante :

on cherche la fonction $f \colon [0, w] \to [0, 255]$ qui à $x$ associe une couleur. On sait que cette fonction est affine, et on sait que $f(0) = 0$ et $f(w) = 255$. On a :

  • $f(0) = 0$ ;
  • $f(w) = 255$;
  • $f(x) = ax + b$.

Avec $f(0) = 0$, on trouve $b = 0$ et avec $f(w) = 255 = aw$, on trouve $a = \frac{255}{w}$. D’où

$$ f(x) = \frac{255x}{w}. $$

EDIT : c’est pour un dégradé noir vers blanc, pas blanc vers noir. Pour faire du blanc vers noir, il faut juste changer deux petits trucs dans la fonction à cherche.

+0 -0

Pourquoi trouves-tu $f(w) = 255 \equiv f(w) = aw$ ?

Mais sinon oui c'est une encore meilleure façon de m'expliquer ça que le tableau. En fait on cherche à distribuer la couleur de manière à l'économiser, lorsque l'image a une taille plus grande que 255 !

Pourquoi trouves-tu $f(w) = 255 \equiv f(w) = aw$ ?

J’ai trouvé $b = 0$ grâce à $f(0)$, avec $f(x) = ax + b$, donc $f(w) = aw$ or $f(w) = 255$, donc $aw = 255$.

+0 -0

Ah, le fait d'avoir conclu que $b = 0$ lorsque $x = 0$ peut être réutilisé quelle que soit la valeur de l'antécédent $x$ ? Je pensais que c'était vrai juste pour 0 en fait

Lern-X

Oui, pour une fonction affine, on a $f(x) = ax + b$ avec $a$ et $b$ deux constantes (donc les mêmes pour tout $x$). Là, c’est des mathématiques, tu peux aller regarder ce tutoriel et celui-là.

+0 -0

Ah, le fait d'avoir conclu que $b = 0$ lorsque $x = 0$ peut être réutilisé quelle que soit la valeur de l'antécédent $x$ ? Je pensais que c'était vrai juste pour 0 en fait

Lern-X

Oui, pour une fonction affine, on a $f(x) = ax + b$ avec $a$ et $b$ deux constantes (donc les mêmes pour tout $x$). Là, c’est des mathématiques, tu peux aller regarder ce tutoriel et celui-là.

Karnaj

Ah oui, ce sont des constantes.. Ca fait longtemps que je n'ai pas touché à ça (la dernière fois c'était en seconde en fait).

Merci !

J'ai réussi à passer d'un dégradé blanc-noir à un dégradé noir-blanc !

Bon du coup… demain j'essaierai d'obtenir un dégradé arc-en-ciel en jouant avec les composantes RGB du coup.

Pour le dégradé arc-en-ciel, c’est un peu plus dur, mais il suffit de bien poser le problème en suivant l’image postée par @Berdes.

Sur $[0, \frac{w}{6}]$,

  • le rouge suit une fonction constante égale à 255 ;
  • le bleu suit une fonction constante nulle ;
  • le vert suit une fonction affine avec $f(0) = 0$ et $f(\frac{w}{6}) = 255$.

Et on fait pareil pour les autres morceaux.

+0 -0

Coucou !

J'ai réussi à faire les dégradés blanc noir et noir blanc, et le polychrome également ! Merci à tous pour votre aide et votre soutien, c'était vraiment cool de votre part !

Une petite question me taraude cependant :p En effet, on est partis de l'observation de dégradés existants déjà, et on a vu quelles relations liait la couleur à chaque abscisse grâce à ces dégradés déjà construits. On a vu que pour un dégradé monochrome noir-blanc par exemple, les trois composantes suivent une même fonction affine qui monte ; le dégradé polychrome, lui, est soumis à l'interpolation : ainsi chaque composante évolue selon sa propre fonction dont la définition dépend d'un intervalle (parfois il s'agit d'une fonction-constante, parfois d'une fonction affine).

Ma question est : pourquoi ? Pourquoi ça marche ? Pourquoi obtient-on un dégradé polychrome de cette manière ? J'imagine que ce n'est pas un hasard : est-ce une convention d'informaticiens ? Est-ce dû à la nature-même du système RGB ? On peut étendre cette question aux dégradés noir-blanc/blanc-noir : comment se fait-il que mettre une même fonction affine aux trois composantes donne un tel dégradé ?! Là non plus ce n'est pas dû au hasard…

EDIT :

Voici les images :p :

Et le source final :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
public void displayHorGraduation(String type) {
        double w = this.writable_image.getWidth();
        double r = 0, g = 0, b = 0;
        for(int x = 0; x < this.writable_image.getWidth(); x++) {
            for (int y = 0; y < this.writable_image.getHeight(); y++) {

                if(type.equals("Blanc vers noir")) {
                    this.writable_pixel_writer.setColor(x, y, Color.color(-x/w + 1, -x/w + 1, -x/w + 1));
                } else if(type.equals("Noir vers blanc")) {
                    this.writable_pixel_writer.setColor(x, y, Color.color(x/w, x/w, x/w));
                } else if(type.equals("Polychrome")) {

                    if(x >= 0 && x < w/6) {
                        r = 255;
                        g = 1530*x/w;
                    }

                    if(x >= 0 && x < 2*w/6) {
                        b = 0;
                    }

                    if(x >= 2*w/6 && x < 3*w/6) {
                        b = 1530*x/w - 510;
                    }

                    if(x >= 3*w/6 && x < 5*w/6) {
                        b = 255;
                    }

                    if(x >= 5*w/6 && x <= w) {
                        b = -1530*x/w + 1530;
                    }

                    if (x >= w/6 && x < 3*w/6) {
                        g = 255;
                    }

                    if(x >= 3*w/6 && x < 4*w/6) {
                        g = -1530*x/w + 1020;
                    }

                    if(x >= 4*w/6 && x <= w) {
                        g = 0;
                    }

                    if(x >= w/6 && x < 2*w/6) {
                        r = -1530*x/w + 510;
                    }

                    if(x >= 2*w/6 && x < 4*w/6) {
                        r = 0;
                    }

                    if(x >= 4*w/6 && x < 5*w/6) {
                        r = 1530*x/w - 1020;
                    }

                    if(x >= 5*w/6 && x <= w) {
                        r = 255;
                    }

                    this.writable_pixel_writer.setColor(x, y, Color.color(r/255, g/255, b/255));
                }
            }
        }
    }
+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte