CodeS-SourceS
Rechercher un code, un tuto, une réponse

Tutorial sur scanline

Octobre 2017



Tutorial ScanLine


= == << Par Bacterius >> ===

1) Présentation

ScanLine est une fonction présente dans chaque objet


=== TBitmap.C'est de loin la façon la plus rapide = d'accéder aux pixels du bitmap.
Mais attention : certains préréquis sont nécessaires pour pouvoir utiliser cette fonction ... == =
2) Préréquis


=== - il faut déclarer des types, contenus par défaut dans l'unité de Windows, mais ne sont pas déclarés par défaut. Dans une clause " type ", dans l'interface de votre unité, déclarez ces 2 types : == =

=== TRGBArray = array [0..10000 * of TRGBTriple;pTRGBArray ^TRGBArray; ==

Nous allons décortiquer ces 2 lignes :



TRGBArray



il s'agit du nom (vous pouvez le modifier mais autant le garder come cela) par lequel vous définirez une ligne ScanLine. Elle ne sera jamais utilisée dans votre code directement.



Array[0.10000 * of

l'étendue maximale d'une ligne ScanLine. Ici, le maximum est de 10.000 pixels (c'est suffisant je pense, mais à adapter aux besoins de chacun).



TRGBTriple

: c'est le type déclaré dans l'unité de Windows, il représente un enregistrement RGB (Red, Green, Blue).



Son enregistrement complet est :


=== TRGBTriple= record == =

rgbtBlue: Byte;



rgbtGreen: Byte;



rgbtRed: Byte;



end;



pTRGBArray



Il s'agit en fait de l'équivalent pointeur de TRGBArray. Il sera, en quelque sorte, le porte-parole de TRGBArray. Vous pouvez changer le nom de ce type, mais il est conseillé de le garder comme tel (il faudra l'appeler dans le code).


=== ^TRGBArray

: L'equivalent pointeur, graçe au ' ^ '. == =
=== - vous devez avoir un bitmap de type Pf24Bit (expliqué plus tard dans le tutorial). Pour cela, il faudra, avant chaque tentative d'accès à ScanLine, appliquer cette ligne : == =

=== MonBitmap.PixelFormat := pf24Bit; ===

3) Explications sur ScanLine

=== Bon, j'ai dû vous le dire, ScanLine est la façon la plus rapide d'accéder aux pixels du bitmap. Cela vient du fait qu'il ne nécessite aucune copie en mémoire des pixels, car le pointeur attribué par ScanLine (pTRGBArray) reflète directement l'état des pixels du bitmap, contrairement à Pixels[X, Y * , ou à la paire GetDiBits, SetDiBits. == =

=== Ne parlons pas de Pixels[X, Y * , le petit chouchou de ceux qui n'ont jamais essayé ScanLine : chaque pixel doit être scanné et mis en mémoire indépendemment, d'ou la longueur du traitement. == =

=== Le GetDiBits, SetDiBits est beaucoup plus rapide que Pixels[X, Y * , mais est toujours largement battu par ScanLine. == =

GetDiBits et SetDiBits


=== sont des routines API . GetDiBits scanne le pixel, en récupérant les valeurs RGB, et SetDiBits les applique sur le bitmap passé en paramètre. Le traitement des pixels doit se situer entre GetDiBits et SetDiBits. Mais c'est un tutorial pour ScanLine, et je ne m'attarderai pas sur ces routines.Remarque : ScanLine scanne les lignes horizontalement, donc il faut toujours faire un parcours des pixels de cette façon : == =

for


=== A := 0 to Height - 1 do == =
=== for B : = 0 to Width - 1 do = ==

 

4) Exemple d'utilisation de ScanLine

Ici l'on construira une routine pour appliquer un filtre rouge sur le bitmap.


 

procedure



FiltreRouge(Bitmap: TBitmap);



Var



P: PTRGBARRAY;



// Le pointeur ScanLine, qui sera appelé à chaque ligne.



X, Y: Integer;



// Les variables de contrôle for-do, pour parcourir le bitmap



Bmp: TBitmap;



// Le bitmap tampon pour effectuer les traitements



begin


=== Bmp := TBitmap.Create; ===

// Création du bitmap tampon



Bmp.Assign(Bitmap);



// Le bitmap tampon récupère le contenu du bitmap passé en paramètre


=== Bmp.PixelFormat := pf24Bit; ===

// On change les formats des pixels du bitmap


===   for X : = 0 to Bmp.Height - 1 do = ==

// On scanne chaque ligne du bitmap, et on scanne cette ligne avec ScanLine



    begin


===       P := Bmp.ScanLine[X * ; ===

// On scanne la ligne ...


===         for Y : = 0 to Bmp.Width - 1 do = ==

// Pour chaque pixel de la ligne ...



         begin


===          P[Y * .rgbtGreen : = 0; = ==

// Le pixel actuel de la ligne (contenue dans P) fixe sa valeur G à 0


===          P[Y * .rgbtBlue : = 0; = ==

// Même chose pour la valeur B



       end;



// Donc, si l'on fixe les valeurs G et B à 0, il reste les valeurs R (Red, Rouge), qui sont restées intactes, et 



on obtient un bitmap ...



   end;



// ... avec des niveaux de rouge (comme si l'on avait appliqué un cellophane rouge dessus)



Bitmap.Assign(Bmp);



// Ne pas oublier de redonner l'image traitée au bitmap original



Bmp.Free;



// On libère le bitmap tampon



end;


 

5) Précisions supplémentaires sur ScanLine

Les valeurs RGB (rgbtRed, rgbtGreen, rgbtBlue) sont comprises entre 0 et 255.


=== Si vous dépassez 255, la valeur passera immédiatement à 0 ( Réciproquement , si vous allez en dessous de 0, il passera automatiquement à 255). == =

=== Pour éviter cela, il est conseillé d'utiliser des variables R, G, B ( Integer ) pendant le traitement, de vérifier les étendues, de les remettre à 255 si elles dépassent 255 (ou 0 si elles sont inférieures de 0), et de les restituer à ScanLine ensuite. == =

=== Pensez bien à entourer votre ScanLine de try..except , car les exceptions sont fréquentes (Indice de ligne hors limites notamment). == =

ScanLine,


=== avec son type par défaut === , ne prend
pas == = en charge les octets de transparence contenus dans les bitmaps 32 bits. == =
=== Passons à la loupe un pixel de bitmap 32 bits : == =

rgbtRed: Byte;


=== // Octet ( 8 bits ) valeur rouge == =

rgbtGreen: Byte;


=== // Octet ( 8 bits ) valeur verte == =

rgbtBlue: Byte;


=== // Octet ( 8 bits ) valeur bleue == =

rgbtAlpha: Byte;


=== // Octet ( 8 bits ) valeur alpha (degré de transparence) == =


 

=== Mais rien ne vous empêche de coder un ScanLine avec prise en charge Alpha ;) == =

=== Il suffit de faire un enregistrement pointeur compatible avec ScanLine (voir 1er lien externe) == =

Vous pouvez absolument tout faire avec ScanLine sur les valeurs rouge, vert, bleu, et Alpha (mais le type fourni par défaut est limité à rouge, vert, bleu).

 

6) Tests de performances

== = Afin d'illustrer la rapidité de ScanLine comparé aux autres routines de traitement de pixels, voici un test de performance ! ===

[ Tests effectués en parfaites conditions de performance, avec un processeur Intel(R) Celeron(R) M, 1.50 GHz *



[ Bitmap testé : dimensions : 255 x 255 pixels, profondeur de couleur 24 bits *



[ Traitements effectués : ajout de 10 aux valeurs rouges, 5 aux valeurs vertes, 3 aux valeurs bleues *



[ Le test de performance prend en compte la mise en mémoire du bitmap tampon, sa création et sa libération, et l'affectation depuis, et à un bitmap paramètre *


 

=== Préliminaires (aucune valeur, mise en chauffe du processeur) : == =

=== ScanLine : 0,6 MS == =

=== Pixels : 531 MS == =

=== GetDiBits/SetDiBits : 155 MS == =

 

Test 1 :




=== ScanLine : 0,4 MS == =

=== Pixels : 453 MS == =

=== GetDiBits/SetDiBits : 182 MS == =

 

Test 2 :


=== ScanLine : 0,5 MS == =

=== Pixels : 665 MS == =

=== GetDiBits/SetDiBits : 123 MS == =

 

Test 3 :


=== ScanLine : 0,5 MS == =

=== Pixels : 438 MS == =

=== GetDiBits/SetDiBits : 244 MS == =

 

Moyenne des performances :


=== ScanLine : (0,4 + 0,5 + 0,5) / 3 = ===
=== 0,46 MS                        ===<< 1ere place >>


=== GetDiBits/SetDiBits : (182 + 123 + 244) / 3 = ===

=== 183 MS     ===<< 2eme place >> Pixels : (453 + 665 + 438) / 3 ===

518,6 MS                       


<< 3eme place >>

 

== = Vous pouvez maintenant constater la rapidité écrasante de ScanLine par rapport aux autres routines ... ===

Alors ...


 

Faites le bon choix, faites le choix

ScanLine !  

7) Liens externes

http://www.efg2.com/Lab/ImageProcessing/Scanline.htm (Exemples d'utilisation de ScanLine, en anglais)



http://dn.codegear.com/article/29173 (Article CodeGear sur ScanLine)


<hr>
Bon, j'ai essayé d'écrire un tutorial interessant, et agréable à lire. Il manque peut-être des informations ... C'est mon 2eme tutorial sur CS :)

Cordialement, Bacterius !



Adresse d'origine
Publié par Bacterius.
Ce document intitulé «  Tutorial sur scanline  » issu de CodeS-SourceS (codes-sources.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Exporter une fonction api avec delphi.net
Utiliser JEDI-SDL sous Codegear Delphi 2009