IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Lazarus Pascal Discussion :

TBitMap et Scanline [Lazarus]


Sujet :

Lazarus Pascal

  1. #1
    Membre extrêmement actif Avatar de Jon Shannow
    Homme Profil pro
    Responsable de service informatique
    Inscrit en
    Avril 2011
    Messages
    4 384
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Responsable de service informatique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2011
    Messages : 4 384
    Points : 9 748
    Points
    9 748
    Par défaut TBitMap et Scanline
    Bonjour,

    Je transcris en Lazarus un composant Delphi que j'utilise sans problème et que je n'ai pas écrit, je l'avoue !

    Dans le code du composant Delphi, il y a ces lignes...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    for y:=0 to d.Height-1 do
      begin
      l:=c.ScanLine[y];
      t:=d.ScanLine[y];
      for x:=0 to d.Width-1 do
        if not ((l^[x*3+2]=255) and (l^[x*3+1]=0) and (l^[x*3]=0) and
               (t^[x*3+2]=0) and (t^[x*3+1]=0) and (t^[x*3]=255)) then
          begin
          if Result=0 then
            Result:=CreateRectRgn(x,y,x+1,y+1)
          else
            begin
            r:=CreateRectRgn(x,y,x+1,y+1);
            CombineRgn(Result,Result,r,RGN_OR);
            DeleteObject(r);
            end;
          end;
      end;
    c et d sont des TBitMap
    l et t sont des PBtyteArray;

    Hélas, je viens de découvrir que ScanLine n'existe pas dans Lazarus !

    Comme je suis une bille de première en graphisme, j'ai beau chercher, je ne vois pas comment traduire ces quelques lignes !

    Est-ce que quelqu'un peut m'aider ?

    Merci d'avance

    JS
    Au nom du pèze, du fisc et du St Estephe
    Au nom du fric, on baisse son froc...

  2. #2
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 445
    Points
    28 445
    Par défaut
    TBitmap.RawImage.Data^
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  3. #3
    Membre extrêmement actif Avatar de Jon Shannow
    Homme Profil pro
    Responsable de service informatique
    Inscrit en
    Avril 2011
    Messages
    4 384
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Responsable de service informatique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2011
    Messages : 4 384
    Points : 9 748
    Points
    9 748
    Par défaut
    Dois-je en conclure que RawData remplace ScanLine ? Et que je peux remplacer
    par

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    l := d.RawImage.Data^[y]
    ?
    Au nom du pèze, du fisc et du St Estephe
    Au nom du fric, on baisse son froc...

  4. #4
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 445
    Points
    28 445
    Par défaut
    pas exactement, j'avais vu ça il y a longtemps

    RawImage.Data est un pointeur vers le tableaux de tous les pixels.

    sans avoir testé je pense qu'il faut faire ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    var
      LineWidth: Intege;
      ScanLine: PByte;
    begin
      LineWidth := Bitmap.Description.BytesPerLine;
      ScanLine := Bitmap.RawImage.Data; // première ligne
      for i := 0 to Bitmap.Height - 1 do
      begin
        ...traitement du scanline...
        Inc(ScanLine, LineWidth); // ligne suivante
      end;
    end;
    mais il est possible que l'ordre des lignes soit inversé, je ne sais pas dans quel sens le RawBitmap est stocké, ni si cet ordre est dépendant de l'OS (les Bitmap Windows ont la tête en bas)
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  5. #5
    Membre extrêmement actif Avatar de Jon Shannow
    Homme Profil pro
    Responsable de service informatique
    Inscrit en
    Avril 2011
    Messages
    4 384
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Responsable de service informatique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2011
    Messages : 4 384
    Points : 9 748
    Points
    9 748
    Par défaut
    Merci, je m'en suis sorti !
    Au nom du pèze, du fisc et du St Estephe
    Au nom du fric, on baisse son froc...

  6. #6
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 730
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut Déterrage motivé !
    Bonsoir,

    Désolé de déterrer ce topic vieux de presque 2 ans, mais le commentaire de Jon est plus que sibyllin et mystérieux, et ne m'aide pas beaucoup...
    Citation Envoyé par Jon Shannow Voir le message
    Merci, je m'en suis sorti !
    Jon, comment ? ? ?


    Dans l'attente, si tu passes par là Paul, j'ai voulu utiliser ton bout de code pour passer un exemple trouvé chez efg et qui fonctionne bien en Delphi, et je bute comme Jon sur ce scanline...

    J'ai fait comme ça (le but de la manip est de dessiner des ronds RGB ou CMY dans une TImage de 480 x 480 sur la Form) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
      // RESULT est un TBitmap
      LineWidth := RESULT.RawImage.Description.BytesPerLine; // = 1920 vu en step-by-step
      ScanLine := RESULT.RawImage.Data; // (Paul) première ligne
     
      Getmem(row, SizeOf(row)*LineWidth);
      FillChar(row^, SizeOf(row)*LineWidth, '0');
     
      FOR j := 0 TO RESULT.Height-1 DO
      BEGIN
        //row := RESULT.Scanline[j]; // original Delphi
        row := @Scanline;
     
        FOR i := 0 TO RESULT.Width-1 DO  // crash ici (SIGSEGV) avec j = 237 et i = 479
        // 238 x 480 = 114240, ça ne me parle pas, d'autant plus que juste pour voir,
        // si je mets .Width-2 ça crashe pareil avec j = 237 et i = 478
        BEGIN
          WITH row[i] DO
          // work with row
        END;
        Inc(ScanLine, LineWidth); // (Paul) ligne suivante
     
      END;
      Freemem(row, SizeOf(row)*LineWidth);
    Une idée ?
    Merci d'avance,
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  7. #7
    Membre extrêmement actif Avatar de Jon Shannow
    Homme Profil pro
    Responsable de service informatique
    Inscrit en
    Avril 2011
    Messages
    4 384
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Responsable de service informatique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2011
    Messages : 4 384
    Points : 9 748
    Points
    9 748
    Par défaut
    Salut Jipété,

    Je suis désolé, mais j'ai abandonné cette partie de programmation depuis pas mal de temps. Je regarde si je retrouve ce que j'avais fait à l'époque pour contourner le problème.

    A+

    JS
    Au nom du pèze, du fisc et du St Estephe
    Au nom du fric, on baisse son froc...

  8. #8
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 072
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 072
    Points : 15 462
    Points
    15 462
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par Jipété Voir le message
    Dans l'attente, si tu passes par là Paul, j'ai voulu utiliser ton bout de code pour passer un exemple trouvé chez efg et qui fonctionne bien en Delphi, et je bute comme Jon sur ce scanline...
    Moi aussi je serais curieux de connaître la solution. J'avais cherché il y a quelque temps le moyen d'afficher à l'écran une surface cairo avec FreePascal et de fil en aiguille j'étais tombé sur cette discussion. Il m'avait semblé que ce rawimage.data était peut-être ce que je cherchais mais je n'ai pas su m'en servir.
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  9. #9
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 858
    Points : 11 301
    Points
    11 301
    Billets dans le blog
    6
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
      FBitmap:=Graphics.TBitmap.Create;
      // initialisation de l'image BitMap de travail, interne,
      // copiée ensuite dans le BitMap à passer aux utilisateurs,
      // qui permet une émulation de l'utilisation des ScanLines
      with RawImage // intermédiaire d'initialisation
      do begin
        Init;
        // pour compatibilité, création forcée BitMap pf24Bit dans un format BGRA 32 bits
        Description.Init_BPP32_B8G8R8_BIO_TTB(FWidth, FHeight);
        CreateData(True);
      end;
      ScanlineImage:=TLazIntfImage.Create(0,0);
      with ScanlineImage
      do begin
        SetRawImage(RawImage);
        ScanlineSize:=DataDescription.BytesPerLine;
      end;
      w:=FWidth*IntfBytesPerPixel;
      if w>ScanlineSize
      then raise ElyJpegError.Create('Bitmap Scanline Width Error')
      else ScanlineSize:=w; // car si ScanlineSize > w, ne sert qu'à l'alignement
    //...
      with ScanlineImage
      do begin
        BeginUpdate;
          for yy:=0 to FHeight-1
          do begin
            Ptr:=GetDataLineStart(yy); // ligne du bmp (initialise aussi PRP, absolute) = équivalent ScanLine
          //  Ptr: Pointer;
          //  PRP: ^TBGRAPixel absolute Ptr;
            with PRP^
            do begin
              Alpha := 0;
              // rouge
              //... 
              Inc(PRP);
            end;
          end;  
          //...
      end;
    //...
      // puis passage à la propriété BitMap interne
      FBitmap.LoadFromIntfImage(ScanlineImage);
      ScanlineImage.Free;
    Dans cet extrait de code (décompression JPEG-> BitMap), il semble me souvenir que le LazIntfImage sert justement à s'abstraire des différences d'implémentations entre OS http://wiki.lazarus.freepascal.org/D...r_avec_TBitmap
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  10. #10
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 072
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 072
    Points : 15 462
    Points
    15 462
    Billets dans le blog
    9
    Par défaut
    Voici une version Lazarus de l'exemple ColorMix. J'ai supprimé pas mal de choses du programme original, mais je crois que la partie intéressante y est.

    La solution que j'ai trouvée a été de remplacer le type TBitmap par le type TBGRABitmap, qui a une propriété ScanLine.

    J'ai ajouté l'unité Windows, pour les fonctions RGB() et MulDiv() (si ma mémoire est bonne). Sûrement il y avait moyen de faire autrement.
    Fichiers attachés Fichiers attachés
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  11. #11
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 730
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Citation Envoyé par Roland Chastain Voir le message
    Voici une version Lazarus de l'exemple ColorMix. J'ai supprimé pas mal de choses du programme original, mais je crois que la partie intéressante y est. (...)
    Toutes mes félicitations !

    En adaptant pour Linux (remplacement de l'unité Windows par LCLIntf, LCLType), ça fonctionne tip-top !

    J'ai rajouté la fonction pour CMY comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    function CreateCMYCircles(const size: integer; const Cflag, Mflag, Yflag: boolean): tBGRABitmap;
    var
      adjustedSize : integer;
      border       : integer;
      i, iC,iM,iY  :  INTEGER;
      j, jC,jM,jY  :  INTEGER;
      jOffset      : integer;
      radiusSquared: integer;
      row          : pBGRAPixel;//pRGBTripleArray;
    begin
      border := MulDiv(size, 5, 1000);
      adjustedSize := size - 2 * border;
      radiusSquared := Sqr( MulDiv(adjustedSize, 2,6) );
      iC := border + MulDiv(adjustedSize, 2, 6);
      iM := border + MulDiv(adjustedSize, 3, 6);
      iY := border + MulDiv(adjustedSize, 4, 6);
      jOffset := Round(adjustedSize * (2 - Sqrt(3))/12);
      jC := jOffset + border + Round(adjustedSize * (2 + Sqrt(3)) / 6);
      jM := jOffset + border + MulDiv(adjustedSize, 2, 6);
      jY := jC;
      result := tBGRABitmap.Create(size, size);//TBitmap.Create;
      //result.Width  := size;
      //result.Height := size;
      //result.PixelFormat := pf24bit;
      result.Canvas.Brush.Color := RGB(255,255,255);  // white
      result.Canvas.FillRect(result.Canvas.ClipRect);
      for j := 0 to result.Height-1 do
      begin
        row := result.Scanline[j];
        for i := 0 to result.Width-1 do
        begin
          with row[i] do
          begin
            if Cflag and (DistanceSquared(i,j, iC,jC) < radiusSquared) then red := 0;
            if MFlag and (DistanceSquared(i,j, iM,jM) < radiusSquared) then Green := 0;
            if YFlag and (DistanceSquared(i,j, iY,jY) < radiusSquared) then Blue := 0
          end
        end
      end
    end;
    J'ai rajouté un ComboBox (name: ComboBoxPrimaries) dont l'événement OnChange pointe sur CheckBoxRedClick, j'ai modifié cette procédure comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    begin
      IF   ComboBoxPrimaries.ItemIndex = 0
      THEN LabelDescribe.Caption := 'Add to Black'
      ELSE LabelDescribe.Caption := 'Subtract from White';
      UpdateEverything;
    end;
    et j'ai modifié UpdateEverything comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      IF ComboBoxPrimaries.ItemIndex = 0
      then Bitmap := CreateRGBCircles(Image.Width, CheckBoxRed.Checked, CheckBoxGreen.Checked, CheckBoxBlue.Checked)
      else Bitmap := CreateCMYCircles(Image.Width, CheckBoxRed.Checked, CheckBoxGreen.Checked, CheckBoxBlue.Checked);
      . . .
    Je ne regarderai pas / n'implémenterai pas la fonction "Print" car je n'ai pas d'imprimante couleur, mais à l'occasion je me pencherai sur "SaveToFile"...

    Yves, merci pour ta participation, mais rien qu'à lire ton petit bout de code j'en ai déjà mal à la tête

    Citation Envoyé par Roland Chastain Voir le message
    (...) La solution que j'ai trouvée a été de remplacer le type TBitmap par le type TBGRABitmap, qui a une propriété ScanLine. (...)
    Ça serait cool si Paul passait par là pour nous expliquer mon cafouillage d'il y a 2 jours, mais il doit être en vacances, c'est de saison

    Encore merci et bon week-end,

    [EDIT]
    mais à l'occasion je me pencherai sur "SaveToFile"...
    Dont acte : un bouton (name: btnSave), un SavePictureDialog (name: spd) avec son filtre réglé juste sur *.bmp, et ce bout de code et voilà
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    procedure TFormColorMix.btnSaveClick(Sender: TObject);
    CONST
      ImageSizeForFile = 512;
    VAR
      Bitmap: tBGRABitmap;//TBitmap;
      s: string;
    BEGIN
      IF spd.Execute THEN
      BEGIN
        IF ComboBoxPrimaries.ItemIndex = 0
        then Bitmap := CreateRGBCircles(ImageSizeForFile, CheckBoxRed.Checked, CheckBoxGreen.Checked, CheckBoxBlue.Checked)
        else Bitmap := CreateCMYCircles(ImageSizeForFile, CheckBoxRed.Checked, CheckBoxGreen.Checked, CheckBoxBlue.Checked);
        if LowerCase(ExtractFileExt(spd.Filename)) <> '.bmp'
        then s := spd.Filename + '.bmp'
        else s := spd.Filename;
        TRY
          Bitmap.SavetoFile(s);
          ShowMessage('File ' + s + ' written.')
        FINALLY
          Bitmap.Free
        END
      END
    end;
    PS : merci à celui (ou celle) qui m'a plussé
    [/EDIT]
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  12. #12
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 445
    Points
    28 445
    Par défaut
    Citation Envoyé par Jipété Voir le message
    Bonsoir,

    Désolé de déterrer ce topic vieux de presque 2 ans, mais le commentaire de Jon est plus que sibyllin et mystérieux, et ne m'aide pas beaucoup...

    Jon, comment ? ? ?


    Dans l'attente, si tu passes par là Paul, j'ai voulu utiliser ton bout de code pour passer un exemple trouvé chez efg et qui fonctionne bien en Delphi, et je bute comme Jon sur ce scanline...

    J'ai fait comme ça (le but de la manip est de dessiner des ronds RGB ou CMY dans une TImage de 480 x 480 sur la Form) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
      // RESULT est un TBitmap
      LineWidth := RESULT.RawImage.Description.BytesPerLine; // = 1920 vu en step-by-step
      ScanLine := RESULT.RawImage.Data; // (Paul) première ligne
     
      Getmem(row, SizeOf(row)*LineWidth);
      FillChar(row^, SizeOf(row)*LineWidth, '0');
     
      FOR j := 0 TO RESULT.Height-1 DO
      BEGIN
        //row := RESULT.Scanline[j]; // original Delphi
        row := @Scanline;
     
        FOR i := 0 TO RESULT.Width-1 DO  // crash ici (SIGSEGV) avec j = 237 et i = 479
        // 238 x 480 = 114240, ça ne me parle pas, d'autant plus que juste pour voir,
        // si je mets .Width-2 ça crashe pareil avec j = 237 et i = 478
        BEGIN
          WITH row[i] DO
          // work with row
        END;
        Inc(ScanLine, LineWidth); // (Paul) ligne suivante
     
      END;
      Freemem(row, SizeOf(row)*LineWidth);
    Une idée ?
    Merci d'avance,
    y'a des choses très étranges dans ton code !

    c'est quoi ça ? Getmem(row, SizeOf(row)*LineWidth); ?!

    là tu prends l'adresse d'un pointeur row := @Scanline; ?!

    à vu de nez il faudrait fait quelque chose comme ça

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     
     
      // Tous les pixels d'un coup
      row := RESULT.RawImage.Data;
     
      FOR j := 0 TO RESULT.Height-1 DO
      BEGIN
        //row := RESULT.Scanline[j];
        FOR i := 0 TO RESULT.Width-1 DO
        BEGIN
          WITH row[i] DO
          BEGIN
            IF   Rflag AND (DistanceSquared(i,j, iR,jR) < RadiusSquared)
            THEN rgbtRed := 255;
     
            IF   GFlag AND (DistanceSquared(i,j, iG,jG) < RadiusSquared)
            THEN rgbtGreen := 255;
     
            IF   BFlag AND (DistanceSquared(i,j, iB,jB) < RadiusSquared)
            THEN rgbtBlue := 255
          END
        END
     
       // Ligne suivante
        Inc(Cardinal(row), RESULT.Description.BytesPerLine);
     
      END;
    en effet, contrairement à ScanLine sous Delphi, RawImage.Data est un pointeur vers tous les pixels du tableau, à chaque ligne il faut sauter "BytesPerLine" octets pour atteindre la ligne suivante.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  13. #13
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 730
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut typo
    Bonsoir à tous,

    et plus particulièrement à Paul, qui passe du temps à dépatouiller mes soucis, et que je remercie très fort, si si !
    Citation Envoyé par Paul TOTH Voir le message
    y a des choses très étranges dans ton code !
    Aïe aïe aïe, ça va causer pointeurs, où est mon aspirine ?

    Citation Envoyé par Paul TOTH Voir le message
    c'est quoi ça ? Getmem(row, SizeOf(row)*LineWidth); ?!
    (...)
    en effet, contrairement à ScanLine sous Delphi, RawImage.Data est un pointeur vers tous les pixels du tableau, à chaque ligne il faut sauter "BytesPerLine" octets pour atteindre la ligne suivante.
    Et donc pour me balader ligne par ligne, j'ai gardé le "row" du source d'origine :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    var 
      row          :  pRGBTripleArray;
    Et puisque c'est un pointeur, faut bien que je lui alloue de la mémoire, nan ? D'où le Getmem.

    Petit aparté : suis réfractaire aux pointeurs depuis que j'ai essayé d'y comprendre quelque chose avec mon vieux D7 (ou peut-être 6) et que le premier exemple de l'aide ne compilait pas, et qu'après y être arrivé, c'était AV sur AV Bref...

    Citation Envoyé par Paul TOTH Voir le message
    là tu prends l'adresse d'un pointeur row := @Scanline; ?!
    C'est Lazarus qui demande ça : enlève l'esperluette et tu gagnes Error: Incompatible types: got "PByte" expected "pRGBTripleArray"

    Citation Envoyé par Paul TOTH Voir le message
    à vue de nez il faudrait fait quelque chose comme ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      // Tous les pixels d'un coup
      row := RESULT.RawImage.Data;
    et je ne passe pas cette première ligne ! : Error: Incompatible types: got "PByte" expected "pRGBTripleArray" avec le curseur entre "T" et "."
    Si je mets une esperluette, row := @RESULT.RawImage.Data; c'est le curseur à la fin de RawImage avec Error: Variable identifier expected...
    Je précise que RawImage et Data ont été proposés par la complétion automatique...
    Je vous ai dit que j'avais du mal avec les pointeurs

    Si je mets cette ligne qui pose problème en commentaire pour voir si sans elle ça compile, ça compile si je modifie
    Inc(Cardinal(row), RESULT.Description.BytesPerLine); en
    Inc(Cardinal(row), RESULT.RawImage.Description.BytesPerLine);

    Retour sur ce "row" (qui devrait s'appeler "raw", maintenant, s'il représente "tous les pixels d'un coup") : ça compile comme ça : row := pRGBTripleArray(RESULT.RawImage.Data);
    Et ça s'exécute sans crasher, impec !, mais sans rien afficher, moins impec...

    La destination est un TImage au fond noir sur lequel doivent s'afficher 3 cercles (R, V, B) en fonction de Checkbox :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    VAR
      Bitmap:  TBitmap;
    BEGIN
      Bitmap := CreateRGBCircles(Image.Width,
                                 CheckBoxRed.Checked,
                                 CheckBoxGreen.Checked,
                                 CheckBoxBlue.Checked)
      TRY
        Image.Picture.Graphic := Bitmap;
      FINALLY
        Bitmap.Free
      END;   
    END;
    Merci pour vos retours lumineux, bonne soirée,
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  14. #14
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 858
    Points : 11 301
    Points
    11 301
    Billets dans le blog
    6
    Par défaut
    Ouh, malheureux !

    N'alloue de la mémoire que si ton pointeur doit adresser une zone que tu dois créer.

    Ici, il s'agit simplement de lui attribuer l'adresse d'une zone mémoire déjà créée.

    Et en ces temps de fête, aspirine OK, mais citrate de bétaïne aussi ;-)
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  15. #15
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 730
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Citation Envoyé par tourlourou Voir le message
    Ouh, malheureux !

    N'alloue de la mémoire que si ton pointeur doit adresser une zone que tu dois créer.

    Ici, il s'agit simplement de lui attribuer l'adresse d'une zone mémoire déjà créée.
    Ok Ok, je vais essayer de me graver ça dans le cerveau

    Cependant, avec ou sans Getmem, mon TImage reste désespérément noir...
    Comment savoir si c'est la mécanique de calcul qui foire, ou l'affichage ?

    Citation Envoyé par tourlourou Voir le message
    Et en ces temps de fête, aspirine OK, mais citrate de bétaïne aussi ;-)
    D'ac !
    PS : très bien, ton avatar
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  16. #16
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 730
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Citation Envoyé par Jipété Voir le message
    Comment savoir si c'est la mécanique de calcul qui foire, ou l'affichage ?
    Bon, c'est les deux qui foiraient, mais on y est presque !

    1- pour m'affranchir du problème d'affichage, j'ai fait ça et ça roule :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    VAR
      Bitmap:  TBitmap;
      ms: TMemoryStream; // +1 !
    BEGIN
      Bitmap := CreateRGBCircles(Image.Width,
                                 CheckBoxRed.Checked,
                                 CheckBoxGreen.Checked,
                                 CheckBoxBlue.Checked)
      TRY
        ms := TMemoryStream.Create;
        Bitmap.SaveToStream(ms);
        ms.Position:=0;
        Image.Picture.LoadFromStream(ms);
      finally
        ms.Free;
        Bitmap.Free;
      END;   
    END;
    2- ensuite, j'ai "remonté"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        // Ligne suivante
        Inc(Cardinal(row), RESULT.RawImage.Description.BytesPerLine);
    dans la boucle For j := 0... et j'ai enfin une image !
    Bon, pas terrible encore, mais on y est presque :
    Nom : colormix.png
