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 :

Comparer deux fichiers Bitmap [Lazarus]


Sujet :

Lazarus Pascal

  1. #1
    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 Comparer deux fichiers Bitmap
    Hello, it's me again -- désolé.

    Je ne voulais pas vous embêter si vite mais franchement, il y a des jours on se demande...

    Suite à mes récents déboires avec des images transparentes qui ne devraient pas l'être, je me suis mis en tête de bricoler vite fait un petit outil pour comparer des fichiers.
    En même temps je me proposais de tester l'astuce que m'a passée anapurna concernant Scanline, mais on verra ça après, parce que d'entrée ça part mal.

    Est-ce que vous voyez un défaut à cet algo (le premier fichier est parfaitement bien chargé par ailleurs, ça, ça concerne le second fichier et la comparaison) ?
    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
    procedure TForm1.Button2Click(Sender: TObject);
    var
      pic: TPicture;
      p1,p2: pRGBQuad;
      h,w: integer;
    begin
      if not opd.Execute then exit;
      pic := TPicture.Create;
      try
        pic.LoadFromFile(opd.Filename); // chargement du fichier
        imgDisplay.Picture.Bitmap.BeginUpdate;
        // parcours vertical
    //    for h := 0 to imgDisplay.Picture.Bitmap.Canvas.Height-1 do begin
    //    for h := 0 to imgDisplay.Picture.Bitmap.Height-1 do begin
        for h := 0 to imgDisplay.Height-1 do begin
    //      p1 := pRGBQuad(imgDisplay.Picture.Bitmap.ScanLine[h]);
    //      p2 := pRGBQuad(pic.Bitmap.Scanline[h]);
    // dessus en attente que ça fonctionne dessous
          p1 := pRGBQuad(imgDisplay.Picture.Bitmap.RawImage.GetLineStart(h));;// source
          p2 := pRGBQuad(pic.Bitmap.RawImage.GetLineStart(h));// second fichier
          // parcours horizontal
    //      for w := 0 to imgDisplay.Picture.Bitmap.Canvas.Width-1 do begin
    //      for w := 0 to imgDisplay.Picture.Bitmap.Width-1 do begin
          for w := 0 to imgDisplay.Width-1 do begin
            if pRGBQuad(p1[w]) <> pRGBQuad(p2[w]) then begin // test et action si différence
              // 2 lignes pour voir la vie des choses
              memo1.Lines.Add(inttostr(h)+' '+inttostr(w));// de 299 303 à 299 399 -- le fic de test fait 400 x 300
              Application.ProcessMessages;
    // obligé de mettre ces 4 lignes en commentaire sinon SIGSEGV en fin de boucle
    {          p1[w].rgbBlue :=0;
              p1[w].rgbGreen:=0;
              p1[w].rgbRed  :=255;
              p1[w].rgbReserved:=255;   }
            end; // test
          end; // for w
        end; // for h
        imgDisplay.Picture.Bitmap.EndUpdate;
      finally
        pic.Free;
      end;
    end;
    Vous noterez que j'ai fait trois tentatives de balayage, avec toujours le même résultat, SIGSEGV

    Et maintenant le truc qui tue, indépendamment de l'AV en fin de boucle : pour tester, avant de m'embarquer avec des fichiers dont je ne sais pas où sont les différences et s'il y en a, je teste en ouvrant deux fois le même fichier, et j'ai des lignes logguées dans le mémo !

    Mais comment c'est possible un cauchemar pareil ?

    Ah, tiens, si quelqu'un veut essayer rapidement, un TOpenPictureDialog, un TImage alClient dans un TPanel avec Color à clWhite et ça roule :
    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 TForm1.OpenImage(Filename: string);
    var
      pic: TPicture;
    begin
      pic := TPicture.Create;
      pic.Bitmap.Transparent:=False;
      try
        pic.LoadFromFile(Filename);
        if (pic.Width <> pnl4img.Width) or (pic.Height <> pnl4img.Height) then begin
          pnl4img.Width  := pic.Width;
          pnl4img.Height := pic.Height;
        end;
        imgDisplay.Picture.Assign(pic);
      finally
        pic.Free;
      end;
    end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      if opd.Execute then OpenImage(opd.FileName);
      Button2.SetFocus;
    end;
    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. #2
    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.

    On peut dire que tu m'en fais faire des tests !

    Malheureusement pour toi, c'est sous Windows.

    J'ai repris ton code de comparaison de deux bitmaps avec le code de mise en rouge "décommenté".
    Ces bitmaps sont créés sous PShop, enregistrés en mode windows 32bits. Le deuxième a une toute petite différence avec le premier.
    Ils sont "loadés" en runtime.
    Résultat : Cela marche impec ! Seuls les pixels différents sont peints en rouge.

    Alors, où est ton erreur ? Je n'en sais rien.

    Bonne soirée.
    Thierry

  3. #3
    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
    Bonsoir Thierry,

    Citation Envoyé par ThWilliam Voir le message
    On peut dire que tu m'en fais faire des tests !


    Citation Envoyé par ThWilliam Voir le message
    Malheureusement pour toi, c'est sous Windows.
    J'oublie toujours de tester dans cet environnement : quand ce sur quoi je bosse part en live, je m'engraine dessus et zappe complètement l'autre environnement

    Citation Envoyé par ThWilliam Voir le message
    Résultat : Cela marche impec ! Seuls les pixels différents sont peints en rouge.

    Alors, où est ton erreur ? Je n'en sais rien.
    Tu m'achèves, là. Tu me rassures cependant sur le fait que ça fonctionne comme je l'espérais.

    Mais tu m'achèves d'autant plus qu'après avoir posté j'ai farfouillé dans des vieux codes à la recherche d'une idée, et suis retombé sur un truc inutile mais qui fonctionne, une copie 1/1 à base de scanline ; je le mets ici, des fois que quelqu'un veuille l'étudier, mais bon, y a qu'une ligne, hein !
    Mais j'ai trouvé que ça ressemblait à ce que j'ai posté cet aprème, alors voilà :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
      with dst do begin
        Width:=src.Width; Height:=src.Height; // copie 1/1 pour le moment
        try
          BeginUpdate();
          for h := 0 to src.Height-1 do begin
            ps := pRGBQuad(src.RawImage.GetLineStart(h)); // scanline source
            pd := pRGBQuad(dst.RawImage.GetLineStart(h)); // scanline dest.
            for w := 0 to src.Width-1 do pd[w] := ps[w]; // la copie pRGBQuad par pRGBQuad
          end;
        finally
          EndUpdate();
        end;
      end;
    Bon, ben je vais chercher, mais où ?

    EDIT :
    Citation Envoyé par ThWilliam Voir le message
    Ces bitmaps sont créés sous PShop, enregistrés en mode windows 32bits.
    D'accord, mais, en mode BMP ou JPG ?

    Parce que sans rien changer au code j'arrive à faire fonctionner la comparaison sur des .jpg mais c'est moche à cause des artefacts,
    Nom : compar_a_b.png
