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 :

Copie d'image : résultat bon ou mauvais selon le type d'image [Lazarus]


Sujet :

Lazarus Pascal

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Maintenant qu'on y voit un peu plus clair, replongeons vite dans le brouillard des pointeurs et des codes qui font un peu ce qu'ils veulent et pas ce que j'ai écrit...

    1-les infos :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    //avec un fichier (gimpA_MSopaque3x1.bmp) de 1 seule ligne :
    (bih) Width           : 3
    (bih) Height          : 1
    (bih) Size Image      : 12
    (brid) Depth          : 24
    (bih)  biBitCount     : 32 // Bits-per-Pixel
    LineSize              : 12
    bmp2.PixelFormat      : 4
    2-la copie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // pas de balayage vertical pour alléger et essayer de comprendre, le bitmap dans le fichier n'a qu'une ligne
    bs := TBytesStream.Create;
    bs.SetSize(bih.biSizeImage);
    ptr1 := bmp1.RawImage.Data;
    for w := 0 to LineSize-1 do begin
      bs.WriteByte(byte(ptr1^));  
      ptr1 := Pointer( integer(ptr1)+1);
    end;
    bs.SaveToFile('/chemin/fichier.bin');
    3-le fichier résultat
    Nom : gimpA_MSopaque3x1.bmp.png
