IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

GTK+ avec C & C++ Discussion :

dégradé de couleurs où de gris


Sujet :

GTK+ avec C & C++

  1. #1
    Membre régulier
    Homme Profil pro
    chercheur
    Inscrit en
    Décembre 2012
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Décembre 2012
    Messages : 195
    Points : 84
    Points
    84
    Par défaut dégradé de couleurs où de gris
    Bonjour à tous. Je développe depuis des années des applications graphiques avec GTK et cairo. J'utilise souvent des palettes de (quelques) couleurs, en passant par des fonctions comme, e.g., cairo_set_source_rgb(), etc.

    Voici qu'aujourd'hui je dois développer une applications avec des dégradés de couleurs ou de gris, un peu comme une carte IGN utilisant des couleurs - niveaux de gris - pour indiquer les altitudes.

    Quelqu'un aurait-il ici des conseils à me donner pour ce faire ? J'ai du mal à imaginer que je doive déclarer des (un tableau de) centaines de d'objets créés avec gdk_cairo_create(), etc., pour chaque niveau de couleurs ou de gris utilisé. Serait-ce vraiment la seule solution ?

    Toute aide sur ce point me serait utile.

    D'avance merci,

    Eric.

  2. #2
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Bonsoir.

    J’ai beaucoup de mal à comprendre la problématique.

    Si tu cherches des dégradés cairo dispose de fonctions adéquates. Regarde les exemples du site officiel.

    Si tu désires choisir une couleur parmi un dégradé Gtk mets à ta disposition un widget dédié : GtkcolorChoiceDialog

    Si ça ne répond pas du tout à tes attentes pourrais-tu préciser tes besoins ?

  3. #3
    Membre régulier
    Homme Profil pro
    chercheur
    Inscrit en
    Décembre 2012
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Décembre 2012
    Messages : 195
    Points : 84
    Points
    84
    Par défaut
    Merci Gerald,

    Si j'ai bien compris, cairo propose effectivement des moyens de gérer des gradients, mais il ne s'agit que de gradients linéaires ou circulaires, ce qui n'est pas ce donc j'ai besoin. Par ailleurs, si j'ai bien compris également, GtkcolorChoiceDialog discute avec l'utilisateur pour choisir une couleur, ce qui n'est pas non plus ce dont j'ai besoin.

    Le cas typique que je dois coder, comme je l'ai dit, serait celui une carte IGN utilisant des couleurs - niveaux de gris - pour indiquer les altitudes.

    Imaginons donc que j'ai un tableau x à deux dim, et dans chaque case x[i][j] j'ai une valeur différente. Imaginons que je veuille représenter ce tableau dans une drawing area et que je veuille figurer dans chaque case [i,j] une couleur ou une intensité de gris qui corresponde à la valeur de x[i][j]. Il n'y a aucun gradient linéaire ou circulaire dans ce cas, ni d'interaction avec l'utilisateur.

    Mon idée, "bourrin" aurait été de définir à l'avance un tableau de (centaines) d'objets créés avec gdk_cairo_create(), chacun correspondant à un niveau de couleur ou de gris différent, et de choisir à chaque fois le bon pour figure la valeur de chaque case du tableau. Mais ca me parait bien lourd, d'où ma question.

    J'espère être plus clair.

    Ou bien ai-je loupé quelque chose dans ta réponse ?

    Encore merci, Eric.

  4. #4
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Effectivement ma réponse a tapé à côté

    Si je comprends bien f(x,y) correspond à une altitude. Cette altitude est donc bornée. Par exemple [-2000, 6000].

    Si tu choisis une représentation en niveau de gris une simple interpolation linéaire sur le segment [-2000, 6000] peut te donner un réel compris entre 0 et 1. À partir de ce nombre tu le convertis en RGB pour être utilisé avec cairo.

    Au final tu peux faire la même conversion RGB en couleur en partant d’une couleur arbitraire. Tu peux aussi créer des «*tranches*» de couleur. Tu crées arbitrairement des intervalles d’altitude. Pour chaque intervalle tu décides d’une couleur que tu dégrades du plus foncé au plus clair sur l’intervalle par exemple . Le nombre d’intervalle va déterminer la taille d’un tableau qui contiendra les couleurs pour chacun d’eux. Ça te permet de limiter sa taille.

  5. #5
    Membre régulier
    Homme Profil pro
    chercheur
    Inscrit en
    Décembre 2012
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Décembre 2012
    Messages : 195
    Points : 84
    Points
    84
    Par défaut
    Merci Gerald,

    Cependant le problème n'est pas de calculer les couleurs intermédiaires ou niveau de gris dans un dégradé par interpolation. Ca pas de problème. Le problème est bien comment mettre ceci en machine dans GTK/cairo.

    De ta réponse, je comprends donc que je n'ai effectivement pas d'autres choix - comme je le disais - que de créer un tableau de (centaines) d'objets créés avec gdk_cairo_create(), et d'argumenter celui qui convient en fonction de la valeur de la case x[i][j]. Je trouve cette solution un peu "bourrin" (comme je le disais), et j'imaginais qu'il pourrait y avoir quelque chose de plus "rusé".

    Ai-je bien compris ?

    Encore merci pour ta disponibilité,

    Eric.

  6. #6
    Membre éprouvé Avatar de balkany
    Homme Profil pro
    Touriste
    Inscrit en
    Juillet 2017
    Messages
    346
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Touriste

    Informations forums :
    Inscription : Juillet 2017
    Messages : 346
    Points : 977
    Points
    977
    Par défaut
    Non tu n'es pas censé faire ça.
    L'idée est plutôt d'avoir un contexte Cairo pour toute ta surface de dessin (que tu peux éventuellement obtenir via les fonctions gdk_cairo_*()), puis d'utiliser les fonctions Cairo pour dessiner dans ce contexte.
    En l'occurrence, il se pourrait qu'il te suffise de boucler sur les coordonnées de ton maillage avec ce trio de fonctions :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    cairo_set_source_rgb()
    cairo_rectangle()
    cairo_fill()
    La première définit la couleur de la maille, la seconde ses coordonnées, la troisième la remplit.
    Et puis à la fin un cairo_paint() pour appliquer tout ça.

    À tester et compléter probablement : je n'utilise pas ça tous les jours, et j'ai surtout adapté ou mis à jour du code existant et contenant ce genre de choses, plutôt que de le faire moi-même en partant de zéro.
    Mais je pense que c'est ça l'idée.

  7. #7
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Je ne comprends pas bien pourquoi il faudrait créer tout un tas de cairo_t*.

    Pourrais-tu me montrer un bout de code qui pourrait m’éclairer sur ta façon de faire ?

  8. #8
    Membre régulier
    Homme Profil pro
    chercheur
    Inscrit en
    Décembre 2012
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Décembre 2012
    Messages : 195
    Points : 84
    Points
    84
    Par défaut
    Bon, de toute évidence il y a quelque chose que je ne comprend pas encore clairement.

    Pour moi, à chaque couleur ou niveau de gris correspond un seul objet créé avec gdk_cairo_create(). Comme j'ai besoin de plein de niveaux de gris, il m'en faut donc un paquet, que je propose de regrouper dans un tableau, ce qui facilitera leur argumentation.

    Ou bien puis-je n'en créer qu'un seul, et changer sa valeur rgb avec un cairo_set_source_rgb() à chaque fois. C'est ça que je dois comprendre ?

    Si oui, je gagne en espace mémoire, mais je vais perdre pas mal en temps de calcul il me semble.

    On avance.

    Merci en tout cas pour votre aide.

    Eric.

  9. #9
    Membre éprouvé Avatar de balkany
    Homme Profil pro
    Touriste
    Inscrit en
    Juillet 2017
    Messages
    346
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Touriste

    Informations forums :
    Inscription : Juillet 2017
    Messages : 346
    Points : 977
    Points
    977
    Par défaut
    Quand une application GTK se redessine, elle définit un contexte Cairo au niveau du widget "racine" (disons la fenêtre principale), puis ce contexte est passé de widget enfant en widget enfant jusqu'au plus bas de la hiérarchie.
    Le contexte est unique, et chaque widget le reçoit accompagné de sa zone de dessin.
    C'est comme ça que c'est supposé fonctionner.

  10. #10
    Membre régulier
    Homme Profil pro
    chercheur
    Inscrit en
    Décembre 2012
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Décembre 2012
    Messages : 195
    Points : 84
    Points
    84
    Par défaut
    Citation Envoyé par balkany Voir le message
    Quand une application GTK se redessine, elle définit un contexte Cairo au niveau du widget "racine" (disons la fenêtre principale), puis ce contexte est passé de widget enfant en widget enfant jusqu'au plus bas de la hiérarchie.
    Le contexte est unique, et chaque widget le reçoit accompagné de sa zone de dessin.
    C'est comme ça que c'est supposé fonctionner.
    J'entends bien, mais en quoi ceci répond à ma question ?

    Eric.

  11. #11
    Membre éprouvé Avatar de balkany
    Homme Profil pro
    Touriste
    Inscrit en
    Juillet 2017
    Messages
    346
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Touriste

    Informations forums :
    Inscription : Juillet 2017
    Messages : 346
    Points : 977
    Points
    977
    Par défaut
    Par analogie : une maille dans ton dégradé de couleurs doit correspondre à un rectangle dans un unique contexte, et non pas à un contexte dans une myriade de contextes.
    Et non, ça ne te coutera pas très cher en temps de calcul : déplacer un rectangle sur ton maillage pour appliquer ces trois fonctions ira vite.
    Par ailleurs, même si tu avais un contexte par maille, il faudrait bien que tu boucles sur les contextes pour les mettre à jour.

  12. #12
    Membre régulier
    Homme Profil pro
    chercheur
    Inscrit en
    Décembre 2012
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Décembre 2012
    Messages : 195
    Points : 84
    Points
    84
    Par défaut
    Ok, merci.

    Je vais me mettre à coder ça prochainement.

    Encore merci pour vos réponses.

    Eric.

  13. #13
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Histoire d'enfoncer le clou effectivement tout widget dispose de son propre contexte graphique (cairo_t*). Il va de soit qu'un GtkDrawingArea à forcément son contexte aussi.

    En générale on a tendance à dessiner directement dans ce contexte. C'est une mauvaise habitude. Le principe est le suivant :
    • Créer une cairo_surface_t* qui sera affichée dans le GtkDdrawingArea ;
    • dessiner sur cette surface en dehors du callback affecté au signal "draw" du GtkDrawingArea ;
    • Dans le callback affecté au signal "draw" du GtkDrawingarea insérer la surface au context du GtkDrawingArea.


    De cette manière le temps d'affichage est le plus court possible.

    Comme je suis de bon humeur aujourd'hui (c'est pas tous les jours faut en profiter ) voila un code exemple qui te montre comment agencer tout ce petit monde :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    #include <stdlib.h>
    #include <gtk/gtk.h>
     
    cairo_surface_t*
    create_surface ()
    {
      /* Création d'une surface de taille 1000, 1000 */
      cairo_surface_t* surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
    							 1000,
    							 1000);
      /* Création d'un contexte graphique pour la surface temporaire */
      cairo_t* cr = cairo_create (surface);
     
      /* Effacement en noire de la surface */
      cairo_set_source_rgba (cr, 0, 0, 0, 1);
      cairo_paint (cr);
     
      /* Dessin d'un cadre pour délimiter la surface à l'affichage */
      cairo_set_source_rgba (cr, 1, 1, 1, 1);
      cairo_rectangle (cr, 0, 0, 1000, 1000);
      cairo_stroke (cr);
     
      /* Dessin d'une diagonale avec une interpolation linéaire pour l'exemple */
      gdouble coeff;
      for (gint i=100; i<900; i++) {
        coeff = (gdouble)i / 1131.;
        cairo_set_source_rgba (cr, coeff, coeff, coeff, 1);
        cairo_move_to (cr, i, i);
        cairo_line_to (cr, i+1, i);
        cairo_stroke (cr);
      }
     
      /* Destruction du contexte devenu inutile */
      cairo_destroy (cr);
     
      return surface;
    }
     
    gboolean
    draw_CB (GtkWidget *drawing, cairo_t *cr, cairo_surface_t *surface)
    {
      /* Fond du GtkDrawingArea couleur paille */
      cairo_set_source_rgba (cr, 0.87, 0.82, 0.58, 1);
      cairo_paint (cr);
     
      /* Placement de la surface en 0, 0 */
      cairo_set_source_surface (cr, surface, 0, 0);
      cairo_paint (cr);
     
      return FALSE;
    }
     
    int
    main(int argc, char *argv[]) {
      GtkWidget *window = NULL;
     
      /* Initialisation de Gtk */
      gtk_init(&argc, &argv);
     
      window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
      gtk_widget_set_size_request (window, 200, 200);
      g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (gtk_main_quit), NULL);
     
      GtkWidget *scrolled = gtk_scrolled_window_new (NULL, NULL);
      gtk_container_add (GTK_CONTAINER (window), scrolled);
     
      GtkWidget *drawing = gtk_drawing_area_new ();
      gtk_widget_set_size_request (drawing, 1000, 1000);
      gtk_container_add (GTK_CONTAINER (scrolled), drawing);
     
      cairo_surface_t *surface = create_surface ();
      g_signal_connect (G_OBJECT (drawing), "draw", G_CALLBACK (draw_CB), surface);
     
      gtk_widget_show_all(window);
     
      gtk_main();
     
      cairo_surface_destroy (surface);
     
      return 0;
    }
    Le résultat :
    Nom : Capture d’écran du 2022-01-18 16-05-46.png
