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

 C++ Discussion :

copier ecran et obtenir les couleurs rapidement.


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 43
    Points : 25
    Points
    25
    Par défaut copier ecran et obtenir les couleurs rapidement.
    Voila je cherche à faire une copie d'ecran, puis de pouvoir chercher des couleurs dans cette copie. Le plus rapidement possible.

    j'ai essayé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void PhotoHdcEcran(HDC hdc)
    {
      hdc = CreateDC("DISPLAY", 0, 0, 0);
    }
     
    void HdcCouleur(HDC hdc, int x, int y, unsigned char *r, unsigned char *g, unsigned char *b)
    {
      COLORREF Pix;
      Pix = GetPixel(hdc, x, y);
      *r = GetRValue(Pix);
      *g = GetGValue(Pix);
      *b = GetBValue(Pix);
    }
    ca marche, c'est rapide mais le résultat des couleurs est sur l'écran en temps réel alors que je voudrai une image fixe.
    On dirait que mon hdc est un acces à l'écran et non une copie image de ce dernier... comment faire pour faire aussi court et le faire sur un acces fixe?
    Merci à vous tous.

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Tiré d'ici : HDC ScreenSrc = GetWindowDC(0);. L'adaptation pour l'API window est trivial.

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 43
    Points : 25
    Points
    25
    Par défaut HDC ScreenSrc = GetWindowDC(0);
    Même problème...
    En fait je comprends que la fonction GetWindowDC et CreateDC ("display",0,0,0) donne des handles sur l'affichage de l'ecran.

    J'en déduis qu'un handle et un accès temps réel car dès que l'on demande les couleurs en x,y du hdc on obtient les couleurs au moment ou on les demande et non celle du moment ou l'on a crée le handle.

    Suis je dans le vrai jusque là???

    Donc sur le lien que tu m'as envoyé 3DArchi je vois qu'il poursuit avec BiltBlt. Je dois avouer que je ne sais pas encore comment je vais récupéré mes couleurs... lol. Mais je vais creuser. Donc je laisse encore la question le temps de trouver ou si d'autre idée me sont données.

    Merci 3DArchi.

  4. #4
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Avec le handle de l'écran, tu vas créer un DC (un "Memory DC") qui va contenir la même chose :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    HDC hdcMemory = CreateCompatibleDC(hdcEcran);
    HBITMAP hBitmap = CreateCompatibleBitmap(hdcEcran, LARGEUR_ECRAN, HAUTEUR_ECRAN); /* On va utiliser ce bitmap sur notre Memory DC ... */
    SelectObject(hdcMemory, hBitmap); /* ... Voilà c'est fait */
     
    /* On copie tous les bits du DC de l'écran vers notre Memory DC */
     
    BitBlt(hdcMemory, 0, 0, LARGEUR_ECRAN, HAUTEUR_ECRAN, hdcEcran, 0, 0, SRCCOPY);
     
    /* Capture terminée. Utilise hdcMemory pour les applications et non hdcEcran ... */
     
    DeleteObject(hBitmap);
    DeleteDC(hdcMemory);
    La fonction qui réalise la capture (la copie ...), c'est BitBlt et non GetDC ou CreateDC qui ne font que retourner un handle vers quelque chose ...

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 43
    Points : 25
    Points
    25
    Par défaut
    Ok Melem.

    donc le handle reste disons vivant lol... si l'ecran change le handle change vu que c'est un peu comme une passerelle. soit un handle lol.

    je comprends bien que du coup pour figer cet instant j'en fait une copie via la fonction bitblt et directement dans un Hbitmap.

    du coup je ne peux plus utiliser : GetPixel...

    et mon origine est elle inversé? c'est a dire 0,0 en haut a gauche dans un hdc et 0,0 en bas a gauche dans un bitmap?

    En tous les cas merci beaucoup j'avance à grand pas.

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 43
    Points : 25
    Points
    25
    Par défaut apres un peu de temps sur msdn
    il y a encore une ou deux chose qui me semblent obscure. Déjà je dis ce que j'ai compris :

    HDC hdcMemory = CreateCompatibleDC(hdcEcran)
    // on crée un emplacement mémoire identique pour recevoir la copie

    HBITMAP hBitmap = CreateCompatibleBitmap(hdcEcran, LARGEUR_ECRAN, HAUTEUR_ECRAN); /* On va utiliser ce bitmap sur notre Memory DC ... */
    // ici on crée un hbitmap vide??? de la taille de l'ecran.

    SelectObject(hdcMemory, hBitmap); /* ... Voilà c'est fait */
    // "Selects an object into the device context." heuu oui... pourquoi pas... donc on sélectionne dans le hdcMemory un hbitmap qui doit ressembler à celui que l'on vient de crée.

    /* On copie tous les bits du DC de l'écran vers notre Memory DC */

    BitBlt(hdcMemory, 0, 0, LARGEUR_ECRAN, HAUTEUR_ECRAN, hdcEcran, 0, 0, SRCCOPY);

    Bien.. bien...
    pourquoi apres le CreateCompatible on ne passe pas directement au BitBlt(vu qu'ils sont compatible)?

    Pourquoi crétons ce Hbitmap (je n'ai pas compris ce que représente ce Hbitmap)

    Et la fonction SelectObject je ne la comprends pas bien non plus. On sectionne un objet dans le contexte. Pourquoi ne pas donné simplement la class de l'objet à sélectionner dans ce cas?
    Et pourquoi faire cette sélection vu qu'il y a tellement peu d'argument que je ne voit pas a quoi cela abouti.

  7. #7
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    donc le handle reste disons vivant lol ...
    Bah, c'est ça un HANDLE . Pour le tuer, il faut appeler CloseHandle, DeleteDC, DeleteObject, etc. selon le type du handle.

    si l'ecran change le handle change
    Non, le handle ne change pas mais il continue à référencer l'écran (tant qu'il n'a pas encore été fermé) un point c'est tout. N'oublie pas qu'un handle ce n'est qu'un bête entier ...

    je comprends bien que du coup pour figer cet instant j'en fait une copie via la fonction bitblt et directement dans un Hbitmap.
    Non, vers un autre DC (le DC en mémoire). Relis bien le code ...

    du coup je ne peux plus utiliser : GetPixel
    ... du coup, si.

    et mon origine est elle inversée ? c'est a dire 0,0 en haut a gauche dans un hdc et 0,0 en bas a gauche dans un bitmap ?
    Pour le moment oublie le bitmap et pense plutôt au DC en mémoire. Mais quand tu devras faire des optimisations, lire les informations depuis le bitmap est bien plus rapide que de les lire depuis un DC.

    HBITMAP hBitmap = CreateCompatibleBitmap(hdcEcran, LARGEUR_ECRAN, HAUTEUR_ECRAN); /* On va utiliser ce bitmap sur notre Memory DC ... */
    // ici on crée un hbitmap vide ??? de la taille de l'écran.
    Un bitmap vide de même dimensions que l'écran et référence par hBitmap (handle vers ce bitmap). Le DC créé par CreateCompatible DC ne fait que 1 px de largeur et de hauteur. Il faut sélectionner un bitmap (SelectObject) sur ce DC pour lui donner une surface de la taille du bitmap ...

    pourquoi apres le CreateCompatible on ne passe pas directement au BitBlt(vu qu'ils sont compatible)?

    Pourquoi crétons ce Hbitmap (je n'ai pas compris ce que représente ce Hbitmap)

    Et la fonction SelectObject je ne la comprends pas bien non plus. On sectionne un objet dans le contexte. Pourquoi ne pas donné simplement la class de l'objet à sélectionner dans ce cas?
    Et pourquoi faire cette sélection vu qu'il y a tellement peu d'argument que je ne voit pas a quoi cela abouti.
    Déjà répondus.

  8. #8
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par espritlune Voir le message
    il y a encore une ou deux chose qui me semblent obscure. Déjà je dis ce que j'ai compris :

    HDC hdcMemory = CreateCompatibleDC(hdcEcran)
    // on crée un emplacement mémoire identique pour recevoir la copie
    Oui
    Citation Envoyé par espritlune Voir le message
    HBITMAP hBitmap = CreateCompatibleBitmap(hdcEcran, LARGEUR_ECRAN, HAUTEUR_ECRAN); /* On va utiliser ce bitmap sur notre Memory DC ... */
    // ici on crée un hbitmap vide??? de la taille de l'ecran.
    Oui. On crée un bitmap compatible avec l'écran. Cela veut dire que les paramètres du bitmpa (par exemple nbr bits par pixel) sont ceux de l'écran. Par contre ce bitmap ne contient pas encore d'image.
    Citation Envoyé par espritlune Voir le message
    SelectObject(hdcMemory, hBitmap); /* ... Voilà c'est fait */
    // "Selects an object into the device context." heuu oui... pourquoi pas... donc on sélectionne dans le hdcMemory un hbitmap qui doit ressembler à celui que l'on vient de crée.
    En fait, une bitmap c'est comme une brosse ou un stylo. Il faut dire au HDC quel est le bitmap courant. C'est ce qu'on fait ici.

    Citation Envoyé par espritlune Voir le message
    /* On copie tous les bits du DC de l'écran vers notre Memory DC */

    BitBlt(hdcMemory, 0, 0, LARGEUR_ECRAN, HAUTEUR_ECRAN, hdcEcran, 0, 0, SRCCOPY);
    Oui.

    Citation Envoyé par espritlune Voir le message
    Bien.. bien...
    pourquoi apres le CreateCompatible on ne passe pas directement au BitBlt(vu qu'ils sont compatible)?
    Parceque BitBlt opère sur des HDC et pas des bitmaps. Donc, il faut sélectionner le bitmap dans le HDC cible. On crée un bitmap compatible pour récupérer les paramètres qui vont bien du HDC de l'écran. En théorie, tu pourrais créer un bitmap à la main pour le HDC mémoire sans passer par CreateCompatibleBitmap. Mais, t'aurais 2/3 chance de te tromper sur un paramètre. C'est pourquoi cette fonction t'es proposée.

    Citation Envoyé par espritlune Voir le message
    Pourquoi crétons ce Hbitmap (je n'ai pas compris ce que représente ce Hbitmap)
    On dessine sur des HDC pas sur des bitmaps. Cependant, on peut vouloir voir la zone dessinée comme un bitmap. C'est pourquoi on crée un HBITMAP.
    Citation Envoyé par espritlune Voir le message
    Et la fonction SelectObject je ne la comprends pas bien non plus. On sectionne un objet dans le contexte. Pourquoi ne pas donné simplement la class de l'objet à sélectionner dans ce cas?
    Et pourquoi faire cette sélection vu qu'il y a tellement peu d'argument que je ne voit pas a quoi cela abouti.
    C'est comme une brosse ou une font. Quand tu écris SelectObject(hdcMemory, hBitmap); cela signifie que le bitmap courant de hdcMemory est hBitmap.

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 43
    Points : 25
    Points
    25
    Par défaut
    Merci pour toutes ces explications. Vraiment merci.

    Je vais encore abuser une petite fois avant de clore le sujet en résolu.
    Au départ j'ai commencé en C simple avec une bmplib venant du net écrite à la main qui ne gérai que r,g,b et pas le gamma.
    Voici un morceau pour exemple :

    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
    void bmp_setcolor(BMP *bmp, int x, int y, unsigned char r, unsigned char g, unsigned char b)
    {
      if((x < bmp->width) && (y < bmp->height))
      {
        int a = (x + (y*bmp->width))*3;
        bmp->data[a + 0] = r;
        bmp->data[a + 1] = g;
        bmp->data[a + 2] = b;
      }
    }
     
     
    void bmp_getcolor(BMP *bmp, int x, int y, pixel *p)
    {
      if((x < bmp->width) && (y < bmp->height))
      {
        int a = (x + (y*bmp->width))*3;
        p->r = bmp->data[a + 0];
        p->g = bmp->data[a + 1];
        p->b = bmp->data[a + 2];
      }
    }

    Devant faire des captures de l'écran j'étais tombé sur le chapitre DC.
    Puis sur les fonction donnant accès simplement aux couleurs en fonction de X Y.
    Et j'ai bifurqué dans la simplicité relative des fonctions toutes faites de windows.

    Tu me dis maintenant que travailler sur les bitmap sera plus rapide.

    Comme je dois faire une capture d'écran toutes les secondes et y contrôler la couleur de pixels avant de recommencer une capture, plus je serai rapide plus je pourrai en contrôler...
    Penses tu vraiment que de passer l'écran en bitmap et de bosser dessus me ferrai gagner beaucoup de temps?
    1 copie d'écran / sec
    100 à 500 000 test de couleur / image
    et si oui une petite direction à suivre?

  10. #10
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Penses tu vraiment que de passer l'écran en bitmap et de bosser dessus me ferrait gagner beaucoup de temps ?
    Non, accéder aux bits du bitmap ne te fera gagner du temps que si tu fais des traitements très très lourds (filtrage par exemple), bref du traitement d'images (où on a besoin de lire et de modifier l'image, pas juste lire quelques pixels par image ...). Pour ton application, tu peux continuer à travailler avec un simple DC en mémoire (sache en effet qu'un DC en mémoire ça sert souvent à encapsuler un bitmap, mais ça peut servir à autre chose également).

    Sinon, pour récupérer les bits du bitmap utilisé par un DC, on appelle GetObject (pour récupérer la taille et le nombre de bits par pixel de l'image) suivi de GetBitmapBits (pour récupérer les bits de l'image une fois la taille et le nombre de bits par pixel connus ...). Tu peux aussi faire tout ça (et plus ...) avec la fonction GetDIBits.

  11. #11
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 43
    Points : 25
    Points
    25
    Par défaut
    Merci a tous.

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

Discussions similaires

  1. [OpenOffice][Texte] Copier coller d'un code Matlab avec les couleurs
    Par abel413 dans le forum OpenOffice & LibreOffice
    Réponses: 3
    Dernier message: 01/08/2013, 12h48
  2. Copier uniquement les Couleurs de fond des cellules sur Excel 2007
    Par fherolvera dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 19/10/2011, 11h41
  3. [XL-2007] copier en gardant les couleurs textes
    Par dodo28 dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 17/09/2009, 09h54
  4. [XL-2003] Copier les couleurs suivant des critères.
    Par annad dans le forum Excel
    Réponses: 9
    Dernier message: 17/08/2009, 14h51
  5. Réponses: 10
    Dernier message: 02/03/2009, 11h59

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