Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

EXEMPLE D'UTILISATION DE SETDIBITSTODEVICE


Information sur la source

Catégorie :Multimédia Classé sous : setdibitstodevice Niveau : Débutant Date de création : 18/05/2006 Date de mise à jour : 22/05/2006 22:45:38 Vu / téléchargé: 4 900 / 423

Note :
Aucune note

Commentaire sur cette source (31)
Ajouter un commentaire et/ou une note


Description

Cette source a pour but d'expliquer une utilisation simple de SetDIBitsToDevice. Cette fonction est très utile pour accélérer l'affichage de pixel à l'écran (au lieu de SetPixel par exemple). Il y a quelque sources de librairie graphique sur ce site (MGraphics par exemple). MGraphics utilise SetPixel et malheureusement, c'est très lent. J'ai fait ma propre librairie graphique moi aussi (et ça n'a pas été facile croyez moi) mais elle utilise SetDIBitsToDevice et je peux vous garantir que la différence de vitesse est incroyable.
 

Fichier Zip

Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !
  •   SetDIBitsToDevice_Exemple
    •   release
      • SetDIBitsToDevice.ex_Télécharger ce fichier [Réservé aux membres club]3 584 octets
    •   SetDIBitsToDevice
      • main.cppTélécharger ce fichier [Réservé aux membres club]Voir ce fichier5 609 octets
      • SetDIBitsToDevice.vcprojTélécharger ce fichier [Réservé aux membres club]4 539 octets
    • SetDIBitsToDevice.slnTélécharger ce fichier [Réservé aux membres club]Voir ce fichier921 octets

Télécharger le zip

Historique

18 mai 2006 23:56:31 :
Correction de certaines explications
19 mai 2006 00:42:27 :
Correction du delete
19 mai 2006 21:20:57 :
Ajout de ReleaseDC
20 mai 2006 17:52:06 :
Optimisation
20 mai 2006 18:32:50 :
Optimisation et explication
20 mai 2006 21:41:00 :
Correction d'un problème
22 mai 2006 15:00:26 :
Optimisation et mise à jour
22 mai 2006 22:45:38 :
Correction de la fonction myZeroMemory

Commentaires et avis

signaler à un administrateur
Commentaire de vecchio56 le 19/05/2006 00:35:10 administrateur CS

