Accueil > Forum > > > > Getdibits qui ne marche pas
Getdibits qui ne marche pas
mercredi 20 juin 2007 à 19:42:40 |
Getdibits qui ne marche pas

barbichette
|
Voilà, j'ai un souci avec la fonction GetDibits. Je veux récupérer les pixels de l'écran complet. A la fin de la procedure FormCreate, j'utilise GetDiBits. Mais ça marche pas... le pointeur tmp passe de la zone pointée à la valeur $FF. (pas terrible comme adresse mémoire) et le code d'erreur de retour et 6 (invalide handle). J'ai le souci dans plein de cas, comme pour l'effet d'eau que j'avais posté sur ce site. J'ai beau retourner et recompiler dans tout les sens... ça ne marche pas...
HELP ME...
// alloue de l'espace mémoire function WinGetMem(Size:Cardinal):pointer; begin result:=VirtualAlloc(nil,Size,MEM_COMMIT or MEM_RESERVE,PAGE_READWRITE); if not Assigned(result) then RaiseLastOSError; end;
//libère la mémoire procedure WinFreeMem(p:Pointer); begin if Assigned(p) and not VirtualFree(p,0,MEM_RELEASE) then RaiseLastOSError; end;
procedure TForm1.FormCreate(Sender: TObject); begin //précalcul les coefficients de la lentille PreCalcul; // crée l'image de fond (capture de l'écran) fond:=tbitmap.Create; fond.Width:=screen.Width; fond.Height:=screen.Height; fond.PixelFormat:=pf32bit; // copie l'image de l'écran comme il est maintenant BitBlt(fond.Canvas.Handle,0,0,fond.Width,fond.Height,getdc(0),0,0,cmSrcCopy);
// prépare la structure bi (bitmap info) fillchar(bi,sizeof(bi.bmiHeader),0); bi.bmiHeader.biSize:=sizeof(bi.bmiHeader); // appel de getdibits avec nil comme pointeur pour avoir juste les infos dans bi getdibits(fond.Canvas.Handle,fond.Handle,0,fond.height,nil,bi,DIB_RGB_COLORS); // alloue la mémoire buffer:=wingetmem(bi.bmiHeader.biSizeImage); tmp:=wingetmem(bi.bmiHeader.biSizeImage);
// prépare la structure bi (bitmap info) fillchar(bi,sizeof(bi.bmiHeader),0); bi.bmiHeader.biSize:=sizeof(bi.bmiHeader); // appel de getdibits avec tmp pour récupérer les pixels de l'image fond getdibits(fond.Canvas.Handle,fond.Handle,0,fond.height,tmp,bi,DIB_RGB_COLORS); caption:=inttostr(GetLastError); end;
|
|
mercredi 20 juin 2007 à 20:10:44 |
Re : Getdibits qui ne marche pas

florenth
|
Salut !
GetDIBits ne fonctionne qu'avec un bitmap ! Pas avec un simple contexte de périphérique (DC pur Device Contect). Tu dois donc créer un bitmap et faire ton BitBlt dedans.
Sinon, pourquoi récupérer le bitmapinfo à l'aide d'un premier appel à GetDIBits pour finalement écraser les valeurs ?
Et, autre chose: on a eu une conversation avec Cirec hier et, d'après moi, GetDIBits/SetDIBits ne serait pas plus rapide qu'un "bon" Scanline[]. Chez moi, pour une opération toute simple, SetDIBits me prend le double du temps que met Scanline[].
Dernière chose: tu fais GetDc(0) dans le paramètre de BitBlt mais tu dois récupérer la valeur fournie par la fonction pour pouvoir libérer le DC que tu viens de réserver. Me trompe-je ? (ch'uis pas 100% sûr sur ce coup) Il me semble pourtant que cela devrait être cela : dc0 := GetDC(0); BitBlt(fond.Canvas.Handle,0,0,fond.Width,fond.Height,getdc(0),0,0,cmSrcCopy); ReleaseDC(dc0);
Alors, toujours des problèmes ?
|
|
mercredi 20 juin 2007 à 20:23:11 |
Re : Getdibits qui ne marche pas

florenth
|
Bon, dans mon code, j'ai oublié de remplacer le getdc(0) (vive le copier-coller ^^).
Sinon, j'ai vu que tu a écrit cela sur une source de mauricio:
Pour le test de performance, j'ai deux réponses : Dans ma source Flames version 2, j'ai remplacé les scanline par ce système, on double en gros la fréquence d'affichage. La réponse est simple, à chaque demande d'un pointeur par scanline, dernière, il y a ceci :
function TBitmap.GetScanLine(Row: Integer): Pointer; begin Changing(Self); with FImage.FDIB, dsbm, dsbmih do begin if (Row < 0) or (Row >= bmHeight) then InvalidOperation(@SScanLine); DIBNeeded; GDIFlush; if biHeight > 0 then // bottom-up DIB Row := biHeight - Row - 1; Integer(Result) := Integer(bmBits) + Row * BytesPerScanline(biWidth, biBitCount, 32); end;
Cela est bien évidemment juste. Cela dit, tu peux ne faire que deux appels à Scanline[] dans tout ton traitement et incrémenter le pointeur de données. Dans ce cas là, le problème ne se pose plus. Mais le gain de performance n'est pas énorme: 1ms à peine pour une image de 1024 lignes !!! C'est dire à quel point cette procédure est rapide !
Par contre, ce qui est lent, c'est de devoir copier TOUS les pixels lors d'une affectation par SetDIBits. Du coup, c'est moins performant. (avec Scanline on travaille directement sur le bloc concerné) Et en plus, tu dois utiliser deux fois plus de mémoire !
Bref, j'attends quand même ta réponse, le débat risque d'être intéressant !
++
|
|
mercredi 20 juin 2007 à 22:21:46 |
Re : Getdibits qui ne marche pas

barbichette
|
alors, en deux mot, j'appelle une première fois getdibits pour remplir bitmapinfo et ainsi avoir la taille de l'image complète. Normalement, le deuxième ne sers à rien, mais si je l'enlève, ça ne marche plus, c'est dans ce cas d'ailleurs que le pointeur pert sa valeur.
Bon, sinon, je viens de regarder de plus près tout ça... Et il me semble en effet que les deux soit pareil. Pour la petite histoire, j'avait besoin de visualiser rapidement un tableau de byte sous forme de bitmap. En regardant à gauche à droite sur le web, j'ai trouvé ça, Getdibits et Setdibits. Dans mon cas, j'avais un pointeur et je ne voulais pas faire une fonction qui recopie le tableau byte à byte vers un tbitmap. Et en utilisant une scanline pour avoir le pointeur vers la première ligne puis en recopiant tout d'un bloc, il y a une magnifique erreur car un écris n'importe où à la fin de la ligne... Je me suis donc dis que scanline donne un pointeur vers une ligne mais pas à l'ensemble du bitmap (tel la mémoire vidéo). En fait, je viens de voir que je me suis gouré... mais il faud demander un scanline sur la dernière ligne puis le pointeur donne tout le bitmap mais (comme tout les bitmaps) de du bas vers le haut... Et Et au fin fond des choses, ça revient au même que SetDibits... qui fait en gros ça :
p,tableau : pointer;
p:=bitmap.scanline[bitmap.heigth-1]; move(tableau,p,taille_du_bitmap)
donc plus besoin de setdibits... sniff...
Cependant j'aimerai bien savoir pourquoi ça ne marche pas.
|
|
jeudi 21 juin 2007 à 10:05:21 |
Re : Getdibits qui ne marche pas

Kenavo
|
"En fait, je viens de voir que je me suis gouré... mais il faud demander
un scanline sur la dernière ligne puis le pointeur donne tout le bitmap
mais (comme tout les bitmaps) de du bas vers le haut..." Salut barbichette,
Il faut quand même faire gaffe avec Scanline ! Les lignes du bitmap sont alignées. Je sais c'est pas très clair, je m'explique :
Les pointeurs renvoyés par Scanline sur chaque ligne sont tous divisibles par 8 (alignement sur un DWord). Si (Nombre de pixels par ligne) x (Nombre d'octet par pixel) n'est pas multiple de 8, il y aura quelques octets non significatifs entre deux lignes. Pas très pratique !
Je dit 8 mais c'est peut-être 4
Ken@vo
Code, Code, Codec !
|
|
jeudi 21 juin 2007 à 10:33:37 |
Re : Getdibits qui ne marche pas

florenth
|
"Normalement, le deuxième ne sers à rien" => non, c'est le premier appel à GetDIBits qui ne sert à rien (dans ton cas) puisque tu vides la structure qu'il te remplit ! Le deuxième est forcément nécessaire, c'est lui qui copie les données. "J'avais besoin de visualiser rapidement un tableau de byte sous forme de bitmap" => Deux solutions: SetDIBits ou Scanline[]. Mais ça, tu l'as bien compris. "Je me suis donc dis que scanline donne un pointeur vers une ligne mais pas à l'ensemble du bitmap" => C'est juste ! Pour avoir une autre ligne, tu refais un appel à Scanline[] ou tu incrémente ton pointeur de la taille de la ligne (en respectant les alignements, voir plus bas) "Cependant j'aimerai bien savoir pourquoi ça ne marche pas." => En fait, les données des bitmaps sont alignées sur des double-mots (DWord ou Cardinal). Ce qui veut dire qu'a la fin d'une ligne, il faut rajouter les zéros jusqu'à tomber sur une limite d'un mot. Dans le cas ou le format est pf32Bit, il n'y a aucun problème puisque chaque pixel se termine sur la fin d'un mot, la fin de la ligne aussi (logique). Par contre, en pf24Bit, suivant la largeur de ton bitmap, ce n'est pas le cas. Exemple avec un bitmap de 3 pixels de largeur, les données de couleur sont stockées comme ça (une lettre: un octet - les apostrophes indiquent les fins de double-mots): BGRB'GRBG'R000' BGRB'GRBG'R000'
Tu vois donc bien qu'on a rajouté trois zéro pour compléter la ligne. De plus, pour finir, les bitmaps ne sont pas toujours orientés de bas en haut. Pour finir, je te laisse voir ici cette merveilleuse traduction de nono40 sur l'utilisation de Scanline[]A+
|
|
jeudi 21 juin 2007 à 10:51:17 |
Re : Getdibits qui ne marche pas

florenth
|
@Kenavo: ahh, croisement de messages ! Au moins, je pense que c'est clair maintenant !
|
|
jeudi 21 juin 2007 à 21:46:02 |
Re : Getdibits qui ne marche pas

florenth
|
Ahhh, je viens de passer une demi-heure sur un problème de GetDIBits !!! En fait, les données de GetDIBits sont aussi alignées sur des double-mots, ce qui fait qu'au final, c'est plus compliqué ! (en fait, c'est aussi compliqué à gérer qu'avec Scanline[]).
Alors forcément le problème ne se pose pas lorsque les dimensions font en sorte que (W * 3) / 4 est un nombre entier et pareil pour (H * 3) / 4 mais partout ailleurs, c'est le bug assuré (et bonne chance pour comprendre, le message d'erreur obtenu est "descripteur non valide" !)
Conclusion: GetDIBits/SetDIBits n'a aucun intérêt et n'est pas du tout pratique !!!
Oubliez le !!! Préférez lui un bon Scanline[]
++
|
|
vendredi 22 juin 2007 à 11:51:02 |
Re : Getdibits qui ne marche pas

barbichette
|
ce que je ne comprend pas, c'est la chose suivante. (on oublie le code de mon premier post) J'appel une première fois GetDibits avec nil comme pointer de bits. sur la MSDN, ils disent que ça rempli la structure bitmapinfo. Et en particulier le membre biSizeImage qui donne la taille du buffer pour recevoir les bits. Puis on alloue de l'espace memoire en utilisant cette taille. Et je rappel getdibits pour transferer l'image. Mais voilà, une fois sur deux, il y a un débordement je ne sais pas trop où et soit le pointer reçois la valeur $FF, soit il y a erreur à l'execution, soit une autre variable globale de mon programme vois sa valeur modifier... C'est du n'importe quoi....
Par ailleurs, je viens de comprendre un truc important avec getdibits et setdibits. Lorsque le membre bmiColors est renseigné dans la structure bitmapinfo, la copie se fait en cherchant la meilleur concordance entre les pixels du buffer et la palette bmiColors, et la palette du bitmap où l'on copie. Donc, diminuer le nombre de couleur ou appliquer une autre palette à une image en ne perdant que peu l'image elle même. Ca peut êter utilile pour faire rapidement ce genre de processus sans avoir à coder toute une fonction. encore faut il que ça marche...
Barbichette
|
|
vendredi 22 juin 2007 à 14:05:25 |
Re : Getdibits qui ne marche pas

rt15
|
Salut, Bin éventuellement, montre le code, vérifie la valeur retournée par GetDIBits (non nulle pour l'appel avec lpvBits, la taille des données quand le buffer n'est pas à nil...). Assure toi que les handles de ta bitmap et de ton hDC sont valide. D'ailleur je me demande quel handle de DC ils veulent... (Windows permet de créer un DC compatible avec une bitmap à l'aide de CreateCompatibleDC, et on peut utiliser SelectObject pour spécifier la bitmap d'un DC) Et surtout, utilise scanline ! 
|
|
Cette discussion est classée dans : fond, handle, bi, bmiheader, getdibits
Répondre à ce message
Sujets en rapport avec ce message
Image de fond dans un TreeView [ par Valérie ]
Bonjour, J'utilise une application DELPHI6 CLX et je n'aarive pas à avoir une image de fond dans mon TreeView. L'événement OnPaint n'existe pas. Si
Handle [ par SMoG ]
une bonne documentation sur les handle ? merci ;)SMoG
Handle [ par Vinch ]
Bonjour à tous,J'ai une erreur lors d'un ajout d'un enregistrement dans ma base access depuis delphi, il me met:"Erreur lors de la création du handle
Recup texte d'une statusbar par handle/classe [ par replic ]
salut, j'aimerai recuperer le texte de la statusbar d'une application en execution. Puis-je y arriver par l'intermediaire du handle de celle et de la
Problème avec les images et leur fond [ par fab30 ]
Salut a tous, voilà, j'ai un probleme avec le Timage de Delphi : Sur ma forme, il y a un Timage avec une image de fond en bmp. Dessus, je rajoute un T
comment mettre une image de fond dans un report ? [ par Bidochon ]
Salut tout le mondeJe souhaiterais incorporer une image de fond dans un report ?L'image est au format JPEG, Bmp ou autre.Merci de votre aide
Graphique sur un TEdit [ par magicvinni ]
Bonjour, j'ai un dessin sur la fond de ma fiche et un TEdit dessus mais invisible au debut de l'application. Quand je veux faire un rectangle sur le f
Rendre Transparente le fond d'une fenêtre quelconque [ par GuyoSt ]
Bonjour, j'aimerais savoir comment rendre transparente le fond de n'importe quel fenêtre, même des fenêtres qui ne sont pas dans le projet.Par exemple
Un programme Delphi en tache de fond?? [ par lomig ]
Bonjour, j'ai une petite appli qui travaille en relation avec une base de données et dont la tache principale est d'en extraire des infos automatiquem
Traducteur Delphi please ! [ par minipod ]
Un sympatique delphinaute m'a dit de faire ceci pour résoudre mon problème. Le problème c'est que je sais pas faire çà en Delphi. Est-ce que quelqu'un
Livres en rapport
|
Derniers Blogs
[SHAREPOINT] LES SESSIONS TECHDAYS 2012.[SHAREPOINT] LES SESSIONS TECHDAYS 2012. par Patrick Guimonet
Voici donc pour ceux qui n'ont pas pu venir, ou ceux qui n'ont pas pu toutes les suivre la liste des sessions SharePoint aux TechDays 2012, que je mettrais à jour dès que les liens des vidéo seront disponibles. Ou ici : http...
Cliquez pour lire la suite de l'article par Patrick Guimonet TECHDAYS PARIS 2012 : SESSION PLEINIèRE JOUR 3TECHDAYS PARIS 2012 : SESSION PLEINIèRE JOUR 3 par ROMELARD Fabrice
Speaker: Bernard Ourghanlian Cette session est comme chaque jour transmise en live par BrainSonic, et j'ai donc suivi cette troisième pleinière par ce moyen sur mon iPad . Elle est dédiée comme chaque année à la mise en perspective de l'é...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice MISHRA READER : UN LECTEUR RSS TRèS ZUNE STYLE EN OPEN SOURCE !MISHRA READER : UN LECTEUR RSS TRèS ZUNE STYLE EN OPEN SOURCE ! par Vko
Hier durant une session dédiée aux Techdays 2012, j'ai eu le plaisir d'annoncer la sortie de la Béta 2 de Mishra Reader. C'est quoi ? Pour les utilisateurs, c'est une vraie expérience de lecture de flux RSS sur Windows. Rien à voir avec les produit...
Cliquez pour lire la suite de l'article par Vko [FRAMEWORK 4] LES TASKS ET LE THREAD UI[FRAMEWORK 4] LES TASKS ET LE THREAD UI par fathi
Je viens de passer quelques temps au TechDay's et j'ai pu voir pas mal de session intéressante. Par contre une chose m'a un peu étonné lors de certaines de ces sessions qui abordaient les améliorations du framework .NET (donc le 4.5) : en gros, bea...
Cliquez pour lire la suite de l'article par fathi WORKFLOW FOUNDATION 3 A UN PIED DANS LA TOMBEWORKFLOW FOUNDATION 3 A UN PIED DANS LA TOMBE par JeremyJeanson
Depuis déjà un an, je conseille vivement les utilisateurs de Workflow Foundation 3 à migrer vers la version 4. L'information qui va suivre ne devrait donc pas trop prendre au dépourvu les personnes qui m'ont suivi. Je profite de ce poste, pour faire le re...
Cliquez pour lire la suite de l'article par JeremyJeanson
Logiciels
Academy System (17.2.1.0)ACADEMY SYSTEM (17.2.1.0)Logiciel de gestion des établissements.
- élèves/étudiants (inscription, dossier, absence...)
-... Cliquez pour télécharger Academy System Easy-Planning (1.0.0.1)EASY-PLANNING (1.0.0.1)Basé sur les mêmes principes que MyPlanning, Easy-Planning permet de créer des plannings sous la ... Cliquez pour télécharger Easy-Planning COLLECTOR PLUS (3.00B)COLLECTOR PLUS (3.00B)COLLECTOR PLUS version 3.00B est un logiciel utilisant une base de données alimentée par :
- L... Cliquez pour télécharger COLLECTOR PLUS PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO (V7.4)PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO (V7.4)PONAMEDIA TV DEVIENS HELLLOOO FLASH
LA TV SUR VOTRE ORDINATEUR.
Toute une plateforme Multi... Cliquez pour télécharger PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO LettresFaciles 2011 (8.0.0.1)LETTRESFACILES 2011 (8.0.0.1)LettresFaciles est un logiciel facilitant la création et la rédaction de lettres types.
Son inte... Cliquez pour télécharger LettresFaciles 2011
|