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 :

Travailler avec TBitmap et des fichiers bmp sous Linux [Lazarus]


Sujet :

Lazarus Pascal

  1. #141
    Rédacteur/Modérateur
    Avatar de M.Dlb
    Inscrit en
    Avril 2002
    Messages
    2 464
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Avril 2002
    Messages : 2 464
    Points : 4 311
    Points
    4 311
    Par défaut
    Non Self désigne toujours le même objet, aucune confusion possible.

    Et je prèfère mille fois :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    un_objet_avec_un_nom_long.une_main_propriété_au_nom_long_aussi.sous_propriété1 := valeur1;
    un_objet_avec_un_nom_long.une_main_propriété_au_nom_long_aussi.sous_propriété2 := valeur2;
    un_objet_avec_un_nom_long.une_main_propriété_au_nom_long_aussi.sous_propriétén := valeurn;
    à ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    With un_objet_avec_un_nom_long.une_main_propriété_au_nom_long_aussi Do 
    begin
      sous_propriété1 := valeur1;
      sous_propriété2 := valeur2;
      sous_propriétén := valeurn;
    end;
    Car dans la première écriture, aucune ambiguité possible sur l'origine de valeur1/valeur2/valeurn -> on est sûr que ce ne sont pas des attributs de l'objet avec lequel le with est fait.
    Et l'excuse du "ça fait trop de caractères sur l'écran" n'est pas valable, car c'est beaucoup plus simple de scroller vers la droite que de balayer tout un code (qui potentiellement n'a pas été écrit par toi) afin de chercher l'origine d'une variable.
    M.Dlb - Modérateur z/OS - Rédacteur et Modérateur Pascal

  2. #142
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    Septembre 2015
    Messages
    1 899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2015
    Messages : 1 899
    Points : 4 346
    Points
    4 346
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Jipété Voir le message
    Yop !


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Begin
      SrcW := Self.Width;
      SrcH := self.Height;
     
              AColor := Self.getPixel(ii, jj);
     
      self.Assign(TmpBmp);
    End;
    Ben en fait je n'y comprends rien, car sortie de son contexte, je ne sais pas avec quoi travaille ta routine.
    Je n'ai gardé que la partie qui me pose problème, ce "Self" qui a l'air de désigner en haut et au milieu la source, et en bas la destination

    Largué, le jipé, là...
    Comme l'as dis AndNotOr le sefl designe l'objet lui même

    Ma procedure StretchBicubic redimensionne le bitmap lui même (Self)
    La procedure ne renvoie pas un bitmap de destination. Comme tu peux le voir le redimensionnement est effectué dans un bitmap temporaire qui est, à la fin assigné à Self et donc qui remplace l'image originelle, d'ou self.Assign(TmpBmp);La destination c'est TmpBmp et la source Self

    C'était la même avec la procedure Stretch, que j'avais posté :

    Citation Envoyé par BeanzMaster Voir le message
    1) Le FastBitmap est retaillé lui même
    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
     
    function Clamp(const V,Min,Max : integer) : integer;
    begin
      Result := V;
      if Result > Max then begin result := Max; exit; end;
      if Result < Min then result := Min;
    end; 
     
    procedure TFastBitmap.Stretch(var NW, NH : Integer; const KeepRatio : Boolean = false);
    Var
      TmpBmp: TfastBitmap;
      SrcW, SrcH, DstW, DstH, X, Y, UX, UY: Integer;
      Dx, Dy, uvx, uvy: Single;
      DstPtr, SrcPtr: PColor32;
      AColor: TColor32;
     
      Procedure KeepAspectRatio(Const aSrcW, aSrcH: Integer; Var NewWidth, NewHeight: Integer);
      Var
        w, h: Integer;
      Begin
        W := NewWidth;
        H := newHeight;
        if ( aSrcW > 1) and ( aSrcH > 1) then // On calcul le ratio par rapport aux dimensions du buffer d'affichage
        begin
          H:=Trunc((aSrcH*W) / aSrcW);
          if (H>=NewHeight) then
          begin
            H:=NewHeight;
            W:=Trunc((aSrcW*H) / aSrcH);
          end;
          NewWidth := W;
          NewHeight := H;
        end;
      end;
     
    Begin
      SrcW := Self.Width;
      SrcH := Self.Height;
      If (NW = SrcW) And (NH = SrcH) Then exit;
      If KeepRatio Then KeepAspectRatio(SrcW, SrcH, NW, NH);
      TmpBmp := TFastBitmap.Create;
      TmpBmp.SetSize(NW, NH);
      DstW := NW - 1;
      DstH := NH - 1;
      Dx := SrcW / DstW;
      Dy := SrcH / DstH;
      DstPtr := TmpBmp.GetScanLine(0);
      UvY :=0;
      For y := 0 To DstH Do
      Begin
        UY := Clamp(Trunc(UvY), 0, Self.Height-1);
        SrcPtr := Self.GetScanLine(UY);
        UvX := 0;
        For X := 0 To DstW Do
        Begin
          UX := Clamp(Trunc(UvX), 0, Self.Width-1);
          AColor := PColor32(SrcPtr + UX)^;
          DstPtr^ := AColor;
          Inc(DstPtr);
          UvX := UvX + DX;
        End;
        UvY := UvY + DY;
      End;
      Self.Assign(TmpBmp);
      FreeAndNil(TmpBmp);
    End;
    2) Le FastBitmap est retaillé vers un autre FastBitmap (on conserve donc celui d'origine)

    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
     
    function TFastBitmap.StretchTo(var NW, NH : Integer; const KeepRatio : Boolean = false) : TFastBitmap;
    Var
      TmpBmp: TfastBitmap;
      SrcW, SrcH, DstW, DstH, X, Y, UX, UY: Integer;
      Dx, Dy, uvx, uvy: Single;
      DstPtr, SrcPtr: PColor32;
      AColor: TColor32;
     
      Procedure KeepAspectRatio(Const aSrcW, aSrcH: Integer; Var NewWidth, NewHeight: Integer);
      Var
        w, h: Integer;
      Begin
        W := NewWidth;
        H := newHeight;
        if ( aSrcW > 1) and ( aSrcH > 1) then // On calcul le ratio par rapport aux dimensions du buffer d'affichage
        begin
          H:=Trunc((aSrcH*W) / aSrcW);
          if (H>=NewHeight) then
          begin
            H:=NewHeight;
            W:=Trunc((aSrcW*H) / aSrcH);
          end;
          NewWidth := W;
          NewHeight := H;
        end;
      end;
     
    Begin
      SrcW := Self.Width;
      SrcH := Self.Height;
      If (NW = SrcW) And (NH = SrcH) Then exit;
      If KeepRatio Then KeepAspectRatio(SrcW, SrcH, NW, NH);
      TmpBmp := TFastBitmap.Create;
      TmpBmp.SetSize(NW, NH);
      DstW := NW - 1;
      DstH := NH - 1;
      Dx := SrcW / DstW;
      Dy := SrcH / DstH;
      DstPtr := TmpBmp.GetScanLine(0);
      UvY :=0;
      For y := 0 To DstH Do
      Begin
        UY := Clamp(Trunc(UvY), 0, Self.Height-1);
        SrcPtr := Self.GetScanLine(UY);
        UvX := 0;
        For X := 0 To DstW Do
        Begin
          UX := Clamp(Trunc(UvX), 0, Self.Width-1);
          AColor := PColor32(SrcPtr + UX)^;
          DstPtr^ := AColor;
          Inc(DstPtr);
          UvX := UvX + DX;
        End;
        UvY := UvY + DY;
      End;
      Result := TmpBmp;
    End;
    ou sinon tu rajoutes un "var BmpDst : TFastBitmap" ce qui donnerai

    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    procedure TFastBitmap.Stretch(var BmpDst : TFastBitmap; var NW, NH : Integer; const KeepRatio : Boolean = false);
    Var
      SrcW, SrcH, DstW, DstH, X, Y, UX, UY: Integer;
      Dx, Dy, uvx, uvy: Single;
      DstPtr, SrcPtr: PColor32;
      AColor: TColor32;
     
      Procedure KeepAspectRatio(Const aSrcW, aSrcH: Integer; Var NewWidth, NewHeight: Integer);
      Var
        w, h: Integer;
      Begin
        W := NewWidth;
        H := newHeight;
        if ( aSrcW > 1) and ( aSrcH > 1) then // On calcul le ratio par rapport aux dimensions du buffer d'affichage
        begin
          H:=Trunc((aSrcH*W) / aSrcW);
          if (H>=NewHeight) then
          begin
            H:=NewHeight;
            W:=Trunc((aSrcW*H) / aSrcH);
          end;
          NewWidth := W;
          NewHeight := H;
        end;
      end;
     
    Begin
      SrcW := Self.Width;
      SrcH := Self.Height;
      If (NW = SrcW) And (NH = SrcH) Then exit;
      If KeepRatio Then KeepAspectRatio(SrcW, SrcH, NW, NH);
      BmpDst.SetSize(NW, NH);
      DstW := NW - 1;
      DstH := NH - 1;
      Dx := SrcW / DstW;
      Dy := SrcH / DstH;
      DstPtr := BmpDst.GetScanLine(0);
      UvY :=0;
      For y := 0 To DstH Do
      Begin
        UY := Clamp(Trunc(UvY), 0, Self.Height-1);
        SrcPtr := Self.GetScanLine(UY);
        UvX := 0;
        For X := 0 To DstW Do
        Begin
          UX := Clamp(Trunc(UvX), 0, Self.Width-1);
          AColor := PColor32(SrcPtr + UX)^;
          DstPtr^ := AColor;
          Inc(DstPtr);
          UvX := UvX + DX;
        End;
        UvY := UvY + DY;
      End;
    End;
    Voila a toi de voir. Idem pour "Var NW, NH" tu peux virer le var si jamais, car sinon tu ne peux pas passer les nouvelles dimensions en dur (genre stretch(100,100); ).
    Je les ai mis en var pour récupérer facilement les nouvelles dimensions si elles sont ajustés par "KeepRatio"
    Lorsque je fais des modifications sur un bitmap je préfère que celles-ci s'appliquent directement sur le bitmap "source" plutôt que de passer par un bitmap de destination supplémentaire, puis réassigné, puis ne pas oublié de libérer le bitmap de destination.
    Le fait de faire ainsi limite aussi les oublis de libération des objets (ici le Bitmap temporaire est gérer en interne dans la procedure et est valide que pendant la durée du traitement) On n'a donc pas 2 bitmaps en mémoire à la fin du traitement.
    Si je veux conserver conserver l'original, je fais une copie avant traitement. Et mettre en place un système de "UNDO/REDO" devient plus facile à mettre en place selon moi.

    En passant par le TBMPViewer.FastBitmap par exemple, si tu effectues un redimensionnement directement sur le bitmap, l'affichage de celui-ci est quasi automatique suffit juste de demandé le rafraichissement.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    BmpViewer.FastBitmap.Strecth(nw,nh,true);
    BmpViewer.Invalidate;
    Voilà j'espère que cela t'éclaireras

    A+
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

  3. #143
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    762
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 762
    Points : 957
    Points
    957
    Par défaut
    Citation Envoyé par M.Dlb Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    un_objet_avec_un_nom_long.une_main_propriété_au_nom_long_aussi.sous_propriété1 := valeur1;
    un_objet_avec_un_nom_long.une_main_propriété_au_nom_long_aussi.sous_propriété2 := valeur2;
    un_objet_avec_un_nom_long.une_main_propriété_au_nom_long_aussi.sous_propriétén := valeurn;
    Dieu, quel horreur que ce genre de code...

    Citation Envoyé par M.Dlb Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    With un_objet_avec_un_nom_long.une_main_propriété_au_nom_long_aussi Do 
    begin
      sous_propriété1 := valeur1;
      sous_propriété2 := valeur2;
      sous_propriétén := valeurn;
    end;
    Je préféré celui-ci, et de loin…

    comme quoi, le goût et les couleurs, hein !


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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Citation Envoyé par der§en Voir le message
    Dieu, quel horreur que ce genre de code...

    Je préféré celui-ci, et de loin…

    comme quoi, le goût et les couleurs, hein !

    En fait, c'est lié à une histoire de lecture, et de mise en page typographique : on est à des années-lumière de la programmation et du code, et nos yeux lisent ça comme ils liraient un journal ou n'importe quoi d'autre, et avec plus ou moins de confort totalement inconscient en fonction de la composition du document.

    Et il faut savoir que nos yeux préfèrent des lignes courtes, 10 à 12 mots max, après ils se "perdent" car, fonctionnant comme une télévision à l'envers, ils balaient la surface de gauche à droite puis reviennent au début de la ligne et passent à la suivante pour recommencer.

    Et sur les lignes longues, des études ont montré que l'œil se "perd" pendant le retour et ne sait plus trop sur quelle ligne il doit continuer.

    Quand je vois tous ces gens avec leurs discours à la main, leurs plaquettes reliées, toutes ces choses qu'on croise en entreprise, imprimées sur du A4 sans aucune correction des marges, ben je les plains.
    Les contrats, les rapports, les machins juridiques, les comptes-rendus, toute cette foultitude de documents mal fichus...

    Posez-vous donc la question du pourquoi des colonnes dans les journaux et magazines...
    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

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Bonjour,

    allez, tiens, juste pour enfoncer mon clou et faire profiter la communauté, je viens de reprendre un vieux truc minimaliste (qui va me servir de base pour autre chose), minimaliste dans le sens où il n'y a sur la fiche qu'une scrollbox (alClient) contenant un tpanel contenant un timage (alClient) et un tpanel (alBottom) contenant une trackbar pour la taille.

    Deux variables déclarées en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      private
        { private declarations }
        srcRect, dstRect: TRect;
    et roule ma poule :
    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      pnl4image.OnPaint:=@pnl4imagePaint; //!\ /!\ /!\ /!\ /!\
     
      {$IFDEF LINUX}
      Image.Picture.LoadFromFile (ProgramDirectory+'400x300.jpg');
      {$ELSE}
      Image.Picture.LoadFromFile ('p:\Programmation\bmp4test.jpg');
      {$ENDIF}
      with srcRect do begin
        Left   := 0;
        Top    := 0;
        Right  := Image.Picture.Bitmap.Width;
        Bottom := Image.Picture.Bitmap.Height;
      end;
     
      with pnl4image do begin
        Width  := srcRect.Right;
        Height := srcRect.Bottom;
      end;
    end;
     
    procedure TForm1.FormResize(Sender: TObject);
    begin
      with pnl4image do begin
        if (Width  < sbox.ClientWidth)
        then Left :=(sbox.ClientWidth -Width ) div 2
        else Left :=0;
     
        if (Height < sbox.ClientHeight)
        then Top  :=(sbox.ClientHeight-Height) div 2
        else Top  :=0;
      end;
    end;
     
    procedure TForm1.trkScaleChange(Sender: TObject);
    var
      scale: single;
    begin
      scale := trkScale.Position / 100;
      with dstRect do begin
        Left   := trunc(srcRect.Left   * scale);
        Top    := trunc(srcRect.Top    * scale);
        Right  := trunc(srcRect.Right  * scale);
        Bottom := trunc(srcRect.Bottom * scale);
      end;
     
      with pnl4image do begin
        Left  := (Width  - Parent.Width ) div 2;
        Top   := (Height - Parent.Height) div 2;
        Width := dstRect.Right;
        Height:= dstRect.Bottom;
      end;
     
      FormResize(nil); // pour positionner le pnl4image
    end;
     
    procedure TForm1.pnl4imagePaint(Sender: TObject);
    begin
      with Sender as TPANEL do
        Canvas.StretchDraw(ClientRect, Image.Picture.Bitmap);
    end;
    Ça te plait, der§en ?

    Nom : illustration.png
Affichages : 194
Taille : 129,3 Ko

    Allez, au boulot !
    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

  6. #146
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    762
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 762
    Points : 957
    Points
    957
    Par défaut
    Tu veux vraiment que je commente ÇA ?


  7. #147
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    762
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 762
    Points : 957
    Points
    957
    Par défaut
    Rapidement, comme cela sans comprendre vraiment ou tu veux allez avec ton bout de code, j'aurai fait plutôt un truc comme ceci:
    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
    45
     
    Procedure TForm1.FormCreate(Sender: TObject);
    Begin
      Image.Picture.LoadFromFile ('G:\Mes Projets Lazarus\Test Jipete\bmp4test.jpg');
     
      srcRect := Bounds(0, 0, Image.Picture.Bitmap.Width, Image.Picture.Bitmap.Height);
      dstRect := srcRect;
    end;
     
    Procedure TForm1.FormResize(Sender: TObject);
    Begin
      ControlePosition;
    end;
     
    Procedure TForm1.pnl4imagePaint(Sender: TObject);
    Begin
      pnl4image.Canvas.StretchDraw(dstRect, Image.Picture.Bitmap);
    end;
     
    Procedure TForm1.trkScaleChange(Sender: TObject);
    var
      scale: single;
    Begin
      scale := trkScale.Position / 100;
     
      dstRect := Bounds(0, 0, trunc(srcRect.Right * scale), trunc(srcRect.Bottom * scale));
     
      ControlePosition;
    end;
     
    Procedure TForm1.ControlePosition;
    Begin
       if dstRect.Width >= sBox.Width then
        pnl4image.Left := 0
      else
        pnl4image.Left := (sBox.Width - dstRect.Width) div 2;
     
      if dstRect.Height >= sBox.Height then
        pnl4image.Top := 0
      else
          pnl4image.Top := (sBox.Height - dstRect.Height) div 2;
     
      pnl4image.Width  := dstRect.Width;
      pnl4image.Height := dstRect.Height;
    End;
    Nom : resultat.jpg
Affichages : 195
Taille : 79,3 Ko
    Test Jipete.zip

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Bonjour,

    Citation Envoyé par der§en Voir le message
    Rapidement, comme cela sans comprendre vraiment ou tu veux aller avec ton bout de code, j'aurai fait plutôt un truc comme ceci:
    Nulle part, c'était juste pour montrer ma palanquée de with, qui ne nuit pas à la lisibilité, àmha.
    Pas plus.

    Sinon, hier et aujourd'hui, j'ai fait des tests avec
    • TBitmap
    • TLazIntfImage
    • TBMPViewer de Jérôme
    • TFastBitmap du même
    • la paire TCompImages/TlclCompImages du père Mitchell (à ne pas confondre avec la mère Michel, )

    J'ai été vicieux et pervers en demandant la création d'un bitmap à 32 bits par pixel et avec une largeur de 121 pixels (après tout, Gimp, 'toshop et les autres peuvent le faire, alors pourquoi pas nous ?), voilà les résultats :
    Nom : 5_bitmaps.png
Affichages : 170
Taille : 22,7 Ko
    et voilà le code :
    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    540
    541
    542
    543
    544
    545
    546
    547
    548
    549
    550
    551
    552
    553
    554
    555
    556
    557
    558
    559
    //////////////////////// UNIT1.LFM
    object Form1: TForm1
      Left = 401
      Height = 770
      Top = 132
      Width = 330
      Caption = 'Form1'
      ClientHeight = 770
      ClientWidth = 330
      OnCreate = FormCreate
      LCLVersion = '1.4.0.4'
      object trkTranspar: TTrackBar
        Left = 288
        Height = 238
        Top = 8
        Width = 36
        Max = 255
        Orientation = trVertical
        PageSize = 15
        Position = 127
        Reversed = True
        TabOrder = 0
      end
      object gbxTBitmap: TGroupBox
        Left = 10
        Height = 140
        Top = 10
        Width = 185
        Caption = 'TBitmap'
        ClientHeight = 123
        ClientWidth = 181
        TabOrder = 1
        object btnTBitmap: TButton
          Left = 40
          Height = 25
          Top = 8
          Width = 81
          Caption = 'Button'
          OnClick = btnTBitmapClick
          TabOrder = 0
        end
        object imgTBitmap: TImage
          Left = 16
          Height = 69
          Top = 40
          Width = 137
        end
      end
      object gbxTLazIntfImage: TGroupBox
        Left = 10
        Height = 140
        Top = 160
        Width = 185
        Caption = 'TLazIntfImage'
        ClientHeight = 123
        ClientWidth = 181
        TabOrder = 2
        object btnTLazIntfImage: TButton
          Left = 40
          Height = 25
          Top = 8
          Width = 81
          Caption = 'Button'
          OnClick = btnTLazIntfImageClick
          TabOrder = 0
        end
        object imgTLazIntfImage: TImage
          Left = 16
          Height = 69
          Top = 40
          Width = 137
        end
      end
      object gbxTbzBMPViewer: TGroupBox
        Left = 10
        Height = 140
        Top = 310
        Width = 185
        Caption = 'TbzBMPViewer'
        ClientHeight = 123
        ClientWidth = 181
        TabOrder = 3
        object btnTbzBMPViewer: TButton
          Left = 40
          Height = 25
          Top = 8
          Width = 81
          Caption = 'Button'
          OnClick = btnTbzBMPViewerClick
          TabOrder = 0
        end
        object pnlTbzBMPViewer: TPanel
          Left = 16
          Height = 69
          Top = 40
          Width = 137
          BevelOuter = bvNone
          Caption = 'pnlTbzBMPViewer'
          ClientHeight = 69
          ClientWidth = 137
          TabOrder = 1
          object imgTbzBMPViewer: TImage
            Left = 0
            Height = 69
            Top = 0
            Width = 137
            Align = alClient
          end
        end
      end
      object gbxTbzFastBitmap: TGroupBox
        Left = 10
        Height = 140
        Top = 460
        Width = 185
        Caption = 'TbzFastBitmap'
        ClientHeight = 123
        ClientWidth = 181
        TabOrder = 4
        object btnTbzFastBitmap: TButton
          Left = 40
          Height = 25
          Top = 8
          Width = 81
          Caption = 'Button'
          OnClick = btnTbzFastBitmapClick
          TabOrder = 0
        end
        object imgTbzFastBitmap: TImage
          Left = 16
          Height = 69
          Top = 40
          Width = 137
        end
      end
      object gbxTMitchell: TGroupBox
        Left = 10
        Height = 140
        Top = 610
        Width = 185
        Caption = 'TMitchell'
        ClientHeight = 123
        ClientWidth = 181
        TabOrder = 5
        object btnTMitchell: TButton
          Left = 40
          Height = 25
          Top = 8
          Width = 81
          Caption = 'Button'
          OnClick = btnTMitchellClick
          TabOrder = 0
        end
        object imgTMitchell: TImage
          Left = 16
          Height = 69
          Top = 40
          Width = 137
        end
      end
    end
     
    //////////////////////// UNIT1.PAS
     
    unit Unit1;
     
    {$mode objfpc}{$H+}
     
    interface
     
    uses
      LCLintf, LCLtype,
      Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
      FPImage, GraphType, IntfGraphics,
      uBMPViewer, uFastBitmap,
      u_mitchell,
      ExtCtrls, ComCtrls;
     
    type
     
      { TForm1 }
     
      TForm1 = class(TForm)
        btnTBitmap: TButton;
        btnTbzFastBitmap: TButton;
        btnTMitchell: TButton;
        btnTLazIntfImage: TButton;
        btnTbzBMPViewer: TButton;
        gbxTBitmap: TGroupBox;
        gbxTbzFastBitmap: TGroupBox;
        gbxTMitchell: TGroupBox;
        gbxTLazIntfImage: TGroupBox;
        gbxTbzBMPViewer: TGroupBox;
        imgTBitmap: TImage;
        imgTbzBMPViewer: TImage;
        imgTbzFastBitmap: TImage;
        imgTMitchell: TImage;
        imgTLazIntfImage: TImage;
        pnlTbzBMPViewer: TPanel;
        trkTranspar: TTrackBar;
        procedure btnTBitmapClick(Sender: TObject);
        procedure btnTbzBMPViewerClick(Sender: TObject);
        procedure btnTbzFastBitmapClick(Sender: TObject);
        procedure btnTLazIntfImageClick(Sender: TObject);
        procedure btnTMitchellClick(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        { private declarations }
        HSIZE,WSIZE,aWidth: integer;
        ratio: single;
      public
        { public declarations }
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    {$R *.lfm}
     
    { TForm1 }
     
    function its(i:integer):string; begin Result:=IntToStr(i); end;
     
    function BytesPerPixel(APixelFormat: TPixelFormat): integer;
    begin
      Result := -1;
      case APixelFormat of
        pf8bit : result := 1;
        pf16bit: result := 2;
        pf24bit: result := 3;
        pf32bit: result := 4;
      end;
    end;
     
     
    //////////       les boutons     ///////////////
     
    procedure TForm1.btnTBitmapClick(Sender: TObject);
    var
      aBmp: TBitmap;
      procedure bmpComputeArray;
      var
        h, w: integer;
        gray: integer;
        Pixels: pRGBQuad;
     
        FUNCTION RGBAtoBGRA(CONST red, green, blue, reserved: BYTE): TRGBQuad;
        BEGIN
          WITH RESULT DO
          BEGIN
            rgbRed   := red;
            rgbGreen := green;
            rgbBlue  := blue;
            rgbReserved := reserved;
          END
        END {RGBQuad};
     
      begin
        aBmp := TBitmap.Create;
        with aBmp do begin
          PixelFormat := pf32bit;
          Width  := aWidth;
          Height := HSIZE;
          BeginUpdate();
          for h := 0 to HSIZE-1 do
          begin
            Pixels := pRGBQuad(RawImage.GetLineStart(h));
     
            if h = 0 then        // ligne du haut
              for w := 0 to aWidth-1 do
                Pixels[w] := RGBAtoBGRA(0,0,255,255)
            else
            if h = HSIZE-1 then  // ligne du bas
              for w := 0 to aWidth-1 do
                Pixels[w] := RGBAtoBGRA(0,255,255,255)
            else                 // entre les deux
              for w := 0 to aWidth-1 do begin
                gray := round((h+w) * ratio);   // le dégradé gris
                if gray > 255 then gray := round(gray * ratio);
                Pixels[w] := RGBAtoBGRA(gray, gray, gray, trkTranspar.Position);
              end;
          end;
          EndUpdate();
          Width := WSIZE; // traits verticaux si décommenté donc TBitmap inutilisable
        end;
      end;
    begin
      bmpComputeArray;
      imgTBitmap.Picture.Bitmap.Assign(aBmp);
      btnTBitmap.Caption := its(BytesPerPixel(imgTBitmap.Picture.Bitmap.PixelFormat)*8);
      aBmp.Free;
    end;
     
    procedure TForm1.btnTLazIntfImageClick(Sender: TObject);
    var
      aBitmap: TBitmap;
      IntfImage: TLazIntfImage;
      procedure lazComputeArray;
      var
        h, w: integer;
        gray: integer;
        row : pRGBQuad;
      begin
        with IntfImage do begin
          BeginUpdate;
          for h := 0 to HSIZE-1 do begin
            row := GetDataLineStart(h);
            for w := 0 to aWidth-1 do begin
              if h = 0 then
                begin       // ligne du haut
                  row[w].rgbRed      := 0; // qui est en fait le bleu
                  row[w].rgbGreen    := 0;
                  row[w].rgbBlue     := 255; // qui est en fait le rouge
                  row[w].rgbReserved := 255;
                end
              else
              if h = HSIZE-1 then
                begin       // ligne du bas
                  row[w].rgbRed      := 0;
                  row[w].rgbGreen    := 255;
                  row[w].rgbBlue     := 255;
                  row[w].rgbReserved := 255;
                end
              else
                begin       // entre les deux
                  gray := round((h+w) * ratio);   // le dégradé gris
                  if gray > 255 then gray := round(gray * ratio);
                  row[w].rgbRed      := gray;
                  row[w].rgbGreen    := gray;
                  row[w].rgbBlue     := gray;
                  row[w].rgbReserved := trkTranspar.Position;
                end;
            end; // for w
          end; // for h
          EndUpdate;
        end;
      end;
    begin
      aBitmap := TBitmap.Create;
      with aBitmap do begin                // 1
        PixelFormat := pf32bit;
        Width  := aWidth;
        Height := HSIZE;
      end;
     
      IntfImage := aBitmap.CreateIntfImage;// 3
      lazComputeArray; // 2 -- tuto dit "work on bitmap", ici c'est "work on tlazintfimage"
      aBitmap.Clear;                       // +/- similaire au 4
      aBitmap.LoadFromIntfImage(IntfImage);// 5
      IntfImage.Free;
      aBitmap.Width := WSIZE;              // 6
      //aBitmap.SaveToFile('/chemin/aBitmap.bmp'); // 7 -- taille ok, pf32
     
      imgTLazIntfImage.Picture.Bitmap := aBitmap;  // 8
      aBitmap.Free;
      btnTLazIntfImage.Caption := its(BytesPerPixel(imgTLazIntfImage.Picture.Bitmap.PixelFormat)*8);
     
    { http://forum.lazarus.freepascal.org/index.php?topic=19704.0
    I've found an ADMITTEDLY DIRTY workaround:
    1) Create your Bitmap as needed, ensuring that its width IS A MULTIPLE OF 8 PIXELS.
    2) Work on your bitmap as needed.
    3) Obtain a TLazIntfImage from the bitmap.
    4) Create another graphical object (I tried only with TPortableNetworkGraphic)
    5) Load from the TLazInfImage obtained in step 3.
    6) Resize the another graphical object as needed (for instance, reduce the width so that it's no longer a multiple of 8 ).
    7) Save this graphic.
    8) At this point, the image saved will retain its transparency, even though its width is no longer a multiple of 8 pixels.
     
    I tried this workaround in Ubuntu, and it certainly does the trick. Yes, it's dirty, but at least I got my problem solved...}
    end;
     
    procedure TForm1.btnTbzBMPViewerClick(Sender: TObject);
    var
      bz: TBMPViewer;
      procedure bzComputeArray;
      var
        h, w: integer;
        gray: integer;
        pixelline: pColor32;
      begin
        pnlTbzBMPViewer.Width := aWidth;
        pnlTbzBMPViewer.Height:= HSIZE;
        bz := TBMPViewer.Create(self);
        with bz do begin
          //Parent := Self;
          Parent := pnlTbzBMPViewer; // impossible de mettre le TImage, il FAUT un WinControl
          Align  := alClient;
          AutoStretchMode := smManual;
          Center := True; // le dessin de l'image est centré dans le viewer
          FastBitmap.Create(aWidth, HSIZE);
    //      Bitmap.PixelFormat := pf32bit; //logiquement ne devrait pas être utile
          for h := 0 to HSIZE-1 do begin
            pixelline := FastBitmap.GetScanLine(h);
            for w := 0 to aWidth-1 do begin
              if h = 0 then        // ligne du haut
                begin
                  pixelline[w].Red   := 255;
                  pixelline[w].Green := 0;
                  pixelline[w].Blue  := 0;
                  pixelline[w].Alpha := 255;
                end
              else
              if h = HSIZE-1 then  // ligne du bas
                begin
                  pixelline[w].Red   := 255;
                  pixelline[w].Green := 255;
                  pixelline[w].Blue  := 0;
                  pixelline[w].Alpha := 255;
                end
              else                 // entre les deux
                begin
                  gray := round((h+w) * ratio);   // le dégradé gris
                  if gray > 255 then gray := round(gray * ratio);
                  pixelline[w].Red   := gray;
                  pixelline[w].Green := gray;
                  pixelline[w].Blue  := gray;
                  pixelline[w].Alpha := trkTranspar.Position;
                end;
            end; // for w
          end; // for h
          pnlTbzBMPViewer.Width := WSIZE;
          Width := WSIZE; // pas redimensionnée
    //      FastBitmap.Width:=WSIZE;// détruit l'image...
        end; // with bz
      end;
    begin
      bzComputeArray;
      //imgTbzBMPViewer.Picture.Bitmap.PixelFormat:=pf32bit; // si présent, image vide -- si commenté, pf24
      bz.GetLoader.FastBitmap.Draw(imgTbzBMPViewer.Canvas, 0,0);
      //bz.GetLoader.FastBitmap.Draw(pnlTbzBMPViewer.Canvas, 0,0); // img flashe et disparaît
      //bz.FastBitmap.GetBitmap.SaveToFile('/chemin/bz.bmp'); // 32 bit mais pas redimensionnée
      btnTbzBMPViewer.Caption := its(BytesPerPixel(imgTbzBMPViewer.Picture.Bitmap.PixelFormat)*8);
      bz.Free;
    end;
     
    procedure TForm1.btnTbzFastBitmapClick(Sender: TObject);
    var
      bzFB: TFastBitmap;
      bmp: TBitmap;
      procedure bzComputeFBArray;
      var
        h, w: integer;
        gray: integer;
        //pixelline: pColor32;
        pixelline: pRGBQuad;
      begin
        bmp := TBitmap.Create;
        with bmp do begin
          PixelFormat := pf32bit;
          Width := aWidth;
          Height:= HSize;
          for h := 0 to HSIZE-1 do begin
            pixelline := pRGBQuad(RawImage.GetLineStart(h));
            for w := 0 to aWidth-1 do begin
              if h = 0 then        // ligne du haut
                begin
                  pixelline[w].rgbRed   := 0; // blue
                  pixelline[w].rgbGreen := 0;
                  pixelline[w].rgbBlue  := 255;// red
                  pixelline[w].rgbReserved := 255;
                end
              else
              if h = HSIZE-1 then  // ligne du bas
                begin
                  pixelline[w].rgbRed   := 0;
                  pixelline[w].rgbGreen := 255;
                  pixelline[w].rgbBlue  := 255;
                  pixelline[w].rgbReserved := 255;
                end
              else                 // entre les deux
                begin
                  gray := round((h+w) * ratio);   // le dégradé gris
                  if gray > 255 then gray := round(gray * ratio);
                  pixelline[w].rgbRed   := gray;
                  pixelline[w].rgbGreen := gray;
                  pixelline[w].rgbBlue  := gray;
                  pixelline[w].rgbReserved := trkTranspar.Position;
                end;
            end; // for w
          end; // for h
          Width := WSIZE;
        end; // with bmp
      end;
    begin
      bzFB := TFastBitmap.Create(aWidth, HSIZE);
      bzComputeFBArray;
      //bzFB.ImportFromRawImage(bmp.RawImage);
      //bmp.SaveToFile('/chemin/testbmp1.bmp');// ce fichier EST pf32 et à la bonne taille
      // ces 2 lignes dessus ou les 2 dessous fonctionnent pareil
      bzFB.ImportFromBitmap(bmp);
      //bmp.SaveToFile('/chemin/testbmp2.bmp');// ce fichier EST pf32 et à la bonne taille
     
      imgTbzFastBitmap.Width := WSIZE;
      bzFB.Draw(imgTbzFastBitmap.Canvas, rect(0,0,imgTbzFastBitmap.Width,imgTbzFastBitmap.Height));
      btnTbzFastBitmap.Caption := its(BytesPerPixel(imgTbzFastBitmap.Picture.Bitmap.PixelFormat)*8);// 24 ! aïe !
    end;
     
    procedure TForm1.btnTMitchellClick(Sender: TObject);
    var
      ci: TCompactImage;
      lclci: TLCLCompactImage;
      procedure ciComputeArray;
      var
        h, w: integer;
        gray: integer;
      begin  // pas concerné par le problème de width divisible par 8 ou pas
        ci := TCompactImage.Create(WSIZE, HSIZE);
        with ci do
          for h := 0 to HSIZE-1 do
            for w := 0 to (WSIZE)-1 do begin
              if h = 0 then       begin // ligne du haut
                  ci.Data[(h * ci.Width) + w].Red   := 255;
                  ci.Data[(h * ci.Width) + w].Green := 0;
                  ci.Data[(h * ci.Width) + w].Blue  := 0;
                  ci.Data[(h * ci.Width) + w].Alpha := 255;
                end
              else
              if h = HSIZE-1 then begin // ligne du bas
                  ci.Data[(h * ci.Width) + w].Red   := 255;
                  ci.Data[(h * ci.Width) + w].Green := 255;
                  ci.Data[(h * ci.Width) + w].Blue  := 0;
                  ci.Data[(h * ci.Width) + w].Alpha := 255;
                end
              else                begin // entre les deux
                  gray := round((h+w) * ratio);   // le dégradé gris
                  if gray > 255 then gray := round(gray * ratio);
                  ci.Data[(h * ci.Width) + w].Red   := gray;
                  ci.Data[(h * ci.Width) + w].Green := gray;
                  ci.Data[(h * ci.Width) + w].Blue  := gray;
                  ci.Data[(h * ci.Width) + w].Alpha := trkTranspar.Position;
                end;
            end; // for w
        lclci := TLCLCompactImage.Create(ci);
      end;
    begin
      ciComputeArray;
      imgTMitchell.Picture.Bitmap.Assign(lclci.ImageBitmap);
      btnTMitchell.Caption := its(BytesPerPixel(imgTMitchell.Picture.Bitmap.PixelFormat)*8);
      lclci.Free;
      ci.Free;
    end;
     
     
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      WSIZE := 121;
      // 2 lignes pour calcul d'une width divisible par 8
      aWidth:= WSIZE;
      while ((aWidth mod 8) <> 0) do inc(aWidth);
      Caption := its(awidth); // affiche bien 128 pour WSIZE à 121
     
      HSIZE := 69;
      ratio := 256 / (HSIZE + WSIZE); // une valeur au pif pour gérer le dégradé
    end;
     
    end.
    Pour bien l'apprécier, je vous suggère de partir de tout en bas où se trouve FormCreate et le truc pour avoir une Width divisible pas 8 si d'aventure elle ne l'était pas au départ.

    Code que j'ai peut-être mal mis en œuvre en ce qui concerne Jérôme puisqu'on note qu'on perd le PixelFormat à 32 bits pour l'affichage (et du coup le curseur pour la transparence est inefficace).
    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

  9. #149
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    Septembre 2015
    Messages
    1 899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2015
    Messages : 1 899
    Points : 4 346
    Points
    4 346
    Billets dans le blog
    2
    Par défaut
    Salut

    Concernant ton code et ma partie :

    1) Avec TBmpViewer :

    Ce type de procedure est parfaitement inutile. Utiliser un TFastBitmap comme tu l'as fait avec Mitchell est suffisant.
    Le TBMPViewer est un control visuel comparable au TImage. Pour accéder au bitmap tu fais TBmpViewer.FastBitmap qui équivaut à TImage.Picture.BitmapDe plus le TFastBitmap n'est pas sensible à ce problème de dimension.

    Même si dans procedure TForm1.btnTbzFastBitmapClick(Sender: TObject); tu remplaces les aWidth par WSize cela fonctionne

    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    procedure TForm1.btnTbzFastBitmapClick(Sender: TObject);
    var
      bzFB: TFastBitmap;
      bmp: TBitmap;
     
      procedure bzComputeFBArray;
      var
        h, w: integer;
        gray: integer;
        //pixelline: pColor32;
        pixelline: pRGBQuad;
      begin
        bmp := TBitmap.Create;
        with bmp do
        begin
          PixelFormat := pf32bit;
          Width := WSIZE;//aWidth;
          Height:= HSize;
          for h := 0 to HSIZE-1 do begin
            pixelline := pRGBQuad(RawImage.GetLineStart(h));
            for w := 0 to WSIZE-1 do begin
              if h = 0 then        // ligne du haut
                begin
                  pixelline[w].rgbRed   := 0; // blue
                  pixelline[w].rgbGreen := 0;
                  pixelline[w].rgbBlue  := 255;// red
                  pixelline[w].rgbReserved := 255;
                end
              else
              if h = HSIZE-1 then  // ligne du bas
                begin
                  pixelline[w].rgbRed   := 0;
                  pixelline[w].rgbGreen := 255;
                  pixelline[w].rgbBlue  := 255;
                  pixelline[w].rgbReserved := 255;
                end
              else                 // entre les deux
                begin
                  gray := round((h+w) * ratio);   // le dégradé gris
                  if gray > 255 then gray := round(gray * ratio);
                  pixelline[w].rgbRed   := gray;
                  pixelline[w].rgbGreen := gray;
                  pixelline[w].rgbBlue  := gray;
                  pixelline[w].rgbReserved := trkTranspar.Position;
                end;
            end; // for w
          end; // for h
          //Width := WSIZE;
        end; // with bmp
      end;
    begin
      bzFB := TFastBitmap.Create(WSIZE, HSIZE);
      bzComputeFBArray;
      //bzFB.ImportFromRawImage(bmp.RawImage);
      //bmp.SaveToFile('/chemin/testbmp1.bmp');// ce fichier EST pf32 et à la bonne taille
      // ces 2 lignes dessus ou les 2 dessous fonctionnent pareil
      bzFB.ImportFromBitmap(bmp);
      //bmp.SaveToFile('/chemin/testbmp2.bmp');// ce fichier EST pf32 et à la bonne taille
     
      imgTbzFastBitmap.Width := WSIZE;
      //bzFB.Draw(imgTbzFastBitmap.Canvas, rect(0,0,imgTbzFastBitmap.Width,imgTbzFastBitmap.Height)); ---> /!\  NE CHANGE PAS LE PIXELFORMAT DE LA CIBLE
      imgTbzFastBitmap.Picture.Bitmap.Assign(bzFB.GetBitmap);
      btnTbzFastBitmap.Caption := its(BytesPerPixel(imgTbzFastBitmap.Picture.Bitmap.PixelFormat)*8);// 32 ! YES ! YES ! YES !
    end;
    2) Avec TFastBitmap : Pourquoi passes tu par un TBitmap intermédiaire ? le dégradé peut-être généré directement comme tu l'as fait avec Mitchell.

    Enfin pour les 2 tu utilises la fonction Draw ce qui est normal que tu sois toujours en 24bits (format par defaut du TImage). Pour Mitchell tu n'utilises pas Draw mais imgTMitchell.Picture.Bitmap.Assign(lclci.ImageBitmap); avec le TFastBitmap tu doit faire de même imgTbzFastBitmap.Picture.Bitmap.Assign(bzFB.GetBitmap); et là tu auras la transparence.
    Attention ! La fonction Draw n'a pas pour but de changer le pixelformat de la cible (c'est la même avec TBitmap.Draw/StretchDraw)

    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    procedure TForm1.btnTbzFastBitmapClick(Sender: TObject);
    var
      bzFB: TFastBitmap;
     
      procedure bzComputeFBArray;
      var
        h, w: integer;
        gray: integer;
        pixelline: pColor32;
      begin
        with bzFB do
        begin      
          for h := 0 to HSIZE-1 do
          begin
            pixelline := GetScanLine(h);
            for w := 0 to WSIZE-1 do
            begin
              if h = 0 then        // ligne du haut
                begin
                  pixelline[w].Red   := 0; // blue
                  pixelline[w].Green := 0;
                  pixelline[w].Blue  := 255;// red
                  pixelline[w].Alpha := 255;
                end
              else
              if h = HSIZE-1 then  // ligne du bas
                begin
                  pixelline[w].Red   := 0;
                  pixelline[w].Green := 255;
                  pixelline[w].Blue  := 255;
                  pixelline[w].Alpha := 255;
                end
              else                 // entre les deux
                begin
                  gray := round((h+w) * ratio);   // le dégradé gris
                  if gray > 255 then gray := round(gray * ratio);
                  pixelline[w].Red   := gray;
                  pixelline[w].Green := gray;
                  pixelline[w].Blue  := gray;
                  pixelline[w].Alpha := trkTranspar.Position;
                end;
            end; // for w
          end; // for h
        end; // with bmp
      end;
    begin
      bzFB := TFastBitmap.Create(WSIZE, HSIZE);
      bzComputeFBArray;
      imgTbzFastBitmap.Width := WSIZE;
      imgTbzFastBitmap.Picture.Bitmap.Assign(bzFB.GetBitmap);
      btnTbzFastBitmap.Caption := its(BytesPerPixel(imgTbzFastBitmap.Picture.Bitmap.PixelFormat)*8);// 32 ! YES ! YES ! YES !
      FreeAndNil(BzFB);
    end;
    voila voilou

    Notes que sous Win ton code pour le TBitmap fonctionne, et c'est la que tu devrais faire comme pour le TLazIntfImg. D'ailleurs dans le lien de la discussion que tu as donné ont peux lire que ce problème est spécifique à Linux.

    A+
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Yop !

    Citation Envoyé par BeanzMaster Voir le message
    Salut

    Concernant ton code et ma partie :
    Merci pour tes précisions, j'étudierai tout ça demain matin, là ça va comme ça pour aujourd'hui.

    Juste un petit cadeau, et la preuve par a + b qu'on peut avoir des bitmaps avec transparence, puisque je joue par code à remplir un TBitmap d'un gris qui prend en compte la valeur de la position du curseur du trackbar (qu'on retrouve dans le nom des fichiers : 42, 127, et 231, et àmha c'est plus un degré d'opacité que de transparence : 231 c'est presque 255, qui est totalement opaque)

    Nom : 3_bmp+transp.png
Affichages : 171
Taille : 60,1 Ko

    Et d'ailleurs, pour bien voir le rendu il a fallu que j'insère un calque blanc sous le calque des datas, dans chaque fichier.
    Ce qui est amusant, c'est que j'arrive à gérer cette non-divisibilité par 8 en utilisant la combine de la variable intermédiaire divisible par 8 puis resizing à la bonne valeur horrible, ça fonctionne et j'enregistre un fichier correct (largeur ok, pf32), mais pas moyen de le voir bien dans un TImage, j'ai droit aux traits...

    Et pour gérer ça correctement, un impératif : dans la section Begin/EndUpdate ! Sinon pâté...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
        with aBmp do begin
          //setup objet
          BeginUpdate();
          //setup datas : gris et autres couleurs
          Width := WSIZE; restaure la largeur demandée
          EndUpdate();
          SaveToFile('/chemin/aBmp.bmp'); // parfaitement correct
        end;
    Citation Envoyé par BeanzMaster Voir le message
    Note que sous Win ton code pour le TBitmap fonctionne, et c'est là que tu devrais faire comme pour le TLazIntfImg. D'ailleurs dans le lien de la discussion que tu as donné on peut lire que ce problème est spécifique à Linux.
    Yes yes, Linux, le parent pauvre du graphisme,
    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

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Bonjour,

    je reviens donc comme promis sur ta réponse, en commençant par le TBMPViewer, avec un truc que je ne comprends pas du tout : tu nous parles d'un composant pouvant faire la même chose que le TImage, mais dans ton exemple tu utilises le TImage. Quelque chose m'échappe, là.
    Il est vrai que j'ai utilisé des noms de composants peut-être un peu ambigus, mais c'était pour mieux m'y retrouver, d'ailleurs j'ai bien mis des préfixes, donc imgTbzFastBitmap n'est pas un TBMPViewer, c'est bien un TImage.


    Ah, j'ai compris, tu t'es fait un nœud, ça m'a pris du temps pour capter : ton 1er bloc de code dans le post ne correspond pas au 1er point, le TBMPViewer !, mais au second, le bzFastBitmap,

    Bon, tout ça se résume à ça, concernant le bzFastBitmap :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      //bzFB.Draw(imgTbzFastBitmap.Canvas, rect(0,0,imgTbzFastBitmap.Width,imgTbzFastBitmap.Height));
      // suite post bz, dessus commenté dessous ajouté MAIS n'utilise pas son BMPViewer
      imgTbzFastBitmap.Picture.Bitmap.Assign(bzFB.GetBitmap);
    et du coup, je repose ma question : pourquoi utilises-tu un TImage alors que tu nous fabriques un viewer plus performant ?

    Tu devrais nous faire un tuto là-dessus.
    (tiens, je reviens deux secondes sur ces histoires de mots, d'une importance capitale [pour moi].
    Dans la ligne précédente, on lit ...Assign(bzFB.GetBitmap); et si tu savais à quel point ce "GetBitmap" me triture les méninges alors qu'un simple ...Assign(bzFB.Bitmap); aurait été d'une simplicité et d'une limpidité redoutables : le "Get" n'apporte rien à l'affaire -- au contraire, en ce qui me concerne.
    )

    Par exemple, j'avais noté dans un post
    1er cas simple
    suivi par du code pour générer une image, mais tu ne nous y montres pas comment l'afficher. Pour un "viewer", c'est un peu gros, non ?


    De mon côté, j'ai concocté ça, minimaliste, avec un TPanel (name = pnl4viewer, BevelOuter à bvNone, Caption vide [pas pour la démo gif]), mais ça ne doit pas être au top, j'ai des soucis…
    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
        procedure PaintBzViewer(Sender: TObject);
      private
        { private declarations }
        BmpViewer: TBMPViewer;
      public
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      BmpViewer := TBMPViewer.Create(pnl4viewer);
      with BmpViewer do begin
        //Align  := alClient;
        AutoStretchMode := smManual;
        //Center := True; // ne fonctionne pas, ou alors c'est contradictoire avec le Align ?
        // Align commenté ça ne change rien : l'image générée vient se coller en haut à gauche,
        // sans doute à cause du Draw(pnl4viewer.Canvas, 0,0) -- mais comment dessiner autrement ?
        OnPaint := @PaintBzViewer; // obligatoire sinon l'image recouverte ne réapparaît pas.
      end;
    end;
     
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      FreeAndNil(BmpViewer);
    end;
     
    procedure TForm1.PaintBzViewer(Sender: TObject);
    begin
      //BMPViewer.Invalidate; // sans action
      // et dessous, a un comportement curieux : le simple fait
      // de déplacer la souris en dehors de la fiche génère une action ici.
      // voir le gif : à force de dessiner, la Caption du TPanel disparaît
      BmpViewer.GetLoader.FastBitmap.Draw(pnl4viewer.Canvas, 0,0); 
    end;
    Nom : capt.gif