Affichages : 438
Taille : 9,4 Ko la 1re image a un A rouge (tiens, faudrait que je change la couleur de comparaison), la 2e a un B, au même endroit.

    Par contre, en mode BMP c'est le SIGSEGV, que j'utilise 2 fois le même fichier ou 2 fichiers différents.
    J'en ai maaaaaaaaaaaaaaaaaaarre de cette informatique de pieds nickelés .
    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. #4
    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
    Salut je viens de tester avac laz1.8rc1 32bits j'obtiens ça
    Nom : 2017-06-04_231609.jpg
Affichages : 448
Taille : 17,0 Ko

    Tu es sous linux ? non ? car la definitions de

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
         RGBQUAD = record
              rgbBlue : BYTE;
              rgbGreen : BYTE;
              rgbRed : BYTE;
              rgbReserved : BYTE;
           end;
         tagRGBQUAD = RGBQUAD;
         TRGBQUAD = RGBQUAD;
         PRGBQUAD = ^RGBQUAD;
    se trouve dans l'unité windows. Elle est déclaré ou sous Linux et comment ?

    car là tu fais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     if pRGBQuad(p1[w]) <> pRGBQuad(p2[w]) then begin // test et action si différence
    P1 et P2 ne sont pas des tableaux (dans mon cas) dons normal que tu es un SIGSEGV
    Et de plus on ne peux pas comparer directement deux variable de type record A moins que les opérateurs soient surchargés. Il faut donc tester chaque membre 1 à 1.

    j'ai modifié 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
    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
    procedure TForm1.Button2Click(Sender: TObject);
      function RGBQuadIsEqual(c1,c2:TRGBQuad):Boolean;
      begin
        Result:=False;
        if ((c1.rgbBlue = c2.rgbBlue) and (c1.rgbGreen = c2.rgbGreen) and (c1.rgbRed = c2.rgbRed) and (c1.rgbReserved = c2.rgbReserved)) then result:= true;
      end;
     
    var
      pic: TPicture;
      p1,p2: pRGBQuad;
      h,w: integer;
    begin
      if not opd.Execute then exit;
      pic := TPicture.Create;
      try
        pic.LoadFromFile(opd.Filename); // chargement du fichier
        imgDisplay.Picture.Bitmap.BeginUpdate;
        // parcours vertical
        memo1.Lines.Add(inttostr(imgDisplay.Picture.Bitmap.Width)+' '+inttostr(imgDisplay.Picture.Bitmap.Height));
       for h := 0 to imgDisplay.Picture.Bitmap.Height-1 do
        begin
     
    // dessus en attente que ça fonctionne dessous
          p1 := pRGBQuad(imgDisplay.Picture.Bitmap.RawImage.GetLineStart(h));// source
          p2 := pRGBQuad(pic.Bitmap.RawImage.GetLineStart(h));// second fichier
          // parcours horizontal
          for w := 0 to imgDisplay.Picture.Bitmap.Width-1 do
          begin
            if not(RGBQuadIsEqual(p1^,p2^)) then
            begin // test et action si différence
              // 2 lignes pour voir la vie des choses
              memo1.Lines.Add(inttostr(h)+' '+inttostr(w));// de 299 303 à 299 399 -- le fic de test fait 400 x 300
             // Application.ProcessMessages;
     
              p1^.rgbBlue :=0;
              p1^.rgbGreen:=0;
              p1^.rgbRed  :=255;
              p1^.rgbReserved:=255;
            end; // test
            inc(p1);
            inc(p2);
          end; // for w
        end; // for h
        imgDisplay.Picture.Bitmap.EndUpdate;
      finally
        pic.Free;
      end;
    end;
    et ça roule et ha oui faut faire attention que soient bien des images 32bits et de dimensions identiques, évidemment

    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

  5. #5
    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
    Tu es sous linux ? Elle est déclarée où sous Linux et comment ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    uses
      LCLtype, // pour pRGBQuad
    Citation Envoyé par BeanzMaster Voir le message
    P1 et P2 ne sont pas des tableaux (dans mon cas) donc normal que tu aies un SIGSEGV
    Je n'ai pas de SIGSEGV avec les .jpg.

    Citation Envoyé par BeanzMaster Voir le message
    Et de plus on ne peut pas comparer directement deux variables de type record à moins que les opérateurs soient surchargés. Il faut donc tester chaque membre 1 à 1.

    - Thierry a dit que pour lui ça fonctionnait ;
    - as-tu vu mon code de copie ? for w := 0 to src.Width-1 do pd[w] := ps[w]; // la copie pRGBQuad par pRGBQuad Quelque part la comparaison c'est pareil, enfin, il me semble.

    'fin bon, j'ai testé ton code avec des .bmp 32 bits, je n'ai plus de SIGSEGV mais le machin ne compare rien ou plutôt, ne détecte aucune différence, or il y en a une, j'en suis sûr !

    Citation Envoyé par BeanzMaster Voir le message
    et ça roule et ha oui faut faire attention que soient bien des images 32bits et de dimensions identiques, évidemment
    Tu lis trop vite ! J'ai bien dit que le premier test je le faisais sur le même fichier (oui, de 32 bits) donc obligatoirement de la même taille (je suis neuneu, mais y a des limites, )
    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. #6
    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
    D'accord avec beanzmaster

    Citation Envoyé par BeanzMaster Voir le message
    P1 et P2 ne sont pas des tableaux (dans mon cas) dons normal que tu es un SIGSEGV
    Et en Delphi, ça ne compilerait même pas avec une erreur E2016.

    Citation Envoyé par BeanzMaster Voir le message
    Et de plus on ne peux pas comparer directement deux variable de type record
    C'est pour cela qu'il est obligé de transtyper. Après, le type utilisé (pRGBQuad) est parfaitement aléatoire et prête plus à confusion qu'autre chose, P1[w] (si tableau) étant un TRGBQuad (une valeur, une couleur) et non un pointeur.
    Ça entraînerait même des erreurs sporadiques en 64 bits puisque le dernier pixel/pointeur serait lu au-delà du bloc de données du bitmap. Mieux vaudrait transtyper en integer.

    Citation Envoyé par Jipété Voir le message
    - as-tu vu mon code de copie ? for w := 0 to src.Width-1 do pd[w] := ps[w]; // la copie pRGBQuad par pRGBQuad Quelque part la comparaison c'est pareil, enfin, il me semble.
    Pas pRGBQuad mais TRGBQuad comme dit précédemment.

    Il y a d'autres contraintes avec les record et la comparaison ne pourrait fonctionner qu'en étant sûr qu'ils ont été initialisés à zéro ou qu'il y ait un Dest^ := Source^ quelque part.

    S'ils sont unpacked, que contiennent les paddings ? => ils sont indéterminés.
    S'ils contiennent une chaînes, disons string[10], et qu'on ne remplit que deux caractères, que valent les huit autres ? => ils sont aussi indéterminés.

    Ça devient compliqué pour le compilateur

  7. #7
    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
    Tu lis trop vite ! J'ai bien dit que le premier test je le faisais sur le même fichier (oui, de 32 bits) donc obligatoirement de la même taille (je suis neuneu, mais y a des limites, )
    Je dis ça car les jpeg sont des fichiers 24bits en général mais jamais 32bits.(Pas de prise en charge de la transparence dans ce format) Mais ça à l'air de fonctionner pareil, ici pourquoi (car les pixels dans le rawimage ont une taille de 4 bytes (32bits) car sinon faudrait utiliser un TRGBTrible et non TRGAQuad. Le mieux est de tester le pixelformat (enfin mieux vaut se fier au RawImage.Description.Depth) et dirigé vers la bonne fonction 24 ou 32bits. Apres le pourquoi du comment c'est dans la sauce interne de la gestion des bitmap de la LCL.

    Sinon avec ton code que j'ai modifié les JPG passent, et les fichiers 32bits BMP également sans soucis
    • "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

  8. #8
    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 fait, au départ je ne voulais pas fouiller le site et au-delà le web (l'idée ne m'était même pas venue à l'esprit), j'étais parti en me disant que ça serait bouclé en 5 minutes, comme pour la copie qui, soit dit en passant, fonctionne très bien à partir de pRGBQuad.
    Mais ça doit être un coup de bol, de hasard, si je comprends bien.
    Va falloir que je revoie tous mes codes à base de scanline ? Fouhhh, suis pas rendu...
    Et si la détection chez Thierry fonctionne bien, c'est aussi un coup de bol ? Thierry, revois tes codes !

    Bon, en attendant et pour pouvoir répondre à Andnotor, je suis allé fouiller dans mes vieilles docs, j'y ai retrouvé un tuto de nono40 qui est la traduction d'un truc énorme d'efg (28 pages !), et dedans il y avait un petit lien "exemple de comparaison de deux images", hé hé hé !

    J'avais la solution sous la main !
    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
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    // For bitmaps of the same size, count the number of pixels that match
    // and the number that are different.
    PROCEDURE CompareBitmaps(CONST BitmapA, BitmapB:  TBitmap;
                             VAR Total, Match, Differ:  INTEGER);
      TYPE
        TRGBTripleArray =  ARRAY[WORD] OF TRGBTriple;
        pRGBTripleArray =  ^TRGBTripleArray;
      VAR
        i   :  INTEGER;
        j   :  INTEGER;
        rowA:  pRGBTripleArray;
        rowB:  pRGBTripleArray;
    BEGIN
      ASSERT( (BitmapA.width  = BitmapB.width) AND
              (BitmapA.height = BitmapB.height),  'Different sizes');
     
      // Force bitmaps to have the same pf24bit Pixelformat
      // (this may be undesirable, for example, for large pf1bit bitmaps)
      BitmapA.PixelFormat := pf24bit;
      BitmapB.PixelFormat := pf24bit;
     
      Total  := BitmapA.width * BitmapA.height;
      Match  := 0;
      Differ := 0;
     
      FOR j := 0 TO BitmapA.height-1 DO
      BEGIN
        rowA := BitmapA.Scanline[j];
        rowB := BitmapB.Scanline[j];
     
        FOR i := 0 TO BitmapA.width-1 DO
        BEGIN
     
    {$IFDEF DELPHI5}
    {$DEFINE SIMPLEWAY}
    {$ENDIF}
     
    {$IFDEF DELPHI6}      // should work in D6
    {$DEFINE SIMPLEWAY}
    {$ENDIF}
     
    {$IFDEF SIMPLEWAY}    // update this for D7 or later
          // new easy way for D5 or later (actually D4.02 and later)
          IF   rowA[i] = rowB[i]
          THEN INC(Match)
          ELSE INC(Differ)
    {$ELSE}              // D3 and D4 cannot use "simple" way
          // "bug" in earlier versions forces more code for test
          // chapeau sinon compilo pas content ! -- modif jpt
          IF   (rowA^[i].rgbtRed   = rowB^[i].rgbtRed)   AND
               (rowA^[i].rgbtGreen = rowB^[i].rgbtGreen) AND
               (rowA^[i].rgbtBlue  = rowB^[i].rgbtBlue)
          THEN INC(Match)
          ELSE begin INC(Differ);
          form1.memo1.Lines.Add(inttostr(j)+' '+inttostr(i)); // ajout jpt
          end;
    {$ENDIF}
        END
      END
    END {CompareBitmaps};
     
    procedure TForm1.Button3Click(Sender: TObject);
    // http://nono40.developpez.com/tutoriel/delphi/efg/scanline/fichiers/CompareTBitmaps.TXT
    VAR
      Bitmap1:  TBitmap;
      Bitmap2:  TBitmap;
      PixelsDiffer:  INTEGER;
      PixelsMatch :  INTEGER;
      PixelsTotal :  INTEGER;
    begin
      Bitmap1 := TBitmap.Create;
      Bitmap2 := TBitmap.Create;
      TRY
        Bitmap1.LoadFromFile('/_share_4_VM/Programmation/bart/img_4_tests/400x300x32_v3_96.bmp');
        Bitmap2.LoadFromFile('/_share_4_VM/Programmation/bart/img_4_tests/400x300x32_v3M_96.bmp');
     
        CompareBitmaps(Bitmap1, Bitmap2, PixelsTotal, PixelsMatch, PixelsDiffer);
     
        // Sample output:  Total=307200, Match=265, Differ=306935
        ShowMessage(Format('Total=%d, Match=%d, Differ=%d',
                           [PixelsTotal, PixelsMatch, PixelsDiffer]));
      FINALLY
        Bitmap1.Free;
        Bitmap2.Free
      END
    end;
    et juste comme ça, ça fonctionne (source originale : encore efg ! Quel homme !), le log dans le mémo montre bien les coordonnées modifiées entre les deux fichiers (une lettre rajoutée), plus qu'à l'adapter pour mettre ça en couleur.

    Juste un point de détail : le compilo n'apprécie pas du tout que je définisse SIMPLEWAY, il me crie fort dessus à la ligne 44, IF rowA[i] = rowB[i], avec le message Error: Operator is not overloaded: "TRGBTripleArray" = "TRGBTripleArray" . Bah, l'autre manière de faire fonctionne, alors bon,
    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. #9
    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
    Bon,

    j'ai regardé posément le code d'efg, j'ai apporté une modification à la procédure de comparaison :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    //    BitmapA.PixelFormat := pf24bit;
    //    BitmapB.PixelFormat := pf24bit;
    Citation Envoyé par BeanzMaster Voir le message
    Le mieux est de tester le pixelformat (enfin mieux vaut se fier au RawImage.Description.Depth)
    et comme j'avais dit ailleurs que je ne voulais plus entendre parler de RawImage, j'ai donc mis en place une récupération de l'info dans le BitmapInfoHeader, c'est testé ça fonctionne ; début de la proc du bouton :
    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
    begin
      PixelsTotal:=0; PixelsMatch:=0; PixelsDiffer:=0; // happy compilo
      if not opd.Execute then exit;
      f1 := opd.FileName;
      if not opd.Execute then exit;
      f2 := opd.FileName;
      pf1:=ReturnsPixelFormat(f1);
      pf2:=ReturnsPixelFormat(f2);
      ASSERT( (pf1 = pf2),  'Different PixelFormats');
     
      Bitmap1 := TBitmap.Create;
      Bitmap2 := TBitmap.Create;
      TRY
        Bitmap1.LoadFromFile(f1);
        Bitmap2.LoadFromFile(f2);
        // ASSERT déplacé de la proc CompareBitmaps à ici
        ASSERT( (Bitmap1.width  = Bitmap2.width) AND
                (Bitmap1.height = Bitmap2.height),  'Different sizes');
    et en cas de différence, dans la proc de comparaison j'ai rajouté la modification des pixels (élémentaire pour le moment) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
      ELSE 
      begin
        INC(Differ);
        memo1.Lines.Add(inttostr(h)+' '+inttostr(w)); // ajouts jpt
        BitmapA.BeginUpdate();
        rowA^[w].rgbtBlue :=0;
        rowA^[w].rgbtGreen:=255;
        rowA^[w].rgbtRed  :=0;
        BitmapA.EndUpdate();
      end;
    Toute cette cuisine fonctionne :
    Nom : comparM.png
Affichages : 420
Taille : 74,6 Ko
    l'image en haut à gauche au lancement de la proc a un joli ciel de printemps fin d'après-midi et le M rouge en bas à droite est le fichier modifié.
    Bien bien bien.

    Sauf que...
    Sauf que ces fichiers sont des 32 bits et qu'il faut que je sois configuré ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        VAR
          h,w :  INTEGER;
          rowA:  pRGBTripleArray;
          rowB:  pRGBTripleArray;
    //      rowA:  pRGBQuadArray;
    //      rowB:  pRGBQuadArray;
    sinon c'est SIGSEGV garanti ! Pourquoi ? Car je ne vois aucune différence mis à part les noms des choses et le 4e byte pour le canal Alpha. J'ai recopié le bout concerné de LCLType, pour comparer :
    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
        TYPE
          {extrait de LCLType :
            PRGBTriple = ^TRGBTriple;
            tagRGBTRIPLE = record
              rgbtBlue: Byte;
              rgbtGreen: Byte;
              rgbtRed: Byte;
            end;
            TRGBTriple = tagRGBTRIPLE;
            RGBTRIPLE = tagRGBTRIPLE;
     
            PRGBQUAD = ^TRGBQUAD;
            tagRGBQUAD = record
              rgbBlue : BYTE;
              rgbGreen : BYTE;
              rgbRed : BYTE;
              rgbReserved : BYTE;
            end;
            TRGBQuad = tagRGBQUAD;
            RGBQUAD = tagRGBQUAD;   }
          TRGBTripleArray =  ARRAY[WORD] OF TRGBTriple;
          pRGBTripleArray =  ^TRGBTripleArray;
          TRGBQuadArray =  ARRAY[WORD] OF TRGBQuad;
          pRGBQuadArray =  ^TRGBQuadArray;
    Ce que j'ai fait a été d'inventer les pRGBQuadArray et TRGBQuadArray en m'inspirant des pRGBTripleArray et TRGBTripleArray.
    À toi, Andnotor, car là, moi, je suis sec.
    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

  10. #10
    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
    Citation Envoyé par Jipété Voir le message
    Juste un point de détail : le compilo n'apprécie pas du tout que je définisse SIMPLEWAY, il me crie fort dessus à la ligne 44, IF rowA[i] = rowB[i], avec le message Error: Operator is not overloaded
    C'est ce que te disait BeanzMaster : tu ne peux pas directement comparer deux record sans définir un operator d'équivalence.

    Et ce n'est pas un détail, c'est exactement ce que tu faisais au départ qui ne fonctionne pas. Y a-t-il eu un essai de comparaison de record il y a... 17 ans (octobre 2000) ? Peut être, mais ça n'a manifestement pas fait long feu

    Citation Envoyé par Jipété Voir le message
    comme pour la copie qui, soit dit en passant, fonctionne très bien à partir de pRGBQuad.
    Oui mais non. pd est un pointeur, pd[w] est une valeur. pd[w] := ps[w], ce n'est pas une copie de pointeur mais de valeur, soit un TRGBQuad.
    L'activation de la syntaxe étendue fait que tu peux simplifier l'écriture. Ce qui se passe derrière est effectivement pd^[w] := ps^[w].

  11. #11
    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
    [...] Ce qui se passe derrière est effectivement pd^[w] := ps^[w].
    Ah ouais, mais alors, s'il se passe des trucs dans mon dos je n'y arriverai pas...

    Surtout si en plus personne ne percute sur les trucs que je considère les plus importants :
    • cité vers 15 h : il faut que j'active RGBTriple pour comparer des fichiers 32 bits ! Ça ne choque personne ? Genre il faut que je loue un bus de 24 places pour trimbaler 32 gamins au parc.
    • découvert ensuite : ai fouillé le web de fond en comble ("freepascal compare bitmap", il y a plein de réponses avec Delphi et quasiment rien avec FP [comm' d'hab' quoi]), ai vu plein de codes + ou - similaires, il n'y a rien qui fonctionne : soit ça ne trouve aucune différence, soit ça trouve tous les pixels en différence, avec des codes basés sur pByte, sur CompareMem, etc.

    Exemples :
    http://embarcadero.newsgroups.archiv...202254871.html
    http://delphidabbler.com/tips/145

    Y a des jours j'ai vraiment l'impression que mon carrosse a perdu une roue et qu'en plus il est tiré par un cheval boiteux...

    Pi là,
    Citation Envoyé par Andnotor Voir le message
    [...] Ce qui se passe derrière est effectivement pd^[w] := ps^[w].
    il faudrait m'expliquer plus en détail parce que dans mon code de copie, si je tape ce qui se passe derrière avec les petits chapeaux, je gagne
    Citation Envoyé par compilo_sans_humour
    Error: No default property available
    Fatal: Syntax error, ";" expected but "[" found
    avec le curseur qui clignote entre le 1er petit chapeau et le 1er crochet ouvrant.

    Citation Envoyé par Andnotor Voir le message
    [...] L'activation de la syntaxe étendue fait que tu peux simplifier l'écriture.
    Ça se cache où, le réglage de cette engeance ?

    Bon, j'ai encore la comparaison avec les streams à tester, et l'utilisation de PIntegerArray (en gros je pars dans tous les sens parce que le truc basique qui aurait dû être torché en 5 minutes m'a pété entre les mains, comme un artificier novice...)
    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. #12
    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,

    je vais essayer de vous la faire courte, je vous préviens c'est un truc à s'arracher les cheveux (heureusement j'en ai beaucoup).
    Prêts ?

    Hier j'ai donné deux liens, j'avais noté d'autres codes au cours de mes pérégrinations sur le web, hier soir tard j'ai testé, ce matin j'ai testé dans XP les tests d'hier, il en sort ça, avec un bon point pour XP, les défauts sont les mêmes que sous Linux :
    • checkifdifferent = résultat ok fic24 comme fic32
    • utilise des streams = ne détecte pas les fichiers différents, fic24 comme fic32
    • utilise pintegerarray = détecte différents les fichiers identiques, fic24 comme fic32
    • embarcadero utilise comparemem = idem dessus


    Il y en a donc un qui fonctionne correctement ! Verrait-on le bout du tunnel ? Son algo, très basique :
    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
      function CheckIfDifferent(bmp1, bmp2: TBitmap): boolean;
      // http://freedelphitutorials.blogspot.fr/2015/04/how-to-compare-2-images.html
      var
        p1, p2  : pByte;
        h, w    : integer;
        checkRes: boolean;
      begin
        checkRes := false;
        h:=0;
        while not (checkRes) and (h < bmp1.Height) do begin
          p1 := bmp1.Scanline[h];
          p2 := bmp2.Scanline[h];
          w := 0;
          while not (checkRes) and (w < bmp1.Width) do begin // on dirait qu'on parcourt par bytes -- il est faux ce parcours ?
            if Integer(p1^) <> Integer(p2^)
            then checkRes := true 
            else begin inc(p1); inc(p2); end;
            inc(w);
          end;  
        result := checkRes;
      end;
    Testé donc avec fichier 24 bits, fichier 32 bits, sous XP et Linux, ça fonctionne, pas d'AV, bien bien bien.

    Sauf que je suis curieux, et que je voulais voir où les détections se passaient. Bien m'en a pris de vouloir logguer h et w, j'ai découvert un truc de fou, que je ne soupçonnais pas.
    J'ai rajouté un paramètre à la fonction CheckIfDifferent(var BytesPerPixel: integer; bmp1, bmp2: TBitmap): boolean; et je vous laisse lire les commentaires :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //      for w := 0 to (bmp1.Width * BytesPerPixel)-1 do begin // on dirait qu'on parcourt par bytes --> modif en multipliant par BPP
    // dessous forcé pour test avec fic32 (car BytesPerPixel à 4 [fic32] montre 3 bytes only par pixel dans le log...)
          for w := 0 to (bmp1.Width * 3)-1 do begin // juste pour voir
            if Integer(p1^) <> Integer(p2^)
            then begin memo1.lines.Add(inttostr(h)+' '+inttostr(w)+' '+inttostr(Integer(p1^))+' '+inttostr(Integer(p2^))); end;
    // confirmé : le byte alpha n'existe pas dans le log
    // donc ce qui est pris en compte dans les couches de bas niveau auxquelles je n'accède pas,
    // c'est un PixelFormat à pf24bit malgré le fichier 32 bits et le PixelFormat du header à pf32bit...
            inc(p1); inc(p2);
          end;
    Tout ça pour dire que si les bytes RGB d'un pixel sont identiques mais que son canal Alpha est différent, ça ne sera pas détecté.
    Au final, cette histoire de Scanline c'est pas glop

    Va falloir trouver autre chose, mais comme noté plus haut,
    • utilise des streams = ne détecte pas les fichiers différents, fic24 comme fic32
    • utilise pintegerarray = détecte différents les fichiers identiques, fic24 comme fic32
    • embarcadero utilise comparemem = idem dessus


    J'avais dit "3 jours" dans le titre (ah tiens, on me l'a modifié ), je risque de dépasser...
    (d'autant plus que j'ai découvert au passage que le contenu des fichiers BMP n'était pas toujours ce qu'on demandait et supposait -- mais je ne sais pas encore si je poste ça ici ou dans des sous-forums plus appropriés sur l'image, ou si c'est The Gimp qui nous fait un caca nerveux...)
    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. #13
    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 jp

    tu te fais des nœuds à la tète tout seul. je m'explique
    tu peut très bien faire ton test sur le width mais dans ta boucle pour chaque tour in te faudra vérifier le pixel et sa définition
    si c'est du 32 le pixel = 4 byte si c'est du 24 le pixel = 3 byte inférieur a 16 = 1 byte
    il est donc recommandé de comparer les fichier ayant les même caractéristiques
    si ce n'est pas le cas il faut que tu passe en paramètre les caractéristique de chaque fichier
    après pour comparer ce qui est comparable il te faut transformer tes éléments en element de même caractéristique

    imaginons que pour plus de facilite je défini mon propre enregistrement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
       TmaRecord = Record 
          Posi      = Integer;
          Rouge   = Byte;
          Vert     = Byte;
          Bleu     = Byte;
          Alpha   = Byte;
      end;
    Tu crée Pour chaque définition une fonction

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
       Fonction Transform24ToPerso(Datas : Pointer;Position : integer) :TmaRecord; 
       Fonction Transform16ToPerso(Datas : Pointer;Position : integer) :TmaRecord; 
       Fonction Transform1ToPerso(Datas : Pointer;Position : integer)   :TmaRecord; 
       Fonction Transform32ToPerso(Datas : Pointer;Position : integer) :TmaRecord;
    ...
    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
     
      Fonction Transform24ToPerso(Datas : Pointer;Position : integer) :TmaRecord; 
      begin
         Result.Posi     := Position;
         Result.Rouge  := Datas[Position]^
         Result.Vert    := Datas[Position+1]^
         Result.Bleu    := Datas[Position+2]^
         Result.Alpha  := 255;
         inc(Datas,3);
      End;
      //////////////////////////////////
      Fonction Transform32ToPerso(Datas : Pointer;Position : integer) :TmaRecord; 
      begin
         Result.Posi     := Position;
         Result.Rouge  := Datas[Position]^
         Result.Vert     := Datas[Position+1]^
         Result.Bleu     := Datas[Position+2]^
         Result.Alpha   := Datas[Position+3]^;
         inc(Datas,4);
      End;
      // ...
      TransformToPerso(Datas : Pointer;Position,BytesPerPixel : integer) :TmaRecord;
      begin
         Case BytesPerPixel of 
           1    : Result  :=  Transform1ToPerso(Datas,Position);
           16  : Result  :=  Transform16ToPerso(Datas,Position);
           24  : Result  :=  Transform24ToPerso(Datas,Position);
           32  : Result  :=  Transform32ToPerso(Datas,Position);
           ....
        else
          fillechar(Result,sizeof(TmaRecord),0) ;
        end;
       end;
      //----------------------------------------------
    donc imaginons que tu est deux images n'ayant pas le meme format il te faudra faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
        checkRes := False;
    //   Width := Min( bmp1.Width, bmp2.Width);// on prend la plus petite longueur
       checkRes := bmp1.Width = bmp2.Width; // on verifie que les taille sont identique
       p1 := bmp1.Scanline[h];
       p2 := bmp2.Scanline[h];
       While not(checkRes) and W < Width do 
       begin
          c1 := TransformToPerso(p1,w,24);
          c2 := TransformToPerso(p2,w,32);
          if  c1 <> c2 Then 
             checkRes := False;
          Inc(w); 
       End;
    voila globalement la marche à suivre
    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

  14. #14
    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 anapurna Voir le message
    il est donc recommandé de comparer les fichier ayant les même caractéristiques
    C'est ex-ac-te-ment ce que je fais avant même d'appeler la fonction de comparaison, pas de souci de ce côté-là.
    J'attends que les choses simples fonctionnent pour passer aux compliquées.

    Citation Envoyé par anapurna Voir le message
    si c'est du 32 le pixel = 4 byte si c'est du 24 le pixel = 3 byte inférieur a 16 = 1 byte
    Pourquoi 1 byte ? J'ai déjà vu des paddings à 2 ou 3 bytes...

    Citation Envoyé par anapurna Voir le message
    tu te fais des nœuds à la tête tout seul.
    Euh, pas tant que ça, je crois. En fait c'est ScanLine qui me met la pagaille : quand je prends un fichier 32 bits et que je fais tourner ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for w := 0 to (bmp1.Width * BytesPerPixel)-1 do begin 
      if Integer(p1^) <> Integer(p2^) then 
        memo1.lines.Add(inttostr(h)+' '+inttostr(w)+' '+inttostr(Integer(p1^))+' '+inttostr(Integer(p2^)));
    je vois bien avec mes yeux dans le mémo qu'il n'y a que 3 bytes par pixel, alors que j'en vois 4 avec le même fichier dans un afficheur hexa.

    D'ailleurs c'est ce que je disais hier :
    il faut que j'active RGBTriple pour comparer des fichiers 32 bits ! Ça ne choque personne ? Genre il faut que je loue un bus de 24 places pour trimbaler 32 gamins au parc.
    Sous-entendu (maintenant j'ai compris !) un gamin sur 4 (le gamin alpha ! ) est laissé au bas des marches de la porte du bus.

    Pas plus à dire...

    Ah si ! J'ai testé ton helper, il fonctionne mais au final je vais zapper Scanline pour attaquer directement la mémoire avec les infos remontées par BitmapInfoHeader.
    Là je contrôlerai tout du début à la fin.
    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. #15
    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
    Citation Envoyé par Jipété Voir le message
    je vois bien avec mes yeux dans le mémo qu'il n'y a que 3 bytes par pixel
    Et comment peux-tu voir ça dès lors que tu lis systématiquement 4 octets integer(p1^)

    De plus et du fait que la boucle soit fausse (inc(p1) décale de un octet et non de un pixel) tu dois obligatoirement te retrouver à un moment ou un autre avec des valeurs supérieures ou égales à 224 (à moins que l'image soit noire).

  16. #16
    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

    quand c'est inférieur à 16 c'est du mono dans mon souvenir donc
    1 byte suffisais a définir le pixel
    au delà c’était un index dans une table ou la couleur était défini à l'avance
    j'ai donné ce code a titre d'exemple il est pas a prendre tels quel
    il ne tiens pas compte de la compression non plus et diverses petite subtilité



    Ps : sur le liens d'hier c'est normal tu compare que des triplet
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
       if not CompareMem(Pr, Ps, SizeOf(TRGBTriple)) then
    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

  17. #17
    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
    Et comment peux-tu voir ça dès lors que tu lis systématiquement 4 octets integer(p1^)
    Parce qu'on croit lire systématiquement 4 octets !

    Regarde :
    1er pixel différent entre l'original (en haut) et le modifié (avec le M rouge et la souris dessus, pour que la loupe fasse son office).
    Nom : lena_et_loupe.png
Affichages : 412
Taille : 228,8 Ko

    Regarde bien le mémo 3e colonne : c'est l'original, et le carré noir dans la loupe montre où je "pipette" la couleur, 1 pixel à gauche du rouge (ça n'aurait présenté aucun intérêt d'être dessus) et 4e colonne c'est integer(p2^) où on voit bien les suites rouges (0 0 225, RGB inversé), on attaque en haut à gauche du M.
    (1re colonne c'est h du balayage vertical, 2e colonne c'est w de l'horizontal).
    Quant au bleu dans l'original, il fluctue un poil 201 dans la loupe mais pas dans le mémo, puis 202 ... 203 ... 202, les deux autres sont stables (217 222)

    Si on regarde bien, on a l'impression que le carré noir de la loupe est presque à la même distance du bord gauche et du bord haut, presque, hein, à peine un poil plus court en largeur, or le mémo dit 22 et 57.
    Oui ! Parce que 57 / 3 = 19 et 19 c'est presque 22.
    22 c'est la ligne de pixels, et 57 c'est le byte dans la ligne en cours d'analyse, pas le pixel. Si on parlait en colonnes, on dirait 22 (de haut) 19 (depuis le bord), ce qui correspond à la grande image (pas la loupe, qui ne montre pas les bords, méfiance !)


    Citation Envoyé par Andnotor Voir le message
    De plus et du fait que la boucle soit fausse (inc(p1) décale de un octet et non de un pixel) tu dois obligatoirement te retrouver à un moment ou un autre avec des valeurs supérieures ou égales à 224 (à moins que l'image soit noire).
    Elle est fausse ? Elle me va très bien, je peux comparer les octets, je pourrai choper l'alpha, bientôt !

    Et le plus fou, donc, c'est que si je teste avec deux fichiers 32 bits, le résultat dans le mémo est le même ! Pas de copie d'écran, croyez-moi sur parole, merci.
    J'ai même rajouté, tout en fin de boucle,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
          inc(h);
        end;
        memo1.lines.Add(inttostr(h)+' '+inttostr(w)); // 300 1199 avec fic 24 (1199 = 400x3 -1)
    400 parce que mes fichiers font 400 px de large sur 300 lignes de haut.

    Et lol de lol, j'ai les deux mêmes valeurs avec mon fichier 32 bits, or à aucun moment je n'interviens sur ces paramètres ! Au contraire même, la proc appelante force le bmp.PixelFormat en fonction du BitmapInfoHeader (et j'ai vérifié à coups de ShowMessage, c'est good).
    La seule intervention qui peut mettre sa pagaille, c'est les bmp.Scanline[h], je ne vois que ça...


    Citation Envoyé par anapurna Voir le message
    quand c'est inférieur à 16 c'est du mono dans mon souvenir donc
    1 byte suffisait à définir le pixel
    J'ai lu à la va-vite (suis pressé c't'aprème...), j'ai cru à une histoire de padding, désolé.
    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. #18
    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
    Mea Culpa ! J'ai dit une bêtise, c'est bien sûr PInteger(p1)^ qui lirait quatre octets.

  19. #19
    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 salut,

    allez, pour vous mettre l'eau à la bouche, voici un petit intermède sympathique :
    Nom : compar_transparences3.png
Affichages : 403
Taille : 47,0 Ko
    • à gauche le fichier original avec canal alpha, plusieurs calques tous avec l'opacité à 100 % et une exportation A8R8G8B8 demandée à The Gimp. -- Basique.
    • au milieu j'ai rajouté un calque "nouveau depuis le visible" en haut de la pile et je lui ai descendu l'opacité à 80 %, puis j'ai décoché la visibilité de tous les calques dessous SAUF le fond tout en bas, qui est blanc, et export comme précédemment.
    • à droite je me suis ensuite contenté de juste décocher la visibilité du calque blanc du fond, résultat l'image s'est affichée avec le damier matérialisant la transparence, et export comme les deux autres. Vous allez me dire "mais elle n'est pas transparente ton image !" "Bah nan je réponds, voir dessous la seconde constatation..."

    Analyse :
    les 4 bytes qu'on lit proviennent de l'affichage d'un éditeur hexa et représentent ce que voit une pipette positionnée sur le coin complètement en haut à droite de l'image.
    • Première constatation, l'ordre des bytes n'est pas A8R8G8B8 tel que demandé dans la fenêtre des options avancées d'exportation, mais B8G8R8A8 (confirmé au colorpicker). Pourquoi ? Mystère... Mais la liste des 4 bytes de chaque pixel serait-elle parcourue à l'envers ?
    • Seconde constatation sur l'image de droite : là le canal alpha a changé (CChex ça fait 20410 et 255 x 80 / 100 = 204, rappel : le calque a une opacité de 80 %) et les couleurs sont intactes ; ce n'est pas vraiment ce qu'on voit à l'écran, mais d'après ce que j'ai compris, mon environnement de bureau sous Linux ne gère pas la transparence.

    Voilà.

    Et du coup je profite de ce post, j'ai la joie l'honneur le plaisir et l'avantage de vous annoncer que je peux sans problèmes détecter les différences entre ces fichiers à condition de virer ces cochonneries de RawImage.Description, RawImage.GetLineStart et autres Scanline, toutes choses donnant l'impression qu'on est proche du cœur des choses mais c'est faux !
    Pour atteindre les bonnes datas, pas d'autre solution que de passer par des procédures perso après avoir récupéré les bonnes données à coups de BlockRead dans les fichiers.

    Bientôt un zip pour démontrer tout ça, soyez un peu patients...
    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. #20
    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
    Citation Envoyé par Jipété Voir le message
    Salut salut,

    allez, pour vous mettre l'eau à la bouche, voici un petit intermède sympathique :

    • à gauche le fichier original avec canal alpha, plusieurs calques tous avec l'opacité à 100 % et une exportation A8R8G8B8 demandée à The Gimp. -- Basique.
    • au milieu j'ai rajouté un calque "nouveau depuis le visible" en haut de la pile et je lui ai descendu l'opacité à 80 %, puis j'ai décoché la visibilité de tous les calques dessous SAUF le fond tout en bas, qui est blanc, et export comme précédemment.
    • à droite je me suis ensuite contenté de juste décocher la visibilité du calque blanc du fond, résultat l'image s'est affichée avec le damier matérialisant la transparence, et export comme les deux autres. Vous allez me dire "mais elle n'est pas transparente ton image !" "Bah nan je réponds, voir dessous la seconde constatation..."

    Analyse :
    les 4 bytes qu'on lit proviennent de l'affichage d'un éditeur hexa et représentent ce que voit une pipette positionnée sur le coin complètement en haut à droite de l'image.
    • Première constatation, l'ordre des bytes n'est pas A8R8G8B8 tel que demandé dans la fenêtre des options avancées d'exportation, mais B8G8R8A8 (confirmé au colorpicker). Pourquoi ? Mystère... Mais la liste des 4 bytes de chaque pixel
      serait-elle parcourue à l'envers ?
    Elle ne sont pas parcourue, les données des pixels dans les fichiers au format BMP sont écrites en BIG-ENDIAN. Donc normal jusque là.

    Les Informations de l'encodage BitField, vu qu'il n'y pas d'encodage les pixels sont bien écrit au format par défaut ABGR comme décrit dans les spécifications
    Citation Envoyé par Jipété Voir le message
    • Seconde constatation sur l'image de droite : là le canal alpha a changé (CChex ça fait 20410 et 255 x 80 / 100 = 204, rappel : le calque a une opacité de 80 %) et les couleurs sont intactes ; ce n'est pas vraiment ce qu'on voit à l'écran, mais d'après ce que j'ai compris, mon environnement de bureau sous Linux ne gère pas la transparence.

    Voilà.
    Normal là aussi cela provient des spécifications du format bmp et de la gestion d'affichage en transparence de Windows

    https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx

    AlphaFormat
    This member controls the way the source and destination bitmaps are interpreted. AlphaFormat has the following value.
    Value Meaning
    AC_SRC_ALPHA : This flag is set when the bitmap has an Alpha channel (that is, per-pixel alpha). Note that the APIs use premultiplied alpha, which means that the red, green and blue channel values in the bitmap must be premultiplied with the alpha channel value. For example, if the alpha channel value is x, the red, green and blue channels must be multiplied by x and divided by 0xff prior to the call.

    https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx
    Donc je pense que Gimp applique ce principe en sens inverse lors de la sauvegarde.

    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
    function UnPremultiplyAlpha(const Pixel: TColorFPRec): TColorFPRec;
    begin
      Result.A := Pixel.A;
      if Pixel.A <> 0.0 then
      begin
        Result.R := Result.R / Pixel.A;
        Result.G := Result.G / Pixel.A;
        Result.B := Result.B / Pixel.A;
      end
      else
      begin
        Result.R := 0;
        Result.G := 0;
        Result.B := 0;
      end;
    end;
    Il faut te dire que RawImage ne reflète pas ton fichier BMP tel qu'il est. Le RawImage est une "passerelle" pour afficher et convertir les données (par rapport au format par défaut définit par les développeurs de FPC et en plus il peut être différent suivant les OS). Le problèmes et il est vrai c'est que parfois les informations fournies ne sont pas très limpides. Par exemple le bitCount, il faut le coupler avec HasAlpha, pour en déduire la valeur juste du PixelFormat. Mais ces 2 informations sont surtout utilisées dans la gestion de l'affichage. Exemple prend le fichier bmpsuite-2.5/g/rgb32.bmp. Regardes les valeurs du canal Alpha. Elles sont à 0. 0 = Transparent, donc normalement tu ne devrait pas la voir. non ?
    Pas évident à comprendre, tout ça. Toi t'as de la chance tu as encore plein de cheveux à t'arracher ! moi j'ai plus rien

    Bref je suis très curieux de voir ton test

    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

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 3 123 DernièreDernière

Discussions similaires

  1. comparer deux fichier .xls
    Par oursquetaire dans le forum Excel
    Réponses: 6
    Dernier message: 06/07/2006, 16h52
  2. [JDOM] Comparer deux fichiers XML en Java
    Par calimero2611 dans le forum Format d'échange (XML, JSON...)
    Réponses: 5
    Dernier message: 30/06/2006, 11h19
  3. Comparer deux fichier
    Par Taz_8626 dans le forum Langage
    Réponses: 3
    Dernier message: 20/06/2006, 11h46
  4. comparer deux fichiers avec une api windows
    Par sweetdreamer dans le forum Windows
    Réponses: 4
    Dernier message: 25/05/2006, 22h10
  5. Fonction c qui compare deux fichiers ???
    Par babyface dans le forum C
    Réponses: 4
    Dernier message: 19/11/2005, 13h07

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