|
begin process at 2008 08 28 13:51:33
Derniers logiciels
|
Trouver une ressource (Nouvelle version du moteur, plus rapide & pertinent, essayez le !)
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 !
Sujet : Besoin d'un traduction ASM [ Archives / Graphique ] (DeltaFX)
|
Besoin d'un traduction ASM
le 11/05/2006 12:29:52

DeltaFX
|
Salut les gens,
J'ai retrouvé un source ici traitant de routines graphiques en assembleur : http://www.delphifr.com/article.aspx?ID=1873
mais l'assembleur et moi, euh, la derniere fois que j'en ai écrit (assembleur saturn 4bit, en 1997), j'ai crashé la ram de ma hp48 (et toutes mes gruges, snurfl.......)
Bon ca c'était l'intro, pour dire que je n'y capte rien, mais alors rien de rien. Or pour un prog qui adapte son interface en fonction de la luminosité ambiante, je me trouve a faire une correction gamma sur mes skins. Je me suis donc écrit une procedure pour me faire ca, à base de scanline, trgbtriple et consorts ( je poste le source de ma fonction juste apres ma bafouille) et si globalement, ca marche, ca reste du pascal, intrinsequement lent. Or une correction gamma, ca revient à multiplier les R G B par un facteur, et contraindre le résultat entre 0 et 255, pour chaque pixel. Ca me semble très "assembleurable", non ?
Donc ben voila, je fais appel à celles et ceux qui maitrise l'assembleur inline de delphi, et je leur demande, en toute humilité.... Y aurait'il une ame charitable pour me réécrire le coeur de la procedure ci dessous en assembleur ?
//------------------------------------------------------- function AdjustGamma(Red,Green,Blue:Extended; Source:TPicture; var Cible:TPicture):boolean; type TRGBArray=ARRAY[0..10000]of TRGBTriple; pTRGBArray=^TRGBArray;
var BmpTempSource,BmpTempCible:TBitmap; x,y:integer; R,G,B:integer; LigneSource, LigneCible : pTRGBArray; begin Result:=True;
BmpTempSource:=TBitmap.Create; BmpTempCible:=TBitmap.Create; try BmpTempSource.Assign(Source.Graphic); BmpTempSource.PixelFormat:=pf24bit; BmpTempCible.PixelFormat:=pf24bit; BmpTempCible.Height:=BmpTempSource.Height; BmpTempCible.Width:=BmpTempSource.Width; for y:=0 to BmpTempSource.Height-1 do begin LigneSource:= BmpTempSource.ScanLine[y]; For x:=0 to BmpTempSource.Width-1 do begin R:=LigneSource[x].rgbtRed; G:=LigneSource[x].rgbtGreen; B:=LigneSource[x].rgbtBlue; {traitement} R:=round(R*Red); G:=round(G*Green); B:=round(B*Blue); {controle} if R<0 then R:=0 else if R>255 then R:=255; if G<0 then G:=0 else if G>255 then G:=255; if B<0 then B:=0 else if B>255 then B:=255; {fin traitement} LigneCible[x].rgbtRed:=R; LigneCible[x].rgbtGreen:=G; LigneCible[x].rgbtBlue:=B; end; end; Cible.Assign(BmpTempCible); except Result:=False; end; BmpTempSource.Free; BmpTempCible.Free; end;
A vot' bon coeur,
DFX.
|
|
|
|
Re : Besoin d'un traduction ASM
le 11/05/2006 15:07:03

florenth
Membre Club 
|
A mon avis, je crois que la majorité du temps que tu perds, c'est par tes deux assignations et par le changement du format de pixel. Pourquoi ? Car une assignation de bitmap nécéssite la copie de toutes les données qu'il contient Et un changement de format de pixel (certes nécéssaire dans ton cas) demande de recalculer tous les pixels. Long tout ça ... Je pense que ton problème vient de là. Mais si tu veux vraiment de mettre à l'assembleur, voici un lien qui traite de ce que tu cherches : [ Lien ]PS: Tu mets BmpTempCible.PixelFormat:=pf24bit; avant de définir ses dimensions (Width et Height). Normalement, cela ne fait rien car la valeur de PixelFormat n'est effective que lorsquele bitmap à un Handle (enfin c'est ce qui me semble ...). ++ Si tu ne te plantes pas ...... tu ne pousseras jamais
|
|
|
|
Re : Besoin d'un traduction ASM
le 11/05/2006 18:16:54

DeltaFX
|
Florenth, mon problème c'est qu'apprendre l'assembleur, ca me botte pas du tout pour l'instant ;)
vu que je fais BmpTempCible.PixelFormat:=pf24bit; apres avoir fait BmpTempCible:=TBitmap.Create; normalement BmptempCible a un handle, non ?
Si je prends un bout du code que je donne en link dans mon premier post
Je trouve Ca :
procedure TForm1.RVB(BmpSource,BmpDest:tbitmap;R,V,B:extended); var addrSource,addrDest:pointer; npix,heure,lim:dword; cr,cv,cb:byte; mR,mV,mB:word; begin addrsource:=bmpSource.ScanLine[bmpSource.height-1]; addrDest:=bmpDest.ScanLine[bmpSource.height-1]; npix:=bmpSource.height*bmpSource.width; mR:=round(R*256); mV:=round(V*256); mB:=round(B*256); asm push edi push esi mov eax,npix;shl eax,2;add eax,addrsource {l'assembleur permet d'utiliser de la même facon des pointeurs et des doubles-mots} mov lim,eax //lim=addrbmp+4*npix mov edi,addrsource //edi= addresse du pixel source en cours mov esi,addrDest //esi=addresse du pixel destination en cours @b1: xor eax,eax mov edx,dword [edi] //edx:8*0 8*r 8*v 8*b mov cb,dl //cb :8*b mov cv,dh //cv :8*v shr edx,16 //edx:8*0 8*0 8*0 8*r mov cr,dl //cr :8*r
xor edx,edx;mov dl,cr;mov cx,mR imul dx,cx //r'=round(R*cr) shr dx,8 //dl :8*r' mov ax,dx shl eax,16 //eax:8*0 8*r' 8*0 8*0
xor edx,edx;mov dl,cv;mov cx,mV imul dx,cx //v'=round(V*cv) shr dx,8 shl dx,8 //dl :8*v' add eax,edx //eax:8*0 8*r' 8*v' 8*0
xor edx,edx;mov dl,cb;mov cx,mB
imul dx,cx //b'=round(B*cb) shr dx,8 add eax,edx //eax:8*0 8*r' 8*v' 8*b'
mov dword [esi],eax add edi,4;add esi,4 //saut de 32 bit, pixel suivant cmp edi,lim //boucle jusqu'à edi=lim jne @b1 pop esi pop edi end; end;
Et je suspecte que ce bout d'asm est tres proche de ce que je cherche (au vu des parametres necessaires...) mais j'aimerai un avis extérieur.
|
|
|
|
Re : Besoin d'un traduction ASM
le 12/05/2006 02:40:34

f0xi
Membre Club 
(Admin CS)
|
procedure AdjustGamma(const Red, Green, Blue: single; Src,Dest : TPicture); function Clamp(V,Min,Max : integer) : byte; { ajuste V dans l'interval Min..Max } begin if V < Min then begin result := Min; exit; end; if V > Max then begin result := Max; exit; end; result := V; { cmp jle mov (ret) } { cmp jnl mov (ret) } { mov } { <3..5 op> } end;
type TRGBRec = record B,G,R : byte; end; TRGBMatrix = array[0..6400] of TRGBRec; pRGBMatrix = ^TRGBMatrix;
var Buffer : TBitmap; X,Y,FR,FG,FB : integer; Scans : pRGBMatrix; begin { un seul buffer suffit } Buffer := TBitmap.Create; Buffer.Assign(Src.Graphic); Buffer.PixelFormat := pf24bit;
{ il est rare de rencontrer des images de plus de 6400 pixels de large (4 ecrans en 1600xH)} if Buffer.Width > 6400 then exit;
{ calcul en virgule fixe et en dehors de la boucle ... on gagne de precieuses OPS } FR := round(Red * 256); FG := round(Green * 256); FB := round(Blue * 256); { fld fmul call mov } { fld fmul call mov } { fld fmul call mov } { <12 op> }
for y := 0 to Buffer.Height-1 do begin Scans := Buffer.ScanLine[y]; For x := 0 to Buffer.Width-1 do begin with Scans[X] do begin { tellement simple que meme en assembleur ça mets autant de temps } R := clamp((R*FR) shr 8,0,255); G := clamp((G*FG) shr 8,0,255); B := clamp((B*FB) shr 8,0,255); { xor mov imul shr mov xor call mov }
{ xor mov imul shr mov xor call mov }
{ xor mov imul shr mov xor call mov } { <(Y*X)*33..42 op> }
end; end; end;
{ on assigne } Dest.Assign(Buffer); { on libere } Buffer.Free; { tout ça en ~47..63ms pour une image bitmap de 1280x1024, le seul moyen d'ameliorer serait d'écrire tout la routine en assembleur et d'utiliser les accecleration 3DNow2 ou SSE2 que seul les PC les plus puissant possede, on pourrait tout de meme se retrancher sur MMX qui est en standard sur tout les processeurs depuis le Pentium 2 et le K6 d'AMD} end;
|
|
|
|
Re : Besoin d'un traduction ASM
le 12/05/2006 12:15:40

Emandhal
|
FR := round(Red * 256); FG := round(Green * 256); FB := round(Blue * 256);
Optimisons un minimum ^^ : FR := round(Red shl 8); FG := round(Green shl 8); FB := round(Blue shl 8);
Enfin... je mets ça comme ça... En passant...
Tout problème a sa solution... Mais en général, celle que l'on trouve n'est jamais la bonne...
|
|
|
|
Re : Besoin d'un traduction ASM
le 12/05/2006 12:19:16

Emandhal
|
C'est sûr, ça ne devrait pas avoir trop d'incidence...  Mais je préfère largement, quand il y a un multiple de 2 à diviser ou multiplier, j'utilise des décalages de bits, même sur des bouts de code où ce n'est pas forcément utile.
Tout problème a sa solution... Mais en général, celle que l'on trouve n'est jamais la bonne...
|
|
|
|
Re : Besoin d'un traduction ASM
le 12/05/2006 15:50:18

f0xi
Membre Club 
(Admin CS)
|
salut emandhal ...
probleme, on ne peut pas faire de SHL ou SHR sur des flottants.
Gamma est un parametre unique qui s'applique de la meme façon sur toute les couleurs sa valeur vas de 0.00..1..5.00 ce qui est suffisant pour réhausser n'importe qu'elle image un peu trop sombre ou un peu trop claire, comme c'est un multiplicateur, 1 nous renvois une image identique a la source, en dessous de 1 l'image est assombrie et au dessus l'image est eclaircie ... generalement un decalage de 0.15 ou 0.30 en dessous ou au dessus de 1 suffit. la methode de calcul et de "clamping" sont fusionnées dans la meme et seule methode. toute les valeurs sont asjustée correctement pour gagner le maximum de performance, liberé un maximum de variables locales.
Tout cela nous donne d'assé bonnes performances meme en s'amusant a monter et descendre continnuellement la trackbar qui change la valeur du gamma.
0x0 .. 512x512 : 0..15 ms 512x512 .. 1024x1024 : 15..30 ms 1024x1024 .. 2048x2048 : 30..70 ms
procedure AdjustGamma(const Gamma : single; Src,Dest : Tbitmap); type TRGBRec = record B,G,R : byte; end; TRGBMatrix = array[0..2047] of TRGBRec; pRGBMatrix = ^TRGBMatrix;
var Buffer : TBitmap; X, Y, Gam : integer; ScanBuf,ScanSrc : pRGBMatrix;
procedure Process(const SV : integer; var BV : byte); var SG : integer; begin SG := (SV * Gam) shr 8; if SG <= 0 then begin BV := 0; exit; end; if SG >= 255 then begin BV := 255; exit; end; BV := SG; end;
begin if Gamma = 1 then begin Dest.Assign(Src); exit; end;
Buffer := TBitmap.Create; Buffer.PixelFormat := pf24bit; Buffer.Width := src.Width; Buffer.Height := src.Height;
if Buffer.width > 2048 then exit;
Gam := round(Gamma * 256); for y := 0 to Buffer.Height-1 do begin ScanSrc := Src.ScanLine[y]; ScanBuf := Buffer.ScanLine[y]; For x := 0 to Buffer.Width-1 do begin Process(ScanSrc[X].R, ScanBuf[X].R); Process(ScanSrc[X].G, ScanBuf[X].G); Process(ScanSrc[X].B, ScanBuf[X].B); end; end;
Dest.Assign(Buffer); Buffer.Free; end;
|
|
|
|
Re : Besoin d'un traduction ASM
le 12/05/2006 16:06:12

f0xi
Membre Club 
(Admin CS)
|
ah oui, precision, le double scanline (Src,Buffer) permet aussi de gagner du temps. si on utilise qu'un scanline notre temps varie de 47..63 ms pour une image en 1024x1024 et avec le double scanline le temps varie entre 31..47 ms pour la meme image. de toute façon, le plus gros du temps que l'on perd c'est l'affichage de l'image a l'ecran ... en pur dynamique et non visuel (traitements de frames) on avoisinerais les 30..36 FPS ... ce qui est deja pas mal pour un "algorythme" aussi poussif. bon il faudrait ~75 minutes pour traiter toute les frames d'un films de 90 minute ... mais bon ... sans optimisation MMX ou SSE ou autres ... difficile de faire mieux ... mais moi je trouve ça pas mal pour du delphi.
|
|
|
|
Re : Besoin d'un traduction ASM
le 12/05/2006 17:13:19

DeltaFX
|
Merci Foxi (precision, je tiens à mes 3 valeurs de gamma, une par canal).
C'est pour ca que j'ai recopié ( dans mon second message) le source d'une fonction( le lien de mon premier message) qui a mon sens fait ce que fait la mienne à ceci pres qu'elle ne clampe pas la sortie. Ca pourrait se corriger ca ?
|
|
|
|
Re : Besoin d'un traduction ASM
le 12/05/2006 17:27:50

Emandhal
|
J'ai pourtant pas rêvé... C'est déclaré comme ça... FR,FG,FB : integer;J'ai dû louper un truc...
Tout problème a sa solution... Mais en général, celle que l'on trouve n'est jamais la bonne...
|
|
|
Classé sous : source, assembleur, bmptempsource, bmptempcible, lignesource
|
Téléchargements
Logiciels à télécharger sur le même thème :
|
|