delete lpBits; ->  delete[] lpBits; (c'est un tableau)

Effectivement c'est beaucoup plus rapide de faire ca que de faire des SetPixel
En général, je n'utilise SetPixel que quand il y a une ou deux pixels à changer.
Dans ton exemple, je pense que FillRect sera encore plus rapide

signaler à un administrateur
Commentaire de SAKingdom le 19/05/2006 00:37:48

En effet. FillRect serais plus rapide mais c'est pour dessiner un rectangle je crois non? Avec SetDIBitsToDevice, si on sais bien l'utiliser, on peut dessiner n'importequoi.

signaler à un administrateur
Commentaire de vecchio56 le 19/05/2006 01:55:57 administrateur CS

Remplir des rectangles, c'est bien ce que tu fais dans ce code, non?

signaler à un administrateur
Commentaire de SAKingdom le 19/05/2006 03:14:28

Ouais mais le but premier de ce code est de montrer comment utiliser le buffer mémoire pour SetDIBitsToDevice, démontrer son fonctionnement. On peut faire plus qu'un simple rectangle avec ça.

signaler à un administrateur
Commentaire de Taron31 le 19/05/2006 19:05:17

C'est sympa comme effet, et ça à l'air beaucoup moins lourd que d'utiliser SetPixel...
Ps: T'oublie un ReleaseDC()

Bon code.

signaler à un administrateur
Commentaire de SAKingdom le 19/05/2006 21:17:40

Oui c'est vrai c'est beacoup moin lourd que SetPixel.
Merci pour ReleaseDC.

signaler à un administrateur
Commentaire de SAKingdom le 20/05/2006 17:54:23

Bon j'ai optimiser le code en mode release. Il ne prend plus que 3.5Ko et n'utilise plus le CRT. Pas encore d'assembler. Je préfere éviter pour l'instant.

signaler à un administrateur
Commentaire de Taron31 le 20/05/2006 21:26:02

tu penses utiliser de l'asm pour la partie du remplissage de tableau avec les couleurs ?

signaler à un administrateur
Commentaire de SAKingdom le 20/05/2006 21:28:17

Non non surtout pas sinon à koi bon poster cette source sur ce site. L'assembler c'est plutot pour les utilitaires et la fonction myWinMain car ça diminurais encore plus la taille du fichier exe.

signaler à un administrateur
Commentaire de Taron31 le 20/05/2006 21:42:51

Ok

signaler à un administrateur
Commentaire de vecchio56 le 20/05/2006 21:57:54 administrateur CS

C'est pourtant le code qui est dans le WM_TIMER qui mériterait d'être optimisé

signaler à un administrateur
Commentaire de SAKingdom le 20/05/2006 22:01:50

Ah ouais?? Comment. C'est optimisable en restant dans le C?

signaler à un administrateur
Commentaire de BruNews le 20/05/2006 22:35:03 administrateur CS

for (y = 0; y < TABHEIGHT; y++)
xor ebx, ebx ;;; y = 0
lblFOR:
;;; divers codes
inc ebx
cmp ebx, TABHEIGHT
jb lblFOR

for (y = TABHEIGHT - 1; y >= 0; y--)
mov ebx, TABHEIGHT - 1
lblFOR:
;;; divers codes
dec ebx
jns lblFOR

On voit ici que boucler VERS 0 est toujours meilleur que DEPUIS 0, à transformer tant que faire se peut.

A part cela, il faudrait vérifier comment le compilo a généré la multiplication par 3 dans:
tmp = (TABHEIGHT-y-1)*bytewidth+3*x;
Si tu vois un "mul 3" alors remplacer par un "lea eax, [eax+eax*2]"

bytewidth : ne me semble pas être recalculé donc mettre en constante dans un #define, tu éviteras un accès mémoire dans les boucles pour chaque ligne vue plus haut.

signaler à un administrateur
Commentaire de SAKingdom le 20/05/2006 23:48:41

D'accord je comprend pour les boucles, pour bytewidth mais je comprend pas de quoi tu parle quand tu dit "il faudrait vérifier comment le compilo a généré la multiplication par 3". J'ai été voir dans le listing mais j'ai rien trouvé alors j'ai lancer avec le debuggeur et ça a données ceci pour tmp = (TABHEIGHT-y-1)*BYTEWIDTH+3*x avec comme coordonné x et y 349:

mov         eax,15Eh
sub         eax,dword ptr [y]
lea         ecx,[eax*4-4]
imul        ecx,ecx,107h
mov         edx,dword ptr [x]
imul        edx,edx,3
add         ecx,edx
mov         dword ptr [tmp],ecx

signaler à un administrateur
Commentaire de BruNews le 21/05/2006 00:23:53 administrateur CS

mov         edx,dword ptr [x]
imul        edx,edx,3

C'est de la daube ce imul, au moins 12 cycles, remplacer par:
mov edx, dword ptr[x]
lea edx, [edx+edx*2]

signaler à un administrateur
Commentaire de SAKingdom le 21/05/2006 00:27:46

D'accord je vais essayer de remplacer la commande C par de l'assembler. Mais ça risque pas de rendre le code illisible pour ceux qui ne connaisse pas l'ASM?

signaler à un administrateur
Commentaire de vecchio56 le 21/05/2006 00:35:16 administrateur CS

Ca tombe sous le sens, ceux qui ne connaissent pas l'asm ne comprendront pas, de même que ceux qui ne connaissent pas le C ne comprennent pas la version actuelle

signaler à un administrateur
Commentaire de BruNews le 21/05/2006 00:41:19 administrateur CS

Je déconseille fortement de mettre un mini bout d'asm dans une fonction, ça empêche toute optimisation du compilo. Soit on la fait en entier soit rien.

signaler à un administrateur
Commentaire de SAKingdom le 21/05/2006 00:43:08

Bon alors tu me conseille quoi pour tmp = (TABHEIGHT-y-1)*BYTEWIDTH+3*x? Je le laisse comme ça?

signaler à un administrateur
Commentaire de BruNews le 21/05/2006 00:49:59 administrateur CS

ben non, tu peux lui indiquer la marche à suivre:
tmp = (TABHEIGHT-y-1)*BYTEWIDTH+x+x*2

signaler à un administrateur
Commentaire de SAKingdom le 21/05/2006 00:54:45

Ah ok. Merci. Mais pour avoir un programme completement optimiser de cette façon, il faut soi: avoir beaucoup d'expérience ou avoir beacoup de temps devant soi non? Il faut vraiment penser au moindre petit detail. Évidament connaitre l'assembler ça aide beaucoup. Bon je mis remet. Merci encore.

signaler à un administrateur
Commentaire de MickCo le 22/05/2006 11:01:26

Bonjour à tous,

Sans chercher midi à 14h, ton code peut être facilement optimisé en faisant :
int y = 0; int x = 0;
int tmp = (TABHEIGHT-1) * bytewidth;
for (y = 0; y < TABHEIGHT; y++)
{
   int tmp2 = tmp;
   for (x = 0; x < TABWIDTH; x++)
   {
//Écriture dans le tableau de couleurs des 3 octects de couleur (BGR)
lpBits[tmp]=bluelevel;
lpBits[tmp+1]=greenlevel;
lpBits[tmp+2]=redlevel;
        tmp += 3;
   }
   tmp = tmp2 - bytewidth;
}

Sur mon micro, ta fonction originale mets à peu près 2ms, avec les changements que je te propose, => env 1,2 ms

au passage pour BruNews, on pourrait en plus faire :
(TABHEIGHT-y-1)*BYTEWIDTH+x+(x<<1)  (ah, les vieux souvenir du DOS avec son mode 320x200)

signaler à un administrateur
Commentaire de BruNews le 22/05/2006 11:09:31 administrateur CS

le shift est mis en place de toute div ou mul si puissance de 2 directement par tout compilo moderne, il est clair que si tel n'eut pas été le cas je l'aurais mis.

signaler à un administrateur
Commentaire de BruNews le 22/05/2006 11:16:05 administrateur CS

OUPS,
le but ici est d'indiquer au compilo de mettre un 'lea' donc pas de forcer un shift plus couteux en cycles.

signaler à un administrateur
Commentaire de MickCo le 22/05/2006 12:21:08

C'est un vieux réflexe. Je ne peux pas m'empecher d'optimiser le code moi-même.
S'il est vrai que les optimisations de compilations sont efficaces, on ne sait pas trop ce que fait réellement chaque compilateur. De plus, pour mon boulot, j'utilise les mêmes algos sur plusieurs plateformes differentes et donc plusieurs compilateurs differents (et plus ou moins evolués selon la plateforme). Donc, à la base, mieux vaut que j'optimise au max mon code sans trop savoir ce qu'a dans le ventre chaque compilateur.

Je n'ai plus que de vague souvenir de l'assembleur, mais il me semblais qu'un shift soit fait qu'en 1 seul cycle.
Il est vrai qu'avec la puissance actuelle des PC ainsi que les optimisations des compilateurs pour PC, j'ai délaissé l'assembleur depuis près de 10 ans.

En tout cas ton info est très interressante.
Si tu as des liens parlant des optimisations, je suis prenneur.

signaler à un administrateur
Commentaire de BruNews le 22/05/2006 13:15:10 administrateur CS

shift ne sera pas parallélisable avec ADD sur le même registre, que soit avant ou après.
Si on fait le tout en 1 'lea' alors no probleme.

Regarde "Agner Fog" (google), MASM32 inclut un fichier sur les optimisations.
Manuels Intel: http://brunews.free.fr/brunews/download/Intel.rar
Michael Abrash explique aussi tout cela dans ses bouquins.

signaler à un administrateur
Commentaire de SAKingdom le 22/05/2006 15:06:01

Bon j'ai apporté les optimisations que BruNews ma suggéré. J'ai aussi remplacé ma fonction mymemset par myZeroMemory. Elle est en assembler. Ensuite, pour MickCo:

lpBits[tmp]=bluelevel;
lpBits[tmp+1]=greenlevel;
lpBits[tmp+2]=redlevel;
tmp += 3;

Le but de cette source est en partie d'expliquer comme le calcule des positions dans le buffer s'effectue. Si je fais tmp += 3, sa reviend à expliquer une méthode pour dessiner des rectangles. Hors avec ce que j'explique et avec un peut d'imagination, on peut tout faire avec ça même du 3D.

signaler à un administrateur
Commentaire de MickCo le 22/05/2006 16:21:14

Merci à toi BruNews.
Désolé SAKingdom, je me suis égaré quand j'ai vu qu'on parlait d'optimisation.

signaler à un administrateur
Commentaire de BruNews le 22/05/2006 21:03:44 administrateur CS

Allez une dernière:

myZeroMemory() boucle autant de tours que d'octets, pas terrible, il faut dérouler afin de faire le moins de sauts de code possible, c'est le plus pénalisant pour les perfs.

Exemple avec 8 octets (2 DWORDs) par tour:
__declspec(naked) void __fastcall bnZeroMemory(void *destination, UINT size)
{ // ECX = destination, EDX = size
  __asm {
    test  edx, edx
    mov   eax, edx
    je    short zeroEXIT
    and   eax, 7
    sub   edx, eax
    jz    short finHUIT
  parHUIT:
    mov   dword ptr[ecx], 0
    mov   dword ptr[ecx+4], 0
    add   ecx, 8
    sub   edx, 8
    jnz   short parHUIT
  finHUIT:
    test  eax, eax
    je    short zeroEXIT
  parUN:
    mov   byte ptr[ecx], 0
    inc   ecx
    dec   eax
    jnz   short parUN
zeroEXIT:
    ret 0
  }
}

signaler à un administrateur
Commentaire de SAKingdom le 22/05/2006 22:48:54

La dernière deja?!? C'est pas grave. C'est déja bien gentil de ta part de me consacrer ce temps. Merci bien. Bon allez. C'est la dernière mise à jour après moi aussi je passe à autre chose. Voila j'ai corriger la fonction myZeroMemory. C'est maintenant celle de BruNews. Plus grosse mais plus rapide.

signaler à un administrateur
Commentaire de gabuzomeuh le 12/08/2007 19:14:28


Bonjour,

Moi je comprends pas pourquoi define BYTEWIDTH = 4*((3*TABWIDTH+3)/4) c'est a dire (TABWIDTH*3)+3.

Pourquoi + 3 ?

Qqn peut m'expliquer ?

Merci

Ajouter un commentaire

Discussions en rapport avec ce code source dans le forum

SetDIBitsToDevice [ par SAKingdom ] J'aimerais savoir comment fonction SetDIBitsToDevice. J'ai regarder MSDN mais ce n'est pas suffisant. J'aimerais sourtout une explication de la sectio SetDIBitsToDevice, y'a mieux ou pas ? [ par bouba ] Bonjours, j'ai un buffer contenant des pixels au format RGBA, j'utilise la fonction SetDIBitsToDevice pour faire le transfert des pixels de ce buffer


Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Comparez les prix Nouvelle version

Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,390 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.