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

Langage Delphi Discussion :

[Delphi 7][Graphisme] Problème de rendu défectueux d'une fonction de rééchantillonnage bicubique


Sujet :

Langage Delphi

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 878
    Points : 15 310
    Points
    15 310
    Par défaut [Delphi 7][Graphisme] Problème de rendu défectueux d'une fonction de rééchantillonnage bicubique
    Bonsoir,

    Ayant découvert le superbe projet (pas tout jeune mais certainement utile) reechantillonnage-bicubique-vs-stretchblt, je viens voir s'il y aurait par ici du... SAV,  !

    Car, oui, une des fonctions nous fait un petit caca nerveux en faisant sauter la ligne du bas et la dernière colonne à droite, je veux parler de StretchBmpAlpha3.

    D'habitude je code en Lazarus, et c'est là que j'ai découvert le souci.
    Pour en avoir le cœur net, j'ai lancé dans une machine virtuelle Win2000 mon vieux D7pe toujours vaillant, mais un poil plus chatouilleux, on va le voir + bas.

    Commençons avec une première image animée, où l'on constate que si StretchbmpAlpha3 réduit l'image, StretchBlt & Halftone éclaircit les couleurs (si si, prenez un color picker et vous le verrez) :
    Nom : delphi7compar3funct.gif
Affichages : 674
Taille : 38,5 Ko

    Mais ce n'est pas pour moi le plus important : le souci c'est vraiment la géométrie et on le voit mieux là avec un agrandissement à 400 % ; j'ai forcé le gris qui entoure l'image dans le prog, on le voit bien en bas et à droite et il laisse donc apparaître les ligne et colonne en blanc :

    Nom : delphi7ligne400pcent.png
Affichages : 557
Taille : 43,0 Ko

    Tout ça est confirmé par l'examen avec un éditeur hexa du fichier généré par l'outil, où l'on constate qu'après les 3 lignes et 1/2 du header le début des données (dernière ligne de l'image) est plein de blanc (FF 4 fois, il s'agit de 32 bits), ainsi que 4 colonnes à droite toute, en bas de l'éditeur (fin du fichier) où l'on voit le bout droit de la première ligne de l'image, contenant 16 FF (4 fois pour 1 pixel, et il y en a 4 puisque agrandissement à 400 %).
    Les DF DF DF 00 qui précédent correspondent au carré gris (223 223 223) en haut à droite.


    Ensuite je suis un peu allé voir le code, et pour comprendre j'ai rajouté un mémo et ça :

    D'abord juste avant la ligne end; // if yo2 :
    logtype1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
            with FrmDemoMain.Memo1.Lines do
              Add(its(yr)+'--'+its(yo1)+'--'+its(yo2)+'--'+its(xo1)+'--'+its(xr));
              // première ligne   0--  0--  1--  0--  0
              // dernière ligne 126--126--127--190--190
    on parcourt toute la hauteur sauf la dernière ligne de l'image (192x128), et on ne va pas au bout de la ligne.

    Avec Lazarus, si je modifie
    if (yo2 < HS) and (xo2 < WS) then en
    if (yo2 <= HS) and (xo2 <= WS) then alors je parcours toute l'image :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     // si option "<=" dernière ligne = 127--127--128--191--191 on parcourt tout
    mais il y a des effets de bords (couleurs bizarres dans les dernières ligne et colonne) et plus grave, violation d'accès sous Delphi

    logtype2
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
            with FrmDemoMain.Memo1.Lines do
              if ((yr = 0) or (yr = hr-1)) and ((xr = 0) or (xr = wr-1)) then begin
                Add(its(yr)+'--'+its(xr));
                Add(its(PRGBQuad(scanR)^.rgbBlue));
                Add(its(PRGBQuad(scanR)^.rgbGreen));
                Add(its(PRGBQuad(scanR)^.rgbRed));
                Add(its(PRGBQuad(scanR)^.rgbReserved));
                Add('');
              end;
              // juste 0--0 / 128 128 0 0
    et c'est normal puisqu'on ne va pas au bout de la hauteur ni de la largeur.

    si la mécanique logtype2 est déplacée après la ligne end; // if yo2, voilà les résultats :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    000--000 / 128-128-000-0 vert-bleu ok
    000--191 / 223-223-223-0 gris ok
    127--000 / 022-085-220-0 orange FAUX !
    127--191 / 022-085-220-0 orange ok
    Sous Lazarus, avec la manip étendant le parcours, le 3e pixel retrouve ses bonnes couleurs.

    Je peux étendre le parcours autrement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    //if (yo2 <  HS)   and (xo2 <  WS)   then // original, trop petit
      if (yo2 <  HS+1) and (xo2 <  WS+1) then // taille ok mais défauts bas + droite
    sous Lazarus, mais Delphi nous fait encore un caprice de violation d'accès.

    Ah, its c'est juste ça (mais ça va tellement plus vite à taper, et le code est plus lisible, que du bonheur) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    function its(i:integer):string; begin result:=IntToStr(i); end;

    C'est tout ce que je peux en dire pour le moment, ces parcours de pixels me dépassent un peu, je l'avoue.

    Alors si quelqu'un a une idée, si les auteurs se reconnaissent et passent par là (il m'est arrivé d'en lire deux, des fois, ici), leurs conseils seront les bienvenus.
    Merci,

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 878
    Points : 15 310
    Points
    15 310
    Par défaut
    Une question dont la réponse pourrait éclairer ce brouillard :

    dans le code du parcours de la destination (pour sa "construction"), je lis ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
          // Arrivé ici xo1,yo1 et xo2,yo2 sont les coord's des 4 pixels du bmp-source
          // formant un carré de 2x2 (dont les centres forment un carré de 1x1 pixel)
          // et à partir desquels on fera un dégradé de couleurs en fonction de dxo,dyo
          // dans le carré de taille k*k correspondant du bmp-result.
    Une chose me turlupine : à la première ligne je vois 4 coordonnées et on me parle de 4 pixels.
    Mais pour moi, un pixel doit avoir 2 coordonnées, donc il en faudrait 8 ?
    Ou je n'ai rien compris ?

    Quelqu'un pour m'expliquer ?

  3. #3
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 374
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 374
    Points : 3 152
    Points
    3 152
    Par défaut
    Bonjour,
    C'est peut être le coin haut gauche et le coin bas droite des 4 pixels ?

    Mais c'est un peu bête, car si on veut désigner un carré de 4 pixels, il ne faut que 2 coordonnées : celles du pixel du coin haut gauche !

    A+
    Charly

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 878
    Points : 15 310
    Points
    15 310
    Par défaut
    Merci d'avoir amorcé la pompe à réponses,

    Ce qui me gêne en informatique, c'est ça :
    Citation Envoyé par Charly910 Voir le message
    C'est peut-être le coin [...]


    Citation Envoyé par Charly910 Voir le message
    il ne faut que 2 coordonnées : celles du pixel du coin haut gauche !
    C'est pas faux !
    Pour les 3 autres, il suffit de faire +0, +1 puis +1, +0 et enfin +1, +1.
    Donc le mystère reste entier.

    Bon, on est week-end pendant les vacances scolaires : peut-être pas la meilleure période pour crouler sous les réponses,
    Waiting...

  5. #5
    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
    Hello

    // Arrivé ici xo1,yo1 et xo2,yo2 sont les coord's des 4 pixels du bmp-source
    // formant un carré de 2x2
    Je comprend le truc comme cela :

    Pixel-1 = (xo1,yo1) représente le pixel en haut a gauche,
    Pixel-2 = (xo2,yo2) représente le pixel en bas à droite

    Par déduction

    Pixel-3 = (xo2,yo1)
    Pixel-4 = (xo1,yo2)

    On a bien 4 pixels définis par 4 coordonnées (X,Y) ! pas évident de commenter des fois (j'en sais quelque chose, dur de choisir les bon mots et être précis par moment pour expliquer une chose à d'autres personnes )

    Je me suis décidé à télécharger les sources originelles

    dans StretchBmpAlpha3 (je n'ai pas testé)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    //  WR := trunc(k * BmpS.width); HR := trunc(k * bmpS.Height);
      WR := Round(k * BmpS.width);
      HR := Round(k * bmpS.Height);
    Je pense que le problème viens du Round (on en avait parlé pour je ne sais plus trop quel problème) L'erreur viens de là je pense.

    C'est du a l'algorithme utilisé par FPC pour round.

    In the case of .5, the algorithm uses "banker's rounding": .5 values are always rounded towards the even number.
    -------
    Dans le cas de 0,5, l'algorithme utilise 'l'arrondi de banque': les valeurs 0,5 sont toujours arrondies vers le nombre pair.
    en gros :

    Round(3.5) = 4
    Round(2.5) = 2 ===> Ouch !!!!!!

    Avec Trunc vu que c'est en commentaire, trunc pose des problèmes et c'est compréhensible

    Essayes

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
      WR := Round(k * BmpS.width + 0.5);
      HR := Round(k * bmpS.Height + 0.5);
    Sinon essayes d'utiliser Floor de l'unité math à la place de Round

    A+

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 878
    Points : 15 310
    Points
    15 310
    Par défaut
    Citation Envoyé par BeanzMaster Voir le message
    Je comprend le truc comme cela :

    Pixel-1 = (xo1,yo1) représente le pixel en haut a gauche,
    Pixel-2 = (xo2,yo2) représente le pixel en bas à droite

    Par déduction

    Pixel-3 = (xo2,yo1)
    Pixel-4 = (xo1,yo2)

    On a bien 4 pixels définis par 4 coordonnées (X,Y) ! pas évident de commenter des fois (j'en sais quelque chose, dur de choisir les bon mots et être précis par moment pour expliquer une chose à d'autres personnes )
    Oui, ça doit être ça.

    Citation Envoyé par BeanzMaster Voir le message
    C'est dû à l'algorithme utilisé par FPC pour round.

    Sinon essaye d'utiliser Floor de l'unité math à la place de Round
    Bien tenté, mais si j'ai posté ici dans Delphi/Windows, c'est bien parce que le problème est présent dans les deux environnements,

    Par ailleurs, ça ne peut pas être où tu l'indiques :
    Citation Envoyé par BeanzMaster Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    //  WR := trunc(k * BmpS.width); HR := trunc(k * bmpS.Height);
      WR := Round(k * BmpS.width);
      HR := Round(k * bmpS.Height);
    car si c'était là-dedans, ça impacterait les dimensions de l'image finale, ce qui n'est pas le cas !
    Regarde bien ma copie d'écran avec la vue de l'éditeur hexa : si tu décortiques les dimensions hexa, elles sont justes (pour ce test je fais une copie 1/1), et le paquet de FF, c'est la ligne blanche tout en bas de l'image.
    Mais sans zoomer ça ne se voit quasiment pas : faut passer par le gif pour mieux voir le défaut.

    Àmha, c'est là-dedans que ça se passe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
          if (yo2 <  HS)   and (xo2 <  WS)   then // original, trop petit : à 400%, 4 lignes et 4 colonnes de moins que b.précalculé
    //    if (yo2 <= HS)   and (xo2 <= WS)   then // bande colorée
    //    if (yo2 <  HS+1) and (xo2 <  WS+1) then // taille ok mais défaut bas + droite
    //    if (yo2 <  HS-1) and (xo2 <  WS-1) then // trop petit
    //    if (yo2 <= HS-1) and (xo2 <= WS-1) then // trop petit
          begin
            // Identification des 4 couleurs de base :
            ...
            // Le dégradé de couleurs :
            ...
          end;
    EDIT :
    Je réalise, à force de lire et relire, qu'en fait, quand j'écris "trop petit" c'est faux : c'est juste visuel, c'est ce que j'ai dit ci-dessus, c'est que la ligne blanche ne se voit pas mais elle existe dans le fichier, dont les dimensions sont bonnes.

    Faut juste trouver pourquoi le calcul du rendu génère du blanc quand yr = 0 (première ligne) et quand xr = wr-1 (dernière colonne).

  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
    Citation Envoyé par Jipété Voir le message
    Oui, ça doit être ça.



    Bien tenté, mais si j'ai posté ici dans Delphi/Windows, c'est bien parce que le problème est présent dans les deux environnements,
    J'avais même pas fais gaffe que l'on était dans le formum Delphi (l'habitude).

    Citation Envoyé par Jipété Voir le message
    Par ailleurs, ça ne peut pas être où tu l'indiques :

    car si c'était là-dedans, ça impacterait les dimensions de l'image finale, ce qui n'est pas le cas !
    Regarde bien ma copie d'écran avec la vue de l'éditeur hexa : si tu décortiques les dimensions hexa, elles sont justes (pour ce test je fais une copie 1/1), et le paquet de FF, c'est la ligne blanche tout en bas de l'image.
    Mais sans zoomer ça ne se voit quasiment pas : faut passer par le gif pour mieux voir le défaut.
    Avec Lazarus faudra quand même se méfier à cause du round que cela ne décale pas de 1 pixel. Je vais tester avec TFastImage, c'est vite fait à convertir



    Citation Envoyé par Jipété Voir le message
    Àmha, c'est là-dedans que ça se passe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
          if (yo2 <  HS)   and (xo2 <  WS)   then // original, trop petit : à 400%, 4 lignes et 4 colonnes de moins que b.précalculé
    //    if (yo2 <= HS)   and (xo2 <= WS)   then // bande colorée
    //    if (yo2 <  HS+1) and (xo2 <  WS+1) then // taille ok mais défaut bas + droite
    //    if (yo2 <  HS-1) and (xo2 <  WS-1) then // trop petit
    //    if (yo2 <= HS-1) and (xo2 <= WS-1) then // trop petit
          begin
            // Identification des 4 couleurs de base :
            ...
            // Le dégradé de couleurs :
            ...
          end;
    EDIT :
    Je réalise, à force de lire et relire, qu'en fait, quand j'écris "trop petit" c'est faux : c'est juste visuel, c'est ce que j'ai dit ci-dessus, c'est que la ligne blanche ne se voit pas mais elle existe dans le fichier, dont les dimensions sont bonnes.

    Faut juste trouver pourquoi le calcul du rendu génère du blanc quand yr = 0 (première ligne) et quand xr = wr-1 (dernière colonne).
    Les dimensions du bitmap de destination sont bonne. Le blanc peux s'expliquer par la couleur de fond lorsque tu initalises le bitmap de destination.

    Le truc que je vois, c'est dans la boucle

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
      for yr := 0 to HR - 1 do
      begin
        yrSurk := yr / k;
        yo1 := trunc(yrSurk);
        yo2 := trunc((yr + k) / k);
        dyo := frac(yrSurk);
        for xr := 0 to WR - 1 do
        begin
          xrSurk := xr / k;
          xo1 := trunc(xrSurk);
          xo2 := trunc((xr + k) / k);
          dxo := frac(xrSurk);
    Pourquoi utiliser Trunc qu'alors que pour les dimensions il utilise Round ????
    ensuite yo2 := trunc((yr + k) / k); et xo2 := trunc((xr + k) / k); par rapport à sont commentaire pourquoi ne pas avoir fait simplement if yr<(HR-1) then yo2 := yo1 +1 else yo2:=yo2 et idem pour xo2 ????

    Je pense que l'erreur se situe plus à ce niveau, que dans le "if". Tu as essayé de logger les valeurs xo1, yo1... ?

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 878
    Points : 15 310
    Points
    15 310
    Par défaut
    Citation Envoyé par BeanzMaster Voir le message
    Je pense que l'erreur se situe plus à ce niveau, que dans le "if". Tu as essayé de logger les valeurs xo1, yo1... ?
    Je ne fais que ça et j'avance, petit à petit...

    Le drame c'est que ce que je logge est bon ! ! !

    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
        ...
        end; // for  xr
        if Assigned(ProgressCallBack) then ProgressCallBack;
        with FrmDemoMain.Memo2.Lines do
        if ((yr = 0) or (xr = wr_moins_un)) then
          with PRGBQuad(scanTR)^ do
            Add(i3s(yr)+'--'+i3s(xr)+' / '+i3s(rgbBlue)+'-'+i3s(rgbGreen)+'-'+i3s(rgbRed)+'-'+i3s(rgbReserved));
    // 000--191 / 223-223-223-255 - gris
    // 063--191 / 223-223-223-255
    // 064--191 / 220-085-022-255 - orange
    // 127--191 / 220-085-022-255
      end; // for  yr
      ScanOR := ScanTR; // oublié par l'auteur ?
      ilDst.FastBitmap.GetBitmap.SaveToFile('/chemin/ilDst.bmp'); //--> BAD !
      result.Assign(ilDst.FastBitmap.GetBitmap);// renvoyer vers le TImage
    end; // StretchBmpAlpha3
    i3s c'est its modifié pour formater sur 3 digits les datas --> plus lisible ! function i3s(i:integer):string; begin result:=Format('%.3u', [i]); end;
    On voit là les valeurs de la dernière colonne (je n'ai pas tout mis), les deux carrés présentent les bonnes valeurs.
    Mais ça ne se retrouve pas dans le fichier ! ! !
    J'en mangerais mon chapeau si j'en avais un.

    Début de la proc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      ilDst.FastBitmap.SetSize(WR,HR);
      Result := ilDst.FastBitmap.GetBitmap;
      ScanOR := uint(ilDst.FastBitmap.GetScanLine(0));
      MLS_RR := uint(ilDst.FastBitmap.GetScanLine(1)) - ScanOR;
    Et c'est pareil en Delphi sauf qu'il n'y a pas les 3 lignes entre les deux end; du bas.

  9. #9
    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
    Il y a quand même un truc qui me gène avec

    xo2 := trunc((xr + k) / k); j'ai fais quelques calculs à la main histoire de


    Supposons que le bitmap source ai une largeur "WS = 96" que le ratio k = 1.333.
    On a donc pour le bitmap de destination une largeur "WR" = 128

    Prenons le dernier pixel d'une ligne dans la boucle, soit xr =127
    On a alors xo2 = (127 + 1.333) / 1.333 = 96.27 ( Trunc(96.27) = 96. Le maximum pour le bitmap source via l'accès avec les pointers est "WS = 96 -1" = 95.

    Du coup je pense que ce décalage et la ligne blanche vient de la. Ce dernier pixel ne sera jamais pris en compte du fait du "if (xo2 < WS)" alors qu'il devrait

    Je pense qu"un petit [c]if (xo2>=WS) then xo2 := ws -1;[c] devrait régler le problème

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 878
    Points : 15 310
    Points
    15 310
    Par défaut
    Citation Envoyé par BeanzMaster Voir le message
    Supposons que le bitmap source ai une largeur "WS = 96" que le ratio k = 1.333.
    Sauf que, pour ces tests je ne cherche pas à agrandir ni à réduire, je voudrais d'abord avoir un rendu à l'identique, donc k = 1.

    Et c'est le cas en terme de tailles : le fichier destination a les mêmes largeur et hauteur que le fichier source.

    Par ailleurs, j'ai bien écrit que pendant les logs les données sont bonnes !

    Tiens, regarde, un truc de ce matin, tôt (avant "i3s", mise en forme à la mano ) :
    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
            PRGBQuad(scanTR)^ := rgbQuadDegra4;
          end; // if yo2
     
          with FrmDemoMain.Memo2.Lines do
          if ((yr = 0) or (xr = wr_moins_un)) then begin
            Add(its(yr)+'--'+its(xr));
            Add(its(PRGBQuad(scanTR)^.rgbBlue));
            Add(its(PRGBQuad(scanTR)^.rgbGreen));
            Add(its(PRGBQuad(scanTR)^.rgbRed));
            Add(its(PRGBQuad(scanTR)^.rgbReserved));
            Add('');
          end;   
    {                   R   G   B   A
            première ligne, 1er carré
            début
            000--000 / 000-128-128-255
            fin
            000--063 / 000-128-128-255
     
            première ligne, 2e carré
            début
            000--064 / 000-255-000-255
            fin
            000--127 / 000-255-000-255
     
            première ligne, 3e carré
            début
            000--128 / 223-223-223-255
            fin
            000--191 / 223-223-223-255
     
            dernière colonne, 1er carré
            début
            001--191 / 223-223-223-255
            fin
            063--191 / 223-223-223-255
     
            dernière colonne, 2nd carré
            début
            064--191 / 220-085-022-255
            fin
            127--191 / 220-085-022-255              }
        end; // for  xr
        if Assigned(ProgressCallBack) then ProgressCallBack;
      end; // for  yr
      result.Assign(ilDst.FastBitmap.GetBitmap);// renvoyer vers le TImage d'affichage
    end; // StretchBmpAlpha3
    Citation Envoyé par BeanzMaster Voir le message
    Ce dernier pixel ne sera jamais pris en compte du fait du "if (xo2 < WS)" alors qu'il devrait
    Je crois que je l'ai dit au tout début !
    Mais si je modifie la borne, alors AV ou couleurs en vrac, etc.

    Ceci dit, je suis d'accord avec toi : ça tourne autour de ça.
    Notre problème, c'est que nous ne sommes pas dans la tête de celui (ceux) qui a (ont) écrit ça, et qu'il nous faut donc tout démonter pour comprendre les mécanismes...

    Dans les autres fonctions du prog, il y a une autre manière de gérer les bornes concernant le groupe des 4 carrés qui, fatalement, débordent "dans le vide" en haut à gauche et en bas à droite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
          for m := -1 to 2 do
            for n := -1 to 2 do
            begin
              ii := xs + m;
              jj := ys + n;
              if ii  < 0  then ii := 0;
              if ii >= WS then ii := WS_moins_un;
              if jj  < 0  then jj := 0;
              if jj >= HS then jj := HS_moins_un;
    Faudrait s'en inspirer.

  11. #11
    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
    Sauf que, pour ces tests je ne cherche pas à agrandir ni à réduire, je voudrais d'abord avoir un rendu à l'identique, donc k = 1.
    Ok

    Citation Envoyé par Jipété Voir le message
    Ceci dit, je suis d'accord avec toi : ça tourne autour de ça.
    Notre problème, c'est que nous ne sommes pas dans la tête de celui (ceux) qui a (ont) écrit ça, et qu'il nous faut donc tout démonter pour comprendre les mécanismes...

    Je crois que je l'ai dit au tout début !
    Mais si je modifie la borne, alors AV ou couleurs en vrac, etc.
    L'AV et le débordement est la dedans

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    ScanS := Scan0S;
            Inc(ScanS, yo1 * MLSS + xo1 * Bpp);  // Si yo1 = derniere ligne et xo1 dernier pixel
            c0 := PRGBQuad(scanS)^;
            inc(ScanS, Bpp);                                //  On passe au pixel suivant, mais on a déjà atteint la fin 
            c3 := PRGBQuad(scanS)^;                 //  Puis AV ici
            ScanS := Scan0S;
            Inc(ScanS, yo2 * MLSS + xo1 * Bpp);  // idem
            c1 := PRGBQuad(scanS)^;
            inc(ScanS, Bpp);
            c2 := PRGBQuad(scanS)^;
    Essayes de borner ici :

    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
    ScanS := Scan0S;
            Inc(ScanS, yo1 * MLSS + xo1 * Bpp);  
            c0 := PRGBQuad(scanS)^;
            if xo1 < (WS-1) then 
            begin
              inc(ScanS, Bpp);       
              c3 := PRGBQuad(scanS)^;          
            end
            else C3 := C0;
            ScanS := Scan0S;
            Inc(ScanS, yo2 * MLSS + xo1 * Bpp); 
            c1 := PRGBQuad(scanS)^;
            if xo1 < (WS-1) then 
            begin
              inc(ScanS, Bpp);       
              c1 := PRGBQuad(scanS)^;          
            end
            else C2 := C1;
    Citation Envoyé par Jipété Voir le message
    Dans les autres fonctions du prog, il y a une autre manière de gérer les bornes concernant le groupe des 4 carrés qui, fatalement, débordent "dans le vide" en haut à gauche et en bas à droite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
          for m := -1 to 2 do
            for n := -1 to 2 do
            begin
              ii := xs + m;
              jj := ys + n;
              if ii  < 0  then ii := 0;
              if ii >= WS then ii := WS_moins_un;
              if jj  < 0  then jj := 0;
              if jj >= HS then jj := HS_moins_un;
    Faudrait s'en inspirer.
    Regardes la fonction Bicubic precal que je t'ai passé pour ça car -1 to 2 = un carré de 4x4 (-1,0,1,2);

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 878
    Points : 15 310
    Points
    15 310
    Par défaut
    Citation Envoyé par BeanzMaster Voir le message
    Essaye de borner ici :
    EDIT :
    Strictement le même résultat...
    T'avais juste oublié de me dire de virer cette fucking ligne if (yo2 < HS) and (xo2 < WS) then qui mettait ses bornes à la noix !

    C'est bon !
    Plus de décalage et fichier correctement rempli,

    Plus qu'à tester en agrandissement et en réduc, et en Delphi7.
    'tain, un grand, un énorme merci à toi !

    Bon dimanche,


    EDIT 2 : en informatique, ne jamais crier victoire trop vite... Agrandissement à 120 % (et réduc c'est pareil) :
    Nom : agrand.png
Affichages : 410
Taille : 2,7 Ko
    Pas de défaut à 40 % ni à 200 %, si ça t'inspire.

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 878
    Points : 15 310
    Points
    15 310
    Par défaut
    Bon voilà,

    après avoir tout tourné dans tous les sens, à un moment ça a fini par tomber en marche,

    Fallait juste pas chercher midi à quatorze heures :
    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
            // Identification des 4 couleurs de base :
            if xo2 < WS then
            begin
              ScanTS := ScanOS;
              Inc(ScanTS, yo1 * MLS_OS + xo1 * Bpp);
              c0 := PRGBQuad(scanTS)^;
     
              inc(ScanTS, Bpp);
              c3 := PRGBQuad(scanTS)^;
     
              ScanTS := ScanOS;
              Inc(ScanTS, yo1 * MLS_OS + xo1 * Bpp);
              c1 := PRGBQuad(scanTS)^;
     
              inc(ScanTS, Bpp);
              c2 := PRGBQuad(scanTS)^;
            end;
     
            // Le dégradé de couleurs :
    C'est tout.
    J'agrandis, je réduis, sans soucis.
    Attention, j'ai modifié dès le début le nom de certaines variables, et bonjour la confusion entre le chiffre 0 et la majuscule O.

    Un petit problème (et là, franchement, vu le principe employé, je ne vois pas comment le traiter), c'est si on réduit en dessous de 20 %, genre là à 5 %, laisse tomber ! Bon, c'est pas trop grave, quel intérêt de réduire un bitmap à ces tailles ridicules-là, mmmh ? Il ne fait que 10x6, heureusement que j'ai une bonne loupe :

    Nom : 5pourcent.png
Affichages : 421
Taille : 5,5 Ko

    Et un autre, un poil plus gênant, c'est la disparition du bord noir dans ce cas précis (original à gauche, copie à 200 %) :

    Nom : bord_noir.png
Affichages : 689
Taille : 20,5 Ko


    Sinon, la vraie cata c'est en Delphi :

    Nom : lenfer_sous_d7.png
Affichages : 407
Taille : 4,8 Ko

    Pourquoi le précalculé balance des points à 120 % et pas les autres manières de faire ? J'avoue que je n'ai pas le courage de creuser...

    Allez, c'est tout pour aujourd'hui.
    J'attends un jour ou deux avant de cocher

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 878
    Points : 15 310
    Points
    15 310
    Par défaut
    Citation Envoyé par Jipété Voir le message
    Et un autre, un poil plus gênant, c'est la disparition du bord noir dans ce cas précis (original à gauche, copie à 200 %) :

    Nom : bord_noir.png
Affichages : 689
Taille : 20,5 Ko
    Honteusement pompé sur les autres méthodes du programme, le coup du "-0.5" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
      for yr := 0 to hr_moins_un do begin  // parcours vertical de la destination
        yr_sur_k := yr / k;
        yo1 := trunc(yr_sur_k);
        //yo2 := trunc((yr + k) / k);
        yo2 := trunc((-0.5 + yr + k) / k);
        dyo := frac(yr_sur_k);
     
        for xr := 0 to wr_moins_un do begin  // parcours horizontal de la destination
          xr_sur_k := xr / k;
          xo1 := trunc(xr_sur_k);
          //xo2 := trunc((xr + k) / k); dessous, améliore le rendu du bord noir de l'avion
          xo2 := trunc((-0.5 + xr + k) / k);
          dxo := frac(xr_sur_k);
    Nom : bordnoirok.png
Affichages : 394
Taille : 17,7 Ko

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 878
    Points : 15 310
    Points
    15 310
    Par défaut
    Deux choses qui restent dans le thème, mais un peu moins sur le sujet.

    J'ai regardé ce que tu m'avais donné, cette
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Procedure TFastBitmap.StretchBicubic(Var NW, NH: Integer; Const KeepRatio: Boolean = False);
    { https://en.wikipedia.org/wiki/Bicubic_interpolation du chinois pour moi toutes ces formules :) 
      fonction adaptée du code source de  ??
      d'après le code source en C de Paul Toth (trouvé je ne sais plus où)}
    Const
      BiCubicRPrecal: Array[1..16] Of Single = (0.00260416666666667, 0.0208333333333333, 0.0703125, 0.166666666666667,
        0.315104166666667, 0.479166666666667, 0.611979166666667, 0.666666666666667,
        0.611979166666667, 0.479166666666667, 0.315104166666667, 0.166666666666667,
        0.0703125, 0.0208333333333333, 0.00260416666666667, 0.0);
    Var
      SrcH, SrcW: Integer;
      TmpBmp: TFastBitmap;
      ...
    Ton commentaire en haut me fait rire, je suis dans le même cas. Mais j'ai trouvé plus sympathique, en pseudo-code et en français s'il vous plait (sauf que quand je le teste [ça ressemble énormément au resample v1.03 qui traîne sur le web et chez moi et surement chez toi, on en a parlé il y a longtemps], certaines procédures plantent. Bah... Faudrait recreuser, c'est juste le temps qui manque)
    Bref : https://clouard.users.greyc.fr/Panth.../index-fr.html
    Attention, il me semble que deux graphiques sont faux, au milieu de ses explication.
    Et tout en bas tu trouves les formules de convolution classiques.


    Ensuite, ton bout de code, je n'arrive pas à le mettre en œuvre ou plutôt, je le mets en place j'exécute, il ne se passe rien, je mets un point d'arrêt au début de ma proc appelante et un autre au début de ta proc appelée et crois-le si tu veux, mais à l'exécution je ne m'arrête ni sur l'un ni sur l'autre.
    Là je reste sans voix, d'autant plus que si je rajoute des ShowMessage je les vois.

    J'ai transformé ta proc en fonction renvoyant un TBitmap, et je l'appelle comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    begin
      ShowMessage('ici');
      ilSrc.FastBitmap.ImportFromRawImage(bm_in.RawImage); // ilSrc utilisé depuis une semaine dans bicubic, créé dans Initialization 
      w:= ilSrc.FastBitmap.Width; 
      h := ilSrc.FastBitmap.Height;
      bm_out.Assign(StretchBicubic(w,h,true)); // pour renvoyer vers affichage
    end;
    Une idée, maître ?

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 878
    Points : 15 310
    Points
    15 310
    Par défaut
    Citation Envoyé par Jipété Voir le message
    Ensuite, ton bout de code, je le mets en place j'exécute, il ne se passe rien, je mets un point d'arrêt au début de ma proc appelante et un autre au début de ta proc appelée et crois-le si tu veux, mais à l'exécution je ne m'arrête ni sur l'un ni sur l'autre.
    Là je reste sans voix, d'autant plus que si je rajoute des ShowMessage je les vois.
    C'est un truc que j'oublie tout le temps, un défaut de Lazarus (vais me faire houspiller par les puristes, ) : quand ça se produit, il y a une variable à basculer dans les options de Lazarus.

    Jamais réussi à fixer ce truc...

    Bon, c'est tout, pour moi c'est , le reste concernera plutôt le sous-forum Algorithme, mais j'ai des .gif à préparer, avant.

  17. #17
    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,

    Citation Envoyé par Jipété Voir le message

    J'ai transformé ta proc en fonction renvoyant un TBitmap, et je l'appelle comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    begin
      ShowMessage('ici');
      ilSrc.FastBitmap.ImportFromRawImage(bm_in.RawImage); // ilSrc utilisé depuis une semaine dans bicubic, créé dans Initialization 
      w:= ilSrc.FastBitmap.Width; 
      h := ilSrc.FastBitmap.Height;
      bm_out.Assign(StretchBicubic(w,h,true)); // pour renvoyer vers affichage
    end;
    Une idée, maître ?
    Oui, une idée bm_out.Assign(ilSrc.StretchBicubic(w,h,true));

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 25/06/2007, 11h38
  2. problème avec l'utilisation d'une fonction
    Par mcspawn dans le forum Langage
    Réponses: 6
    Dernier message: 06/06/2007, 15h39
  3. Problème de passage de variable à une fonction
    Par PunkMetal dans le forum Langage
    Réponses: 2
    Dernier message: 26/04/2007, 23h56
  4. Problème pour la création d'une fonction
    Par jipé95 dans le forum C
    Réponses: 5
    Dernier message: 10/12/2006, 14h28
  5. problème avec l'appel d'une fonction
    Par mademoizel dans le forum ASP
    Réponses: 5
    Dernier message: 26/06/2006, 15h04

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