Getpixel et Setpixel trop lents! :(

Résolu
cs_Omeya Messages postés 28 Date d'inscription dimanche 4 mai 2003 Statut Membre Dernière intervention 10 août 2006 - 24 juil. 2006 à 00:03
cs_Omeya Messages postés 28 Date d'inscription dimanche 4 mai 2003 Statut Membre Dernière intervention 10 août 2006 - 26 juil. 2006 à 21:35
Bonsoir à tous,
Depuis quelques temps, j'essaye de réaliser un capteur d'écran en temps réel et les seuls instructions que je sais vraiment utiliser sont Getpixel et Setpixel... seulement ils sont décidément beaucoup trop lent pour faire quoi que ce soit de viable.
Savez-vous comment je pourrai faire pour remplacer ces deux instructions par un code beaucoup plus rapide, s'il vous plaît?

//Voici un bout de mon code volontairement tronqué
//(certaines variables sont globales donc non définies ici)
void capture()
{
    int hauteur, longueur;
    hauteur = 200;
    longueur = 250;
    int i, j;
    COLORREF Essaicaptureligne[50000];
    GetCursorPos(&pt);

    dc = GetDC( NULL );
    Rectangle(Essaicaptureligne, pt.x-125, pt.y-100, longueur, hauteur);
    ReleaseDC( NULL, dc );

    dc = ::GetDC(GetDlgItem(Mainbox, IDC_SCREEN));
    for (i = 0; i < hauteur; i++)
    {
        for (j = 0; j < longueur; j++) SetPixel(dc, j, i, Essaicaptureligne[j+(i*longueur)]);
    }
    ReleaseDC( GetDlgItem(Mainbox, IDC_SCREEN), dc );
}

COLORREF Pixel(int x, int y)
{
    COLORREF cr = 0;    if( NULL !dc ) cr GetPixel( dc, x, y );
    return cr;
}

void Rectangle(COLORREF *sourceligne, int x, int y, int longueur, int hauteur)
{
    for (int i=0; i<hauteur;i++)
    {
        for (int j=0; j<longueur; j++)
        {
            *sourceligne = Pixel(x+j, y+i);
            sourceligne++;
        }
    }
}
/////////////////////////////////////////

Vous pouvez constater que je tente de mettre les informations obtenues via Getpixel dans un tableau à 2 dimentions pour pouvoir les manipuler. Et là, en l'occurence, je m'en sers pour les afficher dans une picturebox grâce à Setpixel.

Merci par avance pour vos éclaircissements :)

16 réponses

SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
26 juil. 2006 à 19:37
Tien. J'ai fais une petite source exemple qui utilise GetDIBits et SetDIBits pour modifier une image via son buffer de couleur.

http://www.cppfrance.com/codes/GET-SETDIBITS_38788.aspx

C++ (@++)
___________________________________________
Les plus grands esprits trouvent toujours une solution

