begin process at 2012 02 08 21:58:53
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Multimédia

 > EXEMPLE D'UTILISATION DE SETDIBITSTODEVICE

EXEMPLE D'UTILISATION DE SETDIBITSTODEVICE


 Information sur la source

Note :
Aucune note
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é :6 452 / 478

Auteur : SAKingdom

Ecrire un message privé
Ce membre participe au partage de revenus publicitaires
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

Les Membres Club peuvent 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

 Sources du même auteur

Source avec Zip Source avec une capture [C/WIN32] EFFACER FICHIERS/RÉPERTOIRES VIDES
Source avec Zip Source avec une capture GET ET SETDIBITS

 Sources de la même categorie

Source avec Zip ADAPTER LES TEMPS DE SUBTITLES DE SOUS TITRAGE ENTRE DEUX LA... par berrami
Source avec Zip Source avec une capture DÉTECTION DE VISAGE (YEUX, NEZ, BOUCHE) AVEC OPENCV EN TEMPS... par MadM@tt
Source avec Zip Source avec une capture GÉNÉRATEUR FM EXPÉRIMENTAL par tontonCD
Source avec Zip LECTEUR MULTIMÉDIA par omegatou
Source avec Zip IMPLÉMENTATION D'UN ALGORITHME DE COMPRESSION/DECOMPRESSION ... par eemikhm

Commentaires et avis

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

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.

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?

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.

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.

Commentaire de SAKingdom le 19/05/2006 21:17:40

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

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.

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 ?

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.

Commentaire de Taron31 le 20/05/2006 21:42:51

Ok

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é

Commentaire de SAKingdom le 20/05/2006 22:01:50

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

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.

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

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]

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?

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

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.

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?

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

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.

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)

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.

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.

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.

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.

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.

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.

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
  }
}

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.

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

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

Consulter la suite du CalendriCode

Photothèque

 
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

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,562 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales