Animer vos Gifs avec TGIFViewer sous Lazarus
Un composant de Jérôme Delauney

Le , par BeanzMaster, Membre émérite
TGIFViewer 👀
Composant d'animation de GIFs pour Lazarus

Bonjour à tous,

Suite à notre discussion, je vous présente le composant TGIFViewer en version 1.0.

TGIFViewer est un composant visuel pour l'affichage d'animations au format GIF (Graphic Interchange Format) avec Free Pascal et Lazarus.

Compatibilité : Windows, Linux et MacOS

Capacités de TGIFViewer :
  • Chargement depuis un stream, un fichier ou une ressource (fonctions LoadFromStream, LoadFromFile, LoadFromResource) ;
  • Extraction des images brutes (**fonction DisplayRawFrame) ;
  • Extraction des images pré-calculées de l'animation (fonction DisplayFrame ) ;
  • Affichage avec ou sans transparence (Transparent) ;
  • Gestion silencieuse de certaines données mal encodées pour permette l'affichage des images sans perturber l'utilisateur ;
  • Gestion des erreurs pour les fichiers mal compressés (OnLoadError) ;
  • Centrage (Center), redimensionnement (Stretch) de l'affichage ;
  • Dimension du composant automatique en fonction de l'image (AutoSize) ;
  • Evénement à la lecture, l'arrêt ou la mise en pause de l'animation (OnStart, OnPause, OnStop) ;
  • Accès aux images et informations du GIF via la propiété Frames.Items[x].
  • Traduction des messages interne via les fichiers po du français à l'anglais à l'aide du composant de Gilles Vasseur TGVTranslate légèrement modifié provenant de son tutoriel Comment internationaliser une application avec Free Pascal/Lazarus (voir demonstration gifview. Notez que vous devez copier le dossier languages dans le dossier de sortie de l'executable )


Voici une démonstration avec MacOS :



ℹ️ Contient également deux unités :

  • uFastBitmap : classe pour la manipulation de bitmaps 32 bits au format RGBA ou BGRA suivant l'OS ;
  • TypesHelpers : classes ajoutant des fonctions utiles au type de données (byte, integer, string, double, TDateTime...) les fonctions sont accessibles directement par la complétion du code sous Lazarus.
  • GVTranslate : Classe d'aide pour traduire une application


ℹ️ Vous pouvez télécharger GIF-ImageTestSuite pour tester avec plusieurs GIFs encodés différemment.

Installation :
  1. Dans Lazarus, allez dans le menu "Paquet" et sélectionnez "Ouvrir un fichier de paquet (".lpk" ;
  2. Sélectionnez gifviewer_pkg.lpk du dossier Package ;
  3. Cliquez sur le bouton "Compiler" ;
  4. Cliquez sur le bouton "Utiliser" puis "Installer".


Le composant TGIFViewer sera installé dans la section Beanz Extra.

Note :
L'application de démonstration GifView du dossier Demos ne nécessite pas l'installation du composant dans l'EDI pour fonctionner.

Licence : MPL

Téléchargement à partir de DVP

Que pensez-vous de ce composant ?
Quels outils graphiques souhaiteriez-vous voir développés avec Lazarus ?


Vous avez aimé cette actualité ? Alors partagez-la avec vos amis en cliquant sur les boutons ci-dessous :


 Poster une réponse Signaler un problème

Avatar de Jipété Jipété - Expert éminent sénior https://www.developpez.com
le 24/06/2018 à 0:03
Citation Envoyé par BeanzMaster Voir le message
Bonjour à tous

Suite à notre discussion, je vous présente le composant TGIFViewer en version 1.0
Houla, je te trouve bien précipité, là :
girl
balle rouge
1re boucle boucles suivantes
38732719
48487099
rotating_earth
769l
smartfullcolour triangle vert aléatoire
J'ai arrêté là, il est tard...
Avatar de BeanzMaster BeanzMaster - Membre émérite https://www.developpez.com
le 24/06/2018 à 0:46
Test sous Windows 10:


Avatar de BeanzMaster BeanzMaster - Membre émérite https://www.developpez.com
le 24/06/2018 à 1:02
Citation Envoyé par Jipété Voir le message
Houla, je te trouve bien précipité, là :
J'ai arrêté là, il est tard...
Effectivement je viens de tester sous Linux il y a un problème avec la transparence.

Précipité ? NON ! même sous Mac TGIFViewer fonctionne nickel. Je vais essayer de voir ce que je peux modifier. Mais ça sent pas bon du côté du TBitmap avec Linux. C'est vraiment aléatoire comme comportement.
Avatar de BeanzMaster BeanzMaster - Membre émérite https://www.developpez.com
le 24/06/2018 à 3:09
Vraiment chelou comme bug

Chargement de la girl nickel. Je visualise l'animation image par image pas de soucis. Arrivé à la 16ème image, je redescends et là paf .

Le problème se situe avec l'utilisation de TBitmap.MaskHandle (voir la fonction TFastBitmap.BuildBitmap) si tu commentes la ligne "Temp.MaskHandle" toutes les images que tu as postées ci-dessus fonctionnent. Par contre Pen-Gif, le singe, la WikiBall sont en vrac.
Le plus étrange, c'est que la transparence est bien prise en charge pour la première image de chaque gif mais pas les suivantes (c'est suivant les gif : avec girl, l'animation jouée, la première fois est bonne, mais pas la seconde ). Ce bug ne vient pas de mon code. Sinon si quelqu'un a la solution, on est preneur.

Pour info, j'ai même forcé la couleur alpha à 255 dans "TFastBitmap.PutImage", même problème. En remplaçant "StretchDraw" par "Draw" dans TGifViewer.Paint, l'incohérence de la transparence est encore plus flagrante . A part utiliser mon projet, vu que je travaille avec les bitmaps différemment et où je n'ai pas ce soucis je ne vois pas comment faire. Ou sinon la solution serait comme dans GifAnim : passer par TLazIntfImage avant de passer les données au TBitmap.

Bref, c'est vraiment frustrant pour le coup
Avatar de BeanzMaster BeanzMaster - Membre émérite https://www.developpez.com
le 24/06/2018 à 3:58
Et enfin voilà le test sous Linux :



C'est quand même fou que d'être obligé de passer par TLazIntfImg sous Linux pour que la transparence soit gérée correctement.

PS : Les sources ont été mises à jour. Tout roule dans les trois mondes
Avatar de Jipété Jipété - Expert éminent sénior https://www.developpez.com
le 24/06/2018 à 10:52
Salut,

et bravo !
Bravo pour avoir trouvé le coup du TLazIntfImage, et bravo également pour tout le reste.

Hélas, il y a encore deux-trois bricoles et ça va être comme l'ascension du Mont-Blanc, les derniers mètres seront les plus difficiles...

Je me suis concentré uniquement sur le dossier des good89 (il y a sans doute des petites différences de contenu avec le tien, pour le moment on s'en moque), j'ai examiné 54 fichiers, et il y a des soucis de transparence avec balle :
zoomé à 800 %

et Animaux-0 et son problème de barre verticale présente ou absente à gauche dans le trou supérieur du B, zoomé à 800 % aussi : à gauche l'image 1, à droite l'image 0 :


Ce problème disparaît en affectant clWhite à la couleur transparente : cela ne devrait-il pas être fait automagiquement ?

Ensuite un souci avec "adapter dimension" qui ne fonctionne pas comme il faudrait :
  • pour les trop grandes images il faut le cocher sinon on en perd mais regarder une petite image ensuite ça va l'agrandir (avec effet de pixellisation) et il faut donc décocher.
  • pour les petites images il faut être décoché mais examiner ensuite des grandes images les tronque : il faut alors cocher.

Pour certaines images c'est évident qu'elles sont tronquées :

bell non coché
donc on coche,

SUN02 coché

pour d'autres ça n'est pas visible du tout (le feu d'artifice 38732719) et on ne pensera pas à jouer avec la case à cocher.

Bon dimanche, ne passe pas la journée là-dessus.
Avatar de BeanzMaster BeanzMaster - Membre émérite https://www.developpez.com
le 24/06/2018 à 11:58
Citation Envoyé par Jipété Voir le message
Salut,

et bravo !
Bravo pour avoir trouvé le coup du TLazIntfImage, et bravo également pour tout le reste.

Hélas, il y a encore deux-trois bricoles et ça va être comme l'ascension du Mont-Blanc, les derniers mètres seront les plus difficiles...

Je me suis concentré uniquement sur le dossier des good89 (il y a sans doute des petites différences de contenu avec le tien, pour le moment on s'en moque), j'ai examiné 54 fichiers, et il y a des soucis de transparence avec balle :
zoomé à 800 %

et Animaux-0 et son problème de barre verticale présente ou absente à gauche dans le trou supérieur du B, zoomé à 800 % aussi : à gauche l'image 1, à droite l'image 0 :
Ca je n'y peux rein les images sont comme ça

Citation Envoyé par Jipété Voir le message

Ce problème disparaît en affectant clWhite à la couleur transparente : cela ne devrait-il pas être fait automagiquement ?
Non je ne peux pas le savoir car gif sont marqués comme étant des gifs transparent

Citation Envoyé par Jipété Voir le message

Ensuite un souci avec "adapter dimension" qui ne fonctionne pas comme il faudrait :
  • pour les trop grandes images il faut le cocher sinon on en perd mais regarder une petite image ensuite ça va l'agrandir (avec effet de pixellisation) et il faut donc décocher.
  • pour les petites images il faut être décoché mais examiner ensuite des grandes images les tronque : il faut alors cocher.

Pour
bell non coché
donc on coche,
SUN02 coché

pour d'autres ça n'est pas visible du tout (le feu d'artifice 38732719) et on ne pensera pas à jouer avec la case à cocher.

Bon dimanche, ne passe pas la journée là-dessus.
Ok merci je vais regardé, car j'ai modifié les formules. C'est 3x rien ça juste un petit réajustement à faire

Bon dimanche

Avatar de BeanzMaster BeanzMaster - Membre émérite https://www.developpez.com
le 24/06/2018 à 12:00
En passant merci Gilles pour la mise en page et la mise en avant.

Avatar de Jipété Jipété - Expert éminent sénior https://www.developpez.com
le 24/06/2018 à 12:31
Citation Envoyé par BeanzMaster Voir le message
Non je ne peux pas le savoir car les gif sont marqués comme étant des gifs transparent


Voilà ce que je trouve dans le fichier gif89a.txt, concernant le Graphic Control Extension ligne 1218 et suivantes :
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
  4  |               |       Transparent Color Index       Byte
     +---------------+
     +---------------+
  0  |               |       Block Terminator              Byte
     +---------------+

      <Packed Fields>  =     Reserved                      3 Bits
                             Disposal Method               3 Bits
                             User Input Flag               1 Bit
                             Transparent Color Flag        1 Bit
Cela ne suffirait-il pas à notre bonheur ?

Pendant qu'on y est, ça concerne l'IHM mais je le mets ici quand même :

j'ai testé (va savoir pourquoi) le message d'erreur de FormDropFiles, et ça donne ça :


Tu vois écrit "Ok", toi ? Et "Abandonner" ? Moi pas.

Je suggère ça :
Code : Sélectionner tout
1
2
3
4
      MessageDlg('Erreur Inconnue : ' +
      //  #13 + #10 + 'Ok pour continuer' + #13 + #10 + 'Abandonner pour quitter l''application', mtError, [mbOK, mbAbort], 0);
        #13 + #10 + 'Valider pour continuer' + #13 + #10 + 'Annuler pour quitter l''application', mtError, [mbOK, mbCancel], 0);
      // TODO : if MessageDlg.Result = mbCancel then Application.Halt;
J'ai mis un TODO et un pseudo-code car F1 sur MessageDlg m'envoie dans les choux, donc je ne sais pas détecter le clic sur le bouton...

Et enfin, un mystère pour moi dans l'unité uFastBitmap :
le compilateur n'est pas content : Warning: Local variable "ColorRGB24" does not seem to be initialized et ça concerne la ligne 5 (312 du code)
Code : Sélectionner tout
1
2
3
4
5
6
7
procedure TColor32.Create(Color: TColor);
Var
  ColorRGB24 : TColorRGB24;
Begin
  ColorRGB24.Create(Color); // là !
  Create(ColorRGB24);
End;
Alors je tente ça, comme je le ferais pour une TStringlist par ex. (sl := TStringlist.Create;) :
Code : Sélectionner tout
1
2
3
4
5
6
7
8
procedure TColor32.Create(Color: TColor);
Var
  ColorRGB24 : TColorRGB24;
Begin
//  ColorRGB24.Create(Color);
  ColorRGB24 := TColorRGB24.Create(Color);
  Create(ColorRGB24);
End;
mais là ça ne compile plus du tout : Error: Incompatible types: got "untyped" expected "TColorRGB24" sur la ligne 6.
Pourquoi ?

Précisions :
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Type
  { TColorRGB24 : Définition d'un pixel sur 24 bits au format RGB }
  TColorRGB24Type = packed array[0..2] of byte;
  TColorRGB24 = packed record
    { Creation de la couleur }
    procedure Create(R,G,B : Byte); Overload;
    procedure Create(Color:TColor); Overload;

    { Conversion vers un TColor }
    function ToColor : TColor;

    Case Integer of
     0 : (V:TColorRGB24Type);    // Acces via Tableau
     1 : (Red,Green,Blue: Byte); // Acces via Composantes
  end;
et
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
Procedure TColorRGB24.Create(Color : TColor);
Var
  lr,lg,lb : Byte;
Begin
  lr := Color;
  lg := Color shr 8;
  lb := Color shr 16;
  Create(lr,lg,lb);
End;
Merci les gourous,
Avatar de BeanzMaster BeanzMaster - Membre émérite https://www.developpez.com
le 24/06/2018 à 12:52
Le bug du stretch est corrigé et le github mise à jour

Responsables bénévoles de la rubrique Lazarus : Alcatîz - Gilles Vasseur -