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 !

Tutorial sur ScanLine


Information sur le tutorial

Catégorie :Graphique Date de création : 25/08/2008 16:07:04 Vu : 3 935 fois

Note :
Aucune note

Commentaire sur cette source (14)
Ajouter un commentaire et/ou une note

Description

Bonjour,
je vous présente ici un tutorial sur le ScanLine, qui est extrement puissant et rapide, mais peu utilisé parmi les débutants, comme parmi les initiés.
Alors, sans plus attendre, voici le tutorial !

Tutorial

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 bitmap32 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 pointeurcompatible 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)


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 !

signaler à un administrateur
Commentaire de Bacterius le 25/08/2008 16:09:24

Tutorial codé sous Delphi 6 (lol)

Rha la la comment il m'a bousillé ma mise en page que j'avais mis 30 minutes à faire !
Saleté de FreeTextBox ... je vais essayer de mettre sous Word 2007 !

Cordialement, Bacterius !

signaler à un administrateur
Commentaire de cirec le 26/08/2008 14:32:02 administrateur CS

Salut,

bon comment dire ^^
il y a moyen de faire encore plus vite, toujours avec ScanLine.

et il est préférable de forcer le mode pf32Bit (pas de soucis d'alignement contrairement au pf24Bit) ...

Mais comme tu t'en sorts très bien je te laisse chercher un peut ^^

Sinon pour coder un vrai Bitmap32 (avec Alpha Chanel) c'est très simple à faire :)
ce qui m'a pris plus de temps c'est de coder un agrandissement et une réduction (de bonne qualité) en respectant le canal Alpha.

signaler à un administrateur
Commentaire de Bacterius le 26/08/2008 15:00:10

Merci pour ces conseils Cirec.
Mais j'ai des problèmes de mise en forme ...
Et je n'arrive pas à télécharger Word 2007 (il pèse 550 Mo et je n'arrive pas à télécharger tout ça avant de me faire déconnecter, ce qui est fréquent chez moi ...)

Cordialement, Bacterius !

signaler à un administrateur
Commentaire de Nicolas___ le 27/08/2008 07:13:00

<< Et je n'arrive pas à télécharger Word 2007 (il pèse 550 Mo et je n'arrive pas à télécharger tout ça avant de me faire déconnecter, ce qui est fréquent chez moi ...) >>

Graine de voyou , on ne télécharge pas , on achète en magasin ^^

Sinon pour des exemples d'utilisation de scanline , regarde les snippets graphismes, il y a de très bon exemple

signaler à un administrateur
Commentaire de Bacterius le 27/08/2008 11:01:24

Oui mais j'ai pas envie de payer Word, pour plusieurs raisons :

1) Word est pourri de bugs (il était au collège)

2) Word est nul

3) Word est lourd

4) Word est gourmand

5) J'en ai juste l'utilité pour poster un tutorial et qu'il se mette correctement en forme (j'espère que je n'aurai pas le même résultat sous word ...), alors il doit bien exister des logiciels gratos pour reproduire le format Word non ?

Cordialement, Bacterius !

PS : pour les points 1, 2, 3, et 4, c'est mon avis personnel, n'allez pas croire que j'ai une dent envers Bill ;)

signaler à un administrateur
Commentaire de Nicolas___ le 27/08/2008 14:13:55

le format doc -> openOffice
pour docX je ne sais pas

signaler à un administrateur
Commentaire de Bacterius le 27/08/2008 14:27:04

docX c'est le tout nouveau format de Word 2007 paraît-il (comme aspx [regarde ta barre d'adresses]) et evidemment, l'editeur de tutorial ne prend en charge que les docX ...).

Cordialement, Bacterius !

signaler à un administrateur
Commentaire de PCPT le 27/08/2008 14:28:08 administrateur CS

Nicolas___ -> docx est le format doc intégrant les images (un zip au final, le docx étant extractible)
c'est bien word2007, office ultimate donc

Bacterius -> utilise un downloader pour reprendre à la coupure :)
genre DAP ou .... y'a du choix

ps : la FreeTextBox supporte très bien le copier/coller d'une page HTML si elle est bien faite :)

signaler à un administrateur
Commentaire de Bacterius le 27/08/2008 14:59:29

"si elle est bien faite :)" la freetextbox ou la page html ?
Parce que la FreeTextBox elle est pas bien faite ... déjà que j'ai pas le droit d'avoir une signature sinon j'arrive pas à poster quoi que ce soit (rien ne passe) ...
Mais je vais essayer les download manager pour reprendre ... je pourrai peut-être boucler ça en 4-5 coupures ... lol

Cordialement, Bacterius !

signaler à un administrateur
Commentaire de Nicolas___ le 27/08/2008 16:02:17

Eh je sais ce que c'est le docX , je ne sais pas si OpenOffice le supporte ;)

signaler à un administrateur
Commentaire de f0xi le 04/09/2008 02:55:59 administrateur CS

Pas besoin de ça :

TscanLine = array[0..10000] of TRGBTriple;

tu fait directement :

ptr : pRGBTriple;

begin
  ptr := Bitmap.ScanLine[Bitmap.Height-1];
  for N := 0 to Bitmap.Width*Bitmap.Height-1 do
  begin
    inc(ptr);
  end;

ou
  
  for Y := 0 to Bitmap.Height-1 do
    for X := 0 to Bitmap.Width-1 do
    begin
      inc(ptr);
    end;

signaler à un administrateur
Commentaire de Bacterius le 05/09/2008 17:18:04

Bonjour, ah oui je ne savais pas ça ... d'ailleurs c'était un de mes problèmes ...
Mais je n'ai pas encore internet, j'ai déménagé à Paris et je suis sur l'ordinateur de la famille, mais j'aurai bientôt internet sur mon ordinateur et je pourrai participer plus souvent :)

Cordialement, Bacterius !

signaler à un administrateur
Commentaire de cantador le 03/12/2008 22:37:55

Bravo Bacterius !

signaler à un administrateur
Commentaire de Bacterius le 04/12/2008 17:16:07

Oh !
Merci Cantador, j'avais oublié ce tutoriel.
Désolé de ne pas pouvoir contribuer en ce moment, mais j'ai pas mal de boulot et en plus, comme on a déménagé, mon Delphi est resté à la campagne et mes parents me laissent l'avoir que une ou deux fois par mois, quand on descend à la campagne, pour pas me distraire de mes devoirs ...
Merci :)

Cordialement, Bacterius !

Ajouter un commentaire



Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Comparez les prix Nouvelle version


HTC G1

Entre 449€ et 449€


Photothèque Nouveau !



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
Temps d'éxécution de la page : 0,094 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.