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 :

Comment travailler avec un bmp mal formé, si on ne le sait pas [Lazarus]


Sujet :

Lazarus Pascal

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 132
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 132
    Par défaut Comment travailler avec un bmp mal formé, si on ne le sait pas
    Bonjour,

    (cette nouvelle discussion part d'un court échange dans le fil du composant TGifViewer, mais pour ne pas le polluer je redémarre ici, avec un soupçon d'édition des échanges.)

    Je voulais voir comment réagit le TFastBitmap proposé par BeanzMaster avec un .bmp mal formé, et la conclusion que j'en tire est la suivante : à gauche avec un TBitmap, à droite avec le TFastbimap (qui "rend" comme un TLazInftImage), en bas au milieu le viewer de Linux.

    Nom : tbitmap_vs_tfastbitmap2.png
Affichages : 723
Taille : 130,4 Ko

    Réponse intégrale de BeanzMaster recopiée ici pour comprendre la suite :
    Citation Envoyé par BeanzMaster Voir le message
    Je ne sais pas comment tu charges les BMP, mais il faut que tu fasses attention à l'ordre des composantes de couleur. Dans les fichiers BMP les couleurs sont codée au format BGR TFastBitmap sous linux est au format RGBA. Il faut donc inverser le Rouge et Bleu (procedure SwapRB) ou le faire dans ta procédure de chargement. Note le bmp que tu nous montre "FondRVB.Bmp" n'est pas mal formé c'est Lazarus qui le lit mal. Et comme je te l'ai dis jette un oeil dans BZImageFileBMP.pas que je t'ai passé. Je l'ai justement blindé de commentaires parce que j'en ai ch.... Tu y trouveras plein d'informations qui t'aideront, j'en suis sure avec ce format qui semble pourtant facile à prendre en charge. Il reste encore quelques erreurs notamment avec la compression RLE dans certain cas ou je ne gère pas les erreurs d'encodage correctement et quelques couleurs que je n'ai pas inversé (surtout les bmp os22x 8bits)

    Si tu veux des BMP bizarres et hors normes à tester : https://github.com/jdelauney/BMP-ImageTestSuite
    J'ai écrit "mal formé" dans le titre, Jérome n'est pas d'accord mais je ne vois pas quoi mettre d'autre, on en parle dans la suite...

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 132
    Par défaut
    Citation Envoyé par BeanzMaster Voir le message
    Je ne sais pas comment tu charges les BMP, mais il faut que tu fasses attention à l'ordre des composantes de couleur.
    Je fais comme un pimpin qui n'est pas au courant, y a qu'à voir cet exemple de la page du wiki), utilisé ainsi (en détournant le projet GifViewer pour un accès simple à uFastBitmap) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    procedure TForm1.Button1Click(Sender: TObject);
    var
     fbmp: TFastBitmap;
     bmp: TBitmap;
    begin
      bmp:= TBitmap.Create;
      bmp.LoadFromFile('/chemin/FondRVB32bad.bmp');// fic d'origine s'appelle FondRVB.bmp, le mien c'est le même juste renommé
      pnlView.Canvas.Draw(0,0,bmp);
      fbmp:= TFastBitmap.Create;
      fbmp.ImportFromBitmap(bmp);
      fbmp.Draw(pnlView.Canvas, 300,0);
    end;
    Citation Envoyé par BeanzMaster Voir le message
    Note le bmp que tu nous montre "FondRVB.Bmp" n'est pas mal formé c'est Lazarus qui le lit mal.
    Je l'appelle "mal formé" parce que je ne sais pas comment l'appeler, d'autant plus qu'étant codé sur 32 bits, le simple fait de l'exporter sans rien changer depuis The Gimp vers un autre fichier rend celui-ci conforme à ce qu'on doit voir. La différence (il y en a une) c'est l'offset des datas dans le fichier : 54 pour le mauvais, 122 pour le bon. Mais à partir de là les datas sont identiques (difficile d'en juger car il y a une bande blanche de 28 px de haut au début de l'image)

    Citation Envoyé par BeanzMaster Voir le message
    Et comme je te l'ai dis jette un oeil dans BZImageFileBMP.pas que je t'ai passé.
    Non. Tant qu'il ne fait pas partie de la distrib officielle, je ne sors pas des rails.

    Citation Envoyé par BeanzMaster Voir le message
    Si tu veux des BMP bizarres et hors normes à tester : https://github.com/jdelauney/BMP-ImageTestSuite
    J'ai déjà. On verra ça plus tard.

    Pour le moment, on note que sur un simple coup d'œil il est impossible de distinguer un original mal fichu mais correctement ouvert avec TLazIntfImage/TFastBitmap si on met à part l'inversion R<>B, versus un rendu avec le viewer de Linux, ou avec The Gimp, ou avec ImageJ.

    Comment font ces logiciels, que le couple FreePascal/Lazarus n'est pas capable de reproduire ?
    Sur quelles données du fichier se basent-ils ?

    Pour y voir clair, l'éditeur hexa, en haut sur le bad (les données commencent à 5E9A), en bas sur le good (à 5EDE) (Note : 122-54=6810 soit 4416, et 5E9A+44=5EDE).
    J'ai coloré (en vieux rose, bleu pâle et beige) les 3 premiers pixels, on voit bien qu'il n'y a aucune différence, alors sur quoi se base FreePascal ?
    Nom : compar_fondRVB.png
Affichages : 563
Taille : 64,4 Ko

    Pour essayer de le savoir, j'ai doublé mon test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    procedure TMainForm.Button1Click(Sender: TObject);
    var
     fbmp: TFastBitmap;
     bmp: TBitmap;
    begin
      bmp:= TBitmap.Create;
      bmp.LoadFromFile('/datas/_share_4_VM/Programmation/FondRVB32bad.bmp');// fic d'origine s'appelle FondRVB.bmp, le mien c'est le même juste renommé
      pnlView.Canvas.Draw(0,0,bmp);
      fbmp:= TFastBitmap.Create;
      fbmp.ImportFromBitmap(bmp);
      fbmp.Draw(pnlView.Canvas, 300,0);
      fbmp.Free;
      bmp.Free;
     
      bmp:= TBitmap.Create;
      bmp.LoadFromFile('/datas/_share_4_VM/Programmation/FondRVB32_ok.bmp');// généré par The Gimp depuis le fic d'origine
      pnlView.Canvas.Draw(0,300,bmp);
      fbmp:= TFastBitmap.Create;
      fbmp.ImportFromBitmap(bmp);
      fbmp.Draw(pnlView.Canvas, 300,300);
      fbmp.Free;
      bmp.Free;
    end;
    mais ça coince sur la ligne fbmp.ImportFromBitmap(bmp); :
    Nom : erreur_sur_ok.png
Affichages : 621
Taille : 126,5 Ko

    et là, ça me dépasse.
    Tiens, je recopie l'endroit concerné :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    procedure TColor32.SetColorComponent(Index: Integer; aValue: Byte);
    Begin
      v[Index] := aValue; // ligne 317 c'est elle
    End;
    Au moment du plantage l'index vaut 3 et aValue 255.

    On notera que le TBitmap a correctement affiché l'image, cette fois.

  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
    Salut, je vais répondre message par message

    Citation Envoyé par Jipété Voir le message
    Je fais comme un pimpin qui n'est pas au courant, y a qu'à voir cet exemple de la page du wiki), utilisé ainsi (en détournant le projet GifViewer pour un accès simple à uFastBitmap) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    procedure TForm1.Button1Click(Sender: TObject);
    var
     fbmp: TFastBitmap;
     bmp: TBitmap;
    begin
      bmp:= TBitmap.Create;
      bmp.LoadFromFile('/chemin/FondRVB32bad.bmp');// fic d'origine s'appelle FondRVB.bmp, le mien c'est le même juste renommé
      pnlView.Canvas.Draw(0,0,bmp);
      fbmp:= TFastBitmap.Create;
      fbmp.ImportFromBitmap(bmp);
      fbmp.Draw(pnlView.Canvas, 300,0);
    end;

    Je l'appelle "mal formé" parce que je ne sais pas comment l'appeler, d'autant plus qu'étant codé sur 32 bits, le simple fait de l'exporter sans rien changer depuis The Gimp vers un autre fichier rend celui-ci conforme à ce qu'on doit voir. La différence (il y en a une) c'est l'offset des dats dans le fichier : 54 pour le mauvais, 122 pour le bon. Mais à partir de là les datas sont identiques (difficile d'en juger car il y a une bande blanche de 28 px de haut au début de l'image)
    Pourquoi 54 et 122 ? 54 Correspond à un BMP version 1 et 122 à un BMP Version 4

    D'abord on à un en-tête commun

    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
    Type
      { L'entête principale d'un fichier BMP est composée de 4 champs :@br
        - La signature (sur 2 octets), indiquant qu'il s'agit d'un fichier BMP à l'aide de 2 caractères :
        @unorderedList(
          @item( BM $424D en hexadécimal, indique qu'il s'agit d'un Bitmap Windows.)
          @item( BA $4241 indique qu'il s'agit d'un Bitmap OS/2.)
          @item( CI $4349 indique qu'il s'agit d'une icone couleur OS/2.)
          @item( CP $4350 indique qu'il s'agit d'un pointeur de couleur OS/2.)
          @item( IC $4943 indique qu'il s'agit d'une icone OS/2.)
          @item( PT $5054 indique qu'il s'agit d'un pointeur OS/2.)
        - La taille totale du fichier en octets (codée sur 4 octets)@br
        - 2 champs réservés (de 2 octets)@br
        - L'offset de l'image (sur 4 octets), en français décalage }
      TBZBMPFileHeader = Packed Record   // < Taille de l'en-tête commune 14 octets
        bfType: Array[0..1] Of Char;  // bfType, Normalement Word;@brEn déclarant un array of char on evite de se prendre la tête avec  le "Little et Big Endian"
        bfSize: Longword;                // Taille totale du fichier
        bfReserved1: Word;             // Hospot X -> OS2x
        bfReserved2: Word;             // Hospot Y -> OS2x
        bfOffBits: Longword;           // Position des données de l'image dans le fichier
      End;
    L'en-tête pour la version 1

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
      { En-têtes BMP OS/2 V2@br
        biSize: LongWord; Taille de l'en-tête  =  40 octets  }
      TBZWindowsBMPInfoHeaderV1 = Packed Record   // Ici Taille 36, biSize est lu avant
        biWidth: Longint;                     // Largeur de l'image en pixels
        biHeight: Longint;                   // Hauteur de l'image en pixels
        biPlanes: Word;                      // Nombre de Plans de couleur  = 1
        biBitCount: Word;                   // Nombre de bits par pixel
        biCompression: Longword;      // Type de compression
        biSizeImage: Longword;         // Taille de l'image  AVEC LE PADDING
        biXPixelsPerMeter: Longint;     // Nombre de pixel horizontal par mètre
        biYPixelsPerMeter: Longint;     // Nombre de pixel vertical par mètre
        biClrUsed: Longword;             // Nombre de couleurs utilisées (0 = toutes)
        biClrImportant: Longword;      // Nombre de couleurs importantes (0 = toutes)
      End;
    40 + 14 = 54 octets

    L'en-tête pour la version 4

    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
      { Definitions pour la prise en charge type de couleur spéciale CIExyz@br
       dans les en-têtes Windows V4 et V5
       @groupbegin }
      TBZBMP_CIEXYZCoord = Packed Record
        X: Longint;
        Y: Longint;
        Z: Longint;
      End;
     
      TBZBMP_CIEXYZCoordTriple = Packed Record
        CRed: TBZBMP_CIExyzCoord;
        CGreen: TBZBMP_CIExyzCoord;
        CBlue: TBZBMP_CIExyzCoord;
      End;
     
      { En-tête BMP Windows V4@br
        biSize: LongWord; Taille de l'en-tête  = 108 octets }
      TBZWindowsBMPInfoHeaderV4 = Packed Record   //< Ici Taille 104, biSize est lu avant
        biWidth: Longint;                         // Largeur de l'image en pixels
        biHeight: Longint;                       // Hauteur de l'image en pixels
        biPlanes: Word;                          // Nombre de Plans de couleur  = 1
        biBitCount: Word;                       // Nombre de bits par pixel
        biCompression: Longword;          // Type de compression
        biSizeImage: Longword;             // Taille de l'image  AVEC LE PADDING peut être 0 si pas de compression
        biXPixelsPerMeter: Longint;        // hoizontal pixels per meter
        biYPixelsPerMeter: Longint;        // vertical pixels per meter
        biClrUsed: Longword;                // Nombre de couleurs utilisées (0 = toutes)
        biClrImportant: Longword;        // Nombre de couleurs importantes (0 = toutes)
        biRedMask: Longword;              // Masque Couleur Rouge
        biGreenMask: Longword;          //< Masque Couleur Vert
        biBlueMask: Longword;            //< Masque Couleur Bleu
        biAlphaMask: Longword;          //< Masque Couleur Alpha
        biCSType: Longword;              //< Type de l'espace de couleur CIE
        biEndpoints: TBZBMP_CIEXYZCoordTriple; //< "Color space endpoints"
        biGammaRed: Longword;            // Correction Gamma Rouge
        biGammaGreen: Longword;        // Correction Gamma Vert
        biGammaBlue: Longword;          // Correction Gamma Bleu
      End;
    On à donc bien 14 + 108 = 122 octets

    La différence est là, si les datas sont identiques, c'est ce que je te disais le bmp n'est pas mal formé, mais mal lu. C'est histoire de hachure viens du fait que Lazarus le prend pour un 24 bit alors que c'est un 32 bit
    On avait d'ailleurs déja bien galérer ici

    Citation Envoyé par Jipété Voir le message
    Pour le moment, on note que sur un simple coup d'œil il est impossible de distinguer un original mal fichu mais correctement ouvert avec TLazIntfImage/TFastBitmap si on met à part l'inversion R<>B, versus un rendu avec le viewer de Linux, ou avec The Gimp, ou avec ImageJ.

    Comment font ces logiciels, que le couple FreePascal/Lazarus n'est pas capable de reproduire ?
    Sur quelles données du fichier se basent-ils ?

    Pour y voir clair, l'éditeur hexa, en haut sur le bad (les données commencent à 5E9A), en bas sur le good (à 5EDE) (Note : 122-54=6810 soit 4416, et 5E9A+44=5EDE).
    J'ai coloré (en vieux rose, bleu pâle et beige) les 3 premiers pixels, on voit bien qu'il n'y a aucune différence, alors sur quoi se base FreePascal ?
    Lazarus se prend les pied à cause de son calcul avec la composante Alpha et certain BMP codés en 32bits

    Citation Envoyé par Jipété Voir le message
    Pour essayer de le savoir, j'ai doublé mon test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    procedure TMainForm.Button1Click(Sender: TObject);
    var
     fbmp: TFastBitmap;
     bmp: TBitmap;
    begin
      bmp:= TBitmap.Create;
      bmp.LoadFromFile('/datas/_share_4_VM/Programmation/FondRVB32bad.bmp');// fic d'origine s'appelle FondRVB.bmp, le mien c'est le même juste renommé
      pnlView.Canvas.Draw(0,0,bmp);
      fbmp:= TFastBitmap.Create;
      fbmp.ImportFromBitmap(bmp);
      fbmp.Draw(pnlView.Canvas, 300,0);
      fbmp.Free;
      bmp.Free;
     
      bmp:= TBitmap.Create;
      bmp.LoadFromFile('/datas/_share_4_VM/Programmation/FondRVB32_ok.bmp');// généré par The Gimp depuis le fic d'origine
      pnlView.Canvas.Draw(0,300,bmp);
      fbmp:= TFastBitmap.Create;
      fbmp.ImportFromBitmap(bmp);
      fbmp.Draw(pnlView.Canvas, 300,300);
      fbmp.Free;
      bmp.Free;
    end;
    et là, ça me dépasse.
    Tiens, je recopie l'endroit concerné :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    procedure TColor32.SetColorComponent(Index: Integer; aValue: Byte);
    Begin
      v[Index] := aValue; // ligne 317 c'est elle
    End;
    Au moment du plantage l'index vaut 3 et aValue 255.

    On notera que le TBitmap a correctement affiché l'image, cette fois.
    C'est sur le 1er ou le 2eme appel que tu te prend le SIGSEGV ?

    Sin en partant de ton BMP fournit ici Je suppose que c'est bien le même

    Sous windows l'affichage est correcte avec

    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 TMainForm.Button1Click(Sender: TObject);
    var
     fbmp: TFastBitmap;
     bmp: TBitmap;
    begin
      bmp:= TBitmap.Create;
      bmp.LoadFromFile('/datas/_share_4_VM/Programmation/FondRVB32bad.bmp');// fic d'origine s'appelle FondRVB.bmp, le mien c'est le même juste renommé
      pnlView.Canvas.Draw(0,0,bmp);
      fbmp:= TFastBitmap.Create;
      fbmp.ImportFromBitmap(bmp);
      fbmp.Draw(pnlView.Canvas, 300,0);
      fbmp.Free;
      bmp.Free;
    end;
    Nom : 2018-07-12_154514.jpg
Affichages : 581
Taille : 27,4 Ko

    Comme on peux le voir ici par d'inversion R et B. Il faudra donc que je revois ma copie pour "ImportFromBitmap" ici c'est correct car le format de FastBitmap est BGRA donc identique à celui du bitmap.

    Je vais allez tester sous Linux et je ferais un petit edit

    EDIT : De retour sous linux

    Premier test sans rien changer :

    Nom : Screenshot_20180712_161714.jpeg
Affichages : 619
Taille : 35,2 Ko

    Maintenant petite rectification à faire dans uFastBitmap

    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
    Function TFastBitmap.ImportFromRawImage(Const ARawImage: TRawImage): Boolean;
    var
      BufferData : PByte;
    begin
      SetSize(ARawImage.Description.Width,ARawImage.Description.Height);
      result:=false;
      // On verifie si la taille des deux tampons sont identique
      // Si ce n'est pas le cas, cela veut dire que le TRawImage n'est pas au format 32bit
      if (ARawImage.DataSize= FSize) then
      begin
        try
          BufferData := PByte(Self.getSurfaceBuffer);
          Move(ARawImage.Data^, BufferData^, self.Size);
          {$IFDEF WINDOWS}
               if (ARawImage.Description.RedShift = 0) and ((ARawImage.Description.BlueShift = 16)) then Self.SwapRB; // Le RawImage est-il en RGB, si oui on échange
          {$ELSE}       
              if (ARawImage.Description.RedShift = 16) and ((ARawImage.Description.BlueShift = 0)) then Self.SwapRB; // Le RawImage est-il en BGR, si oui on échange
          {$ENDIF}
        finally
          result:=true;
        end;
      end;
    End;
    Résultat

    Nom : Screenshot_20180712_162638.jpeg
Affichages : 599
Taille : 35,2 Ko

    RE-EDIT : Afin d'être synchrone j'ai fais un zip du petit test à decompresser dans un sous dossier du dossier Demos de TGIFViewer : BMPTest.zip
    • "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
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 132
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 132
    Par défaut
    Yop !

    Citation Envoyé par BeanzMaster Voir le message
    C'est sur le 1er ou le 2eme appel que tu te prends le SIGSEGV ?
    Sur le 2e. Je ne l'ai pas indiqué ? Désolé, ça me semblait évident, puisque le 2e appel est rajouté sous le 1er et ses deux images moisies, l'une avec ses traits et l'autre avec ses couleurs inversées.
    Allez, au boulot,
    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
    procedure TMainForm.Button1Click(Sender: TObject);
    var
     fbmp: TFastBitmap;
     bmp: TBitmap;
    begin
      bmp:= TBitmap.Create;
      bmp.LoadFromFile('/datas/_share_4_VM/Programmation/FondRVB32bad.bmp'); // fic d'origine s'appelle FondRVB.bmp, le mien c'est le même juste renommé
      pnlView.Canvas.Draw(0,0,bmp);  // traits à gauche
     
      fbmp:= TFastBitmap.Create;
      fbmp.ImportFromBitmap(bmp);
      fbmp.Draw(pnlView.Canvas, 300,0);  // couleurs inversées à droite
      fbmp.Free;
      bmp.Free;
     
      bmp:= TBitmap.Create;
      bmp.LoadFromFile('/datas/_share_4_VM/Programmation/FondRVB32_ok.bmp');// généré par The Gimp depuis le fic d'origine
      pnlView.Canvas.Draw(0,300,bmp);
      fbmp:= TFastBitmap.Create;
      fbmp.ImportFromBitmap(bmp); // SIGSEGV là ! <<<<<<<<<<<<<<<<<<
      fbmp.Draw(pnlView.Canvas, 300,300);
      fbmp.Free;
      bmp.Free;
    end;

    Citation Envoyé par BeanzMaster Voir le message
    Sinon en partant de ton BMP fourni ici je suppose que c'est bien le même
    Quelle mémoire ! Je ne me souvenais pas d'avoir déjà parlé de ça : je tourne en rond et je marche dans mes traces, comme les Dupond dans je ne sais plus quel Tintin On a marché sur la Lune...
    Et oui, c'est tout-à-fait ça.

    Citation Envoyé par BeanzMaster Voir le message
    Sous windows l'affichage est correcte avec
    Sous Windows l'affichage est toujours correct, !

    Citation Envoyé par BeanzMaster Voir le message
    Maintenant petite rectification à faire dans uFastBitmap
    En effet c'est bon, maintenant. Et j'ai récupéré ton prog de test, mais une dernière question : comment faire en sorte que l'affichage ne disparaisse pas quand on recouvre puis découvre la fenêtre ? Le panel ne "maintient" pas l'image...
    EDIT :
    Citation Envoyé par BeanzMaster Voir le message
    Maintenant petite rectification à faire dans uFastBitmap
    si je peux me permettre :
    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
    Function TFastBitmap.ImportFromRawImage(Const ARawImage: TRawImage): Boolean;
    var
      BufferData : PByte;
    begin
      SetSize(ARawImage.Description.Width,ARawImage.Description.Height);
      result:=false;
      // On verifie si les tailles des deux tampons sont identiques
      // Si ce n'est pas le cas, cela veut dire que le TRawImage n'est pas au format 32bit et donc qu'est-ce qu'on fait ?
      if (ARawImage.DataSize= FSize) then
      begin
        try
          BufferData := PByte(Self.getSurfaceBuffer);
          Move(ARawImage.Data^, BufferData^, self.Size);
          {$IFDEF WINDOWS}
             if (ARawImage.Description.RedShift = 0)  and ((ARawImage.Description.BlueShift = 16)) then Self.SwapRB; // Le RawImage est-il en RGB, si oui on échange
          {$ELSE}       
             if (ARawImage.Description.RedShift = 16) and ((ARawImage.Description.BlueShift = 0))  then Self.SwapRB; // Le RawImage est-il en BGR, si oui on échange
          {$ENDIF}
        finally
          result:=true;
        end;
      // end;
      end else // tailles différentes
      begin
      // qu'est-ce qu'on fait ?
      end;
    End;
    /EDIT

    Citation Envoyé par BeanzMaster Voir le message
    A l'heure actuelle TLazIntfImage est la meilleure solution pour la gestion des bitmap surtout sous Linux, on a vu le problème lié à la transparence dans TGifViewer.
    Non, puisqu'il se plante sur l'inversion des couleurs R<>B comme je l'ai montré dans le 1er post (le triangle en haut à gauche doit être dans les orange-marron et pas bleu !)
    Oui, je sais, cette image abstraite est très trompeuse, affichée seule s'il n'y a pas le bout de noir en bas à droite, on se trompe facilement !

    Citation Envoyé par BeanzMaster Voir le message
    Ca c'est un erreur qui vient de la FCL, surement une petite embrouille avec un TRect dans le code du TLazIntfImage. J'ai fait quelques tests il y a 1 ou 2 semaine en utilisant juste la FCL cf chez les voisins
    Ouaip, j'ai tout lu, j'ai même récupéré un petit prog en fin de 1re page, mais il a le même problème qu'ici.
    Par contre, quelqu'un t'a suggéré la librairie Vampyre et je dois dire que celle-ci ouvre correctement le fichier bad ! Pas de traits verticaux, pas d'inversion de couleurs avec la démo Image_Browser (qui remonte un format A8R8G8B8 pour ce fichier maudit).

    Nom : fondrvb_sur_vampyre.png
Affichages : 526
Taille : 42,6 Ko

  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
    Citation Envoyé par Jipété Voir le message
    Yop !


    Sur le 2e. Je ne l'ai pas indiqué ? Désolé, ça me semblait évident, puisque le 2e appel est rajouté sous le 1er et ses deux images moisies, l'une avec ses traits et l'autre avec ses couleurs inversées.

    Non, puisqu'il se plante sur l'inversion des couleurs R<>B comme je l'ai montré dans le 1er post (le triangle en haut à gauche doit être dans les orange-marron et pas bleu !)
    Oui, je sais, cette image abstraite est très trompeuse, affichée seule s'il n'y a pas le bout de noir en bas à droite, on se trompe facilement !

    Allez, au boulot,
    Ok je vais tester. Juste une petite question le fichier générer avec Gimp quelles options as tu appliqué ? 32 bits --> X8 R8 G8 B8 ?

    Citation Envoyé par Jipété Voir le message
    En effet c'est bon, maintenant. Et j'ai récupéré ton prog de test, mais une dernière question : comment faire en sorte que l'affichage ne disparaisse pas quand on recouvre puis découvre la fenêtre ? Le panel ne "maintient" pas l'image...
    Il faut passer par l'évènement OnPaint du panel. Et dans le formCreate ajouter Doublebuffered := true;
    Citation Envoyé par Jipété Voir le message
    EDIT :

    si je peux me permettre :
    Il faudrait en effet rajouté un commentaire comme quoi cette fonction marche qu'avec des bitmap 32 bits. Ou faudrait que je la passe dans protected afin qu'elle ne soit pas disponible pour l'utilisateur final. Si tu regardes ImportFromBmp tu remarqueras que tous les bitmaps différents de 32 bits est convertit dans ce format avant d'appeler ImportFromRawImage. Et ce tout simplement car notre TFastBitmap est en 32 bits.


    Citation Envoyé par Jipété Voir le message
    Ouaip, j'ai tout lu, j'ai même récupéré un petit prog en fin de 1re page, mais il a le même problème qu'ici.
    Par contre, quelqu'un t'a suggéré la librairie Vampyre et je dois dire que celle-ci ouvre correctement le fichier bad ! Pas de traits verticaux, pas d'inversion de couleurs avec la démo Image_Browser (qui remonte un format A8R8G8B8 pour ce fichier maudit).
    Effectivement JP me l'a suggéré , mais vu que je bosse sur ma solution. Bref un si jamais tu as toujours DragZNView sous la main tu peux également tester avec (même si je sais que certain BMP ne s'afficheront pas correctement avec la version que je t'ai passé)

    Là il me remonte un format BGRA et on peux le vérifier avec les infos "bitfields" maintenant Vampyre renvoie l'inverse ARGB <> BGRA. Et pour ce coup je suis sûre des infos remontés par mes outils car sinon l'affichage serait en vrac

    Nom : 2018-07-12_225232.jpg
Affichages : 613
Taille : 135,6 Ko
    • "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 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
    Pour le SIGSegv c'est une erreur d'inattention de ma part.

    Dans Function TFastBitmap.ImportFromBitmap(Const ABitmap: Graphics.TBitmap): Boolean;il faut modifier la sous procedure setAlpha 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
      procedure SetAlpha(Value : Byte);
      var
        i : Integer;
        PixPtr : PColor32;
        maxi : Integer;
      begin
        i:=0;
        Maxi := (FWidth * FHeight)-1;
        PixPtr :=PColor32(FData);// Self.GetScanLine(0);
        While i<Maxi do
        begin
          PixPtr^.Alpha:= Value;
          inc(PixPtr);
          inc(i);
        end;
      end;
    Et oui j'avais prix FSize comme référence qui la taille du tampon en octet et non le nombre total de pixel. On pourrais d'ailleurs rajouté une variable dans FTotalPixel ou un truc dans le genre dans Private ou protected et qui serait calculée dans la procedure SetSizeSinon ce qui est drôle c'est que cette procédure est appelée seulement si le TBitmap n'est pas un 32 Bits

    Voilà d'ailleurs les infos du RawImage.Description du TBitmap

    Nom : 2018-07-12_233050.jpg
Affichages : 548
Taille : 50,9 Ko

    Il est clair que Lazarus se prend les pieds dans le tapis avec ce genre de bmp et fait sa mayonnaise interne

    et voila les infos retournées par DragZNView

    Nom : 2018-07-12_233648.jpg
Affichages : 962
Taille : 73,8 Ko
    • "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

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 132
    Par défaut
    Bonjour,

    Citation Envoyé par BeanzMaster Voir le message
    Par contre j'ai fait un petit changement pour vérifier
    dans ImagingFormats.pas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    function Has32BitImageAlpha(NumPixels: LongInt; Data: PLongWord): Boolean;
        if (Byte(Data^ shr 24)) > 0 then // Extraction du canal alpha des données
    Ah ouais, pas mal !

    +++
    Ce matin j'ai repris la discussion depuis le début (car au bout du compte, si Vampyre c'est la croix et la bannière à utiliser à cause de l'aide pas à jour et des exemples en vrac, je vais peut-être le zapper), et je me suis rendu compte d'une bêtise là :

    Citation Envoyé par Jipété Voir le message
    Citation Envoyé par BeanzMaster Voir le message
    A l'heure actuelle TLazIntfImage est la meilleure solution pour la gestion des bitmap surtout sous Linux, on a vu le problème lié à la transparence dans TGifViewer.
    Non, puisqu'il se plante sur l'inversion des couleurs R<>B comme je l'ai montré dans le 1er post (le triangle en haut à gauche doit être dans les orange-marron et pas bleu !)
    En fait cette inversion R <> B est due à une mauvaise utilisation de ma part, pour cause d'ignorance.
    Et je m'en sors comme ça, c'est assez amusant car, oui, j'ai remarqué que le xrgb est affiché en gris selon comment j'initialise le TLazIntfImage ! :
    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
     
        try
          if OffsetToDatas = 54 then begin // fichier d'origine sans infos de couleur -- 122 pour le bgra, 138 pour le xbgr
            lii := TLazIntfImage.Create(0,0);
            lii.DataDescription := GetDescriptionFromDevice(0);
            lii.LoadFromFile(opd.FileName);
          end else begin
            lii := bmpFic.CreateIntfImage; // bmpFic c'est le bitmap d'origine qui fonctionne bien sauf quand le fichier source n'a pas les infos de couleur
            lii.LoadFromBitmap(bmpFic.Handle, bmpFic.Handle, bmpFic.Width, bmpFic.Height);
          end;
     
          with img4result do begin // TImage d'affichage final
            Picture.Clear;
            Picture.Bitmap.LoadFromIntfImage(lii);
          end;
     
        finally
          lii.Free;
        end;
    Et voilà.
    Résultat, , héhé !

    Me reste plus qu'à creuser l'enregistrement sur disque d'un fichier LazIntfImage car l'enregistrement du TImage fait sauter le canal Alpha,

    Bon week-end, merci à tous, gros bisous, toussa toussa,

  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,
    Citation Envoyé par Jipété Voir le message
    Bonjour,

    ...

    Me reste plus qu'à creuser l'enregistrement sur disque d'un fichier LazIntfImage car l'enregistrement du TImage fait sauter le canal Alpha,

    Bon week-end, merci à tous, gros bisous, toussa toussa,
    Pour la sauvegarde essayes comme ça (cf dans l'unité IntfGraphics)

    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
        var
            BmpHnd,MaskHnd: HBitmap;
            Bitmap1: TBitmap;
            IntfImg1: TLazIntfImage;
            Writer: TLazWriterBMP; // Basé sur TFPWriterBMP de FPC dans l'unité FPWriteBMP du dossier fcl-image/src/
          begin
            ...
            // create the raw image
            IntfImg1:=TLazIntfImage.Create(0,0,[]);
            // load the raw image from the bitmap handles
            IntfImg1.LoadFromBitmap(Bitmap1.Handle,Bitmap1.MaskHandle);
            // create the BMP writer
            Writer:=TLazWriterBMP.Create;
            // save image to file
            IntfImg1.SaveToFile('filename.BMP',Writer);
            // clean up
            Writer.Free;
            IntfImg1.Free;
          end;
    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

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 132
    Par défaut
    Bonjour,

    voilà donc mon writer modifié : myfpwritebmp.pas.zip

    C'est une copie du FPwriterBMP.pp à laquelle j'ai rajouté 2 ou 3 fonctions et procédures pour gérer le xbgr, plus des ajustements dans des méthodes existantes, et tout ce que j'ai ajouté ou modifié est repéré par la chaîne "jpt".

    Il y a des commentaires, mais j'aimerais bien un coup de main pour finir l'annotation des masks dans SetupXBGR32bpp, en s'inspirant du Setup16bpp existant car j'avoue que ces histoires de masks, entre le LittleEndian et le BigEndian, une chatte n'y retrouverait pas ses petits.
    J'ai réussi à pondre une explication pas piquée des vers concernant le remplacement des bytes RGBA par les bytes XBGR pour qu'ils "tombent" au bon endroit dans le fichier, vous m'en direz des nouvelles, ligne 140.

    Pour l'utiliser, je fais comme ça :
    1. j'ouvre un fichier .bmp, je récupère les datas du header et je fais afficher son image dans un TImage ;
    2. il y a un clic-droit associé au TImage qui peut ouvrir un TSavePictureDialog ;
    3. auquel cas,
      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
        procedure Enregistre(b:TBitmap; fic:string); // infos Header : LCLType ligne 1280
        var
          lii: TLazIntfImage;
          Writer: TmyLazWriterBMP; // Basé sur TFPWriterBMP de FPC dans l'unité FPWriteBMP du dossier fcl-image/src/
          //ImgFormatDescription: TRawImageDescription; semble inutile
        begin
          //b.SaveToFile(fic); // pour test
          // on a récupéré cette info (et 2 autres + bas) dans le header au chargement du fichier
          if OffsetToDatas = 54 then begin // 122 pour le argb, 138 pour le xbgr
            lii := TLazIntfImage.Create(0,0);
            lii.DataDescription:=GetDescriptionFromDevice(0);
            lii.LoadFromFile(opd.FileName);
          end else with b do begin
            lii:=TLazIntfImage.Create(0,0,[]);
            lii.LoadFromBitmap(Handle, MaskHandle, Width, Height);
          end;
          Writer:=TmyLazWriterBMP.Create;
          Writer.Initialize(lii);
          Writer.BitsPerPixel := BitsPerPixel; // idem
          Writer.XBGRmode := (Compression = BI_BITFIELDS); // idem
          // save image to file
          lii.SaveToFile(fic, Writer);
          // clean up
          Writer.Free;
          lii.Free;
        end;

    et voilà.

    +++
    Ah, pendant que je vous tiens, j'ai trouvé un truc (en C++ mais c'est lisible, et probablement adaptable au Pascal) en provenance de Microsoft, qui est sensé récupérer toutes les infos d'un .bmp, à voir là : https://raw.githubusercontent.com/wi...ex/bmpdump.cpp


    +++
    Citation Envoyé par tourlourou Voir le message
    BeanzMaster a raison : la différence vient du support ou non de la version 3 du BIH, non officiel, quoique !
    dans l'article d'Adobe, tout en bas il y a un lien vers une autre page (danger ! il y a des pages bizarres avec des dames charmantes et peu vêtues qui s'affichent quand on clique pour faire un malheureux copier/coller !) qui raconte en plus des bêtises : faites une recherche sur CSType, il n'y a que 5 entrées très proches, qui expliquent des trucs et des machins qui n'ont rien à voir avec la vraie vie...
    La réalité est là :
    https://msdn.microsoft.com/en-us/library/cc250396.aspx
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     typedef  enum
     {
       LCS_CALIBRATED_RGB = 0x00000000,
       LCS_sRGB = 0x73524742,
       LCS_WINDOWS_COLOR_SPACE = 0x57696E20
     } LogicalColorSpace;
        LCS_CALIBRATED_RGB:  Color values are calibrated red green blue (RGB) values.
        LCS_sRGB:  The value is an encoding of the ASCII characters "sRGB",
            and it indicates that the color values are sRGB values.
        LCS_WINDOWS_COLOR_SPACE:  The value is an encoding of the ASCII characters "Win ", including the trailing space,
            and it indicates that the color values are Windows default color space values.

    et je pense qu'il a confondu bv5CSType avec bv5Intent...

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 132
    Par défaut Effet de bord épouvantablement pervers !
    J'ai dit que TFastBitmap affichait le mauvais .bmp comme un TLazIntfImage. J'ai voulu vérifier ce point et là, patatras, le TLazIntfImage se met à afficher des traits verticaux !

    Je vous la fais courte car je fatigue, à force, et si Gilles passe par là, il verra bien qu'on a affaire à du vaudou mal intentionné, regardez bien ces lignes de code, quasiment identiques sauf celle qui dessine le bmp sur le canvas du TPanel, présente en haut et absente en bas, et c'est sa présence qui met la pagaille !
    Je vous laisse imaginer la quantité de tests pour trouver ça, car c'est juste impensable, donc inenvisageable, et pourtant...

    Nom : panel_problem.gif
Affichages : 1022
Taille : 94,1 Ko

    Désolé pour le rendu des couleurs, mais la compression gif ça vaut vraiment rien, :aie;

    En quoi le dessin d'un bmp sur le canvas d'un panel impacterait ce bmp ? Ne marcherait-on pas sur la tête, là ?

    Ceux qui veulent jouer trouveront leur bonheur là-dessous (sauf la ligne qui casse tout) :

    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.Button6Click(Sender: TObject);
    var  
    // http://wiki.freepascal.org/Developing_with_Graphics#Conversion_between_TLazIntfImage_and_TBitmap
    // http://wiki.freepascal.org/Developing_with_Graphics#Loading_a_TLazIntfImage_into_a_TImage
      b: TBitmap;
      t: TLazIntfImage;
    begin
      If Not opd.Execute Then Exit; // ajout perso
     
      b := TBitmap.Create;
      try
        b.LoadFromFile(opd.FileName);
        t := b.CreateIntfImage;
     
        // Read and/or write to the pixels
    //    t.Colors[10,20] := colGreen; // tuto1, inutile ici
     
    //    b.LoadFromIntfImage(t); // tuto1, inutile ici
        Image1.Width := t.Width; Image1.Height:= t.Height; // ajout perso
        Image1.Picture.Bitmap.LoadFromIntfImage(t); // tuto2
      finally
        t.Free;
        b.Free;
      end;
    end;
    Nota : quand l'image est bad, elle a parfois une ligne noire en bas à droite, de longueur variable, et avec plus ou moins de pixels pas noirs (là en l'espèce, un seul bleu à gauche, visible dans l'agrandissement) :
    Nom : aff_bon_mais_faux.png
Affichages : 547
Taille : 37,6 Ko

    Comparez avec le gif, où cette barre est beaucoup plus courte.

  11. #11
    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
    Citation Envoyé par Jipété Voir le message
    En quoi le dessin d'un bmp sur le canvas d'un panel impacterait ce bmp ? Ne marcherait-on pas sur la tête, là ?
    Cela vien du TRawImage qui est mal remplis Non en fait le RawImage est remplis correctement. Il semblerai que cela vienne du StretchDraw utilisé par le Widget GTK qui est en cause. J'essayerai de trouvé ou se cache cette procedure pour y jeter un oeil.

    Citation Envoyé par Jipété Voir le message
    Ceux qui veulent jouer trouveront leur bonheur là-dessous (sauf la ligne qui casse tout) :

    Nota : quand l'image est bad, elle a parfois une ligne noire en bas à droite, de longueur variable, et avec plus ou moins de pixels pas noirs (là en l'espèce, un seul bleu à gauche, visible dans l'agrandissement) :
    A l'heure actuelle TLazIntfImage est la meilleur solution pour la gestion des bitmap surtout sous Linux, on à vu le problème liée à la transparence dans TGifViewer.

    Citation Envoyé par Jipété Voir le message
    Comparez avec le gif, où cette barre est beaucoup plus courte.
    Ca c'est un erreur qui vient de la FCL, surement une petite embrouille avec un TRect dans le code du TLazIntfImage. J'ai fais quelques tests il y à 1 ou 2 semaine en utilisant juste la FCL cf chez les voisins
    • "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

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 132
    Par défaut
    Alors voilà, pour essayer d'y voir clair, j'ai généré une image de 1x1 pixel remplie avec mon bel orange, en 24 bits d'abord et que j'ai exporté en rgb.

    Ensuite j'ai rajouté un canal Alpha et j'ai exporté en argb et pendant que j'y étais, j'ai enfin exporté en xrgb.
    Nom : compar_xrgb_(a)rgb.png
Affichages : 563
Taille : 67,2 Ko

    Ce qui saute aux yeux c'est ce 03 à l'adresse 1Ehex dans le fichier xrgb (ce qui correspond à BI_BITFIELDS, on est d'accord), et la présence d'une ligne 30 en plus par rapport aux deux autres fichiers, ligne dont je n'ai pas encore trouvé l'utilité ; on notera que la 1re ligne reporte bien le changement de taille du fichier.


    Ensuite je me suis concentré sur les datas "visibles" puisque Linux affiche le xrgb avec la bonne couleur (ce qui confirme que je ne sais pas à quoi sert la ligne 30), et voilà ce que ça donne :
    Nom : compar_datas.png
Affichages : 507
Taille : 25,5 Ko

    Constatations : il faut se graver dans le marbre et dans le cerveau au fer rouge que ce que tout le monde appelle rgb est en réalité bgr, et il faut le dire, le redire et le répéter encore ! Regardez le haut de l'image, en orange on voit bien les 3 bytes B G R suivis du byte de padding, BGR certifié car pour avoir un bel orange il faut à peine de B donc 08 et beaucoup de R donc CA.

    On retrouve cette règle dessous avec le argb qui N'EST PAS un argb mais bien un bgra, notez le canal Alpha à fond avec FF, tout ça en bleu transparent.

    Et tout en bas la misère du xrgb qui est juste un xbgr, mais j'ai séparé le byte x des 3 autres, il ne participe pas aux datas (j'ai lu quelque part que ça pourrait être un byte de padding avant l'invention du canal Alpha).

    Tout pour compliquer les choses, et ce n'est pas fini ! Un dernier point : toutes les datas commencent ici "sous" la data 02 mais si Vampyre considère le xrbg comme du argb, il devrait nous faire B 00, G 08 et R 45, ce qui ne correspond pas à cette espèce de marron moche vu ce matin (rgb 102 55 53, soit bgrhex 35 39 66).
    Ça me dépasse...

  13. #13
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 931
    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 931
    Billets dans le blog
    6
    Par défaut
    Salut JP !
    la 1re ligne reporte bien le changement de taille du fichier
    Celle-ci constitue le premier champ du Bitmap Info Header : 108 octets (6Ch) pour un BITMAPV4HEADER (version 4) et 124 (7Ch) pour une BITMAPV5HEADER, la version 5 ajoutant des données de profils ICC.
    ligne 30 en plus par rapport aux deux autres fichiers
    Elle n'est pas en plus : elle est seulement "renseignée"... Ce sont les masques des octets R, G, B, puis A (sans signification ici) à appliquer à un Cardinal pour retrouver chaque canal. Ces octets ne sont pas utilisés dans les 2 premiers fichiers, qui ne sont pas des BI_BITFIELDS.
    En appliquant ces masques, on trouve bien R = CAh, B = 45h et G = 8h, donc ton beau orange.
    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 !

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 132
    Par défaut
    Bonsoir, Yves,

    et bienvenue au club

    Merci pour ta participation, qui va m'éclairer certains recoins sombres, et m'enfoncer un peu plus par ailleurs...

    Commençons par un point sur lequel je ne suis pas d'accord :
    Citation Envoyé par tourlourou Voir le message
    Citation Envoyé par Jipété Voir le message
    ligne 30 en plus par rapport aux deux autres fichiers,
    Elle n'est pas en plus : elle est seulement "renseignée"... Ce sont les masques des octets R, G, B, puis A (sans signification ici) à appliquer à un Cardinal pour retrouver chaque canal. Ces octets ne sont pas utilisés dans les 2 premiers fichiers, qui ne sont pas des BI_BITFIELDS.
    les deux premiers fichiers ont 8 lignes, le troisième en a 9, il y a donc bien
    Citation Envoyé par Jipété Voir le message
    une ligne 30 en plus par rapport aux deux autres fichiers,
    D'ailleurs,
    Citation Envoyé par tourlourou Voir le message
    108 octets (6Ch) pour un BITMAPV4HEADER (version 4) et 124 (7Ch) pour une BITMAPV5HEADER, la version 5 ajoutant des données
    124-108=16, la longueur de cette ligne en plus
    Ensuite, oui, cette ligne est renseignée avec cette histoire de profils que je creuserai demain (fait trop chaud le soir).

    Citation Envoyé par tourlourou Voir le message
    En appliquant ces masques, on trouve bien R = CAh, B = 45h et G = 8h, donc ton beau orange.
    Faudrait que tu nous expliques comment les appliquer, si t'as deux minutes

    Et ce qui est curieux dans tout ça, c'est que les trois fichiers ont été générés par la même session Gimp depuis la même image : pourquoi a-t-il utilisé un BITMAPV4HEADER pour le argb et un BITMAPV5HEADER pour le xrgb ?
    Un mystère qui complique les choses...

    Et pourquoi Vampyre n'arrive pas à le lire ? Un autre mystère.

    Merci pour le coup de main,

  15. #15
    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,
    Citation Envoyé par Jipété Voir le message
    les deux premiers fichiers ont 8 lignes, le troisième en a 9, il y a donc bien
    D'ailleurs,
    124-108=16, la longueur de cette ligne en plus
    Ensuite, oui, cette ligne est renseignée avec cette histoire de profils que je creuserai demain (fait trop chaud le soir).
    Ce n'est pas le profil ICC c'est le GapSize dont on à parlé plus haut 16 octets = Masque pour RGBA = 1 masque = 4 octets 4x4 = 16

    Citation Envoyé par Jipété Voir le message
    Faudrait que tu nous expliques comment les appliquer, si t'as deux minutes
    C'est dans le code que j'ai mis ici cf function ConvertBitFieldsToBZColor(Const aBitFields : TBZColorBitFields; SrcColor : Integer):TBZColor; Plus jette un oeil sur https://en.wikipedia.org/wiki/BMP_file_format partie Pixel Format.
    Citation Envoyé par Jipété Voir le message
    Et ce qui est curieux dans tout ça, c'est que les trois fichiers ont été générés par la même session Gimp depuis la même image : pourquoi a-t-il utilisé un BITMAPV4HEADER pour le argb et un BITMAPV5HEADER pour le xrgb ?
    Un mystère qui complique les choses...

    Et pourquoi Vampyre n'arrive pas à le lire ? Un autre mystère.
    Bonne question pourquoi Gimp choisi telle ou telle version ?

    Si j'ai bien vu Vampyre gère les BMP jusqu'a la version 4 pas la 5
    • "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

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 132
    Par défaut
    Citation Envoyé par BeanzMaster Voir le message
    Bonne question pourquoi Gimp choisit telle ou telle version ?

    Bon, maintenant, peut-être que la dernière version a uniformisé tout ça.

    Citation Envoyé par BeanzMaster Voir le message
    Si j'ai bien vu Vampyre gère les BMP jusqu'à la version 4 pas la 5


    La suite à demain...

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 132
    Par défaut Devoir de vacances
    J'ai bien conscience que ma manière de faire afficher un xrgb avec Vampyre n'est qu'une grosse bidouille, c"était juste pour vérifier que l'outil est capable de me montrer mon bel orange.
    L'ayant vu, je la supprime.

    Je conserve cependant la détection efficace du ifX8R8G8B8 dans ImagingBitmaps ligne 431 avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
        case BI.BitCount of
          ...
    //jpt      32: Format := ifA8R8G8B8; // As with R5G5B5 there is alpha check later 
          32:
            if BI.Compression = BI_BITFIELDS 
            then Format := ifX8R8G8B8 
            else Format := ifA8R8G8B8; // As with R5G5B5 there is alpha check later
        end;
    Si quelqu'un a mieux, qu'il le dise maintenant sinon qu'il se taise à jamais qu'il le dise plus tard,

    Et la bidouille va devoir être remplacée par quelque chose de plus professionnel, dans ImagingFormats ligne 2491 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        4:
          with Pix do
          if SrcInfo.Format = ifX8R8G8B8 then // jpt -- to deal with xrgb
          begin
            // devoir de vacances : utiliser les masks...
          end else // Format is ifA8R8G8B8
          begin
            A := MulDiv(PColor32Rec(Src).A, 65535, 255);
            R := MulDiv(PColor32Rec(Src).R, 65535, 255);
            G := MulDiv(PColor32Rec(Src).G, 65535, 255);
            B := MulDiv(PColor32Rec(Src).B, 65535, 255);
          end;
    Le support d'étude se résume à cette vision colorée du fichier 1x1x32_xbgr avec
    • en 1Ehex la valeur BI_BITFIELD ;
    • de 36hex à 45hex les 16 bytes des 4 masks (msdn ) ;
    • et tout en bas à partir de 8Ahex la data, dans l'ordre X, B, G, R. (smiley bidon juste pour gérer l'espacement vertical de ces trois lignes -- encore une bidouille, )

    Nom : masks+datas_xbgr.png
Affichages : 414
Taille : 25,7 Ko

    Voili voilou,

    EDIT 1 : une première piste :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        4:
          with Pix do begin
            if SrcInfo.Format = ifX8R8G8B8 then // jpt -- to deal with xrgb
            begin
              // l'idée est de convertir ifX8R8G8B8 vers ifA8R8G8B8 en utilisant les masks
            end; 
            // Format ifA8R8G8B8
            A := MulDiv(PColor32Rec(Src).A, 65535, 255);
            R := MulDiv(PColor32Rec(Src).R, 65535, 255);
            G := MulDiv(PColor32Rec(Src).G, 65535, 255);
            B := MulDiv(PColor32Rec(Src).B, 65535, 255);
          end;
    EDIT 2 : question liminaire : ils servent à quoi, ces masks ?

    Si on lit des pixels de 32 bits à la queue leu leu, d'accord pour retrouver les bytes des couleurs, mais si on lit directement des bytes ?
    Un truc m'échappe, là...

    Parce que quand on travaille avec du RGBQuad par exemple, on travaille en fait avec un uint de 32 bits et si on veut la couleur rouge on précise simplement monRGBQuad.rgbRed, et je suspecte fortement qu'en interne et à bas niveau c'est le système d'exploitation qui fait mumuse avec les masks pour me renvoyer la valeur que je demande, donc à quoi bon en rajouter une couche ?

  18. #18
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 931
    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 931
    Billets dans le blog
    6
    Par défaut
    EDIT 2 : question liminaire : ils servent à quoi, ces masks ?
    Ils indiquent quels bits des 32 codent chaque canal, selon le schéma d'où mon image était extraite).
    Ce n'est pas parce qu'on code les pixels sur 32 bits qu'on a forcément un codage en 4 fois 8 bits... Le format permet de définir une image non compressée (BitFields) dont les pixels sont codés en True Colors sur 32 bits, mais avec des canaux inégaux (par exemple 5 bits pour le rouge et 7 pour le bleu, mais 8 pour le vert ; un canal de transparence sur 4 bits, et 8 bits qui ne servent à rien...). Je pense que la seule limitation des masques est qu'un canal doit être une succession de bits contigus (et encore...). Un canal peut être à cheval sur plusieurs octets : ce ne sont pas des RGBQuad qu'on lit, mais des pixels dont le format particulier est entièrement décrit dans l'entête.
    Pour les masques, l'utilisation est simple : on lit le Cardinal représentant le pixel, on fait un and avec le masque du canal à lire, et un décalage pour le caler sur le poids faible du Cardinal. Au passage, j'imagine mal que masques et pixels aient des endianités différentes !
    Il n'y a que 4 masques définis : A, R, G, B ; le X correspondant à la différence éventuelle, qui reste inexploitée (sauf en stéganographie ?).
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  19. #19
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 772
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 772
    Par défaut
    Citation Envoyé par Jipété Voir le message
    tout le monde appelle rgb est en réalité bgr
    J'ai travaillé en C++ avec la VCL/ Embarcadero Xe et c'est la même chose.

    Le problème du truc c'est que le format BMP a été inventé dans les années 90 avec la notion de palette de couleurs sur des systèmes 16 bits, pour évoluer avec un canal de transparence, abandon des palettes, un rien de compression etc.
    Il me semble aussi que le stockage de l'image est inversé avec des lignes multiples de 4 : il est unique ce format
    Et au passage, on remercie Microsoft d'avoir fournit/ autorisé des outils qui sont tolérants aux erreurs
    Si la version 5 n'est pas utilisée c'est parce qu'elle ne sert à rien (ajout des profils ICC) .. si à augmenter le nombre de fonctionnalités et la complexité des "compatibles/ incompatibles"

    Et pour revenir au bgr cela vient des processeurs Intel qui lisent les mots de 16 bits poids faible/poids fort (little endian)

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

Discussions similaires

  1. [DW MX2004] Comment travailler avec Excel?
    Par pierrot10 dans le forum Dreamweaver
    Réponses: 3
    Dernier message: 11/05/2006, 17h34
  2. Comment travailler avec Win32
    Par Mathieu.J dans le forum MFC
    Réponses: 4
    Dernier message: 25/01/2006, 09h49
  3. [XSLT] Comment travailler avec la balise <br/>
    Par billou13 dans le forum XSL/XSLT/XPATH
    Réponses: 3
    Dernier message: 11/10/2005, 10h47
  4. Comment travailler avec le port IEEE 1394?
    Par Cornejito dans le forum MFC
    Réponses: 6
    Dernier message: 04/05/2005, 14h22
  5. Comment travailler avec le client ?
    Par mathieu dans le forum Gestion de projet
    Réponses: 3
    Dernier message: 12/10/2004, 20h56

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