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 :

Combiner zoom, rotation et transparence avec BGRABitmap [Lazarus]


Sujet :

Lazarus Pascal

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Développeur occasionnel
    Inscrit en
    Janvier 2018
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Développeur occasionnel
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2018
    Messages : 49
    Par défaut Combiner zoom, rotation et transparence avec BGRABitmap
    Bonsoir,

    Je souhaite pouvoir effectuer tout à la fois un zoom, une rotation ou encore une transparence sur un graphique contenu dans un BGRABitmap.
    Le problème est que je ne parviens pas à associer les trois effets simultanément.

    Je suis parti du code suivant, inspiré d'une démo trouvé sur le forum anglais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    procedure TfrmMap.bgraMainRedraw(Sender: TObject; Bitmap: TBGRABitmap);
    begin
      Bitmap.PutImageAngle(Bitmap.Width/2-0.5, Bitmap.Height/2-0.5, bmp, tbAngle.Position, bmp.Width/2-0.5, bmp.Height/2-0.5, tbOpacity.Position);
    end;
    bmp est le graphique d'origine (taille: 1920x1080px) modifié et affiché dans Bitmap (taille: 856x624px).
    Le code ci-dessus effectue superbement une rotation avec transparence en prenant le centre de Bitmap comme axe de rotation.
    Mais je n'ai pas trouvé une procédure ou fonction qui permette en même temps de zoomer le graphique d'origine.

    Aussi j'ai modifié le code de la manière suivante :

    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
    procedure TfrmMap.bgraMainRedraw(Sender: TObject; Bitmap: TBGRABitmap);
    var
      affine: TBGRAAffineBitmapTransform;
      LBGRATemp: TBGRABitmap;
    begin
      LBGRATemp := TBGRABitmap.Create(bgraMain.ClientWidth, bgraMain.ClientHeight, BGRABlack);
      try
        affine := TBGRAAffineBitmapTransform.Create(bmp, false);
        affine.GlobalOpacity := tbOpacity.Position;
        affine.RotateDeg(tbAngle.Position);
        affine.Scale(tbZoom.Position / 100);
        affine.Translate(bgraMain.ClientWidth / 2, bgraMain.ClientHeight / 2); 
        LBGRATemp.Fill(affine);
        Bitmap.PutImage(0, 0, LBGRATemp, dmSet, tbOpacity.Position);             
      finally
        LBGRATemp.Free;
        affine.Free;
      end;
    end;
    Et là j'avais les trois effets (transparence, rotation et zoom) réunis ! Le hic toutefois, c'est que la rotation ne s'effectue plus à partir du centre de l'image !
    Quelle procédure ou fonction dois-je ajouter à la variable affine pour parvenir à ce résultat ?
    Merci d'avance pour votre aide.

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

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

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 907
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Dans son tuto, Gilles utilise un code un peu différent : présente-t-il le même inconvénient ?
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  3. #3
    Membre Expert
    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
    Billets dans le blog
    2
    Par défaut
    Bonjour,
    je ne suis pas a la maison pour vérifier mais dans ton exemple tu as 4 étapes :

    Opacité --> Rotation --> Scale --> Translation

    Ton problème je pense est l'ordre des transformations. C'est important. Pour ma part je ferai comme ceci

    Scale --> Rotation --> Opacité --> (Translation si besoin)

    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

  4. #4
    Membre averti
    Homme Profil pro
    Développeur occasionnel
    Inscrit en
    Janvier 2018
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Développeur occasionnel
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2018
    Messages : 49
    Par défaut
    Bonsoir BeanzMaster,

    Citation Envoyé par BeanzMaster Voir le message
    Ton problème je pense est l'ordre des transformations. C'est important. Pour ma part je ferai comme ceci :

    Scale --> Rotation --> Opacité --> (Translation si besoin)
    Merci de me faire profiter de ton expérience.
    Si je laisse de côté l'opacité qui n'est pas vraiment un problème, j'en suis venu à penser qu'il valait mieux tourner l'image en premier pour ne pas perdre les parties de cette image qui sont dans les coins !
    Après, il y a le problème de la "Translation" qui doit effectivement être considérée.
    Mais je ne suis qu'au début de ma découverte de TBGRABitmap qui me semble très prometteur.
    Merci beaucoup pour ton aide.

  5. #5
    Membre Expert
    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
    Billets dans le blog
    2
    Par défaut
    Salut j'ai fait quelques recherche vite fait pour pouvoir effectuer un zoom et une rotation en même temps, regardes du coté de la fonction

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    procedure PutImageAffine(Origin,HAxis,VAxis: TPointF; Source: TBGRACustomBitmap; AOutputBounds: TRect; AResampleFilter: TResampleFilter; AMode: TDrawMode; AOpacity: Byte=255); overload;
    procedure PutImageAffine(Origin,HAxis,VAxis: TPointF; Source: TBGRACustomBitmap; AOutputBounds: TRect; AResampleFilter: TResampleFilter; AMode: TDrawMode; AOpacity: Byte=255); overload;
    procedure PutImageAffine(Origin,HAxis,VAxis: TPointF; Source: TBGRACustomBitmap; AOutputBounds: TRect; AOpacity: Byte=255; ACorrectBlur: Boolean = false); overload;
    procedure PutImageAffine(AMatrix: TAffineMatrix; Source: TBGRACustomBitmap; AOpacity: Byte=255; ACorrectBlur: Boolean = false); overload;
    procedure PutImageAffine(AMatrix: TAffineMatrix; Source: TBGRACustomBitmap; AResampleFilter: TResampleFilter; AOpacity: Byte=255); overload;
    procedure PutImageAffine(AMatrix: TAffineMatrix; Source: TBGRACustomBitmap; AResampleFilter: TResampleFilter; AMode: TDrawMode; AOpacity: Byte=255); overload;
    procedure PutImageAffine(AMatrix: TAffineMatrix; Source: TBGRACustomBitmap; AOutputBounds: TRect; AResampleFilter: TResampleFilter; AMode: TDrawMode; AOpacity: Byte=255); virtual; abstract; overload;
    procedure PutImageAffine(AMatrix: TAffineMatrix; Source: TBGRACustomBitmap; AOutputBounds: TRect; AOpacity: Byte=255; ACorrectBlur: Boolean = false); overload;
    A l'aide des matrices tu pourras effectuer un zoom et une rotation
    • "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

  6. #6
    Membre averti
    Homme Profil pro
    Développeur occasionnel
    Inscrit en
    Janvier 2018
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Développeur occasionnel
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2018
    Messages : 49
    Par défaut
    Bonjour BeanzMaster,

    Merci pour ces quelques recherches. Je me suis essayé avec PutImageAffine, mais je n'ai pas trouvé comment faire pivoter l'image à partir de son centre durant "l'affinage".

    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
    procedure TfrmMap.bgraMainRedraw(Sender: TObject; Bitmap: TBGRABitmap);
    var
      LBGRATemp: TBGRABitmap;
      percent, ratio: single;
    begin
      percent := (LBGRABase.Width / Bitmap.Width) / 100;
      ratio := tbZoom.Position * percent;
      LBGRATemp := TBGRABitmap.Create(LBGRABase.Width, LBGRABase.Height, BGRAWhite);
      try
        LBGRATemp.PutImageAffine(AffineMatrixScale(ratio, ratio) *
                                 AffineMatrixRotationDeg(tbAngle.Position),
                                 LBGRABase, tbOpacity.Position);
        LBGRATemp.Draw(Bitmap.Canvas, 0, 0);
      finally
        LBGRATemp.Free;
      end;
    end;

  7. #7
    Membre averti
    Homme Profil pro
    Développeur occasionnel
    Inscrit en
    Janvier 2018
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Développeur occasionnel
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2018
    Messages : 49
    Par défaut
    Bonsoir BeanzMaster,

    Citation Envoyé par Péhelji
    J'en suis venu à penser qu'il valait mieux tourner l'image en premier pour ne pas perdre les parties de cette image qui sont dans les coins !
    Je suis venu à bout de ce problème et à combiner les trois effets avec la procédure suivante :

    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
     
      offsetX := round(((tbZoom.Position - 100) * LBGRABase.Width  div 2) / 100);
      offsetY := round(((tbZoom.Position - 100) * LBGRABase.Height div 2) / 100);
     
      LBGRATemp := TBGRABitmap.Create(LBGRABase.Width, LBGRABase.Height);
      try
        LBGRATemp.PutImageAngle(LBGRATemp.Width/2-0.5, LBGRATemp.Height/2-0.5, LBGRABase, tbAngle.Position,
                                LBGRABase.Width/2-0.5, LBGRABase.Height/2-0.5, tbOpacity.Position);
        rc := LBGRATemp.ClipRect;
        rc.Inflate(round(offsetX), round(offsetY));
     
        Bitmap.Canvas.CopyRect(Bitmap.ClipRect, LBGRATemp.Canvas, rc);
      finally
        LBGRATemp.Free;
      end;
    Peut-être serait-il possible d'améliorer la fluidité du zoom en utilisant BGRAVirtualScreen ou encore BGRACanvas2D ?

    J'ai trouvé de quoi plancher sur le sujet avec la démo LayerOriginal fournie avec BGRABitmap, et aussi celle postée ici par Circular.

  8. #8
    Membre Expert
    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
    Billets dans le blog
    2
    Par défaut
    Salut,

    je n'ai pas beaucoup de temps en ce moment et je n'utilise que très rarement BGRABitmap mais, pour ce qui est de la fluidité lis les tutoriels de Gilles,. Tu n'as pas vraiment besoin du BGRAVirtualScreen.
    Le BGRACanvas2D c'est comme le TCanvas donc pas besoin dans ton cas.

    Voila comment à fait Gilles pour la rotation et le zoom :

    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 TGVTransition.DoGrowCenterRotate(CCW: Boolean);
    // *** GrowCenterCCWRotate et GrowCenterCWRotate ***
    var
      LBGRATemp: TBGRABitmap;
    begin
      LBGRATemp := fLBGRATo.Resample(
        ComputeInterpolationInt(C_MinResample, ClientWidth),
        ComputeInterpolationInt(C_MinResample, ClientHeight)) as TBGRABitmap;
      try
        fLBGRAFrom.PutImageAngle(ClientWidth / 2, ClientHeight / 2, LBGRATemp,
          ifthen(CCW, ComputeInterpolation(360, 0), ComputeInterpolation(-360, 0)),
          LBGRATemp.Width / 2, LBGRATemp.Height / 2,DestinationOpacity);
      finally
        LBGRATemp.Free;
      end;
    end;
    Moins de calcul déja ici

    Petite question que souhaites tu réaliser au final ? Une animation ? un mini-éditeur ?

    https://gilles-vasseur.developpez.co...sitions/bgra1/
    https://gilles-vasseur.developpez.co...sitions/bgra2/
    https://gilles-vasseur.developpez.co...sitions/bgra3/
    https://gilles-vasseur.developpez.co...sitions/bgra4/
    https://gilles-vasseur.developpez.co...sitions/bgra5/
    https://gilles-vasseur.developpez.co...sitions/bgra6/
    https://gilles-vasseur.developpez.co...sitions/bgra7/
    https://gilles-vasseur.developpez.co...sitions/bgra8/
    • "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

  9. #9
    Membre averti
    Homme Profil pro
    Développeur occasionnel
    Inscrit en
    Janvier 2018
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Développeur occasionnel
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2018
    Messages : 49
    Par défaut
    Bonjour BeanzMaster,

    J'ai téléchargé les tutoriels de Gilles et j'ai testé les démos et le test simple livré avec le tutoriel n°8. C'est pour le moins bluffant !
    C'est effectivement vers les transitions GrowCenter et GrowCenterCWRotate que je dois rechercher la solution à mon problème.
    Quoique j'étais parvenu à une meilleure fluidité avec la séquence suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
      LBGRATemp := TBGRABitmap.Create(LBGRABase.Width, LBGRABase.Height{, BGRAWhite});
      try
        LBGRATemp.PutImageAffine(
          AffineMatrixScale(ratio, ratio) *
          AffineMatrixTranslation(LBGRABase.Width/2-0.5, LBGRABase.Height/2-0.5) *
          AffineMatrixRotationDeg(tbAngle.Position) *
          AffineMatrixTranslation(-LBGRABase.Width/2-0.5, -LBGRABase.Height/2-0.5),
          LBGRABase, tbOpacity.Position);
        LBGRATemp.Draw(Bitmap.Canvas, 0, 0);
      finally
        LBGRATemp.Free;
      end;
    La rotation est nickel au centre du canvas... mais le zoom n'opère qu'à partir du coin supérieur gauche !
    Le nœud du problème se situe au niveau des paramètres passés à AffineMatrixTranslation. Je vais voir si les fonctions ComputeInterpolation des tutos ne seraient pas la solution.

    Citation Envoyé par BeanzMaster Voir le message
    Petite question que souhaites tu réaliser au final ? Une animation ? un mini-éditeur ?
    Je travaille sur une application de cartographie et, dans un premier temps, je souhaite pouvoir ajuster des cartes de différentes tailles en les superposant (j'ai testé BGRALayers), chaque couche devant être modifiable par zoom, rotation, transparence et bien entendu déplacement.
    Merci encore pour ta recherche et tes conseils.

  10. #10
    Membre averti
    Homme Profil pro
    Développeur occasionnel
    Inscrit en
    Janvier 2018
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Développeur occasionnel
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2018
    Messages : 49
    Par défaut
    Bonsoir Tourlourou,

    Citation Envoyé par tourlourou Voir le message
    Gilles utilise un code un peu différent : présente-t-il le même inconvénient ?
    J'avais repéré hier la série de tutoriaux de Gilles Vasseur (au demeurant bienvenus) mais n'avais pas eu le temps de les étudier en profondeur.
    J'ai modifié la procédure principale de la façon suivante :

    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
     
      LBGRATemp := TBGRABitmap.Create(imgResult.ClientWidth, imgResult.ClientHeight, BGRABlack);
      try
        fStep := 0;
        ratio := round((imgResult.Width / imgTo.Picture.Width) * 100);
     
        repeat //
          Inc(fStep);
     
          // traitement ici...
          LX := imgResult.ClientWidth div 2;
          LY := imgResult.ClientHeight div 2;
          LBGRATemp.PutImageAngle(LX, LY, fBGRATo, fStep, fBGRATo.Width div 2, fBGRATo.Height div 2, Opacity);
          LBGRATemp.Draw(imgResult.Canvas, 0, 0);
          Application.ProcessMessages;
          sleep(100 - fSpeed);
     
          //inc(ratio);
          BGRAReplace(fBGRATo, fBGRATo.Resample(fBGRATo.Width + 2, fBGRATo.Height + 2));
          fBGRATo.StretchPutImage(fBGRATo.ClipRect, fBGRATest, dmSet);
          //until (ratio = 100);
          until (fStep = 360);
      finally
        LBGRATemp.Free;
        btnGo.Enabled := True;
      end;
    Tel quel, ce code redimensionne l'image d'origine (quel magnifique rouge-gorge !) tout en la faisant tourner par incrément d'un degré autour de son centre.
    L'incrément de 2 dans la procédure Resample est arbitraire. Il est censé être remplacé par un pourcentage de la taille originale de l'image.
    C'est dire que le code a encore besoin d'être amélioré !
    Merci pour ton aide.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [D5] Zoom d'image PNG avec transparence
    Par Thierry Laborde dans le forum Delphi
    Réponses: 9
    Dernier message: 12/06/2006, 15h41
  2. Réponses: 13
    Dernier message: 01/12/2005, 05h34
  3. Texte en transparence avec TextOut
    Par TigreRouge dans le forum MFC
    Réponses: 2
    Dernier message: 06/06/2005, 22h57
  4. [Rotations] Rotations Locales/Globales avec Quaternions
    Par Clorish dans le forum Algorithmes et structures de données
    Réponses: 2
    Dernier message: 24/05/2005, 16h41
  5. probleme de transparence avec fog
    Par Daedar dans le forum OpenGL
    Réponses: 10
    Dernier message: 03/05/2004, 08h14

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