Affichages : 706
Taille : 4,5 Ko
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  17. #17
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 445
    Points
    28 445
    Par défaut
    Citation Envoyé par Jipété Voir le message
    Bonsoir à tous,

    et plus particulièrement à Paul, qui passe du temps à dépatouiller mes soucis, et que je remercie très fort, si si !

    A:ïe aïe aïe, ça va causer pointeurs, où est mon aspirine ?
    ok, petit rappel sur les pointeurs

    une varaible rgb: TRGBTriple; occupe un certain espace mémoire (sur la pile), je peux la modifier comme je veux mais ça m'intéresse assez peu si c'est le contenu de l'image que je veux modifier. Donc ce qui serait génial c'est de pouvoir dire, que ma variable n'est pas allouée sur la pile mais qu'elle se trouve au début de mon bitmap. ça serait cool non ? Et bien pour avoir une variable dont on peut à la fois modifier la valeur et l'adresse, il faut utilise un pointer rgb: PRGBTriple. Cette nouvelle variable n'a pas d'espace mémoire alloué (c'est le but) je vais donc lui en donner un :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    var
      rgb: PRGBTriple;
    begin
      rgb := PRGBTriple(Bitmap.RawImage.Data);
      rgb^.rgbtRed := 1;
    end;
    dans le code ci-dessus je copie un pointer (RawImage.Data) dans un autre (rgb) c'est donc tout à fait valide, même si le fait qu'ils soient typés m'oblige à transtyper le pointer. @ ne doit être utilisé que pour récupérer l'adresse d'un TRGTriple pour obtenir un PRGBTriple, ce qui n'est pas le cas ici car j'ai déjà un pointeur.

    dans le code on utilise un pRGBTripleArray mais c'est le même principe sur un tableau de valeur au lieu d'une valeur unique.

    Citation Envoyé par Jipété Voir le message
    Et donc pour me balader ligne par ligne, j'ai gardé le "row" du source d'origine :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    var 
      row          :  pRGBTripleArray;
    Et puisque c'est un pointeur, faut bien que je lui alloue de la mémoire, nan ? D'où le Getmem.
    donc non

    Citation Envoyé par Jipété Voir le message
    Petit aparté : suis réfractaire aux pointeurs depuis que j'ai essayé d'y comprendre quelque chose avec mon vieux D7 (ou peut-être 6) et que le premier exemple de l'aide ne compilait pas, et qu'après y être arrivé, c'était AV sur AV Bref...


    C'est Lazarus que demande ça : enlève l'esperluette et tu gagnes Error: Incompatible types: got "PByte" expected "pRGBTripleArray"


    et je ne passe pas cette première ligne ! : Error: Incompatible types: got "PByte" expected "pRGBTripleArray" avec le curseur entre "T" et "."
    Si je mets une esperluette, row := @RESULT.RawImage.Data; c'est le curseur à la fin de RawImage avec Error: Variable identifier expected...
    voir plus haut

    Citation Envoyé par Jipété Voir le message
    Je précise que RawImage et Data ont été proposés par la complétion automatique...
    Je vous ai dit que j'avais du mal avec les pointeurs

    Si je mets cette ligne qui pose problème en commentaire pour voir si sans elle ça compile, ça compile si je modifie
    Inc(Cardinal(row), RESULT.Description.BytesPerLine); en
    Inc(Cardinal(row), RESULT.RawImage.Description.BytesPerLine);
    peut-être je n'ai pas testé le code, je ne sais plus où se trouve l'info

    Citation Envoyé par Jipété Voir le message
    Retour sur ce "row" (qui devrait s'appeler "raw", maintenant, s'il représente "tous les pixels d'un coup") : ça compile comme ça : row := pRGBTripleArray(RESULT.RawImage.Data);
    je le laisserai en "row" vu que s'il pointe bien sur toute l'image au départ, on va à chaque boucle changer sa valeur pour pointer sur le premier pixel de la ligne.

    Citation Envoyé par Jipété Voir le message
    Et ça s'exécute sans crasher, impec !, mais sans rien afficher, moins impec...

    La destination est un TImage au fond noir sur lequel doivent s'afficher 3 cercles (R, V, B) en fonction de Checkbox :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    VAR
      Bitmap:  TBitmap;
    BEGIN
      Bitmap := CreateRGBCircles(Image.Width,
                                 CheckBoxRed.Checked,
                                 CheckBoxGreen.Checked,
                                 CheckBoxBlue.Checked)
      TRY
        Image.Picture.Graphic := Bitmap;
      FINALLY
        Bitmap.Free
      END;   
    END;
    Merci pour vos retours lumineux, bonne soirée,
    peut-être un Image.Picture.Assign(Bitmap), même sous Delphi j'ai toujours un doute sur cette opération

    Et pour ce qui est de ton dernier post avec une image "rayées" c'est manifestement un problème de format de Bitmap, 24bits/32bits etc..
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  18. #18
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 858
    Points : 11 301
    Points
    11 301
    Billets dans le blog
    6
    Par défaut
    Finalement, le code que je proposais (mais sans aspirine !) se réduit aux fondamentaux !
    1) imposer un format aux pixels d'un RawImage ;
    2) en tirer un LazIntfImage, indépendant de l'OS, qui fournit directement un équivalent de Scanline (GetDataLineStart)
    3) le coller à un BitMap (LoadFromIntfImage)
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  19. #19
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 730
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut Ajout
    Bonjour tout le monde,

    Yves,
    merci de ton soutien, cependant un point me pose problème quant au bout de code posté par toi il y a qq jours.
    Ligne 30 je vois ça :
    // PRP: ^TBGRAPixel absolute Ptr;qui signifie, àmha, qu'il faut inclure les unités BGRABitmap et BGRABitmapTypes, or le but de la manip était de faire tourner la routine de Paul sans unités supplémentaires.
    Car sinon, le code de Roland fonctionne très bien, et plus de prise de tête.


    Paul,
    un grand merci pour toutes ces explications
    Du coup j'ai réussi à faire fonctionner la première version de ton code, celle d'il y a deux ans
    Citation Envoyé par Paul TOTH Voir le message
    peut-être un Image.Picture.Assign(Bitmap), même sous Delphi j'ai toujours un doute sur cette opération
    Déjà tenté, rien d'affiché, juste le fond noir.

    Citation Envoyé par Paul TOTH Voir le message
    Et pour ce qui est de ton dernier post avec une image "rayées" c'est manifestement un problème de format de Bitmap, 24bits/32bits etc..
    avec pf8bit, rien et le noir n'est même pas affiché
    avec pf15bit, même résultat qu'avec 24
    avec pf16bit, même résultat qu'avec 24
    avec pf32bit, le noir n'est pas affiché et les 3 ovales sont rayés de rose.

    Mais j'ai trouvé !
    À grands coups de ShowMessage et de Memo.Log plus un soupçon de gamberge, j'ai mis le doigt là où ça faisait mal, et il suffit juste de changer row: pRGBTripleArray; en pRGBQuadArray.
    La preuve :
    Nom : colormix-ok.png
Affichages : 650
Taille : 18,5 Ko

    Voilà le truc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
      TYPE
        TRGBQuadArray = ARRAY[0..PixelCountMax-1] OF TRGBQuad;
        pRGBQuadArray = ^TRGBQuadArray;
      VAR
        row          :  pRGBQuadArray;
      . . .
      ScanLine  := RESULT.RawImage.Data; // première ligne
     
      FOR j := 0 TO RESULT.Height-1 DO
        BEGIN
          //row := RESULT.Scanline[j]; // orig Delphi
          row := pRGBQuadArray(Scanline);
     
          FOR i := 0 TO RESULT.Width-1 DO
          BEGIN
            WITH row[i] DO
            BEGIN
              if RESULT.PixelFormat = pf32bit then rgbReserved := 0;
     
              IF   RFlag AND (DistanceSquared(i,j, iR,jR) < RadiusSquared)
              THEN rgbRed := 255;
     
              IF   GFlag AND (DistanceSquared(i,j, iG,jG) < RadiusSquared)
              THEN rgbGreen := 255;
     
              IF   BFlag AND (DistanceSquared(i,j, iB,jB) < RadiusSquared)
              THEN rgbBlue := 255;
            END;
          END;
          Inc(ScanLine, LineWidth); // ligne suivante
        END;
    Fonctionne en RESULT.PixelFormat := pf24bit; et RESULT.PixelFormat := pf32bit;

    [ EDIT ] avec un curieux effet de bord : l'image ci-dessus vient suite à pf24bit. Si je mets pf32bit, le rouge et le bleu sont inversés [ /EDIT ]


    Valà, encore un grand merci à tous, le est bien justifié , bonne fin de dimanche.
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  20. #20
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 072
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 072
    Points : 15 462
    Points
    15 462
    Billets dans le blog
    9
    Par défaut
    Bravo Jipété !

    Sans vouloir te commander, si tu voulais bien poster le projet complet, je serais preneur.

    Est-ce que ça ne mériterait pas même d'être ajouté dans nos sources (éventuellement en incluant la version BGRABitmap) ?
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. probleme fct TBitmap::ScanLine
    Par comrad85 dans le forum C++Builder
    Réponses: 11
    Dernier message: 19/01/2008, 23h41
  2. pb couleur avec Scanline
    Par bobymaw dans le forum C++Builder
    Réponses: 6
    Dernier message: 10/05/2004, 22h25
  3. TBitmap et problèmes de pointeurs...
    Par benj63 dans le forum C++Builder
    Réponses: 8
    Dernier message: 28/07/2003, 13h39
  4. Rotation de Bitmap -> ScanLine
    Par jujuesteban dans le forum Langage
    Réponses: 7
    Dernier message: 03/07/2003, 15h11
  5. tbitmap.free dans une function
    Par portu dans le forum Langage
    Réponses: 7
    Dernier message: 19/06/2003, 22h08

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo