begin process at 2008 08 28 13:51:33
1 233 106 membres
213 nouveaux aujourd'hui
14 291 membres club

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



[Page 1 Page 2]
Classé sous : source, assembleur, bmptempsource, bmptempcible, lignesource

Participer à cet échange

Pub



Appels d'offres

Recherche developpeur ...
Budget : 700€
SITE MARCHAND LOCATION...
Budget : 3 000€
SITE MARCHAND POUR HOTEL
Budget : 4 000€

CalendriCode

Août 2008
LMMJVSD
    123
45678910
11121314151617
18192021222324
25262728293031

VS Express FR Gratuit !

VS Express en français et 100% gratuit !

Téléchargements

Logiciels à télécharger sur le même thème :

Boutique

Boutique de goodies CodeS-SourceS