http://programmationdebat.discutforum.com
3
cs_Omeya Messages postés 28 Date d'inscription dimanche 4 mai 2003 Statut Membre Dernière intervention 10 août 2006
24 juil. 2006 à 00:07
Pour l'environnement, j'utilise Visual Studio 6 (C++) sous Windows XP SP2.
0
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
24 juil. 2006 à 00:57
Oui il y a plus rapide: obtenir un pointeur sur une zone mémoire qui contients les pixels
GetDIBits te permet de récupérer cette zone (et remplace donc les GetPixel), puis tu alloues une deuxième zone mémoire de la même taille, sur laquelle tu va travailler. A la fin tu utilises SetDIBits ou SetDIBitsToDevice pour actualiser d'un coup ton HDC
Tu peux aussi expliquer ce que tu veux faire (j'ai un peu de mal a comprendre le code), peut être qu'il y a une facon plus simple de faire

_____________________________________
Un éditeur de ressources gratuit pour Windows
0
cs_Omeya Messages postés 28 Date d'inscription dimanche 4 mai 2003 Statut Membre Dernière intervention 10 août 2006
24 juil. 2006 à 01:18
Ce que je voudrai faire, en réalité, c'est obtenir un aperçu en temps réel (dans une picturebox) du carré qui se trouve autour de ma souris (un carré de taille 200x200 pixels, par exemple, au centre duquel se trouve donc ma souris).

Le HDC pris en compte est celui de l'écran, d'où le GetDC( NULL ).
Si j'ai choisis GetPixel/SetPixel en instruction, c'est parceque j'avais juste besoin d'une zone bien précise de l'écran (relative à la position de la souris), or je ne sais pas le faire avec GetDIBits et encore moins avec SetDIBits ou SetDIBitsToDevice.
Si tu pouvais me donner un exemple concret sur l'utilisation de GetDIBits, SetDIBits et/ou SetDIBitsToDevice, je t'en serai reconnaissant. J'ai tenté pendant 3 ou 4 jours d'utiliser ces instructions sans succès (aucun affichage) même avec la MSDN (que je trouve vraiment mal foutue côté exemples concrets).
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
SnOOpss Messages postés 571 Date d'inscription samedi 3 avril 2004 Statut Membre Dernière intervention 5 décembre 2013
24 juil. 2006 à 07:10
La lenteur de getpixel et Setpixel sont tres connues.
>> http://www.cppfrance.com/infomsg_Lenteur2_618463.aspx gros post de quelqu'un qui a eu le mem probleme que toi avec un example de code mais je crois meme que l'auteur en a fait une source.
0
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
24 juil. 2006 à 09:14
En l'occurence, je crois que la fonction BitBlt devrait suffire, et cette fonction est plus facile d'utilisation que SetDIBits

_____________________________________
Un éditeur de ressources gratuit pour Windows
0
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
24 juil. 2006 à 20:33
http://www.cppfrance.com/infomsg_Lenteur2_618463.aspx

Ouais mais regarde les dernières pages. Tout ce qui précède est digne d'un pur débutant :)

Ensuite, la source en question est ici:
http://www.cppfrance.com/listeauteur2.aspx?ID=617077
L'utilisation du buffer pour SetDIBitsToDevice y est expliqué.

BitBlt. Ok mais ce n'est que pour copier un DC mémoire vers le DC principal non? Son DC mémoire devra utiliser quelque chose pour déssiner dedans. Si il utilise SetPixel, ce sera toujours aussi long. Aussi d'après le code actuel, tu n'utilise pas de DC mémoire. Ça doit cintiller affreusement non?

C++ (@++)
___________________________________________
Les plus grands esprits trouvent toujours un solution

http://programmationdebat.discutforum.com
0
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
24 juil. 2006 à 20:37
Woups. Mon lien vers la source mène vers ma liste de code.
Voici le vrai lien:
EXEMPLE D'UTILISATION DE SETDIBITSTODEVICE

C++ (@++)
___________________________________________
Les plus grands esprits trouvent toujours un solution

http://programmationdebat.discutforum.com
0
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
25 juil. 2006 à 05:08
On peut utiliser BitBlt avec le même DC source et destination (à des endroits différents bien entendu)

_____________________________________
Un éditeur de ressources gratuit pour Windows
0
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
25 juil. 2006 à 17:25
Oui mais, si il continue à utiliser SetPixel, ce sera toujours aussi long. D'après ce qu'il dit, c'est la lenteur son problème. Je ne vois pas comment BitBlt pourrait régler cela si il continue d'utiliser SetPixel. Pourrais tu m'éclairer un peu s'il te plait?

C++ (@++)
___________________________________________
Les plus grands esprits trouvent toujours un solution

http://programmationdebat.discutforum.com
0
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
25 juil. 2006 à 17:38
Mais justement BitBlt est a utiliser en remplacement à SetPixel. D'après ce que j'ai compris, il veut copier une partie de l'écran à un autre endroit, donc BitBlt

_____________________________________
Un éditeur de ressources gratuit pour Windows
0
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
25 juil. 2006 à 17:47
Ok je comprend. Mais cependant, il disait qu'il voulait manipuler les données receuillies dans un tableau à double dimention. Si c'est pour un simple copie, ça passe mais si il veut, par exemple, modifier une couleur X pour la remplacer par la couleur Y, il n'a pas le choix que de récupérer toute les données.

C++ (@++)
___________________________________________
Les plus grands esprits trouvent toujours un solution

http://programmationdebat.discutforum.com
0
cs_Omeya Messages postés 28 Date d'inscription dimanche 4 mai 2003 Statut Membre Dernière intervention 10 août 2006
25 juil. 2006 à 23:45
@ [auteurdetail.aspx?ID=19734 vecchio56] :
///////////////////////////////////////
void capture()
{
    Point pt;
    GetCursorPos(&pt);
    int hauteur (200), longueur (250);

    HDC dcecran = GetDC( NULL );

    dce = GetDC(GetDlgItem(Mainbox, IDC_ECRAN));
    BitBlt(dce, 0, 0, longueur, hauteur, dcecran, pt.x-(longueur/2), pt.y-(hauteur/2), SRCCOPY);
    ReleaseDC( GetDlgItem(Mainbox, IDC_ECRAN), dce );
    
    ReleaseDC( NULL, dcecran );
}
///////////////////////////////////////

Comme tu peux le constater, mon problème n'est pas la simple recopie de l'écran vers une picturebox mais bel et bien le traitement des pixels entre les 2.
En gros, j'aimerai pouvoir travailler sur les pixels venant de l'écran avant d'afficher le résultat dans la picturebox.

Parfois je me demande pourquoi SetPixel et GetPixel ont été créés si c'est pour les mettre systématiquement à la pouvelle vu leur extrême lenteur (et encore, je suis gentil).
0
cs_Omeya Messages postés 28 Date d'inscription dimanche 4 mai 2003 Statut Membre Dernière intervention 10 août 2006
25 juil. 2006 à 23:54
J'ai oublié de vous dire que mon exemple ci-dessus ne sert strictement à rien si c'est simplement pour faire de la recopie.
J'ai besoin de traiter les données entre la capture de l'écran et l'affichage dans la picturebox (par exemple pour inverser les couleur, jouer sur les nuances, inverser l'image elle-même ou tout simplement afficher les couleurs RGB au format texte dans une autre fenetre, etc).

