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 :

Problème avec PixelFormat [Lazarus]


Sujet :

Lazarus Pascal

  1. #1
    Membre émérite
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 122
    Par défaut Problème avec PixelFormat
    Bonjour à toutes et à tous,

    Avant que je n'étale encore ma prose sur le bugTracker, je me permets de soumettre à votre sagacité le petit programme ci-joint.

    Il charge une image et dès lors on peut changer son format d'image (pfDevice, pf24bit, pf32bit).

    Sous Windows et DELPHI 6 (testé seulement avec l'image bmp) tout fonctionne correctement. L'image se réaffiche dans le nouveau format.

    Avec Lazarus 0.9.30, que ce soit sous Windows XP ou sous Ubuntu 11.04 cela ne fonctionne pas avec aucun des types d'image fournis : bmp, jpg, gif, tif et png. Le format reste à celui initial et l'image disparaît.

    Autre problème : l'image jpg se trouve au format 32 bits sous Windows et en 24 bits sous Ubuntu ??? (tous les autres logiciels que j'ai (Ubuntu ou windows) m'indiquent une image en 24 bits).

    Si vous pouvez lz tester et me dire ce que vous trouvez ...

    Merci de votre aide.

    Pierre

  2. #2
    Membre émérite
    Avatar de CapJack
    Homme Profil pro
    Prof, développeur amateur vaguement éclairé...
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Prof, développeur amateur vaguement éclairé...
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Par défaut
    Effectivement, on obtient un rectangle noir quand on essaie de changer le format du bitmap "à la sauvage", ce qui est logique, puisque l'affectation de PixelFormat réinitialise le contenu du Bitmap.

    Il faut redessiner le bitmap après changement de format :
    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 TForm1.NbBitCloseUp(Sender: TObject);
    var Bmp : TBitmap;
    begin
      Bmp := TBitmap.Create;
      Bmp.Assign(Image.Picture.BitMap);
      case NbBit.ItemIndex of
       0: Image.Picture.BitMap.PixelFormat:= pf24bit;
       1: Image.Picture.BitMap.PixelFormat:= pf32bit;
       2: Image.Picture.BitMap.PixelFormat:= pfDevice;
      end;
      Image.Picture.Bitmap.Canvas.Draw(0,0,Bmp);
      case Image.Picture.BitMap.PixelFormat of
       pf24bit:  NbBit.ItemIndex:= 0;
       pf32bit:  NbBit.ItemIndex:= 1;
       pfDevice: NbBit.ItemIndex:= 2;
      end;
      Bmp.Free;
    end;
    De mémoire, c'était pareil sous les très anciennes versions de Delphi, la modification sauvage de PixelFormat est une fonctionnalité qui est venue plus tard, apparemment pas implémentée dans Lazarus.

    Je ne pense pas que ce soit un "bug", mais ça peut faire un "wish".

  3. #3
    Membre émérite
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 122
    Par défaut
    Merci CapJack pour cette modification. Effectivement, ça fonctionne correctement.

    Cordialement.

    Pierre

  4. #4
    Membre émérite
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 122
    Par défaut
    En fait, ce n'est pas si évident que cela.

    Tout content de la solution du re-dessin après le changement de format, j'ai voulu appliquer cela à mon programme de traitement d'image ...ça ne marche pas du tout ???

    J'ai recréé un petit programme reproduisant uniquement ces lignes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
      Bmp:= TBitmap.Create;
      Bmp.Assign(Image.Picture.BitMap);
      Image.Picture.BitMap.PixelFormat:= pf24bit;
      Image.Picture.Bitmap.Canvas.Draw(0, 0, Bmp);
      Bmp.Free;
    Et bien ça ne fonctionne pas non plus. Sur un format jpg en 32 bits, il refuse systématiquement de passer en 24 bits.

    Amusant par ailleurs, car comme cela ne fonctionne pas, on peut ne pas le retracer (Draw()), l'image reste !

    J'ai voulu recréer le petit programme que j'avais au départ pour en avoir le coeur net et voici mon constat :

    • Dans la méthode qui charge l'image, le changement de format n'agit pas.
    • Dans une méthode appelée après que l'image se soit affichée, le changement de format fonctionne !!


    Voir le petit programme modifié joint (NOTA, j'ai supprimé le précédent pour pouvoir mettre celui-ci).

    Avez-vous une explication à cela, comment faire pour y pallier ?
    Fichiers attachés Fichiers attachés

  5. #5
    Membre émérite
    Avatar de CapJack
    Homme Profil pro
    Prof, développeur amateur vaguement éclairé...
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Prof, développeur amateur vaguement éclairé...
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Par défaut
    Que le bitmap ne se redessine pas, c'est un peu normal, vu que tu as oublié le :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Bmp.Assign(Image.Picture.BitMap);


    Ceci étant, ça ne résout pas le problème. Si je trouve ne solution simple, je la poste... ce composant TBitmap de Laz m'a l'air passablement bogué !

    Edit : bon, je ne suis pas sûr de trouver. Il y a un truc bizarre avec la méthode Assign de Lazarus. Sous Delphi, pas de lézard, ça copie l'image, mais là, le comportement me semble erratique... je ne pige pas tout.

  6. #6
    Membre émérite
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 122
    Par défaut
    Citation Envoyé par CapJack Voir le message
    Que le bitmap ne se redessine pas, c'est un peu normal, vu que tu as oublié le :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Bmp.Assign(Image.Picture.BitMap);
    ...
    C'est vrai, je commence un peu à tourner en bourrique.
    Dans mes autres tests, je ne l'avais pas oublié et de toutes façons, ça ne change malheureusement rien au problème !

    Cordialement.

    Pierre

  7. #7
    Membre émérite
    Avatar de CapJack
    Homme Profil pro
    Prof, développeur amateur vaguement éclairé...
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Prof, développeur amateur vaguement éclairé...
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Par défaut
    Bon, aux grands maux les grands remèdes. Moi aussi, ça me fait un peu tourner en bourrique, cette histoire, parce que j'aimerais bien comprendre.

    Voilà une fonction qui copie méchamment un bitmap en forçant le format (enfin, j'espère, je finis par douter) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    procedure BmpCopy(const Src:TBitmap;
                      var   Dst:TBitmap;
                      const pxFormat:TPixelFormat);
     begin
       if not assigned(Src) then exit;
       if assigned(Dst) then Dst.Free;
       Dst := TBitmap.Create;
       Dst.PixelFormat := pxFormat;
       Dst.Width  := Src.Width;
       Dst.Height := Src.Height;
       Dst.Canvas.Draw(0,0,Src);
     end;
    Appliquée au premier projet, ça donne 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
     
    procedure TForm1.NbBitCloseUp(Sender: TObject);
    var Bmp : TBitmap; pxf : TPixelFormat;
    begin
     
      case NbBit.ItemIndex of
       0: pxf := pf24bit;
       1: pxf := pf32bit;
       2: pxf := pfDevice;
      end;
     
      Bmp := TBitmap.Create; // on peut mettre nil
      BmpCopy(Image.Picture.BitMap,Bmp,pxf);
      Image.Picture.Bitmap.PixelFormat := pxf;
      Image.Picture.Bitmap.Assign(Bmp);
      Bmp.Free;
     
      case Image.Picture.BitMap.PixelFormat of
      //case Bmp.PixelFormat of
       pf24bit:  NbBit.ItemIndex:= 0;
       pf32bit:  NbBit.ItemIndex:= 1;
       pfDevice: NbBit.ItemIndex:= 2;
      end;
     
    end;
    Appliquée au deuxième projet, ça donne cela :

    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
    procedure TForm1.OuvrirClick(Sender: TObject);
    var
      Bmp: TBitMap;
    begin
      OpenDialog.InitialDir:=ExtractFilePath(ParamStr(0));
      if OpenDialog.Execute then
      begin
        Image.Picture.LoadFromFile(OpenDialog.Filename);
        Bmp:= TBitMap.Create; // on peut mettre nil
        BmpCopy(Image.Picture.Bitmap,Bmp,pf24bit);
        Image.Picture.Bitmap.PixelFormat := pf24bit;
        Image.Picture.Bitmap.Assign(Bmp);
        Bmp.Free;
        case Image.Picture.Bitmap.PixelFormat of
         pf24bit : begin PF.Text:= 'pf24bit'; pf24.Checked:= True; end;
         pf32bit : begin PF.Text:= 'pf32bit'; pf32.Checked:= True; end;
         pfDevice: begin PF.Text:= 'pfDevice'; pfDe.Checked:= True; end;
        end;
        Nb.Text:= TailleReelle(Image.Picture.BitMap);
      end;
    end;
     
    procedure TForm1.pf24Change(Sender: TObject);
    var pxf : TPixelFormat;
    var
      Bmp: TBitMap;
    begin
     
      if pf24.Checked then pxf := pf24bit;
      if pf32.Checked then pxf := pf32bit;
      if pfDe.Checked then pxf := pfDevice;
     
      Bmp:= TBitMap.Create; // on peut mettre nil
      BmpCopy(Image.Picture.Bitmap,Bmp,pxf);
      Image.Picture.Bitmap.PixelFormat := pxf;
      Image.Picture.Bitmap.Assign(Bmp);
      Bmp.Free;
      case Image.Picture.Bitmap.PixelFormat of
       pf24bit : begin PF.Text:= 'pf24bit'; pf24.Checked:= True; end;
       pf32bit : begin PF.Text:= 'pf32bit'; pf32.Checked:= True; end;
       pfDevice: begin PF.Text:= 'pfDevice'; pfDe.Checked:= True; end;
      end;
      Nb.Text:= TailleReelle(Image.Picture.BitMap);
    end;
    Chez moi ça marche, mais vu le comportement erratique de la bête...

    Edit : un coup ça marche, un coup ça marche pas....
    http://62.166.198.202/view.php?id=15128
    En fait, il faut rajouter l'instruction qui modifie le PixelFormat du TImage.
    Je viens de le faire. Mais franchement, du coup je commence à me demander quel est le format réel du bitmap qu'on obtient en mémoire...

    Edit 2 : j'avais pas compris ta procédure TailleReelle... Astucieuse d'ailleurs, car multi-plate-forme.
    Moi, j'ai demandé à Windows de me confirmer avec ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    var  bm : Windows.BITMAP;
     
      ...
     
      Windows.GetObject(Image.Picture.Bitmap.Handle,SizeOf(bm),@bm);
      Label3.Caption := IntToStr(bm.bmBitsPixel);
    Et ça me renvoie le même résultat que TailleReelle. Double confirmation que les bitmaps sont au bon format, donc.

  8. #8
    Membre émérite
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 122
    Par défaut
    CapJack, j'ai testé chez moi dans les deux projets, ça fonctionne parfaitement. Ce qui est bien c'est que cela fonctionne dès le chargement. Apparemment, la raison de ce fonctionnement est que tu fais le changement de format au niveau du bitmap de transfert.

    Merci.

    Pierre

  9. #9
    Membre émérite
    Avatar de CapJack
    Homme Profil pro
    Prof, développeur amateur vaguement éclairé...
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Prof, développeur amateur vaguement éclairé...
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Par défaut
    Content d'avoir rendu service.

    Petite cerise sur le gâteau, si tu es aussi paresseux que moi, tu apprécieras la fonction suivante qui permet de s'affranchir des cinq lignes nécessaires à chaque fois :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    procedure ChangeImagePixelFormat(Image:TImage;pxf:TPixelFormat);
     var lBmp:TBitmap;
     begin
       lBmp := nil;
       try
        BmpCopy(Image.Picture.Bitmap,lBmp,pxf);
        Image.Picture.Bitmap.PixelFormat := pxf;
        Image.Picture.Bitmap.Assign(lBmp);
       finally
        if assigned(lBmp) then lBmp.Free;
       end;
     end;

    Du coup, le projet 2 devient :

    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
    procedure TForm1.OuvrirClick(Sender: TObject);
    begin
      OpenDialog.InitialDir:=ExtractFilePath(ParamStr(0));
      if OpenDialog.Execute then
      begin
     
        Image.Picture.LoadFromFile(OpenDialog.Filename);
        ChangeImagePixelFormat(Image,pf24bit);
     
        case Image.Picture.Bitmap.PixelFormat of
         pf24bit : begin PF.Text:= 'pf24bit'; pf24.Checked:= True; end;
         pf32bit : begin PF.Text:= 'pf32bit'; pf32.Checked:= True; end;
         pfDevice: begin PF.Text:= 'pfDevice'; pfDe.Checked:= True; end;
        end;
     
        Nb.Text:= TailleReelle(Image.Picture.BitMap);
      end;
    end;
     
    procedure TForm1.pf24Change(Sender: TObject);
    var pxf : TPixelFormat;
    begin
     
      if pf24.Checked then pxf := pf24bit;
      if pf32.Checked then pxf := pf32bit;
      if pfDe.Checked then pxf := pfDevice;
     
      ChangeImagePixelFormat(Image,pxf);
     
      case Image.Picture.Bitmap.PixelFormat of
       pf24bit : begin PF.Text:= 'pf24bit'; pf24.Checked:= True; end;
       pf32bit : begin PF.Text:= 'pf32bit'; pf32.Checked:= True; end;
       pfDevice: begin PF.Text:= 'pfDevice'; pfDe.Checked:= True; end;
      end;
     
      Nb.Text:= TailleReelle(Image.Picture.BitMap);
     
    end;

  10. #10
    Membre émérite
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 122
    Par défaut
    Je pense avoir été encore plus fainéant que toi :

    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
    procedure BmpXfr(var Dst: TImage; const pxFormat: TPixelFormat);
    var
      Bmp: TBitMap;
    begin
      Bmp:= TBitmap.Create;
      with Dst.Picture do
      begin
        Bmp.PixelFormat:= pxFormat;
        Bmp.Width := Bitmap.Width;
        Bmp.Height:= Bitmap.Height;
        Bmp.Canvas.Draw(0, 0, Bitmap);
        Bitmap.Assign(Bmp);
      end;
      Bmp.Free;
    end;
    Ce qui donne dans l'application :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        Image.Picture.LoadFromFile(OpenDialog.Filename);
        BmpXfr(Image, pf24bit {ou pxf});

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

Discussions similaires

  1. VC++ Direct3D8, problème avec LPD3DXFONT et LPD3DTEXTURE8
    Par Magus (Dave) dans le forum DirectX
    Réponses: 3
    Dernier message: 03/08/2002, 11h10
  2. Problème avec [b]struct[/b]
    Par Bouziane Abderraouf dans le forum CORBA
    Réponses: 2
    Dernier message: 17/07/2002, 10h25
  3. Problème avec le type 'Corba::Any_out'
    Par Steven dans le forum CORBA
    Réponses: 2
    Dernier message: 14/07/2002, 18h48
  4. Problème avec la mémoire virtuelle
    Par Anonymous dans le forum CORBA
    Réponses: 13
    Dernier message: 16/04/2002, 16h10

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