Affichages : 217
Taille : 13,7 Ko

  14. #14
    Membre régulier
    Homme Profil pro
    chercheur
    Inscrit en
    Décembre 2012
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Décembre 2012
    Messages : 195
    Points : 84
    Points
    84
    Par défaut
    Super Gerald, et merci !

    Eric.

  15. #15
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 729
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 729
    Points : 15 133
    Points
    15 133
    Par défaut
    Bonsoir,

    si je peux me permettre de squatter ce sujet, je voudrais signaler que dans mon contexte (une vieille distro Debian 7 dans un Linux 3.8 et gtk2), le code de gerald3d compile sans lui changer une virgule mais à l'exécution je n'ai qu'une fenêtre blanche et vide qui s'affiche...

    Comme je lance le binaire depuis un terminal, ça me dit ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    > ./sanstitre 
     
    (sanstitre:12205): Gtk-WARNING **: gtk_scrolled_window_add(): cannot add non scrollable widget use \
    gtk_scrolled_window_add_with_viewport() instead
     
    (sanstitre:12205): GLib-GObject-WARNING **: /build/buildd-glib2.0_2.33.12+really2.32.4-5-i386-eISom6/ \
    glib2.0-2.33.12+really2.32.4/./gobject/gsignal.c:2459: signal `draw' is invalid for instance `0x890d0c0'
    Merci des idées pour avancer.
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  16. #16
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Bonsoir.

    Sur les anciennes versions de Gtk3 les GtkScrolledWindow ne disposaient pas en interne d’un GtkViewPort. Il faut créer un GtkViewPort que tu insères dans le GtkScrolledWindow. Le widget enfant vient enfin s’insérer dans ce GtkViewPort.

  17. #17
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 729
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 729
    Points : 15 133
    Points
    15 133
    Par défaut
    Bonsoir,

    et merci de cette réponse rapide, qui me dépasse un peu, Gtk n'étant pas ma tasse de thé (je cause plutôt Pascal, d'habitude)

    Et un truc m'a surpris :
    Citation Envoyé par gerald3d Voir le message
    Sur les anciennes versions de Gtk3 les GtkScrolledWindow...
    c'est la première fois que je vois ce mot en gras dans cette discussion, alors qu'est-ce qui permet de déterminer que c'est du code Gtk3 (ou 2 ou 1) dans le snippet que tu as posté ?
    Parce qu'il n'y a rien dans les lignes que tu as données et, ma foi, ça a compilé dans ma machine gtk2.

    Bon, bah, c'est pas bien grave, si je suis passé par ici, c'est surtout par curiosité, attiré par les mots dégradé, couleurs, gris dans le titre de la discussion.
    On peut laisser tomber, en ce qui me concerne, et désolé pour le dérangement.
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Dégradé de couleur
    Par néocodeur dans le forum Images
    Réponses: 7
    Dernier message: 18/04/2007, 14h15
  2. [VBA-E]dégradé de couleurs
    Par spileo dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 05/04/2007, 07h45
  3. Dégradé de couleur dans un rectangle
    Par macoute dans le forum 2D
    Réponses: 3
    Dernier message: 10/01/2006, 16h30
  4. Réponses: 8
    Dernier message: 17/05/2005, 18h08
  5. [Image]Dégradé de couleur
    Par eyal555 dans le forum AWT/Swing
    Réponses: 2
    Dernier message: 12/04/2005, 09h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo