QUELQUES ROUTINES GRAPHIQUES PERFORMANTES (NÉGATIF D'UNE IMAGE,BALANCE RVB,NOIR

cs_cam91 Messages postés 19 Date d'inscription dimanche 9 juin 2002 Statut Membre Dernière intervention 4 février 2006 - 27 juil. 2002 à 22:47
cs_CALAMS Messages postés 3 Date d'inscription mercredi 28 février 2007 Statut Membre Dernière intervention 3 janvier 2009 - 3 janv. 2009 à 12:28
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/12005-quelques-routines-graphiques-performantes-negatif-d-une-image-balance-rvb-noir-et-blanc

cs_CALAMS Messages postés 3 Date d'inscription mercredi 28 février 2007 Statut Membre Dernière intervention 3 janvier 2009
3 janv. 2009 à 12:28
BRAVO
cs_cam91 Messages postés 19 Date d'inscription dimanche 9 juin 2002 Statut Membre Dernière intervention 4 février 2006
27 juil. 2002 à 22:47
je viens de découvrir que pour la routine NB il y avait moyen d'accélerer beaucoup le code en remplacant la division par une multiplication:

@b1:
mov edx,dword [edi] //edx:8*0 8*r 8*v 8*b
xor eax,eax;xor ecx,ecx;mov al,dl;mov cl,dh
add ax,cx;shr edx,16;mov cl,dl
add ax,cx //ax=cr+cv+cb
// à la place de xor edx,edx;mov ecx,3;idiv ecx on écrit
imul eax,21845
shr eax,16 //multiplication par 0,33333

imul edx,eax,$010101
mov dword [esi],edx //edx:8*0 8*cnb 8*cnb 8*cnb
add edi,4;add esi,4 //saut de 32 bit, pixel suivant
cmp edi,lim //boucle jusqu'à edi=lim
jne @b1

En fait au lieu de diviser par 3 on multiplie par 21845/(2^16)=0,333328 Très éfficace quand on sait la lourdeur d'une division en assembleur.
cs_Nono40 Messages postés 962 Date d'inscription mercredi 3 avril 2002 Statut Membre Dernière intervention 12 septembre 2006 2
1 juil. 2002 à 22:06
Merci, mais je viens de vérifier un peu la différence de vitesse car j'étais resté sur les souvenirs d'un 386. Or il apparait que de travailler sur les registres et mémoires 8 bits est beaucoup plus long. Ainsi ce que je t'ai dis pour le bleu est faux :
@b1:
mov edx,dword [edi]
shl edx,24
shr edx,24
mov dword [esi],edx
add edi,4;add esi,4 //saut de 32 bit, pixel suivant
cmp edi,lim
jne @b1
( 16,8 secondes pour 1000 boucles )
est plus rapide que
xor edx,edx
@b1:
mov dl,byte [edi]
mov dword [esi],edx
add edi,4;add esi,4 //saut de 32 bit, pixel suivant
cmp edi,lim
jne @b1
( 19,3 secondes pour 1000 boucles )

Amusant non ?

Note que le source le plus court ( en taille ) pour le bleu serait le suivant :
asm
push edi
push esi
mov ecx,npix
mov esi,addrsource
mov edi,addrDest
xor eax,eax
@b1:
mov al,byte [ecx*4+esi-4]
mov dword [ecx*4+edi-4],eax
loop @b1
pop esi
pop edi
end;
( 19,7 secondes pour 1000 boucles )

Et le plus rapide que j'ai trouvé est le suivant :
asm
push edi
push esi
mov eax,npix
shl eax,2
add eax,addrsource
mov lim,eax
mov esi,addrsource // j'ai inversé ESI et EDI
mov edi,addrDest
cld // pour incrémenter EDI et ESI
@b1:
lodsd
shl eax,24
shr eax,24
stosd
cmp edi,lim
jne @b1
pop esi
pop edi
end;
( 16,1 secondes pour 1000 boucles )

Il est surprenant de constater que le source le plus court en ligne ( 3 lignes pour la boucle ) est le plus long à l'exécution !!!

On pourrait discuter encore longtemps sur le sujet, mais on va finir me dire que le site est un site Delphi et non assembleur... Ton source à de toute façon sa place ici, car c'est la seule manière d'avoir une procédure optimisée. Il suffit de regarder dans les sources des unités de Delphi pour voir que l'assembleur est très présent...

Bonne continuation.

Nono.
cs_cam91 Messages postés 19 Date d'inscription dimanche 9 juin 2002 Statut Membre Dernière intervention 4 février 2006
1 juil. 2002 à 00:29
Merci pour tous vos commentaires, surtout à nono40 qui semble vraiment bien maitriser l'assembleur intégré.
Quant à fabiin, je suis désolé mais je ne maitrise pas du tout l'anti-aliasing, je sais à peine de quoi il s'agit!
J'ai tenu à mettre cette source sur le site de Delphi pour montrer l'importance et la simplicité de l'assembleur intégré.
cs_Bestiol Messages postés 833 Date d'inscription dimanche 6 janvier 2002 Statut Membre Dernière intervention 3 novembre 2005 1
28 juin 2002 à 13:31
euh... Y a quand même un site assembleur, maintenant...
Pasque moi, j'y comprends rien !!!

Mais c'est toute fois assez intéressant à utiliser !
Bye !
fabiin Messages postés 329 Date d'inscription mercredi 4 avril 2001 Statut Membre Dernière intervention 8 décembre 2009 6
28 juin 2002 à 12:49
ca serait cool de faire pareil mais avec l'effet, anti-aliasing, enfin ca m'arrangerai bien :)
fabiin Messages postés 329 Date d'inscription mercredi 4 avril 2001 Statut Membre Dernière intervention 8 décembre 2009 6
28 juin 2002 à 09:35
tès interessant !
cs_Nono40 Messages postés 962 Date d'inscription mercredi 3 avril 2002 Statut Membre Dernière intervention 12 septembre 2006 2
28 juin 2002 à 06:31
C'est effectivement très rapide, mais en assembleur point de limite ! En creusant un peu on trouve presque toujours quelques cycles à gagner :

** Pour la procédure Negatif
On peut aller plus vite en tolérant une erreur de 1/256 sur les couleurs. En effet NEG et XOR $FF ne font une différence que de 1 sur le poids faible. Par contre le XOR n'ayant pas de retenue, on peut traiter les trois couleurs en même temps :
mov edx,dword [edi] //edx:8*0 8*r 8*v 8*b
xor edx,$00FFFFFF
mov dword [esi],edx //b'=256-b,v'=256-v,r'=256-r

C'est d'ailleurs plus juste car pour le noir ($000000) XOR donne blanc ($FFFFFF) tandis que NEG reste noir

** RVB
Le XOR eax,eax en début de boucle n'est pas utile, car tout est mis à zéro par le calcul de R

Pour le calcul de V tu écris trois lignes là ou une seule suffit :
shr dx,8
shl dx,8
add eax,edx
Peut être remplacé par
Mov ah,dh
Car en fait seul DH importe et on doit le caser dans AH

De même pour le calcul de B
shr dx,8
add eax,edx //eax:8*0 8*r' 8*v' 8*b'
Peut être remplacé par
Mov al,dh

** NB
Le XOR CX,CX n'est pas utile car CH est déjà zéro et CL est écrit juste après.

Ensuite j'ai doute car je n'ai pas les temps de cycle CPU, mais
mov dl,al
shl edx,16
mov dl,al
mov dh,al
peut être remplacé par :
imul edx,eax,$010101
C'est plus court mais ce n'est plus rapide que la multiplication entière est cablèe dans le processeur ( c'est pour ça que j'ai un doute car je sais pas... )

** Bleu
On peut simplifier la boucle
xor edx,edx // une seule fois pour toute l'image
@b1:
mov dl,byte [edi] // on ne lit que DL
mov dword [esi],edx
add edi,4;add esi,4 //saut de 32 bit, pixel suivant
cmp edi,lim
jne @b1

** Vert
On peut simplifier la boucle :
xor edx,edx
@b1:
mov dh,byte [edi+1] // On ne lit que DH
mov dword [esi],edx
add edi,4;add esi,4 //saut de 32 bit, pixel suivant
cmp edi,lim
jne @b1

** Rouge
On peut remplacer
shr edx,16
shl edx,16
Par
xor dx,dx

Voila, c'est tout. Ton programme montre une chose importante : l'assembleur en ligne est vraiement simple à utiliser et dans ce cas beaucoup plus rapide qu'une procédure en pur Pascal.

Nono
Rejoignez-nous