En tout cas, merci pour vos réponses, même si ça n'a rien donné pour le moment.
Là j'en suis à m'arracher les cheveux pour tenter de manipuler les HBITMAP dans ce but, sans aucun succès.
0
cs_Omeya Messages postés 28 Date d'inscription dimanche 4 mai 2003 Statut Membre Dernière intervention 10 août 2006
26 juil. 2006 à 01:06
Juste une dernière précision sur le type du tableau que je cherche à remplir.
C'est un tableau à 1 dimension du genre :
COLORREF tableau [longueur*hauteur]

Si je trouve une solution à mon problème d'ici 2 ou 3 jours (je doute du délai), je vous tiendrai au courant
0
cs_Omeya Messages postés 28 Date d'inscription dimanche 4 mai 2003 Statut Membre Dernière intervention 10 août 2006
26 juil. 2006 à 21:35
Merci pour le mal que vous vous donnez!

Pour ma part, j'ai entièrement résolu mon problème ce matin.
J'arrive à enregistrer la totalité de l'écran (1280*1024) dans un buffer, à en extrairer la totalité des pixels dans un tableau à 1 dimension de type COLORREF. Et, enfin, j'arrive à afficher dans une picturebox les pixels modifiés du tableau COLORREF (afin d'avoir un apperçu de mon travail)

Je vous avoue que, parfois, la programmation n'est pas du tout une partie de plaisir

Je vais continuer la discution sur l'autre topic que [auteurdetail.aspx?ID=617077 SAKingdom] à créé ;)
(http://www.cppfrance.com/codes/GET-SETDIBITS_38788.aspx)
0
Rejoignez-nous