Affichages : 136
Taille : 7,8 Ko

    usage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      with BmpViewer.GetLoader.FastBitmap do begin
        ImportFromBitmap(aBmp); 
        Draw(pnl4viewer.Canvas, 0,0);
      end;
    J'ai aussi essayé de remplacer Draw(pnl4viewer.Canvas, 0,0); par Draw(pnl4viewer.Canvas, pnl4viewer.Canvas.ClipRect);, ça tombe sous le sens, mais j'ai des résultats aléatoires (indépendamment des histoires de tailles, bien sûr)
    Nom : canvas_cliprect.png
Affichages : 152
Taille : 4,4 Ko
    Le label lblPFbz se trouve quelques pixels à droite du pnl4viewer, c'est un repère pour situer le côté droit de ce panel.

    Bref, tu devrais nous faire un bon tuto sur "comment afficher avec le composant BMPViewer".
    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. #152
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 719
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Ah, j'ai oublié un point important : le TBitmap n'a pas besoin de l'astuce de la largeur divisible par 8 !

    La preuve ci-dessous où l'on voit en bas en arrière-plan dans un viewer Linux le .bmp généré par mon prog, sans largeur adaptée.

    Nom : aBmp_ds_viewer+timage.png
Affichages : 376
Taille : 6,6 Ko

    En haut à droite en incrustation, le TImage à qui l'on a passé le TBitmap,

    C'est vraiment dommage...
    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

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Bonjour,

    je dois des excuses à la communauté : j'ai encore fait et publié une boulette, ,
    Cette histoire de modifier la valeur de la largeur pour qu'elle soit divisible par 8 pour pouvoir travailler puis la ramener à la valeur prévue au départ, tant qu'on travaille sur des aplats de couleurs ou des dégradés, ça ne se voit pas, mais dès qu'on manipule des vrais sujets on se rend très vite compte qu'on rabote de la data, puisqu'on ne fait pas de StretchDraw mais qu'on tranche dans le vif.
    Et ça, ce n'est pas bon du tout pour l'intégrité des images, alors dégage !
    Car l'écart peut aller jusqu'à 7 pixels, ce qui pour moi est énorme.

    J'ai donc repris tout ça du début, force est de constater qu'il y a bien un problème dans le dessin des bitmaps, que ça soit vers un TImage ou une TPaintBox.

    Draw appelle StretchDraw qui appelle SrcGraphic.Draw qui appelle TRasterImage.Draw qui appelle StretchMaskBlt planqué dans lclintf.inc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    function StretchMaskBlt(DestDC: HDC; X, Y, Width, Height: Integer;
      SrcDC: HDC; XSrc, YSrc, SrcWidth, SrcHeight: Integer;
      Mask: HBITMAP; XMask, YMask: Integer; Rop: DWORD): Boolean;
    begin
      Result := WidgetSet.StretchMaskBlt(DestDC, X, Y, Width, Height,
                   SrcDC, XSrc, YSrc, SrcWidth, SrcHeight, Mask, XMask, YMask, Rop);
    end;
    et ce WidgetSet.StretchMaskBlt dans /usr/share/lazarus/version/lcl/interfaces/gtk2/gtk2winapi.inc appelle StretchCopyArea dans gtk2widgetset.inc, de 3650 à 4260 soit 610 lignes, où l'on trouve, lignes 3718 et 3757 (sous-fonction ScaleAndROP) :
    Depth:=gdk_visual_get_system^.Depth;, et un ShowMessage avec ça recopié dans l'ihm montre 24...
    alors qu'un gdk_visual_get_best_depth donne 32.

    Mais une tentative de remplacement de l'un par l'autre se solde par un résultat toujours rayé avec les widths exotiques.
    Décourageant, et rageant tout court !

    Il reste donc comme choix le BMPViewer de Jérôme et le couple de compos de Mitchell, le premier s'affichant dans un TPanel par ex. (ou un TPaintBox, ça fonctionne aussi) et le second dans un TImage (pas essayé d'autre cible).

    Le compo de Jérôme m'a surpris par un comportement différent entre deux projets similaires : l'un a absolument besoin de la bidouille connue pour dessiner sur un TPanel :
    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
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      rempli := False; // déclaré en private
      pnlTbzBMPViewer.OnPaint := @PanelOnPaint;
    end;
     
    procedure TForm1.PanelOnPaint(Sender: TObject);
    begin
      // si le bitmap n'est pas créé ou s'il est vide, on sort.
    //  if (not assigned(bz)) or bz.Bitmap.Empty then exit;
    // source : https://www.developpez.net/forums/d856121/environnements-developpement/delphi/debutant/paintbox-resolution/#post4886685
      if not rempli then exit; // seconde bidouille perso car TBitmap.Empty n'est pas dispo chez Jérôme
     
      // affiche le bitmap dans le panel
      bz.GetLoader.FastBitmap.Draw(pnlTbzBMPViewer.Canvas, 0,0);
    end;
    quand l'autre projet n'en a pas du tout besoin...
    Ce projet est ultra minimaliste (2 panels dont l'un contient un TImage et c'est tout -- 100 lignes du début à la fin du .pas), l'autre est plein de groupbox avec boutons, tpanels, timages, tpaintbox, 1 trackbar, toutes ces choses bien indépendantes mais la fiche est chargée : pagaille dans les tréfonds du code ?

    Passablement désagréable et difficile à cerner/appréhender...

    EDIT -- besoin d'une petite précision : que doit-on utiliser vraiment, car deux fois deux lignes au comportement identique, ça fait 4 possibilités,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
      with BmpViewer.GetLoader.FastBitmap do
      // 2 lignes au comportement identique
      //with BmpViewer.FastBitmap do
     
        ImportFromBitmap(aBmp);
        // 2 lignes au comportement identique
        //ImportFromRawImage(aBmp.RawImage);
    Merci,
    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. #154
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    Septembre 2015
    Messages
    1 899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2015
    Messages : 1 899
    Points : 4 346
    Points
    4 346
    Billets dans le blog
    2
    Par défaut
    Salut
    Citation Envoyé par Jipété Voir le message
    Bonjour,

    ....
    Ah, j'ai compris, tu t'es fait un nœud, ça m'a pris du temps pour capter : ton 1er bloc de code dans le post ne correspond pas au 1er point, le TBMPViewer !, mais au second, le bzFastBitmap,
    J'aurais du faire un retour chariot avant "TFastBitmap n'est pas sensible à ce problème de dimension."

    Citation Envoyé par Jipété Voir le message
    Bon, tout ça se résume à ça, concernant le bzFastBitmap :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      //bzFB.Draw(imgTbzFastBitmap.Canvas, rect(0,0,imgTbzFastBitmap.Width,imgTbzFastBitmap.Height));
      // suite post bz, dessus commenté dessous ajouté MAIS n'utilise pas son BMPViewer
      imgTbzFastBitmap.Picture.Bitmap.Assign(bzFB.GetBitmap);
    et du coup, je repose ma question : pourquoi utilises-tu un TImage alors que tu nous fabriques un viewer plus performant ?
    Ben c'est pas moi c'est ti c'est ton code

    Citation Envoyé par Jipété Voir le message
    Tu devrais nous faire un tuto là-dessus.
    (tiens, je reviens deux secondes sur ces histoires de mots, d'une importance capitale [pour moi].
    Dans la ligne précédente, on lit ...Assign(bzFB.GetBitmap); et si tu savais à quel point ce "GetBitmap" me triture les méninges alors qu'un simple ...Assign(bzFB.Bitmap); aurait été d'une simplicité et d'une limpidité redoutables : le "Get" n'apporte rien à l'affaire -- au contraire, en ce qui me concerne.
    )
    GetBitmap est une fonction, mais c'est facile de la passé en "Private" ou "Protected" et d'ajouté une propriété "public" property Bitmap : Graphics.TBitmap read GetBitmap;
    Citation Envoyé par Jipété Voir le message
    Par exemple, j'avais noté dans un post
    suivi par du code pour générer une image, mais tu ne nous y montres pas comment l'afficher. Pour un "viewer", c'est un peu gros, non ?
    Non, c'est comme utiliser un TBitmap sans utiliser un TImage. Je reviendrais plus bas sur le TBMPViewer

    Citation Envoyé par Jipété Voir le message
    Il reste donc comme choix le BMPViewer de Jérôme et le couple de compos de Mitchell, le premier s'affichant dans un TPanel par ex. (ou un TPaintBox, ça fonctionne aussi) et le second dans un TImage (pas essayé d'autre cible).

    Le compo de Jérôme m'a surpris par un comportement différent entre deux projets similaires : l'un a absolument besoin de la bidouille connue pour dessiner sur un TPanel :
    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
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      rempli := False; // déclaré en private
      pnlTbzBMPViewer.OnPaint := @PanelOnPaint;
    end;
     
    procedure TForm1.PanelOnPaint(Sender: TObject);
    begin
      // si le bitmap n'est pas créé ou s'il est vide, on sort.
    //  if (not assigned(bz)) or bz.Bitmap.Empty then exit;
    // source : https://www.developpez.net/forums/d856121/environnements-developpement/delphi/debutant/paintbox-resolution/#post4886685
      if not rempli then exit; // seconde bidouille perso car TBitmap.Empty n'est pas dispo chez Jérôme
     
      // affiche le bitmap dans le panel
      bz.GetLoader.FastBitmap.Draw(pnlTbzBMPViewer.Canvas, 0,0);
    end;
    Tout dépend du contexte et quel sont les paramètres de TBitmap/TImage vs TFastBitmap

    Citation Envoyé par Jipété Voir le message
    EDIT -- besoin d'une petite précision : que doit-on utiliser vraiment, car deux fois deux lignes au comportement identique, ça fait 4 possibilités,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
      with BmpViewer.GetLoader.FastBitmap do
      // 2 lignes au comportement identique
      //with BmpViewer.FastBitmap do
     
        ImportFromBitmap(aBmp);
        // 2 lignes au comportement identique
        //ImportFromRawImage(aBmp.RawImage);
    Merci,

    Je vais tenter de t'expliquer plus clairement le TBMPViewer et répondre à tes petites questions.

    Je comprend ce que tu souhaites faire et je comprend que tu te fasses des noeuds. le TBMPViewer c'est comme le TGIFViewer se sont tous les deux des composants visuels qui se charge uniquement d'afficher ces formats (BMP et GIF en l'occurence). Le fait de vouloir assimilé le TBMPViewer à un TImage est erroné (il est vrai que tu peux manipuler les données en passant par des chemins détourné). A l'heure actuel vouloir utiliser le TBMPViewer comme un TImage n'est pas la meilleur solution.

    Dans mon projet, j'ai un composant nommé TBZImageViewer et qui se rapproche beaucoup plus du TImage. En effet comme le TImage j'ai une propriété "Picture" qui me permet de charger plusieurs formats de fichier image (XPM, BMP, PCX, PixMap, TGA, JPEG, GIF, PNG,....).

    Le TBZBitmap (aka TFastBitmap), quant à lui dispose de plus de possibilités pour la retouche et l'édition des données et dispose d'un "Canvas" (en cours de chantier) pour dessiner et/ou écrire du texte.
    Pas ce week-end, mais le prochain, je devrais pouvoir mettre en ligne une première version, si je dispose d'assez de temps dans la semaine pour fignoler ce que je veux.

    Concernant le TBMPViewer tel qu'il est aujourd'hui
    BmpViewer.GetLoader.FastBitmap getLoader est une fonction pour récupérer la Classe TBMPLoader utilisée pour le chargement des fichier BMP.

    BmpViewer.FastBitmap ici FastBitmap est un propriété permettant d'accéder directement au FastBitmap du Loader c'est équivalant à BmpViewer.GetLoader.FastBitmapPour ImportFromBitmap(aBmp); et ImportFromRawImage(aBmp.RawImage); ces fonctions on un comportement équivalent uniquement si le RawImage/TBitmap sont des 32bits.
    ImportFromRawImage(aBmp.RawImage) fonctionne uniquement avec des données de même BPP et si les dimensions de l'image sont identiques. Cette fonction par contre échange les valeurs Rouge et Bleu des couleurs en fonctions de l'os et si les données sont en RGB ou BGR. Jettes un oeil au code de ImportFromBitmap(aBmp);. Ici je convertit les données en 32bits (si Bitmap 24bpp ou plus petit) et passe le RawImage du bitmap convertit à ImportFromRawImage(aBmp.RawImage);.

    C'est un peu minimaliste concernant ImportFromRawImage(aBmp.RawImage); et cette fonction mériterait d'être plus aboutie dans l'absolue. J'aurais du placer ImportFromRawImage; dans "Protected" cela aurait été plus judicieux.

    Si tu modifie Le FastBitmap du TBmpViewer pour voir les changements tu dois forcer le rafraichissement par "TBMPViewer.Invalidate" ou TBMPViewer.RePaint"

    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    procedure TForm1.btnTbzBMPViewerClick(Sender: TObject);
    var
      bz: TBMPViewer;
     
      procedure bzComputeArray;
      var
        h, w: integer;
        gray: integer;
        pixelline: pColor32;
      begin
        pnlTbzBMPViewer.Width := WSIZE;
        pnlTbzBMPViewer.Height:= HSIZE;
        bz := TBMPViewer.Create(self);
     
        with bz do
        begin
          //Parent := Self;
          Parent := pnlTbzBMPViewer; // impossible de mettre le TImage, il FAUT un WinControl
          Align  := alClient;
          AutoStretchMode := smManual;
          Center := True; // le dessin de l'image est centré dans le viewer
          FastBitmap.SetSize(WSIZE, HSIZE);
    //      Bitmap.PixelFormat := pf32bit; //logiquement ne devrait pas être utile
          for h := 0 to HSIZE-1 do
          begin
            pixelline := FastBitmap.GetScanLine(h);
            for w := 0 to WSIZE-1 do
            begin
              if h = 0 then        // ligne du haut
                begin
                  pixelline[w].Red   := 255;
                  pixelline[w].Green := 0;
                  pixelline[w].Blue  := 0;
                  pixelline[w].Alpha := 255;
                end
              else
              if h = HSIZE-1 then  // ligne du bas
                begin
                  pixelline[w].Red   := 255;
                  pixelline[w].Green := 255;
                  pixelline[w].Blue  := 0;
                  pixelline[w].Alpha := 255;
                end
              else                 // entre les deux
                begin
                  gray := round((h+w) * ratio);   // le dégradé gris
                  if gray > 255 then gray := round(gray * ratio);
                  pixelline[w].Red   := gray;
                  pixelline[w].Green := gray;
                  pixelline[w].Blue  := gray;
                  pixelline[w].Alpha := trkTranspar.Position;
                end;
            end; // for w
          end; // for h
        end; // with bz
      end;
     
    begin
      bzComputeArray;
      bz.Invalidate;
      //bz.Repaint;
      //imgTbzBMPViewer.Picture.Bitmap.PixelFormat:=pf32bit; // si présent, image vide -- si commenté, pf24
      //bz.FastBitmap.Draw(imgTbzBMPViewer.Canvas, 0,0);
      //bz.GetLoader.FastBitmap.Draw(pnlTbzBMPViewer.Canvas, 0,0); // img flashe et disparaît
      //bz.FastBitmap.GetBitmap.SaveToFile('/chemin/bz.bmp'); // 32 bit mais pas redimensionnée
      btnTbzBMPViewer.Caption := its(32);
     // bz.Free;
    end;
    Par contre tu ne verra pas la transparence car il faut modifié la "procedure paint". En effet le TBMPViewer étant prévue pour l'affichage des fichiers BMP uniquement. La prise en charge de la transparence (Alpha) lors de l'affichage est en fonction des informations et de l'encodage du fichier BMP. Pour controler l'affichage avec transparence avec le TBMPViewer il faut modifié la procedure Paint;Comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     UpdateBitmap; // mise à jour du TBitmap pour l'affichage
     FBitmap.Transparent := FTransparent;
     C.StretchDraw(R, FBitmap);
    Notes que dans mon projet pour l'affichage dans un "Canvas" j'utilises la méthode de Mitchell (donc les Apis) légèrement modifiée

    Faut déja que je retourne bosser

    A+
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Merci de ta réponse.

    On va prendre le problème à l'envers parce que je dois être particulièrement bouché ce soir, toujours est-il que je ne m'en sors pas en tentant de StretchDrawer un BMPViewer sur un autre.

    Quand on regarde les réponses sur ce forum, ça a l'air enfantin :
    Image2.Canvas.StretchDraw(Image2.ClientRect, Image1.Picture.Bitmap); mais avec moi les choses les plus simples prennent une éternité de temps...

    J'ai essayé ça BmpViewerDest.Canvas.StretchDraw(BmpViewerDest.ClientRect, BmpViewerOrig.Bitmap); et tout un tas de variantes sur ce thème, avec un résultat toujours identique : le TPanel censé afficher l'image reste désespérément vide

    Avec cette variante je ne suis pas loin, BmpViewerDest.Canvas.StretchDraw(BmpViewerDest.ClientRect, BmpViewerOrig.FastBitmap.GetBitmap); puisque l'image s'affiche un court instant puis est effacée.
    Je la vois dans un flash, et elle a l'air aux bonnes dimensions. On est tout près...

    Mais résultat strictement identique (le flicker) avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ////    BmpViewerDest.Invalidate;
    ////    pnl4Dst.Invalidate;
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        BmpViewerDest.Invalidate;
    ////    pnl4Dst.Invalidate;
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ////    BmpViewerDest.Invalidate;
        pnl4Dst.Invalidate;
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        BmpViewerDest.Invalidate;
        pnl4Dst.Invalidate;
    Là, je ne sais plus quoi inventer...

    HS : ça va, le boulot ?
    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. #156
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    Septembre 2015
    Messages
    1 899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2015
    Messages : 1 899
    Points : 4 346
    Points
    4 346
    Billets dans le blog
    2
    Par défaut
    Bonsoir
    Citation Envoyé par Jipété Voir le message
    Merci de ta réponse.
    Pas de soucis.
    Premier point, cet après midi pas eu assez de temps pour relire mon message. Du coup, (sans compter les "fotes d'aurtographe" ) je me suis un peu embrouillé :

    Par contre tu ne verras pas la transparence car il faut modifié la "procedure paint". En effet le TBMPViewer étant prévue pour l'affichage des fichiers BMP uniquement. La prise en charge de la transparence (Alpha) lors de l'affichage est en fonction des informations et de l'encodage du fichier BMP. Pour controler l'affichage avec transparence avec le TBMPViewer il faut modifié la procedure Paint;Comme ceci :
    En fait il faut comprendre : Par contre tu ne verra pas la transparence les changements car il faut modifié la "procedure paint". En effet le TBMPViewer étant prévue pour l'affichage des fichiers BMP uniquement. La prise en charge de la transparence (Alpha) lors de l'affichage est en fonction des informations et de l'encodage du fichier BMP. Pour contrôler le rafraichissement [S l'affichage avec transparence[/S] avec le TBMPViewer il faut modifié la procedure Paint Comme ceci :

    Citation Envoyé par Jipété Voir le message
    On va prendre le problème à l'envers parce que je dois être particulièrement bouché ce soir, toujours est-il que je ne m'en sors pas en tentant de StretchDrawer un BMPViewer sur un autre.

    Quand on regarde les réponses sur ce forum, ça a l'air enfantin :
    Image2.Canvas.StretchDraw(Image2.ClientRect, Image1.Picture.Bitmap); mais avec moi les choses les plus simples prennent une éternité de temps...

    J'ai essayé ça BmpViewerDest.Canvas.StretchDraw(BmpViewerDest.ClientRect, BmpViewerOrig.Bitmap); et tout un tas de variantes sur ce thème, avec un résultat toujours identique : le TPanel censé afficher l'image reste désespérément vide

    Avec cette variante je ne suis pas loin, BmpViewerDest.Canvas.StretchDraw(BmpViewerDest.ClientRect, BmpViewerOrig.FastBitmap.GetBitmap); puisque l'image s'affiche un court instant puis est effacée.
    Je la vois dans un flash, et elle a l'air aux bonnes dimensions. On est tout près...

    Mais résultat strictement identique (le flicker) avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ////    BmpViewerDest.Invalidate;
    ////    pnl4Dst.Invalidate;
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        BmpViewerDest.Invalidate;
    ////    pnl4Dst.Invalidate;
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ////    BmpViewerDest.Invalidate;
        pnl4Dst.Invalidate;
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        BmpViewerDest.Invalidate;
        pnl4Dst.Invalidate;
    Là, je ne sais plus quoi inventer...
    Tu ne peux pas te servir de "BmpViewerDest.Canvas" tout simplement car le TFastBitmap n'a pas de Canvas. Avec ça tu accèdes au Canvas du contrôle visuel. D'ou rien ou le flash.

    Avant d'aller plus loin rajoute "UpdateBitmap" dans la procedure paint comme mentionné dans mon message précédent.

    Si tu veux "stretcher"

    En gros il faut faire comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Var
      BmpViewerOrig,
      BmpViewerDest : TBMPViewer;
     
    begin
      With BmpViewerDest do
      begin
        AutoStretchMode := smStretchAll;
        FastBitmap.Assign(BmpViewerOrig.FastBitmap);
        Invalidate;
      end
    end;

    Il suffit juste d'assigner le TFastBitmap d'origine. Il n'est pas nécessaire d'obtenir le TBitmap pour ce faire. Enfin il faut paramétrer la propriété "AutoStretchMode" (je me rend compte que smManual est inapproprié je devrais changer par smNone et on devrait rajouté une options pour savoir si on veux garder le ratio ou pas. Car ici, par défaut le ratio est conservé. Petit chose présente dans ma bibliothèque).

    Sinon si tu souhaites redimensionner le bitmap avec une taille quelconque.
    Il faut rajouter le code de la procedure Stretch que j'avais déja posté dans l'unité uFastBitmap.pas

    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
     
    Interface
    Type
      TFastBitmap = Class
      public
     
        procedure Stretch(var NW, NH : Integer; const KeepRatio : Boolean);
      end;
     
    implementation
     
    function Clamp(const V,Min,Max : integer) : integer;
    begin
      Result := V;
      if Result > Max then begin result := Max; exit; end;
      if Result < Min then result := Min;
    end;
     
    procedure TFastBitmap.Stretch(var NW, NH : Integer; const KeepRatio : Boolean);
    Var
      TmpBmp: TfastBitmap;
      SrcW, SrcH, DstW, DstH, X, Y, UX, UY: Integer;
      Dx, Dy, uvx, uvy: Single;
      DstPtr, SrcPtr: PColor32;
      AColor: TColor32;
     
      Procedure KeepAspectRatio(Const aSrcW, aSrcH: Integer; Var NewWidth, NewHeight: Integer);
      Var
        w, h: Integer;
      Begin
        W := NewWidth;
        H := newHeight;
        if ( aSrcW > 1) and ( aSrcH > 1) then // On calcul le ratio par rapport aux dimensions du buffer d'affichage
        begin
          H:=Trunc((aSrcH*W) / aSrcW);
          if (H>=NewHeight) then
          begin
            H:=NewHeight;
            W:=Trunc((aSrcW*H) / aSrcH);
          end;
          NewWidth := W;
          NewHeight := H;
        end;
      end;
     
    Begin
      SrcW := Self.Width;
      SrcH := Self.Height;
     
      If (NW = SrcW) And (NH = SrcH) Then exit;
      If KeepRatio Then KeepAspectRatio(SrcW, SrcH, NW, NH);
     
      TmpBmp := TFastBitmap.Create;
      TmpBmp.SetSize(NW, NH);
      DstW := NW - 1;
      DstH := NH - 1;
      Dx := SrcW / DstW;
      Dy := SrcH / DstH;
      DstPtr := TmpBmp.GetScanLine(0);
      UvY :=0;
      For y := 0 To DstH Do
      Begin
        UY := Clamp(Trunc(UvY), 0, Self.Height-1);
        SrcPtr := Self.GetScanLine(UY);
        UvX := 0;
        For X := 0 To DstW Do
        Begin
          UX := Clamp(Trunc(UvX), 0, Self.Width-1);
          AColor := PColor32(SrcPtr + UX)^;
          DstPtr^ := AColor;
          Inc(DstPtr);
          UvX := UvX + DX;
        End;
        UvY := UvY + DY;
      End;
      Self.Assign(TmpBmp);
      FreeAndNil(TmpBmp);
    End;
    Puis simplement

    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
      BmpViewerOrig,
      BmpViewerDest : TBMPViewer;
      NW, NH : Integer;
      bKeepRatio : Boolean;
    begin
      bKeepRatio := False;
      NW := InttoStr(EdtNewWidth.Text);
      NH := InttoStr(EdtNewHeight.Text);
      With BmpViewerDest do
      begin
        AutoStretchMode := smManual; // Pas de stretch automatique
        Center := true; // Optionnel
        FastBitmap.Assign(BmpViewerOrig.FastBitmap);
        FastBitmap.Stretch(NW,NH, bKeepRatio);
        Invalidate;
      end
    end;
    Voila, je sais c'est frustrant car le couple TFastBitmap /TBMPViewer, TGIFViewer sont ici minimisé (surtout comparer au code de mon projet)

    Citation Envoyé par Jipété Voir le message
    HS : ça va, le boulot ?
    Merci, c'est fatiguant, plus le reste en plus du restaurant. En gros, Je pars à 8h je rentre à 15h en moyenne (quand je rentre), je repart à 17h et je rentre à 23h en moyenne (sauf ce soir, c'était 22h. On a eu juste une cliente)
    Bref voila des bonnes journées à mi-temps minimum.

    A+
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Pourquoi je ne comprends plus rien :
    Citation Envoyé par BeanzMaster Voir le message
    Tu ne peux pas te servir de "BmpViewerDest.Canvas" tout simplement car le TFastBitmap n'a pas de Canvas. Avec ça tu accèdes au Canvas du contrôle visuel. D'ou rien ou le flash.
    Parce que la complétion me permet par exemple d'écrire ça : FastBitmap.GetBitmap.Canvas.Brush.Color := clRed;... Tu vois ma perplexité ?

    Citation Envoyé par BeanzMaster Voir le message
    Avant d'aller plus loin rajoute "UpdateBitmap" dans la procedure paint comme mentionné dans mon message précédent.
    Rajouté, résultat strictement identique, c-à-d du flashing...
    Réglé, lire + bas

    Citation Envoyé par BeanzMaster Voir le message
    Si tu veux "stretcher"

    En gros il faut faire comme ça :
    Mais où définis-tu les nouvelles dimensions de la cible ? Il n'y a rien dans les quelques lignes de code que tu donnes...

    Citation Envoyé par BeanzMaster Voir le message
    Sinon si tu souhaites redimensionner le bitmap avec une taille quelconque.
    Il faut rajouter le code de la procedure Stretch que j'avais déja posté dans l'unité uFastBitmap.pas
    Rajouter et pourquoi si c'est déjà présent dans uFastBitmmap ?
    Je n'ai qu'à utiliser, non ?

    Ce n'était pas présent, j'ai rajouté, j'ai pris tes 3 lignes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
      NW := pnl4Dst.Width;
      NH := pnl4Dst.Height;
      with BmpViewerDest do begin
        FastBitmap.Assign(BmpViewerOrig.FastBitmap);
        FastBitmap.Stretch(NW,NH, True);
        Invalidate;
    et ça roule. Je vais pouvoir rebondir, demain matin.

    Ah, j'ai viré ce var qui m'empêchait de passer des valeurs prises sur des objets, avec ce message "can't take address of je sais plus quoi", très gonflant !
    Citation Envoyé par BeanzMaster Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        procedure Stretch(var NW, NH : Integer; const KeepRatio : Boolean);
    Du coup :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      with BmpViewerDest do begin
        FastBitmap.Assign(BmpViewerOrig.FastBitmap);
        FastBitmap.Stretch(pnl4Dst.Width, pnl4Dst.Height, True);
        Invalidate;
    Très light, très top !


    En fait, mon problème, c'est que je n'ai toujours pas compris comment tout ça s'articule : qui est au-dessus de qui, qui contrôle qui, qu'est-ce qu'il faut utiliser pour obtenir tel résultat, etc.
    Entre le BMPViewer qui n'affiche rien, le FastBitmap qui n'est qu'un bête Bitmap, le BMPImageLoader dont on se demande ce qu'il vient faire au milieu puisqu'un Bitmap prévoit LoadFromFile, bref, je suis largué.
    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

  18. #158
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    Septembre 2015
    Messages
    1 899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2015
    Messages : 1 899
    Points : 4 346
    Points
    4 346
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Jipété Voir le message
    Pourquoi je ne comprends plus rien :

    Parce que la complétion me permet par exemple d'écrire ça : FastBitmap.GetBitmap.Canvas.Brush.Color := clRed;... Tu vois ma perplexité ?
    ...
    Rajouté, résultat strictement identique, c-à-d du flashing...
    La fonction GetBitmap est la pour récupérer un TBitmap, c'est une conversion des données depuis le TFastBitmap vers le TBitmap rien de plus. Dans TBMPViewer on ne se sert pas du TBitmap pour manipuler les pixels.
    Par contre, le TBMPViewer transforme en interne le TFastBitmap vers un TBitmap (cf procedure UpdateBitmap) en vue d'utiliser la fonction native de Lazarus "StretchDraw".

    TImage ==> TBitmap DIFFERENT DE TBMPViewer ==> TFastBitmap

    Lors de ton exemple précédent pour créer le dégradé on a utilisé le TFastBitmap et non un TBitmap (cf procedure TForm1.btnTbzBMPViewerClick(Sender: TObject); posté 2 messages plus haut)

    Citation Envoyé par Jipété Voir le message
    Mais où définis-tu les nouvelles dimensions de la cible ? Il n'y a rien dans les quelques lignes de code que tu donnes...
    C'est comme avec le TImage avec la propriété stretch à true lorsque que tu fais TImage.Picture.Bitmap.Assign(UnTBitmap) l'image est automatiquement redimensionné aux dimensions du TImage. Tu ne fais de Canvas.StretchDraw ou autre pour afficher ton nouveau bitmap dans le TImage. Ici c'est pareil avec le TBMPViewer, si la propriété AutoStretchMode := smStretchAll; alors toutes les images plus petites ou plus grande seront automatiquement redimensionner aux dimensions du composant visuel. Pas besoins de te prendre la tête

    Citation Envoyé par Jipété Voir le message
    Rajouter et pourquoi si c'est déjà présent dans uFastBitmap ?
    Je n'ai qu'à utiliser, non ?
    Je n'avais pas souvenir que je l'avait déja rajouté


    Citation Envoyé par Jipété Voir le message
    Entre le BMPViewer qui n'affiche rien,
    Normal tu t'obstines à utiliser TBitmap.Canvas

    Citation Envoyé par Jipété Voir le message
    le FastBitmap qui n'est qu'un bête Bitmap,
    NON CE N'EST PAS Q'UN BËTE TBITMAP c'est un TFASTBITMAP

    Il ne faut pas comparer TImage/TBitmap natif de Lazarus avec TBMPViewer/TFastBitmap cela n'a rien a voir (même si la finalité est presque la même). C'est pour ça que tu te mets des battons dans les roues. Tu essayes d'utiliser le fonctionnement natif du TBitmap/TImage avec TFastBitmap/TBMPViewer ce sont deux classes (objets) différents. Du coup tu te prend des murs à essayer d'utiliser les methodes de l'un avec l'autre.

    Citation Envoyé par Jipété Voir le message
    le BMPImageLoader dont on se demande ce qu'il vient faire au milieu puisqu'un TBitmap prévoit LoadFromFile (pas TFastBitmap) , bref, je suis largué.
    Citation Envoyé par Jipété Voir le message
    En fait, mon problème, c'est que je n'ai toujours pas compris comment tout ça s'articule : qui est au-dessus de qui, qui contrôle qui, qu'est-ce qu'il faut utiliser pour obtenir tel résultat, etc.
    BMPImageLoader est la pour charger un fichier au format BMP dans un TFastBitmap. TBMPViewer est là pour afficher ce TFastBitmap.

    Le TBitmap natif de Lazarus gère plusieurs formats de fichier le code de prise en charge pour plusieurs format est différent.
    Le problème vient du fait que tu essayes d'amalgamer les 2. Donc tu vas dans

    Bonne fin de soirée
    A+

    [EDIT] Ben voila ca commence à rentrer. Mais du coup si ton BmpViewerDest est posé sur ton pnl4Dst et que Align:=alClient et que AutoStretchMode := smStretchAll comme je l'ai dis tu n'a pas besoins de passer par la procedure Stretch à moins que tu souhaites réellement redimensionner ton image et conserver le résultat. sinon :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    With BmpViewerDest do
      begin    
        FastBitmap.Assign(BmpViewerOrig.FastBitmap);
        Invalidate;
      end
    suffit.
    [/EDIT]
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Bonsoir,
    Fouhhh, fatigué, ce soir...

    La journée avait pourtant bien commencé, je corrigeais mes bugs, genre virer cette histoire de stretch rajouté hier, qui présente un défaut de géométrie :
    Nom : compar_stretch-stretchdraw.png
Affichages : 136
Taille : 25,1 Ko

    à gauche dans Linux on voit sous l'image les dernières lignes copiées collées de l'image de droite prise sous XP, qui est à la bonne taille : agrandie x 2, elle fait 256 px.
    Celle de gauche n'en fait que 248 et la hauteur n'est pas bonne non plus...

    Et j'ai décidé d'appeler une amie, pour faire une pause et là, stupéfaction, je constate que ma ligne fixe est morte !
    Pas de tonalité...
    Je vous passe les détails, juste un point technique : en mesurant au niveau de la barrette de répartition dans la rue, avec le câble vers chez moi déconnecté, je n'ai pas de 48 V !
    Confirmé par FT, qui va intervenir.
    Journée à moitié fichue.

    Sinon, j'ai bien suivi tes conseils pour le stretching automatique :
    Citation Envoyé par BeanzMaster Voir le message
    Mais du coup si ton BmpViewerDest est posé sur tonpnl4Dst et que Align:=alClient et que AutoStretchMode := smStretchAll comme je l'ai dis tu n'a pas besoins de passer par la procedure Stretch à moins que tu souhaites réellement redimensionner ton image et conserver le résultat. sinon :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    With BmpViewerDest do
      begin    
        FastBitmap.Assign(BmpViewerOrig.FastBitmap);
        Invalidate;
      end
    suffit.
    mais ça foire à l'affichage : il faut que je masque puis réaffiche la fiche pour que l'agrandissement soit visuellement effectif !
    À peine gonflant...
    Nom : dst=src.png
Affichages : 118
Taille : 7,3 Ko
    À gauche l'original, à droite la copie avec en blanc le tpanel container du bmpviewer, et en bleu la scrollbox alClient contenant le tpanel, et je te garantis que je demande "x 2". D'ailleurs, je réduis en barre de tâches puis je remonte et c'est bon.
    J'ai tenté d'attribuer ce Invalidate également au tpanel, ainsi qu'aux deux composants, ou soit l'un soit l'autre et c'est strictement identique.


    Ensuite, toujours à ce chapitre, selon le rapport d'agrandissement demandé, j'ai parfois une bande blanche (sans doute le tpanel -- oui oui, confirmé avec une autre couleur) qui apparaît, donc le bmpviewer n'occupe pas l'espace qui lui est imparti malgré le alClient.

    Nom : ligne_blanche_parfois.png
Affichages : 149
Taille : 43,6 Ko

    À gauche sous l'original j'ai incrusté une capture à 800 % du bas de la partie centrale de l'agrandissement à x 2,4 à droite. On reconnaît le trait coloré séparant les zones jaune et verte.

    EDIT
    Je vais essayer de faire un autre projet ultra léger pour mettre ces problèmes en évidence.
    minimalist.zip

    Et il aurait fallu créer une discussion dédiée à ce composant parce que là, on part en vrac...
    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. #160
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    Septembre 2015
    Messages
    1 899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2015
    Messages : 1 899
    Points : 4 346
    Points
    4 346
    Billets dans le blog
    2
    Par défaut
    Salut,

    Je ne vois pas ou je ne comprends pas le problème

    voila ce que j'ai à la compilation sous win de taon application "minimaliste"

    Nom : 2019-03-16_001757.jpeg
Affichages : 148
Taille : 38,2 Ko

    pourrais-tu être plus précis, j'ai du mal a saisir.

    Un truc que je n'arrive toujours pas a saisir pourquoi utilises tu un TImage ?????
    Pourquoi veux tu passer par les compos de Mitchell ???

    Sinon, ok , j'ai trouvé pourquoi le TBMPViewer n'est pas rafraichit dans le FormCreate

    Il faut modifié un peu l'unité uBMPViewer

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    procedure TBMPViewer.UpdateBitmap;
    Var
       TmpBmp : Graphics.TBitmap;
    Begin
      // Note : Sous MacOS on ne peut pas assigner Bitmap directement avec
      // TFastBitmap.GetBitmap; On est obligé de créer le bitmap de destination temporaire et utiliser Assign.
     
      if not(assigned(FBMPLoader)) then exit; // Ligne à rajouter
     
      TmpBmp := Graphics.TBitmap.Create;
      TmpBmp := FBMPLoader.FastBitmap.GetBitmap;
      FBitmap.Assign(TmpBmp);
      FreeAndNil(TmpBmp);
    end;
    du coup dans la procedure PaintOn peux virer le updatebitmap (a vérifier quand même suivant les cas, mais normalement plus besoin)

    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    procedure TBMPViewer.Paint;
     
      Procedure DrawFrame;
      Begin
        With Inherited Canvas Do
        Begin
          Pen.Color := clBlack;
          Pen.Style := psDash;
          MoveTo(0, 0);
          LineTo(Self.Width - 1, 0);
          LineTo(Self.Width - 1, Self.Height - 1);
          LineTo(0, Self.Height - 1);
          LineTo(0, 0);
        End;
      End;
     
    Var
      R:     TRect;
      C:     TCanvas;
      ARect: TRect;
      w:     Integer;
    Begin
     
      If csDesigning In ComponentState Then DrawFrame;
     
      C         := Inherited Canvas;
      FPainting := True;
      R         := DestRect;
      Try
        C.Lock;
        // Fond
        If (FColor <> clNone) Then //and Not(FTransparent)
        Begin
          With C Do
          Begin
            Brush.Style := bsSolid;
            Brush.Color := FColor;
            FillRect(0, 0, ClientWidth, ClientHeight);
          End;
        End;
     
        // Bitmap
        //UpdateBitmap; // mise à jour du TBitmap pour l'affichage -- conseil Jérôme
        FBitmap.Transparent := FTransparent;
        C.StretchDraw(R, FBitmap);
     
        // Bordures
        If FBorderShow Then
        Begin
          ARect := rect(0, 0, ClientWidth, ClientHeight);
          w     := FBevelWidth;
          If (FBevelInner <> bvNone) And (w > 0) Then C.Frame3d(ARect, w, BevelInner); // Note: Frame3D inflates ARect
          InflateRect(ARect, -(FBorderWidth + 1), -(FBorderWidth + 1));
          If (FBevelOuter <> bvNone) And (w > 0) Then C.Frame3d(ARect, w, BevelOuter);
     
          If FBorderWidth > 0 Then With C Do
            Begin
              Pen.Style   := psSolid;
              Pen.Width   := FBorderWidth;
              Pen.Color   := FBorderColor;
              Brush.Style := bsClear;
              Rectangle(0, 0, ClientWidth, ClientHeight);
            End;
        End;
     
        C.UnLock;
      Finally
        FPainting := False;
      End;
     
      Inherited Paint;
    End;
    Et dans ton exemple : minimalist juste le code ci-dessous suffit

    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      rempliO := False;
      rempliD := False;
     
      BmpViewerOrig := TBMPViewer.Create(Self);
      with BmpViewerOrig do begin
        Parent := pnl4Src;
        Align  := alClient;
        AutoStretchMode := smManual;
      end;
      //pnl4Src.OnPaint := @PaintBzViewerOrig;
     
      BmpViewerDest := TBMPViewer.Create(Self);
      with BmpViewerDest do begin
        Parent := pnl4Dst;
        Align  := alClient;
        AutoStretchMode := smStretchAll;//smManual;
      end;
      //pnl4Dst.OnPaint := @PaintBzViewerDest;
     
      LoadedFile := ProgramDirectory+'embedded_xbr32.bmp';
     
      //LoadedFile := ProgramDirectory+'embedded_xbr24.bmp';
     
      //intermediaire; // charge la source
      BmpViewerOrig.LoadFromFile(LoadedFile);
     
     
      // attention ! devrait être lié au chargement/changement de fichier, plutôt
      with pnl4Src do begin
        Left   := 0;
        Top    := 0;
        Width  := BmpViewerOrig.FastBitmap.Width; // et PAS bmpv.Width !
        Height := BmpViewerOrig.FastBitmap.Height;
        if Width < pnl4display.ClientWidth // pour récupérer de la place pour la copie
          then sboxSrc.ClientWidth := Width;
      end;
     
      // SRC
      with srcRect do begin
        Left   := 0;
        Top    := 0;
        Right  := pnl4Src.Width;
        Bottom := pnl4Src.Height;
      end;
     
      BmpViewerDest.FastBitmap.Assign(BmpViewerOrig.FastBitmap);
     
     
      trkScaleChange(nil);
     // Application.ProcessMessages;
     
      // pas pris en compte ici -- faut jouer du curseur pour que ça change :koi:
      // ou cacher puis découvrir la fiche
    end;
     
    procedure TForm1.trkScaleChange(Sender: TObject);
    var
      scale: single;
    begin
      scale := trkScale.Position / 100;
      lblStep.Caption := 'Step : ' + FloatToStr( round (scale*10) / 10 ); // donne des valeurs bien arrondies genre 0.3 1.2 etc.
      // et en admettant qu'elles soient utiles, comment les récupérer ?
     
      with dstRect do begin // calcul des dimensions de la cible
        Left   := round(srcRect.Left   * scale); // trunc avant
        Top    := round(srcRect.Top    * scale); // et là, ça change la vie !
        Right  := round(srcRect.Right  * scale); // tout bon
        Bottom := round(srcRect.Bottom * scale); // :-)
      end;
     
      with pnl4Dst do begin // ajustement du container de la cible
        Left  := 0;
        Top   := 0;
        Width := dstRect.Right;
        Height:= dstRect.Bottom;
      end;
     
    //  with BmpViewerDest do begin
    //    FastBitmap.Assign(BmpViewerOrig.FastBitmap);
    //bz ici      Invalidate;
    //  end;
     
       //rempliD := True;
       BmpViewerDest.Invalidate;
    //    pnl4Dst.Invalidate;
    end;
    Le reste tu peux tout virer

    Nom : minimalist_jipete.gif
Affichages : 150
Taille : 1,12 Mo


    PS : Pas besoins d'ouvrir une nouvelle discussion on est que les deux (dommage !)

    A+
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

+ Répondre à la discussion
Cette discussion est résolue.
Page 8 sur 10 PremièrePremière ... 45678910 DernièreDernière

Discussions similaires

  1. Déplacer des fichiers Excel sous Windows avec SAS
    Par Antoun dans le forum Outils BI
    Réponses: 6
    Dernier message: 19/11/2009, 17h05
  2. [Vxi] liens avec des fichiers .jpg, bmp, ou gif
    Par chendo dans le forum Designer
    Réponses: 1
    Dernier message: 14/10/2009, 09h48
  3. Gestion des fichiers users sous linux
    Par darkvodka dans le forum C++
    Réponses: 2
    Dernier message: 29/09/2007, 19h04
  4. Créer et utiliser des fichiers excel sous linux
    Par cronos6 dans le forum Zope
    Réponses: 2
    Dernier message: 02/06/2006, 09h14
  5. Lire des fichiers iso sous linux
    Par wodel dans le forum Applications et environnements graphiques
    Réponses: 3
    Dernier message: 28/11/2005, 10h17

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