Affichages : 190
Taille : 8,0 Ko

    Données présentes dans la cible : 3 RGBTriple. Pourquoi ?

    Le fichier source contient 80 00 FF FF | 80 00 FF FF | 80 00 FF FF (séparations " " et "|" ici de mon fait, si je mets 8000FFFF8000FFFF8000FFFF c'est passablement illisible -- mais plus juste).

    Je rajoute, en début de boucle, memo1.Lines.Add('prt1 : '+ IntToHex(Integer(ptr1), 4)+' '+ IntToHex(Byte(ptr1^), 2)); et je récupère
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    prt1 : B6E61290 80
    prt1 : B6E61291 00
    prt1 : B6E61292 FF
    prt1 : B6E61293 80
    prt1 : B6E61294 00
    prt1 : B6E61295 FF
    prt1 : B6E61296 80
    prt1 : B6E61297 00
    prt1 : B6E61298 FF
    prt1 : B6E61299 6F
    prt1 : B6E6129A 6E
    prt1 : B6E6129B 00
    qui ressemble bien au .bin, de haut en bas.

    Mais avec memo1.Lines.Add('prt1 : '+ IntToHex(Integer(ptr1), 4)+' '+ IntToHex(Integer(ptr1^), 8)); c'est la cata :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    prt1 : B6E61290 80FF0080
    prt1 : B6E61291 0080FF00
    prt1 : B6E61292 FF0080FF
    prt1 : B6E61293 80FF0080
    prt1 : B6E61294 0080FF00
    prt1 : B6E61295 FF0080FF
    prt1 : B6E61296 6FFF0080
    prt1 : B6E61297 6E6FFF00
    prt1 : B6E61298 006E6FFF
    prt1 : B6E61299 11006E6F
    prt1 : B6E6129A C011006E
    prt1 : B6E6129B 29C01100
    On voit bien, en lisant de droite à gauche, que le dernier byte de chaque RGBQuad (le 2e FF), a sauté, transformant les RGBQuad en RGBTriple.
    Pourquoi ?
    Je "discute" au niveau pointeurs, là, les notions de RGBxxx n'ont pas de raison d'être, pas plus que PixelFormat et autres.
    Je ne comprends pas.

    Je n'aurais jamais imaginé que cela puisse être si compliqué de récupérer 3 integers (ou 12 bytes à la suite) dans une zone à plat dans un fichier...

    Ou alors... Ou alors il y aurait un contrôle dans le code de RawImage.Data qui y adapterait les données qu'on y envoie en fonction des paramètres de haut niveau dont je pensais m'affranchir ?
    Ça se tient.
    Capillo-tracté mais ça se tient.
    En tout cas, ça explique ce que je vois.

    Hypothèse idiote, ce que je vois c'est ce que le code lit dans la source, et force est de constater que c'est mal lu.
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

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

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

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 858
    Points : 11 301
    Points
    11 301
    Billets dans le blog
    6
    Par défaut
    Bonjour Jean-Pierre,

    Ton but est-il de charger des images dans des Bitmaps de Lazarus, qu'ils devront tous héberger au même format, pour pouvoir ensuite leur appliquer uniformément des traitements de ton crû dépendant de cette structure ?
    Par exemple, quelque soit le fichier image chargé, obtenir un bitmap 32 bits BGRA ?
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Bonjour, Yves,
    Citation Envoyé par tourlourou Voir le message
    Ton but est-il de charger des images dans des Bitmaps de Lazarus, qu'ils devront tous héberger au même format, pour pouvoir ensuite leur appliquer uniformément des traitements de ton crû dépendant de cette structure ?
    Par exemple, quelque soit le fichier image chargé, obtenir un bitmap 32 bits BGRA ?
    oh la la, ça remonte loin...
    Un jour je suis tombé sur des procédures de resizing qui avaient l'air bien fichues, mais écrites pour Delphi.

    J'ai donc essayé de les adapter, mais c'est d'autant plus compliqué qu'elles font pratiquement exclusivement appel à ScanLine et autres pointeurs avec des syntaxes chelou des fois, je te dis pas !
    Pour faire simple, j'ai alors voulu étudier (comprendre "faire fonctionner le code du lien") le lien que j'ai passé dans le premier post de cette discussion, et on en est là.

    Mais sinon, en gros, oui, c'est ça, quelque soit le fichier chargé, pouvoir le resizer et donc déjà, dans un premier temps, pouvoir le recopier à l'identique, ce qui mine de rien s'avère laborieux.

    EDIT : alors voilà, pour une recopie à l'identique, il suffit d'utiliser les streams, comme ça :
    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
    bip := ReturnsBitmapInfosPerso(opd.FileName); // récupère infos dans fichier.bmp
    SizeImage := bip.bih.biSizeImage;
    bs := TBytesStream.Create; // destination
    bs.SetSize(SizeImage);
    ms := TMemoryStream.Create;// source
    with ms do begin
      LoadFromFile(opd.FileName);
      Position  := bip.bfh.bmfBitMapDataOffset;
      while Compteur < SizeImage do begin
        bs.WriteByte(ReadByte); // récupère datas et avance tout seul
        // pour démo--dans la vraie vie, s'il faut intervenir sur les bytes des pixels, va falloir y aller en mode chirurgien, genre
        // aByte := ReadByte;
        // traffic sur aByte;
        // bs.WriteByte(aByte);
        inc(Compteur);
      end;
    end;
    bs.SaveToFile('/chemin/fichier.bin'); // pour démo--dans la vraie vie il va falloir utiliser bs pour le mettre à la place de Bitmap.RawImage.Data du TImage cible
    bs.Free;
    Mais ce n'est pas avec les streams que je vais pouvoir faire fonctionner les mathématiques et la mécanique des pointeurs -- le but visé c'est quand même le resize -- donc le sujet reste grand ouvert !
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut Résumé synthétique
    Bon, je résume :

    le fichier est comme ça (juste la partie concernée, 1 ligne de 3 pixels BGRA) :
    Nom : ligne12pixels.png
Affichages : 174
Taille : 2,0 Ko

    les données techniques dedans ("bih" = BitmapInfoHeader, "moi" = c'est qui qui fais des calculs) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    (bih) Width           : 3
    (bih) Height          : 1
    (bih) Size Image      : 12
    (bih) Bits-per-Pixel  : 32
    (moi) Pixels Mode     : RGBQuad
    (bfh) BitMapDataOffset: 122
    (moi) Data Structure  : Down2Top
    (bih) Compression     : 0
    (moi) LineSize        : 12 // merci à Andnotor /!\
    Quand je veux accéder aux données stockées à partir de l'adresse renvoyée par BitMapDataOffset (122), je peux utiliser les streams :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ms.Position := bip.bfh.bmfBitMapDataOffset; // ms (TMemoryStream) contient le fichier .bmp
    while Compteur < SizeImage do begin
      bs.WriteByte(ms.ReadByte); // bs = TBytesStream pour récupérer les datas
      inc(Compteur);
    end;
    et ça fonctionne très bien (mais je n'ai pas encore essayé de renvoyer les données du stream "bs" vers un bitmap d'affichage genre TImage, à chaque jour suffit sa peine), ou je peux utiliser les pointeurs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    ptr4 := pRGBQuad(bmp1.RawImage.GetLineStart(0));
    for w := 0 to LineSize-1 do begin
      memo1.Lines.Add(IntToHex(byte(ptr4[w].rgbBlue),    2));
      memo1.Lines.Add(IntToHex(byte(ptr4[w].rgbGreen),   2));
      memo1.Lines.Add(IntToHex(byte(ptr4[w].rgbRed),     2));
      memo1.Lines.Add(IntToHex(byte(ptr4[w].rgbReserved),2));
    end;
    et là ça merdouille : pas moyen de récupérer le 4e byte, le canal alpha, rempli avec FF comme on l'a vu dans l'image en haut :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    80  // B
    00  // G
    FF  // R
    80  // A ? ? ?
     
    00
    FF
    80
    00
    je vous fais grâce des 10 autres blocs, le 4e byte n'est jamais à FF.

    J'en suis là et je ne vois pas comment franchir cette barrière,
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Et voilà !
    (enfin, la première partie -- ensuite va falloir passer les datas récupérées vers un objet pour affichage)

    Avec simplement un TMemoryStream et une Array of Bytes, j'arrive à ça :
    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
    Filename : MSopaque3x1.bmp
    (bih) Bits-per-Pixel  : 24
    (moi) Offset          : 54
    (moi) Pixel''s Byte : 80
    (moi) Pixel''s Byte : 00
    (moi) Pixel''s Byte : FF
    (moi) Pixel''s Byte : 80
    (moi) Pixel''s Byte : 00
    (moi) Pixel''s Byte : FF
    (moi) Pixel''s Byte : 80
    (moi) Pixel''s Byte : 00
    (moi) Pixel''s Byte : FF
    (moi) Pixel''s Byte : 00 // padding
    (moi) Pixel''s Byte : 00 // padding
    (moi) Pixel''s Byte : 00 // padding
    
    Filename : gimpA_MSopaque3x1.bmp
    (bih) Bits-per-Pixel  : 32
    (moi) Offset          : 122
    (moi) Pixel''s Byte : 80
    (moi) Pixel''s Byte : 00
    (moi) Pixel''s Byte : FF
    (moi) Pixel''s Byte : FF /!\
    (moi) Pixel''s Byte : 80
    (moi) Pixel''s Byte : 00
    (moi) Pixel''s Byte : FF
    (moi) Pixel''s Byte : FF /!\
    (moi) Pixel''s Byte : 80
    (moi) Pixel''s Byte : 00
    (moi) Pixel''s Byte : FF
    (moi) Pixel''s Byte : FF /!\
    C'est exactement le contenu de la partie "datas" des fichiers .bmp, et en fait c'est assez simple, voici la partie utile du code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    ms.LoadFromFile(opd.FileName);
    SetLength(TheBytes, ms.Size); // TheBytes c'est une TBytes
    TheBytes := ms.Memory;
    Offset := TheBytes[10];
    memo1.Lines.Add('(moi) Offset          : ' + IntToStr(Offset));
    for w := 0 to LineSize-1 do
      memo1.Lines.Add('(moi) Pixel''s Byte : ' + IntToHex(TheBytes[Offset+w], 2));
    Et comme j'ai accès à tous les pixels (mieux, beaucoup mieux qu'avec les accès par Bitmap -- vous trouvez ça normal, vous ?), ça ne devrait pas être très compliqué de monter d'un niveau dans l'abstraction pour jouer avec les RGBTriple et RGBQuad.
    À voir, à suivre...
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  6. #46
    Membre chevronné

    Homme Profil pro
    au repos
    Inscrit en
    Février 2014
    Messages
    429
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : au repos

    Informations forums :
    Inscription : Février 2014
    Messages : 429
    Points : 1 884
    Points
    1 884
    Par défaut
    Salut JP.

    Dans ton avant-dernier post, ce qui merdouille, c'est la ligne : for w := 0 to LineSize-1 (soit de 0 à 11)
    Comme tu utilises un pRGBQuad et que la ligne de ton bitmap a 3 pixels, tu n'as que 3 pointeurs à lire. (3 x 4 octets = 12)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for w := 0 to Bmp1.Width - 1 do...
    Et pour lire un bitmap de plusieurs lignes :

    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 TForm1.Button1Click(Sender: TObject);
    var
      bmp1: TBitmap;
      ptr4: pRGBQuad;
      h,w: integer;
    begin
      bmp1:= tbitmap.create;
      try
        bmp1.loadfromfile('bmp3x3_32.bmp');
        for h:= 0 to bmp1.height -1 do
        begin
           ptr4 := pRGBQuad(bmp1.RawImage.GetLineStart(h));
           for w := 0 to bmp1.width - 1 do
           begin
               memo1.Lines.Add(IntToHex(byte(ptr4[w].rgbBlue),    2));
               memo1.Lines.Add(IntToHex(byte(ptr4[w].rgbGreen),   2));
               memo1.Lines.Add(IntToHex(byte(ptr4[w].rgbRed),     2));
               memo1.Lines.Add(IntToHex(byte(ptr4[w].rgbReserved),2));
           end;
        end;
      finally
        bmp1.free;
      end;
    end;
    Amicalement
    Thierry

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Salut, Thierry,

    Merci de prendre de ton temps pour cette misère,

    Citation Envoyé par ThWilliam Voir le message
    Dans ton avant-dernier post, ce qui merdouille, c'est la ligne : for w := 0 to LineSize-1 (soit de 0 à 11)
    Comme tu utilises un pRGBQuad et que la ligne de ton bitmap a 3 pixels, tu n'as que 3 pointeurs à lire. (3 x 4 octets = 12)
    Ah, j'ai dû me faire des nœuds dans les neurones, ça arrive, à force
    Ce matin j'ai fait des essais multi-ligne avec la dernière version, c'est bon.

    Mais ça tombe bien que tu relances la balle, car moi, je l'ai encore envoyée dans le décor

    Pour faire court et simple, ce matin je suis tombé sur cette page et comme il y avait une jolie copie d'écran (les dégradés me font rêver -- c'est fou, non ? -- Bah, Lena aussi, hein, dans un autre genre, ) je me suis dit "en avant", je zappe les BGRA compos, je passe en TBitmap pur et au bout de quelques minutes je suis arrivé à ça, qui fonctionne bien (ie j'ai le même dégradé) sous Linux et sous Windows :

    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
    procedure TForm1.btnGradientBGRAClick(Sender: TObject);
    // http://wiki.lazarus.freepascal.org/BGRABitmap_tutorial_4
    var x,y: integer; 
        p: pRGBQuad;
        image: TBitmap;
      procedure SwapRBdatas; inline;
      var tR,tB: byte;
      begin tR:= p^.rgbBlue;tB:=p^.rgbRed;p^.rgbRed:=tR;p^.rgbBlue:=tB; end;
    begin
      image := TBitmap.Create;
      image.PixelFormat:=pf32bit;
      image.SetSize(image2.Width, image2.Height);
     
      image.BeginUpdate();
      for y := 0 to image.Height-1 do
      begin
        p := pRGBQuad(image.RawImage.GetLineStart(y));
        for x := 0 to image.Width-1 do
        begin
          p^.rgbred   := x*256 div image.Width;
          p^.rgbgreen := y*256 div image.Height;
          p^.rgbblue  := 0;
          p^.rgbreserved := 255;
          {$IFDEF LINUX}
          SwapRBdatas; // /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\
          {$ENDIF}
          inc(p);
        end;
      end;
      image.EndUpdate();
      // image.SaveToFile('/chemin/image.bmp'); // OK
      image2.Picture.Assign(image);
      image.free;
    { dans wiki  -|-   Linux --> corrigé par SwapRBdatas
    noir...rouge  |  noir...bleu
    .          .  |  .         .
    .     orange  |  .         .
    .          .  |  .         .
    vert...jaune  |  vert...cyan  }
    end;
    Vous pouvez copier-coller sans prise de tête, normalement ça doit fonctionner direct (sans oublier uses LCLtype; // pour pRGBQuad).

    Et je me suis dit que j'allais utiliser cette construction pour l'avancement de mon projet, à savoir faire afficher correctement les bytes récupérés, en gros, comme ça ('tention, c'est du lourd, et y a pas tout, là c'est juste l'essentiel) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
          bmp := TBitmap.Create;
          case BpP of // Bits-per-Pixel
            24: bmp.PixelFormat := pf24bit;
            32: bmp.PixelFormat := pf32bit;
          end;
          bmp.SetSize(aWidth, aHeight); // valeurs récupérées par stream depuis le fichier bitmap
     
          bmp.BeginUpdate();
          for h := 0 to aHeight-1 do begin
            idx := Offset + (LineSize * h);
            case BpP of
              24: ptr3 := pRGBTriple(bmp.RawImage.GetLineStart(h));
              32: ptr4 := pRGBQuad(  bmp.RawImage.GetLineStart(h));
            end;
            for w := 0 to LineSize-1 do
    // avec MSopaque3x1 j'ai 4 RGPTriple : 80 00 FF | 80 00 FF | 80 00 FF | 00 00 00
              case BpP of
                24: begin
                  if (w mod 3 = 0) then begin //équivalent au "step 3"
                    //showmessage(inttostr(w)); // 0 3 6 9
                    memo1.Lines.Add('(moi) Pixel''s Byte R : ' + IntToHex(byte(TheBytes[idx+w]), 2));
                    memo1.Lines.Add('(moi) Pixel''s Byte G : ' + IntToHex(byte(TheBytes[idx+w+1]), 2));
                    memo1.Lines.Add('(moi) Pixel''s Byte B : ' + IntToHex(byte(TheBytes[idx+w+2]), 2));
                    ptr3^.rgbtRed     := byte(TheBytes[idx+w]);
                    ptr3^.rgbtGreen   := byte(TheBytes[idx+w+1]);
                    ptr3^.rgbtBlue    := byte(TheBytes[idx+w+2]);
                    memo1.Lines.Add('(moi) Pixel''s Data R : ' + IntToHex(byte(ptr3^.rgbtRed),   2));
                    memo1.Lines.Add('(moi) Pixel''s Data G : ' + IntToHex(byte(ptr3^.rgbtGreen), 2));
                    memo1.Lines.Add('(moi) Pixel''s Data B : ' + IntToHex(byte(ptr3^.rgbtBlue),  2));
                    memo1.Lines.Add('');
                    inc(ptr3);
                  end;
                end;
                32: begin
                  if (w mod 4 = 0) then begin //équivalent au "step 4"
                    showmessage(inttostr(w));
                    ptr4^.rgbRed      := byte(TheBytes[idx+w]);
                    ptr4^.rgbGreen    := byte(TheBytes[idx+w+1]);
                    ptr4^.rgbBlue     := byte(TheBytes[idx+w+2]);
                    ptr4^.rgbReserved := byte(TheBytes[idx+w+3]);
                    inc(ptr4);
                  end;
                end;
              end;
     
              {$IFDEF LINUX}
    //          SwapRBdatas; // /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\
              {$ENDIF}
          end;
     
          bmp.EndUpdate();
          bmp.SaveToFile('/chemin/test.bmp');
          image3.Picture.Assign(bmp);
          bmp.Free;
    Tout n'est pas fini, le swap R-B et le mode pf32bit, c'est normal, c'est en attente du fonctionnement parfait du mode pf24bit, car j'ai essayé avec le fichier indiqué en commentaire, et malheureusement, j'ai de nouveau les problèmes de shift ou perte ou que sais-je des bytes dans la destination -- il comprend pas le monsieur...
    En haut l'original, en bas la copie :
    Nom : test_pointeurs.png
Affichages : 171
Taille : 5,6 Ko

    Voilà les datas dans le TMemo de log et contrôle, avant (repérées par "byte") et après (repérées par "data") leur transfert dans les RGBTriple :
    (j'ai écrit R G B un peu à la va-vite, en fait c'est B G R mais l'outil de conversion n'est pas prêt -- on s'en fout, pour le moment)
    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
    (moi) Pixel''s Byte R : 80
    (moi) Pixel''s Byte G : 00
    (moi) Pixel''s Byte B : FF
    (moi) Pixel''s Data R : 80
    (moi) Pixel''s Data G : 00
    (moi) Pixel''s Data B : FF
     
    (moi) Pixel''s Byte R : 80
    (moi) Pixel''s Byte G : 00
    (moi) Pixel''s Byte B : FF
    (moi) Pixel''s Data R : 80
    (moi) Pixel''s Data G : 00
    (moi) Pixel''s Data B : FF
     
    (moi) Pixel''s Byte R : 80
    (moi) Pixel''s Byte G : 00
    (moi) Pixel''s Byte B : FF
    (moi) Pixel''s Data R : 80
    (moi) Pixel''s Data G : 00
    (moi) Pixel''s Data B : FF
     
    (moi) Pixel''s Byte R : 00
    (moi) Pixel''s Byte G : 00
    (moi) Pixel''s Byte B : 00
    (moi) Pixel''s Data R : 00
    (moi) Pixel''s Data G : 00
    (moi) Pixel''s Data B : 00
    Elles sont bonnes, excellentes, même !

    Voilà, après la boucle de recopie, il y a le bmp.EndUpdate(); obligatoire, l'écriture facultative dans un fichier et le transfert dans un TImage pour voir que les couleurs n'y sont pas bonnes
    Franchement décourageant...
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Comment les choses sont mises en place (allégées pour la lisibilité) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ms := TMemoryStream.Create;
    ms.LoadFromFile(opd.FileName);
    SetLength(TheBytes, ms.Size); //  TBytes;
    TheBytes := ms.Memory; // pointe au début du fichier
    Offset := TheBytes[10];// récupére l'offset vers les datas
    Concentrée sur l'essentiel, la boucle de création des datas (bs1,bs2: TBytesStream)
    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
    // le fichier de test ne contient que 4 RGPTriple : 80 00 FF | 80 00 FF | 80 00 FF | 00 00 00
    for h := 0 to aHeight-1 do begin
      idx := Offset + (LineSize * h); // LineSize vaut 12
      p3  := pRGBTriple(bmp.RawImage.GetLineStart(h));
      for w := 0 to LineSize-1 do if (w mod 3 = 0) then begin
        showmessage(inttostr(w)); // --> 0 3 6 9
        p3^.rgbtRed  := byte(TheBytes[idx+w+0]);
        bs1.WriteByte  (byte(TheBytes[idx+w+0]));
        bs2.WriteByte  (byte(p3^.rgbtRed));
     
        p3^.rgbtGreen:= byte(TheBytes[idx+w+1]);
        bs1.WriteByte  (byte(TheBytes[idx+w+1]));
        bs2.WriteByte  (byte(p3^.rgbtGreen));
     
        p3^.rgbtBlue := byte(TheBytes[idx+w+2]);
        bs1.WriteByte  (byte(TheBytes[idx+w+2]));
        bs2.WriteByte  (byte(p3^.rgbtBlue));
        inc(p3);
      end;
    end;
    bmp.EndUpdate();
    bmp.SaveToFile('/chemin/test.bmp');
    bs1.SaveToFile('/chemin/bs1_data.bin');
    bs2.SaveToFile('/chemin/bs2_data.bin');
    showmessage(inttostr(BytesPerPixel(bmp.PixelFormat)));// 3 avec MSopaque3x1 = OK
    image3.Picture.Assign(bmp);
    showmessage(inttostr(BytesPerPixel(image3.Picture.bitmap.PixelFormat)));// 3 = OK
    Et le résultat, qui fait peur :
    Nom : erreur_datas.png
Affichages : 209
Taille : 30,8 Ko

    En vert ce qui est bon (les fichiers issus des TBytes Streams), en rouge ce qui débloque (le TBitmap) :

    À l'heure actuelle, la seule solution que je vois serait de générer le bitmap foireux et le fichier avec les bonnes datas, puis de faire un mix des deux à coup de streams. Vous voyez le boulot ?
    Truc de malade...

    PS : il semblerait qu'il soit possible d'intervenir sur ms.Memory (pourtant je croyais que c'était ReadOnly, mais je suis tombé sur une page de S.O. où les gens ont l'air de trifouiller en écriture) : je teste et je vous dis...
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  9. #49
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 693
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 693
    Points : 13 128
    Points
    13 128
    Par défaut
    Il y a un croisement entre rouge et bleu mais sinon tu nous montres systématiquement un problème d'incrément de pointeur, un 24 est traité comme du 32.

    Alors je regarde (enfin) quelle est la définition de PRGBTriple, remonte à TRGBTriple (sans surprise) qui nous amène finalement à tagRGBTRIPLE.

    Et que constate-t-on ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    type tagRGBTRIPLE = record
      rgbtBlue: Byte;  
      rgbtGreen: Byte;  
      rgbtRed: Byte;
    end;
    Le record n'est pas pack-é !

    Donc ?

    (Sous Delphi, il suffirait de définir l'alignement des enregistrements sur "octet")

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Il y a un croisement entre rouge et bleu
    Oui, ça je sais, j'ai décidé que je le traiterai après, quand j'aurai enfin des RGBTriple corrects.

    Citation Envoyé par Andnotor Voir le message
    mais sinon tu nous montres systématiquement un problème d'incrément de pointeur, un 24 est traité comme du 32.
    Ça, je l'aurais capté si j'avais trouvé des RGBQuad dans le .bmp généré, genre les RGBTriple correctement recopiés et chacun suivi d'un byte à 00, mais ce n'est pas du tout le cas.

    Citation Envoyé par Andnotor Voir le message
    Et que constate-t-on ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    type tagRGBTRIPLE = record
      rgbtBlue: Byte;  
      rgbtGreen: Byte;  
      rgbtRed: Byte;
    end;
    Le record n'est pas pack-é !

    Donc ?

    (Sous Delphi, il suffirait de définir l'alignement des enregistrements sur "octet")
    En suivant le même cheminement que toi, j'ai pu constater que le tagRGBQUAD tout comme le TRGBAQUAD ne sont pas pack-és non plus (sans doute moins grave pour ces deux-là), et n'écoutant que mon courage pi au point où j'en suis je peux bien tester ça, j'ai donc rajouté "packed" 3 fois à l'endroit qui va bien, j'ai relancé le bazar et j'ai exactement le même problème.


    Ah, au passage, j'avais dit que je donnerais des nouvelles de l'autre essai, ben il est aussi négatif que le reste...
    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
    p := ms.Memory;
    inc(p, 10);
    Offset := p^;
    inc(p, Offset-10); // 1er byte des datas
    for h := 0 to aHeight-1 do begin
      idx := Offset + (LineSize * h);
      ptr3 := pRGBTriple(bmp.RawImage.GetLineStart(h));
      for w := 0 to LineSize-1 do if (w mod 3 = 0) then begin //équivalent au "step 3"
      // pour parcourir les bytes comme si les données étaient groupées en RGBTriple
          //showmessage(inttostr(p^)); // 128 128 128 0 c'est bon : 1er byte de chaque "RGBTriple"
          ptr3^.rgbtRed   := p^;
          memo1.Lines.Add('Data R : ' + IntToHex(byte(ptr3^.rgbtRed),  2));
          inc(p); // byte suivant
     
          ptr3^.rgbtGreen := p^;
          memo1.Lines.Add('Data G : ' + IntToHex(byte(ptr3^.rgbtGreen),  2));
          inc(p); // byte suivant
     
          ptr3^.rgbtBlue  := p^;
          memo1.Lines.Add('Data B : ' + IntToHex(byte(ptr3^.rgbtBlue),  2));
          inc(p); // byte suivant
     
          inc(ptr3); // RGBTriple suivant
        end;
      end;
    end;
    Je ne remets pas de copie du mémo où les 12 lignes montrent que les bonnes datas sont aux bons endroits, je ne remets pas d'image où on perd des bytes dans le fichier .bmp résultant, je rappelle juste qu'entre les deux il y a simplement un bmp.EndUpdate dont j'ai un peu regardé le code mais je n'ai rien trouvé, pas plus que dans le bmp.SaveToFile.

    EDIT : j'ai viré le bmp.SaveToFile et le couple Begin-EndUpdate (parait que c'est pas bon, qu'il ne faut pas le faire, mais juste pour voir et tester je me suis permis), l'image qui s'affiche me montre les mêmes couleurs habituelles et moisies, symptomatiques de la perte des bytes.
    Et là maintenant, il n'y a plus rien entre la dernière ligne dans le mémo de contrôle et l'affichage dans le TImage.
    La seule différence c'est que le mémo prend ses données dans une suite de bytes quand le TImage les prend dans une structure bitmap (étant entendu que c'est la même chose).
    Et pourtant j'ai vérifié ça aussi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    showmessage(inttostr(BytesPerPixel(bmp.PixelFormat)));// 3 avec MSopaque3x1
    showmessage(inttostr(BytesPerPixel(image3.Picture.bitmap.PixelFormat)));// 3 avec MSopaque3x1
    Et même en forçant avant le transfert, l'affichage foire...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    image3.Picture.Bitmap.PixelFormat := pf24bit;
    image3.Picture.Assign(bmp);
    /EDIT
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    La réflexion de pas-d'heure :

    En fait, je suspecte qu'il se passe des choses dans notre dos, qu'on ne maîtrise et ne contrôle pas, à moins de passer des jours dans le code source, regardez ce que j'ai trouvé :
    en haut un fichier en mode pf32bit généré par The Gimp à partir d'un fichier pf24bit créé par MSPaint présenté en bas. Ensuite j'utilise les "API" pour aller chercher les infos qui m'intéressent dans les structures idoines.
    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
    Filename : gimpA_MSopaque3x1.bmp
    (bih) Width (en pixel): 3
    (bih) Height(en pixel): 1
    (bih) Size Image      : 12
    (bih) Bits-per-Pixel  : 32
    (moi) Bytes-per-Pixel : 4
    (moi) SizeImage (byte): 12
    (brid) BytesPerLine   : 12
    (brid) BitsPerLine    : 96
    (brid) ByteOrder      : LSBFirst
    (brid) ColorFormat    : ricfRGBA
    (brid) Depth          : 32
    ---
    Filename : MSopaque3x1.bmp
    (bih) Width (en pixel): 3
    (bih) Height(en pixel): 1
    (bih) Size Image      : 12
    (bih) Bits-per-Pixel  : 24
    (moi) Bytes-per-Pixel : 3
    (moi) SizeImage (byte): 9
    (brid) BytesPerLine   : 12
    (brid) BitsPerLine    : 96
    (brid) ByteOrder      : LSBFirst
    (brid) ColorFormat    : ricfRGBA
    (brid) Depth          : 24
    "bih" c'est le BitmapInfoHeader et "moi" c'est quand je calcule.

    La chose intéressante est de comparer les 4e et 5e lignes en partant de la fin, je vous les remets ici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    pf32bit
    (brid) BytesPerLine   : 12
    (brid) BitsPerLine    : 96
    ---
    pf24bit
    (brid) BytesPerLine   : 12
    (brid) BitsPerLine    : 96
    "brid" c'est Bitmap.RawImage.Description, et vous voyez une différence, vous, entre le pf32bit et le pf24bit ?
    Moi pas.
    Et mine de rien, 12 BytesPerLine et 3 pixels sur la ligne, ça fait des pixels de 4 bytes, un de trop pour du pf24bit.

    D'ici à ce que ça soit pareil dans le code fonctionnel de bas niveau, ben je crois que le souci est par là...
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Bonjour

    En ce jour férié, je vous fais profiter de ma dernière découverte et de ma grande réussite dans ce combat infernal : en me débarrassant de la structure TBitmap1, il est possible de faire de grandes choses :
    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
      bs := TBytesStream.Create;
      bs.SetSize(ms.Size);
      SetLength(TheBytes, ms.Size);
      TheBytes := ms.Memory; // Array de bytes
     
      //1-recopier les bytes du header
      Offset := TheBytes[10];// récupére l'offset vers les datas
      ms.Position := 0; bs.Position := 0;
      bs.CopyFrom(ms, Offset);
     
      //2 recopier les bytes de datas
      for h := 0 to aHeight-1 do 
        for w := 0 to LineSize-1 do begin
          aByte := ms.ReadByte;
          // ici il est possible d'intervenir sur le byte 
          bs.WriteByte(aByte);
        end;
     
      //3 vérifs
      //ok      bs.SaveToFile('/chemin/bs.bin'); exit;
      bmp := TBitmap.Create;
      case BpP of
        24: bmp.PixelFormat := pf24bit;
        32: bmp.PixelFormat := pf32bit;
      end;
      bmp.SetSize(aWidth,aHeight);
      bs.Position:=0;
      bmp.LoadFromStream(bs, bs.Size);
     
      image3.Picture.Assign(bmp); // OKKKKKKKKKKKKKKKKKKK !
      //  bmp.SaveToFile('/chemin/a_test.bmp');
      bmp.Free;
    Version avec un pointeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var
      p: ^Byte;
    begin
      ...
      p := ms.Memory;
      for h := 0 to aHeight-1 do
        for w := 0 to LineSize-1 do begin
          p^ := ms.ReadByte;
          // ici il est possible d'intervenir sur le byte pointé
          bs.WriteByte(p^);
        end;
    Alors oui, d'aucuns diront qu'il aurait été encore plus simple et plus facile de le faire en une seule ligne, genre bs.CopyFrom(ms, ms.Size-Offset); mais c'est oublier que la chose qui m'intéresse, c'est la ligne centrale en commentaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    p^ := ms.ReadByte; // byte source
    // ici il est possible d'intervenir sur le byte pointé
    bs.WriteByte(p^);  // destination
    1 : ce qui m'ennuie avec ma trouvaille, c'est d'abandonner la structure TBitmap pour la bonne et simple raison que l'immense majorité des exemples qui traînent sur le web concernant la manipulation des images (resizing, modif des couleurs, etc.) s'appuie dessus, à grands coups de ScanLine entre autres.
    Et là, toute cette mécanique de haut niveau a disparu, je trafique directement les bytes sans savoir qui fait quoi et où.

    Résultat des courses, je ne sais pas si je coche ou pas, car la question dans le post no 1 n'est pas résolue, elle : j'ai regardé avec un œil neuf les deux procédures données dans le lien du premier post, elles s'appuient à donf sur des infos remontées par Bitmap.RawImage.Description et on a vu ces jours-ci ce que ça valait...

    À titre d'exemple, je vous recopie un commentaire retrouvé dans les lignes de la procédure BitmapToBytes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      BPP := BytesPerPixel(Bitmap.PixelFormat);
      form1.Caption:=IntToStr(BPP);
      // 4 avec le fichier pf32 (OK), 3 avec 96x96x24 (OK) mais 3 aussi avec 96x96xA32 (not OK) !
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

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

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

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

    En ce jour férié, je vous fais profiter de ma dernière découverte et de ma grande réussite dans ce combat infernal : en me débarrassant de la structure TBitmap1, il est possible de faire de grandes choses :
    Ha ! enfin

    Non, sans rire, avec Lazarus et FPC la gestion des bitmaps c'est la croix et la bannière. Tout y est parfaitement intégré et fonctionne dans la plus part des cas bien. Le soucis c'est que beaucoup de routines nous sont "cachées". Et ou que la manipulation avec les objet de bases (TIntfImage, TBitmap, ect.. .) est très complexe. La gestion des bitmap en interne c'est pareil. Vraiment compliquée dans FPC et très très différente de Delphi. Delphi que le bitmap soit de format 1bits, 24bits, 32... les pixels ont toujours la même taille 32bits soit 4 octets. Sous FPC le format change plus ou moins en fonction de le "couche" que l'on manipule. Par ex TFPColor est codé sur 64bits, mais dans de le rawImage on aura du 32bits, bref la gestion des bits avec Lazarus c'est une grosse chi....lie.

    Juste pour info, par rapport à ton problème d'origine. J'étais en train de fouiner dans les sources de fpc/lazarus et je suis tombé la dessus dans Lcl\GraphType.pp partie implementation jette un oeil sur les 1ere routines
    Bien cachées et non publiques. Mais qui t'aurais été bien utiles je pense. (ps c'est la aussi qu'est caché le TRawImage ) et la couche du dessus c'est lcl\Intfgraphics.pas

    A+ et bonne fin de Pâques
    • "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

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Yep !
    Citation Envoyé par BeanzMaster Voir le message
    Juste pour info, par rapport à ton problème d'origine. J'étais en train de fouiner dans les sources de fpc/lazarus et je suis tombé là-dessus dans Lcl\GraphType.pp partie implementation jette un œil sur les 1res routines
    Oh la la...

    Toute première function,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    function CopyImageData(AWidth, AHeight, ARowStride: Integer; ABPP: Word; ASource: Pointer; const ARect: TRect; ASourceOrder: TRawImageLineOrder;
                           ADestinationOrder: TRawImageLineOrder; ADestinationEnd: TRawImageLineEnd; out ADestination: Pointer; out ASize: PtrUInt): Boolean;
    J'ai vidé la boîte d'aspirine !

    Un poil plus bas,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    procedure RawImage_ReadBits(AData: PByte; const APosition: TRawImagePosition;
                           ABitsPerPixel, APrec, AShift: Byte;
                           ABitOrder: TRawImageBitOrder; out ABits: Word);
    et sa sister RawImage_WriteBits ne connaissent pas le mode 24 bits :
    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
      case ABitsPerPixel of
      1,2,4:
          begin
            if ABitOrder = riboBitsInOrder then
              ABits := (PB^ shr (AShift + APosition.Bit)) and PrecMask
            else
              ABits := (PB^ shr (AShift + 7 - APosition.Bit)) and PrecMask;
          end;
      8:  begin
            ABits := (PB^ shr AShift) and PrecMask;
          end;
      16: begin
            {$IFDEF VerboseLCLTodos}{$note check endian and/or source byte order}{$ENDIF}
            ABits := (PW^ shr AShift) and PrecMask;
          end;
      32: begin
            {$IFDEF VerboseLCLTodos}{$note check endian and/or source byte order}{$ENDIF}
            ABits := (PC^ shr AShift) and PrecMask;
          end;
      else
        ABits:=0;
      end;
    Comment est-ce possible ?
    Ceci explique peut-être le problème rencontré avec les fichiers pf24bit -- flemme de faire des tests (après tout, ch'suis pas le seul : // I'm to lazy to zero line by line, so we might do to much here dans CopyImageData, avec deux fautes, ce qui oblige à réfléchir très fort avant de comprendre...
    // I'm too lazy to zero line by line, so we might do too much here).

    Quant à cette fonction :
    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
    function TRawImage.IsTransparent(ATestPixels: Boolean): Boolean;
      function CheckAlpha: Boolean;
      begin
        {$IFDEF VerboseLCLTodos}{$note TODO: implement CheckAlpha}{$ENDIF}
        Result := True;
      end;
    begin
      Result :=
        (Data <> nil) and
        (DataSize <> 0) and
        (Description.AlphaPrec <> 0) and
        (Description.Width = 0) and
        (Description.Height = 0);
     
      if Result and ATestPixels then
        Result := CheckAlpha;
    end;
    elle renvoie toujours False ! Ou je ne sais pas l'utiliser ? Vous feriez comment, vous ? Moi j'ai testé ça, après avoir ouvert un fichier 32 bits :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        showmessage(booltostr(bmp.RawImage.IsTransparent(true))); // renvoie false
        showmessage(booltostr(bmp.RawImage.IsTransparent(false)));// renvoie false
    On se demande bien à quoi elle sert.
    Vous me direz, quand on voit le TODO ! Et ce fichier date de 2002.
    mattias est passé dessus en mai 2015, du coup il a perdu 70 bytes entre les versions 1.4 et 1.6.2 mais on ne sait pas quoi, mattias n'ayant rien indiqué au début du fichier .

    Et, tiens, je profite qu'on casse du sucre sur le dos des développeurs (qui aime bien châtie bien, dit le proverbe), pour vous faire part d'une perle magnifique, trouvée dans l'aide :
    Nom : TCustomMemoryStream.png
Affichages : 158
Taille : 6,9 Ko
    En gros, il ne faut pas créer d'instance de TMemoryStream, il faut plutôt créer des instances de... TMemoryStream !
    Bravo les gars
    Là on a du bol, l'erreur est flagrante. Mais combien de cas où c'est moins évident ? Et avec des conséquences fâcheuses, du coup ?

    Merci pour les infos, bonne journée,
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  15. #55
    Membre chevronné

    Homme Profil pro
    au repos
    Inscrit en
    Février 2014
    Messages
    429
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : au repos

    Informations forums :
    Inscription : Février 2014
    Messages : 429
    Points : 1 884
    Points
    1 884
    Par défaut
    Salut JP.

    Citation Envoyé par Jipété Voir le message
    Et mine de rien, 12 BytesPerLine et 3 pixels sur la ligne, ça fait des pixels de 4 bytes, un de trop pour du pf24bit.
    Non, il n'y a bien que 3 pixels de 3 octets.
    Mais chaque ligne d'un bitmap doit avoir un nombre d'octets divisible par 4.
    Ligne de 3 pixels : 3px x 3 octets = 9 --> padding de 3 octets --> total 12 octets
    Ligne de 2 pixels : 2px x 3 octets = 6 --> padding de 2 octets --> total 8 octets.
    Par contre, dans un bitmap 32bits, il n'y évidemment pas de padding.
    J'ai vérifié tout ceci par des tests sous Windows.

    Amicalement
    Thierry

    [EDIT] Je tiens à préciser que je n'utilise jamais le pouce vers le bas...

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Salut Thierry,
    Citation Envoyé par ThWilliam Voir le message
    Non, il n'y a bien que 3 pixels de 3 octets.
    Oui, et avec cette histoire de padding, je me demande si tout ça ne serait pas qu'un problème d'appellation des choses. Regarde ce que j'avais noté dans un coin, suite à étude approfondie du BitmapInfoHeader :
    N'y aurait-il pas une confusion entre BitmapInfoHeader.biWidth qui serait, d'après MSDN, the width of the bitmap, in pixels, et BitmapInfoHeader.biSizeImage, the size, in bytes, of the image.
    Il aurait peut-être mieux fallu expliquer ce champ comme étant the size, in bytes, of the data's field.

    Car en ce qui concerne le fichier qui me pose tant problème, je rappelle qu'il a 3 pixels de large, valeur que je retrouve dans biWidth, mais je trouve 12 bytes dans biSizeImage, or, pour moi, les 3 derniers bytes de padding ne font pas partie, stricto sensu, de l'image.


    Citation Envoyé par ThWilliam Voir le message
    Mais chaque ligne d'un bitmap doit avoir un nombre d'octets divisible par 4.
    Oui, Andnotor nous l'a bien expliqué il y a quelques posts (retrouvable facilement car il est "vert", sans doute en page précédente)

    Citation Envoyé par ThWilliam Voir le message
    [EDIT] Je tiens à préciser que je n'utilise jamais le pouce vers le bas...
    Moi non plus, ou alors je l'explique en long en large et en travers
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut Une mission pour Thierry
    Yop !

    Regarde l'image : en bas le fichier que je t'avais posté pour faire des essais, au milieu une fois que tu l'as ouvert avec 'toshop, pi modifié le dernier pixel (FF FF 00 FF --> F0 9D D2 FF), ce qui lui a fait rajouter 2 bytes à la fin (zone mauve), et en haut ce même fichier une fois renvoyé dans mes mains et ouvert avec l'une des 2 routines qui ont initié cette très intéressante discussion.
    Nom : mission_thierry.png
Affichages : 163
Taille : 60,6 Ko

    Et on constate que, au-delà du changement global de taille (Gimp doit rajouer des trucs inutiles, qui ont disparu à l'enregistrement de 'toshop), la valeur de la zone verte a évolué, passant de 10 à 12.
    Cette zone s'appelle, dans le BitmapInfoHeader, "biSizeImage" et est expliquée comme étant the size, in bytes, of the image.
    10 hex soit 16 bytes, à 4 bytes par pixel, ça nous fait 4 pixels entiers, ce qui est bien ce qu'on voit : 4 fois FF FF 00 FF.
    Mais le calcul de 'toshop passe à 12 (18 déc.) car 2 bytes de padding ont été rajoutés. Pourquoi ?

    Tout en haut la recopie du fichier a fait sauter les 2 bytes de padding mais l'info à l'adresse 22 est restée à 18, donc fausse maintenant : j'avais noté dans un coin de ne pas se fier à biSizeImage mais de refaire les calculs en partant du biBitCount, le number of bits-per-pixel, à l'adresse 1C (ronds bleus, valeur 20 soit 32 déc.) : 32 bits-per-pixel = 4 bytes-per-pixel, on a bien la présence du canal alpha.

    Plus qu'à essayer de comprendre pourquoi 'toshop a rajouté 2 bytes puisque tu nous disais ce matin (et les autres jours) qu'il fallait être divisible par 4 : 18 ne l'est pas !

    En ce qui me concerne, ayant fait une copie de bytes par move mais à partir de la zone "data" d'un TBitmap, j'en conclus (on le supposait déjà, ça se confirme) que le SaveToFile utilisé ensuite pour récupérer le résultat de la copie vit sa vie solitaire et aléatoire, recopiant des bytes de datas d'une manière pifométrique et sans mettre à jour les données afférentes dans la zone InfoHeader.
    On est mal, on est très mal...

    Et même pas j'essaye l'autre procédure, Bytes2Bitmap : si je lui donne des datas fausses, je ne risque pas d'aller bien loin.
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

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

    Informations forums :
    Inscription : Avril 2002
    Messages : 2 464
    Points : 4 311
    Points
    4 311
    Par défaut
    Citation Envoyé par Jipété Voir le message
    Plus qu'à essayer de comprendre pourquoi 'toshop a rajouté 2 bytes puisque tu nous disais ce matin (et les autres jours) qu'il fallait être divisible par 4 : 18 ne l'est pas !
    Si je lis bien, tu avais toi-même trouvé la réponse avant :
    https://www.developpez.net/forums/d1...e/#post9186769
    M.Dlb - Modérateur z/OS - Rédacteur et Modérateur Pascal

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Citation Envoyé par M.Dlb Voir le message
    Si je lis bien, tu avais toi-même trouvé la réponse avant :
    https://www.developpez.net/forums/d1...e/#post9186769
    Oui oui, c'était pour vérifier si tout le monde suivait,

    Nan, j'déconn', en fait je l'avais oublié, ce post, pour la bonne et simple raison qu'on dirait qu'il y a deux écoles :
    • pair et divisible par 4
    • pair et non divisible par 4

    et entre les deux mon cœur balance, vois-tu !
    Parce que du coup, pourquoi The Gimp n'en a-t-il pas rajouté deux à la création, alors ?
    Quel foutoir, non mais quel foutoir !
    Sans compter qu'au plus je relis la phrase (tout en bas de la page), au moins je la comprends :
    The scan lines are DWORD aligned, except for RLE-compressed bitmaps. They must be padded for scan line widths, in bytes, that are not evenly divisible by four, except for RLE compressed bitmaps.
    Et la traduction de gougueul n'arrange pas trop les choses :
    Les lignes de balayage sont alignées par DWORD, à l'exception des bitmaps compressés RLE. Ils doivent être rembourrés pour les largeurs de la ligne de balayage, en octets, qui ne sont pas divisibles uniformément par quatre, à l'exception des bitmaps compressés RLE.
    Essayons d'y voir clair :
    la 1re phrase pourrait se récrire Les lignes de balayage sont alignées sur 4, à l'exception des bitmaps compressés RLE, donc divisibles par 4 sauf les RLE qui ne sont pas concernés.
    C'est ensuite que ça se corse : They must... gougueul a écrit Ils doivent, sous-entendu ça concerne ces fameux bitmaps RLE ? Sauf que la fin de la phrase les rejette : à l'exception des RLE. Donc en fait ça concerne les lignes de balayage, et donc Elles doivent être complétées (ah, le fameux padding !), pour celles qui ne sont pas divisibles par 4.
    Et ces phrases sont tellement alambiquées que les gens de 'toshop les ont mal comprises et se sont foutus dedans ?

    Ça se tient, mais pour en avoir le cœur net (en espérant que les développeurs de programmes chez Microsoft comprennent ce que les développeurs d'API chez Microsoft ont voulu dire ), XP, MSPaint, un fichier de 4x1x24, un autre de 5, un de 6 un de 7 et un de 8, empilés en ringuette : constatation que le padding ne s'applique pas aux lignes divisibles par 4, et fermez le ban (les données [des pixels jaunes, donc BGR et donc 00 FF FF] commencent par 00 à l'adresse 36, c'est la colonne du A de Aide) :

    Nom : fichiers45678x1x24.png
Affichages : 178
Taille : 72,3 Ko

    Pi le nombre de posts ici n'aide pas à la synthèse : on va atteindre la soixantaine pour un problème qui n'aurait jamais dû exister.


    Et surtout ne raccrochez pas, je vous en ai mitonné un tout mignon tout choupinet pour demain matin, certains vont se régaler (stay tuned, Andnotor, ça te concerne, toi et ta démo d'alignement...)

    En attendant, les cadeaux du soir :
    un résumé synthétique des infos en provenance directe de MSDN et concernant les BitmapFileHeader et BitmapInfoHeader, et comme c'est un fichier image et que les liens n'y sont donc pas cliquables, ben dessous la même chose en pdf, à télécharger et à garder précieusement.
    Nom : format_bitmap.png
Affichages : 207
Taille : 125,0 Ko
    format_bitmap.pdf

    See you tomorrow morning
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  20. #60
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 419
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 419
    Points : 5 818
    Points
    5 818
    Par défaut
    Salut

    la traduction serait :

    le padding sur 4 octets n'est valable que pour les données brutes.
    Pour un fichier compressé RLE, ce n'est absolument pas nécessaire.
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

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

Discussions similaires

  1. Résultat \backslashbox très mauvais
    Par ToTo13 dans le forum Mise en forme
    Réponses: 8
    Dernier message: 09/06/2011, 22h53
  2. Image d'un bouton : mauvais rendu
    Par t.n.b.g dans le forum WinDev
    Réponses: 1
    Dernier message: 24/06/2008, 15h00
  3. Réponses: 1
    Dernier message: 13/05/2008, 10h44
  4. Pom tantot bon tantot mauvais ?
    Par spekal dans le forum Maven
    Réponses: 3
    Dernier message: 21/11/2006, 11h04
  5. Rendu images Photoshop=>Flash très mauvais
    Par jul2006 dans le forum Flash
    Réponses: 8
    Dernier message: 12/09/2006, 13h35

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